@deque/cauldron-react 6.12.0-canary.98683670 → 6.12.0-canary.afa8fb4f

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.
@@ -2,15 +2,29 @@ import React from 'react';
2
2
  import type { ListboxOption } from './ListboxContext';
3
3
  import type { ListboxValue } from './ListboxOption';
4
4
  import type { PolymorphicProps, PolymorphicComponent } from '../../utils/polymorphicComponent';
5
- interface ListboxProps extends PolymorphicProps<Omit<React.HTMLAttributes<HTMLElement>, 'onSelect'>> {
6
- value?: ListboxValue;
5
+ interface BaseListboxProps extends PolymorphicProps<Omit<React.HTMLAttributes<HTMLElement>, 'onSelect' | 'defaultValue'>> {
7
6
  navigation?: 'cycle' | 'bound';
8
- onSelectionChange?: <T extends HTMLElement = HTMLElement>({ value }: {
7
+ onActiveChange?: (option: ListboxOption) => void;
8
+ }
9
+ interface SingleSelectListboxProps extends BaseListboxProps {
10
+ multiselect?: false;
11
+ value?: ListboxValue;
12
+ defaultValue?: ListboxValue;
13
+ onSelectionChange?: <T extends HTMLElement = HTMLElement>(props: {
9
14
  target: T;
10
15
  previousValue: ListboxValue;
11
16
  value: ListboxValue;
12
17
  }) => void;
13
- onActiveChange?: (option: ListboxOption) => void;
14
18
  }
15
- declare const Listbox: PolymorphicComponent<ListboxProps>;
19
+ interface MultiSelectListboxProps extends BaseListboxProps {
20
+ multiselect: true;
21
+ value?: ListboxValue[];
22
+ defaultValue?: ListboxValue[];
23
+ onSelectionChange?: <T extends HTMLElement = HTMLElement>(props: {
24
+ target: T;
25
+ previousValue: ListboxValue[];
26
+ value: ListboxValue[];
27
+ }) => void;
28
+ }
29
+ declare const Listbox: PolymorphicComponent<SingleSelectListboxProps | MultiSelectListboxProps>;
16
30
  export default Listbox;
@@ -8,7 +8,8 @@ type ListboxOption<Element = HTMLElement, Value = string | number> = {
8
8
  type ListboxContext<T extends ListboxOption> = {
9
9
  options: T[];
10
10
  active: T | null;
11
- selected: T | null;
11
+ selected: T[] | null;
12
+ multiselect: boolean;
12
13
  setOptions: React.Dispatch<React.SetStateAction<T[]>>;
13
14
  onSelect: (option: T) => void;
14
15
  };
@@ -19,9 +20,10 @@ declare const ListboxContext: React.Context<{
19
20
  options: never[];
20
21
  active: null;
21
22
  selected: null;
23
+ multiselect: boolean;
22
24
  setOptions: () => null;
23
25
  onSelect: () => null;
24
26
  }>;
25
- declare function ListboxProvider<T extends ListboxOption>({ options, active, selected, setOptions, onSelect, children }: ListboxProvider<T>): React.JSX.Element;
27
+ declare function ListboxProvider<T extends ListboxOption>({ options, active, selected, multiselect, setOptions, onSelect, children }: ListboxProvider<T>): React.JSX.Element;
26
28
  declare function useListboxContext<T extends ListboxOption>(): ListboxContext<T>;
27
29
  export { ListboxProvider, useListboxContext, ListboxOption };
@@ -4,6 +4,7 @@ export type ListboxValue = Readonly<string | number | undefined>;
4
4
  interface ListboxOptionProps extends PolymorphicProps<React.HTMLAttributes<HTMLElement>> {
5
5
  value?: ListboxValue;
6
6
  disabled?: boolean;
7
+ selected?: boolean;
7
8
  activeClass?: string;
8
9
  }
9
10
  declare const ListboxOption: PolymorphicComponent<ListboxOptionProps>;
package/lib/index.js CHANGED
@@ -1282,7 +1282,7 @@ var SideBar = /** @class */ (function (_super) {
1282
1282
  }(React.Component));
1283
1283
 
1284
1284
  var SideBarItem = function (_a) {
1285
- var children = _a.children, autoClickLink = _a.autoClickLink, other = tslib.__rest(_a, ["children", "autoClickLink"]);
1285
+ var children = _a.children, _b = _a.autoClickLink, autoClickLink = _b === void 0 ? true : _b, other = tslib.__rest(_a, ["children", "autoClickLink"]);
1286
1286
  var onClick = function (e) {
1287
1287
  if (!autoClickLink) {
1288
1288
  return;
@@ -1294,9 +1294,6 @@ var SideBarItem = function (_a) {
1294
1294
  /* eslint-enable jsx-a11y/no-noninteractive-element-interactions, jsx-a11y/click-events-have-key-events */
1295
1295
  };
1296
1296
  SideBarItem.displayName = 'SideBarItem';
1297
- SideBarItem.defaultProps = {
1298
- autoClickLink: true
1299
- };
1300
1297
 
1301
1298
  /**
1302
1299
  * Handles aria-hidden for dialogs.
@@ -3447,19 +3444,21 @@ var ListboxContext = React.createContext({
3447
3444
  options: [],
3448
3445
  active: null,
3449
3446
  selected: null,
3447
+ multiselect: false,
3450
3448
  setOptions: function () { return null; },
3451
3449
  onSelect: function () { return null; }
3452
3450
  });
3453
3451
  function ListboxProvider(_a) {
3454
- var options = _a.options, active = _a.active, selected = _a.selected, setOptions = _a.setOptions, onSelect = _a.onSelect, children = _a.children;
3452
+ var options = _a.options, active = _a.active, selected = _a.selected, multiselect = _a.multiselect, setOptions = _a.setOptions, onSelect = _a.onSelect, children = _a.children;
3455
3453
  var Provider = ListboxContext.Provider;
3456
3454
  var value = React.useMemo(function () { return ({
3457
3455
  options: options,
3458
3456
  active: active,
3459
3457
  selected: selected,
3458
+ multiselect: multiselect,
3460
3459
  setOptions: setOptions,
3461
3460
  onSelect: onSelect
3462
- }); }, [options, active, selected, setOptions]);
3461
+ }); }, [options, active, selected, multiselect, setOptions]);
3463
3462
  return React__default["default"].createElement(Provider, { value: value }, children);
3464
3463
  }
3465
3464
  function useListboxContext() {
@@ -3481,40 +3480,78 @@ var optionMatchesValue = function (option, value) {
3481
3480
  option.value === value;
3482
3481
  };
3483
3482
  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];
3483
+ 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"]);
3484
+ var _e = tslib.__read(React.useState([]), 2), options = _e[0], setOptions = _e[1];
3485
+ var _f = tslib.__read(React.useState(null), 2), activeOption = _f[0], setActiveOption = _f[1];
3486
+ var _g = tslib.__read(React.useState([]), 2), selectedOptions = _g[0], setSelectedOptions = _g[1];
3488
3487
  var listboxRef = useSharedRef(ref);
3489
3488
  var isControlled = typeof value !== 'undefined';
3490
3489
  React.useLayoutEffect(function () {
3491
- if (!isControlled && selectedOption) {
3490
+ if (!isControlled && selectedOptions.length > 0) {
3492
3491
  return;
3493
3492
  }
3494
3493
  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]);
3494
+ if (!listboxValue) {
3495
+ return;
3496
+ }
3497
+ if (multiselect) {
3498
+ var matchingOptions = options.filter(function (option) {
3499
+ return listboxValue.find(function (value) {
3500
+ return optionMatchesValue(option, value);
3501
+ });
3502
+ });
3503
+ setSelectedOptions(matchingOptions);
3504
+ setActiveOption(matchingOptions[0] || null);
3505
+ }
3506
+ else {
3507
+ var matchingOption = options.find(function (option) {
3508
+ return optionMatchesValue(option, listboxValue);
3509
+ });
3510
+ setSelectedOptions(matchingOption ? [matchingOption] : []);
3511
+ setActiveOption(matchingOption || null);
3512
+ }
3513
+ }, [isControlled, options, value, defaultValue]);
3501
3514
  React.useEffect(function () {
3502
3515
  if (activeOption) {
3503
3516
  onActiveChange === null || onActiveChange === void 0 ? void 0 : onActiveChange(activeOption);
3504
3517
  }
3505
3518
  }, [activeOption]);
3506
3519
  var handleSelect = React.useCallback(function (option) {
3520
+ var _a;
3507
3521
  setActiveOption(option);
3522
+ var optionIsSelected = selectedOptions.some(function (selected) { return selected.element === option.element; });
3523
+ var previousValues = selectedOptions.map(function (selected) { return selected.value; });
3508
3524
  // istanbul ignore else
3509
3525
  if (!isControlled) {
3510
- setSelectedOption(option);
3526
+ if (!multiselect) {
3527
+ setSelectedOptions([option]);
3528
+ }
3529
+ else {
3530
+ setSelectedOptions(optionIsSelected
3531
+ ? tslib.__spreadArray([], tslib.__read(selectedOptions.filter(function (selected) { return selected.element !== option.element; })), false) : tslib.__spreadArray(tslib.__spreadArray([], tslib.__read(selectedOptions), false), [option], false));
3532
+ }
3511
3533
  }
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]);
3534
+ if (multiselect) {
3535
+ onSelectionChange === null || onSelectionChange === void 0 ? void 0 : onSelectionChange({
3536
+ target: option.element,
3537
+ value: optionIsSelected
3538
+ ? selectedOptions
3539
+ .filter(function (selectedOption) {
3540
+ return selectedOption.element !== option.element;
3541
+ })
3542
+ .map(function (selectedOption) { return selectedOption.value; })
3543
+ : tslib.__spreadArray(tslib.__spreadArray([], tslib.__read(previousValues), false), [option.value], false),
3544
+ previousValue: previousValues
3545
+ });
3546
+ }
3547
+ else {
3548
+ onSelectionChange === null || onSelectionChange === void 0 ? void 0 : onSelectionChange({
3549
+ target: option.element,
3550
+ value: option.value,
3551
+ previousValue: (_a = selectedOptions[0]) === null || _a === void 0 ? void 0 : _a.value
3552
+ });
3553
+ }
3554
+ }, [isControlled, selectedOptions, multiselect, onSelectionChange]);
3518
3555
  var handleKeyDown = React.useCallback(function (event) {
3519
3556
  onKeyDown === null || onKeyDown === void 0 ? void 0 : onKeyDown(event);
3520
3557
  if (!keys.includes(event.key)) {
@@ -3564,9 +3601,9 @@ var Listbox = React.forwardRef(function (_a, ref) {
3564
3601
  activeOption && handleSelect(activeOption);
3565
3602
  break;
3566
3603
  }
3567
- }, [options, activeOption, navigation]);
3604
+ }, [options, activeOption, navigation, handleSelect]);
3568
3605
  var handleFocus = React.useCallback(function (event) {
3569
- if (!activeOption && !selectedOption) {
3606
+ if (!activeOption) {
3570
3607
  var firstOption = options.find(function (option) { return !isDisabledOption(option); });
3571
3608
  // istanbul ignore else
3572
3609
  if (firstOption) {
@@ -3574,13 +3611,14 @@ var Listbox = React.forwardRef(function (_a, ref) {
3574
3611
  }
3575
3612
  // istanbul ignore else
3576
3613
  }
3577
- else if (event.target === listboxRef.current) {
3578
- setActiveOption(selectedOption);
3614
+ else if (selectedOptions.length &&
3615
+ event.target === listboxRef.current) {
3616
+ setActiveOption(selectedOptions[selectedOptions.length - 1]);
3579
3617
  }
3580
3618
  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)));
3619
+ }, [options, activeOption, selectedOptions]);
3620
+ 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),
3621
+ React__default["default"].createElement(ListboxProvider, { options: options, active: activeOption, multiselect: multiselect, selected: selectedOptions, setOptions: setOptions, onSelect: handleSelect }, children)));
3584
3622
  });
3585
3623
  Listbox.displayName = 'Listbox';
3586
3624
 
@@ -3590,12 +3628,15 @@ function isElementPreceding(a, b) {
3590
3628
  var ListboxOption = React.forwardRef(function (_a, ref) {
3591
3629
  var _b;
3592
3630
  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"]);
3631
+ 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
3632
  var _f = useListboxContext(), active = _f.active, selected = _f.selected, setOptions = _f.setOptions, onSelect = _f.onSelect;
3595
3633
  var listboxOptionRef = useSharedRef(ref);
3596
3634
  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;
3635
+ var isActive = (active === null || active === void 0 ? void 0 : active.element) === listboxOptionRef.current;
3636
+ var isSelected = typeof selectedProp === 'boolean'
3637
+ ? selectedProp
3638
+ : selected !== null &&
3639
+ !!selected.find(function (option) { return option.element === listboxOptionRef.current; });
3599
3640
  var optionValue = typeof value !== 'undefined'
3600
3641
  ? value
3601
3642
  : (_c = listboxOptionRef.current) === null || _c === void 0 ? void 0 : _c.innerText;
@@ -3645,7 +3686,7 @@ var ListboxOption = React.forwardRef(function (_a, ref) {
3645
3686
  }
3646
3687
  onSelect({ element: listboxOptionRef.current, value: optionValue });
3647
3688
  onClick === null || onClick === void 0 ? void 0 : onClick(event);
3648
- }, [optionValue]);
3689
+ }, [optionValue, onSelect, onClick, disabled]);
3649
3690
  return (React__default["default"].createElement(Component, tslib.__assign({ id: id, className: classNames__default["default"](className, (_b = {},
3650
3691
  _b[activeClass] = isActive,
3651
3692
  _b)), role: "option", ref: listboxOptionRef, "aria-disabled": typeof disabled === 'boolean' ? disabled : undefined, "aria-selected": isSelected, onClick: handleClick }, props), children));
@@ -3767,17 +3808,20 @@ var ComboboxMatch = function (_a) {
3767
3808
  React__default["default"].createElement("span", null, matchAfter)));
3768
3809
  };
3769
3810
  var ComboboxOption = React.forwardRef(function (_a, ref) {
3811
+ var _b;
3770
3812
  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;
3813
+ var _c = tslib.__read(propId ? [propId] : nextId.useId(1, 'combobox-option'), 1), id = _c[0];
3814
+ var _d = useListboxContext(), selected = _d.selected, active = _d.active;
3815
+ var _e = useComboboxContext(), selectedValue = _e.selectedValue, matches = _e.matches, setMatchingOptions = _e.setMatchingOptions, setFormValue = _e.setFormValue;
3774
3816
  var comboboxOptionRef = useSharedRef(ref);
3775
3817
  var intersectionRef = useIntersectionRef(comboboxOptionRef, {
3776
3818
  root: null,
3777
3819
  threshold: 1.0
3778
3820
  });
3779
3821
  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;
3822
+ var isSelected = !!(selected &&
3823
+ !!((_b = selected[0]) === null || _b === void 0 ? void 0 : _b.element) &&
3824
+ selected[0].element === comboboxOptionRef.current);
3781
3825
  var isMatching = (typeof matches === 'boolean' && matches) ||
3782
3826
  (typeof matches === 'function' && matches(children));
3783
3827
  // istanbul ignore next
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@deque/cauldron-react",
3
- "version": "6.12.0-canary.98683670",
3
+ "version": "6.12.0-canary.afa8fb4f",
4
4
  "license": "MPL-2.0",
5
5
  "description": "Fully accessible react components library for Deque Cauldron",
6
6
  "homepage": "https://cauldron.dequelabs.com/",