@rescui/select 0.15.1-RUI-280-Update-select-component-separate-components-e772abaa1.56 → 0.15.1-RUI-280-Update-select-component-downshift-2f40ef205.67

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (70) hide show
  1. package/lib/_virtual/index.css.js +12 -12
  2. package/lib/constants.d.ts +0 -1
  3. package/lib/constants.js +1 -2
  4. package/lib/hooks/use-a11y.d.ts +29 -0
  5. package/lib/hooks/use-a11y.js +53 -0
  6. package/lib/hooks/use-backward-compatible-id.d.ts +4 -0
  7. package/lib/hooks/use-backward-compatible-id.js +14 -0
  8. package/lib/hooks/use-focus.d.ts +10 -0
  9. package/lib/hooks/use-focus.js +17 -0
  10. package/lib/hooks/use-hover.d.ts +10 -0
  11. package/lib/hooks/use-hover.js +17 -0
  12. package/lib/hooks/use-label-focus.d.ts +1 -3
  13. package/lib/hooks/use-label-focus.js +3 -9
  14. package/lib/hooks/use-multi-handlers.d.ts +11 -0
  15. package/lib/hooks/use-multi-handlers.js +48 -0
  16. package/lib/hooks/use-options.d.ts +13 -0
  17. package/lib/hooks/use-options.js +89 -0
  18. package/lib/index.css +423 -1195
  19. package/lib/multiselect.d.ts +3 -29
  20. package/lib/multiselect.js +250 -180
  21. package/lib/native-select.js +75 -48
  22. package/lib/parts/hidden-select.d.ts +13 -0
  23. package/lib/parts/hidden-select.js +45 -0
  24. package/lib/parts/icons.js +2 -8
  25. package/lib/parts/list-box.d.ts +7 -15
  26. package/lib/parts/list-box.js +50 -82
  27. package/lib/parts/multi-trigger.d.ts +5 -4
  28. package/lib/parts/multi-trigger.js +27 -15
  29. package/lib/public-api.p.css +368 -126
  30. package/lib/public-api.pcss +368 -126
  31. package/lib/select-basic.d.ts +2 -2
  32. package/lib/select-basic.js +160 -103
  33. package/lib/select-searchable.d.ts +2 -2
  34. package/lib/select-searchable.js +205 -127
  35. package/lib/select.d.ts +1 -1
  36. package/lib/select.js +38 -31
  37. package/lib/styles/common.p.module.css.js +28 -24
  38. package/lib/styles/form-trigger.p.module.css.js +12 -12
  39. package/lib/styles/list-box.p.module.css.js +11 -13
  40. package/lib/types.d.ts +26 -27
  41. package/lib/utils/get-real-items-cnt.d.ts +2 -2
  42. package/lib/utils/get-real-items-cnt.js +8 -10
  43. package/lib/utils/item-to-string.d.ts +2 -0
  44. package/lib/utils/item-to-string.js +7 -0
  45. package/lib/utils/merge-props.d.ts +29 -0
  46. package/lib/utils/merge-props.js +106 -0
  47. package/package.json +11 -23
  48. package/lib/hooks/use-css-context-transfer.d.ts +0 -14
  49. package/lib/hooks/use-css-context-transfer.js +0 -40
  50. package/lib/hooks/use-multi-option-serialization.d.ts +0 -10
  51. package/lib/hooks/use-multi-option-serialization.js +0 -82
  52. package/lib/hooks/use-observable-force-rerender.d.ts +0 -2
  53. package/lib/hooks/use-observable-force-rerender.js +0 -16
  54. package/lib/hooks/use-option-serialization.d.ts +0 -10
  55. package/lib/hooks/use-option-serialization.js +0 -59
  56. package/lib/parts/native-select-trigger.d.ts +0 -18
  57. package/lib/parts/native-select-trigger.js +0 -54
  58. package/lib/parts/popover.d.ts +0 -12
  59. package/lib/parts/popover.js +0 -64
  60. package/lib/parts/popup-content.d.ts +0 -19
  61. package/lib/parts/popup-content.js +0 -76
  62. package/lib/styles/native-select-trigger.p.module.css.js +0 -17
  63. package/lib/styles/native-select.p.module.css.js +0 -9
  64. package/lib/styles/popover.p.module.css.js +0 -10
  65. package/lib/utils/convert-options.d.ts +0 -3
  66. package/lib/utils/convert-options.js +0 -52
  67. package/lib/utils/convert-placement.d.ts +0 -3
  68. package/lib/utils/convert-placement.js +0 -22
  69. package/lib/utils/css-vars-utils.d.ts +0 -3
  70. package/lib/utils/css-vars-utils.js +0 -20
@@ -1,145 +1,202 @@
1
- import React, { useRef } from 'react';
1
+ import React from 'react';
2
2
  import cn from 'classnames';
3
- import { useSelectState } from '@react-stately/select';
4
- import { useSelect, HiddenSelect } from '@react-aria/select';
5
- import { useButton } from '@react-aria/button';
6
- import { useFocusRing } from '@react-aria/focus';
7
- import { mergeProps } from '@react-aria/utils';
8
- import { PopupContent } from './parts/popup-content.js';
3
+ import { Dropdown } from '@rescui/dropdown';
4
+ import { useSelect } from 'downshift';
5
+ import scrollIntoView from 'scroll-into-view-if-needed';
6
+ import { useLabelFocus } from './hooks/use-label-focus.js';
7
+ import { useOptions } from './hooks/use-options.js';
8
+ import { useA11y } from './hooks/use-a11y.js';
9
+ import { ListBox } from './parts/list-box.js';
9
10
  import { Icons } from './parts/icons.js';
11
+ import { HiddenSelect } from './parts/hidden-select.js';
10
12
  import { FormTriggerWrapper } from './parts/form-trigger-wrapper.js';
11
- import { useLabelFocus } from './hooks/use-label-focus.js';
12
13
  import { getEmptyMessage } from './utils/get-empty-message.js';
13
- import styles from './styles/common.p.module.css.js';
14
- const THEME_STYLES = {
15
- light: styles.themeLight,
16
- dark: styles.themeDark
17
- };
18
- const SIZE_STYLES = {
19
- s: styles.sizeS,
20
- m: styles.sizeM,
21
- l: styles.sizeL
22
- };
23
- const MODE_STYLES = {
24
- classic: styles.classic,
25
- rock: styles.rock
26
- }; // eslint-disable-next-line complexity
14
+ import { mergeProps } from './utils/merge-props.js';
15
+ import { itemToString } from './utils/item-to-string.js';
16
+ import { getOptionValue } from './utils/get-option-value.js';
17
+ import { getRealItemsCnt } from './utils/get-real-items-cnt.js';
18
+ import styles from './styles/common.p.module.css.js'; // eslint-disable-next-line complexity
27
19
 
28
20
  function SelectBasic(_ref) {
29
- var _state$selectedItems$;
30
-
31
21
  let {
32
- id,
22
+ options,
23
+ value: selectedItem,
24
+ onChange,
25
+ error,
26
+ label,
27
+ note,
33
28
  size,
34
29
  mode,
35
30
  theme,
36
- style,
37
- className,
38
- isClearable,
39
- isLoading,
40
31
  placement,
41
32
  boldLabel,
42
33
  reserveErrorLine,
43
- noOptionsMessage,
44
34
  maxVisibleItems,
45
- ...ariaProps
35
+ isClearable,
36
+ isLoading,
37
+ isDisabled,
38
+ name,
39
+ noOptionsMessage,
40
+ className,
41
+ id,
42
+ style,
43
+ placeholder,
44
+ ...rest
46
45
  } = _ref;
47
- // Create state based on the incoming props
48
- const state = useSelectState({ ...ariaProps,
49
- allowsEmptyCollection: true
50
- });
51
- const hasValue = state.selectedItems.length > 0; // Get props for child elements from useSelect
52
-
53
- const triggerRef = useRef(null);
46
+ const triggerRef = React.useRef(null);
47
+ const dropdownRef = React.useRef(null);
48
+ const menuRef = React.useRef(null);
54
49
  const {
55
- labelProps,
56
- triggerProps,
57
- valueProps,
58
- menuProps: listBoxProps,
59
- hiddenSelectProps,
60
- errorMessageProps,
61
- descriptionProps
62
- } = useSelect({ ...ariaProps,
63
- onKeyDown: e => {
64
- if (isClearable && hasValue) {
65
- if (e.key === 'Backspace' || e.key === 'Delete') {
66
- state.setValue(null);
67
- e.stopPropagation();
68
- }
69
- }
70
- }
71
- }, state, triggerRef);
50
+ flattenedOptions,
51
+ listBoxItems
52
+ } = useOptions(options);
53
+ const isListBoxEmpty = getRealItemsCnt(listBoxItems) === 0;
54
+ const hasValue = Boolean(selectedItem);
55
+ const selectedMap = selectedItem ? new Map([[getOptionValue(selectedItem), selectedItem]]) : new Map();
72
56
  const {
73
- buttonProps
74
- } = useButton({ ...triggerProps,
75
- elementType: 'div'
76
- }, triggerRef);
77
- const isDisabled = ariaProps.isDisabled;
78
- const isOpen = state.isOpen;
57
+ fieldProps,
58
+ errorMessageProps,
59
+ descriptionProps,
60
+ baseId
61
+ } = useA11y({
62
+ prefix: 'select',
63
+ error,
64
+ description: note
65
+ });
79
66
  const {
80
- isFocusVisible,
81
- focusProps
82
- } = useFocusRing({
83
- within: true
67
+ isOpen,
68
+ getToggleButtonProps,
69
+ getLabelProps,
70
+ getMenuProps,
71
+ highlightedIndex,
72
+ getItemProps,
73
+ reset
74
+ } = useSelect({
75
+ items: flattenedOptions,
76
+ itemToString,
77
+ id: baseId,
78
+ selectedItem,
79
+ // defining our scroll behavior because on the first menu render the hook
80
+ // doesn't know menuRef and use page as the scroll boundary
81
+ scrollIntoView: (listItemEl, listEl) => {
82
+ scrollIntoView(listItemEl, {
83
+ scrollMode: 'if-needed',
84
+ block: 'nearest',
85
+ boundary: listEl ?? menuRef.current
86
+ });
87
+ },
88
+ onSelectedItemChange: _ref2 => {
89
+ let {
90
+ selectedItem: newSelectedItem
91
+ } = _ref2;
92
+ onChange === null || onChange === void 0 || onChange(newSelectedItem);
93
+ },
94
+
95
+ isItemDisabled(item) {
96
+ return item && item.disabled;
97
+ }
98
+
99
+ });
100
+ const menuProps = getMenuProps({
101
+ ref: menuRef
102
+ }, {
103
+ suppressRefError: true
104
+ });
105
+ const triggerProps = getToggleButtonProps({
106
+ ref: triggerRef,
107
+ onKeyDown: event => {
108
+ // backspace and backspace removing the last selected item (when popup is closed)
109
+ if (isClearable && !isOpen && (event.key === 'Backspace' || event.key === 'Delete')) {
110
+ reset();
111
+ }
112
+ },
113
+ // fix screen-reader focus on an opened popup with an empty list
114
+ ...(isOpen && isListBoxEmpty ? {
115
+ 'aria-activedescendant': menuProps.id
116
+ } : {})
84
117
  });
85
118
  const {
86
119
  isFocusedByLabel,
87
120
  labelClickProps,
88
121
  triggerFocusProps: labelFocusForTriggerProps
89
- } = useLabelFocus(triggerRef);
122
+ } = useLabelFocus();
90
123
  const emptyListMessage = getEmptyMessage({
91
124
  isLoading,
92
125
  isNothingFound: false,
93
126
  noOptionsMessage
94
127
  });
95
- return /*#__PURE__*/React.createElement("div", {
96
- className: cn(className, styles.root, THEME_STYLES[theme], SIZE_STYLES[size], MODE_STYLES[mode], isDisabled ? styles.disabled : styles.enabled, Boolean(ariaProps.errorMessage) && styles.error),
97
- id: id,
98
- style: style,
99
- "data-test": "select"
100
- }, /*#__PURE__*/React.createElement(FormTriggerWrapper, {
128
+ const listBoxState = {
129
+ selectedMap,
130
+ selectionMode: 'single',
131
+ highlightedIndex,
132
+ getItemProps,
133
+ menuProps
134
+ };
135
+ return /*#__PURE__*/React.createElement(FormTriggerWrapper, {
101
136
  theme: theme,
102
137
  size: size,
103
138
  disabled: isDisabled,
104
- label: ariaProps.label,
105
- labelProps: mergeProps(labelClickProps, labelProps),
139
+ label: label,
140
+ labelProps: mergeProps(getLabelProps(), labelClickProps),
106
141
  boldLabel: boldLabel,
107
- error: ariaProps.errorMessage,
142
+ error: error,
108
143
  reserveErrorLine: reserveErrorLine,
109
144
  errorMessageProps: errorMessageProps,
110
- note: ariaProps.description,
145
+ note: note,
111
146
  descriptionProps: descriptionProps
112
- }, /*#__PURE__*/React.createElement(HiddenSelect, { ...hiddenSelectProps
113
- }), /*#__PURE__*/React.createElement("div", { ...mergeProps(buttonProps, focusProps, labelFocusForTriggerProps),
114
- ref: triggerRef,
115
- className: styles.trigger,
116
- "data-open": isOpen,
117
- "data-focus-visible": isFocusVisible,
118
- "data-label-focused": isFocusedByLabel,
119
- "data-test": "select__trigger"
120
- }, /*#__PURE__*/React.createElement("span", { ...valueProps,
121
- className: cn(styles.triggerText, !hasValue && styles.labelNotSelected),
122
- "data-test": "select__trigger_content"
123
- }, ((_state$selectedItems$ = state.selectedItems[0]) === null || _state$selectedItems$ === void 0 ? void 0 : _state$selectedItems$.rendered) ?? ariaProps.placeholder), /*#__PURE__*/React.createElement(Icons, {
124
- isLoading: isLoading,
125
- canHaveClearIcon: isClearable && !isDisabled && hasValue,
126
- onClear: () => {
127
- var _triggerRef$current;
128
-
129
- state.setValue(null);
130
- (_triggerRef$current = triggerRef.current) === null || _triggerRef$current === void 0 || _triggerRef$current.focus();
131
- },
132
- triggerId: triggerProps.id
133
- })), /*#__PURE__*/React.createElement(PopupContent, {
147
+ }, /*#__PURE__*/React.createElement(HiddenSelect, {
148
+ name: name,
149
+ value: selectedItem,
150
+ isMultiple: false,
151
+ options: flattenedOptions
152
+ }), /*#__PURE__*/React.createElement(Dropdown, {
153
+ mode: mode,
134
154
  theme: theme,
135
- state: state,
136
- triggerRef: triggerRef,
155
+ ref: dropdownRef,
137
156
  placement: placement,
157
+ maxWidth: "trigger",
158
+ minWidth: "trigger",
159
+ isOpen: isOpen,
160
+ cancelCloseAnimation: true,
161
+ disableFocusLock: true,
162
+ trigger: _ref3 => {
163
+ let {
164
+ ref: triggerRefForDropdown
165
+ } = _ref3;
166
+ return /*#__PURE__*/React.createElement("div", {
167
+ className: styles.triggerContainer,
168
+ "data-open": isOpen,
169
+ "data-label-focused": isFocusedByLabel
170
+ }, /*#__PURE__*/React.createElement("div", { ...rest,
171
+ ...mergeProps(fieldProps, // aria-invalid & aria-describedby, rest are overridden by triggerProps
172
+ triggerProps, labelFocusForTriggerProps, {
173
+ ref: triggerRefForDropdown
174
+ }),
175
+ className: styles.trigger,
176
+ "data-test": "select__trigger"
177
+ }, /*#__PURE__*/React.createElement("span", {
178
+ className: cn(styles.triggerText, !hasValue && styles.labelNotSelected),
179
+ "data-test": "select__trigger_content"
180
+ }, (selectedItem === null || selectedItem === void 0 ? void 0 : selectedItem.label) ?? placeholder), /*#__PURE__*/React.createElement(Icons, {
181
+ isLoading: isLoading,
182
+ canHaveClearIcon: isClearable && !isDisabled && hasValue,
183
+ onClear: () => {
184
+ var _triggerRef$current;
185
+
186
+ reset();
187
+ (_triggerRef$current = triggerRef.current) === null || _triggerRef$current === void 0 || _triggerRef$current.focus({
188
+ focusVisible: false
189
+ });
190
+ },
191
+ triggerId: triggerProps.id
192
+ })));
193
+ }
194
+ }, /*#__PURE__*/React.createElement(ListBox, {
195
+ state: listBoxState,
138
196
  size: size,
139
- mode: mode,
140
- listBoxProps: listBoxProps,
197
+ maxVisibleItems: maxVisibleItems,
141
198
  emptyListMessage: emptyListMessage,
142
- maxVisibleItems: maxVisibleItems
199
+ items: listBoxItems
143
200
  })));
144
201
  }
145
202
 
@@ -1,3 +1,3 @@
1
1
  /// <reference types="react" />
2
- import type { InnerSingleComponentProps } from './types';
3
- export declare function SelectSearchable<T extends object>({ id, size, mode, theme, className, style, isClearable, isLoading, placement, boldLabel, reserveErrorLine, noOptionsMessage, maxVisibleItems, ...ariaProps }: InnerSingleComponentProps<T>): JSX.Element;
2
+ import { InnerSingleComponentProps } from './types';
3
+ export declare function SelectSearchable({ options, value: selectedItem, onChange, error, label, note, size, mode, theme, placement, boldLabel, reserveErrorLine, maxVisibleItems, isClearable, isLoading, isDisabled, name, noOptionsMessage, className, id, style, placeholder, ...rest }: InnerSingleComponentProps): JSX.Element;
@@ -1,171 +1,249 @@
1
- import _includesInstanceProperty from "@babel/runtime-corejs3/core-js-stable/instance/includes";
2
1
  import React, { useRef } from 'react';
3
- import cn from 'classnames';
4
- import { useComboBoxState } from '@react-stately/combobox';
5
- import { HiddenSelect } from '@react-aria/select';
6
- import { useComboBox } from '@react-aria/combobox';
7
- import { useButton } from '@react-aria/button';
8
- import { useFocusRing } from '@react-aria/focus';
9
- import { mergeProps } from '@react-aria/utils';
10
- import { PopupContent } from './parts/popup-content.js';
2
+ import { Dropdown } from '@rescui/dropdown';
3
+ import { useCombobox } from 'downshift';
4
+ import scrollIntoView from 'scroll-into-view-if-needed';
5
+ import { useLabelFocus } from './hooks/use-label-focus.js';
6
+ import { useOptions } from './hooks/use-options.js';
7
+ import { useA11y } from './hooks/use-a11y.js';
8
+ import { ListBox } from './parts/list-box.js';
11
9
  import { Icons } from './parts/icons.js';
10
+ import { HiddenSelect } from './parts/hidden-select.js';
12
11
  import { FormTriggerWrapper } from './parts/form-trigger-wrapper.js';
13
- import { useLabelFocus } from './hooks/use-label-focus.js';
14
12
  import { getEmptyMessage } from './utils/get-empty-message.js';
15
- import styles from './styles/common.p.module.css.js';
16
- const THEME_STYLES = {
17
- light: styles.themeLight,
18
- dark: styles.themeDark
19
- };
20
- const SIZE_STYLES = {
21
- s: styles.sizeS,
22
- m: styles.sizeM,
23
- l: styles.sizeL
24
- };
25
- const MODE_STYLES = {
26
- classic: styles.classic,
27
- rock: styles.rock
28
- }; // Do not use useFilter from 'react-aria' package as it's much slower for most cases
29
-
30
- const contains = (string, substring) => {
31
- var _context;
32
-
33
- if (substring.length === 0) {
34
- return true;
35
- }
36
-
37
- return _includesInstanceProperty(_context = string.toLowerCase()).call(_context, substring.toLowerCase());
38
- }; // eslint-disable-next-line complexity
39
-
13
+ import { mergeProps } from './utils/merge-props.js';
14
+ import { itemToString } from './utils/item-to-string.js';
15
+ import { getOptionValue } from './utils/get-option-value.js';
16
+ import { getRealItemsCnt } from './utils/get-real-items-cnt.js';
17
+ import styles from './styles/common.p.module.css.js'; // eslint-disable-next-line complexity
40
18
 
41
19
  function SelectSearchable(_ref) {
42
- var _state$inputValue;
43
-
44
20
  let {
45
- id,
21
+ options,
22
+ value: selectedItem,
23
+ onChange,
24
+ error,
25
+ label,
26
+ note,
46
27
  size,
47
28
  mode,
48
29
  theme,
49
- className,
50
- style,
51
- isClearable,
52
- isLoading,
53
30
  placement,
54
31
  boldLabel,
55
32
  reserveErrorLine,
56
- noOptionsMessage,
57
33
  maxVisibleItems,
58
- ...ariaProps
34
+ isClearable,
35
+ isLoading,
36
+ isDisabled,
37
+ name,
38
+ noOptionsMessage,
39
+ className,
40
+ id,
41
+ style,
42
+ placeholder,
43
+ ...rest
59
44
  } = _ref;
60
- // Create state based on the incoming props
61
- const state = useComboBoxState({ ...ariaProps,
62
- defaultFilter: contains,
63
- allowsEmptyCollection: true
64
- });
65
- const hasValue = state.selectedItems.length > 0; // Setup refs and get props for child elements.
66
-
67
- const triggerRef = useRef(null);
68
45
  const inputRef = useRef(null);
69
- const listBoxRef = useRef(null);
70
- const popoverRef = useRef(null);
71
- const {
72
- labelProps,
73
- buttonProps: triggerProps,
74
- listBoxProps,
75
- inputProps: inputPropsWithName,
76
- errorMessageProps,
77
- descriptionProps
78
- } = useComboBox({ ...ariaProps,
79
- inputRef,
80
- buttonRef: triggerRef,
81
- listBoxRef,
82
- popoverRef
83
- }, state); // Extract name from inputProps to use with HiddenSelect instead
84
-
46
+ const dropdownRef = useRef(null);
47
+ const menuRef = useRef(null);
85
48
  const {
86
- name,
87
- ...inputProps
88
- } = inputPropsWithName;
49
+ flattenedOptions,
50
+ listBoxItems,
51
+ setFilterString
52
+ } = useOptions(options);
53
+ const isListBoxEmpty = getRealItemsCnt(listBoxItems) === 0;
54
+ const hasValue = Boolean(selectedItem);
55
+ const selectedMap = selectedItem ? new Map([[getOptionValue(selectedItem), selectedItem]]) : new Map();
89
56
  const {
90
- buttonProps
91
- } = useButton({ ...triggerProps,
92
- elementType: 'div'
93
- }, triggerRef);
94
- const isDisabled = ariaProps.isDisabled;
95
- const isOpen = state.isOpen;
57
+ fieldProps,
58
+ errorMessageProps,
59
+ descriptionProps,
60
+ baseId,
61
+ labelProps
62
+ } = useA11y({
63
+ prefix: 'select',
64
+ error,
65
+ description: note,
66
+ fieldRef: inputRef
67
+ });
96
68
  const {
97
- isFocusVisible,
98
- focusProps
99
- } = useFocusRing({
100
- within: true
69
+ isOpen,
70
+ getToggleButtonProps,
71
+ getLabelProps,
72
+ getMenuProps,
73
+ getInputProps,
74
+ highlightedIndex,
75
+ getItemProps,
76
+ reset,
77
+ setInputValue
78
+ } = useCombobox({
79
+ onInputValueChange(_ref2) {
80
+ let {
81
+ inputValue,
82
+ type
83
+ } = _ref2;
84
+
85
+ if (type === useCombobox.stateChangeTypes.InputChange) {
86
+ setFilterString(inputValue);
87
+ }
88
+ },
89
+
90
+ items: flattenedOptions,
91
+ id: baseId,
92
+ itemToString,
93
+ selectedItem,
94
+ // defining our scroll behavior because on the first menu render the hook
95
+ // doesn't know menuRef and use page as the scroll boundary
96
+ scrollIntoView: (listItemEl, listEl) => {
97
+ scrollIntoView(listItemEl, {
98
+ scrollMode: 'if-needed',
99
+ block: 'nearest',
100
+ boundary: listEl ?? menuRef.current
101
+ });
102
+ },
103
+ onSelectedItemChange: _ref3 => {
104
+ let {
105
+ selectedItem: newSelectedItem
106
+ } = _ref3;
107
+ onChange === null || onChange === void 0 || onChange(newSelectedItem);
108
+ },
109
+
110
+ isItemDisabled(item) {
111
+ return item && item.disabled;
112
+ },
113
+
114
+ onIsOpenChange(_ref4) {
115
+ let {
116
+ isOpen: newIsOpen,
117
+ selectedItem: newSelectedItem
118
+ } = _ref4;
119
+
120
+ if (newIsOpen) {
121
+ setFilterString('');
122
+ } else {
123
+ setInputValue(itemToString(newSelectedItem));
124
+ }
125
+ },
126
+
127
+ stateReducer(state, actionAndChanges) {
128
+ const {
129
+ changes,
130
+ type
131
+ } = actionAndChanges;
132
+
133
+ switch (type) {
134
+ case useCombobox.stateChangeTypes.InputKeyDownEscape:
135
+ if (!state.isOpen) {
136
+ return state;
137
+ }
138
+
139
+ return changes;
140
+
141
+ default:
142
+ return changes;
143
+ }
144
+ }
145
+
146
+ });
147
+ const menuProps = getMenuProps({
148
+ ref: menuRef
149
+ }, {
150
+ suppressRefError: true
151
+ });
152
+ const inputProps = getInputProps({
153
+ ref: inputRef,
154
+ // fix screen-reader focus on an opened popup with an empty list
155
+ ...(isOpen && isListBoxEmpty ? {
156
+ 'aria-activedescendant': menuProps.id
157
+ } : {})
101
158
  });
102
159
  const {
103
160
  isFocusedByLabel,
104
161
  labelClickProps,
105
162
  triggerFocusProps: labelFocusForTriggerProps
106
- } = useLabelFocus(triggerRef);
163
+ } = useLabelFocus();
107
164
  const emptyListMessage = getEmptyMessage({
108
165
  isLoading,
109
- isNothingFound: ((_state$inputValue = state.inputValue) === null || _state$inputValue === void 0 ? void 0 : _state$inputValue.length) > 0,
166
+ isNothingFound: false,
110
167
  noOptionsMessage
111
168
  });
112
- return /*#__PURE__*/React.createElement("div", {
113
- className: cn(className, styles.root, THEME_STYLES[theme], SIZE_STYLES[size], MODE_STYLES[mode], isDisabled ? styles.disabled : styles.enabled, Boolean(ariaProps.errorMessage) && styles.error),
114
- id: id,
115
- style: style,
116
- "data-test": "select"
117
- }, /*#__PURE__*/React.createElement(FormTriggerWrapper, {
169
+ const listBoxState = {
170
+ selectedMap,
171
+ selectionMode: 'single',
172
+ highlightedIndex,
173
+ getItemProps,
174
+ menuProps
175
+ };
176
+ return /*#__PURE__*/React.createElement(FormTriggerWrapper, {
118
177
  theme: theme,
119
178
  size: size,
120
179
  disabled: isDisabled,
121
- label: ariaProps.label,
122
- labelProps: mergeProps(labelClickProps, labelProps),
180
+ label: label,
181
+ labelProps: mergeProps(labelProps, getLabelProps(), labelClickProps),
123
182
  boldLabel: boldLabel,
124
- error: ariaProps.errorMessage,
183
+ error: error,
125
184
  reserveErrorLine: reserveErrorLine,
126
185
  errorMessageProps: errorMessageProps,
127
- note: ariaProps.description,
186
+ note: note,
128
187
  descriptionProps: descriptionProps
129
188
  }, /*#__PURE__*/React.createElement(HiddenSelect, {
130
- state: state,
131
- triggerRef: triggerRef,
132
- label: ariaProps.label,
133
189
  name: name,
134
- isDisabled: isDisabled
135
- }), /*#__PURE__*/React.createElement("div", { ...mergeProps(buttonProps, focusProps, labelFocusForTriggerProps),
136
- ref: triggerRef,
137
- className: styles.trigger,
138
- "data-open": isOpen,
139
- "data-focus-visible": isFocusVisible,
140
- "data-label-focused": isFocusedByLabel,
141
- "data-test": "select__trigger"
142
- }, /*#__PURE__*/React.createElement("input", { ...inputProps,
143
- ref: inputRef,
144
- className: styles.searchInput,
145
- value: inputProps.value,
146
- "data-test": "select__trigger_input"
147
- }), /*#__PURE__*/React.createElement(Icons, {
148
- isLoading: isLoading,
149
- canHaveClearIcon: isClearable && !isDisabled && hasValue,
150
- onClear: () => {
151
- var _inputRef$current;
152
-
153
- state.setValue(null);
154
- (_inputRef$current = inputRef.current) === null || _inputRef$current === void 0 || _inputRef$current.focus();
155
- },
156
- triggerId: triggerProps.id
157
- })), /*#__PURE__*/React.createElement(PopupContent, {
190
+ value: selectedItem,
191
+ isMultiple: false,
192
+ options: flattenedOptions
193
+ }), /*#__PURE__*/React.createElement(Dropdown, {
194
+ mode: mode,
158
195
  theme: theme,
159
- state: state,
160
- triggerRef: triggerRef,
161
- popoverRef: popoverRef,
162
- listBoxRef: listBoxRef,
196
+ ref: dropdownRef,
163
197
  placement: placement,
198
+ maxWidth: "trigger",
199
+ minWidth: "trigger",
200
+ isOpen: isOpen,
201
+ cancelCloseAnimation: true,
202
+ disableFocusLock: true,
203
+ trigger: _ref5 => {
204
+ let {
205
+ ref: triggerRefForDropdown
206
+ } = _ref5;
207
+ return /*#__PURE__*/React.createElement("div", {
208
+ className: styles.triggerContainer,
209
+ "data-open": isOpen,
210
+ "data-label-focused": isFocusedByLabel
211
+ }, /*#__PURE__*/React.createElement("input", { ...rest,
212
+ ...mergeProps(fieldProps, // aria-invalid & aria-describedby, rest are overridden by inputProps,
213
+ inputProps, labelFocusForTriggerProps),
214
+ className: styles.searchInput,
215
+ placeholder: placeholder,
216
+ "data-test": "select__trigger_input"
217
+ }), /*#__PURE__*/React.createElement("div", {
218
+ role: "button",
219
+ ...mergeProps(getToggleButtonProps(), {
220
+ ref: triggerRefForDropdown,
221
+ onFocus: () => {
222
+ var _inputRef$current;
223
+
224
+ (_inputRef$current = inputRef.current) === null || _inputRef$current === void 0 || _inputRef$current.focus();
225
+ }
226
+ }),
227
+ className: styles.trigger,
228
+ "data-test": "select__trigger"
229
+ }, /*#__PURE__*/React.createElement(Icons, {
230
+ isLoading: isLoading,
231
+ canHaveClearIcon: isClearable && !isDisabled && hasValue,
232
+ onClear: () => {
233
+ var _inputRef$current2;
234
+
235
+ reset();
236
+ (_inputRef$current2 = inputRef.current) === null || _inputRef$current2 === void 0 || _inputRef$current2.focus();
237
+ },
238
+ triggerId: inputProps.id
239
+ })));
240
+ }
241
+ }, /*#__PURE__*/React.createElement(ListBox, {
242
+ state: listBoxState,
164
243
  size: size,
165
- mode: mode,
166
- listBoxProps: listBoxProps,
244
+ maxVisibleItems: maxVisibleItems,
167
245
  emptyListMessage: emptyListMessage,
168
- maxVisibleItems: maxVisibleItems
246
+ items: listBoxItems
169
247
  })));
170
248
  }
171
249