@lobehub/ui 5.10.5 → 5.11.0

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,7 +1,9 @@
1
+ import { IconProps } from "../Icon/type.mjs";
1
2
  import { MenuCheckboxItemType } from "./checkboxItem.mjs";
2
3
  import { MenuSwitchItemType } from "./switchItem.mjs";
3
4
  import { MenuDividerType, MenuItemType, SubMenuType } from "./type.mjs";
4
- import { Key, ReactNode } from "react";
5
+ import { ComponentPropsWithRef, Key, MouseEventHandler, ReactNode } from "react";
6
+ import { MenuSubmenuRoot } from "@base-ui/react/menu";
5
7
 
6
8
  //#region src/Menu/baseItem.d.ts
7
9
  /**
@@ -16,10 +18,36 @@ interface BaseMenuItemGroupType {
16
18
  }
17
19
  /**
18
20
  * Submenu type for Base UI driven menus (DropdownMenu / ContextMenu).
19
- * Unlike SubMenuType, this supports checkbox/switch items in children.
21
+ * Unlike rc-menu's SubMenuType, this maps to @base-ui's Menu.SubmenuRoot + Menu.SubmenuTrigger.
20
22
  */
21
- interface BaseSubMenuType extends Omit<SubMenuType, 'children'> {
23
+ interface BaseSubMenuType {
22
24
  children?: BaseMenuItemType[];
25
+ /** Hover-close delay in ms. Requires `openOnHover`. */
26
+ closeDelay?: number;
27
+ danger?: boolean;
28
+ /** Initial open state when uncontrolled. */
29
+ defaultOpen?: boolean;
30
+ /** Hover-open delay in ms. Requires `openOnHover`. */
31
+ delay?: number;
32
+ desc?: ReactNode;
33
+ disabled?: boolean;
34
+ icon?: IconProps['icon'];
35
+ key?: Key;
36
+ label?: ReactNode;
37
+ /** Click handler on the trigger. */
38
+ onClick?: MouseEventHandler<HTMLElement>;
39
+ /** Fired when the submenu opens or closes. */
40
+ onOpenChange?: (open: boolean, eventDetails: MenuSubmenuRoot.ChangeEventDetails) => void;
41
+ /** Controlled open state of the submenu. */
42
+ open?: boolean;
43
+ /** Open the submenu when the trigger is hovered. */
44
+ openOnHover?: boolean;
45
+ /**
46
+ * Extra DOM props spread onto the trigger element.
47
+ * Use for `ref`, `id`, `style`, `data-*`, `aria-*`, mouse/focus events, etc.
48
+ */
49
+ triggerProps?: ComponentPropsWithRef<'div'>;
50
+ type?: 'submenu';
23
51
  }
24
52
  /**
25
53
  * Base item union for Base UI driven menus (DropdownMenu / ContextMenu).
@@ -27,7 +55,7 @@ interface BaseSubMenuType extends Omit<SubMenuType, 'children'> {
27
55
  * Note: This intentionally does NOT change `GenericItemType` itself,
28
56
  * because `GenericItemType` maps to rc-menu/antd Menu item types.
29
57
  */
30
- type BaseMenuItemType = MenuItemType | BaseSubMenuType | BaseMenuItemGroupType | MenuDividerType | MenuCheckboxItemType | MenuSwitchItemType | null;
58
+ type BaseMenuItemType = MenuItemType | BaseSubMenuType | SubMenuType | BaseMenuItemGroupType | MenuDividerType | MenuCheckboxItemType | MenuSwitchItemType | null;
31
59
  //#endregion
32
60
  export { BaseMenuItemGroupType, BaseMenuItemType, BaseSubMenuType };
33
61
  //# sourceMappingURL=baseItem.d.mts.map
@@ -186,29 +186,39 @@ const renderContextMenuItems = (items, keyPath = [], options) => {
186
186
  const label = getItemLabel(submenu);
187
187
  const labelText = typeof label === "string" ? label : void 0;
188
188
  const isDanger = "danger" in submenu && Boolean(submenu.danger);
189
- return /* @__PURE__ */ jsxs(ContextMenu.SubmenuRoot, { children: [/* @__PURE__ */ jsx(ContextMenu.SubmenuTrigger, {
190
- className: cx(styles.item, isDanger && styles.danger),
191
- disabled: submenu.disabled,
192
- label: labelText,
193
- children: renderItemContent(submenu, {
194
- iconAlign,
195
- reserveIconSpace,
196
- submenu: true
197
- })
198
- }), /* @__PURE__ */ jsx(ContextMenu.Portal, { children: /* @__PURE__ */ jsx(ContextMenu.Positioner, {
199
- alignOffset: -4,
200
- className: styles.positioner,
201
- "data-submenu": "",
202
- sideOffset: -1,
203
- onContextMenu: preventDefaultAndStopPropagation,
204
- children: /* @__PURE__ */ jsx(ContextMenu.Popup, {
205
- className: styles.popup,
206
- children: submenu.children && submenu.children.length > 0 ? renderContextMenuItems(submenu.children, nextKeyPath, {
189
+ return /* @__PURE__ */ jsxs(ContextMenu.SubmenuRoot, {
190
+ defaultOpen: submenu.defaultOpen,
191
+ open: submenu.open,
192
+ onOpenChange: submenu.onOpenChange,
193
+ children: [/* @__PURE__ */ jsx(ContextMenu.SubmenuTrigger, {
194
+ ...submenu.triggerProps,
195
+ className: cx(styles.item, isDanger && styles.danger),
196
+ closeDelay: submenu.closeDelay,
197
+ delay: submenu.delay,
198
+ disabled: submenu.disabled,
199
+ label: labelText,
200
+ openOnHover: submenu.openOnHover,
201
+ onClick: submenu.onClick,
202
+ children: renderItemContent(submenu, {
207
203
  iconAlign,
208
- iconSpaceMode
209
- }) : /* @__PURE__ */ jsx(EmptyMenuItem, {})
210
- })
211
- }) })] }, itemKey);
204
+ reserveIconSpace,
205
+ submenu: true
206
+ })
207
+ }), /* @__PURE__ */ jsx(ContextMenu.Portal, { children: /* @__PURE__ */ jsx(ContextMenu.Positioner, {
208
+ alignOffset: -4,
209
+ className: styles.positioner,
210
+ "data-submenu": "",
211
+ sideOffset: -1,
212
+ onContextMenu: preventDefaultAndStopPropagation,
213
+ children: /* @__PURE__ */ jsx(ContextMenu.Popup, {
214
+ className: styles.popup,
215
+ children: submenu.children && submenu.children.length > 0 ? renderContextMenuItems(submenu.children, nextKeyPath, {
216
+ iconAlign,
217
+ iconSpaceMode
218
+ }) : /* @__PURE__ */ jsx(EmptyMenuItem, {})
219
+ })
220
+ }) })]
221
+ }, itemKey);
212
222
  }
213
223
  const menuItem = item;
214
224
  const label = getItemLabel(menuItem);
@@ -1 +1 @@
1
- {"version":3,"file":"renderItems.mjs","names":["common"],"sources":["../../../src/base-ui/ContextMenu/renderItems.tsx"],"sourcesContent":["import { ContextMenu } from '@base-ui/react/context-menu';\nimport { Switch } from 'antd';\nimport { cx } from 'antd-style';\nimport { Check, ChevronRight } from 'lucide-react';\nimport { type MenuInfo } from 'rc-menu/es/interface';\nimport {\n type KeyboardEvent as ReactKeyboardEvent,\n type MouseEvent as ReactMouseEvent,\n type ReactNode,\n} from 'react';\nimport { memo, useCallback, useState } from 'react';\n\nimport common from '@/i18n/resources/en/common';\nimport { useTranslation } from '@/i18n/useTranslation';\nimport Icon from '@/Icon';\nimport {\n getItemKey,\n getItemLabel,\n hasAnyIcon,\n hasCheckboxAndIcon,\n type MenuDividerType,\n type MenuItemGroupType,\n type MenuItemType,\n renderIcon,\n type RenderItemContentOptions,\n type RenderOptions,\n type SubMenuType,\n} from '@/Menu';\nimport { styles } from '@/Menu/sharedStyle';\nimport { preventDefaultAndStopPropagation } from '@/utils/dom';\n\nimport {\n type ContextMenuCheckboxItem,\n type ContextMenuItem,\n type ContextMenuSwitchItem,\n} from './type';\n\nexport type { IconAlign, IconSpaceMode } from '@/Menu';\n\nconst EmptyMenuItem = memo(() => {\n const { t } = useTranslation(common);\n return (\n <ContextMenu.Item disabled className={cx(styles.item, styles.empty)}>\n <div className={styles.itemContent}>\n <span className={styles.label}>{t('common.empty')}</span>\n </div>\n </ContextMenu.Item>\n );\n});\n\nEmptyMenuItem.displayName = 'EmptyMenuItem';\n\ninterface ContextMenuSwitchItemInternalProps {\n checked?: boolean;\n children: ReactNode;\n closeOnClick?: boolean;\n danger?: boolean;\n defaultChecked?: boolean;\n disabled?: boolean;\n label?: string;\n onCheckedChange?: (checked: boolean) => void;\n}\n\nconst ContextMenuSwitchItemInternal = ({\n checked: checkedProp,\n children,\n closeOnClick = false,\n danger,\n defaultChecked,\n disabled,\n label,\n onCheckedChange,\n}: ContextMenuSwitchItemInternalProps) => {\n const [internalChecked, setInternalChecked] = useState(defaultChecked ?? false);\n const isControlled = checkedProp !== undefined;\n const checked = isControlled ? checkedProp : internalChecked;\n\n const handleCheckedChange = useCallback(\n (newChecked: boolean) => {\n if (!isControlled) {\n setInternalChecked(newChecked);\n }\n onCheckedChange?.(newChecked);\n },\n [isControlled, onCheckedChange],\n );\n\n return (\n <ContextMenu.Item\n className={cx(styles.item, danger && styles.danger)}\n closeOnClick={closeOnClick}\n disabled={disabled}\n label={label}\n onClick={(e) => {\n e.preventDefault();\n if (!disabled) {\n handleCheckedChange(!checked);\n }\n }}\n >\n {children}\n <span\n style={{ display: 'inline-flex', marginInlineStart: 16 }}\n onFocus={(e) => e.stopPropagation()}\n >\n <Switch\n checked={checked}\n disabled={disabled}\n size=\"small\"\n tabIndex={-1}\n onChange={handleCheckedChange}\n onClick={(_, e) => e.stopPropagation()}\n />\n </span>\n </ContextMenu.Item>\n );\n};\n\nconst renderItemContent = (\n item: MenuItemType | SubMenuType | ContextMenuCheckboxItem | ContextMenuSwitchItem,\n options?: RenderItemContentOptions,\n iconNode?: ReactNode,\n) => {\n const label = getItemLabel(item);\n const desc = 'desc' in item ? item.desc : undefined;\n const extra = 'extra' in item ? item.extra : undefined;\n const indicatorOnRight = options?.indicatorOnRight;\n const alignStart = Boolean(desc) && options?.iconAlign === 'start';\n const hasCustomIcon = iconNode !== undefined && !indicatorOnRight;\n const hasIcon = hasCustomIcon ? Boolean(iconNode) : Boolean(item.icon);\n const shouldRenderIcon = hasCustomIcon\n ? Boolean(options?.reserveIconSpace || iconNode)\n : Boolean(hasIcon || options?.reserveIconSpace);\n\n const labelNode = desc ? (\n <div className={styles.labelGroup}>\n <span className={styles.label}>{label}</span>\n <span className={styles.desc}>{desc}</span>\n </div>\n ) : (\n <span className={styles.label}>{label}</span>\n );\n\n return (\n <div className={cx(styles.itemContent, alignStart && styles.itemContentAlignStart)}>\n {shouldRenderIcon ? (\n <span\n aria-hidden={!hasIcon}\n className={cx(styles.icon, alignStart && styles.iconAlignStart)}\n >\n {hasCustomIcon ? iconNode : hasIcon ? renderIcon(item.icon, 'small') : null}\n </span>\n ) : null}\n {labelNode}\n {extra ? <span className={styles.extra}>{extra}</span> : null}\n {indicatorOnRight && iconNode ? iconNode : null}\n {options?.submenu ? (\n <span className={styles.submenuArrow}>\n <ChevronRight size={16} />\n </span>\n ) : null}\n </div>\n );\n};\n\nconst invokeItemClick = (\n item: MenuItemType,\n keyPath: string[],\n event: ReactMouseEvent<HTMLElement> | ReactKeyboardEvent<HTMLElement>,\n) => {\n if (!item.onClick) return;\n const key = item.key ?? keyPath.at(-1) ?? '';\n const info: MenuInfo = {\n domEvent: event,\n item: event.currentTarget as MenuInfo['item'],\n key: String(key),\n keyPath,\n };\n item.onClick(info);\n};\n\nexport const renderContextMenuItems = (\n items: ContextMenuItem[],\n keyPath: string[] = [],\n options?: RenderOptions,\n): ReactNode[] => {\n const iconAlign = options?.iconAlign;\n const iconSpaceMode = options?.iconSpaceMode ?? 'global';\n const reserveIconSpace =\n options?.reserveIconSpace ?? hasAnyIcon(items, iconSpaceMode === 'global');\n const indicatorOnRight = options?.indicatorOnRight ?? hasCheckboxAndIcon(items);\n\n return items.map((item, index) => {\n if (!item) return null;\n\n const fallbackKey = `${keyPath.join('-') || 'root'}-${index}`;\n const itemKey = getItemKey(item, fallbackKey);\n const nextKeyPath = [...keyPath, String(itemKey)];\n\n if ((item as ContextMenuCheckboxItem).type === 'checkbox') {\n const checkboxItem = item as ContextMenuCheckboxItem;\n const label = getItemLabel(checkboxItem);\n const labelText = typeof label === 'string' ? label : undefined;\n const isDanger = Boolean(checkboxItem.danger);\n const indicator = (\n <ContextMenu.CheckboxItemIndicator>\n <Icon icon={Check} size={'small'} />\n </ContextMenu.CheckboxItemIndicator>\n );\n\n return (\n <ContextMenu.CheckboxItem\n checked={checkboxItem.checked}\n className={cx(styles.item, isDanger && styles.danger)}\n closeOnClick={checkboxItem.closeOnClick}\n defaultChecked={checkboxItem.defaultChecked}\n disabled={checkboxItem.disabled}\n key={itemKey}\n label={labelText}\n onCheckedChange={(checked) => checkboxItem.onCheckedChange?.(checked)}\n >\n {renderItemContent(\n checkboxItem,\n { iconAlign, indicatorOnRight, reserveIconSpace },\n indicator,\n )}\n </ContextMenu.CheckboxItem>\n );\n }\n\n if ((item as ContextMenuSwitchItem).type === 'switch') {\n const switchItem = item as ContextMenuSwitchItem;\n const label = getItemLabel(switchItem);\n const labelText = typeof label === 'string' ? label : undefined;\n const isDanger = Boolean(switchItem.danger);\n\n return (\n <ContextMenuSwitchItemInternal\n checked={switchItem.checked}\n closeOnClick={switchItem.closeOnClick}\n danger={isDanger}\n defaultChecked={switchItem.defaultChecked}\n disabled={switchItem.disabled}\n key={itemKey}\n label={labelText}\n onCheckedChange={switchItem.onCheckedChange}\n >\n {renderItemContent(switchItem, { iconAlign, reserveIconSpace })}\n </ContextMenuSwitchItemInternal>\n );\n }\n\n if ((item as MenuDividerType).type === 'divider') {\n return <ContextMenu.Separator className={styles.separator} key={itemKey} />;\n }\n\n if ((item as MenuItemGroupType).type === 'group') {\n const group = item as MenuItemGroupType;\n const groupReserveIconSpace =\n iconSpaceMode === 'group'\n ? group.children\n ? hasAnyIcon(group.children)\n : false\n : reserveIconSpace;\n const groupIndicatorOnRight = group.children ? hasCheckboxAndIcon(group.children) : false;\n return (\n <ContextMenu.Group key={itemKey}>\n {group.label ? (\n <ContextMenu.GroupLabel className={styles.groupLabel}>\n {group.label}\n </ContextMenu.GroupLabel>\n ) : null}\n {group.children\n ? renderContextMenuItems(group.children, nextKeyPath, {\n iconAlign,\n iconSpaceMode,\n indicatorOnRight: groupIndicatorOnRight,\n reserveIconSpace: groupReserveIconSpace,\n })\n : null}\n </ContextMenu.Group>\n );\n }\n\n if (\n (item as SubMenuType).type === 'submenu' ||\n ('children' in item && (item as SubMenuType).children)\n ) {\n const submenu = item as SubMenuType;\n const label = getItemLabel(submenu);\n const labelText = typeof label === 'string' ? label : undefined;\n const isDanger = 'danger' in submenu && Boolean(submenu.danger);\n\n return (\n <ContextMenu.SubmenuRoot key={itemKey}>\n <ContextMenu.SubmenuTrigger\n className={cx(styles.item, isDanger && styles.danger)}\n disabled={submenu.disabled}\n label={labelText}\n >\n {renderItemContent(submenu, {\n iconAlign,\n reserveIconSpace,\n submenu: true,\n })}\n </ContextMenu.SubmenuTrigger>\n <ContextMenu.Portal>\n <ContextMenu.Positioner\n alignOffset={-4}\n className={styles.positioner}\n data-submenu=\"\"\n sideOffset={-1}\n onContextMenu={preventDefaultAndStopPropagation}\n >\n <ContextMenu.Popup className={styles.popup}>\n {submenu.children && submenu.children.length > 0 ? (\n renderContextMenuItems(submenu.children, nextKeyPath, {\n iconAlign,\n iconSpaceMode,\n })\n ) : (\n <EmptyMenuItem />\n )}\n </ContextMenu.Popup>\n </ContextMenu.Positioner>\n </ContextMenu.Portal>\n </ContextMenu.SubmenuRoot>\n );\n }\n\n const menuItem = item as MenuItemType;\n const label = getItemLabel(menuItem);\n const labelText = typeof label === 'string' ? label : undefined;\n const isDanger = 'danger' in menuItem && Boolean(menuItem.danger);\n\n return (\n <ContextMenu.Item\n className={cx(styles.item, isDanger && styles.danger)}\n closeOnClick={menuItem.closeOnClick}\n disabled={menuItem.disabled}\n key={itemKey}\n label={labelText}\n onClick={(event) => invokeItemClick(menuItem, nextKeyPath, event)}\n >\n {renderItemContent(menuItem, { iconAlign, reserveIconSpace })}\n </ContextMenu.Item>\n );\n });\n};\n"],"mappings":";;;;;;;;;;;;;AAuCA,MAAM,gBAAgB,WAAW;CAC/B,MAAM,EAAE,MAAM,eAAeA,eAAO;AACpC,QACE,oBAAC,YAAY,MAAb;EAAkB,UAAA;EAAS,WAAW,GAAG,OAAO,MAAM,OAAO,MAAM;YACjE,oBAAC,OAAD;GAAK,WAAW,OAAO;aACrB,oBAAC,QAAD;IAAM,WAAW,OAAO;cAAQ,EAAE,eAAe;IAAQ,CAAA;GACrD,CAAA;EACW,CAAA;EAErB;AAEF,cAAc,cAAc;AAa5B,MAAM,iCAAiC,EACrC,SAAS,aACT,UACA,eAAe,OACf,QACA,gBACA,UACA,OACA,sBACwC;CACxC,MAAM,CAAC,iBAAiB,sBAAsB,SAAS,kBAAkB,MAAM;CAC/E,MAAM,eAAe,gBAAgB,KAAA;CACrC,MAAM,UAAU,eAAe,cAAc;CAE7C,MAAM,sBAAsB,aACzB,eAAwB;AACvB,MAAI,CAAC,aACH,oBAAmB,WAAW;AAEhC,oBAAkB,WAAW;IAE/B,CAAC,cAAc,gBAAgB,CAChC;AAED,QACE,qBAAC,YAAY,MAAb;EACE,WAAW,GAAG,OAAO,MAAM,UAAU,OAAO,OAAO;EACrC;EACJ;EACH;EACP,UAAU,MAAM;AACd,KAAE,gBAAgB;AAClB,OAAI,CAAC,SACH,qBAAoB,CAAC,QAAQ;;YARnC,CAYG,UACD,oBAAC,QAAD;GACE,OAAO;IAAE,SAAS;IAAe,mBAAmB;IAAI;GACxD,UAAU,MAAM,EAAE,iBAAiB;aAEnC,oBAAC,QAAD;IACW;IACC;IACV,MAAK;IACL,UAAU;IACV,UAAU;IACV,UAAU,GAAG,MAAM,EAAE,iBAAiB;IACtC,CAAA;GACG,CAAA,CACU;;;AAIvB,MAAM,qBACJ,MACA,SACA,aACG;CACH,MAAM,QAAQ,aAAa,KAAK;CAChC,MAAM,OAAO,UAAU,OAAO,KAAK,OAAO,KAAA;CAC1C,MAAM,QAAQ,WAAW,OAAO,KAAK,QAAQ,KAAA;CAC7C,MAAM,mBAAmB,SAAS;CAClC,MAAM,aAAa,QAAQ,KAAK,IAAI,SAAS,cAAc;CAC3D,MAAM,gBAAgB,aAAa,KAAA,KAAa,CAAC;CACjD,MAAM,UAAU,gBAAgB,QAAQ,SAAS,GAAG,QAAQ,KAAK,KAAK;CACtE,MAAM,mBAAmB,gBACrB,QAAQ,SAAS,oBAAoB,SAAS,GAC9C,QAAQ,WAAW,SAAS,iBAAiB;CAEjD,MAAM,YAAY,OAChB,qBAAC,OAAD;EAAK,WAAW,OAAO;YAAvB,CACE,oBAAC,QAAD;GAAM,WAAW,OAAO;aAAQ;GAAa,CAAA,EAC7C,oBAAC,QAAD;GAAM,WAAW,OAAO;aAAO;GAAY,CAAA,CACvC;MAEN,oBAAC,QAAD;EAAM,WAAW,OAAO;YAAQ;EAAa,CAAA;AAG/C,QACE,qBAAC,OAAD;EAAK,WAAW,GAAG,OAAO,aAAa,cAAc,OAAO,sBAAsB;YAAlF;GACG,mBACC,oBAAC,QAAD;IACE,eAAa,CAAC;IACd,WAAW,GAAG,OAAO,MAAM,cAAc,OAAO,eAAe;cAE9D,gBAAgB,WAAW,UAAU,WAAW,KAAK,MAAM,QAAQ,GAAG;IAClE,CAAA,GACL;GACH;GACA,QAAQ,oBAAC,QAAD;IAAM,WAAW,OAAO;cAAQ;IAAa,CAAA,GAAG;GACxD,oBAAoB,WAAW,WAAW;GAC1C,SAAS,UACR,oBAAC,QAAD;IAAM,WAAW,OAAO;cACtB,oBAAC,cAAD,EAAc,MAAM,IAAM,CAAA;IACrB,CAAA,GACL;GACA;;;AAIV,MAAM,mBACJ,MACA,SACA,UACG;AACH,KAAI,CAAC,KAAK,QAAS;CACnB,MAAM,MAAM,KAAK,OAAO,QAAQ,GAAG,GAAG,IAAI;CAC1C,MAAM,OAAiB;EACrB,UAAU;EACV,MAAM,MAAM;EACZ,KAAK,OAAO,IAAI;EAChB;EACD;AACD,MAAK,QAAQ,KAAK;;AAGpB,MAAa,0BACX,OACA,UAAoB,EAAE,EACtB,YACgB;CAChB,MAAM,YAAY,SAAS;CAC3B,MAAM,gBAAgB,SAAS,iBAAiB;CAChD,MAAM,mBACJ,SAAS,oBAAoB,WAAW,OAAO,kBAAkB,SAAS;CAC5E,MAAM,mBAAmB,SAAS,oBAAoB,mBAAmB,MAAM;AAE/E,QAAO,MAAM,KAAK,MAAM,UAAU;AAChC,MAAI,CAAC,KAAM,QAAO;EAGlB,MAAM,UAAU,WAAW,MAAM,GADV,QAAQ,KAAK,IAAI,IAAI,OAAO,GAAG,QACT;EAC7C,MAAM,cAAc,CAAC,GAAG,SAAS,OAAO,QAAQ,CAAC;AAEjD,MAAK,KAAiC,SAAS,YAAY;GACzD,MAAM,eAAe;GACrB,MAAM,QAAQ,aAAa,aAAa;GACxC,MAAM,YAAY,OAAO,UAAU,WAAW,QAAQ,KAAA;GACtD,MAAM,WAAW,QAAQ,aAAa,OAAO;GAC7C,MAAM,YACJ,oBAAC,YAAY,uBAAb,EAAA,UACE,oBAAC,MAAD;IAAM,MAAM;IAAO,MAAM;IAAW,CAAA,EACF,CAAA;AAGtC,UACE,oBAAC,YAAY,cAAb;IACE,SAAS,aAAa;IACtB,WAAW,GAAG,OAAO,MAAM,YAAY,OAAO,OAAO;IACrD,cAAc,aAAa;IAC3B,gBAAgB,aAAa;IAC7B,UAAU,aAAa;IAEvB,OAAO;IACP,kBAAkB,YAAY,aAAa,kBAAkB,QAAQ;cAEpE,kBACC,cACA;KAAE;KAAW;KAAkB;KAAkB,EACjD,UACD;IACwB,EATpB,QASoB;;AAI/B,MAAK,KAA+B,SAAS,UAAU;GACrD,MAAM,aAAa;GACnB,MAAM,QAAQ,aAAa,WAAW;GACtC,MAAM,YAAY,OAAO,UAAU,WAAW,QAAQ,KAAA;GACtD,MAAM,WAAW,QAAQ,WAAW,OAAO;AAE3C,UACE,oBAAC,+BAAD;IACE,SAAS,WAAW;IACpB,cAAc,WAAW;IACzB,QAAQ;IACR,gBAAgB,WAAW;IAC3B,UAAU,WAAW;IAErB,OAAO;IACP,iBAAiB,WAAW;cAE3B,kBAAkB,YAAY;KAAE;KAAW;KAAkB,CAAC;IACjC,EALzB,QAKyB;;AAIpC,MAAK,KAAyB,SAAS,UACrC,QAAO,oBAAC,YAAY,WAAb,EAAuB,WAAW,OAAO,WAA2B,EAAX,QAAW;AAG7E,MAAK,KAA2B,SAAS,SAAS;GAChD,MAAM,QAAQ;GACd,MAAM,wBACJ,kBAAkB,UACd,MAAM,WACJ,WAAW,MAAM,SAAS,GAC1B,QACF;GACN,MAAM,wBAAwB,MAAM,WAAW,mBAAmB,MAAM,SAAS,GAAG;AACpF,UACE,qBAAC,YAAY,OAAb,EAAA,UAAA,CACG,MAAM,QACL,oBAAC,YAAY,YAAb;IAAwB,WAAW,OAAO;cACvC,MAAM;IACgB,CAAA,GACvB,MACH,MAAM,WACH,uBAAuB,MAAM,UAAU,aAAa;IAClD;IACA;IACA,kBAAkB;IAClB,kBAAkB;IACnB,CAAC,GACF,KACc,EAAA,EAdI,QAcJ;;AAIxB,MACG,KAAqB,SAAS,aAC9B,cAAc,QAAS,KAAqB,UAC7C;GACA,MAAM,UAAU;GAChB,MAAM,QAAQ,aAAa,QAAQ;GACnC,MAAM,YAAY,OAAO,UAAU,WAAW,QAAQ,KAAA;GACtD,MAAM,WAAW,YAAY,WAAW,QAAQ,QAAQ,OAAO;AAE/D,UACE,qBAAC,YAAY,aAAb,EAAA,UAAA,CACE,oBAAC,YAAY,gBAAb;IACE,WAAW,GAAG,OAAO,MAAM,YAAY,OAAO,OAAO;IACrD,UAAU,QAAQ;IAClB,OAAO;cAEN,kBAAkB,SAAS;KAC1B;KACA;KACA,SAAS;KACV,CAAC;IACyB,CAAA,EAC7B,oBAAC,YAAY,QAAb,EAAA,UACE,oBAAC,YAAY,YAAb;IACE,aAAa;IACb,WAAW,OAAO;IAClB,gBAAa;IACb,YAAY;IACZ,eAAe;cAEf,oBAAC,YAAY,OAAb;KAAmB,WAAW,OAAO;eAClC,QAAQ,YAAY,QAAQ,SAAS,SAAS,IAC7C,uBAAuB,QAAQ,UAAU,aAAa;MACpD;MACA;MACD,CAAC,GAEF,oBAAC,eAAD,EAAiB,CAAA;KAED,CAAA;IACG,CAAA,EACN,CAAA,CACG,EAAA,EAhCI,QAgCJ;;EAI9B,MAAM,WAAW;EACjB,MAAM,QAAQ,aAAa,SAAS;EACpC,MAAM,YAAY,OAAO,UAAU,WAAW,QAAQ,KAAA;EACtD,MAAM,WAAW,YAAY,YAAY,QAAQ,SAAS,OAAO;AAEjE,SACE,oBAAC,YAAY,MAAb;GACE,WAAW,GAAG,OAAO,MAAM,YAAY,OAAO,OAAO;GACrD,cAAc,SAAS;GACvB,UAAU,SAAS;GAEnB,OAAO;GACP,UAAU,UAAU,gBAAgB,UAAU,aAAa,MAAM;aAEhE,kBAAkB,UAAU;IAAE;IAAW;IAAkB,CAAC;GAC5C,EALZ,QAKY;GAErB"}
1
+ {"version":3,"file":"renderItems.mjs","names":["common"],"sources":["../../../src/base-ui/ContextMenu/renderItems.tsx"],"sourcesContent":["import { ContextMenu } from '@base-ui/react/context-menu';\nimport { Switch } from 'antd';\nimport { cx } from 'antd-style';\nimport { Check, ChevronRight } from 'lucide-react';\nimport { type MenuInfo } from 'rc-menu/es/interface';\nimport {\n type KeyboardEvent as ReactKeyboardEvent,\n type MouseEvent as ReactMouseEvent,\n type ReactNode,\n} from 'react';\nimport { memo, useCallback, useState } from 'react';\n\nimport common from '@/i18n/resources/en/common';\nimport { useTranslation } from '@/i18n/useTranslation';\nimport Icon from '@/Icon';\nimport {\n type BaseMenuItemGroupType,\n type BaseSubMenuType,\n getItemKey,\n getItemLabel,\n hasAnyIcon,\n hasCheckboxAndIcon,\n type MenuDividerType,\n type MenuItemType,\n renderIcon,\n type RenderItemContentOptions,\n type RenderOptions,\n} from '@/Menu';\nimport { styles } from '@/Menu/sharedStyle';\nimport { preventDefaultAndStopPropagation } from '@/utils/dom';\n\nimport {\n type ContextMenuCheckboxItem,\n type ContextMenuItem,\n type ContextMenuSwitchItem,\n} from './type';\n\nexport type { IconAlign, IconSpaceMode } from '@/Menu';\n\nconst EmptyMenuItem = memo(() => {\n const { t } = useTranslation(common);\n return (\n <ContextMenu.Item disabled className={cx(styles.item, styles.empty)}>\n <div className={styles.itemContent}>\n <span className={styles.label}>{t('common.empty')}</span>\n </div>\n </ContextMenu.Item>\n );\n});\n\nEmptyMenuItem.displayName = 'EmptyMenuItem';\n\ninterface ContextMenuSwitchItemInternalProps {\n checked?: boolean;\n children: ReactNode;\n closeOnClick?: boolean;\n danger?: boolean;\n defaultChecked?: boolean;\n disabled?: boolean;\n label?: string;\n onCheckedChange?: (checked: boolean) => void;\n}\n\nconst ContextMenuSwitchItemInternal = ({\n checked: checkedProp,\n children,\n closeOnClick = false,\n danger,\n defaultChecked,\n disabled,\n label,\n onCheckedChange,\n}: ContextMenuSwitchItemInternalProps) => {\n const [internalChecked, setInternalChecked] = useState(defaultChecked ?? false);\n const isControlled = checkedProp !== undefined;\n const checked = isControlled ? checkedProp : internalChecked;\n\n const handleCheckedChange = useCallback(\n (newChecked: boolean) => {\n if (!isControlled) {\n setInternalChecked(newChecked);\n }\n onCheckedChange?.(newChecked);\n },\n [isControlled, onCheckedChange],\n );\n\n return (\n <ContextMenu.Item\n className={cx(styles.item, danger && styles.danger)}\n closeOnClick={closeOnClick}\n disabled={disabled}\n label={label}\n onClick={(e) => {\n e.preventDefault();\n if (!disabled) {\n handleCheckedChange(!checked);\n }\n }}\n >\n {children}\n <span\n style={{ display: 'inline-flex', marginInlineStart: 16 }}\n onFocus={(e) => e.stopPropagation()}\n >\n <Switch\n checked={checked}\n disabled={disabled}\n size=\"small\"\n tabIndex={-1}\n onChange={handleCheckedChange}\n onClick={(_, e) => e.stopPropagation()}\n />\n </span>\n </ContextMenu.Item>\n );\n};\n\nconst renderItemContent = (\n item: MenuItemType | BaseSubMenuType | ContextMenuCheckboxItem | ContextMenuSwitchItem,\n options?: RenderItemContentOptions,\n iconNode?: ReactNode,\n) => {\n const label = getItemLabel(item);\n const desc = 'desc' in item ? item.desc : undefined;\n const extra = 'extra' in item ? item.extra : undefined;\n const indicatorOnRight = options?.indicatorOnRight;\n const alignStart = Boolean(desc) && options?.iconAlign === 'start';\n const hasCustomIcon = iconNode !== undefined && !indicatorOnRight;\n const hasIcon = hasCustomIcon ? Boolean(iconNode) : Boolean(item.icon);\n const shouldRenderIcon = hasCustomIcon\n ? Boolean(options?.reserveIconSpace || iconNode)\n : Boolean(hasIcon || options?.reserveIconSpace);\n\n const labelNode = desc ? (\n <div className={styles.labelGroup}>\n <span className={styles.label}>{label}</span>\n <span className={styles.desc}>{desc}</span>\n </div>\n ) : (\n <span className={styles.label}>{label}</span>\n );\n\n return (\n <div className={cx(styles.itemContent, alignStart && styles.itemContentAlignStart)}>\n {shouldRenderIcon ? (\n <span\n aria-hidden={!hasIcon}\n className={cx(styles.icon, alignStart && styles.iconAlignStart)}\n >\n {hasCustomIcon ? iconNode : hasIcon ? renderIcon(item.icon, 'small') : null}\n </span>\n ) : null}\n {labelNode}\n {extra ? <span className={styles.extra}>{extra}</span> : null}\n {indicatorOnRight && iconNode ? iconNode : null}\n {options?.submenu ? (\n <span className={styles.submenuArrow}>\n <ChevronRight size={16} />\n </span>\n ) : null}\n </div>\n );\n};\n\nconst invokeItemClick = (\n item: MenuItemType,\n keyPath: string[],\n event: ReactMouseEvent<HTMLElement> | ReactKeyboardEvent<HTMLElement>,\n) => {\n if (!item.onClick) return;\n const key = item.key ?? keyPath.at(-1) ?? '';\n const info: MenuInfo = {\n domEvent: event,\n item: event.currentTarget as MenuInfo['item'],\n key: String(key),\n keyPath,\n };\n item.onClick(info);\n};\n\nexport const renderContextMenuItems = (\n items: ContextMenuItem[],\n keyPath: string[] = [],\n options?: RenderOptions,\n): ReactNode[] => {\n const iconAlign = options?.iconAlign;\n const iconSpaceMode = options?.iconSpaceMode ?? 'global';\n const reserveIconSpace =\n options?.reserveIconSpace ?? hasAnyIcon(items, iconSpaceMode === 'global');\n const indicatorOnRight = options?.indicatorOnRight ?? hasCheckboxAndIcon(items);\n\n return items.map((item, index) => {\n if (!item) return null;\n\n const fallbackKey = `${keyPath.join('-') || 'root'}-${index}`;\n const itemKey = getItemKey(item, fallbackKey);\n const nextKeyPath = [...keyPath, String(itemKey)];\n\n if ((item as ContextMenuCheckboxItem).type === 'checkbox') {\n const checkboxItem = item as ContextMenuCheckboxItem;\n const label = getItemLabel(checkboxItem);\n const labelText = typeof label === 'string' ? label : undefined;\n const isDanger = Boolean(checkboxItem.danger);\n const indicator = (\n <ContextMenu.CheckboxItemIndicator>\n <Icon icon={Check} size={'small'} />\n </ContextMenu.CheckboxItemIndicator>\n );\n\n return (\n <ContextMenu.CheckboxItem\n checked={checkboxItem.checked}\n className={cx(styles.item, isDanger && styles.danger)}\n closeOnClick={checkboxItem.closeOnClick}\n defaultChecked={checkboxItem.defaultChecked}\n disabled={checkboxItem.disabled}\n key={itemKey}\n label={labelText}\n onCheckedChange={(checked) => checkboxItem.onCheckedChange?.(checked)}\n >\n {renderItemContent(\n checkboxItem,\n { iconAlign, indicatorOnRight, reserveIconSpace },\n indicator,\n )}\n </ContextMenu.CheckboxItem>\n );\n }\n\n if ((item as ContextMenuSwitchItem).type === 'switch') {\n const switchItem = item as ContextMenuSwitchItem;\n const label = getItemLabel(switchItem);\n const labelText = typeof label === 'string' ? label : undefined;\n const isDanger = Boolean(switchItem.danger);\n\n return (\n <ContextMenuSwitchItemInternal\n checked={switchItem.checked}\n closeOnClick={switchItem.closeOnClick}\n danger={isDanger}\n defaultChecked={switchItem.defaultChecked}\n disabled={switchItem.disabled}\n key={itemKey}\n label={labelText}\n onCheckedChange={switchItem.onCheckedChange}\n >\n {renderItemContent(switchItem, { iconAlign, reserveIconSpace })}\n </ContextMenuSwitchItemInternal>\n );\n }\n\n if ((item as MenuDividerType).type === 'divider') {\n return <ContextMenu.Separator className={styles.separator} key={itemKey} />;\n }\n\n if ((item as BaseMenuItemGroupType).type === 'group') {\n const group = item as BaseMenuItemGroupType;\n const groupReserveIconSpace =\n iconSpaceMode === 'group'\n ? group.children\n ? hasAnyIcon(group.children)\n : false\n : reserveIconSpace;\n const groupIndicatorOnRight = group.children ? hasCheckboxAndIcon(group.children) : false;\n return (\n <ContextMenu.Group key={itemKey}>\n {group.label ? (\n <ContextMenu.GroupLabel className={styles.groupLabel}>\n {group.label}\n </ContextMenu.GroupLabel>\n ) : null}\n {group.children\n ? renderContextMenuItems(group.children, nextKeyPath, {\n iconAlign,\n iconSpaceMode,\n indicatorOnRight: groupIndicatorOnRight,\n reserveIconSpace: groupReserveIconSpace,\n })\n : null}\n </ContextMenu.Group>\n );\n }\n\n if (\n (item as BaseSubMenuType).type === 'submenu' ||\n ('children' in item && (item as BaseSubMenuType).children)\n ) {\n const submenu = item as BaseSubMenuType;\n const label = getItemLabel(submenu);\n const labelText = typeof label === 'string' ? label : undefined;\n const isDanger = 'danger' in submenu && Boolean(submenu.danger);\n\n return (\n <ContextMenu.SubmenuRoot\n defaultOpen={submenu.defaultOpen}\n key={itemKey}\n open={submenu.open}\n onOpenChange={submenu.onOpenChange}\n >\n <ContextMenu.SubmenuTrigger\n {...submenu.triggerProps}\n className={cx(styles.item, isDanger && styles.danger)}\n closeDelay={submenu.closeDelay}\n delay={submenu.delay}\n disabled={submenu.disabled}\n label={labelText}\n openOnHover={submenu.openOnHover}\n onClick={submenu.onClick}\n >\n {renderItemContent(submenu, {\n iconAlign,\n reserveIconSpace,\n submenu: true,\n })}\n </ContextMenu.SubmenuTrigger>\n <ContextMenu.Portal>\n <ContextMenu.Positioner\n alignOffset={-4}\n className={styles.positioner}\n data-submenu=\"\"\n sideOffset={-1}\n onContextMenu={preventDefaultAndStopPropagation}\n >\n <ContextMenu.Popup className={styles.popup}>\n {submenu.children && submenu.children.length > 0 ? (\n renderContextMenuItems(submenu.children, nextKeyPath, {\n iconAlign,\n iconSpaceMode,\n })\n ) : (\n <EmptyMenuItem />\n )}\n </ContextMenu.Popup>\n </ContextMenu.Positioner>\n </ContextMenu.Portal>\n </ContextMenu.SubmenuRoot>\n );\n }\n\n const menuItem = item as MenuItemType;\n const label = getItemLabel(menuItem);\n const labelText = typeof label === 'string' ? label : undefined;\n const isDanger = 'danger' in menuItem && Boolean(menuItem.danger);\n\n return (\n <ContextMenu.Item\n className={cx(styles.item, isDanger && styles.danger)}\n closeOnClick={menuItem.closeOnClick}\n disabled={menuItem.disabled}\n key={itemKey}\n label={labelText}\n onClick={(event) => invokeItemClick(menuItem, nextKeyPath, event)}\n >\n {renderItemContent(menuItem, { iconAlign, reserveIconSpace })}\n </ContextMenu.Item>\n );\n });\n};\n"],"mappings":"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"}
@@ -105,24 +105,35 @@ const renderDropdownMenuItems = (items, keyPath = [], options) => {
105
105
  const submenu = item;
106
106
  const label = getItemLabel(submenu);
107
107
  const labelText = typeof label === "string" ? label : void 0;
108
- return /* @__PURE__ */ jsxs(DropdownMenuSubmenuRoot, { children: [/* @__PURE__ */ jsx(DropdownMenuSubmenuTrigger, {
109
- danger: "danger" in submenu && Boolean(submenu.danger),
110
- disabled: submenu.disabled,
111
- label: labelText,
112
- children: renderItemContent(submenu, {
113
- iconAlign,
114
- reserveIconSpace,
115
- submenu: true
116
- })
117
- }), /* @__PURE__ */ jsx(DropdownMenuPortal, { children: /* @__PURE__ */ jsx(DropdownMenuPositioner, {
118
- alignOffset: -4,
119
- "data-submenu": "",
120
- sideOffset: -1,
121
- children: /* @__PURE__ */ jsx(DropdownMenuPopup, { children: submenu.children ? renderDropdownMenuItems(submenu.children, nextKeyPath, {
122
- iconAlign,
123
- iconSpaceMode
124
- }) : null })
125
- }) })] }, itemKey);
108
+ const isDanger = "danger" in submenu && Boolean(submenu.danger);
109
+ return /* @__PURE__ */ jsxs(DropdownMenuSubmenuRoot, {
110
+ defaultOpen: submenu.defaultOpen,
111
+ open: submenu.open,
112
+ onOpenChange: submenu.onOpenChange,
113
+ children: [/* @__PURE__ */ jsx(DropdownMenuSubmenuTrigger, {
114
+ ...submenu.triggerProps,
115
+ closeDelay: submenu.closeDelay,
116
+ danger: isDanger,
117
+ delay: submenu.delay,
118
+ disabled: submenu.disabled,
119
+ label: labelText,
120
+ openOnHover: submenu.openOnHover,
121
+ onClick: submenu.onClick,
122
+ children: renderItemContent(submenu, {
123
+ iconAlign,
124
+ reserveIconSpace,
125
+ submenu: true
126
+ })
127
+ }), /* @__PURE__ */ jsx(DropdownMenuPortal, { children: /* @__PURE__ */ jsx(DropdownMenuPositioner, {
128
+ alignOffset: -4,
129
+ "data-submenu": "",
130
+ sideOffset: -1,
131
+ children: /* @__PURE__ */ jsx(DropdownMenuPopup, { children: submenu.children ? renderDropdownMenuItems(submenu.children, nextKeyPath, {
132
+ iconAlign,
133
+ iconSpaceMode
134
+ }) : null })
135
+ }) })]
136
+ }, itemKey);
126
137
  }
127
138
  const menuItem = item;
128
139
  const label = getItemLabel(menuItem);
@@ -1 +1 @@
1
- {"version":3,"file":"renderItems.mjs","names":[],"sources":["../../../src/base-ui/DropdownMenu/renderItems.tsx"],"sourcesContent":["import { Check, ChevronRight } from 'lucide-react';\nimport { type MenuInfo } from 'rc-menu/es/interface';\nimport {\n type KeyboardEvent as ReactKeyboardEvent,\n type MouseEvent as ReactMouseEvent,\n type ReactNode,\n} from 'react';\n\nimport {\n getItemKey,\n getItemLabel,\n hasAnyIcon,\n hasCheckboxAndIcon,\n type MenuDividerType,\n type MenuItemGroupType,\n type MenuItemType,\n renderIcon,\n type RenderItemContentOptions,\n type RenderOptions,\n type SubMenuType,\n} from '@/Menu';\nimport { styles } from '@/Menu/sharedStyle';\n\nimport {\n DropdownMenuCheckboxItemIndicator,\n DropdownMenuCheckboxItemPrimitive,\n DropdownMenuGroup,\n DropdownMenuGroupLabel,\n DropdownMenuItem,\n DropdownMenuItemContent,\n DropdownMenuItemDesc,\n DropdownMenuItemExtra,\n DropdownMenuItemIcon,\n DropdownMenuItemLabel,\n DropdownMenuItemLabelGroup,\n DropdownMenuPopup,\n DropdownMenuPortal,\n DropdownMenuPositioner,\n DropdownMenuSeparator,\n DropdownMenuSubmenuArrow,\n DropdownMenuSubmenuRoot,\n DropdownMenuSubmenuTrigger,\n DropdownMenuSwitchItem,\n} from './atoms';\nimport {\n type DropdownItem,\n type DropdownMenuCheckboxItem as DropdownMenuCheckboxItemType,\n type DropdownMenuSwitchItem as DropdownMenuSwitchItemType,\n} from './type';\n\nexport type { IconAlign, IconSpaceMode } from '@/Menu';\n\nconst renderItemContent = (\n item: MenuItemType | SubMenuType | DropdownMenuCheckboxItemType | DropdownMenuSwitchItemType,\n options?: RenderItemContentOptions,\n iconNode?: ReactNode,\n) => {\n const label = getItemLabel(item);\n const desc = 'desc' in item ? item.desc : undefined;\n const extra = 'extra' in item ? item.extra : undefined;\n const indicatorOnRight = options?.indicatorOnRight;\n const alignStart = Boolean(desc) && options?.iconAlign === 'start';\n\n const hasCustomIcon = iconNode !== undefined && !indicatorOnRight;\n const hasIcon = hasCustomIcon ? Boolean(iconNode) : Boolean(item.icon);\n const shouldRenderIcon = hasCustomIcon\n ? Boolean(options?.reserveIconSpace || iconNode)\n : Boolean(hasIcon || options?.reserveIconSpace);\n\n const labelNode = desc ? (\n <DropdownMenuItemLabelGroup>\n <DropdownMenuItemLabel>{label}</DropdownMenuItemLabel>\n <DropdownMenuItemDesc>{desc}</DropdownMenuItemDesc>\n </DropdownMenuItemLabelGroup>\n ) : (\n <DropdownMenuItemLabel>{label}</DropdownMenuItemLabel>\n );\n\n return (\n <DropdownMenuItemContent className={alignStart ? styles.itemContentAlignStart : undefined}>\n {shouldRenderIcon ? (\n <DropdownMenuItemIcon\n aria-hidden={!hasIcon}\n className={alignStart ? styles.iconAlignStart : undefined}\n >\n {hasCustomIcon ? iconNode : hasIcon ? renderIcon(item.icon) : null}\n </DropdownMenuItemIcon>\n ) : null}\n {labelNode}\n {extra ? <DropdownMenuItemExtra>{extra}</DropdownMenuItemExtra> : null}\n {indicatorOnRight && iconNode ? iconNode : null}\n {options?.submenu ? (\n <DropdownMenuSubmenuArrow>\n <ChevronRight size={16} />\n </DropdownMenuSubmenuArrow>\n ) : null}\n </DropdownMenuItemContent>\n );\n};\n\nconst invokeItemClick = (\n item: MenuItemType,\n keyPath: string[],\n event: ReactMouseEvent<HTMLElement> | ReactKeyboardEvent<HTMLElement>,\n) => {\n if (!item.onClick) return;\n const key = item.key ?? keyPath.at(-1) ?? '';\n const info: MenuInfo = {\n domEvent: event,\n item: event.currentTarget as MenuInfo['item'],\n key: String(key),\n keyPath,\n };\n item.onClick(info);\n};\n\nexport const renderDropdownMenuItems = (\n items: DropdownItem[],\n keyPath: string[] = [],\n options?: RenderOptions,\n): ReactNode[] => {\n const iconAlign = options?.iconAlign;\n const iconSpaceMode = options?.iconSpaceMode ?? 'global';\n const reserveIconSpace =\n options?.reserveIconSpace ?? hasAnyIcon(items, iconSpaceMode === 'global');\n const indicatorOnRight = options?.indicatorOnRight ?? hasCheckboxAndIcon(items);\n\n return items.map((item, index) => {\n if (!item) return null;\n\n const fallbackKey = `${keyPath.join('-') || 'root'}-${index}`;\n const itemKey = getItemKey(item, fallbackKey);\n const nextKeyPath = [...keyPath, String(itemKey)];\n\n if ((item as DropdownMenuCheckboxItemType).type === 'checkbox') {\n const checkboxItem = item as DropdownMenuCheckboxItemType;\n const label = getItemLabel(checkboxItem);\n const labelText = typeof label === 'string' ? label : undefined;\n const isDanger = Boolean(checkboxItem.danger);\n const indicator = (\n <DropdownMenuCheckboxItemIndicator>{renderIcon(Check)}</DropdownMenuCheckboxItemIndicator>\n );\n\n return (\n <DropdownMenuCheckboxItemPrimitive\n checked={checkboxItem.checked}\n closeOnClick={checkboxItem.closeOnClick}\n danger={isDanger}\n defaultChecked={checkboxItem.defaultChecked}\n disabled={checkboxItem.disabled}\n key={itemKey}\n label={labelText}\n onCheckedChange={(checked) => checkboxItem.onCheckedChange?.(checked)}\n >\n {renderItemContent(\n checkboxItem,\n { iconAlign, indicatorOnRight, reserveIconSpace },\n indicator,\n )}\n </DropdownMenuCheckboxItemPrimitive>\n );\n }\n\n if ((item as DropdownMenuSwitchItemType).type === 'switch') {\n const switchItem = item as DropdownMenuSwitchItemType;\n const label = getItemLabel(switchItem);\n const labelText = typeof label === 'string' ? label : undefined;\n const isDanger = Boolean(switchItem.danger);\n\n return (\n <DropdownMenuSwitchItem\n checked={switchItem.checked}\n closeOnClick={switchItem.closeOnClick}\n danger={isDanger}\n defaultChecked={switchItem.defaultChecked}\n disabled={switchItem.disabled}\n key={itemKey}\n label={labelText}\n onCheckedChange={(checked) => switchItem.onCheckedChange?.(checked)}\n >\n {renderItemContent(switchItem, { iconAlign, reserveIconSpace })}\n </DropdownMenuSwitchItem>\n );\n }\n\n if ((item as MenuDividerType).type === 'divider') {\n return <DropdownMenuSeparator key={itemKey} />;\n }\n\n if ((item as MenuItemGroupType).type === 'group') {\n const group = item as MenuItemGroupType;\n const groupReserveIconSpace =\n iconSpaceMode === 'group'\n ? group.children\n ? hasAnyIcon(group.children)\n : false\n : reserveIconSpace;\n const groupIndicatorOnRight = group.children ? hasCheckboxAndIcon(group.children) : false;\n return (\n <DropdownMenuGroup key={itemKey}>\n {group.label ? <DropdownMenuGroupLabel>{group.label}</DropdownMenuGroupLabel> : null}\n {group.children\n ? renderDropdownMenuItems(group.children, nextKeyPath, {\n iconAlign,\n iconSpaceMode,\n indicatorOnRight: groupIndicatorOnRight,\n reserveIconSpace: groupReserveIconSpace,\n })\n : null}\n </DropdownMenuGroup>\n );\n }\n\n if ((item as SubMenuType).type === 'submenu' || 'children' in item) {\n const submenu = item as SubMenuType;\n const label = getItemLabel(submenu);\n const labelText = typeof label === 'string' ? label : undefined;\n const isDanger = 'danger' in submenu && Boolean(submenu.danger);\n\n return (\n <DropdownMenuSubmenuRoot key={itemKey}>\n <DropdownMenuSubmenuTrigger\n danger={isDanger}\n disabled={submenu.disabled}\n label={labelText}\n >\n {renderItemContent(submenu, {\n iconAlign,\n reserveIconSpace,\n submenu: true,\n })}\n </DropdownMenuSubmenuTrigger>\n <DropdownMenuPortal>\n <DropdownMenuPositioner alignOffset={-4} data-submenu=\"\" sideOffset={-1}>\n <DropdownMenuPopup>\n {submenu.children\n ? renderDropdownMenuItems(submenu.children, nextKeyPath, {\n iconAlign,\n iconSpaceMode,\n })\n : null}\n </DropdownMenuPopup>\n </DropdownMenuPositioner>\n </DropdownMenuPortal>\n </DropdownMenuSubmenuRoot>\n );\n }\n\n const menuItem = item as MenuItemType;\n const label = getItemLabel(menuItem);\n const labelText = typeof label === 'string' ? label : undefined;\n const isDanger = 'danger' in menuItem && Boolean(menuItem.danger);\n\n return (\n <DropdownMenuItem\n closeOnClick={menuItem.closeOnClick}\n danger={isDanger}\n disabled={menuItem.disabled}\n key={itemKey}\n label={labelText}\n onClick={(event) => invokeItemClick(menuItem, nextKeyPath, event)}\n >\n {renderItemContent(menuItem, { iconAlign, reserveIconSpace })}\n </DropdownMenuItem>\n );\n });\n};\n"],"mappings":"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"}
1
+ {"version":3,"file":"renderItems.mjs","names":[],"sources":["../../../src/base-ui/DropdownMenu/renderItems.tsx"],"sourcesContent":["import { Check, ChevronRight } from 'lucide-react';\nimport { type MenuInfo } from 'rc-menu/es/interface';\nimport {\n type KeyboardEvent as ReactKeyboardEvent,\n type MouseEvent as ReactMouseEvent,\n type ReactNode,\n} from 'react';\n\nimport {\n type BaseMenuItemGroupType,\n type BaseSubMenuType,\n getItemKey,\n getItemLabel,\n hasAnyIcon,\n hasCheckboxAndIcon,\n type MenuDividerType,\n type MenuItemType,\n renderIcon,\n type RenderItemContentOptions,\n type RenderOptions,\n} from '@/Menu';\nimport { styles } from '@/Menu/sharedStyle';\n\nimport {\n DropdownMenuCheckboxItemIndicator,\n DropdownMenuCheckboxItemPrimitive,\n DropdownMenuGroup,\n DropdownMenuGroupLabel,\n DropdownMenuItem,\n DropdownMenuItemContent,\n DropdownMenuItemDesc,\n DropdownMenuItemExtra,\n DropdownMenuItemIcon,\n DropdownMenuItemLabel,\n DropdownMenuItemLabelGroup,\n DropdownMenuPopup,\n DropdownMenuPortal,\n DropdownMenuPositioner,\n DropdownMenuSeparator,\n DropdownMenuSubmenuArrow,\n DropdownMenuSubmenuRoot,\n DropdownMenuSubmenuTrigger,\n DropdownMenuSwitchItem,\n} from './atoms';\nimport {\n type DropdownItem,\n type DropdownMenuCheckboxItem as DropdownMenuCheckboxItemType,\n type DropdownMenuSwitchItem as DropdownMenuSwitchItemType,\n} from './type';\n\nexport type { IconAlign, IconSpaceMode } from '@/Menu';\n\nconst renderItemContent = (\n item: MenuItemType | BaseSubMenuType | DropdownMenuCheckboxItemType | DropdownMenuSwitchItemType,\n options?: RenderItemContentOptions,\n iconNode?: ReactNode,\n) => {\n const label = getItemLabel(item);\n const desc = 'desc' in item ? item.desc : undefined;\n const extra = 'extra' in item ? item.extra : undefined;\n const indicatorOnRight = options?.indicatorOnRight;\n const alignStart = Boolean(desc) && options?.iconAlign === 'start';\n\n const hasCustomIcon = iconNode !== undefined && !indicatorOnRight;\n const hasIcon = hasCustomIcon ? Boolean(iconNode) : Boolean(item.icon);\n const shouldRenderIcon = hasCustomIcon\n ? Boolean(options?.reserveIconSpace || iconNode)\n : Boolean(hasIcon || options?.reserveIconSpace);\n\n const labelNode = desc ? (\n <DropdownMenuItemLabelGroup>\n <DropdownMenuItemLabel>{label}</DropdownMenuItemLabel>\n <DropdownMenuItemDesc>{desc}</DropdownMenuItemDesc>\n </DropdownMenuItemLabelGroup>\n ) : (\n <DropdownMenuItemLabel>{label}</DropdownMenuItemLabel>\n );\n\n return (\n <DropdownMenuItemContent className={alignStart ? styles.itemContentAlignStart : undefined}>\n {shouldRenderIcon ? (\n <DropdownMenuItemIcon\n aria-hidden={!hasIcon}\n className={alignStart ? styles.iconAlignStart : undefined}\n >\n {hasCustomIcon ? iconNode : hasIcon ? renderIcon(item.icon) : null}\n </DropdownMenuItemIcon>\n ) : null}\n {labelNode}\n {extra ? <DropdownMenuItemExtra>{extra}</DropdownMenuItemExtra> : null}\n {indicatorOnRight && iconNode ? iconNode : null}\n {options?.submenu ? (\n <DropdownMenuSubmenuArrow>\n <ChevronRight size={16} />\n </DropdownMenuSubmenuArrow>\n ) : null}\n </DropdownMenuItemContent>\n );\n};\n\nconst invokeItemClick = (\n item: MenuItemType,\n keyPath: string[],\n event: ReactMouseEvent<HTMLElement> | ReactKeyboardEvent<HTMLElement>,\n) => {\n if (!item.onClick) return;\n const key = item.key ?? keyPath.at(-1) ?? '';\n const info: MenuInfo = {\n domEvent: event,\n item: event.currentTarget as MenuInfo['item'],\n key: String(key),\n keyPath,\n };\n item.onClick(info);\n};\n\nexport const renderDropdownMenuItems = (\n items: DropdownItem[],\n keyPath: string[] = [],\n options?: RenderOptions,\n): ReactNode[] => {\n const iconAlign = options?.iconAlign;\n const iconSpaceMode = options?.iconSpaceMode ?? 'global';\n const reserveIconSpace =\n options?.reserveIconSpace ?? hasAnyIcon(items, iconSpaceMode === 'global');\n const indicatorOnRight = options?.indicatorOnRight ?? hasCheckboxAndIcon(items);\n\n return items.map((item, index) => {\n if (!item) return null;\n\n const fallbackKey = `${keyPath.join('-') || 'root'}-${index}`;\n const itemKey = getItemKey(item, fallbackKey);\n const nextKeyPath = [...keyPath, String(itemKey)];\n\n if ((item as DropdownMenuCheckboxItemType).type === 'checkbox') {\n const checkboxItem = item as DropdownMenuCheckboxItemType;\n const label = getItemLabel(checkboxItem);\n const labelText = typeof label === 'string' ? label : undefined;\n const isDanger = Boolean(checkboxItem.danger);\n const indicator = (\n <DropdownMenuCheckboxItemIndicator>{renderIcon(Check)}</DropdownMenuCheckboxItemIndicator>\n );\n\n return (\n <DropdownMenuCheckboxItemPrimitive\n checked={checkboxItem.checked}\n closeOnClick={checkboxItem.closeOnClick}\n danger={isDanger}\n defaultChecked={checkboxItem.defaultChecked}\n disabled={checkboxItem.disabled}\n key={itemKey}\n label={labelText}\n onCheckedChange={(checked) => checkboxItem.onCheckedChange?.(checked)}\n >\n {renderItemContent(\n checkboxItem,\n { iconAlign, indicatorOnRight, reserveIconSpace },\n indicator,\n )}\n </DropdownMenuCheckboxItemPrimitive>\n );\n }\n\n if ((item as DropdownMenuSwitchItemType).type === 'switch') {\n const switchItem = item as DropdownMenuSwitchItemType;\n const label = getItemLabel(switchItem);\n const labelText = typeof label === 'string' ? label : undefined;\n const isDanger = Boolean(switchItem.danger);\n\n return (\n <DropdownMenuSwitchItem\n checked={switchItem.checked}\n closeOnClick={switchItem.closeOnClick}\n danger={isDanger}\n defaultChecked={switchItem.defaultChecked}\n disabled={switchItem.disabled}\n key={itemKey}\n label={labelText}\n onCheckedChange={(checked) => switchItem.onCheckedChange?.(checked)}\n >\n {renderItemContent(switchItem, { iconAlign, reserveIconSpace })}\n </DropdownMenuSwitchItem>\n );\n }\n\n if ((item as MenuDividerType).type === 'divider') {\n return <DropdownMenuSeparator key={itemKey} />;\n }\n\n if ((item as BaseMenuItemGroupType).type === 'group') {\n const group = item as BaseMenuItemGroupType;\n const groupReserveIconSpace =\n iconSpaceMode === 'group'\n ? group.children\n ? hasAnyIcon(group.children)\n : false\n : reserveIconSpace;\n const groupIndicatorOnRight = group.children ? hasCheckboxAndIcon(group.children) : false;\n return (\n <DropdownMenuGroup key={itemKey}>\n {group.label ? <DropdownMenuGroupLabel>{group.label}</DropdownMenuGroupLabel> : null}\n {group.children\n ? renderDropdownMenuItems(group.children, nextKeyPath, {\n iconAlign,\n iconSpaceMode,\n indicatorOnRight: groupIndicatorOnRight,\n reserveIconSpace: groupReserveIconSpace,\n })\n : null}\n </DropdownMenuGroup>\n );\n }\n\n if ((item as BaseSubMenuType).type === 'submenu' || 'children' in item) {\n const submenu = item as BaseSubMenuType;\n const label = getItemLabel(submenu);\n const labelText = typeof label === 'string' ? label : undefined;\n const isDanger = 'danger' in submenu && Boolean(submenu.danger);\n\n return (\n <DropdownMenuSubmenuRoot\n defaultOpen={submenu.defaultOpen}\n key={itemKey}\n open={submenu.open}\n onOpenChange={submenu.onOpenChange}\n >\n <DropdownMenuSubmenuTrigger\n {...submenu.triggerProps}\n closeDelay={submenu.closeDelay}\n danger={isDanger}\n delay={submenu.delay}\n disabled={submenu.disabled}\n label={labelText}\n openOnHover={submenu.openOnHover}\n onClick={submenu.onClick}\n >\n {renderItemContent(submenu, {\n iconAlign,\n reserveIconSpace,\n submenu: true,\n })}\n </DropdownMenuSubmenuTrigger>\n <DropdownMenuPortal>\n <DropdownMenuPositioner alignOffset={-4} data-submenu=\"\" sideOffset={-1}>\n <DropdownMenuPopup>\n {submenu.children\n ? renderDropdownMenuItems(submenu.children, nextKeyPath, {\n iconAlign,\n iconSpaceMode,\n })\n : null}\n </DropdownMenuPopup>\n </DropdownMenuPositioner>\n </DropdownMenuPortal>\n </DropdownMenuSubmenuRoot>\n );\n }\n\n const menuItem = item as MenuItemType;\n const label = getItemLabel(menuItem);\n const labelText = typeof label === 'string' ? label : undefined;\n const isDanger = 'danger' in menuItem && Boolean(menuItem.danger);\n\n return (\n <DropdownMenuItem\n closeOnClick={menuItem.closeOnClick}\n danger={isDanger}\n disabled={menuItem.disabled}\n key={itemKey}\n label={labelText}\n onClick={(event) => invokeItemClick(menuItem, nextKeyPath, event)}\n >\n {renderItemContent(menuItem, { iconAlign, reserveIconSpace })}\n </DropdownMenuItem>\n );\n });\n};\n"],"mappings":"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"}