@xsolla/xui-context-menu 0.160.1 → 0.161.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.
package/native/index.js CHANGED
@@ -151,7 +151,7 @@ var OptionCell = ({
151
151
  const size = propSize ?? ctx?.size ?? "md";
152
152
  const sizing = theme.sizing.contextMenu(size);
153
153
  const variants = sizeToVariants[size];
154
- const id = (0, import_react2.useId)();
154
+ const id = (0, import_xui_core.useId)();
155
155
  const [index, setIndex] = (0, import_react2.useState)(-1);
156
156
  const [submenuOpen, setSubmenuOpen] = (0, import_react2.useState)(false);
157
157
  const [submenuPos, setSubmenuPos] = (0, import_react2.useState)(null);
@@ -467,7 +467,7 @@ var HeadingCell = ({
467
467
  const size = propSize ?? ctx?.size ?? "md";
468
468
  const sizing = theme.sizing.contextMenu(size);
469
469
  const variants = sizeToVariants[size];
470
- const id = (0, import_react2.useId)();
470
+ const id = (0, import_xui_core.useId)();
471
471
  (0, import_react2.useEffect)(() => {
472
472
  if (!ctx) return;
473
473
  ctx.registerCell(id, { type: "heading" });
@@ -525,7 +525,7 @@ var SearchCell = ({
525
525
  const ctx = useContextMenu();
526
526
  const size = propSize ?? ctx?.size ?? "md";
527
527
  const sizing = theme.sizing.contextMenu(size);
528
- const id = (0, import_react2.useId)();
528
+ const id = (0, import_xui_core.useId)();
529
529
  (0, import_react2.useEffect)(() => {
530
530
  if (!ctx) return;
531
531
  ctx.registerCell(id, { type: "search" });
@@ -562,7 +562,7 @@ var SearchCell = ({
562
562
  var DividerCell = ({ themeMode, themeProductContext, "data-testid": testId }) => {
563
563
  const { theme } = (0, import_xui_core.useResolvedTheme)({ themeMode, themeProductContext });
564
564
  const ctx = useContextMenu();
565
- const id = (0, import_react2.useId)();
565
+ const id = (0, import_xui_core.useId)();
566
566
  (0, import_react2.useEffect)(() => {
567
567
  if (!ctx) return;
568
568
  ctx.registerCell(id, { type: "divider" });
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/index.tsx","../../src/ContextMenu.tsx","../../src/ContextMenuContext.tsx","../../src/ContextMenuItem.tsx","../../src/hooks/useContextMenuPosition.ts","../../src/hooks/useKeyboardNavigation.ts"],"sourcesContent":["export { ContextMenu } from \"./ContextMenu\";\nexport { ContextMenuItem } from \"./ContextMenuItem\";\n\nexport {\n useContextMenu,\n useContextMenuRequired,\n ContextMenuContext,\n} from \"./ContextMenuContext\";\n\nexport { useContextMenuPosition } from \"./hooks/useContextMenuPosition\";\nexport { useKeyboardNavigation } from \"./hooks/useKeyboardNavigation\";\n\nexport type {\n ContextMenuSize,\n ContextMenuItemType,\n ContextMenuItemLeadingControl,\n ContextMenuOptionItemProps,\n ContextMenuSearchItemProps,\n ContextMenuHeadingItemProps,\n ContextMenuDividerItemProps,\n ContextMenuItemProps,\n ContextMenuPanelType,\n ContextMenuPlacement,\n ContextMenuPosition,\n ContextMenuProps,\n ContextMenuContextValue,\n ContextMenuSizing,\n} from \"./types\";\n","import React, {\n useCallback,\n useEffect,\n useMemo,\n useRef,\n useState,\n isValidElement,\n cloneElement,\n type ReactElement,\n} from \"react\";\nimport { createPortal } from \"react-dom\";\nimport { useResolvedTheme, type ThemeOverrideProps } from \"@xsolla/xui-core\";\nimport { Spinner } from \"@xsolla/xui-spinner\";\nimport { ContextMenuContext } from \"./ContextMenuContext\";\nimport { ContextMenuItem } from \"./ContextMenuItem\";\nimport { useContextMenuPosition } from \"./hooks/useContextMenuPosition\";\nimport { useKeyboardNavigation } from \"./hooks/useKeyboardNavigation\";\nimport type {\n ContextMenuCellMeta,\n ContextMenuContextValue,\n ContextMenuDividerItemProps,\n ContextMenuHeadingItemProps,\n ContextMenuOptionItemProps,\n ContextMenuProps,\n ContextMenuSize,\n} from \"./types\";\n\ntype Props = ContextMenuProps & ThemeOverrideProps;\n\ninterface CellEntry {\n id: string;\n meta: ContextMenuCellMeta;\n}\n\ntype PresetItem =\n | ContextMenuOptionItemProps\n | ContextMenuHeadingItemProps\n | ContextMenuDividerItemProps;\n\nconst SEARCH_DEBOUNCE_MS = 200;\n\nconst EmptyMessage: React.FC<{ children: React.ReactNode; color: string }> = ({\n children,\n color,\n}) => (\n <div\n style={{\n padding: 12,\n color,\n fontSize: 14,\n textAlign: \"center\",\n }}\n >\n {children}\n </div>\n);\n\nexport const ContextMenu: React.FC<Props> = (props) => {\n const {\n type,\n items,\n children,\n size = \"md\",\n searchable,\n loading,\n emptyMessage,\n empty,\n trigger,\n isOpen,\n onOpenChange,\n closeOnSelect,\n width,\n maxHeight,\n placement = \"bottom-start\",\n onSelect,\n \"aria-label\": ariaLabel,\n \"data-testid\": testId,\n testID,\n themeMode,\n themeProductContext,\n } = props;\n\n const { theme } = useResolvedTheme({ themeMode, themeProductContext });\n\n const isControlled = isOpen !== undefined;\n const [internalOpen, setInternalOpen] = useState(false);\n const open = isControlled ? !!isOpen : internalOpen;\n\n const setOpen = useCallback(\n (next: boolean) => {\n if (!isControlled) setInternalOpen(next);\n onOpenChange?.(next);\n },\n [isControlled, onOpenChange]\n );\n\n const [activeIndex, setActiveIndex] = useState<number>(-1);\n const cellsRef = useRef<CellEntry[]>([]);\n const [cellsVersion, setCellsVersion] = useState(0);\n\n const triggerRef = useRef<HTMLElement | null>(null);\n const panelRef = useRef<HTMLDivElement | null>(null);\n\n // Search query state\n const [query, setQuery] = useState(\"\");\n const [debouncedQuery, setDebouncedQuery] = useState(\"\");\n const debounceTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n\n useEffect(() => {\n if (debounceTimerRef.current) clearTimeout(debounceTimerRef.current);\n debounceTimerRef.current = setTimeout(() => {\n setDebouncedQuery(query);\n }, SEARCH_DEBOUNCE_MS);\n return () => {\n if (debounceTimerRef.current) clearTimeout(debounceTimerRef.current);\n };\n }, [query]);\n\n const closeMenu = useCallback(() => {\n setOpen(false);\n setActiveIndex(-1);\n }, [setOpen]);\n\n const registerCell = useCallback((id: string, meta: ContextMenuCellMeta) => {\n const existing = cellsRef.current.findIndex((c) => c.id === id);\n if (existing === -1) {\n cellsRef.current.push({ id, meta });\n setCellsVersion((v) => v + 1);\n return cellsRef.current.length - 1;\n }\n cellsRef.current[existing] = { id, meta };\n return existing;\n }, []);\n\n const unregisterCell = useCallback((id: string) => {\n const idx = cellsRef.current.findIndex((c) => c.id === id);\n if (idx !== -1) {\n cellsRef.current.splice(idx, 1);\n setCellsVersion((v) => v + 1);\n }\n }, []);\n\n const ctx: ContextMenuContextValue = useMemo(\n () => ({\n size: size as ContextMenuSize,\n closeMenu,\n registerCell,\n unregisterCell,\n activeIndex,\n setActiveIndex,\n query,\n setQuery,\n }),\n [size, closeMenu, registerCell, unregisterCell, activeIndex, query]\n );\n\n const triggerNode = useMemo(() => {\n if (!trigger) return null;\n const inner = isValidElement(trigger)\n ? cloneElement(\n trigger as ReactElement<{\n \"aria-haspopup\"?: string;\n \"aria-expanded\"?: string | boolean;\n }>,\n {\n \"aria-haspopup\": \"menu\",\n \"aria-expanded\": open ? \"true\" : \"false\",\n }\n )\n : trigger;\n return (\n <span\n ref={(node) => {\n if (!node) {\n triggerRef.current = null;\n return;\n }\n const focusable = node.querySelector<HTMLElement>(\n \"button, [href], input, select, textarea, [tabindex]:not([tabindex='-1'])\"\n );\n triggerRef.current = focusable ?? node;\n }}\n onClick={() => setOpen(!open)}\n style={{ display: \"inline-flex\" }}\n >\n {inner}\n </span>\n );\n }, [trigger, open, setOpen]);\n\n const usePortal = !!trigger && typeof document !== \"undefined\";\n\n const position = useContextMenuPosition({\n triggerRef,\n panelRef,\n isOpen: open && usePortal,\n placement,\n });\n\n const cellsForNav = useMemo(\n () => cellsRef.current.map((c) => ({ id: c.id, meta: c.meta })),\n // eslint-disable-next-line react-hooks/exhaustive-deps\n [cellsVersion]\n );\n\n const { handleKeyDown } = useKeyboardNavigation({\n isOpen: open,\n cells: cellsForNav,\n activeIndex,\n setActiveIndex,\n onClose: closeMenu,\n triggerRef,\n });\n\n const sizingFn = (theme.sizing as { contextMenu?: (s: string) => unknown })\n .contextMenu;\n const sizing = sizingFn\n ? (sizingFn(size) as {\n panelWidth?: number;\n borderRadius?: number;\n paddingVertical?: number;\n })\n : {};\n const radiusObj = (theme as { radius?: { contextMenu?: number } }).radius;\n const radiusVal = sizing.borderRadius ?? radiusObj?.contextMenu ?? 8;\n const shadowObj = (theme as { shadow?: { contextMenu?: string } }).shadow;\n const shadowVal = shadowObj?.contextMenu ?? \"\";\n const panelPaddingVertical = sizing.paddingVertical ?? 8;\n\n const panelStyle: React.CSSProperties = {\n background: theme.colors.background.primary,\n borderRadius: radiusVal,\n boxShadow: shadowVal,\n width: width ?? sizing.panelWidth,\n maxHeight,\n overflow: \"hidden\",\n display: open ? \"flex\" : \"none\",\n flexDirection: \"column\",\n outline: \"none\",\n fontFamily: theme.fonts.body,\n paddingTop: panelPaddingVertical,\n paddingBottom: panelPaddingVertical,\n };\n\n if (usePortal) {\n panelStyle.position = \"fixed\";\n panelStyle.top = position?.top ?? 0;\n panelStyle.left = position?.left ?? 0;\n }\n\n // Filter preset items based on debounced query (only when searchable + items)\n const filteredItems = useMemo<PresetItem[] | undefined>(() => {\n if (!items) return undefined;\n if (!searchable || !debouncedQuery) return items.slice();\n const q = debouncedQuery.toLowerCase();\n const matchedFlags = items.map((item) => {\n if (item.type === \"option\") {\n return String(item.label ?? \"\")\n .toLowerCase()\n .includes(q);\n }\n return false; // headings/dividers themselves never match\n });\n // Now hide headings whose options are all filtered out and trailing dividers\n const result: PresetItem[] = [];\n let pendingHeading: {\n item: ContextMenuHeadingItemProps;\n idx: number;\n } | null = null;\n let lastEmittedWasContent = false; // whether last pushed was option (so divider can follow)\n let groupHasOption = false;\n for (let i = 0; i < items.length; i += 1) {\n const item = items[i];\n if (item.type === \"heading\") {\n // Starting a new group\n pendingHeading = { item, idx: i };\n groupHasOption = false;\n } else if (item.type === \"divider\") {\n // Emit divider only if the previously emitted thing was content\n if (lastEmittedWasContent) {\n result.push(item);\n lastEmittedWasContent = false;\n }\n // dividers also reset pending heading so a heading sits with its group\n pendingHeading = null;\n groupHasOption = false;\n } else if (item.type === \"option\") {\n if (matchedFlags[i]) {\n if (pendingHeading) {\n result.push(pendingHeading.item);\n pendingHeading = null;\n }\n result.push(item);\n lastEmittedWasContent = true;\n groupHasOption = true;\n }\n }\n }\n // Strip trailing divider if any\n while (result.length > 0 && result[result.length - 1].type === \"divider\") {\n result.pop();\n }\n // Suppress unused\n void groupHasOption;\n return result;\n }, [items, searchable, debouncedQuery]);\n\n const effectiveCloseOnSelect =\n closeOnSelect !== undefined ? closeOnSelect : type !== \"checkbox\";\n\n const renderPresetItem = (item: PresetItem, key: number) => {\n if (item.type === \"heading\") {\n return (\n <ContextMenuItem\n key={`h-${key}`}\n {...item}\n size={item.size ?? (size as ContextMenuSize)}\n />\n );\n }\n if (item.type === \"divider\") {\n return (\n <ContextMenuItem\n key={`d-${key}`}\n {...item}\n size={item.size ?? (size as ContextMenuSize)}\n />\n );\n }\n const composed = composeItemForPreset(type, item);\n const originalSelect = composed.onSelect;\n const wrappedSelect = () => {\n originalSelect?.();\n onSelect?.(item);\n if (effectiveCloseOnSelect) closeMenu();\n };\n return (\n <ContextMenuItem\n key={`o-${key}`}\n {...composed}\n size={composed.size ?? (size as ContextMenuSize)}\n onSelect={wrappedSelect}\n />\n );\n };\n\n // Determine what to render in the panel body\n const isLoadingState = loading;\n\n let bodyContent: React.ReactNode = null;\n let isBodyEmpty = false;\n let searchNode: React.ReactNode = null;\n\n if (isLoadingState) {\n bodyContent = (\n <div\n style={{\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n padding: 16,\n }}\n >\n <Spinner size={size === \"xl\" ? \"lg\" : size === \"lg\" ? \"md\" : \"sm\"} />\n </div>\n );\n } else if (children !== undefined && children !== null) {\n // Custom path. Empty when children is falsy/empty array.\n const childArr = React.Children.toArray(children);\n if (childArr.length === 0) {\n isBodyEmpty = true;\n } else {\n bodyContent = children;\n }\n } else if (type && items) {\n // Preset path\n if (searchable) {\n searchNode = (\n <ContextMenuItem\n type=\"search\"\n value={query}\n onValueChange={setQuery}\n size={size as ContextMenuSize}\n />\n );\n }\n const visible = filteredItems ?? [];\n const optionCount = visible.filter((i) => i.type === \"option\").length;\n if (optionCount === 0) {\n isBodyEmpty = true;\n } else {\n bodyContent = visible.map((it, idx) => renderPresetItem(it, idx));\n }\n } else {\n // No children, no items — empty\n isBodyEmpty = true;\n }\n\n if (isBodyEmpty) {\n bodyContent = empty ?? (\n <EmptyMessage color={theme.colors.content.tertiary}>\n {emptyMessage ?? \"No results\"}\n </EmptyMessage>\n );\n }\n\n const hasStickySearch = !!searchNode;\n\n // Focus management on open/close transitions\n const prevOpenRef = useRef(false);\n useEffect(() => {\n const wasOpen = prevOpenRef.current;\n prevOpenRef.current = open;\n if (!wasOpen && open) {\n // open transition: focus search if present, else first option\n // wait for cells to register\n const timer = setTimeout(() => {\n const panel = panelRef.current;\n if (!panel) return;\n const search =\n panel.querySelector<HTMLInputElement>(\"[role='searchbox']\");\n if (search) {\n search.focus();\n return;\n }\n const firstOption = panel.querySelector<HTMLElement>(\n \"[role='menuitem'], [role='menuitemcheckbox'], [role='menuitemradio']\"\n );\n if (firstOption) {\n firstOption.focus();\n // Reset activeIndex so keyboard nav starts fresh; onFocus will have\n // set it to the focused option's index, but tests expect ArrowDown\n // to move to the first option from -1.\n setActiveIndex(-1);\n } else {\n panel.focus();\n }\n }, 0);\n return () => clearTimeout(timer);\n }\n if (wasOpen && !open) {\n // close transition: focus the trigger\n triggerRef.current?.focus();\n }\n }, [open]);\n\n const resolvedPlacement = position?.placement ?? placement;\n\n const scrollContainerStyle: React.CSSProperties = {\n overflowY: \"auto\",\n flex: 1,\n minHeight: 0,\n };\n\n const stickyHeaderStyle: React.CSSProperties = {\n position: \"sticky\",\n top: 0,\n zIndex: 1,\n background: theme.colors.background.primary,\n };\n\n const panel = open ? (\n <ContextMenuContext.Provider value={ctx}>\n <div\n ref={panelRef}\n role=\"menu\"\n aria-label={ariaLabel}\n data-testid={testId || testID}\n data-placement={usePortal ? resolvedPlacement : undefined}\n tabIndex={-1}\n onKeyDown={handleKeyDown}\n style={panelStyle}\n >\n {hasStickySearch && (\n <div data-sticky=\"top\" style={stickyHeaderStyle}>\n {searchNode}\n </div>\n )}\n <div style={scrollContainerStyle}>{bodyContent}</div>\n </div>\n </ContextMenuContext.Provider>\n ) : null;\n\n return (\n <>\n {triggerNode}\n {usePortal ? panel && createPortal(panel, document.body) : panel}\n </>\n );\n};\n\nContextMenu.displayName = \"ContextMenu\";\n\nfunction composeItemForPreset(\n type: ContextMenuProps[\"type\"],\n item: ContextMenuOptionItemProps\n): ContextMenuOptionItemProps {\n switch (type) {\n case \"checkbox\":\n return { ...item, leadingControl: \"checkbox\" };\n case \"radio\":\n return { ...item, leadingControl: \"radio\" };\n case \"list\":\n case \"phone\":\n case \"status\":\n case \"brandLogo\":\n case \"avatar\":\n default:\n return { ...item };\n }\n}\n","import { createContext, useContext } from \"react\";\nimport type { ContextMenuContextValue } from \"./types\";\n\nexport const ContextMenuContext = createContext<\n ContextMenuContextValue | undefined\n>(undefined);\n\nexport const useContextMenu = () => {\n const context = useContext(ContextMenuContext);\n return context;\n};\n\nexport const useContextMenuRequired = () => {\n const context = useContext(ContextMenuContext);\n if (!context) {\n throw new Error(\n \"useContextMenuRequired must be used within a ContextMenu component\"\n );\n }\n return context;\n};\n","import React, { useEffect, useId, useLayoutEffect, useState } from \"react\";\nimport { createPortal } from \"react-dom\";\nimport { useResolvedTheme, type ThemeOverrideProps } from \"@xsolla/xui-core\";\nimport { Typography } from \"@xsolla/xui-typography\";\nimport { Checkbox } from \"@xsolla/xui-checkbox\";\nimport { Radio } from \"@xsolla/xui-radio\";\nimport { useContextMenu } from \"./ContextMenuContext\";\nimport type {\n ContextMenuDividerItemProps,\n ContextMenuHeadingItemProps,\n ContextMenuItemProps,\n ContextMenuOptionItemProps,\n ContextMenuSearchItemProps,\n ContextMenuSize,\n} from \"./types\";\n\ntype BodyVariant = \"bodyLg\" | \"bodyMd\" | \"bodySm\" | \"bodyXs\";\ntype AccentVariant =\n | \"bodyLgAccent\"\n | \"bodyMdAccent\"\n | \"bodySmAccent\"\n | \"bodyXsAccent\";\n\nconst sizeToVariants: Record<\n ContextMenuSize,\n { label: BodyVariant; description: BodyVariant; headingAccent: AccentVariant }\n> = {\n xl: { label: \"bodyLg\", description: \"bodyLg\", headingAccent: \"bodyLgAccent\" },\n lg: { label: \"bodyLg\", description: \"bodyMd\", headingAccent: \"bodyMdAccent\" },\n md: { label: \"bodyMd\", description: \"bodySm\", headingAccent: \"bodySmAccent\" },\n sm: { label: \"bodySm\", description: \"bodyXs\", headingAccent: \"bodyXsAccent\" },\n};\n\nconst sizeLabelOverride: Partial<\n Record<ContextMenuSize, { fontSize: number; lineHeight: string }>\n> = {\n xl: { fontSize: 20, lineHeight: \"26px\" },\n};\n\ntype Props = ContextMenuItemProps & ThemeOverrideProps;\n\nexport const ContextMenuItem: React.FC<Props> = (props) => {\n if (props.type === \"option\") return <OptionCell {...props} />;\n if (props.type === \"heading\") return <HeadingCell {...props} />;\n if (props.type === \"divider\") return <DividerCell {...props} />;\n if (props.type === \"search\") return <SearchCell {...props} />;\n return null;\n};\n\nContextMenuItem.displayName = \"ContextMenuItem\";\n\nconst SubmenuChevron: React.FC<{ color: string; size: number }> = ({\n color,\n size,\n}) => (\n <span\n data-testid=\"ctxmenu-submenu-chevron\"\n aria-hidden=\"true\"\n style={{\n color,\n display: \"inline-flex\",\n alignItems: \"center\",\n width: size,\n height: size,\n }}\n >\n <svg\n width={size}\n height={size}\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n xmlns=\"http://www.w3.org/2000/svg\"\n >\n <path\n d=\"M17.0605 11.6464C17.2558 11.8417 17.2558 12.1583 17.0605 12.3536L9.70703 19.707L8.29297 18.293L14.5859 12L8.29297 5.70703L9.70703 4.29297L17.0605 11.6464Z\"\n fill=\"currentColor\"\n />\n </svg>\n </span>\n);\n\nconst OptionCell: React.FC<ContextMenuOptionItemProps & ThemeOverrideProps> = ({\n size: propSize,\n label,\n description,\n disabled,\n destructive,\n checked,\n leadingControl,\n leadingIcon,\n status,\n iconWrapper,\n slotContent,\n value,\n hint,\n trailingIcon,\n keyboardShortcut,\n hasSubmenu,\n submenu,\n onSelect,\n testID,\n themeMode,\n themeProductContext,\n \"data-testid\": testId,\n}) => {\n const { theme } = useResolvedTheme({ themeMode, themeProductContext });\n const ctx = useContextMenu();\n const size: ContextMenuSize = propSize ?? ctx?.size ?? \"md\";\n const sizing = theme.sizing.contextMenu(size);\n const variants = sizeToVariants[size];\n\n const id = useId();\n const [index, setIndex] = useState<number>(-1);\n const [submenuOpen, setSubmenuOpen] = useState(false);\n const [submenuPos, setSubmenuPos] = useState<{\n top: number;\n left: number;\n } | null>(null);\n const optionRef = React.useRef<HTMLDivElement | null>(null);\n const submenuWrapperRef = React.useRef<HTMLDivElement | null>(null);\n const closeTimerRef = React.useRef<ReturnType<typeof setTimeout> | null>(\n null\n );\n\n const cancelClose = () => {\n if (closeTimerRef.current) {\n clearTimeout(closeTimerRef.current);\n closeTimerRef.current = null;\n }\n };\n\n const scheduleClose = () => {\n cancelClose();\n closeTimerRef.current = setTimeout(() => setSubmenuOpen(false), 120);\n };\n\n useEffect(() => () => cancelClose(), []);\n\n useEffect(() => {\n if (!hasSubmenu || !submenuOpen) return;\n const onMouseDown = (e: MouseEvent) => {\n const target = e.target as HTMLElement | null;\n if (!target) return;\n const inOption = optionRef.current?.contains(target);\n const inSubmenu = submenuWrapperRef.current?.contains(target);\n if (!inOption && !inSubmenu) {\n setSubmenuOpen(false);\n return;\n }\n if (\n inSubmenu &&\n target.closest(\n '[role=\"menuitem\"],[role=\"menuitemcheckbox\"],[role=\"menuitemradio\"]'\n )\n ) {\n setSubmenuOpen(false);\n }\n };\n document.addEventListener(\"mousedown\", onMouseDown);\n return () => document.removeEventListener(\"mousedown\", onMouseDown);\n }, [hasSubmenu, submenuOpen]);\n\n useLayoutEffect(() => {\n if (!hasSubmenu || !submenuOpen) {\n setSubmenuPos(null);\n return;\n }\n const update = () => {\n const node = optionRef.current;\n if (!node) return;\n const rect = node.getBoundingClientRect();\n setSubmenuPos({ top: rect.top, left: rect.right });\n };\n update();\n window.addEventListener(\"scroll\", update, true);\n window.addEventListener(\"resize\", update);\n return () => {\n window.removeEventListener(\"scroll\", update, true);\n window.removeEventListener(\"resize\", update);\n };\n }, [hasSubmenu, submenuOpen]);\n const onSelectRef = React.useRef(onSelect);\n onSelectRef.current = onSelect;\n useEffect(() => {\n if (!ctx) return;\n const idx = ctx.registerCell(id, {\n type: \"option\",\n disabled,\n onSelect: () => onSelectRef.current?.(),\n });\n setIndex(idx);\n return () => ctx.unregisterCell(id);\n }, [ctx, id, disabled]);\n\n const isActive = ctx ? index >= 0 && ctx.activeIndex === index : false;\n const inHoverState = isActive || (hasSubmenu && submenuOpen);\n\n const handleEnter = () => {\n if (disabled) return;\n if (ctx && index >= 0) ctx.setActiveIndex(index);\n if (hasSubmenu) setSubmenuOpen(true);\n };\n\n const labelColor = disabled\n ? theme.colors.control.input.textDisable\n : destructive\n ? theme.colors.content.alert.primary\n : theme.colors.content.primary;\n\n const bg = inHoverState ? theme.colors.control.input.bgHover : \"transparent\";\n\n const role =\n !hasSubmenu && checked !== undefined ? \"menuitemcheckbox\" : \"menuitem\";\n const ariaChecked =\n !hasSubmenu && checked !== undefined\n ? checked\n ? \"true\"\n : \"false\"\n : undefined;\n\n const handleClick = () => {\n if (disabled) return;\n if (hasSubmenu) {\n setSubmenuOpen(true);\n return;\n }\n onSelect?.();\n };\n\n const closeSubmenuAndFocus = () => {\n setSubmenuOpen(false);\n optionRef.current?.focus();\n };\n\n const handleKeyDown = (e: React.KeyboardEvent) => {\n if (disabled) {\n if (e.key === \"Enter\" || e.key === \" \") e.preventDefault();\n return;\n }\n if (hasSubmenu) {\n if (e.key === \"ArrowRight\" || e.key === \"Enter\") {\n e.preventDefault();\n e.stopPropagation();\n setSubmenuOpen(true);\n return;\n }\n if (e.key === \"ArrowLeft\" || e.key === \"Escape\") {\n if (submenuOpen) {\n e.preventDefault();\n e.stopPropagation();\n closeSubmenuAndFocus();\n return;\n }\n }\n }\n if (e.key === \"Enter\" || e.key === \" \") {\n e.preventDefault();\n onSelect?.();\n }\n };\n\n return (\n <div\n ref={optionRef}\n role={role}\n aria-checked={ariaChecked}\n aria-disabled={disabled ? \"true\" : undefined}\n aria-haspopup={hasSubmenu ? \"menu\" : undefined}\n aria-expanded={hasSubmenu ? (submenuOpen ? \"true\" : \"false\") : undefined}\n tabIndex={0}\n data-testid={testId || testID}\n data-state={inHoverState ? \"hover\" : undefined}\n data-destructive={destructive ? \"true\" : undefined}\n aria-keyshortcuts={keyboardShortcut}\n onMouseEnter={() => {\n cancelClose();\n handleEnter();\n }}\n onMouseLeave={() => {\n if (hasSubmenu) scheduleClose();\n }}\n onFocus={handleEnter}\n onClick={handleClick}\n onKeyDown={handleKeyDown}\n style={{\n position: \"relative\",\n display: \"flex\",\n flexDirection: \"row\",\n alignItems: \"center\",\n gap: sizing.gap,\n paddingLeft: sizing.itemPaddingHorizontal,\n paddingRight: sizing.itemPaddingHorizontal,\n paddingTop: sizing.itemPaddingVertical,\n paddingBottom: sizing.itemPaddingVertical,\n backgroundColor: bg,\n cursor: disabled ? \"not-allowed\" : \"pointer\",\n outline: \"none\",\n }}\n >\n {leadingControl === \"checkbox\" && (\n <span\n data-testid=\"ctxmenu-leading-checkbox\"\n aria-hidden=\"true\"\n style={{ pointerEvents: \"none\", display: \"inline-flex\" }}\n >\n <Checkbox\n size={size}\n checked={!!checked}\n disabled={!!disabled}\n themeMode={themeMode}\n themeProductContext={themeProductContext}\n />\n </span>\n )}\n {leadingControl === \"radio\" && (\n <span\n data-testid=\"ctxmenu-leading-radio\"\n aria-hidden=\"true\"\n style={{ pointerEvents: \"none\", display: \"inline-flex\" }}\n >\n <Radio\n size={size}\n checked={!!checked}\n disabled={!!disabled}\n themeMode={themeMode}\n themeProductContext={themeProductContext}\n />\n </span>\n )}\n {leadingIcon}\n {status}\n {iconWrapper}\n {slotContent}\n <span\n style={{\n flex: 1,\n display: \"flex\",\n flexDirection: \"column\",\n gap: 2,\n minWidth: 0,\n }}\n >\n <Typography\n variant={variants.label}\n color={labelColor}\n noWrap={description === undefined}\n style={{\n ...(description === undefined\n ? { display: \"block\", minWidth: 0 }\n : {}),\n ...(sizeLabelOverride[size] ?? {}),\n }}\n >\n {label}\n </Typography>\n {description !== undefined && (\n <Typography\n variant={variants.description}\n color={theme.colors.content.tertiary}\n >\n {description}\n </Typography>\n )}\n </span>\n {(value !== undefined || hint !== undefined) && (\n <span\n style={{\n display: \"flex\",\n flexDirection: \"column\",\n alignItems: \"flex-end\",\n }}\n >\n {value !== undefined && (\n <Typography\n variant={variants.label}\n color={theme.colors.content.secondary}\n style={sizeLabelOverride[size]}\n >\n {value}\n </Typography>\n )}\n {hint !== undefined && (\n <Typography\n variant={variants.description}\n color={theme.colors.content.tertiary}\n >\n {hint}\n </Typography>\n )}\n </span>\n )}\n {keyboardShortcut && (\n <Typography\n as=\"kbd\"\n variant={variants.description}\n color={theme.colors.content.tertiary}\n >\n {keyboardShortcut}\n </Typography>\n )}\n {hasSubmenu && (\n <SubmenuChevron\n color={theme.colors.content.tertiary}\n size={sizing.iconSize}\n />\n )}\n {trailingIcon}\n {hasSubmenu &&\n submenuOpen &&\n submenu &&\n submenuPos &&\n typeof document !== \"undefined\" &&\n createPortal(\n <div\n ref={submenuWrapperRef}\n onMouseEnter={cancelClose}\n onMouseLeave={scheduleClose}\n style={{\n position: \"fixed\",\n top: submenuPos.top,\n left: submenuPos.left,\n zIndex: 2000,\n }}\n >\n {submenu}\n </div>,\n document.body\n )}\n </div>\n );\n};\n\nconst HeadingCell: React.FC<\n ContextMenuHeadingItemProps & ThemeOverrideProps\n> = ({\n size: propSize,\n label,\n description,\n testID,\n themeMode,\n themeProductContext,\n \"data-testid\": testId,\n}) => {\n const { theme } = useResolvedTheme({ themeMode, themeProductContext });\n const ctx = useContextMenu();\n const size: ContextMenuSize = propSize ?? ctx?.size ?? \"md\";\n const sizing = theme.sizing.contextMenu(size);\n const variants = sizeToVariants[size];\n\n const id = useId();\n useEffect(() => {\n if (!ctx) return;\n ctx.registerCell(id, { type: \"heading\" });\n return () => ctx.unregisterCell(id);\n }, [ctx, id]);\n\n return (\n <div\n role=\"presentation\"\n data-testid={testId}\n style={{\n display: \"flex\",\n flexDirection: \"column\",\n gap: 2,\n paddingLeft: sizing.itemPaddingHorizontal,\n paddingRight: sizing.itemPaddingHorizontal,\n paddingTop: sizing.itemPaddingVertical,\n paddingBottom: sizing.itemPaddingVertical,\n }}\n >\n <Typography\n variant={variants.headingAccent}\n color={theme.colors.content.secondary}\n style={{ textTransform: \"uppercase\", letterSpacing: 0.5 }}\n >\n {label}\n </Typography>\n {description !== undefined && (\n <Typography\n variant={variants.description}\n color={theme.colors.content.tertiary}\n >\n {description}\n </Typography>\n )}\n </div>\n );\n};\n\nconst SearchCell: React.FC<ContextMenuSearchItemProps & ThemeOverrideProps> = ({\n size: propSize,\n value,\n onValueChange,\n placeholder = \"Search\",\n autoFocus,\n \"aria-label\": ariaLabel = \"Search options\",\n \"data-testid\": testId,\n testID,\n themeMode,\n themeProductContext,\n}) => {\n const { theme } = useResolvedTheme({ themeMode, themeProductContext });\n const ctx = useContextMenu();\n const size: ContextMenuSize = propSize ?? ctx?.size ?? \"md\";\n const sizing = theme.sizing.contextMenu(size);\n\n const id = useId();\n useEffect(() => {\n if (!ctx) return;\n ctx.registerCell(id, { type: \"search\" });\n return () => ctx.unregisterCell(id);\n }, [ctx, id]);\n\n return (\n <input\n type=\"search\"\n role=\"searchbox\"\n aria-label={ariaLabel}\n placeholder={placeholder}\n value={value}\n autoFocus={autoFocus}\n onChange={(e) => onValueChange(e.target.value)}\n data-testid={testId}\n style={{\n width: \"100%\",\n boxSizing: \"border-box\",\n border: \"none\",\n outline: \"none\",\n background: \"transparent\",\n color: theme.colors.content.primary,\n fontSize: sizing.fontSize,\n lineHeight: `${sizing.fontSize + 2}px`,\n paddingLeft: sizing.itemPaddingHorizontal,\n paddingRight: sizing.itemPaddingHorizontal,\n paddingTop: sizing.itemPaddingVertical,\n paddingBottom: sizing.itemPaddingVertical,\n }}\n />\n );\n};\n\nconst DividerCell: React.FC<\n ContextMenuDividerItemProps & ThemeOverrideProps\n> = ({ themeMode, themeProductContext, \"data-testid\": testId }) => {\n const { theme } = useResolvedTheme({ themeMode, themeProductContext });\n const ctx = useContextMenu();\n const id = useId();\n useEffect(() => {\n if (!ctx) return;\n ctx.registerCell(id, { type: \"divider\" });\n return () => ctx.unregisterCell(id);\n }, [ctx, id]);\n return (\n <div\n role=\"separator\"\n data-testid={testId}\n style={{\n height: 1,\n backgroundColor: theme.colors.border.secondary,\n margin: \"4px 0\",\n }}\n />\n );\n};\n","import { useEffect, useState, type RefObject } from \"react\";\nimport type { ContextMenuPlacement } from \"../types\";\n\ninterface UseContextMenuPositionOptions {\n triggerRef: RefObject<HTMLElement | null>;\n panelRef: RefObject<HTMLElement | null>;\n isOpen: boolean;\n placement?: ContextMenuPlacement;\n offset?: number;\n}\n\ninterface ResolvedPosition {\n top: number;\n left: number;\n placement: ContextMenuPlacement;\n}\n\nconst splitPlacement = (\n placement: ContextMenuPlacement\n): { vertical: \"top\" | \"bottom\"; horizontal: \"start\" | \"end\" } => {\n const [vertical, horizontal] = placement.split(\"-\") as [\n \"top\" | \"bottom\",\n \"start\" | \"end\",\n ];\n return { vertical, horizontal };\n};\n\nconst joinPlacement = (\n vertical: \"top\" | \"bottom\",\n horizontal: \"start\" | \"end\"\n): ContextMenuPlacement => `${vertical}-${horizontal}` as ContextMenuPlacement;\n\nexport const useContextMenuPosition = ({\n triggerRef,\n panelRef,\n isOpen,\n placement = \"bottom-start\",\n offset = 4,\n}: UseContextMenuPositionOptions): ResolvedPosition | undefined => {\n const [resolved, setResolved] = useState<ResolvedPosition | undefined>();\n\n useEffect(() => {\n if (!isOpen) {\n setResolved(undefined);\n return;\n }\n\n const compute = () => {\n const trigger = triggerRef.current;\n const panel = panelRef.current;\n if (!trigger || !panel) return;\n\n const triggerRect = trigger.getBoundingClientRect();\n const panelRect = panel.getBoundingClientRect();\n const viewportWidth = window.innerWidth;\n const viewportHeight = window.innerHeight;\n\n let { vertical, horizontal } = splitPlacement(placement);\n\n const computeTop = (v: \"top\" | \"bottom\") =>\n v === \"bottom\"\n ? triggerRect.bottom + offset\n : triggerRect.top - panelRect.height - offset;\n\n const computeLeft = (h: \"start\" | \"end\") =>\n h === \"start\" ? triggerRect.left : triggerRect.right - panelRect.width;\n\n let top = computeTop(vertical);\n const wantedBottom = top + panelRect.height;\n if (top < 0 || wantedBottom > viewportHeight) {\n const flipped = vertical === \"bottom\" ? \"top\" : \"bottom\";\n const flippedTop = computeTop(flipped);\n const flippedBottom = flippedTop + panelRect.height;\n if (flippedTop >= 0 && flippedBottom <= viewportHeight) {\n vertical = flipped;\n top = flippedTop;\n }\n }\n\n let left = computeLeft(horizontal);\n const wantedRight = left + panelRect.width;\n if (left < 0 || wantedRight > viewportWidth) {\n const flipped = horizontal === \"start\" ? \"end\" : \"start\";\n const flippedLeft = computeLeft(flipped);\n const flippedRight = flippedLeft + panelRect.width;\n if (flippedLeft >= 0 && flippedRight <= viewportWidth) {\n horizontal = flipped;\n left = flippedLeft;\n }\n }\n\n setResolved({\n top,\n left,\n placement: joinPlacement(vertical, horizontal),\n });\n };\n\n const rafId = window.requestAnimationFrame(compute);\n const onResize = () => compute();\n window.addEventListener(\"resize\", onResize);\n\n return () => {\n window.cancelAnimationFrame(rafId);\n window.removeEventListener(\"resize\", onResize);\n };\n }, [isOpen, placement, offset, triggerRef, panelRef]);\n\n return resolved;\n};\n","import { useCallback, type RefObject } from \"react\";\n\nexport type CellType = \"option\" | \"search\" | \"heading\" | \"divider\";\n\nexport interface CellMeta {\n type: CellType;\n onSelect?: () => void;\n disabled?: boolean;\n}\n\ninterface UseKeyboardNavigationOptions {\n isOpen: boolean;\n cells: Array<{ id: string; meta: CellMeta }>;\n activeIndex: number;\n setActiveIndex: (index: number) => void;\n onClose: () => void;\n triggerRef?: RefObject<HTMLElement | null>;\n}\n\nconst isNavigableOption = (meta: CellMeta) =>\n meta.type === \"option\" && !meta.disabled;\n\nconst isTextInputTarget = (target: EventTarget | null): boolean => {\n if (!(target instanceof HTMLElement)) return false;\n if (target.tagName === \"INPUT\" || target.tagName === \"TEXTAREA\") return true;\n return target.getAttribute(\"role\") === \"searchbox\";\n};\n\nexport const useKeyboardNavigation = ({\n isOpen,\n cells,\n activeIndex,\n setActiveIndex,\n onClose,\n triggerRef,\n}: UseKeyboardNavigationOptions) => {\n const findFirstOption = useCallback(() => {\n for (let i = 0; i < cells.length; i += 1) {\n if (isNavigableOption(cells[i].meta)) return i;\n }\n return -1;\n }, [cells]);\n\n const findLastOption = useCallback(() => {\n for (let i = cells.length - 1; i >= 0; i -= 1) {\n if (isNavigableOption(cells[i].meta)) return i;\n }\n return -1;\n }, [cells]);\n\n const findNextOption = useCallback(\n (from: number) => {\n const len = cells.length;\n if (len === 0) return -1;\n for (let step = 1; step <= len; step += 1) {\n const idx = (from + step + len) % len;\n if (isNavigableOption(cells[idx].meta)) return idx;\n }\n return -1;\n },\n [cells]\n );\n\n const findPrevOption = useCallback(\n (from: number) => {\n const len = cells.length;\n if (len === 0) return -1;\n for (let step = 1; step <= len; step += 1) {\n const idx = (from - step + len * 2) % len;\n if (isNavigableOption(cells[idx].meta)) return idx;\n }\n return -1;\n },\n [cells]\n );\n\n const handleKeyDown = useCallback(\n (event: React.KeyboardEvent) => {\n if (!isOpen) return;\n\n switch (event.key) {\n case \"ArrowDown\": {\n event.preventDefault();\n const next =\n activeIndex < 0 ? findFirstOption() : findNextOption(activeIndex);\n if (next >= 0) setActiveIndex(next);\n break;\n }\n case \"ArrowUp\": {\n event.preventDefault();\n const prev =\n activeIndex < 0 ? findLastOption() : findPrevOption(activeIndex);\n if (prev >= 0) setActiveIndex(prev);\n break;\n }\n case \"Home\": {\n event.preventDefault();\n const first = findFirstOption();\n if (first >= 0) setActiveIndex(first);\n break;\n }\n case \"End\": {\n event.preventDefault();\n const last = findLastOption();\n if (last >= 0) setActiveIndex(last);\n break;\n }\n case \"Enter\":\n case \" \": {\n if (event.defaultPrevented) break;\n if (event.key === \" \" && isTextInputTarget(event.target)) break;\n if (event.key === \" \") event.preventDefault();\n if (activeIndex >= 0 && activeIndex < cells.length) {\n const meta = cells[activeIndex].meta;\n if (isNavigableOption(meta)) meta.onSelect?.();\n }\n break;\n }\n case \"Escape\": {\n event.preventDefault();\n onClose();\n triggerRef?.current?.focus();\n break;\n }\n case \"Tab\": {\n onClose();\n break;\n }\n default:\n break;\n }\n },\n [\n isOpen,\n cells,\n activeIndex,\n setActiveIndex,\n onClose,\n triggerRef,\n findFirstOption,\n findLastOption,\n findNextOption,\n findPrevOption,\n ]\n );\n\n return { handleKeyDown };\n};\n"],"mappings":"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","names":["import_react","import_react_dom","import_xui_core","import_react","React","import_react","import_react","import_jsx_runtime","React","panel"]}
1
+ {"version":3,"sources":["../../src/index.tsx","../../src/ContextMenu.tsx","../../src/ContextMenuContext.tsx","../../src/ContextMenuItem.tsx","../../src/hooks/useContextMenuPosition.ts","../../src/hooks/useKeyboardNavigation.ts"],"sourcesContent":["export { ContextMenu } from \"./ContextMenu\";\nexport { ContextMenuItem } from \"./ContextMenuItem\";\n\nexport {\n useContextMenu,\n useContextMenuRequired,\n ContextMenuContext,\n} from \"./ContextMenuContext\";\n\nexport { useContextMenuPosition } from \"./hooks/useContextMenuPosition\";\nexport { useKeyboardNavigation } from \"./hooks/useKeyboardNavigation\";\n\nexport type {\n ContextMenuSize,\n ContextMenuItemType,\n ContextMenuItemLeadingControl,\n ContextMenuOptionItemProps,\n ContextMenuSearchItemProps,\n ContextMenuHeadingItemProps,\n ContextMenuDividerItemProps,\n ContextMenuItemProps,\n ContextMenuPanelType,\n ContextMenuPlacement,\n ContextMenuPosition,\n ContextMenuProps,\n ContextMenuContextValue,\n ContextMenuSizing,\n} from \"./types\";\n","import React, {\n useCallback,\n useEffect,\n useMemo,\n useRef,\n useState,\n isValidElement,\n cloneElement,\n type ReactElement,\n} from \"react\";\nimport { createPortal } from \"react-dom\";\nimport { useResolvedTheme, type ThemeOverrideProps } from \"@xsolla/xui-core\";\nimport { Spinner } from \"@xsolla/xui-spinner\";\nimport { ContextMenuContext } from \"./ContextMenuContext\";\nimport { ContextMenuItem } from \"./ContextMenuItem\";\nimport { useContextMenuPosition } from \"./hooks/useContextMenuPosition\";\nimport { useKeyboardNavigation } from \"./hooks/useKeyboardNavigation\";\nimport type {\n ContextMenuCellMeta,\n ContextMenuContextValue,\n ContextMenuDividerItemProps,\n ContextMenuHeadingItemProps,\n ContextMenuOptionItemProps,\n ContextMenuProps,\n ContextMenuSize,\n} from \"./types\";\n\ntype Props = ContextMenuProps & ThemeOverrideProps;\n\ninterface CellEntry {\n id: string;\n meta: ContextMenuCellMeta;\n}\n\ntype PresetItem =\n | ContextMenuOptionItemProps\n | ContextMenuHeadingItemProps\n | ContextMenuDividerItemProps;\n\nconst SEARCH_DEBOUNCE_MS = 200;\n\nconst EmptyMessage: React.FC<{ children: React.ReactNode; color: string }> = ({\n children,\n color,\n}) => (\n <div\n style={{\n padding: 12,\n color,\n fontSize: 14,\n textAlign: \"center\",\n }}\n >\n {children}\n </div>\n);\n\nexport const ContextMenu: React.FC<Props> = (props) => {\n const {\n type,\n items,\n children,\n size = \"md\",\n searchable,\n loading,\n emptyMessage,\n empty,\n trigger,\n isOpen,\n onOpenChange,\n closeOnSelect,\n width,\n maxHeight,\n placement = \"bottom-start\",\n onSelect,\n \"aria-label\": ariaLabel,\n \"data-testid\": testId,\n testID,\n themeMode,\n themeProductContext,\n } = props;\n\n const { theme } = useResolvedTheme({ themeMode, themeProductContext });\n\n const isControlled = isOpen !== undefined;\n const [internalOpen, setInternalOpen] = useState(false);\n const open = isControlled ? !!isOpen : internalOpen;\n\n const setOpen = useCallback(\n (next: boolean) => {\n if (!isControlled) setInternalOpen(next);\n onOpenChange?.(next);\n },\n [isControlled, onOpenChange]\n );\n\n const [activeIndex, setActiveIndex] = useState<number>(-1);\n const cellsRef = useRef<CellEntry[]>([]);\n const [cellsVersion, setCellsVersion] = useState(0);\n\n const triggerRef = useRef<HTMLElement | null>(null);\n const panelRef = useRef<HTMLDivElement | null>(null);\n\n // Search query state\n const [query, setQuery] = useState(\"\");\n const [debouncedQuery, setDebouncedQuery] = useState(\"\");\n const debounceTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n\n useEffect(() => {\n if (debounceTimerRef.current) clearTimeout(debounceTimerRef.current);\n debounceTimerRef.current = setTimeout(() => {\n setDebouncedQuery(query);\n }, SEARCH_DEBOUNCE_MS);\n return () => {\n if (debounceTimerRef.current) clearTimeout(debounceTimerRef.current);\n };\n }, [query]);\n\n const closeMenu = useCallback(() => {\n setOpen(false);\n setActiveIndex(-1);\n }, [setOpen]);\n\n const registerCell = useCallback((id: string, meta: ContextMenuCellMeta) => {\n const existing = cellsRef.current.findIndex((c) => c.id === id);\n if (existing === -1) {\n cellsRef.current.push({ id, meta });\n setCellsVersion((v) => v + 1);\n return cellsRef.current.length - 1;\n }\n cellsRef.current[existing] = { id, meta };\n return existing;\n }, []);\n\n const unregisterCell = useCallback((id: string) => {\n const idx = cellsRef.current.findIndex((c) => c.id === id);\n if (idx !== -1) {\n cellsRef.current.splice(idx, 1);\n setCellsVersion((v) => v + 1);\n }\n }, []);\n\n const ctx: ContextMenuContextValue = useMemo(\n () => ({\n size: size as ContextMenuSize,\n closeMenu,\n registerCell,\n unregisterCell,\n activeIndex,\n setActiveIndex,\n query,\n setQuery,\n }),\n [size, closeMenu, registerCell, unregisterCell, activeIndex, query]\n );\n\n const triggerNode = useMemo(() => {\n if (!trigger) return null;\n const inner = isValidElement(trigger)\n ? cloneElement(\n trigger as ReactElement<{\n \"aria-haspopup\"?: string;\n \"aria-expanded\"?: string | boolean;\n }>,\n {\n \"aria-haspopup\": \"menu\",\n \"aria-expanded\": open ? \"true\" : \"false\",\n }\n )\n : trigger;\n return (\n <span\n ref={(node) => {\n if (!node) {\n triggerRef.current = null;\n return;\n }\n const focusable = node.querySelector<HTMLElement>(\n \"button, [href], input, select, textarea, [tabindex]:not([tabindex='-1'])\"\n );\n triggerRef.current = focusable ?? node;\n }}\n onClick={() => setOpen(!open)}\n style={{ display: \"inline-flex\" }}\n >\n {inner}\n </span>\n );\n }, [trigger, open, setOpen]);\n\n const usePortal = !!trigger && typeof document !== \"undefined\";\n\n const position = useContextMenuPosition({\n triggerRef,\n panelRef,\n isOpen: open && usePortal,\n placement,\n });\n\n const cellsForNav = useMemo(\n () => cellsRef.current.map((c) => ({ id: c.id, meta: c.meta })),\n // eslint-disable-next-line react-hooks/exhaustive-deps\n [cellsVersion]\n );\n\n const { handleKeyDown } = useKeyboardNavigation({\n isOpen: open,\n cells: cellsForNav,\n activeIndex,\n setActiveIndex,\n onClose: closeMenu,\n triggerRef,\n });\n\n const sizingFn = (theme.sizing as { contextMenu?: (s: string) => unknown })\n .contextMenu;\n const sizing = sizingFn\n ? (sizingFn(size) as {\n panelWidth?: number;\n borderRadius?: number;\n paddingVertical?: number;\n })\n : {};\n const radiusObj = (theme as { radius?: { contextMenu?: number } }).radius;\n const radiusVal = sizing.borderRadius ?? radiusObj?.contextMenu ?? 8;\n const shadowObj = (theme as { shadow?: { contextMenu?: string } }).shadow;\n const shadowVal = shadowObj?.contextMenu ?? \"\";\n const panelPaddingVertical = sizing.paddingVertical ?? 8;\n\n const panelStyle: React.CSSProperties = {\n background: theme.colors.background.primary,\n borderRadius: radiusVal,\n boxShadow: shadowVal,\n width: width ?? sizing.panelWidth,\n maxHeight,\n overflow: \"hidden\",\n display: open ? \"flex\" : \"none\",\n flexDirection: \"column\",\n outline: \"none\",\n fontFamily: theme.fonts.body,\n paddingTop: panelPaddingVertical,\n paddingBottom: panelPaddingVertical,\n };\n\n if (usePortal) {\n panelStyle.position = \"fixed\";\n panelStyle.top = position?.top ?? 0;\n panelStyle.left = position?.left ?? 0;\n }\n\n // Filter preset items based on debounced query (only when searchable + items)\n const filteredItems = useMemo<PresetItem[] | undefined>(() => {\n if (!items) return undefined;\n if (!searchable || !debouncedQuery) return items.slice();\n const q = debouncedQuery.toLowerCase();\n const matchedFlags = items.map((item) => {\n if (item.type === \"option\") {\n return String(item.label ?? \"\")\n .toLowerCase()\n .includes(q);\n }\n return false; // headings/dividers themselves never match\n });\n // Now hide headings whose options are all filtered out and trailing dividers\n const result: PresetItem[] = [];\n let pendingHeading: {\n item: ContextMenuHeadingItemProps;\n idx: number;\n } | null = null;\n let lastEmittedWasContent = false; // whether last pushed was option (so divider can follow)\n let groupHasOption = false;\n for (let i = 0; i < items.length; i += 1) {\n const item = items[i];\n if (item.type === \"heading\") {\n // Starting a new group\n pendingHeading = { item, idx: i };\n groupHasOption = false;\n } else if (item.type === \"divider\") {\n // Emit divider only if the previously emitted thing was content\n if (lastEmittedWasContent) {\n result.push(item);\n lastEmittedWasContent = false;\n }\n // dividers also reset pending heading so a heading sits with its group\n pendingHeading = null;\n groupHasOption = false;\n } else if (item.type === \"option\") {\n if (matchedFlags[i]) {\n if (pendingHeading) {\n result.push(pendingHeading.item);\n pendingHeading = null;\n }\n result.push(item);\n lastEmittedWasContent = true;\n groupHasOption = true;\n }\n }\n }\n // Strip trailing divider if any\n while (result.length > 0 && result[result.length - 1].type === \"divider\") {\n result.pop();\n }\n // Suppress unused\n void groupHasOption;\n return result;\n }, [items, searchable, debouncedQuery]);\n\n const effectiveCloseOnSelect =\n closeOnSelect !== undefined ? closeOnSelect : type !== \"checkbox\";\n\n const renderPresetItem = (item: PresetItem, key: number) => {\n if (item.type === \"heading\") {\n return (\n <ContextMenuItem\n key={`h-${key}`}\n {...item}\n size={item.size ?? (size as ContextMenuSize)}\n />\n );\n }\n if (item.type === \"divider\") {\n return (\n <ContextMenuItem\n key={`d-${key}`}\n {...item}\n size={item.size ?? (size as ContextMenuSize)}\n />\n );\n }\n const composed = composeItemForPreset(type, item);\n const originalSelect = composed.onSelect;\n const wrappedSelect = () => {\n originalSelect?.();\n onSelect?.(item);\n if (effectiveCloseOnSelect) closeMenu();\n };\n return (\n <ContextMenuItem\n key={`o-${key}`}\n {...composed}\n size={composed.size ?? (size as ContextMenuSize)}\n onSelect={wrappedSelect}\n />\n );\n };\n\n // Determine what to render in the panel body\n const isLoadingState = loading;\n\n let bodyContent: React.ReactNode = null;\n let isBodyEmpty = false;\n let searchNode: React.ReactNode = null;\n\n if (isLoadingState) {\n bodyContent = (\n <div\n style={{\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n padding: 16,\n }}\n >\n <Spinner size={size === \"xl\" ? \"lg\" : size === \"lg\" ? \"md\" : \"sm\"} />\n </div>\n );\n } else if (children !== undefined && children !== null) {\n // Custom path. Empty when children is falsy/empty array.\n const childArr = React.Children.toArray(children);\n if (childArr.length === 0) {\n isBodyEmpty = true;\n } else {\n bodyContent = children;\n }\n } else if (type && items) {\n // Preset path\n if (searchable) {\n searchNode = (\n <ContextMenuItem\n type=\"search\"\n value={query}\n onValueChange={setQuery}\n size={size as ContextMenuSize}\n />\n );\n }\n const visible = filteredItems ?? [];\n const optionCount = visible.filter((i) => i.type === \"option\").length;\n if (optionCount === 0) {\n isBodyEmpty = true;\n } else {\n bodyContent = visible.map((it, idx) => renderPresetItem(it, idx));\n }\n } else {\n // No children, no items — empty\n isBodyEmpty = true;\n }\n\n if (isBodyEmpty) {\n bodyContent = empty ?? (\n <EmptyMessage color={theme.colors.content.tertiary}>\n {emptyMessage ?? \"No results\"}\n </EmptyMessage>\n );\n }\n\n const hasStickySearch = !!searchNode;\n\n // Focus management on open/close transitions\n const prevOpenRef = useRef(false);\n useEffect(() => {\n const wasOpen = prevOpenRef.current;\n prevOpenRef.current = open;\n if (!wasOpen && open) {\n // open transition: focus search if present, else first option\n // wait for cells to register\n const timer = setTimeout(() => {\n const panel = panelRef.current;\n if (!panel) return;\n const search =\n panel.querySelector<HTMLInputElement>(\"[role='searchbox']\");\n if (search) {\n search.focus();\n return;\n }\n const firstOption = panel.querySelector<HTMLElement>(\n \"[role='menuitem'], [role='menuitemcheckbox'], [role='menuitemradio']\"\n );\n if (firstOption) {\n firstOption.focus();\n // Reset activeIndex so keyboard nav starts fresh; onFocus will have\n // set it to the focused option's index, but tests expect ArrowDown\n // to move to the first option from -1.\n setActiveIndex(-1);\n } else {\n panel.focus();\n }\n }, 0);\n return () => clearTimeout(timer);\n }\n if (wasOpen && !open) {\n // close transition: focus the trigger\n triggerRef.current?.focus();\n }\n }, [open]);\n\n const resolvedPlacement = position?.placement ?? placement;\n\n const scrollContainerStyle: React.CSSProperties = {\n overflowY: \"auto\",\n flex: 1,\n minHeight: 0,\n };\n\n const stickyHeaderStyle: React.CSSProperties = {\n position: \"sticky\",\n top: 0,\n zIndex: 1,\n background: theme.colors.background.primary,\n };\n\n const panel = open ? (\n <ContextMenuContext.Provider value={ctx}>\n <div\n ref={panelRef}\n role=\"menu\"\n aria-label={ariaLabel}\n data-testid={testId || testID}\n data-placement={usePortal ? resolvedPlacement : undefined}\n tabIndex={-1}\n onKeyDown={handleKeyDown}\n style={panelStyle}\n >\n {hasStickySearch && (\n <div data-sticky=\"top\" style={stickyHeaderStyle}>\n {searchNode}\n </div>\n )}\n <div style={scrollContainerStyle}>{bodyContent}</div>\n </div>\n </ContextMenuContext.Provider>\n ) : null;\n\n return (\n <>\n {triggerNode}\n {usePortal ? panel && createPortal(panel, document.body) : panel}\n </>\n );\n};\n\nContextMenu.displayName = \"ContextMenu\";\n\nfunction composeItemForPreset(\n type: ContextMenuProps[\"type\"],\n item: ContextMenuOptionItemProps\n): ContextMenuOptionItemProps {\n switch (type) {\n case \"checkbox\":\n return { ...item, leadingControl: \"checkbox\" };\n case \"radio\":\n return { ...item, leadingControl: \"radio\" };\n case \"list\":\n case \"phone\":\n case \"status\":\n case \"brandLogo\":\n case \"avatar\":\n default:\n return { ...item };\n }\n}\n","import { createContext, useContext } from \"react\";\nimport type { ContextMenuContextValue } from \"./types\";\n\nexport const ContextMenuContext = createContext<\n ContextMenuContextValue | undefined\n>(undefined);\n\nexport const useContextMenu = () => {\n const context = useContext(ContextMenuContext);\n return context;\n};\n\nexport const useContextMenuRequired = () => {\n const context = useContext(ContextMenuContext);\n if (!context) {\n throw new Error(\n \"useContextMenuRequired must be used within a ContextMenu component\"\n );\n }\n return context;\n};\n","import React, { useEffect, useLayoutEffect, useState } from \"react\";\nimport { createPortal } from \"react-dom\";\nimport {\n useResolvedTheme,\n useId,\n type ThemeOverrideProps,\n} from \"@xsolla/xui-core\";\nimport { Typography } from \"@xsolla/xui-typography\";\nimport { Checkbox } from \"@xsolla/xui-checkbox\";\nimport { Radio } from \"@xsolla/xui-radio\";\nimport { useContextMenu } from \"./ContextMenuContext\";\nimport type {\n ContextMenuDividerItemProps,\n ContextMenuHeadingItemProps,\n ContextMenuItemProps,\n ContextMenuOptionItemProps,\n ContextMenuSearchItemProps,\n ContextMenuSize,\n} from \"./types\";\n\ntype BodyVariant = \"bodyLg\" | \"bodyMd\" | \"bodySm\" | \"bodyXs\";\ntype AccentVariant =\n | \"bodyLgAccent\"\n | \"bodyMdAccent\"\n | \"bodySmAccent\"\n | \"bodyXsAccent\";\n\nconst sizeToVariants: Record<\n ContextMenuSize,\n { label: BodyVariant; description: BodyVariant; headingAccent: AccentVariant }\n> = {\n xl: { label: \"bodyLg\", description: \"bodyLg\", headingAccent: \"bodyLgAccent\" },\n lg: { label: \"bodyLg\", description: \"bodyMd\", headingAccent: \"bodyMdAccent\" },\n md: { label: \"bodyMd\", description: \"bodySm\", headingAccent: \"bodySmAccent\" },\n sm: { label: \"bodySm\", description: \"bodyXs\", headingAccent: \"bodyXsAccent\" },\n};\n\nconst sizeLabelOverride: Partial<\n Record<ContextMenuSize, { fontSize: number; lineHeight: string }>\n> = {\n xl: { fontSize: 20, lineHeight: \"26px\" },\n};\n\ntype Props = ContextMenuItemProps & ThemeOverrideProps;\n\nexport const ContextMenuItem: React.FC<Props> = (props) => {\n if (props.type === \"option\") return <OptionCell {...props} />;\n if (props.type === \"heading\") return <HeadingCell {...props} />;\n if (props.type === \"divider\") return <DividerCell {...props} />;\n if (props.type === \"search\") return <SearchCell {...props} />;\n return null;\n};\n\nContextMenuItem.displayName = \"ContextMenuItem\";\n\nconst SubmenuChevron: React.FC<{ color: string; size: number }> = ({\n color,\n size,\n}) => (\n <span\n data-testid=\"ctxmenu-submenu-chevron\"\n aria-hidden=\"true\"\n style={{\n color,\n display: \"inline-flex\",\n alignItems: \"center\",\n width: size,\n height: size,\n }}\n >\n <svg\n width={size}\n height={size}\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n xmlns=\"http://www.w3.org/2000/svg\"\n >\n <path\n d=\"M17.0605 11.6464C17.2558 11.8417 17.2558 12.1583 17.0605 12.3536L9.70703 19.707L8.29297 18.293L14.5859 12L8.29297 5.70703L9.70703 4.29297L17.0605 11.6464Z\"\n fill=\"currentColor\"\n />\n </svg>\n </span>\n);\n\nconst OptionCell: React.FC<ContextMenuOptionItemProps & ThemeOverrideProps> = ({\n size: propSize,\n label,\n description,\n disabled,\n destructive,\n checked,\n leadingControl,\n leadingIcon,\n status,\n iconWrapper,\n slotContent,\n value,\n hint,\n trailingIcon,\n keyboardShortcut,\n hasSubmenu,\n submenu,\n onSelect,\n testID,\n themeMode,\n themeProductContext,\n \"data-testid\": testId,\n}) => {\n const { theme } = useResolvedTheme({ themeMode, themeProductContext });\n const ctx = useContextMenu();\n const size: ContextMenuSize = propSize ?? ctx?.size ?? \"md\";\n const sizing = theme.sizing.contextMenu(size);\n const variants = sizeToVariants[size];\n\n const id = useId();\n const [index, setIndex] = useState<number>(-1);\n const [submenuOpen, setSubmenuOpen] = useState(false);\n const [submenuPos, setSubmenuPos] = useState<{\n top: number;\n left: number;\n } | null>(null);\n const optionRef = React.useRef<HTMLDivElement | null>(null);\n const submenuWrapperRef = React.useRef<HTMLDivElement | null>(null);\n const closeTimerRef = React.useRef<ReturnType<typeof setTimeout> | null>(\n null\n );\n\n const cancelClose = () => {\n if (closeTimerRef.current) {\n clearTimeout(closeTimerRef.current);\n closeTimerRef.current = null;\n }\n };\n\n const scheduleClose = () => {\n cancelClose();\n closeTimerRef.current = setTimeout(() => setSubmenuOpen(false), 120);\n };\n\n useEffect(() => () => cancelClose(), []);\n\n useEffect(() => {\n if (!hasSubmenu || !submenuOpen) return;\n const onMouseDown = (e: MouseEvent) => {\n const target = e.target as HTMLElement | null;\n if (!target) return;\n const inOption = optionRef.current?.contains(target);\n const inSubmenu = submenuWrapperRef.current?.contains(target);\n if (!inOption && !inSubmenu) {\n setSubmenuOpen(false);\n return;\n }\n if (\n inSubmenu &&\n target.closest(\n '[role=\"menuitem\"],[role=\"menuitemcheckbox\"],[role=\"menuitemradio\"]'\n )\n ) {\n setSubmenuOpen(false);\n }\n };\n document.addEventListener(\"mousedown\", onMouseDown);\n return () => document.removeEventListener(\"mousedown\", onMouseDown);\n }, [hasSubmenu, submenuOpen]);\n\n useLayoutEffect(() => {\n if (!hasSubmenu || !submenuOpen) {\n setSubmenuPos(null);\n return;\n }\n const update = () => {\n const node = optionRef.current;\n if (!node) return;\n const rect = node.getBoundingClientRect();\n setSubmenuPos({ top: rect.top, left: rect.right });\n };\n update();\n window.addEventListener(\"scroll\", update, true);\n window.addEventListener(\"resize\", update);\n return () => {\n window.removeEventListener(\"scroll\", update, true);\n window.removeEventListener(\"resize\", update);\n };\n }, [hasSubmenu, submenuOpen]);\n const onSelectRef = React.useRef(onSelect);\n onSelectRef.current = onSelect;\n useEffect(() => {\n if (!ctx) return;\n const idx = ctx.registerCell(id, {\n type: \"option\",\n disabled,\n onSelect: () => onSelectRef.current?.(),\n });\n setIndex(idx);\n return () => ctx.unregisterCell(id);\n }, [ctx, id, disabled]);\n\n const isActive = ctx ? index >= 0 && ctx.activeIndex === index : false;\n const inHoverState = isActive || (hasSubmenu && submenuOpen);\n\n const handleEnter = () => {\n if (disabled) return;\n if (ctx && index >= 0) ctx.setActiveIndex(index);\n if (hasSubmenu) setSubmenuOpen(true);\n };\n\n const labelColor = disabled\n ? theme.colors.control.input.textDisable\n : destructive\n ? theme.colors.content.alert.primary\n : theme.colors.content.primary;\n\n const bg = inHoverState ? theme.colors.control.input.bgHover : \"transparent\";\n\n const role =\n !hasSubmenu && checked !== undefined ? \"menuitemcheckbox\" : \"menuitem\";\n const ariaChecked =\n !hasSubmenu && checked !== undefined\n ? checked\n ? \"true\"\n : \"false\"\n : undefined;\n\n const handleClick = () => {\n if (disabled) return;\n if (hasSubmenu) {\n setSubmenuOpen(true);\n return;\n }\n onSelect?.();\n };\n\n const closeSubmenuAndFocus = () => {\n setSubmenuOpen(false);\n optionRef.current?.focus();\n };\n\n const handleKeyDown = (e: React.KeyboardEvent) => {\n if (disabled) {\n if (e.key === \"Enter\" || e.key === \" \") e.preventDefault();\n return;\n }\n if (hasSubmenu) {\n if (e.key === \"ArrowRight\" || e.key === \"Enter\") {\n e.preventDefault();\n e.stopPropagation();\n setSubmenuOpen(true);\n return;\n }\n if (e.key === \"ArrowLeft\" || e.key === \"Escape\") {\n if (submenuOpen) {\n e.preventDefault();\n e.stopPropagation();\n closeSubmenuAndFocus();\n return;\n }\n }\n }\n if (e.key === \"Enter\" || e.key === \" \") {\n e.preventDefault();\n onSelect?.();\n }\n };\n\n return (\n <div\n ref={optionRef}\n role={role}\n aria-checked={ariaChecked}\n aria-disabled={disabled ? \"true\" : undefined}\n aria-haspopup={hasSubmenu ? \"menu\" : undefined}\n aria-expanded={hasSubmenu ? (submenuOpen ? \"true\" : \"false\") : undefined}\n tabIndex={0}\n data-testid={testId || testID}\n data-state={inHoverState ? \"hover\" : undefined}\n data-destructive={destructive ? \"true\" : undefined}\n aria-keyshortcuts={keyboardShortcut}\n onMouseEnter={() => {\n cancelClose();\n handleEnter();\n }}\n onMouseLeave={() => {\n if (hasSubmenu) scheduleClose();\n }}\n onFocus={handleEnter}\n onClick={handleClick}\n onKeyDown={handleKeyDown}\n style={{\n position: \"relative\",\n display: \"flex\",\n flexDirection: \"row\",\n alignItems: \"center\",\n gap: sizing.gap,\n paddingLeft: sizing.itemPaddingHorizontal,\n paddingRight: sizing.itemPaddingHorizontal,\n paddingTop: sizing.itemPaddingVertical,\n paddingBottom: sizing.itemPaddingVertical,\n backgroundColor: bg,\n cursor: disabled ? \"not-allowed\" : \"pointer\",\n outline: \"none\",\n }}\n >\n {leadingControl === \"checkbox\" && (\n <span\n data-testid=\"ctxmenu-leading-checkbox\"\n aria-hidden=\"true\"\n style={{ pointerEvents: \"none\", display: \"inline-flex\" }}\n >\n <Checkbox\n size={size}\n checked={!!checked}\n disabled={!!disabled}\n themeMode={themeMode}\n themeProductContext={themeProductContext}\n />\n </span>\n )}\n {leadingControl === \"radio\" && (\n <span\n data-testid=\"ctxmenu-leading-radio\"\n aria-hidden=\"true\"\n style={{ pointerEvents: \"none\", display: \"inline-flex\" }}\n >\n <Radio\n size={size}\n checked={!!checked}\n disabled={!!disabled}\n themeMode={themeMode}\n themeProductContext={themeProductContext}\n />\n </span>\n )}\n {leadingIcon}\n {status}\n {iconWrapper}\n {slotContent}\n <span\n style={{\n flex: 1,\n display: \"flex\",\n flexDirection: \"column\",\n gap: 2,\n minWidth: 0,\n }}\n >\n <Typography\n variant={variants.label}\n color={labelColor}\n noWrap={description === undefined}\n style={{\n ...(description === undefined\n ? { display: \"block\", minWidth: 0 }\n : {}),\n ...(sizeLabelOverride[size] ?? {}),\n }}\n >\n {label}\n </Typography>\n {description !== undefined && (\n <Typography\n variant={variants.description}\n color={theme.colors.content.tertiary}\n >\n {description}\n </Typography>\n )}\n </span>\n {(value !== undefined || hint !== undefined) && (\n <span\n style={{\n display: \"flex\",\n flexDirection: \"column\",\n alignItems: \"flex-end\",\n }}\n >\n {value !== undefined && (\n <Typography\n variant={variants.label}\n color={theme.colors.content.secondary}\n style={sizeLabelOverride[size]}\n >\n {value}\n </Typography>\n )}\n {hint !== undefined && (\n <Typography\n variant={variants.description}\n color={theme.colors.content.tertiary}\n >\n {hint}\n </Typography>\n )}\n </span>\n )}\n {keyboardShortcut && (\n <Typography\n as=\"kbd\"\n variant={variants.description}\n color={theme.colors.content.tertiary}\n >\n {keyboardShortcut}\n </Typography>\n )}\n {hasSubmenu && (\n <SubmenuChevron\n color={theme.colors.content.tertiary}\n size={sizing.iconSize}\n />\n )}\n {trailingIcon}\n {hasSubmenu &&\n submenuOpen &&\n submenu &&\n submenuPos &&\n typeof document !== \"undefined\" &&\n createPortal(\n <div\n ref={submenuWrapperRef}\n onMouseEnter={cancelClose}\n onMouseLeave={scheduleClose}\n style={{\n position: \"fixed\",\n top: submenuPos.top,\n left: submenuPos.left,\n zIndex: 2000,\n }}\n >\n {submenu}\n </div>,\n document.body\n )}\n </div>\n );\n};\n\nconst HeadingCell: React.FC<\n ContextMenuHeadingItemProps & ThemeOverrideProps\n> = ({\n size: propSize,\n label,\n description,\n testID,\n themeMode,\n themeProductContext,\n \"data-testid\": testId,\n}) => {\n const { theme } = useResolvedTheme({ themeMode, themeProductContext });\n const ctx = useContextMenu();\n const size: ContextMenuSize = propSize ?? ctx?.size ?? \"md\";\n const sizing = theme.sizing.contextMenu(size);\n const variants = sizeToVariants[size];\n\n const id = useId();\n useEffect(() => {\n if (!ctx) return;\n ctx.registerCell(id, { type: \"heading\" });\n return () => ctx.unregisterCell(id);\n }, [ctx, id]);\n\n return (\n <div\n role=\"presentation\"\n data-testid={testId}\n style={{\n display: \"flex\",\n flexDirection: \"column\",\n gap: 2,\n paddingLeft: sizing.itemPaddingHorizontal,\n paddingRight: sizing.itemPaddingHorizontal,\n paddingTop: sizing.itemPaddingVertical,\n paddingBottom: sizing.itemPaddingVertical,\n }}\n >\n <Typography\n variant={variants.headingAccent}\n color={theme.colors.content.secondary}\n style={{ textTransform: \"uppercase\", letterSpacing: 0.5 }}\n >\n {label}\n </Typography>\n {description !== undefined && (\n <Typography\n variant={variants.description}\n color={theme.colors.content.tertiary}\n >\n {description}\n </Typography>\n )}\n </div>\n );\n};\n\nconst SearchCell: React.FC<ContextMenuSearchItemProps & ThemeOverrideProps> = ({\n size: propSize,\n value,\n onValueChange,\n placeholder = \"Search\",\n autoFocus,\n \"aria-label\": ariaLabel = \"Search options\",\n \"data-testid\": testId,\n testID,\n themeMode,\n themeProductContext,\n}) => {\n const { theme } = useResolvedTheme({ themeMode, themeProductContext });\n const ctx = useContextMenu();\n const size: ContextMenuSize = propSize ?? ctx?.size ?? \"md\";\n const sizing = theme.sizing.contextMenu(size);\n\n const id = useId();\n useEffect(() => {\n if (!ctx) return;\n ctx.registerCell(id, { type: \"search\" });\n return () => ctx.unregisterCell(id);\n }, [ctx, id]);\n\n return (\n <input\n type=\"search\"\n role=\"searchbox\"\n aria-label={ariaLabel}\n placeholder={placeholder}\n value={value}\n autoFocus={autoFocus}\n onChange={(e) => onValueChange(e.target.value)}\n data-testid={testId}\n style={{\n width: \"100%\",\n boxSizing: \"border-box\",\n border: \"none\",\n outline: \"none\",\n background: \"transparent\",\n color: theme.colors.content.primary,\n fontSize: sizing.fontSize,\n lineHeight: `${sizing.fontSize + 2}px`,\n paddingLeft: sizing.itemPaddingHorizontal,\n paddingRight: sizing.itemPaddingHorizontal,\n paddingTop: sizing.itemPaddingVertical,\n paddingBottom: sizing.itemPaddingVertical,\n }}\n />\n );\n};\n\nconst DividerCell: React.FC<\n ContextMenuDividerItemProps & ThemeOverrideProps\n> = ({ themeMode, themeProductContext, \"data-testid\": testId }) => {\n const { theme } = useResolvedTheme({ themeMode, themeProductContext });\n const ctx = useContextMenu();\n const id = useId();\n useEffect(() => {\n if (!ctx) return;\n ctx.registerCell(id, { type: \"divider\" });\n return () => ctx.unregisterCell(id);\n }, [ctx, id]);\n return (\n <div\n role=\"separator\"\n data-testid={testId}\n style={{\n height: 1,\n backgroundColor: theme.colors.border.secondary,\n margin: \"4px 0\",\n }}\n />\n );\n};\n","import { useEffect, useState, type RefObject } from \"react\";\nimport type { ContextMenuPlacement } from \"../types\";\n\ninterface UseContextMenuPositionOptions {\n triggerRef: RefObject<HTMLElement | null>;\n panelRef: RefObject<HTMLElement | null>;\n isOpen: boolean;\n placement?: ContextMenuPlacement;\n offset?: number;\n}\n\ninterface ResolvedPosition {\n top: number;\n left: number;\n placement: ContextMenuPlacement;\n}\n\nconst splitPlacement = (\n placement: ContextMenuPlacement\n): { vertical: \"top\" | \"bottom\"; horizontal: \"start\" | \"end\" } => {\n const [vertical, horizontal] = placement.split(\"-\") as [\n \"top\" | \"bottom\",\n \"start\" | \"end\",\n ];\n return { vertical, horizontal };\n};\n\nconst joinPlacement = (\n vertical: \"top\" | \"bottom\",\n horizontal: \"start\" | \"end\"\n): ContextMenuPlacement => `${vertical}-${horizontal}` as ContextMenuPlacement;\n\nexport const useContextMenuPosition = ({\n triggerRef,\n panelRef,\n isOpen,\n placement = \"bottom-start\",\n offset = 4,\n}: UseContextMenuPositionOptions): ResolvedPosition | undefined => {\n const [resolved, setResolved] = useState<ResolvedPosition | undefined>();\n\n useEffect(() => {\n if (!isOpen) {\n setResolved(undefined);\n return;\n }\n\n const compute = () => {\n const trigger = triggerRef.current;\n const panel = panelRef.current;\n if (!trigger || !panel) return;\n\n const triggerRect = trigger.getBoundingClientRect();\n const panelRect = panel.getBoundingClientRect();\n const viewportWidth = window.innerWidth;\n const viewportHeight = window.innerHeight;\n\n let { vertical, horizontal } = splitPlacement(placement);\n\n const computeTop = (v: \"top\" | \"bottom\") =>\n v === \"bottom\"\n ? triggerRect.bottom + offset\n : triggerRect.top - panelRect.height - offset;\n\n const computeLeft = (h: \"start\" | \"end\") =>\n h === \"start\" ? triggerRect.left : triggerRect.right - panelRect.width;\n\n let top = computeTop(vertical);\n const wantedBottom = top + panelRect.height;\n if (top < 0 || wantedBottom > viewportHeight) {\n const flipped = vertical === \"bottom\" ? \"top\" : \"bottom\";\n const flippedTop = computeTop(flipped);\n const flippedBottom = flippedTop + panelRect.height;\n if (flippedTop >= 0 && flippedBottom <= viewportHeight) {\n vertical = flipped;\n top = flippedTop;\n }\n }\n\n let left = computeLeft(horizontal);\n const wantedRight = left + panelRect.width;\n if (left < 0 || wantedRight > viewportWidth) {\n const flipped = horizontal === \"start\" ? \"end\" : \"start\";\n const flippedLeft = computeLeft(flipped);\n const flippedRight = flippedLeft + panelRect.width;\n if (flippedLeft >= 0 && flippedRight <= viewportWidth) {\n horizontal = flipped;\n left = flippedLeft;\n }\n }\n\n setResolved({\n top,\n left,\n placement: joinPlacement(vertical, horizontal),\n });\n };\n\n const rafId = window.requestAnimationFrame(compute);\n const onResize = () => compute();\n window.addEventListener(\"resize\", onResize);\n\n return () => {\n window.cancelAnimationFrame(rafId);\n window.removeEventListener(\"resize\", onResize);\n };\n }, [isOpen, placement, offset, triggerRef, panelRef]);\n\n return resolved;\n};\n","import { useCallback, type RefObject } from \"react\";\n\nexport type CellType = \"option\" | \"search\" | \"heading\" | \"divider\";\n\nexport interface CellMeta {\n type: CellType;\n onSelect?: () => void;\n disabled?: boolean;\n}\n\ninterface UseKeyboardNavigationOptions {\n isOpen: boolean;\n cells: Array<{ id: string; meta: CellMeta }>;\n activeIndex: number;\n setActiveIndex: (index: number) => void;\n onClose: () => void;\n triggerRef?: RefObject<HTMLElement | null>;\n}\n\nconst isNavigableOption = (meta: CellMeta) =>\n meta.type === \"option\" && !meta.disabled;\n\nconst isTextInputTarget = (target: EventTarget | null): boolean => {\n if (!(target instanceof HTMLElement)) return false;\n if (target.tagName === \"INPUT\" || target.tagName === \"TEXTAREA\") return true;\n return target.getAttribute(\"role\") === \"searchbox\";\n};\n\nexport const useKeyboardNavigation = ({\n isOpen,\n cells,\n activeIndex,\n setActiveIndex,\n onClose,\n triggerRef,\n}: UseKeyboardNavigationOptions) => {\n const findFirstOption = useCallback(() => {\n for (let i = 0; i < cells.length; i += 1) {\n if (isNavigableOption(cells[i].meta)) return i;\n }\n return -1;\n }, [cells]);\n\n const findLastOption = useCallback(() => {\n for (let i = cells.length - 1; i >= 0; i -= 1) {\n if (isNavigableOption(cells[i].meta)) return i;\n }\n return -1;\n }, [cells]);\n\n const findNextOption = useCallback(\n (from: number) => {\n const len = cells.length;\n if (len === 0) return -1;\n for (let step = 1; step <= len; step += 1) {\n const idx = (from + step + len) % len;\n if (isNavigableOption(cells[idx].meta)) return idx;\n }\n return -1;\n },\n [cells]\n );\n\n const findPrevOption = useCallback(\n (from: number) => {\n const len = cells.length;\n if (len === 0) return -1;\n for (let step = 1; step <= len; step += 1) {\n const idx = (from - step + len * 2) % len;\n if (isNavigableOption(cells[idx].meta)) return idx;\n }\n return -1;\n },\n [cells]\n );\n\n const handleKeyDown = useCallback(\n (event: React.KeyboardEvent) => {\n if (!isOpen) return;\n\n switch (event.key) {\n case \"ArrowDown\": {\n event.preventDefault();\n const next =\n activeIndex < 0 ? findFirstOption() : findNextOption(activeIndex);\n if (next >= 0) setActiveIndex(next);\n break;\n }\n case \"ArrowUp\": {\n event.preventDefault();\n const prev =\n activeIndex < 0 ? findLastOption() : findPrevOption(activeIndex);\n if (prev >= 0) setActiveIndex(prev);\n break;\n }\n case \"Home\": {\n event.preventDefault();\n const first = findFirstOption();\n if (first >= 0) setActiveIndex(first);\n break;\n }\n case \"End\": {\n event.preventDefault();\n const last = findLastOption();\n if (last >= 0) setActiveIndex(last);\n break;\n }\n case \"Enter\":\n case \" \": {\n if (event.defaultPrevented) break;\n if (event.key === \" \" && isTextInputTarget(event.target)) break;\n if (event.key === \" \") event.preventDefault();\n if (activeIndex >= 0 && activeIndex < cells.length) {\n const meta = cells[activeIndex].meta;\n if (isNavigableOption(meta)) meta.onSelect?.();\n }\n break;\n }\n case \"Escape\": {\n event.preventDefault();\n onClose();\n triggerRef?.current?.focus();\n break;\n }\n case \"Tab\": {\n onClose();\n break;\n }\n default:\n break;\n }\n },\n [\n isOpen,\n cells,\n activeIndex,\n setActiveIndex,\n onClose,\n triggerRef,\n findFirstOption,\n findLastOption,\n findNextOption,\n findPrevOption,\n ]\n );\n\n return { handleKeyDown };\n};\n"],"mappings":"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","names":["import_react","import_react_dom","import_xui_core","import_react","React","import_react","import_react","import_jsx_runtime","React","panel"]}
package/native/index.mjs CHANGED
@@ -30,9 +30,12 @@ var useContextMenuRequired = () => {
30
30
  };
31
31
 
32
32
  // src/ContextMenuItem.tsx
33
- import React, { useEffect, useId, useLayoutEffect, useState } from "react";
33
+ import React, { useEffect, useLayoutEffect, useState } from "react";
34
34
  import { createPortal } from "react-dom";
35
- import { useResolvedTheme } from "@xsolla/xui-core";
35
+ import {
36
+ useResolvedTheme,
37
+ useId
38
+ } from "@xsolla/xui-core";
36
39
  import { Typography } from "@xsolla/xui-typography";
37
40
  import { Checkbox } from "@xsolla/xui-checkbox";
38
41
  import { Radio } from "@xsolla/xui-radio";