@lobehub/ui 5.43.0 → 5.44.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.
Files changed (47) hide show
  1. package/es/GlobalFocusRing/index.mjs +11 -1
  2. package/es/GlobalFocusRing/index.mjs.map +1 -1
  3. package/es/base-ui/ContextMenu/ContextMenuHost.mjs +5 -1
  4. package/es/base-ui/ContextMenu/ContextMenuHost.mjs.map +1 -1
  5. package/es/base-ui/ContextMenu/ContextMenuTrigger.d.mts +3 -1
  6. package/es/base-ui/ContextMenu/ContextMenuTrigger.mjs +7 -3
  7. package/es/base-ui/ContextMenu/ContextMenuTrigger.mjs.map +1 -1
  8. package/es/base-ui/ContextMenu/store.d.mts +3 -1
  9. package/es/base-ui/ContextMenu/store.mjs +6 -2
  10. package/es/base-ui/ContextMenu/store.mjs.map +1 -1
  11. package/es/base-ui/DropdownMenu/DropdownMenu.mjs +6 -2
  12. package/es/base-ui/DropdownMenu/DropdownMenu.mjs.map +1 -1
  13. package/es/base-ui/DropdownMenu/atoms.d.mts +4 -2
  14. package/es/base-ui/DropdownMenu/atoms.mjs +17 -5
  15. package/es/base-ui/DropdownMenu/atoms.mjs.map +1 -1
  16. package/es/base-ui/DropdownMenu/sharedStyle.mjs +26 -3
  17. package/es/base-ui/DropdownMenu/sharedStyle.mjs.map +1 -1
  18. package/es/base-ui/DropdownMenu/type.d.mts +3 -1
  19. package/es/base-ui/ScrollArea/atoms.mjs +4 -4
  20. package/es/base-ui/ScrollArea/atoms.mjs.map +1 -1
  21. package/es/base-ui/Select/Select.mjs +1 -3
  22. package/es/base-ui/Select/Select.mjs.map +1 -1
  23. package/es/base-ui/Select/hooks.mjs +1 -40
  24. package/es/base-ui/Select/hooks.mjs.map +1 -1
  25. package/es/base-ui/Select/parts.mjs +20 -18
  26. package/es/base-ui/Select/parts.mjs.map +1 -1
  27. package/es/base-ui/Select/renderOptions.mjs +1 -2
  28. package/es/base-ui/Select/renderOptions.mjs.map +1 -1
  29. package/es/base-ui/Select/style.mjs +2 -4
  30. package/es/base-ui/Select/style.mjs.map +1 -1
  31. package/es/base-ui/Select/type.d.mts +3 -3
  32. package/es/base-ui/index.d.mts +4 -2
  33. package/es/base-ui/index.mjs +1 -1
  34. package/es/base-ui/virtual/MenuVirtualList.d.mts +3 -0
  35. package/es/base-ui/virtual/MenuVirtualList.mjs +28 -0
  36. package/es/base-ui/virtual/MenuVirtualList.mjs.map +1 -0
  37. package/es/base-ui/virtual/VirtualScrollArea.d.mts +3 -0
  38. package/es/base-ui/virtual/VirtualScrollArea.mjs +82 -0
  39. package/es/base-ui/virtual/VirtualScrollArea.mjs.map +1 -0
  40. package/es/base-ui/virtual/index.d.mts +5 -0
  41. package/es/base-ui/virtual/type.d.mts +26 -0
  42. package/es/base-ui/virtual/useMenuVirtualList.d.mts +3 -0
  43. package/es/base-ui/virtual/useMenuVirtualList.mjs +256 -0
  44. package/es/base-ui/virtual/useMenuVirtualList.mjs.map +1 -0
  45. package/es/index.d.mts +1 -1
  46. package/es/index.mjs +1 -1
  47. package/package.json +1 -1
@@ -38,7 +38,17 @@ const installGlobalFocusRing = (doc = document) => {
38
38
  const next = doc.activeElement;
39
39
  if (next === target && next?.matches(":focus-visible") && next.isConnected) return;
40
40
  clear();
41
- if (!next || next === doc.body || next.namespaceURI !== "http://www.w3.org/1999/xhtml" || next.shadowRoot || !next.matches(":focus-visible") || next.getClientRects().length !== 1) return;
41
+ if (!next || next === doc.body || next.namespaceURI !== "http://www.w3.org/1999/xhtml" || next.shadowRoot || next.closest("[data-lobe-focus-ring=\"off\"]") || next.matches("textarea") || next.isContentEditable || next.matches("input") && ![
42
+ "button",
43
+ "submit",
44
+ "reset",
45
+ "image",
46
+ "checkbox",
47
+ "radio",
48
+ "range",
49
+ "color",
50
+ "file"
51
+ ].includes(next.type) || !next.matches(":focus-visible") || next.getClientRects().length !== 1) return;
42
52
  const element = next;
43
53
  const computed = win.getComputedStyle(element);
44
54
  const rect = element.getBoundingClientRect();
@@ -1 +1 @@
1
- {"version":3,"file":"index.mjs","names":[],"sources":["../../src/GlobalFocusRing/index.ts"],"sourcesContent":["import { globalFocusRingCSS } from './style';\n\nconst installations = new WeakMap<Document, { dispose: () => void; users: number }>();\n\n/** Install once per document. The returned cleanup is safe for nested providers and Strict Mode. */\nexport const installGlobalFocusRing = (doc: Document = document): (() => void) => {\n const existing = installations.get(doc);\n if (existing) {\n existing.users += 1;\n let released = false;\n return () => {\n if (released) return;\n released = true;\n if (--existing.users === 0) existing.dispose();\n };\n }\n\n const win = doc.defaultView;\n if (\n !win ||\n !doc.body ||\n !win.CSS?.supports('top', 'anchor(top)') ||\n !win.CSS.supports('position-visibility', 'anchors-visible') ||\n !('showPopover' in doc.createElement('div'))\n )\n return () => {};\n\n const sheet = doc.createElement('style');\n sheet.textContent = globalFocusRingCSS;\n const ring = doc.createElement('div');\n ring.setAttribute('data-lobe-global-focus-ring', '');\n ring.setAttribute('aria-hidden', 'true');\n ring.setAttribute('popover', 'manual');\n doc.head.append(sheet);\n doc.body.append(ring);\n\n let target: HTMLElement | undefined;\n let restoreTarget: (() => void) | undefined;\n let frame = 0;\n let disposed = false;\n\n const clear = () => {\n if (ring.matches(':popover-open')) ring.hidePopover();\n restoreTarget?.();\n restoreTarget = undefined;\n target = undefined;\n };\n\n const sync = () => {\n if (disposed) return;\n const next = doc.activeElement;\n if (next === target && next?.matches(':focus-visible') && next.isConnected) return;\n clear();\n // Shadow roots and fragmented inline text retain their own focus treatment.\n if (\n !next ||\n next === doc.body ||\n next.namespaceURI !== 'http://www.w3.org/1999/xhtml' ||\n next.shadowRoot ||\n !next.matches(':focus-visible') ||\n next.getClientRects().length !== 1\n )\n return;\n\n const element = next as HTMLElement;\n const computed = win.getComputedStyle(element);\n const rect = element.getBoundingClientRect();\n if (!rect.width || !rect.height || computed.visibility !== 'visible') return;\n\n const saved = ['anchor-name', 'outline'].map((property) => ({\n priority: element.style.getPropertyPriority(property),\n property,\n value: element.style.getPropertyValue(property),\n }));\n const oldMarker = element.getAttribute('data-lobe-focus-ring');\n const anchor = computed.getPropertyValue('anchor-name').trim();\n const assignedAnchor =\n anchor && anchor !== 'none' ? `${anchor}, --lobe-global-focus` : '--lobe-global-focus';\n element.style.setProperty('anchor-name', assignedAnchor, 'important');\n ring.style.borderRadius = computed.borderRadius;\n ring.style.setProperty(\n '--lobe-focus-ring-color',\n computed.getPropertyValue('--lobe-focus-ring-color').trim() ||\n computed.getPropertyValue('--ant-color-info').trim() ||\n '#1677ff',\n );\n\n restoreTarget = () => {\n for (const { property, value, priority } of saved) {\n const assigned = property === 'anchor-name' ? assignedAnchor : 'none';\n if (element.style.getPropertyValue(property) !== assigned) continue;\n if (value) element.style.setProperty(property, value, priority);\n else element.style.removeProperty(property);\n }\n if (element.getAttribute('data-lobe-focus-ring') === 'managed') {\n if (oldMarker === null) element.removeAttribute('data-lobe-focus-ring');\n else element.setAttribute('data-lobe-focus-ring', oldMarker);\n }\n };\n try {\n ring.showPopover();\n // Do not suppress a working native outline when an anchor cannot resolve.\n const bounds = ring.getBoundingClientRect();\n if (\n Math.max(\n ...(['top', 'right', 'bottom', 'left'] as const).map((edge) =>\n Math.abs(bounds[edge] - rect[edge]),\n ),\n ) > 1\n ) {\n clear();\n return;\n }\n element.style.setProperty('outline', 'none', 'important');\n element.setAttribute('data-lobe-focus-ring', 'managed');\n target = element;\n } catch {\n clear();\n }\n };\n\n const schedule = () => {\n if (!frame)\n frame = win.requestAnimationFrame(() => {\n frame = 0;\n sync();\n });\n };\n const blur = () => {\n win.cancelAnimationFrame(frame);\n frame = 0;\n clear();\n };\n const observer = new MutationObserver(() => {\n if (target && !target.isConnected) clear();\n });\n observer.observe(doc.body, { childList: true, subtree: true });\n doc.addEventListener('focusin', sync, true);\n doc.addEventListener('focusout', schedule, true);\n doc.addEventListener('keydown', schedule, true);\n doc.addEventListener('pointerdown', schedule, true);\n win.addEventListener('blur', blur);\n win.addEventListener('focus', schedule);\n\n const installation = {\n dispose: () => {\n disposed = true;\n win.cancelAnimationFrame(frame);\n observer.disconnect();\n doc.removeEventListener('focusin', sync, true);\n doc.removeEventListener('focusout', schedule, true);\n doc.removeEventListener('keydown', schedule, true);\n doc.removeEventListener('pointerdown', schedule, true);\n win.removeEventListener('blur', blur);\n win.removeEventListener('focus', schedule);\n clear();\n ring.remove();\n sheet.remove();\n installations.delete(doc);\n },\n users: 0,\n };\n installations.set(doc, installation);\n sync();\n return installGlobalFocusRing(doc);\n};\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.mjs","names":[],"sources":["../../src/GlobalFocusRing/index.ts"],"sourcesContent":["import { globalFocusRingCSS } from './style';\n\nconst installations = new WeakMap<Document, { dispose: () => void; users: number }>();\n\n/** Install once per document. The returned cleanup is safe for nested providers and Strict Mode. */\nexport const installGlobalFocusRing = (doc: Document = document): (() => void) => {\n const existing = installations.get(doc);\n if (existing) {\n existing.users += 1;\n let released = false;\n return () => {\n if (released) return;\n released = true;\n if (--existing.users === 0) existing.dispose();\n };\n }\n\n const win = doc.defaultView;\n if (\n !win ||\n !doc.body ||\n !win.CSS?.supports('top', 'anchor(top)') ||\n !win.CSS.supports('position-visibility', 'anchors-visible') ||\n !('showPopover' in doc.createElement('div'))\n )\n return () => {};\n\n const sheet = doc.createElement('style');\n sheet.textContent = globalFocusRingCSS;\n const ring = doc.createElement('div');\n ring.setAttribute('data-lobe-global-focus-ring', '');\n ring.setAttribute('aria-hidden', 'true');\n ring.setAttribute('popover', 'manual');\n doc.head.append(sheet);\n doc.body.append(ring);\n\n let target: HTMLElement | undefined;\n let restoreTarget: (() => void) | undefined;\n let frame = 0;\n let disposed = false;\n\n const clear = () => {\n if (ring.matches(':popover-open')) ring.hidePopover();\n restoreTarget?.();\n restoreTarget = undefined;\n target = undefined;\n };\n\n const sync = () => {\n if (disposed) return;\n const next = doc.activeElement;\n if (next === target && next?.matches(':focus-visible') && next.isConnected) return;\n clear();\n // Shadow roots and fragmented inline text retain their own focus treatment.\n if (\n !next ||\n next === doc.body ||\n next.namespaceURI !== 'http://www.w3.org/1999/xhtml' ||\n next.shadowRoot ||\n next.closest('[data-lobe-focus-ring=\"off\"]') ||\n next.matches('textarea') ||\n (next as HTMLElement).isContentEditable ||\n (next.matches('input') &&\n ![\n 'button',\n 'submit',\n 'reset',\n 'image',\n 'checkbox',\n 'radio',\n 'range',\n 'color',\n 'file',\n ].includes((next as HTMLInputElement).type)) ||\n !next.matches(':focus-visible') ||\n next.getClientRects().length !== 1\n )\n return;\n\n const element = next as HTMLElement;\n const computed = win.getComputedStyle(element);\n const rect = element.getBoundingClientRect();\n if (!rect.width || !rect.height || computed.visibility !== 'visible') return;\n\n const saved = ['anchor-name', 'outline'].map((property) => ({\n priority: element.style.getPropertyPriority(property),\n property,\n value: element.style.getPropertyValue(property),\n }));\n const oldMarker = element.getAttribute('data-lobe-focus-ring');\n const anchor = computed.getPropertyValue('anchor-name').trim();\n const assignedAnchor =\n anchor && anchor !== 'none' ? `${anchor}, --lobe-global-focus` : '--lobe-global-focus';\n element.style.setProperty('anchor-name', assignedAnchor, 'important');\n ring.style.borderRadius = computed.borderRadius;\n ring.style.setProperty(\n '--lobe-focus-ring-color',\n computed.getPropertyValue('--lobe-focus-ring-color').trim() ||\n computed.getPropertyValue('--ant-color-info').trim() ||\n '#1677ff',\n );\n\n restoreTarget = () => {\n for (const { property, value, priority } of saved) {\n const assigned = property === 'anchor-name' ? assignedAnchor : 'none';\n if (element.style.getPropertyValue(property) !== assigned) continue;\n if (value) element.style.setProperty(property, value, priority);\n else element.style.removeProperty(property);\n }\n if (element.getAttribute('data-lobe-focus-ring') === 'managed') {\n if (oldMarker === null) element.removeAttribute('data-lobe-focus-ring');\n else element.setAttribute('data-lobe-focus-ring', oldMarker);\n }\n };\n try {\n ring.showPopover();\n // Do not suppress a working native outline when an anchor cannot resolve.\n const bounds = ring.getBoundingClientRect();\n if (\n Math.max(\n ...(['top', 'right', 'bottom', 'left'] as const).map((edge) =>\n Math.abs(bounds[edge] - rect[edge]),\n ),\n ) > 1\n ) {\n clear();\n return;\n }\n element.style.setProperty('outline', 'none', 'important');\n element.setAttribute('data-lobe-focus-ring', 'managed');\n target = element;\n } catch {\n clear();\n }\n };\n\n const schedule = () => {\n if (!frame)\n frame = win.requestAnimationFrame(() => {\n frame = 0;\n sync();\n });\n };\n const blur = () => {\n win.cancelAnimationFrame(frame);\n frame = 0;\n clear();\n };\n const observer = new MutationObserver(() => {\n if (target && !target.isConnected) clear();\n });\n observer.observe(doc.body, { childList: true, subtree: true });\n doc.addEventListener('focusin', sync, true);\n doc.addEventListener('focusout', schedule, true);\n doc.addEventListener('keydown', schedule, true);\n doc.addEventListener('pointerdown', schedule, true);\n win.addEventListener('blur', blur);\n win.addEventListener('focus', schedule);\n\n const installation = {\n dispose: () => {\n disposed = true;\n win.cancelAnimationFrame(frame);\n observer.disconnect();\n doc.removeEventListener('focusin', sync, true);\n doc.removeEventListener('focusout', schedule, true);\n doc.removeEventListener('keydown', schedule, true);\n doc.removeEventListener('pointerdown', schedule, true);\n win.removeEventListener('blur', blur);\n win.removeEventListener('focus', schedule);\n clear();\n ring.remove();\n sheet.remove();\n installations.delete(doc);\n },\n users: 0,\n };\n installations.set(doc, installation);\n sync();\n return installGlobalFocusRing(doc);\n};\n"],"mappings":"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"}
@@ -3,6 +3,7 @@ import { getFloatingCollisionPadding } from "../floating/collisionPadding.mjs";
3
3
  import { useIsClient } from "../../hooks/useIsClient.mjs";
4
4
  import { useAppElement } from "../../ThemeProvider/AppElementContext.mjs";
5
5
  import { preventDefaultAndStopPropagation } from "../../utils/dom.mjs";
6
+ import { MenuVirtualList } from "../virtual/MenuVirtualList.mjs";
6
7
  import { useLayerZIndex } from "../zIndex/useLayerZIndex.mjs";
7
8
  import { styles } from "../DropdownMenu/sharedStyle.mjs";
8
9
  import { registerDevSingleton } from "../../utils/devSingleton.mjs";
@@ -75,7 +76,10 @@ const ContextMenuHost = memo(() => {
75
76
  className: styles.header,
76
77
  children: state.header
77
78
  }),
78
- hasSlots ? /* @__PURE__ */ jsx("div", {
79
+ state.virtual ? /* @__PURE__ */ jsx(MenuVirtualList, {
80
+ itemSize: state.listItemHeight,
81
+ children: menuItems
82
+ }) : hasSlots ? /* @__PURE__ */ jsx("div", {
79
83
  className: styles.slotViewport,
80
84
  children: menuItems
81
85
  }) : menuItems,
@@ -1 +1 @@
1
- {"version":3,"file":"ContextMenuHost.mjs","names":[],"sources":["../../../src/base-ui/ContextMenu/ContextMenuHost.tsx"],"sourcesContent":["'use client';\n\nimport { ContextMenu } from '@base-ui/react/context-menu';\nimport { cx } from 'antd-style';\nimport { memo, useEffect, useMemo, useSyncExternalStore } from 'react';\n\nimport { getFloatingCollisionPadding } from '@/base-ui/floating';\nimport { useIsClient } from '@/hooks/useIsClient';\nimport { useAppElement } from '@/ThemeProvider';\nimport { registerDevSingleton } from '@/utils/devSingleton';\nimport { preventDefaultAndStopPropagation } from '@/utils/dom';\n\nimport { useLayerZIndex } from '../zIndex';\nimport { renderContextMenuItems } from './renderItems';\nimport {\n closeContextMenu,\n getServerSnapshot,\n getSnapshot,\n setContextMenuState,\n subscribe,\n updateLastPointer,\n} from './store';\nimport { styles } from './style';\n\nconst noAnimationStyles = { '--lobe-dropdown-animation-duration': '0ms' } as React.CSSProperties;\n\nexport const ContextMenuHost = memo(() => {\n const isClient = useIsClient();\n const appElement = useAppElement();\n const state = useSyncExternalStore(subscribe, getSnapshot, getServerSnapshot);\n\n useEffect(() => {\n const DEV = process.env.NODE_ENV === 'development';\n if (!isClient || !DEV) return;\n return registerDevSingleton('ContextMenuHost', document.body);\n }, [isClient]);\n\n useEffect(() => {\n const handler = (event: MouseEvent | PointerEvent) => updateLastPointer(event);\n window.addEventListener('pointerdown', handler, true);\n window.addEventListener('contextmenu', handler, true);\n return () => {\n window.removeEventListener('pointerdown', handler, true);\n window.removeEventListener('contextmenu', handler, true);\n };\n }, []);\n\n const menuItems = useMemo(\n () =>\n renderContextMenuItems(state.items, [], {\n iconAlign: state.iconAlign,\n iconSpaceMode: state.iconSpaceMode,\n }),\n [state.items, state.iconAlign, state.iconSpaceMode],\n );\n const { zIndex, ref: zRef } = useLayerZIndex<HTMLDivElement>('floating');\n const hasSlots = state.header != null || state.footer != null;\n if (!isClient) return null;\n if (!state.open && state.items.length === 0) return null;\n\n return (\n <ContextMenu.Root\n open={state.open}\n onOpenChange={(open) => {\n if (open) {\n setContextMenuState({ open });\n return;\n }\n closeContextMenu();\n }}\n >\n <ContextMenu.Portal container={appElement}>\n <ContextMenu.Positioner\n anchor={state.anchor ?? undefined}\n className={styles.positioner}\n collisionPadding={getFloatingCollisionPadding()}\n ref={zRef as any}\n sideOffset={6}\n style={{ ...noAnimationStyles, zIndex }}\n >\n <ContextMenu.Popup\n className={cx(styles.popup, hasSlots && styles.popupWithSlots)}\n data-has-footer={state.footer == null ? undefined : ''}\n data-has-header={state.header == null ? undefined : ''}\n onContextMenu={preventDefaultAndStopPropagation}\n >\n {state.header == null ? null : <div className={styles.header}>{state.header}</div>}\n {hasSlots ? <div className={styles.slotViewport}>{menuItems}</div> : menuItems}\n {state.footer == null ? null : <div className={styles.footer}>{state.footer}</div>}\n </ContextMenu.Popup>\n </ContextMenu.Positioner>\n </ContextMenu.Portal>\n </ContextMenu.Root>\n );\n});\n\nContextMenuHost.displayName = 'ContextMenuHost';\n"],"mappings":";;;;;;;;;;;;;;;AAwBA,MAAM,oBAAoB,EAAE,sCAAsC,MAAM;AAExE,MAAa,kBAAkB,WAAW;CACxC,MAAM,WAAW,YAAY;CAC7B,MAAM,aAAa,cAAc;CACjC,MAAM,QAAQ,qBAAqB,WAAW,aAAa,iBAAiB;CAE5E,gBAAgB;EACd,MAAM,MAAM,QAAQ,IAAI,aAAa;EACrC,IAAI,CAAC,YAAY,CAAC,KAAK;EACvB,OAAO,qBAAqB,mBAAmB,SAAS,IAAI;CAC9D,GAAG,CAAC,QAAQ,CAAC;CAEb,gBAAgB;EACd,MAAM,WAAW,UAAqC,kBAAkB,KAAK;EAC7E,OAAO,iBAAiB,eAAe,SAAS,IAAI;EACpD,OAAO,iBAAiB,eAAe,SAAS,IAAI;EACpD,aAAa;GACX,OAAO,oBAAoB,eAAe,SAAS,IAAI;GACvD,OAAO,oBAAoB,eAAe,SAAS,IAAI;EACzD;CACF,GAAG,CAAC,CAAC;CAEL,MAAM,YAAY,cAEd,uBAAuB,MAAM,OAAO,CAAC,GAAG;EACtC,WAAW,MAAM;EACjB,eAAe,MAAM;CACvB,CAAC,GACH;EAAC,MAAM;EAAO,MAAM;EAAW,MAAM;CAAa,CACpD;CACA,MAAM,EAAE,QAAQ,KAAK,SAAS,eAA+B,UAAU;CACvE,MAAM,WAAW,MAAM,UAAU,QAAQ,MAAM,UAAU;CACzD,IAAI,CAAC,UAAU,OAAO;CACtB,IAAI,CAAC,MAAM,QAAQ,MAAM,MAAM,WAAW,GAAG,OAAO;CAEpD,OACE,oBAAC,YAAY,MAAb;EACE,MAAM,MAAM;EACZ,eAAe,SAAS;GACtB,IAAI,MAAM;IACR,oBAAoB,EAAE,KAAK,CAAC;IAC5B;GACF;GACA,iBAAiB;EACnB;EAEA,UAAA,oBAAC,YAAY,QAAb;GAAoB,WAAW;GAC7B,UAAA,oBAAC,YAAY,YAAb;IACE,QAAQ,MAAM,UAAU,KAAA;IACxB,WAAW,OAAO;IAClB,kBAAkB,4BAA4B;IAC9C,KAAK;IACL,YAAY;IACZ,OAAO;KAAE,GAAG;KAAmB;IAAO;IAEtC,UAAA,qBAAC,YAAY,OAAb;KACE,WAAW,GAAG,OAAO,OAAO,YAAY,OAAO,cAAc;KAC7D,mBAAiB,MAAM,UAAU,OAAO,KAAA,IAAY;KACpD,mBAAiB,MAAM,UAAU,OAAO,KAAA,IAAY;KACpD,eAAe;KAJjB,UAAA;MAMG,MAAM,UAAU,OAAO,OAAO,oBAAC,OAAD;OAAK,WAAW,OAAO;OAAS,UAAA,MAAM;MAAY,CAAA;MAChF,WAAW,oBAAC,OAAD;OAAK,WAAW,OAAO;OAAe,UAAA;MAAe,CAAA,IAAI;MACpE,MAAM,UAAU,OAAO,OAAO,oBAAC,OAAD;OAAK,WAAW,OAAO;OAAS,UAAA,MAAM;MAAY,CAAA;KAChE;;GACG,CAAA;EACN,CAAA;CACJ,CAAA;AAEtB,CAAC;AAED,gBAAgB,cAAc"}
1
+ {"version":3,"file":"ContextMenuHost.mjs","names":[],"sources":["../../../src/base-ui/ContextMenu/ContextMenuHost.tsx"],"sourcesContent":["'use client';\n\nimport { ContextMenu } from '@base-ui/react/context-menu';\nimport { cx } from 'antd-style';\nimport { memo, useEffect, useMemo, useSyncExternalStore } from 'react';\n\nimport { getFloatingCollisionPadding } from '@/base-ui/floating';\nimport { MenuVirtualList } from '@/base-ui/virtual';\nimport { useIsClient } from '@/hooks/useIsClient';\nimport { useAppElement } from '@/ThemeProvider';\nimport { registerDevSingleton } from '@/utils/devSingleton';\nimport { preventDefaultAndStopPropagation } from '@/utils/dom';\n\nimport { useLayerZIndex } from '../zIndex';\nimport { renderContextMenuItems } from './renderItems';\nimport {\n closeContextMenu,\n getServerSnapshot,\n getSnapshot,\n setContextMenuState,\n subscribe,\n updateLastPointer,\n} from './store';\nimport { styles } from './style';\n\nconst noAnimationStyles = { '--lobe-dropdown-animation-duration': '0ms' } as React.CSSProperties;\n\nexport const ContextMenuHost = memo(() => {\n const isClient = useIsClient();\n const appElement = useAppElement();\n const state = useSyncExternalStore(subscribe, getSnapshot, getServerSnapshot);\n\n useEffect(() => {\n const DEV = process.env.NODE_ENV === 'development';\n if (!isClient || !DEV) return;\n return registerDevSingleton('ContextMenuHost', document.body);\n }, [isClient]);\n\n useEffect(() => {\n const handler = (event: MouseEvent | PointerEvent) => updateLastPointer(event);\n window.addEventListener('pointerdown', handler, true);\n window.addEventListener('contextmenu', handler, true);\n return () => {\n window.removeEventListener('pointerdown', handler, true);\n window.removeEventListener('contextmenu', handler, true);\n };\n }, []);\n\n const menuItems = useMemo(\n () =>\n renderContextMenuItems(state.items, [], {\n iconAlign: state.iconAlign,\n iconSpaceMode: state.iconSpaceMode,\n }),\n [state.items, state.iconAlign, state.iconSpaceMode],\n );\n const { zIndex, ref: zRef } = useLayerZIndex<HTMLDivElement>('floating');\n const hasSlots = state.header != null || state.footer != null;\n if (!isClient) return null;\n if (!state.open && state.items.length === 0) return null;\n\n return (\n <ContextMenu.Root\n open={state.open}\n onOpenChange={(open) => {\n if (open) {\n setContextMenuState({ open });\n return;\n }\n closeContextMenu();\n }}\n >\n <ContextMenu.Portal container={appElement}>\n <ContextMenu.Positioner\n anchor={state.anchor ?? undefined}\n className={styles.positioner}\n collisionPadding={getFloatingCollisionPadding()}\n ref={zRef as any}\n sideOffset={6}\n style={{ ...noAnimationStyles, zIndex }}\n >\n <ContextMenu.Popup\n className={cx(styles.popup, hasSlots && styles.popupWithSlots)}\n data-has-footer={state.footer == null ? undefined : ''}\n data-has-header={state.header == null ? undefined : ''}\n onContextMenu={preventDefaultAndStopPropagation}\n >\n {state.header == null ? null : <div className={styles.header}>{state.header}</div>}\n {state.virtual ? (\n <MenuVirtualList itemSize={state.listItemHeight}>{menuItems}</MenuVirtualList>\n ) : hasSlots ? (\n <div className={styles.slotViewport}>{menuItems}</div>\n ) : (\n menuItems\n )}\n {state.footer == null ? null : <div className={styles.footer}>{state.footer}</div>}\n </ContextMenu.Popup>\n </ContextMenu.Positioner>\n </ContextMenu.Portal>\n </ContextMenu.Root>\n );\n});\n\nContextMenuHost.displayName = 'ContextMenuHost';\n"],"mappings":";;;;;;;;;;;;;;;;AAyBA,MAAM,oBAAoB,EAAE,sCAAsC,MAAM;AAExE,MAAa,kBAAkB,WAAW;CACxC,MAAM,WAAW,YAAY;CAC7B,MAAM,aAAa,cAAc;CACjC,MAAM,QAAQ,qBAAqB,WAAW,aAAa,iBAAiB;CAE5E,gBAAgB;EACd,MAAM,MAAM,QAAQ,IAAI,aAAa;EACrC,IAAI,CAAC,YAAY,CAAC,KAAK;EACvB,OAAO,qBAAqB,mBAAmB,SAAS,IAAI;CAC9D,GAAG,CAAC,QAAQ,CAAC;CAEb,gBAAgB;EACd,MAAM,WAAW,UAAqC,kBAAkB,KAAK;EAC7E,OAAO,iBAAiB,eAAe,SAAS,IAAI;EACpD,OAAO,iBAAiB,eAAe,SAAS,IAAI;EACpD,aAAa;GACX,OAAO,oBAAoB,eAAe,SAAS,IAAI;GACvD,OAAO,oBAAoB,eAAe,SAAS,IAAI;EACzD;CACF,GAAG,CAAC,CAAC;CAEL,MAAM,YAAY,cAEd,uBAAuB,MAAM,OAAO,CAAC,GAAG;EACtC,WAAW,MAAM;EACjB,eAAe,MAAM;CACvB,CAAC,GACH;EAAC,MAAM;EAAO,MAAM;EAAW,MAAM;CAAa,CACpD;CACA,MAAM,EAAE,QAAQ,KAAK,SAAS,eAA+B,UAAU;CACvE,MAAM,WAAW,MAAM,UAAU,QAAQ,MAAM,UAAU;CACzD,IAAI,CAAC,UAAU,OAAO;CACtB,IAAI,CAAC,MAAM,QAAQ,MAAM,MAAM,WAAW,GAAG,OAAO;CAEpD,OACE,oBAAC,YAAY,MAAb;EACE,MAAM,MAAM;EACZ,eAAe,SAAS;GACtB,IAAI,MAAM;IACR,oBAAoB,EAAE,KAAK,CAAC;IAC5B;GACF;GACA,iBAAiB;EACnB;EAEA,UAAA,oBAAC,YAAY,QAAb;GAAoB,WAAW;GAC7B,UAAA,oBAAC,YAAY,YAAb;IACE,QAAQ,MAAM,UAAU,KAAA;IACxB,WAAW,OAAO;IAClB,kBAAkB,4BAA4B;IAC9C,KAAK;IACL,YAAY;IACZ,OAAO;KAAE,GAAG;KAAmB;IAAO;IAEtC,UAAA,qBAAC,YAAY,OAAb;KACE,WAAW,GAAG,OAAO,OAAO,YAAY,OAAO,cAAc;KAC7D,mBAAiB,MAAM,UAAU,OAAO,KAAA,IAAY;KACpD,mBAAiB,MAAM,UAAU,OAAO,KAAA,IAAY;KACpD,eAAe;KAJjB,UAAA;MAMG,MAAM,UAAU,OAAO,OAAO,oBAAC,OAAD;OAAK,WAAW,OAAO;OAAS,UAAA,MAAM;MAAY,CAAA;MAChF,MAAM,UACL,oBAAC,iBAAD;OAAiB,UAAU,MAAM;OAAiB,UAAA;MAA2B,CAAA,IAC3E,WACF,oBAAC,OAAD;OAAK,WAAW,OAAO;OAAe,UAAA;MAAe,CAAA,IAErD;MAED,MAAM,UAAU,OAAO,OAAO,oBAAC,OAAD;OAAK,WAAW,OAAO;OAAS,UAAA,MAAM;MAAY,CAAA;KAChE;;GACG,CAAA;EACN,CAAA;CACJ,CAAA;AAEtB,CAAC;AAED,gBAAgB,cAAc"}
@@ -1,7 +1,9 @@
1
+ import { VirtualListProps } from "../virtual/type.mjs";
2
+ import "../virtual/index.mjs";
1
3
  import { ContextMenuItem } from "./type.mjs";
2
4
  import React, { HTMLAttributes, MouseEvent, ReactNode } from "react";
3
5
  //#region src/base-ui/ContextMenu/ContextMenuTrigger.d.ts
4
- type ContextMenuTriggerProps = {
6
+ type ContextMenuTriggerProps = Pick<VirtualListProps, 'virtual' | 'listItemHeight'> & {
5
7
  children: ReactNode;
6
8
  /**
7
9
  * Footer slot pinned below the scrollable items area, with a divider border.
@@ -7,7 +7,7 @@ import { mergeProps } from "@base-ui/react/merge-props";
7
7
  import clsx from "clsx";
8
8
  //#region src/base-ui/ContextMenu/ContextMenuTrigger.tsx
9
9
  const styles = { trigger: { display: "contents" } };
10
- const ContextMenuTrigger = memo(({ children, footer, header, items, onContextMenu, ...rest }) => {
10
+ const ContextMenuTrigger = memo(({ children, footer, header, items, listItemHeight, onContextMenu, virtual, ...rest }) => {
11
11
  const triggerId = useId();
12
12
  const state = useSyncExternalStore(subscribe, getSnapshot, getServerSnapshot);
13
13
  const open = state.open && state.triggerId === triggerId;
@@ -17,7 +17,9 @@ const ContextMenuTrigger = memo(({ children, footer, header, items, onContextMen
17
17
  const resolvedItems = typeof items === "function" ? items() : items;
18
18
  showContextMenu(resolvedItems, {
19
19
  footer,
20
- header
20
+ header,
21
+ listItemHeight,
22
+ virtual
21
23
  });
22
24
  }
23
25
  onContextMenu?.(event);
@@ -25,7 +27,9 @@ const ContextMenuTrigger = memo(({ children, footer, header, items, onContextMen
25
27
  items,
26
28
  onContextMenu,
27
29
  footer,
28
- header
30
+ header,
31
+ listItemHeight,
32
+ virtual
29
33
  ]);
30
34
  const triggerProps = {
31
35
  ...rest,
@@ -1 +1 @@
1
- {"version":3,"file":"ContextMenuTrigger.mjs","names":[],"sources":["../../../src/base-ui/ContextMenu/ContextMenuTrigger.tsx"],"sourcesContent":["'use client';\n\nimport { mergeProps } from '@base-ui/react/merge-props';\nimport clsx from 'clsx';\nimport React, {\n cloneElement,\n type HTMLAttributes,\n isValidElement,\n memo,\n type MouseEvent,\n type ReactNode,\n useCallback,\n useId,\n useSyncExternalStore,\n} from 'react';\n\nimport { CLASSNAMES } from '@/styles/classNames';\n\nimport { getServerSnapshot, getSnapshot, showContextMenu, subscribe } from './store';\nimport { type ContextMenuItem } from './type';\n\nexport type ContextMenuTriggerProps = {\n children: ReactNode;\n /**\n * Footer slot pinned below the scrollable items area, with a divider border.\n */\n footer?: ReactNode;\n /**\n * Header slot pinned above the scrollable items area, with a divider border.\n */\n header?: ReactNode;\n /**\n * Menu items to display. Supports lazy rendering via function.\n * When provided, context menu will be automatically shown on right-click.\n */\n items?: ContextMenuItem[] | (() => ContextMenuItem[]);\n /**\n * Custom context menu handler. If `items` is provided, this is optional.\n */\n onContextMenu?: (event: MouseEvent<HTMLElement>) => void;\n} & Omit<HTMLAttributes<HTMLElement>, 'onContextMenu' | 'children'>;\n\nconst styles = {\n trigger: {\n display: 'contents',\n },\n};\n\nexport const ContextMenuTrigger = memo<ContextMenuTriggerProps>(\n ({ children, footer, header, items, onContextMenu, ...rest }) => {\n const triggerId = useId();\n const state = useSyncExternalStore(subscribe, getSnapshot, getServerSnapshot);\n const open = state.open && state.triggerId === triggerId;\n\n const handleContextMenu = useCallback(\n (event: MouseEvent<HTMLElement>) => {\n if (items) {\n event.preventDefault();\n const resolvedItems = typeof items === 'function' ? items() : items;\n showContextMenu(resolvedItems, { footer, header });\n }\n onContextMenu?.(event);\n },\n [items, onContextMenu, footer, header],\n );\n\n const triggerProps = {\n ...rest,\n 'aria-expanded': open || undefined,\n 'className': clsx(CLASSNAMES.ContextTrigger, rest.className),\n 'data-contextmenu-trigger': triggerId,\n 'data-popup-open': open ? '' : undefined,\n 'data-state': open ? 'open' : undefined,\n 'onContextMenu': handleContextMenu,\n };\n\n if (isValidElement(children) && React.Children.only(children)) {\n return cloneElement(children, mergeProps(children.props as any, triggerProps));\n }\n\n return (\n <span style={styles.trigger} {...triggerProps}>\n {children}\n </span>\n );\n },\n);\n\nContextMenuTrigger.displayName = 'ContextMenuTrigger';\n"],"mappings":";;;;;;;;AA0CA,MAAM,SAAS,EACb,SAAS,EACP,SAAS,WACX,EACF;AAEA,MAAa,qBAAqB,MAC/B,EAAE,UAAU,QAAQ,QAAQ,OAAO,eAAe,GAAG,WAAW;CAC/D,MAAM,YAAY,MAAM;CACxB,MAAM,QAAQ,qBAAqB,WAAW,aAAa,iBAAiB;CAC5E,MAAM,OAAO,MAAM,QAAQ,MAAM,cAAc;CAE/C,MAAM,oBAAoB,aACvB,UAAmC;EAClC,IAAI,OAAO;GACT,MAAM,eAAe;GACrB,MAAM,gBAAgB,OAAO,UAAU,aAAa,MAAM,IAAI;GAC9D,gBAAgB,eAAe;IAAE;IAAQ;GAAO,CAAC;EACnD;EACA,gBAAgB,KAAK;CACvB,GACA;EAAC;EAAO;EAAe;EAAQ;CAAM,CACvC;CAEA,MAAM,eAAe;EACnB,GAAG;EACH,iBAAiB,QAAQ,KAAA;EACzB,aAAa,KAAK,WAAW,gBAAgB,KAAK,SAAS;EAC3D,4BAA4B;EAC5B,mBAAmB,OAAO,KAAK,KAAA;EAC/B,cAAc,OAAO,SAAS,KAAA;EAC9B,iBAAiB;CACnB;CAEA,IAAI,eAAe,QAAQ,KAAK,MAAM,SAAS,KAAK,QAAQ,GAC1D,OAAO,aAAa,UAAU,WAAW,SAAS,OAAc,YAAY,CAAC;CAG/E,OACE,oBAAC,QAAD;EAAM,OAAO,OAAO;EAAS,GAAI;EAC9B;CACG,CAAA;AAEV,CACF;AAEA,mBAAmB,cAAc"}
1
+ {"version":3,"file":"ContextMenuTrigger.mjs","names":[],"sources":["../../../src/base-ui/ContextMenu/ContextMenuTrigger.tsx"],"sourcesContent":["'use client';\n\nimport { mergeProps } from '@base-ui/react/merge-props';\nimport clsx from 'clsx';\nimport React, {\n cloneElement,\n type HTMLAttributes,\n isValidElement,\n memo,\n type MouseEvent,\n type ReactNode,\n useCallback,\n useId,\n useSyncExternalStore,\n} from 'react';\n\nimport type { VirtualListProps } from '@/base-ui/virtual';\nimport { CLASSNAMES } from '@/styles/classNames';\n\nimport { getServerSnapshot, getSnapshot, showContextMenu, subscribe } from './store';\nimport { type ContextMenuItem } from './type';\n\nexport type ContextMenuTriggerProps = Pick<VirtualListProps, 'virtual' | 'listItemHeight'> & {\n children: ReactNode;\n /**\n * Footer slot pinned below the scrollable items area, with a divider border.\n */\n footer?: ReactNode;\n /**\n * Header slot pinned above the scrollable items area, with a divider border.\n */\n header?: ReactNode;\n /**\n * Menu items to display. Supports lazy rendering via function.\n * When provided, context menu will be automatically shown on right-click.\n */\n items?: ContextMenuItem[] | (() => ContextMenuItem[]);\n /**\n * Custom context menu handler. If `items` is provided, this is optional.\n */\n onContextMenu?: (event: MouseEvent<HTMLElement>) => void;\n} & Omit<HTMLAttributes<HTMLElement>, 'onContextMenu' | 'children'>;\n\nconst styles = {\n trigger: {\n display: 'contents',\n },\n};\n\nexport const ContextMenuTrigger = memo<ContextMenuTriggerProps>(\n ({ children, footer, header, items, listItemHeight, onContextMenu, virtual, ...rest }) => {\n const triggerId = useId();\n const state = useSyncExternalStore(subscribe, getSnapshot, getServerSnapshot);\n const open = state.open && state.triggerId === triggerId;\n\n const handleContextMenu = useCallback(\n (event: MouseEvent<HTMLElement>) => {\n if (items) {\n event.preventDefault();\n const resolvedItems = typeof items === 'function' ? items() : items;\n showContextMenu(resolvedItems, { footer, header, listItemHeight, virtual });\n }\n onContextMenu?.(event);\n },\n [items, onContextMenu, footer, header, listItemHeight, virtual],\n );\n\n const triggerProps = {\n ...rest,\n 'aria-expanded': open || undefined,\n 'className': clsx(CLASSNAMES.ContextTrigger, rest.className),\n 'data-contextmenu-trigger': triggerId,\n 'data-popup-open': open ? '' : undefined,\n 'data-state': open ? 'open' : undefined,\n 'onContextMenu': handleContextMenu,\n };\n\n if (isValidElement(children) && React.Children.only(children)) {\n return cloneElement(children, mergeProps(children.props as any, triggerProps));\n }\n\n return (\n <span style={styles.trigger} {...triggerProps}>\n {children}\n </span>\n );\n },\n);\n\nContextMenuTrigger.displayName = 'ContextMenuTrigger';\n"],"mappings":";;;;;;;;AA2CA,MAAM,SAAS,EACb,SAAS,EACP,SAAS,WACX,EACF;AAEA,MAAa,qBAAqB,MAC/B,EAAE,UAAU,QAAQ,QAAQ,OAAO,gBAAgB,eAAe,SAAS,GAAG,WAAW;CACxF,MAAM,YAAY,MAAM;CACxB,MAAM,QAAQ,qBAAqB,WAAW,aAAa,iBAAiB;CAC5E,MAAM,OAAO,MAAM,QAAQ,MAAM,cAAc;CAE/C,MAAM,oBAAoB,aACvB,UAAmC;EAClC,IAAI,OAAO;GACT,MAAM,eAAe;GACrB,MAAM,gBAAgB,OAAO,UAAU,aAAa,MAAM,IAAI;GAC9D,gBAAgB,eAAe;IAAE;IAAQ;IAAQ;IAAgB;GAAQ,CAAC;EAC5E;EACA,gBAAgB,KAAK;CACvB,GACA;EAAC;EAAO;EAAe;EAAQ;EAAQ;EAAgB;CAAO,CAChE;CAEA,MAAM,eAAe;EACnB,GAAG;EACH,iBAAiB,QAAQ,KAAA;EACzB,aAAa,KAAK,WAAW,gBAAgB,KAAK,SAAS;EAC3D,4BAA4B;EAC5B,mBAAmB,OAAO,KAAK,KAAA;EAC/B,cAAc,OAAO,SAAS,KAAA;EAC9B,iBAAiB;CACnB;CAEA,IAAI,eAAe,QAAQ,KAAK,MAAM,SAAS,KAAK,QAAQ,GAC1D,OAAO,aAAa,UAAU,WAAW,SAAS,OAAc,YAAY,CAAC;CAG/E,OACE,oBAAC,QAAD;EAAM,OAAO,OAAO;EAAS,GAAI;EAC9B;CACG,CAAA;AAEV,CACF;AAEA,mBAAmB,cAAc"}
@@ -1,3 +1,5 @@
1
+ import { VirtualListProps } from "../virtual/type.mjs";
2
+ import "../virtual/index.mjs";
1
3
  import { IconAlign, IconSpaceMode } from "../../Menu/renderUtils.mjs";
2
4
  import "../../Menu/index.mjs";
3
5
  import { ContextMenuItem } from "./type.mjs";
@@ -5,7 +7,7 @@ import "./renderItems.mjs";
5
7
  import { ReactNode } from "react";
6
8
  import "@floating-ui/react";
7
9
  //#region src/base-ui/ContextMenu/store.d.ts
8
- interface ShowContextMenuOptions {
10
+ interface ShowContextMenuOptions extends Pick<VirtualListProps, 'virtual' | 'listItemHeight'> {
9
11
  footer?: ReactNode;
10
12
  header?: ReactNode;
11
13
  iconAlign?: IconAlign;
@@ -80,8 +80,10 @@ const showWebContextMenu = (items, options) => {
80
80
  iconAlign: options?.iconAlign,
81
81
  iconSpaceMode: options?.iconSpaceMode ?? "global",
82
82
  items,
83
+ listItemHeight: options?.listItemHeight,
83
84
  open: true,
84
- triggerId: lastPointer.triggerId ?? null
85
+ triggerId: lastPointer.triggerId ?? null,
86
+ virtual: options?.virtual
85
87
  });
86
88
  };
87
89
  const showContextMenu = (items, options) => {
@@ -107,8 +109,10 @@ const closeWebContextMenu = () => {
107
109
  header: void 0,
108
110
  iconSpaceMode: "global",
109
111
  items: [],
112
+ listItemHeight: void 0,
110
113
  open: false,
111
- triggerId: null
114
+ triggerId: null,
115
+ virtual: void 0
112
116
  });
113
117
  };
114
118
  const closeContextMenu = () => {
@@ -1 +1 @@
1
- {"version":3,"file":"store.mjs","names":[],"sources":["../../../src/base-ui/ContextMenu/store.ts"],"sourcesContent":["import type { VirtualElement } from '@floating-ui/react';\nimport type { ReactNode } from 'react';\n\nimport type { IconAlign } from '@/Menu';\n\nimport type { IconSpaceMode } from './renderItems';\nimport type { ContextMenuItem } from './type';\n\nexport type ContextMenuState = {\n anchor: VirtualElement | null;\n footer?: ReactNode;\n header?: ReactNode;\n iconAlign?: IconAlign;\n iconSpaceMode: IconSpaceMode;\n items: ContextMenuItem[];\n open: boolean;\n triggerId: string | null;\n};\n\nconst emptyState: ContextMenuState = {\n anchor: null,\n iconSpaceMode: 'global',\n items: [],\n open: false,\n triggerId: null,\n};\n\nlet contextMenuState: ContextMenuState = emptyState;\nconst listeners = new Set<() => void>();\nconst lastPointer = { ready: false, triggerId: null as string | null, x: 0, y: 0 };\n\nconst notify = () => {\n listeners.forEach((listener) => listener());\n};\n\nexport const subscribe = (listener: () => void) => {\n listeners.add(listener);\n return () => listeners.delete(listener);\n};\n\nexport const getSnapshot = () => contextMenuState;\nexport const getServerSnapshot = () => emptyState;\n\nexport const updateLastPointer = (event: MouseEvent | PointerEvent) => {\n lastPointer.x = event.clientX;\n lastPointer.y = event.clientY;\n lastPointer.ready = true;\n if (event.target instanceof Element) {\n const trigger = event.target.closest<HTMLElement>('[data-contextmenu-trigger]');\n lastPointer.triggerId = trigger?.dataset.contextmenuTrigger ?? null;\n } else {\n lastPointer.triggerId = null;\n }\n};\n\nconst createVirtualElement = (point: { x: number; y: number }): VirtualElement => ({\n contextElement: typeof document === 'undefined' ? undefined : document.body,\n getBoundingClientRect: () =>\n ({\n bottom: point.y,\n height: 0,\n left: point.x,\n right: point.x,\n toJSON: () => undefined,\n top: point.y,\n width: 0,\n x: point.x,\n y: point.y,\n }) as DOMRect,\n});\n\nexport const setContextMenuState = (next: Partial<ContextMenuState>) => {\n contextMenuState = { ...contextMenuState, ...next };\n notify();\n};\n\nexport interface ShowContextMenuOptions {\n footer?: ReactNode;\n header?: ReactNode;\n iconAlign?: IconAlign;\n iconSpaceMode?: IconSpaceMode;\n}\n\nexport interface ContextMenuInterceptor {\n close?: (fallback: () => void) => void;\n show?: (\n items: ContextMenuItem[],\n options: ShowContextMenuOptions | undefined,\n fallback: () => void,\n ) => void;\n}\n\nlet interceptor: ContextMenuInterceptor | null = null;\n\n/**\n * Register a global interceptor for every context menu — imperative\n * `showContextMenu`/`closeContextMenu` calls and `ContextMenuTrigger` alike.\n * The interceptor may render the menu through another system (e.g. a native\n * OS menu) or invoke `fallback()` to show the default web menu. Pass `null`\n * to restore the default behavior.\n */\nexport const setContextMenuInterceptor = (next: ContextMenuInterceptor | null) => {\n interceptor = next;\n};\n\nconst showWebContextMenu = (items: ContextMenuItem[], options?: ShowContextMenuOptions) => {\n const fallbackPoint = { x: window.innerWidth / 2, y: window.innerHeight / 2 };\n const point = lastPointer.ready ? { x: lastPointer.x, y: lastPointer.y } : fallbackPoint;\n\n setContextMenuState({\n anchor: createVirtualElement(point),\n footer: options?.footer,\n header: options?.header,\n iconAlign: options?.iconAlign,\n iconSpaceMode: options?.iconSpaceMode ?? 'global',\n items,\n open: true,\n triggerId: lastPointer.triggerId ?? null,\n });\n};\n\nexport const showContextMenu = (items: ContextMenuItem[], options?: ShowContextMenuOptions) => {\n if (typeof window === 'undefined') return;\n\n if (interceptor?.show) {\n interceptor.show(items, options, () => showWebContextMenu(items, options));\n return;\n }\n\n showWebContextMenu(items, options);\n};\n\n/**\n * Update menu items while keeping current anchor/position.\n * Useful for interactive menu items (e.g. checkbox) to avoid re-positioning.\n */\nexport const updateContextMenuItems = (items: ContextMenuItem[]) => {\n if (typeof window === 'undefined') return;\n setContextMenuState({ items });\n};\n\nconst closeWebContextMenu = () => {\n setContextMenuState({\n anchor: null,\n footer: undefined,\n header: undefined,\n iconSpaceMode: 'global',\n items: [],\n open: false,\n triggerId: null,\n });\n};\n\nexport const closeContextMenu = () => {\n if (interceptor?.close) {\n interceptor.close(closeWebContextMenu);\n return;\n }\n\n closeWebContextMenu();\n};\n"],"mappings":";AAmBA,MAAM,aAA+B;CACnC,QAAQ;CACR,eAAe;CACf,OAAO,CAAC;CACR,MAAM;CACN,WAAW;AACb;AAEA,IAAI,mBAAqC;AACzC,MAAM,4BAAY,IAAI,IAAgB;AACtC,MAAM,cAAc;CAAE,OAAO;CAAO,WAAW;CAAuB,GAAG;CAAG,GAAG;AAAE;AAEjF,MAAM,eAAe;CACnB,UAAU,SAAS,aAAa,SAAS,CAAC;AAC5C;AAEA,MAAa,aAAa,aAAyB;CACjD,UAAU,IAAI,QAAQ;CACtB,aAAa,UAAU,OAAO,QAAQ;AACxC;AAEA,MAAa,oBAAoB;AACjC,MAAa,0BAA0B;AAEvC,MAAa,qBAAqB,UAAqC;CACrE,YAAY,IAAI,MAAM;CACtB,YAAY,IAAI,MAAM;CACtB,YAAY,QAAQ;CACpB,IAAI,MAAM,kBAAkB,SAAS;EACnC,MAAM,UAAU,MAAM,OAAO,QAAqB,4BAA4B;EAC9E,YAAY,YAAY,SAAS,QAAQ,sBAAsB;CACjE,OACE,YAAY,YAAY;AAE5B;AAEA,MAAM,wBAAwB,WAAqD;CACjF,gBAAgB,OAAO,aAAa,cAAc,KAAA,IAAY,SAAS;CACvE,8BACG;EACC,QAAQ,MAAM;EACd,QAAQ;EACR,MAAM,MAAM;EACZ,OAAO,MAAM;EACb,cAAc,KAAA;EACd,KAAK,MAAM;EACX,OAAO;EACP,GAAG,MAAM;EACT,GAAG,MAAM;CACX;AACJ;AAEA,MAAa,uBAAuB,SAAoC;CACtE,mBAAmB;EAAE,GAAG;EAAkB,GAAG;CAAK;CAClD,OAAO;AACT;AAkBA,IAAI,cAA6C;;;;;;;;AASjD,MAAa,6BAA6B,SAAwC;CAChF,cAAc;AAChB;AAEA,MAAM,sBAAsB,OAA0B,YAAqC;CACzF,MAAM,gBAAgB;EAAE,GAAG,OAAO,aAAa;EAAG,GAAG,OAAO,cAAc;CAAE;CAC5E,MAAM,QAAQ,YAAY,QAAQ;EAAE,GAAG,YAAY;EAAG,GAAG,YAAY;CAAE,IAAI;CAE3E,oBAAoB;EAClB,QAAQ,qBAAqB,KAAK;EAClC,QAAQ,SAAS;EACjB,QAAQ,SAAS;EACjB,WAAW,SAAS;EACpB,eAAe,SAAS,iBAAiB;EACzC;EACA,MAAM;EACN,WAAW,YAAY,aAAa;CACtC,CAAC;AACH;AAEA,MAAa,mBAAmB,OAA0B,YAAqC;CAC7F,IAAI,OAAO,WAAW,aAAa;CAEnC,IAAI,aAAa,MAAM;EACrB,YAAY,KAAK,OAAO,eAAe,mBAAmB,OAAO,OAAO,CAAC;EACzE;CACF;CAEA,mBAAmB,OAAO,OAAO;AACnC;;;;;AAMA,MAAa,0BAA0B,UAA6B;CAClE,IAAI,OAAO,WAAW,aAAa;CACnC,oBAAoB,EAAE,MAAM,CAAC;AAC/B;AAEA,MAAM,4BAA4B;CAChC,oBAAoB;EAClB,QAAQ;EACR,QAAQ,KAAA;EACR,QAAQ,KAAA;EACR,eAAe;EACf,OAAO,CAAC;EACR,MAAM;EACN,WAAW;CACb,CAAC;AACH;AAEA,MAAa,yBAAyB;CACpC,IAAI,aAAa,OAAO;EACtB,YAAY,MAAM,mBAAmB;EACrC;CACF;CAEA,oBAAoB;AACtB"}
1
+ {"version":3,"file":"store.mjs","names":[],"sources":["../../../src/base-ui/ContextMenu/store.ts"],"sourcesContent":["import type { VirtualElement } from '@floating-ui/react';\nimport type { ReactNode } from 'react';\n\nimport type { VirtualListProps } from '@/base-ui/virtual';\nimport type { IconAlign } from '@/Menu';\n\nimport type { IconSpaceMode } from './renderItems';\nimport type { ContextMenuItem } from './type';\n\nexport type ContextMenuState = Pick<VirtualListProps, 'virtual' | 'listItemHeight'> & {\n anchor: VirtualElement | null;\n footer?: ReactNode;\n header?: ReactNode;\n iconAlign?: IconAlign;\n iconSpaceMode: IconSpaceMode;\n items: ContextMenuItem[];\n open: boolean;\n triggerId: string | null;\n};\n\nconst emptyState: ContextMenuState = {\n anchor: null,\n iconSpaceMode: 'global',\n items: [],\n open: false,\n triggerId: null,\n};\n\nlet contextMenuState: ContextMenuState = emptyState;\nconst listeners = new Set<() => void>();\nconst lastPointer = { ready: false, triggerId: null as string | null, x: 0, y: 0 };\n\nconst notify = () => {\n listeners.forEach((listener) => listener());\n};\n\nexport const subscribe = (listener: () => void) => {\n listeners.add(listener);\n return () => listeners.delete(listener);\n};\n\nexport const getSnapshot = () => contextMenuState;\nexport const getServerSnapshot = () => emptyState;\n\nexport const updateLastPointer = (event: MouseEvent | PointerEvent) => {\n lastPointer.x = event.clientX;\n lastPointer.y = event.clientY;\n lastPointer.ready = true;\n if (event.target instanceof Element) {\n const trigger = event.target.closest<HTMLElement>('[data-contextmenu-trigger]');\n lastPointer.triggerId = trigger?.dataset.contextmenuTrigger ?? null;\n } else {\n lastPointer.triggerId = null;\n }\n};\n\nconst createVirtualElement = (point: { x: number; y: number }): VirtualElement => ({\n contextElement: typeof document === 'undefined' ? undefined : document.body,\n getBoundingClientRect: () =>\n ({\n bottom: point.y,\n height: 0,\n left: point.x,\n right: point.x,\n toJSON: () => undefined,\n top: point.y,\n width: 0,\n x: point.x,\n y: point.y,\n }) as DOMRect,\n});\n\nexport const setContextMenuState = (next: Partial<ContextMenuState>) => {\n contextMenuState = { ...contextMenuState, ...next };\n notify();\n};\n\nexport interface ShowContextMenuOptions extends Pick<\n VirtualListProps,\n 'virtual' | 'listItemHeight'\n> {\n footer?: ReactNode;\n header?: ReactNode;\n iconAlign?: IconAlign;\n iconSpaceMode?: IconSpaceMode;\n}\n\nexport interface ContextMenuInterceptor {\n close?: (fallback: () => void) => void;\n show?: (\n items: ContextMenuItem[],\n options: ShowContextMenuOptions | undefined,\n fallback: () => void,\n ) => void;\n}\n\nlet interceptor: ContextMenuInterceptor | null = null;\n\n/**\n * Register a global interceptor for every context menu — imperative\n * `showContextMenu`/`closeContextMenu` calls and `ContextMenuTrigger` alike.\n * The interceptor may render the menu through another system (e.g. a native\n * OS menu) or invoke `fallback()` to show the default web menu. Pass `null`\n * to restore the default behavior.\n */\nexport const setContextMenuInterceptor = (next: ContextMenuInterceptor | null) => {\n interceptor = next;\n};\n\nconst showWebContextMenu = (items: ContextMenuItem[], options?: ShowContextMenuOptions) => {\n const fallbackPoint = { x: window.innerWidth / 2, y: window.innerHeight / 2 };\n const point = lastPointer.ready ? { x: lastPointer.x, y: lastPointer.y } : fallbackPoint;\n\n setContextMenuState({\n anchor: createVirtualElement(point),\n footer: options?.footer,\n header: options?.header,\n iconAlign: options?.iconAlign,\n iconSpaceMode: options?.iconSpaceMode ?? 'global',\n items,\n listItemHeight: options?.listItemHeight,\n open: true,\n triggerId: lastPointer.triggerId ?? null,\n virtual: options?.virtual,\n });\n};\n\nexport const showContextMenu = (items: ContextMenuItem[], options?: ShowContextMenuOptions) => {\n if (typeof window === 'undefined') return;\n\n if (interceptor?.show) {\n interceptor.show(items, options, () => showWebContextMenu(items, options));\n return;\n }\n\n showWebContextMenu(items, options);\n};\n\n/**\n * Update menu items while keeping current anchor/position.\n * Useful for interactive menu items (e.g. checkbox) to avoid re-positioning.\n */\nexport const updateContextMenuItems = (items: ContextMenuItem[]) => {\n if (typeof window === 'undefined') return;\n setContextMenuState({ items });\n};\n\nconst closeWebContextMenu = () => {\n setContextMenuState({\n anchor: null,\n footer: undefined,\n header: undefined,\n iconSpaceMode: 'global',\n items: [],\n listItemHeight: undefined,\n open: false,\n triggerId: null,\n virtual: undefined,\n });\n};\n\nexport const closeContextMenu = () => {\n if (interceptor?.close) {\n interceptor.close(closeWebContextMenu);\n return;\n }\n\n closeWebContextMenu();\n};\n"],"mappings":";AAoBA,MAAM,aAA+B;CACnC,QAAQ;CACR,eAAe;CACf,OAAO,CAAC;CACR,MAAM;CACN,WAAW;AACb;AAEA,IAAI,mBAAqC;AACzC,MAAM,4BAAY,IAAI,IAAgB;AACtC,MAAM,cAAc;CAAE,OAAO;CAAO,WAAW;CAAuB,GAAG;CAAG,GAAG;AAAE;AAEjF,MAAM,eAAe;CACnB,UAAU,SAAS,aAAa,SAAS,CAAC;AAC5C;AAEA,MAAa,aAAa,aAAyB;CACjD,UAAU,IAAI,QAAQ;CACtB,aAAa,UAAU,OAAO,QAAQ;AACxC;AAEA,MAAa,oBAAoB;AACjC,MAAa,0BAA0B;AAEvC,MAAa,qBAAqB,UAAqC;CACrE,YAAY,IAAI,MAAM;CACtB,YAAY,IAAI,MAAM;CACtB,YAAY,QAAQ;CACpB,IAAI,MAAM,kBAAkB,SAAS;EACnC,MAAM,UAAU,MAAM,OAAO,QAAqB,4BAA4B;EAC9E,YAAY,YAAY,SAAS,QAAQ,sBAAsB;CACjE,OACE,YAAY,YAAY;AAE5B;AAEA,MAAM,wBAAwB,WAAqD;CACjF,gBAAgB,OAAO,aAAa,cAAc,KAAA,IAAY,SAAS;CACvE,8BACG;EACC,QAAQ,MAAM;EACd,QAAQ;EACR,MAAM,MAAM;EACZ,OAAO,MAAM;EACb,cAAc,KAAA;EACd,KAAK,MAAM;EACX,OAAO;EACP,GAAG,MAAM;EACT,GAAG,MAAM;CACX;AACJ;AAEA,MAAa,uBAAuB,SAAoC;CACtE,mBAAmB;EAAE,GAAG;EAAkB,GAAG;CAAK;CAClD,OAAO;AACT;AAqBA,IAAI,cAA6C;;;;;;;;AASjD,MAAa,6BAA6B,SAAwC;CAChF,cAAc;AAChB;AAEA,MAAM,sBAAsB,OAA0B,YAAqC;CACzF,MAAM,gBAAgB;EAAE,GAAG,OAAO,aAAa;EAAG,GAAG,OAAO,cAAc;CAAE;CAC5E,MAAM,QAAQ,YAAY,QAAQ;EAAE,GAAG,YAAY;EAAG,GAAG,YAAY;CAAE,IAAI;CAE3E,oBAAoB;EAClB,QAAQ,qBAAqB,KAAK;EAClC,QAAQ,SAAS;EACjB,QAAQ,SAAS;EACjB,WAAW,SAAS;EACpB,eAAe,SAAS,iBAAiB;EACzC;EACA,gBAAgB,SAAS;EACzB,MAAM;EACN,WAAW,YAAY,aAAa;EACpC,SAAS,SAAS;CACpB,CAAC;AACH;AAEA,MAAa,mBAAmB,OAA0B,YAAqC;CAC7F,IAAI,OAAO,WAAW,aAAa;CAEnC,IAAI,aAAa,MAAM;EACrB,YAAY,KAAK,OAAO,eAAe,mBAAmB,OAAO,OAAO,CAAC;EACzE;CACF;CAEA,mBAAmB,OAAO,OAAO;AACnC;;;;;AAMA,MAAa,0BAA0B,UAA6B;CAClE,IAAI,OAAO,WAAW,aAAa;CACnC,oBAAoB,EAAE,MAAM,CAAC;AAC/B;AAEA,MAAM,4BAA4B;CAChC,oBAAoB;EAClB,QAAQ;EACR,QAAQ,KAAA;EACR,QAAQ,KAAA;EACR,eAAe;EACf,OAAO,CAAC;EACR,gBAAgB,KAAA;EAChB,MAAM;EACN,WAAW;EACX,SAAS,KAAA;CACX,CAAC;AACH;AAEA,MAAa,yBAAyB;CACpC,IAAI,aAAa,OAAO;EACtB,YAAY,MAAM,mBAAmB;EACrC;CACF;CAEA,oBAAoB;AACtB"}
@@ -9,7 +9,7 @@ import { jsx, jsxs } from "react/jsx-runtime";
9
9
  import { cx } from "antd-style";
10
10
  import { Menu } from "@base-ui/react/menu";
11
11
  //#region src/base-ui/DropdownMenu/DropdownMenu.tsx
12
- const DropdownMenu = memo(({ children, defaultOpen, footer, header, iconAlign, iconSpaceMode, items, nativeButton, onOpenChange, onOpenChangeComplete, open, placement = "bottomLeft", popupProps, portalProps, positionerProps, trigger = "click", triggerProps, ...rest }) => {
12
+ const DropdownMenu = memo(({ children, defaultOpen, footer, header, iconAlign, iconSpaceMode, items, listItemHeight, nativeButton, onOpenChange, onOpenChangeComplete, open, placement = "bottomLeft", popupProps, portalProps, positionerProps, trigger = "click", triggerProps, virtual, ...rest }) => {
13
13
  const [uncontrolledOpen, setUncontrolledOpen] = useState(Boolean(defaultOpen));
14
14
  const { openOnHover } = useMemo(() => parseTrigger(trigger), [trigger]);
15
15
  const resolvedOpenOnHover = triggerProps?.openOnHover ?? openOnHover;
@@ -78,7 +78,11 @@ const DropdownMenu = memo(({ children, defaultOpen, footer, header, iconAlign, i
78
78
  className: hasSlots ? cx(styles.popupWithSlots, popupProps?.className) : popupProps?.className,
79
79
  children: [
80
80
  header == null ? null : /* @__PURE__ */ jsx(DropdownMenuHeader, { children: header }),
81
- hasSlots ? /* @__PURE__ */ jsx(DropdownMenuScrollViewport, { children: menuItems }) : menuItems,
81
+ hasSlots || virtual ? /* @__PURE__ */ jsx(DropdownMenuScrollViewport, {
82
+ listItemHeight,
83
+ virtual,
84
+ children: menuItems
85
+ }) : menuItems,
82
86
  footer == null ? null : /* @__PURE__ */ jsx(DropdownMenuFooter, { children: footer })
83
87
  ]
84
88
  })
@@ -1 +1 @@
1
- {"version":3,"file":"DropdownMenu.mjs","names":[],"sources":["../../../src/base-ui/DropdownMenu/DropdownMenu.tsx"],"sourcesContent":["'use client';\n\nimport { Menu } from '@base-ui/react/menu';\nimport { cx } from 'antd-style';\nimport { memo, useCallback, useEffect, useMemo, useRef, useState } from 'react';\n\nimport { useNativeButton } from '@/hooks/useNativeButton';\nimport { parseTrigger } from '@/utils/parseTrigger';\n\nimport {\n DropdownMenuFooter,\n DropdownMenuHeader,\n DropdownMenuPopup,\n DropdownMenuPortal,\n DropdownMenuPositioner,\n DropdownMenuScrollViewport,\n DropdownMenuTrigger,\n} from './atoms';\nimport { renderDropdownMenuItems } from './renderItems';\nimport { styles } from './sharedStyle';\nimport type { DropdownMenuProps } from './type';\n\nconst DropdownMenu = memo<DropdownMenuProps>(\n ({\n children,\n defaultOpen,\n footer,\n header,\n iconAlign,\n iconSpaceMode,\n items,\n nativeButton,\n onOpenChange,\n onOpenChangeComplete,\n open,\n placement = 'bottomLeft',\n popupProps,\n portalProps,\n positionerProps,\n trigger = 'click',\n triggerProps,\n ...rest\n }) => {\n const [uncontrolledOpen, setUncontrolledOpen] = useState(Boolean(defaultOpen));\n\n const { openOnHover } = useMemo(() => parseTrigger(trigger), [trigger]);\n const resolvedOpenOnHover = (triggerProps as any)?.openOnHover ?? openOnHover;\n\n useEffect(() => {\n if (open === undefined) return;\n setUncontrolledOpen(open);\n }, [open]);\n\n const handleOpenChange = useCallback(\n (nextOpen: boolean, details: Parameters<NonNullable<typeof onOpenChange>>[1]) => {\n onOpenChange?.(nextOpen, details);\n if (open === undefined) {\n setUncontrolledOpen(nextOpen);\n }\n },\n [onOpenChange, open],\n );\n\n const menuItemsRef = useRef<ReturnType<typeof renderDropdownMenuItems> | null>(null);\n const isOpen = open ?? uncontrolledOpen;\n const menuItems = useMemo(() => {\n if (isOpen) {\n const resolvedItems = typeof items === 'function' ? items() : items;\n const renderedItems = renderDropdownMenuItems(resolvedItems, [], {\n iconAlign,\n iconSpaceMode,\n });\n menuItemsRef.current = renderedItems;\n return renderedItems;\n }\n return menuItemsRef.current;\n }, [isOpen, items, iconAlign, iconSpaceMode]);\n const handleOpenChangeComplete = useCallback(\n (nextOpen: boolean) => {\n onOpenChangeComplete?.(nextOpen);\n if (!nextOpen) {\n menuItemsRef.current = null;\n }\n },\n [onOpenChangeComplete],\n );\n const { container: portalContainer, ...restPortalProps } = (portalProps ?? {}) as any;\n\n const { resolvedNativeButton } = useNativeButton({\n children,\n nativeButton,\n triggerNativeButton: triggerProps?.nativeButton,\n });\n\n const hasSlots = header != null || footer != null;\n\n const triggerElement = (\n <DropdownMenuTrigger\n {...triggerProps}\n nativeButton={resolvedNativeButton}\n openOnHover={resolvedOpenOnHover}\n >\n {children}\n </DropdownMenuTrigger>\n );\n\n return (\n <Menu.Root\n {...rest}\n defaultOpen={defaultOpen}\n modal={false}\n open={open}\n onOpenChange={handleOpenChange}\n onOpenChangeComplete={handleOpenChangeComplete}\n >\n {triggerElement}\n <DropdownMenuPortal container={portalContainer} {...restPortalProps}>\n <DropdownMenuPositioner\n {...positionerProps}\n hoverTrigger={resolvedOpenOnHover}\n placement={placement}\n >\n <DropdownMenuPopup\n {...popupProps}\n data-has-footer={footer == null ? undefined : ''}\n data-has-header={header == null ? undefined : ''}\n className={\n hasSlots\n ? (cx(styles.popupWithSlots, popupProps?.className as string) as any)\n : popupProps?.className\n }\n >\n {header == null ? null : <DropdownMenuHeader>{header}</DropdownMenuHeader>}\n {hasSlots ? (\n <DropdownMenuScrollViewport>{menuItems}</DropdownMenuScrollViewport>\n ) : (\n menuItems\n )}\n {footer == null ? null : <DropdownMenuFooter>{footer}</DropdownMenuFooter>}\n </DropdownMenuPopup>\n </DropdownMenuPositioner>\n </DropdownMenuPortal>\n </Menu.Root>\n );\n },\n);\n\nDropdownMenu.displayName = 'DropdownMenuV2';\n\nexport default DropdownMenu;\n"],"mappings":";;;;;;;;;;;AAsBA,MAAM,eAAe,MAClB,EACC,UACA,aACA,QACA,QACA,WACA,eACA,OACA,cACA,cACA,sBACA,MACA,YAAY,cACZ,YACA,aACA,iBACA,UAAU,SACV,cACA,GAAG,WACC;CACJ,MAAM,CAAC,kBAAkB,uBAAuB,SAAS,QAAQ,WAAW,CAAC;CAE7E,MAAM,EAAE,gBAAgB,cAAc,aAAa,OAAO,GAAG,CAAC,OAAO,CAAC;CACtE,MAAM,sBAAuB,cAAsB,eAAe;CAElE,gBAAgB;EACd,IAAI,SAAS,KAAA,GAAW;EACxB,oBAAoB,IAAI;CAC1B,GAAG,CAAC,IAAI,CAAC;CAET,MAAM,mBAAmB,aACtB,UAAmB,YAA6D;EAC/E,eAAe,UAAU,OAAO;EAChC,IAAI,SAAS,KAAA,GACX,oBAAoB,QAAQ;CAEhC,GACA,CAAC,cAAc,IAAI,CACrB;CAEA,MAAM,eAAe,OAA0D,IAAI;CACnF,MAAM,SAAS,QAAQ;CACvB,MAAM,YAAY,cAAc;EAC9B,IAAI,QAAQ;GACV,MAAM,gBAAgB,OAAO,UAAU,aAAa,MAAM,IAAI;GAC9D,MAAM,gBAAgB,wBAAwB,eAAe,CAAC,GAAG;IAC/D;IACA;GACF,CAAC;GACD,aAAa,UAAU;GACvB,OAAO;EACT;EACA,OAAO,aAAa;CACtB,GAAG;EAAC;EAAQ;EAAO;EAAW;CAAa,CAAC;CAC5C,MAAM,2BAA2B,aAC9B,aAAsB;EACrB,uBAAuB,QAAQ;EAC/B,IAAI,CAAC,UACH,aAAa,UAAU;CAE3B,GACA,CAAC,oBAAoB,CACvB;CACA,MAAM,EAAE,WAAW,iBAAiB,GAAG,oBAAqB,eAAe,CAAC;CAE5E,MAAM,EAAE,yBAAyB,gBAAgB;EAC/C;EACA;EACA,qBAAqB,cAAc;CACrC,CAAC;CAED,MAAM,WAAW,UAAU,QAAQ,UAAU;CAE7C,MAAM,iBACJ,oBAAC,qBAAD;EACE,GAAI;EACJ,cAAc;EACd,aAAa;EAEZ;CACkB,CAAA;CAGvB,OACE,qBAAC,KAAK,MAAN;EACE,GAAI;EACS;EACb,OAAO;EACD;EACN,cAAc;EACd,sBAAsB;EANxB,UAAA,CAQG,gBACD,oBAAC,oBAAD;GAAoB,WAAW;GAAiB,GAAI;GAClD,UAAA,oBAAC,wBAAD;IACE,GAAI;IACJ,cAAc;IACH;IAEX,UAAA,qBAAC,mBAAD;KACE,GAAI;KACJ,mBAAiB,UAAU,OAAO,KAAA,IAAY;KAC9C,mBAAiB,UAAU,OAAO,KAAA,IAAY;KAC9C,WACE,WACK,GAAG,OAAO,gBAAgB,YAAY,SAAmB,IAC1D,YAAY;KAPpB,UAAA;MAUG,UAAU,OAAO,OAAO,oBAAC,oBAAD,EAAA,UAAqB,OAA2B,CAAA;MACxE,WACC,oBAAC,4BAAD,EAAA,UAA6B,UAAsC,CAAA,IAEnE;MAED,UAAU,OAAO,OAAO,oBAAC,oBAAD,EAAA,UAAqB,OAA2B,CAAA;KACxD;;GACG,CAAA;EACN,CAAA,CACX;;AAEf,CACF;AAEA,aAAa,cAAc"}
1
+ {"version":3,"file":"DropdownMenu.mjs","names":[],"sources":["../../../src/base-ui/DropdownMenu/DropdownMenu.tsx"],"sourcesContent":["'use client';\n\nimport { Menu } from '@base-ui/react/menu';\nimport { cx } from 'antd-style';\nimport { memo, useCallback, useEffect, useMemo, useRef, useState } from 'react';\n\nimport { useNativeButton } from '@/hooks/useNativeButton';\nimport { parseTrigger } from '@/utils/parseTrigger';\n\nimport {\n DropdownMenuFooter,\n DropdownMenuHeader,\n DropdownMenuPopup,\n DropdownMenuPortal,\n DropdownMenuPositioner,\n DropdownMenuScrollViewport,\n DropdownMenuTrigger,\n} from './atoms';\nimport { renderDropdownMenuItems } from './renderItems';\nimport { styles } from './sharedStyle';\nimport type { DropdownMenuProps } from './type';\n\nconst DropdownMenu = memo<DropdownMenuProps>(\n ({\n children,\n defaultOpen,\n footer,\n header,\n iconAlign,\n iconSpaceMode,\n items,\n listItemHeight,\n nativeButton,\n onOpenChange,\n onOpenChangeComplete,\n open,\n placement = 'bottomLeft',\n popupProps,\n portalProps,\n positionerProps,\n trigger = 'click',\n triggerProps,\n virtual,\n ...rest\n }) => {\n const [uncontrolledOpen, setUncontrolledOpen] = useState(Boolean(defaultOpen));\n\n const { openOnHover } = useMemo(() => parseTrigger(trigger), [trigger]);\n const resolvedOpenOnHover = (triggerProps as any)?.openOnHover ?? openOnHover;\n\n useEffect(() => {\n if (open === undefined) return;\n setUncontrolledOpen(open);\n }, [open]);\n\n const handleOpenChange = useCallback(\n (nextOpen: boolean, details: Parameters<NonNullable<typeof onOpenChange>>[1]) => {\n onOpenChange?.(nextOpen, details);\n if (open === undefined) {\n setUncontrolledOpen(nextOpen);\n }\n },\n [onOpenChange, open],\n );\n\n const menuItemsRef = useRef<ReturnType<typeof renderDropdownMenuItems> | null>(null);\n const isOpen = open ?? uncontrolledOpen;\n const menuItems = useMemo(() => {\n if (isOpen) {\n const resolvedItems = typeof items === 'function' ? items() : items;\n const renderedItems = renderDropdownMenuItems(resolvedItems, [], {\n iconAlign,\n iconSpaceMode,\n });\n menuItemsRef.current = renderedItems;\n return renderedItems;\n }\n return menuItemsRef.current;\n }, [isOpen, items, iconAlign, iconSpaceMode]);\n const handleOpenChangeComplete = useCallback(\n (nextOpen: boolean) => {\n onOpenChangeComplete?.(nextOpen);\n if (!nextOpen) {\n menuItemsRef.current = null;\n }\n },\n [onOpenChangeComplete],\n );\n const { container: portalContainer, ...restPortalProps } = (portalProps ?? {}) as any;\n\n const { resolvedNativeButton } = useNativeButton({\n children,\n nativeButton,\n triggerNativeButton: triggerProps?.nativeButton,\n });\n\n const hasSlots = header != null || footer != null;\n\n const triggerElement = (\n <DropdownMenuTrigger\n {...triggerProps}\n nativeButton={resolvedNativeButton}\n openOnHover={resolvedOpenOnHover}\n >\n {children}\n </DropdownMenuTrigger>\n );\n\n return (\n <Menu.Root\n {...rest}\n defaultOpen={defaultOpen}\n modal={false}\n open={open}\n onOpenChange={handleOpenChange}\n onOpenChangeComplete={handleOpenChangeComplete}\n >\n {triggerElement}\n <DropdownMenuPortal container={portalContainer} {...restPortalProps}>\n <DropdownMenuPositioner\n {...positionerProps}\n hoverTrigger={resolvedOpenOnHover}\n placement={placement}\n >\n <DropdownMenuPopup\n {...popupProps}\n data-has-footer={footer == null ? undefined : ''}\n data-has-header={header == null ? undefined : ''}\n className={\n hasSlots\n ? (cx(styles.popupWithSlots, popupProps?.className as string) as any)\n : popupProps?.className\n }\n >\n {header == null ? null : <DropdownMenuHeader>{header}</DropdownMenuHeader>}\n {hasSlots || virtual ? (\n <DropdownMenuScrollViewport listItemHeight={listItemHeight} virtual={virtual}>\n {menuItems}\n </DropdownMenuScrollViewport>\n ) : (\n menuItems\n )}\n {footer == null ? null : <DropdownMenuFooter>{footer}</DropdownMenuFooter>}\n </DropdownMenuPopup>\n </DropdownMenuPositioner>\n </DropdownMenuPortal>\n </Menu.Root>\n );\n },\n);\n\nDropdownMenu.displayName = 'DropdownMenuV2';\n\nexport default DropdownMenu;\n"],"mappings":";;;;;;;;;;;AAsBA,MAAM,eAAe,MAClB,EACC,UACA,aACA,QACA,QACA,WACA,eACA,OACA,gBACA,cACA,cACA,sBACA,MACA,YAAY,cACZ,YACA,aACA,iBACA,UAAU,SACV,cACA,SACA,GAAG,WACC;CACJ,MAAM,CAAC,kBAAkB,uBAAuB,SAAS,QAAQ,WAAW,CAAC;CAE7E,MAAM,EAAE,gBAAgB,cAAc,aAAa,OAAO,GAAG,CAAC,OAAO,CAAC;CACtE,MAAM,sBAAuB,cAAsB,eAAe;CAElE,gBAAgB;EACd,IAAI,SAAS,KAAA,GAAW;EACxB,oBAAoB,IAAI;CAC1B,GAAG,CAAC,IAAI,CAAC;CAET,MAAM,mBAAmB,aACtB,UAAmB,YAA6D;EAC/E,eAAe,UAAU,OAAO;EAChC,IAAI,SAAS,KAAA,GACX,oBAAoB,QAAQ;CAEhC,GACA,CAAC,cAAc,IAAI,CACrB;CAEA,MAAM,eAAe,OAA0D,IAAI;CACnF,MAAM,SAAS,QAAQ;CACvB,MAAM,YAAY,cAAc;EAC9B,IAAI,QAAQ;GACV,MAAM,gBAAgB,OAAO,UAAU,aAAa,MAAM,IAAI;GAC9D,MAAM,gBAAgB,wBAAwB,eAAe,CAAC,GAAG;IAC/D;IACA;GACF,CAAC;GACD,aAAa,UAAU;GACvB,OAAO;EACT;EACA,OAAO,aAAa;CACtB,GAAG;EAAC;EAAQ;EAAO;EAAW;CAAa,CAAC;CAC5C,MAAM,2BAA2B,aAC9B,aAAsB;EACrB,uBAAuB,QAAQ;EAC/B,IAAI,CAAC,UACH,aAAa,UAAU;CAE3B,GACA,CAAC,oBAAoB,CACvB;CACA,MAAM,EAAE,WAAW,iBAAiB,GAAG,oBAAqB,eAAe,CAAC;CAE5E,MAAM,EAAE,yBAAyB,gBAAgB;EAC/C;EACA;EACA,qBAAqB,cAAc;CACrC,CAAC;CAED,MAAM,WAAW,UAAU,QAAQ,UAAU;CAE7C,MAAM,iBACJ,oBAAC,qBAAD;EACE,GAAI;EACJ,cAAc;EACd,aAAa;EAEZ;CACkB,CAAA;CAGvB,OACE,qBAAC,KAAK,MAAN;EACE,GAAI;EACS;EACb,OAAO;EACD;EACN,cAAc;EACd,sBAAsB;EANxB,UAAA,CAQG,gBACD,oBAAC,oBAAD;GAAoB,WAAW;GAAiB,GAAI;GAClD,UAAA,oBAAC,wBAAD;IACE,GAAI;IACJ,cAAc;IACH;IAEX,UAAA,qBAAC,mBAAD;KACE,GAAI;KACJ,mBAAiB,UAAU,OAAO,KAAA,IAAY;KAC9C,mBAAiB,UAAU,OAAO,KAAA,IAAY;KAC9C,WACE,WACK,GAAG,OAAO,gBAAgB,YAAY,SAAmB,IAC1D,YAAY;KAPpB,UAAA;MAUG,UAAU,OAAO,OAAO,oBAAC,oBAAD,EAAA,UAAqB,OAA2B,CAAA;MACxE,YAAY,UACX,oBAAC,4BAAD;OAA4C;OAAyB;OAClE,UAAA;MACyB,CAAA,IAE5B;MAED,UAAU,OAAO,OAAO,oBAAC,oBAAD,EAAA,UAAqB,OAA2B,CAAA;KACxD;;GACG,CAAA;EACN,CAAA,CACX;;AAEf,CACF;AAEA,aAAa,cAAc"}
@@ -1,3 +1,5 @@
1
+ import { VirtualListProps } from "../virtual/type.mjs";
2
+ import "../virtual/index.mjs";
1
3
  import { DropdownMenuPlacement } from "./type.mjs";
2
4
  import React from "react";
3
5
  import { Menu } from "@base-ui/react/menu";
@@ -45,9 +47,9 @@ declare const DropdownMenuFooter: {
45
47
  ({ className, ...rest }: DropdownMenuFooterProps): React.JSX.Element;
46
48
  displayName: string;
47
49
  };
48
- type DropdownMenuScrollViewportProps = React.HTMLAttributes<HTMLDivElement>;
50
+ type DropdownMenuScrollViewportProps = React.HTMLAttributes<HTMLDivElement> & VirtualListProps;
49
51
  declare const DropdownMenuScrollViewport: {
50
- ({ className, ...rest }: DropdownMenuScrollViewportProps): React.JSX.Element;
52
+ ({ children, className, getItemLabel, keepMounted, listItemHeight, virtual, ...rest }: DropdownMenuScrollViewportProps): React.JSX.Element;
51
53
  displayName: string;
52
54
  };
53
55
  type DropdownMenuItemProps = React.ComponentProps<typeof Menu.Item> & {
@@ -6,6 +6,7 @@ import { useAppElement } from "../../ThemeProvider/AppElementContext.mjs";
6
6
  import { CLASSNAMES } from "../../styles/classNames.mjs";
7
7
  import { placementMap } from "../../utils/placement.mjs";
8
8
  import Switch from "../Switch/Switch.mjs";
9
+ import { MenuVirtualList } from "../virtual/MenuVirtualList.mjs";
9
10
  import { useLayerZIndex } from "../zIndex/useLayerZIndex.mjs";
10
11
  import { styles } from "./sharedStyle.mjs";
11
12
  import { cloneElement, isValidElement, useCallback, useState } from "react";
@@ -111,21 +112,32 @@ DropdownMenuPopup.displayName = "DropdownMenuPopup";
111
112
  const DropdownMenuHeader = ({ className, ...rest }) => {
112
113
  return /* @__PURE__ */ jsx("div", {
113
114
  ...rest,
114
- className: cx(styles.header, className)
115
+ className: cx(styles.header, className),
116
+ "data-slot": "header"
115
117
  });
116
118
  };
117
119
  DropdownMenuHeader.displayName = "DropdownMenuHeader";
118
120
  const DropdownMenuFooter = ({ className, ...rest }) => {
119
121
  return /* @__PURE__ */ jsx("div", {
120
122
  ...rest,
121
- className: cx(styles.footer, className)
123
+ className: cx(styles.footer, className),
124
+ "data-slot": "footer"
122
125
  });
123
126
  };
124
127
  DropdownMenuFooter.displayName = "DropdownMenuFooter";
125
- const DropdownMenuScrollViewport = ({ className, ...rest }) => {
126
- return /* @__PURE__ */ jsx("div", {
128
+ const DropdownMenuScrollViewport = ({ children, className, getItemLabel, keepMounted, listItemHeight, virtual, ...rest }) => {
129
+ if (!virtual) return /* @__PURE__ */ jsx("div", {
127
130
  ...rest,
128
- className: cx(styles.slotViewport, className)
131
+ className: cx(styles.slotViewport, className),
132
+ children
133
+ });
134
+ return /* @__PURE__ */ jsx(MenuVirtualList, {
135
+ ...rest,
136
+ className,
137
+ getItemLabel,
138
+ itemSize: listItemHeight,
139
+ keepMounted,
140
+ children
129
141
  });
130
142
  };
131
143
  DropdownMenuScrollViewport.displayName = "DropdownMenuScrollViewport";
@@ -1 +1 @@
1
- {"version":3,"file":"atoms.mjs","names":[],"sources":["../../../src/base-ui/DropdownMenu/atoms.tsx"],"sourcesContent":["'use client';\n\nimport { Menu } from '@base-ui/react/menu';\nimport { mergeProps } from '@base-ui/react/merge-props';\nimport { cx } from 'antd-style';\nimport clsx from 'clsx';\nimport type React from 'react';\nimport { cloneElement, isValidElement, useCallback, useState } from 'react';\nimport { mergeRefs, useMergeRefs } from 'react-merge-refs';\n\nimport { getFloatingCollisionPadding } from '@/base-ui/floating';\nimport Switch from '@/base-ui/Switch';\nimport { FloatingLayerProvider } from '@/hooks/useFloatingLayer';\nimport { useNativeButton } from '@/hooks/useNativeButton';\nimport { CLASSNAMES } from '@/styles/classNames';\nimport { useAppElement } from '@/ThemeProvider';\nimport { placementMap } from '@/utils/placement';\n\nimport { useLayerZIndex } from '../zIndex';\nimport { styles } from './sharedStyle';\nimport { type DropdownMenuPlacement } from './type';\n\nexport const DropdownMenuRoot: typeof Menu.Root = (props) => <Menu.Root modal={false} {...props} />;\nexport const DropdownMenuSubmenuRoot = Menu.SubmenuRoot;\nexport const DropdownMenuCheckboxItemIndicator = Menu.CheckboxItemIndicator;\n\nconst mergeStateClassName = <TState,>(\n base: string,\n className: string | ((state: TState) => string | undefined) | undefined,\n) => {\n if (typeof className === 'function') return (state: TState) => cx(base, className(state));\n return cx(base, className);\n};\n\nexport type DropdownMenuTriggerProps = Omit<\n React.ComponentPropsWithRef<typeof Menu.Trigger>,\n 'children' | 'render'\n> & {\n children: React.ReactNode;\n};\n\nexport const DropdownMenuTrigger = ({\n children,\n className,\n nativeButton,\n ref: refProp,\n ...rest\n}: DropdownMenuTriggerProps) => {\n const { isNativeButtonTriggerElement, resolvedNativeButton } = useNativeButton({\n children,\n nativeButton,\n });\n\n const renderer = (props: any) => {\n // Base UI's trigger props include `type=\"button\"` by default.\n // If we render into a non-<button> element, that prop is invalid and can warn.\n const resolvedProps = (() => {\n if (isNativeButtonTriggerElement) return props as any;\n // eslint-disable-next-line unused-imports/no-unused-vars\n const { type, ...restProps } = props as any;\n return restProps;\n })();\n\n const mergedProps = mergeProps((children as any).props, resolvedProps);\n return cloneElement(children as any, {\n ...mergedProps,\n className: clsx(CLASSNAMES.DropdownMenuTrigger, className, mergedProps.className),\n ref: mergeRefs([(children as any).ref, (props as any).ref, refProp]),\n });\n };\n\n if (isValidElement(children)) {\n return <Menu.Trigger {...rest} nativeButton={resolvedNativeButton} render={renderer as any} />;\n }\n\n return (\n <Menu.Trigger\n {...rest}\n className={clsx(CLASSNAMES.DropdownMenuTrigger, className)}\n nativeButton={resolvedNativeButton}\n ref={refProp as any}\n >\n {children}\n </Menu.Trigger>\n );\n};\n\nDropdownMenuTrigger.displayName = 'DropdownMenuTrigger';\n\nexport type DropdownMenuPortalProps = React.ComponentProps<typeof Menu.Portal> & {\n /**\n * When `container` is not provided, it uses a shared container created by `usePortalContainer`.\n */\n container?: HTMLElement | null;\n};\n\nexport const DropdownMenuPortal = ({ container, ...rest }: DropdownMenuPortalProps) => {\n const appElement = useAppElement();\n return <Menu.Portal container={container ?? appElement ?? undefined} {...rest} />;\n};\n\nDropdownMenuPortal.displayName = 'DropdownMenuPortal';\n\nexport type DropdownMenuPositionerProps = React.ComponentProps<typeof Menu.Positioner> & {\n hoverTrigger?: boolean;\n placement?: DropdownMenuPlacement;\n};\n\nexport const DropdownMenuPositioner = ({\n className,\n collisionPadding,\n placement,\n hoverTrigger,\n align,\n side,\n sideOffset,\n children,\n style,\n ...rest\n}: DropdownMenuPositionerProps) => {\n const placementConfig = placement ? placementMap[placement] : undefined;\n const [positionerNode, setPositionerNode] = useState<HTMLDivElement | null>(null);\n\n const explicitZIndex =\n typeof style !== 'function' && style?.zIndex != null && typeof style.zIndex === 'number'\n ? style.zIndex\n : undefined;\n const { zIndex, ref: zRef } = useLayerZIndex<HTMLDivElement>('floating', explicitZIndex);\n const composedRef = useMergeRefs([setPositionerNode, zRef]);\n\n const resolvedStyle =\n typeof style === 'function'\n ? (state: any) => ({ zIndex, ...style(state) })\n : { zIndex, ...style };\n\n return (\n <Menu.Positioner\n {...rest}\n align={align ?? placementConfig?.align}\n className={mergeStateClassName(styles.positioner, className as any) as any}\n collisionPadding={collisionPadding ?? getFloatingCollisionPadding()}\n data-hover-trigger={hoverTrigger || undefined}\n data-placement={placement}\n ref={composedRef as any}\n side={side ?? placementConfig?.side}\n sideOffset={sideOffset ?? (placementConfig ? 6 : undefined)}\n style={resolvedStyle}\n >\n <FloatingLayerProvider value={positionerNode}>{children}</FloatingLayerProvider>\n </Menu.Positioner>\n );\n};\n\nDropdownMenuPositioner.displayName = 'DropdownMenuPositioner';\n\nexport type DropdownMenuPopupProps = React.ComponentProps<typeof Menu.Popup>;\n\nexport const DropdownMenuPopup = ({ className, ...rest }: DropdownMenuPopupProps) => {\n return (\n <Menu.Popup {...rest} className={mergeStateClassName(styles.popup, className as any) as any} />\n );\n};\n\nDropdownMenuPopup.displayName = 'DropdownMenuPopup';\n\nexport type DropdownMenuHeaderProps = React.HTMLAttributes<HTMLDivElement>;\n\nexport const DropdownMenuHeader = ({ className, ...rest }: DropdownMenuHeaderProps) => {\n return <div {...rest} className={cx(styles.header, className)} />;\n};\n\nDropdownMenuHeader.displayName = 'DropdownMenuHeader';\n\nexport type DropdownMenuFooterProps = React.HTMLAttributes<HTMLDivElement>;\n\nexport const DropdownMenuFooter = ({ className, ...rest }: DropdownMenuFooterProps) => {\n return <div {...rest} className={cx(styles.footer, className)} />;\n};\n\nDropdownMenuFooter.displayName = 'DropdownMenuFooter';\n\nexport type DropdownMenuScrollViewportProps = React.HTMLAttributes<HTMLDivElement>;\n\nexport const DropdownMenuScrollViewport = ({\n className,\n ...rest\n}: DropdownMenuScrollViewportProps) => {\n return <div {...rest} className={cx(styles.slotViewport, className)} />;\n};\n\nDropdownMenuScrollViewport.displayName = 'DropdownMenuScrollViewport';\n\nexport type DropdownMenuItemProps = React.ComponentProps<typeof Menu.Item> & { danger?: boolean };\n\nexport const DropdownMenuItem = ({ className, danger, ...rest }: DropdownMenuItemProps) => {\n return (\n <Menu.Item\n {...rest}\n className={(state) =>\n cx(\n styles.item,\n danger && styles.danger,\n typeof className === 'function' ? className(state) : className,\n )\n }\n />\n );\n};\n\nDropdownMenuItem.displayName = 'DropdownMenuItem';\n\nexport type DropdownMenuCheckboxItemProps = React.ComponentProps<typeof Menu.CheckboxItem> & {\n danger?: boolean;\n};\n\nexport const DropdownMenuCheckboxItemPrimitive = ({\n className,\n danger,\n ...rest\n}: DropdownMenuCheckboxItemProps) => {\n return (\n <Menu.CheckboxItem\n {...rest}\n className={(state) =>\n cx(\n styles.item,\n danger && styles.danger,\n typeof className === 'function' ? className(state) : className,\n )\n }\n />\n );\n};\n\nDropdownMenuCheckboxItemPrimitive.displayName = 'DropdownMenuCheckboxItemPrimitive';\n\nexport type DropdownMenuSeparatorProps = React.ComponentProps<typeof Menu.Separator>;\n\nexport const DropdownMenuSeparator = ({ className, ...rest }: DropdownMenuSeparatorProps) => {\n return (\n <Menu.Separator\n {...rest}\n className={(state) =>\n cx(styles.separator, typeof className === 'function' ? className(state) : className)\n }\n />\n );\n};\n\nDropdownMenuSeparator.displayName = 'DropdownMenuSeparator';\n\nexport const DropdownMenuGroup = Menu.Group;\n\nexport type DropdownMenuGroupLabelProps = React.ComponentProps<typeof Menu.GroupLabel>;\n\nexport const DropdownMenuGroupLabel = ({ className, ...rest }: DropdownMenuGroupLabelProps) => {\n return (\n <Menu.GroupLabel\n {...rest}\n className={(state) =>\n cx(styles.groupLabel, typeof className === 'function' ? className(state) : className)\n }\n />\n );\n};\n\nDropdownMenuGroupLabel.displayName = 'DropdownMenuGroupLabel';\n\nexport type DropdownMenuSubmenuTriggerProps = React.ComponentProps<typeof Menu.SubmenuTrigger> & {\n danger?: boolean;\n};\n\nexport const DropdownMenuSubmenuTrigger = ({\n className,\n danger,\n ...rest\n}: DropdownMenuSubmenuTriggerProps) => {\n return (\n <Menu.SubmenuTrigger\n {...rest}\n className={(state) =>\n cx(\n styles.item,\n danger && styles.danger,\n typeof className === 'function' ? className(state) : className,\n )\n }\n />\n );\n};\n\nDropdownMenuSubmenuTrigger.displayName = 'DropdownMenuSubmenuTrigger';\n\nexport type DropdownMenuItemContentProps = React.HTMLAttributes<HTMLDivElement>;\n\nexport const DropdownMenuItemContent = ({ className, ...rest }: DropdownMenuItemContentProps) => {\n return <div {...rest} className={cx(styles.itemContent, className)} />;\n};\n\nDropdownMenuItemContent.displayName = 'DropdownMenuItemContent';\n\nexport type DropdownMenuItemIconProps = React.HTMLAttributes<HTMLSpanElement>;\n\nexport const DropdownMenuItemIcon = ({ className, ...rest }: DropdownMenuItemIconProps) => {\n return <span {...rest} className={cx(styles.icon, className)} />;\n};\n\nDropdownMenuItemIcon.displayName = 'DropdownMenuItemIcon';\n\nexport type DropdownMenuItemLabelGroupProps = React.HTMLAttributes<HTMLDivElement>;\n\nexport const DropdownMenuItemLabelGroup = ({\n className,\n ...rest\n}: DropdownMenuItemLabelGroupProps) => {\n return <div {...rest} className={cx(styles.labelGroup, className)} />;\n};\n\nDropdownMenuItemLabelGroup.displayName = 'DropdownMenuItemLabelGroup';\n\nexport type DropdownMenuItemLabelProps = React.HTMLAttributes<HTMLSpanElement>;\n\nexport const DropdownMenuItemLabel = ({ className, ...rest }: DropdownMenuItemLabelProps) => {\n return <span {...rest} className={cx(styles.label, className)} />;\n};\n\nDropdownMenuItemLabel.displayName = 'DropdownMenuItemLabel';\n\nexport type DropdownMenuItemDescProps = React.HTMLAttributes<HTMLSpanElement>;\n\nexport const DropdownMenuItemDesc = ({ className, ...rest }: DropdownMenuItemDescProps) => {\n return <span {...rest} className={cx(styles.desc, className)} />;\n};\n\nDropdownMenuItemDesc.displayName = 'DropdownMenuItemDesc';\n\nexport type DropdownMenuItemExtraProps = React.HTMLAttributes<HTMLSpanElement>;\n\nexport const DropdownMenuItemExtra = ({ className, ...rest }: DropdownMenuItemExtraProps) => {\n return <span {...rest} className={cx(styles.extra, className)} />;\n};\n\nDropdownMenuItemExtra.displayName = 'DropdownMenuItemExtra';\n\nexport type DropdownMenuSubmenuArrowProps = React.HTMLAttributes<HTMLSpanElement>;\n\nexport const DropdownMenuSubmenuArrow = ({ className, ...rest }: DropdownMenuSubmenuArrowProps) => {\n return <span {...rest} className={cx(styles.submenuArrow, className)} />;\n};\n\nDropdownMenuSubmenuArrow.displayName = 'DropdownMenuSubmenuArrow';\n\nexport type DropdownMenuSwitchItemProps = Omit<\n React.ComponentProps<typeof Menu.Item>,\n 'onClick'\n> & {\n checked?: boolean;\n closeOnClick?: boolean;\n danger?: boolean;\n defaultChecked?: boolean;\n onCheckedChange?: (checked: boolean) => void;\n};\n\nexport const DropdownMenuSwitchItem = ({\n checked: checkedProp,\n className,\n closeOnClick = false,\n danger,\n defaultChecked,\n disabled,\n onCheckedChange,\n children,\n ...rest\n}: DropdownMenuSwitchItemProps) => {\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 <Menu.Item\n {...rest}\n closeOnClick={closeOnClick}\n disabled={disabled}\n className={(state) =>\n cx(\n styles.item,\n danger && styles.danger,\n typeof className === 'function' ? className(state) : className,\n )\n }\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 </Menu.Item>\n );\n};\n\nDropdownMenuSwitchItem.displayName = 'DropdownMenuSwitchItem';\n"],"mappings":"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"}
1
+ {"version":3,"file":"atoms.mjs","names":[],"sources":["../../../src/base-ui/DropdownMenu/atoms.tsx"],"sourcesContent":["'use client';\n\nimport { Menu } from '@base-ui/react/menu';\nimport { mergeProps } from '@base-ui/react/merge-props';\nimport { cx } from 'antd-style';\nimport clsx from 'clsx';\nimport type React from 'react';\nimport { cloneElement, isValidElement, useCallback, useState } from 'react';\nimport { mergeRefs, useMergeRefs } from 'react-merge-refs';\n\nimport { getFloatingCollisionPadding } from '@/base-ui/floating';\nimport Switch from '@/base-ui/Switch';\nimport { MenuVirtualList, type VirtualListProps } from '@/base-ui/virtual';\nimport { FloatingLayerProvider } from '@/hooks/useFloatingLayer';\nimport { useNativeButton } from '@/hooks/useNativeButton';\nimport { CLASSNAMES } from '@/styles/classNames';\nimport { useAppElement } from '@/ThemeProvider';\nimport { placementMap } from '@/utils/placement';\n\nimport { useLayerZIndex } from '../zIndex';\nimport { styles } from './sharedStyle';\nimport { type DropdownMenuPlacement } from './type';\n\nexport const DropdownMenuRoot: typeof Menu.Root = (props) => <Menu.Root modal={false} {...props} />;\nexport const DropdownMenuSubmenuRoot = Menu.SubmenuRoot;\nexport const DropdownMenuCheckboxItemIndicator = Menu.CheckboxItemIndicator;\n\nconst mergeStateClassName = <TState,>(\n base: string,\n className: string | ((state: TState) => string | undefined) | undefined,\n) => {\n if (typeof className === 'function') return (state: TState) => cx(base, className(state));\n return cx(base, className);\n};\n\nexport type DropdownMenuTriggerProps = Omit<\n React.ComponentPropsWithRef<typeof Menu.Trigger>,\n 'children' | 'render'\n> & {\n children: React.ReactNode;\n};\n\nexport const DropdownMenuTrigger = ({\n children,\n className,\n nativeButton,\n ref: refProp,\n ...rest\n}: DropdownMenuTriggerProps) => {\n const { isNativeButtonTriggerElement, resolvedNativeButton } = useNativeButton({\n children,\n nativeButton,\n });\n\n const renderer = (props: any) => {\n // Base UI's trigger props include `type=\"button\"` by default.\n // If we render into a non-<button> element, that prop is invalid and can warn.\n const resolvedProps = (() => {\n if (isNativeButtonTriggerElement) return props as any;\n // eslint-disable-next-line unused-imports/no-unused-vars\n const { type, ...restProps } = props as any;\n return restProps;\n })();\n\n const mergedProps = mergeProps((children as any).props, resolvedProps);\n return cloneElement(children as any, {\n ...mergedProps,\n className: clsx(CLASSNAMES.DropdownMenuTrigger, className, mergedProps.className),\n ref: mergeRefs([(children as any).ref, (props as any).ref, refProp]),\n });\n };\n\n if (isValidElement(children)) {\n return <Menu.Trigger {...rest} nativeButton={resolvedNativeButton} render={renderer as any} />;\n }\n\n return (\n <Menu.Trigger\n {...rest}\n className={clsx(CLASSNAMES.DropdownMenuTrigger, className)}\n nativeButton={resolvedNativeButton}\n ref={refProp as any}\n >\n {children}\n </Menu.Trigger>\n );\n};\n\nDropdownMenuTrigger.displayName = 'DropdownMenuTrigger';\n\nexport type DropdownMenuPortalProps = React.ComponentProps<typeof Menu.Portal> & {\n /**\n * When `container` is not provided, it uses a shared container created by `usePortalContainer`.\n */\n container?: HTMLElement | null;\n};\n\nexport const DropdownMenuPortal = ({ container, ...rest }: DropdownMenuPortalProps) => {\n const appElement = useAppElement();\n return <Menu.Portal container={container ?? appElement ?? undefined} {...rest} />;\n};\n\nDropdownMenuPortal.displayName = 'DropdownMenuPortal';\n\nexport type DropdownMenuPositionerProps = React.ComponentProps<typeof Menu.Positioner> & {\n hoverTrigger?: boolean;\n placement?: DropdownMenuPlacement;\n};\n\nexport const DropdownMenuPositioner = ({\n className,\n collisionPadding,\n placement,\n hoverTrigger,\n align,\n side,\n sideOffset,\n children,\n style,\n ...rest\n}: DropdownMenuPositionerProps) => {\n const placementConfig = placement ? placementMap[placement] : undefined;\n const [positionerNode, setPositionerNode] = useState<HTMLDivElement | null>(null);\n\n const explicitZIndex =\n typeof style !== 'function' && style?.zIndex != null && typeof style.zIndex === 'number'\n ? style.zIndex\n : undefined;\n const { zIndex, ref: zRef } = useLayerZIndex<HTMLDivElement>('floating', explicitZIndex);\n const composedRef = useMergeRefs([setPositionerNode, zRef]);\n\n const resolvedStyle =\n typeof style === 'function'\n ? (state: any) => ({ zIndex, ...style(state) })\n : { zIndex, ...style };\n\n return (\n <Menu.Positioner\n {...rest}\n align={align ?? placementConfig?.align}\n className={mergeStateClassName(styles.positioner, className as any) as any}\n collisionPadding={collisionPadding ?? getFloatingCollisionPadding()}\n data-hover-trigger={hoverTrigger || undefined}\n data-placement={placement}\n ref={composedRef as any}\n side={side ?? placementConfig?.side}\n sideOffset={sideOffset ?? (placementConfig ? 6 : undefined)}\n style={resolvedStyle}\n >\n <FloatingLayerProvider value={positionerNode}>{children}</FloatingLayerProvider>\n </Menu.Positioner>\n );\n};\n\nDropdownMenuPositioner.displayName = 'DropdownMenuPositioner';\n\nexport type DropdownMenuPopupProps = React.ComponentProps<typeof Menu.Popup>;\n\nexport const DropdownMenuPopup = ({ className, ...rest }: DropdownMenuPopupProps) => {\n return (\n <Menu.Popup {...rest} className={mergeStateClassName(styles.popup, className as any) as any} />\n );\n};\n\nDropdownMenuPopup.displayName = 'DropdownMenuPopup';\n\nexport type DropdownMenuHeaderProps = React.HTMLAttributes<HTMLDivElement>;\n\nexport const DropdownMenuHeader = ({ className, ...rest }: DropdownMenuHeaderProps) => {\n return <div {...rest} className={cx(styles.header, className)} data-slot=\"header\" />;\n};\n\nDropdownMenuHeader.displayName = 'DropdownMenuHeader';\n\nexport type DropdownMenuFooterProps = React.HTMLAttributes<HTMLDivElement>;\n\nexport const DropdownMenuFooter = ({ className, ...rest }: DropdownMenuFooterProps) => {\n return <div {...rest} className={cx(styles.footer, className)} data-slot=\"footer\" />;\n};\n\nDropdownMenuFooter.displayName = 'DropdownMenuFooter';\n\nexport type DropdownMenuScrollViewportProps = React.HTMLAttributes<HTMLDivElement> &\n VirtualListProps;\n\nexport const DropdownMenuScrollViewport = ({\n children,\n className,\n getItemLabel,\n keepMounted,\n listItemHeight,\n virtual,\n ...rest\n}: DropdownMenuScrollViewportProps) => {\n if (!virtual) {\n return (\n <div {...rest} className={cx(styles.slotViewport, className)}>\n {children}\n </div>\n );\n }\n\n return (\n <MenuVirtualList\n {...rest}\n className={className}\n getItemLabel={getItemLabel}\n itemSize={listItemHeight}\n keepMounted={keepMounted}\n >\n {children}\n </MenuVirtualList>\n );\n};\n\nDropdownMenuScrollViewport.displayName = 'DropdownMenuScrollViewport';\n\nexport type DropdownMenuItemProps = React.ComponentProps<typeof Menu.Item> & { danger?: boolean };\n\nexport const DropdownMenuItem = ({ className, danger, ...rest }: DropdownMenuItemProps) => {\n return (\n <Menu.Item\n {...rest}\n className={(state) =>\n cx(\n styles.item,\n danger && styles.danger,\n typeof className === 'function' ? className(state) : className,\n )\n }\n />\n );\n};\n\nDropdownMenuItem.displayName = 'DropdownMenuItem';\n\nexport type DropdownMenuCheckboxItemProps = React.ComponentProps<typeof Menu.CheckboxItem> & {\n danger?: boolean;\n};\n\nexport const DropdownMenuCheckboxItemPrimitive = ({\n className,\n danger,\n ...rest\n}: DropdownMenuCheckboxItemProps) => {\n return (\n <Menu.CheckboxItem\n {...rest}\n className={(state) =>\n cx(\n styles.item,\n danger && styles.danger,\n typeof className === 'function' ? className(state) : className,\n )\n }\n />\n );\n};\n\nDropdownMenuCheckboxItemPrimitive.displayName = 'DropdownMenuCheckboxItemPrimitive';\n\nexport type DropdownMenuSeparatorProps = React.ComponentProps<typeof Menu.Separator>;\n\nexport const DropdownMenuSeparator = ({ className, ...rest }: DropdownMenuSeparatorProps) => {\n return (\n <Menu.Separator\n {...rest}\n className={(state) =>\n cx(styles.separator, typeof className === 'function' ? className(state) : className)\n }\n />\n );\n};\n\nDropdownMenuSeparator.displayName = 'DropdownMenuSeparator';\n\nexport const DropdownMenuGroup = Menu.Group;\n\nexport type DropdownMenuGroupLabelProps = React.ComponentProps<typeof Menu.GroupLabel>;\n\nexport const DropdownMenuGroupLabel = ({ className, ...rest }: DropdownMenuGroupLabelProps) => {\n return (\n <Menu.GroupLabel\n {...rest}\n className={(state) =>\n cx(styles.groupLabel, typeof className === 'function' ? className(state) : className)\n }\n />\n );\n};\n\nDropdownMenuGroupLabel.displayName = 'DropdownMenuGroupLabel';\n\nexport type DropdownMenuSubmenuTriggerProps = React.ComponentProps<typeof Menu.SubmenuTrigger> & {\n danger?: boolean;\n};\n\nexport const DropdownMenuSubmenuTrigger = ({\n className,\n danger,\n ...rest\n}: DropdownMenuSubmenuTriggerProps) => {\n return (\n <Menu.SubmenuTrigger\n {...rest}\n className={(state) =>\n cx(\n styles.item,\n danger && styles.danger,\n typeof className === 'function' ? className(state) : className,\n )\n }\n />\n );\n};\n\nDropdownMenuSubmenuTrigger.displayName = 'DropdownMenuSubmenuTrigger';\n\nexport type DropdownMenuItemContentProps = React.HTMLAttributes<HTMLDivElement>;\n\nexport const DropdownMenuItemContent = ({ className, ...rest }: DropdownMenuItemContentProps) => {\n return <div {...rest} className={cx(styles.itemContent, className)} />;\n};\n\nDropdownMenuItemContent.displayName = 'DropdownMenuItemContent';\n\nexport type DropdownMenuItemIconProps = React.HTMLAttributes<HTMLSpanElement>;\n\nexport const DropdownMenuItemIcon = ({ className, ...rest }: DropdownMenuItemIconProps) => {\n return <span {...rest} className={cx(styles.icon, className)} />;\n};\n\nDropdownMenuItemIcon.displayName = 'DropdownMenuItemIcon';\n\nexport type DropdownMenuItemLabelGroupProps = React.HTMLAttributes<HTMLDivElement>;\n\nexport const DropdownMenuItemLabelGroup = ({\n className,\n ...rest\n}: DropdownMenuItemLabelGroupProps) => {\n return <div {...rest} className={cx(styles.labelGroup, className)} />;\n};\n\nDropdownMenuItemLabelGroup.displayName = 'DropdownMenuItemLabelGroup';\n\nexport type DropdownMenuItemLabelProps = React.HTMLAttributes<HTMLSpanElement>;\n\nexport const DropdownMenuItemLabel = ({ className, ...rest }: DropdownMenuItemLabelProps) => {\n return <span {...rest} className={cx(styles.label, className)} />;\n};\n\nDropdownMenuItemLabel.displayName = 'DropdownMenuItemLabel';\n\nexport type DropdownMenuItemDescProps = React.HTMLAttributes<HTMLSpanElement>;\n\nexport const DropdownMenuItemDesc = ({ className, ...rest }: DropdownMenuItemDescProps) => {\n return <span {...rest} className={cx(styles.desc, className)} />;\n};\n\nDropdownMenuItemDesc.displayName = 'DropdownMenuItemDesc';\n\nexport type DropdownMenuItemExtraProps = React.HTMLAttributes<HTMLSpanElement>;\n\nexport const DropdownMenuItemExtra = ({ className, ...rest }: DropdownMenuItemExtraProps) => {\n return <span {...rest} className={cx(styles.extra, className)} />;\n};\n\nDropdownMenuItemExtra.displayName = 'DropdownMenuItemExtra';\n\nexport type DropdownMenuSubmenuArrowProps = React.HTMLAttributes<HTMLSpanElement>;\n\nexport const DropdownMenuSubmenuArrow = ({ className, ...rest }: DropdownMenuSubmenuArrowProps) => {\n return <span {...rest} className={cx(styles.submenuArrow, className)} />;\n};\n\nDropdownMenuSubmenuArrow.displayName = 'DropdownMenuSubmenuArrow';\n\nexport type DropdownMenuSwitchItemProps = Omit<\n React.ComponentProps<typeof Menu.Item>,\n 'onClick'\n> & {\n checked?: boolean;\n closeOnClick?: boolean;\n danger?: boolean;\n defaultChecked?: boolean;\n onCheckedChange?: (checked: boolean) => void;\n};\n\nexport const DropdownMenuSwitchItem = ({\n checked: checkedProp,\n className,\n closeOnClick = false,\n danger,\n defaultChecked,\n disabled,\n onCheckedChange,\n children,\n ...rest\n}: DropdownMenuSwitchItemProps) => {\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 <Menu.Item\n {...rest}\n closeOnClick={closeOnClick}\n disabled={disabled}\n className={(state) =>\n cx(\n styles.item,\n danger && styles.danger,\n typeof className === 'function' ? className(state) : className,\n )\n }\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 </Menu.Item>\n );\n};\n\nDropdownMenuSwitchItem.displayName = 'DropdownMenuSwitchItem';\n"],"mappings":"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"}
@@ -28,12 +28,23 @@ const styles = createStaticStyles(({ css, cssVar }) => ({
28
28
  padding-block: 8px;
29
29
  padding-inline: 12px;
30
30
  border-block-start: 1px solid ${cssVar.colorBorder};
31
+
32
+ /* A menu item pinned in a slot keeps the same inset as the rows above it. */
33
+ &:has(> [role^='menuitem']) {
34
+ padding-block: 4px;
35
+ padding-inline: 0;
36
+ }
31
37
  `,
32
38
  header: css`
33
39
  flex-shrink: 0;
34
40
  padding-block: 8px;
35
41
  padding-inline: 12px;
36
42
  border-block-end: 1px solid ${cssVar.colorBorder};
43
+
44
+ &:has(> [role^='menuitem']) {
45
+ padding-block: 4px;
46
+ padding-inline: 0;
47
+ }
37
48
  `,
38
49
  groupLabel: css`
39
50
  user-select: none;
@@ -164,11 +175,13 @@ const styles = createStaticStyles(({ css, cssVar }) => ({
164
175
  white-space: nowrap;
165
176
  `,
166
177
  popup: css`
178
+ --lobe-menu-popup-padding: 4px;
179
+
167
180
  overflow-y: auto;
168
181
 
169
182
  min-width: 220px;
170
183
  max-height: var(--available-height);
171
- padding: 4px;
184
+ padding: var(--lobe-menu-popup-padding);
172
185
  border-radius: ${cssVar.borderRadius};
173
186
 
174
187
  background: ${cssVar.colorBgElevated};
@@ -178,14 +191,24 @@ const styles = createStaticStyles(({ css, cssVar }) => ({
178
191
  0 4px 12px 0 rgb(0 0 0 / 8%),
179
192
  0 1px 3px 0 rgb(0 0 0 / 6%);
180
193
 
181
- &[data-has-header] {
194
+ &[data-has-header],
195
+ &:has(> [data-slot='header']) {
182
196
  padding-block-start: 0;
183
197
  }
184
198
 
185
- &[data-has-footer] {
199
+ &[data-has-footer],
200
+ &:has(> [data-slot='footer']) {
186
201
  padding-block-end: 0;
187
202
  }
188
203
 
204
+ &:has(> [data-virtual]) {
205
+ --lobe-virtual-scroll-inset: var(--lobe-menu-popup-padding);
206
+
207
+ overflow: hidden;
208
+ display: flex;
209
+ flex-direction: column;
210
+ }
211
+
189
212
  /* Base UI moves data-highlighted with the arrow keys, but :hover keeps painting
190
213
  whatever the resting cursor sits on, so two items light up at once. */
191
214
  &:has([data-highlighted]) {
@@ -1 +1 @@
1
- {"version":3,"file":"sharedStyle.mjs","names":[],"sources":["../../../src/base-ui/DropdownMenu/sharedStyle.ts"],"sourcesContent":["import { createStaticStyles } from 'antd-style';\n\nexport const styles = createStaticStyles(({ css, cssVar }) => ({\n danger: css`\n --lobe-menu-icon-color: ${cssVar.colorError};\n\n color: ${cssVar.colorError} !important;\n\n &:hover {\n background: ${cssVar.colorErrorBg} !important;\n }\n `,\n\n empty: css`\n cursor: default;\n font-style: italic;\n color: ${cssVar.colorTextTertiary};\n `,\n\n extra: css`\n margin-inline-start: auto;\n padding-inline-start: 16px;\n\n font-family: ${cssVar.fontFamilyCode};\n font-size: 12px;\n color: ${cssVar.colorTextTertiary};\n `,\n\n footer: css`\n flex-shrink: 0;\n padding-block: 8px;\n padding-inline: 12px;\n border-block-start: 1px solid ${cssVar.colorBorder};\n `,\n\n header: css`\n flex-shrink: 0;\n padding-block: 8px;\n padding-inline: 12px;\n border-block-end: 1px solid ${cssVar.colorBorder};\n `,\n\n groupLabel: css`\n user-select: none;\n\n padding-block: 8px 4px;\n padding-inline: 12px;\n\n font-size: 10px;\n font-weight: 600;\n line-height: 14px;\n color: ${cssVar.colorTextTertiary};\n text-transform: uppercase;\n letter-spacing: 0.6px;\n\n [role='group']:first-child > & {\n padding-block-start: 4px;\n }\n `,\n\n icon: css`\n display: flex;\n flex-shrink: 0;\n align-items: center;\n justify-content: center;\n\n width: 14px;\n height: 14px;\n margin-inline-end: 12px;\n\n color: var(--lobe-menu-icon-color, ${cssVar.colorTextSecondary});\n\n & svg {\n width: 100%;\n height: 100%;\n }\n `,\n\n item: css`\n user-select: none;\n\n position: relative;\n\n overflow: hidden;\n display: flex;\n align-items: center;\n\n width: 100%;\n min-height: 32px;\n padding-block: 6px;\n padding-inline: 12px;\n border-radius: ${cssVar.borderRadiusSM};\n\n font-size: 14px;\n line-height: 20px;\n color: ${cssVar.colorText};\n\n outline: none;\n\n transition: all 150ms ${cssVar.motionEaseOut};\n\n &:hover {\n background: ${cssVar.colorFillTertiary};\n }\n\n &:active {\n background: ${cssVar.colorFillSecondary};\n }\n\n &[data-disabled] {\n cursor: not-allowed;\n color: ${cssVar.colorTextDisabled};\n opacity: 0.5;\n\n &:hover {\n background: transparent;\n }\n }\n\n &[data-highlighted]:not([data-disabled]) {\n background: ${cssVar.colorFillTertiary};\n }\n\n &[data-state='open']:not([data-disabled]),\n &[data-open]:not([data-disabled]),\n &[aria-expanded='true']:not([data-disabled]) {\n background: ${cssVar.colorFillTertiary};\n }\n `,\n\n itemContent: css`\n display: flex;\n flex: 1;\n gap: 0;\n align-items: center;\n `,\n\n itemContentAlignStart: css`\n align-items: flex-start;\n `,\n\n iconAlignStart: css`\n align-self: flex-start;\n margin-block-start: 2px;\n `,\n\n label: css`\n overflow: hidden;\n flex: 1;\n text-overflow: ellipsis;\n white-space: nowrap;\n\n & a,\n & a:visited,\n & a:hover,\n & a:active {\n color: inherit;\n }\n `,\n\n labelGroup: css`\n overflow: hidden;\n display: flex;\n flex: 1;\n flex-direction: column;\n\n min-width: 0;\n `,\n\n desc: css`\n overflow: hidden;\n\n font-size: 12px;\n line-height: 16px;\n color: ${cssVar.colorTextTertiary};\n text-overflow: ellipsis;\n white-space: nowrap;\n `,\n\n popup: css`\n overflow-y: auto;\n\n min-width: 220px;\n max-height: var(--available-height);\n padding: 4px;\n border-radius: ${cssVar.borderRadius};\n\n background: ${cssVar.colorBgElevated};\n outline: none;\n box-shadow:\n 0 0 0 1px ${cssVar.colorBorder},\n 0 4px 12px 0 rgb(0 0 0 / 8%),\n 0 1px 3px 0 rgb(0 0 0 / 6%);\n\n &[data-has-header] {\n padding-block-start: 0;\n }\n\n &[data-has-footer] {\n padding-block-end: 0;\n }\n\n /* Base UI moves data-highlighted with the arrow keys, but :hover keeps painting\n whatever the resting cursor sits on, so two items light up at once. */\n &:has([data-highlighted]) {\n [role^='menuitem']:hover:not([data-highlighted]),\n [role='option']:hover:not([data-highlighted]) {\n background: transparent !important;\n }\n }\n `,\n\n popupWithSlots: css`\n overflow: hidden;\n display: flex;\n flex-direction: column;\n max-height: var(--available-height);\n `,\n\n slotViewport: css`\n overflow-y: auto;\n flex: 1;\n min-height: 0;\n `,\n\n positioner: css`\n --lobe-dropdown-animation-duration: 140ms;\n --lobe-dropdown-animation-scale-y: 0.92;\n --lobe-dropdown-animation-ease-in: ease-in;\n --lobe-dropdown-animation-ease-out: ${cssVar.motionEaseOut};\n\n z-index: 1100;\n\n & > * {\n will-change: opacity, transform;\n transform-origin: var(--transform-origin);\n animation: none;\n }\n\n &[data-open] > * {\n transform: scaleY(1);\n opacity: 1;\n transition:\n opacity var(--lobe-dropdown-animation-duration) var(--lobe-dropdown-animation-ease-out),\n transform var(--lobe-dropdown-animation-duration) var(--lobe-dropdown-animation-ease-out);\n }\n\n &[data-open] > *[data-starting-style] {\n transform: scaleY(var(--lobe-dropdown-animation-scale-y));\n opacity: 0;\n }\n\n &[data-closed] > * {\n transform: scaleY(var(--lobe-dropdown-animation-scale-y));\n opacity: 0;\n transition:\n opacity var(--lobe-dropdown-animation-duration) var(--lobe-dropdown-animation-ease-in),\n transform var(--lobe-dropdown-animation-duration) var(--lobe-dropdown-animation-ease-in);\n }\n\n &[data-hover-trigger] {\n --lobe-dropdown-animation-duration: 140ms;\n }\n\n &[data-submenu],\n &[data-nested] {\n --lobe-dropdown-animation-duration: 0ms;\n --lobe-dropdown-animation-scale-y: 1;\n\n z-index: 1199;\n }\n\n &[data-side='left'],\n &[data-side='right'] {\n --lobe-dropdown-animation-duration: 0ms;\n --lobe-dropdown-animation-scale-y: 1;\n }\n `,\n\n separator: css`\n height: 1px;\n margin-block: 4px;\n margin-inline: 0;\n background: ${cssVar.colorBorder};\n `,\n\n submenuArrow: css`\n display: flex;\n flex-shrink: 0;\n align-items: center;\n justify-content: center;\n\n width: 16px;\n height: 16px;\n margin-inline-start: 8px;\n\n color: var(--lobe-menu-icon-color, ${cssVar.colorTextSecondary});\n\n & svg {\n width: 12px;\n height: 12px;\n }\n `,\n}));\n"],"mappings":";;AAEA,MAAa,SAAS,oBAAoB,EAAE,KAAK,cAAc;CAC7D,QAAQ,GAAG;8BACiB,OAAO,WAAW;;aAEnC,OAAO,WAAW;;;oBAGX,OAAO,aAAa;;;CAItC,OAAO,GAAG;;;aAGC,OAAO,kBAAkB;;CAGpC,OAAO,GAAG;;;;mBAIO,OAAO,eAAe;;aAE5B,OAAO,kBAAkB;;CAGpC,QAAQ,GAAG;;;;oCAIuB,OAAO,YAAY;;CAGrD,QAAQ,GAAG;;;;kCAIqB,OAAO,YAAY;;CAGnD,YAAY,GAAG;;;;;;;;;aASJ,OAAO,kBAAkB;;;;;;;;CASpC,MAAM,GAAG;;;;;;;;;;yCAU8B,OAAO,mBAAmB;;;;;;;CAQjE,MAAM,GAAG;;;;;;;;;;;;;qBAaU,OAAO,eAAe;;;;aAI9B,OAAO,UAAU;;;;4BAIF,OAAO,cAAc;;;oBAG7B,OAAO,kBAAkB;;;;oBAIzB,OAAO,mBAAmB;;;;;eAK/B,OAAO,kBAAkB;;;;;;;;;oBASpB,OAAO,kBAAkB;;;;;;oBAMzB,OAAO,kBAAkB;;;CAI3C,aAAa,GAAG;;;;;;CAOhB,uBAAuB,GAAG;;;CAI1B,gBAAgB,GAAG;;;;CAKnB,OAAO,GAAG;;;;;;;;;;;;;CAcV,YAAY,GAAG;;;;;;;;CASf,MAAM,GAAG;;;;;aAKE,OAAO,kBAAkB;;;;CAKpC,OAAO,GAAG;;;;;;qBAMS,OAAO,aAAa;;kBAEvB,OAAO,gBAAgB;;;kBAGvB,OAAO,YAAY;;;;;;;;;;;;;;;;;;;;;CAsBnC,gBAAgB,GAAG;;;;;;CAOnB,cAAc,GAAG;;;;;CAMjB,YAAY,GAAG;;;;0CAIyB,OAAO,cAAc;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAkD7D,WAAW,GAAG;;;;kBAIE,OAAO,YAAY;;CAGnC,cAAc,GAAG;;;;;;;;;;yCAUsB,OAAO,mBAAmB;;;;;;;AAOnE,EAAE"}
1
+ {"version":3,"file":"sharedStyle.mjs","names":[],"sources":["../../../src/base-ui/DropdownMenu/sharedStyle.ts"],"sourcesContent":["import { createStaticStyles } from 'antd-style';\n\nexport const styles = createStaticStyles(({ css, cssVar }) => ({\n danger: css`\n --lobe-menu-icon-color: ${cssVar.colorError};\n\n color: ${cssVar.colorError} !important;\n\n &:hover {\n background: ${cssVar.colorErrorBg} !important;\n }\n `,\n\n empty: css`\n cursor: default;\n font-style: italic;\n color: ${cssVar.colorTextTertiary};\n `,\n\n extra: css`\n margin-inline-start: auto;\n padding-inline-start: 16px;\n\n font-family: ${cssVar.fontFamilyCode};\n font-size: 12px;\n color: ${cssVar.colorTextTertiary};\n `,\n\n footer: css`\n flex-shrink: 0;\n padding-block: 8px;\n padding-inline: 12px;\n border-block-start: 1px solid ${cssVar.colorBorder};\n\n /* A menu item pinned in a slot keeps the same inset as the rows above it. */\n &:has(> [role^='menuitem']) {\n padding-block: 4px;\n padding-inline: 0;\n }\n `,\n\n header: css`\n flex-shrink: 0;\n padding-block: 8px;\n padding-inline: 12px;\n border-block-end: 1px solid ${cssVar.colorBorder};\n\n &:has(> [role^='menuitem']) {\n padding-block: 4px;\n padding-inline: 0;\n }\n `,\n\n groupLabel: css`\n user-select: none;\n\n padding-block: 8px 4px;\n padding-inline: 12px;\n\n font-size: 10px;\n font-weight: 600;\n line-height: 14px;\n color: ${cssVar.colorTextTertiary};\n text-transform: uppercase;\n letter-spacing: 0.6px;\n\n [role='group']:first-child > & {\n padding-block-start: 4px;\n }\n `,\n\n icon: css`\n display: flex;\n flex-shrink: 0;\n align-items: center;\n justify-content: center;\n\n width: 14px;\n height: 14px;\n margin-inline-end: 12px;\n\n color: var(--lobe-menu-icon-color, ${cssVar.colorTextSecondary});\n\n & svg {\n width: 100%;\n height: 100%;\n }\n `,\n\n item: css`\n user-select: none;\n\n position: relative;\n\n overflow: hidden;\n display: flex;\n align-items: center;\n\n width: 100%;\n min-height: 32px;\n padding-block: 6px;\n padding-inline: 12px;\n border-radius: ${cssVar.borderRadiusSM};\n\n font-size: 14px;\n line-height: 20px;\n color: ${cssVar.colorText};\n\n outline: none;\n\n transition: all 150ms ${cssVar.motionEaseOut};\n\n &:hover {\n background: ${cssVar.colorFillTertiary};\n }\n\n &:active {\n background: ${cssVar.colorFillSecondary};\n }\n\n &[data-disabled] {\n cursor: not-allowed;\n color: ${cssVar.colorTextDisabled};\n opacity: 0.5;\n\n &:hover {\n background: transparent;\n }\n }\n\n &[data-highlighted]:not([data-disabled]) {\n background: ${cssVar.colorFillTertiary};\n }\n\n &[data-state='open']:not([data-disabled]),\n &[data-open]:not([data-disabled]),\n &[aria-expanded='true']:not([data-disabled]) {\n background: ${cssVar.colorFillTertiary};\n }\n `,\n\n itemContent: css`\n display: flex;\n flex: 1;\n gap: 0;\n align-items: center;\n `,\n\n itemContentAlignStart: css`\n align-items: flex-start;\n `,\n\n iconAlignStart: css`\n align-self: flex-start;\n margin-block-start: 2px;\n `,\n\n label: css`\n overflow: hidden;\n flex: 1;\n text-overflow: ellipsis;\n white-space: nowrap;\n\n & a,\n & a:visited,\n & a:hover,\n & a:active {\n color: inherit;\n }\n `,\n\n labelGroup: css`\n overflow: hidden;\n display: flex;\n flex: 1;\n flex-direction: column;\n\n min-width: 0;\n `,\n\n desc: css`\n overflow: hidden;\n\n font-size: 12px;\n line-height: 16px;\n color: ${cssVar.colorTextTertiary};\n text-overflow: ellipsis;\n white-space: nowrap;\n `,\n\n popup: css`\n --lobe-menu-popup-padding: 4px;\n\n overflow-y: auto;\n\n min-width: 220px;\n max-height: var(--available-height);\n padding: var(--lobe-menu-popup-padding);\n border-radius: ${cssVar.borderRadius};\n\n background: ${cssVar.colorBgElevated};\n outline: none;\n box-shadow:\n 0 0 0 1px ${cssVar.colorBorder},\n 0 4px 12px 0 rgb(0 0 0 / 8%),\n 0 1px 3px 0 rgb(0 0 0 / 6%);\n\n &[data-has-header],\n &:has(> [data-slot='header']) {\n padding-block-start: 0;\n }\n\n &[data-has-footer],\n &:has(> [data-slot='footer']) {\n padding-block-end: 0;\n }\n\n &:has(> [data-virtual]) {\n --lobe-virtual-scroll-inset: var(--lobe-menu-popup-padding);\n\n overflow: hidden;\n display: flex;\n flex-direction: column;\n }\n\n /* Base UI moves data-highlighted with the arrow keys, but :hover keeps painting\n whatever the resting cursor sits on, so two items light up at once. */\n &:has([data-highlighted]) {\n [role^='menuitem']:hover:not([data-highlighted]),\n [role='option']:hover:not([data-highlighted]) {\n background: transparent !important;\n }\n }\n `,\n\n popupWithSlots: css`\n overflow: hidden;\n display: flex;\n flex-direction: column;\n max-height: var(--available-height);\n `,\n\n slotViewport: css`\n overflow-y: auto;\n flex: 1;\n min-height: 0;\n `,\n\n positioner: css`\n --lobe-dropdown-animation-duration: 140ms;\n --lobe-dropdown-animation-scale-y: 0.92;\n --lobe-dropdown-animation-ease-in: ease-in;\n --lobe-dropdown-animation-ease-out: ${cssVar.motionEaseOut};\n\n z-index: 1100;\n\n & > * {\n will-change: opacity, transform;\n transform-origin: var(--transform-origin);\n animation: none;\n }\n\n &[data-open] > * {\n transform: scaleY(1);\n opacity: 1;\n transition:\n opacity var(--lobe-dropdown-animation-duration) var(--lobe-dropdown-animation-ease-out),\n transform var(--lobe-dropdown-animation-duration) var(--lobe-dropdown-animation-ease-out);\n }\n\n &[data-open] > *[data-starting-style] {\n transform: scaleY(var(--lobe-dropdown-animation-scale-y));\n opacity: 0;\n }\n\n &[data-closed] > * {\n transform: scaleY(var(--lobe-dropdown-animation-scale-y));\n opacity: 0;\n transition:\n opacity var(--lobe-dropdown-animation-duration) var(--lobe-dropdown-animation-ease-in),\n transform var(--lobe-dropdown-animation-duration) var(--lobe-dropdown-animation-ease-in);\n }\n\n &[data-hover-trigger] {\n --lobe-dropdown-animation-duration: 140ms;\n }\n\n &[data-submenu],\n &[data-nested] {\n --lobe-dropdown-animation-duration: 0ms;\n --lobe-dropdown-animation-scale-y: 1;\n\n z-index: 1199;\n }\n\n &[data-side='left'],\n &[data-side='right'] {\n --lobe-dropdown-animation-duration: 0ms;\n --lobe-dropdown-animation-scale-y: 1;\n }\n `,\n\n separator: css`\n height: 1px;\n margin-block: 4px;\n margin-inline: 0;\n background: ${cssVar.colorBorder};\n `,\n\n submenuArrow: css`\n display: flex;\n flex-shrink: 0;\n align-items: center;\n justify-content: center;\n\n width: 16px;\n height: 16px;\n margin-inline-start: 8px;\n\n color: var(--lobe-menu-icon-color, ${cssVar.colorTextSecondary});\n\n & svg {\n width: 12px;\n height: 12px;\n }\n `,\n}));\n"],"mappings":";;AAEA,MAAa,SAAS,oBAAoB,EAAE,KAAK,cAAc;CAC7D,QAAQ,GAAG;8BACiB,OAAO,WAAW;;aAEnC,OAAO,WAAW;;;oBAGX,OAAO,aAAa;;;CAItC,OAAO,GAAG;;;aAGC,OAAO,kBAAkB;;CAGpC,OAAO,GAAG;;;;mBAIO,OAAO,eAAe;;aAE5B,OAAO,kBAAkB;;CAGpC,QAAQ,GAAG;;;;oCAIuB,OAAO,YAAY;;;;;;;;CASrD,QAAQ,GAAG;;;;kCAIqB,OAAO,YAAY;;;;;;;CAQnD,YAAY,GAAG;;;;;;;;;aASJ,OAAO,kBAAkB;;;;;;;;CASpC,MAAM,GAAG;;;;;;;;;;yCAU8B,OAAO,mBAAmB;;;;;;;CAQjE,MAAM,GAAG;;;;;;;;;;;;;qBAaU,OAAO,eAAe;;;;aAI9B,OAAO,UAAU;;;;4BAIF,OAAO,cAAc;;;oBAG7B,OAAO,kBAAkB;;;;oBAIzB,OAAO,mBAAmB;;;;;eAK/B,OAAO,kBAAkB;;;;;;;;;oBASpB,OAAO,kBAAkB;;;;;;oBAMzB,OAAO,kBAAkB;;;CAI3C,aAAa,GAAG;;;;;;CAOhB,uBAAuB,GAAG;;;CAI1B,gBAAgB,GAAG;;;;CAKnB,OAAO,GAAG;;;;;;;;;;;;;CAcV,YAAY,GAAG;;;;;;;;CASf,MAAM,GAAG;;;;;aAKE,OAAO,kBAAkB;;;;CAKpC,OAAO,GAAG;;;;;;;;qBAQS,OAAO,aAAa;;kBAEvB,OAAO,gBAAgB;;;kBAGvB,OAAO,YAAY;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAgCnC,gBAAgB,GAAG;;;;;;CAOnB,cAAc,GAAG;;;;;CAMjB,YAAY,GAAG;;;;0CAIyB,OAAO,cAAc;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAkD7D,WAAW,GAAG;;;;kBAIE,OAAO,YAAY;;CAGnC,cAAc,GAAG;;;;;;;;;;yCAUsB,OAAO,mBAAmB;;;;;;;AAOnE,EAAE"}
@@ -1,6 +1,8 @@
1
1
  import { Trigger } from "../../types/trigger.mjs";
2
2
  import "../../types/index.mjs";
3
3
  import { Placement } from "../../utils/placement.mjs";
4
+ import { VirtualListProps } from "../virtual/type.mjs";
5
+ import "../virtual/index.mjs";
4
6
  import { MenuCheckboxItemType } from "../../Menu/checkboxItem.mjs";
5
7
  import { MenuSwitchItemType } from "../../Menu/switchItem.mjs";
6
8
  import { BaseMenuItemType } from "../../Menu/baseItem.mjs";
@@ -14,7 +16,7 @@ type DropdownMenuPlacement = Placement;
14
16
  type DropdownMenuCheckboxItem = MenuCheckboxItemType;
15
17
  type DropdownMenuSwitchItem = MenuSwitchItemType;
16
18
  type DropdownItem = BaseMenuItemType;
17
- interface DropdownMenuProps<Payload = unknown> extends Omit<MenuRootProps<Payload>, 'children'> {
19
+ interface DropdownMenuProps<Payload = unknown> extends Omit<MenuRootProps<Payload>, 'children'>, Pick<VirtualListProps, 'virtual' | 'listItemHeight'> {
18
20
  children: ReactNode;
19
21
  /**
20
22
  * 底部固定插槽,渲染于可滚动的 items 区域下方,自带分隔边框