@atlaskit/react-select 0.0.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.
Files changed (197) hide show
  1. package/CHANGELOG.md +9 -0
  2. package/LICENSE.md +11 -0
  3. package/README.md +10 -0
  4. package/async/package.json +15 -0
  5. package/base/package.json +15 -0
  6. package/creatable/package.json +15 -0
  7. package/dist/cjs/accessibility/helpers.js +34 -0
  8. package/dist/cjs/accessibility/index.js +74 -0
  9. package/dist/cjs/async-creatable.js +27 -0
  10. package/dist/cjs/async.js +30 -0
  11. package/dist/cjs/builtins.js +18 -0
  12. package/dist/cjs/components/containers.js +100 -0
  13. package/dist/cjs/components/control.js +67 -0
  14. package/dist/cjs/components/group.js +79 -0
  15. package/dist/cjs/components/index.js +53 -0
  16. package/dist/cjs/components/indicators.js +214 -0
  17. package/dist/cjs/components/input.js +93 -0
  18. package/dist/cjs/components/internal/a11y-text.js +34 -0
  19. package/dist/cjs/components/internal/dummy-input.js +43 -0
  20. package/dist/cjs/components/internal/index.js +34 -0
  21. package/dist/cjs/components/internal/required-input.js +43 -0
  22. package/dist/cjs/components/internal/scroll-manager.js +57 -0
  23. package/dist/cjs/components/internal/use-scroll-capture.js +132 -0
  24. package/dist/cjs/components/internal/use-scroll-lock.js +149 -0
  25. package/dist/cjs/components/live-region.js +153 -0
  26. package/dist/cjs/components/menu.js +464 -0
  27. package/dist/cjs/components/multi-value.js +129 -0
  28. package/dist/cjs/components/option.js +62 -0
  29. package/dist/cjs/components/placeholder.js +39 -0
  30. package/dist/cjs/components/single-value.js +46 -0
  31. package/dist/cjs/creatable.js +30 -0
  32. package/dist/cjs/diacritics.js +274 -0
  33. package/dist/cjs/filters.js +50 -0
  34. package/dist/cjs/index.js +55 -0
  35. package/dist/cjs/nonce-provider.js +30 -0
  36. package/dist/cjs/select.js +1803 -0
  37. package/dist/cjs/state-manager.js +31 -0
  38. package/dist/cjs/styles.js +66 -0
  39. package/dist/cjs/theme.js +42 -0
  40. package/dist/cjs/types.js +5 -0
  41. package/dist/cjs/use-async.js +156 -0
  42. package/dist/cjs/use-creatable.js +114 -0
  43. package/dist/cjs/use-state-manager.js +83 -0
  44. package/dist/cjs/utils.js +357 -0
  45. package/dist/es2019/accessibility/helpers.js +24 -0
  46. package/dist/es2019/accessibility/index.js +72 -0
  47. package/dist/es2019/async-creatable.js +17 -0
  48. package/dist/es2019/async.js +16 -0
  49. package/dist/es2019/builtins.js +4 -0
  50. package/dist/es2019/components/containers.js +100 -0
  51. package/dist/es2019/components/control.js +62 -0
  52. package/dist/es2019/components/group.js +74 -0
  53. package/dist/es2019/components/index.js +41 -0
  54. package/dist/es2019/components/indicators.js +211 -0
  55. package/dist/es2019/components/input.js +88 -0
  56. package/dist/es2019/components/internal/a11y-text.js +25 -0
  57. package/dist/es2019/components/internal/dummy-input.js +36 -0
  58. package/dist/es2019/components/internal/index.js +4 -0
  59. package/dist/es2019/components/internal/required-input.js +35 -0
  60. package/dist/es2019/components/internal/scroll-manager.js +49 -0
  61. package/dist/es2019/components/internal/use-scroll-capture.js +128 -0
  62. package/dist/es2019/components/internal/use-scroll-lock.js +143 -0
  63. package/dist/es2019/components/live-region.js +151 -0
  64. package/dist/es2019/components/menu.js +466 -0
  65. package/dist/es2019/components/multi-value.js +134 -0
  66. package/dist/es2019/components/option.js +57 -0
  67. package/dist/es2019/components/placeholder.js +34 -0
  68. package/dist/es2019/components/single-value.js +41 -0
  69. package/dist/es2019/creatable.js +15 -0
  70. package/dist/es2019/diacritics.js +264 -0
  71. package/dist/es2019/filters.js +36 -0
  72. package/dist/es2019/index.js +8 -0
  73. package/dist/es2019/nonce-provider.js +19 -0
  74. package/dist/es2019/select.js +1766 -0
  75. package/dist/es2019/state-manager.js +22 -0
  76. package/dist/es2019/styles.js +56 -0
  77. package/dist/es2019/theme.js +36 -0
  78. package/dist/es2019/types.js +1 -0
  79. package/dist/es2019/use-async.js +117 -0
  80. package/dist/es2019/use-creatable.js +81 -0
  81. package/dist/es2019/use-state-manager.js +60 -0
  82. package/dist/es2019/utils.js +309 -0
  83. package/dist/esm/accessibility/helpers.js +24 -0
  84. package/dist/esm/accessibility/index.js +68 -0
  85. package/dist/esm/async-creatable.js +17 -0
  86. package/dist/esm/async.js +16 -0
  87. package/dist/esm/builtins.js +12 -0
  88. package/dist/esm/components/containers.js +96 -0
  89. package/dist/esm/components/control.js +62 -0
  90. package/dist/esm/components/group.js +74 -0
  91. package/dist/esm/components/index.js +43 -0
  92. package/dist/esm/components/indicators.js +209 -0
  93. package/dist/esm/components/input.js +88 -0
  94. package/dist/esm/components/internal/a11y-text.js +27 -0
  95. package/dist/esm/components/internal/dummy-input.js +37 -0
  96. package/dist/esm/components/internal/index.js +4 -0
  97. package/dist/esm/components/internal/required-input.js +36 -0
  98. package/dist/esm/components/internal/scroll-manager.js +49 -0
  99. package/dist/esm/components/internal/use-scroll-capture.js +126 -0
  100. package/dist/esm/components/internal/use-scroll-lock.js +143 -0
  101. package/dist/esm/components/live-region.js +148 -0
  102. package/dist/esm/components/menu.js +460 -0
  103. package/dist/esm/components/multi-value.js +122 -0
  104. package/dist/esm/components/option.js +57 -0
  105. package/dist/esm/components/placeholder.js +34 -0
  106. package/dist/esm/components/single-value.js +41 -0
  107. package/dist/esm/creatable.js +15 -0
  108. package/dist/esm/diacritics.js +268 -0
  109. package/dist/esm/filters.js +43 -0
  110. package/dist/esm/index.js +8 -0
  111. package/dist/esm/nonce-provider.js +20 -0
  112. package/dist/esm/select.js +1794 -0
  113. package/dist/esm/state-manager.js +22 -0
  114. package/dist/esm/styles.js +58 -0
  115. package/dist/esm/theme.js +36 -0
  116. package/dist/esm/types.js +1 -0
  117. package/dist/esm/use-async.js +149 -0
  118. package/dist/esm/use-creatable.js +107 -0
  119. package/dist/esm/use-state-manager.js +76 -0
  120. package/dist/esm/utils.js +328 -0
  121. package/dist/types/accessibility/helpers.d.ts +5 -0
  122. package/dist/types/accessibility/index.d.ts +125 -0
  123. package/dist/types/async-creatable.d.ts +10 -0
  124. package/dist/types/async.d.ts +9 -0
  125. package/dist/types/builtins.d.ts +5 -0
  126. package/dist/types/components/containers.d.ts +50 -0
  127. package/dist/types/components/control.d.ts +33 -0
  128. package/dist/types/components/group.d.ts +53 -0
  129. package/dist/types/components/index.d.ts +73 -0
  130. package/dist/types/components/indicators.d.ts +72 -0
  131. package/dist/types/components/input.d.ts +33 -0
  132. package/dist/types/components/internal/a11y-text.d.ts +8 -0
  133. package/dist/types/components/internal/dummy-input.d.ts +9 -0
  134. package/dist/types/components/internal/index.d.ts +4 -0
  135. package/dist/types/components/internal/required-input.d.ts +10 -0
  136. package/dist/types/components/internal/scroll-manager.d.ts +17 -0
  137. package/dist/types/components/internal/use-scroll-capture.d.ts +12 -0
  138. package/dist/types/components/internal/use-scroll-lock.d.ts +9 -0
  139. package/dist/types/components/live-region.d.ts +24 -0
  140. package/dist/types/components/menu.d.ts +130 -0
  141. package/dist/types/components/multi-value.d.ts +47 -0
  142. package/dist/types/components/option.d.ts +49 -0
  143. package/dist/types/components/placeholder.d.ts +22 -0
  144. package/dist/types/components/single-value.d.ts +28 -0
  145. package/dist/types/creatable.d.ts +10 -0
  146. package/dist/types/diacritics.d.ts +1 -0
  147. package/dist/types/filters.d.ts +15 -0
  148. package/dist/types/index.d.ts +28 -0
  149. package/dist/types/nonce-provider.d.ts +8 -0
  150. package/dist/types/select.d.ts +616 -0
  151. package/dist/types/state-manager.d.ts +17 -0
  152. package/dist/types/styles.d.ts +68 -0
  153. package/dist/types/theme.d.ts +27 -0
  154. package/dist/types/types.d.ts +134 -0
  155. package/dist/types/use-async.d.ts +31 -0
  156. package/dist/types/use-creatable.d.ts +46 -0
  157. package/dist/types/use-state-manager.d.ts +15 -0
  158. package/dist/types/utils.d.ts +44 -0
  159. package/dist/types-ts4.5/accessibility/helpers.d.ts +5 -0
  160. package/dist/types-ts4.5/accessibility/index.d.ts +125 -0
  161. package/dist/types-ts4.5/async-creatable.d.ts +10 -0
  162. package/dist/types-ts4.5/async.d.ts +9 -0
  163. package/dist/types-ts4.5/builtins.d.ts +5 -0
  164. package/dist/types-ts4.5/components/containers.d.ts +50 -0
  165. package/dist/types-ts4.5/components/control.d.ts +33 -0
  166. package/dist/types-ts4.5/components/group.d.ts +53 -0
  167. package/dist/types-ts4.5/components/index.d.ts +73 -0
  168. package/dist/types-ts4.5/components/indicators.d.ts +72 -0
  169. package/dist/types-ts4.5/components/input.d.ts +33 -0
  170. package/dist/types-ts4.5/components/internal/a11y-text.d.ts +8 -0
  171. package/dist/types-ts4.5/components/internal/dummy-input.d.ts +9 -0
  172. package/dist/types-ts4.5/components/internal/index.d.ts +4 -0
  173. package/dist/types-ts4.5/components/internal/required-input.d.ts +10 -0
  174. package/dist/types-ts4.5/components/internal/scroll-manager.d.ts +17 -0
  175. package/dist/types-ts4.5/components/internal/use-scroll-capture.d.ts +12 -0
  176. package/dist/types-ts4.5/components/internal/use-scroll-lock.d.ts +9 -0
  177. package/dist/types-ts4.5/components/live-region.d.ts +24 -0
  178. package/dist/types-ts4.5/components/menu.d.ts +130 -0
  179. package/dist/types-ts4.5/components/multi-value.d.ts +47 -0
  180. package/dist/types-ts4.5/components/option.d.ts +49 -0
  181. package/dist/types-ts4.5/components/placeholder.d.ts +22 -0
  182. package/dist/types-ts4.5/components/single-value.d.ts +28 -0
  183. package/dist/types-ts4.5/creatable.d.ts +10 -0
  184. package/dist/types-ts4.5/diacritics.d.ts +1 -0
  185. package/dist/types-ts4.5/filters.d.ts +15 -0
  186. package/dist/types-ts4.5/index.d.ts +28 -0
  187. package/dist/types-ts4.5/nonce-provider.d.ts +8 -0
  188. package/dist/types-ts4.5/select.d.ts +616 -0
  189. package/dist/types-ts4.5/state-manager.d.ts +17 -0
  190. package/dist/types-ts4.5/styles.d.ts +68 -0
  191. package/dist/types-ts4.5/theme.d.ts +27 -0
  192. package/dist/types-ts4.5/types.d.ts +134 -0
  193. package/dist/types-ts4.5/use-async.d.ts +31 -0
  194. package/dist/types-ts4.5/use-creatable.d.ts +46 -0
  195. package/dist/types-ts4.5/use-state-manager.d.ts +15 -0
  196. package/dist/types-ts4.5/utils.d.ts +44 -0
  197. package/package.json +83 -0
@@ -0,0 +1,22 @@
1
+ import _extends from "@babel/runtime/helpers/extends";
2
+ import React, { forwardRef } from 'react';
3
+ import Select from './select';
4
+ import useStateManager from './use-state-manager';
5
+
6
+ /**
7
+ * __StateManagedSelect__
8
+ *
9
+ * A state managed select {description}.
10
+ *
11
+ * - [Examples](https://atlassian.design/components/{packageName}/examples)
12
+ * - [Code](https://atlassian.design/components/{packageName}/code)
13
+ * - [Usage](https://atlassian.design/components/{packageName}/usage)
14
+ */
15
+
16
+ const StateManagedSelect = /*#__PURE__*/forwardRef((props, ref) => {
17
+ const baseSelectProps = useStateManager(props);
18
+ return /*#__PURE__*/React.createElement(Select, _extends({
19
+ ref: ref
20
+ }, baseSelectProps));
21
+ });
22
+ export default StateManagedSelect;
@@ -0,0 +1,56 @@
1
+ import { containerCSS, indicatorsContainerCSS, valueContainerCSS } from './components/containers';
2
+ import { css as controlCSS } from './components/control';
3
+ import { groupCSS, groupHeadingCSS } from './components/group';
4
+ import { clearIndicatorCSS, dropdownIndicatorCSS, indicatorSeparatorCSS, loadingIndicatorCSS } from './components/indicators';
5
+ import { inputCSS } from './components/input';
6
+ import { loadingMessageCSS, menuCSS, menuListCSS, menuPortalCSS, noOptionsMessageCSS } from './components/menu';
7
+ import { multiValueCSS, multiValueLabelCSS, multiValueRemoveCSS } from './components/multi-value';
8
+ import { optionCSS } from './components/option';
9
+ import { placeholderCSS } from './components/placeholder';
10
+ import { css as singleValueCSS } from './components/single-value';
11
+ export const defaultStyles = {
12
+ clearIndicator: clearIndicatorCSS,
13
+ container: containerCSS,
14
+ control: controlCSS,
15
+ dropdownIndicator: dropdownIndicatorCSS,
16
+ group: groupCSS,
17
+ groupHeading: groupHeadingCSS,
18
+ indicatorsContainer: indicatorsContainerCSS,
19
+ indicatorSeparator: indicatorSeparatorCSS,
20
+ input: inputCSS,
21
+ loadingIndicator: loadingIndicatorCSS,
22
+ loadingMessage: loadingMessageCSS,
23
+ menu: menuCSS,
24
+ menuList: menuListCSS,
25
+ menuPortal: menuPortalCSS,
26
+ multiValue: multiValueCSS,
27
+ multiValueLabel: multiValueLabelCSS,
28
+ multiValueRemove: multiValueRemoveCSS,
29
+ noOptionsMessage: noOptionsMessageCSS,
30
+ option: optionCSS,
31
+ placeholder: placeholderCSS,
32
+ singleValue: singleValueCSS,
33
+ valueContainer: valueContainerCSS
34
+ };
35
+ // Merge Utility
36
+ // Allows consumers to extend a base Select with additional styles
37
+
38
+ export function mergeStyles(source, target = {}) {
39
+ // initialize with source styles
40
+ const styles = {
41
+ ...source
42
+ };
43
+
44
+ // massage in target styles
45
+ Object.keys(target).forEach(keyAsString => {
46
+ const key = keyAsString;
47
+ if (source[key]) {
48
+ styles[key] = (rsCss, props) => {
49
+ return target[key](source[key](rsCss, props), props);
50
+ };
51
+ } else {
52
+ styles[key] = target[key];
53
+ }
54
+ });
55
+ return styles;
56
+ }
@@ -0,0 +1,36 @@
1
+ export const colors = {
2
+ primary: '#2684FF',
3
+ primary75: '#4C9AFF',
4
+ primary50: '#B2D4FF',
5
+ primary25: '#DEEBFF',
6
+ danger: '#DE350B',
7
+ dangerLight: '#FFBDAD',
8
+ neutral0: 'hsl(0, 0%, 100%)',
9
+ neutral5: 'hsl(0, 0%, 95%)',
10
+ neutral10: 'hsl(0, 0%, 90%)',
11
+ neutral20: 'hsl(0, 0%, 80%)',
12
+ neutral30: 'hsl(0, 0%, 70%)',
13
+ neutral40: 'hsl(0, 0%, 60%)',
14
+ neutral50: 'hsl(0, 0%, 50%)',
15
+ neutral60: 'hsl(0, 0%, 40%)',
16
+ neutral70: 'hsl(0, 0%, 30%)',
17
+ neutral80: 'hsl(0, 0%, 20%)',
18
+ neutral90: 'hsl(0, 0%, 10%)'
19
+ };
20
+ const borderRadius = 4;
21
+ // Used to calculate consistent margin/padding on elements
22
+ const baseUnit = 4;
23
+ // The minimum height of the control
24
+ const controlHeight = 38;
25
+ // The amount of space between the control and menu */
26
+ const menuGutter = baseUnit * 2;
27
+ export const spacing = {
28
+ baseUnit,
29
+ controlHeight,
30
+ menuGutter
31
+ };
32
+ export const defaultTheme = {
33
+ borderRadius,
34
+ colors,
35
+ spacing
36
+ };
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,117 @@
1
+ import { useCallback, useEffect, useRef, useState } from 'react';
2
+ import { handleInputChange } from './utils';
3
+ // TODO: Fill in the hook {description}.
4
+ /**
5
+ * {description}.
6
+ */
7
+ export default function useAsync({
8
+ defaultOptions: propsDefaultOptions = false,
9
+ cacheOptions = false,
10
+ loadOptions: propsLoadOptions,
11
+ options: propsOptions,
12
+ isLoading: propsIsLoading = false,
13
+ onInputChange: propsOnInputChange,
14
+ filterOption = null,
15
+ ...restSelectProps
16
+ }) {
17
+ const {
18
+ inputValue: propsInputValue
19
+ } = restSelectProps;
20
+ const lastRequest = useRef(undefined);
21
+ const mounted = useRef(false);
22
+ const [defaultOptions, setDefaultOptions] = useState(Array.isArray(propsDefaultOptions) ? propsDefaultOptions : undefined);
23
+ const [stateInputValue, setStateInputValue] = useState(typeof propsInputValue !== 'undefined' ? propsInputValue : '');
24
+ const [isLoading, setIsLoading] = useState(propsDefaultOptions === true);
25
+ const [loadedInputValue, setLoadedInputValue] = useState(undefined);
26
+ const [loadedOptions, setLoadedOptions] = useState([]);
27
+ const [passEmptyOptions, setPassEmptyOptions] = useState(false);
28
+ const [optionsCache, setOptionsCache] = useState({});
29
+ const [prevDefaultOptions, setPrevDefaultOptions] = useState(undefined);
30
+ const [prevCacheOptions, setPrevCacheOptions] = useState(undefined);
31
+ if (cacheOptions !== prevCacheOptions) {
32
+ setOptionsCache({});
33
+ setPrevCacheOptions(cacheOptions);
34
+ }
35
+ if (propsDefaultOptions !== prevDefaultOptions) {
36
+ setDefaultOptions(Array.isArray(propsDefaultOptions) ? propsDefaultOptions : undefined);
37
+ setPrevDefaultOptions(propsDefaultOptions);
38
+ }
39
+ useEffect(() => {
40
+ mounted.current = true;
41
+ return () => {
42
+ mounted.current = false;
43
+ };
44
+ }, []);
45
+ const loadOptions = useCallback((inputValue, callback) => {
46
+ if (!propsLoadOptions) {
47
+ return callback();
48
+ }
49
+ const loader = propsLoadOptions(inputValue, callback);
50
+ if (loader && typeof loader.then === 'function') {
51
+ loader.then(callback, () => callback());
52
+ }
53
+ }, [propsLoadOptions]);
54
+ useEffect(() => {
55
+ if (propsDefaultOptions === true) {
56
+ loadOptions(stateInputValue, options => {
57
+ if (!mounted.current) {
58
+ return;
59
+ }
60
+ setDefaultOptions(options || []);
61
+ setIsLoading(!!lastRequest.current);
62
+ });
63
+ }
64
+ // NOTE: this effect is designed to only run when the component mounts,
65
+ // so we don't want to include any hook dependencies
66
+ // eslint-disable-next-line react-hooks/exhaustive-deps
67
+ }, []);
68
+ const onInputChange = useCallback((newValue, actionMeta) => {
69
+ const inputValue = handleInputChange(newValue, actionMeta, propsOnInputChange);
70
+ if (!inputValue) {
71
+ lastRequest.current = undefined;
72
+ setStateInputValue('');
73
+ setLoadedInputValue('');
74
+ setLoadedOptions([]);
75
+ setIsLoading(false);
76
+ setPassEmptyOptions(false);
77
+ return;
78
+ }
79
+ if (cacheOptions && optionsCache[inputValue]) {
80
+ setStateInputValue(inputValue);
81
+ setLoadedInputValue(inputValue);
82
+ setLoadedOptions(optionsCache[inputValue]);
83
+ setIsLoading(false);
84
+ setPassEmptyOptions(false);
85
+ } else {
86
+ const request = lastRequest.current = {};
87
+ setStateInputValue(inputValue);
88
+ setIsLoading(true);
89
+ setPassEmptyOptions(!loadedInputValue);
90
+ loadOptions(inputValue, options => {
91
+ if (!mounted) {
92
+ return;
93
+ }
94
+ if (request !== lastRequest.current) {
95
+ return;
96
+ }
97
+ lastRequest.current = undefined;
98
+ setIsLoading(false);
99
+ setLoadedInputValue(inputValue);
100
+ setLoadedOptions(options || []);
101
+ setPassEmptyOptions(false);
102
+ setOptionsCache(options ? {
103
+ ...optionsCache,
104
+ [inputValue]: options
105
+ } : optionsCache);
106
+ });
107
+ }
108
+ }, [cacheOptions, loadOptions, loadedInputValue, optionsCache, propsOnInputChange]);
109
+ const options = passEmptyOptions ? [] : stateInputValue && loadedInputValue ? loadedOptions : defaultOptions || [];
110
+ return {
111
+ ...restSelectProps,
112
+ options,
113
+ isLoading: isLoading || propsIsLoading,
114
+ onInputChange,
115
+ filterOption
116
+ };
117
+ }
@@ -0,0 +1,81 @@
1
+ import { useCallback, useMemo } from 'react';
2
+ import { getOptionLabel as baseGetOptionLabel, getOptionValue as baseGetOptionValue } from './builtins';
3
+ import { cleanValue, valueTernary } from './utils';
4
+ const compareOption = (inputValue = '', option, accessors) => {
5
+ const candidate = String(inputValue).toLowerCase();
6
+ const optionValue = String(accessors.getOptionValue(option)).toLowerCase();
7
+ const optionLabel = String(accessors.getOptionLabel(option)).toLowerCase();
8
+ return optionValue === candidate || optionLabel === candidate;
9
+ };
10
+ const builtins = {
11
+ formatCreateLabel: inputValue => `Create "${inputValue}"`,
12
+ isValidNewOption: (inputValue, selectValue, selectOptions, accessors) => !(!inputValue || selectValue.some(option => compareOption(inputValue, option, accessors)) || selectOptions.some(option => compareOption(inputValue, option, accessors))),
13
+ getNewOptionData: (inputValue, optionLabel) => ({
14
+ label: optionLabel,
15
+ value: inputValue,
16
+ __isNew__: true
17
+ })
18
+ };
19
+
20
+ // TODO: Fill in the hook {description}.
21
+ /**
22
+ * {description}.
23
+ */
24
+ export default function useCreatable({
25
+ allowCreateWhileLoading = false,
26
+ createOptionPosition = 'last',
27
+ formatCreateLabel = builtins.formatCreateLabel,
28
+ //@ts-ignore
29
+ isValidNewOption = builtins.isValidNewOption,
30
+ //@ts-ignore
31
+ getNewOptionData = builtins.getNewOptionData,
32
+ onCreateOption,
33
+ options: propsOptions = [],
34
+ onChange: propsOnChange,
35
+ ...restSelectProps
36
+ }) {
37
+ const {
38
+ getOptionValue = baseGetOptionValue,
39
+ getOptionLabel = baseGetOptionLabel,
40
+ inputValue,
41
+ isLoading,
42
+ isMulti,
43
+ value,
44
+ name
45
+ } = restSelectProps;
46
+ const newOption = useMemo(() =>
47
+ //@ts-ignore
48
+ isValidNewOption(inputValue, cleanValue(value), propsOptions, {
49
+ getOptionValue,
50
+ getOptionLabel
51
+ }) ? getNewOptionData(inputValue, formatCreateLabel(inputValue)) : undefined, [formatCreateLabel, getNewOptionData, getOptionLabel, getOptionValue, inputValue, isValidNewOption, propsOptions, value]);
52
+ const options = useMemo(() => (allowCreateWhileLoading || !isLoading) && newOption ? createOptionPosition === 'first' ? [newOption, ...propsOptions] : [...propsOptions, newOption] : propsOptions, [allowCreateWhileLoading, createOptionPosition, isLoading, newOption, propsOptions]);
53
+ const onChange = useCallback((newValue, actionMeta) => {
54
+ if (actionMeta.action !== 'select-option') {
55
+ return propsOnChange(newValue, actionMeta);
56
+ }
57
+ const valueArray = Array.isArray(newValue) ? newValue : [newValue];
58
+ if (valueArray[valueArray.length - 1] === newOption) {
59
+ if (onCreateOption) {
60
+ onCreateOption(inputValue);
61
+ } else {
62
+ const newOptionData = getNewOptionData(inputValue, inputValue);
63
+ const newActionMeta = {
64
+ action: 'create-option',
65
+ name,
66
+ option: newOptionData
67
+ };
68
+ propsOnChange(
69
+ //@ts-ignore
70
+ valueTernary(isMulti, [...cleanValue(value), newOptionData], newOptionData), newActionMeta);
71
+ }
72
+ return;
73
+ }
74
+ propsOnChange(newValue, actionMeta);
75
+ }, [getNewOptionData, inputValue, isMulti, name, newOption, onCreateOption, propsOnChange, value]);
76
+ return {
77
+ ...restSelectProps,
78
+ options,
79
+ onChange
80
+ };
81
+ }
@@ -0,0 +1,60 @@
1
+ import { useCallback, useState } from 'react';
2
+ // TODO: Fill in the hook {description}.
3
+ /**
4
+ * {description}.
5
+ */
6
+ export default function useStateManager({
7
+ defaultInputValue = '',
8
+ defaultMenuIsOpen = false,
9
+ defaultValue = null,
10
+ inputValue: propsInputValue,
11
+ menuIsOpen: propsMenuIsOpen,
12
+ onChange: propsOnChange,
13
+ onInputChange: propsOnInputChange,
14
+ onMenuClose: propsOnMenuClose,
15
+ onMenuOpen: propsOnMenuOpen,
16
+ value: propsValue,
17
+ ...restSelectProps
18
+ }) {
19
+ const [stateInputValue, setStateInputValue] = useState(propsInputValue !== undefined ? propsInputValue : defaultInputValue);
20
+ const [stateMenuIsOpen, setStateMenuIsOpen] = useState(propsMenuIsOpen !== undefined ? propsMenuIsOpen : defaultMenuIsOpen);
21
+ const [stateValue, setStateValue] = useState(propsValue !== undefined ? propsValue : defaultValue);
22
+ const onChange = useCallback((value, actionMeta) => {
23
+ if (typeof propsOnChange === 'function') {
24
+ propsOnChange(value, actionMeta);
25
+ }
26
+ setStateValue(value);
27
+ }, [propsOnChange]);
28
+ const onInputChange = useCallback((value, actionMeta) => {
29
+ let newValue;
30
+ if (typeof propsOnInputChange === 'function') {
31
+ newValue = propsOnInputChange(value, actionMeta);
32
+ }
33
+ setStateInputValue(newValue !== undefined ? newValue : value);
34
+ }, [propsOnInputChange]);
35
+ const onMenuOpen = useCallback(() => {
36
+ if (typeof propsOnMenuOpen === 'function') {
37
+ propsOnMenuOpen();
38
+ }
39
+ setStateMenuIsOpen(true);
40
+ }, [propsOnMenuOpen]);
41
+ const onMenuClose = useCallback(() => {
42
+ if (typeof propsOnMenuClose === 'function') {
43
+ propsOnMenuClose();
44
+ }
45
+ setStateMenuIsOpen(false);
46
+ }, [propsOnMenuClose]);
47
+ const inputValue = propsInputValue !== undefined ? propsInputValue : stateInputValue;
48
+ const menuIsOpen = propsMenuIsOpen !== undefined ? propsMenuIsOpen : stateMenuIsOpen;
49
+ const value = propsValue !== undefined ? propsValue : stateValue;
50
+ return {
51
+ ...restSelectProps,
52
+ inputValue,
53
+ menuIsOpen,
54
+ onChange,
55
+ onInputChange,
56
+ onMenuClose,
57
+ onMenuOpen,
58
+ value
59
+ };
60
+ }
@@ -0,0 +1,309 @@
1
+ // ==============================
2
+ // NO OP
3
+ // ==============================
4
+
5
+ export const noop = () => {};
6
+ export const emptyString = () => '';
7
+
8
+ // ==============================
9
+ // Class Name Prefixer
10
+ // ==============================
11
+
12
+ /**
13
+ * String representation of component state for styling with class names.
14
+ *
15
+ * Expects an array of strings OR a string/object pair:
16
+ * - className(['comp', 'comp-arg', 'comp-arg-2'])
17
+ * @returns 'react-select__comp react-select__comp-arg react-select__comp-arg-2'
18
+ * - className('comp', { some: true, state: false })
19
+ * @returns 'react-select__comp react-select__comp--some'
20
+ */
21
+ function applyPrefixToName(prefix, name) {
22
+ if (!name) {
23
+ return prefix;
24
+ } else if (name[0] === '-') {
25
+ return prefix + name;
26
+ } else {
27
+ return prefix + '__' + name;
28
+ }
29
+ }
30
+ export function classNames(prefix, state, ...classNameList) {
31
+ const arr = [...classNameList];
32
+ if (state && prefix) {
33
+ for (let key in state) {
34
+ if (state.hasOwnProperty(key) && state[key]) {
35
+ arr.push(`${applyPrefixToName(prefix, key)}`);
36
+ }
37
+ }
38
+ }
39
+ return arr.filter(i => i).map(i => String(i).trim()).join(' ');
40
+ }
41
+ // ==============================
42
+ // Clean Value
43
+ // ==============================
44
+
45
+ export const cleanValue = value => {
46
+ if (isArray(value)) {
47
+ return value.filter(Boolean);
48
+ }
49
+ if (typeof value === 'object' && value !== null) {
50
+ return [value];
51
+ }
52
+ return [];
53
+ };
54
+
55
+ // ==============================
56
+ // Clean Common Props
57
+ // ==============================
58
+
59
+ export const cleanCommonProps = props => {
60
+ //className
61
+ const {
62
+ className,
63
+ // not listed in commonProps documentation, needs to be removed to allow Emotion to generate classNames
64
+ clearValue,
65
+ cx,
66
+ getStyles,
67
+ getClassNames,
68
+ getValue,
69
+ hasValue,
70
+ isMulti,
71
+ isRtl,
72
+ options,
73
+ // not listed in commonProps documentation
74
+ selectOption,
75
+ selectProps,
76
+ setValue,
77
+ theme,
78
+ // not listed in commonProps documentation
79
+ ...innerProps
80
+ } = props;
81
+ return {
82
+ ...innerProps
83
+ };
84
+ };
85
+
86
+ // ==============================
87
+ // Get Style Props
88
+ // ==============================
89
+
90
+ export const getStyleProps = (props, name, classNamesState) => {
91
+ const {
92
+ cx,
93
+ getStyles,
94
+ getClassNames,
95
+ className
96
+ } = props;
97
+ return {
98
+ css: getStyles(name, props),
99
+ className: cx(classNamesState !== null && classNamesState !== void 0 ? classNamesState : {}, getClassNames(name, props), className)
100
+ };
101
+ };
102
+
103
+ // ==============================
104
+ // Handle Input Change
105
+ // ==============================
106
+
107
+ export function handleInputChange(inputValue, actionMeta, onInputChange) {
108
+ if (onInputChange) {
109
+ const newValue = onInputChange(inputValue, actionMeta);
110
+ if (typeof newValue === 'string') {
111
+ return newValue;
112
+ }
113
+ }
114
+ return inputValue;
115
+ }
116
+
117
+ // ==============================
118
+ // Scroll Helpers
119
+ // ==============================
120
+
121
+ export function isDocumentElement(el) {
122
+ return [document.documentElement, document.body, window].indexOf(el) > -1;
123
+ }
124
+
125
+ // Normalized Scroll Top
126
+ // ------------------------------
127
+
128
+ export function normalizedHeight(el) {
129
+ if (isDocumentElement(el)) {
130
+ return window.innerHeight;
131
+ }
132
+ return el.clientHeight;
133
+ }
134
+
135
+ // Normalized scrollTo & scrollTop
136
+ // ------------------------------
137
+
138
+ export function getScrollTop(el) {
139
+ if (isDocumentElement(el)) {
140
+ return window.pageYOffset;
141
+ }
142
+ return el.scrollTop;
143
+ }
144
+ export function scrollTo(el, top) {
145
+ // with a scroll distance, we perform scroll on the element
146
+ if (isDocumentElement(el)) {
147
+ window.scrollTo(0, top);
148
+ return;
149
+ }
150
+ el.scrollTop = top;
151
+ }
152
+
153
+ // Get Scroll Parent
154
+ // ------------------------------
155
+
156
+ export function getScrollParent(element) {
157
+ let style = getComputedStyle(element);
158
+ const excludeStaticParent = style.position === 'absolute';
159
+ const overflowRx = /(auto|scroll)/;
160
+ if (style.position === 'fixed') {
161
+ return document.documentElement;
162
+ }
163
+ for (let parent = element; parent = parent.parentElement;) {
164
+ style = getComputedStyle(parent);
165
+ if (excludeStaticParent && style.position === 'static') {
166
+ continue;
167
+ }
168
+ if (overflowRx.test(style.overflow + style.overflowY + style.overflowX)) {
169
+ return parent;
170
+ }
171
+ }
172
+ return document.documentElement;
173
+ }
174
+
175
+ // Animated Scroll To
176
+ // ------------------------------
177
+
178
+ /**
179
+ * @param t: time (elapsed)
180
+ * @param b: initial value
181
+ * @param c: amount of change
182
+ * @param d: duration
183
+ */
184
+ function easeOutCubic(t, b, c, d) {
185
+ return c * ((t = t / d - 1) * t * t + 1) + b;
186
+ }
187
+ export function animatedScrollTo(element, to, duration = 200, callback = noop) {
188
+ const start = getScrollTop(element);
189
+ const change = to - start;
190
+ const increment = 10;
191
+ let currentTime = 0;
192
+ function animateScroll() {
193
+ currentTime += increment;
194
+ const val = easeOutCubic(currentTime, start, change, duration);
195
+ scrollTo(element, val);
196
+ if (currentTime < duration) {
197
+ window.requestAnimationFrame(animateScroll);
198
+ } else {
199
+ callback(element);
200
+ }
201
+ }
202
+ animateScroll();
203
+ }
204
+
205
+ // Scroll Into View
206
+ // ------------------------------
207
+
208
+ export function scrollIntoView(menuEl, focusedEl) {
209
+ const menuRect = menuEl.getBoundingClientRect();
210
+ const focusedRect = focusedEl.getBoundingClientRect();
211
+ const overScroll = focusedEl.offsetHeight / 3;
212
+ if (focusedRect.bottom + overScroll > menuRect.bottom) {
213
+ scrollTo(menuEl, Math.min(focusedEl.offsetTop + focusedEl.clientHeight - menuEl.offsetHeight + overScroll, menuEl.scrollHeight));
214
+ } else if (focusedRect.top - overScroll < menuRect.top) {
215
+ scrollTo(menuEl, Math.max(focusedEl.offsetTop - overScroll, 0));
216
+ }
217
+ }
218
+
219
+ // ==============================
220
+ // Get bounding client object
221
+ // ==============================
222
+
223
+ // cannot get keys using array notation with DOMRect
224
+ export function getBoundingClientObj(element) {
225
+ const rect = element.getBoundingClientRect();
226
+ return {
227
+ bottom: rect.bottom,
228
+ height: rect.height,
229
+ left: rect.left,
230
+ right: rect.right,
231
+ top: rect.top,
232
+ width: rect.width
233
+ };
234
+ }
235
+ // ==============================
236
+ // String to Key (kebabify)
237
+ // ==============================
238
+
239
+ export function toKey(str) {
240
+ return str.replace(/\W/g, '-');
241
+ }
242
+
243
+ // ==============================
244
+ // Touch Capability Detector
245
+ // ==============================
246
+
247
+ export function isTouchCapable() {
248
+ try {
249
+ document.createEvent('TouchEvent');
250
+ return true;
251
+ } catch (e) {
252
+ return false;
253
+ }
254
+ }
255
+
256
+ // ==============================
257
+ // Mobile Device Detector
258
+ // ==============================
259
+
260
+ export function isMobileDevice() {
261
+ try {
262
+ return /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent);
263
+ } catch (e) {
264
+ return false;
265
+ }
266
+ }
267
+
268
+ // ==============================
269
+ // Passive Event Detector
270
+ // ==============================
271
+
272
+ // https://github.com/rafgraph/detect-it/blob/main/src/index.ts#L19-L36
273
+ let passiveOptionAccessed = false;
274
+ const options = {
275
+ get passive() {
276
+ return passiveOptionAccessed = true;
277
+ }
278
+ };
279
+ // check for SSR
280
+ const w = typeof window !== 'undefined' ? window : {};
281
+ if (w.addEventListener && w.removeEventListener) {
282
+ // eslint-disable-next-line @repo/internal/dom-events/no-unsafe-event-listeners
283
+ w.addEventListener('p', noop, options);
284
+ // eslint-disable-next-line @repo/internal/dom-events/no-unsafe-event-listeners
285
+ w.removeEventListener('p', noop, false);
286
+ }
287
+ export const supportsPassiveEvents = passiveOptionAccessed;
288
+ export function notNullish(item) {
289
+ return item != null;
290
+ }
291
+ export function isArray(arg) {
292
+ return Array.isArray(arg);
293
+ }
294
+ export function valueTernary(isMulti, multiValue, singleValue) {
295
+ return isMulti ? multiValue : singleValue;
296
+ }
297
+ export function singleValueAsValue(singleValue) {
298
+ return singleValue;
299
+ }
300
+ export function multiValueAsValue(multiValue) {
301
+ return multiValue;
302
+ }
303
+ export const removeProps = (propsObj, ...properties) => {
304
+ let propsMap = Object.entries(propsObj).filter(([key]) => !properties.includes(key));
305
+ return propsMap.reduce((newProps, [key, val]) => {
306
+ newProps[key] = val;
307
+ return newProps;
308
+ }, {});
309
+ };