@oliasoft-open-source/react-ui-library 1.0.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.
Files changed (317) hide show
  1. package/.eslintignore +2 -0
  2. package/.eslintrc.js +125 -0
  3. package/.gitlab-ci.yml +45 -0
  4. package/.husky/pre-commit +4 -0
  5. package/.prettierignore +3 -0
  6. package/.prettierrc +4 -0
  7. package/.storybook/main.js +36 -0
  8. package/.storybook/preview.js +40 -0
  9. package/.storybook/storybook.less +8 -0
  10. package/LICENSE +21 -0
  11. package/README.md +5 -0
  12. package/babel.config.js +31 -0
  13. package/index.js +76 -0
  14. package/jest.config.js +9 -0
  15. package/package.json +136 -0
  16. package/src/components/accordion/accordion.jsx +132 -0
  17. package/src/components/accordion/accordion.module.less +66 -0
  18. package/src/components/accordion/accordion.stories.jsx +171 -0
  19. package/src/components/accordion/chevron/chevron.jsx +12 -0
  20. package/src/components/accordion/chevron/chevron.module.less +12 -0
  21. package/src/components/accordion/helpers/accordion-with-default-toggle.jsx +106 -0
  22. package/src/components/accordion/helpers/accordion-with-default-toggle.module.less +24 -0
  23. package/src/components/actions/actions.jsx +129 -0
  24. package/src/components/actions/actions.module.less +44 -0
  25. package/src/components/actions/actions.shape.js +32 -0
  26. package/src/components/actions/actions.stories.jsx +79 -0
  27. package/src/components/badge/badge.jsx +58 -0
  28. package/src/components/badge/badge.module.less +55 -0
  29. package/src/components/badge/badge.stories.jsx +31 -0
  30. package/src/components/breadcrumb/breadcrumb.jsx +49 -0
  31. package/src/components/breadcrumb/breadcrumb.module.less +39 -0
  32. package/src/components/breadcrumb/breadcrumb.stories.jsx +45 -0
  33. package/src/components/breadcrumb/link.jsx +31 -0
  34. package/src/components/button/button.jsx +156 -0
  35. package/src/components/button/button.module.less +300 -0
  36. package/src/components/button/button.stories.jsx +74 -0
  37. package/src/components/button-group/button-group.jsx +140 -0
  38. package/src/components/button-group/button-group.module.less +24 -0
  39. package/src/components/button-group/button-group.stories-data.jsx +67 -0
  40. package/src/components/button-group/button-group.stories.jsx +63 -0
  41. package/src/components/buttons-and-links.stories.mdx +55 -0
  42. package/src/components/card/card.jsx +51 -0
  43. package/src/components/card/card.module.less +48 -0
  44. package/src/components/card/card.stories.jsx +39 -0
  45. package/src/components/check-box/check-box.jsx +92 -0
  46. package/src/components/check-box/check-box.module.less +101 -0
  47. package/src/components/check-box/check-box.stories.jsx +27 -0
  48. package/src/components/color/color.stories-data.jsx +71 -0
  49. package/src/components/color/color.stories.mdx +37 -0
  50. package/src/components/dialog/dialog.jsx +64 -0
  51. package/src/components/dialog/dialog.module.less +76 -0
  52. package/src/components/divider/divider.jsx +40 -0
  53. package/src/components/divider/divider.module.less +28 -0
  54. package/src/components/divider/divider.stories.jsx +50 -0
  55. package/src/components/drawer/drawer-tabs.jsx +43 -0
  56. package/src/components/drawer/drawer.jsx +150 -0
  57. package/src/components/drawer/drawer.module.less +167 -0
  58. package/src/components/drawer/drawer.stories.jsx +156 -0
  59. package/src/components/empty/empty.jsx +52 -0
  60. package/src/components/empty/empty.module.less +17 -0
  61. package/src/components/empty/empty.stories.jsx +26 -0
  62. package/src/components/file-input/file-input.jsx +101 -0
  63. package/src/components/file-input/file-input.module.less +3 -0
  64. package/src/components/file-input/file-input.stories.jsx +109 -0
  65. package/src/components/form/field.jsx +96 -0
  66. package/src/components/form/field.stories.jsx +101 -0
  67. package/src/components/form/form.module.less +30 -0
  68. package/src/components/form/form.stories.jsx +191 -0
  69. package/src/components/heading/heading.jsx +105 -0
  70. package/src/components/heading/heading.module.less +59 -0
  71. package/src/components/heading/heading.stories.jsx +60 -0
  72. package/src/components/icon/deprecated-icon.jsx +97 -0
  73. package/src/components/icon/icon.jsx +71 -0
  74. package/src/components/icon/icon.module.less +33 -0
  75. package/src/components/icon/icon.stories.jsx +37 -0
  76. package/src/components/icon/icons.example.module.less +4 -0
  77. package/src/components/input/input.jsx +167 -0
  78. package/src/components/input/input.module.less +94 -0
  79. package/src/components/input/input.stories.jsx +28 -0
  80. package/src/components/input-group/input-group-addon/input-group-addon.jsx +36 -0
  81. package/src/components/input-group/input-group-addon/input-group-addon.module.less +31 -0
  82. package/src/components/input-group/input-group.jsx +51 -0
  83. package/src/components/input-group/input-group.module.less +10 -0
  84. package/src/components/input-group/input-group.stories.jsx +77 -0
  85. package/src/components/input-validation.stories.mdx +61 -0
  86. package/src/components/inputs.stories.mdx +201 -0
  87. package/src/components/label/label.jsx +115 -0
  88. package/src/components/label/label.module.less +43 -0
  89. package/src/components/label/label.stories.jsx +60 -0
  90. package/src/components/layout/column/column.jsx +85 -0
  91. package/src/components/layout/column/styles.js +45 -0
  92. package/src/components/layout/column.stories.jsx +60 -0
  93. package/src/components/layout/examples/afe.stories.jsx +180 -0
  94. package/src/components/layout/examples/blowout.stories.jsx +68 -0
  95. package/src/components/layout/examples/casing-loads.stories.jsx +297 -0
  96. package/src/components/layout/examples/formation.stories.jsx +110 -0
  97. package/src/components/layout/examples/projects.stories.jsx +108 -0
  98. package/src/components/layout/examples/reservoirs.stories.jsx +211 -0
  99. package/src/components/layout/examples/site.stories.jsx +263 -0
  100. package/src/components/layout/flex/flex.jsx +48 -0
  101. package/src/components/layout/flex/flex.stories.jsx +54 -0
  102. package/src/components/layout/form-row/form-row.jsx +15 -0
  103. package/src/components/layout/form-row/form-row.module.less +11 -0
  104. package/src/components/layout/grid/grid.jsx +62 -0
  105. package/src/components/layout/grid/grid.stories.jsx +65 -0
  106. package/src/components/layout/page/page.jsx +42 -0
  107. package/src/components/layout/page/page.module.less +27 -0
  108. package/src/components/layout/page.stories.jsx +93 -0
  109. package/src/components/layout/placeholder.jsx +2 -0
  110. package/src/components/layout/print-header/print-header.jsx +22 -0
  111. package/src/components/layout/print-header/print-header.module.less +9 -0
  112. package/src/components/layout/row/row.jsx +75 -0
  113. package/src/components/layout/row/row.module.less +7 -0
  114. package/src/components/layout/spacer/spacer.jsx +26 -0
  115. package/src/components/layout/spacer/spacer.stories.jsx +50 -0
  116. package/src/components/layout-forms.stories.mdx +104 -0
  117. package/src/components/layout-general.stories.mdx +215 -0
  118. package/src/components/list/list-row/item-content.jsx +15 -0
  119. package/src/components/list/list-row/label.jsx +11 -0
  120. package/src/components/list/list-row/list-heading.jsx +52 -0
  121. package/src/components/list/list-row/list-row.jsx +128 -0
  122. package/src/components/list/list-row/list-subheading.jsx +72 -0
  123. package/src/components/list/list-row/meta-content.jsx +24 -0
  124. package/src/components/list/list-row/meta-count.jsx +10 -0
  125. package/src/components/list/list-row/name.jsx +45 -0
  126. package/src/components/list/list.jsx +276 -0
  127. package/src/components/list/list.module.less +256 -0
  128. package/src/components/list/list.stories-data.jsx +287 -0
  129. package/src/components/list/list.stories.jsx +458 -0
  130. package/src/components/list/toggle-narrow.jsx +13 -0
  131. package/src/components/loader/loader.jsx +63 -0
  132. package/src/components/loader/loader.module.less +63 -0
  133. package/src/components/loader/loader.stories.jsx +155 -0
  134. package/src/components/menu/index.js +7 -0
  135. package/src/components/menu/layer/divider.jsx +4 -0
  136. package/src/components/menu/layer/heading.jsx +15 -0
  137. package/src/components/menu/layer/layer.jsx +82 -0
  138. package/src/components/menu/layer/option.jsx +77 -0
  139. package/src/components/menu/layer/path.js +44 -0
  140. package/src/components/menu/layer/placementOptions.js +6 -0
  141. package/src/components/menu/layer/section.jsx +66 -0
  142. package/src/components/menu/menu.jsx +359 -0
  143. package/src/components/menu/menu.module.less +241 -0
  144. package/src/components/menu/menu.stories-data.jsx +168 -0
  145. package/src/components/menu/menu.stories.jsx +126 -0
  146. package/src/components/menu/menu.test.js +58 -0
  147. package/src/components/menu/trigger/button.jsx +50 -0
  148. package/src/components/menu/trigger/component.jsx +14 -0
  149. package/src/components/menu/trigger/text.jsx +25 -0
  150. package/src/components/menu/trigger/trigger.jsx +86 -0
  151. package/src/components/message/dismiss.jsx +26 -0
  152. package/src/components/message/message.jsx +137 -0
  153. package/src/components/message/message.module.less +114 -0
  154. package/src/components/message/message.stories.jsx +84 -0
  155. package/src/components/modal/modal.jsx +50 -0
  156. package/src/components/modal/modal.module.less +35 -0
  157. package/src/components/modal/modal.stories.jsx +159 -0
  158. package/src/components/option-dropdown/heading.jsx +6 -0
  159. package/src/components/option-dropdown/layer.jsx +81 -0
  160. package/src/components/option-dropdown/option-dropdown.jsx +53 -0
  161. package/src/components/option-dropdown/option-dropdown.module.less +50 -0
  162. package/src/components/option-dropdown/option-dropdown.stories.jsx +35 -0
  163. package/src/components/option-dropdown/option.jsx +13 -0
  164. package/src/components/pagination/pagination.jsx +139 -0
  165. package/src/components/pagination/pagination.module.less +11 -0
  166. package/src/components/pagination/pagination.stories.jsx +78 -0
  167. package/src/components/pagination/pagination.test.js +92 -0
  168. package/src/components/pagination/pagination.viewdata.js +66 -0
  169. package/src/components/pop-confirm/content.jsx +25 -0
  170. package/src/components/pop-confirm/pop-confirm.jsx +61 -0
  171. package/src/components/pop-confirm/pop-confirm.module.less +18 -0
  172. package/src/components/pop-confirm/pop-confirm.stories.jsx +53 -0
  173. package/src/components/popover/popover.jsx +112 -0
  174. package/src/components/popover/popover.module.less +22 -0
  175. package/src/components/popover/popover.stories.jsx +59 -0
  176. package/src/components/portal/portal.jsx +16 -0
  177. package/src/components/portal/portal.stories.jsx +69 -0
  178. package/src/components/progress-bar/progress-bar.jsx +64 -0
  179. package/src/components/progress-bar/progress-bar.module.less +64 -0
  180. package/src/components/progress-bar/progress-bar.stories.jsx +23 -0
  181. package/src/components/radio-button/radio-button.jsx +139 -0
  182. package/src/components/radio-button/radio-button.module.less +135 -0
  183. package/src/components/radio-button/radio-button.stories.jsx +37 -0
  184. package/src/components/radio-button/radio-input.jsx +52 -0
  185. package/src/components/select/custom-select/custom-select.jsx +440 -0
  186. package/src/components/select/custom-select/custom-select.module.less +123 -0
  187. package/src/components/select/custom-select/custom-select.reducer.js +157 -0
  188. package/src/components/select/custom-select/layer/heading.jsx +13 -0
  189. package/src/components/select/custom-select/layer/layer.jsx +73 -0
  190. package/src/components/select/custom-select/layer/option.jsx +54 -0
  191. package/src/components/select/custom-select/layer/placementOptions.js +7 -0
  192. package/src/components/select/custom-select/layer/section.jsx +35 -0
  193. package/src/components/select/custom-select/trigger/input.jsx +100 -0
  194. package/src/components/select/custom-select/trigger/trigger.jsx +155 -0
  195. package/src/components/select/custom-select/trigger/trigger.module.less +289 -0
  196. package/src/components/select/native-select/native-select.jsx +198 -0
  197. package/src/components/select/native-select/native-select.module.less +107 -0
  198. package/src/components/select/select.input.js +146 -0
  199. package/src/components/select/select.jsx +207 -0
  200. package/src/components/select/select.stories-data.jsx +92 -0
  201. package/src/components/select/select.stories.jsx +135 -0
  202. package/src/components/select/select.test.js +519 -0
  203. package/src/components/side-bar/container.module.less +29 -0
  204. package/src/components/side-bar/link.jsx +83 -0
  205. package/src/components/side-bar/sections.jsx +23 -0
  206. package/src/components/side-bar/side-bar.jsx +102 -0
  207. package/src/components/side-bar/side-bar.module.less +137 -0
  208. package/src/components/side-bar/side-bar.stories.jsx +101 -0
  209. package/src/components/slider/rc-slider.less +47 -0
  210. package/src/components/slider/slider-tooltip.jsx +20 -0
  211. package/src/components/slider/slider.jsx +233 -0
  212. package/src/components/slider/slider.module.less +40 -0
  213. package/src/components/slider/slider.stories.jsx +110 -0
  214. package/src/components/spinner/spinner.jsx +37 -0
  215. package/src/components/spinner/spinner.module.less +115 -0
  216. package/src/components/spinner/spinner.stories.jsx +24 -0
  217. package/src/components/table/cell/cell.jsx +614 -0
  218. package/src/components/table/cell/cell.module.less +152 -0
  219. package/src/components/table/footer/footer.jsx +66 -0
  220. package/src/components/table/footer/footer.module.less +14 -0
  221. package/src/components/table/helper.js +64 -0
  222. package/src/components/table/helper.test.js +166 -0
  223. package/src/components/table/icon/icon.module.less +31 -0
  224. package/src/components/table/row/expanded-content-row.jsx +16 -0
  225. package/src/components/table/row/row.jsx +253 -0
  226. package/src/components/table/row/row.module.less +62 -0
  227. package/src/components/table/table-scroll-wrapper.jsx +48 -0
  228. package/src/components/table/table.jsx +232 -0
  229. package/src/components/table/table.module.less +145 -0
  230. package/src/components/table/table.stories-data.jsx +752 -0
  231. package/src/components/table/table.stories.jsx +814 -0
  232. package/src/components/table/table.test.js +30 -0
  233. package/src/components/table/table.variables.less +19 -0
  234. package/src/components/table/table.viewdata.js +26 -0
  235. package/src/components/table/title/title.jsx +30 -0
  236. package/src/components/table/title/title.module.less +9 -0
  237. package/src/components/tabs/content.jsx +14 -0
  238. package/src/components/tabs/label.jsx +50 -0
  239. package/src/components/tabs/tabs.jsx +191 -0
  240. package/src/components/tabs/tabs.module.less +73 -0
  241. package/src/components/tabs/tabs.stories.jsx +110 -0
  242. package/src/components/text/text.jsx +64 -0
  243. package/src/components/text/text.module.less +45 -0
  244. package/src/components/text/text.stories.jsx +31 -0
  245. package/src/components/text-link/text-link.jsx +23 -0
  246. package/src/components/text-link/text-link.stories.jsx +20 -0
  247. package/src/components/textarea/textarea.jsx +126 -0
  248. package/src/components/textarea/textarea.module.less +55 -0
  249. package/src/components/textarea/textarea.stories.jsx +26 -0
  250. package/src/components/toaster/toaster.jsx +39 -0
  251. package/src/components/toaster/toaster.less +17 -0
  252. package/src/components/toaster/toaster.stories.jsx +116 -0
  253. package/src/components/toggle/toggle.jsx +65 -0
  254. package/src/components/toggle/toggle.module.less +139 -0
  255. package/src/components/toggle/toggle.stories.jsx +26 -0
  256. package/src/components/tooltip/tooltip-layer.jsx +72 -0
  257. package/src/components/tooltip/tooltip.jsx +108 -0
  258. package/src/components/tooltip/tooltip.module.less +28 -0
  259. package/src/components/tooltip/tooltip.stories.jsx +71 -0
  260. package/src/components/top-bar/element/element.jsx +72 -0
  261. package/src/components/top-bar/element/link.jsx +29 -0
  262. package/src/components/top-bar/title.jsx +24 -0
  263. package/src/components/top-bar/top-bar.jsx +79 -0
  264. package/src/components/top-bar/top-bar.module.less +191 -0
  265. package/src/components/top-bar/top-bar.stories.jsx +137 -0
  266. package/src/components/top-bar/warning.jsx +6 -0
  267. package/src/components/tree/tree-item.jsx +79 -0
  268. package/src/components/tree/tree-placeholder.jsx +6 -0
  269. package/src/components/tree/tree.jsx +129 -0
  270. package/src/components/tree/tree.module.less +33 -0
  271. package/src/components/tree/tree.stories-data.jsx +89 -0
  272. package/src/components/tree/tree.stories.jsx +106 -0
  273. package/src/docs/components/page/page.jsx +16 -0
  274. package/src/docs/config/config.js +1 -0
  275. package/src/docs/html/favicon.png +0 -0
  276. package/src/docs/html/index.html +11 -0
  277. package/src/docs/navigation/footer/footer.jsx +48 -0
  278. package/src/docs/navigation/header/header.jsx +39 -0
  279. package/src/docs/navigation/header/header.module.less +32 -0
  280. package/src/docs/navigation/routes/routes.jsx +16 -0
  281. package/src/docs/start.jsx +12 -0
  282. package/src/docs/views/main/main.jsx +209 -0
  283. package/src/docs/views/main/main.module.less +14 -0
  284. package/src/docs/views/not-found/not-found.jsx +5 -0
  285. package/src/helpers/disabled-context.js +8 -0
  286. package/src/helpers/styles.js +68 -0
  287. package/src/helpers/text.js +6 -0
  288. package/src/helpers/types.js +5 -0
  289. package/src/hooks/index.js +3 -0
  290. package/src/hooks/use-focus.js +11 -0
  291. package/src/hooks/use-keyboard-event.js +16 -0
  292. package/src/hooks/use-window-width.js +20 -0
  293. package/src/images/icons/icon-drop.png +0 -0
  294. package/src/images/icons/icon-share.png +0 -0
  295. package/src/images/icons/icons8-junction.svg +4 -0
  296. package/src/images/logo.png +0 -0
  297. package/src/images/logo.svg +13 -0
  298. package/src/images/oliasoft-logo.svg +1 -0
  299. package/src/style/colors.less +26 -0
  300. package/src/style/external.less +10 -0
  301. package/src/style/fonts/lato/Lato-Bold.woff2 +0 -0
  302. package/src/style/fonts/lato/Lato-BoldItalic.woff2 +0 -0
  303. package/src/style/fonts/lato/Lato-Italic.woff2 +0 -0
  304. package/src/style/fonts/lato/Lato-Regular.woff2 +0 -0
  305. package/src/style/fonts.less +27 -0
  306. package/src/style/global.less +51 -0
  307. package/src/style/mixins.less +67 -0
  308. package/src/style/reset/reset.less +34 -0
  309. package/src/style/shared.less +25 -0
  310. package/src/style/theme.dark.less +37 -0
  311. package/src/style/theme.default.less +74 -0
  312. package/src/style/variables.less +49 -0
  313. package/webpack/webpack.common.js +39 -0
  314. package/webpack/webpack.common.rules.js +102 -0
  315. package/webpack/webpack.dev.js +22 -0
  316. package/webpack/webpack.prod.js +23 -0
  317. package/webpack/webpack.resolve.js +22 -0
@@ -0,0 +1,146 @@
1
+ export const isMulti = (selectedOptions) => selectedOptions instanceof Array;
2
+
3
+ const isEmptyNullOrUndefined = (value) =>
4
+ value === null || value === undefined || value === '';
5
+
6
+ export const standardizeOptions = (options, simple) => {
7
+ return simple && options instanceof Array
8
+ ? options.map((o) =>
9
+ typeof o === 'string' || typeof o === 'number'
10
+ ? { label: o, value: o }
11
+ : o,
12
+ )
13
+ : options;
14
+ };
15
+
16
+ export const standardizeSelectedOption = (
17
+ standardizedOptions,
18
+ selectedOption,
19
+ ) => {
20
+ if (
21
+ selectedOption !== null &&
22
+ typeof selectedOption === 'object' &&
23
+ selectedOption.hasOwnProperty('label') &&
24
+ selectedOption.hasOwnProperty('value')
25
+ ) {
26
+ return selectedOption;
27
+ } else {
28
+ const value =
29
+ selectedOption !== null &&
30
+ typeof selectedOption === 'object' &&
31
+ selectedOption.hasOwnProperty('value')
32
+ ? selectedOption.value
33
+ : selectedOption;
34
+ const foundFullValue =
35
+ standardizedOptions instanceof Array
36
+ ? standardizedOptions
37
+ .filter((o) => o.type !== 'Heading')
38
+ .find((o) => o.value == value /* allow coercion */)
39
+ : undefined;
40
+ return (
41
+ foundFullValue ||
42
+ (isEmptyNullOrUndefined(value) ? undefined : { value, label: value })
43
+ );
44
+ }
45
+ };
46
+
47
+ export const standardizeSelectedOptions = (
48
+ standardizedOptions,
49
+ selectedOptions,
50
+ ) => {
51
+ const isMulti = selectedOptions instanceof Array;
52
+ if (isMulti) {
53
+ return selectedOptions
54
+ .map((selectedOption) =>
55
+ standardizeSelectedOption(standardizedOptions, selectedOption),
56
+ )
57
+ .filter((selectedOption) => selectedOption !== undefined);
58
+ } else {
59
+ return selectedOptions === null
60
+ ? undefined
61
+ : standardizeSelectedOption(standardizedOptions, selectedOptions);
62
+ }
63
+ };
64
+
65
+ export const isSimpleOptions = (options) =>
66
+ options instanceof Array &&
67
+ options.some((o) => typeof o === 'string' || typeof o === 'number');
68
+
69
+ export const isSimpleSelectedOptions = (selectedOptions) => {
70
+ return (
71
+ typeof selectedOptions === 'string' ||
72
+ typeof selectedOptions === 'number' ||
73
+ (selectedOptions instanceof Array && isSimpleOptions(selectedOptions))
74
+ );
75
+ };
76
+
77
+ export const getFirstSelectedOptionIndex = (options, selectedOptions) => {
78
+ const firstSelected =
79
+ selectedOptions instanceof Array
80
+ ? selectedOptions.length
81
+ ? selectedOptions[0]
82
+ : null
83
+ : selectedOptions;
84
+ const firstSelectedValue =
85
+ firstSelected === null || firstSelected === undefined
86
+ ? null
87
+ : typeof firstSelected === 'string' || typeof firstSelected === 'number'
88
+ ? firstSelected
89
+ : firstSelected.value;
90
+ const index = options
91
+ .filter((o) => o.type !== 'Heading')
92
+ .findIndex((o) => {
93
+ if (typeof o === 'string' || typeof o === 'number') {
94
+ return o == firstSelectedValue; //allow coercion
95
+ } else {
96
+ return o.value == firstSelectedValue; //allow coercion
97
+ }
98
+ });
99
+ return index === -1 ? null : index;
100
+ };
101
+
102
+ export const nonExistentValue = (options, selectedOptions) => {
103
+ const isMulti = selectedOptions instanceof Array;
104
+ const selected = isMulti
105
+ ? selectedOptions
106
+ : isEmptyNullOrUndefined(selectedOptions)
107
+ ? []
108
+ : [selectedOptions];
109
+ return !selected.every((selectedValue) => {
110
+ const found = options.find((o) => o.value === selectedValue.value);
111
+ return found !== undefined;
112
+ });
113
+ };
114
+
115
+ export const standardizeInputs = (
116
+ options,
117
+ selectedOptions,
118
+ enableAutoScroll,
119
+ checkNonExistentValues,
120
+ ) => {
121
+ const cleanedOptions = options instanceof Array ? options : []; // don't crash when options is null or wrong type
122
+ const multi = isMulti(selectedOptions);
123
+ const simpleOptions = isSimpleOptions(cleanedOptions);
124
+ const simpleSelectedOptions = isSimpleSelectedOptions(selectedOptions);
125
+ const standardizedOptions = standardizeOptions(cleanedOptions, simpleOptions);
126
+ const firstSelectedOptionIndex = enableAutoScroll
127
+ ? getFirstSelectedOptionIndex(cleanedOptions, selectedOptions)
128
+ : null;
129
+ const standardizedSelectedOptions = standardizeSelectedOptions(
130
+ standardizedOptions,
131
+ selectedOptions,
132
+ simpleSelectedOptions,
133
+ multi,
134
+ );
135
+ const hasNonExistentValue = checkNonExistentValues
136
+ ? nonExistentValue(standardizedOptions, standardizedSelectedOptions)
137
+ : false;
138
+ return {
139
+ options: standardizedOptions,
140
+ selectedOptions: standardizedSelectedOptions,
141
+ multi,
142
+ simpleInputs: simpleOptions,
143
+ firstSelectedOptionIndex,
144
+ hasNonExistentValue,
145
+ };
146
+ };
@@ -0,0 +1,207 @@
1
+ import React from 'react';
2
+ import * as PropTypes from 'prop-types';
3
+ import { NativeSelect } from './native-select/native-select';
4
+ import {
5
+ CustomSelect,
6
+ selectOptionShape,
7
+ selectedOptionsShape,
8
+ } from './custom-select/custom-select';
9
+ import { standardizeInputs } from './select.input';
10
+
11
+ export const Select = (props) => {
12
+ const {
13
+ name,
14
+ options: rawOptions = [],
15
+ value: rawSelectedOptions,
16
+ native,
17
+ onChange,
18
+ deprecatedEventHandler,
19
+ autoScroll = true,
20
+ warning,
21
+ error,
22
+ checkNonExistentValues,
23
+ closeOnOptionActionClick,
24
+ testId,
25
+ } = props;
26
+ const enableAutoScroll = !native && autoScroll === true;
27
+ const {
28
+ multi,
29
+ simpleInputs,
30
+ options,
31
+ selectedOptions,
32
+ firstSelectedOptionIndex,
33
+ hasNonExistentValue,
34
+ } = standardizeInputs(
35
+ rawOptions,
36
+ rawSelectedOptions,
37
+ enableAutoScroll,
38
+ checkNonExistentValues,
39
+ );
40
+ const canUseNative = !multi; //ignore searchable since it's on by default
41
+ const useNative = native && canUseNative;
42
+ if (native && !canUseNative) {
43
+ console.warn('Native select does not support provided props (see stories)');
44
+ }
45
+
46
+ const nonExistentWarning = 'Value no longer available for re-selection';
47
+ const fullWarning = hasNonExistentValue ? (
48
+ warning ? (
49
+ <div>
50
+ <div>{nonExistentWarning}</div>
51
+ <div>{warning}</div>
52
+ </div>
53
+ ) : (
54
+ nonExistentWarning
55
+ )
56
+ ) : (
57
+ warning
58
+ );
59
+
60
+ const fullError =
61
+ hasNonExistentValue && error ? (
62
+ <div>
63
+ <div>{nonExistentWarning}</div>
64
+ <div>{error}</div>
65
+ </div>
66
+ ) : (
67
+ error
68
+ );
69
+
70
+ const onChangeSelectedValue = (evt, selectedOptions) => {
71
+ if (deprecatedEventHandler) {
72
+ const newSelectedOptions = multi
73
+ ? selectedOptions.map((o) => (simpleInputs ? o.value : o))
74
+ : simpleInputs
75
+ ? selectedOptions.value
76
+ : selectedOptions;
77
+ onChange(newSelectedOptions);
78
+ } else {
79
+ /*
80
+ - For React synthetic events, mutate the values and forward the event
81
+ - For native (keyboard) events, clone the enumerable properties and forward
82
+ - Explanation:
83
+ https://gitlab.com/oliasoft-open-source/react-ui-library/-/issues/77
84
+ */
85
+ const isSyntheticEvent = !(evt instanceof Event);
86
+ const value = multi ? selectedOptions : selectedOptions.value;
87
+ if (isSyntheticEvent) {
88
+ evt.target.name = name;
89
+ evt.target.value = value;
90
+ if (!multi) {
91
+ evt.target.label = selectedOptions.label;
92
+ }
93
+ onChange(evt);
94
+ } else {
95
+ onChange({
96
+ ...evt,
97
+ target: {
98
+ ...evt.target,
99
+ name,
100
+ value,
101
+ ...(!multi && { label: selectedOptions.label }),
102
+ },
103
+ });
104
+ }
105
+ }
106
+ };
107
+
108
+ return useNative ? (
109
+ <NativeSelect
110
+ {...props} // eslint-disable-line react/jsx-props-no-spreading
111
+ options={options}
112
+ selectedOption={selectedOptions}
113
+ onChange={onChangeSelectedValue}
114
+ hasNonExistentValue={hasNonExistentValue}
115
+ warning={fullWarning}
116
+ error={fullError}
117
+ testId={testId}
118
+ />
119
+ ) : (
120
+ <CustomSelect
121
+ {...props} // eslint-disable-line react/jsx-props-no-spreading
122
+ options={options}
123
+ selectedOptions={selectedOptions}
124
+ onChange={onChangeSelectedValue}
125
+ multi={multi}
126
+ firstSelectedOptionIndex={firstSelectedOptionIndex}
127
+ warning={fullWarning}
128
+ error={fullError}
129
+ testId={testId}
130
+ closeOnOptionActionClick={closeOnOptionActionClick}
131
+ />
132
+ );
133
+ };
134
+
135
+ Select.defaultProps = {
136
+ autoLayerWidth: false,
137
+ borderRadius: null,
138
+ clearable: false,
139
+ disabled: false,
140
+ error: null,
141
+ firstSelectedOptionIndex: null,
142
+ groupOrder: null,
143
+ isInTable: false,
144
+ multi: false,
145
+ onBlur: () => {},
146
+ onChange: () => {},
147
+ onCreate: null,
148
+ onFocus: () => {},
149
+ right: false,
150
+ searchable: true,
151
+ selectedOption: null,
152
+ selectedOptions: null,
153
+ small: false,
154
+ tabIndex: 0,
155
+ tooltip: null,
156
+ warning: null,
157
+ width: null,
158
+ checkNonExistentValues: true,
159
+ closeOnOptionActionClick: true,
160
+ testId: undefined,
161
+ };
162
+
163
+ const SelectShape = {
164
+ name: PropTypes.string,
165
+ disabled: PropTypes.bool,
166
+ error: PropTypes.oneOfType([
167
+ PropTypes.string,
168
+ PropTypes.number,
169
+ PropTypes.node,
170
+ ]),
171
+ warning: PropTypes.oneOfType([
172
+ PropTypes.string,
173
+ PropTypes.number,
174
+ PropTypes.node,
175
+ ]),
176
+ tooltip: PropTypes.oneOfType([
177
+ PropTypes.string,
178
+ PropTypes.number,
179
+ PropTypes.node,
180
+ ]),
181
+ options: PropTypes.arrayOf(selectOptionShape).isRequired,
182
+ value: selectedOptionsShape,
183
+ onChange: PropTypes.func,
184
+ onCreate: PropTypes.func,
185
+ small: PropTypes.bool,
186
+ tabIndex: PropTypes.number,
187
+ width: PropTypes.string,
188
+ autoLayerWidth: PropTypes.bool,
189
+ onFocus: PropTypes.func,
190
+ onBlur: PropTypes.func,
191
+ searchable: PropTypes.bool,
192
+ clearable: PropTypes.bool,
193
+ maxTooltipWidth: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
194
+ autoScroll: PropTypes.bool,
195
+ checkNonExistentValues: PropTypes.bool,
196
+ testId: PropTypes.string,
197
+ closeOnOptionActionClick: PropTypes.bool,
198
+ //native select only:
199
+ borderRadius: PropTypes.number,
200
+ //deprecated props:
201
+ deprecatedEventHandler: PropTypes.bool,
202
+ //private props (don't use)
203
+ isInTable: PropTypes.bool,
204
+ right: PropTypes.bool,
205
+ };
206
+
207
+ Select.propTypes = PropTypes.shape(SelectShape).isRequired;
@@ -0,0 +1,92 @@
1
+ import React from 'react';
2
+ import {
3
+ FaExclamationTriangle,
4
+ FaPencilAlt,
5
+ FaSkull,
6
+ FaTrash,
7
+ } from 'react-icons/fa';
8
+
9
+ export const options = [
10
+ { label: 'Aardvarks', value: 'termites' },
11
+ { label: 'Kangaroos', value: 'grass' },
12
+ { label: 'Monkeys', value: 'bananas', disabled: true },
13
+ ];
14
+
15
+ export const optionsWithDetails = [
16
+ { label: 'Kangaroos', value: 'grass', details: '(grass)' },
17
+ { label: 'Monkeys', value: 'bananas', details: '(bananas)' },
18
+ { label: 'Possums', value: 'slugs', details: '(slugs)' },
19
+ ];
20
+
21
+ export const optionsWithHeadings = [
22
+ { type: 'Heading', label: 'Large' },
23
+ { label: 'Aardvarks', value: 'termites' },
24
+ { label: 'Kangaroos', value: 'grass' },
25
+ { label: 'Monkeys', value: 'bananas' },
26
+ { type: 'Heading', label: 'Small' },
27
+ { label: 'Possums', value: 'slugs' },
28
+ ];
29
+
30
+ export const optionsNumeric = [
31
+ { label: 1, value: 1 },
32
+ { label: 2, value: 2 },
33
+ { label: 3, value: 3 },
34
+ { label: 4, value: 4 },
35
+ ];
36
+
37
+ export const optionsWithIcons = [
38
+ {
39
+ label: 'Aardvarks',
40
+ value: 'termites',
41
+ },
42
+ { label: 'Monkeys', value: 'bananas' },
43
+ {
44
+ label: 'Vampires',
45
+ value: 'blood',
46
+ icon: <FaExclamationTriangle color="var(--color-text-warning)" />,
47
+ },
48
+ {
49
+ label: 'Zombies',
50
+ value: 'brains',
51
+ icon: <FaSkull color="var(--color-text-error)" />,
52
+ },
53
+ ];
54
+
55
+ export const actions = [
56
+ {
57
+ label: 'Delete',
58
+ icon: <FaTrash />,
59
+ onClick: () => {},
60
+ },
61
+ {
62
+ label: 'Rename',
63
+ icon: <FaPencilAlt />,
64
+ onClick: () => {},
65
+ },
66
+ ];
67
+
68
+ export const optionsWithActions = [
69
+ {
70
+ label: 'Kangaroos',
71
+ value: 'grass',
72
+ actions,
73
+ },
74
+ {
75
+ label: 'Monkeys',
76
+ value: 'bananas',
77
+ actions,
78
+ },
79
+ {
80
+ label: 'Possums',
81
+ value: 'slugs',
82
+ actions,
83
+ details: '(some details)',
84
+ },
85
+ ];
86
+
87
+ export const optionsLong = [...Array(10000).keys()].map((o, i) => ({
88
+ label: Math.random().toString(36).substring(7),
89
+ value: i,
90
+ }));
91
+
92
+ export const optionsSimple = ['Aardvarks', 'Kangaroos', 'Monkeys', 'Possums'];
@@ -0,0 +1,135 @@
1
+ import React, { useState } from 'react';
2
+ import { Select } from './select';
3
+ import * as storyData from './select.stories-data';
4
+
5
+ export default {
6
+ title: 'Forms/Select',
7
+ component: Select,
8
+ args: {
9
+ options: storyData.options,
10
+ native: false,
11
+ multi: false,
12
+ disabled: false,
13
+ small: false,
14
+ autoLayerWidth: false,
15
+ clearable: false,
16
+ searchable: true,
17
+ right: false,
18
+ },
19
+ };
20
+
21
+ const Template = (args) => {
22
+ const { multi, value } = args;
23
+ const [selectedValue, setSelectedValue] = useState(
24
+ value || (multi ? [] : undefined),
25
+ );
26
+ const handleChange = (evt) => {
27
+ const { value } = evt.target;
28
+ setSelectedValue(multi ? value : { value });
29
+ };
30
+ return (
31
+ <Select
32
+ // eslint-disable-next-line react/jsx-props-no-spreading
33
+ {...args}
34
+ value={selectedValue}
35
+ onChange={handleChange}
36
+ />
37
+ );
38
+ };
39
+
40
+ export const Default = Template.bind({});
41
+
42
+ export const Native = Template.bind({});
43
+ Native.args = { native: true };
44
+
45
+ export const Multiselect = Template.bind({});
46
+ Multiselect.args = { multi: true };
47
+
48
+ export const Empty = Template.bind({});
49
+ Empty.args = { options: [] };
50
+
51
+ export const Clearable = Template.bind({});
52
+ Clearable.args = { clearable: true };
53
+
54
+ export const OptionsWithDetails = Template.bind({});
55
+ OptionsWithDetails.args = { options: storyData.optionsWithDetails };
56
+
57
+ export const NonExistentValue = Template.bind({});
58
+ NonExistentValue.args = { value: { label: 'Vampires', value: 'blood' } };
59
+
60
+ export const CustomPlaceholder = Template.bind({});
61
+ CustomPlaceholder.args = { placeholder: 'Select the best animal...' };
62
+
63
+ export const OptionsWithHeadings = Template.bind({});
64
+ OptionsWithHeadings.args = { options: storyData.optionsWithHeadings };
65
+
66
+ export const OptionsWithIcons = Template.bind({});
67
+ OptionsWithIcons.args = { options: storyData.optionsWithIcons };
68
+
69
+ export const OptionsWithActions = Template.bind({});
70
+ OptionsWithActions.args = { options: storyData.optionsWithActions };
71
+
72
+ export const NotSearchable = Template.bind({});
73
+ NotSearchable.args = { searchable: false };
74
+
75
+ export const Small = Template.bind({});
76
+ Small.args = { small: true };
77
+
78
+ export const RightAligned = Template.bind({});
79
+ RightAligned.args = { right: true };
80
+
81
+ export const AutoWidth = Template.bind({});
82
+ AutoWidth.parameters = {
83
+ docs: {
84
+ description: {
85
+ story: 'Avoid `width: auto` for very long lists in custom selects (slow)',
86
+ },
87
+ },
88
+ };
89
+ AutoWidth.args = { width: 'auto' };
90
+
91
+ export const AutoLayerWidth = Template.bind({});
92
+ AutoLayerWidth.parameters = {
93
+ docs: {
94
+ description: {
95
+ story:
96
+ 'Avoid autoLayerWidth for very long lists in custom selects (slow)',
97
+ },
98
+ },
99
+ };
100
+ AutoLayerWidth.args = { width: '70px', autoLayerWidth: true };
101
+
102
+ export const FixedWidth = Template.bind({});
103
+ FixedWidth.args = { width: '200px' };
104
+
105
+ export const Tooltip = Template.bind({});
106
+ Tooltip.args = { tooltip: 'Some info' };
107
+
108
+ export const Error = Template.bind({});
109
+ Error.args = { error: 'Some info' };
110
+
111
+ export const Warning = Template.bind({});
112
+ Warning.args = { warning: 'Some info' };
113
+
114
+ export const Disabled = Template.bind({});
115
+ Disabled.args = { disabled: true };
116
+
117
+ export const NumericOptions = Template.bind({});
118
+ NumericOptions.args = { options: storyData.optionsNumeric };
119
+
120
+ export const SimpleOptions = Template.bind({});
121
+ SimpleOptions.args = { options: storyData.optionsSimple };
122
+
123
+ export const VeryLongList = Template.bind({});
124
+ VeryLongList.parameters = {
125
+ docs: {
126
+ description: {
127
+ story:
128
+ 'Avoid `width: auto` and autoLayerWidth for very long lists in custom selects (slow). Consider checkNonExistentValues={false}.',
129
+ },
130
+ },
131
+ };
132
+ VeryLongList.args = { options: storyData.optionsLong };
133
+
134
+ export const DeprecatedEventHandler = Template.bind({});
135
+ DeprecatedEventHandler.args = { deprecatedEventHandler: true };