@dhis2-ui/select 10.16.1 → 10.16.3-alpha.1

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 (278) hide show
  1. package/build/cjs/select/select.js +5 -2
  2. package/build/cjs/simple-single-select/use-handle-key-press/use-handle-key-press-on-filter-input.js +2 -2
  3. package/build/es/select/select.js +5 -2
  4. package/build/es/simple-single-select/use-handle-key-press/use-handle-key-press-on-filter-input.js +2 -2
  5. package/package.json +17 -16
  6. package/src/index.js +9 -0
  7. package/src/locales/ar/translations.json +7 -0
  8. package/src/locales/ar_IQ/translations.json +7 -0
  9. package/src/locales/ckb/translations.json +7 -0
  10. package/src/locales/cs/translations.json +7 -0
  11. package/src/locales/da/translations.json +7 -0
  12. package/src/locales/en/translations.json +11 -0
  13. package/src/locales/en_US/translations.json +9 -0
  14. package/src/locales/es/translations.json +7 -0
  15. package/src/locales/es_419/translations.json +7 -0
  16. package/src/locales/fr/translations.json +7 -0
  17. package/src/locales/hi_IN/translations.json +7 -0
  18. package/src/locales/id/translations.json +7 -0
  19. package/src/locales/index.js +80 -0
  20. package/src/locales/km/translations.json +7 -0
  21. package/src/locales/lo/translations.json +7 -0
  22. package/src/locales/my/translations.json +7 -0
  23. package/src/locales/nb/translations.json +7 -0
  24. package/src/locales/nl/translations.json +7 -0
  25. package/src/locales/prs/translations.json +7 -0
  26. package/src/locales/ps/translations.json +7 -0
  27. package/src/locales/pt/translations.json +7 -0
  28. package/src/locales/pt_BR/translations.json +7 -0
  29. package/src/locales/ru/translations.json +7 -0
  30. package/src/locales/sv/translations.json +7 -0
  31. package/src/locales/tet/translations.json +7 -0
  32. package/src/locales/tg/translations.json +7 -0
  33. package/src/locales/uk/translations.json +7 -0
  34. package/src/locales/ur/translations.json +7 -0
  35. package/src/locales/uz_Latn/translations.json +7 -0
  36. package/src/locales/uz_UZ_Cyrl/translations.json +7 -0
  37. package/src/locales/uz_UZ_Latn/translations.json +7 -0
  38. package/src/locales/vi/translations.json +7 -0
  39. package/src/locales/zh/translations.json +9 -0
  40. package/src/locales/zh_CN/translations.json +7 -0
  41. package/src/multi-select/__tests__/multi-select.test.js +23 -0
  42. package/src/multi-select/__tests__/selection-list.test.js +102 -0
  43. package/src/multi-select/features/accepts_blur_cb/index.js +14 -0
  44. package/src/multi-select/features/accepts_blur_cb.feature +8 -0
  45. package/src/multi-select/features/accepts_focus_cb/index.js +14 -0
  46. package/src/multi-select/features/accepts_focus_cb.feature +6 -0
  47. package/src/multi-select/features/accepts_initial_focus/index.js +5 -0
  48. package/src/multi-select/features/accepts_initial_focus.feature +5 -0
  49. package/src/multi-select/features/accepts_loading/index.js +22 -0
  50. package/src/multi-select/features/accepts_loading.feature +14 -0
  51. package/src/multi-select/features/accepts_max_height/index.js +31 -0
  52. package/src/multi-select/features/accepts_max_height.feature +11 -0
  53. package/src/multi-select/features/accepts_placeholder/index.js +25 -0
  54. package/src/multi-select/features/accepts_placeholder.feature +10 -0
  55. package/src/multi-select/features/accepts_prefix/index.js +19 -0
  56. package/src/multi-select/features/accepts_prefix.feature +10 -0
  57. package/src/multi-select/features/allows_invalid_options/index.js +27 -0
  58. package/src/multi-select/features/allows_invalid_options.feature +12 -0
  59. package/src/multi-select/features/allows_selecting/index.js +81 -0
  60. package/src/multi-select/features/allows_selecting.feature +44 -0
  61. package/src/multi-select/features/can_be_cleared/index.js +22 -0
  62. package/src/multi-select/features/can_be_cleared.feature +6 -0
  63. package/src/multi-select/features/can_be_disabled/index.js +36 -0
  64. package/src/multi-select/features/can_be_disabled.feature +32 -0
  65. package/src/multi-select/features/can_be_empty/index.js +28 -0
  66. package/src/multi-select/features/can_be_empty.feature +16 -0
  67. package/src/multi-select/features/can_be_filtered/index.js +23 -0
  68. package/src/multi-select/features/can_be_filtered.feature +14 -0
  69. package/src/multi-select/features/can_be_opened_and_closed/index.js +32 -0
  70. package/src/multi-select/features/can_be_opened_and_closed.feature +41 -0
  71. package/src/multi-select/features/common/index.js +49 -0
  72. package/src/multi-select/features/duplicate_option_values/index.js +21 -0
  73. package/src/multi-select/features/duplicate_option_values.feature +7 -0
  74. package/src/multi-select/features/menu_width_matches_input/index.js +53 -0
  75. package/src/multi-select/features/menu_width_matches_input.feature +11 -0
  76. package/src/multi-select/features/position/index.js +160 -0
  77. package/src/multi-select/features/position.feature +46 -0
  78. package/src/multi-select/features/shows_selections/index.js +18 -0
  79. package/src/multi-select/features/shows_selections.feature +9 -0
  80. package/src/multi-select/filterable-menu.js +43 -0
  81. package/src/multi-select/index.js +1 -0
  82. package/src/multi-select/input.js +129 -0
  83. package/src/multi-select/menu.js +91 -0
  84. package/src/multi-select/multi-select.e2e.stories.js +407 -0
  85. package/src/multi-select/multi-select.js +148 -0
  86. package/src/multi-select/multi-select.prod.stories.js +408 -0
  87. package/src/multi-select/selection-list.js +79 -0
  88. package/src/multi-select-field/__tests__/multi-select-field.test.js +29 -0
  89. package/src/multi-select-field/features/accepts_help_text/index.js +9 -0
  90. package/src/multi-select-field/features/accepts_help_text.feature +5 -0
  91. package/src/multi-select-field/features/accepts_label/index.js +9 -0
  92. package/src/multi-select-field/features/accepts_label.feature +5 -0
  93. package/src/multi-select-field/features/accepts_validation_text/index.js +9 -0
  94. package/src/multi-select-field/features/accepts_validation_text.feature +5 -0
  95. package/src/multi-select-field/features/can_be_required/index.js +11 -0
  96. package/src/multi-select-field/features/can_be_required.feature +5 -0
  97. package/src/multi-select-field/features/has_default_clear_text/index.js +16 -0
  98. package/src/multi-select-field/features/has_default_clear_text.feature +6 -0
  99. package/src/multi-select-field/features/has_default_empty_text/index.js +13 -0
  100. package/src/multi-select-field/features/has_default_empty_text.feature +6 -0
  101. package/src/multi-select-field/features/has_default_filter_nomatch_text/index.js +17 -0
  102. package/src/multi-select-field/features/has_default_filter_nomatch_text.feature +7 -0
  103. package/src/multi-select-field/features/has_default_filter_placeholder/index.js +15 -0
  104. package/src/multi-select-field/features/has_default_filter_placeholder.feature +6 -0
  105. package/src/multi-select-field/features/has_default_loading_text/index.js +13 -0
  106. package/src/multi-select-field/features/has_default_loading_text.feature +6 -0
  107. package/src/multi-select-field/index.js +1 -0
  108. package/src/multi-select-field/multi-select-field.e2e.stories.js +45 -0
  109. package/src/multi-select-field/multi-select-field.js +178 -0
  110. package/src/multi-select-field/multi-select-field.prod.stories.js +137 -0
  111. package/src/multi-select-option/index.js +1 -0
  112. package/src/multi-select-option/multi-select-option.js +70 -0
  113. package/src/select/__tests__/select.test.js +31 -0
  114. package/src/select/debounce/debounce.js +30 -0
  115. package/src/select/debounce/debounce.spec.js +35 -0
  116. package/src/select/empty.js +28 -0
  117. package/src/select/filter-input.js +42 -0
  118. package/src/select/filterable-menu.js +106 -0
  119. package/src/select/index.js +14 -0
  120. package/src/select/input-clear-button.js +66 -0
  121. package/src/select/input-placeholder.js +30 -0
  122. package/src/select/input-prefix.js +32 -0
  123. package/src/select/input-wrapper.js +114 -0
  124. package/src/select/loading.js +33 -0
  125. package/src/select/menu-wrapper.js +52 -0
  126. package/src/select/no-match.js +28 -0
  127. package/src/select/option-helpers.js +34 -0
  128. package/src/select/select.js +256 -0
  129. package/src/simple-single-select/__stories__/DefaultPosition.js +37 -0
  130. package/src/simple-single-select/__stories__/Dense.js +17 -0
  131. package/src/simple-single-select/__stories__/Empty.js +15 -0
  132. package/src/simple-single-select/__stories__/EmptyWithEmptyNode.js +27 -0
  133. package/src/simple-single-select/__stories__/EmptyWithEmptyText.js +16 -0
  134. package/src/simple-single-select/__stories__/FlippedPosition.js +36 -0
  135. package/src/simple-single-select/__stories__/InfiniteLoading.js +65 -0
  136. package/src/simple-single-select/__stories__/Loading.js +15 -0
  137. package/src/simple-single-select/__stories__/ShiftedIntoView.js +35 -0
  138. package/src/simple-single-select/__stories__/WithClearButton.js +26 -0
  139. package/src/simple-single-select/__stories__/WithCustomLowMaxHeight.js +17 -0
  140. package/src/simple-single-select/__stories__/WithCustomOptions.js +78 -0
  141. package/src/simple-single-select/__stories__/WithDisabledOption.js +25 -0
  142. package/src/simple-single-select/__stories__/WithFilterField.js +30 -0
  143. package/src/simple-single-select/__stories__/WithInitialFocus.js +29 -0
  144. package/src/simple-single-select/__stories__/WithManyOptions.js +19 -0
  145. package/src/simple-single-select/__stories__/WithMultipleSelectsAndScrollableParent.js +65 -0
  146. package/src/simple-single-select/__stories__/WithNoMatchText.js +25 -0
  147. package/src/simple-single-select/__stories__/WithOnBlur.js +22 -0
  148. package/src/simple-single-select/__stories__/WithOnFocus.js +22 -0
  149. package/src/simple-single-select/__stories__/WithOptionsAndDisabled.js +17 -0
  150. package/src/simple-single-select/__stories__/WithOptionsAndLoading.js +23 -0
  151. package/src/simple-single-select/__stories__/WithOptionsAndLoadingText.js +24 -0
  152. package/src/simple-single-select/__stories__/WithPlaceholder.js +18 -0
  153. package/src/simple-single-select/__stories__/WithPlaceholderAndSelection.js +20 -0
  154. package/src/simple-single-select/__stories__/WithPrefix.js +17 -0
  155. package/src/simple-single-select/__stories__/WithPrefixAndSelection.js +20 -0
  156. package/src/simple-single-select/__stories__/WithRTL.js +29 -0
  157. package/src/simple-single-select/__stories__/WithScrollingParent.js +51 -0
  158. package/src/simple-single-select/__stories__/WithSelection.js +19 -0
  159. package/src/simple-single-select/__stories__/WithSelectionAndDisabled.js +20 -0
  160. package/src/simple-single-select/__stories__/WithServerSideFilteringDemo.js +245 -0
  161. package/src/simple-single-select/__stories__/WithSimpleFilteringDemo.js +50 -0
  162. package/src/simple-single-select/__stories__/WithoutOptionsAndLoading.js +16 -0
  163. package/src/simple-single-select/__stories__/WithoutSelection.js +17 -0
  164. package/src/simple-single-select/__stories__/options.js +96 -0
  165. package/src/simple-single-select/__stories__/simple-single-select-server-side-filtering/CustomDataProvider.js +70 -0
  166. package/src/simple-single-select/__stories__/simple-single-select-server-side-filtering/dataElements.js +4271 -0
  167. package/src/simple-single-select/__stories__/simple-single-select-server-side-filtering/index.js +1 -0
  168. package/src/simple-single-select/features/keyboard-interactions.test.e2e.js +581 -0
  169. package/src/simple-single-select/features/menu-positioning.test.e2e.js +187 -0
  170. package/src/simple-single-select/index.js +2 -0
  171. package/src/simple-single-select/is-option-hidden.js +21 -0
  172. package/src/simple-single-select/menu/empty.js +27 -0
  173. package/src/simple-single-select/menu/filter.js +61 -0
  174. package/src/simple-single-select/menu/index.js +1 -0
  175. package/src/simple-single-select/menu/loading.js +38 -0
  176. package/src/simple-single-select/menu/menu.js +171 -0
  177. package/src/simple-single-select/menu/no-match.js +28 -0
  178. package/src/simple-single-select/menu/option.js +161 -0
  179. package/src/simple-single-select/menu/options-list.js +107 -0
  180. package/src/simple-single-select/selected-value/clear-button.js +71 -0
  181. package/src/simple-single-select/selected-value/container.js +146 -0
  182. package/src/simple-single-select/selected-value/index.js +1 -0
  183. package/src/simple-single-select/selected-value/placeholder.js +24 -0
  184. package/src/simple-single-select/selected-value/prefix.js +26 -0
  185. package/src/simple-single-select/selected-value/selected-value.js +174 -0
  186. package/src/simple-single-select/shared-prop-types.js +8 -0
  187. package/src/simple-single-select/simple-single-select.e2e.stories.js +216 -0
  188. package/src/simple-single-select/simple-single-select.js +389 -0
  189. package/src/simple-single-select/simple-single-select.prod.stories.js +41 -0
  190. package/src/simple-single-select/simple-single-select.test.js +1136 -0
  191. package/src/simple-single-select/use-handle-key-press/index.js +2 -0
  192. package/src/simple-single-select/use-handle-key-press/use-focus-option.js +24 -0
  193. package/src/simple-single-select/use-handle-key-press/use-handle-key-press-on-combobox.js +259 -0
  194. package/src/simple-single-select/use-handle-key-press/use-handle-key-press-on-filter-input.js +147 -0
  195. package/src/simple-single-select/use-handle-key-press/use-handle-typing.js +79 -0
  196. package/src/simple-single-select/use-handle-key-press/use-highlight-first-option-on-previous-page.js +62 -0
  197. package/src/simple-single-select/use-handle-key-press/use-highlight-first-visible-option.js +38 -0
  198. package/src/simple-single-select/use-handle-key-press/use-highlight-last-option-on-next-page.js +60 -0
  199. package/src/simple-single-select/use-handle-key-press/use-highlight-last-visible-option.js +52 -0
  200. package/src/simple-single-select/use-handle-key-press/use-page-down.js +50 -0
  201. package/src/simple-single-select/use-handle-key-press/use-page-up.js +50 -0
  202. package/src/simple-single-select/use-handle-key-press/utils.js +23 -0
  203. package/src/simple-single-select-field/index.js +1 -0
  204. package/src/simple-single-select-field/simple-single-select-field.js +198 -0
  205. package/src/simple-single-select-field/simple-single-select-field.prod.stories.js +188 -0
  206. package/src/simple-single-select-field/simple-single-select-field.test.js +144 -0
  207. package/src/single-select/__tests__/selection.test.js +102 -0
  208. package/src/single-select/__tests__/single-select.test.js +23 -0
  209. package/src/single-select/features/accepts_blur_cb/index.js +14 -0
  210. package/src/single-select/features/accepts_blur_cb.feature +8 -0
  211. package/src/single-select/features/accepts_focus_cb/index.js +14 -0
  212. package/src/single-select/features/accepts_focus_cb.feature +6 -0
  213. package/src/single-select/features/accepts_initial_focus/index.js +5 -0
  214. package/src/single-select/features/accepts_initial_focus.feature +5 -0
  215. package/src/single-select/features/accepts_loading/index.js +22 -0
  216. package/src/single-select/features/accepts_loading.feature +14 -0
  217. package/src/single-select/features/accepts_max_height/index.js +31 -0
  218. package/src/single-select/features/accepts_max_height.feature +11 -0
  219. package/src/single-select/features/accepts_placeholder/index.js +25 -0
  220. package/src/single-select/features/accepts_placeholder.feature +10 -0
  221. package/src/single-select/features/accepts_prefix/index.js +19 -0
  222. package/src/single-select/features/accepts_prefix.feature +10 -0
  223. package/src/single-select/features/allows_invalid_options/index.js +28 -0
  224. package/src/single-select/features/allows_invalid_options.feature +12 -0
  225. package/src/single-select/features/allows_selecting/index.js +38 -0
  226. package/src/single-select/features/allows_selecting.feature +21 -0
  227. package/src/single-select/features/can_be_cleared/index.js +22 -0
  228. package/src/single-select/features/can_be_cleared.feature +6 -0
  229. package/src/single-select/features/can_be_disabled/index.js +39 -0
  230. package/src/single-select/features/can_be_disabled.feature +32 -0
  231. package/src/single-select/features/can_be_empty/index.js +28 -0
  232. package/src/single-select/features/can_be_empty.feature +16 -0
  233. package/src/single-select/features/can_be_filtered/index.js +23 -0
  234. package/src/single-select/features/can_be_filtered.feature +14 -0
  235. package/src/single-select/features/can_be_opened_and_closed/index.js +32 -0
  236. package/src/single-select/features/can_be_opened_and_closed.feature +41 -0
  237. package/src/single-select/features/common/index.js +44 -0
  238. package/src/single-select/features/duplicate_option_values/index.js +26 -0
  239. package/src/single-select/features/duplicate_option_values.feature +7 -0
  240. package/src/single-select/features/menu_width_matches_input/index.js +53 -0
  241. package/src/single-select/features/menu_width_matches_input.feature +11 -0
  242. package/src/single-select/features/position/index.js +111 -0
  243. package/src/single-select/features/position.feature +26 -0
  244. package/src/single-select/features/shows_selections/index.js +9 -0
  245. package/src/single-select/features/shows_selections.feature +5 -0
  246. package/src/single-select/filterable-menu.js +41 -0
  247. package/src/single-select/index.js +1 -0
  248. package/src/single-select/input.js +101 -0
  249. package/src/single-select/menu.js +75 -0
  250. package/src/single-select/selection.js +60 -0
  251. package/src/single-select/single-select.e2e.stories.js +376 -0
  252. package/src/single-select/single-select.js +146 -0
  253. package/src/single-select/single-select.prod.stories.js +358 -0
  254. package/src/single-select-field/__tests__/single-select-field.test.js +29 -0
  255. package/src/single-select-field/features/accepts_help_text/index.js +9 -0
  256. package/src/single-select-field/features/accepts_help_text.feature +5 -0
  257. package/src/single-select-field/features/accepts_label/index.js +9 -0
  258. package/src/single-select-field/features/accepts_label.feature +5 -0
  259. package/src/single-select-field/features/accepts_validation_text/index.js +9 -0
  260. package/src/single-select-field/features/accepts_validation_text.feature +5 -0
  261. package/src/single-select-field/features/can_be_required/index.js +11 -0
  262. package/src/single-select-field/features/can_be_required.feature +5 -0
  263. package/src/single-select-field/features/has_default_clear_text/index.js +16 -0
  264. package/src/single-select-field/features/has_default_clear_text.feature +6 -0
  265. package/src/single-select-field/features/has_default_empty_text/index.js +13 -0
  266. package/src/single-select-field/features/has_default_empty_text.feature +6 -0
  267. package/src/single-select-field/features/has_default_filter_nomatch_text/index.js +17 -0
  268. package/src/single-select-field/features/has_default_filter_nomatch_text.feature +7 -0
  269. package/src/single-select-field/features/has_default_filter_placeholder/index.js +15 -0
  270. package/src/single-select-field/features/has_default_filter_placeholder.feature +6 -0
  271. package/src/single-select-field/features/has_default_loading_text/index.js +13 -0
  272. package/src/single-select-field/features/has_default_loading_text.feature +6 -0
  273. package/src/single-select-field/index.js +1 -0
  274. package/src/single-select-field/single-select-field.e2e.stories.js +45 -0
  275. package/src/single-select-field/single-select-field.js +178 -0
  276. package/src/single-select-field/single-select-field.prod.stories.js +146 -0
  277. package/src/single-select-option/index.js +1 -0
  278. package/src/single-select-option/single-select-option.js +84 -0
@@ -0,0 +1,106 @@
1
+ import PropTypes from 'prop-types'
2
+ import React, { Component } from 'react'
3
+ import { FilterInput } from './filter-input.js'
4
+ import { NoMatch } from './no-match.js'
5
+ import { filterIgnored, checkIfValidOption } from './option-helpers.js'
6
+
7
+ export class FilterableMenu extends Component {
8
+ state = {
9
+ filter: '',
10
+ }
11
+
12
+ onFilterChange = ({ value }) => {
13
+ this.setState({ filter: value })
14
+ }
15
+
16
+ render() {
17
+ const {
18
+ dataTest,
19
+ options,
20
+ onChange,
21
+ selected,
22
+ empty,
23
+ handleClose,
24
+ handleFocusInput,
25
+ placeholder,
26
+ noMatchText,
27
+ Menu,
28
+ } = this.props
29
+ const { filter } = this.state
30
+ const menuProps = {
31
+ onChange,
32
+ selected,
33
+ empty,
34
+ handleClose,
35
+ handleFocusInput,
36
+ dataTest,
37
+ }
38
+
39
+ const renderedOptions = filterIgnored(options)
40
+
41
+ // If there are no options or there's no filter, just pass everything through
42
+ if (React.Children.count(renderedOptions) === 0 || !filter) {
43
+ return (
44
+ <React.Fragment>
45
+ <FilterInput
46
+ dataTest={`${dataTest}-filterinput`}
47
+ placeholder={placeholder}
48
+ value={filter}
49
+ onChange={this.onFilterChange}
50
+ />
51
+ <Menu {...menuProps} options={options} />
52
+ </React.Fragment>
53
+ )
54
+ }
55
+
56
+ const filtered = React.Children.map(options, (child) => {
57
+ const isValidOption = checkIfValidOption(child)
58
+
59
+ // Filter it out if it's an invalid option
60
+ if (!isValidOption) {
61
+ return null
62
+ }
63
+
64
+ const { label } = child.props
65
+
66
+ // Filter by label, because that's the part of an option that's displayed to the user
67
+ const match = label.toLowerCase().includes(filter.toLowerCase())
68
+
69
+ return match ? child : null
70
+ })
71
+
72
+ const hasMatch = React.Children.count(filtered) > 0
73
+
74
+ return (
75
+ <React.Fragment>
76
+ <FilterInput
77
+ dataTest={`${dataTest}-filterinput`}
78
+ placeholder={placeholder}
79
+ value={filter}
80
+ onChange={this.onFilterChange}
81
+ />
82
+ {hasMatch ? (
83
+ <Menu {...menuProps} options={filtered} />
84
+ ) : (
85
+ <NoMatch message={noMatchText} />
86
+ )}
87
+ </React.Fragment>
88
+ )
89
+ }
90
+ }
91
+
92
+ FilterableMenu.propTypes = {
93
+ Menu: PropTypes.elementType.isRequired,
94
+ dataTest: PropTypes.string.isRequired,
95
+ noMatchText: PropTypes.string.isRequired,
96
+ selected: PropTypes.oneOfType([
97
+ PropTypes.string,
98
+ PropTypes.arrayOf(PropTypes.string),
99
+ ]).isRequired,
100
+ empty: PropTypes.node,
101
+ handleClose: PropTypes.func,
102
+ handleFocusInput: PropTypes.func,
103
+ options: PropTypes.node,
104
+ placeholder: PropTypes.string,
105
+ onChange: PropTypes.func,
106
+ }
@@ -0,0 +1,14 @@
1
+ export { Select } from './select.js'
2
+ export { Loading } from './loading.js'
3
+ export { FilterableMenu } from './filterable-menu.js'
4
+ export { Empty } from './empty.js'
5
+ export {
6
+ checkIfValidOption,
7
+ filterIgnored,
8
+ findOptionChild,
9
+ findOption,
10
+ removeOption,
11
+ } from './option-helpers.js'
12
+ export { InputClearButton } from './input-clear-button.js'
13
+ export { InputPlaceholder } from './input-placeholder.js'
14
+ export { InputPrefix } from './input-prefix.js'
@@ -0,0 +1,66 @@
1
+ import { colors, theme } from '@dhis2/ui-constants'
2
+ import { Tooltip } from '@dhis2-ui/tooltip'
3
+ import PropTypes from 'prop-types'
4
+ import React from 'react'
5
+
6
+ const InputClearButton = ({ onClear, clearText, className, dataTest }) => (
7
+ <Tooltip openDelay={500} content={clearText}>
8
+ <button
9
+ data-test={dataTest}
10
+ onClick={onClear}
11
+ type="button"
12
+ className={className}
13
+ >
14
+ <svg
15
+ width="16"
16
+ height="16"
17
+ viewBox="0 0 16 16"
18
+ fill="none"
19
+ xmlns="http://www.w3.org/2000/svg"
20
+ >
21
+ <path
22
+ d="M8 16A8 8 0 1 0 8 0a8 8 0 0 0 0 16Zm3.536-5.879a1 1 0 1 1-1.415 1.414l-2.12-2.12-2.122 2.121a1 1 0 1 1-1.415-1.414L6.586 8 4.464 5.878A1 1 0 1 1 5.88 4.464L8 6.586l2.121-2.121a1 1 0 1 1 1.415 1.414L9.415 8l2.12 2.121Z"
23
+ fill="none"
24
+ />
25
+ </svg>
26
+ <style jsx>{`
27
+ button {
28
+ background: none;
29
+ border: none;
30
+ display: flex;
31
+ flex-shrink: 0;
32
+ align-items: center;
33
+ justify-content: center;
34
+ cursor: pointer;
35
+ height: 24px;
36
+ width: 24px;
37
+ border-radius: 3px;
38
+ }
39
+ button svg {
40
+ flex-shrink: 0;
41
+ }
42
+ button svg path {
43
+ fill: ${colors.grey500};
44
+ }
45
+ button:hover svg path {
46
+ fill: ${colors.grey800};
47
+ }
48
+ button:hover {
49
+ background: ${colors.grey200};
50
+ }
51
+ button:focus {
52
+ outline: 2px solid ${theme.focus};
53
+ }
54
+ `}</style>
55
+ </button>
56
+ </Tooltip>
57
+ )
58
+
59
+ InputClearButton.propTypes = {
60
+ clearText: PropTypes.string.isRequired,
61
+ dataTest: PropTypes.string.isRequired,
62
+ onClear: PropTypes.func.isRequired,
63
+ className: PropTypes.string,
64
+ }
65
+
66
+ export { InputClearButton }
@@ -0,0 +1,30 @@
1
+ import { colors } from '@dhis2/ui-constants'
2
+ import PropTypes from 'prop-types'
3
+ import React from 'react'
4
+
5
+ const InputPlaceholder = ({ placeholder, className, dataTest }) => {
6
+ if (!placeholder) {
7
+ return null
8
+ }
9
+
10
+ return (
11
+ <div className={className} data-test={dataTest}>
12
+ {placeholder}
13
+
14
+ <style jsx>{`
15
+ div {
16
+ color: ${colors.grey600};
17
+ user-select: none;
18
+ }
19
+ `}</style>
20
+ </div>
21
+ )
22
+ }
23
+
24
+ InputPlaceholder.propTypes = {
25
+ dataTest: PropTypes.string.isRequired,
26
+ className: PropTypes.string,
27
+ placeholder: PropTypes.string,
28
+ }
29
+
30
+ export { InputPlaceholder }
@@ -0,0 +1,32 @@
1
+ import { colors, spacers } from '@dhis2/ui-constants'
2
+ import PropTypes from 'prop-types'
3
+ import React from 'react'
4
+
5
+ const InputPrefix = ({ prefix, className, dataTest }) => {
6
+ if (!prefix) {
7
+ return null
8
+ }
9
+
10
+ return (
11
+ <div className={className} data-test={dataTest}>
12
+ {prefix}
13
+
14
+ <style jsx>{`
15
+ div {
16
+ color: ${colors.grey600};
17
+ padding-inline-end: ${spacers.dp12};
18
+ font-size: 14px;
19
+ user-select: none;
20
+ }
21
+ `}</style>
22
+ </div>
23
+ )
24
+ }
25
+
26
+ InputPrefix.propTypes = {
27
+ dataTest: PropTypes.string.isRequired,
28
+ className: PropTypes.string,
29
+ prefix: PropTypes.string,
30
+ }
31
+
32
+ export { InputPrefix }
@@ -0,0 +1,114 @@
1
+ import { colors, theme, sharedPropTypes } from '@dhis2/ui-constants'
2
+ import { IconChevronDown16 } from '@dhis2/ui-icons'
3
+ import cx from 'classnames'
4
+ import PropTypes from 'prop-types'
5
+ import React from 'react'
6
+
7
+ const InputWrapper = ({
8
+ dataTest,
9
+ onToggle,
10
+ children,
11
+ tabIndex = '0',
12
+ error,
13
+ warning,
14
+ valid,
15
+ disabled,
16
+ dense,
17
+ className,
18
+ inputRef,
19
+ }) => {
20
+ const classNames = cx(className, 'root', {
21
+ error,
22
+ warning,
23
+ valid,
24
+ disabled,
25
+ dense,
26
+ })
27
+
28
+ return (
29
+ <div
30
+ className={classNames}
31
+ onClick={onToggle}
32
+ tabIndex={tabIndex}
33
+ ref={inputRef}
34
+ data-test={dataTest}
35
+ >
36
+ <div className="root-children">{children}</div>
37
+ <div className="root-right">
38
+ <IconChevronDown16 />
39
+ </div>
40
+
41
+ <style jsx>{`
42
+ .root {
43
+ align-items: center;
44
+ background-color: white;
45
+ border-radius: 3px;
46
+ border: 1px solid ${colors.grey500};
47
+ box-sizing: border-box;
48
+ display: flex;
49
+ min-height: 40px;
50
+ padding-block: 6px;
51
+ padding-inline: 12px 6px;
52
+ box-shadow: inset 0 0 1px 0 rgba(48, 54, 60, 0.1);
53
+ }
54
+
55
+ .root:not(.disabled):focus,
56
+ .root:not(.disabled):active {
57
+ outline: none;
58
+ box-shadow: inset 0 0 0 2px ${theme.focus};
59
+ border-color: ${theme.focus};
60
+ }
61
+
62
+ .root.valid {
63
+ border-color: ${theme.valid};
64
+ }
65
+
66
+ .root.warning {
67
+ border-color: ${theme.warning};
68
+ }
69
+
70
+ .root.error {
71
+ border-color: ${theme.error};
72
+ }
73
+
74
+ .root.disabled {
75
+ background-color: ${colors.grey100};
76
+ border-color: ${colors.grey500};
77
+ color: ${theme.disabled};
78
+ cursor: not-allowed;
79
+ }
80
+
81
+ .root.dense {
82
+ padding-block: 2px;
83
+ padding-inline: 8px 4px;
84
+ min-height: 32px;
85
+ }
86
+
87
+ .root-children {
88
+ flex-grow: 1;
89
+ }
90
+
91
+ .root-right {
92
+ margin-block-start: 4px;
93
+ margin-inline-start: 2px;
94
+ }
95
+ `}</style>
96
+ </div>
97
+ )
98
+ }
99
+
100
+ InputWrapper.propTypes = {
101
+ dataTest: PropTypes.string.isRequired,
102
+ inputRef: PropTypes.object.isRequired,
103
+ onToggle: PropTypes.func.isRequired,
104
+ children: PropTypes.element,
105
+ className: PropTypes.string,
106
+ dense: PropTypes.bool,
107
+ disabled: PropTypes.bool,
108
+ error: sharedPropTypes.statusPropType,
109
+ tabIndex: PropTypes.string,
110
+ valid: sharedPropTypes.statusPropType,
111
+ warning: sharedPropTypes.statusPropType,
112
+ }
113
+
114
+ export { InputWrapper }
@@ -0,0 +1,33 @@
1
+ import { colors, spacers, theme } from '@dhis2/ui-constants'
2
+ import { CircularLoader } from '@dhis2-ui/loader'
3
+ import cx from 'classnames'
4
+ import PropTypes from 'prop-types'
5
+ import React from 'react'
6
+
7
+ export const Loading = ({ message, className, dataTest }) => (
8
+ <div className={cx(className, 'container')} data-test={dataTest}>
9
+ <div>
10
+ <CircularLoader small />
11
+ </div>
12
+ {message}
13
+ <style jsx>{`
14
+ .container {
15
+ display: flex;
16
+ gap: ${spacers.dp16};
17
+ align-items: center;
18
+ justify-content: center;
19
+ color: ${colors.grey700};
20
+ font-family: ${theme.fonts};
21
+ font-size: 13px;
22
+ padding-block: ${spacers.dp8};
23
+ padding-inline: ${spacers.dp24};
24
+ }
25
+ `}</style>
26
+ </div>
27
+ )
28
+
29
+ Loading.propTypes = {
30
+ dataTest: PropTypes.string.isRequired,
31
+ className: PropTypes.string,
32
+ message: PropTypes.string,
33
+ }
@@ -0,0 +1,52 @@
1
+ import { colors, elevations } from '@dhis2/ui-constants'
2
+ import { Layer } from '@dhis2-ui/layer'
3
+ import { Popper } from '@dhis2-ui/popper'
4
+ import PropTypes from 'prop-types'
5
+ import React from 'react'
6
+
7
+ const MenuWrapper = ({
8
+ children,
9
+ dataTest,
10
+ maxHeight = '280px',
11
+ menuWidth,
12
+ onClick,
13
+ selectRef,
14
+ }) => {
15
+ return (
16
+ <Layer onBackdropClick={onClick} transparent>
17
+ <Popper
18
+ reference={selectRef}
19
+ placement="bottom-start"
20
+ observeReferenceResize
21
+ >
22
+ <div data-test={`${dataTest}-menuwrapper`}>
23
+ {children}
24
+
25
+ <style jsx>{`
26
+ div {
27
+ width: ${menuWidth};
28
+ height: auto;
29
+ max-height: ${maxHeight};
30
+ overflow: auto;
31
+ background: ${colors.white};
32
+ border: 1px solid ${colors.grey200};
33
+ border-radius: 3px;
34
+ box-shadow: ${elevations.popover};
35
+ }
36
+ `}</style>
37
+ </div>
38
+ </Popper>
39
+ </Layer>
40
+ )
41
+ }
42
+
43
+ MenuWrapper.propTypes = {
44
+ dataTest: PropTypes.string.isRequired,
45
+ menuWidth: PropTypes.string.isRequired,
46
+ selectRef: PropTypes.object.isRequired,
47
+ children: PropTypes.node,
48
+ maxHeight: PropTypes.string,
49
+ onClick: PropTypes.func,
50
+ }
51
+
52
+ export { MenuWrapper }
@@ -0,0 +1,28 @@
1
+ import { colors, spacers, theme } from '@dhis2/ui-constants'
2
+ import PropTypes from 'prop-types'
3
+ import React from 'react'
4
+
5
+ const NoMatch = ({ message, className }) => (
6
+ <div className={className}>
7
+ {message}
8
+
9
+ <style jsx>{`
10
+ div {
11
+ color: ${colors.grey700};
12
+ font-family: ${theme.fonts};
13
+ font-size: 13px;
14
+ line-height: 16px;
15
+ padding-block: ${spacers.dp8};
16
+ padding-inline: ${spacers.dp24};
17
+ text-align: center;
18
+ }
19
+ `}</style>
20
+ </div>
21
+ )
22
+
23
+ NoMatch.propTypes = {
24
+ message: PropTypes.string.isRequired,
25
+ className: PropTypes.string,
26
+ }
27
+
28
+ export { NoMatch }
@@ -0,0 +1,34 @@
1
+ import React from 'react'
2
+
3
+ // Check whether an option is valid
4
+ export const checkIfValidOption = (option) =>
5
+ option &&
6
+ 'props' in option &&
7
+ 'value' in option.props &&
8
+ 'label' in option.props
9
+
10
+ // Filters all children that won't be rendered from an array of react children
11
+ export const filterIgnored = (children) =>
12
+ React.Children.toArray(children).filter(
13
+ (child) => child !== null && child !== false && child !== undefined
14
+ )
15
+
16
+ // Find an option in an array of react children
17
+ export const findOptionChild = (value, optionChildren) =>
18
+ React.Children.toArray(optionChildren).find((currentOption) => {
19
+ if (!currentOption.props) {
20
+ return false
21
+ }
22
+
23
+ return value === currentOption.props.value
24
+ })
25
+
26
+ // Find an option in an array of option objects
27
+ export const findOption = (value, optionArray) =>
28
+ optionArray.find((optionValue) => value === optionValue)
29
+
30
+ // Remove a specific option from an array of options
31
+ export const removeOption = (value, optionArray) =>
32
+ optionArray.filter((optionValue) => {
33
+ return optionValue !== value
34
+ })