@axzydev/axzy_ui_system 1.2.8 → 1.2.11

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 (45) hide show
  1. package/README.md +109 -51
  2. package/dist/index.cjs +141 -73
  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 +141 -5
  7. package/dist/index.d.ts +141 -5
  8. package/dist/index.js +141 -73
  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 +43 -33
  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 +26 -3
  16. package/src/components/confirm-dialog/confirm-dialog.tsx +1 -1
  17. package/src/components/data-table/dataTable.props.ts +10 -0
  18. package/src/components/data-table/dataTable.tsx +24 -13
  19. package/src/components/date-picker/datePicker.tsx +1 -1
  20. package/src/components/dialog/dialog.tsx +2 -1
  21. package/src/components/drawer/drawer.tsx +1 -1
  22. package/src/components/dropfile/dropfile.props.ts +6 -0
  23. package/src/components/dropfile/dropfile.tsx +51 -16
  24. package/src/components/layout/layout.tsx +1 -1
  25. package/src/components/navbar/navbar.tsx +2 -2
  26. package/src/components/popover/popover.tsx +1 -1
  27. package/src/components/search-select/search-select.tsx +4 -4
  28. package/src/components/select/select.tsx +6 -8
  29. package/src/components/sidebar/sidebar.tsx +15 -15
  30. package/src/components/stepper/stepper.props.ts +4 -0
  31. package/src/components/table/table.props.ts +21 -3
  32. package/src/components/table/table.tsx +24 -13
  33. package/src/components/theme-provider/themeProvider.props.ts +21 -3
  34. package/src/components/time-picker/timePicker.tsx +1 -1
  35. package/src/components/toast/toast.tsx +1 -1
  36. package/src/components/tooltip/tooltip.tsx +1 -1
  37. package/src/components/topbar/topbar.tsx +1 -1
  38. package/src/dev.css +1 -1
  39. package/src/hooks/useClickOutside.ts +8 -0
  40. package/src/hooks/useTableState.ts +5 -2
  41. package/src/index.css +1 -1
  42. package/src/showcases/GettingStartedShowcase.tsx +207 -0
  43. package/src/showcases/HomeShowcase.tsx +95 -3
  44. package/src/theme/theme.ts +21 -0
  45. package/src/types/field.types.ts +70 -7
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";
@@ -13,6 +12,7 @@ import "./index.css";
13
12
 
14
13
  // Import Showcases
15
14
  import { HomeShowcase } from "./showcases/HomeShowcase";
15
+ import { GettingStartedShowcase } from "./showcases/GettingStartedShowcase";
16
16
  import {
17
17
  CardShowcase,
18
18
  LayoutShowcase,
@@ -60,34 +60,37 @@ import {
60
60
  ThemeProviderShowcase,
61
61
  } from "./showcases/FeedbackShowcases";
62
62
 
63
+ type ViewMode = "home" | "ui-system";
64
+
63
65
  function App() {
64
- const [activeComponentId, setActiveComponentId] = useState(
65
- () => window.location.hash.replace("#", "") || "home"
66
- );
67
- const [searchTerm, setSearchTerm] = useState("");
68
- 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<
69
73
  "dot" | "|" | "none"
70
74
  >("dot");
71
75
 
72
76
  useEffect(() => {
73
77
  const onHashChange = () => {
74
- const id = window.location.hash.replace("#", "") || "home";
75
- setActiveComponentId(id);
78
+ const hash = window.location.hash.replace("#", "");
79
+ setView(hash.startsWith("ui-system") ? "ui-system" : "home");
76
80
  };
77
81
  window.addEventListener("hashchange", onHashChange);
78
82
  return () => window.removeEventListener("hashchange", onHashChange);
79
83
  }, []);
80
84
 
81
- useEffect(() => {
82
- window.location.hash = activeComponentId;
83
- }, [activeComponentId]);
84
-
85
- // Group definitions for the sidebar
85
+ // Group definitions for the sidebar (UI System showroom)
86
86
  const categories = [
87
87
  {
88
88
  id: "general",
89
89
  label: "General",
90
90
  icon: <FaHome />,
91
+ subitems: [
92
+ { id: "getting-started", label: "Getting Started" },
93
+ ],
91
94
  },
92
95
  {
93
96
  id: "struc",
@@ -169,8 +172,8 @@ function App() {
169
172
  if (matches) {
170
173
  return {
171
174
  ...cat,
172
- isActive: activeComponentId === cat.id,
173
- action: () => setActiveComponentId(cat.id),
175
+ isActive: showroomActive === cat.id,
176
+ action: () => setShowroomActive(cat.id),
174
177
  };
175
178
  }
176
179
  return null;
@@ -185,8 +188,8 @@ function App() {
185
188
  const mappedSubitems = matchingSubitems.map((sub) => ({
186
189
  id: sub.id,
187
190
  label: sub.label,
188
- isActive: activeComponentId === sub.id,
189
- action: () => setActiveComponentId(sub.id),
191
+ isActive: showroomActive === sub.id,
192
+ action: () => setShowroomActive(sub.id),
190
193
  }));
191
194
 
192
195
  const isAnySubitemActive = mappedSubitems.some((sub) => sub.isActive);
@@ -202,7 +205,7 @@ function App() {
202
205
  if (cat.subitems) return cat.subitems.length > 0;
203
206
  return true;
204
207
  });
205
- }, [searchTerm, activeComponentId]);
208
+ }, [searchTerm, showroomActive]);
206
209
 
207
210
  const sidebarProps = {
208
211
  navigationItems: filteredNavigationItems,
@@ -210,27 +213,26 @@ function App() {
210
213
  };
211
214
 
212
215
  const topBarProps = {
213
- logoText: "AXZY Showroom",
216
+ logoText: "AXZY UI System",
214
217
  userMenu: {
215
218
  userName: "Alex Dev",
216
219
  userEmail: "alex@axzy.dev",
217
220
  menuItems: [
218
221
  {
219
- label: "Resetear Demo",
222
+ label: "Ir al Portafolio",
220
223
  onClick: () => {
221
- setActiveComponentId("home");
222
- setSearchTerm("");
224
+ window.location.hash = "home";
223
225
  },
224
226
  },
225
227
  ],
226
228
  },
227
229
  };
228
230
 
229
- // Render correct component based on active navigation
231
+ // Render correct component based on active showroom navigation
230
232
  const renderShowcase = () => {
231
- switch (activeComponentId) {
232
- case "home":
233
- return <HomeShowcase />;
233
+ switch (showroomActive) {
234
+ case "getting-started":
235
+ return <GettingStartedShowcase />;
234
236
  // Structure
235
237
  case "layout":
236
238
  return <LayoutShowcase />;
@@ -301,17 +303,25 @@ function App() {
301
303
  case "themeprovider":
302
304
  return <ThemeProviderShowcase />;
303
305
  default:
304
- return <HomeShowcase />;
306
+ return <GettingStartedShowcase />;
305
307
  }
306
308
  };
307
309
 
308
310
  return (
309
- <ITThemeProvider showFab={true}>
310
- <ITLayout sidebar={sidebarProps} topBar={topBarProps}>
311
- <div className="max-w-7xl mx-auto">
312
- {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>
313
317
  </div>
314
- </ITLayout>
318
+ ) : (
319
+ <ITLayout sidebar={sidebarProps} topBar={topBarProps}>
320
+ <div className="max-w-7xl mx-auto">
321
+ {renderShowcase()}
322
+ </div>
323
+ </ITLayout>
324
+ )}
315
325
  </ITThemeProvider>
316
326
  );
317
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
+ };
@@ -14,6 +14,17 @@ const DEFAULT_COLOR = "bg-primary-600";
14
14
  const DEFAULT_BG = "var(--color-primary-600)";
15
15
  const DEFAULT_SHADOW = "0 4px 14px 0 rgba(37, 99, 235, 0.35)";
16
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());
27
+
17
28
  /**
18
29
  * Circular avatar component with image, initials fallback, and optional badge overlay.
19
30
  *
@@ -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}
@@ -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);
@@ -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-black/50 z-[60]`}
73
74
  >
74
75
  <div
75
76
  ref={modalRef}
@@ -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 */
@@ -3,6 +3,7 @@ import { useDropzone } from "react-dropzone";
3
3
  // import pdfjsLib from "@/hooks/pdf"; // Disabled as hook is missing
4
4
  import clsx from "clsx";
5
5
  import ITText from "@/components/text/text";
6
+ import ITButton from "@/components/button/button";
6
7
  import { ITDropfileProps, FileTypeEnum, UploadStatus } from "./dropfile.props";
7
8
  export { FileTypeEnum, UploadStatus } from "./dropfile.props";
8
9
 
@@ -94,6 +95,24 @@ const ITDropfile: React.FC<ITDropfileProps> = ({
94
95
  case FileTypeEnum.JPEG:
95
96
  accept[FileTypeEnum.JPEG] = [".jpeg", ".jpg"];
96
97
  break;
98
+ case FileTypeEnum.MP4:
99
+ accept[FileTypeEnum.MP4] = [".mp4"];
100
+ break;
101
+ case FileTypeEnum.MOV:
102
+ accept[FileTypeEnum.MOV] = [".mov"];
103
+ break;
104
+ case FileTypeEnum.AVI:
105
+ accept[FileTypeEnum.AVI] = [".avi"];
106
+ break;
107
+ case FileTypeEnum.MKV:
108
+ accept[FileTypeEnum.MKV] = [".mkv"];
109
+ break;
110
+ case FileTypeEnum.VIDEO_3GPP:
111
+ accept[FileTypeEnum.VIDEO_3GPP] = [".3gp"];
112
+ break;
113
+ case FileTypeEnum.WEBM:
114
+ accept[FileTypeEnum.WEBM] = [".webm"];
115
+ break;
97
116
  }
98
117
  });
99
118
 
@@ -121,6 +140,14 @@ const ITDropfile: React.FC<ITDropfileProps> = ({
121
140
  case FileTypeEnum.JPEG:
122
141
  if (!extensions.includes("IMAGEN")) extensions.push("IMAGEN");
123
142
  break;
143
+ case FileTypeEnum.MP4:
144
+ case FileTypeEnum.MOV:
145
+ case FileTypeEnum.AVI:
146
+ case FileTypeEnum.MKV:
147
+ case FileTypeEnum.VIDEO_3GPP:
148
+ case FileTypeEnum.WEBM:
149
+ if (!extensions.includes("VIDEO")) extensions.push("VIDEO");
150
+ break;
124
151
  }
125
152
  });
126
153
 
@@ -341,35 +368,43 @@ const ITDropfile: React.FC<ITDropfileProps> = ({
341
368
  <div className="px-3 py-2 bg-white border-t border-gray-100 flex justify-end gap-2">
342
369
  {!isConfirmed ? (
343
370
  <>
344
- <button
371
+ <ITButton
345
372
  type="button"
373
+ variant="outlined"
374
+ color="secondary"
375
+ size="small"
346
376
  onClick={handleCancel}
347
- className="px-3 py-1.5 text-xs font-medium text-gray-700 bg-white border border-gray-300 rounded-lg hover:bg-gray-50 transition-colors"
348
377
  >
349
- <ITText as="span">Cancelar</ITText>
350
- </button>
351
- <button
378
+ <ITText>Cancelar</ITText>
379
+ </ITButton>
380
+ <ITButton
352
381
  type="button"
382
+ variant="filled"
383
+ color="primary"
384
+ size="small"
353
385
  onClick={handleConfirm}
354
- className="px-3 py-1.5 text-xs font-medium text-white bg-primary-600 rounded-lg hover:bg-primary-700 shadow-sm transition-colors flex items-center gap-1"
355
386
  >
356
- <ITText as="span">Confirmar</ITText>
357
- <svg className="w-3 h-3" fill="none" viewBox="0 0 24 24" stroke="currentColor">
358
- <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M5 13l4 4L19 7" />
359
- </svg>
360
- </button>
387
+ <div className="flex items-center gap-2">
388
+ <ITText>Confirmar</ITText>
389
+ <svg className="w-3 h-3" fill="none" viewBox="0 0 24 24" stroke="currentColor">
390
+ <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M5 13l4 4L19 7" />
391
+ </svg>
392
+ </div>
393
+ </ITButton>
361
394
  </>
362
395
  ) : (
363
- <button
396
+ <ITButton
364
397
  type="button"
398
+ variant="outlined"
399
+ color="danger"
400
+ size="small"
365
401
  onClick={handleDelete}
366
- className="px-3 py-1.5 text-xs font-medium text-danger-600 bg-danger-50 border border-danger-100 rounded-lg hover:bg-danger-100 transition-colors flex items-center gap-1"
367
402
  >
368
403
  <svg className="w-3 h-3" fill="none" viewBox="0 0 24 24" stroke="currentColor">
369
404
  <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16" />
370
405
  </svg>
371
- <ITText as="span">Eliminar</ITText>
372
- </button>
406
+ <ITText>Eliminar</ITText>
407
+ </ITButton>
373
408
  )}
374
409
  </div>
375
410
 
@@ -392,4 +427,4 @@ const ITDropfile: React.FC<ITDropfileProps> = ({
392
427
  );
393
428
  };
394
429
 
395
- export default ITDropfile;
430
+ export default ITDropfile;
@@ -73,7 +73,7 @@ export default function ITLayout({
73
73
  {/* MOBILE SIDEBAR PANE */}
74
74
  {mobileSidebarOpen && (
75
75
  <div
76
- className="lg:hidden fixed inset-0 z-50 transition-opacity duration-300 backdrop-blur-sm bg-black/40"
76
+ className="lg:hidden fixed inset-0 z-[40] transition-opacity duration-300 backdrop-blur-sm bg-black/40"
77
77
  onClick={() => setMobileSidebarOpen(false)}
78
78
  >
79
79
  <div
@@ -116,7 +116,7 @@ export default function ITNavbar({
116
116
  {isUserMenuOpen && (
117
117
  <div
118
118
  ref={userMenuRef}
119
- className="z-50 absolute right-0 mt-2 text-base list-none bg-white divide-y divide-gray-100 rounded-lg shadow-sm"
119
+ className="z-[70] absolute right-0 mt-2 text-base list-none bg-white divide-y divide-gray-100 rounded-lg shadow-sm"
120
120
  >
121
121
  <div className="px-4 py-3">
122
122
  <ITText as="span" className="block text-sm text-gray-900">
@@ -152,7 +152,7 @@ export default function ITNavbar({
152
152
 
153
153
  <div className="flex-1 flex overflow-hidden relative">
154
154
  {(showSidebar || showSidebarOnMobile) && (
155
- <aside className="fixed inset-y-0 left-0 w-64 bg-gray-50 transform transition-transform duration-300 ease-in-out z-50 shadow-lg md:static md:transform-none md:shadow-none md:border-r md:border-gray-200">
155
+ <aside className="fixed inset-y-0 left-0 w-64 bg-gray-50 transform transition-transform duration-300 ease-in-out z-[40] shadow-lg md:static md:transform-none md:shadow-none md:border-r md:border-gray-200">
156
156
  <div className="h-full overflow-y-auto py-4 px-3">
157
157
  <ul className="space-y-2 font-medium">{sidebarItems}</ul>
158
158
  </div>
@@ -47,7 +47,7 @@ export default function ITPopover({
47
47
  {trigger}
48
48
  </div>
49
49
  {open && (
50
- <div className={clsx("absolute z-[200]", positionClasses[position])}>
50
+ <div className={clsx("absolute z-[70]", positionClasses[position])}>
51
51
  <div className="bg-white dark:bg-slate-800 rounded-xl shadow-xl border border-slate-200 dark:border-slate-700 p-3 min-w-[160px]">
52
52
  {children}
53
53
  </div>
@@ -148,7 +148,7 @@ export default function ITSearchSelect({
148
148
  const getInputStyle = () => {
149
149
  const style: React.CSSProperties = {
150
150
  backgroundColor: inputTheme.backgroundColor || "#ffffff",
151
- borderColor: inputTheme.borderColor || "#e2e8f0",
151
+ borderColor: inputTheme.borderColor || "var(--color-secondary-300)",
152
152
  borderRadius: inputTheme.borderRadius || "0.5rem",
153
153
  padding: inputTheme.padding || "0.5rem 0.75rem",
154
154
  fontSize: inputTheme.fontSize || "0.875rem",
@@ -160,8 +160,8 @@ export default function ITSearchSelect({
160
160
  };
161
161
 
162
162
  if (disabled) {
163
- style.backgroundColor = inputTheme.disabled?.backgroundColor || "#f1f5f9";
164
- style.borderColor = inputTheme.disabled?.borderColor || "#e2e8f0";
163
+ style.backgroundColor = inputTheme.disabled?.backgroundColor || "var(--color-secondary-100)";
164
+ style.borderColor = inputTheme.disabled?.borderColor || "var(--color-secondary-200)";
165
165
  style.opacity = 0.7;
166
166
  style.cursor = "not-allowed";
167
167
  }
@@ -217,7 +217,7 @@ export default function ITSearchSelect({
217
217
 
218
218
  {/* Dropdown Panel */}
219
219
  {isOpen && (
220
- <div className="absolute z-50 w-full mt-1 bg-white dark:bg-slate-900 border border-gray-200 dark:border-slate-800 rounded-lg shadow-xl overflow-hidden animate-in fade-in zoom-in duration-200 origin-top">
220
+ <div className="absolute z-[70] w-full mt-1 bg-white dark:bg-slate-900 border border-gray-200 dark:border-slate-800 rounded-lg shadow-xl overflow-hidden animate-in fade-in zoom-in duration-200 origin-top">
221
221
  <div className="max-h-60 overflow-y-auto">
222
222
  {filteredOptions.length > 0 ? (
223
223
  filteredOptions.map((option) => (