@elyra/canvas 12.42.0 → 12.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/{canvas-constants-ff5cf88e.js → canvas-constants-089e7830.js} +2 -2
- package/dist/{canvas-constants-ff5cf88e.js.map → canvas-constants-089e7830.js.map} +1 -1
- package/dist/{canvas-constants-13b58448.js → canvas-constants-69e90162.js} +2 -2
- package/dist/{canvas-constants-13b58448.js.map → canvas-constants-69e90162.js.map} +1 -1
- package/dist/canvas-controller-3e6b8ce4.js +2 -0
- package/dist/canvas-controller-3e6b8ce4.js.map +1 -0
- package/dist/canvas-controller-c6274fad.js +2 -0
- package/dist/canvas-controller-c6274fad.js.map +1 -0
- package/dist/{canvas-logger-295dafe4.js → canvas-logger-6f4b2551.js} +2 -2
- package/dist/{canvas-logger-295dafe4.js.map → canvas-logger-6f4b2551.js.map} +1 -1
- package/dist/{canvas-logger-e07a0b4a.js → canvas-logger-ab9d9048.js} +2 -2
- package/dist/{canvas-logger-e07a0b4a.js.map → canvas-logger-ab9d9048.js.map} +1 -1
- package/dist/common-canvas-6ed21ab6.js +2 -0
- package/dist/common-canvas-6ed21ab6.js.map +1 -0
- package/dist/common-canvas-8abf016c.js +2 -0
- package/dist/common-canvas-8abf016c.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-88377242.js +2 -0
- package/dist/common-properties-88377242.js.map +1 -0
- package/dist/common-properties-b295acc8.js +2 -0
- package/dist/common-properties-b295acc8.js.map +1 -0
- package/dist/context-menu-wrapper-949393c7.js +2 -0
- package/dist/context-menu-wrapper-949393c7.js.map +1 -0
- package/dist/context-menu-wrapper-f62dfcdb.js +2 -0
- package/dist/context-menu-wrapper-f62dfcdb.js.map +1 -0
- package/dist/{createClass-440000a3.js → createClass-02596015.js} +2 -2
- package/dist/createClass-02596015.js.map +1 -0
- package/dist/createClass-155bf7da.js +2 -0
- package/dist/createClass-155bf7da.js.map +1 -0
- package/dist/datarecord-metadata-v3-schema-07d18e19.js +2 -0
- package/dist/{datarecord-metadata-v3-schema-98ec66e9.js.map → datarecord-metadata-v3-schema-07d18e19.js.map} +1 -1
- package/dist/datarecord-metadata-v3-schema-df939dd1.js +2 -0
- package/dist/{datarecord-metadata-v3-schema-dba0b214.js.map → datarecord-metadata-v3-schema-df939dd1.js.map} +1 -1
- package/dist/defineProperty-ad55dbff.js +2 -0
- package/dist/{defineProperty-3dc7d8d0.js.map → defineProperty-ad55dbff.js.map} +1 -1
- package/dist/{defineProperty-6d406743.js → defineProperty-bcc9968d.js} +2 -2
- package/dist/{defineProperty-6d406743.js.map → defineProperty-bcc9968d.js.map} +1 -1
- package/dist/flexible-table-c6a8b402.js +2 -0
- package/dist/{flexible-table-7c7de0f9.js.map → flexible-table-c6a8b402.js.map} +1 -1
- package/dist/flexible-table-f7b294a0.js +2 -0
- package/dist/{flexible-table-35e9922a.js.map → flexible-table-f7b294a0.js.map} +1 -1
- package/dist/{icon-9edff40c.js → icon-56b27c4f.js} +2 -2
- package/dist/{icon-9edff40c.js.map → icon-56b27c4f.js.map} +1 -1
- package/dist/{icon-e622f99b.js → icon-8ec2f0ec.js} +2 -2
- package/dist/{icon-e622f99b.js.map → icon-8ec2f0ec.js.map} +1 -1
- package/dist/index-01cbacf9.js +2 -0
- package/dist/{index-e2f8a935.js.map → index-01cbacf9.js.map} +1 -1
- package/dist/index-79543d41.js +2 -0
- package/dist/{index-94fec521.js.map → index-79543d41.js.map} +1 -1
- package/dist/inherits-42ae8426.js +2 -0
- package/dist/inherits-42ae8426.js.map +1 -0
- package/dist/inherits-75817f22.js +2 -0
- package/dist/inherits-75817f22.js.map +1 -0
- package/dist/isArrayLikeObject-04f333a5.js +1 -1
- package/dist/isArrayLikeObject-04f333a5.js.map +1 -1
- package/dist/isArrayLikeObject-7a30aa4b.js +1 -1
- package/dist/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/command-stack.es.js +1 -1
- package/dist/lib/command-stack.es.js.map +1 -1
- package/dist/lib/command-stack.js +1 -1
- package/dist/lib/command-stack.js.map +1 -1
- package/dist/lib/context-menu.es.js +1 -1
- package/dist/lib/context-menu.js +1 -1
- package/dist/lib/properties/clem.es.js +2 -0
- package/dist/lib/properties/clem.es.js.map +1 -0
- package/dist/lib/properties/clem.js +2 -0
- package/dist/lib/properties/clem.js.map +1 -0
- 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/getPythonHints.es.js +2 -0
- package/dist/lib/properties/getPythonHints.es.js.map +1 -0
- package/dist/lib/properties/getPythonHints.js +2 -0
- package/dist/lib/properties/getPythonHints.js.map +1 -0
- 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-235dfb9d.js +2 -0
- package/dist/toolbar-235dfb9d.js.map +1 -0
- package/dist/toolbar-6607e35c.js +2 -0
- package/dist/toolbar-6607e35c.js.map +1 -0
- package/package.json +3 -3
- package/rollup.config.js +2 -0
- package/src/color-picker/color-picker.jsx +5 -1
- package/src/common-canvas/canvas-controller.js +56 -1
- package/src/common-canvas/cc-central-items.jsx +0 -4
- package/src/common-canvas/cc-toolbar.jsx +35 -13
- package/src/common-canvas/common-canvas-utils.js +73 -2
- package/src/common-canvas/common-canvas.scss +8 -8
- package/src/common-canvas/constants/canvas-constants.js +1 -0
- package/src/common-canvas/svg-canvas-d3.scss +3 -2
- package/src/common-canvas/svg-canvas-renderer.js +184 -94
- package/src/common-canvas/svg-canvas-utils-external.js +1 -1
- package/src/common-canvas/svg-canvas-utils-links.js +28 -32
- package/src/common-canvas/svg-canvas-utils-nodes.js +5 -13
- package/src/common-properties/components/field-picker/field-picker.jsx +4 -0
- package/src/common-properties/controls/checkbox/checkbox.scss +0 -1
- package/src/common-properties/controls/expression/expression.jsx +3 -5
- package/src/common-properties/controls/expression/languages/python-hint.js +18 -30
- package/src/common-properties/controls/expression/languages/r-hint.js +16 -8
- package/src/common-properties/index.js +4 -2
- package/src/icons/icon.scss +1 -1
- package/src/index.js +2 -2
- package/src/notification-panel/notification-panel.jsx +82 -56
- package/src/notification-panel/notification-panel.scss +42 -40
- package/src/object-model/config-utils.js +2 -2
- package/src/object-model/layout-dimensions.js +82 -87
- package/src/object-model/object-model-utils.js +271 -0
- package/src/object-model/object-model.js +47 -245
- package/src/object-model/redux/reducers/canvasinfo.js +7 -11
- package/src/object-model/redux/reducers/canvastoolbar.js +5 -6
- package/src/palette/palette-dialog-topbar.jsx +27 -38
- package/src/palette/palette-flyout-content-category.jsx +25 -6
- package/src/palette/palette.scss +8 -40
- package/src/toolbar/index.js +18 -0
- package/src/toolbar/toolbar-action-item.jsx +42 -11
- package/src/toolbar/toolbar-button-item.jsx +49 -21
- package/src/toolbar/toolbar-divider-item.jsx +1 -1
- package/src/toolbar/toolbar-overflow-item.jsx +14 -6
- package/src/toolbar/toolbar-sub-menu-item.jsx +6 -5
- package/src/toolbar/toolbar-sub-menu.jsx +4 -6
- package/src/toolbar/toolbar-sub-panel.jsx +31 -18
- package/src/toolbar/toolbar-sub-utils.js +21 -12
- package/src/toolbar/toolbar.jsx +83 -26
- package/src/toolbar/toolbar.scss +47 -47
- package/src/tooltip/tooltip.jsx +56 -10
- package/stats.html +1 -1
- package/assets/images/palette/close_32.svg +0 -1
- package/assets/images/palette/palette_close.svg +0 -4
- package/assets/images/palette/palette_grid_deselected.svg +0 -2
- package/assets/images/palette/palette_grid_hover.svg +0 -2
- package/assets/images/palette/palette_grid_selected.svg +0 -2
- package/assets/images/palette/palette_list_deselected.svg +0 -1
- package/assets/images/palette/palette_list_hover.svg +0 -1
- package/assets/images/palette/palette_list_selected.svg +0 -1
- package/assets/images/palette/palette_open.svg +0 -4
- package/assets/images/zoom_to_fit.svg +0 -8
- package/dist/canvas-controller-a53943e4.js +0 -2
- package/dist/canvas-controller-a53943e4.js.map +0 -1
- package/dist/canvas-controller-cb1d7420.js +0 -2
- package/dist/canvas-controller-cb1d7420.js.map +0 -1
- package/dist/common-canvas-42027a3f.js +0 -2
- package/dist/common-canvas-42027a3f.js.map +0 -1
- package/dist/common-canvas-f758ff42.js +0 -2
- package/dist/common-canvas-f758ff42.js.map +0 -1
- package/dist/common-properties-2e1b7ec7.js +0 -2
- package/dist/common-properties-2e1b7ec7.js.map +0 -1
- package/dist/common-properties-5e8870e3.js +0 -2
- package/dist/common-properties-5e8870e3.js.map +0 -1
- package/dist/context-menu-wrapper-49f9a1af.js +0 -2
- package/dist/context-menu-wrapper-49f9a1af.js.map +0 -1
- package/dist/context-menu-wrapper-5d6a399f.js +0 -2
- package/dist/context-menu-wrapper-5d6a399f.js.map +0 -1
- package/dist/createClass-440000a3.js.map +0 -1
- package/dist/createClass-5ca26865.js +0 -2
- package/dist/createClass-5ca26865.js.map +0 -1
- package/dist/datarecord-metadata-v3-schema-98ec66e9.js +0 -2
- package/dist/datarecord-metadata-v3-schema-dba0b214.js +0 -2
- package/dist/defineProperty-3dc7d8d0.js +0 -2
- package/dist/flexible-table-35e9922a.js +0 -2
- package/dist/flexible-table-7c7de0f9.js +0 -2
- package/dist/index-94fec521.js +0 -2
- package/dist/index-e2f8a935.js +0 -2
- package/dist/inherits-226dfdb2.js +0 -2
- package/dist/inherits-226dfdb2.js.map +0 -1
- package/dist/inherits-41673c87.js +0 -2
- package/dist/inherits-41673c87.js.map +0 -1
- package/dist/toolbar-6acda0a2.js +0 -2
- package/dist/toolbar-6acda0a2.js.map +0 -1
- package/dist/toolbar-d5647da2.js +0 -2
- package/dist/toolbar-d5647da2.js.map +0 -1
- package/src/palette/palette-dialog-topbar-three-way-icon.jsx +0 -82
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/*
|
|
2
|
-
* Copyright
|
|
2
|
+
* Copyright 2024 Elyra Authors
|
|
3
3
|
*
|
|
4
4
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
5
|
* you may not use this file except in compliance with the License.
|
|
@@ -20,46 +20,59 @@ import PropTypes from "prop-types";
|
|
|
20
20
|
import { adjustSubAreaPosition, generateSubAreaStyle } from "./toolbar-sub-utils.js";
|
|
21
21
|
|
|
22
22
|
const ESC_KEY = 27;
|
|
23
|
+
const LEFT_ARROW_KEY = 37;
|
|
24
|
+
const RIGHT_ARROW_KEY = 39;
|
|
25
|
+
|
|
23
26
|
|
|
24
27
|
class ToolbarSubPanel extends React.Component {
|
|
25
28
|
constructor(props) {
|
|
26
29
|
super(props);
|
|
27
30
|
|
|
28
|
-
this.areaRef = React.createRef();
|
|
29
|
-
|
|
30
|
-
this.onClick = this.onClick.bind(this);
|
|
31
31
|
this.onKeyDown = this.onKeyDown.bind(this);
|
|
32
|
+
this.closeSubPanel = this.closeSubPanel.bind(this);
|
|
32
33
|
}
|
|
33
34
|
|
|
34
35
|
componentDidMount() {
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
this.props.containingDivId, this.props.expandDirection, this.props.actionItemRect);
|
|
38
|
-
}
|
|
36
|
+
adjustSubAreaPosition(this.areaRef,
|
|
37
|
+
this.props.containingDivId, this.props.expandDirection, this.props.actionItemRect);
|
|
39
38
|
}
|
|
40
39
|
|
|
41
|
-
|
|
42
|
-
this.
|
|
40
|
+
componentDidUpdate() {
|
|
41
|
+
adjustSubAreaPosition(this.areaRef,
|
|
42
|
+
this.props.containingDivId, this.props.expandDirection, this.props.actionItemRect);
|
|
43
43
|
}
|
|
44
44
|
|
|
45
45
|
onKeyDown(evt) {
|
|
46
46
|
if (evt.keyCode === ESC_KEY) {
|
|
47
47
|
this.props.closeSubArea();
|
|
48
48
|
evt.stopPropagation();
|
|
49
|
+
|
|
50
|
+
} else if (evt.keyCode === LEFT_ARROW_KEY || evt.keyCode === RIGHT_ARROW_KEY) {
|
|
51
|
+
evt.stopPropagation();
|
|
49
52
|
}
|
|
50
53
|
}
|
|
51
54
|
|
|
55
|
+
// If the user clicks the panel background, by default focus would go
|
|
56
|
+
// through to the toolbar and focus would be lost from this sub-panel.
|
|
57
|
+
// This method prevents any focus event going through to the toolbar.
|
|
58
|
+
onFocus(evt) {
|
|
59
|
+
evt.stopPropagation();
|
|
60
|
+
evt.preventDefault();
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
closeSubPanel(evt) {
|
|
64
|
+
this.props.closeSubArea(); // Don't pass a paremeter otherwise it will check closeSubAreaOnClick.
|
|
65
|
+
}
|
|
66
|
+
|
|
52
67
|
render() {
|
|
53
68
|
const style = generateSubAreaStyle(this.props.expandDirection, this.props.actionItemRect);
|
|
54
69
|
|
|
55
70
|
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
71
|
return (
|
|
61
|
-
<div ref={this.areaRef} style={style} className={"toolbar-popover-list subpanel"}
|
|
62
|
-
{
|
|
72
|
+
<div ref={(ref) => (this.areaRef = ref)} style={style} className={"toolbar-popover-list subpanel"} tabIndex={-1}
|
|
73
|
+
onKeyDown={this.onKeyDown} onFocus={this.onFocus}
|
|
74
|
+
>
|
|
75
|
+
<this.props.subPanel closeSubPanel={this.closeSubPanel} subPanelData={this.props.subPanelData} />
|
|
63
76
|
</div>
|
|
64
77
|
);
|
|
65
78
|
}
|
|
@@ -69,11 +82,11 @@ class ToolbarSubPanel extends React.Component {
|
|
|
69
82
|
}
|
|
70
83
|
|
|
71
84
|
ToolbarSubPanel.propTypes = {
|
|
72
|
-
subPanel: PropTypes.any,
|
|
85
|
+
subPanel: PropTypes.any.isRequired,
|
|
73
86
|
subPanelData: PropTypes.object,
|
|
74
87
|
closeSubArea: PropTypes.func,
|
|
75
88
|
setToolbarFocusAction: PropTypes.func,
|
|
76
|
-
actionItemRect: PropTypes.object
|
|
89
|
+
actionItemRect: PropTypes.object,
|
|
77
90
|
expandDirection: PropTypes.string.isRequired,
|
|
78
91
|
containingDivId: PropTypes.string
|
|
79
92
|
};
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/*
|
|
2
|
-
* Copyright
|
|
2
|
+
* Copyright 2024 Elyra Authors
|
|
3
3
|
*
|
|
4
4
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
5
|
* you may not use this file except in compliance with the License.
|
|
@@ -15,20 +15,25 @@
|
|
|
15
15
|
*/
|
|
16
16
|
|
|
17
17
|
// These utility functions are used by both toolbar-sub-menu.jsx AND
|
|
18
|
-
// toolbar-sub-panel.jsx to position the
|
|
19
|
-
// to the parent actionItemRect, passed in, in the direction
|
|
20
|
-
// the expandDirection parameter and constrained within
|
|
21
|
-
// specified by the containingDivId parameter.
|
|
18
|
+
// toolbar-sub-panel.jsx to position the sub-area (sub-menu or sub-panel)
|
|
19
|
+
// relative to the parent actionItemRect, passed in, in the direction
|
|
20
|
+
// indicated by the expandDirection parameter and constrained within
|
|
21
|
+
// the <div> specified by the containingDivId parameter.
|
|
22
22
|
|
|
23
23
|
|
|
24
24
|
// Adjust the position of the sub-area to make sure it doesn't extend
|
|
25
25
|
// outside the containing divs boundary. We need to do this after the subarea
|
|
26
26
|
// has been mounted so we can query its size and position.
|
|
27
27
|
export function adjustSubAreaPosition(areaRef, containingDivId, expandDirection, actionItemRect) {
|
|
28
|
+
if (!areaRef || !actionItemRect || !containingDivId) {
|
|
29
|
+
return;
|
|
30
|
+
}
|
|
28
31
|
const containingDiv = document.getElementById(containingDivId);
|
|
29
|
-
const containingDivRect = containingDiv
|
|
32
|
+
const containingDivRect = containingDiv
|
|
33
|
+
? containingDiv.getBoundingClientRect()
|
|
34
|
+
: { top: -1000, bottom: 1000, left: -1000, right: 1000 }; // To enable Jest tests.
|
|
30
35
|
|
|
31
|
-
const thisAreaRect = areaRef.
|
|
36
|
+
const thisAreaRect = areaRef.getBoundingClientRect();
|
|
32
37
|
|
|
33
38
|
const outsideBottom = thisAreaRect.bottom - containingDivRect.bottom;
|
|
34
39
|
const outsideRight = thisAreaRect.right - containingDivRect.right;
|
|
@@ -40,28 +45,32 @@ export function adjustSubAreaPosition(areaRef, containingDivId, expandDirection,
|
|
|
40
45
|
? actionItemRect.top - thisAreaRect.height
|
|
41
46
|
: actionItemRect.bottom - outsideBottom;
|
|
42
47
|
|
|
43
|
-
areaRef.
|
|
48
|
+
areaRef.style.top = newTop + "px";
|
|
44
49
|
}
|
|
45
50
|
|
|
46
51
|
if (outsideRight > 0) {
|
|
47
|
-
const newLeft = actionItemRect.left - outsideRight
|
|
48
|
-
areaRef.
|
|
52
|
+
const newLeft = actionItemRect.left - outsideRight;
|
|
53
|
+
areaRef.style.left = newLeft + "px";
|
|
49
54
|
}
|
|
50
55
|
|
|
51
56
|
} else {
|
|
52
57
|
if (outsideBottom > 0) {
|
|
53
58
|
const newTop = thisAreaRect.top - outsideBottom - 2;
|
|
54
|
-
areaRef.
|
|
59
|
+
areaRef.style.top = newTop + "px";
|
|
55
60
|
}
|
|
56
61
|
|
|
57
62
|
if (outsideRight > 0) {
|
|
58
63
|
const newLeft = actionItemRect.left - thisAreaRect.width;
|
|
59
|
-
areaRef.
|
|
64
|
+
areaRef.style.left = newLeft + "px";
|
|
60
65
|
}
|
|
61
66
|
}
|
|
62
67
|
}
|
|
63
68
|
|
|
64
69
|
export function generateSubAreaStyle(expandDirection, actionItemRect) {
|
|
70
|
+
if (!actionItemRect) {
|
|
71
|
+
return null;
|
|
72
|
+
}
|
|
73
|
+
|
|
65
74
|
if (expandDirection === "vertical") {
|
|
66
75
|
return {
|
|
67
76
|
top: actionItemRect.bottom + 1,
|
package/src/toolbar/toolbar.jsx
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/*
|
|
2
|
-
* Copyright 2017-
|
|
2
|
+
* Copyright 2017-2024 Elyra Authors
|
|
3
3
|
*
|
|
4
4
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
5
|
* you may not use this file except in compliance with the License.
|
|
@@ -69,6 +69,7 @@ class Toolbar extends React.Component {
|
|
|
69
69
|
this.generateToolbarItems = this.generateToolbarItems.bind(this);
|
|
70
70
|
this.setFocusAction = this.setFocusAction.bind(this);
|
|
71
71
|
this.setFocusOnItem = this.setFocusOnItem.bind(this);
|
|
72
|
+
this.closeAnyOpenSubArea = this.closeAnyOpenSubArea.bind(this);
|
|
72
73
|
}
|
|
73
74
|
|
|
74
75
|
// If, after updating, we are left in a situation where this.state.focusAction
|
|
@@ -76,13 +77,12 @@ class Toolbar extends React.Component {
|
|
|
76
77
|
// item. This might happen when an item with focus is activated and the action it
|
|
77
78
|
// performs causes itself to become disabled. For example, if the delete item is
|
|
78
79
|
// activated the selected objects are deleted and since no objects are now selected
|
|
79
|
-
// the delete item (which has focus) will become disabled.
|
|
80
|
+
// the delete item (which has focus) will become disabled. It may also happen if the
|
|
81
|
+
// toolbar config is updated and the current focusAction item is removed.
|
|
80
82
|
componentDidUpdate() {
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
this.setFocusOnFirstItem();
|
|
85
|
-
}
|
|
83
|
+
const index = this.getFocusableItemRefs().findIndex((item) => this.getRefAction(item) === this.state.focusAction);
|
|
84
|
+
if (index === -1) {
|
|
85
|
+
this.setFocusOnFirstItem();
|
|
86
86
|
}
|
|
87
87
|
}
|
|
88
88
|
|
|
@@ -106,11 +106,15 @@ class Toolbar extends React.Component {
|
|
|
106
106
|
}
|
|
107
107
|
}
|
|
108
108
|
|
|
109
|
-
// When focus leaves the toolbar make sure we record it
|
|
110
|
-
// accidentally
|
|
111
|
-
// the focus elsewhere.
|
|
112
|
-
onBlur() {
|
|
113
|
-
|
|
109
|
+
// When focus leaves the toolbar make sure we record it. This prevents
|
|
110
|
+
// us accidentally setting focus on a toolbar item when the toolbar
|
|
111
|
+
// re-renders with the focus elsewhere.
|
|
112
|
+
onBlur(evt) {
|
|
113
|
+
// If the focus is being moved to an object outside the toolbar div
|
|
114
|
+
// we set isFocusInToolbar to false.
|
|
115
|
+
if (!evt.relatedTarget?.closest(".toolbar-div")) {
|
|
116
|
+
this.isFocusInToolbar = false;
|
|
117
|
+
}
|
|
114
118
|
}
|
|
115
119
|
|
|
116
120
|
// This is called when the user presses a key with focus on one of the
|
|
@@ -136,17 +140,51 @@ class Toolbar extends React.Component {
|
|
|
136
140
|
}
|
|
137
141
|
|
|
138
142
|
// When the toolbar resizes, check each toolbar item to see if it has
|
|
139
|
-
//
|
|
143
|
+
// an open sub-area and, if that item is not a focusable item, close
|
|
144
|
+
// the sub-area. The item may no longer be focusable it is it was wrapped
|
|
145
|
+
// into the overflow menu. Also, check to see if the current focus action
|
|
146
|
+
// item is focusable and, if not, set focus on the first focusable item.
|
|
140
147
|
onToolbarResize() {
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
148
|
+
const focusableItemRefs = this.getFocusableItemRefs();
|
|
149
|
+
// Note: isFocusActionFocusable needs to be calculated here before any
|
|
150
|
+
// update to the toolbar caused by the code in the subsequent if ststement.
|
|
151
|
+
const isFocusActionFocusable = this.isFocusActionFocusable(this.state.focusAction, focusableItemRefs);
|
|
152
|
+
const refWithOpenSubArea = this.getRefWithOpenSubArea();
|
|
153
|
+
|
|
154
|
+
if (refWithOpenSubArea) {
|
|
155
|
+
const action = refWithOpenSubArea.current.getAction();
|
|
156
|
+
const isFocusActionWithOpenSubAreaFocusable = this.isFocusActionFocusable(action, focusableItemRefs);
|
|
157
|
+
|
|
158
|
+
if (!isFocusActionWithOpenSubAreaFocusable) {
|
|
159
|
+
refWithOpenSubArea.current.closeSubArea();
|
|
160
|
+
|
|
161
|
+
} else {
|
|
162
|
+
// This forces a refresh that will cause the position of any
|
|
163
|
+
// open sub-area to be recaulculated based on the new toolbar width.
|
|
164
|
+
this.setFocusAction(this.state.focusAction);
|
|
165
|
+
}
|
|
166
|
+
}
|
|
144
167
|
|
|
145
|
-
|
|
168
|
+
// If the focus action item is not focusable (maybe because it has been
|
|
169
|
+
// moved into the overflow menu) then set focus on the first focusable item.
|
|
170
|
+
if (!isFocusActionFocusable) {
|
|
146
171
|
this.setFocusOnFirstItem();
|
|
147
172
|
}
|
|
148
173
|
}
|
|
149
174
|
|
|
175
|
+
// Returns the ref to any item that currently has an open sub-area or null
|
|
176
|
+
// if no item has an open sub-area.
|
|
177
|
+
getRefWithOpenSubArea() {
|
|
178
|
+
let subAreaOpenRef = this.leftItemRefs.find((ref) => ref.current.isSubAreaDisplayed());
|
|
179
|
+
if (!subAreaOpenRef) {
|
|
180
|
+
subAreaOpenRef = this.rightItemRefs.find((ref) => ref.current.isSubAreaDisplayed());
|
|
181
|
+
}
|
|
182
|
+
if (!subAreaOpenRef) {
|
|
183
|
+
subAreaOpenRef = this.overflowItemRefs.find((ref) => ref.current.isSubAreaDisplayed());
|
|
184
|
+
}
|
|
185
|
+
return subAreaOpenRef;
|
|
186
|
+
}
|
|
187
|
+
|
|
150
188
|
// Either sets the focus on the item for the action passed in or, if
|
|
151
189
|
// no action is passed in, set the focus on the current focusAction.
|
|
152
190
|
// Setting the current focusAction is used to return focus back to an
|
|
@@ -192,18 +230,18 @@ class Toolbar extends React.Component {
|
|
|
192
230
|
|
|
193
231
|
getPreviousItemRef(focusableItemRefs) {
|
|
194
232
|
const index = focusableItemRefs.findIndex((item) => this.getRefAction(item) === this.state.focusAction);
|
|
195
|
-
if (index
|
|
196
|
-
return focusableItemRefs[
|
|
233
|
+
if (index === 0) {
|
|
234
|
+
return focusableItemRefs[focusableItemRefs.length - 1];
|
|
197
235
|
}
|
|
198
|
-
return
|
|
236
|
+
return focusableItemRefs[index - 1];
|
|
199
237
|
}
|
|
200
238
|
|
|
201
239
|
getNextItemRef(focusableItemRefs) {
|
|
202
240
|
const index = focusableItemRefs.findIndex((item) => this.getRefAction(item) === this.state.focusAction);
|
|
203
|
-
if (index
|
|
204
|
-
return focusableItemRefs[
|
|
241
|
+
if (index === focusableItemRefs.length - 1) {
|
|
242
|
+
return focusableItemRefs[0];
|
|
205
243
|
}
|
|
206
|
-
return
|
|
244
|
+
return focusableItemRefs[index + 1];
|
|
207
245
|
}
|
|
208
246
|
|
|
209
247
|
getRefAction(ref) {
|
|
@@ -313,6 +351,14 @@ class Toolbar extends React.Component {
|
|
|
313
351
|
return index;
|
|
314
352
|
}
|
|
315
353
|
|
|
354
|
+
// Returns true of the current focus action item is one of the focusable
|
|
355
|
+
// items. (It may not be if it has been placed in the overflow menu).
|
|
356
|
+
isFocusActionFocusable(focusAction, focusableItemRefs) {
|
|
357
|
+
const indexFocusAction = focusableItemRefs.findIndex((ref) =>
|
|
358
|
+
ref.current.props.actionObj?.action === focusAction);
|
|
359
|
+
return indexFocusAction > -1;
|
|
360
|
+
}
|
|
361
|
+
|
|
316
362
|
// Returns a reference to the first item that is not on the
|
|
317
363
|
// top (visible) row of the toolbar.
|
|
318
364
|
findFirstRightItemRefNotOnTopRow() {
|
|
@@ -386,6 +432,7 @@ class Toolbar extends React.Component {
|
|
|
386
432
|
toolbarFocusAction={this.state.focusAction}
|
|
387
433
|
setToolbarFocusAction={this.setFocusOnItem}
|
|
388
434
|
isFocusInToolbar={this.isFocusInToolbar}
|
|
435
|
+
closeAnyOpenSubArea={this.closeAnyOpenSubArea}
|
|
389
436
|
size={this.props.size}
|
|
390
437
|
/>
|
|
391
438
|
);
|
|
@@ -421,6 +468,7 @@ class Toolbar extends React.Component {
|
|
|
421
468
|
toolbarFocusAction={this.state.focusAction}
|
|
422
469
|
setToolbarFocusAction={this.setFocusOnItem}
|
|
423
470
|
isFocusInToolbar={this.isFocusInToolbar}
|
|
471
|
+
closeAnyOpenSubArea={this.closeAnyOpenSubArea}
|
|
424
472
|
/>
|
|
425
473
|
);
|
|
426
474
|
|
|
@@ -440,15 +488,24 @@ class Toolbar extends React.Component {
|
|
|
440
488
|
return subMenuActions;
|
|
441
489
|
}
|
|
442
490
|
|
|
443
|
-
|
|
444
|
-
|
|
491
|
+
closeAnyOpenSubArea() {
|
|
492
|
+
this.leftItemRefs.forEach((ref) => this.closeSubAreaOnRef(ref));
|
|
493
|
+
this.rightItemRefs.forEach((ref) => this.closeSubAreaOnRef(ref));
|
|
494
|
+
this.overflowItemRefs.forEach((ref) => this.closeOverflowMenuOnRef(ref));
|
|
495
|
+
}
|
|
496
|
+
|
|
497
|
+
closeSubAreaOnRef(ref) {
|
|
498
|
+
if (ref.current.props.actionObj.setExtIsSubAreaDisplayed) {
|
|
499
|
+
ref.current.props.actionObj.setExtIsSubAreaDisplayed(false);
|
|
500
|
+
|
|
501
|
+
} else if (ref.current.state.subAreaDisplayed) {
|
|
445
502
|
ref.current.closeSubArea();
|
|
446
503
|
}
|
|
447
504
|
}
|
|
448
505
|
|
|
449
506
|
closeOverflowMenuOnRef(ref) {
|
|
450
507
|
if (ref.current.state.showExtendedMenu) {
|
|
451
|
-
ref.current.
|
|
508
|
+
ref.current.closeSubArea();
|
|
452
509
|
}
|
|
453
510
|
}
|
|
454
511
|
|
package/src/toolbar/toolbar.scss
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/*
|
|
2
|
-
* Copyright 2017-
|
|
2
|
+
* Copyright 2017-2024 Elyra Authors
|
|
3
3
|
*
|
|
4
4
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
5
|
* you may not use this file except in compliance with the License.
|
|
@@ -30,16 +30,16 @@ $toolbar-divider-width: 1px;
|
|
|
30
30
|
background-color: $ui-01;
|
|
31
31
|
box-sizing: content-box;
|
|
32
32
|
position: relative;
|
|
33
|
-
|
|
34
33
|
display: flex;
|
|
35
34
|
justify-content: space-between;
|
|
35
|
+
outline: none; // Turn outline off and use carbon style for focus below.
|
|
36
36
|
|
|
37
37
|
/* Prevent elements from being dragged onto canvas */
|
|
38
38
|
-webkit-user-drag: none;
|
|
39
39
|
|
|
40
40
|
&:focus {
|
|
41
|
-
border-color: $interactive-
|
|
42
|
-
box-shadow: inset 0 0 0
|
|
41
|
+
border-color: $interactive-03;
|
|
42
|
+
box-shadow: inset 0 0 0 2px $interactive-03;
|
|
43
43
|
}
|
|
44
44
|
|
|
45
45
|
/* Small size toolbar */
|
|
@@ -106,6 +106,7 @@ $toolbar-divider-width: 1px;
|
|
|
106
106
|
& button {
|
|
107
107
|
padding: 0;
|
|
108
108
|
min-height: 30px;
|
|
109
|
+
height: $toolbar-button-height;
|
|
109
110
|
}
|
|
110
111
|
|
|
111
112
|
&.default,
|
|
@@ -201,10 +202,15 @@ $toolbar-divider-width: 1px;
|
|
|
201
202
|
&.disabled.default {
|
|
202
203
|
color: $disabled-02;
|
|
203
204
|
fill: $disabled-02; // For custom svg images
|
|
205
|
+
& .toolbar-tick-mark {
|
|
206
|
+
fill: $disabled-02;
|
|
207
|
+
}
|
|
208
|
+
& .toolbar-text-content {
|
|
209
|
+
stroke: $disabled-02;
|
|
210
|
+
}
|
|
204
211
|
}
|
|
205
212
|
|
|
206
213
|
.toolbar-icon {
|
|
207
|
-
height: $toolbar-icon-size;
|
|
208
214
|
& svg {
|
|
209
215
|
height: $toolbar-icon-size;
|
|
210
216
|
width: $toolbar-icon-size;
|
|
@@ -212,52 +218,52 @@ $toolbar-divider-width: 1px;
|
|
|
212
218
|
-webkit-user-drag: none;
|
|
213
219
|
}
|
|
214
220
|
}
|
|
215
|
-
}
|
|
216
221
|
|
|
217
|
-
.toolbar-text-content {
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
}
|
|
222
|
+
.toolbar-text-content {
|
|
223
|
+
position: absolute;
|
|
224
|
+
top: 14px;
|
|
225
|
+
font-size: 9px;
|
|
226
|
+
line-height: 9px;
|
|
227
|
+
color: $icon-01;
|
|
228
|
+
}
|
|
224
229
|
|
|
225
|
-
.toolbar-icon-label {
|
|
226
|
-
|
|
230
|
+
.toolbar-icon-label {
|
|
231
|
+
line-height: 16px;
|
|
227
232
|
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
233
|
+
&.before {
|
|
234
|
+
padding-right: 8px;
|
|
235
|
+
}
|
|
231
236
|
|
|
232
|
-
|
|
233
|
-
|
|
237
|
+
&.after {
|
|
238
|
+
padding-left: 8px;
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
&.overflow {
|
|
242
|
+
padding-left: 8px;
|
|
243
|
+
word-break: break-word;
|
|
244
|
+
hyphens: auto;
|
|
245
|
+
}
|
|
234
246
|
}
|
|
235
247
|
|
|
236
|
-
|
|
248
|
+
.toolbar-up-down-chevron {
|
|
237
249
|
padding-left: 8px;
|
|
238
|
-
|
|
239
|
-
|
|
250
|
+
height: 16px;
|
|
251
|
+
pointer-events: none;
|
|
240
252
|
}
|
|
241
|
-
}
|
|
242
253
|
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
position: absolute;
|
|
252
|
-
bottom: 0;
|
|
253
|
-
right: 0;
|
|
254
|
-
height: $toolbar-button-height;
|
|
255
|
-
width: $toolbar-button-height;
|
|
256
|
-
pointer-events: none;
|
|
257
|
-
}
|
|
254
|
+
// Triangular tick mark in bottom right corner of an expandable icon
|
|
255
|
+
.toolbar-tick-svg {
|
|
256
|
+
position: absolute;
|
|
257
|
+
bottom: 0;
|
|
258
|
+
right: 0;
|
|
259
|
+
height: $toolbar-button-height;
|
|
260
|
+
width: $toolbar-button-height;
|
|
261
|
+
pointer-events: none;
|
|
258
262
|
|
|
259
|
-
.toolbar-tick-mark {
|
|
260
|
-
|
|
263
|
+
& .toolbar-tick-mark {
|
|
264
|
+
fill: $icon-01;
|
|
265
|
+
}
|
|
266
|
+
}
|
|
261
267
|
}
|
|
262
268
|
|
|
263
269
|
.toolbar-jsx-item {
|
|
@@ -285,14 +291,8 @@ $toolbar-divider-width: 1px;
|
|
|
285
291
|
&.ghost {
|
|
286
292
|
& button {
|
|
287
293
|
background-color: $ui-03;
|
|
288
|
-
border-color: transparent;
|
|
289
|
-
box-shadow: none;
|
|
290
294
|
border-bottom: 2px solid $interactive-01;
|
|
291
295
|
}
|
|
292
|
-
& button:focus {
|
|
293
|
-
border-color: $interactive-01;
|
|
294
|
-
box-shadow: inset 0 0 0 1px $interactive-01, inset 0 0 0 2px $ui-background;
|
|
295
|
-
}
|
|
296
296
|
}
|
|
297
297
|
}
|
|
298
298
|
|
package/src/tooltip/tooltip.jsx
CHANGED
|
@@ -79,6 +79,13 @@ class ToolTip extends React.Component {
|
|
|
79
79
|
if (tooltipTrigger && tooltip) {
|
|
80
80
|
this.updateTooltipLayout(tooltip, tooltipTrigger, tooltip.getAttribute("direction"));
|
|
81
81
|
}
|
|
82
|
+
|
|
83
|
+
const linkElement = this.targetRef.querySelector("a");
|
|
84
|
+
|
|
85
|
+
// Focus on link when tooltip with link is opened
|
|
86
|
+
if (linkElement) {
|
|
87
|
+
linkElement.focus();
|
|
88
|
+
}
|
|
82
89
|
}
|
|
83
90
|
}
|
|
84
91
|
}
|
|
@@ -87,6 +94,10 @@ class ToolTip extends React.Component {
|
|
|
87
94
|
if (evt.key === "Tab") {
|
|
88
95
|
this.tabKeyPressed = true;
|
|
89
96
|
}
|
|
97
|
+
if (evt.key === "Escape") {
|
|
98
|
+
this.triggerRef.focus();
|
|
99
|
+
this.setTooltipVisible(false);
|
|
100
|
+
}
|
|
90
101
|
}
|
|
91
102
|
|
|
92
103
|
getStyleValue(value) {
|
|
@@ -320,6 +331,9 @@ class ToolTip extends React.Component {
|
|
|
320
331
|
// To prevent this default behavior, stopPropagation and preventDefault is used.
|
|
321
332
|
evt.stopPropagation();
|
|
322
333
|
evt.preventDefault();
|
|
334
|
+
|
|
335
|
+
// When tooltip with link is closed and another tooltip is opened newly opened tooltip should have focus.
|
|
336
|
+
this.triggerRef.focus();
|
|
323
337
|
if (this.state.isTooltipVisible) {
|
|
324
338
|
// Tooltip is visible and user clicks on trigger element again, hide tooltip
|
|
325
339
|
this.setTooltipVisible(false);
|
|
@@ -405,22 +419,53 @@ class ToolTip extends React.Component {
|
|
|
405
419
|
if (this.props.className) {
|
|
406
420
|
tipClass += " " + this.props.className;
|
|
407
421
|
}
|
|
408
|
-
|
|
422
|
+
let linkClicked = false;
|
|
409
423
|
let link = null;
|
|
410
424
|
if (this.state.isTooltipVisible && this.props.tooltipLinkHandler && this.props.link) {
|
|
411
425
|
const linkInformation = this.props.tooltipLinkHandler(this.props.link);
|
|
412
426
|
// Verify tooltipLinkHandler returns object in correct format
|
|
413
427
|
if (typeof linkInformation === "object" && linkInformation.label && linkInformation.url) {
|
|
414
|
-
link = (<
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
428
|
+
link = (<div
|
|
429
|
+
ref={(ref) => (this.linkRef = ref)}
|
|
430
|
+
onKeyDown={(evt) => {
|
|
431
|
+
evt.stopPropagation();
|
|
432
|
+
evt.preventDefault();
|
|
433
|
+
|
|
434
|
+
// When 'Esc' is pressed shift the focus to tooltip icon so that user can navigate following elements.
|
|
435
|
+
if (evt.key === "Escape") {
|
|
436
|
+
this.triggerRef.focus();
|
|
437
|
+
this.setTooltipVisible(false);
|
|
438
|
+
} else if (evt.key === "Enter") { // Open active/highlighted link when Enter or Return is clicked.
|
|
439
|
+
const focusedElement = this.linkRef.children[0];
|
|
440
|
+
if (focusedElement) {
|
|
441
|
+
window.open(focusedElement, "_blank");
|
|
442
|
+
}
|
|
443
|
+
}
|
|
444
|
+
}}
|
|
445
|
+
onBlur={() => {
|
|
446
|
+
if (linkClicked) { // Keep tooltip open when link is clicked
|
|
447
|
+
this.setTooltipVisible(true);
|
|
448
|
+
} else { // Close the tooltip and shift focus to tooltip icon
|
|
449
|
+
this.triggerRef.focus();
|
|
450
|
+
this.setTooltipVisible(false);
|
|
451
|
+
}
|
|
452
|
+
}
|
|
453
|
+
}
|
|
454
|
+
onClick={() => {
|
|
455
|
+
linkClicked = true;
|
|
456
|
+
}}
|
|
421
457
|
>
|
|
422
|
-
|
|
423
|
-
|
|
458
|
+
<Link
|
|
459
|
+
className="tooltip-link"
|
|
460
|
+
id={this.props.link.id}
|
|
461
|
+
href={linkInformation.url}
|
|
462
|
+
target="_blank"
|
|
463
|
+
rel="noopener"
|
|
464
|
+
visited={false}
|
|
465
|
+
>
|
|
466
|
+
{linkInformation.label}
|
|
467
|
+
</Link>
|
|
468
|
+
</div>);
|
|
424
469
|
}
|
|
425
470
|
}
|
|
426
471
|
|
|
@@ -435,6 +480,7 @@ class ToolTip extends React.Component {
|
|
|
435
480
|
className={tipClass}
|
|
436
481
|
aria-hidden={!this.state.isTooltipVisible}
|
|
437
482
|
direction={this.props.direction}
|
|
483
|
+
ref={(ref) => (this.targetRef = ref)}
|
|
438
484
|
>
|
|
439
485
|
<svg className="tipArrow" x="0px" y="0px" viewBox="0 0 9.1 16.1">
|
|
440
486
|
<polyline points="9.1,15.7 1.4,8.1 9.1,0.5" />
|