1 | import _extends from "@babel/runtime/helpers/esm/extends";
|
2 | import * as React from 'react';
|
3 | import { unstable_useForkRef as useForkRef, unstable_useId as useId, unstable_useEnhancedEffect as useEnhancedEffect } from '@mui/utils';
|
4 | import useButton from '../useButton';
|
5 | import { SelectActionTypes } from './useSelect.types';
|
6 | import useList from '../useList';
|
7 | import defaultOptionStringifier from './defaultOptionStringifier';
|
8 | import { useCompoundParent } from '../utils/useCompound';
|
9 | import selectReducer from './selectReducer';
|
10 | import combineHooksSlotProps from '../utils/combineHooksSlotProps';
|
11 | function preventDefault(event) {
|
12 | event.preventDefault();
|
13 | }
|
14 |
|
15 |
|
16 |
|
17 |
|
18 |
|
19 |
|
20 |
|
21 |
|
22 |
|
23 |
|
24 |
|
25 | function useSelect(props) {
|
26 | var buttonRefProp = props.buttonRef,
|
27 | _props$defaultOpen = props.defaultOpen,
|
28 | defaultOpen = _props$defaultOpen === void 0 ? false : _props$defaultOpen,
|
29 | defaultValueProp = props.defaultValue,
|
30 | _props$disabled = props.disabled,
|
31 | disabled = _props$disabled === void 0 ? false : _props$disabled,
|
32 | listboxIdProp = props.listboxId,
|
33 | listboxRefProp = props.listboxRef,
|
34 | _props$multiple = props.multiple,
|
35 | multiple = _props$multiple === void 0 ? false : _props$multiple,
|
36 | onChange = props.onChange,
|
37 | onHighlightChange = props.onHighlightChange,
|
38 | onOpenChange = props.onOpenChange,
|
39 | openProp = props.open,
|
40 | optionsParam = props.options,
|
41 | _props$getOptionAsStr = props.getOptionAsString,
|
42 | getOptionAsString = _props$getOptionAsStr === void 0 ? defaultOptionStringifier : _props$getOptionAsStr,
|
43 | valueProp = props.value;
|
44 | var buttonRef = React.useRef(null);
|
45 | var handleButtonRef = useForkRef(buttonRefProp, buttonRef);
|
46 | var listboxRef = React.useRef(null);
|
47 | var listboxId = useId(listboxIdProp);
|
48 | var defaultValue;
|
49 | if (valueProp === undefined && defaultValueProp === undefined) {
|
50 | defaultValue = [];
|
51 | } else if (defaultValueProp !== undefined) {
|
52 | if (multiple) {
|
53 | defaultValue = defaultValueProp;
|
54 | } else {
|
55 | defaultValue = defaultValueProp == null ? [] : [defaultValueProp];
|
56 | }
|
57 | }
|
58 | var value = React.useMemo(function () {
|
59 | if (valueProp !== undefined) {
|
60 | if (multiple) {
|
61 | return valueProp;
|
62 | }
|
63 | return valueProp == null ? [] : [valueProp];
|
64 | }
|
65 | return undefined;
|
66 | }, [valueProp, multiple]);
|
67 | var _useCompoundParent = useCompoundParent(),
|
68 | subitems = _useCompoundParent.subitems,
|
69 | compoundComponentContextValue = _useCompoundParent.contextValue;
|
70 | var options = React.useMemo(function () {
|
71 | if (optionsParam != null) {
|
72 | return new Map(optionsParam.map(function (option, index) {
|
73 | return [option.value, {
|
74 | value: option.value,
|
75 | label: option.label,
|
76 | disabled: option.disabled,
|
77 | ref: React.createRef(),
|
78 | id: "".concat(listboxId, "_").concat(index)
|
79 | }];
|
80 | }));
|
81 | }
|
82 | return subitems;
|
83 | }, [optionsParam, subitems, listboxId]);
|
84 | var handleListboxRef = useForkRef(listboxRefProp, listboxRef);
|
85 | var _useButton = useButton({
|
86 | disabled: disabled,
|
87 | rootRef: handleButtonRef
|
88 | }),
|
89 | getButtonRootProps = _useButton.getRootProps,
|
90 | buttonActive = _useButton.active,
|
91 | buttonFocusVisible = _useButton.focusVisible,
|
92 | mergedButtonRef = _useButton.rootRef;
|
93 | var optionValues = React.useMemo(function () {
|
94 | return Array.from(options.keys());
|
95 | }, [options]);
|
96 | var isItemDisabled = React.useCallback(function (valueToCheck) {
|
97 | var _option$disabled;
|
98 | var option = options.get(valueToCheck);
|
99 | return (_option$disabled = option == null ? void 0 : option.disabled) != null ? _option$disabled : false;
|
100 | }, [options]);
|
101 | var stringifyOption = React.useCallback(function (valueToCheck) {
|
102 | var option = options.get(valueToCheck);
|
103 | if (!option) {
|
104 | return '';
|
105 | }
|
106 | return getOptionAsString(option);
|
107 | }, [options, getOptionAsString]);
|
108 | var controlledState = React.useMemo(function () {
|
109 | return {
|
110 | selectedValues: value,
|
111 | open: openProp
|
112 | };
|
113 | }, [value, openProp]);
|
114 | var getItemId = React.useCallback(function (itemValue) {
|
115 | var _options$get;
|
116 | return (_options$get = options.get(itemValue)) == null ? void 0 : _options$get.id;
|
117 | }, [options]);
|
118 | var handleSelectionChange = React.useCallback(function (event, newValues) {
|
119 | if (multiple) {
|
120 | onChange == null ? void 0 : onChange(event, newValues);
|
121 | } else {
|
122 | var _newValues$;
|
123 | onChange == null ? void 0 : onChange(event, (_newValues$ = newValues[0]) != null ? _newValues$ : null);
|
124 | }
|
125 | }, [multiple, onChange]);
|
126 | var handleHighlightChange = React.useCallback(function (event, newValue) {
|
127 | onHighlightChange == null ? void 0 : onHighlightChange(event, newValue != null ? newValue : null);
|
128 | }, [onHighlightChange]);
|
129 | var handleStateChange = React.useCallback(function (event, field, fieldValue) {
|
130 | if (field === 'open') {
|
131 | onOpenChange == null ? void 0 : onOpenChange(fieldValue);
|
132 | if (fieldValue === false && (event == null ? void 0 : event.type) !== 'blur') {
|
133 | var _buttonRef$current;
|
134 | (_buttonRef$current = buttonRef.current) == null ? void 0 : _buttonRef$current.focus();
|
135 | }
|
136 | }
|
137 | }, [onOpenChange]);
|
138 | var useListParameters = {
|
139 | getInitialState: function getInitialState() {
|
140 | var _defaultValue;
|
141 | return {
|
142 | highlightedValue: null,
|
143 | selectedValues: (_defaultValue = defaultValue) != null ? _defaultValue : [],
|
144 | open: defaultOpen
|
145 | };
|
146 | },
|
147 | getItemId: getItemId,
|
148 | controlledProps: controlledState,
|
149 | isItemDisabled: isItemDisabled,
|
150 | rootRef: mergedButtonRef,
|
151 | onChange: handleSelectionChange,
|
152 | onHighlightChange: handleHighlightChange,
|
153 | onStateChange: handleStateChange,
|
154 | reducerActionContext: React.useMemo(function () {
|
155 | return {
|
156 | multiple: multiple
|
157 | };
|
158 | }, [multiple]),
|
159 | items: optionValues,
|
160 | getItemAsString: stringifyOption,
|
161 | selectionMode: multiple ? 'multiple' : 'single',
|
162 | stateReducer: selectReducer
|
163 | };
|
164 | var _useList = useList(useListParameters),
|
165 | dispatch = _useList.dispatch,
|
166 | getListboxRootProps = _useList.getRootProps,
|
167 | listContextValue = _useList.contextValue,
|
168 | _useList$state = _useList.state,
|
169 | open = _useList$state.open,
|
170 | highlightedOption = _useList$state.highlightedValue,
|
171 | selectedOptions = _useList$state.selectedValues,
|
172 | mergedListRootRef = _useList.rootRef;
|
173 | var createHandleButtonClick = function createHandleButtonClick(otherHandlers) {
|
174 | return function (event) {
|
175 | var _otherHandlers$onClic;
|
176 | otherHandlers == null ? void 0 : (_otherHandlers$onClic = otherHandlers.onClick) == null ? void 0 : _otherHandlers$onClic.call(otherHandlers, event);
|
177 | if (!event.defaultMuiPrevented) {
|
178 | var action = {
|
179 | type: SelectActionTypes.buttonClick,
|
180 | event: event
|
181 | };
|
182 | dispatch(action);
|
183 | }
|
184 | };
|
185 | };
|
186 | useEnhancedEffect(function () {
|
187 |
|
188 | if (highlightedOption != null) {
|
189 | var _options$get2;
|
190 | var optionRef = (_options$get2 = options.get(highlightedOption)) == null ? void 0 : _options$get2.ref;
|
191 | if (!listboxRef.current || !(optionRef != null && optionRef.current)) {
|
192 | return;
|
193 | }
|
194 | var listboxClientRect = listboxRef.current.getBoundingClientRect();
|
195 | var optionClientRect = optionRef.current.getBoundingClientRect();
|
196 | if (optionClientRect.top < listboxClientRect.top) {
|
197 | listboxRef.current.scrollTop -= listboxClientRect.top - optionClientRect.top;
|
198 | } else if (optionClientRect.bottom > listboxClientRect.bottom) {
|
199 | listboxRef.current.scrollTop += optionClientRect.bottom - listboxClientRect.bottom;
|
200 | }
|
201 | }
|
202 | }, [highlightedOption, options]);
|
203 | var getOptionMetadata = React.useCallback(function (optionValue) {
|
204 | return options.get(optionValue);
|
205 | }, [options]);
|
206 | var getSelectTriggerProps = function getSelectTriggerProps() {
|
207 | var otherHandlers = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
|
208 | return _extends({}, otherHandlers, {
|
209 | onClick: createHandleButtonClick(otherHandlers),
|
210 | ref: mergedListRootRef,
|
211 | role: 'combobox',
|
212 | 'aria-expanded': open,
|
213 | 'aria-controls': listboxId
|
214 | });
|
215 | };
|
216 | var getButtonProps = function getButtonProps() {
|
217 | var otherHandlers = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
|
218 | var listboxAndButtonProps = combineHooksSlotProps(getButtonRootProps, getListboxRootProps);
|
219 | var combinedProps = combineHooksSlotProps(listboxAndButtonProps, getSelectTriggerProps);
|
220 | return combinedProps(otherHandlers);
|
221 | };
|
222 | var getListboxProps = function getListboxProps() {
|
223 | var otherHandlers = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
|
224 | return _extends({}, otherHandlers, {
|
225 | id: listboxId,
|
226 | role: 'listbox',
|
227 | 'aria-multiselectable': multiple ? 'true' : undefined,
|
228 | ref: handleListboxRef,
|
229 | onMouseDown: preventDefault
|
230 | });
|
231 | };
|
232 |
|
233 | React.useDebugValue({
|
234 | selectedOptions: selectedOptions,
|
235 | highlightedOption: highlightedOption,
|
236 | open: open
|
237 | });
|
238 | var contextValue = React.useMemo(function () {
|
239 | return _extends({}, listContextValue, compoundComponentContextValue);
|
240 | }, [listContextValue, compoundComponentContextValue]);
|
241 | var selectValue;
|
242 | if (props.multiple) {
|
243 | selectValue = selectedOptions;
|
244 | } else {
|
245 | selectValue = selectedOptions.length > 0 ? selectedOptions[0] : null;
|
246 | }
|
247 | return {
|
248 | buttonActive: buttonActive,
|
249 | buttonFocusVisible: buttonFocusVisible,
|
250 | buttonRef: mergedButtonRef,
|
251 | contextValue: contextValue,
|
252 | disabled: disabled,
|
253 | dispatch: dispatch,
|
254 | getButtonProps: getButtonProps,
|
255 | getListboxProps: getListboxProps,
|
256 | getOptionMetadata: getOptionMetadata,
|
257 | listboxRef: mergedListRootRef,
|
258 | open: open,
|
259 | options: optionValues,
|
260 | value: selectValue,
|
261 | highlightedOption: highlightedOption
|
262 | };
|
263 | }
|
264 | export default useSelect; |
\ | No newline at end of file |