@liberfi.io/ui-chain-select 0.1.24 → 0.1.26
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/README.md +229 -0
- package/dist/index.d.mts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +1 -1
- package/dist/index.mjs.map +1 -1
- package/package.json +13 -7
package/README.md
ADDED
|
@@ -0,0 +1,229 @@
|
|
|
1
|
+
# @liberfi.io/ui-chain-select
|
|
2
|
+
|
|
3
|
+
Chain selection UI and state management for the Liberfi React SDK. Provides a responsive chain selector widget (desktop popover / mobile icon buttons), Jotai-based state atoms, and hooks for reading and switching the current chain. Consumed by app-level packages and widgets that need chain-aware behaviour.
|
|
4
|
+
|
|
5
|
+
## Design Philosophy
|
|
6
|
+
|
|
7
|
+
- **State / Hooks / UI layering** — Jotai atoms own the chain state; hooks read/write atoms and invoke callbacks; the widget wires them together; UI components are purely presentational and can be used independently.
|
|
8
|
+
- **Inversion of control** — All side effects (wallet switching, toast, analytics) are delegated to the caller via `onSwitchChain`, `onSuccess`, and `onError` callbacks. The package never hardcodes feedback.
|
|
9
|
+
- **Optional Provider** — Works out of the box with default atoms (zero-config). Wrap with `ChainSelectProvider` only when multiple independent chain selectors need to coexist (different `storageKeyPrefix`).
|
|
10
|
+
- **Single source of truth** — `Chain` and `ChainNamespace` types come from `@liberfi.io/types`; display names, colors, icons, and `chainToNamespace` come from `@liberfi.io/utils` and `@liberfi.io/ui`.
|
|
11
|
+
|
|
12
|
+
## Installation
|
|
13
|
+
|
|
14
|
+
```bash
|
|
15
|
+
pnpm add @liberfi.io/ui-chain-select
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
### Peer dependencies
|
|
19
|
+
|
|
20
|
+
The consumer must provide:
|
|
21
|
+
|
|
22
|
+
| Package | Version |
|
|
23
|
+
| ----------- | --------- |
|
|
24
|
+
| `react` | >= 18 |
|
|
25
|
+
| `react-dom` | >= 18 |
|
|
26
|
+
| `jotai` | >= 2.15.1 |
|
|
27
|
+
|
|
28
|
+
## API Reference
|
|
29
|
+
|
|
30
|
+
### Components
|
|
31
|
+
|
|
32
|
+
#### `ChainSelectWidget`
|
|
33
|
+
|
|
34
|
+
Full-featured chain selector that wires state and callbacks. Drop-in usage — no Provider required.
|
|
35
|
+
|
|
36
|
+
```tsx
|
|
37
|
+
function ChainSelectWidget(props: ChainSelectWidgetProps): JSX.Element;
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
| Prop | Type | Default | Description |
|
|
41
|
+
| --------------- | --------------------------------- | ----------------------------- | ----------------------------------- |
|
|
42
|
+
| `size` | `"sm" \| "md" \| "lg"` | `undefined` | Button / item size |
|
|
43
|
+
| `className` | `string` | `undefined` | Class on the root element |
|
|
44
|
+
| `candidates` | `Chain[]` | `[SOLANA, ETHEREUM, BINANCE]` | Chains to offer |
|
|
45
|
+
| `onSwitchChain` | `(chain: Chain) => Promise<void>` | `undefined` | Async handler (e.g. wallet switch) |
|
|
46
|
+
| `onSuccess` | `(chain: Chain) => void` | `undefined` | Called after successful switch |
|
|
47
|
+
| `onError` | `(error: unknown) => void` | `undefined` | Called when `onSwitchChain` rejects |
|
|
48
|
+
|
|
49
|
+
#### `ChainSelectUI`
|
|
50
|
+
|
|
51
|
+
Presentational responsive shell. Renders `ChainSelectDesktopUI` or `ChainSelectMobileUI` based on viewport.
|
|
52
|
+
|
|
53
|
+
```tsx
|
|
54
|
+
function ChainSelectUI(props: ChainSelectUIProps): JSX.Element;
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
| Prop | Type | Default | Description |
|
|
58
|
+
| --------------- | ----------------------------------------- | -------------------- | ------------------------- |
|
|
59
|
+
| `size` | `"sm" \| "md" \| "lg"` | `undefined` | Button / item size |
|
|
60
|
+
| `chain` | `Chain` | `candidates[0]` | Currently selected chain |
|
|
61
|
+
| `candidates` | `Chain[]` | `DEFAULT_CANDIDATES` | Chains to show |
|
|
62
|
+
| `onSelectChain` | `(chain: Chain) => void \| Promise<void>` | `undefined` | Selection handler |
|
|
63
|
+
| `isSwitching` | `boolean` | `undefined` | Shows loading state |
|
|
64
|
+
| `className` | `string` | `undefined` | Class on the root element |
|
|
65
|
+
|
|
66
|
+
#### `ChainAvatar`
|
|
67
|
+
|
|
68
|
+
Renders a chain icon. Uses dedicated SVG icons for known chains, falls back to an `Avatar` with the chain's icon URL.
|
|
69
|
+
|
|
70
|
+
```tsx
|
|
71
|
+
function ChainAvatar(props: ChainAvatarProps): JSX.Element;
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
| Prop | Type | Description |
|
|
75
|
+
| ----------- | -------- | -------------------------- |
|
|
76
|
+
| `chain` | `Chain` | The chain to display |
|
|
77
|
+
| `className` | `string` | Class on the icon / avatar |
|
|
78
|
+
|
|
79
|
+
#### `ChainSelectProvider`
|
|
80
|
+
|
|
81
|
+
Optional context provider for multi-instance scenarios.
|
|
82
|
+
|
|
83
|
+
```tsx
|
|
84
|
+
function ChainSelectProvider(props: ChainSelectProviderProps): JSX.Element;
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
| Prop | Type | Default | Description |
|
|
88
|
+
| ------------------ | ----------- | ------- | ---------------------------- |
|
|
89
|
+
| `storageKeyPrefix` | `string` | `""` | Prefix for localStorage keys |
|
|
90
|
+
| `children` | `ReactNode` | — | Children |
|
|
91
|
+
|
|
92
|
+
### Hooks
|
|
93
|
+
|
|
94
|
+
#### `useSelectChain`
|
|
95
|
+
|
|
96
|
+
Returns a `selectChain` function and `isSwitching` state.
|
|
97
|
+
|
|
98
|
+
```typescript
|
|
99
|
+
function useSelectChain(options?: UseSelectChainOptions): {
|
|
100
|
+
selectChain: (chain: Chain) => Promise<void>;
|
|
101
|
+
isSwitching: boolean;
|
|
102
|
+
};
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
| Option | Type | Description |
|
|
106
|
+
| --------------- | --------------------------------- | ----------------------------------- |
|
|
107
|
+
| `onSwitchChain` | `(chain: Chain) => Promise<void>` | Async handler before state update |
|
|
108
|
+
| `onSuccess` | `(chain: Chain) => void` | Called after successful switch |
|
|
109
|
+
| `onError` | `(error: unknown) => void` | Called when `onSwitchChain` rejects |
|
|
110
|
+
|
|
111
|
+
#### `useCurrentChain`
|
|
112
|
+
|
|
113
|
+
Reads the current chain and namespace from state.
|
|
114
|
+
|
|
115
|
+
```typescript
|
|
116
|
+
function useCurrentChain(): {
|
|
117
|
+
chain: Chain;
|
|
118
|
+
chainNamespace: ChainNamespace;
|
|
119
|
+
};
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
### State (Jotai atoms)
|
|
123
|
+
|
|
124
|
+
| Export | Type | Description |
|
|
125
|
+
| -------------------- | --------------------------------- | ----------------------------------------------- |
|
|
126
|
+
| `chainAtom` | `WritableAtom<Chain>` | Default chain atom (key `"chain"`) |
|
|
127
|
+
| `chainNamespaceAtom` | `WritableAtom<ChainNamespace>` | Default namespace atom (key `"chainNamespace"`) |
|
|
128
|
+
| `defaultChainAtoms` | `ChainAtoms` | Bundle of both default atoms |
|
|
129
|
+
| `createChainAtoms` | `(prefix?: string) => ChainAtoms` | Factory for custom-prefixed atoms |
|
|
130
|
+
|
|
131
|
+
### Types
|
|
132
|
+
|
|
133
|
+
| Export | Description |
|
|
134
|
+
| ------------------------------ | ----------------------------------- |
|
|
135
|
+
| `ChainAtoms` | `{ chainAtom, chainNamespaceAtom }` |
|
|
136
|
+
| `ChainSelectStateContextValue` | Context value type |
|
|
137
|
+
| `ChainSelectProviderProps` | Props for `ChainSelectProvider` |
|
|
138
|
+
| `ChainSelectWidgetProps` | Props for `ChainSelectWidget` |
|
|
139
|
+
| `ChainSelectUIProps` | Props for `ChainSelectUI` |
|
|
140
|
+
| `ChainSelectDesktopUIProps` | Props for `ChainSelectDesktopUI` |
|
|
141
|
+
| `ChainSelectMobileUIProps` | Props for `ChainSelectMobileUI` |
|
|
142
|
+
| `ChainAvatarProps` | Props for `ChainAvatar` |
|
|
143
|
+
| `UseSelectChainOptions` | Options for `useSelectChain` |
|
|
144
|
+
|
|
145
|
+
### Constants
|
|
146
|
+
|
|
147
|
+
| Export | Type | Value |
|
|
148
|
+
| -------------------- | --------- | ----------------------------------------------- |
|
|
149
|
+
| `DEFAULT_CANDIDATES` | `Chain[]` | `[Chain.SOLANA, Chain.ETHEREUM, Chain.BINANCE]` |
|
|
150
|
+
|
|
151
|
+
## Usage Examples
|
|
152
|
+
|
|
153
|
+
### Basic usage
|
|
154
|
+
|
|
155
|
+
```tsx
|
|
156
|
+
import { ChainSelectWidget } from "@liberfi.io/ui-chain-select";
|
|
157
|
+
|
|
158
|
+
function App() {
|
|
159
|
+
return (
|
|
160
|
+
<ChainSelectWidget
|
|
161
|
+
onSwitchChain={async (chain) => {
|
|
162
|
+
await wallet.switchChain(chain);
|
|
163
|
+
}}
|
|
164
|
+
onSuccess={(chain) => toast.success(`Switched to ${chain}`)}
|
|
165
|
+
onError={(err) => toast.error("Switch failed")}
|
|
166
|
+
/>
|
|
167
|
+
);
|
|
168
|
+
}
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
### Presentational-only (no state management)
|
|
172
|
+
|
|
173
|
+
```tsx
|
|
174
|
+
import { Chain } from "@liberfi.io/types";
|
|
175
|
+
import { ChainSelectUI } from "@liberfi.io/ui-chain-select";
|
|
176
|
+
|
|
177
|
+
function ReadOnlyChainDisplay() {
|
|
178
|
+
return (
|
|
179
|
+
<ChainSelectUI
|
|
180
|
+
chain={Chain.ETHEREUM}
|
|
181
|
+
candidates={[Chain.ETHEREUM, Chain.BINANCE]}
|
|
182
|
+
onSelectChain={(chain) => console.log(chain)}
|
|
183
|
+
/>
|
|
184
|
+
);
|
|
185
|
+
}
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
### Multiple independent instances
|
|
189
|
+
|
|
190
|
+
```tsx
|
|
191
|
+
import {
|
|
192
|
+
ChainSelectProvider,
|
|
193
|
+
ChainSelectWidget,
|
|
194
|
+
} from "@liberfi.io/ui-chain-select";
|
|
195
|
+
|
|
196
|
+
function MultiChainApp() {
|
|
197
|
+
return (
|
|
198
|
+
<>
|
|
199
|
+
<ChainSelectProvider storageKeyPrefix="source_">
|
|
200
|
+
<ChainSelectWidget onSwitchChain={handleSourceSwitch} />
|
|
201
|
+
</ChainSelectProvider>
|
|
202
|
+
<ChainSelectProvider storageKeyPrefix="target_">
|
|
203
|
+
<ChainSelectWidget onSwitchChain={handleTargetSwitch} />
|
|
204
|
+
</ChainSelectProvider>
|
|
205
|
+
</>
|
|
206
|
+
);
|
|
207
|
+
}
|
|
208
|
+
```
|
|
209
|
+
|
|
210
|
+
### Reading current chain from hooks
|
|
211
|
+
|
|
212
|
+
```tsx
|
|
213
|
+
import { useCurrentChain } from "@liberfi.io/ui-chain-select";
|
|
214
|
+
|
|
215
|
+
function ChainInfo() {
|
|
216
|
+
const { chain, chainNamespace } = useCurrentChain();
|
|
217
|
+
return (
|
|
218
|
+
<p>
|
|
219
|
+
Current: {chain} ({chainNamespace})
|
|
220
|
+
</p>
|
|
221
|
+
);
|
|
222
|
+
}
|
|
223
|
+
```
|
|
224
|
+
|
|
225
|
+
## Future Improvements
|
|
226
|
+
|
|
227
|
+
- Add render tests for `ChainSelectWidget`, `ChainSelectUI`, `ChainSelectDesktopUI`, and `ChainSelectMobileUI`.
|
|
228
|
+
- Externalize `@liberfi.io/types`, `@liberfi.io/utils`, `@liberfi.io/ui` in `tsup.config.ts` to prevent duplicate bundling when multiple `@liberfi.io` packages are consumed together.
|
|
229
|
+
- Refactor `version.ts` module-level side effect to a lazy registration pattern (monorepo-wide change).
|
package/dist/index.d.mts
CHANGED
|
@@ -14,7 +14,7 @@ declare global {
|
|
|
14
14
|
};
|
|
15
15
|
}
|
|
16
16
|
}
|
|
17
|
-
declare const _default: "0.1.
|
|
17
|
+
declare const _default: "0.1.26";
|
|
18
18
|
|
|
19
19
|
type ChainAtoms = {
|
|
20
20
|
chainAtom: ReturnType<typeof atomWithStorage<Chain>>;
|
|
@@ -55,7 +55,7 @@ type ChainSelectUIProps = {
|
|
|
55
55
|
isSwitching?: boolean;
|
|
56
56
|
className?: string;
|
|
57
57
|
};
|
|
58
|
-
declare function ChainSelectUI({ size,
|
|
58
|
+
declare function ChainSelectUI({ size, candidates, chain, onSelectChain, isSwitching, className, }: ChainSelectUIProps): react_jsx_runtime.JSX.Element;
|
|
59
59
|
|
|
60
60
|
type ChainSelectWidgetProps = {
|
|
61
61
|
size?: "sm" | "md" | "lg";
|
package/dist/index.d.ts
CHANGED
|
@@ -14,7 +14,7 @@ declare global {
|
|
|
14
14
|
};
|
|
15
15
|
}
|
|
16
16
|
}
|
|
17
|
-
declare const _default: "0.1.
|
|
17
|
+
declare const _default: "0.1.26";
|
|
18
18
|
|
|
19
19
|
type ChainAtoms = {
|
|
20
20
|
chainAtom: ReturnType<typeof atomWithStorage<Chain>>;
|
|
@@ -55,7 +55,7 @@ type ChainSelectUIProps = {
|
|
|
55
55
|
isSwitching?: boolean;
|
|
56
56
|
className?: string;
|
|
57
57
|
};
|
|
58
|
-
declare function ChainSelectUI({ size,
|
|
58
|
+
declare function ChainSelectUI({ size, candidates, chain, onSelectChain, isSwitching, className, }: ChainSelectUIProps): react_jsx_runtime.JSX.Element;
|
|
59
59
|
|
|
60
60
|
type ChainSelectWidgetProps = {
|
|
61
61
|
size?: "sm" | "md" | "lg";
|
package/dist/index.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
'use strict';var react=require('react'),utils=require('jotai/utils'),types=require('@liberfi.io/types'),jsxRuntime=require('react/jsx-runtime'),ui=require('@liberfi.io/ui'),utils$1=require('@liberfi.io/utils'),jotai=require('jotai');typeof window<"u"&&(window.__LIBERFI_VERSION__=window.__LIBERFI_VERSION__||{},window.__LIBERFI_VERSION__["@liberfi.io/ui-chain-select"]="0.1.
|
|
1
|
+
'use strict';var react=require('react'),utils=require('jotai/utils'),types=require('@liberfi.io/types'),jsxRuntime=require('react/jsx-runtime'),ui=require('@liberfi.io/ui'),utils$1=require('@liberfi.io/utils'),jotai=require('jotai');typeof window<"u"&&(window.__LIBERFI_VERSION__=window.__LIBERFI_VERSION__||{},window.__LIBERFI_VERSION__["@liberfi.io/ui-chain-select"]="0.1.26");var B="0.1.26";var A={getOnInit:true};function l(e=""){let t=`${e}chain`,o=`${e}chainNamespace`;return {chainAtom:utils.atomWithStorage(t,types.Chain.SOLANA,void 0,A),chainNamespaceAtom:utils.atomWithStorage(o,types.ChainNamespace.SOLANA,void 0,A)}}var C=l(""),g=C,fe=C.chainAtom,Se=C.chainNamespaceAtom;var h=react.createContext(g);function ge({storageKeyPrefix:e="",children:t}){let o=react.useMemo(()=>l(e),[e]);return jsxRuntime.jsx(h.Provider,{value:o,children:t})}var Q={[types.Chain.SOLANA]:ui.SolanaIcon,[types.Chain.ETHEREUM]:ui.EthereumIcon,[types.Chain.BINANCE]:ui.BinanceIcon};function p({chain:e,className:t}){let o=Q[e];return o?jsxRuntime.jsx(o,{className:t}):jsxRuntime.jsx(ui.Avatar,{className:t,src:utils$1.chainIcon(e),name:utils$1.capitalize(utils$1.chainSlug(e)??"")})}var x=[types.Chain.SOLANA,types.Chain.ETHEREUM,types.Chain.BINANCE];function b({size:e,candidates:t,chain:o=t[0],onSelectChain:a,isSwitching:r,className:c}){let n=i=>{a?.(i);},m=ui.cn(e==="sm"?"w-4 h-4":e==="lg"?"w-6 h-6":"w-5 h-5");return jsxRuntime.jsxs(ui.Dropdown,{placement:"bottom-end",className:c,classNames:{content:"w-38 bg-content1 border border-border"},children:[jsxRuntime.jsx(ui.DropdownTrigger,{children:jsxRuntime.jsx(ui.Button,{isLoading:r,size:e,variant:"bordered",radius:"full",style:{borderColor:utils$1.chainColor(o)?`${utils$1.chainColor(o)}60`:void 0},startContent:jsxRuntime.jsx(p,{chain:o,className:m}),children:utils$1.chainDisplayName(o)})}),jsxRuntime.jsx(ui.DropdownMenu,{"aria-label":"Select chain",selectionMode:"single",selectedKeys:o?[o]:[],onAction:n,classNames:{list:"gap-1"},itemClasses:{base:ui.cn("rounded-md px-3",e==="sm"?"h-8":e==="lg"?"h-12":"h-10")},children:t.map(i=>jsxRuntime.jsx(ui.DropdownItem,{startContent:jsxRuntime.jsx(p,{chain:i,className:m}),className:i===o?"bg-content2 text-foreground":"text-neutral",children:utils$1.chainDisplayName(i)},i))})]})}function P({size:e,candidates:t,chain:o=t[0],onSelectChain:a,isSwitching:r,className:c}){return jsxRuntime.jsx("div",{role:"group","aria-label":"Select chain",className:ui.cn("flex items-center gap-1",c),children:t.map(n=>jsxRuntime.jsx(ui.Button,{isIconOnly:true,"aria-label":utils$1.chainDisplayName(n),isDisabled:r,radius:"full",className:ui.cn("min-w-0 min-h-0 border",e==="sm"?"w-6 h-6":e==="md"||e===void 0?"w-7 h-7":"w-8 h-8",n===o?"bg-content1 scale-110 hover:opacity-100":"bg-transparent scale-90 opacity-50 hover:opacity-100 border-transparent"),style:n===o&&utils$1.chainColor(n)?{borderColor:`${utils$1.chainColor(n)}60`}:void 0,onPress:()=>a?.(n),children:jsxRuntime.jsx(p,{chain:n,className:ui.cn(e==="sm"?"w-4 h-4":e==="md"||e===void 0?"w-5 h-5":"w-6 h-6")})},n))})}function D({size:e,candidates:t=x,chain:o=t[0],onSelectChain:a,isSwitching:r,className:c}){let{isMobile:n}=ui.useScreen();return n?jsxRuntime.jsx(P,{size:e,chain:o,onSelectChain:a,isSwitching:r,candidates:t,className:c}):jsxRuntime.jsx(b,{size:e,chain:o,onSelectChain:a,isSwitching:r,candidates:t,className:c})}function R(e){let{chainAtom:t,chainNamespaceAtom:o}=react.useContext(h),a=jotai.useSetAtom(t),r=jotai.useSetAtom(o),[c,n]=react.useState(false);return {selectChain:react.useCallback(async i=>{try{n(!0),await e?.onSwitchChain?.(i),r(utils$1.chainToNamespace(i)),a(i),e?.onSuccess?.(i);}catch(M){e?.onError?.(M);}finally{n(false);}},[a,r,e?.onSwitchChain,e?.onSuccess,e?.onError]),isSwitching:c}}function T(){let{chainAtom:e,chainNamespaceAtom:t}=react.useContext(h),o=jotai.useAtomValue(e),a=jotai.useAtomValue(t);return react.useMemo(()=>({chain:o,chainNamespace:a}),[o,a])}function ro({size:e,className:t,candidates:o,onSwitchChain:a,onSuccess:r,onError:c}){let{chain:n}=T(),{selectChain:m,isSwitching:i}=R({onSwitchChain:a,onSuccess:r,onError:c});return jsxRuntime.jsx(D,{chain:n,candidates:o,onSelectChain:m,isSwitching:i,size:e,className:t})}exports.ChainAvatar=p;exports.ChainSelectProvider=ge;exports.ChainSelectStateContext=h;exports.ChainSelectUI=D;exports.ChainSelectWidget=ro;exports.chainAtom=fe;exports.chainNamespaceAtom=Se;exports.createChainAtoms=l;exports.defaultChainAtoms=g;exports.useCurrentChain=T;exports.useSelectChain=R;exports.version=B;//# sourceMappingURL=index.js.map
|
|
2
2
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/version.ts","../src/states.ts","../src/chain-select.context.tsx","../src/components/chain-avatar.tsx","../src/constants.ts","../src/components/chain-select.desktop.ui.tsx","../src/components/chain-select.mobile.ui.tsx","../src/components/chain-select.ui.tsx","../src/hooks/useSelectChain.tsx","../src/hooks/useCurrentChain.tsx","../src/components/chain-select.widget.tsx"],"names":["version_default","storageOptions","createChainAtoms","storageKeyPrefix","chainKey","chainNamespaceKey","atomWithStorage","Chain","ChainNamespace","defaultAtoms","defaultChainAtoms","chainAtom","chainNamespaceAtom","ChainSelectStateContext","createContext","ChainSelectProvider","children","value","useMemo","jsx","ChainAvatar","chain","className","SolanaIcon","EthereumIcon","BinanceIcon","Avatar","chainIcon","capitalize","chainSlug","DEFAULT_CANDIDATES","ChainSelectDesktopUI","size","candidates","onSelectChain","isSwitching","isOpen","onClose","onOpenChange","useDisclosure","handleSelect","useCallback","jsxs","Popover","PopoverTrigger","Button","chainColor","clsx","chainDisplayName","PopoverContent","it","ChainSelectMobileUI","ChainSelectUI","isMobile","useScreen","useSelectChain","options","useContext","setChain","useSetAtom","setChainNamespace","setIsSwitching","useState","chainToNamespace","e","useCurrentChain","useAtomValue","chainNamespace","ChainSelectWidget","onSwitchChain","onSuccess","onError","selectChain"],"mappings":"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","file":"index.js","sourcesContent":["declare global {\n interface Window {\n __LIBERFI_VERSION__?: {\n [key: string]: string;\n };\n }\n}\nif (typeof window !== \"undefined\") {\n window.__LIBERFI_VERSION__ = window.__LIBERFI_VERSION__ || {};\n window.__LIBERFI_VERSION__[\"@liberfi.io/ui-chain-select\"] = \"0.1.24\";\n}\n\nexport default \"0.1.24\";\n","import { atomWithStorage } from \"jotai/utils\";\nimport { Chain, ChainNamespace } from \"@liberfi.io/types\";\n\nconst storageOptions = { getOnInit: true as const };\n\nexport type ChainAtoms = {\n chainAtom: ReturnType<typeof atomWithStorage<Chain>>;\n chainNamespaceAtom: ReturnType<typeof atomWithStorage<ChainNamespace>>;\n};\n\n/**\n * Creates chain state atoms with optional storage key prefix.\n * Use a prefix when multiple independent chain selectors must coexist on the same origin.\n */\nexport function createChainAtoms(storageKeyPrefix: string = \"\"): ChainAtoms {\n const chainKey = `${storageKeyPrefix}chain`;\n const chainNamespaceKey = `${storageKeyPrefix}chainNamespace`;\n return {\n chainAtom: atomWithStorage<Chain>(\n chainKey,\n Chain.SOLANA,\n undefined,\n storageOptions,\n ),\n chainNamespaceAtom: atomWithStorage<ChainNamespace>(\n chainNamespaceKey,\n ChainNamespace.SOLANA,\n undefined,\n storageOptions,\n ),\n };\n}\n\nconst defaultAtoms = createChainAtoms(\"\");\n\n/** Default atoms (used when not inside ChainSelectProvider) */\nexport const defaultChainAtoms = defaultAtoms;\n\n/** Current chain (default instance, key \"chain\") */\nexport const chainAtom = defaultAtoms.chainAtom;\n\n/** Current chain namespace (default instance, key \"chainNamespace\") */\nexport const chainNamespaceAtom = defaultAtoms.chainNamespaceAtom;\n","import { createContext, useMemo, type ReactNode } from \"react\";\nimport { createChainAtoms, defaultChainAtoms } from \"./states\";\n\nexport type ChainSelectStateContextValue = ReturnType<typeof createChainAtoms>;\n\nexport const ChainSelectStateContext =\n createContext<ChainSelectStateContextValue>(defaultChainAtoms);\n\nexport type ChainSelectProviderProps = {\n /** Optional storage key prefix so multiple instances can coexist (e.g. \"app1_\") */\n storageKeyPrefix?: string;\n children: ReactNode;\n};\n\nexport function ChainSelectProvider({\n storageKeyPrefix = \"\",\n children,\n}: ChainSelectProviderProps) {\n const value = useMemo(\n () => createChainAtoms(storageKeyPrefix),\n [storageKeyPrefix],\n );\n return (\n <ChainSelectStateContext.Provider value={value}>\n {children}\n </ChainSelectStateContext.Provider>\n );\n}\n","import { Chain } from \"@liberfi.io/types\";\nimport { Avatar, BinanceIcon, EthereumIcon, SolanaIcon } from \"@liberfi.io/ui\";\nimport { capitalize, chainIcon, chainSlug } from \"@liberfi.io/utils\";\n\nexport type ChainAvatarProps = {\n chain: Chain;\n className?: string;\n};\n\nexport function ChainAvatar({ chain, className }: ChainAvatarProps) {\n switch (chain) {\n case Chain.SOLANA:\n return <SolanaIcon className={className} />;\n case Chain.ETHEREUM:\n return <EthereumIcon className={className} />;\n case Chain.BINANCE:\n return <BinanceIcon className={className} />;\n default:\n return (\n <Avatar\n className={className}\n src={chainIcon(chain)}\n name={capitalize(chainSlug(chain) ?? \"\")}\n />\n );\n }\n}\n","import { Chain } from \"@liberfi.io/types\";\n\n/** Default chain list when candidates are not provided */\nexport const DEFAULT_CANDIDATES: Chain[] = [\n Chain.SOLANA,\n Chain.ETHEREUM,\n Chain.BINANCE,\n];\n","import { useCallback } from \"react\";\nimport { Chain } from \"@liberfi.io/types\";\nimport {\n Button,\n clsx,\n Popover,\n PopoverContent,\n PopoverTrigger,\n useDisclosure,\n} from \"@liberfi.io/ui\";\nimport { chainColor, chainDisplayName } from \"@liberfi.io/utils\";\nimport { ChainAvatar } from \"./chain-avatar\";\n\nexport type ChainSelectDesktopUIProps = {\n size?: \"sm\" | \"md\" | \"lg\";\n candidates: Chain[];\n chain?: Chain;\n onSelectChain?: (chain: Chain) => void | Promise<void>;\n isSwitching?: boolean;\n className?: string;\n};\n\nexport function ChainSelectDesktopUI({\n size,\n candidates,\n chain = candidates[0],\n onSelectChain,\n isSwitching,\n className,\n}: ChainSelectDesktopUIProps) {\n const { isOpen, onClose, onOpenChange } = useDisclosure();\n\n const handleSelect = useCallback(\n (chain: Chain) => {\n onSelectChain?.(chain);\n onClose();\n },\n [onSelectChain, onClose],\n );\n\n return (\n <Popover\n isOpen={isOpen}\n onOpenChange={onOpenChange}\n placement=\"bottom-end\"\n className={className}\n classNames={{ content: \"w-38 bg-content1 border border-border\" }}\n >\n <PopoverTrigger>\n <Button\n isLoading={isSwitching}\n size={size}\n variant=\"bordered\"\n radius=\"full\"\n style={{\n borderColor: chainColor(chain)\n ? `${chainColor(chain)}60`\n : undefined,\n }}\n startContent={\n <ChainAvatar\n chain={chain}\n className={clsx(\n size === \"sm\"\n ? \"w-4 h-4\"\n : size === \"lg\"\n ? \"w-6 h-6\"\n : \"w-5 h-5\",\n )}\n />\n }\n >\n {chainDisplayName(chain)}\n </Button>\n </PopoverTrigger>\n <PopoverContent className=\"w-40 flex flex-col gap-1 p-1 rounded-md\">\n {candidates.map((it) => (\n <div\n key={it}\n className={clsx(\n \"w-full hover:bg-content2/80 cursor-pointer rounded-md px-3\",\n \"flex gap-2 items-center\",\n size === \"sm\" ? \"h-8\" : size === \"lg\" ? \"h-12\" : \"h-10\",\n it === chain ? \"bg-content2 text-foreground\" : \"text-neutral\",\n )}\n onClick={() => handleSelect(it)}\n >\n <ChainAvatar\n chain={it}\n className={clsx(\n size === \"sm\"\n ? \"w-4 h-4\"\n : size === \"lg\"\n ? \"w-6 h-6\"\n : \"w-5 h-5\",\n )}\n />\n {chainDisplayName(it)}\n </div>\n ))}\n </PopoverContent>\n </Popover>\n );\n}\n","import { Chain } from \"@liberfi.io/types\";\nimport { Button, clsx } from \"@liberfi.io/ui\";\nimport { chainColor } from \"@liberfi.io/utils\";\nimport { ChainAvatar } from \"./chain-avatar\";\n\nexport type ChainSelectMobileUIProps = {\n size?: \"sm\" | \"md\" | \"lg\";\n candidates: Chain[];\n chain?: Chain;\n onSelectChain?: (chain: Chain) => void | Promise<void>;\n isSwitching?: boolean;\n className?: string;\n};\n\nexport function ChainSelectMobileUI({\n size,\n candidates,\n chain = Chain.SOLANA,\n onSelectChain,\n isSwitching,\n className,\n}: ChainSelectMobileUIProps) {\n return (\n <div className={clsx(\"flex items-center gap-1\", className)}>\n {candidates.map((it) => (\n <Button\n isIconOnly\n isDisabled={isSwitching}\n radius=\"full\"\n className={clsx(\n \"min-w-0 min-h-0 border\",\n size === \"sm\"\n ? \"w-6 h-6\"\n : size === \"md\" || size === undefined\n ? \"w-7 h-7\"\n : \"w-8 h-8\",\n it === chain\n ? \"bg-content1 scale-110 hover:opacity-100\"\n : \"bg-transparent scale-90 opacity-50 hover:opacity-100 border-transparent\",\n )}\n style={\n it === chain && chainColor(it)\n ? { borderColor: `${chainColor(it)}60` }\n : undefined\n }\n key={it}\n onPress={() => onSelectChain?.(it)}\n >\n <ChainAvatar\n chain={it}\n className={clsx(\n size === \"sm\"\n ? \"w-4 h-4\"\n : size === \"md\" || size === undefined\n ? \"w-5 h-5\"\n : \"w-6 h-6\",\n )}\n />\n </Button>\n ))}\n </div>\n );\n}\n","import { Chain } from \"@liberfi.io/types\";\nimport { useScreen } from \"@liberfi.io/ui\";\nimport { DEFAULT_CANDIDATES } from \"../constants\";\nimport { ChainSelectDesktopUI } from \"./chain-select.desktop.ui\";\nimport { ChainSelectMobileUI } from \"./chain-select.mobile.ui\";\n\nexport type ChainSelectUIProps = {\n size?: \"sm\" | \"md\" | \"lg\";\n chain?: Chain;\n candidates?: Chain[];\n onSelectChain?: (chain: Chain) => void | Promise<void>;\n isSwitching?: boolean;\n className?: string;\n};\n\nexport function ChainSelectUI({\n size,\n chain = Chain.SOLANA,\n candidates = DEFAULT_CANDIDATES,\n onSelectChain,\n isSwitching,\n className,\n}: ChainSelectUIProps) {\n const { isMobile } = useScreen();\n\n if (isMobile) {\n return (\n <ChainSelectMobileUI\n size={size}\n chain={chain}\n onSelectChain={onSelectChain}\n isSwitching={isSwitching}\n candidates={candidates}\n className={className}\n />\n );\n } else {\n return (\n <ChainSelectDesktopUI\n size={size}\n chain={chain}\n onSelectChain={onSelectChain}\n isSwitching={isSwitching}\n candidates={candidates}\n className={className}\n />\n );\n }\n}\n","import { useCallback, useContext, useState } from \"react\";\nimport { useSetAtom } from \"jotai\";\nimport { Chain } from \"@liberfi.io/types\";\nimport { chainToNamespace } from \"@liberfi.io/utils\";\nimport { ChainSelectStateContext } from \"../chain-select.context\";\n\nexport type UseSelectChainOptions = {\n onSwitchChain?: (chain: Chain) => Promise<void>;\n /** Called when switching chain succeeds; caller can toast / analytics here */\n onSuccess?: (chain: Chain) => void;\n /** Called when switching chain fails; caller can toast / modal / report here */\n onError?: (error: unknown) => void;\n};\n\nexport function useSelectChain(options?: UseSelectChainOptions) {\n const { chainAtom, chainNamespaceAtom } = useContext(ChainSelectStateContext);\n const setChain = useSetAtom(chainAtom);\n const setChainNamespace = useSetAtom(chainNamespaceAtom);\n const [isSwitching, setIsSwitching] = useState(false);\n\n const selectChain = useCallback(\n async (chain: Chain) => {\n try {\n setIsSwitching(true);\n await options?.onSwitchChain?.(chain);\n\n setChainNamespace(chainToNamespace(chain));\n setChain(chain);\n options?.onSuccess?.(chain);\n } catch (e) {\n options?.onError?.(e);\n } finally {\n setIsSwitching(false);\n }\n },\n [\n setChain,\n setChainNamespace,\n options?.onSwitchChain,\n options?.onSuccess,\n options?.onError,\n ],\n );\n\n return { selectChain, isSwitching };\n}\n","import { useMemo, useContext } from \"react\";\nimport { useAtomValue } from \"jotai\";\nimport { ChainSelectStateContext } from \"../chain-select.context\";\n\nexport function useCurrentChain() {\n const { chainAtom, chainNamespaceAtom } = useContext(ChainSelectStateContext);\n const chain = useAtomValue(chainAtom);\n const chainNamespace = useAtomValue(chainNamespaceAtom);\n return useMemo(() => ({ chain, chainNamespace }), [chain, chainNamespace]);\n}\n","import { Chain } from \"@liberfi.io/types\";\nimport { useSelectChain, useCurrentChain } from \"../hooks\";\nimport { ChainSelectUI } from \"./chain-select.ui\";\n\nexport type ChainSelectWidgetProps = {\n size?: \"sm\" | \"md\" | \"lg\";\n className?: string;\n /** Optional list of chains to show. Defaults to [SOLANA, ETHEREUM, BINANCE] when not provided. */\n candidates?: Chain[];\n onSwitchChain?: (chain: Chain) => Promise<void>;\n /** Called when switching chain succeeds; caller can toast / analytics here */\n onSuccess?: (chain: Chain) => void;\n /** Called when switching chain fails; caller can toast / modal / report here */\n onError?: (error: unknown) => void;\n};\n\nexport function ChainSelectWidget({\n size,\n className,\n candidates,\n onSwitchChain,\n onSuccess,\n onError,\n}: ChainSelectWidgetProps) {\n const { chain } = useCurrentChain();\n const { selectChain, isSwitching } = useSelectChain({\n onSwitchChain,\n onSuccess,\n onError,\n });\n\n return (\n <ChainSelectUI\n chain={chain}\n candidates={candidates}\n onSelectChain={selectChain}\n isSwitching={isSwitching}\n size={size}\n className={className}\n />\n );\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/version.ts","../src/states.ts","../src/chain-select.context.tsx","../src/components/chain-avatar.tsx","../src/constants.ts","../src/components/chain-select.desktop.ui.tsx","../src/components/chain-select.mobile.ui.tsx","../src/components/chain-select.ui.tsx","../src/hooks/useSelectChain.tsx","../src/hooks/useCurrentChain.tsx","../src/components/chain-select.widget.tsx"],"names":["version_default","storageOptions","createChainAtoms","storageKeyPrefix","chainKey","chainNamespaceKey","atomWithStorage","Chain","ChainNamespace","defaultAtoms","defaultChainAtoms","chainAtom","chainNamespaceAtom","ChainSelectStateContext","createContext","ChainSelectProvider","children","value","useMemo","jsx","CHAIN_ICON_MAP","SolanaIcon","EthereumIcon","BinanceIcon","ChainAvatar","chain","className","Icon","Avatar","chainIcon","capitalize","chainSlug","DEFAULT_CANDIDATES","ChainSelectDesktopUI","size","candidates","onSelectChain","isSwitching","handleAction","key","avatarSize","cn","jsxs","Dropdown","DropdownTrigger","Button","chainColor","chainDisplayName","DropdownMenu","it","DropdownItem","ChainSelectMobileUI","ChainSelectUI","isMobile","useScreen","useSelectChain","options","useContext","setChain","useSetAtom","setChainNamespace","setIsSwitching","useState","useCallback","chainToNamespace","e","useCurrentChain","useAtomValue","chainNamespace","ChainSelectWidget","onSwitchChain","onSuccess","onError","selectChain"],"mappings":"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","file":"index.js","sourcesContent":["declare global {\n interface Window {\n __LIBERFI_VERSION__?: {\n [key: string]: string;\n };\n }\n}\nif (typeof window !== \"undefined\") {\n window.__LIBERFI_VERSION__ = window.__LIBERFI_VERSION__ || {};\n window.__LIBERFI_VERSION__[\"@liberfi.io/ui-chain-select\"] = \"0.1.26\";\n}\n\nexport default \"0.1.26\";\n","import { atomWithStorage } from \"jotai/utils\";\nimport { Chain, ChainNamespace } from \"@liberfi.io/types\";\n\nconst storageOptions = { getOnInit: true as const };\n\nexport type ChainAtoms = {\n chainAtom: ReturnType<typeof atomWithStorage<Chain>>;\n chainNamespaceAtom: ReturnType<typeof atomWithStorage<ChainNamespace>>;\n};\n\n/**\n * Creates chain state atoms with optional storage key prefix.\n * Use a prefix when multiple independent chain selectors must coexist on the same origin.\n */\nexport function createChainAtoms(storageKeyPrefix: string = \"\"): ChainAtoms {\n const chainKey = `${storageKeyPrefix}chain`;\n const chainNamespaceKey = `${storageKeyPrefix}chainNamespace`;\n return {\n chainAtom: atomWithStorage<Chain>(\n chainKey,\n Chain.SOLANA,\n undefined,\n storageOptions,\n ),\n chainNamespaceAtom: atomWithStorage<ChainNamespace>(\n chainNamespaceKey,\n ChainNamespace.SOLANA,\n undefined,\n storageOptions,\n ),\n };\n}\n\nconst defaultAtoms = createChainAtoms(\"\");\n\n/** Default atoms (used when not inside ChainSelectProvider) */\nexport const defaultChainAtoms = defaultAtoms;\n\n/** Current chain (default instance, key \"chain\") */\nexport const chainAtom = defaultAtoms.chainAtom;\n\n/** Current chain namespace (default instance, key \"chainNamespace\") */\nexport const chainNamespaceAtom = defaultAtoms.chainNamespaceAtom;\n","import { createContext, useMemo, type ReactNode } from \"react\";\nimport { createChainAtoms, defaultChainAtoms } from \"./states\";\n\nexport type ChainSelectStateContextValue = ReturnType<typeof createChainAtoms>;\n\nexport const ChainSelectStateContext =\n createContext<ChainSelectStateContextValue>(defaultChainAtoms);\n\nexport type ChainSelectProviderProps = {\n /** Optional storage key prefix so multiple instances can coexist (e.g. \"app1_\") */\n storageKeyPrefix?: string;\n children: ReactNode;\n};\n\nexport function ChainSelectProvider({\n storageKeyPrefix = \"\",\n children,\n}: ChainSelectProviderProps) {\n const value = useMemo(\n () => createChainAtoms(storageKeyPrefix),\n [storageKeyPrefix],\n );\n return (\n <ChainSelectStateContext.Provider value={value}>\n {children}\n </ChainSelectStateContext.Provider>\n );\n}\n","import type { ComponentType } from \"react\";\nimport { Chain } from \"@liberfi.io/types\";\nimport { Avatar, BinanceIcon, EthereumIcon, SolanaIcon } from \"@liberfi.io/ui\";\nimport { capitalize, chainIcon, chainSlug } from \"@liberfi.io/utils\";\n\nexport type ChainAvatarProps = {\n chain: Chain;\n className?: string;\n};\n\nconst CHAIN_ICON_MAP: Partial<\n Record<Chain, ComponentType<{ className?: string }>>\n> = {\n [Chain.SOLANA]: SolanaIcon,\n [Chain.ETHEREUM]: EthereumIcon,\n [Chain.BINANCE]: BinanceIcon,\n};\n\nexport function ChainAvatar({ chain, className }: ChainAvatarProps) {\n const Icon = CHAIN_ICON_MAP[chain];\n if (Icon) return <Icon className={className} />;\n return (\n <Avatar\n className={className}\n src={chainIcon(chain)}\n name={capitalize(chainSlug(chain) ?? \"\")}\n />\n );\n}\n","import { Chain } from \"@liberfi.io/types\";\n\n/** Default chain list when candidates are not provided */\nexport const DEFAULT_CANDIDATES: Chain[] = [\n Chain.SOLANA,\n Chain.ETHEREUM,\n Chain.BINANCE,\n];\n","import { type Key } from \"react\";\nimport { Chain } from \"@liberfi.io/types\";\nimport {\n Button,\n cn,\n Dropdown,\n DropdownItem,\n DropdownMenu,\n DropdownTrigger,\n} from \"@liberfi.io/ui\";\nimport { chainColor, chainDisplayName } from \"@liberfi.io/utils\";\nimport { ChainAvatar } from \"./chain-avatar\";\n\nexport type ChainSelectDesktopUIProps = {\n size?: \"sm\" | \"md\" | \"lg\";\n candidates: Chain[];\n chain?: Chain;\n onSelectChain?: (chain: Chain) => void | Promise<void>;\n isSwitching?: boolean;\n className?: string;\n};\n\nexport function ChainSelectDesktopUI({\n size,\n candidates,\n chain = candidates[0],\n onSelectChain,\n isSwitching,\n className,\n}: ChainSelectDesktopUIProps) {\n const handleAction = (key: Key) => {\n onSelectChain?.(key as Chain);\n };\n\n const avatarSize = cn(\n size === \"sm\" ? \"w-4 h-4\" : size === \"lg\" ? \"w-6 h-6\" : \"w-5 h-5\",\n );\n\n return (\n <Dropdown\n placement=\"bottom-end\"\n className={className}\n classNames={{ content: \"w-38 bg-content1 border border-border\" }}\n >\n <DropdownTrigger>\n <Button\n isLoading={isSwitching}\n size={size}\n variant=\"bordered\"\n radius=\"full\"\n style={{\n borderColor: chainColor(chain)\n ? `${chainColor(chain)}60`\n : undefined,\n }}\n startContent={<ChainAvatar chain={chain} className={avatarSize} />}\n >\n {chainDisplayName(chain)}\n </Button>\n </DropdownTrigger>\n <DropdownMenu\n aria-label=\"Select chain\"\n selectionMode=\"single\"\n selectedKeys={chain ? [chain] : []}\n onAction={handleAction}\n classNames={{ list: \"gap-1\" }}\n itemClasses={{\n base: cn(\n \"rounded-md px-3\",\n size === \"sm\" ? \"h-8\" : size === \"lg\" ? \"h-12\" : \"h-10\",\n ),\n }}\n >\n {candidates.map((it) => (\n <DropdownItem\n key={it}\n startContent={<ChainAvatar chain={it} className={avatarSize} />}\n className={\n it === chain ? \"bg-content2 text-foreground\" : \"text-neutral\"\n }\n >\n {chainDisplayName(it)}\n </DropdownItem>\n ))}\n </DropdownMenu>\n </Dropdown>\n );\n}\n","import { Chain } from \"@liberfi.io/types\";\nimport { Button, cn } from \"@liberfi.io/ui\";\nimport { chainColor, chainDisplayName } from \"@liberfi.io/utils\";\nimport { ChainAvatar } from \"./chain-avatar\";\n\nexport type ChainSelectMobileUIProps = {\n size?: \"sm\" | \"md\" | \"lg\";\n candidates: Chain[];\n chain?: Chain;\n onSelectChain?: (chain: Chain) => void | Promise<void>;\n isSwitching?: boolean;\n className?: string;\n};\n\nexport function ChainSelectMobileUI({\n size,\n candidates,\n chain = candidates[0],\n onSelectChain,\n isSwitching,\n className,\n}: ChainSelectMobileUIProps) {\n return (\n <div\n role=\"group\"\n aria-label=\"Select chain\"\n className={cn(\"flex items-center gap-1\", className)}\n >\n {candidates.map((it) => (\n <Button\n isIconOnly\n aria-label={chainDisplayName(it)}\n isDisabled={isSwitching}\n radius=\"full\"\n className={cn(\n \"min-w-0 min-h-0 border\",\n size === \"sm\"\n ? \"w-6 h-6\"\n : size === \"md\" || size === undefined\n ? \"w-7 h-7\"\n : \"w-8 h-8\",\n it === chain\n ? \"bg-content1 scale-110 hover:opacity-100\"\n : \"bg-transparent scale-90 opacity-50 hover:opacity-100 border-transparent\",\n )}\n style={\n it === chain && chainColor(it)\n ? { borderColor: `${chainColor(it)}60` }\n : undefined\n }\n key={it}\n onPress={() => onSelectChain?.(it)}\n >\n <ChainAvatar\n chain={it}\n className={cn(\n size === \"sm\"\n ? \"w-4 h-4\"\n : size === \"md\" || size === undefined\n ? \"w-5 h-5\"\n : \"w-6 h-6\",\n )}\n />\n </Button>\n ))}\n </div>\n );\n}\n","import { Chain } from \"@liberfi.io/types\";\nimport { useScreen } from \"@liberfi.io/ui\";\nimport { DEFAULT_CANDIDATES } from \"../constants\";\nimport { ChainSelectDesktopUI } from \"./chain-select.desktop.ui\";\nimport { ChainSelectMobileUI } from \"./chain-select.mobile.ui\";\n\nexport type ChainSelectUIProps = {\n size?: \"sm\" | \"md\" | \"lg\";\n chain?: Chain;\n candidates?: Chain[];\n onSelectChain?: (chain: Chain) => void | Promise<void>;\n isSwitching?: boolean;\n className?: string;\n};\n\nexport function ChainSelectUI({\n size,\n candidates = DEFAULT_CANDIDATES,\n chain = candidates[0],\n onSelectChain,\n isSwitching,\n className,\n}: ChainSelectUIProps) {\n const { isMobile } = useScreen();\n\n if (isMobile) {\n return (\n <ChainSelectMobileUI\n size={size}\n chain={chain}\n onSelectChain={onSelectChain}\n isSwitching={isSwitching}\n candidates={candidates}\n className={className}\n />\n );\n } else {\n return (\n <ChainSelectDesktopUI\n size={size}\n chain={chain}\n onSelectChain={onSelectChain}\n isSwitching={isSwitching}\n candidates={candidates}\n className={className}\n />\n );\n }\n}\n","import { useCallback, useContext, useState } from \"react\";\nimport { useSetAtom } from \"jotai\";\nimport { Chain } from \"@liberfi.io/types\";\nimport { chainToNamespace } from \"@liberfi.io/utils\";\nimport { ChainSelectStateContext } from \"../chain-select.context\";\n\nexport type UseSelectChainOptions = {\n onSwitchChain?: (chain: Chain) => Promise<void>;\n /** Called when switching chain succeeds; caller can toast / analytics here */\n onSuccess?: (chain: Chain) => void;\n /** Called when switching chain fails; caller can toast / modal / report here */\n onError?: (error: unknown) => void;\n};\n\nexport function useSelectChain(options?: UseSelectChainOptions) {\n const { chainAtom, chainNamespaceAtom } = useContext(ChainSelectStateContext);\n const setChain = useSetAtom(chainAtom);\n const setChainNamespace = useSetAtom(chainNamespaceAtom);\n const [isSwitching, setIsSwitching] = useState(false);\n\n const selectChain = useCallback(\n async (chain: Chain) => {\n try {\n setIsSwitching(true);\n await options?.onSwitchChain?.(chain);\n\n setChainNamespace(chainToNamespace(chain));\n setChain(chain);\n options?.onSuccess?.(chain);\n } catch (e) {\n options?.onError?.(e);\n } finally {\n setIsSwitching(false);\n }\n },\n [\n setChain,\n setChainNamespace,\n options?.onSwitchChain,\n options?.onSuccess,\n options?.onError,\n ],\n );\n\n return { selectChain, isSwitching };\n}\n","import { useMemo, useContext } from \"react\";\nimport { useAtomValue } from \"jotai\";\nimport { ChainSelectStateContext } from \"../chain-select.context\";\n\nexport function useCurrentChain() {\n const { chainAtom, chainNamespaceAtom } = useContext(ChainSelectStateContext);\n const chain = useAtomValue(chainAtom);\n const chainNamespace = useAtomValue(chainNamespaceAtom);\n return useMemo(() => ({ chain, chainNamespace }), [chain, chainNamespace]);\n}\n","import { Chain } from \"@liberfi.io/types\";\nimport { useSelectChain, useCurrentChain } from \"../hooks\";\nimport { ChainSelectUI } from \"./chain-select.ui\";\n\nexport type ChainSelectWidgetProps = {\n size?: \"sm\" | \"md\" | \"lg\";\n className?: string;\n /** Optional list of chains to show. Defaults to [SOLANA, ETHEREUM, BINANCE] when not provided. */\n candidates?: Chain[];\n onSwitchChain?: (chain: Chain) => Promise<void>;\n /** Called when switching chain succeeds; caller can toast / analytics here */\n onSuccess?: (chain: Chain) => void;\n /** Called when switching chain fails; caller can toast / modal / report here */\n onError?: (error: unknown) => void;\n};\n\nexport function ChainSelectWidget({\n size,\n className,\n candidates,\n onSwitchChain,\n onSuccess,\n onError,\n}: ChainSelectWidgetProps) {\n const { chain } = useCurrentChain();\n const { selectChain, isSwitching } = useSelectChain({\n onSwitchChain,\n onSuccess,\n onError,\n });\n\n return (\n <ChainSelectUI\n chain={chain}\n candidates={candidates}\n onSelectChain={selectChain}\n isSwitching={isSwitching}\n size={size}\n className={className}\n />\n );\n}\n"]}
|
package/dist/index.mjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import {createContext,useMemo,useContext,useState,useCallback}from'react';import {atomWithStorage}from'jotai/utils';import {Chain,ChainNamespace}from'@liberfi.io/types';import {jsx,jsxs}from'react/jsx-runtime';import {
|
|
1
|
+
import {createContext,useMemo,useContext,useState,useCallback}from'react';import {atomWithStorage}from'jotai/utils';import {Chain,ChainNamespace}from'@liberfi.io/types';import {jsx,jsxs}from'react/jsx-runtime';import {BinanceIcon,EthereumIcon,SolanaIcon,Avatar,useScreen,cn,Button,Dropdown,DropdownTrigger,DropdownMenu,DropdownItem}from'@liberfi.io/ui';import {capitalize,chainIcon,chainSlug,chainToNamespace,chainColor,chainDisplayName}from'@liberfi.io/utils';import {useSetAtom,useAtomValue}from'jotai';typeof window<"u"&&(window.__LIBERFI_VERSION__=window.__LIBERFI_VERSION__||{},window.__LIBERFI_VERSION__["@liberfi.io/ui-chain-select"]="0.1.26");var B="0.1.26";var A={getOnInit:true};function l(e=""){let t=`${e}chain`,o=`${e}chainNamespace`;return {chainAtom:atomWithStorage(t,Chain.SOLANA,void 0,A),chainNamespaceAtom:atomWithStorage(o,ChainNamespace.SOLANA,void 0,A)}}var C=l(""),g=C,fe=C.chainAtom,Se=C.chainNamespaceAtom;var h=createContext(g);function ge({storageKeyPrefix:e="",children:t}){let o=useMemo(()=>l(e),[e]);return jsx(h.Provider,{value:o,children:t})}var Q={[Chain.SOLANA]:SolanaIcon,[Chain.ETHEREUM]:EthereumIcon,[Chain.BINANCE]:BinanceIcon};function p({chain:e,className:t}){let o=Q[e];return o?jsx(o,{className:t}):jsx(Avatar,{className:t,src:chainIcon(e),name:capitalize(chainSlug(e)??"")})}var x=[Chain.SOLANA,Chain.ETHEREUM,Chain.BINANCE];function b({size:e,candidates:t,chain:o=t[0],onSelectChain:a,isSwitching:r,className:c}){let n=i=>{a?.(i);},m=cn(e==="sm"?"w-4 h-4":e==="lg"?"w-6 h-6":"w-5 h-5");return jsxs(Dropdown,{placement:"bottom-end",className:c,classNames:{content:"w-38 bg-content1 border border-border"},children:[jsx(DropdownTrigger,{children:jsx(Button,{isLoading:r,size:e,variant:"bordered",radius:"full",style:{borderColor:chainColor(o)?`${chainColor(o)}60`:void 0},startContent:jsx(p,{chain:o,className:m}),children:chainDisplayName(o)})}),jsx(DropdownMenu,{"aria-label":"Select chain",selectionMode:"single",selectedKeys:o?[o]:[],onAction:n,classNames:{list:"gap-1"},itemClasses:{base:cn("rounded-md px-3",e==="sm"?"h-8":e==="lg"?"h-12":"h-10")},children:t.map(i=>jsx(DropdownItem,{startContent:jsx(p,{chain:i,className:m}),className:i===o?"bg-content2 text-foreground":"text-neutral",children:chainDisplayName(i)},i))})]})}function P({size:e,candidates:t,chain:o=t[0],onSelectChain:a,isSwitching:r,className:c}){return jsx("div",{role:"group","aria-label":"Select chain",className:cn("flex items-center gap-1",c),children:t.map(n=>jsx(Button,{isIconOnly:true,"aria-label":chainDisplayName(n),isDisabled:r,radius:"full",className:cn("min-w-0 min-h-0 border",e==="sm"?"w-6 h-6":e==="md"||e===void 0?"w-7 h-7":"w-8 h-8",n===o?"bg-content1 scale-110 hover:opacity-100":"bg-transparent scale-90 opacity-50 hover:opacity-100 border-transparent"),style:n===o&&chainColor(n)?{borderColor:`${chainColor(n)}60`}:void 0,onPress:()=>a?.(n),children:jsx(p,{chain:n,className:cn(e==="sm"?"w-4 h-4":e==="md"||e===void 0?"w-5 h-5":"w-6 h-6")})},n))})}function D({size:e,candidates:t=x,chain:o=t[0],onSelectChain:a,isSwitching:r,className:c}){let{isMobile:n}=useScreen();return n?jsx(P,{size:e,chain:o,onSelectChain:a,isSwitching:r,candidates:t,className:c}):jsx(b,{size:e,chain:o,onSelectChain:a,isSwitching:r,candidates:t,className:c})}function R(e){let{chainAtom:t,chainNamespaceAtom:o}=useContext(h),a=useSetAtom(t),r=useSetAtom(o),[c,n]=useState(false);return {selectChain:useCallback(async i=>{try{n(!0),await e?.onSwitchChain?.(i),r(chainToNamespace(i)),a(i),e?.onSuccess?.(i);}catch(M){e?.onError?.(M);}finally{n(false);}},[a,r,e?.onSwitchChain,e?.onSuccess,e?.onError]),isSwitching:c}}function T(){let{chainAtom:e,chainNamespaceAtom:t}=useContext(h),o=useAtomValue(e),a=useAtomValue(t);return useMemo(()=>({chain:o,chainNamespace:a}),[o,a])}function ro({size:e,className:t,candidates:o,onSwitchChain:a,onSuccess:r,onError:c}){let{chain:n}=T(),{selectChain:m,isSwitching:i}=R({onSwitchChain:a,onSuccess:r,onError:c});return jsx(D,{chain:n,candidates:o,onSelectChain:m,isSwitching:i,size:e,className:t})}export{p as ChainAvatar,ge as ChainSelectProvider,h as ChainSelectStateContext,D as ChainSelectUI,ro as ChainSelectWidget,fe as chainAtom,Se as chainNamespaceAtom,l as createChainAtoms,g as defaultChainAtoms,T as useCurrentChain,R as useSelectChain,B as version};//# sourceMappingURL=index.mjs.map
|
|
2
2
|
//# sourceMappingURL=index.mjs.map
|
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/version.ts","../src/states.ts","../src/chain-select.context.tsx","../src/components/chain-avatar.tsx","../src/constants.ts","../src/components/chain-select.desktop.ui.tsx","../src/components/chain-select.mobile.ui.tsx","../src/components/chain-select.ui.tsx","../src/hooks/useSelectChain.tsx","../src/hooks/useCurrentChain.tsx","../src/components/chain-select.widget.tsx"],"names":["version_default","storageOptions","createChainAtoms","storageKeyPrefix","chainKey","chainNamespaceKey","atomWithStorage","Chain","ChainNamespace","defaultAtoms","defaultChainAtoms","chainAtom","chainNamespaceAtom","ChainSelectStateContext","createContext","ChainSelectProvider","children","value","useMemo","jsx","ChainAvatar","chain","className","SolanaIcon","EthereumIcon","BinanceIcon","Avatar","chainIcon","capitalize","chainSlug","DEFAULT_CANDIDATES","ChainSelectDesktopUI","size","candidates","onSelectChain","isSwitching","isOpen","onClose","onOpenChange","useDisclosure","handleSelect","useCallback","jsxs","Popover","PopoverTrigger","Button","chainColor","clsx","chainDisplayName","PopoverContent","it","ChainSelectMobileUI","ChainSelectUI","isMobile","useScreen","useSelectChain","options","useContext","setChain","useSetAtom","setChainNamespace","setIsSwitching","useState","chainToNamespace","e","useCurrentChain","useAtomValue","chainNamespace","ChainSelectWidget","onSwitchChain","onSuccess","onError","selectChain"],"mappings":"4fAOI,OAAO,MAAA,CAAW,MACpB,MAAA,CAAO,mBAAA,CAAsB,OAAO,mBAAA,EAAuB,EAAC,CAC5D,MAAA,CAAO,mBAAA,CAAoB,6BAA6B,EAAI,QAAA,CAAA,CAG9D,IAAOA,EAAQ,SCTf,IAAMC,CAAAA,CAAiB,CAAE,SAAA,CAAW,IAAc,EAW3C,SAASC,CAAAA,CAAiBC,EAA2B,EAAA,CAAgB,CAC1E,IAAMC,CAAAA,CAAW,CAAA,EAAGD,CAAgB,CAAA,KAAA,CAAA,CAC9BE,CAAAA,CAAoB,CAAA,EAAGF,CAAgB,CAAA,cAAA,CAAA,CAC7C,OAAO,CACL,SAAA,CAAWG,eAAAA,CACTF,EACAG,KAAAA,CAAM,MAAA,CACN,MAAA,CACAN,CACF,CAAA,CACA,kBAAA,CAAoBK,gBAClBD,CAAAA,CACAG,cAAAA,CAAe,OACf,MAAA,CACAP,CACF,CACF,CACF,CAEA,IAAMQ,CAAAA,CAAeP,CAAAA,CAAiB,EAAE,EAG3BQ,CAAAA,CAAoBD,CAAAA,CAGpBE,GAAYF,CAAAA,CAAa,SAAA,CAGzBG,GAAqBH,CAAAA,CAAa,mBCrCxC,IAAMI,EACXC,aAAAA,CAA4CJ,CAAiB,EAQxD,SAASK,EAAAA,CAAoB,CAClC,gBAAA,CAAAZ,CAAAA,CAAmB,EAAA,CACnB,QAAA,CAAAa,CACF,CAAA,CAA6B,CAC3B,IAAMC,CAAAA,CAAQC,QACZ,IAAMhB,CAAAA,CAAiBC,CAAgB,CAAA,CACvC,CAACA,CAAgB,CACnB,CAAA,CACA,OACEgB,IAACN,CAAAA,CAAwB,QAAA,CAAxB,CAAiC,KAAA,CAAOI,CAAAA,CACtC,SAAAD,CAAAA,CACH,CAEJ,CClBO,SAASI,CAAAA,CAAY,CAAE,KAAA,CAAAC,EAAO,SAAA,CAAAC,CAAU,EAAqB,CAClE,OAAQD,GACN,KAAKd,KAAAA,CAAM,MAAA,CACT,OAAOY,GAAAA,CAACI,WAAA,CAAW,SAAA,CAAWD,EAAW,CAAA,CAC3C,KAAKf,MAAM,QAAA,CACT,OAAOY,GAAAA,CAACK,YAAAA,CAAA,CAAa,SAAA,CAAWF,EAAW,CAAA,CAC7C,KAAKf,MAAM,OAAA,CACT,OAAOY,IAACM,WAAAA,CAAA,CAAY,SAAA,CAAWH,CAAAA,CAAW,CAAA,CAC5C,QACE,OACEH,GAAAA,CAACO,MAAAA,CAAA,CACC,SAAA,CAAWJ,CAAAA,CACX,IAAKK,SAAAA,CAAUN,CAAK,CAAA,CACpB,IAAA,CAAMO,UAAAA,CAAWC,SAAAA,CAAUR,CAAK,CAAA,EAAK,EAAE,EACzC,CAEN,CACF,CCvBO,IAAMS,CAAAA,CAA8B,CACzCvB,KAAAA,CAAM,MAAA,CACNA,KAAAA,CAAM,QAAA,CACNA,MAAM,OACR,CAAA,CCeO,SAASwB,CAAAA,CAAqB,CACnC,IAAA,CAAAC,CAAAA,CACA,UAAA,CAAAC,CAAAA,CACA,MAAAZ,CAAAA,CAAQY,CAAAA,CAAW,CAAC,CAAA,CACpB,aAAA,CAAAC,EACA,WAAA,CAAAC,CAAAA,CACA,SAAA,CAAAb,CACF,CAAA,CAA8B,CAC5B,GAAM,CAAE,MAAA,CAAAc,EAAQ,OAAA,CAAAC,CAAAA,CAAS,aAAAC,CAAa,CAAA,CAAIC,aAAAA,EAAc,CAElDC,CAAAA,CAAeC,WAAAA,CAClBpB,GAAiB,CAChBa,CAAAA,GAAgBb,CAAK,CAAA,CACrBgB,CAAAA,GACF,CAAA,CACA,CAACH,CAAAA,CAAeG,CAAO,CACzB,CAAA,CAEA,OACEK,IAAAA,CAACC,OAAAA,CAAA,CACC,MAAA,CAAQP,CAAAA,CACR,aAAcE,CAAAA,CACd,SAAA,CAAU,YAAA,CACV,SAAA,CAAWhB,CAAAA,CACX,UAAA,CAAY,CAAE,OAAA,CAAS,uCAAwC,EAE/D,QAAA,CAAA,CAAAH,GAAAA,CAACyB,eAAA,CACC,QAAA,CAAAzB,GAAAA,CAAC0B,MAAAA,CAAA,CACC,SAAA,CAAWV,EACX,IAAA,CAAMH,CAAAA,CACN,QAAQ,UAAA,CACR,MAAA,CAAO,OACP,KAAA,CAAO,CACL,WAAA,CAAac,UAAAA,CAAWzB,CAAK,CAAA,CACzB,GAAGyB,UAAAA,CAAWzB,CAAK,CAAC,CAAA,EAAA,CAAA,CACpB,MACN,EACA,YAAA,CACEF,GAAAA,CAACC,CAAAA,CAAA,CACC,KAAA,CAAOC,CAAAA,CACP,UAAW0B,IAAAA,CACTf,CAAAA,GAAS,KACL,SAAA,CACAA,CAAAA,GAAS,KACP,SAAA,CACA,SACR,CAAA,CACF,CAAA,CAGD,QAAA,CAAAgB,gBAAAA,CAAiB3B,CAAK,CAAA,CACzB,CAAA,CACF,EACAF,GAAAA,CAAC8B,cAAAA,CAAA,CAAe,SAAA,CAAU,yCAAA,CACvB,QAAA,CAAAhB,CAAAA,CAAW,GAAA,CAAKiB,CAAAA,EACfR,KAAC,KAAA,CAAA,CAEC,SAAA,CAAWK,KACT,4DAAA,CACA,yBAAA,CACAf,IAAS,IAAA,CAAO,KAAA,CAAQA,CAAAA,GAAS,IAAA,CAAO,MAAA,CAAS,MAAA,CACjDkB,IAAO7B,CAAAA,CAAQ,6BAAA,CAAgC,cACjD,CAAA,CACA,OAAA,CAAS,IAAMmB,CAAAA,CAAaU,CAAE,CAAA,CAE9B,QAAA,CAAA,CAAA/B,GAAAA,CAACC,CAAAA,CAAA,CACC,KAAA,CAAO8B,CAAAA,CACP,UAAWH,IAAAA,CACTf,CAAAA,GAAS,KACL,SAAA,CACAA,CAAAA,GAAS,IAAA,CACP,SAAA,CACA,SACR,CAAA,CACF,EACCgB,gBAAAA,CAAiBE,CAAE,IAnBfA,CAoBP,CACD,EACH,CAAA,CAAA,CACF,CAEJ,CCzFO,SAASC,CAAAA,CAAoB,CAClC,IAAA,CAAAnB,CAAAA,CACA,WAAAC,CAAAA,CACA,KAAA,CAAAZ,CAAAA,CAAQd,KAAAA,CAAM,MAAA,CACd,aAAA,CAAA2B,EACA,WAAA,CAAAC,CAAAA,CACA,UAAAb,CACF,CAAA,CAA6B,CAC3B,OACEH,GAAAA,CAAC,KAAA,CAAA,CAAI,SAAA,CAAW4B,IAAAA,CAAK,yBAAA,CAA2BzB,CAAS,CAAA,CACtD,QAAA,CAAAW,EAAW,GAAA,CAAKiB,CAAAA,EACf/B,IAAC0B,MAAAA,CAAA,CACC,UAAA,CAAU,IAAA,CACV,UAAA,CAAYV,CAAAA,CACZ,OAAO,MAAA,CACP,SAAA,CAAWY,KACT,wBAAA,CACAf,CAAAA,GAAS,KACL,SAAA,CACAA,CAAAA,GAAS,IAAA,EAAQA,CAAAA,GAAS,MAAA,CACxB,SAAA,CACA,UACNkB,CAAAA,GAAO7B,CAAAA,CACH,0CACA,yEACN,CAAA,CACA,MACE6B,CAAAA,GAAO7B,CAAAA,EAASyB,UAAAA,CAAWI,CAAE,CAAA,CACzB,CAAE,YAAa,CAAA,EAAGJ,UAAAA,CAAWI,CAAE,CAAC,CAAA,EAAA,CAAK,EACrC,MAAA,CAGN,OAAA,CAAS,IAAMhB,CAAAA,GAAgBgB,CAAE,CAAA,CAEjC,SAAA/B,GAAAA,CAACC,CAAAA,CAAA,CACC,KAAA,CAAO8B,CAAAA,CACP,UAAWH,IAAAA,CACTf,CAAAA,GAAS,IAAA,CACL,SAAA,CACAA,CAAAA,GAAS,IAAA,EAAQA,IAAS,MAAA,CACxB,SAAA,CACA,SACR,CAAA,CACF,CAAA,CAAA,CAZKkB,CAaP,CACD,CAAA,CACH,CAEJ,CC/CO,SAASE,CAAAA,CAAc,CAC5B,IAAA,CAAApB,CAAAA,CACA,MAAAX,CAAAA,CAAQd,KAAAA,CAAM,MAAA,CACd,UAAA,CAAA0B,CAAAA,CAAaH,CAAAA,CACb,cAAAI,CAAAA,CACA,WAAA,CAAAC,EACA,SAAA,CAAAb,CACF,EAAuB,CACrB,GAAM,CAAE,QAAA,CAAA+B,CAAS,CAAA,CAAIC,WAAU,CAE/B,OAAID,EAEAlC,GAAAA,CAACgC,CAAAA,CAAA,CACC,IAAA,CAAMnB,CAAAA,CACN,KAAA,CAAOX,CAAAA,CACP,aAAA,CAAea,CAAAA,CACf,YAAaC,CAAAA,CACb,UAAA,CAAYF,EACZ,SAAA,CAAWX,CAAAA,CACb,EAIAH,GAAAA,CAACY,CAAAA,CAAA,CACC,IAAA,CAAMC,CAAAA,CACN,KAAA,CAAOX,EACP,aAAA,CAAea,CAAAA,CACf,YAAaC,CAAAA,CACb,UAAA,CAAYF,EACZ,SAAA,CAAWX,CAAAA,CACb,CAGN,CClCO,SAASiC,CAAAA,CAAeC,EAAiC,CAC9D,GAAM,CAAE,SAAA,CAAA7C,CAAAA,CAAW,kBAAA,CAAAC,CAAmB,CAAA,CAAI6C,UAAAA,CAAW5C,CAAuB,CAAA,CACtE6C,CAAAA,CAAWC,WAAWhD,CAAS,CAAA,CAC/BiD,EAAoBD,UAAAA,CAAW/C,CAAkB,CAAA,CACjD,CAACuB,CAAAA,CAAa0B,CAAc,EAAIC,QAAAA,CAAS,KAAK,EA0BpD,OAAO,CAAE,YAxBWrB,WAAAA,CAClB,MAAOpB,CAAAA,EAAiB,CACtB,GAAI,CACFwC,EAAe,CAAA,CAAI,CAAA,CACnB,MAAML,CAAAA,EAAS,aAAA,GAAgBnC,CAAK,CAAA,CAEpCuC,CAAAA,CAAkBG,gBAAAA,CAAiB1C,CAAK,CAAC,CAAA,CACzCqC,EAASrC,CAAK,CAAA,CACdmC,GAAS,SAAA,GAAYnC,CAAK,EAC5B,CAAA,MAAS2C,CAAAA,CAAG,CACVR,CAAAA,EAAS,OAAA,GAAUQ,CAAC,EACtB,CAAA,OAAE,CACAH,EAAe,KAAK,EACtB,CACF,CAAA,CACA,CACEH,CAAAA,CACAE,CAAAA,CACAJ,CAAAA,EAAS,aAAA,CACTA,GAAS,SAAA,CACTA,CAAAA,EAAS,OACX,CACF,CAAA,CAEsB,YAAArB,CAAY,CACpC,CCzCO,SAAS8B,CAAAA,EAAkB,CAChC,GAAM,CAAE,SAAA,CAAAtD,EAAW,kBAAA,CAAAC,CAAmB,EAAI6C,UAAAA,CAAW5C,CAAuB,EACtEQ,CAAAA,CAAQ6C,YAAAA,CAAavD,CAAS,CAAA,CAC9BwD,CAAAA,CAAiBD,YAAAA,CAAatD,CAAkB,CAAA,CACtD,OAAOM,QAAQ,KAAO,CAAE,MAAAG,CAAAA,CAAO,cAAA,CAAA8C,CAAe,CAAA,CAAA,CAAI,CAAC9C,CAAAA,CAAO8C,CAAc,CAAC,CAC3E,CCOO,SAASC,EAAAA,CAAkB,CAChC,IAAA,CAAApC,CAAAA,CACA,SAAA,CAAAV,EACA,UAAA,CAAAW,CAAAA,CACA,cAAAoC,CAAAA,CACA,SAAA,CAAAC,EACA,OAAA,CAAAC,CACF,CAAA,CAA2B,CACzB,GAAM,CAAE,MAAAlD,CAAM,CAAA,CAAI4C,GAAgB,CAC5B,CAAE,YAAAO,CAAAA,CAAa,WAAA,CAAArC,CAAY,CAAA,CAAIoB,CAAAA,CAAe,CAClD,cAAAc,CAAAA,CACA,SAAA,CAAAC,EACA,OAAA,CAAAC,CACF,CAAC,CAAA,CAED,OACEpD,GAAAA,CAACiC,CAAAA,CAAA,CACC,KAAA,CAAO/B,EACP,UAAA,CAAYY,CAAAA,CACZ,cAAeuC,CAAAA,CACf,WAAA,CAAarC,EACb,IAAA,CAAMH,CAAAA,CACN,SAAA,CAAWV,CAAAA,CACb,CAEJ","file":"index.mjs","sourcesContent":["declare global {\n interface Window {\n __LIBERFI_VERSION__?: {\n [key: string]: string;\n };\n }\n}\nif (typeof window !== \"undefined\") {\n window.__LIBERFI_VERSION__ = window.__LIBERFI_VERSION__ || {};\n window.__LIBERFI_VERSION__[\"@liberfi.io/ui-chain-select\"] = \"0.1.24\";\n}\n\nexport default \"0.1.24\";\n","import { atomWithStorage } from \"jotai/utils\";\nimport { Chain, ChainNamespace } from \"@liberfi.io/types\";\n\nconst storageOptions = { getOnInit: true as const };\n\nexport type ChainAtoms = {\n chainAtom: ReturnType<typeof atomWithStorage<Chain>>;\n chainNamespaceAtom: ReturnType<typeof atomWithStorage<ChainNamespace>>;\n};\n\n/**\n * Creates chain state atoms with optional storage key prefix.\n * Use a prefix when multiple independent chain selectors must coexist on the same origin.\n */\nexport function createChainAtoms(storageKeyPrefix: string = \"\"): ChainAtoms {\n const chainKey = `${storageKeyPrefix}chain`;\n const chainNamespaceKey = `${storageKeyPrefix}chainNamespace`;\n return {\n chainAtom: atomWithStorage<Chain>(\n chainKey,\n Chain.SOLANA,\n undefined,\n storageOptions,\n ),\n chainNamespaceAtom: atomWithStorage<ChainNamespace>(\n chainNamespaceKey,\n ChainNamespace.SOLANA,\n undefined,\n storageOptions,\n ),\n };\n}\n\nconst defaultAtoms = createChainAtoms(\"\");\n\n/** Default atoms (used when not inside ChainSelectProvider) */\nexport const defaultChainAtoms = defaultAtoms;\n\n/** Current chain (default instance, key \"chain\") */\nexport const chainAtom = defaultAtoms.chainAtom;\n\n/** Current chain namespace (default instance, key \"chainNamespace\") */\nexport const chainNamespaceAtom = defaultAtoms.chainNamespaceAtom;\n","import { createContext, useMemo, type ReactNode } from \"react\";\nimport { createChainAtoms, defaultChainAtoms } from \"./states\";\n\nexport type ChainSelectStateContextValue = ReturnType<typeof createChainAtoms>;\n\nexport const ChainSelectStateContext =\n createContext<ChainSelectStateContextValue>(defaultChainAtoms);\n\nexport type ChainSelectProviderProps = {\n /** Optional storage key prefix so multiple instances can coexist (e.g. \"app1_\") */\n storageKeyPrefix?: string;\n children: ReactNode;\n};\n\nexport function ChainSelectProvider({\n storageKeyPrefix = \"\",\n children,\n}: ChainSelectProviderProps) {\n const value = useMemo(\n () => createChainAtoms(storageKeyPrefix),\n [storageKeyPrefix],\n );\n return (\n <ChainSelectStateContext.Provider value={value}>\n {children}\n </ChainSelectStateContext.Provider>\n );\n}\n","import { Chain } from \"@liberfi.io/types\";\nimport { Avatar, BinanceIcon, EthereumIcon, SolanaIcon } from \"@liberfi.io/ui\";\nimport { capitalize, chainIcon, chainSlug } from \"@liberfi.io/utils\";\n\nexport type ChainAvatarProps = {\n chain: Chain;\n className?: string;\n};\n\nexport function ChainAvatar({ chain, className }: ChainAvatarProps) {\n switch (chain) {\n case Chain.SOLANA:\n return <SolanaIcon className={className} />;\n case Chain.ETHEREUM:\n return <EthereumIcon className={className} />;\n case Chain.BINANCE:\n return <BinanceIcon className={className} />;\n default:\n return (\n <Avatar\n className={className}\n src={chainIcon(chain)}\n name={capitalize(chainSlug(chain) ?? \"\")}\n />\n );\n }\n}\n","import { Chain } from \"@liberfi.io/types\";\n\n/** Default chain list when candidates are not provided */\nexport const DEFAULT_CANDIDATES: Chain[] = [\n Chain.SOLANA,\n Chain.ETHEREUM,\n Chain.BINANCE,\n];\n","import { useCallback } from \"react\";\nimport { Chain } from \"@liberfi.io/types\";\nimport {\n Button,\n clsx,\n Popover,\n PopoverContent,\n PopoverTrigger,\n useDisclosure,\n} from \"@liberfi.io/ui\";\nimport { chainColor, chainDisplayName } from \"@liberfi.io/utils\";\nimport { ChainAvatar } from \"./chain-avatar\";\n\nexport type ChainSelectDesktopUIProps = {\n size?: \"sm\" | \"md\" | \"lg\";\n candidates: Chain[];\n chain?: Chain;\n onSelectChain?: (chain: Chain) => void | Promise<void>;\n isSwitching?: boolean;\n className?: string;\n};\n\nexport function ChainSelectDesktopUI({\n size,\n candidates,\n chain = candidates[0],\n onSelectChain,\n isSwitching,\n className,\n}: ChainSelectDesktopUIProps) {\n const { isOpen, onClose, onOpenChange } = useDisclosure();\n\n const handleSelect = useCallback(\n (chain: Chain) => {\n onSelectChain?.(chain);\n onClose();\n },\n [onSelectChain, onClose],\n );\n\n return (\n <Popover\n isOpen={isOpen}\n onOpenChange={onOpenChange}\n placement=\"bottom-end\"\n className={className}\n classNames={{ content: \"w-38 bg-content1 border border-border\" }}\n >\n <PopoverTrigger>\n <Button\n isLoading={isSwitching}\n size={size}\n variant=\"bordered\"\n radius=\"full\"\n style={{\n borderColor: chainColor(chain)\n ? `${chainColor(chain)}60`\n : undefined,\n }}\n startContent={\n <ChainAvatar\n chain={chain}\n className={clsx(\n size === \"sm\"\n ? \"w-4 h-4\"\n : size === \"lg\"\n ? \"w-6 h-6\"\n : \"w-5 h-5\",\n )}\n />\n }\n >\n {chainDisplayName(chain)}\n </Button>\n </PopoverTrigger>\n <PopoverContent className=\"w-40 flex flex-col gap-1 p-1 rounded-md\">\n {candidates.map((it) => (\n <div\n key={it}\n className={clsx(\n \"w-full hover:bg-content2/80 cursor-pointer rounded-md px-3\",\n \"flex gap-2 items-center\",\n size === \"sm\" ? \"h-8\" : size === \"lg\" ? \"h-12\" : \"h-10\",\n it === chain ? \"bg-content2 text-foreground\" : \"text-neutral\",\n )}\n onClick={() => handleSelect(it)}\n >\n <ChainAvatar\n chain={it}\n className={clsx(\n size === \"sm\"\n ? \"w-4 h-4\"\n : size === \"lg\"\n ? \"w-6 h-6\"\n : \"w-5 h-5\",\n )}\n />\n {chainDisplayName(it)}\n </div>\n ))}\n </PopoverContent>\n </Popover>\n );\n}\n","import { Chain } from \"@liberfi.io/types\";\nimport { Button, clsx } from \"@liberfi.io/ui\";\nimport { chainColor } from \"@liberfi.io/utils\";\nimport { ChainAvatar } from \"./chain-avatar\";\n\nexport type ChainSelectMobileUIProps = {\n size?: \"sm\" | \"md\" | \"lg\";\n candidates: Chain[];\n chain?: Chain;\n onSelectChain?: (chain: Chain) => void | Promise<void>;\n isSwitching?: boolean;\n className?: string;\n};\n\nexport function ChainSelectMobileUI({\n size,\n candidates,\n chain = Chain.SOLANA,\n onSelectChain,\n isSwitching,\n className,\n}: ChainSelectMobileUIProps) {\n return (\n <div className={clsx(\"flex items-center gap-1\", className)}>\n {candidates.map((it) => (\n <Button\n isIconOnly\n isDisabled={isSwitching}\n radius=\"full\"\n className={clsx(\n \"min-w-0 min-h-0 border\",\n size === \"sm\"\n ? \"w-6 h-6\"\n : size === \"md\" || size === undefined\n ? \"w-7 h-7\"\n : \"w-8 h-8\",\n it === chain\n ? \"bg-content1 scale-110 hover:opacity-100\"\n : \"bg-transparent scale-90 opacity-50 hover:opacity-100 border-transparent\",\n )}\n style={\n it === chain && chainColor(it)\n ? { borderColor: `${chainColor(it)}60` }\n : undefined\n }\n key={it}\n onPress={() => onSelectChain?.(it)}\n >\n <ChainAvatar\n chain={it}\n className={clsx(\n size === \"sm\"\n ? \"w-4 h-4\"\n : size === \"md\" || size === undefined\n ? \"w-5 h-5\"\n : \"w-6 h-6\",\n )}\n />\n </Button>\n ))}\n </div>\n );\n}\n","import { Chain } from \"@liberfi.io/types\";\nimport { useScreen } from \"@liberfi.io/ui\";\nimport { DEFAULT_CANDIDATES } from \"../constants\";\nimport { ChainSelectDesktopUI } from \"./chain-select.desktop.ui\";\nimport { ChainSelectMobileUI } from \"./chain-select.mobile.ui\";\n\nexport type ChainSelectUIProps = {\n size?: \"sm\" | \"md\" | \"lg\";\n chain?: Chain;\n candidates?: Chain[];\n onSelectChain?: (chain: Chain) => void | Promise<void>;\n isSwitching?: boolean;\n className?: string;\n};\n\nexport function ChainSelectUI({\n size,\n chain = Chain.SOLANA,\n candidates = DEFAULT_CANDIDATES,\n onSelectChain,\n isSwitching,\n className,\n}: ChainSelectUIProps) {\n const { isMobile } = useScreen();\n\n if (isMobile) {\n return (\n <ChainSelectMobileUI\n size={size}\n chain={chain}\n onSelectChain={onSelectChain}\n isSwitching={isSwitching}\n candidates={candidates}\n className={className}\n />\n );\n } else {\n return (\n <ChainSelectDesktopUI\n size={size}\n chain={chain}\n onSelectChain={onSelectChain}\n isSwitching={isSwitching}\n candidates={candidates}\n className={className}\n />\n );\n }\n}\n","import { useCallback, useContext, useState } from \"react\";\nimport { useSetAtom } from \"jotai\";\nimport { Chain } from \"@liberfi.io/types\";\nimport { chainToNamespace } from \"@liberfi.io/utils\";\nimport { ChainSelectStateContext } from \"../chain-select.context\";\n\nexport type UseSelectChainOptions = {\n onSwitchChain?: (chain: Chain) => Promise<void>;\n /** Called when switching chain succeeds; caller can toast / analytics here */\n onSuccess?: (chain: Chain) => void;\n /** Called when switching chain fails; caller can toast / modal / report here */\n onError?: (error: unknown) => void;\n};\n\nexport function useSelectChain(options?: UseSelectChainOptions) {\n const { chainAtom, chainNamespaceAtom } = useContext(ChainSelectStateContext);\n const setChain = useSetAtom(chainAtom);\n const setChainNamespace = useSetAtom(chainNamespaceAtom);\n const [isSwitching, setIsSwitching] = useState(false);\n\n const selectChain = useCallback(\n async (chain: Chain) => {\n try {\n setIsSwitching(true);\n await options?.onSwitchChain?.(chain);\n\n setChainNamespace(chainToNamespace(chain));\n setChain(chain);\n options?.onSuccess?.(chain);\n } catch (e) {\n options?.onError?.(e);\n } finally {\n setIsSwitching(false);\n }\n },\n [\n setChain,\n setChainNamespace,\n options?.onSwitchChain,\n options?.onSuccess,\n options?.onError,\n ],\n );\n\n return { selectChain, isSwitching };\n}\n","import { useMemo, useContext } from \"react\";\nimport { useAtomValue } from \"jotai\";\nimport { ChainSelectStateContext } from \"../chain-select.context\";\n\nexport function useCurrentChain() {\n const { chainAtom, chainNamespaceAtom } = useContext(ChainSelectStateContext);\n const chain = useAtomValue(chainAtom);\n const chainNamespace = useAtomValue(chainNamespaceAtom);\n return useMemo(() => ({ chain, chainNamespace }), [chain, chainNamespace]);\n}\n","import { Chain } from \"@liberfi.io/types\";\nimport { useSelectChain, useCurrentChain } from \"../hooks\";\nimport { ChainSelectUI } from \"./chain-select.ui\";\n\nexport type ChainSelectWidgetProps = {\n size?: \"sm\" | \"md\" | \"lg\";\n className?: string;\n /** Optional list of chains to show. Defaults to [SOLANA, ETHEREUM, BINANCE] when not provided. */\n candidates?: Chain[];\n onSwitchChain?: (chain: Chain) => Promise<void>;\n /** Called when switching chain succeeds; caller can toast / analytics here */\n onSuccess?: (chain: Chain) => void;\n /** Called when switching chain fails; caller can toast / modal / report here */\n onError?: (error: unknown) => void;\n};\n\nexport function ChainSelectWidget({\n size,\n className,\n candidates,\n onSwitchChain,\n onSuccess,\n onError,\n}: ChainSelectWidgetProps) {\n const { chain } = useCurrentChain();\n const { selectChain, isSwitching } = useSelectChain({\n onSwitchChain,\n onSuccess,\n onError,\n });\n\n return (\n <ChainSelectUI\n chain={chain}\n candidates={candidates}\n onSelectChain={selectChain}\n isSwitching={isSwitching}\n size={size}\n className={className}\n />\n );\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/version.ts","../src/states.ts","../src/chain-select.context.tsx","../src/components/chain-avatar.tsx","../src/constants.ts","../src/components/chain-select.desktop.ui.tsx","../src/components/chain-select.mobile.ui.tsx","../src/components/chain-select.ui.tsx","../src/hooks/useSelectChain.tsx","../src/hooks/useCurrentChain.tsx","../src/components/chain-select.widget.tsx"],"names":["version_default","storageOptions","createChainAtoms","storageKeyPrefix","chainKey","chainNamespaceKey","atomWithStorage","Chain","ChainNamespace","defaultAtoms","defaultChainAtoms","chainAtom","chainNamespaceAtom","ChainSelectStateContext","createContext","ChainSelectProvider","children","value","useMemo","jsx","CHAIN_ICON_MAP","SolanaIcon","EthereumIcon","BinanceIcon","ChainAvatar","chain","className","Icon","Avatar","chainIcon","capitalize","chainSlug","DEFAULT_CANDIDATES","ChainSelectDesktopUI","size","candidates","onSelectChain","isSwitching","handleAction","key","avatarSize","cn","jsxs","Dropdown","DropdownTrigger","Button","chainColor","chainDisplayName","DropdownMenu","it","DropdownItem","ChainSelectMobileUI","ChainSelectUI","isMobile","useScreen","useSelectChain","options","useContext","setChain","useSetAtom","setChainNamespace","setIsSwitching","useState","useCallback","chainToNamespace","e","useCurrentChain","useAtomValue","chainNamespace","ChainSelectWidget","onSwitchChain","onSuccess","onError","selectChain"],"mappings":"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","file":"index.mjs","sourcesContent":["declare global {\n interface Window {\n __LIBERFI_VERSION__?: {\n [key: string]: string;\n };\n }\n}\nif (typeof window !== \"undefined\") {\n window.__LIBERFI_VERSION__ = window.__LIBERFI_VERSION__ || {};\n window.__LIBERFI_VERSION__[\"@liberfi.io/ui-chain-select\"] = \"0.1.26\";\n}\n\nexport default \"0.1.26\";\n","import { atomWithStorage } from \"jotai/utils\";\nimport { Chain, ChainNamespace } from \"@liberfi.io/types\";\n\nconst storageOptions = { getOnInit: true as const };\n\nexport type ChainAtoms = {\n chainAtom: ReturnType<typeof atomWithStorage<Chain>>;\n chainNamespaceAtom: ReturnType<typeof atomWithStorage<ChainNamespace>>;\n};\n\n/**\n * Creates chain state atoms with optional storage key prefix.\n * Use a prefix when multiple independent chain selectors must coexist on the same origin.\n */\nexport function createChainAtoms(storageKeyPrefix: string = \"\"): ChainAtoms {\n const chainKey = `${storageKeyPrefix}chain`;\n const chainNamespaceKey = `${storageKeyPrefix}chainNamespace`;\n return {\n chainAtom: atomWithStorage<Chain>(\n chainKey,\n Chain.SOLANA,\n undefined,\n storageOptions,\n ),\n chainNamespaceAtom: atomWithStorage<ChainNamespace>(\n chainNamespaceKey,\n ChainNamespace.SOLANA,\n undefined,\n storageOptions,\n ),\n };\n}\n\nconst defaultAtoms = createChainAtoms(\"\");\n\n/** Default atoms (used when not inside ChainSelectProvider) */\nexport const defaultChainAtoms = defaultAtoms;\n\n/** Current chain (default instance, key \"chain\") */\nexport const chainAtom = defaultAtoms.chainAtom;\n\n/** Current chain namespace (default instance, key \"chainNamespace\") */\nexport const chainNamespaceAtom = defaultAtoms.chainNamespaceAtom;\n","import { createContext, useMemo, type ReactNode } from \"react\";\nimport { createChainAtoms, defaultChainAtoms } from \"./states\";\n\nexport type ChainSelectStateContextValue = ReturnType<typeof createChainAtoms>;\n\nexport const ChainSelectStateContext =\n createContext<ChainSelectStateContextValue>(defaultChainAtoms);\n\nexport type ChainSelectProviderProps = {\n /** Optional storage key prefix so multiple instances can coexist (e.g. \"app1_\") */\n storageKeyPrefix?: string;\n children: ReactNode;\n};\n\nexport function ChainSelectProvider({\n storageKeyPrefix = \"\",\n children,\n}: ChainSelectProviderProps) {\n const value = useMemo(\n () => createChainAtoms(storageKeyPrefix),\n [storageKeyPrefix],\n );\n return (\n <ChainSelectStateContext.Provider value={value}>\n {children}\n </ChainSelectStateContext.Provider>\n );\n}\n","import type { ComponentType } from \"react\";\nimport { Chain } from \"@liberfi.io/types\";\nimport { Avatar, BinanceIcon, EthereumIcon, SolanaIcon } from \"@liberfi.io/ui\";\nimport { capitalize, chainIcon, chainSlug } from \"@liberfi.io/utils\";\n\nexport type ChainAvatarProps = {\n chain: Chain;\n className?: string;\n};\n\nconst CHAIN_ICON_MAP: Partial<\n Record<Chain, ComponentType<{ className?: string }>>\n> = {\n [Chain.SOLANA]: SolanaIcon,\n [Chain.ETHEREUM]: EthereumIcon,\n [Chain.BINANCE]: BinanceIcon,\n};\n\nexport function ChainAvatar({ chain, className }: ChainAvatarProps) {\n const Icon = CHAIN_ICON_MAP[chain];\n if (Icon) return <Icon className={className} />;\n return (\n <Avatar\n className={className}\n src={chainIcon(chain)}\n name={capitalize(chainSlug(chain) ?? \"\")}\n />\n );\n}\n","import { Chain } from \"@liberfi.io/types\";\n\n/** Default chain list when candidates are not provided */\nexport const DEFAULT_CANDIDATES: Chain[] = [\n Chain.SOLANA,\n Chain.ETHEREUM,\n Chain.BINANCE,\n];\n","import { type Key } from \"react\";\nimport { Chain } from \"@liberfi.io/types\";\nimport {\n Button,\n cn,\n Dropdown,\n DropdownItem,\n DropdownMenu,\n DropdownTrigger,\n} from \"@liberfi.io/ui\";\nimport { chainColor, chainDisplayName } from \"@liberfi.io/utils\";\nimport { ChainAvatar } from \"./chain-avatar\";\n\nexport type ChainSelectDesktopUIProps = {\n size?: \"sm\" | \"md\" | \"lg\";\n candidates: Chain[];\n chain?: Chain;\n onSelectChain?: (chain: Chain) => void | Promise<void>;\n isSwitching?: boolean;\n className?: string;\n};\n\nexport function ChainSelectDesktopUI({\n size,\n candidates,\n chain = candidates[0],\n onSelectChain,\n isSwitching,\n className,\n}: ChainSelectDesktopUIProps) {\n const handleAction = (key: Key) => {\n onSelectChain?.(key as Chain);\n };\n\n const avatarSize = cn(\n size === \"sm\" ? \"w-4 h-4\" : size === \"lg\" ? \"w-6 h-6\" : \"w-5 h-5\",\n );\n\n return (\n <Dropdown\n placement=\"bottom-end\"\n className={className}\n classNames={{ content: \"w-38 bg-content1 border border-border\" }}\n >\n <DropdownTrigger>\n <Button\n isLoading={isSwitching}\n size={size}\n variant=\"bordered\"\n radius=\"full\"\n style={{\n borderColor: chainColor(chain)\n ? `${chainColor(chain)}60`\n : undefined,\n }}\n startContent={<ChainAvatar chain={chain} className={avatarSize} />}\n >\n {chainDisplayName(chain)}\n </Button>\n </DropdownTrigger>\n <DropdownMenu\n aria-label=\"Select chain\"\n selectionMode=\"single\"\n selectedKeys={chain ? [chain] : []}\n onAction={handleAction}\n classNames={{ list: \"gap-1\" }}\n itemClasses={{\n base: cn(\n \"rounded-md px-3\",\n size === \"sm\" ? \"h-8\" : size === \"lg\" ? \"h-12\" : \"h-10\",\n ),\n }}\n >\n {candidates.map((it) => (\n <DropdownItem\n key={it}\n startContent={<ChainAvatar chain={it} className={avatarSize} />}\n className={\n it === chain ? \"bg-content2 text-foreground\" : \"text-neutral\"\n }\n >\n {chainDisplayName(it)}\n </DropdownItem>\n ))}\n </DropdownMenu>\n </Dropdown>\n );\n}\n","import { Chain } from \"@liberfi.io/types\";\nimport { Button, cn } from \"@liberfi.io/ui\";\nimport { chainColor, chainDisplayName } from \"@liberfi.io/utils\";\nimport { ChainAvatar } from \"./chain-avatar\";\n\nexport type ChainSelectMobileUIProps = {\n size?: \"sm\" | \"md\" | \"lg\";\n candidates: Chain[];\n chain?: Chain;\n onSelectChain?: (chain: Chain) => void | Promise<void>;\n isSwitching?: boolean;\n className?: string;\n};\n\nexport function ChainSelectMobileUI({\n size,\n candidates,\n chain = candidates[0],\n onSelectChain,\n isSwitching,\n className,\n}: ChainSelectMobileUIProps) {\n return (\n <div\n role=\"group\"\n aria-label=\"Select chain\"\n className={cn(\"flex items-center gap-1\", className)}\n >\n {candidates.map((it) => (\n <Button\n isIconOnly\n aria-label={chainDisplayName(it)}\n isDisabled={isSwitching}\n radius=\"full\"\n className={cn(\n \"min-w-0 min-h-0 border\",\n size === \"sm\"\n ? \"w-6 h-6\"\n : size === \"md\" || size === undefined\n ? \"w-7 h-7\"\n : \"w-8 h-8\",\n it === chain\n ? \"bg-content1 scale-110 hover:opacity-100\"\n : \"bg-transparent scale-90 opacity-50 hover:opacity-100 border-transparent\",\n )}\n style={\n it === chain && chainColor(it)\n ? { borderColor: `${chainColor(it)}60` }\n : undefined\n }\n key={it}\n onPress={() => onSelectChain?.(it)}\n >\n <ChainAvatar\n chain={it}\n className={cn(\n size === \"sm\"\n ? \"w-4 h-4\"\n : size === \"md\" || size === undefined\n ? \"w-5 h-5\"\n : \"w-6 h-6\",\n )}\n />\n </Button>\n ))}\n </div>\n );\n}\n","import { Chain } from \"@liberfi.io/types\";\nimport { useScreen } from \"@liberfi.io/ui\";\nimport { DEFAULT_CANDIDATES } from \"../constants\";\nimport { ChainSelectDesktopUI } from \"./chain-select.desktop.ui\";\nimport { ChainSelectMobileUI } from \"./chain-select.mobile.ui\";\n\nexport type ChainSelectUIProps = {\n size?: \"sm\" | \"md\" | \"lg\";\n chain?: Chain;\n candidates?: Chain[];\n onSelectChain?: (chain: Chain) => void | Promise<void>;\n isSwitching?: boolean;\n className?: string;\n};\n\nexport function ChainSelectUI({\n size,\n candidates = DEFAULT_CANDIDATES,\n chain = candidates[0],\n onSelectChain,\n isSwitching,\n className,\n}: ChainSelectUIProps) {\n const { isMobile } = useScreen();\n\n if (isMobile) {\n return (\n <ChainSelectMobileUI\n size={size}\n chain={chain}\n onSelectChain={onSelectChain}\n isSwitching={isSwitching}\n candidates={candidates}\n className={className}\n />\n );\n } else {\n return (\n <ChainSelectDesktopUI\n size={size}\n chain={chain}\n onSelectChain={onSelectChain}\n isSwitching={isSwitching}\n candidates={candidates}\n className={className}\n />\n );\n }\n}\n","import { useCallback, useContext, useState } from \"react\";\nimport { useSetAtom } from \"jotai\";\nimport { Chain } from \"@liberfi.io/types\";\nimport { chainToNamespace } from \"@liberfi.io/utils\";\nimport { ChainSelectStateContext } from \"../chain-select.context\";\n\nexport type UseSelectChainOptions = {\n onSwitchChain?: (chain: Chain) => Promise<void>;\n /** Called when switching chain succeeds; caller can toast / analytics here */\n onSuccess?: (chain: Chain) => void;\n /** Called when switching chain fails; caller can toast / modal / report here */\n onError?: (error: unknown) => void;\n};\n\nexport function useSelectChain(options?: UseSelectChainOptions) {\n const { chainAtom, chainNamespaceAtom } = useContext(ChainSelectStateContext);\n const setChain = useSetAtom(chainAtom);\n const setChainNamespace = useSetAtom(chainNamespaceAtom);\n const [isSwitching, setIsSwitching] = useState(false);\n\n const selectChain = useCallback(\n async (chain: Chain) => {\n try {\n setIsSwitching(true);\n await options?.onSwitchChain?.(chain);\n\n setChainNamespace(chainToNamespace(chain));\n setChain(chain);\n options?.onSuccess?.(chain);\n } catch (e) {\n options?.onError?.(e);\n } finally {\n setIsSwitching(false);\n }\n },\n [\n setChain,\n setChainNamespace,\n options?.onSwitchChain,\n options?.onSuccess,\n options?.onError,\n ],\n );\n\n return { selectChain, isSwitching };\n}\n","import { useMemo, useContext } from \"react\";\nimport { useAtomValue } from \"jotai\";\nimport { ChainSelectStateContext } from \"../chain-select.context\";\n\nexport function useCurrentChain() {\n const { chainAtom, chainNamespaceAtom } = useContext(ChainSelectStateContext);\n const chain = useAtomValue(chainAtom);\n const chainNamespace = useAtomValue(chainNamespaceAtom);\n return useMemo(() => ({ chain, chainNamespace }), [chain, chainNamespace]);\n}\n","import { Chain } from \"@liberfi.io/types\";\nimport { useSelectChain, useCurrentChain } from \"../hooks\";\nimport { ChainSelectUI } from \"./chain-select.ui\";\n\nexport type ChainSelectWidgetProps = {\n size?: \"sm\" | \"md\" | \"lg\";\n className?: string;\n /** Optional list of chains to show. Defaults to [SOLANA, ETHEREUM, BINANCE] when not provided. */\n candidates?: Chain[];\n onSwitchChain?: (chain: Chain) => Promise<void>;\n /** Called when switching chain succeeds; caller can toast / analytics here */\n onSuccess?: (chain: Chain) => void;\n /** Called when switching chain fails; caller can toast / modal / report here */\n onError?: (error: unknown) => void;\n};\n\nexport function ChainSelectWidget({\n size,\n className,\n candidates,\n onSwitchChain,\n onSuccess,\n onError,\n}: ChainSelectWidgetProps) {\n const { chain } = useCurrentChain();\n const { selectChain, isSwitching } = useSelectChain({\n onSwitchChain,\n onSuccess,\n onError,\n });\n\n return (\n <ChainSelectUI\n chain={chain}\n candidates={candidates}\n onSelectChain={selectChain}\n isSwitching={isSwitching}\n size={size}\n className={className}\n />\n );\n}\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@liberfi.io/ui-chain-select",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.26",
|
|
4
4
|
"description": "Chain Management for Liberfi React SDK",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"module": "dist/index.mjs",
|
|
@@ -14,29 +14,35 @@
|
|
|
14
14
|
"access": "public"
|
|
15
15
|
},
|
|
16
16
|
"dependencies": {
|
|
17
|
-
"@liberfi.io/types": "0.1.
|
|
18
|
-
"@liberfi.io/
|
|
19
|
-
"@liberfi.io/utils": "0.1.30"
|
|
17
|
+
"@liberfi.io/types": "0.1.35",
|
|
18
|
+
"@liberfi.io/utils": "0.1.32"
|
|
20
19
|
},
|
|
21
20
|
"devDependencies": {
|
|
21
|
+
"@testing-library/jest-dom": "^6.6.3",
|
|
22
|
+
"@testing-library/react": "^16.3.0",
|
|
22
23
|
"@types/node": "^24.5.0",
|
|
23
24
|
"@types/react": "^19.1.13",
|
|
24
25
|
"@types/react-dom": "^19.1.9",
|
|
26
|
+
"jest": "^29.7.0",
|
|
27
|
+
"jest-environment-jsdom": "^29.7.0",
|
|
25
28
|
"jotai": "^2.15.1",
|
|
26
29
|
"react": "^19.1.1",
|
|
27
30
|
"react-dom": "^19.1.1",
|
|
31
|
+
"ts-jest": "^29.3.0",
|
|
28
32
|
"tsup": "^8.5.0",
|
|
29
33
|
"typescript": "^5.9.2",
|
|
30
|
-
"
|
|
34
|
+
"@liberfi.io/ui": "0.1.35",
|
|
35
|
+
"tsconfig": "0.1.23"
|
|
31
36
|
},
|
|
32
37
|
"peerDependencies": {
|
|
33
38
|
"jotai": ">=2.15.1",
|
|
34
39
|
"react": ">=18",
|
|
35
|
-
"react-dom": ">=18"
|
|
40
|
+
"react-dom": ">=18",
|
|
41
|
+
"@liberfi.io/ui": "0.1.35"
|
|
36
42
|
},
|
|
37
43
|
"scripts": {
|
|
38
44
|
"dev": "tsup --watch",
|
|
39
45
|
"build": "tsup",
|
|
40
|
-
"test": "
|
|
46
|
+
"test": "jest"
|
|
41
47
|
}
|
|
42
48
|
}
|