@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
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import React, { useState, useEffect, useMemo } from "react";
|
|
2
|
-
import { FaSync, FaSave, FaTrash, FaEdit } from "react-icons/fa";
|
|
2
|
+
import { FaSync, FaSave, FaTrash, FaEdit, FaCode } from "react-icons/fa";
|
|
3
3
|
import {
|
|
4
4
|
ITButton,
|
|
5
5
|
ITInput,
|
|
@@ -13,7 +13,36 @@ import {
|
|
|
13
13
|
ITFormBuilder,
|
|
14
14
|
UploadStatus
|
|
15
15
|
} from "../index";
|
|
16
|
-
import { ShowcaseLayout } from "./ShowcaseLayout";
|
|
16
|
+
import { ShowcaseLayout, CodeViewer } from "./ShowcaseLayout";
|
|
17
|
+
import ITFlex from "../components/flex/flex";
|
|
18
|
+
|
|
19
|
+
const CodeExampleBlock = ({ title, desc, code, children }: { title: string; desc: string; code: string; children: React.ReactNode }) => {
|
|
20
|
+
const [showCode, setShowCode] = useState(false);
|
|
21
|
+
return (
|
|
22
|
+
<div className="bg-white dark:bg-slate-900 rounded-xl border border-slate-200 dark:border-slate-700 shadow-sm overflow-hidden">
|
|
23
|
+
<div className="px-6 py-4 border-b border-slate-200 dark:border-slate-700">
|
|
24
|
+
<ITFlex justify="between" align="center">
|
|
25
|
+
<div>
|
|
26
|
+
<h3 className="text-sm font-bold text-slate-800 dark:text-white">{title}</h3>
|
|
27
|
+
<p className="text-xs text-slate-500 mt-1">{desc}</p>
|
|
28
|
+
</div>
|
|
29
|
+
<ITButton variant="outlined" color="gray" size="small" onClick={() => setShowCode(!showCode)}>
|
|
30
|
+
<ITFlex align="center" gap={1}>
|
|
31
|
+
<FaCode size={9} />
|
|
32
|
+
{showCode ? "Ocultar código" : "Ver código"}
|
|
33
|
+
</ITFlex>
|
|
34
|
+
</ITButton>
|
|
35
|
+
</ITFlex>
|
|
36
|
+
</div>
|
|
37
|
+
<div className="p-6">{children}</div>
|
|
38
|
+
{showCode && (
|
|
39
|
+
<div className="px-6 pb-6 border-t border-slate-200 dark:border-slate-700 pt-4">
|
|
40
|
+
<CodeViewer code={code} compact />
|
|
41
|
+
</div>
|
|
42
|
+
)}
|
|
43
|
+
</div>
|
|
44
|
+
);
|
|
45
|
+
};
|
|
17
46
|
|
|
18
47
|
// 1. ITButton Showcase
|
|
19
48
|
export const ButtonShowcase = () => {
|
|
@@ -1099,6 +1128,7 @@ export const FormBuilderShowcase = () => {
|
|
|
1099
1128
|
country: "MX",
|
|
1100
1129
|
accept: false
|
|
1101
1130
|
});
|
|
1131
|
+
const [submitted, setSubmitted] = useState<any>(null);
|
|
1102
1132
|
|
|
1103
1133
|
const handleChange = (e: any) => {
|
|
1104
1134
|
const { name, value, type, checked } = e.target;
|
|
@@ -1109,51 +1139,391 @@ export const FormBuilderShowcase = () => {
|
|
|
1109
1139
|
};
|
|
1110
1140
|
|
|
1111
1141
|
const config: any = [
|
|
1112
|
-
{ name: "name", label: "Nombre Completo", type: "text", required: true },
|
|
1113
|
-
{ name: "email", label: "Correo de Contacto", type: "email", required: true },
|
|
1142
|
+
{ name: "name", label: "Nombre Completo", type: "text", required: true, column: 6 },
|
|
1143
|
+
{ name: "email", label: "Correo de Contacto", type: "email", required: true, column: 6 },
|
|
1114
1144
|
{
|
|
1115
1145
|
name: "country",
|
|
1116
1146
|
label: "País Operación",
|
|
1117
1147
|
type: "select",
|
|
1148
|
+
column: 6,
|
|
1118
1149
|
options: [
|
|
1119
1150
|
{ label: "México", value: "MX" },
|
|
1120
1151
|
{ label: "Chile", value: "CL" },
|
|
1121
1152
|
{ label: "Perú", value: "PE" }
|
|
1122
1153
|
]
|
|
1123
1154
|
},
|
|
1124
|
-
{ name: "accept", label: "Acepto términos y condiciones", type: "checkbox" }
|
|
1155
|
+
{ name: "accept", label: "Acepto términos y condiciones", type: "checkbox", column: 12 }
|
|
1125
1156
|
];
|
|
1126
1157
|
|
|
1127
1158
|
const code = `<ITFormBuilder\n config={[\n { name: 'name', label: 'Nombre', type: 'text', required: true },\n { name: 'email', label: 'Email', type: 'email' },\n ...\n ]}\n values={formValues}\n handleChange={handleFormChange}\n/>`;
|
|
1128
1159
|
|
|
1129
1160
|
return (
|
|
1130
|
-
<
|
|
1131
|
-
|
|
1132
|
-
|
|
1133
|
-
|
|
1134
|
-
|
|
1135
|
-
|
|
1136
|
-
<
|
|
1137
|
-
|
|
1138
|
-
|
|
1139
|
-
|
|
1140
|
-
|
|
1141
|
-
|
|
1142
|
-
|
|
1143
|
-
|
|
1144
|
-
|
|
1145
|
-
|
|
1146
|
-
|
|
1147
|
-
|
|
1148
|
-
|
|
1161
|
+
<div className="space-y-8">
|
|
1162
|
+
<ShowcaseLayout
|
|
1163
|
+
title="ITFormBuilder"
|
|
1164
|
+
description="Generador dinámico de formularios basado en un esquema estructurado JSON."
|
|
1165
|
+
code={code}
|
|
1166
|
+
demo={
|
|
1167
|
+
<div className="w-full max-w-md space-y-6">
|
|
1168
|
+
<form
|
|
1169
|
+
onSubmit={(e) => { e.preventDefault(); setSubmitted(values); }}
|
|
1170
|
+
className="bg-white dark:bg-slate-900 p-6 rounded-2xl border shadow-sm space-y-4"
|
|
1171
|
+
>
|
|
1172
|
+
<ITFormBuilder
|
|
1173
|
+
config={config}
|
|
1174
|
+
values={values}
|
|
1175
|
+
handleChange={handleChange}
|
|
1176
|
+
handleBlur={() => {}}
|
|
1177
|
+
touched={{}}
|
|
1178
|
+
errors={{}}
|
|
1179
|
+
setFieldValue={(field, val) => { setValues(prev => ({ ...prev, [field]: val })); return Promise.resolve(); }}
|
|
1180
|
+
/>
|
|
1181
|
+
<div className="pt-4 flex justify-end gap-3">
|
|
1182
|
+
<ITButton variant="outlined" color="gray" size="small" onClick={() => { setValues({ name: "", email: "", country: "MX", accept: false }); setSubmitted(null); }}>
|
|
1183
|
+
Limpiar
|
|
1184
|
+
</ITButton>
|
|
1185
|
+
<ITButton variant="filled" color="primary" size="small" type="submit">
|
|
1186
|
+
Enviar
|
|
1187
|
+
</ITButton>
|
|
1188
|
+
</div>
|
|
1189
|
+
</form>
|
|
1190
|
+
{submitted && (
|
|
1191
|
+
<div className="p-4 bg-slate-950 text-emerald-400 text-xs rounded-xl border border-slate-800 font-mono">
|
|
1192
|
+
<p className="font-bold text-emerald-300 mb-2">✓ Payload Enviado:</p>
|
|
1193
|
+
<pre>{JSON.stringify(submitted, null, 2)}</pre>
|
|
1194
|
+
</div>
|
|
1195
|
+
)}
|
|
1196
|
+
</div>
|
|
1197
|
+
}
|
|
1198
|
+
controls={
|
|
1199
|
+
<div className="p-2 bg-slate-50 dark:bg-slate-900 rounded-lg text-xs">
|
|
1200
|
+
<p className="text-slate-500">El formulario se genera dinámicamente inyectando un array de campos configurados.</p>
|
|
1149
1201
|
</div>
|
|
1202
|
+
}
|
|
1203
|
+
/>
|
|
1204
|
+
|
|
1205
|
+
<CodeExampleBlock
|
|
1206
|
+
title="Formulario llenado desde API"
|
|
1207
|
+
desc="Carga datos asíncronamente al montar el formulario"
|
|
1208
|
+
code={`const FormFillFromApi = () => {
|
|
1209
|
+
const [loading, setLoading] = useState(true);
|
|
1210
|
+
const [values, setValues] = useState({ name: "", email: "", role: "" });
|
|
1211
|
+
|
|
1212
|
+
useEffect(() => {
|
|
1213
|
+
setTimeout(() => {
|
|
1214
|
+
// Simula fetch de API
|
|
1215
|
+
setValues({ name: "Juan Pérez", email: "juan@ejemplo.com", role: "admin" });
|
|
1216
|
+
setLoading(false);
|
|
1217
|
+
}, 1500);
|
|
1218
|
+
}, []);
|
|
1219
|
+
|
|
1220
|
+
if (loading) return <Spinner />;
|
|
1221
|
+
|
|
1222
|
+
return (
|
|
1223
|
+
<form onSubmit={handleSubmit}>
|
|
1224
|
+
<ITFormBuilder
|
|
1225
|
+
config={[
|
|
1226
|
+
{ name: "name", label: "Nombre", type: "text", required: true, column: 6 },
|
|
1227
|
+
{ name: "email", label: "Correo", type: "email", required: true, column: 6 },
|
|
1228
|
+
{ name: "role", label: "Rol", type: "select", column: 12,
|
|
1229
|
+
options: [
|
|
1230
|
+
{ label: "Admin", value: "admin" },
|
|
1231
|
+
{ label: "Editor", value: "editor" },
|
|
1232
|
+
{ label: "Usuario", value: "user" }
|
|
1233
|
+
]
|
|
1234
|
+
}
|
|
1235
|
+
]}
|
|
1236
|
+
values={values}
|
|
1237
|
+
handleChange={...}
|
|
1238
|
+
setFieldValue={...}
|
|
1239
|
+
/>
|
|
1240
|
+
</form>
|
|
1241
|
+
);
|
|
1242
|
+
};`}
|
|
1243
|
+
>
|
|
1244
|
+
<FormFillFromApi />
|
|
1245
|
+
</CodeExampleBlock>
|
|
1246
|
+
|
|
1247
|
+
<CodeExampleBlock
|
|
1248
|
+
title="Select conectado a API con Cascade"
|
|
1249
|
+
desc="Select asíncrono que al seleccionar actualiza otro campo"
|
|
1250
|
+
code={`const config = [
|
|
1251
|
+
{
|
|
1252
|
+
name: "country", label: "País", type: "select",
|
|
1253
|
+
options: [
|
|
1254
|
+
{ label: "México", value: "MX" },
|
|
1255
|
+
{ label: "España", value: "ES" },
|
|
1256
|
+
{ label: "Colombia", value: "CO" }
|
|
1257
|
+
],
|
|
1258
|
+
onChangeAction: (val, { setFieldValue }) => {
|
|
1259
|
+
setFieldValue("city", ""); // limpia ciudad al cambiar país
|
|
1260
|
+
}
|
|
1261
|
+
},
|
|
1262
|
+
{
|
|
1263
|
+
name: "city", label: "Ciudad", type: "select",
|
|
1264
|
+
options: async () => {
|
|
1265
|
+
const cities = {
|
|
1266
|
+
MX: [
|
|
1267
|
+
{ value: "CDMX", label: "Ciudad de México" },
|
|
1268
|
+
{ value: "GDL", label: "Guadalajara" },
|
|
1269
|
+
{ value: "MTY", label: "Monterrey" }
|
|
1270
|
+
],
|
|
1271
|
+
ES: [
|
|
1272
|
+
{ value: "MAD", label: "Madrid" },
|
|
1273
|
+
{ value: "BCN", label: "Barcelona" },
|
|
1274
|
+
{ value: "SEV", label: "Sevilla" }
|
|
1275
|
+
],
|
|
1276
|
+
CO: [
|
|
1277
|
+
{ value: "BOG", label: "Bogotá" },
|
|
1278
|
+
{ value: "MED", label: "Medellín" },
|
|
1279
|
+
{ value: "CAL", label: "Cali" }
|
|
1280
|
+
]
|
|
1281
|
+
};
|
|
1282
|
+
await new Promise(r => setTimeout(r, 800));
|
|
1283
|
+
return cities[country] || [];
|
|
1284
|
+
}
|
|
1285
|
+
}
|
|
1286
|
+
];`}
|
|
1287
|
+
>
|
|
1288
|
+
<CascadingSelectsExample />
|
|
1289
|
+
</CodeExampleBlock>
|
|
1290
|
+
|
|
1291
|
+
<CodeExampleBlock
|
|
1292
|
+
title="Conversor de Moneda"
|
|
1293
|
+
desc="Select de divisa que actualiza precios en MXN y USD"
|
|
1294
|
+
code={`const CurrencyConverterExample = () => {
|
|
1295
|
+
const [values, setValues] = useState({ currency: "MXN", amount: 1000 });
|
|
1296
|
+
const TC = 20.50;
|
|
1297
|
+
|
|
1298
|
+
const config = [
|
|
1299
|
+
{
|
|
1300
|
+
name: "currency", label: "Moneda", type: "select", column: 6,
|
|
1301
|
+
options: [
|
|
1302
|
+
{ label: "MXN - Peso Mexicano", value: "MXN" },
|
|
1303
|
+
{ label: "USD - Dólar Americano", value: "USD" }
|
|
1304
|
+
]
|
|
1305
|
+
},
|
|
1306
|
+
{
|
|
1307
|
+
name: "amount", label: "Cantidad", type: "number", column: 6,
|
|
1308
|
+
currencyFormat: true
|
|
1309
|
+
}
|
|
1310
|
+
];
|
|
1311
|
+
|
|
1312
|
+
const converted = values.currency === "MXN"
|
|
1313
|
+
? { mxn: values.amount, usd: values.amount / TC }
|
|
1314
|
+
: { mxn: values.amount * TC, usd: values.amount };
|
|
1315
|
+
|
|
1316
|
+
return (
|
|
1317
|
+
<>
|
|
1318
|
+
<ITFormBuilder config={config} values={values} setFieldValue={...} />
|
|
1319
|
+
<div className="grid grid-cols-2 gap-4">
|
|
1320
|
+
<div>MXN: {converted.mxn}</div>
|
|
1321
|
+
<div>USD: {converted.usd}</div>
|
|
1322
|
+
</div>
|
|
1323
|
+
</>
|
|
1324
|
+
);
|
|
1325
|
+
};`}
|
|
1326
|
+
>
|
|
1327
|
+
<CurrencyConverterExample />
|
|
1328
|
+
</CodeExampleBlock>
|
|
1329
|
+
</div>
|
|
1330
|
+
);
|
|
1331
|
+
};
|
|
1332
|
+
|
|
1333
|
+
// ── Fill from API example ──
|
|
1334
|
+
const FormFillFromApi = () => {
|
|
1335
|
+
const [loading, setLoading] = useState(true);
|
|
1336
|
+
const [values, setValues] = useState({ name: "", email: "", role: "" });
|
|
1337
|
+
const [submitted, setSubmitted] = useState<any>(null);
|
|
1338
|
+
|
|
1339
|
+
useEffect(() => {
|
|
1340
|
+
const timer = setTimeout(() => {
|
|
1341
|
+
setValues({ name: "Juan Pérez", email: "juan@ejemplo.com", role: "admin" });
|
|
1342
|
+
setLoading(false);
|
|
1343
|
+
}, 1500);
|
|
1344
|
+
return () => clearTimeout(timer);
|
|
1345
|
+
}, []);
|
|
1346
|
+
|
|
1347
|
+
const handleChange = (e: any) => {
|
|
1348
|
+
const { name, value } = e.target;
|
|
1349
|
+
setValues(prev => ({ ...prev, [name]: value }));
|
|
1350
|
+
};
|
|
1351
|
+
|
|
1352
|
+
const config: any = [
|
|
1353
|
+
{ name: "name", label: "Nombre", type: "text", required: true, column: 6 },
|
|
1354
|
+
{ name: "email", label: "Correo", type: "email", required: true, column: 6 },
|
|
1355
|
+
{
|
|
1356
|
+
name: "role", label: "Rol", type: "select", column: 12,
|
|
1357
|
+
options: [
|
|
1358
|
+
{ label: "Admin", value: "admin" },
|
|
1359
|
+
{ label: "Editor", value: "editor" },
|
|
1360
|
+
{ label: "Usuario", value: "user" }
|
|
1361
|
+
]
|
|
1362
|
+
}
|
|
1363
|
+
];
|
|
1364
|
+
|
|
1365
|
+
if (loading) {
|
|
1366
|
+
return (
|
|
1367
|
+
<div className="flex items-center gap-3 py-8 justify-center">
|
|
1368
|
+
<FaSync className="animate-spin text-primary-500" />
|
|
1369
|
+
<span className="text-sm text-slate-500">Cargando datos del usuario...</span>
|
|
1370
|
+
</div>
|
|
1371
|
+
);
|
|
1372
|
+
}
|
|
1373
|
+
|
|
1374
|
+
return (
|
|
1375
|
+
<div className="w-full max-w-md space-y-4">
|
|
1376
|
+
<form onSubmit={(e) => { e.preventDefault(); setSubmitted(values); }} className="space-y-4">
|
|
1377
|
+
<ITFormBuilder
|
|
1378
|
+
config={config}
|
|
1379
|
+
values={values}
|
|
1380
|
+
handleChange={handleChange}
|
|
1381
|
+
handleBlur={() => {}}
|
|
1382
|
+
touched={{}}
|
|
1383
|
+
errors={{}}
|
|
1384
|
+
setFieldValue={(field, val) => { setValues(prev => ({ ...prev, [field]: val })); return Promise.resolve(); }}
|
|
1385
|
+
/>
|
|
1386
|
+
<div className="flex justify-end">
|
|
1387
|
+
<ITButton variant="filled" color="primary" size="small" type="submit">Guardar Cambios</ITButton>
|
|
1150
1388
|
</div>
|
|
1151
|
-
|
|
1152
|
-
|
|
1153
|
-
<div className="p-
|
|
1154
|
-
<p className="
|
|
1389
|
+
</form>
|
|
1390
|
+
{submitted && (
|
|
1391
|
+
<div className="p-3 bg-slate-950 text-emerald-400 text-xs rounded-lg font-mono border border-slate-800">
|
|
1392
|
+
<p className="font-bold mb-1">✓ Editado:</p>
|
|
1393
|
+
<pre>{JSON.stringify(submitted, null, 2)}</pre>
|
|
1155
1394
|
</div>
|
|
1395
|
+
)}
|
|
1396
|
+
</div>
|
|
1397
|
+
);
|
|
1398
|
+
};
|
|
1399
|
+
|
|
1400
|
+
// ── Cascading Selects Example ──
|
|
1401
|
+
const CascadingSelectsExample = () => {
|
|
1402
|
+
const [values, setValues] = useState({ country: "", city: "" });
|
|
1403
|
+
const [submitted, setSubmitted] = useState<any>(null);
|
|
1404
|
+
|
|
1405
|
+
const handleChange = (e: any) => {
|
|
1406
|
+
const { name, value } = e.target;
|
|
1407
|
+
setValues(prev => ({ ...prev, [name]: value }));
|
|
1408
|
+
};
|
|
1409
|
+
|
|
1410
|
+
const config: any = [
|
|
1411
|
+
{
|
|
1412
|
+
name: "country", label: "País", type: "select", required: true, column: 6,
|
|
1413
|
+
options: [
|
|
1414
|
+
{ label: "México", value: "MX" },
|
|
1415
|
+
{ label: "España", value: "ES" },
|
|
1416
|
+
{ label: "Colombia", value: "CO" }
|
|
1417
|
+
],
|
|
1418
|
+
onChangeAction: (val: any, { setFieldValue }: any) => {
|
|
1419
|
+
setFieldValue("city", "");
|
|
1156
1420
|
}
|
|
1157
|
-
|
|
1421
|
+
},
|
|
1422
|
+
{
|
|
1423
|
+
name: "city", label: "Ciudad", type: "select", required: true, column: 6,
|
|
1424
|
+
options: async () => {
|
|
1425
|
+
const cities: Record<string, { value: string; label: string }[]> = {
|
|
1426
|
+
MX: [
|
|
1427
|
+
{ value: "CDMX", label: "Ciudad de México" },
|
|
1428
|
+
{ value: "GDL", label: "Guadalajara" },
|
|
1429
|
+
{ value: "MTY", label: "Monterrey" }
|
|
1430
|
+
],
|
|
1431
|
+
ES: [
|
|
1432
|
+
{ value: "MAD", label: "Madrid" },
|
|
1433
|
+
{ value: "BCN", label: "Barcelona" },
|
|
1434
|
+
{ value: "SEV", label: "Sevilla" }
|
|
1435
|
+
],
|
|
1436
|
+
CO: [
|
|
1437
|
+
{ value: "BOG", label: "Bogotá" },
|
|
1438
|
+
{ value: "MED", label: "Medellín" },
|
|
1439
|
+
{ value: "CAL", label: "Cali" }
|
|
1440
|
+
]
|
|
1441
|
+
};
|
|
1442
|
+
await new Promise(r => setTimeout(r, 800));
|
|
1443
|
+
return cities[values.country] || [];
|
|
1444
|
+
}
|
|
1445
|
+
}
|
|
1446
|
+
];
|
|
1447
|
+
|
|
1448
|
+
return (
|
|
1449
|
+
<div className="w-full max-w-md space-y-4">
|
|
1450
|
+
<form onSubmit={(e) => { e.preventDefault(); setSubmitted(values); }} className="space-y-4">
|
|
1451
|
+
<ITFormBuilder
|
|
1452
|
+
config={config}
|
|
1453
|
+
values={values}
|
|
1454
|
+
handleChange={handleChange}
|
|
1455
|
+
handleBlur={() => {}}
|
|
1456
|
+
touched={{}}
|
|
1457
|
+
errors={{}}
|
|
1458
|
+
setFieldValue={(field, val) => { setValues(prev => ({ ...prev, [field]: val })); return Promise.resolve(); }}
|
|
1459
|
+
/>
|
|
1460
|
+
<div className="flex justify-end">
|
|
1461
|
+
<ITButton variant="filled" color="primary" size="small" type="submit">Enviar</ITButton>
|
|
1462
|
+
</div>
|
|
1463
|
+
</form>
|
|
1464
|
+
{submitted && (
|
|
1465
|
+
<div className="p-3 bg-slate-950 text-emerald-400 text-xs rounded-lg font-mono border border-slate-800">
|
|
1466
|
+
<p className="font-bold mb-1">✓ Datos:</p>
|
|
1467
|
+
<pre>{JSON.stringify(submitted, null, 2)}</pre>
|
|
1468
|
+
</div>
|
|
1469
|
+
)}
|
|
1470
|
+
</div>
|
|
1471
|
+
);
|
|
1472
|
+
};
|
|
1473
|
+
|
|
1474
|
+
// ── Currency Converter Example ──
|
|
1475
|
+
const CurrencyConverterExample = () => {
|
|
1476
|
+
const [values, setValues] = useState({ currency: "MXN", amount: 1000 });
|
|
1477
|
+
const TC = 20.50;
|
|
1478
|
+
|
|
1479
|
+
const config: any = [
|
|
1480
|
+
{
|
|
1481
|
+
name: "currency", label: "Moneda", type: "select", required: true, column: 6,
|
|
1482
|
+
options: [
|
|
1483
|
+
{ label: "MXN - Peso Mexicano", value: "MXN" },
|
|
1484
|
+
{ label: "USD - Dólar Americano", value: "USD" }
|
|
1485
|
+
]
|
|
1486
|
+
},
|
|
1487
|
+
{
|
|
1488
|
+
name: "amount", label: "Cantidad", type: "number", required: true, column: 6,
|
|
1489
|
+
currencyFormat: true
|
|
1490
|
+
}
|
|
1491
|
+
];
|
|
1492
|
+
|
|
1493
|
+
const converted = values.currency === "MXN"
|
|
1494
|
+
? { mxn: values.amount, usd: values.amount / TC }
|
|
1495
|
+
: { mxn: values.amount * TC, usd: values.amount };
|
|
1496
|
+
|
|
1497
|
+
return (
|
|
1498
|
+
<div className="w-full max-w-md space-y-4">
|
|
1499
|
+
<ITFormBuilder
|
|
1500
|
+
config={config}
|
|
1501
|
+
values={values}
|
|
1502
|
+
handleChange={() => {}}
|
|
1503
|
+
handleBlur={() => {}}
|
|
1504
|
+
touched={{}}
|
|
1505
|
+
errors={{}}
|
|
1506
|
+
setFieldValue={(field, val) => { setValues(prev => ({ ...prev, [field]: val })); return Promise.resolve(); }}
|
|
1507
|
+
/>
|
|
1508
|
+
<div className="grid grid-cols-2 gap-4 pt-2">
|
|
1509
|
+
<div className="p-4 rounded-xl bg-emerald-50 dark:bg-emerald-950/30 border border-emerald-200 dark:border-emerald-800/50">
|
|
1510
|
+
<p className="text-[10px] font-bold uppercase tracking-wider text-emerald-600 dark:text-emerald-400">MXN</p>
|
|
1511
|
+
<p className="text-xl font-bold text-emerald-900 dark:text-emerald-200 font-mono">
|
|
1512
|
+
{converted.mxn.toLocaleString("es-MX", { style: "currency", currency: "MXN" })}
|
|
1513
|
+
</p>
|
|
1514
|
+
</div>
|
|
1515
|
+
<div className="p-4 rounded-xl bg-blue-50 dark:bg-blue-950/30 border border-blue-200 dark:border-blue-800/50">
|
|
1516
|
+
<p className="text-[10px] font-bold uppercase tracking-wider text-blue-600 dark:text-blue-400">USD</p>
|
|
1517
|
+
<p className="text-xl font-bold text-blue-900 dark:text-blue-200 font-mono">
|
|
1518
|
+
{converted.usd.toLocaleString("en-US", { style: "currency", currency: "USD" })}
|
|
1519
|
+
</p>
|
|
1520
|
+
</div>
|
|
1521
|
+
</div>
|
|
1522
|
+
{values.amount > 0 && (
|
|
1523
|
+
<p className="text-[11px] text-slate-400 text-center">
|
|
1524
|
+
TC: 1 USD = {TC.toFixed(2)} MXN
|
|
1525
|
+
</p>
|
|
1526
|
+
)}
|
|
1527
|
+
</div>
|
|
1158
1528
|
);
|
|
1159
1529
|
};
|
|
@@ -0,0 +1,207 @@
|
|
|
1
|
+
import { FaNpm, FaReact, FaCheck } from "react-icons/fa";
|
|
2
|
+
import { SiTailwindcss, SiTypescript, SiVite } from "react-icons/si";
|
|
3
|
+
import { useState } from "react";
|
|
4
|
+
import ITBadget from "../components/badget/badget";
|
|
5
|
+
import ITButton from "../components/button/button";
|
|
6
|
+
import ITCard from "../components/card/card";
|
|
7
|
+
import ITDivider from "../components/divider/divider";
|
|
8
|
+
import ITFlex from "../components/flex/flex";
|
|
9
|
+
import ITGrid from "../components/grid/grid";
|
|
10
|
+
import ITStack from "../components/stack/stack";
|
|
11
|
+
import ITText from "../components/text/text";
|
|
12
|
+
|
|
13
|
+
const CopyButton = ({ text }: { text: string }) => {
|
|
14
|
+
const [copied, setCopied] = useState(false);
|
|
15
|
+
return (
|
|
16
|
+
<ITButton
|
|
17
|
+
variant="text"
|
|
18
|
+
color="gray"
|
|
19
|
+
size="small"
|
|
20
|
+
onClick={() => { navigator.clipboard.writeText(text); setCopied(true); setTimeout(() => setCopied(false), 2000); }}
|
|
21
|
+
>
|
|
22
|
+
<ITFlex align="center" gap={1.5}>
|
|
23
|
+
{copied ? <FaCheck size={10} className="text-emerald-400" /> : <FaNpm size={10} />}
|
|
24
|
+
{copied ? "Copiado" : "Copiar"}
|
|
25
|
+
</ITFlex>
|
|
26
|
+
</ITButton>
|
|
27
|
+
);
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
const CodeBlock = ({ code, filename, color }: { code: string; filename?: string; color?: string }) => (
|
|
31
|
+
<div className="overflow-hidden rounded-xl border border-slate-200 dark:border-slate-700 bg-white dark:bg-slate-900">
|
|
32
|
+
{filename && (
|
|
33
|
+
<div className={`px-4 py-2 border-b border-slate-200 dark:border-slate-700 ${color || "bg-slate-50 dark:bg-slate-800/80"}`}>
|
|
34
|
+
<ITText as="span" className="!text-xs !font-mono !text-slate-400">{filename}</ITText>
|
|
35
|
+
</div>
|
|
36
|
+
)}
|
|
37
|
+
<div className="relative bg-slate-950">
|
|
38
|
+
<pre className="p-4 text-xs font-mono overflow-x-auto leading-relaxed text-slate-200">
|
|
39
|
+
<code>{code}</code>
|
|
40
|
+
</pre>
|
|
41
|
+
</div>
|
|
42
|
+
</div>
|
|
43
|
+
);
|
|
44
|
+
|
|
45
|
+
const codeFileColors = [
|
|
46
|
+
"bg-emerald-50 dark:bg-emerald-950/30",
|
|
47
|
+
"bg-blue-50 dark:bg-blue-950/30",
|
|
48
|
+
"bg-cyan-50 dark:bg-cyan-950/30",
|
|
49
|
+
"bg-violet-50 dark:bg-violet-950/30",
|
|
50
|
+
"bg-amber-50 dark:bg-amber-950/30",
|
|
51
|
+
"bg-rose-50 dark:bg-rose-950/30",
|
|
52
|
+
];
|
|
53
|
+
|
|
54
|
+
const stepStyles = [
|
|
55
|
+
{ iconBg: "bg-emerald-100 dark:bg-emerald-950/40 text-emerald-600 dark:text-emerald-400" },
|
|
56
|
+
{ iconBg: "bg-blue-100 dark:bg-blue-950/40 text-blue-600 dark:text-blue-400" },
|
|
57
|
+
{ iconBg: "bg-cyan-100 dark:bg-cyan-950/40 text-cyan-600 dark:text-cyan-400" },
|
|
58
|
+
{ iconBg: "bg-violet-100 dark:bg-violet-950/40 text-violet-600 dark:text-violet-400" },
|
|
59
|
+
{ iconBg: "bg-amber-100 dark:bg-amber-950/40 text-amber-600 dark:text-amber-400" },
|
|
60
|
+
{ iconBg: "bg-rose-100 dark:bg-rose-950/40 text-rose-600 dark:text-rose-400" },
|
|
61
|
+
];
|
|
62
|
+
|
|
63
|
+
const steps = [
|
|
64
|
+
{
|
|
65
|
+
icon: <FaNpm size={14} />,
|
|
66
|
+
title: "Instalar dependencias",
|
|
67
|
+
desc: "Tailwind v4 y su plugin para Vite.",
|
|
68
|
+
filename: "terminal",
|
|
69
|
+
code: "npm install @axzydev/axzy_ui_system\nnpm install -D tailwindcss @tailwindcss/vite @vitejs/plugin-react-swc",
|
|
70
|
+
},
|
|
71
|
+
{
|
|
72
|
+
icon: <SiVite size={14} />,
|
|
73
|
+
title: "Configurar Vite",
|
|
74
|
+
desc: "Agrega Tailwind como plugin de Vite.",
|
|
75
|
+
filename: "vite.config.ts",
|
|
76
|
+
code: `import { defineConfig } from "vite"
|
|
77
|
+
import react from "@vitejs/plugin-react-swc"
|
|
78
|
+
import tailwindcss from "@tailwindcss/vite"
|
|
79
|
+
|
|
80
|
+
export default defineConfig({
|
|
81
|
+
plugins: [tailwindcss(), react()],
|
|
82
|
+
})`,
|
|
83
|
+
},
|
|
84
|
+
{
|
|
85
|
+
icon: <SiTailwindcss size={14} />,
|
|
86
|
+
title: "Agregar Tailwind",
|
|
87
|
+
desc: "Importa Tailwind en tu archivo CSS.",
|
|
88
|
+
filename: "src/index.css",
|
|
89
|
+
code: `@import "tailwindcss";
|
|
90
|
+
@variant dark (&:is(.dark &));`,
|
|
91
|
+
},
|
|
92
|
+
{
|
|
93
|
+
icon: <FaReact size={14} />,
|
|
94
|
+
title: "Importar estilos",
|
|
95
|
+
desc: "Envuelve tu app con el provider.",
|
|
96
|
+
filename: "src/main.tsx",
|
|
97
|
+
code: `import { ITThemeProvider } from "@axzydev/axzy_ui_system"
|
|
98
|
+
import "@axzydev/axzy_ui_system/dist/index.css"
|
|
99
|
+
|
|
100
|
+
<ITThemeProvider>
|
|
101
|
+
<App />
|
|
102
|
+
</ITThemeProvider>`,
|
|
103
|
+
},
|
|
104
|
+
{
|
|
105
|
+
icon: <SiTypescript size={14} />,
|
|
106
|
+
title: "Declaración de tipos",
|
|
107
|
+
desc: "Para que TS acepte imports CSS.",
|
|
108
|
+
filename: "src/vite-env.d.ts",
|
|
109
|
+
code: `/// <reference types="vite/client" />
|
|
110
|
+
|
|
111
|
+
declare module "*.css" {
|
|
112
|
+
const content: string
|
|
113
|
+
export default content
|
|
114
|
+
}`,
|
|
115
|
+
},
|
|
116
|
+
{
|
|
117
|
+
icon: <FaReact size={14} />,
|
|
118
|
+
title: "Primer componente",
|
|
119
|
+
desc: "Ya puedes usar cualquier componente.",
|
|
120
|
+
filename: "src/App.tsx",
|
|
121
|
+
code: `import { ITButton } from "@axzydev/axzy_ui_system"
|
|
122
|
+
|
|
123
|
+
export default function App() {
|
|
124
|
+
return <ITButton variant="rounded">Empezar</ITButton>
|
|
125
|
+
}`,
|
|
126
|
+
},
|
|
127
|
+
];
|
|
128
|
+
|
|
129
|
+
export const GettingStartedShowcase = () => {
|
|
130
|
+
return (
|
|
131
|
+
<ITStack spacing={10}>
|
|
132
|
+
{/* ─── HERO ─── */}
|
|
133
|
+
<ITCard className="overflow-hidden border-0 bg-gradient-to-br from-primary-50 via-white to-purple-50 dark:from-primary-950/20 dark:via-slate-900 dark:to-purple-950/20 shadow-sm">
|
|
134
|
+
<div className="relative">
|
|
135
|
+
<div className="absolute -top-40 -right-40 w-[500px] h-[500px] bg-primary-500/10 rounded-full blur-[120px] pointer-events-none" />
|
|
136
|
+
<div className="absolute -bottom-40 -left-40 w-[500px] h-[500px] bg-purple-500/10 rounded-full blur-[120px] pointer-events-none" />
|
|
137
|
+
|
|
138
|
+
<ITStack spacing={5} className="relative z-10">
|
|
139
|
+
<ITStack spacing={2}>
|
|
140
|
+
<ITBadget label="v1.0.0" color="primary" variant="outlined" className="w-fit" />
|
|
141
|
+
<ITText as="h1" className="!text-4xl !font-bold !tracking-tight">
|
|
142
|
+
AXZY UI System
|
|
143
|
+
</ITText>
|
|
144
|
+
<ITText as="p" muted className="!text-base !leading-relaxed max-w-xl">
|
|
145
|
+
Librería de componentes React con Tailwind CSS v4. Diseñada para apps enterprise con experiencia de desarrollo fluida.
|
|
146
|
+
</ITText>
|
|
147
|
+
</ITStack>
|
|
148
|
+
|
|
149
|
+
<ITFlex gap={3} wrap="wrap" align="center">
|
|
150
|
+
<div className="px-4 py-2 rounded-xl bg-gradient-to-r from-primary-50 to-purple-50 dark:from-primary-950/30 dark:to-purple-950/30 border border-primary-200 dark:border-primary-800/50 shadow-sm">
|
|
151
|
+
<ITFlex align="center" gap={2}>
|
|
152
|
+
<FaNpm size={16} className="text-primary-500" />
|
|
153
|
+
<code className="text-sm font-mono text-slate-800 dark:text-slate-200">npm install @axzydev/axzy_ui_system</code>
|
|
154
|
+
<CopyButton text="npm install @axzydev/axzy_ui_system" />
|
|
155
|
+
</ITFlex>
|
|
156
|
+
</div>
|
|
157
|
+
</ITFlex>
|
|
158
|
+
</ITStack>
|
|
159
|
+
</div>
|
|
160
|
+
</ITCard>
|
|
161
|
+
|
|
162
|
+
{/* ─── SETUP STEPS ─── */}
|
|
163
|
+
<ITGrid container spacing={6}>
|
|
164
|
+
{steps.map((step, i) => (
|
|
165
|
+
<ITGrid item xs={12} md={6} key={i}>
|
|
166
|
+
<ITCard className="border-slate-200/60 dark:border-slate-800/60 shadow-sm h-full">
|
|
167
|
+
<ITStack spacing={4}>
|
|
168
|
+
<ITFlex align="center" gap={2.5}>
|
|
169
|
+
<div className={`w-8 h-8 rounded-lg ${stepStyles[i].iconBg} flex items-center justify-center`}>
|
|
170
|
+
{step.icon}
|
|
171
|
+
</div>
|
|
172
|
+
<div>
|
|
173
|
+
<ITText as="p" className="!text-sm !font-semibold">{step.title}</ITText>
|
|
174
|
+
<ITText as="p" className="!text-xs !text-slate-400">{step.desc}</ITText>
|
|
175
|
+
</div>
|
|
176
|
+
</ITFlex>
|
|
177
|
+
<CodeBlock code={step.code} filename={step.filename} color={codeFileColors[i]} />
|
|
178
|
+
</ITStack>
|
|
179
|
+
</ITCard>
|
|
180
|
+
</ITGrid>
|
|
181
|
+
))}
|
|
182
|
+
</ITGrid>
|
|
183
|
+
|
|
184
|
+
{/* ─── THEMING ─── */}
|
|
185
|
+
<ITCard title="Theming" className="border-purple-200/60 dark:border-purple-800/60 shadow-sm">
|
|
186
|
+
<ITStack spacing={4}>
|
|
187
|
+
<ITText as="p" className="!text-sm" muted>
|
|
188
|
+
Personaliza colores en runtime. Solo necesitas los que quieras cambiar.
|
|
189
|
+
</ITText>
|
|
190
|
+
<div className="bg-gradient-to-r from-purple-50 via-fuchsia-50 to-pink-50 dark:from-purple-950/20 dark:via-fuchsia-950/20 dark:to-pink-950/20 rounded-xl p-5 border border-purple-200 dark:border-purple-800/30">
|
|
191
|
+
<CodeBlock
|
|
192
|
+
code={`const myTheme = {
|
|
193
|
+
colors: {
|
|
194
|
+
primary: { 50: "#fef2f2", 500: "#ef4444" },
|
|
195
|
+
},
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
<ITThemeProvider theme={myTheme}>
|
|
199
|
+
<App />
|
|
200
|
+
</ITThemeProvider>`}
|
|
201
|
+
/>
|
|
202
|
+
</div>
|
|
203
|
+
</ITStack>
|
|
204
|
+
</ITCard>
|
|
205
|
+
</ITStack>
|
|
206
|
+
);
|
|
207
|
+
};
|