@verdaccio/ui-components 3.0.0-next-7.7 → 3.0.0-next-7.8

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 (300) hide show
  1. package/.eslintrc +1 -1
  2. package/CHANGELOG.md +6 -0
  3. package/build/Theme/theme.js +3 -3
  4. package/build/components/ActionBar/ActionBar.js +3 -1
  5. package/build/components/ActionBar/ActionBarAction.js +7 -6
  6. package/build/components/Author/Author.js +13 -42
  7. package/build/components/CopyClipboard/utils.js +3 -12
  8. package/build/components/Dependencies/Dependencies.js +12 -13
  9. package/build/components/Dependencies/DependencyBlock.js +5 -4
  10. package/build/components/Developers/DeveloperType.js +12 -0
  11. package/build/components/Developers/Developers.js +20 -22
  12. package/build/components/Developers/Title.js +5 -9
  13. package/build/components/Developers/index.js +4 -4
  14. package/build/components/Distribution/Dist.js +1 -1
  15. package/build/components/Distribution/styles.js +10 -23
  16. package/build/components/Engines/Engines.js +7 -1
  17. package/build/components/Engines/styles.js +6 -6
  18. package/build/components/FundButton/FundButton.js +7 -8
  19. package/build/components/HeaderInfoDialog/HeaderInfoDialog.js +2 -1
  20. package/build/components/Icons/DevsIcons/CommonJS.js +1 -12
  21. package/build/components/Icons/DevsIcons/ES6Module.js +2 -13
  22. package/build/components/Icons/DevsIcons/Git.js +1 -12
  23. package/build/components/Icons/DevsIcons/NodeJS.js +1 -12
  24. package/build/components/Icons/DevsIcons/TypeScript.js +1 -12
  25. package/build/components/Icons/FileBinary.js +11 -5
  26. package/build/components/Icons/Law.js +12 -6
  27. package/build/components/Icons/Managers/Npm.js +1 -12
  28. package/build/components/Icons/Managers/Pnpm.js +1 -12
  29. package/build/components/Icons/Managers/Yarn.js +1 -12
  30. package/build/components/Install/Install.js +23 -18
  31. package/build/components/Install/InstallListItem.js +19 -18
  32. package/build/components/Keywords/KeywordListItems.js +34 -0
  33. package/build/components/Keywords/Keywords.js +39 -0
  34. package/build/{sections/Header/RegistryInfoDialog → components/Keywords}/index.js +2 -2
  35. package/build/components/Link/Link.js +4 -16
  36. package/build/components/Link/index.js +1 -1
  37. package/build/components/LinkExternal/LinkExternal.js +32 -0
  38. package/build/components/LinkExternal/index.js +14 -0
  39. package/build/components/Loading/styles.js +3 -2
  40. package/build/components/LoginDialog/LoginDialog.js +12 -1
  41. package/build/components/LoginDialog/LoginDialogCloseButton.js +3 -2
  42. package/build/components/LoginDialog/LoginDialogForm.js +2 -14
  43. package/build/components/LoginDialog/LoginDialogFormError.js +3 -2
  44. package/build/components/Logo/Logo.js +13 -6
  45. package/build/components/Package/Package.js +43 -34
  46. package/build/components/Package/styles.js +46 -58
  47. package/build/components/Person/Person.js +48 -0
  48. package/build/components/Person/PersonTooltip.js +22 -0
  49. package/build/components/{Package/Tag → Person}/index.js +2 -2
  50. package/build/components/Person/utils.js +17 -0
  51. package/build/components/RawViewer/RawViewer.js +11 -5
  52. package/build/components/Readme/Readme.js +15 -6
  53. package/build/components/Readme/Readme.js.map +1 -1
  54. package/build/components/Readme/Readme.spec.js +19 -0
  55. package/build/components/Readme/Readme.spec.js.map +1 -1
  56. package/build/components/Readme/utils.js +2 -5
  57. package/build/components/RegistryInfoDialog/styles.js +9 -10
  58. package/build/components/Repository/Repository.js +19 -31
  59. package/build/components/Search/AutoComplete/styles.js +4 -41
  60. package/build/components/Search/Search.js +4 -2
  61. package/build/components/Search/SearchItem.js +51 -38
  62. package/build/components/Search/utils.js +23 -0
  63. package/build/components/SettingsMenu/SettingsMenu.js +35 -9
  64. package/build/components/SideBarTitle/SideBarTitle.js +16 -6
  65. package/build/components/UpLinks/UpLinks.js +35 -6
  66. package/build/components/UpLinks/UplinkLink.js +22 -0
  67. package/build/components/UpLinks/styles.js +5 -4
  68. package/build/components/Versions/HistoryList.js +8 -5
  69. package/build/components/Versions/TagList.js +8 -4
  70. package/build/components/Versions/Versions.js +30 -7
  71. package/build/index.js +27 -3
  72. package/build/providers/AppConfigurationProvider/AppConfigurationProvider.js +1 -0
  73. package/build/providers/PersistenceSettingProvider/PersistenceSettingProvider.js +1 -0
  74. package/build/sections/Detail/Detail.js +6 -2
  75. package/build/sections/Detail/Tabs.js +4 -3
  76. package/build/sections/Footer/Footer.js +17 -8
  77. package/build/sections/Footer/styles.js +13 -10
  78. package/build/sections/Header/HeaderLeft.js +14 -17
  79. package/build/sections/Header/HeaderMenu.js +1 -1
  80. package/build/sections/Header/HeaderRight.js +12 -3
  81. package/build/sections/Header/HeaderSettingsDialog.js +2 -2
  82. package/build/sections/Header/styles.js +43 -82
  83. package/build/sections/SideBar/Sidebar.js +10 -15
  84. package/build/src/Theme/ThemeProvider.test.d.ts +1 -0
  85. package/build/src/components/Author/Author.d.ts +0 -5
  86. package/build/src/components/CopyClipboard/CopyToClipBoard.test.d.ts +1 -0
  87. package/build/src/components/Dependencies/Dependencies.d.ts +0 -1
  88. package/build/src/components/Developers/DeveloperType.d.ts +4 -0
  89. package/build/src/components/Developers/Developers.d.ts +1 -4
  90. package/build/src/components/Developers/Title.d.ts +1 -4
  91. package/build/src/components/Developers/index.d.ts +2 -1
  92. package/build/src/components/Distribution/styles.d.ts +0 -1
  93. package/build/src/components/ErrorBoundary/ErrorBoundary.test.d.ts +1 -0
  94. package/build/src/components/HeaderInfoDialog/HeaderInfoDialog.test.d.ts +1 -0
  95. package/build/src/components/Heading/Heading.test.d.ts +1 -0
  96. package/build/src/components/Icons/Icons.test.d.ts +1 -0
  97. package/build/src/components/Install/InstallListItem.d.ts +1 -1
  98. package/build/src/components/Keywords/KeywordListItems.d.ts +5 -0
  99. package/build/src/components/Keywords/Keywords.d.ts +6 -0
  100. package/build/src/components/Keywords/Keywords.stories.d.ts +5 -0
  101. package/build/src/components/Keywords/Keywords.test.d.ts +1 -0
  102. package/build/src/components/Keywords/index.d.ts +1 -0
  103. package/build/src/components/Link/Link.d.ts +0 -3
  104. package/build/src/components/Link/Link.test.d.ts +1 -0
  105. package/build/src/components/Link/index.d.ts +1 -1
  106. package/build/src/components/LinkExternal/LinkExternal.d.ts +3 -0
  107. package/build/src/components/LinkExternal/LinkExternal.test.d.ts +1 -0
  108. package/build/src/components/LinkExternal/index.d.ts +1 -0
  109. package/build/src/components/Logo/Logo.d.ts +1 -0
  110. package/build/src/components/Logo/Logo.stories.d.ts +5 -0
  111. package/build/src/components/Package/Package.d.ts +1 -1
  112. package/build/src/components/Package/styles.d.ts +0 -8
  113. package/build/src/components/Person/Person.d.ts +9 -0
  114. package/build/src/components/Person/Person.test.d.ts +1 -0
  115. package/build/src/components/Person/PersonTooltip.d.ts +6 -0
  116. package/build/src/components/Person/index.d.ts +1 -0
  117. package/build/src/components/Person/utils.d.ts +3 -0
  118. package/build/src/components/Readme/Readme.d.ts +0 -1
  119. package/build/src/components/Search/AutoComplete/styles.d.ts +0 -8
  120. package/build/src/components/Search/utils.d.ts +1 -0
  121. package/build/src/components/SettingsMenu/SettingsMenu.d.ts +2 -2
  122. package/build/src/components/SettingsMenu/SettingsMenu.test.d.ts +1 -0
  123. package/build/src/components/UpLinks/UplinkLink.d.ts +6 -0
  124. package/build/src/components/Versions/Versions.d.ts +1 -0
  125. package/build/src/index.d.ts +4 -1
  126. package/build/src/sections/Detail/Tabs.d.ts +1 -0
  127. package/build/src/sections/Header/styles.d.ts +0 -7
  128. package/build/src/store/models/routes.d.ts +8 -0
  129. package/build/src/store/models/utils.d.ts +1 -0
  130. package/build/src/types/packageMeta.d.ts +7 -5
  131. package/build/src/utils/routes.d.ts +1 -0
  132. package/build/src/utils/utils.d.ts +1 -0
  133. package/build/store/models/configuration.js +2 -1
  134. package/build/store/models/login.js +4 -2
  135. package/build/store/models/manifest.js +5 -3
  136. package/build/store/models/packages.js +4 -2
  137. package/build/store/models/routes.js +18 -0
  138. package/build/store/models/search.js +4 -2
  139. package/build/store/models/utils.js +10 -0
  140. package/build/utils/routes.js +1 -0
  141. package/build/utils/utils.js +20 -1
  142. package/package.json +2 -2
  143. package/src/AppTest/AppRoute.test.tsx +65 -0
  144. package/src/Theme/ThemeProvider.test.tsx +27 -0
  145. package/src/Theme/theme.ts +3 -3
  146. package/src/components/ActionBar/ActionBar.test.tsx +36 -15
  147. package/src/components/ActionBar/ActionBar.tsx +1 -1
  148. package/src/components/ActionBar/ActionBarAction.tsx +8 -5
  149. package/src/components/Author/Author.test.tsx +7 -1
  150. package/src/components/Author/Author.tsx +3 -41
  151. package/src/components/CopyClipboard/CopyToClipBoard.test.tsx +23 -0
  152. package/src/components/CopyClipboard/utils.ts +2 -13
  153. package/src/components/Dependencies/Dependencies.tsx +9 -9
  154. package/src/components/Dependencies/DependencyBlock.tsx +2 -1
  155. package/src/components/Developers/DeveloperType.tsx +4 -0
  156. package/src/components/Developers/Developers.test.tsx +37 -10
  157. package/src/components/Developers/Developers.tsx +13 -13
  158. package/src/components/Developers/Title.tsx +1 -5
  159. package/src/components/Developers/index.ts +2 -1
  160. package/src/components/Distribution/Dist.test.tsx +1 -1
  161. package/src/components/Distribution/Dist.tsx +2 -4
  162. package/src/components/Distribution/styles.ts +0 -6
  163. package/src/components/Engines/Engines.tsx +6 -2
  164. package/src/components/Engines/styles.ts +1 -1
  165. package/src/components/ErrorBoundary/ErrorBoundary.test.tsx +39 -0
  166. package/src/components/FundButton/FundButton.tsx +5 -5
  167. package/src/components/HeaderInfoDialog/HeaderInfoDialog.test.tsx +51 -0
  168. package/src/components/HeaderInfoDialog/HeaderInfoDialog.tsx +2 -2
  169. package/src/components/Heading/Heading.test.tsx +20 -0
  170. package/src/components/Icons/DevsIcons/CommonJS.tsx +1 -7
  171. package/src/components/Icons/DevsIcons/ES6Module.tsx +2 -8
  172. package/src/components/Icons/DevsIcons/Git.tsx +1 -7
  173. package/src/components/Icons/DevsIcons/NodeJS.tsx +1 -7
  174. package/src/components/Icons/DevsIcons/TypeScript.tsx +1 -7
  175. package/src/components/Icons/FileBinary.tsx +2 -1
  176. package/src/components/Icons/Icons.stories.tsx +21 -5
  177. package/src/components/Icons/Icons.test.tsx +70 -0
  178. package/src/components/Icons/Law.tsx +2 -1
  179. package/src/components/Icons/Managers/Npm.tsx +1 -7
  180. package/src/components/Icons/Managers/Pnpm.tsx +1 -7
  181. package/src/components/Icons/Managers/Yarn.tsx +1 -7
  182. package/src/components/Install/Install.test.tsx +54 -13
  183. package/src/components/Install/Install.tsx +12 -11
  184. package/src/components/Install/InstallListItem.tsx +12 -11
  185. package/src/components/Keywords/KeywordListItems.tsx +22 -0
  186. package/src/components/Keywords/Keywords.stories.tsx +19 -0
  187. package/src/components/Keywords/Keywords.test.tsx +57 -0
  188. package/src/components/Keywords/Keywords.tsx +35 -0
  189. package/src/components/Keywords/index.ts +1 -0
  190. package/src/components/Link/Link.test.tsx +25 -0
  191. package/src/components/Link/Link.tsx +4 -18
  192. package/src/components/Link/index.ts +1 -1
  193. package/src/components/LinkExternal/LinkExternal.test.tsx +18 -0
  194. package/src/components/LinkExternal/LinkExternal.tsx +22 -0
  195. package/src/components/LinkExternal/index.ts +1 -0
  196. package/src/components/Loading/Loading.test.tsx +8 -5
  197. package/src/components/Loading/styles.ts +1 -0
  198. package/src/components/LoginDialog/LoginDialog.test.tsx +1 -1
  199. package/src/components/LoginDialog/LoginDialog.tsx +10 -1
  200. package/src/components/LoginDialog/LoginDialogCloseButton.tsx +1 -0
  201. package/src/components/LoginDialog/LoginDialogForm.tsx +0 -2
  202. package/src/components/LoginDialog/LoginDialogFormError.tsx +1 -1
  203. package/src/components/Logo/Logo.stories.tsx +16 -0
  204. package/src/components/Logo/Logo.test.tsx +8 -1
  205. package/src/components/Logo/Logo.tsx +19 -3
  206. package/src/components/Package/Package.test.tsx +47 -14
  207. package/src/components/Package/Package.tsx +41 -44
  208. package/src/components/Package/styles.ts +7 -17
  209. package/src/components/PackageList/Packagelist.test.tsx +1 -0
  210. package/src/components/Person/Person.test.tsx +50 -0
  211. package/src/components/Person/Person.tsx +45 -0
  212. package/src/components/Person/PersonTooltip.tsx +26 -0
  213. package/src/components/Person/index.ts +1 -0
  214. package/src/components/Person/utils.ts +20 -0
  215. package/src/components/RawViewer/RawViewer.tsx +8 -4
  216. package/src/components/Readme/Readme.spec.tsx +17 -0
  217. package/src/components/Readme/Readme.tsx +10 -5
  218. package/src/components/Readme/utils.ts +2 -5
  219. package/src/components/RegistryInfoDialog/styles.ts +5 -4
  220. package/src/components/Repository/Repository.tsx +9 -14
  221. package/src/components/Search/AutoComplete/styles.ts +7 -0
  222. package/src/components/Search/Search.test.tsx +36 -9
  223. package/src/components/Search/Search.tsx +4 -2
  224. package/src/components/Search/SearchItem.tsx +19 -8
  225. package/src/components/Search/utils.ts +17 -0
  226. package/src/components/SettingsMenu/SettingsMenu.test.tsx +41 -0
  227. package/src/components/SettingsMenu/SettingsMenu.tsx +48 -10
  228. package/src/components/SideBarTitle/SideBarTitle.tsx +19 -3
  229. package/src/components/UpLinks/UpLinks.test.tsx +7 -0
  230. package/src/components/UpLinks/UpLinks.tsx +38 -15
  231. package/src/components/UpLinks/UplinkLink.tsx +20 -0
  232. package/src/components/UpLinks/styles.ts +1 -0
  233. package/src/components/Versions/HistoryList.tsx +9 -4
  234. package/src/components/Versions/TagList.tsx +4 -3
  235. package/src/components/Versions/Versions.test.tsx +2 -0
  236. package/src/components/Versions/Versions.tsx +57 -32
  237. package/src/index.ts +4 -1
  238. package/src/providers/AppConfigurationProvider/AppConfigurationProvider.tsx +1 -0
  239. package/src/providers/PersistenceSettingProvider/PersistenceSettingProvider.tsx +2 -0
  240. package/src/providers/VersionProvider/VersionProvider.test.tsx +3 -3
  241. package/src/sections/Detail/Detail.test.tsx +8 -1
  242. package/src/sections/Detail/Detail.tsx +11 -4
  243. package/src/sections/Detail/Tabs.tsx +5 -2
  244. package/src/sections/Footer/Footer.tsx +15 -4
  245. package/src/sections/Footer/styles.ts +4 -0
  246. package/src/sections/Header/Header.test.tsx +12 -10
  247. package/src/sections/Header/HeaderLeft.tsx +19 -11
  248. package/src/sections/Header/HeaderMenu.tsx +1 -1
  249. package/src/sections/Header/HeaderRight.tsx +14 -3
  250. package/src/sections/Header/HeaderSettingsDialog.tsx +1 -1
  251. package/src/sections/Header/RegistryInfoContent/RegistryInfoContent.test.tsx +1 -1
  252. package/src/sections/Header/styles.ts +4 -16
  253. package/src/sections/Home/Home.test.tsx +12 -4
  254. package/src/sections/SideBar/Sidebar.test.tsx +20 -13
  255. package/src/sections/SideBar/Sidebar.tsx +5 -9
  256. package/src/store/api.test.ts +16 -0
  257. package/src/store/models/configuration.ts +2 -1
  258. package/src/store/models/login.ts +10 -12
  259. package/src/store/models/manifest.ts +6 -5
  260. package/src/store/models/packages.ts +4 -5
  261. package/src/store/models/routes.ts +10 -0
  262. package/src/store/models/search.ts +4 -2
  263. package/src/store/models/utils.ts +3 -0
  264. package/src/types/packageMeta.ts +7 -5
  265. package/src/utils/routes.ts +1 -0
  266. package/src/utils/utils.test.ts +34 -0
  267. package/src/utils/utils.ts +20 -5
  268. package/tsconfig.json +1 -1
  269. package/build/components/Developers/styles.js +0 -65
  270. package/build/components/Distribution/utils.js +0 -25
  271. package/build/components/Distribution/utilts.spec.js +0 -18
  272. package/build/components/Package/Tag/Tag.js +0 -14
  273. package/build/components/Package/Tag/styles.js +0 -24
  274. package/build/sections/Header/RegistryInfoDialog/RegistryInfoDialog.js +0 -36
  275. package/build/sections/Header/RegistryInfoDialog/styles.js +0 -46
  276. package/build/sections/Header/RegistryInfoDialog/types.js +0 -6
  277. package/build/src/components/Developers/styles.d.ts +0 -11
  278. package/build/src/components/Distribution/utils.d.ts +0 -7
  279. package/build/src/components/Package/Tag/Tag.d.ts +0 -6
  280. package/build/src/components/Package/Tag/index.d.ts +0 -1
  281. package/build/src/components/Package/Tag/styles.d.ts +0 -5
  282. package/build/src/sections/Header/RegistryInfoDialog/RegistryInfoDialog.d.ts +0 -4
  283. package/build/src/sections/Header/RegistryInfoDialog/index.d.ts +0 -1
  284. package/build/src/sections/Header/RegistryInfoDialog/styles.d.ts +0 -13
  285. package/build/src/sections/Header/RegistryInfoDialog/types.d.ts +0 -7
  286. package/src/components/Developers/styles.ts +0 -31
  287. package/src/components/Distribution/utils.ts +0 -32
  288. package/src/components/Distribution/utilts.spec.ts +0 -17
  289. package/src/components/Package/Tag/Tag.test.tsx +0 -15
  290. package/src/components/Package/Tag/Tag.tsx +0 -11
  291. package/src/components/Package/Tag/index.ts +0 -1
  292. package/src/components/Package/Tag/styles.ts +0 -11
  293. package/src/components/Search/AutoComplete/styles.tsx +0 -42
  294. package/src/sections/Header/RegistryInfoDialog/RegistryInfoDialog.tsx +0 -31
  295. package/src/sections/Header/RegistryInfoDialog/index.ts +0 -1
  296. package/src/sections/Header/RegistryInfoDialog/styles.ts +0 -21
  297. package/src/sections/Header/RegistryInfoDialog/types.ts +0 -8
  298. /package/build/components/Icons/DevsIcons/{es6modules.svg → es6module.svg} +0 -0
  299. /package/build/src/{components/Package/Tag/Tag.test.d.ts → AppTest/AppRoute.test.d.ts} +0 -0
  300. /package/src/components/Icons/DevsIcons/{es6modules.svg → es6module.svg} +0 -0
@@ -3,20 +3,20 @@ import styled from '@emotion/styled';
3
3
  import BugReport from '@mui/icons-material/BugReport';
4
4
  import DownloadIcon from '@mui/icons-material/CloudDownload';
5
5
  import HomeIcon from '@mui/icons-material/Home';
6
- import { useTheme } from '@mui/material';
7
6
  import CircularProgress from '@mui/material/CircularProgress';
8
7
  import Grid from '@mui/material/Grid';
8
+ import List from '@mui/material/List';
9
9
  import ListItem from '@mui/material/ListItem';
10
10
  import Tooltip from '@mui/material/Tooltip';
11
11
  import React, { useCallback } from 'react';
12
12
  import { useTranslation } from 'react-i18next';
13
13
  import { useDispatch, useSelector } from 'react-redux';
14
14
 
15
- import { Dispatch, Link, RootState, Theme } from '../../';
15
+ import { Dispatch, Link, LinkExternal, RootState, Theme } from '../../';
16
16
  import { FileBinary, Law, Time, Version } from '../../components/Icons';
17
17
  import { Author as PackageAuthor, PackageMetaInterface } from '../../types/packageMeta';
18
- import { url, utils } from '../../utils';
19
- import Tag from './Tag';
18
+ import { Route, url, utils } from '../../utils';
19
+ import KeywordListItems from '../Keywords/KeywordListItems';
20
20
  import {
21
21
  Author,
22
22
  Avatar,
@@ -28,7 +28,6 @@ import {
28
28
  PackageListItemText,
29
29
  PackageTitle,
30
30
  Published,
31
- TagContainer,
32
31
  Wrapper,
33
32
  WrapperLink,
34
33
  } from './styles';
@@ -47,7 +46,7 @@ export interface PackageInterface {
47
46
  time?: number | string;
48
47
  author: PackageAuthor;
49
48
  description?: string;
50
- keywords?: string[];
49
+ keywords?: PackageMetaInterface['latest']['keywords'];
51
50
  license?: PackageMetaInterface['latest']['license'];
52
51
  homepage?: string;
53
52
  bugs?: Bugs;
@@ -61,7 +60,7 @@ const Package: React.FC<PackageInterface> = ({
61
60
  description,
62
61
  dist,
63
62
  homepage,
64
- keywords = [],
63
+ keywords,
65
64
  license,
66
65
  name: packageName,
67
66
  time,
@@ -71,7 +70,6 @@ const Package: React.FC<PackageInterface> = ({
71
70
  const config = useSelector((state: RootState) => state.configuration.config);
72
71
  const dispatch = useDispatch<Dispatch>();
73
72
  const { t } = useTranslation();
74
- const theme = useTheme();
75
73
  const isLoading = useSelector((state: RootState) => state?.loading?.models.download);
76
74
 
77
75
  const handleDownload = useCallback(
@@ -94,21 +92,12 @@ const Package: React.FC<PackageInterface> = ({
94
92
  const renderAuthorInfo = (): React.ReactNode => {
95
93
  const name = utils.getAuthorName(authorName);
96
94
  return (
97
- <Author>
98
- <Avatar alt={name} src={authorAvatar} />
99
- <Details>
100
- <div
101
- style={{
102
- fontSize: '12px',
103
- fontWeight: theme?.fontWeight.semiBold,
104
- color:
105
- theme?.palette.mode === 'light' ? theme?.palette.greyLight2 : theme?.palette.white,
106
- }}
107
- >
108
- {name}
109
- </div>
110
- </Details>
111
- </Author>
95
+ <OverviewItem>
96
+ <Author>
97
+ <Avatar alt={name} src={authorAvatar} />
98
+ <Details>{name}</Details>
99
+ </Author>
100
+ </OverviewItem>
112
101
  );
113
102
  };
114
103
 
@@ -132,33 +121,34 @@ const Package: React.FC<PackageInterface> = ({
132
121
  time && (
133
122
  <OverviewItem>
134
123
  <StyledTime />
135
- <Published>{t('package.published-on', { time: utils.formatDate(time) })}</Published>
136
- {utils.formatDateDistance(time)}
124
+ <Published title={utils.formatDate(time)}>
125
+ {t('package.published-on', { time: utils.formatDateDistance(time) })}
126
+ </Published>
137
127
  </OverviewItem>
138
128
  );
139
129
 
140
130
  const renderHomePageLink = (): React.ReactNode =>
141
131
  homepage &&
142
132
  url.isURL(homepage) && (
143
- <Link external={true} to={homepage}>
133
+ <LinkExternal to={homepage}>
144
134
  <Tooltip aria-label={t('package.homepage')} title={t('package.visit-home-page')}>
145
135
  <IconButton aria-label={t('package.homepage')} size="large">
146
136
  <HomeIcon />
147
137
  </IconButton>
148
138
  </Tooltip>
149
- </Link>
139
+ </LinkExternal>
150
140
  );
151
141
 
152
142
  const renderBugsLink = (): React.ReactNode =>
153
143
  bugs?.url &&
154
144
  url.isURL(bugs.url) && (
155
- <Link external={true} to={bugs.url}>
145
+ <LinkExternal to={bugs.url}>
156
146
  <Tooltip aria-label={t('package.bugs')} title={t('package.open-an-issue')}>
157
147
  <IconButton aria-label={t('package.bugs')} size="large">
158
148
  <BugReport />
159
149
  </IconButton>
160
150
  </Tooltip>
161
- </Link>
151
+ </LinkExternal>
162
152
  );
163
153
 
164
154
  const renderDownloadLink = (): React.ReactNode =>
@@ -174,7 +164,11 @@ const Package: React.FC<PackageInterface> = ({
174
164
  aria-label={t('package.download', { what: t('package.the-tar-file') })}
175
165
  title={t('package.tarball')}
176
166
  >
177
- <IconButton aria-label={t('package.download')} size="large">
167
+ <IconButton
168
+ aria-label={t('package.download')}
169
+ data-testid="download-tarball"
170
+ size="large"
171
+ >
178
172
  {isLoading ? (
179
173
  <CircularProgress size={13}>
180
174
  <DownloadIcon />
@@ -191,7 +185,7 @@ const Package: React.FC<PackageInterface> = ({
191
185
  return (
192
186
  <Grid container={true} item={true} xs={12}>
193
187
  <Grid item={true} xs={11}>
194
- <WrapperLink to={`/-/web/detail/${packageName}`}>
188
+ <WrapperLink to={`${Route.DETAIL}${packageName}`}>
195
189
  <PackageTitle className="package-title" data-testid="package-title">
196
190
  {packageName}
197
191
  </PackageTitle>
@@ -213,15 +207,7 @@ const Package: React.FC<PackageInterface> = ({
213
207
  );
214
208
  };
215
209
 
216
- const renderSecondaryComponent = (): React.ReactNode => {
217
- const tags = keywords.sort().map((keyword, index) => <Tag key={index}>{keyword}</Tag>);
218
- return (
219
- <>
220
- <Description>{description}</Description>
221
- {tags.length > 0 && <TagContainer>{tags}</TagContainer>}
222
- </>
223
- );
224
- };
210
+ const renderSecondaryComponent = (): React.ReactNode => <Description>{description}</Description>;
225
211
 
226
212
  const renderPackageListItemText = (): React.ReactNode => (
227
213
  <PackageListItemText
@@ -231,10 +217,21 @@ const Package: React.FC<PackageInterface> = ({
231
217
  />
232
218
  );
233
219
 
220
+ const renderKeywords = (): React.ReactNode => (
221
+ <ListItem alignItems={'flex-start'} sx={{ py: 0, my: 0 }}>
222
+ <List sx={{ p: 0, my: 0 }}>
223
+ <KeywordListItems keywords={keywords} />
224
+ </List>
225
+ </ListItem>
226
+ );
227
+
234
228
  return (
235
229
  <Wrapper className={'package'} data-testid="package-item-list">
236
- <ListItem alignItems={'flex-start'}>{renderPackageListItemText()}</ListItem>
237
- <ListItem alignItems={'flex-start'}>
230
+ <ListItem alignItems={'flex-start'} sx={{ mb: 0 }}>
231
+ {renderPackageListItemText()}
232
+ </ListItem>
233
+ {keywords && keywords?.length > 0 ? renderKeywords() : null}
234
+ <ListItem alignItems={'flex-start'} sx={{ mt: 0 }}>
238
235
  {renderAuthorInfo()}
239
236
  {renderVersionInfo()}
240
237
  {renderPublishedInfo()}
@@ -248,8 +245,8 @@ const Package: React.FC<PackageInterface> = ({
248
245
  export default Package;
249
246
 
250
247
  const iconStyle = ({ theme }: { theme: Theme }) => css`
251
- margin: 2px 10px 0 0;
252
- fill: ${theme?.palette.mode === 'light' ? theme?.palette.greyLight2 : theme?.palette.white};
248
+ margin: 0 10px 0 0;
249
+ fill: ${theme?.palette.mode === 'light' ? theme?.palette.greyDark : theme?.palette.white};
253
250
  `;
254
251
 
255
252
  const StyledVersion = styled(Version)`
@@ -11,8 +11,8 @@ import { Theme } from '../../';
11
11
  export const OverviewItem = styled('span')<{ theme?: Theme }>(({ theme }) => ({
12
12
  display: 'flex',
13
13
  alignItems: 'center',
14
- margin: '0 0 0 16px',
15
- color: theme?.palette.mode === 'light' ? theme?.palette.greyLight2 : theme?.palette.white,
14
+ margin: '0 20px 0 0',
15
+ color: theme?.palette.mode === 'light' ? theme?.palette.greyDark2 : theme?.palette.white,
16
16
  fontSize: 12,
17
17
  [`@media (max-width: ${theme?.breakPoints.medium}px)`]: {
18
18
  ':nth-of-type(3)': {
@@ -26,10 +26,9 @@ export const OverviewItem = styled('span')<{ theme?: Theme }>(({ theme }) => ({
26
26
  },
27
27
  }));
28
28
 
29
- export const Published = styled('span')<{ theme?: Theme }>(({ theme }) => ({
30
- color: theme?.palette.mode === 'light' ? theme?.palette.greyLight2 : theme?.palette.white,
29
+ export const Published = styled('span')({
31
30
  margin: '0 5px 0 0',
32
- }));
31
+ });
33
32
 
34
33
  export const Details = styled('span')({
35
34
  marginLeft: '5px',
@@ -59,6 +58,7 @@ export const PackageTitle = styled('span')<{ theme?: Theme }>(({ theme }) => ({
59
58
  marginBottom: 12,
60
59
  color: theme?.palette.mode == 'dark' ? theme?.palette.dodgerBlue : theme?.palette.eclipse,
61
60
  cursor: 'pointer',
61
+ textDecoration: 'none',
62
62
  [`@media (max-width: ${theme?.breakPoints.small}px)`]: {
63
63
  fontSize: 14,
64
64
  marginBottom: 8,
@@ -70,9 +70,9 @@ export const GridRightAligned = styled(Grid)({
70
70
  });
71
71
 
72
72
  export const Wrapper = styled(List)<{ theme?: Theme }>(({ theme }) => ({
73
- ':hover': {
73
+ '&:hover': {
74
74
  backgroundColor:
75
- theme?.palette?.type == 'dark' ? theme?.palette?.secondary.main : theme?.palette?.greyLight3,
75
+ theme?.palette?.type == 'dark' ? theme?.palette?.secondary.main : theme?.palette?.greyLight2,
76
76
  },
77
77
  }));
78
78
 
@@ -83,16 +83,6 @@ export const IconButton = styled(MuiIconButton)({
83
83
  },
84
84
  });
85
85
 
86
- export const TagContainer = styled('span')<{ theme?: Theme }>(({ theme }) => ({
87
- marginTop: 8,
88
- marginBottom: 12,
89
- display: 'flex',
90
- flexWrap: 'wrap',
91
- [`@media (max-width: ${theme?.breakPoints.medium}px)`]: {
92
- display: 'none',
93
- },
94
- }));
95
-
96
86
  export const PackageListItemText = styled(ListItemText)({
97
87
  paddingRight: 0,
98
88
  });
@@ -40,6 +40,7 @@ describe('<PackageList /> component', () => {
40
40
  name: 'xyz',
41
41
  version: '1.1.0',
42
42
  description: 'xyz description',
43
+ keywords: ['hello', 'mars'],
43
44
  author: { name: 'Martin', avatar: 'test avatar' },
44
45
  },
45
46
  ],
@@ -0,0 +1,50 @@
1
+ import React from 'react';
2
+
3
+ import { fireEvent, render, screen } from '../../test/test-react-testing-library';
4
+ import { Developer } from '../../types/packageMeta';
5
+ import Person from './Person';
6
+
7
+ const mockPerson: Developer = {
8
+ name: 'John Doe',
9
+ email: 'john.doe@example.com',
10
+ avatar: 'https://example.com/avatar.jpg',
11
+ url: 'https://example.com/~johndoe',
12
+ };
13
+
14
+ const mockPackageName = 'test-package';
15
+ const mockVersion = '1.0.0';
16
+
17
+ const ComponentToBeRendered: React.FC<{ withText?: boolean }> = ({ withText = false }) => {
18
+ return (
19
+ <Person
20
+ packageName={mockPackageName}
21
+ person={mockPerson}
22
+ version={mockVersion}
23
+ withText={withText}
24
+ />
25
+ );
26
+ };
27
+
28
+ describe('Person component', () => {
29
+ test('should render avatar', () => {
30
+ render(<ComponentToBeRendered />);
31
+ const avatar = screen.getByAltText(mockPerson.name);
32
+ expect(avatar).toBeInTheDocument();
33
+ // but not include text
34
+ expect(screen.queryByText(mockPerson.name)).not.toBeInTheDocument();
35
+ });
36
+
37
+ test('should render name when withText is true', () => {
38
+ render(<ComponentToBeRendered withText={true} />);
39
+ const name = screen.getByText(mockPerson.name);
40
+ expect(name).toBeInTheDocument();
41
+ });
42
+
43
+ test('should not render name when withText is false', async () => {
44
+ render(<ComponentToBeRendered />);
45
+ // hover over the avatar
46
+ fireEvent.mouseEnter(screen.getByTestId(mockPerson.name));
47
+ // wait for the tooltip to appear
48
+ await screen.findByTestId(mockPerson.name + '-tooltip');
49
+ });
50
+ });
@@ -0,0 +1,45 @@
1
+ import { Typography } from '@mui/material';
2
+ import Avatar from '@mui/material/Avatar';
3
+ import Tooltip from '@mui/material/Tooltip';
4
+ import React from 'react';
5
+
6
+ import { Developer } from '../../types/packageMeta';
7
+ import LinkExternal from '../LinkExternal';
8
+ import PersonTooltip from './PersonTooltip';
9
+ import { getLink, getName } from './utils';
10
+
11
+ const Person: React.FC<{
12
+ person: Developer;
13
+ packageName: string;
14
+ version: string;
15
+ withText?: boolean;
16
+ }> = ({ person, packageName, version, withText = false }) => {
17
+ const link = getLink(person, packageName, version);
18
+
19
+ const avatarComponent = (
20
+ <Avatar alt={person.name} src={person.avatar} sx={{ width: 40, height: 40, ml: 0, mr: 1 }} />
21
+ );
22
+
23
+ return (
24
+ <>
25
+ <Tooltip
26
+ data-testid={person.name}
27
+ key={person.email}
28
+ title={<PersonTooltip person={person} />}
29
+ >
30
+ {link.length > 0 ? (
31
+ <LinkExternal to={link}>{avatarComponent}</LinkExternal>
32
+ ) : (
33
+ avatarComponent
34
+ )}
35
+ </Tooltip>
36
+ {withText && (
37
+ <Typography sx={{ ml: 1 }} variant="subtitle2">
38
+ {getName(person.name)}
39
+ </Typography>
40
+ )}
41
+ </>
42
+ );
43
+ };
44
+
45
+ export default Person;
@@ -0,0 +1,26 @@
1
+ import Typography from '@mui/material/Typography';
2
+ import React from 'react';
3
+
4
+ import { Developer } from '../../types/packageMeta';
5
+ import { url } from '../../utils';
6
+ import LinkExternal from '../LinkExternal';
7
+
8
+ const PersonTooltip: React.FC<{ person: Developer }> = ({ person }) => (
9
+ <Typography data-testid={person.name + '-tooltip'}>
10
+ {person.name}
11
+ {person.email && url.isEmail(person.email) && (
12
+ <LinkExternal to={`mailto:${person.email}`}>
13
+ <br />
14
+ {person.email}
15
+ </LinkExternal>
16
+ )}
17
+ {person.url && url.isURL(person.url) && (
18
+ <LinkExternal to={person.url}>
19
+ <br />
20
+ {person.url}
21
+ </LinkExternal>
22
+ )}
23
+ </Typography>
24
+ );
25
+
26
+ export default PersonTooltip;
@@ -0,0 +1 @@
1
+ export { default } from './Person';
@@ -0,0 +1,20 @@
1
+ import i18next from 'i18next';
2
+
3
+ import { Developer } from '../../types/packageMeta';
4
+ import { url } from '../../utils';
5
+
6
+ export function getLink(person: Developer, packageName: string, version: string): string {
7
+ return person.email && url.isEmail(person.email)
8
+ ? `mailto:${person.email}?subject=${packageName} v${version}`
9
+ : person.url && url.isURL(person.url)
10
+ ? person.url
11
+ : '';
12
+ }
13
+
14
+ export function getName(name?: string): string {
15
+ return !name
16
+ ? i18next.t('author-unknown')
17
+ : name.toLowerCase() === 'anonymous'
18
+ ? i18next.t('author-anonymous')
19
+ : name;
20
+ }
@@ -3,6 +3,7 @@ import Dialog from '@mui/material/Dialog';
3
3
  import DialogContent from '@mui/material/DialogContent';
4
4
  import DialogTitle from '@mui/material/DialogTitle';
5
5
  import IconButton from '@mui/material/IconButton';
6
+ import { useTheme } from '@mui/styles';
6
7
  import React from 'react';
7
8
  import { useTranslation } from 'react-i18next';
8
9
  import ReactJson from 'react-json-view';
@@ -22,6 +23,7 @@ const ViewerTitle = (props: ViewerTitleProps) => {
22
23
  {onClose ? (
23
24
  <IconButton
24
25
  aria-label="close"
26
+ data-testid="close-raw-viewer"
25
27
  onClick={onClose}
26
28
  sx={{
27
29
  position: 'absolute',
@@ -46,18 +48,20 @@ type Props = {
46
48
  /* eslint-disable verdaccio/jsx-spread */
47
49
  const RawViewer: React.FC<Props> = ({ isOpen = false, onClose, packageMeta }) => {
48
50
  const { t } = useTranslation();
51
+ const theme = useTheme();
49
52
  return (
50
53
  <Dialog data-testid={'rawViewer--dialog'} fullScreen={true} open={isOpen}>
51
54
  <ViewerTitle id="viewer-title" onClose={onClose}>
52
- {t('action-bar-action.raw')}
55
+ {t('action-bar-action.raw-title', { package: packageMeta.latest.name })}
53
56
  </ViewerTitle>
54
57
  <DialogContent>
55
58
  <ReactJson
56
- collapseStringsAfterLength={40}
57
- collapsed={true}
58
- enableClipboard={false}
59
+ collapseStringsAfterLength={200}
60
+ collapsed={2}
61
+ enableClipboard={true}
59
62
  groupArraysAfterLength={10}
60
63
  src={packageMeta as any}
64
+ theme={theme?.palette.mode == 'light' ? 'bright:inverted' : 'bright'}
61
65
  />
62
66
  </DialogContent>
63
67
  </Dialog>
@@ -15,4 +15,21 @@ describe('<Readme /> component', () => {
15
15
  const wrapper = render(<Readme description="<h1>This is a test string</h1>" />);
16
16
  expect(wrapper.getByText('This is a test string')).toBeInTheDocument();
17
17
  });
18
+
19
+ test('should sanitize html', () => {
20
+ const markdown = `<script>alert('test')</script>`;
21
+ const wrapper = render(<Readme description={markdown} />);
22
+ expect(wrapper.queryAllByText('test')).toHaveLength(0);
23
+ });
24
+
25
+ test('should highlight code', () => {
26
+ const markdown = `\`\`\`js\nconst test = 1 + 2;\n\`\`\``;
27
+ const wrapper = render(<Readme description={markdown} />);
28
+ expect(wrapper.getByText('const')).toBeInTheDocument();
29
+ expect(wrapper.getByText('const')).toHaveClass('hljs-keyword');
30
+ expect(wrapper.getByText('1')).toBeInTheDocument();
31
+ expect(wrapper.getByText('1')).toHaveClass('hljs-number');
32
+ expect(wrapper.getByText('2')).toBeInTheDocument();
33
+ expect(wrapper.getByText('2')).toHaveClass('hljs-number');
34
+ });
18
35
  });
@@ -2,8 +2,6 @@ import styled from '@emotion/styled';
2
2
  import Box from '@mui/material/Box';
3
3
  import Card from '@mui/material/Card';
4
4
  import CardContent from '@mui/material/CardContent';
5
- import { useTheme } from '@mui/styles';
6
- import 'highlight.js/styles/default.css';
7
5
  import React from 'react';
8
6
 
9
7
  import { useCustomTheme } from '../../';
@@ -14,12 +12,19 @@ import { parseReadme } from './utils';
14
12
  const Readme: React.FC<Props> = ({ description }) => {
15
13
  // @ts-ignore
16
14
  const { isDarkMode } = useCustomTheme();
17
- const theme = useTheme();
15
+
16
+ // Stackoverflow theme fits well to Verdaccio dark colors
17
+ // https://highlightjs.org/examples
18
+ if (isDarkMode) {
19
+ require('highlight.js/styles/github-dark.css');
20
+ } else {
21
+ require('highlight.js/styles/github.css');
22
+ }
18
23
 
19
24
  return (
20
- <Card>
25
+ <Card sx={{ mb: 2 }}>
21
26
  <CardContent>
22
- <Box data-testid="readme" sx={{ margin: theme.spacing(1) }}>
27
+ <Box data-testid="readme" sx={{ m: 2 }}>
23
28
  <Wrapper
24
29
  className={`markdown-body ${isDarkMode ? 'markdown-dark' : 'markdown-light'}`}
25
30
  dangerouslySetInnerHTML={{ __html: parseReadme(description) as string }}
@@ -21,9 +21,6 @@ marked.setOptions({
21
21
  });
22
22
 
23
23
  export function parseReadme(readme: string): string | void {
24
- if (typeof readme === 'string') {
25
- const html = marked.parse(readme);
26
- return DOMPurify.sanitize(html);
27
- }
28
- return '';
24
+ const html = marked.parse(readme);
25
+ return DOMPurify.sanitize(html);
29
26
  }
@@ -4,10 +4,11 @@ import DialogTitle from '@mui/material/DialogTitle';
4
4
 
5
5
  import { Theme } from '../../';
6
6
 
7
- export const Title = styled(DialogTitle)<{ theme?: Theme }>((props) => ({
8
- backgroundColor: props.theme?.palette.primary.main,
9
- color: props.theme?.palette.white,
10
- fontSize: props.theme?.fontSize.lg,
7
+ export const Title = styled(DialogTitle)<{ theme?: Theme }>(({ theme }) => ({
8
+ backgroundColor:
9
+ theme?.palette.mode === 'light' ? theme?.palette.primary.main : theme?.palette.cyanBlue,
10
+ color: theme?.palette.white,
11
+ fontSize: theme?.fontSize.lg,
11
12
  }));
12
13
 
13
14
  export const Content = styled(DialogContent)<{ theme?: Theme }>(({ theme }) => ({
@@ -4,6 +4,7 @@ import List from '@mui/material/List';
4
4
  import ListItem from '@mui/material/ListItem';
5
5
  import ListItemText from '@mui/material/ListItemText';
6
6
  import Typography from '@mui/material/Typography';
7
+ import { useTheme } from '@mui/styles';
7
8
  import React from 'react';
8
9
  import { useTranslation } from 'react-i18next';
9
10
 
@@ -11,20 +12,13 @@ import { Theme } from '../../Theme';
11
12
  import { url as urlUtils } from '../../utils';
12
13
  import CopyClipboard from '../CopyClipboard';
13
14
  import { Git } from '../Icons';
14
- import { Link } from '../Link';
15
+ import LinkExternal from '../LinkExternal';
15
16
 
16
17
  const StyledText = styled(Typography)<{ theme?: Theme }>((props) => ({
17
18
  fontWeight: props.theme?.fontWeight.bold,
18
19
  textTransform: 'capitalize',
19
20
  }));
20
21
 
21
- const GithubLink = styled(Link)<{ theme?: Theme }>(({ theme }) => ({
22
- color: theme?.palette.mode === 'light' ? theme?.palette.primary.main : theme?.palette.white,
23
- ':hover': {
24
- color: theme?.palette.dodgerBlue,
25
- },
26
- }));
27
-
28
22
  const RepositoryListItem = styled(ListItem)({
29
23
  padding: 0,
30
24
  ':hover': {
@@ -33,18 +27,19 @@ const RepositoryListItem = styled(ListItem)({
33
27
  });
34
28
 
35
29
  const RepositoryListItemText = styled(ListItemText)({
36
- padding: '0 10px',
30
+ padding: '0 0 0 10px',
37
31
  margin: 0,
38
32
  });
39
33
 
40
34
  const RepositoryAvatar = styled(Avatar)({
41
- borderRadius: '0px',
42
- padding: '0',
35
+ padding: 0,
36
+ marginLeft: 0,
43
37
  backgroundColor: 'transparent',
44
38
  });
45
39
 
46
40
  const Repository: React.FC<{ packageMeta: any }> = ({ packageMeta }) => {
47
41
  const { t } = useTranslation();
42
+ const theme = useTheme();
48
43
  const url = packageMeta?.latest?.repository?.url;
49
44
  if (!url || !urlUtils.isURL(url)) {
50
45
  return null;
@@ -66,15 +61,15 @@ const Repository: React.FC<{ packageMeta: any }> = ({ packageMeta }) => {
66
61
  subheader={<StyledText variant="subtitle1">{t('sidebar.repository.title')}</StyledText>}
67
62
  >
68
63
  <RepositoryListItem>
69
- <RepositoryAvatar sx={{ backgroundColor: '#fff' }}>
64
+ <RepositoryAvatar sx={{ bgcolor: theme.palette.white }}>
70
65
  <Git />
71
66
  </RepositoryAvatar>
72
67
  <RepositoryListItemText
73
68
  primary={
74
69
  <CopyClipboard dataTestId="repositoryID" text={repositoryURL} title={repositoryURL}>
75
- <GithubLink external={true} to={repositoryURL} variant="outline">
70
+ <LinkExternal to={repositoryURL} variant="outline">
76
71
  {repositoryURL}
77
- </GithubLink>
72
+ </LinkExternal>
78
73
  </CopyClipboard>
79
74
  }
80
75
  />
@@ -0,0 +1,7 @@
1
+ import styled from '@emotion/styled';
2
+
3
+ export const Wrapper = styled('div')({
4
+ width: '100%',
5
+ position: 'relative',
6
+ zIndex: 1,
7
+ });