@itwin/core-react 5.19.0 → 5.21.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/CHANGELOG.md +4 -0
- package/lib/core-react/UiCore.js +2 -1
- package/lib/core-react/UiCore.js.map +1 -1
- package/lib/core-react/autosuggest/AutoSuggest.js +86 -86
- package/lib/core-react/autosuggest/AutoSuggest.js.map +1 -1
- package/lib/core-react/contextmenu/ContextMenu.js +272 -269
- package/lib/core-react/contextmenu/ContextMenu.js.map +1 -1
- package/lib/core-react/contextmenu/ContextMenuItem.js +57 -55
- package/lib/core-react/contextmenu/ContextMenuItem.js.map +1 -1
- package/lib/core-react/contextmenu/ContextSubMenu.js +70 -67
- package/lib/core-react/contextmenu/ContextSubMenu.js.map +1 -1
- package/lib/core-react/contextmenu/GlobalContextMenu.js +23 -22
- package/lib/core-react/contextmenu/GlobalContextMenu.js.map +1 -1
- package/lib/core-react/contextmenu/TildeFinder.js +52 -52
- package/lib/core-react/contextmenu/TildeFinder.js.map +1 -1
- package/lib/core-react/dialog/Dialog.js +29 -29
- package/lib/core-react/dialog/Dialog.js.map +1 -1
- package/lib/core-react/dialog/GlobalDialog.js +24 -23
- package/lib/core-react/dialog/GlobalDialog.js.map +1 -1
- package/lib/core-react/expandable/ExpandableList.js +15 -15
- package/lib/core-react/expandable/ExpandableList.js.map +1 -1
- package/lib/core-react/focus/ItemKeyboardNavigator.js +7 -3
- package/lib/core-react/focus/ItemKeyboardNavigator.js.map +1 -1
- package/lib/core-react/hocs/withIsPressed.js +14 -17
- package/lib/core-react/hocs/withIsPressed.js.map +1 -1
- package/lib/core-react/hocs/withOnOutsideClick.js +38 -41
- package/lib/core-react/hocs/withOnOutsideClick.js.map +1 -1
- package/lib/core-react/hocs/withTimeout.js +2 -5
- package/lib/core-react/hocs/withTimeout.js.map +1 -1
- package/lib/core-react/icons/ConditionalIconItem.js +3 -0
- package/lib/core-react/icons/ConditionalIconItem.js.map +1 -1
- package/lib/core-react/imagecheckbox/ImageCheckBox.js +15 -18
- package/lib/core-react/imagecheckbox/ImageCheckBox.js.map +1 -1
- package/lib/core-react/loading/LoadingBar.js +3 -3
- package/lib/core-react/loading/LoadingBar.js.map +1 -1
- package/lib/core-react/loading/LoadingPrompt.js +9 -9
- package/lib/core-react/loading/LoadingPrompt.js.map +1 -1
- package/lib/core-react/loading/LoadingSpinner.js +3 -3
- package/lib/core-react/loading/LoadingSpinner.js.map +1 -1
- package/lib/core-react/loading/LoadingStatus.js +4 -4
- package/lib/core-react/loading/LoadingStatus.js.map +1 -1
- package/lib/core-react/messagebox/MessageBox.js +6 -6
- package/lib/core-react/messagebox/MessageBox.js.map +1 -1
- package/lib/core-react/popup/Popup.js +209 -209
- package/lib/core-react/popup/Popup.js.map +1 -1
- package/lib/core-react/radialmenu/Annulus.js +19 -2
- package/lib/core-react/radialmenu/Annulus.js.map +1 -1
- package/lib/core-react/radialmenu/RadialMenu.js +56 -56
- package/lib/core-react/radialmenu/RadialMenu.js.map +1 -1
- package/lib/core-react/searchbox/SearchBox.js +60 -60
- package/lib/core-react/searchbox/SearchBox.js.map +1 -1
- package/lib/core-react/settings/SettingsManager.js +20 -22
- package/lib/core-react/settings/SettingsManager.js.map +1 -1
- package/lib/core-react/tabs/Tabs.js +14 -13
- package/lib/core-react/tabs/Tabs.js.map +1 -1
- package/lib/core-react/tree/Node.js +18 -18
- package/lib/core-react/tree/Node.js.map +1 -1
- package/lib/core-react/tree/Tree.js +1 -4
- package/lib/core-react/tree/Tree.js.map +1 -1
- package/lib/core-react/uistate/LocalStateStorage.js +1 -0
- package/lib/core-react/uistate/LocalStateStorage.js.map +1 -1
- package/lib/core-react/uistate/UiStateEntry.js +5 -0
- package/lib/core-react/uistate/UiStateEntry.js.map +1 -1
- package/lib/core-react/utils/Point.js +2 -0
- package/lib/core-react/utils/Point.js.map +1 -1
- package/lib/core-react/utils/Rectangle.js +4 -0
- package/lib/core-react/utils/Rectangle.js.map +1 -1
- package/lib/core-react/utils/ScrollPositionMaintainer.js +1 -0
- package/lib/core-react/utils/ScrollPositionMaintainer.js.map +1 -1
- package/lib/core-react/utils/Timer.js +5 -2
- package/lib/core-react/utils/Timer.js.map +1 -1
- package/package.json +3 -3
|
@@ -20,181 +20,97 @@ import { ContextSubMenu } from "./ContextSubMenu.js";
|
|
|
20
20
|
* @deprecated in 4.16.0. Use {@link https://itwinui.bentley.com/docs/dropdownmenu iTwinUI DropdownMenu} component instead.
|
|
21
21
|
*/
|
|
22
22
|
export class ContextMenu extends React.PureComponent {
|
|
23
|
+
_rootElement = null;
|
|
24
|
+
_menuElement = null;
|
|
25
|
+
_selectedElement = null;
|
|
26
|
+
_length = 0;
|
|
27
|
+
_hotKeyMap = new Map();
|
|
28
|
+
_lastChildren;
|
|
29
|
+
_lastDirection = ContextMenuDirection.BottomRight;
|
|
30
|
+
_lastSelectedIndex = 0;
|
|
31
|
+
_injectedChildren;
|
|
32
|
+
_parentWindowHeight = 0;
|
|
33
|
+
_parentWindowWidth = 0;
|
|
34
|
+
static defaultProps = {
|
|
35
|
+
direction: ContextMenuDirection.BottomRight,
|
|
36
|
+
autoflip: true,
|
|
37
|
+
edgeLimit: true,
|
|
38
|
+
hotkeySelect: true,
|
|
39
|
+
selectedIndex: -1,
|
|
40
|
+
floating: true,
|
|
41
|
+
};
|
|
42
|
+
state;
|
|
23
43
|
constructor(props) {
|
|
24
44
|
super(props);
|
|
25
|
-
this._rootElement = null;
|
|
26
|
-
this._menuElement = null;
|
|
27
|
-
this._selectedElement = null;
|
|
28
|
-
this._length = 0;
|
|
29
|
-
this._hotKeyMap = new Map();
|
|
30
|
-
this._lastDirection = ContextMenuDirection.BottomRight;
|
|
31
|
-
this._lastSelectedIndex = 0;
|
|
32
|
-
this._parentWindowHeight = 0;
|
|
33
|
-
this._parentWindowWidth = 0;
|
|
34
|
-
this._handleHotKeyParsed = (index, hotKey) => {
|
|
35
|
-
this._hotKeyMap.set(index, hotKey);
|
|
36
|
-
};
|
|
37
|
-
this._handleOnOutsideClick = (event) => {
|
|
38
|
-
if (this.props.opened && this.props.onOutsideClick)
|
|
39
|
-
this.props.onOutsideClick(event);
|
|
40
|
-
};
|
|
41
|
-
this._injectMenuItemProps = (children, direction, selectedIndex) => {
|
|
42
|
-
let index = 0;
|
|
43
|
-
// add inheritance data to submenu children
|
|
44
|
-
const ch = React.Children.map(children, (child) => {
|
|
45
|
-
// Capture only ContextSubMenus and ContextMenuItems.
|
|
46
|
-
if (child &&
|
|
47
|
-
typeof child === "object" &&
|
|
48
|
-
"props" in child &&
|
|
49
|
-
(child.type === ContextSubMenu || child.type === ContextMenuItem) &&
|
|
50
|
-
React.isValidElement(child) &&
|
|
51
|
-
!ConditionalBooleanValue.getValue(child.props.disabled) &&
|
|
52
|
-
!ConditionalBooleanValue.getValue(child.props.hidden)) {
|
|
53
|
-
const id = index; // get separate id variable so value stays the same when onHover is called later.
|
|
54
|
-
const onHover = () => {
|
|
55
|
-
this.setState({ selectedIndex: id });
|
|
56
|
-
this.focus();
|
|
57
|
-
};
|
|
58
|
-
const ref = (el) => {
|
|
59
|
-
if (selectedIndex === id)
|
|
60
|
-
// only save to this._selectedElement if previously captured bool is true
|
|
61
|
-
this._selectedElement = el;
|
|
62
|
-
};
|
|
63
|
-
const boundHandleHotKeyParse = this._handleHotKeyParsed.bind(this, id); // bind local callback for specific index
|
|
64
|
-
const childProps = {
|
|
65
|
-
parentMenu: this,
|
|
66
|
-
ref,
|
|
67
|
-
onHover,
|
|
68
|
-
isSelected: selectedIndex === id,
|
|
69
|
-
onHotKeyParsed: boundHandleHotKeyParse,
|
|
70
|
-
};
|
|
71
|
-
if (child.type === ContextSubMenu &&
|
|
72
|
-
React.isValidElement(child)) {
|
|
73
|
-
// add direction only to sub-menus
|
|
74
|
-
childProps.direction = child.props.direction || direction;
|
|
75
|
-
}
|
|
76
|
-
index++;
|
|
77
|
-
return React.cloneElement(child, childProps);
|
|
78
|
-
}
|
|
79
|
-
else
|
|
80
|
-
return child; // Else, pass through unmodified
|
|
81
|
-
});
|
|
82
|
-
this._length = index;
|
|
83
|
-
return ch;
|
|
84
|
-
};
|
|
85
|
-
this._rootRef = (el) => {
|
|
86
|
-
this._rootElement = el;
|
|
87
|
-
};
|
|
88
|
-
this._menuRef = (el) => {
|
|
89
|
-
this._menuElement = el;
|
|
90
|
-
};
|
|
91
|
-
this.focus = () => {
|
|
92
|
-
if (this._menuElement)
|
|
93
|
-
this._menuElement.focus();
|
|
94
|
-
};
|
|
95
|
-
this.blur = () => {
|
|
96
|
-
if (this._menuElement)
|
|
97
|
-
this._menuElement.blur();
|
|
98
|
-
};
|
|
99
|
-
this.getRect = () => {
|
|
100
|
-
let clientRect = DOMRect.fromRect({ x: 0, y: 0, width: 0, height: 0 });
|
|
101
|
-
if (this._menuElement) {
|
|
102
|
-
clientRect = this._menuElement.getBoundingClientRect();
|
|
103
|
-
}
|
|
104
|
-
return clientRect;
|
|
105
|
-
};
|
|
106
|
-
this._handleFocusChange = (event) => {
|
|
107
|
-
if (this._rootElement &&
|
|
108
|
-
this.props.opened &&
|
|
109
|
-
event.target instanceof Node &&
|
|
110
|
-
this.props.onOutsideClick &&
|
|
111
|
-
!this._rootElement.contains(event.target))
|
|
112
|
-
this.props.onOutsideClick(event);
|
|
113
|
-
};
|
|
114
|
-
this._handleClick = (event) => {
|
|
115
|
-
if (this.props.onSelect)
|
|
116
|
-
this.props.onSelect(event);
|
|
117
|
-
};
|
|
118
|
-
this._handleKeyUp = (event) => {
|
|
119
|
-
if (this.state.ignoreNextKeyUp) {
|
|
120
|
-
this.setState({ ignoreNextKeyUp: false });
|
|
121
|
-
return;
|
|
122
|
-
}
|
|
123
|
-
if (event.key) {
|
|
124
|
-
for (const [key, value] of this._hotKeyMap) {
|
|
125
|
-
if (!this.props.hotkeySelect && key > this.state.selectedIndex) {
|
|
126
|
-
// Start search at current index.
|
|
127
|
-
if (event.key.toUpperCase() === value) {
|
|
128
|
-
this.setState({ selectedIndex: key });
|
|
129
|
-
return;
|
|
130
|
-
}
|
|
131
|
-
}
|
|
132
|
-
}
|
|
133
|
-
for (const [key, value] of this._hotKeyMap) {
|
|
134
|
-
if (event.key.toUpperCase() === value) {
|
|
135
|
-
this.setState({ selectedIndex: key }, () => {
|
|
136
|
-
if (this.props.hotkeySelect && this._selectedElement) {
|
|
137
|
-
this._selectedElement.select();
|
|
138
|
-
}
|
|
139
|
-
});
|
|
140
|
-
event.stopPropagation();
|
|
141
|
-
return;
|
|
142
|
-
}
|
|
143
|
-
}
|
|
144
|
-
}
|
|
145
|
-
if (event.key === Key.ArrowLeft.valueOf()) {
|
|
146
|
-
event.stopPropagation();
|
|
147
|
-
if (this.props.parentMenu && this.props.parentSubmenu) {
|
|
148
|
-
this.props.parentSubmenu.close();
|
|
149
|
-
this.props.parentMenu.focus();
|
|
150
|
-
}
|
|
151
|
-
if (this.props.onEsc)
|
|
152
|
-
this.props.onEsc(event);
|
|
153
|
-
}
|
|
154
|
-
if (event.key === Key.Escape.valueOf()) {
|
|
155
|
-
if (this.props.onEsc)
|
|
156
|
-
this.props.onEsc(event);
|
|
157
|
-
}
|
|
158
|
-
if ((event.key === Key.Enter.valueOf() ||
|
|
159
|
-
event.key === Key.ArrowRight.valueOf()) &&
|
|
160
|
-
this._selectedElement) {
|
|
161
|
-
event.stopPropagation();
|
|
162
|
-
if (event.key === Key.Enter.valueOf() ||
|
|
163
|
-
this._selectedElement instanceof ContextSubMenu) {
|
|
164
|
-
if (this._selectedElement.select)
|
|
165
|
-
this._selectedElement.select();
|
|
166
|
-
}
|
|
167
|
-
}
|
|
168
|
-
let { selectedIndex } = this.state;
|
|
169
|
-
if (event.key === Key.ArrowUp.valueOf() ||
|
|
170
|
-
event.key === Key.ArrowDown.valueOf()) {
|
|
171
|
-
event.stopPropagation();
|
|
172
|
-
if (selectedIndex === -1) {
|
|
173
|
-
selectedIndex = 0;
|
|
174
|
-
}
|
|
175
|
-
else {
|
|
176
|
-
if (event.key === Key.ArrowUp.valueOf()) {
|
|
177
|
-
if (this.state.selectedIndex === 0)
|
|
178
|
-
selectedIndex = this._length - 1;
|
|
179
|
-
else
|
|
180
|
-
selectedIndex--;
|
|
181
|
-
}
|
|
182
|
-
if (event.key === Key.ArrowDown.valueOf()) {
|
|
183
|
-
if (this.state.selectedIndex === this._length - 1)
|
|
184
|
-
selectedIndex = 0;
|
|
185
|
-
else
|
|
186
|
-
selectedIndex++;
|
|
187
|
-
}
|
|
188
|
-
}
|
|
189
|
-
}
|
|
190
|
-
this.setState({ selectedIndex });
|
|
191
|
-
};
|
|
192
45
|
this.state = {
|
|
193
46
|
selectedIndex: this.props.selectedIndex,
|
|
194
47
|
direction: props.direction,
|
|
195
48
|
ignoreNextKeyUp: props.ignoreNextKeyUp,
|
|
196
49
|
};
|
|
197
50
|
}
|
|
51
|
+
/** @internal */
|
|
52
|
+
static autoFlip = (dir, rect, windowWidth, windowHeight) => {
|
|
53
|
+
if (rect.right > windowWidth) {
|
|
54
|
+
switch (dir) {
|
|
55
|
+
case ContextMenuDirection.TopRight:
|
|
56
|
+
dir = ContextMenuDirection.TopLeft;
|
|
57
|
+
break;
|
|
58
|
+
case ContextMenuDirection.Right:
|
|
59
|
+
dir = ContextMenuDirection.Left;
|
|
60
|
+
break;
|
|
61
|
+
case ContextMenuDirection.BottomRight:
|
|
62
|
+
dir = ContextMenuDirection.BottomLeft;
|
|
63
|
+
break;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
if (rect.left < 0) {
|
|
67
|
+
switch (dir) {
|
|
68
|
+
case ContextMenuDirection.TopLeft:
|
|
69
|
+
dir = ContextMenuDirection.TopRight;
|
|
70
|
+
break;
|
|
71
|
+
case ContextMenuDirection.Left:
|
|
72
|
+
dir = ContextMenuDirection.Right;
|
|
73
|
+
break;
|
|
74
|
+
case ContextMenuDirection.BottomLeft:
|
|
75
|
+
dir = ContextMenuDirection.BottomRight;
|
|
76
|
+
break;
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
if (rect.bottom > windowHeight) {
|
|
80
|
+
switch (dir) {
|
|
81
|
+
case ContextMenuDirection.BottomLeft:
|
|
82
|
+
dir = ContextMenuDirection.TopLeft;
|
|
83
|
+
break;
|
|
84
|
+
case ContextMenuDirection.Bottom:
|
|
85
|
+
dir = ContextMenuDirection.Top;
|
|
86
|
+
break;
|
|
87
|
+
case ContextMenuDirection.BottomRight:
|
|
88
|
+
dir = ContextMenuDirection.TopRight;
|
|
89
|
+
break;
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
if (rect.top < 0) {
|
|
93
|
+
switch (dir) {
|
|
94
|
+
case ContextMenuDirection.TopLeft:
|
|
95
|
+
dir = ContextMenuDirection.BottomLeft;
|
|
96
|
+
break;
|
|
97
|
+
case ContextMenuDirection.Top:
|
|
98
|
+
dir = ContextMenuDirection.Bottom;
|
|
99
|
+
break;
|
|
100
|
+
case ContextMenuDirection.TopRight:
|
|
101
|
+
dir = ContextMenuDirection.BottomRight;
|
|
102
|
+
break;
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
return dir;
|
|
106
|
+
};
|
|
107
|
+
_handleHotKeyParsed = (index, hotKey) => {
|
|
108
|
+
this._hotKeyMap.set(index, hotKey);
|
|
109
|
+
};
|
|
110
|
+
_handleOnOutsideClick = (event) => {
|
|
111
|
+
if (this.props.opened && this.props.onOutsideClick)
|
|
112
|
+
this.props.onOutsideClick(event);
|
|
113
|
+
};
|
|
198
114
|
render() {
|
|
199
115
|
const { opened, direction, onOutsideClick, onSelect, onEsc, autoflip, edgeLimit, hotkeySelect, selectedIndex, floating, parentMenu, parentSubmenu, children, className, ignoreNextKeyUp, offset = 0, ...props } = this.props;
|
|
200
116
|
const renderDirection = parentMenu === undefined ? this.state.direction : direction;
|
|
@@ -212,6 +128,94 @@ export class ContextMenu extends React.PureComponent {
|
|
|
212
128
|
"--_core-context-menu-offset": `${offset}px`,
|
|
213
129
|
} }, this._injectedChildren))));
|
|
214
130
|
}
|
|
131
|
+
/** @internal */
|
|
132
|
+
static getCSSClassNameFromDirection = (direction) => {
|
|
133
|
+
let className = "";
|
|
134
|
+
if (direction === undefined)
|
|
135
|
+
direction = ContextMenuDirection.BottomRight;
|
|
136
|
+
if (direction === ContextMenuDirection.None)
|
|
137
|
+
return "";
|
|
138
|
+
switch (direction) {
|
|
139
|
+
case ContextMenuDirection.TopLeft:
|
|
140
|
+
className = "core-context-menu-top core-context-menu-left";
|
|
141
|
+
break;
|
|
142
|
+
case ContextMenuDirection.Top:
|
|
143
|
+
className = "core-context-menu-top";
|
|
144
|
+
break;
|
|
145
|
+
case ContextMenuDirection.TopRight:
|
|
146
|
+
className = "core-context-menu-top core-context-menu-right";
|
|
147
|
+
break;
|
|
148
|
+
case ContextMenuDirection.Left:
|
|
149
|
+
className = "core-context-menu-left";
|
|
150
|
+
break;
|
|
151
|
+
case ContextMenuDirection.Center:
|
|
152
|
+
className = "core-context-menu-center";
|
|
153
|
+
break;
|
|
154
|
+
case ContextMenuDirection.Right:
|
|
155
|
+
className = "core-context-menu-right";
|
|
156
|
+
break;
|
|
157
|
+
case ContextMenuDirection.BottomLeft:
|
|
158
|
+
className = "core-context-menu-bottom core-context-menu-left";
|
|
159
|
+
break;
|
|
160
|
+
case ContextMenuDirection.Bottom:
|
|
161
|
+
className = "core-context-menu-bottom";
|
|
162
|
+
break;
|
|
163
|
+
case ContextMenuDirection.BottomRight:
|
|
164
|
+
className = "core-context-menu-bottom core-context-menu-right";
|
|
165
|
+
break;
|
|
166
|
+
}
|
|
167
|
+
return className;
|
|
168
|
+
};
|
|
169
|
+
_injectMenuItemProps = (children, direction, selectedIndex) => {
|
|
170
|
+
let index = 0;
|
|
171
|
+
// add inheritance data to submenu children
|
|
172
|
+
const ch = React.Children.map(children, (child) => {
|
|
173
|
+
// Capture only ContextSubMenus and ContextMenuItems.
|
|
174
|
+
if (child &&
|
|
175
|
+
typeof child === "object" &&
|
|
176
|
+
"props" in child &&
|
|
177
|
+
(child.type === ContextSubMenu || child.type === ContextMenuItem) &&
|
|
178
|
+
React.isValidElement(child) &&
|
|
179
|
+
!ConditionalBooleanValue.getValue(child.props.disabled) &&
|
|
180
|
+
!ConditionalBooleanValue.getValue(child.props.hidden)) {
|
|
181
|
+
const id = index; // get separate id variable so value stays the same when onHover is called later.
|
|
182
|
+
const onHover = () => {
|
|
183
|
+
this.setState({ selectedIndex: id });
|
|
184
|
+
this.focus();
|
|
185
|
+
};
|
|
186
|
+
const ref = (el) => {
|
|
187
|
+
if (selectedIndex === id)
|
|
188
|
+
// only save to this._selectedElement if previously captured bool is true
|
|
189
|
+
this._selectedElement = el;
|
|
190
|
+
};
|
|
191
|
+
const boundHandleHotKeyParse = this._handleHotKeyParsed.bind(this, id); // bind local callback for specific index
|
|
192
|
+
const childProps = {
|
|
193
|
+
parentMenu: this,
|
|
194
|
+
ref,
|
|
195
|
+
onHover,
|
|
196
|
+
isSelected: selectedIndex === id,
|
|
197
|
+
onHotKeyParsed: boundHandleHotKeyParse,
|
|
198
|
+
};
|
|
199
|
+
if (child.type === ContextSubMenu &&
|
|
200
|
+
React.isValidElement(child)) {
|
|
201
|
+
// add direction only to sub-menus
|
|
202
|
+
childProps.direction = child.props.direction || direction;
|
|
203
|
+
}
|
|
204
|
+
index++;
|
|
205
|
+
return React.cloneElement(child, childProps);
|
|
206
|
+
}
|
|
207
|
+
else
|
|
208
|
+
return child; // Else, pass through unmodified
|
|
209
|
+
});
|
|
210
|
+
this._length = index;
|
|
211
|
+
return ch;
|
|
212
|
+
};
|
|
213
|
+
_rootRef = (el) => {
|
|
214
|
+
this._rootElement = el;
|
|
215
|
+
};
|
|
216
|
+
_menuRef = (el) => {
|
|
217
|
+
this._menuElement = el;
|
|
218
|
+
};
|
|
215
219
|
getWindow() {
|
|
216
220
|
const el = this._rootElement ? this._rootElement : this._menuElement;
|
|
217
221
|
const parentDocument = el.ownerDocument;
|
|
@@ -247,6 +251,107 @@ export class ContextMenu extends React.PureComponent {
|
|
|
247
251
|
this.setState({ direction: renderDirection });
|
|
248
252
|
}
|
|
249
253
|
}
|
|
254
|
+
focus = () => {
|
|
255
|
+
if (this._menuElement)
|
|
256
|
+
this._menuElement.focus();
|
|
257
|
+
};
|
|
258
|
+
blur = () => {
|
|
259
|
+
if (this._menuElement)
|
|
260
|
+
this._menuElement.blur();
|
|
261
|
+
};
|
|
262
|
+
getRect = () => {
|
|
263
|
+
let clientRect = DOMRect.fromRect({ x: 0, y: 0, width: 0, height: 0 });
|
|
264
|
+
if (this._menuElement) {
|
|
265
|
+
clientRect = this._menuElement.getBoundingClientRect();
|
|
266
|
+
}
|
|
267
|
+
return clientRect;
|
|
268
|
+
};
|
|
269
|
+
_handleFocusChange = (event) => {
|
|
270
|
+
if (this._rootElement &&
|
|
271
|
+
this.props.opened &&
|
|
272
|
+
event.target instanceof Node &&
|
|
273
|
+
this.props.onOutsideClick &&
|
|
274
|
+
!this._rootElement.contains(event.target))
|
|
275
|
+
this.props.onOutsideClick(event);
|
|
276
|
+
};
|
|
277
|
+
_handleClick = (event) => {
|
|
278
|
+
if (this.props.onSelect)
|
|
279
|
+
this.props.onSelect(event);
|
|
280
|
+
};
|
|
281
|
+
_handleKeyUp = (event) => {
|
|
282
|
+
if (this.state.ignoreNextKeyUp) {
|
|
283
|
+
this.setState({ ignoreNextKeyUp: false });
|
|
284
|
+
return;
|
|
285
|
+
}
|
|
286
|
+
if (event.key) {
|
|
287
|
+
for (const [key, value] of this._hotKeyMap) {
|
|
288
|
+
if (!this.props.hotkeySelect && key > this.state.selectedIndex) {
|
|
289
|
+
// Start search at current index.
|
|
290
|
+
if (event.key.toUpperCase() === value) {
|
|
291
|
+
this.setState({ selectedIndex: key });
|
|
292
|
+
return;
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
for (const [key, value] of this._hotKeyMap) {
|
|
297
|
+
if (event.key.toUpperCase() === value) {
|
|
298
|
+
this.setState({ selectedIndex: key }, () => {
|
|
299
|
+
if (this.props.hotkeySelect && this._selectedElement) {
|
|
300
|
+
this._selectedElement.select();
|
|
301
|
+
}
|
|
302
|
+
});
|
|
303
|
+
event.stopPropagation();
|
|
304
|
+
return;
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
if (event.key === Key.ArrowLeft.valueOf()) {
|
|
309
|
+
event.stopPropagation();
|
|
310
|
+
if (this.props.parentMenu && this.props.parentSubmenu) {
|
|
311
|
+
this.props.parentSubmenu.close();
|
|
312
|
+
this.props.parentMenu.focus();
|
|
313
|
+
}
|
|
314
|
+
if (this.props.onEsc)
|
|
315
|
+
this.props.onEsc(event);
|
|
316
|
+
}
|
|
317
|
+
if (event.key === Key.Escape.valueOf()) {
|
|
318
|
+
if (this.props.onEsc)
|
|
319
|
+
this.props.onEsc(event);
|
|
320
|
+
}
|
|
321
|
+
if ((event.key === Key.Enter.valueOf() ||
|
|
322
|
+
event.key === Key.ArrowRight.valueOf()) &&
|
|
323
|
+
this._selectedElement) {
|
|
324
|
+
event.stopPropagation();
|
|
325
|
+
if (event.key === Key.Enter.valueOf() ||
|
|
326
|
+
this._selectedElement instanceof ContextSubMenu) {
|
|
327
|
+
if (this._selectedElement.select)
|
|
328
|
+
this._selectedElement.select();
|
|
329
|
+
}
|
|
330
|
+
}
|
|
331
|
+
let { selectedIndex } = this.state;
|
|
332
|
+
if (event.key === Key.ArrowUp.valueOf() ||
|
|
333
|
+
event.key === Key.ArrowDown.valueOf()) {
|
|
334
|
+
event.stopPropagation();
|
|
335
|
+
if (selectedIndex === -1) {
|
|
336
|
+
selectedIndex = 0;
|
|
337
|
+
}
|
|
338
|
+
else {
|
|
339
|
+
if (event.key === Key.ArrowUp.valueOf()) {
|
|
340
|
+
if (this.state.selectedIndex === 0)
|
|
341
|
+
selectedIndex = this._length - 1;
|
|
342
|
+
else
|
|
343
|
+
selectedIndex--;
|
|
344
|
+
}
|
|
345
|
+
if (event.key === Key.ArrowDown.valueOf()) {
|
|
346
|
+
if (this.state.selectedIndex === this._length - 1)
|
|
347
|
+
selectedIndex = 0;
|
|
348
|
+
else
|
|
349
|
+
selectedIndex++;
|
|
350
|
+
}
|
|
351
|
+
}
|
|
352
|
+
}
|
|
353
|
+
this.setState({ selectedIndex });
|
|
354
|
+
};
|
|
250
355
|
/** @internal */
|
|
251
356
|
componentDidUpdate(prevProps) {
|
|
252
357
|
if (prevProps.selectedIndex !== this.props.selectedIndex) {
|
|
@@ -262,106 +367,4 @@ export class ContextMenu extends React.PureComponent {
|
|
|
262
367
|
}
|
|
263
368
|
}
|
|
264
369
|
}
|
|
265
|
-
ContextMenu.defaultProps = {
|
|
266
|
-
direction: ContextMenuDirection.BottomRight,
|
|
267
|
-
autoflip: true,
|
|
268
|
-
edgeLimit: true,
|
|
269
|
-
hotkeySelect: true,
|
|
270
|
-
selectedIndex: -1,
|
|
271
|
-
floating: true,
|
|
272
|
-
};
|
|
273
|
-
/** @internal */
|
|
274
|
-
ContextMenu.autoFlip = (dir, rect, windowWidth, windowHeight) => {
|
|
275
|
-
if (rect.right > windowWidth) {
|
|
276
|
-
switch (dir) {
|
|
277
|
-
case ContextMenuDirection.TopRight:
|
|
278
|
-
dir = ContextMenuDirection.TopLeft;
|
|
279
|
-
break;
|
|
280
|
-
case ContextMenuDirection.Right:
|
|
281
|
-
dir = ContextMenuDirection.Left;
|
|
282
|
-
break;
|
|
283
|
-
case ContextMenuDirection.BottomRight:
|
|
284
|
-
dir = ContextMenuDirection.BottomLeft;
|
|
285
|
-
break;
|
|
286
|
-
}
|
|
287
|
-
}
|
|
288
|
-
if (rect.left < 0) {
|
|
289
|
-
switch (dir) {
|
|
290
|
-
case ContextMenuDirection.TopLeft:
|
|
291
|
-
dir = ContextMenuDirection.TopRight;
|
|
292
|
-
break;
|
|
293
|
-
case ContextMenuDirection.Left:
|
|
294
|
-
dir = ContextMenuDirection.Right;
|
|
295
|
-
break;
|
|
296
|
-
case ContextMenuDirection.BottomLeft:
|
|
297
|
-
dir = ContextMenuDirection.BottomRight;
|
|
298
|
-
break;
|
|
299
|
-
}
|
|
300
|
-
}
|
|
301
|
-
if (rect.bottom > windowHeight) {
|
|
302
|
-
switch (dir) {
|
|
303
|
-
case ContextMenuDirection.BottomLeft:
|
|
304
|
-
dir = ContextMenuDirection.TopLeft;
|
|
305
|
-
break;
|
|
306
|
-
case ContextMenuDirection.Bottom:
|
|
307
|
-
dir = ContextMenuDirection.Top;
|
|
308
|
-
break;
|
|
309
|
-
case ContextMenuDirection.BottomRight:
|
|
310
|
-
dir = ContextMenuDirection.TopRight;
|
|
311
|
-
break;
|
|
312
|
-
}
|
|
313
|
-
}
|
|
314
|
-
if (rect.top < 0) {
|
|
315
|
-
switch (dir) {
|
|
316
|
-
case ContextMenuDirection.TopLeft:
|
|
317
|
-
dir = ContextMenuDirection.BottomLeft;
|
|
318
|
-
break;
|
|
319
|
-
case ContextMenuDirection.Top:
|
|
320
|
-
dir = ContextMenuDirection.Bottom;
|
|
321
|
-
break;
|
|
322
|
-
case ContextMenuDirection.TopRight:
|
|
323
|
-
dir = ContextMenuDirection.BottomRight;
|
|
324
|
-
break;
|
|
325
|
-
}
|
|
326
|
-
}
|
|
327
|
-
return dir;
|
|
328
|
-
};
|
|
329
|
-
/** @internal */
|
|
330
|
-
ContextMenu.getCSSClassNameFromDirection = (direction) => {
|
|
331
|
-
let className = "";
|
|
332
|
-
if (direction === undefined)
|
|
333
|
-
direction = ContextMenuDirection.BottomRight;
|
|
334
|
-
if (direction === ContextMenuDirection.None)
|
|
335
|
-
return "";
|
|
336
|
-
switch (direction) {
|
|
337
|
-
case ContextMenuDirection.TopLeft:
|
|
338
|
-
className = "core-context-menu-top core-context-menu-left";
|
|
339
|
-
break;
|
|
340
|
-
case ContextMenuDirection.Top:
|
|
341
|
-
className = "core-context-menu-top";
|
|
342
|
-
break;
|
|
343
|
-
case ContextMenuDirection.TopRight:
|
|
344
|
-
className = "core-context-menu-top core-context-menu-right";
|
|
345
|
-
break;
|
|
346
|
-
case ContextMenuDirection.Left:
|
|
347
|
-
className = "core-context-menu-left";
|
|
348
|
-
break;
|
|
349
|
-
case ContextMenuDirection.Center:
|
|
350
|
-
className = "core-context-menu-center";
|
|
351
|
-
break;
|
|
352
|
-
case ContextMenuDirection.Right:
|
|
353
|
-
className = "core-context-menu-right";
|
|
354
|
-
break;
|
|
355
|
-
case ContextMenuDirection.BottomLeft:
|
|
356
|
-
className = "core-context-menu-bottom core-context-menu-left";
|
|
357
|
-
break;
|
|
358
|
-
case ContextMenuDirection.Bottom:
|
|
359
|
-
className = "core-context-menu-bottom";
|
|
360
|
-
break;
|
|
361
|
-
case ContextMenuDirection.BottomRight:
|
|
362
|
-
className = "core-context-menu-bottom core-context-menu-right";
|
|
363
|
-
break;
|
|
364
|
-
}
|
|
365
|
-
return className;
|
|
366
|
-
};
|
|
367
370
|
//# sourceMappingURL=ContextMenu.js.map
|