@lifi/widget 3.4.0-beta.5 → 3.4.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 (123) hide show
  1. package/CHANGELOG.md +15 -0
  2. package/_esm/components/AppContainer.d.ts +0 -1
  3. package/_esm/components/AppContainer.js +53 -24
  4. package/_esm/components/AppContainer.js.map +1 -1
  5. package/_esm/components/ChainSelect/useChainSelect.js +10 -2
  6. package/_esm/components/ChainSelect/useChainSelect.js.map +1 -1
  7. package/_esm/components/Header/Header.d.ts +2 -0
  8. package/_esm/components/Header/Header.js +8 -1
  9. package/_esm/components/Header/Header.js.map +1 -1
  10. package/_esm/components/Header/Header.style.d.ts +3 -0
  11. package/_esm/components/Header/Header.style.js +27 -11
  12. package/_esm/components/Header/Header.style.js.map +1 -1
  13. package/_esm/components/Routes/RoutesExpanded.js +3 -3
  14. package/_esm/components/Routes/RoutesExpanded.js.map +1 -1
  15. package/_esm/components/Routes/RoutesExpanded.style.d.ts +8 -1
  16. package/_esm/components/Routes/RoutesExpanded.style.js +22 -5
  17. package/_esm/components/Routes/RoutesExpanded.style.js.map +1 -1
  18. package/_esm/components/TokenList/TokenList.js +1 -3
  19. package/_esm/components/TokenList/TokenList.js.map +1 -1
  20. package/_esm/components/TokenList/types.d.ts +1 -0
  21. package/_esm/components/TokenList/useTokenSelect.js +7 -2
  22. package/_esm/components/TokenList/useTokenSelect.js.map +1 -1
  23. package/_esm/config/coinbase.d.ts +2 -0
  24. package/_esm/config/coinbase.js +6 -0
  25. package/_esm/config/coinbase.js.map +1 -0
  26. package/_esm/config/constants.d.ts +1 -0
  27. package/_esm/config/constants.js +2 -0
  28. package/_esm/config/constants.js.map +1 -0
  29. package/_esm/config/metaMask.d.ts +2 -0
  30. package/_esm/config/metaMask.js +11 -0
  31. package/_esm/config/metaMask.js.map +1 -0
  32. package/_esm/config/version.d.ts +1 -1
  33. package/_esm/config/version.js +1 -1
  34. package/_esm/config/version.js.map +1 -1
  35. package/_esm/config/walletConnect.d.ts +2 -1
  36. package/_esm/config/walletConnect.js +3 -1
  37. package/_esm/config/walletConnect.js.map +1 -1
  38. package/_esm/hooks/{useContentHeight.d.ts → useSetContentHeight.d.ts} +0 -1
  39. package/_esm/hooks/useSetContentHeight.js +19 -0
  40. package/_esm/hooks/useSetContentHeight.js.map +1 -0
  41. package/_esm/hooks/useWallets.d.ts +6 -0
  42. package/_esm/hooks/useWallets.js +80 -0
  43. package/_esm/hooks/useWallets.js.map +1 -0
  44. package/_esm/i18n/en.json +1 -0
  45. package/_esm/index.d.ts +2 -0
  46. package/_esm/index.js +2 -0
  47. package/_esm/index.js.map +1 -1
  48. package/_esm/pages/MainPage/MainPage.js +2 -2
  49. package/_esm/pages/MainPage/MainPage.js.map +1 -1
  50. package/_esm/pages/SelectTokenPage/SelectTokenPage.js +8 -9
  51. package/_esm/pages/SelectTokenPage/SelectTokenPage.js.map +1 -1
  52. package/_esm/pages/SelectTokenPage/useTokenListHeight.d.ts +12 -0
  53. package/_esm/pages/SelectTokenPage/useTokenListHeight.js +70 -0
  54. package/_esm/pages/SelectTokenPage/useTokenListHeight.js.map +1 -0
  55. package/_esm/pages/SelectWalletPage/EVMListItemButton.d.ts +2 -1
  56. package/_esm/pages/SelectWalletPage/EVMListItemButton.js +2 -1
  57. package/_esm/pages/SelectWalletPage/EVMListItemButton.js.map +1 -1
  58. package/_esm/pages/SelectWalletPage/SelectWalletPage.js +7 -44
  59. package/_esm/pages/SelectWalletPage/SelectWalletPage.js.map +1 -1
  60. package/_esm/pages/SendToWallet/BookmarksPage.js +4 -2
  61. package/_esm/pages/SendToWallet/BookmarksPage.js.map +1 -1
  62. package/_esm/pages/SendToWallet/SendToWalletPage.js +6 -4
  63. package/_esm/pages/SendToWallet/SendToWalletPage.js.map +1 -1
  64. package/_esm/pages/SendToWallet/SendToWalletPage.style.d.ts +10 -0
  65. package/_esm/pages/SendToWallet/SendToWalletPage.style.js +17 -5
  66. package/_esm/pages/SendToWallet/SendToWalletPage.style.js.map +1 -1
  67. package/_esm/pages/TransactionDetailsPage/TransactionDetailsPage.js +0 -1
  68. package/_esm/pages/TransactionDetailsPage/TransactionDetailsPage.js.map +1 -1
  69. package/_esm/pages/TransactionPage/ExchangeRateBottomSheet.js +1 -1
  70. package/_esm/pages/TransactionPage/ExchangeRateBottomSheet.js.map +1 -1
  71. package/_esm/pages/TransactionPage/StatusBottomSheet.js +1 -1
  72. package/_esm/pages/TransactionPage/StatusBottomSheet.js.map +1 -1
  73. package/_esm/pages/TransactionPage/TokenValueBottomSheet.js +1 -1
  74. package/_esm/pages/TransactionPage/TokenValueBottomSheet.js.map +1 -1
  75. package/_esm/providers/WalletProvider/EVMBaseProvider.js +7 -9
  76. package/_esm/providers/WalletProvider/EVMBaseProvider.js.map +1 -1
  77. package/_esm/themes/createTheme.js +1 -0
  78. package/_esm/themes/createTheme.js.map +1 -1
  79. package/_esm/themes/types.d.ts +2 -0
  80. package/_esm/types/widget.d.ts +19 -14
  81. package/_esm/types/widget.js.map +1 -1
  82. package/components/AppContainer.tsx +70 -24
  83. package/components/ChainSelect/useChainSelect.ts +11 -3
  84. package/components/Header/Header.style.ts +28 -11
  85. package/components/Header/Header.tsx +11 -0
  86. package/components/Routes/RoutesExpanded.style.ts +30 -5
  87. package/components/Routes/RoutesExpanded.tsx +12 -5
  88. package/components/TokenList/TokenList.tsx +1 -2
  89. package/components/TokenList/types.ts +1 -0
  90. package/components/TokenList/useTokenSelect.ts +8 -2
  91. package/config/coinbase.ts +7 -0
  92. package/config/constants.ts +1 -0
  93. package/config/metaMask.ts +13 -0
  94. package/config/version.ts +1 -1
  95. package/config/walletConnect.ts +5 -1
  96. package/hooks/useSetContentHeight.ts +24 -0
  97. package/hooks/useWallets.ts +147 -0
  98. package/i18n/en.json +1 -0
  99. package/index.ts +2 -0
  100. package/package.json +11 -11
  101. package/pages/MainPage/MainPage.tsx +3 -2
  102. package/pages/SelectTokenPage/SelectTokenPage.tsx +16 -20
  103. package/pages/SelectTokenPage/useTokenListHeight.ts +112 -0
  104. package/pages/SelectWalletPage/EVMListItemButton.tsx +16 -7
  105. package/pages/SelectWalletPage/SelectWalletPage.tsx +7 -65
  106. package/pages/SendToWallet/BookmarksPage.tsx +12 -6
  107. package/pages/SendToWallet/SendToWalletPage.style.tsx +25 -5
  108. package/pages/SendToWallet/SendToWalletPage.tsx +42 -33
  109. package/pages/TransactionDetailsPage/TransactionDetailsPage.tsx +0 -1
  110. package/pages/TransactionPage/ExchangeRateBottomSheet.tsx +1 -1
  111. package/pages/TransactionPage/StatusBottomSheet.tsx +1 -1
  112. package/pages/TransactionPage/TokenValueBottomSheet.tsx +1 -1
  113. package/providers/WalletProvider/EVMBaseProvider.tsx +7 -9
  114. package/themes/createTheme.ts +1 -0
  115. package/themes/types.ts +2 -0
  116. package/types/widget.ts +23 -13
  117. package/_esm/hooks/useContentHeight.js +0 -40
  118. package/_esm/hooks/useContentHeight.js.map +0 -1
  119. package/_esm/pages/SelectWalletPage/utils.d.ts +0 -3
  120. package/_esm/pages/SelectWalletPage/utils.js +0 -18
  121. package/_esm/pages/SelectWalletPage/utils.js.map +0 -1
  122. package/hooks/useContentHeight.ts +0 -53
  123. package/pages/SelectWalletPage/utils.ts +0 -26
@@ -1,60 +1,105 @@
1
1
  import { Box, Container, ScopedCssBaseline, styled } from '@mui/material';
2
2
  import type { PropsWithChildren } from 'react';
3
+ import {
4
+ maxHeaderHeight,
5
+ minHeaderHeight,
6
+ } from '../components/Header/Header.js';
7
+ import { defaultMaxHeight } from '../config/constants.js';
3
8
  import { useWidgetConfig } from '../providers/WidgetProvider/WidgetProvider.js';
4
9
  import type { WidgetVariant } from '../types/widget.js';
5
10
  import { ElementId, createElementId } from '../utils/elements.js';
6
11
 
7
- export const maxHeight = 682;
8
-
9
12
  export const AppExpandedContainer = styled(Box, {
10
13
  shouldForwardProp: (prop) => prop !== 'variant',
11
- })<{ variant?: WidgetVariant }>(({ variant }) => ({
14
+ })<{ variant?: WidgetVariant }>(({ theme, variant }) => ({
12
15
  display: 'flex',
13
16
  justifyContent: 'center',
14
17
  alignItems: 'start',
15
18
  flex: 1,
16
- height: variant === 'drawer' ? 'none' : maxHeight,
19
+ height:
20
+ variant === 'drawer'
21
+ ? 'none'
22
+ : theme.container?.display === 'flex'
23
+ ? '100%'
24
+ : theme.container?.maxHeight
25
+ ? 'auto'
26
+ : theme.container?.height || 'auto',
17
27
  }));
18
28
 
19
29
  export const RelativeContainer = styled(Box, {
20
30
  shouldForwardProp: (prop) => prop !== 'variant',
21
- })<{ variant?: WidgetVariant }>(({ theme, variant }) => ({
22
- position: 'relative',
23
- boxSizing: 'content-box',
24
- width: '100%',
25
- minWidth: theme.breakpoints.values.xs,
26
- maxWidth: theme.breakpoints.values.sm,
27
- maxHeight: variant === 'drawer' ? 'none' : maxHeight,
28
- background: theme.palette.background.default,
29
- overflow: 'auto',
30
- flex: 1,
31
- zIndex: 0,
32
- ...theme.container,
33
- }));
31
+ })<{ variant?: WidgetVariant }>(({ theme, variant }) => {
32
+ const container = { ...theme.container };
33
+
34
+ if (variant === 'drawer') {
35
+ container.height = '100%';
36
+ }
37
+
38
+ return {
39
+ position: 'relative',
40
+ boxSizing: 'content-box',
41
+ width: '100%',
42
+ minWidth: theme.breakpoints.values.xs,
43
+ maxWidth: theme.breakpoints.values.sm,
44
+ background: theme.palette.background.default,
45
+ overflow: 'auto',
46
+ flex: 1,
47
+ zIndex: 0,
48
+ ...container,
49
+ maxHeight:
50
+ variant === 'drawer'
51
+ ? 'none'
52
+ : theme.container?.display === 'flex' && !theme.container?.height
53
+ ? '100%'
54
+ : theme.container?.maxHeight
55
+ ? theme.container?.maxHeight
56
+ : theme.container?.height || defaultMaxHeight,
57
+ };
58
+ });
59
+
60
+ interface CssBaselineContainerProps {
61
+ variant?: WidgetVariant;
62
+ paddingTopAdjustment: number;
63
+ }
34
64
 
35
65
  const CssBaselineContainer = styled(ScopedCssBaseline, {
36
- shouldForwardProp: (prop) => prop !== 'variant',
37
- })<{ variant?: WidgetVariant }>(({ variant }) => ({
66
+ shouldForwardProp: (prop) =>
67
+ !['variant', 'paddingTopAdjustment'].includes(prop as string),
68
+ })<CssBaselineContainerProps>(({ theme, variant, paddingTopAdjustment }) => ({
38
69
  display: 'flex',
39
70
  flex: 1,
40
71
  flexDirection: 'column',
41
72
  overflowX: 'clip',
42
73
  margin: 0,
43
74
  width: '100%',
44
- maxHeight: variant === 'drawer' ? 'none' : maxHeight,
75
+ maxHeight:
76
+ variant === 'drawer' || theme.container?.display === 'flex'
77
+ ? 'none'
78
+ : theme.container?.maxHeight
79
+ ? theme.container?.maxHeight
80
+ : theme.container?.height || defaultMaxHeight,
45
81
  overflowY: 'auto',
46
- height: '100%',
82
+ height: theme.container?.display === 'flex' ? 'auto' : '100%',
83
+ paddingTop: paddingTopAdjustment,
47
84
  }));
48
85
 
49
- export const FlexContainer = styled(Container)({
86
+ export const FlexContainer = styled(Container)(({ theme }) => ({
50
87
  display: 'flex',
51
88
  flexDirection: 'column',
52
89
  flex: 1,
53
- });
90
+ }));
54
91
 
55
92
  export const AppContainer: React.FC<PropsWithChildren<{}>> = ({ children }) => {
56
93
  // const ref = useRef<HTMLDivElement>(null);
57
- const { variant, elementId } = useWidgetConfig();
94
+ const { variant, elementId, hiddenUI, theme } = useWidgetConfig();
95
+
96
+ const positionFixedAdjustment =
97
+ theme?.header?.position === 'fixed'
98
+ ? hiddenUI?.includes('walletMenu')
99
+ ? minHeaderHeight
100
+ : maxHeaderHeight
101
+ : 0;
102
+
58
103
  return (
59
104
  <RelativeContainer
60
105
  variant={variant}
@@ -64,6 +109,7 @@ export const AppContainer: React.FC<PropsWithChildren<{}>> = ({ children }) => {
64
109
  id={createElementId(ElementId.ScrollableContainer, elementId)}
65
110
  variant={variant}
66
111
  enableColorScheme
112
+ paddingTopAdjustment={positionFixedAdjustment}
67
113
  // ref={ref}
68
114
  >
69
115
  <FlexContainer disableGutters>{children}</FlexContainer>
@@ -2,16 +2,18 @@ import type { EVMChain } from '@lifi/sdk';
2
2
  import { useChains } from '../../hooks/useChains.js';
3
3
  import { useSwapOnly } from '../../hooks/useSwapOnly.js';
4
4
  import { useToAddressReset } from '../../hooks/useToAddressReset.js';
5
+ import { useWidgetConfig } from '../../providers/WidgetProvider/WidgetProvider.js';
5
6
  import { useChainOrder } from '../../stores/chains/useChainOrder.js';
6
7
  import type { FormType } from '../../stores/form/types.js';
7
8
  import { FormKeyHelper } from '../../stores/form/types.js';
8
9
  import { useFieldActions } from '../../stores/form/useFieldActions.js';
9
10
  import { useFieldController } from '../../stores/form/useFieldController.js';
11
+ import type { DisabledUI } from '../../types/widget.js';
10
12
 
11
13
  export const useChainSelect = (formType: FormType) => {
14
+ const { disabledUI } = useWidgetConfig();
12
15
  const chainKey = FormKeyHelper.getChainKey(formType);
13
16
  const { onChange } = useFieldController({ name: chainKey });
14
-
15
17
  const { setFieldValue, getFieldValues } = useFieldActions();
16
18
  const { chains, isLoading, getChainById } = useChains(formType);
17
19
  const [chainOrder, setChainOrder] = useChainOrder(formType);
@@ -35,8 +37,14 @@ export const useChainSelect = (formType: FormType) => {
35
37
  isTouched: true,
36
38
  });
37
39
  }
38
- setFieldValue(FormKeyHelper.getTokenKey(formType), '');
39
- setFieldValue(FormKeyHelper.getAmountKey(formType), '');
40
+ const tokenKey = FormKeyHelper.getTokenKey(formType);
41
+ if (!disabledUI?.includes(tokenKey as DisabledUI)) {
42
+ setFieldValue(tokenKey, '');
43
+ }
44
+ const amountKey = FormKeyHelper.getAmountKey(formType);
45
+ if (!disabledUI?.includes(amountKey as DisabledUI)) {
46
+ setFieldValue(amountKey, '');
47
+ }
40
48
  setFieldValue('tokenSearchFilter', '');
41
49
 
42
50
  const [toChainId] = getFieldValues('toChain');
@@ -20,17 +20,34 @@ export const HeaderAppBar = styled(AppBar)(({ theme }) => ({
20
20
 
21
21
  export const Container = styled(Box, {
22
22
  shouldForwardProp: (prop) => prop !== 'sticky',
23
- })<{ sticky?: boolean }>(({ theme, sticky }) => ({
24
- display: 'flex',
25
- flexDirection: 'column',
26
- backgroundColor: theme.palette.background.default,
27
- backdropFilter: 'blur(12px)',
28
- position: sticky ? 'sticky' : 'relative',
29
- top: 0,
30
- zIndex: 1200,
31
- gap: theme.spacing(0.5),
32
- padding: theme.spacing(1.5, 3, 1.5, 3),
33
- }));
23
+ })<{ sticky?: boolean }>(({ theme, sticky }) => {
24
+ return {
25
+ display: 'flex',
26
+ flexDirection: 'column',
27
+ backgroundColor: theme.palette.background.default,
28
+ backdropFilter: 'blur(12px)',
29
+ position: sticky ? 'sticky' : 'relative',
30
+ top: 0,
31
+ zIndex: 1200,
32
+ gap: theme.spacing(0.5),
33
+ padding: theme.spacing(1.5, 3, 1.5, 3),
34
+ overflow: 'auto',
35
+ ...theme.header,
36
+ ...(theme.header?.position === 'fixed'
37
+ ? {
38
+ minWidth: theme.breakpoints.values.xs,
39
+ maxWidth: theme.breakpoints.values.sm,
40
+ width: '100%',
41
+ }
42
+ : {}),
43
+ };
44
+ });
45
+
46
+ export const ContainerPlaceholder = styled(Box)(({ theme }) => {
47
+ return {
48
+ ...(theme.header?.position === 'fixed' ? {} : { display: 'none' }),
49
+ };
50
+ });
34
51
 
35
52
  export const WalletButton = styled(Button, {
36
53
  shouldForwardProp: (prop) => prop !== 'subvariant',
@@ -1,19 +1,30 @@
1
1
  import type { FC, PropsWithChildren } from 'react';
2
2
  import { useLocation } from 'react-router-dom';
3
3
  import { useDefaultElementId } from '../../hooks/useDefaultElementId.js';
4
+ import { useWidgetConfig } from '../../providers/WidgetProvider/WidgetProvider.js';
4
5
  import { ElementId, createElementId } from '../../utils/elements.js';
5
6
  import { stickyHeaderRoutes } from '../../utils/navigationRoutes.js';
6
7
  import { Container } from './Header.style.js';
7
8
  import { NavigationHeader } from './NavigationHeader.js';
8
9
  import { WalletHeader } from './WalletHeader.js';
9
10
 
11
+ export const minHeaderHeight = 64;
12
+ export const maxHeaderHeight = 108;
13
+
10
14
  export const HeaderContainer: FC<PropsWithChildren<{}>> = ({ children }) => {
11
15
  const { pathname } = useLocation();
12
16
  const elementId = useDefaultElementId();
17
+ const { hiddenUI } = useWidgetConfig();
18
+
19
+ const headerHeight = hiddenUI?.includes('walletMenu')
20
+ ? minHeaderHeight
21
+ : maxHeaderHeight;
22
+
13
23
  return (
14
24
  <Container
15
25
  id={createElementId(ElementId.Header, elementId)}
16
26
  sticky={stickyHeaderRoutes.some((route) => pathname.includes(route))}
27
+ maxHeight={headerHeight}
17
28
  >
18
29
  {children}
19
30
  </Container>
@@ -1,9 +1,20 @@
1
- import { Box, ScopedCssBaseline, styled } from '@mui/material';
2
- import { maxHeight } from '../AppContainer.js';
1
+ import type { ScopedCssBaselineProps } from '@mui/material';
2
+ import { Box, Collapse, Grow, ScopedCssBaseline, styled } from '@mui/material';
3
+ import { defaultMaxHeight } from '../../config/constants.js';
3
4
 
4
5
  export const CollapseContainer = styled(Box)(({ theme }) => ({
5
- height: maxHeight,
6
6
  zIndex: 0,
7
+ ...(theme.container.display === 'flex'
8
+ ? { display: 'flex', maxHeight: '100%' }
9
+ : { height: 'auto' }),
10
+ }));
11
+
12
+ export const RoutesExpandedCollapse = styled(Collapse)(({ theme }) => ({
13
+ ...(theme.container?.display === 'flex' ? { height: '100%' } : {}),
14
+ }));
15
+
16
+ export const RouteTopLevelGrow = styled(Grow)(({ theme }) => ({
17
+ ...(theme.container?.display === 'flex' ? { height: '100%' } : {}),
7
18
  }));
8
19
 
9
20
  export const ScrollableContainer = styled(Box)({
@@ -15,14 +26,28 @@ export const ScrollableContainer = styled(Box)({
15
26
  flexDirection: 'column',
16
27
  });
17
28
 
18
- export const Container = styled(ScopedCssBaseline)(({ theme }) => ({
29
+ interface ContainerProps extends ScopedCssBaselineProps {
30
+ minimumHeight: boolean;
31
+ }
32
+
33
+ export const Container = styled(ScopedCssBaseline, {
34
+ shouldForwardProp: (prop) => !['minimumHeight'].includes(prop as string),
35
+ })<ContainerProps>(({ theme, minimumHeight }) => ({
19
36
  backgroundColor: theme.palette.background.default,
20
37
  overflow: 'auto',
21
38
  width: 436,
22
- maxHeight,
23
39
  marginLeft: theme.spacing(3),
24
40
  display: 'flex',
25
41
  flexDirection: 'column',
42
+ ...(theme.container?.display !== 'flex'
43
+ ? {
44
+ maxHeight:
45
+ theme.container?.maxHeight ??
46
+ theme.container?.height ??
47
+ defaultMaxHeight,
48
+ ...(minimumHeight ? { '&': { height: 'auto' } } : {}),
49
+ }
50
+ : { height: minimumHeight ? 'auto' : '100%' }),
26
51
  ...theme.container,
27
52
  }));
28
53
 
@@ -22,6 +22,8 @@ import {
22
22
  CollapseContainer,
23
23
  Container,
24
24
  Header,
25
+ RouteTopLevelGrow,
26
+ RoutesExpandedCollapse,
25
27
  ScrollableContainer,
26
28
  } from './RoutesExpanded.style.js';
27
29
 
@@ -45,11 +47,16 @@ export const RoutesExpanded = () => {
45
47
  return (
46
48
  <CollapseContainer>
47
49
  <Collapse timeout={timeout} in={match} orientation="horizontal">
48
- <Grow timeout={timeout} in={match} mountOnEnter unmountOnExit>
50
+ <RouteTopLevelGrow
51
+ timeout={timeout}
52
+ in={match}
53
+ mountOnEnter
54
+ unmountOnExit
55
+ >
49
56
  <div>
50
57
  <RoutesExpandedElement />
51
58
  </div>
52
- </Grow>
59
+ </RouteTopLevelGrow>
53
60
  </Collapse>
54
61
  </CollapseContainer>
55
62
  );
@@ -112,14 +119,14 @@ export const RoutesExpandedElement = () => {
112
119
  }, [emitter, expanded]);
113
120
 
114
121
  return (
115
- <Collapse
122
+ <RoutesExpandedCollapse
116
123
  timeout={timeout.enter}
117
124
  in={expanded}
118
125
  orientation="horizontal"
119
126
  onExited={onExit}
120
127
  >
121
128
  <Grow timeout={timeout.enter} in={expanded} mountOnEnter unmountOnExit>
122
- <Container enableColorScheme>
129
+ <Container enableColorScheme minimumHeight={isLoading}>
123
130
  <ScrollableContainer>
124
131
  <Header>
125
132
  <Typography fontSize={18} fontWeight="700" flex={1} noWrap>
@@ -163,6 +170,6 @@ export const RoutesExpandedElement = () => {
163
170
  </ScrollableContainer>
164
171
  </Container>
165
172
  </Grow>
166
- </Collapse>
173
+ </RoutesExpandedCollapse>
167
174
  );
168
175
  };
@@ -1,6 +1,5 @@
1
1
  import { Box } from '@mui/material';
2
2
  import type { FC } from 'react';
3
- import { useRef } from 'react';
4
3
  import { useAccount } from '../../hooks/useAccount.js';
5
4
  import { useChain } from '../../hooks/useChain.js';
6
5
  import { useDebouncedWatch } from '../../hooks/useDebouncedWatch.js';
@@ -17,10 +16,10 @@ import { filteredTokensComparator } from './utils.js';
17
16
 
18
17
  export const TokenList: FC<TokenListProps> = ({
19
18
  formType,
19
+ parentRef,
20
20
  height,
21
21
  onClick,
22
22
  }) => {
23
- const parentRef = useRef<HTMLUListElement | null>(null);
24
23
  const [selectedChainId] = useFieldValues(FormKeyHelper.getChainKey(formType));
25
24
  const [tokenSearchFilter]: string[] = useDebouncedWatch(
26
25
  320,
@@ -5,6 +5,7 @@ import type { FormType } from '../../stores/form/types.js';
5
5
  import type { TokenAmount } from '../../types/token.js';
6
6
 
7
7
  export interface TokenListProps {
8
+ parentRef: MutableRefObject<HTMLElement | null>;
8
9
  formType: FormType;
9
10
  height: number;
10
11
  onClick?(): void;
@@ -7,9 +7,10 @@ import { FormKeyHelper } from '../../stores/form/types.js';
7
7
  import { useFieldActions } from '../../stores/form/useFieldActions.js';
8
8
  import { useFieldController } from '../../stores/form/useFieldController.js';
9
9
  import { WidgetEvent } from '../../types/events.js';
10
+ import type { DisabledUI } from '../../types/widget.js';
10
11
 
11
12
  export const useTokenSelect = (formType: FormType, onClick?: () => void) => {
12
- const { subvariant } = useWidgetConfig();
13
+ const { subvariant, disabledUI } = useWidgetConfig();
13
14
  const emitter = useWidgetEvents();
14
15
  const { setFieldValue, getFieldValues } = useFieldActions();
15
16
  const tokenKey = FormKeyHelper.getTokenKey(formType);
@@ -26,12 +27,16 @@ export const useTokenSelect = (formType: FormType, onClick?: () => void) => {
26
27
  isDirty: true,
27
28
  isTouched: true,
28
29
  });
29
- setFieldValue(FormKeyHelper.getAmountKey(formType), '');
30
+ const amountKey = FormKeyHelper.getAmountKey(formType);
31
+ if (!disabledUI?.includes(amountKey as DisabledUI)) {
32
+ setFieldValue(amountKey, '');
33
+ }
30
34
  const oppositeFormType = formType === 'from' ? 'to' : 'from';
31
35
  const [selectedOppositeToken, selectedOppositeChainId] = getFieldValues(
32
36
  FormKeyHelper.getTokenKey(oppositeFormType),
33
37
  FormKeyHelper.getChainKey(oppositeFormType),
34
38
  );
39
+ // TODO: remove when we enable same chain/token transfers
35
40
  if (
36
41
  selectedOppositeToken === tokenAddress &&
37
42
  selectedOppositeChainId === selectedChainId &&
@@ -73,6 +78,7 @@ export const useTokenSelect = (formType: FormType, onClick?: () => void) => {
73
78
  },
74
79
  [
75
80
  chainOrderStore,
81
+ disabledUI,
76
82
  emitter,
77
83
  formType,
78
84
  getFieldValues,
@@ -0,0 +1,7 @@
1
+ import type { CoinbaseWalletParameters } from 'wagmi/connectors';
2
+ import { LiFiToolLogo } from '../icons/lifi.js';
3
+
4
+ export const defaultCoinbaseConfig: CoinbaseWalletParameters = {
5
+ appName: 'LI.FI',
6
+ appLogoUrl: LiFiToolLogo,
7
+ };
@@ -0,0 +1 @@
1
+ export const defaultMaxHeight = 682;
@@ -0,0 +1,13 @@
1
+ import type { MetaMaskParameters } from 'wagmi/connectors';
2
+ import { LiFiToolLogo } from '../icons/lifi.js';
3
+
4
+ export const defaultMetaMaskConfig: MetaMaskParameters = {
5
+ dappMetadata: {
6
+ name: 'LI.FI',
7
+ url:
8
+ typeof window !== 'undefined'
9
+ ? (window as any)?.location.href
10
+ : 'https://li.fi/',
11
+ base64Icon: LiFiToolLogo,
12
+ },
13
+ };
package/config/version.ts CHANGED
@@ -1,2 +1,2 @@
1
1
  export const name = '@lifi/widget';
2
- export const version = '3.4.0-beta.5';
2
+ export const version = '3.4.0';
@@ -1 +1,5 @@
1
- export const defaultWalletConnectProjectId = '5432e3507d41270bee46b7b85bbc2ef8';
1
+ import type { WalletConnectParameters } from 'wagmi/connectors';
2
+
3
+ export const defaultWalletConnectConfig: WalletConnectParameters = {
4
+ projectId: '5432e3507d41270bee46b7b85bbc2ef8',
5
+ };
@@ -0,0 +1,24 @@
1
+ import type { MutableRefObject } from 'react';
2
+ import { useLayoutEffect } from 'react';
3
+ import { useDefaultElementId } from './useDefaultElementId.js';
4
+ import { getScrollableContainer } from './useScrollableContainer.js';
5
+
6
+ export const useSetContentHeight = (
7
+ ref: MutableRefObject<HTMLElement | undefined>,
8
+ ) => {
9
+ const elementId = useDefaultElementId();
10
+ useLayoutEffect(() => {
11
+ const scrollableContainer = getScrollableContainer(elementId);
12
+ if (
13
+ !scrollableContainer ||
14
+ !ref.current ||
15
+ ref.current?.clientHeight <= scrollableContainer?.clientHeight
16
+ ) {
17
+ return;
18
+ }
19
+ scrollableContainer.style.height = `${ref.current.clientHeight}px`;
20
+ return () => {
21
+ scrollableContainer.style.removeProperty('height');
22
+ };
23
+ }, [elementId, ref]);
24
+ };
@@ -0,0 +1,147 @@
1
+ import { ChainType } from '@lifi/sdk';
2
+ import type { CreateConnectorFnExtended } from '@lifi/wallet-management';
3
+ import {
4
+ createCoinbaseConnector,
5
+ createMetaMaskConnector,
6
+ createWalletConnectConnector,
7
+ getWalletPriority,
8
+ isWalletInstalled,
9
+ } from '@lifi/wallet-management';
10
+ import type { Theme } from '@mui/material';
11
+ import { useMediaQuery } from '@mui/material';
12
+ import { WalletReadyState } from '@solana/wallet-adapter-base';
13
+ import type { Wallet } from '@solana/wallet-adapter-react';
14
+ import { useWallet } from '@solana/wallet-adapter-react';
15
+ import { useMemo } from 'react';
16
+ import type { Connector } from 'wagmi';
17
+ import { useConnect, useAccount as useWagmiAccount } from 'wagmi';
18
+ import { defaultCoinbaseConfig } from '../config/coinbase.js';
19
+ import { defaultMetaMaskConfig } from '../config/metaMask.js';
20
+ import { defaultWalletConnectConfig } from '../config/walletConnect.js';
21
+ import type { WidgetChains, WidgetWalletConfig } from '../types/widget.js';
22
+ import { isItemAllowed } from '../utils/item.js';
23
+
24
+ export const useWallets = (
25
+ walletConfig?: WidgetWalletConfig,
26
+ chains?: WidgetChains,
27
+ ) => {
28
+ const account = useWagmiAccount();
29
+ const { connectors } = useConnect();
30
+ const { wallets: solanaWallets } = useWallet();
31
+
32
+ const isDesktopView = useMediaQuery((theme: Theme) =>
33
+ theme.breakpoints.up('sm'),
34
+ );
35
+
36
+ const wallets = useMemo(() => {
37
+ const evmConnectors: (CreateConnectorFnExtended | Connector)[] =
38
+ Array.from(connectors);
39
+ if (
40
+ !connectors.some((connector) =>
41
+ connector.id.toLowerCase().includes('walletconnect'),
42
+ )
43
+ ) {
44
+ evmConnectors.unshift(
45
+ createWalletConnectConnector(
46
+ walletConfig?.walletConnect ?? defaultWalletConnectConfig,
47
+ ),
48
+ );
49
+ }
50
+ if (
51
+ !connectors.some((connector) =>
52
+ connector.id.toLowerCase().includes('coinbase'),
53
+ ) &&
54
+ !isWalletInstalled('coinbase')
55
+ ) {
56
+ evmConnectors.unshift(
57
+ createCoinbaseConnector(
58
+ walletConfig?.coinbase ?? defaultCoinbaseConfig,
59
+ ),
60
+ );
61
+ }
62
+ if (
63
+ !connectors.some((connector) =>
64
+ connector.id.toLowerCase().includes('metamask'),
65
+ ) &&
66
+ !isWalletInstalled('metaMask')
67
+ ) {
68
+ evmConnectors.unshift(
69
+ createMetaMaskConnector(
70
+ walletConfig?.metaMask ?? defaultMetaMaskConfig,
71
+ ),
72
+ );
73
+ }
74
+ const evmInstalled = isItemAllowed(ChainType.EVM, chains?.types)
75
+ ? evmConnectors.filter(
76
+ (connector) =>
77
+ isWalletInstalled(connector.id!) &&
78
+ // We should not show already connected connectors
79
+ account.connector?.id !== connector.id,
80
+ )
81
+ : [];
82
+ const evmNotDetected = isItemAllowed(ChainType.EVM, chains?.types)
83
+ ? evmConnectors.filter((connector) => !isWalletInstalled(connector.id!))
84
+ : [];
85
+ const svmInstalled = isItemAllowed(ChainType.SVM, chains?.types)
86
+ ? solanaWallets?.filter(
87
+ (connector) =>
88
+ connector.adapter.readyState === WalletReadyState.Installed &&
89
+ // We should not show already connected connectors
90
+ !connector.adapter.connected,
91
+ )
92
+ : [];
93
+ const svmNotDetected = isItemAllowed(ChainType.SVM, chains?.types)
94
+ ? solanaWallets?.filter(
95
+ (connector) =>
96
+ connector.adapter.readyState !== WalletReadyState.Installed,
97
+ )
98
+ : [];
99
+
100
+ const installedWallets = [...evmInstalled, ...svmInstalled].sort(
101
+ walletComparator,
102
+ );
103
+
104
+ if (isDesktopView) {
105
+ const notDetectedWallets = [...evmNotDetected, ...svmNotDetected].sort(
106
+ walletComparator,
107
+ );
108
+ installedWallets.push(...notDetectedWallets);
109
+ }
110
+
111
+ return installedWallets;
112
+ }, [
113
+ account.connector?.id,
114
+ chains?.types,
115
+ connectors,
116
+ isDesktopView,
117
+ solanaWallets,
118
+ walletConfig?.coinbase,
119
+ walletConfig?.metaMask,
120
+ walletConfig?.walletConnect,
121
+ ]);
122
+
123
+ return wallets;
124
+ };
125
+
126
+ export const walletComparator = (
127
+ a: CreateConnectorFnExtended | Connector | Wallet,
128
+ b: CreateConnectorFnExtended | Connector | Wallet,
129
+ ) => {
130
+ let aId = (a as Connector).id || (a as Wallet).adapter?.name;
131
+ let bId = (b as Connector).id || (b as Wallet).adapter?.name;
132
+
133
+ const priorityA = getWalletPriority(aId);
134
+ const priorityB = getWalletPriority(bId);
135
+
136
+ if (priorityA !== priorityB) {
137
+ return priorityA - priorityB;
138
+ }
139
+
140
+ if (aId < bId) {
141
+ return -1;
142
+ }
143
+ if (aId > bId) {
144
+ return 1;
145
+ }
146
+ return 0;
147
+ };
package/i18n/en.json CHANGED
@@ -53,6 +53,7 @@
53
53
  "bookmarkedWallets": "Bookmarked wallets",
54
54
  "bridge": "Bridge",
55
55
  "checkout": "Checkout",
56
+ "deposit": "Deposit",
56
57
  "exchange": "Exchange",
57
58
  "from": "Exchange from",
58
59
  "gas": "Gas",
package/index.ts CHANGED
@@ -6,9 +6,11 @@ export * from './components/ContractComponent/NFT/NFT.js';
6
6
  export * from './components/ContractComponent/NFT/NFTBase.js';
7
7
  export * from './components/ContractComponent/NFT/types.js';
8
8
  export * from './components/Skeleton/WidgetSkeleton.js';
9
+ export { defaultMaxHeight } from './config/constants.js';
9
10
  export * from './config/version.js';
10
11
  export { useAccount } from './hooks/useAccount.js';
11
12
  export { useAvailableChains } from './hooks/useAvailableChains.js';
13
+ export { useWallets, walletComparator } from './hooks/useWallets.js';
12
14
  export { useWidgetEvents, widgetEvents } from './hooks/useWidgetEvents.js';
13
15
  export * from './stores/form/types.js';
14
16
  export { useFieldActions } from './stores/form/useFieldActions.js';