@lumen-dapps-kit/web3 0.1.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.
- package/dist/chunk-AMDZMZJO.js +32 -0
- package/dist/chunk-AMDZMZJO.js.map +1 -0
- package/dist/index.cjs +413 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +143 -0
- package/dist/index.d.ts +143 -0
- package/dist/index.js +376 -0
- package/dist/index.js.map +1 -0
- package/dist/utils.cjs +36 -0
- package/dist/utils.cjs.map +1 -0
- package/dist/utils.d.cts +39 -0
- package/dist/utils.d.ts +39 -0
- package/dist/utils.js +3 -0
- package/dist/utils.js.map +1 -0
- package/package.json +63 -0
- package/src/components/AddressDisplay.tsx +92 -0
- package/src/components/AmountDisplay.tsx +59 -0
- package/src/components/ChainSelector.tsx +123 -0
- package/src/components/GasIndicator.tsx +47 -0
- package/src/components/NetworkStatus.tsx +49 -0
- package/src/components/TxStatus.tsx +96 -0
- package/src/components/WalletPill.tsx +87 -0
- package/src/index.ts +22 -0
- package/src/utils.ts +88 -0
package/dist/index.d.cts
ADDED
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
|
+
import { ChainBrief, TxState } from './utils.cjs';
|
|
3
|
+
export { TruncateAddressOpts, formatGwei, formatUnits, truncateAddress } from './utils.cjs';
|
|
4
|
+
|
|
5
|
+
interface AddressDisplayProps {
|
|
6
|
+
/** Raw address. */
|
|
7
|
+
address: string;
|
|
8
|
+
/** Optional ENS / display name override. */
|
|
9
|
+
name?: string;
|
|
10
|
+
/** Show a small chain symbol after the address. */
|
|
11
|
+
chainSymbol?: string;
|
|
12
|
+
/** Enable click-to-copy. Defaults true. */
|
|
13
|
+
copyable?: boolean;
|
|
14
|
+
/** Surface treatment. */
|
|
15
|
+
variant?: 'pill' | 'inline';
|
|
16
|
+
/** Truncation params. */
|
|
17
|
+
head?: number;
|
|
18
|
+
tail?: number;
|
|
19
|
+
className?: string;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* AddressDisplay — wallet address with optional name resolution, chain
|
|
23
|
+
* label, and click-to-copy. Chain-agnostic — you resolve ENS/name yourself
|
|
24
|
+
* (e.g. via wagmi's useEnsName) and pass it as `name`.
|
|
25
|
+
*/
|
|
26
|
+
declare const AddressDisplay: ({ address, name, chainSymbol, copyable, variant, head, tail, className, }: AddressDisplayProps) => react_jsx_runtime.JSX.Element;
|
|
27
|
+
|
|
28
|
+
interface WalletPillProps {
|
|
29
|
+
/** Address — undefined renders the connect CTA. */
|
|
30
|
+
address?: string;
|
|
31
|
+
/** Display name (ENS, etc). */
|
|
32
|
+
name?: string;
|
|
33
|
+
/** Active chain symbol shown after the address. */
|
|
34
|
+
chainSymbol?: string;
|
|
35
|
+
onConnect?: () => void;
|
|
36
|
+
/** When provided, the pill becomes a click target (opens an account drawer, etc).
|
|
37
|
+
* When omitted, the pill defaults to click-to-copy. */
|
|
38
|
+
onClick?: () => void;
|
|
39
|
+
/** Loading state during connect/reconnect handshake. */
|
|
40
|
+
pending?: boolean;
|
|
41
|
+
className?: string;
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* WalletPill — top-right wallet affordance. Renders a CONNECT button when
|
|
45
|
+
* disconnected; a pill with truncated address (+ optional ENS, chain symbol)
|
|
46
|
+
* when connected. Wallet-library agnostic — pass state in via props.
|
|
47
|
+
*/
|
|
48
|
+
declare const WalletPill: ({ address, name, chainSymbol, onConnect, onClick, pending, className, }: WalletPillProps) => react_jsx_runtime.JSX.Element;
|
|
49
|
+
|
|
50
|
+
interface NetworkStatusProps {
|
|
51
|
+
/** "online" | "degraded" | "offline" */
|
|
52
|
+
state?: 'online' | 'degraded' | 'offline';
|
|
53
|
+
/** Latency in ms, rendered as "42ms". */
|
|
54
|
+
latencyMs?: number;
|
|
55
|
+
/** Optional override label ("NET ONLINE", "RPC DOWN", etc). */
|
|
56
|
+
label?: string;
|
|
57
|
+
className?: string;
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* NetworkStatus — the pulsing network-state pill from the header. Pairs
|
|
61
|
+
* with RPC health checks or a wagmi `useBlockNumber` watcher.
|
|
62
|
+
*/
|
|
63
|
+
declare const NetworkStatus: ({ state, latencyMs, label, className, }: NetworkStatusProps) => react_jsx_runtime.JSX.Element;
|
|
64
|
+
|
|
65
|
+
interface ChainSelectorProps {
|
|
66
|
+
chains: ChainBrief[];
|
|
67
|
+
/** Selected chain id. */
|
|
68
|
+
value: ChainBrief['id'];
|
|
69
|
+
onChange?: (id: ChainBrief['id']) => void;
|
|
70
|
+
className?: string;
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* ChainSelector — a minimal dropdown for switching active networks. Pure
|
|
74
|
+
* controlled component — pair with wagmi's `useSwitchChain` for execution.
|
|
75
|
+
*
|
|
76
|
+
* For dApps that need testnet/mainnet groupings, sort the `chains` prop
|
|
77
|
+
* upstream (testnets last) — this component renders them in input order.
|
|
78
|
+
*/
|
|
79
|
+
declare const ChainSelector: ({ chains, value, onChange, className, }: ChainSelectorProps) => react_jsx_runtime.JSX.Element | null;
|
|
80
|
+
|
|
81
|
+
interface GasIndicatorProps {
|
|
82
|
+
/** Current gas price in wei (bigint) or gwei (pass `unit="gwei"`). */
|
|
83
|
+
value: bigint | string | number;
|
|
84
|
+
/** Unit of the `value` prop. Defaults wei. */
|
|
85
|
+
unit?: 'wei' | 'gwei';
|
|
86
|
+
/** Optional threshold gwei values that flip tone (warn/err). */
|
|
87
|
+
thresholds?: {
|
|
88
|
+
warn: number;
|
|
89
|
+
err: number;
|
|
90
|
+
};
|
|
91
|
+
/** Label prefix. Defaults "GAS". */
|
|
92
|
+
label?: string;
|
|
93
|
+
className?: string;
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* GasIndicator — chip showing current gas price with tone shifts at warn/err
|
|
97
|
+
* thresholds. Drop into the footer status bar or near tx CTAs.
|
|
98
|
+
*/
|
|
99
|
+
declare const GasIndicator: ({ value, unit, thresholds, label, className, }: GasIndicatorProps) => react_jsx_runtime.JSX.Element;
|
|
100
|
+
|
|
101
|
+
interface TxStatusProps {
|
|
102
|
+
state: TxState;
|
|
103
|
+
/** Tx hash, when available. */
|
|
104
|
+
hash?: string;
|
|
105
|
+
/** Optional block explorer URL to link to. */
|
|
106
|
+
explorerUrl?: string;
|
|
107
|
+
/** Optional title (defaults from state). */
|
|
108
|
+
title?: string;
|
|
109
|
+
/** Confirmations seen so far. */
|
|
110
|
+
confirmations?: number;
|
|
111
|
+
/** Required confirmations target. */
|
|
112
|
+
requiredConfirmations?: number;
|
|
113
|
+
className?: string;
|
|
114
|
+
}
|
|
115
|
+
/**
|
|
116
|
+
* TxStatus — transaction lifecycle indicator. Six canonical states, each
|
|
117
|
+
* with its own tone + dot/badge. Pair with wagmi's `useWaitForTransactionReceipt`
|
|
118
|
+
* to drive state, or any custom signer flow.
|
|
119
|
+
*/
|
|
120
|
+
declare const TxStatus: ({ state, hash, explorerUrl, title, confirmations, requiredConfirmations, className, }: TxStatusProps) => react_jsx_runtime.JSX.Element;
|
|
121
|
+
|
|
122
|
+
interface AmountDisplayProps {
|
|
123
|
+
/** Raw value in base units (e.g. wei for ETH). */
|
|
124
|
+
value: bigint | string;
|
|
125
|
+
/** Decimal places of the token. */
|
|
126
|
+
decimals: number;
|
|
127
|
+
/** Symbol to render after the amount. */
|
|
128
|
+
symbol?: string;
|
|
129
|
+
/** Decimals to display. Defaults 4. */
|
|
130
|
+
displayDecimals?: number;
|
|
131
|
+
/** Size scale of the rendered amount. */
|
|
132
|
+
size?: 'sm' | 'md' | 'lg' | 'xl';
|
|
133
|
+
/** USD value (numeric). Renders as a caption beneath. */
|
|
134
|
+
usd?: number;
|
|
135
|
+
className?: string;
|
|
136
|
+
}
|
|
137
|
+
/**
|
|
138
|
+
* AmountDisplay — formats a base-unit bigint as a tabular-nums token amount
|
|
139
|
+
* with optional USD caption. Use for balances, deposits, claim amounts.
|
|
140
|
+
*/
|
|
141
|
+
declare const AmountDisplay: ({ value, decimals, symbol, displayDecimals, size, usd, className, }: AmountDisplayProps) => react_jsx_runtime.JSX.Element;
|
|
142
|
+
|
|
143
|
+
export { AddressDisplay, type AddressDisplayProps, AmountDisplay, type AmountDisplayProps, ChainBrief, ChainSelector, type ChainSelectorProps, GasIndicator, type GasIndicatorProps, NetworkStatus, type NetworkStatusProps, TxState, TxStatus, type TxStatusProps, WalletPill, type WalletPillProps };
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
|
+
import { ChainBrief, TxState } from './utils.js';
|
|
3
|
+
export { TruncateAddressOpts, formatGwei, formatUnits, truncateAddress } from './utils.js';
|
|
4
|
+
|
|
5
|
+
interface AddressDisplayProps {
|
|
6
|
+
/** Raw address. */
|
|
7
|
+
address: string;
|
|
8
|
+
/** Optional ENS / display name override. */
|
|
9
|
+
name?: string;
|
|
10
|
+
/** Show a small chain symbol after the address. */
|
|
11
|
+
chainSymbol?: string;
|
|
12
|
+
/** Enable click-to-copy. Defaults true. */
|
|
13
|
+
copyable?: boolean;
|
|
14
|
+
/** Surface treatment. */
|
|
15
|
+
variant?: 'pill' | 'inline';
|
|
16
|
+
/** Truncation params. */
|
|
17
|
+
head?: number;
|
|
18
|
+
tail?: number;
|
|
19
|
+
className?: string;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* AddressDisplay — wallet address with optional name resolution, chain
|
|
23
|
+
* label, and click-to-copy. Chain-agnostic — you resolve ENS/name yourself
|
|
24
|
+
* (e.g. via wagmi's useEnsName) and pass it as `name`.
|
|
25
|
+
*/
|
|
26
|
+
declare const AddressDisplay: ({ address, name, chainSymbol, copyable, variant, head, tail, className, }: AddressDisplayProps) => react_jsx_runtime.JSX.Element;
|
|
27
|
+
|
|
28
|
+
interface WalletPillProps {
|
|
29
|
+
/** Address — undefined renders the connect CTA. */
|
|
30
|
+
address?: string;
|
|
31
|
+
/** Display name (ENS, etc). */
|
|
32
|
+
name?: string;
|
|
33
|
+
/** Active chain symbol shown after the address. */
|
|
34
|
+
chainSymbol?: string;
|
|
35
|
+
onConnect?: () => void;
|
|
36
|
+
/** When provided, the pill becomes a click target (opens an account drawer, etc).
|
|
37
|
+
* When omitted, the pill defaults to click-to-copy. */
|
|
38
|
+
onClick?: () => void;
|
|
39
|
+
/** Loading state during connect/reconnect handshake. */
|
|
40
|
+
pending?: boolean;
|
|
41
|
+
className?: string;
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* WalletPill — top-right wallet affordance. Renders a CONNECT button when
|
|
45
|
+
* disconnected; a pill with truncated address (+ optional ENS, chain symbol)
|
|
46
|
+
* when connected. Wallet-library agnostic — pass state in via props.
|
|
47
|
+
*/
|
|
48
|
+
declare const WalletPill: ({ address, name, chainSymbol, onConnect, onClick, pending, className, }: WalletPillProps) => react_jsx_runtime.JSX.Element;
|
|
49
|
+
|
|
50
|
+
interface NetworkStatusProps {
|
|
51
|
+
/** "online" | "degraded" | "offline" */
|
|
52
|
+
state?: 'online' | 'degraded' | 'offline';
|
|
53
|
+
/** Latency in ms, rendered as "42ms". */
|
|
54
|
+
latencyMs?: number;
|
|
55
|
+
/** Optional override label ("NET ONLINE", "RPC DOWN", etc). */
|
|
56
|
+
label?: string;
|
|
57
|
+
className?: string;
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* NetworkStatus — the pulsing network-state pill from the header. Pairs
|
|
61
|
+
* with RPC health checks or a wagmi `useBlockNumber` watcher.
|
|
62
|
+
*/
|
|
63
|
+
declare const NetworkStatus: ({ state, latencyMs, label, className, }: NetworkStatusProps) => react_jsx_runtime.JSX.Element;
|
|
64
|
+
|
|
65
|
+
interface ChainSelectorProps {
|
|
66
|
+
chains: ChainBrief[];
|
|
67
|
+
/** Selected chain id. */
|
|
68
|
+
value: ChainBrief['id'];
|
|
69
|
+
onChange?: (id: ChainBrief['id']) => void;
|
|
70
|
+
className?: string;
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* ChainSelector — a minimal dropdown for switching active networks. Pure
|
|
74
|
+
* controlled component — pair with wagmi's `useSwitchChain` for execution.
|
|
75
|
+
*
|
|
76
|
+
* For dApps that need testnet/mainnet groupings, sort the `chains` prop
|
|
77
|
+
* upstream (testnets last) — this component renders them in input order.
|
|
78
|
+
*/
|
|
79
|
+
declare const ChainSelector: ({ chains, value, onChange, className, }: ChainSelectorProps) => react_jsx_runtime.JSX.Element | null;
|
|
80
|
+
|
|
81
|
+
interface GasIndicatorProps {
|
|
82
|
+
/** Current gas price in wei (bigint) or gwei (pass `unit="gwei"`). */
|
|
83
|
+
value: bigint | string | number;
|
|
84
|
+
/** Unit of the `value` prop. Defaults wei. */
|
|
85
|
+
unit?: 'wei' | 'gwei';
|
|
86
|
+
/** Optional threshold gwei values that flip tone (warn/err). */
|
|
87
|
+
thresholds?: {
|
|
88
|
+
warn: number;
|
|
89
|
+
err: number;
|
|
90
|
+
};
|
|
91
|
+
/** Label prefix. Defaults "GAS". */
|
|
92
|
+
label?: string;
|
|
93
|
+
className?: string;
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* GasIndicator — chip showing current gas price with tone shifts at warn/err
|
|
97
|
+
* thresholds. Drop into the footer status bar or near tx CTAs.
|
|
98
|
+
*/
|
|
99
|
+
declare const GasIndicator: ({ value, unit, thresholds, label, className, }: GasIndicatorProps) => react_jsx_runtime.JSX.Element;
|
|
100
|
+
|
|
101
|
+
interface TxStatusProps {
|
|
102
|
+
state: TxState;
|
|
103
|
+
/** Tx hash, when available. */
|
|
104
|
+
hash?: string;
|
|
105
|
+
/** Optional block explorer URL to link to. */
|
|
106
|
+
explorerUrl?: string;
|
|
107
|
+
/** Optional title (defaults from state). */
|
|
108
|
+
title?: string;
|
|
109
|
+
/** Confirmations seen so far. */
|
|
110
|
+
confirmations?: number;
|
|
111
|
+
/** Required confirmations target. */
|
|
112
|
+
requiredConfirmations?: number;
|
|
113
|
+
className?: string;
|
|
114
|
+
}
|
|
115
|
+
/**
|
|
116
|
+
* TxStatus — transaction lifecycle indicator. Six canonical states, each
|
|
117
|
+
* with its own tone + dot/badge. Pair with wagmi's `useWaitForTransactionReceipt`
|
|
118
|
+
* to drive state, or any custom signer flow.
|
|
119
|
+
*/
|
|
120
|
+
declare const TxStatus: ({ state, hash, explorerUrl, title, confirmations, requiredConfirmations, className, }: TxStatusProps) => react_jsx_runtime.JSX.Element;
|
|
121
|
+
|
|
122
|
+
interface AmountDisplayProps {
|
|
123
|
+
/** Raw value in base units (e.g. wei for ETH). */
|
|
124
|
+
value: bigint | string;
|
|
125
|
+
/** Decimal places of the token. */
|
|
126
|
+
decimals: number;
|
|
127
|
+
/** Symbol to render after the amount. */
|
|
128
|
+
symbol?: string;
|
|
129
|
+
/** Decimals to display. Defaults 4. */
|
|
130
|
+
displayDecimals?: number;
|
|
131
|
+
/** Size scale of the rendered amount. */
|
|
132
|
+
size?: 'sm' | 'md' | 'lg' | 'xl';
|
|
133
|
+
/** USD value (numeric). Renders as a caption beneath. */
|
|
134
|
+
usd?: number;
|
|
135
|
+
className?: string;
|
|
136
|
+
}
|
|
137
|
+
/**
|
|
138
|
+
* AmountDisplay — formats a base-unit bigint as a tabular-nums token amount
|
|
139
|
+
* with optional USD caption. Use for balances, deposits, claim amounts.
|
|
140
|
+
*/
|
|
141
|
+
declare const AmountDisplay: ({ value, decimals, symbol, displayDecimals, size, usd, className, }: AmountDisplayProps) => react_jsx_runtime.JSX.Element;
|
|
142
|
+
|
|
143
|
+
export { AddressDisplay, type AddressDisplayProps, AmountDisplay, type AmountDisplayProps, ChainBrief, ChainSelector, type ChainSelectorProps, GasIndicator, type GasIndicatorProps, NetworkStatus, type NetworkStatusProps, TxState, TxStatus, type TxStatusProps, WalletPill, type WalletPillProps };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,376 @@
|
|
|
1
|
+
import { truncateAddress, formatGwei, formatUnits } from './chunk-AMDZMZJO.js';
|
|
2
|
+
export { formatGwei, formatUnits, truncateAddress } from './chunk-AMDZMZJO.js';
|
|
3
|
+
import { useState, useCallback } from 'react';
|
|
4
|
+
import { cn, Button, PulseDot, StatusBadge } from '@lumen-dapps-kit/ui';
|
|
5
|
+
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
6
|
+
|
|
7
|
+
var AddressDisplay = ({
|
|
8
|
+
address,
|
|
9
|
+
name,
|
|
10
|
+
chainSymbol,
|
|
11
|
+
copyable = true,
|
|
12
|
+
variant = "pill",
|
|
13
|
+
head = 4,
|
|
14
|
+
tail = 4,
|
|
15
|
+
className
|
|
16
|
+
}) => {
|
|
17
|
+
const [copied, setCopied] = useState(false);
|
|
18
|
+
const handleCopy = useCallback(async () => {
|
|
19
|
+
if (!copyable || !address) return;
|
|
20
|
+
try {
|
|
21
|
+
await navigator.clipboard.writeText(address);
|
|
22
|
+
setCopied(true);
|
|
23
|
+
setTimeout(() => setCopied(false), 1200);
|
|
24
|
+
} catch {
|
|
25
|
+
}
|
|
26
|
+
}, [address, copyable]);
|
|
27
|
+
const label = name || truncateAddress(address, { head, tail });
|
|
28
|
+
if (variant === "inline") {
|
|
29
|
+
return /* @__PURE__ */ jsx(
|
|
30
|
+
"button",
|
|
31
|
+
{
|
|
32
|
+
type: "button",
|
|
33
|
+
onClick: handleCopy,
|
|
34
|
+
disabled: !copyable,
|
|
35
|
+
className: cn(
|
|
36
|
+
"mono text-[11px] text-ink-900 hover:text-white transition-colors",
|
|
37
|
+
className
|
|
38
|
+
),
|
|
39
|
+
title: address,
|
|
40
|
+
children: copied ? "COPIED" : label
|
|
41
|
+
}
|
|
42
|
+
);
|
|
43
|
+
}
|
|
44
|
+
return /* @__PURE__ */ jsxs(
|
|
45
|
+
"button",
|
|
46
|
+
{
|
|
47
|
+
type: "button",
|
|
48
|
+
onClick: handleCopy,
|
|
49
|
+
disabled: !copyable,
|
|
50
|
+
title: address,
|
|
51
|
+
className: cn(
|
|
52
|
+
"flex items-center gap-2 px-3 h-8 hairline mono text-[11px] transition-colors",
|
|
53
|
+
copyable && "hover:bg-white/5",
|
|
54
|
+
className
|
|
55
|
+
),
|
|
56
|
+
children: [
|
|
57
|
+
/* @__PURE__ */ jsx("span", { className: "w-1.5 h-1.5 bg-white", "aria-hidden": "true" }),
|
|
58
|
+
/* @__PURE__ */ jsx("span", { className: "text-ink-900", children: copied ? "COPIED" : label }),
|
|
59
|
+
chainSymbol && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
60
|
+
/* @__PURE__ */ jsx("span", { className: "text-ink-700", children: "\xB7" }),
|
|
61
|
+
/* @__PURE__ */ jsx("span", { className: "text-ink-700", children: chainSymbol })
|
|
62
|
+
] })
|
|
63
|
+
]
|
|
64
|
+
}
|
|
65
|
+
);
|
|
66
|
+
};
|
|
67
|
+
var WalletPill = ({
|
|
68
|
+
address,
|
|
69
|
+
name,
|
|
70
|
+
chainSymbol,
|
|
71
|
+
onConnect,
|
|
72
|
+
onClick,
|
|
73
|
+
pending,
|
|
74
|
+
className
|
|
75
|
+
}) => {
|
|
76
|
+
const [copied, setCopied] = useState(false);
|
|
77
|
+
const handleCopy = useCallback(async () => {
|
|
78
|
+
if (!address) return;
|
|
79
|
+
try {
|
|
80
|
+
await navigator.clipboard.writeText(address);
|
|
81
|
+
setCopied(true);
|
|
82
|
+
setTimeout(() => setCopied(false), 1200);
|
|
83
|
+
} catch {
|
|
84
|
+
}
|
|
85
|
+
}, [address]);
|
|
86
|
+
if (!address) {
|
|
87
|
+
return /* @__PURE__ */ jsx(
|
|
88
|
+
Button,
|
|
89
|
+
{
|
|
90
|
+
variant: "primary",
|
|
91
|
+
size: "sm",
|
|
92
|
+
onClick: onConnect,
|
|
93
|
+
disabled: pending,
|
|
94
|
+
className: cn(className),
|
|
95
|
+
children: pending ? "CONNECTING\u2026" : "CONNECT WALLET"
|
|
96
|
+
}
|
|
97
|
+
);
|
|
98
|
+
}
|
|
99
|
+
const handleClick = onClick ?? handleCopy;
|
|
100
|
+
const label = copied ? "COPIED" : name || truncateAddress(address);
|
|
101
|
+
return /* @__PURE__ */ jsxs(
|
|
102
|
+
"button",
|
|
103
|
+
{
|
|
104
|
+
type: "button",
|
|
105
|
+
onClick: handleClick,
|
|
106
|
+
title: address,
|
|
107
|
+
className: cn(
|
|
108
|
+
"flex items-center gap-2 px-3 h-8 hairline mono text-[11px] hover:bg-white/5 transition-colors",
|
|
109
|
+
className
|
|
110
|
+
),
|
|
111
|
+
children: [
|
|
112
|
+
/* @__PURE__ */ jsx("span", { className: "w-1.5 h-1.5 bg-white", "aria-hidden": "true" }),
|
|
113
|
+
/* @__PURE__ */ jsx("span", { className: "text-ink-900", children: label }),
|
|
114
|
+
chainSymbol && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
115
|
+
/* @__PURE__ */ jsx("span", { className: "text-ink-700", children: "\xB7" }),
|
|
116
|
+
/* @__PURE__ */ jsx("span", { className: "text-ink-700", children: chainSymbol })
|
|
117
|
+
] })
|
|
118
|
+
]
|
|
119
|
+
}
|
|
120
|
+
);
|
|
121
|
+
};
|
|
122
|
+
var TONE = {
|
|
123
|
+
online: { dot: "ok", txt: "NET ONLINE" },
|
|
124
|
+
degraded: { dot: "warn", txt: "NET DEGRADED" },
|
|
125
|
+
offline: { dot: "err", txt: "NET OFFLINE" }
|
|
126
|
+
};
|
|
127
|
+
var NetworkStatus = ({
|
|
128
|
+
state = "online",
|
|
129
|
+
latencyMs,
|
|
130
|
+
label,
|
|
131
|
+
className
|
|
132
|
+
}) => {
|
|
133
|
+
const tone = TONE[state];
|
|
134
|
+
return /* @__PURE__ */ jsxs(
|
|
135
|
+
"div",
|
|
136
|
+
{
|
|
137
|
+
className: cn(
|
|
138
|
+
"flex items-center gap-2 px-3 h-8 hairline mono text-[11px] text-ink-800",
|
|
139
|
+
className
|
|
140
|
+
),
|
|
141
|
+
children: [
|
|
142
|
+
/* @__PURE__ */ jsx(PulseDot, { tone: tone.dot }),
|
|
143
|
+
/* @__PURE__ */ jsx("span", { children: label ?? tone.txt }),
|
|
144
|
+
typeof latencyMs === "number" && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
145
|
+
/* @__PURE__ */ jsx("span", { className: "text-ink-600", children: "\xB7" }),
|
|
146
|
+
/* @__PURE__ */ jsxs("span", { className: "text-ink-700", children: [
|
|
147
|
+
Math.round(latencyMs),
|
|
148
|
+
"ms"
|
|
149
|
+
] })
|
|
150
|
+
] })
|
|
151
|
+
]
|
|
152
|
+
}
|
|
153
|
+
);
|
|
154
|
+
};
|
|
155
|
+
var ChainSelector = ({
|
|
156
|
+
chains,
|
|
157
|
+
value,
|
|
158
|
+
onChange,
|
|
159
|
+
className
|
|
160
|
+
}) => {
|
|
161
|
+
const [open, setOpen] = useState(false);
|
|
162
|
+
const active = chains.find((c) => c.id === value) ?? chains[0];
|
|
163
|
+
if (!active) return null;
|
|
164
|
+
return /* @__PURE__ */ jsxs("div", { className: cn("relative", className), children: [
|
|
165
|
+
/* @__PURE__ */ jsxs(
|
|
166
|
+
"button",
|
|
167
|
+
{
|
|
168
|
+
type: "button",
|
|
169
|
+
onClick: () => setOpen((o) => !o),
|
|
170
|
+
"aria-haspopup": "listbox",
|
|
171
|
+
"aria-expanded": open,
|
|
172
|
+
className: "flex items-center gap-2 px-3 h-8 hairline mono text-[11px] hover:bg-white/5",
|
|
173
|
+
children: [
|
|
174
|
+
/* @__PURE__ */ jsx(
|
|
175
|
+
"span",
|
|
176
|
+
{
|
|
177
|
+
className: "w-1.5 h-1.5",
|
|
178
|
+
style: { backgroundColor: active.color ?? "#ffffff" },
|
|
179
|
+
"aria-hidden": "true"
|
|
180
|
+
}
|
|
181
|
+
),
|
|
182
|
+
/* @__PURE__ */ jsx("span", { className: "text-ink-900", children: active.symbol }),
|
|
183
|
+
/* @__PURE__ */ jsx("span", { className: "text-ink-700", children: "\xB7" }),
|
|
184
|
+
/* @__PURE__ */ jsx("span", { className: "text-ink-700 text-[10.5px]", children: active.name }),
|
|
185
|
+
active.testnet && /* @__PURE__ */ jsx("span", { className: "text-signal-warn ml-1", children: "TESTNET" })
|
|
186
|
+
]
|
|
187
|
+
}
|
|
188
|
+
),
|
|
189
|
+
open && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
190
|
+
/* @__PURE__ */ jsx(
|
|
191
|
+
"div",
|
|
192
|
+
{
|
|
193
|
+
className: "fixed inset-0 z-40",
|
|
194
|
+
onClick: () => setOpen(false),
|
|
195
|
+
"aria-hidden": "true"
|
|
196
|
+
}
|
|
197
|
+
),
|
|
198
|
+
/* @__PURE__ */ jsx(
|
|
199
|
+
"div",
|
|
200
|
+
{
|
|
201
|
+
role: "listbox",
|
|
202
|
+
className: "absolute right-0 mt-1 min-w-[240px] glass z-50 p-1",
|
|
203
|
+
children: chains.map((c) => {
|
|
204
|
+
const selected = c.id === value;
|
|
205
|
+
return /* @__PURE__ */ jsxs(
|
|
206
|
+
"button",
|
|
207
|
+
{
|
|
208
|
+
role: "option",
|
|
209
|
+
"aria-selected": selected,
|
|
210
|
+
type: "button",
|
|
211
|
+
onClick: () => {
|
|
212
|
+
onChange?.(c.id);
|
|
213
|
+
setOpen(false);
|
|
214
|
+
},
|
|
215
|
+
className: cn(
|
|
216
|
+
"w-full flex items-center gap-2 px-3 h-8 mono text-[11px] text-left transition-colors",
|
|
217
|
+
selected ? "bg-white text-black" : "text-ink-800 hover:bg-white/5"
|
|
218
|
+
),
|
|
219
|
+
children: [
|
|
220
|
+
/* @__PURE__ */ jsx(
|
|
221
|
+
"span",
|
|
222
|
+
{
|
|
223
|
+
className: "w-1.5 h-1.5",
|
|
224
|
+
style: { backgroundColor: c.color ?? "#ffffff" },
|
|
225
|
+
"aria-hidden": "true"
|
|
226
|
+
}
|
|
227
|
+
),
|
|
228
|
+
/* @__PURE__ */ jsx(
|
|
229
|
+
"span",
|
|
230
|
+
{
|
|
231
|
+
className: cn(
|
|
232
|
+
"font-medium",
|
|
233
|
+
selected ? "text-black" : "text-ink-900"
|
|
234
|
+
),
|
|
235
|
+
children: c.symbol
|
|
236
|
+
}
|
|
237
|
+
),
|
|
238
|
+
/* @__PURE__ */ jsxs(
|
|
239
|
+
"span",
|
|
240
|
+
{
|
|
241
|
+
className: cn(
|
|
242
|
+
selected ? "text-black/60" : "text-ink-700"
|
|
243
|
+
),
|
|
244
|
+
children: [
|
|
245
|
+
"\xB7 ",
|
|
246
|
+
c.name
|
|
247
|
+
]
|
|
248
|
+
}
|
|
249
|
+
),
|
|
250
|
+
c.testnet && /* @__PURE__ */ jsx(
|
|
251
|
+
"span",
|
|
252
|
+
{
|
|
253
|
+
className: cn(
|
|
254
|
+
"ml-auto",
|
|
255
|
+
selected ? "text-black" : "text-signal-warn"
|
|
256
|
+
),
|
|
257
|
+
children: "TESTNET"
|
|
258
|
+
}
|
|
259
|
+
)
|
|
260
|
+
]
|
|
261
|
+
},
|
|
262
|
+
c.id
|
|
263
|
+
);
|
|
264
|
+
})
|
|
265
|
+
}
|
|
266
|
+
)
|
|
267
|
+
] })
|
|
268
|
+
] });
|
|
269
|
+
};
|
|
270
|
+
var GasIndicator = ({
|
|
271
|
+
value,
|
|
272
|
+
unit = "wei",
|
|
273
|
+
thresholds = { warn: 40, err: 100 },
|
|
274
|
+
label = "GAS",
|
|
275
|
+
className
|
|
276
|
+
}) => {
|
|
277
|
+
const gwei = unit === "gwei" ? Number(value) : Number(typeof value === "bigint" ? value : BigInt(value)) / 1e9;
|
|
278
|
+
const tone = gwei >= thresholds.err ? "text-signal-err" : gwei >= thresholds.warn ? "text-signal-warn" : "text-signal-ok";
|
|
279
|
+
return /* @__PURE__ */ jsxs("span", { className: cn("mono text-[10.5px] tracking-wider", className), children: [
|
|
280
|
+
/* @__PURE__ */ jsx("span", { className: "text-ink-800", children: label }),
|
|
281
|
+
" ",
|
|
282
|
+
/* @__PURE__ */ jsxs("span", { className: cn("tabular-nums", tone), children: [
|
|
283
|
+
formatGwei(value),
|
|
284
|
+
" gwei"
|
|
285
|
+
] })
|
|
286
|
+
] });
|
|
287
|
+
};
|
|
288
|
+
var COPY = {
|
|
289
|
+
idle: { title: "IDLE", tone: "muted", live: false },
|
|
290
|
+
preparing: { title: "PREPARING", tone: "data", live: true },
|
|
291
|
+
"awaiting-signature": { title: "AWAITING SIGNATURE", tone: "warn", live: true },
|
|
292
|
+
pending: { title: "PENDING", tone: "data", live: true },
|
|
293
|
+
confirmed: { title: "CONFIRMED", tone: "ok", live: false },
|
|
294
|
+
failed: { title: "FAILED", tone: "err", live: false },
|
|
295
|
+
rejected: { title: "REJECTED", tone: "err", live: false }
|
|
296
|
+
};
|
|
297
|
+
var TxStatus = ({
|
|
298
|
+
state,
|
|
299
|
+
hash,
|
|
300
|
+
explorerUrl,
|
|
301
|
+
title,
|
|
302
|
+
confirmations,
|
|
303
|
+
requiredConfirmations,
|
|
304
|
+
className
|
|
305
|
+
}) => {
|
|
306
|
+
const copy = COPY[state];
|
|
307
|
+
const label = title ?? copy.title;
|
|
308
|
+
const link = hash && explorerUrl ? `${explorerUrl.replace(/\/$/, "")}/tx/${hash}` : void 0;
|
|
309
|
+
return /* @__PURE__ */ jsxs(
|
|
310
|
+
"div",
|
|
311
|
+
{
|
|
312
|
+
className: cn(
|
|
313
|
+
"flex items-center justify-between hairline px-3 py-2.5",
|
|
314
|
+
className
|
|
315
|
+
),
|
|
316
|
+
children: [
|
|
317
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2.5", children: [
|
|
318
|
+
copy.live ? /* @__PURE__ */ jsx(PulseDot, { tone: copy.tone === "muted" ? "data" : copy.tone }) : /* @__PURE__ */ jsx(StatusBadge, { tone: copy.tone, dot: true, children: "" }),
|
|
319
|
+
/* @__PURE__ */ jsx("span", { className: "mono text-[11px] text-ink-900", children: label })
|
|
320
|
+
] }),
|
|
321
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-3 mono text-[10.5px] text-ink-700", children: [
|
|
322
|
+
typeof confirmations === "number" && typeof requiredConfirmations === "number" && /* @__PURE__ */ jsxs("span", { className: "tabular-nums", children: [
|
|
323
|
+
confirmations,
|
|
324
|
+
"/",
|
|
325
|
+
requiredConfirmations,
|
|
326
|
+
" CONF"
|
|
327
|
+
] }),
|
|
328
|
+
hash && (link ? /* @__PURE__ */ jsx(
|
|
329
|
+
"a",
|
|
330
|
+
{
|
|
331
|
+
href: link,
|
|
332
|
+
target: "_blank",
|
|
333
|
+
rel: "noreferrer",
|
|
334
|
+
className: "text-ink-800 hover:text-white underline-offset-2 hover:underline",
|
|
335
|
+
children: truncateAddress(hash, { head: 6, tail: 4 })
|
|
336
|
+
}
|
|
337
|
+
) : /* @__PURE__ */ jsx("span", { className: "text-ink-800", children: truncateAddress(hash, { head: 6, tail: 4 }) }))
|
|
338
|
+
] })
|
|
339
|
+
]
|
|
340
|
+
}
|
|
341
|
+
);
|
|
342
|
+
};
|
|
343
|
+
var SIZE = {
|
|
344
|
+
sm: "text-[14px]",
|
|
345
|
+
md: "text-[18px]",
|
|
346
|
+
lg: "text-[24px]",
|
|
347
|
+
xl: "text-[40px]"
|
|
348
|
+
};
|
|
349
|
+
var AmountDisplay = ({
|
|
350
|
+
value,
|
|
351
|
+
decimals,
|
|
352
|
+
symbol,
|
|
353
|
+
displayDecimals = 4,
|
|
354
|
+
size = "md",
|
|
355
|
+
usd,
|
|
356
|
+
className
|
|
357
|
+
}) => /* @__PURE__ */ jsxs("div", { className: cn("leading-none", className), children: [
|
|
358
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-baseline gap-1", children: [
|
|
359
|
+
/* @__PURE__ */ jsx(
|
|
360
|
+
"span",
|
|
361
|
+
{
|
|
362
|
+
className: cn("font-semibold tabular-nums tracking-tight", SIZE[size]),
|
|
363
|
+
children: formatUnits(value, decimals, displayDecimals)
|
|
364
|
+
}
|
|
365
|
+
),
|
|
366
|
+
symbol && /* @__PURE__ */ jsx("span", { className: "text-ink-700 text-[11px]", children: symbol })
|
|
367
|
+
] }),
|
|
368
|
+
typeof usd === "number" && /* @__PURE__ */ jsxs("div", { className: "mono text-[10.5px] text-ink-700 mt-1 tabular-nums", children: [
|
|
369
|
+
"$",
|
|
370
|
+
usd.toLocaleString("en-US", { maximumFractionDigits: 2 })
|
|
371
|
+
] })
|
|
372
|
+
] });
|
|
373
|
+
|
|
374
|
+
export { AddressDisplay, AmountDisplay, ChainSelector, GasIndicator, NetworkStatus, TxStatus, WalletPill };
|
|
375
|
+
//# sourceMappingURL=index.js.map
|
|
376
|
+
//# sourceMappingURL=index.js.map
|