@arcblock/ux 2.10.66 → 2.10.68

Sign up to get free protection for your applications and to get access to all the features.
Files changed (294) hide show
  1. package/lib/Address/did-address.d.ts +6 -5
  2. package/lib/Address/index.d.ts +1 -1
  3. package/lib/Avatar/index.d.ts +10 -8
  4. package/lib/Avatar/index.js +6 -4
  5. package/lib/Blocklet/blocklet.d.ts +4 -4
  6. package/lib/Blocklet/blocklet.js +2 -2
  7. package/lib/BlockletContext/index.d.ts +3 -3
  8. package/lib/BlockletNFT/index.d.ts +6 -6
  9. package/lib/BlockletNFT/index.js +3 -3
  10. package/lib/BlockletV2/blocklet.d.ts +2 -2
  11. package/lib/Button/wrap.d.ts +4 -4
  12. package/lib/Button/wrap.js +2 -2
  13. package/lib/CardSelector/index.js +0 -1
  14. package/lib/Center/index.d.ts +1 -1
  15. package/lib/ClickToCopy/copy-button.d.ts +5 -4
  16. package/lib/ClickToCopy/copy-button.js +0 -1
  17. package/lib/ClickToCopy/hook.d.ts +3 -8
  18. package/lib/ClickToCopy/index.d.ts +6 -4
  19. package/lib/CodeBlock/index.d.ts +3 -1
  20. package/lib/CookieConsent/index.d.ts +8 -29
  21. package/lib/CookieConsent/index.js +3 -17
  22. package/lib/CountDown/index.d.ts +21 -25
  23. package/lib/CountDown/index.js +12 -11
  24. package/lib/DID/index.d.ts +9 -8
  25. package/lib/Datatable/index.d.ts +5 -5
  26. package/lib/Datatable/index.js +5 -5
  27. package/lib/Dialog/confirm.d.ts +6 -6
  28. package/lib/Dialog/confirm.js +3 -3
  29. package/lib/Dialog/types.d.ts +1 -1
  30. package/lib/DidLogo/index.d.ts +5 -25
  31. package/lib/DidLogo/index.js +4 -15
  32. package/lib/DriftBot/index.d.ts +13 -19
  33. package/lib/DriftBot/index.js +5 -6
  34. package/lib/Earth/index.d.ts +28 -10
  35. package/lib/Earth/index.js +12 -52
  36. package/lib/Earth/util.d.ts +10 -5
  37. package/lib/Earth/util.js +1 -0
  38. package/lib/ErrorBoundary/fallback.d.ts +12 -19
  39. package/lib/ErrorBoundary/fallback.js +2 -19
  40. package/lib/ErrorBoundary/index.d.ts +1 -1
  41. package/lib/Footer/index.d.ts +17 -24
  42. package/lib/Footer/index.js +2 -11
  43. package/lib/Header/header.d.ts +2 -2
  44. package/lib/Icon/image.d.ts +3 -2
  45. package/lib/Icon/index.d.ts +6 -4
  46. package/lib/Img/index.d.ts +1 -1
  47. package/lib/Img/index.js +1 -1
  48. package/lib/InfoRow/index.d.ts +9 -32
  49. package/lib/InfoRow/index.js +10 -23
  50. package/lib/Layout/dashboard/external-link.d.ts +13 -14
  51. package/lib/Layout/dashboard/external-link.js +5 -22
  52. package/lib/Layout/dashboard/full-page.d.ts +19 -11
  53. package/lib/Layout/dashboard/full-page.js +2 -6
  54. package/lib/Layout/dashboard/index.d.ts +20 -39
  55. package/lib/Layout/dashboard/index.js +10 -38
  56. package/lib/Layout/dashboard/sidebar.d.ts +17 -20
  57. package/lib/Layout/dashboard/sidebar.js +3 -16
  58. package/lib/Layout/dashboard-legacy/header.d.ts +10 -36
  59. package/lib/Layout/dashboard-legacy/header.js +5 -24
  60. package/lib/Layout/dashboard-legacy/index.d.ts +17 -56
  61. package/lib/Layout/dashboard-legacy/index.js +12 -41
  62. package/lib/Layout/dashboard-legacy/sidebar.d.ts +15 -26
  63. package/lib/Layout/dashboard-legacy/sidebar.js +5 -15
  64. package/lib/Layout/index.d.ts +17 -56
  65. package/lib/Layout/index.js +24 -50
  66. package/lib/LoadingMask/index.d.ts +8 -31
  67. package/lib/LoadingMask/index.js +2 -18
  68. package/lib/Locale/browser-lang.d.ts +4 -1
  69. package/lib/Locale/browser-lang.js +8 -3
  70. package/lib/Locale/context.d.ts +18 -8
  71. package/lib/Locale/context.js +1 -1
  72. package/lib/Locale/languages.d.ts +9 -55
  73. package/lib/Locale/selector.d.ts +10 -26
  74. package/lib/Locale/selector.js +8 -25
  75. package/lib/Locale/util.d.ts +4 -3
  76. package/lib/Locale/util.js +0 -1
  77. package/lib/Logo/index.d.ts +9 -40
  78. package/lib/Logo/index.js +88 -46
  79. package/lib/Metric/index.d.ts +9 -31
  80. package/lib/Metric/index.js +5 -20
  81. package/lib/NFTDisplay/aspect-ratio-container.d.ts +5 -12
  82. package/lib/NFTDisplay/aspect-ratio-container.js +0 -5
  83. package/lib/NFTDisplay/broken.d.ts +3 -13
  84. package/lib/NFTDisplay/broken.js +80 -10
  85. package/lib/NFTDisplay/displayApi.d.ts +1 -1
  86. package/lib/NFTDisplay/index.d.ts +28 -6
  87. package/lib/NFTDisplay/index.js +17 -51
  88. package/lib/NFTDisplay/svg-embedder/img.d.ts +8 -23
  89. package/lib/NFTDisplay/svg-embedder/img.js +3 -17
  90. package/lib/NFTDisplay/svg-embedder/inline-svg.d.ts +7 -13
  91. package/lib/NFTDisplay/svg-embedder/inline-svg.js +1 -8
  92. package/lib/NavMenu/nav-menu.d.ts +2 -0
  93. package/lib/NavMenu/nav-menu.js +0 -1
  94. package/lib/PageScroller/index.d.ts +14 -13
  95. package/lib/PageScroller/index.js +12 -37
  96. package/lib/PageScroller/usePrevValue.d.ts +1 -1
  97. package/lib/PageScroller/usePrevValue.js +1 -2
  98. package/lib/Passport/index.d.ts +1 -1
  99. package/lib/Passport/passport.d.ts +10 -30
  100. package/lib/Passport/passport.js +5 -19
  101. package/lib/PoweredByArcBlock/index.d.ts +4 -14
  102. package/lib/PoweredByArcBlock/index.js +1 -8
  103. package/lib/PricingTable/PricingPlan.d.ts +11 -9
  104. package/lib/PricingTable/PricingPlan.js +0 -4
  105. package/lib/PricingTable/index.d.ts +5 -3
  106. package/lib/PricingTable/index.js +1 -5
  107. package/lib/QRCode/index.d.ts +11 -22
  108. package/lib/QRCode/index.js +1 -15
  109. package/lib/RelativeTime/index.d.ts +12 -40
  110. package/lib/RelativeTime/index.js +7 -27
  111. package/lib/Result/common.d.ts +26 -45
  112. package/lib/Result/common.js +2 -4
  113. package/lib/Result/index.d.ts +5 -18
  114. package/lib/Result/index.js +1 -9
  115. package/lib/Result/result.d.ts +7 -29
  116. package/lib/Result/result.js +2 -17
  117. package/lib/Result/translations.d.ts +2 -54
  118. package/lib/Screenshot/BaseScreenshot/index.d.ts +7 -24
  119. package/lib/Screenshot/BaseScreenshot/index.js +2 -15
  120. package/lib/Screenshot/BaseScreenshot/shells/Macbook.d.ts +25 -19
  121. package/lib/Screenshot/BaseScreenshot/shells/Phone.d.ts +25 -19
  122. package/lib/Screenshot/index.d.ts +84 -28
  123. package/lib/Screenshot/index.js +14 -43
  124. package/lib/SessionBlocklet/index.d.ts +6 -19
  125. package/lib/SessionBlocklet/index.js +3 -14
  126. package/lib/SessionManager/index.d.ts +1 -1
  127. package/lib/SessionPermission/index.d.ts +9 -17
  128. package/lib/SessionPermission/index.js +3 -11
  129. package/lib/SessionUser/components/logged-in.d.ts +9 -31
  130. package/lib/SessionUser/components/logged-in.js +13 -29
  131. package/lib/SessionUser/components/session-user-item.d.ts +8 -1
  132. package/lib/SessionUser/components/session-user-item.js +2 -12
  133. package/lib/SessionUser/components/session-user-switch.d.ts +9 -21
  134. package/lib/SessionUser/components/session-user-switch.js +3 -15
  135. package/lib/SessionUser/components/un-login.d.ts +7 -23
  136. package/lib/SessionUser/components/un-login.js +4 -16
  137. package/lib/SessionUser/components/user-info.d.ts +12 -29
  138. package/lib/SessionUser/components/user-info.js +4 -19
  139. package/lib/SessionUser/index.d.ts +7 -30
  140. package/lib/SessionUser/index.js +5 -26
  141. package/lib/SessionUser/libs/translation.d.ts +2 -31
  142. package/lib/SessionUser/libs/translation.js +1 -0
  143. package/lib/SessionUser/libs/utils.d.ts +10 -9
  144. package/lib/Sparkline/index.d.ts +22 -1
  145. package/lib/Sparkline/index.js +25 -17
  146. package/lib/Spinner/index.d.ts +6 -1
  147. package/lib/Spinner/index.js +4 -11
  148. package/lib/Success/index.d.ts +5 -21
  149. package/lib/Success/index.js +4 -16
  150. package/lib/Tabs/index.d.ts +12 -26
  151. package/lib/Tabs/index.js +7 -37
  152. package/lib/TextCollapse/index.d.ts +10 -10
  153. package/lib/TextCollapse/index.js +4 -21
  154. package/lib/Theme/index.js +0 -2
  155. package/lib/Theme/theme-provider.d.ts +1 -1
  156. package/lib/Theme/theme.d.ts +4 -1
  157. package/lib/Theme/theme.js +1 -2
  158. package/lib/Typography/index.d.ts +5 -24
  159. package/lib/Typography/index.js +5 -17
  160. package/lib/Util/index.d.ts +11 -6
  161. package/lib/Util/index.js +6 -0
  162. package/lib/Video/index.d.ts +12 -16
  163. package/lib/Video/index.js +0 -14
  164. package/lib/Wallet/Action.d.ts +13 -18
  165. package/lib/Wallet/Action.js +0 -7
  166. package/lib/Wallet/Download.d.ts +24 -30
  167. package/lib/Wallet/Download.js +201 -18
  168. package/lib/Wallet/Open.d.ts +5 -15
  169. package/lib/Wallet/Open.js +5 -11
  170. package/lib/WalletOSIcon/index.d.ts +6 -25
  171. package/lib/WalletOSIcon/index.js +3 -16
  172. package/lib/WebWalletSWKeeper/index.d.ts +8 -20
  173. package/lib/WebWalletSWKeeper/index.js +14 -19
  174. package/lib/WechatPrompt/index.js +2 -0
  175. package/lib/global.d.ts +15 -0
  176. package/lib/type.d.ts +12 -3
  177. package/lib/withTheme/index.d.ts +8 -6
  178. package/lib/withTracker/index.d.ts +1 -1
  179. package/lib/withTracker/index.js +3 -0
  180. package/package.json +9 -5
  181. package/src/Address/did-address.tsx +7 -6
  182. package/src/Address/index.tsx +1 -1
  183. package/src/Avatar/index.jsx +6 -4
  184. package/src/Blocklet/blocklet.jsx +2 -2
  185. package/src/BlockletContext/index.tsx +3 -3
  186. package/src/BlockletNFT/index.jsx +3 -3
  187. package/src/BlockletV2/blocklet.tsx +2 -2
  188. package/src/Button/wrap.jsx +2 -2
  189. package/src/CardSelector/index.tsx +0 -1
  190. package/src/Center/index.tsx +1 -1
  191. package/src/ClickToCopy/copy-button.tsx +4 -4
  192. package/src/ClickToCopy/hook.ts +3 -2
  193. package/src/ClickToCopy/index.tsx +6 -5
  194. package/src/CodeBlock/index.tsx +3 -1
  195. package/src/CookieConsent/{index.jsx → index.tsx} +16 -19
  196. package/src/CountDown/{index.jsx → index.tsx} +30 -16
  197. package/src/DID/index.tsx +9 -8
  198. package/src/Datatable/index.jsx +5 -5
  199. package/src/Dialog/confirm.jsx +3 -3
  200. package/src/Dialog/types.d.ts +1 -1
  201. package/src/DidLogo/{index.jsx → index.tsx} +7 -14
  202. package/src/DriftBot/{index.jsx → index.tsx} +13 -11
  203. package/src/Earth/{index.jsx → index.tsx} +94 -66
  204. package/src/Earth/{util.js → util.ts} +20 -17
  205. package/src/ErrorBoundary/{fallback.jsx → fallback.tsx} +20 -21
  206. package/src/Footer/{index.jsx → index.tsx} +17 -14
  207. package/src/Header/header.tsx +2 -3
  208. package/src/Header/responsive-header.tsx +0 -1
  209. package/src/Icon/image.tsx +3 -3
  210. package/src/Icon/index.tsx +7 -4
  211. package/src/Img/index.jsx +1 -1
  212. package/src/InfoRow/{index.jsx → index.tsx} +32 -25
  213. package/src/Layout/dashboard/external-link.tsx +46 -0
  214. package/src/Layout/dashboard/{full-page.jsx → full-page.tsx} +20 -9
  215. package/src/Layout/dashboard/{index.jsx → index.tsx} +42 -44
  216. package/src/Layout/dashboard/{sidebar.jsx → sidebar.tsx} +23 -20
  217. package/src/Layout/dashboard-legacy/{header.jsx → header.tsx} +16 -26
  218. package/src/Layout/dashboard-legacy/{index.jsx → index.tsx} +32 -46
  219. package/src/Layout/dashboard-legacy/{sidebar.jsx → sidebar.tsx} +27 -19
  220. package/src/Layout/{index.jsx → index.tsx} +41 -47
  221. package/src/LoadingMask/{index.jsx → index.tsx} +17 -19
  222. package/src/Locale/{browser-lang.js → browser-lang.ts} +9 -7
  223. package/src/Locale/context.tsx +18 -11
  224. package/src/Locale/{languages.js → languages.ts} +1 -1
  225. package/src/Locale/{selector.jsx → selector.tsx} +32 -29
  226. package/src/Locale/{util.js → util.ts} +9 -2
  227. package/src/Logo/index.tsx +58 -0
  228. package/src/Metric/{index.jsx → index.tsx} +23 -18
  229. package/src/NFTDisplay/{aspect-ratio-container.jsx → aspect-ratio-container.tsx} +9 -7
  230. package/src/NFTDisplay/{broken.jsx → broken.tsx} +7 -12
  231. package/src/NFTDisplay/{displayApi.js → displayApi.ts} +4 -4
  232. package/src/NFTDisplay/{index.jsx → index.tsx} +59 -64
  233. package/src/NFTDisplay/svg-embedder/{img.jsx → img.tsx} +10 -18
  234. package/src/NFTDisplay/svg-embedder/{inline-svg.jsx → inline-svg.tsx} +8 -9
  235. package/src/NavMenu/nav-menu.tsx +2 -3
  236. package/src/PageScroller/{index.jsx → index.tsx} +40 -53
  237. package/src/PageScroller/{usePrevValue.js → usePrevValue.ts} +2 -3
  238. package/src/Passport/{passport.jsx → passport.tsx} +22 -19
  239. package/src/PoweredByArcBlock/{index.jsx → index.tsx} +6 -11
  240. package/src/PricingTable/{PricingPlan.jsx → PricingPlan.tsx} +15 -5
  241. package/src/PricingTable/{index.jsx → index.tsx} +9 -6
  242. package/src/QRCode/{index.jsx → index.tsx} +13 -17
  243. package/src/RelativeTime/{index.jsx → index.tsx} +24 -24
  244. package/src/Result/{common.jsx → common.tsx} +17 -13
  245. package/src/Result/index.tsx +30 -0
  246. package/src/Result/{result.jsx → result.tsx} +8 -17
  247. package/src/Result/{translations.js → translations.ts} +3 -1
  248. package/src/Screenshot/BaseScreenshot/{index.jsx → index.tsx} +9 -15
  249. package/src/Screenshot/BaseScreenshot/shells/{Macbook.jsx → Macbook.tsx} +3 -1
  250. package/src/Screenshot/BaseScreenshot/shells/{Phone.jsx → Phone.tsx} +3 -1
  251. package/src/Screenshot/{index.jsx → index.tsx} +60 -54
  252. package/src/SessionBlocklet/{index.jsx → index.tsx} +8 -14
  253. package/src/SessionPermission/index.tsx +25 -0
  254. package/src/SessionUser/components/{logged-in.jsx → logged-in.tsx} +49 -31
  255. package/src/SessionUser/components/session-user-item.tsx +97 -0
  256. package/src/SessionUser/components/{session-user-switch.jsx → session-user-switch.tsx} +16 -21
  257. package/src/SessionUser/components/{un-login.jsx → un-login.tsx} +10 -15
  258. package/src/SessionUser/components/{user-info.jsx → user-info.tsx} +16 -22
  259. package/src/SessionUser/index.tsx +26 -0
  260. package/src/SessionUser/libs/{translation.js → translation.ts} +3 -1
  261. package/src/SessionUser/libs/utils.ts +39 -0
  262. package/src/Sparkline/{index.jsx → index.tsx} +38 -22
  263. package/src/Spinner/index.tsx +20 -0
  264. package/src/Success/{index.jsx → index.tsx} +7 -13
  265. package/src/Tabs/{index.jsx → index.tsx} +26 -40
  266. package/src/TextCollapse/{index.jsx → index.tsx} +26 -21
  267. package/src/Theme/index.ts +0 -1
  268. package/src/Theme/theme-provider.tsx +1 -1
  269. package/src/Theme/theme.ts +6 -3
  270. package/src/Typography/{index.jsx → index.tsx} +19 -22
  271. package/src/Util/index.ts +14 -8
  272. package/src/Video/{index.jsx → index.tsx} +7 -10
  273. package/src/Wallet/{Action.jsx → Action.tsx} +16 -12
  274. package/src/Wallet/{Download.jsx → Download.tsx} +25 -21
  275. package/src/Wallet/{Open.jsx → Open.tsx} +8 -11
  276. package/src/WalletOSIcon/{index.jsx → index.tsx} +8 -16
  277. package/src/WebWalletSWKeeper/{index.jsx → index.tsx} +21 -24
  278. package/src/WechatPrompt/{index.jsx → index.tsx} +1 -0
  279. package/src/global.d.ts +15 -0
  280. package/src/type.d.ts +12 -3
  281. package/src/withTheme/{index.jsx → index.tsx} +12 -2
  282. package/src/withTracker/{index.jsx → index.tsx} +6 -4
  283. package/src/Layout/dashboard/external-link.jsx +0 -47
  284. package/src/Logo/index.jsx +0 -66
  285. package/src/Result/index.jsx +0 -33
  286. package/src/SessionPermission/index.jsx +0 -28
  287. package/src/SessionUser/components/session-user-item.jsx +0 -93
  288. package/src/SessionUser/index.jsx +0 -38
  289. package/src/SessionUser/libs/utils.js +0 -37
  290. package/src/Spinner/index.jsx +0 -21
  291. /package/src/ErrorBoundary/{index.jsx → index.ts} +0 -0
  292. /package/src/NFTDisplay/{loading.jsx → loading.tsx} +0 -0
  293. /package/src/Passport/{index.jsx → index.ts} +0 -0
  294. /package/src/SessionManager/{index.jsx → index.tsx} +0 -0
@@ -1,6 +1,5 @@
1
1
  /* eslint-disable react/jsx-no-bind */
2
- import { useState, useContext, useRef, useMemo } from 'react';
3
- import PropTypes from 'prop-types';
2
+ import React, { useState, useContext, useRef, useMemo } from 'react';
4
3
  import { Button, Typography, IconButton, Popper, MenuItem, MenuList, Box, ClickAwayListener } from '@mui/material';
5
4
  import { Icon as IconifyIcon } from '@iconify/react';
6
5
  import CheckIcon from '@iconify-icons/material-symbols/check';
@@ -11,16 +10,34 @@ import { getColor, getBackground } from '../Util';
11
10
  import { temp as colors } from '../Colors';
12
11
  import { LocaleContext } from './context';
13
12
  import { styled, useTheme } from '../Theme';
13
+ import type { Locale } from '../type';
14
+
15
+ export interface LocaleSelectorProps extends Omit<React.HTMLAttributes<HTMLDivElement>, 'onChange'> {
16
+ showText?: true | false;
17
+ popperProps?: React.HTMLAttributes<HTMLDivElement>;
18
+ popperType?: 'hover' | 'click';
19
+ icon?: React.ComponentType<any>;
20
+ size?: number;
21
+ onChange?: (locale: Locale) => void;
22
+ }
14
23
 
15
- export default function LocaleSelector(props) {
16
- const { showText, popperProps, popperType, icon: Icon, size, ...rest } = props;
24
+ export default function LocaleSelector(props: LocaleSelectorProps) {
25
+ const {
26
+ showText = true,
27
+ popperProps = {},
28
+ popperType = 'click',
29
+ icon: Icon,
30
+ size = 24,
31
+ onChange = noop,
32
+ ...rest
33
+ } = props;
17
34
  const { locale, changeLocale, languages } = useContext(LocaleContext);
18
- const anchorEl = useRef(null);
35
+ const anchorEl = useRef<HTMLButtonElement>(null);
19
36
  const [open, setOpen] = useState(false);
20
37
  const theme = useTheme();
21
38
  const dark = theme?.palette?.mode === 'dark';
22
39
 
23
- const onSelect = (newLocale) => {
40
+ const onSelect = (newLocale: Locale) => {
24
41
  changeLocale(newLocale);
25
42
  setOpen(false);
26
43
  if (typeof props.onChange === 'function') {
@@ -28,14 +45,14 @@ export default function LocaleSelector(props) {
28
45
  }
29
46
  };
30
47
 
31
- const onClose = (e) => {
32
- if (anchorEl.current?.contains(e.target)) {
48
+ const onClose = (e: MouseEvent | TouchEvent) => {
49
+ if (anchorEl.current?.contains(e.target as Node)) {
33
50
  return;
34
51
  }
35
52
  setOpen(false);
36
53
  };
37
54
 
38
- const ButtonComponent = showText ? Button : IconButton;
55
+ const ButtonComponent: typeof Button = showText ? Button : IconButton;
39
56
 
40
57
  const handleEventProps =
41
58
  popperType === 'hover'
@@ -62,14 +79,14 @@ export default function LocaleSelector(props) {
62
79
  }, [Icon, size]);
63
80
 
64
81
  return (
65
- <Div component="div" dark={dark} theme={theme} {...rest} {...handleEventProps}>
82
+ <Div dark={dark} theme={theme} {...rest} {...handleEventProps}>
66
83
  <ButtonComponent ref={anchorEl} className="trigger" role="button" aria-label="Locale selector button">
67
84
  <Box display="flex" alignItems="center">
68
85
  {renderIcon}
69
86
 
70
87
  {showText ? (
71
88
  <Typography component="strong" className="trigger-text">
72
- {languages.find((x) => x.code === locale).name}
89
+ {languages.find((x) => x.code === locale)?.name}
73
90
  </Typography>
74
91
  ) : (
75
92
  ''
@@ -82,7 +99,7 @@ export default function LocaleSelector(props) {
82
99
  <ClickAwayListener onClickAway={onClose}>
83
100
  <MenuList>
84
101
  {languages.map(({ code, name }) => (
85
- <MenuItem key={code} className="locale-item" onClick={() => onSelect(code, name)}>
102
+ <MenuItem key={code} className="locale-item" onClick={() => onSelect(code)}>
86
103
  <IconifyIcon
87
104
  icon={CheckIcon}
88
105
  className={code === locale ? 'check-icon check-icon-visible' : 'check-icon'}
@@ -98,27 +115,13 @@ export default function LocaleSelector(props) {
98
115
  );
99
116
  }
100
117
 
101
- LocaleSelector.propTypes = {
102
- size: PropTypes.number,
103
- showText: PropTypes.bool,
104
- popperProps: PropTypes.object,
105
- onChange: PropTypes.func,
106
- popperType: PropTypes.oneOf(['hover', 'click']),
107
- icon: PropTypes.any,
108
- };
109
-
110
- LocaleSelector.defaultProps = {
111
- showText: true,
112
- size: 24,
113
- popperProps: {},
114
- onChange: noop,
115
- popperType: 'click',
116
- icon: null,
118
+ type DivProps = React.HTMLAttributes<HTMLDivElement> & {
119
+ dark: boolean;
117
120
  };
118
121
 
119
122
  const Div = styled('div', {
120
123
  shouldForwardProp: (prop) => prop !== 'dark',
121
- })`
124
+ })<DivProps>`
122
125
  display: inline-block;
123
126
 
124
127
  .trigger {
@@ -1,10 +1,17 @@
1
1
  import get from 'lodash/get';
2
+ import type { Locale, Translations } from '../type';
2
3
 
3
4
  /* eslint-disable no-prototype-builtins */
4
- export const replace = (template, data) =>
5
+ export const replace = (template: string, data: Record<string, any>) =>
5
6
  template.replace(/{(\w*)}/g, (m, key) => (data.hasOwnProperty(key) ? data[key] : ''));
6
7
 
7
- export const translate = (translations, key, locale, fallbackLocale = 'en', data = {}) => {
8
+ export const translate = (
9
+ translations: Translations,
10
+ key: string,
11
+ locale: Locale,
12
+ fallbackLocale = 'en',
13
+ data = {}
14
+ ) => {
8
15
  const translation = translations[locale];
9
16
  const translationValue = get(translation, key);
10
17
  const fallbackValue = get(translations[fallbackLocale], key);
@@ -0,0 +1,58 @@
1
+ import { type SxProps } from '@mui/material';
2
+ import { styled } from '../Theme';
3
+
4
+ import { ReactComponent as LightLogo } from './images/logo-light-top.svg';
5
+ import { ReactComponent as LightText } from './images/logo-light-text.svg';
6
+ import { ReactComponent as DarkLogo } from './images/logo-dark-top.svg';
7
+ import { ReactComponent as DarkText } from './images/logo-dark-text.svg';
8
+
9
+ export interface LogoProps extends React.HTMLAttributes<HTMLSpanElement> {
10
+ mode?: 'light' | 'dark';
11
+ layout?: 'vertical' | 'horizontal';
12
+ showText?: true | false;
13
+ showLogo?: true | false;
14
+ size?: number;
15
+ sx?: SxProps;
16
+ }
17
+
18
+ export default function Logo({
19
+ showText = true,
20
+ showLogo = true,
21
+ mode = 'dark',
22
+ layout = 'vertical',
23
+ size,
24
+ style = {},
25
+ ...rest
26
+ }: LogoProps) {
27
+ const isLight = mode === 'light';
28
+ const logo = isLight ? <LightLogo /> : <DarkLogo />;
29
+ const text = isLight ? <LightText className="logo-text" /> : <DarkText className="logo-text" />;
30
+
31
+ if (size) {
32
+ style.width = `${size}px`;
33
+ style.height = `${size}px`;
34
+ }
35
+
36
+ return (
37
+ <Container layout={layout} style={style} {...rest}>
38
+ {showLogo && logo}
39
+ {showText && text}
40
+ </Container>
41
+ );
42
+ }
43
+
44
+ type ContainerProps = {
45
+ layout: 'vertical' | 'horizontal';
46
+ };
47
+
48
+ const Container = styled('span')<ContainerProps>`
49
+ display: inline-flex;
50
+ flex-direction: ${(props) => (props.layout === 'horizontal' ? 'row' : 'column')};
51
+ justify-content: center;
52
+ align-items: center;
53
+
54
+ .logo-text {
55
+ ${(props) => (props.layout === 'vertical' ? 'margin-top: 8px;' : '')}
56
+ ${(props) => (props.layout === 'vertical' ? '' : 'margin-left: 8px;')};
57
+ }
58
+ `;
@@ -1,10 +1,28 @@
1
1
  /* eslint-disable react/no-danger */
2
- import PropTypes from 'prop-types';
2
+ import { Link } from '@mui/material';
3
3
 
4
4
  import ImageIcon from '../Icon/image';
5
5
  import { styled } from '../Theme';
6
6
 
7
- export default function Metric({ icon, value, name, url, animated, LinkComponent, prefix }) {
7
+ export interface MetricProps {
8
+ icon: string;
9
+ value: string | number;
10
+ name: React.ReactNode;
11
+ url?: string;
12
+ animated?: false | true;
13
+ LinkComponent?: React.ElementType;
14
+ prefix?: string;
15
+ }
16
+
17
+ export default function Metric({
18
+ icon,
19
+ value,
20
+ name,
21
+ url = '',
22
+ animated = false,
23
+ LinkComponent = Link,
24
+ prefix = '/images',
25
+ }: MetricProps) {
8
26
  const metric = (
9
27
  <>
10
28
  <div className="metric__image">
@@ -23,24 +41,11 @@ export default function Metric({ icon, value, name, url, animated, LinkComponent
23
41
  return <Container>{url ? <LinkComponent to={url}>{metric}</LinkComponent> : metric}</Container>;
24
42
  }
25
43
 
26
- Metric.propTypes = {
27
- icon: PropTypes.string.isRequired,
28
- value: PropTypes.oneOfType([PropTypes.string, PropTypes.number]).isRequired,
29
- name: PropTypes.node.isRequired,
30
- animated: PropTypes.bool,
31
- url: PropTypes.string,
32
- LinkComponent: PropTypes.any,
33
- prefix: PropTypes.string,
34
- };
35
-
36
- Metric.defaultProps = {
37
- animated: false,
38
- url: '',
39
- LinkComponent: null,
40
- prefix: '/images',
44
+ type ContainerProps = {
45
+ size?: 'small' | 'large';
41
46
  };
42
47
 
43
- const Container = styled('div')`
48
+ const Container = styled('div')<ContainerProps>`
44
49
  border-left: 1px solid ${(props) => props.theme.typography.color.main};
45
50
  padding: 10px 0 10px 16px;
46
51
  @media (max-width: ${(props) => props.theme.breakpoints.values.sm}px) {
@@ -1,8 +1,11 @@
1
- import PropTypes from 'prop-types';
2
-
3
1
  import { styled } from '../Theme';
4
2
 
5
- function AspectRatioContainer({ aspect, children, ...rest }) {
3
+ export interface AspectRatioContainerProps {
4
+ aspect: number;
5
+ children?: React.ReactNode;
6
+ }
7
+
8
+ function AspectRatioContainer({ aspect, children, ...rest }: AspectRatioContainerProps) {
6
9
  return (
7
10
  <Root aspect={aspect} {...rest}>
8
11
  <span className="aspect-ratio-container__inner">{children}</span>
@@ -10,12 +13,11 @@ function AspectRatioContainer({ aspect, children, ...rest }) {
10
13
  );
11
14
  }
12
15
 
13
- AspectRatioContainer.propTypes = {
14
- aspect: PropTypes.number.isRequired,
15
- children: PropTypes.node.isRequired,
16
+ type RootProps = {
17
+ aspect: number;
16
18
  };
17
19
 
18
- const Root = styled('span')`
20
+ const Root = styled('span')<RootProps>`
19
21
  display: block;
20
22
  position: relative;
21
23
  width: 100%;
@@ -1,10 +1,13 @@
1
1
  import Box from '@mui/material/Box';
2
- import PropTypes from 'prop-types';
3
- // eslint-disable-next-line import/no-unresolved
4
- import NFTBroken from './NFTBroken.svg?react';
5
2
  import { styled } from '../Theme';
6
3
 
7
- export default function Broken({ children } = {}) {
4
+ import { ReactComponent as NFTBroken } from './NFTBroken.svg';
5
+
6
+ export interface BrokenProps {
7
+ children?: React.ReactNode;
8
+ }
9
+
10
+ export default function Broken({ children = 'Non-publicly accessible NFT' }: BrokenProps = {}) {
8
11
  return (
9
12
  <Root>
10
13
  <NFTBroken className="nft-display-broken-background" />
@@ -13,14 +16,6 @@ export default function Broken({ children } = {}) {
13
16
  );
14
17
  }
15
18
 
16
- Broken.propTypes = {
17
- children: PropTypes.node,
18
- };
19
-
20
- Broken.defaultProps = {
21
- children: 'Non-publicly accessible NFT',
22
- };
23
-
24
19
  const Root = styled(Box)`
25
20
  width: 100%;
26
21
  height: 100%;
@@ -1,10 +1,10 @@
1
- import axios from 'axios';
1
+ import axios, { AxiosAdapter, type AxiosResponse } from 'axios';
2
2
  import adapter from 'axios/lib/adapters/xhr.js';
3
3
 
4
4
  const cache = new Map();
5
5
  const EXPIRATION_TIME_MS = 10 * 60 * 1000; // 10 minutes
6
6
 
7
- const cacheAdapterEnhancer = (config) => {
7
+ const cacheAdapterEnhancer: AxiosAdapter = (config) => {
8
8
  const { url, method } = config;
9
9
  const cacheKey = JSON.stringify({ url, method });
10
10
 
@@ -22,12 +22,12 @@ const cacheAdapterEnhancer = (config) => {
22
22
  }
23
23
 
24
24
  return adapter(config)
25
- .then((response) => {
25
+ .then((response: AxiosResponse) => {
26
26
  // cache headers
27
27
  cache.set(cacheKey, { headers: response.headers, timestamp: Date.now() });
28
28
  return response;
29
29
  })
30
- .catch((error) => {
30
+ .catch((error: unknown) => {
31
31
  // cache error
32
32
  cache.set(cacheKey, { error, timestamp: Date.now() });
33
33
  throw error;
@@ -1,6 +1,5 @@
1
1
  /* eslint-disable react-hooks/rules-of-hooks */
2
- import { useRef, useEffect, useState } from 'react';
3
- import PropTypes from 'prop-types';
2
+ import React, { useRef, useEffect, useState } from 'react';
4
3
  import clsx from 'clsx';
5
4
  import { Buffer } from 'buffer';
6
5
  import get from 'lodash/get';
@@ -8,6 +7,7 @@ import pako from 'pako';
8
7
  import base64 from 'base64-url';
9
8
  import isSvg from 'is-svg';
10
9
  import noop from 'lodash/noop';
10
+ import { Box, type BoxProps } from '@mui/material';
11
11
 
12
12
  import AspectRatioContainer from './aspect-ratio-container';
13
13
  import ImgSvgEmbedder from './svg-embedder/img';
@@ -22,11 +22,11 @@ import displayApi from './displayApi';
22
22
  * - 旧: assetState.data.value (.credentialSubject.display)
23
23
  * - 新: assetState.display
24
24
  */
25
- export function getNFTData(assetState) {
25
+ export function getNFTData(assetState: Record<string, any>) {
26
26
  return assetState?.display || assetState?.data?.value;
27
27
  }
28
28
 
29
- function fromBase64(v) {
29
+ function fromBase64(v: string) {
30
30
  if (typeof v !== 'string') {
31
31
  throw new Error('fromBase64 requires input to be a string');
32
32
  }
@@ -38,7 +38,7 @@ function fromBase64(v) {
38
38
  // };
39
39
 
40
40
  // 仅针对非 url type 的情况
41
- const getSvgEmbedder = (preferredSvgEmbedder) => {
41
+ const getSvgEmbedder = (preferredSvgEmbedder: 'img' | 'svg') => {
42
42
  const embedders = {
43
43
  img: ImgSvgEmbedder,
44
44
  svg: InlineSvgEmbedder,
@@ -46,6 +46,31 @@ const getSvgEmbedder = (preferredSvgEmbedder) => {
46
46
  return embedders[preferredSvgEmbedder];
47
47
  };
48
48
 
49
+ export interface NFTDisplayProps extends BoxProps {
50
+ /** asset data 可以是 raw data 和 parsed data */
51
+ data: string | Record<string, any>;
52
+ address: string;
53
+ inset?: false | true;
54
+ aspect?: number;
55
+ component?: React.ElementType<any>;
56
+ className?: string;
57
+ renderError?: () => React.ReactNode;
58
+ renderLoading?: () => React.ReactNode;
59
+ /** 对于非 url type 的情况, 支持优先选用的 svg 嵌入方式, 默认是 img */
60
+ preferredSvgEmbedder?: 'img' | 'svg';
61
+ /** 针对非 url type 的情况, 检测 svg 有效性, 默认禁用 */
62
+ checkSvg?: false | true;
63
+ /** loading 最小显示时间 (避免闪烁) */
64
+ minimumLoadingTime?: number;
65
+ /** 完成回调, 无论加载成功|失败 */
66
+ onCompleted?: () => void;
67
+ /**
68
+ * 图片处理,参考:https://team.arcblock.io/comment/docs/c158aee4-accd-42f4-9ced-6a23f28c00e0/en/blocklet-image-service-guide
69
+ * 配置参数会全部转发给 Image Service
70
+ */
71
+ imageFilter?: object | null;
72
+ }
73
+
49
74
  /**
50
75
  * TODO:
51
76
  * 考虑把 asset data 解析部分和 nft display 分离, android 端有相关使用场景 - 只传入 svg 或 url, 也可以传入 asset data,
@@ -56,30 +81,31 @@ function NFTDisplay({
56
81
  address,
57
82
  inset,
58
83
  aspect,
59
- component,
60
- className,
84
+ component = 'span',
85
+ className = '',
61
86
  renderError,
62
87
  renderLoading,
63
- preferredSvgEmbedder,
64
- checkSvg,
65
- minimumLoadingTime,
66
- onCompleted,
67
- imageFilter,
88
+ preferredSvgEmbedder = 'img',
89
+ checkSvg = false,
90
+ minimumLoadingTime = 0,
91
+ onCompleted = noop,
92
+ imageFilter = null,
68
93
  ...rest
69
- }) {
70
- const wrapRoot = (children) => (
71
- <Root as={component} {...rest} className={clsx(className, { 'nft-display--inset': inset })}>
94
+ }: NFTDisplayProps) {
95
+ const wrapRoot = (children: React.ReactNode) => (
96
+ <Root component={component} {...rest} className={clsx(className, { 'nft-display--inset': inset })}>
72
97
  {children}
73
98
  </Root>
74
99
  );
75
100
 
76
- const parsed = useRef(data);
101
+ const parsed = useRef<Record<string, any>>({});
77
102
 
78
103
  try {
79
104
  // 如果是 raw data 先解析
80
- if (typeof parsed.current === 'string') {
105
+ if (typeof data === 'string') {
81
106
  parsed.current = JSON.parse(data);
82
- // console.log('[debug] parse data')
107
+ } else {
108
+ parsed.current = data;
83
109
  }
84
110
 
85
111
  const { vcId } = parsed.current;
@@ -91,7 +117,12 @@ function NFTDisplay({
91
117
  const isUrlType = type === 'url';
92
118
 
93
119
  // 首次加载, 对于 url type 的情况, loading 为 true
94
- const [state, setState] = useState({
120
+ const [state, setState] = useState<{
121
+ loading: boolean;
122
+ error: boolean;
123
+ loadingUrlType: boolean;
124
+ urlType: string | null;
125
+ }>({
95
126
  loading: isUrlType,
96
127
  error: false,
97
128
  loadingUrlType: true,
@@ -101,7 +132,7 @@ function NFTDisplay({
101
132
  // console.log('[debug] render', {type, minimumLoadingTime}, JSON.stringify(state))
102
133
 
103
134
  // assemble the complete url
104
- const getFullContentUrl = ({ useImageFilter = false, t } = {}) => {
135
+ const getFullContentUrl = ({ useImageFilter = false, t }: { useImageFilter?: boolean; t?: string } = {}) => {
105
136
  const urlObj = new URL(content);
106
137
 
107
138
  // check protocol
@@ -139,12 +170,13 @@ function NFTDisplay({
139
170
  url: getFullContentUrl({ useImageFilter: false, t: 'nftdisplay' }),
140
171
  method: 'HEAD',
141
172
  });
173
+ // @ts-expect-error
142
174
  const contentType = response?.headers?.get('Content-Type');
143
175
  setState({ ...state, loadingUrlType: false, urlType: contentType });
144
176
  } catch (error) {
145
177
  console.error('Failed to fetch url content type', error);
146
178
  // display an error message when timeout occurs to avoid repeated waiting.
147
- if (error?.message?.includes('timeout')) {
179
+ if ((error as Error)?.message?.includes('timeout')) {
148
180
  setState({ ...state, loadingUrlType: false, loading: false, error: true });
149
181
  return;
150
182
  }
@@ -154,7 +186,7 @@ function NFTDisplay({
154
186
  };
155
187
 
156
188
  useEffect(() => {
157
- let timer;
189
+ let timer: NodeJS.Timeout;
158
190
  if (minimumLoadingTime > 0) {
159
191
  timer = setTimeout(() => setMinimumLoadingReady(true), minimumLoadingTime);
160
192
  }
@@ -295,7 +327,7 @@ function NFTDisplay({
295
327
  </>
296
328
  );
297
329
  } catch (e) {
298
- console.error(e?.message, {
330
+ console.error((e as Error)?.message, {
299
331
  nftId: address,
300
332
  vcId: parsed?.current?.vcId,
301
333
  });
@@ -303,44 +335,7 @@ function NFTDisplay({
303
335
  }
304
336
  }
305
337
 
306
- NFTDisplay.propTypes = {
307
- // asset data 可以是 raw data 和 parsed data
308
- data: PropTypes.oneOfType([PropTypes.object, PropTypes.string]).isRequired,
309
- address: PropTypes.string.isRequired,
310
- component: PropTypes.string,
311
- inset: PropTypes.bool,
312
- aspect: PropTypes.number,
313
- className: PropTypes.string,
314
- renderError: PropTypes.func,
315
- renderLoading: PropTypes.func,
316
- // 对于非 url type 的情况, 支持优先选用的 svg 嵌入方式, 默认是 img
317
- preferredSvgEmbedder: PropTypes.oneOf(['img', 'svg']),
318
- // 针对非 url type 的情况, 检测 svg 有效性, 默认禁用
319
- checkSvg: PropTypes.bool,
320
- // loading 最小显示时间 (避免闪烁)
321
- minimumLoadingTime: PropTypes.number,
322
- // 完成回调, 无论加载成功|失败
323
- onCompleted: PropTypes.func,
324
- // 图片处理,参考:https://team.arcblock.io/comment/docs/c158aee4-accd-42f4-9ced-6a23f28c00e0/en/blocklet-image-service-guide
325
- // 配置参数会全部转发给 Image Service
326
- imageFilter: PropTypes.object,
327
- };
328
-
329
- NFTDisplay.defaultProps = {
330
- component: 'span',
331
- inset: false,
332
- aspect: 0,
333
- className: '',
334
- renderError: null,
335
- renderLoading: null,
336
- preferredSvgEmbedder: 'img',
337
- checkSvg: false,
338
- minimumLoadingTime: 0,
339
- onCompleted: noop,
340
- imageFilter: null,
341
- };
342
-
343
- const Root = styled('div')`
338
+ const Root = styled(Box)`
344
339
  display: flex;
345
340
  justify-content: center;
346
341
  align-items: center;
@@ -369,11 +364,11 @@ const Root = styled('div')`
369
364
  }
370
365
  `;
371
366
 
372
- function withAspectRatio(Component) {
367
+ function withAspectRatio(Component: React.ComponentType<NFTDisplayProps>) {
373
368
  // eslint-disable-next-line func-names, react/prop-types
374
- return function ({ aspect, inset, ...rest }) {
369
+ return function ({ aspect, inset, ...rest }: NFTDisplayProps) {
375
370
  // inset 比 aspect ratio 优先级高, 如果同时设置了 inset 和 aspect, 则后者不生效
376
- const applyAspectRatio = aspect > 0 && !inset;
371
+ const applyAspectRatio = aspect && aspect > 0 && !inset;
377
372
  if (applyAspectRatio) {
378
373
  return (
379
374
  <AspectRatioContainer aspect={aspect}>
@@ -1,16 +1,20 @@
1
- import PropTypes from 'prop-types';
2
1
  import InlineSvgEmbedder from './inline-svg';
3
2
 
4
- const svgToImgUrl = (svg) => {
3
+ const svgToImgUrl = (svg: string) => {
5
4
  // fix: #225, https://stackoverflow.com/a/52135328)
6
5
  const blob = new Blob([svg], { type: 'image/svg+xml' });
7
6
  return URL.createObjectURL(blob);
8
7
  };
9
8
 
10
- /**
11
- * 基于 <img> 嵌入 svg
12
- */
13
- function ImgEmbedder({ svg, alt, fallback, ...rest }) {
9
+ export interface ImgEmbedderProps extends React.HTMLAttributes<HTMLImageElement> {
10
+ svg: string;
11
+ alt?: string;
12
+ /** 对于包含 foreignObject 的 svg, fallback inline svg + shadow DOM */
13
+ fallback?: true | false;
14
+ }
15
+
16
+ /** 基于 <img> 嵌入 svg */
17
+ function ImgEmbedder({ svg, alt = '', fallback = true, ...rest }: ImgEmbedderProps) {
14
18
  // 包含 foreignObject 的 svg, fallback 到 shadow dom
15
19
  if (fallback && svg.indexOf('</foreignObject>') > -1) {
16
20
  return <InlineSvgEmbedder svg={svg} />;
@@ -20,16 +24,4 @@ function ImgEmbedder({ svg, alt, fallback, ...rest }) {
20
24
  return <img src={url} onLoad={() => URL.revokeObjectURL(url)} alt={alt} {...rest} />;
21
25
  }
22
26
 
23
- ImgEmbedder.propTypes = {
24
- svg: PropTypes.string.isRequired,
25
- alt: PropTypes.string,
26
- // 对于包含 foreignObject 的 svg, fallback 到 inline svg + shadow DOM
27
- fallback: PropTypes.bool,
28
- };
29
-
30
- ImgEmbedder.defaultProps = {
31
- alt: '',
32
- fallback: true,
33
- };
34
-
35
27
  export default ImgEmbedder;
@@ -1,12 +1,15 @@
1
- import PropTypes from 'prop-types';
2
1
  import root from 'react-shadow/emotion';
2
+ import { type SxProps } from '@mui/material';
3
3
 
4
4
  import { styled } from '../../Theme';
5
5
 
6
- /**
7
- * inline svg 的方式嵌入 svg, 使用 shadow DOM 避免样式污染
8
- */
9
- function InlineSvg({ svg, ...rest }) {
6
+ export interface InlineSvgProps extends React.HTMLAttributes<HTMLSpanElement> {
7
+ svg: string;
8
+ sx?: SxProps;
9
+ }
10
+
11
+ /** inline svg 的方式嵌入 svg, 使用 shadow DOM 避免样式污染 */
12
+ function InlineSvg({ svg, ...rest }: InlineSvgProps) {
10
13
  return (
11
14
  <Root {...rest}>
12
15
  <Inner dangerouslySetInnerHTML={{ __html: svg }} />
@@ -14,10 +17,6 @@ function InlineSvg({ svg, ...rest }) {
14
17
  );
15
18
  }
16
19
 
17
- InlineSvg.propTypes = {
18
- svg: PropTypes.string.isRequired,
19
- };
20
-
21
20
  const Root = styled(root.span)`
22
21
  display: block;
23
22
  width: 100%;
@@ -1,4 +1,3 @@
1
- /* eslint-disable no-unused-vars */
2
1
  import {
3
2
  Children,
4
3
  cloneElement,
@@ -10,6 +9,7 @@ import {
10
9
  useLayoutEffect,
11
10
  isValidElement,
12
11
  } from 'react';
12
+ import { type SxProps } from '@mui/material';
13
13
  import clsx from 'clsx';
14
14
  import { MoreHoriz as MoreHorizIcon, ExpandMore as ExpandMoreIcon, Menu as MenuIcon } from '@mui/icons-material';
15
15
  import { useCreation, useMemoizedFn, useReactive, useSize, useThrottleFn } from 'ahooks';
@@ -60,8 +60,8 @@ export interface NavMenuProps extends React.HTMLAttributes<HTMLElement> {
60
60
  textColor?: string;
61
61
  activeTextColor?: string;
62
62
  bgColor?: string;
63
- // eslint-disable-next-line no-unused-vars
64
63
  onSelected?: (id: string) => void;
64
+ sx?: SxProps;
65
65
  }
66
66
 
67
67
  /**
@@ -305,7 +305,6 @@ export interface SubProps extends React.HTMLAttributes<HTMLLIElement> {
305
305
  icon?: React.ReactNode;
306
306
  label?: React.ReactNode;
307
307
  children?: Array<React.ReactElement>;
308
- // eslint-disable-next-line no-unused-vars
309
308
  expandIcon?: React.ReactNode | ((props: { isOpen: boolean }) => React.ReactNode);
310
309
  }
311
310