@xsolla/xui-context-menu 0.187.0 → 0.187.1

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/web/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/index.tsx","../../src/ContextMenu.tsx","../../../../foundation/primitives-web/src/Box.tsx","../../../../foundation/primitives-web/src/filterDOMProps.ts","../../../../../node_modules/@emotion/memoize/dist/memoize.esm.js","../../../../../node_modules/@emotion/is-prop-valid/dist/is-prop-valid.esm.js","../../src/ContextMenuContext.tsx","../../src/ContextMenuItem.tsx","../../src/ContextMenuSubmenu.tsx","../../src/hooks/useContextMenuPosition.ts","../../src/hooks/useKeyboardNavigation.ts"],"sourcesContent":["// Components\nexport { ContextMenu } from \"./ContextMenu\";\nexport { ContextMenuItem } from \"./ContextMenuItem\";\nexport { ContextMenuSubmenu } from \"./ContextMenuSubmenu\";\n\n// Context\nexport {\n ContextMenuContext,\n useContextMenu,\n useContextMenuRequired,\n} from \"./ContextMenuContext\";\n\n// Hooks\nexport { useContextMenuPosition } from \"./hooks/useContextMenuPosition\";\nexport { useKeyboardNavigation } from \"./hooks/useKeyboardNavigation\";\n\n// Types\nexport type {\n ContextMenuSize,\n ContextMenuPlacement,\n ContextMenuPresetType,\n ContextMenuPosition,\n ContextMenuProps,\n ContextMenuItemProps,\n ContextMenuOptionItemProps,\n ContextMenuSearchItemProps,\n ContextMenuHeadingItemProps,\n ContextMenuDividerItemProps,\n ContextMenuSubmenuProps,\n ContextMenuContextValue,\n ContextMenuSizing,\n} from \"./types\";\n","import React, {\n cloneElement,\n forwardRef,\n isValidElement,\n useCallback,\n useEffect,\n useLayoutEffect,\n useMemo,\n useRef,\n useState,\n} from \"react\";\n// @ts-expect-error - this will be resolved at build time\nimport { Box } from \"@xsolla/xui-primitives\";\nimport {\n useResolvedTheme,\n useId,\n useOverlayLayer,\n LAYER_OFFSET,\n useModalStackDepth,\n} from \"@xsolla/xui-core\";\nimport { Spinner } from \"@xsolla/xui-spinner\";\nimport { ContextMenuContext } from \"./ContextMenuContext\";\nimport { ContextMenuItem } from \"./ContextMenuItem\";\nimport { ContextMenuSubmenu } from \"./ContextMenuSubmenu\";\nimport { useContextMenuPosition } from \"./hooks/useContextMenuPosition\";\nimport {\n useKeyboardNavigation,\n type CellMeta,\n} from \"./hooks/useKeyboardNavigation\";\nimport type {\n ContextMenuContextValue,\n ContextMenuItemProps,\n ContextMenuOptionItemProps,\n ContextMenuPlacement,\n ContextMenuProps,\n ContextMenuSizing,\n} from \"./types\";\n\ntype CellEntry = { id: string; meta: CellMeta };\n\ntype ContextMenuTheme = {\n sizing: {\n contextMenu: (\n size: NonNullable<ContextMenuProps[\"size\"]>\n ) => ContextMenuSizing;\n };\n shape?: {\n contextMenu?: Partial<\n Record<\n NonNullable<ContextMenuProps[\"size\"]>,\n {\n borderRadius?: number | string;\n }\n >\n >;\n };\n colors: {\n background: {\n secondary: string;\n };\n border: {\n secondary: string;\n };\n control: {\n brand: {\n primary: {\n bg: string;\n };\n };\n };\n };\n};\n\nconst DEFAULT_EMPTY_MESSAGE = \"No results\";\nconst SEARCH_DEBOUNCE_MS = 200;\nconst ARROW_SIZE = 10;\nconst ARROW_HALF = ARROW_SIZE / 2;\nconst ARROW_EDGE_OFFSET = 12;\n// Distance the rotated arrow's tip protrudes past the panel edge toward the\n// trigger. The square is rotated 45deg about its center (pinned to the edge),\n// so its corner sits ARROW_HALF * √2 beyond it. Folded into the position\n// offset when `withArrow` is set so `offset` measures to the arrow tip.\nconst ARROW_TIP_PROTRUSION = ARROW_HALF * Math.SQRT2;\nconst PANEL_SHADOW = \"0 4px 12px rgba(0,0,0,0.15)\";\n\n// Portaled floating layers render onto document.body, OUTSIDE the ContextMenu\n// subtree. These include:\n// - Dropdown-style children (Select / MultiSelect / DatePicker option lists,\n// modal overlays) marked with data-modal-id (via useModalId); listbox-style\n// dropdowns additionally carry role=\"listbox\". See FEP-836.\n// - This ContextMenu's own sub-menus, which each portal to document.body as a\n// flat wrapper marked data-xui-context-menu-portal. A mousedown on a\n// sub-menu item would otherwise read as an outside click and dismiss the\n// whole trigger-anchored menu before the selection resolves.\n// A mousedown inside any of these must NOT be treated as an outside click.\nconst PORTALED_LAYER_SELECTOR =\n '[data-modal-id],[role=\"listbox\"],[data-xui-context-menu-portal]';\n\nconst textFromNode = (node: React.ReactNode): string => {\n if (node === null || node === undefined || typeof node === \"boolean\")\n return \"\";\n if (typeof node === \"string\" || typeof node === \"number\") return String(node);\n if (Array.isArray(node)) return node.map(textFromNode).join(\" \");\n if (isValidElement(node)) return textFromNode(node.props.children);\n return \"\";\n};\n\nconst filterItems = (\n items: ReadonlyArray<ContextMenuItemProps>,\n query: string\n): ContextMenuItemProps[] => {\n const normalized = query.trim().toLowerCase();\n if (!normalized) return [...items];\n\n const result: ContextMenuItemProps[] = [];\n let pendingStructural: ContextMenuItemProps[] = [];\n\n for (const item of items) {\n if (item.type === \"option\") {\n const label = textFromNode(item.label).toLowerCase();\n if (label.includes(normalized)) {\n result.push(...pendingStructural, item);\n pendingStructural = [];\n }\n continue;\n }\n\n if (item.type === \"heading\") {\n pendingStructural = [item];\n continue;\n }\n\n if (item.type === \"divider\") {\n if (result.length > 0) pendingStructural.push(item);\n continue;\n }\n }\n\n return result;\n};\n\nconst isOption = (\n item: ContextMenuItemProps\n): item is ContextMenuOptionItemProps => item.type === \"option\";\n\nconst ContextMenuRoot = forwardRef<HTMLElement, ContextMenuProps>(\n (\n {\n children,\n type = \"list\",\n items = [],\n size = \"md\",\n searchable,\n loading,\n isLoading,\n emptyMessage = DEFAULT_EMPTY_MESSAGE,\n empty,\n isOpen: propIsOpen,\n onOpenChange,\n trigger,\n triggerFullWidth = false,\n placement = \"bottom-start\",\n offset = 4,\n position,\n width,\n maxHeight = 300,\n withArrow = false,\n onSelect,\n closeOnSelect,\n \"aria-label\": ariaLabel,\n testID,\n \"data-testid\": dataTestId,\n themeMode,\n themeProductContext,\n style,\n },\n ref\n ) => {\n const { theme: rawTheme } = useResolvedTheme({\n themeMode,\n themeProductContext,\n });\n const xuiTheme = rawTheme as ContextMenuTheme;\n const menuId = useId();\n const overlayLayer = useOverlayLayer();\n const modalStackDepth = useModalStackDepth();\n const openModalDepthRef = useRef<number | null>(null);\n const [internalIsOpen, setInternalIsOpen] = useState(false);\n const [activeIndex, setActiveIndex] = useState(-1);\n const [cellsVersion, setCellsVersion] = useState(0);\n const [query, setQuery] = useState(\"\");\n const [debouncedQuery, setDebouncedQuery] = useState(\"\");\n const [activeSubmenuId, setActiveSubmenuId] = useState<string | null>(null);\n const containerRef = useRef<HTMLDivElement | null>(null);\n const triggerRef = useRef<HTMLElement | null>(null);\n const panelRef = useRef<HTMLElement | null>(null);\n const cellsRef = useRef<CellEntry[]>([]);\n\n const isOpen = propIsOpen !== undefined ? propIsOpen : internalIsOpen;\n const sizeStyles = xuiTheme.sizing.contextMenu(size);\n const borderRadius = xuiTheme.shape?.contextMenu?.[size]?.borderRadius ?? 8;\n const shouldCloseOnSelect =\n closeOnSelect ?? (type === \"checkbox\" ? false : true);\n\n // With an arrow, the tip protrudes past the panel edge, so push the panel\n // out by that amount to keep `offset` measured to the visible arrow tip.\n const positionOffset = withArrow ? offset + ARROW_TIP_PROTRUSION : offset;\n\n const positioned = useContextMenuPosition({\n triggerRef,\n panelRef,\n containerRef,\n isOpen: isOpen && !!trigger && !position,\n placement,\n offset: positionOffset,\n });\n\n const resolvedPlacement: ContextMenuPlacement =\n positioned?.placement ?? placement;\n\n const getArrowStyle = (\n arrowPlacement: ContextMenuPlacement\n ): React.CSSProperties => {\n const isTop = arrowPlacement.startsWith(\"top\");\n const arrowStyle: React.CSSProperties = {\n position: \"absolute\",\n width: ARROW_SIZE,\n height: ARROW_SIZE,\n backgroundColor: xuiTheme.colors.background.secondary,\n borderStyle: \"solid\",\n borderColor: xuiTheme.colors.border.secondary,\n // 1px outline only on the two outward-facing edges of the rotated square\n borderWidth: isTop ? \"0 1px 1px 0\" : \"1px 0 0 1px\",\n transform: \"rotate(45deg)\",\n pointerEvents: \"none\",\n };\n // Cross axis: sit half outside the panel edge nearest the trigger.\n if (isTop) arrowStyle.bottom = -ARROW_HALF;\n else arrowStyle.top = -ARROW_HALF;\n // Main axis: align toward the trigger side.\n if (arrowPlacement.endsWith(\"center\")) {\n arrowStyle.left = \"50%\";\n arrowStyle.marginLeft = -ARROW_HALF;\n } else if (arrowPlacement.endsWith(\"end\")) {\n arrowStyle.right = ARROW_EDGE_OFFSET;\n } else {\n arrowStyle.left = ARROW_EDGE_OFFSET;\n }\n return arrowStyle;\n };\n\n const setOpen = useCallback(\n (nextOpen: boolean) => {\n if (propIsOpen === undefined) setInternalIsOpen(nextOpen);\n onOpenChange?.(nextOpen);\n if (!nextOpen) setActiveIndex(-1);\n },\n [propIsOpen, onOpenChange]\n );\n\n const closeMenu = useCallback(() => {\n setOpen(false);\n }, [setOpen]);\n\n const toggleMenu = useCallback(() => {\n setOpen(!isOpen);\n }, [isOpen, setOpen]);\n\n const registerCell = useCallback((id: string, meta: CellMeta) => {\n const existingIndex = cellsRef.current.findIndex(\n (cell) => cell.id === id\n );\n if (existingIndex >= 0) {\n cellsRef.current[existingIndex] = { id, meta };\n setCellsVersion((version) => version + 1);\n return existingIndex;\n }\n cellsRef.current.push({ id, meta });\n setCellsVersion((version) => version + 1);\n return cellsRef.current.length - 1;\n }, []);\n\n const unregisterCell = useCallback((id: string) => {\n const index = cellsRef.current.findIndex((cell) => cell.id === id);\n if (index >= 0) {\n cellsRef.current.splice(index, 1);\n setCellsVersion((version) => version + 1);\n }\n }, []);\n\n const getCellIndex = useCallback((id: string) => {\n return cellsRef.current.findIndex((cell) => cell.id === id);\n }, []);\n\n const cells = useMemo(() => [...cellsRef.current], [cellsVersion]);\n const keyboard = useKeyboardNavigation({\n isOpen,\n cells,\n activeIndex,\n setActiveIndex,\n onClose: closeMenu,\n triggerRef,\n });\n\n useEffect(() => {\n if (!isOpen) {\n cellsRef.current = [];\n setCellsVersion((version) => version + 1);\n setQuery(\"\");\n setDebouncedQuery(\"\");\n setActiveSubmenuId(null);\n }\n }, [isOpen]);\n\n // Dismiss the menu when a modal opens over it. Selecting an item that opens\n // a confirmation modal (e.g. StatusDropdown) would otherwise leave the menu\n // orphaned above/behind the modal, and the modal shields it from the\n // outside-click that would normally close it. Capture the modal depth when\n // the menu opens; close once a deeper modal appears. A menu opened inside a\n // modal keeps the depth it was born at, so its own modal never closes it.\n useEffect(() => {\n if (!isOpen) {\n openModalDepthRef.current = null;\n return;\n }\n if (openModalDepthRef.current === null) {\n openModalDepthRef.current = modalStackDepth;\n return;\n }\n if (modalStackDepth > openModalDepthRef.current) {\n closeMenu();\n }\n }, [isOpen, modalStackDepth, closeMenu]);\n\n useEffect(() => {\n const timer = setTimeout(\n () => setDebouncedQuery(query),\n SEARCH_DEBOUNCE_MS\n );\n return () => clearTimeout(timer);\n }, [query]);\n\n useEffect(() => {\n if (!isOpen || !trigger) return;\n\n const onMouseDown = (event: MouseEvent) => {\n const target = event.target as Node | null;\n if (!target) return;\n if (containerRef.current?.contains(target)) return;\n\n // Portal-aware outside-close. Dropdown-style children (Select,\n // MultiSelect, DatePicker, …) render their option list through a React\n // portal mounted on document.body, so the option node lives OUTSIDE the\n // ContextMenu subtree even though it is logically part of the open menu.\n // Without this guard a mousedown on a portaled option reads as an\n // outside click and dismisses the whole ContextMenu before the option's\n // own click resolves (FEP-836). Walk the composed event path so a click\n // anywhere inside a registered floating layer counts as \"inside\".\n const path =\n typeof event.composedPath === \"function\" ? event.composedPath() : [];\n const isInsidePortaledLayer = path.length\n ? path.some(\n (node) =>\n node instanceof Element && node.matches(PORTALED_LAYER_SELECTOR)\n )\n : target instanceof Element &&\n !!target.closest(PORTALED_LAYER_SELECTOR);\n if (isInsidePortaledLayer) return;\n\n closeMenu();\n };\n\n const onScroll = () => closeMenu();\n\n document.addEventListener(\"mousedown\", onMouseDown);\n window.addEventListener(\"scroll\", onScroll);\n return () => {\n document.removeEventListener(\"mousedown\", onMouseDown);\n window.removeEventListener(\"scroll\", onScroll);\n };\n }, [isOpen, trigger, closeMenu]);\n\n useLayoutEffect(() => {\n if (!isOpen || !panelRef.current) return;\n const searchbox =\n panelRef.current.querySelector<HTMLElement>('[role=\"searchbox\"]');\n const firstOption = panelRef.current.querySelector<HTMLElement>(\n '[role=\"menuitem\"],[role=\"menuitemcheckbox\"],[role=\"menuitemradio\"]'\n );\n (searchbox ?? firstOption)?.focus();\n }, [isOpen]);\n\n useLayoutEffect(() => {\n if (!isOpen || !panelRef.current) return;\n const activeElement = document.activeElement;\n if (activeElement && panelRef.current.contains(activeElement)) return;\n panelRef.current.focus();\n }, [isOpen, cellsVersion]);\n\n useEffect(() => {\n if (isOpen) return;\n triggerRef.current?.focus();\n }, [isOpen]);\n\n const contextValue: ContextMenuContextValue = useMemo(\n () => ({\n size,\n menuId,\n closeMenu,\n activeIndex,\n setActiveIndex,\n registerCell,\n unregisterCell,\n getCellIndex,\n cellsVersion,\n query,\n setQuery,\n activeSubmenuId,\n setActiveSubmenuId,\n }),\n [\n size,\n menuId,\n closeMenu,\n activeIndex,\n registerCell,\n unregisterCell,\n getCellIndex,\n cellsVersion,\n query,\n activeSubmenuId,\n ]\n );\n\n const renderPresetItem = (item: ContextMenuItemProps, index: number) => {\n if (!isOption(item)) {\n return (\n <ContextMenuItem\n key={`context-menu-item-${index}`}\n {...item}\n themeMode={themeMode}\n themeProductContext={themeProductContext}\n />\n );\n }\n\n const leadingControl =\n item.leadingControl ??\n (type === \"checkbox\"\n ? \"checkbox\"\n : type === \"radio\"\n ? \"radio\"\n : undefined);\n\n return (\n <ContextMenuItem\n key={`context-menu-item-${index}`}\n {...item}\n leadingControl={leadingControl}\n themeMode={themeMode}\n themeProductContext={themeProductContext}\n onSelect={() => {\n item.onSelect?.();\n onSelect?.(item);\n if (shouldCloseOnSelect) closeMenu();\n }}\n />\n );\n };\n\n const renderedItems = searchable\n ? filterItems(items, debouncedQuery)\n : [...items];\n\n const renderContent = () => {\n if (loading || isLoading || type === \"loading\") {\n const brandColor = xuiTheme.colors.control.brand.primary.bg;\n return (\n <Box\n padding={16}\n alignItems=\"center\"\n justifyContent=\"center\"\n minHeight={60}\n >\n <Spinner size=\"md\" color={brandColor} />\n </Box>\n );\n }\n\n if (children) return children;\n\n const content = renderedItems.map(renderPresetItem);\n if (searchable) {\n content.unshift(\n <div\n key=\"context-menu-search\"\n data-sticky=\"top\"\n style={{\n position: \"sticky\",\n top: 0,\n zIndex: 1,\n backgroundColor: xuiTheme.colors.background.secondary,\n }}\n >\n <ContextMenuItem\n type=\"search\"\n value={query}\n onValueChange={setQuery}\n placeholder=\"Search\"\n autoFocus\n themeMode={themeMode}\n themeProductContext={themeProductContext}\n />\n </div>\n );\n }\n\n if (content.length > (searchable ? 1 : 0)) return content;\n return empty ?? <div style={{ padding: 16 }}>{emptyMessage}</div>;\n };\n\n const assignPanelRef = (node: HTMLElement | null) => {\n panelRef.current = node;\n if (typeof ref === \"function\") ref(node);\n else if (ref) ref.current = node;\n };\n\n const assignTriggerRef = (node: HTMLElement | null) => {\n triggerRef.current = node;\n };\n\n const assignTriggerWrapperRef = (node: HTMLSpanElement | null) => {\n if (!node) {\n assignTriggerRef(null);\n return;\n }\n const firstChild = node.firstElementChild;\n assignTriggerRef(\n firstChild instanceof HTMLElement ? firstChild : (node as HTMLElement)\n );\n };\n\n const triggerNode =\n trigger && isValidElement(trigger) ? (\n <span\n ref={assignTriggerWrapperRef}\n onClick={(event) => {\n if (!event.defaultPrevented) toggleMenu();\n }}\n style={{\n display: \"inline-flex\",\n width: triggerFullWidth ? \"100%\" : \"auto\",\n }}\n >\n {cloneElement(trigger as React.ReactElement<any>, {\n \"aria-haspopup\": \"menu\",\n \"aria-expanded\": isOpen ? \"true\" : \"false\",\n })}\n </span>\n ) : trigger ? (\n <span\n ref={assignTriggerRef}\n role=\"button\"\n tabIndex={0}\n aria-haspopup=\"menu\"\n aria-expanded={isOpen ? \"true\" : \"false\"}\n onClick={toggleMenu}\n >\n {trigger}\n </span>\n ) : null;\n\n const positionStyle: React.CSSProperties | undefined = position\n ? {\n position: \"fixed\" as const,\n left: position.x,\n top: position.y,\n }\n : trigger\n ? positioned\n ? {\n position: \"absolute\" as const,\n left: positioned.left,\n top: positioned.top,\n }\n : {\n position: \"absolute\" as const,\n visibility: \"hidden\" as const,\n }\n : undefined;\n\n return (\n <ContextMenuContext.Provider value={contextValue}>\n <div\n ref={containerRef}\n style={{\n position: trigger || position ? \"relative\" : undefined,\n display: trigger ? \"inline-block\" : undefined,\n }}\n >\n {triggerNode}\n {isOpen && (\n <Box\n ref={assignPanelRef}\n role=\"menu\"\n aria-label={ariaLabel}\n data-testid={dataTestId ?? testID ?? \"context-menu\"}\n data-placement={resolvedPlacement}\n backgroundColor={xuiTheme.colors.background.secondary}\n borderColor={xuiTheme.colors.border.secondary}\n borderWidth={1}\n borderRadius={borderRadius}\n paddingVertical={sizeStyles.paddingVertical}\n width={width}\n minWidth={sizeStyles.minWidth}\n tabIndex={-1}\n onKeyDown={keyboard.handleKeyDown}\n onMouseLeave={() => setActiveIndex(-1)}\n style={{\n ...positionStyle,\n ...style,\n zIndex: overlayLayer + LAYER_OFFSET.menu,\n boxShadow: PANEL_SHADOW,\n ...(withArrow\n ? {\n overflow: \"visible\",\n }\n : {\n maxHeight,\n overflowY: \"auto\",\n }),\n outline: \"none\",\n }}\n >\n {withArrow ? (\n <>\n <span\n aria-hidden=\"true\"\n data-testid=\"context-menu-arrow\"\n style={getArrowStyle(resolvedPlacement)}\n />\n <div style={{ maxHeight, overflowY: \"auto\", borderRadius }}>\n {renderContent()}\n </div>\n </>\n ) : (\n renderContent()\n )}\n </Box>\n )}\n </div>\n </ContextMenuContext.Provider>\n );\n }\n);\n\nContextMenuRoot.displayName = \"ContextMenu\";\n\nexport const ContextMenu = Object.assign(ContextMenuRoot, {\n Item: ContextMenuItem,\n Submenu: ContextMenuSubmenu,\n});\n","import React from \"react\";\nimport styled from \"styled-components\";\nimport type { BoxProps } from \"@xsolla/xui-primitives-core\";\nimport { createFilteredElement } from \"./filterDOMProps\";\n\nconst FilteredDiv = createFilteredElement(\"div\");\n\nconst StyledBox = styled(FilteredDiv)<BoxProps>`\n display: flex;\n box-sizing: border-box;\n background-color: ${(props) => props.backgroundColor || \"transparent\"};\n border-color: ${(props) => props.borderColor || \"transparent\"};\n border-width: ${(props) =>\n typeof props.borderWidth === \"number\"\n ? `${props.borderWidth}px`\n : props.borderWidth || 0};\n\n ${(props) =>\n props.borderBottomWidth !== undefined &&\n `\n border-bottom-width: ${typeof props.borderBottomWidth === \"number\" ? `${props.borderBottomWidth}px` : props.borderBottomWidth};\n border-bottom-color: ${props.borderBottomColor || props.borderColor || \"transparent\"};\n border-bottom-style: solid;\n `}\n ${(props) =>\n props.borderTopWidth !== undefined &&\n `\n border-top-width: ${typeof props.borderTopWidth === \"number\" ? `${props.borderTopWidth}px` : props.borderTopWidth};\n border-top-color: ${props.borderTopColor || props.borderColor || \"transparent\"};\n border-top-style: solid;\n `}\n ${(props) =>\n props.borderLeftWidth !== undefined &&\n `\n border-left-width: ${typeof props.borderLeftWidth === \"number\" ? `${props.borderLeftWidth}px` : props.borderLeftWidth};\n border-left-color: ${props.borderLeftColor || props.borderColor || \"transparent\"};\n border-left-style: solid;\n `}\n ${(props) =>\n props.borderRightWidth !== undefined &&\n `\n border-right-width: ${typeof props.borderRightWidth === \"number\" ? `${props.borderRightWidth}px` : props.borderRightWidth};\n border-right-color: ${props.borderRightColor || props.borderColor || \"transparent\"};\n border-right-style: solid;\n `}\n\n border-style: ${(props) =>\n props.borderStyle ||\n (props.borderWidth ||\n props.borderBottomWidth ||\n props.borderTopWidth ||\n props.borderLeftWidth ||\n props.borderRightWidth\n ? \"solid\"\n : \"none\")};\n border-radius: ${(props) =>\n typeof props.borderRadius === \"number\"\n ? `${props.borderRadius}px`\n : props.borderRadius || 0};\n height: ${(props) =>\n typeof props.height === \"number\"\n ? `${props.height}px`\n : props.height || \"auto\"};\n width: ${(props) =>\n typeof props.width === \"number\"\n ? `${props.width}px`\n : props.width || \"auto\"};\n min-width: ${(props) =>\n typeof props.minWidth === \"number\"\n ? `${props.minWidth}px`\n : props.minWidth || \"auto\"};\n min-height: ${(props) =>\n typeof props.minHeight === \"number\"\n ? `${props.minHeight}px`\n : props.minHeight || \"auto\"};\n max-width: ${(props) =>\n typeof props.maxWidth === \"number\"\n ? `${props.maxWidth}px`\n : props.maxWidth || \"none\"};\n max-height: ${(props) =>\n typeof props.maxHeight === \"number\"\n ? `${props.maxHeight}px`\n : props.maxHeight || \"none\"};\n\n padding: ${(props) =>\n typeof props.padding === \"number\"\n ? `${props.padding}px`\n : props.padding || 0};\n ${(props) =>\n props.paddingHorizontal &&\n `\n padding-left: ${typeof props.paddingHorizontal === \"number\" ? `${props.paddingHorizontal}px` : props.paddingHorizontal};\n padding-right: ${typeof props.paddingHorizontal === \"number\" ? `${props.paddingHorizontal}px` : props.paddingHorizontal};\n `}\n ${(props) =>\n props.paddingVertical &&\n `\n padding-top: ${typeof props.paddingVertical === \"number\" ? `${props.paddingVertical}px` : props.paddingVertical};\n padding-bottom: ${typeof props.paddingVertical === \"number\" ? `${props.paddingVertical}px` : props.paddingVertical};\n `}\n ${(props) =>\n props.paddingTop !== undefined &&\n `padding-top: ${typeof props.paddingTop === \"number\" ? `${props.paddingTop}px` : props.paddingTop};`}\n ${(props) =>\n props.paddingBottom !== undefined &&\n `padding-bottom: ${typeof props.paddingBottom === \"number\" ? `${props.paddingBottom}px` : props.paddingBottom};`}\n ${(props) =>\n props.paddingLeft !== undefined &&\n `padding-left: ${typeof props.paddingLeft === \"number\" ? `${props.paddingLeft}px` : props.paddingLeft};`}\n ${(props) =>\n props.paddingRight !== undefined &&\n `padding-right: ${typeof props.paddingRight === \"number\" ? `${props.paddingRight}px` : props.paddingRight};`}\n\n margin: ${(props) =>\n typeof props.margin === \"number\" ? `${props.margin}px` : props.margin || 0};\n ${(props) =>\n props.marginTop !== undefined &&\n `margin-top: ${typeof props.marginTop === \"number\" ? `${props.marginTop}px` : props.marginTop};`}\n ${(props) =>\n props.marginBottom !== undefined &&\n `margin-bottom: ${typeof props.marginBottom === \"number\" ? `${props.marginBottom}px` : props.marginBottom};`}\n ${(props) =>\n props.marginLeft !== undefined &&\n `margin-left: ${typeof props.marginLeft === \"number\" ? `${props.marginLeft}px` : props.marginLeft};`}\n ${(props) =>\n props.marginRight !== undefined &&\n `margin-right: ${typeof props.marginRight === \"number\" ? `${props.marginRight}px` : props.marginRight};`}\n\n flex-direction: ${(props) => props.flexDirection || \"column\"};\n flex-wrap: ${(props) => props.flexWrap || \"nowrap\"};\n align-items: ${(props) => props.alignItems || \"stretch\"};\n justify-content: ${(props) => props.justifyContent || \"flex-start\"};\n cursor: ${(props) =>\n props.cursor\n ? props.cursor\n : props.onClick || props.onPress\n ? \"pointer\"\n : \"inherit\"};\n position: ${(props) => props.position || \"static\"};\n top: ${(props) =>\n typeof props.top === \"number\" ? `${props.top}px` : props.top};\n bottom: ${(props) =>\n typeof props.bottom === \"number\" ? `${props.bottom}px` : props.bottom};\n left: ${(props) =>\n typeof props.left === \"number\" ? `${props.left}px` : props.left};\n right: ${(props) =>\n typeof props.right === \"number\" ? `${props.right}px` : props.right};\n flex: ${(props) => props.flex};\n flex-shrink: ${(props) => props.flexShrink ?? 1};\n gap: ${(props) =>\n typeof props.gap === \"number\" ? `${props.gap}px` : props.gap || 0};\n align-self: ${(props) => props.alignSelf || \"auto\"};\n overflow: ${(props) => props.overflow || \"visible\"};\n overflow-x: ${(props) => props.overflowX || \"visible\"};\n overflow-y: ${(props) => props.overflowY || \"visible\"};\n z-index: ${(props) => props.zIndex};\n opacity: ${(props) => (props.disabled ? 0.5 : 1)};\n pointer-events: ${(props) => (props.disabled ? \"none\" : \"auto\")};\n\n &:hover {\n ${(props) =>\n props.hoverStyle?.backgroundColor &&\n `background-color: ${props.hoverStyle.backgroundColor};`}\n ${(props) =>\n props.hoverStyle?.borderColor &&\n `border-color: ${props.hoverStyle.borderColor};`}\n }\n\n &:active {\n ${(props) =>\n props.pressStyle?.backgroundColor &&\n `background-color: ${props.pressStyle.backgroundColor};`}\n }\n`;\n\nexport const Box = React.forwardRef<\n HTMLDivElement | HTMLButtonElement,\n BoxProps\n>(\n (\n {\n children,\n onPress,\n onKeyDown,\n onKeyUp,\n role,\n \"aria-label\": ariaLabel,\n \"aria-labelledby\": ariaLabelledBy,\n \"aria-current\": ariaCurrent,\n \"aria-disabled\": ariaDisabled,\n \"aria-live\": ariaLive,\n \"aria-busy\": ariaBusy,\n \"aria-describedby\": ariaDescribedBy,\n \"aria-expanded\": ariaExpanded,\n \"aria-haspopup\": ariaHasPopup,\n \"aria-pressed\": ariaPressed,\n \"aria-controls\": ariaControls,\n tabIndex,\n as,\n src,\n alt,\n onError,\n onLoad,\n type,\n disabled,\n id,\n testID,\n \"data-testid\": dataTestId,\n ...props\n },\n ref\n ) => {\n // Handle as=\"img\" for rendering images with proper border-radius\n if (as === \"img\" && src) {\n return (\n <img\n src={src}\n alt={alt || \"\"}\n onError={onError}\n onLoad={onLoad}\n style={{\n display: \"block\",\n objectFit: \"cover\",\n width:\n typeof props.width === \"number\"\n ? `${props.width}px`\n : props.width,\n height:\n typeof props.height === \"number\"\n ? `${props.height}px`\n : props.height,\n borderRadius:\n typeof props.borderRadius === \"number\"\n ? `${props.borderRadius}px`\n : props.borderRadius,\n position: props.position,\n top: typeof props.top === \"number\" ? `${props.top}px` : props.top,\n left:\n typeof props.left === \"number\" ? `${props.left}px` : props.left,\n right:\n typeof props.right === \"number\"\n ? `${props.right}px`\n : props.right,\n bottom:\n typeof props.bottom === \"number\"\n ? `${props.bottom}px`\n : props.bottom,\n ...props.style,\n }}\n />\n );\n }\n\n return (\n <StyledBox\n ref={ref}\n elementType={as}\n id={id}\n type={as === \"button\" ? type || \"button\" : undefined}\n disabled={as === \"button\" ? disabled : undefined}\n onClick={onPress}\n onKeyDown={onKeyDown}\n onKeyUp={onKeyUp}\n role={role}\n aria-label={ariaLabel}\n aria-labelledby={ariaLabelledBy}\n aria-current={ariaCurrent}\n aria-disabled={ariaDisabled}\n aria-busy={ariaBusy}\n aria-describedby={ariaDescribedBy}\n aria-expanded={ariaExpanded}\n aria-haspopup={ariaHasPopup}\n aria-pressed={ariaPressed}\n aria-controls={ariaControls}\n aria-live={ariaLive}\n tabIndex={tabIndex !== undefined ? tabIndex : undefined}\n data-testid={dataTestId || testID}\n {...props}\n >\n {children}\n </StyledBox>\n );\n }\n);\n\nBox.displayName = \"Box\";\n","import React from \"react\";\nimport isPropValid from \"@emotion/is-prop-valid\";\n\n// Props that @emotion/is-prop-valid incorrectly treats as valid HTML.\n// These are React Native or component-specific props that match\n// valid HTML patterns (on* event handlers, SVG attributes).\nexport const ADDITIONAL_BLOCKED_PROPS = new Set([\n // RN-only event handlers (pass isPropValid's on* pattern)\n \"onPress\",\n \"onChangeText\",\n \"onLayout\",\n \"onMoveShouldSetResponder\",\n \"onResponderGrant\",\n \"onResponderMove\",\n \"onResponderRelease\",\n \"onResponderTerminate\",\n // SVG attributes that pass isPropValid\n \"strokeWidth\",\n // CSS properties that pass isPropValid but are used as component props\n \"overflow\",\n \"cursor\",\n \"fontSize\",\n \"fontWeight\",\n \"fontFamily\",\n \"textDecoration\",\n]);\n\nfunction shouldForwardProp(key: string): boolean {\n if (ADDITIONAL_BLOCKED_PROPS.has(key)) return false;\n return isPropValid(key);\n}\n\n/**\n * Creates a React component that renders the given HTML tag\n * but filters out non-HTML props before they reach the DOM.\n *\n * Uses @emotion/is-prop-valid (same library styled-components v4\n * uses internally) to automatically block invalid HTML attributes,\n * plus a small blocklist for false positives (RN on* handlers, SVG attrs).\n *\n * Usage: `const FilteredDiv = createFilteredElement(\"div\");`\n * Then: `const StyledBox = styled(FilteredDiv)<BoxProps>\\`...\\`;`\n *\n * styled-components can still read ALL props for CSS interpolation,\n * but only valid HTML attributes are forwarded to the DOM element.\n */\nexport function createFilteredElement(defaultTag: string) {\n const Component = React.forwardRef<HTMLElement, Record<string, unknown>>(\n ({ children, elementType, ...props }, ref) => {\n const Tag = (elementType as string) || defaultTag;\n const htmlProps: Record<string, unknown> = {};\n for (const key of Object.keys(props)) {\n if (shouldForwardProp(key)) {\n htmlProps[key] = props[key];\n }\n }\n return React.createElement(\n Tag,\n { ref, ...htmlProps },\n children as React.ReactNode\n );\n }\n );\n Component.displayName = `Filtered(${defaultTag})`;\n return Component;\n}\n","function memoize(fn) {\n var cache = {};\n return function (arg) {\n if (cache[arg] === undefined) cache[arg] = fn(arg);\n return cache[arg];\n };\n}\n\nexport default memoize;\n","import memoize from '@emotion/memoize';\n\nvar reactPropsRegex = /^((children|dangerouslySetInnerHTML|key|ref|autoFocus|defaultValue|defaultChecked|innerHTML|suppressContentEditableWarning|suppressHydrationWarning|valueLink|accept|acceptCharset|accessKey|action|allow|allowUserMedia|allowPaymentRequest|allowFullScreen|allowTransparency|alt|async|autoComplete|autoPlay|capture|cellPadding|cellSpacing|challenge|charSet|checked|cite|classID|className|cols|colSpan|content|contentEditable|contextMenu|controls|controlsList|coords|crossOrigin|data|dateTime|decoding|default|defer|dir|disabled|disablePictureInPicture|download|draggable|encType|form|formAction|formEncType|formMethod|formNoValidate|formTarget|frameBorder|headers|height|hidden|high|href|hrefLang|htmlFor|httpEquiv|id|inputMode|integrity|is|keyParams|keyType|kind|label|lang|list|loading|loop|low|marginHeight|marginWidth|max|maxLength|media|mediaGroup|method|min|minLength|multiple|muted|name|nonce|noValidate|open|optimum|pattern|placeholder|playsInline|poster|preload|profile|radioGroup|readOnly|referrerPolicy|rel|required|reversed|role|rows|rowSpan|sandbox|scope|scoped|scrolling|seamless|selected|shape|size|sizes|slot|span|spellCheck|src|srcDoc|srcLang|srcSet|start|step|style|summary|tabIndex|target|title|type|useMap|value|width|wmode|wrap|about|datatype|inlist|prefix|property|resource|typeof|vocab|autoCapitalize|autoCorrect|autoSave|color|inert|itemProp|itemScope|itemType|itemID|itemRef|on|results|security|unselectable|accentHeight|accumulate|additive|alignmentBaseline|allowReorder|alphabetic|amplitude|arabicForm|ascent|attributeName|attributeType|autoReverse|azimuth|baseFrequency|baselineShift|baseProfile|bbox|begin|bias|by|calcMode|capHeight|clip|clipPathUnits|clipPath|clipRule|colorInterpolation|colorInterpolationFilters|colorProfile|colorRendering|contentScriptType|contentStyleType|cursor|cx|cy|d|decelerate|descent|diffuseConstant|direction|display|divisor|dominantBaseline|dur|dx|dy|edgeMode|elevation|enableBackground|end|exponent|externalResourcesRequired|fill|fillOpacity|fillRule|filter|filterRes|filterUnits|floodColor|floodOpacity|focusable|fontFamily|fontSize|fontSizeAdjust|fontStretch|fontStyle|fontVariant|fontWeight|format|from|fr|fx|fy|g1|g2|glyphName|glyphOrientationHorizontal|glyphOrientationVertical|glyphRef|gradientTransform|gradientUnits|hanging|horizAdvX|horizOriginX|ideographic|imageRendering|in|in2|intercept|k|k1|k2|k3|k4|kernelMatrix|kernelUnitLength|kerning|keyPoints|keySplines|keyTimes|lengthAdjust|letterSpacing|lightingColor|limitingConeAngle|local|markerEnd|markerMid|markerStart|markerHeight|markerUnits|markerWidth|mask|maskContentUnits|maskUnits|mathematical|mode|numOctaves|offset|opacity|operator|order|orient|orientation|origin|overflow|overlinePosition|overlineThickness|panose1|paintOrder|pathLength|patternContentUnits|patternTransform|patternUnits|pointerEvents|points|pointsAtX|pointsAtY|pointsAtZ|preserveAlpha|preserveAspectRatio|primitiveUnits|r|radius|refX|refY|renderingIntent|repeatCount|repeatDur|requiredExtensions|requiredFeatures|restart|result|rotate|rx|ry|scale|seed|shapeRendering|slope|spacing|specularConstant|specularExponent|speed|spreadMethod|startOffset|stdDeviation|stemh|stemv|stitchTiles|stopColor|stopOpacity|strikethroughPosition|strikethroughThickness|string|stroke|strokeDasharray|strokeDashoffset|strokeLinecap|strokeLinejoin|strokeMiterlimit|strokeOpacity|strokeWidth|surfaceScale|systemLanguage|tableValues|targetX|targetY|textAnchor|textDecoration|textRendering|textLength|to|transform|u1|u2|underlinePosition|underlineThickness|unicode|unicodeBidi|unicodeRange|unitsPerEm|vAlphabetic|vHanging|vIdeographic|vMathematical|values|vectorEffect|version|vertAdvY|vertOriginX|vertOriginY|viewBox|viewTarget|visibility|widths|wordSpacing|writingMode|x|xHeight|x1|x2|xChannelSelector|xlinkActuate|xlinkArcrole|xlinkHref|xlinkRole|xlinkShow|xlinkTitle|xlinkType|xmlBase|xmlns|xmlnsXlink|xmlLang|xmlSpace|y|y1|y2|yChannelSelector|z|zoomAndPan|for|class|autofocus)|(([Dd][Aa][Tt][Aa]|[Aa][Rr][Ii][Aa]|x)-.*))$/; // https://esbench.com/bench/5bfee68a4cd7e6009ef61d23\n\nvar index = memoize(function (prop) {\n return reactPropsRegex.test(prop) || prop.charCodeAt(0) === 111\n /* o */\n && prop.charCodeAt(1) === 110\n /* n */\n && prop.charCodeAt(2) < 91;\n}\n/* Z+1 */\n);\n\nexport default index;\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 useOverlayLayer,\n LAYER_OFFSET,\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 { Search } from \"@xsolla/xui-icons-base\";\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\nconst SUBMENU_GAP = 8;\nconst SUBMENU_VIEWPORT_PADDING = 8;\n\nconst clipsOverflow = (style: CSSStyleDeclaration) => {\n return /(auto|scroll|hidden|clip)/.test(\n `${style.overflow}${style.overflowX}${style.overflowY}`\n );\n};\n\nconst getSubmenuBoundary = (node: HTMLElement) => {\n const viewport = {\n top: SUBMENU_VIEWPORT_PADDING,\n right: window.innerWidth - SUBMENU_VIEWPORT_PADDING,\n bottom: window.innerHeight - SUBMENU_VIEWPORT_PADDING,\n left: SUBMENU_VIEWPORT_PADDING,\n };\n\n let current = node.parentElement;\n while (current && current !== document.body) {\n const style = window.getComputedStyle(current);\n if (clipsOverflow(style) && current.getAttribute(\"role\") !== \"menu\") {\n const rect = current.getBoundingClientRect();\n return {\n top: Math.max(viewport.top, rect.top + SUBMENU_VIEWPORT_PADDING),\n right: Math.min(viewport.right, rect.right - SUBMENU_VIEWPORT_PADDING),\n bottom: Math.min(\n viewport.bottom,\n rect.bottom - SUBMENU_VIEWPORT_PADDING\n ),\n left: Math.max(viewport.left, rect.left + SUBMENU_VIEWPORT_PADDING),\n };\n }\n current = current.parentElement;\n }\n\n return viewport;\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 slot,\n slotContent,\n value,\n hint,\n trailingIcon,\n keyboardShortcut,\n hasSubmenu,\n submenu,\n onSelect,\n onCheckedChange,\n testID,\n themeMode,\n themeProductContext,\n \"data-testid\": testId,\n}) => {\n const { theme: rawTheme } = useResolvedTheme({\n themeMode,\n themeProductContext,\n });\n const theme = rawTheme as any;\n const overlayLayer = useOverlayLayer();\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 registerCell = ctx?.registerCell;\n const unregisterCell = ctx?.unregisterCell;\n const getCellIndex = ctx?.getCellIndex;\n const [isHovered, setIsHovered] = useState(false);\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 // A submenu this cell renders itself: submenu content passed via the\n // `submenu` prop (the `items` presets and direct `hasSubmenu` children). The\n // compound <ContextMenu.Submenu> path renders its own panel and manages\n // `activeSubmenuId` itself, passing `hasSubmenu` WITHOUT a `submenu` prop, so\n // it is excluded from the coordination below.\n const ownsSubmenu = Boolean(hasSubmenu && submenu != null);\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(() => {\n setSubmenuOpen(false);\n if (ownsSubmenu && ctx?.activeSubmenuId === id) {\n ctx.setActiveSubmenuId?.(null);\n }\n }, 120);\n };\n\n useEffect(() => () => cancelClose(), []);\n\n // Close this cell's submenu the instant a sibling submenu becomes the active\n // one. Preset submenus each hold independent open state, so without this a\n // fast parent-to-parent switch would leave the outgoing submenu visible for\n // the full 120ms close grace while the incoming one opens - two submenus on\n // screen at once. Keying off the shared `activeSubmenuId` collapses that\n // overlap window to a single render.\n useEffect(() => {\n if (!ownsSubmenu || !submenuOpen) return;\n const activeId = ctx?.activeSubmenuId;\n if (activeId != null && activeId !== id) {\n cancelClose();\n setSubmenuOpen(false);\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [ctx?.activeSubmenuId, ownsSubmenu, submenuOpen, id]);\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 // Nested submenus render as flat portals on document.body, so a click in\n // a DEEPER submenu is not contained by this option's submenuWrapperRef.\n // Without this guard every ancestor treats that click as an outside\n // press and collapses the whole chain (a leaf selection closed all\n // menus). Any context-menu portal in the ancestry means the click is\n // still inside the open menu tree — keep this submenu open and let the\n // owning level decide what to do.\n if (target.closest(\"[data-xui-context-menu-portal]\")) return;\n setSubmenuOpen(false);\n return;\n }\n if (inSubmenu) {\n // Activating a plain leaf action dismisses its submenu. Leave checkbox\n // and radio controls (and nested submenu triggers) open so the user can\n // see the change and keep interacting.\n const activated = target.closest(\n '[role=\"menuitem\"],[role=\"menuitemcheckbox\"],[role=\"menuitemradio\"]'\n );\n const isLeafAction =\n activated?.getAttribute(\"role\") === \"menuitem\" &&\n activated.getAttribute(\"aria-haspopup\") !== \"menu\";\n if (isLeafAction) 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\n const update = () => {\n const node = optionRef.current;\n if (!node) return;\n const rect = node.getBoundingClientRect();\n const submenuRect = submenuWrapperRef.current?.getBoundingClientRect();\n const submenuWidth = submenuRect?.width ?? 0;\n const submenuHeight = submenuRect?.height ?? 0;\n const boundary = getSubmenuBoundary(node);\n\n const rightSideLeft = rect.right + SUBMENU_GAP;\n const leftSideLeft = rect.left - SUBMENU_GAP - submenuWidth;\n const opensLeft =\n submenuWidth > 0 && rightSideLeft + submenuWidth > boundary.right;\n\n let left = opensLeft ? leftSideLeft : rightSideLeft;\n\n if (submenuWidth > 0) {\n if (opensLeft) {\n left = Math.max(SUBMENU_VIEWPORT_PADDING, left);\n } else {\n left = Math.min(\n Math.max(boundary.left, left),\n Math.max(boundary.left, boundary.right - submenuWidth)\n );\n }\n }\n\n let top = rect.top;\n if (submenuHeight > 0 && top + submenuHeight > boundary.bottom) {\n top = boundary.bottom - submenuHeight;\n }\n top = Math.max(boundary.top, top);\n\n setSubmenuPos((prev) =>\n prev?.top === top && prev.left === left ? prev : { top, left }\n );\n };\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 });\n const onSelectRef = React.useRef(onSelect);\n onSelectRef.current = onSelect;\n // Register on mount / unregister on unmount. Deps are the stable registry\n // callbacks + id only - NOT `ctx`, whose identity changes on every hover\n // (activeIndex). Depending on `ctx` here churned register/unregister and, on\n // React <18 (interleaved passive-effect flush), collapsed every row to the\n // same index so one hover highlighted all rows (FEP-764).\n useEffect(() => {\n if (!registerCell || !unregisterCell) return;\n registerCell(id, {\n type: \"option\",\n onSelect: () => onSelectRef.current?.(),\n });\n return () => unregisterCell(id);\n }, [registerCell, unregisterCell, id]);\n\n // Keep registry metadata (disabled) in sync without reordering the cell.\n useEffect(() => {\n if (!registerCell) return;\n registerCell(id, {\n type: \"option\",\n disabled,\n onSelect: () => onSelectRef.current?.(),\n });\n }, [registerCell, id, disabled]);\n\n // Derive index live from the registry instead of caching it in state, so it\n // is always correct after dynamic add/remove without per-item re-registration.\n const index = getCellIndex ? getCellIndex(id) : -1;\n const isActive = ctx ? index >= 0 && ctx.activeIndex === index : false;\n const inHoverState =\n isActive || (!ctx && isHovered) || (hasSubmenu && submenuOpen);\n\n const handleEnter = () => {\n if (disabled) return;\n if (ctx && index >= 0) ctx.setActiveIndex(index);\n if (!ctx) setIsHovered(true);\n if (hasSubmenu) setSubmenuOpen(true);\n // Claim the shared active-submenu slot the instant the pointer enters, so\n // any OTHER open submenu closes immediately (see the effect above) instead\n // of lingering for its 120ms close grace and overlapping this one during a\n // fast parent-to-parent switch.\n if (ownsSubmenu) ctx?.setActiveSubmenuId?.(id);\n };\n\n const handleLeave = () => {\n if (!ctx) setIsHovered(false);\n if (hasSubmenu) scheduleClose();\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\n ? leadingControl === \"radio\"\n ? \"menuitemradio\"\n : \"menuitemcheckbox\"\n : \"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 if (checked !== undefined) {\n onCheckedChange?.(!checked);\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 if (checked !== undefined) {\n onCheckedChange?.(!checked);\n }\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={handleLeave}\n onFocus={handleEnter}\n onBlur={() => {\n if (!ctx) setIsHovered(false);\n }}\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 {slot}\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 data-xui-context-menu-portal={ctx?.menuId}\n onMouseEnter={cancelClose}\n onMouseLeave={scheduleClose}\n style={{\n position: \"fixed\",\n top: submenuPos.top,\n left: submenuPos.left,\n // Same band as the parent menu; the submenu portal mounts later in\n // the DOM so it paints above it (holds for arbitrary nesting depth).\n zIndex: overlayLayer + LAYER_OFFSET.menu,\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: rawTheme } = useResolvedTheme({\n themeMode,\n themeProductContext,\n });\n const theme = rawTheme as any;\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 registerCell = ctx?.registerCell;\n const unregisterCell = ctx?.unregisterCell;\n useEffect(() => {\n if (!registerCell || !unregisterCell) return;\n registerCell(id, { type: \"heading\" });\n return () => unregisterCell(id);\n }, [registerCell, unregisterCell, id]);\n\n return (\n <div\n role=\"presentation\"\n data-testid={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 onChange,\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: rawTheme } = useResolvedTheme({\n themeMode,\n themeProductContext,\n });\n const theme = rawTheme as any;\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 const registerCell = ctx?.registerCell;\n const unregisterCell = ctx?.unregisterCell;\n useEffect(() => {\n if (!registerCell || !unregisterCell) return;\n registerCell(id, { type: \"search\" });\n return () => unregisterCell(id);\n }, [registerCell, unregisterCell, id]);\n\n return (\n <div\n style={{\n boxSizing: \"border-box\",\n paddingLeft: sizing.searchPaddingHorizontal,\n paddingRight: sizing.searchPaddingHorizontal,\n paddingTop: sizing.searchPaddingVertical,\n paddingBottom: sizing.searchPaddingVertical,\n }}\n >\n <div\n style={{\n display: \"flex\",\n alignItems: \"center\",\n gap: 8,\n paddingBottom: 6,\n borderBottom: `1px solid ${theme.colors.border.secondary}`,\n }}\n >\n <Search\n variant=\"line\"\n size={sizing.searchIconSize}\n color={theme.colors.control.input.placeholder}\n aria-hidden\n />\n <input\n type=\"search\"\n role=\"searchbox\"\n aria-label={ariaLabel}\n placeholder={placeholder}\n value={value ?? \"\"}\n autoFocus={autoFocus}\n onChange={(e) => {\n onChange?.(e);\n onValueChange?.(e.target.value);\n }}\n data-testid={testId || testID}\n style={{\n flex: 1,\n minWidth: 0,\n boxSizing: \"border-box\",\n border: \"none\",\n outline: \"none\",\n background: \"transparent\",\n padding: 0,\n color: theme.colors.content.primary,\n fontSize: sizing.searchFontSize,\n lineHeight: `${sizing.searchLineHeight}px`,\n }}\n />\n </div>\n </div>\n );\n};\n\nconst DividerCell: React.FC<\n ContextMenuDividerItemProps & ThemeOverrideProps\n> = ({ themeMode, themeProductContext, \"data-testid\": testId }) => {\n const { theme: rawTheme } = useResolvedTheme({\n themeMode,\n themeProductContext,\n });\n const theme = rawTheme as any;\n const ctx = useContextMenu();\n const id = useId();\n const registerCell = ctx?.registerCell;\n const unregisterCell = ctx?.unregisterCell;\n useEffect(() => {\n if (!registerCell || !unregisterCell) return;\n registerCell(id, { type: \"divider\" });\n return () => unregisterCell(id);\n }, [registerCell, unregisterCell, 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 React, {\n useState,\n useRef,\n useEffect,\n useLayoutEffect,\n useCallback,\n} from \"react\";\n// @ts-expect-error - this will be resolved at build time\nimport { Box } from \"@xsolla/xui-primitives\";\nimport { useDesignSystem } from \"@xsolla/xui-core\";\nimport { ContextMenuItem } from \"./ContextMenuItem\";\nimport { useContextMenu } from \"./ContextMenuContext\";\nimport type { ContextMenuSubmenuProps } from \"./types\";\n\n/** Gap (px) between the parent menu panel and the submenu panel */\nconst SUBMENU_GAP = 4;\n/** Delay (ms) before the submenu opens on hover */\nconst OPEN_DELAY_MS = 200;\n/** Grace period (ms) before the submenu closes after the pointer leaves */\nconst CLOSE_GRACE_MS = 100;\n\n/** Module-level counter for stable, unique submenu IDs (React 16 compatible) */\nlet _submenuIdCounter = 0;\n\nexport const ContextMenuSubmenu: React.FC<ContextMenuSubmenuProps> = ({\n label,\n icon,\n disabled,\n children,\n size: propSize,\n \"data-testid\": testId = \"context-menu-submenu\",\n}) => {\n const { theme } = useDesignSystem();\n const xuiTheme = theme as any;\n const context = useContextMenu();\n const size = propSize || context?.size || \"md\";\n const sizeStyles = xuiTheme.sizing.contextMenu(size);\n const borderRadius =\n xuiTheme.shape?.contextMenu?.[size]?.borderRadius ??\n xuiTheme.radius?.button ??\n 8;\n\n const submenuIdRef = useRef<string | null>(null);\n if (submenuIdRef.current === null) {\n submenuIdRef.current = `xui-cm-submenu-${(_submenuIdCounter += 1)}`;\n }\n const submenuId = submenuIdRef.current;\n\n const [isOpen, setIsOpen] = useState(false);\n const [visible, setVisible] = useState(false);\n const [openLeft, setOpenLeft] = useState(false);\n const [topOffset, setTopOffset] = useState(0);\n\n const triggerRef = useRef<HTMLDivElement>(null);\n const submenuRef = useRef<HTMLDivElement>(null);\n const openTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n const closeTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n\n const clearTimers = useCallback(() => {\n if (openTimerRef.current) clearTimeout(openTimerRef.current);\n if (closeTimerRef.current) clearTimeout(closeTimerRef.current);\n }, []);\n\n // Close this submenu when a sibling submenu becomes active (Bug #3 fix)\n useEffect(() => {\n if (!context?.activeSubmenuId) return;\n if (context.activeSubmenuId !== submenuId) {\n setIsOpen(false);\n }\n }, [context?.activeSubmenuId, submenuId]);\n\n const calculatePlacement = useCallback(() => {\n if (!triggerRef.current) return;\n const triggerRect = triggerRef.current.getBoundingClientRect();\n const estimatedWidth = sizeStyles.minWidth + 32;\n const wouldOverflowRight =\n triggerRect.right + estimatedWidth + SUBMENU_GAP > window.innerWidth - 8;\n // Bug #1/#2 fix: only flip left when there is actually space on the left\n const hasSpaceOnLeft =\n triggerRect.left - SUBMENU_GAP - estimatedWidth >= 8;\n setOpenLeft(wouldOverflowRight && hasSpaceOnLeft);\n setTopOffset(0);\n }, [sizeStyles.minWidth]);\n\n useLayoutEffect(() => {\n if (!isOpen || !submenuRef.current || !triggerRef.current) return;\n\n const submenuRect = submenuRef.current.getBoundingClientRect();\n const triggerRect = triggerRef.current.getBoundingClientRect();\n\n const wouldOverflowRight =\n triggerRect.right + submenuRect.width + SUBMENU_GAP >\n window.innerWidth - 8;\n const hasSpaceOnLeft =\n triggerRect.left - SUBMENU_GAP - submenuRect.width >= 8;\n setOpenLeft(wouldOverflowRight && hasSpaceOnLeft);\n\n const overflowBottom =\n triggerRect.top + submenuRect.height - (window.innerHeight - 8);\n if (overflowBottom > 0) {\n setTopOffset(-Math.min(overflowBottom, triggerRect.top - 8));\n } else {\n setTopOffset(0);\n }\n }, [isOpen]);\n\n useEffect(() => {\n if (!isOpen) {\n setVisible(false);\n return;\n }\n const raf = requestAnimationFrame(() => setVisible(true));\n return () => cancelAnimationFrame(raf);\n }, [isOpen]);\n\n useEffect(() => () => clearTimers(), [clearTimers]);\n\n const handleTriggerEnter = () => {\n if (disabled) return;\n clearTimers();\n openTimerRef.current = setTimeout(() => {\n calculatePlacement();\n setIsOpen(true);\n context?.setActiveSubmenuId(submenuId);\n }, OPEN_DELAY_MS);\n };\n\n const handleTriggerLeave = () => {\n clearTimers();\n closeTimerRef.current = setTimeout(() => {\n setIsOpen(false);\n if (context?.activeSubmenuId === submenuId) {\n context.setActiveSubmenuId(null);\n }\n }, CLOSE_GRACE_MS);\n };\n\n const handleSubmenuEnter = () => clearTimers();\n\n const handleSubmenuLeave = () => {\n clearTimers();\n closeTimerRef.current = setTimeout(() => {\n setIsOpen(false);\n if (context?.activeSubmenuId === submenuId) {\n context.setActiveSubmenuId(null);\n }\n }, CLOSE_GRACE_MS);\n };\n\n const submenuPositionStyle = openLeft\n ? { right: `calc(100% + ${SUBMENU_GAP}px)` }\n : { left: `calc(100% + ${SUBMENU_GAP}px)` };\n\n return (\n <div\n ref={triggerRef}\n style={{ position: \"relative\" }}\n onMouseEnter={handleTriggerEnter}\n onMouseLeave={handleTriggerLeave}\n data-testid={testId}\n >\n <ContextMenuItem\n type=\"option\"\n label={label}\n leadingIcon={icon}\n disabled={disabled}\n hasSubmenu\n size={size}\n data-testid={`${testId}-trigger`}\n />\n\n {isOpen && (\n <div\n ref={submenuRef}\n onMouseEnter={handleSubmenuEnter}\n onMouseLeave={handleSubmenuLeave}\n style={{\n position: \"absolute\",\n top: topOffset,\n ...submenuPositionStyle,\n zIndex: 1001,\n opacity: visible ? 1 : 0,\n transform: visible\n ? \"translateX(0)\"\n : openLeft\n ? \"translateX(4px)\"\n : \"translateX(-4px)\",\n transition: \"opacity 100ms ease, transform 100ms ease\",\n }}\n data-testid={`${testId}-content`}\n >\n <Box\n role=\"menu\"\n backgroundColor={xuiTheme.colors.background.secondary}\n borderColor={xuiTheme.colors.border.secondary}\n borderWidth={1}\n borderRadius={borderRadius}\n paddingVertical={sizeStyles.paddingVertical}\n style={{\n boxShadow: \"0 4px 12px rgba(0,0,0,0.15)\",\n minWidth: sizeStyles.minWidth,\n }}\n >\n {children}\n </Box>\n </div>\n )}\n </div>\n );\n};\n\nContextMenuSubmenu.displayName = \"ContextMenuSubmenu\";\n","import { useLayoutEffect, useState, type RefObject } from \"react\";\nimport type { ContextMenuPlacement } from \"../types\";\n\ninterface UseContextMenuPositionOptions {\n triggerRef: RefObject<HTMLElement | null>;\n panelRef: RefObject<HTMLElement | null>;\n containerRef: 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\" | \"center\" } => {\n const [vertical, horizontal] = placement.split(\"-\") as [\n \"top\" | \"bottom\",\n \"start\" | \"end\" | \"center\",\n ];\n return { vertical, horizontal };\n};\n\nconst joinPlacement = (\n vertical: \"top\" | \"bottom\",\n horizontal: \"start\" | \"end\" | \"center\"\n): ContextMenuPlacement => `${vertical}-${horizontal}` as ContextMenuPlacement;\n\nexport const useContextMenuPosition = ({\n triggerRef,\n panelRef,\n containerRef,\n isOpen,\n placement = \"bottom-start\",\n offset = 4,\n}: UseContextMenuPositionOptions): ResolvedPosition | undefined => {\n const [resolved, setResolved] = useState<ResolvedPosition | undefined>();\n\n useLayoutEffect(() => {\n if (!isOpen) {\n setResolved(undefined);\n return;\n }\n\n const compute = () => {\n const trigger = triggerRef.current;\n const panel = panelRef.current;\n const container = containerRef.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\" | \"center\") => {\n if (h === \"center\")\n return triggerRect.left + triggerRect.width / 2 - panelRect.width / 2;\n return h === \"start\"\n ? triggerRect.left\n : triggerRect.right - panelRect.width;\n };\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 if (horizontal === \"center\") {\n const maxLeft = viewportWidth - panelRect.width;\n left = maxLeft >= 0 ? Math.min(Math.max(left, 0), maxLeft) : 0;\n } else {\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\n // Convert viewport coordinates to local (absolute-positioning) coords\n // relative to the container. Reading containerRect here (inside the\n // layout effect) guarantees we measure at the same time as the trigger\n // and panel, avoiding stale-rect issues from intermediate renders.\n if (container) {\n const containerRect = container.getBoundingClientRect();\n const cOffsetW = container.offsetWidth;\n const cOffsetH = container.offsetHeight;\n const scaleX = cOffsetW > 0 ? containerRect.width / cOffsetW : 1;\n const scaleY = cOffsetH > 0 ? containerRect.height / cOffsetH : 1;\n left = (left - containerRect.left) / (scaleX || 1);\n top = (top - containerRect.top) / (scaleY || 1);\n }\n\n const next = {\n top,\n left,\n placement: joinPlacement(vertical, horizontal),\n };\n setResolved((prev) =>\n prev &&\n prev.top === next.top &&\n prev.left === next.left &&\n prev.placement === next.placement\n ? prev\n : next\n );\n };\n\n compute();\n // No scroll listener: the menu dismisses on scroll (see ContextMenu), so\n // following the trigger would be dead work. Resize still repositions an\n // open menu.\n const onResize = () => compute();\n window.addEventListener(\"resize\", onResize);\n\n return () => {\n window.removeEventListener(\"resize\", onResize);\n };\n }, [isOpen, placement, offset, triggerRef, panelRef, containerRef]);\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","React","styled","React","import_xui_core","import_react","import_react","import_jsx_runtime","React","index","import_react","import_xui_core","import_jsx_runtime","SUBMENU_GAP","import_react","import_react","import_jsx_runtime","index"]}
1
+ {"version":3,"sources":["../../src/index.tsx","../../src/ContextMenu.tsx","../../../../foundation/primitives-web/src/Box.tsx","../../../../foundation/primitives-web/src/filterDOMProps.ts","../../../../../node_modules/@emotion/memoize/dist/memoize.esm.js","../../../../../node_modules/@emotion/is-prop-valid/dist/is-prop-valid.esm.js","../../src/ContextMenuContext.tsx","../../src/ContextMenuItem.tsx","../../src/ContextMenuSubmenu.tsx","../../src/hooks/useContextMenuPosition.ts","../../src/hooks/useKeyboardNavigation.ts"],"sourcesContent":["// Components\nexport { ContextMenu } from \"./ContextMenu\";\nexport { ContextMenuItem } from \"./ContextMenuItem\";\nexport { ContextMenuSubmenu } from \"./ContextMenuSubmenu\";\n\n// Context\nexport {\n ContextMenuContext,\n useContextMenu,\n useContextMenuRequired,\n} from \"./ContextMenuContext\";\n\n// Hooks\nexport { useContextMenuPosition } from \"./hooks/useContextMenuPosition\";\nexport { useKeyboardNavigation } from \"./hooks/useKeyboardNavigation\";\n\n// Types\nexport type {\n ContextMenuSize,\n ContextMenuPlacement,\n ContextMenuPresetType,\n ContextMenuPosition,\n ContextMenuProps,\n ContextMenuItemProps,\n ContextMenuOptionItemProps,\n ContextMenuSearchItemProps,\n ContextMenuHeadingItemProps,\n ContextMenuDividerItemProps,\n ContextMenuSubmenuProps,\n ContextMenuContextValue,\n ContextMenuSizing,\n} from \"./types\";\n","import React, {\n cloneElement,\n forwardRef,\n isValidElement,\n useCallback,\n useEffect,\n useLayoutEffect,\n useMemo,\n useRef,\n useState,\n} from \"react\";\n// @ts-expect-error - this will be resolved at build time\nimport { Box } from \"@xsolla/xui-primitives\";\nimport {\n useResolvedTheme,\n useId,\n useOverlayLayer,\n LAYER_OFFSET,\n useModalStackDepth,\n} from \"@xsolla/xui-core\";\nimport { Spinner } from \"@xsolla/xui-spinner\";\nimport { ContextMenuContext } from \"./ContextMenuContext\";\nimport { ContextMenuItem } from \"./ContextMenuItem\";\nimport { ContextMenuSubmenu } from \"./ContextMenuSubmenu\";\nimport { useContextMenuPosition } from \"./hooks/useContextMenuPosition\";\nimport {\n useKeyboardNavigation,\n type CellMeta,\n} from \"./hooks/useKeyboardNavigation\";\nimport type {\n ContextMenuContextValue,\n ContextMenuItemProps,\n ContextMenuOptionItemProps,\n ContextMenuPlacement,\n ContextMenuProps,\n ContextMenuSizing,\n} from \"./types\";\n\ntype CellEntry = { id: string; meta: CellMeta };\n\ntype ContextMenuTheme = {\n sizing: {\n contextMenu: (\n size: NonNullable<ContextMenuProps[\"size\"]>\n ) => ContextMenuSizing;\n };\n shape?: {\n contextMenu?: Partial<\n Record<\n NonNullable<ContextMenuProps[\"size\"]>,\n {\n borderRadius?: number | string;\n }\n >\n >;\n };\n colors: {\n background: {\n secondary: string;\n };\n border: {\n secondary: string;\n };\n control: {\n brand: {\n primary: {\n bg: string;\n };\n };\n };\n };\n};\n\nconst DEFAULT_EMPTY_MESSAGE = \"No results\";\nconst SEARCH_DEBOUNCE_MS = 200;\nconst ARROW_SIZE = 10;\nconst ARROW_HALF = ARROW_SIZE / 2;\nconst ARROW_EDGE_OFFSET = 12;\n// Distance the rotated arrow's tip protrudes past the panel edge toward the\n// trigger. The square is rotated 45deg about its center (pinned to the edge),\n// so its corner sits ARROW_HALF * √2 beyond it. Folded into the position\n// offset when `withArrow` is set so `offset` measures to the arrow tip.\nconst ARROW_TIP_PROTRUSION = ARROW_HALF * Math.SQRT2;\nconst PANEL_SHADOW = \"0 4px 12px rgba(0,0,0,0.15)\";\n\n// Portaled floating layers render onto document.body, OUTSIDE the ContextMenu\n// subtree. These include:\n// - Dropdown-style children (Select / MultiSelect / DatePicker option lists,\n// modal overlays) marked with data-modal-id (via useModalId); listbox-style\n// dropdowns additionally carry role=\"listbox\". See FEP-836.\n// - This ContextMenu's own sub-menus, which each portal to document.body as a\n// flat wrapper marked data-xui-context-menu-portal. A mousedown on a\n// sub-menu item would otherwise read as an outside click and dismiss the\n// whole trigger-anchored menu before the selection resolves.\n// A mousedown inside any of these must NOT be treated as an outside click.\nconst PORTALED_LAYER_SELECTOR =\n '[data-modal-id],[role=\"listbox\"],[data-xui-context-menu-portal]';\n\nconst textFromNode = (node: React.ReactNode): string => {\n if (node === null || node === undefined || typeof node === \"boolean\")\n return \"\";\n if (typeof node === \"string\" || typeof node === \"number\") return String(node);\n if (Array.isArray(node)) return node.map(textFromNode).join(\" \");\n if (isValidElement(node)) return textFromNode(node.props.children);\n return \"\";\n};\n\nconst filterItems = (\n items: ReadonlyArray<ContextMenuItemProps>,\n query: string\n): ContextMenuItemProps[] => {\n const normalized = query.trim().toLowerCase();\n if (!normalized) return [...items];\n\n const result: ContextMenuItemProps[] = [];\n let pendingStructural: ContextMenuItemProps[] = [];\n\n for (const item of items) {\n if (item.type === \"option\") {\n const label = textFromNode(item.label).toLowerCase();\n if (label.includes(normalized)) {\n result.push(...pendingStructural, item);\n pendingStructural = [];\n }\n continue;\n }\n\n if (item.type === \"heading\") {\n pendingStructural = [item];\n continue;\n }\n\n if (item.type === \"divider\") {\n if (result.length > 0) pendingStructural.push(item);\n continue;\n }\n }\n\n return result;\n};\n\nconst isOption = (\n item: ContextMenuItemProps\n): item is ContextMenuOptionItemProps => item.type === \"option\";\n\nconst ContextMenuRoot = forwardRef<HTMLElement, ContextMenuProps>(\n (\n {\n children,\n type = \"list\",\n items = [],\n size = \"md\",\n searchable,\n loading,\n isLoading,\n emptyMessage = DEFAULT_EMPTY_MESSAGE,\n empty,\n isOpen: propIsOpen,\n onOpenChange,\n trigger,\n triggerFullWidth = false,\n placement = \"bottom-start\",\n offset = 4,\n position,\n width,\n maxHeight = 300,\n withArrow = false,\n onSelect,\n closeOnSelect,\n \"aria-label\": ariaLabel,\n testID,\n \"data-testid\": dataTestId,\n themeMode,\n themeProductContext,\n style,\n },\n ref\n ) => {\n const { theme: rawTheme } = useResolvedTheme({\n themeMode,\n themeProductContext,\n });\n const xuiTheme = rawTheme as ContextMenuTheme;\n const menuId = useId();\n const overlayLayer = useOverlayLayer();\n const modalStackDepth = useModalStackDepth();\n const openModalDepthRef = useRef<number | null>(null);\n const [internalIsOpen, setInternalIsOpen] = useState(false);\n const [activeIndex, setActiveIndex] = useState(-1);\n const [cellsVersion, setCellsVersion] = useState(0);\n const [query, setQuery] = useState(\"\");\n const [debouncedQuery, setDebouncedQuery] = useState(\"\");\n const [activeSubmenuId, setActiveSubmenuId] = useState<string | null>(null);\n const containerRef = useRef<HTMLDivElement | null>(null);\n const triggerRef = useRef<HTMLElement | null>(null);\n const panelRef = useRef<HTMLElement | null>(null);\n const cellsRef = useRef<CellEntry[]>([]);\n\n const isOpen = propIsOpen !== undefined ? propIsOpen : internalIsOpen;\n const sizeStyles = xuiTheme.sizing.contextMenu(size);\n const borderRadius = xuiTheme.shape?.contextMenu?.[size]?.borderRadius ?? 8;\n const shouldCloseOnSelect =\n closeOnSelect ?? (type === \"checkbox\" ? false : true);\n\n // With an arrow, the tip protrudes past the panel edge, so push the panel\n // out by that amount to keep `offset` measured to the visible arrow tip.\n const positionOffset = withArrow ? offset + ARROW_TIP_PROTRUSION : offset;\n\n const positioned = useContextMenuPosition({\n triggerRef,\n panelRef,\n containerRef,\n isOpen: isOpen && !!trigger && !position,\n placement,\n offset: positionOffset,\n });\n\n const resolvedPlacement: ContextMenuPlacement =\n positioned?.placement ?? placement;\n\n const getArrowStyle = (\n arrowPlacement: ContextMenuPlacement\n ): React.CSSProperties => {\n const isTop = arrowPlacement.startsWith(\"top\");\n const arrowStyle: React.CSSProperties = {\n position: \"absolute\",\n width: ARROW_SIZE,\n height: ARROW_SIZE,\n backgroundColor: xuiTheme.colors.background.secondary,\n borderStyle: \"solid\",\n borderColor: xuiTheme.colors.border.secondary,\n // 1px outline only on the two outward-facing edges of the rotated square\n borderWidth: isTop ? \"0 1px 1px 0\" : \"1px 0 0 1px\",\n transform: \"rotate(45deg)\",\n pointerEvents: \"none\",\n };\n // Cross axis: sit half outside the panel edge nearest the trigger.\n if (isTop) arrowStyle.bottom = -ARROW_HALF;\n else arrowStyle.top = -ARROW_HALF;\n // Main axis: align toward the trigger side.\n if (arrowPlacement.endsWith(\"center\")) {\n arrowStyle.left = \"50%\";\n arrowStyle.marginLeft = -ARROW_HALF;\n } else if (arrowPlacement.endsWith(\"end\")) {\n arrowStyle.right = ARROW_EDGE_OFFSET;\n } else {\n arrowStyle.left = ARROW_EDGE_OFFSET;\n }\n return arrowStyle;\n };\n\n const setOpen = useCallback(\n (nextOpen: boolean) => {\n if (propIsOpen === undefined) setInternalIsOpen(nextOpen);\n onOpenChange?.(nextOpen);\n if (!nextOpen) setActiveIndex(-1);\n },\n [propIsOpen, onOpenChange]\n );\n\n const closeMenu = useCallback(() => {\n setOpen(false);\n }, [setOpen]);\n\n const toggleMenu = useCallback(() => {\n setOpen(!isOpen);\n }, [isOpen, setOpen]);\n\n const registerCell = useCallback((id: string, meta: CellMeta) => {\n const existingIndex = cellsRef.current.findIndex(\n (cell) => cell.id === id\n );\n if (existingIndex >= 0) {\n cellsRef.current[existingIndex] = { id, meta };\n setCellsVersion((version) => version + 1);\n return existingIndex;\n }\n cellsRef.current.push({ id, meta });\n setCellsVersion((version) => version + 1);\n return cellsRef.current.length - 1;\n }, []);\n\n const unregisterCell = useCallback((id: string) => {\n const index = cellsRef.current.findIndex((cell) => cell.id === id);\n if (index >= 0) {\n cellsRef.current.splice(index, 1);\n setCellsVersion((version) => version + 1);\n }\n }, []);\n\n const getCellIndex = useCallback((id: string) => {\n return cellsRef.current.findIndex((cell) => cell.id === id);\n }, []);\n\n const cells = useMemo(() => [...cellsRef.current], [cellsVersion]);\n const keyboard = useKeyboardNavigation({\n isOpen,\n cells,\n activeIndex,\n setActiveIndex,\n onClose: closeMenu,\n triggerRef,\n });\n\n useEffect(() => {\n if (!isOpen) {\n cellsRef.current = [];\n setCellsVersion((version) => version + 1);\n setQuery(\"\");\n setDebouncedQuery(\"\");\n setActiveSubmenuId(null);\n }\n }, [isOpen]);\n\n // Dismiss the menu when a modal opens over it. Selecting an item that opens\n // a confirmation modal (e.g. StatusDropdown) would otherwise leave the menu\n // orphaned above/behind the modal, and the modal shields it from the\n // outside-click that would normally close it. Capture the modal depth when\n // the menu opens; close once a deeper modal appears. A menu opened inside a\n // modal keeps the depth it was born at, so its own modal never closes it.\n useEffect(() => {\n if (!isOpen) {\n openModalDepthRef.current = null;\n return;\n }\n if (openModalDepthRef.current === null) {\n openModalDepthRef.current = modalStackDepth;\n return;\n }\n if (modalStackDepth > openModalDepthRef.current) {\n closeMenu();\n }\n }, [isOpen, modalStackDepth, closeMenu]);\n\n useEffect(() => {\n const timer = setTimeout(\n () => setDebouncedQuery(query),\n SEARCH_DEBOUNCE_MS\n );\n return () => clearTimeout(timer);\n }, [query]);\n\n useEffect(() => {\n if (!isOpen || !trigger) return;\n\n const onMouseDown = (event: MouseEvent) => {\n const target = event.target as Node | null;\n if (!target) return;\n if (containerRef.current?.contains(target)) return;\n\n // Portal-aware outside-close. Dropdown-style children (Select,\n // MultiSelect, DatePicker, …) render their option list through a React\n // portal mounted on document.body, so the option node lives OUTSIDE the\n // ContextMenu subtree even though it is logically part of the open menu.\n // Without this guard a mousedown on a portaled option reads as an\n // outside click and dismisses the whole ContextMenu before the option's\n // own click resolves (FEP-836). Walk the composed event path so a click\n // anywhere inside a registered floating layer counts as \"inside\".\n const path =\n typeof event.composedPath === \"function\" ? event.composedPath() : [];\n const isInsidePortaledLayer = path.length\n ? path.some(\n (node) =>\n node instanceof Element && node.matches(PORTALED_LAYER_SELECTOR)\n )\n : target instanceof Element &&\n !!target.closest(PORTALED_LAYER_SELECTOR);\n if (isInsidePortaledLayer) return;\n\n closeMenu();\n };\n\n const onScroll = () => closeMenu();\n\n document.addEventListener(\"mousedown\", onMouseDown);\n window.addEventListener(\"scroll\", onScroll);\n return () => {\n document.removeEventListener(\"mousedown\", onMouseDown);\n window.removeEventListener(\"scroll\", onScroll);\n };\n }, [isOpen, trigger, closeMenu]);\n\n useLayoutEffect(() => {\n if (!isOpen || !panelRef.current) return;\n const searchbox =\n panelRef.current.querySelector<HTMLElement>('[role=\"searchbox\"]');\n const firstOption = panelRef.current.querySelector<HTMLElement>(\n '[role=\"menuitem\"],[role=\"menuitemcheckbox\"],[role=\"menuitemradio\"]'\n );\n (searchbox ?? firstOption)?.focus();\n }, [isOpen]);\n\n useLayoutEffect(() => {\n if (!isOpen || !panelRef.current) return;\n const activeElement = document.activeElement;\n if (activeElement && panelRef.current.contains(activeElement)) return;\n panelRef.current.focus();\n }, [isOpen, cellsVersion]);\n\n // Restore focus to the trigger only on an open→closed transition, not on\n // mount: `isOpen` starts `false`, so gating solely on `if (isOpen) return`\n // would also fire on mount and steal focus. Seeding `wasOpen` with the\n // initial `isOpen` also covers the controlled-open-on-mount case.\n const wasOpen = useRef(isOpen);\n useEffect(() => {\n if (isOpen) {\n wasOpen.current = true;\n return;\n }\n if (wasOpen.current) {\n triggerRef.current?.focus();\n wasOpen.current = false;\n }\n }, [isOpen]);\n\n const contextValue: ContextMenuContextValue = useMemo(\n () => ({\n size,\n menuId,\n closeMenu,\n activeIndex,\n setActiveIndex,\n registerCell,\n unregisterCell,\n getCellIndex,\n cellsVersion,\n query,\n setQuery,\n activeSubmenuId,\n setActiveSubmenuId,\n }),\n [\n size,\n menuId,\n closeMenu,\n activeIndex,\n registerCell,\n unregisterCell,\n getCellIndex,\n cellsVersion,\n query,\n activeSubmenuId,\n ]\n );\n\n const renderPresetItem = (item: ContextMenuItemProps, index: number) => {\n if (!isOption(item)) {\n return (\n <ContextMenuItem\n key={`context-menu-item-${index}`}\n {...item}\n themeMode={themeMode}\n themeProductContext={themeProductContext}\n />\n );\n }\n\n const leadingControl =\n item.leadingControl ??\n (type === \"checkbox\"\n ? \"checkbox\"\n : type === \"radio\"\n ? \"radio\"\n : undefined);\n\n return (\n <ContextMenuItem\n key={`context-menu-item-${index}`}\n {...item}\n leadingControl={leadingControl}\n themeMode={themeMode}\n themeProductContext={themeProductContext}\n onSelect={() => {\n item.onSelect?.();\n onSelect?.(item);\n if (shouldCloseOnSelect) closeMenu();\n }}\n />\n );\n };\n\n const renderedItems = searchable\n ? filterItems(items, debouncedQuery)\n : [...items];\n\n const renderContent = () => {\n if (loading || isLoading || type === \"loading\") {\n const brandColor = xuiTheme.colors.control.brand.primary.bg;\n return (\n <Box\n padding={16}\n alignItems=\"center\"\n justifyContent=\"center\"\n minHeight={60}\n >\n <Spinner size=\"md\" color={brandColor} />\n </Box>\n );\n }\n\n if (children) return children;\n\n const content = renderedItems.map(renderPresetItem);\n if (searchable) {\n content.unshift(\n <div\n key=\"context-menu-search\"\n data-sticky=\"top\"\n style={{\n position: \"sticky\",\n top: 0,\n zIndex: 1,\n backgroundColor: xuiTheme.colors.background.secondary,\n }}\n >\n <ContextMenuItem\n type=\"search\"\n value={query}\n onValueChange={setQuery}\n placeholder=\"Search\"\n autoFocus\n themeMode={themeMode}\n themeProductContext={themeProductContext}\n />\n </div>\n );\n }\n\n if (content.length > (searchable ? 1 : 0)) return content;\n return empty ?? <div style={{ padding: 16 }}>{emptyMessage}</div>;\n };\n\n const assignPanelRef = (node: HTMLElement | null) => {\n panelRef.current = node;\n if (typeof ref === \"function\") ref(node);\n else if (ref) ref.current = node;\n };\n\n const assignTriggerRef = (node: HTMLElement | null) => {\n triggerRef.current = node;\n };\n\n const assignTriggerWrapperRef = (node: HTMLSpanElement | null) => {\n if (!node) {\n assignTriggerRef(null);\n return;\n }\n const firstChild = node.firstElementChild;\n assignTriggerRef(\n firstChild instanceof HTMLElement ? firstChild : (node as HTMLElement)\n );\n };\n\n const triggerNode =\n trigger && isValidElement(trigger) ? (\n <span\n ref={assignTriggerWrapperRef}\n onClick={(event) => {\n if (!event.defaultPrevented) toggleMenu();\n }}\n style={{\n display: \"inline-flex\",\n width: triggerFullWidth ? \"100%\" : \"auto\",\n }}\n >\n {cloneElement(trigger as React.ReactElement<any>, {\n \"aria-haspopup\": \"menu\",\n \"aria-expanded\": isOpen ? \"true\" : \"false\",\n })}\n </span>\n ) : trigger ? (\n <span\n ref={assignTriggerRef}\n role=\"button\"\n tabIndex={0}\n aria-haspopup=\"menu\"\n aria-expanded={isOpen ? \"true\" : \"false\"}\n onClick={toggleMenu}\n >\n {trigger}\n </span>\n ) : null;\n\n const positionStyle: React.CSSProperties | undefined = position\n ? {\n position: \"fixed\" as const,\n left: position.x,\n top: position.y,\n }\n : trigger\n ? positioned\n ? {\n position: \"absolute\" as const,\n left: positioned.left,\n top: positioned.top,\n }\n : {\n position: \"absolute\" as const,\n visibility: \"hidden\" as const,\n }\n : undefined;\n\n return (\n <ContextMenuContext.Provider value={contextValue}>\n <div\n ref={containerRef}\n style={{\n position: trigger || position ? \"relative\" : undefined,\n display: trigger ? \"inline-block\" : undefined,\n }}\n >\n {triggerNode}\n {isOpen && (\n <Box\n ref={assignPanelRef}\n role=\"menu\"\n aria-label={ariaLabel}\n data-testid={dataTestId ?? testID ?? \"context-menu\"}\n data-placement={resolvedPlacement}\n backgroundColor={xuiTheme.colors.background.secondary}\n borderColor={xuiTheme.colors.border.secondary}\n borderWidth={1}\n borderRadius={borderRadius}\n paddingVertical={sizeStyles.paddingVertical}\n width={width}\n minWidth={sizeStyles.minWidth}\n tabIndex={-1}\n onKeyDown={keyboard.handleKeyDown}\n onMouseLeave={() => setActiveIndex(-1)}\n style={{\n ...positionStyle,\n ...style,\n zIndex: overlayLayer + LAYER_OFFSET.menu,\n boxShadow: PANEL_SHADOW,\n ...(withArrow\n ? {\n overflow: \"visible\",\n }\n : {\n maxHeight,\n overflowY: \"auto\",\n }),\n outline: \"none\",\n }}\n >\n {withArrow ? (\n <>\n <span\n aria-hidden=\"true\"\n data-testid=\"context-menu-arrow\"\n style={getArrowStyle(resolvedPlacement)}\n />\n <div style={{ maxHeight, overflowY: \"auto\", borderRadius }}>\n {renderContent()}\n </div>\n </>\n ) : (\n renderContent()\n )}\n </Box>\n )}\n </div>\n </ContextMenuContext.Provider>\n );\n }\n);\n\nContextMenuRoot.displayName = \"ContextMenu\";\n\nexport const ContextMenu = Object.assign(ContextMenuRoot, {\n Item: ContextMenuItem,\n Submenu: ContextMenuSubmenu,\n});\n","import React from \"react\";\nimport styled from \"styled-components\";\nimport type { BoxProps } from \"@xsolla/xui-primitives-core\";\nimport { createFilteredElement } from \"./filterDOMProps\";\n\nconst FilteredDiv = createFilteredElement(\"div\");\n\nconst StyledBox = styled(FilteredDiv)<BoxProps>`\n display: flex;\n box-sizing: border-box;\n background-color: ${(props) => props.backgroundColor || \"transparent\"};\n border-color: ${(props) => props.borderColor || \"transparent\"};\n border-width: ${(props) =>\n typeof props.borderWidth === \"number\"\n ? `${props.borderWidth}px`\n : props.borderWidth || 0};\n\n ${(props) =>\n props.borderBottomWidth !== undefined &&\n `\n border-bottom-width: ${typeof props.borderBottomWidth === \"number\" ? `${props.borderBottomWidth}px` : props.borderBottomWidth};\n border-bottom-color: ${props.borderBottomColor || props.borderColor || \"transparent\"};\n border-bottom-style: solid;\n `}\n ${(props) =>\n props.borderTopWidth !== undefined &&\n `\n border-top-width: ${typeof props.borderTopWidth === \"number\" ? `${props.borderTopWidth}px` : props.borderTopWidth};\n border-top-color: ${props.borderTopColor || props.borderColor || \"transparent\"};\n border-top-style: solid;\n `}\n ${(props) =>\n props.borderLeftWidth !== undefined &&\n `\n border-left-width: ${typeof props.borderLeftWidth === \"number\" ? `${props.borderLeftWidth}px` : props.borderLeftWidth};\n border-left-color: ${props.borderLeftColor || props.borderColor || \"transparent\"};\n border-left-style: solid;\n `}\n ${(props) =>\n props.borderRightWidth !== undefined &&\n `\n border-right-width: ${typeof props.borderRightWidth === \"number\" ? `${props.borderRightWidth}px` : props.borderRightWidth};\n border-right-color: ${props.borderRightColor || props.borderColor || \"transparent\"};\n border-right-style: solid;\n `}\n\n border-style: ${(props) =>\n props.borderStyle ||\n (props.borderWidth ||\n props.borderBottomWidth ||\n props.borderTopWidth ||\n props.borderLeftWidth ||\n props.borderRightWidth\n ? \"solid\"\n : \"none\")};\n border-radius: ${(props) =>\n typeof props.borderRadius === \"number\"\n ? `${props.borderRadius}px`\n : props.borderRadius || 0};\n height: ${(props) =>\n typeof props.height === \"number\"\n ? `${props.height}px`\n : props.height || \"auto\"};\n width: ${(props) =>\n typeof props.width === \"number\"\n ? `${props.width}px`\n : props.width || \"auto\"};\n min-width: ${(props) =>\n typeof props.minWidth === \"number\"\n ? `${props.minWidth}px`\n : props.minWidth || \"auto\"};\n min-height: ${(props) =>\n typeof props.minHeight === \"number\"\n ? `${props.minHeight}px`\n : props.minHeight || \"auto\"};\n max-width: ${(props) =>\n typeof props.maxWidth === \"number\"\n ? `${props.maxWidth}px`\n : props.maxWidth || \"none\"};\n max-height: ${(props) =>\n typeof props.maxHeight === \"number\"\n ? `${props.maxHeight}px`\n : props.maxHeight || \"none\"};\n\n padding: ${(props) =>\n typeof props.padding === \"number\"\n ? `${props.padding}px`\n : props.padding || 0};\n ${(props) =>\n props.paddingHorizontal &&\n `\n padding-left: ${typeof props.paddingHorizontal === \"number\" ? `${props.paddingHorizontal}px` : props.paddingHorizontal};\n padding-right: ${typeof props.paddingHorizontal === \"number\" ? `${props.paddingHorizontal}px` : props.paddingHorizontal};\n `}\n ${(props) =>\n props.paddingVertical &&\n `\n padding-top: ${typeof props.paddingVertical === \"number\" ? `${props.paddingVertical}px` : props.paddingVertical};\n padding-bottom: ${typeof props.paddingVertical === \"number\" ? `${props.paddingVertical}px` : props.paddingVertical};\n `}\n ${(props) =>\n props.paddingTop !== undefined &&\n `padding-top: ${typeof props.paddingTop === \"number\" ? `${props.paddingTop}px` : props.paddingTop};`}\n ${(props) =>\n props.paddingBottom !== undefined &&\n `padding-bottom: ${typeof props.paddingBottom === \"number\" ? `${props.paddingBottom}px` : props.paddingBottom};`}\n ${(props) =>\n props.paddingLeft !== undefined &&\n `padding-left: ${typeof props.paddingLeft === \"number\" ? `${props.paddingLeft}px` : props.paddingLeft};`}\n ${(props) =>\n props.paddingRight !== undefined &&\n `padding-right: ${typeof props.paddingRight === \"number\" ? `${props.paddingRight}px` : props.paddingRight};`}\n\n margin: ${(props) =>\n typeof props.margin === \"number\" ? `${props.margin}px` : props.margin || 0};\n ${(props) =>\n props.marginTop !== undefined &&\n `margin-top: ${typeof props.marginTop === \"number\" ? `${props.marginTop}px` : props.marginTop};`}\n ${(props) =>\n props.marginBottom !== undefined &&\n `margin-bottom: ${typeof props.marginBottom === \"number\" ? `${props.marginBottom}px` : props.marginBottom};`}\n ${(props) =>\n props.marginLeft !== undefined &&\n `margin-left: ${typeof props.marginLeft === \"number\" ? `${props.marginLeft}px` : props.marginLeft};`}\n ${(props) =>\n props.marginRight !== undefined &&\n `margin-right: ${typeof props.marginRight === \"number\" ? `${props.marginRight}px` : props.marginRight};`}\n\n flex-direction: ${(props) => props.flexDirection || \"column\"};\n flex-wrap: ${(props) => props.flexWrap || \"nowrap\"};\n align-items: ${(props) => props.alignItems || \"stretch\"};\n justify-content: ${(props) => props.justifyContent || \"flex-start\"};\n cursor: ${(props) =>\n props.cursor\n ? props.cursor\n : props.onClick || props.onPress\n ? \"pointer\"\n : \"inherit\"};\n position: ${(props) => props.position || \"static\"};\n top: ${(props) =>\n typeof props.top === \"number\" ? `${props.top}px` : props.top};\n bottom: ${(props) =>\n typeof props.bottom === \"number\" ? `${props.bottom}px` : props.bottom};\n left: ${(props) =>\n typeof props.left === \"number\" ? `${props.left}px` : props.left};\n right: ${(props) =>\n typeof props.right === \"number\" ? `${props.right}px` : props.right};\n flex: ${(props) => props.flex};\n flex-shrink: ${(props) => props.flexShrink ?? 1};\n gap: ${(props) =>\n typeof props.gap === \"number\" ? `${props.gap}px` : props.gap || 0};\n align-self: ${(props) => props.alignSelf || \"auto\"};\n overflow: ${(props) => props.overflow || \"visible\"};\n overflow-x: ${(props) => props.overflowX || \"visible\"};\n overflow-y: ${(props) => props.overflowY || \"visible\"};\n z-index: ${(props) => props.zIndex};\n opacity: ${(props) => (props.disabled ? 0.5 : 1)};\n pointer-events: ${(props) => (props.disabled ? \"none\" : \"auto\")};\n\n &:hover {\n ${(props) =>\n props.hoverStyle?.backgroundColor &&\n `background-color: ${props.hoverStyle.backgroundColor};`}\n ${(props) =>\n props.hoverStyle?.borderColor &&\n `border-color: ${props.hoverStyle.borderColor};`}\n }\n\n &:active {\n ${(props) =>\n props.pressStyle?.backgroundColor &&\n `background-color: ${props.pressStyle.backgroundColor};`}\n }\n`;\n\nexport const Box = React.forwardRef<\n HTMLDivElement | HTMLButtonElement,\n BoxProps\n>(\n (\n {\n children,\n onPress,\n onKeyDown,\n onKeyUp,\n role,\n \"aria-label\": ariaLabel,\n \"aria-labelledby\": ariaLabelledBy,\n \"aria-current\": ariaCurrent,\n \"aria-disabled\": ariaDisabled,\n \"aria-live\": ariaLive,\n \"aria-busy\": ariaBusy,\n \"aria-describedby\": ariaDescribedBy,\n \"aria-expanded\": ariaExpanded,\n \"aria-haspopup\": ariaHasPopup,\n \"aria-pressed\": ariaPressed,\n \"aria-controls\": ariaControls,\n tabIndex,\n as,\n src,\n alt,\n onError,\n onLoad,\n type,\n disabled,\n id,\n testID,\n \"data-testid\": dataTestId,\n ...props\n },\n ref\n ) => {\n // Handle as=\"img\" for rendering images with proper border-radius\n if (as === \"img\" && src) {\n return (\n <img\n src={src}\n alt={alt || \"\"}\n onError={onError}\n onLoad={onLoad}\n style={{\n display: \"block\",\n objectFit: \"cover\",\n width:\n typeof props.width === \"number\"\n ? `${props.width}px`\n : props.width,\n height:\n typeof props.height === \"number\"\n ? `${props.height}px`\n : props.height,\n borderRadius:\n typeof props.borderRadius === \"number\"\n ? `${props.borderRadius}px`\n : props.borderRadius,\n position: props.position,\n top: typeof props.top === \"number\" ? `${props.top}px` : props.top,\n left:\n typeof props.left === \"number\" ? `${props.left}px` : props.left,\n right:\n typeof props.right === \"number\"\n ? `${props.right}px`\n : props.right,\n bottom:\n typeof props.bottom === \"number\"\n ? `${props.bottom}px`\n : props.bottom,\n ...props.style,\n }}\n />\n );\n }\n\n return (\n <StyledBox\n ref={ref}\n elementType={as}\n id={id}\n type={as === \"button\" ? type || \"button\" : undefined}\n disabled={as === \"button\" ? disabled : undefined}\n onClick={onPress}\n onKeyDown={onKeyDown}\n onKeyUp={onKeyUp}\n role={role}\n aria-label={ariaLabel}\n aria-labelledby={ariaLabelledBy}\n aria-current={ariaCurrent}\n aria-disabled={ariaDisabled}\n aria-busy={ariaBusy}\n aria-describedby={ariaDescribedBy}\n aria-expanded={ariaExpanded}\n aria-haspopup={ariaHasPopup}\n aria-pressed={ariaPressed}\n aria-controls={ariaControls}\n aria-live={ariaLive}\n tabIndex={tabIndex !== undefined ? tabIndex : undefined}\n data-testid={dataTestId || testID}\n {...props}\n >\n {children}\n </StyledBox>\n );\n }\n);\n\nBox.displayName = \"Box\";\n","import React from \"react\";\nimport isPropValid from \"@emotion/is-prop-valid\";\n\n// Props that @emotion/is-prop-valid incorrectly treats as valid HTML.\n// These are React Native or component-specific props that match\n// valid HTML patterns (on* event handlers, SVG attributes).\nexport const ADDITIONAL_BLOCKED_PROPS = new Set([\n // RN-only event handlers (pass isPropValid's on* pattern)\n \"onPress\",\n \"onChangeText\",\n \"onLayout\",\n \"onMoveShouldSetResponder\",\n \"onResponderGrant\",\n \"onResponderMove\",\n \"onResponderRelease\",\n \"onResponderTerminate\",\n // SVG attributes that pass isPropValid\n \"strokeWidth\",\n // CSS properties that pass isPropValid but are used as component props\n \"overflow\",\n \"cursor\",\n \"fontSize\",\n \"fontWeight\",\n \"fontFamily\",\n \"textDecoration\",\n]);\n\nfunction shouldForwardProp(key: string): boolean {\n if (ADDITIONAL_BLOCKED_PROPS.has(key)) return false;\n return isPropValid(key);\n}\n\n/**\n * Creates a React component that renders the given HTML tag\n * but filters out non-HTML props before they reach the DOM.\n *\n * Uses @emotion/is-prop-valid (same library styled-components v4\n * uses internally) to automatically block invalid HTML attributes,\n * plus a small blocklist for false positives (RN on* handlers, SVG attrs).\n *\n * Usage: `const FilteredDiv = createFilteredElement(\"div\");`\n * Then: `const StyledBox = styled(FilteredDiv)<BoxProps>\\`...\\`;`\n *\n * styled-components can still read ALL props for CSS interpolation,\n * but only valid HTML attributes are forwarded to the DOM element.\n */\nexport function createFilteredElement(defaultTag: string) {\n const Component = React.forwardRef<HTMLElement, Record<string, unknown>>(\n ({ children, elementType, ...props }, ref) => {\n const Tag = (elementType as string) || defaultTag;\n const htmlProps: Record<string, unknown> = {};\n for (const key of Object.keys(props)) {\n if (shouldForwardProp(key)) {\n htmlProps[key] = props[key];\n }\n }\n return React.createElement(\n Tag,\n { ref, ...htmlProps },\n children as React.ReactNode\n );\n }\n );\n Component.displayName = `Filtered(${defaultTag})`;\n return Component;\n}\n","function memoize(fn) {\n var cache = {};\n return function (arg) {\n if (cache[arg] === undefined) cache[arg] = fn(arg);\n return cache[arg];\n };\n}\n\nexport default memoize;\n","import memoize from '@emotion/memoize';\n\nvar reactPropsRegex = /^((children|dangerouslySetInnerHTML|key|ref|autoFocus|defaultValue|defaultChecked|innerHTML|suppressContentEditableWarning|suppressHydrationWarning|valueLink|accept|acceptCharset|accessKey|action|allow|allowUserMedia|allowPaymentRequest|allowFullScreen|allowTransparency|alt|async|autoComplete|autoPlay|capture|cellPadding|cellSpacing|challenge|charSet|checked|cite|classID|className|cols|colSpan|content|contentEditable|contextMenu|controls|controlsList|coords|crossOrigin|data|dateTime|decoding|default|defer|dir|disabled|disablePictureInPicture|download|draggable|encType|form|formAction|formEncType|formMethod|formNoValidate|formTarget|frameBorder|headers|height|hidden|high|href|hrefLang|htmlFor|httpEquiv|id|inputMode|integrity|is|keyParams|keyType|kind|label|lang|list|loading|loop|low|marginHeight|marginWidth|max|maxLength|media|mediaGroup|method|min|minLength|multiple|muted|name|nonce|noValidate|open|optimum|pattern|placeholder|playsInline|poster|preload|profile|radioGroup|readOnly|referrerPolicy|rel|required|reversed|role|rows|rowSpan|sandbox|scope|scoped|scrolling|seamless|selected|shape|size|sizes|slot|span|spellCheck|src|srcDoc|srcLang|srcSet|start|step|style|summary|tabIndex|target|title|type|useMap|value|width|wmode|wrap|about|datatype|inlist|prefix|property|resource|typeof|vocab|autoCapitalize|autoCorrect|autoSave|color|inert|itemProp|itemScope|itemType|itemID|itemRef|on|results|security|unselectable|accentHeight|accumulate|additive|alignmentBaseline|allowReorder|alphabetic|amplitude|arabicForm|ascent|attributeName|attributeType|autoReverse|azimuth|baseFrequency|baselineShift|baseProfile|bbox|begin|bias|by|calcMode|capHeight|clip|clipPathUnits|clipPath|clipRule|colorInterpolation|colorInterpolationFilters|colorProfile|colorRendering|contentScriptType|contentStyleType|cursor|cx|cy|d|decelerate|descent|diffuseConstant|direction|display|divisor|dominantBaseline|dur|dx|dy|edgeMode|elevation|enableBackground|end|exponent|externalResourcesRequired|fill|fillOpacity|fillRule|filter|filterRes|filterUnits|floodColor|floodOpacity|focusable|fontFamily|fontSize|fontSizeAdjust|fontStretch|fontStyle|fontVariant|fontWeight|format|from|fr|fx|fy|g1|g2|glyphName|glyphOrientationHorizontal|glyphOrientationVertical|glyphRef|gradientTransform|gradientUnits|hanging|horizAdvX|horizOriginX|ideographic|imageRendering|in|in2|intercept|k|k1|k2|k3|k4|kernelMatrix|kernelUnitLength|kerning|keyPoints|keySplines|keyTimes|lengthAdjust|letterSpacing|lightingColor|limitingConeAngle|local|markerEnd|markerMid|markerStart|markerHeight|markerUnits|markerWidth|mask|maskContentUnits|maskUnits|mathematical|mode|numOctaves|offset|opacity|operator|order|orient|orientation|origin|overflow|overlinePosition|overlineThickness|panose1|paintOrder|pathLength|patternContentUnits|patternTransform|patternUnits|pointerEvents|points|pointsAtX|pointsAtY|pointsAtZ|preserveAlpha|preserveAspectRatio|primitiveUnits|r|radius|refX|refY|renderingIntent|repeatCount|repeatDur|requiredExtensions|requiredFeatures|restart|result|rotate|rx|ry|scale|seed|shapeRendering|slope|spacing|specularConstant|specularExponent|speed|spreadMethod|startOffset|stdDeviation|stemh|stemv|stitchTiles|stopColor|stopOpacity|strikethroughPosition|strikethroughThickness|string|stroke|strokeDasharray|strokeDashoffset|strokeLinecap|strokeLinejoin|strokeMiterlimit|strokeOpacity|strokeWidth|surfaceScale|systemLanguage|tableValues|targetX|targetY|textAnchor|textDecoration|textRendering|textLength|to|transform|u1|u2|underlinePosition|underlineThickness|unicode|unicodeBidi|unicodeRange|unitsPerEm|vAlphabetic|vHanging|vIdeographic|vMathematical|values|vectorEffect|version|vertAdvY|vertOriginX|vertOriginY|viewBox|viewTarget|visibility|widths|wordSpacing|writingMode|x|xHeight|x1|x2|xChannelSelector|xlinkActuate|xlinkArcrole|xlinkHref|xlinkRole|xlinkShow|xlinkTitle|xlinkType|xmlBase|xmlns|xmlnsXlink|xmlLang|xmlSpace|y|y1|y2|yChannelSelector|z|zoomAndPan|for|class|autofocus)|(([Dd][Aa][Tt][Aa]|[Aa][Rr][Ii][Aa]|x)-.*))$/; // https://esbench.com/bench/5bfee68a4cd7e6009ef61d23\n\nvar index = memoize(function (prop) {\n return reactPropsRegex.test(prop) || prop.charCodeAt(0) === 111\n /* o */\n && prop.charCodeAt(1) === 110\n /* n */\n && prop.charCodeAt(2) < 91;\n}\n/* Z+1 */\n);\n\nexport default index;\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 useOverlayLayer,\n LAYER_OFFSET,\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 { Search } from \"@xsolla/xui-icons-base\";\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\nconst SUBMENU_GAP = 8;\nconst SUBMENU_VIEWPORT_PADDING = 8;\n\nconst clipsOverflow = (style: CSSStyleDeclaration) => {\n return /(auto|scroll|hidden|clip)/.test(\n `${style.overflow}${style.overflowX}${style.overflowY}`\n );\n};\n\nconst getSubmenuBoundary = (node: HTMLElement) => {\n const viewport = {\n top: SUBMENU_VIEWPORT_PADDING,\n right: window.innerWidth - SUBMENU_VIEWPORT_PADDING,\n bottom: window.innerHeight - SUBMENU_VIEWPORT_PADDING,\n left: SUBMENU_VIEWPORT_PADDING,\n };\n\n let current = node.parentElement;\n while (current && current !== document.body) {\n const style = window.getComputedStyle(current);\n if (clipsOverflow(style) && current.getAttribute(\"role\") !== \"menu\") {\n const rect = current.getBoundingClientRect();\n return {\n top: Math.max(viewport.top, rect.top + SUBMENU_VIEWPORT_PADDING),\n right: Math.min(viewport.right, rect.right - SUBMENU_VIEWPORT_PADDING),\n bottom: Math.min(\n viewport.bottom,\n rect.bottom - SUBMENU_VIEWPORT_PADDING\n ),\n left: Math.max(viewport.left, rect.left + SUBMENU_VIEWPORT_PADDING),\n };\n }\n current = current.parentElement;\n }\n\n return viewport;\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 slot,\n slotContent,\n value,\n hint,\n trailingIcon,\n keyboardShortcut,\n hasSubmenu,\n submenu,\n onSelect,\n onCheckedChange,\n testID,\n themeMode,\n themeProductContext,\n \"data-testid\": testId,\n}) => {\n const { theme: rawTheme } = useResolvedTheme({\n themeMode,\n themeProductContext,\n });\n const theme = rawTheme as any;\n const overlayLayer = useOverlayLayer();\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 registerCell = ctx?.registerCell;\n const unregisterCell = ctx?.unregisterCell;\n const getCellIndex = ctx?.getCellIndex;\n const [isHovered, setIsHovered] = useState(false);\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 // A submenu this cell renders itself: submenu content passed via the\n // `submenu` prop (the `items` presets and direct `hasSubmenu` children). The\n // compound <ContextMenu.Submenu> path renders its own panel and manages\n // `activeSubmenuId` itself, passing `hasSubmenu` WITHOUT a `submenu` prop, so\n // it is excluded from the coordination below.\n const ownsSubmenu = Boolean(hasSubmenu && submenu != null);\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(() => {\n setSubmenuOpen(false);\n if (ownsSubmenu && ctx?.activeSubmenuId === id) {\n ctx.setActiveSubmenuId?.(null);\n }\n }, 120);\n };\n\n useEffect(() => () => cancelClose(), []);\n\n // Close this cell's submenu the instant a sibling submenu becomes the active\n // one. Preset submenus each hold independent open state, so without this a\n // fast parent-to-parent switch would leave the outgoing submenu visible for\n // the full 120ms close grace while the incoming one opens - two submenus on\n // screen at once. Keying off the shared `activeSubmenuId` collapses that\n // overlap window to a single render.\n useEffect(() => {\n if (!ownsSubmenu || !submenuOpen) return;\n const activeId = ctx?.activeSubmenuId;\n if (activeId != null && activeId !== id) {\n cancelClose();\n setSubmenuOpen(false);\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [ctx?.activeSubmenuId, ownsSubmenu, submenuOpen, id]);\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 // Nested submenus render as flat portals on document.body, so a click in\n // a DEEPER submenu is not contained by this option's submenuWrapperRef.\n // Without this guard every ancestor treats that click as an outside\n // press and collapses the whole chain (a leaf selection closed all\n // menus). Any context-menu portal in the ancestry means the click is\n // still inside the open menu tree — keep this submenu open and let the\n // owning level decide what to do.\n if (target.closest(\"[data-xui-context-menu-portal]\")) return;\n setSubmenuOpen(false);\n return;\n }\n if (inSubmenu) {\n // Activating a plain leaf action dismisses its submenu. Leave checkbox\n // and radio controls (and nested submenu triggers) open so the user can\n // see the change and keep interacting.\n const activated = target.closest(\n '[role=\"menuitem\"],[role=\"menuitemcheckbox\"],[role=\"menuitemradio\"]'\n );\n const isLeafAction =\n activated?.getAttribute(\"role\") === \"menuitem\" &&\n activated.getAttribute(\"aria-haspopup\") !== \"menu\";\n if (isLeafAction) 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\n const update = () => {\n const node = optionRef.current;\n if (!node) return;\n const rect = node.getBoundingClientRect();\n const submenuRect = submenuWrapperRef.current?.getBoundingClientRect();\n const submenuWidth = submenuRect?.width ?? 0;\n const submenuHeight = submenuRect?.height ?? 0;\n const boundary = getSubmenuBoundary(node);\n\n const rightSideLeft = rect.right + SUBMENU_GAP;\n const leftSideLeft = rect.left - SUBMENU_GAP - submenuWidth;\n const opensLeft =\n submenuWidth > 0 && rightSideLeft + submenuWidth > boundary.right;\n\n let left = opensLeft ? leftSideLeft : rightSideLeft;\n\n if (submenuWidth > 0) {\n if (opensLeft) {\n left = Math.max(SUBMENU_VIEWPORT_PADDING, left);\n } else {\n left = Math.min(\n Math.max(boundary.left, left),\n Math.max(boundary.left, boundary.right - submenuWidth)\n );\n }\n }\n\n let top = rect.top;\n if (submenuHeight > 0 && top + submenuHeight > boundary.bottom) {\n top = boundary.bottom - submenuHeight;\n }\n top = Math.max(boundary.top, top);\n\n setSubmenuPos((prev) =>\n prev?.top === top && prev.left === left ? prev : { top, left }\n );\n };\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 });\n const onSelectRef = React.useRef(onSelect);\n onSelectRef.current = onSelect;\n // Register on mount / unregister on unmount. Deps are the stable registry\n // callbacks + id only - NOT `ctx`, whose identity changes on every hover\n // (activeIndex). Depending on `ctx` here churned register/unregister and, on\n // React <18 (interleaved passive-effect flush), collapsed every row to the\n // same index so one hover highlighted all rows (FEP-764).\n useEffect(() => {\n if (!registerCell || !unregisterCell) return;\n registerCell(id, {\n type: \"option\",\n onSelect: () => onSelectRef.current?.(),\n });\n return () => unregisterCell(id);\n }, [registerCell, unregisterCell, id]);\n\n // Keep registry metadata (disabled) in sync without reordering the cell.\n useEffect(() => {\n if (!registerCell) return;\n registerCell(id, {\n type: \"option\",\n disabled,\n onSelect: () => onSelectRef.current?.(),\n });\n }, [registerCell, id, disabled]);\n\n // Derive index live from the registry instead of caching it in state, so it\n // is always correct after dynamic add/remove without per-item re-registration.\n const index = getCellIndex ? getCellIndex(id) : -1;\n const isActive = ctx ? index >= 0 && ctx.activeIndex === index : false;\n const inHoverState =\n isActive || (!ctx && isHovered) || (hasSubmenu && submenuOpen);\n\n const handleEnter = () => {\n if (disabled) return;\n if (ctx && index >= 0) ctx.setActiveIndex(index);\n if (!ctx) setIsHovered(true);\n if (hasSubmenu) setSubmenuOpen(true);\n // Claim the shared active-submenu slot the instant the pointer enters, so\n // any OTHER open submenu closes immediately (see the effect above) instead\n // of lingering for its 120ms close grace and overlapping this one during a\n // fast parent-to-parent switch.\n if (ownsSubmenu) ctx?.setActiveSubmenuId?.(id);\n };\n\n const handleLeave = () => {\n if (!ctx) setIsHovered(false);\n if (hasSubmenu) scheduleClose();\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\n ? leadingControl === \"radio\"\n ? \"menuitemradio\"\n : \"menuitemcheckbox\"\n : \"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 if (checked !== undefined) {\n onCheckedChange?.(!checked);\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 if (checked !== undefined) {\n onCheckedChange?.(!checked);\n }\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={handleLeave}\n onFocus={handleEnter}\n onBlur={() => {\n if (!ctx) setIsHovered(false);\n }}\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 {slot}\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 data-xui-context-menu-portal={ctx?.menuId}\n onMouseEnter={cancelClose}\n onMouseLeave={scheduleClose}\n style={{\n position: \"fixed\",\n top: submenuPos.top,\n left: submenuPos.left,\n // Same band as the parent menu; the submenu portal mounts later in\n // the DOM so it paints above it (holds for arbitrary nesting depth).\n zIndex: overlayLayer + LAYER_OFFSET.menu,\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: rawTheme } = useResolvedTheme({\n themeMode,\n themeProductContext,\n });\n const theme = rawTheme as any;\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 registerCell = ctx?.registerCell;\n const unregisterCell = ctx?.unregisterCell;\n useEffect(() => {\n if (!registerCell || !unregisterCell) return;\n registerCell(id, { type: \"heading\" });\n return () => unregisterCell(id);\n }, [registerCell, unregisterCell, id]);\n\n return (\n <div\n role=\"presentation\"\n data-testid={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 onChange,\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: rawTheme } = useResolvedTheme({\n themeMode,\n themeProductContext,\n });\n const theme = rawTheme as any;\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 const registerCell = ctx?.registerCell;\n const unregisterCell = ctx?.unregisterCell;\n useEffect(() => {\n if (!registerCell || !unregisterCell) return;\n registerCell(id, { type: \"search\" });\n return () => unregisterCell(id);\n }, [registerCell, unregisterCell, id]);\n\n return (\n <div\n style={{\n boxSizing: \"border-box\",\n paddingLeft: sizing.searchPaddingHorizontal,\n paddingRight: sizing.searchPaddingHorizontal,\n paddingTop: sizing.searchPaddingVertical,\n paddingBottom: sizing.searchPaddingVertical,\n }}\n >\n <div\n style={{\n display: \"flex\",\n alignItems: \"center\",\n gap: 8,\n paddingBottom: 6,\n borderBottom: `1px solid ${theme.colors.border.secondary}`,\n }}\n >\n <Search\n variant=\"line\"\n size={sizing.searchIconSize}\n color={theme.colors.control.input.placeholder}\n aria-hidden\n />\n <input\n type=\"search\"\n role=\"searchbox\"\n aria-label={ariaLabel}\n placeholder={placeholder}\n value={value ?? \"\"}\n autoFocus={autoFocus}\n onChange={(e) => {\n onChange?.(e);\n onValueChange?.(e.target.value);\n }}\n data-testid={testId || testID}\n style={{\n flex: 1,\n minWidth: 0,\n boxSizing: \"border-box\",\n border: \"none\",\n outline: \"none\",\n background: \"transparent\",\n padding: 0,\n color: theme.colors.content.primary,\n fontSize: sizing.searchFontSize,\n lineHeight: `${sizing.searchLineHeight}px`,\n }}\n />\n </div>\n </div>\n );\n};\n\nconst DividerCell: React.FC<\n ContextMenuDividerItemProps & ThemeOverrideProps\n> = ({ themeMode, themeProductContext, \"data-testid\": testId }) => {\n const { theme: rawTheme } = useResolvedTheme({\n themeMode,\n themeProductContext,\n });\n const theme = rawTheme as any;\n const ctx = useContextMenu();\n const id = useId();\n const registerCell = ctx?.registerCell;\n const unregisterCell = ctx?.unregisterCell;\n useEffect(() => {\n if (!registerCell || !unregisterCell) return;\n registerCell(id, { type: \"divider\" });\n return () => unregisterCell(id);\n }, [registerCell, unregisterCell, 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 React, {\n useState,\n useRef,\n useEffect,\n useLayoutEffect,\n useCallback,\n} from \"react\";\n// @ts-expect-error - this will be resolved at build time\nimport { Box } from \"@xsolla/xui-primitives\";\nimport { useDesignSystem } from \"@xsolla/xui-core\";\nimport { ContextMenuItem } from \"./ContextMenuItem\";\nimport { useContextMenu } from \"./ContextMenuContext\";\nimport type { ContextMenuSubmenuProps } from \"./types\";\n\n/** Gap (px) between the parent menu panel and the submenu panel */\nconst SUBMENU_GAP = 4;\n/** Delay (ms) before the submenu opens on hover */\nconst OPEN_DELAY_MS = 200;\n/** Grace period (ms) before the submenu closes after the pointer leaves */\nconst CLOSE_GRACE_MS = 100;\n\n/** Module-level counter for stable, unique submenu IDs (React 16 compatible) */\nlet _submenuIdCounter = 0;\n\nexport const ContextMenuSubmenu: React.FC<ContextMenuSubmenuProps> = ({\n label,\n icon,\n disabled,\n children,\n size: propSize,\n \"data-testid\": testId = \"context-menu-submenu\",\n}) => {\n const { theme } = useDesignSystem();\n const xuiTheme = theme as any;\n const context = useContextMenu();\n const size = propSize || context?.size || \"md\";\n const sizeStyles = xuiTheme.sizing.contextMenu(size);\n const borderRadius =\n xuiTheme.shape?.contextMenu?.[size]?.borderRadius ??\n xuiTheme.radius?.button ??\n 8;\n\n const submenuIdRef = useRef<string | null>(null);\n if (submenuIdRef.current === null) {\n submenuIdRef.current = `xui-cm-submenu-${(_submenuIdCounter += 1)}`;\n }\n const submenuId = submenuIdRef.current;\n\n const [isOpen, setIsOpen] = useState(false);\n const [visible, setVisible] = useState(false);\n const [openLeft, setOpenLeft] = useState(false);\n const [topOffset, setTopOffset] = useState(0);\n\n const triggerRef = useRef<HTMLDivElement>(null);\n const submenuRef = useRef<HTMLDivElement>(null);\n const openTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n const closeTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n\n const clearTimers = useCallback(() => {\n if (openTimerRef.current) clearTimeout(openTimerRef.current);\n if (closeTimerRef.current) clearTimeout(closeTimerRef.current);\n }, []);\n\n // Close this submenu when a sibling submenu becomes active (Bug #3 fix)\n useEffect(() => {\n if (!context?.activeSubmenuId) return;\n if (context.activeSubmenuId !== submenuId) {\n setIsOpen(false);\n }\n }, [context?.activeSubmenuId, submenuId]);\n\n const calculatePlacement = useCallback(() => {\n if (!triggerRef.current) return;\n const triggerRect = triggerRef.current.getBoundingClientRect();\n const estimatedWidth = sizeStyles.minWidth + 32;\n const wouldOverflowRight =\n triggerRect.right + estimatedWidth + SUBMENU_GAP > window.innerWidth - 8;\n // Bug #1/#2 fix: only flip left when there is actually space on the left\n const hasSpaceOnLeft =\n triggerRect.left - SUBMENU_GAP - estimatedWidth >= 8;\n setOpenLeft(wouldOverflowRight && hasSpaceOnLeft);\n setTopOffset(0);\n }, [sizeStyles.minWidth]);\n\n useLayoutEffect(() => {\n if (!isOpen || !submenuRef.current || !triggerRef.current) return;\n\n const submenuRect = submenuRef.current.getBoundingClientRect();\n const triggerRect = triggerRef.current.getBoundingClientRect();\n\n const wouldOverflowRight =\n triggerRect.right + submenuRect.width + SUBMENU_GAP >\n window.innerWidth - 8;\n const hasSpaceOnLeft =\n triggerRect.left - SUBMENU_GAP - submenuRect.width >= 8;\n setOpenLeft(wouldOverflowRight && hasSpaceOnLeft);\n\n const overflowBottom =\n triggerRect.top + submenuRect.height - (window.innerHeight - 8);\n if (overflowBottom > 0) {\n setTopOffset(-Math.min(overflowBottom, triggerRect.top - 8));\n } else {\n setTopOffset(0);\n }\n }, [isOpen]);\n\n useEffect(() => {\n if (!isOpen) {\n setVisible(false);\n return;\n }\n const raf = requestAnimationFrame(() => setVisible(true));\n return () => cancelAnimationFrame(raf);\n }, [isOpen]);\n\n useEffect(() => () => clearTimers(), [clearTimers]);\n\n const handleTriggerEnter = () => {\n if (disabled) return;\n clearTimers();\n openTimerRef.current = setTimeout(() => {\n calculatePlacement();\n setIsOpen(true);\n context?.setActiveSubmenuId(submenuId);\n }, OPEN_DELAY_MS);\n };\n\n const handleTriggerLeave = () => {\n clearTimers();\n closeTimerRef.current = setTimeout(() => {\n setIsOpen(false);\n if (context?.activeSubmenuId === submenuId) {\n context.setActiveSubmenuId(null);\n }\n }, CLOSE_GRACE_MS);\n };\n\n const handleSubmenuEnter = () => clearTimers();\n\n const handleSubmenuLeave = () => {\n clearTimers();\n closeTimerRef.current = setTimeout(() => {\n setIsOpen(false);\n if (context?.activeSubmenuId === submenuId) {\n context.setActiveSubmenuId(null);\n }\n }, CLOSE_GRACE_MS);\n };\n\n const submenuPositionStyle = openLeft\n ? { right: `calc(100% + ${SUBMENU_GAP}px)` }\n : { left: `calc(100% + ${SUBMENU_GAP}px)` };\n\n return (\n <div\n ref={triggerRef}\n style={{ position: \"relative\" }}\n onMouseEnter={handleTriggerEnter}\n onMouseLeave={handleTriggerLeave}\n data-testid={testId}\n >\n <ContextMenuItem\n type=\"option\"\n label={label}\n leadingIcon={icon}\n disabled={disabled}\n hasSubmenu\n size={size}\n data-testid={`${testId}-trigger`}\n />\n\n {isOpen && (\n <div\n ref={submenuRef}\n onMouseEnter={handleSubmenuEnter}\n onMouseLeave={handleSubmenuLeave}\n style={{\n position: \"absolute\",\n top: topOffset,\n ...submenuPositionStyle,\n zIndex: 1001,\n opacity: visible ? 1 : 0,\n transform: visible\n ? \"translateX(0)\"\n : openLeft\n ? \"translateX(4px)\"\n : \"translateX(-4px)\",\n transition: \"opacity 100ms ease, transform 100ms ease\",\n }}\n data-testid={`${testId}-content`}\n >\n <Box\n role=\"menu\"\n backgroundColor={xuiTheme.colors.background.secondary}\n borderColor={xuiTheme.colors.border.secondary}\n borderWidth={1}\n borderRadius={borderRadius}\n paddingVertical={sizeStyles.paddingVertical}\n style={{\n boxShadow: \"0 4px 12px rgba(0,0,0,0.15)\",\n minWidth: sizeStyles.minWidth,\n }}\n >\n {children}\n </Box>\n </div>\n )}\n </div>\n );\n};\n\nContextMenuSubmenu.displayName = \"ContextMenuSubmenu\";\n","import { useLayoutEffect, useState, type RefObject } from \"react\";\nimport type { ContextMenuPlacement } from \"../types\";\n\ninterface UseContextMenuPositionOptions {\n triggerRef: RefObject<HTMLElement | null>;\n panelRef: RefObject<HTMLElement | null>;\n containerRef: 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\" | \"center\" } => {\n const [vertical, horizontal] = placement.split(\"-\") as [\n \"top\" | \"bottom\",\n \"start\" | \"end\" | \"center\",\n ];\n return { vertical, horizontal };\n};\n\nconst joinPlacement = (\n vertical: \"top\" | \"bottom\",\n horizontal: \"start\" | \"end\" | \"center\"\n): ContextMenuPlacement => `${vertical}-${horizontal}` as ContextMenuPlacement;\n\nexport const useContextMenuPosition = ({\n triggerRef,\n panelRef,\n containerRef,\n isOpen,\n placement = \"bottom-start\",\n offset = 4,\n}: UseContextMenuPositionOptions): ResolvedPosition | undefined => {\n const [resolved, setResolved] = useState<ResolvedPosition | undefined>();\n\n useLayoutEffect(() => {\n if (!isOpen) {\n setResolved(undefined);\n return;\n }\n\n const compute = () => {\n const trigger = triggerRef.current;\n const panel = panelRef.current;\n const container = containerRef.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\" | \"center\") => {\n if (h === \"center\")\n return triggerRect.left + triggerRect.width / 2 - panelRect.width / 2;\n return h === \"start\"\n ? triggerRect.left\n : triggerRect.right - panelRect.width;\n };\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 if (horizontal === \"center\") {\n const maxLeft = viewportWidth - panelRect.width;\n left = maxLeft >= 0 ? Math.min(Math.max(left, 0), maxLeft) : 0;\n } else {\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\n // Convert viewport coordinates to local (absolute-positioning) coords\n // relative to the container. Reading containerRect here (inside the\n // layout effect) guarantees we measure at the same time as the trigger\n // and panel, avoiding stale-rect issues from intermediate renders.\n if (container) {\n const containerRect = container.getBoundingClientRect();\n const cOffsetW = container.offsetWidth;\n const cOffsetH = container.offsetHeight;\n const scaleX = cOffsetW > 0 ? containerRect.width / cOffsetW : 1;\n const scaleY = cOffsetH > 0 ? containerRect.height / cOffsetH : 1;\n left = (left - containerRect.left) / (scaleX || 1);\n top = (top - containerRect.top) / (scaleY || 1);\n }\n\n const next = {\n top,\n left,\n placement: joinPlacement(vertical, horizontal),\n };\n setResolved((prev) =>\n prev &&\n prev.top === next.top &&\n prev.left === next.left &&\n prev.placement === next.placement\n ? prev\n : next\n );\n };\n\n compute();\n // No scroll listener: the menu dismisses on scroll (see ContextMenu), so\n // following the trigger would be dead work. Resize still repositions an\n // open menu.\n const onResize = () => compute();\n window.addEventListener(\"resize\", onResize);\n\n return () => {\n window.removeEventListener(\"resize\", onResize);\n };\n }, [isOpen, placement, offset, triggerRef, panelRef, containerRef]);\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","React","styled","React","import_xui_core","import_react","import_react","import_jsx_runtime","React","index","import_react","import_xui_core","import_jsx_runtime","SUBMENU_GAP","import_react","import_react","import_jsx_runtime","index"]}