@axzydev/axzy_ui_system 1.2.7 → 1.2.9
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 +105 -53
- package/dist/index.cjs +576 -398
- package/dist/index.cjs.map +1 -1
- package/dist/index.css +1 -1
- package/dist/index.css.map +1 -1
- package/dist/index.d.cts +1463 -86
- package/dist/index.d.ts +1463 -86
- package/dist/index.js +597 -417
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/src/App.tsx +26 -54
- package/src/components/alert/alert.doc.mdx +48 -0
- package/src/components/alert/alert.props.ts +7 -0
- package/src/components/alert/alert.tsx +8 -0
- package/src/components/avatar/avatar.doc.mdx +48 -0
- package/src/components/avatar/avatar.props.ts +8 -0
- package/src/components/avatar/avatar.tsx +25 -5
- package/src/components/badget/badget.doc.mdx +46 -0
- package/src/components/badget/badget.props.ts +6 -0
- package/src/components/badget/badget.tsx +11 -0
- package/src/components/breadcrumbs/breadcrumbs.doc.mdx +57 -0
- package/src/components/breadcrumbs/breadcrumbs.props.ts +6 -0
- package/src/components/breadcrumbs/breadcrumbs.tsx +12 -0
- package/src/components/button/button.doc.mdx +59 -0
- package/src/components/button/button.props.ts +12 -0
- package/src/components/button/button.tsx +11 -0
- package/src/components/calendar/calendar.doc.mdx +75 -0
- package/src/components/calendar/calendar.props.ts +27 -7
- package/src/components/calendar/calendar.tsx +13 -0
- package/src/components/card/card.doc.mdx +54 -0
- package/src/components/card/card.props.ts +11 -0
- package/src/components/card/card.tsx +13 -0
- package/src/components/checkbox/checkbox.doc.mdx +54 -0
- package/src/components/checkbox/checkbox.props.ts +7 -0
- package/src/components/checkbox/checkbox.tsx +9 -0
- package/src/components/confirm-dialog/confirm-dialog.doc.mdx +60 -0
- package/src/components/confirm-dialog/confirm-dialog.props.ts +9 -0
- package/src/components/confirm-dialog/confirm-dialog.tsx +19 -0
- package/src/components/data-table/ITDataTable.doc.mdx +59 -0
- package/src/components/data-table/dataTable.props.ts +15 -0
- package/src/components/data-table/dataTable.tsx +178 -73
- package/src/components/date-picker/date-picker.doc.mdx +65 -0
- package/src/components/date-picker/date-picker.props.ts +17 -0
- package/src/components/date-picker/datePicker.tsx +31 -1
- package/src/components/dialog/dialog.doc.mdx +54 -0
- package/src/components/dialog/dialog.props.ts +7 -0
- package/src/components/dialog/dialog.tsx +26 -0
- package/src/components/divider/divider.doc.mdx +42 -0
- package/src/components/divider/divider.props.ts +5 -0
- package/src/components/divider/divider.tsx +16 -0
- package/src/components/drawer/drawer.doc.mdx +59 -0
- package/src/components/drawer/drawer.props.ts +9 -0
- package/src/components/drawer/drawer.tsx +20 -0
- package/src/components/dropfile/dropfile.doc.mdx +59 -0
- package/src/components/dropfile/dropfile.props.ts +41 -0
- package/src/components/dropfile/dropfile.tsx +21 -33
- package/src/components/empty-state/empty-state.doc.mdx +50 -0
- package/src/components/empty-state/empty-state.props.ts +5 -0
- package/src/components/empty-state/empty-state.tsx +16 -0
- package/src/components/flex/flex.doc.mdx +59 -0
- package/src/components/flex/flex.props.ts +13 -0
- package/src/components/flex/flex.tsx +15 -0
- package/src/components/form-builder/fieldRenderer.tsx +52 -2
- package/src/components/form-builder/formBuilder.doc.mdx +124 -0
- package/src/components/form-builder/formBuilder.props.ts +12 -2
- package/src/components/form-builder/formBuilder.tsx +31 -0
- package/src/components/form-header/form-header.doc.mdx +38 -0
- package/src/components/form-header/form-header.props.ts +3 -0
- package/src/components/form-header/form-header.stories.tsx +53 -0
- package/src/components/form-header/form-header.tsx +11 -0
- package/src/components/grid/grid.doc.mdx +54 -0
- package/src/components/grid/grid.props.ts +13 -0
- package/src/components/grid/grid.tsx +19 -0
- package/src/components/image/image.doc.mdx +44 -0
- package/src/components/image/image.props.ts +5 -0
- package/src/components/image/image.stories.tsx +49 -0
- package/src/components/image/image.tsx +19 -0
- package/src/components/input/input.doc.mdx +70 -0
- package/src/components/input/input.props.ts +34 -2
- package/src/components/input/input.tsx +29 -0
- package/src/components/layout/layout.doc.mdx +51 -0
- package/src/components/layout/layout.props.ts +5 -0
- package/src/components/layout/layout.tsx +29 -2
- package/src/components/loader/loader.doc.mdx +43 -0
- package/src/components/loader/loader.props.ts +4 -0
- package/src/components/loader/loader.tsx +17 -0
- package/src/components/navbar/navbar.doc.mdx +77 -0
- package/src/components/navbar/navbar.props.ts +37 -1
- package/src/components/navbar/navbar.stories.tsx +84 -0
- package/src/components/navbar/navbar.tsx +27 -0
- package/src/components/page/page.doc.mdx +80 -0
- package/src/components/page/page.props.ts +21 -0
- package/src/components/page/page.tsx +18 -0
- package/src/components/page-header/page-header.doc.mdx +54 -0
- package/src/components/page-header/page-header.props.ts +9 -0
- package/src/components/page-header/page-header.tsx +15 -0
- package/src/components/pagination/pagination.doc.mdx +62 -0
- package/src/components/pagination/pagination.props.ts +11 -32
- package/src/components/pagination/pagination.tsx +17 -0
- package/src/components/popover/popover.doc.mdx +53 -0
- package/src/components/popover/popover.props.ts +8 -0
- package/src/components/popover/popover.tsx +13 -0
- package/src/components/progress/progress.doc.mdx +48 -0
- package/src/components/progress/progress.props.ts +8 -0
- package/src/components/progress/progress.tsx +9 -0
- package/src/components/radio/radio.doc.mdx +62 -0
- package/src/components/radio/radio.props.ts +11 -0
- package/src/components/radio/radio.tsx +18 -0
- package/src/components/search-select/search-select.doc.mdx +72 -0
- package/src/components/search-select/search-select.props.ts +23 -18
- package/src/components/search-select/search-select.tsx +27 -2
- package/src/components/searchTable/searchTable.doc.mdx +79 -0
- package/src/components/searchTable/searchTable.props.ts +42 -3
- package/src/components/searchTable/searchTable.stories.tsx +74 -0
- package/src/components/searchTable/searchTable.tsx +23 -0
- package/src/components/segmented-control/segmented-control.doc.mdx +60 -0
- package/src/components/segmented-control/segmented-control.props.ts +12 -0
- package/src/components/segmented-control/segmented-control.tsx +15 -0
- package/src/components/select/select.doc.mdx +75 -0
- package/src/components/select/select.props.ts +22 -0
- package/src/components/select/select.tsx +2 -5
- package/src/components/sidebar/sidebar.doc.mdx +86 -0
- package/src/components/sidebar/sidebar.props.ts +22 -0
- package/src/components/sidebar/sidebar.tsx +22 -0
- package/src/components/skeleton/skeleton.doc.mdx +43 -0
- package/src/components/skeleton/skeleton.props.ts +8 -0
- package/src/components/skeleton/skeleton.tsx +10 -0
- package/src/components/slide/slide.doc.mdx +46 -0
- package/src/components/slide/slide.props.ts +11 -24
- package/src/components/slide/slide.tsx +10 -1
- package/src/components/slider/slider.doc.mdx +49 -0
- package/src/components/slider/slider.props.ts +9 -0
- package/src/components/slider/slider.tsx +15 -0
- package/src/components/stack/stack.doc.mdx +126 -0
- package/src/components/stack/stack.props.ts +18 -0
- package/src/components/stack/stack.stories.tsx +221 -16
- package/src/components/stack/stack.tsx +21 -0
- package/src/components/stat-card/stat-card.doc.mdx +48 -0
- package/src/components/stat-card/stat-card.props.ts +9 -0
- package/src/components/stat-card/stat-card.tsx +10 -0
- package/src/components/stepper/stepper.doc.mdx +54 -0
- package/src/components/stepper/stepper.props.ts +11 -1
- package/src/components/stepper/stepper.tsx +15 -0
- package/src/components/table/table.doc.mdx +58 -0
- package/src/components/table/table.props.ts +17 -0
- package/src/components/table/table.tsx +199 -84
- package/src/components/tabs/tabs.doc.mdx +52 -0
- package/src/components/tabs/tabs.props.ts +11 -0
- package/src/components/tabs/tabs.tsx +14 -0
- package/src/components/text/text.doc.mdx +41 -0
- package/src/components/text/text.props.ts +5 -0
- package/src/components/text/text.stories.tsx +67 -0
- package/src/components/text/text.tsx +10 -0
- package/src/components/textarea/textarea.doc.mdx +64 -0
- package/src/components/textarea/textarea.props.ts +11 -0
- package/src/components/textarea/textarea.tsx +16 -0
- package/src/components/theme-provider/themeProvider.doc.mdx +75 -0
- package/src/components/theme-provider/themeProvider.props.ts +3 -0
- package/src/components/theme-provider/themeProvider.stories.tsx +59 -0
- package/src/components/theme-provider/themeProvider.tsx +14 -0
- package/src/components/time-picker/timePicker.doc.mdx +68 -0
- package/src/components/time-picker/timePicker.props.ts +14 -0
- package/src/components/time-picker/timePicker.tsx +22 -1
- package/src/components/toast/toast.doc.mdx +50 -0
- package/src/components/toast/toast.props.ts +5 -0
- package/src/components/toast/toast.tsx +21 -0
- package/src/components/tooltip/tooltip.doc.mdx +47 -0
- package/src/components/tooltip/tooltip.props.ts +6 -0
- package/src/components/tooltip/tooltip.tsx +19 -0
- package/src/components/topbar/topbar.doc.mdx +69 -0
- package/src/components/topbar/topbar.props.ts +15 -0
- package/src/components/topbar/topbar.tsx +38 -0
- package/src/components/triple-filter/tripleFilter.doc.mdx +62 -0
- package/src/components/triple-filter/tripleFilter.props.ts +7 -0
- package/src/components/triple-filter/tripleFilter.tsx +32 -0
- package/src/index.css +2 -0
- package/src/showcases/DataShowcases.tsx +529 -45
- package/src/showcases/FormShowcases.tsx +399 -29
- package/src/showcases/GettingStartedShowcase.tsx +207 -0
- package/src/showcases/HomeShowcase.tsx +252 -272
- package/src/showcases/LayoutPrimitivesShowcases.tsx +1224 -248
- package/src/showcases/PageShowcases.tsx +688 -391
- package/src/showcases/ShowcaseLayout.tsx +237 -73
- package/src/showcases/StructureShowcases.tsx +846 -73
- package/src/types/table.types.ts +1 -1
- package/src/utils/styles.ts +2 -1
|
@@ -3,6 +3,11 @@ import {
|
|
|
3
3
|
ITTable,
|
|
4
4
|
ITDataTable,
|
|
5
5
|
ITBadget,
|
|
6
|
+
ITAvatar,
|
|
7
|
+
ITButton,
|
|
8
|
+
ITFlex,
|
|
9
|
+
ITStack,
|
|
10
|
+
ITText,
|
|
6
11
|
ITImage,
|
|
7
12
|
ITInput,
|
|
8
13
|
ITSelect,
|
|
@@ -12,49 +17,174 @@ import {
|
|
|
12
17
|
} from "../index";
|
|
13
18
|
import { ShowcaseLayout } from "./ShowcaseLayout";
|
|
14
19
|
|
|
20
|
+
const TABLE_DATA: Record<string, unknown>[] = [
|
|
21
|
+
{ id: 1, name: "Sofía Castillo", email: "sofia@axzy.dev", role: "Admin", status: "active", lastLogin: "2026-07-18T09:30:00", sales: 28400 },
|
|
22
|
+
{ id: 2, name: "Daniela Klein", email: "daniela@axzy.dev", role: "Editor", status: "active", lastLogin: "2026-07-17T14:22:00", sales: 15200 },
|
|
23
|
+
{ id: 3, name: "Mariana Reyes", email: "mariana@axzy.dev", role: "Viewer", status: "inactive", lastLogin: "2026-07-10T11:00:00", sales: 3200 },
|
|
24
|
+
{ id: 4, name: "Camila Torres", email: "camila@axzy.dev", role: "Admin", status: "active", lastLogin: "2026-07-18T08:15:00", sales: 42100 },
|
|
25
|
+
{ id: 5, name: "Valentina Méndez", email: "valentina@axzy.dev", role: "Editor", status: "active", lastLogin: "2026-07-16T19:45:00", sales: 9800 },
|
|
26
|
+
{ id: 6, name: "Luciana Rivas", email: "luciana@axzy.dev", role: "Viewer", status: "inactive", lastLogin: "2026-06-28T16:30:00", sales: 1500 },
|
|
27
|
+
{ id: 7, name: "Isabella Cruz", email: "isabella@axzy.dev", role: "Editor", status: "active", lastLogin: "2026-07-18T10:05:00", sales: 20300 },
|
|
28
|
+
{ id: 8, name: "Gabriela Vargas", email: "gabriela@axzy.dev", role: "Admin", status: "active", lastLogin: "2026-07-15T22:10:00", sales: 35600 },
|
|
29
|
+
{ id: 9, name: "Ana López", email: "ana@axzy.dev", role: "Editor", status: "pending", lastLogin: "2026-07-14T11:20:00", sales: 7500 },
|
|
30
|
+
{ id: 10, name: "Carla Jiménez", email: "carla@axzy.dev", role: "Viewer", status: "active", lastLogin: "2026-07-13T16:45:00", sales: 4100 },
|
|
31
|
+
{ id: 11, name: "Luisa Fernández", email: "luisa@axzy.dev", role: "Admin", status: "active", lastLogin: "2026-07-12T08:00:00", sales: 51200 },
|
|
32
|
+
{ id: 12, name: "Renata Morales", email: "renata@axzy.dev", role: "Editor", status: "inactive", lastLogin: "2026-06-30T12:15:00", sales: 6800 },
|
|
33
|
+
{ id: 13, name: "Paola Herrera", email: "paola@axzy.dev", role: "Viewer", status: "pending", lastLogin: "2026-07-11T09:30:00", sales: 900 },
|
|
34
|
+
{ id: 14, name: "Ximena Ríos", email: "ximena@axzy.dev", role: "Editor", status: "active", lastLogin: "2026-07-17T15:50:00", sales: 16700 },
|
|
35
|
+
{ id: 15, name: "Florencia Díaz", email: "florencia@axzy.dev", role: "Admin", status: "active", lastLogin: "2026-07-18T07:15:00", sales: 48900 },
|
|
36
|
+
];
|
|
37
|
+
|
|
38
|
+
const nameColumn = {
|
|
39
|
+
key: "name",
|
|
40
|
+
label: "Name",
|
|
41
|
+
type: "string" as const,
|
|
42
|
+
sortable: true,
|
|
43
|
+
filter: true,
|
|
44
|
+
render: (row: Record<string, unknown>) => {
|
|
45
|
+
const initials = (row.name as string).split(" ").map((w: string) => w[0]).join("");
|
|
46
|
+
return (
|
|
47
|
+
<div className="flex items-center gap-2.5">
|
|
48
|
+
<ITAvatar initials={initials} size="sm" />
|
|
49
|
+
<div>
|
|
50
|
+
<p className="font-semibold text-slate-800 dark:text-white text-sm leading-tight">{row.name as string}</p>
|
|
51
|
+
<p className="text-[10px] text-slate-400">{row.email as string}</p>
|
|
52
|
+
</div>
|
|
53
|
+
</div>
|
|
54
|
+
);
|
|
55
|
+
},
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
const statusColor = (s: string) =>
|
|
59
|
+
s === "active" ? "bg-emerald-100 text-emerald-700 dark:bg-emerald-950/30 dark:text-emerald-300" :
|
|
60
|
+
s === "pending" ? "bg-amber-100 text-amber-700 dark:bg-amber-950/30 dark:text-amber-300" :
|
|
61
|
+
"bg-slate-100 text-slate-600 dark:bg-slate-800 dark:text-slate-400";
|
|
62
|
+
|
|
63
|
+
const roleColor = (r: string) =>
|
|
64
|
+
r === "Admin" ? "bg-primary-100 text-primary-700 dark:bg-primary-950/40 dark:text-primary-300" :
|
|
65
|
+
r === "Editor" ? "bg-blue-100 text-blue-700 dark:bg-blue-950/40 dark:text-blue-300" :
|
|
66
|
+
"bg-slate-100 text-slate-600 dark:bg-slate-800 dark:text-slate-400";
|
|
67
|
+
|
|
15
68
|
// 1. ITTable Showcase
|
|
16
69
|
export const TableShowcase = () => {
|
|
17
70
|
const [variant, setVariant] = useState<any>("default");
|
|
18
|
-
const [size, setSize] = useState<any>("
|
|
71
|
+
const [size, setSize] = useState<any>("sm");
|
|
72
|
+
const [useCustomCard, setUseCustomCard] = useState(true);
|
|
73
|
+
|
|
74
|
+
const customCard = (row: Record<string, unknown>) => {
|
|
75
|
+
const initials = (row.name as string).split(" ").map((w: string) => w[0]).join("");
|
|
76
|
+
const status = row.status as string;
|
|
77
|
+
const role = row.role as string;
|
|
78
|
+
const date = new Date(row.lastLogin as string);
|
|
79
|
+
return (
|
|
80
|
+
<div className="group bg-white dark:bg-slate-800 rounded-xl border border-slate-200 dark:border-slate-700 p-4 transition-all duration-200 hover:-translate-y-0.5 hover:shadow-lg hover:border-slate-300 dark:hover:border-slate-600">
|
|
81
|
+
<div className="flex items-start justify-between mb-3">
|
|
82
|
+
<div className="flex items-center gap-3">
|
|
83
|
+
<ITAvatar initials={initials} size="md" />
|
|
84
|
+
<div>
|
|
85
|
+
<p className="font-bold text-slate-800 dark:text-white text-sm">{row.name as string}</p>
|
|
86
|
+
<p className="text-xs text-slate-400">{row.email as string}</p>
|
|
87
|
+
</div>
|
|
88
|
+
</div>
|
|
89
|
+
<span className={`px-2 py-0.5 text-[10px] font-bold uppercase tracking-wider rounded-md ${statusColor(status)}`}>
|
|
90
|
+
{status}
|
|
91
|
+
</span>
|
|
92
|
+
</div>
|
|
93
|
+
<div className="flex items-center gap-3 text-xs text-slate-500 mb-3">
|
|
94
|
+
<span className={`px-2 py-0.5 rounded-md font-semibold ${roleColor(role)}`}>{role}</span>
|
|
95
|
+
<span>Last login: {date.toLocaleDateString("en-US", { month: "short", day: "numeric" })}</span>
|
|
96
|
+
</div>
|
|
97
|
+
<div className="flex items-center justify-between pt-3 border-t border-slate-100 dark:border-slate-700">
|
|
98
|
+
<span className="text-xs text-slate-400">Sales: <strong className="text-slate-700 dark:text-slate-200">${(row.sales as number).toLocaleString()}</strong></span>
|
|
99
|
+
<div className="flex gap-1.5 opacity-0 group-hover:opacity-100 transition-opacity">
|
|
100
|
+
<button className="p-1.5 rounded-md hover:bg-slate-100 dark:hover:bg-slate-700 text-slate-400 hover:text-primary-600 transition-colors">
|
|
101
|
+
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2"><path d="M1 12s4-8 11-8 11 8 11 8-4 8-11 8-11-8-11-8z"/><circle cx="12" cy="12" r="3"/></svg>
|
|
102
|
+
</button>
|
|
103
|
+
<button className="p-1.5 rounded-md hover:bg-slate-100 dark:hover:bg-slate-700 text-slate-400 hover:text-blue-600 transition-colors">
|
|
104
|
+
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2"><path d="M11 4H4a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-7"/><path d="M18.5 2.5a2.121 2.121 0 0 1 3 3L12 15l-4 1 1-4 9.5-9.5z"/></svg>
|
|
105
|
+
</button>
|
|
106
|
+
</div>
|
|
107
|
+
</div>
|
|
108
|
+
</div>
|
|
109
|
+
);
|
|
110
|
+
};
|
|
19
111
|
|
|
20
112
|
const columns: any = [
|
|
21
|
-
|
|
22
|
-
{ key: "
|
|
23
|
-
{
|
|
113
|
+
nameColumn,
|
|
114
|
+
{ key: "email", label: "Email", type: "string", sortable: true, filter: true, className: "hidden lg:table-cell" },
|
|
115
|
+
{
|
|
116
|
+
key: "role",
|
|
117
|
+
label: "Role",
|
|
118
|
+
type: "string",
|
|
119
|
+
sortable: true,
|
|
120
|
+
filter: true,
|
|
121
|
+
render: (row: any) => (
|
|
122
|
+
<span className={`px-2 py-0.5 text-[10px] font-bold uppercase tracking-wider rounded-md ${roleColor(row.role)}`}>
|
|
123
|
+
{row.role}
|
|
124
|
+
</span>
|
|
125
|
+
)
|
|
126
|
+
},
|
|
24
127
|
{
|
|
25
128
|
key: "status",
|
|
26
|
-
label: "
|
|
27
|
-
type: "
|
|
129
|
+
label: "Status",
|
|
130
|
+
type: "string",
|
|
131
|
+
sortable: true,
|
|
132
|
+
filter: true,
|
|
28
133
|
render: (row: any) => (
|
|
29
|
-
<
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
134
|
+
<span className={`px-2 py-0.5 text-[10px] font-bold uppercase tracking-wider rounded-md ${statusColor(row.status)}`}>
|
|
135
|
+
{row.status}
|
|
136
|
+
</span>
|
|
137
|
+
)
|
|
138
|
+
},
|
|
139
|
+
{
|
|
140
|
+
key: "sales",
|
|
141
|
+
label: "Sales",
|
|
142
|
+
type: "number",
|
|
143
|
+
sortable: true,
|
|
144
|
+
render: (row: any) => <span className="font-mono font-semibold text-slate-800 dark:text-white">${(row.sales as number).toLocaleString()}</span>
|
|
145
|
+
},
|
|
146
|
+
{
|
|
147
|
+
key: "actions",
|
|
148
|
+
label: "",
|
|
149
|
+
type: "actions",
|
|
150
|
+
actions: (row: any) => (
|
|
151
|
+
<div className="flex gap-1">
|
|
152
|
+
<button className="p-1.5 rounded-md hover:bg-slate-100 dark:hover:bg-slate-700 text-slate-400 hover:text-primary-600 transition-colors" title="View">
|
|
153
|
+
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2"><path d="M1 12s4-8 11-8 11 8 11 8-4 8-11 8-11-8-11-8z"/><circle cx="12" cy="12" r="3"/></svg>
|
|
154
|
+
</button>
|
|
155
|
+
<button className="p-1.5 rounded-md hover:bg-slate-100 dark:hover:bg-slate-700 text-slate-400 hover:text-blue-600 transition-colors" title="Edit">
|
|
156
|
+
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2"><path d="M11 4H4a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-7"/><path d="M18.5 2.5a2.121 2.121 0 0 1 3 3L12 15l-4 1 1-4 9.5-9.5z"/></svg>
|
|
157
|
+
</button>
|
|
158
|
+
</div>
|
|
34
159
|
)
|
|
35
160
|
}
|
|
36
161
|
];
|
|
37
162
|
|
|
38
|
-
const
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
163
|
+
const code = `<ITTable
|
|
164
|
+
columns={columns}
|
|
165
|
+
data={data}
|
|
166
|
+
title="Team members"
|
|
167
|
+
variant="${variant}"
|
|
168
|
+
size="${size}"
|
|
169
|
+
defaultItemsPerPage={5}
|
|
170
|
+
renderCard={(row) => <CustomCard row={row} />}
|
|
171
|
+
/>`;
|
|
45
172
|
|
|
46
173
|
return (
|
|
47
174
|
<ShowcaseLayout
|
|
48
175
|
title="ITTable"
|
|
49
|
-
description="
|
|
176
|
+
description="Tabla con vista responsive Table / Cards, paginación, filtros y template de card personalizable."
|
|
50
177
|
code={code}
|
|
51
178
|
demo={
|
|
52
|
-
<div className="w-full bg-white dark:bg-slate-900
|
|
179
|
+
<div className="w-full bg-white dark:bg-slate-900 rounded-xl overflow-hidden shadow-sm">
|
|
53
180
|
<ITTable
|
|
54
181
|
columns={columns}
|
|
55
|
-
data={
|
|
182
|
+
data={TABLE_DATA}
|
|
183
|
+
title="Team members"
|
|
56
184
|
variant={variant}
|
|
57
185
|
size={size}
|
|
186
|
+
defaultItemsPerPage={5}
|
|
187
|
+
renderCard={useCustomCard ? customCard : undefined}
|
|
58
188
|
/>
|
|
59
189
|
</div>
|
|
60
190
|
}
|
|
@@ -62,19 +192,19 @@ export const TableShowcase = () => {
|
|
|
62
192
|
<>
|
|
63
193
|
<ITSelect
|
|
64
194
|
name="var_ctrl"
|
|
65
|
-
label="
|
|
195
|
+
label="Table variant"
|
|
66
196
|
value={variant}
|
|
67
197
|
onChange={(e: any) => setVariant(e.target.value)}
|
|
68
198
|
options={[
|
|
69
199
|
{ label: "Default", value: "default" },
|
|
70
|
-
{ label: "Striped
|
|
71
|
-
{ label: "Bordered
|
|
72
|
-
{ label: "Clean
|
|
200
|
+
{ label: "Striped", value: "striped" },
|
|
201
|
+
{ label: "Bordered", value: "bordered" },
|
|
202
|
+
{ label: "Clean", value: "clean" }
|
|
73
203
|
]}
|
|
74
204
|
/>
|
|
75
205
|
<ITSelect
|
|
76
206
|
name="sz_ctrl"
|
|
77
|
-
label="
|
|
207
|
+
label="Row size"
|
|
78
208
|
value={size}
|
|
79
209
|
onChange={(e: any) => setSize(e.target.value)}
|
|
80
210
|
options={[
|
|
@@ -83,30 +213,169 @@ export const TableShowcase = () => {
|
|
|
83
213
|
{ label: "Large (lg)", value: "lg" }
|
|
84
214
|
]}
|
|
85
215
|
/>
|
|
216
|
+
<div className="flex items-center justify-between pt-2">
|
|
217
|
+
<span className="text-sm font-semibold text-gray-700 dark:text-slate-300">Custom card template</span>
|
|
218
|
+
<ITSlideToggle isOn={useCustomCard} onToggle={setUseCustomCard} size="sm" />
|
|
219
|
+
</div>
|
|
220
|
+
{!useCustomCard && (
|
|
221
|
+
<div className="p-2 bg-slate-100 dark:bg-slate-800 rounded text-xs text-slate-500">
|
|
222
|
+
Default card active — shows all columns as label-value pairs
|
|
223
|
+
</div>
|
|
224
|
+
)}
|
|
86
225
|
</>
|
|
87
226
|
}
|
|
227
|
+
gallery={
|
|
228
|
+
<div className="space-y-6">
|
|
229
|
+
<div>
|
|
230
|
+
<h4 className="text-sm font-bold text-slate-700 dark:text-slate-200 mb-3">Custom cards with hover</h4>
|
|
231
|
+
<div className="grid grid-cols-1 sm:grid-cols-2 gap-4">
|
|
232
|
+
{TABLE_DATA.slice(0, 4).map((row, i) => {
|
|
233
|
+
const initials = (row.name as string).split(" ").map((w: string) => w[0]).join("");
|
|
234
|
+
const status = row.status as string;
|
|
235
|
+
const role = row.role as string;
|
|
236
|
+
const date = new Date(row.lastLogin as string);
|
|
237
|
+
return (
|
|
238
|
+
<div key={i} className="group bg-white dark:bg-slate-800 rounded-xl border border-slate-200 dark:border-slate-700 p-4 transition-all duration-200 hover:-translate-y-0.5 hover:shadow-lg hover:border-slate-300 dark:hover:border-slate-600 cursor-pointer">
|
|
239
|
+
<div className="flex items-start justify-between mb-3">
|
|
240
|
+
<div className="flex items-center gap-3">
|
|
241
|
+
<ITAvatar initials={initials} size="md" />
|
|
242
|
+
<div>
|
|
243
|
+
<p className="font-bold text-slate-800 dark:text-white text-sm">{row.name as string}</p>
|
|
244
|
+
<p className="text-xs text-slate-400">{row.email as string}</p>
|
|
245
|
+
</div>
|
|
246
|
+
</div>
|
|
247
|
+
<span className={`px-2 py-0.5 text-[10px] font-bold uppercase tracking-wider rounded-md ${statusColor(status)}`}>{status}</span>
|
|
248
|
+
</div>
|
|
249
|
+
<div className="flex items-center gap-3 text-xs text-slate-500 mb-3">
|
|
250
|
+
<span className={`px-2 py-0.5 rounded-md font-semibold ${roleColor(role)}`}>{role}</span>
|
|
251
|
+
<span>Login: {date.toLocaleDateString("en-US", { month: "short", day: "numeric" })}</span>
|
|
252
|
+
</div>
|
|
253
|
+
<div className="flex items-center justify-between pt-3 border-t border-slate-100 dark:border-slate-700">
|
|
254
|
+
<span className="text-xs text-slate-400">Sales: <strong className="text-slate-700 dark:text-slate-200">${(row.sales as number).toLocaleString()}</strong></span>
|
|
255
|
+
<div className="flex gap-1.5 opacity-0 group-hover:opacity-100 transition-opacity">
|
|
256
|
+
<button className="p-1.5 rounded-md hover:bg-slate-100 dark:hover:bg-slate-700 text-slate-400 hover:text-primary-600"><svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2"><path d="M1 12s4-8 11-8 11 8 11 8-4 8-11 8-11-8-11-8z"/><circle cx="12" cy="12" r="3"/></svg></button>
|
|
257
|
+
<button className="p-1.5 rounded-md hover:bg-slate-100 dark:hover:bg-slate-700 text-slate-400 hover:text-blue-600"><svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2"><path d="M11 4H4a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-7"/><path d="M18.5 2.5a2.121 2.121 0 0 1 3 3L12 15l-4 1 1-4 9.5-9.5z"/></svg></button>
|
|
258
|
+
</div>
|
|
259
|
+
</div>
|
|
260
|
+
</div>
|
|
261
|
+
);
|
|
262
|
+
})}
|
|
263
|
+
</div>
|
|
264
|
+
</div>
|
|
265
|
+
|
|
266
|
+
<div>
|
|
267
|
+
<h4 className="text-sm font-bold text-slate-700 dark:text-slate-200 mb-3">ITTable with default cards</h4>
|
|
268
|
+
<div className="border border-slate-200 dark:border-slate-700 rounded-xl overflow-hidden">
|
|
269
|
+
<ITTable
|
|
270
|
+
columns={columns}
|
|
271
|
+
data={TABLE_DATA.slice(0, 6)}
|
|
272
|
+
size="sm"
|
|
273
|
+
defaultItemsPerPage={6}
|
|
274
|
+
defaultView="cards"
|
|
275
|
+
/>
|
|
276
|
+
</div>
|
|
277
|
+
</div>
|
|
278
|
+
|
|
279
|
+
<div>
|
|
280
|
+
<h4 className="text-sm font-bold text-slate-700 dark:text-slate-200 mb-3">ITTable with custom cards + pagination</h4>
|
|
281
|
+
<div className="border border-slate-200 dark:border-slate-700 rounded-xl overflow-hidden">
|
|
282
|
+
<ITTable
|
|
283
|
+
columns={columns}
|
|
284
|
+
data={TABLE_DATA}
|
|
285
|
+
size="sm"
|
|
286
|
+
title="All members"
|
|
287
|
+
defaultItemsPerPage={4}
|
|
288
|
+
renderCard={(row: any) => {
|
|
289
|
+
const initials = (row.name as string).split(" ").map((w: string) => w[0]).join("");
|
|
290
|
+
return (
|
|
291
|
+
<div className="group bg-white dark:bg-slate-800 rounded-lg border border-slate-200 dark:border-slate-700 p-3 transition-all duration-200 hover:-translate-y-0.5 hover:shadow-md hover:border-slate-300 dark:hover:border-slate-600 cursor-pointer">
|
|
292
|
+
<div className="flex items-center gap-3 mb-2">
|
|
293
|
+
<ITAvatar initials={initials} size="sm" />
|
|
294
|
+
<div className="flex-1 min-w-0">
|
|
295
|
+
<p className="font-semibold text-slate-800 dark:text-white text-sm truncate">{row.name as string}</p>
|
|
296
|
+
<p className="text-[11px] text-slate-400 truncate">{row.email as string}</p>
|
|
297
|
+
</div>
|
|
298
|
+
<span className={`px-2 py-0.5 text-[9px] font-bold uppercase tracking-wider rounded-md ${statusColor(row.status as string)}`}>{row.status as string}</span>
|
|
299
|
+
</div>
|
|
300
|
+
<div className="flex items-center justify-between text-xs text-slate-500">
|
|
301
|
+
<span className={`px-1.5 py-0.5 rounded font-semibold ${roleColor(row.role as string)}`}>{row.role as string}</span>
|
|
302
|
+
<span>${(row.sales as number).toLocaleString()}</span>
|
|
303
|
+
</div>
|
|
304
|
+
</div>
|
|
305
|
+
);
|
|
306
|
+
}}
|
|
307
|
+
/>
|
|
308
|
+
</div>
|
|
309
|
+
</div>
|
|
310
|
+
</div>
|
|
311
|
+
}
|
|
88
312
|
/>
|
|
89
313
|
);
|
|
90
314
|
};
|
|
91
315
|
|
|
92
316
|
// 2. ITDataTable Showcase
|
|
93
317
|
export const DataTableShowcase = () => {
|
|
318
|
+
const [useCustomCard, setUseCustomCard] = useState(true);
|
|
319
|
+
const [apiState, setApiState] = useState<"normal" | "loading" | "empty" | "error">("normal");
|
|
320
|
+
const [reloadKey, setReloadKey] = useState(0);
|
|
321
|
+
const [showVBorder, setShowVBorder] = useState(true);
|
|
322
|
+
const [borderStyle, setBorderStyle] = useState<"default" | "blue" | "rose" | "none">("default");
|
|
323
|
+
|
|
94
324
|
const userColumns = useMemo(() => [
|
|
95
325
|
{ key: "id", label: "ID", type: "number" as const },
|
|
96
|
-
{ key: "name", label: "
|
|
97
|
-
|
|
98
|
-
|
|
326
|
+
{ key: "name", label: "Name", type: "string" as const, filter: true, sortable: true,
|
|
327
|
+
render: (row: any) => (
|
|
328
|
+
<div className="flex items-center gap-2.5">
|
|
329
|
+
<ITAvatar initials={(row.name as string).split(" ").map((w: string) => w[0]).join("")} size="sm" />
|
|
330
|
+
<span className="font-semibold text-slate-800 dark:text-white">{row.name}</span>
|
|
331
|
+
</div>
|
|
332
|
+
)
|
|
333
|
+
},
|
|
334
|
+
{
|
|
335
|
+
key: "role",
|
|
336
|
+
label: "Role",
|
|
337
|
+
type: "string" as const,
|
|
338
|
+
filter: true,
|
|
339
|
+
sortable: true,
|
|
340
|
+
render: (row: any) => (
|
|
341
|
+
<span className={`px-2 py-0.5 text-[10px] font-bold uppercase tracking-wider rounded-md ${
|
|
342
|
+
row.role === "Admin" ? "bg-primary-100 text-primary-700 dark:bg-primary-950/40 dark:text-primary-300" :
|
|
343
|
+
row.role === "Editor" ? "bg-blue-100 text-blue-700 dark:bg-blue-950/40 dark:text-blue-300" :
|
|
344
|
+
"bg-slate-100 text-slate-600 dark:bg-slate-800 dark:text-slate-400"
|
|
345
|
+
}`}>{row.role}</span>
|
|
346
|
+
)
|
|
347
|
+
},
|
|
348
|
+
{ key: "active", label: "Active", type: "boolean" as const, filter: true }
|
|
349
|
+
], []);
|
|
350
|
+
|
|
351
|
+
const MOCK_USERS = useMemo(() => [
|
|
352
|
+
{ id: 1, name: "Sofía Castillo", role: "Admin", active: true },
|
|
353
|
+
{ id: 2, name: "Daniela Klein", role: "Editor", active: true },
|
|
354
|
+
{ id: 3, name: "Mariana Reyes", role: "Viewer", active: false },
|
|
355
|
+
{ id: 4, name: "Camila Torres", role: "Admin", active: true },
|
|
356
|
+
{ id: 5, name: "Valentina Méndez", role: "Editor", active: true },
|
|
357
|
+
{ id: 6, name: "Luciana Rivas", role: "Viewer", active: false },
|
|
358
|
+
{ id: 7, name: "Isabella Cruz", role: "Editor", active: true },
|
|
359
|
+
{ id: 8, name: "Gabriela Vargas", role: "Admin", active: true },
|
|
360
|
+
{ id: 9, name: "Ana López", role: "Editor", active: false },
|
|
361
|
+
{ id: 10, name: "Carla Jiménez", role: "Viewer", active: true },
|
|
362
|
+
{ id: 11, name: "Luisa Fernández", role: "Admin", active: true },
|
|
363
|
+
{ id: 12, name: "Renata Morales", role: "Viewer", active: false },
|
|
99
364
|
], []);
|
|
100
365
|
|
|
101
366
|
const fetchData = useCallback(async (params: ITDataTableFetchParams): Promise<ITDataTableResponse<any>> => {
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
367
|
+
const delay = apiState === "loading" ? 8000 : 400;
|
|
368
|
+
await new Promise(resolve => setTimeout(resolve, delay));
|
|
369
|
+
|
|
370
|
+
if (apiState === "error") {
|
|
371
|
+
throw new Error("Connection lost — server is not responding");
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
if (apiState === "empty") {
|
|
375
|
+
return { data: [], total: 0 };
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
let mockData = [...MOCK_USERS];
|
|
110
379
|
|
|
111
380
|
if (params.filters) {
|
|
112
381
|
Object.keys(params.filters).forEach(key => {
|
|
@@ -119,32 +388,188 @@ export const DataTableShowcase = () => {
|
|
|
119
388
|
});
|
|
120
389
|
}
|
|
121
390
|
|
|
391
|
+
if (params.sort) {
|
|
392
|
+
const { key, direction } = params.sort;
|
|
393
|
+
mockData.sort((a: any, b: any) => {
|
|
394
|
+
const av = a[key], bv = b[key];
|
|
395
|
+
if (typeof av === "string") return direction === "asc" ? av.localeCompare(bv) : bv.localeCompare(av);
|
|
396
|
+
return direction === "asc" ? av - bv : bv - av;
|
|
397
|
+
});
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
const start = (params.page - 1) * params.limit;
|
|
401
|
+
const paged = mockData.slice(start, start + params.limit);
|
|
402
|
+
|
|
122
403
|
return {
|
|
123
|
-
data:
|
|
404
|
+
data: paged,
|
|
124
405
|
total: mockData.length
|
|
125
406
|
};
|
|
126
|
-
}, []);
|
|
407
|
+
}, [apiState, MOCK_USERS]);
|
|
408
|
+
|
|
409
|
+
const handleStateChange = (s: typeof apiState) => {
|
|
410
|
+
setApiState(s);
|
|
411
|
+
setReloadKey(k => k + 1);
|
|
412
|
+
};
|
|
127
413
|
|
|
128
|
-
const code = `<ITDataTable
|
|
414
|
+
const code = `<ITDataTable
|
|
415
|
+
columns={columns}
|
|
416
|
+
fetchData={api.fetchUsers}
|
|
417
|
+
title="Users"
|
|
418
|
+
defaultItemsPerPage={5}
|
|
419
|
+
showVerticalBorder={${showVBorder}}${borderStyle !== "default" ? `\n verticalBorderClassname="${borderStyle === "blue" ? "[&_th]:border-blue-200 [&_td]:border-blue-100" : "[&_th]:border-rose-200 [&_td]:border-rose-100"}"` : ""}
|
|
420
|
+
renderCard={(row) => <CustomCard row={row} />}
|
|
421
|
+
/>`;
|
|
422
|
+
|
|
423
|
+
const borderClass = borderStyle === "default" ? undefined : borderStyle === "blue" ? "[&_th]:border-blue-200 dark:[&_th]:border-blue-800/30 [&_td]:border-blue-100 dark:[&_td]:border-blue-800/20" : borderStyle === "rose" ? "[&_th]:border-rose-200 dark:[&_th]:border-rose-800/30 [&_td]:border-rose-100 dark:[&_td]:border-rose-800/20" : undefined;
|
|
129
424
|
|
|
130
425
|
return (
|
|
131
426
|
<ShowcaseLayout
|
|
132
427
|
title="ITDataTable"
|
|
133
|
-
description="Tabla
|
|
428
|
+
description="Tabla auto-suficiente con carga dinámica, filtros, paginación y vista responsive Cards/Table."
|
|
134
429
|
code={code}
|
|
135
430
|
demo={
|
|
136
431
|
<div className="w-full bg-white dark:bg-slate-900 border border-slate-200 dark:border-slate-800 rounded-xl overflow-hidden shadow-md">
|
|
137
432
|
<ITDataTable
|
|
433
|
+
key={reloadKey}
|
|
138
434
|
columns={userColumns}
|
|
139
435
|
fetchData={fetchData}
|
|
436
|
+
title={apiState === "error" ? "Connection error" : apiState === "empty" ? "No data" : "Users"}
|
|
437
|
+
defaultItemsPerPage={4}
|
|
438
|
+
showVerticalBorder={showVBorder}
|
|
439
|
+
verticalBorderClassname={borderClass}
|
|
440
|
+
renderCard={useCustomCard ? (row: any) => {
|
|
441
|
+
const initials = (row.name as string).split(" ").map((w: string) => w[0]).join("");
|
|
442
|
+
return (
|
|
443
|
+
<div className="group bg-white dark:bg-slate-800 rounded-lg border border-slate-200 dark:border-slate-700 p-3 transition-all duration-200 hover:-translate-y-0.5 hover:shadow-md hover:border-slate-300 dark:hover:border-slate-600">
|
|
444
|
+
<div className="flex items-center gap-3 mb-2">
|
|
445
|
+
<ITAvatar initials={initials} size="sm" />
|
|
446
|
+
<div className="flex-1 min-w-0">
|
|
447
|
+
<p className="font-semibold text-slate-800 dark:text-white text-sm truncate">{row.name}</p>
|
|
448
|
+
</div>
|
|
449
|
+
<span className={`px-2 py-0.5 text-[9px] font-bold uppercase tracking-wider rounded-md ${
|
|
450
|
+
row.active ? "bg-emerald-100 text-emerald-700 dark:bg-emerald-950/30 dark:text-emerald-300" : "bg-slate-100 text-slate-600 dark:bg-slate-800 dark:text-slate-400"
|
|
451
|
+
}`}>{row.active ? "Active" : "Inactive"}</span>
|
|
452
|
+
</div>
|
|
453
|
+
<div className="flex items-center justify-between">
|
|
454
|
+
<span className={`px-1.5 py-0.5 text-[10px] font-bold rounded ${
|
|
455
|
+
row.role === "Admin" ? "bg-primary-100 text-primary-700 dark:bg-primary-950/40 dark:text-primary-300" :
|
|
456
|
+
row.role === "Editor" ? "bg-blue-100 text-blue-700 dark:bg-blue-950/40 dark:text-blue-300" :
|
|
457
|
+
"bg-slate-100 text-slate-600 dark:bg-slate-800 dark:text-slate-400"
|
|
458
|
+
}`}>{row.role}</span>
|
|
459
|
+
<span className="text-[10px] text-slate-400">ID: #{row.id}</span>
|
|
460
|
+
</div>
|
|
461
|
+
</div>
|
|
462
|
+
);
|
|
463
|
+
} : undefined}
|
|
140
464
|
/>
|
|
141
465
|
</div>
|
|
142
466
|
}
|
|
143
467
|
controls={
|
|
144
|
-
<div className="
|
|
145
|
-
<
|
|
146
|
-
|
|
147
|
-
|
|
468
|
+
<div className="space-y-3">
|
|
469
|
+
<div>
|
|
470
|
+
<p className="text-xs font-bold uppercase tracking-wider text-slate-400 dark:text-slate-500 mb-2">API state</p>
|
|
471
|
+
<div className="flex flex-wrap gap-2">
|
|
472
|
+
{(["normal", "loading", "empty", "error"] as const).map((s) => (
|
|
473
|
+
<button
|
|
474
|
+
key={s}
|
|
475
|
+
onClick={() => handleStateChange(s)}
|
|
476
|
+
className={`px-3 py-1.5 text-xs font-bold rounded-lg transition-all ${
|
|
477
|
+
apiState === s
|
|
478
|
+
? "bg-slate-900 text-white dark:bg-white dark:text-slate-900 shadow-sm"
|
|
479
|
+
: "bg-slate-100 dark:bg-slate-800 text-slate-600 dark:text-slate-300 hover:bg-slate-200 dark:hover:bg-slate-700"
|
|
480
|
+
}`}
|
|
481
|
+
>
|
|
482
|
+
{s === "normal" ? "✅ Normal" : s === "loading" ? "⏳ Loading" : s === "empty" ? "📭 Empty" : "💥 Error"}
|
|
483
|
+
</button>
|
|
484
|
+
))}
|
|
485
|
+
</div>
|
|
486
|
+
</div>
|
|
487
|
+
<div className="flex items-center justify-between pt-1">
|
|
488
|
+
<span className="text-sm font-semibold text-gray-700 dark:text-slate-300">Custom card template</span>
|
|
489
|
+
<ITSlideToggle isOn={useCustomCard} onToggle={setUseCustomCard} size="sm" />
|
|
490
|
+
</div>
|
|
491
|
+
{!useCustomCard && (
|
|
492
|
+
<div className="p-2 bg-slate-100 dark:bg-slate-800 rounded text-xs text-slate-500">
|
|
493
|
+
Default card active — shows all columns as label-value pairs
|
|
494
|
+
</div>
|
|
495
|
+
)}
|
|
496
|
+
<div>
|
|
497
|
+
<p className="text-xs font-bold uppercase tracking-wider text-slate-400 dark:text-slate-500 mb-2">Borders</p>
|
|
498
|
+
<div className="flex flex-wrap gap-2">
|
|
499
|
+
{(["default", "blue", "rose", "none"] as const).map((s) => (
|
|
500
|
+
<button
|
|
501
|
+
key={s}
|
|
502
|
+
onClick={() => {
|
|
503
|
+
setBorderStyle(s);
|
|
504
|
+
setShowVBorder(s !== "none");
|
|
505
|
+
}}
|
|
506
|
+
className={`px-3 py-1.5 text-xs font-bold rounded-lg transition-all ${
|
|
507
|
+
borderStyle === s
|
|
508
|
+
? "bg-slate-900 text-white dark:bg-white dark:text-slate-900 shadow-sm"
|
|
509
|
+
: "bg-slate-100 dark:bg-slate-800 text-slate-600 dark:text-slate-300 hover:bg-slate-200 dark:hover:bg-slate-700"
|
|
510
|
+
}`}
|
|
511
|
+
>
|
|
512
|
+
{s === "default" ? "Gray" : s === "blue" ? "Blue" : s === "rose" ? "Rose" : "None"}
|
|
513
|
+
</button>
|
|
514
|
+
))}
|
|
515
|
+
</div>
|
|
516
|
+
</div>
|
|
517
|
+
</div>
|
|
518
|
+
}
|
|
519
|
+
gallery={
|
|
520
|
+
<div className="space-y-6">
|
|
521
|
+
<div>
|
|
522
|
+
<h4 className="text-sm font-bold text-slate-700 dark:text-slate-200 mb-3">Custom cards with hover</h4>
|
|
523
|
+
<div className="border border-slate-200 dark:border-slate-700 rounded-xl overflow-hidden">
|
|
524
|
+
<GalleryDataTable
|
|
525
|
+
title="Team members"
|
|
526
|
+
defaultItemsPerPage={4}
|
|
527
|
+
renderCard={(row: any) => {
|
|
528
|
+
const initials = (row.name as string).split(" ").map((w: string) => w[0]).join("");
|
|
529
|
+
return (
|
|
530
|
+
<div className="group bg-white dark:bg-slate-800 rounded-xl border border-slate-200 dark:border-slate-700 p-4 transition-all duration-200 hover:-translate-y-0.5 hover:shadow-lg hover:border-slate-300 dark:hover:border-slate-600">
|
|
531
|
+
<div className="flex items-start justify-between mb-3">
|
|
532
|
+
<div className="flex items-center gap-3">
|
|
533
|
+
<ITAvatar initials={initials} size="md" />
|
|
534
|
+
<div>
|
|
535
|
+
<p className="font-bold text-slate-800 dark:text-white text-sm">{row.name as string}</p>
|
|
536
|
+
<p className="text-xs text-slate-400">{row.email as string}</p>
|
|
537
|
+
</div>
|
|
538
|
+
</div>
|
|
539
|
+
<span className={`px-2 py-0.5 text-[10px] font-bold uppercase tracking-wider rounded-md ${
|
|
540
|
+
row.active ? "bg-emerald-100 text-emerald-700 dark:bg-emerald-950/30 dark:text-emerald-300" : "bg-slate-100 text-slate-600 dark:bg-slate-800 dark:text-slate-400"
|
|
541
|
+
}`}>{row.active ? "Active" : "Inactive"}</span>
|
|
542
|
+
</div>
|
|
543
|
+
<div className="flex items-center gap-2 text-xs text-slate-500 mb-3">
|
|
544
|
+
<span className={`px-2 py-0.5 rounded-md font-semibold ${
|
|
545
|
+
row.role === "Admin" ? "bg-primary-100 text-primary-700 dark:bg-primary-950/40 dark:text-primary-300" :
|
|
546
|
+
row.role === "Editor" ? "bg-blue-100 text-blue-700 dark:bg-blue-950/40 dark:text-blue-300" :
|
|
547
|
+
"bg-slate-100 text-slate-600 dark:bg-slate-800 dark:text-slate-400"
|
|
548
|
+
}`}>{row.role as string}</span>
|
|
549
|
+
</div>
|
|
550
|
+
<div className="flex items-center justify-between pt-3 border-t border-slate-100 dark:border-slate-700">
|
|
551
|
+
<span className="text-xs text-slate-400">ID: <strong className="text-slate-700 dark:text-slate-200">#{row.id}</strong></span>
|
|
552
|
+
<div className="flex gap-1.5 opacity-0 group-hover:opacity-100 transition-opacity">
|
|
553
|
+
<button className="p-1.5 rounded-md hover:bg-slate-100 dark:hover:bg-slate-700 text-slate-400 hover:text-primary-600"><svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2"><path d="M1 12s4-8 11-8 11 8 11 8-4 8-11 8-11-8-11-8z"/><circle cx="12" cy="12" r="3"/></svg></button>
|
|
554
|
+
<button className="p-1.5 rounded-md hover:bg-slate-100 dark:hover:bg-slate-700 text-slate-400 hover:text-blue-600"><svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2"><path d="M11 4H4a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-7"/><path d="M18.5 2.5a2.121 2.121 0 0 1 3 3L12 15l-4 1 1-4 9.5-9.5z"/></svg></button>
|
|
555
|
+
</div>
|
|
556
|
+
</div>
|
|
557
|
+
</div>
|
|
558
|
+
);
|
|
559
|
+
}}
|
|
560
|
+
/>
|
|
561
|
+
</div>
|
|
562
|
+
</div>
|
|
563
|
+
|
|
564
|
+
<div>
|
|
565
|
+
<h4 className="text-sm font-bold text-slate-700 dark:text-slate-200 mb-3">Default cards with pagination</h4>
|
|
566
|
+
<div className="border border-slate-200 dark:border-slate-700 rounded-xl overflow-hidden">
|
|
567
|
+
<GalleryDataTable
|
|
568
|
+
size="sm"
|
|
569
|
+
defaultItemsPerPage={3}
|
|
570
|
+
defaultView="cards"
|
|
571
|
+
/>
|
|
572
|
+
</div>
|
|
148
573
|
</div>
|
|
149
574
|
</div>
|
|
150
575
|
}
|
|
@@ -152,6 +577,65 @@ export const DataTableShowcase = () => {
|
|
|
152
577
|
);
|
|
153
578
|
};
|
|
154
579
|
|
|
580
|
+
function GalleryDataTable({ title, size, defaultItemsPerPage, defaultView, renderCard }: {
|
|
581
|
+
title?: string;
|
|
582
|
+
size?: string;
|
|
583
|
+
defaultItemsPerPage?: number;
|
|
584
|
+
defaultView?: "table" | "cards";
|
|
585
|
+
renderCard?: (row: any) => React.ReactNode;
|
|
586
|
+
}) {
|
|
587
|
+
const columns = useMemo(() => [
|
|
588
|
+
{ key: "id", label: "ID", type: "number" as const },
|
|
589
|
+
{ key: "name", label: "Name", type: "string" as const, filter: true, sortable: true,
|
|
590
|
+
render: (row: any) => (
|
|
591
|
+
<div className="flex items-center gap-2.5">
|
|
592
|
+
<ITAvatar initials={(row.name as string).split(" ").map((w: string) => w[0]).join("")} size="sm" />
|
|
593
|
+
<span className="font-semibold text-slate-800 dark:text-white">{row.name}</span>
|
|
594
|
+
</div>
|
|
595
|
+
)
|
|
596
|
+
},
|
|
597
|
+
{
|
|
598
|
+
key: "role", label: "Role", type: "string" as const, filter: true, sortable: true,
|
|
599
|
+
render: (row: any) => (
|
|
600
|
+
<span className={`px-2 py-0.5 text-[10px] font-bold uppercase tracking-wider rounded-md ${
|
|
601
|
+
row.role === "Admin" ? "bg-primary-100 text-primary-700 dark:bg-primary-950/40 dark:text-primary-300" :
|
|
602
|
+
row.role === "Editor" ? "bg-blue-100 text-blue-700 dark:bg-blue-950/40 dark:text-blue-300" :
|
|
603
|
+
"bg-slate-100 text-slate-600 dark:bg-slate-800 dark:text-slate-400"
|
|
604
|
+
}`}>{row.role}</span>
|
|
605
|
+
)
|
|
606
|
+
},
|
|
607
|
+
{ key: "active", label: "Active", type: "boolean" as const, filter: true }
|
|
608
|
+
], []);
|
|
609
|
+
|
|
610
|
+
const fetchData = useCallback(async (params: ITDataTableFetchParams) => {
|
|
611
|
+
const all = [
|
|
612
|
+
{ id: 1, name: "Sofía Castillo", email: "sofia@axzy.dev", role: "Admin", active: true },
|
|
613
|
+
{ id: 2, name: "Daniela Klein", email: "daniela@axzy.dev", role: "Editor", active: true },
|
|
614
|
+
{ id: 3, name: "Mariana Reyes", email: "mariana@axzy.dev", role: "Viewer", active: false },
|
|
615
|
+
{ id: 4, name: "Camila Torres", email: "camila@axzy.dev", role: "Admin", active: true },
|
|
616
|
+
{ id: 5, name: "Valentina Méndez", email: "valentina@axzy.dev", role: "Editor", active: true },
|
|
617
|
+
{ id: 6, name: "Luciana Rivas", email: "luciana@axzy.dev", role: "Viewer", active: false },
|
|
618
|
+
{ id: 7, name: "Isabella Cruz", email: "isabella@axzy.dev", role: "Editor", active: true },
|
|
619
|
+
{ id: 8, name: "Gabriela Vargas", email: "gabriela@axzy.dev", role: "Admin", active: true },
|
|
620
|
+
];
|
|
621
|
+
await new Promise(r => setTimeout(r, 200));
|
|
622
|
+
const start = (params.page - 1) * params.limit;
|
|
623
|
+
return { data: all.slice(start, start + params.limit), total: all.length };
|
|
624
|
+
}, []);
|
|
625
|
+
|
|
626
|
+
return (
|
|
627
|
+
<ITDataTable
|
|
628
|
+
columns={columns}
|
|
629
|
+
fetchData={fetchData}
|
|
630
|
+
title={title}
|
|
631
|
+
size={size as any}
|
|
632
|
+
defaultItemsPerPage={defaultItemsPerPage}
|
|
633
|
+
defaultView={defaultView}
|
|
634
|
+
renderCard={renderCard}
|
|
635
|
+
/>
|
|
636
|
+
);
|
|
637
|
+
}
|
|
638
|
+
|
|
155
639
|
// 3. ITBadget Showcase
|
|
156
640
|
export const BadgetShowcase = () => {
|
|
157
641
|
const [color, setColor] = useState<any>("success");
|