@verdaccio/ui-components 5.0.0-next-9.24 → 5.0.0-next-9.26

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 (296) hide show
  1. package/README.md +20 -0
  2. package/build/api/use-data.d.ts +2 -2
  3. package/build/api/use-data.js +2 -2
  4. package/build/api/use-data.js.map +1 -1
  5. package/build/api/use-data.mjs +2 -2
  6. package/build/api/use-data.mjs.map +1 -1
  7. package/build/components/CopyClipboard/CopyToClipBoard.d.ts +1 -0
  8. package/build/components/CopyClipboard/CopyToClipBoard.js +36 -17
  9. package/build/components/CopyClipboard/CopyToClipBoard.js.map +1 -1
  10. package/build/components/CopyClipboard/CopyToClipBoard.mjs +36 -19
  11. package/build/components/CopyClipboard/CopyToClipBoard.mjs.map +1 -1
  12. package/build/components/CopyClipboard/utils.d.ts +2 -1
  13. package/build/components/CopyClipboard/utils.js +6 -4
  14. package/build/components/CopyClipboard/utils.js.map +1 -1
  15. package/build/components/CopyClipboard/utils.mjs +6 -4
  16. package/build/components/CopyClipboard/utils.mjs.map +1 -1
  17. package/build/components/DocsLink/DocsLink.d.ts +8 -0
  18. package/build/components/DocsLink/DocsLink.js +40 -0
  19. package/build/components/DocsLink/DocsLink.js.map +1 -0
  20. package/build/components/DocsLink/DocsLink.mjs +35 -0
  21. package/build/components/DocsLink/DocsLink.mjs.map +1 -0
  22. package/build/components/DocsLink/index.d.ts +1 -0
  23. package/build/components/DocsLink/index.js +3 -0
  24. package/build/components/DocsLink/index.mjs +1 -0
  25. package/build/components/Help/Help.d.ts +13 -0
  26. package/build/components/Help/Help.js +280 -36
  27. package/build/components/Help/Help.js.map +1 -1
  28. package/build/components/Help/Help.mjs +274 -39
  29. package/build/components/Help/Help.mjs.map +1 -1
  30. package/build/components/Help/styles.d.ts +29 -0
  31. package/build/components/Help/styles.js +86 -1
  32. package/build/components/Help/styles.js.map +1 -1
  33. package/build/components/Help/styles.mjs +82 -2
  34. package/build/components/Help/styles.mjs.map +1 -1
  35. package/build/components/Icons/Managers/Bun.d.ts +2 -0
  36. package/build/components/Icons/Managers/Bun2.js +18 -0
  37. package/build/components/Icons/Managers/Bun2.js.map +1 -0
  38. package/build/components/Icons/Managers/Bun2.mjs +16 -0
  39. package/build/components/Icons/Managers/Bun2.mjs.map +1 -0
  40. package/build/components/Icons/Managers/bun.js +6 -0
  41. package/build/components/Icons/Managers/bun.js.map +1 -0
  42. package/build/components/Icons/Managers/bun.mjs +6 -0
  43. package/build/components/Icons/Managers/bun.mjs.map +1 -0
  44. package/build/components/Icons/Managers/bun.svg +1 -0
  45. package/build/components/Icons/Managers/index.d.ts +1 -0
  46. package/build/components/Icons/Managers/index.js +2 -0
  47. package/build/components/Icons/Managers/index.mjs +2 -1
  48. package/build/components/Icons/index.js +3 -0
  49. package/build/components/Icons/index.mjs +3 -1
  50. package/build/components/Install/Install.d.ts +2 -0
  51. package/build/components/Install/Install.js +30 -2
  52. package/build/components/Install/Install.js.map +1 -1
  53. package/build/components/Install/Install.mjs +30 -3
  54. package/build/components/Install/Install.mjs.map +1 -1
  55. package/build/components/Install/InstallListItem.d.ts +2 -1
  56. package/build/components/Install/InstallListItem.js +17 -0
  57. package/build/components/Install/InstallListItem.js.map +1 -1
  58. package/build/components/Install/InstallListItem.mjs +17 -0
  59. package/build/components/Install/InstallListItem.mjs.map +1 -1
  60. package/build/components/Loading/PackageListSkeleton.d.ts +3 -0
  61. package/build/components/Loading/PackageListSkeleton.js +70 -0
  62. package/build/components/Loading/PackageListSkeleton.js.map +1 -0
  63. package/build/components/Loading/PackageListSkeleton.mjs +65 -0
  64. package/build/components/Loading/PackageListSkeleton.mjs.map +1 -0
  65. package/build/components/Loading/VersionSkeleton.d.ts +3 -0
  66. package/build/components/Loading/VersionSkeleton.js +119 -0
  67. package/build/components/Loading/VersionSkeleton.js.map +1 -0
  68. package/build/components/Loading/VersionSkeleton.mjs +111 -0
  69. package/build/components/Loading/VersionSkeleton.mjs.map +1 -0
  70. package/build/components/Loading/index.d.ts +2 -0
  71. package/build/components/Loading/index.js +4 -0
  72. package/build/components/Loading/index.mjs +4 -1
  73. package/build/components/Package/Package.js +5 -1
  74. package/build/components/Package/Package.js.map +1 -1
  75. package/build/components/Package/Package.mjs +6 -2
  76. package/build/components/Package/Package.mjs.map +1 -1
  77. package/build/components/Package/styles.d.ts +3 -0
  78. package/build/components/Package/styles.js +8 -0
  79. package/build/components/Package/styles.js.map +1 -1
  80. package/build/components/Package/styles.mjs +8 -1
  81. package/build/components/Package/styles.mjs.map +1 -1
  82. package/build/components/PackageList/PackageList.js +4 -4
  83. package/build/components/PackageList/PackageList.js.map +1 -1
  84. package/build/components/PackageList/PackageList.mjs +5 -5
  85. package/build/components/PackageList/PackageList.mjs.map +1 -1
  86. package/build/components/PackageList/PackageListToolbar.d.ts +15 -0
  87. package/build/components/PackageList/PackageListToolbar.js +127 -0
  88. package/build/components/PackageList/PackageListToolbar.js.map +1 -0
  89. package/build/components/PackageList/PackageListToolbar.mjs +119 -0
  90. package/build/components/PackageList/PackageListToolbar.mjs.map +1 -0
  91. package/build/components/PackageList/filterPackages.d.ts +16 -0
  92. package/build/components/PackageList/filterPackages.js +37 -0
  93. package/build/components/PackageList/filterPackages.js.map +1 -0
  94. package/build/components/PackageList/filterPackages.mjs +34 -0
  95. package/build/components/PackageList/filterPackages.mjs.map +1 -0
  96. package/build/components/RegistryInfoDialog/RegistryInfoDialog.js +18 -7
  97. package/build/components/RegistryInfoDialog/RegistryInfoDialog.js.map +1 -1
  98. package/build/components/RegistryInfoDialog/RegistryInfoDialog.mjs +18 -7
  99. package/build/components/RegistryInfoDialog/RegistryInfoDialog.mjs.map +1 -1
  100. package/build/components/RegistryInfoDialog/types.d.ts +1 -0
  101. package/build/components/Search/AutoComplete/AutoComplete.d.ts +3 -0
  102. package/build/components/Search/AutoComplete/AutoComplete.js +3 -1
  103. package/build/components/Search/AutoComplete/AutoComplete.js.map +1 -1
  104. package/build/components/Search/AutoComplete/AutoComplete.mjs +3 -1
  105. package/build/components/Search/AutoComplete/AutoComplete.mjs.map +1 -1
  106. package/build/components/Search/Search.js +28 -1
  107. package/build/components/Search/Search.js.map +1 -1
  108. package/build/components/Search/Search.mjs +31 -5
  109. package/build/components/Search/Search.mjs.map +1 -1
  110. package/build/components/Search/SearchItem.d.ts +12 -1
  111. package/build/components/Search/SearchItem.js +53 -70
  112. package/build/components/Search/SearchItem.js.map +1 -1
  113. package/build/components/Search/SearchItem.mjs +51 -67
  114. package/build/components/Search/SearchItem.mjs.map +1 -1
  115. package/build/components/Search/utils.d.ts +10 -0
  116. package/build/components/Search/utils.js +28 -1
  117. package/build/components/Search/utils.js.map +1 -1
  118. package/build/components/Search/utils.mjs +26 -2
  119. package/build/components/Search/utils.mjs.map +1 -1
  120. package/build/components/SettingsMenu/SettingsMenu.js +2 -2
  121. package/build/components/SettingsMenu/SettingsMenu.mjs +1 -1
  122. package/build/components/Versions/Versions.js +8 -2
  123. package/build/components/Versions/Versions.js.map +1 -1
  124. package/build/components/Versions/Versions.mjs +8 -2
  125. package/build/components/Versions/Versions.mjs.map +1 -1
  126. package/build/components/VisuallyHidden/index.d.ts +5 -0
  127. package/build/components/VisuallyHidden/index.js +17 -0
  128. package/build/components/VisuallyHidden/index.js.map +1 -0
  129. package/build/components/VisuallyHidden/index.mjs +15 -0
  130. package/build/components/VisuallyHidden/index.mjs.map +1 -0
  131. package/build/configuration.js +2 -1
  132. package/build/configuration.js.map +1 -1
  133. package/build/configuration.mjs +2 -1
  134. package/build/configuration.mjs.map +1 -1
  135. package/build/i18n/crowdin/ui.js +68 -11
  136. package/build/i18n/crowdin/ui.js.map +1 -1
  137. package/build/i18n/crowdin/ui.json +64 -11
  138. package/build/i18n/crowdin/ui.mjs +67 -12
  139. package/build/i18n/crowdin/ui.mjs.map +1 -1
  140. package/build/i18n/download_translations/cs-CZ/ui.js +68 -11
  141. package/build/i18n/download_translations/cs-CZ/ui.js.map +1 -1
  142. package/build/i18n/download_translations/cs-CZ/ui.json +64 -11
  143. package/build/i18n/download_translations/cs-CZ/ui.mjs +67 -12
  144. package/build/i18n/download_translations/cs-CZ/ui.mjs.map +1 -1
  145. package/build/i18n/download_translations/de-DE/ui.js +68 -11
  146. package/build/i18n/download_translations/de-DE/ui.js.map +1 -1
  147. package/build/i18n/download_translations/de-DE/ui.json +64 -11
  148. package/build/i18n/download_translations/de-DE/ui.mjs +67 -12
  149. package/build/i18n/download_translations/de-DE/ui.mjs.map +1 -1
  150. package/build/i18n/download_translations/es-ES/ui.js +68 -11
  151. package/build/i18n/download_translations/es-ES/ui.js.map +1 -1
  152. package/build/i18n/download_translations/es-ES/ui.json +64 -11
  153. package/build/i18n/download_translations/es-ES/ui.mjs +67 -12
  154. package/build/i18n/download_translations/es-ES/ui.mjs.map +1 -1
  155. package/build/i18n/download_translations/fr-FR/ui.js +68 -11
  156. package/build/i18n/download_translations/fr-FR/ui.js.map +1 -1
  157. package/build/i18n/download_translations/fr-FR/ui.json +64 -11
  158. package/build/i18n/download_translations/fr-FR/ui.mjs +67 -12
  159. package/build/i18n/download_translations/fr-FR/ui.mjs.map +1 -1
  160. package/build/i18n/download_translations/ga-IE/ui.js +68 -11
  161. package/build/i18n/download_translations/ga-IE/ui.js.map +1 -1
  162. package/build/i18n/download_translations/ga-IE/ui.json +64 -11
  163. package/build/i18n/download_translations/ga-IE/ui.mjs +67 -12
  164. package/build/i18n/download_translations/ga-IE/ui.mjs.map +1 -1
  165. package/build/i18n/download_translations/gl-ES/ui.js +68 -11
  166. package/build/i18n/download_translations/gl-ES/ui.js.map +1 -1
  167. package/build/i18n/download_translations/gl-ES/ui.json +64 -11
  168. package/build/i18n/download_translations/gl-ES/ui.mjs +67 -12
  169. package/build/i18n/download_translations/gl-ES/ui.mjs.map +1 -1
  170. package/build/i18n/download_translations/it-IT/ui.js +68 -11
  171. package/build/i18n/download_translations/it-IT/ui.js.map +1 -1
  172. package/build/i18n/download_translations/it-IT/ui.json +64 -11
  173. package/build/i18n/download_translations/it-IT/ui.mjs +67 -12
  174. package/build/i18n/download_translations/it-IT/ui.mjs.map +1 -1
  175. package/build/i18n/download_translations/ko-KR/ui.js +68 -11
  176. package/build/i18n/download_translations/ko-KR/ui.js.map +1 -1
  177. package/build/i18n/download_translations/ko-KR/ui.json +64 -11
  178. package/build/i18n/download_translations/ko-KR/ui.mjs +67 -12
  179. package/build/i18n/download_translations/ko-KR/ui.mjs.map +1 -1
  180. package/build/i18n/download_translations/pl-PL/ui.js +68 -11
  181. package/build/i18n/download_translations/pl-PL/ui.js.map +1 -1
  182. package/build/i18n/download_translations/pl-PL/ui.json +64 -11
  183. package/build/i18n/download_translations/pl-PL/ui.mjs +67 -12
  184. package/build/i18n/download_translations/pl-PL/ui.mjs.map +1 -1
  185. package/build/i18n/download_translations/pt-BR/ui.js +68 -11
  186. package/build/i18n/download_translations/pt-BR/ui.js.map +1 -1
  187. package/build/i18n/download_translations/pt-BR/ui.json +64 -11
  188. package/build/i18n/download_translations/pt-BR/ui.mjs +67 -12
  189. package/build/i18n/download_translations/pt-BR/ui.mjs.map +1 -1
  190. package/build/i18n/download_translations/ru-RU/ui.js +68 -11
  191. package/build/i18n/download_translations/ru-RU/ui.js.map +1 -1
  192. package/build/i18n/download_translations/ru-RU/ui.json +64 -11
  193. package/build/i18n/download_translations/ru-RU/ui.mjs +67 -12
  194. package/build/i18n/download_translations/ru-RU/ui.mjs.map +1 -1
  195. package/build/i18n/download_translations/sr-CS/ui.js +66 -12
  196. package/build/i18n/download_translations/sr-CS/ui.js.map +1 -1
  197. package/build/i18n/download_translations/sr-CS/ui.json +64 -11
  198. package/build/i18n/download_translations/sr-CS/ui.mjs +66 -13
  199. package/build/i18n/download_translations/sr-CS/ui.mjs.map +1 -1
  200. package/build/i18n/download_translations/tr-TR/ui.js +68 -11
  201. package/build/i18n/download_translations/tr-TR/ui.js.map +1 -1
  202. package/build/i18n/download_translations/tr-TR/ui.json +64 -11
  203. package/build/i18n/download_translations/tr-TR/ui.mjs +67 -12
  204. package/build/i18n/download_translations/tr-TR/ui.mjs.map +1 -1
  205. package/build/i18n/download_translations/vi-VN/ui.js +66 -12
  206. package/build/i18n/download_translations/vi-VN/ui.js.map +1 -1
  207. package/build/i18n/download_translations/vi-VN/ui.json +64 -11
  208. package/build/i18n/download_translations/vi-VN/ui.mjs +66 -13
  209. package/build/i18n/download_translations/vi-VN/ui.mjs.map +1 -1
  210. package/build/i18n/download_translations/yo-NG/ui.js +66 -12
  211. package/build/i18n/download_translations/yo-NG/ui.js.map +1 -1
  212. package/build/i18n/download_translations/yo-NG/ui.json +64 -11
  213. package/build/i18n/download_translations/yo-NG/ui.mjs +66 -13
  214. package/build/i18n/download_translations/yo-NG/ui.mjs.map +1 -1
  215. package/build/i18n/download_translations/zh-CN/ui.js +68 -11
  216. package/build/i18n/download_translations/zh-CN/ui.js.map +1 -1
  217. package/build/i18n/download_translations/zh-CN/ui.json +64 -11
  218. package/build/i18n/download_translations/zh-CN/ui.mjs +67 -12
  219. package/build/i18n/download_translations/zh-CN/ui.mjs.map +1 -1
  220. package/build/i18n/download_translations/zh-TW/ui.js +68 -11
  221. package/build/i18n/download_translations/zh-TW/ui.js.map +1 -1
  222. package/build/i18n/download_translations/zh-TW/ui.json +64 -11
  223. package/build/i18n/download_translations/zh-TW/ui.mjs +67 -12
  224. package/build/i18n/download_translations/zh-TW/ui.mjs.map +1 -1
  225. package/build/i18n/loadTranslationFile.d.ts +2 -2
  226. package/build/i18n/loadTranslationFile.js +2 -2
  227. package/build/i18n/loadTranslationFile.js.map +1 -1
  228. package/build/i18n/loadTranslationFile.mjs +2 -2
  229. package/build/i18n/loadTranslationFile.mjs.map +1 -1
  230. package/build/index.d.ts +1 -0
  231. package/build/index.js +8 -0
  232. package/build/index.mjs +4 -2
  233. package/build/mockServiceWorker.js +1 -0
  234. package/build/pages/Version/Version.js +2 -2
  235. package/build/pages/Version/Version.js.map +1 -1
  236. package/build/pages/Version/Version.mjs +2 -2
  237. package/build/pages/Version/Version.mjs.map +1 -1
  238. package/build/providers/AppConfigurationProvider/AppConfigurationProvider.js +3 -1
  239. package/build/providers/AppConfigurationProvider/AppConfigurationProvider.js.map +1 -1
  240. package/build/providers/AppConfigurationProvider/AppConfigurationProvider.mjs +3 -1
  241. package/build/providers/AppConfigurationProvider/AppConfigurationProvider.mjs.map +1 -1
  242. package/build/providers/ManifestsProvider/ManifestsProvider.d.ts +3 -0
  243. package/build/providers/ManifestsProvider/ManifestsProvider.js +9 -2
  244. package/build/providers/ManifestsProvider/ManifestsProvider.js.map +1 -1
  245. package/build/providers/ManifestsProvider/ManifestsProvider.mjs +10 -4
  246. package/build/providers/ManifestsProvider/ManifestsProvider.mjs.map +1 -1
  247. package/build/sections/Detail/ContainerContent.js +8 -0
  248. package/build/sections/Detail/ContainerContent.js.map +1 -1
  249. package/build/sections/Detail/ContainerContent.mjs +8 -1
  250. package/build/sections/Detail/ContainerContent.mjs.map +1 -1
  251. package/build/sections/Detail/Detail.d.ts +3 -6
  252. package/build/sections/Detail/Detail.js +13 -14
  253. package/build/sections/Detail/Detail.js.map +1 -1
  254. package/build/sections/Detail/Detail.mjs +14 -15
  255. package/build/sections/Detail/Detail.mjs.map +1 -1
  256. package/build/sections/Detail/Tabs.d.ts +3 -2
  257. package/build/sections/Detail/Tabs.js +9 -4
  258. package/build/sections/Detail/Tabs.js.map +1 -1
  259. package/build/sections/Detail/Tabs.mjs +9 -4
  260. package/build/sections/Detail/Tabs.mjs.map +1 -1
  261. package/build/sections/Footer/Footer.js +24 -3
  262. package/build/sections/Footer/Footer.js.map +1 -1
  263. package/build/sections/Footer/Footer.mjs +24 -4
  264. package/build/sections/Footer/Footer.mjs.map +1 -1
  265. package/build/sections/Footer/styles.d.ts +6 -0
  266. package/build/sections/Footer/styles.js +21 -2
  267. package/build/sections/Footer/styles.js.map +1 -1
  268. package/build/sections/Footer/styles.mjs +21 -3
  269. package/build/sections/Footer/styles.mjs.map +1 -1
  270. package/build/sections/Header/HeaderSettingsDialog.js +39 -10
  271. package/build/sections/Header/HeaderSettingsDialog.js.map +1 -1
  272. package/build/sections/Header/HeaderSettingsDialog.mjs +39 -10
  273. package/build/sections/Header/HeaderSettingsDialog.mjs.map +1 -1
  274. package/build/sections/Header/RegistryInfoContent/RegistryInfoContent.d.ts +1 -4
  275. package/build/sections/Header/RegistryInfoContent/RegistryInfoContent.js +98 -15
  276. package/build/sections/Header/RegistryInfoContent/RegistryInfoContent.js.map +1 -1
  277. package/build/sections/Header/RegistryInfoContent/RegistryInfoContent.mjs +100 -15
  278. package/build/sections/Header/RegistryInfoContent/RegistryInfoContent.mjs.map +1 -1
  279. package/build/sections/Home/Home.js +58 -2
  280. package/build/sections/Home/Home.js.map +1 -1
  281. package/build/sections/Home/Home.mjs +60 -4
  282. package/build/sections/Home/Home.mjs.map +1 -1
  283. package/build/utils/cli-utils.d.ts +10 -0
  284. package/build/utils/cli-utils.js +26 -0
  285. package/build/utils/cli-utils.js.map +1 -1
  286. package/build/utils/cli-utils.mjs +23 -1
  287. package/build/utils/cli-utils.mjs.map +1 -1
  288. package/build/utils/index.d.ts +1 -1
  289. package/build/utils/index.js +4 -0
  290. package/build/utils/index.mjs +2 -2
  291. package/build/utils/markdown.d.ts +6 -0
  292. package/build/utils/markdown.js +16 -0
  293. package/build/utils/markdown.js.map +1 -0
  294. package/build/utils/markdown.mjs +13 -0
  295. package/build/utils/markdown.mjs.map +1 -0
  296. package/package.json +8 -8
@@ -7,7 +7,7 @@ let react_jsx_runtime = require("react/jsx-runtime");
7
7
  let _mui_material_Autocomplete = require("@mui/material/Autocomplete");
8
8
  _mui_material_Autocomplete = require_runtime.__toESM(_mui_material_Autocomplete);
9
9
  //#region src/components/Search/AutoComplete/AutoComplete.tsx
10
- var AutoComplete = ({ suggestions = [], onSuggestionsFetch, onCleanSuggestions, renderInput, renderOption, getOptionLabel, onSelectItem, suggestionsLoading = false, hasError = false }) => {
10
+ var AutoComplete = ({ suggestions = [], onSuggestionsFetch, onCleanSuggestions, renderInput, renderOption, getOptionLabel, onSelectItem, suggestionsLoading = false, hasError = false, groupBy, renderGroup }) => {
11
11
  const { t } = (0, react_i18next.useTranslation)();
12
12
  const [inputValue, setInputValue] = (0, react.useState)("");
13
13
  const handleOnInputChange = (event, value, reason) => {
@@ -30,6 +30,7 @@ var AutoComplete = ({ suggestions = [], onSuggestionsFetch, onCleanSuggestions,
30
30
  filterOptions: (options, state) => state.inputValue.trim() ? options : [],
31
31
  fullWidth: true,
32
32
  getOptionLabel,
33
+ groupBy,
33
34
  id: "search-header-suggest",
34
35
  inputValue,
35
36
  loading: suggestionsLoading,
@@ -40,6 +41,7 @@ var AutoComplete = ({ suggestions = [], onSuggestionsFetch, onCleanSuggestions,
40
41
  onInputChange: handleOnInputChange,
41
42
  options: hasError ? [] : suggestions,
42
43
  renderInput,
44
+ renderGroup,
43
45
  renderOption,
44
46
  renderTags: () => null
45
47
  }) });
@@ -1 +1 @@
1
- {"version":3,"file":"AutoComplete.js","names":["useTranslation","useState","Wrapper","Autocomplete"],"sources":["../../../../src/components/Search/AutoComplete/AutoComplete.tsx"],"sourcesContent":["import Autocomplete from '@mui/material/Autocomplete';\nimport type { FC } from 'react';\nimport React, { useState } from 'react';\nimport { useTranslation } from 'react-i18next';\n\nimport type { SearchResultWeb } from '@verdaccio/types';\n\nimport { Wrapper } from './styles';\n\nexport type OnSelecItem = (\n event: React.SyntheticEvent,\n value: SearchResultWeb,\n reason: string,\n details?: string\n) => void;\ninterface Props {\n suggestions?: SearchResultWeb[];\n suggestionsLoading?: boolean;\n hasError?: boolean;\n placeholder: string;\n renderOption?: (props: any, option: any) => React.JSX.Element;\n renderInput: (params: any) => React.JSX.Element;\n onSuggestionsFetch: any;\n getOptionLabel: (option: any) => any;\n onCleanSuggestions: (event: React.SyntheticEvent) => void;\n onSelectItem: OnSelecItem;\n}\n\nconst AutoComplete: FC<Props> = ({\n suggestions = [],\n onSuggestionsFetch,\n onCleanSuggestions,\n renderInput,\n renderOption,\n getOptionLabel,\n onSelectItem,\n suggestionsLoading = false,\n hasError = false,\n}: Props) => {\n const { t } = useTranslation();\n const [inputValue, setInputValue] = useState('');\n\n const handleOnInputChange = (event: React.SyntheticEvent, value: string, reason: string) => {\n if (reason === 'input') {\n event.preventDefault();\n onSuggestionsFetch({ value });\n setInputValue(value);\n } else if (reason === 'clear') {\n onCleanSuggestions(event);\n setInputValue('');\n }\n };\n\n const handleOnClose = (event) => {\n onCleanSuggestions(event);\n setInputValue('');\n };\n\n // @ts-ignore\n return (\n <Wrapper>\n <Autocomplete\n /* @ts-ignore */\n clearOnBlur={true}\n disablePortal={true}\n filterOptions={(options, state) => (state.inputValue.trim() ? options : [])}\n fullWidth={true}\n getOptionLabel={getOptionLabel}\n id=\"search-header-suggest\"\n inputValue={inputValue}\n loading={suggestionsLoading}\n loadingText={t('autoComplete.loading')}\n // a failed search must not read as \"no results found\"\n noOptionsText={hasError ? t('autoComplete.error') : t('autoComplete.no-results-found')}\n onChange={onSelectItem as any}\n onClose={handleOnClose}\n onInputChange={handleOnInputChange}\n options={hasError ? [] : suggestions}\n renderInput={renderInput}\n renderOption={renderOption}\n renderTags={() => null}\n />\n </Wrapper>\n );\n};\n\nexport default AutoComplete;\n"],"mappings":";;;;;;;;;AA4BA,IAAM,gBAA2B,EAC/B,cAAc,CAAC,GACf,oBACA,oBACA,aACA,cACA,gBACA,cACA,qBAAqB,OACrB,WAAW,YACA;CACX,MAAM,EAAE,OAAA,GAAMA,cAAAA,eAAAA,CAAe;CAC7B,MAAM,CAAC,YAAY,kBAAA,GAAiBC,MAAAA,SAAAA,CAAS,EAAE;CAE/C,MAAM,uBAAuB,OAA6B,OAAe,WAAmB;EAC1F,IAAI,WAAW,SAAS;GACtB,MAAM,eAAe;GACrB,mBAAmB,EAAE,MAAM,CAAC;GAC5B,cAAc,KAAK;EACrB,OAAO,IAAI,WAAW,SAAS;GAC7B,mBAAmB,KAAK;GACxB,cAAc,EAAE;EAClB;CACF;CAEA,MAAM,iBAAiB,UAAU;EAC/B,mBAAmB,KAAK;EACxB,cAAc,EAAE;CAClB;CAGA,OACE,iBAAA,GAAA,kBAAA,IAAA,CAACC,eAAAA,SAAD,EAAA,UACE,iBAAA,GAAA,kBAAA,IAAA,CAACC,2BAAAA,SAAD;EAEE,aAAa;EACb,eAAe;EACf,gBAAgB,SAAS,UAAW,MAAM,WAAW,KAAK,IAAI,UAAU,CAAC;EACzE,WAAW;EACK;EAChB,IAAG;EACS;EACZ,SAAS;EACT,aAAa,EAAE,sBAAsB;EAErC,eAAe,WAAW,EAAE,oBAAoB,IAAI,EAAE,+BAA+B;EACrF,UAAU;EACV,SAAS;EACT,eAAe;EACf,SAAS,WAAW,CAAC,IAAI;EACZ;EACC;EACd,kBAAkB;CACnB,CAAA,EACM,CAAA;AAEb"}
1
+ {"version":3,"file":"AutoComplete.js","names":["useTranslation","useState","Wrapper","Autocomplete"],"sources":["../../../../src/components/Search/AutoComplete/AutoComplete.tsx"],"sourcesContent":["import type { AutocompleteRenderGroupParams } from '@mui/material/Autocomplete';\nimport Autocomplete from '@mui/material/Autocomplete';\nimport type { FC } from 'react';\nimport React, { useState } from 'react';\nimport { useTranslation } from 'react-i18next';\n\nimport type { SearchResultWeb } from '@verdaccio/types';\n\nimport { Wrapper } from './styles';\n\nexport type OnSelecItem = (\n event: React.SyntheticEvent,\n value: SearchResultWeb,\n reason: string,\n details?: string\n) => void;\ninterface Props {\n suggestions?: SearchResultWeb[];\n suggestionsLoading?: boolean;\n hasError?: boolean;\n placeholder: string;\n renderOption?: (props: any, option: any) => React.JSX.Element;\n renderInput: (params: any) => React.JSX.Element;\n onSuggestionsFetch: any;\n getOptionLabel: (option: any) => any;\n onCleanSuggestions: (event: React.SyntheticEvent) => void;\n onSelectItem: OnSelecItem;\n groupBy?: (option: any) => string;\n renderGroup?: (params: AutocompleteRenderGroupParams) => React.ReactNode;\n}\n\nconst AutoComplete: FC<Props> = ({\n suggestions = [],\n onSuggestionsFetch,\n onCleanSuggestions,\n renderInput,\n renderOption,\n getOptionLabel,\n onSelectItem,\n suggestionsLoading = false,\n hasError = false,\n groupBy,\n renderGroup,\n}: Props) => {\n const { t } = useTranslation();\n const [inputValue, setInputValue] = useState('');\n\n const handleOnInputChange = (event: React.SyntheticEvent, value: string, reason: string) => {\n if (reason === 'input') {\n event.preventDefault();\n onSuggestionsFetch({ value });\n setInputValue(value);\n } else if (reason === 'clear') {\n onCleanSuggestions(event);\n setInputValue('');\n }\n };\n\n const handleOnClose = (event) => {\n onCleanSuggestions(event);\n setInputValue('');\n };\n\n // @ts-ignore\n return (\n <Wrapper>\n <Autocomplete\n /* @ts-ignore */\n clearOnBlur={true}\n disablePortal={true}\n filterOptions={(options, state) => (state.inputValue.trim() ? options : [])}\n fullWidth={true}\n getOptionLabel={getOptionLabel}\n groupBy={groupBy}\n id=\"search-header-suggest\"\n inputValue={inputValue}\n loading={suggestionsLoading}\n loadingText={t('autoComplete.loading')}\n // a failed search must not read as \"no results found\"\n noOptionsText={hasError ? t('autoComplete.error') : t('autoComplete.no-results-found')}\n onChange={onSelectItem as any}\n onClose={handleOnClose}\n onInputChange={handleOnInputChange}\n options={hasError ? [] : suggestions}\n renderInput={renderInput}\n renderGroup={renderGroup}\n renderOption={renderOption}\n renderTags={() => null}\n />\n </Wrapper>\n );\n};\n\nexport default AutoComplete;\n"],"mappings":";;;;;;;;;AA+BA,IAAM,gBAA2B,EAC/B,cAAc,CAAC,GACf,oBACA,oBACA,aACA,cACA,gBACA,cACA,qBAAqB,OACrB,WAAW,OACX,SACA,kBACW;CACX,MAAM,EAAE,OAAA,GAAMA,cAAAA,eAAAA,CAAe;CAC7B,MAAM,CAAC,YAAY,kBAAA,GAAiBC,MAAAA,SAAAA,CAAS,EAAE;CAE/C,MAAM,uBAAuB,OAA6B,OAAe,WAAmB;EAC1F,IAAI,WAAW,SAAS;GACtB,MAAM,eAAe;GACrB,mBAAmB,EAAE,MAAM,CAAC;GAC5B,cAAc,KAAK;EACrB,OAAO,IAAI,WAAW,SAAS;GAC7B,mBAAmB,KAAK;GACxB,cAAc,EAAE;EAClB;CACF;CAEA,MAAM,iBAAiB,UAAU;EAC/B,mBAAmB,KAAK;EACxB,cAAc,EAAE;CAClB;CAGA,OACE,iBAAA,GAAA,kBAAA,IAAA,CAACC,eAAAA,SAAD,EAAA,UACE,iBAAA,GAAA,kBAAA,IAAA,CAACC,2BAAAA,SAAD;EAEE,aAAa;EACb,eAAe;EACf,gBAAgB,SAAS,UAAW,MAAM,WAAW,KAAK,IAAI,UAAU,CAAC;EACzE,WAAW;EACK;EACP;EACT,IAAG;EACS;EACZ,SAAS;EACT,aAAa,EAAE,sBAAsB;EAErC,eAAe,WAAW,EAAE,oBAAoB,IAAI,EAAE,+BAA+B;EACrF,UAAU;EACV,SAAS;EACT,eAAe;EACf,SAAS,WAAW,CAAC,IAAI;EACZ;EACA;EACC;EACd,kBAAkB;CACnB,CAAA,EACM,CAAA;AAEb"}
@@ -4,7 +4,7 @@ import { useTranslation } from "react-i18next";
4
4
  import { jsx } from "react/jsx-runtime";
5
5
  import Autocomplete from "@mui/material/Autocomplete";
6
6
  //#region src/components/Search/AutoComplete/AutoComplete.tsx
7
- var AutoComplete = ({ suggestions = [], onSuggestionsFetch, onCleanSuggestions, renderInput, renderOption, getOptionLabel, onSelectItem, suggestionsLoading = false, hasError = false }) => {
7
+ var AutoComplete = ({ suggestions = [], onSuggestionsFetch, onCleanSuggestions, renderInput, renderOption, getOptionLabel, onSelectItem, suggestionsLoading = false, hasError = false, groupBy, renderGroup }) => {
8
8
  const { t } = useTranslation();
9
9
  const [inputValue, setInputValue] = useState("");
10
10
  const handleOnInputChange = (event, value, reason) => {
@@ -27,6 +27,7 @@ var AutoComplete = ({ suggestions = [], onSuggestionsFetch, onCleanSuggestions,
27
27
  filterOptions: (options, state) => state.inputValue.trim() ? options : [],
28
28
  fullWidth: true,
29
29
  getOptionLabel,
30
+ groupBy,
30
31
  id: "search-header-suggest",
31
32
  inputValue,
32
33
  loading: suggestionsLoading,
@@ -37,6 +38,7 @@ var AutoComplete = ({ suggestions = [], onSuggestionsFetch, onCleanSuggestions,
37
38
  onInputChange: handleOnInputChange,
38
39
  options: hasError ? [] : suggestions,
39
40
  renderInput,
41
+ renderGroup,
40
42
  renderOption,
41
43
  renderTags: () => null
42
44
  }) });
@@ -1 +1 @@
1
- {"version":3,"file":"AutoComplete.mjs","names":[],"sources":["../../../../src/components/Search/AutoComplete/AutoComplete.tsx"],"sourcesContent":["import Autocomplete from '@mui/material/Autocomplete';\nimport type { FC } from 'react';\nimport React, { useState } from 'react';\nimport { useTranslation } from 'react-i18next';\n\nimport type { SearchResultWeb } from '@verdaccio/types';\n\nimport { Wrapper } from './styles';\n\nexport type OnSelecItem = (\n event: React.SyntheticEvent,\n value: SearchResultWeb,\n reason: string,\n details?: string\n) => void;\ninterface Props {\n suggestions?: SearchResultWeb[];\n suggestionsLoading?: boolean;\n hasError?: boolean;\n placeholder: string;\n renderOption?: (props: any, option: any) => React.JSX.Element;\n renderInput: (params: any) => React.JSX.Element;\n onSuggestionsFetch: any;\n getOptionLabel: (option: any) => any;\n onCleanSuggestions: (event: React.SyntheticEvent) => void;\n onSelectItem: OnSelecItem;\n}\n\nconst AutoComplete: FC<Props> = ({\n suggestions = [],\n onSuggestionsFetch,\n onCleanSuggestions,\n renderInput,\n renderOption,\n getOptionLabel,\n onSelectItem,\n suggestionsLoading = false,\n hasError = false,\n}: Props) => {\n const { t } = useTranslation();\n const [inputValue, setInputValue] = useState('');\n\n const handleOnInputChange = (event: React.SyntheticEvent, value: string, reason: string) => {\n if (reason === 'input') {\n event.preventDefault();\n onSuggestionsFetch({ value });\n setInputValue(value);\n } else if (reason === 'clear') {\n onCleanSuggestions(event);\n setInputValue('');\n }\n };\n\n const handleOnClose = (event) => {\n onCleanSuggestions(event);\n setInputValue('');\n };\n\n // @ts-ignore\n return (\n <Wrapper>\n <Autocomplete\n /* @ts-ignore */\n clearOnBlur={true}\n disablePortal={true}\n filterOptions={(options, state) => (state.inputValue.trim() ? options : [])}\n fullWidth={true}\n getOptionLabel={getOptionLabel}\n id=\"search-header-suggest\"\n inputValue={inputValue}\n loading={suggestionsLoading}\n loadingText={t('autoComplete.loading')}\n // a failed search must not read as \"no results found\"\n noOptionsText={hasError ? t('autoComplete.error') : t('autoComplete.no-results-found')}\n onChange={onSelectItem as any}\n onClose={handleOnClose}\n onInputChange={handleOnInputChange}\n options={hasError ? [] : suggestions}\n renderInput={renderInput}\n renderOption={renderOption}\n renderTags={() => null}\n />\n </Wrapper>\n );\n};\n\nexport default AutoComplete;\n"],"mappings":";;;;;;AA4BA,IAAM,gBAA2B,EAC/B,cAAc,CAAC,GACf,oBACA,oBACA,aACA,cACA,gBACA,cACA,qBAAqB,OACrB,WAAW,YACA;CACX,MAAM,EAAE,MAAM,eAAe;CAC7B,MAAM,CAAC,YAAY,iBAAiB,SAAS,EAAE;CAE/C,MAAM,uBAAuB,OAA6B,OAAe,WAAmB;EAC1F,IAAI,WAAW,SAAS;GACtB,MAAM,eAAe;GACrB,mBAAmB,EAAE,MAAM,CAAC;GAC5B,cAAc,KAAK;EACrB,OAAO,IAAI,WAAW,SAAS;GAC7B,mBAAmB,KAAK;GACxB,cAAc,EAAE;EAClB;CACF;CAEA,MAAM,iBAAiB,UAAU;EAC/B,mBAAmB,KAAK;EACxB,cAAc,EAAE;CAClB;CAGA,OACE,oBAAC,SAAD,EAAA,UACE,oBAAC,cAAD;EAEE,aAAa;EACb,eAAe;EACf,gBAAgB,SAAS,UAAW,MAAM,WAAW,KAAK,IAAI,UAAU,CAAC;EACzE,WAAW;EACK;EAChB,IAAG;EACS;EACZ,SAAS;EACT,aAAa,EAAE,sBAAsB;EAErC,eAAe,WAAW,EAAE,oBAAoB,IAAI,EAAE,+BAA+B;EACrF,UAAU;EACV,SAAS;EACT,eAAe;EACf,SAAS,WAAW,CAAC,IAAI;EACZ;EACC;EACd,kBAAkB;CACnB,CAAA,EACM,CAAA;AAEb"}
1
+ {"version":3,"file":"AutoComplete.mjs","names":[],"sources":["../../../../src/components/Search/AutoComplete/AutoComplete.tsx"],"sourcesContent":["import type { AutocompleteRenderGroupParams } from '@mui/material/Autocomplete';\nimport Autocomplete from '@mui/material/Autocomplete';\nimport type { FC } from 'react';\nimport React, { useState } from 'react';\nimport { useTranslation } from 'react-i18next';\n\nimport type { SearchResultWeb } from '@verdaccio/types';\n\nimport { Wrapper } from './styles';\n\nexport type OnSelecItem = (\n event: React.SyntheticEvent,\n value: SearchResultWeb,\n reason: string,\n details?: string\n) => void;\ninterface Props {\n suggestions?: SearchResultWeb[];\n suggestionsLoading?: boolean;\n hasError?: boolean;\n placeholder: string;\n renderOption?: (props: any, option: any) => React.JSX.Element;\n renderInput: (params: any) => React.JSX.Element;\n onSuggestionsFetch: any;\n getOptionLabel: (option: any) => any;\n onCleanSuggestions: (event: React.SyntheticEvent) => void;\n onSelectItem: OnSelecItem;\n groupBy?: (option: any) => string;\n renderGroup?: (params: AutocompleteRenderGroupParams) => React.ReactNode;\n}\n\nconst AutoComplete: FC<Props> = ({\n suggestions = [],\n onSuggestionsFetch,\n onCleanSuggestions,\n renderInput,\n renderOption,\n getOptionLabel,\n onSelectItem,\n suggestionsLoading = false,\n hasError = false,\n groupBy,\n renderGroup,\n}: Props) => {\n const { t } = useTranslation();\n const [inputValue, setInputValue] = useState('');\n\n const handleOnInputChange = (event: React.SyntheticEvent, value: string, reason: string) => {\n if (reason === 'input') {\n event.preventDefault();\n onSuggestionsFetch({ value });\n setInputValue(value);\n } else if (reason === 'clear') {\n onCleanSuggestions(event);\n setInputValue('');\n }\n };\n\n const handleOnClose = (event) => {\n onCleanSuggestions(event);\n setInputValue('');\n };\n\n // @ts-ignore\n return (\n <Wrapper>\n <Autocomplete\n /* @ts-ignore */\n clearOnBlur={true}\n disablePortal={true}\n filterOptions={(options, state) => (state.inputValue.trim() ? options : [])}\n fullWidth={true}\n getOptionLabel={getOptionLabel}\n groupBy={groupBy}\n id=\"search-header-suggest\"\n inputValue={inputValue}\n loading={suggestionsLoading}\n loadingText={t('autoComplete.loading')}\n // a failed search must not read as \"no results found\"\n noOptionsText={hasError ? t('autoComplete.error') : t('autoComplete.no-results-found')}\n onChange={onSelectItem as any}\n onClose={handleOnClose}\n onInputChange={handleOnInputChange}\n options={hasError ? [] : suggestions}\n renderInput={renderInput}\n renderGroup={renderGroup}\n renderOption={renderOption}\n renderTags={() => null}\n />\n </Wrapper>\n );\n};\n\nexport default AutoComplete;\n"],"mappings":";;;;;;AA+BA,IAAM,gBAA2B,EAC/B,cAAc,CAAC,GACf,oBACA,oBACA,aACA,cACA,gBACA,cACA,qBAAqB,OACrB,WAAW,OACX,SACA,kBACW;CACX,MAAM,EAAE,MAAM,eAAe;CAC7B,MAAM,CAAC,YAAY,iBAAiB,SAAS,EAAE;CAE/C,MAAM,uBAAuB,OAA6B,OAAe,WAAmB;EAC1F,IAAI,WAAW,SAAS;GACtB,MAAM,eAAe;GACrB,mBAAmB,EAAE,MAAM,CAAC;GAC5B,cAAc,KAAK;EACrB,OAAO,IAAI,WAAW,SAAS;GAC7B,mBAAmB,KAAK;GACxB,cAAc,EAAE;EAClB;CACF;CAEA,MAAM,iBAAiB,UAAU;EAC/B,mBAAmB,KAAK;EACxB,cAAc,EAAE;CAClB;CAGA,OACE,oBAAC,SAAD,EAAA,UACE,oBAAC,cAAD;EAEE,aAAa;EACb,eAAe;EACf,gBAAgB,SAAS,UAAW,MAAM,WAAW,KAAK,IAAI,UAAU,CAAC;EACzE,WAAW;EACK;EACP;EACT,IAAG;EACS;EACZ,SAAS;EACT,aAAa,EAAE,sBAAsB;EAErC,eAAe,WAAW,EAAE,oBAAoB,IAAI,EAAE,+BAA+B;EACrF,UAAU;EACV,SAAS;EACT,eAAe;EACf,SAAS,WAAW,CAAC,IAAI;EACZ;EACA;EACC;EACd,kBAAkB;CACnB,CAAA,EACM,CAAA;AAEb"}
@@ -1,6 +1,7 @@
1
1
  const require_runtime = require("../../_virtual/_rolldown/runtime.js");
2
2
  const require_routes = require("../../utils/routes.js");
3
3
  require("../../utils/index.js");
4
+ const require_AppConfigurationProvider = require("../../providers/AppConfigurationProvider/AppConfigurationProvider.js");
4
5
  const require_SearchProvider = require("../../providers/SearchProvider/SearchProvider.js");
5
6
  const require_AutoComplete = require("./AutoComplete/AutoComplete.js");
6
7
  require("./AutoComplete/index.js");
@@ -16,6 +17,8 @@ let lodash_es = require("lodash-es");
16
17
  let react_router = require("react-router");
17
18
  let _mui_icons_material_Search = require("@mui/icons-material/Search");
18
19
  _mui_icons_material_Search = require_runtime.__toESM(_mui_icons_material_Search);
20
+ let _mui_material_ListSubheader = require("@mui/material/ListSubheader");
21
+ _mui_material_ListSubheader = require_runtime.__toESM(_mui_material_ListSubheader);
19
22
  //#region src/components/Search/Search.tsx
20
23
  var CONSTANTS = {
21
24
  API_DELAY: 300,
@@ -25,6 +28,9 @@ var Search = () => {
25
28
  const { t } = (0, react_i18next.useTranslation)();
26
29
  const navigate = (0, react_router.useNavigate)();
27
30
  const { searchResults, isLoading, isError, doSearch, resetSearch } = require_SearchProvider.useSearch();
31
+ const { configOptions } = require_AppConfigurationProvider.useConfig();
32
+ const groupByOrigin = configOptions?.showUplinks === true;
33
+ const suggestions = (0, react.useMemo)(() => groupByOrigin && searchResults ? require_utils.sortByOrigin(searchResults) : searchResults, [groupByOrigin, searchResults]);
28
34
  const abortControllerRef = (0, react.useRef)(null);
29
35
  const cancelAllSearchRequests = (0, react.useCallback)(() => {
30
36
  if (abortControllerRef.current) {
@@ -107,19 +113,40 @@ var Search = () => {
107
113
  variant: "standard"
108
114
  });
109
115
  };
116
+ const getOptionGroup = (option) => require_utils.normalizeSearchOption(option).origin ?? "";
117
+ const renderGroup = ({ key, group, children }) => {
118
+ if (!group) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react.default.Fragment, { children }, key);
119
+ const OriginIcon = require_SearchItem.ORIGIN_ICONS[group];
120
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("li", { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)(_mui_material_ListSubheader.default, {
121
+ component: "div",
122
+ "data-testid": `search-group-${group}`,
123
+ sx: {
124
+ display: "flex",
125
+ alignItems: "center",
126
+ gap: 1,
127
+ lineHeight: "36px"
128
+ },
129
+ children: [OriginIcon && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(OriginIcon, { fontSize: "small" }), t(`search.group.${group}`, { count: react.default.Children.count(children) })]
130
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("ul", {
131
+ style: { padding: 0 },
132
+ children
133
+ })] }, key);
134
+ };
110
135
  const getOptionLabel = (option) => {
111
136
  return require_utils.normalizeSearchOption(option).name;
112
137
  };
113
138
  return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_AutoComplete.default, {
114
139
  getOptionLabel,
140
+ groupBy: groupByOrigin ? getOptionGroup : void 0,
115
141
  hasError: isError,
116
142
  onCleanSuggestions: handleOnBlur,
117
143
  onSelectItem: handleClickSearch,
118
144
  onSuggestionsFetch: handleSuggestionsFetch,
119
145
  placeholder: t("search.packages"),
146
+ renderGroup: groupByOrigin ? renderGroup : void 0,
120
147
  renderInput,
121
148
  renderOption,
122
- suggestions: searchResults,
149
+ suggestions,
123
150
  suggestionsLoading: isLoading || isDebouncing
124
151
  });
125
152
  };
@@ -1 +1 @@
1
- {"version":3,"file":"Search.js","names":["useTranslation","useNavigate","useSearch","useRef","useCallback","normalizeSearchOption","Route","useState","useMemo","debounce","SearchItem","StyledTextField","StyledInputAdornment","SearchMui","AutoComplete"],"sources":["../../../src/components/Search/Search.tsx"],"sourcesContent":["import SearchMui from '@mui/icons-material/Search';\nimport { debounce } from 'lodash-es';\nimport React, { useCallback, useEffect, useMemo, useRef, useState } from 'react';\nimport { useTranslation } from 'react-i18next';\nimport { useNavigate } from 'react-router';\n\nimport { useSearch } from '../../';\nimport { Route } from '../../utils';\nimport AutoComplete from './AutoComplete';\nimport SearchItem from './SearchItem';\nimport { StyledInputAdornment, StyledTextField } from './styles';\nimport { normalizeSearchOption } from './utils';\n\nconst CONSTANTS = {\n API_DELAY: 300,\n ABORT_ERROR: 'AbortError',\n};\n\nconst Search: React.FC = () => {\n const { t } = useTranslation();\n const navigate = useNavigate();\n const { searchResults, isLoading, isError, doSearch, resetSearch } = useSearch();\n\n const abortControllerRef = useRef<AbortController | null>(null);\n\n const cancelAllSearchRequests = useCallback(() => {\n if (abortControllerRef.current) {\n abortControllerRef.current.abort();\n abortControllerRef.current = null;\n }\n }, []);\n\n const handleOnBlur = useCallback(\n (event: React.SyntheticEvent) => {\n event.stopPropagation();\n cancelAllSearchRequests();\n },\n [cancelAllSearchRequests]\n );\n\n const handleClickSearch = useCallback(\n (event: React.SyntheticEvent, value: any, reason: string): void => {\n event.stopPropagation();\n if (reason === 'selectOption') {\n const { name } = normalizeSearchOption(value);\n if (name) {\n navigate(`${Route.DETAIL}${name}`);\n }\n }\n },\n [navigate]\n );\n\n // Use a ref to always access the latest doSearch without re-creating the debounced function\n const doSearchRef = useRef(doSearch);\n doSearchRef.current = doSearch;\n\n // shows the dropdown as loading during the debounce window; without it the\n // immediate reset below reads as \"no results found\" on every keystroke\n const [isDebouncing, setIsDebouncing] = useState(false);\n\n /**\n * Stable fetch function that reads the latest doSearch from a ref,\n * avoiding dependency changes that would break the debounce.\n */\n const handleFetchPackages = useCallback(\n async ({ value }: { value: string }) => {\n setIsDebouncing(false);\n if (value?.trim() !== '') {\n // Abort any previous pending request before starting a new one\n cancelAllSearchRequests();\n\n // Create a new controller for the current request\n const controller = new AbortController();\n abortControllerRef.current = controller;\n\n try {\n await doSearchRef.current?.({\n text: value,\n signal: controller.signal,\n });\n } catch (err: any) {\n if (err.name === CONSTANTS.ABORT_ERROR) {\n console.warn('Search request aborted');\n } else {\n console.error('Search error:', err);\n }\n }\n }\n },\n [cancelAllSearchRequests]\n );\n\n // Memoize the debounced function so a single instance is reused across renders,\n // ensuring the debounce timer works correctly instead of creating a new timer per render.\n const debouncedFetch = useMemo(\n () => debounce(handleFetchPackages, CONSTANTS.API_DELAY),\n [handleFetchPackages]\n );\n\n // clear the previous query's results right away so the dropdown never lists\n // stale suggestions under the new input while the debounce timer runs\n const handleSuggestionsFetch = useCallback(\n ({ value }: { value: string }) => {\n resetSearch?.();\n if (value?.trim() !== '') {\n setIsDebouncing(true);\n }\n debouncedFetch({ value });\n },\n [resetSearch, debouncedFetch]\n );\n\n useEffect(() => {\n return () => {\n debouncedFetch.cancel?.();\n cancelAllSearchRequests();\n };\n }, [debouncedFetch, cancelAllSearchRequests]);\n\n const renderOption = (props, option) => {\n const { key, ...otherProps } = props;\n const { name, version, description, isPrivate, isCached, isRemote } =\n normalizeSearchOption(option);\n return (\n <SearchItem\n key={key}\n {...otherProps}\n description={description}\n isCached={isCached}\n isPrivate={isPrivate}\n isRemote={isRemote}\n name={name}\n version={version}\n />\n );\n };\n\n const renderInput = (params) => {\n return (\n <StyledTextField\n {...params}\n InputProps={{\n ...params.InputProps,\n startAdornment: (\n <StyledInputAdornment position=\"start\">\n <SearchMui />\n </StyledInputAdornment>\n ),\n }}\n label=\"\"\n placeholder={t('search.packages')}\n variant=\"standard\"\n />\n );\n };\n\n const getOptionLabel = (option) => {\n return normalizeSearchOption(option).name;\n };\n\n return (\n <AutoComplete\n getOptionLabel={getOptionLabel}\n hasError={isError}\n onCleanSuggestions={handleOnBlur}\n onSelectItem={handleClickSearch}\n onSuggestionsFetch={handleSuggestionsFetch}\n placeholder={t('search.packages')}\n renderInput={renderInput}\n renderOption={renderOption}\n suggestions={searchResults}\n suggestionsLoading={isLoading || isDebouncing}\n />\n );\n};\n\nexport default Search;\n"],"mappings":"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"}
1
+ {"version":3,"file":"Search.js","names":["useTranslation","useNavigate","useSearch","useConfig","useMemo","sortByOrigin","useRef","useCallback","normalizeSearchOption","Route","useState","debounce","SearchItem","StyledTextField","StyledInputAdornment","SearchMui","React","ORIGIN_ICONS","ListSubheader","AutoComplete"],"sources":["../../../src/components/Search/Search.tsx"],"sourcesContent":["import SearchMui from '@mui/icons-material/Search';\nimport type { AutocompleteRenderGroupParams } from '@mui/material/Autocomplete';\nimport ListSubheader from '@mui/material/ListSubheader';\nimport { debounce } from 'lodash-es';\nimport React, { useCallback, useEffect, useMemo, useRef, useState } from 'react';\nimport { useTranslation } from 'react-i18next';\nimport { useNavigate } from 'react-router';\n\nimport { useConfig, useSearch } from '../../';\nimport { Route } from '../../utils';\nimport AutoComplete from './AutoComplete';\nimport SearchItem, { ORIGIN_ICONS } from './SearchItem';\nimport { StyledInputAdornment, StyledTextField } from './styles';\nimport type { SearchOrigin } from './utils';\nimport { normalizeSearchOption, sortByOrigin } from './utils';\n\nconst CONSTANTS = {\n API_DELAY: 300,\n ABORT_ERROR: 'AbortError',\n};\n\nconst Search: React.FC = () => {\n const { t } = useTranslation();\n const navigate = useNavigate();\n const { searchResults, isLoading, isError, doSearch, resetSearch } = useSearch();\n const { configOptions } = useConfig();\n const groupByOrigin = configOptions?.showUplinks === true;\n const suggestions = useMemo(\n () => (groupByOrigin && searchResults ? sortByOrigin(searchResults) : searchResults),\n [groupByOrigin, searchResults]\n );\n\n const abortControllerRef = useRef<AbortController | null>(null);\n\n const cancelAllSearchRequests = useCallback(() => {\n if (abortControllerRef.current) {\n abortControllerRef.current.abort();\n abortControllerRef.current = null;\n }\n }, []);\n\n const handleOnBlur = useCallback(\n (event: React.SyntheticEvent) => {\n event.stopPropagation();\n cancelAllSearchRequests();\n },\n [cancelAllSearchRequests]\n );\n\n const handleClickSearch = useCallback(\n (event: React.SyntheticEvent, value: any, reason: string): void => {\n event.stopPropagation();\n if (reason === 'selectOption') {\n const { name } = normalizeSearchOption(value);\n if (name) {\n navigate(`${Route.DETAIL}${name}`);\n }\n }\n },\n [navigate]\n );\n\n // Use a ref to always access the latest doSearch without re-creating the debounced function\n const doSearchRef = useRef(doSearch);\n doSearchRef.current = doSearch;\n\n // shows the dropdown as loading during the debounce window; without it the\n // immediate reset below reads as \"no results found\" on every keystroke\n const [isDebouncing, setIsDebouncing] = useState(false);\n\n /**\n * Stable fetch function that reads the latest doSearch from a ref,\n * avoiding dependency changes that would break the debounce.\n */\n const handleFetchPackages = useCallback(\n async ({ value }: { value: string }) => {\n setIsDebouncing(false);\n if (value?.trim() !== '') {\n // Abort any previous pending request before starting a new one\n cancelAllSearchRequests();\n\n // Create a new controller for the current request\n const controller = new AbortController();\n abortControllerRef.current = controller;\n\n try {\n await doSearchRef.current?.({\n text: value,\n signal: controller.signal,\n });\n } catch (err: any) {\n if (err.name === CONSTANTS.ABORT_ERROR) {\n console.warn('Search request aborted');\n } else {\n console.error('Search error:', err);\n }\n }\n }\n },\n [cancelAllSearchRequests]\n );\n\n // Memoize the debounced function so a single instance is reused across renders,\n // ensuring the debounce timer works correctly instead of creating a new timer per render.\n const debouncedFetch = useMemo(\n () => debounce(handleFetchPackages, CONSTANTS.API_DELAY),\n [handleFetchPackages]\n );\n\n // clear the previous query's results right away so the dropdown never lists\n // stale suggestions under the new input while the debounce timer runs\n const handleSuggestionsFetch = useCallback(\n ({ value }: { value: string }) => {\n resetSearch?.();\n if (value?.trim() !== '') {\n setIsDebouncing(true);\n }\n debouncedFetch({ value });\n },\n [resetSearch, debouncedFetch]\n );\n\n useEffect(() => {\n return () => {\n debouncedFetch.cancel?.();\n cancelAllSearchRequests();\n };\n }, [debouncedFetch, cancelAllSearchRequests]);\n\n const renderOption = (props, option) => {\n const { key, ...otherProps } = props;\n const { name, version, description, isPrivate, isCached, isRemote } =\n normalizeSearchOption(option);\n return (\n <SearchItem\n key={key}\n {...otherProps}\n description={description}\n isCached={isCached}\n isPrivate={isPrivate}\n isRemote={isRemote}\n name={name}\n version={version}\n />\n );\n };\n\n const renderInput = (params) => {\n return (\n <StyledTextField\n {...params}\n InputProps={{\n ...params.InputProps,\n startAdornment: (\n <StyledInputAdornment position=\"start\">\n <SearchMui />\n </StyledInputAdornment>\n ),\n }}\n label=\"\"\n placeholder={t('search.packages')}\n variant=\"standard\"\n />\n );\n };\n\n const getOptionGroup = (option) => normalizeSearchOption(option).origin ?? '';\n\n const renderGroup = ({ key, group, children }: AutocompleteRenderGroupParams) => {\n if (!group) {\n return <React.Fragment key={key}>{children}</React.Fragment>;\n }\n const OriginIcon = ORIGIN_ICONS[group as SearchOrigin];\n return (\n <li key={key}>\n {/* a div: the default <li> would nest a list item inside the group's <li> */}\n <ListSubheader\n component=\"div\"\n data-testid={`search-group-${group}`}\n sx={{ display: 'flex', alignItems: 'center', gap: 1, lineHeight: '36px' }}\n >\n {OriginIcon && <OriginIcon fontSize=\"small\" />}\n {t(`search.group.${group}`, { count: React.Children.count(children) })}\n </ListSubheader>\n <ul style={{ padding: 0 }}>{children}</ul>\n </li>\n );\n };\n\n const getOptionLabel = (option) => {\n return normalizeSearchOption(option).name;\n };\n\n return (\n <AutoComplete\n getOptionLabel={getOptionLabel}\n groupBy={groupByOrigin ? getOptionGroup : undefined}\n hasError={isError}\n onCleanSuggestions={handleOnBlur}\n onSelectItem={handleClickSearch}\n onSuggestionsFetch={handleSuggestionsFetch}\n placeholder={t('search.packages')}\n renderGroup={groupByOrigin ? renderGroup : undefined}\n renderInput={renderInput}\n renderOption={renderOption}\n suggestions={suggestions}\n suggestionsLoading={isLoading || isDebouncing}\n />\n );\n};\n\nexport default Search;\n"],"mappings":"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"}
@@ -1,18 +1,20 @@
1
1
  import { Route as Route$1 } from "../../utils/routes.mjs";
2
2
  import "../../utils/index.mjs";
3
+ import { useConfig } from "../../providers/AppConfigurationProvider/AppConfigurationProvider.mjs";
3
4
  import { useSearch } from "../../providers/SearchProvider/SearchProvider.mjs";
4
5
  import AutoComplete from "./AutoComplete/AutoComplete.mjs";
5
6
  import "./AutoComplete/index.mjs";
6
- import { normalizeSearchOption } from "./utils.mjs";
7
- import SearchItem from "./SearchItem.mjs";
7
+ import { normalizeSearchOption, sortByOrigin } from "./utils.mjs";
8
+ import SearchItem, { ORIGIN_ICONS } from "./SearchItem.mjs";
8
9
  import { StyledInputAdornment, StyledTextField } from "./styles.mjs";
9
10
  import "../../index.mjs";
10
- import { useCallback, useEffect, useMemo, useRef, useState } from "react";
11
+ import React, { useCallback, useEffect, useMemo, useRef, useState } from "react";
11
12
  import { useTranslation } from "react-i18next";
12
- import { jsx } from "react/jsx-runtime";
13
+ import { jsx, jsxs } from "react/jsx-runtime";
13
14
  import { debounce } from "lodash-es";
14
15
  import { useNavigate } from "react-router";
15
16
  import SearchMui from "@mui/icons-material/Search";
17
+ import ListSubheader from "@mui/material/ListSubheader";
16
18
  //#region src/components/Search/Search.tsx
17
19
  var CONSTANTS = {
18
20
  API_DELAY: 300,
@@ -22,6 +24,9 @@ var Search = () => {
22
24
  const { t } = useTranslation();
23
25
  const navigate = useNavigate();
24
26
  const { searchResults, isLoading, isError, doSearch, resetSearch } = useSearch();
27
+ const { configOptions } = useConfig();
28
+ const groupByOrigin = configOptions?.showUplinks === true;
29
+ const suggestions = useMemo(() => groupByOrigin && searchResults ? sortByOrigin(searchResults) : searchResults, [groupByOrigin, searchResults]);
25
30
  const abortControllerRef = useRef(null);
26
31
  const cancelAllSearchRequests = useCallback(() => {
27
32
  if (abortControllerRef.current) {
@@ -104,19 +109,40 @@ var Search = () => {
104
109
  variant: "standard"
105
110
  });
106
111
  };
112
+ const getOptionGroup = (option) => normalizeSearchOption(option).origin ?? "";
113
+ const renderGroup = ({ key, group, children }) => {
114
+ if (!group) return /* @__PURE__ */ jsx(React.Fragment, { children }, key);
115
+ const OriginIcon = ORIGIN_ICONS[group];
116
+ return /* @__PURE__ */ jsxs("li", { children: [/* @__PURE__ */ jsxs(ListSubheader, {
117
+ component: "div",
118
+ "data-testid": `search-group-${group}`,
119
+ sx: {
120
+ display: "flex",
121
+ alignItems: "center",
122
+ gap: 1,
123
+ lineHeight: "36px"
124
+ },
125
+ children: [OriginIcon && /* @__PURE__ */ jsx(OriginIcon, { fontSize: "small" }), t(`search.group.${group}`, { count: React.Children.count(children) })]
126
+ }), /* @__PURE__ */ jsx("ul", {
127
+ style: { padding: 0 },
128
+ children
129
+ })] }, key);
130
+ };
107
131
  const getOptionLabel = (option) => {
108
132
  return normalizeSearchOption(option).name;
109
133
  };
110
134
  return /* @__PURE__ */ jsx(AutoComplete, {
111
135
  getOptionLabel,
136
+ groupBy: groupByOrigin ? getOptionGroup : void 0,
112
137
  hasError: isError,
113
138
  onCleanSuggestions: handleOnBlur,
114
139
  onSelectItem: handleClickSearch,
115
140
  onSuggestionsFetch: handleSuggestionsFetch,
116
141
  placeholder: t("search.packages"),
142
+ renderGroup: groupByOrigin ? renderGroup : void 0,
117
143
  renderInput,
118
144
  renderOption,
119
- suggestions: searchResults,
145
+ suggestions,
120
146
  suggestionsLoading: isLoading || isDebouncing
121
147
  });
122
148
  };
@@ -1 +1 @@
1
- {"version":3,"file":"Search.mjs","names":["Route"],"sources":["../../../src/components/Search/Search.tsx"],"sourcesContent":["import SearchMui from '@mui/icons-material/Search';\nimport { debounce } from 'lodash-es';\nimport React, { useCallback, useEffect, useMemo, useRef, useState } from 'react';\nimport { useTranslation } from 'react-i18next';\nimport { useNavigate } from 'react-router';\n\nimport { useSearch } from '../../';\nimport { Route } from '../../utils';\nimport AutoComplete from './AutoComplete';\nimport SearchItem from './SearchItem';\nimport { StyledInputAdornment, StyledTextField } from './styles';\nimport { normalizeSearchOption } from './utils';\n\nconst CONSTANTS = {\n API_DELAY: 300,\n ABORT_ERROR: 'AbortError',\n};\n\nconst Search: React.FC = () => {\n const { t } = useTranslation();\n const navigate = useNavigate();\n const { searchResults, isLoading, isError, doSearch, resetSearch } = useSearch();\n\n const abortControllerRef = useRef<AbortController | null>(null);\n\n const cancelAllSearchRequests = useCallback(() => {\n if (abortControllerRef.current) {\n abortControllerRef.current.abort();\n abortControllerRef.current = null;\n }\n }, []);\n\n const handleOnBlur = useCallback(\n (event: React.SyntheticEvent) => {\n event.stopPropagation();\n cancelAllSearchRequests();\n },\n [cancelAllSearchRequests]\n );\n\n const handleClickSearch = useCallback(\n (event: React.SyntheticEvent, value: any, reason: string): void => {\n event.stopPropagation();\n if (reason === 'selectOption') {\n const { name } = normalizeSearchOption(value);\n if (name) {\n navigate(`${Route.DETAIL}${name}`);\n }\n }\n },\n [navigate]\n );\n\n // Use a ref to always access the latest doSearch without re-creating the debounced function\n const doSearchRef = useRef(doSearch);\n doSearchRef.current = doSearch;\n\n // shows the dropdown as loading during the debounce window; without it the\n // immediate reset below reads as \"no results found\" on every keystroke\n const [isDebouncing, setIsDebouncing] = useState(false);\n\n /**\n * Stable fetch function that reads the latest doSearch from a ref,\n * avoiding dependency changes that would break the debounce.\n */\n const handleFetchPackages = useCallback(\n async ({ value }: { value: string }) => {\n setIsDebouncing(false);\n if (value?.trim() !== '') {\n // Abort any previous pending request before starting a new one\n cancelAllSearchRequests();\n\n // Create a new controller for the current request\n const controller = new AbortController();\n abortControllerRef.current = controller;\n\n try {\n await doSearchRef.current?.({\n text: value,\n signal: controller.signal,\n });\n } catch (err: any) {\n if (err.name === CONSTANTS.ABORT_ERROR) {\n console.warn('Search request aborted');\n } else {\n console.error('Search error:', err);\n }\n }\n }\n },\n [cancelAllSearchRequests]\n );\n\n // Memoize the debounced function so a single instance is reused across renders,\n // ensuring the debounce timer works correctly instead of creating a new timer per render.\n const debouncedFetch = useMemo(\n () => debounce(handleFetchPackages, CONSTANTS.API_DELAY),\n [handleFetchPackages]\n );\n\n // clear the previous query's results right away so the dropdown never lists\n // stale suggestions under the new input while the debounce timer runs\n const handleSuggestionsFetch = useCallback(\n ({ value }: { value: string }) => {\n resetSearch?.();\n if (value?.trim() !== '') {\n setIsDebouncing(true);\n }\n debouncedFetch({ value });\n },\n [resetSearch, debouncedFetch]\n );\n\n useEffect(() => {\n return () => {\n debouncedFetch.cancel?.();\n cancelAllSearchRequests();\n };\n }, [debouncedFetch, cancelAllSearchRequests]);\n\n const renderOption = (props, option) => {\n const { key, ...otherProps } = props;\n const { name, version, description, isPrivate, isCached, isRemote } =\n normalizeSearchOption(option);\n return (\n <SearchItem\n key={key}\n {...otherProps}\n description={description}\n isCached={isCached}\n isPrivate={isPrivate}\n isRemote={isRemote}\n name={name}\n version={version}\n />\n );\n };\n\n const renderInput = (params) => {\n return (\n <StyledTextField\n {...params}\n InputProps={{\n ...params.InputProps,\n startAdornment: (\n <StyledInputAdornment position=\"start\">\n <SearchMui />\n </StyledInputAdornment>\n ),\n }}\n label=\"\"\n placeholder={t('search.packages')}\n variant=\"standard\"\n />\n );\n };\n\n const getOptionLabel = (option) => {\n return normalizeSearchOption(option).name;\n };\n\n return (\n <AutoComplete\n getOptionLabel={getOptionLabel}\n hasError={isError}\n onCleanSuggestions={handleOnBlur}\n onSelectItem={handleClickSearch}\n onSuggestionsFetch={handleSuggestionsFetch}\n placeholder={t('search.packages')}\n renderInput={renderInput}\n renderOption={renderOption}\n suggestions={searchResults}\n suggestionsLoading={isLoading || isDebouncing}\n />\n );\n};\n\nexport default Search;\n"],"mappings":";;;;;;;;;;;;;;;;AAaA,IAAM,YAAY;CAChB,WAAW;CACX,aAAa;AACf;AAEA,IAAM,eAAyB;CAC7B,MAAM,EAAE,MAAM,eAAe;CAC7B,MAAM,WAAW,YAAY;CAC7B,MAAM,EAAE,eAAe,WAAW,SAAS,UAAU,gBAAgB,UAAU;CAE/E,MAAM,qBAAqB,OAA+B,IAAI;CAE9D,MAAM,0BAA0B,kBAAkB;EAChD,IAAI,mBAAmB,SAAS;GAC9B,mBAAmB,QAAQ,MAAM;GACjC,mBAAmB,UAAU;EAC/B;CACF,GAAG,CAAC,CAAC;CAEL,MAAM,eAAe,aAClB,UAAgC;EAC/B,MAAM,gBAAgB;EACtB,wBAAwB;CAC1B,GACA,CAAC,uBAAuB,CAC1B;CAEA,MAAM,oBAAoB,aACvB,OAA6B,OAAY,WAAyB;EACjE,MAAM,gBAAgB;EACtB,IAAI,WAAW,gBAAgB;GAC7B,MAAM,EAAE,SAAS,sBAAsB,KAAK;GAC5C,IAAI,MACF,SAAS,GAAGA,QAAM,SAAS,MAAM;EAErC;CACF,GACA,CAAC,QAAQ,CACX;CAGA,MAAM,cAAc,OAAO,QAAQ;CACnC,YAAY,UAAU;CAItB,MAAM,CAAC,cAAc,mBAAmB,SAAS,KAAK;;;;;CAMtD,MAAM,sBAAsB,YAC1B,OAAO,EAAE,YAA+B;EACtC,gBAAgB,KAAK;EACrB,IAAI,OAAO,KAAK,MAAM,IAAI;GAExB,wBAAwB;GAGxB,MAAM,aAAa,IAAI,gBAAgB;GACvC,mBAAmB,UAAU;GAE7B,IAAI;IACF,MAAM,YAAY,UAAU;KAC1B,MAAM;KACN,QAAQ,WAAW;IACrB,CAAC;GACH,SAAS,KAAU;IACjB,IAAI,IAAI,SAAS,UAAU,aACzB,QAAQ,KAAK,wBAAwB;SAErC,QAAQ,MAAM,iBAAiB,GAAG;GAEtC;EACF;CACF,GACA,CAAC,uBAAuB,CAC1B;CAIA,MAAM,iBAAiB,cACf,SAAS,qBAAqB,UAAU,SAAS,GACvD,CAAC,mBAAmB,CACtB;CAIA,MAAM,yBAAyB,aAC5B,EAAE,YAA+B;EAChC,cAAc;EACd,IAAI,OAAO,KAAK,MAAM,IACpB,gBAAgB,IAAI;EAEtB,eAAe,EAAE,MAAM,CAAC;CAC1B,GACA,CAAC,aAAa,cAAc,CAC9B;CAEA,gBAAgB;EACd,aAAa;GACX,eAAe,SAAS;GACxB,wBAAwB;EAC1B;CACF,GAAG,CAAC,gBAAgB,uBAAuB,CAAC;CAE5C,MAAM,gBAAgB,OAAO,WAAW;EACtC,MAAM,EAAE,KAAK,GAAG,eAAe;EAC/B,MAAM,EAAE,MAAM,SAAS,aAAa,WAAW,UAAU,aACvD,sBAAsB,MAAM;EAC9B,OACE,oBAAC,YAAD;GAEE,GAAI;GACS;GACH;GACC;GACD;GACJ;GACG;EACV,GARM,GAQN;CAEL;CAEA,MAAM,eAAe,WAAW;EAC9B,OACE,oBAAC,iBAAD;GACE,GAAI;GACJ,YAAY;IACV,GAAG,OAAO;IACV,gBACE,oBAAC,sBAAD;KAAsB,UAAS;KAC7B,UAAA,oBAAC,WAAD,CAAY,CAAA;IACQ,CAAA;GAE1B;GACA,OAAM;GACN,aAAa,EAAE,iBAAiB;GAChC,SAAQ;EACT,CAAA;CAEL;CAEA,MAAM,kBAAkB,WAAW;EACjC,OAAO,sBAAsB,MAAM,CAAC,CAAC;CACvC;CAEA,OACE,oBAAC,cAAD;EACkB;EAChB,UAAU;EACV,oBAAoB;EACpB,cAAc;EACd,oBAAoB;EACpB,aAAa,EAAE,iBAAiB;EACnB;EACC;EACd,aAAa;EACb,oBAAoB,aAAa;CAClC,CAAA;AAEL"}
1
+ {"version":3,"file":"Search.mjs","names":["Route"],"sources":["../../../src/components/Search/Search.tsx"],"sourcesContent":["import SearchMui from '@mui/icons-material/Search';\nimport type { AutocompleteRenderGroupParams } from '@mui/material/Autocomplete';\nimport ListSubheader from '@mui/material/ListSubheader';\nimport { debounce } from 'lodash-es';\nimport React, { useCallback, useEffect, useMemo, useRef, useState } from 'react';\nimport { useTranslation } from 'react-i18next';\nimport { useNavigate } from 'react-router';\n\nimport { useConfig, useSearch } from '../../';\nimport { Route } from '../../utils';\nimport AutoComplete from './AutoComplete';\nimport SearchItem, { ORIGIN_ICONS } from './SearchItem';\nimport { StyledInputAdornment, StyledTextField } from './styles';\nimport type { SearchOrigin } from './utils';\nimport { normalizeSearchOption, sortByOrigin } from './utils';\n\nconst CONSTANTS = {\n API_DELAY: 300,\n ABORT_ERROR: 'AbortError',\n};\n\nconst Search: React.FC = () => {\n const { t } = useTranslation();\n const navigate = useNavigate();\n const { searchResults, isLoading, isError, doSearch, resetSearch } = useSearch();\n const { configOptions } = useConfig();\n const groupByOrigin = configOptions?.showUplinks === true;\n const suggestions = useMemo(\n () => (groupByOrigin && searchResults ? sortByOrigin(searchResults) : searchResults),\n [groupByOrigin, searchResults]\n );\n\n const abortControllerRef = useRef<AbortController | null>(null);\n\n const cancelAllSearchRequests = useCallback(() => {\n if (abortControllerRef.current) {\n abortControllerRef.current.abort();\n abortControllerRef.current = null;\n }\n }, []);\n\n const handleOnBlur = useCallback(\n (event: React.SyntheticEvent) => {\n event.stopPropagation();\n cancelAllSearchRequests();\n },\n [cancelAllSearchRequests]\n );\n\n const handleClickSearch = useCallback(\n (event: React.SyntheticEvent, value: any, reason: string): void => {\n event.stopPropagation();\n if (reason === 'selectOption') {\n const { name } = normalizeSearchOption(value);\n if (name) {\n navigate(`${Route.DETAIL}${name}`);\n }\n }\n },\n [navigate]\n );\n\n // Use a ref to always access the latest doSearch without re-creating the debounced function\n const doSearchRef = useRef(doSearch);\n doSearchRef.current = doSearch;\n\n // shows the dropdown as loading during the debounce window; without it the\n // immediate reset below reads as \"no results found\" on every keystroke\n const [isDebouncing, setIsDebouncing] = useState(false);\n\n /**\n * Stable fetch function that reads the latest doSearch from a ref,\n * avoiding dependency changes that would break the debounce.\n */\n const handleFetchPackages = useCallback(\n async ({ value }: { value: string }) => {\n setIsDebouncing(false);\n if (value?.trim() !== '') {\n // Abort any previous pending request before starting a new one\n cancelAllSearchRequests();\n\n // Create a new controller for the current request\n const controller = new AbortController();\n abortControllerRef.current = controller;\n\n try {\n await doSearchRef.current?.({\n text: value,\n signal: controller.signal,\n });\n } catch (err: any) {\n if (err.name === CONSTANTS.ABORT_ERROR) {\n console.warn('Search request aborted');\n } else {\n console.error('Search error:', err);\n }\n }\n }\n },\n [cancelAllSearchRequests]\n );\n\n // Memoize the debounced function so a single instance is reused across renders,\n // ensuring the debounce timer works correctly instead of creating a new timer per render.\n const debouncedFetch = useMemo(\n () => debounce(handleFetchPackages, CONSTANTS.API_DELAY),\n [handleFetchPackages]\n );\n\n // clear the previous query's results right away so the dropdown never lists\n // stale suggestions under the new input while the debounce timer runs\n const handleSuggestionsFetch = useCallback(\n ({ value }: { value: string }) => {\n resetSearch?.();\n if (value?.trim() !== '') {\n setIsDebouncing(true);\n }\n debouncedFetch({ value });\n },\n [resetSearch, debouncedFetch]\n );\n\n useEffect(() => {\n return () => {\n debouncedFetch.cancel?.();\n cancelAllSearchRequests();\n };\n }, [debouncedFetch, cancelAllSearchRequests]);\n\n const renderOption = (props, option) => {\n const { key, ...otherProps } = props;\n const { name, version, description, isPrivate, isCached, isRemote } =\n normalizeSearchOption(option);\n return (\n <SearchItem\n key={key}\n {...otherProps}\n description={description}\n isCached={isCached}\n isPrivate={isPrivate}\n isRemote={isRemote}\n name={name}\n version={version}\n />\n );\n };\n\n const renderInput = (params) => {\n return (\n <StyledTextField\n {...params}\n InputProps={{\n ...params.InputProps,\n startAdornment: (\n <StyledInputAdornment position=\"start\">\n <SearchMui />\n </StyledInputAdornment>\n ),\n }}\n label=\"\"\n placeholder={t('search.packages')}\n variant=\"standard\"\n />\n );\n };\n\n const getOptionGroup = (option) => normalizeSearchOption(option).origin ?? '';\n\n const renderGroup = ({ key, group, children }: AutocompleteRenderGroupParams) => {\n if (!group) {\n return <React.Fragment key={key}>{children}</React.Fragment>;\n }\n const OriginIcon = ORIGIN_ICONS[group as SearchOrigin];\n return (\n <li key={key}>\n {/* a div: the default <li> would nest a list item inside the group's <li> */}\n <ListSubheader\n component=\"div\"\n data-testid={`search-group-${group}`}\n sx={{ display: 'flex', alignItems: 'center', gap: 1, lineHeight: '36px' }}\n >\n {OriginIcon && <OriginIcon fontSize=\"small\" />}\n {t(`search.group.${group}`, { count: React.Children.count(children) })}\n </ListSubheader>\n <ul style={{ padding: 0 }}>{children}</ul>\n </li>\n );\n };\n\n const getOptionLabel = (option) => {\n return normalizeSearchOption(option).name;\n };\n\n return (\n <AutoComplete\n getOptionLabel={getOptionLabel}\n groupBy={groupByOrigin ? getOptionGroup : undefined}\n hasError={isError}\n onCleanSuggestions={handleOnBlur}\n onSelectItem={handleClickSearch}\n onSuggestionsFetch={handleSuggestionsFetch}\n placeholder={t('search.packages')}\n renderGroup={groupByOrigin ? renderGroup : undefined}\n renderInput={renderInput}\n renderOption={renderOption}\n suggestions={suggestions}\n suggestionsLoading={isLoading || isDebouncing}\n />\n );\n};\n\nexport default Search;\n"],"mappings":"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"}
@@ -8,11 +8,22 @@ type SearchItemProps = {
8
8
  isCached?: boolean;
9
9
  isRemote?: boolean;
10
10
  };
11
+ export declare const ORIGIN_ICONS: {
12
+ private: import("@mui/material/OverridableComponent").OverridableComponent<import("@mui/material").SvgIconTypeMap<{}, "svg">> & {
13
+ muiName: string;
14
+ };
15
+ cached: import("@mui/material/OverridableComponent").OverridableComponent<import("@mui/material").SvgIconTypeMap<{}, "svg">> & {
16
+ muiName: string;
17
+ };
18
+ remote: import("@mui/material/OverridableComponent").OverridableComponent<import("@mui/material").SvgIconTypeMap<{}, "svg">> & {
19
+ muiName: string;
20
+ };
21
+ };
11
22
  export declare const Description: import("@emotion/styled").StyledComponent<{
12
23
  theme?: import("@emotion/react").Theme;
13
24
  as?: React.ElementType;
14
25
  } & {
15
26
  theme?: Theme;
16
- }, React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement>, {}>;
27
+ }, React.DetailedHTMLProps<React.HTMLAttributes<HTMLSpanElement>, HTMLSpanElement>, {}>;
17
28
  declare const SearchItem: React.FC<SearchItemProps>;
18
29
  export default SearchItem;
@@ -8,92 +8,75 @@ let react = require("react");
8
8
  react = require_runtime.__toESM(react);
9
9
  let react_i18next = require("react-i18next");
10
10
  let react_jsx_runtime = require("react/jsx-runtime");
11
- let _mui_material_Stack = require("@mui/material/Stack");
12
- _mui_material_Stack = require_runtime.__toESM(_mui_material_Stack);
13
- let _mui_material_Chip = require("@mui/material/Chip");
14
- _mui_material_Chip = require_runtime.__toESM(_mui_material_Chip);
15
- let _mui_icons_material_Cached = require("@mui/icons-material/Cached");
16
- _mui_icons_material_Cached = require_runtime.__toESM(_mui_icons_material_Cached);
17
- let _mui_icons_material_Https = require("@mui/icons-material/Https");
18
- _mui_icons_material_Https = require_runtime.__toESM(_mui_icons_material_Https);
19
- let _mui_icons_material_SyncAlt = require("@mui/icons-material/SyncAlt");
20
- _mui_icons_material_SyncAlt = require_runtime.__toESM(_mui_icons_material_SyncAlt);
11
+ let _mui_icons_material_LockOutlined = require("@mui/icons-material/LockOutlined");
12
+ _mui_icons_material_LockOutlined = require_runtime.__toESM(_mui_icons_material_LockOutlined);
13
+ let _mui_icons_material_CloudOutlined = require("@mui/icons-material/CloudOutlined");
14
+ _mui_icons_material_CloudOutlined = require_runtime.__toESM(_mui_icons_material_CloudOutlined);
15
+ let _mui_icons_material_Inventory2Outlined = require("@mui/icons-material/Inventory2Outlined");
16
+ _mui_icons_material_Inventory2Outlined = require_runtime.__toESM(_mui_icons_material_Inventory2Outlined);
21
17
  //#region src/components/Search/SearchItem.tsx
22
- var Wrapper = _emotion_styled.default.div({
18
+ var ORIGIN_ICONS = {
19
+ [require_utils.SearchOrigin.PRIVATE]: _mui_icons_material_LockOutlined.default,
20
+ [require_utils.SearchOrigin.CACHED]: _mui_icons_material_Inventory2Outlined.default,
21
+ [require_utils.SearchOrigin.REMOTE]: _mui_icons_material_CloudOutlined.default
22
+ };
23
+ var Row = (0, _emotion_styled.default)("div")({
23
24
  display: "flex",
24
25
  alignItems: "center",
25
- width: "100%"
26
+ gap: 12,
27
+ width: "100%",
28
+ minWidth: 0
26
29
  });
27
- var Description = (0, _emotion_styled.default)("div")(({ theme }) => ({
28
- display: "none",
29
- color: theme.palette.greyLight2,
30
- lineHeight: "1.5rem",
31
- whiteSpace: "nowrap",
32
- textOverflow: "ellipsis",
33
- alignItems: "center",
34
- overflow: "hidden",
35
- paddingLeft: theme.spacing(),
36
- fontSize: theme.fontSize.ssm,
37
- [`@media (min-width: ${theme.breakPoints.medium}px)`]: {
38
- display: "block",
39
- width: "300px"
40
- },
41
- [`@media (min-width: ${theme.breakPoints.large}px)`]: {
42
- display: "block",
43
- width: "500px"
44
- },
45
- [`@media (min-width: 1440px)`]: {
46
- display: "block",
47
- width: "600px"
48
- }
49
- }));
50
- var NameGroup = _emotion_styled.default.span({
30
+ var Text = (0, _emotion_styled.default)("div")({
31
+ display: "flex",
32
+ flexDirection: "column",
33
+ flex: 1,
34
+ minWidth: 0
35
+ });
36
+ var TitleLine = (0, _emotion_styled.default)("div")({
51
37
  display: "flex",
52
- flex: "1"
38
+ alignItems: "baseline",
39
+ gap: 8
53
40
  });
54
41
  var Name = (0, _emotion_styled.default)("span")(({ theme }) => ({
55
- fontWeight: "700",
56
- fontSize: theme.fontSize.sm
42
+ fontWeight: 700,
43
+ fontSize: theme.fontSize.sm,
44
+ overflow: "hidden",
45
+ textOverflow: "ellipsis",
46
+ whiteSpace: "nowrap"
47
+ }));
48
+ var Version = (0, _emotion_styled.default)("span")(({ theme }) => ({
49
+ marginLeft: "auto",
50
+ flexShrink: 0,
51
+ fontSize: theme.fontSize.ssm,
52
+ color: theme.palette.text.secondary
53
+ }));
54
+ var Description = (0, _emotion_styled.default)("span")(({ theme }) => ({
55
+ color: theme.palette.text.secondary,
56
+ fontSize: theme.fontSize.ssm,
57
+ lineHeight: 1.5,
58
+ overflow: "hidden",
59
+ textOverflow: "ellipsis",
60
+ whiteSpace: "nowrap"
57
61
  }));
58
- var Version = (0, _emotion_styled.default)("span")(({ theme }) => ({ fontSize: theme.fontSize.ssm }));
59
62
  var SearchItem = ({ name, description, isPrivate = false, isRemote = false, isCached = false, version, ...props }) => {
60
63
  const { t } = (0, react_i18next.useTranslation)();
61
64
  const { configOptions } = require_AppConfigurationProvider.useConfig();
62
- const handleDelete = () => {};
63
- return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("li", {
65
+ const origin = isPrivate ? require_utils.SearchOrigin.PRIVATE : isCached ? require_utils.SearchOrigin.CACHED : isRemote ? require_utils.SearchOrigin.REMOTE : void 0;
66
+ const OriginIcon = configOptions?.showUplinks && origin ? ORIGIN_ICONS[origin] : void 0;
67
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("li", {
64
68
  ...props,
65
- style: { flexDirection: "column" },
66
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)(Wrapper, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)(NameGroup, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(Name, { children: name }), description && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Description, { children: require_utils.cleanDescription(description) })] }), version && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Version, { children: version })] }), configOptions?.showUplinks && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Wrapper, { children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(_mui_material_Stack.default, {
67
- direction: "row",
68
- spacing: 1,
69
- children: [
70
- isPrivate && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_mui_material_Chip.default, {
71
- color: "primary",
72
- deleteIcon: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_mui_icons_material_Https.default, {}),
73
- label: t("search.isPrivate"),
74
- onDelete: handleDelete,
75
- size: "small"
76
- }),
77
- isRemote && !isPrivate && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_mui_material_Chip.default, {
78
- deleteIcon: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_mui_icons_material_SyncAlt.default, {}),
79
- label: t("search.isRemote"),
80
- onDelete: handleDelete,
81
- size: "small",
82
- variant: "outlined"
83
- }),
84
- isCached && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_mui_material_Chip.default, {
85
- deleteIcon: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_mui_icons_material_Cached.default, {}),
86
- label: t("search.isCached"),
87
- onDelete: handleDelete,
88
- size: "small",
89
- variant: "outlined"
90
- })
91
- ]
92
- }) })]
69
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(Row, { children: [OriginIcon && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(OriginIcon, {
70
+ color: origin === require_utils.SearchOrigin.PRIVATE ? "primary" : "action",
71
+ "data-testid": `search-origin-${origin}`,
72
+ fontSize: "small",
73
+ titleAccess: t(`search.origin.${origin}`)
74
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(Text, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)(TitleLine, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(Name, { children: name }), version && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Version, { children: version })] }), description && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Description, { children: require_utils.cleanDescription(description) })] })] })
93
75
  });
94
76
  };
95
77
  //#endregion
96
78
  exports.Description = Description;
79
+ exports.ORIGIN_ICONS = ORIGIN_ICONS;
97
80
  exports.default = SearchItem;
98
81
 
99
82
  //# sourceMappingURL=SearchItem.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"SearchItem.js","names":["styled","useTranslation","useConfig","cleanDescription","Stack","Chip","HttpsIcon","SyncAlt","Cached"],"sources":["../../../src/components/Search/SearchItem.tsx"],"sourcesContent":["import styled from '@emotion/styled';\nimport Cached from '@mui/icons-material/Cached';\nimport HttpsIcon from '@mui/icons-material/Https';\nimport SyncAlt from '@mui/icons-material/SyncAlt';\nimport type { Theme } from '@mui/material';\nimport Chip from '@mui/material/Chip';\nimport Stack from '@mui/material/Stack';\nimport React from 'react';\nimport { useTranslation } from 'react-i18next';\n\nimport { useConfig } from '../../';\nimport { cleanDescription } from './utils';\n\ntype SearchItemProps = {\n name: string;\n version?: string;\n description?: string;\n isPrivate?: boolean;\n isCached?: boolean;\n isRemote?: boolean;\n};\n\nconst Wrapper = styled.div({\n display: 'flex',\n alignItems: 'center',\n width: '100%',\n});\n\nexport const Description = styled('div')<{ theme?: Theme }>(({ theme }) => ({\n display: 'none',\n color: theme.palette.greyLight2,\n lineHeight: '1.5rem',\n whiteSpace: 'nowrap',\n textOverflow: 'ellipsis',\n alignItems: 'center',\n overflow: 'hidden',\n paddingLeft: theme.spacing(),\n fontSize: theme.fontSize.ssm,\n [`@media (min-width: ${theme.breakPoints.medium}px)`]: {\n display: 'block',\n width: '300px',\n },\n [`@media (min-width: ${theme.breakPoints.large}px)`]: {\n display: 'block',\n width: '500px',\n },\n [`@media (min-width: 1440px)`]: {\n display: 'block',\n width: '600px',\n },\n}));\n\nconst NameGroup = styled.span({\n display: 'flex',\n flex: '1',\n});\n\nconst Name = styled('span')<{ theme?: Theme }>(({ theme }) => ({\n fontWeight: '700',\n fontSize: theme.fontSize.sm,\n}));\n\nconst Version = styled('span')<{ theme?: Theme }>(({ theme }) => ({\n fontSize: theme.fontSize.ssm,\n}));\n\nconst SearchItem: React.FC<SearchItemProps> = ({\n name,\n description,\n isPrivate = false,\n isRemote = false,\n isCached = false,\n version,\n ...props\n}) => {\n const { t } = useTranslation();\n const { configOptions } = useConfig();\n const handleDelete = () => {\n // no action assigned by default\n };\n return (\n <li {...props} style={{ flexDirection: 'column' }}>\n <Wrapper>\n <NameGroup>\n <Name>{name}</Name>\n {description && <Description>{cleanDescription(description)}</Description>}\n </NameGroup>\n {version && <Version>{version}</Version>}\n </Wrapper>\n {configOptions?.showUplinks && (\n <Wrapper>\n <Stack direction=\"row\" spacing={1}>\n {isPrivate && (\n <Chip\n color=\"primary\"\n deleteIcon={<HttpsIcon />}\n label={t('search.isPrivate')}\n onDelete={handleDelete}\n size=\"small\"\n />\n )}\n {isRemote && !isPrivate && (\n <Chip\n deleteIcon={<SyncAlt />}\n label={t('search.isRemote')}\n onDelete={handleDelete}\n size=\"small\"\n variant=\"outlined\"\n />\n )}\n {isCached && (\n <Chip\n deleteIcon={<Cached />}\n label={t('search.isCached')}\n onDelete={handleDelete}\n size=\"small\"\n variant=\"outlined\"\n />\n )}\n </Stack>\n </Wrapper>\n )}\n </li>\n );\n};\n\nexport default SearchItem;\n"],"mappings":"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"}
1
+ {"version":3,"file":"SearchItem.js","names":["SearchOrigin","LockOutlined","Inventory2Outlined","CloudOutlined","styled","useTranslation","useConfig","cleanDescription"],"sources":["../../../src/components/Search/SearchItem.tsx"],"sourcesContent":["import styled from '@emotion/styled';\nimport CloudOutlined from '@mui/icons-material/CloudOutlined';\nimport Inventory2Outlined from '@mui/icons-material/Inventory2Outlined';\nimport LockOutlined from '@mui/icons-material/LockOutlined';\nimport type { Theme } from '@mui/material';\nimport React from 'react';\nimport { useTranslation } from 'react-i18next';\n\nimport { useConfig } from '../../';\nimport { SearchOrigin, cleanDescription } from './utils';\n\ntype SearchItemProps = {\n name: string;\n version?: string;\n description?: string;\n isPrivate?: boolean;\n isCached?: boolean;\n isRemote?: boolean;\n};\n\nexport const ORIGIN_ICONS = {\n [SearchOrigin.PRIVATE]: LockOutlined,\n [SearchOrigin.CACHED]: Inventory2Outlined,\n [SearchOrigin.REMOTE]: CloudOutlined,\n};\n\nconst Row = styled('div')({\n display: 'flex',\n alignItems: 'center',\n gap: 12,\n width: '100%',\n minWidth: 0,\n});\n\nconst Text = styled('div')({\n display: 'flex',\n flexDirection: 'column',\n flex: 1,\n minWidth: 0,\n});\n\nconst TitleLine = styled('div')({\n display: 'flex',\n alignItems: 'baseline',\n gap: 8,\n});\n\nconst Name = styled('span')<{ theme?: Theme }>(({ theme }) => ({\n fontWeight: 700,\n fontSize: theme.fontSize.sm,\n overflow: 'hidden',\n textOverflow: 'ellipsis',\n whiteSpace: 'nowrap',\n}));\n\nconst Version = styled('span')<{ theme?: Theme }>(({ theme }) => ({\n marginLeft: 'auto',\n flexShrink: 0,\n fontSize: theme.fontSize.ssm,\n color: theme.palette.text.secondary,\n}));\n\nexport const Description = styled('span')<{ theme?: Theme }>(({ theme }) => ({\n color: theme.palette.text.secondary,\n fontSize: theme.fontSize.ssm,\n lineHeight: 1.5,\n overflow: 'hidden',\n textOverflow: 'ellipsis',\n whiteSpace: 'nowrap',\n}));\n\nconst SearchItem: React.FC<SearchItemProps> = ({\n name,\n description,\n isPrivate = false,\n isRemote = false,\n isCached = false,\n version,\n ...props\n}) => {\n const { t } = useTranslation();\n const { configOptions } = useConfig();\n const origin = isPrivate\n ? SearchOrigin.PRIVATE\n : isCached\n ? SearchOrigin.CACHED\n : isRemote\n ? SearchOrigin.REMOTE\n : undefined;\n const OriginIcon = configOptions?.showUplinks && origin ? ORIGIN_ICONS[origin] : undefined;\n\n return (\n <li {...props}>\n <Row>\n {OriginIcon && (\n <OriginIcon\n color={origin === SearchOrigin.PRIVATE ? 'primary' : 'action'}\n data-testid={`search-origin-${origin}`}\n fontSize=\"small\"\n titleAccess={t(`search.origin.${origin}`)}\n />\n )}\n <Text>\n <TitleLine>\n <Name>{name}</Name>\n {version && <Version>{version}</Version>}\n </TitleLine>\n {description && <Description>{cleanDescription(description)}</Description>}\n </Text>\n </Row>\n </li>\n );\n};\n\nexport default SearchItem;\n"],"mappings":";;;;;;;;;;;;;;;;;AAoBA,IAAa,eAAe;EACzBA,cAAAA,aAAa,UAAUC,iCAAAA;EACvBD,cAAAA,aAAa,SAASE,uCAAAA;EACtBF,cAAAA,aAAa,SAASG,kCAAAA;AACzB;AAEA,IAAM,OAAA,GAAMC,gBAAAA,QAAAA,CAAO,KAAK,CAAC,CAAC;CACxB,SAAS;CACT,YAAY;CACZ,KAAK;CACL,OAAO;CACP,UAAU;AACZ,CAAC;AAED,IAAM,QAAA,GAAOA,gBAAAA,QAAAA,CAAO,KAAK,CAAC,CAAC;CACzB,SAAS;CACT,eAAe;CACf,MAAM;CACN,UAAU;AACZ,CAAC;AAED,IAAM,aAAA,GAAYA,gBAAAA,QAAAA,CAAO,KAAK,CAAC,CAAC;CAC9B,SAAS;CACT,YAAY;CACZ,KAAK;AACP,CAAC;AAED,IAAM,QAAA,GAAOA,gBAAAA,QAAAA,CAAO,MAAM,CAAC,EAAqB,EAAE,aAAa;CAC7D,YAAY;CACZ,UAAU,MAAM,SAAS;CACzB,UAAU;CACV,cAAc;CACd,YAAY;AACd,EAAE;AAEF,IAAM,WAAA,GAAUA,gBAAAA,QAAAA,CAAO,MAAM,CAAC,EAAqB,EAAE,aAAa;CAChE,YAAY;CACZ,YAAY;CACZ,UAAU,MAAM,SAAS;CACzB,OAAO,MAAM,QAAQ,KAAK;AAC5B,EAAE;AAEF,IAAa,eAAA,GAAcA,gBAAAA,QAAAA,CAAO,MAAM,CAAC,EAAqB,EAAE,aAAa;CAC3E,OAAO,MAAM,QAAQ,KAAK;CAC1B,UAAU,MAAM,SAAS;CACzB,YAAY;CACZ,UAAU;CACV,cAAc;CACd,YAAY;AACd,EAAE;AAEF,IAAM,cAAyC,EAC7C,MACA,aACA,YAAY,OACZ,WAAW,OACX,WAAW,OACX,SACA,GAAG,YACC;CACJ,MAAM,EAAE,OAAA,GAAMC,cAAAA,eAAAA,CAAe;CAC7B,MAAM,EAAE,kBAAkBC,iCAAAA,UAAU;CACpC,MAAM,SAAS,YACXN,cAAAA,aAAa,UACb,WACEA,cAAAA,aAAa,SACb,WACEA,cAAAA,aAAa,SACb,KAAA;CACR,MAAM,aAAa,eAAe,eAAe,SAAS,aAAa,UAAU,KAAA;CAEjF,OACE,iBAAA,GAAA,kBAAA,IAAA,CAAC,MAAD;EAAI,GAAI;EACN,UAAA,iBAAA,GAAA,kBAAA,KAAA,CAAC,KAAD,EAAA,UAAA,CACG,cACC,iBAAA,GAAA,kBAAA,IAAA,CAAC,YAAD;GACE,OAAO,WAAWA,cAAAA,aAAa,UAAU,YAAY;GACrD,eAAa,iBAAiB;GAC9B,UAAS;GACT,aAAa,EAAE,iBAAiB,QAAQ;EACzC,CAAA,GAEH,iBAAA,GAAA,kBAAA,KAAA,CAAC,MAAD,EAAA,UAAA,CACE,iBAAA,GAAA,kBAAA,KAAA,CAAC,WAAD,EAAA,UAAA,CACE,iBAAA,GAAA,kBAAA,IAAA,CAAC,MAAD,EAAA,UAAO,KAAW,CAAA,GACjB,WAAW,iBAAA,GAAA,kBAAA,IAAA,CAAC,SAAD,EAAA,UAAU,QAAiB,CAAA,CAC9B,EAAA,CAAA,GACV,eAAe,iBAAA,GAAA,kBAAA,IAAA,CAAC,aAAD,EAAA,UAAcO,cAAAA,iBAAiB,WAAW,EAAe,CAAA,CACrE,EAAA,CAAA,CACH,EAAA,CAAA;CACH,CAAA;AAER"}