@deque/cauldron-react 6.12.0-canary.4505ef2e → 6.12.0-canary.775bed0e

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/lib/index.js CHANGED
@@ -8,8 +8,9 @@ var classNames = require('classnames');
8
8
  var nextId = require('react-id-generator');
9
9
  var keyname = require('keyname');
10
10
  var reactDom = require('react-dom');
11
- var FocusTrap = require('focus-trap-react');
12
- var reactPopper = require('react-popper');
11
+ var focusable = require('focusable');
12
+ var dom = require('@floating-ui/dom');
13
+ var reactDom$1 = require('@floating-ui/react-dom');
13
14
  var SyntaxHighlighter = require('react-syntax-highlighter/dist/cjs/light');
14
15
  var js = require('react-syntax-highlighter/dist/cjs/languages/hljs/javascript');
15
16
  var css = require('react-syntax-highlighter/dist/cjs/languages/hljs/css');
@@ -22,7 +23,7 @@ var React__default = /*#__PURE__*/_interopDefaultLegacy(React);
22
23
  var classNames__default = /*#__PURE__*/_interopDefaultLegacy(classNames);
23
24
  var nextId__default = /*#__PURE__*/_interopDefaultLegacy(nextId);
24
25
  var keyname__default = /*#__PURE__*/_interopDefaultLegacy(keyname);
25
- var FocusTrap__default = /*#__PURE__*/_interopDefaultLegacy(FocusTrap);
26
+ var focusable__default = /*#__PURE__*/_interopDefaultLegacy(focusable);
26
27
  var SyntaxHighlighter__default = /*#__PURE__*/_interopDefaultLegacy(SyntaxHighlighter);
27
28
  var js__default = /*#__PURE__*/_interopDefaultLegacy(js);
28
29
  var css__default = /*#__PURE__*/_interopDefaultLegacy(css);
@@ -1341,133 +1342,277 @@ var AriaIsolate = /** @class */ (function () {
1341
1342
  return AriaIsolate;
1342
1343
  }());
1343
1344
 
1344
- var isEscape = function (event) {
1345
- return event.key === 'Escape' || event.key === 'Esc' || event.keyCode === 27;
1346
- };
1347
- var noop = function () {
1348
- //not empty
1345
+ /**
1346
+ * When a component needs to track an internal ref on a component that has a
1347
+ * forwarded ref, useSharedRef will return a MutableRefObject<T> that will
1348
+ * correctly invoke the parent ref as well providing an internal ref.
1349
+ *
1350
+ * @example
1351
+ * React.forwardRef(function Component({ children }, ref) {
1352
+ * const internalRef = useSharedRef<HTMLElement>(ref)
1353
+ * if (internalRef.current) {
1354
+ * // do something with the internal ref...
1355
+ * }
1356
+ * return (<div ref={internalRef}>...</div>)
1357
+ * })
1358
+ */
1359
+ function useSharedRef(ref) {
1360
+ var internalRef = React.useRef();
1361
+ React.useEffect(function () {
1362
+ setRef(ref, internalRef.current);
1363
+ }, [ref]);
1364
+ return internalRef;
1365
+ }
1366
+
1367
+ // When multiple focus traps are created, we need to keep track of all previous traps
1368
+ // in the stack and temporarily suspend any traps created before the most recent trap
1369
+ var focusTrapStack = [];
1370
+ var removeFocusTrapFromStack = function (focusTrap) {
1371
+ var focusTrapIndex = focusTrapStack.findIndex(function (trap) { return focusTrap.targetElement === trap.targetElement; });
1372
+ focusTrapStack.splice(focusTrapIndex, 1);
1349
1373
  };
1350
- var Dialog = /** @class */ (function (_super) {
1351
- tslib.__extends(Dialog, _super);
1352
- function Dialog(props) {
1353
- var _this = _super.call(this, props) || this;
1354
- _this.headingId = nextId__default["default"]('dialog-title-');
1355
- _this.close = _this.close.bind(_this);
1356
- _this.focusHeading = _this.focusHeading.bind(_this);
1357
- _this.handleClickOutside = _this.handleClickOutside.bind(_this);
1358
- _this.handleEscape = _this.handleEscape.bind(_this);
1359
- _this.state = {};
1360
- return _this;
1374
+ function getActiveElement(target) {
1375
+ var _a;
1376
+ return (((_a = target === null || target === void 0 ? void 0 : target.ownerDocument.activeElement) !== null && _a !== void 0 ? _a : document.activeElement) ||
1377
+ document.body);
1378
+ }
1379
+ function elementContains(containerElement, targetElement) {
1380
+ if (!targetElement) {
1381
+ return false;
1361
1382
  }
1362
- Dialog.prototype.componentDidMount = function () {
1363
- var _this = this;
1364
- if (this.props.show) {
1365
- this.attachEventListeners();
1366
- this.attachIsolator(function () { return setTimeout(_this.focusHeading); });
1383
+ if (containerElement.getRootNode() === targetElement.getRootNode()) {
1384
+ return containerElement.contains(targetElement);
1385
+ }
1386
+ var root = targetElement.getRootNode();
1387
+ while (root && root !== containerElement.getRootNode()) {
1388
+ if (root.nodeType === Node.DOCUMENT_FRAGMENT_NODE) {
1389
+ // likely a shadow root, and we need to get the host
1390
+ root = root.host;
1367
1391
  }
1392
+ else {
1393
+ break;
1394
+ }
1395
+ }
1396
+ return root && containerElement.contains(root);
1397
+ }
1398
+ function createTrapGuard() {
1399
+ var trapGuard = document.createElement('span');
1400
+ trapGuard.setAttribute('tabindex', '0');
1401
+ trapGuard.setAttribute('aria-hidden', 'true');
1402
+ return trapGuard;
1403
+ }
1404
+ function createFocusTrap(targetElement, initialFocusElement) {
1405
+ var _a;
1406
+ var startGuard = createTrapGuard();
1407
+ var endGuard = createTrapGuard();
1408
+ targetElement.insertAdjacentElement('beforebegin', startGuard);
1409
+ targetElement.insertAdjacentElement('afterend', endGuard);
1410
+ var focusTrapMetadata = {
1411
+ targetElement: targetElement,
1412
+ lastFocusedElement: null,
1413
+ suspended: false
1368
1414
  };
1369
- Dialog.prototype.componentWillUnmount = function () {
1370
- var isolator = this.state.isolator;
1371
- isolator === null || isolator === void 0 ? void 0 : isolator.deactivate();
1372
- this.removeEventListeners();
1373
- };
1374
- Dialog.prototype.componentDidUpdate = function (prevProps) {
1375
- if (!prevProps.show && this.props.show) {
1376
- this.attachIsolator(this.focusHeading);
1377
- this.attachEventListeners();
1415
+ var focusListener = function (event) {
1416
+ var _a, _b, _c, _d;
1417
+ var eventTarget = event.target;
1418
+ var elementContainsTarget = elementContains(targetElement, eventTarget);
1419
+ if (focusTrapMetadata.suspended) {
1420
+ return;
1378
1421
  }
1379
- else if (prevProps.show && !this.props.show) {
1380
- this.removeEventListeners();
1381
- this.close();
1422
+ if (!elementContainsTarget) {
1423
+ // If the event target element is not contained within the target element
1424
+ // for this focus trap, we need to prevent focus from escaping the container
1425
+ event.stopImmediatePropagation();
1382
1426
  }
1383
- };
1384
- Dialog.prototype.attachIsolator = function (done) {
1385
- this.setState({
1386
- isolator: new AriaIsolate(this.element)
1387
- }, done);
1388
- };
1389
- Dialog.prototype.render = function () {
1390
- var _this = this;
1391
- var _a = this.props, dialogRef = _a.dialogRef, forceAction = _a.forceAction, className = _a.className, children = _a.children, closeButtonText = _a.closeButtonText, heading = _a.heading, show = _a.show, other = tslib.__rest(_a, ["dialogRef", "forceAction", "className", "children", "closeButtonText", "heading", "show"]);
1392
- if (!show || !isBrowser()) {
1393
- return null;
1427
+ else if (eventTarget instanceof HTMLElement) {
1428
+ // Ensure we keep track of the most recent valid focus element if we
1429
+ // need to redirect focus later
1430
+ focusTrapMetadata.lastFocusedElement = eventTarget;
1431
+ return;
1394
1432
  }
1395
- var portal = this.props.portal || document.body;
1396
- var close = !forceAction ? (React__default["default"].createElement("button", { className: "Dialog__close", type: "button", onClick: this.close },
1397
- React__default["default"].createElement(Icon, { type: "close", "aria-hidden": "true" }),
1398
- React__default["default"].createElement(Offscreen, null, closeButtonText))) : null;
1399
- var Heading = "h".concat(typeof heading === 'object' && 'level' in heading && !!heading.level
1400
- ? heading.level
1401
- : 2);
1402
- var Dialog = (React__default["default"].createElement(FocusTrap__default["default"], { focusTrapOptions: {
1403
- allowOutsideClick: true,
1404
- escapeDeactivates: false,
1405
- fallbackFocus: '.Dialog__heading'
1406
- } },
1407
- React__default["default"].createElement(ClickOutsideListener$1, { onClickOutside: this.handleClickOutside },
1408
- React__default["default"].createElement("div", tslib.__assign({ role: "dialog", className: classNames__default["default"]('Dialog', className, {
1409
- 'Dialog--show': show
1410
- }), ref: function (el) {
1411
- _this.element = el;
1412
- if (!dialogRef) {
1413
- return;
1414
- }
1415
- setRef(dialogRef, el);
1416
- }, "aria-labelledby": this.headingId }, other),
1417
- React__default["default"].createElement("div", { className: "Dialog__inner" },
1418
- React__default["default"].createElement("div", { className: "Dialog__header" },
1419
- React__default["default"].createElement(Heading, { className: "Dialog__heading", ref: function (el) { return (_this.heading = el); }, tabIndex: -1, id: this.headingId }, typeof heading === 'object' && 'text' in heading
1420
- ? heading.text
1421
- : heading),
1422
- close),
1423
- children)))));
1424
- return reactDom.createPortal(Dialog, ('current' in portal ? portal.current : portal) || document.body);
1425
- };
1426
- Dialog.prototype.close = function () {
1427
- var _a, _b, _c;
1428
- (_a = this.state.isolator) === null || _a === void 0 ? void 0 : _a.deactivate();
1429
- if (this.props.show) {
1430
- (_c = (_b = this.props).onClose) === null || _c === void 0 ? void 0 : _c.call(_b);
1433
+ var focusableElements = Array.from((targetElement === null || targetElement === void 0 ? void 0 : targetElement.querySelectorAll(focusable__default["default"])) || []);
1434
+ // If focus reaches the trap guards, we need to wrap focus around to the leading
1435
+ // or trailing focusable element depending on which guard obtained focus
1436
+ if (focusableElements.length && eventTarget === startGuard) {
1437
+ (_a = focusableElements.reverse()[0]) === null || _a === void 0 ? void 0 : _a.focus();
1438
+ return;
1431
1439
  }
1432
- };
1433
- Dialog.prototype.handleClickOutside = function () {
1434
- var _a = this.props, show = _a.show, forceAction = _a.forceAction;
1435
- if (show && !forceAction) {
1436
- this.close();
1440
+ else if (focusableElements.length && eventTarget === endGuard) {
1441
+ (_b = focusableElements[0]) === null || _b === void 0 ? void 0 : _b.focus();
1442
+ return;
1443
+ }
1444
+ // If focus somehow escaped the trap, we need to try to restore focus to
1445
+ // to a suitable focusable element within the focus trap target. Otherwise
1446
+ // we'll need to focus on an alternative within the container.
1447
+ if (elementContains(targetElement, focusTrapMetadata.lastFocusedElement)) {
1448
+ (_c = focusTrapMetadata.lastFocusedElement) === null || _c === void 0 ? void 0 : _c.focus();
1449
+ }
1450
+ else if (focusableElements.length) {
1451
+ (_d = focusableElements[0]) === null || _d === void 0 ? void 0 : _d.focus();
1452
+ }
1453
+ else {
1454
+ // if there are no focusable elements, just focus the container
1455
+ targetElement.focus();
1437
1456
  }
1438
1457
  };
1439
- Dialog.prototype.focusHeading = function () {
1458
+ document.addEventListener('focus', focusListener, true);
1459
+ if (focusTrapStack.length >= 1) {
1460
+ // Suspend any other traps in the stack while this one is active
1461
+ focusTrapStack.forEach(function (trap) {
1462
+ trap.suspended = true;
1463
+ });
1464
+ }
1465
+ focusTrapStack.push(focusTrapMetadata);
1466
+ if (initialFocusElement) {
1467
+ initialFocusElement.focus();
1468
+ }
1469
+ else {
1470
+ // Try to find a suitable focus element
1471
+ var focusableElements = Array.from((targetElement === null || targetElement === void 0 ? void 0 : targetElement.querySelectorAll(focusable__default["default"])) ||
1472
+ /* istanbul ignore else */ []);
1473
+ (_a = focusableElements[0]) === null || _a === void 0 ? void 0 : _a.focus();
1474
+ }
1475
+ return tslib.__assign(tslib.__assign({}, focusTrapMetadata), { initialFocusElement: initialFocusElement, destroy: function () {
1476
+ var _a, _b;
1477
+ document.removeEventListener('focus', focusListener, true);
1478
+ removeFocusTrapFromStack(focusTrapMetadata);
1479
+ (_a = startGuard.parentNode) === null || _a === void 0 ? void 0 : _a.removeChild(startGuard);
1480
+ (_b = endGuard.parentNode) === null || _b === void 0 ? void 0 : _b.removeChild(endGuard);
1481
+ // If there are any remaining focus traps in the stack, we need
1482
+ // to unsuspend the most recently added focus trap
1483
+ if (focusTrapStack.length) {
1484
+ focusTrapStack[focusTrapStack.length - 1].suspended = false;
1485
+ }
1486
+ } });
1487
+ }
1488
+ function useFocusTrap(target, options) {
1489
+ if (options === void 0) { options = {}; }
1490
+ 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;
1491
+ var focusTrap = React.useRef(null);
1492
+ var returnFocusElementRef = React.useRef();
1493
+ function restoreFocusToReturnFocusElement() {
1440
1494
  var _a;
1441
- if (this.heading) {
1442
- this.heading.focus();
1495
+ var resolvedReturnFocusElement = resolveElement(returnFocusElement);
1496
+ if (resolvedReturnFocusElement instanceof HTMLElement) {
1497
+ resolvedReturnFocusElement.focus();
1443
1498
  }
1444
- (_a = this.state.isolator) === null || _a === void 0 ? void 0 : _a.activate();
1445
- };
1446
- Dialog.prototype.handleEscape = function (keyboardEvent) {
1499
+ else {
1500
+ (_a = returnFocusElementRef.current) === null || _a === void 0 ? void 0 : _a.focus();
1501
+ returnFocusElementRef.current = null;
1502
+ }
1503
+ }
1504
+ React.useEffect(function () {
1505
+ var targetElement = resolveElement(target);
1506
+ var initialFocusElement = resolveElement(initialFocusElementOrRef);
1507
+ if (!targetElement || disabled) {
1508
+ return;
1509
+ }
1510
+ returnFocusElementRef.current = getActiveElement(targetElement);
1511
+ focusTrap.current = createFocusTrap(targetElement, initialFocusElement);
1512
+ return function () {
1513
+ var _a;
1514
+ (_a = focusTrap.current) === null || _a === void 0 ? void 0 : _a.destroy();
1515
+ focusTrap.current = null;
1516
+ // istanbul ignore else
1517
+ if (returnFocus) {
1518
+ restoreFocusToReturnFocusElement();
1519
+ }
1520
+ };
1521
+ }, [target, disabled]);
1522
+ return focusTrap;
1523
+ }
1524
+
1525
+ var isEscape = function (event) {
1526
+ return event.key === 'Escape' || event.key === 'Esc' || event.keyCode === 27;
1527
+ };
1528
+ var Dialog = React.forwardRef(function (_a, ref) {
1529
+ var dialogRefProp = _a.dialogRef, _b = _a.forceAction, forceAction = _b === void 0 ? false : _b, className = _a.className, children = _a.children, _c = _a.closeButtonText, closeButtonText = _c === void 0 ? 'Close' : _c, heading = _a.heading, _d = _a.show, show = _d === void 0 ? false : _d, portal = _a.portal, _e = _a.onClose, onClose = _e === void 0 ? function () { return null; } : _e, other = tslib.__rest(_a, ["dialogRef", "forceAction", "className", "children", "closeButtonText", "heading", "show", "portal", "onClose"]);
1530
+ var dialogRef = useSharedRef(dialogRefProp || ref);
1531
+ var _f = tslib.__read(nextId.useId(1, 'dialog-title-'), 1), headingId = _f[0];
1532
+ var headingRef = React.useRef(null);
1533
+ var isolatorRef = React.useRef();
1534
+ var handleClose = React.useCallback(function () {
1535
+ var _a;
1536
+ (_a = isolatorRef.current) === null || _a === void 0 ? void 0 : _a.deactivate();
1537
+ if (show) {
1538
+ onClose();
1539
+ }
1540
+ }, [show, onClose]);
1541
+ var handleClickOutside = React.useCallback(function () {
1542
+ if (show && !forceAction) {
1543
+ handleClose();
1544
+ }
1545
+ }, [show, forceAction, handleClose]);
1546
+ var focusHeading = React.useCallback(function () {
1547
+ var _a, _b;
1548
+ (_a = headingRef.current) === null || _a === void 0 ? void 0 : _a.focus();
1549
+ (_b = isolatorRef.current) === null || _b === void 0 ? void 0 : _b.activate();
1550
+ }, []);
1551
+ var handleEscape = React.useCallback(function (keyboardEvent) {
1447
1552
  if (!keyboardEvent.defaultPrevented && isEscape(keyboardEvent)) {
1448
- this.close();
1553
+ handleClose();
1449
1554
  }
1450
- };
1451
- Dialog.prototype.attachEventListeners = function () {
1452
- var forceAction = this.props.forceAction;
1555
+ }, [handleClose]);
1556
+ React.useEffect(function () {
1557
+ if (!show || !dialogRef.current)
1558
+ return;
1559
+ isolatorRef.current = new AriaIsolate(dialogRef.current);
1560
+ setTimeout(focusHeading);
1561
+ return function () {
1562
+ var _a;
1563
+ (_a = isolatorRef.current) === null || _a === void 0 ? void 0 : _a.deactivate();
1564
+ };
1565
+ }, [show, focusHeading]);
1566
+ React.useEffect(function () {
1453
1567
  if (!forceAction) {
1454
- var portal = this.props.portal || document.body;
1455
- var targetElement = portal instanceof HTMLElement ? portal : portal.current;
1456
- targetElement === null || targetElement === void 0 ? void 0 : targetElement.addEventListener('keyup', this.handleEscape);
1568
+ var portalElement_1 = portal
1569
+ ? 'current' in portal
1570
+ ? portal.current
1571
+ : portal
1572
+ : document.body;
1573
+ if (show) {
1574
+ portalElement_1 === null || portalElement_1 === void 0 ? void 0 : portalElement_1.addEventListener('keyup', handleEscape);
1575
+ }
1576
+ return function () {
1577
+ portalElement_1 === null || portalElement_1 === void 0 ? void 0 : portalElement_1.removeEventListener('keyup', handleEscape);
1578
+ };
1457
1579
  }
1458
- };
1459
- Dialog.prototype.removeEventListeners = function () {
1460
- var portal = this.props.portal || document.body;
1461
- var targetElement = portal instanceof HTMLElement ? portal : portal.current;
1462
- targetElement === null || targetElement === void 0 ? void 0 : targetElement.removeEventListener('keyup', this.handleEscape);
1463
- };
1464
- Dialog.defaultProps = {
1465
- onClose: noop,
1466
- forceAction: false,
1467
- closeButtonText: 'Close'
1468
- };
1469
- return Dialog;
1470
- }(React__default["default"].Component));
1580
+ }, [show, forceAction, portal, handleEscape]);
1581
+ useFocusTrap(dialogRef, {
1582
+ disabled: !show,
1583
+ initialFocusElement: headingRef
1584
+ });
1585
+ if (!show || !isBrowser()) {
1586
+ return null;
1587
+ }
1588
+ var portalElement = portal
1589
+ ? 'current' in portal
1590
+ ? portal.current
1591
+ : portal
1592
+ : // eslint-disable-next-line ssr-friendly/no-dom-globals-in-react-fc
1593
+ document.body;
1594
+ var closeButton = !forceAction ? (React__default["default"].createElement("button", { className: "Dialog__close", type: "button", onClick: handleClose },
1595
+ React__default["default"].createElement(Icon, { type: "close", "aria-hidden": "true" }),
1596
+ React__default["default"].createElement(Offscreen, null, closeButtonText))) : null;
1597
+ var HeadingLevel = "h".concat(typeof heading === 'object' && 'level' in heading && heading.level
1598
+ ? heading.level
1599
+ : 2);
1600
+ var dialog = (React__default["default"].createElement(ClickOutsideListener$1, { onClickOutside: handleClickOutside },
1601
+ React__default["default"].createElement("div", tslib.__assign({ role: "dialog", className: classNames__default["default"]('Dialog', className, {
1602
+ 'Dialog--show': show
1603
+ }), ref: dialogRef, "aria-labelledby": headingId }, other),
1604
+ React__default["default"].createElement("div", { className: "Dialog__inner" },
1605
+ React__default["default"].createElement("div", { className: "Dialog__header" },
1606
+ React__default["default"].createElement(HeadingLevel, { className: "Dialog__heading", ref: headingRef, tabIndex: -1, id: headingId }, typeof heading === 'object' && 'text' in heading
1607
+ ? heading.text
1608
+ : heading),
1609
+ closeButton),
1610
+ children))));
1611
+ return reactDom.createPortal(dialog,
1612
+ // eslint-disable-next-line ssr-friendly/no-dom-globals-in-react-fc
1613
+ portalElement || document.body);
1614
+ });
1615
+ Dialog.displayName = 'Dialog';
1471
1616
  var DialogContent = function (_a) {
1472
1617
  var children = _a.children, className = _a.className, align = _a.align, other = tslib.__rest(_a, ["children", "className", "align"]);
1473
1618
  return (React__default["default"].createElement("div", tslib.__assign({ className: classNames__default["default"]('Dialog__content', className, {
@@ -1583,43 +1728,6 @@ var Button = React.forwardRef(function (_a, ref) {
1583
1728
  });
1584
1729
  Button.displayName = 'Button';
1585
1730
 
1586
- /**
1587
- * Returns a unique set of id refs from the provided string
1588
- * @param ids - string of id refs
1589
- */
1590
- function idRefs(ids) {
1591
- if (!ids || !ids.trim()) {
1592
- return new Set();
1593
- }
1594
- return new Set(ids.trim().split(/\s+/));
1595
- }
1596
- /**
1597
- * Returns an updated id ref string with the provided id value added
1598
- * @param ids - string of id refs
1599
- * @param id - id to add
1600
- */
1601
- function addIdRef(ids, id) {
1602
- return tslib.__spreadArray([], tslib.__read(idRefs(ids).add(id)), false).join(' ');
1603
- }
1604
- /**
1605
- * Returns an updated id ref string with the provided id value removed
1606
- * @param ids - string of id refs
1607
- * @param id - id to remove
1608
- */
1609
- function removeIdRef(_ids, id) {
1610
- var ids = idRefs(_ids);
1611
- ids.delete(id);
1612
- return tslib.__spreadArray([], tslib.__read(ids), false).join(' ');
1613
- }
1614
- /**
1615
- * Returns if an id ref string contains the provided id value
1616
- * @param ids - string of id refs
1617
- * @param id - id to check if it exists in the provided idRef string
1618
- */
1619
- function hasIdRef(ids, id) {
1620
- return idRefs(ids).has(id);
1621
- }
1622
-
1623
1731
  var isEscapeKey = function (event) {
1624
1732
  return event.key === 'Escape' || event.key === 'Esc' || event.keyCode === 27;
1625
1733
  };
@@ -1660,6 +1768,99 @@ function useEscapeKey(options, dependencies) {
1660
1768
  ], tslib.__read(dependencies), false));
1661
1769
  }
1662
1770
 
1771
+ function getAutoAlignment(placement) {
1772
+ switch (placement) {
1773
+ case 'auto-start':
1774
+ return 'start';
1775
+ case 'auto-end':
1776
+ return 'end';
1777
+ default:
1778
+ return null;
1779
+ }
1780
+ }
1781
+ var AnchoredOverlay = React.forwardRef(function (_a, refProp) {
1782
+ var as = _a.as, _b = _a.placement, initialPlacement = _b === void 0 ? 'auto' : _b, target = _a.target, children = _a.children, style = _a.style, _c = _a.open, open = _c === void 0 ? false : _c, offset = _a.offset, onOpenChange = _a.onOpenChange, onPlacementChange = _a.onPlacementChange, props = tslib.__rest(_a, ["as", "placement", "target", "children", "style", "open", "offset", "onOpenChange", "onPlacementChange"]);
1783
+ var ref = useSharedRef(refProp);
1784
+ var Component = as || 'div';
1785
+ var _d = reactDom$1.useFloating({
1786
+ open: open,
1787
+ // default to initial placement on top when placement is auto
1788
+ // @ts-expect-error auto placement is not a valid placement for floating-ui
1789
+ placement: initialPlacement.startsWith('auto') ? 'top' : initialPlacement,
1790
+ middleware: [
1791
+ reactDom$1.offset(offset !== null && offset !== void 0 ? offset : 0),
1792
+ initialPlacement.startsWith('auto')
1793
+ ? reactDom$1.autoPlacement({
1794
+ alignment: getAutoAlignment(initialPlacement)
1795
+ })
1796
+ : reactDom$1.flip()
1797
+ ].filter(Boolean),
1798
+ elements: {
1799
+ reference: resolveElement(target),
1800
+ floating: ref.current
1801
+ },
1802
+ whileElementsMounted: dom.autoUpdate
1803
+ }), floatingStyles = _d.floatingStyles, placement = _d.placement;
1804
+ useEscapeKey({
1805
+ active: open,
1806
+ capture: true,
1807
+ defaultPrevented: true,
1808
+ callback: function (event) {
1809
+ // when an anchored overlay is open, we want to prevent other potential "escape"
1810
+ // keypress events, like the closing of modals from occurring
1811
+ event.preventDefault();
1812
+ // istanbul ignore else
1813
+ if (typeof onOpenChange === 'function') {
1814
+ onOpenChange(!open);
1815
+ }
1816
+ }
1817
+ });
1818
+ React.useEffect(function () {
1819
+ if (typeof onPlacementChange === 'function') {
1820
+ onPlacementChange(placement);
1821
+ }
1822
+ }, [placement]);
1823
+ return (React__default["default"].createElement(Component, tslib.__assign({ ref: ref }, props, { style: tslib.__assign(tslib.__assign({}, floatingStyles), style) }), children));
1824
+ });
1825
+ AnchoredOverlay.displayName = 'AnchoredOverlay';
1826
+
1827
+ /**
1828
+ * Returns a unique set of id refs from the provided string
1829
+ * @param ids - string of id refs
1830
+ */
1831
+ function idRefs(ids) {
1832
+ if (!ids || !ids.trim()) {
1833
+ return new Set();
1834
+ }
1835
+ return new Set(ids.trim().split(/\s+/));
1836
+ }
1837
+ /**
1838
+ * Returns an updated id ref string with the provided id value added
1839
+ * @param ids - string of id refs
1840
+ * @param id - id to add
1841
+ */
1842
+ function addIdRef(ids, id) {
1843
+ return tslib.__spreadArray([], tslib.__read(idRefs(ids).add(id)), false).join(' ');
1844
+ }
1845
+ /**
1846
+ * Returns an updated id ref string with the provided id value removed
1847
+ * @param ids - string of id refs
1848
+ * @param id - id to remove
1849
+ */
1850
+ function removeIdRef(_ids, id) {
1851
+ var ids = idRefs(_ids);
1852
+ ids.delete(id);
1853
+ return tslib.__spreadArray([], tslib.__read(ids), false).join(' ');
1854
+ }
1855
+ /**
1856
+ * Returns if an id ref string contains the provided id value
1857
+ * @param ids - string of id refs
1858
+ * @param id - id to check if it exists in the provided idRef string
1859
+ */
1860
+ function hasIdRef(ids, id) {
1861
+ return idRefs(ids).has(id);
1862
+ }
1863
+
1663
1864
  var TIP_HIDE_DELAY = 100;
1664
1865
  // fires a custom "cauldron:tooltip:show" / "cauldron:tooltip:hide" event
1665
1866
  // to allow projects using cauldron to hook into when a tooltip is shown/hidden
@@ -1678,50 +1879,27 @@ function Tooltip(_a) {
1678
1879
  var _g = tslib.__read(propId ? [propId] : nextId.useId(1, 'tooltip'), 1), id = _g[0];
1679
1880
  var hideTimeoutRef = React.useRef(null);
1680
1881
  var _h = tslib.__read(React.useState(!!showProp || defaultShow), 2), showTooltip = _h[0], setShowTooltip = _h[1];
1681
- var _j = tslib.__read(React.useState(null), 2), targetElement = _j[0], setTargetElement = _j[1];
1682
- var _k = tslib.__read(React.useState(null), 2), tooltipElement = _k[0], setTooltipElement = _k[1];
1683
- var _l = tslib.__read(React.useState(null), 2), arrowElement = _l[0], setArrowElement = _l[1];
1882
+ var _j = tslib.__read(React.useState(null), 2), tooltipElement = _j[0], setTooltipElement = _j[1];
1883
+ var _k = tslib.__read(React.useState(initialPlacement), 2), placement = _k[0], setPlacement = _k[1];
1684
1884
  var hasAriaAssociation = association !== 'none';
1685
- var _m = reactPopper.usePopper(targetElement, tooltipElement, {
1686
- placement: initialPlacement,
1687
- modifiers: [
1688
- { name: 'preventOverflow', options: { padding: 8 } },
1689
- {
1690
- name: 'flip',
1691
- options: { fallbackPlacements: ['left', 'right', 'top', 'bottom'] }
1692
- },
1693
- { name: 'offset', options: { offset: [0, 8] } },
1694
- { name: 'arrow', options: { padding: 5, element: arrowElement } }
1695
- ]
1696
- }), styles = _m.styles, attributes = _m.attributes, update = _m.update;
1697
1885
  // Show the tooltip
1698
1886
  var show = React.useCallback(function () { return tslib.__awaiter(_this, void 0, void 0, function () {
1887
+ var targetElement;
1699
1888
  return tslib.__generator(this, function (_a) {
1700
- switch (_a.label) {
1701
- case 0:
1702
- // Clear the hide timeout if there was one pending
1703
- if (hideTimeoutRef.current) {
1704
- clearTimeout(hideTimeoutRef.current);
1705
- hideTimeoutRef.current = null;
1706
- }
1707
- if (!update) return [3 /*break*/, 2];
1708
- return [4 /*yield*/, update()];
1709
- case 1:
1710
- _a.sent();
1711
- _a.label = 2;
1712
- case 2:
1713
- setShowTooltip(true);
1714
- fireCustomEvent(true, targetElement);
1715
- return [2 /*return*/];
1889
+ targetElement = resolveElement(target);
1890
+ // Clear the hide timeout if there was one pending
1891
+ if (hideTimeoutRef.current) {
1892
+ clearTimeout(hideTimeoutRef.current);
1893
+ hideTimeoutRef.current = null;
1716
1894
  }
1895
+ setShowTooltip(true);
1896
+ fireCustomEvent(true, targetElement);
1897
+ return [2 /*return*/];
1717
1898
  });
1718
- }); }, [
1719
- targetElement,
1720
- // update starts off as null
1721
- update
1722
- ]);
1899
+ }); }, [target]);
1723
1900
  // Hide the tooltip
1724
1901
  var hide = React.useCallback(function () {
1902
+ var targetElement = resolveElement(target);
1725
1903
  if (!hideTimeoutRef.current) {
1726
1904
  hideTimeoutRef.current = setTimeout(function () {
1727
1905
  hideTimeoutRef.current = null;
@@ -1732,32 +1910,15 @@ function Tooltip(_a) {
1732
1910
  return function () {
1733
1911
  clearTimeout(hideTimeoutRef.current);
1734
1912
  };
1735
- }, [targetElement]);
1736
- // Keep targetElement in sync with target prop
1737
- React.useEffect(function () {
1738
- var targetElement = target && 'current' in target ? target.current : target;
1739
- setTargetElement(targetElement);
1740
1913
  }, [target]);
1741
1914
  React.useEffect(function () {
1742
1915
  if (typeof showProp === 'boolean') {
1743
1916
  setShowTooltip(showProp);
1744
1917
  }
1745
1918
  }, [showProp]);
1746
- // Get popper placement
1747
- var placement = (attributes.popper &&
1748
- attributes.popper['data-popper-placement']) ||
1749
- initialPlacement;
1750
- // Only listen to key ups when the tooltip is visible
1751
- useEscapeKey({
1752
- callback: function (event) {
1753
- event.preventDefault();
1754
- setShowTooltip(false);
1755
- },
1756
- capture: true,
1757
- active: showTooltip && typeof showProp !== 'boolean'
1758
- }, [setShowTooltip]);
1759
1919
  // Handle hover and focus events for the targetElement
1760
1920
  React.useEffect(function () {
1921
+ var targetElement = resolveElement(target);
1761
1922
  if (typeof showProp !== 'boolean') {
1762
1923
  targetElement === null || targetElement === void 0 ? void 0 : targetElement.addEventListener('mouseenter', show);
1763
1924
  targetElement === null || targetElement === void 0 ? void 0 : targetElement.addEventListener('mouseleave', hide);
@@ -1770,7 +1931,7 @@ function Tooltip(_a) {
1770
1931
  targetElement === null || targetElement === void 0 ? void 0 : targetElement.removeEventListener('focusin', show);
1771
1932
  targetElement === null || targetElement === void 0 ? void 0 : targetElement.removeEventListener('focusout', hide);
1772
1933
  };
1773
- }, [targetElement, show, hide, showProp]);
1934
+ }, [target, show, hide, showProp]);
1774
1935
  // Handle hover events for the tooltipElement
1775
1936
  React.useEffect(function () {
1776
1937
  if (typeof showProp !== 'boolean') {
@@ -1784,6 +1945,7 @@ function Tooltip(_a) {
1784
1945
  }, [tooltipElement, show, hide, showProp]);
1785
1946
  // Keep the target's id in sync
1786
1947
  React.useEffect(function () {
1948
+ var targetElement = resolveElement(target);
1787
1949
  if (hasAriaAssociation) {
1788
1950
  var idRefs = targetElement === null || targetElement === void 0 ? void 0 : targetElement.getAttribute(association);
1789
1951
  if (!hasIdRef(idRefs, id)) {
@@ -1796,14 +1958,14 @@ function Tooltip(_a) {
1796
1958
  targetElement.setAttribute(association, removeIdRef(idRefs, id));
1797
1959
  }
1798
1960
  };
1799
- }, [targetElement, id, association]);
1961
+ }, [target, id, association]);
1800
1962
  return (React__default["default"].createElement(React__default["default"].Fragment, null, (showTooltip || hideElementOnHidden) && isBrowser()
1801
- ? reactDom.createPortal(React__default["default"].createElement("div", tslib.__assign({ id: id, className: classNames__default["default"]('Tooltip', "Tooltip--".concat(placement), className, {
1963
+ ? reactDom.createPortal(React__default["default"].createElement(AnchoredOverlay, tslib.__assign({ id: id, target: target, placement: initialPlacement, onPlacementChange: setPlacement, open: showTooltip && typeof showProp !== 'boolean', onOpenChange: setShowTooltip, className: classNames__default["default"]('Tooltip', "Tooltip--".concat(placement), className, {
1802
1964
  TooltipInfo: variant === 'info',
1803
1965
  'Tooltip--hidden': !showTooltip && hideElementOnHidden,
1804
1966
  'Tooltip--big': variant === 'big'
1805
- }), ref: setTooltipElement, role: "tooltip", style: styles.popper }, attributes.popper, props),
1806
- variant !== 'big' && (React__default["default"].createElement("div", { className: "TooltipArrow", ref: setArrowElement, style: styles.arrow })),
1967
+ }), ref: setTooltipElement, role: "tooltip", offset: 8 }, props),
1968
+ variant !== 'big' && React__default["default"].createElement("div", { className: "TooltipArrow" }),
1807
1969
  children), (portal && 'current' in portal ? portal.current : portal) ||
1808
1970
  (
1809
1971
  // eslint-disable-next-line ssr-friendly/no-dom-globals-in-react-fc
@@ -2519,28 +2681,6 @@ var SearchField = React.forwardRef(function (_a, ref) {
2519
2681
  });
2520
2682
  SearchField.displayName = 'SearchField';
2521
2683
 
2522
- /**
2523
- * When a component needs to track an internal ref on a component that has a
2524
- * forwarded ref, useSharedRef will return a MutableRefObject<T> that will
2525
- * correctly invoke the parent ref as well providing an internal ref.
2526
- *
2527
- * @example
2528
- * React.forwardRef(function Component({ children }, ref) {
2529
- * const internalRef = useSharedRef<HTMLElement>(ref)
2530
- * if (internalRef.current) {
2531
- * // do something with the internal ref...
2532
- * }
2533
- * return (<div ref={internalRef}>...</div>)
2534
- * })
2535
- */
2536
- function useSharedRef(ref) {
2537
- var internalRef = React.useRef();
2538
- React.useEffect(function () {
2539
- setRef(ref, internalRef.current);
2540
- }, [ref]);
2541
- return internalRef;
2542
- }
2543
-
2544
2684
  function copyTextToClipboard(text) {
2545
2685
  return tslib.__awaiter(this, void 0, void 0, function () {
2546
2686
  var copied, element, range, selection;
@@ -2699,21 +2839,16 @@ var LoaderOverlay = React.forwardRef(function (_a, ref) {
2699
2839
  overlayRef.current.focus();
2700
2840
  }
2701
2841
  }, []);
2702
- var Wrapper = focusTrap ? FocusTrap__default["default"] : React__default["default"].Fragment;
2703
- var wrapperProps = focusTrap
2704
- ? {
2705
- focusTrapOptions: {
2706
- fallbackFocus: '.Loader__overlay'
2707
- }
2708
- }
2709
- : {};
2710
- return (React__default["default"].createElement(Wrapper, tslib.__assign({}, wrapperProps),
2711
- React__default["default"].createElement("div", tslib.__assign({ className: classNames__default["default"]('Loader__overlay', className), ref: overlayRef, tabIndex: -1 }, other),
2712
- React__default["default"].createElement("div", { className: "Loader__overlay__loader" },
2713
- React__default["default"].createElement(Loader, null),
2714
- React__default["default"].createElement(AxeLoader, null)),
2715
- label ? (React__default["default"].createElement("span", { className: "Loader__overlay__label" }, label)) : null,
2716
- children)));
2842
+ useFocusTrap(overlayRef, {
2843
+ disabled: !focusTrap,
2844
+ initialFocusElement: overlayRef
2845
+ });
2846
+ return (React__default["default"].createElement("div", tslib.__assign({ className: classNames__default["default"]('Loader__overlay', className), ref: overlayRef, tabIndex: -1 }, other),
2847
+ React__default["default"].createElement("div", { className: "Loader__overlay__loader" },
2848
+ React__default["default"].createElement(Loader, null),
2849
+ React__default["default"].createElement(AxeLoader, null)),
2850
+ label ? React__default["default"].createElement("span", { className: "Loader__overlay__label" }, label) : null,
2851
+ children));
2717
2852
  });
2718
2853
  LoaderOverlay.displayName = 'LoaderOverlay';
2719
2854
 
@@ -2797,6 +2932,16 @@ function useTable() {
2797
2932
  return React.useContext(TableContext);
2798
2933
  }
2799
2934
 
2935
+ function parseColumnWidth(width) {
2936
+ var number = Number(width);
2937
+ if (!isNaN(number)) {
2938
+ return "".concat(number, "px");
2939
+ }
2940
+ if (!width) {
2941
+ return 'auto';
2942
+ }
2943
+ return width;
2944
+ }
2800
2945
  var Table = React__default["default"].forwardRef(function (_a, ref) {
2801
2946
  var children = _a.children, className = _a.className, variant = _a.variant, layout = _a.layout, _b = _a.columns, columnsProp = _b === void 0 ? [] : _b, style = _a.style, other = tslib.__rest(_a, ["children", "className", "variant", "layout", "columns", "style"]);
2802
2947
  var isGridLayout = layout === 'grid';
@@ -2817,8 +2962,11 @@ var Table = React__default["default"].forwardRef(function (_a, ref) {
2817
2962
  }
2818
2963
  return columns
2819
2964
  .map(function (_a) {
2820
- var width = _a.width;
2821
- return width || 'auto';
2965
+ var width = _a.width, maxWidth = _a.maxWidth;
2966
+ if (maxWidth) {
2967
+ return "minmax(".concat(parseColumnWidth(width), ", ").concat(parseColumnWidth(maxWidth), ")");
2968
+ }
2969
+ return parseColumnWidth(width);
2822
2970
  })
2823
2971
  .join(' ');
2824
2972
  }, [layout, columns]);
@@ -3386,16 +3534,14 @@ var TwoColumnPanel = React.forwardRef(function (_a, ref) {
3386
3534
  setCollapsed(true);
3387
3535
  }
3388
3536
  };
3537
+ useFocusTrap(columnLeftRef, {
3538
+ disabled: !showPanel || !isFocusTrap
3539
+ });
3389
3540
  return (React__default["default"].createElement("div", tslib.__assign({ className: classNames__default["default"]('TwoColumnPanel', className, {
3390
3541
  'TwoColumnPanel--show': !isCollapsed,
3391
3542
  'TwoColumnPanel--hide': isCollapsed
3392
3543
  }) }, props, { ref: ref }),
3393
3544
  React__default["default"].createElement(React__default["default"].Fragment, null,
3394
- React__default["default"].createElement(FocusTrap__default["default"], { active: !isCollapsed && isFocusTrap, focusTrapOptions: {
3395
- escapeDeactivates: true,
3396
- allowOutsideClick: true,
3397
- fallbackFocus: columnLeftRef.current
3398
- }, containerElements: [columnLeftRef.current] }),
3399
3545
  React__default["default"].createElement(ClickOutsideListener$1, { onClickOutside: handleClickOutside, target: columnLeftRef.current }),
3400
3546
  isCollapsed ? null : skipLink,
3401
3547
  showPanel ? ColumnLeftComponent : null,
@@ -3444,19 +3590,21 @@ var ListboxContext = React.createContext({
3444
3590
  options: [],
3445
3591
  active: null,
3446
3592
  selected: null,
3593
+ multiselect: false,
3447
3594
  setOptions: function () { return null; },
3448
3595
  onSelect: function () { return null; }
3449
3596
  });
3450
3597
  function ListboxProvider(_a) {
3451
- var options = _a.options, active = _a.active, selected = _a.selected, setOptions = _a.setOptions, onSelect = _a.onSelect, children = _a.children;
3598
+ var options = _a.options, active = _a.active, selected = _a.selected, multiselect = _a.multiselect, setOptions = _a.setOptions, onSelect = _a.onSelect, children = _a.children;
3452
3599
  var Provider = ListboxContext.Provider;
3453
3600
  var value = React.useMemo(function () { return ({
3454
3601
  options: options,
3455
3602
  active: active,
3456
3603
  selected: selected,
3604
+ multiselect: multiselect,
3457
3605
  setOptions: setOptions,
3458
3606
  onSelect: onSelect
3459
- }); }, [options, active, selected, setOptions]);
3607
+ }); }, [options, active, selected, multiselect, setOptions]);
3460
3608
  return React__default["default"].createElement(Provider, { value: value }, children);
3461
3609
  }
3462
3610
  function useListboxContext() {
@@ -3478,40 +3626,78 @@ var optionMatchesValue = function (option, value) {
3478
3626
  option.value === value;
3479
3627
  };
3480
3628
  var Listbox = React.forwardRef(function (_a, ref) {
3481
- var _b = _a.as, Component = _b === void 0 ? 'ul' : _b, children = _a.children, defaultValue = _a.defaultValue, value = _a.value, _c = _a.navigation, navigation = _c === void 0 ? 'bound' : _c, onKeyDown = _a.onKeyDown, onFocus = _a.onFocus, onSelectionChange = _a.onSelectionChange, onActiveChange = _a.onActiveChange, props = tslib.__rest(_a, ["as", "children", "defaultValue", "value", "navigation", "onKeyDown", "onFocus", "onSelectionChange", "onActiveChange"]);
3482
- var _d = tslib.__read(React.useState([]), 2), options = _d[0], setOptions = _d[1];
3483
- var _e = tslib.__read(React.useState(null), 2), activeOption = _e[0], setActiveOption = _e[1];
3484
- var _f = tslib.__read(React.useState(null), 2), selectedOption = _f[0], setSelectedOption = _f[1];
3629
+ var _b = _a.as, Component = _b === void 0 ? 'ul' : _b, children = _a.children, defaultValue = _a.defaultValue, value = _a.value, _c = _a.navigation, navigation = _c === void 0 ? 'bound' : _c, _d = _a.multiselect, multiselect = _d === void 0 ? false : _d, onKeyDown = _a.onKeyDown, onFocus = _a.onFocus, onSelectionChange = _a.onSelectionChange, onActiveChange = _a.onActiveChange, props = tslib.__rest(_a, ["as", "children", "defaultValue", "value", "navigation", "multiselect", "onKeyDown", "onFocus", "onSelectionChange", "onActiveChange"]);
3630
+ var _e = tslib.__read(React.useState([]), 2), options = _e[0], setOptions = _e[1];
3631
+ var _f = tslib.__read(React.useState(null), 2), activeOption = _f[0], setActiveOption = _f[1];
3632
+ var _g = tslib.__read(React.useState([]), 2), selectedOptions = _g[0], setSelectedOptions = _g[1];
3485
3633
  var listboxRef = useSharedRef(ref);
3486
3634
  var isControlled = typeof value !== 'undefined';
3487
3635
  React.useLayoutEffect(function () {
3488
- if (!isControlled && selectedOption) {
3636
+ if (!isControlled && selectedOptions.length > 0) {
3489
3637
  return;
3490
3638
  }
3491
3639
  var listboxValue = isControlled ? value : defaultValue;
3492
- var matchingOption = options.find(function (option) {
3493
- return optionMatchesValue(option, listboxValue);
3494
- });
3495
- setSelectedOption(matchingOption || null);
3496
- setActiveOption(matchingOption || null);
3497
- }, [isControlled, options, value]);
3640
+ if (!listboxValue) {
3641
+ return;
3642
+ }
3643
+ if (multiselect) {
3644
+ var matchingOptions = options.filter(function (option) {
3645
+ return listboxValue.find(function (value) {
3646
+ return optionMatchesValue(option, value);
3647
+ });
3648
+ });
3649
+ setSelectedOptions(matchingOptions);
3650
+ setActiveOption(matchingOptions[0] || null);
3651
+ }
3652
+ else {
3653
+ var matchingOption = options.find(function (option) {
3654
+ return optionMatchesValue(option, listboxValue);
3655
+ });
3656
+ setSelectedOptions(matchingOption ? [matchingOption] : []);
3657
+ setActiveOption(matchingOption || null);
3658
+ }
3659
+ }, [isControlled, options, value, defaultValue]);
3498
3660
  React.useEffect(function () {
3499
3661
  if (activeOption) {
3500
3662
  onActiveChange === null || onActiveChange === void 0 ? void 0 : onActiveChange(activeOption);
3501
3663
  }
3502
3664
  }, [activeOption]);
3503
3665
  var handleSelect = React.useCallback(function (option) {
3666
+ var _a;
3504
3667
  setActiveOption(option);
3668
+ var optionIsSelected = selectedOptions.some(function (selected) { return selected.element === option.element; });
3669
+ var previousValues = selectedOptions.map(function (selected) { return selected.value; });
3505
3670
  // istanbul ignore else
3506
3671
  if (!isControlled) {
3507
- setSelectedOption(option);
3672
+ if (!multiselect) {
3673
+ setSelectedOptions([option]);
3674
+ }
3675
+ else {
3676
+ setSelectedOptions(optionIsSelected
3677
+ ? tslib.__spreadArray([], tslib.__read(selectedOptions.filter(function (selected) { return selected.element !== option.element; })), false) : tslib.__spreadArray(tslib.__spreadArray([], tslib.__read(selectedOptions), false), [option], false));
3678
+ }
3508
3679
  }
3509
- onSelectionChange === null || onSelectionChange === void 0 ? void 0 : onSelectionChange({
3510
- target: option.element,
3511
- value: option.value,
3512
- previousValue: selectedOption === null || selectedOption === void 0 ? void 0 : selectedOption.value
3513
- });
3514
- }, [isControlled, selectedOption]);
3680
+ if (multiselect) {
3681
+ onSelectionChange === null || onSelectionChange === void 0 ? void 0 : onSelectionChange({
3682
+ target: option.element,
3683
+ value: optionIsSelected
3684
+ ? selectedOptions
3685
+ .filter(function (selectedOption) {
3686
+ return selectedOption.element !== option.element;
3687
+ })
3688
+ .map(function (selectedOption) { return selectedOption.value; })
3689
+ : tslib.__spreadArray(tslib.__spreadArray([], tslib.__read(previousValues), false), [option.value], false),
3690
+ previousValue: previousValues
3691
+ });
3692
+ }
3693
+ else {
3694
+ onSelectionChange === null || onSelectionChange === void 0 ? void 0 : onSelectionChange({
3695
+ target: option.element,
3696
+ value: option.value,
3697
+ previousValue: (_a = selectedOptions[0]) === null || _a === void 0 ? void 0 : _a.value
3698
+ });
3699
+ }
3700
+ }, [isControlled, selectedOptions, multiselect, onSelectionChange]);
3515
3701
  var handleKeyDown = React.useCallback(function (event) {
3516
3702
  onKeyDown === null || onKeyDown === void 0 ? void 0 : onKeyDown(event);
3517
3703
  if (!keys.includes(event.key)) {
@@ -3561,9 +3747,9 @@ var Listbox = React.forwardRef(function (_a, ref) {
3561
3747
  activeOption && handleSelect(activeOption);
3562
3748
  break;
3563
3749
  }
3564
- }, [options, activeOption, navigation]);
3750
+ }, [options, activeOption, navigation, handleSelect]);
3565
3751
  var handleFocus = React.useCallback(function (event) {
3566
- if (!activeOption && !selectedOption) {
3752
+ if (!activeOption) {
3567
3753
  var firstOption = options.find(function (option) { return !isDisabledOption(option); });
3568
3754
  // istanbul ignore else
3569
3755
  if (firstOption) {
@@ -3571,13 +3757,14 @@ var Listbox = React.forwardRef(function (_a, ref) {
3571
3757
  }
3572
3758
  // istanbul ignore else
3573
3759
  }
3574
- else if (event.target === listboxRef.current) {
3575
- setActiveOption(selectedOption);
3760
+ else if (selectedOptions.length &&
3761
+ event.target === listboxRef.current) {
3762
+ setActiveOption(selectedOptions[selectedOptions.length - 1]);
3576
3763
  }
3577
3764
  onFocus === null || onFocus === void 0 ? void 0 : onFocus(event);
3578
- }, [options, activeOption, selectedOption]);
3579
- return (React__default["default"].createElement(Component, tslib.__assign({ role: "listbox", ref: listboxRef, tabIndex: "0", onKeyDown: handleKeyDown, onFocus: handleFocus, "aria-activedescendant": activeOption ? getOptionId(activeOption) : undefined }, props),
3580
- React__default["default"].createElement(ListboxProvider, { options: options, active: activeOption, selected: selectedOption, setOptions: setOptions, onSelect: handleSelect }, children)));
3765
+ }, [options, activeOption, selectedOptions]);
3766
+ return (React__default["default"].createElement(Component, tslib.__assign({ role: "listbox", ref: listboxRef, tabIndex: "0", onKeyDown: handleKeyDown, onFocus: handleFocus, "aria-multiselectable": multiselect ? true : undefined, "aria-activedescendant": activeOption ? getOptionId(activeOption) : undefined }, props),
3767
+ React__default["default"].createElement(ListboxProvider, { options: options, active: activeOption, multiselect: multiselect, selected: selectedOptions, setOptions: setOptions, onSelect: handleSelect }, children)));
3581
3768
  });
3582
3769
  Listbox.displayName = 'Listbox';
3583
3770
 
@@ -3587,12 +3774,15 @@ function isElementPreceding(a, b) {
3587
3774
  var ListboxOption = React.forwardRef(function (_a, ref) {
3588
3775
  var _b;
3589
3776
  var _c;
3590
- 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, _e = _a.activeClass, activeClass = _e === void 0 ? 'ListboxOption--active' : _e, onClick = _a.onClick, props = tslib.__rest(_a, ["id", "className", "as", "children", "value", "disabled", "activeClass", "onClick"]);
3777
+ 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"]);
3591
3778
  var _f = useListboxContext(), active = _f.active, selected = _f.selected, setOptions = _f.setOptions, onSelect = _f.onSelect;
3592
3779
  var listboxOptionRef = useSharedRef(ref);
3593
3780
  var _g = tslib.__read(propId ? [propId] : nextId.useId(1, 'listbox-option'), 1), id = _g[0];
3594
- var isActive = active !== null && active.element === listboxOptionRef.current;
3595
- var isSelected = selected !== null && selected.element === listboxOptionRef.current;
3781
+ var isActive = (active === null || active === void 0 ? void 0 : active.element) === listboxOptionRef.current;
3782
+ var isSelected = typeof selectedProp === 'boolean'
3783
+ ? selectedProp
3784
+ : selected !== null &&
3785
+ !!selected.find(function (option) { return option.element === listboxOptionRef.current; });
3596
3786
  var optionValue = typeof value !== 'undefined'
3597
3787
  ? value
3598
3788
  : (_c = listboxOptionRef.current) === null || _c === void 0 ? void 0 : _c.innerText;
@@ -3642,7 +3832,7 @@ var ListboxOption = React.forwardRef(function (_a, ref) {
3642
3832
  }
3643
3833
  onSelect({ element: listboxOptionRef.current, value: optionValue });
3644
3834
  onClick === null || onClick === void 0 ? void 0 : onClick(event);
3645
- }, [optionValue]);
3835
+ }, [optionValue, onSelect, onClick, disabled]);
3646
3836
  return (React__default["default"].createElement(Component, tslib.__assign({ id: id, className: classNames__default["default"](className, (_b = {},
3647
3837
  _b[activeClass] = isActive,
3648
3838
  _b)), role: "option", ref: listboxOptionRef, "aria-disabled": typeof disabled === 'boolean' ? disabled : undefined, "aria-selected": isSelected, onClick: handleClick }, props), children));
@@ -3764,17 +3954,20 @@ var ComboboxMatch = function (_a) {
3764
3954
  React__default["default"].createElement("span", null, matchAfter)));
3765
3955
  };
3766
3956
  var ComboboxOption = React.forwardRef(function (_a, ref) {
3957
+ var _b;
3767
3958
  var className = _a.className, children = _a.children, disabled = _a.disabled, propId = _a.id, description = _a.description, propValue = _a.value, formValue = _a.formValue, props = tslib.__rest(_a, ["className", "children", "disabled", "id", "description", "value", "formValue"]);
3768
- var _b = tslib.__read(propId ? [propId] : nextId.useId(1, 'combobox-option'), 1), id = _b[0];
3769
- var _c = useListboxContext(), selected = _c.selected, active = _c.active;
3770
- var _d = useComboboxContext(), selectedValue = _d.selectedValue, matches = _d.matches, setMatchingOptions = _d.setMatchingOptions, setFormValue = _d.setFormValue;
3959
+ var _c = tslib.__read(propId ? [propId] : nextId.useId(1, 'combobox-option'), 1), id = _c[0];
3960
+ var _d = useListboxContext(), selected = _d.selected, active = _d.active;
3961
+ var _e = useComboboxContext(), selectedValue = _e.selectedValue, matches = _e.matches, setMatchingOptions = _e.setMatchingOptions, setFormValue = _e.setFormValue;
3771
3962
  var comboboxOptionRef = useSharedRef(ref);
3772
3963
  var intersectionRef = useIntersectionRef(comboboxOptionRef, {
3773
3964
  root: null,
3774
3965
  threshold: 1.0
3775
3966
  });
3776
3967
  var isActive = !!(active === null || active === void 0 ? void 0 : active.element) && active.element === comboboxOptionRef.current;
3777
- var isSelected = !!(selected === null || selected === void 0 ? void 0 : selected.element) && selected.element === comboboxOptionRef.current;
3968
+ var isSelected = !!(selected &&
3969
+ !!((_b = selected[0]) === null || _b === void 0 ? void 0 : _b.element) &&
3970
+ selected[0].element === comboboxOptionRef.current);
3778
3971
  var isMatching = (typeof matches === 'boolean' && matches) ||
3779
3972
  (typeof matches === 'function' && matches(children));
3780
3973
  // istanbul ignore next
@@ -4110,19 +4303,7 @@ var Popover = React.forwardRef(function (_a, ref) {
4110
4303
  var _f = tslib.__read(React.useState(null), 2), targetElement = _f[0], setTargetElement = _f[1];
4111
4304
  var _g = tslib.__read(React.useState(null), 2), isolator = _g[0], setIsolator = _g[1];
4112
4305
  var popoverRef = useSharedRef(ref);
4113
- var _h = tslib.__read(React.useState(null), 2), arrowElement = _h[0], setArrowElement = _h[1];
4114
- var _j = reactPopper.usePopper(targetElement, popoverRef === null || popoverRef === void 0 ? void 0 : popoverRef.current, {
4115
- placement: initialPlacement,
4116
- modifiers: [
4117
- { name: 'preventOverflow', options: { padding: 8 } },
4118
- { name: 'flip' },
4119
- { name: 'offset', options: { offset: [0, 8] } },
4120
- { name: 'arrow', options: { padding: 5, element: arrowElement } }
4121
- ]
4122
- }), styles = _j.styles, attributes = _j.attributes;
4123
- var placement = (attributes.popper &&
4124
- attributes.popper['data-popper-placement']) ||
4125
- initialPlacement;
4306
+ var _h = tslib.__read(React.useState(initialPlacement), 2), placement = _h[0], setPlacement = _h[1];
4126
4307
  var additionalProps = variant === 'prompt' && !props['aria-label']
4127
4308
  ? { 'aria-labelledby': "".concat(id, "-label") }
4128
4309
  : {};
@@ -4154,15 +4335,8 @@ var Popover = React.forwardRef(function (_a, ref) {
4154
4335
  attachIsolator();
4155
4336
  }, [popoverRef.current]);
4156
4337
  React.useEffect(function () {
4157
- if (show && popoverRef.current) {
4158
- // Find the first focusable element inside the container
4159
- var firstFocusableElement = popoverRef.current.querySelector(focusableSelector);
4160
- if (firstFocusableElement instanceof HTMLElement) {
4161
- firstFocusableElement.focus();
4162
- }
4163
- }
4164
4338
  targetElement === null || targetElement === void 0 ? void 0 : targetElement.setAttribute('aria-expanded', Boolean(show).toString());
4165
- }, [show, popoverRef.current]);
4339
+ }, [show]);
4166
4340
  React.useEffect(function () {
4167
4341
  var attrText = targetElement === null || targetElement === void 0 ? void 0 : targetElement.getAttribute('aria-controls');
4168
4342
  var hasPopupAttr = targetElement === null || targetElement === void 0 ? void 0 : targetElement.getAttribute('aria-haspopup');
@@ -4196,20 +4370,17 @@ var Popover = React.forwardRef(function (_a, ref) {
4196
4370
  callback: handleClosePopover,
4197
4371
  active: show
4198
4372
  }, [show]);
4373
+ useFocusTrap(popoverRef, { disabled: !show, returnFocus: true });
4199
4374
  if (!show || !isBrowser())
4200
4375
  return null;
4201
- return reactDom.createPortal(React__default["default"].createElement(FocusTrap__default["default"], { focusTrapOptions: {
4202
- allowOutsideClick: true,
4203
- fallbackFocus: '.Popover__borderLeft'
4204
- } },
4205
- React__default["default"].createElement(ClickOutsideListener$1, { onClickOutside: handleClickOutside },
4206
- React__default["default"].createElement("div", tslib.__assign({ id: id, className: classNames__default["default"]('Popover', "Popover--".concat(placement), className, {
4207
- 'Popover--hidden': !show,
4208
- 'Popover--prompt': variant === 'prompt'
4209
- }), ref: popoverRef, role: "dialog", style: styles.popper }, attributes.popper, additionalProps, props),
4210
- React__default["default"].createElement("div", { className: "Popover__popoverArrow", ref: setArrowElement, style: styles.arrow }),
4211
- React__default["default"].createElement("div", { className: "Popover__borderLeft" }),
4212
- variant === 'prompt' ? (React__default["default"].createElement(PromptPopoverContent, { applyButtonText: applyButtonText, onApply: onApply, closeButtonText: closeButtonText, infoText: infoText || '', onClose: handleClosePopover, infoTextId: "".concat(id, "-label") })) : (children)))), (portal && 'current' in portal ? portal.current : portal) ||
4376
+ return reactDom.createPortal(React__default["default"].createElement(ClickOutsideListener$1, { onClickOutside: handleClickOutside },
4377
+ React__default["default"].createElement(AnchoredOverlay, tslib.__assign({ id: id, className: classNames__default["default"]('Popover', "Popover--".concat(placement), className, {
4378
+ 'Popover--hidden': !show,
4379
+ 'Popover--prompt': variant === 'prompt'
4380
+ }), ref: popoverRef, role: "dialog", target: target, open: show, placement: initialPlacement, onPlacementChange: setPlacement, offset: 8 }, additionalProps, props),
4381
+ React__default["default"].createElement("div", { className: "Popover__popoverArrow" }),
4382
+ React__default["default"].createElement("div", { className: "Popover__borderLeft" }),
4383
+ variant === 'prompt' ? (React__default["default"].createElement(PromptPopoverContent, { applyButtonText: applyButtonText, onApply: onApply, closeButtonText: closeButtonText, infoText: infoText || '', onClose: handleClosePopover, infoTextId: "".concat(id, "-label") })) : (children))), (portal && 'current' in portal ? portal.current : portal) ||
4213
4384
  // Dependent on "isBrowser" check above:
4214
4385
  // eslint-disable-next-line ssr-friendly/no-dom-globals-in-react-fc
4215
4386
  document.body);
@@ -4277,7 +4448,6 @@ var Drawer = React.forwardRef(function (_a, ref) {
4277
4448
  var children = _a.children, className = _a.className, position = _a.position, _b = _a.open, open = _b === void 0 ? false : _b, _c = _a.behavior, behavior = _c === void 0 ? 'modal' : _c, _d = _a.focusOptions, focusOptions = _d === void 0 ? {} : _d, portal = _a.portal, onClose = _a.onClose, style = _a.style, props = tslib.__rest(_a, ["children", "className", "position", "open", "behavior", "focusOptions", "portal", "onClose", "style"]);
4278
4449
  var drawerRef = useSharedRef(ref);
4279
4450
  var openRef = React.useRef(!!open);
4280
- var previousActiveElementRef = React.useRef(null);
4281
4451
  var focusInitial = focusOptions.initialFocus, focusReturn = focusOptions.returnFocus;
4282
4452
  var _e = tslib.__read(React.useState(!!open), 2), isTransitioning = _e[0], setIsTransitioning = _e[1];
4283
4453
  var isModal = behavior === 'modal';
@@ -4317,60 +4487,27 @@ var Drawer = React.forwardRef(function (_a, ref) {
4317
4487
  isolator.deactivate();
4318
4488
  };
4319
4489
  }, [isModal, open]);
4320
- React.useLayoutEffect(function () {
4321
- var _a, _b, _c;
4322
- if (open) {
4323
- previousActiveElementRef.current =
4324
- document.activeElement;
4325
- var initialFocusElement = resolveElement(focusInitial);
4326
- if (initialFocusElement) {
4327
- initialFocusElement.focus();
4328
- }
4329
- else {
4330
- var focusable = (_a = drawerRef.current) === null || _a === void 0 ? void 0 : _a.querySelector(focusableSelector);
4331
- if (focusable) {
4332
- focusable.focus();
4333
- }
4334
- else {
4335
- // fallback focus
4336
- (_b = drawerRef.current) === null || _b === void 0 ? void 0 : _b.focus();
4337
- }
4338
- }
4339
- }
4340
- else if (previousActiveElementRef.current) {
4341
- var returnFocusElement = resolveElement(focusReturn);
4342
- if (returnFocusElement) {
4343
- returnFocusElement.focus();
4344
- }
4345
- else {
4346
- // fallback focus
4347
- (_c = previousActiveElementRef.current) === null || _c === void 0 ? void 0 : _c.focus();
4348
- }
4349
- }
4350
- }, [open, focusInitial, focusReturn]);
4351
4490
  useEscapeKey({ callback: handleClose, active: open, defaultPrevented: true }, [onClose]);
4352
4491
  // istanbul ignore next
4353
4492
  if (!isBrowser()) {
4354
4493
  return null;
4355
4494
  }
4495
+ useFocusTrap(drawerRef, {
4496
+ disabled: !isModal || !open,
4497
+ initialFocusElement: focusInitial || drawerRef,
4498
+ returnFocus: true,
4499
+ returnFocusElement: focusReturn
4500
+ });
4356
4501
  var portalElement = resolveElement(portal);
4357
4502
  return reactDom.createPortal(React__default["default"].createElement(React__default["default"].Fragment, null,
4358
4503
  React__default["default"].createElement(ClickOutsideListener$1, { onClickOutside: handleClose, mouseEvent: open ? undefined : false, touchEvent: open ? undefined : false, target: drawerRef },
4359
- React__default["default"].createElement(FocusTrap__default["default"], { active: !!isModal && !!open, focusTrapOptions: {
4360
- allowOutsideClick: true,
4361
- escapeDeactivates: false,
4362
- clickOutsideDeactivates: false,
4363
- initialFocus: false,
4364
- setReturnFocus: false,
4365
- fallbackFocus: function () { return drawerRef.current; }
4366
- } },
4367
- React__default["default"].createElement("div", tslib.__assign({ ref: drawerRef, className: classNames__default["default"](className, 'Drawer', {
4368
- 'Drawer--open': !!open,
4369
- 'Drawer--top': position === 'top',
4370
- 'Drawer--bottom': position === 'bottom',
4371
- 'Drawer--left': position === 'left',
4372
- 'Drawer--right': position === 'right'
4373
- }), "aria-hidden": !open || undefined, style: tslib.__assign({ visibility: !open && !isTransitioning ? 'hidden' : undefined }, style), tabIndex: open ? -1 : undefined }, props), children))),
4504
+ React__default["default"].createElement("div", tslib.__assign({ ref: drawerRef, className: classNames__default["default"](className, 'Drawer', {
4505
+ 'Drawer--open': !!open,
4506
+ 'Drawer--top': position === 'top',
4507
+ 'Drawer--bottom': position === 'bottom',
4508
+ 'Drawer--left': position === 'left',
4509
+ 'Drawer--right': position === 'right'
4510
+ }), "aria-hidden": !open || undefined, style: tslib.__assign({ visibility: !open && !isTransitioning ? 'hidden' : undefined }, style), tabIndex: open ? -1 : undefined }, props), children)),
4374
4511
  React__default["default"].createElement(Scrim, { show: !!open && !!isModal })), portalElement ||
4375
4512
  (
4376
4513
  // eslint-disable-next-line ssr-friendly/no-dom-globals-in-react-fc
@@ -4476,6 +4613,7 @@ exports.AddressLine = AddressLine;
4476
4613
  exports.Alert = Alert;
4477
4614
  exports.AlertActions = AlertActions;
4478
4615
  exports.AlertContent = AlertContent;
4616
+ exports.AnchoredOverlay = AnchoredOverlay;
4479
4617
  exports.AriaIsolate = AriaIsolate;
4480
4618
  exports.Badge = Badge;
4481
4619
  exports.BadgeLabel = BadgeLabel;