@elyra/canvas 12.40.1 → 12.42.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/{_baseIteratee-05ccf6a8.js → _baseIteratee-148093b7.js} +3 -3
- package/dist/{_baseIteratee-05ccf6a8.js.map → _baseIteratee-148093b7.js.map} +1 -1
- package/dist/{canvas-constants-079172c0.js → canvas-constants-13b58448.js} +2 -2
- package/dist/{canvas-constants-079172c0.js.map → canvas-constants-13b58448.js.map} +1 -1
- package/dist/canvas-controller-a53943e4.js +2 -0
- package/dist/canvas-controller-a53943e4.js.map +1 -0
- package/dist/canvas-controller-cb1d7420.js +2 -0
- package/dist/canvas-controller-cb1d7420.js.map +1 -0
- package/dist/common-canvas-42027a3f.js +2 -0
- package/dist/common-canvas-42027a3f.js.map +1 -0
- package/dist/common-canvas-f758ff42.js +2 -0
- package/dist/common-canvas-f758ff42.js.map +1 -0
- package/dist/common-canvas.es.js +1 -1
- package/dist/common-canvas.es.js.map +1 -1
- package/dist/common-canvas.js +1 -1
- package/dist/common-canvas.js.map +1 -1
- package/dist/common-properties-2e1b7ec7.js +2 -0
- package/dist/common-properties-2e1b7ec7.js.map +1 -0
- package/dist/common-properties-5e8870e3.js +2 -0
- package/dist/common-properties-5e8870e3.js.map +1 -0
- package/dist/context-menu-wrapper-49f9a1af.js +2 -0
- package/dist/context-menu-wrapper-49f9a1af.js.map +1 -0
- package/dist/context-menu-wrapper-5d6a399f.js +2 -0
- package/dist/context-menu-wrapper-5d6a399f.js.map +1 -0
- package/dist/{datarecord-metadata-v3-schema-59505bc5.js → datarecord-metadata-v3-schema-98ec66e9.js} +2 -2
- package/dist/{datarecord-metadata-v3-schema-59505bc5.js.map → datarecord-metadata-v3-schema-98ec66e9.js.map} +1 -1
- package/dist/{flexible-table-5ee2a42b.js → flexible-table-35e9922a.js} +2 -2
- package/dist/{flexible-table-5ee2a42b.js.map → flexible-table-35e9922a.js.map} +1 -1
- package/dist/{flexible-table-562ae288.js → flexible-table-7c7de0f9.js} +1 -1
- package/dist/{flexible-table-562ae288.js.map → flexible-table-7c7de0f9.js.map} +1 -1
- package/dist/{icon-0390f1fe.js → icon-9edff40c.js} +2 -2
- package/dist/{icon-0390f1fe.js.map → icon-9edff40c.js.map} +1 -1
- package/dist/{index-fe8d4201.js → index-94fec521.js} +2 -2
- package/dist/index-94fec521.js.map +1 -0
- package/dist/index-e2f8a935.js +2 -0
- package/dist/index-e2f8a935.js.map +1 -0
- package/dist/{isArrayLikeObject-36898fcb.js → isArrayLikeObject-7a30aa4b.js} +2 -2
- package/dist/{isArrayLikeObject-36898fcb.js.map → isArrayLikeObject-7a30aa4b.js.map} +1 -1
- package/dist/lib/canvas-controller.es.js +1 -1
- package/dist/lib/canvas-controller.js +1 -1
- package/dist/lib/canvas.es.js +1 -1
- package/dist/lib/canvas.js +1 -1
- package/dist/lib/context-menu.es.js +1 -1
- package/dist/lib/context-menu.js +1 -1
- package/dist/lib/properties/field-picker.es.js +1 -1
- package/dist/lib/properties/field-picker.js +1 -1
- package/dist/lib/properties/flexible-table.es.js +1 -1
- package/dist/lib/properties/flexible-table.js +1 -1
- package/dist/lib/properties.es.js +1 -1
- package/dist/lib/properties.js +1 -1
- package/dist/lib/tooltip.es.js +1 -1
- package/dist/lib/tooltip.es.js.map +1 -1
- package/dist/lib/tooltip.js +1 -1
- package/dist/lib/tooltip.js.map +1 -1
- package/dist/styles/common-canvas.min.css +1 -1
- package/dist/styles/common-canvas.min.css.map +1 -1
- package/dist/toolbar-6acda0a2.js +2 -0
- package/dist/toolbar-6acda0a2.js.map +1 -0
- package/dist/toolbar-d5647da2.js +2 -0
- package/dist/toolbar-d5647da2.js.map +1 -0
- package/locales/common-properties/locales/de.json +1 -0
- package/locales/common-properties/locales/es.json +1 -0
- package/locales/common-properties/locales/fr.json +1 -0
- package/locales/common-properties/locales/it.json +1 -0
- package/locales/common-properties/locales/ja.json +1 -0
- package/locales/common-properties/locales/ko.json +1 -0
- package/locales/common-properties/locales/pt-br.json +1 -0
- package/locales/common-properties/locales/sv.json +1 -0
- package/locales/common-properties/locales/zh-CN.json +1 -0
- package/locales/common-properties/locales/zh-TW.json +1 -0
- package/package.json +12 -4
- package/src/color-picker/color-picker.jsx +92 -17
- package/src/command-actions/arrangeLayoutAction.js +7 -6
- package/src/command-actions/attachNodeToLinksAction.js +4 -4
- package/src/command-actions/collapseSuperNodeInPlaceAction.js +5 -5
- package/src/command-actions/colorSelectedObjectsAction.js +4 -4
- package/src/command-actions/commonPropertiesAction.js +1 -1
- package/src/command-actions/convertSuperNodeExternalToLocalAction.js +4 -4
- package/src/command-actions/convertSuperNodeLocalToExternalAction.js +4 -4
- package/src/command-actions/createAutoNodeAction.js +14 -5
- package/src/command-actions/createCommentAction.js +4 -10
- package/src/command-actions/createCommentLinkAction.js +4 -4
- package/src/command-actions/createNodeAction.js +13 -4
- package/src/command-actions/createNodeAttachLinksAction.js +4 -4
- package/src/command-actions/createNodeLinkAction.js +13 -4
- package/src/command-actions/createNodeLinkDetachedAction.js +4 -4
- package/src/command-actions/createNodeOnLinkAction.js +4 -4
- package/src/command-actions/createSuperNodeAction.js +7 -7
- package/src/command-actions/deconstructSuperNodeAction.js +5 -5
- package/src/command-actions/deleteLinkAction.js +4 -4
- package/src/command-actions/deleteObjectsAction.js +15 -6
- package/src/command-actions/disconnectObjectsAction.js +13 -4
- package/src/command-actions/displayPreviousPipelineAction.js +4 -4
- package/src/command-actions/displaySubPipelineAction.js +4 -4
- package/src/command-actions/editCommentAction.js +4 -4
- package/src/command-actions/editDecorationLabelAction.js +4 -4
- package/src/command-actions/expandSuperNodeInPlaceAction.js +5 -5
- package/src/command-actions/insertNodeIntoLinkAction.js +4 -4
- package/src/command-actions/moveObjectsAction.js +4 -4
- package/src/command-actions/pasteAction.js +16 -7
- package/src/command-actions/saveToPaletteAction.js +4 -4
- package/src/command-actions/setLinksStyleAction.js +4 -4
- package/src/command-actions/setNodeLabelAction.js +4 -4
- package/src/command-actions/setObjectsStyleAction.js +4 -4
- package/src/command-actions/sizeAndPositionObjectsAction.js +4 -4
- package/src/command-actions/updateLinkAction.js +4 -4
- package/src/common-canvas/canvas-controller-menu-utils.js +1 -1
- package/src/common-canvas/canvas-controller.js +78 -62
- package/src/common-canvas/cc-central-items.jsx +1 -1
- package/src/common-canvas/cc-context-toolbar.jsx +9 -13
- package/src/common-canvas/cc-toolbar.jsx +2 -0
- package/src/common-canvas/svg-canvas-d3.scss +1 -1
- package/src/common-canvas/svg-canvas-renderer.js +6 -2
- package/src/common-canvas/svg-canvas-utils-drag-det-link.js +8 -1
- package/src/common-canvas/svg-canvas-utils-drag-new-link.js +1 -1
- package/src/common-properties/components/table-buttons/table-buttons.scss +0 -1
- package/src/common-properties/components/wide-flyout/wide-flyout.scss +1 -2
- package/src/common-properties/constants/form-constants.js +1 -0
- package/src/common-properties/controls/control-factory.js +6 -1
- package/src/common-properties/controls/controls.scss +1 -0
- package/src/common-properties/controls/expression/expression-builder/expression-builder.jsx +32 -26
- package/src/common-properties/controls/expression/expression.jsx +146 -117
- package/src/common-properties/controls/expression/expression.scss +43 -45
- package/src/common-properties/controls/expression/languages/CLEM-hint.js +86 -159
- package/src/common-properties/controls/expression/languages/python-hint.js +53 -104
- package/src/common-properties/controls/expression/languages/r-hint.js +55 -130
- package/src/{toolbar/toolbar-utils.js → common-properties/controls/slider/index.js} +2 -17
- package/src/common-properties/controls/slider/slider.jsx +96 -0
- package/src/common-properties/controls/slider/slider.scss +44 -0
- package/src/common-properties/form/ControlInfo.js +6 -0
- package/src/common-properties/form/EditorForm.js +2 -0
- package/src/common-properties/form/ParameterInfo.js +8 -0
- package/src/common-properties/properties-controller.js +16 -5
- package/src/context-menu/common-context-menu.jsx +4 -1
- package/src/index.js +12 -2
- package/src/object-model/redux/canvas-store.js +4 -3
- package/src/toolbar/toolbar-action-item.jsx +90 -314
- package/src/toolbar/toolbar-button-item.jsx +354 -0
- package/src/toolbar/toolbar-divider-item.jsx +3 -4
- package/src/toolbar/toolbar-overflow-item.jsx +82 -36
- package/src/toolbar/toolbar-sub-menu-item.jsx +235 -0
- package/src/toolbar/toolbar-sub-menu.jsx +254 -0
- package/src/toolbar/toolbar-sub-panel.jsx +81 -0
- package/src/toolbar/toolbar-sub-utils.js +77 -0
- package/src/toolbar/toolbar.jsx +330 -146
- package/src/toolbar/toolbar.scss +22 -15
- package/src/tooltip/tooltip.jsx +21 -2
- package/stats.html +1 -1
- package/dist/canvas-controller-1e71b405.js +0 -2
- package/dist/canvas-controller-1e71b405.js.map +0 -1
- package/dist/canvas-controller-4bed5320.js +0 -2
- package/dist/canvas-controller-4bed5320.js.map +0 -1
- package/dist/common-canvas-318df796.js +0 -2
- package/dist/common-canvas-318df796.js.map +0 -1
- package/dist/common-canvas-d41ba910.js +0 -2
- package/dist/common-canvas-d41ba910.js.map +0 -1
- package/dist/common-properties-6e904e3b.js +0 -2
- package/dist/common-properties-6e904e3b.js.map +0 -1
- package/dist/common-properties-c91bfb31.js +0 -2
- package/dist/common-properties-c91bfb31.js.map +0 -1
- package/dist/context-menu-wrapper-3a7fdec8.js +0 -2
- package/dist/context-menu-wrapper-3a7fdec8.js.map +0 -1
- package/dist/context-menu-wrapper-fc85d853.js +0 -2
- package/dist/context-menu-wrapper-fc85d853.js.map +0 -1
- package/dist/index-8e8b8729.js +0 -2
- package/dist/index-8e8b8729.js.map +0 -1
- package/dist/index-fe8d4201.js.map +0 -1
- package/dist/toolbar-b01e6749.js +0 -2
- package/dist/toolbar-b01e6749.js.map +0 -1
- package/dist/toolbar-fd4e4a3a.js +0 -2
- package/dist/toolbar-fd4e4a3a.js.map +0 -1
- package/src/toolbar/toolbar-action-sub-area.jsx +0 -126
- package/src/toolbar/toolbar-overflow-menu.jsx +0 -77
|
@@ -0,0 +1,235 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright 2017-2023 Elyra Authors
|
|
3
|
+
*
|
|
4
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
* you may not use this file except in compliance with the License.
|
|
6
|
+
* You may obtain a copy of the License at
|
|
7
|
+
*
|
|
8
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
*
|
|
10
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
* See the License for the specific language governing permissions and
|
|
14
|
+
* limitations under the License.
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
import React from "react";
|
|
18
|
+
import PropTypes from "prop-types";
|
|
19
|
+
|
|
20
|
+
import ToolbarButtonItem from "./toolbar-button-item.jsx";
|
|
21
|
+
|
|
22
|
+
import classNames from "classnames";
|
|
23
|
+
import ToolbarSubMenu from "./toolbar-sub-menu.jsx";
|
|
24
|
+
import ToolbarSubPanel from "./toolbar-sub-panel.jsx";
|
|
25
|
+
|
|
26
|
+
class ToolbarSubMenuItem extends React.Component {
|
|
27
|
+
constructor(props) {
|
|
28
|
+
super(props);
|
|
29
|
+
|
|
30
|
+
this.state = {
|
|
31
|
+
subAreaDisplayed: false
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
this.divRef = React.createRef();
|
|
35
|
+
|
|
36
|
+
this.actionClickHandler = this.actionClickHandler.bind(this);
|
|
37
|
+
this.onMouseEnter = this.onMouseEnter.bind(this);
|
|
38
|
+
this.onMouseLeave = this.onMouseLeave.bind(this);
|
|
39
|
+
this.openSubArea = this.openSubArea.bind(this);
|
|
40
|
+
this.closeSubArea = this.closeSubArea.bind(this);
|
|
41
|
+
this.clickOutside = this.clickOutside.bind(this);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
// We must remove the eventListener in case this class is unmounted due
|
|
45
|
+
// to the toolbar getting redrawn.
|
|
46
|
+
componentWillUnmount() {
|
|
47
|
+
document.removeEventListener("click", this.clickOutside, false);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
onMouseEnter(evt) {
|
|
51
|
+
if (this.props.actionObj.subMenu || this.props.actionObj.subPanel) {
|
|
52
|
+
this.openSubArea();
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
onMouseLeave(evt) {
|
|
57
|
+
if (this.props.actionObj.subMenu || this.props.actionObj.subPanel) {
|
|
58
|
+
this.closeSubArea();
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
clickOutside(evt) {
|
|
63
|
+
if (this.state.subAreaDisplayed) {
|
|
64
|
+
const items = document.getElementsByClassName(this.generateActionName());
|
|
65
|
+
const isOver = items && items.length > 0 ? items[0].contains(evt.target) : false;
|
|
66
|
+
|
|
67
|
+
if (!isOver) {
|
|
68
|
+
this.closeSubArea();
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
openSubArea() {
|
|
74
|
+
this.setState({ subAreaDisplayed: true });
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
closeSubArea(checkCloseSubAreaOnClick) {
|
|
78
|
+
if (!checkCloseSubAreaOnClick || this.props.actionObj.closeSubAreaOnClick) {
|
|
79
|
+
this.setState({ subAreaDisplayed: false });
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
actionClickHandler(evt) {
|
|
84
|
+
if (this.props.actionObj.subMenu || this.props.actionObj.subPanel) {
|
|
85
|
+
if (this.state.subAreaDisplayed) {
|
|
86
|
+
document.removeEventListener("click", this.clickOutside, false);
|
|
87
|
+
this.closeSubArea();
|
|
88
|
+
} else {
|
|
89
|
+
document.addEventListener("click", this.clickOutside, false);
|
|
90
|
+
this.openSubArea();
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
} else {
|
|
94
|
+
evt.stopPropagation();
|
|
95
|
+
if (this.props.isInCascadeMenu) {
|
|
96
|
+
this.props.closeParentSubArea();
|
|
97
|
+
this.props.setSubMenuFocus();
|
|
98
|
+
|
|
99
|
+
} else if (this.props.isInOverflowMenu) {
|
|
100
|
+
this.props.setSubMenuFocus(this.props.actionObj.action);
|
|
101
|
+
|
|
102
|
+
} else {
|
|
103
|
+
this.props.closeParentSubArea();
|
|
104
|
+
this.props.setToolbarFocusAction(); // Resets the toolbar focus action
|
|
105
|
+
}
|
|
106
|
+
this.props.toolbarActionHandler(this.props.actionObj.action, evt);
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
generateActionName() {
|
|
111
|
+
return this.props.actionObj.action + "-action";
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
// Returns a sub-area for a cascading menu item. The sub-area can be either a
|
|
115
|
+
// sub-panel which is a div contaiing whatever the caller passes in within the
|
|
116
|
+
// supPanel field OR a sub-menu which is a list of options which is created
|
|
117
|
+
// from the array of items the caller passes in the subMenu field.
|
|
118
|
+
generateSubArea() {
|
|
119
|
+
const actionItemRect = this.divRef.current.getBoundingClientRect();
|
|
120
|
+
|
|
121
|
+
if (this.props.actionObj.subPanel) {
|
|
122
|
+
return (
|
|
123
|
+
<ToolbarSubPanel
|
|
124
|
+
subPanel={this.props.actionObj.subPanel}
|
|
125
|
+
subPanelData={this.props.actionObj.subPanelData}
|
|
126
|
+
closeSubArea={this.closeSubArea}
|
|
127
|
+
actionItemRect={actionItemRect}
|
|
128
|
+
expandDirection={"horizontal"}
|
|
129
|
+
containingDivId={this.props.containingDivId}
|
|
130
|
+
/>
|
|
131
|
+
);
|
|
132
|
+
}
|
|
133
|
+
return (
|
|
134
|
+
<ToolbarSubMenu
|
|
135
|
+
subMenuActions={this.props.actionObj.subMenu}
|
|
136
|
+
instanceId={this.props.instanceId}
|
|
137
|
+
toolbarActionHandler={this.props.toolbarActionHandler}
|
|
138
|
+
setSubMenuFocus={this.props.setSubMenuFocus}
|
|
139
|
+
closeSubArea={this.closeSubArea}
|
|
140
|
+
actionItemRect={actionItemRect}
|
|
141
|
+
expandDirection={"horizontal"}
|
|
142
|
+
containingDivId={this.props.containingDivId}
|
|
143
|
+
parentSelector={this.generateSelector()}
|
|
144
|
+
isCascadeMenu
|
|
145
|
+
size={this.props.size}
|
|
146
|
+
/>
|
|
147
|
+
);
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
generateSelector() {
|
|
151
|
+
return ".toolbar-sub-menu-item";
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
render() {
|
|
155
|
+
const actionObj = this.props.actionObj;
|
|
156
|
+
const actionName = this.generateActionName();
|
|
157
|
+
const kindAsClass = actionObj.kind ? actionObj.kind : "default";
|
|
158
|
+
|
|
159
|
+
const itemClassName = classNames(
|
|
160
|
+
{ "toolbar-sub-menu-item": true,
|
|
161
|
+
"toolbar-sub-menu-jsx-item": actionObj.jsx,
|
|
162
|
+
"toolbar-item-selected": actionObj.isSelected },
|
|
163
|
+
kindAsClass,
|
|
164
|
+
actionName);
|
|
165
|
+
|
|
166
|
+
const subArea = this.state.subAreaDisplayed ? this.generateSubArea() : null;
|
|
167
|
+
|
|
168
|
+
return (
|
|
169
|
+
<div ref={this.divRef} className={itemClassName} data-toolbar-action={actionObj.action}
|
|
170
|
+
onMouseEnter={this.onMouseEnter} onMouseLeave={this.onMouseLeave} onKeyDown={this.onKeyDown}
|
|
171
|
+
>
|
|
172
|
+
<div>
|
|
173
|
+
<ToolbarButtonItem
|
|
174
|
+
actionObj={actionObj}
|
|
175
|
+
actionName={this.generateActionName()}
|
|
176
|
+
instanceId={this.props.instanceId}
|
|
177
|
+
isInMenu
|
|
178
|
+
subAreaDisplayed={this.state.subAreaDisplayed}
|
|
179
|
+
actionClickHandler={this.actionClickHandler}
|
|
180
|
+
buttonFocusAction={this.props.subMenuFocusAction}
|
|
181
|
+
isFocusInToolbar // Focus must be in toolbar for this sub-menu item to appear
|
|
182
|
+
size={this.props.size}
|
|
183
|
+
/>
|
|
184
|
+
</div>
|
|
185
|
+
{subArea}
|
|
186
|
+
</div>
|
|
187
|
+
);
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
ToolbarSubMenuItem.propTypes = {
|
|
192
|
+
actionObj: PropTypes.shape({
|
|
193
|
+
action: PropTypes.string.isRequired,
|
|
194
|
+
label: PropTypes.oneOfType([
|
|
195
|
+
PropTypes.string,
|
|
196
|
+
PropTypes.object
|
|
197
|
+
]),
|
|
198
|
+
incLabelWithIcon: PropTypes.oneOf(["no", "before", "after"]),
|
|
199
|
+
enable: PropTypes.bool,
|
|
200
|
+
iconEnabled: PropTypes.oneOfType([
|
|
201
|
+
PropTypes.string,
|
|
202
|
+
PropTypes.object
|
|
203
|
+
]),
|
|
204
|
+
iconDisabled: PropTypes.oneOfType([
|
|
205
|
+
PropTypes.string,
|
|
206
|
+
PropTypes.object
|
|
207
|
+
]),
|
|
208
|
+
className: PropTypes.string,
|
|
209
|
+
textContent: PropTypes.string,
|
|
210
|
+
isSelected: PropTypes.bool,
|
|
211
|
+
kind: PropTypes.string,
|
|
212
|
+
closeSubAreaOnClick: PropTypes.bool,
|
|
213
|
+
subMenu: PropTypes.array,
|
|
214
|
+
subPanel: PropTypes.any,
|
|
215
|
+
subPanelData: PropTypes.object,
|
|
216
|
+
jsx: PropTypes.object,
|
|
217
|
+
tooltip: PropTypes.oneOfType([
|
|
218
|
+
PropTypes.string,
|
|
219
|
+
PropTypes.object,
|
|
220
|
+
PropTypes.func
|
|
221
|
+
])
|
|
222
|
+
}),
|
|
223
|
+
toolbarActionHandler: PropTypes.func.isRequired,
|
|
224
|
+
instanceId: PropTypes.number.isRequired,
|
|
225
|
+
containingDivId: PropTypes.string,
|
|
226
|
+
closeParentSubArea: PropTypes.func,
|
|
227
|
+
subMenuFocusAction: PropTypes.string,
|
|
228
|
+
setToolbarFocusAction: PropTypes.func,
|
|
229
|
+
setSubMenuFocus: PropTypes.func,
|
|
230
|
+
isInOverflowMenu: PropTypes.bool,
|
|
231
|
+
isInCascadeMenu: PropTypes.bool,
|
|
232
|
+
size: PropTypes.oneOf(["md", "sm"])
|
|
233
|
+
};
|
|
234
|
+
|
|
235
|
+
export default ToolbarSubMenuItem;
|
|
@@ -0,0 +1,254 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright 2023 Elyra Authors
|
|
3
|
+
*
|
|
4
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
* you may not use this file except in compliance with the License.
|
|
6
|
+
* You may obtain a copy of the License at
|
|
7
|
+
*
|
|
8
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
*
|
|
10
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
* See the License for the specific language governing permissions and
|
|
14
|
+
* limitations under the License.
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
import React from "react";
|
|
18
|
+
import PropTypes from "prop-types";
|
|
19
|
+
import ToolbarSubMenuItem from "./toolbar-sub-menu-item.jsx";
|
|
20
|
+
import ToolbarDividerItem from "./toolbar-divider-item";
|
|
21
|
+
|
|
22
|
+
import { adjustSubAreaPosition, generateSubAreaStyle } from "./toolbar-sub-utils.js";
|
|
23
|
+
|
|
24
|
+
const ESC_KEY = 27;
|
|
25
|
+
const LEFT_ARROW_KEY = 37;
|
|
26
|
+
const UP_ARROW_KEY = 38;
|
|
27
|
+
const RIGHT_ARROW_KEY = 39;
|
|
28
|
+
const DOWN_ARROW_KEY = 40;
|
|
29
|
+
|
|
30
|
+
class ToolbarSubMenu extends React.Component {
|
|
31
|
+
constructor(props) {
|
|
32
|
+
super(props);
|
|
33
|
+
|
|
34
|
+
this.state = {
|
|
35
|
+
focusAction: "subarea"
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
this.areaRef = React.createRef();
|
|
39
|
+
|
|
40
|
+
this.onKeyDown = this.onKeyDown.bind(this);
|
|
41
|
+
this.setFocusAction = this.setFocusAction.bind(this);
|
|
42
|
+
this.setSubMenuFocus = this.setSubMenuFocus.bind(this);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
componentDidMount() {
|
|
46
|
+
if (this.props.containingDivId && this.props.subMenuActions.length > 0) {
|
|
47
|
+
adjustSubAreaPosition(this.areaRef,
|
|
48
|
+
this.props.containingDivId, this.props.expandDirection, this.props.actionItemRect);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
if (this.state.focusAction === "subarea") {
|
|
52
|
+
this.setFocusOnFirstItem();
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
componentDidUpdate() {
|
|
57
|
+
if (this.state.focusAction !== "subarea") {
|
|
58
|
+
const actionObj = this.props.subMenuActions.find((sma) => sma.action === this.state.focusAction);
|
|
59
|
+
if (!actionObj?.enable) {
|
|
60
|
+
const actionToSet = this.getClosestEnabledAction(this.state.focusAction);
|
|
61
|
+
if (actionToSet !== null) {
|
|
62
|
+
this.setFocusAction(actionToSet);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
onKeyDown(evt) {
|
|
69
|
+
if (evt.keyCode === ESC_KEY) {
|
|
70
|
+
this.props.closeSubArea();
|
|
71
|
+
evt.stopPropagation(); // Stop propagation in a case we are a cascade menu
|
|
72
|
+
|
|
73
|
+
} else if (evt.keyCode === UP_ARROW_KEY) {
|
|
74
|
+
this.setFocusOnPreviousItem();
|
|
75
|
+
evt.stopPropagation(); // Stop propagation in a case we are a cascade menu
|
|
76
|
+
|
|
77
|
+
} else if (evt.keyCode === DOWN_ARROW_KEY) {
|
|
78
|
+
this.setFocusOnNextItem();
|
|
79
|
+
evt.stopPropagation(); // Stop propagation in a case we are a cascade menu
|
|
80
|
+
|
|
81
|
+
} else if (evt.keyCode === LEFT_ARROW_KEY) {
|
|
82
|
+
evt.stopPropagation(); // Stop propagation in a case we are a cascade menu
|
|
83
|
+
|
|
84
|
+
} else if (evt.keyCode === RIGHT_ARROW_KEY) {
|
|
85
|
+
evt.stopPropagation(); // Stop propagation in a case we are a cascade menu
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
setFocusOnFirstItem() {
|
|
90
|
+
const focusableActions = this.getFocusableActions();
|
|
91
|
+
if (focusableActions.length > 0) {
|
|
92
|
+
this.setFocusAction(focusableActions[0].action);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
setFocusOnPreviousItem() {
|
|
97
|
+
const focusableActions = this.getFocusableActions();
|
|
98
|
+
const previousFocusAction = this.getPreviousFocusAction(focusableActions);
|
|
99
|
+
if (previousFocusAction) {
|
|
100
|
+
this.setFocusAction(previousFocusAction.action);
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
setFocusOnNextItem() {
|
|
105
|
+
const focusableActions = this.getFocusableActions();
|
|
106
|
+
const nextFocusAction = this.getNextFocusAction(focusableActions);
|
|
107
|
+
if (nextFocusAction) {
|
|
108
|
+
this.setFocusAction(nextFocusAction.action);
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
setFocusAction(focusAction) {
|
|
113
|
+
this.setState({ focusAction });
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
setSubMenuFocus(action) {
|
|
117
|
+
const actionToSet = action || this.state.focusAction;
|
|
118
|
+
this.setFocusAction(actionToSet);
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
getClosestEnabledAction(action) {
|
|
122
|
+
const index = this.props.subMenuActions.findIndex((sma) => sma.action === action);
|
|
123
|
+
let newAction = null;
|
|
124
|
+
let indexUp = index + 1;
|
|
125
|
+
let indexDown = index - 1;
|
|
126
|
+
|
|
127
|
+
while ((indexDown > -1 || indexUp < this.props.subMenuActions.length) && newAction === null) {
|
|
128
|
+
if (indexDown > -1 && this.props.subMenuActions[indexDown].enable) {
|
|
129
|
+
newAction = this.props.subMenuActions[indexDown].action;
|
|
130
|
+
} else {
|
|
131
|
+
indexDown--;
|
|
132
|
+
}
|
|
133
|
+
if (indexUp < this.props.subMenuActions.length && this.props.subMenuActions[indexUp].enable) {
|
|
134
|
+
newAction = this.props.subMenuActions[indexUp].action;
|
|
135
|
+
} else {
|
|
136
|
+
indexUp++;
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
return newAction;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
getFocusableActions() {
|
|
143
|
+
const focusableActions = [];
|
|
144
|
+
|
|
145
|
+
for (let i = 0; i < this.props.subMenuActions.length; i++) {
|
|
146
|
+
if (this.props.subMenuActions[i].enable) {
|
|
147
|
+
focusableActions.push(this.props.subMenuActions[i]);
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
return focusableActions;
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
getPreviousFocusAction(focuableActions) {
|
|
155
|
+
const index = focuableActions.findIndex((fa) => fa.action === this.state.focusAction);
|
|
156
|
+
if (index > 0) {
|
|
157
|
+
return focuableActions[index - 1];
|
|
158
|
+
}
|
|
159
|
+
return focuableActions[focuableActions.length - 1];
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
getNextFocusAction(focuableActions) {
|
|
163
|
+
const index = focuableActions.findIndex((fa) => fa.action === this.state.focusAction);
|
|
164
|
+
if (index < focuableActions.length - 1) {
|
|
165
|
+
return focuableActions[index + 1];
|
|
166
|
+
}
|
|
167
|
+
return focuableActions[0];
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
// Generates an array of JSX objects for a sub-menu defined by the
|
|
171
|
+
// prop subMenuActions parameter array.
|
|
172
|
+
generateSubMenuItems() {
|
|
173
|
+
const newItems = [];
|
|
174
|
+
|
|
175
|
+
for (let i = 0; i < this.props.subMenuActions.length; i++) {
|
|
176
|
+
const actionObj = this.props.subMenuActions[i];
|
|
177
|
+
if (actionObj) {
|
|
178
|
+
newItems.push(this.generateSubMenuItem(actionObj, i));
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
return newItems;
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
// Returns JSX for a toolbar item based on the actionObj passed in.
|
|
185
|
+
generateSubMenuItem(actionObj, i) {
|
|
186
|
+
let jsx = null;
|
|
187
|
+
|
|
188
|
+
if (actionObj) {
|
|
189
|
+
if (actionObj.divider) {
|
|
190
|
+
jsx = (
|
|
191
|
+
<ToolbarDividerItem
|
|
192
|
+
key={"toolbar-item-key-" + i}
|
|
193
|
+
isInMenu
|
|
194
|
+
/>
|
|
195
|
+
);
|
|
196
|
+
} else {
|
|
197
|
+
jsx = (
|
|
198
|
+
<ToolbarSubMenuItem
|
|
199
|
+
key={"toolbar-item-key-" + i}
|
|
200
|
+
actionObj={actionObj}
|
|
201
|
+
toolbarActionHandler={this.props.toolbarActionHandler}
|
|
202
|
+
closeParentSubArea={this.props.closeSubArea}
|
|
203
|
+
instanceId={this.props.instanceId}
|
|
204
|
+
containingDivId={this.props.containingDivId}
|
|
205
|
+
subMenuFocusAction={this.state.focusAction}
|
|
206
|
+
setToolbarFocusAction={this.props.setToolbarFocusAction}
|
|
207
|
+
setSubMenuFocus={this.props.setSubMenuFocus ? this.props.setSubMenuFocus : this.setSubMenuFocus}
|
|
208
|
+
size={this.props.size}
|
|
209
|
+
isInOverflowMenu={this.props.isOverflowMenu}
|
|
210
|
+
isInCascadeMenu={this.props.isCascadeMenu}
|
|
211
|
+
/>
|
|
212
|
+
);
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
return jsx;
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
render() {
|
|
219
|
+
if (this.props.subMenuActions.length > 0) {
|
|
220
|
+
const style = this.props.isCascadeMenu
|
|
221
|
+
? generateSubAreaStyle(this.props.expandDirection, this.props.actionItemRect)
|
|
222
|
+
: null;
|
|
223
|
+
|
|
224
|
+
this.subMenuItems = this.generateSubMenuItems();
|
|
225
|
+
|
|
226
|
+
return (
|
|
227
|
+
<div ref={this.areaRef} style={style} className={"toolbar-popover-list submenu"}
|
|
228
|
+
tabIndex={-1} onKeyDown={this.onKeyDown}
|
|
229
|
+
>
|
|
230
|
+
{this.subMenuItems}
|
|
231
|
+
</div>
|
|
232
|
+
);
|
|
233
|
+
}
|
|
234
|
+
return null;
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
ToolbarSubMenu.propTypes = {
|
|
239
|
+
subMenuActions: PropTypes.array.isRequired,
|
|
240
|
+
instanceId: PropTypes.number.isRequired,
|
|
241
|
+
toolbarActionHandler: PropTypes.func,
|
|
242
|
+
closeSubArea: PropTypes.func,
|
|
243
|
+
setToolbarFocusAction: PropTypes.func,
|
|
244
|
+
setSubMenuFocus: PropTypes.func,
|
|
245
|
+
actionItemRect: PropTypes.object.isRequired,
|
|
246
|
+
expandDirection: PropTypes.string.isRequired,
|
|
247
|
+
containingDivId: PropTypes.string,
|
|
248
|
+
parentSelector: PropTypes.string,
|
|
249
|
+
isOverflowMenu: PropTypes.bool,
|
|
250
|
+
isCascadeMenu: PropTypes.bool,
|
|
251
|
+
size: PropTypes.oneOf(["md", "sm"])
|
|
252
|
+
};
|
|
253
|
+
|
|
254
|
+
export default ToolbarSubMenu;
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright 2023 Elyra Authors
|
|
3
|
+
*
|
|
4
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
* you may not use this file except in compliance with the License.
|
|
6
|
+
* You may obtain a copy of the License at
|
|
7
|
+
*
|
|
8
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
*
|
|
10
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
* See the License for the specific language governing permissions and
|
|
14
|
+
* limitations under the License.
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
import React from "react";
|
|
18
|
+
import PropTypes from "prop-types";
|
|
19
|
+
|
|
20
|
+
import { adjustSubAreaPosition, generateSubAreaStyle } from "./toolbar-sub-utils.js";
|
|
21
|
+
|
|
22
|
+
const ESC_KEY = 27;
|
|
23
|
+
|
|
24
|
+
class ToolbarSubPanel extends React.Component {
|
|
25
|
+
constructor(props) {
|
|
26
|
+
super(props);
|
|
27
|
+
|
|
28
|
+
this.areaRef = React.createRef();
|
|
29
|
+
|
|
30
|
+
this.onClick = this.onClick.bind(this);
|
|
31
|
+
this.onKeyDown = this.onKeyDown.bind(this);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
componentDidMount() {
|
|
35
|
+
if (this.props.containingDivId) {
|
|
36
|
+
adjustSubAreaPosition(this.areaRef,
|
|
37
|
+
this.props.containingDivId, this.props.expandDirection, this.props.actionItemRect);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
onClick() {
|
|
42
|
+
this.props.closeSubArea();
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
onKeyDown(evt) {
|
|
46
|
+
if (evt.keyCode === ESC_KEY) {
|
|
47
|
+
this.props.closeSubArea();
|
|
48
|
+
evt.stopPropagation();
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
render() {
|
|
53
|
+
const style = generateSubAreaStyle(this.props.expandDirection, this.props.actionItemRect);
|
|
54
|
+
|
|
55
|
+
if (this.props.subPanel) {
|
|
56
|
+
const subPanel = typeof this.props.subPanel === "object"
|
|
57
|
+
? this.props.subPanel
|
|
58
|
+
: (<this.props.subPanel closeSubPanel={this.props.closeSubArea} subPanelData={this.props.subPanelData} />);
|
|
59
|
+
|
|
60
|
+
return (
|
|
61
|
+
<div ref={this.areaRef} style={style} className={"toolbar-popover-list subpanel"} onClick={this.onClick} onKeyDown={this.onKeyDown}>
|
|
62
|
+
{subPanel}
|
|
63
|
+
</div>
|
|
64
|
+
);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
return null;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
ToolbarSubPanel.propTypes = {
|
|
72
|
+
subPanel: PropTypes.any,
|
|
73
|
+
subPanelData: PropTypes.object,
|
|
74
|
+
closeSubArea: PropTypes.func,
|
|
75
|
+
setToolbarFocusAction: PropTypes.func,
|
|
76
|
+
actionItemRect: PropTypes.object.isRequired,
|
|
77
|
+
expandDirection: PropTypes.string.isRequired,
|
|
78
|
+
containingDivId: PropTypes.string
|
|
79
|
+
};
|
|
80
|
+
|
|
81
|
+
export default ToolbarSubPanel;
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright 2023 Elyra Authors
|
|
3
|
+
*
|
|
4
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
* you may not use this file except in compliance with the License.
|
|
6
|
+
* You may obtain a copy of the License at
|
|
7
|
+
*
|
|
8
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
*
|
|
10
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
* See the License for the specific language governing permissions and
|
|
14
|
+
* limitations under the License.
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
// These utility functions are used by both toolbar-sub-menu.jsx AND
|
|
18
|
+
// toolbar-sub-panel.jsx to position the areaEf (menu or panel) relative
|
|
19
|
+
// to the parent actionItemRect, passed in, in the direction indicated by
|
|
20
|
+
// the expandDirection parameter and constrained within the <div>
|
|
21
|
+
// specified by the containingDivId parameter.
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
// Adjust the position of the sub-area to make sure it doesn't extend
|
|
25
|
+
// outside the containing divs boundary. We need to do this after the subarea
|
|
26
|
+
// has been mounted so we can query its size and position.
|
|
27
|
+
export function adjustSubAreaPosition(areaRef, containingDivId, expandDirection, actionItemRect) {
|
|
28
|
+
const containingDiv = document.getElementById(containingDivId);
|
|
29
|
+
const containingDivRect = containingDiv.getBoundingClientRect();
|
|
30
|
+
|
|
31
|
+
const thisAreaRect = areaRef.current.getBoundingClientRect();
|
|
32
|
+
|
|
33
|
+
const outsideBottom = thisAreaRect.bottom - containingDivRect.bottom;
|
|
34
|
+
const outsideRight = thisAreaRect.right - containingDivRect.right;
|
|
35
|
+
|
|
36
|
+
if (expandDirection === "vertical") {
|
|
37
|
+
if (outsideBottom > 0) {
|
|
38
|
+
const topGap = actionItemRect.top - containingDivRect.top;
|
|
39
|
+
const newTop = (topGap > thisAreaRect.height)
|
|
40
|
+
? actionItemRect.top - thisAreaRect.height
|
|
41
|
+
: actionItemRect.bottom - outsideBottom;
|
|
42
|
+
|
|
43
|
+
areaRef.current.style.top = newTop + "px";
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
if (outsideRight > 0) {
|
|
47
|
+
const newLeft = actionItemRect.left - outsideRight - 2;
|
|
48
|
+
areaRef.current.style.left = newLeft + "px";
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
} else {
|
|
52
|
+
if (outsideBottom > 0) {
|
|
53
|
+
const newTop = thisAreaRect.top - outsideBottom - 2;
|
|
54
|
+
areaRef.current.style.top = newTop + "px";
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
if (outsideRight > 0) {
|
|
58
|
+
const newLeft = actionItemRect.left - thisAreaRect.width;
|
|
59
|
+
areaRef.current.style.left = newLeft + "px";
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
export function generateSubAreaStyle(expandDirection, actionItemRect) {
|
|
65
|
+
if (expandDirection === "vertical") {
|
|
66
|
+
return {
|
|
67
|
+
top: actionItemRect.bottom + 1,
|
|
68
|
+
left: actionItemRect.left
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
return {
|
|
72
|
+
top: actionItemRect.top - 1,
|
|
73
|
+
left: actionItemRect.left + actionItemRect.width
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
|