@axzydev/axzy_ui_system 1.4.8 → 1.5.1

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 (223) hide show
  1. package/README.md +2 -11
  2. package/dist/index.cjs +1826 -1351
  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 +115 -14
  7. package/dist/index.d.ts +115 -14
  8. package/dist/index.js +1481 -1010
  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.tsx +30 -28
  39. package/src/components/molecules/time-picker/timePicker.tsx +8 -6
  40. package/src/components/molecules/wysiwyg/wysiwyg.tsx +23 -12
  41. package/src/components/organisms/confirm-dialog/confirm-dialog.props.ts +4 -4
  42. package/src/components/organisms/confirm-dialog/confirm-dialog.tsx +16 -8
  43. package/src/components/organisms/data-table/dataTable.tsx +31 -25
  44. package/src/components/organisms/dialog/dialog.tsx +3 -0
  45. package/src/components/organisms/drawer/drawer.tsx +3 -0
  46. package/src/components/organisms/dropfile/dropfile.tsx +19 -17
  47. package/src/components/organisms/form-builder/fieldRenderer.tsx +4 -2
  48. package/src/components/organisms/navbar/navbar.tsx +4 -2
  49. package/src/components/organisms/page-header/page-header.tsx +3 -1
  50. package/src/components/organisms/searchTable/components/PaginationControls.tsx +8 -6
  51. package/src/components/organisms/searchTable/components/PaginationInfo.tsx +3 -1
  52. package/src/components/organisms/searchTable/components/SearchAndSortBar.tsx +7 -5
  53. package/src/components/organisms/searchTable/components/SearchInput.tsx +4 -2
  54. package/src/components/organisms/searchTable/components/SortButton.tsx +13 -11
  55. package/src/components/organisms/searchTable/components/TableEmptyState.tsx +4 -2
  56. package/src/components/organisms/searchTable/components/TableRow.tsx +6 -4
  57. package/src/components/organisms/searchTable/searchTable.tsx +4 -2
  58. package/src/components/organisms/sidebar/sidebar.props.ts +1 -1
  59. package/src/components/organisms/sidebar/sidebar.tsx +9 -4
  60. package/src/components/organisms/toast/toast.tsx +3 -1
  61. package/src/components/organisms/topbar/topbar.tsx +4 -2
  62. package/src/components/templates/page/page.props.ts +4 -4
  63. package/src/components/templates/page/page.tsx +6 -4
  64. package/src/components/theme-provider/themeProvider.tsx +28 -17
  65. package/src/dev.css +61 -2
  66. package/src/global.d.ts +10 -0
  67. package/src/i18n/context.ts +9 -0
  68. package/src/i18n/index.ts +22 -0
  69. package/src/i18n/locales/en.ts +163 -0
  70. package/src/i18n/locales/es.ts +165 -0
  71. package/src/i18n/provider.tsx +44 -0
  72. package/src/i18n/translator.ts +82 -0
  73. package/src/i18n/types.ts +54 -0
  74. package/src/i18n/useITTranslation.ts +20 -0
  75. package/src/index.css +0 -1
  76. package/src/index.ts +7 -1
  77. package/src/sandbox/LandingShowcase.tsx +224 -580
  78. package/src/sandbox/NotFoundShowcase.tsx +51 -36
  79. package/src/sandbox/TopbarSearch.tsx +6 -4
  80. package/src/sandbox/controls.tsx +180 -0
  81. package/src/sandbox/i18n.ts +1939 -0
  82. package/src/sandbox/icons.tsx +25 -0
  83. package/src/sandbox/locale.tsx +72 -0
  84. package/src/sandbox/ui.tsx +474 -0
  85. package/src/sandbox/useHashRoute.ts +46 -10
  86. package/src/showcases/DataShowcases.tsx +103 -87
  87. package/src/showcases/FeedbackShowcases.tsx +37 -30
  88. package/src/showcases/FormShowcases.tsx +303 -215
  89. package/src/showcases/GettingStartedShowcase.tsx +151 -145
  90. package/src/showcases/HelpShowcase.tsx +126 -128
  91. package/src/showcases/HomeShowcase.tsx +678 -482
  92. package/src/showcases/LayoutPrimitivesShowcases.tsx +129 -114
  93. package/src/showcases/NavigationShowcases.tsx +45 -37
  94. package/src/showcases/PageShowcases.tsx +171 -152
  95. package/src/showcases/ProductoDetalle.tsx +272 -129
  96. package/src/showcases/ShowcaseLayout.tsx +256 -219
  97. package/src/showcases/SizesShowcase.tsx +123 -64
  98. package/src/showcases/StructureShowcases.tsx +203 -138
  99. package/src/showcases/portfolioUi.tsx +153 -0
  100. package/src/showcases/techIcons.ts +3 -0
  101. package/src/utils/table.utils.ts +10 -2
  102. package/src/components/atoms/avatar/avatar.doc.mdx +0 -48
  103. package/src/components/atoms/avatar/avatar.stories.tsx +0 -64
  104. package/src/components/atoms/badget/badget.doc.mdx +0 -46
  105. package/src/components/atoms/badget/badget.stories.tsx +0 -75
  106. package/src/components/atoms/button/button.doc.mdx +0 -59
  107. package/src/components/atoms/button/button.stories.tsx +0 -173
  108. package/src/components/atoms/checkbox/checkbox.doc.mdx +0 -54
  109. package/src/components/atoms/checkbox/checkbox.stories.tsx +0 -53
  110. package/src/components/atoms/chip/chip.doc.mdx +0 -47
  111. package/src/components/atoms/chip/chip.stories.tsx +0 -64
  112. package/src/components/atoms/divider/divider.doc.mdx +0 -42
  113. package/src/components/atoms/divider/divider.stories.tsx +0 -33
  114. package/src/components/atoms/flex/flex.doc.mdx +0 -59
  115. package/src/components/atoms/flex/flex.stories.tsx +0 -70
  116. package/src/components/atoms/grid/grid.doc.mdx +0 -54
  117. package/src/components/atoms/grid/grid.stories.tsx +0 -71
  118. package/src/components/atoms/image/image.doc.mdx +0 -44
  119. package/src/components/atoms/image/image.stories.tsx +0 -48
  120. package/src/components/atoms/input/input.doc.mdx +0 -70
  121. package/src/components/atoms/input/input.stories.tsx +0 -113
  122. package/src/components/atoms/input-number/input-number.doc.mdx +0 -74
  123. package/src/components/atoms/input-number/input-number.stories.tsx +0 -111
  124. package/src/components/atoms/loader/loader.doc.mdx +0 -43
  125. package/src/components/atoms/loader/loader.stories.tsx +0 -104
  126. package/src/components/atoms/popover/popover.doc.mdx +0 -53
  127. package/src/components/atoms/popover/popover.stories.tsx +0 -24
  128. package/src/components/atoms/progress/progress.doc.mdx +0 -48
  129. package/src/components/atoms/progress/progress.stories.tsx +0 -39
  130. package/src/components/atoms/radio/radio.doc.mdx +0 -62
  131. package/src/components/atoms/radio/radio.stories.tsx +0 -48
  132. package/src/components/atoms/segmented-control/segmented-control.doc.mdx +0 -60
  133. package/src/components/atoms/segmented-control/segmented-control.stories.tsx +0 -62
  134. package/src/components/atoms/skeleton/skeleton.doc.mdx +0 -43
  135. package/src/components/atoms/skeleton/skeleton.stories.tsx +0 -29
  136. package/src/components/atoms/slide/slide.doc.mdx +0 -46
  137. package/src/components/atoms/slide/slide.stories.tsx +0 -120
  138. package/src/components/atoms/slider/slider.doc.mdx +0 -49
  139. package/src/components/atoms/slider/slider.stories.tsx +0 -29
  140. package/src/components/atoms/stack/stack.doc.mdx +0 -126
  141. package/src/components/atoms/stack/stack.stories.tsx +0 -283
  142. package/src/components/atoms/text/text.doc.mdx +0 -41
  143. package/src/components/atoms/text/text.stories.tsx +0 -66
  144. package/src/components/atoms/textarea/textarea.doc.mdx +0 -64
  145. package/src/components/atoms/textarea/textarea.stories.tsx +0 -26
  146. package/src/components/atoms/tooltip/tooltip.doc.mdx +0 -47
  147. package/src/components/atoms/tooltip/tooltip.stories.tsx +0 -19
  148. package/src/components/isolation/isolation.stories.tsx +0 -202
  149. package/src/components/molecules/accordion/accordion.doc.mdx +0 -47
  150. package/src/components/molecules/accordion/accordion.stories.tsx +0 -68
  151. package/src/components/molecules/alert/alert.doc.mdx +0 -48
  152. package/src/components/molecules/alert/alert.stories.tsx +0 -40
  153. package/src/components/molecules/breadcrumbs/breadcrumbs.doc.mdx +0 -57
  154. package/src/components/molecules/breadcrumbs/breadcrumbs.stories.tsx +0 -20
  155. package/src/components/molecules/calendar/calendar.doc.mdx +0 -76
  156. package/src/components/molecules/calendar/calendar.stories.tsx +0 -90
  157. package/src/components/molecules/card/card.doc.mdx +0 -54
  158. package/src/components/molecules/card/card.stories.tsx +0 -57
  159. package/src/components/molecules/chip-input/chip-input.doc.mdx +0 -44
  160. package/src/components/molecules/chip-input/chip-input.stories.tsx +0 -52
  161. package/src/components/molecules/date-picker/date-picker.doc.mdx +0 -65
  162. package/src/components/molecules/date-picker/date-picker.stories.tsx +0 -88
  163. package/src/components/molecules/dropdown-menu/dropdown-menu.doc.mdx +0 -46
  164. package/src/components/molecules/dropdown-menu/dropdown-menu.stories.tsx +0 -41
  165. package/src/components/molecules/empty-state/empty-state.doc.mdx +0 -50
  166. package/src/components/molecules/empty-state/empty-state.stories.tsx +0 -19
  167. package/src/components/molecules/field/field.doc.mdx +0 -43
  168. package/src/components/molecules/field/field.stories.tsx +0 -42
  169. package/src/components/molecules/form-header/form-header.doc.mdx +0 -38
  170. package/src/components/molecules/form-header/form-header.stories.tsx +0 -52
  171. package/src/components/molecules/masked-input/masked-input.doc.mdx +0 -78
  172. package/src/components/molecules/masked-input/masked-input.stories.tsx +0 -126
  173. package/src/components/molecules/multi-select/multi-select.doc.mdx +0 -55
  174. package/src/components/molecules/multi-select/multi-select.stories.tsx +0 -59
  175. package/src/components/molecules/pagination/pagination.doc.mdx +0 -62
  176. package/src/components/molecules/pagination/pagination.stories.tsx +0 -110
  177. package/src/components/molecules/search-select/search-select.doc.mdx +0 -77
  178. package/src/components/molecules/search-select/search-select.stories.tsx +0 -146
  179. package/src/components/molecules/select/select.doc.mdx +0 -75
  180. package/src/components/molecules/select/select.stories.tsx +0 -85
  181. package/src/components/molecules/stat-card/stat-card.doc.mdx +0 -48
  182. package/src/components/molecules/stat-card/stat-card.stories.tsx +0 -40
  183. package/src/components/molecules/stepper/stepper.doc.mdx +0 -54
  184. package/src/components/molecules/stepper/stepper.stories.tsx +0 -154
  185. package/src/components/molecules/table/table.doc.mdx +0 -140
  186. package/src/components/molecules/table/table.stories.tsx +0 -402
  187. package/src/components/molecules/tabs/tabs.doc.mdx +0 -52
  188. package/src/components/molecules/tabs/tabs.stories.tsx +0 -31
  189. package/src/components/molecules/time-picker/timePicker.doc.mdx +0 -68
  190. package/src/components/molecules/time-picker/timePicker.stories.tsx +0 -130
  191. package/src/components/molecules/wysiwyg/wysiwyg.stories.tsx +0 -95
  192. package/src/components/organisms/confirm-dialog/confirm-dialog.doc.mdx +0 -60
  193. package/src/components/organisms/confirm-dialog/confirm-dialog.stories.tsx +0 -32
  194. package/src/components/organisms/data-table/ITDataTable.doc.mdx +0 -132
  195. package/src/components/organisms/data-table/ITDataTable.stories.tsx +0 -353
  196. package/src/components/organisms/dialog/dialog.doc.mdx +0 -54
  197. package/src/components/organisms/dialog/dialog.stories.tsx +0 -126
  198. package/src/components/organisms/drawer/drawer.doc.mdx +0 -59
  199. package/src/components/organisms/drawer/drawer.stories.tsx +0 -40
  200. package/src/components/organisms/dropfile/dropfile.doc.mdx +0 -74
  201. package/src/components/organisms/dropfile/dropfile.stories.tsx +0 -93
  202. package/src/components/organisms/form-builder/formBuilder.doc.mdx +0 -251
  203. package/src/components/organisms/form-builder/formBuilder.stories.tsx +0 -914
  204. package/src/components/organisms/navbar/navbar.doc.mdx +0 -77
  205. package/src/components/organisms/navbar/navbar.stories.tsx +0 -83
  206. package/src/components/organisms/page-header/page-header.doc.mdx +0 -54
  207. package/src/components/organisms/page-header/page-header.stories.tsx +0 -74
  208. package/src/components/organisms/searchTable/searchTable.doc.mdx +0 -79
  209. package/src/components/organisms/searchTable/searchTable.stories.tsx +0 -73
  210. package/src/components/organisms/sidebar/sidebar.doc.mdx +0 -176
  211. package/src/components/organisms/sidebar/sidebar.stories.tsx +0 -234
  212. package/src/components/organisms/toast/toast.doc.mdx +0 -50
  213. package/src/components/organisms/toast/toast.stories.tsx +0 -137
  214. package/src/components/organisms/topbar/topbar.doc.mdx +0 -72
  215. package/src/components/organisms/topbar/topbar.stories.tsx +0 -79
  216. package/src/components/organisms/triple-filter/tripleFilter.doc.mdx +0 -62
  217. package/src/components/organisms/triple-filter/tripleFilter.stories.tsx +0 -31
  218. package/src/components/templates/layout/layout.doc.mdx +0 -53
  219. package/src/components/templates/layout/layout.stories.tsx +0 -113
  220. package/src/components/templates/page/page.doc.mdx +0 -86
  221. package/src/components/templates/page/page.stories.tsx +0 -97
  222. package/src/components/theme-provider/themeProvider.doc.mdx +0 -85
  223. package/src/components/theme-provider/themeProvider.stories.tsx +0 -58
@@ -35,6 +35,7 @@ import {
35
35
  tableRowClickable,
36
36
  } from "@/utils/styles";
37
37
  import { formatCurrencyMX, getNestedValue, getPinnedColumnMeta, isInteractiveTarget } from "@/utils/table.utils";
38
+ import { useITTranslation, toIntlLocale } from "@/i18n";
38
39
 
39
40
  /**
40
41
  * A feature-rich data table with per-column filtering, sortable columns,
@@ -95,6 +96,7 @@ export default function ITTable<T extends Record<string, unknown>>({
95
96
  footerClassName,
96
97
  footerStyle,
97
98
  }: ITTableProps<T>) {
99
+ const { t, locale } = useITTranslation();
98
100
  const [viewMode, setViewMode] = useState<"table" | "cards">(defaultView);
99
101
  const { ref: rootRef, width: containerWidth } = useElementSize<HTMLDivElement>();
100
102
 
@@ -282,17 +284,17 @@ export default function ITTable<T extends Record<string, unknown>>({
282
284
  : undefined;
283
285
 
284
286
  const getToggleLabel = () => {
285
- if (currentValue === undefined) return "Mostrar todos";
286
- if (currentValue === true) return "Filtrar solo verdaderos";
287
- return "Filtrar solo falsos";
287
+ if (currentValue === undefined) return t("table.showAll");
288
+ if (currentValue === true) return t("table.filterTrue");
289
+ return t("table.filterFalse");
288
290
  };
289
291
 
290
292
  return (
291
293
  <button
292
294
  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"
293
295
  onClick={() => handleFilterChange(col.key, nextValue)}
294
- aria-label={`${getToggleLabel()} para ${col.label}`}
295
- title={`${getToggleLabel()} para ${col.label}`}
296
+ aria-label={t("table.filterToggle", { action: getToggleLabel(), label: col.label })}
297
+ title={t("table.filterToggle", { action: getToggleLabel(), label: col.label })}
296
298
  >
297
299
  <div className="relative w-10 h-5 bg-secondary-300 rounded-full">
298
300
  <div
@@ -315,21 +317,21 @@ export default function ITTable<T extends Record<string, unknown>>({
315
317
  return (
316
318
  <FaSpinner
317
319
  className="animate-spin"
318
- aria-label="Cargando opciones"
319
- title="Cargando opciones"
320
+ aria-label={t("common.loadingOptions")}
321
+ title={t("common.loadingOptions")}
320
322
  />
321
323
  );
322
324
  }
323
325
 
324
326
  if (col.catalogOptions.error) {
325
- return <ITText as="span" className="text-danger-500 text-xs">Error cargando</ITText>;
327
+ return <ITText as="span" className="text-danger-500 text-xs">{t("common.loadError")}</ITText>;
326
328
  }
327
329
 
328
330
  return (
329
331
  <ITSelect
330
332
  name={`filter-${col.key}`}
331
333
  options={[
332
- { value: "", label: "Todos" },
334
+ { value: "", label: t("common.all") },
333
335
  ...col.catalogOptions.data.map((item) => ({
334
336
  value: String(item.id),
335
337
  label: item.name,
@@ -351,14 +353,14 @@ export default function ITTable<T extends Record<string, unknown>>({
351
353
  return (
352
354
  <FaSpinner
353
355
  className="animate-spin"
354
- aria-label="Cargando opciones"
355
- title="Cargando opciones"
356
+ aria-label={t("common.loadingOptions")}
357
+ title={t("common.loadingOptions")}
356
358
  />
357
359
  );
358
360
  }
359
361
 
360
362
  if (col.catalogOptions.error) {
361
- return <ITText as="span" className="text-danger-500 text-xs">Error cargando</ITText>;
363
+ return <ITText as="span" className="text-danger-500 text-xs">{t("common.loadError")}</ITText>;
362
364
  }
363
365
 
364
366
  const searchValue = filters[col.key];
@@ -378,7 +380,7 @@ export default function ITTable<T extends Record<string, unknown>>({
378
380
  onSearch={col.catalogOptions.onSearch}
379
381
  isLoading={col.catalogOptions.loading}
380
382
  size="sm"
381
- placeholder="Buscar..."
383
+ placeholder={t("common.search")}
382
384
  clearable
383
385
  className="w-full"
384
386
  onBlur={() => { }}
@@ -396,7 +398,7 @@ export default function ITTable<T extends Record<string, unknown>>({
396
398
  minDate={col.dateFilterOptions?.minDate}
397
399
  maxDate={col.dateFilterOptions?.maxDate}
398
400
  size="sm"
399
- placeholder="dd/mm/aaaa"
401
+ placeholder={t("datePicker.placeholder")}
400
402
  className="w-full"
401
403
  />
402
404
  );
@@ -415,7 +417,7 @@ export default function ITTable<T extends Record<string, unknown>>({
415
417
  minDate={col.dateFilterOptions?.minDate}
416
418
  maxDate={col.dateFilterOptions?.maxDate}
417
419
  size="sm"
418
- placeholder="dd/mm/aaaa - dd/mm/aaaa"
420
+ placeholder={t("datePicker.rangePlaceholder")}
419
421
  className="w-full"
420
422
  />
421
423
  );
@@ -425,7 +427,7 @@ export default function ITTable<T extends Record<string, unknown>>({
425
427
  <ITInput
426
428
  name={`filter-${col.key}`}
427
429
  className="w-full text-xs"
428
- placeholder="Buscar..."
430
+ placeholder={t("common.search")}
429
431
  value={String(filters[col.key] || "")}
430
432
  onChange={(e) => handleFilterChange(col.key, e.target.value)}
431
433
  onBlur={() => { }}
@@ -442,19 +444,19 @@ export default function ITTable<T extends Record<string, unknown>>({
442
444
 
443
445
  switch (col.type) {
444
446
  case "number":
445
- return (typeof value === "number") && col.currencyMX ? formatCurrencyMX(value) : value;
447
+ return (typeof value === "number") && col.currencyMX ? formatCurrencyMX(value, toIntlLocale(locale)) : value;
446
448
  case "boolean":
447
449
  return value ? (
448
450
  <FaCheck
449
451
  className="text-success-500"
450
- aria-label="Verdadero"
451
- title="Verdadero"
452
+ aria-label={t("common.true")}
453
+ title={t("common.true")}
452
454
  />
453
455
  ) : (
454
456
  <FaTimes
455
457
  className="text-danger-500"
456
- aria-label="Falso"
457
- title="Falso"
458
+ aria-label={t("common.false")}
459
+ title={t("common.false")}
458
460
  />
459
461
  );
460
462
  case "actions":
@@ -531,7 +533,7 @@ export default function ITTable<T extends Record<string, unknown>>({
531
533
  }`}
532
534
  >
533
535
  <FaTable size={11} />
534
- Table
536
+ {t("table.viewTable")}
535
537
  </button>
536
538
  <button
537
539
  onClick={() => setViewMode("cards")}
@@ -542,7 +544,7 @@ export default function ITTable<T extends Record<string, unknown>>({
542
544
  }`}
543
545
  >
544
546
  <FaThLarge size={11} />
545
- Cards
547
+ {t("table.viewCards")}
546
548
  </button>
547
549
  </div>
548
550
  );
@@ -591,8 +593,8 @@ export default function ITTable<T extends Record<string, unknown>>({
591
593
  ))
592
594
  ) : (
593
595
  <div className={clsx(tableEmptyContent, "py-12")}>
594
- <ITText as="span" className="text-lg">No se encontraron resultados</ITText>
595
- <ITText as="span" className="text-sm mt-1">Intenta ajustar los filtros</ITText>
596
+ <ITText as="span" className="text-lg">{t("table.noResults")}</ITText>
597
+ <ITText as="span" className="text-sm mt-1">{t("table.adjustFilters")}</ITText>
596
598
  </div>
597
599
  )}
598
600
  </div>
@@ -674,7 +676,7 @@ export default function ITTable<T extends Record<string, unknown>>({
674
676
  ? "bg-secondary-200 text-secondary-900"
675
677
  : "hover:bg-secondary-200 text-secondary-400 hover:text-secondary-700"
676
678
  }`}
677
- title={`Ordenar por ${col.label}`}
679
+ title={t("table.sortBy", { label: col.label })}
678
680
  >
679
681
  <MdOutlineSwapVert className="w-4 h-4" aria-hidden="true" />
680
682
  </button>
@@ -772,8 +774,8 @@ export default function ITTable<T extends Record<string, unknown>>({
772
774
  <tr>
773
775
  <td colSpan={columns.length} className="px-6 py-12 text-center">
774
776
  <div className={tableEmptyContent}>
775
- <ITText as="span" className="text-lg">No se encontraron resultados</ITText>
776
- <ITText as="span" className="text-sm mt-1">Intenta ajustar los filtros</ITText>
777
+ <ITText as="span" className="text-lg">{t("table.noResults")}</ITText>
778
+ <ITText as="span" className="text-sm mt-1">{t("table.adjustFilters")}</ITText>
777
779
  </div>
778
780
  </td>
779
781
  </tr>
@@ -9,6 +9,7 @@ import { useFloatingPanel } from "@/hooks/useFloatingPanel";
9
9
  import { theme } from "@/theme/theme";
10
10
  import { ITTimePickerProps } from "./timePicker.props";
11
11
  import ITText from "@/components/atoms/text/text";
12
+ import { useITTranslation } from "@/i18n";
12
13
 
13
14
  /**
14
15
  * Time selection input with a dual-column dropdown (hours / minutes).
@@ -35,7 +36,7 @@ export default function ITTimePicker({
35
36
  name,
36
37
  value,
37
38
  label,
38
- placeholder = "HH:MM",
39
+ placeholder,
39
40
  onChange,
40
41
  onBlur,
41
42
  required,
@@ -47,6 +48,7 @@ export default function ITTimePicker({
47
48
  variant = "primary",
48
49
  color = "primary",
49
50
  }: ITTimePickerProps) {
51
+ const { t } = useITTranslation();
50
52
  const [isOpen, setIsOpen] = useState(false);
51
53
  const [inputValue, setInputValue] = useState(value || "");
52
54
  const [isValidTime, setIsValidTime] = useState(true);
@@ -185,7 +187,7 @@ export default function ITTimePicker({
185
187
  <ITInput
186
188
  name={name}
187
189
  label={label}
188
- placeholder={placeholder}
190
+ placeholder={placeholder ?? t("timePicker.placeholder")}
189
191
  type="text"
190
192
  value={inputValue}
191
193
  onChange={handleInputChange}
@@ -196,7 +198,7 @@ export default function ITTimePicker({
196
198
  variant={variant}
197
199
  size={size}
198
200
  touched={touched}
199
- error={!isValidTime ? "Hora inválida" : typeof error === 'string' ? error : undefined}
201
+ error={!isValidTime ? t("timePicker.invalid") : typeof error === 'string' ? error : undefined}
200
202
  iconRight={
201
203
  <FaClock
202
204
  onClick={() => {
@@ -223,9 +225,9 @@ export default function ITTimePicker({
223
225
  >
224
226
  <div className="flex bg-secondary-50 border-b border-secondary-100 text-xs font-semibold text-secondary-500 uppercase tracking-wider">
225
227
  <ITText as="div" className="flex-1 text-center py-2 border-r border-secondary-100">
226
- Horas
228
+ {t("timePicker.hours")}
227
229
  </ITText>
228
- <ITText as="div" className="flex-1 text-center py-2">Minutos</ITText>
230
+ <ITText as="div" className="flex-1 text-center py-2">{t("timePicker.minutes")}</ITText>
229
231
  </div>
230
232
 
231
233
  <div className="flex h-56 relative bg-white">
@@ -316,7 +318,7 @@ export default function ITTimePicker({
316
318
  size="sm"
317
319
  onClick={handleConfirm}
318
320
  >
319
- <ITText as="span">Aceptar</ITText>
321
+ <ITText as="span">{t("timePicker.accept")}</ITText>
320
322
  </ITButton>
321
323
  </div>
322
324
  </div>,
@@ -20,20 +20,30 @@ import ITTooltip from "@/components/atoms/tooltip/tooltip";
20
20
  import ITText from "@/components/atoms/text/text";
21
21
  import { inputError, inputLabel, inputWrapper } from "@/utils/styles";
22
22
  import { inputSizeTokens } from "@/theme/theme";
23
+ import { useITTranslation } from "@/i18n";
23
24
 
24
25
  const INLINE_TAGS = new Set(["STRONG", "B", "EM", "I", "U", "MARK"]);
25
26
 
26
- const ACTION_META: Record<
27
- ToolbarAction,
28
- { label: string; icon: ReactNode }
29
- > = {
30
- bold: { label: "Negrita", icon: <FaBold /> },
31
- italic: { label: "Itálica", icon: <FaItalic /> },
32
- underline: { label: "Subrayado", icon: <FaUnderline /> },
33
- highlight: { label: "Marcador", icon: <FaHighlighter /> },
34
- ul: { label: "Lista con viñetas", icon: <FaListUl /> },
35
- ol: { label: "Lista numerada", icon: <FaListOl /> },
36
- clear: { label: "Limpiar formato", icon: <FaEraser /> },
27
+ /** Catálogo de key por acción de la barra de herramientas. */
28
+ const ACTION_LABEL_KEYS: Record<ToolbarAction, string> = {
29
+ bold: "wysiwyg.bold",
30
+ italic: "wysiwyg.italic",
31
+ underline: "wysiwyg.underline",
32
+ highlight: "wysiwyg.highlight",
33
+ ul: "wysiwyg.bulletList",
34
+ ol: "wysiwyg.numberedList",
35
+ clear: "wysiwyg.clearFormat",
36
+ };
37
+
38
+ /** Icono por acción de la barra de herramientas. */
39
+ const ACTION_ICONS: Record<ToolbarAction, ReactNode> = {
40
+ bold: <FaBold />,
41
+ italic: <FaItalic />,
42
+ underline: <FaUnderline />,
43
+ highlight: <FaHighlighter />,
44
+ ul: <FaListUl />,
45
+ ol: <FaListOl />,
46
+ clear: <FaEraser />,
37
47
  };
38
48
 
39
49
  type ActiveState = Partial<Record<ToolbarAction, boolean>>;
@@ -73,6 +83,7 @@ export default function ITWysiwyg({
73
83
  toolbar = toolbarActions,
74
84
  className,
75
85
  }: ITWysiwygProps) {
86
+ const { t } = useITTranslation();
76
87
  const editorRef = useRef<HTMLDivElement>(null);
77
88
  const focusedRef = useRef(false);
78
89
  const [active, setActive] = useState<ActiveState>({});
@@ -516,7 +527,7 @@ export default function ITWysiwyg({
516
527
  }: {
517
528
  action: ToolbarAction;
518
529
  }) => {
519
- const meta = ACTION_META[action];
530
+ const meta = { label: t(ACTION_LABEL_KEYS[action]), icon: ACTION_ICONS[action] };
520
531
  const isActive = !!active[action];
521
532
  return (
522
533
  <ITTooltip content={meta.label}>
@@ -8,13 +8,13 @@ export interface ITConfirmDialogProps {
8
8
  onClose: () => void;
9
9
  /** Callback fired when the user confirms the destructive action. */
10
10
  onConfirm: () => void;
11
- /** Heading text displayed at the top of the dialog. @default "Confirmar acción" */
11
+ /** Heading text displayed at the top of the dialog. @default i18n `confirmDialog.title` ("Confirmar acción") */
12
12
  title?: string;
13
- /** Body content — accepts plain strings or React nodes. @default "¿Estás seguro de que deseas continuar?" */
13
+ /** Body content — accepts plain strings or React nodes. @default i18n `confirmDialog.message` ("¿Estás seguro de que deseas continuar?") */
14
14
  message?: ReactNode;
15
- /** Label for the confirm button. @default "Confirmar" */
15
+ /** Label for the confirm button. @default i18n `common.confirm` ("Confirmar") */
16
16
  confirmLabel?: string;
17
- /** Label for the cancel button. @default "Cancelar" */
17
+ /** Label for the cancel button. @default i18n `common.cancel` ("Cancelar") */
18
18
  cancelLabel?: string;
19
19
  /** Color variant applied to the confirm button. Accepts any ColorsTypes value (e.g. "primary", "danger", "warning", "info"). @default "primary" */
20
20
  variant?: ColorsTypes;
@@ -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>
@@ -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 {
@@ -106,6 +107,7 @@ export default function ITDataTable<T extends Record<string, unknown>>({
106
107
  footerClassName,
107
108
  footerStyle,
108
109
  }: ITDataTableProps<T>) {
110
+ const { t, locale } = useITTranslation();
109
111
  const [viewMode, setViewMode] = useState<"table" | "cards">(defaultView || "table");
110
112
  const { ref: rootRef, width: containerWidth } = useElementSize<HTMLDivElement>();
111
113
  const [data, setData] = useState<T[]>([]);
@@ -239,17 +241,21 @@ export default function ITDataTable<T extends Record<string, unknown>>({
239
241
  currentValue === undefined ? true : currentValue === true ? false : undefined;
240
242
 
241
243
  const getToggleLabel = () => {
242
- if (currentValue === undefined) return "Mostrar todos";
243
- if (currentValue === true) return "Filtrar solo verdaderos";
244
- 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");
245
247
  };
248
+ const toggleLabel = t("table.filterToggle", {
249
+ action: getToggleLabel(),
250
+ label: col.label,
251
+ });
246
252
 
247
253
  return (
248
254
  <button
249
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"
250
256
  onClick={() => handleFilterChange(col.key, nextValue)}
251
- aria-label={`${getToggleLabel()} para ${col.label}`}
252
- title={`${getToggleLabel()} para ${col.label}`}
257
+ aria-label={toggleLabel}
258
+ title={toggleLabel}
253
259
  disabled={isLoading}
254
260
  >
255
261
  <div className="relative w-10 h-5 bg-secondary-300 rounded-full">
@@ -270,16 +276,16 @@ export default function ITDataTable<T extends Record<string, unknown>>({
270
276
 
271
277
  if (col.filter === "catalog" && col.catalogOptions) {
272
278
  if (col.catalogOptions.loading) {
273
- 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")} />;
274
280
  }
275
281
  if (col.catalogOptions.error) {
276
- 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>;
277
283
  }
278
284
  return (
279
285
  <ITSelect
280
286
  name={`filter-${col.key}`}
281
287
  options={[
282
- { value: "", label: "Todos" },
288
+ { value: "", label: t("common.all") },
283
289
  ...col.catalogOptions.data.map((item) => ({
284
290
  value: String(item.id),
285
291
  label: item.name,
@@ -299,10 +305,10 @@ export default function ITDataTable<T extends Record<string, unknown>>({
299
305
 
300
306
  if (col.filter === "search" && col.catalogOptions) {
301
307
  if (col.catalogOptions.loading) {
302
- 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")} />;
303
309
  }
304
310
  if (col.catalogOptions.error) {
305
- 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>;
306
312
  }
307
313
  const searchValue = filters[col.key];
308
314
  return (
@@ -321,7 +327,7 @@ export default function ITDataTable<T extends Record<string, unknown>>({
321
327
  onSearch={col.catalogOptions.onSearch}
322
328
  isLoading={col.catalogOptions.loading}
323
329
  size="sm"
324
- placeholder="Buscar..."
330
+ placeholder={t("common.search")}
325
331
  clearable
326
332
  className="w-full"
327
333
  onBlur={() => {}}
@@ -340,7 +346,7 @@ export default function ITDataTable<T extends Record<string, unknown>>({
340
346
  minDate={col.dateFilterOptions?.minDate}
341
347
  maxDate={col.dateFilterOptions?.maxDate}
342
348
  size="sm"
343
- placeholder="dd/mm/aaaa"
349
+ placeholder={t("datePicker.placeholder")}
344
350
  className="w-full"
345
351
  disabled={isLoading}
346
352
  />
@@ -360,7 +366,7 @@ export default function ITDataTable<T extends Record<string, unknown>>({
360
366
  minDate={col.dateFilterOptions?.minDate}
361
367
  maxDate={col.dateFilterOptions?.maxDate}
362
368
  size="sm"
363
- placeholder="dd/mm/aaaa - dd/mm/aaaa"
369
+ placeholder={t("datePicker.rangePlaceholder")}
364
370
  className="w-full"
365
371
  disabled={isLoading}
366
372
  />
@@ -371,7 +377,7 @@ export default function ITDataTable<T extends Record<string, unknown>>({
371
377
  <ITInput
372
378
  name={`filter-${col.key}`}
373
379
  className="w-full text-xs"
374
- placeholder="Buscar..."
380
+ placeholder={t("common.search")}
375
381
  value={String(filters[col.key] || "")}
376
382
  onChange={(e) => handleFilterChange(col.key, e.target.value)}
377
383
  onBlur={() => {}}
@@ -386,12 +392,12 @@ export default function ITDataTable<T extends Record<string, unknown>>({
386
392
 
387
393
  switch (col.type) {
388
394
  case "number":
389
- return typeof value === "number" && col.currencyMX ? formatCurrencyMX(value) : value;
395
+ return typeof value === "number" && col.currencyMX ? formatCurrencyMX(value, toIntlLocale(locale)) : value;
390
396
  case "boolean":
391
397
  return value ? (
392
- <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")} />
393
399
  ) : (
394
- <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")} />
395
401
  );
396
402
  case "actions":
397
403
  return col.actions ? col.actions(row) : null;
@@ -464,11 +470,11 @@ export default function ITDataTable<T extends Record<string, unknown>>({
464
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">
465
471
  <button onClick={() => setViewMode("table")} disabled={forcedCards} className={segCtrlClass("table")}>
466
472
  <FaTable size={11} />
467
- Table
473
+ {t("table.viewTable")}
468
474
  </button>
469
475
  <button onClick={() => setViewMode("cards")} className={segCtrlClass("cards")}>
470
476
  <FaThLarge size={11} />
471
- Cards
477
+ {t("table.viewCards")}
472
478
  </button>
473
479
  </div>
474
480
  );
@@ -550,7 +556,7 @@ export default function ITDataTable<T extends Record<string, unknown>>({
550
556
  ? "bg-secondary-200 text-secondary-900"
551
557
  : "hover:bg-secondary-200 text-secondary-400 hover:text-secondary-700"
552
558
  } disabled:opacity-50`}
553
- title={`Ordenar por ${col.label}`}
559
+ title={t("table.sortBy", { label: col.label })}
554
560
  >
555
561
  <MdOutlineSwapVert className="w-4 h-4" aria-hidden="true" />
556
562
  </button>
@@ -648,8 +654,8 @@ export default function ITDataTable<T extends Record<string, unknown>>({
648
654
  <td colSpan={columns.length} className="px-6 py-12 text-center">
649
655
  {!isLoading && (
650
656
  <div className={tableEmptyContent}>
651
- <ITText as="span" className="text-lg">No se encontraron resultados</ITText>
652
- <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>
653
659
  </div>
654
660
  )}
655
661
  </td>
@@ -699,7 +705,7 @@ export default function ITDataTable<T extends Record<string, unknown>>({
699
705
  {loadingIndicator || (
700
706
  <>
701
707
  <FaSpinner className="animate-spin text-primary-500 text-4xl" />
702
- <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>
703
709
  </>
704
710
  )}
705
711
  </div>
@@ -724,8 +730,8 @@ export default function ITDataTable<T extends Record<string, unknown>>({
724
730
  ) : (
725
731
  !isLoading && (
726
732
  <div className={clsx(tableEmptyContent, "py-12")}>
727
- <ITText as="span" className="text-lg">No se encontraron resultados</ITText>
728
- <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>
729
735
  </div>
730
736
  )
731
737
  )}
@@ -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} />