@axzydev/axzy_ui_system 1.2.6 → 1.2.8

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.
Files changed (185) hide show
  1. package/dist/index.cjs +777 -535
  2. package/dist/index.cjs.map +1 -1
  3. package/dist/index.css +1 -1
  4. package/dist/index.css.map +1 -1
  5. package/dist/index.d.cts +1470 -87
  6. package/dist/index.d.ts +1470 -87
  7. package/dist/index.js +799 -555
  8. package/dist/index.js.map +1 -1
  9. package/package.json +1 -1
  10. package/src/App.tsx +19 -54
  11. package/src/components/alert/alert.doc.mdx +48 -0
  12. package/src/components/alert/alert.props.ts +7 -0
  13. package/src/components/alert/alert.tsx +8 -0
  14. package/src/components/avatar/avatar.doc.mdx +48 -0
  15. package/src/components/avatar/avatar.props.ts +8 -0
  16. package/src/components/avatar/avatar.tsx +25 -5
  17. package/src/components/badget/badget.doc.mdx +46 -0
  18. package/src/components/badget/badget.props.ts +6 -0
  19. package/src/components/badget/badget.tsx +11 -0
  20. package/src/components/breadcrumbs/breadcrumbs.doc.mdx +57 -0
  21. package/src/components/breadcrumbs/breadcrumbs.props.ts +6 -0
  22. package/src/components/breadcrumbs/breadcrumbs.tsx +12 -0
  23. package/src/components/button/button.doc.mdx +59 -0
  24. package/src/components/button/button.props.ts +12 -0
  25. package/src/components/button/button.tsx +11 -0
  26. package/src/components/calendar/calendar.doc.mdx +75 -0
  27. package/src/components/calendar/calendar.props.ts +27 -7
  28. package/src/components/calendar/calendar.tsx +13 -0
  29. package/src/components/card/card.doc.mdx +54 -0
  30. package/src/components/card/card.props.ts +11 -0
  31. package/src/components/card/card.tsx +13 -0
  32. package/src/components/checkbox/checkbox.doc.mdx +54 -0
  33. package/src/components/checkbox/checkbox.props.ts +7 -0
  34. package/src/components/checkbox/checkbox.tsx +9 -0
  35. package/src/components/confirm-dialog/confirm-dialog.doc.mdx +60 -0
  36. package/src/components/confirm-dialog/confirm-dialog.props.ts +9 -0
  37. package/src/components/confirm-dialog/confirm-dialog.tsx +19 -0
  38. package/src/components/data-table/ITDataTable.doc.mdx +59 -0
  39. package/src/components/data-table/dataTable.props.ts +15 -0
  40. package/src/components/data-table/dataTable.tsx +178 -73
  41. package/src/components/date-picker/date-picker.doc.mdx +65 -0
  42. package/src/components/date-picker/date-picker.props.ts +17 -0
  43. package/src/components/date-picker/datePicker.tsx +31 -1
  44. package/src/components/dialog/dialog.doc.mdx +54 -0
  45. package/src/components/dialog/dialog.props.ts +7 -0
  46. package/src/components/dialog/dialog.tsx +26 -0
  47. package/src/components/divider/divider.doc.mdx +42 -0
  48. package/src/components/divider/divider.props.ts +5 -0
  49. package/src/components/divider/divider.tsx +16 -0
  50. package/src/components/drawer/drawer.doc.mdx +59 -0
  51. package/src/components/drawer/drawer.props.ts +9 -0
  52. package/src/components/drawer/drawer.tsx +20 -0
  53. package/src/components/dropfile/dropfile.doc.mdx +59 -0
  54. package/src/components/dropfile/dropfile.props.ts +41 -0
  55. package/src/components/dropfile/dropfile.tsx +21 -33
  56. package/src/components/empty-state/empty-state.doc.mdx +50 -0
  57. package/src/components/empty-state/empty-state.props.ts +5 -0
  58. package/src/components/empty-state/empty-state.tsx +16 -0
  59. package/src/components/flex/flex.doc.mdx +59 -0
  60. package/src/components/flex/flex.props.ts +13 -0
  61. package/src/components/flex/flex.tsx +15 -0
  62. package/src/components/form-builder/fieldRenderer.tsx +52 -2
  63. package/src/components/form-builder/formBuilder.doc.mdx +124 -0
  64. package/src/components/form-builder/formBuilder.props.ts +12 -2
  65. package/src/components/form-builder/formBuilder.tsx +31 -0
  66. package/src/components/form-header/form-header.doc.mdx +38 -0
  67. package/src/components/form-header/form-header.props.ts +3 -0
  68. package/src/components/form-header/form-header.stories.tsx +53 -0
  69. package/src/components/form-header/form-header.tsx +11 -0
  70. package/src/components/grid/grid.doc.mdx +54 -0
  71. package/src/components/grid/grid.props.ts +13 -0
  72. package/src/components/grid/grid.tsx +26 -2
  73. package/src/components/image/image.doc.mdx +44 -0
  74. package/src/components/image/image.props.ts +5 -0
  75. package/src/components/image/image.stories.tsx +49 -0
  76. package/src/components/image/image.tsx +19 -0
  77. package/src/components/input/input.doc.mdx +70 -0
  78. package/src/components/input/input.props.ts +34 -2
  79. package/src/components/input/input.tsx +29 -0
  80. package/src/components/layout/layout.doc.mdx +51 -0
  81. package/src/components/layout/layout.props.ts +5 -0
  82. package/src/components/layout/layout.tsx +41 -17
  83. package/src/components/loader/loader.doc.mdx +43 -0
  84. package/src/components/loader/loader.props.ts +4 -0
  85. package/src/components/loader/loader.tsx +17 -0
  86. package/src/components/navbar/navbar.doc.mdx +77 -0
  87. package/src/components/navbar/navbar.props.ts +37 -1
  88. package/src/components/navbar/navbar.stories.tsx +84 -0
  89. package/src/components/navbar/navbar.tsx +78 -46
  90. package/src/components/page/page.doc.mdx +80 -0
  91. package/src/components/page/page.props.ts +25 -0
  92. package/src/components/page/page.tsx +35 -7
  93. package/src/components/page-header/page-header.doc.mdx +54 -0
  94. package/src/components/page-header/page-header.props.ts +11 -0
  95. package/src/components/page-header/page-header.stories.tsx +14 -0
  96. package/src/components/page-header/page-header.tsx +50 -15
  97. package/src/components/pagination/pagination.doc.mdx +62 -0
  98. package/src/components/pagination/pagination.props.ts +11 -32
  99. package/src/components/pagination/pagination.tsx +17 -0
  100. package/src/components/popover/popover.doc.mdx +53 -0
  101. package/src/components/popover/popover.props.ts +8 -0
  102. package/src/components/popover/popover.tsx +13 -0
  103. package/src/components/progress/progress.doc.mdx +48 -0
  104. package/src/components/progress/progress.props.ts +8 -0
  105. package/src/components/progress/progress.tsx +9 -0
  106. package/src/components/radio/radio.doc.mdx +62 -0
  107. package/src/components/radio/radio.props.ts +11 -0
  108. package/src/components/radio/radio.tsx +18 -0
  109. package/src/components/search-select/search-select.doc.mdx +72 -0
  110. package/src/components/search-select/search-select.props.ts +23 -18
  111. package/src/components/search-select/search-select.tsx +27 -2
  112. package/src/components/searchTable/searchTable.doc.mdx +79 -0
  113. package/src/components/searchTable/searchTable.props.ts +42 -3
  114. package/src/components/searchTable/searchTable.stories.tsx +74 -0
  115. package/src/components/searchTable/searchTable.tsx +23 -0
  116. package/src/components/segmented-control/segmented-control.doc.mdx +60 -0
  117. package/src/components/segmented-control/segmented-control.props.ts +12 -0
  118. package/src/components/segmented-control/segmented-control.tsx +15 -0
  119. package/src/components/select/select.doc.mdx +75 -0
  120. package/src/components/select/select.props.ts +22 -0
  121. package/src/components/select/select.tsx +2 -5
  122. package/src/components/sidebar/sidebar.doc.mdx +86 -0
  123. package/src/components/sidebar/sidebar.props.ts +22 -0
  124. package/src/components/sidebar/sidebar.tsx +22 -0
  125. package/src/components/skeleton/skeleton.doc.mdx +43 -0
  126. package/src/components/skeleton/skeleton.props.ts +8 -0
  127. package/src/components/skeleton/skeleton.tsx +10 -0
  128. package/src/components/slide/slide.doc.mdx +46 -0
  129. package/src/components/slide/slide.props.ts +11 -24
  130. package/src/components/slide/slide.tsx +10 -1
  131. package/src/components/slider/slider.doc.mdx +49 -0
  132. package/src/components/slider/slider.props.ts +9 -0
  133. package/src/components/slider/slider.tsx +15 -0
  134. package/src/components/stack/stack.doc.mdx +126 -0
  135. package/src/components/stack/stack.props.ts +18 -0
  136. package/src/components/stack/stack.stories.tsx +221 -16
  137. package/src/components/stack/stack.tsx +21 -0
  138. package/src/components/stat-card/stat-card.doc.mdx +48 -0
  139. package/src/components/stat-card/stat-card.props.ts +9 -0
  140. package/src/components/stat-card/stat-card.tsx +10 -0
  141. package/src/components/stepper/stepper.doc.mdx +54 -0
  142. package/src/components/stepper/stepper.props.ts +11 -1
  143. package/src/components/stepper/stepper.tsx +15 -0
  144. package/src/components/table/table.doc.mdx +58 -0
  145. package/src/components/table/table.props.ts +17 -0
  146. package/src/components/table/table.tsx +199 -84
  147. package/src/components/tabs/tabs.doc.mdx +52 -0
  148. package/src/components/tabs/tabs.props.ts +11 -0
  149. package/src/components/tabs/tabs.tsx +14 -0
  150. package/src/components/text/text.doc.mdx +41 -0
  151. package/src/components/text/text.props.ts +5 -0
  152. package/src/components/text/text.stories.tsx +67 -0
  153. package/src/components/text/text.tsx +10 -0
  154. package/src/components/textarea/textarea.doc.mdx +64 -0
  155. package/src/components/textarea/textarea.props.ts +11 -0
  156. package/src/components/textarea/textarea.tsx +16 -0
  157. package/src/components/theme-provider/themeProvider.doc.mdx +75 -0
  158. package/src/components/theme-provider/themeProvider.props.ts +3 -0
  159. package/src/components/theme-provider/themeProvider.stories.tsx +59 -0
  160. package/src/components/theme-provider/themeProvider.tsx +14 -0
  161. package/src/components/time-picker/timePicker.doc.mdx +68 -0
  162. package/src/components/time-picker/timePicker.props.ts +14 -0
  163. package/src/components/time-picker/timePicker.tsx +22 -1
  164. package/src/components/toast/toast.doc.mdx +50 -0
  165. package/src/components/toast/toast.props.ts +5 -0
  166. package/src/components/toast/toast.tsx +21 -0
  167. package/src/components/tooltip/tooltip.doc.mdx +47 -0
  168. package/src/components/tooltip/tooltip.props.ts +6 -0
  169. package/src/components/tooltip/tooltip.tsx +19 -0
  170. package/src/components/topbar/topbar.doc.mdx +69 -0
  171. package/src/components/topbar/topbar.props.ts +15 -0
  172. package/src/components/topbar/topbar.tsx +38 -0
  173. package/src/components/triple-filter/tripleFilter.doc.mdx +62 -0
  174. package/src/components/triple-filter/tripleFilter.props.ts +7 -0
  175. package/src/components/triple-filter/tripleFilter.tsx +32 -0
  176. package/src/index.css +17 -0
  177. package/src/showcases/DataShowcases.tsx +529 -45
  178. package/src/showcases/FormShowcases.tsx +399 -29
  179. package/src/showcases/HomeShowcase.tsx +252 -272
  180. package/src/showcases/LayoutPrimitivesShowcases.tsx +1224 -248
  181. package/src/showcases/PageShowcases.tsx +868 -151
  182. package/src/showcases/ShowcaseLayout.tsx +237 -73
  183. package/src/showcases/StructureShowcases.tsx +1039 -97
  184. package/src/types/table.types.ts +1 -1
  185. 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
- <ShowcaseLayout
1131
- title="ITFormBuilder"
1132
- description="Generador dinámico de formularios basado en un esquema estructurado JSON."
1133
- code={code}
1134
- demo={
1135
- <div className="w-full max-w-md bg-white dark:bg-slate-900 p-6 rounded-2xl border shadow-sm space-y-6">
1136
- <ITFormBuilder
1137
- config={config}
1138
- values={values}
1139
- handleChange={handleChange}
1140
- handleBlur={() => { }}
1141
- touched={{}}
1142
- errors={{}}
1143
- />
1144
- <div className="pt-4 border-t border-slate-100 dark:border-slate-800">
1145
- <h5 className="text-xs font-bold uppercase text-slate-400 mb-2">Valores del Formulario (JSON):</h5>
1146
- <pre className="p-3 bg-slate-950 text-emerald-400 text-xs rounded-lg overflow-x-auto font-mono">
1147
- {JSON.stringify(values, null, 2)}
1148
- </pre>
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
- controls={
1153
- <div className="p-2 bg-slate-50 dark:bg-slate-900 rounded-lg text-xs">
1154
- <p className="text-slate-500">El formulario se genera dinámicamente inyectando un array de campos configurados.</p>
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
  };