@deque/cauldron-react 6.12.0 → 6.13.0-canary.2b0bb381

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);
@@ -1282,7 +1283,7 @@ var SideBar = /** @class */ (function (_super) {
1282
1283
  }(React.Component));
1283
1284
 
1284
1285
  var SideBarItem = function (_a) {
1285
- var children = _a.children, autoClickLink = _a.autoClickLink, other = tslib.__rest(_a, ["children", "autoClickLink"]);
1286
+ var children = _a.children, _b = _a.autoClickLink, autoClickLink = _b === void 0 ? true : _b, other = tslib.__rest(_a, ["children", "autoClickLink"]);
1286
1287
  var onClick = function (e) {
1287
1288
  if (!autoClickLink) {
1288
1289
  return;
@@ -1294,9 +1295,6 @@ var SideBarItem = function (_a) {
1294
1295
  /* eslint-enable jsx-a11y/no-noninteractive-element-interactions, jsx-a11y/click-events-have-key-events */
1295
1296
  };
1296
1297
  SideBarItem.displayName = 'SideBarItem';
1297
- SideBarItem.defaultProps = {
1298
- autoClickLink: true
1299
- };
1300
1298
 
1301
1299
  /**
1302
1300
  * Handles aria-hidden for dialogs.
@@ -1344,133 +1342,277 @@ var AriaIsolate = /** @class */ (function () {
1344
1342
  return AriaIsolate;
1345
1343
  }());
1346
1344
 
1347
- var isEscape = function (event) {
1348
- return event.key === 'Escape' || event.key === 'Esc' || event.keyCode === 27;
1349
- };
1350
- var noop = function () {
1351
- //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);
1352
1373
  };
1353
- var Dialog = /** @class */ (function (_super) {
1354
- tslib.__extends(Dialog, _super);
1355
- function Dialog(props) {
1356
- var _this = _super.call(this, props) || this;
1357
- _this.headingId = nextId__default["default"]('dialog-title-');
1358
- _this.close = _this.close.bind(_this);
1359
- _this.focusHeading = _this.focusHeading.bind(_this);
1360
- _this.handleClickOutside = _this.handleClickOutside.bind(_this);
1361
- _this.handleEscape = _this.handleEscape.bind(_this);
1362
- _this.state = {};
1363
- 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;
1364
1382
  }
1365
- Dialog.prototype.componentDidMount = function () {
1366
- var _this = this;
1367
- if (this.props.show) {
1368
- this.attachEventListeners();
1369
- 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;
1370
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
1371
1414
  };
1372
- Dialog.prototype.componentWillUnmount = function () {
1373
- var isolator = this.state.isolator;
1374
- isolator === null || isolator === void 0 ? void 0 : isolator.deactivate();
1375
- this.removeEventListeners();
1376
- };
1377
- Dialog.prototype.componentDidUpdate = function (prevProps) {
1378
- if (!prevProps.show && this.props.show) {
1379
- this.attachIsolator(this.focusHeading);
1380
- 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;
1381
1421
  }
1382
- else if (prevProps.show && !this.props.show) {
1383
- this.removeEventListeners();
1384
- 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();
1385
1426
  }
1386
- };
1387
- Dialog.prototype.attachIsolator = function (done) {
1388
- this.setState({
1389
- isolator: new AriaIsolate(this.element)
1390
- }, done);
1391
- };
1392
- Dialog.prototype.render = function () {
1393
- var _this = this;
1394
- 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"]);
1395
- if (!show || !isBrowser()) {
1396
- 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;
1397
1432
  }
1398
- var portal = this.props.portal || document.body;
1399
- var close = !forceAction ? (React__default["default"].createElement("button", { className: "Dialog__close", type: "button", onClick: this.close },
1400
- React__default["default"].createElement(Icon, { type: "close", "aria-hidden": "true" }),
1401
- React__default["default"].createElement(Offscreen, null, closeButtonText))) : null;
1402
- var Heading = "h".concat(typeof heading === 'object' && 'level' in heading && !!heading.level
1403
- ? heading.level
1404
- : 2);
1405
- var Dialog = (React__default["default"].createElement(FocusTrap__default["default"], { focusTrapOptions: {
1406
- allowOutsideClick: true,
1407
- escapeDeactivates: false,
1408
- fallbackFocus: '.Dialog__heading'
1409
- } },
1410
- React__default["default"].createElement(ClickOutsideListener$1, { onClickOutside: this.handleClickOutside },
1411
- React__default["default"].createElement("div", tslib.__assign({ role: "dialog", className: classNames__default["default"]('Dialog', className, {
1412
- 'Dialog--show': show
1413
- }), ref: function (el) {
1414
- _this.element = el;
1415
- if (!dialogRef) {
1416
- return;
1417
- }
1418
- setRef(dialogRef, el);
1419
- }, "aria-labelledby": this.headingId }, other),
1420
- React__default["default"].createElement("div", { className: "Dialog__inner" },
1421
- React__default["default"].createElement("div", { className: "Dialog__header" },
1422
- 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
1423
- ? heading.text
1424
- : heading),
1425
- close),
1426
- children)))));
1427
- return reactDom.createPortal(Dialog, ('current' in portal ? portal.current : portal) || document.body);
1428
- };
1429
- Dialog.prototype.close = function () {
1430
- var _a, _b, _c;
1431
- (_a = this.state.isolator) === null || _a === void 0 ? void 0 : _a.deactivate();
1432
- if (this.props.show) {
1433
- (_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;
1434
1439
  }
1435
- };
1436
- Dialog.prototype.handleClickOutside = function () {
1437
- var _a = this.props, show = _a.show, forceAction = _a.forceAction;
1438
- if (show && !forceAction) {
1439
- 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();
1440
1456
  }
1441
1457
  };
1442
- 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() {
1443
1494
  var _a;
1444
- if (this.heading) {
1445
- this.heading.focus();
1495
+ var resolvedReturnFocusElement = resolveElement(returnFocusElement);
1496
+ if (resolvedReturnFocusElement instanceof HTMLElement) {
1497
+ resolvedReturnFocusElement.focus();
1446
1498
  }
1447
- (_a = this.state.isolator) === null || _a === void 0 ? void 0 : _a.activate();
1448
- };
1449
- 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) {
1450
1552
  if (!keyboardEvent.defaultPrevented && isEscape(keyboardEvent)) {
1451
- this.close();
1553
+ handleClose();
1452
1554
  }
1453
- };
1454
- Dialog.prototype.attachEventListeners = function () {
1455
- 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 () {
1456
1567
  if (!forceAction) {
1457
- var portal = this.props.portal || document.body;
1458
- var targetElement = portal instanceof HTMLElement ? portal : portal.current;
1459
- 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
+ };
1460
1579
  }
1461
- };
1462
- Dialog.prototype.removeEventListeners = function () {
1463
- var portal = this.props.portal || document.body;
1464
- var targetElement = portal instanceof HTMLElement ? portal : portal.current;
1465
- targetElement === null || targetElement === void 0 ? void 0 : targetElement.removeEventListener('keyup', this.handleEscape);
1466
- };
1467
- Dialog.defaultProps = {
1468
- onClose: noop,
1469
- forceAction: false,
1470
- closeButtonText: 'Close'
1471
- };
1472
- return Dialog;
1473
- }(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';
1474
1616
  var DialogContent = function (_a) {
1475
1617
  var children = _a.children, className = _a.className, align = _a.align, other = tslib.__rest(_a, ["children", "className", "align"]);
1476
1618
  return (React__default["default"].createElement("div", tslib.__assign({ className: classNames__default["default"]('Dialog__content', className, {
@@ -1586,43 +1728,6 @@ var Button = React.forwardRef(function (_a, ref) {
1586
1728
  });
1587
1729
  Button.displayName = 'Button';
1588
1730
 
1589
- /**
1590
- * Returns a unique set of id refs from the provided string
1591
- * @param ids - string of id refs
1592
- */
1593
- function idRefs(ids) {
1594
- if (!ids || !ids.trim()) {
1595
- return new Set();
1596
- }
1597
- return new Set(ids.trim().split(/\s+/));
1598
- }
1599
- /**
1600
- * Returns an updated id ref string with the provided id value added
1601
- * @param ids - string of id refs
1602
- * @param id - id to add
1603
- */
1604
- function addIdRef(ids, id) {
1605
- return tslib.__spreadArray([], tslib.__read(idRefs(ids).add(id)), false).join(' ');
1606
- }
1607
- /**
1608
- * Returns an updated id ref string with the provided id value removed
1609
- * @param ids - string of id refs
1610
- * @param id - id to remove
1611
- */
1612
- function removeIdRef(_ids, id) {
1613
- var ids = idRefs(_ids);
1614
- ids.delete(id);
1615
- return tslib.__spreadArray([], tslib.__read(ids), false).join(' ');
1616
- }
1617
- /**
1618
- * Returns if an id ref string contains the provided id value
1619
- * @param ids - string of id refs
1620
- * @param id - id to check if it exists in the provided idRef string
1621
- */
1622
- function hasIdRef(ids, id) {
1623
- return idRefs(ids).has(id);
1624
- }
1625
-
1626
1731
  var isEscapeKey = function (event) {
1627
1732
  return event.key === 'Escape' || event.key === 'Esc' || event.keyCode === 27;
1628
1733
  };
@@ -1663,6 +1768,100 @@ function useEscapeKey(options, dependencies) {
1663
1768
  ], tslib.__read(dependencies), false));
1664
1769
  }
1665
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, focusTrap = _a.focusTrap, focusTrapOptions = _a.focusTrapOptions, onOpenChange = _a.onOpenChange, onPlacementChange = _a.onPlacementChange, props = tslib.__rest(_a, ["as", "placement", "target", "children", "style", "open", "offset", "focusTrap", "focusTrapOptions", "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
+ useFocusTrap(ref, !focusTrap ? { disabled: true } : focusTrapOptions);
1819
+ React.useEffect(function () {
1820
+ if (typeof onPlacementChange === 'function') {
1821
+ onPlacementChange(placement);
1822
+ }
1823
+ }, [placement]);
1824
+ return (React__default["default"].createElement(Component, tslib.__assign({ ref: ref }, props, { style: tslib.__assign(tslib.__assign({}, floatingStyles), style) }), children));
1825
+ });
1826
+ AnchoredOverlay.displayName = 'AnchoredOverlay';
1827
+
1828
+ /**
1829
+ * Returns a unique set of id refs from the provided string
1830
+ * @param ids - string of id refs
1831
+ */
1832
+ function idRefs(ids) {
1833
+ if (!ids || !ids.trim()) {
1834
+ return new Set();
1835
+ }
1836
+ return new Set(ids.trim().split(/\s+/));
1837
+ }
1838
+ /**
1839
+ * Returns an updated id ref string with the provided id value added
1840
+ * @param ids - string of id refs
1841
+ * @param id - id to add
1842
+ */
1843
+ function addIdRef(ids, id) {
1844
+ return tslib.__spreadArray([], tslib.__read(idRefs(ids).add(id)), false).join(' ');
1845
+ }
1846
+ /**
1847
+ * Returns an updated id ref string with the provided id value removed
1848
+ * @param ids - string of id refs
1849
+ * @param id - id to remove
1850
+ */
1851
+ function removeIdRef(_ids, id) {
1852
+ var ids = idRefs(_ids);
1853
+ ids.delete(id);
1854
+ return tslib.__spreadArray([], tslib.__read(ids), false).join(' ');
1855
+ }
1856
+ /**
1857
+ * Returns if an id ref string contains the provided id value
1858
+ * @param ids - string of id refs
1859
+ * @param id - id to check if it exists in the provided idRef string
1860
+ */
1861
+ function hasIdRef(ids, id) {
1862
+ return idRefs(ids).has(id);
1863
+ }
1864
+
1666
1865
  var TIP_HIDE_DELAY = 100;
1667
1866
  // fires a custom "cauldron:tooltip:show" / "cauldron:tooltip:hide" event
1668
1867
  // to allow projects using cauldron to hook into when a tooltip is shown/hidden
@@ -1681,50 +1880,27 @@ function Tooltip(_a) {
1681
1880
  var _g = tslib.__read(propId ? [propId] : nextId.useId(1, 'tooltip'), 1), id = _g[0];
1682
1881
  var hideTimeoutRef = React.useRef(null);
1683
1882
  var _h = tslib.__read(React.useState(!!showProp || defaultShow), 2), showTooltip = _h[0], setShowTooltip = _h[1];
1684
- var _j = tslib.__read(React.useState(null), 2), targetElement = _j[0], setTargetElement = _j[1];
1685
- var _k = tslib.__read(React.useState(null), 2), tooltipElement = _k[0], setTooltipElement = _k[1];
1686
- var _l = tslib.__read(React.useState(null), 2), arrowElement = _l[0], setArrowElement = _l[1];
1883
+ var _j = tslib.__read(React.useState(null), 2), tooltipElement = _j[0], setTooltipElement = _j[1];
1884
+ var _k = tslib.__read(React.useState(initialPlacement), 2), placement = _k[0], setPlacement = _k[1];
1687
1885
  var hasAriaAssociation = association !== 'none';
1688
- var _m = reactPopper.usePopper(targetElement, tooltipElement, {
1689
- placement: initialPlacement,
1690
- modifiers: [
1691
- { name: 'preventOverflow', options: { padding: 8 } },
1692
- {
1693
- name: 'flip',
1694
- options: { fallbackPlacements: ['left', 'right', 'top', 'bottom'] }
1695
- },
1696
- { name: 'offset', options: { offset: [0, 8] } },
1697
- { name: 'arrow', options: { padding: 5, element: arrowElement } }
1698
- ]
1699
- }), styles = _m.styles, attributes = _m.attributes, update = _m.update;
1700
1886
  // Show the tooltip
1701
1887
  var show = React.useCallback(function () { return tslib.__awaiter(_this, void 0, void 0, function () {
1888
+ var targetElement;
1702
1889
  return tslib.__generator(this, function (_a) {
1703
- switch (_a.label) {
1704
- case 0:
1705
- // Clear the hide timeout if there was one pending
1706
- if (hideTimeoutRef.current) {
1707
- clearTimeout(hideTimeoutRef.current);
1708
- hideTimeoutRef.current = null;
1709
- }
1710
- if (!update) return [3 /*break*/, 2];
1711
- return [4 /*yield*/, update()];
1712
- case 1:
1713
- _a.sent();
1714
- _a.label = 2;
1715
- case 2:
1716
- setShowTooltip(true);
1717
- fireCustomEvent(true, targetElement);
1718
- return [2 /*return*/];
1890
+ targetElement = resolveElement(target);
1891
+ // Clear the hide timeout if there was one pending
1892
+ if (hideTimeoutRef.current) {
1893
+ clearTimeout(hideTimeoutRef.current);
1894
+ hideTimeoutRef.current = null;
1719
1895
  }
1896
+ setShowTooltip(true);
1897
+ fireCustomEvent(true, targetElement);
1898
+ return [2 /*return*/];
1720
1899
  });
1721
- }); }, [
1722
- targetElement,
1723
- // update starts off as null
1724
- update
1725
- ]);
1900
+ }); }, [target]);
1726
1901
  // Hide the tooltip
1727
1902
  var hide = React.useCallback(function () {
1903
+ var targetElement = resolveElement(target);
1728
1904
  if (!hideTimeoutRef.current) {
1729
1905
  hideTimeoutRef.current = setTimeout(function () {
1730
1906
  hideTimeoutRef.current = null;
@@ -1735,32 +1911,15 @@ function Tooltip(_a) {
1735
1911
  return function () {
1736
1912
  clearTimeout(hideTimeoutRef.current);
1737
1913
  };
1738
- }, [targetElement]);
1739
- // Keep targetElement in sync with target prop
1740
- React.useEffect(function () {
1741
- var targetElement = target && 'current' in target ? target.current : target;
1742
- setTargetElement(targetElement);
1743
1914
  }, [target]);
1744
1915
  React.useEffect(function () {
1745
1916
  if (typeof showProp === 'boolean') {
1746
1917
  setShowTooltip(showProp);
1747
1918
  }
1748
1919
  }, [showProp]);
1749
- // Get popper placement
1750
- var placement = (attributes.popper &&
1751
- attributes.popper['data-popper-placement']) ||
1752
- initialPlacement;
1753
- // Only listen to key ups when the tooltip is visible
1754
- useEscapeKey({
1755
- callback: function (event) {
1756
- event.preventDefault();
1757
- setShowTooltip(false);
1758
- },
1759
- capture: true,
1760
- active: showTooltip && typeof showProp !== 'boolean'
1761
- }, [setShowTooltip]);
1762
1920
  // Handle hover and focus events for the targetElement
1763
1921
  React.useEffect(function () {
1922
+ var targetElement = resolveElement(target);
1764
1923
  if (typeof showProp !== 'boolean') {
1765
1924
  targetElement === null || targetElement === void 0 ? void 0 : targetElement.addEventListener('mouseenter', show);
1766
1925
  targetElement === null || targetElement === void 0 ? void 0 : targetElement.addEventListener('mouseleave', hide);
@@ -1773,7 +1932,7 @@ function Tooltip(_a) {
1773
1932
  targetElement === null || targetElement === void 0 ? void 0 : targetElement.removeEventListener('focusin', show);
1774
1933
  targetElement === null || targetElement === void 0 ? void 0 : targetElement.removeEventListener('focusout', hide);
1775
1934
  };
1776
- }, [targetElement, show, hide, showProp]);
1935
+ }, [target, show, hide, showProp]);
1777
1936
  // Handle hover events for the tooltipElement
1778
1937
  React.useEffect(function () {
1779
1938
  if (typeof showProp !== 'boolean') {
@@ -1787,6 +1946,7 @@ function Tooltip(_a) {
1787
1946
  }, [tooltipElement, show, hide, showProp]);
1788
1947
  // Keep the target's id in sync
1789
1948
  React.useEffect(function () {
1949
+ var targetElement = resolveElement(target);
1790
1950
  if (hasAriaAssociation) {
1791
1951
  var idRefs = targetElement === null || targetElement === void 0 ? void 0 : targetElement.getAttribute(association);
1792
1952
  if (!hasIdRef(idRefs, id)) {
@@ -1799,14 +1959,14 @@ function Tooltip(_a) {
1799
1959
  targetElement.setAttribute(association, removeIdRef(idRefs, id));
1800
1960
  }
1801
1961
  };
1802
- }, [targetElement, id, association]);
1962
+ }, [target, id, association]);
1803
1963
  return (React__default["default"].createElement(React__default["default"].Fragment, null, (showTooltip || hideElementOnHidden) && isBrowser()
1804
- ? reactDom.createPortal(React__default["default"].createElement("div", tslib.__assign({ id: id, className: classNames__default["default"]('Tooltip', "Tooltip--".concat(placement), className, {
1964
+ ? 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, {
1805
1965
  TooltipInfo: variant === 'info',
1806
1966
  'Tooltip--hidden': !showTooltip && hideElementOnHidden,
1807
1967
  'Tooltip--big': variant === 'big'
1808
- }), ref: setTooltipElement, role: "tooltip", style: styles.popper }, attributes.popper, props),
1809
- variant !== 'big' && (React__default["default"].createElement("div", { className: "TooltipArrow", ref: setArrowElement, style: styles.arrow })),
1968
+ }), ref: setTooltipElement, role: "tooltip", offset: 8 }, props),
1969
+ variant !== 'big' && React__default["default"].createElement("div", { className: "TooltipArrow" }),
1810
1970
  children), (portal && 'current' in portal ? portal.current : portal) ||
1811
1971
  (
1812
1972
  // eslint-disable-next-line ssr-friendly/no-dom-globals-in-react-fc
@@ -2522,28 +2682,6 @@ var SearchField = React.forwardRef(function (_a, ref) {
2522
2682
  });
2523
2683
  SearchField.displayName = 'SearchField';
2524
2684
 
2525
- /**
2526
- * When a component needs to track an internal ref on a component that has a
2527
- * forwarded ref, useSharedRef will return a MutableRefObject<T> that will
2528
- * correctly invoke the parent ref as well providing an internal ref.
2529
- *
2530
- * @example
2531
- * React.forwardRef(function Component({ children }, ref) {
2532
- * const internalRef = useSharedRef<HTMLElement>(ref)
2533
- * if (internalRef.current) {
2534
- * // do something with the internal ref...
2535
- * }
2536
- * return (<div ref={internalRef}>...</div>)
2537
- * })
2538
- */
2539
- function useSharedRef(ref) {
2540
- var internalRef = React.useRef();
2541
- React.useEffect(function () {
2542
- setRef(ref, internalRef.current);
2543
- }, [ref]);
2544
- return internalRef;
2545
- }
2546
-
2547
2685
  function copyTextToClipboard(text) {
2548
2686
  return tslib.__awaiter(this, void 0, void 0, function () {
2549
2687
  var copied, element, range, selection;
@@ -2702,21 +2840,16 @@ var LoaderOverlay = React.forwardRef(function (_a, ref) {
2702
2840
  overlayRef.current.focus();
2703
2841
  }
2704
2842
  }, []);
2705
- var Wrapper = focusTrap ? FocusTrap__default["default"] : React__default["default"].Fragment;
2706
- var wrapperProps = focusTrap
2707
- ? {
2708
- focusTrapOptions: {
2709
- fallbackFocus: '.Loader__overlay'
2710
- }
2711
- }
2712
- : {};
2713
- return (React__default["default"].createElement(Wrapper, tslib.__assign({}, wrapperProps),
2714
- React__default["default"].createElement("div", tslib.__assign({ className: classNames__default["default"]('Loader__overlay', className), ref: overlayRef, tabIndex: -1 }, other),
2715
- React__default["default"].createElement("div", { className: "Loader__overlay__loader" },
2716
- React__default["default"].createElement(Loader, null),
2717
- React__default["default"].createElement(AxeLoader, null)),
2718
- label ? (React__default["default"].createElement("span", { className: "Loader__overlay__label" }, label)) : null,
2719
- children)));
2843
+ useFocusTrap(overlayRef, {
2844
+ disabled: !focusTrap,
2845
+ initialFocusElement: overlayRef
2846
+ });
2847
+ return (React__default["default"].createElement("div", tslib.__assign({ className: classNames__default["default"]('Loader__overlay', className), ref: overlayRef, tabIndex: -1 }, other),
2848
+ React__default["default"].createElement("div", { className: "Loader__overlay__loader" },
2849
+ React__default["default"].createElement(Loader, null),
2850
+ React__default["default"].createElement(AxeLoader, null)),
2851
+ label ? React__default["default"].createElement("span", { className: "Loader__overlay__label" }, label) : null,
2852
+ children));
2720
2853
  });
2721
2854
  LoaderOverlay.displayName = 'LoaderOverlay';
2722
2855
 
@@ -2800,6 +2933,16 @@ function useTable() {
2800
2933
  return React.useContext(TableContext);
2801
2934
  }
2802
2935
 
2936
+ function parseColumnWidth(width) {
2937
+ var number = Number(width);
2938
+ if (!isNaN(number)) {
2939
+ return "".concat(number, "px");
2940
+ }
2941
+ if (!width) {
2942
+ return 'auto';
2943
+ }
2944
+ return width;
2945
+ }
2803
2946
  var Table = React__default["default"].forwardRef(function (_a, ref) {
2804
2947
  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"]);
2805
2948
  var isGridLayout = layout === 'grid';
@@ -2820,8 +2963,11 @@ var Table = React__default["default"].forwardRef(function (_a, ref) {
2820
2963
  }
2821
2964
  return columns
2822
2965
  .map(function (_a) {
2823
- var width = _a.width;
2824
- return width || 'auto';
2966
+ var width = _a.width, maxWidth = _a.maxWidth;
2967
+ if (maxWidth) {
2968
+ return "minmax(".concat(parseColumnWidth(width), ", ").concat(parseColumnWidth(maxWidth), ")");
2969
+ }
2970
+ return parseColumnWidth(width);
2825
2971
  })
2826
2972
  .join(' ');
2827
2973
  }, [layout, columns]);
@@ -3389,16 +3535,14 @@ var TwoColumnPanel = React.forwardRef(function (_a, ref) {
3389
3535
  setCollapsed(true);
3390
3536
  }
3391
3537
  };
3538
+ useFocusTrap(columnLeftRef, {
3539
+ disabled: !showPanel || !isFocusTrap
3540
+ });
3392
3541
  return (React__default["default"].createElement("div", tslib.__assign({ className: classNames__default["default"]('TwoColumnPanel', className, {
3393
3542
  'TwoColumnPanel--show': !isCollapsed,
3394
3543
  'TwoColumnPanel--hide': isCollapsed
3395
3544
  }) }, props, { ref: ref }),
3396
3545
  React__default["default"].createElement(React__default["default"].Fragment, null,
3397
- React__default["default"].createElement(FocusTrap__default["default"], { active: !isCollapsed && isFocusTrap, focusTrapOptions: {
3398
- escapeDeactivates: true,
3399
- allowOutsideClick: true,
3400
- fallbackFocus: columnLeftRef.current
3401
- }, containerElements: [columnLeftRef.current] }),
3402
3546
  React__default["default"].createElement(ClickOutsideListener$1, { onClickOutside: handleClickOutside, target: columnLeftRef.current }),
3403
3547
  isCollapsed ? null : skipLink,
3404
3548
  showPanel ? ColumnLeftComponent : null,
@@ -3447,19 +3591,21 @@ var ListboxContext = React.createContext({
3447
3591
  options: [],
3448
3592
  active: null,
3449
3593
  selected: null,
3594
+ multiselect: false,
3450
3595
  setOptions: function () { return null; },
3451
3596
  onSelect: function () { return null; }
3452
3597
  });
3453
3598
  function ListboxProvider(_a) {
3454
- var options = _a.options, active = _a.active, selected = _a.selected, setOptions = _a.setOptions, onSelect = _a.onSelect, children = _a.children;
3599
+ var options = _a.options, active = _a.active, selected = _a.selected, multiselect = _a.multiselect, setOptions = _a.setOptions, onSelect = _a.onSelect, children = _a.children;
3455
3600
  var Provider = ListboxContext.Provider;
3456
3601
  var value = React.useMemo(function () { return ({
3457
3602
  options: options,
3458
3603
  active: active,
3459
3604
  selected: selected,
3605
+ multiselect: multiselect,
3460
3606
  setOptions: setOptions,
3461
3607
  onSelect: onSelect
3462
- }); }, [options, active, selected, setOptions]);
3608
+ }); }, [options, active, selected, multiselect, setOptions]);
3463
3609
  return React__default["default"].createElement(Provider, { value: value }, children);
3464
3610
  }
3465
3611
  function useListboxContext() {
@@ -3481,40 +3627,82 @@ var optionMatchesValue = function (option, value) {
3481
3627
  option.value === value;
3482
3628
  };
3483
3629
  var Listbox = React.forwardRef(function (_a, ref) {
3484
- 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"]);
3485
- var _d = tslib.__read(React.useState([]), 2), options = _d[0], setOptions = _d[1];
3486
- var _e = tslib.__read(React.useState(null), 2), activeOption = _e[0], setActiveOption = _e[1];
3487
- var _f = tslib.__read(React.useState(null), 2), selectedOption = _f[0], setSelectedOption = _f[1];
3630
+ 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"]);
3631
+ var _e = tslib.__read(React.useState([]), 2), options = _e[0], setOptions = _e[1];
3632
+ var _f = tslib.__read(React.useState(null), 2), activeOption = _f[0], setActiveOption = _f[1];
3633
+ var _g = tslib.__read(React.useState([]), 2), selectedOptions = _g[0], setSelectedOptions = _g[1];
3488
3634
  var listboxRef = useSharedRef(ref);
3489
3635
  var isControlled = typeof value !== 'undefined';
3490
3636
  React.useLayoutEffect(function () {
3491
- if (!isControlled && selectedOption) {
3637
+ if (!isControlled && selectedOptions.length > 0) {
3492
3638
  return;
3493
3639
  }
3494
3640
  var listboxValue = isControlled ? value : defaultValue;
3495
- var matchingOption = options.find(function (option) {
3496
- return optionMatchesValue(option, listboxValue);
3497
- });
3498
- setSelectedOption(matchingOption || null);
3499
- setActiveOption(matchingOption || null);
3500
- }, [isControlled, options, value]);
3641
+ if (!listboxValue) {
3642
+ return;
3643
+ }
3644
+ if (multiselect) {
3645
+ var matchingOptions = options.filter(function (option) {
3646
+ return listboxValue.find(function (value) {
3647
+ return optionMatchesValue(option, value);
3648
+ });
3649
+ });
3650
+ setSelectedOptions(matchingOptions);
3651
+ if (!activeOption) {
3652
+ setActiveOption(matchingOptions[0] || null);
3653
+ }
3654
+ }
3655
+ else {
3656
+ var matchingOption = options.find(function (option) {
3657
+ return optionMatchesValue(option, listboxValue);
3658
+ });
3659
+ setSelectedOptions(matchingOption ? [matchingOption] : []);
3660
+ if (!activeOption) {
3661
+ setActiveOption(matchingOption || null);
3662
+ }
3663
+ }
3664
+ }, [isControlled, options, value, defaultValue, activeOption]);
3501
3665
  React.useEffect(function () {
3502
3666
  if (activeOption) {
3503
3667
  onActiveChange === null || onActiveChange === void 0 ? void 0 : onActiveChange(activeOption);
3504
3668
  }
3505
3669
  }, [activeOption]);
3506
3670
  var handleSelect = React.useCallback(function (option) {
3671
+ var _a;
3507
3672
  setActiveOption(option);
3673
+ var optionIsSelected = selectedOptions.some(function (selected) { return selected.element === option.element; });
3674
+ var previousValues = selectedOptions.map(function (selected) { return selected.value; });
3508
3675
  // istanbul ignore else
3509
3676
  if (!isControlled) {
3510
- setSelectedOption(option);
3677
+ if (!multiselect) {
3678
+ setSelectedOptions([option]);
3679
+ }
3680
+ else {
3681
+ setSelectedOptions(optionIsSelected
3682
+ ? tslib.__spreadArray([], tslib.__read(selectedOptions.filter(function (selected) { return selected.element !== option.element; })), false) : tslib.__spreadArray(tslib.__spreadArray([], tslib.__read(selectedOptions), false), [option], false));
3683
+ }
3511
3684
  }
3512
- onSelectionChange === null || onSelectionChange === void 0 ? void 0 : onSelectionChange({
3513
- target: option.element,
3514
- value: option.value,
3515
- previousValue: selectedOption === null || selectedOption === void 0 ? void 0 : selectedOption.value
3516
- });
3517
- }, [isControlled, selectedOption]);
3685
+ if (multiselect) {
3686
+ onSelectionChange === null || onSelectionChange === void 0 ? void 0 : onSelectionChange({
3687
+ target: option.element,
3688
+ value: optionIsSelected
3689
+ ? selectedOptions
3690
+ .filter(function (selectedOption) {
3691
+ return selectedOption.element !== option.element;
3692
+ })
3693
+ .map(function (selectedOption) { return selectedOption.value; })
3694
+ : tslib.__spreadArray(tslib.__spreadArray([], tslib.__read(previousValues), false), [option.value], false),
3695
+ previousValue: previousValues
3696
+ });
3697
+ }
3698
+ else {
3699
+ onSelectionChange === null || onSelectionChange === void 0 ? void 0 : onSelectionChange({
3700
+ target: option.element,
3701
+ value: option.value,
3702
+ previousValue: (_a = selectedOptions[0]) === null || _a === void 0 ? void 0 : _a.value
3703
+ });
3704
+ }
3705
+ }, [isControlled, selectedOptions, multiselect, onSelectionChange]);
3518
3706
  var handleKeyDown = React.useCallback(function (event) {
3519
3707
  onKeyDown === null || onKeyDown === void 0 ? void 0 : onKeyDown(event);
3520
3708
  if (!keys.includes(event.key)) {
@@ -3564,9 +3752,9 @@ var Listbox = React.forwardRef(function (_a, ref) {
3564
3752
  activeOption && handleSelect(activeOption);
3565
3753
  break;
3566
3754
  }
3567
- }, [options, activeOption, navigation]);
3755
+ }, [options, activeOption, navigation, handleSelect]);
3568
3756
  var handleFocus = React.useCallback(function (event) {
3569
- if (!activeOption && !selectedOption) {
3757
+ if (!activeOption) {
3570
3758
  var firstOption = options.find(function (option) { return !isDisabledOption(option); });
3571
3759
  // istanbul ignore else
3572
3760
  if (firstOption) {
@@ -3574,13 +3762,14 @@ var Listbox = React.forwardRef(function (_a, ref) {
3574
3762
  }
3575
3763
  // istanbul ignore else
3576
3764
  }
3577
- else if (event.target === listboxRef.current) {
3578
- setActiveOption(selectedOption);
3765
+ else if (selectedOptions.length &&
3766
+ event.target === listboxRef.current) {
3767
+ setActiveOption(selectedOptions[selectedOptions.length - 1]);
3579
3768
  }
3580
3769
  onFocus === null || onFocus === void 0 ? void 0 : onFocus(event);
3581
- }, [options, activeOption, selectedOption]);
3582
- 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),
3583
- React__default["default"].createElement(ListboxProvider, { options: options, active: activeOption, selected: selectedOption, setOptions: setOptions, onSelect: handleSelect }, children)));
3770
+ }, [options, activeOption, selectedOptions]);
3771
+ 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),
3772
+ React__default["default"].createElement(ListboxProvider, { options: options, active: activeOption, multiselect: multiselect, selected: selectedOptions, setOptions: setOptions, onSelect: handleSelect }, children)));
3584
3773
  });
3585
3774
  Listbox.displayName = 'Listbox';
3586
3775
 
@@ -3590,12 +3779,15 @@ function isElementPreceding(a, b) {
3590
3779
  var ListboxOption = React.forwardRef(function (_a, ref) {
3591
3780
  var _b;
3592
3781
  var _c;
3593
- 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"]);
3782
+ 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"]);
3594
3783
  var _f = useListboxContext(), active = _f.active, selected = _f.selected, setOptions = _f.setOptions, onSelect = _f.onSelect;
3595
3784
  var listboxOptionRef = useSharedRef(ref);
3596
3785
  var _g = tslib.__read(propId ? [propId] : nextId.useId(1, 'listbox-option'), 1), id = _g[0];
3597
- var isActive = active !== null && active.element === listboxOptionRef.current;
3598
- var isSelected = selected !== null && selected.element === listboxOptionRef.current;
3786
+ var isActive = (active === null || active === void 0 ? void 0 : active.element) === listboxOptionRef.current;
3787
+ var isSelected = typeof selectedProp === 'boolean'
3788
+ ? selectedProp
3789
+ : selected !== null &&
3790
+ !!selected.find(function (option) { return option.element === listboxOptionRef.current; });
3599
3791
  var optionValue = typeof value !== 'undefined'
3600
3792
  ? value
3601
3793
  : (_c = listboxOptionRef.current) === null || _c === void 0 ? void 0 : _c.innerText;
@@ -3645,7 +3837,7 @@ var ListboxOption = React.forwardRef(function (_a, ref) {
3645
3837
  }
3646
3838
  onSelect({ element: listboxOptionRef.current, value: optionValue });
3647
3839
  onClick === null || onClick === void 0 ? void 0 : onClick(event);
3648
- }, [optionValue]);
3840
+ }, [optionValue, onSelect, onClick, disabled]);
3649
3841
  return (React__default["default"].createElement(Component, tslib.__assign({ id: id, className: classNames__default["default"](className, (_b = {},
3650
3842
  _b[activeClass] = isActive,
3651
3843
  _b)), role: "option", ref: listboxOptionRef, "aria-disabled": typeof disabled === 'boolean' ? disabled : undefined, "aria-selected": isSelected, onClick: handleClick }, props), children));
@@ -3767,17 +3959,20 @@ var ComboboxMatch = function (_a) {
3767
3959
  React__default["default"].createElement("span", null, matchAfter)));
3768
3960
  };
3769
3961
  var ComboboxOption = React.forwardRef(function (_a, ref) {
3962
+ var _b;
3770
3963
  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"]);
3771
- var _b = tslib.__read(propId ? [propId] : nextId.useId(1, 'combobox-option'), 1), id = _b[0];
3772
- var _c = useListboxContext(), selected = _c.selected, active = _c.active;
3773
- var _d = useComboboxContext(), selectedValue = _d.selectedValue, matches = _d.matches, setMatchingOptions = _d.setMatchingOptions, setFormValue = _d.setFormValue;
3964
+ var _c = tslib.__read(propId ? [propId] : nextId.useId(1, 'combobox-option'), 1), id = _c[0];
3965
+ var _d = useListboxContext(), selected = _d.selected, active = _d.active;
3966
+ var _e = useComboboxContext(), selectedValue = _e.selectedValue, matches = _e.matches, setMatchingOptions = _e.setMatchingOptions, setFormValue = _e.setFormValue;
3774
3967
  var comboboxOptionRef = useSharedRef(ref);
3775
3968
  var intersectionRef = useIntersectionRef(comboboxOptionRef, {
3776
3969
  root: null,
3777
3970
  threshold: 1.0
3778
3971
  });
3779
3972
  var isActive = !!(active === null || active === void 0 ? void 0 : active.element) && active.element === comboboxOptionRef.current;
3780
- var isSelected = !!(selected === null || selected === void 0 ? void 0 : selected.element) && selected.element === comboboxOptionRef.current;
3973
+ var isSelected = !!(selected &&
3974
+ !!((_b = selected[0]) === null || _b === void 0 ? void 0 : _b.element) &&
3975
+ selected[0].element === comboboxOptionRef.current);
3781
3976
  var isMatching = (typeof matches === 'boolean' && matches) ||
3782
3977
  (typeof matches === 'function' && matches(children));
3783
3978
  // istanbul ignore next
@@ -4113,19 +4308,7 @@ var Popover = React.forwardRef(function (_a, ref) {
4113
4308
  var _f = tslib.__read(React.useState(null), 2), targetElement = _f[0], setTargetElement = _f[1];
4114
4309
  var _g = tslib.__read(React.useState(null), 2), isolator = _g[0], setIsolator = _g[1];
4115
4310
  var popoverRef = useSharedRef(ref);
4116
- var _h = tslib.__read(React.useState(null), 2), arrowElement = _h[0], setArrowElement = _h[1];
4117
- var _j = reactPopper.usePopper(targetElement, popoverRef === null || popoverRef === void 0 ? void 0 : popoverRef.current, {
4118
- placement: initialPlacement,
4119
- modifiers: [
4120
- { name: 'preventOverflow', options: { padding: 8 } },
4121
- { name: 'flip' },
4122
- { name: 'offset', options: { offset: [0, 8] } },
4123
- { name: 'arrow', options: { padding: 5, element: arrowElement } }
4124
- ]
4125
- }), styles = _j.styles, attributes = _j.attributes;
4126
- var placement = (attributes.popper &&
4127
- attributes.popper['data-popper-placement']) ||
4128
- initialPlacement;
4311
+ var _h = tslib.__read(React.useState(initialPlacement), 2), placement = _h[0], setPlacement = _h[1];
4129
4312
  var additionalProps = variant === 'prompt' && !props['aria-label']
4130
4313
  ? { 'aria-labelledby': "".concat(id, "-label") }
4131
4314
  : {};
@@ -4157,15 +4340,8 @@ var Popover = React.forwardRef(function (_a, ref) {
4157
4340
  attachIsolator();
4158
4341
  }, [popoverRef.current]);
4159
4342
  React.useEffect(function () {
4160
- if (show && popoverRef.current) {
4161
- // Find the first focusable element inside the container
4162
- var firstFocusableElement = popoverRef.current.querySelector(focusableSelector);
4163
- if (firstFocusableElement instanceof HTMLElement) {
4164
- firstFocusableElement.focus();
4165
- }
4166
- }
4167
4343
  targetElement === null || targetElement === void 0 ? void 0 : targetElement.setAttribute('aria-expanded', Boolean(show).toString());
4168
- }, [show, popoverRef.current]);
4344
+ }, [show]);
4169
4345
  React.useEffect(function () {
4170
4346
  var attrText = targetElement === null || targetElement === void 0 ? void 0 : targetElement.getAttribute('aria-controls');
4171
4347
  var hasPopupAttr = targetElement === null || targetElement === void 0 ? void 0 : targetElement.getAttribute('aria-haspopup');
@@ -4199,20 +4375,17 @@ var Popover = React.forwardRef(function (_a, ref) {
4199
4375
  callback: handleClosePopover,
4200
4376
  active: show
4201
4377
  }, [show]);
4378
+ useFocusTrap(popoverRef, { disabled: !show, returnFocus: true });
4202
4379
  if (!show || !isBrowser())
4203
4380
  return null;
4204
- return reactDom.createPortal(React__default["default"].createElement(FocusTrap__default["default"], { focusTrapOptions: {
4205
- allowOutsideClick: true,
4206
- fallbackFocus: '.Popover__borderLeft'
4207
- } },
4208
- React__default["default"].createElement(ClickOutsideListener$1, { onClickOutside: handleClickOutside },
4209
- React__default["default"].createElement("div", tslib.__assign({ id: id, className: classNames__default["default"]('Popover', "Popover--".concat(placement), className, {
4210
- 'Popover--hidden': !show,
4211
- 'Popover--prompt': variant === 'prompt'
4212
- }), ref: popoverRef, role: "dialog", style: styles.popper }, attributes.popper, additionalProps, props),
4213
- React__default["default"].createElement("div", { className: "Popover__popoverArrow", ref: setArrowElement, style: styles.arrow }),
4214
- React__default["default"].createElement("div", { className: "Popover__borderLeft" }),
4215
- 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) ||
4381
+ return reactDom.createPortal(React__default["default"].createElement(ClickOutsideListener$1, { onClickOutside: handleClickOutside },
4382
+ React__default["default"].createElement(AnchoredOverlay, tslib.__assign({ id: id, className: classNames__default["default"]('Popover', "Popover--".concat(placement), className, {
4383
+ 'Popover--hidden': !show,
4384
+ 'Popover--prompt': variant === 'prompt'
4385
+ }), ref: popoverRef, role: "dialog", target: target, open: show, placement: initialPlacement, onPlacementChange: setPlacement, offset: 8 }, additionalProps, props),
4386
+ React__default["default"].createElement("div", { className: "Popover__popoverArrow" }),
4387
+ React__default["default"].createElement("div", { className: "Popover__borderLeft" }),
4388
+ 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) ||
4216
4389
  // Dependent on "isBrowser" check above:
4217
4390
  // eslint-disable-next-line ssr-friendly/no-dom-globals-in-react-fc
4218
4391
  document.body);
@@ -4280,7 +4453,6 @@ var Drawer = React.forwardRef(function (_a, ref) {
4280
4453
  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"]);
4281
4454
  var drawerRef = useSharedRef(ref);
4282
4455
  var openRef = React.useRef(!!open);
4283
- var previousActiveElementRef = React.useRef(null);
4284
4456
  var focusInitial = focusOptions.initialFocus, focusReturn = focusOptions.returnFocus;
4285
4457
  var _e = tslib.__read(React.useState(!!open), 2), isTransitioning = _e[0], setIsTransitioning = _e[1];
4286
4458
  var isModal = behavior === 'modal';
@@ -4320,60 +4492,27 @@ var Drawer = React.forwardRef(function (_a, ref) {
4320
4492
  isolator.deactivate();
4321
4493
  };
4322
4494
  }, [isModal, open]);
4323
- React.useLayoutEffect(function () {
4324
- var _a, _b, _c;
4325
- if (open) {
4326
- previousActiveElementRef.current =
4327
- document.activeElement;
4328
- var initialFocusElement = resolveElement(focusInitial);
4329
- if (initialFocusElement) {
4330
- initialFocusElement.focus();
4331
- }
4332
- else {
4333
- var focusable = (_a = drawerRef.current) === null || _a === void 0 ? void 0 : _a.querySelector(focusableSelector);
4334
- if (focusable) {
4335
- focusable.focus();
4336
- }
4337
- else {
4338
- // fallback focus
4339
- (_b = drawerRef.current) === null || _b === void 0 ? void 0 : _b.focus();
4340
- }
4341
- }
4342
- }
4343
- else if (previousActiveElementRef.current) {
4344
- var returnFocusElement = resolveElement(focusReturn);
4345
- if (returnFocusElement) {
4346
- returnFocusElement.focus();
4347
- }
4348
- else {
4349
- // fallback focus
4350
- (_c = previousActiveElementRef.current) === null || _c === void 0 ? void 0 : _c.focus();
4351
- }
4352
- }
4353
- }, [open, focusInitial, focusReturn]);
4354
4495
  useEscapeKey({ callback: handleClose, active: open, defaultPrevented: true }, [onClose]);
4355
4496
  // istanbul ignore next
4356
4497
  if (!isBrowser()) {
4357
4498
  return null;
4358
4499
  }
4500
+ useFocusTrap(drawerRef, {
4501
+ disabled: !isModal || !open,
4502
+ initialFocusElement: focusInitial || drawerRef,
4503
+ returnFocus: true,
4504
+ returnFocusElement: focusReturn
4505
+ });
4359
4506
  var portalElement = resolveElement(portal);
4360
4507
  return reactDom.createPortal(React__default["default"].createElement(React__default["default"].Fragment, null,
4361
4508
  React__default["default"].createElement(ClickOutsideListener$1, { onClickOutside: handleClose, mouseEvent: open ? undefined : false, touchEvent: open ? undefined : false, target: drawerRef },
4362
- React__default["default"].createElement(FocusTrap__default["default"], { active: !!isModal && !!open, focusTrapOptions: {
4363
- allowOutsideClick: true,
4364
- escapeDeactivates: false,
4365
- clickOutsideDeactivates: false,
4366
- initialFocus: false,
4367
- setReturnFocus: false,
4368
- fallbackFocus: function () { return drawerRef.current; }
4369
- } },
4370
- React__default["default"].createElement("div", tslib.__assign({ ref: drawerRef, className: classNames__default["default"](className, 'Drawer', {
4371
- 'Drawer--open': !!open,
4372
- 'Drawer--top': position === 'top',
4373
- 'Drawer--bottom': position === 'bottom',
4374
- 'Drawer--left': position === 'left',
4375
- 'Drawer--right': position === 'right'
4376
- }), "aria-hidden": !open || undefined, style: tslib.__assign({ visibility: !open && !isTransitioning ? 'hidden' : undefined }, style), tabIndex: open ? -1 : undefined }, props), children))),
4509
+ React__default["default"].createElement("div", tslib.__assign({ ref: drawerRef, className: classNames__default["default"](className, 'Drawer', {
4510
+ 'Drawer--open': !!open,
4511
+ 'Drawer--top': position === 'top',
4512
+ 'Drawer--bottom': position === 'bottom',
4513
+ 'Drawer--left': position === 'left',
4514
+ 'Drawer--right': position === 'right'
4515
+ }), "aria-hidden": !open || undefined, style: tslib.__assign({ visibility: !open && !isTransitioning ? 'hidden' : undefined }, style), tabIndex: open ? -1 : undefined }, props), children)),
4377
4516
  React__default["default"].createElement(Scrim, { show: !!open && !!isModal })), portalElement ||
4378
4517
  (
4379
4518
  // eslint-disable-next-line ssr-friendly/no-dom-globals-in-react-fc
@@ -4479,6 +4618,7 @@ exports.AddressLine = AddressLine;
4479
4618
  exports.Alert = Alert;
4480
4619
  exports.AlertActions = AlertActions;
4481
4620
  exports.AlertContent = AlertContent;
4621
+ exports.AnchoredOverlay = AnchoredOverlay;
4482
4622
  exports.AriaIsolate = AriaIsolate;
4483
4623
  exports.Badge = Badge;
4484
4624
  exports.BadgeLabel = BadgeLabel;