@gluwa/connect-kit 0.2.0-next.1 → 0.2.0-next.10

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 (99) hide show
  1. package/CHANGELOG.md +62 -0
  2. package/assets/fonts/Inter-Medium.ttf +0 -0
  3. package/assets/fonts/Inter-Medium.woff2 +0 -0
  4. package/assets/fonts/Inter-Regular.ttf +0 -0
  5. package/assets/fonts/Inter-Regular.woff2 +0 -0
  6. package/assets/fonts/Inter-SemiBold.ttf +0 -0
  7. package/assets/fonts/Inter-SemiBold.woff2 +0 -0
  8. package/assets/graphic.png +0 -0
  9. package/assets/metamask.png +0 -0
  10. package/assets/penguinwallet.png +0 -0
  11. package/assets/wc-logo.svg +3 -0
  12. package/assets/wc-search.png +0 -0
  13. package/dist/chunk-VE5LB7BN.js +405 -0
  14. package/dist/credit-connect.js +2 -409
  15. package/dist/index.css +1903 -389
  16. package/dist/index.d.ts +21 -10
  17. package/dist/index.js +1507 -922
  18. package/dist/package.json +7 -6
  19. package/package.json +8 -8
  20. package/src/ConnectKitProvider.tsx +97 -65
  21. package/src/api/asset.ts +10 -0
  22. package/src/assets.d.ts +5 -0
  23. package/src/components/actionItem/index.tsx +50 -0
  24. package/src/components/actionItem/style.scss +47 -0
  25. package/src/components/copyLink/index.tsx +16 -0
  26. package/src/components/copyLink/style.scss +16 -0
  27. package/src/components/qrArea/index.tsx +72 -0
  28. package/src/components/qrArea/style.scss +122 -0
  29. package/src/components/searchBar/asset/Search.tsx +20 -0
  30. package/src/components/searchBar/asset/XMarkCircle.tsx +24 -0
  31. package/src/components/searchBar/index.tsx +44 -0
  32. package/src/components/searchBar/style.scss +58 -0
  33. package/src/components/toast/index.tsx +41 -0
  34. package/src/components/toast/style.scss +108 -0
  35. package/src/components/toggle/index.tsx +27 -0
  36. package/src/components/toggle/style.scss +53 -0
  37. package/src/components/walletGrid/index.tsx +64 -0
  38. package/src/components/walletGrid/style.scss +108 -0
  39. package/src/components/walletItem/index.tsx +49 -0
  40. package/src/components/walletItem/style.scss +70 -0
  41. package/src/connector-meta.ts +16 -11
  42. package/src/core/config.ts +20 -1
  43. package/src/creditConnectConnector.ts +23 -25
  44. package/src/events/account.ts +30 -3
  45. package/src/hooks/useConnectBanner.ts +79 -0
  46. package/src/hooks/useConnectTimeout.ts +92 -0
  47. package/src/hooks/useMetaMaskExtension.ts +29 -0
  48. package/src/hooks/useWCState.ts +21 -5
  49. package/src/hooks/useWagmiConnect.ts +35 -9
  50. package/src/index.ts +5 -2
  51. package/src/layout/allWallets/index.tsx +52 -0
  52. package/src/layout/allWallets/style.scss +57 -0
  53. package/src/layout/connectDialog/asset/backIcon.tsx +24 -0
  54. package/src/layout/connectDialog/asset/checkIcon.tsx +28 -0
  55. package/src/layout/connectDialog/asset/closeIcon.tsx +21 -0
  56. package/src/layout/connectDialog/asset/copyIcon.tsx +28 -0
  57. package/src/layout/connectDialog/asset/linkIcon.tsx +24 -0
  58. package/src/layout/connectDialog/asset/spinner.tsx +21 -0
  59. package/src/layout/connectDialog/asset/warningIcon.tsx +21 -0
  60. package/src/layout/connectDialog/idle/assets/banner-placeholder.png +0 -0
  61. package/src/layout/connectDialog/idle/index.tsx +55 -0
  62. package/src/layout/connectDialog/idle/style.scss +52 -0
  63. package/src/layout/connectDialog/index.tsx +432 -0
  64. package/src/layout/connectDialog/loading/index.tsx +13 -0
  65. package/src/layout/connectDialog/loading/style.scss +19 -0
  66. package/src/layout/connectDialog/metaMask/index.tsx +61 -0
  67. package/src/layout/connectDialog/metaMask/style.scss +65 -0
  68. package/src/layout/connectDialog/qr/index.tsx +33 -0
  69. package/src/layout/connectDialog/style.scss +48 -0
  70. package/src/layout/connectDialog/timeout/index.tsx +31 -0
  71. package/src/layout/connectDialog/timeout/style.scss +64 -0
  72. package/src/layout/connectDialog/walletConnect/index.tsx +45 -0
  73. package/src/layout/connectDialog/walletConnect/style.scss +48 -0
  74. package/src/layout/connectDialog/walletQR/index.tsx +37 -0
  75. package/src/layout/detailPanel/index.tsx +175 -0
  76. package/src/layout/detailPanel/style.scss +70 -0
  77. package/src/layout/selectorPanel/index.tsx +100 -0
  78. package/src/layout/selectorPanel/style.scss +113 -0
  79. package/src/style/color.scss +417 -0
  80. package/src/style/font.scss +28 -0
  81. package/src/style/index.scss +5 -0
  82. package/src/style/mixin.scss +217 -0
  83. package/src/style/reset.scss +110 -0
  84. package/src/style/variables.scss +13 -0
  85. package/src/types.ts +32 -8
  86. package/src/utils/platform.ts +5 -3
  87. package/src/wallet-display-override.ts +15 -0
  88. package/tsconfig.json +5 -1
  89. package/tsup.config.ts +32 -2
  90. package/assets/creditwallet.png +0 -0
  91. package/dist/chunk-DDA6FP6U.js +0 -7
  92. package/src/ConnectModal.scss +0 -665
  93. package/src/ConnectModal.tsx +0 -573
  94. package/src/components/QRFrame.tsx +0 -43
  95. package/src/views/CreditWalletView.tsx +0 -58
  96. package/src/views/IdleView.tsx +0 -10
  97. package/src/views/MetaMaskView.tsx +0 -66
  98. package/src/views/SwitchChainView.tsx +0 -72
  99. package/src/views/WalletConnectView.tsx +0 -206
@@ -0,0 +1,122 @@
1
+ @use '../../style/mixin.scss' as *;
2
+
3
+ .ck-qr-area {
4
+ display: flex;
5
+ flex-direction: column;
6
+ align-items: center;
7
+ flex: 1;
8
+ width: 100%;
9
+ padding: 32px 0;
10
+ }
11
+
12
+ // ── Text ──────────────────────────────────────────────────────────────────────
13
+ .ck-qr-text {
14
+ display: flex;
15
+ flex-direction: column;
16
+ align-items: center;
17
+ gap: 6px;
18
+ width: 100%;
19
+ margin-top: 24px;
20
+ }
21
+
22
+ .ck-qr-label {
23
+ @include textToken('subtitle2-bold');
24
+ color: var(--scale-gray-900);
25
+ text-align: center;
26
+ }
27
+
28
+ .ck-qr {
29
+ display: flex;
30
+ flex-direction: column;
31
+ align-items: center;
32
+ margin: 0;
33
+ border-radius: 20px;
34
+ overflow: hidden;
35
+ outline: none;
36
+ }
37
+
38
+ .ck-qr-skeleton {
39
+ padding: 20px;
40
+ border: 1px solid var(--semantic-divider-divider-1);
41
+ border-radius: 20px;
42
+ }
43
+
44
+ .ck-qr-skeleton-inner {
45
+ display: block;
46
+ width: 246px;
47
+ height: 246px;
48
+ background: linear-gradient(
49
+ 132deg,
50
+ var(--scale-gray-100) 36%,
51
+ var(--scale-gray-200) 51%,
52
+ var(--scale-gray-100) 66%
53
+ );
54
+ background-size: 200% 100%;
55
+ animation: ck-qr-shimmer 1.5s linear infinite;
56
+
57
+ @include tablet {
58
+ width: 198px;
59
+ height: 198px;
60
+ }
61
+ }
62
+
63
+ // ── Timeout ───────────────────────────────────────────────────────────────────
64
+ .ck-qr-timeout {
65
+ width: 288px;
66
+ height: 288px;
67
+ border: 1px solid var(--semantic-divider-divider-1);
68
+ background: var(--scale-gray-100);
69
+ display: flex;
70
+ align-items: center;
71
+ justify-content: center;
72
+
73
+ @include tablet {
74
+ width: 240px;
75
+ height: 240px;
76
+ }
77
+ }
78
+
79
+ @keyframes ck-qr-shimmer {
80
+ 0% { background-position: 200% 0; }
81
+ 100% { background-position: -200% 0; }
82
+ }
83
+
84
+ // ── Ready ─────────────────────────────────────────────────────────────────────
85
+ .ck-qr-frame {
86
+ --ck-qr-bg: transparent;
87
+ padding: 20px;
88
+ border-radius: 20px;
89
+ border: 1px solid var(--semantic-divider-divider-1);
90
+
91
+ svg {
92
+ display: block;
93
+ width: 246px;
94
+ height: 246px;
95
+
96
+ @include tablet {
97
+ width: 198px;
98
+ height: 198px;
99
+ }
100
+ }
101
+ }
102
+
103
+ .ck-qr-timeout-inner {
104
+ display: flex;
105
+ flex-direction: column;
106
+ align-items: center;
107
+ gap: 8px;
108
+ }
109
+
110
+ .ck-qr-timeout-icon {
111
+ display: block;
112
+ width: 32px;
113
+ height: 32px;
114
+ background: var(--scale-gray-400);
115
+ border-radius: 50%;
116
+ }
117
+
118
+ .ck-qr-timeout-text {
119
+ @include textToken('label5-regular');
120
+ color: var(--scale-gray-600);
121
+ text-align: center;
122
+ }
@@ -0,0 +1,20 @@
1
+ import { type FC, type SVGProps } from 'react';
2
+
3
+ export const SearchIcon: FC<SVGProps<SVGSVGElement>> = (props) => {
4
+ return (
5
+ <svg
6
+ xmlns="http://www.w3.org/2000/svg"
7
+ width="20"
8
+ height="19"
9
+ viewBox="0 0 20 19"
10
+ fill="none"
11
+ aria-hidden="true"
12
+ {...props}
13
+ >
14
+ <path
15
+ d="M14.4688 8.03418C14.4688 4.48066 11.5877 1.59961 8.03418 1.59961C4.48068 1.59963 1.59961 4.48067 1.59961 8.03418C1.59963 11.5877 4.48069 14.4688 8.03418 14.4688C11.5877 14.4688 14.4688 11.5877 14.4688 8.03418ZM16.0577 8.44726C15.9732 10.1146 15.3799 11.6473 14.4307 12.8946L19.0674 17.5108L19.1221 17.5713C19.3788 17.8848 19.3608 18.3474 19.0674 18.6397C18.7738 18.9319 18.3091 18.95 17.9942 18.6944L17.9336 18.6397L13.3389 14.0645C12.0201 15.2255 10.3191 15.9628 8.44726 16.0576L8.03418 16.0684C3.59703 16.0684 1.9e-05 12.4714 0 8.03418L0.010742 7.62109C0.225741 3.3759 3.73556 1.8e-05 8.03418 0L8.44726 0.010742C12.6925 0.225746 16.0684 3.73555 16.0684 8.03418L16.0577 8.44726Z"
16
+ fill="currentColor"
17
+ />
18
+ </svg>
19
+ );
20
+ };
@@ -0,0 +1,24 @@
1
+ import { type FC, type SVGProps } from 'react';
2
+
3
+ export const XMarkCircleIcon: FC<SVGProps<SVGSVGElement>> = (props) => {
4
+ return (
5
+ <svg
6
+ width={20}
7
+ height={20}
8
+ viewBox="0 0 20 20"
9
+ fill="none"
10
+ xmlns="http://www.w3.org/2000/svg"
11
+ aria-hidden="true"
12
+ focusable="false"
13
+ {...props}
14
+ >
15
+ <circle cx="10" cy="10" r="10" fill="currentColor" />
16
+ <path
17
+ d="M6.5 6.5L13.5 13.5M13.5 6.5L6.5 13.5"
18
+ stroke="var(--semantic-paper-sheet)"
19
+ strokeWidth="1.5"
20
+ strokeLinecap="round"
21
+ />
22
+ </svg>
23
+ );
24
+ };
@@ -0,0 +1,44 @@
1
+ import { type FC, type ChangeEvent } from 'react';
2
+ import './style.scss';
3
+ import { SearchIcon } from './asset/Search';
4
+ import { XMarkCircleIcon } from './asset/XMarkCircle';
5
+
6
+ interface SearchBarProps {
7
+ value: string;
8
+ placeholder?: string;
9
+ onChange: (value: string) => void;
10
+ onClear: () => void;
11
+ }
12
+
13
+ export const SearchBar: FC<SearchBarProps> = ({
14
+ value,
15
+ placeholder = 'Search wallet',
16
+ onChange,
17
+ onClear,
18
+ }) => {
19
+ const handleChange = (e: ChangeEvent<HTMLInputElement>) => onChange(e.target.value);
20
+
21
+ return (
22
+ <div className="ck-search">
23
+ <SearchIcon className="ck-search-icon" />
24
+ <input
25
+ className="ck-search-input"
26
+ type="search"
27
+ value={value}
28
+ placeholder={placeholder}
29
+ onChange={handleChange}
30
+ aria-label="Search wallet"
31
+ />
32
+ <button
33
+ type="button"
34
+ className="ck-search-clear"
35
+ onClick={onClear}
36
+ aria-label="Clear search"
37
+ aria-hidden={!value || undefined}
38
+ tabIndex={value ? 0 : -1}
39
+ >
40
+ <XMarkCircleIcon />
41
+ </button>
42
+ </div>
43
+ );
44
+ };
@@ -0,0 +1,58 @@
1
+ @use '../../style/mixin.scss' as *;
2
+
3
+ .ck-root .ck-search {
4
+ display: flex;
5
+ align-items: center;
6
+ gap: 6px;
7
+ flex: 1;
8
+ padding: 12px 16px;
9
+ border-radius: 100px;
10
+ background: var(--scale-gray-100);
11
+ border: 1px solid transparent;
12
+ transition: border-color 0.15s ease;
13
+
14
+ &:focus-within {
15
+ border-color: var(--semantic-brand-trugi-primary);
16
+ }
17
+ }
18
+
19
+ .ck-search-icon {
20
+ display: block;
21
+ flex-shrink: 0;
22
+ color: var(--scale-gray-500);
23
+ width: 20px;
24
+ height: 19px;
25
+ }
26
+
27
+ .ck-root .ck-search-input {
28
+ flex: 1;
29
+ @include textToken('body4-l2-regular');
30
+ color: var(--scale-gray-900);
31
+ caret-color: var(--semantic-brand-trugi-primary);
32
+ background: none;
33
+ min-width: 0;
34
+
35
+ &::placeholder {
36
+ color: var(--scale-gray-500);
37
+ }
38
+
39
+ &::-webkit-search-cancel-button {
40
+ display: none;
41
+ }
42
+ }
43
+
44
+ .ck-root .ck-search-clear {
45
+ display: flex;
46
+ align-items: center;
47
+ justify-content: center;
48
+ width: 20px;
49
+ height: 20px;
50
+ flex-shrink: 0;
51
+ color: var(--scale-gray-500);
52
+ cursor: pointer;
53
+ visibility: hidden;
54
+
55
+ &:not([aria-hidden]) {
56
+ visibility: visible;
57
+ }
58
+ }
@@ -0,0 +1,41 @@
1
+ import { type FC, useEffect } from 'react';
2
+ import './style.scss';
3
+ import { CloseIcon } from '../../layout/connectDialog/asset/closeIcon';
4
+ import { CheckIcon } from '../../layout/connectDialog/asset/checkIcon';
5
+ import { WarningIcon } from '../../layout/connectDialog/asset/warningIcon';
6
+
7
+ export type ToastVariant = 'success' | 'warning';
8
+
9
+ const AUTO_CLOSE_MS = 3000;
10
+
11
+ interface ToastProps {
12
+ message: string;
13
+ variant?: ToastVariant;
14
+ onClose?: () => void;
15
+ }
16
+
17
+ export const Toast: FC<ToastProps> = ({ message, variant = 'success', onClose }) => {
18
+ useEffect(() => {
19
+ if (!onClose) return;
20
+ const timer = setTimeout(onClose, AUTO_CLOSE_MS);
21
+ return () => clearTimeout(timer);
22
+ }, [variant, onClose, message]);
23
+
24
+ return (
25
+ <div className="ck-toast" data-variant={variant} role="status" aria-live="polite">
26
+ <div className="ck-toast-content">
27
+ {variant === 'warning' ? (
28
+ <WarningIcon className="ck-toast-icon ck-toast-icon--warning" />
29
+ ) : (
30
+ <CheckIcon className="ck-toast-icon ck-toast-icon--success" />
31
+ )}
32
+ <p className="ck-toast-message">{message}</p>
33
+ </div>
34
+ {onClose && (
35
+ <button type="button" className="ck-toast-close" onClick={onClose} aria-label="Close">
36
+ <CloseIcon width={20} height={20} />
37
+ </button>
38
+ )}
39
+ </div>
40
+ );
41
+ };
@@ -0,0 +1,108 @@
1
+ @use '../../style/mixin.scss' as *;
2
+
3
+ .ck-toast-stack {
4
+ position: fixed;
5
+ top: clamp(20px, 9.2vh, 99px);
6
+ left: 50%;
7
+ z-index: 1001;
8
+ display: flex;
9
+ flex-direction: column;
10
+ align-items: center;
11
+ gap: 8px;
12
+ max-width: calc(100vw - 40px);
13
+ transform: translateX(-50%);
14
+
15
+ @include tablet {
16
+ top: clamp(
17
+ calc(env(safe-area-inset-top, 0px) + 20px),
18
+ calc(env(safe-area-inset-top, 0px) + 20px),
19
+ calc(env(safe-area-inset-top, 0px) + 20px)
20
+ );
21
+ left: 20px;
22
+ right: 20px;
23
+ align-items: stretch;
24
+ max-width: none;
25
+ transform: none;
26
+ }
27
+ }
28
+
29
+ .ck-toast {
30
+ display: flex;
31
+ align-items: center;
32
+ justify-content: space-between;
33
+ gap: 16px;
34
+ width: max-content;
35
+ min-width: min(400px, calc(100vw - 40px));
36
+ max-width: 100%;
37
+ padding: 12px 16px;
38
+ border-radius: 8px;
39
+ background: var(--semantic-paper-sheet);
40
+ border: 1px solid var(--semantic-divider-divider-1);
41
+ animation: ck-toast-in 0.2s ease;
42
+
43
+ @include tablet {
44
+ width: 100%;
45
+ min-width: 0;
46
+ }
47
+ }
48
+
49
+ @keyframes ck-toast-in {
50
+ from {
51
+ opacity: 0;
52
+ transform: translateY(8px);
53
+ }
54
+
55
+ to {
56
+ opacity: 1;
57
+ transform: translateY(0);
58
+ }
59
+ }
60
+
61
+ .ck-toast-content {
62
+ display: flex;
63
+ align-items: center;
64
+ gap: 8px;
65
+
66
+ @include tablet {
67
+ flex: 1;
68
+ min-width: 0;
69
+ }
70
+ }
71
+
72
+ .ck-toast-icon {
73
+ display: flex;
74
+ align-items: center;
75
+ justify-content: center;
76
+ width: 24px;
77
+ height: 24px;
78
+ flex-shrink: 0;
79
+ }
80
+
81
+ .ck-toast-icon--success {
82
+ color: var(--semantic-information-success);
83
+ }
84
+
85
+ .ck-toast-icon--warning {
86
+ color: var(--semantic-information-caution);
87
+ }
88
+
89
+ .ck-toast-message {
90
+ @include textToken('body3-l1-medium');
91
+ color: var(--scale-gray-900);
92
+ white-space: nowrap;
93
+
94
+ @include tablet {
95
+ flex: 1;
96
+ min-width: 0;
97
+ white-space: normal;
98
+ }
99
+ }
100
+
101
+ .ck-root .ck-toast-close {
102
+ display: flex;
103
+ align-items: center;
104
+ justify-content: center;
105
+ flex-shrink: 0;
106
+ color: var(--scale-gray-700);
107
+ cursor: pointer;
108
+ }
@@ -0,0 +1,27 @@
1
+ import './style.scss';
2
+ import { type FC } from 'react';
3
+
4
+ interface ToggleProps {
5
+ checked: boolean;
6
+ label: string;
7
+ onChange: (checked: boolean) => void;
8
+ }
9
+
10
+ export const Toggle: FC<ToggleProps> = ({ checked, label, onChange }) => {
11
+ return (
12
+ <label className="ck-toggle">
13
+ <input
14
+ className="ck-toggle-input"
15
+ type="checkbox"
16
+ role="switch"
17
+ checked={checked}
18
+ onChange={(e) => onChange(e.target.checked)}
19
+ aria-label={label}
20
+ />
21
+ <span className="ck-toggle-track" aria-hidden="true">
22
+ <span className="ck-toggle-thumb" />
23
+ </span>
24
+ <span className="ck-toggle-label">{label}</span>
25
+ </label>
26
+ );
27
+ };
@@ -0,0 +1,53 @@
1
+ @use '../../style/mixin.scss' as *;
2
+
3
+ .ck-toggle {
4
+ display: inline-flex;
5
+ align-items: center;
6
+ gap: 6px;
7
+ cursor: pointer;
8
+ flex-shrink: 0;
9
+ }
10
+
11
+ .ck-toggle-input {
12
+ position: absolute;
13
+ opacity: 0;
14
+ width: 0;
15
+ height: 0;
16
+ pointer-events: none;
17
+ }
18
+
19
+ .ck-toggle-track {
20
+ position: relative;
21
+ width: 40px;
22
+ height: 24px;
23
+ border-radius: 100px;
24
+ background: var(--scale-gray-400);
25
+ transition: background 0.2s;
26
+ flex-shrink: 0;
27
+
28
+ .ck-toggle-input:checked + & {
29
+ background: var(--semantic-brand-trugi-primary);
30
+ }
31
+ }
32
+
33
+ .ck-toggle-thumb {
34
+ position: absolute;
35
+ top: 3px;
36
+ left: 2.4px;
37
+ width: 19.2px;
38
+ height: 19.2px;
39
+ border-radius: 50%;
40
+ background: var(--static-white-main);
41
+ box-shadow: 0 1px 2px rgba(0, 0, 0, 0.25);
42
+ transition: transform 0.2s;
43
+
44
+ .ck-toggle-input:checked ~ .ck-toggle-track & {
45
+ transform: translateX(16px);
46
+ }
47
+ }
48
+
49
+ .ck-toggle-label {
50
+ @include textToken('body4-l2-regular');
51
+ color: var(--scale-gray-700);
52
+ white-space: nowrap;
53
+ }
@@ -0,0 +1,64 @@
1
+ import { type FC } from 'react';
2
+ import './style.scss';
3
+ import { type WCWallet } from '../../types';
4
+ import wcBadge from '../../../assets/wc-search.png';
5
+
6
+ interface WalletGridProps {
7
+ wallets: WCWallet[];
8
+ isLoading: boolean;
9
+ onSelect: (wallet: WCWallet) => void;
10
+ }
11
+
12
+ export const WalletGrid: FC<WalletGridProps> = ({ wallets, isLoading, onSelect }) => {
13
+ if (isLoading) {
14
+ return (
15
+ <div className="ck-wallet-grid-scroll">
16
+ <ul className="ck-wallet-grid ck-wallet-grid--loading" role="list" aria-busy="true">
17
+ {Array.from({ length: 8 }).map((_, i) => (
18
+ <li key={i} className="ck-wallet-grid-item">
19
+ <span className="ck-wallet-grid-icon ck-wallet-grid-icon--skeleton" />
20
+ <span className="ck-wallet-grid-name ck-wallet-grid-name--skeleton" />
21
+ </li>
22
+ ))}
23
+ </ul>
24
+ </div>
25
+ );
26
+ }
27
+
28
+ return (
29
+ <div className="ck-wallet-grid-scroll">
30
+ <ul className="ck-wallet-grid" role="list">
31
+ {wallets.map((wallet) => (
32
+ <li key={wallet.id}>
33
+ <button type="button" className="ck-wallet-grid-item" onClick={() => onSelect(wallet)}>
34
+ {wallet.imageUrl ? (
35
+ <img
36
+ className="ck-wallet-grid-icon"
37
+ src={wallet.imageUrl}
38
+ alt=""
39
+ aria-hidden="true"
40
+ />
41
+ ) : (
42
+ <span className="ck-wallet-grid-icon" aria-hidden="true" />
43
+ )}
44
+ <span className="ck-wallet-grid-name-wrap">
45
+ <span className="ck-wallet-grid-name">{wallet.name}</span>
46
+ {(wallet.mobileNative ||
47
+ wallet.mobileUniversal ||
48
+ wallet.desktopNative ||
49
+ wallet.desktopUniversal) && (
50
+ <img
51
+ className="ck-wallet-grid-wc-badge"
52
+ src={wcBadge}
53
+ alt=""
54
+ aria-hidden="true"
55
+ />
56
+ )}
57
+ </span>
58
+ </button>
59
+ </li>
60
+ ))}
61
+ </ul>
62
+ </div>
63
+ );
64
+ };
@@ -0,0 +1,108 @@
1
+ @use '../../style/mixin.scss' as *;
2
+
3
+ .ck-wallet-grid-scroll {
4
+ flex: 1;
5
+ min-height: 0;
6
+ overflow-y: auto;
7
+ overflow-x: hidden;
8
+ width: 100%;
9
+ @include themedScrollbar;
10
+ }
11
+
12
+ .ck-wallet-grid {
13
+ display: grid;
14
+ grid-template-columns: repeat(4, minmax(0, 1fr));
15
+ grid-auto-rows: auto;
16
+ column-gap: 16px;
17
+ row-gap: 16px;
18
+ list-style: none;
19
+ margin: 0;
20
+ padding: 0;
21
+ width: 100%;
22
+
23
+ @include small-mobile {
24
+ row-gap: 3px;
25
+ }
26
+ @include max-width(392px) {
27
+ grid-template-columns: repeat(3, minmax(0, 1fr));
28
+ }
29
+ }
30
+
31
+ .ck-root .ck-wallet-grid-item {
32
+ display: flex;
33
+ flex-direction: column;
34
+ align-items: center;
35
+ justify-content: center;
36
+ gap: 6px;
37
+ padding: 20px 12px;
38
+ width: 100%;
39
+ cursor: pointer;
40
+ }
41
+
42
+ .ck-wallet-grid-icon {
43
+ width: 54px;
44
+ height: 54px;
45
+ max-width: none;
46
+ border-radius: 12px;
47
+ flex-shrink: 0;
48
+ background: var(--scale-gray-200);
49
+ overflow: hidden;
50
+ cursor: pointer;
51
+
52
+ img {
53
+ width: 100%;
54
+ height: 100%;
55
+ object-fit: cover;
56
+ display: block;
57
+ }
58
+ }
59
+
60
+ .ck-wallet-grid-name-wrap {
61
+ display: flex;
62
+ align-items: center;
63
+ justify-content: center;
64
+ gap: 2px;
65
+ width: 100%;
66
+ min-width: 0;
67
+ }
68
+
69
+ .ck-wallet-grid-name {
70
+ @include textToken('label6-bold');
71
+ color: var(--scale-gray-900);
72
+ text-align: center;
73
+ overflow: hidden;
74
+ text-overflow: ellipsis;
75
+ white-space: nowrap;
76
+ min-width: 0;
77
+ flex-shrink: 1;
78
+ }
79
+
80
+ .ck-wallet-grid-wc-badge {
81
+ width: 16px;
82
+ height: 16px;
83
+ flex-shrink: 0;
84
+ }
85
+
86
+ // ── Skeleton ──────────────────────────────────────────────────────────────────
87
+ .ck-wallet-grid-loading .ck-wallet-grid-item {
88
+ cursor: default;
89
+ }
90
+
91
+ .ck-wallet-grid-icon-skeleton {
92
+ background: var(--scale-gray-100);
93
+ animation: ck-grid-pulse 1.5s ease-in-out infinite;
94
+ }
95
+
96
+ .ck-wallet-grid-name-skeleton {
97
+ height: 12px;
98
+ border-radius: 4px;
99
+ background: var(--scale-gray-100);
100
+ width: 60%;
101
+ margin: 0 auto;
102
+ animation: ck-grid-pulse 1.5s ease-in-out infinite;
103
+ }
104
+
105
+ @keyframes ck-grid-pulse {
106
+ 0%, 100% { opacity: 1; }
107
+ 50% { opacity: 0.4; }
108
+ }