@rescui/select 0.15.1-RUI-280-Update-select-component-separate-components-e772abaa1.56 → 0.15.1-RUI-280-Update-select-component-downshift-cd2a98813.66

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 (65) hide show
  1. package/lib/_virtual/index.css.js +12 -12
  2. package/lib/constants.d.ts +0 -1
  3. package/lib/constants.js +1 -2
  4. package/lib/hooks/use-a11y.d.ts +29 -0
  5. package/lib/hooks/use-a11y.js +53 -0
  6. package/lib/hooks/use-backward-compatible-id.d.ts +4 -0
  7. package/lib/hooks/use-backward-compatible-id.js +14 -0
  8. package/lib/hooks/use-label-focus.d.ts +1 -3
  9. package/lib/hooks/use-label-focus.js +3 -9
  10. package/lib/hooks/use-multi-handlers.d.ts +11 -0
  11. package/lib/hooks/use-multi-handlers.js +48 -0
  12. package/lib/hooks/use-options.d.ts +13 -0
  13. package/lib/hooks/use-options.js +89 -0
  14. package/lib/index.css +323 -371
  15. package/lib/multiselect.d.ts +3 -29
  16. package/lib/multiselect.js +249 -174
  17. package/lib/native-select.js +67 -46
  18. package/lib/parts/hidden-select.d.ts +13 -0
  19. package/lib/parts/hidden-select.js +45 -0
  20. package/lib/parts/icons.d.ts +3 -1
  21. package/lib/parts/icons.js +11 -14
  22. package/lib/parts/list-box.d.ts +7 -15
  23. package/lib/parts/list-box.js +50 -82
  24. package/lib/parts/multi-trigger.d.ts +5 -4
  25. package/lib/parts/multi-trigger.js +27 -15
  26. package/lib/parts/native-select-trigger.d.ts +6 -8
  27. package/lib/parts/native-select-trigger.js +14 -23
  28. package/lib/select-basic.d.ts +2 -2
  29. package/lib/select-basic.js +161 -97
  30. package/lib/select-searchable.d.ts +2 -2
  31. package/lib/select-searchable.js +208 -122
  32. package/lib/select.d.ts +1 -1
  33. package/lib/select.js +38 -31
  34. package/lib/styles/common.p.module.css.js +25 -24
  35. package/lib/styles/form-trigger.p.module.css.js +12 -12
  36. package/lib/styles/list-box.p.module.css.js +11 -13
  37. package/lib/styles/native-select-trigger.p.module.css.js +15 -14
  38. package/lib/styles/native-select.p.module.css.js +6 -6
  39. package/lib/types.d.ts +26 -27
  40. package/lib/utils/get-real-items-cnt.d.ts +2 -2
  41. package/lib/utils/get-real-items-cnt.js +8 -10
  42. package/lib/utils/item-to-string.d.ts +2 -0
  43. package/lib/utils/item-to-string.js +7 -0
  44. package/lib/utils/merge-props.d.ts +29 -0
  45. package/lib/utils/merge-props.js +106 -0
  46. package/package.json +13 -22
  47. package/lib/hooks/use-css-context-transfer.d.ts +0 -14
  48. package/lib/hooks/use-css-context-transfer.js +0 -40
  49. package/lib/hooks/use-multi-option-serialization.d.ts +0 -10
  50. package/lib/hooks/use-multi-option-serialization.js +0 -82
  51. package/lib/hooks/use-observable-force-rerender.d.ts +0 -2
  52. package/lib/hooks/use-observable-force-rerender.js +0 -16
  53. package/lib/hooks/use-option-serialization.d.ts +0 -10
  54. package/lib/hooks/use-option-serialization.js +0 -59
  55. package/lib/parts/popover.d.ts +0 -12
  56. package/lib/parts/popover.js +0 -64
  57. package/lib/parts/popup-content.d.ts +0 -19
  58. package/lib/parts/popup-content.js +0 -76
  59. package/lib/styles/popover.p.module.css.js +0 -10
  60. package/lib/utils/convert-options.d.ts +0 -3
  61. package/lib/utils/convert-options.js +0 -52
  62. package/lib/utils/convert-placement.d.ts +0 -3
  63. package/lib/utils/convert-placement.js +0 -22
  64. package/lib/utils/css-vars-utils.d.ts +0 -3
  65. package/lib/utils/css-vars-utils.js +0 -20
package/lib/types.d.ts CHANGED
@@ -1,15 +1,8 @@
1
1
  import React from 'react';
2
2
  import type { Theme } from '@rescui/ui-contexts';
3
- import type { AriaComboBoxProps } from '@react-aria/combobox';
4
- import type { AriaSelectProps } from '@react-aria/select';
5
- import type { AriaPositionProps } from '@react-aria/overlays';
6
- import type { AriaFieldProps } from '@react-aria/label';
7
- import type { SelectState } from '@react-stately/select';
8
- import type { ComboBoxState } from '@react-stately/combobox';
9
- import type { Key } from '@react-types/shared';
10
- export type { Key } from '@react-types/shared';
3
+ import type { UseSelectPropGetters } from 'downshift';
4
+ export declare type Key = string | number;
11
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';
12
- export declare type AriaPlacement = AriaPositionProps['placement'];
13
6
  export declare type SelectSize = 'l' | 'm' | 's';
14
7
  export declare type SelectMode = 'classic' | 'rock';
15
8
  export declare type SelectOption = {
@@ -22,6 +15,27 @@ export declare type SelectOptionsGroup = {
22
15
  };
23
16
  export declare type SelectOptionOrGroup = SelectOption | SelectOptionsGroup;
24
17
  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
+ };
25
39
  export declare type NativeSelectOption = {
26
40
  label: string;
27
41
  value?: Key;
@@ -166,6 +180,7 @@ export declare type NativeSelectProps = {
166
180
  placeholder?: string;
167
181
  isLoading?: boolean;
168
182
  isDisabled?: boolean;
183
+ isClearable?: boolean;
169
184
  trigger?: (props: TriggerFuncProps) => React.ReactNode;
170
185
  label?: React.ReactNode;
171
186
  note?: React.ReactNode;
@@ -178,21 +193,5 @@ export declare type NativeSelectProps = {
178
193
  noOptionsMessage?: NoOptionsMessage;
179
194
  name?: string;
180
195
  boldLabel?: boolean;
181
- } & Omit<AriaFieldProps, 'isInvalid' | 'errorMessage' | 'description' | 'id' | 'label' | 'labelElementType' | 'validate' | 'validationBehavior' | 'validationState'>;
182
- export declare type InnerSingleComponentProps<T extends object> = {
183
- size?: SelectSize;
184
- mode?: SelectMode;
185
- theme?: Theme;
186
- style?: React.CSSProperties;
187
- className?: string;
188
- isClearable?: boolean;
189
- isLoading?: boolean;
190
- errorMessage?: React.ReactNode;
191
- placement?: AriaPlacement;
192
- boldLabel?: boolean;
193
- reserveErrorLine?: boolean;
194
- placeholder?: string;
195
- noOptionsMessage?: NoOptionsMessage;
196
- maxVisibleItems?: number;
197
- } & Omit<AriaSelectProps<T, 'single'> | AriaComboBoxProps<T, 'single'>, 'errorMessage' | 'validate'>;
198
- export declare type CommonState<T extends object> = SelectState<T, 'single'> | SelectState<T, 'multiple'> | ComboBoxState<T>;
196
+ };
197
+ export declare type InnerSingleComponentProps = Omit<SelectProps, 'isSearchable'>;
@@ -1,2 +1,2 @@
1
- import type { ListState } from 'react-stately';
2
- export declare const getRealItemsCnt: <T extends object>(state: ListState<T>) => number;
1
+ import { ListBoxItem } from '../types';
2
+ export declare const getRealItemsCnt: (items: ListBoxItem[]) => number;
@@ -1,16 +1,14 @@
1
- import { VIRTUAL_ITEMS_SECTION_KEY } from '../constants.js';
1
+ const getRealItemsCnt = items => {
2
+ // Count total number of items
3
+ return items.reduce((count, item) => {
4
+ if (item.type === 'group') {
5
+ const groupOptions = item.options;
6
+ const hasHeading = item.label !== null && item.label !== undefined; // Count heading (if present) + all options in the section
2
7
 
3
- const getRealItemsCnt = state => {
4
- // Count total number of items, ignoring virtual items
5
- return [...state.collection].reduce((count, item) => {
6
- if (item.type === 'section' && item.key !== VIRTUAL_ITEMS_SECTION_KEY) {
7
- const sectionChildren = [...state.collection.getChildren(item.key)];
8
- const hasHeading = item.rendered !== null && item.rendered !== undefined; // Count heading (if present) + all options in the section
9
-
10
- return count + (hasHeading ? 1 : 0) + sectionChildren.length;
8
+ return count + (hasHeading ? 1 : 0) + groupOptions.length;
11
9
  }
12
10
 
13
- if (item.type === 'item') {
11
+ if (item.type === 'option') {
14
12
  return count + 1;
15
13
  }
16
14
 
@@ -0,0 +1,2 @@
1
+ import type { SelectOption } from '../types';
2
+ export declare function itemToString(item: SelectOption): string;
@@ -0,0 +1,7 @@
1
+ import { getTextFromNodes } from './get-text-from-nodes.js';
2
+
3
+ function itemToString(item) {
4
+ return item ? getTextFromNodes(item.label) : '';
5
+ }
6
+
7
+ export { itemToString };
@@ -0,0 +1,29 @@
1
+ /**
2
+ * Copied from react-aria repo
3
+ * @see https://github.com/adobe/react-spectrum/blob/main/packages/react-aria/src/utils/mergeProps.ts
4
+ */
5
+ import type { MutableRefObject, RefCallback } from 'react';
6
+ /**
7
+ * Merges multiple refs into one. Works with either callback or object refs.
8
+ */
9
+ export declare function mergeRefs<T>(...refs: Array<RefCallback<T> | MutableRefObject<T> | null | undefined>): RefCallback<T> | MutableRefObject<T>;
10
+ export declare function chain(...callbacks: any[]): (...args: any[]) => void;
11
+ interface Props {
12
+ [key: string]: any;
13
+ }
14
+ declare type PropsArg = Props | null | undefined;
15
+ declare type TupleTypes<T> = {
16
+ [P in keyof T]: T[P];
17
+ } extends {
18
+ [key: number]: infer V;
19
+ } ? NullToObject<V> : never;
20
+ declare type NullToObject<T> = T extends null | undefined ? object : T;
21
+ declare type UnionToIntersection<U> = (U extends any ? (k: U) => void : never) extends (k: infer I) => void ? I : never;
22
+ /**
23
+ * Merges multiple props objects together. Event handlers are chained,
24
+ * classNames are combined, ids are deduplicated, and refs are merged.
25
+ * For all other props, the last prop object overrides all previous ones.
26
+ * @param args - Multiple sets of props to merge together.
27
+ */
28
+ export declare function mergeProps<T extends PropsArg[]>(...args: T): UnionToIntersection<TupleTypes<T>>;
29
+ export {};
@@ -0,0 +1,106 @@
1
+ import cn from 'classnames';
2
+ /* eslint-disable @typescript-eslint/no-explicit-any,consistent-return */
3
+
4
+ function setRef(ref, value) {
5
+ if (typeof ref === 'function') {
6
+ return ref(value);
7
+ } else if (ref !== null) {
8
+ ref.current = value;
9
+ }
10
+ }
11
+ /**
12
+ * Merges multiple refs into one. Works with either callback or object refs.
13
+ */
14
+
15
+
16
+ function mergeRefs() {
17
+ for (var _len = arguments.length, refs = new Array(_len), _key = 0; _key < _len; _key++) {
18
+ refs[_key] = arguments[_key];
19
+ }
20
+
21
+ if (refs.length === 1 && refs[0]) {
22
+ return refs[0];
23
+ }
24
+
25
+ return value => {
26
+ let hasCleanup = false;
27
+ const cleanups = refs.map(ref => {
28
+ const cleanup = setRef(ref, value);
29
+ hasCleanup = hasCleanup || typeof cleanup === 'function';
30
+ return cleanup;
31
+ });
32
+
33
+ if (hasCleanup) {
34
+ return () => {
35
+ cleanups.forEach((cleanup, i) => {
36
+ if (typeof cleanup === 'function') {
37
+ cleanup();
38
+ } else {
39
+ setRef(refs[i], null);
40
+ }
41
+ });
42
+ };
43
+ }
44
+ };
45
+ }
46
+
47
+ function chain() {
48
+ for (var _len2 = arguments.length, callbacks = new Array(_len2), _key2 = 0; _key2 < _len2; _key2++) {
49
+ callbacks[_key2] = arguments[_key2];
50
+ }
51
+
52
+ return function () {
53
+ for (const callback of callbacks) {
54
+ if (typeof callback === 'function') {
55
+ callback(...arguments);
56
+ }
57
+ }
58
+ };
59
+ }
60
+ /**
61
+ * Merges multiple props objects together. Event handlers are chained,
62
+ * classNames are combined, ids are deduplicated, and refs are merged.
63
+ * For all other props, the last prop object overrides all previous ones.
64
+ * @param args - Multiple sets of props to merge together.
65
+ */
66
+ // eslint-disable-next-line complexity
67
+
68
+
69
+ function mergeProps() {
70
+ // Start with a base clone of the first argument. This is a lot faster than starting
71
+ // with an empty object and adding properties as we go.
72
+ const result = { ...(arguments.length <= 0 ? undefined : arguments[0])
73
+ };
74
+
75
+ for (let i = 1; i < arguments.length; i++) {
76
+ const props = i < 0 || arguments.length <= i ? undefined : arguments[i];
77
+
78
+ for (const key in props) {
79
+ if (!props.hasOwnProperty(key)) {
80
+ continue;
81
+ }
82
+
83
+ const a = result[key];
84
+ const b = props[key]; // Chain events
85
+
86
+ if (typeof a === 'function' && typeof b === 'function' && // This is a lot faster than a regex.
87
+ key[0] === 'o' && key[1] === 'n' && key.charCodeAt(2) >=
88
+ /* 'A' */
89
+ 65 && key.charCodeAt(2) <=
90
+ /* 'Z' */
91
+ 90) {
92
+ result[key] = chain(a, b); // Merge classnames, sometimes classNames are empty string which eval to false, so we just need to do a type check
93
+ } else if (key === 'className' && typeof a === 'string' && typeof b === 'string') {
94
+ result[key] = cn(a, b);
95
+ } else if (key === 'ref' && a && b) {
96
+ result.ref = mergeRefs(a, b); // Override others
97
+ } else {
98
+ result[key] = b !== undefined ? b : a;
99
+ }
100
+ }
101
+ }
102
+
103
+ return result;
104
+ }
105
+
106
+ export { chain, mergeProps, mergeRefs };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rescui/select",
3
- "version": "0.15.1-RUI-280-Update-select-component-separate-components-e772abaa1.56+e772abaa1",
3
+ "version": "0.15.1-RUI-280-Update-select-component-downshift-cd2a98813.66+cd2a98813",
4
4
  "description": "",
5
5
  "license": "Apache-2.0",
6
6
  "author": "JetBrains",
@@ -16,25 +16,16 @@
16
16
  },
17
17
  "dependencies": {
18
18
  "@babel/runtime-corejs3": "^7.26.0",
19
- "@react-aria/button": "^3.15.0",
20
- "@react-aria/combobox": "^3.16.0",
21
19
  "@react-aria/focus": "^3.22.0",
22
- "@react-aria/interactions": "^3.28.0",
23
- "@react-aria/label": "^3.8.0",
24
- "@react-aria/listbox": "^3.16.0",
25
- "@react-aria/overlays": "^3.32.0",
26
- "@react-aria/select": "^3.18.0",
27
- "@react-aria/utils": "^3.34.0",
28
- "@react-stately/collections": "^3.13.0",
29
- "@react-stately/combobox": "^3.14.0",
30
- "@react-stately/list": "^3.14.0",
31
- "@react-stately/overlays": "^3.7.0",
32
- "@react-stately/select": "^3.10.0",
33
- "@react-types/shared": "^3.34.0",
34
- "@rescui/form-field": "0.1.1-RUI-280-Update-select-component-separate-components-e772abaa1.56+e772abaa1",
35
- "@rescui/tag": "0.13.5-RUI-280-Update-select-component-separate-components-e772abaa1.56+e772abaa1",
36
- "@rescui/use-resize-observer": "0.3.1-RUI-280-Update-select-component-separate-components-e772abaa1.168+e772abaa1",
37
- "classnames": "^2.2.6"
20
+ "@rescui/dropdown": "0.9.5-RUI-280-Update-select-component-downshift-cd2a98813.66+cd2a98813",
21
+ "@rescui/form-field": "0.1.1-RUI-280-Update-select-component-downshift-cd2a98813.66+cd2a98813",
22
+ "@rescui/tag": "0.13.5-RUI-280-Update-select-component-downshift-cd2a98813.66+cd2a98813",
23
+ "@rescui/use-resize-observer": "0.3.1-RUI-280-Update-select-component-downshift-cd2a98813.178+cd2a98813",
24
+ "classnames": "^2.2.6",
25
+ "downshift": "^9.3.2",
26
+ "react-aria": "^3.47.0",
27
+ "react-stately": "^3.45.0",
28
+ "scroll-into-view-if-needed": "3.1.0"
38
29
  },
39
30
  "peerDependencies": {
40
31
  "@rescui/ui-contexts": "^0.6.0",
@@ -42,9 +33,9 @@
42
33
  "react": ">=16.8.0 <20"
43
34
  },
44
35
  "devDependencies": {
45
- "@rescui/colors": "0.3.1-RUI-280-Update-select-component-separate-components-e772abaa1.56+e772abaa1",
36
+ "@rescui/colors": "0.3.1-RUI-280-Update-select-component-downshift-cd2a98813.66+cd2a98813",
46
37
  "@rescui/scripts": "0.5.1",
47
- "@rescui/typography": "0.24.5-RUI-280-Update-select-component-separate-components-e772abaa1.56+e772abaa1",
38
+ "@rescui/typography": "0.24.5-RUI-280-Update-select-component-downshift-cd2a98813.66+cd2a98813",
48
39
  "@rescui/visual-regression": "0.1.4",
49
40
  "sniffr": "^1.2.0"
50
41
  },
@@ -53,5 +44,5 @@
53
44
  "build-pcss-api": "rescui-scripts build-pcss-api --file public-api.p.css"
54
45
  },
55
46
  "nx": {},
56
- "gitHead": "e772abaa1615818504b1d498233bec348bcb7bb5"
47
+ "gitHead": "cd2a98813d37db8b46393317febfce4e91592516"
57
48
  }
@@ -1,14 +0,0 @@
1
- import React from 'react';
2
- import { type Theme } from '@rescui/ui-contexts';
3
- import type { SelectSize } from '../types';
4
- export declare type useCssContextTransferArgs = {
5
- triggerRef: React.RefObject<HTMLElement>;
6
- isOpen: boolean;
7
- themeFromProps: Theme;
8
- sizeFromProps: SelectSize;
9
- };
10
- export declare const useCssContextTransfer: ({ triggerRef, isOpen, themeFromProps, sizeFromProps }: useCssContextTransferArgs) => {
11
- size: SelectSize;
12
- theme: Theme;
13
- primaryColors: Record<string, string>;
14
- };
@@ -1,40 +0,0 @@
1
- import _includesInstanceProperty from "@babel/runtime-corejs3/core-js-stable/instance/includes";
2
- import { useContext } from 'react';
3
- import { ThemeContext } from '@rescui/ui-contexts';
4
- import { extractThemeFromCss, extractPrimaryColors } from '../utils/css-vars-utils.js';
5
-
6
- const useCssContextTransfer = _ref => {
7
- let {
8
- triggerRef,
9
- isOpen,
10
- themeFromProps,
11
- sizeFromProps
12
- } = _ref;
13
- let sizeFromCss = null;
14
- let themeFromCss = 'light';
15
- let primaryColors = {};
16
-
17
- if (triggerRef.current && isOpen) {
18
- var _context;
19
-
20
- const triggerFormWrapperStyles = getComputedStyle(triggerRef.current);
21
- const rawSizeFromCss = triggerFormWrapperStyles.getPropertyValue('--_rs-select-size');
22
- sizeFromCss = _includesInstanceProperty(_context = ['s', 'm', 'l']).call(_context, rawSizeFromCss) ? rawSizeFromCss : null;
23
- themeFromCss = extractThemeFromCss(triggerFormWrapperStyles);
24
- primaryColors = extractPrimaryColors(triggerFormWrapperStyles);
25
- }
26
-
27
- const size = sizeFromCss || sizeFromProps;
28
- const {
29
- theme: themeFromContext,
30
- noProvider
31
- } = useContext(ThemeContext);
32
- const theme = themeFromProps || (noProvider ? themeFromCss : themeFromContext);
33
- return {
34
- size,
35
- theme,
36
- primaryColors
37
- };
38
- };
39
-
40
- export { useCssContextTransfer };
@@ -1,10 +0,0 @@
1
- import type { SelectOption, SelectOptionOrGroup, Key } from '../types';
2
- export declare function useMultiOptionSerialization(options: SelectOptionOrGroup[], value?: SelectOption[] | null): {
3
- optionsMap: Map<Key, {
4
- option: SelectOption;
5
- isVirtual: boolean;
6
- }>;
7
- selectedKeys: Key[];
8
- findOptionsByKeys: (keys: Key[]) => SelectOption[];
9
- virtualOptions: SelectOption[];
10
- };
@@ -1,82 +0,0 @@
1
- import { useMemo } from 'react';
2
- import { isOptionAGroup } from '../utils/is-option-a-group.js';
3
- import { getOptionValue } from '../utils/get-option-value.js';
4
-
5
- function useMultiOptionSerialization(options, value) {
6
- // Create a map of keys to option objects for O(1) lookup
7
- const optionsMap = useMemo(() => {
8
- const map = new Map();
9
- options.forEach(item => {
10
- if (isOptionAGroup(item)) {
11
- item.options.forEach(option => {
12
- const key = getOptionValue(option);
13
- map.set(key, {
14
- option,
15
- isVirtual: false
16
- });
17
- });
18
- } else {
19
- const key = getOptionValue(item);
20
- map.set(key, {
21
- option: item,
22
- isVirtual: false
23
- });
24
- }
25
- });
26
-
27
- if (value && Array.isArray(value)) {
28
- value.forEach(option => {
29
- const key = getOptionValue(option);
30
-
31
- if (!map.has(key)) {
32
- map.set(key, {
33
- option,
34
- isVirtual: true
35
- });
36
- }
37
- });
38
- }
39
-
40
- return map;
41
- }, [options, value]); // Convert selected option objects array to Set of keys
42
-
43
- const selectedKeys = [];
44
- const virtualOptions = [];
45
-
46
- if (value && Array.isArray(value)) {
47
- value.forEach(option => {
48
- const key = getOptionValue(option);
49
- selectedKeys.push(key);
50
- const {
51
- isVirtual
52
- } = optionsMap.get(key);
53
-
54
- if (isVirtual) {
55
- virtualOptions.push(option);
56
- }
57
- });
58
- } // Helper function to find options by Set of keys
59
-
60
-
61
- const findOptionsByKeys = keys => {
62
- const foundOptions = [];
63
- keys.forEach(key => {
64
- if (optionsMap.has(key)) {
65
- const {
66
- option
67
- } = optionsMap.get(key);
68
- foundOptions.push(option);
69
- }
70
- });
71
- return foundOptions;
72
- };
73
-
74
- return {
75
- optionsMap,
76
- selectedKeys,
77
- findOptionsByKeys,
78
- virtualOptions
79
- };
80
- }
81
-
82
- export { useMultiOptionSerialization };
@@ -1,2 +0,0 @@
1
- /// <reference types="react" />
2
- export declare const useObservableForceRerender: () => import("react").MutableRefObject<HTMLDivElement>;
@@ -1,16 +0,0 @@
1
- import { useRef, useState } from 'react';
2
- import { useResizeObserver } from '@rescui/use-resize-observer';
3
-
4
- const useObservableForceRerender = () => {
5
- const observableRef = useRef(null);
6
- const [, setDummyState] = useState(false);
7
- useResizeObserver(observableRef, () => {
8
- //force rerender
9
- setDummyState(s => !s);
10
- }, {
11
- ignoreFirstCall: true
12
- });
13
- return observableRef;
14
- };
15
-
16
- export { useObservableForceRerender };
@@ -1,10 +0,0 @@
1
- import type { SelectOption, SelectOptionOrGroup, Key } from '../types';
2
- export declare function useOptionSerialization(options: SelectOptionOrGroup[], value?: SelectOption | null): {
3
- optionsMap: Map<Key, {
4
- option: SelectOption;
5
- isVirtual: boolean;
6
- }>;
7
- selectedKey: Key;
8
- findOptionByKey: (key: Key | null) => SelectOption | null;
9
- virtualOption: SelectOption;
10
- };
@@ -1,59 +0,0 @@
1
- import { useMemo } from 'react';
2
- import { isOptionAGroup } from '../utils/is-option-a-group.js';
3
- import { getOptionValue } from '../utils/get-option-value.js';
4
-
5
- function useOptionSerialization(options, value) {
6
- // Create a map of keys to option objects for O(1) lookup
7
- const optionsMap = useMemo(() => {
8
- const map = new Map();
9
- options.forEach(item => {
10
- if (isOptionAGroup(item)) {
11
- item.options.forEach(option => {
12
- const key = getOptionValue(option);
13
- map.set(key, {
14
- option,
15
- isVirtual: false
16
- });
17
- });
18
- } else {
19
- const key = getOptionValue(item);
20
- map.set(key, {
21
- option: item,
22
- isVirtual: false
23
- });
24
- }
25
- });
26
-
27
- if (value) {
28
- const key = getOptionValue(value);
29
-
30
- if (!map.has(key)) {
31
- map.set(key, {
32
- option: value,
33
- isVirtual: true
34
- });
35
- }
36
- }
37
-
38
- return map;
39
- }, [options, value]); // Convert selected option object to key
40
-
41
- const selectedKey = value ? getOptionValue(value) : null;
42
- const virtualOption = value && optionsMap.get(selectedKey).isVirtual ? value : null; // Helper function to find option by key
43
-
44
- const findOptionByKey = key => {
45
- var _optionsMap$get;
46
-
47
- if (key === null) return null;
48
- return ((_optionsMap$get = optionsMap.get(key)) === null || _optionsMap$get === void 0 ? void 0 : _optionsMap$get.option) || null;
49
- };
50
-
51
- return {
52
- optionsMap,
53
- selectedKey,
54
- findOptionByKey,
55
- virtualOption
56
- };
57
- }
58
-
59
- export { useOptionSerialization };
@@ -1,12 +0,0 @@
1
- import React from 'react';
2
- import type { OverlayTriggerState } from '@react-stately/overlays';
3
- import type { AriaPopoverProps } from '@react-aria/overlays';
4
- import type { SelectMode } from '../types';
5
- export interface PopoverProps extends Omit<AriaPopoverProps, 'popoverRef' | 'isNonModal'> {
6
- children: React.ReactNode;
7
- state: OverlayTriggerState;
8
- style?: React.CSSProperties;
9
- popoverRef?: React.RefObject<HTMLDivElement | null>;
10
- mode?: SelectMode;
11
- }
12
- export declare function Popover({ children, state, style, triggerRef, mode, ...props }: PopoverProps): JSX.Element;
@@ -1,64 +0,0 @@
1
- import React, { useRef } from 'react';
2
- import cn from 'classnames';
3
- import { usePopover, Overlay, DismissButton } from '@react-aria/overlays';
4
- import { useInteractOutside } from '@react-aria/interactions';
5
- import { mergeProps } from '@react-aria/utils';
6
- import styles from '../styles/popover.p.module.css.js';
7
- const MODE_STYLES = {
8
- classic: styles.classic,
9
- rock: styles.rock
10
- };
11
-
12
- function Popover(_ref) {
13
- let {
14
- children,
15
- state,
16
- style,
17
- triggerRef,
18
- mode,
19
- ...props
20
- } = _ref;
21
- const popoverRefLocal = useRef(null);
22
- const popoverRef = props.popoverRef ?? popoverRefLocal;
23
- const {
24
- popoverProps,
25
- placement: realPlacement
26
- } = usePopover({ ...props,
27
- offset: 8,
28
- popoverRef,
29
- triggerRef,
30
- isNonModal: true
31
- }, state);
32
- useInteractOutside({
33
- ref: popoverRef,
34
- onInteractOutside: state.close
35
- });
36
-
37
- const handleKeyDown = e => {
38
- // Block default browser behavior for arrow keys
39
- // This will prevent the page from scrolling when we focus on the edges of the list.
40
- // Relevant only for useSelect usage
41
- if (e.key === 'ArrowDown' || e.key === 'ArrowUp') {
42
- e.preventDefault();
43
- }
44
- };
45
-
46
- return /*#__PURE__*/React.createElement(Overlay, null, /*#__PURE__*/React.createElement("div", { ...mergeProps(popoverProps, {
47
- onKeyDown: handleKeyDown
48
- }),
49
- ref: popoverRef,
50
- className: cn(styles.popover, MODE_STYLES[mode]),
51
- style: { ...popoverProps.style,
52
- ...style
53
- },
54
- "data-popover-placement": realPlacement
55
- }, /*#__PURE__*/React.createElement(DismissButton, {
56
- onDismiss: state.close
57
- }), /*#__PURE__*/React.createElement("div", {
58
- className: styles.contentWrapper
59
- }, children), /*#__PURE__*/React.createElement(DismissButton, {
60
- onDismiss: state.close
61
- })));
62
- }
63
-
64
- export { Popover };
@@ -1,19 +0,0 @@
1
- import React from 'react';
2
- import type { AriaListBoxOptions } from '@react-aria/listbox';
3
- import type { Theme } from '@rescui/ui-contexts';
4
- import type { CommonState, SelectMode, SelectSize, AriaPlacement } from '../types';
5
- export declare type PopupContentProps<T extends object> = {
6
- theme: Theme;
7
- state: CommonState<T>;
8
- triggerRef: React.RefObject<HTMLElement>;
9
- popoverRef?: React.RefObject<HTMLDivElement>;
10
- listBoxRef?: React.RefObject<HTMLUListElement>;
11
- placement: AriaPlacement;
12
- size?: SelectSize;
13
- mode?: SelectMode;
14
- listBoxProps: AriaListBoxOptions<T>;
15
- emptyListMessage: string;
16
- maxVisibleItems?: number;
17
- selectionMode?: 'single' | 'multiple';
18
- };
19
- export declare const PopupContent: <T extends object>({ theme: themeFromProps, state, triggerRef, popoverRef, listBoxRef, placement, size: sizeFromProps, mode, listBoxProps, emptyListMessage, maxVisibleItems, selectionMode }: PopupContentProps<T>) => JSX.Element;