@lax-wp/design-system 0.13.43 → 0.13.44

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,2 +1,2 @@
1
- "use strict";Object.defineProperties(exports,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}});const n=require("react/jsx-runtime"),C=require("antd"),p=require("react"),t=require("../../lib/utils.cjs.js"),f=require("../icon/icons.generated.cjs.js");function j(e){return!!e&&!("type"in e)}const O=({items:e,onItemClick:s,minWidth:l=200,onItemSelected:a})=>n.jsx("div",{className:"bg-white dark:bg-black-800 border border-neutral-200 dark:border-black-600 rounded-[8px] shadow flex flex-col gap-1 p-0",style:{minWidth:l},children:e?.map((r,o)=>r?"type"in r&&r.type==="divider"?n.jsx("div",{className:"h-px bg-neutral-200 dark:bg-black-600 mx-1 my-0.5"},r.key??`divider-${o}`):"type"in r&&r.type==="group"?n.jsxs("div",{children:[r.label&&n.jsx("div",{className:"px-3 py-1 text-xs font-semibold text-neutral-500 dark:text-neutral-400 uppercase tracking-wide",children:r.label}),r.children?.map((c,x)=>j(c)?n.jsx(k,{item:c,onItemClick:s,onItemSelected:a},c.key??x):null)]},r.key??`group-${o}`):j(r)?n.jsx(k,{item:r,onItemClick:s,onItemSelected:a},r.key??o):null:null)}),k=({item:e,onItemClick:s,isChild:l=!1,onItemSelected:a})=>{const[r,o]=p.useState(e.defaultOpen??!1),[c,x]=p.useState(!1),h=Array.isArray(e.children)&&e.children.length>0,d=h&&e.expandable===!0,i=h&&!e.expandable,v=e.icon!==void 0,w=u=>{if(e.disabled)return;if(d){o(g=>!g);return}const b=String(e.key??"");i||(e.onClick?.({key:b,domEvent:u}),s?.({key:b,keyPath:[b],domEvent:u}),a?.())},E=p.useCallback(()=>{x(!1),a?.()},[a]),M=t.cn("flex items-center justify-between rounded-[4px] cursor-pointer select-none w-full transition-colors duration-100",l?"pl-9 pr-1 min-h-[36px]":"px-0 py-0.5",!v&&"overflow-hidden",e.disabled?"opacity-50 cursor-not-allowed":"",e.className),R=t.cn("flex items-center justify-between gap-3 rounded-[4px] cursor-pointer select-none w-full transition-colors duration-100 dark:bg-black-800",l?"pl-9 pr-1 py-2 min-h-[36px]":"px-3 py-2",e.disabled?"opacity-50 cursor-not-allowed":"",e.className),N=d?n.jsx(f.ExpandMoreFilledIcon,{size:16,className:t.cn("flex-none transition-transform duration-200",r?"rotate-180":"rotate-0")}):i?n.jsx(f.KeyboardArrowRightIcon,{size:16,className:"flex-none"}):null,y=p.isValidElement(e.label)&&e.label.type?.displayName==="OptionButton",S=y&&N?p.cloneElement(e.label,{chevron:N}):e.label,m=v?n.jsxs("div",{className:R,onClick:e.disabled?void 0:w,children:[n.jsxs("div",{className:"flex items-center gap-3 min-w-0 flex-1",children:[n.jsx("span",{className:t.cn("flex-none flex items-center justify-center",l?"size-4":"size-5"),children:e.icon}),n.jsx("span",{className:t.cn("text-sm font-medium leading-5 whitespace-nowrap",e.danger?"text-error-600":"text-neutral-900 dark:text-neutral-100"),children:e.label})]}),d&&n.jsx(f.ExpandMoreFilledIcon,{size:20,className:t.cn("flex-none text-neutral-500 dark:text-neutral-400 transition-transform duration-200",r?"rotate-180":"rotate-0")}),i&&n.jsx(f.KeyboardArrowRightIcon,{size:20,className:"flex-none text-neutral-500 dark:text-neutral-400"})]}):n.jsxs("div",{className:M,onClick:e.disabled?void 0:w,children:[n.jsx("div",{className:t.cn("min-w-0 flex-1"),children:S}),!y&&d&&n.jsx(f.ExpandMoreFilledIcon,{size:16,className:t.cn("flex-none mr-2 text-neutral-500 dark:text-neutral-400 transition-transform duration-200",r?"rotate-180":"rotate-0")}),!y&&i&&n.jsx(f.KeyboardArrowRightIcon,{size:16,className:"flex-none mr-2 text-neutral-500 dark:text-neutral-400"})]});return i?n.jsx(C.Popover,{open:c,onOpenChange:x,content:n.jsx(O,{items:e.children,onItemClick:s,onItemSelected:E}),trigger:"hover",placement:"rightTop",overlayInnerStyle:{padding:0},overlayStyle:{padding:0},arrow:!1,children:n.jsx("div",{children:m})}):n.jsxs("div",{children:[m,d&&n.jsx("div",{className:t.cn("grid transition-[grid-template-rows] duration-200 ease-in-out",r?"grid-rows-[1fr]":"grid-rows-[0fr]"),children:n.jsx("div",{className:"overflow-hidden",children:n.jsx("div",{className:"flex flex-col",children:e.children?.map((u,b)=>{if(!u||!j(u))return null;const g=b===(e.children?.length??0)-1;return n.jsxs("div",{className:"relative",children:[n.jsx("div",{className:"absolute left-[19px] top-0 w-3.5 border-l border-b border-neutral-200 dark:border-black-600 rounded-bl-[6px] pointer-events-none",style:{height:"calc(50% + 4px)"}}),!g&&n.jsx("div",{className:"absolute left-[19px] top-1/2 bottom-0 w-px bg-neutral-200 dark:bg-black-600 pointer-events-none"}),n.jsx(k,{item:u,onItemClick:s,isChild:!0,onItemSelected:a})]},u.key??b)})})})})]})},z=({children:e,menu:s,minWidth:l=200,onOpenChange:a,...r})=>{const[o,c]=p.useState(0),x=(d,i)=>{d||c(v=>v+1),a?.(d,i)},h=p.useCallback(()=>n.jsx(O,{items:s?.items,onItemClick:s?.onClick,minWidth:l},o),[s?.items,s?.onClick,l,o]);return n.jsx(C.Dropdown,{...r,onOpenChange:x,popupRender:h,children:e})};exports.Dropdown=z;exports.default=z;
1
+ "use strict";Object.defineProperties(exports,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}});const n=require("react/jsx-runtime"),C=require("antd"),p=require("react"),t=require("../../lib/utils.cjs.js"),f=require("../icon/icons.generated.cjs.js");function j(e){return!!e&&!("type"in e)}const O=({items:e,onItemClick:s,minWidth:l=200,onItemSelected:a})=>n.jsx("div",{className:"bg-white dark:bg-black-800 border border-neutral-200 dark:border-black-600 rounded-[8px] shadow flex flex-col p-0 border-none overflow-hidden",style:{minWidth:l},children:e?.map((r,o)=>r?"type"in r&&r.type==="divider"?n.jsx("div",{className:"h-px bg-neutral-200 dark:bg-black-600 mx-1 my-0.5"},r.key??`divider-${o}`):"type"in r&&r.type==="group"?n.jsxs("div",{children:[r.label&&n.jsx("div",{className:"px-3 py-1 text-xs font-semibold text-neutral-500 dark:text-neutral-400 uppercase tracking-wide",children:r.label}),r.children?.map((c,x)=>j(c)?n.jsx(k,{item:c,onItemClick:s,onItemSelected:a},c.key??x):null)]},r.key??`group-${o}`):j(r)?n.jsx(k,{item:r,onItemClick:s,onItemSelected:a},r.key??o):null:null)}),k=({item:e,onItemClick:s,isChild:l=!1,onItemSelected:a})=>{const[r,o]=p.useState(e.defaultOpen??!1),[c,x]=p.useState(!1),h=Array.isArray(e.children)&&e.children.length>0,d=h&&e.expandable===!0,i=h&&!e.expandable,v=e.icon!==void 0,w=u=>{if(e.disabled)return;if(d){o(g=>!g);return}const b=String(e.key??"");i||(e.onClick?.({key:b,domEvent:u}),s?.({key:b,keyPath:[b],domEvent:u}),a?.())},E=p.useCallback(()=>{x(!1),a?.()},[a]),M=t.cn("flex items-center justify-between rounded-[4px] cursor-pointer select-none w-full transition-colors duration-100",l?"pl-9 pr-1 min-h-[36px]":"px-0 py-0.5",!v&&"overflow-hidden",e.disabled?"opacity-50 cursor-not-allowed":"",e.className),R=t.cn("flex items-center justify-between gap-3 rounded-[4px] cursor-pointer select-none w-full transition-colors duration-100 dark:bg-black-800",l?"pl-9 pr-1 py-2 min-h-[36px]":"px-3 py-2",e.disabled?"opacity-50 cursor-not-allowed":"",e.className),N=d?n.jsx(f.ExpandMoreFilledIcon,{size:16,className:t.cn("flex-none transition-transform duration-200",r?"rotate-180":"rotate-0")}):i?n.jsx(f.KeyboardArrowRightIcon,{size:16,className:"flex-none"}):null,y=p.isValidElement(e.label)&&e.label.type?.displayName==="OptionButton",S=y&&N?p.cloneElement(e.label,{chevron:N}):e.label,m=v?n.jsxs("div",{className:R,onClick:e.disabled?void 0:w,children:[n.jsxs("div",{className:"flex items-center gap-3 min-w-0 flex-1",children:[n.jsx("span",{className:t.cn("flex-none flex items-center justify-center",l?"size-4":"size-5"),children:e.icon}),n.jsx("span",{className:t.cn("text-sm font-medium leading-5 whitespace-nowrap",e.danger?"text-error-600":"text-neutral-900 dark:text-neutral-100"),children:e.label})]}),d&&n.jsx(f.ExpandMoreFilledIcon,{size:20,className:t.cn("flex-none text-neutral-500 dark:text-neutral-400 transition-transform duration-200",r?"rotate-180":"rotate-0")}),i&&n.jsx(f.KeyboardArrowRightIcon,{size:20,className:"flex-none text-neutral-500 dark:text-neutral-400"})]}):n.jsxs("div",{className:M,onClick:e.disabled?void 0:w,children:[n.jsx("div",{className:t.cn("min-w-0 flex-1"),children:S}),!y&&d&&n.jsx(f.ExpandMoreFilledIcon,{size:16,className:t.cn("flex-none mr-2 text-neutral-500 dark:text-neutral-400 transition-transform duration-200",r?"rotate-180":"rotate-0")}),!y&&i&&n.jsx(f.KeyboardArrowRightIcon,{size:16,className:"flex-none mr-2 text-neutral-500 dark:text-neutral-400"})]});return i?n.jsx(C.Popover,{open:c,onOpenChange:x,content:n.jsx(O,{items:e.children,onItemClick:s,onItemSelected:E}),trigger:"hover",placement:"rightTop",overlayInnerStyle:{padding:0},overlayStyle:{padding:0},arrow:!1,children:n.jsx("div",{children:m})}):n.jsxs("div",{children:[m,d&&n.jsx("div",{className:t.cn("grid transition-[grid-template-rows] duration-200 ease-in-out",r?"grid-rows-[1fr]":"grid-rows-[0fr]"),children:n.jsx("div",{className:"overflow-hidden",children:n.jsx("div",{className:"flex flex-col",children:e.children?.map((u,b)=>{if(!u||!j(u))return null;const g=b===(e.children?.length??0)-1;return n.jsxs("div",{className:"relative",children:[n.jsx("div",{className:"absolute left-[19px] top-0 w-3.5 border-l border-b border-neutral-200 dark:border-black-600 rounded-bl-[6px] pointer-events-none",style:{height:"calc(50% + 4px)"}}),!g&&n.jsx("div",{className:"absolute left-[19px] top-1/2 bottom-0 w-px bg-neutral-200 dark:bg-black-600 pointer-events-none"}),n.jsx(k,{item:u,onItemClick:s,isChild:!0,onItemSelected:a})]},u.key??b)})})})})]})},z=({children:e,menu:s,minWidth:l=200,onOpenChange:a,...r})=>{const[o,c]=p.useState(0),x=(d,i)=>{d||c(v=>v+1),a?.(d,i)},h=p.useCallback(()=>n.jsx(O,{items:s?.items,onItemClick:s?.onClick,minWidth:l},o),[s?.items,s?.onClick,l,o]);return n.jsx(C.Dropdown,{...r,onOpenChange:x,popupRender:h,children:e})};exports.Dropdown=z;exports.default=z;
2
2
  //# sourceMappingURL=Dropdown.cjs.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"Dropdown.cjs.js","sources":["../../../src/components/dropdown/Dropdown.tsx"],"sourcesContent":["import { Dropdown as AntDropdown, Popover } from 'antd';\nimport type { DropdownProps as AntDropdownProps } from 'antd';\nimport React, { useCallback, useState } from 'react';\nimport { cn } from '../../lib/utils';\nimport {\n ExpandMoreFilledIcon,\n KeyboardArrowRightIcon,\n} from '../icon';\n\n// ─── Item Types ──────────────────────────────────────────────────────────────\n\nexport interface DropdownMenuItemDef {\n key?: string | number;\n label?: React.ReactNode;\n /** Icon displayed before the label (enables native rendering mode). */\n icon?: React.ReactNode;\n disabled?: boolean;\n /** Renders label in error-600 color. */\n danger?: boolean;\n className?: string;\n onClick?: (info: { key: string; domEvent: React.MouseEvent }) => void;\n children?: DropdownItemDef[];\n /**\n * When `true` and `children` is provided, items expand inline below the\n * parent rather than opening a side-panel popup. Defaults to `false`.\n */\n expandable?: boolean;\n /** When `expandable` is true, controls the initial open state. */\n defaultOpen?: boolean;\n}\n\nexport interface DropdownDividerDef {\n type: 'divider';\n key?: string | number;\n dashed?: boolean;\n}\n\nexport interface DropdownGroupDef {\n type: 'group';\n key?: string | number;\n label?: React.ReactNode;\n children?: DropdownItemDef[];\n}\n\nexport type DropdownItemDef =\n | DropdownMenuItemDef\n | DropdownDividerDef\n | DropdownGroupDef\n | null\n | undefined;\n\nexport interface DropdownMenuConfig {\n items?: DropdownItemDef[];\n onClick?: (info: {\n key: string;\n keyPath: string[];\n domEvent: React.MouseEvent;\n }) => void;\n [key: string]: unknown;\n}\n\nexport interface DropdownProps\n extends Omit<AntDropdownProps, 'overlay' | 'dropdownRender' | 'menu'> {\n menu?: DropdownMenuConfig;\n /** Minimum width of the dropdown panel in pixels. Defaults to 200. */\n minWidth?: number;\n}\n\n// ─── Internal helpers ────────────────────────────────────────────────────────\n\nfunction isMenuItemDef(item: DropdownItemDef): item is DropdownMenuItemDef {\n return !!item && !('type' in item);\n}\n\n// ─── DropdownMenuPanel ────────────────────────────────────────────────────────\n\ninterface DropdownMenuPanelProps {\n items?: DropdownItemDef[];\n onItemClick?: DropdownMenuConfig['onClick'];\n minWidth?: number;\n /** Fires after a leaf item is clicked. Used to close ancestor popovers. */\n onItemSelected?: () => void;\n}\n\nconst DropdownMenuPanel: React.FC<DropdownMenuPanelProps> = ({\n items,\n onItemClick,\n minWidth = 200,\n onItemSelected,\n}) => {\n return (\n <div\n className='bg-white dark:bg-black-800 border border-neutral-200 dark:border-black-600 rounded-[8px] shadow flex flex-col gap-1 p-0'\n style={{ minWidth }}\n >\n {items?.map((item, idx) => {\n if (!item) return null;\n\n if ('type' in item && item.type === 'divider') {\n return (\n <div\n key={item.key ?? `divider-${idx}`}\n className='h-px bg-neutral-200 dark:bg-black-600 mx-1 my-0.5'\n />\n );\n }\n\n if ('type' in item && item.type === 'group') {\n return (\n <div key={item.key ?? `group-${idx}`}>\n {item.label && (\n <div className='px-3 py-1 text-xs font-semibold text-neutral-500 dark:text-neutral-400 uppercase tracking-wide'>\n {item.label}\n </div>\n )}\n {item.children?.map((child, childIdx) =>\n isMenuItemDef(child) ? (\n <DropdownMenuItemRow\n key={(child as DropdownMenuItemDef).key ?? childIdx}\n item={child}\n onItemClick={onItemClick}\n onItemSelected={onItemSelected}\n />\n ) : null,\n )}\n </div>\n );\n }\n\n if (isMenuItemDef(item)) {\n return (\n <DropdownMenuItemRow\n key={item.key ?? idx}\n item={item}\n onItemClick={onItemClick}\n onItemSelected={onItemSelected}\n />\n );\n }\n\n return null;\n })}\n </div>\n );\n};\n\n// ─── DropdownMenuItemRow ─────────────────────────────────────────────────────\n\ninterface DropdownMenuItemRowProps {\n item: DropdownMenuItemDef;\n onItemClick?: DropdownMenuConfig['onClick'];\n isChild?: boolean;\n /** Closes the enclosing popover. Propagates upward through nested submenus. */\n onItemSelected?: () => void;\n}\n\nconst DropdownMenuItemRow: React.FC<DropdownMenuItemRowProps> = ({\n item,\n onItemClick,\n isChild = false,\n onItemSelected,\n}) => {\n const [expanded, setExpanded] = useState(item.defaultOpen ?? false);\n const [popoverOpen, setPopoverOpen] = useState(false);\n\n const hasChildren =\n Array.isArray(item.children) && item.children.length > 0;\n const isCollapsable = hasChildren && item.expandable === true;\n const isSubmenu = hasChildren && !item.expandable;\n const isNative = item.icon !== undefined;\n\n const handleClick = (e: React.MouseEvent) => {\n if (item.disabled) return;\n\n if (isCollapsable) {\n setExpanded((prev) => !prev);\n return;\n }\n\n const key = String(item.key ?? '');\n if (!isSubmenu) {\n item.onClick?.({ key, domEvent: e });\n onItemClick?.({ key, keyPath: [key], domEvent: e });\n onItemSelected?.();\n }\n };\n\n const handleChildSelected = useCallback(() => {\n setPopoverOpen(false);\n onItemSelected?.();\n }, [onItemSelected]);\n\n const containerClasses = cn(\n 'flex items-center justify-between rounded-[4px] cursor-pointer select-none w-full transition-colors duration-100',\n isChild ? 'pl-9 pr-1 min-h-[36px]' : 'px-0 py-0.5',\n !isNative && 'overflow-hidden',\n item.disabled ? 'opacity-50 cursor-not-allowed' : '',\n item.className,\n );\n\n const nativeContainerClasses = cn(\n 'flex items-center justify-between gap-3 rounded-[4px] cursor-pointer select-none w-full transition-colors duration-100 dark:bg-black-800',\n isChild ? 'pl-9 pr-1 py-2 min-h-[36px]' : 'px-3 py-2',\n item.disabled ? 'opacity-50 cursor-not-allowed' : '',\n item.className,\n );\n\n const compatChevron = isCollapsable ? (\n <ExpandMoreFilledIcon\n size={16}\n className={cn(\n 'flex-none transition-transform duration-200',\n expanded ? 'rotate-180' : 'rotate-0',\n )}\n />\n ) : isSubmenu ? (\n <KeyboardArrowRightIcon size={16} className='flex-none' />\n ) : null;\n\n const compatLabelIsOptionButton =\n React.isValidElement(item.label) &&\n (item.label.type as { displayName?: string })?.displayName === 'OptionButton';\n\n const compatLabelNode =\n compatLabelIsOptionButton && compatChevron\n ? React.cloneElement(item.label as React.ReactElement<{ chevron?: React.ReactNode }>, {\n chevron: compatChevron,\n })\n : item.label;\n\n const itemContent = isNative ? (\n // Native rendering: icon + label + optional indicator\n <div className={nativeContainerClasses} onClick={!item.disabled ? handleClick : undefined}>\n <div className='flex items-center gap-3 min-w-0 flex-1'>\n <span\n className={cn(\n 'flex-none flex items-center justify-center',\n isChild ? 'size-4' : 'size-5',\n )}\n >\n {item.icon}\n </span>\n <span\n className={cn(\n 'text-sm font-medium leading-5 whitespace-nowrap',\n item.danger\n ? 'text-error-600'\n : 'text-neutral-900 dark:text-neutral-100',\n )}\n >\n {item.label}\n </span>\n </div>\n\n {isCollapsable && (\n <ExpandMoreFilledIcon\n size={20}\n className={cn(\n 'flex-none text-neutral-500 dark:text-neutral-400 transition-transform duration-200',\n expanded ? 'rotate-180' : 'rotate-0',\n )}\n />\n )}\n {isSubmenu && (\n <KeyboardArrowRightIcon\n size={20}\n className='flex-none text-neutral-500 dark:text-neutral-400'\n />\n )}\n </div>\n ) : (\n // Compat rendering: label is a fully rendered node (e.g. OptionButton).\n // For OptionButton labels we inject the chevron as a prop so it sits inside\n // the button's hover area; for any other node we fall back to a sibling chevron.\n <div className={containerClasses} onClick={!item.disabled ? handleClick : undefined}>\n <div className={cn('min-w-0 flex-1')}>{compatLabelNode}</div>\n {!compatLabelIsOptionButton && isCollapsable && (\n <ExpandMoreFilledIcon\n size={16}\n className={cn(\n 'flex-none mr-2 text-neutral-500 dark:text-neutral-400 transition-transform duration-200',\n expanded ? 'rotate-180' : 'rotate-0',\n )}\n />\n )}\n {!compatLabelIsOptionButton && isSubmenu && (\n <KeyboardArrowRightIcon\n size={16}\n className='flex-none mr-2 text-neutral-500 dark:text-neutral-400'\n />\n )}\n </div>\n );\n\n if (isSubmenu) {\n return (\n <Popover\n open={popoverOpen}\n onOpenChange={setPopoverOpen}\n content={\n <DropdownMenuPanel\n items={item.children}\n onItemClick={onItemClick}\n onItemSelected={handleChildSelected}\n />\n }\n trigger='hover'\n placement='rightTop'\n overlayInnerStyle={{ padding: 0 }}\n overlayStyle={{ padding: 0 }}\n arrow={false}\n >\n <div>{itemContent}</div>\n </Popover>\n );\n }\n\n return (\n <div>\n {itemContent}\n {isCollapsable && (\n <div\n className={cn(\n 'grid transition-[grid-template-rows] duration-200 ease-in-out',\n expanded ? 'grid-rows-[1fr]' : 'grid-rows-[0fr]',\n )}\n >\n <div className='overflow-hidden'>\n <div className='flex flex-col'>\n {item.children?.map((child, idx) => {\n if (!child || !isMenuItemDef(child)) return null;\n const isLast = idx === (item.children?.length ?? 0) - 1;\n return (\n <div key={(child as DropdownMenuItemDef).key ?? idx} className='relative'>\n {/* L-shaped connector: vertical segment from top to row midpoint, curves right */}\n <div\n className='absolute left-[19px] top-0 w-3.5 border-l border-b border-neutral-200 dark:border-black-600 rounded-bl-[6px] pointer-events-none'\n style={{ height: 'calc(50% + 4px)' }}\n />\n {/* Vertical bridge down to next sibling */}\n {!isLast && (\n <div className='absolute left-[19px] top-1/2 bottom-0 w-px bg-neutral-200 dark:bg-black-600 pointer-events-none' />\n )}\n <DropdownMenuItemRow\n item={child as DropdownMenuItemDef}\n onItemClick={onItemClick}\n isChild\n onItemSelected={onItemSelected}\n />\n </div>\n );\n })}\n </div>\n </div>\n </div>\n )}\n </div>\n );\n};\n\n// ─── Dropdown ────────────────────────────────────────────────────────────────\n\nexport const Dropdown: React.FC<DropdownProps> = ({\n children,\n menu,\n minWidth = 200,\n onOpenChange,\n ...rest\n}) => {\n const [remountKey, setRemountKey] = useState(0);\n\n const handleOpenChange: AntDropdownProps['onOpenChange'] = (open, info) => {\n if (!open) {\n // Force-remount the panel on close so nested collapsible/submenu\n // open state is reset the next time the dropdown is opened.\n setRemountKey((k) => k + 1);\n }\n onOpenChange?.(open, info);\n };\n\n const popupRender = useCallback(\n () => (\n <DropdownMenuPanel\n key={remountKey}\n items={menu?.items as DropdownItemDef[]}\n onItemClick={menu?.onClick as DropdownMenuConfig['onClick']}\n minWidth={minWidth}\n />\n ),\n // eslint-disable-next-line react-hooks/exhaustive-deps\n [menu?.items, menu?.onClick, minWidth, remountKey],\n );\n\n return (\n <AntDropdown\n {...rest}\n onOpenChange={handleOpenChange}\n popupRender={popupRender}\n >\n {children as React.ReactElement}\n </AntDropdown>\n );\n};\n\nexport default Dropdown;\n"],"names":["isMenuItemDef","item","DropdownMenuPanel","items","onItemClick","minWidth","onItemSelected","jsx","idx","child","childIdx","DropdownMenuItemRow","isChild","expanded","setExpanded","useState","popoverOpen","setPopoverOpen","hasChildren","isCollapsable","isSubmenu","isNative","handleClick","e","prev","key","handleChildSelected","useCallback","containerClasses","cn","nativeContainerClasses","compatChevron","ExpandMoreFilledIcon","KeyboardArrowRightIcon","compatLabelIsOptionButton","React","compatLabelNode","itemContent","jsxs","Popover","isLast","Dropdown","children","menu","onOpenChange","rest","remountKey","setRemountKey","handleOpenChange","open","info","k","popupRender","AntDropdown"],"mappings":"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"}
1
+ {"version":3,"file":"Dropdown.cjs.js","sources":["../../../src/components/dropdown/Dropdown.tsx"],"sourcesContent":["import { Dropdown as AntDropdown, Popover } from 'antd';\nimport type { DropdownProps as AntDropdownProps } from 'antd';\nimport React, { useCallback, useState } from 'react';\nimport { cn } from '../../lib/utils';\nimport {\n ExpandMoreFilledIcon,\n KeyboardArrowRightIcon,\n} from '../icon';\n\n// ─── Item Types ──────────────────────────────────────────────────────────────\n\nexport interface DropdownMenuItemDef {\n key?: string | number;\n label?: React.ReactNode;\n /** Icon displayed before the label (enables native rendering mode). */\n icon?: React.ReactNode;\n disabled?: boolean;\n /** Renders label in error-600 color. */\n danger?: boolean;\n className?: string;\n onClick?: (info: { key: string; domEvent: React.MouseEvent }) => void;\n children?: DropdownItemDef[];\n /**\n * When `true` and `children` is provided, items expand inline below the\n * parent rather than opening a side-panel popup. Defaults to `false`.\n */\n expandable?: boolean;\n /** When `expandable` is true, controls the initial open state. */\n defaultOpen?: boolean;\n}\n\nexport interface DropdownDividerDef {\n type: 'divider';\n key?: string | number;\n dashed?: boolean;\n}\n\nexport interface DropdownGroupDef {\n type: 'group';\n key?: string | number;\n label?: React.ReactNode;\n children?: DropdownItemDef[];\n}\n\nexport type DropdownItemDef =\n | DropdownMenuItemDef\n | DropdownDividerDef\n | DropdownGroupDef\n | null\n | undefined;\n\nexport interface DropdownMenuConfig {\n items?: DropdownItemDef[];\n onClick?: (info: {\n key: string;\n keyPath: string[];\n domEvent: React.MouseEvent;\n }) => void;\n [key: string]: unknown;\n}\n\nexport interface DropdownProps\n extends Omit<AntDropdownProps, 'overlay' | 'dropdownRender' | 'menu'> {\n menu?: DropdownMenuConfig;\n /** Minimum width of the dropdown panel in pixels. Defaults to 200. */\n minWidth?: number;\n}\n\n// ─── Internal helpers ────────────────────────────────────────────────────────\n\nfunction isMenuItemDef(item: DropdownItemDef): item is DropdownMenuItemDef {\n return !!item && !('type' in item);\n}\n\n// ─── DropdownMenuPanel ────────────────────────────────────────────────────────\n\ninterface DropdownMenuPanelProps {\n items?: DropdownItemDef[];\n onItemClick?: DropdownMenuConfig['onClick'];\n minWidth?: number;\n /** Fires after a leaf item is clicked. Used to close ancestor popovers. */\n onItemSelected?: () => void;\n}\n\nconst DropdownMenuPanel: React.FC<DropdownMenuPanelProps> = ({\n items,\n onItemClick,\n minWidth = 200,\n onItemSelected,\n}) => {\n return (\n <div\n className='bg-white dark:bg-black-800 border border-neutral-200 dark:border-black-600 rounded-[8px] shadow flex flex-col p-0 border-none overflow-hidden'\n style={{ minWidth }}\n >\n {items?.map((item, idx) => {\n if (!item) return null;\n\n if ('type' in item && item.type === 'divider') {\n return (\n <div\n key={item.key ?? `divider-${idx}`}\n className='h-px bg-neutral-200 dark:bg-black-600 mx-1 my-0.5'\n />\n );\n }\n\n if ('type' in item && item.type === 'group') {\n return (\n <div key={item.key ?? `group-${idx}`}>\n {item.label && (\n <div className='px-3 py-1 text-xs font-semibold text-neutral-500 dark:text-neutral-400 uppercase tracking-wide'>\n {item.label}\n </div>\n )}\n {item.children?.map((child, childIdx) =>\n isMenuItemDef(child) ? (\n <DropdownMenuItemRow\n key={(child as DropdownMenuItemDef).key ?? childIdx}\n item={child}\n onItemClick={onItemClick}\n onItemSelected={onItemSelected}\n />\n ) : null,\n )}\n </div>\n );\n }\n\n if (isMenuItemDef(item)) {\n return (\n <DropdownMenuItemRow\n key={item.key ?? idx}\n item={item}\n onItemClick={onItemClick}\n onItemSelected={onItemSelected}\n />\n );\n }\n\n return null;\n })}\n </div>\n );\n};\n\n// ─── DropdownMenuItemRow ─────────────────────────────────────────────────────\n\ninterface DropdownMenuItemRowProps {\n item: DropdownMenuItemDef;\n onItemClick?: DropdownMenuConfig['onClick'];\n isChild?: boolean;\n /** Closes the enclosing popover. Propagates upward through nested submenus. */\n onItemSelected?: () => void;\n}\n\nconst DropdownMenuItemRow: React.FC<DropdownMenuItemRowProps> = ({\n item,\n onItemClick,\n isChild = false,\n onItemSelected,\n}) => {\n const [expanded, setExpanded] = useState(item.defaultOpen ?? false);\n const [popoverOpen, setPopoverOpen] = useState(false);\n\n const hasChildren =\n Array.isArray(item.children) && item.children.length > 0;\n const isCollapsable = hasChildren && item.expandable === true;\n const isSubmenu = hasChildren && !item.expandable;\n const isNative = item.icon !== undefined;\n\n const handleClick = (e: React.MouseEvent) => {\n if (item.disabled) return;\n\n if (isCollapsable) {\n setExpanded((prev) => !prev);\n return;\n }\n\n const key = String(item.key ?? '');\n if (!isSubmenu) {\n item.onClick?.({ key, domEvent: e });\n onItemClick?.({ key, keyPath: [key], domEvent: e });\n onItemSelected?.();\n }\n };\n\n const handleChildSelected = useCallback(() => {\n setPopoverOpen(false);\n onItemSelected?.();\n }, [onItemSelected]);\n\n const containerClasses = cn(\n 'flex items-center justify-between rounded-[4px] cursor-pointer select-none w-full transition-colors duration-100',\n isChild ? 'pl-9 pr-1 min-h-[36px]' : 'px-0 py-0.5',\n !isNative && 'overflow-hidden',\n item.disabled ? 'opacity-50 cursor-not-allowed' : '',\n item.className,\n );\n\n const nativeContainerClasses = cn(\n 'flex items-center justify-between gap-3 rounded-[4px] cursor-pointer select-none w-full transition-colors duration-100 dark:bg-black-800',\n isChild ? 'pl-9 pr-1 py-2 min-h-[36px]' : 'px-3 py-2',\n item.disabled ? 'opacity-50 cursor-not-allowed' : '',\n item.className,\n );\n\n const compatChevron = isCollapsable ? (\n <ExpandMoreFilledIcon\n size={16}\n className={cn(\n 'flex-none transition-transform duration-200',\n expanded ? 'rotate-180' : 'rotate-0',\n )}\n />\n ) : isSubmenu ? (\n <KeyboardArrowRightIcon size={16} className='flex-none' />\n ) : null;\n\n const compatLabelIsOptionButton =\n React.isValidElement(item.label) &&\n (item.label.type as { displayName?: string })?.displayName === 'OptionButton';\n\n const compatLabelNode =\n compatLabelIsOptionButton && compatChevron\n ? React.cloneElement(item.label as React.ReactElement<{ chevron?: React.ReactNode }>, {\n chevron: compatChevron,\n })\n : item.label;\n\n const itemContent = isNative ? (\n // Native rendering: icon + label + optional indicator\n <div className={nativeContainerClasses} onClick={!item.disabled ? handleClick : undefined}>\n <div className='flex items-center gap-3 min-w-0 flex-1'>\n <span\n className={cn(\n 'flex-none flex items-center justify-center',\n isChild ? 'size-4' : 'size-5',\n )}\n >\n {item.icon}\n </span>\n <span\n className={cn(\n 'text-sm font-medium leading-5 whitespace-nowrap',\n item.danger\n ? 'text-error-600'\n : 'text-neutral-900 dark:text-neutral-100',\n )}\n >\n {item.label}\n </span>\n </div>\n\n {isCollapsable && (\n <ExpandMoreFilledIcon\n size={20}\n className={cn(\n 'flex-none text-neutral-500 dark:text-neutral-400 transition-transform duration-200',\n expanded ? 'rotate-180' : 'rotate-0',\n )}\n />\n )}\n {isSubmenu && (\n <KeyboardArrowRightIcon\n size={20}\n className='flex-none text-neutral-500 dark:text-neutral-400'\n />\n )}\n </div>\n ) : (\n // Compat rendering: label is a fully rendered node (e.g. OptionButton).\n // For OptionButton labels we inject the chevron as a prop so it sits inside\n // the button's hover area; for any other node we fall back to a sibling chevron.\n <div className={containerClasses} onClick={!item.disabled ? handleClick : undefined}>\n <div className={cn('min-w-0 flex-1')}>{compatLabelNode}</div>\n {!compatLabelIsOptionButton && isCollapsable && (\n <ExpandMoreFilledIcon\n size={16}\n className={cn(\n 'flex-none mr-2 text-neutral-500 dark:text-neutral-400 transition-transform duration-200',\n expanded ? 'rotate-180' : 'rotate-0',\n )}\n />\n )}\n {!compatLabelIsOptionButton && isSubmenu && (\n <KeyboardArrowRightIcon\n size={16}\n className='flex-none mr-2 text-neutral-500 dark:text-neutral-400'\n />\n )}\n </div>\n );\n\n if (isSubmenu) {\n return (\n <Popover\n open={popoverOpen}\n onOpenChange={setPopoverOpen}\n content={\n <DropdownMenuPanel\n items={item.children}\n onItemClick={onItemClick}\n onItemSelected={handleChildSelected}\n />\n }\n trigger='hover'\n placement='rightTop'\n overlayInnerStyle={{ padding: 0 }}\n overlayStyle={{ padding: 0 }}\n arrow={false}\n >\n <div>{itemContent}</div>\n </Popover>\n );\n }\n\n return (\n <div>\n {itemContent}\n {isCollapsable && (\n <div\n className={cn(\n 'grid transition-[grid-template-rows] duration-200 ease-in-out',\n expanded ? 'grid-rows-[1fr]' : 'grid-rows-[0fr]',\n )}\n >\n <div className='overflow-hidden'>\n <div className='flex flex-col'>\n {item.children?.map((child, idx) => {\n if (!child || !isMenuItemDef(child)) return null;\n const isLast = idx === (item.children?.length ?? 0) - 1;\n return (\n <div key={(child as DropdownMenuItemDef).key ?? idx} className='relative'>\n {/* L-shaped connector: vertical segment from top to row midpoint, curves right */}\n <div\n className='absolute left-[19px] top-0 w-3.5 border-l border-b border-neutral-200 dark:border-black-600 rounded-bl-[6px] pointer-events-none'\n style={{ height: 'calc(50% + 4px)' }}\n />\n {/* Vertical bridge down to next sibling */}\n {!isLast && (\n <div className='absolute left-[19px] top-1/2 bottom-0 w-px bg-neutral-200 dark:bg-black-600 pointer-events-none' />\n )}\n <DropdownMenuItemRow\n item={child as DropdownMenuItemDef}\n onItemClick={onItemClick}\n isChild\n onItemSelected={onItemSelected}\n />\n </div>\n );\n })}\n </div>\n </div>\n </div>\n )}\n </div>\n );\n};\n\n// ─── Dropdown ────────────────────────────────────────────────────────────────\n\nexport const Dropdown: React.FC<DropdownProps> = ({\n children,\n menu,\n minWidth = 200,\n onOpenChange,\n ...rest\n}) => {\n const [remountKey, setRemountKey] = useState(0);\n\n const handleOpenChange: AntDropdownProps['onOpenChange'] = (open, info) => {\n if (!open) {\n // Force-remount the panel on close so nested collapsible/submenu\n // open state is reset the next time the dropdown is opened.\n setRemountKey((k) => k + 1);\n }\n onOpenChange?.(open, info);\n };\n\n const popupRender = useCallback(\n () => (\n <DropdownMenuPanel\n key={remountKey}\n items={menu?.items as DropdownItemDef[]}\n onItemClick={menu?.onClick as DropdownMenuConfig['onClick']}\n minWidth={minWidth}\n />\n ),\n // eslint-disable-next-line react-hooks/exhaustive-deps\n [menu?.items, menu?.onClick, minWidth, remountKey],\n );\n\n return (\n <AntDropdown\n {...rest}\n onOpenChange={handleOpenChange}\n popupRender={popupRender}\n >\n {children as React.ReactElement}\n </AntDropdown>\n );\n};\n\nexport default Dropdown;\n"],"names":["isMenuItemDef","item","DropdownMenuPanel","items","onItemClick","minWidth","onItemSelected","jsx","idx","child","childIdx","DropdownMenuItemRow","isChild","expanded","setExpanded","useState","popoverOpen","setPopoverOpen","hasChildren","isCollapsable","isSubmenu","isNative","handleClick","e","prev","key","handleChildSelected","useCallback","containerClasses","cn","nativeContainerClasses","compatChevron","ExpandMoreFilledIcon","KeyboardArrowRightIcon","compatLabelIsOptionButton","React","compatLabelNode","itemContent","jsxs","Popover","isLast","Dropdown","children","menu","onOpenChange","rest","remountKey","setRemountKey","handleOpenChange","open","info","k","popupRender","AntDropdown"],"mappings":"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"}
@@ -1,8 +1,8 @@
1
1
  import { jsx as n, jsxs as x } from "react/jsx-runtime";
2
2
  import { Dropdown as K, Popover as L } from "antd";
3
- import D, { useState as m, useCallback as E } from "react";
3
+ import D, { useState as g, useCallback as E } from "react";
4
4
  import { cn as l } from "../../lib/utils.es.js";
5
- import { ExpandMoreFilledIcon as g, KeyboardArrowRightIcon as k } from "../icon/icons.generated.es.js";
5
+ import { ExpandMoreFilledIcon as k, KeyboardArrowRightIcon as m } from "../icon/icons.generated.es.js";
6
6
  function w(e) {
7
7
  return !!e && !("type" in e);
8
8
  }
@@ -14,7 +14,7 @@ const j = ({
14
14
  }) => /* @__PURE__ */ n(
15
15
  "div",
16
16
  {
17
- className: "bg-white dark:bg-black-800 border border-neutral-200 dark:border-black-600 rounded-[8px] shadow flex flex-col gap-1 p-0",
17
+ className: "bg-white dark:bg-black-800 border border-neutral-200 dark:border-black-600 rounded-[8px] shadow flex flex-col p-0 border-none overflow-hidden",
18
18
  style: { minWidth: o },
19
19
  children: e?.map((r, s) => r ? "type" in r && r.type === "divider" ? /* @__PURE__ */ n(
20
20
  "div",
@@ -51,7 +51,7 @@ const j = ({
51
51
  isChild: o = !1,
52
52
  onItemSelected: t
53
53
  }) => {
54
- const [r, s] = m(e.defaultOpen ?? !1), [i, u] = m(!1), b = Array.isArray(e.children) && e.children.length > 0, d = b && e.expandable === !0, c = b && !e.expandable, h = e.icon !== void 0, C = (p) => {
54
+ const [r, s] = g(e.defaultOpen ?? !1), [i, u] = g(!1), b = Array.isArray(e.children) && e.children.length > 0, d = b && e.expandable === !0, c = b && !e.expandable, h = e.icon !== void 0, C = (p) => {
55
55
  if (e.disabled) return;
56
56
  if (d) {
57
57
  s((y) => !y);
@@ -73,7 +73,7 @@ const j = ({
73
73
  e.disabled ? "opacity-50 cursor-not-allowed" : "",
74
74
  e.className
75
75
  ), z = d ? /* @__PURE__ */ n(
76
- g,
76
+ k,
77
77
  {
78
78
  size: 16,
79
79
  className: l(
@@ -81,7 +81,7 @@ const j = ({
81
81
  r ? "rotate-180" : "rotate-0"
82
82
  )
83
83
  }
84
- ) : c ? /* @__PURE__ */ n(k, { size: 16, className: "flex-none" }) : null, v = D.isValidElement(e.label) && e.label.type?.displayName === "OptionButton", A = v && z ? D.cloneElement(e.label, {
84
+ ) : c ? /* @__PURE__ */ n(m, { size: 16, className: "flex-none" }) : null, v = D.isValidElement(e.label) && e.label.type?.displayName === "OptionButton", A = v && z ? D.cloneElement(e.label, {
85
85
  chevron: z
86
86
  }) : e.label, O = h ? (
87
87
  // Native rendering: icon + label + optional indicator
@@ -109,7 +109,7 @@ const j = ({
109
109
  )
110
110
  ] }),
111
111
  d && /* @__PURE__ */ n(
112
- g,
112
+ k,
113
113
  {
114
114
  size: 20,
115
115
  className: l(
@@ -119,7 +119,7 @@ const j = ({
119
119
  }
120
120
  ),
121
121
  c && /* @__PURE__ */ n(
122
- k,
122
+ m,
123
123
  {
124
124
  size: 20,
125
125
  className: "flex-none text-neutral-500 dark:text-neutral-400"
@@ -133,7 +133,7 @@ const j = ({
133
133
  /* @__PURE__ */ x("div", { className: M, onClick: e.disabled ? void 0 : C, children: [
134
134
  /* @__PURE__ */ n("div", { className: l("min-w-0 flex-1"), children: A }),
135
135
  !v && d && /* @__PURE__ */ n(
136
- g,
136
+ k,
137
137
  {
138
138
  size: 16,
139
139
  className: l(
@@ -143,7 +143,7 @@ const j = ({
143
143
  }
144
144
  ),
145
145
  !v && c && /* @__PURE__ */ n(
146
- k,
146
+ m,
147
147
  {
148
148
  size: 16,
149
149
  className: "flex-none mr-2 text-neutral-500 dark:text-neutral-400"
@@ -213,7 +213,7 @@ const j = ({
213
213
  onOpenChange: t,
214
214
  ...r
215
215
  }) => {
216
- const [s, i] = m(0), u = (d, c) => {
216
+ const [s, i] = g(0), u = (d, c) => {
217
217
  d || i((h) => h + 1), t?.(d, c);
218
218
  }, b = E(
219
219
  () => /* @__PURE__ */ n(
@@ -1 +1 @@
1
- {"version":3,"file":"Dropdown.es.js","sources":["../../../src/components/dropdown/Dropdown.tsx"],"sourcesContent":["import { Dropdown as AntDropdown, Popover } from 'antd';\nimport type { DropdownProps as AntDropdownProps } from 'antd';\nimport React, { useCallback, useState } from 'react';\nimport { cn } from '../../lib/utils';\nimport {\n ExpandMoreFilledIcon,\n KeyboardArrowRightIcon,\n} from '../icon';\n\n// ─── Item Types ──────────────────────────────────────────────────────────────\n\nexport interface DropdownMenuItemDef {\n key?: string | number;\n label?: React.ReactNode;\n /** Icon displayed before the label (enables native rendering mode). */\n icon?: React.ReactNode;\n disabled?: boolean;\n /** Renders label in error-600 color. */\n danger?: boolean;\n className?: string;\n onClick?: (info: { key: string; domEvent: React.MouseEvent }) => void;\n children?: DropdownItemDef[];\n /**\n * When `true` and `children` is provided, items expand inline below the\n * parent rather than opening a side-panel popup. Defaults to `false`.\n */\n expandable?: boolean;\n /** When `expandable` is true, controls the initial open state. */\n defaultOpen?: boolean;\n}\n\nexport interface DropdownDividerDef {\n type: 'divider';\n key?: string | number;\n dashed?: boolean;\n}\n\nexport interface DropdownGroupDef {\n type: 'group';\n key?: string | number;\n label?: React.ReactNode;\n children?: DropdownItemDef[];\n}\n\nexport type DropdownItemDef =\n | DropdownMenuItemDef\n | DropdownDividerDef\n | DropdownGroupDef\n | null\n | undefined;\n\nexport interface DropdownMenuConfig {\n items?: DropdownItemDef[];\n onClick?: (info: {\n key: string;\n keyPath: string[];\n domEvent: React.MouseEvent;\n }) => void;\n [key: string]: unknown;\n}\n\nexport interface DropdownProps\n extends Omit<AntDropdownProps, 'overlay' | 'dropdownRender' | 'menu'> {\n menu?: DropdownMenuConfig;\n /** Minimum width of the dropdown panel in pixels. Defaults to 200. */\n minWidth?: number;\n}\n\n// ─── Internal helpers ────────────────────────────────────────────────────────\n\nfunction isMenuItemDef(item: DropdownItemDef): item is DropdownMenuItemDef {\n return !!item && !('type' in item);\n}\n\n// ─── DropdownMenuPanel ────────────────────────────────────────────────────────\n\ninterface DropdownMenuPanelProps {\n items?: DropdownItemDef[];\n onItemClick?: DropdownMenuConfig['onClick'];\n minWidth?: number;\n /** Fires after a leaf item is clicked. Used to close ancestor popovers. */\n onItemSelected?: () => void;\n}\n\nconst DropdownMenuPanel: React.FC<DropdownMenuPanelProps> = ({\n items,\n onItemClick,\n minWidth = 200,\n onItemSelected,\n}) => {\n return (\n <div\n className='bg-white dark:bg-black-800 border border-neutral-200 dark:border-black-600 rounded-[8px] shadow flex flex-col gap-1 p-0'\n style={{ minWidth }}\n >\n {items?.map((item, idx) => {\n if (!item) return null;\n\n if ('type' in item && item.type === 'divider') {\n return (\n <div\n key={item.key ?? `divider-${idx}`}\n className='h-px bg-neutral-200 dark:bg-black-600 mx-1 my-0.5'\n />\n );\n }\n\n if ('type' in item && item.type === 'group') {\n return (\n <div key={item.key ?? `group-${idx}`}>\n {item.label && (\n <div className='px-3 py-1 text-xs font-semibold text-neutral-500 dark:text-neutral-400 uppercase tracking-wide'>\n {item.label}\n </div>\n )}\n {item.children?.map((child, childIdx) =>\n isMenuItemDef(child) ? (\n <DropdownMenuItemRow\n key={(child as DropdownMenuItemDef).key ?? childIdx}\n item={child}\n onItemClick={onItemClick}\n onItemSelected={onItemSelected}\n />\n ) : null,\n )}\n </div>\n );\n }\n\n if (isMenuItemDef(item)) {\n return (\n <DropdownMenuItemRow\n key={item.key ?? idx}\n item={item}\n onItemClick={onItemClick}\n onItemSelected={onItemSelected}\n />\n );\n }\n\n return null;\n })}\n </div>\n );\n};\n\n// ─── DropdownMenuItemRow ─────────────────────────────────────────────────────\n\ninterface DropdownMenuItemRowProps {\n item: DropdownMenuItemDef;\n onItemClick?: DropdownMenuConfig['onClick'];\n isChild?: boolean;\n /** Closes the enclosing popover. Propagates upward through nested submenus. */\n onItemSelected?: () => void;\n}\n\nconst DropdownMenuItemRow: React.FC<DropdownMenuItemRowProps> = ({\n item,\n onItemClick,\n isChild = false,\n onItemSelected,\n}) => {\n const [expanded, setExpanded] = useState(item.defaultOpen ?? false);\n const [popoverOpen, setPopoverOpen] = useState(false);\n\n const hasChildren =\n Array.isArray(item.children) && item.children.length > 0;\n const isCollapsable = hasChildren && item.expandable === true;\n const isSubmenu = hasChildren && !item.expandable;\n const isNative = item.icon !== undefined;\n\n const handleClick = (e: React.MouseEvent) => {\n if (item.disabled) return;\n\n if (isCollapsable) {\n setExpanded((prev) => !prev);\n return;\n }\n\n const key = String(item.key ?? '');\n if (!isSubmenu) {\n item.onClick?.({ key, domEvent: e });\n onItemClick?.({ key, keyPath: [key], domEvent: e });\n onItemSelected?.();\n }\n };\n\n const handleChildSelected = useCallback(() => {\n setPopoverOpen(false);\n onItemSelected?.();\n }, [onItemSelected]);\n\n const containerClasses = cn(\n 'flex items-center justify-between rounded-[4px] cursor-pointer select-none w-full transition-colors duration-100',\n isChild ? 'pl-9 pr-1 min-h-[36px]' : 'px-0 py-0.5',\n !isNative && 'overflow-hidden',\n item.disabled ? 'opacity-50 cursor-not-allowed' : '',\n item.className,\n );\n\n const nativeContainerClasses = cn(\n 'flex items-center justify-between gap-3 rounded-[4px] cursor-pointer select-none w-full transition-colors duration-100 dark:bg-black-800',\n isChild ? 'pl-9 pr-1 py-2 min-h-[36px]' : 'px-3 py-2',\n item.disabled ? 'opacity-50 cursor-not-allowed' : '',\n item.className,\n );\n\n const compatChevron = isCollapsable ? (\n <ExpandMoreFilledIcon\n size={16}\n className={cn(\n 'flex-none transition-transform duration-200',\n expanded ? 'rotate-180' : 'rotate-0',\n )}\n />\n ) : isSubmenu ? (\n <KeyboardArrowRightIcon size={16} className='flex-none' />\n ) : null;\n\n const compatLabelIsOptionButton =\n React.isValidElement(item.label) &&\n (item.label.type as { displayName?: string })?.displayName === 'OptionButton';\n\n const compatLabelNode =\n compatLabelIsOptionButton && compatChevron\n ? React.cloneElement(item.label as React.ReactElement<{ chevron?: React.ReactNode }>, {\n chevron: compatChevron,\n })\n : item.label;\n\n const itemContent = isNative ? (\n // Native rendering: icon + label + optional indicator\n <div className={nativeContainerClasses} onClick={!item.disabled ? handleClick : undefined}>\n <div className='flex items-center gap-3 min-w-0 flex-1'>\n <span\n className={cn(\n 'flex-none flex items-center justify-center',\n isChild ? 'size-4' : 'size-5',\n )}\n >\n {item.icon}\n </span>\n <span\n className={cn(\n 'text-sm font-medium leading-5 whitespace-nowrap',\n item.danger\n ? 'text-error-600'\n : 'text-neutral-900 dark:text-neutral-100',\n )}\n >\n {item.label}\n </span>\n </div>\n\n {isCollapsable && (\n <ExpandMoreFilledIcon\n size={20}\n className={cn(\n 'flex-none text-neutral-500 dark:text-neutral-400 transition-transform duration-200',\n expanded ? 'rotate-180' : 'rotate-0',\n )}\n />\n )}\n {isSubmenu && (\n <KeyboardArrowRightIcon\n size={20}\n className='flex-none text-neutral-500 dark:text-neutral-400'\n />\n )}\n </div>\n ) : (\n // Compat rendering: label is a fully rendered node (e.g. OptionButton).\n // For OptionButton labels we inject the chevron as a prop so it sits inside\n // the button's hover area; for any other node we fall back to a sibling chevron.\n <div className={containerClasses} onClick={!item.disabled ? handleClick : undefined}>\n <div className={cn('min-w-0 flex-1')}>{compatLabelNode}</div>\n {!compatLabelIsOptionButton && isCollapsable && (\n <ExpandMoreFilledIcon\n size={16}\n className={cn(\n 'flex-none mr-2 text-neutral-500 dark:text-neutral-400 transition-transform duration-200',\n expanded ? 'rotate-180' : 'rotate-0',\n )}\n />\n )}\n {!compatLabelIsOptionButton && isSubmenu && (\n <KeyboardArrowRightIcon\n size={16}\n className='flex-none mr-2 text-neutral-500 dark:text-neutral-400'\n />\n )}\n </div>\n );\n\n if (isSubmenu) {\n return (\n <Popover\n open={popoverOpen}\n onOpenChange={setPopoverOpen}\n content={\n <DropdownMenuPanel\n items={item.children}\n onItemClick={onItemClick}\n onItemSelected={handleChildSelected}\n />\n }\n trigger='hover'\n placement='rightTop'\n overlayInnerStyle={{ padding: 0 }}\n overlayStyle={{ padding: 0 }}\n arrow={false}\n >\n <div>{itemContent}</div>\n </Popover>\n );\n }\n\n return (\n <div>\n {itemContent}\n {isCollapsable && (\n <div\n className={cn(\n 'grid transition-[grid-template-rows] duration-200 ease-in-out',\n expanded ? 'grid-rows-[1fr]' : 'grid-rows-[0fr]',\n )}\n >\n <div className='overflow-hidden'>\n <div className='flex flex-col'>\n {item.children?.map((child, idx) => {\n if (!child || !isMenuItemDef(child)) return null;\n const isLast = idx === (item.children?.length ?? 0) - 1;\n return (\n <div key={(child as DropdownMenuItemDef).key ?? idx} className='relative'>\n {/* L-shaped connector: vertical segment from top to row midpoint, curves right */}\n <div\n className='absolute left-[19px] top-0 w-3.5 border-l border-b border-neutral-200 dark:border-black-600 rounded-bl-[6px] pointer-events-none'\n style={{ height: 'calc(50% + 4px)' }}\n />\n {/* Vertical bridge down to next sibling */}\n {!isLast && (\n <div className='absolute left-[19px] top-1/2 bottom-0 w-px bg-neutral-200 dark:bg-black-600 pointer-events-none' />\n )}\n <DropdownMenuItemRow\n item={child as DropdownMenuItemDef}\n onItemClick={onItemClick}\n isChild\n onItemSelected={onItemSelected}\n />\n </div>\n );\n })}\n </div>\n </div>\n </div>\n )}\n </div>\n );\n};\n\n// ─── Dropdown ────────────────────────────────────────────────────────────────\n\nexport const Dropdown: React.FC<DropdownProps> = ({\n children,\n menu,\n minWidth = 200,\n onOpenChange,\n ...rest\n}) => {\n const [remountKey, setRemountKey] = useState(0);\n\n const handleOpenChange: AntDropdownProps['onOpenChange'] = (open, info) => {\n if (!open) {\n // Force-remount the panel on close so nested collapsible/submenu\n // open state is reset the next time the dropdown is opened.\n setRemountKey((k) => k + 1);\n }\n onOpenChange?.(open, info);\n };\n\n const popupRender = useCallback(\n () => (\n <DropdownMenuPanel\n key={remountKey}\n items={menu?.items as DropdownItemDef[]}\n onItemClick={menu?.onClick as DropdownMenuConfig['onClick']}\n minWidth={minWidth}\n />\n ),\n // eslint-disable-next-line react-hooks/exhaustive-deps\n [menu?.items, menu?.onClick, minWidth, remountKey],\n );\n\n return (\n <AntDropdown\n {...rest}\n onOpenChange={handleOpenChange}\n popupRender={popupRender}\n >\n {children as React.ReactElement}\n </AntDropdown>\n );\n};\n\nexport default Dropdown;\n"],"names":["isMenuItemDef","item","DropdownMenuPanel","items","onItemClick","minWidth","onItemSelected","jsx","idx","child","childIdx","DropdownMenuItemRow","isChild","expanded","setExpanded","useState","popoverOpen","setPopoverOpen","hasChildren","isCollapsable","isSubmenu","isNative","handleClick","e","prev","key","handleChildSelected","useCallback","containerClasses","cn","nativeContainerClasses","compatChevron","ExpandMoreFilledIcon","KeyboardArrowRightIcon","compatLabelIsOptionButton","React","compatLabelNode","itemContent","jsxs","Popover","isLast","Dropdown","children","menu","onOpenChange","rest","remountKey","setRemountKey","handleOpenChange","open","info","k","popupRender","AntDropdown"],"mappings":"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"}
1
+ {"version":3,"file":"Dropdown.es.js","sources":["../../../src/components/dropdown/Dropdown.tsx"],"sourcesContent":["import { Dropdown as AntDropdown, Popover } from 'antd';\nimport type { DropdownProps as AntDropdownProps } from 'antd';\nimport React, { useCallback, useState } from 'react';\nimport { cn } from '../../lib/utils';\nimport {\n ExpandMoreFilledIcon,\n KeyboardArrowRightIcon,\n} from '../icon';\n\n// ─── Item Types ──────────────────────────────────────────────────────────────\n\nexport interface DropdownMenuItemDef {\n key?: string | number;\n label?: React.ReactNode;\n /** Icon displayed before the label (enables native rendering mode). */\n icon?: React.ReactNode;\n disabled?: boolean;\n /** Renders label in error-600 color. */\n danger?: boolean;\n className?: string;\n onClick?: (info: { key: string; domEvent: React.MouseEvent }) => void;\n children?: DropdownItemDef[];\n /**\n * When `true` and `children` is provided, items expand inline below the\n * parent rather than opening a side-panel popup. Defaults to `false`.\n */\n expandable?: boolean;\n /** When `expandable` is true, controls the initial open state. */\n defaultOpen?: boolean;\n}\n\nexport interface DropdownDividerDef {\n type: 'divider';\n key?: string | number;\n dashed?: boolean;\n}\n\nexport interface DropdownGroupDef {\n type: 'group';\n key?: string | number;\n label?: React.ReactNode;\n children?: DropdownItemDef[];\n}\n\nexport type DropdownItemDef =\n | DropdownMenuItemDef\n | DropdownDividerDef\n | DropdownGroupDef\n | null\n | undefined;\n\nexport interface DropdownMenuConfig {\n items?: DropdownItemDef[];\n onClick?: (info: {\n key: string;\n keyPath: string[];\n domEvent: React.MouseEvent;\n }) => void;\n [key: string]: unknown;\n}\n\nexport interface DropdownProps\n extends Omit<AntDropdownProps, 'overlay' | 'dropdownRender' | 'menu'> {\n menu?: DropdownMenuConfig;\n /** Minimum width of the dropdown panel in pixels. Defaults to 200. */\n minWidth?: number;\n}\n\n// ─── Internal helpers ────────────────────────────────────────────────────────\n\nfunction isMenuItemDef(item: DropdownItemDef): item is DropdownMenuItemDef {\n return !!item && !('type' in item);\n}\n\n// ─── DropdownMenuPanel ────────────────────────────────────────────────────────\n\ninterface DropdownMenuPanelProps {\n items?: DropdownItemDef[];\n onItemClick?: DropdownMenuConfig['onClick'];\n minWidth?: number;\n /** Fires after a leaf item is clicked. Used to close ancestor popovers. */\n onItemSelected?: () => void;\n}\n\nconst DropdownMenuPanel: React.FC<DropdownMenuPanelProps> = ({\n items,\n onItemClick,\n minWidth = 200,\n onItemSelected,\n}) => {\n return (\n <div\n className='bg-white dark:bg-black-800 border border-neutral-200 dark:border-black-600 rounded-[8px] shadow flex flex-col p-0 border-none overflow-hidden'\n style={{ minWidth }}\n >\n {items?.map((item, idx) => {\n if (!item) return null;\n\n if ('type' in item && item.type === 'divider') {\n return (\n <div\n key={item.key ?? `divider-${idx}`}\n className='h-px bg-neutral-200 dark:bg-black-600 mx-1 my-0.5'\n />\n );\n }\n\n if ('type' in item && item.type === 'group') {\n return (\n <div key={item.key ?? `group-${idx}`}>\n {item.label && (\n <div className='px-3 py-1 text-xs font-semibold text-neutral-500 dark:text-neutral-400 uppercase tracking-wide'>\n {item.label}\n </div>\n )}\n {item.children?.map((child, childIdx) =>\n isMenuItemDef(child) ? (\n <DropdownMenuItemRow\n key={(child as DropdownMenuItemDef).key ?? childIdx}\n item={child}\n onItemClick={onItemClick}\n onItemSelected={onItemSelected}\n />\n ) : null,\n )}\n </div>\n );\n }\n\n if (isMenuItemDef(item)) {\n return (\n <DropdownMenuItemRow\n key={item.key ?? idx}\n item={item}\n onItemClick={onItemClick}\n onItemSelected={onItemSelected}\n />\n );\n }\n\n return null;\n })}\n </div>\n );\n};\n\n// ─── DropdownMenuItemRow ─────────────────────────────────────────────────────\n\ninterface DropdownMenuItemRowProps {\n item: DropdownMenuItemDef;\n onItemClick?: DropdownMenuConfig['onClick'];\n isChild?: boolean;\n /** Closes the enclosing popover. Propagates upward through nested submenus. */\n onItemSelected?: () => void;\n}\n\nconst DropdownMenuItemRow: React.FC<DropdownMenuItemRowProps> = ({\n item,\n onItemClick,\n isChild = false,\n onItemSelected,\n}) => {\n const [expanded, setExpanded] = useState(item.defaultOpen ?? false);\n const [popoverOpen, setPopoverOpen] = useState(false);\n\n const hasChildren =\n Array.isArray(item.children) && item.children.length > 0;\n const isCollapsable = hasChildren && item.expandable === true;\n const isSubmenu = hasChildren && !item.expandable;\n const isNative = item.icon !== undefined;\n\n const handleClick = (e: React.MouseEvent) => {\n if (item.disabled) return;\n\n if (isCollapsable) {\n setExpanded((prev) => !prev);\n return;\n }\n\n const key = String(item.key ?? '');\n if (!isSubmenu) {\n item.onClick?.({ key, domEvent: e });\n onItemClick?.({ key, keyPath: [key], domEvent: e });\n onItemSelected?.();\n }\n };\n\n const handleChildSelected = useCallback(() => {\n setPopoverOpen(false);\n onItemSelected?.();\n }, [onItemSelected]);\n\n const containerClasses = cn(\n 'flex items-center justify-between rounded-[4px] cursor-pointer select-none w-full transition-colors duration-100',\n isChild ? 'pl-9 pr-1 min-h-[36px]' : 'px-0 py-0.5',\n !isNative && 'overflow-hidden',\n item.disabled ? 'opacity-50 cursor-not-allowed' : '',\n item.className,\n );\n\n const nativeContainerClasses = cn(\n 'flex items-center justify-between gap-3 rounded-[4px] cursor-pointer select-none w-full transition-colors duration-100 dark:bg-black-800',\n isChild ? 'pl-9 pr-1 py-2 min-h-[36px]' : 'px-3 py-2',\n item.disabled ? 'opacity-50 cursor-not-allowed' : '',\n item.className,\n );\n\n const compatChevron = isCollapsable ? (\n <ExpandMoreFilledIcon\n size={16}\n className={cn(\n 'flex-none transition-transform duration-200',\n expanded ? 'rotate-180' : 'rotate-0',\n )}\n />\n ) : isSubmenu ? (\n <KeyboardArrowRightIcon size={16} className='flex-none' />\n ) : null;\n\n const compatLabelIsOptionButton =\n React.isValidElement(item.label) &&\n (item.label.type as { displayName?: string })?.displayName === 'OptionButton';\n\n const compatLabelNode =\n compatLabelIsOptionButton && compatChevron\n ? React.cloneElement(item.label as React.ReactElement<{ chevron?: React.ReactNode }>, {\n chevron: compatChevron,\n })\n : item.label;\n\n const itemContent = isNative ? (\n // Native rendering: icon + label + optional indicator\n <div className={nativeContainerClasses} onClick={!item.disabled ? handleClick : undefined}>\n <div className='flex items-center gap-3 min-w-0 flex-1'>\n <span\n className={cn(\n 'flex-none flex items-center justify-center',\n isChild ? 'size-4' : 'size-5',\n )}\n >\n {item.icon}\n </span>\n <span\n className={cn(\n 'text-sm font-medium leading-5 whitespace-nowrap',\n item.danger\n ? 'text-error-600'\n : 'text-neutral-900 dark:text-neutral-100',\n )}\n >\n {item.label}\n </span>\n </div>\n\n {isCollapsable && (\n <ExpandMoreFilledIcon\n size={20}\n className={cn(\n 'flex-none text-neutral-500 dark:text-neutral-400 transition-transform duration-200',\n expanded ? 'rotate-180' : 'rotate-0',\n )}\n />\n )}\n {isSubmenu && (\n <KeyboardArrowRightIcon\n size={20}\n className='flex-none text-neutral-500 dark:text-neutral-400'\n />\n )}\n </div>\n ) : (\n // Compat rendering: label is a fully rendered node (e.g. OptionButton).\n // For OptionButton labels we inject the chevron as a prop so it sits inside\n // the button's hover area; for any other node we fall back to a sibling chevron.\n <div className={containerClasses} onClick={!item.disabled ? handleClick : undefined}>\n <div className={cn('min-w-0 flex-1')}>{compatLabelNode}</div>\n {!compatLabelIsOptionButton && isCollapsable && (\n <ExpandMoreFilledIcon\n size={16}\n className={cn(\n 'flex-none mr-2 text-neutral-500 dark:text-neutral-400 transition-transform duration-200',\n expanded ? 'rotate-180' : 'rotate-0',\n )}\n />\n )}\n {!compatLabelIsOptionButton && isSubmenu && (\n <KeyboardArrowRightIcon\n size={16}\n className='flex-none mr-2 text-neutral-500 dark:text-neutral-400'\n />\n )}\n </div>\n );\n\n if (isSubmenu) {\n return (\n <Popover\n open={popoverOpen}\n onOpenChange={setPopoverOpen}\n content={\n <DropdownMenuPanel\n items={item.children}\n onItemClick={onItemClick}\n onItemSelected={handleChildSelected}\n />\n }\n trigger='hover'\n placement='rightTop'\n overlayInnerStyle={{ padding: 0 }}\n overlayStyle={{ padding: 0 }}\n arrow={false}\n >\n <div>{itemContent}</div>\n </Popover>\n );\n }\n\n return (\n <div>\n {itemContent}\n {isCollapsable && (\n <div\n className={cn(\n 'grid transition-[grid-template-rows] duration-200 ease-in-out',\n expanded ? 'grid-rows-[1fr]' : 'grid-rows-[0fr]',\n )}\n >\n <div className='overflow-hidden'>\n <div className='flex flex-col'>\n {item.children?.map((child, idx) => {\n if (!child || !isMenuItemDef(child)) return null;\n const isLast = idx === (item.children?.length ?? 0) - 1;\n return (\n <div key={(child as DropdownMenuItemDef).key ?? idx} className='relative'>\n {/* L-shaped connector: vertical segment from top to row midpoint, curves right */}\n <div\n className='absolute left-[19px] top-0 w-3.5 border-l border-b border-neutral-200 dark:border-black-600 rounded-bl-[6px] pointer-events-none'\n style={{ height: 'calc(50% + 4px)' }}\n />\n {/* Vertical bridge down to next sibling */}\n {!isLast && (\n <div className='absolute left-[19px] top-1/2 bottom-0 w-px bg-neutral-200 dark:bg-black-600 pointer-events-none' />\n )}\n <DropdownMenuItemRow\n item={child as DropdownMenuItemDef}\n onItemClick={onItemClick}\n isChild\n onItemSelected={onItemSelected}\n />\n </div>\n );\n })}\n </div>\n </div>\n </div>\n )}\n </div>\n );\n};\n\n// ─── Dropdown ────────────────────────────────────────────────────────────────\n\nexport const Dropdown: React.FC<DropdownProps> = ({\n children,\n menu,\n minWidth = 200,\n onOpenChange,\n ...rest\n}) => {\n const [remountKey, setRemountKey] = useState(0);\n\n const handleOpenChange: AntDropdownProps['onOpenChange'] = (open, info) => {\n if (!open) {\n // Force-remount the panel on close so nested collapsible/submenu\n // open state is reset the next time the dropdown is opened.\n setRemountKey((k) => k + 1);\n }\n onOpenChange?.(open, info);\n };\n\n const popupRender = useCallback(\n () => (\n <DropdownMenuPanel\n key={remountKey}\n items={menu?.items as DropdownItemDef[]}\n onItemClick={menu?.onClick as DropdownMenuConfig['onClick']}\n minWidth={minWidth}\n />\n ),\n // eslint-disable-next-line react-hooks/exhaustive-deps\n [menu?.items, menu?.onClick, minWidth, remountKey],\n );\n\n return (\n <AntDropdown\n {...rest}\n onOpenChange={handleOpenChange}\n popupRender={popupRender}\n >\n {children as React.ReactElement}\n </AntDropdown>\n );\n};\n\nexport default Dropdown;\n"],"names":["isMenuItemDef","item","DropdownMenuPanel","items","onItemClick","minWidth","onItemSelected","jsx","idx","child","childIdx","DropdownMenuItemRow","isChild","expanded","setExpanded","useState","popoverOpen","setPopoverOpen","hasChildren","isCollapsable","isSubmenu","isNative","handleClick","e","prev","key","handleChildSelected","useCallback","containerClasses","cn","nativeContainerClasses","compatChevron","ExpandMoreFilledIcon","KeyboardArrowRightIcon","compatLabelIsOptionButton","React","compatLabelNode","itemContent","jsxs","Popover","isLast","Dropdown","children","menu","onOpenChange","rest","remountKey","setRemountKey","handleOpenChange","open","info","k","popupRender","AntDropdown"],"mappings":"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"}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@lax-wp/design-system",
3
3
  "private": false,
4
- "version": "0.13.43",
4
+ "version": "0.13.44",
5
5
  "type": "module",
6
6
  "main": "dist/index.cjs.js",
7
7
  "module": "dist/index.es.js",