@thenamespace/ens-components 0.11.0 → 0.13.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,209 +1,510 @@
1
- # @arti/ui-components
1
+ # @thenamespace/ens-components
2
2
 
3
- A comprehensive React UI component library with TypeScript support, built for modern web applications.
3
+ React components for ENS (Ethereum Name Service) name registration and subname minting.
4
4
 
5
- ## Features
5
+ ## Installation
6
+
7
+ ```bash
8
+ npm install @thenamespace/ens-components
9
+ ```
6
10
 
7
- - 🎨 **Modern Design System** - Consistent, accessible components
8
- - 📱 **Responsive** - Mobile-first design approach
9
- - 🌙 **Dark/Light Theme** - Built-in theme support
10
- - 🎯 **TypeScript** - Full type safety and IntelliSense
11
- - 📦 **Tree-shakable** - Import only what you need
12
- - 🎭 **Storybook** - Interactive component documentation
13
- - ⚡ **Performance** - Optimized for production use
11
+ ## Peer Dependencies
14
12
 
15
- ## Installation
13
+ This package requires the following peer dependencies:
16
14
 
17
15
  ```bash
18
- npm install @arti/ui-components
19
- # or
20
- yarn add @arti/ui-components
21
- # or
22
- pnpm add @arti/ui-components
16
+ npm install wagmi @rainbow-me/rainbowkit @tanstack/react-query viem react react-dom
23
17
  ```
24
18
 
25
19
  ## Quick Start
26
20
 
27
- ### 1. Import Styles
21
+ ### 1. Setup Required Providers
22
+
23
+ Wrap your application with the required providers:
28
24
 
29
25
  ```tsx
30
- // Import the bundled CSS
31
- import "@arti/ui-components/styles";
26
+ import React from "react";
27
+ import { WagmiProvider } from "wagmi";
28
+ import { QueryClientProvider, QueryClient } from "@tanstack/react-query";
29
+ import { RainbowKitProvider, getDefaultConfig } from "@rainbow-me/rainbowkit";
30
+ import { mainnet, sepolia } from "wagmi/chains";
31
+ import { http } from "wagmi";
32
+
33
+ // Import styles
34
+ import "@thenamespace/ens-components/index.css";
35
+ import "@rainbow-me/rainbowkit/styles.css";
36
+
37
+ const wagmiConfig = getDefaultConfig({
38
+ appName: "My ENS App",
39
+ projectId: "YOUR_WALLETCONNECT_PROJECT_ID", // Get from https://cloud.walletconnect.com
40
+ chains: [mainnet, sepolia],
41
+ transports: {
42
+ [mainnet.id]: http(),
43
+ [sepolia.id]: http(),
44
+ },
45
+ });
46
+
47
+ const queryClient = new QueryClient();
48
+
49
+ function AppProviders({ children }: { children: React.ReactNode }) {
50
+ return (
51
+ <WagmiProvider config={wagmiConfig}>
52
+ <QueryClientProvider client={queryClient}>
53
+ <RainbowKitProvider>
54
+ {children}
55
+ </RainbowKitProvider>
56
+ </QueryClientProvider>
57
+ </WagmiProvider>
58
+ );
59
+ }
32
60
  ```
33
61
 
34
- ### 2. Setup Theme Provider
62
+ ### 2. Use the Components
35
63
 
36
64
  ```tsx
37
- import { ThemeProvider } from "@arti/ui-components";
65
+ import { ENSNamesRegistrarComponent, SubnameOnChainRegistrarModal } from "@thenamespace/ens-components";
38
66
 
39
- function App() {
67
+ function MyApp() {
40
68
  return (
41
- <ThemeProvider initialTheme="light">
42
- <YourApp />
43
- </ThemeProvider>
69
+ <AppProviders>
70
+ {/* Your components here */}
71
+ </AppProviders>
44
72
  );
45
73
  }
46
74
  ```
47
75
 
48
- ### 3. Use Components
76
+ ## Components
77
+
78
+ ### ENSNamesRegistrarComponent
79
+
80
+ Component for registering top-level ENS names (e.g., `myname.eth`).
81
+
82
+ #### Basic Usage
49
83
 
50
84
  ```tsx
51
- import { Button, Text, Input, Tooltip } from "@arti/ui-components";
85
+ import { useState } from "react";
86
+ import { ENSNamesRegistrarComponent } from "@thenamespace/ens-components";
87
+
88
+ function RegisterENSName() {
89
+ const [name, setName] = useState("");
90
+ const [duration, setDuration] = useState(1);
52
91
 
53
- function MyComponent() {
54
92
  return (
55
- <div>
56
- <Text size="lg" weight="bold">
57
- Welcome!
58
- </Text>
59
- <Button variant="solid" prefix={<Icon name="check-circle" />}>
60
- Get Started
61
- </Button>
62
- <Input placeholder="Enter your name" />
63
- <Tooltip content="This is a tooltip">
64
- <Button>Hover me</Button>
65
- </Tooltip>
66
- </div>
93
+ <ENSNamesRegistrarComponent
94
+ name={name}
95
+ duration={duration}
96
+ onNameChange={setName}
97
+ onDurationChange={setDuration}
98
+ onCompleteRegistration={() => {
99
+ console.log("Registration complete!");
100
+ }}
101
+ />
67
102
  );
68
103
  }
69
104
  ```
70
105
 
71
- ## Available Components
72
-
73
- ### Atoms
74
-
75
- - **Button** - Interactive button with variants and icons
76
- - **Input** - Form input with prefix/suffix support
77
- - **Text** - Typography component with size and weight options
78
- - **Icon** - Icon component with Lucide React icons
79
- - **ChainIcon** - Blockchain network icons
80
- - **Tooltip** - Contextual tooltip component
106
+ #### Component Flow
81
107
 
82
- ### Molecules
108
+ The component has 4 main steps:
83
109
 
84
- - **Alert** - Notification alert component
85
- - **Dropdown** - Dropdown menu component
86
- - **Modal** - Modal dialog component
110
+ 1. **NameSearch** - User searches for an available ENS name
111
+ 2. **RegistrationForm** - User reviews details and sets registration duration
112
+ 3. **RegistrationProcess** - Transaction processing with multiple steps
113
+ 4. **SuccessScreen** - Registration completion confirmation
87
114
 
88
- ### Complex Components
115
+ #### Props
89
116
 
90
- - **PendingTransaction** - Transaction status display
91
- - **SelectRecordsForm** - ENS records form
92
- - **EnsRecordsForm** - ENS management form
117
+ | Prop | Type | Required | Default | Description |
118
+ |------|------|----------|---------|-------------|
119
+ | `name` | `string` | No | `"brightwave"` | Initial ENS name (without .eth suffix) |
120
+ | `duration` | `number` | No | `1` | Registration duration in years |
121
+ | `onNameChange` | `(name: string) => void` | No | - | Callback when name changes |
122
+ | `onDurationChange` | `(duration: number) => void` | No | - | Callback when duration changes |
123
+ | `onBack` | `() => void` | No | - | Callback when back button is clicked |
124
+ | `onClose` | `() => void` | No | - | Callback when close button is clicked |
125
+ | `onNext` | `() => void` | No | - | Callback when next button is clicked |
126
+ | `onCompleteProfile` | `() => void` | No | - | Callback when "Complete Profile" is clicked |
127
+ | `onOpenWallet` | `() => void` | No | - | Callback when wallet needs to be opened |
128
+ | `onCompleteRegistration` | `() => void` | No | - | Callback when registration completes |
129
+ | `onRegisterAnother` | `() => void` | No | - | Callback when "Register Another" is clicked |
130
+ | `onViewName` | `() => void` | No | - | Callback when "View Name" is clicked |
93
131
 
94
- ## Hooks
132
+ #### Complete Example
95
133
 
96
134
  ```tsx
97
- import {
98
- useTheme,
99
- useWaitForTransaction,
100
- useWeb3Clients,
101
- } from "@arti/ui-components";
135
+ import { useState } from "react";
136
+ import { ENSNamesRegistrarComponent } from "@thenamespace/ens-components";
102
137
 
103
- function MyComponent() {
104
- const { theme, setTheme, toggleTheme } = useTheme();
105
- const { data, isLoading } = useWaitForTransaction({ hash: "0x..." });
138
+ function ENSRegistrationExample() {
139
+ const [name, setName] = useState("");
140
+ const [duration, setDuration] = useState(1);
141
+ const [registeredNames, setRegisteredNames] = useState<string[]>([]);
142
+
143
+ const handleCompleteRegistration = () => {
144
+ if (name) {
145
+ setRegisteredNames([...registeredNames, name]);
146
+ alert(`Successfully registered ${name}.eth!`);
147
+ }
148
+ };
106
149
 
107
150
  return (
108
151
  <div>
109
- <Button onClick={toggleTheme}>
110
- Switch to {theme === "light" ? "dark" : "light"} mode
111
- </Button>
152
+ <ENSNamesRegistrarComponent
153
+ name={name}
154
+ duration={duration}
155
+ onNameChange={setName}
156
+ onDurationChange={setDuration}
157
+ onBack={() => console.log("Back clicked")}
158
+ onClose={() => console.log("Close clicked")}
159
+ onNext={() => console.log("Next clicked")}
160
+ onCompleteProfile={() => {
161
+ console.log("Complete profile clicked");
162
+ // Navigate to profile completion page
163
+ }}
164
+ onOpenWallet={() => console.log("Open wallet clicked")}
165
+ onCompleteRegistration={handleCompleteRegistration}
166
+ onRegisterAnother={() => {
167
+ setName("");
168
+ setDuration(1);
169
+ }}
170
+ onViewName={() => {
171
+ if (name) {
172
+ window.open(`https://app.ens.domains/${name}`, "_blank");
173
+ }
174
+ }}
175
+ />
176
+
177
+ {registeredNames.length > 0 && (
178
+ <div>
179
+ <h3>Registered Names:</h3>
180
+ <ul>
181
+ {registeredNames.map((n) => (
182
+ <li key={n}>{n}.eth</li>
183
+ ))}
184
+ </ul>
185
+ </div>
186
+ )}
112
187
  </div>
113
188
  );
114
189
  }
115
190
  ```
116
191
 
117
- ## Utils
192
+ ---
118
193
 
119
- ```tsx
120
- import {
121
- formatAddress,
122
- parseRecords,
123
- validateAddress,
124
- getCoinInfo,
125
- getResolverAddress,
126
- } from "@arti/ui-components";
127
-
128
- // Format Ethereum address
129
- const shortAddress = formatAddress(
130
- "0x1234567890abcdef1234567890abcdef12345678"
131
- );
132
-
133
- // Parse ENS records
134
- const records = parseRecords(recordData);
135
-
136
- // Validate address
137
- const isValid = validateAddress("0x123...");
138
- ```
194
+ ### SubnameOnChainRegistrarModal
139
195
 
140
- ## Types
196
+ Component for registering on-chain subnames (e.g., `mysubname.mydomain.eth`).
197
+
198
+ #### Basic Usage
141
199
 
142
200
  ```tsx
143
- import type {
144
- ButtonProps,
145
- TransactionState,
146
- TooltipPosition,
147
- ThemeName,
148
- } from "@arti/ui-components";
201
+ import { useState } from "react";
202
+ import { SubnameOnChainRegistrarModal } from "@thenamespace/ens-components";
203
+
204
+ function RegisterSubname() {
205
+ const [step, setStep] = useState(0);
206
+ const [name, setName] = useState("");
207
+ const [parentName] = useState("mydomain.eth");
208
+ const [profileComplete, setProfileComplete] = useState(false);
209
+ const [owner, setOwner] = useState("");
210
+ const [duration, setDuration] = useState(1);
211
+ const [useAsPrimary, setUseAsPrimary] = useState(false);
212
+
213
+ return (
214
+ <SubnameOnChainRegistrarModal
215
+ step={step}
216
+ name={name}
217
+ parentName={parentName}
218
+ profileComplete={profileComplete}
219
+ owner={owner}
220
+ duration={duration}
221
+ useAsPrimary={useAsPrimary}
222
+ onStepChange={setStep}
223
+ onNameChange={setName}
224
+ onProfileCompleteChange={setProfileComplete}
225
+ onOwnerChange={setOwner}
226
+ onDurationChange={setDuration}
227
+ onUseAsPrimaryChange={setUseAsPrimary}
228
+ onCompleteRegistration={() => {
229
+ setStep(2); // Move to success screen
230
+ }}
231
+ />
232
+ );
233
+ }
149
234
  ```
150
235
 
151
- ## Web3 Integration
236
+ #### Component Flow
237
+
238
+ The component has 3 main steps:
239
+
240
+ 1. **InitialStep** (step 0) - User enters subname label
241
+ 2. **RegistrationStep** (step 1) - User reviews details and registers
242
+ 3. **SuccessScreen** (step 2) - Registration completion confirmation
243
+
244
+ #### Props
245
+
246
+ | Prop | Type | Required | Default | Description |
247
+ |------|------|----------|---------|-------------|
248
+ | `step` | `number` | No | `0` | Current step (0: Initial, 1: Registration, 2: Success) |
249
+ | `name` | `string` | No | `""` | Subname label (without parent domain) |
250
+ | `parentName` | `string` | No | `"celotest.eth"` | Parent domain name |
251
+ | `profileComplete` | `boolean` | No | `false` | Whether profile is complete |
252
+ | `domainSuffix` | `string` | No | `"eth"` | Domain suffix |
253
+ | `owner` | `string` | No | `"0x035eB...24117D3"` | Owner address for the subname |
254
+ | `duration` | `number` | No | `1` | Registration duration in years |
255
+ | `registrationFee` | `string` | No | - | Registration fee (optional) |
256
+ | `networkFee` | `string` | No | - | Network fee (optional) |
257
+ | `totalCost` | `string` | No | - | Total cost (optional) |
258
+ | `useAsPrimary` | `boolean` | No | `false` | Whether to use as primary name |
259
+ | `profileImageUrl` | `string` | No | - | Profile image URL (optional) |
260
+ | `onStepChange` | `(step: number) => void` | No | - | Callback when step changes |
261
+ | `onNameChange` | `(name: string) => void` | No | - | Callback when name changes |
262
+ | `onProfileCompleteChange` | `(complete: boolean) => void` | No | - | Callback when profile complete status changes |
263
+ | `onOwnerChange` | `(owner: string) => void` | No | - | Callback when owner changes |
264
+ | `onDurationChange` | `(duration: number) => void` | No | - | Callback when duration changes |
265
+ | `onUseAsPrimaryChange` | `(useAsPrimary: boolean) => void` | No | - | Callback when useAsPrimary changes |
266
+ | `onRegister` | `() => void` | No | - | Callback when register button is clicked |
267
+ | `onCancel` | `() => void` | No | - | Callback when cancel button is clicked |
268
+ | `onClose` | `() => void` | No | - | Callback when close button is clicked |
269
+ | `onCompleteProfile` | `() => void` | No | - | Callback when "Complete Profile" is clicked |
270
+ | `onOpenWallet` | `() => void` | No | - | Callback when wallet needs to be opened |
271
+ | `onCompleteRegistration` | `() => void` | No | - | Callback when registration completes |
272
+ | `onRegisterAnother` | `() => void` | No | - | Callback when "Register Another" is clicked |
273
+ | `onViewName` | `() => void` | No | - | Callback when "View Name" is clicked |
274
+ | `onFinish` | `() => void` | No | - | Callback when finish button is clicked (success screen) |
275
+
276
+ #### Complete Example
152
277
 
153
278
  ```tsx
154
- import { getResolverAddress, resolverAbi } from "@arti/ui-components";
279
+ import { useState } from "react";
280
+ import { SubnameOnChainRegistrarModal } from "@thenamespace/ens-components";
281
+
282
+ function SubnameRegistrationExample() {
283
+ const [isOpen, setIsOpen] = useState(false);
284
+ const [step, setStep] = useState(0);
285
+ const [name, setName] = useState("");
286
+ const [parentName] = useState("mydomain.eth");
287
+ const [profileComplete, setProfileComplete] = useState(false);
288
+ const [owner, setOwner] = useState("");
289
+ const [duration, setDuration] = useState(1);
290
+ const [useAsPrimary, setUseAsPrimary] = useState(false);
291
+ const [registeredSubnames, setRegisteredSubnames] = useState<string[]>([]);
292
+
293
+ const handleCompleteRegistration = () => {
294
+ const fullName = name ? `${name}.${parentName}` : "";
295
+ if (fullName) {
296
+ setRegisteredSubnames([...registeredSubnames, fullName]);
297
+ setStep(2); // Move to success screen
298
+ alert(`Successfully registered ${fullName}!`);
299
+ }
300
+ };
301
+
302
+ const handleFinish = () => {
303
+ setIsOpen(false);
304
+ setStep(0);
305
+ setName("");
306
+ setProfileComplete(false);
307
+ setDuration(1);
308
+ setUseAsPrimary(false);
309
+ };
310
+
311
+ if (!isOpen) {
312
+ return (
313
+ <div>
314
+ <button onClick={() => setIsOpen(true)}>
315
+ Register Subname
316
+ </button>
317
+ {registeredSubnames.length > 0 && (
318
+ <div>
319
+ <h3>Registered Subnames:</h3>
320
+ <ul>
321
+ {registeredSubnames.map((n) => (
322
+ <li key={n}>{n}</li>
323
+ ))}
324
+ </ul>
325
+ </div>
326
+ )}
327
+ </div>
328
+ );
329
+ }
155
330
 
156
- // Get resolver contract address
157
- const resolverAddress = getResolverAddress("mainnet");
158
-
159
- // Use ABI for contract interactions
160
- const contract = new ethers.Contract(resolverAddress, resolverAbi, provider);
331
+ return (
332
+ <div style={{ position: "fixed", inset: 0, backgroundColor: "rgba(0, 0, 0, 0.5)", display: "flex", alignItems: "center", justifyContent: "center", zIndex: 1000 }}>
333
+ <div style={{ backgroundColor: "white", borderRadius: "8px", padding: "20px", maxWidth: "600px", width: "90%", maxHeight: "90vh", overflow: "auto" }}>
334
+ <SubnameOnChainRegistrarModal
335
+ step={step}
336
+ name={name}
337
+ parentName={parentName}
338
+ profileComplete={profileComplete}
339
+ owner={owner}
340
+ duration={duration}
341
+ useAsPrimary={useAsPrimary}
342
+ onStepChange={setStep}
343
+ onNameChange={setName}
344
+ onProfileCompleteChange={setProfileComplete}
345
+ onOwnerChange={setOwner}
346
+ onDurationChange={setDuration}
347
+ onUseAsPrimaryChange={setUseAsPrimary}
348
+ onRegister={() => console.log("Register clicked")}
349
+ onCancel={() => {
350
+ console.log("Cancel clicked");
351
+ setStep(0);
352
+ }}
353
+ onClose={handleFinish}
354
+ onCompleteProfile={() => {
355
+ console.log("Complete profile clicked");
356
+ setProfileComplete(true);
357
+ }}
358
+ onCompleteRegistration={handleCompleteRegistration}
359
+ onFinish={handleFinish}
360
+ />
361
+ </div>
362
+ </div>
363
+ );
364
+ }
161
365
  ```
162
366
 
163
- ## Theme Customization
164
-
165
- The library uses CSS custom properties for theming. You can override the default theme:
367
+ ## Full Example with Both Components
166
368
 
167
- ```css
168
- :root {
169
- --ns-color-primary: #your-color;
170
- --ns-color-bg: #your-bg-color;
171
- --ns-color-fg: #your-text-color;
172
- /* ... other theme variables */
369
+ ```tsx
370
+ import React, { useState } from "react";
371
+ import { WagmiProvider } from "wagmi";
372
+ import { QueryClientProvider, QueryClient } from "@tanstack/react-query";
373
+ import { RainbowKitProvider, getDefaultConfig } from "@rainbow-me/rainbowkit";
374
+ import { mainnet, sepolia } from "wagmi/chains";
375
+ import { http } from "wagmi";
376
+ import { ENSNamesRegistrarComponent, SubnameOnChainRegistrarModal } from "@thenamespace/ens-components";
377
+ import "@thenamespace/ens-components/index.css";
378
+ import "@rainbow-me/rainbowkit/styles.css";
379
+
380
+ const wagmiConfig = getDefaultConfig({
381
+ appName: "My ENS App",
382
+ projectId: "YOUR_WALLETCONNECT_PROJECT_ID",
383
+ chains: [mainnet, sepolia],
384
+ transports: {
385
+ [mainnet.id]: http(),
386
+ [sepolia.id]: http(),
387
+ },
388
+ });
389
+
390
+ const queryClient = new QueryClient();
391
+
392
+ function AppProviders({ children }: { children: React.ReactNode }) {
393
+ return (
394
+ <WagmiProvider config={wagmiConfig}>
395
+ <QueryClientProvider client={queryClient}>
396
+ <RainbowKitProvider>
397
+ {children}
398
+ </RainbowKitProvider>
399
+ </QueryClientProvider>
400
+ </WagmiProvider>
401
+ );
173
402
  }
174
- ```
175
403
 
176
- ## Storybook
404
+ function App() {
405
+ const [activeTab, setActiveTab] = useState<"ens" | "subname">("ens");
406
+
407
+ // ENS Name Registration State
408
+ const [ensName, setEnsName] = useState("");
409
+ const [ensDuration, setEnsDuration] = useState(1);
410
+
411
+ // Subname Registration State
412
+ const [subnameStep, setSubnameStep] = useState(0);
413
+ const [subname, setSubname] = useState("");
414
+ const [parentName] = useState("mydomain.eth");
415
+ const [profileComplete, setProfileComplete] = useState(false);
416
+ const [owner, setOwner] = useState("");
417
+ const [duration, setDuration] = useState(1);
418
+ const [useAsPrimary, setUseAsPrimary] = useState(false);
177
419
 
178
- To view all components and their documentation:
420
+ return (
421
+ <AppProviders>
422
+ <div style={{ padding: "20px" }}>
423
+ <div style={{ marginBottom: "20px" }}>
424
+ <button
425
+ onClick={() => setActiveTab("ens")}
426
+ style={{ marginRight: "10px", padding: "10px", backgroundColor: activeTab === "ens" ? "#007bff" : "#ccc", color: "white", border: "none", borderRadius: "4px", cursor: "pointer" }}
427
+ >
428
+ Register ENS Name
429
+ </button>
430
+ <button
431
+ onClick={() => setActiveTab("subname")}
432
+ style={{ padding: "10px", backgroundColor: activeTab === "subname" ? "#007bff" : "#ccc", color: "white", border: "none", borderRadius: "4px", cursor: "pointer" }}
433
+ >
434
+ Register Subname
435
+ </button>
436
+ </div>
437
+
438
+ {activeTab === "ens" && (
439
+ <div>
440
+ <h2>Register ENS Name</h2>
441
+ <ENSNamesRegistrarComponent
442
+ name={ensName}
443
+ duration={ensDuration}
444
+ onNameChange={setEnsName}
445
+ onDurationChange={setEnsDuration}
446
+ onCompleteRegistration={() => {
447
+ alert(`Successfully registered ${ensName}.eth!`);
448
+ }}
449
+ />
450
+ </div>
451
+ )}
452
+
453
+ {activeTab === "subname" && (
454
+ <div>
455
+ <h2>Register On-Chain Subname</h2>
456
+ <SubnameOnChainRegistrarModal
457
+ step={subnameStep}
458
+ name={subname}
459
+ parentName={parentName}
460
+ profileComplete={profileComplete}
461
+ owner={owner}
462
+ duration={duration}
463
+ useAsPrimary={useAsPrimary}
464
+ onStepChange={setSubnameStep}
465
+ onNameChange={setSubname}
466
+ onProfileCompleteChange={setProfileComplete}
467
+ onOwnerChange={setOwner}
468
+ onDurationChange={setDuration}
469
+ onUseAsPrimaryChange={setUseAsPrimary}
470
+ onCompleteRegistration={() => {
471
+ setSubnameStep(2);
472
+ alert(`Successfully registered ${subname}.${parentName}!`);
473
+ }}
474
+ onFinish={() => {
475
+ setSubnameStep(0);
476
+ setSubname("");
477
+ }}
478
+ />
479
+ </div>
480
+ )}
481
+ </div>
482
+ </AppProviders>
483
+ );
484
+ }
179
485
 
180
- ```bash
181
- npm run storybook
486
+ export default App;
182
487
  ```
183
488
 
184
- ## Development
489
+ ## Styling
185
490
 
186
- ```bash
187
- # Install dependencies
188
- npm install
189
-
190
- # Start development build
191
- npm run dev
491
+ The components come with their own CSS. Make sure to import the styles:
192
492
 
193
- # Build library
194
- npm run build
493
+ ```tsx
494
+ import "@thenamespace/ens-components/index.css";
495
+ import "@rainbow-me/rainbowkit/styles.css";
496
+ ```
195
497
 
196
- # Run Storybook
197
- npm run storybook
498
+ ## Requirements
198
499
 
199
- # Build Storybook
200
- npm run build-storybook
201
- ```
500
+ - React 18+
501
+ - Node.js 16+
502
+ - A WalletConnect Project ID (get one at https://cloud.walletconnect.com)
202
503
 
203
504
  ## License
204
505
 
205
506
  ISC
206
507
 
207
- ## Contributing
508
+ ## Support
208
509
 
209
- Contributions are welcome! Please feel free to submit a Pull Request.
510
+ For issues and questions, please visit the package repository.