@axzydev/axzy_ui_system 1.2.9 → 1.2.12

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 (66) hide show
  1. package/README.md +6 -0
  2. package/dist/index.cjs +313 -242
  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 +142 -6
  7. package/dist/index.d.ts +142 -6
  8. package/dist/index.js +313 -242
  9. package/dist/index.js.map +1 -1
  10. package/package.json +4 -3
  11. package/snippets/axzy-ui-system.code-snippets +547 -0
  12. package/src/App.tsx +37 -34
  13. package/src/components/avatar/avatar.props.ts +12 -1
  14. package/src/components/avatar/avatar.stories.tsx +19 -0
  15. package/src/components/avatar/avatar.tsx +27 -4
  16. package/src/components/calendar/calendar.tsx +1 -1
  17. package/src/components/card/card.tsx +11 -8
  18. package/src/components/confirm-dialog/confirm-dialog.tsx +1 -1
  19. package/src/components/data-table/dataTable.props.ts +10 -0
  20. package/src/components/data-table/dataTable.tsx +27 -16
  21. package/src/components/date-picker/datePicker.tsx +1 -1
  22. package/src/components/dialog/dialog.tsx +3 -2
  23. package/src/components/divider/divider.tsx +1 -1
  24. package/src/components/drawer/drawer.tsx +1 -1
  25. package/src/components/dropfile/dropfile.props.ts +6 -0
  26. package/src/components/dropfile/dropfile.tsx +65 -30
  27. package/src/components/form-builder/fieldRenderer.tsx +3 -3
  28. package/src/components/input/input.tsx +7 -7
  29. package/src/components/layout/layout.tsx +1 -1
  30. package/src/components/loader/loader.tsx +1 -1
  31. package/src/components/navbar/navbar.tsx +10 -10
  32. package/src/components/pagination/pagination.tsx +11 -11
  33. package/src/components/popover/popover.tsx +1 -1
  34. package/src/components/search-select/search-select.tsx +11 -11
  35. package/src/components/searchTable/components/EditableCell.tsx +1 -1
  36. package/src/components/searchTable/components/PaginationControls.tsx +2 -2
  37. package/src/components/searchTable/components/PaginationInfo.tsx +1 -1
  38. package/src/components/searchTable/components/SearchAndSortBar.tsx +1 -1
  39. package/src/components/searchTable/components/SearchInput.tsx +1 -1
  40. package/src/components/searchTable/components/SortButton.tsx +3 -3
  41. package/src/components/searchTable/components/TableHeader.tsx +1 -1
  42. package/src/components/searchTable/components/TableRow.tsx +4 -4
  43. package/src/components/searchTable/searchTable.tsx +2 -2
  44. package/src/components/select/select.tsx +8 -10
  45. package/src/components/sidebar/sidebar.tsx +29 -29
  46. package/src/components/slider/slider.tsx +3 -3
  47. package/src/components/stepper/stepper.props.ts +4 -0
  48. package/src/components/stepper/stepper.tsx +5 -5
  49. package/src/components/table/table.props.ts +21 -3
  50. package/src/components/table/table.tsx +27 -16
  51. package/src/components/tabs/tabs.tsx +4 -4
  52. package/src/components/textarea/textarea.tsx +3 -3
  53. package/src/components/theme-provider/themeProvider.props.ts +21 -3
  54. package/src/components/theme-provider/themeProvider.tsx +32 -32
  55. package/src/components/time-picker/timePicker.tsx +5 -5
  56. package/src/components/toast/toast.tsx +1 -1
  57. package/src/components/tooltip/tooltip.tsx +1 -1
  58. package/src/components/topbar/topbar.tsx +7 -7
  59. package/src/dev.css +1 -1
  60. package/src/hooks/useClickOutside.ts +8 -0
  61. package/src/hooks/useTableState.ts +5 -2
  62. package/src/index.css +24 -1
  63. package/src/showcases/HomeShowcase.tsx +95 -3
  64. package/src/theme/theme.ts +38 -17
  65. package/src/types/field.types.ts +70 -7
  66. package/src/utils/styles.ts +5 -5
package/src/App.tsx CHANGED
@@ -1,10 +1,9 @@
1
1
  import React, { useEffect, useMemo, useState } from "react";
2
2
  import {
3
3
  FaCreditCard,
4
- FaHome,
4
+ FaHome,
5
5
  FaKeyboard,
6
6
  FaRegBell,
7
- FaSearch,
8
7
  FaSlidersH,
9
8
  FaTable,
10
9
  } from "react-icons/fa";
@@ -61,36 +60,35 @@ import {
61
60
  ThemeProviderShowcase,
62
61
  } from "./showcases/FeedbackShowcases";
63
62
 
63
+ type ViewMode = "home" | "ui-system";
64
+
64
65
  function App() {
65
- const [activeComponentId, setActiveComponentId] = useState(
66
- () => window.location.hash.replace("#", "") || "home"
67
- );
68
- const [searchTerm, setSearchTerm] = useState("");
69
- const [subitemConnector, setSubitemConnector] = useState<
66
+ const [view, setView] = useState<ViewMode>(() => {
67
+ const hash = window.location.hash.replace("#", "");
68
+ return hash.startsWith("ui-system") ? "ui-system" : "home";
69
+ });
70
+ const [showroomActive, setShowroomActive] = useState("getting-started");
71
+ const [searchTerm] = useState("");
72
+ const [subitemConnector] = useState<
70
73
  "dot" | "|" | "none"
71
74
  >("dot");
72
75
 
73
76
  useEffect(() => {
74
77
  const onHashChange = () => {
75
- const id = window.location.hash.replace("#", "") || "home";
76
- setActiveComponentId(id);
78
+ const hash = window.location.hash.replace("#", "");
79
+ setView(hash.startsWith("ui-system") ? "ui-system" : "home");
77
80
  };
78
81
  window.addEventListener("hashchange", onHashChange);
79
82
  return () => window.removeEventListener("hashchange", onHashChange);
80
83
  }, []);
81
84
 
82
- useEffect(() => {
83
- window.location.hash = activeComponentId;
84
- }, [activeComponentId]);
85
-
86
- // Group definitions for the sidebar
85
+ // Group definitions for the sidebar (UI System showroom)
87
86
  const categories = [
88
87
  {
89
88
  id: "general",
90
89
  label: "General",
91
90
  icon: <FaHome />,
92
91
  subitems: [
93
- { id: "home", label: "Home" },
94
92
  { id: "getting-started", label: "Getting Started" },
95
93
  ],
96
94
  },
@@ -174,8 +172,8 @@ function App() {
174
172
  if (matches) {
175
173
  return {
176
174
  ...cat,
177
- isActive: activeComponentId === cat.id,
178
- action: () => setActiveComponentId(cat.id),
175
+ isActive: showroomActive === cat.id,
176
+ action: () => setShowroomActive(cat.id),
179
177
  };
180
178
  }
181
179
  return null;
@@ -190,8 +188,8 @@ function App() {
190
188
  const mappedSubitems = matchingSubitems.map((sub) => ({
191
189
  id: sub.id,
192
190
  label: sub.label,
193
- isActive: activeComponentId === sub.id,
194
- action: () => setActiveComponentId(sub.id),
191
+ isActive: showroomActive === sub.id,
192
+ action: () => setShowroomActive(sub.id),
195
193
  }));
196
194
 
197
195
  const isAnySubitemActive = mappedSubitems.some((sub) => sub.isActive);
@@ -207,7 +205,7 @@ function App() {
207
205
  if (cat.subitems) return cat.subitems.length > 0;
208
206
  return true;
209
207
  });
210
- }, [searchTerm, activeComponentId]);
208
+ }, [searchTerm, showroomActive]);
211
209
 
212
210
  const sidebarProps = {
213
211
  navigationItems: filteredNavigationItems,
@@ -215,27 +213,24 @@ function App() {
215
213
  };
216
214
 
217
215
  const topBarProps = {
218
- logoText: "AXZY Showroom",
216
+ logoText: "AXZY UI System",
219
217
  userMenu: {
220
218
  userName: "Alex Dev",
221
219
  userEmail: "alex@axzy.dev",
222
220
  menuItems: [
223
221
  {
224
- label: "Resetear Demo",
222
+ label: "Ir al Portafolio",
225
223
  onClick: () => {
226
- setActiveComponentId("home");
227
- setSearchTerm("");
224
+ window.location.hash = "home";
228
225
  },
229
226
  },
230
227
  ],
231
228
  },
232
229
  };
233
230
 
234
- // Render correct component based on active navigation
231
+ // Render correct component based on active showroom navigation
235
232
  const renderShowcase = () => {
236
- switch (activeComponentId) {
237
- case "home":
238
- return <HomeShowcase />;
233
+ switch (showroomActive) {
239
234
  case "getting-started":
240
235
  return <GettingStartedShowcase />;
241
236
  // Structure
@@ -308,17 +303,25 @@ function App() {
308
303
  case "themeprovider":
309
304
  return <ThemeProviderShowcase />;
310
305
  default:
311
- return <HomeShowcase />;
306
+ return <GettingStartedShowcase />;
312
307
  }
313
308
  };
314
309
 
315
310
  return (
316
- <ITThemeProvider showFab={true}>
317
- <ITLayout sidebar={sidebarProps} topBar={topBarProps}>
318
- <div className="max-w-7xl mx-auto">
319
- {renderShowcase()}
311
+ <ITThemeProvider showFab={false}>
312
+ {view === "home" ? (
313
+ <div className="min-h-screen bg-slate-50 dark:bg-slate-950 py-10 px-4 sm:px-6 lg:px-8">
314
+ <div className="max-w-6xl mx-auto">
315
+ <HomeShowcase />
316
+ </div>
320
317
  </div>
321
- </ITLayout>
318
+ ) : (
319
+ <ITLayout sidebar={sidebarProps} topBar={topBarProps}>
320
+ <div className="max-w-7xl mx-auto">
321
+ {renderShowcase()}
322
+ </div>
323
+ </ITLayout>
324
+ )}
322
325
  </ITThemeProvider>
323
326
  );
324
327
  }
@@ -11,7 +11,18 @@ export interface ITAvatarProps {
11
11
  initials?: string;
12
12
  /** Avatar dimensions. Valid values: `"xs"`, `"sm"`, `"md"`, `"lg"`, `"xl"`. @default "md" */
13
13
  size?: AvatarSize;
14
- /** Background color class for the initials fallback. @default "bg-primary-600" */
14
+ /**
15
+ * Color de fondo para el fallback de iniciales. Acepta un valor de color
16
+ * real (`"#8b5cf6"`, `"rgb(...)"`, `"hsl(...)"`, `"var(--...)"`) — se
17
+ * aplica como `style` inline y SIEMPRE se renderiza — o una clase de
18
+ * Tailwind (`"bg-purple-600"`) por compatibilidad con código existente.
19
+ * Una clase de Tailwind solo se ve si esa clase exacta ya existe en el
20
+ * CSS compilado que consume la app (esta librería se distribuye con un
21
+ * CSS estático pre-compilado, ver scripts/build-css.mjs), así que para
22
+ * cualquier color calculado en tiempo de ejecución (p.ej. un hash por
23
+ * usuario) se recomienda pasar el valor de color directamente.
24
+ * @default "bg-primary-600"
25
+ */
15
26
  color?: string;
16
27
  /** Additional CSS class names for the avatar container. */
17
28
  className?: string;
@@ -44,3 +44,22 @@ export const Sizes: Story = {
44
44
  </div>
45
45
  ),
46
46
  };
47
+
48
+ export const WithRawColor: Story = {
49
+ name: "Con color calculado en runtime",
50
+ parameters: {
51
+ docs: {
52
+ description: {
53
+ story:
54
+ "Cuando el color se calcula dinámicamente (por ejemplo, un hash por usuario o etiqueta), pasa un valor de color real en vez de una clase de Tailwind. Una clase de Tailwind arbitraria solo se ve si ya existe en el CSS pre-compilado de esta librería; un color inline siempre se aplica.",
55
+ },
56
+ },
57
+ },
58
+ render: () => (
59
+ <div className="flex items-center gap-4">
60
+ {["#3b82f6", "#a855f7", "#059669", "#f59e0b", "#ec4899"].map((hex) => (
61
+ <ITAvatar key={hex} initials="JD" size="md" color={hex} />
62
+ ))}
63
+ </div>
64
+ ),
65
+ };
@@ -12,7 +12,18 @@ const sizeMap: Record<AvatarSize, { container: string; text: string }> = {
12
12
 
13
13
  const DEFAULT_COLOR = "bg-primary-600";
14
14
  const DEFAULT_BG = "var(--color-primary-600)";
15
- const DEFAULT_SHADOW = "0 4px 14px 0 rgba(37, 99, 235, 0.35)";
15
+ const DEFAULT_SHADOW = "0 6px 16px -2px rgba(37, 99, 235, 0.25)";
16
+
17
+ // Un valor tipo "#8b5cf6", "rgb(...)", "hsl(...)" o "var(--...)" se aplica
18
+ // como color inline; cualquier otra cosa se trata como clase de Tailwind
19
+ // (comportamiento previo, sin romper a quien ya pasa "bg-purple-600" etc.).
20
+ // Motivo: esta librería se consume vía un CSS estático pre-compilado
21
+ // (ver scripts/build-css.mjs) que solo contiene las clases usadas en el
22
+ // código FUENTE de la librería. Si una app consumidora pasa un color de
23
+ // Tailwind que la librería nunca usa en ningún otro lado, esa clase no
24
+ // existe en el CSS entregado y el avatar se renderiza sin color visible.
25
+ // Un valor de color inline no tiene ese problema: siempre se aplica.
26
+ const isRawColorValue = (value: string) => /^#|^rgb|^hsl|^var\(/i.test(value.trim());
16
27
 
17
28
  /**
18
29
  * Circular avatar component with image, initials fallback, and optional badge overlay.
@@ -22,6 +33,11 @@ const DEFAULT_SHADOW = "0 4px 14px 0 rgba(37, 99, 235, 0.35)";
22
33
  *
23
34
  * @example
24
35
  * <ITAvatar initials="JD" size="md" color="bg-purple-600" />
36
+ *
37
+ * @example
38
+ * // Recomendado cuando el color se calcula en tiempo de ejecución (p.ej. un
39
+ * // hash por usuario/etiqueta): pasa un valor de color real, no una clase.
40
+ * <ITAvatar initials="JD" size="md" color="#8b5cf6" />
25
41
  */
26
42
  export default function ITAvatar({
27
43
  src,
@@ -34,17 +50,24 @@ export default function ITAvatar({
34
50
  onClick,
35
51
  }: ITAvatarProps) {
36
52
  const { container, text } = sizeMap[size];
37
- const useInlineStyle = !color || color === DEFAULT_COLOR;
53
+ const useDefaultStyle = !color || color === DEFAULT_COLOR;
54
+ const useRawColorStyle = !useDefaultStyle && isRawColorValue(color);
38
55
 
39
56
  return (
40
57
  <div
41
58
  className={clsx(
42
59
  "relative inline-flex items-center justify-center rounded-full flex-shrink-0 overflow-hidden text-white font-bold tracking-wide",
43
60
  container,
44
- !useInlineStyle && color,
61
+ !useDefaultStyle && !useRawColorStyle && color,
45
62
  className,
46
63
  )}
47
- style={useInlineStyle ? { backgroundColor: DEFAULT_BG, boxShadow: DEFAULT_SHADOW } : undefined}
64
+ style={
65
+ useDefaultStyle
66
+ ? { backgroundColor: DEFAULT_BG, boxShadow: DEFAULT_SHADOW }
67
+ : useRawColorStyle
68
+ ? { backgroundColor: color }
69
+ : undefined
70
+ }
48
71
  onClick={onClick}
49
72
  role={onClick ? "button" : undefined}
50
73
  tabIndex={onClick ? 0 : undefined}
@@ -371,7 +371,7 @@ export const ITCalendar: React.FC<ITCalendarProps> = ({
371
371
  {/* Weekday Headers */}
372
372
  <div className="grid grid-cols-7 mb-2">
373
373
  {['Lun', 'Mar', 'Mié', 'Jue', 'Vie', 'Sáb', 'Dom'].map(day => (
374
- <ITText key={day} as="div" className="text-center text-xs font-semibold text-gray-400 uppercase py-1">
374
+ <ITText key={day} as="div" className="text-center text-xs font-semibold text-secondary-400 uppercase py-1">
375
375
  {day}
376
376
  </ITText>
377
377
  ))}
@@ -33,15 +33,18 @@ export default function ITCard({
33
33
 
34
34
  const containerStyle: React.CSSProperties = {
35
35
  backgroundColor: "var(--card-bg, #ffffff)",
36
- borderColor: "var(--card-border, #e2e8f0)",
36
+ borderColor: "var(--card-border, rgba(15, 23, 42, 0.06))",
37
37
  borderWidth: "1px",
38
- borderRadius: "var(--card-radius, 0.75rem)",
38
+ borderRadius: "var(--card-radius, var(--radius-2xl))",
39
+ // Soft depth: every card floats a little at rest; interactive cards
40
+ // gain visual weight on hover instead of appearing flat until clicked.
39
41
  boxShadow: onClick
40
42
  ? isHovered
41
- ? "0 8px 25px -5px rgba(0, 0, 0, 0.1)"
42
- : "0 1px 3px 0 rgba(0, 0, 0, 0.05)"
43
- : "none",
44
- transition: onClick ? "all 0.2s ease-in-out" : "none",
43
+ ? "var(--shadow-lg)"
44
+ : "var(--shadow-sm)"
45
+ : "var(--shadow-sm)",
46
+ transition: onClick ? "box-shadow 0.2s ease-in-out, transform 0.2s ease-in-out" : "none",
47
+ transform: onClick && isHovered ? "translateY(-2px)" : "translateY(0)",
45
48
  cursor: onClick ? "pointer" : "default",
46
49
  };
47
50
 
@@ -74,12 +77,12 @@ export default function ITCard({
74
77
  {title}
75
78
  </ITText>
76
79
  )}
77
- <ITText as="div" className="text-gray-600">{children}</ITText>
80
+ <ITText as="div" className="text-secondary-600">{children}</ITText>
78
81
  </div>
79
82
  {actions && (
80
83
  <div
81
84
  className={clsx(
82
- "p-4 border-t border-gray-100 mt-auto",
85
+ "p-4 border-t border-secondary-100 mt-auto",
83
86
  actionClassName,
84
87
  )}
85
88
  >
@@ -37,7 +37,7 @@ export default function ITConfirmDialog({
37
37
  if (!isOpen) return null;
38
38
 
39
39
  return (
40
- <div className="fixed inset-0 z-[300] flex items-center justify-center p-4">
40
+ <div className="fixed inset-0 z-[60] flex items-center justify-center p-4">
41
41
  <div className="absolute inset-0 bg-black/40 backdrop-blur-sm" onClick={onClose} />
42
42
  <div
43
43
  className={clsx(
@@ -1,18 +1,28 @@
1
1
  import { ReactNode } from "react";
2
2
  import { Column } from "../table/table.props";
3
3
 
4
+ /** Parameters passed to `fetchData` every time pagination, filters, or sorting change. */
4
5
  export interface ITDataTableFetchParams {
6
+ /** 1-indexed current page number. */
5
7
  page: number;
8
+ /** Number of rows requested per page. */
6
9
  limit: number;
10
+ /** Active per-column filter values (from `Column.filter`), keyed by column `key`. */
7
11
  filters: Record<string, string | number | boolean | Date>;
12
+ /** Active sort, present only when the user has clicked a sortable column header. */
8
13
  sort?: {
14
+ /** Column `key` currently sorted by. */
9
15
  key: string;
16
+ /** Sort direction. */
10
17
  direction: "asc" | "desc";
11
18
  };
12
19
  }
13
20
 
21
+ /** Expected shape of the Promise returned by `fetchData`. */
14
22
  export interface ITDataTableResponse<T> {
23
+ /** Rows for the requested page. */
15
24
  data: T[];
25
+ /** Total row count across all pages (used to compute the paginator's total pages). */
16
26
  total: number;
17
27
  }
18
28
 
@@ -11,6 +11,17 @@ import { Column } from "../table/table.props";
11
11
  import { formatCurrencyMX } from "../table/table";
12
12
  import { ITDataTableProps } from "./dataTable.props";
13
13
  import ITText from "@/components/text/text";
14
+ import {
15
+ tableActionsCell,
16
+ tableBody,
17
+ tableCell,
18
+ tableCellText,
19
+ tableContainer,
20
+ tableEmptyContent,
21
+ tableHeaderCell,
22
+ tableHeaderRow,
23
+ tableRow,
24
+ } from "@/utils/styles";
14
25
 
15
26
  const getNestedValue = (obj: unknown, path: string) => {
16
27
  return path.split(".").reduce((acc, part) => acc && acc[part], obj);
@@ -136,14 +147,14 @@ export default function ITDataTable<T extends Record<string, unknown>>({
136
147
  title={`${getToggleLabel()} para ${col.label}`}
137
148
  disabled={isLoading}
138
149
  >
139
- <div className="relative w-10 h-5 bg-gray-300 rounded-full">
150
+ <div className="relative w-10 h-5 bg-secondary-300 rounded-full">
140
151
  <div
141
152
  className={clsx(
142
153
  "absolute top-0.5 w-4 h-4 rounded-full transition-all duration-300 shadow-sm",
143
154
  {
144
- "left-0.5 bg-gray-400": currentValue === undefined,
155
+ "left-0.5 bg-secondary-400": currentValue === undefined,
145
156
  "left-5 bg-slate-500": currentValue === true,
146
- "left-0.5 bg-gray-500": currentValue === false,
157
+ "left-0.5 bg-secondary-500": currentValue === false,
147
158
  }
148
159
  )}
149
160
  />
@@ -157,7 +168,7 @@ export default function ITDataTable<T extends Record<string, unknown>>({
157
168
  return <FaSpinner className="animate-spin" aria-label="Cargando opciones" title="Cargando opciones" />;
158
169
  }
159
170
  if (col.catalogOptions.error) {
160
- return <ITText as="span" className="text-red-500 text-xs">Error cargando</ITText>;
171
+ return <ITText as="span" className="text-danger-500 text-xs">Error cargando</ITText>;
161
172
  }
162
173
  return (
163
174
  <ITSelect
@@ -203,9 +214,9 @@ export default function ITDataTable<T extends Record<string, unknown>>({
203
214
  return typeof value === "number" && col.currencyMX ? formatCurrencyMX(value) : value;
204
215
  case "boolean":
205
216
  return value ? (
206
- <FaCheck className="text-green-500" aria-label="Verdadero" title="Verdadero" />
217
+ <FaCheck className="text-success-500" aria-label="Verdadero" title="Verdadero" />
207
218
  ) : (
208
- <FaTimes className="text-red-500" aria-label="Falso" title="Falso" />
219
+ <FaTimes className="text-danger-500" aria-label="Falso" title="Falso" />
209
220
  );
210
221
  case "actions":
211
222
  return col.actions ? col.actions(row) : null;
@@ -253,7 +264,7 @@ export default function ITDataTable<T extends Record<string, unknown>>({
253
264
 
254
265
  return (
255
266
  <div className={clsx("space-y-4 w-full relative", containerClassName)}>
256
- <div className="rounded-xl shadow-sm overflow-hidden" style={{ backgroundColor: 'var(--color-table-rowBg, #ffffff)' }}>
267
+ <div className={tableContainer} style={{ backgroundColor: 'var(--color-table-rowBg, #ffffff)' }}>
257
268
  {title && (
258
269
  <div className="px-6 py-5 flex items-center justify-between" style={{ backgroundColor: 'var(--color-table-rowBg, #ffffff)' }}>
259
270
  <ITText as="h2" className="text-xl font-bold text-secondary-900 leading-tight">{title}</ITText>
@@ -316,7 +327,7 @@ export default function ITDataTable<T extends Record<string, unknown>>({
316
327
  ))
317
328
  ) : (
318
329
  !isLoading && (
319
- <div className="flex flex-col items-center justify-center py-12 text-secondary-400">
330
+ <div className={clsx(tableEmptyContent, "py-12")}>
320
331
  <ITText as="span" className="text-lg">No se encontraron resultados</ITText>
321
332
  <ITText as="span" className="text-sm mt-1">Intenta ajustar los filtros</ITText>
322
333
  </div>
@@ -336,9 +347,9 @@ export default function ITDataTable<T extends Record<string, unknown>>({
336
347
  )}
337
348
  >
338
349
  <thead>
339
- <tr className="bg-secondary-50 text-xs uppercase tracking-wider font-semibold text-slate-700 dark:text-slate-200">
350
+ <tr className={clsx(tableHeaderRow, "dark:text-slate-200")}>
340
351
  {columns.map((col) => (
341
- <th key={col.key} scope="col" className={clsx("px-4 py-4 align-top", col.className)}>
352
+ <th key={col.key} scope="col" className={tableHeaderCell(col.className)}>
342
353
  <div className="flex flex-col gap-3 min-w-[150px]">
343
354
  <div className="flex items-center justify-between gap-2">
344
355
  <ITText as="span" className="text-slate-900 dark:text-white font-bold">{col.label}</ITText>
@@ -364,18 +375,18 @@ export default function ITDataTable<T extends Record<string, unknown>>({
364
375
  ))}
365
376
  </tr>
366
377
  </thead>
367
- <tbody className="divide-y divide-slate-100 dark:divide-slate-700/30">
378
+ <tbody className={clsx(tableBody, "dark:divide-slate-700/30")}>
368
379
  {data.length > 0 ? (
369
380
  data.map((row, rowIndex) => (
370
- <tr key={rowIndex} className={clsx("hover:bg-secondary-50/50 transition-colors duration-150 group", variant === "striped" && "odd:bg-secondary-50/40 dark:odd:bg-slate-800/20")}>
381
+ <tr key={rowIndex} className={clsx(tableRow, variant === "striped" && "odd:bg-secondary-50/40 dark:odd:bg-slate-800/20")}>
371
382
  {columns.map((col) => (
372
- <td key={`${rowIndex}-${col.key}`} className={clsx("px-4 py-3 align-middle", col.className)}>
383
+ <td key={`${rowIndex}-${col.key}`} className={tableCell(col.className)}>
373
384
  {col.type === "actions" ? (
374
- <div className="flex items-center justify-center gap-2">
385
+ <div className={tableActionsCell}>
375
386
  {renderCellContent(col, row) as React.ReactNode}
376
387
  </div>
377
388
  ) : (
378
- <div className="text-secondary-700 font-medium">
389
+ <div className={tableCellText}>
379
390
  {renderCellContent(col, row) as React.ReactNode}
380
391
  </div>
381
392
  )}
@@ -387,7 +398,7 @@ export default function ITDataTable<T extends Record<string, unknown>>({
387
398
  <tr>
388
399
  <td colSpan={columns.length} className="px-6 py-12 text-center">
389
400
  {!isLoading && (
390
- <div className="flex flex-col items-center justify-center text-secondary-400">
401
+ <div className={tableEmptyContent}>
391
402
  <ITText as="span" className="text-lg">No se encontraron resultados</ITText>
392
403
  <ITText as="span" className="text-sm mt-1">Intenta ajustar los filtros</ITText>
393
404
  </div>
@@ -303,7 +303,7 @@ export default function ITDatePicker({
303
303
  {isOpen && (
304
304
  <div
305
305
  className={clsx(
306
- "fixed z-[9999]",
306
+ "fixed z-[70]",
307
307
  calendarClassName,
308
308
  range ? "w-[320px]" : "w-[280px]"
309
309
  )}
@@ -67,9 +67,10 @@ export default function ITDialog({
67
67
 
68
68
  const content = (
69
69
  <div
70
+ data-it-dialog="true"
70
71
  className={`fixed inset-0 flex ${
71
72
  fullScreen ? "items-stretch" : "items-center justify-center"
72
- } bg-black/50 z-[9999]`}
73
+ } bg-slate-900/50 z-[60]`}
73
74
  >
74
75
  <div
75
76
  ref={modalRef}
@@ -97,7 +98,7 @@ export default function ITDialog({
97
98
  ) : (
98
99
  <>
99
100
  <button
100
- className="absolute top-2 right-2 text-gray-600 hover:text-gray-900"
101
+ className="absolute top-2 right-2 text-secondary-600 hover:text-secondary-900"
101
102
  onClick={onClose}
102
103
  >
103
104
  <FaRegTimesCircle />
@@ -14,7 +14,7 @@ import { ITDividerProps } from "./divider.props";
14
14
  *
15
15
  * @example
16
16
  * ```tsx
17
- * <ITDivider orientation="vertical" color="bg-red-500" thickness="w-1" />
17
+ * <ITDivider orientation="vertical" color="bg-danger-500" thickness="w-1" />
18
18
  * ```
19
19
  */
20
20
  export default function ITDivider({
@@ -41,7 +41,7 @@ export default function ITDrawer({
41
41
  return (
42
42
  <>
43
43
  {isOpen && (
44
- <div className="fixed inset-0 z-[100] flex">
44
+ <div className="fixed inset-0 z-[50] flex">
45
45
  <div className="absolute inset-0 bg-black/40 backdrop-blur-sm transition-opacity" />
46
46
  <div
47
47
  ref={panelRef}
@@ -7,6 +7,12 @@ export enum FileTypeEnum {
7
7
  PNG = "image/png",
8
8
  JPG = "image/jpg",
9
9
  JPEG = "image/jpeg",
10
+ MP4 = "video/mp4",
11
+ MOV = "video/quicktime",
12
+ AVI = "video/x-msvideo",
13
+ MKV = "video/x-matroska",
14
+ VIDEO_3GPP = "video/3gpp",
15
+ WEBM = "video/webm",
10
16
  }
11
17
 
12
18
  /** Upload lifecycle status */