@eturnity/eturnity_reusable_components 7.48.1-EPDM-11314.0 → 7.48.1-EPDM-12680.3

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 (375) hide show
  1. package/README.md +29 -29
  2. package/package.json +85 -85
  3. package/src/App.vue +30 -30
  4. package/src/Test.vue +128 -128
  5. package/src/assets/icons/arrow_down.svg +3 -3
  6. package/src/assets/icons/arrow_up_red.svg +3 -3
  7. package/src/assets/icons/black_spinner.svg +35 -35
  8. package/src/assets/icons/delete_icon.svg +11 -11
  9. package/src/assets/icons/delete_icon_gray.svg +11 -11
  10. package/src/assets/icons/drag_icon.svg +8 -8
  11. package/src/assets/icons/external_icon.svg +6 -6
  12. package/src/assets/icons/language_icon.svg +6 -6
  13. package/src/assets/icons/pdf_icon.svg +6 -6
  14. package/src/assets/icons/plus_button.svg +4 -4
  15. package/src/assets/icons/search_icon_black.svg +3 -3
  16. package/src/assets/icons/subposition_icon.svg +3 -3
  17. package/src/assets/icons/subposition_marker.svg +3 -3
  18. package/src/assets/icons/warning_icon.svg +3 -3
  19. package/src/assets/svgIcons/2d_active.svg +7 -7
  20. package/src/assets/svgIcons/2d_inactive.svg +8 -8
  21. package/src/assets/svgIcons/3d_active.svg +7 -7
  22. package/src/assets/svgIcons/3d_inactive.svg +8 -8
  23. package/src/assets/svgIcons/_readme.md +7 -7
  24. package/src/assets/svgIcons/accept.svg +5 -5
  25. package/src/assets/svgIcons/activate_panels_active.svg +22 -22
  26. package/src/assets/svgIcons/activate_panels_inactive.svg +20 -20
  27. package/src/assets/svgIcons/add_icon-1.svg +3 -3
  28. package/src/assets/svgIcons/add_icon.svg +4 -4
  29. package/src/assets/svgIcons/address_book.svg +3 -3
  30. package/src/assets/svgIcons/adjust_roof.svg +6 -6
  31. package/src/assets/svgIcons/after_sale_as_a_service.svg +6 -6
  32. package/src/assets/svgIcons/all_good.svg +3 -3
  33. package/src/assets/svgIcons/angle_active.svg +5 -5
  34. package/src/assets/svgIcons/angle_inactive.svg +4 -4
  35. package/src/assets/svgIcons/area_active.svg +11 -11
  36. package/src/assets/svgIcons/area_inactive.svg +26 -26
  37. package/src/assets/svgIcons/areas_tool.svg +14 -14
  38. package/src/assets/svgIcons/arrow_down.svg +3 -3
  39. package/src/assets/svgIcons/arrow_left.svg +4 -4
  40. package/src/assets/svgIcons/arrow_right.svg +4 -4
  41. package/src/assets/svgIcons/arrow_up.svg +3 -3
  42. package/src/assets/svgIcons/attachment.svg +3 -3
  43. package/src/assets/svgIcons/base_layer.svg +3 -3
  44. package/src/assets/svgIcons/battery.svg +3 -3
  45. package/src/assets/svgIcons/bell.svg +3 -3
  46. package/src/assets/svgIcons/bexio.svg +4 -4
  47. package/src/assets/svgIcons/bold.svg +3 -3
  48. package/src/assets/svgIcons/bom.svg +3 -3
  49. package/src/assets/svgIcons/bom_generation.svg +10 -10
  50. package/src/assets/svgIcons/bookmaker.svg +3 -3
  51. package/src/assets/svgIcons/bubble.svg +3 -3
  52. package/src/assets/svgIcons/bug.svg +5 -5
  53. package/src/assets/svgIcons/buildings.svg +55 -55
  54. package/src/assets/svgIcons/bullet_list.svg +8 -8
  55. package/src/assets/svgIcons/calendar.svg +7 -7
  56. package/src/assets/svgIcons/calendar_icon.svg +7 -7
  57. package/src/assets/svgIcons/call.svg +3 -3
  58. package/src/assets/svgIcons/camera.svg +3 -3
  59. package/src/assets/svgIcons/car.svg +3 -3
  60. package/src/assets/svgIcons/cart.svg +3 -3
  61. package/src/assets/svgIcons/charger_icon_white.svg +44 -44
  62. package/src/assets/svgIcons/checkbox.svg +3 -3
  63. package/src/assets/svgIcons/clear_formatting.svg +7 -7
  64. package/src/assets/svgIcons/clickable_info.svg +4 -4
  65. package/src/assets/svgIcons/clip.svg +3 -3
  66. package/src/assets/svgIcons/clock.svg +17 -17
  67. package/src/assets/svgIcons/clock_full.svg +3 -3
  68. package/src/assets/svgIcons/close_for_modals,_tool_tips.svg +4 -4
  69. package/src/assets/svgIcons/co_branding.svg +5 -5
  70. package/src/assets/svgIcons/collapse.svg +4 -4
  71. package/src/assets/svgIcons/collapse_all.svg +4 -0
  72. package/src/assets/svgIcons/collections.svg +3 -3
  73. package/src/assets/svgIcons/component_library.svg +7 -7
  74. package/src/assets/svgIcons/consumption_tariffs.svg +43 -43
  75. package/src/assets/svgIcons/context_menu-1.svg +6 -6
  76. package/src/assets/svgIcons/context_menu-2.svg +5 -5
  77. package/src/assets/svgIcons/context_menu.svg +5 -5
  78. package/src/assets/svgIcons/context_menu_tabs.svg +5 -5
  79. package/src/assets/svgIcons/cross.svg +4 -4
  80. package/src/assets/svgIcons/current_variant.svg +4 -4
  81. package/src/assets/svgIcons/dashboard.svg +3 -3
  82. package/src/assets/svgIcons/data_transfer.svg +3 -3
  83. package/src/assets/svgIcons/deadline.svg +4 -4
  84. package/src/assets/svgIcons/deal_flow.svg +5 -5
  85. package/src/assets/svgIcons/delete.svg +4 -4
  86. package/src/assets/svgIcons/delete_area_active.svg +16 -16
  87. package/src/assets/svgIcons/delete_area_inactive.svg +15 -15
  88. package/src/assets/svgIcons/direction_active-1.svg +12 -12
  89. package/src/assets/svgIcons/direction_active.svg +5 -5
  90. package/src/assets/svgIcons/direction_arrow.svg +4 -4
  91. package/src/assets/svgIcons/direction_inactive.svg +4 -4
  92. package/src/assets/svgIcons/dislike.svg +3 -3
  93. package/src/assets/svgIcons/distance_tool.svg +8 -8
  94. package/src/assets/svgIcons/distances_active.svg +9 -9
  95. package/src/assets/svgIcons/distances_inactive.svg +8 -8
  96. package/src/assets/svgIcons/distort_tool.svg +10 -10
  97. package/src/assets/svgIcons/distort_tool2.svg +16 -16
  98. package/src/assets/svgIcons/document.svg +3 -3
  99. package/src/assets/svgIcons/documents.svg +4 -4
  100. package/src/assets/svgIcons/downarrow.svg +3 -3
  101. package/src/assets/svgIcons/download.svg +4 -4
  102. package/src/assets/svgIcons/drag_icon.svg +8 -8
  103. package/src/assets/svgIcons/draggable_corner.svg +5 -5
  104. package/src/assets/svgIcons/draw_tool.svg +3 -3
  105. package/src/assets/svgIcons/duplicate-1.svg +8 -8
  106. package/src/assets/svgIcons/duplicate-2.svg +5 -5
  107. package/src/assets/svgIcons/duplicate.svg +4 -4
  108. package/src/assets/svgIcons/e-mobility_configurator.svg +6 -6
  109. package/src/assets/svgIcons/e_signature.svg +5 -5
  110. package/src/assets/svgIcons/edit_button.svg +3 -3
  111. package/src/assets/svgIcons/electricity_tariff.svg +3 -3
  112. package/src/assets/svgIcons/email.svg +3 -3
  113. package/src/assets/svgIcons/ems-1.svg +3 -3
  114. package/src/assets/svgIcons/ems.svg +3 -3
  115. package/src/assets/svgIcons/end_of_the_list.svg +5 -5
  116. package/src/assets/svgIcons/erase.svg +4 -4
  117. package/src/assets/svgIcons/external_icon.svg +5 -5
  118. package/src/assets/svgIcons/fav_icon.svg +4 -4
  119. package/src/assets/svgIcons/finance.svg +3 -3
  120. package/src/assets/svgIcons/financing_for_pv-1.svg +5 -5
  121. package/src/assets/svgIcons/financing_for_pv-2.svg +3 -3
  122. package/src/assets/svgIcons/financing_for_pv.svg +6 -6
  123. package/src/assets/svgIcons/finish-1.svg +4 -4
  124. package/src/assets/svgIcons/finish.svg +3 -3
  125. package/src/assets/svgIcons/flatten.svg +11 -11
  126. package/src/assets/svgIcons/flatten_roof.svg +20 -20
  127. package/src/assets/svgIcons/folder.svg +3 -3
  128. package/src/assets/svgIcons/free_technology.svg +5 -5
  129. package/src/assets/svgIcons/handle.svg +5 -5
  130. package/src/assets/svgIcons/heat_calc.svg +7 -7
  131. package/src/assets/svgIcons/height_equalize.svg +3 -3
  132. package/src/assets/svgIcons/height_snap.svg +3 -3
  133. package/src/assets/svgIcons/house.svg +3 -3
  134. package/src/assets/svgIcons/house_3d-1.svg +7 -7
  135. package/src/assets/svgIcons/house_3d.svg +7 -7
  136. package/src/assets/svgIcons/hybrid.svg +4 -0
  137. package/src/assets/svgIcons/inclination.svg +2 -2
  138. package/src/assets/svgIcons/info.svg +3 -3
  139. package/src/assets/svgIcons/initial_situation.svg +3 -3
  140. package/src/assets/svgIcons/integrations.svg +3 -3
  141. package/src/assets/svgIcons/intro-tour-1.svg +3 -3
  142. package/src/assets/svgIcons/intro-tour.svg +3 -3
  143. package/src/assets/svgIcons/inverter-1.svg +5 -5
  144. package/src/assets/svgIcons/inverter.svg +3 -3
  145. package/src/assets/svgIcons/italic.svg +3 -3
  146. package/src/assets/svgIcons/key.svg +3 -3
  147. package/src/assets/svgIcons/lake.svg +29 -29
  148. package/src/assets/svgIcons/layers_close.svg +4 -4
  149. package/src/assets/svgIcons/layers_open.svg +4 -4
  150. package/src/assets/svgIcons/lead_marketplace.svg +6 -6
  151. package/src/assets/svgIcons/lead_provider.svg +4 -4
  152. package/src/assets/svgIcons/length_2d.svg +2 -2
  153. package/src/assets/svgIcons/length_3d.svg +4 -4
  154. package/src/assets/svgIcons/length_calculator.svg +2 -2
  155. package/src/assets/svgIcons/length_in_2d_active.svg +12 -12
  156. package/src/assets/svgIcons/length_in_2d_inctive.svg +13 -13
  157. package/src/assets/svgIcons/light_bulb.svg +3 -3
  158. package/src/assets/svgIcons/like.svg +3 -3
  159. package/src/assets/svgIcons/line_graph.svg +3 -3
  160. package/src/assets/svgIcons/local_subsidies.svg +18 -18
  161. package/src/assets/svgIcons/location.svg +3 -3
  162. package/src/assets/svgIcons/lock.svg +3 -3
  163. package/src/assets/svgIcons/logout.svg +3 -3
  164. package/src/assets/svgIcons/loop.svg +3 -3
  165. package/src/assets/svgIcons/low-vegetation.svg +37 -37
  166. package/src/assets/svgIcons/lunch.svg +4 -4
  167. package/src/assets/svgIcons/magic_tool.svg +6 -6
  168. package/src/assets/svgIcons/map_icon.svg +5 -5
  169. package/src/assets/svgIcons/map_settings.svg +3 -3
  170. package/src/assets/svgIcons/margin_tool.svg +4 -4
  171. package/src/assets/svgIcons/meeting.svg +6 -6
  172. package/src/assets/svgIcons/module.svg +3 -0
  173. package/src/assets/svgIcons/move_copy.svg +4 -4
  174. package/src/assets/svgIcons/new_area_inactive.svg +11 -11
  175. package/src/assets/svgIcons/next.svg +4 -4
  176. package/src/assets/svgIcons/normal-tg.svg +30 -30
  177. package/src/assets/svgIcons/normal-vegetation.svg +53 -53
  178. package/src/assets/svgIcons/not_equal_to.svg +3 -3
  179. package/src/assets/svgIcons/numbered_list.svg +6 -6
  180. package/src/assets/svgIcons/obstacle_tool.svg +8 -8
  181. package/src/assets/svgIcons/obstacle_tool_origin.svg +3 -3
  182. package/src/assets/svgIcons/offset_tool.svg +8 -8
  183. package/src/assets/svgIcons/open-tg.svg +21 -21
  184. package/src/assets/svgIcons/optimizer.svg +6 -0
  185. package/src/assets/svgIcons/outline_tool.svg +11 -11
  186. package/src/assets/svgIcons/pan_tool.svg +12 -12
  187. package/src/assets/svgIcons/panels_tool.svg +8 -8
  188. package/src/assets/svgIcons/pen_tool.svg +4 -4
  189. package/src/assets/svgIcons/picker_tool.svg +4 -4
  190. package/src/assets/svgIcons/picture.svg +3 -3
  191. package/src/assets/svgIcons/pin.svg +5 -5
  192. package/src/assets/svgIcons/presentation.svg +3 -3
  193. package/src/assets/svgIcons/previous.svg +4 -4
  194. package/src/assets/svgIcons/profile-1.svg +4 -4
  195. package/src/assets/svgIcons/profile.svg +4 -4
  196. package/src/assets/svgIcons/profitability.svg +3 -3
  197. package/src/assets/svgIcons/project_analysis.svg +4 -4
  198. package/src/assets/svgIcons/project_settings.svg +4 -4
  199. package/src/assets/svgIcons/protected-tg.svg +47 -47
  200. package/src/assets/svgIcons/pv.svg +3 -3
  201. package/src/assets/svgIcons/quotations.svg +6 -6
  202. package/src/assets/svgIcons/redo.svg +6 -6
  203. package/src/assets/svgIcons/resizer.svg +5 -5
  204. package/src/assets/svgIcons/roof_layer.svg +3 -3
  205. package/src/assets/svgIcons/rotate_tool.svg +3 -3
  206. package/src/assets/svgIcons/rotate_view.svg +5 -5
  207. package/src/assets/svgIcons/ruler_tool.svg +3 -3
  208. package/src/assets/svgIcons/run_simulation.svg +3 -3
  209. package/src/assets/svgIcons/save.svg +3 -3
  210. package/src/assets/svgIcons/scaling_tool.svg +8 -8
  211. package/src/assets/svgIcons/sea.svg +34 -34
  212. package/src/assets/svgIcons/search.svg +3 -3
  213. package/src/assets/svgIcons/security.svg +3 -3
  214. package/src/assets/svgIcons/settings.svg +3 -3
  215. package/src/assets/svgIcons/show_in_a_new_tab.svg +12 -12
  216. package/src/assets/svgIcons/smartphone.svg +4 -4
  217. package/src/assets/svgIcons/solar_calc.svg +13 -13
  218. package/src/assets/svgIcons/sorting.svg +4 -4
  219. package/src/assets/svgIcons/split.svg +12 -12
  220. package/src/assets/svgIcons/start_of_the_list.svg +5 -5
  221. package/src/assets/svgIcons/strikethrough.svg +4 -4
  222. package/src/assets/svgIcons/string_design.svg +5 -0
  223. package/src/assets/svgIcons/subscriptions.svg +3 -3
  224. package/src/assets/svgIcons/subsidies-1.svg +5 -5
  225. package/src/assets/svgIcons/subsidies-2.svg +3 -3
  226. package/src/assets/svgIcons/subsidies.svg +3 -3
  227. package/src/assets/svgIcons/subtract_icon.svg +3 -3
  228. package/src/assets/svgIcons/suitcase.svg +3 -3
  229. package/src/assets/svgIcons/summer.svg +3 -3
  230. package/src/assets/svgIcons/template_icon_not_clickable.svg +6 -6
  231. package/src/assets/svgIcons/transfer.svg +4 -4
  232. package/src/assets/svgIcons/trim_tool.svg +4 -4
  233. package/src/assets/svgIcons/truck.svg +3 -3
  234. package/src/assets/svgIcons/underlined.svg +3 -3
  235. package/src/assets/svgIcons/undo.svg +6 -6
  236. package/src/assets/svgIcons/uparrow.svg +3 -3
  237. package/src/assets/svgIcons/update.svg +3 -3
  238. package/src/assets/svgIcons/upload_avatar-1.svg +12 -12
  239. package/src/assets/svgIcons/upload_avatar.svg +5 -5
  240. package/src/assets/svgIcons/upload_image.svg +8 -8
  241. package/src/assets/svgIcons/upload_image_tool.svg +7 -7
  242. package/src/assets/svgIcons/variants.svg +6 -6
  243. package/src/assets/svgIcons/vertical_tool.svg +3 -3
  244. package/src/assets/svgIcons/virtual_storage.svg +4 -4
  245. package/src/assets/svgIcons/warning.svg +4 -4
  246. package/src/assets/svgIcons/way.svg +5 -5
  247. package/src/assets/svgIcons/wifi.svg +3 -3
  248. package/src/assets/svgIcons/winter.svg +3 -3
  249. package/src/assets/svgIcons/workflow_template.svg +11 -11
  250. package/src/assets/tests/__mocks__/iconCache.js +1 -1
  251. package/src/assets/tests/__mocks__/svgMock.js +1 -1
  252. package/src/assets/tests/helpers.js +12 -12
  253. package/src/assets/theme.js +44 -44
  254. package/src/components/addNewButton/AddNewButton.stories.js +17 -17
  255. package/src/components/addNewButton/addNewButton.spec.js +23 -23
  256. package/src/components/addNewButton/index.vue +62 -62
  257. package/src/components/banner/actionBanner/ActionBanner.stories.js +45 -45
  258. package/src/components/banner/actionBanner/actionBanner.spec.js +76 -76
  259. package/src/components/banner/actionBanner/index.vue +86 -86
  260. package/src/components/banner/banner/Banner.stories.js +64 -64
  261. package/src/components/banner/banner/banner.spec.js +149 -149
  262. package/src/components/banner/banner/index.vue +205 -205
  263. package/src/components/banner/infoBanner/InfoBanner.spec.js +70 -70
  264. package/src/components/banner/infoBanner/InfoBanner.stories.js +42 -42
  265. package/src/components/banner/infoBanner/index.vue +97 -97
  266. package/src/components/buttons/buttonIcon/index.vue +147 -145
  267. package/src/components/buttons/closeButton/CloseButton.stories.js +25 -25
  268. package/src/components/buttons/closeButton/index.vue +62 -62
  269. package/src/components/buttons/mainButton/MainButton.stories.js +51 -51
  270. package/src/components/buttons/mainButton/index.vue +159 -150
  271. package/src/components/buttons/mainButton/mainButton.spec.js +35 -35
  272. package/src/components/card/Card.stories.js +79 -79
  273. package/src/components/card/card.spec.js +135 -135
  274. package/src/components/card/index.vue +116 -116
  275. package/src/components/collapsableInfoText/index.vue +127 -127
  276. package/src/components/deleteIcon/DeleteIcon.stories.js +29 -29
  277. package/src/components/deleteIcon/index.vue +78 -78
  278. package/src/components/draggableInputHandle/index.vue +46 -46
  279. package/src/components/dropdown/Dropdown.stories.js +53 -53
  280. package/src/components/dropdown/index.vue +138 -138
  281. package/src/components/errorMessage/index.vue +64 -64
  282. package/src/components/filter/filterSettings.vue +669 -669
  283. package/src/components/filter/index.vue +154 -154
  284. package/src/components/filter/parentDropdown.vue +91 -91
  285. package/src/components/icon/Icons.stories.js +41 -41
  286. package/src/components/icon/iconCache.mjs +23 -23
  287. package/src/components/icon/iconCollection.vue +82 -82
  288. package/src/components/icon/index.vue +141 -140
  289. package/src/components/iconWrapper/index.vue +179 -179
  290. package/src/components/infoCard/index.vue +67 -140
  291. package/src/components/infoText/index.vue +190 -190
  292. package/src/components/inputs/checkbox/Checkbox.stories.js +63 -63
  293. package/src/components/inputs/checkbox/checkbox.spec.js +109 -109
  294. package/src/components/inputs/checkbox/index.vue +225 -225
  295. package/src/components/inputs/inputNumber/InputNumber.stories.js +150 -150
  296. package/src/components/inputs/inputNumber/index.vue +963 -789
  297. package/src/components/inputs/inputNumberQuestion/index.vue +218 -218
  298. package/src/components/inputs/inputText/InputText.stories.js +70 -70
  299. package/src/components/inputs/inputText/index.vue +438 -417
  300. package/src/components/inputs/inputText/inputText.spec.js +588 -588
  301. package/src/components/inputs/radioButton/RadioButton.stories.js +77 -77
  302. package/src/components/inputs/radioButton/defaultProps.js +33 -31
  303. package/src/components/inputs/radioButton/index.vue +330 -309
  304. package/src/components/inputs/radioButton/radioButton.spec.js +269 -269
  305. package/src/components/inputs/searchInput/SearchInput.stories.js +66 -66
  306. package/src/components/inputs/searchInput/defaultProps.js +12 -12
  307. package/src/components/inputs/searchInput/index.vue +159 -159
  308. package/src/components/inputs/searchInput/searchInput.spec.js +64 -64
  309. package/src/components/inputs/select/index.vue +952 -918
  310. package/src/components/inputs/select/option/index.vue +165 -156
  311. package/src/components/inputs/select/select.stories.js +58 -58
  312. package/src/components/inputs/slider/index.vue +126 -126
  313. package/src/components/inputs/switchField/index.vue +254 -254
  314. package/src/components/inputs/textAreaInput/TextAreaInput.stories.js +127 -127
  315. package/src/components/inputs/textAreaInput/index.vue +198 -198
  316. package/src/components/inputs/toggle/Toggle.stories.js +77 -77
  317. package/src/components/inputs/toggle/index.vue +317 -317
  318. package/src/components/inputs/toggle/toggle.spec.js +102 -102
  319. package/src/components/label/index.vue +99 -99
  320. package/src/components/markerItem/index.vue +95 -88
  321. package/src/components/modals/actionModal/index.vue +64 -64
  322. package/src/components/modals/infoModal/index.vue +52 -52
  323. package/src/components/modals/modal/index.vue +190 -196
  324. package/src/components/modals/modal/modal.stories.js +31 -31
  325. package/src/components/navigationTabs/index.vue +114 -114
  326. package/src/components/pageSubtitle/PageSubtitle.stories.js +59 -59
  327. package/src/components/pageSubtitle/index.vue +78 -78
  328. package/src/components/pageSubtitle/pageSubtitle.spec.js +46 -46
  329. package/src/components/pageTitle/PageTitle.stories.js +95 -95
  330. package/src/components/pageTitle/index.vue +91 -91
  331. package/src/components/pageTitle/pageTitle.spec.js +46 -46
  332. package/src/components/pagination/index.vue +148 -148
  333. package/src/components/progressBar/index.vue +125 -125
  334. package/src/components/projectMarker/index.vue +300 -300
  335. package/src/components/rangeSlider/Slider.vue +573 -573
  336. package/src/components/rangeSlider/index.vue +517 -517
  337. package/src/components/rangeSlider/utils/dom.js +49 -49
  338. package/src/components/rangeSlider/utils/fns.js +26 -26
  339. package/src/components/roundTabs/index.vue +107 -107
  340. package/src/components/selectedOptions/index.vue +471 -471
  341. package/src/components/selectedOptions/selectedOptions.spec.js +176 -176
  342. package/src/components/selectedOptions/selectedOptions.stories.js +155 -155
  343. package/src/components/sideMenu/index.vue +270 -270
  344. package/src/components/spinner/Spinner.stories.js +34 -34
  345. package/src/components/spinner/index.vue +96 -85
  346. package/src/components/spinner/spinner.spec.js +69 -69
  347. package/src/components/stringDesign/DropdownMenu/index.vue +431 -0
  348. package/src/components/tableDropdown/index.vue +638 -638
  349. package/src/components/tables/mainTable/exampleNested.vue +328 -328
  350. package/src/components/tables/mainTable/index.vue +510 -510
  351. package/src/components/tables/viewTable/index.vue +195 -195
  352. package/src/components/tabsHeader/index.vue +83 -83
  353. package/src/components/threeDots/index.vue +413 -413
  354. package/src/components/videoThumbnail/index.vue +103 -103
  355. package/src/components/videoThumbnail/videoThumbnail.stories.js +33 -33
  356. package/src/helpers/currencyMapping.js +28 -28
  357. package/src/helpers/numberConverter.js +103 -103
  358. package/src/helpers/translateLang.js +128 -128
  359. package/src/main.js +7 -7
  360. package/src/mixins/inputValidations.js +97 -97
  361. package/src/router/dynamicRoutes.js +23 -23
  362. package/src/stories/Button.stories.js +48 -48
  363. package/src/stories/Button.vue +52 -52
  364. package/src/stories/Configure.mdx +364 -364
  365. package/src/stories/Header.stories.js +41 -41
  366. package/src/stories/Header.vue +59 -59
  367. package/src/stories/Page.stories.js +30 -30
  368. package/src/stories/Page.vue +83 -83
  369. package/src/stories/button.css +30 -30
  370. package/src/stories/header.css +32 -32
  371. package/src/stories/page.css +69 -69
  372. package/src/utils/index.js +12 -12
  373. package/src/components/infoCard/InfoCard.stories.js +0 -144
  374. package/src/components/infoCard/defaultProps.js +0 -7
  375. package/src/components/infoCard/infoCard.spec.js +0 -56
@@ -1,918 +1,952 @@
1
- <template>
2
- <Container
3
- :no-relative="noRelative"
4
- :select-width="selectWidth"
5
- @mouseenter="mouseEnterHandler"
6
- @mouseleave="mouseLeaveHandler"
7
- >
8
- <InputWrapper
9
- :align-items="alignItems"
10
- :has-label="!!label && label.length > 0"
11
- :no-relative="noRelative"
12
- >
13
- <LabelWrapper
14
- v-if="label"
15
- :data-id="labelDataId"
16
- :info-text-message="!!infoTextMessage || !!$slots.infoText"
17
- >
18
- <InputLabel
19
- :font-color="
20
- labelFontColor || colorMode == 'dark' ? 'white' : 'eturnityGrey'
21
- "
22
- :font-size="fontSize"
23
- >{{ label }}
24
- <OptionalLabel v-if="labelOptional">
25
- ({{ $gettext('Optional') }})</OptionalLabel
26
- >
27
- </InputLabel>
28
- <InfoText
29
- v-if="infoTextMessage || !!$slots.infoText"
30
- :align-arrow="infoTextAlignArrow"
31
- :max-width="infoTextWidth"
32
- :size="infoTextSize"
33
- :text="infoTextMessage"
34
- :width="infoTextWidth"
35
- >
36
- <slot name="infoText"></slot>
37
- </InfoText>
38
- </LabelWrapper>
39
- <SelectButtonWrapper :disabled="disabled">
40
- <SelectButton
41
- ref="select"
42
- :bg-color="
43
- buttonBgColor || colorMode == 'dark' ? 'transparentBlack1' : 'white'
44
- "
45
- class="select-button"
46
- :data-id="dataId"
47
- :disabled="disabled"
48
- :font-color="
49
- buttonFontColor || colorMode == 'dark' ? 'white' : 'black'
50
- "
51
- :font-size="fontSize"
52
- :has-error="hasError"
53
- :has-no-padding="isSearchBarVisible || !hasSelectButtonPadding"
54
- :height="height"
55
- :no-relative="noRelative"
56
- :padding-left="paddingLeft"
57
- :select-height="selectHeight"
58
- :select-min-height="selectMinHeight"
59
- :select-width="selectWidth"
60
- :show-border="showBorder"
61
- :show-disabled-background="showDisabledBackground"
62
- :table-padding-left="tablePaddingLeft"
63
- @click="toggleDropdown"
64
- @keydown="onKeyDown"
65
- >
66
- <DraggableInputHandle
67
- v-if="isDraggable && !isSearchBarVisible"
68
- :height="selectHeight"
69
- />
70
- <InputText
71
- v-if="isSearchBarVisible"
72
- ref="searchInput"
73
- background-color="transparent"
74
- :font-color="
75
- buttonFontColor || colorMode == 'dark' ? 'white' : 'black'
76
- "
77
- :font-size="fontSize"
78
- input-height="34px"
79
- :input-width="computedWidth"
80
- :no-border="true"
81
- tabindex="0"
82
- :value="textSearch"
83
- @click.stop
84
- @input-change="searchChange"
85
- @keydown.stop="onKeyDown"
86
- />
87
- <Selector
88
- v-else
89
- :disabled="disabled"
90
- :padding-left="paddingLeft"
91
- :select-width="selectWidth"
92
- :show-border="showBorder"
93
- >
94
- <slot name="selector" :selected-value="selectedValue"></slot>
95
- </Selector>
96
- <Caret class="caret_dropdown" @click.stop="toggleCaretDropdown">
97
- <Icon
98
- v-if="isDropdownOpen"
99
- :color="
100
- caretColor || disabled
101
- ? 'grey2'
102
- : colorMode == 'dark'
103
- ? 'white'
104
- : 'transparentBlack1'
105
- "
106
- name="arrow_up"
107
- size="12px"
108
- />
109
- <Icon
110
- v-else
111
- :color="
112
- caretColor || disabled
113
- ? 'grey2'
114
- : colorMode == 'dark'
115
- ? 'white'
116
- : 'transparentBlack1'
117
- "
118
- name="arrow_down"
119
- size="12px"
120
- />
121
- </Caret>
122
- </SelectButton>
123
- <DropdownWrapper ref="dropdownWrapperRef" :no-relative="noRelative">
124
- <Teleport to="#portal-target">
125
- <SelectDropdown
126
- v-show="isSelectDropdownShown"
127
- ref="dropdown"
128
- :bg-color="
129
- dropdownBgColor || colorMode == 'dark' ? 'black' : 'white'
130
- "
131
- :dropdown-position="dropdownPosition"
132
- :font-color="
133
- dropdownFontColor || colorMode == 'dark' ? 'white' : 'black'
134
- "
135
- :font-size="fontSize"
136
- :hovered-bg-color="
137
- colorMode == 'dark' ? '#000000' : dropdownBgColor
138
- "
139
- :hovered-index="hoveredIndex"
140
- :hovered-value="hoveredValue"
141
- :is-active="isActive"
142
- :min-width="minWidth"
143
- :no-relative="noRelative"
144
- :option-width="getOptionWidth"
145
- :selected-value="selectedValue"
146
- @mouseleave="optionLeave"
147
- @option-hovered="optionHovered"
148
- @option-selected="optionSelected"
149
- >
150
- <slot name="dropdown"></slot>
151
- </SelectDropdown>
152
- </Teleport>
153
- </DropdownWrapper>
154
- </SelectButtonWrapper>
155
- </InputWrapper>
156
- </Container>
157
- </template>
158
-
159
- <script>
160
- //How to use it
161
- // <Select
162
- // hoverDropdown="true"
163
- // selectWidth="100%"
164
- // minWidth="220px"
165
- // optionWidth="50%"
166
- // label="that is a label"
167
- // alignItems="vertical"
168
- // label-data-id="test-label-data-id"
169
- // data-id="test-data-id"
170
- // :hasSelectButtonPadding="false"
171
- // >
172
- // <template #selector="{selectedValue}">
173
- // value selected: {{selectedValue}}
174
- // </template>
175
- // <template #dropdown>
176
- // <Option value="1">value one</Option>
177
- // <Option value="2">value two</Option>
178
- // <Option value="3">value three</Option>
179
- // <Option value="4">value four</Option>
180
- // </template>
181
- // </Select>
182
-
183
- import { Teleport } from 'vue'
184
- import styled from 'vue3-styled-components'
185
- import InfoText from '../../infoText'
186
- import Icon from '../../icon'
187
- import InputText from '../inputText'
188
- import DraggableInputHandle from '../../draggableInputHandle'
189
- import { debounce } from '../../../utils'
190
-
191
- const CARET_WIDTH = '30px'
192
- const BORDER_WIDTH = '1px'
193
-
194
- const Caret = styled.div`
195
- display: flex;
196
- align-items: center;
197
- justify-content: center;
198
- width: ${CARET_WIDTH};
199
- min-width: ${CARET_WIDTH};
200
- height: 100%;
201
- align-items: center;
202
- cursor: pointer;
203
- margin-left: auto;
204
- `
205
-
206
- const selectorProps = {
207
- disabled: Boolean,
208
- selectWidth: String,
209
- paddingLeft: String,
210
- showBorder: Boolean,
211
- }
212
- const Selector = styled('div', selectorProps)`
213
- color: ${(props) => (props.disabled ? props.theme.colors.grey2 : '')};
214
- ${(props) =>
215
- props.selectWidth === '100%'
216
- ? 'width: 100%;'
217
- : `width: calc(${props.selectWidth} -
218
- (
219
- ${CARET_WIDTH} +
220
- ${props.paddingLeft}
221
- ${props.showBorder ? `+ (${BORDER_WIDTH} * 2)` : ''}
222
- )
223
- );
224
- white-space: nowrap;
225
- text-overflow: ellipsis;
226
- overflow: hidden;`}
227
- `
228
-
229
- const labelAttrs = { fontSize: String, fontColor: String }
230
- const InputLabel = styled('div', labelAttrs)`
231
- color: ${(props) =>
232
- props.theme.colors[props.fontColor]
233
- ? props.theme.colors[props.fontColor]
234
- : props.fontColor};
235
- font-size: ${(props) => props.fontSize};
236
- font-weight: 700;
237
- `
238
- const OptionalLabel = styled.span`
239
- font-weight: 300;
240
- `
241
- const inputProps = {
242
- selectWidth: String,
243
- optionWidth: String,
244
- noRelative: Boolean,
245
- }
246
- const Container = styled('div', inputProps)`
247
- width: ${(props) => props.selectWidth};
248
- position: ${(props) => (props.noRelative ? 'static' : 'relative')};
249
- display: inline-block;
250
- `
251
-
252
- const LabelWrapperAttrs = { infoTextMessage: Boolean }
253
- const LabelWrapper = styled('div', LabelWrapperAttrs)`
254
- display: inline-grid;
255
- grid-template-columns: ${(props) =>
256
- props.infoTextMessage ? 'auto auto' : 'auto'};
257
- grid-gap: 12px;
258
- align-items: center;
259
- justify-content: start;
260
- `
261
-
262
- const SelectButtonWrapperAttrs = {
263
- disabled: Boolean,
264
- }
265
- const SelectButtonWrapper = styled('div', SelectButtonWrapperAttrs)`
266
- ${(props) => (props.disabled ? 'cursor: not-allowed' : 'cursor: pointer')};
267
- `
268
-
269
- const selectButtonAttrs = {
270
- bgColor: String,
271
- fontColor: String,
272
- hasError: Boolean,
273
- disabled: Boolean,
274
- selectHeight: String,
275
- selectWidth: String,
276
- height: String,
277
- selectMinHeight: String,
278
- hasNoPadding: Boolean,
279
- showBorder: Boolean,
280
- paddingLeft: String,
281
- noRelative: Boolean,
282
- tablePaddingLeft: String,
283
- showDisabledBackground: Boolean,
284
- }
285
- const SelectButton = styled('div', selectButtonAttrs)`
286
- position: ${(props) => (props.noRelative ? 'static' : 'relative')};
287
- box-sizing: border-box;
288
- border-radius: 4px;
289
- max-width: ${(props) => (props.selectWidth ? props.selectWidth : '100%')};
290
- ${(props) =>
291
- props.isSearchBarVisible
292
- ? ''
293
- : `padding-left: ${
294
- props.hasNoPadding
295
- ? '0'
296
- : props.tablePaddingLeft
297
- ? props.tablePaddingLeft
298
- : props.paddingLeft
299
- }`};
300
- text-align: left;
301
- min-height: ${(props) =>
302
- props.selectHeight
303
- ? props.selectHeight
304
- : props.selectMinHeight
305
- ? props.selectMinHeight
306
- : props.height
307
- ? props.height
308
- : '36px'};
309
- display: flex;
310
- align-items: center;
311
- height: ${(props) => props.selectHeight};
312
- ${({ showBorder, theme, hasError }) =>
313
- showBorder &&
314
- `
315
- border: ${BORDER_WIDTH} solid ${
316
- hasError ? theme.colors.red : theme.colors.grey4
317
- }
318
- `}
319
- background-color:${(props) =>
320
- props.disabled && props.showDisabledBackground
321
- ? props.theme.colors.grey5
322
- : props.theme.colors[props.bgColor]
323
- ? props.theme.colors[props.bgColor]
324
- : props.bgColor};
325
- color: ${(props) =>
326
- props.theme.colors[props.fontColor]
327
- ? props.theme.colors[props.fontColor]
328
- : props.fontColor};
329
- ${(props) => (props.disabled ? 'pointer-events: none' : '')};
330
- overflow: hidden;
331
- & > .handle {
332
- border-right: ${(props) =>
333
- props.hasError ? props.theme.colors.red : props.theme.colors.grey4}
334
- 1px solid;
335
- }
336
- `
337
- const selectDropdownAttrs = {
338
- hoveredBgColor: String,
339
- bgColor: String,
340
- fontColor: String,
341
- optionWidth: String,
342
- hoveredIndex: Number,
343
- fontSize: String,
344
- dropdownPosition: Object,
345
- hoveredValue: Number | String,
346
- selectedValue: Number | String,
347
- noRelative: Boolean,
348
- minWidth: String,
349
- }
350
- const SelectDropdown = styled('div', selectDropdownAttrs)`
351
- box-sizing: border-box;
352
- z-index: ${(props) => (props.isActive ? '2' : '99999')};
353
- position: absolute;
354
- top: ${(props) =>
355
- props.noRelative ? 'auto' : props.dropdownPosition?.top + 'px'};
356
- left: ${(props) => props.dropdownPosition?.left}px;
357
- border: ${BORDER_WIDTH} solid ${(props) => props.theme.colors.grey4};
358
- border-radius: 4px;
359
- display: flex;
360
- flex-direction: column;
361
- align-items: flex-start;
362
- padding: 0px;
363
- box-shadow: 0px 8px 16px 0px rgba(0, 0, 0, 0.2);
364
- width: ${(props) => (props.optionWidth ? props.optionWidth : '100%')};
365
- min-width: ${(props) =>
366
- props.minWidth
367
- ? props.minWidth
368
- : props.optionWidth
369
- ? props.optionWidth
370
- : '100%'};
371
- background-color: ${(props) =>
372
- props.theme.colors[props.bgColor]
373
- ? props.theme.colors[props.bgColor]
374
- : props.bgColor};
375
- color: ${(props) =>
376
- props.theme.colors[props.fontColor]
377
- ? props.theme.colors[props.fontColor]
378
- : props.fontColor};
379
- max-height: 300px;
380
- overflow-y: auto;
381
- & > div[data-value='${(props) => props.hoveredValue}'] {
382
- background-color: ${(props) =>
383
- props.theme.colors[props.hoveredBgColor]
384
- ? props.theme.colors[props.hoveredBgColor]
385
- : props.hoveredBgColor};
386
- }
387
- font-size: ${(props) => props.fontSize};
388
- `
389
- SelectDropdown.emits = ['option-hovered', 'option-selected']
390
- const DropdownAttrs = { noRelative: Boolean }
391
- const DropdownWrapper = styled('div', DropdownAttrs)`
392
- position: ${(props) => (props.noRelative ? 'static' : 'relative')};
393
- `
394
- const inputAttrs = {
395
- alignItems: String,
396
- hasLabel: Boolean,
397
- noRelative: Boolean,
398
- }
399
- const InputWrapper = styled('div', inputAttrs)`
400
- position: ${(props) => (props.noRelative ? 'static' : 'relative')};
401
- display: grid;
402
- width: 100%;
403
- min-width: ${(props) => (props.minWidth ? props.minWidth : '150px')};
404
- align-items: center;
405
- gap: 8px;
406
- grid-template-columns: ${(props) =>
407
- props.alignItems === 'vertical' || !props.hasLabel ? '1fr' : 'auto 1fr'};
408
- `
409
-
410
- const DROPDOWN_HEIGHT_OFFSET = 4
411
- const DROPDOWN_TOP_OFFSET = 21
412
- const MIN_OPTION_LENGTH = 5
413
-
414
- const DROPDOWN_MENU_POSITIONS = {
415
- Automatic: 'automatic',
416
- Bottom: 'bottom',
417
- }
418
-
419
- export default {
420
- name: 'RCselect',
421
-
422
- components: {
423
- SelectButton,
424
- SelectButtonWrapper,
425
- SelectDropdown,
426
- Container,
427
- InputLabel,
428
- LabelWrapper,
429
- OptionalLabel,
430
- InfoText,
431
- InputWrapper,
432
- DropdownWrapper,
433
- Icon,
434
- Caret,
435
- Selector,
436
- InputText,
437
- Teleport,
438
- DraggableInputHandle,
439
- },
440
-
441
- props: {
442
- value: {
443
- required: false,
444
- default: null,
445
- },
446
- fontSize: {
447
- required: false,
448
- default: '13px',
449
- },
450
- noRelative: {
451
- required: false,
452
- default: false,
453
- },
454
- label: {
455
- required: false,
456
- },
457
- labelOptional: {
458
- required: false,
459
- default: false,
460
- },
461
- labelDataId: {
462
- required: false,
463
- default: '',
464
- },
465
- infoTextMessage: {
466
- required: false,
467
- },
468
- selectWidth: {
469
- type: String,
470
- required: false,
471
- default: '100%',
472
- },
473
- minWidth: {
474
- required: false,
475
- },
476
- maxWidth: {
477
- required: false,
478
- },
479
- selectHeight: {
480
- type: String,
481
- required: false,
482
- default: null,
483
- },
484
- height: {
485
- required: false,
486
- default: null,
487
- },
488
- selectMinHeight: {
489
- required: false,
490
- default: '36px',
491
- },
492
- optionWidth: {
493
- required: false,
494
- default: null,
495
- },
496
- hoverDropdown: {
497
- required: false,
498
- default: false,
499
- },
500
- dropdownAutoClose: {
501
- required: false,
502
- default: false,
503
- },
504
- alignItems: {
505
- required: false,
506
- default: 'horizontal',
507
- },
508
- buttonBgColor: {
509
- required: false,
510
- },
511
- buttonFontColor: {
512
- required: false,
513
- },
514
- dropdownBgColor: {
515
- required: false,
516
- default: 'grey5',
517
- },
518
- dropdownFontColor: {
519
- required: false,
520
- },
521
- dropDownArrowVisible: {
522
- required: false,
523
- default: true,
524
- },
525
- caretColor: {
526
- required: false,
527
- },
528
- labelFontColor: {
529
- required: false,
530
- },
531
- colorMode: {
532
- required: false,
533
- default: 'light',
534
- },
535
- isSearchable: {
536
- required: false,
537
- default: true,
538
- },
539
- hasError: {
540
- required: false,
541
- default: false,
542
- },
543
- disabled: {
544
- required: false,
545
- type: Boolean,
546
- default: false,
547
- },
548
- isAutoSearch: {
549
- required: false,
550
- default: true,
551
- },
552
- showBorder: {
553
- required: false,
554
- default: true,
555
- },
556
- infoTextSize: {
557
- required: false,
558
- default: '14px',
559
- },
560
- dataId: {
561
- type: String,
562
- default: '',
563
- },
564
- hasSelectButtonPadding: {
565
- required: false,
566
- type: Boolean,
567
- default: true,
568
- },
569
- isDraggable: {
570
- type: Boolean,
571
- default: false,
572
- },
573
- leftPadding: {
574
- type: String,
575
- default: '15px',
576
- },
577
- tablePaddingLeft: {
578
- required: false,
579
- },
580
- showDisabledBackground: {
581
- required: false,
582
- default: true,
583
- },
584
- minOptionLength: {
585
- type: Number,
586
- default: MIN_OPTION_LENGTH,
587
- },
588
- dropdownMenuPosition: {
589
- type: String,
590
- default: DROPDOWN_MENU_POSITIONS.Automatic, // options: ['automatic', bottom]
591
- },
592
- infoTextWidth: {
593
- type: String,
594
- required: false,
595
- },
596
- infoTextAlignArrow: {
597
- type: String,
598
- required: false,
599
- },
600
- },
601
-
602
- data() {
603
- return {
604
- selectedValue: null,
605
- paddingLeft: this.isDraggable ? '30px' : this.leftPadding,
606
- isDropdownOpen: false,
607
- isActive: false,
608
- textSearch: '',
609
- hoveredIndex: 0,
610
- isClickOutsideActive: false,
611
- dropdownPosition: {
612
- left: null,
613
- top: null,
614
- },
615
- dropdownWidth: null,
616
- hoveredValue: null,
617
- }
618
- },
619
- computed: {
620
- optionLength() {
621
- if (this.isDropdownOpen) {
622
- return this.$refs.dropdown.$el.childElementCount > 1
623
- ? this.$refs.dropdown.$el.childElementCount
624
- : !!this.$refs.dropdown.$el.children[0]
625
- ? this.$refs.dropdown.$el.children[0].childElementCount
626
- : 0
627
- }
628
-
629
- return 0
630
- },
631
- isSearchBarVisible() {
632
- return (
633
- this.isSearchable &&
634
- this.optionLength >= this.minOptionLength &&
635
- this.isDropdownOpen
636
- )
637
- },
638
- computedWidth() {
639
- function removePX(item) {
640
- return Number(item.replace('px', ''))
641
- }
642
-
643
- return this.selectWidth === '100%'
644
- ? '100%'
645
- : removePX(this.selectWidth) - removePX(CARET_WIDTH) + 'px'
646
- },
647
- getOptionWidth() {
648
- if (this.optionWidth) return this.optionWidth
649
-
650
- return this.dropdownWidth
651
- },
652
- isSelectDropdownShown() {
653
- return (
654
- this.isDropdownOpen &&
655
- this.dropdownPosition.left !== null &&
656
- (!this.isSearchable || this.isSearchable)
657
- )
658
- },
659
- isMobileDevice() {
660
- const userAgent =
661
- navigator.userAgent || navigator.vendor || window.opera
662
- const touchCapable =
663
- 'ontouchstart' in window ||
664
- navigator.maxTouchPoints > 0 ||
665
- navigator.msMaxTouchPoints > 0
666
-
667
- return (
668
- /Android/i.test(userAgent) ||
669
- /iPad|iPhone|iPod/.test(userAgent) ||
670
- (/Macintosh/.test(userAgent) && touchCapable) ||
671
- /windows phone/i.test(userAgent)
672
- )
673
- },
674
- },
675
- watch: {
676
- value(val) {
677
- this.selectedValue = val
678
- },
679
- async isDropdownOpen(val) {
680
- if (val) {
681
- this.$emit('on-dropdown-open')
682
- setTimeout(() => {
683
- this.isClickOutsideActive = true
684
- }, 10)
685
- await this.$nextTick()
686
- this.handleSetDropdownOffet()
687
- } else {
688
- this.dropdownPosition.left = null
689
- setTimeout(() => {
690
- this.isClickOutsideActive = false
691
- }, 10)
692
- }
693
- if (val && this.isSearchable) {
694
- this.$nextTick(() => {
695
- if (this.$refs.searchInput && !this.isMobileDevice) {
696
- this.$refs.searchInput.$el.querySelector('input').focus()
697
- }
698
- })
699
- }
700
- },
701
- },
702
- mounted() {
703
- this.observeDropdownHeight()
704
- this.observeSelectWidth()
705
- window.addEventListener('resize', this.handleSetDropdownOffet)
706
- },
707
- beforeMount() {
708
- this.selectedValue = this.value
709
- document.addEventListener('click', this.clickOutside)
710
- this.getDropdownPosition()
711
- window.removeEventListener('resize', this.handleSetDropdownOffet)
712
- if (this.dropdownResizeObserver) this.dropdownResizeObserver.disconnect()
713
- if (this.selectResizeObserver) this.selectResizeObserver.disconnect()
714
- },
715
- unmounted() {
716
- document.removeEventListener('click', this.clickOutside)
717
- },
718
- methods: {
719
- focus() {
720
- this.isActive = true
721
- },
722
- blur(e) {
723
- this.isActive = false
724
- this.$emit('blur', e)
725
- },
726
- toggleDropdown() {
727
- this.isDropdownOpen = !this.isDropdownOpen
728
- },
729
- toggleCaretDropdown() {
730
- this.isDropdownOpen = !this.isDropdownOpen
731
- },
732
- closeDropdown() {
733
- this.blur()
734
- this.clearSearch()
735
- this.isDropdownOpen = false
736
- },
737
- clearSearch() {
738
- this.textSearch = ''
739
- this.searchChange('')
740
- },
741
- optionSelected(e) {
742
- this.selectedValue = e
743
- this.closeDropdown()
744
- this.blur()
745
- this.$emit('input-change', e)
746
- },
747
- optionHovered: debounce(function (e) {
748
- this.hoveredValue = e
749
- }, 300),
750
- mouseEnterHandler() {
751
- if (this.hoverDropdown) {
752
- this.focus()
753
- this.isDropdownOpen = true
754
- }
755
- },
756
- mouseLeaveHandler() {
757
- if (this.hoverDropdown) {
758
- this.blur()
759
- }
760
- },
761
- optionLeave() {
762
- if (this.dropdownAutoClose) {
763
- this.isDropdownOpen = false
764
- }
765
- },
766
- searchChange(value) {
767
- this.textSearch = value
768
- this.$emit('search-change', value)
769
- const dropdownChildren = [...this.$refs.dropdown.$el.children]
770
- dropdownChildren.forEach((el) => {
771
- if (!el.textContent.toLowerCase().includes(value.toLowerCase())) {
772
- el.style.display = 'none'
773
-
774
- return
775
- }
776
-
777
- el.style.display = 'inherit'
778
- })
779
- },
780
- clickOutside(event) {
781
- const dropdownRef = this.$refs.dropdown
782
- // we need to prevent closing on selecting an option, because in the case of
783
- // a disabled option, we don't want to close the dropdown
784
- if (!this.isClickOutsideActive) return
785
- if (
786
- this.$refs.select.$el == event.target ||
787
- this.$refs.select.$el.contains(event.target) ||
788
- event.target.id === 'more-button' ||
789
- event.target.parentNode === dropdownRef.$el
790
- ) {
791
- return
792
- } else {
793
- this.closeDropdown()
794
- }
795
- },
796
- onKeyDown(e) {
797
- if (e.key == 'ArrowDown') {
798
- this.onArrowPress(1)
799
- } else if (e.key == 'ArrowUp') {
800
- this.onArrowPress(-1)
801
- } else if (e.key == 'Enter') {
802
- const optionHoveredComponent = [...this.$refs.dropdown.$el.children][
803
- (this.hoveredIndex - 1 + this.optionLength) % this.optionLength
804
- ]
805
- this.optionSelected(optionHoveredComponent.$el.dataset.value)
806
- }
807
- },
808
- // If some part of the dropdown menu is outside viewport of the bottom of the screen,
809
- // we need to offset it and display it at the top of the select dropdown instead
810
- async getDropdownPosition() {
811
- if (
812
- !this.$refs.dropdownWrapperRef ||
813
- !this.$refs.select ||
814
- !this.$refs.dropdown
815
- ) {
816
- return
817
- }
818
- await this.$nextTick()
819
- const isDisplayedAtBottom = await this.generateDropdownPosition()
820
- // If the dropdown menu is going to be displayed at the bottom,
821
- // we need reverify its position after a dom update (nextTick)
822
- await this.$nextTick()
823
- if (isDisplayedAtBottom) this.generateDropdownPosition()
824
- },
825
- async generateDropdownPosition() {
826
- const isDropdownNotCompletelyVisible =
827
- await this.isBottomOfDropdownOutOfViewport()
828
- const dropdownWrapperEl = this.$refs.dropdownWrapperRef.$el
829
- const selectButtonHeight = this.$refs.select.$el.clientHeight
830
- const dropdownHeight = this.$refs.dropdown.$el.clientHeight
831
- const dropdownWrapperRelativeHeight =
832
- dropdownWrapperEl.getBoundingClientRect().top +
833
- window.scrollY +
834
- DROPDOWN_HEIGHT_OFFSET
835
-
836
- const top =
837
- isDropdownNotCompletelyVisible ||
838
- (!isDropdownNotCompletelyVisible &&
839
- this.dropdownMenuPosition === DROPDOWN_MENU_POSITIONS.Bottom)
840
- ? dropdownWrapperRelativeHeight
841
- : dropdownWrapperRelativeHeight -
842
- dropdownHeight -
843
- selectButtonHeight -
844
- DROPDOWN_TOP_OFFSET
845
- const left = this.dropdownPosition.left
846
- ? this.dropdownPosition.left
847
- : dropdownWrapperEl.getBoundingClientRect().left + window.scrollX
848
-
849
- this.dropdownPosition = { left: Math.floor(left), top: Math.floor(top) }
850
-
851
- return isDropdownNotCompletelyVisible
852
- },
853
- async isBottomOfDropdownOutOfViewport() {
854
- if (
855
- !this.$refs.dropdown ||
856
- this.dropdownMenuPosition === DROPDOWN_MENU_POSITIONS.Bottom
857
- ) {
858
- return false
859
- }
860
-
861
- await this.$nextTick()
862
- const rect = this.$refs.dropdown.$el.getBoundingClientRect()
863
- const windowHeight =
864
- window.innerHeight || document.documentElement.clientHeight
865
-
866
- if (windowHeight <= 650) return true
867
-
868
- // using Math.floor because the offsets may contain decimals we are not going to consider here
869
- return Math.floor(rect.top) + Math.floor(rect.height) <= windowHeight
870
- },
871
- observeDropdownHeight() {
872
- if (!this.$refs.dropdown) return
873
- this.dropdownResizeObserver = new ResizeObserver(() => {
874
- this.$nextTick(() => this.getDropdownPosition())
875
- })
876
- this.dropdownResizeObserver.observe(this.$refs.dropdown.$el)
877
- },
878
- handleSetDropdownOffet() {
879
- if (!this.$refs.select) return
880
- this.dropdownPosition.left = Math.floor(
881
- this.$refs.select.$el.getBoundingClientRect().left
882
- )
883
- this.getDropdownWidth()
884
- },
885
- observeSelectWidth() {
886
- if (!this.$refs.select) return
887
- this.selectResizeObserver = new ResizeObserver(() =>
888
- // eslint-disable-next-line vue/valid-next-tick
889
- this.$nextTick(() => this.getDropdownWidth())
890
- )
891
- this.selectResizeObserver.observe(this.$refs.dropdown.$el)
892
- },
893
- async getDropdownWidth() {
894
- if (!this.$refs.select) return
895
- await this.$nextTick()
896
- this.dropdownWidth = `${this.$refs.select.$el.clientWidth}px`
897
- },
898
- onArrowPress(dir) {
899
- let newHoveredElem
900
- const currentHoveredElem = this.$refs.dropdown.$el.querySelector(
901
- `[data-value="${this.hoveredValue}"]`
902
- )
903
- if (currentHoveredElem) {
904
- if (dir > 0) {
905
- newHoveredElem = currentHoveredElem.nextElementSibling
906
- } else {
907
- newHoveredElem = currentHoveredElem.previousElementSibling
908
- }
909
- if (newHoveredElem) {
910
- this.hoveredValue = newHoveredElem.getAttribute('data-value')
911
- const topPos = newHoveredElem.offsetTop
912
- this.$refs.dropdown.$el.scrollTop = topPos
913
- }
914
- }
915
- },
916
- },
917
- }
918
- </script>
1
+ <template>
2
+ <Container
3
+ :no-relative="noRelative"
4
+ :select-width="selectWidth"
5
+ @mouseenter="mouseEnterHandler"
6
+ @mouseleave="mouseLeaveHandler"
7
+ >
8
+ <InputWrapper
9
+ :align-items="alignItems"
10
+ :has-label="!!label && label.length > 0"
11
+ :no-relative="noRelative"
12
+ >
13
+ <LabelWrapper
14
+ v-if="label"
15
+ :data-id="labelDataId"
16
+ :info-text-message="!!infoTextMessage || !!$slots.infoText"
17
+ >
18
+ <InputLabel
19
+ :font-color="
20
+ labelFontColor || colorMode == 'dark' || colorMode == 'transparent'
21
+ ? 'white'
22
+ : 'eturnityGrey'
23
+ "
24
+ :font-size="fontSize"
25
+ >{{ label }}
26
+ <OptionalLabel v-if="labelOptional">
27
+ ({{ $gettext('Optional') }})</OptionalLabel
28
+ >
29
+ </InputLabel>
30
+ <InfoText
31
+ v-if="infoTextMessage || !!$slots.infoText"
32
+ :align-arrow="infoTextAlignArrow"
33
+ :max-width="infoTextWidth"
34
+ :size="infoTextSize"
35
+ :text="infoTextMessage"
36
+ :width="infoTextWidth"
37
+ >
38
+ <slot name="infoText"></slot>
39
+ </InfoText>
40
+ </LabelWrapper>
41
+ <SelectButtonWrapper :disabled="disabled">
42
+ <SelectButton
43
+ ref="select"
44
+ :bg-color="
45
+ buttonBgColor || colorMode == 'dark'
46
+ ? 'transparentBlack1'
47
+ : colorMode == 'transparent'
48
+ ? 'transparent'
49
+ : 'white'
50
+ "
51
+ class="select-button"
52
+ :color-mode="colorMode"
53
+ :data-id="dataId"
54
+ :disabled="disabled"
55
+ :font-color="
56
+ buttonFontColor || colorMode == 'dark' || colorMode == 'transparent'
57
+ ? 'white'
58
+ : 'black'
59
+ "
60
+ :font-size="fontSize"
61
+ :has-error="hasError"
62
+ :has-no-padding="isSearchBarVisible || !hasSelectButtonPadding"
63
+ :height="height"
64
+ :is-search-bar-visible="isSearchBarVisible"
65
+ :no-relative="noRelative"
66
+ :padding-left="paddingLeft"
67
+ :select-height="selectHeight"
68
+ :select-min-height="selectMinHeight"
69
+ :select-width="selectWidth"
70
+ :show-border="showBorder"
71
+ :show-disabled-background="showDisabledBackground"
72
+ :table-padding-left="tablePaddingLeft"
73
+ @click="toggleDropdown"
74
+ @keydown="onKeyDown"
75
+ >
76
+ <DraggableInputHandle
77
+ v-if="isDraggable && !isSearchBarVisible"
78
+ :height="selectHeight"
79
+ />
80
+ <InputText
81
+ v-if="isSearchBarVisible"
82
+ ref="searchInput"
83
+ background-color="transparent"
84
+ :font-color="
85
+ buttonFontColor ||
86
+ colorMode == 'dark' ||
87
+ colorMode == 'transparent'
88
+ ? 'white'
89
+ : 'black'
90
+ "
91
+ :font-size="fontSize"
92
+ input-height="34px"
93
+ :input-width="computedWidth"
94
+ :no-border="true"
95
+ tabindex="0"
96
+ :value="textSearch"
97
+ @click.stop
98
+ @input-change="searchChange"
99
+ @keydown.stop="onKeyDown"
100
+ />
101
+ <Selector
102
+ v-else
103
+ :padding-left="paddingLeft"
104
+ :select-width="selectWidth"
105
+ :show-border="showBorder"
106
+ >
107
+ <slot name="selector" :selected-value="selectedValue"></slot>
108
+ </Selector>
109
+ <Caret
110
+ class="caret_dropdown"
111
+ :color-mode="colorMode"
112
+ @click.stop="toggleCaretDropdown"
113
+ >
114
+ <Icon
115
+ v-if="isDropdownOpen"
116
+ :color="
117
+ caretColor || colorMode == 'dark' || colorMode == 'transparent'
118
+ ? 'white'
119
+ : 'transparentBlack1'
120
+ "
121
+ name="arrow_up"
122
+ :size="colorMode === 'transparent' ? '8px' : '12px'"
123
+ />
124
+ <Icon
125
+ v-else
126
+ :color="
127
+ caretColor || colorMode == 'dark' || colorMode == 'transparent'
128
+ ? 'white'
129
+ : 'transparentBlack1'
130
+ "
131
+ name="arrow_down"
132
+ :size="colorMode === 'transparent' ? '8px' : '12px'"
133
+ />
134
+ </Caret>
135
+ </SelectButton>
136
+ <DropdownWrapper ref="dropdownWrapperRef" :no-relative="noRelative">
137
+ <Teleport to="#portal-target">
138
+ <SelectDropdown
139
+ v-show="isSelectDropdownShown"
140
+ ref="dropdown"
141
+ :bg-color="
142
+ dropdownBgColor ||
143
+ colorMode == 'dark' ||
144
+ colorMode == 'transparent'
145
+ ? 'black'
146
+ : 'white'
147
+ "
148
+ :dropdown-position="dropdownPosition"
149
+ :font-color="
150
+ dropdownFontColor ||
151
+ colorMode == 'dark' ||
152
+ colorMode == 'transparent'
153
+ ? 'white'
154
+ : 'black'
155
+ "
156
+ :font-size="fontSize"
157
+ :hovered-bg-color="
158
+ colorMode == 'dark'
159
+ ? '#000000'
160
+ : colorMode == 'transparent'
161
+ ? 'grey6'
162
+ : dropdownBgColor
163
+ "
164
+ :hovered-index="hoveredIndex"
165
+ :hovered-value="hoveredValue"
166
+ :is-active="isActive"
167
+ :min-width="minWidth"
168
+ :no-relative="noRelative"
169
+ :option-width="getOptionWidth"
170
+ :selected-value="selectedValue"
171
+ @mouseleave="optionLeave"
172
+ @option-hovered="optionHovered"
173
+ @option-selected="optionSelected"
174
+ >
175
+ <slot name="dropdown"></slot>
176
+ </SelectDropdown>
177
+ </Teleport>
178
+ </DropdownWrapper>
179
+ </SelectButtonWrapper>
180
+ </InputWrapper>
181
+ </Container>
182
+ </template>
183
+
184
+ <script>
185
+ //How to use it
186
+ // <Select
187
+ // hoverDropdown="true"
188
+ // selectWidth="100%"
189
+ // minWidth="220px"
190
+ // optionWidth="50%"
191
+ // label="that is a label"
192
+ // alignItems="vertical"
193
+ // label-data-id="test-label-data-id"
194
+ // data-id="test-data-id"
195
+ // :hasSelectButtonPadding="false"
196
+ // >
197
+ // <template #selector="{selectedValue}">
198
+ // value selected: {{selectedValue}}
199
+ // </template>
200
+ // <template #dropdown>
201
+ // <Option value="1">value one</Option>
202
+ // <Option value="2">value two</Option>
203
+ // <Option value="3">value three</Option>
204
+ // <Option value="4">value four</Option>
205
+ // </template>
206
+ // </Select>
207
+
208
+ import { Teleport } from 'vue'
209
+ import styled from 'vue3-styled-components'
210
+ import InfoText from '../../infoText'
211
+ import Icon from '../../icon'
212
+ import InputText from '../inputText'
213
+ import DraggableInputHandle from '../../draggableInputHandle'
214
+ import { debounce } from '../../../utils'
215
+
216
+ const CARET_WIDTH = '30px'
217
+ const BORDER_WIDTH = '1px'
218
+
219
+ const CaretAttrs = { colorMode: String }
220
+ const Caret = styled('div', CaretAttrs)`
221
+ display: flex;
222
+ align-items: center;
223
+ justify-content: center;
224
+ width: ${(props) =>
225
+ props.colorMode === 'transparent' ? '15px' : CARET_WIDTH};
226
+ min-width: ${(props) =>
227
+ props.colorMode === 'transparent' ? '15px' : CARET_WIDTH};
228
+ height: 100%;
229
+ align-items: center;
230
+ cursor: pointer;
231
+ margin-left: auto;
232
+ `
233
+
234
+ const selectorProps = {
235
+ selectWidth: String,
236
+ paddingLeft: String,
237
+ showBorder: Boolean,
238
+ }
239
+ const Selector = styled('div', selectorProps)`
240
+ ${(props) =>
241
+ props.selectWidth === '100%'
242
+ ? 'width: 100%;'
243
+ : `width: calc(${props.selectWidth} -
244
+ (
245
+ ${CARET_WIDTH} +
246
+ ${props.paddingLeft}
247
+ ${props.showBorder ? `+ (${BORDER_WIDTH} * 2)` : ''}
248
+ )
249
+ );
250
+ white-space: nowrap;
251
+ text-overflow: ellipsis;
252
+ overflow: hidden;`}
253
+ `
254
+
255
+ const labelAttrs = { fontSize: String, fontColor: String }
256
+ const InputLabel = styled('div', labelAttrs)`
257
+ color: ${(props) =>
258
+ props.theme.colors[props.fontColor]
259
+ ? props.theme.colors[props.fontColor]
260
+ : props.fontColor};
261
+ font-size: ${(props) => props.fontSize};
262
+ font-weight: 700;
263
+ `
264
+ const OptionalLabel = styled.span`
265
+ font-weight: 300;
266
+ text-transform: lowercase;
267
+ `
268
+ const inputProps = {
269
+ selectWidth: String,
270
+ optionWidth: String,
271
+ noRelative: Boolean,
272
+ }
273
+ const Container = styled('div', inputProps)`
274
+ width: ${(props) => props.selectWidth};
275
+ position: ${(props) => (props.noRelative ? 'static' : 'relative')};
276
+ display: inline-block;
277
+ `
278
+
279
+ const LabelWrapperAttrs = { infoTextMessage: Boolean }
280
+ const LabelWrapper = styled('div', LabelWrapperAttrs)`
281
+ display: inline-grid;
282
+ grid-template-columns: ${(props) =>
283
+ props.infoTextMessage ? 'auto auto' : 'auto'};
284
+ grid-gap: 12px;
285
+ align-items: center;
286
+ justify-content: start;
287
+ `
288
+
289
+ const SelectButtonWrapperAttrs = {
290
+ disabled: Boolean,
291
+ }
292
+ const SelectButtonWrapper = styled('div', SelectButtonWrapperAttrs)`
293
+ ${(props) => (props.disabled ? 'cursor: not-allowed' : 'cursor: pointer')};
294
+ `
295
+
296
+ const selectButtonAttrs = {
297
+ bgColor: String,
298
+ fontColor: String,
299
+ hasError: Boolean,
300
+ disabled: Boolean,
301
+ selectHeight: String,
302
+ selectWidth: String,
303
+ height: String,
304
+ selectMinHeight: String,
305
+ hasNoPadding: Boolean,
306
+ showBorder: Boolean,
307
+ paddingLeft: String,
308
+ noRelative: Boolean,
309
+ tablePaddingLeft: String,
310
+ showDisabledBackground: Boolean,
311
+ colorMode: String,
312
+ isSearchBarVisible: Boolean,
313
+ }
314
+ const SelectButton = styled('div', selectButtonAttrs)`
315
+ position: ${(props) => (props.noRelative ? 'static' : 'relative')};
316
+ box-sizing: border-box;
317
+ border-radius: 4px;
318
+ max-width: ${(props) => (props.selectWidth ? props.selectWidth : '100%')};
319
+ ${(props) =>
320
+ props.colorMode === 'transparent'
321
+ ? props.isSearchBarVisible
322
+ ? 'padding: 10px 15px 10px 5px;'
323
+ : 'padding: 10px 15px;'
324
+ : props.isSearchBarVisible
325
+ ? ''
326
+ : `padding-left: ${
327
+ props.hasNoPadding
328
+ ? '0'
329
+ : props.tablePaddingLeft
330
+ ? props.tablePaddingLeft
331
+ : props.paddingLeft
332
+ }`};
333
+ text-align: left;
334
+ min-height: ${(props) =>
335
+ props.selectHeight
336
+ ? props.selectHeight
337
+ : props.selectMinHeight
338
+ ? props.selectMinHeight
339
+ : props.height
340
+ ? props.height
341
+ : '36px'};
342
+ display: flex;
343
+ align-items: center;
344
+ height: ${(props) => props.selectHeight};
345
+ ${({ showBorder, theme, hasError }) =>
346
+ showBorder &&
347
+ `
348
+ border: ${BORDER_WIDTH} solid ${
349
+ hasError ? theme.colors.red : theme.colors.grey4
350
+ }
351
+ `}
352
+ background-color:${(props) =>
353
+ props.disabled && props.showDisabledBackground
354
+ ? props.theme.colors.disabled
355
+ : props.theme.colors[props.bgColor]
356
+ ? props.theme.colors[props.bgColor]
357
+ : props.bgColor};
358
+ color: ${(props) =>
359
+ props.disabled && props.showDisabledBackground
360
+ ? props.theme.colors.black
361
+ : props.theme.colors[props.fontColor]
362
+ ? props.theme.colors[props.fontColor]
363
+ : props.fontColor};
364
+ ${(props) => (props.disabled ? 'pointer-events: none' : '')};
365
+ overflow: hidden;
366
+ & > .handle {
367
+ border-right: ${(props) =>
368
+ props.hasError ? props.theme.colors.red : props.theme.colors.grey4}
369
+ 1px solid;
370
+ }
371
+ `
372
+ const selectDropdownAttrs = {
373
+ hoveredBgColor: String,
374
+ bgColor: String,
375
+ fontColor: String,
376
+ optionWidth: String,
377
+ hoveredIndex: Number,
378
+ fontSize: String,
379
+ dropdownPosition: Object,
380
+ hoveredValue: Number | String,
381
+ selectedValue: Number | String,
382
+ noRelative: Boolean,
383
+ minWidth: String,
384
+ }
385
+ const SelectDropdown = styled('div', selectDropdownAttrs)`
386
+ box-sizing: border-box;
387
+ z-index: ${(props) => (props.isActive ? '2' : '99999')};
388
+ position: absolute;
389
+ top: ${(props) =>
390
+ props.noRelative ? 'auto' : props.dropdownPosition?.top + 'px'};
391
+ left: ${(props) => props.dropdownPosition?.left}px;
392
+ border: ${BORDER_WIDTH} solid ${(props) => props.theme.colors.grey4};
393
+ border-radius: 4px;
394
+ display: flex;
395
+ flex-direction: column;
396
+ align-items: flex-start;
397
+ padding: 0px;
398
+ box-shadow: 0px 8px 16px 0px rgba(0, 0, 0, 0.2);
399
+ width: ${(props) => (props.optionWidth ? props.optionWidth : '100%')};
400
+ min-width: ${(props) =>
401
+ props.minWidth
402
+ ? props.minWidth
403
+ : props.optionWidth
404
+ ? props.optionWidth
405
+ : '100%'};
406
+ background-color: ${(props) =>
407
+ props.theme.colors[props.bgColor]
408
+ ? props.theme.colors[props.bgColor]
409
+ : props.bgColor};
410
+ color: ${(props) =>
411
+ props.theme.colors[props.fontColor]
412
+ ? props.theme.colors[props.fontColor]
413
+ : props.fontColor};
414
+ max-height: 300px;
415
+ overflow-y: auto;
416
+ & > div[data-value='${(props) => props.hoveredValue}'] {
417
+ background-color: ${(props) =>
418
+ props.theme.colors[props.hoveredBgColor]
419
+ ? props.theme.colors[props.hoveredBgColor]
420
+ : props.hoveredBgColor};
421
+ }
422
+ font-size: ${(props) => props.fontSize};
423
+ `
424
+ SelectDropdown.emits = ['option-hovered', 'option-selected']
425
+ const DropdownAttrs = { noRelative: Boolean }
426
+ const DropdownWrapper = styled('div', DropdownAttrs)`
427
+ position: ${(props) => (props.noRelative ? 'static' : 'relative')};
428
+ `
429
+ const inputAttrs = {
430
+ alignItems: String,
431
+ hasLabel: Boolean,
432
+ noRelative: Boolean,
433
+ }
434
+ const InputWrapper = styled('div', inputAttrs)`
435
+ position: ${(props) => (props.noRelative ? 'static' : 'relative')};
436
+ display: grid;
437
+ width: 100%;
438
+ min-width: ${(props) => (props.minWidth ? props.minWidth : '150px')};
439
+ align-items: center;
440
+ gap: 8px;
441
+ grid-template-columns: ${(props) =>
442
+ props.alignItems === 'vertical' || !props.hasLabel ? '1fr' : 'auto 1fr'};
443
+ `
444
+
445
+ const DROPDOWN_HEIGHT_OFFSET = 4
446
+ const DROPDOWN_TOP_OFFSET = 21
447
+ const MIN_OPTION_LENGTH = 5
448
+
449
+ const DROPDOWN_MENU_POSITIONS = {
450
+ Automatic: 'automatic',
451
+ Bottom: 'bottom',
452
+ }
453
+
454
+ export default {
455
+ name: 'RCselect',
456
+
457
+ components: {
458
+ SelectButton,
459
+ SelectButtonWrapper,
460
+ SelectDropdown,
461
+ Container,
462
+ InputLabel,
463
+ LabelWrapper,
464
+ OptionalLabel,
465
+ InfoText,
466
+ InputWrapper,
467
+ DropdownWrapper,
468
+ Icon,
469
+ Caret,
470
+ Selector,
471
+ InputText,
472
+ Teleport,
473
+ DraggableInputHandle,
474
+ },
475
+
476
+ props: {
477
+ value: {
478
+ required: false,
479
+ default: null,
480
+ },
481
+ fontSize: {
482
+ required: false,
483
+ default: '13px',
484
+ },
485
+ noRelative: {
486
+ required: false,
487
+ default: false,
488
+ },
489
+ label: {
490
+ required: false,
491
+ },
492
+ labelOptional: {
493
+ required: false,
494
+ default: false,
495
+ },
496
+ labelDataId: {
497
+ required: false,
498
+ default: '',
499
+ },
500
+ infoTextMessage: {
501
+ required: false,
502
+ },
503
+ selectWidth: {
504
+ type: String,
505
+ required: false,
506
+ default: '100%',
507
+ },
508
+ minWidth: {
509
+ required: false,
510
+ },
511
+ maxWidth: {
512
+ required: false,
513
+ },
514
+ selectHeight: {
515
+ type: String,
516
+ required: false,
517
+ default: null,
518
+ },
519
+ height: {
520
+ required: false,
521
+ default: null,
522
+ },
523
+ selectMinHeight: {
524
+ required: false,
525
+ default: '36px',
526
+ },
527
+ optionWidth: {
528
+ required: false,
529
+ default: null,
530
+ },
531
+ hoverDropdown: {
532
+ required: false,
533
+ default: false,
534
+ },
535
+ dropdownAutoClose: {
536
+ required: false,
537
+ default: false,
538
+ },
539
+ alignItems: {
540
+ required: false,
541
+ default: 'horizontal',
542
+ },
543
+ buttonBgColor: {
544
+ required: false,
545
+ },
546
+ buttonFontColor: {
547
+ required: false,
548
+ },
549
+ dropdownBgColor: {
550
+ required: false,
551
+ default: 'grey5',
552
+ },
553
+ dropdownFontColor: {
554
+ required: false,
555
+ },
556
+ dropDownArrowVisible: {
557
+ required: false,
558
+ default: true,
559
+ },
560
+ caretColor: {
561
+ required: false,
562
+ },
563
+ labelFontColor: {
564
+ required: false,
565
+ },
566
+ colorMode: {
567
+ required: false,
568
+ default: 'light',
569
+ },
570
+ isSearchable: {
571
+ required: false,
572
+ default: true,
573
+ },
574
+ hasError: {
575
+ required: false,
576
+ default: false,
577
+ },
578
+ disabled: {
579
+ required: false,
580
+ default: false,
581
+ },
582
+ isAutoSearch: {
583
+ required: false,
584
+ default: true,
585
+ },
586
+ showBorder: {
587
+ required: false,
588
+ default: true,
589
+ },
590
+ infoTextSize: {
591
+ required: false,
592
+ default: '14px',
593
+ },
594
+ dataId: {
595
+ type: String,
596
+ default: '',
597
+ },
598
+ hasSelectButtonPadding: {
599
+ required: false,
600
+ type: Boolean,
601
+ default: true,
602
+ },
603
+ isDraggable: {
604
+ type: Boolean,
605
+ default: false,
606
+ },
607
+ leftPadding: {
608
+ type: String,
609
+ default: '15px',
610
+ },
611
+ tablePaddingLeft: {
612
+ required: false,
613
+ },
614
+ showDisabledBackground: {
615
+ required: false,
616
+ default: true,
617
+ },
618
+ minOptionLength: {
619
+ type: Number,
620
+ default: MIN_OPTION_LENGTH,
621
+ },
622
+ dropdownMenuPosition: {
623
+ type: String,
624
+ default: DROPDOWN_MENU_POSITIONS.Automatic, // options: ['automatic', bottom]
625
+ },
626
+ infoTextWidth: {
627
+ type: String,
628
+ required: false,
629
+ },
630
+ infoTextAlignArrow: {
631
+ type: String,
632
+ required: false,
633
+ },
634
+ },
635
+
636
+ data() {
637
+ return {
638
+ selectedValue: null,
639
+ paddingLeft: this.isDraggable ? '30px' : this.leftPadding,
640
+ isDropdownOpen: false,
641
+ isActive: false,
642
+ textSearch: '',
643
+ hoveredIndex: 0,
644
+ isClickOutsideActive: false,
645
+ dropdownPosition: {
646
+ left: null,
647
+ top: null,
648
+ },
649
+ dropdownWidth: null,
650
+ hoveredValue: null,
651
+ }
652
+ },
653
+ computed: {
654
+ optionLength() {
655
+ if (this.isDropdownOpen) {
656
+ return this.$refs.dropdown.$el.childElementCount > 1
657
+ ? this.$refs.dropdown.$el.childElementCount
658
+ : this.$refs.dropdown.$el.children[0]
659
+ ? this.$refs.dropdown.$el.children[0].childElementCount
660
+ : 0
661
+ }
662
+
663
+ return 0
664
+ },
665
+ isSearchBarVisible() {
666
+ return (
667
+ this.isSearchable &&
668
+ this.optionLength >= this.minOptionLength &&
669
+ this.isDropdownOpen
670
+ )
671
+ },
672
+ computedWidth() {
673
+ function removePX(item) {
674
+ return Number(item.replace('px', ''))
675
+ }
676
+
677
+ return this.selectWidth === '100%'
678
+ ? '100%'
679
+ : removePX(this.selectWidth) - removePX(CARET_WIDTH) + 'px'
680
+ },
681
+ getOptionWidth() {
682
+ if (this.optionWidth) return this.optionWidth
683
+
684
+ return this.dropdownWidth
685
+ },
686
+ isSelectDropdownShown() {
687
+ return (
688
+ this.isDropdownOpen &&
689
+ this.dropdownPosition.left !== null &&
690
+ (!this.isSearchable || this.isSearchable)
691
+ )
692
+ },
693
+ isMobileDevice() {
694
+ const userAgent =
695
+ navigator.userAgent || navigator.vendor || window.opera
696
+ const touchCapable =
697
+ 'ontouchstart' in window ||
698
+ navigator.maxTouchPoints > 0 ||
699
+ navigator.msMaxTouchPoints > 0
700
+
701
+ return (
702
+ /Android/i.test(userAgent) ||
703
+ /iPad|iPhone|iPod/.test(userAgent) ||
704
+ (/Macintosh/.test(userAgent) && touchCapable) ||
705
+ /windows phone/i.test(userAgent)
706
+ )
707
+ },
708
+ },
709
+ watch: {
710
+ value(val) {
711
+ this.selectedValue = val
712
+ },
713
+ async isDropdownOpen(val) {
714
+ if (val) {
715
+ this.$emit('on-dropdown-open')
716
+ setTimeout(() => {
717
+ this.isClickOutsideActive = true
718
+ }, 10)
719
+ await this.$nextTick()
720
+ this.handleSetDropdownOffet()
721
+ } else {
722
+ this.dropdownPosition.left = null
723
+ setTimeout(() => {
724
+ this.isClickOutsideActive = false
725
+ }, 10)
726
+ }
727
+ if (val && this.isSearchable) {
728
+ this.$nextTick(() => {
729
+ if (this.$refs.searchInput && !this.isMobileDevice) {
730
+ this.$refs.searchInput.$el.querySelector('input').focus()
731
+ }
732
+ })
733
+ }
734
+ },
735
+ },
736
+ mounted() {
737
+ this.observeDropdownHeight()
738
+ this.observeSelectWidth()
739
+ window.addEventListener('resize', this.handleSetDropdownOffet)
740
+ },
741
+ beforeMount() {
742
+ this.selectedValue = this.value
743
+ document.addEventListener('click', this.clickOutside)
744
+ this.getDropdownPosition()
745
+ window.removeEventListener('resize', this.handleSetDropdownOffet)
746
+ if (this.dropdownResizeObserver) this.dropdownResizeObserver.disconnect()
747
+ if (this.selectResizeObserver) this.selectResizeObserver.disconnect()
748
+ },
749
+ unmounted() {
750
+ document.removeEventListener('click', this.clickOutside)
751
+ },
752
+ methods: {
753
+ focus() {
754
+ this.isActive = true
755
+ },
756
+ blur(e) {
757
+ this.isActive = false
758
+ this.$emit('blur', e)
759
+ },
760
+ toggleDropdown() {
761
+ this.isDropdownOpen = !this.isDropdownOpen
762
+ },
763
+ toggleCaretDropdown() {
764
+ this.isDropdownOpen = !this.isDropdownOpen
765
+ },
766
+ closeDropdown() {
767
+ this.blur()
768
+ this.clearSearch()
769
+ this.isDropdownOpen = false
770
+ },
771
+ clearSearch() {
772
+ this.textSearch = ''
773
+ this.searchChange('')
774
+ },
775
+ optionSelected(e) {
776
+ this.selectedValue = e
777
+ this.closeDropdown()
778
+ this.blur()
779
+ this.$emit('input-change', e)
780
+ },
781
+ optionHovered: debounce(function (e) {
782
+ this.hoveredValue = e
783
+ }, 300),
784
+ mouseEnterHandler() {
785
+ if (this.hoverDropdown) {
786
+ this.focus()
787
+ this.isDropdownOpen = true
788
+ }
789
+ },
790
+ mouseLeaveHandler() {
791
+ if (this.hoverDropdown) {
792
+ this.blur()
793
+ }
794
+ },
795
+ optionLeave() {
796
+ if (this.dropdownAutoClose) {
797
+ this.isDropdownOpen = false
798
+ }
799
+ },
800
+ searchChange(value) {
801
+ this.textSearch = value
802
+ this.$emit('search-change', value)
803
+ const dropdownChildren = [...this.$refs.dropdown.$el.children]
804
+ dropdownChildren.forEach((el) => {
805
+ if (!el.textContent.toLowerCase().includes(value.toLowerCase())) {
806
+ el.style.display = 'none'
807
+
808
+ return
809
+ }
810
+
811
+ el.style.display = 'inherit'
812
+ })
813
+ },
814
+ clickOutside(event) {
815
+ const dropdownRef = this.$refs.dropdown
816
+ // we need to prevent closing on selecting an option, because in the case of
817
+ // a disabled option, we don't want to close the dropdown
818
+ if (!this.isClickOutsideActive) return
819
+ if (
820
+ this.$refs.select.$el == event.target ||
821
+ this.$refs.select.$el.contains(event.target) ||
822
+ event.target.id === 'more-button' ||
823
+ event.target.parentNode === dropdownRef.$el
824
+ ) {
825
+ return
826
+ } else {
827
+ this.closeDropdown()
828
+ }
829
+ },
830
+ onKeyDown(e) {
831
+ if (e.key == 'ArrowDown') {
832
+ this.onArrowPress(1)
833
+ } else if (e.key == 'ArrowUp') {
834
+ this.onArrowPress(-1)
835
+ } else if (e.key == 'Enter') {
836
+ const optionHoveredComponent = [...this.$refs.dropdown.$el.children][
837
+ (this.hoveredIndex - 1 + this.optionLength) % this.optionLength
838
+ ]
839
+ this.optionSelected(optionHoveredComponent.$el.dataset.value)
840
+ }
841
+ },
842
+ // If some part of the dropdown menu is outside viewport of the bottom of the screen,
843
+ // we need to offset it and display it at the top of the select dropdown instead
844
+ async getDropdownPosition() {
845
+ if (
846
+ !this.$refs.dropdownWrapperRef ||
847
+ !this.$refs.select ||
848
+ !this.$refs.dropdown
849
+ ) {
850
+ return
851
+ }
852
+ await this.$nextTick()
853
+ const isDisplayedAtBottom = await this.generateDropdownPosition()
854
+ // If the dropdown menu is going to be displayed at the bottom,
855
+ // we need reverify its position after a dom update (nextTick)
856
+ await this.$nextTick()
857
+ if (isDisplayedAtBottom) this.generateDropdownPosition()
858
+ },
859
+ async generateDropdownPosition() {
860
+ const isDropdownNotCompletelyVisible =
861
+ await this.isBottomOfDropdownOutOfViewport()
862
+ const dropdownWrapperEl = this.$refs.dropdownWrapperRef.$el
863
+ const selectButtonHeight = this.$refs.select.$el.clientHeight
864
+ const dropdownHeight = this.$refs.dropdown.$el.clientHeight
865
+ const dropdownWrapperRelativeHeight =
866
+ dropdownWrapperEl.getBoundingClientRect().top +
867
+ window.scrollY +
868
+ DROPDOWN_HEIGHT_OFFSET
869
+
870
+ const top =
871
+ isDropdownNotCompletelyVisible ||
872
+ (!isDropdownNotCompletelyVisible &&
873
+ this.dropdownMenuPosition === DROPDOWN_MENU_POSITIONS.Bottom)
874
+ ? dropdownWrapperRelativeHeight
875
+ : dropdownWrapperRelativeHeight -
876
+ dropdownHeight -
877
+ selectButtonHeight -
878
+ DROPDOWN_TOP_OFFSET
879
+ const left = this.dropdownPosition.left
880
+ ? this.dropdownPosition.left
881
+ : dropdownWrapperEl.getBoundingClientRect().left + window.scrollX
882
+
883
+ this.dropdownPosition = { left: Math.floor(left), top: Math.floor(top) }
884
+
885
+ return isDropdownNotCompletelyVisible
886
+ },
887
+ async isBottomOfDropdownOutOfViewport() {
888
+ if (
889
+ !this.$refs.dropdown ||
890
+ this.dropdownMenuPosition === DROPDOWN_MENU_POSITIONS.Bottom
891
+ ) {
892
+ return false
893
+ }
894
+
895
+ await this.$nextTick()
896
+ const rect = this.$refs.dropdown.$el.getBoundingClientRect()
897
+ const windowHeight =
898
+ window.innerHeight || document.documentElement.clientHeight
899
+
900
+ if (windowHeight <= 650) return true
901
+
902
+ // using Math.floor because the offsets may contain decimals we are not going to consider here
903
+ return Math.floor(rect.top) + Math.floor(rect.height) <= windowHeight
904
+ },
905
+ observeDropdownHeight() {
906
+ if (!this.$refs.dropdown) return
907
+ this.dropdownResizeObserver = new ResizeObserver(() => {
908
+ this.$nextTick(() => this.getDropdownPosition())
909
+ })
910
+ this.dropdownResizeObserver.observe(this.$refs.dropdown.$el)
911
+ },
912
+ handleSetDropdownOffet() {
913
+ if (!this.$refs.select) return
914
+ this.dropdownPosition.left = Math.floor(
915
+ this.$refs.select.$el.getBoundingClientRect().left
916
+ )
917
+ this.getDropdownWidth()
918
+ },
919
+ observeSelectWidth() {
920
+ if (!this.$refs.select) return
921
+ this.selectResizeObserver = new ResizeObserver(() =>
922
+ // eslint-disable-next-line vue/valid-next-tick
923
+ this.$nextTick(() => this.getDropdownWidth())
924
+ )
925
+ this.selectResizeObserver.observe(this.$refs.dropdown.$el)
926
+ },
927
+ async getDropdownWidth() {
928
+ if (!this.$refs.select) return
929
+ await this.$nextTick()
930
+ this.dropdownWidth = `${this.$refs.select.$el.clientWidth}px`
931
+ },
932
+ onArrowPress(dir) {
933
+ let newHoveredElem
934
+ const currentHoveredElem = this.$refs.dropdown.$el.querySelector(
935
+ `[data-value="${this.hoveredValue}"]`
936
+ )
937
+ if (currentHoveredElem) {
938
+ if (dir > 0) {
939
+ newHoveredElem = currentHoveredElem.nextElementSibling
940
+ } else {
941
+ newHoveredElem = currentHoveredElem.previousElementSibling
942
+ }
943
+ if (newHoveredElem) {
944
+ this.hoveredValue = newHoveredElem.getAttribute('data-value')
945
+ const topPos = newHoveredElem.offsetTop
946
+ this.$refs.dropdown.$el.scrollTop = topPos
947
+ }
948
+ }
949
+ },
950
+ },
951
+ }
952
+ </script>