@elyra/canvas 12.45.1 → 12.47.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.
Files changed (56) hide show
  1. package/dist/{canvas-controller-0c83caa0.js → canvas-controller-26440c36.js} +2 -2
  2. package/dist/canvas-controller-26440c36.js.map +1 -0
  3. package/dist/{canvas-controller-024d7fa4.js → canvas-controller-aa5d9a51.js} +2 -2
  4. package/dist/canvas-controller-aa5d9a51.js.map +1 -0
  5. package/dist/common-canvas-24b39e38.js +2 -0
  6. package/dist/common-canvas-24b39e38.js.map +1 -0
  7. package/dist/common-canvas-6b306626.js +2 -0
  8. package/dist/common-canvas-6b306626.js.map +1 -0
  9. package/dist/common-canvas.es.js +1 -1
  10. package/dist/common-canvas.js +1 -1
  11. package/dist/{common-properties-cc1584aa.js → common-properties-0e7576bf.js} +2 -2
  12. package/dist/{common-properties-cc1584aa.js.map → common-properties-0e7576bf.js.map} +1 -1
  13. package/dist/{common-properties-cdedfd5c.js → common-properties-95fbce18.js} +2 -2
  14. package/dist/{common-properties-cdedfd5c.js.map → common-properties-95fbce18.js.map} +1 -1
  15. package/dist/lib/canvas-controller.es.js +1 -1
  16. package/dist/lib/canvas-controller.js +1 -1
  17. package/dist/lib/canvas.es.js +1 -1
  18. package/dist/lib/canvas.js +1 -1
  19. package/dist/lib/command-stack.es.js +1 -1
  20. package/dist/lib/command-stack.es.js.map +1 -1
  21. package/dist/lib/command-stack.js +1 -1
  22. package/dist/lib/command-stack.js.map +1 -1
  23. package/dist/lib/properties.es.js +1 -1
  24. package/dist/lib/properties.js +1 -1
  25. package/dist/styles/common-canvas.min.css +1 -1
  26. package/dist/styles/common-canvas.min.css.map +1 -1
  27. package/dist/toolbar-5e3013fd.js +2 -0
  28. package/dist/toolbar-5e3013fd.js.map +1 -0
  29. package/dist/toolbar-bb5b5c13.js +2 -0
  30. package/dist/toolbar-bb5b5c13.js.map +1 -0
  31. package/package.json +1 -1
  32. package/src/command-stack/command-stack.js +4 -0
  33. package/src/common-canvas/canvas-controller.js +25 -8
  34. package/src/common-canvas/cc-context-toolbar.jsx +10 -3
  35. package/src/common-canvas/cc-toolbar.jsx +0 -3
  36. package/src/common-canvas/common-canvas.scss +0 -6
  37. package/src/common-canvas/svg-canvas-renderer.js +1 -1
  38. package/src/common-properties/controls/checkbox/checkbox.jsx +12 -12
  39. package/src/common-properties/controls/checkbox/checkbox.scss +0 -3
  40. package/src/object-model/layout-dimensions.js +2 -2
  41. package/src/toolbar/toolbar-action-item.jsx +38 -4
  42. package/src/toolbar/toolbar-button-item.jsx +38 -28
  43. package/src/toolbar/toolbar-overflow-item.jsx +27 -10
  44. package/src/toolbar/toolbar.jsx +22 -22
  45. package/src/toolbar/toolbar.scss +61 -11
  46. package/stats.html +1 -1
  47. package/dist/canvas-controller-024d7fa4.js.map +0 -1
  48. package/dist/canvas-controller-0c83caa0.js.map +0 -1
  49. package/dist/common-canvas-39d943f9.js +0 -2
  50. package/dist/common-canvas-39d943f9.js.map +0 -1
  51. package/dist/common-canvas-e831aa7c.js +0 -2
  52. package/dist/common-canvas-e831aa7c.js.map +0 -1
  53. package/dist/toolbar-6af353fa.js +0 -2
  54. package/dist/toolbar-6af353fa.js.map +0 -1
  55. package/dist/toolbar-c4e22755.js +0 -2
  56. package/dist/toolbar-c4e22755.js.map +0 -1
@@ -69,18 +69,18 @@ class CheckboxControl extends React.Component {
69
69
  </span>
70
70
  );
71
71
  return (
72
- <div className={classNames("properties-checkbox", { "hide": this.props.state === STATES.HIDDEN }, this.props.messageInfo ? this.props.messageInfo.type : null)}
73
- data-id={ControlUtils.getDataId(this.props.propertyId)}
74
- >
75
- <Checkbox
76
- disabled={this.props.state === STATES.DISABLED}
77
- id={this.id}
78
- labelText={checkboxLabel}
79
- onChange={this.handleChange.bind(this)}
80
- checked={Boolean(this.props.value)}
81
- hideLabel={this.props.tableControl}
82
- />
83
- {tooltipIcon}
72
+ <div data-id={ControlUtils.getDataId(this.props.propertyId)}>
73
+ <div className={classNames("properties-checkbox", { "hide": this.props.state === STATES.HIDDEN }, this.props.messageInfo ? this.props.messageInfo.type : null)}>
74
+ <Checkbox
75
+ disabled={this.props.state === STATES.DISABLED}
76
+ id={this.id}
77
+ labelText={checkboxLabel}
78
+ onChange={this.handleChange.bind(this)}
79
+ checked={Boolean(this.props.value)}
80
+ hideLabel={this.props.tableControl}
81
+ />
82
+ {tooltipIcon}
83
+ </div>
84
84
  <ValidationMessage inTable={this.props.tableControl} state={this.props.state} messageInfo={this.props.controller.getErrorMessage(this.props.propertyId)} />
85
85
  </div>
86
86
  );
@@ -27,9 +27,6 @@
27
27
  .bx--form-item.bx--checkbox-wrapper {
28
28
  flex: initial; // override carbon style to show tooltipIcon next to checkbox label
29
29
  }
30
- .properties-validation-message {
31
- flex: 0 1 100%;
32
- }
33
30
  &.hide {
34
31
  display: none;
35
32
  }
@@ -75,7 +75,7 @@ const portsHorizontalDefaultLayout = {
75
75
  labelAllowReturnKey: false, // true allows line feed to be inserted into label, "save" to make the return key save the label.
76
76
 
77
77
  // An array of decorations to be applied to the node. For details see:
78
- // https://github.com/elyra-ai/canvas/wiki/2.4.2-Decoration-Specification
78
+ // https://elyra-ai.github.io/canvas/03.04.01-decorations/
79
79
  // These are added to the node at run time and will not be saved into
80
80
  // the pipeline flow.
81
81
  decorations: [],
@@ -475,7 +475,7 @@ const portsVerticalDefaultLayout = {
475
475
  labelAllowReturnKey: false, // true allows line feed to be inserted into label, "save" to make the return key save the label.
476
476
 
477
477
  // An array of decorations to be applied to the node. For details see:
478
- // https://github.com/elyra-ai/canvas/wiki/2.4.2-Decoration-Specification
478
+ // https://elyra-ai.github.io/canvas/03.04.01-decorations/
479
479
  // These are added to the node at run time and will not be saved into
480
480
  // the pipeline flow.
481
481
  decorations: [],
@@ -24,6 +24,8 @@ import ToolbarSubMenu from "./toolbar-sub-menu.jsx";
24
24
  import ToolbarSubPanel from "./toolbar-sub-panel.jsx";
25
25
 
26
26
  const ESC_KEY = 27;
27
+ const DOWN_ARROW_KEY = 40;
28
+ const TOOLBAR_ICON_WIDTH = 40;
27
29
 
28
30
  class ToolbarActionItem extends React.Component {
29
31
  constructor(props) {
@@ -51,8 +53,14 @@ class ToolbarActionItem extends React.Component {
51
53
  onKeyDown(evt) {
52
54
  if (evt.keyCode === ESC_KEY) {
53
55
  this.closeSubArea();
54
- return;
56
+
57
+ } else if (evt.keyCode === DOWN_ARROW_KEY) {
58
+ if (this.hasSubArea()) {
59
+ this.openSubArea();
60
+ }
55
61
  }
62
+ // Left and Right arrow clicks are caught in the
63
+ // toolbar.jsx onKeyDown method.
56
64
  }
57
65
 
58
66
  // Called by toolbar.jsx
@@ -90,6 +98,10 @@ class ToolbarActionItem extends React.Component {
90
98
  }
91
99
  }
92
100
 
101
+ hasSubArea() {
102
+ return this.props.actionObj.subMenu || this.props.actionObj.subPanel;
103
+ }
104
+
93
105
  openSubArea() {
94
106
  // If host app is controlling display of the sub-area call it to say
95
107
  // sub-area is closing.
@@ -112,8 +124,9 @@ class ToolbarActionItem extends React.Component {
112
124
  }
113
125
  }
114
126
 
115
- actionClickHandler(evt) {
116
- if (this.props.actionObj.subMenu || this.props.actionObj.subPanel) {
127
+ actionClickHandler(evt, chevronClicked) {
128
+ if (this.hasSubArea() &&
129
+ (this.props.actionObj.purpose !== "dual" || chevronClicked)) {
117
130
  if (this.isSubAreaDisplayed()) {
118
131
  document.removeEventListener("click", this.clickOutside, false);
119
132
  this.closeSubArea();
@@ -127,6 +140,7 @@ class ToolbarActionItem extends React.Component {
127
140
  }
128
141
 
129
142
  } else {
143
+ this.closeSubArea();
130
144
  this.props.toolbarActionHandler(this.props.actionObj.action, evt);
131
145
  this.props.setToolbarFocusAction(this.props.actionObj.action);
132
146
  }
@@ -141,7 +155,10 @@ class ToolbarActionItem extends React.Component {
141
155
  // supPanel field OR a sub-menu which is a list of options which is created
142
156
  // from the array of items the caller passes in the subMenu field.
143
157
  generateSubArea() {
144
- const actionItemRect = this.divRef.current ? this.divRef.current.getBoundingClientRect() : null;
158
+ let actionItemRect = this.divRef.current ? this.divRef.current.getBoundingClientRect() : null;
159
+ actionItemRect = (actionItemRect && this.props.actionObj.purpose === "dual")
160
+ ? this.adjustForDual(actionItemRect)
161
+ : actionItemRect;
145
162
 
146
163
  if (this.props.actionObj.subPanel) {
147
164
  return (
@@ -173,6 +190,22 @@ class ToolbarActionItem extends React.Component {
173
190
  );
174
191
  }
175
192
 
193
+ // For a dual-purpose toolbar button, adjusts the rectangle dimensions so
194
+ // the sub-panel is opened based on the location of the right chevron of
195
+ // the dual button.
196
+ adjustForDual(actionItemRect) {
197
+ return {
198
+ height: actionItemRect.height,
199
+ width: actionItemRect.width,
200
+ top: actionItemRect.top,
201
+ bottom: actionItemRect.bottom,
202
+ left: actionItemRect.left + TOOLBAR_ICON_WIDTH,
203
+ right: actionItemRect.right + TOOLBAR_ICON_WIDTH,
204
+ x: actionItemRect.x + TOOLBAR_ICON_WIDTH,
205
+ y: actionItemRect.y
206
+ };
207
+ }
208
+
176
209
  generateSelector(actionObj) {
177
210
  if (actionObj.jsx) {
178
211
  return ".toolbar-jsx-item";
@@ -229,6 +262,7 @@ ToolbarActionItem.propTypes = {
229
262
  PropTypes.object
230
263
  ]),
231
264
  incLabelWithIcon: PropTypes.oneOf(["no", "before", "after"]),
265
+ purpose: PropTypes.oneOf(["single", "dual"]),
232
266
  enable: PropTypes.bool,
233
267
  iconEnabled: PropTypes.oneOfType([
234
268
  PropTypes.string,
@@ -197,20 +197,24 @@ class ToolbarButtonItem extends React.Component {
197
197
 
198
198
  const itemContentClassName = classNames(
199
199
  "toolbar-item-content",
200
- { "overflow": this.props.isInMenu, "disabled": !actionObj.enable, "default": !actionObj.kind });
200
+ { "is-in-menu": this.props.isInMenu, "disabled": !actionObj.enable, "default": !actionObj.kind });
201
201
 
202
202
  // If no 'kind' is set, use ghost and then override colors using the "default" class in innerDivClassName.
203
203
  const kind = actionObj.kind || "ghost";
204
204
 
205
- const chevronIcon = this.generateChevronIcon(actionObj);
205
+ const chevronDiv = this.generateChevronDiv(actionObj);
206
+
207
+ const mainClassName = actionObj.purpose ? "content-main dual" : "content-main";
206
208
 
207
209
  let buttonContent = (
208
210
  <div className={itemContentClassName}>
209
- {labelBefore}
210
- {icon}
211
- {labelAfter}
212
- {textContent}
213
- {chevronIcon}
211
+ <div className={mainClassName}>
212
+ {labelBefore}
213
+ {icon}
214
+ {labelAfter}
215
+ {textContent}
216
+ </div>
217
+ {chevronDiv}
214
218
  </div>
215
219
  );
216
220
 
@@ -237,39 +241,44 @@ class ToolbarButtonItem extends React.Component {
237
241
  return button;
238
242
  }
239
243
 
240
- // Returns a chevron icon if the action icon is displaying a sub-menu or
241
- // sub-panel. The chevron will:
242
- // * point right if this action item is in a drop down menu
243
- // * point down if this action item is displayed with text in the toolbar
244
- // and the menu isn't displayed
245
- // * point up if this action item is displayed with text in the toolbar
246
- // and the menu is displayed
247
- // * be a mini-chevron (small triangle in the bottom right of icon) if this
248
- // action item isn't displayed with text.
249
- generateChevronIcon(actionObj) {
244
+ // Returns a civ containing a chevron icon. If the action icon is displaying
245
+ // a sub-menu or sub-panel. The chevron will:
246
+ // * point right if this action item is in a drop down menu.
247
+ // * point down and be regular size if this action item is displayed with
248
+ // text in the toolbar and the menu isn't displayed.
249
+ // * point up and be regular size if this action item is displayed with
250
+ // text in the toolbar and the menu is displayed.
251
+ // * point down and be a mini-chevron if this action item is displayed without
252
+ // text in the toolbar and the menu isn't displayed.
253
+ // * point up and be a mini-chevron if this action item is displayed without
254
+ // text in the toolbar and the menu is displayed.
255
+ generateChevronDiv(actionObj) {
250
256
  if (actionObj.subMenu || actionObj.subPanel) {
251
257
  if (this.props.isInMenu) {
252
- return (<ChevronRight16 />);
258
+ return <div className={"toolbar-right-chevron"}><ChevronRight16 /></div>;
253
259
  }
254
260
  if (actionObj.incLabelWithIcon === "before" ||
255
261
  actionObj.incLabelWithIcon === "after") {
256
262
  const chev = this.props.subAreaDisplayed ? (<ChevronUp16 />) : (<ChevronDown16 />);
257
263
  return (<div className={"toolbar-up-down-chevron"}>{chev}</div>);
258
264
  }
259
- return this.generateChevronMini();
265
+ if (actionObj.purpose === "dual") {
266
+ const chevMini = this.props.subAreaDisplayed ? (<ChevronUp16 />) : (<ChevronDown16 />);
267
+ return (<div className={"toolbar-up-down-chevron-mini"} onClick={this.miniChevronClicked.bind(this)}>{chevMini}</div>);
268
+ }
269
+ const path = this.props.size === "sm" ? "M 29 29 L 29 23 23 29 Z" : "M 37 37 L 37 30 30 37 Z";
270
+ return (
271
+ <svg className="toolbar-tick-svg">
272
+ <path d={path} className="toolbar-tick-mark" />
273
+ </svg>
274
+ );
260
275
  }
261
276
  return null;
262
277
  }
263
278
 
264
- // Returns an svg to display the little triangle that appears in the bottom
265
- // right corner of icons that, when clicked, show a drop down menu.
266
- generateChevronMini() {
267
- const path = this.props.size === "sm" ? "M 29 29 L 29 23 23 29 Z" : "M 37 37 L 37 30 30 37 Z";
268
- return (
269
- <svg className="toolbar-tick-svg">
270
- <path d={path} className="toolbar-tick-mark" />
271
- </svg>
272
- );
279
+ miniChevronClicked(evt) {
280
+ this.props.actionClickHandler(evt, true);
281
+ evt.stopPropagation();
273
282
  }
274
283
 
275
284
  // Creates a <div> containing the JSX in the actionObj.jsx field, wrapped in a tooltip
@@ -341,6 +350,7 @@ ToolbarButtonItem.propTypes = {
341
350
  PropTypes.object
342
351
  ]),
343
352
  incLabelWithIcon: PropTypes.oneOf(["no", "before", "after"]),
353
+ purpose: PropTypes.oneOf(["single", "dual"]),
344
354
  enable: PropTypes.bool,
345
355
  iconEnabled: PropTypes.oneOfType([
346
356
  PropTypes.string,
@@ -22,6 +22,9 @@ import { Button } from "carbon-components-react";
22
22
  import { OverflowMenuVertical16 } from "@carbon/icons-react";
23
23
  import ToolbarSubMenu from "./toolbar-sub-menu.jsx";
24
24
 
25
+ const ESC_KEY = 27;
26
+ const DOWN_ARROW_KEY = 40;
27
+
25
28
  class ToolbarOverflowItem extends React.Component {
26
29
  constructor(props) {
27
30
  super(props);
@@ -36,6 +39,7 @@ class ToolbarOverflowItem extends React.Component {
36
39
  this.toggleExtendedMenu = this.toggleExtendedMenu.bind(this);
37
40
  this.clickOutside = this.clickOutside.bind(this);
38
41
  this.closeSubArea = this.closeSubArea.bind(this);
42
+ this.onKeyDown = this.onKeyDown.bind(this);
39
43
  }
40
44
 
41
45
  componentDidUpdate() {
@@ -50,6 +54,18 @@ class ToolbarOverflowItem extends React.Component {
50
54
  document.removeEventListener("click", this.clickOutside, false);
51
55
  }
52
56
 
57
+ onKeyDown(evt) {
58
+ if (evt.keyCode === ESC_KEY) {
59
+ this.closeSubArea();
60
+
61
+ } else if (evt.keyCode === DOWN_ARROW_KEY) {
62
+ this.openSubArea();
63
+ }
64
+ // Left and Right arrow clicks are caught in the
65
+ // toolbar.jsx onKeyDown method.
66
+ }
67
+
68
+
53
69
  // Called by toolbar.jsx
54
70
  getAction() {
55
71
  return this.props.action;
@@ -62,11 +78,18 @@ class ToolbarOverflowItem extends React.Component {
62
78
 
63
79
  // Called by toolbar.jsx and internally
64
80
  closeSubArea() {
81
+ document.removeEventListener("click", this.clickOutside, false);
82
+ this.props.setOverflowIndex(null); // Clear the indexes
65
83
  this.setState({ showExtendedMenu: false });
84
+ this.props.setToolbarFocusAction(this.props.action); // This will not set focus on this item
66
85
  }
67
86
 
68
- openSubMenu() {
87
+ openSubArea() {
88
+ document.addEventListener("click", this.clickOutside, false);
89
+ this.props.closeAnyOpenSubArea();
90
+ this.props.setOverflowIndex(this.props.index);
69
91
  this.setState({ showExtendedMenu: true });
92
+ this.props.setToolbarFocusAction(this.props.action);
70
93
  }
71
94
 
72
95
  genOverflowButtonClassName() {
@@ -88,17 +111,10 @@ class ToolbarOverflowItem extends React.Component {
88
111
  // When the overflow menu is closed we set the overflow index values to null.
89
112
  toggleExtendedMenu() {
90
113
  if (this.state.showExtendedMenu) {
91
- document.removeEventListener("click", this.clickOutside, false);
92
- this.props.setOverflowIndex(null); // Clear the indexes
93
114
  this.closeSubArea();
94
- this.props.setToolbarFocusAction(this.props.action); // This will not set focus on this item
95
115
 
96
116
  } else {
97
- document.addEventListener("click", this.clickOutside, false);
98
- this.props.closeAnyOpenSubArea();
99
- this.props.setOverflowIndex(this.props.index);
100
- this.openSubMenu();
101
- this.props.setToolbarFocusAction(this.props.action);
117
+ this.openSubArea();
102
118
  }
103
119
  }
104
120
 
@@ -147,11 +163,12 @@ class ToolbarOverflowItem extends React.Component {
147
163
  kind="ghost"
148
164
  tabIndex={tabIndex}
149
165
  onClick={this.toggleExtendedMenu}
166
+ onKeyDown={this.onKeyDown}
150
167
  aria-label={this.props.label}
151
168
  size={this.props.size}
152
169
  >
153
170
  <div className="toolbar-item-content default">
154
- <div className="toolbar-icon">
171
+ <div className="toolbar-icon overflow-item">
155
172
  <OverflowMenuVertical16 />
156
173
  </div>
157
174
  </div>
@@ -152,11 +152,11 @@ class Toolbar extends React.Component {
152
152
  const refWithOpenSubArea = this.getRefWithOpenSubArea();
153
153
 
154
154
  if (refWithOpenSubArea) {
155
- const action = refWithOpenSubArea.current.getAction();
155
+ const action = refWithOpenSubArea.current?.getAction();
156
156
  const isFocusActionWithOpenSubAreaFocusable = this.isFocusActionFocusable(action, focusableItemRefs);
157
157
 
158
158
  if (!isFocusActionWithOpenSubAreaFocusable) {
159
- refWithOpenSubArea.current.closeSubArea();
159
+ refWithOpenSubArea.current?.closeSubArea();
160
160
 
161
161
  } else {
162
162
  // This forces a refresh that will cause the position of any
@@ -175,12 +175,12 @@ class Toolbar extends React.Component {
175
175
  // Returns the ref to any item that currently has an open sub-area or null
176
176
  // if no item has an open sub-area.
177
177
  getRefWithOpenSubArea() {
178
- let subAreaOpenRef = this.leftItemRefs.find((ref) => ref.current.isSubAreaDisplayed());
178
+ let subAreaOpenRef = this.leftItemRefs.find((ref) => ref.current?.isSubAreaDisplayed());
179
179
  if (!subAreaOpenRef) {
180
- subAreaOpenRef = this.rightItemRefs.find((ref) => ref.current.isSubAreaDisplayed());
180
+ subAreaOpenRef = this.rightItemRefs.find((ref) => ref.current?.isSubAreaDisplayed());
181
181
  }
182
182
  if (!subAreaOpenRef) {
183
- subAreaOpenRef = this.overflowItemRefs.find((ref) => ref.current.isSubAreaDisplayed());
183
+ subAreaOpenRef = this.overflowItemRefs.find((ref) => ref.current?.isSubAreaDisplayed());
184
184
  }
185
185
  return subAreaOpenRef;
186
186
  }
@@ -245,7 +245,7 @@ class Toolbar extends React.Component {
245
245
  }
246
246
 
247
247
  getRefAction(ref) {
248
- return ref.current.getAction();
248
+ return ref.current?.getAction();
249
249
  }
250
250
 
251
251
  // Returns an array of references to focusable (that is enabled)
@@ -270,17 +270,17 @@ class Toolbar extends React.Component {
270
270
  let overflowItemRef = null;
271
271
 
272
272
  for (let i = 0; i < this.leftItemRefs.length; i++) {
273
- const itemRect = this.leftItemRefs[i].current.getBoundingRect();
273
+ const itemRect = this.leftItemRefs[i].current?.getBoundingRect();
274
274
 
275
- if (itemRect.top === topRowY) {
276
- if (this.leftItemRefs[i].current.isEnabled()) {
275
+ if (itemRect?.top === topRowY) {
276
+ if (this.leftItemRefs[i].current?.isEnabled()) {
277
277
  focusableItemRefs.push(this.leftItemRefs[i]);
278
278
  }
279
279
 
280
280
  } else if (!overflowItemRef) {
281
281
  const leftRefAction = this.getRefAction(this.leftItemRefs[i]);
282
282
  const overflowAction = this.getOverflowAction(leftRefAction);
283
- overflowItemRef = this.overflowItemRefs.find((oRef) => oRef.current.getAction() === overflowAction);
283
+ overflowItemRef = this.overflowItemRefs.find((oRef) => oRef.current?.getAction() === overflowAction);
284
284
  if (overflowItemRef) {
285
285
  focusableItemRefs.push(overflowItemRef);
286
286
  }
@@ -303,8 +303,8 @@ class Toolbar extends React.Component {
303
303
  const topRowY = this.findToolbarTopYCoordinate();
304
304
 
305
305
  for (let i = 0; i < this.rightItemRefs.length; i++) {
306
- if (this.rightItemRefs[i].current.isEnabled()) {
307
- const refRect = this.rightItemRefs[i].current.getBoundingRect();
306
+ if (this.rightItemRefs[i].current?.isEnabled()) {
307
+ const refRect = this.rightItemRefs[i].current?.getBoundingRect();
308
308
 
309
309
  if (refRect.top === topRowY) {
310
310
  focusableItemRefs.push(this.rightItemRefs[i]);
@@ -355,7 +355,7 @@ class Toolbar extends React.Component {
355
355
  // items. (It may not be if it has been placed in the overflow menu).
356
356
  isFocusActionFocusable(focusAction, focusableItemRefs) {
357
357
  const indexFocusAction = focusableItemRefs.findIndex((ref) =>
358
- ref.current.props.actionObj?.action === focusAction);
358
+ ref.current?.props.actionObj?.action === focusAction);
359
359
  return indexFocusAction > -1;
360
360
  }
361
361
 
@@ -367,7 +367,7 @@ class Toolbar extends React.Component {
367
367
  let rightItemRef = null;
368
368
 
369
369
  for (let i = 0; i < this.rightItemRefs.length; i++) {
370
- const itemRect = this.rightItemRefs[i].current.getBoundingRect();
370
+ const itemRect = this.rightItemRefs[i].current?.getBoundingRect();
371
371
  if (itemRect.top !== topRowY && rightItemRef === null) {
372
372
  rightItemRef = this.rightItemRefs[i];
373
373
  }
@@ -379,8 +379,8 @@ class Toolbar extends React.Component {
379
379
  // used to detecg which toolbar items are on the top (visible)
380
380
  // row and which are wrapped onto other rows.
381
381
  findToolbarTopYCoordinate() {
382
- const rect = this.toolbarRef.current.getBoundingClientRect();
383
- return rect.top;
382
+ const rect = this.toolbarRef.current?.getBoundingClientRect();
383
+ return rect?.top;
384
384
  }
385
385
 
386
386
  // Generates an array of toolbar items from the toolbarActions array passed in. When
@@ -495,17 +495,17 @@ class Toolbar extends React.Component {
495
495
  }
496
496
 
497
497
  closeSubAreaOnRef(ref) {
498
- if (ref.current.props.actionObj.setExtIsSubAreaDisplayed) {
499
- ref.current.props.actionObj.setExtIsSubAreaDisplayed(false);
498
+ if (ref.current?.props.actionObj.setExtIsSubAreaDisplayed) {
499
+ ref.current?.props.actionObj.setExtIsSubAreaDisplayed(false);
500
500
 
501
- } else if (ref.current.state.subAreaDisplayed) {
502
- ref.current.closeSubArea();
501
+ } else if (ref.current?.state.subAreaDisplayed) {
502
+ ref.current?.closeSubArea();
503
503
  }
504
504
  }
505
505
 
506
506
  closeOverflowMenuOnRef(ref) {
507
- if (ref.current.state.showExtendedMenu) {
508
- ref.current.closeSubArea();
507
+ if (ref.current?.state.showExtendedMenu) {
508
+ ref.current?.closeSubArea();
509
509
  }
510
510
  }
511
511
 
@@ -61,10 +61,21 @@ $toolbar-divider-width: 1px;
61
61
  }
62
62
 
63
63
  .toolbar-item-content {
64
- padding: $spacing-02 $spacing-03;
65
64
  height: $toolbar-button-sm-height;
66
65
  align-items: center;
67
66
  min-width: 32px;
67
+
68
+ &.is-in-menu {
69
+ padding-left: 10px;
70
+ }
71
+
72
+ & .content-main {
73
+ padding: 0;
74
+ }
75
+
76
+ & .overflow-item {
77
+ padding: 6px;
78
+ }
68
79
  }
69
80
 
70
81
  .toolbar-popover-list button {
@@ -195,11 +206,53 @@ $toolbar-divider-width: 1px;
195
206
  width: inherit;
196
207
  display: flex;
197
208
  justify-content: center;
198
- padding: 11px;
199
209
 
200
- &.overflow {
210
+ &.disabled {
211
+ pointer-events: none;
212
+
213
+ & .content-main:hover,
214
+ & .toolbar-up-down-chevron-mini:hover {
215
+ pointer-events: none;
216
+ }
217
+ }
218
+
219
+ & .content-main {
220
+ padding: 11px;
221
+ display: flex;
222
+
223
+ &.dual:hover {
224
+ background-color: $background-selected-hover;
225
+ }
226
+ }
227
+
228
+ & .toolbar-up-down-chevron {
229
+ padding: 11px 8px 11px 0;
230
+ pointer-events: none;
231
+ }
232
+
233
+ & .toolbar-up-down-chevron-mini {
234
+ padding: 11px 2px;
235
+
236
+ &:hover {
237
+ background-color: $background-selected-hover;
238
+ }
239
+ }
240
+
241
+ & .toolbar-right-chevron {
242
+ padding: 9px 0 2px;
243
+ pointer-events: none;
244
+ }
245
+
246
+ & .overflow-item {
247
+ padding: 11px;
248
+ }
249
+
250
+ &.is-in-menu {
201
251
  justify-content: left;
202
- padding: 8px 0;
252
+
253
+ & .content-main {
254
+ padding: 8px 0 6px;
255
+ }
203
256
  }
204
257
 
205
258
  &.default {
@@ -228,10 +281,13 @@ $toolbar-divider-width: 1px;
228
281
 
229
282
  .toolbar-text-content {
230
283
  position: absolute;
231
- top: 14px;
284
+ width: 11px;
285
+ top: 15px;
286
+ left: 13px;
232
287
  font-size: 9px;
233
288
  line-height: 9px;
234
289
  color: $icon-01;
290
+ text-align: center;
235
291
  }
236
292
 
237
293
  .toolbar-icon-label {
@@ -252,12 +308,6 @@ $toolbar-divider-width: 1px;
252
308
  }
253
309
  }
254
310
 
255
- .toolbar-up-down-chevron {
256
- padding-left: 8px;
257
- height: 16px;
258
- pointer-events: none;
259
- }
260
-
261
311
  // Triangular tick mark in bottom right corner of an expandable icon
262
312
  .toolbar-tick-svg {
263
313
  position: absolute;