@tuwaio/nova-core 0.6.0 → 0.7.1

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 CHANGED
@@ -1,31 +1,30 @@
1
1
  # @tuwaio/nova-core
2
2
 
3
3
  [![NPM Version](https://img.shields.io/npm/v/@tuwaio/nova-core.svg)](https://www.npmjs.com/package/@tuwaio/nova-core)
4
- [![License](https://img.shields.io/npm/l/@tuwaio/nova-core.svg)](./LICENSE)
4
+ [![License](https://img.shields.io/npm/l/@tuwaio/nova-core.svg)](https://github.com/TuwaIO/nova-uikit/blob/main/packages/nova-core/LICENSE)
5
5
 
6
- `@tuwaio/nova-core` is the **UI Core (L6)** package of the TUWA Ecosystem design system. It acts as the shared foundation for styling primitives, CSS variable definitions, base React elements, and helper utilities. Fully independent of Web3 logic, it provides the common design boundaries consumed by visual modules like `@tuwaio/nova-connect` and `@tuwaio/nova-transactions` to maintain visual consistency across all TUWA interfaces.
6
+ `@tuwaio/nova-core` is the core Layer 6 (L6) package of **Nova UI Kit**, the user interface project of TUWA Stage 4 ("User Interface"). It holds what the L7 packages [`@tuwaio/nova-connect`](https://stories.tuwa.io/?path=/docs/packages-nova-connect-overview--docs) and [`@tuwaio/nova-transactions`](https://stories.tuwa.io/?path=/docs/packages-nova-transactions-overview--docs) share: the `--tuwa-*` CSS variables of the theme, a dialog built on Radix UI, network and wallet icons, and small React hooks and helpers. It has no Web3 logic and no wallet or transaction state.
7
7
 
8
8
  ---
9
9
 
10
10
  ## 🏛️ Core Capabilities
11
11
 
12
- - **🎨 Design Token System:** Declares variables for colors, typography, borders, animations, and spacing, with built-in switching for light and dark modes.
13
- - **🛠️ Style Merger (`cn`):** An optimized composition utility blending `clsx` and `tailwind-merge` to resolve style overrides dynamically without class conflicts.
14
- - **⚡ Tailwind CSS v4 Native:** Configured to map variables into Tailwind's modern engine, allowing arbitrary class declarations.
15
- - **♿ Base Components & Primitives:** Shared layout modules, dialog nodes, overlays, and common utility indicators.
16
- - **📱 Shared React Hooks:** Reusable, performance-optimized hooks for clipboards (`useCopyToClipboard`) and responsive layouts (`useMediaQuery`).
12
+ - **Theme variables:** `dist/index.css` defines the `--tuwa-*` CSS variables (colors, borders, rounded corners, status colors) for the light theme on `:root` and for the dark theme on `.dark`, the Geist Mono font (embedded, no font request), the Tailwind CSS v4 utilities of the package, prefixed with `novacore:`, and a few global rules: `scrollbar-gutter: stable` on `html`, no page scrolling while a Nova dialog is open, and no padding and background on `react-toastify` toasts (`.Toastify__toast`), which the Nova toasts draw themselves. Every Nova component reads these variables, so overriding them restyles the whole kit.
13
+ - **Dialog:** `Dialog`, `DialogTrigger`, `DialogPortal`, `DialogClose` are the Radix UI primitives; `DialogOverlay`, `DialogContent`, `DialogHeader`, `DialogFooter`, `DialogTitle` and `DialogDescription` add the Nova styles and `framer-motion` animations. The connect and transaction modals of the L7 packages use them.
14
+ - **Icons:** `NetworkIcon` and `WalletIcon` render icons from `@web3icons/react` (loaded on demand), fetch missing ones from the web3icons repository on GitHub (`GithubFallbackIcon`) and show `FallbackIcon` otherwise; `NetworkIcon` recolors the icons of testnets and of the Solana devnet and testnet with `--tuwa-testnet-icons`. `SvgToImg` and `SvgImg` render an SVG as an `<img>`, so identical icons on one page do not share SVG `id`s. `CloseIcon`, `ChevronArrowWithAnim`, `ToastCloseButton` and `StarsBackground` are small shared parts.
15
+ - **Hooks and helpers:** `useCopyToClipboard` and `useMediaQuery`; `cn` (`clsx` + `tailwind-merge`), `deepMerge`, `getChainName`, `isSolanaDev`, `isTouchDevice`, `textCenterEllipsis`, the SVG helpers used by the icons and `standardButtonClasses`.
17
16
 
18
17
  ---
19
18
 
20
19
  ## 💾 Installation
21
20
 
22
21
  ```bash
23
- pnpm add @tuwaio/nova-core @radix-ui/react-dialog @web3icons/react @web3icons/common clsx framer-motion tailwind-merge react
22
+ pnpm add @tuwaio/nova-core react @radix-ui/react-dialog @web3icons/react @web3icons/common framer-motion clsx tailwind-merge
24
23
  ```
25
24
 
26
- ### CSS Setup
25
+ Peer dependencies: `react` (>=19.2.3), `@radix-ui/react-dialog` (1.x), `@web3icons/react` (>=4), `@web3icons/common` (>=0.11), `framer-motion`, `clsx` (2.x) and `tailwind-merge` (3.x).
27
26
 
28
- Import the core CSS styles into the entrypoint of your application (e.g., `main.css` or `globals.css`):
27
+ Import the stylesheet once, before the stylesheets of the other Nova packages:
29
28
 
30
29
  ```css
31
30
  @import '@tuwaio/nova-core/dist/index.css';
@@ -33,68 +32,38 @@ Import the core CSS styles into the entrypoint of your application (e.g., `main.
33
32
 
34
33
  ---
35
34
 
36
- ## 🚀 Usage Guide
35
+ ## 🚀 Usage
37
36
 
38
- ### 1. Tailwind Arbitrary Tokens
37
+ Most apps use `@tuwaio/nova-core` through Nova Connect and Nova Transactions and only override its CSS variables:
39
38
 
40
- Use Nova custom variables directly in components for consistent styling:
41
-
42
- ```tsx
43
- export function AccentCard() {
44
- return (
45
- <div className="p-6 bg-[var(--tuwa-bg-secondary)] border border-[var(--tuwa-border-primary)] rounded-[var(--tuwa-rounded-corners)]">
46
- <h3 className="text-[var(--tuwa-text-primary)] font-medium">Core Primitive Card</h3>
47
- <p className="mt-2 text-[var(--tuwa-text-secondary)] text-sm">Styled using central ecosystem design tokens.</p>
48
- <button className="mt-4 px-4 py-2 bg-[var(--tuwa-text-accent)] text-[var(--tuwa-text-on-accent)]">Action</button>
49
- </div>
50
- );
51
- }
52
- ```
53
-
54
- ### 2. Styling Composition (`cn`)
55
-
56
- Blend default styles with external prop overrides cleanly:
57
-
58
- ```tsx
59
- import { cn } from '@tuwaio/nova-core';
60
-
61
- interface ButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {
62
- variant?: 'primary' | 'secondary';
39
+ ```css
40
+ :root {
41
+ --tuwa-rounded-corners: 8px;
63
42
  }
64
43
 
65
- export function Button({ variant = 'primary', className, ...props }: ButtonProps) {
66
- return (
67
- <button
68
- className={cn(
69
- 'px-4 py-2 font-medium rounded transition-colors',
70
- variant === 'primary'
71
- ? 'bg-[var(--tuwa-text-accent)] text-[var(--tuwa-text-on-accent)]'
72
- : 'bg-[var(--tuwa-standart-button-bg)] text-[var(--tuwa-text-primary)] hover:bg-[var(--tuwa-standart-button-hover)]',
73
- className,
74
- )}
75
- {...props}
76
- />
77
- );
44
+ .dark {
45
+ --tuwa-bg-primary: #050505;
78
46
  }
79
47
  ```
80
48
 
81
- ### 3. Clipboard copy with `useCopyToClipboard`
82
-
83
- Easily build wallet address display nodes with copying feedback:
49
+ The variables and a full theme example are on the **[Theming](https://stories.tuwa.io/?path=/docs/theming--docs)** page. The components and helpers can also be used directly:
84
50
 
85
51
  ```tsx
86
- import { useCopyToClipboard } from '@tuwaio/nova-core';
52
+ import { cn, NetworkIcon, textCenterEllipsis, useCopyToClipboard } from '@tuwaio/nova-core';
87
53
 
88
- export function AddressDisplay({ address }: { address: string }) {
89
- const [copied, copy] = useCopyToClipboard();
54
+ export function AddressChip({ address, chainId }: { address: string; chainId: number }) {
55
+ const { isCopied, copy } = useCopyToClipboard();
90
56
 
91
57
  return (
92
58
  <button
59
+ type="button"
93
60
  onClick={() => copy(address)}
94
- className="font-mono text-xs text-[var(--tuwa-text-secondary)] hover:text-[var(--tuwa-text-accent)]"
61
+ className={cn('flex items-center gap-2', isCopied && 'opacity-70')}
95
62
  >
96
- {address.slice(0, 6)}...{address.slice(-4)}
97
- {copied ? ' (Copied ✓)' : ' (Copy)'}
63
+ <span className="h-4 w-4">
64
+ <NetworkIcon chainId={chainId} />
65
+ </span>
66
+ {isCopied ? 'Copied' : textCenterEllipsis(address, 6, 4)}
98
67
  </button>
99
68
  );
100
69
  }
@@ -102,40 +71,20 @@ export function AddressDisplay({ address }: { address: string }) {
102
71
 
103
72
  ---
104
73
 
105
- ## 🎨 Theme Customization
74
+ ## 🌐 External Services
106
75
 
107
- Override default tokens in your global CSS stylesheet to match your brand:
108
-
109
- ```css
110
- :root {
111
- /* Customize Brand Accent Colors */
112
- --tuwa-text-accent: #10b981; /* Emerald-500 */
113
- --tuwa-text-on-accent: #ffffff;
114
- --tuwa-rounded-corners: 8px;
115
- }
76
+ | Helper | Host | Purpose |
77
+ | ---------------------------------------------------------- | --------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------- |
78
+ | `GithubFallbackIcon` (used by `NetworkIcon`, `WalletIcon`) | `raw.githubusercontent.com` (the `0xa3k5/web3icons` repository) | SVG of a network or wallet that the installed `@web3icons/common` does not list. The SVGs are cached in memory until the page reloads. |
116
79
 
117
- /* Customize Dark Mode styling */
118
- .dark {
119
- --tuwa-bg-primary: #050505;
120
- --tuwa-bg-secondary: #121212;
121
- --tuwa-border-primary: #222222;
122
- }
123
- ```
80
+ The other icons come from the installed `@web3icons/react`, and the font is embedded in the stylesheet. The package does not use `localStorage`.
124
81
 
125
82
  ---
126
83
 
127
- ## 🔧 API & Module Architecture
128
-
129
- `@tuwaio/nova-core` exports the following modules and functions:
84
+ ## 📚 API Reference
130
85
 
131
- - **Style Composition:** `cn`.
132
- - **React Hooks:** `useCopyToClipboard`, `useMediaQuery`.
133
- - **UI Dialog Primitives:** `Dialog`, `DialogOverlay`, `DialogContent`, `DialogHeader`, `DialogTitle`, `DialogDescription`, `DialogFooter`.
134
- - **Utility Indicators:** `StarsBackground`, `FallbackIcon`, `GithubFallbackIcon`, `ChevronArrowWithAnim`, `ToastCloseButton`, `ToastValidationError`, `NetworkIcon`, `WalletIcon`.
135
- - **Formatters:** `deepMerge`, `svgToBase64`, `isTouchDevice`, `textCenterEllipsis`, `resolveCssVariable`.
136
-
137
- ---
86
+ Every export, with signatures and types generated from the source, is documented at **[stories.tuwa.io → Packages → nova-core](https://stories.tuwa.io/?path=/docs/packages-nova-core-overview--docs)**.
138
87
 
139
88
  ## 📄 License
140
89
 
141
- Licensed under the **Apache-2.0 License**. See the [LICENSE](./LICENSE) file for details.
90
+ Licensed under the **Apache-2.0 License**. See the [LICENSE](https://github.com/TuwaIO/nova-uikit/blob/main/packages/nova-core/LICENSE) file for details.
package/dist/index.cjs CHANGED
@@ -1,4 +1,4 @@
1
- 'use strict';var framerMotion=require('framer-motion'),clsx=require('clsx'),tailwindMerge=require('tailwind-merge'),metadata=require('@web3icons/common/metadata'),jsxRuntime=require('react/jsx-runtime'),d=require('react'),c=require('@radix-ui/react-dialog');function _interopNamespace(e){if(e&&e.__esModule)return e;var n=Object.create(null);if(e){Object.keys(e).forEach(function(k){if(k!=='default'){var d=Object.getOwnPropertyDescriptor(e,k);Object.defineProperty(n,k,d.get?d:{enumerable:true,get:function(){return e[k]}});}})}n.default=e;return Object.freeze(n)}var d__namespace=/*#__PURE__*/_interopNamespace(d);var c__namespace=/*#__PURE__*/_interopNamespace(c);var _o="novacore:cursor-pointer novacore:rounded-[var(--tuwa-rounded-corners)] novacore:bg-[var(--tuwa-standart-button-bg)] novacore:px-3 novacore:py-2 novacore:flex novacore:items-center novacore:gap-1 novacore:text-sm novacore:font-mono novacore:font-semibold novacore:text-[var(--tuwa-text-primary)] novacore:transition-colors novacore:hover:bg-[var(--tuwa-standart-button-hover)] novacore:disabled:cursor-not-allowed novacore:disabled:opacity-50 novacore:min-h-[36px]";function s(...o){return tailwindMerge.twMerge(clsx.clsx(o))}var y=o=>typeof o=="object"&&o!==null&&!Array.isArray(o);function J(o,e){let t={...o};return y(o)&&y(e)&&Object.keys(e).forEach(n=>{let r=o[n],a=e[n];y(r)&&y(a)?t[n]=J(r,a):t[n]=a;}),t}function x(o){if(typeof o!="string")return false;let e=o.toLowerCase();return e.includes("solana")&&(e.includes("devnet")||e.includes("testnet"))}var M="Unknown";function oo(o){return o.charAt(0).toUpperCase()+o.slice(1).toLowerCase()}function W(o){let e={name:M,id:M.toLowerCase(),filePath:M.toLowerCase(),chainId:o};if(typeof o=="number"){let i=metadata.networks.find(l=>l.chainId===o);return i?{name:i.name,id:i.id,filePath:i.filePath?.split(":")[1],chainId:o}:e}let[t,n]=o?o.split(":"):[o],r=metadata.networks.find(i=>i.id===t);return r?{name:n&&x(o)?`${r.name} ${oo(n)}`:r.name,id:r.id,filePath:r.filePath?.split(":")[1],chainId:o}:e}function G(o=1200){if(typeof window>"u")return false;let e="ontouchstart"in window,t=navigator.maxTouchPoints>0,n=false;window.matchMedia&&(n=window.matchMedia("(pointer: coarse)").matches);let r=e||t||n,a=window.innerWidth<=o;return r&&a}function eo(o){if(!o.startsWith("var("))return o;let e=o.match(/var\(\s*(--[\w-]+)/);if(!e)return o;let t=e[1];return getComputedStyle(document.documentElement).getPropertyValue(t).trim()||o}function to(o,e){let t=eo(e),r=new DOMParser().parseFromString(o,"image/svg+xml");if(r.querySelector("parsererror"))return console.warn("SVG parse error, returning original"),o;let i=r.querySelector("path");return i&&i.setAttribute("fill",t),new XMLSerializer().serializeToString(r.documentElement)}function N(o,e){let t=o;return e&&(t=to(t,e)),`data:image/svg+xml;base64,${btoa(unescape(encodeURIComponent(t)))}`}var S=o=>`${o.replace(/\s+/g,"-").toLowerCase()}.svg`;function te(o,e,t){if(!o)return "";if(o.length<=e+t)return o;let n=o.slice(0,e),r=o.slice(o.length-t);return `${n}...${r}`}function ve({className:o,strokeWidth:e,isOpen:t}){return jsxRuntime.jsxs("svg",{xmlns:"http://www.w3.org/2000/svg",fill:"none",viewBox:"0 0 24 24",strokeWidth:e??2,stroke:"currentColor",className:s("novacore:w-4 novacore:h-4 novacore:text-[var(--tuwa-text-secondary)]",o),children:[jsxRuntime.jsx(framerMotion.AnimatePresence,{children:t&&jsxRuntime.jsx(framerMotion.motion.path,{strokeLinecap:"round",strokeLinejoin:"round",d:"m4.5 15.75 7.5-7.5 7.5 7.5",variants:{hidden:{translateY:3,scaleY:.8,opacity:0},visible:{translateY:0,scaleY:1,opacity:1}},initial:"hidden",animate:"visible",transition:{duration:.4}})}),jsxRuntime.jsx(framerMotion.AnimatePresence,{children:!t&&jsxRuntime.jsx(framerMotion.motion.path,{strokeLinecap:"round",strokeLinejoin:"round",d:"m19.5 8.25-7.5 7.5-7.5-7.5",className:"novacore:relative",variants:{hidden:{translateY:-3,scaleY:.8,opacity:0},visible:{translateY:0,scaleY:1,opacity:1}},initial:"hidden",animate:"visible",transition:{duration:.4}})})]})}var no=d__namespace.forwardRef(({className:o,...e},t)=>jsxRuntime.jsxs("svg",{ref:t,xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round",className:s("novacore:h-5 novacore:w-5 novacore:text-[var(--tuwa-text-primary)] novacore:transition-colors",o),...e,children:[jsxRuntime.jsx("path",{d:"M18 6 6 18"}),jsxRuntime.jsx("path",{d:"m6 6 12 12"})]}));no.displayName="CloseIcon";var io="novacore:flex novacore:items-center novacore:justify-center novacore:w-full novacore:h-full novacore:rounded-full novacore:text-[var(--tuwa-text-secondary)] novacore:bg-[var(--tuwa-bg-muted)]",p=({animate:o=false,content:e="",className:t})=>jsxRuntime.jsx("div",{className:s(io,"Nova_Web3_Icon",t,{"novacore:animate-pulse":o}),children:e});function C({src:o,alt:e,...t}){return jsxRuntime.jsx("img",{...t,src:o,alt:e??"",draggable:false,onDragStart:n=>n.preventDefault(),style:{outline:"none",pointerEvents:"none"}})}var mo="https://raw.githubusercontent.com/0xa3k5/web3icons/refs/heads/main/raw-svgs",L=new Map;function P({githubSrc:o,className:e,alt:t,firstPathFill:n,...r}){let a=`${o}|${n??""}`,i=L.get(a),[l,u]=d.useState(null),[w,b]=d.useState("idle"),T=i||l,g=i?"success":w;return d.useEffect(()=>{let D=true;return L.has(a)?void 0:((async()=>{b("loading");try{let R=await fetch(`${mo}/${o}`);if(!R.ok)throw new Error(`Failed to load icon: ${R.status}`);let X=await R.text();if(D){let V=N(X,n);L.set(a,V),u(V),b("success");}}catch{D&&b("error");}})(),()=>{D=false;})},[o,n,a]),g==="loading"||g==="idle"?jsxRuntime.jsx(p,{animate:true,className:e}):g==="success"&&T?jsxRuntime.jsx(C,{...r,src:T,alt:t,className:e}):jsxRuntime.jsx(p,{content:"?",className:e})}var Ve=c__namespace.Root,ze=c__namespace.Trigger,uo=c__namespace.Portal,We=c__namespace.Close,fo={initial:{opacity:0,scale:.9,y:20},animate:{opacity:1,scale:1,y:0},exit:{opacity:0,scale:.9,transition:{duration:.2}}},po={initial:{opacity:0,y:"100%"},animate:{opacity:1,y:"0%"},exit:{opacity:0,y:"100%",transition:{duration:.2}}},vo={initial:{opacity:0},animate:{opacity:1},exit:{opacity:0}},Y=({className:o,backdropAnimation:e})=>(d__namespace.useEffect(()=>(typeof window<"u"&&window.document.body.classList.add("NovaModalOpen"),()=>{typeof window<"u"&&window.document.body.classList.remove("NovaModalOpen");}),[]),jsxRuntime.jsx(framerMotion.AnimatePresence,{children:jsxRuntime.jsx(framerMotion.motion.div,{variants:e??vo,transition:{duration:.2,ease:"easeInOut"},animate:"animate",initial:"initial",exit:"exit",className:"novacore:relative novacore:overflow-hidden",children:jsxRuntime.jsx("div",{className:s("novacore:fixed novacore:inset-0 novacore:z-50 novacore:bg-black/55 novacore:backdrop-blur-sm novacore:backdrop-saturate-150",o)})})}));Y.displayName=c__namespace.Overlay.displayName;var go=d__namespace.forwardRef(({className:o,children:e,modalAnimation:t,backdropAnimation:n,...r},a)=>{let[i,l]=d__namespace.useState(false);d__namespace.useEffect(()=>{l(G());},[]);let u=t??(i?po:fo);return jsxRuntime.jsxs(uo,{children:[jsxRuntime.jsx(Y,{backdropAnimation:n}),jsxRuntime.jsx(c__namespace.Content,{"aria-describedby":"tuwa:modal-content",ref:a,className:s("NovaNoScrolling novacore:fixed novacore:bottom-0 novacore:left-0 novacore:p-0 novacore:sm:bottom-auto novacore:sm:left-[50%] novacore:sm:top-[50%] novacore:sm:translate-x-[-50%] novacore:sm:translate-y-[-50%] novacore:z-50 novacore:sm:p-4 novacore:outline-none",o),...r,children:jsxRuntime.jsx(framerMotion.motion.div,{layout:true,className:"NovaNoScrolling novacore:relative novacore:overflow-hidden",transition:{layout:{duration:.2,ease:[.1,.1,.2,1]}},children:jsxRuntime.jsx(framerMotion.AnimatePresence,{children:jsxRuntime.jsx(framerMotion.motion.div,{variants:u,transition:{duration:.2,ease:"easeInOut"},animate:"animate",initial:"initial",exit:"exit",className:"NovaNoScrolling novacore:relative novacore:overflow-hidden novacore:bg-[var(--tuwa-bg-primary)] novacore:border novacore:border-[var(--tuwa-border-primary)] novacore:rounded-t-[var(--tuwa-rounded-corners)] novacore:sm:rounded-[var(--tuwa-rounded-corners)]",children:jsxRuntime.jsx("div",{className:s("NovaNoScrolling NovaDialogContent__elements novacore:relative novacore:flex novacore:max-h-[100dvh] novacore:w-full novacore:flex-col novacore:overflow-y-auto","novacore:[transform:translateZ(0)] novacore:[backface-visibility:hidden]"),children:e})})})})})]})});go.displayName=c__namespace.Content.displayName;var wo=({className:o,...e})=>jsxRuntime.jsx("div",{"aria-describedby":"tuwa:modal-header",className:s("novacore:sticky novacore:flex novacore:top-0 novacore:z-11 novacore:w-full novacore:flex-row novacore:items-center novacore:justify-between","novacore:border-b novacore:border-[var(--tuwa-border-primary)] novacore:bg-[var(--tuwa-bg-primary)] novacore:p-4",o),...e});wo.displayName="DialogHeader";var bo=({className:o,...e})=>jsxRuntime.jsx("div",{"aria-describedby":"tuwa:modal-footer",className:s("novacore:flex novacore:flex-col-reverse novacore:sm:flex-row novacore:sm:justify-end novacore:sm:space-x-2",o),...e});bo.displayName="DialogFooter";var ho=d__namespace.forwardRef(({className:o,...e},t)=>jsxRuntime.jsx(c__namespace.Title,{ref:t,"aria-describedby":"tuwa:modal-title",className:s("novacore:text-lg novacore:font-bold novacore:leading-none novacore:tracking-tight novacore:text-[var(--tuwa-text-primary)] novacore:m-0 novacore:font-mono",o),...e}));ho.displayName=c__namespace.Title.displayName;var yo=d__namespace.forwardRef(({className:o,...e},t)=>jsxRuntime.jsx(c__namespace.Description,{"aria-describedby":"tuwa:modal-description",ref:t,className:s("novacore:text-sm novacore:text-[var(--tuwa-text-secondary)]",o),...e}));yo.displayName=c__namespace.Description.displayName;function h({children:o,iconId:e,alt:t,firstPathFill:n,...r}){let[a,i]=d.useState(null),l=d.useCallback(u=>{if(u){let w=N(u.outerHTML,n);i({id:e,src:w});}},[e,n]);return a&&a.id===e?jsxRuntime.jsx(C,{...r,src:a.src,alt:t}):jsxRuntime.jsx(jsxRuntime.Fragment,{children:o(l)})}var K=d.lazy(()=>import('@web3icons/react/dynamic').then(o=>({default:o.NetworkIcon}))),Io="var(--tuwa-testnet-icons)";function Je({chainId:o,variant:e="background",className:t}){let n=W(o),r=typeof o=="string",a=r?o.split(":")[0].toLowerCase():o,l=r&&x(o)||n.name.toLowerCase().includes("testnet")?Io:void 0,u=s("novacore:w-full novacore:h-full novacore:rounded-full",t),w=typeof a=="string"?a:n.filePath,b=`networks/${e}/${S(w)}`;return n.name==="Unknown"?typeof o=="number"?jsxRuntime.jsx(p,{content:"?",className:t}):jsxRuntime.jsx(P,{githubSrc:b,className:u,firstPathFill:l}):jsxRuntime.jsx(d.Suspense,{fallback:jsxRuntime.jsx(p,{animate:true,className:t}),children:jsxRuntime.jsx(h,{iconId:`${o}-${e}`,className:u,firstPathFill:l,children:g=>typeof a=="string"?jsxRuntime.jsx(K,{ref:g,id:a,variant:e}):jsxRuntime.jsx(K,{ref:g,chainId:a,variant:e})})})}function rt({starsCount:o}){let[e,t]=d.useState(false);d.useEffect(()=>t(true),[]);let n=d.useMemo(()=>e?Array.from({length:o??200}).map(()=>({x:Math.random()*window.innerWidth,y:Math.random()*window.innerHeight,r:Math.random()*1+.5,isSupernova:Math.random()<.1,delay:Math.random()*10,duration:5+Math.random()*5})):[],[e]);return jsxRuntime.jsx("div",{className:"novacore:absolute novacore:inset-0 novacore:z-1 novacore:h-full novacore:w-full novacore:overflow-hidden",children:jsxRuntime.jsxs("svg",{width:"100%",height:"100%",xmlns:"http://www.w3.org/2000/svg",children:[jsxRuntime.jsx("defs",{children:jsxRuntime.jsx("style",{children:`
1
+ 'use strict';var framerMotion=require('framer-motion'),clsx=require('clsx'),tailwindMerge=require('tailwind-merge'),metadata=require('@web3icons/common/metadata'),jsxRuntime=require('react/jsx-runtime'),d=require('react'),c=require('@radix-ui/react-dialog');function _interopNamespace(e){if(e&&e.__esModule)return e;var n=Object.create(null);if(e){Object.keys(e).forEach(function(k){if(k!=='default'){var d=Object.getOwnPropertyDescriptor(e,k);Object.defineProperty(n,k,d.get?d:{enumerable:true,get:function(){return e[k]}});}})}n.default=e;return Object.freeze(n)}var d__namespace=/*#__PURE__*/_interopNamespace(d);var c__namespace=/*#__PURE__*/_interopNamespace(c);var Uo="novacore:cursor-pointer novacore:rounded-[var(--tuwa-rounded-corners)] novacore:bg-[var(--tuwa-standart-button-bg)] novacore:px-3 novacore:py-2 novacore:flex novacore:items-center novacore:gap-1 novacore:text-sm novacore:font-mono novacore:font-semibold novacore:text-[var(--tuwa-text-primary)] novacore:transition-colors novacore:hover:bg-[var(--tuwa-standart-button-hover)] novacore:disabled:cursor-not-allowed novacore:disabled:opacity-50 novacore:min-h-[36px]";function s(...o){return tailwindMerge.twMerge(clsx.clsx(o))}var y=o=>typeof o=="object"&&o!==null&&!Array.isArray(o);function J(o,e){let t={...o};return y(o)&&y(e)&&Object.keys(e).forEach(n=>{let r=o[n],a=e[n];y(r)&&y(a)?t[n]=J(r,a):t[n]=a;}),t}function x(o){if(typeof o!="string")return false;let e=o.toLowerCase();return e.includes("solana")&&(e.includes("devnet")||e.includes("testnet"))}var M="Unknown";function oo(o){return o.charAt(0).toUpperCase()+o.slice(1).toLowerCase()}function W(o){let e={name:M,id:M.toLowerCase(),filePath:M.toLowerCase(),chainId:o};if(typeof o=="number"){let i=metadata.networks.find(l=>l.chainId===o);return i?{name:i.name,id:i.id,filePath:i.filePath?.split(":")[1],chainId:o}:e}let[t,n]=o?o.split(":"):[o],r=metadata.networks.find(i=>i.id===t);return r?{name:n&&x(o)?`${r.name} ${oo(n)}`:r.name,id:r.id,filePath:r.filePath?.split(":")[1],chainId:o}:e}function G(o=1200){if(typeof window>"u")return false;let e="ontouchstart"in window,t=navigator.maxTouchPoints>0,n=false;window.matchMedia&&(n=window.matchMedia("(pointer: coarse)").matches);let r=e||t||n,a=window.innerWidth<=o;return r&&a}function eo(o){if(!o.startsWith("var("))return o;let e=o.match(/var\(\s*(--[\w-]+)/);if(!e)return o;let t=e[1];return getComputedStyle(document.documentElement).getPropertyValue(t).trim()||o}function to(o,e){let t=eo(e),r=new DOMParser().parseFromString(o,"image/svg+xml");if(r.querySelector("parsererror"))return console.warn("SVG parse error, returning original"),o;let i=r.querySelector("path");return i&&i.setAttribute("fill",t),new XMLSerializer().serializeToString(r.documentElement)}function N(o,e){let t=o;return e&&(t=to(t,e)),`data:image/svg+xml;base64,${btoa(unescape(encodeURIComponent(t)))}`}var C=o=>`${o.replace(/\s+/g,"-").toLowerCase()}.svg`;function te(o,e,t){if(!o)return "";if(o.length<=e+t)return o;let n=o.slice(0,e),r=o.slice(o.length-t);return `${n}...${r}`}function ve({className:o,strokeWidth:e,isOpen:t}){return jsxRuntime.jsxs("svg",{xmlns:"http://www.w3.org/2000/svg",fill:"none",viewBox:"0 0 24 24",strokeWidth:e??2,stroke:"currentColor",className:s("novacore:w-4 novacore:h-4 novacore:text-[var(--tuwa-text-secondary)]",o),children:[jsxRuntime.jsx(framerMotion.AnimatePresence,{children:t&&jsxRuntime.jsx(framerMotion.motion.path,{strokeLinecap:"round",strokeLinejoin:"round",d:"m4.5 15.75 7.5-7.5 7.5 7.5",variants:{hidden:{translateY:3,scaleY:.8,opacity:0},visible:{translateY:0,scaleY:1,opacity:1}},initial:"hidden",animate:"visible",transition:{duration:.4}})}),jsxRuntime.jsx(framerMotion.AnimatePresence,{children:!t&&jsxRuntime.jsx(framerMotion.motion.path,{strokeLinecap:"round",strokeLinejoin:"round",d:"m19.5 8.25-7.5 7.5-7.5-7.5",className:"novacore:relative",variants:{hidden:{translateY:-3,scaleY:.8,opacity:0},visible:{translateY:0,scaleY:1,opacity:1}},initial:"hidden",animate:"visible",transition:{duration:.4}})})]})}var no=d__namespace.forwardRef(({className:o,...e},t)=>jsxRuntime.jsxs("svg",{ref:t,xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round",className:s("novacore:h-5 novacore:w-5 novacore:text-[var(--tuwa-text-primary)] novacore:transition-colors",o),...e,children:[jsxRuntime.jsx("path",{d:"M18 6 6 18"}),jsxRuntime.jsx("path",{d:"m6 6 12 12"})]}));no.displayName="CloseIcon";var io="novacore:flex novacore:items-center novacore:justify-center novacore:w-full novacore:h-full novacore:rounded-full novacore:text-[var(--tuwa-text-secondary)] novacore:bg-[var(--tuwa-bg-muted)]",f=({animate:o=false,content:e="",className:t})=>jsxRuntime.jsx("div",{className:s(io,"Nova_Web3_Icon",t,{"novacore:animate-pulse":o}),children:e});function k({src:o,alt:e,...t}){return jsxRuntime.jsx("img",{...t,src:o,alt:e??"",draggable:false,onDragStart:n=>n.preventDefault(),style:{outline:"none",pointerEvents:"none"}})}var mo="https://raw.githubusercontent.com/0xa3k5/web3icons/refs/heads/main/raw-svgs",L=new Map;function P({githubSrc:o,className:e,alt:t,firstPathFill:n,...r}){let a=`${o}|${n??""}`,i=L.get(a),[l,m]=d.useState(null),[w,b]=d.useState("idle"),I=i||l,g=i?"success":w;return d.useEffect(()=>{let R=true;return L.has(a)?void 0:((async()=>{b("loading");try{let D=await fetch(`${mo}/${o}`);if(!D.ok)throw new Error(`Failed to load icon: ${D.status}`);let X=await D.text();if(R){let V=N(X,n);L.set(a,V),m(V),b("success");}}catch{R&&b("error");}})(),()=>{R=false;})},[o,n,a]),g==="loading"||g==="idle"?jsxRuntime.jsx(f,{animate:true,className:e}):g==="success"&&I?jsxRuntime.jsx(k,{...r,src:I,alt:t,className:e}):jsxRuntime.jsx(f,{content:"?",className:e})}var Ve=c__namespace.Root,ze=c__namespace.Trigger,uo=c__namespace.Portal,We=c__namespace.Close,po={initial:{opacity:0,scale:.9,y:20},animate:{opacity:1,scale:1,y:0},exit:{opacity:0,scale:.9,transition:{duration:.2}}},fo={initial:{opacity:0,y:"100%"},animate:{opacity:1,y:"0%"},exit:{opacity:0,y:"100%",transition:{duration:.2}}},vo={initial:{opacity:0},animate:{opacity:1},exit:{opacity:0}},Y=({className:o,backdropAnimation:e})=>(d__namespace.useEffect(()=>(typeof window<"u"&&window.document.body.classList.add("NovaModalOpen"),()=>{typeof window<"u"&&window.document.body.classList.remove("NovaModalOpen");}),[]),jsxRuntime.jsx(framerMotion.AnimatePresence,{children:jsxRuntime.jsx(framerMotion.motion.div,{variants:e??vo,transition:{duration:.2,ease:"easeInOut"},animate:"animate",initial:"initial",exit:"exit",className:"novacore:relative novacore:overflow-hidden",children:jsxRuntime.jsx("div",{className:s("novacore:fixed novacore:inset-0 novacore:z-50 novacore:bg-black/55 novacore:backdrop-blur-sm novacore:backdrop-saturate-150",o)})})}));Y.displayName=c__namespace.Overlay.displayName;var go=d__namespace.forwardRef(({className:o,children:e,modalAnimation:t,backdropAnimation:n,...r},a)=>{let[i,l]=d__namespace.useState(false);d__namespace.useEffect(()=>{l(G());},[]);let m=t??(i?fo:po);return jsxRuntime.jsxs(uo,{children:[jsxRuntime.jsx(Y,{backdropAnimation:n}),jsxRuntime.jsx(c__namespace.Content,{"aria-describedby":"tuwa:modal-content",ref:a,className:s("NovaNoScrolling novacore:fixed novacore:bottom-0 novacore:left-0 novacore:p-0 novacore:sm:bottom-auto novacore:sm:left-[50%] novacore:sm:top-[50%] novacore:sm:translate-x-[-50%] novacore:sm:translate-y-[-50%] novacore:z-50 novacore:sm:p-4 novacore:outline-none",o),...r,children:jsxRuntime.jsx(framerMotion.motion.div,{layout:true,className:"NovaNoScrolling novacore:relative novacore:overflow-hidden",transition:{layout:{duration:.2,ease:[.1,.1,.2,1]}},children:jsxRuntime.jsx(framerMotion.AnimatePresence,{children:jsxRuntime.jsx(framerMotion.motion.div,{variants:m,transition:{duration:.2,ease:"easeInOut"},animate:"animate",initial:"initial",exit:"exit",className:"NovaNoScrolling novacore:relative novacore:overflow-hidden novacore:bg-[var(--tuwa-bg-primary)] novacore:border novacore:border-[var(--tuwa-border-primary)] novacore:rounded-t-[var(--tuwa-rounded-corners)] novacore:sm:rounded-[var(--tuwa-rounded-corners)]",children:jsxRuntime.jsx("div",{className:s("NovaNoScrolling NovaDialogContent__elements novacore:relative novacore:flex novacore:max-h-[100dvh] novacore:w-full novacore:flex-col novacore:overflow-y-auto","novacore:[transform:translateZ(0)] novacore:[backface-visibility:hidden]"),children:e})})})})})]})});go.displayName=c__namespace.Content.displayName;var wo=({className:o,...e})=>jsxRuntime.jsx("div",{"aria-describedby":"tuwa:modal-header",className:s("novacore:sticky novacore:flex novacore:top-0 novacore:z-11 novacore:w-full novacore:flex-row novacore:items-center novacore:justify-between","novacore:border-b novacore:border-[var(--tuwa-border-primary)] novacore:bg-[var(--tuwa-bg-primary)] novacore:p-4",o),...e});wo.displayName="DialogHeader";var bo=({className:o,...e})=>jsxRuntime.jsx("div",{"aria-describedby":"tuwa:modal-footer",className:s("novacore:flex novacore:flex-col-reverse novacore:sm:flex-row novacore:sm:justify-end novacore:sm:space-x-2",o),...e});bo.displayName="DialogFooter";var ho=d__namespace.forwardRef(({className:o,...e},t)=>jsxRuntime.jsx(c__namespace.Title,{ref:t,"aria-describedby":"tuwa:modal-title",className:s("novacore:text-lg novacore:font-bold novacore:leading-none novacore:tracking-tight novacore:text-[var(--tuwa-text-primary)] novacore:m-0 novacore:font-mono",o),...e}));ho.displayName=c__namespace.Title.displayName;var yo=d__namespace.forwardRef(({className:o,...e},t)=>jsxRuntime.jsx(c__namespace.Description,{"aria-describedby":"tuwa:modal-description",ref:t,className:s("novacore:text-sm novacore:text-[var(--tuwa-text-secondary)]",o),...e}));yo.displayName=c__namespace.Description.displayName;function h({children:o,iconId:e,alt:t,firstPathFill:n,...r}){let[a,i]=d.useState(null),l=d.useCallback(m=>{if(m){let w=N(m.outerHTML,n);i({id:e,src:w});}},[e,n]);return a&&a.id===e?jsxRuntime.jsx(k,{...r,src:a.src,alt:t}):jsxRuntime.jsx(jsxRuntime.Fragment,{children:o(l)})}var K=d.lazy(()=>import('@web3icons/react/dynamic').then(o=>({default:o.NetworkIcon}))),To="var(--tuwa-testnet-icons)";function Je({chainId:o,variant:e="background",className:t}){let n=W(o),r=typeof o=="string",a=r?o.split(":")[0].toLowerCase():o,l=r&&x(o)||n.name.toLowerCase().includes("testnet")?To:void 0,m=s("novacore:w-full novacore:h-full novacore:rounded-full",t),w=typeof a=="string"?a:n.filePath,b=`networks/${e}/${C(w)}`;return n.name==="Unknown"?typeof o=="number"?jsxRuntime.jsx(f,{content:"?",className:t}):jsxRuntime.jsx(P,{githubSrc:b,className:m,firstPathFill:l}):jsxRuntime.jsx(d.Suspense,{fallback:jsxRuntime.jsx(f,{animate:true,className:t}),children:jsxRuntime.jsx(h,{iconId:`${o}-${e}`,className:m,firstPathFill:l,children:g=>typeof a=="string"?jsxRuntime.jsx(K,{ref:g,id:a,variant:e}):jsxRuntime.jsx(K,{ref:g,chainId:a,variant:e})})})}function rt({starsCount:o}){let[e,t]=d.useState(false);d.useEffect(()=>t(true),[]);let n=d.useMemo(()=>e?Array.from({length:o??200}).map(()=>({x:Math.random()*window.innerWidth,y:Math.random()*window.innerHeight,r:Math.random()*1+.5,isSupernova:Math.random()<.1,delay:Math.random()*10,duration:5+Math.random()*5})):[],[e]);return jsxRuntime.jsx("div",{className:"novacore:absolute novacore:inset-0 novacore:z-1 novacore:h-full novacore:w-full novacore:overflow-hidden",children:jsxRuntime.jsxs("svg",{width:"100%",height:"100%",xmlns:"http://www.w3.org/2000/svg",children:[jsxRuntime.jsx("defs",{children:jsxRuntime.jsx("style",{children:`
2
2
  /* Pulse animation now includes scale for a more organic feel. */
3
3
  @keyframes pulse {
4
4
  0%, 100% {
@@ -44,5 +44,5 @@
44
44
  transform-origin: center;
45
45
  stroke-width: 2;
46
46
  }
47
- `})}),n.map((r,a)=>jsxRuntime.jsx("circle",{cx:r.x,cy:r.y,r:r.r,fill:"rgba(var(--tuwa-bg-primary), 0.7)",className:r.isSupernova?"supernova":"pulsar",style:{animationDelay:`${r.delay}s`,animationDuration:`${r.duration}s`}},a))]})})}function st({closeToast:o,ariaLabel:e="Close toast notification",title:t="Close toast notification",className:n,iconClassName:r}){return jsxRuntime.jsx("button",{type:"button",onClick:o,"aria-label":e,title:t,className:s("novacore:absolute novacore:top-2 novacore:right-2 novacore:cursor-pointer novacore:rounded-[var(--tuwa-rounded-corners)] novacore:p-1","novacore:text-[var(--tuwa-text-tertiary)] novacore:transition-colors","novacore:hover:bg-[var(--tuwa-bg-muted)] novacore:hover:text-[var(--tuwa-text-primary)]",n),children:jsxRuntime.jsx("svg",{xmlns:"http://www.w3.org/2000/svg",fill:"none",viewBox:"0 0 24 24",strokeWidth:1.5,stroke:"currentColor",className:s("novacore:h-5 novacore:w-5",r),children:jsxRuntime.jsx("path",{strokeLinecap:"round",strokeLinejoin:"round",d:"M6 18 18 6M6 6l12 12"})})})}var Fo=d.lazy(()=>import('@web3icons/react/dynamic').then(o=>({default:o.WalletIcon}))),Vo={walletconnect:"wallet-connect"};function zo(o){return metadata.wallets.some(e=>e.id===o||e.name?.toLowerCase()===o)}var Wo=({className:o,ref:e})=>jsxRuntime.jsxs("svg",{ref:e,className:o,fill:"none",viewBox:"0 0 32 32",xmlns:"http://www.w3.org/2000/svg",children:[jsxRuntime.jsx("path",{fill:"#fff",fillRule:"evenodd",d:"M16 0c8.84 0 16 7.16 16 16s-7.16 16-16 16S0 24.84 0 16 7.16 0 16 0",clipRule:"evenodd"}),jsxRuntime.jsx("path",{fill:"#000",fillRule:"evenodd",d:"M16.54 2.01h1.53c.5.09.99.23 1.48.42.21.25.19.48-.05.69q-.195.045-.39 0c-1.86-.65-3.55-.35-5.07.89 2.39.7 3.84 2.27 4.36 4.7.12.85.08 1.68-.12 2.51.87 0 1.74 0 2.61-.02.39-.4.7-.85.94-1.35-.45-.45-.65-.99-.59-1.63-1.15.08-1.79-.44-1.92-1.58.14-1.12.78-1.67 1.92-1.63a.7.7 0 0 0-.12-.49l-.89-.89c-.02-.45.19-.6.62-.47.24.19.46.39.66.62.71-.79 1.5-.89 2.39-.32.44.42.62.94.54 1.55 1.49.02 2.11.76 1.85 2.22-.08.17-.17.34-.27.49.53.59.87 1.28 1.01 2.07.08 4.6.1 9.19.05 13.79-.19 1.58-1 2.71-2.44 3.37-.29.1-.59.2-.89.27H7.2c-1.31-.33-2.05-1.17-2.24-2.51-.03-5.24-.03-10.47 0-15.71.3-1.62 1.28-2.46 2.93-2.54 1.26-1.77 2.98-2.64 5.17-2.61.96-1.01 2.13-1.62 3.5-1.85zm6.11 1.87c.39-.03.7.12.91.44.06.39.09.79.1 1.18.02.12.07.21.17.27.41 0 .82.04 1.23.1.49.26.63.65.42 1.16-.07.14-.18.25-.32.32-.39.06-.79.09-1.18.1-.12.02-.21.07-.27.17l-.15 1.33c-.32.46-.72.55-1.21.27a.76.76 0 0 1-.27-.37c-.06-.41-.09-.82-.1-1.23a.35.35 0 0 0-.27-.17l-1.08-.05c-.46-.24-.62-.61-.47-1.11.14-.27.36-.43.66-.47l.99-.05s.09-.04.12-.07l.15-1.28q.18-.39.57-.54m-10.49.79c2.41-.09 4.12.94 5.15 3.1.44 1.12.48 2.25.12 3.4-.84.06-1.67.07-2.51.02.56-.68.52-1.32-.1-1.92-.26-.13-.54-.19-.84-.17.02-.95 0-1.91-.07-2.86-.21-.41-.55-.58-1.01-.52-.17.03-.31.09-.44.2-.72.92-1.43 1.85-2.14 2.78-.28.45-.29.91-.05 1.38q.225.3.57.42c.34.02.69.03 1.03.02v.69c-1.3.02-2.59 0-3.89-.05-.58-2.1-.08-3.88 1.53-5.34.79-.62 1.68-1 2.66-1.16zm.83 1.82c.07 0 .13.03.17.1l.05 3.05c.04.09.1.16.17.22l.89.05c.22.08.3.24.22.47q-.27.42-.57.81c-.43.02-.85.03-1.28.02 0-.41 0-.82-.02-1.23a.46.46 0 0 0-.17-.17l-1.28-.05c-.3-.1-.37-.29-.22-.57.7-.89 1.39-1.79 2.04-2.71zm-5.81.84h.2a6.1 6.1 0 0 0-.25 3.77c-.59-.13-1.01-.49-1.26-1.06-.36-1.29.08-2.19 1.31-2.71m17.98.83c.05 0 .1 0 .15.02q.825.855.96 2.04.045 1.305 0 2.61a3.76 3.76 0 0 0-2.54-1.55c-.61-.05-1.21-.08-1.82-.1.26-.31.48-.66.64-1.03 1.31.02 1.94-.62 1.87-1.95.26.02.5 0 .74-.05zM5.7 11.22c.41.4.91.65 1.48.76l16.06.05c1.42.13 2.38.87 2.88 2.19.07.24.12.49.15.74.03 2.86.03 5.71 0 8.57-.21 1.44-1 2.38-2.39 2.83-.24.05-.49.08-.74.1-1.26.02-2.53.03-3.79.02 0-1.33 0-2.66.02-3.99l1.55-1.55c1.42-.04 2.09-.78 1.99-2.19-.24-.88-.81-1.34-1.72-1.38-1.2.12-1.81.8-1.82 2.02l-1.92 1.92c-.08.11-.14.22-.2.34-.07 1.61-.1 3.22-.07 4.83h-.44c0-2.28 0-4.56-.02-6.85a1.8 1.8 0 0 0-.15-.34l-1.13-1.13c0-1.23-.61-1.92-1.82-2.07-1.29.17-1.87.91-1.72 2.22q.465 1.395 1.95 1.35l.71.71c0 .3.04.6.1.89.25.21.48.19.69-.05.03-.39.03-.79 0-1.18-.2-.25-.43-.49-.66-.71.15-.1.29-.22.39-.37.3.27.58.55.86.84.02 2.23.03 4.47.02 6.7h-.59c0-1.38 0-2.76-.02-4.14-.15-.25-.35-.31-.62-.17a1 1 0 0 0-.12.22c-.02 1.36-.03 2.73-.02 4.09h-.44c0-.99 0-1.97-.02-2.96-.02-.09-.06-.17-.1-.25-.67-.72-1.36-1.43-2.07-2.12-.06-1.48-.82-2.13-2.29-1.95-1.02.41-1.42 1.16-1.21 2.24q.51 1.32 1.95 1.26l1.55 1.55c.02.74.03 1.48.02 2.22-1.56.02-3.12 0-4.68-.07-.9-.24-1.42-.83-1.55-1.75-.02-4.48-.03-8.96-.02-13.45zm7.79 5.66c.84.06 1.19.5 1.06 1.33-.32.62-.8.79-1.45.52-.46-.37-.56-.82-.32-1.35.18-.26.42-.42.71-.49zm7.43 1.28c.89-.03 1.29.4 1.21 1.28-.33.67-.83.85-1.5.52-.54-.49-.58-1-.1-1.55.12-.11.25-.19.39-.25M9.94 19.94c.84 0 1.22.4 1.16 1.23-.28.68-.76.89-1.45.62-.63-.54-.65-1.09-.05-1.67l.34-.17zm9.75.24c.16.13.3.27.44.42-.53.52-1.05 1.05-1.55 1.6-.02 1.43-.03 2.86-.02 4.28h-.59c0-1.51 0-3.02.02-4.53a71 71 0 0 1 1.7-1.77M11.56 22c.62.53 1.21 1.11 1.75 1.72.02.92.03 1.84.02 2.76h-.59c0-.85 0-1.71-.02-2.56l-1.48-1.48s-.03-.07 0-.1c.12-.11.22-.22.32-.34",clipRule:"evenodd"})]});function gt({walletName:o,variant:e="background",className:t}){let n=s("novacore:w-full novacore:h-full novacore:rounded-full",t),r=o.toLowerCase();if(r==="impersonatedwallet")return jsxRuntime.jsx(h,{iconId:"impersonatedwallet",className:n,children:l=>jsxRuntime.jsx(Wo,{ref:l})});let a=Vo[r]??r,i=`wallets/${e}/${S(a)}`;return zo(a)?jsxRuntime.jsx(d.Suspense,{fallback:jsxRuntime.jsx(p,{animate:true,className:t}),children:jsxRuntime.jsx(h,{iconId:`${a}-${e}`,className:n,children:l=>jsxRuntime.jsx(Fo,{ref:l,id:a,variant:e})})}):jsxRuntime.jsx(P,{githubSrc:i,className:n})}function yt(o=2e3){let[e,t]=d.useState(false),[n,r]=d.useState(null),a=d.useCallback(async i=>{if(i)try{await navigator.clipboard.writeText(i),t(!0),r(null),setTimeout(()=>t(!1),o);}catch(l){let u=l instanceof Error?l:new Error("Failed to copy text.");console.error(u),r(u),setTimeout(()=>r(null),o);}},[o]);return {isCopied:e,copy:a,error:n}}function St(o){let e=r=>typeof window<"u"?window.matchMedia(r).matches:false,[t,n]=d.useState(e(o));return d.useEffect(()=>{let r=window.matchMedia(o),a=()=>n(r.matches);return a(),window.addEventListener("resize",a),()=>window.removeEventListener("resize",a)},[o]),t}
48
- exports.ChevronArrowWithAnim=ve;exports.CloseIcon=no;exports.Dialog=Ve;exports.DialogClose=We;exports.DialogContent=go;exports.DialogDescription=yo;exports.DialogFooter=bo;exports.DialogHeader=wo;exports.DialogOverlay=Y;exports.DialogPortal=uo;exports.DialogTitle=ho;exports.DialogTrigger=ze;exports.FallbackIcon=p;exports.GithubFallbackIcon=P;exports.NetworkIcon=Je;exports.StarsBackground=rt;exports.SvgImg=C;exports.SvgToImg=h;exports.ToastCloseButton=st;exports.WalletIcon=gt;exports.applyFirstPathFill=to;exports.cn=s;exports.deepMerge=J;exports.formatIconNameForGithub=S;exports.getChainName=W;exports.isSolanaDev=x;exports.isTouchDevice=G;exports.resolveCssVariable=eo;exports.standardButtonClasses=_o;exports.svgToBase64=N;exports.textCenterEllipsis=te;exports.useCopyToClipboard=yt;exports.useMediaQuery=St;
47
+ `})}),n.map((r,a)=>jsxRuntime.jsx("circle",{cx:r.x,cy:r.y,r:r.r,fill:"rgba(var(--tuwa-bg-primary), 0.7)",className:r.isSupernova?"supernova":"pulsar",style:{animationDelay:`${r.delay}s`,animationDuration:`${r.duration}s`}},a))]})})}function st({closeToast:o,ariaLabel:e="Close toast notification",title:t="Close toast notification",className:n,iconClassName:r}){return jsxRuntime.jsx("button",{type:"button",onClick:o,"aria-label":e,title:t,className:s("novacore:absolute novacore:top-2 novacore:right-2 novacore:cursor-pointer novacore:rounded-[var(--tuwa-rounded-corners)] novacore:p-1","novacore:text-[var(--tuwa-text-tertiary)] novacore:transition-colors","novacore:hover:bg-[var(--tuwa-bg-muted)] novacore:hover:text-[var(--tuwa-text-primary)]",n),children:jsxRuntime.jsx("svg",{xmlns:"http://www.w3.org/2000/svg",fill:"none",viewBox:"0 0 24 24",strokeWidth:1.5,stroke:"currentColor",className:s("novacore:h-5 novacore:w-5",r),children:jsxRuntime.jsx("path",{strokeLinecap:"round",strokeLinejoin:"round",d:"M6 18 18 6M6 6l12 12"})})})}var Fo=d.lazy(()=>import('@web3icons/react/dynamic').then(o=>({default:o.WalletIcon}))),Vo={walletconnect:"wallet-connect"};function zo(o){return metadata.wallets.some(e=>e.id===o||e.name?.toLowerCase()===o)}var Wo=({className:o,ref:e})=>jsxRuntime.jsxs("svg",{ref:e,className:o,fill:"none",viewBox:"0 0 32 32",xmlns:"http://www.w3.org/2000/svg",children:[jsxRuntime.jsx("path",{fill:"#fff",fillRule:"evenodd",d:"M16 0c8.84 0 16 7.16 16 16s-7.16 16-16 16S0 24.84 0 16 7.16 0 16 0",clipRule:"evenodd"}),jsxRuntime.jsx("path",{fill:"#000",fillRule:"evenodd",d:"M16.54 2.01h1.53c.5.09.99.23 1.48.42.21.25.19.48-.05.69q-.195.045-.39 0c-1.86-.65-3.55-.35-5.07.89 2.39.7 3.84 2.27 4.36 4.7.12.85.08 1.68-.12 2.51.87 0 1.74 0 2.61-.02.39-.4.7-.85.94-1.35-.45-.45-.65-.99-.59-1.63-1.15.08-1.79-.44-1.92-1.58.14-1.12.78-1.67 1.92-1.63a.7.7 0 0 0-.12-.49l-.89-.89c-.02-.45.19-.6.62-.47.24.19.46.39.66.62.71-.79 1.5-.89 2.39-.32.44.42.62.94.54 1.55 1.49.02 2.11.76 1.85 2.22-.08.17-.17.34-.27.49.53.59.87 1.28 1.01 2.07.08 4.6.1 9.19.05 13.79-.19 1.58-1 2.71-2.44 3.37-.29.1-.59.2-.89.27H7.2c-1.31-.33-2.05-1.17-2.24-2.51-.03-5.24-.03-10.47 0-15.71.3-1.62 1.28-2.46 2.93-2.54 1.26-1.77 2.98-2.64 5.17-2.61.96-1.01 2.13-1.62 3.5-1.85zm6.11 1.87c.39-.03.7.12.91.44.06.39.09.79.1 1.18.02.12.07.21.17.27.41 0 .82.04 1.23.1.49.26.63.65.42 1.16-.07.14-.18.25-.32.32-.39.06-.79.09-1.18.1-.12.02-.21.07-.27.17l-.15 1.33c-.32.46-.72.55-1.21.27a.76.76 0 0 1-.27-.37c-.06-.41-.09-.82-.1-1.23a.35.35 0 0 0-.27-.17l-1.08-.05c-.46-.24-.62-.61-.47-1.11.14-.27.36-.43.66-.47l.99-.05s.09-.04.12-.07l.15-1.28q.18-.39.57-.54m-10.49.79c2.41-.09 4.12.94 5.15 3.1.44 1.12.48 2.25.12 3.4-.84.06-1.67.07-2.51.02.56-.68.52-1.32-.1-1.92-.26-.13-.54-.19-.84-.17.02-.95 0-1.91-.07-2.86-.21-.41-.55-.58-1.01-.52-.17.03-.31.09-.44.2-.72.92-1.43 1.85-2.14 2.78-.28.45-.29.91-.05 1.38q.225.3.57.42c.34.02.69.03 1.03.02v.69c-1.3.02-2.59 0-3.89-.05-.58-2.1-.08-3.88 1.53-5.34.79-.62 1.68-1 2.66-1.16zm.83 1.82c.07 0 .13.03.17.1l.05 3.05c.04.09.1.16.17.22l.89.05c.22.08.3.24.22.47q-.27.42-.57.81c-.43.02-.85.03-1.28.02 0-.41 0-.82-.02-1.23a.46.46 0 0 0-.17-.17l-1.28-.05c-.3-.1-.37-.29-.22-.57.7-.89 1.39-1.79 2.04-2.71zm-5.81.84h.2a6.1 6.1 0 0 0-.25 3.77c-.59-.13-1.01-.49-1.26-1.06-.36-1.29.08-2.19 1.31-2.71m17.98.83c.05 0 .1 0 .15.02q.825.855.96 2.04.045 1.305 0 2.61a3.76 3.76 0 0 0-2.54-1.55c-.61-.05-1.21-.08-1.82-.1.26-.31.48-.66.64-1.03 1.31.02 1.94-.62 1.87-1.95.26.02.5 0 .74-.05zM5.7 11.22c.41.4.91.65 1.48.76l16.06.05c1.42.13 2.38.87 2.88 2.19.07.24.12.49.15.74.03 2.86.03 5.71 0 8.57-.21 1.44-1 2.38-2.39 2.83-.24.05-.49.08-.74.1-1.26.02-2.53.03-3.79.02 0-1.33 0-2.66.02-3.99l1.55-1.55c1.42-.04 2.09-.78 1.99-2.19-.24-.88-.81-1.34-1.72-1.38-1.2.12-1.81.8-1.82 2.02l-1.92 1.92c-.08.11-.14.22-.2.34-.07 1.61-.1 3.22-.07 4.83h-.44c0-2.28 0-4.56-.02-6.85a1.8 1.8 0 0 0-.15-.34l-1.13-1.13c0-1.23-.61-1.92-1.82-2.07-1.29.17-1.87.91-1.72 2.22q.465 1.395 1.95 1.35l.71.71c0 .3.04.6.1.89.25.21.48.19.69-.05.03-.39.03-.79 0-1.18-.2-.25-.43-.49-.66-.71.15-.1.29-.22.39-.37.3.27.58.55.86.84.02 2.23.03 4.47.02 6.7h-.59c0-1.38 0-2.76-.02-4.14-.15-.25-.35-.31-.62-.17a1 1 0 0 0-.12.22c-.02 1.36-.03 2.73-.02 4.09h-.44c0-.99 0-1.97-.02-2.96-.02-.09-.06-.17-.1-.25-.67-.72-1.36-1.43-2.07-2.12-.06-1.48-.82-2.13-2.29-1.95-1.02.41-1.42 1.16-1.21 2.24q.51 1.32 1.95 1.26l1.55 1.55c.02.74.03 1.48.02 2.22-1.56.02-3.12 0-4.68-.07-.9-.24-1.42-.83-1.55-1.75-.02-4.48-.03-8.96-.02-13.45zm7.79 5.66c.84.06 1.19.5 1.06 1.33-.32.62-.8.79-1.45.52-.46-.37-.56-.82-.32-1.35.18-.26.42-.42.71-.49zm7.43 1.28c.89-.03 1.29.4 1.21 1.28-.33.67-.83.85-1.5.52-.54-.49-.58-1-.1-1.55.12-.11.25-.19.39-.25M9.94 19.94c.84 0 1.22.4 1.16 1.23-.28.68-.76.89-1.45.62-.63-.54-.65-1.09-.05-1.67l.34-.17zm9.75.24c.16.13.3.27.44.42-.53.52-1.05 1.05-1.55 1.6-.02 1.43-.03 2.86-.02 4.28h-.59c0-1.51 0-3.02.02-4.53a71 71 0 0 1 1.7-1.77M11.56 22c.62.53 1.21 1.11 1.75 1.72.02.92.03 1.84.02 2.76h-.59c0-.85 0-1.71-.02-2.56l-1.48-1.48s-.03-.07 0-.1c.12-.11.22-.22.32-.34",clipRule:"evenodd"})]});function gt({walletName:o,variant:e="background",className:t}){let n=s("novacore:w-full novacore:h-full novacore:rounded-full",t),r=o.toLowerCase();if(r==="impersonatedwallet")return jsxRuntime.jsx(h,{iconId:"impersonatedwallet",className:n,children:l=>jsxRuntime.jsx(Wo,{ref:l})});let a=Vo[r]??r,i=`wallets/${e}/${C(a)}`;return zo(a)?jsxRuntime.jsx(d.Suspense,{fallback:jsxRuntime.jsx(f,{animate:true,className:t}),children:jsxRuntime.jsx(h,{iconId:`${a}-${e}`,className:n,children:l=>jsxRuntime.jsx(Fo,{ref:l,id:a,variant:e})})}):jsxRuntime.jsx(P,{githubSrc:i,className:n})}function yt(o=2e3){let[e,t]=d.useState(false),[n,r]=d.useState(null),a=d.useCallback(async i=>{if(!i)return {copied:false,error:new Error("There is no text to copy.")};try{return await navigator.clipboard.writeText(i),t(!0),r(null),setTimeout(()=>t(!1),o),{copied:!0}}catch(l){let m=l instanceof Error?l:new Error("Failed to copy text.");return console.error(m),r(m),setTimeout(()=>r(null),o),{copied:false,error:m}}},[o]);return {isCopied:e,copy:a,error:n}}function Ct(o){let e=r=>typeof window<"u"?window.matchMedia(r).matches:false,[t,n]=d.useState(e(o));return d.useEffect(()=>{let r=window.matchMedia(o),a=()=>n(r.matches);return a(),window.addEventListener("resize",a),()=>window.removeEventListener("resize",a)},[o]),t}
48
+ exports.ChevronArrowWithAnim=ve;exports.CloseIcon=no;exports.Dialog=Ve;exports.DialogClose=We;exports.DialogContent=go;exports.DialogDescription=yo;exports.DialogFooter=bo;exports.DialogHeader=wo;exports.DialogOverlay=Y;exports.DialogPortal=uo;exports.DialogTitle=ho;exports.DialogTrigger=ze;exports.FallbackIcon=f;exports.GithubFallbackIcon=P;exports.NetworkIcon=Je;exports.StarsBackground=rt;exports.SvgImg=k;exports.SvgToImg=h;exports.ToastCloseButton=st;exports.WalletIcon=gt;exports.applyFirstPathFill=to;exports.cn=s;exports.deepMerge=J;exports.formatIconNameForGithub=C;exports.getChainName=W;exports.isSolanaDev=x;exports.isTouchDevice=G;exports.resolveCssVariable=eo;exports.standardButtonClasses=Uo;exports.svgToBase64=N;exports.textCenterEllipsis=te;exports.useCopyToClipboard=yt;exports.useMediaQuery=Ct;
package/dist/index.d.cts CHANGED
@@ -4,6 +4,16 @@ import * as DialogPrimitive from '@radix-ui/react-dialog';
4
4
  import { Variants } from 'framer-motion';
5
5
  import { ClassValue } from 'clsx';
6
6
 
7
+ /**
8
+ * A chevron that points up when `isOpen` is `true` and down otherwise, animated with `framer-motion` when it flips.
9
+ * Nova uses it in dropdown triggers such as the chain selector.
10
+ *
11
+ * @param props - The chevron props.
12
+ * @param props.className - Classes merged with the default size and color (`--tuwa-text-secondary`).
13
+ * @param props.strokeWidth - Stroke width of the SVG path. Defaults to `2`.
14
+ * @param props.isOpen - Whether the related list is open.
15
+ * @returns The SVG element.
16
+ */
7
17
  declare function ChevronArrowWithAnim({ className, strokeWidth, isOpen, }: {
8
18
  className?: string;
9
19
  strokeWidth?: number;
@@ -69,10 +79,29 @@ interface GithubFallbackIconProps extends Omit<ComponentProps<'img'>, 'src'> {
69
79
  */
70
80
  declare function GithubFallbackIcon({ githubSrc, className, alt, firstPathFill, ...props }: GithubFallbackIconProps): React$1.JSX.Element;
71
81
 
82
+ /**
83
+ * The dialog root (`Root` of `@radix-ui/react-dialog`): holds the open state (`open`, `defaultOpen`, `onOpenChange`).
84
+ */
72
85
  declare const Dialog: React$1.FC<DialogPrimitive.DialogProps>;
86
+ /** The element that opens the dialog (`Trigger` of `@radix-ui/react-dialog`). */
73
87
  declare const DialogTrigger: React$1.ForwardRefExoticComponent<DialogPrimitive.DialogTriggerProps & React$1.RefAttributes<HTMLButtonElement>>;
88
+ /** Renders its children in `document.body` (`Portal` of `@radix-ui/react-dialog`). {@link DialogContent} uses it. */
74
89
  declare const DialogPortal: React$1.FC<DialogPrimitive.DialogPortalProps>;
90
+ /** An element that closes the dialog (`Close` of `@radix-ui/react-dialog`). */
75
91
  declare const DialogClose: React$1.ForwardRefExoticComponent<DialogPrimitive.DialogCloseProps & React$1.RefAttributes<HTMLButtonElement>>;
92
+ /**
93
+ * The dimmed, blurred backdrop behind the dialog, faded in and out with `framer-motion`. {@link DialogContent} renders
94
+ * it.
95
+ *
96
+ * Side effect: while it is mounted, the `NovaModalOpen` class is set on `document.body`; the stylesheet of this package
97
+ * uses it to stop the page from scrolling.
98
+ *
99
+ * @param props - The overlay props.
100
+ * @param props.className - Classes added to the backdrop element.
101
+ * @param props.backdropAnimation - `framer-motion` variants (`initial`, `animate`, `exit`) of the backdrop; a fade by
102
+ * default.
103
+ * @returns The backdrop.
104
+ */
76
105
  declare const DialogOverlay: {
77
106
  ({ className, backdropAnimation }: {
78
107
  backdropAnimation?: Variants;
@@ -80,28 +109,77 @@ declare const DialogOverlay: {
80
109
  }): React$1.JSX.Element;
81
110
  displayName: string | undefined;
82
111
  };
112
+ /**
113
+ * The dialog panel (`Content` of `@radix-ui/react-dialog`), rendered in a portal above {@link DialogOverlay}. It takes
114
+ * the props of the Radix `Content` plus `modalAnimation` and `backdropAnimation` (`framer-motion` variants). By default
115
+ * the panel scales in at the center of the screen, or slides up from the bottom on touch devices (`isTouchDevice`); its
116
+ * content scrolls when it is taller than the viewport. Use it inside {@link Dialog}.
117
+ */
83
118
  declare const DialogContent: React$1.ForwardRefExoticComponent<Omit<DialogPrimitive.DialogContentProps & React$1.RefAttributes<HTMLDivElement>, "ref"> & {
84
119
  modalAnimation?: Variants;
85
120
  backdropAnimation?: Variants;
86
121
  } & React$1.RefAttributes<HTMLDivElement>>;
122
+ /**
123
+ * A sticky header row of the dialog, with a bottom border.
124
+ *
125
+ * @param props - Props of the `<div>` element; `className` is merged with the default classes.
126
+ * @returns The header element.
127
+ */
87
128
  declare const DialogHeader: {
88
129
  ({ className, ...props }: React$1.HTMLAttributes<HTMLDivElement>): React$1.JSX.Element;
89
130
  displayName: string;
90
131
  };
132
+ /**
133
+ * A footer row of the dialog: stacked on small screens, aligned to the end on wider ones.
134
+ *
135
+ * @param props - Props of the `<div>` element; `className` is merged with the default classes.
136
+ * @returns The footer element.
137
+ */
91
138
  declare const DialogFooter: {
92
139
  ({ className, ...props }: React$1.HTMLAttributes<HTMLDivElement>): React$1.JSX.Element;
93
140
  displayName: string;
94
141
  };
142
+ /** The dialog title (`Title` of `@radix-ui/react-dialog`), styled with the Nova theme. */
95
143
  declare const DialogTitle: React$1.ForwardRefExoticComponent<Omit<DialogPrimitive.DialogTitleProps & React$1.RefAttributes<HTMLHeadingElement>, "ref"> & React$1.RefAttributes<HTMLHeadingElement>>;
144
+ /** The dialog description (`Description` of `@radix-ui/react-dialog`), styled with the Nova theme. */
96
145
  declare const DialogDescription: React$1.ForwardRefExoticComponent<Omit<DialogPrimitive.DialogDescriptionProps & React$1.RefAttributes<HTMLParagraphElement>, "ref"> & React$1.RefAttributes<HTMLParagraphElement>>;
97
146
 
147
+ /**
148
+ * Props of {@link NetworkIcon}.
149
+ */
98
150
  interface NetworkIconProps {
151
+ /**
152
+ * The network: an EVM chain ID (`1`), or a string whose part before `:` is a network id of `@web3icons/common`
153
+ * (`'solana:devnet'`, `'base'`).
154
+ */
99
155
  chainId: number | string;
156
+ /** Icon style of `@web3icons/react`. Defaults to `'background'`. */
100
157
  variant?: 'background' | 'branded' | 'mono';
158
+ /** Classes merged with the default classes (full size of the parent, rounded). */
101
159
  className?: string;
102
160
  }
161
+ /**
162
+ * The icon of a network. Networks listed in `@web3icons/common` are drawn with `@web3icons/react`, loaded on demand
163
+ * (a pulsing {@link FallbackIcon} is shown meanwhile) and rendered through {@link SvgToImg}. An unknown numeric chain
164
+ * shows a `?` placeholder; an unknown string id is fetched from the web3icons repository on GitHub
165
+ * ({@link GithubFallbackIcon}). Testnets and the Solana devnet and testnet are recolored with `--tuwa-testnet-icons`.
166
+ *
167
+ * Side effect: a GitHub request (`raw.githubusercontent.com`) for icons that `@web3icons/common` does not list.
168
+ *
169
+ * @param props - See {@link NetworkIconProps}.
170
+ * @returns The icon element.
171
+ */
103
172
  declare function NetworkIcon({ chainId, variant, className }: NetworkIconProps): React$1.JSX.Element;
104
173
 
174
+ /**
175
+ * An animated background of twinkling stars, drawn as SVG circles with CSS animations. It fills its positioned parent
176
+ * (`absolute`, `inset-0`); the stars are placed at random over the window size after mount, so nothing is rendered on
177
+ * the server. Nova Connect uses it in the "about wallets" and "get a wallet" screens of the connect modal.
178
+ *
179
+ * @param props - The background props.
180
+ * @param props.starsCount - Number of stars. Defaults to `200`.
181
+ * @returns The background element.
182
+ */
105
183
  declare function StarsBackground({ starsCount }: {
106
184
  starsCount?: number;
107
185
  }): React$1.JSX.Element;
@@ -126,7 +204,12 @@ declare function SvgImg({ src, alt, ...props }: SvgImgProps): React$1.JSX.Elemen
126
204
  * Props for the SvgToImg component.
127
205
  */
128
206
  interface SvgToImgProps extends Omit<ComponentProps<'img'>, 'ref' | 'src' | 'children'> {
129
- /** Child SVG element to render while converting */
207
+ /**
208
+ * Renders the SVG. Pass `ref` to the `<svg>` element: when it mounts, its markup is converted to an image.
209
+ *
210
+ * @param ref - Callback ref for the `<svg>` element; it receives the element (or `null` when it unmounts).
211
+ * @returns The SVG to convert.
212
+ */
130
213
  children: (ref: (node: SVGSVGElement | null) => void) => ReactNode;
131
214
  /**
132
215
  * Unique identifier for the icon. When this changes, the cached image is reset.
@@ -149,14 +232,22 @@ interface SvgToImgProps extends Omit<ComponentProps<'img'>, 'ref' | 'src' | 'chi
149
232
  * Uses a render prop pattern to inject a callback ref that captures
150
233
  * the SVG immediately when it mounts.
151
234
  *
152
- * @param props - {@link SvgToImgProps}
153
- * @returns The converted image or the original children while loading
235
+ * @param props - See {@link SvgToImgProps}; the other props are passed to the `<img>` element.
236
+ * @returns The `<img>` with the converted SVG, or the output of `children` until the SVG has mounted.
154
237
  *
155
238
  * @example
156
239
  * ```tsx
157
- * <SvgToImg iconId={chainId} firstPathFill={TESTNET_FILL}>
158
- * {(ref) => <NetworkIconLazy ref={ref} chainId={chainId} />}
159
- * </SvgToImg>
240
+ * import { SvgToImg } from '@tuwaio/nova-core';
241
+ *
242
+ * export const DotIcon = () => (
243
+ * <SvgToImg iconId="dot" alt="Dot">
244
+ * {(ref) => (
245
+ * <svg ref={ref} viewBox="0 0 24 24">
246
+ * <circle cx="12" cy="12" r="10" />
247
+ * </svg>
248
+ * )}
249
+ * </SvgToImg>
250
+ * );
160
251
  * ```
161
252
  */
162
253
  declare function SvgToImg({ children, iconId, alt, firstPathFill, ...props }: SvgToImgProps): React$1.JSX.Element;
@@ -169,17 +260,14 @@ declare function SvgToImg({ children, iconId, alt, firstPathFill, ...props }: Sv
169
260
  */
170
261
  type ToastCloseButtonProps = {
171
262
  /**
172
- * The function to call when the button is clicked. This is typically provided by the
173
- * toast library (e.g., react-toastify) to dismiss the notification.
263
+ * Called when the button is clicked. `react-toastify` passes it to a custom close button to dismiss the toast.
264
+ *
265
+ * @param e - The click event.
174
266
  */
175
267
  closeToast?: (e: React.MouseEvent<HTMLElement>) => void;
176
- /**
177
- * Optional custom aria-label for accessibility.
178
- */
268
+ /** Accessible label of the button. Defaults to `'Close toast notification'`. */
179
269
  ariaLabel?: string;
180
- /**
181
- * Optional custom title for the button tooltip.
182
- */
270
+ /** Tooltip of the button. Defaults to `'Close toast notification'`. */
183
271
  title?: string;
184
272
  /**
185
273
  * Optional custom className for the button container.
@@ -191,8 +279,11 @@ type ToastCloseButtonProps = {
191
279
  iconClassName?: string;
192
280
  };
193
281
  /**
194
- * A simple, styled close button component ('X' icon) intended for use within toast notifications.
195
- * It uses theme-aware CSS variables for styling and i18n labels for accessibility.
282
+ * A close button with an X icon, placed in the top-right corner of a toast (`absolute`) and styled with the `--tuwa-*`
283
+ * variables. Pass it to `react-toastify` as `closeButton`, which provides `closeToast`.
284
+ *
285
+ * @param props - See {@link ToastCloseButtonProps}.
286
+ * @returns The button element.
196
287
  */
197
288
  declare function ToastCloseButton({ closeToast, ariaLabel, title, className, iconClassName, }: ToastCloseButtonProps): React$1.JSX.Element;
198
289
 
@@ -230,42 +321,74 @@ declare function WalletIcon({ walletName, variant, className }: WalletIconProps)
230
321
  * @file This file contains a custom React hook for copying text to the clipboard.
231
322
  */
232
323
  /**
233
- * A custom React hook that provides functionality to copy text to the clipboard.
234
- * It also manages a "copied" state with a timeout for user feedback.
324
+ * Result of `copy` of {@link useCopyToClipboard}: `copied: true`, or `copied: false` with the error (also without
325
+ * text to copy).
326
+ */
327
+ type CopyToClipboardResult = {
328
+ copied: true;
329
+ } | {
330
+ copied: false;
331
+ error: Error;
332
+ };
333
+ /**
334
+ * Value returned by {@link useCopyToClipboard}.
335
+ */
336
+ interface UseCopyToClipboardResult {
337
+ /** `true` for `timeout` milliseconds after a successful copy */
338
+ isCopied: boolean;
339
+ /**
340
+ * Writes the text to the clipboard (`navigator.clipboard.writeText`). A failed write is logged with
341
+ * `console.error` and kept in `error` for `timeout` milliseconds.
342
+ *
343
+ * @param text - The text to copy.
344
+ * @returns Whether the text was copied, with the error when it was not.
345
+ */
346
+ copy: (text: string) => Promise<CopyToClipboardResult>;
347
+ /** The error of the last failed write, for `timeout` milliseconds */
348
+ error: Error | null;
349
+ }
350
+ /**
351
+ * Copies text to the clipboard and keeps a "copied" state for user feedback.
235
352
  *
236
- * @param {number} [timeout=2000] - The duration in milliseconds to keep the `isCopied` state as true.
237
- * @returns {{
238
- * isCopied: boolean;
239
- * copy: (text: string) => Promise<void>;
240
- * error: Error | null;
241
- * }} An object containing the `isCopied` state, the `copy` function, and any potential error.
353
+ * @param timeout - How long `isCopied` (and `error` after a failure) stays set, in milliseconds (default: `2000`).
354
+ * @returns See {@link UseCopyToClipboardResult}.
242
355
  *
243
356
  * @example
244
- * const MyComponent = () => {
245
- * const { isCopied, copy } = useCopyToClipboard();
246
- * const textToCopy = '0x123...';
247
- *
248
- * return (
249
- * <button onClick={() => copy(textToCopy)}>
250
- * {isCopied ? 'Copied!' : 'Copy Address'}
251
- * </button>
252
- * );
357
+ * ```tsx
358
+ * import { useCopyToClipboard } from '@tuwaio/nova-core';
359
+ *
360
+ * export function CopyAddress({ address }: { address: string }) {
361
+ * const { isCopied, copy } = useCopyToClipboard();
362
+ *
363
+ * const handleClick = async () => {
364
+ * const result = await copy(address);
365
+ * if (!result.copied) console.warn(result.error.message);
366
+ * };
367
+ *
368
+ * return (
369
+ * <button type="button" onClick={handleClick}>
370
+ * {isCopied ? 'Copied!' : 'Copy address'}
371
+ * </button>
372
+ * );
253
373
  * }
374
+ * ```
254
375
  */
255
- declare function useCopyToClipboard(timeout?: number): {
256
- isCopied: boolean;
257
- copy: (text: string) => Promise<void>;
258
- error: Error | null;
259
- };
376
+ declare function useCopyToClipboard(timeout?: number): UseCopyToClipboardResult;
260
377
 
261
378
  /**
262
379
  * A custom hook to detect if a media query matches the current screen dimensions.
263
- * Handles SSR gracefully.
264
- * @param {string} query - The media query string (e.g., '(max-width: 767px)').
265
- * @returns {boolean} Whether the query matches or not.
380
+ * Returns `false` on the server. In the browser it checks the query again on every `resize` event of `window`
381
+ * (a listener that is removed on unmount).
382
+ *
383
+ * @param query - The media query string (e.g., '(max-width: 767px)').
384
+ * @returns Whether the query matches.
266
385
  */
267
386
  declare function useMediaQuery(query: string): boolean;
268
387
 
388
+ /**
389
+ * Classes of the standard secondary button of Nova (Tailwind utilities with the `novacore:` prefix, styled with the
390
+ * `--tuwa-standart-button-*` variables). The connect modal uses them for its buttons.
391
+ */
269
392
  declare const standardButtonClasses = "novacore:cursor-pointer novacore:rounded-[var(--tuwa-rounded-corners)] novacore:bg-[var(--tuwa-standart-button-bg)] novacore:px-3 novacore:py-2 novacore:flex novacore:items-center novacore:gap-1 novacore:text-sm novacore:font-mono novacore:font-semibold novacore:text-[var(--tuwa-text-primary)] novacore:transition-colors novacore:hover:bg-[var(--tuwa-standart-button-hover)] novacore:disabled:cursor-not-allowed novacore:disabled:opacity-50 novacore:min-h-[36px]";
270
393
 
271
394
  /**
@@ -334,22 +457,24 @@ interface ChainInfo {
334
457
  * For string IDs with environment suffixes (like "solana:devnet"),
335
458
  * the suffix is appended to the name if it's a known dev/test environment.
336
459
  *
460
+ * The networks are looked up in the metadata of `@web3icons/common`.
461
+ *
337
462
  * @param chainId - Chain identifier (number for EVM, string for non-EVM)
338
- * @returns Chain information object with name, id, and original chainId
463
+ * @returns The network name, id and icon file path, and the original `chainId`; `'Unknown'`/`'unknown'` when the
464
+ * network is not listed.
339
465
  *
340
466
  * @example
341
467
  * ```ts
342
- * // EVM network
343
- * getChainName(1)
344
- * // → { name: "Ethereum", id: "ethereum", chainId: 1 }
468
+ * import { getChainName } from '@tuwaio/nova-core';
469
+ *
470
+ * getChainName(1);
471
+ * // → { name: 'Ethereum', id: 'ethereum', filePath: 'ethereum', chainId: 1 }
345
472
  *
346
- * // Solana devnet
347
- * getChainName("solana:devnet")
348
- * // → { name: "Solana Devnet", id: "solana", chainId: "solana:devnet" }
473
+ * getChainName('solana:devnet');
474
+ * // → { name: 'Solana Devnet', id: 'solana', filePath: 'solana', chainId: 'solana:devnet' }
349
475
  *
350
- * // Unknown network
351
- * getChainName(999999)
352
- * // → { name: "Unknown", id: "unknown", chainId: 999999 }
476
+ * getChainName(999999);
477
+ * // → { name: 'Unknown', id: 'unknown', filePath: 'unknown', chainId: 999999 }
353
478
  * ```
354
479
  */
355
480
  declare function getChainName(chainId: number | string): ChainInfo;
@@ -366,7 +491,7 @@ declare function getChainName(chainId: number | string): ChainInfo;
366
491
  declare function isSolanaDev(chainId: number | string): boolean;
367
492
 
368
493
  /**
369
- * @fileoverview Utility function to determine if the current environment supports touch input.
494
+ * @file Utility function to determine if the current environment supports touch input.
370
495
  * This is safe to use in Next.js applications as it checks for the `window` object existence.
371
496
  */
372
497
  /**
@@ -379,14 +504,16 @@ declare function isSolanaDev(chainId: number | string): boolean;
379
504
  *
380
505
  * This function is safe for server-side rendering (SSR) environments like Next.js.
381
506
  *
382
- * @param {number} [maxWidth=1200] The maximum screen width (in pixels) for a device to be considered 'touch' (default is 1200).
383
- * @returns {boolean} Returns true if the environment is determined to support touch input AND is within the width limit, otherwise false.
507
+ * @param {number} [maxWidth=1200] The maximum screen width (in pixels) for a device to be considered 'touch' (default
508
+ * is 1200).
509
+ * @returns {boolean} Returns true if the environment is determined to support touch input AND is within the width
510
+ * limit, otherwise false.
384
511
  */
385
512
  declare function isTouchDevice(maxWidth?: number): boolean;
386
513
 
387
514
  /**
388
- * Resolves a CSS variable to its computed value.
389
- * Returns the original value if it's not a CSS variable.
515
+ * Resolves a CSS variable to its computed value on `document.documentElement`.
516
+ * Returns the original value if it's not a CSS variable. Call it in the browser: it reads `getComputedStyle`.
390
517
  *
391
518
  * @param value - Color value, potentially a CSS variable like `var(--my-color)`
392
519
  * @returns Resolved color value (e.g., `#ff0000`) or original if not a variable
@@ -394,20 +521,20 @@ declare function isTouchDevice(maxWidth?: number): boolean;
394
521
  declare function resolveCssVariable(value: string): string;
395
522
  /**
396
523
  * Modifies the fill attribute of the first `<path>` element in an SVG string.
397
- * Uses DOMParser for safe XML manipulation.
398
- * Automatically resolves CSS variables (e.g., `var(--color)`) to their computed values.
524
+ * Uses DOMParser for safe XML manipulation, so call it in the browser.
525
+ * Automatically resolves CSS variables (e.g., `var(--color)`) to their computed values with {@link resolveCssVariable}.
399
526
  *
400
527
  * @param svgString - The original SVG markup
401
528
  * @param fillColor - The color to apply (supports CSS variables)
402
- * @returns Modified SVG string
529
+ * @returns Modified SVG string, or the original string (with a console warning) when it cannot be parsed
403
530
  */
404
531
  declare function applyFirstPathFill(svgString: string, fillColor: string): string;
405
532
  /**
406
533
  * Encodes an SVG string to a base64 data URL.
407
534
  *
408
535
  * @param svgString - The SVG markup
409
- * @param firstPathFill - Optional fill color to apply to the first path
410
- * @returns Base64-encoded data URL
536
+ * @param firstPathFill - Optional fill color to apply to the first path, with {@link applyFirstPathFill} (browser only)
537
+ * @returns Base64-encoded data URL (`data:image/svg+xml;base64,…`)
411
538
  */
412
539
  declare function svgToBase64(svgString: string, firstPathFill?: string): string;
413
540
  /**
@@ -421,14 +548,10 @@ declare function svgToBase64(svgString: string, firstPathFill?: string): string;
421
548
  *
422
549
  * @example
423
550
  * ```ts
424
- * formatIconNameForGithub("Wallet Connect")
425
- * // → "wallet-connect.svg"
426
- *
427
- * formatIconNameForGithub("MetaMask")
428
- * // → "metamask.svg"
551
+ * import { formatIconNameForGithub } from '@tuwaio/nova-core';
429
552
  *
430
- * formatIconNameForGithub("coinbase")
431
- * // → "coinbase.svg"
553
+ * formatIconNameForGithub('Wallet Connect'); // → 'wallet-connect.svg'
554
+ * formatIconNameForGithub('MetaMask'); // → 'metamask.svg'
432
555
  * ```
433
556
  */
434
557
  declare const formatIconNameForGithub: (name: string) => string;
@@ -453,4 +576,4 @@ declare const formatIconNameForGithub: (name: string) => string;
453
576
  */
454
577
  declare function textCenterEllipsis(str: string | undefined | null, from: number, to: number): string;
455
578
 
456
- export { type ChainInfo, ChevronArrowWithAnim, CloseIcon, Dialog, DialogClose, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogOverlay, DialogPortal, DialogTitle, DialogTrigger, FallbackIcon, type FallbackIconProps, GithubFallbackIcon, NetworkIcon, StarsBackground, SvgImg, type SvgImgProps, SvgToImg, ToastCloseButton, type ToastCloseButtonProps, WalletIcon, applyFirstPathFill, cn, deepMerge, formatIconNameForGithub, getChainName, isSolanaDev, isTouchDevice, resolveCssVariable, standardButtonClasses, svgToBase64, textCenterEllipsis, useCopyToClipboard, useMediaQuery };
579
+ export { type ChainInfo, ChevronArrowWithAnim, CloseIcon, type CopyToClipboardResult, Dialog, DialogClose, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogOverlay, DialogPortal, DialogTitle, DialogTrigger, FallbackIcon, type FallbackIconProps, GithubFallbackIcon, type GithubFallbackIconProps, NetworkIcon, type NetworkIconProps, StarsBackground, SvgImg, type SvgImgProps, SvgToImg, type SvgToImgProps, ToastCloseButton, type ToastCloseButtonProps, type UseCopyToClipboardResult, WalletIcon, type WalletIconProps, applyFirstPathFill, cn, deepMerge, formatIconNameForGithub, getChainName, isSolanaDev, isTouchDevice, resolveCssVariable, standardButtonClasses, svgToBase64, textCenterEllipsis, useCopyToClipboard, useMediaQuery };
package/dist/index.d.ts CHANGED
@@ -4,6 +4,16 @@ import * as DialogPrimitive from '@radix-ui/react-dialog';
4
4
  import { Variants } from 'framer-motion';
5
5
  import { ClassValue } from 'clsx';
6
6
 
7
+ /**
8
+ * A chevron that points up when `isOpen` is `true` and down otherwise, animated with `framer-motion` when it flips.
9
+ * Nova uses it in dropdown triggers such as the chain selector.
10
+ *
11
+ * @param props - The chevron props.
12
+ * @param props.className - Classes merged with the default size and color (`--tuwa-text-secondary`).
13
+ * @param props.strokeWidth - Stroke width of the SVG path. Defaults to `2`.
14
+ * @param props.isOpen - Whether the related list is open.
15
+ * @returns The SVG element.
16
+ */
7
17
  declare function ChevronArrowWithAnim({ className, strokeWidth, isOpen, }: {
8
18
  className?: string;
9
19
  strokeWidth?: number;
@@ -69,10 +79,29 @@ interface GithubFallbackIconProps extends Omit<ComponentProps<'img'>, 'src'> {
69
79
  */
70
80
  declare function GithubFallbackIcon({ githubSrc, className, alt, firstPathFill, ...props }: GithubFallbackIconProps): React$1.JSX.Element;
71
81
 
82
+ /**
83
+ * The dialog root (`Root` of `@radix-ui/react-dialog`): holds the open state (`open`, `defaultOpen`, `onOpenChange`).
84
+ */
72
85
  declare const Dialog: React$1.FC<DialogPrimitive.DialogProps>;
86
+ /** The element that opens the dialog (`Trigger` of `@radix-ui/react-dialog`). */
73
87
  declare const DialogTrigger: React$1.ForwardRefExoticComponent<DialogPrimitive.DialogTriggerProps & React$1.RefAttributes<HTMLButtonElement>>;
88
+ /** Renders its children in `document.body` (`Portal` of `@radix-ui/react-dialog`). {@link DialogContent} uses it. */
74
89
  declare const DialogPortal: React$1.FC<DialogPrimitive.DialogPortalProps>;
90
+ /** An element that closes the dialog (`Close` of `@radix-ui/react-dialog`). */
75
91
  declare const DialogClose: React$1.ForwardRefExoticComponent<DialogPrimitive.DialogCloseProps & React$1.RefAttributes<HTMLButtonElement>>;
92
+ /**
93
+ * The dimmed, blurred backdrop behind the dialog, faded in and out with `framer-motion`. {@link DialogContent} renders
94
+ * it.
95
+ *
96
+ * Side effect: while it is mounted, the `NovaModalOpen` class is set on `document.body`; the stylesheet of this package
97
+ * uses it to stop the page from scrolling.
98
+ *
99
+ * @param props - The overlay props.
100
+ * @param props.className - Classes added to the backdrop element.
101
+ * @param props.backdropAnimation - `framer-motion` variants (`initial`, `animate`, `exit`) of the backdrop; a fade by
102
+ * default.
103
+ * @returns The backdrop.
104
+ */
76
105
  declare const DialogOverlay: {
77
106
  ({ className, backdropAnimation }: {
78
107
  backdropAnimation?: Variants;
@@ -80,28 +109,77 @@ declare const DialogOverlay: {
80
109
  }): React$1.JSX.Element;
81
110
  displayName: string | undefined;
82
111
  };
112
+ /**
113
+ * The dialog panel (`Content` of `@radix-ui/react-dialog`), rendered in a portal above {@link DialogOverlay}. It takes
114
+ * the props of the Radix `Content` plus `modalAnimation` and `backdropAnimation` (`framer-motion` variants). By default
115
+ * the panel scales in at the center of the screen, or slides up from the bottom on touch devices (`isTouchDevice`); its
116
+ * content scrolls when it is taller than the viewport. Use it inside {@link Dialog}.
117
+ */
83
118
  declare const DialogContent: React$1.ForwardRefExoticComponent<Omit<DialogPrimitive.DialogContentProps & React$1.RefAttributes<HTMLDivElement>, "ref"> & {
84
119
  modalAnimation?: Variants;
85
120
  backdropAnimation?: Variants;
86
121
  } & React$1.RefAttributes<HTMLDivElement>>;
122
+ /**
123
+ * A sticky header row of the dialog, with a bottom border.
124
+ *
125
+ * @param props - Props of the `<div>` element; `className` is merged with the default classes.
126
+ * @returns The header element.
127
+ */
87
128
  declare const DialogHeader: {
88
129
  ({ className, ...props }: React$1.HTMLAttributes<HTMLDivElement>): React$1.JSX.Element;
89
130
  displayName: string;
90
131
  };
132
+ /**
133
+ * A footer row of the dialog: stacked on small screens, aligned to the end on wider ones.
134
+ *
135
+ * @param props - Props of the `<div>` element; `className` is merged with the default classes.
136
+ * @returns The footer element.
137
+ */
91
138
  declare const DialogFooter: {
92
139
  ({ className, ...props }: React$1.HTMLAttributes<HTMLDivElement>): React$1.JSX.Element;
93
140
  displayName: string;
94
141
  };
142
+ /** The dialog title (`Title` of `@radix-ui/react-dialog`), styled with the Nova theme. */
95
143
  declare const DialogTitle: React$1.ForwardRefExoticComponent<Omit<DialogPrimitive.DialogTitleProps & React$1.RefAttributes<HTMLHeadingElement>, "ref"> & React$1.RefAttributes<HTMLHeadingElement>>;
144
+ /** The dialog description (`Description` of `@radix-ui/react-dialog`), styled with the Nova theme. */
96
145
  declare const DialogDescription: React$1.ForwardRefExoticComponent<Omit<DialogPrimitive.DialogDescriptionProps & React$1.RefAttributes<HTMLParagraphElement>, "ref"> & React$1.RefAttributes<HTMLParagraphElement>>;
97
146
 
147
+ /**
148
+ * Props of {@link NetworkIcon}.
149
+ */
98
150
  interface NetworkIconProps {
151
+ /**
152
+ * The network: an EVM chain ID (`1`), or a string whose part before `:` is a network id of `@web3icons/common`
153
+ * (`'solana:devnet'`, `'base'`).
154
+ */
99
155
  chainId: number | string;
156
+ /** Icon style of `@web3icons/react`. Defaults to `'background'`. */
100
157
  variant?: 'background' | 'branded' | 'mono';
158
+ /** Classes merged with the default classes (full size of the parent, rounded). */
101
159
  className?: string;
102
160
  }
161
+ /**
162
+ * The icon of a network. Networks listed in `@web3icons/common` are drawn with `@web3icons/react`, loaded on demand
163
+ * (a pulsing {@link FallbackIcon} is shown meanwhile) and rendered through {@link SvgToImg}. An unknown numeric chain
164
+ * shows a `?` placeholder; an unknown string id is fetched from the web3icons repository on GitHub
165
+ * ({@link GithubFallbackIcon}). Testnets and the Solana devnet and testnet are recolored with `--tuwa-testnet-icons`.
166
+ *
167
+ * Side effect: a GitHub request (`raw.githubusercontent.com`) for icons that `@web3icons/common` does not list.
168
+ *
169
+ * @param props - See {@link NetworkIconProps}.
170
+ * @returns The icon element.
171
+ */
103
172
  declare function NetworkIcon({ chainId, variant, className }: NetworkIconProps): React$1.JSX.Element;
104
173
 
174
+ /**
175
+ * An animated background of twinkling stars, drawn as SVG circles with CSS animations. It fills its positioned parent
176
+ * (`absolute`, `inset-0`); the stars are placed at random over the window size after mount, so nothing is rendered on
177
+ * the server. Nova Connect uses it in the "about wallets" and "get a wallet" screens of the connect modal.
178
+ *
179
+ * @param props - The background props.
180
+ * @param props.starsCount - Number of stars. Defaults to `200`.
181
+ * @returns The background element.
182
+ */
105
183
  declare function StarsBackground({ starsCount }: {
106
184
  starsCount?: number;
107
185
  }): React$1.JSX.Element;
@@ -126,7 +204,12 @@ declare function SvgImg({ src, alt, ...props }: SvgImgProps): React$1.JSX.Elemen
126
204
  * Props for the SvgToImg component.
127
205
  */
128
206
  interface SvgToImgProps extends Omit<ComponentProps<'img'>, 'ref' | 'src' | 'children'> {
129
- /** Child SVG element to render while converting */
207
+ /**
208
+ * Renders the SVG. Pass `ref` to the `<svg>` element: when it mounts, its markup is converted to an image.
209
+ *
210
+ * @param ref - Callback ref for the `<svg>` element; it receives the element (or `null` when it unmounts).
211
+ * @returns The SVG to convert.
212
+ */
130
213
  children: (ref: (node: SVGSVGElement | null) => void) => ReactNode;
131
214
  /**
132
215
  * Unique identifier for the icon. When this changes, the cached image is reset.
@@ -149,14 +232,22 @@ interface SvgToImgProps extends Omit<ComponentProps<'img'>, 'ref' | 'src' | 'chi
149
232
  * Uses a render prop pattern to inject a callback ref that captures
150
233
  * the SVG immediately when it mounts.
151
234
  *
152
- * @param props - {@link SvgToImgProps}
153
- * @returns The converted image or the original children while loading
235
+ * @param props - See {@link SvgToImgProps}; the other props are passed to the `<img>` element.
236
+ * @returns The `<img>` with the converted SVG, or the output of `children` until the SVG has mounted.
154
237
  *
155
238
  * @example
156
239
  * ```tsx
157
- * <SvgToImg iconId={chainId} firstPathFill={TESTNET_FILL}>
158
- * {(ref) => <NetworkIconLazy ref={ref} chainId={chainId} />}
159
- * </SvgToImg>
240
+ * import { SvgToImg } from '@tuwaio/nova-core';
241
+ *
242
+ * export const DotIcon = () => (
243
+ * <SvgToImg iconId="dot" alt="Dot">
244
+ * {(ref) => (
245
+ * <svg ref={ref} viewBox="0 0 24 24">
246
+ * <circle cx="12" cy="12" r="10" />
247
+ * </svg>
248
+ * )}
249
+ * </SvgToImg>
250
+ * );
160
251
  * ```
161
252
  */
162
253
  declare function SvgToImg({ children, iconId, alt, firstPathFill, ...props }: SvgToImgProps): React$1.JSX.Element;
@@ -169,17 +260,14 @@ declare function SvgToImg({ children, iconId, alt, firstPathFill, ...props }: Sv
169
260
  */
170
261
  type ToastCloseButtonProps = {
171
262
  /**
172
- * The function to call when the button is clicked. This is typically provided by the
173
- * toast library (e.g., react-toastify) to dismiss the notification.
263
+ * Called when the button is clicked. `react-toastify` passes it to a custom close button to dismiss the toast.
264
+ *
265
+ * @param e - The click event.
174
266
  */
175
267
  closeToast?: (e: React.MouseEvent<HTMLElement>) => void;
176
- /**
177
- * Optional custom aria-label for accessibility.
178
- */
268
+ /** Accessible label of the button. Defaults to `'Close toast notification'`. */
179
269
  ariaLabel?: string;
180
- /**
181
- * Optional custom title for the button tooltip.
182
- */
270
+ /** Tooltip of the button. Defaults to `'Close toast notification'`. */
183
271
  title?: string;
184
272
  /**
185
273
  * Optional custom className for the button container.
@@ -191,8 +279,11 @@ type ToastCloseButtonProps = {
191
279
  iconClassName?: string;
192
280
  };
193
281
  /**
194
- * A simple, styled close button component ('X' icon) intended for use within toast notifications.
195
- * It uses theme-aware CSS variables for styling and i18n labels for accessibility.
282
+ * A close button with an X icon, placed in the top-right corner of a toast (`absolute`) and styled with the `--tuwa-*`
283
+ * variables. Pass it to `react-toastify` as `closeButton`, which provides `closeToast`.
284
+ *
285
+ * @param props - See {@link ToastCloseButtonProps}.
286
+ * @returns The button element.
196
287
  */
197
288
  declare function ToastCloseButton({ closeToast, ariaLabel, title, className, iconClassName, }: ToastCloseButtonProps): React$1.JSX.Element;
198
289
 
@@ -230,42 +321,74 @@ declare function WalletIcon({ walletName, variant, className }: WalletIconProps)
230
321
  * @file This file contains a custom React hook for copying text to the clipboard.
231
322
  */
232
323
  /**
233
- * A custom React hook that provides functionality to copy text to the clipboard.
234
- * It also manages a "copied" state with a timeout for user feedback.
324
+ * Result of `copy` of {@link useCopyToClipboard}: `copied: true`, or `copied: false` with the error (also without
325
+ * text to copy).
326
+ */
327
+ type CopyToClipboardResult = {
328
+ copied: true;
329
+ } | {
330
+ copied: false;
331
+ error: Error;
332
+ };
333
+ /**
334
+ * Value returned by {@link useCopyToClipboard}.
335
+ */
336
+ interface UseCopyToClipboardResult {
337
+ /** `true` for `timeout` milliseconds after a successful copy */
338
+ isCopied: boolean;
339
+ /**
340
+ * Writes the text to the clipboard (`navigator.clipboard.writeText`). A failed write is logged with
341
+ * `console.error` and kept in `error` for `timeout` milliseconds.
342
+ *
343
+ * @param text - The text to copy.
344
+ * @returns Whether the text was copied, with the error when it was not.
345
+ */
346
+ copy: (text: string) => Promise<CopyToClipboardResult>;
347
+ /** The error of the last failed write, for `timeout` milliseconds */
348
+ error: Error | null;
349
+ }
350
+ /**
351
+ * Copies text to the clipboard and keeps a "copied" state for user feedback.
235
352
  *
236
- * @param {number} [timeout=2000] - The duration in milliseconds to keep the `isCopied` state as true.
237
- * @returns {{
238
- * isCopied: boolean;
239
- * copy: (text: string) => Promise<void>;
240
- * error: Error | null;
241
- * }} An object containing the `isCopied` state, the `copy` function, and any potential error.
353
+ * @param timeout - How long `isCopied` (and `error` after a failure) stays set, in milliseconds (default: `2000`).
354
+ * @returns See {@link UseCopyToClipboardResult}.
242
355
  *
243
356
  * @example
244
- * const MyComponent = () => {
245
- * const { isCopied, copy } = useCopyToClipboard();
246
- * const textToCopy = '0x123...';
247
- *
248
- * return (
249
- * <button onClick={() => copy(textToCopy)}>
250
- * {isCopied ? 'Copied!' : 'Copy Address'}
251
- * </button>
252
- * );
357
+ * ```tsx
358
+ * import { useCopyToClipboard } from '@tuwaio/nova-core';
359
+ *
360
+ * export function CopyAddress({ address }: { address: string }) {
361
+ * const { isCopied, copy } = useCopyToClipboard();
362
+ *
363
+ * const handleClick = async () => {
364
+ * const result = await copy(address);
365
+ * if (!result.copied) console.warn(result.error.message);
366
+ * };
367
+ *
368
+ * return (
369
+ * <button type="button" onClick={handleClick}>
370
+ * {isCopied ? 'Copied!' : 'Copy address'}
371
+ * </button>
372
+ * );
253
373
  * }
374
+ * ```
254
375
  */
255
- declare function useCopyToClipboard(timeout?: number): {
256
- isCopied: boolean;
257
- copy: (text: string) => Promise<void>;
258
- error: Error | null;
259
- };
376
+ declare function useCopyToClipboard(timeout?: number): UseCopyToClipboardResult;
260
377
 
261
378
  /**
262
379
  * A custom hook to detect if a media query matches the current screen dimensions.
263
- * Handles SSR gracefully.
264
- * @param {string} query - The media query string (e.g., '(max-width: 767px)').
265
- * @returns {boolean} Whether the query matches or not.
380
+ * Returns `false` on the server. In the browser it checks the query again on every `resize` event of `window`
381
+ * (a listener that is removed on unmount).
382
+ *
383
+ * @param query - The media query string (e.g., '(max-width: 767px)').
384
+ * @returns Whether the query matches.
266
385
  */
267
386
  declare function useMediaQuery(query: string): boolean;
268
387
 
388
+ /**
389
+ * Classes of the standard secondary button of Nova (Tailwind utilities with the `novacore:` prefix, styled with the
390
+ * `--tuwa-standart-button-*` variables). The connect modal uses them for its buttons.
391
+ */
269
392
  declare const standardButtonClasses = "novacore:cursor-pointer novacore:rounded-[var(--tuwa-rounded-corners)] novacore:bg-[var(--tuwa-standart-button-bg)] novacore:px-3 novacore:py-2 novacore:flex novacore:items-center novacore:gap-1 novacore:text-sm novacore:font-mono novacore:font-semibold novacore:text-[var(--tuwa-text-primary)] novacore:transition-colors novacore:hover:bg-[var(--tuwa-standart-button-hover)] novacore:disabled:cursor-not-allowed novacore:disabled:opacity-50 novacore:min-h-[36px]";
270
393
 
271
394
  /**
@@ -334,22 +457,24 @@ interface ChainInfo {
334
457
  * For string IDs with environment suffixes (like "solana:devnet"),
335
458
  * the suffix is appended to the name if it's a known dev/test environment.
336
459
  *
460
+ * The networks are looked up in the metadata of `@web3icons/common`.
461
+ *
337
462
  * @param chainId - Chain identifier (number for EVM, string for non-EVM)
338
- * @returns Chain information object with name, id, and original chainId
463
+ * @returns The network name, id and icon file path, and the original `chainId`; `'Unknown'`/`'unknown'` when the
464
+ * network is not listed.
339
465
  *
340
466
  * @example
341
467
  * ```ts
342
- * // EVM network
343
- * getChainName(1)
344
- * // → { name: "Ethereum", id: "ethereum", chainId: 1 }
468
+ * import { getChainName } from '@tuwaio/nova-core';
469
+ *
470
+ * getChainName(1);
471
+ * // → { name: 'Ethereum', id: 'ethereum', filePath: 'ethereum', chainId: 1 }
345
472
  *
346
- * // Solana devnet
347
- * getChainName("solana:devnet")
348
- * // → { name: "Solana Devnet", id: "solana", chainId: "solana:devnet" }
473
+ * getChainName('solana:devnet');
474
+ * // → { name: 'Solana Devnet', id: 'solana', filePath: 'solana', chainId: 'solana:devnet' }
349
475
  *
350
- * // Unknown network
351
- * getChainName(999999)
352
- * // → { name: "Unknown", id: "unknown", chainId: 999999 }
476
+ * getChainName(999999);
477
+ * // → { name: 'Unknown', id: 'unknown', filePath: 'unknown', chainId: 999999 }
353
478
  * ```
354
479
  */
355
480
  declare function getChainName(chainId: number | string): ChainInfo;
@@ -366,7 +491,7 @@ declare function getChainName(chainId: number | string): ChainInfo;
366
491
  declare function isSolanaDev(chainId: number | string): boolean;
367
492
 
368
493
  /**
369
- * @fileoverview Utility function to determine if the current environment supports touch input.
494
+ * @file Utility function to determine if the current environment supports touch input.
370
495
  * This is safe to use in Next.js applications as it checks for the `window` object existence.
371
496
  */
372
497
  /**
@@ -379,14 +504,16 @@ declare function isSolanaDev(chainId: number | string): boolean;
379
504
  *
380
505
  * This function is safe for server-side rendering (SSR) environments like Next.js.
381
506
  *
382
- * @param {number} [maxWidth=1200] The maximum screen width (in pixels) for a device to be considered 'touch' (default is 1200).
383
- * @returns {boolean} Returns true if the environment is determined to support touch input AND is within the width limit, otherwise false.
507
+ * @param {number} [maxWidth=1200] The maximum screen width (in pixels) for a device to be considered 'touch' (default
508
+ * is 1200).
509
+ * @returns {boolean} Returns true if the environment is determined to support touch input AND is within the width
510
+ * limit, otherwise false.
384
511
  */
385
512
  declare function isTouchDevice(maxWidth?: number): boolean;
386
513
 
387
514
  /**
388
- * Resolves a CSS variable to its computed value.
389
- * Returns the original value if it's not a CSS variable.
515
+ * Resolves a CSS variable to its computed value on `document.documentElement`.
516
+ * Returns the original value if it's not a CSS variable. Call it in the browser: it reads `getComputedStyle`.
390
517
  *
391
518
  * @param value - Color value, potentially a CSS variable like `var(--my-color)`
392
519
  * @returns Resolved color value (e.g., `#ff0000`) or original if not a variable
@@ -394,20 +521,20 @@ declare function isTouchDevice(maxWidth?: number): boolean;
394
521
  declare function resolveCssVariable(value: string): string;
395
522
  /**
396
523
  * Modifies the fill attribute of the first `<path>` element in an SVG string.
397
- * Uses DOMParser for safe XML manipulation.
398
- * Automatically resolves CSS variables (e.g., `var(--color)`) to their computed values.
524
+ * Uses DOMParser for safe XML manipulation, so call it in the browser.
525
+ * Automatically resolves CSS variables (e.g., `var(--color)`) to their computed values with {@link resolveCssVariable}.
399
526
  *
400
527
  * @param svgString - The original SVG markup
401
528
  * @param fillColor - The color to apply (supports CSS variables)
402
- * @returns Modified SVG string
529
+ * @returns Modified SVG string, or the original string (with a console warning) when it cannot be parsed
403
530
  */
404
531
  declare function applyFirstPathFill(svgString: string, fillColor: string): string;
405
532
  /**
406
533
  * Encodes an SVG string to a base64 data URL.
407
534
  *
408
535
  * @param svgString - The SVG markup
409
- * @param firstPathFill - Optional fill color to apply to the first path
410
- * @returns Base64-encoded data URL
536
+ * @param firstPathFill - Optional fill color to apply to the first path, with {@link applyFirstPathFill} (browser only)
537
+ * @returns Base64-encoded data URL (`data:image/svg+xml;base64,…`)
411
538
  */
412
539
  declare function svgToBase64(svgString: string, firstPathFill?: string): string;
413
540
  /**
@@ -421,14 +548,10 @@ declare function svgToBase64(svgString: string, firstPathFill?: string): string;
421
548
  *
422
549
  * @example
423
550
  * ```ts
424
- * formatIconNameForGithub("Wallet Connect")
425
- * // → "wallet-connect.svg"
426
- *
427
- * formatIconNameForGithub("MetaMask")
428
- * // → "metamask.svg"
551
+ * import { formatIconNameForGithub } from '@tuwaio/nova-core';
429
552
  *
430
- * formatIconNameForGithub("coinbase")
431
- * // → "coinbase.svg"
553
+ * formatIconNameForGithub('Wallet Connect'); // → 'wallet-connect.svg'
554
+ * formatIconNameForGithub('MetaMask'); // → 'metamask.svg'
432
555
  * ```
433
556
  */
434
557
  declare const formatIconNameForGithub: (name: string) => string;
@@ -453,4 +576,4 @@ declare const formatIconNameForGithub: (name: string) => string;
453
576
  */
454
577
  declare function textCenterEllipsis(str: string | undefined | null, from: number, to: number): string;
455
578
 
456
- export { type ChainInfo, ChevronArrowWithAnim, CloseIcon, Dialog, DialogClose, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogOverlay, DialogPortal, DialogTitle, DialogTrigger, FallbackIcon, type FallbackIconProps, GithubFallbackIcon, NetworkIcon, StarsBackground, SvgImg, type SvgImgProps, SvgToImg, ToastCloseButton, type ToastCloseButtonProps, WalletIcon, applyFirstPathFill, cn, deepMerge, formatIconNameForGithub, getChainName, isSolanaDev, isTouchDevice, resolveCssVariable, standardButtonClasses, svgToBase64, textCenterEllipsis, useCopyToClipboard, useMediaQuery };
579
+ export { type ChainInfo, ChevronArrowWithAnim, CloseIcon, type CopyToClipboardResult, Dialog, DialogClose, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogOverlay, DialogPortal, DialogTitle, DialogTrigger, FallbackIcon, type FallbackIconProps, GithubFallbackIcon, type GithubFallbackIconProps, NetworkIcon, type NetworkIconProps, StarsBackground, SvgImg, type SvgImgProps, SvgToImg, type SvgToImgProps, ToastCloseButton, type ToastCloseButtonProps, type UseCopyToClipboardResult, WalletIcon, type WalletIconProps, applyFirstPathFill, cn, deepMerge, formatIconNameForGithub, getChainName, isSolanaDev, isTouchDevice, resolveCssVariable, standardButtonClasses, svgToBase64, textCenterEllipsis, useCopyToClipboard, useMediaQuery };
package/dist/index.js CHANGED
@@ -1,4 +1,4 @@
1
- import {motion,AnimatePresence}from'framer-motion';import {clsx}from'clsx';import {twMerge}from'tailwind-merge';import {networks,wallets}from'@web3icons/common/metadata';import {jsxs,jsx,Fragment}from'react/jsx-runtime';import*as d from'react';import {lazy,useState,useEffect,useCallback,Suspense,useMemo}from'react';import*as c from'@radix-ui/react-dialog';var _o="novacore:cursor-pointer novacore:rounded-[var(--tuwa-rounded-corners)] novacore:bg-[var(--tuwa-standart-button-bg)] novacore:px-3 novacore:py-2 novacore:flex novacore:items-center novacore:gap-1 novacore:text-sm novacore:font-mono novacore:font-semibold novacore:text-[var(--tuwa-text-primary)] novacore:transition-colors novacore:hover:bg-[var(--tuwa-standart-button-hover)] novacore:disabled:cursor-not-allowed novacore:disabled:opacity-50 novacore:min-h-[36px]";function s(...o){return twMerge(clsx(o))}var y=o=>typeof o=="object"&&o!==null&&!Array.isArray(o);function J(o,e){let t={...o};return y(o)&&y(e)&&Object.keys(e).forEach(n=>{let r=o[n],a=e[n];y(r)&&y(a)?t[n]=J(r,a):t[n]=a;}),t}function x(o){if(typeof o!="string")return false;let e=o.toLowerCase();return e.includes("solana")&&(e.includes("devnet")||e.includes("testnet"))}var M="Unknown";function oo(o){return o.charAt(0).toUpperCase()+o.slice(1).toLowerCase()}function W(o){let e={name:M,id:M.toLowerCase(),filePath:M.toLowerCase(),chainId:o};if(typeof o=="number"){let i=networks.find(l=>l.chainId===o);return i?{name:i.name,id:i.id,filePath:i.filePath?.split(":")[1],chainId:o}:e}let[t,n]=o?o.split(":"):[o],r=networks.find(i=>i.id===t);return r?{name:n&&x(o)?`${r.name} ${oo(n)}`:r.name,id:r.id,filePath:r.filePath?.split(":")[1],chainId:o}:e}function G(o=1200){if(typeof window>"u")return false;let e="ontouchstart"in window,t=navigator.maxTouchPoints>0,n=false;window.matchMedia&&(n=window.matchMedia("(pointer: coarse)").matches);let r=e||t||n,a=window.innerWidth<=o;return r&&a}function eo(o){if(!o.startsWith("var("))return o;let e=o.match(/var\(\s*(--[\w-]+)/);if(!e)return o;let t=e[1];return getComputedStyle(document.documentElement).getPropertyValue(t).trim()||o}function to(o,e){let t=eo(e),r=new DOMParser().parseFromString(o,"image/svg+xml");if(r.querySelector("parsererror"))return console.warn("SVG parse error, returning original"),o;let i=r.querySelector("path");return i&&i.setAttribute("fill",t),new XMLSerializer().serializeToString(r.documentElement)}function N(o,e){let t=o;return e&&(t=to(t,e)),`data:image/svg+xml;base64,${btoa(unescape(encodeURIComponent(t)))}`}var S=o=>`${o.replace(/\s+/g,"-").toLowerCase()}.svg`;function te(o,e,t){if(!o)return "";if(o.length<=e+t)return o;let n=o.slice(0,e),r=o.slice(o.length-t);return `${n}...${r}`}function ve({className:o,strokeWidth:e,isOpen:t}){return jsxs("svg",{xmlns:"http://www.w3.org/2000/svg",fill:"none",viewBox:"0 0 24 24",strokeWidth:e??2,stroke:"currentColor",className:s("novacore:w-4 novacore:h-4 novacore:text-[var(--tuwa-text-secondary)]",o),children:[jsx(AnimatePresence,{children:t&&jsx(motion.path,{strokeLinecap:"round",strokeLinejoin:"round",d:"m4.5 15.75 7.5-7.5 7.5 7.5",variants:{hidden:{translateY:3,scaleY:.8,opacity:0},visible:{translateY:0,scaleY:1,opacity:1}},initial:"hidden",animate:"visible",transition:{duration:.4}})}),jsx(AnimatePresence,{children:!t&&jsx(motion.path,{strokeLinecap:"round",strokeLinejoin:"round",d:"m19.5 8.25-7.5 7.5-7.5-7.5",className:"novacore:relative",variants:{hidden:{translateY:-3,scaleY:.8,opacity:0},visible:{translateY:0,scaleY:1,opacity:1}},initial:"hidden",animate:"visible",transition:{duration:.4}})})]})}var no=d.forwardRef(({className:o,...e},t)=>jsxs("svg",{ref:t,xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round",className:s("novacore:h-5 novacore:w-5 novacore:text-[var(--tuwa-text-primary)] novacore:transition-colors",o),...e,children:[jsx("path",{d:"M18 6 6 18"}),jsx("path",{d:"m6 6 12 12"})]}));no.displayName="CloseIcon";var io="novacore:flex novacore:items-center novacore:justify-center novacore:w-full novacore:h-full novacore:rounded-full novacore:text-[var(--tuwa-text-secondary)] novacore:bg-[var(--tuwa-bg-muted)]",p=({animate:o=false,content:e="",className:t})=>jsx("div",{className:s(io,"Nova_Web3_Icon",t,{"novacore:animate-pulse":o}),children:e});function C({src:o,alt:e,...t}){return jsx("img",{...t,src:o,alt:e??"",draggable:false,onDragStart:n=>n.preventDefault(),style:{outline:"none",pointerEvents:"none"}})}var mo="https://raw.githubusercontent.com/0xa3k5/web3icons/refs/heads/main/raw-svgs",L=new Map;function P({githubSrc:o,className:e,alt:t,firstPathFill:n,...r}){let a=`${o}|${n??""}`,i=L.get(a),[l,u]=useState(null),[w,b]=useState("idle"),T=i||l,g=i?"success":w;return useEffect(()=>{let D=true;return L.has(a)?void 0:((async()=>{b("loading");try{let R=await fetch(`${mo}/${o}`);if(!R.ok)throw new Error(`Failed to load icon: ${R.status}`);let X=await R.text();if(D){let V=N(X,n);L.set(a,V),u(V),b("success");}}catch{D&&b("error");}})(),()=>{D=false;})},[o,n,a]),g==="loading"||g==="idle"?jsx(p,{animate:true,className:e}):g==="success"&&T?jsx(C,{...r,src:T,alt:t,className:e}):jsx(p,{content:"?",className:e})}var Ve=c.Root,ze=c.Trigger,uo=c.Portal,We=c.Close,fo={initial:{opacity:0,scale:.9,y:20},animate:{opacity:1,scale:1,y:0},exit:{opacity:0,scale:.9,transition:{duration:.2}}},po={initial:{opacity:0,y:"100%"},animate:{opacity:1,y:"0%"},exit:{opacity:0,y:"100%",transition:{duration:.2}}},vo={initial:{opacity:0},animate:{opacity:1},exit:{opacity:0}},Y=({className:o,backdropAnimation:e})=>(d.useEffect(()=>(typeof window<"u"&&window.document.body.classList.add("NovaModalOpen"),()=>{typeof window<"u"&&window.document.body.classList.remove("NovaModalOpen");}),[]),jsx(AnimatePresence,{children:jsx(motion.div,{variants:e??vo,transition:{duration:.2,ease:"easeInOut"},animate:"animate",initial:"initial",exit:"exit",className:"novacore:relative novacore:overflow-hidden",children:jsx("div",{className:s("novacore:fixed novacore:inset-0 novacore:z-50 novacore:bg-black/55 novacore:backdrop-blur-sm novacore:backdrop-saturate-150",o)})})}));Y.displayName=c.Overlay.displayName;var go=d.forwardRef(({className:o,children:e,modalAnimation:t,backdropAnimation:n,...r},a)=>{let[i,l]=d.useState(false);d.useEffect(()=>{l(G());},[]);let u=t??(i?po:fo);return jsxs(uo,{children:[jsx(Y,{backdropAnimation:n}),jsx(c.Content,{"aria-describedby":"tuwa:modal-content",ref:a,className:s("NovaNoScrolling novacore:fixed novacore:bottom-0 novacore:left-0 novacore:p-0 novacore:sm:bottom-auto novacore:sm:left-[50%] novacore:sm:top-[50%] novacore:sm:translate-x-[-50%] novacore:sm:translate-y-[-50%] novacore:z-50 novacore:sm:p-4 novacore:outline-none",o),...r,children:jsx(motion.div,{layout:true,className:"NovaNoScrolling novacore:relative novacore:overflow-hidden",transition:{layout:{duration:.2,ease:[.1,.1,.2,1]}},children:jsx(AnimatePresence,{children:jsx(motion.div,{variants:u,transition:{duration:.2,ease:"easeInOut"},animate:"animate",initial:"initial",exit:"exit",className:"NovaNoScrolling novacore:relative novacore:overflow-hidden novacore:bg-[var(--tuwa-bg-primary)] novacore:border novacore:border-[var(--tuwa-border-primary)] novacore:rounded-t-[var(--tuwa-rounded-corners)] novacore:sm:rounded-[var(--tuwa-rounded-corners)]",children:jsx("div",{className:s("NovaNoScrolling NovaDialogContent__elements novacore:relative novacore:flex novacore:max-h-[100dvh] novacore:w-full novacore:flex-col novacore:overflow-y-auto","novacore:[transform:translateZ(0)] novacore:[backface-visibility:hidden]"),children:e})})})})})]})});go.displayName=c.Content.displayName;var wo=({className:o,...e})=>jsx("div",{"aria-describedby":"tuwa:modal-header",className:s("novacore:sticky novacore:flex novacore:top-0 novacore:z-11 novacore:w-full novacore:flex-row novacore:items-center novacore:justify-between","novacore:border-b novacore:border-[var(--tuwa-border-primary)] novacore:bg-[var(--tuwa-bg-primary)] novacore:p-4",o),...e});wo.displayName="DialogHeader";var bo=({className:o,...e})=>jsx("div",{"aria-describedby":"tuwa:modal-footer",className:s("novacore:flex novacore:flex-col-reverse novacore:sm:flex-row novacore:sm:justify-end novacore:sm:space-x-2",o),...e});bo.displayName="DialogFooter";var ho=d.forwardRef(({className:o,...e},t)=>jsx(c.Title,{ref:t,"aria-describedby":"tuwa:modal-title",className:s("novacore:text-lg novacore:font-bold novacore:leading-none novacore:tracking-tight novacore:text-[var(--tuwa-text-primary)] novacore:m-0 novacore:font-mono",o),...e}));ho.displayName=c.Title.displayName;var yo=d.forwardRef(({className:o,...e},t)=>jsx(c.Description,{"aria-describedby":"tuwa:modal-description",ref:t,className:s("novacore:text-sm novacore:text-[var(--tuwa-text-secondary)]",o),...e}));yo.displayName=c.Description.displayName;function h({children:o,iconId:e,alt:t,firstPathFill:n,...r}){let[a,i]=useState(null),l=useCallback(u=>{if(u){let w=N(u.outerHTML,n);i({id:e,src:w});}},[e,n]);return a&&a.id===e?jsx(C,{...r,src:a.src,alt:t}):jsx(Fragment,{children:o(l)})}var K=lazy(()=>import('@web3icons/react/dynamic').then(o=>({default:o.NetworkIcon}))),Io="var(--tuwa-testnet-icons)";function Je({chainId:o,variant:e="background",className:t}){let n=W(o),r=typeof o=="string",a=r?o.split(":")[0].toLowerCase():o,l=r&&x(o)||n.name.toLowerCase().includes("testnet")?Io:void 0,u=s("novacore:w-full novacore:h-full novacore:rounded-full",t),w=typeof a=="string"?a:n.filePath,b=`networks/${e}/${S(w)}`;return n.name==="Unknown"?typeof o=="number"?jsx(p,{content:"?",className:t}):jsx(P,{githubSrc:b,className:u,firstPathFill:l}):jsx(Suspense,{fallback:jsx(p,{animate:true,className:t}),children:jsx(h,{iconId:`${o}-${e}`,className:u,firstPathFill:l,children:g=>typeof a=="string"?jsx(K,{ref:g,id:a,variant:e}):jsx(K,{ref:g,chainId:a,variant:e})})})}function rt({starsCount:o}){let[e,t]=useState(false);useEffect(()=>t(true),[]);let n=useMemo(()=>e?Array.from({length:o??200}).map(()=>({x:Math.random()*window.innerWidth,y:Math.random()*window.innerHeight,r:Math.random()*1+.5,isSupernova:Math.random()<.1,delay:Math.random()*10,duration:5+Math.random()*5})):[],[e]);return jsx("div",{className:"novacore:absolute novacore:inset-0 novacore:z-1 novacore:h-full novacore:w-full novacore:overflow-hidden",children:jsxs("svg",{width:"100%",height:"100%",xmlns:"http://www.w3.org/2000/svg",children:[jsx("defs",{children:jsx("style",{children:`
1
+ import {motion,AnimatePresence}from'framer-motion';import {clsx}from'clsx';import {twMerge}from'tailwind-merge';import {networks,wallets}from'@web3icons/common/metadata';import {jsxs,jsx,Fragment}from'react/jsx-runtime';import*as d from'react';import {lazy,useState,useEffect,useCallback,Suspense,useMemo}from'react';import*as c from'@radix-ui/react-dialog';var Uo="novacore:cursor-pointer novacore:rounded-[var(--tuwa-rounded-corners)] novacore:bg-[var(--tuwa-standart-button-bg)] novacore:px-3 novacore:py-2 novacore:flex novacore:items-center novacore:gap-1 novacore:text-sm novacore:font-mono novacore:font-semibold novacore:text-[var(--tuwa-text-primary)] novacore:transition-colors novacore:hover:bg-[var(--tuwa-standart-button-hover)] novacore:disabled:cursor-not-allowed novacore:disabled:opacity-50 novacore:min-h-[36px]";function s(...o){return twMerge(clsx(o))}var y=o=>typeof o=="object"&&o!==null&&!Array.isArray(o);function J(o,e){let t={...o};return y(o)&&y(e)&&Object.keys(e).forEach(n=>{let r=o[n],a=e[n];y(r)&&y(a)?t[n]=J(r,a):t[n]=a;}),t}function x(o){if(typeof o!="string")return false;let e=o.toLowerCase();return e.includes("solana")&&(e.includes("devnet")||e.includes("testnet"))}var M="Unknown";function oo(o){return o.charAt(0).toUpperCase()+o.slice(1).toLowerCase()}function W(o){let e={name:M,id:M.toLowerCase(),filePath:M.toLowerCase(),chainId:o};if(typeof o=="number"){let i=networks.find(l=>l.chainId===o);return i?{name:i.name,id:i.id,filePath:i.filePath?.split(":")[1],chainId:o}:e}let[t,n]=o?o.split(":"):[o],r=networks.find(i=>i.id===t);return r?{name:n&&x(o)?`${r.name} ${oo(n)}`:r.name,id:r.id,filePath:r.filePath?.split(":")[1],chainId:o}:e}function G(o=1200){if(typeof window>"u")return false;let e="ontouchstart"in window,t=navigator.maxTouchPoints>0,n=false;window.matchMedia&&(n=window.matchMedia("(pointer: coarse)").matches);let r=e||t||n,a=window.innerWidth<=o;return r&&a}function eo(o){if(!o.startsWith("var("))return o;let e=o.match(/var\(\s*(--[\w-]+)/);if(!e)return o;let t=e[1];return getComputedStyle(document.documentElement).getPropertyValue(t).trim()||o}function to(o,e){let t=eo(e),r=new DOMParser().parseFromString(o,"image/svg+xml");if(r.querySelector("parsererror"))return console.warn("SVG parse error, returning original"),o;let i=r.querySelector("path");return i&&i.setAttribute("fill",t),new XMLSerializer().serializeToString(r.documentElement)}function N(o,e){let t=o;return e&&(t=to(t,e)),`data:image/svg+xml;base64,${btoa(unescape(encodeURIComponent(t)))}`}var C=o=>`${o.replace(/\s+/g,"-").toLowerCase()}.svg`;function te(o,e,t){if(!o)return "";if(o.length<=e+t)return o;let n=o.slice(0,e),r=o.slice(o.length-t);return `${n}...${r}`}function ve({className:o,strokeWidth:e,isOpen:t}){return jsxs("svg",{xmlns:"http://www.w3.org/2000/svg",fill:"none",viewBox:"0 0 24 24",strokeWidth:e??2,stroke:"currentColor",className:s("novacore:w-4 novacore:h-4 novacore:text-[var(--tuwa-text-secondary)]",o),children:[jsx(AnimatePresence,{children:t&&jsx(motion.path,{strokeLinecap:"round",strokeLinejoin:"round",d:"m4.5 15.75 7.5-7.5 7.5 7.5",variants:{hidden:{translateY:3,scaleY:.8,opacity:0},visible:{translateY:0,scaleY:1,opacity:1}},initial:"hidden",animate:"visible",transition:{duration:.4}})}),jsx(AnimatePresence,{children:!t&&jsx(motion.path,{strokeLinecap:"round",strokeLinejoin:"round",d:"m19.5 8.25-7.5 7.5-7.5-7.5",className:"novacore:relative",variants:{hidden:{translateY:-3,scaleY:.8,opacity:0},visible:{translateY:0,scaleY:1,opacity:1}},initial:"hidden",animate:"visible",transition:{duration:.4}})})]})}var no=d.forwardRef(({className:o,...e},t)=>jsxs("svg",{ref:t,xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round",className:s("novacore:h-5 novacore:w-5 novacore:text-[var(--tuwa-text-primary)] novacore:transition-colors",o),...e,children:[jsx("path",{d:"M18 6 6 18"}),jsx("path",{d:"m6 6 12 12"})]}));no.displayName="CloseIcon";var io="novacore:flex novacore:items-center novacore:justify-center novacore:w-full novacore:h-full novacore:rounded-full novacore:text-[var(--tuwa-text-secondary)] novacore:bg-[var(--tuwa-bg-muted)]",f=({animate:o=false,content:e="",className:t})=>jsx("div",{className:s(io,"Nova_Web3_Icon",t,{"novacore:animate-pulse":o}),children:e});function k({src:o,alt:e,...t}){return jsx("img",{...t,src:o,alt:e??"",draggable:false,onDragStart:n=>n.preventDefault(),style:{outline:"none",pointerEvents:"none"}})}var mo="https://raw.githubusercontent.com/0xa3k5/web3icons/refs/heads/main/raw-svgs",L=new Map;function P({githubSrc:o,className:e,alt:t,firstPathFill:n,...r}){let a=`${o}|${n??""}`,i=L.get(a),[l,m]=useState(null),[w,b]=useState("idle"),I=i||l,g=i?"success":w;return useEffect(()=>{let R=true;return L.has(a)?void 0:((async()=>{b("loading");try{let D=await fetch(`${mo}/${o}`);if(!D.ok)throw new Error(`Failed to load icon: ${D.status}`);let X=await D.text();if(R){let V=N(X,n);L.set(a,V),m(V),b("success");}}catch{R&&b("error");}})(),()=>{R=false;})},[o,n,a]),g==="loading"||g==="idle"?jsx(f,{animate:true,className:e}):g==="success"&&I?jsx(k,{...r,src:I,alt:t,className:e}):jsx(f,{content:"?",className:e})}var Ve=c.Root,ze=c.Trigger,uo=c.Portal,We=c.Close,po={initial:{opacity:0,scale:.9,y:20},animate:{opacity:1,scale:1,y:0},exit:{opacity:0,scale:.9,transition:{duration:.2}}},fo={initial:{opacity:0,y:"100%"},animate:{opacity:1,y:"0%"},exit:{opacity:0,y:"100%",transition:{duration:.2}}},vo={initial:{opacity:0},animate:{opacity:1},exit:{opacity:0}},Y=({className:o,backdropAnimation:e})=>(d.useEffect(()=>(typeof window<"u"&&window.document.body.classList.add("NovaModalOpen"),()=>{typeof window<"u"&&window.document.body.classList.remove("NovaModalOpen");}),[]),jsx(AnimatePresence,{children:jsx(motion.div,{variants:e??vo,transition:{duration:.2,ease:"easeInOut"},animate:"animate",initial:"initial",exit:"exit",className:"novacore:relative novacore:overflow-hidden",children:jsx("div",{className:s("novacore:fixed novacore:inset-0 novacore:z-50 novacore:bg-black/55 novacore:backdrop-blur-sm novacore:backdrop-saturate-150",o)})})}));Y.displayName=c.Overlay.displayName;var go=d.forwardRef(({className:o,children:e,modalAnimation:t,backdropAnimation:n,...r},a)=>{let[i,l]=d.useState(false);d.useEffect(()=>{l(G());},[]);let m=t??(i?fo:po);return jsxs(uo,{children:[jsx(Y,{backdropAnimation:n}),jsx(c.Content,{"aria-describedby":"tuwa:modal-content",ref:a,className:s("NovaNoScrolling novacore:fixed novacore:bottom-0 novacore:left-0 novacore:p-0 novacore:sm:bottom-auto novacore:sm:left-[50%] novacore:sm:top-[50%] novacore:sm:translate-x-[-50%] novacore:sm:translate-y-[-50%] novacore:z-50 novacore:sm:p-4 novacore:outline-none",o),...r,children:jsx(motion.div,{layout:true,className:"NovaNoScrolling novacore:relative novacore:overflow-hidden",transition:{layout:{duration:.2,ease:[.1,.1,.2,1]}},children:jsx(AnimatePresence,{children:jsx(motion.div,{variants:m,transition:{duration:.2,ease:"easeInOut"},animate:"animate",initial:"initial",exit:"exit",className:"NovaNoScrolling novacore:relative novacore:overflow-hidden novacore:bg-[var(--tuwa-bg-primary)] novacore:border novacore:border-[var(--tuwa-border-primary)] novacore:rounded-t-[var(--tuwa-rounded-corners)] novacore:sm:rounded-[var(--tuwa-rounded-corners)]",children:jsx("div",{className:s("NovaNoScrolling NovaDialogContent__elements novacore:relative novacore:flex novacore:max-h-[100dvh] novacore:w-full novacore:flex-col novacore:overflow-y-auto","novacore:[transform:translateZ(0)] novacore:[backface-visibility:hidden]"),children:e})})})})})]})});go.displayName=c.Content.displayName;var wo=({className:o,...e})=>jsx("div",{"aria-describedby":"tuwa:modal-header",className:s("novacore:sticky novacore:flex novacore:top-0 novacore:z-11 novacore:w-full novacore:flex-row novacore:items-center novacore:justify-between","novacore:border-b novacore:border-[var(--tuwa-border-primary)] novacore:bg-[var(--tuwa-bg-primary)] novacore:p-4",o),...e});wo.displayName="DialogHeader";var bo=({className:o,...e})=>jsx("div",{"aria-describedby":"tuwa:modal-footer",className:s("novacore:flex novacore:flex-col-reverse novacore:sm:flex-row novacore:sm:justify-end novacore:sm:space-x-2",o),...e});bo.displayName="DialogFooter";var ho=d.forwardRef(({className:o,...e},t)=>jsx(c.Title,{ref:t,"aria-describedby":"tuwa:modal-title",className:s("novacore:text-lg novacore:font-bold novacore:leading-none novacore:tracking-tight novacore:text-[var(--tuwa-text-primary)] novacore:m-0 novacore:font-mono",o),...e}));ho.displayName=c.Title.displayName;var yo=d.forwardRef(({className:o,...e},t)=>jsx(c.Description,{"aria-describedby":"tuwa:modal-description",ref:t,className:s("novacore:text-sm novacore:text-[var(--tuwa-text-secondary)]",o),...e}));yo.displayName=c.Description.displayName;function h({children:o,iconId:e,alt:t,firstPathFill:n,...r}){let[a,i]=useState(null),l=useCallback(m=>{if(m){let w=N(m.outerHTML,n);i({id:e,src:w});}},[e,n]);return a&&a.id===e?jsx(k,{...r,src:a.src,alt:t}):jsx(Fragment,{children:o(l)})}var K=lazy(()=>import('@web3icons/react/dynamic').then(o=>({default:o.NetworkIcon}))),To="var(--tuwa-testnet-icons)";function Je({chainId:o,variant:e="background",className:t}){let n=W(o),r=typeof o=="string",a=r?o.split(":")[0].toLowerCase():o,l=r&&x(o)||n.name.toLowerCase().includes("testnet")?To:void 0,m=s("novacore:w-full novacore:h-full novacore:rounded-full",t),w=typeof a=="string"?a:n.filePath,b=`networks/${e}/${C(w)}`;return n.name==="Unknown"?typeof o=="number"?jsx(f,{content:"?",className:t}):jsx(P,{githubSrc:b,className:m,firstPathFill:l}):jsx(Suspense,{fallback:jsx(f,{animate:true,className:t}),children:jsx(h,{iconId:`${o}-${e}`,className:m,firstPathFill:l,children:g=>typeof a=="string"?jsx(K,{ref:g,id:a,variant:e}):jsx(K,{ref:g,chainId:a,variant:e})})})}function rt({starsCount:o}){let[e,t]=useState(false);useEffect(()=>t(true),[]);let n=useMemo(()=>e?Array.from({length:o??200}).map(()=>({x:Math.random()*window.innerWidth,y:Math.random()*window.innerHeight,r:Math.random()*1+.5,isSupernova:Math.random()<.1,delay:Math.random()*10,duration:5+Math.random()*5})):[],[e]);return jsx("div",{className:"novacore:absolute novacore:inset-0 novacore:z-1 novacore:h-full novacore:w-full novacore:overflow-hidden",children:jsxs("svg",{width:"100%",height:"100%",xmlns:"http://www.w3.org/2000/svg",children:[jsx("defs",{children:jsx("style",{children:`
2
2
  /* Pulse animation now includes scale for a more organic feel. */
3
3
  @keyframes pulse {
4
4
  0%, 100% {
@@ -44,5 +44,5 @@ import {motion,AnimatePresence}from'framer-motion';import {clsx}from'clsx';impor
44
44
  transform-origin: center;
45
45
  stroke-width: 2;
46
46
  }
47
- `})}),n.map((r,a)=>jsx("circle",{cx:r.x,cy:r.y,r:r.r,fill:"rgba(var(--tuwa-bg-primary), 0.7)",className:r.isSupernova?"supernova":"pulsar",style:{animationDelay:`${r.delay}s`,animationDuration:`${r.duration}s`}},a))]})})}function st({closeToast:o,ariaLabel:e="Close toast notification",title:t="Close toast notification",className:n,iconClassName:r}){return jsx("button",{type:"button",onClick:o,"aria-label":e,title:t,className:s("novacore:absolute novacore:top-2 novacore:right-2 novacore:cursor-pointer novacore:rounded-[var(--tuwa-rounded-corners)] novacore:p-1","novacore:text-[var(--tuwa-text-tertiary)] novacore:transition-colors","novacore:hover:bg-[var(--tuwa-bg-muted)] novacore:hover:text-[var(--tuwa-text-primary)]",n),children:jsx("svg",{xmlns:"http://www.w3.org/2000/svg",fill:"none",viewBox:"0 0 24 24",strokeWidth:1.5,stroke:"currentColor",className:s("novacore:h-5 novacore:w-5",r),children:jsx("path",{strokeLinecap:"round",strokeLinejoin:"round",d:"M6 18 18 6M6 6l12 12"})})})}var Fo=lazy(()=>import('@web3icons/react/dynamic').then(o=>({default:o.WalletIcon}))),Vo={walletconnect:"wallet-connect"};function zo(o){return wallets.some(e=>e.id===o||e.name?.toLowerCase()===o)}var Wo=({className:o,ref:e})=>jsxs("svg",{ref:e,className:o,fill:"none",viewBox:"0 0 32 32",xmlns:"http://www.w3.org/2000/svg",children:[jsx("path",{fill:"#fff",fillRule:"evenodd",d:"M16 0c8.84 0 16 7.16 16 16s-7.16 16-16 16S0 24.84 0 16 7.16 0 16 0",clipRule:"evenodd"}),jsx("path",{fill:"#000",fillRule:"evenodd",d:"M16.54 2.01h1.53c.5.09.99.23 1.48.42.21.25.19.48-.05.69q-.195.045-.39 0c-1.86-.65-3.55-.35-5.07.89 2.39.7 3.84 2.27 4.36 4.7.12.85.08 1.68-.12 2.51.87 0 1.74 0 2.61-.02.39-.4.7-.85.94-1.35-.45-.45-.65-.99-.59-1.63-1.15.08-1.79-.44-1.92-1.58.14-1.12.78-1.67 1.92-1.63a.7.7 0 0 0-.12-.49l-.89-.89c-.02-.45.19-.6.62-.47.24.19.46.39.66.62.71-.79 1.5-.89 2.39-.32.44.42.62.94.54 1.55 1.49.02 2.11.76 1.85 2.22-.08.17-.17.34-.27.49.53.59.87 1.28 1.01 2.07.08 4.6.1 9.19.05 13.79-.19 1.58-1 2.71-2.44 3.37-.29.1-.59.2-.89.27H7.2c-1.31-.33-2.05-1.17-2.24-2.51-.03-5.24-.03-10.47 0-15.71.3-1.62 1.28-2.46 2.93-2.54 1.26-1.77 2.98-2.64 5.17-2.61.96-1.01 2.13-1.62 3.5-1.85zm6.11 1.87c.39-.03.7.12.91.44.06.39.09.79.1 1.18.02.12.07.21.17.27.41 0 .82.04 1.23.1.49.26.63.65.42 1.16-.07.14-.18.25-.32.32-.39.06-.79.09-1.18.1-.12.02-.21.07-.27.17l-.15 1.33c-.32.46-.72.55-1.21.27a.76.76 0 0 1-.27-.37c-.06-.41-.09-.82-.1-1.23a.35.35 0 0 0-.27-.17l-1.08-.05c-.46-.24-.62-.61-.47-1.11.14-.27.36-.43.66-.47l.99-.05s.09-.04.12-.07l.15-1.28q.18-.39.57-.54m-10.49.79c2.41-.09 4.12.94 5.15 3.1.44 1.12.48 2.25.12 3.4-.84.06-1.67.07-2.51.02.56-.68.52-1.32-.1-1.92-.26-.13-.54-.19-.84-.17.02-.95 0-1.91-.07-2.86-.21-.41-.55-.58-1.01-.52-.17.03-.31.09-.44.2-.72.92-1.43 1.85-2.14 2.78-.28.45-.29.91-.05 1.38q.225.3.57.42c.34.02.69.03 1.03.02v.69c-1.3.02-2.59 0-3.89-.05-.58-2.1-.08-3.88 1.53-5.34.79-.62 1.68-1 2.66-1.16zm.83 1.82c.07 0 .13.03.17.1l.05 3.05c.04.09.1.16.17.22l.89.05c.22.08.3.24.22.47q-.27.42-.57.81c-.43.02-.85.03-1.28.02 0-.41 0-.82-.02-1.23a.46.46 0 0 0-.17-.17l-1.28-.05c-.3-.1-.37-.29-.22-.57.7-.89 1.39-1.79 2.04-2.71zm-5.81.84h.2a6.1 6.1 0 0 0-.25 3.77c-.59-.13-1.01-.49-1.26-1.06-.36-1.29.08-2.19 1.31-2.71m17.98.83c.05 0 .1 0 .15.02q.825.855.96 2.04.045 1.305 0 2.61a3.76 3.76 0 0 0-2.54-1.55c-.61-.05-1.21-.08-1.82-.1.26-.31.48-.66.64-1.03 1.31.02 1.94-.62 1.87-1.95.26.02.5 0 .74-.05zM5.7 11.22c.41.4.91.65 1.48.76l16.06.05c1.42.13 2.38.87 2.88 2.19.07.24.12.49.15.74.03 2.86.03 5.71 0 8.57-.21 1.44-1 2.38-2.39 2.83-.24.05-.49.08-.74.1-1.26.02-2.53.03-3.79.02 0-1.33 0-2.66.02-3.99l1.55-1.55c1.42-.04 2.09-.78 1.99-2.19-.24-.88-.81-1.34-1.72-1.38-1.2.12-1.81.8-1.82 2.02l-1.92 1.92c-.08.11-.14.22-.2.34-.07 1.61-.1 3.22-.07 4.83h-.44c0-2.28 0-4.56-.02-6.85a1.8 1.8 0 0 0-.15-.34l-1.13-1.13c0-1.23-.61-1.92-1.82-2.07-1.29.17-1.87.91-1.72 2.22q.465 1.395 1.95 1.35l.71.71c0 .3.04.6.1.89.25.21.48.19.69-.05.03-.39.03-.79 0-1.18-.2-.25-.43-.49-.66-.71.15-.1.29-.22.39-.37.3.27.58.55.86.84.02 2.23.03 4.47.02 6.7h-.59c0-1.38 0-2.76-.02-4.14-.15-.25-.35-.31-.62-.17a1 1 0 0 0-.12.22c-.02 1.36-.03 2.73-.02 4.09h-.44c0-.99 0-1.97-.02-2.96-.02-.09-.06-.17-.1-.25-.67-.72-1.36-1.43-2.07-2.12-.06-1.48-.82-2.13-2.29-1.95-1.02.41-1.42 1.16-1.21 2.24q.51 1.32 1.95 1.26l1.55 1.55c.02.74.03 1.48.02 2.22-1.56.02-3.12 0-4.68-.07-.9-.24-1.42-.83-1.55-1.75-.02-4.48-.03-8.96-.02-13.45zm7.79 5.66c.84.06 1.19.5 1.06 1.33-.32.62-.8.79-1.45.52-.46-.37-.56-.82-.32-1.35.18-.26.42-.42.71-.49zm7.43 1.28c.89-.03 1.29.4 1.21 1.28-.33.67-.83.85-1.5.52-.54-.49-.58-1-.1-1.55.12-.11.25-.19.39-.25M9.94 19.94c.84 0 1.22.4 1.16 1.23-.28.68-.76.89-1.45.62-.63-.54-.65-1.09-.05-1.67l.34-.17zm9.75.24c.16.13.3.27.44.42-.53.52-1.05 1.05-1.55 1.6-.02 1.43-.03 2.86-.02 4.28h-.59c0-1.51 0-3.02.02-4.53a71 71 0 0 1 1.7-1.77M11.56 22c.62.53 1.21 1.11 1.75 1.72.02.92.03 1.84.02 2.76h-.59c0-.85 0-1.71-.02-2.56l-1.48-1.48s-.03-.07 0-.1c.12-.11.22-.22.32-.34",clipRule:"evenodd"})]});function gt({walletName:o,variant:e="background",className:t}){let n=s("novacore:w-full novacore:h-full novacore:rounded-full",t),r=o.toLowerCase();if(r==="impersonatedwallet")return jsx(h,{iconId:"impersonatedwallet",className:n,children:l=>jsx(Wo,{ref:l})});let a=Vo[r]??r,i=`wallets/${e}/${S(a)}`;return zo(a)?jsx(Suspense,{fallback:jsx(p,{animate:true,className:t}),children:jsx(h,{iconId:`${a}-${e}`,className:n,children:l=>jsx(Fo,{ref:l,id:a,variant:e})})}):jsx(P,{githubSrc:i,className:n})}function yt(o=2e3){let[e,t]=useState(false),[n,r]=useState(null),a=useCallback(async i=>{if(i)try{await navigator.clipboard.writeText(i),t(!0),r(null),setTimeout(()=>t(!1),o);}catch(l){let u=l instanceof Error?l:new Error("Failed to copy text.");console.error(u),r(u),setTimeout(()=>r(null),o);}},[o]);return {isCopied:e,copy:a,error:n}}function St(o){let e=r=>typeof window<"u"?window.matchMedia(r).matches:false,[t,n]=useState(e(o));return useEffect(()=>{let r=window.matchMedia(o),a=()=>n(r.matches);return a(),window.addEventListener("resize",a),()=>window.removeEventListener("resize",a)},[o]),t}
48
- export{ve as ChevronArrowWithAnim,no as CloseIcon,Ve as Dialog,We as DialogClose,go as DialogContent,yo as DialogDescription,bo as DialogFooter,wo as DialogHeader,Y as DialogOverlay,uo as DialogPortal,ho as DialogTitle,ze as DialogTrigger,p as FallbackIcon,P as GithubFallbackIcon,Je as NetworkIcon,rt as StarsBackground,C as SvgImg,h as SvgToImg,st as ToastCloseButton,gt as WalletIcon,to as applyFirstPathFill,s as cn,J as deepMerge,S as formatIconNameForGithub,W as getChainName,x as isSolanaDev,G as isTouchDevice,eo as resolveCssVariable,_o as standardButtonClasses,N as svgToBase64,te as textCenterEllipsis,yt as useCopyToClipboard,St as useMediaQuery};
47
+ `})}),n.map((r,a)=>jsx("circle",{cx:r.x,cy:r.y,r:r.r,fill:"rgba(var(--tuwa-bg-primary), 0.7)",className:r.isSupernova?"supernova":"pulsar",style:{animationDelay:`${r.delay}s`,animationDuration:`${r.duration}s`}},a))]})})}function st({closeToast:o,ariaLabel:e="Close toast notification",title:t="Close toast notification",className:n,iconClassName:r}){return jsx("button",{type:"button",onClick:o,"aria-label":e,title:t,className:s("novacore:absolute novacore:top-2 novacore:right-2 novacore:cursor-pointer novacore:rounded-[var(--tuwa-rounded-corners)] novacore:p-1","novacore:text-[var(--tuwa-text-tertiary)] novacore:transition-colors","novacore:hover:bg-[var(--tuwa-bg-muted)] novacore:hover:text-[var(--tuwa-text-primary)]",n),children:jsx("svg",{xmlns:"http://www.w3.org/2000/svg",fill:"none",viewBox:"0 0 24 24",strokeWidth:1.5,stroke:"currentColor",className:s("novacore:h-5 novacore:w-5",r),children:jsx("path",{strokeLinecap:"round",strokeLinejoin:"round",d:"M6 18 18 6M6 6l12 12"})})})}var Fo=lazy(()=>import('@web3icons/react/dynamic').then(o=>({default:o.WalletIcon}))),Vo={walletconnect:"wallet-connect"};function zo(o){return wallets.some(e=>e.id===o||e.name?.toLowerCase()===o)}var Wo=({className:o,ref:e})=>jsxs("svg",{ref:e,className:o,fill:"none",viewBox:"0 0 32 32",xmlns:"http://www.w3.org/2000/svg",children:[jsx("path",{fill:"#fff",fillRule:"evenodd",d:"M16 0c8.84 0 16 7.16 16 16s-7.16 16-16 16S0 24.84 0 16 7.16 0 16 0",clipRule:"evenodd"}),jsx("path",{fill:"#000",fillRule:"evenodd",d:"M16.54 2.01h1.53c.5.09.99.23 1.48.42.21.25.19.48-.05.69q-.195.045-.39 0c-1.86-.65-3.55-.35-5.07.89 2.39.7 3.84 2.27 4.36 4.7.12.85.08 1.68-.12 2.51.87 0 1.74 0 2.61-.02.39-.4.7-.85.94-1.35-.45-.45-.65-.99-.59-1.63-1.15.08-1.79-.44-1.92-1.58.14-1.12.78-1.67 1.92-1.63a.7.7 0 0 0-.12-.49l-.89-.89c-.02-.45.19-.6.62-.47.24.19.46.39.66.62.71-.79 1.5-.89 2.39-.32.44.42.62.94.54 1.55 1.49.02 2.11.76 1.85 2.22-.08.17-.17.34-.27.49.53.59.87 1.28 1.01 2.07.08 4.6.1 9.19.05 13.79-.19 1.58-1 2.71-2.44 3.37-.29.1-.59.2-.89.27H7.2c-1.31-.33-2.05-1.17-2.24-2.51-.03-5.24-.03-10.47 0-15.71.3-1.62 1.28-2.46 2.93-2.54 1.26-1.77 2.98-2.64 5.17-2.61.96-1.01 2.13-1.62 3.5-1.85zm6.11 1.87c.39-.03.7.12.91.44.06.39.09.79.1 1.18.02.12.07.21.17.27.41 0 .82.04 1.23.1.49.26.63.65.42 1.16-.07.14-.18.25-.32.32-.39.06-.79.09-1.18.1-.12.02-.21.07-.27.17l-.15 1.33c-.32.46-.72.55-1.21.27a.76.76 0 0 1-.27-.37c-.06-.41-.09-.82-.1-1.23a.35.35 0 0 0-.27-.17l-1.08-.05c-.46-.24-.62-.61-.47-1.11.14-.27.36-.43.66-.47l.99-.05s.09-.04.12-.07l.15-1.28q.18-.39.57-.54m-10.49.79c2.41-.09 4.12.94 5.15 3.1.44 1.12.48 2.25.12 3.4-.84.06-1.67.07-2.51.02.56-.68.52-1.32-.1-1.92-.26-.13-.54-.19-.84-.17.02-.95 0-1.91-.07-2.86-.21-.41-.55-.58-1.01-.52-.17.03-.31.09-.44.2-.72.92-1.43 1.85-2.14 2.78-.28.45-.29.91-.05 1.38q.225.3.57.42c.34.02.69.03 1.03.02v.69c-1.3.02-2.59 0-3.89-.05-.58-2.1-.08-3.88 1.53-5.34.79-.62 1.68-1 2.66-1.16zm.83 1.82c.07 0 .13.03.17.1l.05 3.05c.04.09.1.16.17.22l.89.05c.22.08.3.24.22.47q-.27.42-.57.81c-.43.02-.85.03-1.28.02 0-.41 0-.82-.02-1.23a.46.46 0 0 0-.17-.17l-1.28-.05c-.3-.1-.37-.29-.22-.57.7-.89 1.39-1.79 2.04-2.71zm-5.81.84h.2a6.1 6.1 0 0 0-.25 3.77c-.59-.13-1.01-.49-1.26-1.06-.36-1.29.08-2.19 1.31-2.71m17.98.83c.05 0 .1 0 .15.02q.825.855.96 2.04.045 1.305 0 2.61a3.76 3.76 0 0 0-2.54-1.55c-.61-.05-1.21-.08-1.82-.1.26-.31.48-.66.64-1.03 1.31.02 1.94-.62 1.87-1.95.26.02.5 0 .74-.05zM5.7 11.22c.41.4.91.65 1.48.76l16.06.05c1.42.13 2.38.87 2.88 2.19.07.24.12.49.15.74.03 2.86.03 5.71 0 8.57-.21 1.44-1 2.38-2.39 2.83-.24.05-.49.08-.74.1-1.26.02-2.53.03-3.79.02 0-1.33 0-2.66.02-3.99l1.55-1.55c1.42-.04 2.09-.78 1.99-2.19-.24-.88-.81-1.34-1.72-1.38-1.2.12-1.81.8-1.82 2.02l-1.92 1.92c-.08.11-.14.22-.2.34-.07 1.61-.1 3.22-.07 4.83h-.44c0-2.28 0-4.56-.02-6.85a1.8 1.8 0 0 0-.15-.34l-1.13-1.13c0-1.23-.61-1.92-1.82-2.07-1.29.17-1.87.91-1.72 2.22q.465 1.395 1.95 1.35l.71.71c0 .3.04.6.1.89.25.21.48.19.69-.05.03-.39.03-.79 0-1.18-.2-.25-.43-.49-.66-.71.15-.1.29-.22.39-.37.3.27.58.55.86.84.02 2.23.03 4.47.02 6.7h-.59c0-1.38 0-2.76-.02-4.14-.15-.25-.35-.31-.62-.17a1 1 0 0 0-.12.22c-.02 1.36-.03 2.73-.02 4.09h-.44c0-.99 0-1.97-.02-2.96-.02-.09-.06-.17-.1-.25-.67-.72-1.36-1.43-2.07-2.12-.06-1.48-.82-2.13-2.29-1.95-1.02.41-1.42 1.16-1.21 2.24q.51 1.32 1.95 1.26l1.55 1.55c.02.74.03 1.48.02 2.22-1.56.02-3.12 0-4.68-.07-.9-.24-1.42-.83-1.55-1.75-.02-4.48-.03-8.96-.02-13.45zm7.79 5.66c.84.06 1.19.5 1.06 1.33-.32.62-.8.79-1.45.52-.46-.37-.56-.82-.32-1.35.18-.26.42-.42.71-.49zm7.43 1.28c.89-.03 1.29.4 1.21 1.28-.33.67-.83.85-1.5.52-.54-.49-.58-1-.1-1.55.12-.11.25-.19.39-.25M9.94 19.94c.84 0 1.22.4 1.16 1.23-.28.68-.76.89-1.45.62-.63-.54-.65-1.09-.05-1.67l.34-.17zm9.75.24c.16.13.3.27.44.42-.53.52-1.05 1.05-1.55 1.6-.02 1.43-.03 2.86-.02 4.28h-.59c0-1.51 0-3.02.02-4.53a71 71 0 0 1 1.7-1.77M11.56 22c.62.53 1.21 1.11 1.75 1.72.02.92.03 1.84.02 2.76h-.59c0-.85 0-1.71-.02-2.56l-1.48-1.48s-.03-.07 0-.1c.12-.11.22-.22.32-.34",clipRule:"evenodd"})]});function gt({walletName:o,variant:e="background",className:t}){let n=s("novacore:w-full novacore:h-full novacore:rounded-full",t),r=o.toLowerCase();if(r==="impersonatedwallet")return jsx(h,{iconId:"impersonatedwallet",className:n,children:l=>jsx(Wo,{ref:l})});let a=Vo[r]??r,i=`wallets/${e}/${C(a)}`;return zo(a)?jsx(Suspense,{fallback:jsx(f,{animate:true,className:t}),children:jsx(h,{iconId:`${a}-${e}`,className:n,children:l=>jsx(Fo,{ref:l,id:a,variant:e})})}):jsx(P,{githubSrc:i,className:n})}function yt(o=2e3){let[e,t]=useState(false),[n,r]=useState(null),a=useCallback(async i=>{if(!i)return {copied:false,error:new Error("There is no text to copy.")};try{return await navigator.clipboard.writeText(i),t(!0),r(null),setTimeout(()=>t(!1),o),{copied:!0}}catch(l){let m=l instanceof Error?l:new Error("Failed to copy text.");return console.error(m),r(m),setTimeout(()=>r(null),o),{copied:false,error:m}}},[o]);return {isCopied:e,copy:a,error:n}}function Ct(o){let e=r=>typeof window<"u"?window.matchMedia(r).matches:false,[t,n]=useState(e(o));return useEffect(()=>{let r=window.matchMedia(o),a=()=>n(r.matches);return a(),window.addEventListener("resize",a),()=>window.removeEventListener("resize",a)},[o]),t}
48
+ export{ve as ChevronArrowWithAnim,no as CloseIcon,Ve as Dialog,We as DialogClose,go as DialogContent,yo as DialogDescription,bo as DialogFooter,wo as DialogHeader,Y as DialogOverlay,uo as DialogPortal,ho as DialogTitle,ze as DialogTrigger,f as FallbackIcon,P as GithubFallbackIcon,Je as NetworkIcon,rt as StarsBackground,k as SvgImg,h as SvgToImg,st as ToastCloseButton,gt as WalletIcon,to as applyFirstPathFill,s as cn,J as deepMerge,C as formatIconNameForGithub,W as getChainName,x as isSolanaDev,G as isTouchDevice,eo as resolveCssVariable,Uo as standardButtonClasses,N as svgToBase64,te as textCenterEllipsis,yt as useCopyToClipboard,Ct as useMediaQuery};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tuwaio/nova-core",
3
- "version": "0.6.0",
3
+ "version": "0.7.1",
4
4
  "private": false,
5
5
  "author": "Oleksandr Tkach",
6
6
  "license": "Apache-2.0",
@@ -53,28 +53,28 @@
53
53
  "@web3icons/react": ">=4",
54
54
  "@web3icons/common": ">=0.11",
55
55
  "clsx": "2.x.x",
56
- "framer-motion": "12.x.x",
56
+ "framer-motion": "12.x.x || 13.x.x",
57
57
  "react": ">=19.2.3",
58
58
  "tailwind-merge": "3.x.x"
59
59
  },
60
60
  "devDependencies": {
61
61
  "@tailwindcss/postcss": "^4.3.3",
62
62
  "@tailwindcss/vite": "^4.3.3",
63
- "@types/react": "^19.2.18",
63
+ "@types/react": "^19.3.0",
64
64
  "@radix-ui/react-dialog": "^1.1.23",
65
- "@web3icons/react": "^4.1.21",
66
- "@web3icons/common": "^0.11.50",
67
- "autoprefixer": "^10.5.5",
65
+ "@web3icons/react": "^4.1.22",
66
+ "@web3icons/common": "^0.11.51",
67
+ "autoprefixer": "^10.6.1",
68
68
  "clsx": "^2.1.1",
69
- "framer-motion": "^13.2.0",
69
+ "framer-motion": "^13.4.6",
70
70
  "postcss": "^8.5.28",
71
71
  "postcss-cli": "^12.0.0",
72
- "react": "^19.2.8",
72
+ "react": "^19.3.0",
73
73
  "tailwindcss": "^4.3.3",
74
- "tailwind-merge": "^3.6.0",
74
+ "tailwind-merge": "^3.7.0",
75
75
  "tsup": "^8.5.1",
76
76
  "typescript": "6.0.3",
77
- "vitest": "^5.0.0"
77
+ "vitest": "^5.0.2"
78
78
  },
79
79
  "scripts": {
80
80
  "build": "tsup && pnpm exec postcss ./src/styles/variables.css -o ./dist/index.css",