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