@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.
- package/lib/_virtual/index.css.js +12 -12
- package/lib/constants.d.ts +0 -1
- package/lib/constants.js +1 -2
- package/lib/hooks/use-a11y.d.ts +29 -0
- package/lib/hooks/use-a11y.js +53 -0
- package/lib/hooks/use-backward-compatible-id.d.ts +4 -0
- package/lib/hooks/use-backward-compatible-id.js +14 -0
- package/lib/hooks/use-focus.d.ts +10 -0
- package/lib/hooks/use-focus.js +17 -0
- package/lib/hooks/use-hover.d.ts +10 -0
- package/lib/hooks/use-hover.js +17 -0
- package/lib/hooks/use-label-focus.d.ts +1 -3
- package/lib/hooks/use-label-focus.js +3 -9
- package/lib/hooks/use-multi-handlers.d.ts +11 -0
- package/lib/hooks/use-multi-handlers.js +48 -0
- package/lib/hooks/use-options.d.ts +13 -0
- package/lib/hooks/use-options.js +89 -0
- package/lib/index.css +423 -1195
- package/lib/multiselect.d.ts +3 -29
- package/lib/multiselect.js +250 -180
- package/lib/native-select.js +75 -48
- package/lib/parts/hidden-select.d.ts +13 -0
- package/lib/parts/hidden-select.js +45 -0
- package/lib/parts/icons.js +2 -8
- package/lib/parts/list-box.d.ts +7 -15
- package/lib/parts/list-box.js +50 -82
- package/lib/parts/multi-trigger.d.ts +5 -4
- package/lib/parts/multi-trigger.js +27 -15
- package/lib/public-api.p.css +368 -126
- package/lib/public-api.pcss +368 -126
- package/lib/select-basic.d.ts +2 -2
- package/lib/select-basic.js +160 -103
- package/lib/select-searchable.d.ts +2 -2
- package/lib/select-searchable.js +205 -127
- package/lib/select.d.ts +1 -1
- package/lib/select.js +38 -31
- package/lib/styles/common.p.module.css.js +28 -24
- package/lib/styles/form-trigger.p.module.css.js +12 -12
- package/lib/styles/list-box.p.module.css.js +11 -13
- package/lib/types.d.ts +26 -27
- package/lib/utils/get-real-items-cnt.d.ts +2 -2
- package/lib/utils/get-real-items-cnt.js +8 -10
- package/lib/utils/item-to-string.d.ts +2 -0
- package/lib/utils/item-to-string.js +7 -0
- package/lib/utils/merge-props.d.ts +29 -0
- package/lib/utils/merge-props.js +106 -0
- package/package.json +11 -23
- package/lib/hooks/use-css-context-transfer.d.ts +0 -14
- package/lib/hooks/use-css-context-transfer.js +0 -40
- package/lib/hooks/use-multi-option-serialization.d.ts +0 -10
- package/lib/hooks/use-multi-option-serialization.js +0 -82
- package/lib/hooks/use-observable-force-rerender.d.ts +0 -2
- package/lib/hooks/use-observable-force-rerender.js +0 -16
- package/lib/hooks/use-option-serialization.d.ts +0 -10
- package/lib/hooks/use-option-serialization.js +0 -59
- package/lib/parts/native-select-trigger.d.ts +0 -18
- package/lib/parts/native-select-trigger.js +0 -54
- package/lib/parts/popover.d.ts +0 -12
- package/lib/parts/popover.js +0 -64
- package/lib/parts/popup-content.d.ts +0 -19
- package/lib/parts/popup-content.js +0 -76
- package/lib/styles/native-select-trigger.p.module.css.js +0 -17
- package/lib/styles/native-select.p.module.css.js +0 -9
- package/lib/styles/popover.p.module.css.js +0 -10
- package/lib/utils/convert-options.d.ts +0 -3
- package/lib/utils/convert-options.js +0 -52
- package/lib/utils/convert-placement.d.ts +0 -3
- package/lib/utils/convert-placement.js +0 -22
- package/lib/utils/css-vars-utils.d.ts +0 -3
- package/lib/utils/css-vars-utils.js +0 -20
package/lib/native-select.js
CHANGED
|
@@ -1,20 +1,20 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
import React
|
|
2
|
+
import React from 'react';
|
|
3
3
|
import PropTypes from 'prop-types';
|
|
4
4
|
import cn from 'classnames';
|
|
5
5
|
import { useThemeWithUndefined } from '@rescui/ui-contexts';
|
|
6
6
|
import { ErrorMessage } from '@rescui/form-field';
|
|
7
|
-
import { useField } from '@react-aria/label';
|
|
8
|
-
import { useFocusRing } from '@react-aria/focus';
|
|
9
|
-
import { mergeProps } from '@react-aria/utils';
|
|
10
7
|
import { nativeOptionType, nativeOptionsGroupType, noOptionsMessageType } from './common-prop-types.js';
|
|
8
|
+
import { useA11y } from './hooks/use-a11y.js';
|
|
9
|
+
import { useHover } from './hooks/use-hover.js';
|
|
10
|
+
import { useFocus } from './hooks/use-focus.js';
|
|
11
11
|
import { FormTriggerWrapper } from './parts/form-trigger-wrapper.js';
|
|
12
|
+
import { NativeSelectOptionsWithGroups } from './parts/native-select-options-with-groups.js';
|
|
13
|
+
import { Icons } from './parts/icons.js';
|
|
12
14
|
import { isOptionAGroup } from './utils/is-option-a-group.js';
|
|
13
15
|
import { getEmptyMessage } from './utils/get-empty-message.js';
|
|
14
|
-
import {
|
|
15
|
-
import
|
|
16
|
-
import { NativeSelectOptionsWithGroups } from './parts/native-select-options-with-groups.js';
|
|
17
|
-
import styles from './styles/native-select.p.module.css.js';
|
|
16
|
+
import { mergeProps } from './utils/merge-props.js';
|
|
17
|
+
import styles from './styles/common.p.module.css.js';
|
|
18
18
|
|
|
19
19
|
function findSelectedOption(options, selectedValue) {
|
|
20
20
|
let result = null;
|
|
@@ -42,6 +42,10 @@ const SIZE_STYLES = {
|
|
|
42
42
|
s: styles.sizeS,
|
|
43
43
|
m: styles.sizeM,
|
|
44
44
|
l: styles.sizeL
|
|
45
|
+
};
|
|
46
|
+
const THEME_STYLES = {
|
|
47
|
+
light: styles.themeLight,
|
|
48
|
+
dark: styles.themeDark
|
|
45
49
|
}; // eslint-disable-next-line complexity
|
|
46
50
|
|
|
47
51
|
const NativeSelect = _ref => {
|
|
@@ -57,6 +61,7 @@ const NativeSelect = _ref => {
|
|
|
57
61
|
placeholder,
|
|
58
62
|
isLoading = false,
|
|
59
63
|
isDisabled = false,
|
|
64
|
+
isClearable = false,
|
|
60
65
|
trigger,
|
|
61
66
|
label,
|
|
62
67
|
note,
|
|
@@ -65,20 +70,25 @@ const NativeSelect = _ref => {
|
|
|
65
70
|
noOptionsMessage,
|
|
66
71
|
name,
|
|
67
72
|
boldLabel = true,
|
|
68
|
-
...
|
|
73
|
+
...rest
|
|
69
74
|
} = _ref;
|
|
75
|
+
const triggerRef = React.useRef(null);
|
|
70
76
|
const {
|
|
71
77
|
labelProps,
|
|
72
78
|
fieldProps,
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
} =
|
|
76
|
-
|
|
79
|
+
errorMessageProps,
|
|
80
|
+
descriptionProps
|
|
81
|
+
} = useA11y({
|
|
82
|
+
prefix: 'native-select',
|
|
83
|
+
error,
|
|
77
84
|
description: note,
|
|
78
|
-
|
|
85
|
+
label,
|
|
86
|
+
fieldRef: triggerRef
|
|
79
87
|
});
|
|
88
|
+
|
|
89
|
+
const reset = () => onChange(null);
|
|
90
|
+
|
|
80
91
|
const theme = useThemeWithUndefined(themeFromProps);
|
|
81
|
-
const [isHovered, setIsHovered] = useState(false);
|
|
82
92
|
|
|
83
93
|
const handleChange = event => {
|
|
84
94
|
const newValue = event.target.value;
|
|
@@ -87,28 +97,30 @@ const NativeSelect = _ref => {
|
|
|
87
97
|
if (onChange) {
|
|
88
98
|
onChange(selectedOption);
|
|
89
99
|
}
|
|
90
|
-
};
|
|
100
|
+
}; // delete it when triggerFunc is migrated to the css-states instead of js-props for hover/focus
|
|
101
|
+
// replace it with ":focus + &" selector in that case
|
|
102
|
+
|
|
91
103
|
|
|
92
|
-
const triggerRef = React.useRef(null);
|
|
93
104
|
const {
|
|
94
|
-
|
|
105
|
+
isFocused,
|
|
95
106
|
focusProps
|
|
96
|
-
} =
|
|
97
|
-
|
|
98
|
-
});
|
|
107
|
+
} = useFocus({
|
|
108
|
+
isDisabled
|
|
109
|
+
}); // same as above, could be replaced with ":hover + &" selector
|
|
110
|
+
|
|
99
111
|
const {
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
112
|
+
isHovered,
|
|
113
|
+
hoverProps
|
|
114
|
+
} = useHover({
|
|
115
|
+
isDisabled
|
|
116
|
+
});
|
|
105
117
|
const emptyListMessage = getEmptyMessage({
|
|
106
118
|
isLoading,
|
|
107
119
|
isNothingFound: false,
|
|
108
120
|
noOptionsMessage
|
|
109
121
|
});
|
|
110
122
|
return /*#__PURE__*/React.createElement("div", {
|
|
111
|
-
className: cn(className, styles.
|
|
123
|
+
className: cn(className, styles.root, SIZE_STYLES[size], THEME_STYLES[theme], styles.classic, isDisabled ? styles.disabled : styles.enabled, Boolean(error) && styles.error),
|
|
112
124
|
id: id,
|
|
113
125
|
style: style,
|
|
114
126
|
"data-test": "native-select"
|
|
@@ -117,7 +129,7 @@ const NativeSelect = _ref => {
|
|
|
117
129
|
size: size,
|
|
118
130
|
disabled: isDisabled,
|
|
119
131
|
label: label,
|
|
120
|
-
labelProps: mergeProps(
|
|
132
|
+
labelProps: mergeProps(labelProps),
|
|
121
133
|
boldLabel: boldLabel,
|
|
122
134
|
error: error,
|
|
123
135
|
errorMessageProps: errorMessageProps,
|
|
@@ -125,26 +137,15 @@ const NativeSelect = _ref => {
|
|
|
125
137
|
note: note,
|
|
126
138
|
descriptionProps: descriptionProps
|
|
127
139
|
}, /*#__PURE__*/React.createElement("div", {
|
|
128
|
-
className: styles.
|
|
129
|
-
},
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
isLoading: isLoading,
|
|
138
|
-
isFocused: isFocused,
|
|
139
|
-
isHovered: isHovered,
|
|
140
|
-
isDisabled: isDisabled,
|
|
141
|
-
size: size,
|
|
142
|
-
theme: theme,
|
|
143
|
-
hasError: Boolean(error),
|
|
144
|
-
placeholder: placeholder
|
|
145
|
-
}), /*#__PURE__*/React.createElement("select", { ...mergeProps(fieldProps, focusProps, labelFocusForTriggerProps, {
|
|
146
|
-
onMouseEnter: () => setIsHovered(true),
|
|
147
|
-
onMouseLeave: () => setIsHovered(false)
|
|
140
|
+
className: styles.triggerContainer
|
|
141
|
+
}, /*#__PURE__*/React.createElement("select", { ...rest,
|
|
142
|
+
...mergeProps(fieldProps, focusProps, hoverProps, {
|
|
143
|
+
onKeyDown: event => {
|
|
144
|
+
// backspace and backspace removing the last selected item (when popup is closed)
|
|
145
|
+
if (isClearable && (event.key === 'Backspace' || event.key === 'Delete')) {
|
|
146
|
+
reset();
|
|
147
|
+
}
|
|
148
|
+
}
|
|
148
149
|
}),
|
|
149
150
|
ref: triggerRef,
|
|
150
151
|
"data-test": "native-select_select",
|
|
@@ -158,6 +159,32 @@ const NativeSelect = _ref => {
|
|
|
158
159
|
optionsWithGroups: options,
|
|
159
160
|
placeholder: placeholder,
|
|
160
161
|
emptyListMessage: emptyListMessage
|
|
162
|
+
})), trigger ? trigger({
|
|
163
|
+
focused: isFocused,
|
|
164
|
+
hovered: isHovered,
|
|
165
|
+
selectedLabel: value === null || value === void 0 ? void 0 : value.label,
|
|
166
|
+
selectedValue: value === null || value === void 0 ? void 0 : value.value,
|
|
167
|
+
placeholder
|
|
168
|
+
}) : /*#__PURE__*/React.createElement("div", {
|
|
169
|
+
className: cn(styles.trigger),
|
|
170
|
+
"data-test": 'native-select_trigger',
|
|
171
|
+
"data-rs-internal": 'select-native-trigger'
|
|
172
|
+
}, /*#__PURE__*/React.createElement("span", {
|
|
173
|
+
className: cn(styles.triggerText, !(value !== null && value !== void 0 && value.value) && styles.labelNotSelected),
|
|
174
|
+
"data-test": 'native-select_trigger_text',
|
|
175
|
+
"aria-hidden": "true"
|
|
176
|
+
}, (value === null || value === void 0 ? void 0 : value.label) ?? placeholder), /*#__PURE__*/React.createElement(Icons, {
|
|
177
|
+
isLoading: isLoading,
|
|
178
|
+
triggerId: fieldProps.id,
|
|
179
|
+
onClear: () => {
|
|
180
|
+
var _triggerRef$current;
|
|
181
|
+
|
|
182
|
+
reset();
|
|
183
|
+
(_triggerRef$current = triggerRef.current) === null || _triggerRef$current === void 0 || _triggerRef$current.focus({
|
|
184
|
+
focusVisible: false
|
|
185
|
+
});
|
|
186
|
+
},
|
|
187
|
+
canHaveClearIcon: isClearable && !isDisabled && Boolean(value === null || value === void 0 ? void 0 : value.value)
|
|
161
188
|
})))));
|
|
162
189
|
};
|
|
163
190
|
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/// <reference types="react" />
|
|
2
|
+
import type { SelectOption } from '../types';
|
|
3
|
+
export declare type HiddenSelectProps = {
|
|
4
|
+
name?: string;
|
|
5
|
+
options: SelectOption[];
|
|
6
|
+
} & ({
|
|
7
|
+
value: SelectOption[];
|
|
8
|
+
isMultiple: true;
|
|
9
|
+
} | {
|
|
10
|
+
value: SelectOption;
|
|
11
|
+
isMultiple: false;
|
|
12
|
+
});
|
|
13
|
+
export declare const HiddenSelect: ({ name, options, value, isMultiple }: HiddenSelectProps) => JSX.Element;
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import styles from '../styles/common.p.module.css.js';
|
|
3
|
+
|
|
4
|
+
const HiddenSelect = _ref => {
|
|
5
|
+
let {
|
|
6
|
+
name,
|
|
7
|
+
options,
|
|
8
|
+
value,
|
|
9
|
+
isMultiple
|
|
10
|
+
} = _ref;
|
|
11
|
+
const selectProps = {
|
|
12
|
+
name,
|
|
13
|
+
'aria-hidden': true,
|
|
14
|
+
readOnly: true,
|
|
15
|
+
tabIndex: -1
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
if (isMultiple) {
|
|
19
|
+
selectProps.multiple = true;
|
|
20
|
+
|
|
21
|
+
if (value && value.length !== 0) {
|
|
22
|
+
selectProps.value = value.map(v => String(v.value));
|
|
23
|
+
}
|
|
24
|
+
} else if (value) {
|
|
25
|
+
const singleValue = value;
|
|
26
|
+
selectProps.value = singleValue.value;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
const arrayValue = isMultiple ? value : [value]; // merge options with value in case the provided value is not included in options
|
|
30
|
+
|
|
31
|
+
const allItems = Array.from( // map will deduplicate options by values
|
|
32
|
+
new Map((!value ? options : [...options, ...arrayValue]).map(item => [item.value, item])).values());
|
|
33
|
+
return /*#__PURE__*/React.createElement("div", {
|
|
34
|
+
className: styles.visuallyHidden
|
|
35
|
+
}, /*#__PURE__*/React.createElement("select", { ...selectProps
|
|
36
|
+
}, /*#__PURE__*/React.createElement("option", {
|
|
37
|
+
value: "",
|
|
38
|
+
label: '\u00A0'
|
|
39
|
+
}, '\u00A0'), allItems.map(option => /*#__PURE__*/React.createElement("option", {
|
|
40
|
+
key: option.value,
|
|
41
|
+
value: option.value
|
|
42
|
+
}, option.label))));
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
export { HiddenSelect };
|
package/lib/parts/icons.js
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import cn from 'classnames';
|
|
3
|
-
import { useFocusRing } from '@react-aria/focus';
|
|
4
3
|
import CloseOutlineIcon from '../_virtual/close-outline.js';
|
|
5
4
|
import LoadingOutlineIcon from '../_virtual/loading-outline.js';
|
|
6
5
|
import DownOutlineIcon from '../_virtual/down-outline.js';
|
|
@@ -14,10 +13,6 @@ const ClearOrLoading = _ref => {
|
|
|
14
13
|
triggerId,
|
|
15
14
|
className
|
|
16
15
|
} = _ref;
|
|
17
|
-
const {
|
|
18
|
-
isFocusVisible,
|
|
19
|
-
focusProps
|
|
20
|
-
} = useFocusRing();
|
|
21
16
|
|
|
22
17
|
if (isLoading) {
|
|
23
18
|
return /*#__PURE__*/React.createElement(LoadingOutlineIcon, {
|
|
@@ -31,7 +26,7 @@ const ClearOrLoading = _ref => {
|
|
|
31
26
|
} else if (canHaveClearIcon) {
|
|
32
27
|
return /*#__PURE__*/React.createElement("button", {
|
|
33
28
|
type: "button",
|
|
34
|
-
className: cn(className, styles.icon, styles.clearIcon
|
|
29
|
+
className: cn(className, styles.icon, styles.clearIcon),
|
|
35
30
|
"data-test": "clear-icon",
|
|
36
31
|
onClick: e => {
|
|
37
32
|
e.stopPropagation();
|
|
@@ -41,8 +36,7 @@ const ClearOrLoading = _ref => {
|
|
|
41
36
|
onMouseDown: e => e.stopPropagation(),
|
|
42
37
|
onKeyDown: e => e.stopPropagation(),
|
|
43
38
|
"aria-label": "Clear",
|
|
44
|
-
"aria-controls": triggerId
|
|
45
|
-
...focusProps
|
|
39
|
+
"aria-controls": triggerId
|
|
46
40
|
}, /*#__PURE__*/React.createElement(CloseOutlineIcon, {
|
|
47
41
|
"data-render-all-sizes": true
|
|
48
42
|
}));
|
package/lib/parts/list-box.d.ts
CHANGED
|
@@ -1,19 +1,11 @@
|
|
|
1
|
-
|
|
2
|
-
import
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
listBoxRef?: React.RefObject<HTMLUListElement>;
|
|
7
|
-
state: ListState<T>;
|
|
8
|
-
ariaListBoxProps?: AriaListBoxOptions<T>;
|
|
1
|
+
/// <reference types="react" />
|
|
2
|
+
import { SelectSize, ListBoxItem, ListBoxState } from '../types';
|
|
3
|
+
export declare type ListBoxProps = {
|
|
4
|
+
state: ListBoxState;
|
|
5
|
+
items: ListBoxItem[];
|
|
9
6
|
size?: SelectSize;
|
|
10
|
-
mode?: SelectMode;
|
|
11
7
|
className?: string;
|
|
12
8
|
maxVisibleItems?: number;
|
|
13
|
-
selectionMode?: 'single' | 'multiple';
|
|
14
|
-
};
|
|
15
|
-
export declare function ListBox<T extends object>({ listBoxRef: listBoxRefFromProps, state, ariaListBoxProps, size, mode, maxVisibleItems, selectionMode }: ListBoxProps<T>): JSX.Element;
|
|
16
|
-
export declare type EmptyListBoxProps<T extends object> = {
|
|
17
9
|
emptyListMessage: string;
|
|
18
|
-
}
|
|
19
|
-
export declare
|
|
10
|
+
};
|
|
11
|
+
export declare function ListBox({ state, items, size, maxVisibleItems, emptyListMessage }: ListBoxProps): JSX.Element;
|
package/lib/parts/list-box.js
CHANGED
|
@@ -1,18 +1,10 @@
|
|
|
1
1
|
import React, { useRef } from 'react';
|
|
2
2
|
import cn from 'classnames';
|
|
3
|
-
import { useListState } from '@react-stately/list';
|
|
4
|
-
import { Item } from '@react-stately/collections';
|
|
5
|
-
import { useListBox, useOption, useListBoxSection } from '@react-aria/listbox';
|
|
6
|
-
import { mergeProps } from '@react-aria/utils';
|
|
7
3
|
import styles from '../styles/list-box.p.module.css.js';
|
|
8
4
|
import { calculateMaxHeightByItems } from '../utils/calculate-max-height-by-items.js';
|
|
9
5
|
import { getRealItemsCnt } from '../utils/get-real-items-cnt.js';
|
|
10
|
-
import {
|
|
6
|
+
import { getTextFromNodes } from '../utils/get-text-from-nodes.js';
|
|
11
7
|
import CheckOutlineIcon from '../_virtual/check-outline.js';
|
|
12
|
-
const MODE_STYLES = {
|
|
13
|
-
classic: styles.modeClassic,
|
|
14
|
-
rock: styles.modeRock
|
|
15
|
-
};
|
|
16
8
|
const SIZE_STYLES = {
|
|
17
9
|
s: styles.sizeS,
|
|
18
10
|
m: styles.sizeM,
|
|
@@ -22,66 +14,65 @@ const SIZE_STYLES = {
|
|
|
22
14
|
function Option(_ref) {
|
|
23
15
|
let {
|
|
24
16
|
item,
|
|
25
|
-
state
|
|
26
|
-
selectionMode
|
|
17
|
+
state
|
|
27
18
|
} = _ref;
|
|
28
19
|
// Get props for the option element
|
|
29
20
|
const ref = useRef(null);
|
|
30
21
|
const {
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
} =
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
22
|
+
selectedMap,
|
|
23
|
+
selectionMode,
|
|
24
|
+
getItemProps,
|
|
25
|
+
highlightedIndex
|
|
26
|
+
} = state;
|
|
27
|
+
const index = item.index;
|
|
28
|
+
const isSelected = selectedMap.has(item.key);
|
|
29
|
+
const isHighlighted = highlightedIndex === item.index;
|
|
30
|
+
const isDisabled = item.disabled;
|
|
31
|
+
return /*#__PURE__*/React.createElement("li", { ...getItemProps({
|
|
32
|
+
item,
|
|
33
|
+
index,
|
|
34
|
+
'aria-selected': isSelected,
|
|
35
|
+
'tab-index': isHighlighted ? 0 : -1,
|
|
36
|
+
ref
|
|
37
|
+
}),
|
|
40
38
|
className: cn(styles.item, isSelected && styles.selected, isDisabled && styles.disabled),
|
|
41
39
|
"data-rs-internal": "select-list-box__item",
|
|
42
|
-
"data-focused":
|
|
40
|
+
"data-focused": isHighlighted,
|
|
43
41
|
"data-test": `select-options-list__item_${item.key}`
|
|
44
|
-
}, /*#__PURE__*/React.createElement("span", null, item.
|
|
42
|
+
}, /*#__PURE__*/React.createElement("span", null, item.label), selectionMode === 'multiple' && /*#__PURE__*/React.createElement(CheckOutlineIcon, {
|
|
45
43
|
"data-rs-internal": "select-list-box__check-icon",
|
|
46
44
|
className: cn(styles.checkIcon, isSelected && styles.visible)
|
|
47
45
|
}));
|
|
48
46
|
}
|
|
49
47
|
|
|
50
|
-
function
|
|
48
|
+
function ListBoxGroup(_ref2) {
|
|
51
49
|
let {
|
|
52
|
-
|
|
53
|
-
state,
|
|
50
|
+
item,
|
|
54
51
|
isFirst,
|
|
55
|
-
|
|
52
|
+
state
|
|
56
53
|
} = _ref2;
|
|
57
|
-
const
|
|
58
|
-
itemProps,
|
|
59
|
-
headingProps,
|
|
60
|
-
groupProps
|
|
61
|
-
} = useListBoxSection({
|
|
62
|
-
heading: section.rendered,
|
|
63
|
-
'aria-label': section['aria-label']
|
|
64
|
-
});
|
|
65
|
-
const hasHeading = section.rendered !== null && section.rendered !== undefined;
|
|
54
|
+
const hasHeading = item.label !== null && item.label !== undefined;
|
|
66
55
|
const hasDivider = !isFirst && !hasHeading; // If the section is not the first, add a divider for visual separation
|
|
67
56
|
|
|
68
57
|
return /*#__PURE__*/React.createElement(React.Fragment, null, hasDivider && /*#__PURE__*/React.createElement("hr", {
|
|
69
58
|
className: styles.divider
|
|
70
|
-
}), /*#__PURE__*/React.createElement("li", {
|
|
59
|
+
}), /*#__PURE__*/React.createElement("li", {
|
|
60
|
+
role: "presentation"
|
|
71
61
|
}, hasHeading && /*#__PURE__*/React.createElement("span", {
|
|
72
62
|
className: styles.groupHeader,
|
|
73
|
-
|
|
63
|
+
role: "presentation",
|
|
74
64
|
"data-rs-internal": "select-list-box__group-header"
|
|
75
|
-
},
|
|
65
|
+
}, item.label), /*#__PURE__*/React.createElement("ul", {
|
|
66
|
+
role: "group",
|
|
67
|
+
"aria-label": hasHeading ? getTextFromNodes(item.label) : undefined,
|
|
76
68
|
style: {
|
|
77
69
|
padding: 0,
|
|
78
70
|
listStyle: 'none'
|
|
79
71
|
}
|
|
80
|
-
},
|
|
81
|
-
key:
|
|
82
|
-
item:
|
|
83
|
-
state: state
|
|
84
|
-
selectionMode: selectionMode
|
|
72
|
+
}, item.options.map(option => /*#__PURE__*/React.createElement(Option, {
|
|
73
|
+
key: option.key,
|
|
74
|
+
item: option,
|
|
75
|
+
state: state
|
|
85
76
|
})))));
|
|
86
77
|
}
|
|
87
78
|
|
|
@@ -89,60 +80,37 @@ function ListBox(_ref3) {
|
|
|
89
80
|
var _items$find;
|
|
90
81
|
|
|
91
82
|
let {
|
|
92
|
-
listBoxRef: listBoxRefFromProps,
|
|
93
83
|
state,
|
|
94
|
-
|
|
84
|
+
items,
|
|
95
85
|
size,
|
|
96
|
-
mode,
|
|
97
86
|
maxVisibleItems = 5,
|
|
98
|
-
|
|
87
|
+
emptyListMessage
|
|
99
88
|
} = _ref3;
|
|
100
|
-
const ref = useRef(null);
|
|
101
|
-
const listBoxRef = listBoxRefFromProps ?? ref;
|
|
102
89
|
const {
|
|
103
|
-
|
|
104
|
-
} =
|
|
105
|
-
const
|
|
106
|
-
const
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
className: cn(styles.listBox, MODE_STYLES[mode], SIZE_STYLES[size]),
|
|
110
|
-
ref: listBoxRef,
|
|
90
|
+
menuProps
|
|
91
|
+
} = state;
|
|
92
|
+
const firstGroupKey = (_items$find = items.find(item => item.type === 'group')) === null || _items$find === void 0 ? void 0 : _items$find.key;
|
|
93
|
+
const itemsCount = getRealItemsCnt(items);
|
|
94
|
+
return /*#__PURE__*/React.createElement("ul", { ...menuProps,
|
|
95
|
+
className: cn(styles.listBox, SIZE_STYLES[size]),
|
|
111
96
|
style: {
|
|
112
97
|
'--_rs-select-list-box-max-height-by-items': calculateMaxHeightByItems(itemsCount, maxVisibleItems)
|
|
113
98
|
},
|
|
114
99
|
"data-rs-internal": "select-list-box",
|
|
115
100
|
"data-test": "select-options-list"
|
|
116
|
-
},
|
|
101
|
+
}, itemsCount === 0 ? /*#__PURE__*/React.createElement("li", {
|
|
102
|
+
className: cn(styles.item, styles.disabled),
|
|
103
|
+
"data-rs-internal": "select-list-box__item"
|
|
104
|
+
}, /*#__PURE__*/React.createElement("span", null, emptyListMessage)) : items.map(item => item.type === 'group' ? /*#__PURE__*/React.createElement(ListBoxGroup, {
|
|
117
105
|
key: item.key,
|
|
118
|
-
|
|
106
|
+
item: item,
|
|
119
107
|
state: state,
|
|
120
|
-
isFirst: item.key ===
|
|
121
|
-
selectionMode: selectionMode
|
|
108
|
+
isFirst: item.key === firstGroupKey
|
|
122
109
|
}) : /*#__PURE__*/React.createElement(Option, {
|
|
123
110
|
key: item.key,
|
|
124
111
|
item: item,
|
|
125
|
-
state: state
|
|
126
|
-
selectionMode: selectionMode
|
|
112
|
+
state: state
|
|
127
113
|
})));
|
|
128
114
|
}
|
|
129
115
|
|
|
130
|
-
|
|
131
|
-
let {
|
|
132
|
-
emptyListMessage,
|
|
133
|
-
...props
|
|
134
|
-
} = _ref4;
|
|
135
|
-
const emptyListState = useListState({
|
|
136
|
-
children: [/*#__PURE__*/React.createElement(Item, {
|
|
137
|
-
key: "no-results",
|
|
138
|
-
textValue: emptyListMessage
|
|
139
|
-
}, emptyListMessage)],
|
|
140
|
-
disabledKeys: ['no-results'],
|
|
141
|
-
selectionMode: 'none'
|
|
142
|
-
});
|
|
143
|
-
return /*#__PURE__*/React.createElement(ListBox, { ...props,
|
|
144
|
-
state: emptyListState
|
|
145
|
-
});
|
|
146
|
-
};
|
|
147
|
-
|
|
148
|
-
export { EmptyListBox, ListBox };
|
|
116
|
+
export { ListBox };
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
-
import type {
|
|
3
|
-
export interface MultiTriggerProps
|
|
4
|
-
|
|
2
|
+
import type { SelectOption } from '../types';
|
|
3
|
+
export interface MultiTriggerProps {
|
|
4
|
+
selectedItems: SelectOption[];
|
|
5
|
+
removeSelectedItem: (item: SelectOption) => void;
|
|
5
6
|
valueProps: object;
|
|
6
7
|
isSingleLine: boolean;
|
|
7
8
|
isDisabled: boolean;
|
|
8
9
|
placeholder?: string;
|
|
9
10
|
triggerRef?: React.RefObject<HTMLDivElement>;
|
|
10
11
|
}
|
|
11
|
-
export declare function MultiTrigger
|
|
12
|
+
export declare function MultiTrigger({ selectedItems, valueProps, isSingleLine, isDisabled, placeholder, triggerRef, removeSelectedItem }: MultiTriggerProps): JSX.Element;
|
|
@@ -3,18 +3,20 @@ import cn from 'classnames';
|
|
|
3
3
|
import { RemovableTag, Tag } from '@rescui/tag';
|
|
4
4
|
import styles from '../styles/common.p.module.css.js';
|
|
5
5
|
import { getTextFromNodes } from '../utils/get-text-from-nodes.js';
|
|
6
|
+
import { getOptionValue } from '../utils/get-option-value.js';
|
|
6
7
|
import Foldable from './foldable.js';
|
|
7
8
|
|
|
8
9
|
function MultiTrigger(_ref) {
|
|
9
10
|
let {
|
|
10
|
-
|
|
11
|
+
selectedItems,
|
|
11
12
|
valueProps,
|
|
12
13
|
isSingleLine,
|
|
13
14
|
isDisabled,
|
|
14
15
|
placeholder,
|
|
15
|
-
triggerRef
|
|
16
|
+
triggerRef,
|
|
17
|
+
removeSelectedItem
|
|
16
18
|
} = _ref;
|
|
17
|
-
const hasValue =
|
|
19
|
+
const hasValue = selectedItems.length > 0;
|
|
18
20
|
|
|
19
21
|
if (!hasValue) {
|
|
20
22
|
return /*#__PURE__*/React.createElement("div", { ...valueProps,
|
|
@@ -23,25 +25,35 @@ function MultiTrigger(_ref) {
|
|
|
23
25
|
}, placeholder);
|
|
24
26
|
}
|
|
25
27
|
|
|
26
|
-
const
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
state.setValue([...state.selectedItems].map(item => item.key).filter(itemKey => itemKey !== key));
|
|
30
|
-
(_triggerRef$current = triggerRef.current) === null || _triggerRef$current === void 0 || _triggerRef$current.focus();
|
|
31
|
-
};
|
|
32
|
-
|
|
33
|
-
const tags = [...state.selectedItems].map(item => {
|
|
34
|
-
const key = item.key;
|
|
28
|
+
const tags = selectedItems.map(option => {
|
|
29
|
+
const key = getOptionValue(option);
|
|
35
30
|
return /*#__PURE__*/React.createElement(RemovableTag, {
|
|
36
31
|
key: key,
|
|
32
|
+
tabIndex: -1,
|
|
37
33
|
"data-test": `selected-tag-${key}`,
|
|
38
34
|
className: styles.tag,
|
|
39
35
|
disabled: isDisabled,
|
|
40
|
-
onRemoveClick: () =>
|
|
36
|
+
onRemoveClick: () => {
|
|
37
|
+
var _triggerRef$current;
|
|
38
|
+
|
|
39
|
+
removeSelectedItem(option);
|
|
40
|
+
(_triggerRef$current = triggerRef.current) === null || _triggerRef$current === void 0 || _triggerRef$current.focus({
|
|
41
|
+
focusVisible: false
|
|
42
|
+
});
|
|
43
|
+
},
|
|
41
44
|
"data-rs-internal": "select-trigger__removable-tag",
|
|
42
45
|
wrap: !isSingleLine,
|
|
43
|
-
"aria-label": getTextFromNodes(
|
|
44
|
-
|
|
46
|
+
"aria-label": getTextFromNodes(option.label),
|
|
47
|
+
onFocus: e => {
|
|
48
|
+
if (e.target.getAttribute('tabindex') === '-1') {
|
|
49
|
+
var _triggerRef$current2;
|
|
50
|
+
|
|
51
|
+
(_triggerRef$current2 = triggerRef.current) === null || _triggerRef$current2 === void 0 || _triggerRef$current2.focus({
|
|
52
|
+
focusVisible: false
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
}, option.label);
|
|
45
57
|
});
|
|
46
58
|
return /*#__PURE__*/React.createElement("div", { ...valueProps,
|
|
47
59
|
className: styles.multi,
|