@deephaven/components 0.43.0 → 0.44.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/AutoCompleteInput.css +35 -0
- package/dist/AutoCompleteInput.css.map +1 -0
- package/dist/AutoCompleteInput.js +496 -0
- package/dist/AutoCompleteInput.js.map +1 -0
- package/dist/AutoResizeTextarea.css +11 -0
- package/dist/AutoResizeTextarea.css.map +1 -0
- package/dist/AutoResizeTextarea.js +128 -0
- package/dist/AutoResizeTextarea.js.map +1 -0
- package/dist/BasicModal.js +112 -0
- package/dist/BasicModal.js.map +1 -0
- package/dist/Button.d.ts +1 -1
- package/dist/Button.js +193 -0
- package/dist/Button.js.map +1 -0
- package/dist/ButtonGroup.js +31 -0
- package/dist/ButtonGroup.js.map +1 -0
- package/dist/ButtonOld.js +41 -0
- package/dist/ButtonOld.js.map +1 -0
- package/dist/CardFlip.css +36 -0
- package/dist/CardFlip.css.map +1 -0
- package/dist/CardFlip.js +61 -0
- package/dist/CardFlip.js.map +1 -0
- package/dist/Checkbox.js +104 -0
- package/dist/Checkbox.js.map +1 -0
- package/dist/Collapse.js +89 -0
- package/dist/Collapse.js.map +1 -0
- package/dist/ComboBox.css +50 -0
- package/dist/ComboBox.css.map +1 -0
- package/dist/ComboBox.js +487 -0
- package/dist/ComboBox.js.map +1 -0
- package/dist/CopyButton.js +30 -0
- package/dist/CopyButton.js.map +1 -0
- package/dist/CustomTimeSelect.css +65 -0
- package/dist/CustomTimeSelect.css.map +1 -0
- package/dist/CustomTimeSelect.js +516 -0
- package/dist/CustomTimeSelect.js.map +1 -0
- package/dist/DateInput.js +54 -0
- package/dist/DateInput.js.map +1 -0
- package/dist/DateInputUtils.js +33 -0
- package/dist/DateInputUtils.js.map +1 -0
- package/dist/DateTimeInput.js +84 -0
- package/dist/DateTimeInput.js.map +1 -0
- package/dist/DateTimeInputUtils.js +8 -0
- package/dist/DateTimeInputUtils.js.map +1 -0
- package/dist/DebouncedSearchInput.js +79 -0
- package/dist/DebouncedSearchInput.js.map +1 -0
- package/dist/DragUtils.js +68 -0
- package/dist/DragUtils.js.map +1 -0
- package/dist/DraggableItemList.css +118 -0
- package/dist/DraggableItemList.css.map +1 -0
- package/dist/DraggableItemList.js +268 -0
- package/dist/DraggableItemList.js.map +1 -0
- package/dist/EditableItemList.js +105 -0
- package/dist/EditableItemList.js.map +1 -0
- package/dist/HierarchicalCheckboxMenu.css +30 -0
- package/dist/HierarchicalCheckboxMenu.css.map +1 -0
- package/dist/HierarchicalCheckboxMenu.js +218 -0
- package/dist/HierarchicalCheckboxMenu.js.map +1 -0
- package/dist/ItemList.css +13 -0
- package/dist/ItemList.css.map +1 -0
- package/dist/ItemList.js +686 -0
- package/dist/ItemList.js.map +1 -0
- package/dist/ItemListItem.css +48 -0
- package/dist/ItemListItem.css.map +1 -0
- package/dist/ItemListItem.js +214 -0
- package/dist/ItemListItem.js.map +1 -0
- package/dist/LoadingOverlay.css +24 -0
- package/dist/LoadingOverlay.css.map +1 -0
- package/dist/LoadingOverlay.js +48 -0
- package/dist/LoadingOverlay.js.map +1 -0
- package/dist/LoadingSpinner.css +8 -0
- package/dist/LoadingSpinner.css.map +1 -0
- package/dist/LoadingSpinner.js +24 -0
- package/dist/LoadingSpinner.js.map +1 -0
- package/dist/MaskedInput.css +7 -0
- package/dist/MaskedInput.css.map +1 -0
- package/dist/MaskedInput.js +394 -0
- package/dist/MaskedInput.js.map +1 -0
- package/dist/MaskedInputUtils.js +36 -0
- package/dist/MaskedInputUtils.js.map +1 -0
- package/dist/Option.js +16 -0
- package/dist/Option.js.map +1 -0
- package/dist/RadioGroup.js +34 -0
- package/dist/RadioGroup.js.map +1 -0
- package/dist/RadioItem.js +55 -0
- package/dist/RadioItem.js.map +1 -0
- package/dist/RandomAreaPlotAnimation.css +18 -0
- package/dist/RandomAreaPlotAnimation.css.map +1 -0
- package/dist/RandomAreaPlotAnimation.js +290 -0
- package/dist/RandomAreaPlotAnimation.js.map +1 -0
- package/dist/SearchInput.css +43 -0
- package/dist/SearchInput.css.map +1 -0
- package/dist/SearchInput.js +66 -0
- package/dist/SearchInput.js.map +1 -0
- package/dist/Select.js +30 -0
- package/dist/Select.js.map +1 -0
- package/dist/SelectValueList.css +38 -0
- package/dist/SelectValueList.css.map +1 -0
- package/dist/SelectValueList.js +175 -0
- package/dist/SelectValueList.js.map +1 -0
- package/dist/SocketedButton.css +123 -0
- package/dist/SocketedButton.css.map +1 -0
- package/dist/SocketedButton.js +63 -0
- package/dist/SocketedButton.js.map +1 -0
- package/dist/SpectrumThemeDark.module.css +9 -0
- package/dist/SpectrumThemeDark.module.css.map +1 -0
- package/dist/SpectrumThemeLight.module.css +9 -0
- package/dist/SpectrumThemeLight.module.css.map +1 -0
- package/dist/SpectrumUtils.js +59 -0
- package/dist/SpectrumUtils.js.map +1 -0
- package/dist/ThemeExport.js +15 -0
- package/dist/ThemeExport.js.map +1 -0
- package/dist/ThemeExport.module.css +40 -0
- package/dist/ThemeExport.module.css.map +1 -0
- package/dist/TimeInput.js +101 -0
- package/dist/TimeInput.js.map +1 -0
- package/dist/TimeSlider.css +178 -0
- package/dist/TimeSlider.css.map +1 -0
- package/dist/TimeSlider.js +314 -0
- package/dist/TimeSlider.js.map +1 -0
- package/dist/TimeSlider.module.css +185 -0
- package/dist/TimeSlider.module.css.map +1 -0
- package/dist/ToastNotification.css +62 -0
- package/dist/ToastNotification.css.map +1 -0
- package/dist/ToastNotification.js +56 -0
- package/dist/ToastNotification.js.map +1 -0
- package/dist/UISwitch.css +94 -0
- package/dist/UISwitch.css.map +1 -0
- package/dist/UISwitch.js +30 -0
- package/dist/UISwitch.js.map +1 -0
- package/dist/ValidateLabelInput.css +9 -0
- package/dist/ValidateLabelInput.css.map +1 -0
- package/dist/ValidateLabelInput.js +50 -0
- package/dist/ValidateLabelInput.js.map +1 -0
- package/dist/context-actions/ContextActionUtils.js +142 -0
- package/dist/context-actions/ContextActionUtils.js.map +1 -0
- package/dist/context-actions/ContextActions.css +157 -0
- package/dist/context-actions/ContextActions.css.map +1 -0
- package/dist/context-actions/ContextActions.js +182 -0
- package/dist/context-actions/ContextActions.js.map +1 -0
- package/dist/context-actions/ContextMenu.js +559 -0
- package/dist/context-actions/ContextMenu.js.map +1 -0
- package/dist/context-actions/ContextMenuItem.js +139 -0
- package/dist/context-actions/ContextMenuItem.js.map +1 -0
- package/dist/context-actions/ContextMenuRoot.js +135 -0
- package/dist/context-actions/ContextMenuRoot.js.map +1 -0
- package/dist/context-actions/GlobalContextAction.js +53 -0
- package/dist/context-actions/GlobalContextAction.js.map +1 -0
- package/dist/context-actions/GlobalContextActions.js +28 -0
- package/dist/context-actions/GlobalContextActions.js.map +1 -0
- package/dist/context-actions/index.js +5 -0
- package/dist/context-actions/index.js.map +1 -0
- package/dist/declaration.d.js +2 -0
- package/dist/declaration.d.js.map +1 -0
- package/dist/index.js +52 -0
- package/dist/index.js.map +1 -0
- package/dist/menu-actions/DropdownMenu.css +39 -0
- package/dist/menu-actions/DropdownMenu.css.map +1 -0
- package/dist/menu-actions/DropdownMenu.js +174 -0
- package/dist/menu-actions/DropdownMenu.js.map +1 -0
- package/dist/menu-actions/Menu.js +244 -0
- package/dist/menu-actions/Menu.js.map +1 -0
- package/dist/menu-actions/index.js +4 -0
- package/dist/menu-actions/index.js.map +1 -0
- package/dist/modal/DebouncedModal.js +26 -0
- package/dist/modal/DebouncedModal.js.map +1 -0
- package/dist/modal/InfoModal.css +24 -0
- package/dist/modal/InfoModal.css.map +1 -0
- package/dist/modal/InfoModal.js +34 -0
- package/dist/modal/InfoModal.js.map +1 -0
- package/dist/modal/Modal.js +122 -0
- package/dist/modal/Modal.js.map +1 -0
- package/dist/modal/ModalBody.js +16 -0
- package/dist/modal/ModalBody.js.map +1 -0
- package/dist/modal/ModalFooter.js +14 -0
- package/dist/modal/ModalFooter.js.map +1 -0
- package/dist/modal/ModalHeader.js +27 -0
- package/dist/modal/ModalHeader.js.map +1 -0
- package/dist/modal/index.js +7 -0
- package/dist/modal/index.js.map +1 -0
- package/dist/navigation/Menu.css +13 -0
- package/dist/navigation/Menu.css.map +1 -0
- package/dist/navigation/Menu.js +25 -0
- package/dist/navigation/Menu.js.map +1 -0
- package/dist/navigation/MenuItem.css +46 -0
- package/dist/navigation/MenuItem.css.map +1 -0
- package/dist/navigation/MenuItem.js +65 -0
- package/dist/navigation/MenuItem.js.map +1 -0
- package/dist/navigation/Page.css +34 -0
- package/dist/navigation/Page.css.map +1 -0
- package/dist/navigation/Page.js +46 -0
- package/dist/navigation/Page.js.map +1 -0
- package/dist/navigation/Stack.css +24 -0
- package/dist/navigation/Stack.css.map +1 -0
- package/dist/navigation/Stack.js +82 -0
- package/dist/navigation/Stack.js.map +1 -0
- package/dist/navigation/index.js +5 -0
- package/dist/navigation/index.js.map +1 -0
- package/dist/popper/Popper.css +127 -0
- package/dist/popper/Popper.css.map +1 -0
- package/dist/popper/Popper.js +283 -0
- package/dist/popper/Popper.js.map +1 -0
- package/dist/popper/Tooltip.js +283 -0
- package/dist/popper/Tooltip.js.map +1 -0
- package/dist/popper/index.js +3 -0
- package/dist/popper/index.js.map +1 -0
- package/dist/shortcuts/GlobalShortcuts.js +47 -0
- package/dist/shortcuts/GlobalShortcuts.js.map +1 -0
- package/dist/shortcuts/Shortcut.js +393 -0
- package/dist/shortcuts/Shortcut.js.map +1 -0
- package/dist/shortcuts/ShortcutRegistry.js +78 -0
- package/dist/shortcuts/ShortcutRegistry.js.map +1 -0
- package/dist/shortcuts/index.js +5 -0
- package/dist/shortcuts/index.js.map +1 -0
- package/package.json +7 -7
|
@@ -0,0 +1,559 @@
|
|
|
1
|
+
function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); enumerableOnly && (symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; })), keys.push.apply(keys, symbols); } return keys; }
|
|
2
|
+
function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = null != arguments[i] ? arguments[i] : {}; i % 2 ? ownKeys(Object(source), !0).forEach(function (key) { _defineProperty(target, key, source[key]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)) : ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } return target; }
|
|
3
|
+
function _defineProperty(obj, key, value) { key = _toPropertyKey(key); if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
|
|
4
|
+
function _toPropertyKey(arg) { var key = _toPrimitive(arg, "string"); return typeof key === "symbol" ? key : String(key); }
|
|
5
|
+
function _toPrimitive(input, hint) { if (typeof input !== "object" || input === null) return input; var prim = input[Symbol.toPrimitive]; if (prim !== undefined) { var res = prim.call(input, hint || "default"); if (typeof res !== "object") return res; throw new TypeError("@@toPrimitive must return a primitive value."); } return (hint === "string" ? String : Number)(input); }
|
|
6
|
+
import React, { PureComponent } from 'react';
|
|
7
|
+
import classNames from 'classnames';
|
|
8
|
+
import Log from '@deephaven/log';
|
|
9
|
+
import { PromiseUtils } from '@deephaven/utils';
|
|
10
|
+
import ContextActionUtils from "./ContextActionUtils.js";
|
|
11
|
+
import ContextMenuItem from "./ContextMenuItem.js";
|
|
12
|
+
import LoadingSpinner from "../LoadingSpinner.js";
|
|
13
|
+
var log = Log.module('ContextMenu');
|
|
14
|
+
/** Do not use this class directly. Use ContextMenuRoot and ContextActions instead. */
|
|
15
|
+
class ContextMenu extends PureComponent {
|
|
16
|
+
static handleContextMenu(e) {
|
|
17
|
+
if (e.metaKey) {
|
|
18
|
+
return;
|
|
19
|
+
}
|
|
20
|
+
e.stopPropagation();
|
|
21
|
+
e.preventDefault();
|
|
22
|
+
}
|
|
23
|
+
constructor(props) {
|
|
24
|
+
super(props);
|
|
25
|
+
_defineProperty(this, "container", void 0);
|
|
26
|
+
_defineProperty(this, "oldFocus", void 0);
|
|
27
|
+
_defineProperty(this, "activeSubMenuRef", void 0);
|
|
28
|
+
_defineProperty(this, "subMenuTimer", void 0);
|
|
29
|
+
_defineProperty(this, "rAF", void 0);
|
|
30
|
+
_defineProperty(this, "initialPosition", void 0);
|
|
31
|
+
this.handleBlur = this.handleBlur.bind(this);
|
|
32
|
+
this.handleCloseSubMenu = this.handleCloseSubMenu.bind(this);
|
|
33
|
+
this.handleKeyDown = this.handleKeyDown.bind(this);
|
|
34
|
+
this.handleMenuItemClick = this.handleMenuItemClick.bind(this);
|
|
35
|
+
this.handleMenuItemContextMenu = this.handleMenuItemContextMenu.bind(this);
|
|
36
|
+
this.handleMenuItemMouseMove = this.handleMenuItemMouseMove.bind(this);
|
|
37
|
+
this.handleMouseLeave = this.handleMouseLeave.bind(this);
|
|
38
|
+
this.handleWindowResize = this.handleWindowResize.bind(this);
|
|
39
|
+
this.container = /*#__PURE__*/React.createRef();
|
|
40
|
+
this.oldFocus = document.activeElement;
|
|
41
|
+
this.activeSubMenuRef = /*#__PURE__*/React.createRef();
|
|
42
|
+
this.subMenuTimer = 0;
|
|
43
|
+
this.rAF = 0;
|
|
44
|
+
this.initialPosition = {
|
|
45
|
+
top: props.top,
|
|
46
|
+
left: props.left
|
|
47
|
+
};
|
|
48
|
+
this.state = {
|
|
49
|
+
menuItems: [],
|
|
50
|
+
pendingItems: [],
|
|
51
|
+
activeSubMenu: null,
|
|
52
|
+
hasOverflow: false,
|
|
53
|
+
subMenuTop: null,
|
|
54
|
+
subMenuLeft: null,
|
|
55
|
+
subMenuParentWidth: 0,
|
|
56
|
+
subMenuParentHeight: 0,
|
|
57
|
+
keyboardIndex: -1,
|
|
58
|
+
mouseIndex: -1
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
componentDidMount() {
|
|
62
|
+
this.initMenu();
|
|
63
|
+
this.verifyPosition();
|
|
64
|
+
window.addEventListener('resize', this.handleWindowResize);
|
|
65
|
+
|
|
66
|
+
// rAF is needed to wait for a submenus popper to be created before
|
|
67
|
+
// attempting to set focus, however on a quick mount/unmount when
|
|
68
|
+
// mousing past an item, the submenu could be unmounted before the
|
|
69
|
+
// async rAF finishes, so it is cancelled in willUnmount()
|
|
70
|
+
this.rAF = window.requestAnimationFrame(() => {
|
|
71
|
+
var _this$container$curre;
|
|
72
|
+
(_this$container$curre = this.container.current) === null || _this$container$curre === void 0 ? void 0 : _this$container$curre.focus();
|
|
73
|
+
var {
|
|
74
|
+
onMenuOpened
|
|
75
|
+
} = this.props;
|
|
76
|
+
onMenuOpened(this);
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
componentDidUpdate(prevProps, prevState) {
|
|
80
|
+
var {
|
|
81
|
+
actions
|
|
82
|
+
} = this.props;
|
|
83
|
+
var {
|
|
84
|
+
activeSubMenu
|
|
85
|
+
} = this.state;
|
|
86
|
+
if (activeSubMenu !== prevState.activeSubMenu) {
|
|
87
|
+
if (activeSubMenu == null) {
|
|
88
|
+
var _this$container$curre2;
|
|
89
|
+
// close sub menu, refocus parent menu
|
|
90
|
+
(_this$container$curre2 = this.container.current) === null || _this$container$curre2 === void 0 ? void 0 : _this$container$curre2.focus();
|
|
91
|
+
} else {
|
|
92
|
+
// open sub menu, set its initial position
|
|
93
|
+
this.setActiveSubMenuPosition();
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
if (prevProps.actions !== actions) {
|
|
97
|
+
this.initMenu();
|
|
98
|
+
if (this.container.current == null || !this.container.current.contains(document.activeElement)) {
|
|
99
|
+
var _this$container$curre3;
|
|
100
|
+
(_this$container$curre3 = this.container.current) === null || _this$container$curre3 === void 0 ? void 0 : _this$container$curre3.focus();
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
this.verifyPosition();
|
|
104
|
+
}
|
|
105
|
+
componentWillUnmount() {
|
|
106
|
+
this.cancelPromises();
|
|
107
|
+
window.removeEventListener('resize', this.handleWindowResize);
|
|
108
|
+
cancelAnimationFrame(this.rAF);
|
|
109
|
+
}
|
|
110
|
+
getKeyboardIndex() {
|
|
111
|
+
var {
|
|
112
|
+
options
|
|
113
|
+
} = this.props;
|
|
114
|
+
if (options.separateKeyboardMouse !== undefined && options.separateKeyboardMouse) {
|
|
115
|
+
var {
|
|
116
|
+
keyboardIndex
|
|
117
|
+
} = this.state;
|
|
118
|
+
return keyboardIndex;
|
|
119
|
+
}
|
|
120
|
+
return this.getMouseIndex();
|
|
121
|
+
}
|
|
122
|
+
setKeyboardIndex(index) {
|
|
123
|
+
var {
|
|
124
|
+
options
|
|
125
|
+
} = this.props;
|
|
126
|
+
if (options.separateKeyboardMouse !== undefined && options.separateKeyboardMouse) {
|
|
127
|
+
this.setState({
|
|
128
|
+
keyboardIndex: index
|
|
129
|
+
});
|
|
130
|
+
} else {
|
|
131
|
+
this.setMouseIndex(index);
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
getMouseIndex() {
|
|
135
|
+
var {
|
|
136
|
+
mouseIndex
|
|
137
|
+
} = this.state;
|
|
138
|
+
return mouseIndex;
|
|
139
|
+
}
|
|
140
|
+
setMouseIndex(index) {
|
|
141
|
+
this.setState({
|
|
142
|
+
mouseIndex: index
|
|
143
|
+
});
|
|
144
|
+
}
|
|
145
|
+
initMenu() {
|
|
146
|
+
// cancel any pending close and promises
|
|
147
|
+
this.cancelPromises();
|
|
148
|
+
cancelAnimationFrame(this.rAF);
|
|
149
|
+
var {
|
|
150
|
+
options
|
|
151
|
+
} = this.props;
|
|
152
|
+
var keyboardIndex = options.initialKeyboardIndex;
|
|
153
|
+
if (keyboardIndex === undefined) {
|
|
154
|
+
keyboardIndex = -1;
|
|
155
|
+
}
|
|
156
|
+
var {
|
|
157
|
+
actions
|
|
158
|
+
} = this.props;
|
|
159
|
+
var menuItems = ContextActionUtils.getMenuItems(actions);
|
|
160
|
+
var nonPromiseItems = [];
|
|
161
|
+
for (var i = menuItems.length - 1; i >= 0; i -= 1) {
|
|
162
|
+
var menuItem = menuItems[i];
|
|
163
|
+
if (menuItem instanceof Promise) {
|
|
164
|
+
this.initMenuPromise(menuItem);
|
|
165
|
+
} else {
|
|
166
|
+
nonPromiseItems.push(menuItem);
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
this.setState({
|
|
170
|
+
mouseIndex: -1,
|
|
171
|
+
keyboardIndex,
|
|
172
|
+
activeSubMenu: null,
|
|
173
|
+
menuItems: ContextActionUtils.sortActions(nonPromiseItems)
|
|
174
|
+
});
|
|
175
|
+
}
|
|
176
|
+
initMenuPromise(promise) {
|
|
177
|
+
// make all promises cancellable
|
|
178
|
+
var cancellablePromise = PromiseUtils.makeCancelable(promise);
|
|
179
|
+
this.setState(state => ({
|
|
180
|
+
pendingItems: state.pendingItems.concat(cancellablePromise)
|
|
181
|
+
}));
|
|
182
|
+
cancellablePromise.then(resolvedMenuItems => {
|
|
183
|
+
this.setState(state => {
|
|
184
|
+
var index = state.pendingItems.indexOf(cancellablePromise);
|
|
185
|
+
if (index >= 0) {
|
|
186
|
+
var pendingItems = state.pendingItems.slice();
|
|
187
|
+
pendingItems.splice(index, 1);
|
|
188
|
+
return {
|
|
189
|
+
menuItems: ContextActionUtils.sortActions(state.menuItems.concat(resolvedMenuItems)),
|
|
190
|
+
pendingItems
|
|
191
|
+
};
|
|
192
|
+
}
|
|
193
|
+
// This item is stale, don't update the menu
|
|
194
|
+
return null;
|
|
195
|
+
});
|
|
196
|
+
}, error => {
|
|
197
|
+
if (PromiseUtils.isCanceled(error)) {
|
|
198
|
+
return; // Canceled promise is ignored
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
// remove failed item from pending list
|
|
202
|
+
this.setState(state => {
|
|
203
|
+
var index = state.pendingItems.indexOf(cancellablePromise);
|
|
204
|
+
if (index >= 0) {
|
|
205
|
+
var pendingItems = state.pendingItems.slice();
|
|
206
|
+
pendingItems.splice(index, 1);
|
|
207
|
+
return {
|
|
208
|
+
pendingItems
|
|
209
|
+
};
|
|
210
|
+
}
|
|
211
|
+
return null;
|
|
212
|
+
});
|
|
213
|
+
|
|
214
|
+
// Log the error
|
|
215
|
+
log.error(error);
|
|
216
|
+
});
|
|
217
|
+
}
|
|
218
|
+
cancelPromises() {
|
|
219
|
+
var {
|
|
220
|
+
pendingItems
|
|
221
|
+
} = this.state;
|
|
222
|
+
pendingItems.map(item => item.cancel());
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
/**
|
|
226
|
+
* Sets the unverfied start position of a submenu. Submenu then self-verfies
|
|
227
|
+
* its own position and potentially reports back a new position.
|
|
228
|
+
*/
|
|
229
|
+
setActiveSubMenuPosition() {
|
|
230
|
+
if (this.activeSubMenuRef.current === null) return;
|
|
231
|
+
var parentRect = this.activeSubMenuRef.current.getBoundingClientRect();
|
|
232
|
+
|
|
233
|
+
// intentionally rect.right, we want the sub menu to start at the right edge of the current menu
|
|
234
|
+
this.setState({
|
|
235
|
+
subMenuTop: parentRect.top,
|
|
236
|
+
subMenuLeft: parentRect.right,
|
|
237
|
+
subMenuParentHeight: parentRect.height,
|
|
238
|
+
subMenuParentWidth: parentRect.width
|
|
239
|
+
});
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
/**
|
|
243
|
+
* Verifies the position of this menu in relation to the parent to make sure it's on screen.
|
|
244
|
+
* Will update the top left state (updatePosition) if necessary (causing a re-render)
|
|
245
|
+
* By default it tries to top-align with parent, at the right side of the parent.
|
|
246
|
+
* Because we aren't a native context menu and can't escape window bounds, we also do
|
|
247
|
+
* somethings to better fit on screen, such as the "nudge" offset position, and further
|
|
248
|
+
* allow overflow scrolling for large menus in a small window.
|
|
249
|
+
*/
|
|
250
|
+
verifyPosition() {
|
|
251
|
+
var _this$container$curre4, _this$container$curre5, _this$container$curre6, _this$container$curre7;
|
|
252
|
+
var {
|
|
253
|
+
options,
|
|
254
|
+
updatePosition,
|
|
255
|
+
subMenuParentWidth,
|
|
256
|
+
subMenuParentHeight,
|
|
257
|
+
top: oldTop,
|
|
258
|
+
left: oldLeft
|
|
259
|
+
} = this.props;
|
|
260
|
+
if (!this.container.current || options.doNotVerifyPosition != null && options.doNotVerifyPosition) {
|
|
261
|
+
return;
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
// initial position is used rather than current position,
|
|
265
|
+
// as the number of menu items can change (actions can bubble)
|
|
266
|
+
// and menu should always be positioned relative to spawn point
|
|
267
|
+
var {
|
|
268
|
+
top,
|
|
269
|
+
left
|
|
270
|
+
} = this.initialPosition;
|
|
271
|
+
var {
|
|
272
|
+
width,
|
|
273
|
+
height
|
|
274
|
+
} = (_this$container$curre4 = (_this$container$curre5 = this.container.current) === null || _this$container$curre5 === void 0 ? void 0 : _this$container$curre5.getBoundingClientRect()) !== null && _this$container$curre4 !== void 0 ? _this$container$curre4 : {
|
|
275
|
+
width: 0,
|
|
276
|
+
height: 0
|
|
277
|
+
};
|
|
278
|
+
var hasOverflow = ((_this$container$curre6 = (_this$container$curre7 = this.container.current) === null || _this$container$curre7 === void 0 ? void 0 : _this$container$curre7.scrollHeight) !== null && _this$container$curre6 !== void 0 ? _this$container$curre6 : 0) > window.innerHeight;
|
|
279
|
+
if (height === 0 || width === 0) {
|
|
280
|
+
// We don't have a height or width yet, don't bother doing anything
|
|
281
|
+
return;
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
// does it fit below?
|
|
285
|
+
if (top + height > window.innerHeight) {
|
|
286
|
+
// can it be flipped to above? include offset if submenu (defaults to 0 if not submenu)
|
|
287
|
+
if (top - height - subMenuParentHeight > 0) {
|
|
288
|
+
// flip like a native menu would
|
|
289
|
+
top -= height - subMenuParentHeight;
|
|
290
|
+
} else {
|
|
291
|
+
// still doesnt fit? okay, position at bottom edge
|
|
292
|
+
top = window.innerHeight - height;
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
if (left + width > window.innerWidth) {
|
|
296
|
+
// less picky about left right positioning, just keep it going off to right
|
|
297
|
+
left = left - width - subMenuParentWidth;
|
|
298
|
+
}
|
|
299
|
+
if (oldLeft !== left || oldTop !== top) {
|
|
300
|
+
// parent owns positioning as single source of truth, ask to update props
|
|
301
|
+
this.setState({
|
|
302
|
+
hasOverflow
|
|
303
|
+
});
|
|
304
|
+
updatePosition(top, left);
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
// since window resize doesn't trigger blur, listen and close the menu
|
|
309
|
+
handleWindowResize() {
|
|
310
|
+
if (!this.container.current) {
|
|
311
|
+
return;
|
|
312
|
+
}
|
|
313
|
+
this.closeMenu(true);
|
|
314
|
+
}
|
|
315
|
+
handleBlur(e) {
|
|
316
|
+
if (!this.container.current) {
|
|
317
|
+
log.warn('Container is null!');
|
|
318
|
+
return;
|
|
319
|
+
}
|
|
320
|
+
if (!this.container.current.contains(e.relatedTarget)) {
|
|
321
|
+
var element = e.relatedTarget;
|
|
322
|
+
var isContextMenuChild = false;
|
|
323
|
+
while (element && !isContextMenuChild) {
|
|
324
|
+
isContextMenuChild = element.hasAttribute('data-dh-context-menu');
|
|
325
|
+
element = element.parentElement;
|
|
326
|
+
}
|
|
327
|
+
if (!isContextMenuChild) {
|
|
328
|
+
// close all submenus on blur
|
|
329
|
+
this.closeMenu(true);
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
/** Returns whether the specified key should remove the menu. Depends on the side the parent is on. */
|
|
335
|
+
isEscapeKey(key) {
|
|
336
|
+
var {
|
|
337
|
+
left
|
|
338
|
+
} = this.props;
|
|
339
|
+
return key === 'Escape' || left < 0 && key === 'ArrowRight' || key === 'ArrowLeft';
|
|
340
|
+
}
|
|
341
|
+
handleKeyDown(e) {
|
|
342
|
+
var {
|
|
343
|
+
menuItems
|
|
344
|
+
} = this.state;
|
|
345
|
+
var oldFocus = this.getKeyboardIndex();
|
|
346
|
+
var newFocus = oldFocus;
|
|
347
|
+
var openSubMenu = false;
|
|
348
|
+
if (e.key === 'Enter' || e.key === ' ') {
|
|
349
|
+
if (oldFocus >= 0 && oldFocus < menuItems.length) {
|
|
350
|
+
this.handleMenuItemClick(menuItems[oldFocus], e);
|
|
351
|
+
}
|
|
352
|
+
return;
|
|
353
|
+
}
|
|
354
|
+
if (e.key === 'ArrowRight') {
|
|
355
|
+
if (oldFocus >= 0 && oldFocus <= menuItems.length) {
|
|
356
|
+
openSubMenu = true;
|
|
357
|
+
} else {
|
|
358
|
+
newFocus = 0;
|
|
359
|
+
}
|
|
360
|
+
} else if (this.isEscapeKey(e.key)) {
|
|
361
|
+
newFocus = null;
|
|
362
|
+
} else if (e.key === 'ArrowUp' || e.shiftKey && e.key === 'Tab') {
|
|
363
|
+
newFocus = ContextActionUtils.getNextMenuItem(newFocus, -1, menuItems);
|
|
364
|
+
} else if (e.key === 'ArrowDown' || e.key === 'Tab') {
|
|
365
|
+
newFocus = ContextActionUtils.getNextMenuItem(newFocus, 1, menuItems);
|
|
366
|
+
}
|
|
367
|
+
if (openSubMenu) {
|
|
368
|
+
this.openSubMenu(oldFocus);
|
|
369
|
+
e.preventDefault();
|
|
370
|
+
e.stopPropagation();
|
|
371
|
+
return;
|
|
372
|
+
}
|
|
373
|
+
if (oldFocus !== newFocus) {
|
|
374
|
+
if (newFocus !== null) {
|
|
375
|
+
this.setKeyboardIndex(newFocus);
|
|
376
|
+
} else {
|
|
377
|
+
this.closeMenu();
|
|
378
|
+
if (this.oldFocus instanceof HTMLElement) {
|
|
379
|
+
this.oldFocus.focus();
|
|
380
|
+
}
|
|
381
|
+
}
|
|
382
|
+
e.preventDefault();
|
|
383
|
+
e.stopPropagation();
|
|
384
|
+
}
|
|
385
|
+
}
|
|
386
|
+
openSubMenu(index) {
|
|
387
|
+
var {
|
|
388
|
+
menuItems,
|
|
389
|
+
activeSubMenu
|
|
390
|
+
} = this.state;
|
|
391
|
+
var newSubMenu = menuItems[index].actions ? index : null;
|
|
392
|
+
if (activeSubMenu === newSubMenu) return;
|
|
393
|
+
this.setState({
|
|
394
|
+
activeSubMenu: newSubMenu,
|
|
395
|
+
subMenuTop: null,
|
|
396
|
+
subMenuLeft: null
|
|
397
|
+
});
|
|
398
|
+
}
|
|
399
|
+
closeMenu() {
|
|
400
|
+
var closeAll = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false;
|
|
401
|
+
var {
|
|
402
|
+
closeMenu,
|
|
403
|
+
onMenuClosed
|
|
404
|
+
} = this.props;
|
|
405
|
+
cancelAnimationFrame(this.rAF);
|
|
406
|
+
this.rAF = window.requestAnimationFrame(() => {
|
|
407
|
+
closeMenu(closeAll);
|
|
408
|
+
onMenuClosed(this);
|
|
409
|
+
});
|
|
410
|
+
}
|
|
411
|
+
closeSubMenu() {
|
|
412
|
+
this.setState({
|
|
413
|
+
activeSubMenu: null
|
|
414
|
+
});
|
|
415
|
+
}
|
|
416
|
+
handleCloseSubMenu(closeAllMenus) {
|
|
417
|
+
if (closeAllMenus) {
|
|
418
|
+
this.closeMenu(true);
|
|
419
|
+
} else {
|
|
420
|
+
this.closeSubMenu();
|
|
421
|
+
}
|
|
422
|
+
}
|
|
423
|
+
handleMenuItemClick(menuItem, e) {
|
|
424
|
+
e.preventDefault();
|
|
425
|
+
e.stopPropagation();
|
|
426
|
+
var {
|
|
427
|
+
menuItems
|
|
428
|
+
} = this.state;
|
|
429
|
+
if (menuItem != null && (menuItem.disabled === undefined || !menuItem.disabled)) {
|
|
430
|
+
if (menuItem.actions != null) {
|
|
431
|
+
this.openSubMenu(menuItems.indexOf(menuItem));
|
|
432
|
+
} else if (menuItem.action != null) {
|
|
433
|
+
menuItem.action();
|
|
434
|
+
this.closeMenu(true);
|
|
435
|
+
}
|
|
436
|
+
}
|
|
437
|
+
}
|
|
438
|
+
handleMenuItemContextMenu(menuItem, e) {
|
|
439
|
+
if (e.metaKey) {
|
|
440
|
+
return;
|
|
441
|
+
}
|
|
442
|
+
this.handleMenuItemClick(menuItem, e);
|
|
443
|
+
}
|
|
444
|
+
handleMenuItemMouseMove(menuItem) {
|
|
445
|
+
var {
|
|
446
|
+
menuItems
|
|
447
|
+
} = this.state;
|
|
448
|
+
var focusIndex = menuItems.indexOf(menuItem);
|
|
449
|
+
this.setMouseIndex(focusIndex);
|
|
450
|
+
if (focusIndex >= 0 && focusIndex < menuItems.length && (menuItem.disabled === undefined || !menuItem.disabled)) {
|
|
451
|
+
this.openSubMenu(focusIndex);
|
|
452
|
+
}
|
|
453
|
+
}
|
|
454
|
+
handleMouseLeave() {
|
|
455
|
+
this.setMouseIndex(-1);
|
|
456
|
+
}
|
|
457
|
+
render() {
|
|
458
|
+
var menuItemElements = [];
|
|
459
|
+
var {
|
|
460
|
+
top,
|
|
461
|
+
left
|
|
462
|
+
} = this.props;
|
|
463
|
+
var {
|
|
464
|
+
activeSubMenu,
|
|
465
|
+
hasOverflow,
|
|
466
|
+
keyboardIndex,
|
|
467
|
+
menuItems,
|
|
468
|
+
mouseIndex,
|
|
469
|
+
pendingItems,
|
|
470
|
+
subMenuTop,
|
|
471
|
+
subMenuLeft,
|
|
472
|
+
subMenuParentWidth,
|
|
473
|
+
subMenuParentHeight
|
|
474
|
+
} = this.state;
|
|
475
|
+
for (var i = 0; i < menuItems.length; i += 1) {
|
|
476
|
+
var menuItem = menuItems[i];
|
|
477
|
+
if (i > 0 && menuItem.group !== menuItems[i - 1].group) {
|
|
478
|
+
menuItemElements.push( /*#__PURE__*/React.createElement("hr", {
|
|
479
|
+
key: "".concat(i, ".separator")
|
|
480
|
+
}));
|
|
481
|
+
}
|
|
482
|
+
var menuItemElement = /*#__PURE__*/React.createElement(ContextMenuItem, {
|
|
483
|
+
key: i,
|
|
484
|
+
ref: activeSubMenu === i ? this.activeSubMenuRef : null,
|
|
485
|
+
isKeyboardSelected: keyboardIndex === i,
|
|
486
|
+
isMouseSelected: mouseIndex === i,
|
|
487
|
+
menuItem: menuItem,
|
|
488
|
+
closeMenu: this.handleCloseSubMenu,
|
|
489
|
+
onMenuItemClick: this.handleMenuItemClick,
|
|
490
|
+
onMenuItemMouseMove: this.handleMenuItemMouseMove,
|
|
491
|
+
onMenuItemContextMenu: this.handleMenuItemContextMenu
|
|
492
|
+
});
|
|
493
|
+
menuItemElements.push(menuItemElement);
|
|
494
|
+
}
|
|
495
|
+
var pendingElement = null;
|
|
496
|
+
if (pendingItems.length > 0) {
|
|
497
|
+
pendingElement = /*#__PURE__*/React.createElement("div", {
|
|
498
|
+
className: "loading"
|
|
499
|
+
}, /*#__PURE__*/React.createElement(LoadingSpinner, null));
|
|
500
|
+
}
|
|
501
|
+
var {
|
|
502
|
+
menuStyle,
|
|
503
|
+
'data-testid': dataTestId
|
|
504
|
+
} = this.props;
|
|
505
|
+
|
|
506
|
+
// don't show submenu until it has an position initialized
|
|
507
|
+
var showSubmenu = activeSubMenu !== null && subMenuTop !== null && subMenuLeft !== null;
|
|
508
|
+
return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement("div", {
|
|
509
|
+
className: classNames({
|
|
510
|
+
'has-overflow': hasOverflow
|
|
511
|
+
}, 'context-menu-container'),
|
|
512
|
+
style: _objectSpread({
|
|
513
|
+
top,
|
|
514
|
+
left
|
|
515
|
+
}, menuStyle),
|
|
516
|
+
ref: this.container,
|
|
517
|
+
"data-dh-context-menu": true,
|
|
518
|
+
onBlur: this.handleBlur,
|
|
519
|
+
onKeyDown: this.handleKeyDown,
|
|
520
|
+
onMouseLeave: this.handleMouseLeave,
|
|
521
|
+
onContextMenu: ContextMenu.handleContextMenu,
|
|
522
|
+
role: "menuitem",
|
|
523
|
+
tabIndex: 0,
|
|
524
|
+
"data-testid": dataTestId
|
|
525
|
+
}, menuItemElements, pendingElement), showSubmenu && activeSubMenu !== null && subMenuTop !== null && subMenuLeft !== null && /*#__PURE__*/React.createElement(ContextMenu, {
|
|
526
|
+
key: "sub-".concat(activeSubMenu),
|
|
527
|
+
actions: menuItems[activeSubMenu].actions || [],
|
|
528
|
+
closeMenu: this.handleCloseSubMenu,
|
|
529
|
+
top: subMenuTop,
|
|
530
|
+
left: subMenuLeft,
|
|
531
|
+
updatePosition: (verifiedTop, verifiedLeft) => {
|
|
532
|
+
this.setState({
|
|
533
|
+
subMenuTop: verifiedTop,
|
|
534
|
+
subMenuLeft: verifiedLeft
|
|
535
|
+
});
|
|
536
|
+
},
|
|
537
|
+
subMenuParentWidth: subMenuParentWidth,
|
|
538
|
+
subMenuParentHeight: subMenuParentHeight
|
|
539
|
+
}));
|
|
540
|
+
}
|
|
541
|
+
}
|
|
542
|
+
_defineProperty(ContextMenu, "defaultProps", {
|
|
543
|
+
subMenuParentWidth: 0,
|
|
544
|
+
subMenuParentHeight: 0,
|
|
545
|
+
closeMenu() {
|
|
546
|
+
// no-op
|
|
547
|
+
},
|
|
548
|
+
onMenuOpened() {
|
|
549
|
+
// no-op
|
|
550
|
+
},
|
|
551
|
+
onMenuClosed() {
|
|
552
|
+
// no-op
|
|
553
|
+
},
|
|
554
|
+
options: {},
|
|
555
|
+
menuStyle: {},
|
|
556
|
+
'data-testid': undefined
|
|
557
|
+
});
|
|
558
|
+
export default ContextMenu;
|
|
559
|
+
//# sourceMappingURL=ContextMenu.js.map
|
|
@@ -0,0 +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 {\n width,\n 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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"}
|