@rescui/select 0.14.4-RUI-286-Fix-tooltip-stacking-f4145b01.1 → 0.15.1-RUI-280-Update-select-component-026338d06.52

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 (91) hide show
  1. package/lib/_virtual/index.css.js +12 -12
  2. package/lib/common-prop-types.d.ts +9 -14
  3. package/lib/common-prop-types.js +4 -3
  4. package/lib/constants.d.ts +7 -0
  5. package/lib/constants.js +8 -0
  6. package/lib/hooks/use-css-context-transfer.d.ts +14 -0
  7. package/lib/hooks/use-css-context-transfer.js +40 -0
  8. package/lib/hooks/use-label-focus.d.ts +11 -0
  9. package/lib/hooks/use-label-focus.js +28 -0
  10. package/lib/hooks/use-multi-option-serialization.d.ts +10 -0
  11. package/lib/hooks/use-multi-option-serialization.js +82 -0
  12. package/lib/hooks/use-option-serialization.d.ts +10 -0
  13. package/lib/hooks/use-option-serialization.js +59 -0
  14. package/lib/index.css +1700 -705
  15. package/lib/index.d.ts +4 -6
  16. package/lib/index.js +3 -3
  17. package/lib/multiselect.d.ts +29 -0
  18. package/lib/multiselect.js +239 -0
  19. package/lib/native-select.d.ts +4 -0
  20. package/lib/native-select.js +182 -0
  21. package/lib/parts/foldable.js +5 -7
  22. package/lib/parts/form-trigger-wrapper.d.ts +21 -3
  23. package/lib/parts/form-trigger-wrapper.js +30 -40
  24. package/lib/parts/icons.d.ts +17 -0
  25. package/lib/parts/icons.js +75 -0
  26. package/lib/parts/list-box.d.ts +19 -0
  27. package/lib/parts/list-box.js +146 -0
  28. package/lib/parts/multi-trigger.d.ts +11 -0
  29. package/lib/parts/multi-trigger.js +62 -0
  30. package/lib/parts/native-select-options-with-groups.d.ts +8 -0
  31. package/lib/parts/native-select-options-with-groups.js +76 -0
  32. package/lib/parts/native-select-trigger.d.ts +18 -0
  33. package/lib/parts/native-select-trigger.js +54 -0
  34. package/lib/parts/popover.d.ts +12 -0
  35. package/lib/parts/popover.js +62 -0
  36. package/lib/parts/popup-content.d.ts +19 -0
  37. package/lib/parts/popup-content.js +76 -0
  38. package/lib/public-api.p.css +401 -1022
  39. package/lib/public-api.pcss +401 -1022
  40. package/lib/select-basic.d.ts +3 -0
  41. package/lib/select-basic.js +143 -0
  42. package/lib/select-searchable.d.ts +3 -0
  43. package/lib/select-searchable.js +168 -0
  44. package/lib/select.d.ts +27 -86
  45. package/lib/select.js +58 -352
  46. package/lib/styles/common.p.module.css.js +27 -0
  47. package/lib/styles/form-trigger.p.module.css.js +15 -0
  48. package/lib/styles/list-box.p.module.css.js +16 -0
  49. package/lib/styles/native-select-trigger.p.module.css.js +17 -0
  50. package/lib/styles/native-select.p.module.css.js +9 -0
  51. package/lib/styles/popover.p.module.css.js +10 -0
  52. package/lib/types.d.ts +167 -4
  53. package/lib/utils/calculate-max-height-by-items.d.ts +13 -0
  54. package/lib/utils/calculate-max-height-by-items.js +22 -0
  55. package/lib/utils/convert-options.d.ts +3 -0
  56. package/lib/utils/convert-options.js +52 -0
  57. package/lib/utils/convert-placement.d.ts +3 -0
  58. package/lib/utils/convert-placement.js +22 -0
  59. package/lib/utils/css-vars-utils.d.ts +3 -0
  60. package/lib/utils/css-vars-utils.js +20 -0
  61. package/lib/utils/get-empty-message.d.ts +6 -0
  62. package/lib/utils/get-empty-message.js +32 -0
  63. package/lib/utils/get-option-value.d.ts +2 -0
  64. package/lib/utils/get-option-value.js +11 -0
  65. package/lib/utils/get-real-items-cnt.d.ts +2 -0
  66. package/lib/utils/get-real-items-cnt.js +21 -0
  67. package/lib/utils/get-text-from-nodes.d.ts +2 -0
  68. package/lib/utils/get-text-from-nodes.js +28 -0
  69. package/lib/utils/is-option-a-group.d.ts +2 -0
  70. package/lib/utils/is-option-a-group.js +5 -0
  71. package/lib/utils/throttle.d.ts +1 -0
  72. package/package.json +12 -8
  73. package/lib/_virtual/warning.js +0 -106
  74. package/lib/key-codes.d.ts +0 -7
  75. package/lib/key-codes.js +0 -8
  76. package/lib/parts/common-select.p.module.css.js +0 -15
  77. package/lib/parts/form-trigger.p.module.css.js +0 -13
  78. package/lib/parts/multiselect.d.ts +0 -81
  79. package/lib/parts/multiselect.js +0 -441
  80. package/lib/parts/native-select.d.ts +0 -30
  81. package/lib/parts/native-select.js +0 -244
  82. package/lib/parts/native-select.p.module.css.js +0 -9
  83. package/lib/parts/throttle.d.ts +0 -1
  84. package/lib/parts/trigger.d.ts +0 -37
  85. package/lib/parts/trigger.js +0 -255
  86. package/lib/parts/trigger.p.module.css.js +0 -31
  87. package/lib/utils.d.ts +0 -22
  88. package/lib/utils.js +0 -201
  89. /package/lib/{parts → hooks}/use-observable-force-rerender.d.ts +0 -0
  90. /package/lib/{parts → hooks}/use-observable-force-rerender.js +0 -0
  91. /package/lib/{parts → utils}/throttle.js +0 -0
@@ -0,0 +1,3 @@
1
+ /// <reference types="react" />
2
+ import type { InnerSingleComponentProps } from './types';
3
+ export declare function SelectBasic<T extends object>({ id, size, mode, theme, style, className, isClearable, isLoading, placement, boldLabel, reserveErrorLine, noOptionsMessage, maxVisibleItems, ...ariaProps }: InnerSingleComponentProps<T>): JSX.Element;
@@ -0,0 +1,143 @@
1
+ import React, { useRef } from 'react';
2
+ import cn from 'classnames';
3
+ import { useSelectState } from 'react-stately';
4
+ import { useSelect, useButton, useFocusRing, mergeProps, HiddenSelect } from 'react-aria';
5
+ import { PopupContent } from './parts/popup-content.js';
6
+ import { Icons } from './parts/icons.js';
7
+ import { FormTriggerWrapper } from './parts/form-trigger-wrapper.js';
8
+ import { useLabelFocus } from './hooks/use-label-focus.js';
9
+ import { getEmptyMessage } from './utils/get-empty-message.js';
10
+ import styles from './styles/common.p.module.css.js';
11
+ const THEME_STYLES = {
12
+ light: styles.themeLight,
13
+ dark: styles.themeDark
14
+ };
15
+ const SIZE_STYLES = {
16
+ s: styles.sizeS,
17
+ m: styles.sizeM,
18
+ l: styles.sizeL
19
+ };
20
+ const MODE_STYLES = {
21
+ classic: styles.classic,
22
+ rock: styles.rock
23
+ }; // eslint-disable-next-line complexity
24
+
25
+ function SelectBasic(_ref) {
26
+ var _state$selectedItems$;
27
+
28
+ let {
29
+ id,
30
+ size,
31
+ mode,
32
+ theme,
33
+ style,
34
+ className,
35
+ isClearable,
36
+ isLoading,
37
+ placement,
38
+ boldLabel,
39
+ reserveErrorLine,
40
+ noOptionsMessage,
41
+ maxVisibleItems,
42
+ ...ariaProps
43
+ } = _ref;
44
+ // Create state based on the incoming props
45
+ const state = useSelectState({ ...ariaProps,
46
+ allowsEmptyCollection: true
47
+ });
48
+ const hasValue = state.selectedItems.length > 0; // Get props for child elements from useSelect
49
+
50
+ const triggerRef = useRef(null);
51
+ const {
52
+ labelProps,
53
+ triggerProps,
54
+ valueProps,
55
+ menuProps: listBoxProps,
56
+ hiddenSelectProps,
57
+ errorMessageProps,
58
+ descriptionProps
59
+ } = useSelect({ ...ariaProps,
60
+ onKeyDown: e => {
61
+ if (isClearable && hasValue) {
62
+ if (e.key === 'Backspace' || e.key === 'Delete') {
63
+ state.setValue(null);
64
+ e.stopPropagation();
65
+ }
66
+ }
67
+ }
68
+ }, state, triggerRef);
69
+ const {
70
+ buttonProps
71
+ } = useButton({ ...triggerProps,
72
+ elementType: 'div'
73
+ }, triggerRef);
74
+ const isDisabled = ariaProps.isDisabled;
75
+ const isOpen = state.isOpen;
76
+ const {
77
+ isFocusVisible,
78
+ focusProps
79
+ } = useFocusRing({
80
+ within: true
81
+ });
82
+ const {
83
+ isFocusedByLabel,
84
+ labelClickProps,
85
+ triggerFocusProps: labelFocusForTriggerProps
86
+ } = useLabelFocus(triggerRef);
87
+ const emptyListMessage = getEmptyMessage({
88
+ isLoading,
89
+ isNothingFound: false,
90
+ noOptionsMessage
91
+ });
92
+ return /*#__PURE__*/React.createElement("div", {
93
+ className: cn(className, styles.root, THEME_STYLES[theme], SIZE_STYLES[size], MODE_STYLES[mode], isDisabled ? styles.disabled : styles.enabled, Boolean(ariaProps.errorMessage) && styles.error),
94
+ id: id,
95
+ style: style,
96
+ "data-test": "select"
97
+ }, /*#__PURE__*/React.createElement(FormTriggerWrapper, {
98
+ theme: theme,
99
+ size: size,
100
+ disabled: isDisabled,
101
+ label: ariaProps.label,
102
+ labelProps: mergeProps(labelClickProps, labelProps),
103
+ boldLabel: boldLabel,
104
+ error: ariaProps.errorMessage,
105
+ reserveErrorLine: reserveErrorLine,
106
+ errorMessageProps: errorMessageProps,
107
+ note: ariaProps.description,
108
+ descriptionProps: descriptionProps
109
+ }, /*#__PURE__*/React.createElement(HiddenSelect, { ...hiddenSelectProps
110
+ }), /*#__PURE__*/React.createElement("div", { ...mergeProps(buttonProps, focusProps, labelFocusForTriggerProps),
111
+ ref: triggerRef,
112
+ className: styles.trigger,
113
+ "data-open": isOpen,
114
+ "data-focus-visible": isFocusVisible,
115
+ "data-label-focused": isFocusedByLabel,
116
+ "data-test": "select__trigger"
117
+ }, /*#__PURE__*/React.createElement("span", { ...valueProps,
118
+ className: cn(styles.triggerText, !hasValue && styles.labelNotSelected),
119
+ "data-test": "select__trigger_content"
120
+ }, ((_state$selectedItems$ = state.selectedItems[0]) === null || _state$selectedItems$ === void 0 ? void 0 : _state$selectedItems$.rendered) ?? ariaProps.placeholder), /*#__PURE__*/React.createElement(Icons, {
121
+ isLoading: isLoading,
122
+ canHaveClearIcon: isClearable && !isDisabled && hasValue,
123
+ onClear: () => {
124
+ var _triggerRef$current;
125
+
126
+ state.setValue(null);
127
+ (_triggerRef$current = triggerRef.current) === null || _triggerRef$current === void 0 || _triggerRef$current.focus();
128
+ },
129
+ triggerId: triggerProps.id
130
+ })), /*#__PURE__*/React.createElement(PopupContent, {
131
+ theme: theme,
132
+ state: state,
133
+ triggerRef: triggerRef,
134
+ placement: placement,
135
+ size: size,
136
+ mode: mode,
137
+ listBoxProps: listBoxProps,
138
+ emptyListMessage: emptyListMessage,
139
+ maxVisibleItems: maxVisibleItems
140
+ })));
141
+ }
142
+
143
+ export { SelectBasic };
@@ -0,0 +1,3 @@
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;
@@ -0,0 +1,168 @@
1
+ import _includesInstanceProperty from "@babel/runtime-corejs3/core-js-stable/instance/includes";
2
+ import React, { useRef } from 'react';
3
+ import cn from 'classnames';
4
+ import { useComboBoxState } from 'react-stately';
5
+ import { useComboBox, useButton, useFocusRing, mergeProps, HiddenSelect } from 'react-aria';
6
+ import { PopupContent } from './parts/popup-content.js';
7
+ import { Icons } from './parts/icons.js';
8
+ import { FormTriggerWrapper } from './parts/form-trigger-wrapper.js';
9
+ import { useLabelFocus } from './hooks/use-label-focus.js';
10
+ import { getEmptyMessage } from './utils/get-empty-message.js';
11
+ import styles from './styles/common.p.module.css.js';
12
+ const THEME_STYLES = {
13
+ light: styles.themeLight,
14
+ dark: styles.themeDark
15
+ };
16
+ const SIZE_STYLES = {
17
+ s: styles.sizeS,
18
+ m: styles.sizeM,
19
+ l: styles.sizeL
20
+ };
21
+ const MODE_STYLES = {
22
+ classic: styles.classic,
23
+ rock: styles.rock
24
+ }; // Do not use useFilter from 'react-aria' package as it's much slower for most cases
25
+
26
+ const contains = (string, substring) => {
27
+ var _context;
28
+
29
+ if (substring.length === 0) {
30
+ return true;
31
+ }
32
+
33
+ return _includesInstanceProperty(_context = string.toLowerCase()).call(_context, substring.toLowerCase());
34
+ }; // eslint-disable-next-line complexity
35
+
36
+
37
+ function SelectSearchable(_ref) {
38
+ var _state$inputValue;
39
+
40
+ let {
41
+ id,
42
+ size,
43
+ mode,
44
+ theme,
45
+ className,
46
+ style,
47
+ isClearable,
48
+ isLoading,
49
+ placement,
50
+ boldLabel,
51
+ reserveErrorLine,
52
+ noOptionsMessage,
53
+ maxVisibleItems,
54
+ ...ariaProps
55
+ } = _ref;
56
+ // Create state based on the incoming props
57
+ const state = useComboBoxState({ ...ariaProps,
58
+ defaultFilter: contains,
59
+ allowsEmptyCollection: true
60
+ });
61
+ const hasValue = state.selectedItems.length > 0; // Setup refs and get props for child elements.
62
+
63
+ const triggerRef = useRef(null);
64
+ const inputRef = useRef(null);
65
+ const listBoxRef = useRef(null);
66
+ const popoverRef = useRef(null);
67
+ const {
68
+ labelProps,
69
+ buttonProps: triggerProps,
70
+ listBoxProps,
71
+ inputProps: inputPropsWithName,
72
+ errorMessageProps,
73
+ descriptionProps
74
+ } = useComboBox({ ...ariaProps,
75
+ inputRef,
76
+ buttonRef: triggerRef,
77
+ listBoxRef,
78
+ popoverRef
79
+ }, state); // Extract name from inputProps to use with HiddenSelect instead
80
+
81
+ const {
82
+ name,
83
+ ...inputProps
84
+ } = inputPropsWithName;
85
+ const {
86
+ buttonProps
87
+ } = useButton({ ...triggerProps,
88
+ elementType: 'div'
89
+ }, triggerRef);
90
+ const isDisabled = ariaProps.isDisabled;
91
+ const isOpen = state.isOpen;
92
+ const {
93
+ isFocusVisible,
94
+ focusProps
95
+ } = useFocusRing({
96
+ within: true
97
+ });
98
+ const {
99
+ isFocusedByLabel,
100
+ labelClickProps,
101
+ triggerFocusProps: labelFocusForTriggerProps
102
+ } = useLabelFocus(triggerRef);
103
+ const emptyListMessage = getEmptyMessage({
104
+ isLoading,
105
+ isNothingFound: ((_state$inputValue = state.inputValue) === null || _state$inputValue === void 0 ? void 0 : _state$inputValue.length) > 0,
106
+ noOptionsMessage
107
+ });
108
+ return /*#__PURE__*/React.createElement("div", {
109
+ className: cn(className, styles.root, THEME_STYLES[theme], SIZE_STYLES[size], MODE_STYLES[mode], isDisabled ? styles.disabled : styles.enabled, Boolean(ariaProps.errorMessage) && styles.error),
110
+ id: id,
111
+ style: style,
112
+ "data-test": "select"
113
+ }, /*#__PURE__*/React.createElement(FormTriggerWrapper, {
114
+ theme: theme,
115
+ size: size,
116
+ disabled: isDisabled,
117
+ label: ariaProps.label,
118
+ labelProps: mergeProps(labelClickProps, labelProps),
119
+ boldLabel: boldLabel,
120
+ error: ariaProps.errorMessage,
121
+ reserveErrorLine: reserveErrorLine,
122
+ errorMessageProps: errorMessageProps,
123
+ note: ariaProps.description,
124
+ descriptionProps: descriptionProps
125
+ }, /*#__PURE__*/React.createElement(HiddenSelect, {
126
+ state: state,
127
+ triggerRef: triggerRef,
128
+ label: ariaProps.label,
129
+ name: name,
130
+ isDisabled: isDisabled
131
+ }), /*#__PURE__*/React.createElement("div", { ...mergeProps(buttonProps, focusProps, labelFocusForTriggerProps),
132
+ ref: triggerRef,
133
+ className: styles.trigger,
134
+ "data-open": isOpen,
135
+ "data-focus-visible": isFocusVisible,
136
+ "data-label-focused": isFocusedByLabel,
137
+ "data-test": "select__trigger"
138
+ }, /*#__PURE__*/React.createElement("input", { ...inputProps,
139
+ ref: inputRef,
140
+ className: styles.searchInput,
141
+ value: inputProps.value,
142
+ "data-test": "select__trigger_input"
143
+ }), /*#__PURE__*/React.createElement(Icons, {
144
+ isLoading: isLoading,
145
+ canHaveClearIcon: isClearable && !isDisabled && hasValue,
146
+ onClear: () => {
147
+ var _inputRef$current;
148
+
149
+ state.setValue(null);
150
+ (_inputRef$current = inputRef.current) === null || _inputRef$current === void 0 || _inputRef$current.focus();
151
+ },
152
+ triggerId: triggerProps.id
153
+ })), /*#__PURE__*/React.createElement(PopupContent, {
154
+ theme: theme,
155
+ state: state,
156
+ triggerRef: triggerRef,
157
+ popoverRef: popoverRef,
158
+ listBoxRef: listBoxRef,
159
+ placement: placement,
160
+ size: size,
161
+ mode: mode,
162
+ listBoxProps: listBoxProps,
163
+ emptyListMessage: emptyListMessage,
164
+ maxVisibleItems: maxVisibleItems
165
+ })));
166
+ }
167
+
168
+ export { SelectSearchable };
package/lib/select.d.ts CHANGED
@@ -1,87 +1,28 @@
1
1
  import React from 'react';
2
- import { Theme } from '@rescui/ui-contexts';
3
- import type { SelectOption, NoOptionsMessage, SelectOptionOrGroup, SelectSize, SelectMode } from './types';
4
- export interface CustomTriggerOptions {
5
- selectedLabel?: string;
6
- selectedValue: string;
7
- placeholder?: string;
8
- hovered: boolean;
9
- }
10
- export interface SelectProps {
11
- /**
12
- * Additional class name
13
- */
14
- className?: string;
15
- /**
16
- * Array of options or option groups
17
- */
18
- options: SelectOptionOrGroup[];
19
- /**
20
- * Is select supports clear the value
21
- */
22
- isClearable?: boolean;
23
- /**
24
- * Is select supports inplace filtering
25
- */
26
- isSearchable?: boolean;
27
- /**
28
- * Is select has been disabled
29
- */
30
- isDisabled?: boolean;
31
- /**
32
- * Is loader displayed inside select
33
- */
34
- isLoading?: boolean;
35
- /**
36
- * A hint to the user of what can be entered in the control
37
- */
38
- placeholder?: string;
39
- /**
40
- * Size
41
- */
42
- size?: SelectSize;
43
- /**
44
- * Appearance mode
45
- */
46
- mode?: SelectMode;
47
- /**
48
- * Appearance theme
49
- */
50
- theme?: Theme;
51
- /**
52
- * Value of the select
53
- */
54
- value: SelectOption;
55
- /**
56
- * Change value callback. `value => ...`
57
- */
58
- onChange?: (newValue: SelectOption) => void;
59
- /**
60
- * Error state flag or React.ReactNode (use with forms)
61
- */
62
- error?: boolean | React.ReactNode;
63
- /**
64
- * Label element upper then Select element (use with forms)
65
- */
66
- label?: React.ReactNode;
67
- /**
68
- * Placement of dropdown element
69
- */
70
- 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';
71
- /**
72
- * Note element below then Select element (use with forms)
73
- */
74
- note?: React.ReactNode;
75
- id?: string;
76
- /**
77
- * Text to display when there are no options
78
- */
79
- noOptionsMessage?: NoOptionsMessage;
80
- /**
81
- * Input name attribute
82
- */
83
- name?: string;
84
- boldLabel?: boolean;
85
- }
86
- declare const Select: React.FC<SelectProps>;
87
- export default Select;
2
+ import PropTypes from 'prop-types';
3
+ import type { SelectProps, SelectOption, SelectOptionOrGroup } from './types';
4
+ export declare const Select: {
5
+ ({ options, size, mode, theme: themeFromProps, className, style, value, onChange, placeholder, isClearable, isLoading, isDisabled, isSearchable, noOptionsMessage, error, placement, boldLabel, reserveErrorLine, note, maxVisibleItems, ...restProps }: SelectProps): JSX.Element;
6
+ propTypes: {
7
+ className: PropTypes.Requireable<string>;
8
+ style: PropTypes.Requireable<object>;
9
+ options: PropTypes.Validator<SelectOptionOrGroup[]>;
10
+ value: PropTypes.Validator<SelectOption>;
11
+ onChange: PropTypes.Requireable<(...args: any[]) => any>;
12
+ size: PropTypes.Requireable<string>;
13
+ mode: PropTypes.Requireable<string>;
14
+ theme: PropTypes.Requireable<string>;
15
+ placeholder: PropTypes.Requireable<string>;
16
+ isClearable: PropTypes.Requireable<boolean>;
17
+ isSearchable: PropTypes.Requireable<boolean>;
18
+ isDisabled: PropTypes.Requireable<boolean>;
19
+ isLoading: PropTypes.Requireable<boolean>;
20
+ error: React.Validator<React.ReactNode>;
21
+ label: PropTypes.Requireable<PropTypes.ReactNodeLike>;
22
+ id: PropTypes.Requireable<string>;
23
+ note: PropTypes.Requireable<PropTypes.ReactNodeLike>;
24
+ noOptionsMessage: React.Validator<import("./types").NoOptionsMessage>;
25
+ placement: PropTypes.Requireable<string>;
26
+ name: PropTypes.Requireable<string>;
27
+ };
28
+ };