@deephaven/components 0.46.1-beta.0 → 0.46.1-beta.4
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/dist/AutoCompleteInput.js +40 -34
- package/dist/AutoCompleteInput.js.map +1 -1
- package/dist/AutoResizeTextarea.js +2 -1
- package/dist/AutoResizeTextarea.js.map +1 -1
- package/dist/BasicModal.js +48 -33
- package/dist/BasicModal.js.map +1 -1
- package/dist/Button.js +19 -8
- package/dist/Button.js.map +1 -1
- package/dist/ButtonGroup.js +5 -3
- package/dist/ButtonGroup.js.map +1 -1
- package/dist/ButtonOld.js +5 -3
- package/dist/ButtonOld.js.map +1 -1
- package/dist/CardFlip.js +14 -9
- package/dist/CardFlip.js.map +1 -1
- package/dist/Checkbox.js +23 -19
- package/dist/Checkbox.js.map +1 -1
- package/dist/Collapse.js +12 -9
- package/dist/Collapse.js.map +1 -1
- package/dist/ComboBox.js +61 -51
- package/dist/ComboBox.js.map +1 -1
- package/dist/CopyButton.js +5 -3
- package/dist/CopyButton.js.map +1 -1
- package/dist/CustomTimeSelect.js +92 -84
- package/dist/CustomTimeSelect.js.map +1 -1
- package/dist/DateInput.js +19 -17
- package/dist/DateInput.js.map +1 -1
- package/dist/DateTimeInput.js +20 -18
- package/dist/DateTimeInput.js.map +1 -1
- package/dist/DebouncedSearchInput.js +2 -1
- package/dist/DebouncedSearchInput.js.map +1 -1
- package/dist/DraggableItemList.js +97 -80
- package/dist/DraggableItemList.js.map +1 -1
- package/dist/EditableItemList.js +53 -46
- package/dist/EditableItemList.js.map +1 -1
- package/dist/HierarchicalCheckboxMenu.js +59 -49
- package/dist/HierarchicalCheckboxMenu.js.map +1 -1
- package/dist/ItemList.js +42 -37
- package/dist/ItemList.js.map +1 -1
- package/dist/ItemListItem.js +5 -3
- package/dist/ItemListItem.js.map +1 -1
- package/dist/LoadingOverlay.js +28 -20
- package/dist/LoadingOverlay.js.map +1 -1
- package/dist/LoadingSpinner.js +13 -10
- package/dist/LoadingSpinner.js.map +1 -1
- package/dist/MaskedInput.js +2 -1
- package/dist/MaskedInput.js.map +1 -1
- package/dist/Option.js +5 -3
- package/dist/Option.js.map +1 -1
- package/dist/RadioGroup.js +14 -10
- package/dist/RadioGroup.js.map +1 -1
- package/dist/RadioItem.js +23 -19
- package/dist/RadioItem.js.map +1 -1
- package/dist/RandomAreaPlotAnimation.js +8 -6
- package/dist/RandomAreaPlotAnimation.js.map +1 -1
- package/dist/SearchInput.js +26 -21
- package/dist/SearchInput.js.map +1 -1
- package/dist/Select.js +5 -3
- package/dist/Select.js.map +1 -1
- package/dist/SelectValueList.js +29 -24
- package/dist/SelectValueList.js.map +1 -1
- package/dist/SocketedButton.js +13 -10
- package/dist/SocketedButton.js.map +1 -1
- package/dist/TimeInput.js +2 -1
- package/dist/TimeInput.js.map +1 -1
- package/dist/TimeSlider.js +123 -106
- package/dist/TimeSlider.js.map +1 -1
- package/dist/ToastNotification.js +35 -27
- package/dist/ToastNotification.js.map +1 -1
- package/dist/UISwitch.js +7 -5
- package/dist/UISwitch.js.map +1 -1
- package/dist/ValidateLabelInput.js +33 -24
- package/dist/ValidateLabelInput.js.map +1 -1
- package/dist/context-actions/ContextActions.js +7 -5
- package/dist/context-actions/ContextActions.js.map +1 -1
- package/dist/context-actions/ContextMenu.js +44 -41
- package/dist/context-actions/ContextMenu.js.map +1 -1
- package/dist/context-actions/ContextMenuItem.js +34 -24
- package/dist/context-actions/ContextMenuItem.js.map +1 -1
- package/dist/context-actions/ContextMenuRoot.js +6 -4
- package/dist/context-actions/ContextMenuRoot.js.map +1 -1
- package/dist/context-actions/GlobalContextActions.js +3 -3
- package/dist/context-actions/GlobalContextActions.js.map +1 -1
- package/dist/menu-actions/DropdownMenu.js +19 -16
- package/dist/menu-actions/DropdownMenu.js.map +1 -1
- package/dist/menu-actions/Menu.js +8 -9
- package/dist/menu-actions/Menu.js.map +1 -1
- package/dist/modal/DebouncedModal.js +14 -9
- package/dist/modal/DebouncedModal.js.map +1 -1
- package/dist/modal/InfoModal.js +22 -13
- package/dist/modal/InfoModal.js.map +1 -1
- package/dist/modal/Modal.js +70 -60
- package/dist/modal/Modal.js.map +1 -1
- package/dist/modal/ModalBody.js +5 -3
- package/dist/modal/ModalBody.js.map +1 -1
- package/dist/modal/ModalFooter.js +5 -3
- package/dist/modal/ModalFooter.js.map +1 -1
- package/dist/modal/ModalHeader.js +19 -13
- package/dist/modal/ModalHeader.js.map +1 -1
- package/dist/navigation/Menu.js +15 -12
- package/dist/navigation/Menu.js.map +1 -1
- package/dist/navigation/MenuItem.js +29 -22
- package/dist/navigation/MenuItem.js.map +1 -1
- package/dist/navigation/Page.js +35 -26
- package/dist/navigation/Page.js.map +1 -1
- package/dist/navigation/Stack.js +33 -20
- package/dist/navigation/Stack.js.map +1 -1
- package/dist/popper/Popper.js +31 -25
- package/dist/popper/Popper.js.map +1 -1
- package/dist/popper/Tooltip.js +18 -13
- package/dist/popper/Tooltip.js.map +1 -1
- package/package.json +7 -7
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ValidateLabelInput.js","names":["React","useRef","classNames","shortid","ValidateLabelInput","props","children","className","labelText","hintText","isModified","validationError","showValidationError","dataTestId","id","idProp","current","modified","Children","toArray","map","child","isValidElement","cloneElement","undefined"],"sources":["../src/ValidateLabelInput.tsx"],"sourcesContent":["import React, { useRef } from 'react';\nimport classNames from 'classnames';\nimport shortid from 'shortid';\nimport './ValidateLabelInput.scss';\n\nexport type ValidateLabelInputProps = {\n /** Element to add label to */\n children: React.ReactNode;\n\n /** Any classnames to add */\n className?: string | string[];\n\n /** Text for this validation label */\n labelText?: string;\n\n /** Small hint text next to the main label */\n hintText?: string;\n\n /** Show a modified state. Defaults to false. */\n isModified?: boolean;\n\n /** Validation error that has occurred */\n validationError?: string;\n\n /** Show the validation error if it exists. Default to true. */\n showValidationError?: boolean;\n\n /** ID to use. Auto-generates if not provided */\n id?: string;\n\n /** data-testid to apply to the label */\n 'data-testid'?: string;\n};\n\n/**\n * Takes a child and add a label and validaton error\n */\nexport function ValidateLabelInput(\n props: ValidateLabelInputProps\n): React.ReactElement {\n const {\n children,\n className,\n labelText,\n hintText,\n isModified,\n validationError,\n showValidationError = true,\n 'data-testid': dataTestId,\n id: idProp,\n } = props;\n\n const { current: id } = useRef(idProp ?? shortid());\n\n return (\n <>\n <label\n className={classNames('validate-label', className, {\n modified: isModified,\n })}\n htmlFor={id}\n data-testid={dataTestId}\n >\n {labelText}\n </label>\n {React.Children.toArray(children).map(child => {\n if (!React.isValidElement<React.HTMLAttributes<HTMLElement>>(child)) {\n // eslint-disable-next-line react/jsx-key\n return <div className={classNames(className)}>{child}</div>;\n }\n\n // toArray strips null children\n return React.cloneElement(child, {\n className: classNames(child.props.className, {\n 'is-invalid': validationError,\n }),\n });\n })}\n {hintText !== undefined && (\n <small className=\"form-text text-muted\">{hintText}</small>\n )}\n {validationError !== undefined && showValidationError && (\n <p className=\"validate-label-error text-danger\">{validationError}</p>\n )}\n </>\n );\n}\n\nexport default ValidateLabelInput;\n"],"mappings":"AAAA,OAAOA,KAAK,IAAIC,MAAM,QAAQ,OAAO;AACrC,OAAOC,UAAU,MAAM,YAAY;AACnC,OAAOC,OAAO,MAAM,SAAS;AAAC;AAgC9B;AACA;AACA;AACA,OAAO,SAASC,kBAAkB,CAChCC,KAA8B,EACV;EACpB,IAAM;IACJC,QAAQ;IACRC,SAAS;IACTC,SAAS;IACTC,QAAQ;IACRC,UAAU;IACVC,eAAe;IACfC,mBAAmB,GAAG,IAAI;IAC1B,aAAa,EAAEC,UAAU;IACzBC,EAAE,EAAEC;EACN,CAAC,GAAGV,KAAK;EAET,IAAM;IAAEW,OAAO,EAAEF;EAAG,CAAC,GAAGb,MAAM,CAACc,MAAM,aAANA,MAAM,cAANA,MAAM,GAAIZ,OAAO,EAAE,CAAC;EAEnD,oBACE,
|
|
1
|
+
{"version":3,"file":"ValidateLabelInput.js","names":["React","useRef","classNames","shortid","ValidateLabelInput","props","children","className","labelText","hintText","isModified","validationError","showValidationError","dataTestId","id","idProp","current","modified","Children","toArray","map","child","isValidElement","cloneElement","undefined"],"sources":["../src/ValidateLabelInput.tsx"],"sourcesContent":["import React, { useRef } from 'react';\nimport classNames from 'classnames';\nimport shortid from 'shortid';\nimport './ValidateLabelInput.scss';\n\nexport type ValidateLabelInputProps = {\n /** Element to add label to */\n children: React.ReactNode;\n\n /** Any classnames to add */\n className?: string | string[];\n\n /** Text for this validation label */\n labelText?: string;\n\n /** Small hint text next to the main label */\n hintText?: string;\n\n /** Show a modified state. Defaults to false. */\n isModified?: boolean;\n\n /** Validation error that has occurred */\n validationError?: string;\n\n /** Show the validation error if it exists. Default to true. */\n showValidationError?: boolean;\n\n /** ID to use. Auto-generates if not provided */\n id?: string;\n\n /** data-testid to apply to the label */\n 'data-testid'?: string;\n};\n\n/**\n * Takes a child and add a label and validaton error\n */\nexport function ValidateLabelInput(\n props: ValidateLabelInputProps\n): React.ReactElement {\n const {\n children,\n className,\n labelText,\n hintText,\n isModified,\n validationError,\n showValidationError = true,\n 'data-testid': dataTestId,\n id: idProp,\n } = props;\n\n const { current: id } = useRef(idProp ?? shortid());\n\n return (\n <>\n <label\n className={classNames('validate-label', className, {\n modified: isModified,\n })}\n htmlFor={id}\n data-testid={dataTestId}\n >\n {labelText}\n </label>\n {React.Children.toArray(children).map(child => {\n if (!React.isValidElement<React.HTMLAttributes<HTMLElement>>(child)) {\n // eslint-disable-next-line react/jsx-key\n return <div className={classNames(className)}>{child}</div>;\n }\n\n // toArray strips null children\n return React.cloneElement(child, {\n className: classNames(child.props.className, {\n 'is-invalid': validationError,\n }),\n });\n })}\n {hintText !== undefined && (\n <small className=\"form-text text-muted\">{hintText}</small>\n )}\n {validationError !== undefined && showValidationError && (\n <p className=\"validate-label-error text-danger\">{validationError}</p>\n )}\n </>\n );\n}\n\nexport default ValidateLabelInput;\n"],"mappings":"AAAA,OAAOA,KAAK,IAAIC,MAAM,QAAQ,OAAO;AACrC,OAAOC,UAAU,MAAM,YAAY;AACnC,OAAOC,OAAO,MAAM,SAAS;AAAC;AAAA;AAAA;AAAA;AAgC9B;AACA;AACA;AACA,OAAO,SAASC,kBAAkB,CAChCC,KAA8B,EACV;EACpB,IAAM;IACJC,QAAQ;IACRC,SAAS;IACTC,SAAS;IACTC,QAAQ;IACRC,UAAU;IACVC,eAAe;IACfC,mBAAmB,GAAG,IAAI;IAC1B,aAAa,EAAEC,UAAU;IACzBC,EAAE,EAAEC;EACN,CAAC,GAAGV,KAAK;EAET,IAAM;IAAEW,OAAO,EAAEF;EAAG,CAAC,GAAGb,MAAM,CAACc,MAAM,aAANA,MAAM,cAANA,MAAM,GAAIZ,OAAO,EAAE,CAAC;EAEnD,oBACE;IAAA,wBACE;MACE,SAAS,EAAED,UAAU,CAAC,gBAAgB,EAAEK,SAAS,EAAE;QACjDU,QAAQ,EAAEP;MACZ,CAAC,CAAE;MACH,OAAO,EAAEI,EAAG;MACZ,eAAaD,UAAW;MAAA,UAEvBL;IAAS,EACJ,EACPR,KAAK,CAACkB,QAAQ,CAACC,OAAO,CAACb,QAAQ,CAAC,CAACc,GAAG,CAACC,KAAK,IAAI;MAC7C,IAAI,eAACrB,KAAK,CAACsB,cAAc,CAAoCD,KAAK,CAAC,EAAE;QACnE;QACA,oBAAO;UAAK,SAAS,EAAEnB,UAAU,CAACK,SAAS,CAAE;UAAA,UAAEc;QAAK,EAAO;MAC7D;;MAEA;MACA,oBAAOrB,KAAK,CAACuB,YAAY,CAACF,KAAK,EAAE;QAC/Bd,SAAS,EAAEL,UAAU,CAACmB,KAAK,CAAChB,KAAK,CAACE,SAAS,EAAE;UAC3C,YAAY,EAAEI;QAChB,CAAC;MACH,CAAC,CAAC;IACJ,CAAC,CAAC,EACDF,QAAQ,KAAKe,SAAS,iBACrB;MAAO,SAAS,EAAC,sBAAsB;MAAA,UAAEf;IAAQ,EAClD,EACAE,eAAe,KAAKa,SAAS,IAAIZ,mBAAmB,iBACnD;MAAG,SAAS,EAAC,kCAAkC;MAAA,UAAED;IAAe,EACjE;EAAA,EACA;AAEP;AAEA,eAAeP,kBAAkB"}
|
|
@@ -9,6 +9,7 @@ import Log from '@deephaven/log';
|
|
|
9
9
|
import ContextActionUtils, { isPromise } from "./ContextActionUtils.js";
|
|
10
10
|
import GlobalContextActions from "./GlobalContextActions.js";
|
|
11
11
|
import "./ContextActions.css";
|
|
12
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
12
13
|
var log = Log.module('ContextActions');
|
|
13
14
|
/**
|
|
14
15
|
* ContextActions that you add onto any component.
|
|
@@ -161,13 +162,14 @@ class ContextActions extends Component {
|
|
|
161
162
|
var {
|
|
162
163
|
globalActions
|
|
163
164
|
} = this.state;
|
|
164
|
-
return /*#__PURE__*/
|
|
165
|
+
return /*#__PURE__*/_jsx("div", {
|
|
165
166
|
className: "context-actions-listener",
|
|
166
167
|
ref: this.container,
|
|
167
|
-
"data-testid": dataTestId
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
168
|
+
"data-testid": dataTestId,
|
|
169
|
+
children: /*#__PURE__*/_jsx(GlobalContextActions, {
|
|
170
|
+
actions: globalActions
|
|
171
|
+
})
|
|
172
|
+
});
|
|
171
173
|
}
|
|
172
174
|
}
|
|
173
175
|
_defineProperty(ContextActions, "groups", {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ContextActions.js","names":["React","Component","Log","ContextActionUtils","isPromise","GlobalContextActions","log","module","ContextActions","triggerMenu","element","clientX","clientY","actions","length","mouseEvent","MouseEvent","bubbles","cancelable","contextActions","dispatchEvent","constructor","props","handleContextMenu","bind","handleKeyDown","container","createRef","state","globalActions","keyboardActions","getDerivedStateFromProps","Array","isArray","filter","action","isGlobal","undefined","shortcut","componentDidMount","current","parentElement","addEventListener","componentWillUnmount","removeEventListener","e","ignoreClassNames","el","target","classList","ignoredClassName","find","className","contains","debug2","isContextActionEvent","concat","debug","i","keyboardAction","actionsDisabled","matchesEvent","stopPropagation","preventDefault","render","dataTestId","default","high","medium","low","global","edit"],"sources":["../../src/context-actions/ContextActions.tsx"],"sourcesContent":["/**\n * Just a simple utility class for displaying a popup menu.\n */\nimport React, { Component } from 'react';\nimport Log from '@deephaven/log';\nimport ContextActionUtils, {\n ResolvableContextAction,\n isPromise,\n} from './ContextActionUtils';\nimport type { ContextAction, ContextActionEvent } from './ContextActionUtils';\nimport GlobalContextActions from './GlobalContextActions';\nimport './ContextActions.scss';\n\nconst log = Log.module('ContextActions');\n\ninterface ContextActionsProps {\n actions: ResolvableContextAction | ResolvableContextAction[];\n ignoreClassNames?: string[];\n 'data-testid'?: string;\n}\n\ninterface ContextActionsState {\n globalActions: ContextAction[];\n keyboardActions: ContextAction[];\n}\n\n/**\n * ContextActions that you add onto any component.\n *\n * Usage:\n * let actions = [{\n * title: 'My Action', // Omit the title to hide it from the context menu\n * action: () => { alert('My Action Clicked!') }\n * actions: [] // Submenu of actions\n * icon: faPrint, // Limited to FontAwesome icons for now.\n * iconColor: '#ff0000, // Color to use for the icon\n * shortcut: Shortcut, // Defaults to null\n * isGlobal: false, // Global context action. Defaults to false.\n * group: ContextActions.groups.default, // What group to group the context action with\n * order: null, // Int where to order within group\n * disabled: true // disable action\n * menuElement: null // Custom menu element for displaying in context menu. When null, creates a default menu item based on title\n * }];\n *\n * <div>\n * Right click in this container\n * <ContextActions actions={actions}/>\n * </div>\n *\n * Right clicking the container will then build the context menu, bubbling up until an element with a ContextMenuRoot is on it.\n * You should generally have a ContextMenuRoot on the root node of your document.\n */\nclass ContextActions extends Component<\n ContextActionsProps,\n ContextActionsState\n> {\n /**\n * Group you can assign to context menu actions to group them together.\n * Lower group IDs appear at the top of the list.\n * Groups are separated by a separator item.\n * Items within groups are ordered by their order property, then by their title.\n */\n static groups = {\n default: undefined,\n high: 100,\n medium: 5000,\n low: 10000,\n global: 100000,\n\n edit: 100,\n };\n\n static triggerMenu(\n element: Element,\n clientX: number,\n clientY: number,\n actions: ResolvableContextAction[]\n ): void {\n if (actions.length === 0) {\n return;\n }\n\n const mouseEvent: Partial<ContextActionEvent> = new MouseEvent(\n 'contextmenu',\n {\n clientX,\n clientY,\n bubbles: true,\n cancelable: true,\n }\n );\n mouseEvent.contextActions = actions;\n\n element.dispatchEvent(mouseEvent as ContextActionEvent);\n }\n\n constructor(props: ContextActionsProps) {\n super(props);\n\n this.handleContextMenu = this.handleContextMenu.bind(this);\n this.handleKeyDown = this.handleKeyDown.bind(this);\n\n this.container = React.createRef();\n\n this.state = { globalActions: [], keyboardActions: [] };\n }\n\n static getDerivedStateFromProps(\n props: ContextActionsProps\n ): ContextActionsState {\n if (props.actions == null || !Array.isArray(props.actions)) {\n return { globalActions: [], keyboardActions: [] };\n }\n const globalActions = props.actions.filter(\n action =>\n !isPromise(action) && typeof action !== 'function' && action.isGlobal\n ) as ContextAction[];\n const keyboardActions = props.actions.filter(\n action =>\n !isPromise(action) &&\n typeof action !== 'function' &&\n (action.isGlobal === undefined || !action.isGlobal) &&\n action.shortcut != null\n ) as ContextAction[];\n\n return { globalActions, keyboardActions };\n }\n\n componentDidMount(): void {\n if (this.container.current?.parentElement) {\n this.container.current.parentElement.addEventListener(\n 'contextmenu',\n this.handleContextMenu\n );\n this.container.current.parentElement.addEventListener(\n 'keydown',\n this.handleKeyDown\n );\n }\n }\n\n componentWillUnmount(): void {\n if (this.container.current?.parentElement) {\n this.container.current.parentElement.removeEventListener(\n 'contextmenu',\n this.handleContextMenu\n );\n this.container.current.parentElement.removeEventListener(\n 'keydown',\n this.handleKeyDown\n );\n }\n }\n\n container: React.RefObject<HTMLDivElement>;\n\n handleContextMenu(e: MouseEvent): void {\n const { ignoreClassNames = [] } = this.props;\n if (ignoreClassNames.length > 0) {\n let el = e.target as Element | null;\n while (el != null) {\n const { classList } = el;\n const ignoredClassName = ignoreClassNames.find(className =>\n classList.contains(className)\n );\n if (ignoredClassName !== undefined) {\n log.debug2(\n `Contextmenu event ignored based on the target className \"${ignoredClassName}\"`\n );\n return;\n }\n el = el.parentElement;\n }\n }\n if (!ContextActionUtils.isContextActionEvent(e)) {\n (e as ContextActionEvent).contextActions = [];\n }\n\n if (!ContextActionUtils.isContextActionEvent(e)) {\n return;\n }\n\n const { actions } = this.props;\n if (actions != null) {\n let contextActions = actions;\n if (Array.isArray(contextActions)) {\n contextActions = contextActions.filter(\n action =>\n isPromise(action) ||\n typeof action === 'function' ||\n action.isGlobal === undefined ||\n !action.isGlobal\n );\n }\n\n e.contextActions = e.contextActions.concat(contextActions);\n }\n\n log.debug(\n 'Received context menu event! Menu items are now: ',\n e.contextActions\n );\n }\n\n handleKeyDown(e: KeyboardEvent): void {\n const { keyboardActions } = this.state;\n for (let i = 0; i < keyboardActions.length; i += 1) {\n const keyboardAction = keyboardActions[i];\n if (\n !ContextActionUtils.actionsDisabled &&\n keyboardAction.shortcut != null &&\n keyboardAction.shortcut.matchesEvent(e)\n ) {\n log.debug('Context hotkey matched!', e);\n\n keyboardAction.action?.(e);\n\n e.stopPropagation();\n e.preventDefault();\n\n log.debug2('Matched hotkey returned false, key event not consumed');\n }\n }\n }\n\n render(): JSX.Element {\n const { 'data-testid': dataTestId } = this.props;\n const { globalActions } = this.state;\n return (\n <div\n className=\"context-actions-listener\"\n ref={this.container}\n data-testid={dataTestId}\n >\n <GlobalContextActions actions={globalActions} />\n </div>\n );\n }\n}\n\nexport default ContextActions;\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"ContextActions.js","names":["React","Component","Log","ContextActionUtils","isPromise","GlobalContextActions","log","module","ContextActions","triggerMenu","element","clientX","clientY","actions","length","mouseEvent","MouseEvent","bubbles","cancelable","contextActions","dispatchEvent","constructor","props","handleContextMenu","bind","handleKeyDown","container","createRef","state","globalActions","keyboardActions","getDerivedStateFromProps","Array","isArray","filter","action","isGlobal","undefined","shortcut","componentDidMount","current","parentElement","addEventListener","componentWillUnmount","removeEventListener","e","ignoreClassNames","el","target","classList","ignoredClassName","find","className","contains","debug2","isContextActionEvent","concat","debug","i","keyboardAction","actionsDisabled","matchesEvent","stopPropagation","preventDefault","render","dataTestId","default","high","medium","low","global","edit"],"sources":["../../src/context-actions/ContextActions.tsx"],"sourcesContent":["/**\n * Just a simple utility class for displaying a popup menu.\n */\nimport React, { Component } from 'react';\nimport Log from '@deephaven/log';\nimport ContextActionUtils, {\n ResolvableContextAction,\n isPromise,\n} from './ContextActionUtils';\nimport type { ContextAction, ContextActionEvent } from './ContextActionUtils';\nimport GlobalContextActions from './GlobalContextActions';\nimport './ContextActions.scss';\n\nconst log = Log.module('ContextActions');\n\ninterface ContextActionsProps {\n actions: ResolvableContextAction | ResolvableContextAction[];\n ignoreClassNames?: string[];\n 'data-testid'?: string;\n}\n\ninterface ContextActionsState {\n globalActions: ContextAction[];\n keyboardActions: ContextAction[];\n}\n\n/**\n * ContextActions that you add onto any component.\n *\n * Usage:\n * let actions = [{\n * title: 'My Action', // Omit the title to hide it from the context menu\n * action: () => { alert('My Action Clicked!') }\n * actions: [] // Submenu of actions\n * icon: faPrint, // Limited to FontAwesome icons for now.\n * iconColor: '#ff0000, // Color to use for the icon\n * shortcut: Shortcut, // Defaults to null\n * isGlobal: false, // Global context action. Defaults to false.\n * group: ContextActions.groups.default, // What group to group the context action with\n * order: null, // Int where to order within group\n * disabled: true // disable action\n * menuElement: null // Custom menu element for displaying in context menu. When null, creates a default menu item based on title\n * }];\n *\n * <div>\n * Right click in this container\n * <ContextActions actions={actions}/>\n * </div>\n *\n * Right clicking the container will then build the context menu, bubbling up until an element with a ContextMenuRoot is on it.\n * You should generally have a ContextMenuRoot on the root node of your document.\n */\nclass ContextActions extends Component<\n ContextActionsProps,\n ContextActionsState\n> {\n /**\n * Group you can assign to context menu actions to group them together.\n * Lower group IDs appear at the top of the list.\n * Groups are separated by a separator item.\n * Items within groups are ordered by their order property, then by their title.\n */\n static groups = {\n default: undefined,\n high: 100,\n medium: 5000,\n low: 10000,\n global: 100000,\n\n edit: 100,\n };\n\n static triggerMenu(\n element: Element,\n clientX: number,\n clientY: number,\n actions: ResolvableContextAction[]\n ): void {\n if (actions.length === 0) {\n return;\n }\n\n const mouseEvent: Partial<ContextActionEvent> = new MouseEvent(\n 'contextmenu',\n {\n clientX,\n clientY,\n bubbles: true,\n cancelable: true,\n }\n );\n mouseEvent.contextActions = actions;\n\n element.dispatchEvent(mouseEvent as ContextActionEvent);\n }\n\n constructor(props: ContextActionsProps) {\n super(props);\n\n this.handleContextMenu = this.handleContextMenu.bind(this);\n this.handleKeyDown = this.handleKeyDown.bind(this);\n\n this.container = React.createRef();\n\n this.state = { globalActions: [], keyboardActions: [] };\n }\n\n static getDerivedStateFromProps(\n props: ContextActionsProps\n ): ContextActionsState {\n if (props.actions == null || !Array.isArray(props.actions)) {\n return { globalActions: [], keyboardActions: [] };\n }\n const globalActions = props.actions.filter(\n action =>\n !isPromise(action) && typeof action !== 'function' && action.isGlobal\n ) as ContextAction[];\n const keyboardActions = props.actions.filter(\n action =>\n !isPromise(action) &&\n typeof action !== 'function' &&\n (action.isGlobal === undefined || !action.isGlobal) &&\n action.shortcut != null\n ) as ContextAction[];\n\n return { globalActions, keyboardActions };\n }\n\n componentDidMount(): void {\n if (this.container.current?.parentElement) {\n this.container.current.parentElement.addEventListener(\n 'contextmenu',\n this.handleContextMenu\n );\n this.container.current.parentElement.addEventListener(\n 'keydown',\n this.handleKeyDown\n );\n }\n }\n\n componentWillUnmount(): void {\n if (this.container.current?.parentElement) {\n this.container.current.parentElement.removeEventListener(\n 'contextmenu',\n this.handleContextMenu\n );\n this.container.current.parentElement.removeEventListener(\n 'keydown',\n this.handleKeyDown\n );\n }\n }\n\n container: React.RefObject<HTMLDivElement>;\n\n handleContextMenu(e: MouseEvent): void {\n const { ignoreClassNames = [] } = this.props;\n if (ignoreClassNames.length > 0) {\n let el = e.target as Element | null;\n while (el != null) {\n const { classList } = el;\n const ignoredClassName = ignoreClassNames.find(className =>\n classList.contains(className)\n );\n if (ignoredClassName !== undefined) {\n log.debug2(\n `Contextmenu event ignored based on the target className \"${ignoredClassName}\"`\n );\n return;\n }\n el = el.parentElement;\n }\n }\n if (!ContextActionUtils.isContextActionEvent(e)) {\n (e as ContextActionEvent).contextActions = [];\n }\n\n if (!ContextActionUtils.isContextActionEvent(e)) {\n return;\n }\n\n const { actions } = this.props;\n if (actions != null) {\n let contextActions = actions;\n if (Array.isArray(contextActions)) {\n contextActions = contextActions.filter(\n action =>\n isPromise(action) ||\n typeof action === 'function' ||\n action.isGlobal === undefined ||\n !action.isGlobal\n );\n }\n\n e.contextActions = e.contextActions.concat(contextActions);\n }\n\n log.debug(\n 'Received context menu event! Menu items are now: ',\n e.contextActions\n );\n }\n\n handleKeyDown(e: KeyboardEvent): void {\n const { keyboardActions } = this.state;\n for (let i = 0; i < keyboardActions.length; i += 1) {\n const keyboardAction = keyboardActions[i];\n if (\n !ContextActionUtils.actionsDisabled &&\n keyboardAction.shortcut != null &&\n keyboardAction.shortcut.matchesEvent(e)\n ) {\n log.debug('Context hotkey matched!', e);\n\n keyboardAction.action?.(e);\n\n e.stopPropagation();\n e.preventDefault();\n\n log.debug2('Matched hotkey returned false, key event not consumed');\n }\n }\n }\n\n render(): JSX.Element {\n const { 'data-testid': dataTestId } = this.props;\n const { globalActions } = this.state;\n return (\n <div\n className=\"context-actions-listener\"\n ref={this.container}\n data-testid={dataTestId}\n >\n <GlobalContextActions actions={globalActions} />\n </div>\n );\n }\n}\n\nexport default ContextActions;\n"],"mappings":"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"}
|
|
@@ -10,6 +10,9 @@ import { PromiseUtils } from '@deephaven/utils';
|
|
|
10
10
|
import ContextActionUtils from "./ContextActionUtils.js";
|
|
11
11
|
import ContextMenuItem from "./ContextMenuItem.js";
|
|
12
12
|
import LoadingSpinner from "../LoadingSpinner.js";
|
|
13
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
14
|
+
import { jsxs as _jsxs } from "react/jsx-runtime";
|
|
15
|
+
import { Fragment as _Fragment } from "react/jsx-runtime";
|
|
13
16
|
var log = Log.module('ContextMenu');
|
|
14
17
|
/** Do not use this class directly. Use ContextMenuRoot and ContextActions instead. */
|
|
15
18
|
class ContextMenu extends PureComponent {
|
|
@@ -475,12 +478,9 @@ class ContextMenu extends PureComponent {
|
|
|
475
478
|
for (var i = 0; i < menuItems.length; i += 1) {
|
|
476
479
|
var menuItem = menuItems[i];
|
|
477
480
|
if (i > 0 && menuItem.group !== menuItems[i - 1].group) {
|
|
478
|
-
menuItemElements.push( /*#__PURE__*/
|
|
479
|
-
key: "".concat(i, ".separator")
|
|
480
|
-
}));
|
|
481
|
+
menuItemElements.push( /*#__PURE__*/_jsx("hr", {}, "".concat(i, ".separator")));
|
|
481
482
|
}
|
|
482
|
-
var menuItemElement = /*#__PURE__*/
|
|
483
|
-
key: i,
|
|
483
|
+
var menuItemElement = /*#__PURE__*/_jsx(ContextMenuItem, {
|
|
484
484
|
ref: activeSubMenu === i ? this.activeSubMenuRef : null,
|
|
485
485
|
isKeyboardSelected: keyboardIndex === i,
|
|
486
486
|
isMouseSelected: mouseIndex === i,
|
|
@@ -489,14 +489,15 @@ class ContextMenu extends PureComponent {
|
|
|
489
489
|
onMenuItemClick: this.handleMenuItemClick,
|
|
490
490
|
onMenuItemMouseMove: this.handleMenuItemMouseMove,
|
|
491
491
|
onMenuItemContextMenu: this.handleMenuItemContextMenu
|
|
492
|
-
});
|
|
492
|
+
}, i);
|
|
493
493
|
menuItemElements.push(menuItemElement);
|
|
494
494
|
}
|
|
495
495
|
var pendingElement = null;
|
|
496
496
|
if (pendingItems.length > 0) {
|
|
497
|
-
pendingElement = /*#__PURE__*/
|
|
498
|
-
className: "loading"
|
|
499
|
-
|
|
497
|
+
pendingElement = /*#__PURE__*/_jsx("div", {
|
|
498
|
+
className: "loading",
|
|
499
|
+
children: /*#__PURE__*/_jsx(LoadingSpinner, {})
|
|
500
|
+
});
|
|
500
501
|
}
|
|
501
502
|
var {
|
|
502
503
|
menuStyle,
|
|
@@ -505,38 +506,40 @@ class ContextMenu extends PureComponent {
|
|
|
505
506
|
|
|
506
507
|
// don't show submenu until it has an position initialized
|
|
507
508
|
var showSubmenu = activeSubMenu !== null && subMenuTop !== null && subMenuLeft !== null;
|
|
508
|
-
return /*#__PURE__*/
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
509
|
+
return /*#__PURE__*/_jsxs(_Fragment, {
|
|
510
|
+
children: [/*#__PURE__*/_jsxs("div", {
|
|
511
|
+
className: classNames({
|
|
512
|
+
'has-overflow': hasOverflow
|
|
513
|
+
}, 'context-menu-container'),
|
|
514
|
+
style: _objectSpread({
|
|
515
|
+
top,
|
|
516
|
+
left
|
|
517
|
+
}, menuStyle),
|
|
518
|
+
ref: this.container,
|
|
519
|
+
"data-dh-context-menu": true,
|
|
520
|
+
onBlur: this.handleBlur,
|
|
521
|
+
onKeyDown: this.handleKeyDown,
|
|
522
|
+
onMouseLeave: this.handleMouseLeave,
|
|
523
|
+
onContextMenu: ContextMenu.handleContextMenu,
|
|
524
|
+
role: "menuitem",
|
|
525
|
+
tabIndex: 0,
|
|
526
|
+
"data-testid": dataTestId,
|
|
527
|
+
children: [menuItemElements, pendingElement]
|
|
528
|
+
}), showSubmenu && activeSubMenu !== null && subMenuTop !== null && subMenuLeft !== null && /*#__PURE__*/_jsx(ContextMenu, {
|
|
529
|
+
actions: menuItems[activeSubMenu].actions || [],
|
|
530
|
+
closeMenu: this.handleCloseSubMenu,
|
|
531
|
+
top: subMenuTop,
|
|
532
|
+
left: subMenuLeft,
|
|
533
|
+
updatePosition: (verifiedTop, verifiedLeft) => {
|
|
534
|
+
this.setState({
|
|
535
|
+
subMenuTop: verifiedTop,
|
|
536
|
+
subMenuLeft: verifiedLeft
|
|
537
|
+
});
|
|
538
|
+
},
|
|
539
|
+
subMenuParentWidth: subMenuParentWidth,
|
|
540
|
+
subMenuParentHeight: subMenuParentHeight
|
|
541
|
+
}, "sub-".concat(activeSubMenu))]
|
|
542
|
+
});
|
|
540
543
|
}
|
|
541
544
|
}
|
|
542
545
|
_defineProperty(ContextMenu, "defaultProps", {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ContextMenu.js","names":["React","PureComponent","classNames","Log","PromiseUtils","ContextActionUtils","ContextMenuItem","LoadingSpinner","log","module","ContextMenu","handleContextMenu","e","metaKey","stopPropagation","preventDefault","constructor","props","handleBlur","bind","handleCloseSubMenu","handleKeyDown","handleMenuItemClick","handleMenuItemContextMenu","handleMenuItemMouseMove","handleMouseLeave","handleWindowResize","container","createRef","oldFocus","document","activeElement","activeSubMenuRef","subMenuTimer","rAF","initialPosition","top","left","state","menuItems","pendingItems","activeSubMenu","hasOverflow","subMenuTop","subMenuLeft","subMenuParentWidth","subMenuParentHeight","keyboardIndex","mouseIndex","componentDidMount","initMenu","verifyPosition","window","addEventListener","requestAnimationFrame","current","focus","onMenuOpened","componentDidUpdate","prevProps","prevState","actions","setActiveSubMenuPosition","contains","componentWillUnmount","cancelPromises","removeEventListener","cancelAnimationFrame","getKeyboardIndex","options","separateKeyboardMouse","undefined","getMouseIndex","setKeyboardIndex","index","setState","setMouseIndex","initialKeyboardIndex","getMenuItems","nonPromiseItems","i","length","menuItem","Promise","initMenuPromise","push","sortActions","promise","cancellablePromise","makeCancelable","concat","then","resolvedMenuItems","indexOf","slice","splice","error","isCanceled","map","item","cancel","parentRect","getBoundingClientRect","right","height","width","updatePosition","oldTop","oldLeft","doNotVerifyPosition","scrollHeight","innerHeight","innerWidth","closeMenu","warn","relatedTarget","element","isContextMenuChild","hasAttribute","parentElement","isEscapeKey","key","newFocus","openSubMenu","shiftKey","getNextMenuItem","HTMLElement","newSubMenu","closeAll","onMenuClosed","closeSubMenu","closeAllMenus","disabled","action","focusIndex","render","menuItemElements","group","menuItemElement","pendingElement","menuStyle","dataTestId","showSubmenu","verifiedTop","verifiedLeft"],"sources":["../../src/context-actions/ContextMenu.tsx"],"sourcesContent":["import React, { PureComponent } from 'react';\nimport classNames from 'classnames';\nimport Log from '@deephaven/log';\nimport { PromiseUtils, CancelablePromise } from '@deephaven/utils';\nimport ContextActionUtils, {\n ContextAction,\n ResolvableContextAction,\n} from './ContextActionUtils';\nimport ContextMenuItem from './ContextMenuItem';\nimport LoadingSpinner from '../LoadingSpinner';\n\nconst log = Log.module('ContextMenu');\n\ninterface ContextMenuProps {\n top: number;\n left: number;\n updatePosition(top: number, left: number): void;\n // only submenus will have these, defaults to 0 otherwise\n // represents the width height of the parent menu item\n subMenuParentWidth: number;\n subMenuParentHeight: number;\n actions: ResolvableContextAction[];\n closeMenu(closeAll: boolean): void;\n onMenuClosed(menu: ContextMenu): void;\n onMenuOpened(menu: ContextMenu): void;\n options: {\n doNotVerifyPosition?: boolean;\n separateKeyboardMouse?: boolean;\n initialKeyboardIndex?: number;\n };\n menuStyle: React.CSSProperties;\n 'data-testid'?: string;\n}\n\ninterface ContextMenuState {\n menuItems: ContextAction[];\n pendingItems: CancelablePromise<ContextAction[]>[];\n activeSubMenu: number | null;\n hasOverflow: boolean;\n subMenuTop: number | null;\n subMenuLeft: number | null;\n subMenuParentWidth: number;\n subMenuParentHeight: number;\n keyboardIndex: number;\n mouseIndex: number;\n}\n\n/** Do not use this class directly. Use ContextMenuRoot and ContextActions instead. */\nclass ContextMenu extends PureComponent<ContextMenuProps, ContextMenuState> {\n static defaultProps = {\n subMenuParentWidth: 0,\n subMenuParentHeight: 0,\n closeMenu(): void {\n // no-op\n },\n onMenuOpened(): void {\n // no-op\n },\n onMenuClosed(): void {\n // no-op\n },\n options: {},\n menuStyle: {},\n 'data-testid': undefined,\n };\n\n static handleContextMenu(e: React.MouseEvent): void {\n if (e.metaKey) {\n return;\n }\n\n e.stopPropagation();\n e.preventDefault();\n }\n\n constructor(props: ContextMenuProps) {\n super(props);\n\n this.handleBlur = this.handleBlur.bind(this);\n this.handleCloseSubMenu = this.handleCloseSubMenu.bind(this);\n this.handleKeyDown = this.handleKeyDown.bind(this);\n this.handleMenuItemClick = this.handleMenuItemClick.bind(this);\n this.handleMenuItemContextMenu = this.handleMenuItemContextMenu.bind(this);\n this.handleMenuItemMouseMove = this.handleMenuItemMouseMove.bind(this);\n this.handleMouseLeave = this.handleMouseLeave.bind(this);\n this.handleWindowResize = this.handleWindowResize.bind(this);\n\n this.container = React.createRef();\n this.oldFocus = document.activeElement;\n this.activeSubMenuRef = React.createRef();\n this.subMenuTimer = 0;\n this.rAF = 0;\n\n this.initialPosition = { top: props.top, left: props.left };\n\n this.state = {\n menuItems: [],\n pendingItems: [],\n activeSubMenu: null,\n hasOverflow: false,\n subMenuTop: null,\n subMenuLeft: null,\n subMenuParentWidth: 0,\n subMenuParentHeight: 0,\n keyboardIndex: -1,\n mouseIndex: -1,\n };\n }\n\n componentDidMount(): void {\n this.initMenu();\n\n this.verifyPosition();\n\n window.addEventListener('resize', this.handleWindowResize);\n\n // rAF is needed to wait for a submenus popper to be created before\n // attempting to set focus, however on a quick mount/unmount when\n // mousing past an item, the submenu could be unmounted before the\n // async rAF finishes, so it is cancelled in willUnmount()\n this.rAF = window.requestAnimationFrame(() => {\n this.container.current?.focus();\n\n const { onMenuOpened } = this.props;\n onMenuOpened(this);\n });\n }\n\n componentDidUpdate(\n prevProps: ContextMenuProps,\n prevState: ContextMenuState\n ): void {\n const { actions } = this.props;\n const { activeSubMenu } = this.state;\n\n if (activeSubMenu !== prevState.activeSubMenu) {\n if (activeSubMenu == null) {\n // close sub menu, refocus parent menu\n this.container.current?.focus();\n } else {\n // open sub menu, set its initial position\n this.setActiveSubMenuPosition();\n }\n }\n\n if (prevProps.actions !== actions) {\n this.initMenu();\n\n if (\n this.container.current == null ||\n !this.container.current.contains(document.activeElement)\n ) {\n this.container.current?.focus();\n }\n }\n\n this.verifyPosition();\n }\n\n componentWillUnmount(): void {\n this.cancelPromises();\n window.removeEventListener('resize', this.handleWindowResize);\n cancelAnimationFrame(this.rAF);\n }\n\n container: React.RefObject<HTMLDivElement>;\n\n oldFocus: Element | null;\n\n activeSubMenuRef: React.RefObject<HTMLDivElement>;\n\n subMenuTimer: number;\n\n rAF: number;\n\n initialPosition: { top: number; left: number };\n\n getKeyboardIndex(): number {\n const { options } = this.props;\n if (\n options.separateKeyboardMouse !== undefined &&\n options.separateKeyboardMouse\n ) {\n const { keyboardIndex } = this.state;\n return keyboardIndex;\n }\n\n return this.getMouseIndex();\n }\n\n setKeyboardIndex(index: number): void {\n const { options } = this.props;\n if (\n options.separateKeyboardMouse !== undefined &&\n options.separateKeyboardMouse\n ) {\n this.setState({ keyboardIndex: index });\n } else {\n this.setMouseIndex(index);\n }\n }\n\n getMouseIndex(): number {\n const { mouseIndex } = this.state;\n return mouseIndex;\n }\n\n setMouseIndex(index: number): void {\n this.setState({ mouseIndex: index });\n }\n\n initMenu(): void {\n // cancel any pending close and promises\n this.cancelPromises();\n cancelAnimationFrame(this.rAF);\n\n const { options } = this.props;\n let keyboardIndex = options.initialKeyboardIndex;\n if (keyboardIndex === undefined) {\n keyboardIndex = -1;\n }\n\n const { actions } = this.props;\n const menuItems = ContextActionUtils.getMenuItems(actions);\n const nonPromiseItems: ContextAction[] = [];\n for (let i = menuItems.length - 1; i >= 0; i -= 1) {\n const menuItem = menuItems[i];\n if (menuItem instanceof Promise) {\n this.initMenuPromise(menuItem as Promise<ContextAction[]>);\n } else {\n nonPromiseItems.push(menuItem as ContextAction);\n }\n }\n\n this.setState({\n mouseIndex: -1,\n keyboardIndex,\n activeSubMenu: null,\n menuItems: ContextActionUtils.sortActions(nonPromiseItems),\n });\n }\n\n initMenuPromise(promise: Promise<ContextAction[]>): void {\n // make all promises cancellable\n const cancellablePromise = PromiseUtils.makeCancelable(promise);\n\n this.setState(state => ({\n pendingItems: state.pendingItems.concat(cancellablePromise),\n }));\n\n cancellablePromise.then(\n resolvedMenuItems => {\n this.setState(state => {\n const index = state.pendingItems.indexOf(cancellablePromise);\n if (index >= 0) {\n const pendingItems = state.pendingItems.slice();\n pendingItems.splice(index, 1);\n\n return {\n menuItems: ContextActionUtils.sortActions(\n state.menuItems.concat(resolvedMenuItems)\n ),\n pendingItems,\n };\n }\n // This item is stale, don't update the menu\n return null;\n });\n },\n error => {\n if (PromiseUtils.isCanceled(error)) {\n return; // Canceled promise is ignored\n }\n\n // remove failed item from pending list\n this.setState(state => {\n const index = state.pendingItems.indexOf(cancellablePromise);\n if (index >= 0) {\n const pendingItems = state.pendingItems.slice();\n pendingItems.splice(index, 1);\n return {\n pendingItems,\n };\n }\n return null;\n });\n\n // Log the error\n log.error(error);\n }\n );\n }\n\n cancelPromises(): void {\n const { pendingItems } = this.state;\n pendingItems.map(item => item.cancel());\n }\n\n /**\n * Sets the unverfied start position of a submenu. Submenu then self-verfies\n * its own position and potentially reports back a new position.\n */\n setActiveSubMenuPosition(): void {\n if (this.activeSubMenuRef.current === null) return;\n const parentRect = this.activeSubMenuRef.current.getBoundingClientRect();\n\n // intentionally rect.right, we want the sub menu to start at the right edge of the current menu\n this.setState({\n subMenuTop: parentRect.top,\n subMenuLeft: parentRect.right,\n subMenuParentHeight: parentRect.height,\n subMenuParentWidth: parentRect.width,\n });\n }\n\n /**\n * Verifies the position of this menu in relation to the parent to make sure it's on screen.\n * Will update the top left state (updatePosition) if necessary (causing a re-render)\n * By default it tries to top-align with parent, at the right side of the parent.\n * Because we aren't a native context menu and can't escape window bounds, we also do\n * somethings to better fit on screen, such as the \"nudge\" offset position, and further\n * allow overflow scrolling for large menus in a small window.\n */\n verifyPosition(): void {\n const {\n options,\n updatePosition,\n subMenuParentWidth,\n subMenuParentHeight,\n top: oldTop,\n left: oldLeft,\n } = this.props;\n\n if (\n !this.container.current ||\n (options.doNotVerifyPosition != null && options.doNotVerifyPosition)\n ) {\n return;\n }\n\n // initial position is used rather than current position,\n // as the number of menu items can change (actions can bubble)\n // and menu should always be positioned relative to spawn point\n let { top, left } = this.initialPosition;\n const { width, height } =\n this.container.current?.getBoundingClientRect() ?? {\n width: 0,\n height: 0,\n };\n const hasOverflow =\n (this.container.current?.scrollHeight ?? 0) > window.innerHeight;\n\n if (height === 0 || width === 0) {\n // We don't have a height or width yet, don't bother doing anything\n return;\n }\n\n // does it fit below?\n if (top + height > window.innerHeight) {\n // can it be flipped to above? include offset if submenu (defaults to 0 if not submenu)\n if (top - height - subMenuParentHeight > 0) {\n // flip like a native menu would\n top -= height - subMenuParentHeight;\n } else {\n // still doesnt fit? okay, position at bottom edge\n top = window.innerHeight - height;\n }\n }\n\n if (left + width > window.innerWidth) {\n // less picky about left right positioning, just keep it going off to right\n left = left - width - subMenuParentWidth;\n }\n\n if (oldLeft !== left || oldTop !== top) {\n // parent owns positioning as single source of truth, ask to update props\n this.setState({ hasOverflow });\n updatePosition(top, left);\n }\n }\n\n // since window resize doesn't trigger blur, listen and close the menu\n handleWindowResize(): void {\n if (!this.container.current) {\n return;\n }\n this.closeMenu(true);\n }\n\n handleBlur(e: React.FocusEvent<HTMLDivElement>): void {\n if (!this.container.current) {\n log.warn('Container is null!');\n return;\n }\n\n if (!this.container.current.contains(e.relatedTarget as Node)) {\n let element: HTMLElement | null = e.relatedTarget as HTMLElement;\n let isContextMenuChild = false;\n while (element && !isContextMenuChild) {\n isContextMenuChild = element.hasAttribute('data-dh-context-menu');\n element = element.parentElement;\n }\n\n if (!isContextMenuChild) {\n // close all submenus on blur\n this.closeMenu(true);\n }\n }\n }\n\n /** Returns whether the specified key should remove the menu. Depends on the side the parent is on. */\n isEscapeKey(key: string): boolean {\n const { left } = this.props;\n return (\n key === 'Escape' ||\n (left < 0 && key === 'ArrowRight') ||\n key === 'ArrowLeft'\n );\n }\n\n handleKeyDown(e: React.KeyboardEvent<HTMLDivElement>): void {\n const { menuItems } = this.state;\n const oldFocus = this.getKeyboardIndex();\n let newFocus: number | null = oldFocus;\n let openSubMenu = false;\n\n if (e.key === 'Enter' || e.key === ' ') {\n if (oldFocus >= 0 && oldFocus < menuItems.length) {\n this.handleMenuItemClick(\n menuItems[oldFocus],\n e as React.SyntheticEvent as React.MouseEvent\n );\n }\n return;\n }\n\n if (e.key === 'ArrowRight') {\n if (oldFocus >= 0 && oldFocus <= menuItems.length) {\n openSubMenu = true;\n } else {\n newFocus = 0;\n }\n } else if (this.isEscapeKey(e.key)) {\n newFocus = null;\n } else if (e.key === 'ArrowUp' || (e.shiftKey && e.key === 'Tab')) {\n newFocus = ContextActionUtils.getNextMenuItem(newFocus, -1, menuItems);\n } else if (e.key === 'ArrowDown' || e.key === 'Tab') {\n newFocus = ContextActionUtils.getNextMenuItem(newFocus, 1, menuItems);\n }\n\n if (openSubMenu) {\n this.openSubMenu(oldFocus);\n e.preventDefault();\n e.stopPropagation();\n return;\n }\n\n if (oldFocus !== newFocus) {\n if (newFocus !== null) {\n this.setKeyboardIndex(newFocus);\n } else {\n this.closeMenu();\n if (this.oldFocus instanceof HTMLElement) {\n this.oldFocus.focus();\n }\n }\n\n e.preventDefault();\n e.stopPropagation();\n }\n }\n\n openSubMenu(index: number): void {\n const { menuItems, activeSubMenu } = this.state;\n const newSubMenu = menuItems[index].actions ? index : null;\n if (activeSubMenu === newSubMenu) return;\n this.setState({\n activeSubMenu: newSubMenu,\n subMenuTop: null,\n subMenuLeft: null,\n });\n }\n\n closeMenu(closeAll = false): void {\n const { closeMenu, onMenuClosed } = this.props;\n cancelAnimationFrame(this.rAF);\n this.rAF = window.requestAnimationFrame(() => {\n closeMenu(closeAll);\n onMenuClosed(this);\n });\n }\n\n closeSubMenu(): void {\n this.setState({\n activeSubMenu: null,\n });\n }\n\n handleCloseSubMenu(closeAllMenus: boolean): void {\n if (closeAllMenus) {\n this.closeMenu(true);\n } else {\n this.closeSubMenu();\n }\n }\n\n handleMenuItemClick(menuItem: ContextAction, e: React.MouseEvent): void {\n e.preventDefault();\n e.stopPropagation();\n\n const { menuItems } = this.state;\n if (\n menuItem != null &&\n (menuItem.disabled === undefined || !menuItem.disabled)\n ) {\n if (menuItem.actions != null) {\n this.openSubMenu(menuItems.indexOf(menuItem));\n } else if (menuItem.action != null) {\n menuItem.action();\n this.closeMenu(true);\n }\n }\n }\n\n handleMenuItemContextMenu(\n menuItem: ContextAction,\n e: React.MouseEvent\n ): void {\n if (e.metaKey) {\n return;\n }\n\n this.handleMenuItemClick(menuItem, e);\n }\n\n handleMenuItemMouseMove(menuItem: ContextAction): void {\n const { menuItems } = this.state;\n const focusIndex = menuItems.indexOf(menuItem);\n this.setMouseIndex(focusIndex);\n\n if (\n focusIndex >= 0 &&\n focusIndex < menuItems.length &&\n (menuItem.disabled === undefined || !menuItem.disabled)\n ) {\n this.openSubMenu(focusIndex);\n }\n }\n\n handleMouseLeave(): void {\n this.setMouseIndex(-1);\n }\n\n render(): JSX.Element {\n const menuItemElements = [];\n const { top, left } = this.props;\n const {\n activeSubMenu,\n hasOverflow,\n keyboardIndex,\n menuItems,\n mouseIndex,\n pendingItems,\n subMenuTop,\n subMenuLeft,\n subMenuParentWidth,\n subMenuParentHeight,\n } = this.state;\n for (let i = 0; i < menuItems.length; i += 1) {\n const menuItem = menuItems[i];\n\n if (i > 0 && menuItem.group !== menuItems[i - 1].group) {\n menuItemElements.push(<hr key={`${i}.separator`} />);\n }\n\n const menuItemElement = (\n <ContextMenuItem\n key={i}\n ref={activeSubMenu === i ? this.activeSubMenuRef : null}\n isKeyboardSelected={keyboardIndex === i}\n isMouseSelected={mouseIndex === i}\n menuItem={menuItem}\n closeMenu={this.handleCloseSubMenu}\n onMenuItemClick={this.handleMenuItemClick}\n onMenuItemMouseMove={this.handleMenuItemMouseMove}\n onMenuItemContextMenu={this.handleMenuItemContextMenu}\n />\n );\n\n menuItemElements.push(menuItemElement);\n }\n\n let pendingElement = null;\n if (pendingItems.length > 0) {\n pendingElement = (\n <div className=\"loading\">\n <LoadingSpinner />\n </div>\n );\n }\n\n const { menuStyle, 'data-testid': dataTestId } = this.props;\n\n // don't show submenu until it has an position initialized\n const showSubmenu =\n activeSubMenu !== null && subMenuTop !== null && subMenuLeft !== null;\n\n return (\n <>\n <div\n className={classNames(\n { 'has-overflow': hasOverflow },\n 'context-menu-container'\n )}\n style={{ top, left, ...menuStyle }}\n ref={this.container}\n data-dh-context-menu\n onBlur={this.handleBlur}\n onKeyDown={this.handleKeyDown}\n onMouseLeave={this.handleMouseLeave}\n onContextMenu={ContextMenu.handleContextMenu}\n role=\"menuitem\"\n tabIndex={0}\n data-testid={dataTestId}\n >\n {menuItemElements}\n {pendingElement}\n </div>\n {showSubmenu &&\n activeSubMenu !== null &&\n subMenuTop !== null &&\n subMenuLeft !== null && (\n <ContextMenu\n key={`sub-${activeSubMenu}`}\n actions={menuItems[activeSubMenu].actions || []}\n closeMenu={this.handleCloseSubMenu}\n top={subMenuTop}\n left={subMenuLeft}\n updatePosition={(verifiedTop, verifiedLeft) => {\n this.setState({\n subMenuTop: verifiedTop,\n subMenuLeft: verifiedLeft,\n });\n }}\n subMenuParentWidth={subMenuParentWidth}\n subMenuParentHeight={subMenuParentHeight}\n />\n )}\n </>\n );\n }\n}\n\nexport default ContextMenu;\n"],"mappings":";;;;;AAAA,OAAOA,KAAK,IAAIC,aAAa,QAAQ,OAAO;AAC5C,OAAOC,UAAU,MAAM,YAAY;AACnC,OAAOC,GAAG,MAAM,gBAAgB;AAChC,SAASC,YAAY,QAA2B,kBAAkB;AAAC,OAC5DC,kBAAkB;AAAA,OAIlBC,eAAe;AAAA,OACfC,cAAc;AAErB,IAAMC,GAAG,GAAGL,GAAG,CAACM,MAAM,CAAC,aAAa,CAAC;AAoCrC;AACA,MAAMC,WAAW,SAAST,aAAa,CAAqC;EAkB1E,OAAOU,iBAAiB,CAACC,CAAmB,EAAQ;IAClD,IAAIA,CAAC,CAACC,OAAO,EAAE;MACb;IACF;IAEAD,CAAC,CAACE,eAAe,EAAE;IACnBF,CAAC,CAACG,cAAc,EAAE;EACpB;EAEAC,WAAW,CAACC,KAAuB,EAAE;IACnC,KAAK,CAACA,KAAK,CAAC;IAAC;IAAA;IAAA;IAAA;IAAA;IAAA;IAEb,IAAI,CAACC,UAAU,GAAG,IAAI,CAACA,UAAU,CAACC,IAAI,CAAC,IAAI,CAAC;IAC5C,IAAI,CAACC,kBAAkB,GAAG,IAAI,CAACA,kBAAkB,CAACD,IAAI,CAAC,IAAI,CAAC;IAC5D,IAAI,CAACE,aAAa,GAAG,IAAI,CAACA,aAAa,CAACF,IAAI,CAAC,IAAI,CAAC;IAClD,IAAI,CAACG,mBAAmB,GAAG,IAAI,CAACA,mBAAmB,CAACH,IAAI,CAAC,IAAI,CAAC;IAC9D,IAAI,CAACI,yBAAyB,GAAG,IAAI,CAACA,yBAAyB,CAACJ,IAAI,CAAC,IAAI,CAAC;IAC1E,IAAI,CAACK,uBAAuB,GAAG,IAAI,CAACA,uBAAuB,CAACL,IAAI,CAAC,IAAI,CAAC;IACtE,IAAI,CAACM,gBAAgB,GAAG,IAAI,CAACA,gBAAgB,CAACN,IAAI,CAAC,IAAI,CAAC;IACxD,IAAI,CAACO,kBAAkB,GAAG,IAAI,CAACA,kBAAkB,CAACP,IAAI,CAAC,IAAI,CAAC;IAE5D,IAAI,CAACQ,SAAS,gBAAG3B,KAAK,CAAC4B,SAAS,EAAE;IAClC,IAAI,CAACC,QAAQ,GAAGC,QAAQ,CAACC,aAAa;IACtC,IAAI,CAACC,gBAAgB,gBAAGhC,KAAK,CAAC4B,SAAS,EAAE;IACzC,IAAI,CAACK,YAAY,GAAG,CAAC;IACrB,IAAI,CAACC,GAAG,GAAG,CAAC;IAEZ,IAAI,CAACC,eAAe,GAAG;MAAEC,GAAG,EAAEnB,KAAK,CAACmB,GAAG;MAAEC,IAAI,EAAEpB,KAAK,CAACoB;IAAK,CAAC;IAE3D,IAAI,CAACC,KAAK,GAAG;MACXC,SAAS,EAAE,EAAE;MACbC,YAAY,EAAE,EAAE;MAChBC,aAAa,EAAE,IAAI;MACnBC,WAAW,EAAE,KAAK;MAClBC,UAAU,EAAE,IAAI;MAChBC,WAAW,EAAE,IAAI;MACjBC,kBAAkB,EAAE,CAAC;MACrBC,mBAAmB,EAAE,CAAC;MACtBC,aAAa,EAAE,CAAC,CAAC;MACjBC,UAAU,EAAE,CAAC;IACf,CAAC;EACH;EAEAC,iBAAiB,GAAS;IACxB,IAAI,CAACC,QAAQ,EAAE;IAEf,IAAI,CAACC,cAAc,EAAE;IAErBC,MAAM,CAACC,gBAAgB,CAAC,QAAQ,EAAE,IAAI,CAAC3B,kBAAkB,CAAC;;IAE1D;IACA;IACA;IACA;IACA,IAAI,CAACQ,GAAG,GAAGkB,MAAM,CAACE,qBAAqB,CAAC,MAAM;MAAA;MAC5C,6BAAI,CAAC3B,SAAS,CAAC4B,OAAO,0DAAtB,sBAAwBC,KAAK,EAAE;MAE/B,IAAM;QAAEC;MAAa,CAAC,GAAG,IAAI,CAACxC,KAAK;MACnCwC,YAAY,CAAC,IAAI,CAAC;IACpB,CAAC,CAAC;EACJ;EAEAC,kBAAkB,CAChBC,SAA2B,EAC3BC,SAA2B,EACrB;IACN,IAAM;MAAEC;IAAQ,CAAC,GAAG,IAAI,CAAC5C,KAAK;IAC9B,IAAM;MAAEwB;IAAc,CAAC,GAAG,IAAI,CAACH,KAAK;IAEpC,IAAIG,aAAa,KAAKmB,SAAS,CAACnB,aAAa,EAAE;MAC7C,IAAIA,aAAa,IAAI,IAAI,EAAE;QAAA;QACzB;QACA,8BAAI,CAACd,SAAS,CAAC4B,OAAO,2DAAtB,uBAAwBC,KAAK,EAAE;MACjC,CAAC,MAAM;QACL;QACA,IAAI,CAACM,wBAAwB,EAAE;MACjC;IACF;IAEA,IAAIH,SAAS,CAACE,OAAO,KAAKA,OAAO,EAAE;MACjC,IAAI,CAACX,QAAQ,EAAE;MAEf,IACE,IAAI,CAACvB,SAAS,CAAC4B,OAAO,IAAI,IAAI,IAC9B,CAAC,IAAI,CAAC5B,SAAS,CAAC4B,OAAO,CAACQ,QAAQ,CAACjC,QAAQ,CAACC,aAAa,CAAC,EACxD;QAAA;QACA,8BAAI,CAACJ,SAAS,CAAC4B,OAAO,2DAAtB,uBAAwBC,KAAK,EAAE;MACjC;IACF;IAEA,IAAI,CAACL,cAAc,EAAE;EACvB;EAEAa,oBAAoB,GAAS;IAC3B,IAAI,CAACC,cAAc,EAAE;IACrBb,MAAM,CAACc,mBAAmB,CAAC,QAAQ,EAAE,IAAI,CAACxC,kBAAkB,CAAC;IAC7DyC,oBAAoB,CAAC,IAAI,CAACjC,GAAG,CAAC;EAChC;EAcAkC,gBAAgB,GAAW;IACzB,IAAM;MAAEC;IAAQ,CAAC,GAAG,IAAI,CAACpD,KAAK;IAC9B,IACEoD,OAAO,CAACC,qBAAqB,KAAKC,SAAS,IAC3CF,OAAO,CAACC,qBAAqB,EAC7B;MACA,IAAM;QAAEvB;MAAc,CAAC,GAAG,IAAI,CAACT,KAAK;MACpC,OAAOS,aAAa;IACtB;IAEA,OAAO,IAAI,CAACyB,aAAa,EAAE;EAC7B;EAEAC,gBAAgB,CAACC,KAAa,EAAQ;IACpC,IAAM;MAAEL;IAAQ,CAAC,GAAG,IAAI,CAACpD,KAAK;IAC9B,IACEoD,OAAO,CAACC,qBAAqB,KAAKC,SAAS,IAC3CF,OAAO,CAACC,qBAAqB,EAC7B;MACA,IAAI,CAACK,QAAQ,CAAC;QAAE5B,aAAa,EAAE2B;MAAM,CAAC,CAAC;IACzC,CAAC,MAAM;MACL,IAAI,CAACE,aAAa,CAACF,KAAK,CAAC;IAC3B;EACF;EAEAF,aAAa,GAAW;IACtB,IAAM;MAAExB;IAAW,CAAC,GAAG,IAAI,CAACV,KAAK;IACjC,OAAOU,UAAU;EACnB;EAEA4B,aAAa,CAACF,KAAa,EAAQ;IACjC,IAAI,CAACC,QAAQ,CAAC;MAAE3B,UAAU,EAAE0B;IAAM,CAAC,CAAC;EACtC;EAEAxB,QAAQ,GAAS;IACf;IACA,IAAI,CAACe,cAAc,EAAE;IACrBE,oBAAoB,CAAC,IAAI,CAACjC,GAAG,CAAC;IAE9B,IAAM;MAAEmC;IAAQ,CAAC,GAAG,IAAI,CAACpD,KAAK;IAC9B,IAAI8B,aAAa,GAAGsB,OAAO,CAACQ,oBAAoB;IAChD,IAAI9B,aAAa,KAAKwB,SAAS,EAAE;MAC/BxB,aAAa,GAAG,CAAC,CAAC;IACpB;IAEA,IAAM;MAAEc;IAAQ,CAAC,GAAG,IAAI,CAAC5C,KAAK;IAC9B,IAAMsB,SAAS,GAAGlC,kBAAkB,CAACyE,YAAY,CAACjB,OAAO,CAAC;IAC1D,IAAMkB,eAAgC,GAAG,EAAE;IAC3C,KAAK,IAAIC,CAAC,GAAGzC,SAAS,CAAC0C,MAAM,GAAG,CAAC,EAAED,CAAC,IAAI,CAAC,EAAEA,CAAC,IAAI,CAAC,EAAE;MACjD,IAAME,QAAQ,GAAG3C,SAAS,CAACyC,CAAC,CAAC;MAC7B,IAAIE,QAAQ,YAAYC,OAAO,EAAE;QAC/B,IAAI,CAACC,eAAe,CAACF,QAAQ,CAA6B;MAC5D,CAAC,MAAM;QACLH,eAAe,CAACM,IAAI,CAACH,QAAQ,CAAkB;MACjD;IACF;IAEA,IAAI,CAACP,QAAQ,CAAC;MACZ3B,UAAU,EAAE,CAAC,CAAC;MACdD,aAAa;MACbN,aAAa,EAAE,IAAI;MACnBF,SAAS,EAAElC,kBAAkB,CAACiF,WAAW,CAACP,eAAe;IAC3D,CAAC,CAAC;EACJ;EAEAK,eAAe,CAACG,OAAiC,EAAQ;IACvD;IACA,IAAMC,kBAAkB,GAAGpF,YAAY,CAACqF,cAAc,CAACF,OAAO,CAAC;IAE/D,IAAI,CAACZ,QAAQ,CAACrC,KAAK,KAAK;MACtBE,YAAY,EAAEF,KAAK,CAACE,YAAY,CAACkD,MAAM,CAACF,kBAAkB;IAC5D,CAAC,CAAC,CAAC;IAEHA,kBAAkB,CAACG,IAAI,CACrBC,iBAAiB,IAAI;MACnB,IAAI,CAACjB,QAAQ,CAACrC,KAAK,IAAI;QACrB,IAAMoC,KAAK,GAAGpC,KAAK,CAACE,YAAY,CAACqD,OAAO,CAACL,kBAAkB,CAAC;QAC5D,IAAId,KAAK,IAAI,CAAC,EAAE;UACd,IAAMlC,YAAY,GAAGF,KAAK,CAACE,YAAY,CAACsD,KAAK,EAAE;UAC/CtD,YAAY,CAACuD,MAAM,CAACrB,KAAK,EAAE,CAAC,CAAC;UAE7B,OAAO;YACLnC,SAAS,EAAElC,kBAAkB,CAACiF,WAAW,CACvChD,KAAK,CAACC,SAAS,CAACmD,MAAM,CAACE,iBAAiB,CAAC,CAC1C;YACDpD;UACF,CAAC;QACH;QACA;QACA,OAAO,IAAI;MACb,CAAC,CAAC;IACJ,CAAC,EACDwD,KAAK,IAAI;MACP,IAAI5F,YAAY,CAAC6F,UAAU,CAACD,KAAK,CAAC,EAAE;QAClC,OAAO,CAAC;MACV;;MAEA;MACA,IAAI,CAACrB,QAAQ,CAACrC,KAAK,IAAI;QACrB,IAAMoC,KAAK,GAAGpC,KAAK,CAACE,YAAY,CAACqD,OAAO,CAACL,kBAAkB,CAAC;QAC5D,IAAId,KAAK,IAAI,CAAC,EAAE;UACd,IAAMlC,YAAY,GAAGF,KAAK,CAACE,YAAY,CAACsD,KAAK,EAAE;UAC/CtD,YAAY,CAACuD,MAAM,CAACrB,KAAK,EAAE,CAAC,CAAC;UAC7B,OAAO;YACLlC;UACF,CAAC;QACH;QACA,OAAO,IAAI;MACb,CAAC,CAAC;;MAEF;MACAhC,GAAG,CAACwF,KAAK,CAACA,KAAK,CAAC;IAClB,CAAC,CACF;EACH;EAEA/B,cAAc,GAAS;IACrB,IAAM;MAAEzB;IAAa,CAAC,GAAG,IAAI,CAACF,KAAK;IACnCE,YAAY,CAAC0D,GAAG,CAACC,IAAI,IAAIA,IAAI,CAACC,MAAM,EAAE,CAAC;EACzC;;EAEA;AACF;AACA;AACA;EACEtC,wBAAwB,GAAS;IAC/B,IAAI,IAAI,CAAC9B,gBAAgB,CAACuB,OAAO,KAAK,IAAI,EAAE;IAC5C,IAAM8C,UAAU,GAAG,IAAI,CAACrE,gBAAgB,CAACuB,OAAO,CAAC+C,qBAAqB,EAAE;;IAExE;IACA,IAAI,CAAC3B,QAAQ,CAAC;MACZhC,UAAU,EAAE0D,UAAU,CAACjE,GAAG;MAC1BQ,WAAW,EAAEyD,UAAU,CAACE,KAAK;MAC7BzD,mBAAmB,EAAEuD,UAAU,CAACG,MAAM;MACtC3D,kBAAkB,EAAEwD,UAAU,CAACI;IACjC,CAAC,CAAC;EACJ;;EAEA;AACF;AACA;AACA;AACA;AACA;AACA;AACA;EACEtD,cAAc,GAAS;IAAA;IACrB,IAAM;MACJkB,OAAO;MACPqC,cAAc;MACd7D,kBAAkB;MAClBC,mBAAmB;MACnBV,GAAG,EAAEuE,MAAM;MACXtE,IAAI,EAAEuE;IACR,CAAC,GAAG,IAAI,CAAC3F,KAAK;IAEd,IACE,CAAC,IAAI,CAACU,SAAS,CAAC4B,OAAO,IACtBc,OAAO,CAACwC,mBAAmB,IAAI,IAAI,IAAIxC,OAAO,CAACwC,mBAAoB,EACpE;MACA;IACF;;IAEA;IACA;IACA;IACA,IAAI;MAAEzE,GAAG;MAAEC;IAAK,CAAC,GAAG,IAAI,CAACF,eAAe;IACxC,IAAM;MAAEsE,KAAK;MAAED;IAAO,CAAC,uDACrB,IAAI,CAAC7E,SAAS,CAAC4B,OAAO,2DAAtB,uBAAwB+C,qBAAqB,EAAE,2EAAI;MACjDG,KAAK,EAAE,CAAC;MACRD,MAAM,EAAE;IACV,CAAC;IACH,IAAM9D,WAAW,GACf,qDAAC,IAAI,CAACf,SAAS,CAAC4B,OAAO,2DAAtB,uBAAwBuD,YAAY,2EAAI,CAAC,IAAI1D,MAAM,CAAC2D,WAAW;IAElE,IAAIP,MAAM,KAAK,CAAC,IAAIC,KAAK,KAAK,CAAC,EAAE;MAC/B;MACA;IACF;;IAEA;IACA,IAAIrE,GAAG,GAAGoE,MAAM,GAAGpD,MAAM,CAAC2D,WAAW,EAAE;MACrC;MACA,IAAI3E,GAAG,GAAGoE,MAAM,GAAG1D,mBAAmB,GAAG,CAAC,EAAE;QAC1C;QACAV,GAAG,IAAIoE,MAAM,GAAG1D,mBAAmB;MACrC,CAAC,MAAM;QACL;QACAV,GAAG,GAAGgB,MAAM,CAAC2D,WAAW,GAAGP,MAAM;MACnC;IACF;IAEA,IAAInE,IAAI,GAAGoE,KAAK,GAAGrD,MAAM,CAAC4D,UAAU,EAAE;MACpC;MACA3E,IAAI,GAAGA,IAAI,GAAGoE,KAAK,GAAG5D,kBAAkB;IAC1C;IAEA,IAAI+D,OAAO,KAAKvE,IAAI,IAAIsE,MAAM,KAAKvE,GAAG,EAAE;MACtC;MACA,IAAI,CAACuC,QAAQ,CAAC;QAAEjC;MAAY,CAAC,CAAC;MAC9BgE,cAAc,CAACtE,GAAG,EAAEC,IAAI,CAAC;IAC3B;EACF;;EAEA;EACAX,kBAAkB,GAAS;IACzB,IAAI,CAAC,IAAI,CAACC,SAAS,CAAC4B,OAAO,EAAE;MAC3B;IACF;IACA,IAAI,CAAC0D,SAAS,CAAC,IAAI,CAAC;EACtB;EAEA/F,UAAU,CAACN,CAAmC,EAAQ;IACpD,IAAI,CAAC,IAAI,CAACe,SAAS,CAAC4B,OAAO,EAAE;MAC3B/C,GAAG,CAAC0G,IAAI,CAAC,oBAAoB,CAAC;MAC9B;IACF;IAEA,IAAI,CAAC,IAAI,CAACvF,SAAS,CAAC4B,OAAO,CAACQ,QAAQ,CAACnD,CAAC,CAACuG,aAAa,CAAS,EAAE;MAC7D,IAAIC,OAA2B,GAAGxG,CAAC,CAACuG,aAA4B;MAChE,IAAIE,kBAAkB,GAAG,KAAK;MAC9B,OAAOD,OAAO,IAAI,CAACC,kBAAkB,EAAE;QACrCA,kBAAkB,GAAGD,OAAO,CAACE,YAAY,CAAC,sBAAsB,CAAC;QACjEF,OAAO,GAAGA,OAAO,CAACG,aAAa;MACjC;MAEA,IAAI,CAACF,kBAAkB,EAAE;QACvB;QACA,IAAI,CAACJ,SAAS,CAAC,IAAI,CAAC;MACtB;IACF;EACF;;EAEA;EACAO,WAAW,CAACC,GAAW,EAAW;IAChC,IAAM;MAAEpF;IAAK,CAAC,GAAG,IAAI,CAACpB,KAAK;IAC3B,OACEwG,GAAG,KAAK,QAAQ,IACfpF,IAAI,GAAG,CAAC,IAAIoF,GAAG,KAAK,YAAa,IAClCA,GAAG,KAAK,WAAW;EAEvB;EAEApG,aAAa,CAACT,CAAsC,EAAQ;IAC1D,IAAM;MAAE2B;IAAU,CAAC,GAAG,IAAI,CAACD,KAAK;IAChC,IAAMT,QAAQ,GAAG,IAAI,CAACuC,gBAAgB,EAAE;IACxC,IAAIsD,QAAuB,GAAG7F,QAAQ;IACtC,IAAI8F,WAAW,GAAG,KAAK;IAEvB,IAAI/G,CAAC,CAAC6G,GAAG,KAAK,OAAO,IAAI7G,CAAC,CAAC6G,GAAG,KAAK,GAAG,EAAE;MACtC,IAAI5F,QAAQ,IAAI,CAAC,IAAIA,QAAQ,GAAGU,SAAS,CAAC0C,MAAM,EAAE;QAChD,IAAI,CAAC3D,mBAAmB,CACtBiB,SAAS,CAACV,QAAQ,CAAC,EACnBjB,CAAC,CACF;MACH;MACA;IACF;IAEA,IAAIA,CAAC,CAAC6G,GAAG,KAAK,YAAY,EAAE;MAC1B,IAAI5F,QAAQ,IAAI,CAAC,IAAIA,QAAQ,IAAIU,SAAS,CAAC0C,MAAM,EAAE;QACjD0C,WAAW,GAAG,IAAI;MACpB,CAAC,MAAM;QACLD,QAAQ,GAAG,CAAC;MACd;IACF,CAAC,MAAM,IAAI,IAAI,CAACF,WAAW,CAAC5G,CAAC,CAAC6G,GAAG,CAAC,EAAE;MAClCC,QAAQ,GAAG,IAAI;IACjB,CAAC,MAAM,IAAI9G,CAAC,CAAC6G,GAAG,KAAK,SAAS,IAAK7G,CAAC,CAACgH,QAAQ,IAAIhH,CAAC,CAAC6G,GAAG,KAAK,KAAM,EAAE;MACjEC,QAAQ,GAAGrH,kBAAkB,CAACwH,eAAe,CAACH,QAAQ,EAAE,CAAC,CAAC,EAAEnF,SAAS,CAAC;IACxE,CAAC,MAAM,IAAI3B,CAAC,CAAC6G,GAAG,KAAK,WAAW,IAAI7G,CAAC,CAAC6G,GAAG,KAAK,KAAK,EAAE;MACnDC,QAAQ,GAAGrH,kBAAkB,CAACwH,eAAe,CAACH,QAAQ,EAAE,CAAC,EAAEnF,SAAS,CAAC;IACvE;IAEA,IAAIoF,WAAW,EAAE;MACf,IAAI,CAACA,WAAW,CAAC9F,QAAQ,CAAC;MAC1BjB,CAAC,CAACG,cAAc,EAAE;MAClBH,CAAC,CAACE,eAAe,EAAE;MACnB;IACF;IAEA,IAAIe,QAAQ,KAAK6F,QAAQ,EAAE;MACzB,IAAIA,QAAQ,KAAK,IAAI,EAAE;QACrB,IAAI,CAACjD,gBAAgB,CAACiD,QAAQ,CAAC;MACjC,CAAC,MAAM;QACL,IAAI,CAACT,SAAS,EAAE;QAChB,IAAI,IAAI,CAACpF,QAAQ,YAAYiG,WAAW,EAAE;UACxC,IAAI,CAACjG,QAAQ,CAAC2B,KAAK,EAAE;QACvB;MACF;MAEA5C,CAAC,CAACG,cAAc,EAAE;MAClBH,CAAC,CAACE,eAAe,EAAE;IACrB;EACF;EAEA6G,WAAW,CAACjD,KAAa,EAAQ;IAC/B,IAAM;MAAEnC,SAAS;MAAEE;IAAc,CAAC,GAAG,IAAI,CAACH,KAAK;IAC/C,IAAMyF,UAAU,GAAGxF,SAAS,CAACmC,KAAK,CAAC,CAACb,OAAO,GAAGa,KAAK,GAAG,IAAI;IAC1D,IAAIjC,aAAa,KAAKsF,UAAU,EAAE;IAClC,IAAI,CAACpD,QAAQ,CAAC;MACZlC,aAAa,EAAEsF,UAAU;MACzBpF,UAAU,EAAE,IAAI;MAChBC,WAAW,EAAE;IACf,CAAC,CAAC;EACJ;EAEAqE,SAAS,GAAyB;IAAA,IAAxBe,QAAQ,uEAAG,KAAK;IACxB,IAAM;MAAEf,SAAS;MAAEgB;IAAa,CAAC,GAAG,IAAI,CAAChH,KAAK;IAC9CkD,oBAAoB,CAAC,IAAI,CAACjC,GAAG,CAAC;IAC9B,IAAI,CAACA,GAAG,GAAGkB,MAAM,CAACE,qBAAqB,CAAC,MAAM;MAC5C2D,SAAS,CAACe,QAAQ,CAAC;MACnBC,YAAY,CAAC,IAAI,CAAC;IACpB,CAAC,CAAC;EACJ;EAEAC,YAAY,GAAS;IACnB,IAAI,CAACvD,QAAQ,CAAC;MACZlC,aAAa,EAAE;IACjB,CAAC,CAAC;EACJ;EAEArB,kBAAkB,CAAC+G,aAAsB,EAAQ;IAC/C,IAAIA,aAAa,EAAE;MACjB,IAAI,CAAClB,SAAS,CAAC,IAAI,CAAC;IACtB,CAAC,MAAM;MACL,IAAI,CAACiB,YAAY,EAAE;IACrB;EACF;EAEA5G,mBAAmB,CAAC4D,QAAuB,EAAEtE,CAAmB,EAAQ;IACtEA,CAAC,CAACG,cAAc,EAAE;IAClBH,CAAC,CAACE,eAAe,EAAE;IAEnB,IAAM;MAAEyB;IAAU,CAAC,GAAG,IAAI,CAACD,KAAK;IAChC,IACE4C,QAAQ,IAAI,IAAI,KACfA,QAAQ,CAACkD,QAAQ,KAAK7D,SAAS,IAAI,CAACW,QAAQ,CAACkD,QAAQ,CAAC,EACvD;MACA,IAAIlD,QAAQ,CAACrB,OAAO,IAAI,IAAI,EAAE;QAC5B,IAAI,CAAC8D,WAAW,CAACpF,SAAS,CAACsD,OAAO,CAACX,QAAQ,CAAC,CAAC;MAC/C,CAAC,MAAM,IAAIA,QAAQ,CAACmD,MAAM,IAAI,IAAI,EAAE;QAClCnD,QAAQ,CAACmD,MAAM,EAAE;QACjB,IAAI,CAACpB,SAAS,CAAC,IAAI,CAAC;MACtB;IACF;EACF;EAEA1F,yBAAyB,CACvB2D,QAAuB,EACvBtE,CAAmB,EACb;IACN,IAAIA,CAAC,CAACC,OAAO,EAAE;MACb;IACF;IAEA,IAAI,CAACS,mBAAmB,CAAC4D,QAAQ,EAAEtE,CAAC,CAAC;EACvC;EAEAY,uBAAuB,CAAC0D,QAAuB,EAAQ;IACrD,IAAM;MAAE3C;IAAU,CAAC,GAAG,IAAI,CAACD,KAAK;IAChC,IAAMgG,UAAU,GAAG/F,SAAS,CAACsD,OAAO,CAACX,QAAQ,CAAC;IAC9C,IAAI,CAACN,aAAa,CAAC0D,UAAU,CAAC;IAE9B,IACEA,UAAU,IAAI,CAAC,IACfA,UAAU,GAAG/F,SAAS,CAAC0C,MAAM,KAC5BC,QAAQ,CAACkD,QAAQ,KAAK7D,SAAS,IAAI,CAACW,QAAQ,CAACkD,QAAQ,CAAC,EACvD;MACA,IAAI,CAACT,WAAW,CAACW,UAAU,CAAC;IAC9B;EACF;EAEA7G,gBAAgB,GAAS;IACvB,IAAI,CAACmD,aAAa,CAAC,CAAC,CAAC,CAAC;EACxB;EAEA2D,MAAM,GAAgB;IACpB,IAAMC,gBAAgB,GAAG,EAAE;IAC3B,IAAM;MAAEpG,GAAG;MAAEC;IAAK,CAAC,GAAG,IAAI,CAACpB,KAAK;IAChC,IAAM;MACJwB,aAAa;MACbC,WAAW;MACXK,aAAa;MACbR,SAAS;MACTS,UAAU;MACVR,YAAY;MACZG,UAAU;MACVC,WAAW;MACXC,kBAAkB;MAClBC;IACF,CAAC,GAAG,IAAI,CAACR,KAAK;IACd,KAAK,IAAI0C,CAAC,GAAG,CAAC,EAAEA,CAAC,GAAGzC,SAAS,CAAC0C,MAAM,EAAED,CAAC,IAAI,CAAC,EAAE;MAC5C,IAAME,QAAQ,GAAG3C,SAAS,CAACyC,CAAC,CAAC;MAE7B,IAAIA,CAAC,GAAG,CAAC,IAAIE,QAAQ,CAACuD,KAAK,KAAKlG,SAAS,CAACyC,CAAC,GAAG,CAAC,CAAC,CAACyD,KAAK,EAAE;QACtDD,gBAAgB,CAACnD,IAAI,eAAC;UAAI,GAAG,YAAKL,CAAC;QAAa,EAAG,CAAC;MACtD;MAEA,IAAM0D,eAAe,gBACnB,oBAAC,eAAe;QACd,GAAG,EAAE1D,CAAE;QACP,GAAG,EAAEvC,aAAa,KAAKuC,CAAC,GAAG,IAAI,CAAChD,gBAAgB,GAAG,IAAK;QACxD,kBAAkB,EAAEe,aAAa,KAAKiC,CAAE;QACxC,eAAe,EAAEhC,UAAU,KAAKgC,CAAE;QAClC,QAAQ,EAAEE,QAAS;QACnB,SAAS,EAAE,IAAI,CAAC9D,kBAAmB;QACnC,eAAe,EAAE,IAAI,CAACE,mBAAoB;QAC1C,mBAAmB,EAAE,IAAI,CAACE,uBAAwB;QAClD,qBAAqB,EAAE,IAAI,CAACD;MAA0B,EAEzD;MAEDiH,gBAAgB,CAACnD,IAAI,CAACqD,eAAe,CAAC;IACxC;IAEA,IAAIC,cAAc,GAAG,IAAI;IACzB,IAAInG,YAAY,CAACyC,MAAM,GAAG,CAAC,EAAE;MAC3B0D,cAAc,gBACZ;QAAK,SAAS,EAAC;MAAS,gBACtB,oBAAC,cAAc,OAAG,CAErB;IACH;IAEA,IAAM;MAAEC,SAAS;MAAE,aAAa,EAAEC;IAAW,CAAC,GAAG,IAAI,CAAC5H,KAAK;;IAE3D;IACA,IAAM6H,WAAW,GACfrG,aAAa,KAAK,IAAI,IAAIE,UAAU,KAAK,IAAI,IAAIC,WAAW,KAAK,IAAI;IAEvE,oBACE,uDACE;MACE,SAAS,EAAE1C,UAAU,CACnB;QAAE,cAAc,EAAEwC;MAAY,CAAC,EAC/B,wBAAwB,CACxB;MACF,KAAK;QAAIN,GAAG;QAAEC;MAAI,GAAKuG,SAAS,CAAG;MACnC,GAAG,EAAE,IAAI,CAACjH,SAAU;MACpB,4BAAoB;MACpB,MAAM,EAAE,IAAI,CAACT,UAAW;MACxB,SAAS,EAAE,IAAI,CAACG,aAAc;MAC9B,YAAY,EAAE,IAAI,CAACI,gBAAiB;MACpC,aAAa,EAAEf,WAAW,CAACC,iBAAkB;MAC7C,IAAI,EAAC,UAAU;MACf,QAAQ,EAAE,CAAE;MACZ,eAAakI;IAAW,GAEvBL,gBAAgB,EAChBG,cAAc,CACX,EACLG,WAAW,IACVrG,aAAa,KAAK,IAAI,IACtBE,UAAU,KAAK,IAAI,IACnBC,WAAW,KAAK,IAAI,iBAClB,oBAAC,WAAW;MACV,GAAG,gBAASH,aAAa,CAAG;MAC5B,OAAO,EAAEF,SAAS,CAACE,aAAa,CAAC,CAACoB,OAAO,IAAI,EAAG;MAChD,SAAS,EAAE,IAAI,CAACzC,kBAAmB;MACnC,GAAG,EAAEuB,UAAW;MAChB,IAAI,EAAEC,WAAY;MAClB,cAAc,EAAE,CAACmG,WAAW,EAAEC,YAAY,KAAK;QAC7C,IAAI,CAACrE,QAAQ,CAAC;UACZhC,UAAU,EAAEoG,WAAW;UACvBnG,WAAW,EAAEoG;QACf,CAAC,CAAC;MACJ,CAAE;MACF,kBAAkB,EAAEnG,kBAAmB;MACvC,mBAAmB,EAAEC;IAAoB,EAE5C,CACF;EAEP;AACF;AAAC,gBA3lBKpC,WAAW,kBACO;EACpBmC,kBAAkB,EAAE,CAAC;EACrBC,mBAAmB,EAAE,CAAC;EACtBmE,SAAS,GAAS;IAChB;EAAA,CACD;EACDxD,YAAY,GAAS;IACnB;EAAA,CACD;EACDwE,YAAY,GAAS;IACnB;EAAA,CACD;EACD5D,OAAO,EAAE,CAAC,CAAC;EACXuE,SAAS,EAAE,CAAC,CAAC;EACb,aAAa,EAAErE;AACjB,CAAC;AA6kBH,eAAe7D,WAAW"}
|
|
1
|
+
{"version":3,"file":"ContextMenu.js","names":["React","PureComponent","classNames","Log","PromiseUtils","ContextActionUtils","ContextMenuItem","LoadingSpinner","log","module","ContextMenu","handleContextMenu","e","metaKey","stopPropagation","preventDefault","constructor","props","handleBlur","bind","handleCloseSubMenu","handleKeyDown","handleMenuItemClick","handleMenuItemContextMenu","handleMenuItemMouseMove","handleMouseLeave","handleWindowResize","container","createRef","oldFocus","document","activeElement","activeSubMenuRef","subMenuTimer","rAF","initialPosition","top","left","state","menuItems","pendingItems","activeSubMenu","hasOverflow","subMenuTop","subMenuLeft","subMenuParentWidth","subMenuParentHeight","keyboardIndex","mouseIndex","componentDidMount","initMenu","verifyPosition","window","addEventListener","requestAnimationFrame","current","focus","onMenuOpened","componentDidUpdate","prevProps","prevState","actions","setActiveSubMenuPosition","contains","componentWillUnmount","cancelPromises","removeEventListener","cancelAnimationFrame","getKeyboardIndex","options","separateKeyboardMouse","undefined","getMouseIndex","setKeyboardIndex","index","setState","setMouseIndex","initialKeyboardIndex","getMenuItems","nonPromiseItems","i","length","menuItem","Promise","initMenuPromise","push","sortActions","promise","cancellablePromise","makeCancelable","concat","then","resolvedMenuItems","indexOf","slice","splice","error","isCanceled","map","item","cancel","parentRect","getBoundingClientRect","right","height","width","updatePosition","oldTop","oldLeft","doNotVerifyPosition","scrollHeight","innerHeight","innerWidth","closeMenu","warn","relatedTarget","element","isContextMenuChild","hasAttribute","parentElement","isEscapeKey","key","newFocus","openSubMenu","shiftKey","getNextMenuItem","HTMLElement","newSubMenu","closeAll","onMenuClosed","closeSubMenu","closeAllMenus","disabled","action","focusIndex","render","menuItemElements","group","menuItemElement","pendingElement","menuStyle","dataTestId","showSubmenu","verifiedTop","verifiedLeft"],"sources":["../../src/context-actions/ContextMenu.tsx"],"sourcesContent":["import React, { PureComponent } from 'react';\nimport classNames from 'classnames';\nimport Log from '@deephaven/log';\nimport { PromiseUtils, CancelablePromise } from '@deephaven/utils';\nimport ContextActionUtils, {\n ContextAction,\n ResolvableContextAction,\n} from './ContextActionUtils';\nimport ContextMenuItem from './ContextMenuItem';\nimport LoadingSpinner from '../LoadingSpinner';\n\nconst log = Log.module('ContextMenu');\n\ninterface ContextMenuProps {\n top: number;\n left: number;\n updatePosition(top: number, left: number): void;\n // only submenus will have these, defaults to 0 otherwise\n // represents the width height of the parent menu item\n subMenuParentWidth: number;\n subMenuParentHeight: number;\n actions: ResolvableContextAction[];\n closeMenu(closeAll: boolean): void;\n onMenuClosed(menu: ContextMenu): void;\n onMenuOpened(menu: ContextMenu): void;\n options: {\n doNotVerifyPosition?: boolean;\n separateKeyboardMouse?: boolean;\n initialKeyboardIndex?: number;\n };\n menuStyle: React.CSSProperties;\n 'data-testid'?: string;\n}\n\ninterface ContextMenuState {\n menuItems: ContextAction[];\n pendingItems: CancelablePromise<ContextAction[]>[];\n activeSubMenu: number | null;\n hasOverflow: boolean;\n subMenuTop: number | null;\n subMenuLeft: number | null;\n subMenuParentWidth: number;\n subMenuParentHeight: number;\n keyboardIndex: number;\n mouseIndex: number;\n}\n\n/** Do not use this class directly. Use ContextMenuRoot and ContextActions instead. */\nclass ContextMenu extends PureComponent<ContextMenuProps, ContextMenuState> {\n static defaultProps = {\n subMenuParentWidth: 0,\n subMenuParentHeight: 0,\n closeMenu(): void {\n // no-op\n },\n onMenuOpened(): void {\n // no-op\n },\n onMenuClosed(): void {\n // no-op\n },\n options: {},\n menuStyle: {},\n 'data-testid': undefined,\n };\n\n static handleContextMenu(e: React.MouseEvent): void {\n if (e.metaKey) {\n return;\n }\n\n e.stopPropagation();\n e.preventDefault();\n }\n\n constructor(props: ContextMenuProps) {\n super(props);\n\n this.handleBlur = this.handleBlur.bind(this);\n this.handleCloseSubMenu = this.handleCloseSubMenu.bind(this);\n this.handleKeyDown = this.handleKeyDown.bind(this);\n this.handleMenuItemClick = this.handleMenuItemClick.bind(this);\n this.handleMenuItemContextMenu = this.handleMenuItemContextMenu.bind(this);\n this.handleMenuItemMouseMove = this.handleMenuItemMouseMove.bind(this);\n this.handleMouseLeave = this.handleMouseLeave.bind(this);\n this.handleWindowResize = this.handleWindowResize.bind(this);\n\n this.container = React.createRef();\n this.oldFocus = document.activeElement;\n this.activeSubMenuRef = React.createRef();\n this.subMenuTimer = 0;\n this.rAF = 0;\n\n this.initialPosition = { top: props.top, left: props.left };\n\n this.state = {\n menuItems: [],\n pendingItems: [],\n activeSubMenu: null,\n hasOverflow: false,\n subMenuTop: null,\n subMenuLeft: null,\n subMenuParentWidth: 0,\n subMenuParentHeight: 0,\n keyboardIndex: -1,\n mouseIndex: -1,\n };\n }\n\n componentDidMount(): void {\n this.initMenu();\n\n this.verifyPosition();\n\n window.addEventListener('resize', this.handleWindowResize);\n\n // rAF is needed to wait for a submenus popper to be created before\n // attempting to set focus, however on a quick mount/unmount when\n // mousing past an item, the submenu could be unmounted before the\n // async rAF finishes, so it is cancelled in willUnmount()\n this.rAF = window.requestAnimationFrame(() => {\n this.container.current?.focus();\n\n const { onMenuOpened } = this.props;\n onMenuOpened(this);\n });\n }\n\n componentDidUpdate(\n prevProps: ContextMenuProps,\n prevState: ContextMenuState\n ): void {\n const { actions } = this.props;\n const { activeSubMenu } = this.state;\n\n if (activeSubMenu !== prevState.activeSubMenu) {\n if (activeSubMenu == null) {\n // close sub menu, refocus parent menu\n this.container.current?.focus();\n } else {\n // open sub menu, set its initial position\n this.setActiveSubMenuPosition();\n }\n }\n\n if (prevProps.actions !== actions) {\n this.initMenu();\n\n if (\n this.container.current == null ||\n !this.container.current.contains(document.activeElement)\n ) {\n this.container.current?.focus();\n }\n }\n\n this.verifyPosition();\n }\n\n componentWillUnmount(): void {\n this.cancelPromises();\n window.removeEventListener('resize', this.handleWindowResize);\n cancelAnimationFrame(this.rAF);\n }\n\n container: React.RefObject<HTMLDivElement>;\n\n oldFocus: Element | null;\n\n activeSubMenuRef: React.RefObject<HTMLDivElement>;\n\n subMenuTimer: number;\n\n rAF: number;\n\n initialPosition: { top: number; left: number };\n\n getKeyboardIndex(): number {\n const { options } = this.props;\n if (\n options.separateKeyboardMouse !== undefined &&\n options.separateKeyboardMouse\n ) {\n const { keyboardIndex } = this.state;\n return keyboardIndex;\n }\n\n return this.getMouseIndex();\n }\n\n setKeyboardIndex(index: number): void {\n const { options } = this.props;\n if (\n options.separateKeyboardMouse !== undefined &&\n options.separateKeyboardMouse\n ) {\n this.setState({ keyboardIndex: index });\n } else {\n this.setMouseIndex(index);\n }\n }\n\n getMouseIndex(): number {\n const { mouseIndex } = this.state;\n return mouseIndex;\n }\n\n setMouseIndex(index: number): void {\n this.setState({ mouseIndex: index });\n }\n\n initMenu(): void {\n // cancel any pending close and promises\n this.cancelPromises();\n cancelAnimationFrame(this.rAF);\n\n const { options } = this.props;\n let keyboardIndex = options.initialKeyboardIndex;\n if (keyboardIndex === undefined) {\n keyboardIndex = -1;\n }\n\n const { actions } = this.props;\n const menuItems = ContextActionUtils.getMenuItems(actions);\n const nonPromiseItems: ContextAction[] = [];\n for (let i = menuItems.length - 1; i >= 0; i -= 1) {\n const menuItem = menuItems[i];\n if (menuItem instanceof Promise) {\n this.initMenuPromise(menuItem as Promise<ContextAction[]>);\n } else {\n nonPromiseItems.push(menuItem as ContextAction);\n }\n }\n\n this.setState({\n mouseIndex: -1,\n keyboardIndex,\n activeSubMenu: null,\n menuItems: ContextActionUtils.sortActions(nonPromiseItems),\n });\n }\n\n initMenuPromise(promise: Promise<ContextAction[]>): void {\n // make all promises cancellable\n const cancellablePromise = PromiseUtils.makeCancelable(promise);\n\n this.setState(state => ({\n pendingItems: state.pendingItems.concat(cancellablePromise),\n }));\n\n cancellablePromise.then(\n resolvedMenuItems => {\n this.setState(state => {\n const index = state.pendingItems.indexOf(cancellablePromise);\n if (index >= 0) {\n const pendingItems = state.pendingItems.slice();\n pendingItems.splice(index, 1);\n\n return {\n menuItems: ContextActionUtils.sortActions(\n state.menuItems.concat(resolvedMenuItems)\n ),\n pendingItems,\n };\n }\n // This item is stale, don't update the menu\n return null;\n });\n },\n error => {\n if (PromiseUtils.isCanceled(error)) {\n return; // Canceled promise is ignored\n }\n\n // remove failed item from pending list\n this.setState(state => {\n const index = state.pendingItems.indexOf(cancellablePromise);\n if (index >= 0) {\n const pendingItems = state.pendingItems.slice();\n pendingItems.splice(index, 1);\n return {\n pendingItems,\n };\n }\n return null;\n });\n\n // Log the error\n log.error(error);\n }\n );\n }\n\n cancelPromises(): void {\n const { pendingItems } = this.state;\n pendingItems.map(item => item.cancel());\n }\n\n /**\n * Sets the unverfied start position of a submenu. Submenu then self-verfies\n * its own position and potentially reports back a new position.\n */\n setActiveSubMenuPosition(): void {\n if (this.activeSubMenuRef.current === null) return;\n const parentRect = this.activeSubMenuRef.current.getBoundingClientRect();\n\n // intentionally rect.right, we want the sub menu to start at the right edge of the current menu\n this.setState({\n subMenuTop: parentRect.top,\n subMenuLeft: parentRect.right,\n subMenuParentHeight: parentRect.height,\n subMenuParentWidth: parentRect.width,\n });\n }\n\n /**\n * Verifies the position of this menu in relation to the parent to make sure it's on screen.\n * Will update the top left state (updatePosition) if necessary (causing a re-render)\n * By default it tries to top-align with parent, at the right side of the parent.\n * Because we aren't a native context menu and can't escape window bounds, we also do\n * somethings to better fit on screen, such as the \"nudge\" offset position, and further\n * allow overflow scrolling for large menus in a small window.\n */\n verifyPosition(): void {\n const {\n options,\n updatePosition,\n subMenuParentWidth,\n subMenuParentHeight,\n top: oldTop,\n left: oldLeft,\n } = this.props;\n\n if (\n !this.container.current ||\n (options.doNotVerifyPosition != null && options.doNotVerifyPosition)\n ) {\n return;\n }\n\n // initial position is used rather than current position,\n // as the number of menu items can change (actions can bubble)\n // and menu should always be positioned relative to spawn point\n let { top, left } = this.initialPosition;\n const { width, height } =\n this.container.current?.getBoundingClientRect() ?? {\n width: 0,\n height: 0,\n };\n const hasOverflow =\n (this.container.current?.scrollHeight ?? 0) > window.innerHeight;\n\n if (height === 0 || width === 0) {\n // We don't have a height or width yet, don't bother doing anything\n return;\n }\n\n // does it fit below?\n if (top + height > window.innerHeight) {\n // can it be flipped to above? include offset if submenu (defaults to 0 if not submenu)\n if (top - height - subMenuParentHeight > 0) {\n // flip like a native menu would\n top -= height - subMenuParentHeight;\n } else {\n // still doesnt fit? okay, position at bottom edge\n top = window.innerHeight - height;\n }\n }\n\n if (left + width > window.innerWidth) {\n // less picky about left right positioning, just keep it going off to right\n left = left - width - subMenuParentWidth;\n }\n\n if (oldLeft !== left || oldTop !== top) {\n // parent owns positioning as single source of truth, ask to update props\n this.setState({ hasOverflow });\n updatePosition(top, left);\n }\n }\n\n // since window resize doesn't trigger blur, listen and close the menu\n handleWindowResize(): void {\n if (!this.container.current) {\n return;\n }\n this.closeMenu(true);\n }\n\n handleBlur(e: React.FocusEvent<HTMLDivElement>): void {\n if (!this.container.current) {\n log.warn('Container is null!');\n return;\n }\n\n if (!this.container.current.contains(e.relatedTarget as Node)) {\n let element: HTMLElement | null = e.relatedTarget as HTMLElement;\n let isContextMenuChild = false;\n while (element && !isContextMenuChild) {\n isContextMenuChild = element.hasAttribute('data-dh-context-menu');\n element = element.parentElement;\n }\n\n if (!isContextMenuChild) {\n // close all submenus on blur\n this.closeMenu(true);\n }\n }\n }\n\n /** Returns whether the specified key should remove the menu. Depends on the side the parent is on. */\n isEscapeKey(key: string): boolean {\n const { left } = this.props;\n return (\n key === 'Escape' ||\n (left < 0 && key === 'ArrowRight') ||\n key === 'ArrowLeft'\n );\n }\n\n handleKeyDown(e: React.KeyboardEvent<HTMLDivElement>): void {\n const { menuItems } = this.state;\n const oldFocus = this.getKeyboardIndex();\n let newFocus: number | null = oldFocus;\n let openSubMenu = false;\n\n if (e.key === 'Enter' || e.key === ' ') {\n if (oldFocus >= 0 && oldFocus < menuItems.length) {\n this.handleMenuItemClick(\n menuItems[oldFocus],\n e as React.SyntheticEvent as React.MouseEvent\n );\n }\n return;\n }\n\n if (e.key === 'ArrowRight') {\n if (oldFocus >= 0 && oldFocus <= menuItems.length) {\n openSubMenu = true;\n } else {\n newFocus = 0;\n }\n } else if (this.isEscapeKey(e.key)) {\n newFocus = null;\n } else if (e.key === 'ArrowUp' || (e.shiftKey && e.key === 'Tab')) {\n newFocus = ContextActionUtils.getNextMenuItem(newFocus, -1, menuItems);\n } else if (e.key === 'ArrowDown' || e.key === 'Tab') {\n newFocus = ContextActionUtils.getNextMenuItem(newFocus, 1, menuItems);\n }\n\n if (openSubMenu) {\n this.openSubMenu(oldFocus);\n e.preventDefault();\n e.stopPropagation();\n return;\n }\n\n if (oldFocus !== newFocus) {\n if (newFocus !== null) {\n this.setKeyboardIndex(newFocus);\n } else {\n this.closeMenu();\n if (this.oldFocus instanceof HTMLElement) {\n this.oldFocus.focus();\n }\n }\n\n e.preventDefault();\n e.stopPropagation();\n }\n }\n\n openSubMenu(index: number): void {\n const { menuItems, activeSubMenu } = this.state;\n const newSubMenu = menuItems[index].actions ? index : null;\n if (activeSubMenu === newSubMenu) return;\n this.setState({\n activeSubMenu: newSubMenu,\n subMenuTop: null,\n subMenuLeft: null,\n });\n }\n\n closeMenu(closeAll = false): void {\n const { closeMenu, onMenuClosed } = this.props;\n cancelAnimationFrame(this.rAF);\n this.rAF = window.requestAnimationFrame(() => {\n closeMenu(closeAll);\n onMenuClosed(this);\n });\n }\n\n closeSubMenu(): void {\n this.setState({\n activeSubMenu: null,\n });\n }\n\n handleCloseSubMenu(closeAllMenus: boolean): void {\n if (closeAllMenus) {\n this.closeMenu(true);\n } else {\n this.closeSubMenu();\n }\n }\n\n handleMenuItemClick(menuItem: ContextAction, e: React.MouseEvent): void {\n e.preventDefault();\n e.stopPropagation();\n\n const { menuItems } = this.state;\n if (\n menuItem != null &&\n (menuItem.disabled === undefined || !menuItem.disabled)\n ) {\n if (menuItem.actions != null) {\n this.openSubMenu(menuItems.indexOf(menuItem));\n } else if (menuItem.action != null) {\n menuItem.action();\n this.closeMenu(true);\n }\n }\n }\n\n handleMenuItemContextMenu(\n menuItem: ContextAction,\n e: React.MouseEvent\n ): void {\n if (e.metaKey) {\n return;\n }\n\n this.handleMenuItemClick(menuItem, e);\n }\n\n handleMenuItemMouseMove(menuItem: ContextAction): void {\n const { menuItems } = this.state;\n const focusIndex = menuItems.indexOf(menuItem);\n this.setMouseIndex(focusIndex);\n\n if (\n focusIndex >= 0 &&\n focusIndex < menuItems.length &&\n (menuItem.disabled === undefined || !menuItem.disabled)\n ) {\n this.openSubMenu(focusIndex);\n }\n }\n\n handleMouseLeave(): void {\n this.setMouseIndex(-1);\n }\n\n render(): JSX.Element {\n const menuItemElements = [];\n const { top, left } = this.props;\n const {\n activeSubMenu,\n hasOverflow,\n keyboardIndex,\n menuItems,\n mouseIndex,\n pendingItems,\n subMenuTop,\n subMenuLeft,\n subMenuParentWidth,\n subMenuParentHeight,\n } = this.state;\n for (let i = 0; i < menuItems.length; i += 1) {\n const menuItem = menuItems[i];\n\n if (i > 0 && menuItem.group !== menuItems[i - 1].group) {\n menuItemElements.push(<hr key={`${i}.separator`} />);\n }\n\n const menuItemElement = (\n <ContextMenuItem\n key={i}\n ref={activeSubMenu === i ? this.activeSubMenuRef : null}\n isKeyboardSelected={keyboardIndex === i}\n isMouseSelected={mouseIndex === i}\n menuItem={menuItem}\n closeMenu={this.handleCloseSubMenu}\n onMenuItemClick={this.handleMenuItemClick}\n onMenuItemMouseMove={this.handleMenuItemMouseMove}\n onMenuItemContextMenu={this.handleMenuItemContextMenu}\n />\n );\n\n menuItemElements.push(menuItemElement);\n }\n\n let pendingElement = null;\n if (pendingItems.length > 0) {\n pendingElement = (\n <div className=\"loading\">\n <LoadingSpinner />\n </div>\n );\n }\n\n const { menuStyle, 'data-testid': dataTestId } = this.props;\n\n // don't show submenu until it has an position initialized\n const showSubmenu =\n activeSubMenu !== null && subMenuTop !== null && subMenuLeft !== null;\n\n return (\n <>\n <div\n className={classNames(\n { 'has-overflow': hasOverflow },\n 'context-menu-container'\n )}\n style={{ top, left, ...menuStyle }}\n ref={this.container}\n data-dh-context-menu\n onBlur={this.handleBlur}\n onKeyDown={this.handleKeyDown}\n onMouseLeave={this.handleMouseLeave}\n onContextMenu={ContextMenu.handleContextMenu}\n role=\"menuitem\"\n tabIndex={0}\n data-testid={dataTestId}\n >\n {menuItemElements}\n {pendingElement}\n </div>\n {showSubmenu &&\n activeSubMenu !== null &&\n subMenuTop !== null &&\n subMenuLeft !== null && (\n <ContextMenu\n key={`sub-${activeSubMenu}`}\n actions={menuItems[activeSubMenu].actions || []}\n closeMenu={this.handleCloseSubMenu}\n top={subMenuTop}\n left={subMenuLeft}\n updatePosition={(verifiedTop, verifiedLeft) => {\n this.setState({\n subMenuTop: verifiedTop,\n subMenuLeft: verifiedLeft,\n });\n }}\n subMenuParentWidth={subMenuParentWidth}\n subMenuParentHeight={subMenuParentHeight}\n />\n )}\n </>\n );\n }\n}\n\nexport default ContextMenu;\n"],"mappings":"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"}
|
|
@@ -2,6 +2,8 @@ import React from 'react';
|
|
|
2
2
|
import classNames from 'classnames';
|
|
3
3
|
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
|
4
4
|
import { vsChevronRight } from '@deephaven/icons';
|
|
5
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
6
|
+
import { jsxs as _jsxs } from "react/jsx-runtime";
|
|
5
7
|
var ContextMenuItem = /*#__PURE__*/React.forwardRef((props, ref) => {
|
|
6
8
|
var _menuItem$shortcut;
|
|
7
9
|
function handleMenuItemClick(e) {
|
|
@@ -70,7 +72,7 @@ var ContextMenuItem = /*#__PURE__*/React.forwardRef((props, ref) => {
|
|
|
70
72
|
color: menuItem.iconColor
|
|
71
73
|
};
|
|
72
74
|
}
|
|
73
|
-
icon = /*#__PURE__*/
|
|
75
|
+
icon = /*#__PURE__*/_jsx(FontAwesomeIcon, {
|
|
74
76
|
icon: menuItemIcon,
|
|
75
77
|
style: style
|
|
76
78
|
});
|
|
@@ -79,21 +81,22 @@ var ContextMenuItem = /*#__PURE__*/React.forwardRef((props, ref) => {
|
|
|
79
81
|
var subMenuIndicator = null;
|
|
80
82
|
var isSubMenuActive = Boolean(children);
|
|
81
83
|
if (menuItem.actions) {
|
|
82
|
-
subMenuIndicator = /*#__PURE__*/
|
|
84
|
+
subMenuIndicator = /*#__PURE__*/_jsx(FontAwesomeIcon, {
|
|
83
85
|
icon: vsChevronRight
|
|
84
86
|
});
|
|
85
87
|
}
|
|
86
88
|
var content = null;
|
|
87
89
|
if (menuItem.menuElement) {
|
|
88
|
-
content = /*#__PURE__*/
|
|
90
|
+
content = /*#__PURE__*/_jsx("div", {
|
|
89
91
|
className: "custom-menu-item",
|
|
90
|
-
onMouseMove: handleMenuItemMouseMove
|
|
91
|
-
|
|
92
|
+
onMouseMove: handleMenuItemMouseMove,
|
|
93
|
+
children: renderCustomMenuElement(menuItem.menuElement, icon, displayShortcut)
|
|
94
|
+
});
|
|
92
95
|
} else {
|
|
93
96
|
var _menuItem$description;
|
|
94
97
|
var menuItemDisabled = menuItem.disabled;
|
|
95
98
|
var iconHasOutline = menuItem.iconOutline;
|
|
96
|
-
content = /*#__PURE__*/
|
|
99
|
+
content = /*#__PURE__*/_jsx("button", {
|
|
97
100
|
type: "button",
|
|
98
101
|
className: classNames('btn-context-menu', {
|
|
99
102
|
disabled: menuItemDisabled
|
|
@@ -105,28 +108,35 @@ var ContextMenuItem = /*#__PURE__*/React.forwardRef((props, ref) => {
|
|
|
105
108
|
onClick: handleMenuItemClick,
|
|
106
109
|
onMouseMove: handleMenuItemMouseMove,
|
|
107
110
|
onContextMenu: handleMenuItemContextMenu,
|
|
108
|
-
title: (_menuItem$description = menuItem.description) !== null && _menuItem$description !== void 0 ? _menuItem$description : ''
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
111
|
+
title: (_menuItem$description = menuItem.description) !== null && _menuItem$description !== void 0 ? _menuItem$description : '',
|
|
112
|
+
children: /*#__PURE__*/_jsxs("div", {
|
|
113
|
+
className: "btn-context-menu-wrapper",
|
|
114
|
+
children: [/*#__PURE__*/_jsx("span", {
|
|
115
|
+
className: classNames('icon', {
|
|
116
|
+
outline: iconHasOutline
|
|
117
|
+
}),
|
|
118
|
+
children: icon
|
|
119
|
+
}), /*#__PURE__*/_jsx("span", {
|
|
120
|
+
className: "title",
|
|
121
|
+
children: menuItem.title
|
|
122
|
+
}), displayShortcut !== undefined && /*#__PURE__*/_jsx("span", {
|
|
123
|
+
className: "shortcut",
|
|
124
|
+
children: displayShortcut
|
|
125
|
+
}), subMenuIndicator && /*#__PURE__*/_jsx("span", {
|
|
126
|
+
className: classNames('submenu-indicator', {
|
|
127
|
+
disabled: menuItemDisabled
|
|
128
|
+
}),
|
|
129
|
+
children: subMenuIndicator
|
|
130
|
+
})]
|
|
114
131
|
})
|
|
115
|
-
}
|
|
116
|
-
className: "title"
|
|
117
|
-
}, menuItem.title), displayShortcut !== undefined && /*#__PURE__*/React.createElement("span", {
|
|
118
|
-
className: "shortcut"
|
|
119
|
-
}, displayShortcut), subMenuIndicator && /*#__PURE__*/React.createElement("span", {
|
|
120
|
-
className: classNames('submenu-indicator', {
|
|
121
|
-
disabled: menuItemDisabled
|
|
122
|
-
})
|
|
123
|
-
}, subMenuIndicator)));
|
|
132
|
+
});
|
|
124
133
|
}
|
|
125
|
-
return /*#__PURE__*/
|
|
134
|
+
return /*#__PURE__*/_jsxs("div", {
|
|
126
135
|
className: "context-menu-item",
|
|
127
136
|
ref: ref,
|
|
128
|
-
"data-testid": dataTestId
|
|
129
|
-
|
|
137
|
+
"data-testid": dataTestId,
|
|
138
|
+
children: [children, content]
|
|
139
|
+
});
|
|
130
140
|
});
|
|
131
141
|
ContextMenuItem.displayName = 'ContextMenuItem';
|
|
132
142
|
ContextMenuItem.defaultProps = {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ContextMenuItem.js","names":["React","classNames","FontAwesomeIcon","vsChevronRight","ContextMenuItem","forwardRef","props","ref","handleMenuItemClick","e","menuItem","onMenuItemClick","handleMenuItemMouseMove","onMenuItemMouseMove","handleMenuItemContextMenu","onMenuItemContextMenu","renderCustomMenuElement","element","iconElement","displayShortcut","type","closeMenu","isKeyboardSelected","isMouseSelected","dataTestId","forwardedProps","cloneElement","children","shortcut","getDisplayText","icon","menuItemIcon","isValidElement","style","iconColor","disabled","undefined","color","subMenuIndicator","isSubMenuActive","Boolean","actions","content","menuElement","menuItemDisabled","iconHasOutline","iconOutline","active","description","outline","title","displayName","defaultProps"],"sources":["../../src/context-actions/ContextMenuItem.tsx"],"sourcesContent":["import React from 'react';\nimport classNames from 'classnames';\nimport { FontAwesomeIcon } from '@fortawesome/react-fontawesome';\nimport { vsChevronRight, IconDefinition } from '@deephaven/icons';\nimport type { ContextAction } from './ContextActionUtils';\n\ninterface ContextMenuItemProps {\n children?: React.ReactNode;\n closeMenu(closeAll: boolean): void;\n isKeyboardSelected?: boolean;\n isMouseSelected?: boolean;\n menuItem: ContextAction;\n onMenuItemClick(item: ContextAction, e: React.MouseEvent): void;\n onMenuItemMouseMove(item: ContextAction, e: React.MouseEvent): void;\n onMenuItemContextMenu(item: ContextAction, e: React.MouseEvent): void;\n 'data-testid'?: string;\n}\n\nconst ContextMenuItem = React.forwardRef<HTMLDivElement, ContextMenuItemProps>(\n (props: ContextMenuItemProps, ref) => {\n function handleMenuItemClick(e: React.MouseEvent) {\n const { menuItem, onMenuItemClick } = props;\n onMenuItemClick(menuItem, e);\n }\n\n function handleMenuItemMouseMove(e: React.MouseEvent) {\n const { menuItem, onMenuItemMouseMove } = props;\n onMenuItemMouseMove(menuItem, e);\n }\n\n function handleMenuItemContextMenu(e: React.MouseEvent) {\n const { menuItem, onMenuItemContextMenu } = props;\n onMenuItemContextMenu(menuItem, e);\n }\n\n function renderCustomMenuElement(\n element: React.ReactElement,\n iconElement: IconDefinition | React.ReactElement | null,\n displayShortcut: string | undefined\n ): JSX.Element {\n // Don't pass forwardedProps if menuElement is a native DOM node\n if (typeof element.type === 'string') {\n return element;\n }\n const {\n closeMenu,\n menuItem,\n isKeyboardSelected,\n isMouseSelected,\n 'data-testid': dataTestId,\n } = props;\n const forwardedProps = {\n menuItem,\n closeMenu,\n isKeyboardSelected,\n isMouseSelected,\n iconElement,\n displayShortcut,\n 'data-testid': dataTestId,\n };\n return React.cloneElement(element, {\n forwardedProps,\n });\n }\n\n const {\n children,\n menuItem,\n isKeyboardSelected = false,\n isMouseSelected = false,\n 'data-testid': dataTestId,\n } = props;\n\n const displayShortcut = menuItem.shortcut?.getDisplayText();\n let icon: IconDefinition | React.ReactElement | null = null;\n if (menuItem.icon) {\n const menuItemIcon = menuItem.icon;\n if (React.isValidElement(menuItemIcon)) {\n icon = menuItemIcon;\n } else {\n let style: React.CSSProperties | undefined;\n if (\n menuItem.iconColor != null &&\n (menuItem.disabled === undefined || !menuItem.disabled)\n ) {\n style = { color: menuItem.iconColor };\n }\n icon = <FontAwesomeIcon icon={menuItemIcon} style={style} />;\n }\n }\n\n let subMenuIndicator = null;\n const isSubMenuActive = Boolean(children);\n if (menuItem.actions) {\n subMenuIndicator = <FontAwesomeIcon icon={vsChevronRight} />;\n }\n let content = null;\n if (menuItem.menuElement) {\n content = (\n <div className=\"custom-menu-item\" onMouseMove={handleMenuItemMouseMove}>\n {renderCustomMenuElement(menuItem.menuElement, icon, displayShortcut)}\n </div>\n );\n } else {\n const menuItemDisabled = menuItem.disabled;\n const iconHasOutline = menuItem.iconOutline;\n content = (\n <button\n type=\"button\"\n className={classNames(\n 'btn-context-menu',\n { disabled: menuItemDisabled },\n {\n active:\n (isSubMenuActive || isMouseSelected) &&\n (menuItemDisabled === undefined || !menuItemDisabled),\n },\n {\n 'keyboard-active':\n isKeyboardSelected &&\n (menuItemDisabled === undefined || !menuItemDisabled),\n }\n )}\n onClick={handleMenuItemClick}\n onMouseMove={handleMenuItemMouseMove}\n onContextMenu={handleMenuItemContextMenu}\n title={menuItem.description ?? ''}\n >\n <div className=\"btn-context-menu-wrapper\">\n <span className={classNames('icon', { outline: iconHasOutline })}>\n {icon}\n </span>\n <span className=\"title\">{menuItem.title}</span>\n {displayShortcut !== undefined && (\n <span className=\"shortcut\">{displayShortcut}</span>\n )}\n {subMenuIndicator && (\n <span\n className={classNames('submenu-indicator', {\n disabled: menuItemDisabled,\n })}\n >\n {subMenuIndicator}\n </span>\n )}\n </div>\n </button>\n );\n }\n\n return (\n <div className=\"context-menu-item\" ref={ref} data-testid={dataTestId}>\n {children}\n {content}\n </div>\n );\n }\n);\n\nContextMenuItem.displayName = 'ContextMenuItem';\n\nContextMenuItem.defaultProps = {\n children: null,\n isKeyboardSelected: false,\n isMouseSelected: false,\n 'data-testid': undefined,\n};\n\nexport default ContextMenuItem;\n"],"mappings":"AAAA,OAAOA,KAAK,MAAM,OAAO;AACzB,OAAOC,UAAU,MAAM,YAAY;AACnC,SAASC,eAAe,QAAQ,gCAAgC;AAChE,SAASC,cAAc,QAAwB,kBAAkB;
|
|
1
|
+
{"version":3,"file":"ContextMenuItem.js","names":["React","classNames","FontAwesomeIcon","vsChevronRight","ContextMenuItem","forwardRef","props","ref","handleMenuItemClick","e","menuItem","onMenuItemClick","handleMenuItemMouseMove","onMenuItemMouseMove","handleMenuItemContextMenu","onMenuItemContextMenu","renderCustomMenuElement","element","iconElement","displayShortcut","type","closeMenu","isKeyboardSelected","isMouseSelected","dataTestId","forwardedProps","cloneElement","children","shortcut","getDisplayText","icon","menuItemIcon","isValidElement","style","iconColor","disabled","undefined","color","subMenuIndicator","isSubMenuActive","Boolean","actions","content","menuElement","menuItemDisabled","iconHasOutline","iconOutline","active","description","outline","title","displayName","defaultProps"],"sources":["../../src/context-actions/ContextMenuItem.tsx"],"sourcesContent":["import React from 'react';\nimport classNames from 'classnames';\nimport { FontAwesomeIcon } from '@fortawesome/react-fontawesome';\nimport { vsChevronRight, IconDefinition } from '@deephaven/icons';\nimport type { ContextAction } from './ContextActionUtils';\n\ninterface ContextMenuItemProps {\n children?: React.ReactNode;\n closeMenu(closeAll: boolean): void;\n isKeyboardSelected?: boolean;\n isMouseSelected?: boolean;\n menuItem: ContextAction;\n onMenuItemClick(item: ContextAction, e: React.MouseEvent): void;\n onMenuItemMouseMove(item: ContextAction, e: React.MouseEvent): void;\n onMenuItemContextMenu(item: ContextAction, e: React.MouseEvent): void;\n 'data-testid'?: string;\n}\n\nconst ContextMenuItem = React.forwardRef<HTMLDivElement, ContextMenuItemProps>(\n (props: ContextMenuItemProps, ref) => {\n function handleMenuItemClick(e: React.MouseEvent) {\n const { menuItem, onMenuItemClick } = props;\n onMenuItemClick(menuItem, e);\n }\n\n function handleMenuItemMouseMove(e: React.MouseEvent) {\n const { menuItem, onMenuItemMouseMove } = props;\n onMenuItemMouseMove(menuItem, e);\n }\n\n function handleMenuItemContextMenu(e: React.MouseEvent) {\n const { menuItem, onMenuItemContextMenu } = props;\n onMenuItemContextMenu(menuItem, e);\n }\n\n function renderCustomMenuElement(\n element: React.ReactElement,\n iconElement: IconDefinition | React.ReactElement | null,\n displayShortcut: string | undefined\n ): JSX.Element {\n // Don't pass forwardedProps if menuElement is a native DOM node\n if (typeof element.type === 'string') {\n return element;\n }\n const {\n closeMenu,\n menuItem,\n isKeyboardSelected,\n isMouseSelected,\n 'data-testid': dataTestId,\n } = props;\n const forwardedProps = {\n menuItem,\n closeMenu,\n isKeyboardSelected,\n isMouseSelected,\n iconElement,\n displayShortcut,\n 'data-testid': dataTestId,\n };\n return React.cloneElement(element, {\n forwardedProps,\n });\n }\n\n const {\n children,\n menuItem,\n isKeyboardSelected = false,\n isMouseSelected = false,\n 'data-testid': dataTestId,\n } = props;\n\n const displayShortcut = menuItem.shortcut?.getDisplayText();\n let icon: IconDefinition | React.ReactElement | null = null;\n if (menuItem.icon) {\n const menuItemIcon = menuItem.icon;\n if (React.isValidElement(menuItemIcon)) {\n icon = menuItemIcon;\n } else {\n let style: React.CSSProperties | undefined;\n if (\n menuItem.iconColor != null &&\n (menuItem.disabled === undefined || !menuItem.disabled)\n ) {\n style = { color: menuItem.iconColor };\n }\n icon = <FontAwesomeIcon icon={menuItemIcon} style={style} />;\n }\n }\n\n let subMenuIndicator = null;\n const isSubMenuActive = Boolean(children);\n if (menuItem.actions) {\n subMenuIndicator = <FontAwesomeIcon icon={vsChevronRight} />;\n }\n let content = null;\n if (menuItem.menuElement) {\n content = (\n <div className=\"custom-menu-item\" onMouseMove={handleMenuItemMouseMove}>\n {renderCustomMenuElement(menuItem.menuElement, icon, displayShortcut)}\n </div>\n );\n } else {\n const menuItemDisabled = menuItem.disabled;\n const iconHasOutline = menuItem.iconOutline;\n content = (\n <button\n type=\"button\"\n className={classNames(\n 'btn-context-menu',\n { disabled: menuItemDisabled },\n {\n active:\n (isSubMenuActive || isMouseSelected) &&\n (menuItemDisabled === undefined || !menuItemDisabled),\n },\n {\n 'keyboard-active':\n isKeyboardSelected &&\n (menuItemDisabled === undefined || !menuItemDisabled),\n }\n )}\n onClick={handleMenuItemClick}\n onMouseMove={handleMenuItemMouseMove}\n onContextMenu={handleMenuItemContextMenu}\n title={menuItem.description ?? ''}\n >\n <div className=\"btn-context-menu-wrapper\">\n <span className={classNames('icon', { outline: iconHasOutline })}>\n {icon}\n </span>\n <span className=\"title\">{menuItem.title}</span>\n {displayShortcut !== undefined && (\n <span className=\"shortcut\">{displayShortcut}</span>\n )}\n {subMenuIndicator && (\n <span\n className={classNames('submenu-indicator', {\n disabled: menuItemDisabled,\n })}\n >\n {subMenuIndicator}\n </span>\n )}\n </div>\n </button>\n );\n }\n\n return (\n <div className=\"context-menu-item\" ref={ref} data-testid={dataTestId}>\n {children}\n {content}\n </div>\n );\n }\n);\n\nContextMenuItem.displayName = 'ContextMenuItem';\n\nContextMenuItem.defaultProps = {\n children: null,\n isKeyboardSelected: false,\n isMouseSelected: false,\n 'data-testid': undefined,\n};\n\nexport default ContextMenuItem;\n"],"mappings":"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"}
|
|
@@ -5,6 +5,7 @@ import React, { Component } from 'react';
|
|
|
5
5
|
import classNames from 'classnames';
|
|
6
6
|
import ContextMenu from "./ContextMenu.js";
|
|
7
7
|
import ContextActionUtils from "./ContextActionUtils.js";
|
|
8
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
8
9
|
/**
|
|
9
10
|
* Put at your root container, any contextmenu events that are unhandled in the root container will be handled by this
|
|
10
11
|
*/
|
|
@@ -108,7 +109,7 @@ class ContextMenuRoot extends Component {
|
|
|
108
109
|
left
|
|
109
110
|
} = this.state;
|
|
110
111
|
if (actions) {
|
|
111
|
-
menu = /*#__PURE__*/
|
|
112
|
+
menu = /*#__PURE__*/_jsx(ContextMenu, {
|
|
112
113
|
ref: this.openMenu,
|
|
113
114
|
actions: actions,
|
|
114
115
|
onMenuClosed: this.handleMenuClose,
|
|
@@ -123,12 +124,13 @@ class ContextMenuRoot extends Component {
|
|
|
123
124
|
"data-testid": dataTestId
|
|
124
125
|
});
|
|
125
126
|
}
|
|
126
|
-
return /*#__PURE__*/
|
|
127
|
+
return /*#__PURE__*/_jsx("div", {
|
|
127
128
|
className: classNames('context-menu-root', {
|
|
128
129
|
active: actions
|
|
129
130
|
}),
|
|
130
|
-
ref: this.container
|
|
131
|
-
|
|
131
|
+
ref: this.container,
|
|
132
|
+
children: menu
|
|
133
|
+
});
|
|
132
134
|
}
|
|
133
135
|
}
|
|
134
136
|
export default ContextMenuRoot;
|