@rescui/select 0.15.1 → 0.16.0
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 +8 -14
- package/lib/common-prop-types.js +4 -3
- package/lib/constants.d.ts +6 -0
- package/lib/constants.js +7 -0
- package/lib/hooks/use-a11y.d.ts +30 -0
- package/lib/hooks/use-a11y.js +56 -0
- package/lib/hooks/use-actual-size-from-css.d.ts +10 -0
- package/lib/hooks/use-actual-size-from-css.js +27 -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 +9 -0
- package/lib/hooks/use-label-focus.js +22 -0
- package/lib/hooks/use-multi-handlers.d.ts +11 -0
- package/lib/hooks/use-multi-handlers.js +44 -0
- package/lib/hooks/use-options.d.ts +14 -0
- package/lib/hooks/use-options.js +90 -0
- package/lib/hooks/use-primary-contrast-css-var-transfer.d.ts +11 -0
- package/lib/hooks/use-primary-contrast-css-var-transfer.js +29 -0
- package/lib/hooks/use-safe-id.d.ts +6 -0
- package/lib/hooks/use-safe-id.js +15 -0
- package/lib/index.css +713 -304
- package/lib/index.d.ts +4 -6
- package/lib/index.js +3 -3
- package/lib/multiselect.d.ts +3 -0
- package/lib/multiselect.js +308 -0
- package/lib/native-select.d.ts +4 -0
- package/lib/native-select.js +208 -0
- package/lib/parts/foldable.js +5 -7
- package/lib/parts/form-trigger-wrapper.d.ts +7 -7
- package/lib/parts/form-trigger-wrapper.js +16 -34
- package/lib/parts/hidden-select.d.ts +13 -0
- package/lib/parts/hidden-select.js +45 -0
- package/lib/parts/icons.d.ts +17 -0
- package/lib/parts/icons.js +69 -0
- package/lib/parts/list-box.d.ts +13 -0
- package/lib/parts/list-box.js +120 -0
- package/lib/parts/multi-trigger.d.ts +12 -0
- package/lib/parts/multi-trigger.js +70 -0
- package/lib/parts/native-select-options-with-groups.d.ts +8 -0
- package/lib/parts/native-select-options-with-groups.js +76 -0
- package/lib/parts/popup-content.d.ts +20 -0
- package/lib/parts/popup-content.js +68 -0
- package/lib/public-api.p.css +543 -307
- package/lib/public-api.pcss +543 -307
- package/lib/select-basic.d.ts +3 -0
- package/lib/select-basic.js +204 -0
- package/lib/select-searchable.d.ts +3 -0
- package/lib/select-searchable.js +245 -0
- package/lib/select.d.ts +27 -91
- package/lib/select.js +51 -351
- package/lib/styles/common.p.module.css.js +32 -0
- package/lib/styles/form-trigger.p.module.css.js +15 -0
- package/lib/styles/list-box.p.module.css.js +16 -0
- package/lib/types.d.ts +172 -4
- package/lib/utils/calculate-max-height-by-items.d.ts +13 -0
- package/lib/utils/calculate-max-height-by-items.js +22 -0
- package/lib/utils/get-empty-message.d.ts +6 -0
- package/lib/utils/get-empty-message.js +32 -0
- package/lib/utils/get-option-value.d.ts +2 -0
- package/lib/utils/get-option-value.js +11 -0
- package/lib/utils/get-real-items-cnt.d.ts +2 -0
- package/lib/utils/get-real-items-cnt.js +19 -0
- package/lib/utils/get-text-from-nodes.d.ts +2 -0
- package/lib/utils/get-text-from-nodes.js +26 -0
- package/lib/utils/is-option-a-group.d.ts +2 -0
- package/lib/utils/is-option-a-group.js +5 -0
- 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 +19 -0
- package/lib/utils/merge-props.js +104 -0
- package/lib/utils/throttle.d.ts +1 -0
- package/package.json +8 -8
- package/lib/key-codes.d.ts +0 -7
- package/lib/key-codes.js +0 -8
- package/lib/parts/common-select.p.module.css.js +0 -15
- package/lib/parts/form-trigger.p.module.css.js +0 -15
- package/lib/parts/multiselect.d.ts +0 -86
- package/lib/parts/multiselect.js +0 -455
- package/lib/parts/native-select.d.ts +0 -36
- package/lib/parts/native-select.js +0 -257
- package/lib/parts/native-select.p.module.css.js +0 -9
- package/lib/parts/throttle.d.ts +0 -1
- package/lib/parts/trigger.d.ts +0 -37
- package/lib/parts/trigger.js +0 -255
- package/lib/parts/trigger.p.module.css.js +0 -31
- package/lib/parts/use-backward-compatible-id.d.ts +0 -4
- package/lib/parts/use-backward-compatible-id.js +0 -14
- package/lib/parts/use-observable-force-rerender.d.ts +0 -2
- package/lib/parts/use-observable-force-rerender.js +0 -16
- package/lib/utils.d.ts +0 -22
- package/lib/utils.js +0 -201
- /package/lib/{parts → utils}/throttle.js +0 -0
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
var styles = {
|
|
2
|
-
"icon": "
|
|
3
|
-
"sizeXS": "
|
|
4
|
-
"sizeS": "
|
|
5
|
-
"sizeM": "
|
|
6
|
-
"sizeL": "
|
|
7
|
-
"light": "
|
|
8
|
-
"dark": "
|
|
9
|
-
"allVariants": "
|
|
10
|
-
"variant16": "
|
|
11
|
-
"variant20": "
|
|
12
|
-
"variant24": "
|
|
13
|
-
"variant28": "
|
|
2
|
+
"icon": "_icon_q2bqnl_4",
|
|
3
|
+
"sizeXS": "_sizeXS_q2bqnl_14",
|
|
4
|
+
"sizeS": "_sizeS_q2bqnl_18",
|
|
5
|
+
"sizeM": "_sizeM_q2bqnl_22",
|
|
6
|
+
"sizeL": "_sizeL_q2bqnl_26",
|
|
7
|
+
"light": "_light_q2bqnl_30",
|
|
8
|
+
"dark": "_dark_q2bqnl_34",
|
|
9
|
+
"allVariants": "_allVariants_q2bqnl_48",
|
|
10
|
+
"variant16": "_variant16_q2bqnl_53",
|
|
11
|
+
"variant20": "_variant20_q2bqnl_54",
|
|
12
|
+
"variant24": "_variant24_q2bqnl_55",
|
|
13
|
+
"variant28": "_variant28_q2bqnl_58"
|
|
14
14
|
};
|
|
15
15
|
export { styles as default };
|
|
@@ -1,18 +1,20 @@
|
|
|
1
1
|
import PropTypes from 'prop-types';
|
|
2
|
+
import type { NoOptionsMessage, NoOptionsMessageConfig } from './types';
|
|
3
|
+
export declare const keyType: PropTypes.Requireable<string | number>;
|
|
2
4
|
export declare const optionType: PropTypes.Requireable<PropTypes.InferProps<{
|
|
3
5
|
label: PropTypes.Validator<PropTypes.ReactNodeLike>;
|
|
4
|
-
value: PropTypes.Requireable<string>;
|
|
6
|
+
value: PropTypes.Requireable<string | number>;
|
|
5
7
|
}>>;
|
|
6
8
|
export declare const optionsGroupType: PropTypes.Requireable<PropTypes.InferProps<{
|
|
7
9
|
label: PropTypes.Requireable<PropTypes.ReactNodeLike>;
|
|
8
10
|
options: PropTypes.Requireable<PropTypes.InferProps<{
|
|
9
11
|
label: PropTypes.Validator<PropTypes.ReactNodeLike>;
|
|
10
|
-
value: PropTypes.Requireable<string>;
|
|
12
|
+
value: PropTypes.Requireable<string | number>;
|
|
11
13
|
}>[]>;
|
|
12
14
|
}>>;
|
|
13
15
|
export declare const nativeOptionType: PropTypes.Requireable<PropTypes.InferProps<{
|
|
14
16
|
label: PropTypes.Validator<string>;
|
|
15
|
-
value: PropTypes.Requireable<string>;
|
|
17
|
+
value: PropTypes.Requireable<string | number>;
|
|
16
18
|
disabled: PropTypes.Requireable<boolean>;
|
|
17
19
|
}>>;
|
|
18
20
|
export declare const nativeOptionsGroupType: PropTypes.Requireable<PropTypes.InferProps<{
|
|
@@ -20,16 +22,8 @@ export declare const nativeOptionsGroupType: PropTypes.Requireable<PropTypes.Inf
|
|
|
20
22
|
disabled: PropTypes.Requireable<boolean>;
|
|
21
23
|
options: PropTypes.Requireable<PropTypes.InferProps<{
|
|
22
24
|
label: PropTypes.Validator<PropTypes.ReactNodeLike>;
|
|
23
|
-
value: PropTypes.Requireable<string>;
|
|
25
|
+
value: PropTypes.Requireable<string | number>;
|
|
24
26
|
}>[]>;
|
|
25
27
|
}>>;
|
|
26
|
-
export declare const noOptionsMessageConfigType: PropTypes.
|
|
27
|
-
|
|
28
|
-
nothingFound: PropTypes.Requireable<string>;
|
|
29
|
-
loading: PropTypes.Requireable<string>;
|
|
30
|
-
}>>;
|
|
31
|
-
export declare const noOptionsMessageType: PropTypes.Requireable<string | PropTypes.InferProps<{
|
|
32
|
-
noOptions: PropTypes.Validator<string>;
|
|
33
|
-
nothingFound: PropTypes.Requireable<string>;
|
|
34
|
-
loading: PropTypes.Requireable<string>;
|
|
35
|
-
}>>;
|
|
28
|
+
export declare const noOptionsMessageConfigType: PropTypes.Validator<NoOptionsMessageConfig>;
|
|
29
|
+
export declare const noOptionsMessageType: PropTypes.Validator<NoOptionsMessage>;
|
package/lib/common-prop-types.js
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import PropTypes from 'prop-types';
|
|
2
|
+
const keyType = PropTypes.oneOfType([PropTypes.string, PropTypes.number]);
|
|
2
3
|
const optionType = PropTypes.shape({
|
|
3
4
|
label: PropTypes.node.isRequired,
|
|
4
|
-
value:
|
|
5
|
+
value: keyType
|
|
5
6
|
});
|
|
6
7
|
const optionsGroupType = PropTypes.shape({
|
|
7
8
|
label: PropTypes.node,
|
|
@@ -9,7 +10,7 @@ const optionsGroupType = PropTypes.shape({
|
|
|
9
10
|
});
|
|
10
11
|
const nativeOptionType = PropTypes.shape({
|
|
11
12
|
label: PropTypes.string.isRequired,
|
|
12
|
-
value:
|
|
13
|
+
value: keyType,
|
|
13
14
|
disabled: PropTypes.bool
|
|
14
15
|
});
|
|
15
16
|
const nativeOptionsGroupType = PropTypes.shape({
|
|
@@ -23,4 +24,4 @@ const noOptionsMessageConfigType = PropTypes.shape({
|
|
|
23
24
|
loading: PropTypes.string
|
|
24
25
|
});
|
|
25
26
|
const noOptionsMessageType = PropTypes.oneOfType([PropTypes.string, noOptionsMessageConfigType]);
|
|
26
|
-
export { nativeOptionType, nativeOptionsGroupType, noOptionsMessageConfigType, noOptionsMessageType, optionType, optionsGroupType };
|
|
27
|
+
export { keyType, nativeOptionType, nativeOptionsGroupType, noOptionsMessageConfigType, noOptionsMessageType, optionType, optionsGroupType };
|
package/lib/constants.js
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
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
|
+
isDisabled?: boolean;
|
|
10
|
+
};
|
|
11
|
+
export declare const useA11y: ({ baseId: baseIdFromProps, prefix, description, error, label, fieldRef, isDisabled }: UseA11yArgs) => {
|
|
12
|
+
baseId: string;
|
|
13
|
+
fieldProps: {
|
|
14
|
+
'aria-invalid': boolean;
|
|
15
|
+
'aria-describedby': string;
|
|
16
|
+
'aria-labelledby': string;
|
|
17
|
+
id: string;
|
|
18
|
+
};
|
|
19
|
+
descriptionProps: {
|
|
20
|
+
id: string;
|
|
21
|
+
};
|
|
22
|
+
errorMessageProps: {
|
|
23
|
+
id: string;
|
|
24
|
+
};
|
|
25
|
+
labelProps: {
|
|
26
|
+
id: string;
|
|
27
|
+
htmlFor: string;
|
|
28
|
+
onClick: () => void;
|
|
29
|
+
};
|
|
30
|
+
};
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { useSafeId } from './use-safe-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
|
+
isDisabled = false
|
|
12
|
+
} = _ref;
|
|
13
|
+
const uniqueId = `${prefix ? `${prefix}-` : ''}${useSafeId()}`;
|
|
14
|
+
const baseId = baseIdFromProps ?? uniqueId;
|
|
15
|
+
const fieldId = `${baseId}-field`;
|
|
16
|
+
const descriptionId = description ? `${baseId}-description` : undefined;
|
|
17
|
+
const errorId = error ? `${baseId}-error` : undefined;
|
|
18
|
+
const labelId = label ? `${baseId}-label` : undefined;
|
|
19
|
+
const describedBy = [descriptionId, errorId].filter(Boolean).join(' ') || undefined;
|
|
20
|
+
const fieldProps = {
|
|
21
|
+
'aria-invalid': Boolean(error),
|
|
22
|
+
'aria-describedby': describedBy,
|
|
23
|
+
'aria-labelledby': labelId,
|
|
24
|
+
id: fieldId
|
|
25
|
+
};
|
|
26
|
+
const errorMessageProps = {
|
|
27
|
+
id: errorId
|
|
28
|
+
};
|
|
29
|
+
const descriptionProps = {
|
|
30
|
+
id: descriptionId
|
|
31
|
+
};
|
|
32
|
+
const labelProps = {
|
|
33
|
+
id: labelId,
|
|
34
|
+
htmlFor: fieldId,
|
|
35
|
+
onClick: () => {
|
|
36
|
+
if (isDisabled) {
|
|
37
|
+
return;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
if (fieldRef?.current) {
|
|
41
|
+
fieldRef.current.focus();
|
|
42
|
+
} else {
|
|
43
|
+
document.getElementById(fieldId)?.focus();
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
};
|
|
47
|
+
return {
|
|
48
|
+
baseId,
|
|
49
|
+
fieldProps,
|
|
50
|
+
descriptionProps,
|
|
51
|
+
errorMessageProps,
|
|
52
|
+
labelProps
|
|
53
|
+
};
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
export { useA11y };
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import type { SelectSize } from '../types';
|
|
3
|
+
export declare type UseActualSizeFromCssParams = {
|
|
4
|
+
sizeFromProps: SelectSize;
|
|
5
|
+
triggerRef: React.RefObject<HTMLElement>;
|
|
6
|
+
};
|
|
7
|
+
export declare const useActualSizeFromCss: ({ sizeFromProps, triggerRef }: UseActualSizeFromCssParams) => {
|
|
8
|
+
observableRef: React.MutableRefObject<undefined>;
|
|
9
|
+
size: "l" | "m" | "s";
|
|
10
|
+
};
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import _includesInstanceProperty from "@babel/runtime-corejs3/core-js-stable/instance/includes";
|
|
2
|
+
import { useRef, useState } from 'react';
|
|
3
|
+
import { useResizeObserver } from '@rescui/use-resize-observer';
|
|
4
|
+
|
|
5
|
+
const useActualSizeFromCss = _ref => {
|
|
6
|
+
let {
|
|
7
|
+
sizeFromProps,
|
|
8
|
+
triggerRef
|
|
9
|
+
} = _ref;
|
|
10
|
+
// We use invisible and "untouchable" dummy element to observe `size` changes from css to fetch the actual size
|
|
11
|
+
const observableRef = useRef();
|
|
12
|
+
const [size, setSize] = useState(sizeFromProps);
|
|
13
|
+
useResizeObserver(observableRef, () => {
|
|
14
|
+
var _context;
|
|
15
|
+
|
|
16
|
+
const triggerFormWrapperStyles = getComputedStyle(triggerRef.current);
|
|
17
|
+
const rawSizeFromCss = triggerFormWrapperStyles.getPropertyValue('--_rs-select-size');
|
|
18
|
+
const sizeFromCss = _includesInstanceProperty(_context = ['s', 'm', 'l']).call(_context, rawSizeFromCss) ? rawSizeFromCss : null;
|
|
19
|
+
setSize(sizeFromCss || sizeFromProps);
|
|
20
|
+
});
|
|
21
|
+
return {
|
|
22
|
+
observableRef,
|
|
23
|
+
size
|
|
24
|
+
};
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
export { useActualSizeFromCss };
|
|
@@ -0,0 +1,17 @@
|
|
|
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 };
|
|
@@ -0,0 +1,17 @@
|
|
|
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 };
|
|
@@ -0,0 +1,22 @@
|
|
|
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 };
|
|
@@ -0,0 +1,11 @@
|
|
|
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
|
+
};
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { useRef, useMemo, useCallback } from 'react';
|
|
2
|
+
import { getOptionValue } from '../utils/get-option-value.js';
|
|
3
|
+
|
|
4
|
+
const useMultiHandlers = _ref => {
|
|
5
|
+
let {
|
|
6
|
+
selectedItems,
|
|
7
|
+
onChange
|
|
8
|
+
} = _ref;
|
|
9
|
+
const onChangeRef = useRef(null);
|
|
10
|
+
onChangeRef.current = onChange;
|
|
11
|
+
const selectedMap = useMemo(() => new Map(selectedItems.map(item => [getOptionValue(item), item])), [selectedItems]);
|
|
12
|
+
const addItem = useCallback(item => {
|
|
13
|
+
if (selectedMap.has(getOptionValue(item))) {
|
|
14
|
+
return;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
const newValues = [...selectedMap.values(), item];
|
|
18
|
+
onChangeRef.current?.(newValues);
|
|
19
|
+
}, [selectedMap]);
|
|
20
|
+
const removeItem = useCallback(item => {
|
|
21
|
+
const key = getOptionValue(item);
|
|
22
|
+
const newValues = [...selectedMap.entries()].filter(_ref2 => {
|
|
23
|
+
let [k] = _ref2;
|
|
24
|
+
return k !== key;
|
|
25
|
+
}).map(_ref3 => {
|
|
26
|
+
let [, v] = _ref3;
|
|
27
|
+
return v;
|
|
28
|
+
});
|
|
29
|
+
onChangeRef.current?.(newValues);
|
|
30
|
+
}, [selectedMap]);
|
|
31
|
+
|
|
32
|
+
const removeAllItems = () => {
|
|
33
|
+
onChangeRef.current?.([]);
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
return {
|
|
37
|
+
selectedMap,
|
|
38
|
+
addItem,
|
|
39
|
+
removeItem,
|
|
40
|
+
removeAllItems
|
|
41
|
+
};
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
export { useMultiHandlers };
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/// <reference types="react" />
|
|
2
|
+
import type { SelectOptionOrGroup, SelectOption, ListBoxItem } from '../types';
|
|
3
|
+
/**
|
|
4
|
+
* Convert an array of options with possible groups to the flat array of options, stripping them of the groups.
|
|
5
|
+
* Also creating a list for ListBox component with indexes and keys.
|
|
6
|
+
* Supports filtering by returning the setFilterString function.
|
|
7
|
+
* @param options
|
|
8
|
+
*/
|
|
9
|
+
export declare const useOptions: (options: SelectOptionOrGroup[]) => {
|
|
10
|
+
setFilterString: import("react").Dispatch<import("react").SetStateAction<string>>;
|
|
11
|
+
filterString: string;
|
|
12
|
+
flattenedOptions: SelectOption[];
|
|
13
|
+
listBoxItems: ListBoxItem[];
|
|
14
|
+
};
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import _includesInstanceProperty from "@babel/runtime-corejs3/core-js-stable/instance/includes";
|
|
2
|
+
import { useState, useMemo } from 'react';
|
|
3
|
+
import { isOptionAGroup } from '../utils/is-option-a-group.js';
|
|
4
|
+
import { getTextFromNodes } from '../utils/get-text-from-nodes.js';
|
|
5
|
+
import { getOptionValue } from '../utils/get-option-value.js';
|
|
6
|
+
|
|
7
|
+
const createFilter = substring => {
|
|
8
|
+
if (substring.length === 0) {
|
|
9
|
+
return () => true;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
const lowerSubstring = substring.toLowerCase();
|
|
13
|
+
return string => {
|
|
14
|
+
var _context;
|
|
15
|
+
|
|
16
|
+
return _includesInstanceProperty(_context = string.toLowerCase()).call(_context, lowerSubstring);
|
|
17
|
+
};
|
|
18
|
+
};
|
|
19
|
+
/**
|
|
20
|
+
* Convert an array of options with possible groups to the flat array of options, stripping them of the groups.
|
|
21
|
+
* Also creating a list for ListBox component with indexes and keys.
|
|
22
|
+
* Supports filtering by returning the setFilterString function.
|
|
23
|
+
* @param options
|
|
24
|
+
*/
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
const useOptions = options => {
|
|
28
|
+
const [filterString, setFilterString] = useState('');
|
|
29
|
+
const filterFn = useMemo(() => createFilter(filterString), [filterString]);
|
|
30
|
+
const processedOptions = useMemo(() => {
|
|
31
|
+
const flattenedOptions = [];
|
|
32
|
+
const listBoxItems = [];
|
|
33
|
+
let index = 0;
|
|
34
|
+
|
|
35
|
+
const createOptionItem = option => {
|
|
36
|
+
return { ...option,
|
|
37
|
+
index: index++,
|
|
38
|
+
type: 'option',
|
|
39
|
+
key: getOptionValue(option)
|
|
40
|
+
};
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
options.forEach((optionOrGroup, arrayIndex) => {
|
|
44
|
+
if (isOptionAGroup(optionOrGroup)) {
|
|
45
|
+
const group = optionOrGroup;
|
|
46
|
+
|
|
47
|
+
if (!group.options || group.options.length === 0) {
|
|
48
|
+
return;
|
|
49
|
+
} // Render as Group (with or without label)
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
const groupLabelText = group.label ? getTextFromNodes(group.label) : ''; // Use a special prefix that's unlikely to collide with user values
|
|
53
|
+
|
|
54
|
+
const groupKey = `\0__rs_select_group_${arrayIndex}_${groupLabelText}`;
|
|
55
|
+
const listBoxGroupItem = { ...group,
|
|
56
|
+
type: 'group',
|
|
57
|
+
options: [],
|
|
58
|
+
key: groupKey
|
|
59
|
+
};
|
|
60
|
+
group.options.forEach(option => {
|
|
61
|
+
if (filterFn(getTextFromNodes(option.label))) {
|
|
62
|
+
flattenedOptions.push(option);
|
|
63
|
+
listBoxGroupItem.options.push(createOptionItem(option));
|
|
64
|
+
}
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
if (listBoxGroupItem.options.length > 0) {
|
|
68
|
+
listBoxItems.push(listBoxGroupItem);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
return;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
if (filterFn(getTextFromNodes(optionOrGroup.label))) {
|
|
75
|
+
flattenedOptions.push(optionOrGroup);
|
|
76
|
+
listBoxItems.push(createOptionItem(optionOrGroup));
|
|
77
|
+
}
|
|
78
|
+
});
|
|
79
|
+
return {
|
|
80
|
+
flattenedOptions,
|
|
81
|
+
listBoxItems
|
|
82
|
+
};
|
|
83
|
+
}, [options, filterFn]);
|
|
84
|
+
return { ...processedOptions,
|
|
85
|
+
setFilterString,
|
|
86
|
+
filterString
|
|
87
|
+
};
|
|
88
|
+
};
|
|
89
|
+
|
|
90
|
+
export { useOptions };
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
export declare type UsePrimaryContrastCssVarTransferParams = {
|
|
3
|
+
triggerRef: React.RefObject<HTMLElement>;
|
|
4
|
+
isOpen: boolean;
|
|
5
|
+
};
|
|
6
|
+
/**
|
|
7
|
+
* Transfer primary contrast css var to the dropdown, but only when the dropdown opens
|
|
8
|
+
*/
|
|
9
|
+
export declare const usePrimaryContrastCssVarTransfer: ({ triggerRef, isOpen }: UsePrimaryContrastCssVarTransferParams) => {
|
|
10
|
+
isPrimaryContrast: boolean;
|
|
11
|
+
};
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { useRef } from 'react';
|
|
2
|
+
/**
|
|
3
|
+
* Transfer primary contrast css var to the dropdown, but only when the dropdown opens
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
const usePrimaryContrastCssVarTransfer = _ref => {
|
|
7
|
+
let {
|
|
8
|
+
triggerRef,
|
|
9
|
+
isOpen
|
|
10
|
+
} = _ref;
|
|
11
|
+
const prevIsOpenRef = useRef(false);
|
|
12
|
+
const isPrimaryContrastRef = useRef(false);
|
|
13
|
+
|
|
14
|
+
if (prevIsOpenRef.current !== isOpen && isOpen && triggerRef.current && typeof window !== 'undefined') {
|
|
15
|
+
const isPrimaryContrastFromCss = getComputedStyle(triggerRef.current)?.getPropertyValue('--rs-select-contrast-primary');
|
|
16
|
+
isPrimaryContrastRef.current = isPrimaryContrastFromCss.toString() === '1';
|
|
17
|
+
prevIsOpenRef.current = true;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
if (!isOpen) {
|
|
21
|
+
prevIsOpenRef.current = false;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
return {
|
|
25
|
+
isPrimaryContrast: isPrimaryContrastRef.current
|
|
26
|
+
};
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
export { usePrimaryContrastCssVarTransfer };
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import React, { useRef } from 'react';
|
|
2
|
+
|
|
3
|
+
const useFallbackId = () => {
|
|
4
|
+
const id = useRef(null);
|
|
5
|
+
|
|
6
|
+
if (id.current === null) {
|
|
7
|
+
id.current = useFallbackId.counter++;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
return id.current.toString();
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
useFallbackId.counter = 0;
|
|
14
|
+
const useSafeId = React.useId ?? useFallbackId;
|
|
15
|
+
export { useFallbackId, useSafeId };
|