@deque/cauldron-react 7.1.0-canary.cdc8a15a → 7.1.0-canary.d24d20ed

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 (108) 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/Listbox/Listbox.d.ts +7 -2
  31. package/lib/components/MenuBar/index.d.ts +1 -0
  32. package/lib/components/Popover/index.d.ts +2 -2
  33. package/lib/components/Table/TableContext.d.ts +1 -1
  34. package/lib/components/Tabs/Tab.d.ts +1 -1
  35. package/lib/components/Toast/index.d.ts +4 -4
  36. package/lib/components/Tooltip/index.d.ts +2 -2
  37. package/lib/components/TreeView/helpers.d.ts +33 -0
  38. package/lib/components/TreeView/index.d.ts +6 -0
  39. package/lib/components/TreeView/types.d.ts +3 -0
  40. package/lib/copy.js +1 -1
  41. package/lib/download.js +1 -1
  42. package/lib/dropper.js +1 -1
  43. package/lib/exchange.js +1 -1
  44. package/lib/export-solid.js +1 -1
  45. package/lib/external-link.js +1 -1
  46. package/lib/eye.js +1 -1
  47. package/lib/filter.js +1 -1
  48. package/lib/flag.js +1 -1
  49. package/lib/gears.js +1 -1
  50. package/lib/github.js +1 -1
  51. package/lib/grid.js +1 -1
  52. package/lib/hamburger-menu.js +1 -1
  53. package/lib/hashtag.js +1 -1
  54. package/lib/highlight.js +1 -1
  55. package/lib/images.js +1 -1
  56. package/lib/index.js +269 -105
  57. package/lib/info-circle-alt.js +1 -1
  58. package/lib/info-circle.js +1 -1
  59. package/lib/info-square.js +1 -1
  60. package/lib/kabob.js +1 -1
  61. package/lib/link.js +1 -1
  62. package/lib/linkedin.js +1 -1
  63. package/lib/list.js +1 -1
  64. package/lib/lock.js +1 -1
  65. package/lib/magnifying-glass.js +1 -1
  66. package/lib/menu.js +1 -1
  67. package/lib/minus.js +1 -1
  68. package/lib/new-releases.js +1 -1
  69. package/lib/new.js +1 -1
  70. package/lib/no.js +1 -1
  71. package/lib/pause.js +1 -1
  72. package/lib/pencil.js +1 -1
  73. package/lib/person-running.js +1 -1
  74. package/lib/play.js +1 -1
  75. package/lib/plus.js +1 -1
  76. package/lib/question-circle-alt.js +1 -1
  77. package/lib/question-circle.js +1 -1
  78. package/lib/radio-checked.js +1 -1
  79. package/lib/radio-unchecked.js +1 -1
  80. package/lib/recycle-square.js +1 -1
  81. package/lib/recycle.js +1 -1
  82. package/lib/resend.js +1 -1
  83. package/lib/robot.js +1 -1
  84. package/lib/run-again.js +1 -1
  85. package/lib/save.js +1 -1
  86. package/lib/share-nodes.js +1 -1
  87. package/lib/share.js +1 -1
  88. package/lib/sort-triangle.js +1 -1
  89. package/lib/sort.js +1 -1
  90. package/lib/star.js +1 -1
  91. package/lib/step-back.js +1 -1
  92. package/lib/step-forward.js +1 -1
  93. package/lib/sun.js +1 -1
  94. package/lib/table-sort-ascending.js +1 -1
  95. package/lib/table-sort-descending.js +1 -1
  96. package/lib/tag.js +1 -1
  97. package/lib/target.js +1 -1
  98. package/lib/trash.js +1 -1
  99. package/lib/triangle.js +1 -1
  100. package/lib/twitter.js +1 -1
  101. package/lib/types.d.ts +1 -1
  102. package/lib/upload.js +1 -1
  103. package/lib/utils/getChildRef.d.ts +2 -0
  104. package/lib/utils/polymorphicComponent.d.ts +1 -1
  105. package/lib/utils/useFocusTrap.d.ts +1 -1
  106. package/lib/utils/useMnemonics.d.ts +2 -2
  107. package/lib/utils/useSharedRef.d.ts +3 -3
  108. package/package.json +30 -29
package/lib/index.js CHANGED
@@ -495,24 +495,25 @@ var Accordion = function (_a) {
495
495
  var childrenArray = React__default["default"].Children.toArray(children);
496
496
  var trigger = childrenArray.find(function (child) {
497
497
  return typeof child === 'string' ||
498
- child.type === AccordionTrigger;
498
+ (React__default["default"].isValidElement(child) && child.type === AccordionTrigger);
499
499
  });
500
500
  var panelElement = childrenArray.find(function (child) {
501
501
  return typeof child === 'string' ||
502
- child.type === AccordionContent;
502
+ (React__default["default"].isValidElement(child) && child.type === AccordionContent);
503
503
  });
504
- var isValid = !!(React__default["default"].isValidElement(trigger) && React__default["default"].isValidElement(panelElement));
505
- if (!isValid) {
504
+ if (!React__default["default"].isValidElement(trigger) ||
505
+ !React__default["default"].isValidElement(panelElement)) {
506
506
  console.warn('Must provide <AccordionTrigger /> and <AccordionContent /> element(s). You provided:', {
507
507
  trigger: trigger,
508
508
  panelElement: panelElement,
509
- isValid: isValid
509
+ isValid: false
510
510
  });
511
511
  return null;
512
512
  }
513
+ var panelProps = panelElement.props;
513
514
  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),
515
+ React__default["default"].createElement(ExpandCollapsePanel, tslib.__assign({ id: panelProps.id || "".concat(elementId, "-panel"), open: open, onToggle: onToggle, animationTiming: animationTiming }, panelProps),
516
+ 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
517
  panelElement)));
517
518
  };
518
519
  Accordion.displayName = 'Accordion';
@@ -578,7 +579,9 @@ var Scrim = /** @class */ (function (_super) {
578
579
  if (destroy) {
579
580
  return null;
580
581
  }
581
- return (React__default["default"].createElement("div", { ref: function (el) { return (_this.el = el); }, className: "Scrim ".concat(animationClass) }));
582
+ return (React__default["default"].createElement("div", { ref: function (el) {
583
+ _this.el = el;
584
+ }, className: "Scrim ".concat(animationClass) }));
582
585
  };
583
586
  return Scrim;
584
587
  }(React__default["default"].Component));
@@ -672,6 +675,7 @@ var TopBar$1 = /** @class */ (function (_super) {
672
675
  tslib.__extends(TopBar, _super);
673
676
  function TopBar(props) {
674
677
  var _this = _super.call(this, props) || this;
678
+ _this.menuBarRef = React__default["default"].createRef();
675
679
  _this.onResize = function () {
676
680
  var wide = isWide();
677
681
  if (wide === _this.state.wide) {
@@ -720,10 +724,10 @@ var TopBar$1 = /** @class */ (function (_super) {
720
724
  };
721
725
  TopBar.prototype.onKeyDown = function (e) {
722
726
  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);
727
+ var menuBarElement = this.menuBarRef.current;
728
+ if (!menuBarElement) {
729
+ return;
730
+ }
727
731
  var menuItems = Array.from(menuBarElement.children);
728
732
  // account for hidden side bar trigger (hamburger)
729
733
  if (this.state.wide && this.props.hasTrigger) {
@@ -750,7 +754,7 @@ var TopBar$1 = /** @class */ (function (_super) {
750
754
  // disabling no-unused-vars to prevent thin/hasTrigger from being passed through to div
751
755
  // eslint-disable-next-line @typescript-eslint/no-unused-vars
752
756
  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)));
757
+ return (React__default["default"].createElement("ul", { role: "menubar", onKeyDown: this.onKeyDown, className: className, ref: this.menuBarRef }, React.Children.map(children, this.renderChild)));
754
758
  };
755
759
  TopBar.defaultProps = {
756
760
  thin: false,
@@ -806,9 +810,16 @@ function resolveElement(elementOrRef) {
806
810
  return null;
807
811
  }
808
812
 
813
+ function getChildRef(child, version) {
814
+ if (version === void 0) { version = React__default["default"].version; }
815
+ return parseInt(version, 10) >= 19
816
+ ? child.props.ref
817
+ : child.ref;
818
+ }
819
+
809
820
  function ClickOutsideListener(_a, ref) {
810
821
  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();
822
+ var childElementRef = React.useRef(null);
812
823
  var handleEvent = function (event) {
813
824
  if (event.defaultPrevented) {
814
825
  return;
@@ -831,9 +842,8 @@ function ClickOutsideListener(_a, ref) {
831
842
  childElementRef.current = node;
832
843
  // Ref for this component should pass-through to the child node
833
844
  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;
845
+ // Forward the child's own ref. In React 19 ref lives in props; in 16–18 it's element.ref.
846
+ var childRef = getChildRef(children);
837
847
  setRef(childRef, node);
838
848
  };
839
849
  React.useEffect(function () {
@@ -1342,7 +1352,7 @@ var AriaIsolate = /** @class */ (function () {
1342
1352
 
1343
1353
  /**
1344
1354
  * 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
1355
+ * forwarded ref, useSharedRef will return a RefObject<T | null> that will
1346
1356
  * correctly invoke the parent ref as well providing an internal ref.
1347
1357
  *
1348
1358
  * @example
@@ -1355,7 +1365,7 @@ var AriaIsolate = /** @class */ (function () {
1355
1365
  * })
1356
1366
  */
1357
1367
  function useSharedRef(ref) {
1358
- var internalRef = React.useRef();
1368
+ var internalRef = React.useRef(null);
1359
1369
  React.useEffect(function () {
1360
1370
  setRef(ref, internalRef.current);
1361
1371
  return function () { return setRef(ref, null); };
@@ -1488,7 +1498,7 @@ function useFocusTrap(target, options) {
1488
1498
  if (options === void 0) { options = {}; }
1489
1499
  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
1500
  var focusTrap = React.useRef(null);
1491
- var returnFocusElementRef = React.useRef();
1501
+ var returnFocusElementRef = React.useRef(null);
1492
1502
  function restoreFocusToReturnFocusElement() {
1493
1503
  var _a;
1494
1504
  var resolvedReturnFocusElement = resolveElement(returnFocusElement);
@@ -1538,7 +1548,7 @@ var Dialog = React.forwardRef(function (_a, ref) {
1538
1548
  var dialogRef = useSharedRef(dialogRefProp || ref);
1539
1549
  var _g = tslib.__read(nextId.useId(1, 'dialog-title-'), 1), headingId = _g[0];
1540
1550
  var headingRef = React.useRef(null);
1541
- var isolatorRef = React.useRef();
1551
+ var isolatorRef = React.useRef(null);
1542
1552
  var headingLevel = typeof heading === 'object' && 'level' in heading && heading.level
1543
1553
  ? heading.level
1544
1554
  : 2;
@@ -2133,7 +2143,7 @@ var looksLikeLink = function (props) {
2133
2143
  };
2134
2144
  var IconButton = React.forwardRef(function (_a, ref) {
2135
2145
  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();
2146
+ var internalRef = React.useRef(null);
2137
2147
  React.useImperativeHandle(ref, function () { return internalRef.current; });
2138
2148
  // Configure additional properties based on the type of the Component
2139
2149
  // for accessibility
@@ -2243,14 +2253,22 @@ var useDidUpdate = function (effect, dependencies) {
2243
2253
  /**
2244
2254
  * The cauldron toast notification component
2245
2255
  */
2246
- var Toast = function (_a) {
2256
+ var Toast = React.forwardRef(function (_a, ref) {
2247
2257
  var type = _a.type, children = _a.children, _b = _a.onDismiss, onDismiss = _b === void 0 ? function () {
2248
2258
  // noop
2249
2259
  } : _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);
2260
+ var elRef = useSharedRef(ref);
2251
2261
  var isolatorRef = React.useRef(null);
2252
2262
  var timeoutsRef = React.useRef(new Set());
2253
2263
  var _g = tslib.__read(React.useState(show ? 'FadeIn--flex' : 'is--hidden'), 2), animationClass = _g[0], setAnimationClass = _g[1];
2264
+ // Backwards-compat: propagate to the deprecated toastRef prop as well
2265
+ React.useEffect(function () {
2266
+ var _a;
2267
+ if (!toastRef)
2268
+ return;
2269
+ setRef(toastRef, (_a = elRef.current) !== null && _a !== void 0 ? _a : null);
2270
+ return function () { return setRef(toastRef, null); };
2271
+ }, [toastRef]);
2254
2272
  // Timeout because CSS display: none/block and opacity:
2255
2273
  // 0/1 properties cannot be toggled in the same tick
2256
2274
  // see: https://codepen.io/isnerms/pen/eyQaLP
@@ -2324,7 +2342,7 @@ var Toast = function (_a) {
2324
2342
  type !== 'action-needed' && dismissible && (React__default["default"].createElement("button", { type: "button", className: "Toast__dismiss", "aria-label": dismissText, onClick: dismissToast },
2325
2343
  React__default["default"].createElement(Icon, { type: "close" })))),
2326
2344
  scrim));
2327
- };
2345
+ });
2328
2346
  Toast.displayName = 'Toast';
2329
2347
 
2330
2348
  var Link = React.forwardRef(function (_a, ref) {
@@ -2687,7 +2705,7 @@ Checkbox.displayName = 'Checkbox';
2687
2705
  */
2688
2706
  function TooltipTabstop(_a) {
2689
2707
  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();
2708
+ var buttonRef = React.useRef(null);
2691
2709
  return (React__default["default"].createElement(React__default["default"].Fragment, null,
2692
2710
  React__default["default"].createElement("button", tslib.__assign({ type: "button", ref: buttonRef, "aria-disabled": "true", className: classNames__default["default"]('TooltipTabstop', className) }, buttonProps), children),
2693
2711
  React__default["default"].createElement(Tooltip, { target: buttonRef, variant: variant, association: association, show: show, placement: placement, portal: portal, hideElementOnHidden: hideElementOnHidden }, tooltip)));
@@ -3531,7 +3549,7 @@ var TwoColumnPanel = React.forwardRef(function (_a, ref) {
3531
3549
  var closeButtonRef = React.useRef(null);
3532
3550
  var columnLeftRef = React.useRef(null);
3533
3551
  var columnRightRef = React.useRef(null);
3534
- var columnLeft = React__default["default"].Children.toArray(children).find(function (child) { return child.type === ColumnLeft; });
3552
+ var columnLeft = React__default["default"].Children.toArray(children).find(function (child) { return React__default["default"].isValidElement(child) && child.type === ColumnLeft; });
3535
3553
  var togglePanel = function () {
3536
3554
  var prefersReducedMotion = 'matchMedia' in window &&
3537
3555
  typeof matchMedia === 'function' &&
@@ -3564,16 +3582,17 @@ var TwoColumnPanel = React.forwardRef(function (_a, ref) {
3564
3582
  var ColumnLeftComponent;
3565
3583
  var columnLeftId;
3566
3584
  if (React.isValidElement(columnLeft)) {
3567
- var ref_1 = columnLeft.props.ref || columnLeftRef;
3585
+ var columnLeftProps = columnLeft.props;
3586
+ var ref_1 = columnLeftProps.ref || columnLeftRef;
3568
3587
  var id = (columnLeftId =
3569
- columnLeft.props.id || nextId.useId(undefined, 'sidebar-')[0]);
3588
+ columnLeftProps.id || nextId.useId(undefined, 'sidebar-')[0]);
3570
3589
  var CloseButton = (React__default["default"].createElement("div", { className: "TwoColumnPanel__Close" },
3571
3590
  React__default["default"].createElement("button", { type: "button", onClick: togglePanel, ref: closeButtonRef, "aria-label": hideCollapsedPanelLabel },
3572
3591
  React__default["default"].createElement(Icon, { type: "close" })),
3573
3592
  React__default["default"].createElement(Tooltip, { target: closeButtonRef, association: "aria-labelledby", hideElementOnHidden: true }, hideCollapsedPanelLabel)));
3574
3593
  var children_1 = tslib.__spreadArray([
3575
3594
  CloseButton
3576
- ], tslib.__read(React__default["default"].Children.toArray(columnLeft.props.children)), false);
3595
+ ], tslib.__read(React__default["default"].Children.toArray(columnLeftProps.children)), false);
3577
3596
  ColumnLeftComponent = React.cloneElement(columnLeft, { id: id, ref: ref_1, tabIndex: -1 }, children_1.map(function (child, index) {
3578
3597
  return React.cloneElement(child, {
3579
3598
  key: child.key
@@ -3582,17 +3601,18 @@ var TwoColumnPanel = React.forwardRef(function (_a, ref) {
3582
3601
  });
3583
3602
  }));
3584
3603
  }
3585
- var columnRight = React__default["default"].Children.toArray(children).find(function (child) { return child.type === ColumnRight; });
3604
+ var columnRight = React__default["default"].Children.toArray(children).find(function (child) { return React__default["default"].isValidElement(child) && child.type === ColumnRight; });
3586
3605
  var ColumnRightComponent;
3587
3606
  if (React.isValidElement(columnRight)) {
3588
- var ref_2 = columnRight.props.ref || columnRightRef;
3607
+ var columnRightProps = columnRight.props;
3608
+ var ref_2 = columnRightProps.ref || columnRightRef;
3589
3609
  var ToggleButton = (React__default["default"].createElement("div", { className: "TwoColumnPanel__ButtonToggle" },
3590
3610
  React__default["default"].createElement("button", { type: "button", onClick: togglePanel, ref: toggleButtonRef, "aria-label": !isCollapsed ? hideCollapsedPanelLabel : showCollapsedPanelLabel, "aria-expanded": !isCollapsed, "aria-controls": columnLeftId },
3591
3611
  React__default["default"].createElement(Icon, { type: !isCollapsed ? 'chevron-double-left' : 'chevron-double-right' })),
3592
3612
  React__default["default"].createElement(Tooltip, { target: toggleButtonRef, association: "aria-labelledby", hideElementOnHidden: true }, !isCollapsed ? hideCollapsedPanelLabel : showCollapsedPanelLabel)));
3593
3613
  var children_2 = tslib.__spreadArray([
3594
3614
  ToggleButton
3595
- ], tslib.__read(React__default["default"].Children.toArray(columnRight.props.children)), false);
3615
+ ], tslib.__read(React__default["default"].Children.toArray(columnRightProps.children)), false);
3596
3616
  ColumnRightComponent = React.cloneElement(columnRight, { ref: ref_2, tabIndex: -1 }, children_2.map(function (child, index) {
3597
3617
  return React.cloneElement(child, {
3598
3618
  key: child.key
@@ -3778,7 +3798,8 @@ var Listbox = React.forwardRef(function (_a, ref) {
3778
3798
  }
3779
3799
  }, [activeOption]);
3780
3800
  React.useEffect(function () {
3781
- if (isActiveControlled && controlledActiveOption !== activeOption) {
3801
+ if (isActiveControlled &&
3802
+ (controlledActiveOption === null || controlledActiveOption === void 0 ? void 0 : controlledActiveOption.element) !== (activeOption === null || activeOption === void 0 ? void 0 : activeOption.element)) {
3782
3803
  setActiveOption(controlledActiveOption || null);
3783
3804
  }
3784
3805
  }, [isActiveControlled, controlledActiveOption]);
@@ -3924,11 +3945,11 @@ function isElementPreceding(a, b) {
3924
3945
  }
3925
3946
  var ListboxOption = React.forwardRef(function (_a, ref) {
3926
3947
  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;
3948
+ var _c, _d;
3949
+ 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"]);
3950
+ var _g = useListboxContext(), active = _g.active, selected = _g.selected, setOptions = _g.setOptions, onSelect = _g.onSelect;
3930
3951
  var listboxOptionRef = useSharedRef(ref);
3931
- var _g = tslib.__read(propId ? [propId] : nextId.useId(1, 'listbox-option'), 1), id = _g[0];
3952
+ var _h = tslib.__read(propId ? [propId] : nextId.useId(1, 'listbox-option'), 1), id = _h[0];
3932
3953
  var isActive = (active === null || active === void 0 ? void 0 : active.element) === listboxOptionRef.current;
3933
3954
  var isSelected = typeof selectedProp === 'boolean'
3934
3955
  ? selectedProp
@@ -3936,15 +3957,15 @@ var ListboxOption = React.forwardRef(function (_a, ref) {
3936
3957
  !!selected.find(function (option) { return option.element === listboxOptionRef.current; });
3937
3958
  var optionValue = typeof value !== 'undefined'
3938
3959
  ? value
3939
- : (_c = listboxOptionRef.current) === null || _c === void 0 ? void 0 : _c.innerText;
3960
+ : ((_d = (_c = listboxOptionRef.current) === null || _c === void 0 ? void 0 : _c.textContent) !== null && _d !== void 0 ? _d : undefined);
3940
3961
  React.useEffect(function () {
3941
3962
  var element = listboxOptionRef.current;
3942
3963
  setOptions(function (options) {
3943
3964
  var e_1, _a;
3944
- var option = { element: element, value: optionValue };
3945
3965
  // istanbul ignore next
3946
3966
  if (!element)
3947
3967
  return options;
3968
+ var option = { element: element, value: optionValue };
3948
3969
  // Elements are frequently appended, so check to see if the newly rendered
3949
3970
  // element follows the last element first before any other checks
3950
3971
  if (!options.length ||
@@ -4131,7 +4152,7 @@ var ComboboxOption = React.forwardRef(function (_a, ref) {
4131
4152
  // istanbul ignore next
4132
4153
  React.useLayoutEffect(function () {
4133
4154
  var intersectionEntry = intersectionRef.current;
4134
- if (!intersectionEntry || !isActive) {
4155
+ if (!intersectionEntry || !isActive || !comboboxOptionRef.current) {
4135
4156
  return;
4136
4157
  }
4137
4158
  var rect = comboboxOptionRef.current.getBoundingClientRect();
@@ -4147,10 +4168,10 @@ var ComboboxOption = React.forwardRef(function (_a, ref) {
4147
4168
  }
4148
4169
  }, [isActive]);
4149
4170
  React.useEffect(function () {
4150
- var _a;
4171
+ var _a, _b;
4151
4172
  var comboboxValue = typeof propValue !== 'undefined'
4152
4173
  ? propValue
4153
- : (_a = comboboxOptionRef.current) === null || _a === void 0 ? void 0 : _a.innerText;
4174
+ : ((_b = (_a = comboboxOptionRef.current) === null || _a === void 0 ? void 0 : _a.textContent) !== null && _b !== void 0 ? _b : undefined);
4154
4175
  var value = typeof formValue === 'undefined' ? comboboxValue : formValue;
4155
4176
  setFormValues(function (prev) {
4156
4177
  var formValues = prev.filter(function (fv) { return fv !== value; });
@@ -4169,12 +4190,14 @@ var ComboboxOption = React.forwardRef(function (_a, ref) {
4169
4190
  });
4170
4191
  }, [selectedValues, formValue]);
4171
4192
  React.useEffect(function () {
4172
- var _a;
4193
+ var _a, _b;
4173
4194
  if (isMatching) {
4174
4195
  var comboboxValue_1 = typeof propValue !== 'undefined'
4175
4196
  ? propValue
4176
- : (_a = comboboxOptionRef.current) === null || _a === void 0 ? void 0 : _a.innerText;
4197
+ : ((_b = (_a = comboboxOptionRef.current) === null || _a === void 0 ? void 0 : _a.textContent) !== null && _b !== void 0 ? _b : undefined);
4177
4198
  setMatchingOptions(function (options) {
4199
+ if (!comboboxOptionRef.current)
4200
+ return options;
4178
4201
  return new Map(options.set(comboboxOptionRef.current, {
4179
4202
  value: comboboxValue_1,
4180
4203
  displayValue: children,
@@ -4314,6 +4337,17 @@ var Combobox = React.forwardRef(function (_a, ref) {
4314
4337
  return value === lastSelectedValue;
4315
4338
  }) || [], 2), element = _a[0], option = _a[1];
4316
4339
  if (autocomplete === 'manual') {
4340
+ // In multiselect, the listbox manages its own active option via
4341
+ // keyboard navigation. When the last-selected value no longer
4342
+ // matches any option (e.g. after deselecting the only selected
4343
+ // option), preserve the existing active descendant so the next
4344
+ // Enter keypress can re-toggle the highlighted option.
4345
+ if (multiselect &&
4346
+ !element &&
4347
+ activeDescendant &&
4348
+ matchingOptions.has(activeDescendant.element)) {
4349
+ return;
4350
+ }
4317
4351
  setActiveDescendant(!element ? null : tslib.__assign({ element: element }, option));
4318
4352
  }
4319
4353
  else if (autocomplete === 'automatic' &&
@@ -4493,6 +4527,7 @@ var Combobox = React.forwardRef(function (_a, ref) {
4493
4527
  });
4494
4528
  }, [disabled, selectedValues, onSelectionChange]);
4495
4529
  var handlePillKeyDown = React.useCallback(function (event) {
4530
+ var _a, _b;
4496
4531
  if (!PillKeys.includes(event.key)) {
4497
4532
  return;
4498
4533
  }
@@ -4510,7 +4545,7 @@ var Combobox = React.forwardRef(function (_a, ref) {
4510
4545
  handleRemovePill(pillsRef.current[focusedIndex], selectedValues[focusedIndex]);
4511
4546
  var nextIndex = focusedIndex + 1;
4512
4547
  if (nextIndex == pillsLength) {
4513
- inputRef.current.focus();
4548
+ (_a = inputRef.current) === null || _a === void 0 ? void 0 : _a.focus();
4514
4549
  }
4515
4550
  else {
4516
4551
  pillsRef.current[nextIndex].focus();
@@ -4519,7 +4554,7 @@ var Combobox = React.forwardRef(function (_a, ref) {
4519
4554
  else if (isArrowLeft || isArrowRight) {
4520
4555
  var nextIndex = Math.max(focusedIndex + (isArrowLeft ? -1 : 1), 0);
4521
4556
  if (isArrowRight && nextIndex === pillsLength) {
4522
- inputRef.current.focus();
4557
+ (_b = inputRef.current) === null || _b === void 0 ? void 0 : _b.focus();
4523
4558
  }
4524
4559
  else {
4525
4560
  pillsRef.current[nextIndex].focus();
@@ -4807,10 +4842,12 @@ var TextEllipsis = React__default["default"].forwardRef(function (_a, ref) {
4807
4842
  : overflowElement.clientWidth < overflowElement.scrollWidth);
4808
4843
  });
4809
4844
  };
4845
+ if (!sharedRef.current)
4846
+ return;
4810
4847
  var observer = new ResizeObserver(listener);
4811
4848
  observer.observe(sharedRef.current);
4812
4849
  return function () {
4813
- observer === null || observer === void 0 ? void 0 : observer.disconnect();
4850
+ observer.disconnect();
4814
4851
  };
4815
4852
  }, []);
4816
4853
  React.useEffect(function () {
@@ -4855,7 +4892,7 @@ var Drawer = React.forwardRef(function (_a, ref) {
4855
4892
  openRef.current = open;
4856
4893
  }, [open, setIsTransitioning]);
4857
4894
  React.useEffect(function () {
4858
- if (!isModal) {
4895
+ if (!isModal || !drawerRef.current) {
4859
4896
  return;
4860
4897
  }
4861
4898
  var isolator = new AriaIsolate(drawerRef.current);
@@ -5036,7 +5073,7 @@ function getActiveElement(root) {
5036
5073
  */
5037
5074
  function useMnemonics(_a) {
5038
5075
  var elementOrRef = _a.elementOrRef, matchingElementsSelector = _a.matchingElementsSelector, onMatch = _a.onMatch, _b = _a.enabled, enabled = _b === void 0 ? true : _b;
5039
- var containerRef = React.useRef();
5076
+ var containerRef = React.useRef(null);
5040
5077
  React.useEffect(function () {
5041
5078
  if (elementOrRef instanceof HTMLElement) {
5042
5079
  containerRef.current = elementOrRef;
@@ -5046,7 +5083,8 @@ function useMnemonics(_a) {
5046
5083
  }
5047
5084
  }, [elementOrRef]);
5048
5085
  React.useEffect(function () {
5049
- if (!enabled || !containerRef.current) {
5086
+ var listenerTarget = containerRef.current;
5087
+ if (!enabled || !listenerTarget) {
5050
5088
  return;
5051
5089
  }
5052
5090
  var keyboardHandler = function (event) {
@@ -5059,14 +5097,14 @@ function useMnemonics(_a) {
5059
5097
  if (event.key.length !== 1 || !/[a-z\d]/i.test(event.key)) {
5060
5098
  return;
5061
5099
  }
5062
- var container = containerRef.current;
5063
- if (!container) {
5100
+ var currentContainer = containerRef.current;
5101
+ if (!currentContainer) {
5064
5102
  return;
5065
5103
  }
5066
5104
  // Prevent default behavior and stop propagation for mnemonic keys
5067
5105
  event.preventDefault();
5068
5106
  event.stopPropagation();
5069
- var elements = Array.from(container.querySelectorAll(matchingElementsSelector !== null && matchingElementsSelector !== void 0 ? matchingElementsSelector : focusable__default["default"]));
5107
+ var elements = Array.from(currentContainer.querySelectorAll(matchingElementsSelector !== null && matchingElementsSelector !== void 0 ? matchingElementsSelector : focusable__default["default"]));
5070
5108
  var matchingElements = elements.filter(function (element) {
5071
5109
  return getAccessibleLabel(element).toLowerCase()[0] ===
5072
5110
  event.key.toLowerCase();
@@ -5074,7 +5112,7 @@ function useMnemonics(_a) {
5074
5112
  if (!matchingElements.length) {
5075
5113
  return;
5076
5114
  }
5077
- var currentActiveElement = getActiveElement(containerRef.current);
5115
+ var currentActiveElement = getActiveElement(currentContainer);
5078
5116
  var nextActiveElement = null;
5079
5117
  if (currentActiveElement) {
5080
5118
  nextActiveElement = matchingElements.find(function (element) {
@@ -5088,17 +5126,15 @@ function useMnemonics(_a) {
5088
5126
  onMatch(nextActiveElement !== null && nextActiveElement !== void 0 ? nextActiveElement : matchingElements[0]);
5089
5127
  }
5090
5128
  };
5091
- var container = containerRef.current;
5092
- container.addEventListener('keydown', keyboardHandler);
5093
- return function () { return container.removeEventListener('keydown', keyboardHandler); };
5129
+ listenerTarget.addEventListener('keydown', keyboardHandler);
5130
+ return function () { return listenerTarget.removeEventListener('keydown', keyboardHandler); };
5094
5131
  }, [enabled, containerRef, matchingElementsSelector, onMatch]);
5095
5132
  return containerRef;
5096
5133
  }
5097
5134
 
5098
5135
  var ActionList = React.forwardRef(function (_a, ref) {
5099
5136
  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();
5137
+ var activeElement = React.useRef(null);
5102
5138
  var _c = tslib.__read(React.useState(), 2), activeOption = _c[0], setActiveOption = _c[1];
5103
5139
  var handleActiveChange = React.useCallback(function (value) {
5104
5140
  activeElement.current = value === null || value === void 0 ? void 0 : value.element;
@@ -5109,22 +5145,18 @@ var ActionList = React.forwardRef(function (_a, ref) {
5109
5145
  onAction(key, event);
5110
5146
  }
5111
5147
  }, [onAction]);
5148
+ var handleMnemonicMatch = React.useCallback(function (element) {
5149
+ setActiveOption(function (prev) {
5150
+ return (prev === null || prev === void 0 ? void 0 : prev.element) === element ? prev : { element: element };
5151
+ });
5152
+ }, []);
5112
5153
  var containerRef = useMnemonics({
5113
- onMatch: function (element) {
5114
- setActiveOption({
5115
- element: element
5116
- });
5117
- },
5154
+ onMatch: handleMnemonicMatch,
5118
5155
  matchingElementsSelector: props.role === 'menu'
5119
5156
  ? '[role=menuitem],[role=menuitemcheckbox],[role=menuitemradio]'
5120
5157
  : '[role=option]'
5121
5158
  });
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) {
5159
+ return (React__default["default"].createElement(Listbox, tslib.__assign({ ref: function (element) {
5128
5160
  if (ref) {
5129
5161
  setRef(ref, element);
5130
5162
  }
@@ -5133,7 +5165,7 @@ var ActionList = React.forwardRef(function (_a, ref) {
5133
5165
  /* Listbox comes with an explicit role of "listbox", but we want to either
5134
5166
  * use the role from props, or default to the intrinsic role */
5135
5167
  // 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" }),
5168
+ role: undefined, "aria-multiselectable": undefined, className: classNames__default["default"]('ActionList', className), activeOption: activeOption }, props, { onActiveChange: handleActiveChange, navigation: "bound" }),
5137
5169
  React__default["default"].createElement(ActionListProvider, { role: props.role || 'list', onAction: handleAction, selectionType: selectionType }, children)));
5138
5170
  });
5139
5171
  ActionList.displayName = 'ActionList';
@@ -5151,7 +5183,7 @@ var ActionListItem = React.forwardRef(function (_a, ref) {
5151
5183
  });
5152
5184
  var isActive = !!(active === null || active === void 0 ? void 0 : active.element) && active.element === actionListItemRef.current;
5153
5185
  var handleAction = React.useCallback(function (event) {
5154
- var _a;
5186
+ var _a, _b;
5155
5187
  if (event.defaultPrevented) {
5156
5188
  return;
5157
5189
  }
@@ -5164,7 +5196,7 @@ var ActionListItem = React.forwardRef(function (_a, ref) {
5164
5196
  }
5165
5197
  // istanbul ignore else
5166
5198
  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);
5199
+ onActionListAction(actionKey || ((_b = (_a = labelRef.current) === null || _a === void 0 ? void 0 : _a.textContent) === null || _b === void 0 ? void 0 : _b.trim()) || '', event);
5168
5200
  }
5169
5201
  }, [onAction, onActionListAction, selectionType, actionKey]);
5170
5202
  var listItemRole = undefined;
@@ -5188,7 +5220,7 @@ var ActionListItem = React.forwardRef(function (_a, ref) {
5188
5220
  // istanbul ignore next
5189
5221
  React.useLayoutEffect(function () {
5190
5222
  var intersectionEntry = intersectionRef.current;
5191
- if (!intersectionEntry || !isActive) {
5223
+ if (!intersectionEntry || !isActive || !actionListItemRef.current) {
5192
5224
  return;
5193
5225
  }
5194
5226
  var rect = actionListItemRef.current.getBoundingClientRect();
@@ -5287,9 +5319,10 @@ var ActionMenu = React.forwardRef(function (_a, ref) {
5287
5319
  var _e = tslib.__read(React.useState('first'), 2), focusStrategy = _e[0], setFocusStrategy = _e[1];
5288
5320
  var triggerRef = React.useRef(null);
5289
5321
  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];
5322
+ var _f = actionMenuList.props, actionListRef = _f.ref, actionListOnAction = _f.onAction;
5323
+ var actionMenuListRef = useSharedRef(actionListRef !== null && actionListRef !== void 0 ? actionListRef : null);
5324
+ var _g = tslib.__read(nextId.useId(1, 'menu-trigger'), 1), triggerId = _g[0];
5325
+ var _h = tslib.__read(nextId.useId(1, 'menu'), 1), menuId = _h[0];
5293
5326
  var handleTriggerClick = React.useCallback(function (event) {
5294
5327
  // istanbul ignore else
5295
5328
  if (!event.defaultPrevented) {
@@ -5336,11 +5369,10 @@ var ActionMenu = React.forwardRef(function (_a, ref) {
5336
5369
  if (!event.defaultPrevented) {
5337
5370
  setOpen(false);
5338
5371
  }
5339
- var onAction = actionMenuList.props.onAction;
5340
- if (typeof onAction === 'function') {
5341
- onAction(key, event);
5372
+ if (typeof actionListOnAction === 'function') {
5373
+ actionListOnAction(key, event);
5342
5374
  }
5343
- }, [actionMenuList.props.onAction]);
5375
+ }, [actionListOnAction]);
5344
5376
  React.useEffect(function () {
5345
5377
  var _a, _b;
5346
5378
  if (open) {
@@ -5406,49 +5438,181 @@ var TreeViewItem = function (_a) {
5406
5438
  var checkboxId = React.useMemo(function () { return nextId__default["default"]('tree-view-item-'); }, []);
5407
5439
  return (React__default["default"].createElement(reactAriaComponents.TreeItem, { id: id, textValue: textValue, className: "TreeView__item" },
5408
5440
  React__default["default"].createElement(reactAriaComponents.TreeItemContent, null, function (_a) {
5409
- var selectionMode = _a.selectionMode, isSelected = _a.isSelected;
5441
+ var selectionMode = _a.selectionMode, isSelected = _a.isSelected, isDisabled = _a.isDisabled;
5410
5442
  return (React__default["default"].createElement(React__default["default"].Fragment, null,
5411
5443
  React__default["default"].createElement(reactAriaComponents.Button, { slot: "chevron", className: "TreeView__chevron" },
5412
5444
  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))));
5445
+ 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
5446
  }),
5415
5447
  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
5448
  };
5417
5449
  TreeViewItem.displayName = 'TreeViewItem';
5418
5450
 
5451
+ /** Every node id in the tree, flattened depth-first. */
5419
5452
  function collectAllKeys(nodes) {
5420
5453
  return nodes.flatMap(function (node) { return tslib.__spreadArray([
5421
5454
  node.id
5422
5455
  ], tslib.__read((node.children ? collectAllKeys(node.children) : [])), false); });
5423
5456
  }
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);
5457
+ /** Normalize react-aria's `Selection` ("all" | Set) into a concrete Set of keys. */
5458
+ function toKeySet(selection, nodes) {
5459
+ if (selection !== 'all') {
5460
+ return new Set(selection);
5461
+ }
5462
+ // "Select all" only includes selectable (non-disabled) nodes.
5463
+ var disabled = new Set(collectDisabledKeys(nodes));
5464
+ return new Set(collectAllKeys(nodes).filter(function (key) { return !disabled.has(key); }));
5465
+ }
5466
+ /** Locate a node anywhere in the tree by its id. */
5467
+ function findNode(nodes, key) {
5468
+ var e_1, _a;
5469
+ try {
5470
+ for (var nodes_1 = tslib.__values(nodes), nodes_1_1 = nodes_1.next(); !nodes_1_1.done; nodes_1_1 = nodes_1.next()) {
5471
+ var node = nodes_1_1.value;
5472
+ if (node.id === key) {
5473
+ return node;
5433
5474
  }
5434
- else {
5435
- if (selectionMode === 'single') {
5436
- next.clear();
5475
+ if (node.children) {
5476
+ var found = findNode(node.children, key);
5477
+ if (found) {
5478
+ return found;
5437
5479
  }
5438
- next.add(key);
5439
5480
  }
5440
- return next;
5481
+ }
5482
+ }
5483
+ catch (e_1_1) { e_1 = { error: e_1_1 }; }
5484
+ finally {
5485
+ try {
5486
+ if (nodes_1_1 && !nodes_1_1.done && (_a = nodes_1.return)) _a.call(nodes_1);
5487
+ }
5488
+ finally { if (e_1) throw e_1.error; }
5489
+ }
5490
+ return undefined;
5491
+ }
5492
+ /** All descendant ids of a node (not including the node itself). */
5493
+ function collectDescendantKeys(node) {
5494
+ if (!node.children) {
5495
+ return [];
5496
+ }
5497
+ return node.children.flatMap(function (child) { return tslib.__spreadArray([
5498
+ child.id
5499
+ ], tslib.__read(collectDescendantKeys(child)), false); });
5500
+ }
5501
+ /** Ids of all disabled nodes (rendered disabled / non-selectable). */
5502
+ function collectDisabledKeys(nodes) {
5503
+ 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); });
5504
+ }
5505
+ /**
5506
+ * Toggle a single node, applying cascade per the options (multiple mode only):
5507
+ * - selecting + `cascadeSelect`: also selects all (non-disabled) descendants.
5508
+ * - deselecting + `cascadeDeselect`: also deselects all descendants.
5509
+ *
5510
+ * In `single` mode only the clicked node is selected (clicking it again clears
5511
+ * it); cascade does not apply.
5512
+ */
5513
+ function toggleSelection(nodes, previous, key, selectionMode, _a) {
5514
+ var cascadeSelect = _a.cascadeSelect, cascadeDeselect = _a.cascadeDeselect;
5515
+ if (selectionMode === 'single') {
5516
+ var result_1 = new Set();
5517
+ if (!previous.has(key)) {
5518
+ result_1.add(key);
5519
+ }
5520
+ return result_1;
5521
+ }
5522
+ var result = new Set(previous);
5523
+ var node = findNode(nodes, key);
5524
+ var descendants = node ? collectDescendantKeys(node) : [];
5525
+ var disabled = new Set(collectDisabledKeys(nodes));
5526
+ if (!previous.has(key)) {
5527
+ result.add(key);
5528
+ if (cascadeSelect) {
5529
+ descendants.forEach(function (k) {
5530
+ if (!disabled.has(k)) {
5531
+ result.add(k);
5532
+ }
5533
+ });
5534
+ }
5535
+ }
5536
+ else {
5537
+ result.delete(key);
5538
+ if (cascadeDeselect) {
5539
+ descendants.forEach(function (k) { return result.delete(k); });
5540
+ }
5541
+ }
5542
+ return result;
5543
+ }
5544
+ /**
5545
+ * Apply react-aria's proposed selection while enforcing cascade. Each key
5546
+ * react-aria added cascades to its descendants when `cascadeSelect` is set; each
5547
+ * key it removed cascades when `cascadeDeselect` is set. In non-multiple modes
5548
+ * (or with both toggles off) the proposed selection is used as-is.
5549
+ */
5550
+ function applyCascade(nodes, previous, next, selectionMode, _a) {
5551
+ var cascadeSelect = _a.cascadeSelect, cascadeDeselect = _a.cascadeDeselect;
5552
+ if (selectionMode !== 'multiple' || (!cascadeSelect && !cascadeDeselect)) {
5553
+ return next;
5554
+ }
5555
+ var result = new Set(previous);
5556
+ var added = tslib.__spreadArray([], tslib.__read(next), false).filter(function (key) { return !previous.has(key); });
5557
+ var removed = tslib.__spreadArray([], tslib.__read(previous), false).filter(function (key) { return !next.has(key); });
5558
+ var disabled = new Set(collectDisabledKeys(nodes));
5559
+ added.forEach(function (key) {
5560
+ result.add(key);
5561
+ if (cascadeSelect) {
5562
+ var node = findNode(nodes, key);
5563
+ (node ? collectDescendantKeys(node) : []).forEach(function (k) {
5564
+ if (!disabled.has(k)) {
5565
+ result.add(k);
5566
+ }
5567
+ });
5568
+ }
5569
+ });
5570
+ removed.forEach(function (key) {
5571
+ result.delete(key);
5572
+ if (cascadeDeselect) {
5573
+ var node = findNode(nodes, key);
5574
+ (node ? collectDescendantKeys(node) : []).forEach(function (k) {
5575
+ return result.delete(k);
5576
+ });
5577
+ }
5578
+ });
5579
+ return result;
5580
+ }
5581
+
5582
+ var TreeView = React.forwardRef(function (_a, ref) {
5583
+ 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"]);
5584
+ var _e = tslib.__read(React.useState(new Set()), 2), selectedKeys = _e[0], setSelectedKeys = _e[1];
5585
+ var cascade = { cascadeSelect: cascadeSelect, cascadeDeselect: cascadeDeselect };
5586
+ // Cascade only applies to multiple selection.
5587
+ var isCascade = selectionMode === 'multiple' && (cascadeSelect || cascadeDeselect);
5588
+ // Selection driven by react-aria (row/checkbox press, keyboard). When
5589
+ // cascading, reconcile the proposed change; otherwise store react-aria's
5590
+ // selection as-is so the `'all'` sentinel (Ctrl+A) is preserved.
5591
+ var handleSelectionChange = function (selection) {
5592
+ setSelectedKeys(function (prev) {
5593
+ return isCascade
5594
+ ? applyCascade(items, toKeySet(prev, items), toKeySet(selection, items), selectionMode, cascade)
5595
+ : selection;
5441
5596
  });
5442
- onAction === null || onAction === void 0 ? void 0 : onAction(key);
5443
5597
  };
5444
- var actionProps = onAction
5445
- ? {
5446
- onAction: handleAction,
5447
- selectedKeys: selectedKeys,
5448
- onSelectionChange: setSelectedKeys
5598
+ // When `onAction` is set, react-aria treats a row press as an action rather
5599
+ // than a selection, so we toggle selection here ourselves.
5600
+ var handleAction = function (key) {
5601
+ if (selectionMode !== 'none') {
5602
+ setSelectedKeys(function (prev) {
5603
+ return toggleSelection(items, toKeySet(prev, items), key, selectionMode, cascade);
5604
+ });
5449
5605
  }
5606
+ onAction === null || onAction === void 0 ? void 0 : onAction(key);
5607
+ };
5608
+ // Disabled nodes are non-selectable; react-aria disables them via disabledKeys.
5609
+ var disabledKeys = React.useMemo(function () { return collectDisabledKeys(items); }, [items]);
5610
+ // Cascade requires controlling selection. Without it, preserve the original
5611
+ // behavior: selection is only controlled when an `onAction` handler is set.
5612
+ var selectionProps = selectionMode !== 'none' && (isCascade || onAction)
5613
+ ? { selectedKeys: selectedKeys, onSelectionChange: handleSelectionChange }
5450
5614
  : {};
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))); })));
5615
+ 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
5616
  });
5453
5617
  TreeView.displayName = 'TreeView';
5454
5618