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