@chayns-components/core 5.5.65 → 5.5.66
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/AGENTS.md +32 -0
- package/lib/cjs/components/context-menu/ContextMenu.js +13 -5
- package/lib/cjs/components/context-menu/ContextMenu.js.map +1 -1
- package/lib/cjs/components/context-menu/ContextMenu.test.js +234 -0
- package/lib/cjs/components/context-menu/ContextMenu.test.js.map +1 -0
- package/lib/cjs/components/context-menu/ContextMenu.types.js.map +1 -1
- package/lib/cjs/components/context-menu/ContextMenu.utils.js +4 -1
- package/lib/cjs/components/context-menu/ContextMenu.utils.js.map +1 -1
- package/lib/cjs/components/context-menu/context-menu-content/ContextMenuContent.js +11 -33
- package/lib/cjs/components/context-menu/context-menu-content/ContextMenuContent.js.map +1 -1
- package/lib/cjs/components/context-menu/context-menu-content/ContextMenuContent.styles.js +11 -3
- package/lib/cjs/components/context-menu/context-menu-content/ContextMenuContent.styles.js.map +1 -1
- package/lib/cjs/components/context-menu/context-menu-content/context-menu-content-item/ContextMenuContentItem.js +74 -0
- package/lib/cjs/components/context-menu/context-menu-content/context-menu-content-item/ContextMenuContentItem.js.map +1 -0
- package/lib/esm/components/context-menu/ContextMenu.js +13 -4
- package/lib/esm/components/context-menu/ContextMenu.js.map +1 -1
- package/lib/esm/components/context-menu/ContextMenu.test.js +223 -0
- package/lib/esm/components/context-menu/ContextMenu.test.js.map +1 -0
- package/lib/esm/components/context-menu/ContextMenu.types.js.map +1 -1
- package/lib/esm/components/context-menu/ContextMenu.utils.js +4 -1
- package/lib/esm/components/context-menu/ContextMenu.utils.js.map +1 -1
- package/lib/esm/components/context-menu/context-menu-content/ContextMenuContent.js +13 -35
- package/lib/esm/components/context-menu/context-menu-content/ContextMenuContent.js.map +1 -1
- package/lib/esm/components/context-menu/context-menu-content/ContextMenuContent.styles.js +11 -3
- package/lib/esm/components/context-menu/context-menu-content/ContextMenuContent.styles.js.map +1 -1
- package/lib/esm/components/context-menu/context-menu-content/context-menu-content-item/ContextMenuContentItem.js +66 -0
- package/lib/esm/components/context-menu/context-menu-content/context-menu-content-item/ContextMenuContentItem.js.map +1 -0
- package/lib/types/components/context-menu/ContextMenu.types.d.ts +9 -0
- package/lib/types/components/context-menu/context-menu-content/ContextMenuContent.styles.d.ts +4 -2
- package/lib/types/components/context-menu/context-menu-content/context-menu-content-item/ContextMenuContentItem.d.ts +11 -0
- package/package.json +2 -2
package/AGENTS.md
CHANGED
|
@@ -1650,6 +1650,29 @@ import { ContextMenu } from '@chayns-components/core';
|
|
|
1650
1650
|
/>
|
|
1651
1651
|
```
|
|
1652
1652
|
|
|
1653
|
+
#### With Disabled Items
|
|
1654
|
+
|
|
1655
|
+
```tsx
|
|
1656
|
+
<ContextMenu
|
|
1657
|
+
items={[
|
|
1658
|
+
{
|
|
1659
|
+
icons: ['fa fa-pencil'],
|
|
1660
|
+
key: 'rename',
|
|
1661
|
+
text: 'Umbenennen',
|
|
1662
|
+
onClick: () => alert('Option "Umbenennen" wurde geklickt...'),
|
|
1663
|
+
},
|
|
1664
|
+
{
|
|
1665
|
+
icons: ['fa fa-trash'],
|
|
1666
|
+
key: 'delete',
|
|
1667
|
+
text: 'Löschen',
|
|
1668
|
+
isDisabled: true,
|
|
1669
|
+
disabledReason: 'Dir fehlt die Berechtigung, diesen Eintrag zu löschen.',
|
|
1670
|
+
onClick: () => alert('Option "Löschen" wurde geklickt...'),
|
|
1671
|
+
},
|
|
1672
|
+
]}
|
|
1673
|
+
/>
|
|
1674
|
+
```
|
|
1675
|
+
|
|
1653
1676
|
### Props
|
|
1654
1677
|
|
|
1655
1678
|
| name | type | required | description |
|
|
@@ -1693,6 +1716,15 @@ import { ContextMenu } from '@chayns-components/core';
|
|
|
1693
1716
|
- `ContextMenuItem` -> `type ContextMenuItem = {
|
|
1694
1717
|
/** Optional icons for the item. Can be strings or React nodes. */
|
|
1695
1718
|
icons?: string[] | ReactNode;
|
|
1719
|
+
/**
|
|
1720
|
+
* Whether the item is disabled. Disabled items cannot be activated.
|
|
1721
|
+
*/
|
|
1722
|
+
isDisabled?: boolean;
|
|
1723
|
+
/**
|
|
1724
|
+
* Reason why the item is disabled. Only shown for disabled items.
|
|
1725
|
+
* Displayed as a tooltip on desktop and a subtitle in the native select dialog on touch devices.
|
|
1726
|
+
*/
|
|
1727
|
+
disabledReason?: string;
|
|
1696
1728
|
/** Whether the item is selected. */
|
|
1697
1729
|
isSelected?: boolean;
|
|
1698
1730
|
/** Unique key for the item. */
|
|
@@ -113,17 +113,23 @@ const ContextMenu = /*#__PURE__*/(0, _react2.forwardRef)(({
|
|
|
113
113
|
list: items.map(({
|
|
114
114
|
icons,
|
|
115
115
|
text,
|
|
116
|
-
isSelected
|
|
116
|
+
isSelected,
|
|
117
|
+
isDisabled,
|
|
118
|
+
disabledReason
|
|
117
119
|
}, index) => ({
|
|
118
120
|
name: text,
|
|
119
121
|
id: index,
|
|
120
122
|
isSelected,
|
|
123
|
+
disabled: isDisabled,
|
|
124
|
+
subtitle: isDisabled ? disabledReason : undefined,
|
|
121
125
|
icon: /*#__PURE__*/(0, _react2.isValidElement)(icons) ? undefined : icons === null || icons === void 0 ? void 0 : icons[0]
|
|
122
126
|
}))
|
|
123
127
|
}).open();
|
|
124
128
|
if (result && typeof result[0] === 'number') {
|
|
125
|
-
|
|
126
|
-
|
|
129
|
+
const item = items[result[0]];
|
|
130
|
+
if (item && !item.isDisabled) {
|
|
131
|
+
void item.onClick();
|
|
132
|
+
}
|
|
127
133
|
}
|
|
128
134
|
} else if (contextMenuRef.current) {
|
|
129
135
|
if (!newContainer) {
|
|
@@ -225,7 +231,7 @@ const ContextMenu = /*#__PURE__*/(0, _react2.forwardRef)(({
|
|
|
225
231
|
event.stopPropagation();
|
|
226
232
|
void handleShow();
|
|
227
233
|
}
|
|
228
|
-
}, [focusedIndex, handleHide, handleShow, isHovered, isContentShown, items,
|
|
234
|
+
}, [focusedIndex, handleHide, handleShow, isHovered, isContentShown, items, shouldCloseOnPopupClick, shouldDisableClick, shouldUseFocusableWrapper]);
|
|
229
235
|
const handleContextMenu = (0, _react2.useCallback)(event => {
|
|
230
236
|
event.preventDefault();
|
|
231
237
|
event.stopPropagation();
|
|
@@ -284,7 +290,9 @@ const ContextMenu = /*#__PURE__*/(0, _react2.forwardRef)(({
|
|
|
284
290
|
(0, _react2.useEffect)(() => {
|
|
285
291
|
const handleDocumentClick = event => {
|
|
286
292
|
var _contextMenuContentRe2;
|
|
287
|
-
|
|
293
|
+
const target = event.target;
|
|
294
|
+
const isInsideMenu = (_contextMenuContentRe2 = contextMenuContentRef.current) === null || _contextMenuContentRe2 === void 0 ? void 0 : _contextMenuContentRe2.contains(target);
|
|
295
|
+
if (isInsideMenu && (!shouldCloseOnPopupClick || target.closest('[aria-disabled="true"]'))) {
|
|
288
296
|
return;
|
|
289
297
|
}
|
|
290
298
|
handleHide();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ContextMenu.js","names":["_chaynsApi","require","_react","_react2","_interopRequireWildcard","_reactDom","_uuid","_environment","_Icon","_interopRequireDefault","_ContextMenuContent","_ContextMenu","_ContextMenu2","_ContextMenu3","_useKeyboardFocusHighlighting","_useFocusRingPortal","e","__esModule","default","t","WeakMap","r","n","o","i","f","__proto__","has","get","set","hasOwnProperty","call","Object","defineProperty","getOwnPropertyDescriptor","ContextMenu","forwardRef","alignment","className","children","createElement","icons","size","container","coordinates","headline","items","onHide","onShow","shouldCloseOnPopupClick","shouldDisableClick","shouldHidePopupArrow","shouldShowHoverEffect","shouldEnableKeyboardHighlighting","shouldUseDefaultTriggerStyles","style","yOffset","zIndex","dialogText","ref","internalCoordinates","setInternalCoordinates","useState","x","y","internalAlignment","setInternalAlignment","ContextMenuAlignment","TopLeft","newContainer","setNewContainer","focusedIndex","setFocusedIndex","getDefaultFocusedIndex","isContentShown","setIsContentShown","portal","setPortal","isHovered","setIsHovered","shouldUseFocusableWrapper","setShouldUseFocusableWrapper","uuid","useUuid","contextMenuContentRef","useRef","contextMenuRef","contextMenuFocusRingRef","shouldSkipNextContextMenuOpenRef","shouldPreventNextNativeContextMenuRef","isTouch","useIsTouch","shouldShowKeyboardHighlighting","useKeyboardFocusHighlighting","shouldShowWrapperKeyboardHighlighting","shouldUseKeyboardFocusableWrapper","useFocusRingPortal","isEnabled","overlayRef","shape","padding","useEffect","_contextMenuRef$curre","current","firstElementChild","HTMLElement","el","element","closest","Element","handleHide","useCallback","handleContainerBlur","event","_contextMenuContentRe","nextFocusedElement","relatedTarget","currentContainer","currentTarget","contains","handleShow","result","createDialog","type","DialogType","SELECT","text","buttons","list","map","isSelected","index","name","id","icon","isValidElement","undefined","open","_items$result$","onClick","height","childrenHeight","left","childrenLeft","top","childrenTop","width","childrenWidth","getBoundingClientRect","zoomX","offsetWidth","zoomY","offsetHeight","scrollLeft","scrollTop","BottomRight","TopRight","BottomLeft","handleClick","preventDefault","stopPropagation","handleKeyDown","isActivationKey","key","prev","length","selectItem","getActiveItemIndex","contextMenuContentElement","onClose","target","isContextMenuShortcut","shiftKey","handleContextMenu","handleGlobalKeyDown","activeElement","document","body","documentElement","shouldOpenFromFocusedParent","handleNativeContextMenuCapture","addEventListener","removeEventListener","useImperativeHandle","hide","show","handleDocumentClick","_contextMenuContentRe2","window","createPortal","AnimatePresence","initial","onItemFocus","onMouseEnter","onMouseLeave","focusableChildSelector","hasFocusableChild","Boolean","querySelector","Fragment","StyledContextMenu","$isActive","$shouldAddHoverEffect","$shouldShowWrapperKeyboardHighlighting","$shouldUseDefaultTriggerStyles","onContextMenuCapture","onContextMenu","onKeyDown","onBlur","tabIndex","role","displayName","_default","exports"],"sources":["../../../../src/components/context-menu/ContextMenu.tsx"],"sourcesContent":["import { createDialog, DialogType } from 'chayns-api';\nimport { AnimatePresence } from 'motion/react';\nimport React, {\n forwardRef,\n isValidElement,\n KeyboardEventHandler,\n MouseEvent,\n MouseEventHandler,\n ReactPortal,\n useCallback,\n useEffect,\n useImperativeHandle,\n useRef,\n useState,\n} from 'react';\nimport { createPortal } from 'react-dom';\nimport { useUuid } from '../../hooks/uuid';\nimport { useIsTouch } from '../../utils/environment';\nimport Icon from '../icon/Icon';\nimport ContextMenuContent from './context-menu-content/ContextMenuContent';\nimport { StyledContextMenu } from './ContextMenu.styles';\nimport {\n ContextMenuAlignment,\n type ContextMenuCoordinates,\n type ContextMenuProps,\n type ContextMenuRef,\n} from './ContextMenu.types';\nimport { SelectDialogResult } from '../../types/general';\nimport { getActiveItemIndex, getDefaultFocusedIndex, selectItem } from './ContextMenu.utils';\nimport { useKeyboardFocusHighlighting } from '../../hooks/useKeyboardFocusHighlighting';\nimport { useFocusRingPortal } from '../../hooks/useFocusRingPortal';\n\nconst ContextMenu = forwardRef<ContextMenuRef, ContextMenuProps>(\n (\n {\n alignment,\n className,\n children = <Icon icons={['ts-ellipsis_v']} size={18} />,\n container,\n coordinates,\n headline,\n items,\n onHide,\n onShow,\n shouldCloseOnPopupClick = true,\n shouldDisableClick = false,\n shouldHidePopupArrow = false,\n shouldShowHoverEffect = false,\n shouldEnableKeyboardHighlighting,\n shouldUseDefaultTriggerStyles = true,\n style,\n yOffset = 0,\n zIndex = 20,\n dialogText,\n },\n ref,\n ) => {\n const [internalCoordinates, setInternalCoordinates] = useState<ContextMenuCoordinates>({\n x: 0,\n y: 0,\n });\n\n const [internalAlignment, setInternalAlignment] = useState<ContextMenuAlignment>(\n ContextMenuAlignment.TopLeft,\n );\n\n const [newContainer, setNewContainer] = useState(container ?? null);\n const [focusedIndex, setFocusedIndex] = useState(getDefaultFocusedIndex(items));\n const [isContentShown, setIsContentShown] = useState(false);\n const [portal, setPortal] = useState<ReactPortal>();\n const [isHovered, setIsHovered] = useState(false);\n const [shouldUseFocusableWrapper, setShouldUseFocusableWrapper] = useState(false);\n\n const uuid = useUuid();\n\n const contextMenuContentRef = useRef<HTMLDivElement>(null);\n const contextMenuRef = useRef<HTMLSpanElement>(null);\n const contextMenuFocusRingRef = useRef<HTMLElement | null>(null);\n const shouldSkipNextContextMenuOpenRef = useRef(false);\n const shouldPreventNextNativeContextMenuRef = useRef(false);\n\n const isTouch = useIsTouch();\n const shouldShowKeyboardHighlighting = useKeyboardFocusHighlighting(\n shouldEnableKeyboardHighlighting && !shouldDisableClick,\n );\n const shouldShowWrapperKeyboardHighlighting =\n shouldShowKeyboardHighlighting && shouldUseFocusableWrapper;\n const shouldUseKeyboardFocusableWrapper = shouldUseFocusableWrapper && !shouldDisableClick;\n useFocusRingPortal(contextMenuRef, {\n isEnabled: shouldShowWrapperKeyboardHighlighting,\n overlayRef: contextMenuFocusRingRef,\n shape: shouldUseDefaultTriggerStyles ? 'circle' : 'rectangle',\n padding: shouldUseDefaultTriggerStyles ? 4 : 0,\n });\n\n useEffect(() => {\n contextMenuFocusRingRef.current =\n contextMenuRef.current?.firstElementChild instanceof HTMLElement\n ? contextMenuRef.current.firstElementChild\n : contextMenuRef.current;\n }, [children]);\n\n useEffect(() => {\n if (isContentShown) {\n setFocusedIndex(getDefaultFocusedIndex(items));\n }\n }, [isContentShown, items]);\n\n useEffect(() => {\n if (contextMenuRef.current && !container) {\n const el = contextMenuRef.current as HTMLElement;\n\n const element = el.closest('.dialog-inner, .page-provider, .tapp, body');\n\n setNewContainer(element);\n }\n }, [container]);\n\n useEffect(() => {\n if (container instanceof Element) {\n setNewContainer(container);\n }\n }, [container]);\n\n const handleHide = useCallback(() => {\n setIsContentShown(false);\n }, []);\n\n const handleContainerBlur = useCallback(\n (event: React.FocusEvent<HTMLSpanElement>) => {\n const nextFocusedElement = event.relatedTarget as Node | null;\n const currentContainer = event.currentTarget as HTMLElement;\n\n if (\n !nextFocusedElement ||\n (!currentContainer.contains(nextFocusedElement) &&\n !contextMenuContentRef.current?.contains(nextFocusedElement))\n ) {\n handleHide();\n }\n },\n [handleHide],\n );\n\n const handleShow = useCallback(async () => {\n if (isTouch) {\n const { result } = (await createDialog({\n type: DialogType.SELECT,\n text: dialogText,\n buttons: [],\n list: items.map(({ icons, text, isSelected }, index) => ({\n name: text,\n id: index,\n isSelected,\n icon: isValidElement(icons)\n ? undefined\n : (icons as string[] | undefined)?.[0],\n })),\n }).open()) as SelectDialogResult;\n\n if (result && typeof result[0] === 'number') {\n void items[result[0]]?.onClick();\n }\n } else if (contextMenuRef.current) {\n if (!newContainer) {\n return;\n }\n\n const {\n height: childrenHeight,\n left: childrenLeft,\n top: childrenTop,\n width: childrenWidth,\n } = contextMenuRef.current.getBoundingClientRect();\n\n const { height, width, top, left } = newContainer.getBoundingClientRect();\n\n const zoomX = width / (newContainer as HTMLElement).offsetWidth;\n const zoomY = height / (newContainer as HTMLElement).offsetHeight;\n\n const x =\n (childrenLeft + childrenWidth / 2 - left) / zoomX + newContainer.scrollLeft;\n const y =\n (childrenTop + childrenHeight / 2 - top) / zoomY +\n newContainer.scrollTop -\n yOffset;\n\n setInternalCoordinates({ x, y });\n\n if (x < width / 2) {\n if (y < height / 2) {\n setInternalAlignment(ContextMenuAlignment.BottomRight);\n } else {\n setInternalAlignment(ContextMenuAlignment.TopRight);\n }\n } else if (y < height / 2) {\n setInternalAlignment(ContextMenuAlignment.BottomLeft);\n } else {\n setInternalAlignment(ContextMenuAlignment.TopLeft);\n }\n\n setIsContentShown(true);\n }\n }, [isTouch, items, newContainer, yOffset, dialogText]);\n\n const handleClick = useCallback<MouseEventHandler<HTMLSpanElement>>(\n (event) => {\n if (shouldDisableClick) {\n return;\n }\n\n event.preventDefault();\n event.stopPropagation();\n\n void handleShow();\n },\n [handleShow, shouldDisableClick],\n );\n\n const handleKeyDown = useCallback<KeyboardEventHandler<HTMLSpanElement>>(\n (event) => {\n if (shouldDisableClick) {\n return;\n }\n\n const isActivationKey =\n event.key === 'Enter' || event.key === ' ' || event.key === 'Spacebar';\n\n if (isContentShown && event.key === 'Escape') {\n event.preventDefault();\n event.stopPropagation();\n handleHide();\n return;\n }\n\n if (isContentShown && !isHovered && event.key === 'ArrowDown') {\n event.preventDefault();\n event.stopPropagation();\n setFocusedIndex((prev) => (prev >= items.length - 1 ? 0 : prev + 1));\n return;\n }\n\n if (isContentShown && !isHovered && event.key === 'ArrowUp') {\n event.preventDefault();\n event.stopPropagation();\n setFocusedIndex((prev) => (prev <= 0 ? items.length - 1 : prev - 1));\n return;\n }\n\n if (isContentShown && isActivationKey) {\n if (\n selectItem({\n index: getActiveItemIndex({\n contextMenuContentElement: contextMenuContentRef.current,\n focusedIndex,\n }),\n items,\n onClose: handleHide,\n shouldCloseOnPopupClick,\n })\n ) {\n event.preventDefault();\n event.stopPropagation();\n }\n\n return;\n }\n\n if (event.currentTarget !== event.target) {\n return;\n }\n\n const isContextMenuShortcut =\n event.key === 'ContextMenu' || (event.key === 'F10' && event.shiftKey);\n\n if (isContextMenuShortcut) {\n event.preventDefault();\n event.stopPropagation();\n shouldSkipNextContextMenuOpenRef.current = true;\n void handleShow();\n return;\n }\n\n if (shouldUseFocusableWrapper && isActivationKey) {\n event.preventDefault();\n event.stopPropagation();\n void handleShow();\n }\n },\n [\n focusedIndex,\n handleHide,\n handleShow,\n isHovered,\n isContentShown,\n items,\n items.length,\n shouldCloseOnPopupClick,\n shouldDisableClick,\n shouldUseFocusableWrapper,\n ],\n );\n\n const handleContextMenu = useCallback(\n (event: MouseEvent<HTMLSpanElement>) => {\n event.preventDefault();\n event.stopPropagation();\n\n if (shouldDisableClick) {\n return;\n }\n\n if (shouldSkipNextContextMenuOpenRef.current) {\n shouldSkipNextContextMenuOpenRef.current = false;\n return;\n }\n\n void handleShow();\n },\n [handleShow, shouldDisableClick],\n );\n\n useEffect(() => {\n const handleGlobalKeyDown = (event: KeyboardEvent) => {\n if (shouldDisableClick || !contextMenuRef.current) {\n return;\n }\n\n const isContextMenuShortcut =\n event.key === 'ContextMenu' || (event.key === 'F10' && event.shiftKey);\n\n if (!isContextMenuShortcut) {\n return;\n }\n\n const { activeElement } = document;\n\n if (\n !(activeElement instanceof HTMLElement) ||\n activeElement === document.body ||\n activeElement === document.documentElement\n ) {\n return;\n }\n\n const shouldOpenFromFocusedParent =\n activeElement.contains(contextMenuRef.current) &&\n !contextMenuRef.current.contains(activeElement);\n\n if (!shouldOpenFromFocusedParent) {\n return;\n }\n\n event.preventDefault();\n event.stopPropagation();\n shouldPreventNextNativeContextMenuRef.current = true;\n void handleShow();\n };\n\n const handleNativeContextMenuCapture = (event: Event) => {\n if (!shouldPreventNextNativeContextMenuRef.current) {\n return;\n }\n\n shouldPreventNextNativeContextMenuRef.current = false;\n event.preventDefault();\n event.stopPropagation();\n };\n\n document.addEventListener('keydown', handleGlobalKeyDown, true);\n document.addEventListener('contextmenu', handleNativeContextMenuCapture, true);\n\n return () => {\n document.removeEventListener('keydown', handleGlobalKeyDown, true);\n document.removeEventListener('contextmenu', handleNativeContextMenuCapture, true);\n };\n }, [handleShow, shouldDisableClick]);\n\n useImperativeHandle(\n ref,\n () => ({\n hide: handleHide,\n show: handleShow,\n }),\n [handleHide, handleShow],\n );\n\n useEffect(() => {\n const handleDocumentClick = (event: PointerEvent) => {\n if (\n !shouldCloseOnPopupClick &&\n contextMenuContentRef.current?.contains(event.target as Node)\n ) {\n return;\n }\n\n handleHide();\n };\n\n if (isContentShown) {\n document.addEventListener('click', handleDocumentClick, true);\n window.addEventListener('blur', handleHide);\n\n if (typeof onShow === 'function') {\n onShow();\n }\n } else if (typeof onHide === 'function') {\n onHide();\n }\n\n return () => {\n document.removeEventListener('click', handleDocumentClick, true);\n window.removeEventListener('blur', handleHide);\n };\n }, [handleHide, isContentShown, onHide, onShow, shouldCloseOnPopupClick]);\n\n useEffect(() => {\n if (!newContainer) {\n return;\n }\n\n setPortal(() =>\n createPortal(\n <AnimatePresence initial={false}>\n {isContentShown && (\n <ContextMenuContent\n coordinates={coordinates ?? internalCoordinates}\n items={items}\n zIndex={zIndex}\n headline={headline}\n shouldHidePopupArrow={shouldHidePopupArrow}\n key={`contextMenu_${uuid}`}\n alignment={alignment ?? internalAlignment}\n ref={contextMenuContentRef}\n focusedIndex={focusedIndex}\n onItemFocus={setFocusedIndex}\n onMouseEnter={() => {\n setIsHovered(true);\n setFocusedIndex(-1);\n }}\n onMouseLeave={() => {\n setIsHovered(false);\n }}\n />\n )}\n </AnimatePresence>,\n newContainer,\n ),\n );\n }, [\n alignment,\n newContainer,\n coordinates,\n internalAlignment,\n internalCoordinates,\n isContentShown,\n items,\n uuid,\n zIndex,\n shouldHidePopupArrow,\n headline,\n focusedIndex,\n handleHide,\n ]);\n\n useEffect(() => {\n if (!contextMenuRef.current) {\n return;\n }\n\n const focusableChildSelector =\n 'button:not([disabled]), a[href], input:not([disabled]), select:not([disabled]), textarea:not([disabled]), [tabindex]:not([tabindex=\"-1\"]), [contenteditable=\"true\"]';\n\n const hasFocusableChild = Boolean(\n contextMenuRef.current.querySelector(focusableChildSelector),\n );\n\n setShouldUseFocusableWrapper(!hasFocusableChild);\n }, [children]);\n\n return (\n <>\n <StyledContextMenu\n className={\n className\n ? `beta-chayns-context-menu ${className}`\n : 'beta-chayns-context-menu'\n }\n $isActive={isContentShown && shouldShowHoverEffect}\n $shouldAddHoverEffect={!isTouch && shouldShowHoverEffect}\n $shouldShowWrapperKeyboardHighlighting={shouldShowWrapperKeyboardHighlighting}\n $shouldUseDefaultTriggerStyles={shouldUseDefaultTriggerStyles}\n onClick={handleClick}\n onContextMenuCapture={handleContextMenu}\n onContextMenu={handleContextMenu}\n onKeyDown={handleKeyDown}\n onBlur={handleContainerBlur}\n ref={contextMenuRef}\n tabIndex={shouldUseKeyboardFocusableWrapper ? 0 : undefined}\n role={shouldUseKeyboardFocusableWrapper ? 'button' : undefined}\n aria-haspopup={shouldUseKeyboardFocusableWrapper ? 'menu' : undefined}\n aria-expanded={shouldUseKeyboardFocusableWrapper ? isContentShown : undefined}\n style={style}\n >\n {children}\n </StyledContextMenu>\n {portal}\n </>\n );\n },\n);\n\nContextMenu.displayName = 'ContextMenu';\n\nexport default ContextMenu;\n"],"mappings":";;;;;;AAAA,IAAAA,UAAA,GAAAC,OAAA;AACA,IAAAC,MAAA,GAAAD,OAAA;AACA,IAAAE,OAAA,GAAAC,uBAAA,CAAAH,OAAA;AAaA,IAAAI,SAAA,GAAAJ,OAAA;AACA,IAAAK,KAAA,GAAAL,OAAA;AACA,IAAAM,YAAA,GAAAN,OAAA;AACA,IAAAO,KAAA,GAAAC,sBAAA,CAAAR,OAAA;AACA,IAAAS,mBAAA,GAAAD,sBAAA,CAAAR,OAAA;AACA,IAAAU,YAAA,GAAAV,OAAA;AACA,IAAAW,aAAA,GAAAX,OAAA;AAOA,IAAAY,aAAA,GAAAZ,OAAA;AACA,IAAAa,6BAAA,GAAAb,OAAA;AACA,IAAAc,mBAAA,GAAAd,OAAA;AAAoE,SAAAQ,uBAAAO,CAAA,WAAAA,CAAA,IAAAA,CAAA,CAAAC,UAAA,GAAAD,CAAA,KAAAE,OAAA,EAAAF,CAAA;AAAA,SAAAZ,wBAAAY,CAAA,EAAAG,CAAA,6BAAAC,OAAA,MAAAC,CAAA,OAAAD,OAAA,IAAAE,CAAA,OAAAF,OAAA,YAAAhB,uBAAA,YAAAA,CAAAY,CAAA,EAAAG,CAAA,SAAAA,CAAA,IAAAH,CAAA,IAAAA,CAAA,CAAAC,UAAA,SAAAD,CAAA,MAAAO,CAAA,EAAAC,CAAA,EAAAC,CAAA,KAAAC,SAAA,QAAAR,OAAA,EAAAF,CAAA,iBAAAA,CAAA,uBAAAA,CAAA,yBAAAA,CAAA,SAAAS,CAAA,MAAAF,CAAA,GAAAJ,CAAA,GAAAG,CAAA,GAAAD,CAAA,QAAAE,CAAA,CAAAI,GAAA,CAAAX,CAAA,UAAAO,CAAA,CAAAK,GAAA,CAAAZ,CAAA,GAAAO,CAAA,CAAAM,GAAA,CAAAb,CAAA,EAAAS,CAAA,gBAAAN,CAAA,IAAAH,CAAA,gBAAAG,CAAA,OAAAW,cAAA,CAAAC,IAAA,CAAAf,CAAA,EAAAG,CAAA,OAAAK,CAAA,IAAAD,CAAA,GAAAS,MAAA,CAAAC,cAAA,KAAAD,MAAA,CAAAE,wBAAA,CAAAlB,CAAA,EAAAG,CAAA,OAAAK,CAAA,CAAAI,GAAA,IAAAJ,CAAA,CAAAK,GAAA,IAAAN,CAAA,CAAAE,CAAA,EAAAN,CAAA,EAAAK,CAAA,IAAAC,CAAA,CAAAN,CAAA,IAAAH,CAAA,CAAAG,CAAA,WAAAM,CAAA,KAAAT,CAAA,EAAAG,CAAA;AAEpE,MAAMgB,WAAW,gBAAG,IAAAC,kBAAU,EAC1B,CACI;EACIC,SAAS;EACTC,SAAS;EACTC,QAAQ,gBAAGpC,OAAA,CAAAe,OAAA,CAAAsB,aAAA,CAAChC,KAAA,CAAAU,OAAI;IAACuB,KAAK,EAAE,CAAC,eAAe,CAAE;IAACC,IAAI,EAAE;EAAG,CAAE,CAAC;EACvDC,SAAS;EACTC,WAAW;EACXC,QAAQ;EACRC,KAAK;EACLC,MAAM;EACNC,MAAM;EACNC,uBAAuB,GAAG,IAAI;EAC9BC,kBAAkB,GAAG,KAAK;EAC1BC,oBAAoB,GAAG,KAAK;EAC5BC,qBAAqB,GAAG,KAAK;EAC7BC,gCAAgC;EAChCC,6BAA6B,GAAG,IAAI;EACpCC,KAAK;EACLC,OAAO,GAAG,CAAC;EACXC,MAAM,GAAG,EAAE;EACXC;AACJ,CAAC,EACDC,GAAG,KACF;EACD,MAAM,CAACC,mBAAmB,EAAEC,sBAAsB,CAAC,GAAG,IAAAC,gBAAQ,EAAyB;IACnFC,CAAC,EAAE,CAAC;IACJC,CAAC,EAAE;EACP,CAAC,CAAC;EAEF,MAAM,CAACC,iBAAiB,EAAEC,oBAAoB,CAAC,GAAG,IAAAJ,gBAAQ,EACtDK,kCAAoB,CAACC,OACzB,CAAC;EAED,MAAM,CAACC,YAAY,EAAEC,eAAe,CAAC,GAAG,IAAAR,gBAAQ,EAACnB,SAAS,IAAI,IAAI,CAAC;EACnE,MAAM,CAAC4B,YAAY,EAAEC,eAAe,CAAC,GAAG,IAAAV,gBAAQ,EAAC,IAAAW,oCAAsB,EAAC3B,KAAK,CAAC,CAAC;EAC/E,MAAM,CAAC4B,cAAc,EAAEC,iBAAiB,CAAC,GAAG,IAAAb,gBAAQ,EAAC,KAAK,CAAC;EAC3D,MAAM,CAACc,MAAM,EAAEC,SAAS,CAAC,GAAG,IAAAf,gBAAQ,EAAc,CAAC;EACnD,MAAM,CAACgB,SAAS,EAAEC,YAAY,CAAC,GAAG,IAAAjB,gBAAQ,EAAC,KAAK,CAAC;EACjD,MAAM,CAACkB,yBAAyB,EAAEC,4BAA4B,CAAC,GAAG,IAAAnB,gBAAQ,EAAC,KAAK,CAAC;EAEjF,MAAMoB,IAAI,GAAG,IAAAC,aAAO,EAAC,CAAC;EAEtB,MAAMC,qBAAqB,GAAG,IAAAC,cAAM,EAAiB,IAAI,CAAC;EAC1D,MAAMC,cAAc,GAAG,IAAAD,cAAM,EAAkB,IAAI,CAAC;EACpD,MAAME,uBAAuB,GAAG,IAAAF,cAAM,EAAqB,IAAI,CAAC;EAChE,MAAMG,gCAAgC,GAAG,IAAAH,cAAM,EAAC,KAAK,CAAC;EACtD,MAAMI,qCAAqC,GAAG,IAAAJ,cAAM,EAAC,KAAK,CAAC;EAE3D,MAAMK,OAAO,GAAG,IAAAC,uBAAU,EAAC,CAAC;EAC5B,MAAMC,8BAA8B,GAAG,IAAAC,0DAA4B,EAC/DxC,gCAAgC,IAAI,CAACH,kBACzC,CAAC;EACD,MAAM4C,qCAAqC,GACvCF,8BAA8B,IAAIZ,yBAAyB;EAC/D,MAAMe,iCAAiC,GAAGf,yBAAyB,IAAI,CAAC9B,kBAAkB;EAC1F,IAAA8C,sCAAkB,EAACV,cAAc,EAAE;IAC/BW,SAAS,EAAEH,qCAAqC;IAChDI,UAAU,EAAEX,uBAAuB;IACnCY,KAAK,EAAE7C,6BAA6B,GAAG,QAAQ,GAAG,WAAW;IAC7D8C,OAAO,EAAE9C,6BAA6B,GAAG,CAAC,GAAG;EACjD,CAAC,CAAC;EAEF,IAAA+C,iBAAS,EAAC,MAAM;IAAA,IAAAC,qBAAA;IACZf,uBAAuB,CAACgB,OAAO,GAC3B,EAAAD,qBAAA,GAAAhB,cAAc,CAACiB,OAAO,cAAAD,qBAAA,uBAAtBA,qBAAA,CAAwBE,iBAAiB,aAAYC,WAAW,GAC1DnB,cAAc,CAACiB,OAAO,CAACC,iBAAiB,GACxClB,cAAc,CAACiB,OAAO;EACpC,CAAC,EAAE,CAAChE,QAAQ,CAAC,CAAC;EAEd,IAAA8D,iBAAS,EAAC,MAAM;IACZ,IAAI3B,cAAc,EAAE;MAChBF,eAAe,CAAC,IAAAC,oCAAsB,EAAC3B,KAAK,CAAC,CAAC;IAClD;EACJ,CAAC,EAAE,CAAC4B,cAAc,EAAE5B,KAAK,CAAC,CAAC;EAE3B,IAAAuD,iBAAS,EAAC,MAAM;IACZ,IAAIf,cAAc,CAACiB,OAAO,IAAI,CAAC5D,SAAS,EAAE;MACtC,MAAM+D,EAAE,GAAGpB,cAAc,CAACiB,OAAsB;MAEhD,MAAMI,OAAO,GAAGD,EAAE,CAACE,OAAO,CAAC,4CAA4C,CAAC;MAExEtC,eAAe,CAACqC,OAAO,CAAC;IAC5B;EACJ,CAAC,EAAE,CAAChE,SAAS,CAAC,CAAC;EAEf,IAAA0D,iBAAS,EAAC,MAAM;IACZ,IAAI1D,SAAS,YAAYkE,OAAO,EAAE;MAC9BvC,eAAe,CAAC3B,SAAS,CAAC;IAC9B;EACJ,CAAC,EAAE,CAACA,SAAS,CAAC,CAAC;EAEf,MAAMmE,UAAU,GAAG,IAAAC,mBAAW,EAAC,MAAM;IACjCpC,iBAAiB,CAAC,KAAK,CAAC;EAC5B,CAAC,EAAE,EAAE,CAAC;EAEN,MAAMqC,mBAAmB,GAAG,IAAAD,mBAAW,EAClCE,KAAwC,IAAK;IAAA,IAAAC,qBAAA;IAC1C,MAAMC,kBAAkB,GAAGF,KAAK,CAACG,aAA4B;IAC7D,MAAMC,gBAAgB,GAAGJ,KAAK,CAACK,aAA4B;IAE3D,IACI,CAACH,kBAAkB,IAClB,CAACE,gBAAgB,CAACE,QAAQ,CAACJ,kBAAkB,CAAC,IAC3C,GAAAD,qBAAA,GAAC9B,qBAAqB,CAACmB,OAAO,cAAAW,qBAAA,eAA7BA,qBAAA,CAA+BK,QAAQ,CAACJ,kBAAkB,CAAC,CAAC,EACnE;MACEL,UAAU,CAAC,CAAC;IAChB;EACJ,CAAC,EACD,CAACA,UAAU,CACf,CAAC;EAED,MAAMU,UAAU,GAAG,IAAAT,mBAAW,EAAC,YAAY;IACvC,IAAIrB,OAAO,EAAE;MACT,MAAM;QAAE+B;MAAO,CAAC,GAAI,MAAM,IAAAC,uBAAY,EAAC;QACnCC,IAAI,EAAEC,qBAAU,CAACC,MAAM;QACvBC,IAAI,EAAEpE,UAAU;QAChBqE,OAAO,EAAE,EAAE;QACXC,IAAI,EAAElF,KAAK,CAACmF,GAAG,CAAC,CAAC;UAAExF,KAAK;UAAEqF,IAAI;UAAEI;QAAW,CAAC,EAAEC,KAAK,MAAM;UACrDC,IAAI,EAAEN,IAAI;UACVO,EAAE,EAAEF,KAAK;UACTD,UAAU;UACVI,IAAI,EAAE,iBAAAC,sBAAc,EAAC9F,KAAK,CAAC,GACrB+F,SAAS,GACR/F,KAAK,aAALA,KAAK,uBAALA,KAAK,CAA4B,CAAC;QAC7C,CAAC,CAAC;MACN,CAAC,CAAC,CAACgG,IAAI,CAAC,CAAwB;MAEhC,IAAIhB,MAAM,IAAI,OAAOA,MAAM,CAAC,CAAC,CAAC,KAAK,QAAQ,EAAE;QAAA,IAAAiB,cAAA;QACzC,OAAAA,cAAA,GAAK5F,KAAK,CAAC2E,MAAM,CAAC,CAAC,CAAC,CAAC,cAAAiB,cAAA,uBAAhBA,cAAA,CAAkBC,OAAO,CAAC,CAAC;MACpC;IACJ,CAAC,MAAM,IAAIrD,cAAc,CAACiB,OAAO,EAAE;MAC/B,IAAI,CAAClC,YAAY,EAAE;QACf;MACJ;MAEA,MAAM;QACFuE,MAAM,EAAEC,cAAc;QACtBC,IAAI,EAAEC,YAAY;QAClBC,GAAG,EAAEC,WAAW;QAChBC,KAAK,EAAEC;MACX,CAAC,GAAG7D,cAAc,CAACiB,OAAO,CAAC6C,qBAAqB,CAAC,CAAC;MAElD,MAAM;QAAER,MAAM;QAAEM,KAAK;QAAEF,GAAG;QAAEF;MAAK,CAAC,GAAGzE,YAAY,CAAC+E,qBAAqB,CAAC,CAAC;MAEzE,MAAMC,KAAK,GAAGH,KAAK,GAAI7E,YAAY,CAAiBiF,WAAW;MAC/D,MAAMC,KAAK,GAAGX,MAAM,GAAIvE,YAAY,CAAiBmF,YAAY;MAEjE,MAAMzF,CAAC,GACH,CAACgF,YAAY,GAAGI,aAAa,GAAG,CAAC,GAAGL,IAAI,IAAIO,KAAK,GAAGhF,YAAY,CAACoF,UAAU;MAC/E,MAAMzF,CAAC,GACH,CAACiF,WAAW,GAAGJ,cAAc,GAAG,CAAC,GAAGG,GAAG,IAAIO,KAAK,GAChDlF,YAAY,CAACqF,SAAS,GACtBlG,OAAO;MAEXK,sBAAsB,CAAC;QAAEE,CAAC;QAAEC;MAAE,CAAC,CAAC;MAEhC,IAAID,CAAC,GAAGmF,KAAK,GAAG,CAAC,EAAE;QACf,IAAIlF,CAAC,GAAG4E,MAAM,GAAG,CAAC,EAAE;UAChB1E,oBAAoB,CAACC,kCAAoB,CAACwF,WAAW,CAAC;QAC1D,CAAC,MAAM;UACHzF,oBAAoB,CAACC,kCAAoB,CAACyF,QAAQ,CAAC;QACvD;MACJ,CAAC,MAAM,IAAI5F,CAAC,GAAG4E,MAAM,GAAG,CAAC,EAAE;QACvB1E,oBAAoB,CAACC,kCAAoB,CAAC0F,UAAU,CAAC;MACzD,CAAC,MAAM;QACH3F,oBAAoB,CAACC,kCAAoB,CAACC,OAAO,CAAC;MACtD;MAEAO,iBAAiB,CAAC,IAAI,CAAC;IAC3B;EACJ,CAAC,EAAE,CAACe,OAAO,EAAE5C,KAAK,EAAEuB,YAAY,EAAEb,OAAO,EAAEE,UAAU,CAAC,CAAC;EAEvD,MAAMoG,WAAW,GAAG,IAAA/C,mBAAW,EAC1BE,KAAK,IAAK;IACP,IAAI/D,kBAAkB,EAAE;MACpB;IACJ;IAEA+D,KAAK,CAAC8C,cAAc,CAAC,CAAC;IACtB9C,KAAK,CAAC+C,eAAe,CAAC,CAAC;IAEvB,KAAKxC,UAAU,CAAC,CAAC;EACrB,CAAC,EACD,CAACA,UAAU,EAAEtE,kBAAkB,CACnC,CAAC;EAED,MAAM+G,aAAa,GAAG,IAAAlD,mBAAW,EAC5BE,KAAK,IAAK;IACP,IAAI/D,kBAAkB,EAAE;MACpB;IACJ;IAEA,MAAMgH,eAAe,GACjBjD,KAAK,CAACkD,GAAG,KAAK,OAAO,IAAIlD,KAAK,CAACkD,GAAG,KAAK,GAAG,IAAIlD,KAAK,CAACkD,GAAG,KAAK,UAAU;IAE1E,IAAIzF,cAAc,IAAIuC,KAAK,CAACkD,GAAG,KAAK,QAAQ,EAAE;MAC1ClD,KAAK,CAAC8C,cAAc,CAAC,CAAC;MACtB9C,KAAK,CAAC+C,eAAe,CAAC,CAAC;MACvBlD,UAAU,CAAC,CAAC;MACZ;IACJ;IAEA,IAAIpC,cAAc,IAAI,CAACI,SAAS,IAAImC,KAAK,CAACkD,GAAG,KAAK,WAAW,EAAE;MAC3DlD,KAAK,CAAC8C,cAAc,CAAC,CAAC;MACtB9C,KAAK,CAAC+C,eAAe,CAAC,CAAC;MACvBxF,eAAe,CAAE4F,IAAI,IAAMA,IAAI,IAAItH,KAAK,CAACuH,MAAM,GAAG,CAAC,GAAG,CAAC,GAAGD,IAAI,GAAG,CAAE,CAAC;MACpE;IACJ;IAEA,IAAI1F,cAAc,IAAI,CAACI,SAAS,IAAImC,KAAK,CAACkD,GAAG,KAAK,SAAS,EAAE;MACzDlD,KAAK,CAAC8C,cAAc,CAAC,CAAC;MACtB9C,KAAK,CAAC+C,eAAe,CAAC,CAAC;MACvBxF,eAAe,CAAE4F,IAAI,IAAMA,IAAI,IAAI,CAAC,GAAGtH,KAAK,CAACuH,MAAM,GAAG,CAAC,GAAGD,IAAI,GAAG,CAAE,CAAC;MACpE;IACJ;IAEA,IAAI1F,cAAc,IAAIwF,eAAe,EAAE;MACnC,IACI,IAAAI,wBAAU,EAAC;QACPnC,KAAK,EAAE,IAAAoC,gCAAkB,EAAC;UACtBC,yBAAyB,EAAEpF,qBAAqB,CAACmB,OAAO;UACxDhC;QACJ,CAAC,CAAC;QACFzB,KAAK;QACL2H,OAAO,EAAE3D,UAAU;QACnB7D;MACJ,CAAC,CAAC,EACJ;QACEgE,KAAK,CAAC8C,cAAc,CAAC,CAAC;QACtB9C,KAAK,CAAC+C,eAAe,CAAC,CAAC;MAC3B;MAEA;IACJ;IAEA,IAAI/C,KAAK,CAACK,aAAa,KAAKL,KAAK,CAACyD,MAAM,EAAE;MACtC;IACJ;IAEA,MAAMC,qBAAqB,GACvB1D,KAAK,CAACkD,GAAG,KAAK,aAAa,IAAKlD,KAAK,CAACkD,GAAG,KAAK,KAAK,IAAIlD,KAAK,CAAC2D,QAAS;IAE1E,IAAID,qBAAqB,EAAE;MACvB1D,KAAK,CAAC8C,cAAc,CAAC,CAAC;MACtB9C,KAAK,CAAC+C,eAAe,CAAC,CAAC;MACvBxE,gCAAgC,CAACe,OAAO,GAAG,IAAI;MAC/C,KAAKiB,UAAU,CAAC,CAAC;MACjB;IACJ;IAEA,IAAIxC,yBAAyB,IAAIkF,eAAe,EAAE;MAC9CjD,KAAK,CAAC8C,cAAc,CAAC,CAAC;MACtB9C,KAAK,CAAC+C,eAAe,CAAC,CAAC;MACvB,KAAKxC,UAAU,CAAC,CAAC;IACrB;EACJ,CAAC,EACD,CACIjD,YAAY,EACZuC,UAAU,EACVU,UAAU,EACV1C,SAAS,EACTJ,cAAc,EACd5B,KAAK,EACLA,KAAK,CAACuH,MAAM,EACZpH,uBAAuB,EACvBC,kBAAkB,EAClB8B,yBAAyB,CAEjC,CAAC;EAED,MAAM6F,iBAAiB,GAAG,IAAA9D,mBAAW,EAChCE,KAAkC,IAAK;IACpCA,KAAK,CAAC8C,cAAc,CAAC,CAAC;IACtB9C,KAAK,CAAC+C,eAAe,CAAC,CAAC;IAEvB,IAAI9G,kBAAkB,EAAE;MACpB;IACJ;IAEA,IAAIsC,gCAAgC,CAACe,OAAO,EAAE;MAC1Cf,gCAAgC,CAACe,OAAO,GAAG,KAAK;MAChD;IACJ;IAEA,KAAKiB,UAAU,CAAC,CAAC;EACrB,CAAC,EACD,CAACA,UAAU,EAAEtE,kBAAkB,CACnC,CAAC;EAED,IAAAmD,iBAAS,EAAC,MAAM;IACZ,MAAMyE,mBAAmB,GAAI7D,KAAoB,IAAK;MAClD,IAAI/D,kBAAkB,IAAI,CAACoC,cAAc,CAACiB,OAAO,EAAE;QAC/C;MACJ;MAEA,MAAMoE,qBAAqB,GACvB1D,KAAK,CAACkD,GAAG,KAAK,aAAa,IAAKlD,KAAK,CAACkD,GAAG,KAAK,KAAK,IAAIlD,KAAK,CAAC2D,QAAS;MAE1E,IAAI,CAACD,qBAAqB,EAAE;QACxB;MACJ;MAEA,MAAM;QAAEI;MAAc,CAAC,GAAGC,QAAQ;MAElC,IACI,EAAED,aAAa,YAAYtE,WAAW,CAAC,IACvCsE,aAAa,KAAKC,QAAQ,CAACC,IAAI,IAC/BF,aAAa,KAAKC,QAAQ,CAACE,eAAe,EAC5C;QACE;MACJ;MAEA,MAAMC,2BAA2B,GAC7BJ,aAAa,CAACxD,QAAQ,CAACjC,cAAc,CAACiB,OAAO,CAAC,IAC9C,CAACjB,cAAc,CAACiB,OAAO,CAACgB,QAAQ,CAACwD,aAAa,CAAC;MAEnD,IAAI,CAACI,2BAA2B,EAAE;QAC9B;MACJ;MAEAlE,KAAK,CAAC8C,cAAc,CAAC,CAAC;MACtB9C,KAAK,CAAC+C,eAAe,CAAC,CAAC;MACvBvE,qCAAqC,CAACc,OAAO,GAAG,IAAI;MACpD,KAAKiB,UAAU,CAAC,CAAC;IACrB,CAAC;IAED,MAAM4D,8BAA8B,GAAInE,KAAY,IAAK;MACrD,IAAI,CAACxB,qCAAqC,CAACc,OAAO,EAAE;QAChD;MACJ;MAEAd,qCAAqC,CAACc,OAAO,GAAG,KAAK;MACrDU,KAAK,CAAC8C,cAAc,CAAC,CAAC;MACtB9C,KAAK,CAAC+C,eAAe,CAAC,CAAC;IAC3B,CAAC;IAEDgB,QAAQ,CAACK,gBAAgB,CAAC,SAAS,EAAEP,mBAAmB,EAAE,IAAI,CAAC;IAC/DE,QAAQ,CAACK,gBAAgB,CAAC,aAAa,EAAED,8BAA8B,EAAE,IAAI,CAAC;IAE9E,OAAO,MAAM;MACTJ,QAAQ,CAACM,mBAAmB,CAAC,SAAS,EAAER,mBAAmB,EAAE,IAAI,CAAC;MAClEE,QAAQ,CAACM,mBAAmB,CAAC,aAAa,EAAEF,8BAA8B,EAAE,IAAI,CAAC;IACrF,CAAC;EACL,CAAC,EAAE,CAAC5D,UAAU,EAAEtE,kBAAkB,CAAC,CAAC;EAEpC,IAAAqI,2BAAmB,EACf5H,GAAG,EACH,OAAO;IACH6H,IAAI,EAAE1E,UAAU;IAChB2E,IAAI,EAAEjE;EACV,CAAC,CAAC,EACF,CAACV,UAAU,EAAEU,UAAU,CAC3B,CAAC;EAED,IAAAnB,iBAAS,EAAC,MAAM;IACZ,MAAMqF,mBAAmB,GAAIzE,KAAmB,IAAK;MAAA,IAAA0E,sBAAA;MACjD,IACI,CAAC1I,uBAAuB,KAAA0I,sBAAA,GACxBvG,qBAAqB,CAACmB,OAAO,cAAAoF,sBAAA,eAA7BA,sBAAA,CAA+BpE,QAAQ,CAACN,KAAK,CAACyD,MAAc,CAAC,EAC/D;QACE;MACJ;MAEA5D,UAAU,CAAC,CAAC;IAChB,CAAC;IAED,IAAIpC,cAAc,EAAE;MAChBsG,QAAQ,CAACK,gBAAgB,CAAC,OAAO,EAAEK,mBAAmB,EAAE,IAAI,CAAC;MAC7DE,MAAM,CAACP,gBAAgB,CAAC,MAAM,EAAEvE,UAAU,CAAC;MAE3C,IAAI,OAAO9D,MAAM,KAAK,UAAU,EAAE;QAC9BA,MAAM,CAAC,CAAC;MACZ;IACJ,CAAC,MAAM,IAAI,OAAOD,MAAM,KAAK,UAAU,EAAE;MACrCA,MAAM,CAAC,CAAC;IACZ;IAEA,OAAO,MAAM;MACTiI,QAAQ,CAACM,mBAAmB,CAAC,OAAO,EAAEI,mBAAmB,EAAE,IAAI,CAAC;MAChEE,MAAM,CAACN,mBAAmB,CAAC,MAAM,EAAExE,UAAU,CAAC;IAClD,CAAC;EACL,CAAC,EAAE,CAACA,UAAU,EAAEpC,cAAc,EAAE3B,MAAM,EAAEC,MAAM,EAAEC,uBAAuB,CAAC,CAAC;EAEzE,IAAAoD,iBAAS,EAAC,MAAM;IACZ,IAAI,CAAChC,YAAY,EAAE;MACf;IACJ;IAEAQ,SAAS,CAAC,mBACN,IAAAgH,sBAAY,eACR1L,OAAA,CAAAe,OAAA,CAAAsB,aAAA,CAACtC,MAAA,CAAA4L,eAAe;MAACC,OAAO,EAAE;IAAM,GAC3BrH,cAAc,iBACXvE,OAAA,CAAAe,OAAA,CAAAsB,aAAA,CAAC9B,mBAAA,CAAAQ,OAAkB;MACf0B,WAAW,EAAEA,WAAW,IAAIgB,mBAAoB;MAChDd,KAAK,EAAEA,KAAM;MACbW,MAAM,EAAEA,MAAO;MACfZ,QAAQ,EAAEA,QAAS;MACnBM,oBAAoB,EAAEA,oBAAqB;MAC3CgH,GAAG,EAAE,eAAejF,IAAI,EAAG;MAC3B7C,SAAS,EAAEA,SAAS,IAAI4B,iBAAkB;MAC1CN,GAAG,EAAEyB,qBAAsB;MAC3Bb,YAAY,EAAEA,YAAa;MAC3ByH,WAAW,EAAExH,eAAgB;MAC7ByH,YAAY,EAAEA,CAAA,KAAM;QAChBlH,YAAY,CAAC,IAAI,CAAC;QAClBP,eAAe,CAAC,CAAC,CAAC,CAAC;MACvB,CAAE;MACF0H,YAAY,EAAEA,CAAA,KAAM;QAChBnH,YAAY,CAAC,KAAK,CAAC;MACvB;IAAE,CACL,CAEQ,CAAC,EAClBV,YACJ,CACJ,CAAC;EACL,CAAC,EAAE,CACChC,SAAS,EACTgC,YAAY,EACZzB,WAAW,EACXqB,iBAAiB,EACjBL,mBAAmB,EACnBc,cAAc,EACd5B,KAAK,EACLoC,IAAI,EACJzB,MAAM,EACNN,oBAAoB,EACpBN,QAAQ,EACR0B,YAAY,EACZuC,UAAU,CACb,CAAC;EAEF,IAAAT,iBAAS,EAAC,MAAM;IACZ,IAAI,CAACf,cAAc,CAACiB,OAAO,EAAE;MACzB;IACJ;IAEA,MAAM4F,sBAAsB,GACxB,qKAAqK;IAEzK,MAAMC,iBAAiB,GAAGC,OAAO,CAC7B/G,cAAc,CAACiB,OAAO,CAAC+F,aAAa,CAACH,sBAAsB,CAC/D,CAAC;IAEDlH,4BAA4B,CAAC,CAACmH,iBAAiB,CAAC;EACpD,CAAC,EAAE,CAAC7J,QAAQ,CAAC,CAAC;EAEd,oBACIpC,OAAA,CAAAe,OAAA,CAAAsB,aAAA,CAAArC,OAAA,CAAAe,OAAA,CAAAqL,QAAA,qBACIpM,OAAA,CAAAe,OAAA,CAAAsB,aAAA,CAAC7B,YAAA,CAAA6L,iBAAiB;IACdlK,SAAS,EACLA,SAAS,GACH,4BAA4BA,SAAS,EAAE,GACvC,0BACT;IACDmK,SAAS,EAAE/H,cAAc,IAAItB,qBAAsB;IACnDsJ,qBAAqB,EAAE,CAAChH,OAAO,IAAItC,qBAAsB;IACzDuJ,sCAAsC,EAAE7G,qCAAsC;IAC9E8G,8BAA8B,EAAEtJ,6BAA8B;IAC9DqF,OAAO,EAAEmB,WAAY;IACrB+C,oBAAoB,EAAEhC,iBAAkB;IACxCiC,aAAa,EAAEjC,iBAAkB;IACjCkC,SAAS,EAAE9C,aAAc;IACzB+C,MAAM,EAAEhG,mBAAoB;IAC5BrD,GAAG,EAAE2B,cAAe;IACpB2H,QAAQ,EAAElH,iCAAiC,GAAG,CAAC,GAAGyC,SAAU;IAC5D0E,IAAI,EAAEnH,iCAAiC,GAAG,QAAQ,GAAGyC,SAAU;IAC/D,iBAAezC,iCAAiC,GAAG,MAAM,GAAGyC,SAAU;IACtE,iBAAezC,iCAAiC,GAAGrB,cAAc,GAAG8D,SAAU;IAC9EjF,KAAK,EAAEA;EAAM,GAEZhB,QACc,CAAC,EACnBqC,MACH,CAAC;AAEX,CACJ,CAAC;AAEDzC,WAAW,CAACgL,WAAW,GAAG,aAAa;AAAC,IAAAC,QAAA,GAAAC,OAAA,CAAAnM,OAAA,GAEzBiB,WAAW","ignoreList":[]}
|
|
1
|
+
{"version":3,"file":"ContextMenu.js","names":["_chaynsApi","require","_react","_react2","_interopRequireWildcard","_reactDom","_uuid","_environment","_Icon","_interopRequireDefault","_ContextMenuContent","_ContextMenu","_ContextMenu2","_ContextMenu3","_useKeyboardFocusHighlighting","_useFocusRingPortal","e","__esModule","default","t","WeakMap","r","n","o","i","f","__proto__","has","get","set","hasOwnProperty","call","Object","defineProperty","getOwnPropertyDescriptor","ContextMenu","forwardRef","alignment","className","children","createElement","icons","size","container","coordinates","headline","items","onHide","onShow","shouldCloseOnPopupClick","shouldDisableClick","shouldHidePopupArrow","shouldShowHoverEffect","shouldEnableKeyboardHighlighting","shouldUseDefaultTriggerStyles","style","yOffset","zIndex","dialogText","ref","internalCoordinates","setInternalCoordinates","useState","x","y","internalAlignment","setInternalAlignment","ContextMenuAlignment","TopLeft","newContainer","setNewContainer","focusedIndex","setFocusedIndex","getDefaultFocusedIndex","isContentShown","setIsContentShown","portal","setPortal","isHovered","setIsHovered","shouldUseFocusableWrapper","setShouldUseFocusableWrapper","uuid","useUuid","contextMenuContentRef","useRef","contextMenuRef","contextMenuFocusRingRef","shouldSkipNextContextMenuOpenRef","shouldPreventNextNativeContextMenuRef","isTouch","useIsTouch","shouldShowKeyboardHighlighting","useKeyboardFocusHighlighting","shouldShowWrapperKeyboardHighlighting","shouldUseKeyboardFocusableWrapper","useFocusRingPortal","isEnabled","overlayRef","shape","padding","useEffect","_contextMenuRef$curre","current","firstElementChild","HTMLElement","el","element","closest","Element","handleHide","useCallback","handleContainerBlur","event","_contextMenuContentRe","nextFocusedElement","relatedTarget","currentContainer","currentTarget","contains","handleShow","result","createDialog","type","DialogType","SELECT","text","buttons","list","map","isSelected","isDisabled","disabledReason","index","name","id","disabled","subtitle","undefined","icon","isValidElement","open","item","onClick","height","childrenHeight","left","childrenLeft","top","childrenTop","width","childrenWidth","getBoundingClientRect","zoomX","offsetWidth","zoomY","offsetHeight","scrollLeft","scrollTop","BottomRight","TopRight","BottomLeft","handleClick","preventDefault","stopPropagation","handleKeyDown","isActivationKey","key","prev","length","selectItem","getActiveItemIndex","contextMenuContentElement","onClose","target","isContextMenuShortcut","shiftKey","handleContextMenu","handleGlobalKeyDown","activeElement","document","body","documentElement","shouldOpenFromFocusedParent","handleNativeContextMenuCapture","addEventListener","removeEventListener","useImperativeHandle","hide","show","handleDocumentClick","_contextMenuContentRe2","isInsideMenu","window","createPortal","AnimatePresence","initial","onItemFocus","onMouseEnter","onMouseLeave","focusableChildSelector","hasFocusableChild","Boolean","querySelector","Fragment","StyledContextMenu","$isActive","$shouldAddHoverEffect","$shouldShowWrapperKeyboardHighlighting","$shouldUseDefaultTriggerStyles","onContextMenuCapture","onContextMenu","onKeyDown","onBlur","tabIndex","role","displayName","_default","exports"],"sources":["../../../../src/components/context-menu/ContextMenu.tsx"],"sourcesContent":["import { createDialog, DialogType } from 'chayns-api';\nimport { AnimatePresence } from 'motion/react';\nimport React, {\n forwardRef,\n isValidElement,\n KeyboardEventHandler,\n MouseEvent,\n MouseEventHandler,\n ReactPortal,\n useCallback,\n useEffect,\n useImperativeHandle,\n useRef,\n useState,\n} from 'react';\nimport { createPortal } from 'react-dom';\nimport { useUuid } from '../../hooks/uuid';\nimport { useIsTouch } from '../../utils/environment';\nimport Icon from '../icon/Icon';\nimport ContextMenuContent from './context-menu-content/ContextMenuContent';\nimport { StyledContextMenu } from './ContextMenu.styles';\nimport {\n ContextMenuAlignment,\n type ContextMenuCoordinates,\n type ContextMenuProps,\n type ContextMenuRef,\n} from './ContextMenu.types';\nimport { SelectDialogResult } from '../../types/general';\nimport { getActiveItemIndex, getDefaultFocusedIndex, selectItem } from './ContextMenu.utils';\nimport { useKeyboardFocusHighlighting } from '../../hooks/useKeyboardFocusHighlighting';\nimport { useFocusRingPortal } from '../../hooks/useFocusRingPortal';\n\nconst ContextMenu = forwardRef<ContextMenuRef, ContextMenuProps>(\n (\n {\n alignment,\n className,\n children = <Icon icons={['ts-ellipsis_v']} size={18} />,\n container,\n coordinates,\n headline,\n items,\n onHide,\n onShow,\n shouldCloseOnPopupClick = true,\n shouldDisableClick = false,\n shouldHidePopupArrow = false,\n shouldShowHoverEffect = false,\n shouldEnableKeyboardHighlighting,\n shouldUseDefaultTriggerStyles = true,\n style,\n yOffset = 0,\n zIndex = 20,\n dialogText,\n },\n ref,\n ) => {\n const [internalCoordinates, setInternalCoordinates] = useState<ContextMenuCoordinates>({\n x: 0,\n y: 0,\n });\n\n const [internalAlignment, setInternalAlignment] = useState<ContextMenuAlignment>(\n ContextMenuAlignment.TopLeft,\n );\n\n const [newContainer, setNewContainer] = useState(container ?? null);\n const [focusedIndex, setFocusedIndex] = useState(getDefaultFocusedIndex(items));\n const [isContentShown, setIsContentShown] = useState(false);\n const [portal, setPortal] = useState<ReactPortal>();\n const [isHovered, setIsHovered] = useState(false);\n const [shouldUseFocusableWrapper, setShouldUseFocusableWrapper] = useState(false);\n\n const uuid = useUuid();\n\n const contextMenuContentRef = useRef<HTMLDivElement>(null);\n const contextMenuRef = useRef<HTMLSpanElement>(null);\n const contextMenuFocusRingRef = useRef<HTMLElement | null>(null);\n const shouldSkipNextContextMenuOpenRef = useRef(false);\n const shouldPreventNextNativeContextMenuRef = useRef(false);\n\n const isTouch = useIsTouch();\n const shouldShowKeyboardHighlighting = useKeyboardFocusHighlighting(\n shouldEnableKeyboardHighlighting && !shouldDisableClick,\n );\n const shouldShowWrapperKeyboardHighlighting =\n shouldShowKeyboardHighlighting && shouldUseFocusableWrapper;\n const shouldUseKeyboardFocusableWrapper = shouldUseFocusableWrapper && !shouldDisableClick;\n useFocusRingPortal(contextMenuRef, {\n isEnabled: shouldShowWrapperKeyboardHighlighting,\n overlayRef: contextMenuFocusRingRef,\n shape: shouldUseDefaultTriggerStyles ? 'circle' : 'rectangle',\n padding: shouldUseDefaultTriggerStyles ? 4 : 0,\n });\n\n useEffect(() => {\n contextMenuFocusRingRef.current =\n contextMenuRef.current?.firstElementChild instanceof HTMLElement\n ? contextMenuRef.current.firstElementChild\n : contextMenuRef.current;\n }, [children]);\n\n useEffect(() => {\n if (isContentShown) {\n setFocusedIndex(getDefaultFocusedIndex(items));\n }\n }, [isContentShown, items]);\n\n useEffect(() => {\n if (contextMenuRef.current && !container) {\n const el = contextMenuRef.current as HTMLElement;\n\n const element = el.closest('.dialog-inner, .page-provider, .tapp, body');\n\n setNewContainer(element);\n }\n }, [container]);\n\n useEffect(() => {\n if (container instanceof Element) {\n setNewContainer(container);\n }\n }, [container]);\n\n const handleHide = useCallback(() => {\n setIsContentShown(false);\n }, []);\n\n const handleContainerBlur = useCallback(\n (event: React.FocusEvent<HTMLSpanElement>) => {\n const nextFocusedElement = event.relatedTarget as Node | null;\n const currentContainer = event.currentTarget as HTMLElement;\n\n if (\n !nextFocusedElement ||\n (!currentContainer.contains(nextFocusedElement) &&\n !contextMenuContentRef.current?.contains(nextFocusedElement))\n ) {\n handleHide();\n }\n },\n [handleHide],\n );\n\n const handleShow = useCallback(async () => {\n if (isTouch) {\n const { result } = (await createDialog({\n type: DialogType.SELECT,\n text: dialogText,\n buttons: [],\n list: items.map(\n ({ icons, text, isSelected, isDisabled, disabledReason }, index) => ({\n name: text,\n id: index,\n isSelected,\n disabled: isDisabled,\n subtitle: isDisabled ? disabledReason : undefined,\n icon: isValidElement(icons)\n ? undefined\n : (icons as string[] | undefined)?.[0],\n }),\n ),\n }).open()) as SelectDialogResult;\n\n if (result && typeof result[0] === 'number') {\n const item = items[result[0]];\n\n if (item && !item.isDisabled) {\n void item.onClick();\n }\n }\n } else if (contextMenuRef.current) {\n if (!newContainer) {\n return;\n }\n\n const {\n height: childrenHeight,\n left: childrenLeft,\n top: childrenTop,\n width: childrenWidth,\n } = contextMenuRef.current.getBoundingClientRect();\n\n const { height, width, top, left } = newContainer.getBoundingClientRect();\n\n const zoomX = width / (newContainer as HTMLElement).offsetWidth;\n const zoomY = height / (newContainer as HTMLElement).offsetHeight;\n\n const x =\n (childrenLeft + childrenWidth / 2 - left) / zoomX + newContainer.scrollLeft;\n const y =\n (childrenTop + childrenHeight / 2 - top) / zoomY +\n newContainer.scrollTop -\n yOffset;\n\n setInternalCoordinates({ x, y });\n\n if (x < width / 2) {\n if (y < height / 2) {\n setInternalAlignment(ContextMenuAlignment.BottomRight);\n } else {\n setInternalAlignment(ContextMenuAlignment.TopRight);\n }\n } else if (y < height / 2) {\n setInternalAlignment(ContextMenuAlignment.BottomLeft);\n } else {\n setInternalAlignment(ContextMenuAlignment.TopLeft);\n }\n\n setIsContentShown(true);\n }\n }, [isTouch, items, newContainer, yOffset, dialogText]);\n\n const handleClick = useCallback<MouseEventHandler<HTMLSpanElement>>(\n (event) => {\n if (shouldDisableClick) {\n return;\n }\n\n event.preventDefault();\n event.stopPropagation();\n\n void handleShow();\n },\n [handleShow, shouldDisableClick],\n );\n\n const handleKeyDown = useCallback<KeyboardEventHandler<HTMLSpanElement>>(\n (event) => {\n if (shouldDisableClick) {\n return;\n }\n\n const isActivationKey =\n event.key === 'Enter' || event.key === ' ' || event.key === 'Spacebar';\n\n if (isContentShown && event.key === 'Escape') {\n event.preventDefault();\n event.stopPropagation();\n handleHide();\n return;\n }\n\n if (isContentShown && !isHovered && event.key === 'ArrowDown') {\n event.preventDefault();\n event.stopPropagation();\n setFocusedIndex((prev) => (prev >= items.length - 1 ? 0 : prev + 1));\n return;\n }\n\n if (isContentShown && !isHovered && event.key === 'ArrowUp') {\n event.preventDefault();\n event.stopPropagation();\n setFocusedIndex((prev) => (prev <= 0 ? items.length - 1 : prev - 1));\n return;\n }\n\n if (isContentShown && isActivationKey) {\n if (\n selectItem({\n index: getActiveItemIndex({\n contextMenuContentElement: contextMenuContentRef.current,\n focusedIndex,\n }),\n items,\n onClose: handleHide,\n shouldCloseOnPopupClick,\n })\n ) {\n event.preventDefault();\n event.stopPropagation();\n }\n\n return;\n }\n\n if (event.currentTarget !== event.target) {\n return;\n }\n\n const isContextMenuShortcut =\n event.key === 'ContextMenu' || (event.key === 'F10' && event.shiftKey);\n\n if (isContextMenuShortcut) {\n event.preventDefault();\n event.stopPropagation();\n shouldSkipNextContextMenuOpenRef.current = true;\n void handleShow();\n return;\n }\n\n if (shouldUseFocusableWrapper && isActivationKey) {\n event.preventDefault();\n event.stopPropagation();\n void handleShow();\n }\n },\n [\n focusedIndex,\n handleHide,\n handleShow,\n isHovered,\n isContentShown,\n items,\n shouldCloseOnPopupClick,\n shouldDisableClick,\n shouldUseFocusableWrapper,\n ],\n );\n\n const handleContextMenu = useCallback(\n (event: MouseEvent<HTMLSpanElement>) => {\n event.preventDefault();\n event.stopPropagation();\n\n if (shouldDisableClick) {\n return;\n }\n\n if (shouldSkipNextContextMenuOpenRef.current) {\n shouldSkipNextContextMenuOpenRef.current = false;\n return;\n }\n\n void handleShow();\n },\n [handleShow, shouldDisableClick],\n );\n\n useEffect(() => {\n const handleGlobalKeyDown = (event: KeyboardEvent) => {\n if (shouldDisableClick || !contextMenuRef.current) {\n return;\n }\n\n const isContextMenuShortcut =\n event.key === 'ContextMenu' || (event.key === 'F10' && event.shiftKey);\n\n if (!isContextMenuShortcut) {\n return;\n }\n\n const { activeElement } = document;\n\n if (\n !(activeElement instanceof HTMLElement) ||\n activeElement === document.body ||\n activeElement === document.documentElement\n ) {\n return;\n }\n\n const shouldOpenFromFocusedParent =\n activeElement.contains(contextMenuRef.current) &&\n !contextMenuRef.current.contains(activeElement);\n\n if (!shouldOpenFromFocusedParent) {\n return;\n }\n\n event.preventDefault();\n event.stopPropagation();\n shouldPreventNextNativeContextMenuRef.current = true;\n void handleShow();\n };\n\n const handleNativeContextMenuCapture = (event: Event) => {\n if (!shouldPreventNextNativeContextMenuRef.current) {\n return;\n }\n\n shouldPreventNextNativeContextMenuRef.current = false;\n event.preventDefault();\n event.stopPropagation();\n };\n\n document.addEventListener('keydown', handleGlobalKeyDown, true);\n document.addEventListener('contextmenu', handleNativeContextMenuCapture, true);\n\n return () => {\n document.removeEventListener('keydown', handleGlobalKeyDown, true);\n document.removeEventListener('contextmenu', handleNativeContextMenuCapture, true);\n };\n }, [handleShow, shouldDisableClick]);\n\n useImperativeHandle(\n ref,\n () => ({\n hide: handleHide,\n show: handleShow,\n }),\n [handleHide, handleShow],\n );\n\n useEffect(() => {\n const handleDocumentClick = (event: PointerEvent) => {\n const target = event.target as Element;\n const isInsideMenu = contextMenuContentRef.current?.contains(target);\n\n if (\n isInsideMenu &&\n (!shouldCloseOnPopupClick || target.closest('[aria-disabled=\"true\"]'))\n ) {\n return;\n }\n\n handleHide();\n };\n\n if (isContentShown) {\n document.addEventListener('click', handleDocumentClick, true);\n window.addEventListener('blur', handleHide);\n\n if (typeof onShow === 'function') {\n onShow();\n }\n } else if (typeof onHide === 'function') {\n onHide();\n }\n\n return () => {\n document.removeEventListener('click', handleDocumentClick, true);\n window.removeEventListener('blur', handleHide);\n };\n }, [handleHide, isContentShown, onHide, onShow, shouldCloseOnPopupClick]);\n\n useEffect(() => {\n if (!newContainer) {\n return;\n }\n\n setPortal(() =>\n createPortal(\n <AnimatePresence initial={false}>\n {isContentShown && (\n <ContextMenuContent\n coordinates={coordinates ?? internalCoordinates}\n items={items}\n zIndex={zIndex}\n headline={headline}\n shouldHidePopupArrow={shouldHidePopupArrow}\n key={`contextMenu_${uuid}`}\n alignment={alignment ?? internalAlignment}\n ref={contextMenuContentRef}\n focusedIndex={focusedIndex}\n onItemFocus={setFocusedIndex}\n onMouseEnter={() => {\n setIsHovered(true);\n setFocusedIndex(-1);\n }}\n onMouseLeave={() => {\n setIsHovered(false);\n }}\n />\n )}\n </AnimatePresence>,\n newContainer,\n ),\n );\n }, [\n alignment,\n newContainer,\n coordinates,\n internalAlignment,\n internalCoordinates,\n isContentShown,\n items,\n uuid,\n zIndex,\n shouldHidePopupArrow,\n headline,\n focusedIndex,\n handleHide,\n ]);\n\n useEffect(() => {\n if (!contextMenuRef.current) {\n return;\n }\n\n const focusableChildSelector =\n 'button:not([disabled]), a[href], input:not([disabled]), select:not([disabled]), textarea:not([disabled]), [tabindex]:not([tabindex=\"-1\"]), [contenteditable=\"true\"]';\n\n const hasFocusableChild = Boolean(\n contextMenuRef.current.querySelector(focusableChildSelector),\n );\n\n setShouldUseFocusableWrapper(!hasFocusableChild);\n }, [children]);\n\n return (\n <>\n <StyledContextMenu\n className={\n className\n ? `beta-chayns-context-menu ${className}`\n : 'beta-chayns-context-menu'\n }\n $isActive={isContentShown && shouldShowHoverEffect}\n $shouldAddHoverEffect={!isTouch && shouldShowHoverEffect}\n $shouldShowWrapperKeyboardHighlighting={shouldShowWrapperKeyboardHighlighting}\n $shouldUseDefaultTriggerStyles={shouldUseDefaultTriggerStyles}\n onClick={handleClick}\n onContextMenuCapture={handleContextMenu}\n onContextMenu={handleContextMenu}\n onKeyDown={handleKeyDown}\n onBlur={handleContainerBlur}\n ref={contextMenuRef}\n tabIndex={shouldUseKeyboardFocusableWrapper ? 0 : undefined}\n role={shouldUseKeyboardFocusableWrapper ? 'button' : undefined}\n aria-haspopup={shouldUseKeyboardFocusableWrapper ? 'menu' : undefined}\n aria-expanded={shouldUseKeyboardFocusableWrapper ? isContentShown : undefined}\n style={style}\n >\n {children}\n </StyledContextMenu>\n {portal}\n </>\n );\n },\n);\n\nContextMenu.displayName = 'ContextMenu';\n\nexport default ContextMenu;\n"],"mappings":"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","ignoreList":[]}
|
|
@@ -0,0 +1,234 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
require("@testing-library/jest-dom/vitest");
|
|
4
|
+
var _react = require("@testing-library/react");
|
|
5
|
+
var _chaynsApi = require("chayns-api");
|
|
6
|
+
var _react2 = _interopRequireDefault(require("react"));
|
|
7
|
+
var _vitest2 = require("vitest");
|
|
8
|
+
var _ContextMenu = _interopRequireDefault(require("./ContextMenu"));
|
|
9
|
+
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
|
|
10
|
+
const environment = _vitest2.vi.hoisted(() => ({
|
|
11
|
+
isTouch: false
|
|
12
|
+
}));
|
|
13
|
+
_vitest2.vi.mock('../../utils/environment', () => ({
|
|
14
|
+
useIsTouch: () => environment.isTouch
|
|
15
|
+
}));
|
|
16
|
+
_vitest2.vi.mock('chayns-api', async importOriginal => ({
|
|
17
|
+
...(await importOriginal()),
|
|
18
|
+
createDialog: _vitest2.vi.fn(),
|
|
19
|
+
useSite: () => ({
|
|
20
|
+
colorMode: 0
|
|
21
|
+
})
|
|
22
|
+
}));
|
|
23
|
+
const renderMenu = items => {
|
|
24
|
+
(0, _react.render)(/*#__PURE__*/_react2.default.createElement(_ContextMenu.default, {
|
|
25
|
+
items: items,
|
|
26
|
+
coordinates: {
|
|
27
|
+
x: 0,
|
|
28
|
+
y: 0
|
|
29
|
+
}
|
|
30
|
+
}, /*#__PURE__*/_react2.default.createElement("button", {
|
|
31
|
+
type: "button"
|
|
32
|
+
}, "Options")));
|
|
33
|
+
_react.fireEvent.click(_react.screen.getByRole('button', {
|
|
34
|
+
name: 'Options'
|
|
35
|
+
}));
|
|
36
|
+
};
|
|
37
|
+
const createItems = () => [{
|
|
38
|
+
key: 'edit',
|
|
39
|
+
text: 'Edit',
|
|
40
|
+
onClick: _vitest2.vi.fn()
|
|
41
|
+
}, {
|
|
42
|
+
key: 'delete',
|
|
43
|
+
text: 'Delete',
|
|
44
|
+
isDisabled: true,
|
|
45
|
+
disabledReason: 'You do not have permission to delete this entry.',
|
|
46
|
+
onClick: _vitest2.vi.fn()
|
|
47
|
+
}];
|
|
48
|
+
(0, _vitest2.beforeEach)(() => {
|
|
49
|
+
environment.isTouch = false;
|
|
50
|
+
_vitest2.vi.clearAllMocks();
|
|
51
|
+
});
|
|
52
|
+
(0, _vitest2.describe)('ContextMenu disabled items', () => {
|
|
53
|
+
(0, _vitest2.it)('keeps disabled items visible and leaves the menu open when clicked', async () => {
|
|
54
|
+
var _items$, _items$2;
|
|
55
|
+
const items = createItems();
|
|
56
|
+
renderMenu(items);
|
|
57
|
+
const disabledItem = await _react.screen.findByRole('menuitem', {
|
|
58
|
+
name: 'Delete'
|
|
59
|
+
});
|
|
60
|
+
(0, _vitest2.expect)(disabledItem).toHaveAttribute('aria-disabled', 'true');
|
|
61
|
+
(0, _vitest2.expect)(disabledItem).toHaveAccessibleDescription((_items$ = items[1]) === null || _items$ === void 0 ? void 0 : _items$.disabledReason);
|
|
62
|
+
(0, _vitest2.expect)(disabledItem).toHaveStyle({
|
|
63
|
+
opacity: '0.5',
|
|
64
|
+
cursor: 'default'
|
|
65
|
+
});
|
|
66
|
+
_react.fireEvent.click(disabledItem);
|
|
67
|
+
(0, _vitest2.expect)((_items$2 = items[1]) === null || _items$2 === void 0 ? void 0 : _items$2.onClick).not.toHaveBeenCalled();
|
|
68
|
+
(0, _vitest2.expect)(disabledItem).toBeInTheDocument();
|
|
69
|
+
await (0, _react.waitFor)(() => {
|
|
70
|
+
var _items$3;
|
|
71
|
+
(0, _vitest2.expect)(document.querySelector('[data-ispopup="true"]')).toHaveTextContent(((_items$3 = items[1]) === null || _items$3 === void 0 ? void 0 : _items$3.disabledReason) ?? '');
|
|
72
|
+
});
|
|
73
|
+
});
|
|
74
|
+
(0, _vitest2.it)('shows the disabled reason on hover', async () => {
|
|
75
|
+
renderMenu(createItems());
|
|
76
|
+
const disabledItem = await _react.screen.findByRole('menuitem', {
|
|
77
|
+
name: 'Delete'
|
|
78
|
+
});
|
|
79
|
+
_react.fireEvent.mouseEnter(disabledItem);
|
|
80
|
+
await (0, _react.waitFor)(() => {
|
|
81
|
+
(0, _vitest2.expect)(document.querySelector('[data-ispopup="true"]')).toHaveTextContent('You do not have permission to delete this entry.');
|
|
82
|
+
});
|
|
83
|
+
});
|
|
84
|
+
_vitest2.it.each(['Enter', ' '])('does not activate a disabled item using %s', async key => {
|
|
85
|
+
var _items$4;
|
|
86
|
+
const items = createItems();
|
|
87
|
+
renderMenu(items);
|
|
88
|
+
const disabledItem = await _react.screen.findByRole('menuitem', {
|
|
89
|
+
name: 'Delete'
|
|
90
|
+
});
|
|
91
|
+
disabledItem.focus();
|
|
92
|
+
_react.fireEvent.keyDown(disabledItem, {
|
|
93
|
+
key
|
|
94
|
+
});
|
|
95
|
+
(0, _vitest2.expect)((_items$4 = items[1]) === null || _items$4 === void 0 ? void 0 : _items$4.onClick).not.toHaveBeenCalled();
|
|
96
|
+
(0, _vitest2.expect)(disabledItem).toBeInTheDocument();
|
|
97
|
+
});
|
|
98
|
+
(0, _vitest2.it)('prevents activating disabled items reached using arrow keys', async () => {
|
|
99
|
+
var _items$5, _items$6;
|
|
100
|
+
const items = createItems();
|
|
101
|
+
renderMenu(items);
|
|
102
|
+
await _react.screen.findByRole('menuitem', {
|
|
103
|
+
name: 'Delete'
|
|
104
|
+
});
|
|
105
|
+
const trigger = _react.screen.getByRole('button', {
|
|
106
|
+
name: 'Options'
|
|
107
|
+
});
|
|
108
|
+
_react.fireEvent.keyDown(trigger, {
|
|
109
|
+
key: 'ArrowDown'
|
|
110
|
+
});
|
|
111
|
+
_react.fireEvent.keyDown(trigger, {
|
|
112
|
+
key: 'ArrowDown'
|
|
113
|
+
});
|
|
114
|
+
_react.fireEvent.keyDown(trigger, {
|
|
115
|
+
key: 'Enter'
|
|
116
|
+
});
|
|
117
|
+
(0, _vitest2.expect)((_items$5 = items[1]) === null || _items$5 === void 0 ? void 0 : _items$5.onClick).not.toHaveBeenCalled();
|
|
118
|
+
(0, _vitest2.expect)(_react.screen.getByRole('menuitem', {
|
|
119
|
+
name: 'Delete'
|
|
120
|
+
})).toBeInTheDocument();
|
|
121
|
+
_react.fireEvent.keyDown(trigger, {
|
|
122
|
+
key: 'ArrowDown'
|
|
123
|
+
});
|
|
124
|
+
_react.fireEvent.keyDown(trigger, {
|
|
125
|
+
key: 'Enter'
|
|
126
|
+
});
|
|
127
|
+
(0, _vitest2.expect)((_items$6 = items[0]) === null || _items$6 === void 0 ? void 0 : _items$6.onClick).toHaveBeenCalledOnce();
|
|
128
|
+
});
|
|
129
|
+
(0, _vitest2.it)('does not initially select a disabled item marked as selected', async () => {
|
|
130
|
+
var _items$7;
|
|
131
|
+
const items = createItems().map(item => ({
|
|
132
|
+
...item,
|
|
133
|
+
isSelected: item.isDisabled
|
|
134
|
+
}));
|
|
135
|
+
renderMenu(items);
|
|
136
|
+
await _react.screen.findByRole('menuitem', {
|
|
137
|
+
name: 'Delete'
|
|
138
|
+
});
|
|
139
|
+
_react.fireEvent.keyDown(_react.screen.getByRole('button', {
|
|
140
|
+
name: 'Options'
|
|
141
|
+
}), {
|
|
142
|
+
key: 'Enter'
|
|
143
|
+
});
|
|
144
|
+
(0, _vitest2.expect)((_items$7 = items[1]) === null || _items$7 === void 0 ? void 0 : _items$7.onClick).not.toHaveBeenCalled();
|
|
145
|
+
(0, _vitest2.expect)(_react.screen.getByRole('menuitem', {
|
|
146
|
+
name: 'Delete'
|
|
147
|
+
})).toBeInTheDocument();
|
|
148
|
+
});
|
|
149
|
+
(0, _vitest2.it)('still activates enabled items and closes the menu', async () => {
|
|
150
|
+
var _items$8;
|
|
151
|
+
const items = createItems();
|
|
152
|
+
renderMenu(items);
|
|
153
|
+
_react.fireEvent.click(await _react.screen.findByRole('menuitem', {
|
|
154
|
+
name: 'Edit'
|
|
155
|
+
}));
|
|
156
|
+
(0, _vitest2.expect)((_items$8 = items[0]) === null || _items$8 === void 0 ? void 0 : _items$8.onClick).toHaveBeenCalledOnce();
|
|
157
|
+
await (0, _react.waitFor)(() => (0, _vitest2.expect)(_react.screen.queryByRole('menuitem')).not.toBeInTheDocument());
|
|
158
|
+
});
|
|
159
|
+
(0, _vitest2.it)('supports disabled items without a reason', async () => {
|
|
160
|
+
const onClick = _vitest2.vi.fn();
|
|
161
|
+
renderMenu([{
|
|
162
|
+
key: 'delete',
|
|
163
|
+
text: 'Delete',
|
|
164
|
+
isDisabled: true,
|
|
165
|
+
onClick
|
|
166
|
+
}]);
|
|
167
|
+
_react.fireEvent.click(await _react.screen.findByRole('menuitem', {
|
|
168
|
+
name: 'Delete'
|
|
169
|
+
}));
|
|
170
|
+
(0, _vitest2.expect)(onClick).not.toHaveBeenCalled();
|
|
171
|
+
(0, _vitest2.expect)(document.querySelector('[data-ispopup="true"]')).not.toBeInTheDocument();
|
|
172
|
+
});
|
|
173
|
+
(0, _vitest2.it)('passes disabled items and their reasons to the native select dialog on touch devices', async () => {
|
|
174
|
+
var _items$9, _items$0, _items$1;
|
|
175
|
+
environment.isTouch = true;
|
|
176
|
+
const items = createItems();
|
|
177
|
+
const open = _vitest2.vi.fn().mockResolvedValue({
|
|
178
|
+
result: []
|
|
179
|
+
});
|
|
180
|
+
_vitest2.vi.mocked(_chaynsApi.createDialog).mockReturnValue({
|
|
181
|
+
open
|
|
182
|
+
});
|
|
183
|
+
renderMenu(items);
|
|
184
|
+
await (0, _react.waitFor)(() => (0, _vitest2.expect)(open).toHaveBeenCalledOnce());
|
|
185
|
+
(0, _vitest2.expect)(_chaynsApi.createDialog).toHaveBeenCalledWith(_vitest2.expect.objectContaining({
|
|
186
|
+
list: [_vitest2.expect.objectContaining({
|
|
187
|
+
id: 0,
|
|
188
|
+
name: 'Edit',
|
|
189
|
+
disabled: undefined,
|
|
190
|
+
subtitle: undefined
|
|
191
|
+
}), _vitest2.expect.objectContaining({
|
|
192
|
+
id: 1,
|
|
193
|
+
name: 'Delete',
|
|
194
|
+
disabled: true,
|
|
195
|
+
subtitle: (_items$9 = items[1]) === null || _items$9 === void 0 ? void 0 : _items$9.disabledReason
|
|
196
|
+
})]
|
|
197
|
+
}));
|
|
198
|
+
(0, _vitest2.expect)(_react.screen.queryByRole('menuitem')).not.toBeInTheDocument();
|
|
199
|
+
(0, _vitest2.expect)((_items$0 = items[0]) === null || _items$0 === void 0 ? void 0 : _items$0.onClick).not.toHaveBeenCalled();
|
|
200
|
+
(0, _vitest2.expect)((_items$1 = items[1]) === null || _items$1 === void 0 ? void 0 : _items$1.onClick).not.toHaveBeenCalled();
|
|
201
|
+
});
|
|
202
|
+
(0, _vitest2.it)('does not activate a disabled item even if the native dialog returns it', async () => {
|
|
203
|
+
var _items$10;
|
|
204
|
+
environment.isTouch = true;
|
|
205
|
+
const items = createItems();
|
|
206
|
+
const open = _vitest2.vi.fn().mockResolvedValue({
|
|
207
|
+
result: [1]
|
|
208
|
+
});
|
|
209
|
+
_vitest2.vi.mocked(_chaynsApi.createDialog).mockReturnValue({
|
|
210
|
+
open
|
|
211
|
+
});
|
|
212
|
+
renderMenu(items);
|
|
213
|
+
await (0, _react.waitFor)(() => (0, _vitest2.expect)(open).toHaveBeenCalledOnce());
|
|
214
|
+
(0, _vitest2.expect)((_items$10 = items[1]) === null || _items$10 === void 0 ? void 0 : _items$10.onClick).not.toHaveBeenCalled();
|
|
215
|
+
});
|
|
216
|
+
(0, _vitest2.it)('keeps using the native select dialog on touch devices for enabled items', async () => {
|
|
217
|
+
environment.isTouch = true;
|
|
218
|
+
const onClick = _vitest2.vi.fn();
|
|
219
|
+
_vitest2.vi.mocked(_chaynsApi.createDialog).mockReturnValue({
|
|
220
|
+
open: _vitest2.vi.fn().mockResolvedValue({
|
|
221
|
+
result: [0]
|
|
222
|
+
})
|
|
223
|
+
});
|
|
224
|
+
renderMenu([{
|
|
225
|
+
key: 'edit',
|
|
226
|
+
text: 'Edit',
|
|
227
|
+
onClick
|
|
228
|
+
}]);
|
|
229
|
+
await (0, _react.waitFor)(() => (0, _vitest2.expect)(onClick).toHaveBeenCalledOnce());
|
|
230
|
+
(0, _vitest2.expect)(_chaynsApi.createDialog).toHaveBeenCalledOnce();
|
|
231
|
+
(0, _vitest2.expect)(_react.screen.queryByRole('menuitem')).not.toBeInTheDocument();
|
|
232
|
+
});
|
|
233
|
+
});
|
|
234
|
+
//# sourceMappingURL=ContextMenu.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ContextMenu.test.js","names":["require","_react","_chaynsApi","_react2","_interopRequireDefault","_vitest2","_ContextMenu","e","__esModule","default","environment","vi","hoisted","isTouch","mock","useIsTouch","importOriginal","createDialog","fn","useSite","colorMode","renderMenu","items","render","createElement","coordinates","x","y","type","fireEvent","click","screen","getByRole","name","createItems","key","text","onClick","isDisabled","disabledReason","beforeEach","clearAllMocks","describe","it","_items$","_items$2","disabledItem","findByRole","expect","toHaveAttribute","toHaveAccessibleDescription","toHaveStyle","opacity","cursor","not","toHaveBeenCalled","toBeInTheDocument","waitFor","_items$3","document","querySelector","toHaveTextContent","mouseEnter","each","_items$4","focus","keyDown","_items$5","_items$6","trigger","toHaveBeenCalledOnce","_items$7","map","item","isSelected","_items$8","queryByRole","_items$9","_items$0","_items$1","open","mockResolvedValue","result","mocked","mockReturnValue","toHaveBeenCalledWith","objectContaining","list","id","disabled","undefined","subtitle","_items$10"],"sources":["../../../../src/components/context-menu/ContextMenu.test.tsx"],"sourcesContent":["import '@testing-library/jest-dom/vitest';\nimport { fireEvent, render, screen, waitFor } from '@testing-library/react';\nimport { createDialog } from 'chayns-api';\nimport React from 'react';\nimport { beforeEach, describe, expect, it, vi } from 'vitest';\nimport ContextMenu from './ContextMenu';\nimport type { ContextMenuItem } from './ContextMenu.types';\n\nconst environment = vi.hoisted(() => ({ isTouch: false }));\n\nvi.mock('../../utils/environment', () => ({\n useIsTouch: () => environment.isTouch,\n}));\n\nvi.mock('chayns-api', async (importOriginal) => ({\n ...(await importOriginal<typeof import('chayns-api')>()),\n createDialog: vi.fn(),\n useSite: () => ({ colorMode: 0 }),\n}));\n\nconst renderMenu = (items: ContextMenuItem[]) => {\n render(\n <ContextMenu items={items} coordinates={{ x: 0, y: 0 }}>\n <button type=\"button\">Options</button>\n </ContextMenu>,\n );\n\n fireEvent.click(screen.getByRole('button', { name: 'Options' }));\n};\n\nconst createItems = (): ContextMenuItem[] => [\n { key: 'edit', text: 'Edit', onClick: vi.fn() },\n {\n key: 'delete',\n text: 'Delete',\n isDisabled: true,\n disabledReason: 'You do not have permission to delete this entry.',\n onClick: vi.fn(),\n },\n];\n\nbeforeEach(() => {\n environment.isTouch = false;\n vi.clearAllMocks();\n});\n\ndescribe('ContextMenu disabled items', () => {\n it('keeps disabled items visible and leaves the menu open when clicked', async () => {\n const items = createItems();\n renderMenu(items);\n\n const disabledItem = await screen.findByRole('menuitem', { name: 'Delete' });\n expect(disabledItem).toHaveAttribute('aria-disabled', 'true');\n expect(disabledItem).toHaveAccessibleDescription(items[1]?.disabledReason);\n expect(disabledItem).toHaveStyle({ opacity: '0.5', cursor: 'default' });\n\n fireEvent.click(disabledItem);\n\n expect(items[1]?.onClick).not.toHaveBeenCalled();\n expect(disabledItem).toBeInTheDocument();\n await waitFor(() => {\n expect(document.querySelector('[data-ispopup=\"true\"]')).toHaveTextContent(\n items[1]?.disabledReason ?? '',\n );\n });\n });\n\n it('shows the disabled reason on hover', async () => {\n renderMenu(createItems());\n const disabledItem = await screen.findByRole('menuitem', { name: 'Delete' });\n\n fireEvent.mouseEnter(disabledItem);\n\n await waitFor(() => {\n expect(document.querySelector('[data-ispopup=\"true\"]')).toHaveTextContent(\n 'You do not have permission to delete this entry.',\n );\n });\n });\n\n it.each(['Enter', ' '])('does not activate a disabled item using %s', async (key) => {\n const items = createItems();\n renderMenu(items);\n const disabledItem = await screen.findByRole('menuitem', { name: 'Delete' });\n\n disabledItem.focus();\n fireEvent.keyDown(disabledItem, { key });\n\n expect(items[1]?.onClick).not.toHaveBeenCalled();\n expect(disabledItem).toBeInTheDocument();\n });\n\n it('prevents activating disabled items reached using arrow keys', async () => {\n const items = createItems();\n renderMenu(items);\n await screen.findByRole('menuitem', { name: 'Delete' });\n const trigger = screen.getByRole('button', { name: 'Options' });\n\n fireEvent.keyDown(trigger, { key: 'ArrowDown' });\n fireEvent.keyDown(trigger, { key: 'ArrowDown' });\n fireEvent.keyDown(trigger, { key: 'Enter' });\n\n expect(items[1]?.onClick).not.toHaveBeenCalled();\n expect(screen.getByRole('menuitem', { name: 'Delete' })).toBeInTheDocument();\n\n fireEvent.keyDown(trigger, { key: 'ArrowDown' });\n fireEvent.keyDown(trigger, { key: 'Enter' });\n\n expect(items[0]?.onClick).toHaveBeenCalledOnce();\n });\n\n it('does not initially select a disabled item marked as selected', async () => {\n const items = createItems().map((item) => ({\n ...item,\n isSelected: item.isDisabled,\n }));\n renderMenu(items);\n await screen.findByRole('menuitem', { name: 'Delete' });\n\n fireEvent.keyDown(screen.getByRole('button', { name: 'Options' }), { key: 'Enter' });\n\n expect(items[1]?.onClick).not.toHaveBeenCalled();\n expect(screen.getByRole('menuitem', { name: 'Delete' })).toBeInTheDocument();\n });\n\n it('still activates enabled items and closes the menu', async () => {\n const items = createItems();\n renderMenu(items);\n\n fireEvent.click(await screen.findByRole('menuitem', { name: 'Edit' }));\n\n expect(items[0]?.onClick).toHaveBeenCalledOnce();\n await waitFor(() => expect(screen.queryByRole('menuitem')).not.toBeInTheDocument());\n });\n\n it('supports disabled items without a reason', async () => {\n const onClick = vi.fn();\n renderMenu([{ key: 'delete', text: 'Delete', isDisabled: true, onClick }]);\n\n fireEvent.click(await screen.findByRole('menuitem', { name: 'Delete' }));\n\n expect(onClick).not.toHaveBeenCalled();\n expect(document.querySelector('[data-ispopup=\"true\"]')).not.toBeInTheDocument();\n });\n\n it('passes disabled items and their reasons to the native select dialog on touch devices', async () => {\n environment.isTouch = true;\n const items = createItems();\n const open = vi.fn().mockResolvedValue({ result: [] });\n vi.mocked(createDialog).mockReturnValue({\n open,\n } as unknown as ReturnType<typeof createDialog>);\n\n renderMenu(items);\n\n await waitFor(() => expect(open).toHaveBeenCalledOnce());\n expect(createDialog).toHaveBeenCalledWith(\n expect.objectContaining({\n list: [\n expect.objectContaining({\n id: 0,\n name: 'Edit',\n disabled: undefined,\n subtitle: undefined,\n }),\n expect.objectContaining({\n id: 1,\n name: 'Delete',\n disabled: true,\n subtitle: items[1]?.disabledReason,\n }),\n ],\n }),\n );\n expect(screen.queryByRole('menuitem')).not.toBeInTheDocument();\n expect(items[0]?.onClick).not.toHaveBeenCalled();\n expect(items[1]?.onClick).not.toHaveBeenCalled();\n });\n\n it('does not activate a disabled item even if the native dialog returns it', async () => {\n environment.isTouch = true;\n const items = createItems();\n const open = vi.fn().mockResolvedValue({ result: [1] });\n vi.mocked(createDialog).mockReturnValue({\n open,\n } as unknown as ReturnType<typeof createDialog>);\n\n renderMenu(items);\n\n await waitFor(() => expect(open).toHaveBeenCalledOnce());\n expect(items[1]?.onClick).not.toHaveBeenCalled();\n });\n\n it('keeps using the native select dialog on touch devices for enabled items', async () => {\n environment.isTouch = true;\n const onClick = vi.fn();\n vi.mocked(createDialog).mockReturnValue({\n open: vi.fn().mockResolvedValue({ result: [0] }),\n } as unknown as ReturnType<typeof createDialog>);\n\n renderMenu([{ key: 'edit', text: 'Edit', onClick }]);\n\n await waitFor(() => expect(onClick).toHaveBeenCalledOnce());\n expect(createDialog).toHaveBeenCalledOnce();\n expect(screen.queryByRole('menuitem')).not.toBeInTheDocument();\n });\n});\n"],"mappings":"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","ignoreList":[]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ContextMenu.types.js","names":["ContextMenuAlignment","exports"],"sources":["../../../../src/components/context-menu/ContextMenu.types.ts"],"sourcesContent":["import type { CSSProperties, MouseEvent, ReactNode } from 'react';\n\n/**\n * Enum representing the possible alignments for the context menu.\n */\nexport enum ContextMenuAlignment {\n TopLeft,\n BottomLeft,\n TopRight,\n BottomRight,\n TopCenter,\n BottomCenter,\n}\n\n/**\n * Type representing the coordinates for positioning the context menu.\n */\nexport type ContextMenuCoordinates = {\n /** The x-coordinate. */\n x: number;\n /** The y-coordinate. */\n y: number;\n};\n\n/**\n * Type representing an item in the context menu.\n */\nexport type ContextMenuItem = {\n /** Optional icons for the item. Can be strings or React nodes. */\n icons?: string[] | ReactNode;\n /** Whether the item is selected. */\n isSelected?: boolean;\n /** Unique key for the item. */\n key: string;\n /** Function called when the item is clicked. */\n onClick: (event?: MouseEvent<HTMLDivElement>) => Promise<void> | void;\n /** Whether to show a spacer after the item. */\n shouldShowSpacer?: boolean;\n /** The text displayed for the item. */\n text: string;\n};\n\n/**\n * Props for the ContextMenu component.\n */\nexport type ContextMenuProps = {\n /**\n * Context menu alignment\n * @description Optional custom alignment used instead of calculating it using the alignment\n * within the page. The available alignments can be taken from the ContextMenuAlignment enum.\n * @example alignment={ContextMenuAlignment.TopLeft}\n * @optional\n */\n alignment?: ContextMenuAlignment;\n /**\n * Additional class name applied to the trigger wrapper.\n * @optional\n */\n className?: string;\n /**\n * Children element\n * @description The element over which the content of the ContextMenu should be displayed.\n * @example children={<Icon icons={['fa fa-paper-clip']} />\n * @default <Icon icons={['ts-ellipsis_v']} size={18} />\n * @optional\n */\n children?: ReactNode;\n /**\n * Container element\n * @description The element where the content of the ContextMenu should be rendered via React Portal.\n * @example container={document.body}\n * @optional\n */\n container?: Element;\n /**\n * Custom coordinates\n * @description Optional own coordinates to be used instead of calculating the alignment based\n * on the alignment of the children.\n * @example coordinates={{ x: 100, y: 200 }}\n * @optional\n */\n coordinates?: ContextMenuCoordinates;\n /**\n * Context menu headline\n * @description The headline of the context menu. If not provided, no headline will be displayed.\n * @example headline=\"Options\"\n * @optional\n */\n headline?: string;\n /**\n * Menu items\n * @description The items that will be displayed in the content of the ContextMenu. Custom icon\n * elements only will be displayed on desktop devices.\n * @example items={[{ key: '1', text: 'Option 1', onClick: () => {} }]}\n */\n items: ContextMenuItem[];\n /**\n * Hide callback function\n * @description Function to be executed when the content of the Context menu has been hidden.\n * @example onHide={() => console.log('Menu hidden')}\n * @optional\n */\n onHide?: VoidFunction;\n /**\n * Show callback function\n * @description Function to be executed when the content of the Context menu has been shown.\n * @example onShow={() => console.log('Menu shown')}\n * @optional\n */\n onShow?: VoidFunction;\n /**\n * Close on popup click flag\n * @description Whether the popup should be closed if it is clicked.\n * @default true\n * @optional\n */\n shouldCloseOnPopupClick?: boolean;\n /**\n * Disable click flag\n * @description Whether the click should be disabled.\n * @default false\n * @optional\n */\n shouldDisableClick?: boolean;\n /**\n * Hide popup arrow flag\n * @description Whether the arrow of the popup should be hidden.\n * @default false\n * @optional\n */\n shouldHidePopupArrow?: boolean;\n /**\n * Whether the default trigger padding/background styles should be applied.\n * @description Disable this when the trigger child already provides its own full visual styling.\n * @default true\n * @optional\n */\n shouldUseDefaultTriggerStyles?: boolean;\n /**\n * Show hover effect flag\n * @description Whether the hover effect should be shown.\n * @default false\n * @optional\n */\n shouldShowHoverEffect?: boolean;\n /**\n * Enables keyboard-only focus highlighting for the trigger.\n * @default false\n * @optional\n */\n shouldEnableKeyboardHighlighting?: boolean;\n /**\n * Inline styles applied to the trigger wrapper.\n * @optional\n */\n style?: CSSProperties;\n /**\n * Vertical offset between the trigger element and the context menu.\n * @description Use this prop to fine-tune the context menu position on the Y axis. Positive and\n * negative values can be used depending on the desired spacing.\n * @default 0\n * @example yOffset={8}\n * @optional\n */\n yOffset?: number;\n /**\n * Z-index value\n * @description The z-index of the popup.\n * @example zIndex={100}\n * @default 20\n * @optional\n */\n zIndex?: number;\n /**\n * Optional text for the select dialog.\n */\n dialogText?: string;\n};\n\n/**\n * Ref interface for the ContextMenu component.\n */\nexport interface ContextMenuRef {\n /** Hides the context menu. */\n hide: VoidFunction;\n /** Shows the context menu. */\n show: VoidFunction;\n}\n"],"mappings":";;;;;;AAEA;AACA;AACA;AAFA,IAGYA,oBAAoB,GAAAC,OAAA,CAAAD,oBAAA,0BAApBA,oBAAoB;EAApBA,oBAAoB,CAApBA,oBAAoB;EAApBA,oBAAoB,CAApBA,oBAAoB;EAApBA,oBAAoB,CAApBA,oBAAoB;EAApBA,oBAAoB,CAApBA,oBAAoB;EAApBA,oBAAoB,CAApBA,oBAAoB;EAApBA,oBAAoB,CAApBA,oBAAoB;EAAA,OAApBA,oBAAoB;AAAA;AAShC;AACA;AACA;AAQA;AACA;AACA;
|
|
1
|
+
{"version":3,"file":"ContextMenu.types.js","names":["ContextMenuAlignment","exports"],"sources":["../../../../src/components/context-menu/ContextMenu.types.ts"],"sourcesContent":["import type { CSSProperties, MouseEvent, ReactNode } from 'react';\n\n/**\n * Enum representing the possible alignments for the context menu.\n */\nexport enum ContextMenuAlignment {\n TopLeft,\n BottomLeft,\n TopRight,\n BottomRight,\n TopCenter,\n BottomCenter,\n}\n\n/**\n * Type representing the coordinates for positioning the context menu.\n */\nexport type ContextMenuCoordinates = {\n /** The x-coordinate. */\n x: number;\n /** The y-coordinate. */\n y: number;\n};\n\n/**\n * Type representing an item in the context menu.\n */\nexport type ContextMenuItem = {\n /** Optional icons for the item. Can be strings or React nodes. */\n icons?: string[] | ReactNode;\n /**\n * Whether the item is disabled. Disabled items cannot be activated.\n */\n isDisabled?: boolean;\n /**\n * Reason why the item is disabled. Only shown for disabled items.\n * Displayed as a tooltip on desktop and a subtitle in the native select dialog on touch devices.\n */\n disabledReason?: string;\n /** Whether the item is selected. */\n isSelected?: boolean;\n /** Unique key for the item. */\n key: string;\n /** Function called when the item is clicked. */\n onClick: (event?: MouseEvent<HTMLDivElement>) => Promise<void> | void;\n /** Whether to show a spacer after the item. */\n shouldShowSpacer?: boolean;\n /** The text displayed for the item. */\n text: string;\n};\n\n/**\n * Props for the ContextMenu component.\n */\nexport type ContextMenuProps = {\n /**\n * Context menu alignment\n * @description Optional custom alignment used instead of calculating it using the alignment\n * within the page. The available alignments can be taken from the ContextMenuAlignment enum.\n * @example alignment={ContextMenuAlignment.TopLeft}\n * @optional\n */\n alignment?: ContextMenuAlignment;\n /**\n * Additional class name applied to the trigger wrapper.\n * @optional\n */\n className?: string;\n /**\n * Children element\n * @description The element over which the content of the ContextMenu should be displayed.\n * @example children={<Icon icons={['fa fa-paper-clip']} />\n * @default <Icon icons={['ts-ellipsis_v']} size={18} />\n * @optional\n */\n children?: ReactNode;\n /**\n * Container element\n * @description The element where the content of the ContextMenu should be rendered via React Portal.\n * @example container={document.body}\n * @optional\n */\n container?: Element;\n /**\n * Custom coordinates\n * @description Optional own coordinates to be used instead of calculating the alignment based\n * on the alignment of the children.\n * @example coordinates={{ x: 100, y: 200 }}\n * @optional\n */\n coordinates?: ContextMenuCoordinates;\n /**\n * Context menu headline\n * @description The headline of the context menu. If not provided, no headline will be displayed.\n * @example headline=\"Options\"\n * @optional\n */\n headline?: string;\n /**\n * Menu items\n * @description The items that will be displayed in the content of the ContextMenu. Custom icon\n * elements only will be displayed on desktop devices.\n * @example items={[{ key: '1', text: 'Option 1', onClick: () => {} }]}\n */\n items: ContextMenuItem[];\n /**\n * Hide callback function\n * @description Function to be executed when the content of the Context menu has been hidden.\n * @example onHide={() => console.log('Menu hidden')}\n * @optional\n */\n onHide?: VoidFunction;\n /**\n * Show callback function\n * @description Function to be executed when the content of the Context menu has been shown.\n * @example onShow={() => console.log('Menu shown')}\n * @optional\n */\n onShow?: VoidFunction;\n /**\n * Close on popup click flag\n * @description Whether the popup should be closed if it is clicked.\n * @default true\n * @optional\n */\n shouldCloseOnPopupClick?: boolean;\n /**\n * Disable click flag\n * @description Whether the click should be disabled.\n * @default false\n * @optional\n */\n shouldDisableClick?: boolean;\n /**\n * Hide popup arrow flag\n * @description Whether the arrow of the popup should be hidden.\n * @default false\n * @optional\n */\n shouldHidePopupArrow?: boolean;\n /**\n * Whether the default trigger padding/background styles should be applied.\n * @description Disable this when the trigger child already provides its own full visual styling.\n * @default true\n * @optional\n */\n shouldUseDefaultTriggerStyles?: boolean;\n /**\n * Show hover effect flag\n * @description Whether the hover effect should be shown.\n * @default false\n * @optional\n */\n shouldShowHoverEffect?: boolean;\n /**\n * Enables keyboard-only focus highlighting for the trigger.\n * @default false\n * @optional\n */\n shouldEnableKeyboardHighlighting?: boolean;\n /**\n * Inline styles applied to the trigger wrapper.\n * @optional\n */\n style?: CSSProperties;\n /**\n * Vertical offset between the trigger element and the context menu.\n * @description Use this prop to fine-tune the context menu position on the Y axis. Positive and\n * negative values can be used depending on the desired spacing.\n * @default 0\n * @example yOffset={8}\n * @optional\n */\n yOffset?: number;\n /**\n * Z-index value\n * @description The z-index of the popup.\n * @example zIndex={100}\n * @default 20\n * @optional\n */\n zIndex?: number;\n /**\n * Optional text for the select dialog.\n */\n dialogText?: string;\n};\n\n/**\n * Ref interface for the ContextMenu component.\n */\nexport interface ContextMenuRef {\n /** Hides the context menu. */\n hide: VoidFunction;\n /** Shows the context menu. */\n show: VoidFunction;\n}\n"],"mappings":";;;;;;AAEA;AACA;AACA;AAFA,IAGYA,oBAAoB,GAAAC,OAAA,CAAAD,oBAAA,0BAApBA,oBAAoB;EAApBA,oBAAoB,CAApBA,oBAAoB;EAApBA,oBAAoB,CAApBA,oBAAoB;EAApBA,oBAAoB,CAApBA,oBAAoB;EAApBA,oBAAoB,CAApBA,oBAAoB;EAApBA,oBAAoB,CAApBA,oBAAoB;EAApBA,oBAAoB,CAApBA,oBAAoB;EAAA,OAApBA,oBAAoB;AAAA;AAShC;AACA;AACA;AAQA;AACA;AACA;AAyBA;AACA;AACA;AAuIA;AACA;AACA","ignoreList":[]}
|
|
@@ -4,7 +4,7 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
4
4
|
value: true
|
|
5
5
|
});
|
|
6
6
|
exports.selectItem = exports.getDefaultFocusedIndex = exports.getActiveItemIndex = void 0;
|
|
7
|
-
const getDefaultFocusedIndex = items => items.findIndex(item => item.isSelected);
|
|
7
|
+
const getDefaultFocusedIndex = items => items.findIndex(item => item.isSelected && !item.isDisabled);
|
|
8
8
|
exports.getDefaultFocusedIndex = getDefaultFocusedIndex;
|
|
9
9
|
const getActiveItemIndex = ({
|
|
10
10
|
contextMenuContentElement,
|
|
@@ -25,6 +25,9 @@ const selectItem = ({
|
|
|
25
25
|
if (!item) {
|
|
26
26
|
return false;
|
|
27
27
|
}
|
|
28
|
+
if (item.isDisabled) {
|
|
29
|
+
return true;
|
|
30
|
+
}
|
|
28
31
|
void item.onClick();
|
|
29
32
|
if (shouldCloseOnPopupClick) {
|
|
30
33
|
onClose();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ContextMenu.utils.js","names":["getDefaultFocusedIndex","items","findIndex","item","isSelected","exports","getActiveItemIndex","contextMenuContentElement","focusedIndex","activeElement","document","activeItemElement","contains","closest","undefined","Number","dataset","index","selectItem","onClose","shouldCloseOnPopupClick","onClick"],"sources":["../../../../src/components/context-menu/ContextMenu.utils.ts"],"sourcesContent":["import type { ContextMenuItem } from './ContextMenu.types';\n\nexport const getDefaultFocusedIndex = (items: ContextMenuItem[]): number =>\n items.findIndex((item) => item.isSelected);\n\nexport const getActiveItemIndex = ({\n contextMenuContentElement,\n focusedIndex,\n}: {\n contextMenuContentElement: HTMLDivElement | null;\n focusedIndex: number;\n}) => {\n const activeElement = document.activeElement as HTMLElement | null;\n const activeItemElement = contextMenuContentElement?.contains(activeElement)\n ? activeElement?.closest<HTMLElement>('[data-index]')\n : undefined;\n\n return activeItemElement ? Number(activeItemElement.dataset.index) : focusedIndex;\n};\n\nexport const selectItem = ({\n index,\n items,\n onClose,\n shouldCloseOnPopupClick,\n}: {\n index: number;\n items: ContextMenuItem[];\n onClose: VoidFunction;\n shouldCloseOnPopupClick: boolean;\n}) => {\n const item = items[index];\n\n if (!item) {\n return false;\n }\n\n void item.onClick();\n\n if (shouldCloseOnPopupClick) {\n onClose();\n }\n\n return true;\n};\n"],"mappings":";;;;;;AAEO,MAAMA,sBAAsB,GAAIC,KAAwB,IAC3DA,KAAK,CAACC,SAAS,CAAEC,IAAI,IAAKA,IAAI,CAACC,UAAU,CAAC;AAACC,OAAA,
|
|
1
|
+
{"version":3,"file":"ContextMenu.utils.js","names":["getDefaultFocusedIndex","items","findIndex","item","isSelected","isDisabled","exports","getActiveItemIndex","contextMenuContentElement","focusedIndex","activeElement","document","activeItemElement","contains","closest","undefined","Number","dataset","index","selectItem","onClose","shouldCloseOnPopupClick","onClick"],"sources":["../../../../src/components/context-menu/ContextMenu.utils.ts"],"sourcesContent":["import type { ContextMenuItem } from './ContextMenu.types';\n\nexport const getDefaultFocusedIndex = (items: ContextMenuItem[]): number =>\n items.findIndex((item) => item.isSelected && !item.isDisabled);\n\nexport const getActiveItemIndex = ({\n contextMenuContentElement,\n focusedIndex,\n}: {\n contextMenuContentElement: HTMLDivElement | null;\n focusedIndex: number;\n}) => {\n const activeElement = document.activeElement as HTMLElement | null;\n const activeItemElement = contextMenuContentElement?.contains(activeElement)\n ? activeElement?.closest<HTMLElement>('[data-index]')\n : undefined;\n\n return activeItemElement ? Number(activeItemElement.dataset.index) : focusedIndex;\n};\n\nexport const selectItem = ({\n index,\n items,\n onClose,\n shouldCloseOnPopupClick,\n}: {\n index: number;\n items: ContextMenuItem[];\n onClose: VoidFunction;\n shouldCloseOnPopupClick: boolean;\n}) => {\n const item = items[index];\n\n if (!item) {\n return false;\n }\n\n if (item.isDisabled) {\n return true;\n }\n\n void item.onClick();\n\n if (shouldCloseOnPopupClick) {\n onClose();\n }\n\n return true;\n};\n"],"mappings":";;;;;;AAEO,MAAMA,sBAAsB,GAAIC,KAAwB,IAC3DA,KAAK,CAACC,SAAS,CAAEC,IAAI,IAAKA,IAAI,CAACC,UAAU,IAAI,CAACD,IAAI,CAACE,UAAU,CAAC;AAACC,OAAA,CAAAN,sBAAA,GAAAA,sBAAA;AAE5D,MAAMO,kBAAkB,GAAGA,CAAC;EAC/BC,yBAAyB;EACzBC;AAIJ,CAAC,KAAK;EACF,MAAMC,aAAa,GAAGC,QAAQ,CAACD,aAAmC;EAClE,MAAME,iBAAiB,GAAGJ,yBAAyB,aAAzBA,yBAAyB,eAAzBA,yBAAyB,CAAEK,QAAQ,CAACH,aAAa,CAAC,GACtEA,aAAa,aAAbA,aAAa,uBAAbA,aAAa,CAAEI,OAAO,CAAc,cAAc,CAAC,GACnDC,SAAS;EAEf,OAAOH,iBAAiB,GAAGI,MAAM,CAACJ,iBAAiB,CAACK,OAAO,CAACC,KAAK,CAAC,GAAGT,YAAY;AACrF,CAAC;AAACH,OAAA,CAAAC,kBAAA,GAAAA,kBAAA;AAEK,MAAMY,UAAU,GAAGA,CAAC;EACvBD,KAAK;EACLjB,KAAK;EACLmB,OAAO;EACPC;AAMJ,CAAC,KAAK;EACF,MAAMlB,IAAI,GAAGF,KAAK,CAACiB,KAAK,CAAC;EAEzB,IAAI,CAACf,IAAI,EAAE;IACP,OAAO,KAAK;EAChB;EAEA,IAAIA,IAAI,CAACE,UAAU,EAAE;IACjB,OAAO,IAAI;EACf;EAEA,KAAKF,IAAI,CAACmB,OAAO,CAAC,CAAC;EAEnB,IAAID,uBAAuB,EAAE;IACzBD,OAAO,CAAC,CAAC;EACb;EAEA,OAAO,IAAI;AACf,CAAC;AAACd,OAAA,CAAAa,UAAA,GAAAA,UAAA","ignoreList":[]}
|