warqadui 0.0.4 → 0.0.6
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/.vscode/settings.json +3 -0
- package/apps/dev-app/.env +1 -0
- package/apps/dev-app/errors.log +0 -0
- package/apps/dev-app/index.html +12 -0
- package/apps/dev-app/node_modules/.vite/deps/@tanstack_react-table.js +3254 -0
- package/apps/dev-app/node_modules/.vite/deps/@tanstack_react-table.js.map +7 -0
- package/apps/dev-app/node_modules/.vite/deps/_metadata.json +178 -0
- package/apps/dev-app/node_modules/.vite/deps/antd.js +108982 -0
- package/apps/dev-app/node_modules/.vite/deps/antd.js.map +7 -0
- package/apps/dev-app/node_modules/.vite/deps/axios.js +2751 -0
- package/apps/dev-app/node_modules/.vite/deps/axios.js.map +7 -0
- package/apps/dev-app/node_modules/.vite/deps/chunk-5OG7DCD7.js +41 -0
- package/apps/dev-app/node_modules/.vite/deps/chunk-5OG7DCD7.js.map +7 -0
- package/apps/dev-app/node_modules/.vite/deps/chunk-7YRZYZRE.js +7807 -0
- package/apps/dev-app/node_modules/.vite/deps/chunk-7YRZYZRE.js.map +7 -0
- package/apps/dev-app/node_modules/.vite/deps/chunk-DC5AMYBS.js +39 -0
- package/apps/dev-app/node_modules/.vite/deps/chunk-DC5AMYBS.js.map +7 -0
- package/apps/dev-app/node_modules/.vite/deps/chunk-DKXRQMOD.js +135 -0
- package/apps/dev-app/node_modules/.vite/deps/chunk-DKXRQMOD.js.map +7 -0
- package/apps/dev-app/node_modules/.vite/deps/chunk-EL47BWQR.js +37 -0
- package/apps/dev-app/node_modules/.vite/deps/chunk-EL47BWQR.js.map +7 -0
- package/apps/dev-app/node_modules/.vite/deps/chunk-HHL3MHGV.js +288 -0
- package/apps/dev-app/node_modules/.vite/deps/chunk-HHL3MHGV.js.map +7 -0
- package/apps/dev-app/node_modules/.vite/deps/chunk-IGGUWUPT.js +60 -0
- package/apps/dev-app/node_modules/.vite/deps/chunk-IGGUWUPT.js.map +7 -0
- package/apps/dev-app/node_modules/.vite/deps/chunk-IGXZPJXT.js +928 -0
- package/apps/dev-app/node_modules/.vite/deps/chunk-IGXZPJXT.js.map +7 -0
- package/apps/dev-app/node_modules/.vite/deps/chunk-L2GCM37S.js +21628 -0
- package/apps/dev-app/node_modules/.vite/deps/chunk-L2GCM37S.js.map +7 -0
- package/apps/dev-app/node_modules/.vite/deps/chunk-LDRT62EN.js +14806 -0
- package/apps/dev-app/node_modules/.vite/deps/chunk-LDRT62EN.js.map +7 -0
- package/apps/dev-app/node_modules/.vite/deps/chunk-M7DZDBHW.js +14 -0
- package/apps/dev-app/node_modules/.vite/deps/chunk-M7DZDBHW.js.map +7 -0
- package/apps/dev-app/node_modules/.vite/deps/chunk-S54SBVCU.js +1906 -0
- package/apps/dev-app/node_modules/.vite/deps/chunk-S54SBVCU.js.map +7 -0
- package/apps/dev-app/node_modules/.vite/deps/chunk-WFNHCR67.js +21 -0
- package/apps/dev-app/node_modules/.vite/deps/chunk-WFNHCR67.js.map +7 -0
- package/apps/dev-app/node_modules/.vite/deps/clsx.js +10 -0
- package/apps/dev-app/node_modules/.vite/deps/clsx.js.map +7 -0
- package/apps/dev-app/node_modules/.vite/deps/dayjs.js +6 -0
- package/apps/dev-app/node_modules/.vite/deps/dayjs.js.map +7 -0
- package/apps/dev-app/node_modules/.vite/deps/dayjs_plugin_customParseFormat.js +6 -0
- package/apps/dev-app/node_modules/.vite/deps/dayjs_plugin_customParseFormat.js.map +7 -0
- package/apps/dev-app/node_modules/.vite/deps/framer-motion.js +12388 -0
- package/apps/dev-app/node_modules/.vite/deps/framer-motion.js.map +7 -0
- package/apps/dev-app/node_modules/.vite/deps/html2canvas-pro.js +9713 -0
- package/apps/dev-app/node_modules/.vite/deps/html2canvas-pro.js.map +7 -0
- package/apps/dev-app/node_modules/.vite/deps/html2canvas.esm-VL7GM4AH.js +8 -0
- package/apps/dev-app/node_modules/.vite/deps/html2canvas.esm-VL7GM4AH.js.map +7 -0
- package/apps/dev-app/node_modules/.vite/deps/index.es-3WTXOFZ2.js +10392 -0
- package/apps/dev-app/node_modules/.vite/deps/index.es-3WTXOFZ2.js.map +7 -0
- package/apps/dev-app/node_modules/.vite/deps/jspdf.js +41 -0
- package/apps/dev-app/node_modules/.vite/deps/jspdf.js.map +7 -0
- package/apps/dev-app/node_modules/.vite/deps/lucide-react.js +31586 -0
- package/apps/dev-app/node_modules/.vite/deps/lucide-react.js.map +7 -0
- package/apps/dev-app/node_modules/.vite/deps/package.json +3 -0
- package/apps/dev-app/node_modules/.vite/deps/purify.es-JNLDEIMX.js +1029 -0
- package/apps/dev-app/node_modules/.vite/deps/purify.es-JNLDEIMX.js.map +7 -0
- package/apps/dev-app/node_modules/.vite/deps/react-dom.js +7 -0
- package/apps/dev-app/node_modules/.vite/deps/react-dom.js.map +7 -0
- package/apps/dev-app/node_modules/.vite/deps/react-dom_client.js +8 -0
- package/apps/dev-app/node_modules/.vite/deps/react-dom_client.js.map +7 -0
- package/apps/dev-app/node_modules/.vite/deps/react-hook-form.js +2233 -0
- package/apps/dev-app/node_modules/.vite/deps/react-hook-form.js.map +7 -0
- package/apps/dev-app/node_modules/.vite/deps/react-phone-number-input.js +9307 -0
- package/apps/dev-app/node_modules/.vite/deps/react-phone-number-input.js.map +7 -0
- package/apps/dev-app/node_modules/.vite/deps/react-router-dom.js +14234 -0
- package/apps/dev-app/node_modules/.vite/deps/react-router-dom.js.map +7 -0
- package/apps/dev-app/node_modules/.vite/deps/react-to-pdf.js +268 -0
- package/apps/dev-app/node_modules/.vite/deps/react-to-pdf.js.map +7 -0
- package/apps/dev-app/node_modules/.vite/deps/react.js +6 -0
- package/apps/dev-app/node_modules/.vite/deps/react.js.map +7 -0
- package/apps/dev-app/node_modules/.vite/deps/react_jsx-dev-runtime.js +913 -0
- package/apps/dev-app/node_modules/.vite/deps/react_jsx-dev-runtime.js.map +7 -0
- package/apps/dev-app/node_modules/.vite/deps/react_jsx-runtime.js +7 -0
- package/apps/dev-app/node_modules/.vite/deps/react_jsx-runtime.js.map +7 -0
- package/apps/dev-app/node_modules/.vite/deps/tailwind-merge.js +2534 -0
- package/apps/dev-app/node_modules/.vite/deps/tailwind-merge.js.map +7 -0
- package/apps/dev-app/node_modules/tailwindcss/LICENSE +21 -0
- package/apps/dev-app/node_modules/tailwindcss/README.md +36 -0
- package/apps/dev-app/node_modules/tailwindcss/dist/chunk-L5IEUH3R.mjs +38 -0
- package/apps/dev-app/node_modules/tailwindcss/dist/chunk-UWKE2Z6N.mjs +1 -0
- package/apps/dev-app/node_modules/tailwindcss/dist/chunk-X4GG3EDV.mjs +1 -0
- package/apps/dev-app/node_modules/tailwindcss/dist/colors-C__qRT83.d.ts +347 -0
- package/apps/dev-app/node_modules/tailwindcss/dist/colors.d.mts +347 -0
- package/apps/dev-app/node_modules/tailwindcss/dist/colors.d.ts +5 -0
- package/apps/dev-app/node_modules/tailwindcss/dist/colors.js +1 -0
- package/apps/dev-app/node_modules/tailwindcss/dist/colors.mjs +1 -0
- package/apps/dev-app/node_modules/tailwindcss/dist/default-theme.d.mts +1199 -0
- package/apps/dev-app/node_modules/tailwindcss/dist/default-theme.d.ts +1199 -0
- package/apps/dev-app/node_modules/tailwindcss/dist/default-theme.js +1 -0
- package/apps/dev-app/node_modules/tailwindcss/dist/default-theme.mjs +1 -0
- package/apps/dev-app/node_modules/tailwindcss/dist/flatten-color-palette.d.mts +6 -0
- package/apps/dev-app/node_modules/tailwindcss/dist/flatten-color-palette.d.ts +6 -0
- package/apps/dev-app/node_modules/tailwindcss/dist/flatten-color-palette.js +3 -0
- package/apps/dev-app/node_modules/tailwindcss/dist/flatten-color-palette.mjs +1 -0
- package/apps/dev-app/node_modules/tailwindcss/dist/lib.d.mts +378 -0
- package/apps/dev-app/node_modules/tailwindcss/dist/lib.d.ts +3 -0
- package/apps/dev-app/node_modules/tailwindcss/dist/lib.js +38 -0
- package/apps/dev-app/node_modules/tailwindcss/dist/lib.mjs +1 -0
- package/apps/dev-app/node_modules/tailwindcss/dist/plugin.d.mts +11 -0
- package/apps/dev-app/node_modules/tailwindcss/dist/plugin.d.ts +134 -0
- package/apps/dev-app/node_modules/tailwindcss/dist/plugin.js +1 -0
- package/apps/dev-app/node_modules/tailwindcss/dist/plugin.mjs +1 -0
- package/apps/dev-app/node_modules/tailwindcss/dist/resolve-config-B4yBzhca.d.ts +29 -0
- package/apps/dev-app/node_modules/tailwindcss/dist/resolve-config-QUZ9b-Gn.d.mts +190 -0
- package/apps/dev-app/node_modules/tailwindcss/dist/types-CJYAW1ql.d.mts +128 -0
- package/apps/dev-app/node_modules/tailwindcss/index.css +944 -0
- package/apps/dev-app/node_modules/tailwindcss/package.json +89 -0
- package/apps/dev-app/node_modules/tailwindcss/preflight.css +393 -0
- package/apps/dev-app/node_modules/tailwindcss/theme.css +510 -0
- package/apps/dev-app/node_modules/tailwindcss/utilities.css +1 -0
- package/apps/dev-app/package.json +35 -0
- package/apps/dev-app/src/App.tsx +74 -0
- package/apps/dev-app/src/index.css +18 -0
- package/apps/dev-app/src/main.tsx +18 -0
- package/apps/dev-app/src/pages/Buttons.tsx +122 -0
- package/apps/dev-app/src/pages/DataTable.tsx +208 -0
- package/apps/dev-app/src/pages/Fields.tsx +342 -0
- package/apps/dev-app/src/pages/Modals.tsx +151 -0
- package/apps/dev-app/src/pages/Spins.tsx +161 -0
- package/apps/dev-app/ts_errors.txt +0 -0
- package/apps/dev-app/tsconfig.json +25 -0
- package/apps/dev-app/tsconfig.node.json +10 -0
- package/apps/dev-app/vite.config.ts +11 -0
- package/package.json +10 -49
- package/packages/ui/dist/index.d.mts +356 -0
- package/packages/ui/dist/index.d.ts +356 -0
- package/packages/ui/dist/index.js +2296 -0
- package/packages/ui/dist/index.mjs +2249 -0
- package/packages/ui/dist/styles.js +26 -0
- package/packages/ui/dist/styles.mjs +24 -0
- package/packages/ui/log.txt +0 -0
- package/packages/ui/package.json +68 -0
- package/packages/ui/postcss.config.js +6 -0
- package/packages/ui/src/components/Button.tsx +85 -0
- package/packages/ui/src/components/Card.tsx +97 -0
- package/packages/ui/src/components/CodeBlock.tsx +53 -0
- package/packages/ui/src/components/DashboardLayout.tsx +442 -0
- package/packages/ui/src/components/Fields/Input.tsx +191 -0
- package/packages/ui/src/components/Fields/PhoneInput.tsx +134 -0
- package/packages/ui/src/components/Fields/date.tsx +165 -0
- package/packages/ui/src/components/Fields/index.tsx +17 -0
- package/packages/ui/src/components/Fields/searchApi.tsx +479 -0
- package/packages/ui/src/components/Fields/select.tsx +131 -0
- package/packages/ui/src/components/Fields/textArea.tsx +121 -0
- package/packages/ui/src/components/LoadingBox.tsx +11 -0
- package/packages/ui/src/components/PageHeader.tsx +34 -0
- package/packages/ui/src/components/ThemeToggle.tsx +35 -0
- package/packages/ui/src/components/modal/Modal.tsx +81 -0
- package/packages/ui/src/components/spins/ClassicSpin.tsx +18 -0
- package/packages/ui/src/components/spins/LoadingSpin.tsx +45 -0
- package/packages/ui/src/components/spins/OverlaySpin.tsx +10 -0
- package/packages/ui/src/components/spins/index.tsx +13 -0
- package/packages/ui/src/components/tables/DataTable.tsx +261 -0
- package/packages/ui/src/components/tables/index.ts +1 -0
- package/packages/ui/src/hooks/Fetches/useApis.tsx +197 -0
- package/packages/ui/src/hooks/ThemeContext.tsx +56 -0
- package/packages/ui/src/hooks/useModal.tsx +38 -0
- package/packages/ui/src/hooks/useTheme.ts +34 -0
- package/packages/ui/src/index.ts +24 -0
- package/packages/ui/src/providers/WarqadProvider.tsx +69 -0
- package/packages/ui/src/styles.css +26 -0
- package/packages/ui/src/utils/cn.ts +6 -0
- package/packages/ui/src/utils/pdf.ts +171 -0
- package/packages/ui/tailwind.config.js +13 -0
- package/packages/ui/tsconfig.json +17 -0
- package/packages/ui/warqad-ui-0.0.1.tgz +0 -0
- package/packages/ui/warqadui-0.0.3.tgz +0 -0
- package/warqad-ui-0.0.1.tgz +0 -0
- package/dist/index.d.mts +0 -35
- package/dist/index.d.ts +0 -35
- package/dist/index.js +0 -470
- package/dist/index.mjs +0 -440
- package/dist/styles.js +0 -26
- package/dist/styles.mjs +0 -24
- /package/{dist → packages/ui/dist}/index.css +0 -0
- /package/{dist → packages/ui/dist}/styles.d.mts +0 -0
- /package/{dist → packages/ui/dist}/styles.d.ts +0 -0
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
import { Button, CodeBlock, Card, PageHeader } from "warqadui";
|
|
2
|
+
import { Plus, Send, Settings, Trash2 } from "lucide-react";
|
|
3
|
+
|
|
4
|
+
function Buttons() {
|
|
5
|
+
const importCode = `import { Button } from "warqadui";`;
|
|
6
|
+
|
|
7
|
+
const variantCode = `<Button variant="primary">Primary</Button>
|
|
8
|
+
<Button variant="secondary">Secondary</Button>
|
|
9
|
+
<Button variant="outline">Outline</Button>
|
|
10
|
+
<Button variant="ghost">Ghost</Button>
|
|
11
|
+
<Button variant="danger">Danger</Button>
|
|
12
|
+
<Button variant="warning">Warning</Button>`;
|
|
13
|
+
|
|
14
|
+
const iconCode = `// Button with Icon + Label
|
|
15
|
+
<Button icon={<Plus />} variant="primary">
|
|
16
|
+
Add Item
|
|
17
|
+
</Button>
|
|
18
|
+
|
|
19
|
+
// Icon-only Button (Auto-centered)
|
|
20
|
+
<Button icon={<Settings />} variant="outline" />`;
|
|
21
|
+
|
|
22
|
+
const sizeCode = `<Button size="sm">Small</Button>
|
|
23
|
+
<Button size="md">Medium</Button>
|
|
24
|
+
<Button size="lg">Large</Button>`;
|
|
25
|
+
|
|
26
|
+
const stateCode = `<Button isLoading>Loading</Button>
|
|
27
|
+
<Button disabled>Disabled</Button>`;
|
|
28
|
+
|
|
29
|
+
return (
|
|
30
|
+
<div className="space-y-12 p-4 pb-20">
|
|
31
|
+
<PageHeader
|
|
32
|
+
title="Buttons"
|
|
33
|
+
description="Premium iOS-inspired buttons with support for variants, icons, loading states, and different sizes."
|
|
34
|
+
/>
|
|
35
|
+
|
|
36
|
+
{/* Quick Start */}
|
|
37
|
+
<section className="space-y-4">
|
|
38
|
+
<h2 className="text-xl font-bold">Usage</h2>
|
|
39
|
+
<div className="max-w-xl">
|
|
40
|
+
<CodeBlock code={importCode} />
|
|
41
|
+
</div>
|
|
42
|
+
</section>
|
|
43
|
+
|
|
44
|
+
<div className="grid grid-cols-1 lg:grid-cols-2 gap-8">
|
|
45
|
+
{/* Standard Variants */}
|
|
46
|
+
<Card className="space-y-6">
|
|
47
|
+
<Card.Header>
|
|
48
|
+
<Card.Title>Variants</Card.Title>
|
|
49
|
+
<Card.Description>
|
|
50
|
+
Core visual styles for different contexts.
|
|
51
|
+
</Card.Description>
|
|
52
|
+
</Card.Header>
|
|
53
|
+
<Card.Content className="flex flex-wrap gap-3">
|
|
54
|
+
<Button variant="primary">Primary</Button>
|
|
55
|
+
<Button variant="secondary">Secondary</Button>
|
|
56
|
+
<Button variant="outline">Outline</Button>
|
|
57
|
+
<Button variant="ghost">Ghost</Button>
|
|
58
|
+
<Button variant="danger">Danger</Button>
|
|
59
|
+
<Button variant="warning">Warning</Button>
|
|
60
|
+
</Card.Content>
|
|
61
|
+
<CodeBlock code={variantCode} className="text-xs" />
|
|
62
|
+
</Card>
|
|
63
|
+
|
|
64
|
+
{/* Icons Support */}
|
|
65
|
+
<Card className="space-y-6">
|
|
66
|
+
<Card.Header>
|
|
67
|
+
<Card.Title>Icon Support</Card.Title>
|
|
68
|
+
<Card.Description>
|
|
69
|
+
Seamlessly integrate Lucide icons.
|
|
70
|
+
</Card.Description>
|
|
71
|
+
</Card.Header>
|
|
72
|
+
<Card.Content className="flex flex-wrap gap-3">
|
|
73
|
+
<Button icon={<Plus />} variant="primary">
|
|
74
|
+
Add Item
|
|
75
|
+
</Button>
|
|
76
|
+
<Button icon={<Send />} variant="secondary">
|
|
77
|
+
Send Message
|
|
78
|
+
</Button>
|
|
79
|
+
<Button icon={<Trash2 />} variant="danger">
|
|
80
|
+
Delete
|
|
81
|
+
</Button>
|
|
82
|
+
<Button icon={<Settings />} variant="outline" />
|
|
83
|
+
</Card.Content>
|
|
84
|
+
<CodeBlock code={iconCode} className="text-xs" />
|
|
85
|
+
</Card>
|
|
86
|
+
|
|
87
|
+
{/* Sizes */}
|
|
88
|
+
<Card className="space-y-6">
|
|
89
|
+
<Card.Header>
|
|
90
|
+
<Card.Title>Sizes</Card.Title>
|
|
91
|
+
<Card.Description>
|
|
92
|
+
Predictable sizing for any layout.
|
|
93
|
+
</Card.Description>
|
|
94
|
+
</Card.Header>
|
|
95
|
+
<Card.Content className="flex flex-wrap items-end gap-3">
|
|
96
|
+
<Button size="sm">Small</Button>
|
|
97
|
+
<Button size="md">Medium</Button>
|
|
98
|
+
<Button size="lg">Large</Button>
|
|
99
|
+
</Card.Content>
|
|
100
|
+
<CodeBlock code={sizeCode} className="text-xs" />
|
|
101
|
+
</Card>
|
|
102
|
+
|
|
103
|
+
{/* States */}
|
|
104
|
+
<Card className="space-y-6">
|
|
105
|
+
<Card.Header>
|
|
106
|
+
<Card.Title>States</Card.Title>
|
|
107
|
+
<Card.Description>
|
|
108
|
+
Built-in loading and disabled states.
|
|
109
|
+
</Card.Description>
|
|
110
|
+
</Card.Header>
|
|
111
|
+
<Card.Content className="flex flex-wrap gap-3">
|
|
112
|
+
<Button isLoading>Loading</Button>
|
|
113
|
+
<Button disabled>Disabled</Button>
|
|
114
|
+
</Card.Content>
|
|
115
|
+
<CodeBlock code={stateCode} className="text-xs" />
|
|
116
|
+
</Card>
|
|
117
|
+
</div>
|
|
118
|
+
</div>
|
|
119
|
+
);
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
export default Buttons;
|
|
@@ -0,0 +1,208 @@
|
|
|
1
|
+
import { useState } from "react";
|
|
2
|
+
import { DataTable, Card, PageHeader, CodeBlock } from "warqadui";
|
|
3
|
+
import { type ColumnDef } from "@tanstack/react-table";
|
|
4
|
+
import { MoreHorizontal, ArrowUpDown } from "lucide-react";
|
|
5
|
+
|
|
6
|
+
interface User {
|
|
7
|
+
id: string;
|
|
8
|
+
status: "pending" | "processing" | "success" | "failed";
|
|
9
|
+
email: string;
|
|
10
|
+
amount: number;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
const data: User[] = [
|
|
14
|
+
{
|
|
15
|
+
id: "728ed52f",
|
|
16
|
+
status: "success",
|
|
17
|
+
email: "abe45@example.com",
|
|
18
|
+
amount: 242.0,
|
|
19
|
+
},
|
|
20
|
+
{
|
|
21
|
+
id: "489e1d42",
|
|
22
|
+
status: "processing",
|
|
23
|
+
email: "monserrat44@example.com",
|
|
24
|
+
amount: 837.0,
|
|
25
|
+
},
|
|
26
|
+
{
|
|
27
|
+
id: "d92b1e42",
|
|
28
|
+
status: "success",
|
|
29
|
+
email: "silas22@example.com",
|
|
30
|
+
amount: 874.0,
|
|
31
|
+
},
|
|
32
|
+
{
|
|
33
|
+
id: "a1b2c3d4",
|
|
34
|
+
status: "failed",
|
|
35
|
+
email: "carmella@example.com",
|
|
36
|
+
amount: 721.0,
|
|
37
|
+
},
|
|
38
|
+
{
|
|
39
|
+
id: "e5f6g7h8",
|
|
40
|
+
status: "success",
|
|
41
|
+
email: "ken99@example.com",
|
|
42
|
+
amount: 316.0,
|
|
43
|
+
},
|
|
44
|
+
{
|
|
45
|
+
id: "i9j0k1l2",
|
|
46
|
+
status: "pending",
|
|
47
|
+
email: "user1@example.com",
|
|
48
|
+
amount: 125.5,
|
|
49
|
+
},
|
|
50
|
+
{
|
|
51
|
+
id: "m3n4o5p6",
|
|
52
|
+
status: "success",
|
|
53
|
+
email: "user2@example.com",
|
|
54
|
+
amount: 540.0,
|
|
55
|
+
},
|
|
56
|
+
];
|
|
57
|
+
|
|
58
|
+
const columns: ColumnDef<User>[] = [
|
|
59
|
+
{
|
|
60
|
+
id: "select",
|
|
61
|
+
header: ({ table }: any) => (
|
|
62
|
+
<input
|
|
63
|
+
type="checkbox"
|
|
64
|
+
checked={table.getIsAllPageRowsSelected()}
|
|
65
|
+
onChange={(e) => table.toggleAllPageRowsSelected(!!e.target.checked)}
|
|
66
|
+
className="rounded border-gray-300"
|
|
67
|
+
/>
|
|
68
|
+
),
|
|
69
|
+
cell: ({ row }: any) => (
|
|
70
|
+
<input
|
|
71
|
+
type="checkbox"
|
|
72
|
+
checked={row.getIsSelected()}
|
|
73
|
+
onChange={(e) => row.toggleSelected(!!e.target.checked)}
|
|
74
|
+
className="rounded border-gray-300"
|
|
75
|
+
/>
|
|
76
|
+
),
|
|
77
|
+
enableSorting: false,
|
|
78
|
+
enableHiding: false,
|
|
79
|
+
},
|
|
80
|
+
{
|
|
81
|
+
accessorKey: "status",
|
|
82
|
+
header: "Status",
|
|
83
|
+
cell: ({ row }: any) => {
|
|
84
|
+
const status = row.getValue("status") as string;
|
|
85
|
+
return (
|
|
86
|
+
<div
|
|
87
|
+
className={`capitalize font-medium ${
|
|
88
|
+
status === "success"
|
|
89
|
+
? "text-green-600"
|
|
90
|
+
: status === "failed"
|
|
91
|
+
? "text-red-600"
|
|
92
|
+
: status === "processing"
|
|
93
|
+
? "text-blue-600"
|
|
94
|
+
: "text-gray-600"
|
|
95
|
+
}`}
|
|
96
|
+
>
|
|
97
|
+
{status}
|
|
98
|
+
</div>
|
|
99
|
+
);
|
|
100
|
+
},
|
|
101
|
+
},
|
|
102
|
+
{
|
|
103
|
+
accessorKey: "email",
|
|
104
|
+
header: ({ column }: any) => {
|
|
105
|
+
return (
|
|
106
|
+
<button
|
|
107
|
+
className="flex items-center gap-1 hover:text-gray-900 transition-colors"
|
|
108
|
+
onClick={() => column.toggleSorting(column.getIsSorted() === "asc")}
|
|
109
|
+
>
|
|
110
|
+
Email
|
|
111
|
+
<ArrowUpDown size={14} />
|
|
112
|
+
</button>
|
|
113
|
+
);
|
|
114
|
+
},
|
|
115
|
+
},
|
|
116
|
+
{
|
|
117
|
+
accessorKey: "amount",
|
|
118
|
+
header: () => <div className="text-right">Amount</div>,
|
|
119
|
+
cell: ({ row }: any) => {
|
|
120
|
+
const amount = parseFloat(row.getValue("amount"));
|
|
121
|
+
const formatted = new Intl.NumberFormat("en-US", {
|
|
122
|
+
style: "currency",
|
|
123
|
+
currency: "USD",
|
|
124
|
+
}).format(amount);
|
|
125
|
+
return <div className="text-right font-medium">{formatted}</div>;
|
|
126
|
+
},
|
|
127
|
+
},
|
|
128
|
+
{
|
|
129
|
+
id: "actions",
|
|
130
|
+
cell: () => (
|
|
131
|
+
<button className="p-1 hover:bg-gray-100 rounded-md transition-colors">
|
|
132
|
+
<MoreHorizontal size={16} className="text-gray-400" />
|
|
133
|
+
</button>
|
|
134
|
+
),
|
|
135
|
+
},
|
|
136
|
+
];
|
|
137
|
+
|
|
138
|
+
const tableUsage = `
|
|
139
|
+
const columns: ColumnDef<User>[] = [
|
|
140
|
+
{
|
|
141
|
+
accessorKey: "status",
|
|
142
|
+
header: "Status",
|
|
143
|
+
},
|
|
144
|
+
{
|
|
145
|
+
accessorKey: "email",
|
|
146
|
+
header: "Email",
|
|
147
|
+
},
|
|
148
|
+
{
|
|
149
|
+
accessorKey: "amount",
|
|
150
|
+
header: "Amount",
|
|
151
|
+
},
|
|
152
|
+
];
|
|
153
|
+
|
|
154
|
+
<DataTable
|
|
155
|
+
data={data}
|
|
156
|
+
columns={columns}
|
|
157
|
+
pageRows={5}
|
|
158
|
+
isLoading={false}
|
|
159
|
+
/>
|
|
160
|
+
`;
|
|
161
|
+
|
|
162
|
+
export default function DataTableExample() {
|
|
163
|
+
const [isLoading, setIsLoading] = useState(false);
|
|
164
|
+
|
|
165
|
+
return (
|
|
166
|
+
<div className="p-6 space-y-6 max-w-7xl mx-auto">
|
|
167
|
+
<PageHeader
|
|
168
|
+
title="Data Tables"
|
|
169
|
+
description="Powerful, accessible and flexible tables powered by TanStack Table."
|
|
170
|
+
/>
|
|
171
|
+
|
|
172
|
+
<div className="grid grid-cols-1 gap-6">
|
|
173
|
+
<Card>
|
|
174
|
+
<Card.Header>
|
|
175
|
+
<Card.Title>Advanced Example</Card.Title>
|
|
176
|
+
<Card.Description>
|
|
177
|
+
Table with selection, sorting, filtering, and pagination.
|
|
178
|
+
<button
|
|
179
|
+
onClick={() => {
|
|
180
|
+
setIsLoading(true);
|
|
181
|
+
setTimeout(() => setIsLoading(false), 2000);
|
|
182
|
+
}}
|
|
183
|
+
className="ml-4 text-blue-600 hover:underline text-xs"
|
|
184
|
+
>
|
|
185
|
+
Simulate Loading
|
|
186
|
+
</button>
|
|
187
|
+
</Card.Description>
|
|
188
|
+
</Card.Header>
|
|
189
|
+
<Card.Content className="space-y-6">
|
|
190
|
+
<DataTable
|
|
191
|
+
data={data}
|
|
192
|
+
columns={columns}
|
|
193
|
+
isLoading={isLoading}
|
|
194
|
+
// onChange={(state) => {
|
|
195
|
+
// console.log(state);
|
|
196
|
+
// }}
|
|
197
|
+
/>
|
|
198
|
+
|
|
199
|
+
<div className="pt-4">
|
|
200
|
+
<p className="text-sm font-medium mb-2">Usage</p>
|
|
201
|
+
<CodeBlock code={tableUsage} />
|
|
202
|
+
</div>
|
|
203
|
+
</Card.Content>
|
|
204
|
+
</Card>
|
|
205
|
+
</div>
|
|
206
|
+
</div>
|
|
207
|
+
);
|
|
208
|
+
}
|
|
@@ -0,0 +1,342 @@
|
|
|
1
|
+
import { useForm } from "react-hook-form";
|
|
2
|
+
import { Mail, Lock, User, Hash, Info, Phone } from "lucide-react";
|
|
3
|
+
import { Fields, Card, PageHeader, CodeBlock, Button } from "warqadui";
|
|
4
|
+
|
|
5
|
+
const FieldsShowcase = () => {
|
|
6
|
+
const form = useForm({
|
|
7
|
+
defaultValues: {
|
|
8
|
+
email: "",
|
|
9
|
+
password: "",
|
|
10
|
+
username: "",
|
|
11
|
+
amount: 0,
|
|
12
|
+
phone: "",
|
|
13
|
+
role: "",
|
|
14
|
+
bio: "",
|
|
15
|
+
userId: "",
|
|
16
|
+
dob: "",
|
|
17
|
+
},
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
const importCode = `import { Fields } from "warqadui";`;
|
|
21
|
+
|
|
22
|
+
const basicUsage = `<Fields.Input \n label="Username" \n placeholder="Enter username" \n icon={<User size={18} />} \n/>`;
|
|
23
|
+
|
|
24
|
+
const phoneUsage = `<Fields.PhoneInput\n label="Phone Number"\n form={form}\n name="phone"\n icon={<Phone size={18} />}\n/>`;
|
|
25
|
+
|
|
26
|
+
const selectUsage = `<Fields.Select\n label="Department"\n options={[\n { value: "engineering", label: "Engineering" },\n { value: "design", label: "Design" },\n { value: "marketing", label: "Marketing" },\n ]}\n icon={<User size={18} />}\n/>`;
|
|
27
|
+
|
|
28
|
+
const textareaUsage = `<Fields.Textarea\n label="Biography"\n placeholder="Tell us about yourself..."\n required\n/>`;
|
|
29
|
+
|
|
30
|
+
const dateUsage = `<Fields.DateInput\n label="Birth Date"\n placeholder="DD/MM/YYYY"\n required\n/>`;
|
|
31
|
+
|
|
32
|
+
const searchApiUsage = `<Fields.SearchApi\n label="User Search"\n apiUrl="/users"\n placeholder="Search users..."\n labelKey="username"\n valueKey="id"\n/>`;
|
|
33
|
+
|
|
34
|
+
const withForm = `const form = useForm();\n\n<Fields.Input\n form={form}\n name="email"\n label="Email Address"\n type="email"\n placeholder="alex@example.com"\n icon={<Mail size={18} />}\n required\n/>\n\n<Fields.PhoneInput\n form={form}\n name="phone"\n label="Phone Number"\n icon={<Phone size={18} />}\n required\n/>\n\n<Fields.Select\n form={form}\n name="role"\n label="User Role"\n options={[\n { value: "admin", label: "Admin" },\n { value: "editor", label: "Editor" },\n { value: "viewer", label: "Viewer" },\n ]}\n required\n/>\n\n<Fields.Textarea\n form={form}\n name="bio"\n label="Biography"\n placeholder="Something about you..."\n required\n/>\n\n<Fields.SearchApi\n form={form}\n name="userId"\n label="Remote Search"\n apiUrl="/users"\n placeholder="Search users..."\n labelKey="name"\n valueKey="_id"\n required\n/>\n\n<Fields.DateInput\n form={form}\n name="dob"\n label="Date of Birth"\n required\n/>`;
|
|
35
|
+
|
|
36
|
+
const passwordUsage = `<Fields.Input\n label="Password"\n type="password"\n placeholder="Min. 8 characters"\n icon={<Lock size={18} />}\n/>`;
|
|
37
|
+
|
|
38
|
+
const moneyUsage = `<Fields.Input\n label="Amount"\n type="number"\n placeholder="0.00"\n icon={<Hash size={18} />}\n form={form}\n name="amount"\n/>`;
|
|
39
|
+
|
|
40
|
+
const onSubmit = (data: any) => {
|
|
41
|
+
console.log("Form Data:", data);
|
|
42
|
+
alert("Form submitted! Check console for data.");
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
return (
|
|
46
|
+
<div className="p-8 space-y-12 pb-20">
|
|
47
|
+
<PageHeader
|
|
48
|
+
title="Form Fields"
|
|
49
|
+
description="Premium input components with built-in validation support, icon integration, and smooth interactive states. Optimized for React Hook Form."
|
|
50
|
+
/>
|
|
51
|
+
|
|
52
|
+
<section className="space-y-4">
|
|
53
|
+
<h2 className="text-xl font-bold flex items-center gap-2">Usage</h2>
|
|
54
|
+
<div className="grid grid-cols-1 lg:grid-cols-2 gap-6 items-start">
|
|
55
|
+
<Card variant="flat">
|
|
56
|
+
<p className="text-sm text-gray-600 dark:text-gray-400 font-medium mb-3">
|
|
57
|
+
1. Import components:
|
|
58
|
+
</p>
|
|
59
|
+
<CodeBlock code={importCode} />
|
|
60
|
+
</Card>
|
|
61
|
+
<Card variant="flat">
|
|
62
|
+
<p className="text-sm text-gray-600 dark:text-gray-400 font-medium mb-3">
|
|
63
|
+
2. Basic usage:
|
|
64
|
+
</p>
|
|
65
|
+
<CodeBlock code={basicUsage} />
|
|
66
|
+
</Card>
|
|
67
|
+
</div>
|
|
68
|
+
</section>
|
|
69
|
+
|
|
70
|
+
<section>
|
|
71
|
+
<h2 className="text-xl font-bold mb-6">Live Demos</h2>
|
|
72
|
+
<div className="grid grid-cols-1 md:grid-cols-2 gap-8">
|
|
73
|
+
{/* Basic Inputs */}
|
|
74
|
+
<Card>
|
|
75
|
+
<Card.Header>
|
|
76
|
+
<Card.Title>Input Variations</Card.Title>
|
|
77
|
+
<Card.Description>
|
|
78
|
+
Common input types with icon support and floating-style focus
|
|
79
|
+
states.
|
|
80
|
+
</Card.Description>
|
|
81
|
+
</Card.Header>
|
|
82
|
+
<Card.Content className="space-y-6">
|
|
83
|
+
<Fields.Input
|
|
84
|
+
label="Username"
|
|
85
|
+
placeholder="Enter username"
|
|
86
|
+
icon={<User size={18} />}
|
|
87
|
+
/>
|
|
88
|
+
<Fields.Input
|
|
89
|
+
label="Password"
|
|
90
|
+
type="password"
|
|
91
|
+
placeholder="Enter password"
|
|
92
|
+
icon={<Lock size={18} />}
|
|
93
|
+
/>
|
|
94
|
+
<CodeBlock code={passwordUsage} className="text-[11px]" />
|
|
95
|
+
</Card.Content>
|
|
96
|
+
</Card>
|
|
97
|
+
{/* Money/Number Input */}
|
|
98
|
+
<Card>
|
|
99
|
+
<Card.Header>
|
|
100
|
+
<Card.Title>Formatted Number Input</Card.Title>
|
|
101
|
+
<Card.Description>
|
|
102
|
+
Special handling for currency/number inputs with automatic comma
|
|
103
|
+
formatting.
|
|
104
|
+
</Card.Description>
|
|
105
|
+
</Card.Header>
|
|
106
|
+
<Card.Content className="space-y-6">
|
|
107
|
+
<Fields.Input
|
|
108
|
+
label="Transaction Amount"
|
|
109
|
+
type="number"
|
|
110
|
+
placeholder="0.00"
|
|
111
|
+
icon={<Hash size={18} />}
|
|
112
|
+
form={form}
|
|
113
|
+
name="amount"
|
|
114
|
+
/>
|
|
115
|
+
<div className="p-3 bg-blue-50 dark:bg-blue-900/20 rounded-lg flex items-start gap-3">
|
|
116
|
+
<Info size={16} className="text-blue-500 mt-0.5" />
|
|
117
|
+
<p className="text-xs text-blue-700 dark:text-blue-400">
|
|
118
|
+
Try typing "1000000" to see automatic formatting: 1,000,000
|
|
119
|
+
</p>
|
|
120
|
+
</div>
|
|
121
|
+
<CodeBlock code={moneyUsage} className="text-[11px]" />
|
|
122
|
+
</Card.Content>
|
|
123
|
+
</Card>
|
|
124
|
+
{/* Phone Input */}
|
|
125
|
+
<Card>
|
|
126
|
+
<Card.Header>
|
|
127
|
+
<Card.Title>Phone Number Input</Card.Title>
|
|
128
|
+
<Card.Description>
|
|
129
|
+
International phone number input with country selector and
|
|
130
|
+
validation.
|
|
131
|
+
</Card.Description>
|
|
132
|
+
</Card.Header>
|
|
133
|
+
<Card.Content className="space-y-6">
|
|
134
|
+
<Fields.PhoneInput
|
|
135
|
+
label="Phone Number"
|
|
136
|
+
form={form}
|
|
137
|
+
name="phone"
|
|
138
|
+
icon={<Phone size={18} />}
|
|
139
|
+
/>
|
|
140
|
+
<CodeBlock code={phoneUsage} className="text-[11px]" />
|
|
141
|
+
</Card.Content>
|
|
142
|
+
</Card>
|
|
143
|
+
{/* Select Input */}
|
|
144
|
+
<Card>
|
|
145
|
+
<Card.Header>
|
|
146
|
+
<Card.Title>Select Field</Card.Title>
|
|
147
|
+
<Card.Description>
|
|
148
|
+
Custom styled select component with support for icons and
|
|
149
|
+
validation.
|
|
150
|
+
</Card.Description>
|
|
151
|
+
</Card.Header>
|
|
152
|
+
<Card.Content className="space-y-6">
|
|
153
|
+
<Fields.Select
|
|
154
|
+
label="Region"
|
|
155
|
+
options={[
|
|
156
|
+
{ value: "africa", label: "Africa" },
|
|
157
|
+
{ value: "europe", label: "Europe" },
|
|
158
|
+
{ value: "asia", label: "Asia" },
|
|
159
|
+
{ value: "americas", label: "Americas" },
|
|
160
|
+
]}
|
|
161
|
+
icon={<Mail size={18} />}
|
|
162
|
+
/>
|
|
163
|
+
<CodeBlock code={selectUsage} className="text-[11px]" />
|
|
164
|
+
</Card.Content>
|
|
165
|
+
</Card>
|
|
166
|
+
{/* Textarea Input */}
|
|
167
|
+
<Card>
|
|
168
|
+
<Card.Header>
|
|
169
|
+
<Card.Title>Textarea Field</Card.Title>
|
|
170
|
+
<Card.Description>
|
|
171
|
+
Multi-line text input with smooth focus states and consistent
|
|
172
|
+
styling.
|
|
173
|
+
</Card.Description>
|
|
174
|
+
</Card.Header>
|
|
175
|
+
<Card.Content className="space-y-6">
|
|
176
|
+
<Fields.Textarea
|
|
177
|
+
label="Message"
|
|
178
|
+
placeholder="Enter your message here..."
|
|
179
|
+
required
|
|
180
|
+
/>
|
|
181
|
+
<CodeBlock code={textareaUsage} className="text-[11px]" />
|
|
182
|
+
</Card.Content>
|
|
183
|
+
</Card>
|
|
184
|
+
{/* SearchApi Input */}
|
|
185
|
+
<Card>
|
|
186
|
+
<Card.Header>
|
|
187
|
+
<Card.Title>Search API (Autocomplete)</Card.Title>
|
|
188
|
+
<Card.Description>
|
|
189
|
+
Remote data fetching with debounce, keyboard navigation, and
|
|
190
|
+
automatic hydration.
|
|
191
|
+
</Card.Description>
|
|
192
|
+
</Card.Header>
|
|
193
|
+
<Card.Content className="space-y-6">
|
|
194
|
+
<Fields.SearchApi
|
|
195
|
+
label="User Database"
|
|
196
|
+
apiUrl="/users"
|
|
197
|
+
placeholder="Search users..."
|
|
198
|
+
labelKey="name"
|
|
199
|
+
valueKey="_id"
|
|
200
|
+
/>
|
|
201
|
+
<CodeBlock code={searchApiUsage} className="text-[11px]" />
|
|
202
|
+
</Card.Content>
|
|
203
|
+
</Card>
|
|
204
|
+
|
|
205
|
+
{/* Date Input */}
|
|
206
|
+
<Card className="md:col-span-2">
|
|
207
|
+
<Card.Header>
|
|
208
|
+
<Card.Title>Date Picker</Card.Title>
|
|
209
|
+
<Card.Description>
|
|
210
|
+
Premium date selection with custom styling, keyboard support,
|
|
211
|
+
and localized formatting.
|
|
212
|
+
</Card.Description>
|
|
213
|
+
</Card.Header>
|
|
214
|
+
<Card.Content className="space-y-6">
|
|
215
|
+
<Fields.DateInput
|
|
216
|
+
label="Select Date"
|
|
217
|
+
placeholder="DD/MM/YYYY"
|
|
218
|
+
value="04/03/2026"
|
|
219
|
+
onChange={(d) => console.log(d)}
|
|
220
|
+
/>
|
|
221
|
+
<CodeBlock code={dateUsage} className="text-[11px]" />
|
|
222
|
+
</Card.Content>
|
|
223
|
+
</Card>
|
|
224
|
+
{/* Form Integration */}
|
|
225
|
+
<Card className="md:col-span-2">
|
|
226
|
+
<Card.Header>
|
|
227
|
+
<Card.Title>React Hook Form Integration</Card.Title>
|
|
228
|
+
<Card.Description>
|
|
229
|
+
Seamlessly connects with <code>react-hook-form</code> for
|
|
230
|
+
validation and error handling.
|
|
231
|
+
</Card.Description>
|
|
232
|
+
</Card.Header>
|
|
233
|
+
<Card.Content>
|
|
234
|
+
<form
|
|
235
|
+
onSubmit={form.handleSubmit(onSubmit)}
|
|
236
|
+
className="space-y-6"
|
|
237
|
+
>
|
|
238
|
+
<div className="grid grid-cols-1 md:grid-cols-2 gap-6">
|
|
239
|
+
<Fields.Input
|
|
240
|
+
form={form}
|
|
241
|
+
name="username"
|
|
242
|
+
label="Full Name"
|
|
243
|
+
placeholder="John Doe"
|
|
244
|
+
icon={<User size={18} />}
|
|
245
|
+
required
|
|
246
|
+
/>
|
|
247
|
+
<Fields.Input
|
|
248
|
+
form={form}
|
|
249
|
+
name="email"
|
|
250
|
+
label="Email Address"
|
|
251
|
+
type="email"
|
|
252
|
+
placeholder="john@example.com"
|
|
253
|
+
icon={<Mail size={18} />}
|
|
254
|
+
required
|
|
255
|
+
/>
|
|
256
|
+
<Fields.PhoneInput
|
|
257
|
+
form={form}
|
|
258
|
+
name="phone"
|
|
259
|
+
label="Phone Number"
|
|
260
|
+
icon={<Phone size={18} />}
|
|
261
|
+
required
|
|
262
|
+
/>
|
|
263
|
+
<Fields.Select
|
|
264
|
+
form={form}
|
|
265
|
+
name="role"
|
|
266
|
+
label="User Role"
|
|
267
|
+
options={[
|
|
268
|
+
{ value: "admin", label: "Admin" },
|
|
269
|
+
{ value: "editor", label: "Editor" },
|
|
270
|
+
{ value: "viewer", label: "Viewer" },
|
|
271
|
+
]}
|
|
272
|
+
required
|
|
273
|
+
/>
|
|
274
|
+
<Fields.Textarea
|
|
275
|
+
form={form}
|
|
276
|
+
name="bio"
|
|
277
|
+
label="Biography"
|
|
278
|
+
placeholder="Tell us about yourself..."
|
|
279
|
+
className="md:col-span-2"
|
|
280
|
+
required
|
|
281
|
+
/>
|
|
282
|
+
<Fields.SearchApi
|
|
283
|
+
form={form}
|
|
284
|
+
name="userId"
|
|
285
|
+
label="User Selection"
|
|
286
|
+
apiUrl="/users"
|
|
287
|
+
placeholder="Search for a user..."
|
|
288
|
+
labelKey="name"
|
|
289
|
+
valueKey="_id"
|
|
290
|
+
className="md:col-span-2"
|
|
291
|
+
required
|
|
292
|
+
/>
|
|
293
|
+
<Fields.DateInput
|
|
294
|
+
form={form}
|
|
295
|
+
name="dob"
|
|
296
|
+
label="Date of Birth"
|
|
297
|
+
containerClassName="md:col-span-2"
|
|
298
|
+
required
|
|
299
|
+
/>
|
|
300
|
+
</div>
|
|
301
|
+
<div className="flex flex-col md:flex-row gap-6 items-start">
|
|
302
|
+
<div className="flex-1 w-full">
|
|
303
|
+
<CodeBlock code={withForm} className="text-[11px] h-full" />
|
|
304
|
+
</div>
|
|
305
|
+
<div className="w-full md:w-64 space-y-4">
|
|
306
|
+
<Button
|
|
307
|
+
type="submit"
|
|
308
|
+
variant="primary"
|
|
309
|
+
className="w-full h-12"
|
|
310
|
+
>
|
|
311
|
+
Submit Form
|
|
312
|
+
</Button>
|
|
313
|
+
<p className="text-[10px] text-gray-500 text-center">
|
|
314
|
+
Submitting will show an alert with the current form state.
|
|
315
|
+
</p>
|
|
316
|
+
</div>
|
|
317
|
+
</div>
|
|
318
|
+
</form>
|
|
319
|
+
</Card.Content>
|
|
320
|
+
</Card>
|
|
321
|
+
</div>
|
|
322
|
+
</section>
|
|
323
|
+
|
|
324
|
+
<Card
|
|
325
|
+
variant="glass"
|
|
326
|
+
className="bg-indigo-50/50 dark:bg-indigo-900/10 border-indigo-100 dark:border-indigo-900/20"
|
|
327
|
+
>
|
|
328
|
+
<Card.Title className="text-indigo-900 dark:text-indigo-400 mb-2">
|
|
329
|
+
Validation Features
|
|
330
|
+
</Card.Title>
|
|
331
|
+
<Card.Description className="text-indigo-700 dark:text-indigo-600">
|
|
332
|
+
The <code>Fields.Input</code> component automatically extracts error
|
|
333
|
+
messages from the React Hook Form state based on the <code>name</code>{" "}
|
|
334
|
+
prop. It also clears errors automatically as the user types, providing
|
|
335
|
+
a smoother UX.
|
|
336
|
+
</Card.Description>
|
|
337
|
+
</Card>
|
|
338
|
+
</div>
|
|
339
|
+
);
|
|
340
|
+
};
|
|
341
|
+
|
|
342
|
+
export default FieldsShowcase;
|