neogestify-ui-components 2.2.2 → 2.3.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 (44) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +803 -349
  3. package/dist/components/ElementLibraryBuilder/index.js +299 -120
  4. package/dist/components/ElementLibraryBuilder/index.js.map +1 -1
  5. package/dist/components/ElementLibraryBuilder/index.mjs +300 -121
  6. package/dist/components/ElementLibraryBuilder/index.mjs.map +1 -1
  7. package/dist/components/VenueMapEditor/index.js.map +1 -1
  8. package/dist/components/VenueMapEditor/index.mjs.map +1 -1
  9. package/dist/components/alerts/index.js +108 -51
  10. package/dist/components/alerts/index.js.map +1 -1
  11. package/dist/components/alerts/index.mjs +109 -52
  12. package/dist/components/alerts/index.mjs.map +1 -1
  13. package/dist/components/html/index.d.mts +101 -22
  14. package/dist/components/html/index.d.ts +101 -22
  15. package/dist/components/html/index.js +506 -166
  16. package/dist/components/html/index.js.map +1 -1
  17. package/dist/components/html/index.mjs +507 -167
  18. package/dist/components/html/index.mjs.map +1 -1
  19. package/dist/components/icons/index.d.mts +5 -1
  20. package/dist/components/icons/index.d.ts +5 -1
  21. package/dist/components/icons/index.js +16 -0
  22. package/dist/components/icons/index.js.map +1 -1
  23. package/dist/components/icons/index.mjs +13 -1
  24. package/dist/components/icons/index.mjs.map +1 -1
  25. package/dist/context/theme/index.js +59 -37
  26. package/dist/context/theme/index.js.map +1 -1
  27. package/dist/context/theme/index.mjs +59 -37
  28. package/dist/context/theme/index.mjs.map +1 -1
  29. package/dist/index.d.mts +1 -1
  30. package/dist/index.d.ts +1 -1
  31. package/dist/index.js +510 -166
  32. package/dist/index.js.map +1 -1
  33. package/dist/index.mjs +508 -168
  34. package/dist/index.mjs.map +1 -1
  35. package/package.json +1 -1
  36. package/src/components/html/Button.tsx +84 -38
  37. package/src/components/html/Form.tsx +33 -13
  38. package/src/components/html/Input.tsx +110 -31
  39. package/src/components/html/Loading.tsx +58 -33
  40. package/src/components/html/Modal.tsx +67 -20
  41. package/src/components/html/Select.tsx +92 -39
  42. package/src/components/html/Table.tsx +274 -50
  43. package/src/components/html/TextArea.tsx +81 -31
  44. package/src/components/icons/icons.tsx +32 -0
@@ -1,5 +1,5 @@
1
1
  import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
2
- import { forwardRef, useState, useEffect, useImperativeHandle } from 'react';
2
+ import { forwardRef, useState, useRef, useEffect, useImperativeHandle } from 'react';
3
3
 
4
4
  // src/components/icons/icons.tsx
5
5
  function AnimateSpin({ className }) {
@@ -36,56 +36,101 @@ function CloseIcon({ className }) {
36
36
  }
37
37
  ) });
38
38
  }
39
+ function ChevronDownIcon({ className }) {
40
+ return /* @__PURE__ */ jsx("svg", { viewBox: "0 0 16 16", className, fill: "currentColor", "aria-hidden": true, children: /* @__PURE__ */ jsx("path", { d: "M4.516 7.548c.436-.446 1.043-.481 1.576 0L8 9.747l1.908-2.199c.533-.481 1.14-.446 1.576 0 .436.445.408 1.197 0 1.615-.408.418-2.695 2.977-2.695 2.977-.27.282-.64.423-1.01.423s-.74-.14-1.01-.423c0 0-2.287-2.559-2.695-2.977-.408-.418-.436-1.17 0-1.615z" }) });
41
+ }
42
+ function SortAscIcon({ className }) {
43
+ return /* @__PURE__ */ jsx("svg", { viewBox: "0 0 12 12", className, fill: "currentColor", "aria-hidden": true, children: /* @__PURE__ */ jsx("path", { d: "M6 2.5l4 5H2l4-5z" }) });
44
+ }
45
+ function SortDescIcon({ className }) {
46
+ return /* @__PURE__ */ jsx("svg", { viewBox: "0 0 12 12", className, fill: "currentColor", "aria-hidden": true, children: /* @__PURE__ */ jsx("path", { d: "M6 9.5L2 4.5h8L6 9.5z" }) });
47
+ }
48
+ function SortBothIcon({ className }) {
49
+ return /* @__PURE__ */ jsx("svg", { viewBox: "0 0 12 12", className, fill: "currentColor", "aria-hidden": true, children: /* @__PURE__ */ jsx("path", { d: "M6 1.5l3 3.5H3L6 1.5zm0 9l-3-3.5h6L6 10.5z" }) });
50
+ }
51
+ var BASE = "transition-all duration-200 disabled:opacity-50 disabled:cursor-not-allowed cursor-pointer inline-flex items-center gap-2";
52
+ var SIZE_PAD = {
53
+ sm: "px-2.5 py-1.5 text-xs",
54
+ md: "px-3 py-2 text-sm",
55
+ lg: "px-4 py-2.5 text-base"
56
+ };
57
+ var SIZE_ICON_PAD = {
58
+ sm: "p-1.5",
59
+ md: "p-2",
60
+ lg: "p-2.5"
61
+ };
62
+ var SHAPE_CLASS = {
63
+ rounded: "rounded-md",
64
+ pill: "rounded-full",
65
+ square: "rounded-none"
66
+ };
67
+ var VARIANT_STYLE = {
68
+ primary: "border border-indigo-600/20 dark:border-indigo-500/20 font-medium text-white bg-indigo-600 hover:bg-indigo-700 dark:bg-indigo-500 dark:hover:bg-indigo-600 focus:outline-none focus:ring-2 focus:ring-indigo-500 dark:focus:ring-indigo-400 focus:ring-offset-2 focus:ring-offset-gray-50 dark:focus:ring-offset-gray-900",
69
+ secondary: "font-medium text-gray-600 dark:text-gray-400 hover:text-gray-900 dark:hover:text-white hover:bg-gray-200 dark:hover:bg-gray-800 border border-gray-300 dark:border-gray-600 shadow-sm hover:shadow-md focus:outline-none focus:ring-2 focus:ring-indigo-500 dark:focus:ring-indigo-400 focus:ring-offset-2 focus:ring-offset-gray-50 dark:focus:ring-offset-gray-900",
70
+ icon: "text-gray-600 dark:text-gray-400 hover:text-gray-900 dark:hover:text-white hover:bg-gray-200 dark:hover:bg-gray-800 focus:outline-none focus:ring-2 focus:ring-indigo-500 dark:focus:ring-indigo-400 focus:ring-offset-2 focus:ring-offset-gray-50 dark:focus:ring-offset-gray-900",
71
+ danger: "border border-red-600/20 dark:border-red-500/20 font-medium text-white bg-red-600 hover:bg-red-700 dark:bg-red-500 dark:hover:bg-red-600 focus:outline-none focus:ring-2 focus:ring-red-500 dark:focus:ring-red-400 focus:ring-offset-2 focus:ring-offset-gray-50 dark:focus:ring-offset-gray-900",
72
+ success: "border border-green-600/20 dark:border-green-500/20 font-medium text-white bg-green-600 hover:bg-green-700 dark:bg-green-500 dark:hover:bg-green-600 focus:outline-none focus:ring-2 focus:ring-green-500 dark:focus:ring-green-400 focus:ring-offset-2 focus:ring-offset-gray-50 dark:focus:ring-offset-gray-900",
73
+ outline: "border border-gray-300 dark:border-gray-600 font-medium text-gray-700 dark:text-gray-300 bg-transparent hover:bg-gray-100 dark:hover:bg-gray-700 focus:outline-none focus:ring-2 focus:ring-indigo-500 dark:focus:ring-indigo-400 focus:ring-offset-2 focus:ring-offset-gray-50 dark:focus:ring-offset-gray-900",
74
+ nav: "w-full px-4 py-2 text-sm font-medium hover:scale-105 text-gray-700 dark:text-gray-300 dark:hover:text-white hover:shadow-lg focus:outline-none focus:ring-2 focus:ring-indigo-500 dark:focus:ring-indigo-400 focus:ring-offset-2 focus:ring-offset-gray-50 dark:focus:ring-offset-gray-900",
75
+ custom: "",
76
+ link: "text-sm text-indigo-600 dark:text-indigo-400 hover:text-indigo-700 dark:hover:text-indigo-300 focus:outline-none focus:ring-2 focus:ring-indigo-500 dark:focus:ring-indigo-400 focus:ring-offset-2 focus:ring-offset-gray-50 dark:focus:ring-offset-gray-900 rounded-lg px-2",
77
+ warning: "border border-yellow-600/20 dark:border-yellow-500/20 font-medium text-white bg-yellow-600 hover:bg-yellow-700 dark:bg-yellow-500 dark:hover:bg-yellow-600 focus:outline-none focus:ring-2 focus:ring-yellow-500 dark:focus:ring-yellow-400 focus:ring-offset-2 focus:ring-offset-gray-50 dark:focus:ring-offset-gray-900",
78
+ toggle: "font-medium border-2 focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:ring-offset-2 focus:ring-offset-gray-50 dark:focus:ring-offset-gray-900",
79
+ ghost: "font-medium text-indigo-600 dark:text-indigo-400 bg-transparent border border-indigo-200 dark:border-indigo-800 hover:bg-indigo-50 dark:hover:bg-indigo-900/30 focus:outline-none focus:ring-2 focus:ring-indigo-500 dark:focus:ring-indigo-400 focus:ring-offset-2 focus:ring-offset-gray-50 dark:focus:ring-offset-gray-900"
80
+ };
39
81
  var Button = ({
40
82
  variant = "primary",
41
83
  children,
42
84
  isLoading = false,
43
85
  loadingText,
44
86
  isActive = false,
87
+ size = "md",
88
+ leftIcon,
89
+ rightIcon,
90
+ fullWidth = false,
91
+ shape,
45
92
  className = "",
46
93
  disabled,
47
94
  ...props
48
95
  }) => {
49
- const baseClasses = "transition-all duration-200 disabled:opacity-50 disabled:cursor-not-allowed cursor-pointer";
50
- const variantClasses = {
51
- primary: "py-2 px-2 border border-indigo-600/20 dark:border-indigo-500/20 text-sm font-medium rounded-md text-white bg-indigo-600 hover:bg-indigo-700 dark:bg-indigo-500 dark:hover:bg-indigo-600 focus:outline-none focus:ring-2 focus:ring-indigo-500 dark:focus:ring-indigo-400 focus:ring-offset-2 focus:ring-offset-gray-50 dark:focus:ring-offset-gray-900",
52
- secondary: "p-2 text-gray-600 dark:text-gray-400 hover:text-gray-900 dark:hover:text-white hover:bg-gray-200 dark:hover:bg-gray-800 rounded-md border border-gray-300 dark:border-gray-600 shadow-sm hover:shadow-md focus:outline-none focus:ring-2 focus:ring-indigo-500 dark:focus:ring-indigo-400 focus:ring-offset-2 focus:ring-offset-gray-50 dark:focus:ring-offset-gray-900",
53
- icon: "p-2 text-gray-600 dark:text-gray-400 hover:text-gray-900 dark:hover:text-white hover:bg-gray-200 dark:hover:bg-gray-800 rounded-full focus:outline-none focus:ring-2 focus:ring-indigo-500 dark:focus:ring-indigo-400 focus:ring-offset-2 focus:ring-offset-gray-50 dark:focus:ring-offset-gray-900",
54
- danger: "py-2 px-2 border border-red-600/20 dark:border-red-500/20 text-sm font-medium rounded-md text-white bg-red-600 hover:bg-red-700 dark:bg-red-500 dark:hover:bg-red-600 focus:outline-none focus:ring-2 focus:ring-red-500 dark:focus:ring-red-400 focus:ring-offset-2 focus:ring-offset-gray-50 dark:focus:ring-offset-gray-900",
55
- success: "py-2 px-2 border border-green-600/20 dark:border-green-500/20 text-sm font-medium rounded-md text-white bg-green-600 hover:bg-green-700 dark:bg-green-500 dark:hover:bg-green-600 focus:outline-none focus:ring-2 focus:ring-green-500 dark:focus:ring-green-400 focus:ring-offset-2 focus:ring-offset-gray-50 dark:focus:ring-offset-gray-900",
56
- outline: "py-2 px-2 border border-gray-300 dark:border-gray-600 text-sm font-medium rounded-md text-gray-700 dark:text-gray-300 bg-transparent hover:bg-gray-100 dark:hover:bg-gray-700 focus:outline-none focus:ring-2 focus:ring-indigo-500 dark:focus:ring-indigo-400 focus:ring-offset-2 focus:ring-offset-gray-50 dark:focus:ring-offset-gray-900",
57
- nav: "w-full flex items-center px-4 py-2 text-sm font-medium rounded-md transition-all duration-200 hover:scale-105 text-gray-700 dark:text-gray-300 dark:hover:text-white hover:shadow-lg focus:outline-none focus:ring-2 focus:ring-indigo-500 dark:focus:ring-indigo-400 focus:ring-offset-2 focus:ring-offset-gray-50 dark:focus:ring-offset-gray-900",
58
- custom: "",
59
- link: "text-sm text-indigo-600 dark:text-indigo-400 hover:text-indigo-700 dark:hover:text-indigo-300 transition-colors duration-200 focus:outline-none focus:ring-2 focus:ring-indigo-500 dark:focus:ring-indigo-400 focus:ring-offset-2 focus:ring-offset-gray-50 dark:focus:ring-offset-gray-900 rounded-lg px-2",
60
- warning: "py-2 px-2 border border-yellow-600/20 dark:border-yellow-500/20 text-sm font-medium rounded-md text-white bg-yellow-600 hover:bg-yellow-700 dark:bg-yellow-500 dark:hover:bg-yellow-600 focus:outline-none focus:ring-2 focus:ring-yellow-500 dark:focus:ring-yellow-400 focus:ring-offset-2 focus:ring-offset-gray-50 dark:focus:ring-offset-gray-900",
61
- toggle: "px-2 py-2 rounded-lg font-medium transition-all duration-200 disabled:cursor-not-allowed border-2 focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:ring-offset-2 focus:ring-offset-gray-50 dark:focus:ring-offset-gray-900"
62
- };
63
- let classes = `${baseClasses} ${variantClasses[variant]} ${className}`;
64
- if (variant === "nav" && isActive) {
65
- classes += " bg-indigo-600 dark:bg-indigo-500 hover:bg-indigo-700 dark:hover:bg-indigo-600 text-white shadow-lg scale-105";
66
- }
67
- if (variant === "nav" && !isActive) {
68
- classes += " hover:bg-white dark:hover:bg-gray-700 hover:shadow-lg";
96
+ const sizeCls = variant === "icon" ? SIZE_ICON_PAD[size] : variant === "nav" || variant === "link" || variant === "custom" ? "" : SIZE_PAD[size];
97
+ const defaultShape = variant === "icon" ? "pill" : "rounded";
98
+ const shapeCls = variant === "link" || variant === "custom" ? "" : SHAPE_CLASS[shape ?? defaultShape];
99
+ let stateCls = "";
100
+ if (variant === "nav") {
101
+ stateCls = isActive ? "bg-indigo-600 dark:bg-indigo-500 hover:bg-indigo-700 dark:hover:bg-indigo-600 text-white shadow-lg scale-105" : "hover:bg-white dark:hover:bg-gray-700";
69
102
  }
70
103
  if (variant === "toggle") {
71
- if (isActive) {
72
- classes += " bg-indigo-600 text-white border-indigo-600/30 dark:border-indigo-500/30 hover:bg-indigo-700";
73
- } else {
74
- classes += " bg-gray-200 dark:bg-gray-700 text-gray-700 dark:text-gray-300 border-gray-300 dark:border-gray-600 hover:bg-gray-300 dark:hover:bg-gray-600 hover:border-gray-400 dark:hover:border-gray-500";
75
- }
104
+ stateCls = isActive ? "bg-indigo-600 text-white border-indigo-600/30 dark:border-indigo-500/30 hover:bg-indigo-700" : "bg-gray-200 dark:bg-gray-700 text-gray-700 dark:text-gray-300 border-gray-300 dark:border-gray-600 hover:bg-gray-300 dark:hover:bg-gray-600";
76
105
  }
77
- return /* @__PURE__ */ jsx(
78
- "button",
79
- {
80
- className: classes,
81
- disabled: disabled || isLoading,
82
- ...props,
83
- children: isLoading ? /* @__PURE__ */ jsxs(Fragment, { children: [
84
- /* @__PURE__ */ jsx(AnimateSpin, { className: "h-5 w-5 mr-2 inline-block text-current" }),
85
- loadingText || "Cargando..."
86
- ] }) : children
87
- }
88
- );
106
+ const classes = [
107
+ BASE,
108
+ VARIANT_STYLE[variant],
109
+ sizeCls,
110
+ shapeCls,
111
+ stateCls,
112
+ fullWidth ? "w-full justify-center" : "",
113
+ className
114
+ ].filter(Boolean).join(" ");
115
+ return /* @__PURE__ */ jsx("button", { className: classes, disabled: disabled || isLoading, ...props, children: isLoading ? /* @__PURE__ */ jsxs(Fragment, { children: [
116
+ /* @__PURE__ */ jsx(AnimateSpin, { className: "h-4 w-4 shrink-0 text-current" }),
117
+ loadingText ?? "Cargando..."
118
+ ] }) : /* @__PURE__ */ jsxs(Fragment, { children: [
119
+ leftIcon && /* @__PURE__ */ jsx("span", { className: "shrink-0", children: leftIcon }),
120
+ children,
121
+ rightIcon && /* @__PURE__ */ jsx("span", { className: "shrink-0", children: rightIcon })
122
+ ] }) });
123
+ };
124
+ var SIZE_CLASSES = {
125
+ sm: "px-2.5 py-1.5 text-xs",
126
+ md: "px-3 py-2 text-sm",
127
+ lg: "px-4 py-2.5 text-base"
128
+ };
129
+ var VARIANT_CLASSES = {
130
+ default: "border border-gray-300 dark:border-gray-600 bg-white dark:bg-gray-800",
131
+ outline: "border-2 border-indigo-300 dark:border-indigo-600 bg-transparent",
132
+ filled: "border border-gray-300 dark:border-gray-600 bg-gray-100 dark:bg-gray-700",
133
+ minimal: "border-0 border-b border-gray-300 dark:border-gray-600 bg-transparent rounded-none focus:ring-0"
89
134
  };
90
135
  var Input = ({
91
136
  label,
@@ -93,34 +138,63 @@ var Input = ({
93
138
  helperText,
94
139
  icon,
95
140
  iconSide = "left",
141
+ variant = "default",
142
+ size = "md",
143
+ prefix,
144
+ suffix,
145
+ clearable = false,
146
+ onClear,
96
147
  className = "",
97
148
  id,
98
149
  type,
99
150
  ...props
100
151
  }) => {
101
152
  const inputId = id || `input-${Math.random().toString(36).substring(2, 9)}`;
102
- const baseClasses = "appearance-none relative block w-full px-3 py-2 border placeholder-gray-500 dark:placeholder-gray-400 text-gray-900 dark:text-white bg-white dark:bg-gray-800 rounded-md focus:outline-none focus:ring-2 focus:ring-indigo-500 dark:focus:ring-indigo-400 focus:border-indigo-500 focus:z-10 sm:text-sm disabled:opacity-50 disabled:cursor-not-allowed transition-colors duration-200";
103
- const errorClasses = error ? "border-red-300 dark:border-red-600 focus:ring-red-500 dark:focus:ring-red-400 focus:border-red-500" : "border-gray-300 dark:border-gray-600";
104
- const iconPaddingLeft = icon && iconSide === "left" ? "pl-9" : "";
105
- const iconPaddingRight = icon && iconSide === "right" ? "pr-9" : "";
106
- const classes = `${baseClasses} ${errorClasses} ${iconPaddingLeft} ${iconPaddingRight} ${className}`.trim();
107
- const toggleShape = type === "radio" ? "rounded-full" : "rounded";
108
- const toggleBaseClasses = `h-4 w-4 ${toggleShape} border border-gray-300 dark:border-gray-600 bg-white dark:bg-gray-800 text-indigo-600 dark:text-indigo-400 focus:outline-none focus:ring-2 focus:ring-indigo-500 dark:focus:ring-indigo-400 focus:ring-offset-2 focus:ring-offset-white dark:focus:ring-offset-gray-900 disabled:opacity-50 disabled:cursor-not-allowed transition-colors duration-200 cursor-pointer`;
109
- const toggleErrorClasses = error ? "border-red-300 dark:border-red-600 focus:ring-red-500 dark:focus:ring-red-400" : "";
110
- const toggleClasses = `${toggleBaseClasses} ${toggleErrorClasses}`.trim();
111
- const fileBaseClasses = "block w-full sm:text-sm text-gray-500 dark:text-gray-400 bg-white dark:bg-gray-800 border rounded-md focus:outline-none focus:ring-2 focus:ring-indigo-500 dark:focus:ring-indigo-400 focus:border-indigo-500 disabled:opacity-50 disabled:cursor-not-allowed transition-colors duration-200 file:mr-4 file:py-2 file:px-4 file:rounded-l-md file:border-0 file:text-sm file:font-medium file:bg-indigo-50 file:text-indigo-700 dark:file:bg-indigo-900/50 dark:file:text-indigo-300 hover:file:bg-indigo-100 dark:hover:file:bg-indigo-800/50 file:transition-colors file:duration-200 file:cursor-pointer";
112
- const fileErrorClasses = error ? "border-red-300 dark:border-red-600 focus:ring-red-500 dark:focus:ring-red-400" : "border-gray-300 dark:border-gray-600";
113
- const fileClasses = `${fileBaseClasses} ${fileErrorClasses} ${className}`.trim();
153
+ const errorCls = error ? "border-red-300 dark:border-red-600 focus:ring-red-500 dark:focus:ring-red-400 focus:border-red-500" : "";
154
+ const showClear = clearable && !props.disabled && props.value !== void 0 && props.value !== "";
155
+ const hasRightSlot = icon && iconSide === "right" || showClear;
156
+ const baseCls = "appearance-none relative block w-full placeholder-gray-500 dark:placeholder-gray-400 text-gray-900 dark:text-white rounded-md focus:outline-none focus:ring-2 focus:ring-indigo-500 dark:focus:ring-indigo-400 focus:border-indigo-500 focus:z-10 disabled:opacity-50 disabled:cursor-not-allowed transition-colors duration-200";
157
+ const inputCls = [
158
+ baseCls,
159
+ SIZE_CLASSES[size],
160
+ VARIANT_CLASSES[variant],
161
+ errorCls,
162
+ icon && iconSide === "left" ? "pl-9" : "",
163
+ hasRightSlot ? "pr-9" : "",
164
+ prefix ? "rounded-l-none" : "",
165
+ suffix ? "rounded-r-none" : "",
166
+ className
167
+ ].filter(Boolean).join(" ");
168
+ const toggleCls = [
169
+ `h-4 w-4 ${type === "radio" ? "rounded-full" : "rounded"} border border-gray-300 dark:border-gray-600 bg-white dark:bg-gray-800`,
170
+ "text-indigo-600 dark:text-indigo-400 focus:outline-none focus:ring-2 focus:ring-indigo-500 dark:focus:ring-indigo-400",
171
+ "focus:ring-offset-2 focus:ring-offset-white dark:focus:ring-offset-gray-900",
172
+ "disabled:opacity-50 disabled:cursor-not-allowed transition-colors duration-200 cursor-pointer",
173
+ error ? "border-red-300 dark:border-red-600 focus:ring-red-500 dark:focus:ring-red-400" : ""
174
+ ].filter(Boolean).join(" ");
175
+ const fileCls = [
176
+ "block w-full text-gray-500 dark:text-gray-400 bg-white dark:bg-gray-800 border rounded-md",
177
+ "focus:outline-none focus:ring-2 focus:ring-indigo-500 dark:focus:ring-indigo-400 focus:border-indigo-500",
178
+ "disabled:opacity-50 disabled:cursor-not-allowed transition-colors duration-200",
179
+ "file:mr-4 file:py-2 file:px-4 file:rounded-l-md file:border-0 file:text-sm file:font-medium",
180
+ "file:bg-indigo-50 file:text-indigo-700 dark:file:bg-indigo-900/50 dark:file:text-indigo-300",
181
+ "hover:file:bg-indigo-100 dark:hover:file:bg-indigo-800/50 file:transition-colors file:duration-200 file:cursor-pointer",
182
+ SIZE_CLASSES[size],
183
+ error ? "border-red-300 dark:border-red-600 focus:ring-red-500 dark:focus:ring-red-400" : "border-gray-300 dark:border-gray-600",
184
+ className
185
+ ].filter(Boolean).join(" ");
114
186
  const hasHidden = Boolean(className && /\bhidden\b/.test(className));
115
- const wrapperBase = "space-y-1 w-full";
116
- const wrapperClasses = hasHidden ? `${wrapperBase} hidden` : wrapperBase;
117
- const labelNode = label && (typeof label === "string" ? /* @__PURE__ */ jsx("label", { htmlFor: inputId, className: "block text-sm font-medium text-gray-700 dark:text-gray-300", children: label }) : label);
187
+ const wrapperCls = `space-y-1 w-full${hasHidden ? " hidden" : ""}`;
188
+ const labelNode = label && (typeof label === "string" ? /* @__PURE__ */ jsxs("label", { htmlFor: inputId, className: "block text-sm font-medium text-gray-700 dark:text-gray-300", children: [
189
+ label,
190
+ props.required && /* @__PURE__ */ jsx("span", { className: "ml-1 text-red-500", "aria-hidden": "true", children: "*" })
191
+ ] }) : label);
118
192
  const errorNode = error && /* @__PURE__ */ jsx("p", { className: "text-sm text-red-600 dark:text-red-400", role: "alert", children: error });
119
193
  const helperNode = helperText && !error && /* @__PURE__ */ jsx("p", { className: "text-sm text-gray-500 dark:text-gray-400", children: helperText });
120
194
  if (type === "checkbox" || type === "radio") {
121
- return /* @__PURE__ */ jsxs("div", { className: wrapperClasses, children: [
195
+ return /* @__PURE__ */ jsxs("div", { className: wrapperCls, children: [
122
196
  /* @__PURE__ */ jsxs("div", { className: "flex items-center space-x-2", children: [
123
- /* @__PURE__ */ jsx("input", { id: inputId, type, className: toggleClasses, ...props }),
197
+ /* @__PURE__ */ jsx("input", { id: inputId, type, className: toggleCls, ...props }),
124
198
  labelNode
125
199
  ] }),
126
200
  errorNode,
@@ -128,63 +202,108 @@ var Input = ({
128
202
  ] });
129
203
  }
130
204
  if (type === "file") {
131
- return /* @__PURE__ */ jsxs("div", { className: wrapperClasses, children: [
205
+ return /* @__PURE__ */ jsxs("div", { className: wrapperCls, children: [
132
206
  labelNode,
133
- /* @__PURE__ */ jsx("input", { id: inputId, type: "file", className: fileClasses, ...props }),
207
+ /* @__PURE__ */ jsx("input", { id: inputId, type: "file", className: fileCls, ...props }),
134
208
  errorNode,
135
209
  helperNode
136
210
  ] });
137
211
  }
138
- return /* @__PURE__ */ jsxs("div", { className: wrapperClasses, children: [
212
+ const prefixBorderCls = error ? "border-red-300 dark:border-red-600" : "border-gray-300 dark:border-gray-600";
213
+ return /* @__PURE__ */ jsxs("div", { className: wrapperCls, children: [
139
214
  labelNode,
140
- /* @__PURE__ */ jsxs("div", { className: "relative", children: [
141
- icon && iconSide === "left" && /* @__PURE__ */ jsx("div", { className: "pointer-events-none absolute inset-y-0 left-0 z-10 flex items-center pl-3 text-gray-400 dark:text-gray-500", children: icon }),
142
- /* @__PURE__ */ jsx("input", { id: inputId, className: classes, type, ...props }),
143
- icon && iconSide === "right" && /* @__PURE__ */ jsx("div", { className: "pointer-events-none absolute inset-y-0 right-0 z-10 flex items-center pr-3 text-gray-400 dark:text-gray-500", children: icon })
215
+ /* @__PURE__ */ jsxs("div", { className: "flex", children: [
216
+ prefix && /* @__PURE__ */ jsx("span", { className: `inline-flex shrink-0 items-center px-3 border border-r-0 ${prefixBorderCls} bg-gray-50 dark:bg-gray-700 text-gray-500 dark:text-gray-400 rounded-l-md text-sm`, children: prefix }),
217
+ /* @__PURE__ */ jsxs("div", { className: "relative flex-1", children: [
218
+ icon && iconSide === "left" && /* @__PURE__ */ jsx("div", { className: "pointer-events-none absolute inset-y-0 left-0 z-10 flex items-center pl-3 text-gray-400 dark:text-gray-500", children: icon }),
219
+ /* @__PURE__ */ jsx("input", { id: inputId, className: inputCls, type, ...props }),
220
+ icon && iconSide === "right" && !showClear && /* @__PURE__ */ jsx("div", { className: "pointer-events-none absolute inset-y-0 right-0 z-10 flex items-center pr-3 text-gray-400 dark:text-gray-500", children: icon }),
221
+ showClear && /* @__PURE__ */ jsx(
222
+ "button",
223
+ {
224
+ type: "button",
225
+ onClick: onClear,
226
+ tabIndex: -1,
227
+ "aria-label": "Limpiar",
228
+ className: "absolute inset-y-0 right-0 z-10 flex items-center pr-3 text-gray-400 dark:text-gray-500 hover:text-gray-600 dark:hover:text-gray-300",
229
+ children: /* @__PURE__ */ jsx(CloseIcon, { className: "w-4 h-4" })
230
+ }
231
+ )
232
+ ] }),
233
+ suffix && /* @__PURE__ */ jsx("span", { className: `inline-flex shrink-0 items-center px-3 border border-l-0 ${prefixBorderCls} bg-gray-50 dark:bg-gray-700 text-gray-500 dark:text-gray-400 rounded-r-md text-sm`, children: suffix })
144
234
  ] }),
145
235
  errorNode,
146
236
  helperNode
147
237
  ] });
148
238
  };
239
+ var SIZE_CLASSES2 = {
240
+ small: "px-2 py-1 text-xs",
241
+ medium: "px-3 py-2 text-sm",
242
+ large: "px-4 py-3 text-base"
243
+ };
244
+ var VARIANT_CLASSES2 = {
245
+ default: "border border-gray-300 dark:border-gray-600 bg-white dark:bg-gray-800",
246
+ outline: "border-2 border-indigo-300 dark:border-indigo-600 bg-transparent",
247
+ filled: "border border-gray-300 dark:border-gray-600 bg-gray-100 dark:bg-gray-700",
248
+ minimal: "border-0 border-b border-gray-300 dark:border-gray-600 bg-transparent rounded-none focus:ring-0"
249
+ };
250
+ var RESIZE_CLASSES = {
251
+ vertical: "resize-y",
252
+ horizontal: "resize-x",
253
+ both: "resize",
254
+ none: "resize-none"
255
+ };
149
256
  var TextArea = ({
150
257
  label,
151
258
  error,
152
259
  helperText,
153
260
  variant = "default",
154
261
  size = "medium",
262
+ autoResize = false,
263
+ showCount = false,
264
+ resize = "vertical",
155
265
  className = "",
156
266
  id,
267
+ onInput: propsOnInput,
157
268
  ...props
158
269
  }) => {
159
270
  const textAreaId = id || `textarea-${Math.random().toString(36).substring(2, 9)}`;
160
- const sizeClasses = {
161
- small: "px-2 py-1 text-xs",
162
- medium: "px-3 py-2 text-sm",
163
- large: "px-4 py-3 text-base"
271
+ const textareaRef = useRef(null);
272
+ const adjustHeight = () => {
273
+ const el = textareaRef.current;
274
+ if (!el) return;
275
+ el.style.height = "auto";
276
+ el.style.height = `${el.scrollHeight}px`;
164
277
  };
165
- const variantClasses = {
166
- default: "border-gray-300 dark:border-gray-600 bg-white dark:bg-gray-800",
167
- outline: "border-2 border-indigo-300 dark:border-indigo-600 bg-transparent",
168
- filled: "border-gray-300 dark:border-gray-600 bg-gray-100 dark:bg-gray-700",
169
- minimal: "border-0 bg-transparent focus:ring-0 focus:border-0"
278
+ useEffect(() => {
279
+ if (autoResize) adjustHeight();
280
+ }, [autoResize, props.value]);
281
+ const handleInput = (e) => {
282
+ if (autoResize) adjustHeight();
283
+ propsOnInput?.(e);
170
284
  };
171
- const baseClasses = "appearance-none relative block w-full placeholder-gray-500 dark:placeholder-gray-400 text-gray-900 dark:text-white rounded-md border focus:outline-none focus:ring-2 focus:ring-indigo-500 dark:focus:ring-indigo-400 focus:border-indigo-500 focus:z-10 disabled:opacity-50 disabled:cursor-not-allowed transition-colors duration-200 resize-y";
172
- const errorClasses = error ? "border-red-300 dark:border-red-600 focus:ring-red-500 dark:focus:ring-red-400 focus:border-red-500" : "";
173
- const classes = `${baseClasses} ${sizeClasses[size]} ${variantClasses[variant]} ${errorClasses} ${className}`;
285
+ const baseCls = "appearance-none relative block w-full placeholder-gray-500 dark:placeholder-gray-400 text-gray-900 dark:text-white rounded-md border focus:outline-none focus:ring-2 focus:ring-indigo-500 dark:focus:ring-indigo-400 focus:border-indigo-500 focus:z-10 disabled:opacity-50 disabled:cursor-not-allowed transition-colors duration-200";
286
+ const errorCls = error ? "border-red-300 dark:border-red-600 focus:ring-red-500 dark:focus:ring-red-400 focus:border-red-500" : "";
287
+ const resizeCls = autoResize ? "resize-none overflow-hidden" : RESIZE_CLASSES[resize];
288
+ const classes = [baseCls, SIZE_CLASSES2[size], VARIANT_CLASSES2[variant], errorCls, resizeCls, className].filter(Boolean).join(" ");
289
+ const maxLength = typeof props.maxLength === "number" ? props.maxLength : void 0;
290
+ const currentLength = typeof props.value === "string" ? props.value.length : typeof props.value === "number" ? String(props.value).length : 0;
291
+ const overLimit = maxLength !== void 0 && currentLength > maxLength;
174
292
  return /* @__PURE__ */ jsxs("div", { className: "space-y-1 w-full", children: [
175
- label && typeof label === "string" ? /* @__PURE__ */ jsx(
176
- "label",
177
- {
178
- htmlFor: textAreaId,
179
- className: "block text-sm font-medium text-gray-700 dark:text-gray-300",
180
- children: label
181
- }
182
- ) : label,
293
+ (label || showCount) && /* @__PURE__ */ jsxs("div", { className: "flex items-baseline gap-2", children: [
294
+ /* @__PURE__ */ jsx("div", { className: "flex-1", children: label && (typeof label === "string" ? /* @__PURE__ */ jsxs("label", { htmlFor: textAreaId, className: "block text-sm font-medium text-gray-700 dark:text-gray-300", children: [
295
+ label,
296
+ props.required && /* @__PURE__ */ jsx("span", { className: "ml-1 text-red-500", "aria-hidden": "true", children: "*" })
297
+ ] }) : label) }),
298
+ showCount && /* @__PURE__ */ jsx("span", { className: `text-xs shrink-0 tabular-nums ${overLimit ? "text-red-500" : "text-gray-400 dark:text-gray-500"}`, children: maxLength ? `${currentLength} / ${maxLength}` : currentLength })
299
+ ] }),
183
300
  /* @__PURE__ */ jsx(
184
301
  "textarea",
185
302
  {
303
+ ref: textareaRef,
186
304
  id: textAreaId,
187
305
  className: classes,
306
+ onInput: handleInput,
188
307
  ...props
189
308
  }
190
309
  ),
@@ -192,80 +311,125 @@ var TextArea = ({
192
311
  helperText && !error && /* @__PURE__ */ jsx("p", { className: "text-sm text-gray-500 dark:text-gray-400", children: helperText })
193
312
  ] });
194
313
  };
195
- var Form = ({ onSubmit, children, variant = "default", className = "", ...props }) => {
314
+ var Form = ({
315
+ onSubmit,
316
+ children,
317
+ variant = "default",
318
+ columns,
319
+ className = "",
320
+ style,
321
+ ...props
322
+ }) => {
196
323
  const handleSubmit = (e) => {
197
324
  e.preventDefault();
198
- if (onSubmit) {
199
- onSubmit(e);
200
- }
325
+ onSubmit?.(e);
201
326
  };
327
+ const hasGrid = columns !== void 0 && columns > 1;
202
328
  const getVariantClasses = () => {
203
329
  switch (variant) {
204
330
  case "modal":
205
331
  return "flex-1 px-6 py-4 overflow-y-auto";
206
332
  case "card":
207
- return "p-6 space-y-6";
333
+ return `bg-white dark:bg-gray-800 border border-gray-200 dark:border-gray-700 rounded-xl shadow-sm p-6${hasGrid ? "" : " space-y-6"}`;
208
334
  case "inline":
209
- return "flex flex-wrap gap-4 items-end";
335
+ return hasGrid ? "" : "flex flex-wrap gap-4 items-end";
210
336
  case "compact":
211
- return "space-y-3";
337
+ return hasGrid ? "" : "space-y-3";
212
338
  case "default":
213
339
  default:
214
- return "space-y-4";
340
+ return hasGrid ? "" : "space-y-4";
215
341
  }
216
342
  };
217
- const combinedClassName = `${getVariantClasses()} ${className}`.trim();
218
- return /* @__PURE__ */ jsx("form", { onSubmit: handleSubmit, className: combinedClassName, ...props, children });
343
+ const gridStyle = hasGrid ? { display: "grid", gridTemplateColumns: `repeat(${columns}, minmax(0, 1fr))`, gap: "1rem" } : {};
344
+ const combinedClassName = [getVariantClasses(), className].filter(Boolean).join(" ");
345
+ const combinedStyle = { ...gridStyle, ...style };
346
+ return /* @__PURE__ */ jsx(
347
+ "form",
348
+ {
349
+ onSubmit: handleSubmit,
350
+ className: combinedClassName,
351
+ style: Object.keys(combinedStyle).length > 0 ? combinedStyle : void 0,
352
+ ...props,
353
+ children
354
+ }
355
+ );
356
+ };
357
+ var SIZE_CLASSES3 = {
358
+ sm: "py-1.5 text-xs",
359
+ md: "py-2 text-sm",
360
+ lg: "py-2.5 text-base"
361
+ };
362
+ var VARIANT_CLASSES3 = {
363
+ default: "border border-gray-300 dark:border-gray-600 bg-white dark:bg-gray-800",
364
+ outline: "border-2 border-indigo-300 dark:border-indigo-600 bg-transparent",
365
+ filled: "border border-gray-300 dark:border-gray-600 bg-gray-100 dark:bg-gray-700",
366
+ minimal: "border-0 border-b border-gray-300 dark:border-gray-600 bg-transparent rounded-none focus:ring-0",
367
+ custom: ""
219
368
  };
220
369
  var Select = ({
221
370
  options,
222
371
  placeholder,
223
372
  variant = "default",
373
+ size = "md",
224
374
  error = false,
225
375
  helperText,
226
376
  label,
377
+ icon,
227
378
  className = "",
228
379
  id,
229
380
  ...props
230
381
  }) => {
231
382
  const selectId = id || `select-${Math.random().toString(36).substring(2, 9)}`;
232
- const getVariantClasses = () => {
233
- const baseClasses = "appearance-none relative block w-full px-3 py-2 border placeholder-gray-500 dark:placeholder-gray-400 text-gray-900 dark:text-white bg-white dark:bg-gray-800 rounded-md focus:outline-none focus:ring-2 focus:ring-indigo-500 dark:focus:ring-indigo-400 focus:border-indigo-500 focus:z-10 sm:text-sm disabled:opacity-50 disabled:cursor-not-allowed transition-colors duration-200";
234
- if (variant === "small") {
235
- return `${baseClasses.replace("px-3 py-2", "px-2.5 py-1.5 text-sm")} border-gray-300 dark:border-gray-600`;
236
- }
237
- return `${baseClasses} border-gray-300 dark:border-gray-600 ${error ? "border-red-300 dark:border-red-600 focus:ring-red-500 dark:focus:ring-red-400 focus:border-red-500" : ""}`;
238
- };
239
- const getOptionClasses = (option) => {
240
- return `bg-white dark:bg-gray-800 text-gray-900 dark:text-white py-2 ${option.disabled ? "opacity-50 cursor-not-allowed" : ""}`;
241
- };
242
- const combinedClassName = `${getVariantClasses()} ${className}`.trim();
383
+ const effectiveSize = variant === "small" ? "sm" : size;
384
+ const effectiveVariant = variant === "small" ? "default" : variant;
385
+ const hasError = Boolean(error);
386
+ const errorMsg = typeof error === "string" ? error : "";
387
+ const computedDefaultValue = props.value === void 0 && props.defaultValue === void 0 ? options.find((o) => o.selected)?.value?.toString() : void 0;
388
+ const baseCls = "appearance-none relative block w-full pl-3 pr-9 placeholder-gray-500 dark:placeholder-gray-400 text-gray-900 dark:text-white rounded-md focus:outline-none focus:ring-2 focus:ring-indigo-500 dark:focus:ring-indigo-400 focus:border-indigo-500 focus:z-10 disabled:opacity-50 disabled:cursor-not-allowed transition-colors duration-200";
389
+ const errorCls = hasError ? "border-red-300 dark:border-red-600 focus:ring-red-500 dark:focus:ring-red-400 focus:border-red-500" : "";
390
+ const selectCls = [
391
+ baseCls,
392
+ SIZE_CLASSES3[effectiveSize],
393
+ VARIANT_CLASSES3[effectiveVariant],
394
+ errorCls,
395
+ icon ? "pl-9" : "",
396
+ className
397
+ ].filter(Boolean).join(" ");
243
398
  return /* @__PURE__ */ jsxs("div", { className: "space-y-1 w-full", children: [
244
- label && typeof label === "string" ? /* @__PURE__ */ jsx("label", { htmlFor: selectId, className: "block text-sm font-medium text-gray-700 dark:text-gray-300", children: label }) : label,
245
- /* @__PURE__ */ jsxs("select", { id: selectId, className: combinedClassName, ...props, children: [
246
- placeholder && placeholder.trim() && /* @__PURE__ */ jsx("option", { value: "", disabled: true, selected: true, className: "bg-white dark:bg-gray-800 text-gray-500 dark:text-gray-400 py-2", children: placeholder }),
247
- options.map((option) => /* @__PURE__ */ jsx(
248
- "option",
399
+ label && (typeof label === "string" ? /* @__PURE__ */ jsxs("label", { htmlFor: selectId, className: "block text-sm font-medium text-gray-700 dark:text-gray-300", children: [
400
+ label,
401
+ props.required && /* @__PURE__ */ jsx("span", { className: "ml-1 text-red-500", "aria-hidden": "true", children: "*" })
402
+ ] }) : label),
403
+ /* @__PURE__ */ jsxs("div", { className: "relative", children: [
404
+ icon && /* @__PURE__ */ jsx("div", { className: "pointer-events-none absolute inset-y-0 left-0 z-10 flex items-center pl-3 text-gray-400 dark:text-gray-500", children: icon }),
405
+ /* @__PURE__ */ jsxs(
406
+ "select",
249
407
  {
250
- value: option.value,
251
- disabled: option.disabled,
252
- selected: option.selected,
253
- className: getOptionClasses(option),
254
- children: option.label
255
- },
256
- option.value
257
- ))
408
+ id: selectId,
409
+ className: selectCls,
410
+ defaultValue: computedDefaultValue,
411
+ ...props,
412
+ children: [
413
+ placeholder && /* @__PURE__ */ jsx("option", { value: "", disabled: true, className: "bg-white dark:bg-gray-800 text-gray-500 dark:text-gray-400", children: placeholder }),
414
+ options.map((option) => /* @__PURE__ */ jsx(
415
+ "option",
416
+ {
417
+ value: option.value,
418
+ disabled: option.disabled,
419
+ className: `bg-white dark:bg-gray-800 text-gray-900 dark:text-white${option.disabled ? " opacity-50" : ""}`,
420
+ children: option.label
421
+ },
422
+ option.value
423
+ ))
424
+ ]
425
+ }
426
+ ),
427
+ /* @__PURE__ */ jsx("div", { className: "pointer-events-none absolute inset-y-0 right-0 flex items-center pr-2.5 text-gray-400 dark:text-gray-500", children: /* @__PURE__ */ jsx(ChevronDownIcon, { className: "w-4 h-4" }) })
258
428
  ] }),
259
- helperText && /* @__PURE__ */ jsx("p", { className: `text-sm ${error ? "text-red-600 dark:text-red-400" : "text-gray-500 dark:text-gray-400"}`, children: helperText })
429
+ errorMsg && /* @__PURE__ */ jsx("p", { className: "text-sm text-red-600 dark:text-red-400", role: "alert", children: errorMsg }),
430
+ helperText && !errorMsg && /* @__PURE__ */ jsx("p", { className: `text-sm ${hasError ? "text-red-600 dark:text-red-400" : "text-gray-500 dark:text-gray-400"}`, children: helperText })
260
431
  ] });
261
432
  };
262
- function isColumnDef(col) {
263
- return typeof col === "object" && col !== null && "header" in col;
264
- }
265
- function resolveColumn(col) {
266
- if (isColumnDef(col)) return col;
267
- return { header: col };
268
- }
269
433
  var ALIGN_CLASS = {
270
434
  left: "text-left",
271
435
  center: "text-center",
@@ -286,6 +450,10 @@ var VARIANT_TABLE = {
286
450
  striped: "w-full min-w-full table-auto",
287
451
  bordered: "w-full min-w-full table-auto border border-gray-300 dark:border-gray-600",
288
452
  minimal: "w-full min-w-full table-auto",
453
+ ghost: "w-full min-w-full table-auto",
454
+ card: "w-full min-w-full table-auto",
455
+ accent: "w-full min-w-full table-auto",
456
+ dark: "w-full min-w-full table-auto",
289
457
  custom: "w-full min-w-full table-auto"
290
458
  };
291
459
  var VARIANT_THEAD = {
@@ -293,6 +461,10 @@ var VARIANT_THEAD = {
293
461
  striped: "bg-gray-100 dark:bg-gray-700",
294
462
  bordered: "bg-gray-100 dark:bg-gray-700",
295
463
  minimal: "",
464
+ ghost: "",
465
+ card: "bg-gray-50 dark:bg-gray-800/80",
466
+ accent: "bg-blue-600 dark:bg-blue-700",
467
+ dark: "bg-gray-800 dark:bg-gray-900",
296
468
  custom: ""
297
469
  };
298
470
  var VARIANT_TH = {
@@ -300,13 +472,43 @@ var VARIANT_TH = {
300
472
  striped: "font-semibold uppercase tracking-wider text-gray-600 dark:text-gray-300",
301
473
  bordered: "font-semibold uppercase tracking-wider text-gray-600 dark:text-gray-300 border border-gray-300 dark:border-gray-600",
302
474
  minimal: "font-semibold text-gray-500 dark:text-gray-400 border-b border-gray-200 dark:border-gray-700",
475
+ ghost: "font-semibold text-gray-600 dark:text-gray-400 border-b-2 border-gray-300 dark:border-gray-600",
476
+ card: "font-semibold text-gray-600 dark:text-gray-300 border-b border-gray-200 dark:border-gray-700",
477
+ accent: "font-semibold uppercase tracking-wider text-white",
478
+ dark: "font-semibold uppercase tracking-wider text-gray-100",
479
+ custom: ""
480
+ };
481
+ var VARIANT_TR_BASE = {
482
+ default: "bg-white dark:bg-gray-800",
483
+ striped: "",
484
+ bordered: "bg-white dark:bg-gray-800",
485
+ minimal: "",
486
+ ghost: "",
487
+ card: "bg-white dark:bg-gray-900",
488
+ accent: "bg-white dark:bg-gray-800",
489
+ dark: "bg-white dark:bg-gray-800",
490
+ custom: ""
491
+ };
492
+ var VARIANT_TR_HOVER = {
493
+ default: "hover:bg-gray-50 dark:hover:bg-gray-700/60",
494
+ striped: "hover:bg-blue-50 dark:hover:bg-blue-900/20",
495
+ bordered: "hover:bg-gray-50 dark:hover:bg-gray-700/60",
496
+ minimal: "hover:bg-gray-50 dark:hover:bg-gray-800/60",
497
+ ghost: "hover:bg-gray-50/70 dark:hover:bg-white/5",
498
+ card: "hover:bg-gray-50 dark:hover:bg-gray-800/50",
499
+ accent: "hover:bg-blue-50 dark:hover:bg-blue-900/20",
500
+ dark: "hover:bg-gray-50 dark:hover:bg-gray-700/60",
303
501
  custom: ""
304
502
  };
305
- var VARIANT_TR = {
306
- default: () => "bg-white dark:bg-gray-800 hover:bg-gray-50 dark:hover:bg-gray-700/60 transition-colors",
307
- striped: (i) => `${i % 2 === 0 ? "bg-white dark:bg-gray-800" : "bg-gray-50 dark:bg-gray-700/40"} hover:bg-blue-50 dark:hover:bg-blue-900/20 transition-colors`,
308
- bordered: () => "bg-white dark:bg-gray-800 hover:bg-gray-50 dark:hover:bg-gray-700/60 transition-colors",
309
- minimal: () => "hover:bg-gray-50 dark:hover:bg-gray-800/60 transition-colors",
503
+ var VARIANT_TR_STRIPE = {
504
+ default: () => "",
505
+ striped: (i) => i % 2 === 0 ? "bg-white dark:bg-gray-800" : "bg-gray-50 dark:bg-gray-700/40",
506
+ bordered: () => "",
507
+ minimal: () => "",
508
+ ghost: () => "",
509
+ card: () => "",
510
+ accent: () => "",
511
+ dark: () => "",
310
512
  custom: () => ""
311
513
  };
312
514
  var VARIANT_TD = {
@@ -314,6 +516,10 @@ var VARIANT_TD = {
314
516
  striped: "text-gray-700 dark:text-gray-300",
315
517
  bordered: "text-gray-700 dark:text-gray-300 border border-gray-200 dark:border-gray-700",
316
518
  minimal: "text-gray-700 dark:text-gray-300 border-b border-gray-100 dark:border-gray-800",
519
+ ghost: "text-gray-700 dark:text-gray-300",
520
+ card: "text-gray-700 dark:text-gray-300",
521
+ accent: "text-gray-700 dark:text-gray-300",
522
+ dark: "text-gray-700 dark:text-gray-300",
317
523
  custom: ""
318
524
  };
319
525
  var VARIANT_TBODY_DIVIDER = {
@@ -321,8 +527,33 @@ var VARIANT_TBODY_DIVIDER = {
321
527
  striped: "",
322
528
  bordered: "",
323
529
  minimal: "",
530
+ ghost: "divide-y divide-gray-200 dark:divide-gray-700",
531
+ card: "divide-y divide-gray-100 dark:divide-gray-800",
532
+ accent: "divide-y divide-gray-200 dark:divide-gray-700",
533
+ dark: "divide-y divide-gray-200 dark:divide-gray-700",
324
534
  custom: ""
325
535
  };
536
+ function SortIcon({ direction }) {
537
+ if (direction === "asc") return /* @__PURE__ */ jsx(SortAscIcon, { className: "inline-block ml-1 w-3 h-3 shrink-0" });
538
+ if (direction === "desc") return /* @__PURE__ */ jsx(SortDescIcon, { className: "inline-block ml-1 w-3 h-3 shrink-0" });
539
+ return /* @__PURE__ */ jsx(SortBothIcon, { className: "inline-block ml-1 w-3 h-3 shrink-0 opacity-40" });
540
+ }
541
+ function SkeletonRow({ colCount, size }) {
542
+ return /* @__PURE__ */ jsx("tr", { children: Array.from({ length: colCount }).map((_, i) => /* @__PURE__ */ jsx("td", { className: SIZE_TD[size], children: /* @__PURE__ */ jsx("div", { className: "h-4 rounded bg-gray-200 dark:bg-gray-700 animate-pulse" }) }, i)) });
543
+ }
544
+ function isColumnDef(col) {
545
+ return typeof col === "object" && col !== null && "header" in col;
546
+ }
547
+ function resolveColumn(col) {
548
+ if (isColumnDef(col)) return col;
549
+ return { header: col };
550
+ }
551
+ function colSizeStyle(col) {
552
+ const s = {};
553
+ if (col.width !== void 0) s.width = col.width;
554
+ if (col.minWidth !== void 0) s.minWidth = col.minWidth;
555
+ return s;
556
+ }
326
557
  function Table({
327
558
  columns,
328
559
  rows,
@@ -336,46 +567,84 @@ function Table({
336
567
  emptyState,
337
568
  onRowClick,
338
569
  hideHeader = false,
339
- style
570
+ style,
571
+ stickyHeader = false,
572
+ caption,
573
+ footerRows,
574
+ loading = false,
575
+ loadingRows = 4,
576
+ getRowStyle,
577
+ rounded = false,
578
+ shadow = false,
579
+ hoverable = true,
580
+ sortState,
581
+ onSort
340
582
  }) {
341
583
  const cols = columns.map(resolveColumn);
342
584
  const resolvedTrClass = (i) => {
343
- const variantCls = VARIANT_TR[variant](i);
585
+ const stripeCls = VARIANT_TR_STRIPE[variant](i);
586
+ const baseCls = stripeCls || VARIANT_TR_BASE[variant];
587
+ const hoverCls = hoverable ? `${VARIANT_TR_HOVER[variant]} transition-colors` : "";
344
588
  const clickCls = onRowClick ? "cursor-pointer" : "";
345
589
  const customCls = typeof trClassName === "function" ? trClassName(i) : trClassName ?? "";
346
- return `${variantCls} ${clickCls} ${customCls}`.trim();
590
+ return [baseCls, hoverCls, clickCls, customCls].filter(Boolean).join(" ");
347
591
  };
348
- return /* @__PURE__ */ jsx("div", { className: `overflow-x-auto w-full ${className}`.trim(), children: /* @__PURE__ */ jsxs(
592
+ const wrapperCls = [
593
+ "overflow-x-auto w-full",
594
+ rounded ? "rounded-lg overflow-hidden" : "",
595
+ shadow ? "shadow-md" : "",
596
+ className
597
+ ].filter(Boolean).join(" ");
598
+ const theadCls = [
599
+ VARIANT_THEAD[variant],
600
+ stickyHeader ? "sticky top-0 z-20" : ""
601
+ ].filter(Boolean).join(" ");
602
+ const stickyColCls = "sticky left-0 z-10 bg-inherit";
603
+ return /* @__PURE__ */ jsx("div", { className: wrapperCls, children: /* @__PURE__ */ jsxs(
349
604
  "table",
350
605
  {
351
606
  className: `${VARIANT_TABLE[variant]} ${tableClassName}`.trim(),
352
607
  style,
353
608
  children: [
354
- !hideHeader && /* @__PURE__ */ jsx("thead", { className: VARIANT_THEAD[variant], children: /* @__PURE__ */ jsx("tr", { children: cols.map((col, i) => /* @__PURE__ */ jsx(
355
- "th",
356
- {
357
- className: [
358
- SIZE_TH[size],
359
- VARIANT_TH[variant],
360
- ALIGN_CLASS[col.align ?? "left"],
361
- col.className ?? "",
362
- thClassName
363
- ].filter(Boolean).join(" "),
364
- children: col.header
365
- },
366
- i
367
- )) }) }),
368
- /* @__PURE__ */ jsx("tbody", { className: VARIANT_TBODY_DIVIDER[variant], children: rows.length === 0 ? /* @__PURE__ */ jsx("tr", { children: /* @__PURE__ */ jsx(
609
+ caption && /* @__PURE__ */ jsx("caption", { className: "mb-2 text-left text-sm text-gray-500 dark:text-gray-400", children: caption }),
610
+ !hideHeader && /* @__PURE__ */ jsx("thead", { className: theadCls, children: /* @__PURE__ */ jsx("tr", { children: cols.map((col, i) => {
611
+ const isSortable = col.sortable && col.key;
612
+ const activeSort = sortState && col.key && sortState.key === col.key ? sortState.direction : null;
613
+ return /* @__PURE__ */ jsxs(
614
+ "th",
615
+ {
616
+ scope: "col",
617
+ className: [
618
+ SIZE_TH[size],
619
+ VARIANT_TH[variant],
620
+ ALIGN_CLASS[col.align ?? "left"],
621
+ col.className ?? "",
622
+ thClassName,
623
+ col.sticky ? stickyColCls : "",
624
+ isSortable ? "cursor-pointer select-none" : ""
625
+ ].filter(Boolean).join(" "),
626
+ style: { ...colSizeStyle(col), ...col.thStyle ?? {} },
627
+ onClick: isSortable ? () => onSort?.(col.key) : void 0,
628
+ children: [
629
+ col.header,
630
+ isSortable && /* @__PURE__ */ jsx(SortIcon, { direction: activeSort })
631
+ ]
632
+ },
633
+ i
634
+ );
635
+ }) }) }),
636
+ /* @__PURE__ */ jsx("tbody", { className: VARIANT_TBODY_DIVIDER[variant], children: loading ? Array.from({ length: loadingRows }).map((_, i) => /* @__PURE__ */ jsx(SkeletonRow, { colCount: cols.length, size }, i)) : rows.length === 0 ? /* @__PURE__ */ jsx("tr", { children: /* @__PURE__ */ jsx(
369
637
  "td",
370
638
  {
371
639
  colSpan: cols.length,
372
- className: `${SIZE_TD[size]} text-center text-gray-400 dark:text-gray-500 py-8`,
640
+ className: `${SIZE_TD[size]} py-8 text-center text-gray-400 dark:text-gray-500`,
373
641
  children: emptyState ?? "Sin datos"
374
642
  }
375
643
  ) }) : rows.map((row, rowIndex) => /* @__PURE__ */ jsx(
376
644
  "tr",
377
645
  {
378
646
  className: resolvedTrClass(rowIndex),
647
+ style: getRowStyle?.(rowIndex),
379
648
  onClick: onRowClick ? () => onRowClick(rowIndex) : void 0,
380
649
  children: row.map((cell, cellIndex) => {
381
650
  const col = cols[cellIndex];
@@ -387,8 +656,13 @@ function Table({
387
656
  VARIANT_TD[variant],
388
657
  ALIGN_CLASS[col?.align ?? "left"],
389
658
  col?.className ?? "",
390
- tdClassName
659
+ tdClassName,
660
+ col?.sticky ? stickyColCls : ""
391
661
  ].filter(Boolean).join(" "),
662
+ style: {
663
+ ...col ? colSizeStyle(col) : {},
664
+ ...col?.tdStyle ?? {}
665
+ },
392
666
  children: cell
393
667
  },
394
668
  cellIndex
@@ -396,47 +670,100 @@ function Table({
396
670
  })
397
671
  },
398
672
  rowIndex
399
- )) })
673
+ )) }),
674
+ footerRows && footerRows.length > 0 && /* @__PURE__ */ jsx("tfoot", { className: "border-t border-gray-200 bg-gray-50 dark:border-gray-700 dark:bg-gray-800/50", children: footerRows.map((row, rowIndex) => /* @__PURE__ */ jsx("tr", { children: row.map((cell, cellIndex) => {
675
+ const col = cols[cellIndex];
676
+ return /* @__PURE__ */ jsx(
677
+ "td",
678
+ {
679
+ className: [
680
+ SIZE_TD[size],
681
+ "font-medium text-gray-700 dark:text-gray-300",
682
+ ALIGN_CLASS[col?.align ?? "left"],
683
+ col?.className ?? "",
684
+ tdClassName
685
+ ].filter(Boolean).join(" "),
686
+ style: col?.tdStyle,
687
+ children: cell
688
+ },
689
+ cellIndex
690
+ );
691
+ }) }, rowIndex)) })
400
692
  ]
401
693
  }
402
694
  ) });
403
695
  }
696
+ var SIZE_CLASS = {
697
+ sm: "max-w-sm",
698
+ md: "max-w-md",
699
+ lg: "max-w-2xl",
700
+ xl: "max-w-4xl",
701
+ full: "max-w-[95vw] w-[95vw]"
702
+ };
703
+ var VARIANT_HEADER = {
704
+ default: "bg-gray-50 dark:bg-gray-800 border-b border-gray-200 dark:border-gray-700",
705
+ danger: "bg-red-50 dark:bg-red-900/30 border-b border-red-200 dark:border-red-800",
706
+ success: "bg-green-50 dark:bg-green-900/30 border-b border-green-200 dark:border-green-800",
707
+ warning: "bg-yellow-50 dark:bg-yellow-900/30 border-b border-yellow-200 dark:border-yellow-800"
708
+ };
709
+ var VARIANT_TITLE = {
710
+ default: "text-gray-900 dark:text-white",
711
+ danger: "text-red-700 dark:text-red-300",
712
+ success: "text-green-700 dark:text-green-300",
713
+ warning: "text-yellow-700 dark:text-yellow-300"
714
+ };
404
715
  var Modal = forwardRef(({
405
716
  onClose,
406
717
  title,
407
718
  children,
408
719
  footer,
409
- maxWidth = "max-w-2xl",
720
+ maxWidth,
721
+ size,
410
722
  showCloseButton = true,
411
- zIndex = 50
723
+ zIndex = 50,
724
+ closeOnBackdrop = false,
725
+ closeOnEsc = false,
726
+ variant = "default"
412
727
  }, ref) => {
413
728
  const [show, setShow] = useState(false);
729
+ const handleCloseRef = useRef(() => {
730
+ });
731
+ const handleClose = () => {
732
+ setShow(false);
733
+ setTimeout(() => onClose(), 300);
734
+ };
735
+ handleCloseRef.current = handleClose;
414
736
  useEffect(() => {
415
737
  setShow(true);
416
738
  }, []);
417
- const handleClose = () => {
418
- setShow(false);
419
- setTimeout(() => {
420
- onClose();
421
- }, 300);
739
+ useEffect(() => {
740
+ if (!closeOnEsc) return;
741
+ const handler = (e) => {
742
+ if (e.key === "Escape") handleCloseRef.current();
743
+ };
744
+ document.addEventListener("keydown", handler);
745
+ return () => document.removeEventListener("keydown", handler);
746
+ }, [closeOnEsc]);
747
+ useImperativeHandle(ref, () => ({ handleClose }));
748
+ const widthCls = size ? SIZE_CLASS[size] : maxWidth ?? "max-w-2xl";
749
+ const handleBackdropClick = (e) => {
750
+ if (closeOnBackdrop && e.target === e.currentTarget) handleClose();
422
751
  };
423
- useImperativeHandle(ref, () => ({
424
- handleClose
425
- }));
426
752
  return /* @__PURE__ */ jsx(
427
753
  "dialog",
428
754
  {
429
755
  open: show,
430
- className: `fixed inset-0 w-full h-full flex items-center justify-center p-4 ${show && "opacity-100"} transition-opacity opacity-0 duration-300 bg-gray-900/60 backdrop-blur-sm`,
756
+ className: `fixed inset-0 w-full h-full flex items-center justify-center p-4 transition-opacity duration-300 bg-gray-900/60 backdrop-blur-sm ${show ? "opacity-100" : "opacity-0"}`,
431
757
  style: { zIndex: zIndex - 10 },
758
+ onClick: handleBackdropClick,
432
759
  children: /* @__PURE__ */ jsxs(
433
760
  "article",
434
761
  {
435
- className: `relative bg-white dark:bg-gray-800 border border-gray-200 dark:border-gray-700 rounded-lg shadow-2xl w-full ${maxWidth} max-h-[90vh] flex flex-col overflow-hidden`,
762
+ className: `relative bg-white dark:bg-gray-800 border border-gray-200 dark:border-gray-700 rounded-lg shadow-2xl w-full ${widthCls} max-h-[90vh] flex flex-col overflow-hidden`,
436
763
  style: { zIndex },
437
764
  children: [
438
- /* @__PURE__ */ jsxs("header", { className: "shrink-0 bg-gray-50 dark:bg-gray-800 border-b border-gray-200 dark:border-gray-700 px-6 py-4 flex items-center justify-between", children: [
439
- /* @__PURE__ */ jsx("h2", { className: "text-2xl font-bold text-gray-900 dark:text-white", children: title }),
765
+ /* @__PURE__ */ jsxs("header", { className: `shrink-0 px-6 py-4 flex items-center justify-between ${VARIANT_HEADER[variant]}`, children: [
766
+ /* @__PURE__ */ jsx("h2", { className: `text-2xl font-bold ${VARIANT_TITLE[variant]}`, children: title }),
440
767
  showCloseButton && /* @__PURE__ */ jsx(
441
768
  Button,
442
769
  {
@@ -461,7 +788,9 @@ var Loading = ({
461
788
  size = "medium",
462
789
  color = "primary",
463
790
  label,
464
- className = ""
791
+ className = "",
792
+ overlay = false,
793
+ fullPage = false
465
794
  }) => {
466
795
  const sizeClasses = {
467
796
  small: "h-4 w-4",
@@ -480,13 +809,14 @@ var Loading = ({
480
809
  const renderIcon = () => {
481
810
  const commonClass = `${sizeClasses[size]} ${colorClasses[color]}`;
482
811
  switch (variant) {
483
- case "dots":
812
+ case "dots": {
484
813
  const dotSize = size === "small" ? "h-1 w-1" : size === "medium" ? "h-2 w-2" : size === "large" ? "h-3 w-3" : "h-4 w-4";
485
814
  return /* @__PURE__ */ jsxs("div", { className: `flex space-x-1 ${colorClasses[color]}`, children: [
486
815
  /* @__PURE__ */ jsx("div", { className: `rounded-full bg-current animate-bounce ${dotSize}`, style: { animationDelay: "0s" } }),
487
816
  /* @__PURE__ */ jsx("div", { className: `rounded-full bg-current animate-bounce ${dotSize}`, style: { animationDelay: "0.15s" } }),
488
817
  /* @__PURE__ */ jsx("div", { className: `rounded-full bg-current animate-bounce ${dotSize}`, style: { animationDelay: "0.3s" } })
489
818
  ] });
819
+ }
490
820
  case "bars":
491
821
  return /* @__PURE__ */ jsxs("div", { className: `flex items-end space-x-1 ${sizeClasses[size]} ${colorClasses[color]}`, children: [
492
822
  /* @__PURE__ */ jsx("div", { className: "w-1/4 bg-current animate-[pulse_1s_ease-in-out_infinite]", style: { height: "60%", animationDelay: "0s" } }),
@@ -518,6 +848,16 @@ var Loading = ({
518
848
  ] });
519
849
  }
520
850
  };
851
+ const inner = /* @__PURE__ */ jsxs("div", { className: `flex flex-col items-center justify-center ${className}`, role: "status", children: [
852
+ renderIcon(),
853
+ label && /* @__PURE__ */ jsx("span", { className: `mt-3 text-sm font-medium ${colorClasses[color]}`, children: label })
854
+ ] });
855
+ if (fullPage) {
856
+ return /* @__PURE__ */ jsx("div", { className: "fixed inset-0 z-50 flex items-center justify-center bg-gray-900/50 backdrop-blur-sm", children: inner });
857
+ }
858
+ if (overlay) {
859
+ return /* @__PURE__ */ jsx("div", { className: "absolute inset-0 z-10 flex items-center justify-center bg-gray-900/40 backdrop-blur-sm rounded-[inherit]", children: inner });
860
+ }
521
861
  return /* @__PURE__ */ jsxs("div", { className: `flex flex-col items-center justify-center w-full h-full min-h-[inherit] ${className}`, role: "status", children: [
522
862
  renderIcon(),
523
863
  label && /* @__PURE__ */ jsx("span", { className: `mt-3 text-sm font-medium ${colorClasses[color]}`, children: label })