@deque/cauldron-react 7.1.0 → 7.2.0-canary.f495a82b

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 (111) hide show
  1. package/lib/add-user.js +1 -1
  2. package/lib/arrow-circle.js +1 -1
  3. package/lib/arrow.js +1 -1
  4. package/lib/arrows-alt.js +1 -1
  5. package/lib/bolt.js +1 -1
  6. package/lib/broken-image.js +1 -1
  7. package/lib/caution.js +1 -1
  8. package/lib/check-circle.js +1 -1
  9. package/lib/check-shield.js +1 -1
  10. package/lib/check-solid.js +1 -1
  11. package/lib/check.js +1 -1
  12. package/lib/checkbox-checked.js +1 -1
  13. package/lib/checkbox-unchecked.js +1 -1
  14. package/lib/chevron-double.js +1 -1
  15. package/lib/chevron.js +1 -1
  16. package/lib/clipboard.js +1 -1
  17. package/lib/clock.js +1 -1
  18. package/lib/close.js +1 -1
  19. package/lib/code.js +1 -1
  20. package/lib/components/Accordion/Accordion.d.ts +1 -1
  21. package/lib/components/ActionList/ActionList.d.ts +1 -1
  22. package/lib/components/ActionMenu/ActionMenu.d.ts +14 -8
  23. package/lib/components/AnchoredOverlay/index.d.ts +2 -2
  24. package/lib/components/ClickOutsideListener/index.d.ts +1 -1
  25. package/lib/components/Combobox/Combobox.d.ts +1 -1
  26. package/lib/components/Dialog/DialogContext.d.ts +1 -1
  27. package/lib/components/Dialog/index.d.ts +1 -1
  28. package/lib/components/Drawer/index.d.ts +1 -1
  29. package/lib/components/ExpandCollapsePanel/ExpandCollapsePanel.d.ts +1 -1
  30. package/lib/components/Icon/types.d.ts +1 -1
  31. package/lib/components/Listbox/Listbox.d.ts +7 -2
  32. package/lib/components/MenuBar/index.d.ts +1 -0
  33. package/lib/components/MenuItem/index.d.ts +1 -6
  34. package/lib/components/Popover/index.d.ts +2 -2
  35. package/lib/components/Table/TableContext.d.ts +1 -1
  36. package/lib/components/Tabs/Tab.d.ts +1 -1
  37. package/lib/components/Toast/index.d.ts +4 -4
  38. package/lib/components/Tooltip/index.d.ts +2 -2
  39. package/lib/components/TreeView/helpers.d.ts +33 -0
  40. package/lib/components/TreeView/index.d.ts +6 -0
  41. package/lib/components/TreeView/types.d.ts +3 -0
  42. package/lib/copy.js +1 -1
  43. package/lib/download.js +1 -1
  44. package/lib/dropper.js +1 -1
  45. package/lib/exchange.js +1 -1
  46. package/lib/export-solid.js +1 -1
  47. package/lib/external-link.js +1 -1
  48. package/lib/eye.js +1 -1
  49. package/lib/filter.js +1 -1
  50. package/lib/flag.js +1 -1
  51. package/lib/gears.js +1 -1
  52. package/lib/github.js +1 -1
  53. package/lib/grid.js +1 -1
  54. package/lib/hamburger-menu.js +1 -1
  55. package/lib/hashtag.js +1 -1
  56. package/lib/highlight.js +1 -1
  57. package/lib/images.js +1 -1
  58. package/lib/index.js +276 -116
  59. package/lib/info-circle-alt.js +1 -1
  60. package/lib/info-circle.js +1 -1
  61. package/lib/info-square.js +1 -1
  62. package/lib/kabob.js +1 -1
  63. package/lib/link.js +1 -1
  64. package/lib/linkedin.js +1 -1
  65. package/lib/list.js +1 -1
  66. package/lib/lock.js +1 -1
  67. package/lib/magnifying-glass.js +1 -1
  68. package/lib/menu.js +1 -1
  69. package/lib/minus.js +1 -1
  70. package/lib/new-releases.js +1 -1
  71. package/lib/new.js +1 -1
  72. package/lib/no.js +1 -1
  73. package/lib/pause.js +1 -1
  74. package/lib/pencil.js +1 -1
  75. package/lib/person-running.js +1 -1
  76. package/lib/play.js +1 -1
  77. package/lib/plus.js +1 -1
  78. package/lib/question-circle-alt.js +1 -1
  79. package/lib/question-circle.js +1 -1
  80. package/lib/radio-checked.js +1 -1
  81. package/lib/radio-unchecked.js +1 -1
  82. package/lib/recycle-square.js +1 -1
  83. package/lib/recycle.js +1 -1
  84. package/lib/resend.js +1 -1
  85. package/lib/robot.js +1 -1
  86. package/lib/run-again.js +1 -1
  87. package/lib/save.js +1 -1
  88. package/lib/share-nodes.js +1 -1
  89. package/lib/share.js +1 -1
  90. package/lib/sort-triangle.js +1 -1
  91. package/lib/sort.js +1 -1
  92. package/lib/star-outline.js +36 -0
  93. package/lib/star.js +4 -7
  94. package/lib/step-back.js +1 -1
  95. package/lib/step-forward.js +1 -1
  96. package/lib/sun.js +1 -1
  97. package/lib/table-sort-ascending.js +1 -1
  98. package/lib/table-sort-descending.js +1 -1
  99. package/lib/tag.js +1 -1
  100. package/lib/target.js +1 -1
  101. package/lib/trash.js +1 -1
  102. package/lib/triangle.js +1 -1
  103. package/lib/twitter.js +1 -1
  104. package/lib/types.d.ts +1 -1
  105. package/lib/upload.js +1 -1
  106. package/lib/utils/getChildRef.d.ts +2 -0
  107. package/lib/utils/polymorphicComponent.d.ts +1 -1
  108. package/lib/utils/useFocusTrap.d.ts +1 -1
  109. package/lib/utils/useMnemonics.d.ts +2 -2
  110. package/lib/utils/useSharedRef.d.ts +3 -3
  111. package/package.json +35 -29
package/lib/index.js CHANGED
@@ -185,6 +185,7 @@ var iconTypes = [
185
185
  'share',
186
186
  'sort-triangle',
187
187
  'sort',
188
+ 'star-outline',
188
189
  'star',
189
190
  'step-back',
190
191
  'step-forward',
@@ -273,6 +274,7 @@ function __variableDynamicImportRuntime0__(path) {
273
274
  case './icons/share.svg': return Promise.resolve().then(function () { return require('./share.js'); });
274
275
  case './icons/sort-triangle.svg': return Promise.resolve().then(function () { return require('./sort-triangle.js'); });
275
276
  case './icons/sort.svg': return Promise.resolve().then(function () { return require('./sort.js'); });
277
+ case './icons/star-outline.svg': return Promise.resolve().then(function () { return require('./star-outline.js'); });
276
278
  case './icons/star.svg': return Promise.resolve().then(function () { return require('./star.js'); });
277
279
  case './icons/step-back.svg': return Promise.resolve().then(function () { return require('./step-back.js'); });
278
280
  case './icons/step-forward.svg': return Promise.resolve().then(function () { return require('./step-forward.js'); });
@@ -495,24 +497,25 @@ var Accordion = function (_a) {
495
497
  var childrenArray = React__default["default"].Children.toArray(children);
496
498
  var trigger = childrenArray.find(function (child) {
497
499
  return typeof child === 'string' ||
498
- child.type === AccordionTrigger;
500
+ (React__default["default"].isValidElement(child) && child.type === AccordionTrigger);
499
501
  });
500
502
  var panelElement = childrenArray.find(function (child) {
501
503
  return typeof child === 'string' ||
502
- child.type === AccordionContent;
504
+ (React__default["default"].isValidElement(child) && child.type === AccordionContent);
503
505
  });
504
- var isValid = !!(React__default["default"].isValidElement(trigger) && React__default["default"].isValidElement(panelElement));
505
- if (!isValid) {
506
+ if (!React__default["default"].isValidElement(trigger) ||
507
+ !React__default["default"].isValidElement(panelElement)) {
506
508
  console.warn('Must provide <AccordionTrigger /> and <AccordionContent /> element(s). You provided:', {
507
509
  trigger: trigger,
508
510
  panelElement: panelElement,
509
- isValid: isValid
511
+ isValid: false
510
512
  });
511
513
  return null;
512
514
  }
515
+ var panelProps = panelElement.props;
513
516
  return (React__default["default"].createElement("div", tslib.__assign({ className: "Accordion" }, props),
514
- React__default["default"].createElement(ExpandCollapsePanel, tslib.__assign({ id: panelElement.props.id || "".concat(elementId, "-panel"), open: open, onToggle: onToggle, animationTiming: animationTiming }, panelElement.props),
515
- React__default["default"].createElement(PanelTrigger$1, tslib.__assign({ iconCollapsed: "triangle-right", iconExpanded: "triangle-down", className: classNames__default["default"]('Accordion__trigger', trigger.props.className), "aria-controls": panelElement.props.id || "".concat(elementId, "-panel"), heading: trigger.props.heading }, trigger.props), trigger),
517
+ React__default["default"].createElement(ExpandCollapsePanel, tslib.__assign({ id: panelProps.id || "".concat(elementId, "-panel"), open: open, onToggle: onToggle, animationTiming: animationTiming }, panelProps),
518
+ React__default["default"].createElement(PanelTrigger$1, tslib.__assign({ iconCollapsed: "triangle-right", iconExpanded: "triangle-down", className: classNames__default["default"]('Accordion__trigger', trigger.props.className), "aria-controls": panelProps.id || "".concat(elementId, "-panel"), heading: trigger.props.heading }, trigger.props), trigger),
516
519
  panelElement)));
517
520
  };
518
521
  Accordion.displayName = 'Accordion';
@@ -578,7 +581,9 @@ var Scrim = /** @class */ (function (_super) {
578
581
  if (destroy) {
579
582
  return null;
580
583
  }
581
- return (React__default["default"].createElement("div", { ref: function (el) { return (_this.el = el); }, className: "Scrim ".concat(animationClass) }));
584
+ return (React__default["default"].createElement("div", { ref: function (el) {
585
+ _this.el = el;
586
+ }, className: "Scrim ".concat(animationClass) }));
582
587
  };
583
588
  return Scrim;
584
589
  }(React__default["default"].Component));
@@ -620,16 +625,16 @@ var MenuItem = /** @class */ (function (_super) {
620
625
  if (autoClickLink) {
621
626
  clickLink(e.target, this.item);
622
627
  }
623
- onClick(e);
628
+ onClick === null || onClick === void 0 ? void 0 : onClick(e);
624
629
  };
625
630
  MenuItem.prototype.onKeyDown = function (e) {
626
- var _a;
631
+ var _a, _b, _c;
627
632
  var key = keyname__default["default"](e.which);
628
633
  if (key === 'enter' || key === 'space') {
629
634
  e.preventDefault();
630
635
  (_a = this.item) === null || _a === void 0 ? void 0 : _a.click();
631
636
  }
632
- this.props.onKeyDown(e);
637
+ (_c = (_b = this.props).onKeyDown) === null || _c === void 0 ? void 0 : _c.call(_b, e);
633
638
  };
634
639
  MenuItem.prototype.render = function () {
635
640
  var _this = this;
@@ -642,12 +647,6 @@ var MenuItem = /** @class */ (function (_super) {
642
647
  };
643
648
  MenuItem.displayName = 'MenuItem';
644
649
  MenuItem.defaultProps = {
645
- // eslint-disable-next-line @typescript-eslint/no-empty-function
646
- menuItemRef: function () { },
647
- // eslint-disable-next-line @typescript-eslint/no-empty-function
648
- onClick: function () { },
649
- // eslint-disable-next-line @typescript-eslint/no-empty-function
650
- onKeyDown: function () { },
651
650
  autoClickLink: true
652
651
  };
653
652
  return MenuItem;
@@ -672,6 +671,7 @@ var TopBar$1 = /** @class */ (function (_super) {
672
671
  tslib.__extends(TopBar, _super);
673
672
  function TopBar(props) {
674
673
  var _this = _super.call(this, props) || this;
674
+ _this.menuBarRef = React__default["default"].createRef();
675
675
  _this.onResize = function () {
676
676
  var wide = isWide();
677
677
  if (wide === _this.state.wide) {
@@ -720,10 +720,10 @@ var TopBar$1 = /** @class */ (function (_super) {
720
720
  };
721
721
  TopBar.prototype.onKeyDown = function (e) {
722
722
  var key = keyname__default["default"](e.which);
723
- // This is a temporary workaround until have an opportunity to refactor or replace menubar
724
- // see: https://github.com/dequelabs/cauldron/issues/1934
725
- // eslint-disable-next-line react/no-find-dom-node
726
- var menuBarElement = reactDom.findDOMNode(this);
723
+ var menuBarElement = this.menuBarRef.current;
724
+ if (!menuBarElement) {
725
+ return;
726
+ }
727
727
  var menuItems = Array.from(menuBarElement.children);
728
728
  // account for hidden side bar trigger (hamburger)
729
729
  if (this.state.wide && this.props.hasTrigger) {
@@ -750,7 +750,7 @@ var TopBar$1 = /** @class */ (function (_super) {
750
750
  // disabling no-unused-vars to prevent thin/hasTrigger from being passed through to div
751
751
  // eslint-disable-next-line @typescript-eslint/no-unused-vars
752
752
  var _a = this.props, children = _a.children, className = _a.className; _a.thin; _a.hasTrigger; tslib.__rest(_a, ["children", "className", "thin", "hasTrigger"]);
753
- return (React__default["default"].createElement("ul", { role: "menubar", onKeyDown: this.onKeyDown, className: className }, React.Children.map(children, this.renderChild)));
753
+ return (React__default["default"].createElement("ul", { role: "menubar", onKeyDown: this.onKeyDown, className: className, ref: this.menuBarRef }, React.Children.map(children, this.renderChild)));
754
754
  };
755
755
  TopBar.defaultProps = {
756
756
  thin: false,
@@ -806,9 +806,16 @@ function resolveElement(elementOrRef) {
806
806
  return null;
807
807
  }
808
808
 
809
+ function getChildRef(child, version) {
810
+ if (version === void 0) { version = React__default["default"].version; }
811
+ return parseInt(version, 10) >= 19
812
+ ? child.props.ref
813
+ : child.ref;
814
+ }
815
+
809
816
  function ClickOutsideListener(_a, ref) {
810
817
  var children = _a.children, _b = _a.mouseEvent, mouseEvent = _b === void 0 ? 'click' : _b, _c = _a.touchEvent, touchEvent = _c === void 0 ? 'touchend' : _c, target = _a.target, _d = _a.onClickOutside, onClickOutside = _d === void 0 ? function () { return null; } : _d;
811
- var childElementRef = React.useRef();
818
+ var childElementRef = React.useRef(null);
812
819
  var handleEvent = function (event) {
813
820
  if (event.defaultPrevented) {
814
821
  return;
@@ -831,9 +838,8 @@ function ClickOutsideListener(_a, ref) {
831
838
  childElementRef.current = node;
832
839
  // Ref for this component should pass-through to the child node
833
840
  setRef(ref, node);
834
- // If child has its own ref, we want to update
835
- // its ref with the newly cloned node
836
- var childRef = children.ref;
841
+ // Forward the child's own ref. In React 19 ref lives in props; in 16–18 it's element.ref.
842
+ var childRef = getChildRef(children);
837
843
  setRef(childRef, node);
838
844
  };
839
845
  React.useEffect(function () {
@@ -1342,7 +1348,7 @@ var AriaIsolate = /** @class */ (function () {
1342
1348
 
1343
1349
  /**
1344
1350
  * When a component needs to track an internal ref on a component that has a
1345
- * forwarded ref, useSharedRef will return a MutableRefObject<T> that will
1351
+ * forwarded ref, useSharedRef will return a RefObject<T | null> that will
1346
1352
  * correctly invoke the parent ref as well providing an internal ref.
1347
1353
  *
1348
1354
  * @example
@@ -1355,7 +1361,7 @@ var AriaIsolate = /** @class */ (function () {
1355
1361
  * })
1356
1362
  */
1357
1363
  function useSharedRef(ref) {
1358
- var internalRef = React.useRef();
1364
+ var internalRef = React.useRef(null);
1359
1365
  React.useEffect(function () {
1360
1366
  setRef(ref, internalRef.current);
1361
1367
  return function () { return setRef(ref, null); };
@@ -1488,7 +1494,7 @@ function useFocusTrap(target, options) {
1488
1494
  if (options === void 0) { options = {}; }
1489
1495
  var _a = options.disabled, disabled = _a === void 0 ? false : _a, _b = options.returnFocus, returnFocus = _b === void 0 ? true : _b, initialFocusElementOrRef = options.initialFocusElement, returnFocusElement = options.returnFocusElement;
1490
1496
  var focusTrap = React.useRef(null);
1491
- var returnFocusElementRef = React.useRef();
1497
+ var returnFocusElementRef = React.useRef(null);
1492
1498
  function restoreFocusToReturnFocusElement() {
1493
1499
  var _a;
1494
1500
  var resolvedReturnFocusElement = resolveElement(returnFocusElement);
@@ -1538,7 +1544,7 @@ var Dialog = React.forwardRef(function (_a, ref) {
1538
1544
  var dialogRef = useSharedRef(dialogRefProp || ref);
1539
1545
  var _g = tslib.__read(nextId.useId(1, 'dialog-title-'), 1), headingId = _g[0];
1540
1546
  var headingRef = React.useRef(null);
1541
- var isolatorRef = React.useRef();
1547
+ var isolatorRef = React.useRef(null);
1542
1548
  var headingLevel = typeof heading === 'object' && 'level' in heading && heading.level
1543
1549
  ? heading.level
1544
1550
  : 2;
@@ -2133,7 +2139,7 @@ var looksLikeLink = function (props) {
2133
2139
  };
2134
2140
  var IconButton = React.forwardRef(function (_a, ref) {
2135
2141
  var _b = _a.as, Component = _b === void 0 ? 'button' : _b, icon = _a.icon, label = _a.label, _c = _a.tooltipProps, tooltipPropsProp = _c === void 0 ? {} : _c, className = _a.className, _d = _a.variant, variant = _d === void 0 ? 'secondary' : _d, disabled = _a.disabled, _e = _a.tabIndex, tabIndex = _e === void 0 ? 0 : _e, large = _a.large, other = tslib.__rest(_a, ["as", "icon", "label", "tooltipProps", "className", "variant", "disabled", "tabIndex", "large"]);
2136
- var internalRef = React.useRef();
2142
+ var internalRef = React.useRef(null);
2137
2143
  React.useImperativeHandle(ref, function () { return internalRef.current; });
2138
2144
  // Configure additional properties based on the type of the Component
2139
2145
  // for accessibility
@@ -2208,7 +2214,7 @@ var typeMap = {
2208
2214
  };
2209
2215
  var tabIndexHandler = function (reset, toast) {
2210
2216
  if (reset) {
2211
- // restore tab indicies that we clobbered
2217
+ // restore tab indices that we clobbered
2212
2218
  return queryAll('[data-cached-tabindex]').forEach(function (el) {
2213
2219
  el.tabIndex = Number(el.getAttribute('data-cached-tabindex'));
2214
2220
  });
@@ -2243,14 +2249,22 @@ var useDidUpdate = function (effect, dependencies) {
2243
2249
  /**
2244
2250
  * The cauldron toast notification component
2245
2251
  */
2246
- var Toast = function (_a) {
2252
+ var Toast = React.forwardRef(function (_a, ref) {
2247
2253
  var type = _a.type, children = _a.children, _b = _a.onDismiss, onDismiss = _b === void 0 ? function () {
2248
2254
  // noop
2249
2255
  } : _b, _c = _a.dismissText, dismissText = _c === void 0 ? 'Dismiss' : _c, toastRef = _a.toastRef, _d = _a.focus, focus = _d === void 0 ? true : _d, _e = _a.show, show = _e === void 0 ? false : _e, _f = _a.dismissible, dismissible = _f === void 0 ? true : _f, className = _a.className, otherProps = tslib.__rest(_a, ["type", "children", "onDismiss", "dismissText", "toastRef", "focus", "show", "dismissible", "className"]);
2250
- var elRef = useSharedRef(toastRef !== null && toastRef !== void 0 ? toastRef : null);
2256
+ var elRef = useSharedRef(ref);
2251
2257
  var isolatorRef = React.useRef(null);
2252
2258
  var timeoutsRef = React.useRef(new Set());
2253
2259
  var _g = tslib.__read(React.useState(show ? 'FadeIn--flex' : 'is--hidden'), 2), animationClass = _g[0], setAnimationClass = _g[1];
2260
+ // Backwards-compat: propagate to the deprecated toastRef prop as well
2261
+ React.useEffect(function () {
2262
+ var _a;
2263
+ if (!toastRef)
2264
+ return;
2265
+ setRef(toastRef, (_a = elRef.current) !== null && _a !== void 0 ? _a : null);
2266
+ return function () { return setRef(toastRef, null); };
2267
+ }, [toastRef]);
2254
2268
  // Timeout because CSS display: none/block and opacity:
2255
2269
  // 0/1 properties cannot be toggled in the same tick
2256
2270
  // see: https://codepen.io/isnerms/pen/eyQaLP
@@ -2324,7 +2338,7 @@ var Toast = function (_a) {
2324
2338
  type !== 'action-needed' && dismissible && (React__default["default"].createElement("button", { type: "button", className: "Toast__dismiss", "aria-label": dismissText, onClick: dismissToast },
2325
2339
  React__default["default"].createElement(Icon, { type: "close" })))),
2326
2340
  scrim));
2327
- };
2341
+ });
2328
2342
  Toast.displayName = 'Toast';
2329
2343
 
2330
2344
  var Link = React.forwardRef(function (_a, ref) {
@@ -2687,7 +2701,7 @@ Checkbox.displayName = 'Checkbox';
2687
2701
  */
2688
2702
  function TooltipTabstop(_a) {
2689
2703
  var children = _a.children, className = _a.className, tooltip = _a.tooltip, variant = _a.variant, association = _a.association, show = _a.show, placement = _a.placement, portal = _a.portal, hideElementOnHidden = _a.hideElementOnHidden, buttonProps = tslib.__rest(_a, ["children", "className", "tooltip", "variant", "association", "show", "placement", "portal", "hideElementOnHidden"]);
2690
- var buttonRef = React.useRef();
2704
+ var buttonRef = React.useRef(null);
2691
2705
  return (React__default["default"].createElement(React__default["default"].Fragment, null,
2692
2706
  React__default["default"].createElement("button", tslib.__assign({ type: "button", ref: buttonRef, "aria-disabled": "true", className: classNames__default["default"]('TooltipTabstop', className) }, buttonProps), children),
2693
2707
  React__default["default"].createElement(Tooltip, { target: buttonRef, variant: variant, association: association, show: show, placement: placement, portal: portal, hideElementOnHidden: hideElementOnHidden }, tooltip)));
@@ -3531,7 +3545,7 @@ var TwoColumnPanel = React.forwardRef(function (_a, ref) {
3531
3545
  var closeButtonRef = React.useRef(null);
3532
3546
  var columnLeftRef = React.useRef(null);
3533
3547
  var columnRightRef = React.useRef(null);
3534
- var columnLeft = React__default["default"].Children.toArray(children).find(function (child) { return child.type === ColumnLeft; });
3548
+ var columnLeft = React__default["default"].Children.toArray(children).find(function (child) { return React__default["default"].isValidElement(child) && child.type === ColumnLeft; });
3535
3549
  var togglePanel = function () {
3536
3550
  var prefersReducedMotion = 'matchMedia' in window &&
3537
3551
  typeof matchMedia === 'function' &&
@@ -3564,16 +3578,17 @@ var TwoColumnPanel = React.forwardRef(function (_a, ref) {
3564
3578
  var ColumnLeftComponent;
3565
3579
  var columnLeftId;
3566
3580
  if (React.isValidElement(columnLeft)) {
3567
- var ref_1 = columnLeft.props.ref || columnLeftRef;
3581
+ var columnLeftProps = columnLeft.props;
3582
+ var ref_1 = columnLeftProps.ref || columnLeftRef;
3568
3583
  var id = (columnLeftId =
3569
- columnLeft.props.id || nextId.useId(undefined, 'sidebar-')[0]);
3584
+ columnLeftProps.id || nextId.useId(undefined, 'sidebar-')[0]);
3570
3585
  var CloseButton = (React__default["default"].createElement("div", { className: "TwoColumnPanel__Close" },
3571
3586
  React__default["default"].createElement("button", { type: "button", onClick: togglePanel, ref: closeButtonRef, "aria-label": hideCollapsedPanelLabel },
3572
3587
  React__default["default"].createElement(Icon, { type: "close" })),
3573
3588
  React__default["default"].createElement(Tooltip, { target: closeButtonRef, association: "aria-labelledby", hideElementOnHidden: true }, hideCollapsedPanelLabel)));
3574
3589
  var children_1 = tslib.__spreadArray([
3575
3590
  CloseButton
3576
- ], tslib.__read(React__default["default"].Children.toArray(columnLeft.props.children)), false);
3591
+ ], tslib.__read(React__default["default"].Children.toArray(columnLeftProps.children)), false);
3577
3592
  ColumnLeftComponent = React.cloneElement(columnLeft, { id: id, ref: ref_1, tabIndex: -1 }, children_1.map(function (child, index) {
3578
3593
  return React.cloneElement(child, {
3579
3594
  key: child.key
@@ -3582,17 +3597,18 @@ var TwoColumnPanel = React.forwardRef(function (_a, ref) {
3582
3597
  });
3583
3598
  }));
3584
3599
  }
3585
- var columnRight = React__default["default"].Children.toArray(children).find(function (child) { return child.type === ColumnRight; });
3600
+ var columnRight = React__default["default"].Children.toArray(children).find(function (child) { return React__default["default"].isValidElement(child) && child.type === ColumnRight; });
3586
3601
  var ColumnRightComponent;
3587
3602
  if (React.isValidElement(columnRight)) {
3588
- var ref_2 = columnRight.props.ref || columnRightRef;
3603
+ var columnRightProps = columnRight.props;
3604
+ var ref_2 = columnRightProps.ref || columnRightRef;
3589
3605
  var ToggleButton = (React__default["default"].createElement("div", { className: "TwoColumnPanel__ButtonToggle" },
3590
3606
  React__default["default"].createElement("button", { type: "button", onClick: togglePanel, ref: toggleButtonRef, "aria-label": !isCollapsed ? hideCollapsedPanelLabel : showCollapsedPanelLabel, "aria-expanded": !isCollapsed, "aria-controls": columnLeftId },
3591
3607
  React__default["default"].createElement(Icon, { type: !isCollapsed ? 'chevron-double-left' : 'chevron-double-right' })),
3592
3608
  React__default["default"].createElement(Tooltip, { target: toggleButtonRef, association: "aria-labelledby", hideElementOnHidden: true }, !isCollapsed ? hideCollapsedPanelLabel : showCollapsedPanelLabel)));
3593
3609
  var children_2 = tslib.__spreadArray([
3594
3610
  ToggleButton
3595
- ], tslib.__read(React__default["default"].Children.toArray(columnRight.props.children)), false);
3611
+ ], tslib.__read(React__default["default"].Children.toArray(columnRightProps.children)), false);
3596
3612
  ColumnRightComponent = React.cloneElement(columnRight, { ref: ref_2, tabIndex: -1 }, children_2.map(function (child, index) {
3597
3613
  return React.cloneElement(child, {
3598
3614
  key: child.key
@@ -3614,7 +3630,7 @@ var TwoColumnPanel = React.forwardRef(function (_a, ref) {
3614
3630
  (_a = columnLeftRef.current) === null || _a === void 0 ? void 0 : _a.removeEventListener('transitionend', handleTransitionEnd);
3615
3631
  };
3616
3632
  }, [columnLeftRef.current, isCollapsed]);
3617
- // When the collapsable panel starts to overlay content, it needs to become a focus trap and collapsed by default
3633
+ // When the collapsible panel starts to overlay content, it needs to become a focus trap and collapsed by default
3618
3634
  React.useLayoutEffect(function () {
3619
3635
  var mediaQueryList = matchMedia(collapsedMediaQuery);
3620
3636
  var handleMatch = function (matches) {
@@ -3778,7 +3794,8 @@ var Listbox = React.forwardRef(function (_a, ref) {
3778
3794
  }
3779
3795
  }, [activeOption]);
3780
3796
  React.useEffect(function () {
3781
- if (isActiveControlled && controlledActiveOption !== activeOption) {
3797
+ if (isActiveControlled &&
3798
+ (controlledActiveOption === null || controlledActiveOption === void 0 ? void 0 : controlledActiveOption.element) !== (activeOption === null || activeOption === void 0 ? void 0 : activeOption.element)) {
3782
3799
  setActiveOption(controlledActiveOption || null);
3783
3800
  }
3784
3801
  }, [isActiveControlled, controlledActiveOption]);
@@ -3924,11 +3941,11 @@ function isElementPreceding(a, b) {
3924
3941
  }
3925
3942
  var ListboxOption = React.forwardRef(function (_a, ref) {
3926
3943
  var _b;
3927
- var _c;
3928
- var propId = _a.id, className = _a.className, _d = _a.as, Component = _d === void 0 ? 'li' : _d, children = _a.children, value = _a.value, disabled = _a.disabled, selectedProp = _a.selected, _e = _a.activeClass, activeClass = _e === void 0 ? 'ListboxOption--active' : _e, onClick = _a.onClick, props = tslib.__rest(_a, ["id", "className", "as", "children", "value", "disabled", "selected", "activeClass", "onClick"]);
3929
- var _f = useListboxContext(), active = _f.active, selected = _f.selected, setOptions = _f.setOptions, onSelect = _f.onSelect;
3944
+ var _c, _d;
3945
+ var propId = _a.id, className = _a.className, _e = _a.as, Component = _e === void 0 ? 'li' : _e, children = _a.children, value = _a.value, disabled = _a.disabled, selectedProp = _a.selected, _f = _a.activeClass, activeClass = _f === void 0 ? 'ListboxOption--active' : _f, onClick = _a.onClick, props = tslib.__rest(_a, ["id", "className", "as", "children", "value", "disabled", "selected", "activeClass", "onClick"]);
3946
+ var _g = useListboxContext(), active = _g.active, selected = _g.selected, setOptions = _g.setOptions, onSelect = _g.onSelect;
3930
3947
  var listboxOptionRef = useSharedRef(ref);
3931
- var _g = tslib.__read(propId ? [propId] : nextId.useId(1, 'listbox-option'), 1), id = _g[0];
3948
+ var _h = tslib.__read(propId ? [propId] : nextId.useId(1, 'listbox-option'), 1), id = _h[0];
3932
3949
  var isActive = (active === null || active === void 0 ? void 0 : active.element) === listboxOptionRef.current;
3933
3950
  var isSelected = typeof selectedProp === 'boolean'
3934
3951
  ? selectedProp
@@ -3936,15 +3953,15 @@ var ListboxOption = React.forwardRef(function (_a, ref) {
3936
3953
  !!selected.find(function (option) { return option.element === listboxOptionRef.current; });
3937
3954
  var optionValue = typeof value !== 'undefined'
3938
3955
  ? value
3939
- : (_c = listboxOptionRef.current) === null || _c === void 0 ? void 0 : _c.innerText;
3956
+ : ((_d = (_c = listboxOptionRef.current) === null || _c === void 0 ? void 0 : _c.textContent) !== null && _d !== void 0 ? _d : undefined);
3940
3957
  React.useEffect(function () {
3941
3958
  var element = listboxOptionRef.current;
3942
3959
  setOptions(function (options) {
3943
3960
  var e_1, _a;
3944
- var option = { element: element, value: optionValue };
3945
3961
  // istanbul ignore next
3946
3962
  if (!element)
3947
3963
  return options;
3964
+ var option = { element: element, value: optionValue };
3948
3965
  // Elements are frequently appended, so check to see if the newly rendered
3949
3966
  // element follows the last element first before any other checks
3950
3967
  if (!options.length ||
@@ -4131,7 +4148,7 @@ var ComboboxOption = React.forwardRef(function (_a, ref) {
4131
4148
  // istanbul ignore next
4132
4149
  React.useLayoutEffect(function () {
4133
4150
  var intersectionEntry = intersectionRef.current;
4134
- if (!intersectionEntry || !isActive) {
4151
+ if (!intersectionEntry || !isActive || !comboboxOptionRef.current) {
4135
4152
  return;
4136
4153
  }
4137
4154
  var rect = comboboxOptionRef.current.getBoundingClientRect();
@@ -4147,10 +4164,10 @@ var ComboboxOption = React.forwardRef(function (_a, ref) {
4147
4164
  }
4148
4165
  }, [isActive]);
4149
4166
  React.useEffect(function () {
4150
- var _a;
4167
+ var _a, _b;
4151
4168
  var comboboxValue = typeof propValue !== 'undefined'
4152
4169
  ? propValue
4153
- : (_a = comboboxOptionRef.current) === null || _a === void 0 ? void 0 : _a.innerText;
4170
+ : ((_b = (_a = comboboxOptionRef.current) === null || _a === void 0 ? void 0 : _a.textContent) !== null && _b !== void 0 ? _b : undefined);
4154
4171
  var value = typeof formValue === 'undefined' ? comboboxValue : formValue;
4155
4172
  setFormValues(function (prev) {
4156
4173
  var formValues = prev.filter(function (fv) { return fv !== value; });
@@ -4169,12 +4186,14 @@ var ComboboxOption = React.forwardRef(function (_a, ref) {
4169
4186
  });
4170
4187
  }, [selectedValues, formValue]);
4171
4188
  React.useEffect(function () {
4172
- var _a;
4189
+ var _a, _b;
4173
4190
  if (isMatching) {
4174
4191
  var comboboxValue_1 = typeof propValue !== 'undefined'
4175
4192
  ? propValue
4176
- : (_a = comboboxOptionRef.current) === null || _a === void 0 ? void 0 : _a.innerText;
4193
+ : ((_b = (_a = comboboxOptionRef.current) === null || _a === void 0 ? void 0 : _a.textContent) !== null && _b !== void 0 ? _b : undefined);
4177
4194
  setMatchingOptions(function (options) {
4195
+ if (!comboboxOptionRef.current)
4196
+ return options;
4178
4197
  return new Map(options.set(comboboxOptionRef.current, {
4179
4198
  value: comboboxValue_1,
4180
4199
  displayValue: children,
@@ -4314,6 +4333,17 @@ var Combobox = React.forwardRef(function (_a, ref) {
4314
4333
  return value === lastSelectedValue;
4315
4334
  }) || [], 2), element = _a[0], option = _a[1];
4316
4335
  if (autocomplete === 'manual') {
4336
+ // In multiselect, the listbox manages its own active option via
4337
+ // keyboard navigation. When the last-selected value no longer
4338
+ // matches any option (e.g. after deselecting the only selected
4339
+ // option), preserve the existing active descendant so the next
4340
+ // Enter keypress can re-toggle the highlighted option.
4341
+ if (multiselect &&
4342
+ !element &&
4343
+ activeDescendant &&
4344
+ matchingOptions.has(activeDescendant.element)) {
4345
+ return;
4346
+ }
4317
4347
  setActiveDescendant(!element ? null : tslib.__assign({ element: element }, option));
4318
4348
  }
4319
4349
  else if (autocomplete === 'automatic' &&
@@ -4493,6 +4523,7 @@ var Combobox = React.forwardRef(function (_a, ref) {
4493
4523
  });
4494
4524
  }, [disabled, selectedValues, onSelectionChange]);
4495
4525
  var handlePillKeyDown = React.useCallback(function (event) {
4526
+ var _a, _b;
4496
4527
  if (!PillKeys.includes(event.key)) {
4497
4528
  return;
4498
4529
  }
@@ -4510,7 +4541,7 @@ var Combobox = React.forwardRef(function (_a, ref) {
4510
4541
  handleRemovePill(pillsRef.current[focusedIndex], selectedValues[focusedIndex]);
4511
4542
  var nextIndex = focusedIndex + 1;
4512
4543
  if (nextIndex == pillsLength) {
4513
- inputRef.current.focus();
4544
+ (_a = inputRef.current) === null || _a === void 0 ? void 0 : _a.focus();
4514
4545
  }
4515
4546
  else {
4516
4547
  pillsRef.current[nextIndex].focus();
@@ -4519,7 +4550,7 @@ var Combobox = React.forwardRef(function (_a, ref) {
4519
4550
  else if (isArrowLeft || isArrowRight) {
4520
4551
  var nextIndex = Math.max(focusedIndex + (isArrowLeft ? -1 : 1), 0);
4521
4552
  if (isArrowRight && nextIndex === pillsLength) {
4522
- inputRef.current.focus();
4553
+ (_b = inputRef.current) === null || _b === void 0 ? void 0 : _b.focus();
4523
4554
  }
4524
4555
  else {
4525
4556
  pillsRef.current[nextIndex].focus();
@@ -4807,10 +4838,12 @@ var TextEllipsis = React__default["default"].forwardRef(function (_a, ref) {
4807
4838
  : overflowElement.clientWidth < overflowElement.scrollWidth);
4808
4839
  });
4809
4840
  };
4841
+ if (!sharedRef.current)
4842
+ return;
4810
4843
  var observer = new ResizeObserver(listener);
4811
4844
  observer.observe(sharedRef.current);
4812
4845
  return function () {
4813
- observer === null || observer === void 0 ? void 0 : observer.disconnect();
4846
+ observer.disconnect();
4814
4847
  };
4815
4848
  }, []);
4816
4849
  React.useEffect(function () {
@@ -4855,7 +4888,7 @@ var Drawer = React.forwardRef(function (_a, ref) {
4855
4888
  openRef.current = open;
4856
4889
  }, [open, setIsTransitioning]);
4857
4890
  React.useEffect(function () {
4858
- if (!isModal) {
4891
+ if (!isModal || !drawerRef.current) {
4859
4892
  return;
4860
4893
  }
4861
4894
  var isolator = new AriaIsolate(drawerRef.current);
@@ -5036,7 +5069,7 @@ function getActiveElement(root) {
5036
5069
  */
5037
5070
  function useMnemonics(_a) {
5038
5071
  var elementOrRef = _a.elementOrRef, matchingElementsSelector = _a.matchingElementsSelector, onMatch = _a.onMatch, _b = _a.enabled, enabled = _b === void 0 ? true : _b;
5039
- var containerRef = React.useRef();
5072
+ var containerRef = React.useRef(null);
5040
5073
  React.useEffect(function () {
5041
5074
  if (elementOrRef instanceof HTMLElement) {
5042
5075
  containerRef.current = elementOrRef;
@@ -5046,7 +5079,8 @@ function useMnemonics(_a) {
5046
5079
  }
5047
5080
  }, [elementOrRef]);
5048
5081
  React.useEffect(function () {
5049
- if (!enabled || !containerRef.current) {
5082
+ var listenerTarget = containerRef.current;
5083
+ if (!enabled || !listenerTarget) {
5050
5084
  return;
5051
5085
  }
5052
5086
  var keyboardHandler = function (event) {
@@ -5059,14 +5093,14 @@ function useMnemonics(_a) {
5059
5093
  if (event.key.length !== 1 || !/[a-z\d]/i.test(event.key)) {
5060
5094
  return;
5061
5095
  }
5062
- var container = containerRef.current;
5063
- if (!container) {
5096
+ var currentContainer = containerRef.current;
5097
+ if (!currentContainer) {
5064
5098
  return;
5065
5099
  }
5066
5100
  // Prevent default behavior and stop propagation for mnemonic keys
5067
5101
  event.preventDefault();
5068
5102
  event.stopPropagation();
5069
- var elements = Array.from(container.querySelectorAll(matchingElementsSelector !== null && matchingElementsSelector !== void 0 ? matchingElementsSelector : focusable__default["default"]));
5103
+ var elements = Array.from(currentContainer.querySelectorAll(matchingElementsSelector !== null && matchingElementsSelector !== void 0 ? matchingElementsSelector : focusable__default["default"]));
5070
5104
  var matchingElements = elements.filter(function (element) {
5071
5105
  return getAccessibleLabel(element).toLowerCase()[0] ===
5072
5106
  event.key.toLowerCase();
@@ -5074,7 +5108,7 @@ function useMnemonics(_a) {
5074
5108
  if (!matchingElements.length) {
5075
5109
  return;
5076
5110
  }
5077
- var currentActiveElement = getActiveElement(containerRef.current);
5111
+ var currentActiveElement = getActiveElement(currentContainer);
5078
5112
  var nextActiveElement = null;
5079
5113
  if (currentActiveElement) {
5080
5114
  nextActiveElement = matchingElements.find(function (element) {
@@ -5088,17 +5122,15 @@ function useMnemonics(_a) {
5088
5122
  onMatch(nextActiveElement !== null && nextActiveElement !== void 0 ? nextActiveElement : matchingElements[0]);
5089
5123
  }
5090
5124
  };
5091
- var container = containerRef.current;
5092
- container.addEventListener('keydown', keyboardHandler);
5093
- return function () { return container.removeEventListener('keydown', keyboardHandler); };
5125
+ listenerTarget.addEventListener('keydown', keyboardHandler);
5126
+ return function () { return listenerTarget.removeEventListener('keydown', keyboardHandler); };
5094
5127
  }, [enabled, containerRef, matchingElementsSelector, onMatch]);
5095
5128
  return containerRef;
5096
5129
  }
5097
5130
 
5098
5131
  var ActionList = React.forwardRef(function (_a, ref) {
5099
5132
  var _b = _a.selectionType, selectionType = _b === void 0 ? null : _b, onAction = _a.onAction, className = _a.className, children = _a.children, props = tslib.__rest(_a, ["selectionType", "onAction", "className", "children"]);
5100
- var actionListContext = useActionListContext();
5101
- var activeElement = React.useRef();
5133
+ var activeElement = React.useRef(null);
5102
5134
  var _c = tslib.__read(React.useState(), 2), activeOption = _c[0], setActiveOption = _c[1];
5103
5135
  var handleActiveChange = React.useCallback(function (value) {
5104
5136
  activeElement.current = value === null || value === void 0 ? void 0 : value.element;
@@ -5109,22 +5141,18 @@ var ActionList = React.forwardRef(function (_a, ref) {
5109
5141
  onAction(key, event);
5110
5142
  }
5111
5143
  }, [onAction]);
5144
+ var handleMnemonicMatch = React.useCallback(function (element) {
5145
+ setActiveOption(function (prev) {
5146
+ return (prev === null || prev === void 0 ? void 0 : prev.element) === element ? prev : { element: element };
5147
+ });
5148
+ }, []);
5112
5149
  var containerRef = useMnemonics({
5113
- onMatch: function (element) {
5114
- setActiveOption({
5115
- element: element
5116
- });
5117
- },
5150
+ onMatch: handleMnemonicMatch,
5118
5151
  matchingElementsSelector: props.role === 'menu'
5119
5152
  ? '[role=menuitem],[role=menuitemcheckbox],[role=menuitemradio]'
5120
5153
  : '[role=option]'
5121
5154
  });
5122
- return (
5123
- // Note: we should be able to use listbox without passing a prop
5124
- // value for "multiselect"
5125
- // see: https://github.com/dequelabs/cauldron/issues/1890
5126
- // @ts-expect-error this should be allowed
5127
- React__default["default"].createElement(Listbox, tslib.__assign({ ref: function (element) {
5155
+ return (React__default["default"].createElement(Listbox, tslib.__assign({ ref: function (element) {
5128
5156
  if (ref) {
5129
5157
  setRef(ref, element);
5130
5158
  }
@@ -5133,7 +5161,7 @@ var ActionList = React.forwardRef(function (_a, ref) {
5133
5161
  /* Listbox comes with an explicit role of "listbox", but we want to either
5134
5162
  * use the role from props, or default to the intrinsic role */
5135
5163
  // eslint-disable-next-line jsx-a11y/aria-role
5136
- role: undefined, "aria-multiselectable": actionListContext.role === 'listbox' ? undefined : null, className: classNames__default["default"]('ActionList', className), activeOption: activeOption }, props, { onActiveChange: handleActiveChange, navigation: "bound" }),
5164
+ role: undefined, "aria-multiselectable": undefined, className: classNames__default["default"]('ActionList', className), activeOption: activeOption }, props, { onActiveChange: handleActiveChange, navigation: "bound" }),
5137
5165
  React__default["default"].createElement(ActionListProvider, { role: props.role || 'list', onAction: handleAction, selectionType: selectionType }, children)));
5138
5166
  });
5139
5167
  ActionList.displayName = 'ActionList';
@@ -5151,7 +5179,7 @@ var ActionListItem = React.forwardRef(function (_a, ref) {
5151
5179
  });
5152
5180
  var isActive = !!(active === null || active === void 0 ? void 0 : active.element) && active.element === actionListItemRef.current;
5153
5181
  var handleAction = React.useCallback(function (event) {
5154
- var _a;
5182
+ var _a, _b;
5155
5183
  if (event.defaultPrevented) {
5156
5184
  return;
5157
5185
  }
@@ -5164,7 +5192,7 @@ var ActionListItem = React.forwardRef(function (_a, ref) {
5164
5192
  }
5165
5193
  // istanbul ignore else
5166
5194
  if (typeof onActionListAction === 'function') {
5167
- onActionListAction(actionKey || ((_a = labelRef === null || labelRef === void 0 ? void 0 : labelRef.current) === null || _a === void 0 ? void 0 : _a.innerText.trim()) || '', event);
5195
+ onActionListAction(actionKey || ((_b = (_a = labelRef.current) === null || _a === void 0 ? void 0 : _a.textContent) === null || _b === void 0 ? void 0 : _b.trim()) || '', event);
5168
5196
  }
5169
5197
  }, [onAction, onActionListAction, selectionType, actionKey]);
5170
5198
  var listItemRole = undefined;
@@ -5188,7 +5216,7 @@ var ActionListItem = React.forwardRef(function (_a, ref) {
5188
5216
  // istanbul ignore next
5189
5217
  React.useLayoutEffect(function () {
5190
5218
  var intersectionEntry = intersectionRef.current;
5191
- if (!intersectionEntry || !isActive) {
5219
+ if (!intersectionEntry || !isActive || !actionListItemRef.current) {
5192
5220
  return;
5193
5221
  }
5194
5222
  var rect = actionListItemRef.current.getBoundingClientRect();
@@ -5287,9 +5315,10 @@ var ActionMenu = React.forwardRef(function (_a, ref) {
5287
5315
  var _e = tslib.__read(React.useState('first'), 2), focusStrategy = _e[0], setFocusStrategy = _e[1];
5288
5316
  var triggerRef = React.useRef(null);
5289
5317
  var actionMenuRef = useSharedRef(ref);
5290
- var actionMenuListRef = useSharedRef(actionMenuList.props.ref);
5291
- var _f = tslib.__read(nextId.useId(1, 'menu-trigger'), 1), triggerId = _f[0];
5292
- var _g = tslib.__read(nextId.useId(1, 'menu'), 1), menuId = _g[0];
5318
+ var _f = actionMenuList.props, actionListRef = _f.ref, actionListOnAction = _f.onAction;
5319
+ var actionMenuListRef = useSharedRef(actionListRef !== null && actionListRef !== void 0 ? actionListRef : null);
5320
+ var _g = tslib.__read(nextId.useId(1, 'menu-trigger'), 1), triggerId = _g[0];
5321
+ var _h = tslib.__read(nextId.useId(1, 'menu'), 1), menuId = _h[0];
5293
5322
  var handleTriggerClick = React.useCallback(function (event) {
5294
5323
  // istanbul ignore else
5295
5324
  if (!event.defaultPrevented) {
@@ -5336,11 +5365,10 @@ var ActionMenu = React.forwardRef(function (_a, ref) {
5336
5365
  if (!event.defaultPrevented) {
5337
5366
  setOpen(false);
5338
5367
  }
5339
- var onAction = actionMenuList.props.onAction;
5340
- if (typeof onAction === 'function') {
5341
- onAction(key, event);
5368
+ if (typeof actionListOnAction === 'function') {
5369
+ actionListOnAction(key, event);
5342
5370
  }
5343
- }, [actionMenuList.props.onAction]);
5371
+ }, [actionListOnAction]);
5344
5372
  React.useEffect(function () {
5345
5373
  var _a, _b;
5346
5374
  if (open) {
@@ -5406,49 +5434,181 @@ var TreeViewItem = function (_a) {
5406
5434
  var checkboxId = React.useMemo(function () { return nextId__default["default"]('tree-view-item-'); }, []);
5407
5435
  return (React__default["default"].createElement(reactAriaComponents.TreeItem, { id: id, textValue: textValue, className: "TreeView__item" },
5408
5436
  React__default["default"].createElement(reactAriaComponents.TreeItemContent, null, function (_a) {
5409
- var selectionMode = _a.selectionMode, isSelected = _a.isSelected;
5437
+ var selectionMode = _a.selectionMode, isSelected = _a.isSelected, isDisabled = _a.isDisabled;
5410
5438
  return (React__default["default"].createElement(React__default["default"].Fragment, null,
5411
5439
  React__default["default"].createElement(reactAriaComponents.Button, { slot: "chevron", className: "TreeView__chevron" },
5412
5440
  React__default["default"].createElement(Icon, { type: "chevron-right" })),
5413
- selectionMode !== 'none' ? (React__default["default"].createElement(Checkbox, { id: checkboxId, label: textValue, checked: isSelected, controlled: true, tabIndex: -1 })) : (React__default["default"].createElement(React__default["default"].Fragment, null, textValue))));
5441
+ selectionMode !== 'none' ? (React__default["default"].createElement(Checkbox, { id: checkboxId, label: textValue, checked: isSelected, disabled: isDisabled, controlled: true, tabIndex: -1 })) : (React__default["default"].createElement(React__default["default"].Fragment, null, textValue))));
5414
5442
  }),
5415
5443
  children && children.length > 0 && (React__default["default"].createElement(reactAriaComponents.Collection, null, children.map(function (child) { return (React__default["default"].createElement(TreeViewItem, tslib.__assign({ key: child.id }, child))); })))));
5416
5444
  };
5417
5445
  TreeViewItem.displayName = 'TreeViewItem';
5418
5446
 
5447
+ /** Every node id in the tree, flattened depth-first. */
5419
5448
  function collectAllKeys(nodes) {
5420
5449
  return nodes.flatMap(function (node) { return tslib.__spreadArray([
5421
5450
  node.id
5422
5451
  ], tslib.__read((node.children ? collectAllKeys(node.children) : [])), false); });
5423
5452
  }
5424
- var TreeView = React.forwardRef(function (_a, ref) {
5425
- var items = _a.items, onAction = _a.onAction, _b = _a.selectionMode, selectionMode = _b === void 0 ? 'none' : _b, defaultExpandedKeys = _a.defaultExpandedKeys, className = _a.className, other = tslib.__rest(_a, ["items", "onAction", "selectionMode", "defaultExpandedKeys", "className"]);
5426
- var _c = tslib.__read(React.useState(new Set()), 2), selectedKeys = _c[0], setSelectedKeys = _c[1];
5427
- var handleAction = function (key) {
5428
- setSelectedKeys(function (prev) {
5429
- var prevSet = prev === 'all' ? new Set(collectAllKeys(items)) : new Set(prev);
5430
- var next = new Set(prevSet);
5431
- if (next.has(key)) {
5432
- next.delete(key);
5453
+ /** Normalize react-aria's `Selection` ("all" | Set) into a concrete Set of keys. */
5454
+ function toKeySet(selection, nodes) {
5455
+ if (selection !== 'all') {
5456
+ return new Set(selection);
5457
+ }
5458
+ // "Select all" only includes selectable (non-disabled) nodes.
5459
+ var disabled = new Set(collectDisabledKeys(nodes));
5460
+ return new Set(collectAllKeys(nodes).filter(function (key) { return !disabled.has(key); }));
5461
+ }
5462
+ /** Locate a node anywhere in the tree by its id. */
5463
+ function findNode(nodes, key) {
5464
+ var e_1, _a;
5465
+ try {
5466
+ for (var nodes_1 = tslib.__values(nodes), nodes_1_1 = nodes_1.next(); !nodes_1_1.done; nodes_1_1 = nodes_1.next()) {
5467
+ var node = nodes_1_1.value;
5468
+ if (node.id === key) {
5469
+ return node;
5433
5470
  }
5434
- else {
5435
- if (selectionMode === 'single') {
5436
- next.clear();
5471
+ if (node.children) {
5472
+ var found = findNode(node.children, key);
5473
+ if (found) {
5474
+ return found;
5437
5475
  }
5438
- next.add(key);
5439
5476
  }
5440
- return next;
5477
+ }
5478
+ }
5479
+ catch (e_1_1) { e_1 = { error: e_1_1 }; }
5480
+ finally {
5481
+ try {
5482
+ if (nodes_1_1 && !nodes_1_1.done && (_a = nodes_1.return)) _a.call(nodes_1);
5483
+ }
5484
+ finally { if (e_1) throw e_1.error; }
5485
+ }
5486
+ return undefined;
5487
+ }
5488
+ /** All descendant ids of a node (not including the node itself). */
5489
+ function collectDescendantKeys(node) {
5490
+ if (!node.children) {
5491
+ return [];
5492
+ }
5493
+ return node.children.flatMap(function (child) { return tslib.__spreadArray([
5494
+ child.id
5495
+ ], tslib.__read(collectDescendantKeys(child)), false); });
5496
+ }
5497
+ /** Ids of all disabled nodes (rendered disabled / non-selectable). */
5498
+ function collectDisabledKeys(nodes) {
5499
+ return nodes.flatMap(function (node) { return tslib.__spreadArray(tslib.__spreadArray([], tslib.__read((node.disabled ? [node.id] : [])), false), tslib.__read((node.children ? collectDisabledKeys(node.children) : [])), false); });
5500
+ }
5501
+ /**
5502
+ * Toggle a single node, applying cascade per the options (multiple mode only):
5503
+ * - selecting + `cascadeSelect`: also selects all (non-disabled) descendants.
5504
+ * - deselecting + `cascadeDeselect`: also deselects all descendants.
5505
+ *
5506
+ * In `single` mode only the clicked node is selected (clicking it again clears
5507
+ * it); cascade does not apply.
5508
+ */
5509
+ function toggleSelection(nodes, previous, key, selectionMode, _a) {
5510
+ var cascadeSelect = _a.cascadeSelect, cascadeDeselect = _a.cascadeDeselect;
5511
+ if (selectionMode === 'single') {
5512
+ var result_1 = new Set();
5513
+ if (!previous.has(key)) {
5514
+ result_1.add(key);
5515
+ }
5516
+ return result_1;
5517
+ }
5518
+ var result = new Set(previous);
5519
+ var node = findNode(nodes, key);
5520
+ var descendants = node ? collectDescendantKeys(node) : [];
5521
+ var disabled = new Set(collectDisabledKeys(nodes));
5522
+ if (!previous.has(key)) {
5523
+ result.add(key);
5524
+ if (cascadeSelect) {
5525
+ descendants.forEach(function (k) {
5526
+ if (!disabled.has(k)) {
5527
+ result.add(k);
5528
+ }
5529
+ });
5530
+ }
5531
+ }
5532
+ else {
5533
+ result.delete(key);
5534
+ if (cascadeDeselect) {
5535
+ descendants.forEach(function (k) { return result.delete(k); });
5536
+ }
5537
+ }
5538
+ return result;
5539
+ }
5540
+ /**
5541
+ * Apply react-aria's proposed selection while enforcing cascade. Each key
5542
+ * react-aria added cascades to its descendants when `cascadeSelect` is set; each
5543
+ * key it removed cascades when `cascadeDeselect` is set. In non-multiple modes
5544
+ * (or with both toggles off) the proposed selection is used as-is.
5545
+ */
5546
+ function applyCascade(nodes, previous, next, selectionMode, _a) {
5547
+ var cascadeSelect = _a.cascadeSelect, cascadeDeselect = _a.cascadeDeselect;
5548
+ if (selectionMode !== 'multiple' || (!cascadeSelect && !cascadeDeselect)) {
5549
+ return next;
5550
+ }
5551
+ var result = new Set(previous);
5552
+ var added = tslib.__spreadArray([], tslib.__read(next), false).filter(function (key) { return !previous.has(key); });
5553
+ var removed = tslib.__spreadArray([], tslib.__read(previous), false).filter(function (key) { return !next.has(key); });
5554
+ var disabled = new Set(collectDisabledKeys(nodes));
5555
+ added.forEach(function (key) {
5556
+ result.add(key);
5557
+ if (cascadeSelect) {
5558
+ var node = findNode(nodes, key);
5559
+ (node ? collectDescendantKeys(node) : []).forEach(function (k) {
5560
+ if (!disabled.has(k)) {
5561
+ result.add(k);
5562
+ }
5563
+ });
5564
+ }
5565
+ });
5566
+ removed.forEach(function (key) {
5567
+ result.delete(key);
5568
+ if (cascadeDeselect) {
5569
+ var node = findNode(nodes, key);
5570
+ (node ? collectDescendantKeys(node) : []).forEach(function (k) {
5571
+ return result.delete(k);
5572
+ });
5573
+ }
5574
+ });
5575
+ return result;
5576
+ }
5577
+
5578
+ var TreeView = React.forwardRef(function (_a, ref) {
5579
+ var items = _a.items, onAction = _a.onAction, _b = _a.selectionMode, selectionMode = _b === void 0 ? 'none' : _b, _c = _a.cascadeSelect, cascadeSelect = _c === void 0 ? false : _c, _d = _a.cascadeDeselect, cascadeDeselect = _d === void 0 ? false : _d, defaultExpandedKeys = _a.defaultExpandedKeys, className = _a.className, other = tslib.__rest(_a, ["items", "onAction", "selectionMode", "cascadeSelect", "cascadeDeselect", "defaultExpandedKeys", "className"]);
5580
+ var _e = tslib.__read(React.useState(new Set()), 2), selectedKeys = _e[0], setSelectedKeys = _e[1];
5581
+ var cascade = { cascadeSelect: cascadeSelect, cascadeDeselect: cascadeDeselect };
5582
+ // Cascade only applies to multiple selection.
5583
+ var isCascade = selectionMode === 'multiple' && (cascadeSelect || cascadeDeselect);
5584
+ // Selection driven by react-aria (row/checkbox press, keyboard). When
5585
+ // cascading, reconcile the proposed change; otherwise store react-aria's
5586
+ // selection as-is so the `'all'` sentinel (Ctrl+A) is preserved.
5587
+ var handleSelectionChange = function (selection) {
5588
+ setSelectedKeys(function (prev) {
5589
+ return isCascade
5590
+ ? applyCascade(items, toKeySet(prev, items), toKeySet(selection, items), selectionMode, cascade)
5591
+ : selection;
5441
5592
  });
5442
- onAction === null || onAction === void 0 ? void 0 : onAction(key);
5443
5593
  };
5444
- var actionProps = onAction
5445
- ? {
5446
- onAction: handleAction,
5447
- selectedKeys: selectedKeys,
5448
- onSelectionChange: setSelectedKeys
5594
+ // When `onAction` is set, react-aria treats a row press as an action rather
5595
+ // than a selection, so we toggle selection here ourselves.
5596
+ var handleAction = function (key) {
5597
+ if (selectionMode !== 'none') {
5598
+ setSelectedKeys(function (prev) {
5599
+ return toggleSelection(items, toKeySet(prev, items), key, selectionMode, cascade);
5600
+ });
5449
5601
  }
5602
+ onAction === null || onAction === void 0 ? void 0 : onAction(key);
5603
+ };
5604
+ // Disabled nodes are non-selectable; react-aria disables them via disabledKeys.
5605
+ var disabledKeys = React.useMemo(function () { return collectDisabledKeys(items); }, [items]);
5606
+ // Cascade requires controlling selection. Without it, preserve the original
5607
+ // behavior: selection is only controlled when an `onAction` handler is set.
5608
+ var selectionProps = selectionMode !== 'none' && (isCascade || onAction)
5609
+ ? { selectedKeys: selectedKeys, onSelectionChange: handleSelectionChange }
5450
5610
  : {};
5451
- return (React__default["default"].createElement(reactAriaComponents.Tree, tslib.__assign({ ref: ref, className: classNames__default["default"]('TreeView', className), selectionMode: selectionMode, defaultExpandedKeys: defaultExpandedKeys }, actionProps, other), items.map(function (item) { return (React__default["default"].createElement(TreeViewItem, tslib.__assign({ key: item.id }, item))); })));
5611
+ return (React__default["default"].createElement(reactAriaComponents.Tree, tslib.__assign({ ref: ref, className: classNames__default["default"]('TreeView', className), selectionMode: selectionMode, defaultExpandedKeys: defaultExpandedKeys }, (disabledKeys.length > 0 ? { disabledKeys: disabledKeys } : {}), (onAction ? { onAction: handleAction } : {}), selectionProps, other), items.map(function (item) { return (React__default["default"].createElement(TreeViewItem, tslib.__assign({ key: item.id }, item))); })));
5452
5612
  });
5453
5613
  TreeView.displayName = 'TreeView';
5454
5614