@rescui/select 0.15.1-RUI-280-Update-select-component-downshift-2f40ef205.67 → 0.15.2
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/common-prop-types.d.ts +14 -9
- package/lib/common-prop-types.js +3 -4
- package/lib/index.css +432 -808
- package/lib/index.d.ts +6 -4
- package/lib/index.js +3 -3
- package/lib/key-codes.d.ts +7 -0
- package/lib/key-codes.js +8 -0
- package/lib/parts/common-select.p.module.css.js +15 -0
- package/lib/parts/foldable.js +2 -1
- package/lib/parts/form-trigger-wrapper.d.ts +7 -7
- package/lib/parts/form-trigger-wrapper.js +34 -16
- package/lib/parts/form-trigger.p.module.css.js +15 -0
- package/lib/parts/multiselect.d.ts +86 -0
- package/lib/parts/multiselect.js +455 -0
- package/lib/parts/native-select.d.ts +36 -0
- package/lib/parts/native-select.js +255 -0
- package/lib/parts/native-select.p.module.css.js +9 -0
- package/lib/parts/throttle.d.ts +1 -0
- package/lib/parts/trigger.d.ts +37 -0
- package/lib/parts/trigger.js +255 -0
- package/lib/parts/trigger.p.module.css.js +31 -0
- package/lib/parts/use-observable-force-rerender.d.ts +2 -0
- package/lib/parts/use-observable-force-rerender.js +16 -0
- package/lib/public-api.p.css +309 -545
- package/lib/public-api.pcss +309 -545
- package/lib/select.d.ts +91 -27
- package/lib/select.js +351 -51
- package/lib/types.d.ts +4 -167
- package/lib/utils.d.ts +22 -0
- package/lib/utils.js +199 -0
- package/package.json +12 -12
- package/lib/constants.d.ts +0 -6
- package/lib/constants.js +0 -7
- package/lib/hooks/use-a11y.d.ts +0 -29
- package/lib/hooks/use-a11y.js +0 -53
- package/lib/hooks/use-focus.d.ts +0 -10
- package/lib/hooks/use-focus.js +0 -17
- package/lib/hooks/use-hover.d.ts +0 -10
- package/lib/hooks/use-hover.js +0 -17
- package/lib/hooks/use-label-focus.d.ts +0 -9
- package/lib/hooks/use-label-focus.js +0 -22
- package/lib/hooks/use-multi-handlers.d.ts +0 -11
- package/lib/hooks/use-multi-handlers.js +0 -48
- package/lib/hooks/use-options.d.ts +0 -13
- package/lib/hooks/use-options.js +0 -89
- package/lib/multiselect.d.ts +0 -3
- package/lib/multiselect.js +0 -312
- package/lib/native-select.d.ts +0 -4
- package/lib/native-select.js +0 -211
- package/lib/parts/hidden-select.d.ts +0 -13
- package/lib/parts/hidden-select.js +0 -45
- package/lib/parts/icons.d.ts +0 -17
- package/lib/parts/icons.js +0 -69
- package/lib/parts/list-box.d.ts +0 -11
- package/lib/parts/list-box.js +0 -116
- package/lib/parts/multi-trigger.d.ts +0 -12
- package/lib/parts/multi-trigger.js +0 -74
- package/lib/parts/native-select-options-with-groups.d.ts +0 -8
- package/lib/parts/native-select-options-with-groups.js +0 -76
- package/lib/select-basic.d.ts +0 -3
- package/lib/select-basic.js +0 -203
- package/lib/select-searchable.d.ts +0 -3
- package/lib/select-searchable.js +0 -250
- package/lib/styles/common.p.module.css.js +0 -31
- package/lib/styles/form-trigger.p.module.css.js +0 -15
- package/lib/styles/list-box.p.module.css.js +0 -14
- package/lib/utils/calculate-max-height-by-items.d.ts +0 -13
- package/lib/utils/calculate-max-height-by-items.js +0 -22
- package/lib/utils/get-empty-message.d.ts +0 -6
- package/lib/utils/get-empty-message.js +0 -32
- package/lib/utils/get-option-value.d.ts +0 -2
- package/lib/utils/get-option-value.js +0 -11
- package/lib/utils/get-real-items-cnt.d.ts +0 -2
- package/lib/utils/get-real-items-cnt.js +0 -19
- package/lib/utils/get-text-from-nodes.d.ts +0 -2
- package/lib/utils/get-text-from-nodes.js +0 -28
- package/lib/utils/is-option-a-group.d.ts +0 -2
- package/lib/utils/is-option-a-group.js +0 -5
- package/lib/utils/item-to-string.d.ts +0 -2
- package/lib/utils/item-to-string.js +0 -7
- package/lib/utils/merge-props.d.ts +0 -29
- package/lib/utils/merge-props.js +0 -106
- package/lib/utils/throttle.d.ts +0 -1
- /package/lib/{utils → parts}/throttle.js +0 -0
- /package/lib/{hooks → parts}/use-backward-compatible-id.d.ts +0 -0
- /package/lib/{hooks → parts}/use-backward-compatible-id.js +0 -0
package/lib/types.d.ts
CHANGED
|
@@ -1,13 +1,9 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
-
import type { Theme } from '@rescui/ui-contexts';
|
|
3
|
-
import type { UseSelectPropGetters } from 'downshift';
|
|
4
|
-
export declare type Key = string | number;
|
|
5
|
-
export declare type Placement = 'auto-start' | 'auto' | 'auto-end' | 'top-start' | 'top' | 'top-end' | 'right-start' | 'right' | 'right-end' | 'bottom-end' | 'bottom' | 'bottom-start' | 'left-end' | 'left' | 'left-start';
|
|
6
2
|
export declare type SelectSize = 'l' | 'm' | 's';
|
|
7
3
|
export declare type SelectMode = 'classic' | 'rock';
|
|
8
4
|
export declare type SelectOption = {
|
|
9
5
|
label: React.ReactNode;
|
|
10
|
-
value?:
|
|
6
|
+
value?: string;
|
|
11
7
|
};
|
|
12
8
|
export declare type SelectOptionsGroup = {
|
|
13
9
|
label?: React.ReactNode;
|
|
@@ -15,30 +11,9 @@ export declare type SelectOptionsGroup = {
|
|
|
15
11
|
};
|
|
16
12
|
export declare type SelectOptionOrGroup = SelectOption | SelectOptionsGroup;
|
|
17
13
|
export declare type SelectOptions = SelectOptionOrGroup[];
|
|
18
|
-
export declare type ListBoxOptionItem = SelectOption & {
|
|
19
|
-
index: number;
|
|
20
|
-
type: 'option';
|
|
21
|
-
key: Key;
|
|
22
|
-
disabled?: boolean;
|
|
23
|
-
};
|
|
24
|
-
export declare type ListBoxGroupItem = Omit<SelectOptionsGroup, 'options'> & {
|
|
25
|
-
options: ListBoxOptionItem[];
|
|
26
|
-
type: 'group';
|
|
27
|
-
key: Key;
|
|
28
|
-
};
|
|
29
|
-
export declare type ListBoxItem = ListBoxOptionItem | ListBoxGroupItem;
|
|
30
|
-
export declare type ListBoxItems = ListBoxItem[];
|
|
31
|
-
export declare type ListBoxState = {
|
|
32
|
-
menuProps: ReturnType<UseSelectPropGetters<SelectOption>['getMenuProps']>;
|
|
33
|
-
getItemProps: UseSelectPropGetters<SelectOption>['getItemProps'];
|
|
34
|
-
selectionMode: 'single' | 'multiple';
|
|
35
|
-
highlightedIndex: number;
|
|
36
|
-
selectedMap: Map<Key, SelectOption>;
|
|
37
|
-
menuRef?: React.RefObject<HTMLUListElement>;
|
|
38
|
-
};
|
|
39
14
|
export declare type NativeSelectOption = {
|
|
40
15
|
label: string;
|
|
41
|
-
value?:
|
|
16
|
+
value?: string;
|
|
42
17
|
disabled?: boolean;
|
|
43
18
|
};
|
|
44
19
|
export declare type NativeSelectOptionsGroup = {
|
|
@@ -49,149 +24,11 @@ export declare type NativeSelectOptionsGroup = {
|
|
|
49
24
|
export declare type NativeSelectOptionOrGroup = NativeSelectOption | NativeSelectOptionsGroup;
|
|
50
25
|
export declare type NativeSelectOptions = NativeSelectOptionOrGroup[];
|
|
51
26
|
export declare type Groups = SelectOptionsGroup[];
|
|
27
|
+
export declare type Index = [number, number];
|
|
28
|
+
export declare type FilterFn = (option: SelectOption) => boolean;
|
|
52
29
|
export declare type NoOptionsMessageConfig = {
|
|
53
30
|
noOptions: string;
|
|
54
31
|
nothingFound?: string;
|
|
55
32
|
loading?: string;
|
|
56
33
|
};
|
|
57
34
|
export declare type NoOptionsMessage = string | NoOptionsMessageConfig;
|
|
58
|
-
export declare type SelectProps = {
|
|
59
|
-
/**
|
|
60
|
-
* Value of the select
|
|
61
|
-
*/
|
|
62
|
-
value?: SelectOption | null;
|
|
63
|
-
/**
|
|
64
|
-
* Change value callback. `value => ...`. Pass `null` on clear.
|
|
65
|
-
*/
|
|
66
|
-
onChange?: (newValue: SelectOption | null) => void;
|
|
67
|
-
/**
|
|
68
|
-
* Additional class name
|
|
69
|
-
*/
|
|
70
|
-
className?: string;
|
|
71
|
-
style?: React.CSSProperties;
|
|
72
|
-
id?: string;
|
|
73
|
-
/**
|
|
74
|
-
* Array of options or option groups
|
|
75
|
-
*/
|
|
76
|
-
options?: (SelectOption | SelectOptionsGroup)[] | null;
|
|
77
|
-
/**
|
|
78
|
-
* Is select supports clearing the value
|
|
79
|
-
*/
|
|
80
|
-
isClearable?: boolean;
|
|
81
|
-
/**
|
|
82
|
-
* Is select supports inplace filtering
|
|
83
|
-
*/
|
|
84
|
-
isSearchable?: boolean;
|
|
85
|
-
/**
|
|
86
|
-
* Is the component has been disabled
|
|
87
|
-
*/
|
|
88
|
-
isDisabled?: boolean;
|
|
89
|
-
/**
|
|
90
|
-
* Is loader displayed inside the trigger part
|
|
91
|
-
*/
|
|
92
|
-
isLoading?: boolean;
|
|
93
|
-
/**
|
|
94
|
-
* A hint to the user of what can be entered in the control
|
|
95
|
-
*/
|
|
96
|
-
placeholder?: string;
|
|
97
|
-
/**
|
|
98
|
-
* Size
|
|
99
|
-
*/
|
|
100
|
-
size?: SelectSize;
|
|
101
|
-
/**
|
|
102
|
-
* Appearance mode
|
|
103
|
-
*/
|
|
104
|
-
mode?: SelectMode;
|
|
105
|
-
/**
|
|
106
|
-
* Appearance theme
|
|
107
|
-
*/
|
|
108
|
-
theme?: Theme;
|
|
109
|
-
/**
|
|
110
|
-
* Error state flag or `React.ReactNode` (use with forms)
|
|
111
|
-
*/
|
|
112
|
-
error?: boolean | React.ReactNode;
|
|
113
|
-
/**
|
|
114
|
-
* If `true`, there will be reserved a space for a 1-line error message. Subsequent lines will be placed below normally.
|
|
115
|
-
* If `false`, there will be no reservation.
|
|
116
|
-
*/
|
|
117
|
-
reserveErrorLine?: boolean;
|
|
118
|
-
/**
|
|
119
|
-
* Label element (use with forms)
|
|
120
|
-
*/
|
|
121
|
-
label?: React.ReactNode;
|
|
122
|
-
/**
|
|
123
|
-
* If `true`, label will be bold
|
|
124
|
-
*/
|
|
125
|
-
boldLabel?: boolean;
|
|
126
|
-
/**
|
|
127
|
-
* Placement of dropdown element
|
|
128
|
-
*/
|
|
129
|
-
placement?: Placement;
|
|
130
|
-
/**
|
|
131
|
-
* Note element at the bottom (use with forms)
|
|
132
|
-
*/
|
|
133
|
-
note?: React.ReactNode;
|
|
134
|
-
/**
|
|
135
|
-
* Text to display when there are no options
|
|
136
|
-
*/
|
|
137
|
-
noOptionsMessage?: NoOptionsMessage;
|
|
138
|
-
/**
|
|
139
|
-
* Input name attribute
|
|
140
|
-
*/
|
|
141
|
-
name?: string;
|
|
142
|
-
/**
|
|
143
|
-
* Maximum number of fully visible items in the dropdown list.
|
|
144
|
-
* For large lists, `n + 0.5` items will be visible at a time.
|
|
145
|
-
* If the maximum number of items in a list is exactly `n + 1`, all
|
|
146
|
-
* items will be shown instead (to avoid creating a scroll for half an item only).
|
|
147
|
-
*/
|
|
148
|
-
maxVisibleItems?: number;
|
|
149
|
-
};
|
|
150
|
-
export declare type MultiselectProps = {
|
|
151
|
-
/**
|
|
152
|
-
* Value of the multiselect (array of selected options)
|
|
153
|
-
*/
|
|
154
|
-
value?: SelectOption[] | null;
|
|
155
|
-
/**
|
|
156
|
-
* Change value callback. `value => ...`. Pass `[]` on clear.
|
|
157
|
-
*/
|
|
158
|
-
onChange?: (newValue: SelectOption[]) => void;
|
|
159
|
-
/**
|
|
160
|
-
* Display tags in single line with "+N" counter
|
|
161
|
-
*/
|
|
162
|
-
isSingleLine?: boolean;
|
|
163
|
-
} & Omit<SelectProps, 'value' | 'onChange' | 'isSearchable'>;
|
|
164
|
-
export declare type TriggerFuncProps = {
|
|
165
|
-
selectedLabel?: string;
|
|
166
|
-
selectedValue?: Key;
|
|
167
|
-
placeholder?: string;
|
|
168
|
-
hovered: boolean;
|
|
169
|
-
focused: boolean;
|
|
170
|
-
};
|
|
171
|
-
export declare type NativeSelectProps = {
|
|
172
|
-
options?: (NativeSelectOption | NativeSelectOptionsGroup)[];
|
|
173
|
-
size?: SelectSize;
|
|
174
|
-
theme?: Theme;
|
|
175
|
-
className?: string;
|
|
176
|
-
id?: string;
|
|
177
|
-
style?: React.CSSProperties;
|
|
178
|
-
value?: NativeSelectOption | null;
|
|
179
|
-
onChange?: (newValue: NativeSelectOption | null) => void;
|
|
180
|
-
placeholder?: string;
|
|
181
|
-
isLoading?: boolean;
|
|
182
|
-
isDisabled?: boolean;
|
|
183
|
-
isClearable?: boolean;
|
|
184
|
-
trigger?: (props: TriggerFuncProps) => React.ReactNode;
|
|
185
|
-
label?: React.ReactNode;
|
|
186
|
-
note?: React.ReactNode;
|
|
187
|
-
error?: boolean | React.ReactNode;
|
|
188
|
-
/**
|
|
189
|
-
* If `true`, there will be reserved a space for a 1-line error message. Subsequent lines will be placed below normally.
|
|
190
|
-
* If `false`, there will be no reservation.
|
|
191
|
-
*/
|
|
192
|
-
reserveErrorLine?: boolean;
|
|
193
|
-
noOptionsMessage?: NoOptionsMessage;
|
|
194
|
-
name?: string;
|
|
195
|
-
boldLabel?: boolean;
|
|
196
|
-
};
|
|
197
|
-
export declare type InnerSingleComponentProps = Omit<SelectProps, 'isSearchable'>;
|
package/lib/utils.d.ts
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import type { SelectOptionOrGroup, SelectOptionsGroup, NoOptionsMessage, SelectSize } from './types';
|
|
3
|
+
import { Groups, Index, SelectOption } from './types';
|
|
4
|
+
export declare const getTextFromNodes: (node: React.ReactNode, depth?: number) => string;
|
|
5
|
+
export declare function shouldOpenSelect(key: string, isTriggerTarget?: boolean): boolean;
|
|
6
|
+
export declare function getEmptyMessage(isLoading: boolean, isNothingFound: boolean, noOptionsMessage: NoOptionsMessage): string;
|
|
7
|
+
export declare function escapeRegex(str: string): string;
|
|
8
|
+
export declare function convertToOptionGroupsIfNeeded(optionsOrGroups?: SelectOptionOrGroup[]): SelectOptionsGroup[];
|
|
9
|
+
export declare const calculateMaxHeight: (size: SelectSize) => number;
|
|
10
|
+
export declare function getOptionValue(option: SelectOption): string;
|
|
11
|
+
export declare const OptionGroupTypes: {
|
|
12
|
+
HEADER: string;
|
|
13
|
+
OPTION: string;
|
|
14
|
+
DIVIDER: string;
|
|
15
|
+
};
|
|
16
|
+
export declare const getDefaultCursorIndex: (groups: Groups) => Index;
|
|
17
|
+
export declare const getPlainOptionsFromGroups: (groups: Groups) => any[];
|
|
18
|
+
export declare function isGroupsEmpty(groups: Groups): boolean;
|
|
19
|
+
export declare function useStrongMemo<T>(callback: () => T, deps: unknown[]): T;
|
|
20
|
+
export declare function getMovedCursorIndex(groups: Groups, currentCursorIndex: Index, isDownDirection: boolean): Index;
|
|
21
|
+
export declare const isIndexMatchCursor: (cursorIndex: Index, index: Index) => boolean;
|
|
22
|
+
export declare const withoutGroupsLabel: (groups: Groups) => boolean;
|
package/lib/utils.js
ADDED
|
@@ -0,0 +1,199 @@
|
|
|
1
|
+
import React, { useRef } from 'react';
|
|
2
|
+
import { ARROW_DOWN, ARROW_UP, SPACE, ENTER } from './key-codes.js';
|
|
3
|
+
const DEFAULT_NO_OPTIONS_MESSAGES = {
|
|
4
|
+
noOptions: 'No options',
|
|
5
|
+
nothingFound: 'Nothing found',
|
|
6
|
+
loading: 'Loading...'
|
|
7
|
+
};
|
|
8
|
+
const MAX_VISIBLE_ITEMS = 5;
|
|
9
|
+
const ITEM_HEIGHT_BY_SIZE = {
|
|
10
|
+
s: 32,
|
|
11
|
+
m: 40,
|
|
12
|
+
l: 52
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
const getTextFromNodes = function (node) {
|
|
16
|
+
let depth = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0;
|
|
17
|
+
|
|
18
|
+
if (typeof node === 'string' || typeof node === 'number') {
|
|
19
|
+
return node.toString();
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
if (depth > 15) {
|
|
23
|
+
console.warn('Max depth reached while getting text from nodes');
|
|
24
|
+
return '';
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
if (Array.isArray(node)) {
|
|
28
|
+
return node.map(n => getTextFromNodes(n, depth + 1)).join('');
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
if ( /*#__PURE__*/React.isValidElement(node) && node?.type?.toString()?.toLowerCase() !== 'svg') {
|
|
32
|
+
return getTextFromNodes(node.props.children, depth + 1);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
return '';
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
const isOptionsGroup = optionOrGroup => typeof optionOrGroup.options !== 'undefined';
|
|
39
|
+
|
|
40
|
+
function shouldOpenSelect(key) {
|
|
41
|
+
let isTriggerTarget = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true;
|
|
42
|
+
return key === ARROW_DOWN || key === ARROW_UP || (key === SPACE || key === ENTER) && isTriggerTarget;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
function isString(s) {
|
|
46
|
+
return Object.prototype.toString.call(s) === '[object String]';
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
function getEmptyMessage(isLoading, isNothingFound, noOptionsMessage) {
|
|
50
|
+
const {
|
|
51
|
+
noOptions,
|
|
52
|
+
nothingFound,
|
|
53
|
+
loading
|
|
54
|
+
} = isString(noOptionsMessage) ? { ...DEFAULT_NO_OPTIONS_MESSAGES,
|
|
55
|
+
noOptions: noOptionsMessage
|
|
56
|
+
} : { ...DEFAULT_NO_OPTIONS_MESSAGES,
|
|
57
|
+
...noOptionsMessage
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
if (isLoading) {
|
|
61
|
+
return loading;
|
|
62
|
+
} else if (isNothingFound) {
|
|
63
|
+
return nothingFound;
|
|
64
|
+
} else {
|
|
65
|
+
return noOptions;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
function escapeRegex(str) {
|
|
70
|
+
return str.replace(/[\-\[\]\/{}()\*+?.\\^$|]/g, '\\$&');
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
function convertToOptionGroupsIfNeeded() {
|
|
74
|
+
let optionsOrGroups = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : [];
|
|
75
|
+
const newOptions = [];
|
|
76
|
+
let topLevelOptions = [];
|
|
77
|
+
optionsOrGroups.forEach(optionOrGroup => {
|
|
78
|
+
if (isOptionsGroup(optionOrGroup)) {
|
|
79
|
+
if (topLevelOptions.length) {
|
|
80
|
+
newOptions.push({
|
|
81
|
+
options: topLevelOptions
|
|
82
|
+
});
|
|
83
|
+
topLevelOptions = [];
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
newOptions.push(optionOrGroup);
|
|
87
|
+
} else {
|
|
88
|
+
topLevelOptions.push(optionOrGroup);
|
|
89
|
+
}
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
if (topLevelOptions.length) {
|
|
93
|
+
newOptions.push({
|
|
94
|
+
options: topLevelOptions
|
|
95
|
+
});
|
|
96
|
+
topLevelOptions = [];
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
return newOptions;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
const calculateMaxHeight = size => {
|
|
103
|
+
const itemHeight = ITEM_HEIGHT_BY_SIZE[size]; // half of item added to show that there is more items even if scroll bar hidden
|
|
104
|
+
|
|
105
|
+
return (Math.ceil(MAX_VISIBLE_ITEMS) + 0.5) * itemHeight;
|
|
106
|
+
};
|
|
107
|
+
|
|
108
|
+
function getOptionValue(option) {
|
|
109
|
+
return typeof option.value === 'string' ? option.value : getTextFromNodes(option.label);
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
const OptionGroupTypes = {
|
|
113
|
+
HEADER: 'header',
|
|
114
|
+
OPTION: 'option',
|
|
115
|
+
DIVIDER: 'divider'
|
|
116
|
+
};
|
|
117
|
+
|
|
118
|
+
const getDefaultCursorIndex = groups => {
|
|
119
|
+
if (groups.length === 0) {
|
|
120
|
+
return null;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
const firstNonEmptyGroupIndex = groups.findIndex(group => group.options && group.options.length > 0);
|
|
124
|
+
|
|
125
|
+
if (firstNonEmptyGroupIndex === -1) {
|
|
126
|
+
return null;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
return [firstNonEmptyGroupIndex, 0];
|
|
130
|
+
};
|
|
131
|
+
|
|
132
|
+
function optionsNotEmpty(options) {
|
|
133
|
+
return options && options.length > 0;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
const getPlainOptionsFromGroups = groups => groups.reduce( // eslint-disable-next-line no-shadow
|
|
137
|
+
(acc, group, i) => acc.concat([optionsNotEmpty(group.options) && i !== 0 && !group.label && {
|
|
138
|
+
type: OptionGroupTypes.DIVIDER
|
|
139
|
+
}, optionsNotEmpty(group.options) && group.label && {
|
|
140
|
+
type: OptionGroupTypes.HEADER,
|
|
141
|
+
label: group.label
|
|
142
|
+
}, ...group.options.map((option, j) => ({ ...option,
|
|
143
|
+
index: [i, j],
|
|
144
|
+
type: OptionGroupTypes.OPTION
|
|
145
|
+
}))].filter(e => e)), []);
|
|
146
|
+
|
|
147
|
+
function isGroupsEmpty(groups) {
|
|
148
|
+
return groups.length === 0 || groups.every(g => !g.options || g.options.length === 0);
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
function useStrongMemo(callback, deps) {
|
|
152
|
+
const prevDeps = useRef([]);
|
|
153
|
+
const memoResult = useRef(null);
|
|
154
|
+
|
|
155
|
+
if (deps.length !== prevDeps.current.length || !prevDeps.current.every((dep, i) => dep === deps[i])) {
|
|
156
|
+
prevDeps.current = [...deps];
|
|
157
|
+
memoResult.current = callback();
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
return memoResult.current;
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
function nextIndex(index, isDownDirection) {
|
|
164
|
+
return isDownDirection ? index + 1 : index - 1;
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
function isIndexOutOfRange(index, len) {
|
|
168
|
+
return index < 0 || index >= len;
|
|
169
|
+
} // eslint-disable-next-line complexity
|
|
170
|
+
|
|
171
|
+
|
|
172
|
+
function getMovedCursorIndex(groups, currentCursorIndex, isDownDirection) {
|
|
173
|
+
if (isGroupsEmpty(groups)) return currentCursorIndex;
|
|
174
|
+
const [grpIndex, optIndex] = currentCursorIndex;
|
|
175
|
+
const optLenByGroup = groups.map(g => g.options ? g.options.length : 0);
|
|
176
|
+
let newGrpIndex = grpIndex;
|
|
177
|
+
let newOptIndex = nextIndex(optIndex, isDownDirection);
|
|
178
|
+
|
|
179
|
+
while (isIndexOutOfRange(newOptIndex, optLenByGroup[newGrpIndex]) || isIndexOutOfRange(newGrpIndex, groups.length)) {
|
|
180
|
+
newGrpIndex = nextIndex(newGrpIndex, isDownDirection);
|
|
181
|
+
|
|
182
|
+
if (isIndexOutOfRange(newGrpIndex, groups.length)) {
|
|
183
|
+
newGrpIndex = isDownDirection ? 0 : groups.length - 1;
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
newOptIndex = isDownDirection ? 0 : optLenByGroup[newGrpIndex] - 1;
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
return [newGrpIndex, newOptIndex];
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
const isIndexMatchCursor = (cursorIndex, index) => {
|
|
193
|
+
if (cursorIndex === null) return false;
|
|
194
|
+
return index[0] === cursorIndex[0] && index[1] === cursorIndex[1];
|
|
195
|
+
};
|
|
196
|
+
|
|
197
|
+
const withoutGroupsLabel = groups => groups.every(g => !g.label);
|
|
198
|
+
|
|
199
|
+
export { OptionGroupTypes, calculateMaxHeight, convertToOptionGroupsIfNeeded, escapeRegex, getDefaultCursorIndex, getEmptyMessage, getMovedCursorIndex, getOptionValue, getPlainOptionsFromGroups, getTextFromNodes, isGroupsEmpty, isIndexMatchCursor, shouldOpenSelect, useStrongMemo, withoutGroupsLabel };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rescui/select",
|
|
3
|
-
"version": "0.15.
|
|
3
|
+
"version": "0.15.2",
|
|
4
4
|
"description": "",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"author": "JetBrains",
|
|
@@ -16,13 +16,13 @@
|
|
|
16
16
|
},
|
|
17
17
|
"dependencies": {
|
|
18
18
|
"@babel/runtime-corejs3": "^7.26.0",
|
|
19
|
-
"@rescui/dropdown": "0.9.
|
|
20
|
-
"@rescui/form-field": "0.1.
|
|
21
|
-
"@rescui/
|
|
22
|
-
"@rescui/
|
|
19
|
+
"@rescui/dropdown": "^0.9.6",
|
|
20
|
+
"@rescui/form-field": "^0.1.2",
|
|
21
|
+
"@rescui/menu": "^0.13.4",
|
|
22
|
+
"@rescui/tag": "^0.13.6",
|
|
23
|
+
"@rescui/use-resize-observer": "^0.3.0",
|
|
23
24
|
"classnames": "^2.2.6",
|
|
24
|
-
"
|
|
25
|
-
"scroll-into-view-if-needed": "3.1.0"
|
|
25
|
+
"scroll-into-view-if-needed": "2.2.20"
|
|
26
26
|
},
|
|
27
27
|
"peerDependencies": {
|
|
28
28
|
"@rescui/ui-contexts": "^0.6.0",
|
|
@@ -30,10 +30,10 @@
|
|
|
30
30
|
"react": ">=16.8.0 <20"
|
|
31
31
|
},
|
|
32
32
|
"devDependencies": {
|
|
33
|
-
"@rescui/colors": "0.3.
|
|
34
|
-
"@rescui/scripts": "0.5.1",
|
|
35
|
-
"@rescui/typography": "0.
|
|
36
|
-
"@rescui/visual-regression": "0.1.4",
|
|
33
|
+
"@rescui/colors": "^0.3.0",
|
|
34
|
+
"@rescui/scripts": "^0.5.1",
|
|
35
|
+
"@rescui/typography": "^0.26.0",
|
|
36
|
+
"@rescui/visual-regression": "^0.1.4",
|
|
37
37
|
"sniffr": "^1.2.0"
|
|
38
38
|
},
|
|
39
39
|
"scripts": {
|
|
@@ -41,5 +41,5 @@
|
|
|
41
41
|
"build-pcss-api": "rescui-scripts build-pcss-api --file public-api.p.css"
|
|
42
42
|
},
|
|
43
43
|
"nx": {},
|
|
44
|
-
"gitHead": "
|
|
44
|
+
"gitHead": "faa7a838502974c16bdf773ab001002d1b8dcca8"
|
|
45
45
|
}
|
package/lib/constants.d.ts
DELETED
package/lib/constants.js
DELETED
package/lib/hooks/use-a11y.d.ts
DELETED
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
import React from 'react';
|
|
2
|
-
export declare type UseA11yArgs = {
|
|
3
|
-
prefix?: string;
|
|
4
|
-
baseId?: string;
|
|
5
|
-
description?: React.ReactNode;
|
|
6
|
-
error?: React.ReactNode;
|
|
7
|
-
label?: React.ReactNode;
|
|
8
|
-
fieldRef?: React.RefObject<HTMLElement>;
|
|
9
|
-
};
|
|
10
|
-
export declare const useA11y: ({ baseId: baseIdFromProps, prefix, description, error, label, fieldRef }: UseA11yArgs) => {
|
|
11
|
-
baseId: string;
|
|
12
|
-
fieldProps: {
|
|
13
|
-
'aria-invalid': boolean;
|
|
14
|
-
'aria-describedby': string;
|
|
15
|
-
'aria-labelledby': string;
|
|
16
|
-
id: string;
|
|
17
|
-
};
|
|
18
|
-
descriptionProps: {
|
|
19
|
-
id: string;
|
|
20
|
-
};
|
|
21
|
-
errorMessageProps: {
|
|
22
|
-
id: string;
|
|
23
|
-
};
|
|
24
|
-
labelProps: {
|
|
25
|
-
id: string;
|
|
26
|
-
htmlFor: string;
|
|
27
|
-
onClick: () => void;
|
|
28
|
-
};
|
|
29
|
-
};
|
package/lib/hooks/use-a11y.js
DELETED
|
@@ -1,53 +0,0 @@
|
|
|
1
|
-
import { useBackwardCompatibleId } from './use-backward-compatible-id.js'; // eslint-disable-next-line complexity
|
|
2
|
-
|
|
3
|
-
const useA11y = _ref => {
|
|
4
|
-
let {
|
|
5
|
-
baseId: baseIdFromProps,
|
|
6
|
-
prefix = '',
|
|
7
|
-
description,
|
|
8
|
-
error,
|
|
9
|
-
label,
|
|
10
|
-
fieldRef
|
|
11
|
-
} = _ref;
|
|
12
|
-
const uniqueId = `${prefix ? `${prefix}-` : ''}${useBackwardCompatibleId()}`;
|
|
13
|
-
const baseId = baseIdFromProps ?? uniqueId;
|
|
14
|
-
const fieldId = `${baseId}-field`;
|
|
15
|
-
const descriptionId = description ? `${baseId}-description` : undefined;
|
|
16
|
-
const errorId = error ? `${baseId}-error` : undefined;
|
|
17
|
-
const labelId = label ? `${baseId}-label` : undefined;
|
|
18
|
-
const describedBy = [descriptionId, errorId].filter(Boolean).join(' ') || undefined;
|
|
19
|
-
const fieldProps = {
|
|
20
|
-
'aria-invalid': Boolean(error),
|
|
21
|
-
'aria-describedby': describedBy,
|
|
22
|
-
'aria-labelledby': labelId,
|
|
23
|
-
id: fieldId
|
|
24
|
-
};
|
|
25
|
-
const errorMessageProps = {
|
|
26
|
-
id: errorId
|
|
27
|
-
};
|
|
28
|
-
const descriptionProps = {
|
|
29
|
-
id: descriptionId
|
|
30
|
-
};
|
|
31
|
-
const labelProps = {
|
|
32
|
-
id: labelId,
|
|
33
|
-
htmlFor: fieldId,
|
|
34
|
-
onClick: () => {
|
|
35
|
-
if (fieldRef !== null && fieldRef !== void 0 && fieldRef.current) {
|
|
36
|
-
fieldRef.current.focus();
|
|
37
|
-
} else {
|
|
38
|
-
var _document$getElementB;
|
|
39
|
-
|
|
40
|
-
(_document$getElementB = document.getElementById(fieldId)) === null || _document$getElementB === void 0 || _document$getElementB.focus();
|
|
41
|
-
}
|
|
42
|
-
}
|
|
43
|
-
};
|
|
44
|
-
return {
|
|
45
|
-
baseId,
|
|
46
|
-
fieldProps,
|
|
47
|
-
descriptionProps,
|
|
48
|
-
errorMessageProps,
|
|
49
|
-
labelProps
|
|
50
|
-
};
|
|
51
|
-
};
|
|
52
|
-
|
|
53
|
-
export { useA11y };
|
package/lib/hooks/use-focus.d.ts
DELETED
package/lib/hooks/use-focus.js
DELETED
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
import { useState } from 'react';
|
|
2
|
-
|
|
3
|
-
const useFocus = _ref => {
|
|
4
|
-
let {
|
|
5
|
-
isDisabled
|
|
6
|
-
} = _ref;
|
|
7
|
-
const [isFocused, setIsFocused] = useState(false);
|
|
8
|
-
return {
|
|
9
|
-
isFocused,
|
|
10
|
-
focusProps: {
|
|
11
|
-
onFocus: () => setIsFocused(!isDisabled),
|
|
12
|
-
onBlur: () => setIsFocused(false)
|
|
13
|
-
}
|
|
14
|
-
};
|
|
15
|
-
};
|
|
16
|
-
|
|
17
|
-
export { useFocus };
|
package/lib/hooks/use-hover.d.ts
DELETED
package/lib/hooks/use-hover.js
DELETED
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
import { useState } from 'react';
|
|
2
|
-
|
|
3
|
-
const useHover = _ref => {
|
|
4
|
-
let {
|
|
5
|
-
isDisabled
|
|
6
|
-
} = _ref;
|
|
7
|
-
const [isHovered, setIsHovered] = useState(false);
|
|
8
|
-
return {
|
|
9
|
-
isHovered,
|
|
10
|
-
hoverProps: {
|
|
11
|
-
onMouseEnter: () => setIsHovered(!isDisabled),
|
|
12
|
-
onMouseLeave: () => setIsHovered(false)
|
|
13
|
-
}
|
|
14
|
-
};
|
|
15
|
-
};
|
|
16
|
-
|
|
17
|
-
export { useHover };
|
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
import { useState } from 'react';
|
|
2
|
-
|
|
3
|
-
const useLabelFocus = () => {
|
|
4
|
-
const [isFocusedByLabel, setIsFocusedByLabel] = useState(false);
|
|
5
|
-
const triggerFocusProps = {
|
|
6
|
-
onBlur: () => {
|
|
7
|
-
setIsFocusedByLabel(false);
|
|
8
|
-
}
|
|
9
|
-
};
|
|
10
|
-
const labelClickProps = {
|
|
11
|
-
onClick: () => {
|
|
12
|
-
setIsFocusedByLabel(true);
|
|
13
|
-
}
|
|
14
|
-
};
|
|
15
|
-
return {
|
|
16
|
-
isFocusedByLabel,
|
|
17
|
-
triggerFocusProps,
|
|
18
|
-
labelClickProps
|
|
19
|
-
};
|
|
20
|
-
};
|
|
21
|
-
|
|
22
|
-
export { useLabelFocus };
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
import type { SelectOption } from '../types';
|
|
2
|
-
export declare type UseMultiHandlersArgs = {
|
|
3
|
-
selectedItems: SelectOption[];
|
|
4
|
-
onChange: (value: SelectOption[]) => void;
|
|
5
|
-
};
|
|
6
|
-
export declare const useMultiHandlers: ({ selectedItems, onChange }: UseMultiHandlersArgs) => {
|
|
7
|
-
selectedMap: Map<import("../types").Key, SelectOption>;
|
|
8
|
-
addItem: (item: SelectOption) => void;
|
|
9
|
-
removeItem: (item: SelectOption) => void;
|
|
10
|
-
removeAllItems: () => void;
|
|
11
|
-
};
|