@axzydev/axzy_ui_system 1.2.1 → 1.2.2

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 (202) hide show
  1. package/dist/index.css +82 -1
  2. package/dist/index.css.map +1 -1
  3. package/package.json +2 -2
  4. package/src/App.tsx +354 -0
  5. package/src/assets/logo.png +0 -0
  6. package/src/assets/react.svg +1 -0
  7. package/src/components/alert/alert.props.ts +13 -0
  8. package/src/components/alert/alert.stories.tsx +41 -0
  9. package/src/components/alert/alert.tsx +53 -0
  10. package/src/components/avatar/avatar.props.ts +14 -0
  11. package/src/components/avatar/avatar.stories.tsx +46 -0
  12. package/src/components/avatar/avatar.tsx +53 -0
  13. package/src/components/badget/badget.props.ts +12 -0
  14. package/src/components/badget/badget.stories.tsx +76 -0
  15. package/src/components/badget/badget.tsx +61 -0
  16. package/src/components/breadcrumbs/breadcrumbs.props.ts +13 -0
  17. package/src/components/breadcrumbs/breadcrumbs.stories.tsx +21 -0
  18. package/src/components/breadcrumbs/breadcrumbs.tsx +34 -0
  19. package/src/components/button/button.props.ts +18 -0
  20. package/src/components/button/button.stories.tsx +174 -0
  21. package/src/components/button/button.tsx +117 -0
  22. package/src/components/calendar/calendar.props.ts +33 -0
  23. package/src/components/calendar/calendar.stories.tsx +91 -0
  24. package/src/components/calendar/calendar.tsx +608 -0
  25. package/src/components/calendar/index.ts +3 -0
  26. package/src/components/card/card.props.ts +13 -0
  27. package/src/components/card/card.stories.tsx +58 -0
  28. package/src/components/card/card.tsx +79 -0
  29. package/src/components/checkbox/checkbox.props.ts +11 -0
  30. package/src/components/checkbox/checkbox.stories.tsx +54 -0
  31. package/src/components/checkbox/checkbox.tsx +52 -0
  32. package/src/components/confirm-dialog/confirm-dialog.props.ts +14 -0
  33. package/src/components/confirm-dialog/confirm-dialog.stories.tsx +33 -0
  34. package/src/components/confirm-dialog/confirm-dialog.tsx +45 -0
  35. package/src/components/data-table/ITDataTable.stories.tsx +213 -0
  36. package/src/components/data-table/dataTable.props.ts +69 -0
  37. package/src/components/data-table/dataTable.tsx +313 -0
  38. package/src/components/date-picker/date-picker.props.ts +30 -0
  39. package/src/components/date-picker/date-picker.stories.tsx +90 -0
  40. package/src/components/date-picker/datePicker.tsx +307 -0
  41. package/src/components/dialog/dialog.props.ts +9 -0
  42. package/src/components/dialog/dialog.stories.tsx +80 -0
  43. package/src/components/dialog/dialog.tsx +88 -0
  44. package/src/components/divider/divider.props.ts +8 -0
  45. package/src/components/divider/divider.stories.tsx +34 -0
  46. package/src/components/divider/divider.tsx +21 -0
  47. package/src/components/drawer/drawer.props.ts +14 -0
  48. package/src/components/drawer/drawer.stories.tsx +41 -0
  49. package/src/components/drawer/drawer.tsx +53 -0
  50. package/src/components/dropfile/dropfile.stories.tsx +75 -0
  51. package/src/components/dropfile/dropfile.tsx +407 -0
  52. package/src/components/empty-state/empty-state.props.ts +9 -0
  53. package/src/components/empty-state/empty-state.stories.tsx +20 -0
  54. package/src/components/empty-state/empty-state.tsx +21 -0
  55. package/src/components/flex/flex.props.ts +22 -0
  56. package/src/components/flex/flex.stories.tsx +71 -0
  57. package/src/components/flex/flex.tsx +79 -0
  58. package/src/components/form-builder/fieldRenderer.tsx +218 -0
  59. package/src/components/form-builder/formBuilder.context.tsx +70 -0
  60. package/src/components/form-builder/formBuilder.props.ts +43 -0
  61. package/src/components/form-builder/formBuilder.stories.tsx +317 -0
  62. package/src/components/form-builder/formBuilder.tsx +186 -0
  63. package/src/components/form-builder/useFormBuilder.ts +80 -0
  64. package/src/components/form-header/form-header.props.ts +5 -0
  65. package/src/components/form-header/form-header.tsx +38 -0
  66. package/src/components/grid/grid.props.ts +17 -0
  67. package/src/components/grid/grid.stories.tsx +72 -0
  68. package/src/components/grid/grid.tsx +69 -0
  69. package/src/components/image/image.props.ts +7 -0
  70. package/src/components/image/image.tsx +38 -0
  71. package/src/components/input/input.props.ts +49 -0
  72. package/src/components/input/input.stories.tsx +115 -0
  73. package/src/components/input/input.tsx +615 -0
  74. package/src/components/layout/layout.props.ts +10 -0
  75. package/src/components/layout/layout.stories.tsx +114 -0
  76. package/src/components/layout/layout.tsx +80 -0
  77. package/src/components/loader/loader.props.ts +8 -0
  78. package/src/components/loader/loader.stories.tsx +105 -0
  79. package/src/components/loader/loader.tsx +108 -0
  80. package/src/components/navbar/navbar.props.ts +37 -0
  81. package/src/components/navbar/navbar.tsx +328 -0
  82. package/src/components/page/page.props.ts +19 -0
  83. package/src/components/page/page.stories.tsx +98 -0
  84. package/src/components/page/page.tsx +90 -0
  85. package/src/components/page-header/page-header.props.ts +11 -0
  86. package/src/components/page-header/page-header.stories.tsx +61 -0
  87. package/src/components/page-header/page-header.tsx +62 -0
  88. package/src/components/pagination/pagination.props.ts +53 -0
  89. package/src/components/pagination/pagination.stories.tsx +111 -0
  90. package/src/components/pagination/pagination.tsx +241 -0
  91. package/src/components/popover/popover.props.ts +12 -0
  92. package/src/components/popover/popover.stories.tsx +25 -0
  93. package/src/components/popover/popover.tsx +45 -0
  94. package/src/components/progress/progress.props.ts +12 -0
  95. package/src/components/progress/progress.stories.tsx +40 -0
  96. package/src/components/progress/progress.tsx +52 -0
  97. package/src/components/radio/radio.props.ts +16 -0
  98. package/src/components/radio/radio.stories.tsx +50 -0
  99. package/src/components/radio/radio.tsx +58 -0
  100. package/src/components/search-select/index.ts +2 -0
  101. package/src/components/search-select/search-select.props.ts +46 -0
  102. package/src/components/search-select/search-select.stories.tsx +129 -0
  103. package/src/components/search-select/search-select.tsx +229 -0
  104. package/src/components/searchTable/components/EditableCell.tsx +149 -0
  105. package/src/components/searchTable/components/PaginationControls.tsx +86 -0
  106. package/src/components/searchTable/components/PaginationInfo.tsx +20 -0
  107. package/src/components/searchTable/components/SearchAndSortBar.tsx +53 -0
  108. package/src/components/searchTable/components/SearchInput.tsx +33 -0
  109. package/src/components/searchTable/components/SortButton.tsx +50 -0
  110. package/src/components/searchTable/components/TableEmptyState.tsx +22 -0
  111. package/src/components/searchTable/components/TableHeader.tsx +35 -0
  112. package/src/components/searchTable/components/TableHeaderCell.tsx +43 -0
  113. package/src/components/searchTable/components/TableRow.tsx +144 -0
  114. package/src/components/searchTable/searchTable.props.ts +56 -0
  115. package/src/components/searchTable/searchTable.tsx +187 -0
  116. package/src/components/segmented-control/segmented-control.props.ts +18 -0
  117. package/src/components/segmented-control/segmented-control.stories.tsx +63 -0
  118. package/src/components/segmented-control/segmented-control.tsx +52 -0
  119. package/src/components/select/select.props.ts +25 -0
  120. package/src/components/select/select.stories.tsx +86 -0
  121. package/src/components/select/select.tsx +150 -0
  122. package/src/components/sidebar/sidebar.props.ts +28 -0
  123. package/src/components/sidebar/sidebar.stories.tsx +117 -0
  124. package/src/components/sidebar/sidebar.tsx +313 -0
  125. package/src/components/skeleton/skeleton.props.ts +12 -0
  126. package/src/components/skeleton/skeleton.stories.tsx +30 -0
  127. package/src/components/skeleton/skeleton.tsx +45 -0
  128. package/src/components/slide/slide.props.ts +45 -0
  129. package/src/components/slide/slide.stories.tsx +121 -0
  130. package/src/components/slide/slide.tsx +109 -0
  131. package/src/components/slider/slider.props.ts +10 -0
  132. package/src/components/slider/slider.stories.tsx +30 -0
  133. package/src/components/slider/slider.tsx +49 -0
  134. package/src/components/stack/stack.props.ts +19 -0
  135. package/src/components/stack/stack.stories.tsx +79 -0
  136. package/src/components/stack/stack.tsx +79 -0
  137. package/src/components/stat-card/stat-card.props.ts +13 -0
  138. package/src/components/stat-card/stat-card.stories.tsx +41 -0
  139. package/src/components/stat-card/stat-card.tsx +44 -0
  140. package/src/components/stepper/stepper.css +26 -0
  141. package/src/components/stepper/stepper.props.ts +29 -0
  142. package/src/components/stepper/stepper.stories.tsx +155 -0
  143. package/src/components/stepper/stepper.tsx +227 -0
  144. package/src/components/table/table.props.ts +43 -0
  145. package/src/components/table/table.stories.tsx +189 -0
  146. package/src/components/table/table.tsx +376 -0
  147. package/src/components/tabs/tabs.props.ts +18 -0
  148. package/src/components/tabs/tabs.stories.tsx +32 -0
  149. package/src/components/tabs/tabs.tsx +74 -0
  150. package/src/components/text/text.props.ts +9 -0
  151. package/src/components/text/text.tsx +20 -0
  152. package/src/components/textarea/textarea.props.ts +15 -0
  153. package/src/components/textarea/textarea.stories.tsx +27 -0
  154. package/src/components/textarea/textarea.tsx +55 -0
  155. package/src/components/theme-provider/themeProvider.props.ts +28 -0
  156. package/src/components/theme-provider/themeProvider.tsx +1854 -0
  157. package/src/components/time-picker/timePicker.props.ts +16 -0
  158. package/src/components/time-picker/timePicker.stories.tsx +131 -0
  159. package/src/components/time-picker/timePicker.tsx +317 -0
  160. package/src/components/toast/toast.css +32 -0
  161. package/src/components/toast/toast.props.ts +13 -0
  162. package/src/components/toast/toast.stories.tsx +138 -0
  163. package/src/components/toast/toast.tsx +87 -0
  164. package/src/components/tooltip/tooltip.props.ts +11 -0
  165. package/src/components/tooltip/tooltip.stories.tsx +20 -0
  166. package/src/components/tooltip/tooltip.tsx +55 -0
  167. package/src/components/topbar/topbar.props.ts +21 -0
  168. package/src/components/topbar/topbar.stories.tsx +80 -0
  169. package/src/components/topbar/topbar.tsx +205 -0
  170. package/src/components/triple-filter/tripleFilter.props.ts +15 -0
  171. package/src/components/triple-filter/tripleFilter.stories.tsx +32 -0
  172. package/src/components/triple-filter/tripleFilter.tsx +50 -0
  173. package/src/hooks/useClickOutside.ts +21 -0
  174. package/src/hooks/useDebouncedSearch.ts +55 -0
  175. package/src/hooks/useEditableRow.ts +157 -0
  176. package/src/hooks/useTableState.ts +122 -0
  177. package/src/index.css +168 -0
  178. package/src/index.ts +165 -0
  179. package/src/main.tsx +9 -0
  180. package/src/showcases/DataShowcases.tsx +260 -0
  181. package/src/showcases/FeedbackShowcases.tsx +268 -0
  182. package/src/showcases/FormShowcases.tsx +1159 -0
  183. package/src/showcases/HomeShowcase.tsx +324 -0
  184. package/src/showcases/LayoutPrimitivesShowcases.tsx +569 -0
  185. package/src/showcases/NavigationShowcases.tsx +193 -0
  186. package/src/showcases/PageShowcases.tsx +207 -0
  187. package/src/showcases/ShowcaseLayout.tsx +139 -0
  188. package/src/showcases/StructureShowcases.tsx +152 -0
  189. package/src/types/badget.types.ts +37 -0
  190. package/src/types/button.types.ts +16 -0
  191. package/src/types/colors.types.ts +3 -0
  192. package/src/types/field.types.ts +103 -0
  193. package/src/types/formik.types.ts +15 -0
  194. package/src/types/input.types.ts +14 -0
  195. package/src/types/loader.types.ts +9 -0
  196. package/src/types/sizes.types.ts +1 -0
  197. package/src/types/table.types.ts +15 -0
  198. package/src/types/toast.types.ts +8 -0
  199. package/src/types/yup.types.ts +11 -0
  200. package/src/utils/color.utils.ts +99 -0
  201. package/src/utils/styles.ts +120 -0
  202. package/src/utils/table.utils.ts +10 -0
@@ -0,0 +1,152 @@
1
+ import React, { useState } from "react";
2
+ import { FaCheckCircle } from "react-icons/fa";
3
+ import { ITCard, ITButton, ITInput, ITSlideToggle, ITText, ITNavbar } from "../index";
4
+ import { ShowcaseLayout, CodeViewer } from "./ShowcaseLayout";
5
+
6
+ // 1. ITCard Showcase
7
+ export const CardShowcase = () => {
8
+ const [title, setTitle] = useState("Registro de Logs del Sistema");
9
+ const [showActions, setShowActions] = useState(true);
10
+
11
+ const code = `<ITCard\n title="${title}"\n actions={${showActions ? "<ITButton label='Exportar' />" : "undefined"}}\n>\n <p>Contenido interno de la tarjeta.</p>\n</ITCard>`;
12
+
13
+ return (
14
+ <ShowcaseLayout
15
+ title="ITCard"
16
+ description="Tarjetas de contenedor multipropósito con cabecera y espacio para acciones."
17
+ code={code}
18
+ demo={
19
+ <div className="w-full max-w-md">
20
+ <ITCard
21
+ title={title}
22
+ actions={showActions ? <ITButton label="Exportar" color="primary" size="small" variant="outlined" /> : undefined}
23
+ >
24
+ <div className="space-y-3">
25
+ <p className="text-sm text-slate-600 dark:text-slate-300">
26
+ Esta es una tarjeta administrativa estándar AXZY. Es ideal para agrupar paneles de control, tablas y formularios.
27
+ </p>
28
+ <div className="p-3 bg-emerald-50 dark:bg-emerald-950/20 border border-emerald-100 dark:border-emerald-900 rounded-xl flex items-center gap-2">
29
+ <FaCheckCircle className="text-emerald-500" />
30
+ <span className="text-xs font-medium text-emerald-800 dark:text-emerald-300">Estado de servidor: Conectado</span>
31
+ </div>
32
+ </div>
33
+ </ITCard>
34
+ </div>
35
+ }
36
+ controls={
37
+ <>
38
+ <ITInput name="title_ctrl" label="Título de Tarjeta" value={title} onChange={(e: any) => setTitle(e.target.value)} onBlur={() => { }} />
39
+ <div className="flex items-center justify-between pt-2">
40
+ <span className="text-sm font-semibold text-gray-700">Mostrar Botón de Acción</span>
41
+ <ITSlideToggle isOn={showActions} onToggle={setShowActions} size="sm" />
42
+ </div>
43
+ </>
44
+ }
45
+ />
46
+ );
47
+ };
48
+
49
+ // 2. ITText Showcase
50
+ export const TextShowcase = () => {
51
+ const [bold, setBold] = useState(false);
52
+ const [size, setSize] = useState("text-base");
53
+
54
+ const code = `<ITText className="${bold ? "font-bold" : ""} ${size}">\n Texto tipográfico estándar AXZY\n</ITText>`;
55
+
56
+ return (
57
+ <ShowcaseLayout
58
+ title="ITText"
59
+ description="Contenedor tipográfico básico alineado con las tipografías globales del tema."
60
+ code={code}
61
+ demo={
62
+ <ITText className={`${bold ? "font-bold" : ""} ${size} text-slate-800 dark:text-white`}>
63
+ Diseñado para inyectar consistencia tipográfica sobre las variables globales de Outfit/Inter.
64
+ </ITText>
65
+ }
66
+ controls={
67
+ <>
68
+ <ITSelectStub
69
+ name="sz_ctrl"
70
+ label="Tamaño de Fuente"
71
+ value={size}
72
+ onChange={(e: any) => setSize(e.target.value)}
73
+ options={[
74
+ { label: "Chico (text-xs)", value: "text-xs" },
75
+ { label: "Estándar (text-base)", value: "text-base" },
76
+ { label: "Grande (text-xl)", value: "text-xl" },
77
+ { label: "Título (text-3xl)", value: "text-3xl" }
78
+ ]}
79
+ />
80
+ <div className="flex items-center justify-between pt-2">
81
+ <span className="text-sm font-semibold text-gray-700">Negrita (Bold)</span>
82
+ <ITSlideToggle isOn={bold} onToggle={setBold} size="sm" />
83
+ </div>
84
+ </>
85
+ }
86
+ />
87
+ );
88
+ };
89
+
90
+ // Temporary helper helper to render ITSelect inside showcases
91
+ const ITSelectStub = ({ name, label, value, onChange, options }: any) => {
92
+ return (
93
+ <div className="flex flex-col gap-1">
94
+ <label className="text-xs font-semibold text-slate-600 dark:text-slate-400">{label}</label>
95
+ <select
96
+ name={name}
97
+ value={value}
98
+ onChange={onChange}
99
+ className="w-full bg-slate-50 dark:bg-slate-900 border border-slate-200 dark:border-slate-800 rounded-lg p-2 text-xs text-slate-800 dark:text-slate-100 outline-none"
100
+ >
101
+ {options.map((opt: any) => (
102
+ <option key={opt.value} value={opt.value}>
103
+ {opt.label}
104
+ </option>
105
+ ))}
106
+ </select>
107
+ </div>
108
+ );
109
+ };
110
+
111
+ // 3. ITLayout & ITNavbar Showcase
112
+ export const LayoutShowcase = () => {
113
+ const code = `<ITLayout\n topBar={topBarProps}\n sidebar={sidebarProps}\n>\n {/* Tu Contenido aquí */}\n</ITLayout>`;
114
+
115
+ return (
116
+ <div className="space-y-6">
117
+ <div>
118
+ <h1 className="text-3xl font-extrabold text-slate-800 dark:text-white">ITLayout & ITNavbar</h1>
119
+ <p className="text-slate-500 mt-1.5 text-sm md:text-base">El chasis estructural del portal administrativo con control responsivo y colapso de sidebar.</p>
120
+ </div>
121
+
122
+ <ITCard title="Layout Estructural">
123
+ <div className="space-y-4">
124
+ <p className="text-sm text-slate-600 dark:text-slate-300">
125
+ Este componente es el contenedor raíz de toda la suite que estás navegando en este momento. Proporciona:
126
+ </p>
127
+ <ul className="list-disc pl-5 space-y-2 text-sm text-slate-600 dark:text-slate-300">
128
+ <li>Menú superior (Navbar) con avatar del usuario, correo y menú desplegable.</li>
129
+ <li>Barra de navegación lateral interactiva (Sidebar) colapsable con sub-ítems y badges.</li>
130
+ <li>Fondo dinámico adaptado a presets claros y oscuros.</li>
131
+ </ul>
132
+ <div className="mt-4 p-4 bg-slate-50 dark:bg-slate-900 border rounded-xl">
133
+ <h5 className="font-bold text-xs uppercase text-slate-400 mb-2">Simulación de Barra de Navegación Horizontal (ITNavbar)</h5>
134
+ <ITNavbar
135
+ logoText="PREVIEW NAVBAR"
136
+ navigationItems={[
137
+ { id: "1", label: "Inicio", isActive: true },
138
+ { id: "2", label: "Auditoría" }
139
+ ]}
140
+ userMenu={{
141
+ userName: "Auditor AXZY",
142
+ userEmail: "auditor@axzy.dev",
143
+ menuItems: [{ label: "Ajustes", onClick: () => { } }]
144
+ }}
145
+ />
146
+ </div>
147
+ <CodeViewer code={code} />
148
+ </div>
149
+ </ITCard>
150
+ </div>
151
+ );
152
+ };
@@ -0,0 +1,37 @@
1
+ import { ColorsTypes } from "./colors.types";
2
+
3
+ export const badgeVariants = {
4
+ filled: "filled",
5
+ outlined: "outlined",
6
+ } as const;
7
+
8
+ export const badgeColors = {
9
+ primary: "bg-primary-500 text-white",
10
+ secondary: "bg-secondary-500 text-white",
11
+ success: "bg-success-500 text-white",
12
+ danger: "bg-danger-500 text-white",
13
+ warning: "bg-warning-500 text-black",
14
+ purple: "bg-purple-500 text-white",
15
+ } as const;
16
+
17
+ export const outlinedBadgeColors = {
18
+ primary: "bg-primary-200 border border-primary-500 text-primary-700",
19
+ secondary: "bg-secondary-200 border border-secondary-500 text-secondary-700",
20
+ success: "bg-success-200 border border-success-500 text-success-700",
21
+ danger: "bg-danger-200 border border-danger-500 text-danger-700",
22
+ warning: "bg-warning-200 border border-warning-500 text-warning-700",
23
+ purple: "bg-purple-200 border border-purple-500 text-purple-700",
24
+ } as const;
25
+
26
+ export const badgeSizes = {
27
+ small: "text-xs px-2 py-1",
28
+ medium: "text-sm px-3 py-1.5",
29
+ large: "text-base px-4 py-2",
30
+ } as const;
31
+
32
+ export const getBadgeColorClasses = (color: ColorsTypes, variant: keyof typeof badgeVariants) => {
33
+ if (variant === "outlined") {
34
+ return outlinedBadgeColors[color];
35
+ }
36
+ return badgeColors[color];
37
+ };
@@ -0,0 +1,16 @@
1
+ export const buttonVariants: Record<string, string> = {
2
+ filled: "border-transparent shadow-sm",
3
+ outlined: "bg-transparent border-2",
4
+ raised: "border-transparent shadow-md",
5
+ rounded: "border-transparent shadow-sm rounded-full",
6
+ text: "bg-transparent border-transparent shadow-none hover:bg-black/5 dark:hover:bg-white/10",
7
+ "raised-text": "bg-white border border-gray-200 shadow-sm hover:shadow-md",
8
+ "icon-only": "p-2 aspect-square flex items-center justify-center border-transparent shadow-sm",
9
+ link: "bg-transparent border-transparent shadow-none hover:underline px-0",
10
+ };
11
+
12
+ export const buttonSizes: Record<string, string> = {
13
+ small: "text-xs px-3 py-1.5",
14
+ medium: "text-sm px-5 py-2.5",
15
+ large: "text-lg px-6 py-3",
16
+ };
@@ -0,0 +1,3 @@
1
+ import { semanticColors } from "@/theme/theme";
2
+
3
+ export type ColorsTypes = keyof typeof semanticColors;
@@ -0,0 +1,103 @@
1
+ import React from "react";
2
+ import * as Yup from "yup";
3
+
4
+ // Legacy FieldConfig (kept for backward compatibility during migration)
5
+ export interface FieldConfig {
6
+ name: string;
7
+ label: string;
8
+ type?: "text" | "select" | "date" | "password" | "number";
9
+ currencyFormat?: boolean;
10
+ placeholder?: string;
11
+ disabled?: boolean;
12
+ required?: boolean;
13
+ validation?: Yup.AnySchema;
14
+ column?: number | number[];
15
+ options?: { value: string; label: string }[];
16
+ rightIcon?: React.ReactNode;
17
+ leftIcon?: React.ReactNode;
18
+ valueField?: string;
19
+ showHintLength?: boolean;
20
+ labelField?: string;
21
+ maxLength?: number;
22
+ minLength?: number;
23
+ rows?: number;
24
+ formatNumber?: boolean;
25
+ onChangeAction?: (value: any, setFieldValue: any) => void;
26
+ }
27
+
28
+ // -------------------------------------------------------------
29
+ // V2: ENTERPRISE FORM BUILDER ARCHITECTURE
30
+ // -------------------------------------------------------------
31
+
32
+ export type FieldTypeV2 =
33
+ | "text"
34
+ | "number"
35
+ | "password"
36
+ | "email"
37
+ | "select"
38
+ | "date"
39
+ | "time"
40
+ | "checkbox"
41
+ | "radio"
42
+ | "array" // For dynamic lists
43
+ | "section" // For grouping fields or wizard steps
44
+ | "custom"; // For inversion of control (injecting external components)
45
+
46
+ export interface FieldContextV2 {
47
+ values: Record<string, any>;
48
+ setFieldValue: (field: string, value: any, shouldValidate?: boolean) => void;
49
+ setFieldError: (field: string, error: string) => void;
50
+ setFieldTouched: (field: string, touched?: boolean, shouldValidate?: boolean) => void;
51
+ }
52
+
53
+ export interface FieldConfigV2 {
54
+ name: string;
55
+ label?: string;
56
+ type: FieldTypeV2;
57
+
58
+ // 1. Layout & Structure
59
+ column?: number | { sm?: number; md?: number; lg?: number; xl?: number };
60
+ fields?: FieldConfigV2[]; // REQUIRED if type is "array" or "section"
61
+ collapsible?: boolean; // Optional for "section", default false
62
+ defaultCollapsed?: boolean;
63
+
64
+ // 2. Rules Engine & Dynamic Behavior
65
+ dependsOn?: string[]; // Array of sibling field names to listen to for re-evaluation
66
+ renderWhen?: (values: Record<string, any>) => boolean; // If false, field isn't rendered or submitted
67
+ dynamicProps?: (values: Record<string, any>) => Partial<FieldConfigV2>; // E.g: if A > 100, make this required
68
+
69
+ // 3. Advanced Validations
70
+ validation?: Yup.AnySchema;
71
+ asyncValidation?: (value: any, values: Record<string, any>) => Promise<string | null | undefined>; // Returns error string if invalid
72
+
73
+ // 4. Base Props
74
+ defaultValue?: any;
75
+ placeholder?: string;
76
+ disabled?: boolean | ((values: Record<string, any>) => boolean);
77
+ readOnly?: boolean;
78
+ required?: boolean | ((values: Record<string, any>) => boolean);
79
+
80
+ // 5. Data Support (Sync & Async)
81
+ options?:
82
+ | { value: string | number; label: string }[]
83
+ | (() => Promise<{ value: string | number; label: string }[]>);
84
+ valueField?: string;
85
+ labelField?: string;
86
+
87
+ // 6. Extensibility & UI
88
+ leftIcon?: React.ReactNode;
89
+ rightIcon?: React.ReactNode;
90
+ component?: React.ComponentType<any>; // Custom component for type === "custom"
91
+ className?: string; // Custom container class
92
+
93
+ // Legacy specific overrides
94
+ currencyFormat?: boolean;
95
+ showHintLength?: boolean;
96
+ maxLength?: number;
97
+ minLength?: number;
98
+ rows?: number;
99
+ formatNumber?: boolean;
100
+
101
+ // Lifecycle hook
102
+ onChangeAction?: (val: any, context: FieldContextV2) => void | Promise<void>;
103
+ }
@@ -0,0 +1,15 @@
1
+ export type HandleChange = {
2
+ (e: React.ChangeEvent<unknown>): void;
3
+ <T = string | React.ChangeEvent<unknown>>(
4
+ field: T
5
+ ): T extends React.ChangeEvent<unknown>
6
+ ? void
7
+ : (e: string | React.ChangeEvent<unknown>) => void;
8
+ };
9
+
10
+ export type HandleBlur = {
11
+ (e: React.FocusEvent<unknown, Element>): void;
12
+ <T = unknown>(fieldOrEvent: T): T extends string
13
+ ? (e: unknown) => void
14
+ : void;
15
+ };
@@ -0,0 +1,14 @@
1
+ export const inputVariants: Record<string, string> = {
2
+ primary: "border-slate-500 focus:border-slate-500",
3
+ secondary: "border-gray-400 focus:border-gray-500",
4
+ success: "border-green-500 focus:border-green-500",
5
+ danger: "border-red-500 focus:border-red-500",
6
+ warning: "border-yellow-500 focus:border-yellow-500",
7
+ info: "border-slate-300 focus:border-slate-300",
8
+ };
9
+
10
+ export const inputSizes: Record<string, string> = {
11
+ small: "text-sm py-1 px-2",
12
+ medium: "text-base py-2 px-3",
13
+ large: "text-lg py-3 px-4",
14
+ };
@@ -0,0 +1,9 @@
1
+ export type LoaderSize = "sm" | "md" | "lg" | "xl";
2
+ export type LoaderVariant = "spinner" | "dots" | "bar" | "pulse";
3
+
4
+ export const sizeClasses: Record<LoaderSize, string> = {
5
+ sm: "h-4 w-4",
6
+ md: "h-8 w-8",
7
+ lg: "h-12 w-12",
8
+ xl: "h-16 w-16",
9
+ };
@@ -0,0 +1 @@
1
+ export type SizesTypes = "small" | "medium" | "large";
@@ -0,0 +1,15 @@
1
+ export type TableVariants = "default" | "striped" | "bordered";
2
+
3
+ export type TableSize = "sm" | "md" | "lg";
4
+
5
+ export const variantStyles: Record<TableVariants, string> = {
6
+ default: "",
7
+ striped: "divide-y divide-gray-200",
8
+ bordered: "border border-gray-200",
9
+ };
10
+
11
+ export const sizeStyles: Record<TableSize, string> = {
12
+ sm: "text-xs",
13
+ md: "text-sm",
14
+ lg: "text-lg",
15
+ };
@@ -0,0 +1,8 @@
1
+ export const positionStyles = {
2
+ "top-right": "top-4 right-4",
3
+ "top-center": "top-4 left-1/2 transform -translate-x-1/2",
4
+ "top-left": "top-4 left-4",
5
+ "bottom-right": "bottom-4 right-4",
6
+ "bottom-center": "bottom-4 left-1/2 transform -translate-x-1/2",
7
+ "bottom-left": "bottom-4 left-4",
8
+ };
@@ -0,0 +1,11 @@
1
+ import * as Yup from "yup";
2
+ import { FieldConfig } from "./field.types";
3
+ export const createValidationSchema = (fields: FieldConfig[]) =>
4
+ Yup.object().shape(
5
+ fields.reduce((acc, field) => {
6
+ if (field.validation) {
7
+ acc[field.name] = field.validation;
8
+ }
9
+ return acc;
10
+ }, {} as Record<string, Yup.AnySchema>)
11
+ );
@@ -0,0 +1,99 @@
1
+ import { ITThemePalette } from "@/components/theme-provider/themeProvider.props";
2
+
3
+ /**
4
+ * Determina si un color hexadecimal es claro.
5
+ */
6
+ export const isLightColor = (hex: string): boolean => {
7
+ if (!hex || typeof hex !== "string") return false;
8
+ const color = hex.replace("#", "");
9
+ let r = 0, g = 0, b = 0;
10
+ if (color.length === 3) {
11
+ r = parseInt(color[0] + color[0], 16);
12
+ g = parseInt(color[1] + color[1], 16);
13
+ b = parseInt(color[2] + color[2], 16);
14
+ } else if (color.length === 6) {
15
+ r = parseInt(color.substring(0, 2), 16);
16
+ g = parseInt(color.substring(2, 4), 16);
17
+ b = parseInt(color.substring(4, 6), 16);
18
+ } else {
19
+ return false;
20
+ }
21
+ const brightness = (r * 299 + g * 587 + b * 114) / 1000;
22
+ return brightness > 140;
23
+ };
24
+
25
+ /**
26
+ * Traduce un valor de color de CSS (hexadecimal o variable var(--...)) a hexadecimal absoluto.
27
+ */
28
+ export const resolveCssColor = (
29
+ colorStr: string,
30
+ palette?: ITThemePalette,
31
+ isDarkMode?: boolean
32
+ ): string => {
33
+ if (!colorStr) return "#ffffff";
34
+ const cleanColor = colorStr.trim();
35
+ if (cleanColor.startsWith("#")) return cleanColor;
36
+
37
+ if (cleanColor.includes("var(")) {
38
+ const match = cleanColor.match(/var\(([^,)]+)(?:,\s*([^)]+))?\)/);
39
+ if (match) {
40
+ const varName = match[1].trim();
41
+ const fallback = match[2]?.trim();
42
+
43
+ if (varName === "--color-primary" || varName.includes("primary-500")) {
44
+ return palette?.primary || "#06b6d4";
45
+ }
46
+ if (varName.includes("primary")) {
47
+ return palette?.primary || "#06b6d4";
48
+ }
49
+ if (varName === "--color-secondary" || varName.includes("secondary-500")) {
50
+ return palette?.secondary || "#6b7280";
51
+ }
52
+ if (varName.includes("secondary")) {
53
+ return palette?.secondary || "#6b7280";
54
+ }
55
+ if (varName.includes("ternary")) {
56
+ return palette?.ternary || "#8b5cf6";
57
+ }
58
+ if (varName.includes("danger")) {
59
+ return palette?.danger || "#ef4444";
60
+ }
61
+ if (varName.includes("success")) {
62
+ return palette?.success || "#22c55e";
63
+ }
64
+ if (varName.includes("info")) {
65
+ return palette?.info || "#3b82f6";
66
+ }
67
+ if (varName.includes("warning")) {
68
+ return palette?.warning || "#eab308";
69
+ }
70
+ if (varName.includes("alert")) {
71
+ return palette?.alert || "#f97316";
72
+ }
73
+ if (varName.includes("card-bg")) {
74
+ return isDarkMode ? "#111827" : "#ffffff";
75
+ }
76
+ if (varName.includes("modal-bg")) {
77
+ return isDarkMode ? "#111827" : "#ffffff";
78
+ }
79
+
80
+ if (fallback) {
81
+ return resolveCssColor(fallback, palette, isDarkMode);
82
+ }
83
+ }
84
+ }
85
+
86
+ return "#ffffff";
87
+ };
88
+
89
+ /**
90
+ * Obtiene la clase de color de texto óptima (blanca o gris oscuro) basado en el fondo.
91
+ */
92
+ export const getContrastTextColor = (
93
+ bgColor: string,
94
+ palette?: ITThemePalette,
95
+ isDarkMode?: boolean
96
+ ): "text-white" | "text-slate-800" => {
97
+ const resolvedColor = resolveCssColor(bgColor, palette, isDarkMode);
98
+ return isLightColor(resolvedColor) ? "text-slate-800" : "text-white";
99
+ };
@@ -0,0 +1,120 @@
1
+ import clsx from "clsx";
2
+
3
+ // ──────────────────────────────────────────────
4
+ // INPUT-LIKE COMPONENTS
5
+ // ──────────────────────────────────────────────
6
+
7
+ export function inputContainer(hasError?: boolean, disabled?: boolean) {
8
+ return clsx(
9
+ "w-full border border-solid transition-all duration-200 rounded-lg px-3 py-2 text-sm",
10
+ "focus:outline-none focus:ring-2",
11
+ hasError
12
+ ? "border-red-500 ring-red-100"
13
+ : "border-gray-300 focus:border-primary-500 focus:ring-primary-100",
14
+ disabled && "opacity-50 cursor-not-allowed bg-gray-100"
15
+ );
16
+ }
17
+
18
+ export function inputLabel(error?: boolean) {
19
+ return clsx(
20
+ "text-sm font-medium",
21
+ error ? "text-red-500" : "text-gray-700 dark:text-slate-300"
22
+ );
23
+ }
24
+
25
+ export const inputError = "text-red-500 text-xs mt-1";
26
+
27
+ export function inputWrapper(className?: string) {
28
+ return clsx("flex flex-col gap-1.5", className);
29
+ }
30
+
31
+ export const iconAbsoluteLeft = "absolute inset-y-0 left-0 flex items-center pl-3 z-10";
32
+ export const iconAbsoluteRight = "absolute inset-y-0 right-0 flex items-center pr-3 z-10";
33
+
34
+ // ──────────────────────────────────────────────
35
+ // TABLE COMPONENTS
36
+ // ──────────────────────────────────────────────
37
+
38
+ export const tableContainer = "rounded-xl shadow-sm border border-secondary-200 overflow-hidden";
39
+
40
+ export const tableHeaderRow = "bg-secondary-50 border-b border-secondary-200 text-xs uppercase tracking-wider font-semibold text-secondary-500";
41
+
42
+ export function tableHeaderCell(className?: string) {
43
+ return clsx("px-4 py-4 align-top", className);
44
+ }
45
+
46
+ export const tableSortButtonActive = "bg-secondary-200 text-secondary-900";
47
+ export const tableSortButtonInactive = "hover:bg-secondary-200 text-secondary-400 hover:text-secondary-700";
48
+
49
+ export const tableBody = "divide-y divide-secondary-100";
50
+
51
+ export const tableRow = "hover:bg-secondary-50/50 transition-colors duration-150 group";
52
+
53
+ export function tableCell(className?: string) {
54
+ return clsx("px-4 py-3 align-middle", className);
55
+ }
56
+
57
+ export const tableActionsCell = "flex items-center justify-center gap-2";
58
+ export const tableCellText = "text-secondary-700 font-medium";
59
+
60
+ export function tableEmptyState(colSpan: number) {
61
+ return { colSpan, className: "px-6 py-20 text-center" };
62
+ }
63
+
64
+ export const tableEmptyContent = "flex flex-col items-center justify-center text-secondary-400";
65
+
66
+ // ──────────────────────────────────────────────
67
+ // CARD / CONTAINER
68
+ // ──────────────────────────────────────────────
69
+
70
+ export const cardContainer = "overflow-hidden";
71
+
72
+ // ──────────────────────────────────────────────
73
+ // FORM GRID
74
+ // ──────────────────────────────────────────────
75
+
76
+ export const gridColsClasses: Record<number, string> = {
77
+ 1: "grid-cols-1",
78
+ 2: "grid-cols-2",
79
+ 3: "grid-cols-3",
80
+ 4: "grid-cols-4",
81
+ 6: "grid-cols-6",
82
+ 8: "grid-cols-8",
83
+ 12: "grid-cols-12",
84
+ };
85
+
86
+ export function getGridColsClass(columns: number) {
87
+ return gridColsClasses[columns] || "grid-cols-12";
88
+ }
89
+
90
+ export function getColSpanClass(
91
+ span: number | number[] | { sm?: number; md?: number; lg?: number; xl?: number },
92
+ maxCols: number
93
+ ) {
94
+ if (typeof span === "number") {
95
+ return `col-span-${Math.min(span, maxCols)}`;
96
+ }
97
+ if (Array.isArray(span)) {
98
+ const [sm, md, lg] = span;
99
+ return clsx(
100
+ `col-span-${Math.min(sm, maxCols)}`,
101
+ md !== undefined && `md:col-span-${Math.min(md, maxCols)}`,
102
+ lg !== undefined && `lg:col-span-${Math.min(lg, maxCols)}`
103
+ );
104
+ }
105
+ const classes: string[] = [];
106
+ if (span.sm) classes.push(`col-span-${Math.min(span.sm, maxCols)}`);
107
+ if (span.md) classes.push(`md:col-span-${Math.min(span.md, maxCols)}`);
108
+ if (span.lg) classes.push(`lg:col-span-${Math.min(span.lg, maxCols)}`);
109
+ if (span.xl) classes.push(`xl:col-span-${Math.min(span.xl, maxCols)}`);
110
+ return classes.length ? clsx(classes) : `col-span-${maxCols}`;
111
+ }
112
+
113
+ export const formGrid = (columns: number) =>
114
+ clsx("grid gap-y-6 gap-x-5", getGridColsClass(columns));
115
+
116
+ // ──────────────────────────────────────────────
117
+ // DISABLED OVERLAY
118
+ // ──────────────────────────────────────────────
119
+
120
+ export const disabledOverlay = "opacity-50 cursor-not-allowed";
@@ -0,0 +1,10 @@
1
+ export const formatCurrencyMX = (value: number) => {
2
+ return value.toLocaleString("es-MX", {
3
+ style: "currency",
4
+ currency: "MXN",
5
+ });
6
+ };
7
+
8
+ export const getNestedValue = (obj: any, path: string) => {
9
+ return path.split('.').reduce((acc, part) => acc && acc[part], obj);
10
+ };