@silentswap/ui-kit 0.0.41
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.
- package/dist/components/AssetTile.d.ts +10 -0
- package/dist/components/AssetTile.js +18 -0
- package/dist/components/Button.d.ts +15 -0
- package/dist/components/Button.js +26 -0
- package/dist/components/Card.d.ts +14 -0
- package/dist/components/Card.js +19 -0
- package/dist/components/Input.d.ts +19 -0
- package/dist/components/Input.js +23 -0
- package/dist/components/PopularTokensArea.d.ts +8 -0
- package/dist/components/PopularTokensArea.js +34 -0
- package/dist/components/ProgressBar.d.ts +17 -0
- package/dist/components/ProgressBar.js +30 -0
- package/dist/components/Select.d.ts +12 -0
- package/dist/components/Select.js +7 -0
- package/dist/components/Warning.d.ts +15 -0
- package/dist/components/Warning.js +23 -0
- package/dist/constants.d.ts +2 -0
- package/dist/constants.js +4 -0
- package/dist/data.d.ts +7 -0
- package/dist/data.js +14 -0
- package/dist/index.d.ts +17 -0
- package/dist/index.js +13 -0
- package/dist/styles.css +399 -0
- package/dist/types.d.ts +15 -0
- package/dist/types.js +1 -0
- package/package.json +52 -0
- package/src/components/AssetTile.tsx +69 -0
- package/src/components/Button.tsx +51 -0
- package/src/components/Card.tsx +49 -0
- package/src/components/Input.tsx +72 -0
- package/src/components/PopularTokensArea.tsx +78 -0
- package/src/components/ProgressBar.tsx +67 -0
- package/src/components/Select.tsx +48 -0
- package/src/components/Warning.tsx +54 -0
- package/src/constants.ts +5 -0
- package/src/data.ts +19 -0
- package/src/index.ts +26 -0
- package/src/styles.css +399 -0
- package/src/types.ts +20 -0
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import React, { forwardRef } from 'react';
|
|
2
|
+
import type { InputHTMLAttributes } from 'react';
|
|
3
|
+
|
|
4
|
+
export interface InputProps extends InputHTMLAttributes<HTMLInputElement> {
|
|
5
|
+
/** Visual variant of the input */
|
|
6
|
+
variant?: 'default' | 'digital' | 'amount';
|
|
7
|
+
/** Whether the input has an error */
|
|
8
|
+
error?: boolean;
|
|
9
|
+
/** Whether the input is loading */
|
|
10
|
+
loading?: boolean;
|
|
11
|
+
/** Optional label text */
|
|
12
|
+
label?: string;
|
|
13
|
+
/** Prefix text shown before input */
|
|
14
|
+
prefix?: string;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Simple input component with different variants
|
|
19
|
+
* Based on SilentSwap Form.svelte and Plate.svelte styles
|
|
20
|
+
*/
|
|
21
|
+
export const Input = forwardRef<HTMLInputElement, InputProps>(({
|
|
22
|
+
variant = 'default',
|
|
23
|
+
error = false,
|
|
24
|
+
loading = false,
|
|
25
|
+
label,
|
|
26
|
+
prefix,
|
|
27
|
+
className = '',
|
|
28
|
+
...props
|
|
29
|
+
}, ref) => {
|
|
30
|
+
const baseClasses = 'w-full border-0 rounded-lg transition-all focus:outline-none focus:ring-2 focus:ring-offset-2 disabled:opacity-50 disabled:cursor-not-allowed';
|
|
31
|
+
|
|
32
|
+
const variantClasses = {
|
|
33
|
+
default: 'px-3 py-2 text-base bg-black text-white',
|
|
34
|
+
digital: 'digital-input', // Uses CSS class from styles.css
|
|
35
|
+
amount: 'text-[28px] font-bold text-white px-3 py-1 bg-black rounded-t-lg rounded-b-none',
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
const errorClasses = error ? 'focus:ring-red-500' : 'focus:ring-[var(--color-yellow)]';
|
|
39
|
+
const loadingClasses = loading ? 'animate-[trill_350ms_linear_infinite] bg-[var(--color-gray-dark)]' : '';
|
|
40
|
+
|
|
41
|
+
const classes = `${baseClasses} ${variantClasses[variant]} ${errorClasses} ${loadingClasses} ${className}`.trim();
|
|
42
|
+
|
|
43
|
+
const inputElement = (
|
|
44
|
+
<div className="relative flex items-center">
|
|
45
|
+
{prefix && (
|
|
46
|
+
<span className="absolute left-3 text-gray-400 font-medium">
|
|
47
|
+
{prefix}
|
|
48
|
+
</span>
|
|
49
|
+
)}
|
|
50
|
+
<input
|
|
51
|
+
ref={ref}
|
|
52
|
+
className={`${classes} ${prefix ? 'pl-8' : ''}`}
|
|
53
|
+
{...props}
|
|
54
|
+
/>
|
|
55
|
+
</div>
|
|
56
|
+
);
|
|
57
|
+
|
|
58
|
+
if (label) {
|
|
59
|
+
return (
|
|
60
|
+
<div className="w-full">
|
|
61
|
+
<label className="block text-sm font-medium mb-1 text-gray-300">
|
|
62
|
+
{label}
|
|
63
|
+
</label>
|
|
64
|
+
{inputElement}
|
|
65
|
+
</div>
|
|
66
|
+
);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
return inputElement;
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
Input.displayName = 'Input';
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { S_CAIP19_USDC_AVALANCHE } from '../constants';
|
|
3
|
+
import { asset_get } from '../data';
|
|
4
|
+
import { AssetTile } from './AssetTile';
|
|
5
|
+
|
|
6
|
+
export interface PopularTokensAreaProps {
|
|
7
|
+
onTokenSelect?: (caip19: string) => void;
|
|
8
|
+
title?: string;
|
|
9
|
+
tokens?: string[];
|
|
10
|
+
className?: string;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export const PopularTokensArea: React.FC<PopularTokensAreaProps> = ({
|
|
14
|
+
onTokenSelect,
|
|
15
|
+
title = 'Popular Tokens',
|
|
16
|
+
tokens,
|
|
17
|
+
className = ''
|
|
18
|
+
}) => {
|
|
19
|
+
const defaultTokens = [
|
|
20
|
+
'eip155:1/slip44:60', // ETH on Ethereum
|
|
21
|
+
'eip155:1/erc20:0xdAC17F958D2ee523a2206206994597C13D831ec7', // USDT on Ethereum
|
|
22
|
+
'eip155:1/erc20:0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48', // USDC on Ethereum
|
|
23
|
+
'eip155:1/erc20:0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2', // WETH on Ethereum
|
|
24
|
+
'eip155:1/erc20:0x2260FAC5E5542a773Aa44fBCfeDf7C193bc2C599', // WBTC on Ethereum
|
|
25
|
+
|
|
26
|
+
'eip155:56/slip44:714', // BNB on BSC
|
|
27
|
+
'eip155:56/erc20:0xbb4CdB9CBd36B01bD1cBaEBF2De08d9173bc095c', // WBNB on BSC
|
|
28
|
+
|
|
29
|
+
'eip155:8453/slip44:60', // ETH on Base
|
|
30
|
+
'eip155:8453/erc20:0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913', // USDC on Base
|
|
31
|
+
|
|
32
|
+
'eip155:43114/slip44:9005', // WAVAX on Avalanche
|
|
33
|
+
S_CAIP19_USDC_AVALANCHE, // USDC on Avalanche
|
|
34
|
+
|
|
35
|
+
'eip155:137/slip44:966', // WMATIC/WPOL on Polygon
|
|
36
|
+
'eip155:137/erc20:0xc2132D05D31c914a87C6611C10748AEb04B58e8F', // USDT0 on Polygon
|
|
37
|
+
'eip155:137/erc20:0x3c499c542cEF5E3811e1192ce70d8cC03d5c3359', // USDC on Polygon
|
|
38
|
+
|
|
39
|
+
'eip155:10/slip44:60', // WETH on Optimism
|
|
40
|
+
'eip155:10/erc20:0x0b2C639c533813f4Aa9D7837CAf62653d097Ff85', // USDC on Optimism
|
|
41
|
+
|
|
42
|
+
'eip155:42161/slip44:60', // WETH on Arbitrum
|
|
43
|
+
'eip155:42161/erc20:0xaf88d065e77c8cC2239327C5EDb3A432268e5831', // USDC on Arbitrum
|
|
44
|
+
];
|
|
45
|
+
|
|
46
|
+
const popularTokens = tokens || defaultTokens;
|
|
47
|
+
|
|
48
|
+
return (
|
|
49
|
+
<div className={`${className}`}>
|
|
50
|
+
<div className="font-orbitron text-lg font-bold text-white mb-3">
|
|
51
|
+
{title}
|
|
52
|
+
</div>
|
|
53
|
+
|
|
54
|
+
<div className="flex gap-2 overflow-x-auto pb-2">
|
|
55
|
+
{popularTokens.map((caip19) => {
|
|
56
|
+
const asset = asset_get(caip19);
|
|
57
|
+
if (!asset) return null;
|
|
58
|
+
|
|
59
|
+
return (
|
|
60
|
+
<div
|
|
61
|
+
key={caip19}
|
|
62
|
+
className="flex flex-col items-center gap-2 bg-dim-med rounded-lg p-2 cursor-pointer hover:bg-dim-light transition-colors min-w-fit"
|
|
63
|
+
onClick={() => onTokenSelect?.(caip19)}
|
|
64
|
+
role="button"
|
|
65
|
+
tabIndex={0}
|
|
66
|
+
aria-label={`Select ${asset.symbol}`}
|
|
67
|
+
>
|
|
68
|
+
<AssetTile caip19={caip19} size="small" />
|
|
69
|
+
<div className="text-text-dim text-xs text-center">
|
|
70
|
+
{asset.symbol?.toUpperCase()}
|
|
71
|
+
</div>
|
|
72
|
+
</div>
|
|
73
|
+
);
|
|
74
|
+
})}
|
|
75
|
+
</div>
|
|
76
|
+
</div>
|
|
77
|
+
);
|
|
78
|
+
};
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import type { HTMLAttributes } from 'react';
|
|
3
|
+
|
|
4
|
+
export interface ProgressBarProps extends Omit<HTMLAttributes<HTMLDivElement>, 'children'> {
|
|
5
|
+
/** Progress value from 0 to 1 (0 = 0%, 1 = 100%) */
|
|
6
|
+
value: number;
|
|
7
|
+
/** Height of the progress bar in pixels */
|
|
8
|
+
height?: number;
|
|
9
|
+
/** Color of the progress fill */
|
|
10
|
+
color?: 'green' | 'yellow' | 'purple' | 'orange';
|
|
11
|
+
/** Whether to show the progress bar (animates height) */
|
|
12
|
+
show?: boolean;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Simple progress bar component
|
|
17
|
+
* Based on SilentSwap Plate.svelte progress styles
|
|
18
|
+
*/
|
|
19
|
+
export const ProgressBar: React.FC<ProgressBarProps> = ({
|
|
20
|
+
value,
|
|
21
|
+
height = 6,
|
|
22
|
+
color = 'green',
|
|
23
|
+
show = true,
|
|
24
|
+
className = '',
|
|
25
|
+
style,
|
|
26
|
+
...props
|
|
27
|
+
}) => {
|
|
28
|
+
const colorClasses = {
|
|
29
|
+
green: 'bg-[var(--color-green)]',
|
|
30
|
+
yellow: 'bg-[var(--color-yellow)]',
|
|
31
|
+
purple: 'bg-[var(--color-purple)]',
|
|
32
|
+
orange: 'bg-[var(--color-orange)]',
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
// Clamp value between 0 and 1
|
|
36
|
+
const clampedValue = Math.max(0, Math.min(1, value));
|
|
37
|
+
|
|
38
|
+
const containerStyle: React.CSSProperties = {
|
|
39
|
+
height: show ? `${height}px` : '0px',
|
|
40
|
+
width: '100%',
|
|
41
|
+
backgroundColor: 'var(--color-gray-dark)',
|
|
42
|
+
transition: 'height 500ms linear',
|
|
43
|
+
overflow: 'hidden',
|
|
44
|
+
...style,
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
const fillStyle: React.CSSProperties = {
|
|
48
|
+
width: `${clampedValue * 100}%`,
|
|
49
|
+
height: '100%',
|
|
50
|
+
transition: 'width 490ms linear',
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
return (
|
|
54
|
+
<div
|
|
55
|
+
className={className}
|
|
56
|
+
style={containerStyle}
|
|
57
|
+
role="progressbar"
|
|
58
|
+
aria-valuenow={clampedValue * 100}
|
|
59
|
+
aria-valuemin={0}
|
|
60
|
+
aria-valuemax={100}
|
|
61
|
+
{...props}
|
|
62
|
+
>
|
|
63
|
+
<div className={colorClasses[color]} style={fillStyle} />
|
|
64
|
+
</div>
|
|
65
|
+
);
|
|
66
|
+
};
|
|
67
|
+
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import React, { forwardRef } from 'react';
|
|
2
|
+
import type { SelectHTMLAttributes, ReactNode } from 'react';
|
|
3
|
+
|
|
4
|
+
export interface SelectOption {
|
|
5
|
+
value: string;
|
|
6
|
+
label: string;
|
|
7
|
+
disabled?: boolean;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export interface SelectProps extends Omit<SelectHTMLAttributes<HTMLSelectElement>, 'children'> {
|
|
11
|
+
options: SelectOption[];
|
|
12
|
+
placeholder?: string;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export const Select = forwardRef<HTMLSelectElement, SelectProps>(({
|
|
16
|
+
options,
|
|
17
|
+
placeholder,
|
|
18
|
+
className = '',
|
|
19
|
+
...props
|
|
20
|
+
}, ref) => {
|
|
21
|
+
const classes = `bg-black border-0 rounded-lg text-white px-3 py-2 cursor-pointer transition-colors focus:outline-none focus:ring-2 focus:ring-yellow focus:ring-offset-2 hover:bg-dim-dark ${className}`.trim();
|
|
22
|
+
|
|
23
|
+
return (
|
|
24
|
+
<select
|
|
25
|
+
ref={ref}
|
|
26
|
+
className={classes}
|
|
27
|
+
{...props}
|
|
28
|
+
>
|
|
29
|
+
{placeholder && (
|
|
30
|
+
<option value="" disabled>
|
|
31
|
+
{placeholder}
|
|
32
|
+
</option>
|
|
33
|
+
)}
|
|
34
|
+
{options.map((option) => (
|
|
35
|
+
<option
|
|
36
|
+
key={option.value}
|
|
37
|
+
value={option.value}
|
|
38
|
+
disabled={option.disabled}
|
|
39
|
+
className="bg-black text-text-bright"
|
|
40
|
+
>
|
|
41
|
+
{option.label}
|
|
42
|
+
</option>
|
|
43
|
+
))}
|
|
44
|
+
</select>
|
|
45
|
+
);
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
Select.displayName = 'Select';
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import type { HTMLAttributes, ReactNode } from 'react';
|
|
3
|
+
|
|
4
|
+
export interface WarningProps extends HTMLAttributes<HTMLDivElement> {
|
|
5
|
+
/** Warning content */
|
|
6
|
+
children: ReactNode;
|
|
7
|
+
/** Variant of the warning */
|
|
8
|
+
variant?: 'warning' | 'error' | 'info' | 'success';
|
|
9
|
+
/** Whether to show a dot indicator */
|
|
10
|
+
showDot?: boolean;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Simple warning/notice component
|
|
15
|
+
* Based on SilentSwap Plate.svelte input-notice styles
|
|
16
|
+
*/
|
|
17
|
+
export const Warning: React.FC<WarningProps> = ({
|
|
18
|
+
children,
|
|
19
|
+
variant = 'warning',
|
|
20
|
+
showDot = true,
|
|
21
|
+
className = '',
|
|
22
|
+
...props
|
|
23
|
+
}) => {
|
|
24
|
+
const baseClasses = 'text-xs bg-black/80 rounded px-2 py-1 flex items-center gap-1';
|
|
25
|
+
|
|
26
|
+
const variantClasses = {
|
|
27
|
+
warning: 'text-[#FED703]',
|
|
28
|
+
error: 'text-red-500',
|
|
29
|
+
info: 'text-blue-400',
|
|
30
|
+
success: 'text-[var(--color-green)]',
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
const dotColor = {
|
|
34
|
+
warning: '#FED703',
|
|
35
|
+
error: '#ef4444',
|
|
36
|
+
info: '#60a5fa',
|
|
37
|
+
success: 'var(--color-green)',
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
const classes = `${baseClasses} ${variantClasses[variant]} ${className}`.trim();
|
|
41
|
+
|
|
42
|
+
return (
|
|
43
|
+
<div className={classes} {...props}>
|
|
44
|
+
{showDot && (
|
|
45
|
+
<span
|
|
46
|
+
className="inline-block w-[5px] h-[6px] rounded-full"
|
|
47
|
+
style={{ backgroundColor: dotColor[variant] }}
|
|
48
|
+
/>
|
|
49
|
+
)}
|
|
50
|
+
<span>{children}</span>
|
|
51
|
+
</div>
|
|
52
|
+
);
|
|
53
|
+
};
|
|
54
|
+
|
package/src/constants.ts
ADDED
package/src/data.ts
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { Asset, WeakCaip19, WeakCaip2 } from './types';
|
|
2
|
+
|
|
3
|
+
// Global assets and chains stores
|
|
4
|
+
let H_ASSETS: Record<WeakCaip19, Asset> = {};
|
|
5
|
+
let H_CHAINS: Record<WeakCaip2, any> = {};
|
|
6
|
+
|
|
7
|
+
// Asset data loading function - needs to be called by consumer
|
|
8
|
+
export function loadAssets(assetData: { assets: Record<WeakCaip19, Asset>; chains: Record<WeakCaip2, any> }) {
|
|
9
|
+
H_ASSETS = assetData.assets;
|
|
10
|
+
H_CHAINS = assetData.chains;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export function asset_get(si_caip19: string): Asset | undefined {
|
|
14
|
+
return H_ASSETS[si_caip19 as WeakCaip19];
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export function chain_get(si_caip2: string): any | undefined {
|
|
18
|
+
return H_CHAINS[si_caip2 as WeakCaip2];
|
|
19
|
+
}
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
// Components
|
|
2
|
+
export { Button } from './components/Button';
|
|
3
|
+
export { Input } from './components/Input';
|
|
4
|
+
export { Select } from './components/Select';
|
|
5
|
+
export { Card } from './components/Card';
|
|
6
|
+
export { Warning } from './components/Warning';
|
|
7
|
+
export { ProgressBar } from './components/ProgressBar';
|
|
8
|
+
export { AssetTile } from './components/AssetTile';
|
|
9
|
+
export { PopularTokensArea } from './components/PopularTokensArea';
|
|
10
|
+
|
|
11
|
+
// Note: Import styles.css in your app for Tailwind styles
|
|
12
|
+
|
|
13
|
+
// Types
|
|
14
|
+
export type { Asset, ContactId } from './types';
|
|
15
|
+
export type { ButtonProps } from './components/Button';
|
|
16
|
+
export type { InputProps } from './components/Input';
|
|
17
|
+
export type { SelectProps, SelectOption } from './components/Select';
|
|
18
|
+
export type { CardProps } from './components/Card';
|
|
19
|
+
export type { WarningProps } from './components/Warning';
|
|
20
|
+
export type { ProgressBarProps } from './components/ProgressBar';
|
|
21
|
+
|
|
22
|
+
// Constants
|
|
23
|
+
export { S_CAIP19_USDC_AVALANCHE, X_MINIMUM_INPUT_USD } from './constants';
|
|
24
|
+
|
|
25
|
+
// Data utilities
|
|
26
|
+
export { loadAssets } from './data';
|