@lifi/widget 3.7.0-beta.6 → 3.7.0

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 (327) hide show
  1. package/AppProvider.tsx +6 -4
  2. package/AppRoutes.tsx +14 -2
  3. package/CHANGELOG.md +22 -0
  4. package/_esm/AppProvider.js +3 -2
  5. package/_esm/AppProvider.js.map +1 -1
  6. package/_esm/AppRoutes.js +9 -2
  7. package/_esm/AppRoutes.js.map +1 -1
  8. package/_esm/components/ActiveTransactions/ActiveTransactions.style.js +1 -1
  9. package/_esm/components/ActiveTransactions/ActiveTransactions.style.js.map +1 -1
  10. package/_esm/components/AmountInput/AmountInputEndAdornment.js +3 -1
  11. package/_esm/components/AmountInput/AmountInputEndAdornment.js.map +1 -1
  12. package/_esm/components/AppContainer.js +10 -5
  13. package/_esm/components/AppContainer.js.map +1 -1
  14. package/_esm/components/Avatar/AccountAvatar.d.ts +1 -1
  15. package/_esm/components/Avatar/AccountAvatar.js +1 -1
  16. package/_esm/components/Avatar/AccountAvatar.js.map +1 -1
  17. package/_esm/components/Avatar/Avatar.d.ts +0 -1
  18. package/_esm/components/Avatar/Avatar.js +4 -7
  19. package/_esm/components/Avatar/Avatar.js.map +1 -1
  20. package/_esm/components/Avatar/Avatar.style.d.ts +3 -6
  21. package/_esm/components/Avatar/Avatar.style.js +6 -19
  22. package/_esm/components/Avatar/Avatar.style.js.map +1 -1
  23. package/_esm/components/Avatar/TokenAvatar.js +1 -1
  24. package/_esm/components/Avatar/TokenAvatar.js.map +1 -1
  25. package/_esm/components/BaseTransactionButton/BaseTransactionButton.js +5 -3
  26. package/_esm/components/BaseTransactionButton/BaseTransactionButton.js.map +1 -1
  27. package/_esm/components/Card/InputCard.d.ts +1 -1
  28. package/_esm/components/ChainSelect/useChainSelect.js +1 -5
  29. package/_esm/components/ChainSelect/useChainSelect.js.map +1 -1
  30. package/_esm/components/FeeBreakdownTooltip.js +1 -4
  31. package/_esm/components/FeeBreakdownTooltip.js.map +1 -1
  32. package/_esm/components/FullPageContainer.d.ts +2 -0
  33. package/_esm/components/FullPageContainer.js +9 -0
  34. package/_esm/components/FullPageContainer.js.map +1 -0
  35. package/_esm/components/Header/EVMDisconnectIconButton.d.ts +4 -0
  36. package/_esm/components/Header/EVMDisconnectIconButton.js +12 -0
  37. package/_esm/components/Header/EVMDisconnectIconButton.js.map +1 -0
  38. package/_esm/components/Header/Header.js +23 -3
  39. package/_esm/components/Header/Header.js.map +1 -1
  40. package/_esm/components/Header/NavigationHeader.js +1 -1
  41. package/_esm/components/Header/NavigationHeader.js.map +1 -1
  42. package/_esm/components/Header/SVMDisconnectIconButton.d.ts +1 -0
  43. package/_esm/components/Header/SVMDisconnectIconButton.js +12 -0
  44. package/_esm/components/Header/SVMDisconnectIconButton.js.map +1 -0
  45. package/_esm/components/Header/WalletHeader.js +9 -5
  46. package/_esm/components/Header/WalletHeader.js.map +1 -1
  47. package/_esm/components/Header/WalletMenu.js +18 -10
  48. package/_esm/components/Header/WalletMenu.js.map +1 -1
  49. package/_esm/components/Header/WalletMenu.style.js +1 -5
  50. package/_esm/components/Header/WalletMenu.style.js.map +1 -1
  51. package/_esm/components/PageContainer.d.ts +2 -1
  52. package/_esm/components/PageContainer.js.map +1 -1
  53. package/_esm/components/PageEntered.d.ts +1 -0
  54. package/_esm/components/PageEntered.js +13 -0
  55. package/_esm/components/PageEntered.js.map +1 -0
  56. package/_esm/components/Routes/RoutesExpanded.js +1 -1
  57. package/_esm/components/Routes/RoutesExpanded.js.map +1 -1
  58. package/_esm/components/Search/SearchInput.d.ts +11 -0
  59. package/_esm/components/Search/SearchInput.js +21 -0
  60. package/_esm/components/Search/SearchInput.js.map +1 -0
  61. package/_esm/components/Search/SearchInput.style.d.ts +12 -0
  62. package/_esm/components/Search/SearchInput.style.js +38 -0
  63. package/_esm/components/Search/SearchInput.style.js.map +1 -0
  64. package/_esm/components/Search/SearchNotFound.d.ts +6 -0
  65. package/_esm/components/Search/SearchNotFound.js +5 -0
  66. package/_esm/components/Search/SearchNotFound.js.map +1 -0
  67. package/_esm/components/Search/SearchNotFound.style.d.ts +14 -0
  68. package/_esm/components/Search/SearchNotFound.style.js +29 -0
  69. package/_esm/components/Search/SearchNotFound.style.js.map +1 -0
  70. package/_esm/components/SendToWallet/SendToWalletButton.js +1 -1
  71. package/_esm/components/SendToWallet/SendToWalletButton.js.map +1 -1
  72. package/_esm/components/Skeleton/WidgetSkeleton.js +3 -4
  73. package/_esm/components/Skeleton/WidgetSkeleton.js.map +1 -1
  74. package/_esm/components/Skeleton/WidgetSkeleton.style.d.ts +4 -1
  75. package/_esm/components/Skeleton/WidgetSkeleton.style.js +20 -1
  76. package/_esm/components/Skeleton/WidgetSkeleton.style.js.map +1 -1
  77. package/_esm/components/SmallAvatar.d.ts +10 -0
  78. package/_esm/components/SmallAvatar.js +19 -0
  79. package/_esm/components/SmallAvatar.js.map +1 -0
  80. package/_esm/components/StepActions/StepActions.js +1 -1
  81. package/_esm/components/StepActions/StepActions.js.map +1 -1
  82. package/_esm/components/Tabs/Tabs.style.d.ts +1 -1
  83. package/_esm/components/Token/Token.js +1 -1
  84. package/_esm/components/Token/Token.js.map +1 -1
  85. package/_esm/components/TokenList/TokenList.js +2 -5
  86. package/_esm/components/TokenList/TokenList.js.map +1 -1
  87. package/_esm/components/TokenList/TokenListItem.js +5 -11
  88. package/_esm/components/TokenList/TokenListItem.js.map +1 -1
  89. package/_esm/components/TokenList/TokenNotFound.js +5 -13
  90. package/_esm/components/TokenList/TokenNotFound.js.map +1 -1
  91. package/_esm/components/TokenList/VirtualizedTokenList.js +1 -1
  92. package/_esm/components/TokenList/VirtualizedTokenList.js.map +1 -1
  93. package/_esm/components/TokenList/types.d.ts +3 -3
  94. package/_esm/components/TokenRate/TokenRate.js +2 -2
  95. package/_esm/components/TokenRate/TokenRate.js.map +1 -1
  96. package/_esm/config/version.d.ts +1 -1
  97. package/_esm/config/version.js +1 -1
  98. package/_esm/config/version.js.map +1 -1
  99. package/_esm/hooks/useAccount.d.ts +45 -0
  100. package/_esm/hooks/useAccount.js +56 -0
  101. package/_esm/hooks/useAccount.js.map +1 -0
  102. package/_esm/hooks/useAvailableChains.d.ts +1 -2
  103. package/_esm/hooks/useAvailableChains.js +8 -9
  104. package/_esm/hooks/useAvailableChains.js.map +1 -1
  105. package/_esm/hooks/useChains.d.ts +3 -4
  106. package/_esm/hooks/useChains.js +3 -5
  107. package/_esm/hooks/useChains.js.map +1 -1
  108. package/_esm/hooks/useFromTokenSufficiency.js +1 -1
  109. package/_esm/hooks/useFromTokenSufficiency.js.map +1 -1
  110. package/_esm/hooks/useGasSufficiency.js +3 -3
  111. package/_esm/hooks/useGasSufficiency.js.map +1 -1
  112. package/_esm/hooks/useProcessMessage.js +0 -4
  113. package/_esm/hooks/useProcessMessage.js.map +1 -1
  114. package/_esm/hooks/useRouteExecution.js +1 -1
  115. package/_esm/hooks/useRouteExecution.js.map +1 -1
  116. package/_esm/hooks/useRoutes.js +1 -1
  117. package/_esm/hooks/useRoutes.js.map +1 -1
  118. package/_esm/hooks/useScrollableContainer.d.ts +0 -1
  119. package/_esm/hooks/useScrollableContainer.js +1 -2
  120. package/_esm/hooks/useScrollableContainer.js.map +1 -1
  121. package/_esm/hooks/useSetContentHeight.js +9 -6
  122. package/_esm/hooks/useSetContentHeight.js.map +1 -1
  123. package/_esm/hooks/useTokenBalance.js +1 -1
  124. package/_esm/hooks/useTokenBalance.js.map +1 -1
  125. package/_esm/hooks/useTokenBalances.js +1 -1
  126. package/_esm/hooks/useTokenBalances.js.map +1 -1
  127. package/_esm/hooks/useTokens.js +1 -1
  128. package/_esm/hooks/useTokens.js.map +1 -1
  129. package/_esm/hooks/useTransactionDetails.js +1 -1
  130. package/_esm/hooks/useTransactionDetails.js.map +1 -1
  131. package/_esm/hooks/useTransactionHistory.js +1 -1
  132. package/_esm/hooks/useTransactionHistory.js.map +1 -1
  133. package/_esm/hooks/useWallets.d.ts +6 -0
  134. package/_esm/hooks/useWallets.js +80 -0
  135. package/_esm/hooks/useWallets.js.map +1 -0
  136. package/_esm/i18n/en.json +11 -4
  137. package/_esm/index.d.ts +2 -0
  138. package/_esm/index.js +2 -0
  139. package/_esm/index.js.map +1 -1
  140. package/_esm/pages/RoutesPage/RoutesPage.js +1 -1
  141. package/_esm/pages/RoutesPage/RoutesPage.js.map +1 -1
  142. package/_esm/pages/SelectChainPage/SelectChainPage.js +27 -8
  143. package/_esm/pages/SelectChainPage/SelectChainPage.js.map +1 -1
  144. package/_esm/pages/SelectEnabledToolsPage.js +38 -16
  145. package/_esm/pages/SelectEnabledToolsPage.js.map +1 -1
  146. package/_esm/pages/SelectTokenPage/SearchTokenInput.js +2 -12
  147. package/_esm/pages/SelectTokenPage/SearchTokenInput.js.map +1 -1
  148. package/_esm/pages/SelectTokenPage/SelectTokenPage.js +2 -2
  149. package/_esm/pages/SelectTokenPage/SelectTokenPage.js.map +1 -1
  150. package/_esm/pages/SelectTokenPage/useTokenListHeight.js +8 -14
  151. package/_esm/pages/SelectTokenPage/useTokenListHeight.js.map +1 -1
  152. package/_esm/pages/SelectWalletPage/EVMListItemButton.d.ts +9 -0
  153. package/_esm/pages/SelectWalletPage/EVMListItemButton.js +39 -0
  154. package/_esm/pages/SelectWalletPage/EVMListItemButton.js.map +1 -0
  155. package/_esm/pages/SelectWalletPage/SVMListItemButton.d.ts +6 -0
  156. package/_esm/pages/SelectWalletPage/SVMListItemButton.js +32 -0
  157. package/_esm/pages/SelectWalletPage/SVMListItemButton.js.map +1 -0
  158. package/_esm/pages/SelectWalletPage/SelectWalletPage.d.ts +1 -0
  159. package/_esm/pages/SelectWalletPage/SelectWalletPage.js +41 -0
  160. package/_esm/pages/SelectWalletPage/SelectWalletPage.js.map +1 -0
  161. package/_esm/pages/SendToWallet/ConnectedWalletsPage.js +1 -1
  162. package/_esm/pages/SendToWallet/ConnectedWalletsPage.js.map +1 -1
  163. package/_esm/pages/SendToWallet/SendToWalletPage.js +1 -1
  164. package/_esm/pages/SendToWallet/SendToWalletPage.js.map +1 -1
  165. package/_esm/pages/SendToWallet/SendToWalletPage.style.d.ts +1 -1
  166. package/_esm/pages/TransactionPage/StatusBottomSheet.js +5 -5
  167. package/_esm/pages/TransactionPage/StatusBottomSheet.js.map +1 -1
  168. package/_esm/providers/I18nProvider/types.d.ts +2 -2
  169. package/_esm/providers/WalletProvider/SDKProviders.js +7 -15
  170. package/_esm/providers/WalletProvider/SDKProviders.js.map +1 -1
  171. package/_esm/providers/WalletProvider/WalletProvider.d.ts +0 -1
  172. package/_esm/providers/WalletProvider/WalletProvider.js +1 -14
  173. package/_esm/providers/WalletProvider/WalletProvider.js.map +1 -1
  174. package/_esm/providers/WalletProvider/useHasExternalWalletProvider.d.ts +1 -1
  175. package/_esm/providers/WalletProvider/useHasExternalWalletProvider.js +3 -8
  176. package/_esm/providers/WalletProvider/useHasExternalWalletProvider.js.map +1 -1
  177. package/_esm/providers/WidgetProvider/WidgetProvider.js +1 -2
  178. package/_esm/providers/WidgetProvider/WidgetProvider.js.map +1 -1
  179. package/_esm/providers/WidgetProvider/types.d.ts +2 -0
  180. package/_esm/stores/form/FormUpdater.js +1 -1
  181. package/_esm/stores/form/FormUpdater.js.map +1 -1
  182. package/_esm/stores/form/types.d.ts +4 -4
  183. package/_esm/stores/header/types.d.ts +2 -0
  184. package/_esm/stores/header/useHeaderStore.d.ts +7 -1
  185. package/_esm/stores/header/useHeaderStore.js +26 -2
  186. package/_esm/stores/header/useHeaderStore.js.map +1 -1
  187. package/_esm/stores/routes/useExecutingRoutesIds.js +1 -1
  188. package/_esm/stores/routes/useExecutingRoutesIds.js.map +1 -1
  189. package/_esm/stores/settings/types.d.ts +1 -1
  190. package/_esm/stores/settings/useSettingsStore.js +22 -9
  191. package/_esm/stores/settings/useSettingsStore.js.map +1 -1
  192. package/_esm/themes/createTheme.js +1 -2
  193. package/_esm/themes/createTheme.js.map +1 -1
  194. package/_esm/types/events.d.ts +6 -6
  195. package/_esm/types/events.js +3 -2
  196. package/_esm/types/events.js.map +1 -1
  197. package/_esm/utils/chainType.js +3 -2
  198. package/_esm/utils/chainType.js.map +1 -1
  199. package/_esm/utils/elements.d.ts +5 -2
  200. package/_esm/utils/elements.js +6 -1
  201. package/_esm/utils/elements.js.map +1 -1
  202. package/_esm/utils/fees.js +5 -9
  203. package/_esm/utils/fees.js.map +1 -1
  204. package/_esm/utils/format.js +1 -1
  205. package/_esm/utils/format.js.map +1 -1
  206. package/_esm/utils/navigationRoutes.d.ts +3 -1
  207. package/_esm/utils/navigationRoutes.js +3 -0
  208. package/_esm/utils/navigationRoutes.js.map +1 -1
  209. package/_esm/utils/svm.d.ts +1 -0
  210. package/_esm/utils/svm.js +11 -0
  211. package/_esm/utils/svm.js.map +1 -0
  212. package/_esm/utils/wallet.js +1 -1
  213. package/components/ActiveTransactions/ActiveTransactions.style.ts +1 -1
  214. package/components/AmountInput/AmountInputEndAdornment.tsx +5 -1
  215. package/components/AppContainer.tsx +15 -10
  216. package/components/Avatar/AccountAvatar.tsx +2 -2
  217. package/components/Avatar/Avatar.style.tsx +7 -20
  218. package/components/Avatar/Avatar.tsx +4 -12
  219. package/components/Avatar/TokenAvatar.tsx +1 -1
  220. package/components/BaseTransactionButton/BaseTransactionButton.tsx +5 -3
  221. package/components/ChainSelect/useChainSelect.ts +1 -10
  222. package/components/FeeBreakdownTooltip.tsx +1 -4
  223. package/components/FullPageContainer.tsx +14 -0
  224. package/components/Header/EVMDisconnectIconButton.tsx +24 -0
  225. package/components/Header/Header.tsx +28 -3
  226. package/components/Header/NavigationHeader.tsx +1 -1
  227. package/components/Header/SVMDisconnectIconButton.tsx +19 -0
  228. package/components/Header/WalletHeader.tsx +12 -11
  229. package/components/Header/WalletMenu.style.tsx +1 -5
  230. package/components/Header/WalletMenu.tsx +32 -22
  231. package/components/PageContainer.ts +2 -1
  232. package/components/PageEntered.ts +14 -0
  233. package/components/Routes/RoutesExpanded.tsx +2 -1
  234. package/components/Search/SearchInput.style.tsx +46 -0
  235. package/components/Search/SearchInput.tsx +57 -0
  236. package/components/Search/SearchNotFound.style.tsx +36 -0
  237. package/components/Search/SearchNotFound.tsx +23 -0
  238. package/components/SendToWallet/SendToWalletButton.tsx +1 -1
  239. package/components/Skeleton/WidgetSkeleton.style.tsx +21 -1
  240. package/components/Skeleton/WidgetSkeleton.tsx +10 -9
  241. package/components/SmallAvatar.tsx +25 -0
  242. package/components/StepActions/StepActions.tsx +1 -1
  243. package/components/Token/Token.tsx +1 -1
  244. package/components/TokenList/TokenList.tsx +2 -9
  245. package/components/TokenList/TokenListItem.tsx +7 -15
  246. package/components/TokenList/TokenNotFound.tsx +7 -27
  247. package/components/TokenList/VirtualizedTokenList.tsx +1 -1
  248. package/components/TokenList/types.ts +3 -3
  249. package/components/TokenRate/TokenRate.tsx +2 -2
  250. package/config/version.ts +1 -1
  251. package/hooks/useAccount.ts +109 -0
  252. package/hooks/useAvailableChains.ts +10 -9
  253. package/hooks/useChains.ts +3 -6
  254. package/hooks/useFromTokenSufficiency.ts +1 -1
  255. package/hooks/useGasSufficiency.ts +3 -5
  256. package/hooks/useProcessMessage.ts +0 -4
  257. package/hooks/useRouteExecution.ts +1 -1
  258. package/hooks/useRoutes.ts +1 -1
  259. package/hooks/useScrollableContainer.ts +1 -6
  260. package/hooks/useSetContentHeight.ts +10 -6
  261. package/hooks/useTokenBalance.ts +1 -1
  262. package/hooks/useTokenBalances.ts +1 -1
  263. package/hooks/useTokens.ts +1 -2
  264. package/hooks/useTransactionDetails.ts +1 -1
  265. package/hooks/useTransactionHistory.ts +1 -1
  266. package/hooks/useWallets.ts +147 -0
  267. package/i18n/en.json +11 -4
  268. package/index.ts +2 -0
  269. package/package.json +6 -6
  270. package/pages/RoutesPage/RoutesPage.tsx +1 -1
  271. package/pages/SelectChainPage/SelectChainPage.tsx +62 -23
  272. package/pages/SelectEnabledToolsPage.tsx +94 -37
  273. package/pages/SelectTokenPage/SearchTokenInput.tsx +8 -26
  274. package/pages/SelectTokenPage/SelectTokenPage.tsx +3 -3
  275. package/pages/SelectTokenPage/useTokenListHeight.ts +14 -21
  276. package/pages/SelectWalletPage/EVMListItemButton.tsx +74 -0
  277. package/pages/SelectWalletPage/SVMListItemButton.tsx +47 -0
  278. package/pages/SelectWalletPage/SelectWalletPage.tsx +90 -0
  279. package/pages/SendToWallet/ConnectedWalletsPage.tsx +2 -2
  280. package/pages/SendToWallet/SendToWalletPage.tsx +1 -1
  281. package/pages/TransactionPage/StatusBottomSheet.tsx +6 -8
  282. package/providers/I18nProvider/types.ts +2 -2
  283. package/providers/WalletProvider/SDKProviders.tsx +7 -25
  284. package/providers/WalletProvider/WalletProvider.tsx +3 -24
  285. package/providers/WalletProvider/useHasExternalWalletProvider.ts +5 -11
  286. package/providers/WidgetProvider/WidgetProvider.tsx +1 -2
  287. package/providers/WidgetProvider/types.ts +2 -0
  288. package/stores/form/FormUpdater.tsx +1 -1
  289. package/stores/form/types.ts +4 -4
  290. package/stores/header/types.ts +2 -0
  291. package/stores/header/useHeaderStore.tsx +40 -2
  292. package/stores/routes/useExecutingRoutesIds.ts +1 -1
  293. package/stores/settings/types.ts +1 -1
  294. package/stores/settings/useSettingsStore.ts +30 -9
  295. package/themes/createTheme.ts +1 -3
  296. package/types/events.ts +5 -5
  297. package/utils/chainType.ts +3 -2
  298. package/utils/elements.ts +21 -1
  299. package/utils/fees.ts +13 -15
  300. package/utils/format.ts +1 -1
  301. package/utils/navigationRoutes.ts +7 -1
  302. package/utils/svm.ts +10 -0
  303. package/utils/wallet.ts +1 -1
  304. package/_esm/components/Avatar/SmallAvatar.d.ts +0 -4
  305. package/_esm/components/Avatar/SmallAvatar.js +0 -12
  306. package/_esm/components/Avatar/SmallAvatar.js.map +0 -1
  307. package/_esm/components/Header/DisconnectIconButton.d.ts +0 -4
  308. package/_esm/components/Header/DisconnectIconButton.js +0 -12
  309. package/_esm/components/Header/DisconnectIconButton.js.map +0 -1
  310. package/_esm/hooks/useHeaderHeight.d.ts +0 -6
  311. package/_esm/hooks/useHeaderHeight.js +0 -23
  312. package/_esm/hooks/useHeaderHeight.js.map +0 -1
  313. package/_esm/providers/WalletProvider/UTXOBaseProvider.d.ts +0 -2
  314. package/_esm/providers/WalletProvider/UTXOBaseProvider.js +0 -17
  315. package/_esm/providers/WalletProvider/UTXOBaseProvider.js.map +0 -1
  316. package/_esm/providers/WalletProvider/UTXOExternalContext.d.ts +0 -1
  317. package/_esm/providers/WalletProvider/UTXOExternalContext.js +0 -3
  318. package/_esm/providers/WalletProvider/UTXOExternalContext.js.map +0 -1
  319. package/_esm/providers/WalletProvider/UTXOProvider.d.ts +0 -3
  320. package/_esm/providers/WalletProvider/UTXOProvider.js +0 -18
  321. package/_esm/providers/WalletProvider/UTXOProvider.js.map +0 -1
  322. package/components/Avatar/SmallAvatar.tsx +0 -16
  323. package/components/Header/DisconnectIconButton.tsx +0 -18
  324. package/hooks/useHeaderHeight.ts +0 -27
  325. package/providers/WalletProvider/UTXOBaseProvider.tsx +0 -28
  326. package/providers/WalletProvider/UTXOExternalContext.ts +0 -3
  327. package/providers/WalletProvider/UTXOProvider.tsx +0 -26
@@ -1,3 +1,4 @@
1
+ import type { ToolsResponse } from '@lifi/sdk';
1
2
  import {
2
3
  Check,
3
4
  CheckBoxOutlineBlankOutlined,
@@ -6,20 +7,25 @@ import {
6
7
  } from '@mui/icons-material';
7
8
  import {
8
9
  Avatar,
10
+ debounce,
9
11
  IconButton,
10
- List,
11
12
  ListItemAvatar,
12
13
  Tooltip,
13
14
  useTheme,
14
15
  } from '@mui/material';
15
16
  import type { MouseEventHandler } from 'react';
16
- import { useMemo } from 'react';
17
+ import { type FormEventHandler, useMemo, useState } from 'react';
17
18
  import { useTranslation } from 'react-i18next';
18
19
  import { shallow } from 'zustand/shallow';
20
+ import { FullPageContainer } from '../components/FullPageContainer.js';
19
21
  import { ListItemText } from '../components/ListItemText.js';
20
- import { PageContainer } from '../components/PageContainer.js';
22
+ import { StickySearchInput } from '../components/Search/SearchInput.js';
23
+ import { SearchList } from '../components/Search/SearchInput.style.js';
24
+ import { SearchNotFound } from '../components/Search/SearchNotFound.js';
21
25
  import { SettingsListItemButton } from '../components/SettingsListItemButton.js';
26
+ import { useDefaultElementId } from '../hooks/useDefaultElementId.js';
22
27
  import { useHeader } from '../hooks/useHeader.js';
28
+ import { useScrollableContainer } from '../hooks/useScrollableContainer.js';
23
29
  import { useTools } from '../hooks/useTools.js';
24
30
  import { useSettingsStore } from '../stores/settings/useSettingsStore.js';
25
31
 
@@ -27,18 +33,22 @@ interface SelectAllCheckboxProps {
27
33
  allCheckboxesSelected: boolean;
28
34
  onClick: MouseEventHandler;
29
35
  anyCheckboxesSelected: boolean;
36
+ noCheckboxesAvailable: boolean;
30
37
  }
31
38
 
32
39
  const SelectAllCheckbox: React.FC<SelectAllCheckboxProps> = ({
33
40
  allCheckboxesSelected,
34
41
  anyCheckboxesSelected,
42
+ noCheckboxesAvailable,
35
43
  onClick,
36
44
  }) => {
37
45
  const { t } = useTranslation();
38
46
  const theme = useTheme();
39
- const tooltipTitle = allCheckboxesSelected
40
- ? t('tooltip.deselectAll')
41
- : t('tooltip.selectAll');
47
+ const tooltipTitle = noCheckboxesAvailable
48
+ ? undefined
49
+ : allCheckboxesSelected
50
+ ? t('tooltip.deselectAll')
51
+ : t('tooltip.selectAll');
42
52
 
43
53
  return (
44
54
  <Tooltip title={tooltipTitle}>
@@ -59,33 +69,54 @@ const SelectAllCheckbox: React.FC<SelectAllCheckboxProps> = ({
59
69
  );
60
70
  };
61
71
 
72
+ type ToolCollectionTypes =
73
+ | ToolsResponse['exchanges']
74
+ | ToolsResponse['bridges'];
75
+
62
76
  export const SelectEnabledToolsPage: React.FC<{
63
77
  type: 'Bridges' | 'Exchanges';
64
78
  }> = ({ type }) => {
65
79
  const typeKey = type.toLowerCase() as 'bridges' | 'exchanges';
66
80
  const { tools } = useTools();
67
- const [enabledTools, disabledTools, setToolValue, toggleTools] =
81
+ const [enabledTools, disabledTools, setToolValue, toggleToolKeys] =
68
82
  useSettingsStore(
69
83
  (state) => [
70
84
  state[`_enabled${type}`],
71
85
  state[`disabled${type}`],
72
86
  state.setToolValue,
73
- state.toggleTools,
87
+ state.toggleToolKeys,
74
88
  ],
75
89
  shallow,
76
90
  );
77
91
 
78
92
  const { t } = useTranslation();
93
+ const elementId = useDefaultElementId();
94
+ const scrollableContainer = useScrollableContainer(elementId);
95
+ const [filteredTools, setFilteredTools] = useState<ToolCollectionTypes>(
96
+ tools?.[typeKey] ?? [],
97
+ );
79
98
 
80
99
  const headerAction = useMemo(
81
100
  () => (
82
101
  <SelectAllCheckbox
83
- allCheckboxesSelected={!disabledTools.length}
84
- anyCheckboxesSelected={Boolean(disabledTools.length)}
85
- onClick={() => toggleTools(type)}
102
+ allCheckboxesSelected={
103
+ !!filteredTools.length &&
104
+ filteredTools.every((tool) => !disabledTools.includes(tool.key))
105
+ }
106
+ anyCheckboxesSelected={
107
+ !!filteredTools.length &&
108
+ filteredTools.some((tool) => disabledTools.includes(tool.key))
109
+ }
110
+ noCheckboxesAvailable={!filteredTools.length}
111
+ onClick={() =>
112
+ toggleToolKeys(
113
+ type,
114
+ filteredTools.map((tool) => tool.key),
115
+ )
116
+ }
86
117
  />
87
118
  ),
88
- [disabledTools.length, toggleTools, type],
119
+ [disabledTools, toggleToolKeys, type, filteredTools],
89
120
  );
90
121
 
91
122
  useHeader(t(`settings.enabled${type}`), headerAction);
@@ -94,31 +125,57 @@ export const SelectEnabledToolsPage: React.FC<{
94
125
  setToolValue(type, key, !enabledTools[key]);
95
126
  };
96
127
 
128
+ const handleSearchInputChange: FormEventHandler<HTMLInputElement> = (e) => {
129
+ const value = (e.target as HTMLInputElement).value;
130
+
131
+ if (!value) {
132
+ setFilteredTools(tools?.[typeKey] ?? []);
133
+ } else {
134
+ setFilteredTools(
135
+ (tools?.[typeKey]
136
+ ? tools[typeKey].filter((tool) =>
137
+ tool.name.toLowerCase().includes(value.toLowerCase()),
138
+ )
139
+ : []) as ToolCollectionTypes,
140
+ );
141
+ }
142
+
143
+ if (scrollableContainer) {
144
+ scrollableContainer.scrollTop = 0;
145
+ }
146
+ };
147
+
148
+ const debouncedSearchInputChange = debounce(handleSearchInputChange, 250);
149
+
97
150
  return (
98
- <PageContainer disableGutters>
99
- <List
100
- sx={{
101
- paddingTop: 0,
102
- paddingLeft: 1.5,
103
- paddingRight: 1.5,
104
- paddingBottom: 1.5,
105
- }}
106
- >
107
- {tools?.[typeKey].map((tool) => (
108
- <SettingsListItemButton
109
- key={tool.name}
110
- onClick={() => handleClick(tool.key)}
111
- >
112
- <ListItemAvatar>
113
- <Avatar src={tool.logoURI} alt={tool.name}>
114
- {tool.name[0]}
115
- </Avatar>
116
- </ListItemAvatar>
117
- <ListItemText primary={tool.name} />
118
- {enabledTools[tool.key] && <Check color="primary" />}
119
- </SettingsListItemButton>
120
- ))}
121
- </List>
122
- </PageContainer>
151
+ <FullPageContainer disableGutters>
152
+ <StickySearchInput
153
+ onChange={debouncedSearchInputChange}
154
+ placeholder={t(`main.search${type}`)}
155
+ />
156
+ {filteredTools.length ? (
157
+ <SearchList>
158
+ {filteredTools.map((tool) => (
159
+ <SettingsListItemButton
160
+ key={tool.name}
161
+ onClick={() => handleClick(tool.key)}
162
+ >
163
+ <ListItemAvatar>
164
+ <Avatar src={tool.logoURI} alt={tool.name}>
165
+ {tool.name[0]}
166
+ </Avatar>
167
+ </ListItemAvatar>
168
+ <ListItemText primary={tool.name} />
169
+ {enabledTools[tool.key] && <Check color="primary" />}
170
+ </SettingsListItemButton>
171
+ ))}
172
+ </SearchList>
173
+ ) : (
174
+ <SearchNotFound
175
+ message={t(`info.message.empty${type}List`)}
176
+ adjustForStickySearchInput
177
+ />
178
+ )}
179
+ </FullPageContainer>
123
180
  );
124
181
  };
@@ -1,11 +1,8 @@
1
- import { Search } from '@mui/icons-material';
2
- import { FormControl, InputAdornment } from '@mui/material';
3
1
  import { useEffect } from 'react';
4
2
  import { useTranslation } from 'react-i18next';
5
- import { InputCard } from '../../components/Card/InputCard.js';
3
+ import { SearchInput } from '../../components/Search/SearchInput.js';
6
4
  import { useFieldActions } from '../../stores/form/useFieldActions.js';
7
5
  import { useFieldController } from '../../stores/form/useFieldController.js';
8
- import { Input } from './SearchTokenInput.style.js';
9
6
 
10
7
  export const SearchTokenInput = () => {
11
8
  const { t } = useTranslation();
@@ -22,27 +19,12 @@ export const SearchTokenInput = () => {
22
19
  );
23
20
 
24
21
  return (
25
- <InputCard>
26
- <FormControl fullWidth>
27
- <Input
28
- size="small"
29
- placeholder={t(`main.tokenSearch`) as string}
30
- endAdornment={
31
- <InputAdornment position="end">
32
- <Search />
33
- </InputAdornment>
34
- }
35
- inputProps={{
36
- inputMode: 'search',
37
- onChange: (e) => onChange((e.target as HTMLInputElement).value),
38
- onBlur,
39
- name,
40
- value,
41
- maxLength: 128,
42
- }}
43
- autoComplete="off"
44
- />
45
- </FormControl>
46
- </InputCard>
22
+ <SearchInput
23
+ name={name}
24
+ placeholder={t(`main.tokenSearch`)}
25
+ onChange={(e) => onChange((e.target as HTMLInputElement).value)}
26
+ onBlur={onBlur}
27
+ value={value as string | undefined}
28
+ />
47
29
  );
48
30
  };
@@ -3,7 +3,7 @@ import type { FC } from 'react';
3
3
  import { useRef } from 'react';
4
4
  import { useTranslation } from 'react-i18next';
5
5
  import { ChainSelect } from '../../components/ChainSelect/ChainSelect.js';
6
- import { PageContainer } from '../../components/PageContainer.js';
6
+ import { FullPageContainer } from '../../components/FullPageContainer.js';
7
7
  import { TokenList } from '../../components/TokenList/TokenList.js';
8
8
  import { useHeader } from '../../hooks/useHeader.js';
9
9
  import { useNavigateBack } from '../../hooks/useNavigateBack.js';
@@ -40,7 +40,7 @@ export const SelectTokenPage: FC<FormTypeProps> = ({ formType }) => {
40
40
  const hideChainSelect = swapOnly && formType === 'to';
41
41
 
42
42
  return (
43
- <PageContainer disableGutters>
43
+ <FullPageContainer disableGutters>
44
44
  <Box pb={2} px={3} ref={headerRef}>
45
45
  {!hideChainSelect ? <ChainSelect formType={formType} /> : null}
46
46
  <Box mt={!hideChainSelect ? 2 : 0}>
@@ -55,6 +55,6 @@ export const SelectTokenPage: FC<FormTypeProps> = ({ formType }) => {
55
55
  formType={formType}
56
56
  />
57
57
  </Box>
58
- </PageContainer>
58
+ </FullPageContainer>
59
59
  );
60
60
  };
@@ -1,30 +1,21 @@
1
- import { useTheme } from '@mui/material';
1
+ import { debounce, useTheme } from '@mui/material';
2
2
  import type { MutableRefObject } from 'react';
3
3
  import { useLayoutEffect, useState } from 'react';
4
4
  import { useDefaultElementId } from '../../hooks/useDefaultElementId.js';
5
- import { ElementId, createElementId } from '../../utils/elements.js';
6
-
7
- const debounce = (func: Function, timeout = 300) => {
8
- let timer: ReturnType<typeof setTimeout>;
9
- return (...args: any[]) => {
10
- clearTimeout(timer);
11
- timer = setTimeout(() => {
12
- func.apply(this, args);
13
- }, timeout);
14
- };
15
- };
5
+ import {
6
+ ElementId,
7
+ getAppContainer,
8
+ getHeaderElement,
9
+ getScrollableContainer,
10
+ } from '../../utils/elements.js';
16
11
 
17
12
  const getContentHeight = (
18
13
  elementId: string,
19
14
  listParentRef: MutableRefObject<HTMLUListElement | null>,
20
15
  ) => {
21
- const containerElement = document.getElementById(
22
- createElementId(ElementId.ScrollableContainer, elementId),
23
- );
16
+ const containerElement = getScrollableContainer(elementId);
24
17
 
25
- const headerElement = document.getElementById(
26
- createElementId(ElementId.Header, elementId),
27
- );
18
+ const headerElement = getHeaderElement(elementId);
28
19
 
29
20
  const listParentElement = listParentRef?.current;
30
21
 
@@ -63,6 +54,10 @@ interface UseContentHeightProps {
63
54
  export const minTokenListHeight = 360;
64
55
  export const minMobileTokenListHeight = 160;
65
56
 
57
+ // NOTE: this hook is implicitly tied to the widget height functionality in the
58
+ // AppExpandedContainer, RelativeContainer and CssBaselineContainer components as defined in AppContainer.ts
59
+ // CSS changes in those components can have implications for the functionality in this hook
60
+
66
61
  export const useTokenListHeight = ({
67
62
  listParentRef,
68
63
  headerRef,
@@ -81,9 +76,7 @@ export const useTokenListHeight = ({
81
76
  // calling this on initial mount prevents the lists resizing appearing glitchy
82
77
  handleResize();
83
78
 
84
- const appContainer = document.getElementById(
85
- createElementId(ElementId.AppExpandedContainer, elementId),
86
- );
79
+ const appContainer = getAppContainer(elementId);
87
80
 
88
81
  let resizeObserver: ResizeObserver;
89
82
  if (appContainer) {
@@ -0,0 +1,74 @@
1
+ import { ChainType } from '@lifi/sdk';
2
+ import type { CreateConnectorFnExtended } from '@lifi/wallet-management';
3
+ import {
4
+ getConnectorIcon,
5
+ isWalletInstalledAsync,
6
+ } from '@lifi/wallet-management';
7
+ import { Avatar, ListItemAvatar } from '@mui/material';
8
+ import type { Connector } from 'wagmi';
9
+ import { useConnect, useDisconnect } from 'wagmi';
10
+ import { ListItemButton } from '../../components/ListItemButton.js';
11
+ import { ListItemText } from '../../components/ListItemText.js';
12
+ import { useNavigateBack } from '../../hooks/useNavigateBack.js';
13
+ import { useWidgetEvents } from '../../hooks/useWidgetEvents.js';
14
+ import { WidgetEvent } from '../../types/events.js';
15
+
16
+ interface EVMListItemButtonProps {
17
+ connectedConnector?: Connector;
18
+ connector: CreateConnectorFnExtended | Connector;
19
+ onNotInstalled(connector: Connector): void;
20
+ }
21
+
22
+ export const EVMListItemButton = ({
23
+ connectedConnector,
24
+ connector,
25
+ onNotInstalled,
26
+ }: EVMListItemButtonProps) => {
27
+ const { navigateBack } = useNavigateBack();
28
+ const emitter = useWidgetEvents();
29
+ const { connectAsync } = useConnect();
30
+ const { disconnectAsync } = useDisconnect();
31
+
32
+ const handleEVMConnect = async () => {
33
+ const identityCheckPassed = await isWalletInstalledAsync(
34
+ (connector as Connector).id,
35
+ );
36
+ if (!identityCheckPassed) {
37
+ onNotInstalled(connector as Connector);
38
+ return;
39
+ }
40
+ if (connectedConnector) {
41
+ await disconnectAsync({ connector: connectedConnector });
42
+ }
43
+ await connectAsync(
44
+ { connector },
45
+ {
46
+ onSuccess(data) {
47
+ emitter.emit(WidgetEvent.WalletConnected, {
48
+ address: data.accounts[0],
49
+ chainId: data.chainId,
50
+ chainType: ChainType.EVM,
51
+ });
52
+ },
53
+ },
54
+ );
55
+ navigateBack();
56
+ };
57
+
58
+ const connectorName: string =
59
+ (connector as CreateConnectorFnExtended).displayName || connector.name;
60
+
61
+ return (
62
+ <ListItemButton key={connector.id} onClick={handleEVMConnect}>
63
+ <ListItemAvatar>
64
+ <Avatar
65
+ src={getConnectorIcon(connector as Connector)}
66
+ alt={connectorName}
67
+ >
68
+ {connectorName?.[0]}
69
+ </Avatar>
70
+ </ListItemAvatar>
71
+ <ListItemText primary={connectorName} />
72
+ </ListItemButton>
73
+ );
74
+ };
@@ -0,0 +1,47 @@
1
+ import { ChainId, ChainType } from '@lifi/sdk';
2
+ import { Avatar, ListItemAvatar } from '@mui/material';
3
+ import type { Wallet } from '@solana/wallet-adapter-react';
4
+ import { useWallet } from '@solana/wallet-adapter-react';
5
+ import { ListItemButton } from '../../components/ListItemButton.js';
6
+ import { ListItemText } from '../../components/ListItemText.js';
7
+ import { useNavigateBack } from '../../hooks/useNavigateBack.js';
8
+ import { useWidgetEvents } from '../../hooks/useWidgetEvents.js';
9
+ import { WidgetEvent } from '../../types/events.js';
10
+
11
+ interface SVMListItemButtonProps {
12
+ wallet: Wallet;
13
+ }
14
+
15
+ export const SVMListItemButton = ({ wallet }: SVMListItemButtonProps) => {
16
+ const { navigateBack } = useNavigateBack();
17
+ const emitter = useWidgetEvents();
18
+ const { select, disconnect, connected } = useWallet();
19
+
20
+ const connect = async () => {
21
+ if (connected) {
22
+ await disconnect();
23
+ }
24
+ select(wallet.adapter.name);
25
+ // We use autoConnect on wallet selection
26
+ // await solanaConnect();
27
+ wallet.adapter.once('connect', (publicKey) => {
28
+ emitter.emit(WidgetEvent.WalletConnected, {
29
+ address: publicKey?.toString(),
30
+ chainId: ChainId.SOL,
31
+ chainType: ChainType.SVM,
32
+ });
33
+ });
34
+ navigateBack();
35
+ };
36
+
37
+ return (
38
+ <ListItemButton key={wallet.adapter.name} onClick={connect}>
39
+ <ListItemAvatar>
40
+ <Avatar src={wallet.adapter.icon} alt={wallet.adapter.name}>
41
+ {wallet.adapter.name[0]}
42
+ </Avatar>
43
+ </ListItemAvatar>
44
+ <ListItemText primary={`${wallet.adapter.name} (Solana)`} />
45
+ </ListItemButton>
46
+ );
47
+ };
@@ -0,0 +1,90 @@
1
+ import {
2
+ Button,
3
+ DialogActions,
4
+ DialogContent,
5
+ DialogContentText,
6
+ List,
7
+ } from '@mui/material';
8
+ import type { Wallet } from '@solana/wallet-adapter-react';
9
+ import { useCallback, useState } from 'react';
10
+ import { useTranslation } from 'react-i18next';
11
+ import type { Connector } from 'wagmi';
12
+ import { useAccount as useWagmiAccount } from 'wagmi';
13
+ import { Dialog } from '../../components/Dialog.js';
14
+ import { PageContainer } from '../../components/PageContainer.js';
15
+ import { useHeader } from '../../hooks/useHeader.js';
16
+ import { useWallets } from '../../hooks/useWallets.js';
17
+ import { useWidgetConfig } from '../../providers/WidgetProvider/WidgetProvider.js';
18
+ import { EVMListItemButton } from './EVMListItemButton.js';
19
+ import { SVMListItemButton } from './SVMListItemButton.js';
20
+
21
+ export const SelectWalletPage = () => {
22
+ const { t } = useTranslation();
23
+ const { chains, walletConfig } = useWidgetConfig();
24
+ const account = useWagmiAccount();
25
+ const [walletIdentity, setWalletIdentity] = useState<{
26
+ show: boolean;
27
+ connector?: Connector;
28
+ }>({ show: false });
29
+
30
+ useHeader(t(`header.selectWallet`));
31
+
32
+ const closeDialog = () => {
33
+ setWalletIdentity((state) => ({
34
+ ...state,
35
+ show: false,
36
+ }));
37
+ };
38
+
39
+ const handleNotInstalled = useCallback(async (connector: Connector) => {
40
+ setWalletIdentity({
41
+ show: true,
42
+ connector,
43
+ });
44
+ }, []);
45
+
46
+ const wallets = useWallets(walletConfig, chains);
47
+
48
+ return (
49
+ <PageContainer disableGutters>
50
+ <List
51
+ sx={{
52
+ paddingTop: 0,
53
+ paddingLeft: 1.5,
54
+ paddingRight: 1.5,
55
+ paddingBottom: 1.5,
56
+ }}
57
+ >
58
+ {wallets?.map((connector) =>
59
+ (connector as Connector).id ? (
60
+ <EVMListItemButton
61
+ key={(connector as Connector).id}
62
+ connector={connector as Connector}
63
+ connectedConnector={account.connector}
64
+ onNotInstalled={handleNotInstalled}
65
+ />
66
+ ) : (
67
+ <SVMListItemButton
68
+ key={(connector as Wallet).adapter.name}
69
+ wallet={connector as Wallet}
70
+ />
71
+ ),
72
+ )}
73
+ </List>
74
+ <Dialog open={walletIdentity.show} onClose={closeDialog}>
75
+ <DialogContent>
76
+ <DialogContentText>
77
+ {t('wallet.extensionNotFound', {
78
+ name: walletIdentity.connector?.name,
79
+ })}
80
+ </DialogContentText>
81
+ </DialogContent>
82
+ <DialogActions>
83
+ <Button variant="contained" onClick={closeDialog} autoFocus>
84
+ {t('button.ok')}
85
+ </Button>
86
+ </DialogActions>
87
+ </Dialog>
88
+ </PageContainer>
89
+ );
90
+ };
@@ -1,5 +1,3 @@
1
- import type { Account } from '@lifi/wallet-management';
2
- import { useAccount } from '@lifi/wallet-management';
3
1
  import {
4
2
  ContentCopyRounded,
5
3
  MoreHoriz,
@@ -14,6 +12,8 @@ import { AccountAvatar } from '../../components/Avatar/AccountAvatar.js';
14
12
  import { ListItem } from '../../components/ListItem/ListItem.js';
15
13
  import { ListItemButton } from '../../components/ListItem/ListItemButton.js';
16
14
  import { Menu } from '../../components/Menu.js';
15
+ import type { Account } from '../../hooks/useAccount.js';
16
+ import { useAccount } from '../../hooks/useAccount.js';
17
17
  import { useExplorer } from '../../hooks/useExplorer.js';
18
18
  import { useHeader } from '../../hooks/useHeader.js';
19
19
  import { useToAddressRequirements } from '../../hooks/useToAddressRequirements.js';
@@ -1,4 +1,3 @@
1
- import { useAccount } from '@lifi/wallet-management';
2
1
  import { Error, History, TurnedIn, Wallet } from '@mui/icons-material';
3
2
  import { Box, Tooltip, Typography } from '@mui/material';
4
3
  import type { ChangeEvent } from 'react';
@@ -8,6 +7,7 @@ import { useNavigate } from 'react-router-dom';
8
7
  import type { BottomSheetBase } from '../../components/BottomSheet/types.js';
9
8
  import { ButtonTertiary } from '../../components/ButtonTertiary.js';
10
9
  import { CardButton } from '../../components/Card/CardButton.js';
10
+ import { useAccount } from '../../hooks/useAccount.js';
11
11
  import {
12
12
  AddressType,
13
13
  useAddressValidation,
@@ -301,7 +301,12 @@ export const StatusBottomSheetContent: React.FC<
301
301
  <Typography py={1}>{secondaryMessage}</Typography>
302
302
  ) : null}
303
303
  {VcComponent ? <VcComponent route={route} /> : null}
304
- <Box mt={2}>
304
+ <Box sx={{ display: 'flex', marginTop: 2, gap: 1.5 }}>
305
+ {hasEnumFlag(status, RouteExecutionStatus.Done) ? (
306
+ <Button variant="text" onClick={handleSeeDetails} fullWidth>
307
+ {t('button.seeDetails')}
308
+ </Button>
309
+ ) : null}
305
310
  <Button variant="contained" fullWidth onClick={handlePrimaryButton}>
306
311
  {status === RouteExecutionStatus.Idle ? t('button.ok') : null}
307
312
  {hasEnumFlag(status, RouteExecutionStatus.Done)
@@ -312,13 +317,6 @@ export const StatusBottomSheetContent: React.FC<
312
317
  : null}
313
318
  </Button>
314
319
  </Box>
315
- {hasEnumFlag(status, RouteExecutionStatus.Done) ? (
316
- <Box mt={2}>
317
- <Button variant="text" onClick={handleSeeDetails} fullWidth>
318
- {t('button.seeDetails')}
319
- </Button>
320
- </Box>
321
- ) : null}
322
320
  </Box>
323
321
  );
324
322
  };
@@ -12,14 +12,14 @@ export type LanguageResource = typeof languages.en;
12
12
 
13
13
  export type LanguageResources =
14
14
  | {
15
- [K in LanguageKey]?: PartialResource<LanguageResource>;
15
+ [language in LanguageKey]?: PartialResource<LanguageResource>;
16
16
  }
17
17
  | {
18
18
  [language: string]: PartialResource<LanguageResource>;
19
19
  };
20
20
 
21
21
  export type LanguageTranslationResource = {
22
- [N in 'translation']: PartialResource<LanguageResource>;
22
+ [namespace in 'translation']: PartialResource<LanguageResource>;
23
23
  };
24
24
 
25
25
  export type LanguageTranslationResources = {