@deque/cauldron-react 7.1.0-canary.1107761f → 7.1.0-canary.2ada12a9

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.
@@ -1,6 +1,6 @@
1
1
  import React from 'react';
2
2
  import { type ActionListSelectionType, type onActionCallbackFunction } from './ActionListContext';
3
- interface ActionListProps extends React.HTMLAttributes<HTMLUListElement> {
3
+ interface ActionListProps extends Omit<React.HTMLAttributes<HTMLUListElement>, 'defaultValue' | 'onSelect'> {
4
4
  children: React.ReactNode;
5
5
  /** Limits the amount of selections that can be made within an action list */
6
6
  selectionType?: ActionListSelectionType | null;
@@ -1,7 +1,7 @@
1
1
  import React from 'react';
2
2
  import type { ListboxOption } from './ListboxContext';
3
3
  import type { ListboxValue } from './ListboxOption';
4
- import type { PolymorphicProps, PolymorphicComponent } from '../../utils/polymorphicComponent';
4
+ import type { PolymorphicProps, PolymorphicComponentProps } from '../../utils/polymorphicComponent';
5
5
  interface BaseListboxProps extends PolymorphicProps<Omit<React.HTMLAttributes<HTMLElement>, 'onSelect' | 'defaultValue'>> {
6
6
  navigation?: 'cycle' | 'bound';
7
7
  focusStrategy?: 'lastSelected' | 'first' | 'last';
@@ -30,5 +30,10 @@ interface MultiSelectListboxProps extends BaseListboxProps {
30
30
  value: ListboxValue[];
31
31
  }) => void;
32
32
  }
33
- declare const Listbox: PolymorphicComponent<SingleSelectListboxProps | MultiSelectListboxProps>;
33
+ type ListboxComponent = Omit<React.ForwardRefExoticComponent<SingleSelectListboxProps | MultiSelectListboxProps>, keyof CallableFunction> & {
34
+ <T extends React.ElementType = React.ElementType>(props: PolymorphicComponentProps<MultiSelectListboxProps, T>): React.ReactElement | null;
35
+ <T extends React.ElementType = React.ElementType>(props: PolymorphicComponentProps<SingleSelectListboxProps, T>): React.ReactElement | null;
36
+ <T extends React.ElementType = React.ElementType>(props: PolymorphicComponentProps<SingleSelectListboxProps | MultiSelectListboxProps, T>): React.ReactElement | null;
37
+ };
38
+ declare const Listbox: ListboxComponent;
34
39
  export default Listbox;
package/lib/index.js CHANGED
@@ -809,7 +809,7 @@ function resolveElement(elementOrRef) {
809
809
 
810
810
  function ClickOutsideListener(_a, ref) {
811
811
  var children = _a.children, _b = _a.mouseEvent, mouseEvent = _b === void 0 ? 'click' : _b, _c = _a.touchEvent, touchEvent = _c === void 0 ? 'touchend' : _c, target = _a.target, _d = _a.onClickOutside, onClickOutside = _d === void 0 ? function () { return null; } : _d;
812
- var childElementRef = React.useRef();
812
+ var childElementRef = React.useRef(null);
813
813
  var handleEvent = function (event) {
814
814
  if (event.defaultPrevented) {
815
815
  return;
@@ -1343,7 +1343,7 @@ var AriaIsolate = /** @class */ (function () {
1343
1343
 
1344
1344
  /**
1345
1345
  * When a component needs to track an internal ref on a component that has a
1346
- * forwarded ref, useSharedRef will return a MutableRefObject<T> that will
1346
+ * forwarded ref, useSharedRef will return a MutableRefObject<T | null> that will
1347
1347
  * correctly invoke the parent ref as well providing an internal ref.
1348
1348
  *
1349
1349
  * @example
@@ -1356,7 +1356,7 @@ var AriaIsolate = /** @class */ (function () {
1356
1356
  * })
1357
1357
  */
1358
1358
  function useSharedRef(ref) {
1359
- var internalRef = React.useRef();
1359
+ var internalRef = React.useRef(null);
1360
1360
  React.useEffect(function () {
1361
1361
  setRef(ref, internalRef.current);
1362
1362
  return function () { return setRef(ref, null); };
@@ -1489,7 +1489,7 @@ function useFocusTrap(target, options) {
1489
1489
  if (options === void 0) { options = {}; }
1490
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
1491
  var focusTrap = React.useRef(null);
1492
- var returnFocusElementRef = React.useRef();
1492
+ var returnFocusElementRef = React.useRef(null);
1493
1493
  function restoreFocusToReturnFocusElement() {
1494
1494
  var _a;
1495
1495
  var resolvedReturnFocusElement = resolveElement(returnFocusElement);
@@ -1539,7 +1539,7 @@ var Dialog = React.forwardRef(function (_a, ref) {
1539
1539
  var dialogRef = useSharedRef(dialogRefProp || ref);
1540
1540
  var _g = tslib.__read(nextId.useId(1, 'dialog-title-'), 1), headingId = _g[0];
1541
1541
  var headingRef = React.useRef(null);
1542
- var isolatorRef = React.useRef();
1542
+ var isolatorRef = React.useRef(null);
1543
1543
  var headingLevel = typeof heading === 'object' && 'level' in heading && heading.level
1544
1544
  ? heading.level
1545
1545
  : 2;
@@ -2134,7 +2134,7 @@ var looksLikeLink = function (props) {
2134
2134
  };
2135
2135
  var IconButton = React.forwardRef(function (_a, ref) {
2136
2136
  var _b = _a.as, Component = _b === void 0 ? 'button' : _b, icon = _a.icon, label = _a.label, _c = _a.tooltipProps, tooltipPropsProp = _c === void 0 ? {} : _c, className = _a.className, _d = _a.variant, variant = _d === void 0 ? 'secondary' : _d, disabled = _a.disabled, _e = _a.tabIndex, tabIndex = _e === void 0 ? 0 : _e, large = _a.large, other = tslib.__rest(_a, ["as", "icon", "label", "tooltipProps", "className", "variant", "disabled", "tabIndex", "large"]);
2137
- var internalRef = React.useRef();
2137
+ var internalRef = React.useRef(null);
2138
2138
  React.useImperativeHandle(ref, function () { return internalRef.current; });
2139
2139
  // Configure additional properties based on the type of the Component
2140
2140
  // for accessibility
@@ -2696,7 +2696,7 @@ Checkbox.displayName = 'Checkbox';
2696
2696
  */
2697
2697
  function TooltipTabstop(_a) {
2698
2698
  var children = _a.children, className = _a.className, tooltip = _a.tooltip, variant = _a.variant, association = _a.association, show = _a.show, placement = _a.placement, portal = _a.portal, hideElementOnHidden = _a.hideElementOnHidden, buttonProps = tslib.__rest(_a, ["children", "className", "tooltip", "variant", "association", "show", "placement", "portal", "hideElementOnHidden"]);
2699
- var buttonRef = React.useRef();
2699
+ var buttonRef = React.useRef(null);
2700
2700
  return (React__default["default"].createElement(React__default["default"].Fragment, null,
2701
2701
  React__default["default"].createElement("button", tslib.__assign({ type: "button", ref: buttonRef, "aria-disabled": "true", className: classNames__default["default"]('TooltipTabstop', className) }, buttonProps), children),
2702
2702
  React__default["default"].createElement(Tooltip, { target: buttonRef, variant: variant, association: association, show: show, placement: placement, portal: portal, hideElementOnHidden: hideElementOnHidden }, tooltip)));
@@ -3950,10 +3950,10 @@ var ListboxOption = React.forwardRef(function (_a, ref) {
3950
3950
  var element = listboxOptionRef.current;
3951
3951
  setOptions(function (options) {
3952
3952
  var e_1, _a;
3953
- var option = { element: element, value: optionValue };
3954
3953
  // istanbul ignore next
3955
3954
  if (!element)
3956
3955
  return options;
3956
+ var option = { element: element, value: optionValue };
3957
3957
  // Elements are frequently appended, so check to see if the newly rendered
3958
3958
  // element follows the last element first before any other checks
3959
3959
  if (!options.length ||
@@ -3990,7 +3990,7 @@ var ListboxOption = React.forwardRef(function (_a, ref) {
3990
3990
  if (disabled) {
3991
3991
  return;
3992
3992
  }
3993
- onSelect({ element: listboxOptionRef.current, value: optionValue });
3993
+ onSelect({ element: event.target, value: optionValue });
3994
3994
  onClick === null || onClick === void 0 ? void 0 : onClick(event);
3995
3995
  }, [optionValue, onSelect, onClick, disabled]);
3996
3996
  return (React__default["default"].createElement(Component, tslib.__assign({ id: id, className: classNames__default["default"](className, (_b = {},
@@ -4140,7 +4140,7 @@ var ComboboxOption = React.forwardRef(function (_a, ref) {
4140
4140
  // istanbul ignore next
4141
4141
  React.useLayoutEffect(function () {
4142
4142
  var intersectionEntry = intersectionRef.current;
4143
- if (!intersectionEntry || !isActive) {
4143
+ if (!intersectionEntry || !isActive || !comboboxOptionRef.current) {
4144
4144
  return;
4145
4145
  }
4146
4146
  var rect = comboboxOptionRef.current.getBoundingClientRect();
@@ -4184,6 +4184,8 @@ var ComboboxOption = React.forwardRef(function (_a, ref) {
4184
4184
  ? propValue
4185
4185
  : (_a = comboboxOptionRef.current) === null || _a === void 0 ? void 0 : _a.innerText;
4186
4186
  setMatchingOptions(function (options) {
4187
+ if (!comboboxOptionRef.current)
4188
+ return options;
4187
4189
  return new Map(options.set(comboboxOptionRef.current, {
4188
4190
  value: comboboxValue_1,
4189
4191
  displayValue: children,
@@ -4323,6 +4325,17 @@ var Combobox = React.forwardRef(function (_a, ref) {
4323
4325
  return value === lastSelectedValue;
4324
4326
  }) || [], 2), element = _a[0], option = _a[1];
4325
4327
  if (autocomplete === 'manual') {
4328
+ // In multiselect, the listbox manages its own active option via
4329
+ // keyboard navigation. When the last-selected value no longer
4330
+ // matches any option (e.g. after deselecting the only selected
4331
+ // option), preserve the existing active descendant so the next
4332
+ // Enter keypress can re-toggle the highlighted option.
4333
+ if (multiselect &&
4334
+ !element &&
4335
+ activeDescendant &&
4336
+ matchingOptions.has(activeDescendant.element)) {
4337
+ return;
4338
+ }
4326
4339
  setActiveDescendant(!element ? null : tslib.__assign({ element: element }, option));
4327
4340
  }
4328
4341
  else if (autocomplete === 'automatic' &&
@@ -4502,6 +4515,7 @@ var Combobox = React.forwardRef(function (_a, ref) {
4502
4515
  });
4503
4516
  }, [disabled, selectedValues, onSelectionChange]);
4504
4517
  var handlePillKeyDown = React.useCallback(function (event) {
4518
+ var _a, _b;
4505
4519
  if (!PillKeys.includes(event.key)) {
4506
4520
  return;
4507
4521
  }
@@ -4519,7 +4533,7 @@ var Combobox = React.forwardRef(function (_a, ref) {
4519
4533
  handleRemovePill(pillsRef.current[focusedIndex], selectedValues[focusedIndex]);
4520
4534
  var nextIndex = focusedIndex + 1;
4521
4535
  if (nextIndex == pillsLength) {
4522
- inputRef.current.focus();
4536
+ (_a = inputRef.current) === null || _a === void 0 ? void 0 : _a.focus();
4523
4537
  }
4524
4538
  else {
4525
4539
  pillsRef.current[nextIndex].focus();
@@ -4528,7 +4542,7 @@ var Combobox = React.forwardRef(function (_a, ref) {
4528
4542
  else if (isArrowLeft || isArrowRight) {
4529
4543
  var nextIndex = Math.max(focusedIndex + (isArrowLeft ? -1 : 1), 0);
4530
4544
  if (isArrowRight && nextIndex === pillsLength) {
4531
- inputRef.current.focus();
4545
+ (_b = inputRef.current) === null || _b === void 0 ? void 0 : _b.focus();
4532
4546
  }
4533
4547
  else {
4534
4548
  pillsRef.current[nextIndex].focus();
@@ -4816,10 +4830,12 @@ var TextEllipsis = React__default["default"].forwardRef(function (_a, ref) {
4816
4830
  : overflowElement.clientWidth < overflowElement.scrollWidth);
4817
4831
  });
4818
4832
  };
4833
+ if (!sharedRef.current)
4834
+ return;
4819
4835
  var observer = new ResizeObserver(listener);
4820
4836
  observer.observe(sharedRef.current);
4821
4837
  return function () {
4822
- observer === null || observer === void 0 ? void 0 : observer.disconnect();
4838
+ observer.disconnect();
4823
4839
  };
4824
4840
  }, []);
4825
4841
  React.useEffect(function () {
@@ -4864,7 +4880,7 @@ var Drawer = React.forwardRef(function (_a, ref) {
4864
4880
  openRef.current = open;
4865
4881
  }, [open, setIsTransitioning]);
4866
4882
  React.useEffect(function () {
4867
- if (!isModal) {
4883
+ if (!isModal || !drawerRef.current) {
4868
4884
  return;
4869
4885
  }
4870
4886
  var isolator = new AriaIsolate(drawerRef.current);
@@ -5045,7 +5061,7 @@ function getActiveElement(root) {
5045
5061
  */
5046
5062
  function useMnemonics(_a) {
5047
5063
  var elementOrRef = _a.elementOrRef, matchingElementsSelector = _a.matchingElementsSelector, onMatch = _a.onMatch, _b = _a.enabled, enabled = _b === void 0 ? true : _b;
5048
- var containerRef = React.useRef();
5064
+ var containerRef = React.useRef(null);
5049
5065
  React.useEffect(function () {
5050
5066
  if (elementOrRef instanceof HTMLElement) {
5051
5067
  containerRef.current = elementOrRef;
@@ -5055,7 +5071,8 @@ function useMnemonics(_a) {
5055
5071
  }
5056
5072
  }, [elementOrRef]);
5057
5073
  React.useEffect(function () {
5058
- if (!enabled || !containerRef.current) {
5074
+ var listenerTarget = containerRef.current;
5075
+ if (!enabled || !listenerTarget) {
5059
5076
  return;
5060
5077
  }
5061
5078
  var keyboardHandler = function (event) {
@@ -5068,14 +5085,14 @@ function useMnemonics(_a) {
5068
5085
  if (event.key.length !== 1 || !/[a-z\d]/i.test(event.key)) {
5069
5086
  return;
5070
5087
  }
5071
- var container = containerRef.current;
5072
- if (!container) {
5088
+ var currentContainer = containerRef.current;
5089
+ if (!currentContainer) {
5073
5090
  return;
5074
5091
  }
5075
5092
  // Prevent default behavior and stop propagation for mnemonic keys
5076
5093
  event.preventDefault();
5077
5094
  event.stopPropagation();
5078
- var elements = Array.from(container.querySelectorAll(matchingElementsSelector !== null && matchingElementsSelector !== void 0 ? matchingElementsSelector : focusable__default["default"]));
5095
+ var elements = Array.from(currentContainer.querySelectorAll(matchingElementsSelector !== null && matchingElementsSelector !== void 0 ? matchingElementsSelector : focusable__default["default"]));
5079
5096
  var matchingElements = elements.filter(function (element) {
5080
5097
  return getAccessibleLabel(element).toLowerCase()[0] ===
5081
5098
  event.key.toLowerCase();
@@ -5083,7 +5100,7 @@ function useMnemonics(_a) {
5083
5100
  if (!matchingElements.length) {
5084
5101
  return;
5085
5102
  }
5086
- var currentActiveElement = getActiveElement(containerRef.current);
5103
+ var currentActiveElement = getActiveElement(currentContainer);
5087
5104
  var nextActiveElement = null;
5088
5105
  if (currentActiveElement) {
5089
5106
  nextActiveElement = matchingElements.find(function (element) {
@@ -5097,17 +5114,15 @@ function useMnemonics(_a) {
5097
5114
  onMatch(nextActiveElement !== null && nextActiveElement !== void 0 ? nextActiveElement : matchingElements[0]);
5098
5115
  }
5099
5116
  };
5100
- var container = containerRef.current;
5101
- container.addEventListener('keydown', keyboardHandler);
5102
- return function () { return container.removeEventListener('keydown', keyboardHandler); };
5117
+ listenerTarget.addEventListener('keydown', keyboardHandler);
5118
+ return function () { return listenerTarget.removeEventListener('keydown', keyboardHandler); };
5103
5119
  }, [enabled, containerRef, matchingElementsSelector, onMatch]);
5104
5120
  return containerRef;
5105
5121
  }
5106
5122
 
5107
5123
  var ActionList = React.forwardRef(function (_a, ref) {
5108
5124
  var _b = _a.selectionType, selectionType = _b === void 0 ? null : _b, onAction = _a.onAction, className = _a.className, children = _a.children, props = tslib.__rest(_a, ["selectionType", "onAction", "className", "children"]);
5109
- var actionListContext = useActionListContext();
5110
- var activeElement = React.useRef();
5125
+ var activeElement = React.useRef(null);
5111
5126
  var _c = tslib.__read(React.useState(), 2), activeOption = _c[0], setActiveOption = _c[1];
5112
5127
  var handleActiveChange = React.useCallback(function (value) {
5113
5128
  activeElement.current = value === null || value === void 0 ? void 0 : value.element;
@@ -5128,12 +5143,7 @@ var ActionList = React.forwardRef(function (_a, ref) {
5128
5143
  ? '[role=menuitem],[role=menuitemcheckbox],[role=menuitemradio]'
5129
5144
  : '[role=option]'
5130
5145
  });
5131
- return (
5132
- // Note: we should be able to use listbox without passing a prop
5133
- // value for "multiselect"
5134
- // see: https://github.com/dequelabs/cauldron/issues/1890
5135
- // @ts-expect-error this should be allowed
5136
- React__default["default"].createElement(Listbox, tslib.__assign({ ref: function (element) {
5146
+ return (React__default["default"].createElement(Listbox, tslib.__assign({ ref: function (element) {
5137
5147
  if (ref) {
5138
5148
  setRef(ref, element);
5139
5149
  }
@@ -5142,7 +5152,7 @@ var ActionList = React.forwardRef(function (_a, ref) {
5142
5152
  /* Listbox comes with an explicit role of "listbox", but we want to either
5143
5153
  * use the role from props, or default to the intrinsic role */
5144
5154
  // eslint-disable-next-line jsx-a11y/aria-role
5145
- role: undefined, "aria-multiselectable": actionListContext.role === 'listbox' ? undefined : null, className: classNames__default["default"]('ActionList', className), activeOption: activeOption }, props, { onActiveChange: handleActiveChange, navigation: "bound" }),
5155
+ role: undefined, "aria-multiselectable": undefined, className: classNames__default["default"]('ActionList', className), activeOption: activeOption }, props, { onActiveChange: handleActiveChange, navigation: "bound" }),
5146
5156
  React__default["default"].createElement(ActionListProvider, { role: props.role || 'list', onAction: handleAction, selectionType: selectionType }, children)));
5147
5157
  });
5148
5158
  ActionList.displayName = 'ActionList';
@@ -5197,7 +5207,7 @@ var ActionListItem = React.forwardRef(function (_a, ref) {
5197
5207
  // istanbul ignore next
5198
5208
  React.useLayoutEffect(function () {
5199
5209
  var intersectionEntry = intersectionRef.current;
5200
- if (!intersectionEntry || !isActive) {
5210
+ if (!intersectionEntry || !isActive || !actionListItemRef.current) {
5201
5211
  return;
5202
5212
  }
5203
5213
  var rect = actionListItemRef.current.getBoundingClientRect();
@@ -1,4 +1,4 @@
1
- import type { RefObject } from 'react';
1
+ import type { MutableRefObject } from 'react';
2
2
  import type { ElementOrRef } from '../types';
3
3
  type useMnemonicsOptions = {
4
4
  /**
@@ -19,7 +19,7 @@ type useMnemonicsOptions = {
19
19
  */
20
20
  enabled?: boolean;
21
21
  };
22
- type useMnemonicsResults<T extends HTMLElement> = RefObject<T>;
22
+ type useMnemonicsResults<T extends HTMLElement> = MutableRefObject<T | null>;
23
23
  /**
24
24
  * A hook that provides mnemonic navigation for keyboard users.
25
25
  *
@@ -1,7 +1,7 @@
1
1
  import { MutableRefObject, Ref } from 'react';
2
2
  /**
3
3
  * When a component needs to track an internal ref on a component that has a
4
- * forwarded ref, useSharedRef will return a MutableRefObject<T> that will
4
+ * forwarded ref, useSharedRef will return a MutableRefObject<T | null> that will
5
5
  * correctly invoke the parent ref as well providing an internal ref.
6
6
  *
7
7
  * @example
@@ -13,4 +13,4 @@ import { MutableRefObject, Ref } from 'react';
13
13
  * return (<div ref={internalRef}>...</div>)
14
14
  * })
15
15
  */
16
- export default function useSharedRef<T>(ref: Ref<T>): MutableRefObject<T>;
16
+ export default function useSharedRef<T>(ref: Ref<T>): MutableRefObject<T | null>;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@deque/cauldron-react",
3
- "version": "7.1.0-canary.1107761f",
3
+ "version": "7.1.0-canary.2ada12a9",
4
4
  "license": "MPL-2.0",
5
5
  "description": "Fully accessible react components library for Deque Cauldron",
6
6
  "homepage": "https://cauldron.dequelabs.com/",