@deque/cauldron-react 7.1.0-canary.9946c2dc → 7.1.0-canary.9e9bd2aa

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