@axzydev/axzy_ui_system 1.4.7 → 1.5.0

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 (226) hide show
  1. package/README.md +2 -11
  2. package/dist/index.cjs +2174 -1570
  3. package/dist/index.cjs.map +1 -1
  4. package/dist/index.css +1 -1
  5. package/dist/index.css.map +1 -1
  6. package/dist/index.d.cts +232 -19
  7. package/dist/index.d.ts +232 -19
  8. package/dist/index.js +1838 -1238
  9. package/dist/index.js.map +1 -1
  10. package/dist/layered.css +1 -1
  11. package/package.json +3 -16
  12. package/src/App.tsx +90 -73
  13. package/src/components/atoms/badget/badget.tsx +23 -5
  14. package/src/components/atoms/chip/chip.tsx +3 -1
  15. package/src/components/atoms/image/image.tsx +3 -1
  16. package/src/components/atoms/input/input.tsx +8 -5
  17. package/src/components/atoms/loader/loader.tsx +3 -1
  18. package/src/components/atoms/slide/slide.props.ts +12 -0
  19. package/src/components/atoms/slide/slide.tsx +3 -0
  20. package/src/components/molecules/alert/alert.tsx +3 -1
  21. package/src/components/molecules/breadcrumbs/breadcrumbs.tsx +3 -1
  22. package/src/components/molecules/calendar/calendar.tsx +9 -6
  23. package/src/components/molecules/card/card.tsx +5 -2
  24. package/src/components/molecules/chip-input/chip-input.tsx +9 -7
  25. package/src/components/molecules/date-picker/datePicker.tsx +9 -9
  26. package/src/components/molecules/dropdown-menu/dropdown-menu.props.ts +1 -1
  27. package/src/components/molecules/dropdown-menu/dropdown-menu.tsx +6 -3
  28. package/src/components/molecules/field/field.tsx +3 -1
  29. package/src/components/molecules/form-header/form-header.tsx +3 -1
  30. package/src/components/molecules/line-bar-chart/line-bar-chart.props.ts +2 -2
  31. package/src/components/molecules/line-bar-chart/line-bar-chart.tsx +20 -15
  32. package/src/components/molecules/masked-input/masked-input.tsx +3 -1
  33. package/src/components/molecules/multi-select/multi-select.tsx +12 -9
  34. package/src/components/molecules/pagination/pagination.tsx +11 -5
  35. package/src/components/molecules/search-select/search-select.tsx +11 -9
  36. package/src/components/molecules/select/select.tsx +6 -4
  37. package/src/components/molecules/stepper/stepper.tsx +6 -4
  38. package/src/components/molecules/table/table.props.ts +10 -2
  39. package/src/components/molecules/table/table.tsx +163 -114
  40. package/src/components/molecules/time-picker/timePicker.tsx +8 -6
  41. package/src/components/molecules/wysiwyg/wysiwyg.tsx +23 -12
  42. package/src/components/organisms/confirm-dialog/confirm-dialog.props.ts +4 -4
  43. package/src/components/organisms/confirm-dialog/confirm-dialog.tsx +16 -8
  44. package/src/components/organisms/data-table/dataTable.props.ts +3 -2
  45. package/src/components/organisms/data-table/dataTable.tsx +149 -81
  46. package/src/components/organisms/dialog/dialog.tsx +3 -0
  47. package/src/components/organisms/drawer/drawer.tsx +3 -0
  48. package/src/components/organisms/dropfile/dropfile.tsx +19 -17
  49. package/src/components/organisms/form-builder/fieldRenderer.tsx +4 -2
  50. package/src/components/organisms/navbar/navbar.tsx +4 -2
  51. package/src/components/organisms/page-header/page-header.tsx +3 -1
  52. package/src/components/organisms/searchTable/components/PaginationControls.tsx +8 -6
  53. package/src/components/organisms/searchTable/components/PaginationInfo.tsx +3 -1
  54. package/src/components/organisms/searchTable/components/SearchAndSortBar.tsx +7 -5
  55. package/src/components/organisms/searchTable/components/SearchInput.tsx +4 -2
  56. package/src/components/organisms/searchTable/components/SortButton.tsx +13 -11
  57. package/src/components/organisms/searchTable/components/TableEmptyState.tsx +4 -2
  58. package/src/components/organisms/searchTable/components/TableRow.tsx +6 -4
  59. package/src/components/organisms/searchTable/searchTable.tsx +4 -2
  60. package/src/components/organisms/sidebar/sidebar.props.ts +1 -1
  61. package/src/components/organisms/sidebar/sidebar.tsx +9 -4
  62. package/src/components/organisms/toast/toast.tsx +3 -1
  63. package/src/components/organisms/topbar/topbar.tsx +4 -2
  64. package/src/components/templates/page/page.props.ts +4 -4
  65. package/src/components/templates/page/page.tsx +6 -4
  66. package/src/components/theme-provider/themeProvider.tsx +28 -17
  67. package/src/dev.css +77 -2
  68. package/src/global.d.ts +10 -0
  69. package/src/i18n/context.ts +9 -0
  70. package/src/i18n/index.ts +22 -0
  71. package/src/i18n/locales/en.ts +163 -0
  72. package/src/i18n/locales/es.ts +165 -0
  73. package/src/i18n/provider.tsx +44 -0
  74. package/src/i18n/translator.ts +82 -0
  75. package/src/i18n/types.ts +54 -0
  76. package/src/i18n/useITTranslation.ts +20 -0
  77. package/src/index.css +0 -1
  78. package/src/index.ts +9 -3
  79. package/src/sandbox/LandingShowcase.tsx +224 -580
  80. package/src/sandbox/NotFoundShowcase.tsx +51 -36
  81. package/src/sandbox/TopbarSearch.tsx +6 -4
  82. package/src/sandbox/controls.tsx +180 -0
  83. package/src/sandbox/i18n.ts +1929 -0
  84. package/src/sandbox/icons.tsx +25 -0
  85. package/src/sandbox/locale.tsx +72 -0
  86. package/src/sandbox/ui.tsx +377 -0
  87. package/src/sandbox/useHashRoute.ts +46 -10
  88. package/src/showcases/DataShowcases.tsx +201 -80
  89. package/src/showcases/FeedbackShowcases.tsx +37 -30
  90. package/src/showcases/FormShowcases.tsx +302 -214
  91. package/src/showcases/GettingStartedShowcase.tsx +151 -145
  92. package/src/showcases/HelpShowcase.tsx +126 -128
  93. package/src/showcases/HomeShowcase.tsx +678 -482
  94. package/src/showcases/LayoutPrimitivesShowcases.tsx +129 -114
  95. package/src/showcases/NavigationShowcases.tsx +45 -37
  96. package/src/showcases/PageShowcases.tsx +171 -152
  97. package/src/showcases/ProductoDetalle.tsx +272 -129
  98. package/src/showcases/ShowcaseLayout.tsx +270 -216
  99. package/src/showcases/SizesShowcase.tsx +123 -64
  100. package/src/showcases/StructureShowcases.tsx +157 -131
  101. package/src/showcases/portfolioUi.tsx +153 -0
  102. package/src/showcases/techIcons.ts +3 -0
  103. package/src/types/table.types.ts +110 -0
  104. package/src/utils/table.utils.ts +10 -2
  105. package/src/components/atoms/avatar/avatar.doc.mdx +0 -48
  106. package/src/components/atoms/avatar/avatar.stories.tsx +0 -64
  107. package/src/components/atoms/badget/badget.doc.mdx +0 -46
  108. package/src/components/atoms/badget/badget.stories.tsx +0 -75
  109. package/src/components/atoms/button/button.doc.mdx +0 -59
  110. package/src/components/atoms/button/button.stories.tsx +0 -173
  111. package/src/components/atoms/checkbox/checkbox.doc.mdx +0 -54
  112. package/src/components/atoms/checkbox/checkbox.stories.tsx +0 -53
  113. package/src/components/atoms/chip/chip.doc.mdx +0 -47
  114. package/src/components/atoms/chip/chip.stories.tsx +0 -64
  115. package/src/components/atoms/divider/divider.doc.mdx +0 -42
  116. package/src/components/atoms/divider/divider.stories.tsx +0 -33
  117. package/src/components/atoms/flex/flex.doc.mdx +0 -59
  118. package/src/components/atoms/flex/flex.stories.tsx +0 -70
  119. package/src/components/atoms/grid/grid.doc.mdx +0 -54
  120. package/src/components/atoms/grid/grid.stories.tsx +0 -71
  121. package/src/components/atoms/image/image.doc.mdx +0 -44
  122. package/src/components/atoms/image/image.stories.tsx +0 -48
  123. package/src/components/atoms/input/input.doc.mdx +0 -70
  124. package/src/components/atoms/input/input.stories.tsx +0 -113
  125. package/src/components/atoms/input-number/input-number.doc.mdx +0 -74
  126. package/src/components/atoms/input-number/input-number.stories.tsx +0 -111
  127. package/src/components/atoms/loader/loader.doc.mdx +0 -43
  128. package/src/components/atoms/loader/loader.stories.tsx +0 -104
  129. package/src/components/atoms/popover/popover.doc.mdx +0 -53
  130. package/src/components/atoms/popover/popover.stories.tsx +0 -24
  131. package/src/components/atoms/progress/progress.doc.mdx +0 -48
  132. package/src/components/atoms/progress/progress.stories.tsx +0 -39
  133. package/src/components/atoms/radio/radio.doc.mdx +0 -62
  134. package/src/components/atoms/radio/radio.stories.tsx +0 -48
  135. package/src/components/atoms/segmented-control/segmented-control.doc.mdx +0 -60
  136. package/src/components/atoms/segmented-control/segmented-control.stories.tsx +0 -62
  137. package/src/components/atoms/skeleton/skeleton.doc.mdx +0 -43
  138. package/src/components/atoms/skeleton/skeleton.stories.tsx +0 -29
  139. package/src/components/atoms/slide/slide.doc.mdx +0 -46
  140. package/src/components/atoms/slide/slide.stories.tsx +0 -120
  141. package/src/components/atoms/slider/slider.doc.mdx +0 -49
  142. package/src/components/atoms/slider/slider.stories.tsx +0 -29
  143. package/src/components/atoms/stack/stack.doc.mdx +0 -126
  144. package/src/components/atoms/stack/stack.stories.tsx +0 -283
  145. package/src/components/atoms/text/text.doc.mdx +0 -41
  146. package/src/components/atoms/text/text.stories.tsx +0 -66
  147. package/src/components/atoms/textarea/textarea.doc.mdx +0 -64
  148. package/src/components/atoms/textarea/textarea.stories.tsx +0 -26
  149. package/src/components/atoms/tooltip/tooltip.doc.mdx +0 -47
  150. package/src/components/atoms/tooltip/tooltip.stories.tsx +0 -19
  151. package/src/components/isolation/isolation.stories.tsx +0 -202
  152. package/src/components/molecules/accordion/accordion.doc.mdx +0 -47
  153. package/src/components/molecules/accordion/accordion.stories.tsx +0 -68
  154. package/src/components/molecules/alert/alert.doc.mdx +0 -48
  155. package/src/components/molecules/alert/alert.stories.tsx +0 -40
  156. package/src/components/molecules/breadcrumbs/breadcrumbs.doc.mdx +0 -57
  157. package/src/components/molecules/breadcrumbs/breadcrumbs.stories.tsx +0 -20
  158. package/src/components/molecules/calendar/calendar.doc.mdx +0 -76
  159. package/src/components/molecules/calendar/calendar.stories.tsx +0 -90
  160. package/src/components/molecules/card/card.doc.mdx +0 -54
  161. package/src/components/molecules/card/card.stories.tsx +0 -57
  162. package/src/components/molecules/chip-input/chip-input.doc.mdx +0 -44
  163. package/src/components/molecules/chip-input/chip-input.stories.tsx +0 -52
  164. package/src/components/molecules/date-picker/date-picker.doc.mdx +0 -65
  165. package/src/components/molecules/date-picker/date-picker.stories.tsx +0 -88
  166. package/src/components/molecules/dropdown-menu/dropdown-menu.doc.mdx +0 -46
  167. package/src/components/molecules/dropdown-menu/dropdown-menu.stories.tsx +0 -41
  168. package/src/components/molecules/empty-state/empty-state.doc.mdx +0 -50
  169. package/src/components/molecules/empty-state/empty-state.stories.tsx +0 -19
  170. package/src/components/molecules/field/field.doc.mdx +0 -43
  171. package/src/components/molecules/field/field.stories.tsx +0 -42
  172. package/src/components/molecules/form-header/form-header.doc.mdx +0 -38
  173. package/src/components/molecules/form-header/form-header.stories.tsx +0 -52
  174. package/src/components/molecules/masked-input/masked-input.doc.mdx +0 -78
  175. package/src/components/molecules/masked-input/masked-input.stories.tsx +0 -126
  176. package/src/components/molecules/multi-select/multi-select.doc.mdx +0 -55
  177. package/src/components/molecules/multi-select/multi-select.stories.tsx +0 -59
  178. package/src/components/molecules/pagination/pagination.doc.mdx +0 -62
  179. package/src/components/molecules/pagination/pagination.stories.tsx +0 -110
  180. package/src/components/molecules/search-select/search-select.doc.mdx +0 -77
  181. package/src/components/molecules/search-select/search-select.stories.tsx +0 -146
  182. package/src/components/molecules/select/select.doc.mdx +0 -75
  183. package/src/components/molecules/select/select.stories.tsx +0 -85
  184. package/src/components/molecules/stat-card/stat-card.doc.mdx +0 -48
  185. package/src/components/molecules/stat-card/stat-card.stories.tsx +0 -40
  186. package/src/components/molecules/stepper/stepper.doc.mdx +0 -54
  187. package/src/components/molecules/stepper/stepper.stories.tsx +0 -154
  188. package/src/components/molecules/table/table.doc.mdx +0 -123
  189. package/src/components/molecules/table/table.stories.tsx +0 -402
  190. package/src/components/molecules/tabs/tabs.doc.mdx +0 -52
  191. package/src/components/molecules/tabs/tabs.stories.tsx +0 -31
  192. package/src/components/molecules/time-picker/timePicker.doc.mdx +0 -68
  193. package/src/components/molecules/time-picker/timePicker.stories.tsx +0 -130
  194. package/src/components/molecules/wysiwyg/wysiwyg.stories.tsx +0 -95
  195. package/src/components/organisms/confirm-dialog/confirm-dialog.doc.mdx +0 -60
  196. package/src/components/organisms/confirm-dialog/confirm-dialog.stories.tsx +0 -32
  197. package/src/components/organisms/data-table/ITDataTable.doc.mdx +0 -115
  198. package/src/components/organisms/data-table/ITDataTable.stories.tsx +0 -353
  199. package/src/components/organisms/dialog/dialog.doc.mdx +0 -54
  200. package/src/components/organisms/dialog/dialog.stories.tsx +0 -126
  201. package/src/components/organisms/drawer/drawer.doc.mdx +0 -59
  202. package/src/components/organisms/drawer/drawer.stories.tsx +0 -40
  203. package/src/components/organisms/dropfile/dropfile.doc.mdx +0 -74
  204. package/src/components/organisms/dropfile/dropfile.stories.tsx +0 -93
  205. package/src/components/organisms/form-builder/formBuilder.doc.mdx +0 -251
  206. package/src/components/organisms/form-builder/formBuilder.stories.tsx +0 -914
  207. package/src/components/organisms/navbar/navbar.doc.mdx +0 -77
  208. package/src/components/organisms/navbar/navbar.stories.tsx +0 -83
  209. package/src/components/organisms/page-header/page-header.doc.mdx +0 -54
  210. package/src/components/organisms/page-header/page-header.stories.tsx +0 -74
  211. package/src/components/organisms/searchTable/searchTable.doc.mdx +0 -79
  212. package/src/components/organisms/searchTable/searchTable.stories.tsx +0 -73
  213. package/src/components/organisms/sidebar/sidebar.doc.mdx +0 -176
  214. package/src/components/organisms/sidebar/sidebar.stories.tsx +0 -234
  215. package/src/components/organisms/toast/toast.doc.mdx +0 -50
  216. package/src/components/organisms/toast/toast.stories.tsx +0 -137
  217. package/src/components/organisms/topbar/topbar.doc.mdx +0 -72
  218. package/src/components/organisms/topbar/topbar.stories.tsx +0 -79
  219. package/src/components/organisms/triple-filter/tripleFilter.doc.mdx +0 -62
  220. package/src/components/organisms/triple-filter/tripleFilter.stories.tsx +0 -31
  221. package/src/components/templates/layout/layout.doc.mdx +0 -53
  222. package/src/components/templates/layout/layout.stories.tsx +0 -113
  223. package/src/components/templates/page/page.doc.mdx +0 -86
  224. package/src/components/templates/page/page.stories.tsx +0 -97
  225. package/src/components/theme-provider/themeProvider.doc.mdx +0 -85
  226. package/src/components/theme-provider/themeProvider.stories.tsx +0 -58
@@ -3,6 +3,7 @@ import { ITConfirmDialogProps } from "./confirm-dialog.props";
3
3
  import ITButton from "@/components/atoms/button/button";
4
4
  import { FaExclamationTriangle } from "react-icons/fa";
5
5
  import ITText from "@/components/atoms/text/text";
6
+ import { useITTranslation } from "@/i18n";
6
7
 
7
8
  /**
8
9
  * Confirmation modal dialog for destructive or critical actions.
@@ -27,15 +28,22 @@ export default function ITConfirmDialog({
27
28
  isOpen,
28
29
  onClose,
29
30
  onConfirm,
30
- title = "Confirmar acción",
31
- message = "¿Estás seguro de que deseas continuar?",
32
- confirmLabel = "Confirmar",
33
- cancelLabel = "Cancelar",
31
+ title,
32
+ message,
33
+ confirmLabel,
34
+ cancelLabel,
34
35
  variant = "primary",
35
36
  loading = false,
36
37
  }: ITConfirmDialogProps) {
38
+ const { t } = useITTranslation();
39
+
37
40
  if (!isOpen) return null;
38
41
 
42
+ const resolvedTitle = title ?? t("confirmDialog.title");
43
+ const resolvedMessage = message ?? t("confirmDialog.message");
44
+ const resolvedConfirmLabel = confirmLabel ?? t("common.confirm");
45
+ const resolvedCancelLabel = cancelLabel ?? t("common.cancel");
46
+
39
47
  return (
40
48
  <div className="fixed inset-0 z-[60] flex items-center justify-center p-4">
41
49
  <div className="absolute inset-0 bg-black/40 backdrop-blur-sm" onClick={onClose} />
@@ -50,13 +58,13 @@ export default function ITConfirmDialog({
50
58
  <FaExclamationTriangle className="text-amber-600" size={18} />
51
59
  </div>
52
60
  <div className="flex-1">
53
- <ITText as="h3" className="text-lg font-bold text-slate-800 dark:text-white">{title}</ITText>
54
- <ITText as="p" className="text-sm text-slate-500 dark:text-slate-400 mt-1">{message}</ITText>
61
+ <ITText as="h3" className="text-lg font-bold text-slate-800 dark:text-white">{resolvedTitle}</ITText>
62
+ <ITText as="p" className="text-sm text-slate-500 dark:text-slate-400 mt-1">{resolvedMessage}</ITText>
55
63
  </div>
56
64
  </div>
57
65
  <div className="flex justify-end gap-3 mt-6">
58
- <ITButton label={cancelLabel} variant="outlined" size="sm" onClick={onClose} disabled={loading} />
59
- <ITButton label={confirmLabel} color={variant} size="sm" onClick={onConfirm} disabled={loading} />
66
+ <ITButton label={resolvedCancelLabel} variant="outlined" size="sm" onClick={onClose} disabled={loading} />
67
+ <ITButton label={resolvedConfirmLabel} color={variant} size="sm" onClick={onConfirm} disabled={loading} />
60
68
  </div>
61
69
  </div>
62
70
  </div>
@@ -1,6 +1,6 @@
1
1
  import { ReactNode } from "react";
2
2
  import { Column } from "@/components/molecules/table/table.props";
3
- import { ColumnFilters, TableDensity } from "@/types/table.types";
3
+ import { ColumnFilters, TableDensity, TableDesignProps } from "@/types/table.types";
4
4
 
5
5
  /** Parameters passed to `fetchData` every time pagination, filters, or sorting change. */
6
6
  export interface ITDataTableFetchParams {
@@ -31,7 +31,8 @@ export interface ITDataTableResponse<T> {
31
31
  total: number;
32
32
  }
33
33
 
34
- export interface ITDataTableProps<T extends Record<string, unknown>> {
34
+ export interface ITDataTableProps<T extends Record<string, unknown>>
35
+ extends TableDesignProps {
35
36
  /**
36
37
  * The column configuration array matching ITTable but adapted for Server-Side processing
37
38
  */
@@ -13,6 +13,7 @@ import ITSearchSelect from "@/components/molecules/search-select/search-select";
13
13
  import ITDatePicker from "@/components/molecules/date-picker/datePicker";
14
14
  import { Column } from "@/components/molecules/table/table.props";
15
15
  import { formatCurrencyMX, getPinnedColumnMeta, isInteractiveTarget } from "@/utils/table.utils";
16
+ import { useITTranslation, toIntlLocale } from "@/i18n";
16
17
  import { ITDataTableProps } from "./dataTable.props";
17
18
  import ITText from "@/components/atoms/text/text";
18
19
  import {
@@ -85,13 +86,55 @@ export default function ITDataTable<T extends Record<string, unknown>>({
85
86
  rowHeight,
86
87
  overscan = 5,
87
88
  stickyHeader = false,
89
+ showViewToggle = true,
90
+ design,
91
+ colors,
92
+ containerStyle,
93
+ cardClassName,
94
+ cardStyle,
95
+ toolbarClassName,
96
+ toolbarStyle,
97
+ headerClassName,
98
+ headerStyle,
99
+ headerCellClassName,
100
+ headerCellStyle,
101
+ rowClassName,
102
+ rowStyle,
103
+ cellClassName,
104
+ cellStyle,
105
+ cardsClassName,
106
+ cardsStyle,
107
+ footerClassName,
108
+ footerStyle,
88
109
  }: ITDataTableProps<T>) {
110
+ const { t, locale } = useITTranslation();
89
111
  const [viewMode, setViewMode] = useState<"table" | "cards">(defaultView || "table");
90
112
  const { ref: rootRef, width: containerWidth } = useElementSize<HTMLDivElement>();
91
113
  const [data, setData] = useState<T[]>([]);
92
114
  const [totalItems, setTotalItems] = useState(0);
93
115
  const [isLoading, setIsLoading] = useState(fetchOnMount);
94
116
 
117
+ // Per-instance color overrides written as local `--color-table-*` variables.
118
+ // Declared on the wrapper (an ancestor), they beat the global theme's
119
+ // `:root` values for this subtree only.
120
+ const colorVars = {
121
+ ...(colors?.headerBg ? { "--color-table-headerBg": colors.headerBg } : {}),
122
+ ...(colors?.headerText ? { "--color-table-headerText": colors.headerText } : {}),
123
+ ...(colors?.rowBg ? { "--color-table-rowBg": colors.rowBg } : {}),
124
+ ...(colors?.rowText ? { "--color-table-rowText": colors.rowText } : {}),
125
+ ...(colors?.rowHover ? { "--color-table-rowHover": colors.rowHover } : {}),
126
+ } as React.CSSProperties;
127
+
128
+ /** Merge a `design` slot with its flat shortcut (flat wins) into className/style. */
129
+ const mergeSlot = (
130
+ slot: { className?: string; style?: React.CSSProperties } | undefined,
131
+ flatClassName?: string,
132
+ flatStyle?: React.CSSProperties
133
+ ) => ({
134
+ className: clsx(slot?.className, flatClassName),
135
+ style: { ...slot?.style, ...flatStyle } as React.CSSProperties,
136
+ });
137
+
95
138
  const isFixed = layout === "fixed";
96
139
  const forcedCards =
97
140
  autoCardBreakpoint > 0 && containerWidth > 0 && containerWidth < autoCardBreakpoint;
@@ -198,17 +241,21 @@ export default function ITDataTable<T extends Record<string, unknown>>({
198
241
  currentValue === undefined ? true : currentValue === true ? false : undefined;
199
242
 
200
243
  const getToggleLabel = () => {
201
- if (currentValue === undefined) return "Mostrar todos";
202
- if (currentValue === true) return "Filtrar solo verdaderos";
203
- return "Filtrar solo falsos";
244
+ if (currentValue === undefined) return t("table.showAll");
245
+ if (currentValue === true) return t("table.filterTrue");
246
+ return t("table.filterFalse");
204
247
  };
248
+ const toggleLabel = t("table.filterToggle", {
249
+ action: getToggleLabel(),
250
+ label: col.label,
251
+ });
205
252
 
206
253
  return (
207
254
  <button
208
255
  className="flex items-center justify-center cursor-pointer focus:outline-none focus:ring-2 focus:ring-slate-400 focus:ring-offset-2 rounded-full p-1 transition-all duration-200"
209
256
  onClick={() => handleFilterChange(col.key, nextValue)}
210
- aria-label={`${getToggleLabel()} para ${col.label}`}
211
- title={`${getToggleLabel()} para ${col.label}`}
257
+ aria-label={toggleLabel}
258
+ title={toggleLabel}
212
259
  disabled={isLoading}
213
260
  >
214
261
  <div className="relative w-10 h-5 bg-secondary-300 rounded-full">
@@ -229,16 +276,16 @@ export default function ITDataTable<T extends Record<string, unknown>>({
229
276
 
230
277
  if (col.filter === "catalog" && col.catalogOptions) {
231
278
  if (col.catalogOptions.loading) {
232
- return <FaSpinner className="animate-spin" aria-label="Cargando opciones" title="Cargando opciones" />;
279
+ return <FaSpinner className="animate-spin" aria-label={t("common.loadingOptions")} title={t("common.loadingOptions")} />;
233
280
  }
234
281
  if (col.catalogOptions.error) {
235
- return <ITText as="span" className="text-danger-500 text-xs">Error cargando</ITText>;
282
+ return <ITText as="span" className="text-danger-500 text-xs">{t("common.loadError")}</ITText>;
236
283
  }
237
284
  return (
238
285
  <ITSelect
239
286
  name={`filter-${col.key}`}
240
287
  options={[
241
- { value: "", label: "Todos" },
288
+ { value: "", label: t("common.all") },
242
289
  ...col.catalogOptions.data.map((item) => ({
243
290
  value: String(item.id),
244
291
  label: item.name,
@@ -258,10 +305,10 @@ export default function ITDataTable<T extends Record<string, unknown>>({
258
305
 
259
306
  if (col.filter === "search" && col.catalogOptions) {
260
307
  if (col.catalogOptions.loading) {
261
- return <FaSpinner className="animate-spin" aria-label="Cargando opciones" title="Cargando opciones" />;
308
+ return <FaSpinner className="animate-spin" aria-label={t("common.loadingOptions")} title={t("common.loadingOptions")} />;
262
309
  }
263
310
  if (col.catalogOptions.error) {
264
- return <ITText as="span" className="text-danger-500 text-xs">Error cargando</ITText>;
311
+ return <ITText as="span" className="text-danger-500 text-xs">{t("common.loadError")}</ITText>;
265
312
  }
266
313
  const searchValue = filters[col.key];
267
314
  return (
@@ -280,7 +327,7 @@ export default function ITDataTable<T extends Record<string, unknown>>({
280
327
  onSearch={col.catalogOptions.onSearch}
281
328
  isLoading={col.catalogOptions.loading}
282
329
  size="sm"
283
- placeholder="Buscar..."
330
+ placeholder={t("common.search")}
284
331
  clearable
285
332
  className="w-full"
286
333
  onBlur={() => {}}
@@ -299,7 +346,7 @@ export default function ITDataTable<T extends Record<string, unknown>>({
299
346
  minDate={col.dateFilterOptions?.minDate}
300
347
  maxDate={col.dateFilterOptions?.maxDate}
301
348
  size="sm"
302
- placeholder="dd/mm/aaaa"
349
+ placeholder={t("datePicker.placeholder")}
303
350
  className="w-full"
304
351
  disabled={isLoading}
305
352
  />
@@ -319,7 +366,7 @@ export default function ITDataTable<T extends Record<string, unknown>>({
319
366
  minDate={col.dateFilterOptions?.minDate}
320
367
  maxDate={col.dateFilterOptions?.maxDate}
321
368
  size="sm"
322
- placeholder="dd/mm/aaaa - dd/mm/aaaa"
369
+ placeholder={t("datePicker.rangePlaceholder")}
323
370
  className="w-full"
324
371
  disabled={isLoading}
325
372
  />
@@ -330,7 +377,7 @@ export default function ITDataTable<T extends Record<string, unknown>>({
330
377
  <ITInput
331
378
  name={`filter-${col.key}`}
332
379
  className="w-full text-xs"
333
- placeholder="Buscar..."
380
+ placeholder={t("common.search")}
334
381
  value={String(filters[col.key] || "")}
335
382
  onChange={(e) => handleFilterChange(col.key, e.target.value)}
336
383
  onBlur={() => {}}
@@ -345,12 +392,12 @@ export default function ITDataTable<T extends Record<string, unknown>>({
345
392
 
346
393
  switch (col.type) {
347
394
  case "number":
348
- return typeof value === "number" && col.currencyMX ? formatCurrencyMX(value) : value;
395
+ return typeof value === "number" && col.currencyMX ? formatCurrencyMX(value, toIntlLocale(locale)) : value;
349
396
  case "boolean":
350
397
  return value ? (
351
- <FaCheck className="text-success-500" aria-label="Verdadero" title="Verdadero" />
398
+ <FaCheck className="text-success-500" aria-label={t("common.true")} title={t("common.true")} />
352
399
  ) : (
353
- <FaTimes className="text-danger-500" aria-label="Falso" title="Falso" />
400
+ <FaTimes className="text-danger-500" aria-label={t("common.false")} title={t("common.false")} />
354
401
  );
355
402
  case "actions":
356
403
  return col.actions ? col.actions(row) : null;
@@ -409,6 +456,29 @@ export default function ITDataTable<T extends Record<string, unknown>>({
409
456
  onRowClick(row, event);
410
457
  };
411
458
 
459
+ const containerSlot = mergeSlot(design?.container, containerClassName, containerStyle);
460
+ const cardSlot = mergeSlot(design?.card, cardClassName, cardStyle);
461
+ const toolbarSlot = mergeSlot(design?.toolbar, toolbarClassName, toolbarStyle);
462
+ const headerSlot = mergeSlot(design?.header, headerClassName, headerStyle);
463
+ const headerCellSlot = mergeSlot(design?.headerCell, headerCellClassName, headerCellStyle);
464
+ const rowSlot = mergeSlot(design?.row, rowClassName, rowStyle);
465
+ const cellSlot = mergeSlot(design?.cell, cellClassName, cellStyle);
466
+ const cardsSlot = mergeSlot(design?.cards, cardsClassName, cardsStyle);
467
+ const footerSlot = mergeSlot(design?.footer, footerClassName, footerStyle);
468
+
469
+ const viewToggle = (
470
+ <div className="flex items-center bg-slate-100 dark:bg-slate-800/80 rounded-lg p-0.5 border border-slate-200 dark:border-slate-700/50">
471
+ <button onClick={() => setViewMode("table")} disabled={forcedCards} className={segCtrlClass("table")}>
472
+ <FaTable size={11} />
473
+ {t("table.viewTable")}
474
+ </button>
475
+ <button onClick={() => setViewMode("cards")} className={segCtrlClass("cards")}>
476
+ <FaThLarge size={11} />
477
+ {t("table.viewCards")}
478
+ </button>
479
+ </div>
480
+ );
481
+
412
482
  const tableEl = (
413
483
  <table
414
484
  className={clsx(
@@ -439,7 +509,8 @@ export default function ITDataTable<T extends Record<string, unknown>>({
439
509
  )}
440
510
  <thead>
441
511
  <tr
442
- className={clsx(tableHeaderRow, "dark:text-slate-200")}
512
+ className={clsx(tableHeaderRow, "dark:text-slate-200", headerSlot.className)}
513
+ style={headerSlot.style}
443
514
  aria-rowindex={isTableVirtual ? 1 : undefined}
444
515
  >
445
516
  {columns.map((col) => {
@@ -455,23 +526,23 @@ export default function ITDataTable<T extends Record<string, unknown>>({
455
526
  isPinned && "sticky",
456
527
  isStickyHeader && "sticky top-0 bg-secondary-50",
457
528
  isPinned ? "z-[15]" : isStickyHeader && "z-10",
458
- isPinned && (col.pinned === "left" ? "it-table-pinned-left" : "it-table-pinned-right")
529
+ isPinned && (col.pinned === "left" ? "it-table-pinned-left" : "it-table-pinned-right"),
530
+ headerCellSlot.className,
531
+ col.headerClassName
459
532
  )}
460
- style={
461
- col.minWidth != null || isStickyHeader || isPinned
462
- ? {
463
- ...(col.minWidth != null ? { minWidth: `${col.minWidth}px` } : {}),
464
- ...(isStickyHeader || isPinned
465
- ? { backgroundColor: "var(--color-table-headerBg, #f8fafc)" }
466
- : {}),
467
- ...(isPinned
468
- ? pin.side === "left"
469
- ? { left: pin.offset }
470
- : { right: pin.offset }
471
- : {}),
472
- }
473
- : undefined
474
- }
533
+ style={{
534
+ ...(col.minWidth != null ? { minWidth: `${col.minWidth}px` } : {}),
535
+ ...(isStickyHeader || isPinned
536
+ ? { backgroundColor: "var(--color-table-headerBg, #f8fafc)" }
537
+ : {}),
538
+ ...(isPinned
539
+ ? pin.side === "left"
540
+ ? { left: pin.offset }
541
+ : { right: pin.offset }
542
+ : {}),
543
+ ...headerCellSlot.style,
544
+ ...col.headerStyle,
545
+ }}
475
546
  >
476
547
  <div className={isFixed ? "flex flex-col gap-3" : "flex flex-col gap-3 min-w-[150px]"}>
477
548
  <div className="flex items-center justify-between gap-2">
@@ -485,7 +556,7 @@ export default function ITDataTable<T extends Record<string, unknown>>({
485
556
  ? "bg-secondary-200 text-secondary-900"
486
557
  : "hover:bg-secondary-200 text-secondary-400 hover:text-secondary-700"
487
558
  } disabled:opacity-50`}
488
- title={`Ordenar por ${col.label}`}
559
+ title={t("table.sortBy", { label: col.label })}
489
560
  >
490
561
  <MdOutlineSwapVert className="w-4 h-4" aria-hidden="true" />
491
562
  </button>
@@ -516,8 +587,10 @@ export default function ITDataTable<T extends Record<string, unknown>>({
516
587
  className={clsx(
517
588
  tableRow,
518
589
  variant === "striped" && absoluteIndex % 2 === 0 && "bg-secondary-50/40 dark:bg-slate-800/20",
519
- onRowClick && !isLoading && tableRowClickable
590
+ onRowClick && !isLoading && tableRowClickable,
591
+ rowSlot.className
520
592
  )}
593
+ style={rowSlot.style}
521
594
  tabIndex={onRowClick && !isLoading ? 0 : undefined}
522
595
  onClick={onRowClick && !isLoading ? handleRowClick(row) : undefined}
523
596
  onKeyDown={onRowClick && !isLoading ? handleRowKeyDown(row) : undefined}
@@ -539,20 +612,20 @@ export default function ITDataTable<T extends Record<string, unknown>>({
539
612
  col.align && tableAlignClasses[col.align],
540
613
  isPinned && "sticky bg-[var(--color-table-rowBg,white)] group-hover:bg-[var(--color-table-rowHover,var(--color-secondary-50))]",
541
614
  isPinned && (col.pinned === "left" ? "it-table-pinned-left" : "it-table-pinned-right"),
542
- isPinned && "z-[1]"
615
+ isPinned && "z-[1]",
616
+ cellSlot.className,
617
+ col.cellClassName
543
618
  )}
544
- style={
545
- col.minWidth != null || isPinned
546
- ? {
547
- ...(col.minWidth != null ? { minWidth: `${col.minWidth}px` } : {}),
548
- ...(isPinned
549
- ? pin.side === "left"
550
- ? { left: pin.offset }
551
- : { right: pin.offset }
552
- : {}),
553
- }
554
- : undefined
555
- }
619
+ style={{
620
+ ...(col.minWidth != null ? { minWidth: `${col.minWidth}px` } : {}),
621
+ ...(isPinned
622
+ ? pin.side === "left"
623
+ ? { left: pin.offset }
624
+ : { right: pin.offset }
625
+ : {}),
626
+ ...cellSlot.style,
627
+ ...col.cellStyle,
628
+ }}
556
629
  title={truncateTitle}
557
630
  >
558
631
  {col.type === "actions" ? (
@@ -581,8 +654,8 @@ export default function ITDataTable<T extends Record<string, unknown>>({
581
654
  <td colSpan={columns.length} className="px-6 py-12 text-center">
582
655
  {!isLoading && (
583
656
  <div className={tableEmptyContent}>
584
- <ITText as="span" className="text-lg">No se encontraron resultados</ITText>
585
- <ITText as="span" className="text-sm mt-1">Intenta ajustar los filtros</ITText>
657
+ <ITText as="span" className="text-lg">{t("table.noResults")}</ITText>
658
+ <ITText as="span" className="text-sm mt-1">{t("table.adjustFilters")}</ITText>
586
659
  </div>
587
660
  )}
588
661
  </td>
@@ -593,10 +666,20 @@ export default function ITDataTable<T extends Record<string, unknown>>({
593
666
  );
594
667
 
595
668
  return (
596
- <div ref={rootRef} className={clsx("space-y-4 w-full relative", containerClassName)}>
597
- <div className={tableContainer} style={{ backgroundColor: 'var(--color-table-rowBg, #ffffff)' }}>
669
+ <div
670
+ ref={rootRef}
671
+ className={clsx("space-y-4 w-full relative", containerSlot.className)}
672
+ style={{ ...colorVars, ...containerSlot.style }}
673
+ >
674
+ <div
675
+ className={clsx(tableContainer, cardSlot.className)}
676
+ style={{ backgroundColor: 'var(--color-table-rowBg, #ffffff)', ...cardSlot.style }}
677
+ >
598
678
  {title && (
599
- <div className="px-6 py-5 flex items-center justify-between" style={{ backgroundColor: 'var(--color-table-rowBg, #ffffff)' }}>
679
+ <div
680
+ className={clsx("px-6 py-5 flex items-center justify-between", toolbarSlot.className)}
681
+ style={{ backgroundColor: 'var(--color-table-rowBg, #ffffff)', ...toolbarSlot.style }}
682
+ >
600
683
  <ITText as="h2" className="text-xl font-bold text-secondary-900 leading-tight">{title}</ITText>
601
684
  <div className="flex items-center gap-3">
602
685
  {isLoading && (
@@ -604,32 +687,14 @@ export default function ITDataTable<T extends Record<string, unknown>>({
604
687
  {loadingIndicator || <FaSpinner className="animate-spin text-primary-500 text-xl" />}
605
688
  </div>
606
689
  )}
607
- <div className="flex items-center bg-slate-100 dark:bg-slate-800/80 rounded-lg p-0.5 border border-slate-200 dark:border-slate-700/50">
608
- <button onClick={() => setViewMode("table")} disabled={forcedCards} className={segCtrlClass("table")}>
609
- <FaTable size={11} />
610
- Table
611
- </button>
612
- <button onClick={() => setViewMode("cards")} className={segCtrlClass("cards")}>
613
- <FaThLarge size={11} />
614
- Cards
615
- </button>
616
- </div>
690
+ {showViewToggle && viewToggle}
617
691
  </div>
618
692
  </div>
619
693
  )}
620
694
 
621
- {!title && (
622
- <div className="flex justify-end px-4 pt-3">
623
- <div className="flex items-center bg-slate-100 dark:bg-slate-800/80 rounded-lg p-0.5 border border-slate-200 dark:border-slate-700/50">
624
- <button onClick={() => setViewMode("table")} disabled={forcedCards} className={segCtrlClass("table")}>
625
- <FaTable size={11} />
626
- Table
627
- </button>
628
- <button onClick={() => setViewMode("cards")} className={segCtrlClass("cards")}>
629
- <FaThLarge size={11} />
630
- Cards
631
- </button>
632
- </div>
695
+ {!title && showViewToggle && (
696
+ <div className={clsx("flex justify-end px-4 pt-3", toolbarSlot.className)} style={toolbarSlot.style}>
697
+ {viewToggle}
633
698
  </div>
634
699
  )}
635
700
 
@@ -640,7 +705,7 @@ export default function ITDataTable<T extends Record<string, unknown>>({
640
705
  {loadingIndicator || (
641
706
  <>
642
707
  <FaSpinner className="animate-spin text-primary-500 text-4xl" />
643
- <ITText as="span" className="text-sm font-semibold text-secondary-600 animate-pulse">Cargando datos...</ITText>
708
+ <ITText as="span" className="text-sm font-semibold text-secondary-600 animate-pulse">{t("table.loading")}</ITText>
644
709
  </>
645
710
  )}
646
711
  </div>
@@ -648,7 +713,7 @@ export default function ITDataTable<T extends Record<string, unknown>>({
648
713
  )}
649
714
 
650
715
  {effectiveView === "cards" ? (
651
- <div className="p-4 space-y-3 max-h-[400px] overflow-y-auto">
716
+ <div className={clsx("p-4 space-y-3 max-h-[400px] overflow-y-auto", cardsSlot.className)} style={cardsSlot.style}>
652
717
  {data.length > 0 ? (
653
718
  data.map((row, i) => (
654
719
  <div
@@ -665,8 +730,8 @@ export default function ITDataTable<T extends Record<string, unknown>>({
665
730
  ) : (
666
731
  !isLoading && (
667
732
  <div className={clsx(tableEmptyContent, "py-12")}>
668
- <ITText as="span" className="text-lg">No se encontraron resultados</ITText>
669
- <ITText as="span" className="text-sm mt-1">Intenta ajustar los filtros</ITText>
733
+ <ITText as="span" className="text-lg">{t("table.noResults")}</ITText>
734
+ <ITText as="span" className="text-sm mt-1">{t("table.adjustFilters")}</ITText>
670
735
  </div>
671
736
  )
672
737
  )}
@@ -685,7 +750,10 @@ export default function ITDataTable<T extends Record<string, unknown>>({
685
750
  </div>
686
751
  </div>
687
752
 
688
- <div className="rounded-b-xl px-6 py-4" style={{ backgroundColor: 'var(--color-table-rowBg, #ffffff)' }}>
753
+ <div
754
+ className={clsx("rounded-b-xl px-6 py-4", footerSlot.className)}
755
+ style={{ backgroundColor: 'var(--color-table-rowBg, #ffffff)', ...footerSlot.style }}
756
+ >
689
757
  <ITPagination
690
758
  currentPage={currentPage}
691
759
  totalPages={computedTotalPages}
@@ -6,6 +6,7 @@ import { ITDialogProps } from "./dialog.props";
6
6
  import useClickOutside from "@/hooks/useClickOutside";
7
7
  import ITFormHeader from "@/components/molecules/form-header/form-header";
8
8
  import ITText from "@/components/atoms/text/text";
9
+ import { useITTranslation } from "@/i18n";
9
10
 
10
11
  /**
11
12
  * Modal dialog rendered via React portal with overlay backdrop.
@@ -42,6 +43,7 @@ export default function ITDialog({
42
43
  useFormHeader = false,
43
44
  fullScreen = false,
44
45
  }: ITDialogProps) {
46
+ const { t } = useITTranslation();
45
47
  const modalRef = useRef<HTMLDivElement>(null);
46
48
 
47
49
  useClickOutside(modalRef, onClose);
@@ -100,6 +102,7 @@ export default function ITDialog({
100
102
  <button
101
103
  className="absolute top-2 right-2 text-secondary-600 hover:text-secondary-900"
102
104
  onClick={onClose}
105
+ aria-label={t("common.close")}
103
106
  >
104
107
  <FaRegTimesCircle />
105
108
  </button>
@@ -4,6 +4,7 @@ import { FaTimes } from "react-icons/fa";
4
4
  import useClickOutside from "@/hooks/useClickOutside";
5
5
  import { useRef } from "react";
6
6
  import ITText from "@/components/atoms/text/text";
7
+ import { useITTranslation } from "@/i18n";
7
8
 
8
9
  /**
9
10
  * Sliding panel drawer from the left or right screen edge.
@@ -35,6 +36,7 @@ export default function ITDrawer({
35
36
  className,
36
37
  style,
37
38
  }: ITDrawerProps) {
39
+ const { t } = useITTranslation();
38
40
  const panelRef = useRef<HTMLDivElement>(null);
39
41
  useClickOutside(panelRef, onClose);
40
42
 
@@ -58,6 +60,7 @@ export default function ITDrawer({
58
60
  <ITText as="h2" className="text-lg font-bold text-slate-800 dark:text-white">{title}</ITText>
59
61
  <button
60
62
  onClick={onClose}
63
+ aria-label={t("common.close")}
61
64
  className="w-8 h-8 flex items-center justify-center rounded-lg hover:bg-slate-100 dark:hover:bg-slate-800 text-slate-400 hover:text-slate-600 transition-colors"
62
65
  >
63
66
  <FaTimes size={14} />