@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
@@ -4,6 +4,7 @@ import { useState } from "react";
4
4
  import { FaAngleDown } from "react-icons/fa";
5
5
  import { ITSelectProps } from "./select.props";
6
6
  import ITText from "@/components/text/text";
7
+ import { inputError, inputLabel } from "@/utils/styles";
7
8
 
8
9
  export default function ITSelect({
9
10
  name,
@@ -80,10 +81,7 @@ export default function ITSelect({
80
81
  <ITText
81
82
  as="label"
82
83
  htmlFor={name}
83
- className={clsx(
84
- "text-sm font-medium text-gray-700 dark:text-slate-300 pt-0",
85
- { "text-red-500": hasError }
86
- )}
84
+ className={inputLabel(hasError)}
87
85
  >
88
86
  <ITText as="span">{label}</ITText>
89
87
  {required && <ITText as="span" className="text-red-500 ml-1">*</ITText>}
@@ -110,11 +108,11 @@ export default function ITSelect({
110
108
  )}
111
109
  style={getStyle()}
112
110
  >
113
- <option value=""><ITText as="span">{placeholder || "Selecciona una opción"}</ITText></option>
111
+ <option value="">{placeholder || "Selecciona una opción"}</option>
114
112
  {
115
113
  readOnly ? (
116
114
  <option value={value} disabled>
117
- <ITText as="span">{options.find((option) => option[valueField] === value)?.[labelField]}</ITText>
115
+ {options.find((option) => option[valueField] === value)?.[labelField]}
118
116
  </option>
119
117
  ) : (
120
118
  options.map((option) => (
@@ -123,7 +121,7 @@ export default function ITSelect({
123
121
  value={option[valueField]}
124
122
  title={option[labelField]}
125
123
  >
126
- <ITText as="span">{option[labelField]}</ITText>
124
+ {option[labelField]}
127
125
  </option>
128
126
  ))
129
127
  )
@@ -136,7 +134,7 @@ export default function ITSelect({
136
134
  {/* Validation message aligned with select */}
137
135
  {hasError && (
138
136
  <div className="flex-shrink-0 min-w-[140px] flex items-center pt-3">
139
- <ITText as="p" className="text-red-500 text-xs">{errorMessage}</ITText>
137
+ <ITText as="p" className={inputError}>{errorMessage}</ITText>
140
138
  </div>
141
139
  )}
142
140
  </div>
@@ -126,7 +126,7 @@ export default function ITSidebar({
126
126
  style={{
127
127
  zIndex: 50,
128
128
  backgroundColor: "var(--sidebar-bg, rgba(255, 255, 255, 0.90))",
129
- borderRight: "1px solid var(--sidebar-border, #e2e8f0)",
129
+ borderRight: "1px solid var(--sidebar-border, var(--color-secondary-200))",
130
130
  WebkitBackdropFilter: 'blur(12px)',
131
131
  backdropFilter: 'blur(12px)',
132
132
  }}
@@ -143,12 +143,12 @@ export default function ITSidebar({
143
143
  ${isSidebarCollapsed ? "justify-center p-2.5 mb-2" : "justify-between px-3.5 py-3 mb-1"}
144
144
  `}
145
145
  style={{
146
- backgroundColor: item.isActive ? "var(--sidebar-active-bg, #f8fafc)" : 'transparent',
146
+ backgroundColor: item.isActive ? "var(--sidebar-active-bg, var(--color-secondary-50))" : 'transparent',
147
147
  boxShadow: item.isActive ? '0 1px 2px 0 rgba(0, 0, 0, 0.05)' : 'none',
148
- border: item.isActive ? "1px solid var(--sidebar-border, #e2e8f0)" : '1px solid transparent'
148
+ border: item.isActive ? "1px solid var(--sidebar-border, var(--color-secondary-200))" : '1px solid transparent'
149
149
  }}
150
150
  onMouseEnter={(e) => {
151
- if (!item.isActive) e.currentTarget.style.backgroundColor = "var(--sidebar-hover-bg, #f1f5f9)";
151
+ if (!item.isActive) e.currentTarget.style.backgroundColor = "var(--sidebar-hover-bg, var(--color-secondary-100))";
152
152
  }}
153
153
  onMouseLeave={(e) => {
154
154
  if (!item.isActive) e.currentTarget.style.backgroundColor = 'transparent';
@@ -193,7 +193,7 @@ export default function ITSidebar({
193
193
 
194
194
  {!isSidebarCollapsed && item.subitems && item.subitems.length > 0 && (
195
195
  <div className={`flex-shrink-0 transition-transform duration-300 ease-[cubic-bezier(0.2,0,0,1)] ${expandedItems.has(item.id) ? "rotate-180" : ""}`}
196
- style={{ color: item.isActive ? "var(--sidebar-active-color, #0f172a)" : "var(--sidebar-icon-color, #64748b)", opacity: 0.7 }}>
196
+ style={{ color: item.isActive ? "var(--sidebar-active-color, var(--color-secondary-900))" : "var(--sidebar-icon-color, var(--color-secondary-500))", opacity: 0.7 }}>
197
197
  <FaChevronDown className="w-3 h-3" />
198
198
  </div>
199
199
  )}
@@ -220,15 +220,15 @@ export default function ITSidebar({
220
220
  {/* Glassmorphism Collapsed Tooltip / Submenu */}
221
221
  {isSidebarCollapsed && (
222
222
  <div
223
- className="absolute left-full top-0 ml-4 rounded-2xl opacity-0 invisible group-hover/navitem:opacity-100 group-hover/navitem:visible transition-all duration-300 pointer-events-none z-50 min-w-[220px] overflow-hidden -translate-x-2 group-hover/navitem:translate-x-0 shadow-[0_10px_40px_-10px_rgba(0,0,0,0.15)]"
223
+ className="absolute left-full top-0 ml-4 rounded-2xl opacity-0 invisible group-hover/navitem:opacity-100 group-hover/navitem:visible transition-all duration-300 pointer-events-none z-[70] min-w-[220px] overflow-hidden -translate-x-2 group-hover/navitem:translate-x-0 shadow-[0_10px_40px_-10px_rgba(0,0,0,0.15)]"
224
224
  style={{
225
225
  backgroundColor: "var(--sidebar-bg, #ffffff)",
226
- border: "1px solid var(--sidebar-border, #e2e8f0)",
226
+ border: "1px solid var(--sidebar-border, var(--color-secondary-200))",
227
227
  WebkitBackdropFilter: 'blur(16px)',
228
228
  backdropFilter: 'blur(16px)',
229
229
  }}
230
230
  >
231
- <div className="px-5 py-4 flex items-center gap-3 font-semibold border-b" style={{ borderColor: "var(--sidebar-border, #e2e8f0)", color: "var(--sidebar-active-color, #0f172a)" }}>
231
+ <div className="px-5 py-4 flex items-center gap-3 font-semibold border-b" style={{ borderColor: "var(--sidebar-border, var(--color-secondary-200))", color: "var(--sidebar-active-color, var(--color-secondary-900))" }}>
232
232
  {item.icon && <span style={{ color: "var(--sidebar-active-icon, #10b981)" }} className="text-xl drop-shadow-sm">{item.icon}</span>}
233
233
  <ITText as="span" className="tracking-wide text-[15px]">{item.label}</ITText>
234
234
  </div>
@@ -249,8 +249,8 @@ export default function ITSidebar({
249
249
  }}
250
250
  />
251
251
  )}
252
- <span className={`w-1.5 h-1.5 rounded-full transition-all ${subitem.isActive ? "scale-125" : ""}`} style={{ backgroundColor: subitem.isActive ? "var(--sidebar-active-icon, #10b981)" : "var(--sidebar-icon-color, #94a3b8)" }} />
253
- <ITText as="span" style={{ color: subitem.isActive ? "var(--sidebar-active-color, #0f172a)" : "var(--sidebar-label-color, #475569)", fontWeight: subitem.isActive ? 600 : 500 }}>{subitem.label}</ITText>
252
+ <span className={`w-1.5 h-1.5 rounded-full transition-all ${subitem.isActive ? "scale-125" : ""}`} style={{ backgroundColor: subitem.isActive ? "var(--sidebar-active-icon, #10b981)" : "var(--sidebar-icon-color, var(--color-secondary-400))" }} />
253
+ <ITText as="span" style={{ color: subitem.isActive ? "var(--sidebar-active-color, var(--color-secondary-900))" : "var(--sidebar-label-color, var(--color-secondary-600))", fontWeight: subitem.isActive ? 600 : 500 }}>{subitem.label}</ITText>
254
254
  </div>
255
255
  ))}
256
256
  </div>
@@ -267,7 +267,7 @@ export default function ITSidebar({
267
267
  className="ml-5 flex flex-col gap-0.5 py-1"
268
268
  style={{
269
269
  borderLeft: subitemConnector === '|'
270
- ? "1px solid var(--sidebar-border, #e2e8f0)"
270
+ ? "1px solid var(--sidebar-border, var(--color-secondary-200))"
271
271
  : 'none'
272
272
  }}
273
273
  >
@@ -280,8 +280,8 @@ export default function ITSidebar({
280
280
  }}
281
281
  className={`flex items-center gap-2.5 w-full text-left px-3 py-2 rounded-xl transition-all duration-300`}
282
282
  style={{
283
- color: subitem.isActive ? "var(--sidebar-active-color, #0f172a)" : "var(--sidebar-label-color, #475569)",
284
- backgroundColor: subitem.isActive ? "var(--sidebar-active-bg, #f8fafc)" : 'transparent',
283
+ color: subitem.isActive ? "var(--sidebar-active-color, var(--color-secondary-900))" : "var(--sidebar-label-color, var(--color-secondary-600))",
284
+ backgroundColor: subitem.isActive ? "var(--sidebar-active-bg, var(--color-secondary-50))" : 'transparent',
285
285
  fontSize: '0.85rem',
286
286
  fontWeight: subitem.isActive ? 600 : 500,
287
287
  letterSpacing: '0.01em',
@@ -289,7 +289,7 @@ export default function ITSidebar({
289
289
  }}
290
290
  onMouseEnter={(e) => {
291
291
  if (!subitem.isActive) {
292
- e.currentTarget.style.backgroundColor = "var(--sidebar-hover-bg, #f1f5f9)";
292
+ e.currentTarget.style.backgroundColor = "var(--sidebar-hover-bg, var(--color-secondary-100))";
293
293
  e.currentTarget.style.transform = 'translateX(3px)';
294
294
  }
295
295
  }}
@@ -315,7 +315,7 @@ export default function ITSidebar({
315
315
  style={{
316
316
  backgroundColor: subitem.isActive
317
317
  ? "var(--sidebar-active-icon, #10b981)"
318
- : "var(--sidebar-icon-color, #94a3b8)"
318
+ : "var(--sidebar-icon-color, var(--color-secondary-400))"
319
319
  }}
320
320
  />
321
321
  )}
@@ -2,9 +2,13 @@ import React from "react";
2
2
 
3
3
  export type IconType = React.ReactNode;
4
4
 
5
+ /** A single step in an `ITStepper` flow. */
5
6
  export interface Step {
7
+ /** Label shown next to the step indicator. */
6
8
  label: string;
9
+ /** Content rendered in the panel while this step is active. */
7
10
  content: React.ReactNode;
11
+ /** Custom icon shown in the step indicator when the stepper's `useIcons` is true. */
8
12
  icon?: IconType;
9
13
  }
10
14
 
@@ -1,31 +1,49 @@
1
1
  import { TableSize, TableVariants } from "@/types/table.types";
2
2
 
3
+ /** Data type of a table column, controls default rendering, filter UI, and sort comparison. */
3
4
  export type ColumnType = "string" | "date" | "number" | "boolean" | "actions" | "catalog";
4
5
 
6
+ /** A single selectable entry for a `"catalog"`-type column's filter/value lookup. */
5
7
  export interface CatalogOption {
8
+ /** Unique identifier matched against the row's field value. */
6
9
  id: string | number;
10
+ /** Human-readable label shown in the filter dropdown and resolved cell display. */
7
11
  name: string;
8
12
  }
9
13
 
14
+ /** Definition of a single column for ITTable. */
10
15
  export interface Column<T = any> {
16
+ /** Field key on the row object this column reads from (supports dot-notation for nested values, e.g. `"address.city"`). */
11
17
  key: string;
18
+ /** Column header text. */
12
19
  label: string;
20
+ /** Additional CSS classes applied to both the header (`<th>`) and body (`<td>`) cells of this column. */
13
21
  className?: string;
14
- currencyMX?: boolean;
22
+ /** Formats numeric values as Mexican pesos (MXN) via `Intl`-based currency formatting. Only applies when `type` is `"number"`. @default false */
23
+ currencyMX?: boolean;
24
+ /** Custom action buttons/content rendered for a `"actions"`-type column. Receives the full row object. */
15
25
  actions?: (row: T) => React.ReactNode;
26
+ /** Enables per-column filtering. Pass `true` for a text/number/boolean filter matching `type`, or `"catalog"` to filter against `catalogOptions`. @default false */
16
27
  filter?: boolean | "catalog";
28
+ /** Column data type. Drives default cell rendering, filter UI, and sort comparison. */
17
29
  type: ColumnType;
30
+ /** Whether clicking the header sorts by this column. Ignored for `type: "actions"`. @default false */
18
31
  sortable?: boolean;
32
+ /** Custom cell renderer, takes precedence over the default type-based rendering. Receives the full row object. */
19
33
  render?: (row: T) => React.ReactNode;
34
+ /** Custom inline-edit input renderer (used by table variants that support inline editing). */
20
35
  editComponent?: (props: {
21
36
  value: any;
22
37
  onChange: (value: any) => void;
23
38
  rowData: T;
24
39
  }) => React.ReactNode;
25
- // Nuevas propiedades para catálogo
40
+ /** Configuration for `type: "catalog"` columns: the lookup options plus loading/error state for async catalogs. */
26
41
  catalogOptions?: {
42
+ /** Available catalog entries used to resolve/filter the raw id stored on the row. */
27
43
  data: CatalogOption[];
44
+ /** Shows a loading spinner in the filter UI while the catalog is being fetched. @default false */
28
45
  loading?: boolean;
46
+ /** Shows an error state in the filter UI when the catalog failed to load. @default false */
29
47
  error?: boolean;
30
48
  };
31
49
  }
@@ -57,4 +75,4 @@ export interface ITTableProps<T> {
57
75
  showVerticalBorder?: boolean;
58
76
  /** Custom class for vertical borders (overrides the default subtle gray). */
59
77
  verticalBorderClassname?: string;
60
- }
78
+ }
@@ -15,6 +15,17 @@ import ITPagination from "../pagination/pagination";
15
15
  import ITSelect from "../select/select";
16
16
  import { Column, ITTableProps } from "./table.props";
17
17
  import ITText from "@/components/text/text";
18
+ import {
19
+ tableActionsCell,
20
+ tableBody,
21
+ tableCell,
22
+ tableCellText,
23
+ tableContainer,
24
+ tableEmptyContent,
25
+ tableHeaderCell,
26
+ tableHeaderRow,
27
+ tableRow,
28
+ } from "@/utils/styles";
18
29
 
19
30
  const getNestedValue = (obj: unknown, path: string) => {
20
31
  return path.split(".").reduce((acc, part) => acc && acc[part], obj);
@@ -211,7 +222,7 @@ export default function ITTable<T extends Record<string, unknown>>({
211
222
  }
212
223
 
213
224
  if (col.catalogOptions.error) {
214
- return <ITText as="span" className="text-red-500 text-xs">Error cargando</ITText>;
225
+ return <ITText as="span" className="text-danger-500 text-xs">Error cargando</ITText>;
215
226
  }
216
227
 
217
228
  return (
@@ -260,13 +271,13 @@ export default function ITTable<T extends Record<string, unknown>>({
260
271
  case "boolean":
261
272
  return value ? (
262
273
  <FaCheck
263
- className="text-green-500"
274
+ className="text-success-500"
264
275
  aria-label="Verdadero"
265
276
  title="Verdadero"
266
277
  />
267
278
  ) : (
268
279
  <FaTimes
269
- className="text-red-500"
280
+ className="text-danger-500"
270
281
  aria-label="Falso"
271
282
  title="Falso"
272
283
  />
@@ -312,7 +323,7 @@ export default function ITTable<T extends Record<string, unknown>>({
312
323
 
313
324
  return (
314
325
  <div className={clsx("space-y-4 w-full", containerClassName)}>
315
- <div className="rounded-xl shadow-sm overflow-hidden" style={{ backgroundColor: 'var(--color-table-rowBg, #ffffff)' }}>
326
+ <div className={tableContainer} style={{ backgroundColor: 'var(--color-table-rowBg, #ffffff)' }}>
316
327
  {/* Header outside overflow */}
317
328
  {title && (
318
329
  <div className="px-6 py-5 flex items-center justify-between" style={{ backgroundColor: 'var(--color-table-rowBg, #ffffff)' }}>
@@ -382,7 +393,7 @@ export default function ITTable<T extends Record<string, unknown>>({
382
393
  </div>
383
394
  ))
384
395
  ) : (
385
- <div className="flex flex-col items-center justify-center py-12 text-secondary-400">
396
+ <div className={clsx(tableEmptyContent, "py-12")}>
386
397
  <ITText as="span" className="text-lg">No se encontraron resultados</ITText>
387
398
  <ITText as="span" className="text-sm mt-1">Intenta ajustar los filtros</ITText>
388
399
  </div>
@@ -400,12 +411,12 @@ export default function ITTable<T extends Record<string, unknown>>({
400
411
  )}
401
412
  >
402
413
  <thead>
403
- <tr className="bg-secondary-50 text-xs uppercase tracking-wider font-semibold text-slate-700 dark:text-slate-200">
414
+ <tr className={clsx(tableHeaderRow, "dark:text-slate-200")}>
404
415
  {columns.map((col) => (
405
416
  <th
406
417
  key={col.key}
407
418
  scope="col"
408
- className={clsx("px-4 py-4 align-top", col.className)}
419
+ className={tableHeaderCell(col.className)}
409
420
  >
410
421
  <div className="flex flex-col gap-3 min-w-[150px]">
411
422
  <div className="flex items-center justify-between gap-2">
@@ -431,24 +442,24 @@ export default function ITTable<T extends Record<string, unknown>>({
431
442
  ))}
432
443
  </tr>
433
444
  </thead>
434
- <tbody className="divide-y divide-slate-100 dark:divide-slate-700/30">
445
+ <tbody className={clsx(tableBody, "dark:divide-slate-700/30")}>
435
446
  {currentData.length > 0 ? (
436
447
  currentData.map((row, rowIndex) => (
437
448
  <tr
438
449
  key={rowIndex}
439
- 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")}
450
+ className={clsx(tableRow, variant === "striped" && "odd:bg-secondary-50/40 dark:odd:bg-slate-800/20")}
440
451
  >
441
452
  {columns.map((col) => (
442
453
  <td
443
454
  key={`${rowIndex}-${col.key}`}
444
- className={clsx("px-4 py-3 align-middle", col.className)}
455
+ className={tableCell(col.className)}
445
456
  >
446
457
  {col.type === "actions" ? (
447
- <div className="flex items-center justify-center gap-2">
458
+ <div className={tableActionsCell}>
448
459
  {renderCellContent(col, row) as React.ReactNode}
449
460
  </div>
450
461
  ) : (
451
- <div className="text-secondary-700 font-medium">
462
+ <div className={tableCellText}>
452
463
  {renderCellContent(col, row) as React.ReactNode}
453
464
  </div>
454
465
  )}
@@ -459,7 +470,7 @@ export default function ITTable<T extends Record<string, unknown>>({
459
470
  ) : (
460
471
  <tr>
461
472
  <td colSpan={columns.length} className="px-6 py-12 text-center">
462
- <div className="flex flex-col items-center justify-center text-secondary-400">
473
+ <div className={tableEmptyContent}>
463
474
  <ITText as="span" className="text-lg">No se encontraron resultados</ITText>
464
475
  <ITText as="span" className="text-sm mt-1">Intenta ajustar los filtros</ITText>
465
476
  </div>
@@ -1,31 +1,49 @@
1
1
  export interface ITThemePalette {
2
+ /** Main brand accent color (hex). Drives primary buttons, active nav items, focus rings, links, and the `--color-primary` CSS variable. @default "#06b6d4" */
2
3
  primary: string;
4
+ /** Secondary/neutral accent color (hex). Used for less prominent actions and secondary badges/buttons. @default "#6b7280" */
3
5
  secondary: string;
6
+ /** Tertiary accent color (hex), used for a third level of emphasis (e.g. alternate badges, chart accents). @default "#8b5cf6" */
4
7
  ternary: string;
8
+ /** Semantic color for destructive/error states (hex): delete buttons, error badges, invalid form fields. @default "#ef4444" */
5
9
  danger: string;
10
+ /** Semantic color for success/confirmation states (hex): success badges, completed steps, positive stats. @default "#22c55e" */
6
11
  success: string;
12
+ /** Semantic color for informational states (hex): info banners/badges, neutral notices. @default "#3b82f6" */
7
13
  info: string;
14
+ /** Semantic color for alert/caution states (hex), distinct from `warning`. Used by components that need a stronger visual cue than warning. @default "#f97316" */
8
15
  alert: string;
16
+ /** Semantic color for warning states (hex): warning badges/banners, pending states. @default "#eab308" */
9
17
  warning: string;
18
+ /** Colors for the app shell's sidebar and top navbar (ITSidebar, ITNavbar, ITTopbar, ITLayout). */
10
19
  layout: {
20
+ /** Background color of the sidebar (hex). @default "#ffffff" */
11
21
  sidebarBg: string;
22
+ /** Text/icon color used on the sidebar. @default "#334155" */
12
23
  sidebarText: string;
24
+ /** Background color of the top navigation bar (hex). @default "#ffffff" */
13
25
  navbarBg: string;
26
+ /** Text/icon color used on the top navigation bar. @default "#1e293b" */
14
27
  navbarText: string;
15
28
  };
29
+ /** Colors for ITTable/ITDataTable/ITSearchTable header and rows. */
16
30
  table: {
31
+ /** Background color of the table header row (hex). @default "#f8fafc" */
17
32
  headerBg: string;
33
+ /** Text color of the table header row. @default "#334155" */
18
34
  headerText: string;
35
+ /** Background color of table body rows (hex). @default "#ffffff" */
19
36
  rowBg: string;
37
+ /** Text color of table body rows. @default "#1e293b" */
20
38
  rowText: string;
21
39
  };
22
40
  }
23
41
 
24
42
  export interface ITThemeProviderProps {
25
- /** Partial palette overrides merged with the default theme. Supports primary, secondary, tertiary, danger, success, info, alert, warning, layout, and table colors. */
43
+ /** Partial palette overrides merged (deep merge) with the default theme. Supports primary, secondary, ternary, danger, success, info, alert, warning, layout, and table colors. Persisted to `localStorage` under `"it-theme-palette"` once the user edits it via the FAB/drawer. */
26
44
  theme?: Partial<ITThemePalette>;
27
- /** The subtree that receives the theme context and CSS variables. */
45
+ /** The subtree that receives the theme context and CSS variables. Must wrap your entire app (or the portion that uses AXZY UI System components) once, near the root. */
28
46
  children: React.ReactNode;
29
- /** Whether to show the floating action button for opening the theme designer drawer. */
47
+ /** Whether to render the floating action button (bottom-right) that opens the live theme-designer drawer, letting end users tweak colors and persist their choice. Set to `false` to hide the FAB in production and only theme via the `theme` prop. @default true */
30
48
  showFab?: boolean;
31
49
  }
@@ -227,7 +227,7 @@ export default function ITTimePicker({
227
227
  {isOpen && !disabled && (
228
228
  <div
229
229
  ref={dropdownRef}
230
- className="fixed z-[9999] bg-white border border-gray-100 shadow-xl rounded-xl w-64 overflow-hidden flex flex-col animate-in fade-in zoom-in-95 duration-200 origin-top it-timepicker-dropdown"
230
+ className="fixed z-[70] bg-white border border-gray-100 shadow-xl rounded-xl w-64 overflow-hidden flex flex-col animate-in fade-in zoom-in-95 duration-200 origin-top it-timepicker-dropdown"
231
231
  style={{
232
232
  top: `${dropdownPosition.top}px`,
233
233
  left: `${dropdownPosition.left}px`,
@@ -80,7 +80,7 @@ export default function ITToast({
80
80
  return (
81
81
  <div
82
82
  className={clsx(
83
- "fixed z-50 p-4 rounded-xl shadow-xl flex items-center justify-between gap-4 transition-all duration-300 text-white min-w-[300px]",
83
+ "fixed z-[80] p-4 rounded-xl shadow-xl flex items-center justify-between gap-4 transition-all duration-300 text-white min-w-[300px]",
84
84
  positionStyles[position],
85
85
  {
86
86
  "opacity-100 translate-y-0 scale-100": isVisible,
@@ -62,7 +62,7 @@ export default function ITTooltip({
62
62
  >
63
63
  {children}
64
64
  {visible && (
65
- <div className={clsx("absolute z-[200] pointer-events-none", positionClasses[position])}>
65
+ <div className={clsx("absolute z-[70] pointer-events-none", positionClasses[position])}>
66
66
  <div className="bg-slate-800 dark:bg-slate-700 text-white text-xs rounded-lg px-2.5 py-1.5 whitespace-nowrap shadow-lg">
67
67
  <ITText as="span">{content}</ITText>
68
68
  </div>
@@ -186,7 +186,7 @@ export default function ITTopBar({
186
186
  <div
187
187
  ref={userMenuRef}
188
188
  className={`
189
- absolute right-0 mt-3 w-64 rounded-2xl shadow-[0_10px_40px_-10px_rgba(0,0,0,0.15)] z-50 overflow-hidden transform origin-top-right transition-all duration-200 ease-[cubic-bezier(0.2,0,0,1)]
189
+ absolute right-0 mt-3 w-64 rounded-2xl shadow-[0_10px_40px_-10px_rgba(0,0,0,0.15)] z-[70] overflow-hidden transform origin-top-right transition-all duration-200 ease-[cubic-bezier(0.2,0,0,1)]
190
190
  ${isUserMenuOpen ? "scale-100 opacity-100 translate-y-0" : "scale-95 opacity-0 -translate-y-2 pointer-events-none"}
191
191
  `}
192
192
  style={{
package/src/dev.css CHANGED
@@ -1,2 +1,2 @@
1
1
  @import "tailwindcss";
2
- @import "./index.css";
2
+ @import "./index.css";
@@ -6,6 +6,14 @@ const useClickOutside = (
6
6
  ) => {
7
7
  useEffect(() => {
8
8
  const handleClickOutside = (event: MouseEvent) => {
9
+ const target = event.target as Element | null;
10
+ const clickedDialog = target?.closest("[data-it-dialog]");
11
+ const currentDialog = ref.current?.closest("[data-it-dialog]");
12
+
13
+ // Nested dialogs must not close their parent when interacting with the
14
+ // child overlay or its contents.
15
+ if (clickedDialog && clickedDialog !== currentDialog) return;
16
+
9
17
  if (ref.current && !ref.current.contains(event.target as Node)) {
10
18
  callback();
11
19
  }
@@ -42,11 +42,14 @@ export function useTableState({
42
42
 
43
43
  const goToPage = useCallback(
44
44
  (page: number) => {
45
- if (page >= 1 && page <= totalPages) {
45
+ // No limitar contra `totalPages`: ese estado vive en useTableState y
46
+ // nunca se sincroniza con el total real (ITDataTable calcula el suyo).
47
+ // ITPagination ya deshabilita la navegación más allá de la última página.
48
+ if (page >= 1) {
46
49
  setCurrentPage(page);
47
50
  }
48
51
  },
49
- [totalPages]
52
+ []
50
53
  );
51
54
 
52
55
  const handleItemsPerPageChange = useCallback((value: number) => {
package/src/index.css CHANGED
@@ -5,7 +5,7 @@
5
5
 
6
6
  @variant dark (&:is(.dark &));
7
7
 
8
- :root, :host {
8
+ @theme {
9
9
  --animate-fadeIn: fadeIn 0.5s ease-out forwards;
10
10
  --animate-fade-in: fadeIn 0.5s ease-out forwards;
11
11