carbon-addons-iot-react 2.149.0-next.4 → 2.149.0-next.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -3,6 +3,46 @@
3
3
  All notable changes to this project will be documented in this file.
4
4
  See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
5
5
 
6
+ # [2.149.0-next.8](https://github.com/carbon-design-system/carbon-addons-iot-react/compare/v2.149.0-next.7...v2.149.0-next.8) (2022-02-21)
7
+
8
+ **Note:** Version bump only for package carbon-addons-iot-react
9
+
10
+
11
+
12
+
13
+
14
+ # [2.149.0-next.7](https://github.com/carbon-design-system/carbon-addons-iot-react/compare/v2.149.0-next.6...v2.149.0-next.7) (2022-02-21)
15
+
16
+ **Note:** Version bump only for package carbon-addons-iot-react
17
+
18
+
19
+
20
+
21
+
22
+ # [2.149.0-next.6](https://github.com/carbon-design-system/carbon-addons-iot-react/compare/v2.149.0-next.5...v2.149.0-next.6) (2022-02-18)
23
+
24
+
25
+ ### Bug Fixes
26
+
27
+ * **card:** fix overflow tooltip for card ([68611c4](https://github.com/carbon-design-system/carbon-addons-iot-react/commit/68611c412345ccfe29861fef1dfa17eeb9e32aed))
28
+
29
+
30
+ ### Features
31
+
32
+ * **hierarchy-list:** call onExpandedChange after rows are expanded ([f6811a8](https://github.com/carbon-design-system/carbon-addons-iot-react/commit/f6811a89909d0de4df663883924429e6f4242b38))
33
+
34
+
35
+
36
+
37
+
38
+ # [2.149.0-next.5](https://github.com/carbon-design-system/carbon-addons-iot-react/compare/v2.149.0-next.4...v2.149.0-next.5) (2022-02-16)
39
+
40
+ **Note:** Version bump only for package carbon-addons-iot-react
41
+
42
+
43
+
44
+
45
+
6
46
  # [2.149.0-next.4](https://github.com/carbon-design-system/carbon-addons-iot-react/compare/v2.149.0-next.3...v2.149.0-next.4) (2022-02-16)
7
47
 
8
48
 
@@ -385,8 +385,8 @@ var Card = function Card(props) {
385
385
 
386
386
  var titleRef = useRef();
387
387
  var subTitleRef = useRef();
388
- var hasTitleTooltip = useHasTextOverflow(titleRef);
389
- var hasSubTitleTooltip = useHasTextOverflow(subTitleRef);
388
+ var hasTitleTooltip = useHasTextOverflow(titleRef, title);
389
+ var hasSubTitleTooltip = useHasTextOverflow(subTitleRef, subtitle);
390
390
  var visibilityRef = useRef(null);
391
391
 
392
392
  var _useVisibilityObserve = useVisibilityObserver(visibilityRef, {
@@ -449,6 +449,7 @@ var Card = function Card(props) {
449
449
  triggerText: title
450
450
  }, title) : /*#__PURE__*/React__default.createElement("div", {
451
451
  ref: titleRef,
452
+ "data-testid": "".concat(testId, "-title-notip"),
452
453
  className: classnames("".concat(iotPrefix, "--card--title--text"), _defineProperty({}, "".concat(iotPrefix, "--card--title--text--wrapped"), hasTitleWrap && !subtitle))
453
454
  }, title), tooltip && /*#__PURE__*/React__default.createElement(Tooltip, {
454
455
  "data-testid": "".concat(testID || testId, "-tooltip"),
@@ -379,14 +379,16 @@ var HierarchyList = function HierarchyList(_ref2) {
379
379
  }, [expandedIdsProp]);
380
380
  /**
381
381
  * effect to trigger calling the onExpandedChange callback. Ignore it on the initial render
382
- * when previousExpandedIds is undefined, but fire it on every change afterward
382
+ * when previousExpandedIds is undefined, but fire it on every change afterward when using a
383
+ * virtualList. The regular list triggers the onExpandedChange callback in the handleAfterExpand
384
+ * function below.
383
385
  */
384
386
 
385
387
  useEffect(function () {
386
- if (previousExpandedIds !== undefined && !isEqual(previousExpandedIds, expandedIds)) {
388
+ if (previousExpandedIds !== undefined && !isEqual(previousExpandedIds, expandedIds) && isVirtualList) {
387
389
  onExpandedChange(expandedIds);
388
390
  }
389
- }, [expandedIds, onExpandedChange, previousExpandedIds]);
391
+ }, [expandedIds, isVirtualList, onExpandedChange, previousExpandedIds]);
390
392
  /**
391
393
  * Effect to handle indeterminate state for parent checkboxes. If we're in an editMode and
392
394
  * the selected ids changes, fire this effect to determine the currently indeterminate ids
@@ -640,7 +642,8 @@ var HierarchyList = function HierarchyList(_ref2) {
640
642
  onItemMoved: handleDrag,
641
643
  className: className,
642
644
  emptyState: emptyState,
643
- emptySearchState: emptySearchState
645
+ emptySearchState: emptySearchState,
646
+ onExpandedChange: onExpandedChange
644
647
  }));
645
648
  };
646
649
 
@@ -131,7 +131,10 @@ var propTypes = {
131
131
  handleLoadMore: PropTypes.func,
132
132
 
133
133
  /** RowIds for rows currently loading more child rows */
134
- loadingMoreIds: PropTypes.arrayOf(PropTypes.string)
134
+ loadingMoreIds: PropTypes.arrayOf(PropTypes.string),
135
+
136
+ /** called after the row has expanded or collapsed and is passed the array of expanded ids */
137
+ onExpandedChange: PropTypes.func
135
138
  };
136
139
  var defaultProps = {
137
140
  className: null,
@@ -170,7 +173,8 @@ var defaultProps = {
170
173
  emptyState: 'No list items to show',
171
174
  emptySearchState: 'No results found',
172
175
  testId: 'list',
173
- handleLoadMore: function handleLoadMore() {}
176
+ handleLoadMore: function handleLoadMore() {},
177
+ onExpandedChange: null
174
178
  };
175
179
  var List = /*#__PURE__*/forwardRef(function (props, ref) {
176
180
  var _overrides$header, _overrides$content, _classnames, _overrides$header2, _overrides$header2$pr, _overrides$header3, _overrides$content2;
@@ -205,7 +209,8 @@ var List = /*#__PURE__*/forwardRef(function (props, ref) {
205
209
  emptySearchState = props.emptySearchState,
206
210
  testId = props.testId,
207
211
  handleLoadMore = props.handleLoadMore,
208
- loadingMoreIds = props.loadingMoreIds;
212
+ loadingMoreIds = props.loadingMoreIds,
213
+ onExpandedChange = props.onExpandedChange;
209
214
  var mergedI18n = useMemo(function () {
210
215
  return _objectSpread(_objectSpread({}, defaultProps.i18n), i18n);
211
216
  }, [i18n]);
@@ -248,7 +253,8 @@ var List = /*#__PURE__*/forwardRef(function (props, ref) {
248
253
  loadingMoreIds: loadingMoreIds,
249
254
  selectedItemRef: ref,
250
255
  i18n: mergedI18n,
251
- lockedIds: lockedIds
256
+ lockedIds: lockedIds,
257
+ onExpandedChange: onExpandedChange
252
258
  }, overrides === null || overrides === void 0 ? void 0 : (_overrides$content2 = overrides.content) === null || _overrides$content2 === void 0 ? void 0 : _overrides$content2.props)), pagination && !isLoading ? /*#__PURE__*/React__default.createElement("div", {
253
259
  className: "".concat(iotPrefix, "--list--page")
254
260
  }, /*#__PURE__*/React__default.createElement(SimplePagination, _extends({}, pagination, {
@@ -700,6 +706,17 @@ List.__docgenInfo = {
700
706
  },
701
707
  "required": false,
702
708
  "description": "call back function for when load more row is clicked (rowId) => {}"
709
+ },
710
+ "onExpandedChange": {
711
+ "defaultValue": {
712
+ "value": "null",
713
+ "computed": false
714
+ },
715
+ "type": {
716
+ "name": "func"
717
+ },
718
+ "required": false,
719
+ "description": "called after the row has expanded or collapsed and is passed the array of expanded ids"
703
720
  }
704
721
  }
705
722
  };
@@ -5,11 +5,13 @@ import 'core-js/modules/web.dom-collections.for-each.js';
5
5
  import 'core-js/modules/es.object.get-own-property-descriptors.js';
6
6
  import _toConsumableArray from '@babel/runtime/helpers/toConsumableArray';
7
7
  import _defineProperty from '@babel/runtime/helpers/defineProperty';
8
+ import isEqual from '../../../packages/react/node_modules/lodash-es/isEqual.js';
8
9
  import 'core-js/modules/es.array.concat.js';
9
10
  import 'core-js/modules/es.array.filter.js';
10
11
  import 'core-js/modules/es.array.includes.js';
11
12
  import 'core-js/modules/es.string.includes.js';
12
13
  import 'core-js/modules/es.array.map.js';
14
+ import 'core-js/modules/es.array.slice.js';
13
15
  import React__default, { useMemo } from 'react';
14
16
  import { Checkbox, SkeletonText } from 'carbon-components-react';
15
17
  import classnames from 'classnames';
@@ -22,6 +24,7 @@ import { EditingStyle, editingStyleIsMultiple } from '../../../utils/DragAndDrop
22
24
  import { ListItemPropTypes } from '../ListPropTypes.js';
23
25
  import { HtmlElementRefProp } from '../../../constants/SharedPropTypes.js';
24
26
  import { ITEM_LEVEL_OFFSET, ITEM_COLUMN_GAP } from '../VirtualListContent/listConstants.js';
27
+ import { usePrevious } from '../../../hooks/usePrevious.js';
25
28
 
26
29
  function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); keys.push.apply(keys, symbols); } return keys; }
27
30
 
@@ -100,7 +103,10 @@ var propTypes = {
100
103
 
101
104
  /** icon can be left or right side of list row primary value */
102
105
  iconPosition: PropTypes.oneOf(['left', 'right']),
103
- selectedItemRef: HtmlElementRefProp
106
+ selectedItemRef: HtmlElementRefProp,
107
+
108
+ /** called after the row has expanded or collapsed and is passed the array of expanded ids */
109
+ onExpandedChange: PropTypes.func
104
110
  };
105
111
  var defaultProps = {
106
112
  editingStyle: null,
@@ -133,7 +139,8 @@ var defaultProps = {
133
139
  selectedIds: [],
134
140
  selectedItemRef: /*#__PURE__*/React__default.createRef(),
135
141
  testId: 'list',
136
- toggleExpansion: function toggleExpansion() {}
142
+ toggleExpansion: function toggleExpansion() {},
143
+ onExpandedChange: null
137
144
  };
138
145
 
139
146
  var getAdjustedNestingLevel = function getAdjustedNestingLevel(items, currentLevel) {
@@ -166,7 +173,8 @@ var ListContent = function ListContent(_ref) {
166
173
  lockedIds = _ref.lockedIds,
167
174
  handleLoadMore = _ref.handleLoadMore,
168
175
  i18n = _ref.i18n,
169
- selectedItemRef = _ref.selectedItemRef;
176
+ selectedItemRef = _ref.selectedItemRef,
177
+ onExpandedChange = _ref.onExpandedChange;
170
178
  var mergedI18n = useMemo(function () {
171
179
  return _objectSpread(_objectSpread({}, defaultProps.i18n), i18n);
172
180
  }, [i18n]);
@@ -277,7 +285,34 @@ var ListContent = function ListContent(_ref) {
277
285
  }).concat(item.hasLoadMore ? [renderLoadMore(item, isLoadingMore, level + 1)] : []) : []), _toConsumableArray(!hasChildren && item.hasLoadMore ? [renderLoadMore(item, isLoadingMore, level)] : []));
278
286
  };
279
287
 
288
+ var previousExpandedIds = usePrevious(expandedIds, expandedIds);
289
+ var selectionChanged = !isEqual(expandedIds, previousExpandedIds); // get the lastId of the diff between previous and current, this handles closes
290
+
291
+ var previousLastId = selectionChanged && previousExpandedIds.filter(function (id) {
292
+ return !expandedIds.includes(id);
293
+ }).slice(-1)[0]; // get the lastId of the diff between current and previous, this handles opens
294
+
295
+ var lastId = selectionChanged && expandedIds.filter(function (id) {
296
+ return !previousExpandedIds.includes(id);
297
+ }).slice(-1)[0];
298
+
299
+ var notifyOnLastExpansionChange = function notifyOnLastExpansionChange(itemId) {
300
+ var isLastItem = lastId === itemId || previousLastId === itemId;
301
+
302
+ if (isLastItem && expandedIds.includes(itemId) !== previousExpandedIds.includes(itemId)) {
303
+ // the setTimeout within the request animation frame helps to ensure the event is fired
304
+ // immediately after a repaint. See:
305
+ // https://firefox-source-docs.mozilla.org/performance/bestpractices.html#how-do-i-avoid-triggering-uninterruptible-reflow
306
+ window.requestAnimationFrame(function () {
307
+ setTimeout(function () {
308
+ onExpandedChange(expandedIds);
309
+ });
310
+ }, 0);
311
+ }
312
+ };
313
+
280
314
  var listItems = items.map(function (item, index) {
315
+ notifyOnLastExpansionChange(item.id);
281
316
  return renderItemAndChildren(item, index, null, getAdjustedNestingLevel(items, 0));
282
317
  });
283
318
 
@@ -640,6 +675,17 @@ ListContent.__docgenInfo = {
640
675
  },
641
676
  "required": false,
642
677
  "description": "call back function of expansion"
678
+ },
679
+ "onExpandedChange": {
680
+ "defaultValue": {
681
+ "value": "null",
682
+ "computed": false
683
+ },
684
+ "type": {
685
+ "name": "func"
686
+ },
687
+ "required": false,
688
+ "description": "called after the row has expanded or collapsed and is passed the array of expanded ids"
643
689
  }
644
690
  }
645
691
  };
@@ -291,7 +291,7 @@ var dragSourceSpecification = {
291
291
  id: props.id
292
292
  };
293
293
  }
294
- }; // These props origininate from React DND and are passed down to
294
+ }; // These props originate from React DND and are passed down to
295
295
  // the ListItem via the DragSource wrapper.
296
296
 
297
297
  var dndPropsCollecting = function dndPropsCollecting(connect, monitor) {
@@ -301,7 +301,8 @@ var propTypes = {
301
301
  /** Callbacks for actions of the table, can be used to update state in wrapper component to update `view` props */
302
302
  actions: PropTypes.shape({
303
303
  pagination: PropTypes.shape({
304
- /** Specify a callback for when the current page or page size is changed. This callback is passed an object parameter containing the current page and the current page size */
304
+ /** Specify a callback for when the current page or page size is changed.
305
+ * This callback is passed an object parameter containing the current page and the current page size */
305
306
  onChangePage: PropTypes.func
306
307
  }),
307
308
  toolbar: PropTypes.shape({
@@ -310,9 +311,15 @@ var propTypes = {
310
311
  onShowRowEdit: PropTypes.func,
311
312
  onToggleColumnSelection: PropTypes.func,
312
313
 
313
- /** Specify a callback for when the user clicks toolbar button to clear all filters. Receives a parameter of the current filter values for each column */
314
+ /** Specify a callback for when the user clicks toolbar button to clear all filters.
315
+ * Receives a parameter of the current filter values for each column */
314
316
  onClearAllFilters: PropTypes.func,
317
+
318
+ /** Callback for when the automatcally generated Cancel action in the batch actions bar is clicked */
315
319
  onCancelBatchAction: PropTypes.func,
320
+
321
+ /** Callback for all the batch actions except the cancel. Is called with the id of the clicked action.
322
+ * For the StatefulTable the current selections are received as second parameter */
316
323
  onApplyBatchAction: PropTypes.func,
317
324
 
318
325
  /** Apply a search criteria to the table */
@@ -354,7 +361,8 @@ var propTypes = {
354
361
  onSelectAll: PropTypes.func,
355
362
  onChangeSort: PropTypes.func,
356
363
 
357
- /** callback if a row action is clicked called with the id of the action then the id of the row if you return a promise from apply row action the stateful table will assume you're asynchronous and give a spinner */
364
+ /** callback if a row action is clicked called with the id of the action then the id of the row if you
365
+ * return a promise from apply row action the stateful table will assume you're asynchronous and give a spinner */
358
366
  onApplyRowAction: PropTypes.func,
359
367
  onClearRowError: PropTypes.func,
360
368
  onEmptyStateAction: PropTypes.func,
@@ -1668,7 +1676,7 @@ Table.__docgenInfo = {
1668
1676
  "value": {
1669
1677
  "onChangePage": {
1670
1678
  "name": "func",
1671
- "description": "Specify a callback for when the current page or page size is changed. This callback is passed an object parameter containing the current page and the current page size",
1679
+ "description": "Specify a callback for when the current page or page size is changed.\nThis callback is passed an object parameter containing the current page and the current page size",
1672
1680
  "required": false
1673
1681
  }
1674
1682
  },
@@ -1695,15 +1703,17 @@ Table.__docgenInfo = {
1695
1703
  },
1696
1704
  "onClearAllFilters": {
1697
1705
  "name": "func",
1698
- "description": "Specify a callback for when the user clicks toolbar button to clear all filters. Receives a parameter of the current filter values for each column",
1706
+ "description": "Specify a callback for when the user clicks toolbar button to clear all filters.\nReceives a parameter of the current filter values for each column",
1699
1707
  "required": false
1700
1708
  },
1701
1709
  "onCancelBatchAction": {
1702
1710
  "name": "func",
1711
+ "description": "Callback for when the automatcally generated Cancel action in the batch actions bar is clicked",
1703
1712
  "required": false
1704
1713
  },
1705
1714
  "onApplyBatchAction": {
1706
1715
  "name": "func",
1716
+ "description": "Callback for all the batch actions except the cancel. Is called with the id of the clicked action.\n For the StatefulTable the current selections are received as second parameter",
1707
1717
  "required": false
1708
1718
  },
1709
1719
  "onApplySearch": {
@@ -1784,7 +1794,7 @@ Table.__docgenInfo = {
1784
1794
  },
1785
1795
  "onApplyRowAction": {
1786
1796
  "name": "func",
1787
- "description": "callback if a row action is clicked called with the id of the action then the id of the row if you return a promise from apply row action the stateful table will assume you're asynchronous and give a spinner",
1797
+ "description": "callback if a row action is clicked called with the id of the action then the id of the row if you\nreturn a promise from apply row action the stateful table will assume you're asynchronous and give a spinner",
1788
1798
  "required": false
1789
1799
  },
1790
1800
  "onClearRowError": {
@@ -2,15 +2,24 @@ import _slicedToArray from '@babel/runtime/helpers/slicedToArray';
2
2
  import { useState, useEffect } from 'react';
3
3
 
4
4
  var useHasTextOverflow = function useHasTextOverflow(elementRef) {
5
+ var _elementRef$current5, _elementRef$current6, _elementRef$current7, _elementRef$current8;
6
+
7
+ var text = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : '';
8
+
5
9
  var _useState = useState(false),
6
10
  _useState2 = _slicedToArray(_useState, 2),
7
11
  isOverflowed = _useState2[0],
8
12
  setIsOverflowed = _useState2[1];
9
13
 
10
14
  useEffect(function () {
11
- var overFlowing = elementRef.current && (elementRef.current.scrollHeight > elementRef.current.clientHeight || elementRef.current.scrollWidth > elementRef.current.clientWidth);
15
+ var _elementRef$current, _elementRef$current2, _elementRef$current3, _elementRef$current4;
16
+
17
+ var overFlowing = elementRef.current && ((elementRef === null || elementRef === void 0 ? void 0 : (_elementRef$current = elementRef.current) === null || _elementRef$current === void 0 ? void 0 : _elementRef$current.scrollHeight) > (elementRef === null || elementRef === void 0 ? void 0 : (_elementRef$current2 = elementRef.current) === null || _elementRef$current2 === void 0 ? void 0 : _elementRef$current2.clientHeight) || (elementRef === null || elementRef === void 0 ? void 0 : (_elementRef$current3 = elementRef.current) === null || _elementRef$current3 === void 0 ? void 0 : _elementRef$current3.scrollWidth) > (elementRef === null || elementRef === void 0 ? void 0 : (_elementRef$current4 = elementRef.current) === null || _elementRef$current4 === void 0 ? void 0 : _elementRef$current4.clientWidth));
12
18
  setIsOverflowed(overFlowing);
13
- }, [elementRef]);
19
+ /* disabling to not put the ref in dep array */
20
+
21
+ /* eslint-disable react-hooks/exhaustive-deps */
22
+ }, [elementRef === null || elementRef === void 0 ? void 0 : (_elementRef$current5 = elementRef.current) === null || _elementRef$current5 === void 0 ? void 0 : _elementRef$current5.clientHeight, elementRef === null || elementRef === void 0 ? void 0 : (_elementRef$current6 = elementRef.current) === null || _elementRef$current6 === void 0 ? void 0 : _elementRef$current6.clientWidth, elementRef === null || elementRef === void 0 ? void 0 : (_elementRef$current7 = elementRef.current) === null || _elementRef$current7 === void 0 ? void 0 : _elementRef$current7.scrollHeight, elementRef === null || elementRef === void 0 ? void 0 : (_elementRef$current8 = elementRef.current) === null || _elementRef$current8 === void 0 ? void 0 : _elementRef$current8.scrollWidth, text]);
14
23
  return isOverflowed;
15
24
  };
16
25
 
@@ -400,8 +400,8 @@ var Card = function Card(props) {
400
400
 
401
401
  var titleRef = React.useRef();
402
402
  var subTitleRef = React.useRef();
403
- var hasTitleTooltip = useHasTextOverflow(titleRef);
404
- var hasSubTitleTooltip = useHasTextOverflow(subTitleRef);
403
+ var hasTitleTooltip = useHasTextOverflow(titleRef, title);
404
+ var hasSubTitleTooltip = useHasTextOverflow(subTitleRef, subtitle);
405
405
  var visibilityRef = React.useRef(null);
406
406
 
407
407
  var _useVisibilityObserve = useVisibilityObserver(visibilityRef, {
@@ -464,6 +464,7 @@ var Card = function Card(props) {
464
464
  triggerText: title
465
465
  }, title) : /*#__PURE__*/React__default['default'].createElement("div", {
466
466
  ref: titleRef,
467
+ "data-testid": "".concat(testId, "-title-notip"),
467
468
  className: classnames__default['default']("".concat(iotPrefix, "--card--title--text"), _defineProperty__default['default']({}, "".concat(iotPrefix, "--card--title--text--wrapped"), hasTitleWrap && !subtitle))
468
469
  }, title), tooltip && /*#__PURE__*/React__default['default'].createElement(carbonComponentsReact.Tooltip, {
469
470
  "data-testid": "".concat(testID || testId, "-tooltip"),
@@ -392,14 +392,16 @@ var HierarchyList = function HierarchyList(_ref2) {
392
392
  }, [expandedIdsProp]);
393
393
  /**
394
394
  * effect to trigger calling the onExpandedChange callback. Ignore it on the initial render
395
- * when previousExpandedIds is undefined, but fire it on every change afterward
395
+ * when previousExpandedIds is undefined, but fire it on every change afterward when using a
396
+ * virtualList. The regular list triggers the onExpandedChange callback in the handleAfterExpand
397
+ * function below.
396
398
  */
397
399
 
398
400
  React.useEffect(function () {
399
- if (previousExpandedIds !== undefined && !isEqual(previousExpandedIds, expandedIds)) {
401
+ if (previousExpandedIds !== undefined && !isEqual(previousExpandedIds, expandedIds) && isVirtualList) {
400
402
  onExpandedChange(expandedIds);
401
403
  }
402
- }, [expandedIds, onExpandedChange, previousExpandedIds]);
404
+ }, [expandedIds, isVirtualList, onExpandedChange, previousExpandedIds]);
403
405
  /**
404
406
  * Effect to handle indeterminate state for parent checkboxes. If we're in an editMode and
405
407
  * the selected ids changes, fire this effect to determine the currently indeterminate ids
@@ -653,7 +655,8 @@ var HierarchyList = function HierarchyList(_ref2) {
653
655
  onItemMoved: handleDrag,
654
656
  className: className,
655
657
  emptyState: emptyState,
656
- emptySearchState: emptySearchState
658
+ emptySearchState: emptySearchState,
659
+ onExpandedChange: onExpandedChange
657
660
  }));
658
661
  };
659
662
 
@@ -143,7 +143,10 @@ var propTypes = {
143
143
  handleLoadMore: PropTypes__default['default'].func,
144
144
 
145
145
  /** RowIds for rows currently loading more child rows */
146
- loadingMoreIds: PropTypes__default['default'].arrayOf(PropTypes__default['default'].string)
146
+ loadingMoreIds: PropTypes__default['default'].arrayOf(PropTypes__default['default'].string),
147
+
148
+ /** called after the row has expanded or collapsed and is passed the array of expanded ids */
149
+ onExpandedChange: PropTypes__default['default'].func
147
150
  };
148
151
  var defaultProps = {
149
152
  className: null,
@@ -182,7 +185,8 @@ var defaultProps = {
182
185
  emptyState: 'No list items to show',
183
186
  emptySearchState: 'No results found',
184
187
  testId: 'list',
185
- handleLoadMore: function handleLoadMore() {}
188
+ handleLoadMore: function handleLoadMore() {},
189
+ onExpandedChange: null
186
190
  };
187
191
  var List = /*#__PURE__*/React.forwardRef(function (props, ref) {
188
192
  var _overrides$header, _overrides$content, _classnames, _overrides$header2, _overrides$header2$pr, _overrides$header3, _overrides$content2;
@@ -217,7 +221,8 @@ var List = /*#__PURE__*/React.forwardRef(function (props, ref) {
217
221
  emptySearchState = props.emptySearchState,
218
222
  testId = props.testId,
219
223
  handleLoadMore = props.handleLoadMore,
220
- loadingMoreIds = props.loadingMoreIds;
224
+ loadingMoreIds = props.loadingMoreIds,
225
+ onExpandedChange = props.onExpandedChange;
221
226
  var mergedI18n = React.useMemo(function () {
222
227
  return _objectSpread(_objectSpread({}, defaultProps.i18n), i18n);
223
228
  }, [i18n]);
@@ -260,7 +265,8 @@ var List = /*#__PURE__*/React.forwardRef(function (props, ref) {
260
265
  loadingMoreIds: loadingMoreIds,
261
266
  selectedItemRef: ref,
262
267
  i18n: mergedI18n,
263
- lockedIds: lockedIds
268
+ lockedIds: lockedIds,
269
+ onExpandedChange: onExpandedChange
264
270
  }, overrides === null || overrides === void 0 ? void 0 : (_overrides$content2 = overrides.content) === null || _overrides$content2 === void 0 ? void 0 : _overrides$content2.props)), pagination && !isLoading ? /*#__PURE__*/React__default['default'].createElement("div", {
265
271
  className: "".concat(iotPrefix, "--list--page")
266
272
  }, /*#__PURE__*/React__default['default'].createElement(SimplePagination['default'], _extends__default['default']({}, pagination, {
@@ -712,6 +718,17 @@ List.__docgenInfo = {
712
718
  },
713
719
  "required": false,
714
720
  "description": "call back function for when load more row is clicked (rowId) => {}"
721
+ },
722
+ "onExpandedChange": {
723
+ "defaultValue": {
724
+ "value": "null",
725
+ "computed": false
726
+ },
727
+ "type": {
728
+ "name": "func"
729
+ },
730
+ "required": false,
731
+ "description": "called after the row has expanded or collapsed and is passed the array of expanded ids"
715
732
  }
716
733
  }
717
734
  };
@@ -7,11 +7,13 @@ require('core-js/modules/web.dom-collections.for-each.js');
7
7
  require('core-js/modules/es.object.get-own-property-descriptors.js');
8
8
  var _toConsumableArray = require('@babel/runtime/helpers/toConsumableArray');
9
9
  var _defineProperty = require('@babel/runtime/helpers/defineProperty');
10
+ var isEqual = require('../../../packages/react/node_modules/lodash-es/isEqual.js');
10
11
  require('core-js/modules/es.array.concat.js');
11
12
  require('core-js/modules/es.array.filter.js');
12
13
  require('core-js/modules/es.array.includes.js');
13
14
  require('core-js/modules/es.string.includes.js');
14
15
  require('core-js/modules/es.array.map.js');
16
+ require('core-js/modules/es.array.slice.js');
15
17
  var React = require('react');
16
18
  var carbonComponentsReact = require('carbon-components-react');
17
19
  var classnames = require('classnames');
@@ -24,6 +26,7 @@ var DragAndDropUtils = require('../../../utils/DragAndDropUtils.js');
24
26
  var ListPropTypes = require('../ListPropTypes.js');
25
27
  var SharedPropTypes = require('../../../constants/SharedPropTypes.js');
26
28
  var listConstants = require('../VirtualListContent/listConstants.js');
29
+ var usePrevious = require('../../../hooks/usePrevious.js');
27
30
 
28
31
  function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
29
32
 
@@ -110,7 +113,10 @@ var propTypes = {
110
113
 
111
114
  /** icon can be left or right side of list row primary value */
112
115
  iconPosition: PropTypes__default['default'].oneOf(['left', 'right']),
113
- selectedItemRef: SharedPropTypes.HtmlElementRefProp
116
+ selectedItemRef: SharedPropTypes.HtmlElementRefProp,
117
+
118
+ /** called after the row has expanded or collapsed and is passed the array of expanded ids */
119
+ onExpandedChange: PropTypes__default['default'].func
114
120
  };
115
121
  var defaultProps = {
116
122
  editingStyle: null,
@@ -143,7 +149,8 @@ var defaultProps = {
143
149
  selectedIds: [],
144
150
  selectedItemRef: /*#__PURE__*/React__default['default'].createRef(),
145
151
  testId: 'list',
146
- toggleExpansion: function toggleExpansion() {}
152
+ toggleExpansion: function toggleExpansion() {},
153
+ onExpandedChange: null
147
154
  };
148
155
 
149
156
  var getAdjustedNestingLevel = function getAdjustedNestingLevel(items, currentLevel) {
@@ -176,7 +183,8 @@ var ListContent = function ListContent(_ref) {
176
183
  lockedIds = _ref.lockedIds,
177
184
  handleLoadMore = _ref.handleLoadMore,
178
185
  i18n = _ref.i18n,
179
- selectedItemRef = _ref.selectedItemRef;
186
+ selectedItemRef = _ref.selectedItemRef,
187
+ onExpandedChange = _ref.onExpandedChange;
180
188
  var mergedI18n = React.useMemo(function () {
181
189
  return _objectSpread(_objectSpread({}, defaultProps.i18n), i18n);
182
190
  }, [i18n]);
@@ -287,7 +295,34 @@ var ListContent = function ListContent(_ref) {
287
295
  }).concat(item.hasLoadMore ? [renderLoadMore(item, isLoadingMore, level + 1)] : []) : []), _toConsumableArray__default['default'](!hasChildren && item.hasLoadMore ? [renderLoadMore(item, isLoadingMore, level)] : []));
288
296
  };
289
297
 
298
+ var previousExpandedIds = usePrevious.usePrevious(expandedIds, expandedIds);
299
+ var selectionChanged = !isEqual(expandedIds, previousExpandedIds); // get the lastId of the diff between previous and current, this handles closes
300
+
301
+ var previousLastId = selectionChanged && previousExpandedIds.filter(function (id) {
302
+ return !expandedIds.includes(id);
303
+ }).slice(-1)[0]; // get the lastId of the diff between current and previous, this handles opens
304
+
305
+ var lastId = selectionChanged && expandedIds.filter(function (id) {
306
+ return !previousExpandedIds.includes(id);
307
+ }).slice(-1)[0];
308
+
309
+ var notifyOnLastExpansionChange = function notifyOnLastExpansionChange(itemId) {
310
+ var isLastItem = lastId === itemId || previousLastId === itemId;
311
+
312
+ if (isLastItem && expandedIds.includes(itemId) !== previousExpandedIds.includes(itemId)) {
313
+ // the setTimeout within the request animation frame helps to ensure the event is fired
314
+ // immediately after a repaint. See:
315
+ // https://firefox-source-docs.mozilla.org/performance/bestpractices.html#how-do-i-avoid-triggering-uninterruptible-reflow
316
+ window.requestAnimationFrame(function () {
317
+ setTimeout(function () {
318
+ onExpandedChange(expandedIds);
319
+ });
320
+ }, 0);
321
+ }
322
+ };
323
+
290
324
  var listItems = items.map(function (item, index) {
325
+ notifyOnLastExpansionChange(item.id);
291
326
  return renderItemAndChildren(item, index, null, getAdjustedNestingLevel(items, 0));
292
327
  });
293
328
 
@@ -650,6 +685,17 @@ ListContent.__docgenInfo = {
650
685
  },
651
686
  "required": false,
652
687
  "description": "call back function of expansion"
688
+ },
689
+ "onExpandedChange": {
690
+ "defaultValue": {
691
+ "value": "null",
692
+ "computed": false
693
+ },
694
+ "type": {
695
+ "name": "func"
696
+ },
697
+ "required": false,
698
+ "description": "called after the row has expanded or collapsed and is passed the array of expanded ids"
653
699
  }
654
700
  }
655
701
  };
@@ -304,7 +304,7 @@ var dragSourceSpecification = {
304
304
  id: props.id
305
305
  };
306
306
  }
307
- }; // These props origininate from React DND and are passed down to
307
+ }; // These props originate from React DND and are passed down to
308
308
  // the ListItem via the DragSource wrapper.
309
309
 
310
310
  var dndPropsCollecting = function dndPropsCollecting(connect, monitor) {
@@ -318,7 +318,8 @@ var propTypes = {
318
318
  /** Callbacks for actions of the table, can be used to update state in wrapper component to update `view` props */
319
319
  actions: PropTypes__default['default'].shape({
320
320
  pagination: PropTypes__default['default'].shape({
321
- /** Specify a callback for when the current page or page size is changed. This callback is passed an object parameter containing the current page and the current page size */
321
+ /** Specify a callback for when the current page or page size is changed.
322
+ * This callback is passed an object parameter containing the current page and the current page size */
322
323
  onChangePage: PropTypes__default['default'].func
323
324
  }),
324
325
  toolbar: PropTypes__default['default'].shape({
@@ -327,9 +328,15 @@ var propTypes = {
327
328
  onShowRowEdit: PropTypes__default['default'].func,
328
329
  onToggleColumnSelection: PropTypes__default['default'].func,
329
330
 
330
- /** Specify a callback for when the user clicks toolbar button to clear all filters. Receives a parameter of the current filter values for each column */
331
+ /** Specify a callback for when the user clicks toolbar button to clear all filters.
332
+ * Receives a parameter of the current filter values for each column */
331
333
  onClearAllFilters: PropTypes__default['default'].func,
334
+
335
+ /** Callback for when the automatcally generated Cancel action in the batch actions bar is clicked */
332
336
  onCancelBatchAction: PropTypes__default['default'].func,
337
+
338
+ /** Callback for all the batch actions except the cancel. Is called with the id of the clicked action.
339
+ * For the StatefulTable the current selections are received as second parameter */
333
340
  onApplyBatchAction: PropTypes__default['default'].func,
334
341
 
335
342
  /** Apply a search criteria to the table */
@@ -371,7 +378,8 @@ var propTypes = {
371
378
  onSelectAll: PropTypes__default['default'].func,
372
379
  onChangeSort: PropTypes__default['default'].func,
373
380
 
374
- /** callback if a row action is clicked called with the id of the action then the id of the row if you return a promise from apply row action the stateful table will assume you're asynchronous and give a spinner */
381
+ /** callback if a row action is clicked called with the id of the action then the id of the row if you
382
+ * return a promise from apply row action the stateful table will assume you're asynchronous and give a spinner */
375
383
  onApplyRowAction: PropTypes__default['default'].func,
376
384
  onClearRowError: PropTypes__default['default'].func,
377
385
  onEmptyStateAction: PropTypes__default['default'].func,
@@ -1685,7 +1693,7 @@ Table.__docgenInfo = {
1685
1693
  "value": {
1686
1694
  "onChangePage": {
1687
1695
  "name": "func",
1688
- "description": "Specify a callback for when the current page or page size is changed. This callback is passed an object parameter containing the current page and the current page size",
1696
+ "description": "Specify a callback for when the current page or page size is changed.\nThis callback is passed an object parameter containing the current page and the current page size",
1689
1697
  "required": false
1690
1698
  }
1691
1699
  },
@@ -1712,15 +1720,17 @@ Table.__docgenInfo = {
1712
1720
  },
1713
1721
  "onClearAllFilters": {
1714
1722
  "name": "func",
1715
- "description": "Specify a callback for when the user clicks toolbar button to clear all filters. Receives a parameter of the current filter values for each column",
1723
+ "description": "Specify a callback for when the user clicks toolbar button to clear all filters.\nReceives a parameter of the current filter values for each column",
1716
1724
  "required": false
1717
1725
  },
1718
1726
  "onCancelBatchAction": {
1719
1727
  "name": "func",
1728
+ "description": "Callback for when the automatcally generated Cancel action in the batch actions bar is clicked",
1720
1729
  "required": false
1721
1730
  },
1722
1731
  "onApplyBatchAction": {
1723
1732
  "name": "func",
1733
+ "description": "Callback for all the batch actions except the cancel. Is called with the id of the clicked action.\n For the StatefulTable the current selections are received as second parameter",
1724
1734
  "required": false
1725
1735
  },
1726
1736
  "onApplySearch": {
@@ -1801,7 +1811,7 @@ Table.__docgenInfo = {
1801
1811
  },
1802
1812
  "onApplyRowAction": {
1803
1813
  "name": "func",
1804
- "description": "callback if a row action is clicked called with the id of the action then the id of the row if you return a promise from apply row action the stateful table will assume you're asynchronous and give a spinner",
1814
+ "description": "callback if a row action is clicked called with the id of the action then the id of the row if you\nreturn a promise from apply row action the stateful table will assume you're asynchronous and give a spinner",
1805
1815
  "required": false
1806
1816
  },
1807
1817
  "onClearRowError": {
@@ -8,15 +8,24 @@ function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'defau
8
8
  var _slicedToArray__default = /*#__PURE__*/_interopDefaultLegacy(_slicedToArray);
9
9
 
10
10
  var useHasTextOverflow = function useHasTextOverflow(elementRef) {
11
+ var _elementRef$current5, _elementRef$current6, _elementRef$current7, _elementRef$current8;
12
+
13
+ var text = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : '';
14
+
11
15
  var _useState = React.useState(false),
12
16
  _useState2 = _slicedToArray__default['default'](_useState, 2),
13
17
  isOverflowed = _useState2[0],
14
18
  setIsOverflowed = _useState2[1];
15
19
 
16
20
  React.useEffect(function () {
17
- var overFlowing = elementRef.current && (elementRef.current.scrollHeight > elementRef.current.clientHeight || elementRef.current.scrollWidth > elementRef.current.clientWidth);
21
+ var _elementRef$current, _elementRef$current2, _elementRef$current3, _elementRef$current4;
22
+
23
+ var overFlowing = elementRef.current && ((elementRef === null || elementRef === void 0 ? void 0 : (_elementRef$current = elementRef.current) === null || _elementRef$current === void 0 ? void 0 : _elementRef$current.scrollHeight) > (elementRef === null || elementRef === void 0 ? void 0 : (_elementRef$current2 = elementRef.current) === null || _elementRef$current2 === void 0 ? void 0 : _elementRef$current2.clientHeight) || (elementRef === null || elementRef === void 0 ? void 0 : (_elementRef$current3 = elementRef.current) === null || _elementRef$current3 === void 0 ? void 0 : _elementRef$current3.scrollWidth) > (elementRef === null || elementRef === void 0 ? void 0 : (_elementRef$current4 = elementRef.current) === null || _elementRef$current4 === void 0 ? void 0 : _elementRef$current4.clientWidth));
18
24
  setIsOverflowed(overFlowing);
19
- }, [elementRef]);
25
+ /* disabling to not put the ref in dep array */
26
+
27
+ /* eslint-disable react-hooks/exhaustive-deps */
28
+ }, [elementRef === null || elementRef === void 0 ? void 0 : (_elementRef$current5 = elementRef.current) === null || _elementRef$current5 === void 0 ? void 0 : _elementRef$current5.clientHeight, elementRef === null || elementRef === void 0 ? void 0 : (_elementRef$current6 = elementRef.current) === null || _elementRef$current6 === void 0 ? void 0 : _elementRef$current6.clientWidth, elementRef === null || elementRef === void 0 ? void 0 : (_elementRef$current7 = elementRef.current) === null || _elementRef$current7 === void 0 ? void 0 : _elementRef$current7.scrollHeight, elementRef === null || elementRef === void 0 ? void 0 : (_elementRef$current8 = elementRef.current) === null || _elementRef$current8 === void 0 ? void 0 : _elementRef$current8.scrollWidth, text]);
20
29
  return isOverflowed;
21
30
  };
22
31
 
package/package.json CHANGED
@@ -339,10 +339,10 @@
339
339
  "whatwg-fetch": "^3.0.0"
340
340
  },
341
341
  "sideEffects": false,
342
- "version": "2.149.0-next.4",
342
+ "version": "2.149.0-next.8",
343
343
  "resolutions": {
344
344
  "chokidar": "3.3.1",
345
345
  "react-grid-layout": "1.2.2"
346
346
  },
347
- "gitHead": "f534fed80c7aaf17902ae756f6e30dc9bbeaddce"
347
+ "gitHead": "cd70f9aa373747754c8107c5a03bc83b881e549e"
348
348
  }
@@ -43614,7 +43614,8 @@
43614
43614
  /** Callbacks for actions of the table, can be used to update state in wrapper component to update `view` props */
43615
43615
  actions: PropTypes__default['default'].shape({
43616
43616
  pagination: PropTypes__default['default'].shape({
43617
- /** Specify a callback for when the current page or page size is changed. This callback is passed an object parameter containing the current page and the current page size */
43617
+ /** Specify a callback for when the current page or page size is changed.
43618
+ * This callback is passed an object parameter containing the current page and the current page size */
43618
43619
  onChangePage: PropTypes__default['default'].func
43619
43620
  }),
43620
43621
  toolbar: PropTypes__default['default'].shape({
@@ -43623,9 +43624,15 @@
43623
43624
  onShowRowEdit: PropTypes__default['default'].func,
43624
43625
  onToggleColumnSelection: PropTypes__default['default'].func,
43625
43626
 
43626
- /** Specify a callback for when the user clicks toolbar button to clear all filters. Receives a parameter of the current filter values for each column */
43627
+ /** Specify a callback for when the user clicks toolbar button to clear all filters.
43628
+ * Receives a parameter of the current filter values for each column */
43627
43629
  onClearAllFilters: PropTypes__default['default'].func,
43630
+
43631
+ /** Callback for when the automatcally generated Cancel action in the batch actions bar is clicked */
43628
43632
  onCancelBatchAction: PropTypes__default['default'].func,
43633
+
43634
+ /** Callback for all the batch actions except the cancel. Is called with the id of the clicked action.
43635
+ * For the StatefulTable the current selections are received as second parameter */
43629
43636
  onApplyBatchAction: PropTypes__default['default'].func,
43630
43637
 
43631
43638
  /** Apply a search criteria to the table */
@@ -43667,7 +43674,8 @@
43667
43674
  onSelectAll: PropTypes__default['default'].func,
43668
43675
  onChangeSort: PropTypes__default['default'].func,
43669
43676
 
43670
- /** callback if a row action is clicked called with the id of the action then the id of the row if you return a promise from apply row action the stateful table will assume you're asynchronous and give a spinner */
43677
+ /** callback if a row action is clicked called with the id of the action then the id of the row if you
43678
+ * return a promise from apply row action the stateful table will assume you're asynchronous and give a spinner */
43671
43679
  onApplyRowAction: PropTypes__default['default'].func,
43672
43680
  onClearRowError: PropTypes__default['default'].func,
43673
43681
  onEmptyStateAction: PropTypes__default['default'].func,
@@ -44981,7 +44989,7 @@
44981
44989
  "value": {
44982
44990
  "onChangePage": {
44983
44991
  "name": "func",
44984
- "description": "Specify a callback for when the current page or page size is changed. This callback is passed an object parameter containing the current page and the current page size",
44992
+ "description": "Specify a callback for when the current page or page size is changed.\nThis callback is passed an object parameter containing the current page and the current page size",
44985
44993
  "required": false
44986
44994
  }
44987
44995
  },
@@ -45008,15 +45016,17 @@
45008
45016
  },
45009
45017
  "onClearAllFilters": {
45010
45018
  "name": "func",
45011
- "description": "Specify a callback for when the user clicks toolbar button to clear all filters. Receives a parameter of the current filter values for each column",
45019
+ "description": "Specify a callback for when the user clicks toolbar button to clear all filters.\nReceives a parameter of the current filter values for each column",
45012
45020
  "required": false
45013
45021
  },
45014
45022
  "onCancelBatchAction": {
45015
45023
  "name": "func",
45024
+ "description": "Callback for when the automatcally generated Cancel action in the batch actions bar is clicked",
45016
45025
  "required": false
45017
45026
  },
45018
45027
  "onApplyBatchAction": {
45019
45028
  "name": "func",
45029
+ "description": "Callback for all the batch actions except the cancel. Is called with the id of the clicked action.\n For the StatefulTable the current selections are received as second parameter",
45020
45030
  "required": false
45021
45031
  },
45022
45032
  "onApplySearch": {
@@ -45097,7 +45107,7 @@
45097
45107
  },
45098
45108
  "onApplyRowAction": {
45099
45109
  "name": "func",
45100
- "description": "callback if a row action is clicked called with the id of the action then the id of the row if you return a promise from apply row action the stateful table will assume you're asynchronous and give a spinner",
45110
+ "description": "callback if a row action is clicked called with the id of the action then the id of the row if you\nreturn a promise from apply row action the stateful table will assume you're asynchronous and give a spinner",
45101
45111
  "required": false
45102
45112
  },
45103
45113
  "onClearRowError": {
@@ -46996,7 +47006,7 @@
46996
47006
  id: props.id
46997
47007
  };
46998
47008
  }
46999
- }; // These props origininate from React DND and are passed down to
47009
+ }; // These props originate from React DND and are passed down to
47000
47010
  // the ListItem via the DragSource wrapper.
47001
47011
 
47002
47012
  var dndPropsCollecting = function dndPropsCollecting(connect, monitor) {
@@ -47506,7 +47516,10 @@
47506
47516
 
47507
47517
  /** icon can be left or right side of list row primary value */
47508
47518
  iconPosition: PropTypes__default['default'].oneOf(['left', 'right']),
47509
- selectedItemRef: HtmlElementRefProp
47519
+ selectedItemRef: HtmlElementRefProp,
47520
+
47521
+ /** called after the row has expanded or collapsed and is passed the array of expanded ids */
47522
+ onExpandedChange: PropTypes__default['default'].func
47510
47523
  };
47511
47524
  var defaultProps$1U = {
47512
47525
  editingStyle: null,
@@ -47539,7 +47552,8 @@
47539
47552
  selectedIds: [],
47540
47553
  selectedItemRef: /*#__PURE__*/React__default['default'].createRef(),
47541
47554
  testId: 'list',
47542
- toggleExpansion: function toggleExpansion() {}
47555
+ toggleExpansion: function toggleExpansion() {},
47556
+ onExpandedChange: null
47543
47557
  };
47544
47558
 
47545
47559
  var getAdjustedNestingLevel$1 = function getAdjustedNestingLevel(items, currentLevel) {
@@ -47572,7 +47586,8 @@
47572
47586
  lockedIds = _ref.lockedIds,
47573
47587
  handleLoadMore = _ref.handleLoadMore,
47574
47588
  i18n = _ref.i18n,
47575
- selectedItemRef = _ref.selectedItemRef;
47589
+ selectedItemRef = _ref.selectedItemRef,
47590
+ onExpandedChange = _ref.onExpandedChange;
47576
47591
  var mergedI18n = React$1.useMemo(function () {
47577
47592
  return _objectSpread$1H(_objectSpread$1H({}, defaultProps$1U.i18n), i18n);
47578
47593
  }, [i18n]);
@@ -47683,7 +47698,34 @@
47683
47698
  }).concat(item.hasLoadMore ? [renderLoadMore(item, isLoadingMore, level + 1)] : []) : []), toConsumableArray(!hasChildren && item.hasLoadMore ? [renderLoadMore(item, isLoadingMore, level)] : []));
47684
47699
  };
47685
47700
 
47701
+ var previousExpandedIds = usePrevious(expandedIds, expandedIds);
47702
+ var selectionChanged = !isEqual$2(expandedIds, previousExpandedIds); // get the lastId of the diff between previous and current, this handles closes
47703
+
47704
+ var previousLastId = selectionChanged && previousExpandedIds.filter(function (id) {
47705
+ return !expandedIds.includes(id);
47706
+ }).slice(-1)[0]; // get the lastId of the diff between current and previous, this handles opens
47707
+
47708
+ var lastId = selectionChanged && expandedIds.filter(function (id) {
47709
+ return !previousExpandedIds.includes(id);
47710
+ }).slice(-1)[0];
47711
+
47712
+ var notifyOnLastExpansionChange = function notifyOnLastExpansionChange(itemId) {
47713
+ var isLastItem = lastId === itemId || previousLastId === itemId;
47714
+
47715
+ if (isLastItem && expandedIds.includes(itemId) !== previousExpandedIds.includes(itemId)) {
47716
+ // the setTimeout within the request animation frame helps to ensure the event is fired
47717
+ // immediately after a repaint. See:
47718
+ // https://firefox-source-docs.mozilla.org/performance/bestpractices.html#how-do-i-avoid-triggering-uninterruptible-reflow
47719
+ window.requestAnimationFrame(function () {
47720
+ setTimeout(function () {
47721
+ onExpandedChange(expandedIds);
47722
+ });
47723
+ }, 0);
47724
+ }
47725
+ };
47726
+
47686
47727
  var listItems = items.map(function (item, index) {
47728
+ notifyOnLastExpansionChange(item.id);
47687
47729
  return renderItemAndChildren(item, index, null, getAdjustedNestingLevel$1(items, 0));
47688
47730
  });
47689
47731
 
@@ -48046,6 +48088,17 @@
48046
48088
  },
48047
48089
  "required": false,
48048
48090
  "description": "call back function of expansion"
48091
+ },
48092
+ "onExpandedChange": {
48093
+ "defaultValue": {
48094
+ "value": "null",
48095
+ "computed": false
48096
+ },
48097
+ "type": {
48098
+ "name": "func"
48099
+ },
48100
+ "required": false,
48101
+ "description": "called after the row has expanded or collapsed and is passed the array of expanded ids"
48049
48102
  }
48050
48103
  }
48051
48104
  };
@@ -49861,7 +49914,10 @@
49861
49914
  handleLoadMore: PropTypes__default['default'].func,
49862
49915
 
49863
49916
  /** RowIds for rows currently loading more child rows */
49864
- loadingMoreIds: PropTypes__default['default'].arrayOf(PropTypes__default['default'].string)
49917
+ loadingMoreIds: PropTypes__default['default'].arrayOf(PropTypes__default['default'].string),
49918
+
49919
+ /** called after the row has expanded or collapsed and is passed the array of expanded ids */
49920
+ onExpandedChange: PropTypes__default['default'].func
49865
49921
  };
49866
49922
  var defaultProps$1S = {
49867
49923
  className: null,
@@ -49900,7 +49956,8 @@
49900
49956
  emptyState: 'No list items to show',
49901
49957
  emptySearchState: 'No results found',
49902
49958
  testId: 'list',
49903
- handleLoadMore: function handleLoadMore() {}
49959
+ handleLoadMore: function handleLoadMore() {},
49960
+ onExpandedChange: null
49904
49961
  };
49905
49962
  var List = /*#__PURE__*/React$1.forwardRef(function (props, ref) {
49906
49963
  var _overrides$header, _overrides$content, _classnames, _overrides$header2, _overrides$header2$pr, _overrides$header3, _overrides$content2;
@@ -49935,7 +49992,8 @@
49935
49992
  emptySearchState = props.emptySearchState,
49936
49993
  testId = props.testId,
49937
49994
  handleLoadMore = props.handleLoadMore,
49938
- loadingMoreIds = props.loadingMoreIds;
49995
+ loadingMoreIds = props.loadingMoreIds,
49996
+ onExpandedChange = props.onExpandedChange;
49939
49997
  var mergedI18n = React$1.useMemo(function () {
49940
49998
  return _objectSpread$1F(_objectSpread$1F({}, defaultProps$1S.i18n), i18n);
49941
49999
  }, [i18n]);
@@ -49978,7 +50036,8 @@
49978
50036
  loadingMoreIds: loadingMoreIds,
49979
50037
  selectedItemRef: ref,
49980
50038
  i18n: mergedI18n,
49981
- lockedIds: lockedIds
50039
+ lockedIds: lockedIds,
50040
+ onExpandedChange: onExpandedChange
49982
50041
  }, overrides === null || overrides === void 0 ? void 0 : (_overrides$content2 = overrides.content) === null || _overrides$content2 === void 0 ? void 0 : _overrides$content2.props)), pagination && !isLoading ? /*#__PURE__*/React__default['default'].createElement("div", {
49983
50042
  className: "".concat(iotPrefix$1z, "--list--page")
49984
50043
  }, /*#__PURE__*/React__default['default'].createElement(SimplePagination, _extends_1$1({}, pagination, {
@@ -50430,6 +50489,17 @@
50430
50489
  },
50431
50490
  "required": false,
50432
50491
  "description": "call back function for when load more row is clicked (rowId) => {}"
50492
+ },
50493
+ "onExpandedChange": {
50494
+ "defaultValue": {
50495
+ "value": "null",
50496
+ "computed": false
50497
+ },
50498
+ "type": {
50499
+ "name": "func"
50500
+ },
50501
+ "required": false,
50502
+ "description": "called after the row has expanded or collapsed and is passed the array of expanded ids"
50433
50503
  }
50434
50504
  }
50435
50505
  };
@@ -60287,14 +60357,16 @@
60287
60357
  }, [expandedIdsProp]);
60288
60358
  /**
60289
60359
  * effect to trigger calling the onExpandedChange callback. Ignore it on the initial render
60290
- * when previousExpandedIds is undefined, but fire it on every change afterward
60360
+ * when previousExpandedIds is undefined, but fire it on every change afterward when using a
60361
+ * virtualList. The regular list triggers the onExpandedChange callback in the handleAfterExpand
60362
+ * function below.
60291
60363
  */
60292
60364
 
60293
60365
  React$1.useEffect(function () {
60294
- if (previousExpandedIds !== undefined && !isEqual$2(previousExpandedIds, expandedIds)) {
60366
+ if (previousExpandedIds !== undefined && !isEqual$2(previousExpandedIds, expandedIds) && isVirtualList) {
60295
60367
  onExpandedChange(expandedIds);
60296
60368
  }
60297
- }, [expandedIds, onExpandedChange, previousExpandedIds]);
60369
+ }, [expandedIds, isVirtualList, onExpandedChange, previousExpandedIds]);
60298
60370
  /**
60299
60371
  * Effect to handle indeterminate state for parent checkboxes. If we're in an editMode and
60300
60372
  * the selected ids changes, fire this effect to determine the currently indeterminate ids
@@ -60548,7 +60620,8 @@
60548
60620
  onItemMoved: handleDrag,
60549
60621
  className: className,
60550
60622
  emptyState: emptyState,
60551
- emptySearchState: emptySearchState
60623
+ emptySearchState: emptySearchState,
60624
+ onExpandedChange: onExpandedChange
60552
60625
  }));
60553
60626
  };
60554
60627
 
@@ -109047,15 +109120,24 @@
109047
109120
  };
109048
109121
 
109049
109122
  var useHasTextOverflow = function useHasTextOverflow(elementRef) {
109123
+ var _elementRef$current5, _elementRef$current6, _elementRef$current7, _elementRef$current8;
109124
+
109125
+ var text = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : '';
109126
+
109050
109127
  var _useState = React$1.useState(false),
109051
109128
  _useState2 = slicedToArray$1(_useState, 2),
109052
109129
  isOverflowed = _useState2[0],
109053
109130
  setIsOverflowed = _useState2[1];
109054
109131
 
109055
109132
  React$1.useEffect(function () {
109056
- var overFlowing = elementRef.current && (elementRef.current.scrollHeight > elementRef.current.clientHeight || elementRef.current.scrollWidth > elementRef.current.clientWidth);
109133
+ var _elementRef$current, _elementRef$current2, _elementRef$current3, _elementRef$current4;
109134
+
109135
+ var overFlowing = elementRef.current && ((elementRef === null || elementRef === void 0 ? void 0 : (_elementRef$current = elementRef.current) === null || _elementRef$current === void 0 ? void 0 : _elementRef$current.scrollHeight) > (elementRef === null || elementRef === void 0 ? void 0 : (_elementRef$current2 = elementRef.current) === null || _elementRef$current2 === void 0 ? void 0 : _elementRef$current2.clientHeight) || (elementRef === null || elementRef === void 0 ? void 0 : (_elementRef$current3 = elementRef.current) === null || _elementRef$current3 === void 0 ? void 0 : _elementRef$current3.scrollWidth) > (elementRef === null || elementRef === void 0 ? void 0 : (_elementRef$current4 = elementRef.current) === null || _elementRef$current4 === void 0 ? void 0 : _elementRef$current4.clientWidth));
109057
109136
  setIsOverflowed(overFlowing);
109058
- }, [elementRef]);
109137
+ /* disabling to not put the ref in dep array */
109138
+
109139
+ /* eslint-disable react-hooks/exhaustive-deps */
109140
+ }, [elementRef === null || elementRef === void 0 ? void 0 : (_elementRef$current5 = elementRef.current) === null || _elementRef$current5 === void 0 ? void 0 : _elementRef$current5.clientHeight, elementRef === null || elementRef === void 0 ? void 0 : (_elementRef$current6 = elementRef.current) === null || _elementRef$current6 === void 0 ? void 0 : _elementRef$current6.clientWidth, elementRef === null || elementRef === void 0 ? void 0 : (_elementRef$current7 = elementRef.current) === null || _elementRef$current7 === void 0 ? void 0 : _elementRef$current7.scrollHeight, elementRef === null || elementRef === void 0 ? void 0 : (_elementRef$current8 = elementRef.current) === null || _elementRef$current8 === void 0 ? void 0 : _elementRef$current8.scrollWidth, text]);
109059
109141
  return isOverflowed;
109060
109142
  };
109061
109143
 
@@ -110183,8 +110265,8 @@
110183
110265
 
110184
110266
  var titleRef = React$1.useRef();
110185
110267
  var subTitleRef = React$1.useRef();
110186
- var hasTitleTooltip = useHasTextOverflow(titleRef);
110187
- var hasSubTitleTooltip = useHasTextOverflow(subTitleRef);
110268
+ var hasTitleTooltip = useHasTextOverflow(titleRef, title);
110269
+ var hasSubTitleTooltip = useHasTextOverflow(subTitleRef, subtitle);
110188
110270
  var visibilityRef = React$1.useRef(null);
110189
110271
 
110190
110272
  var _useVisibilityObserve = useVisibilityObserver(visibilityRef, {
@@ -110247,6 +110329,7 @@
110247
110329
  triggerText: title
110248
110330
  }, title) : /*#__PURE__*/React__default['default'].createElement("div", {
110249
110331
  ref: titleRef,
110332
+ "data-testid": "".concat(testId, "-title-notip"),
110250
110333
  className: classnames$1("".concat(iotPrefix$1e, "--card--title--text"), defineProperty$c({}, "".concat(iotPrefix$1e, "--card--title--text--wrapped"), hasTitleWrap && !subtitle))
110251
110334
  }, title), tooltip && /*#__PURE__*/React__default['default'].createElement(carbonComponentsReact.Tooltip, {
110252
110335
  "data-testid": "".concat(testID || testId, "-tooltip"),