@axzydev/axzy_ui_system 1.3.2 → 1.3.4

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.
package/dist/index.cjs CHANGED
@@ -338,6 +338,11 @@ function useFloatingPanel(anchorRef, isOpen, {
338
338
 
339
339
  // src/hooks/useTableState.ts
340
340
  var import_react5 = require("react");
341
+ var isEmptyFilterValue = (value) => {
342
+ if (value === void 0 || value === null || value === "") return true;
343
+ if (Array.isArray(value)) return value[0] == null && value[1] == null;
344
+ return false;
345
+ };
341
346
  function useTableState({
342
347
  defaultItemsPerPage = 10,
343
348
  initialSort = null
@@ -362,7 +367,7 @@ function useTableState({
362
367
  const handleFilterChange = (0, import_react5.useCallback)(
363
368
  (key, value) => {
364
369
  setFilters((prev) => {
365
- if (value === void 0 || value === null || value === "") {
370
+ if (isEmptyFilterValue(value)) {
366
371
  const next = { ...prev };
367
372
  delete next[key];
368
373
  return next;
@@ -2180,9 +2185,10 @@ function tableHeaderCell(className, density = "normal") {
2180
2185
  return (0, import_clsx11.default)(densityStyles[density].header, "align-top", className);
2181
2186
  }
2182
2187
  var tableBody = "divide-y divide-secondary-100";
2183
- var tableRow = "hover:bg-secondary-50/50 transition-colors duration-150 group";
2188
+ var tableRow = "hover:bg-[var(--color-table-rowHover,var(--color-secondary-50))] transition-colors duration-150 group";
2184
2189
  var tableRowClickable = "cursor-pointer focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500 focus-visible:ring-inset";
2185
2190
  var tableCardClickable = "cursor-pointer rounded-lg focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500";
2191
+ var tableCardHover = "hover:bg-[var(--color-table-rowHover,var(--color-secondary-50))] transition-colors duration-150";
2186
2192
  function tableCell(className, density = "normal") {
2187
2193
  return (0, import_clsx11.default)(densityStyles[density].cell, "align-middle", className);
2188
2194
  }
@@ -3681,9 +3687,9 @@ function useVirtualRows({
3681
3687
  }
3682
3688
 
3683
3689
  // src/components/organisms/data-table/dataTable.tsx
3684
- var import_clsx21 = __toESM(require("clsx"), 1);
3685
- var import_react19 = require("react");
3686
- var import_fa11 = require("react-icons/fa");
3690
+ var import_clsx23 = __toESM(require("clsx"), 1);
3691
+ var import_react21 = require("react");
3692
+ var import_fa13 = require("react-icons/fa");
3687
3693
  var import_md = require("react-icons/md");
3688
3694
 
3689
3695
  // src/components/molecules/pagination/pagination.tsx
@@ -3976,445 +3982,240 @@ function ITPagination({
3976
3982
  return /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("nav", { "aria-label": "Pagination", className: (0, import_clsx20.default)("inline-flex", className), children: renderPaginationControls() });
3977
3983
  }
3978
3984
 
3979
- // src/utils/table.utils.ts
3980
- var formatCurrencyMX = (value) => {
3981
- return value.toLocaleString("es-MX", {
3982
- style: "currency",
3983
- currency: "MXN"
3984
- });
3985
- };
3986
- var getNestedValue = (obj, path) => {
3987
- return path.split(".").reduce((acc, part) => acc && acc[part], obj);
3988
- };
3989
- var ROW_CLICK_IGNORE_SELECTOR = 'button, a, input, select, textarea, [role="button"], [role="link"], [data-row-click-ignore]';
3990
- function isInteractiveTarget(target, boundary = null) {
3991
- if (!(target instanceof Element)) return false;
3992
- const interactive = target.closest(ROW_CLICK_IGNORE_SELECTOR);
3993
- if (!interactive) return false;
3994
- if (boundary instanceof Node && interactive === boundary) return false;
3995
- return true;
3996
- }
3997
-
3998
- // src/components/organisms/data-table/dataTable.tsx
3985
+ // src/components/molecules/search-select/search-select.tsx
3986
+ var import_react19 = require("react");
3987
+ var import_react_dom3 = require("react-dom");
3988
+ var import_clsx21 = __toESM(require("clsx"), 1);
3989
+ var import_fa11 = require("react-icons/fa");
3999
3990
  var import_jsx_runtime21 = require("react/jsx-runtime");
4000
- var getNestedValue2 = (obj, path) => {
4001
- return path.split(".").reduce((acc, part) => acc && acc[part], obj);
4002
- };
4003
- var EMPTY_OBJECT = {};
4004
- function ITDataTable({
4005
- columns,
4006
- fetchData,
4007
- debounceMs = 500,
4008
- externalFilters = EMPTY_OBJECT,
4009
- loadingIndicator,
4010
- fetchOnMount = true,
4011
- reloadTrigger,
4012
- containerClassName,
3991
+ function ITSearchSelect({
3992
+ name,
3993
+ options = [],
3994
+ label,
3995
+ placeholder = "Selecciona una opci\xF3n",
3996
+ valueField = "value",
3997
+ labelField = "label",
3998
+ value,
3999
+ onChange,
4000
+ onBlur,
4001
+ disabled = false,
4013
4002
  className,
4014
- variant = "default",
4003
+ touched,
4004
+ required,
4005
+ error,
4006
+ readOnly = false,
4007
+ onSearch,
4008
+ isLoading = false,
4009
+ noResultsMessage = "No se encontraron resultados",
4015
4010
  size = "md",
4016
- itemsPerPageOptions = [5, 10, 20],
4017
- defaultItemsPerPage = 10,
4018
- title,
4019
- renderCard,
4020
- defaultView,
4021
- showVerticalBorder = true,
4022
- verticalBorderClassname,
4023
- onRowClick,
4024
- layout = "auto",
4025
- density = "normal",
4026
- autoCardBreakpoint = 0,
4027
- virtualized = false,
4028
- virtualizedMaxHeight = 400,
4029
- rowHeight,
4030
- overscan = 5,
4031
- stickyHeader = false
4011
+ renderOption,
4012
+ clearable = true,
4013
+ onClear
4032
4014
  }) {
4033
- const [viewMode, setViewMode] = (0, import_react19.useState)(defaultView || "table");
4034
- const { ref: rootRef, width: containerWidth } = useElementSize();
4035
- const [data, setData] = (0, import_react19.useState)([]);
4036
- const [totalItems, setTotalItems] = (0, import_react19.useState)(0);
4037
- const [isLoading, setIsLoading] = (0, import_react19.useState)(fetchOnMount);
4038
- const isFixed = layout === "fixed";
4039
- const forcedCards = autoCardBreakpoint > 0 && containerWidth > 0 && containerWidth < autoCardBreakpoint;
4040
- const effectiveView = forcedCards ? "cards" : viewMode;
4041
- const hasColumnWidths = columns.some((col) => col.width != null);
4042
- const tableLayoutClass = isFixed ? "w-full text-sm text-left text-secondary-600 transition-opacity duration-300" : "min-w-max w-full text-sm text-left text-secondary-600 transition-opacity duration-300";
4043
- const isTableVirtual = virtualized && effectiveView === "table";
4044
- const isStickyHeader = stickyHeader && isTableVirtual;
4045
- const resolvedRowHeight = rowHeight ?? getRowHeight(size, density);
4046
- const columnCount = columns.length;
4047
- const scrollOuterClass = isTableVirtual ? "relative min-h-[200px]" : "overflow-x-auto relative min-h-[200px]";
4048
- const {
4049
- currentPage,
4050
- itemsPerPage,
4051
- filters,
4052
- sortConfig,
4053
- goToPage,
4054
- handleFilterChange,
4055
- handleSort,
4056
- handleItemsPerPageChange
4057
- } = useTableState({ defaultItemsPerPage });
4058
- const {
4059
- scrollRef,
4060
- startIndex,
4061
- endIndex,
4062
- topSpacerHeight,
4063
- bottomSpacerHeight
4064
- } = useVirtualRows({
4065
- count: data.length,
4066
- rowHeight: resolvedRowHeight,
4067
- overscan,
4068
- enabled: isTableVirtual,
4069
- resetKey: `${currentPage}-${itemsPerPage}`
4015
+ const [isOpen, setIsOpen] = (0, import_react19.useState)(false);
4016
+ const [searchTerm, setSearchTerm] = (0, import_react19.useState)("");
4017
+ const [isFocused, setIsFocused] = (0, import_react19.useState)(false);
4018
+ const [localTouched, setLocalTouched] = (0, import_react19.useState)(false);
4019
+ const containerRef = (0, import_react19.useRef)(null);
4020
+ const inputWrapperRef = (0, import_react19.useRef)(null);
4021
+ const timeoutRef = (0, import_react19.useRef)(null);
4022
+ const { panelRef, style: panelStyle } = useFloatingPanel(inputWrapperRef, isOpen, {
4023
+ estimatedHeight: 260,
4024
+ matchWidth: true
4070
4025
  });
4071
- const windowData = isTableVirtual ? data.slice(startIndex, endIndex + 1) : data;
4072
- const debounceTimerRef = (0, import_react19.useRef)(null);
4073
- const hasFetchedRef = (0, import_react19.useRef)(false);
4074
- const fetchDataRef = (0, import_react19.useRef)(fetchData);
4075
- fetchDataRef.current = fetchData;
4076
- const externalFiltersRef = (0, import_react19.useRef)(externalFilters);
4077
- externalFiltersRef.current = externalFilters;
4078
- const externalKey = JSON.stringify(externalFilters);
4079
- const computedTotalPages = Math.ceil(totalItems / itemsPerPage) || 1;
4080
- const performFetch = (0, import_react19.useCallback)(async () => {
4081
- setIsLoading(true);
4082
- try {
4083
- const response = await fetchDataRef.current({
4084
- page: currentPage,
4085
- limit: itemsPerPage,
4086
- filters: { ...filters, ...externalFiltersRef.current },
4087
- sort: sortConfig || void 0
4088
- });
4089
- setData(response.data || []);
4090
- setTotalItems(response.total || 0);
4091
- hasFetchedRef.current = true;
4092
- } catch (error) {
4093
- console.error("ITDataTable: Error fetching data", error);
4094
- setData([]);
4095
- setTotalItems(0);
4096
- hasFetchedRef.current = true;
4097
- } finally {
4098
- setIsLoading(false);
4099
- }
4100
- }, [currentPage, itemsPerPage, filters, sortConfig]);
4101
- const performFetchRef = (0, import_react19.useRef)(performFetch);
4102
- performFetchRef.current = performFetch;
4026
+ const selectedOption = (0, import_react19.useMemo)(() => {
4027
+ return options.find((opt) => opt[valueField] === value);
4028
+ }, [options, value, valueField]);
4103
4029
  (0, import_react19.useEffect)(() => {
4104
- if (!fetchOnMount && !hasFetchedRef.current) return;
4105
- if (debounceTimerRef.current) clearTimeout(debounceTimerRef.current);
4106
- debounceTimerRef.current = setTimeout(() => {
4107
- performFetchRef.current();
4108
- }, debounceMs);
4109
- return () => {
4110
- if (debounceTimerRef.current) clearTimeout(debounceTimerRef.current);
4111
- };
4112
- }, [currentPage, itemsPerPage, sortConfig, filters, externalKey, reloadTrigger, fetchOnMount, debounceMs]);
4113
- const renderFilterInput = (col) => {
4114
- if (!col.filter) return null;
4115
- if (col.type === "boolean") {
4116
- const currentValue = filters[col.key];
4117
- const nextValue = currentValue === void 0 ? true : currentValue === true ? false : void 0;
4118
- const getToggleLabel = () => {
4119
- if (currentValue === void 0) return "Mostrar todos";
4120
- if (currentValue === true) return "Filtrar solo verdaderos";
4121
- return "Filtrar solo falsos";
4122
- };
4123
- return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
4124
- "button",
4125
- {
4126
- className: "flex items-center justify-center cursor-pointer focus:outline-none focus:ring-2 focus:ring-slate-400 focus:ring-offset-2 rounded-full p-1 transition-all duration-200",
4127
- onClick: () => handleFilterChange(col.key, nextValue),
4128
- "aria-label": `${getToggleLabel()} para ${col.label}`,
4129
- title: `${getToggleLabel()} para ${col.label}`,
4130
- disabled: isLoading,
4131
- children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { className: "relative w-10 h-5 bg-secondary-300 rounded-full", children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
4132
- "div",
4133
- {
4134
- className: (0, import_clsx21.default)(
4135
- "absolute top-0.5 w-4 h-4 rounded-full transition-all duration-300 shadow-sm",
4136
- {
4137
- "left-0.5 bg-secondary-400": currentValue === void 0,
4138
- "left-5 bg-slate-500": currentValue === true,
4139
- "left-0.5 bg-secondary-500": currentValue === false
4140
- }
4141
- )
4142
- }
4143
- ) })
4144
- }
4145
- );
4030
+ if (!isFocused) {
4031
+ setSearchTerm(selectedOption ? String(selectedOption[labelField]) : "");
4146
4032
  }
4147
- if (col.filter === "catalog" && col.catalogOptions) {
4148
- if (col.catalogOptions.loading) {
4149
- return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_fa11.FaSpinner, { className: "animate-spin", "aria-label": "Cargando opciones", title: "Cargando opciones" });
4150
- }
4151
- if (col.catalogOptions.error) {
4152
- return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(ITText, { as: "span", className: "text-danger-500 text-xs", children: "Error cargando" });
4033
+ }, [selectedOption, isFocused, labelField]);
4034
+ (0, import_react19.useEffect)(() => {
4035
+ function handleClickOutside(event) {
4036
+ const target = event.target;
4037
+ const inContainer = containerRef.current?.contains(target);
4038
+ const inPanel = panelRef.current?.contains(target);
4039
+ if (!inContainer && !inPanel) {
4040
+ setIsOpen(false);
4153
4041
  }
4154
- return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
4155
- ITSelect,
4156
- {
4157
- name: `filter-${col.key}`,
4158
- options: [
4159
- { value: "", label: "Todos" },
4160
- ...col.catalogOptions.data.map((item) => ({
4161
- value: String(item.id),
4162
- label: item.name
4163
- }))
4164
- ],
4165
- value: String(filters[col.key] || ""),
4166
- onChange: (e) => {
4167
- const value = e.target.value === "" ? void 0 : e.target.value;
4168
- handleFilterChange(col.key, value);
4169
- },
4170
- onBlur: () => {
4171
- },
4172
- className: "w-full text-xs",
4173
- disabled: isLoading
4174
- }
4175
- );
4176
4042
  }
4177
- return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
4178
- ITInput,
4179
- {
4180
- name: `filter-${col.key}`,
4181
- className: "w-full text-xs",
4182
- placeholder: "Buscar...",
4183
- value: String(filters[col.key] || ""),
4184
- onChange: (e) => handleFilterChange(col.key, e.target.value),
4185
- onBlur: () => {
4186
- },
4187
- disabled: isLoading
4188
- }
4043
+ document.addEventListener("mousedown", handleClickOutside);
4044
+ return () => document.removeEventListener("mousedown", handleClickOutside);
4045
+ }, []);
4046
+ const selectedLabel = selectedOption ? String(selectedOption[labelField]) : "";
4047
+ const filteredOptions = (0, import_react19.useMemo)(() => {
4048
+ if (onSearch) return options;
4049
+ if (!searchTerm || !isFocused || searchTerm === selectedLabel) return options;
4050
+ return options.filter(
4051
+ (opt) => String(opt[labelField]).toLowerCase().includes(searchTerm.toLowerCase())
4189
4052
  );
4053
+ }, [options, searchTerm, selectedLabel, onSearch, labelField, isFocused]);
4054
+ const handleInputChange = (e) => {
4055
+ const query = e.target.value;
4056
+ setSearchTerm(query);
4057
+ setIsOpen(true);
4058
+ if (onSearch) {
4059
+ if (timeoutRef.current) clearTimeout(timeoutRef.current);
4060
+ timeoutRef.current = setTimeout(() => {
4061
+ onSearch(query);
4062
+ }, 500);
4063
+ }
4190
4064
  };
4191
- const renderCellContent = (col, row) => {
4192
- const value = getNestedValue2(row, col.key);
4193
- if (col.render) return col.render(row);
4194
- switch (col.type) {
4195
- case "number":
4196
- return typeof value === "number" && col.currencyMX ? formatCurrencyMX(value) : value;
4197
- case "boolean":
4198
- return value ? /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_fa11.FaCheck, { className: "text-success-500", "aria-label": "Verdadero", title: "Verdadero" }) : /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_fa11.FaTimes, { className: "text-danger-500", "aria-label": "Falso", title: "Falso" });
4199
- case "actions":
4200
- return col.actions ? col.actions(row) : null;
4201
- case "catalog":
4202
- if (col.catalogOptions) {
4203
- const catalogItem = col.catalogOptions.data.find((item) => item.id === value);
4204
- return catalogItem?.name || value;
4205
- }
4206
- return value;
4207
- default:
4208
- return value;
4065
+ const handleSelect = (option) => {
4066
+ if (onChange) {
4067
+ onChange(option[valueField], option);
4209
4068
  }
4069
+ setSearchTerm(String(option[labelField]));
4070
+ setIsOpen(false);
4210
4071
  };
4211
- const renderDefaultCard = (row) => {
4212
- const dataCols = columns.filter((c) => c.type !== "actions");
4213
- const actionCol = columns.find((c) => c.type === "actions");
4214
- return /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: "bg-white dark:bg-slate-800 rounded-lg border border-slate-200 dark:border-slate-700 p-3 space-y-2 shadow-sm", children: [
4215
- dataCols.map((col) => /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: "flex items-center justify-between gap-2", children: [
4216
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { className: "text-[10px] font-bold uppercase tracking-wider text-slate-400 whitespace-nowrap flex-shrink-0 min-w-[70px]", children: col.label }),
4217
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { className: "text-sm font-medium text-slate-800 dark:text-white text-right truncate", children: renderCellContent(col, row) })
4218
- ] }, col.key)),
4219
- actionCol?.actions && /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { className: "flex items-center justify-end gap-2 pt-2 border-t border-slate-100 dark:border-slate-700", children: actionCol.actions(row) })
4220
- ] });
4072
+ const handleClear = () => {
4073
+ setSearchTerm("");
4074
+ setIsOpen(true);
4075
+ if (onSearch) onSearch("");
4076
+ if (value !== void 0 && value !== null && value !== "") {
4077
+ onChange?.("", void 0);
4078
+ }
4079
+ onClear?.();
4221
4080
  };
4222
- const segCtrlClass = (mode) => `flex items-center gap-1.5 px-3 py-1.5 rounded-md text-xs font-semibold transition-all ${effectiveView === mode ? "bg-white dark:bg-slate-900 text-slate-900 dark:text-white shadow-sm border border-slate-200/50 dark:border-slate-700" : "text-slate-500 dark:text-slate-400 hover:text-slate-700 dark:hover:text-slate-200"}`;
4223
- const handleRowClick = (row) => (event) => {
4224
- if (!onRowClick || isLoading || isInteractiveTarget(event.target, event.currentTarget)) return;
4225
- onRowClick(row, event);
4081
+ const handleFocus = () => {
4082
+ if (disabled || readOnly) return;
4083
+ setIsFocused(true);
4084
+ setIsOpen(true);
4226
4085
  };
4227
- const handleRowKeyDown = (row) => (event) => {
4228
- if (!onRowClick || isLoading) return;
4229
- if (event.target !== event.currentTarget) return;
4230
- if (event.key !== "Enter" && event.key !== " ") return;
4231
- event.preventDefault();
4232
- onRowClick(row, event);
4086
+ const handleInputBlur = (e) => {
4087
+ setTimeout(() => {
4088
+ setIsFocused(false);
4089
+ setLocalTouched(true);
4090
+ onBlur?.(e);
4091
+ }, 200);
4233
4092
  };
4234
- const tableEl = /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(
4235
- "table",
4236
- {
4237
- className: (0, import_clsx21.default)(
4238
- tableLayoutClass,
4239
- showVerticalBorder && "[&_th]:border-r [&_th:last-child]:border-r-0 [&_td]:border-r [&_td:last-child]:border-r-0",
4240
- showVerticalBorder && (verticalBorderClassname || "[&_th]:border-slate-100 dark:[&_th]:border-slate-700/30 [&_td]:border-slate-100 dark:[&_td]:border-slate-700/30"),
4241
- isLoading ? "opacity-50" : "opacity-100",
4242
- variantStyles[variant],
4243
- sizeStyles[size],
4244
- className
4245
- ),
4246
- style: isFixed ? { tableLayout: "fixed" } : void 0,
4247
- "aria-rowcount": isTableVirtual ? data.length + 1 : void 0,
4248
- children: [
4249
- hasColumnWidths && /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("colgroup", { children: columns.map((col) => /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
4250
- "col",
4251
- {
4252
- style: col.width != null ? { width: typeof col.width === "number" ? `${col.width}px` : col.width } : void 0
4253
- },
4254
- col.key
4255
- )) }),
4256
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("thead", { children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
4257
- "tr",
4093
+ const inputTheme = theme.input || {};
4094
+ const isTouched = touched !== void 0 ? touched : localTouched;
4095
+ const isEmpty = value === void 0 || value === null || String(value).trim() === "";
4096
+ const effectiveError = error !== void 0 && error !== false ? error === true ? "Este campo es requerido" : error : required && isEmpty ? "Este campo es requerido" : void 0;
4097
+ const hasError = isTouched && !!effectiveError;
4098
+ const errorMessage = typeof effectiveError === "string" ? effectiveError : "Este campo es requerido";
4099
+ const showClearButton = clearable && !disabled && !readOnly && (searchTerm.length > 0 || !isEmpty);
4100
+ const getInputStyle = () => {
4101
+ const sizeConfig = inputSizeTokens[size] ?? inputSizeTokens.md;
4102
+ const style = {
4103
+ backgroundColor: inputTheme.backgroundColor || "#ffffff",
4104
+ borderColor: inputTheme.borderColor || "var(--color-secondary-300)",
4105
+ borderRadius: inputTheme.borderRadius || "0.5rem",
4106
+ padding: sizeConfig.padding,
4107
+ fontSize: sizeConfig.fontSize,
4108
+ borderWidth: "1px",
4109
+ borderStyle: "solid",
4110
+ transition: "all 0.2s",
4111
+ color: "var(--it-input-text-color, var(--color-secondary-900))",
4112
+ width: "100%"
4113
+ };
4114
+ if (disabled) {
4115
+ style.backgroundColor = inputTheme.disabled?.backgroundColor || "var(--color-secondary-100)";
4116
+ style.borderColor = inputTheme.disabled?.borderColor || "var(--color-secondary-200)";
4117
+ style.opacity = 0.7;
4118
+ style.cursor = "not-allowed";
4119
+ }
4120
+ if (hasError) {
4121
+ style.borderColor = inputTheme.error?.borderColor || "red";
4122
+ if (isFocused) {
4123
+ style.boxShadow = inputTheme.error?.ring;
4124
+ }
4125
+ } else if (isFocused && !readOnly) {
4126
+ style.boxShadow = inputTheme.focus?.ring;
4127
+ style.borderColor = inputTheme.focus?.borderColor;
4128
+ }
4129
+ return style;
4130
+ };
4131
+ return /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: (0, import_clsx21.default)("w-full flex flex-col gap-1.5", className, isOpen && "relative z-30"), ref: containerRef, children: [
4132
+ label && /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(
4133
+ ITText,
4134
+ {
4135
+ as: "label",
4136
+ className: (0, import_clsx21.default)("text-sm font-medium text-secondary-700 dark:text-slate-300", {
4137
+ "text-danger-500": hasError
4138
+ }),
4139
+ children: [
4140
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(ITText, { as: "span", children: label }),
4141
+ required && /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(ITText, { as: "span", className: "text-danger-500 ml-1", children: "*" })
4142
+ ]
4143
+ }
4144
+ ),
4145
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: "relative", children: [
4146
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { ref: inputWrapperRef, className: "relative flex items-center", children: [
4147
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
4148
+ "input",
4258
4149
  {
4259
- className: (0, import_clsx21.default)(tableHeaderRow, "dark:text-slate-200"),
4260
- "aria-rowindex": isTableVirtual ? 1 : void 0,
4261
- children: columns.map((col) => /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
4262
- "th",
4263
- {
4264
- scope: "col",
4265
- className: (0, import_clsx21.default)(
4266
- tableHeaderCell(col.className, density),
4267
- col.align && tableAlignClasses[col.align],
4268
- isStickyHeader && "sticky top-0 z-10 bg-secondary-50"
4269
- ),
4270
- style: col.minWidth != null || isStickyHeader ? {
4271
- ...col.minWidth != null ? { minWidth: `${col.minWidth}px` } : {},
4272
- ...isStickyHeader ? { backgroundColor: "var(--color-table-headerBg, #f8fafc)" } : {}
4273
- } : void 0,
4274
- children: /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: isFixed ? "flex flex-col gap-3" : "flex flex-col gap-3 min-w-[150px]", children: [
4275
- /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: "flex items-center justify-between gap-2", children: [
4276
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(ITText, { as: "span", className: "text-slate-900 dark:text-white font-bold", children: col.label }),
4277
- col.sortable && col.type !== "actions" && /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
4278
- "button",
4279
- {
4280
- onClick: () => handleSort(col.key),
4281
- disabled: isLoading,
4282
- className: `p-1 rounded-md transition-colors ${sortConfig?.key === col.key ? "bg-secondary-200 text-secondary-900" : "hover:bg-secondary-200 text-secondary-400 hover:text-secondary-700"} disabled:opacity-50`,
4283
- title: `Ordenar por ${col.label}`,
4284
- children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_md.MdOutlineSwapVert, { className: "w-4 h-4", "aria-hidden": "true" })
4285
- }
4286
- )
4287
- ] }),
4288
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { className: "w-full", children: col.filter ? renderFilterInput(col) : null })
4289
- ] })
4290
- },
4291
- col.key
4292
- ))
4150
+ type: "text",
4151
+ name,
4152
+ value: searchTerm,
4153
+ onChange: handleInputChange,
4154
+ onFocus: handleFocus,
4155
+ onBlur: handleInputBlur,
4156
+ disabled,
4157
+ readOnly,
4158
+ placeholder,
4159
+ className: "outline-none pr-10",
4160
+ style: getInputStyle(),
4161
+ autoComplete: "off"
4293
4162
  }
4294
- ) }),
4295
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("tbody", { className: (0, import_clsx21.default)(tableBody, "dark:divide-slate-700/30"), children: data.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(import_jsx_runtime21.Fragment, { children: [
4296
- isTableVirtual && topSpacerHeight > 0 && /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("tr", { "aria-hidden": "true", style: { height: topSpacerHeight }, children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("td", { colSpan: columnCount, style: { padding: 0, border: 0 } }) }),
4297
- windowData.map((row, windowIndex) => {
4298
- const absoluteIndex = isTableVirtual ? startIndex + windowIndex : windowIndex;
4299
- return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
4300
- "tr",
4301
- {
4302
- "aria-rowindex": isTableVirtual ? absoluteIndex + 2 : void 0,
4303
- className: (0, import_clsx21.default)(
4304
- tableRow,
4305
- variant === "striped" && absoluteIndex % 2 === 0 && "bg-secondary-50/40 dark:bg-slate-800/20",
4306
- onRowClick && !isLoading && tableRowClickable
4307
- ),
4308
- tabIndex: onRowClick && !isLoading ? 0 : void 0,
4309
- onClick: onRowClick && !isLoading ? handleRowClick(row) : void 0,
4310
- onKeyDown: onRowClick && !isLoading ? handleRowKeyDown(row) : void 0,
4311
- children: columns.map((col) => {
4312
- const rawValue = getNestedValue2(row, col.key);
4313
- const truncateTitle = col.truncate && (typeof rawValue === "string" || typeof rawValue === "number") ? String(rawValue) : void 0;
4314
- return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
4315
- "td",
4316
- {
4317
- className: (0, import_clsx21.default)(
4318
- tableCell(col.className, density),
4319
- col.align && tableAlignClasses[col.align]
4320
- ),
4321
- style: col.minWidth != null ? { minWidth: `${col.minWidth}px` } : void 0,
4322
- title: truncateTitle,
4323
- children: col.type === "actions" ? /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { className: tableActionsCell, children: renderCellContent(col, row) }) : /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { className: (0, import_clsx21.default)(tableCellText, col.truncate && "truncate"), children: renderCellContent(col, row) })
4324
- },
4325
- `${absoluteIndex}-${col.key}`
4326
- );
4327
- })
4163
+ ),
4164
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: "absolute right-3 flex items-center gap-2 text-secondary-400", children: [
4165
+ isLoading && /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { className: "pointer-events-none animate-spin h-4 w-4 border-2 border-primary-500 border-t-transparent rounded-full" }),
4166
+ !isLoading && showClearButton && /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
4167
+ "button",
4168
+ {
4169
+ type: "button",
4170
+ "aria-label": "Limpiar",
4171
+ title: "Limpiar",
4172
+ onMouseDown: (e) => {
4173
+ e.preventDefault();
4174
+ handleClear();
4328
4175
  },
4329
- absoluteIndex
4330
- );
4331
- }),
4332
- isTableVirtual && bottomSpacerHeight > 0 && /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("tr", { "aria-hidden": "true", style: { height: bottomSpacerHeight }, children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("td", { colSpan: columnCount, style: { padding: 0, border: 0 } }) })
4333
- ] }) : /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("tr", { children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("td", { colSpan: columns.length, className: "px-6 py-12 text-center", children: !isLoading && /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: tableEmptyContent, children: [
4334
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(ITText, { as: "span", className: "text-lg", children: "No se encontraron resultados" }),
4335
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(ITText, { as: "span", className: "text-sm mt-1", children: "Intenta ajustar los filtros" })
4336
- ] }) }) }) })
4337
- ]
4338
- }
4339
- );
4340
- return /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { ref: rootRef, className: (0, import_clsx21.default)("space-y-4 w-full relative", containerClassName), children: [
4341
- /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: tableContainer, style: { backgroundColor: "var(--color-table-rowBg, #ffffff)" }, children: [
4342
- title && /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: "px-6 py-5 flex items-center justify-between", style: { backgroundColor: "var(--color-table-rowBg, #ffffff)" }, children: [
4343
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(ITText, { as: "h2", className: "text-xl font-bold text-secondary-900 leading-tight", children: title }),
4344
- /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: "flex items-center gap-3", children: [
4345
- isLoading && /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { className: "text-secondary-400", children: loadingIndicator || /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_fa11.FaSpinner, { className: "animate-spin text-primary-500 text-xl" }) }),
4346
- /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: "flex items-center bg-slate-100 dark:bg-slate-800/80 rounded-lg p-0.5 border border-slate-200 dark:border-slate-700/50", children: [
4347
- /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("button", { onClick: () => setViewMode("table"), disabled: forcedCards, className: segCtrlClass("table"), children: [
4348
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_fa11.FaTable, { size: 11 }),
4349
- "Table"
4350
- ] }),
4351
- /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("button", { onClick: () => setViewMode("cards"), className: segCtrlClass("cards"), children: [
4352
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_fa11.FaThLarge, { size: 11 }),
4353
- "Cards"
4354
- ] })
4355
- ] })
4176
+ className: "flex items-center justify-center text-secondary-400 hover:text-secondary-600 focus:outline-none focus-visible:ring-2 focus-visible:ring-primary-400 rounded-full",
4177
+ children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_fa11.FaTimes, { size: 14 })
4178
+ }
4179
+ ),
4180
+ !isLoading && !showClearButton && /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_fa11.FaSearch, { size: 14, className: (0, import_clsx21.default)("pointer-events-none", { "text-primary-500": isFocused }) })
4356
4181
  ] })
4357
4182
  ] }),
4358
- !title && /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { className: "flex justify-end px-4 pt-3", children: /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: "flex items-center bg-slate-100 dark:bg-slate-800/80 rounded-lg p-0.5 border border-slate-200 dark:border-slate-700/50", children: [
4359
- /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("button", { onClick: () => setViewMode("table"), disabled: forcedCards, className: segCtrlClass("table"), children: [
4360
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_fa11.FaTable, { size: 11 }),
4361
- "Table"
4362
- ] }),
4363
- /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("button", { onClick: () => setViewMode("cards"), className: segCtrlClass("cards"), children: [
4364
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_fa11.FaThLarge, { size: 11 }),
4365
- "Cards"
4366
- ] })
4367
- ] }) }),
4368
- /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: scrollOuterClass, children: [
4369
- isLoading && /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { className: "absolute inset-0 z-20 flex items-center justify-center bg-white/40 backdrop-blur-[2px] transition-all duration-300", children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { className: "flex flex-col items-center gap-3 p-6 rounded-2xl shadow-xl border border-secondary-100 animate-in fade-in zoom-in duration-300", style: { backgroundColor: "var(--color-table-rowBg, #ffffff)" }, children: loadingIndicator || /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(import_jsx_runtime21.Fragment, { children: [
4370
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_fa11.FaSpinner, { className: "animate-spin text-primary-500 text-4xl" }),
4371
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(ITText, { as: "span", className: "text-sm font-semibold text-secondary-600 animate-pulse", children: "Cargando datos..." })
4372
- ] }) }) }),
4373
- effectiveView === "cards" ? /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { className: "p-4 space-y-3 max-h-[400px] overflow-y-auto", children: data.length > 0 ? data.map((row, i) => /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
4374
- "div",
4375
- {
4376
- className: (0, import_clsx21.default)(onRowClick && !isLoading && tableCardClickable),
4377
- role: onRowClick && !isLoading ? "button" : void 0,
4378
- tabIndex: onRowClick && !isLoading ? 0 : void 0,
4379
- onClick: onRowClick && !isLoading ? handleRowClick(row) : void 0,
4380
- onKeyDown: onRowClick && !isLoading ? handleRowKeyDown(row) : void 0,
4381
- children: renderCard ? renderCard(row) : renderDefaultCard(row)
4382
- },
4383
- i
4384
- )) : !isLoading && /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: (0, import_clsx21.default)(tableEmptyContent, "py-12"), children: [
4385
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(ITText, { as: "span", className: "text-lg", children: "No se encontraron resultados" }),
4386
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(ITText, { as: "span", className: "text-sm mt-1", children: "Intenta ajustar los filtros" })
4387
- ] }) }) : isTableVirtual ? /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
4183
+ isOpen && (0, import_react_dom3.createPortal)(
4184
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
4388
4185
  "div",
4389
4186
  {
4390
- ref: scrollRef,
4391
- className: "overflow-x-auto overflow-y-auto",
4392
- style: { maxHeight: virtualizedMaxHeight },
4393
- children: tableEl
4187
+ ref: panelRef,
4188
+ style: panelStyle,
4189
+ className: "bg-white dark:bg-slate-900 border border-secondary-200 dark:border-slate-800 rounded-lg shadow-xl overflow-hidden animate-in fade-in zoom-in duration-200 origin-top",
4190
+ children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { className: "max-h-60 overflow-y-auto", children: filteredOptions.length > 0 ? filteredOptions.map((option) => {
4191
+ const isSelected = value === option[valueField];
4192
+ return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
4193
+ ITText,
4194
+ {
4195
+ as: "div",
4196
+ onClick: () => handleSelect(option),
4197
+ className: (0, import_clsx21.default)(
4198
+ "px-4 py-2 text-sm cursor-pointer transition-colors",
4199
+ isSelected ? "bg-primary-50 dark:bg-primary-950/40 text-primary-700 dark:text-primary-300 font-medium" : "hover:bg-secondary-50 dark:hover:bg-slate-800 text-secondary-700 dark:text-slate-300"
4200
+ ),
4201
+ children: renderOption ? renderOption(option, { isSelected, searchTerm }) : /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(ITText, { as: "span", children: option[labelField] })
4202
+ },
4203
+ option[valueField]
4204
+ );
4205
+ }) : /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(ITText, { as: "div", className: "px-4 py-6 text-sm text-center text-secondary-500 italic", children: isLoading ? "Cargando..." : noResultsMessage }) })
4394
4206
  }
4395
- ) : tableEl
4396
- ] })
4207
+ ),
4208
+ document.body
4209
+ )
4397
4210
  ] }),
4398
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { className: "rounded-b-xl px-6 py-4", style: { backgroundColor: "var(--color-table-rowBg, #ffffff)" }, children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
4399
- ITPagination,
4400
- {
4401
- currentPage,
4402
- totalPages: computedTotalPages,
4403
- onPageChange: goToPage,
4404
- color: "primary",
4405
- itemsPerPageOptions,
4406
- itemsPerPage,
4407
- onItemsPerPageChange: handleItemsPerPageChange,
4408
- totalItems
4409
- }
4410
- ) })
4211
+ hasError && /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(ITText, { as: "p", className: "text-danger-500 text-xs mt-1", children: errorMessage })
4411
4212
  ] });
4412
4213
  }
4413
4214
 
4414
4215
  // src/components/molecules/date-picker/datePicker.tsx
4415
4216
  var import_clsx22 = __toESM(require("clsx"), 1);
4416
4217
  var import_react20 = __toESM(require("react"), 1);
4417
- var import_react_dom3 = require("react-dom");
4218
+ var import_react_dom4 = require("react-dom");
4418
4219
  var import_fa12 = require("react-icons/fa");
4419
4220
  var import_date_fns2 = require("date-fns");
4420
4221
  var import_jsx_runtime22 = require("react/jsx-runtime");
@@ -4581,109 +4382,609 @@ function ITDatePicker({
4581
4382
  name,
4582
4383
  value: today
4583
4384
  }
4584
- };
4585
- onChange(event);
4586
- setIsValidDate(true);
4587
- } else {
4588
- const [day, month, year] = inputValue.split("/").map(Number);
4589
- const date = new Date(year, month - 1, day);
4590
- if (!isNaN(date.getTime())) {
4591
- onBlur?.({ target: { name, value: date } });
4592
- } else {
4593
- const today = /* @__PURE__ */ new Date();
4594
- setInputValue(formatDate(today));
4595
- onChange({ target: { name, value: today } });
4596
- }
4385
+ };
4386
+ onChange(event);
4387
+ setIsValidDate(true);
4388
+ } else {
4389
+ const [day, month, year] = inputValue.split("/").map(Number);
4390
+ const date = new Date(year, month - 1, day);
4391
+ if (!isNaN(date.getTime())) {
4392
+ onBlur?.({ target: { name, value: date } });
4393
+ } else {
4394
+ const today = /* @__PURE__ */ new Date();
4395
+ setInputValue(formatDate(today));
4396
+ onChange({ target: { name, value: today } });
4397
+ }
4398
+ }
4399
+ };
4400
+ return /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("div", { ref: wrapperRef, className: (0, import_clsx22.default)("relative w-full", className), children: [
4401
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
4402
+ ITInput,
4403
+ {
4404
+ name,
4405
+ type: "text",
4406
+ label,
4407
+ placeholder,
4408
+ value: inputValue,
4409
+ onChange: handleInputChange,
4410
+ onBlur: handleInputBlur,
4411
+ maxLength: 10,
4412
+ iconRight: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("span", { children: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
4413
+ import_fa12.FaCalendarAlt,
4414
+ {
4415
+ onClick: handleIconClick,
4416
+ className: "text-slate-500 dark:text-slate-400 cursor-pointer"
4417
+ }
4418
+ ) }),
4419
+ variant,
4420
+ size,
4421
+ disabled,
4422
+ required,
4423
+ touched,
4424
+ error: !isValidDate ? "Fecha inv\xE1lida" : error,
4425
+ onClick: handleIconClick
4426
+ }
4427
+ ),
4428
+ isOpen && (0, import_react_dom4.createPortal)(
4429
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
4430
+ "div",
4431
+ {
4432
+ ref: panelRef,
4433
+ className: (0, import_clsx22.default)(
4434
+ calendarClassName,
4435
+ range ? "w-[320px]" : "w-[280px]"
4436
+ ),
4437
+ style: {
4438
+ ...panelStyle,
4439
+ backgroundColor: theme.card.backgroundColor,
4440
+ borderColor: theme.card.borderColor,
4441
+ borderWidth: "1px",
4442
+ borderStyle: "solid",
4443
+ borderRadius: theme.card.borderRadius,
4444
+ boxShadow: theme.card.shadow,
4445
+ padding: "0.5rem"
4446
+ },
4447
+ children: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
4448
+ calendar_default,
4449
+ {
4450
+ value: !range ? startDate : void 0,
4451
+ startDate,
4452
+ endDate,
4453
+ selectionMode: range ? "range" : "single",
4454
+ onChange: handleDateChange,
4455
+ minDate,
4456
+ maxDate,
4457
+ variant,
4458
+ className: "h-auto border-none shadow-none w-full"
4459
+ }
4460
+ )
4461
+ }
4462
+ ),
4463
+ document.body
4464
+ )
4465
+ ] });
4466
+ }
4467
+
4468
+ // src/utils/table.utils.ts
4469
+ var formatCurrencyMX = (value) => {
4470
+ return value.toLocaleString("es-MX", {
4471
+ style: "currency",
4472
+ currency: "MXN"
4473
+ });
4474
+ };
4475
+ var getNestedValue = (obj, path) => {
4476
+ return path.split(".").reduce((acc, part) => acc && acc[part], obj);
4477
+ };
4478
+ var ROW_CLICK_IGNORE_SELECTOR = 'button, a, input, select, textarea, [role="button"], [role="link"], [data-row-click-ignore]';
4479
+ function isInteractiveTarget(target, boundary = null) {
4480
+ if (!(target instanceof Element)) return false;
4481
+ const interactive = target.closest(ROW_CLICK_IGNORE_SELECTOR);
4482
+ if (!interactive) return false;
4483
+ if (boundary instanceof Node && interactive === boundary) return false;
4484
+ return true;
4485
+ }
4486
+
4487
+ // src/components/organisms/data-table/dataTable.tsx
4488
+ var import_jsx_runtime23 = require("react/jsx-runtime");
4489
+ var getNestedValue2 = (obj, path) => {
4490
+ return path.split(".").reduce((acc, part) => acc && acc[part], obj);
4491
+ };
4492
+ var EMPTY_OBJECT = {};
4493
+ function ITDataTable({
4494
+ columns,
4495
+ fetchData,
4496
+ debounceMs = 500,
4497
+ externalFilters = EMPTY_OBJECT,
4498
+ loadingIndicator,
4499
+ fetchOnMount = true,
4500
+ reloadTrigger,
4501
+ containerClassName,
4502
+ className,
4503
+ variant = "default",
4504
+ size = "md",
4505
+ itemsPerPageOptions = [5, 10, 20],
4506
+ defaultItemsPerPage = 10,
4507
+ title,
4508
+ renderCard,
4509
+ defaultView,
4510
+ showVerticalBorder = true,
4511
+ verticalBorderClassname,
4512
+ onRowClick,
4513
+ layout = "auto",
4514
+ density = "normal",
4515
+ autoCardBreakpoint = 0,
4516
+ virtualized = false,
4517
+ virtualizedMaxHeight = 400,
4518
+ rowHeight,
4519
+ overscan = 5,
4520
+ stickyHeader = false
4521
+ }) {
4522
+ const [viewMode, setViewMode] = (0, import_react21.useState)(defaultView || "table");
4523
+ const { ref: rootRef, width: containerWidth } = useElementSize();
4524
+ const [data, setData] = (0, import_react21.useState)([]);
4525
+ const [totalItems, setTotalItems] = (0, import_react21.useState)(0);
4526
+ const [isLoading, setIsLoading] = (0, import_react21.useState)(fetchOnMount);
4527
+ const isFixed = layout === "fixed";
4528
+ const forcedCards = autoCardBreakpoint > 0 && containerWidth > 0 && containerWidth < autoCardBreakpoint;
4529
+ const effectiveView = forcedCards ? "cards" : viewMode;
4530
+ const hasColumnWidths = columns.some((col) => col.width != null);
4531
+ const tableLayoutClass = isFixed ? "w-full text-sm text-left text-secondary-600 transition-opacity duration-300" : "min-w-max w-full text-sm text-left text-secondary-600 transition-opacity duration-300";
4532
+ const isTableVirtual = virtualized && effectiveView === "table";
4533
+ const isStickyHeader = stickyHeader && isTableVirtual;
4534
+ const resolvedRowHeight = rowHeight ?? getRowHeight(size, density);
4535
+ const columnCount = columns.length;
4536
+ const scrollOuterClass = isTableVirtual ? "relative min-h-[200px]" : "overflow-x-auto relative min-h-[200px]";
4537
+ const {
4538
+ currentPage,
4539
+ itemsPerPage,
4540
+ filters,
4541
+ sortConfig,
4542
+ goToPage,
4543
+ handleFilterChange,
4544
+ handleSort,
4545
+ handleItemsPerPageChange
4546
+ } = useTableState({ defaultItemsPerPage });
4547
+ const {
4548
+ scrollRef,
4549
+ startIndex,
4550
+ endIndex,
4551
+ topSpacerHeight,
4552
+ bottomSpacerHeight
4553
+ } = useVirtualRows({
4554
+ count: data.length,
4555
+ rowHeight: resolvedRowHeight,
4556
+ overscan,
4557
+ enabled: isTableVirtual,
4558
+ resetKey: `${currentPage}-${itemsPerPage}`
4559
+ });
4560
+ const windowData = isTableVirtual ? data.slice(startIndex, endIndex + 1) : data;
4561
+ const debounceTimerRef = (0, import_react21.useRef)(null);
4562
+ const hasFetchedRef = (0, import_react21.useRef)(false);
4563
+ const fetchDataRef = (0, import_react21.useRef)(fetchData);
4564
+ fetchDataRef.current = fetchData;
4565
+ const externalFiltersRef = (0, import_react21.useRef)(externalFilters);
4566
+ externalFiltersRef.current = externalFilters;
4567
+ const externalKey = JSON.stringify(externalFilters);
4568
+ const computedTotalPages = Math.ceil(totalItems / itemsPerPage) || 1;
4569
+ const performFetch = (0, import_react21.useCallback)(async () => {
4570
+ setIsLoading(true);
4571
+ try {
4572
+ const response = await fetchDataRef.current({
4573
+ page: currentPage,
4574
+ limit: itemsPerPage,
4575
+ filters: { ...filters, ...externalFiltersRef.current },
4576
+ sort: sortConfig || void 0
4577
+ });
4578
+ setData(response.data || []);
4579
+ setTotalItems(response.total || 0);
4580
+ hasFetchedRef.current = true;
4581
+ } catch (error) {
4582
+ console.error("ITDataTable: Error fetching data", error);
4583
+ setData([]);
4584
+ setTotalItems(0);
4585
+ hasFetchedRef.current = true;
4586
+ } finally {
4587
+ setIsLoading(false);
4588
+ }
4589
+ }, [currentPage, itemsPerPage, filters, sortConfig]);
4590
+ const performFetchRef = (0, import_react21.useRef)(performFetch);
4591
+ performFetchRef.current = performFetch;
4592
+ (0, import_react21.useEffect)(() => {
4593
+ if (!fetchOnMount && !hasFetchedRef.current) return;
4594
+ if (debounceTimerRef.current) clearTimeout(debounceTimerRef.current);
4595
+ debounceTimerRef.current = setTimeout(() => {
4596
+ performFetchRef.current();
4597
+ }, debounceMs);
4598
+ return () => {
4599
+ if (debounceTimerRef.current) clearTimeout(debounceTimerRef.current);
4600
+ };
4601
+ }, [currentPage, itemsPerPage, sortConfig, filters, externalKey, reloadTrigger, fetchOnMount, debounceMs]);
4602
+ const renderFilterInput = (col) => {
4603
+ if (!col.filter) return null;
4604
+ if (col.type === "boolean") {
4605
+ const currentValue = filters[col.key];
4606
+ const nextValue = currentValue === void 0 ? true : currentValue === true ? false : void 0;
4607
+ const getToggleLabel = () => {
4608
+ if (currentValue === void 0) return "Mostrar todos";
4609
+ if (currentValue === true) return "Filtrar solo verdaderos";
4610
+ return "Filtrar solo falsos";
4611
+ };
4612
+ return /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
4613
+ "button",
4614
+ {
4615
+ className: "flex items-center justify-center cursor-pointer focus:outline-none focus:ring-2 focus:ring-slate-400 focus:ring-offset-2 rounded-full p-1 transition-all duration-200",
4616
+ onClick: () => handleFilterChange(col.key, nextValue),
4617
+ "aria-label": `${getToggleLabel()} para ${col.label}`,
4618
+ title: `${getToggleLabel()} para ${col.label}`,
4619
+ disabled: isLoading,
4620
+ children: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("div", { className: "relative w-10 h-5 bg-secondary-300 rounded-full", children: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
4621
+ "div",
4622
+ {
4623
+ className: (0, import_clsx23.default)(
4624
+ "absolute top-0.5 w-4 h-4 rounded-full transition-all duration-300 shadow-sm",
4625
+ {
4626
+ "left-0.5 bg-secondary-400": currentValue === void 0,
4627
+ "left-5 bg-slate-500": currentValue === true,
4628
+ "left-0.5 bg-secondary-500": currentValue === false
4629
+ }
4630
+ )
4631
+ }
4632
+ ) })
4633
+ }
4634
+ );
4635
+ }
4636
+ if (col.filter === "catalog" && col.catalogOptions) {
4637
+ if (col.catalogOptions.loading) {
4638
+ return /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(import_fa13.FaSpinner, { className: "animate-spin", "aria-label": "Cargando opciones", title: "Cargando opciones" });
4639
+ }
4640
+ if (col.catalogOptions.error) {
4641
+ return /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(ITText, { as: "span", className: "text-danger-500 text-xs", children: "Error cargando" });
4642
+ }
4643
+ return /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
4644
+ ITSelect,
4645
+ {
4646
+ name: `filter-${col.key}`,
4647
+ options: [
4648
+ { value: "", label: "Todos" },
4649
+ ...col.catalogOptions.data.map((item) => ({
4650
+ value: String(item.id),
4651
+ label: item.name
4652
+ }))
4653
+ ],
4654
+ value: String(filters[col.key] || ""),
4655
+ onChange: (e) => {
4656
+ const value = e.target.value === "" ? void 0 : e.target.value;
4657
+ handleFilterChange(col.key, value);
4658
+ },
4659
+ onBlur: () => {
4660
+ },
4661
+ className: "w-full text-xs",
4662
+ disabled: isLoading
4663
+ }
4664
+ );
4665
+ }
4666
+ if (col.filter === "search" && col.catalogOptions) {
4667
+ if (col.catalogOptions.loading) {
4668
+ return /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(import_fa13.FaSpinner, { className: "animate-spin", "aria-label": "Cargando opciones", title: "Cargando opciones" });
4669
+ }
4670
+ if (col.catalogOptions.error) {
4671
+ return /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(ITText, { as: "span", className: "text-danger-500 text-xs", children: "Error cargando" });
4672
+ }
4673
+ const searchValue = filters[col.key];
4674
+ return /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
4675
+ ITSearchSelect,
4676
+ {
4677
+ name: `filter-${col.key}`,
4678
+ options: col.catalogOptions.data.map((item) => ({
4679
+ value: item.id,
4680
+ label: item.name
4681
+ })),
4682
+ value: typeof searchValue === "string" || typeof searchValue === "number" ? searchValue : "",
4683
+ onChange: (value) => handleFilterChange(col.key, value === "" ? void 0 : value),
4684
+ onSearch: col.catalogOptions.onSearch,
4685
+ isLoading: col.catalogOptions.loading,
4686
+ size: "sm",
4687
+ placeholder: "Buscar...",
4688
+ clearable: true,
4689
+ className: "w-full",
4690
+ onBlur: () => {
4691
+ },
4692
+ disabled: isLoading
4693
+ }
4694
+ );
4695
+ }
4696
+ if (col.filter === "date") {
4697
+ const dateValue = filters[col.key];
4698
+ return /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
4699
+ ITDatePicker,
4700
+ {
4701
+ name: `filter-${col.key}`,
4702
+ value: dateValue instanceof Date ? dateValue : void 0,
4703
+ onChange: (e) => handleFilterChange(col.key, e.target.value),
4704
+ minDate: col.dateFilterOptions?.minDate,
4705
+ maxDate: col.dateFilterOptions?.maxDate,
4706
+ size: "sm",
4707
+ placeholder: "dd/mm/aaaa",
4708
+ className: "w-full",
4709
+ disabled: isLoading
4710
+ }
4711
+ );
4712
+ }
4713
+ if (col.filter === "date-range") {
4714
+ const rangeValue = filters[col.key];
4715
+ return /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
4716
+ ITDatePicker,
4717
+ {
4718
+ name: `filter-${col.key}`,
4719
+ range: true,
4720
+ value: Array.isArray(rangeValue) ? rangeValue : void 0,
4721
+ onChange: (e) => handleFilterChange(col.key, e.target.value),
4722
+ minDate: col.dateFilterOptions?.minDate,
4723
+ maxDate: col.dateFilterOptions?.maxDate,
4724
+ size: "sm",
4725
+ placeholder: "dd/mm/aaaa - dd/mm/aaaa",
4726
+ className: "w-full",
4727
+ disabled: isLoading
4728
+ }
4729
+ );
4730
+ }
4731
+ return /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
4732
+ ITInput,
4733
+ {
4734
+ name: `filter-${col.key}`,
4735
+ className: "w-full text-xs",
4736
+ placeholder: "Buscar...",
4737
+ value: String(filters[col.key] || ""),
4738
+ onChange: (e) => handleFilterChange(col.key, e.target.value),
4739
+ onBlur: () => {
4740
+ },
4741
+ disabled: isLoading
4742
+ }
4743
+ );
4744
+ };
4745
+ const renderCellContent = (col, row) => {
4746
+ const value = getNestedValue2(row, col.key);
4747
+ if (col.render) return col.render(row);
4748
+ switch (col.type) {
4749
+ case "number":
4750
+ return typeof value === "number" && col.currencyMX ? formatCurrencyMX(value) : value;
4751
+ case "boolean":
4752
+ return value ? /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(import_fa13.FaCheck, { className: "text-success-500", "aria-label": "Verdadero", title: "Verdadero" }) : /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(import_fa13.FaTimes, { className: "text-danger-500", "aria-label": "Falso", title: "Falso" });
4753
+ case "actions":
4754
+ return col.actions ? col.actions(row) : null;
4755
+ case "catalog":
4756
+ if (col.catalogOptions) {
4757
+ const catalogItem = col.catalogOptions.data.find((item) => item.id === value);
4758
+ return catalogItem?.name || value;
4759
+ }
4760
+ return value;
4761
+ default:
4762
+ return value;
4597
4763
  }
4598
4764
  };
4599
- return /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("div", { ref: wrapperRef, className: (0, import_clsx22.default)("relative w-full", className), children: [
4600
- /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
4601
- ITInput,
4602
- {
4603
- name,
4604
- type: "text",
4605
- label,
4606
- placeholder,
4607
- value: inputValue,
4608
- onChange: handleInputChange,
4609
- onBlur: handleInputBlur,
4610
- maxLength: 10,
4611
- iconRight: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("span", { children: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
4612
- import_fa12.FaCalendarAlt,
4765
+ const renderDefaultCard = (row) => {
4766
+ const dataCols = columns.filter((c) => c.type !== "actions");
4767
+ const actionCol = columns.find((c) => c.type === "actions");
4768
+ return /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { className: "bg-white dark:bg-slate-800 rounded-lg border border-slate-200 dark:border-slate-700 p-3 space-y-2 shadow-sm", children: [
4769
+ dataCols.map((col) => /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { className: "flex items-center justify-between gap-2", children: [
4770
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("span", { className: "text-[10px] font-bold uppercase tracking-wider text-slate-400 whitespace-nowrap flex-shrink-0 min-w-[70px]", children: col.label }),
4771
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("span", { className: "text-sm font-medium text-slate-800 dark:text-white text-right truncate", children: renderCellContent(col, row) })
4772
+ ] }, col.key)),
4773
+ actionCol?.actions && /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("div", { className: "flex items-center justify-end gap-2 pt-2 border-t border-slate-100 dark:border-slate-700", children: actionCol.actions(row) })
4774
+ ] });
4775
+ };
4776
+ const segCtrlClass = (mode) => `flex items-center gap-1.5 px-3 py-1.5 rounded-md text-xs font-semibold transition-all ${effectiveView === mode ? "bg-white dark:bg-slate-900 text-slate-900 dark:text-white shadow-sm border border-slate-200/50 dark:border-slate-700" : "text-slate-500 dark:text-slate-400 hover:text-slate-700 dark:hover:text-slate-200"}`;
4777
+ const handleRowClick = (row) => (event) => {
4778
+ if (!onRowClick || isLoading || isInteractiveTarget(event.target, event.currentTarget)) return;
4779
+ onRowClick(row, event);
4780
+ };
4781
+ const handleRowKeyDown = (row) => (event) => {
4782
+ if (!onRowClick || isLoading) return;
4783
+ if (event.target !== event.currentTarget) return;
4784
+ if (event.key !== "Enter" && event.key !== " ") return;
4785
+ event.preventDefault();
4786
+ onRowClick(row, event);
4787
+ };
4788
+ const tableEl = /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)(
4789
+ "table",
4790
+ {
4791
+ className: (0, import_clsx23.default)(
4792
+ tableLayoutClass,
4793
+ showVerticalBorder && "[&_th]:border-r [&_th:last-child]:border-r-0 [&_td]:border-r [&_td:last-child]:border-r-0",
4794
+ showVerticalBorder && (verticalBorderClassname || "[&_th]:border-slate-100 dark:[&_th]:border-slate-700/30 [&_td]:border-slate-100 dark:[&_td]:border-slate-700/30"),
4795
+ isLoading ? "opacity-50" : "opacity-100",
4796
+ variantStyles[variant],
4797
+ sizeStyles[size],
4798
+ className
4799
+ ),
4800
+ style: isFixed ? { tableLayout: "fixed" } : void 0,
4801
+ "aria-rowcount": isTableVirtual ? data.length + 1 : void 0,
4802
+ children: [
4803
+ hasColumnWidths && /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("colgroup", { children: columns.map((col) => /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
4804
+ "col",
4613
4805
  {
4614
- onClick: handleIconClick,
4615
- className: "text-slate-500 dark:text-slate-400 cursor-pointer"
4806
+ style: col.width != null ? { width: typeof col.width === "number" ? `${col.width}px` : col.width } : void 0
4807
+ },
4808
+ col.key
4809
+ )) }),
4810
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("thead", { children: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
4811
+ "tr",
4812
+ {
4813
+ className: (0, import_clsx23.default)(tableHeaderRow, "dark:text-slate-200"),
4814
+ "aria-rowindex": isTableVirtual ? 1 : void 0,
4815
+ children: columns.map((col) => /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
4816
+ "th",
4817
+ {
4818
+ scope: "col",
4819
+ className: (0, import_clsx23.default)(
4820
+ tableHeaderCell(col.className, density),
4821
+ col.align && tableAlignClasses[col.align],
4822
+ isStickyHeader && "sticky top-0 z-10 bg-secondary-50"
4823
+ ),
4824
+ style: col.minWidth != null || isStickyHeader ? {
4825
+ ...col.minWidth != null ? { minWidth: `${col.minWidth}px` } : {},
4826
+ ...isStickyHeader ? { backgroundColor: "var(--color-table-headerBg, #f8fafc)" } : {}
4827
+ } : void 0,
4828
+ children: /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { className: isFixed ? "flex flex-col gap-3" : "flex flex-col gap-3 min-w-[150px]", children: [
4829
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { className: "flex items-center justify-between gap-2", children: [
4830
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(ITText, { as: "span", className: "text-slate-900 dark:text-white font-bold", children: col.label }),
4831
+ col.sortable && col.type !== "actions" && /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
4832
+ "button",
4833
+ {
4834
+ onClick: () => handleSort(col.key),
4835
+ disabled: isLoading,
4836
+ className: `p-1 rounded-md transition-colors ${sortConfig?.key === col.key ? "bg-secondary-200 text-secondary-900" : "hover:bg-secondary-200 text-secondary-400 hover:text-secondary-700"} disabled:opacity-50`,
4837
+ title: `Ordenar por ${col.label}`,
4838
+ children: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(import_md.MdOutlineSwapVert, { className: "w-4 h-4", "aria-hidden": "true" })
4839
+ }
4840
+ )
4841
+ ] }),
4842
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("div", { className: "w-full", children: col.filter ? renderFilterInput(col) : null })
4843
+ ] })
4844
+ },
4845
+ col.key
4846
+ ))
4616
4847
  }
4617
4848
  ) }),
4618
- variant,
4619
- size,
4620
- disabled,
4621
- required,
4622
- touched,
4623
- error: !isValidDate ? "Fecha inv\xE1lida" : error,
4624
- onClick: handleIconClick
4625
- }
4626
- ),
4627
- isOpen && (0, import_react_dom3.createPortal)(
4628
- /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
4629
- "div",
4630
- {
4631
- ref: panelRef,
4632
- className: (0, import_clsx22.default)(
4633
- calendarClassName,
4634
- range ? "w-[320px]" : "w-[280px]"
4635
- ),
4636
- style: {
4637
- ...panelStyle,
4638
- backgroundColor: theme.card.backgroundColor,
4639
- borderColor: theme.card.borderColor,
4640
- borderWidth: "1px",
4641
- borderStyle: "solid",
4642
- borderRadius: theme.card.borderRadius,
4643
- boxShadow: theme.card.shadow,
4644
- padding: "0.5rem"
4849
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("tbody", { className: (0, import_clsx23.default)(tableBody, "dark:divide-slate-700/30"), children: data.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)(import_jsx_runtime23.Fragment, { children: [
4850
+ isTableVirtual && topSpacerHeight > 0 && /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("tr", { "aria-hidden": "true", style: { height: topSpacerHeight }, children: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("td", { colSpan: columnCount, style: { padding: 0, border: 0 } }) }),
4851
+ windowData.map((row, windowIndex) => {
4852
+ const absoluteIndex = isTableVirtual ? startIndex + windowIndex : windowIndex;
4853
+ return /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
4854
+ "tr",
4855
+ {
4856
+ "aria-rowindex": isTableVirtual ? absoluteIndex + 2 : void 0,
4857
+ className: (0, import_clsx23.default)(
4858
+ tableRow,
4859
+ variant === "striped" && absoluteIndex % 2 === 0 && "bg-secondary-50/40 dark:bg-slate-800/20",
4860
+ onRowClick && !isLoading && tableRowClickable
4861
+ ),
4862
+ tabIndex: onRowClick && !isLoading ? 0 : void 0,
4863
+ onClick: onRowClick && !isLoading ? handleRowClick(row) : void 0,
4864
+ onKeyDown: onRowClick && !isLoading ? handleRowKeyDown(row) : void 0,
4865
+ children: columns.map((col) => {
4866
+ const rawValue = getNestedValue2(row, col.key);
4867
+ const truncateTitle = col.truncate && (typeof rawValue === "string" || typeof rawValue === "number") ? String(rawValue) : void 0;
4868
+ return /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
4869
+ "td",
4870
+ {
4871
+ className: (0, import_clsx23.default)(
4872
+ tableCell(col.className, density),
4873
+ col.align && tableAlignClasses[col.align]
4874
+ ),
4875
+ style: col.minWidth != null ? { minWidth: `${col.minWidth}px` } : void 0,
4876
+ title: truncateTitle,
4877
+ children: col.type === "actions" ? /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("div", { className: tableActionsCell, children: renderCellContent(col, row) }) : /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("div", { className: (0, import_clsx23.default)(tableCellText, col.truncate && "truncate"), children: renderCellContent(col, row) })
4878
+ },
4879
+ `${absoluteIndex}-${col.key}`
4880
+ );
4881
+ })
4882
+ },
4883
+ absoluteIndex
4884
+ );
4885
+ }),
4886
+ isTableVirtual && bottomSpacerHeight > 0 && /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("tr", { "aria-hidden": "true", style: { height: bottomSpacerHeight }, children: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("td", { colSpan: columnCount, style: { padding: 0, border: 0 } }) })
4887
+ ] }) : /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("tr", { children: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("td", { colSpan: columns.length, className: "px-6 py-12 text-center", children: !isLoading && /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { className: tableEmptyContent, children: [
4888
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(ITText, { as: "span", className: "text-lg", children: "No se encontraron resultados" }),
4889
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(ITText, { as: "span", className: "text-sm mt-1", children: "Intenta ajustar los filtros" })
4890
+ ] }) }) }) })
4891
+ ]
4892
+ }
4893
+ );
4894
+ return /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { ref: rootRef, className: (0, import_clsx23.default)("space-y-4 w-full relative", containerClassName), children: [
4895
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { className: tableContainer, style: { backgroundColor: "var(--color-table-rowBg, #ffffff)" }, children: [
4896
+ title && /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { className: "px-6 py-5 flex items-center justify-between", style: { backgroundColor: "var(--color-table-rowBg, #ffffff)" }, children: [
4897
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(ITText, { as: "h2", className: "text-xl font-bold text-secondary-900 leading-tight", children: title }),
4898
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { className: "flex items-center gap-3", children: [
4899
+ isLoading && /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("div", { className: "text-secondary-400", children: loadingIndicator || /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(import_fa13.FaSpinner, { className: "animate-spin text-primary-500 text-xl" }) }),
4900
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { className: "flex items-center bg-slate-100 dark:bg-slate-800/80 rounded-lg p-0.5 border border-slate-200 dark:border-slate-700/50", children: [
4901
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("button", { onClick: () => setViewMode("table"), disabled: forcedCards, className: segCtrlClass("table"), children: [
4902
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(import_fa13.FaTable, { size: 11 }),
4903
+ "Table"
4904
+ ] }),
4905
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("button", { onClick: () => setViewMode("cards"), className: segCtrlClass("cards"), children: [
4906
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(import_fa13.FaThLarge, { size: 11 }),
4907
+ "Cards"
4908
+ ] })
4909
+ ] })
4910
+ ] })
4911
+ ] }),
4912
+ !title && /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("div", { className: "flex justify-end px-4 pt-3", children: /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { className: "flex items-center bg-slate-100 dark:bg-slate-800/80 rounded-lg p-0.5 border border-slate-200 dark:border-slate-700/50", children: [
4913
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("button", { onClick: () => setViewMode("table"), disabled: forcedCards, className: segCtrlClass("table"), children: [
4914
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(import_fa13.FaTable, { size: 11 }),
4915
+ "Table"
4916
+ ] }),
4917
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("button", { onClick: () => setViewMode("cards"), className: segCtrlClass("cards"), children: [
4918
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(import_fa13.FaThLarge, { size: 11 }),
4919
+ "Cards"
4920
+ ] })
4921
+ ] }) }),
4922
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { className: scrollOuterClass, children: [
4923
+ isLoading && /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("div", { className: "absolute inset-0 z-20 flex items-center justify-center bg-white/40 backdrop-blur-[2px] transition-all duration-300", children: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("div", { className: "flex flex-col items-center gap-3 p-6 rounded-2xl shadow-xl border border-secondary-100 animate-in fade-in zoom-in duration-300", style: { backgroundColor: "var(--color-table-rowBg, #ffffff)" }, children: loadingIndicator || /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)(import_jsx_runtime23.Fragment, { children: [
4924
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(import_fa13.FaSpinner, { className: "animate-spin text-primary-500 text-4xl" }),
4925
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(ITText, { as: "span", className: "text-sm font-semibold text-secondary-600 animate-pulse", children: "Cargando datos..." })
4926
+ ] }) }) }),
4927
+ effectiveView === "cards" ? /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("div", { className: "p-4 space-y-3 max-h-[400px] overflow-y-auto", children: data.length > 0 ? data.map((row, i) => /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
4928
+ "div",
4929
+ {
4930
+ className: (0, import_clsx23.default)(tableCardHover, onRowClick && !isLoading && tableCardClickable),
4931
+ role: onRowClick && !isLoading ? "button" : void 0,
4932
+ tabIndex: onRowClick && !isLoading ? 0 : void 0,
4933
+ onClick: onRowClick && !isLoading ? handleRowClick(row) : void 0,
4934
+ onKeyDown: onRowClick && !isLoading ? handleRowKeyDown(row) : void 0,
4935
+ children: renderCard ? renderCard(row) : renderDefaultCard(row)
4645
4936
  },
4646
- children: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
4647
- calendar_default,
4648
- {
4649
- value: !range ? startDate : void 0,
4650
- startDate,
4651
- endDate,
4652
- selectionMode: range ? "range" : "single",
4653
- onChange: handleDateChange,
4654
- minDate,
4655
- maxDate,
4656
- variant,
4657
- className: "h-auto border-none shadow-none w-full"
4658
- }
4659
- )
4660
- }
4661
- ),
4662
- document.body
4663
- )
4937
+ i
4938
+ )) : !isLoading && /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { className: (0, import_clsx23.default)(tableEmptyContent, "py-12"), children: [
4939
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(ITText, { as: "span", className: "text-lg", children: "No se encontraron resultados" }),
4940
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(ITText, { as: "span", className: "text-sm mt-1", children: "Intenta ajustar los filtros" })
4941
+ ] }) }) : isTableVirtual ? /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
4942
+ "div",
4943
+ {
4944
+ ref: scrollRef,
4945
+ className: "overflow-x-auto overflow-y-auto",
4946
+ style: { maxHeight: virtualizedMaxHeight },
4947
+ children: tableEl
4948
+ }
4949
+ ) : tableEl
4950
+ ] })
4951
+ ] }),
4952
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("div", { className: "rounded-b-xl px-6 py-4", style: { backgroundColor: "var(--color-table-rowBg, #ffffff)" }, children: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
4953
+ ITPagination,
4954
+ {
4955
+ currentPage,
4956
+ totalPages: computedTotalPages,
4957
+ onPageChange: goToPage,
4958
+ color: "primary",
4959
+ itemsPerPageOptions,
4960
+ itemsPerPage,
4961
+ onItemsPerPageChange: handleItemsPerPageChange,
4962
+ totalItems
4963
+ }
4964
+ ) })
4664
4965
  ] });
4665
4966
  }
4666
4967
 
4667
4968
  // src/components/organisms/dialog/dialog.tsx
4668
- var import_react_dom4 = require("react-dom");
4669
- var import_react22 = require("react");
4670
- var import_fa14 = require("react-icons/fa");
4969
+ var import_react_dom5 = require("react-dom");
4970
+ var import_react23 = require("react");
4971
+ var import_fa15 = require("react-icons/fa");
4671
4972
 
4672
4973
  // src/components/molecules/form-header/form-header.tsx
4673
- var import_fa13 = require("react-icons/fa");
4974
+ var import_fa14 = require("react-icons/fa");
4674
4975
 
4675
4976
  // src/theme/theme-context.ts
4676
- var import_react21 = require("react");
4677
- var ITThemeContext = (0, import_react21.createContext)(void 0);
4977
+ var import_react22 = require("react");
4978
+ var ITThemeContext = (0, import_react22.createContext)(void 0);
4678
4979
  var useITTheme = () => {
4679
- const context = (0, import_react21.useContext)(ITThemeContext);
4980
+ const context = (0, import_react22.useContext)(ITThemeContext);
4680
4981
  if (!context) {
4681
4982
  throw new Error("useITTheme must be used within an ITThemeProvider");
4682
4983
  }
4683
4984
  return context;
4684
4985
  };
4685
4986
  var useITThemeSafe = () => {
4686
- return (0, import_react21.useContext)(ITThemeContext);
4987
+ return (0, import_react22.useContext)(ITThemeContext);
4687
4988
  };
4688
4989
 
4689
4990
  // src/utils/color.utils.ts
@@ -4763,7 +5064,7 @@ var getContrastTextColor = (bgColor, palette2, isDarkMode) => {
4763
5064
  };
4764
5065
 
4765
5066
  // src/components/molecules/form-header/form-header.tsx
4766
- var import_jsx_runtime23 = require("react/jsx-runtime");
5067
+ var import_jsx_runtime24 = require("react/jsx-runtime");
4767
5068
  function ITFormHeader({
4768
5069
  title,
4769
5070
  onClose,
@@ -4777,23 +5078,23 @@ function ITFormHeader({
4777
5078
  palette2,
4778
5079
  isDarkMode
4779
5080
  );
4780
- return /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { className: `bg-primary-500 ${textColorClass} px-6 py-4 rounded-t-lg flex justify-center items-center relative ${className}`, children: [
4781
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(ITText, { as: "h2", className: "text-lg font-semibold text-center", style: { color: "inherit" }, children: title }),
4782
- onClose && /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
5081
+ return /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { className: `bg-primary-500 ${textColorClass} px-6 py-4 rounded-t-lg flex justify-center items-center relative ${className}`, children: [
5082
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(ITText, { as: "h2", className: "text-lg font-semibold text-center", style: { color: "inherit" }, children: title }),
5083
+ onClose && /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
4783
5084
  "button",
4784
5085
  {
4785
5086
  onClick: onClose,
4786
5087
  className: `absolute right-4 ${textColorClass} hover:opacity-80 transition-colors duration-200 p-1 rounded-full`,
4787
5088
  style: { color: "inherit" },
4788
5089
  "aria-label": "Cerrar",
4789
- children: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(import_fa13.FaTimes, { className: "w-4 h-4" })
5090
+ children: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(import_fa14.FaTimes, { className: "w-4 h-4" })
4790
5091
  }
4791
5092
  )
4792
5093
  ] });
4793
5094
  }
4794
5095
 
4795
5096
  // src/components/organisms/dialog/dialog.tsx
4796
- var import_jsx_runtime24 = require("react/jsx-runtime");
5097
+ var import_jsx_runtime25 = require("react/jsx-runtime");
4797
5098
  function ITDialog({
4798
5099
  isOpen,
4799
5100
  onClose,
@@ -4803,9 +5104,9 @@ function ITDialog({
4803
5104
  useFormHeader = false,
4804
5105
  fullScreen = false
4805
5106
  }) {
4806
- const modalRef = (0, import_react22.useRef)(null);
5107
+ const modalRef = (0, import_react23.useRef)(null);
4807
5108
  useClickOutside_default(modalRef, onClose);
4808
- (0, import_react22.useEffect)(() => {
5109
+ (0, import_react23.useEffect)(() => {
4809
5110
  const handleEscape = (event) => {
4810
5111
  if (event.key === "Escape") {
4811
5112
  onClose();
@@ -4820,12 +5121,12 @@ function ITDialog({
4820
5121
  }, [isOpen, onClose]);
4821
5122
  if (!isOpen) return null;
4822
5123
  if (typeof document === "undefined") return null;
4823
- const content = /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
5124
+ const content = /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
4824
5125
  "div",
4825
5126
  {
4826
5127
  "data-it-dialog": "true",
4827
5128
  className: `fixed inset-0 flex ${fullScreen ? "items-stretch" : "items-center justify-center"} bg-slate-900/50 z-[60]`,
4828
- children: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
5129
+ children: /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
4829
5130
  "div",
4830
5131
  {
4831
5132
  ref: modalRef,
@@ -4838,41 +5139,41 @@ function ITDialog({
4838
5139
  borderColor: theme.card.borderColor,
4839
5140
  borderStyle: "solid"
4840
5141
  },
4841
- children: useFormHeader && title ? /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(import_jsx_runtime24.Fragment, { children: [
4842
- /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(ITFormHeader, { title, onClose }),
4843
- /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("div", { className: fullScreen ? "flex-1 overflow-auto p-6" : "p-6", children })
4844
- ] }) : /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(import_jsx_runtime24.Fragment, { children: [
4845
- /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
5142
+ children: useFormHeader && title ? /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(import_jsx_runtime25.Fragment, { children: [
5143
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(ITFormHeader, { title, onClose }),
5144
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("div", { className: fullScreen ? "flex-1 overflow-auto p-6" : "p-6", children })
5145
+ ] }) : /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(import_jsx_runtime25.Fragment, { children: [
5146
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
4846
5147
  "button",
4847
5148
  {
4848
5149
  className: "absolute top-2 right-2 text-secondary-600 hover:text-secondary-900",
4849
5150
  onClick: onClose,
4850
- children: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(import_fa14.FaRegTimesCircle, {})
5151
+ children: /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(import_fa15.FaRegTimesCircle, {})
4851
5152
  }
4852
5153
  ),
4853
- title && /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(ITText, { as: "h2", className: "text-xl font-semibold mb-4", children: title }),
4854
- /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("div", { children })
5154
+ title && /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(ITText, { as: "h2", className: "text-xl font-semibold mb-4", children: title }),
5155
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("div", { children })
4855
5156
  ] })
4856
5157
  }
4857
5158
  )
4858
5159
  }
4859
5160
  );
4860
- return (0, import_react_dom4.createPortal)(content, document.body);
5161
+ return (0, import_react_dom5.createPortal)(content, document.body);
4861
5162
  }
4862
5163
 
4863
5164
  // src/components/atoms/divider/divider.tsx
4864
- var import_clsx23 = __toESM(require("clsx"), 1);
4865
- var import_jsx_runtime25 = require("react/jsx-runtime");
5165
+ var import_clsx24 = __toESM(require("clsx"), 1);
5166
+ var import_jsx_runtime26 = require("react/jsx-runtime");
4866
5167
  function ITDivider({
4867
5168
  orientation = "horizontal",
4868
5169
  className,
4869
5170
  color = "bg-slate-200 dark:bg-slate-700",
4870
5171
  thickness = orientation === "horizontal" ? "h-px" : "w-px"
4871
5172
  }) {
4872
- return /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
5173
+ return /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
4873
5174
  "div",
4874
5175
  {
4875
- className: (0, import_clsx23.default)(
5176
+ className: (0, import_clsx24.default)(
4876
5177
  "flex-shrink-0",
4877
5178
  orientation === "horizontal" ? "w-full" : "self-stretch",
4878
5179
  thickness,
@@ -4884,10 +5185,10 @@ function ITDivider({
4884
5185
  }
4885
5186
 
4886
5187
  // src/components/organisms/drawer/drawer.tsx
4887
- var import_clsx24 = __toESM(require("clsx"), 1);
4888
- var import_fa15 = require("react-icons/fa");
4889
- var import_react23 = require("react");
4890
- var import_jsx_runtime26 = require("react/jsx-runtime");
5188
+ var import_clsx25 = __toESM(require("clsx"), 1);
5189
+ var import_fa16 = require("react-icons/fa");
5190
+ var import_react24 = require("react");
5191
+ var import_jsx_runtime27 = require("react/jsx-runtime");
4891
5192
  function ITDrawer({
4892
5193
  isOpen,
4893
5194
  onClose,
@@ -4898,15 +5199,15 @@ function ITDrawer({
4898
5199
  className,
4899
5200
  style
4900
5201
  }) {
4901
- const panelRef = (0, import_react23.useRef)(null);
5202
+ const panelRef = (0, import_react24.useRef)(null);
4902
5203
  useClickOutside_default(panelRef, onClose);
4903
- return /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(import_jsx_runtime26.Fragment, { children: isOpen && /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("div", { className: "fixed inset-0 z-[50] flex", children: [
4904
- /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("div", { className: "absolute inset-0 bg-black/40 backdrop-blur-sm transition-opacity" }),
4905
- /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(
5204
+ return /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(import_jsx_runtime27.Fragment, { children: isOpen && /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("div", { className: "fixed inset-0 z-[50] flex", children: [
5205
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("div", { className: "absolute inset-0 bg-black/40 backdrop-blur-sm transition-opacity" }),
5206
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)(
4906
5207
  "div",
4907
5208
  {
4908
5209
  ref: panelRef,
4909
- className: (0, import_clsx24.default)(
5210
+ className: (0, import_clsx25.default)(
4910
5211
  "relative z-10 h-full bg-white dark:bg-slate-900 shadow-2xl flex flex-col transition-transform duration-300",
4911
5212
  position === "right" ? "ml-auto" : "mr-auto",
4912
5213
  size,
@@ -4914,18 +5215,18 @@ function ITDrawer({
4914
5215
  ),
4915
5216
  style,
4916
5217
  children: [
4917
- title && /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("div", { className: "flex items-center justify-between px-5 py-4 border-b border-slate-200 dark:border-slate-700", children: [
4918
- /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(ITText, { as: "h2", className: "text-lg font-bold text-slate-800 dark:text-white", children: title }),
4919
- /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
5218
+ title && /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("div", { className: "flex items-center justify-between px-5 py-4 border-b border-slate-200 dark:border-slate-700", children: [
5219
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(ITText, { as: "h2", className: "text-lg font-bold text-slate-800 dark:text-white", children: title }),
5220
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
4920
5221
  "button",
4921
5222
  {
4922
5223
  onClick: onClose,
4923
5224
  className: "w-8 h-8 flex items-center justify-center rounded-lg hover:bg-slate-100 dark:hover:bg-slate-800 text-slate-400 hover:text-slate-600 transition-colors",
4924
- children: /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(import_fa15.FaTimes, { size: 14 })
5225
+ children: /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(import_fa16.FaTimes, { size: 14 })
4925
5226
  }
4926
5227
  )
4927
5228
  ] }),
4928
- /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("div", { className: "flex-1 overflow-y-auto p-5", children })
5229
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("div", { className: "flex-1 overflow-y-auto p-5", children })
4929
5230
  ]
4930
5231
  }
4931
5232
  )
@@ -4933,27 +5234,27 @@ function ITDrawer({
4933
5234
  }
4934
5235
 
4935
5236
  // src/components/molecules/empty-state/empty-state.tsx
4936
- var import_clsx25 = __toESM(require("clsx"), 1);
4937
- var import_fa16 = require("react-icons/fa");
4938
- var import_jsx_runtime27 = require("react/jsx-runtime");
5237
+ var import_clsx26 = __toESM(require("clsx"), 1);
5238
+ var import_fa17 = require("react-icons/fa");
5239
+ var import_jsx_runtime28 = require("react/jsx-runtime");
4939
5240
  function ITEmptyState({
4940
- icon = /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(import_fa16.FaInbox, { size: 40 }),
5241
+ icon = /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(import_fa17.FaInbox, { size: 40 }),
4941
5242
  title,
4942
5243
  description,
4943
5244
  action,
4944
5245
  className
4945
5246
  }) {
4946
- return /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("div", { className: (0, import_clsx25.default)("flex flex-col items-center justify-center py-16 px-6 text-center", className), children: [
4947
- /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("div", { className: "text-slate-300 dark:text-slate-600 mb-4", children: icon }),
4948
- /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(ITText, { as: "h3", className: "text-lg font-bold text-slate-700 dark:text-slate-200 mb-1", children: title }),
4949
- description && /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(ITText, { as: "p", className: "text-sm text-slate-400 dark:text-slate-500 max-w-sm mb-4", children: description }),
4950
- action && /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("div", { children: action })
5247
+ return /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)("div", { className: (0, import_clsx26.default)("flex flex-col items-center justify-center py-16 px-6 text-center", className), children: [
5248
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("div", { className: "text-slate-300 dark:text-slate-600 mb-4", children: icon }),
5249
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(ITText, { as: "h3", className: "text-lg font-bold text-slate-700 dark:text-slate-200 mb-1", children: title }),
5250
+ description && /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(ITText, { as: "p", className: "text-sm text-slate-400 dark:text-slate-500 max-w-sm mb-4", children: description }),
5251
+ action && /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("div", { children: action })
4951
5252
  ] });
4952
5253
  }
4953
5254
 
4954
5255
  // src/components/atoms/flex/flex.tsx
4955
- var import_clsx26 = __toESM(require("clsx"), 1);
4956
- var import_jsx_runtime28 = require("react/jsx-runtime");
5256
+ var import_clsx27 = __toESM(require("clsx"), 1);
5257
+ var import_jsx_runtime29 = require("react/jsx-runtime");
4957
5258
  var directionMap = {
4958
5259
  row: "flex-row",
4959
5260
  column: "flex-col",
@@ -5002,10 +5303,10 @@ function ITFlex({
5002
5303
  flexBasis: typeof basis === "number" ? `${basis * 0.25}rem` : basis,
5003
5304
  ...style
5004
5305
  };
5005
- return /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
5306
+ return /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
5006
5307
  Component,
5007
5308
  {
5008
- className: (0, import_clsx26.default)(
5309
+ className: (0, import_clsx27.default)(
5009
5310
  "flex",
5010
5311
  directionMap[direction],
5011
5312
  align && alignMap[align],
@@ -5024,33 +5325,33 @@ function ITFlex({
5024
5325
  var import_react29 = require("react");
5025
5326
 
5026
5327
  // src/components/organisms/form-builder/formBuilder.context.tsx
5027
- var import_react24 = __toESM(require("react"), 1);
5028
- var import_jsx_runtime29 = require("react/jsx-runtime");
5029
- var ITFormBuilderContext = (0, import_react24.createContext)(void 0);
5328
+ var import_react25 = __toESM(require("react"), 1);
5329
+ var import_jsx_runtime30 = require("react/jsx-runtime");
5330
+ var ITFormBuilderContext = (0, import_react25.createContext)(void 0);
5030
5331
  var ITFormBuilderProvider = ({
5031
5332
  children,
5032
5333
  value
5033
5334
  }) => {
5034
- const [fieldRegistry, setFieldRegistry] = (0, import_react24.useState)({});
5035
- const registerField = import_react24.default.useCallback((name, config2) => {
5335
+ const [fieldRegistry, setFieldRegistry] = (0, import_react25.useState)({});
5336
+ const registerField = import_react25.default.useCallback((name, config2) => {
5036
5337
  setFieldRegistry((prev) => ({ ...prev, [name]: config2 }));
5037
5338
  }, []);
5038
- const unregisterField = import_react24.default.useCallback((name) => {
5339
+ const unregisterField = import_react25.default.useCallback((name) => {
5039
5340
  setFieldRegistry((prev) => {
5040
5341
  const next = { ...prev };
5041
5342
  delete next[name];
5042
5343
  return next;
5043
5344
  });
5044
5345
  }, []);
5045
- const getFieldConfig = import_react24.default.useCallback(
5346
+ const getFieldConfig = import_react25.default.useCallback(
5046
5347
  (name) => fieldRegistry[name],
5047
5348
  [fieldRegistry]
5048
5349
  );
5049
- const getAllFieldConfigs = import_react24.default.useCallback(
5350
+ const getAllFieldConfigs = import_react25.default.useCallback(
5050
5351
  () => Object.values(fieldRegistry),
5051
5352
  [fieldRegistry]
5052
5353
  );
5053
- const contextValue = import_react24.default.useMemo(
5354
+ const contextValue = import_react25.default.useMemo(
5054
5355
  () => ({
5055
5356
  ...value,
5056
5357
  registerField,
@@ -5060,10 +5361,10 @@ var ITFormBuilderProvider = ({
5060
5361
  }),
5061
5362
  [value, registerField, unregisterField, getFieldConfig, getAllFieldConfigs]
5062
5363
  );
5063
- return /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(ITFormBuilderContext.Provider, { value: contextValue, children });
5364
+ return /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(ITFormBuilderContext.Provider, { value: contextValue, children });
5064
5365
  };
5065
5366
  var useITFormBuilderContext = () => {
5066
- const context = (0, import_react24.useContext)(ITFormBuilderContext);
5367
+ const context = (0, import_react25.useContext)(ITFormBuilderContext);
5067
5368
  if (!context) {
5068
5369
  throw new Error("useITFormBuilderContext must be used within an ITFormBuilderProvider");
5069
5370
  }
@@ -5075,11 +5376,11 @@ var import_react28 = require("react");
5075
5376
  var import_clsx29 = __toESM(require("clsx"), 1);
5076
5377
 
5077
5378
  // src/components/molecules/time-picker/timePicker.tsx
5078
- var import_clsx27 = __toESM(require("clsx"), 1);
5079
- var import_react25 = require("react");
5080
- var import_react_dom5 = require("react-dom");
5081
- var import_fa17 = require("react-icons/fa");
5082
- var import_jsx_runtime30 = require("react/jsx-runtime");
5379
+ var import_clsx28 = __toESM(require("clsx"), 1);
5380
+ var import_react26 = require("react");
5381
+ var import_react_dom6 = require("react-dom");
5382
+ var import_fa18 = require("react-icons/fa");
5383
+ var import_jsx_runtime31 = require("react/jsx-runtime");
5083
5384
  function ITTimePicker({
5084
5385
  name,
5085
5386
  value,
@@ -5096,12 +5397,12 @@ function ITTimePicker({
5096
5397
  variant = "primary",
5097
5398
  color = "primary"
5098
5399
  }) {
5099
- const [isOpen, setIsOpen] = (0, import_react25.useState)(false);
5100
- const [inputValue, setInputValue] = (0, import_react25.useState)(value || "");
5101
- const [isValidTime, setIsValidTime] = (0, import_react25.useState)(true);
5102
- const wrapperRef = (0, import_react25.useRef)(null);
5103
- const hoursRef = (0, import_react25.useRef)(null);
5104
- const minutesRef = (0, import_react25.useRef)(null);
5400
+ const [isOpen, setIsOpen] = (0, import_react26.useState)(false);
5401
+ const [inputValue, setInputValue] = (0, import_react26.useState)(value || "");
5402
+ const [isValidTime, setIsValidTime] = (0, import_react26.useState)(true);
5403
+ const wrapperRef = (0, import_react26.useRef)(null);
5404
+ const hoursRef = (0, import_react26.useRef)(null);
5405
+ const minutesRef = (0, import_react26.useRef)(null);
5105
5406
  const { panelRef: dropdownRef, style: panelStyle } = useFloatingPanel(
5106
5407
  wrapperRef,
5107
5408
  isOpen && !disabled,
@@ -5115,7 +5416,7 @@ function ITTimePicker({
5115
5416
  const isThemeColor = color in theme.colors;
5116
5417
  const highlightColor = isThemeColor ? theme.colors[color][50] : "#f3f4f6";
5117
5418
  const activeColor = isThemeColor ? theme.colors[color][100] : "#e5e7eb";
5118
- (0, import_react25.useEffect)(() => {
5419
+ (0, import_react26.useEffect)(() => {
5119
5420
  setInputValue(value || "");
5120
5421
  }, [value]);
5121
5422
  const validateTime = (timeString) => {
@@ -5124,7 +5425,7 @@ function ITTimePicker({
5124
5425
  };
5125
5426
  const currentHour = validateTime(inputValue) ? inputValue.split(":")[0] : null;
5126
5427
  const currentMinute = validateTime(inputValue) ? inputValue.split(":")[1] : null;
5127
- (0, import_react25.useEffect)(() => {
5428
+ (0, import_react26.useEffect)(() => {
5128
5429
  if (isOpen) {
5129
5430
  setTimeout(() => {
5130
5431
  if (hoursRef.current && currentHour) {
@@ -5194,8 +5495,8 @@ function ITTimePicker({
5194
5495
  { length: 60 },
5195
5496
  (_, i) => i.toString().padStart(2, "0")
5196
5497
  );
5197
- return /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("div", { ref: wrapperRef, className: (0, import_clsx27.default)("relative w-full", className), children: [
5198
- /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
5498
+ return /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)("div", { ref: wrapperRef, className: (0, import_clsx28.default)("relative w-full", className), children: [
5499
+ /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
5199
5500
  ITInput,
5200
5501
  {
5201
5502
  name,
@@ -5212,15 +5513,15 @@ function ITTimePicker({
5212
5513
  size,
5213
5514
  touched,
5214
5515
  error: !isValidTime ? "Hora inv\xE1lida" : typeof error === "string" ? error : void 0,
5215
- iconRight: /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
5216
- import_fa17.FaClock,
5516
+ iconRight: /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
5517
+ import_fa18.FaClock,
5217
5518
  {
5218
5519
  onClick: () => {
5219
5520
  if (!disabled) {
5220
5521
  setIsOpen(!isOpen);
5221
5522
  }
5222
5523
  },
5223
- className: (0, import_clsx27.default)(
5524
+ className: (0, import_clsx28.default)(
5224
5525
  "cursor-pointer transition-colors",
5225
5526
  disabled ? "text-slate-400 cursor-not-allowed" : "text-slate-500 dark:text-slate-400 hover:text-slate-700 dark:hover:text-slate-200"
5226
5527
  )
@@ -5228,31 +5529,31 @@ function ITTimePicker({
5228
5529
  )
5229
5530
  }
5230
5531
  ),
5231
- isOpen && !disabled && (0, import_react_dom5.createPortal)(
5232
- /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)(
5532
+ isOpen && !disabled && (0, import_react_dom6.createPortal)(
5533
+ /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)(
5233
5534
  "div",
5234
5535
  {
5235
5536
  ref: dropdownRef,
5236
5537
  className: "bg-white border border-secondary-100 shadow-xl rounded-xl w-64 overflow-hidden flex flex-col animate-in fade-in zoom-in-95 duration-200 origin-top it-timepicker-dropdown",
5237
5538
  style: panelStyle,
5238
5539
  children: [
5239
- /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("div", { className: "flex bg-secondary-50 border-b border-secondary-100 text-xs font-semibold text-secondary-500 uppercase tracking-wider", children: [
5240
- /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(ITText, { as: "div", className: "flex-1 text-center py-2 border-r border-secondary-100", children: "Horas" }),
5241
- /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(ITText, { as: "div", className: "flex-1 text-center py-2", children: "Minutos" })
5540
+ /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)("div", { className: "flex bg-secondary-50 border-b border-secondary-100 text-xs font-semibold text-secondary-500 uppercase tracking-wider", children: [
5541
+ /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(ITText, { as: "div", className: "flex-1 text-center py-2 border-r border-secondary-100", children: "Horas" }),
5542
+ /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(ITText, { as: "div", className: "flex-1 text-center py-2", children: "Minutos" })
5242
5543
  ] }),
5243
- /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("div", { className: "flex h-56 relative bg-white", children: [
5244
- /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
5544
+ /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)("div", { className: "flex h-56 relative bg-white", children: [
5545
+ /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
5245
5546
  "div",
5246
5547
  {
5247
5548
  ref: hoursRef,
5248
5549
  className: "flex-1 overflow-y-auto no-scrollbar border-r border-secondary-50 scroll-smooth relative",
5249
- children: /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("div", { className: "py-2", children: hoursList.map((h) => {
5550
+ children: /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("div", { className: "py-2", children: hoursList.map((h) => {
5250
5551
  const isSelected = currentHour === h;
5251
- return /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
5552
+ return /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
5252
5553
  "div",
5253
5554
  {
5254
5555
  "data-value": h,
5255
- className: (0, import_clsx27.default)(
5556
+ className: (0, import_clsx28.default)(
5256
5557
  "text-center py-2 cursor-pointer transition-all duration-200 text-sm font-medium mx-2 rounded-lg my-1",
5257
5558
  isSelected ? "text-slate-900 shadow-sm" : "text-slate-600 hover:text-slate-900"
5258
5559
  ),
@@ -5275,18 +5576,18 @@ function ITTimePicker({
5275
5576
  }) })
5276
5577
  }
5277
5578
  ),
5278
- /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
5579
+ /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
5279
5580
  "div",
5280
5581
  {
5281
5582
  ref: minutesRef,
5282
5583
  className: "flex-1 overflow-y-auto no-scrollbar scroll-smooth relative",
5283
- children: /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("div", { className: "py-2", children: minutesList.map((m) => {
5584
+ children: /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("div", { className: "py-2", children: minutesList.map((m) => {
5284
5585
  const isSelected = currentMinute === m;
5285
- return /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
5586
+ return /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
5286
5587
  "div",
5287
5588
  {
5288
5589
  "data-value": m,
5289
- className: (0, import_clsx27.default)(
5590
+ className: (0, import_clsx28.default)(
5290
5591
  "text-center py-2 cursor-pointer transition-all duration-200 text-sm font-medium mx-2 rounded-lg my-1",
5291
5592
  isSelected ? "text-slate-900 shadow-sm" : "text-slate-600 hover:text-slate-900"
5292
5593
  ),
@@ -5309,16 +5610,16 @@ function ITTimePicker({
5309
5610
  }) })
5310
5611
  }
5311
5612
  ),
5312
- /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("div", { className: "absolute top-1/2 left-0 right-0 h-10 -mt-5 bg-black/5 pointer-events-none border-y border-black/10 z-10" })
5613
+ /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("div", { className: "absolute top-1/2 left-0 right-0 h-10 -mt-5 bg-black/5 pointer-events-none border-y border-black/10 z-10" })
5313
5614
  ] }),
5314
- /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("div", { className: "p-3 bg-secondary-50 border-t border-secondary-100 flex justify-end", children: /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
5615
+ /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("div", { className: "p-3 bg-secondary-50 border-t border-secondary-100 flex justify-end", children: /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
5315
5616
  ITButton,
5316
5617
  {
5317
5618
  variant: "solid",
5318
5619
  color,
5319
5620
  size: "sm",
5320
5621
  onClick: handleConfirm,
5321
- children: /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(ITText, { as: "span", children: "Aceptar" })
5622
+ children: /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(ITText, { as: "span", children: "Aceptar" })
5322
5623
  }
5323
5624
  ) })
5324
5625
  ]
@@ -5329,236 +5630,6 @@ function ITTimePicker({
5329
5630
  ] });
5330
5631
  }
5331
5632
 
5332
- // src/components/molecules/search-select/search-select.tsx
5333
- var import_react26 = require("react");
5334
- var import_react_dom6 = require("react-dom");
5335
- var import_clsx28 = __toESM(require("clsx"), 1);
5336
- var import_fa18 = require("react-icons/fa");
5337
- var import_jsx_runtime31 = require("react/jsx-runtime");
5338
- function ITSearchSelect({
5339
- name,
5340
- options = [],
5341
- label,
5342
- placeholder = "Selecciona una opci\xF3n",
5343
- valueField = "value",
5344
- labelField = "label",
5345
- value,
5346
- onChange,
5347
- onBlur,
5348
- disabled = false,
5349
- className,
5350
- touched,
5351
- required,
5352
- error,
5353
- readOnly = false,
5354
- onSearch,
5355
- isLoading = false,
5356
- noResultsMessage = "No se encontraron resultados",
5357
- size = "md",
5358
- renderOption,
5359
- clearable = true,
5360
- onClear
5361
- }) {
5362
- const [isOpen, setIsOpen] = (0, import_react26.useState)(false);
5363
- const [searchTerm, setSearchTerm] = (0, import_react26.useState)("");
5364
- const [isFocused, setIsFocused] = (0, import_react26.useState)(false);
5365
- const [localTouched, setLocalTouched] = (0, import_react26.useState)(false);
5366
- const containerRef = (0, import_react26.useRef)(null);
5367
- const inputWrapperRef = (0, import_react26.useRef)(null);
5368
- const timeoutRef = (0, import_react26.useRef)(null);
5369
- const { panelRef, style: panelStyle } = useFloatingPanel(inputWrapperRef, isOpen, {
5370
- estimatedHeight: 260,
5371
- matchWidth: true
5372
- });
5373
- const selectedOption = (0, import_react26.useMemo)(() => {
5374
- return options.find((opt) => opt[valueField] === value);
5375
- }, [options, value, valueField]);
5376
- (0, import_react26.useEffect)(() => {
5377
- if (!isFocused) {
5378
- setSearchTerm(selectedOption ? String(selectedOption[labelField]) : "");
5379
- }
5380
- }, [selectedOption, isFocused, labelField]);
5381
- (0, import_react26.useEffect)(() => {
5382
- function handleClickOutside(event) {
5383
- const target = event.target;
5384
- const inContainer = containerRef.current?.contains(target);
5385
- const inPanel = panelRef.current?.contains(target);
5386
- if (!inContainer && !inPanel) {
5387
- setIsOpen(false);
5388
- }
5389
- }
5390
- document.addEventListener("mousedown", handleClickOutside);
5391
- return () => document.removeEventListener("mousedown", handleClickOutside);
5392
- }, []);
5393
- const selectedLabel = selectedOption ? String(selectedOption[labelField]) : "";
5394
- const filteredOptions = (0, import_react26.useMemo)(() => {
5395
- if (onSearch) return options;
5396
- if (!searchTerm || !isFocused || searchTerm === selectedLabel) return options;
5397
- return options.filter(
5398
- (opt) => String(opt[labelField]).toLowerCase().includes(searchTerm.toLowerCase())
5399
- );
5400
- }, [options, searchTerm, selectedLabel, onSearch, labelField, isFocused]);
5401
- const handleInputChange = (e) => {
5402
- const query = e.target.value;
5403
- setSearchTerm(query);
5404
- setIsOpen(true);
5405
- if (onSearch) {
5406
- if (timeoutRef.current) clearTimeout(timeoutRef.current);
5407
- timeoutRef.current = setTimeout(() => {
5408
- onSearch(query);
5409
- }, 500);
5410
- }
5411
- };
5412
- const handleSelect = (option) => {
5413
- if (onChange) {
5414
- onChange(option[valueField], option);
5415
- }
5416
- setSearchTerm(String(option[labelField]));
5417
- setIsOpen(false);
5418
- };
5419
- const handleClear = () => {
5420
- setSearchTerm("");
5421
- setIsOpen(true);
5422
- if (onSearch) onSearch("");
5423
- if (value !== void 0 && value !== null && value !== "") {
5424
- onChange?.("", void 0);
5425
- }
5426
- onClear?.();
5427
- };
5428
- const handleFocus = () => {
5429
- if (disabled || readOnly) return;
5430
- setIsFocused(true);
5431
- setIsOpen(true);
5432
- };
5433
- const handleInputBlur = (e) => {
5434
- setTimeout(() => {
5435
- setIsFocused(false);
5436
- setLocalTouched(true);
5437
- onBlur?.(e);
5438
- }, 200);
5439
- };
5440
- const inputTheme = theme.input || {};
5441
- const isTouched = touched !== void 0 ? touched : localTouched;
5442
- const isEmpty = value === void 0 || value === null || String(value).trim() === "";
5443
- const effectiveError = error !== void 0 && error !== false ? error === true ? "Este campo es requerido" : error : required && isEmpty ? "Este campo es requerido" : void 0;
5444
- const hasError = isTouched && !!effectiveError;
5445
- const errorMessage = typeof effectiveError === "string" ? effectiveError : "Este campo es requerido";
5446
- const showClearButton = clearable && !disabled && !readOnly && (searchTerm.length > 0 || !isEmpty);
5447
- const getInputStyle = () => {
5448
- const sizeConfig = inputSizeTokens[size] ?? inputSizeTokens.md;
5449
- const style = {
5450
- backgroundColor: inputTheme.backgroundColor || "#ffffff",
5451
- borderColor: inputTheme.borderColor || "var(--color-secondary-300)",
5452
- borderRadius: inputTheme.borderRadius || "0.5rem",
5453
- padding: sizeConfig.padding,
5454
- fontSize: sizeConfig.fontSize,
5455
- borderWidth: "1px",
5456
- borderStyle: "solid",
5457
- transition: "all 0.2s",
5458
- color: "var(--it-input-text-color, var(--color-secondary-900))",
5459
- width: "100%"
5460
- };
5461
- if (disabled) {
5462
- style.backgroundColor = inputTheme.disabled?.backgroundColor || "var(--color-secondary-100)";
5463
- style.borderColor = inputTheme.disabled?.borderColor || "var(--color-secondary-200)";
5464
- style.opacity = 0.7;
5465
- style.cursor = "not-allowed";
5466
- }
5467
- if (hasError) {
5468
- style.borderColor = inputTheme.error?.borderColor || "red";
5469
- if (isFocused) {
5470
- style.boxShadow = inputTheme.error?.ring;
5471
- }
5472
- } else if (isFocused && !readOnly) {
5473
- style.boxShadow = inputTheme.focus?.ring;
5474
- style.borderColor = inputTheme.focus?.borderColor;
5475
- }
5476
- return style;
5477
- };
5478
- return /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)("div", { className: (0, import_clsx28.default)("w-full flex flex-col gap-1.5", className, isOpen && "relative z-30"), ref: containerRef, children: [
5479
- label && /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)(
5480
- ITText,
5481
- {
5482
- as: "label",
5483
- className: (0, import_clsx28.default)("text-sm font-medium text-secondary-700 dark:text-slate-300", {
5484
- "text-danger-500": hasError
5485
- }),
5486
- children: [
5487
- /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(ITText, { as: "span", children: label }),
5488
- required && /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(ITText, { as: "span", className: "text-danger-500 ml-1", children: "*" })
5489
- ]
5490
- }
5491
- ),
5492
- /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)("div", { className: "relative", children: [
5493
- /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)("div", { ref: inputWrapperRef, className: "relative flex items-center", children: [
5494
- /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
5495
- "input",
5496
- {
5497
- type: "text",
5498
- name,
5499
- value: searchTerm,
5500
- onChange: handleInputChange,
5501
- onFocus: handleFocus,
5502
- onBlur: handleInputBlur,
5503
- disabled,
5504
- readOnly,
5505
- placeholder,
5506
- className: "outline-none pr-10",
5507
- style: getInputStyle(),
5508
- autoComplete: "off"
5509
- }
5510
- ),
5511
- /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)("div", { className: "absolute right-3 flex items-center gap-2 text-secondary-400", children: [
5512
- isLoading && /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("div", { className: "pointer-events-none animate-spin h-4 w-4 border-2 border-primary-500 border-t-transparent rounded-full" }),
5513
- !isLoading && showClearButton && /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
5514
- "button",
5515
- {
5516
- type: "button",
5517
- "aria-label": "Limpiar",
5518
- title: "Limpiar",
5519
- onMouseDown: (e) => {
5520
- e.preventDefault();
5521
- handleClear();
5522
- },
5523
- className: "flex items-center justify-center text-secondary-400 hover:text-secondary-600 focus:outline-none focus-visible:ring-2 focus-visible:ring-primary-400 rounded-full",
5524
- children: /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(import_fa18.FaTimes, { size: 14 })
5525
- }
5526
- ),
5527
- !isLoading && !showClearButton && /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(import_fa18.FaSearch, { size: 14, className: (0, import_clsx28.default)("pointer-events-none", { "text-primary-500": isFocused }) })
5528
- ] })
5529
- ] }),
5530
- isOpen && (0, import_react_dom6.createPortal)(
5531
- /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
5532
- "div",
5533
- {
5534
- ref: panelRef,
5535
- style: panelStyle,
5536
- className: "bg-white dark:bg-slate-900 border border-secondary-200 dark:border-slate-800 rounded-lg shadow-xl overflow-hidden animate-in fade-in zoom-in duration-200 origin-top",
5537
- children: /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("div", { className: "max-h-60 overflow-y-auto", children: filteredOptions.length > 0 ? filteredOptions.map((option) => {
5538
- const isSelected = value === option[valueField];
5539
- return /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
5540
- ITText,
5541
- {
5542
- as: "div",
5543
- onClick: () => handleSelect(option),
5544
- className: (0, import_clsx28.default)(
5545
- "px-4 py-2 text-sm cursor-pointer transition-colors",
5546
- isSelected ? "bg-primary-50 dark:bg-primary-950/40 text-primary-700 dark:text-primary-300 font-medium" : "hover:bg-secondary-50 dark:hover:bg-slate-800 text-secondary-700 dark:text-slate-300"
5547
- ),
5548
- children: renderOption ? renderOption(option, { isSelected, searchTerm }) : /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(ITText, { as: "span", children: option[labelField] })
5549
- },
5550
- option[valueField]
5551
- );
5552
- }) : /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(ITText, { as: "div", className: "px-4 py-6 text-sm text-center text-secondary-500 italic", children: isLoading ? "Cargando..." : noResultsMessage }) })
5553
- }
5554
- ),
5555
- document.body
5556
- )
5557
- ] }),
5558
- hasError && /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(ITText, { as: "p", className: "text-danger-500 text-xs mt-1", children: errorMessage })
5559
- ] });
5560
- }
5561
-
5562
5633
  // src/components/organisms/form-builder/useFormBuilder.ts
5563
5634
  var import_react27 = require("react");
5564
5635
  var useFieldRules = (config2, dependentValues) => {
@@ -7985,6 +8056,7 @@ var import_clsx43 = __toESM(require("clsx"), 1);
7985
8056
  var import_react37 = __toESM(require("react"), 1);
7986
8057
  var import_fa27 = require("react-icons/fa");
7987
8058
  var import_md2 = require("react-icons/md");
8059
+ var import_date_fns3 = require("date-fns");
7988
8060
  var import_jsx_runtime60 = require("react/jsx-runtime");
7989
8061
  function ITTable({
7990
8062
  columns,
@@ -8068,15 +8140,32 @@ function ITTable({
8068
8140
  }, [data, sortConfig, columns]);
8069
8141
  const filteredData = sortedData.filter(
8070
8142
  (row) => columns.every((col) => {
8071
- if (!col.filter || filters[col.key] === void 0 || filters[col.key] === "")
8143
+ const rawFilter = filters[col.key];
8144
+ if (!col.filter || rawFilter === void 0 || rawFilter === "") return true;
8145
+ if (Array.isArray(rawFilter) && rawFilter[0] == null && rawFilter[1] == null) {
8072
8146
  return true;
8147
+ }
8073
8148
  const value = getNestedValue(row, col.key);
8074
- const filterValue = String(filters[col.key]).toLowerCase();
8149
+ if (col.filter === "date" || col.filter === "date-range") {
8150
+ const rowDate = value instanceof Date ? value : new Date(String(value));
8151
+ if (isNaN(rowDate.getTime())) return false;
8152
+ if (col.filter === "date") {
8153
+ return (0, import_date_fns3.isSameDay)(rowDate, rawFilter);
8154
+ }
8155
+ const [start, end] = rawFilter;
8156
+ if (start && rowDate.getTime() < (0, import_date_fns3.startOfDay)(start).getTime()) return false;
8157
+ if (end && rowDate.getTime() > (0, import_date_fns3.endOfDay)(end).getTime()) return false;
8158
+ return true;
8159
+ }
8160
+ if (col.filter === "search") {
8161
+ return String(value) === String(rawFilter);
8162
+ }
8163
+ const filterValue = String(rawFilter).toLowerCase();
8075
8164
  switch (col.type) {
8076
8165
  case "number":
8077
8166
  return String(value).includes(filterValue);
8078
8167
  case "boolean":
8079
- return value === filters[col.key];
8168
+ return value === rawFilter;
8080
8169
  case "catalog": {
8081
8170
  if (!col.catalogOptions) return true;
8082
8171
  const catalogItem = col.catalogOptions.data.find(
@@ -8182,6 +8271,75 @@ function ITTable({
8182
8271
  }
8183
8272
  );
8184
8273
  }
8274
+ if (col.filter === "search" && col.catalogOptions) {
8275
+ if (col.catalogOptions.loading) {
8276
+ return /* @__PURE__ */ (0, import_jsx_runtime60.jsx)(
8277
+ import_fa27.FaSpinner,
8278
+ {
8279
+ className: "animate-spin",
8280
+ "aria-label": "Cargando opciones",
8281
+ title: "Cargando opciones"
8282
+ }
8283
+ );
8284
+ }
8285
+ if (col.catalogOptions.error) {
8286
+ return /* @__PURE__ */ (0, import_jsx_runtime60.jsx)(ITText, { as: "span", className: "text-danger-500 text-xs", children: "Error cargando" });
8287
+ }
8288
+ const searchValue = filters[col.key];
8289
+ return /* @__PURE__ */ (0, import_jsx_runtime60.jsx)(
8290
+ ITSearchSelect,
8291
+ {
8292
+ name: `filter-${col.key}`,
8293
+ options: col.catalogOptions.data.map((item) => ({
8294
+ value: item.id,
8295
+ label: item.name
8296
+ })),
8297
+ value: typeof searchValue === "string" || typeof searchValue === "number" ? searchValue : "",
8298
+ onChange: (value) => handleFilterChange(col.key, value === "" ? void 0 : value),
8299
+ onSearch: col.catalogOptions.onSearch,
8300
+ isLoading: col.catalogOptions.loading,
8301
+ size: "sm",
8302
+ placeholder: "Buscar...",
8303
+ clearable: true,
8304
+ className: "w-full",
8305
+ onBlur: () => {
8306
+ }
8307
+ }
8308
+ );
8309
+ }
8310
+ if (col.filter === "date") {
8311
+ const dateValue = filters[col.key];
8312
+ return /* @__PURE__ */ (0, import_jsx_runtime60.jsx)(
8313
+ ITDatePicker,
8314
+ {
8315
+ name: `filter-${col.key}`,
8316
+ value: dateValue instanceof Date ? dateValue : void 0,
8317
+ onChange: (e) => handleFilterChange(col.key, e.target.value),
8318
+ minDate: col.dateFilterOptions?.minDate,
8319
+ maxDate: col.dateFilterOptions?.maxDate,
8320
+ size: "sm",
8321
+ placeholder: "dd/mm/aaaa",
8322
+ className: "w-full"
8323
+ }
8324
+ );
8325
+ }
8326
+ if (col.filter === "date-range") {
8327
+ const rangeValue = filters[col.key];
8328
+ return /* @__PURE__ */ (0, import_jsx_runtime60.jsx)(
8329
+ ITDatePicker,
8330
+ {
8331
+ name: `filter-${col.key}`,
8332
+ range: true,
8333
+ value: Array.isArray(rangeValue) ? rangeValue : void 0,
8334
+ onChange: (e) => handleFilterChange(col.key, e.target.value),
8335
+ minDate: col.dateFilterOptions?.minDate,
8336
+ maxDate: col.dateFilterOptions?.maxDate,
8337
+ size: "sm",
8338
+ placeholder: "dd/mm/aaaa - dd/mm/aaaa",
8339
+ className: "w-full"
8340
+ }
8341
+ );
8342
+ }
8185
8343
  return /* @__PURE__ */ (0, import_jsx_runtime60.jsx)(
8186
8344
  ITInput,
8187
8345
  {
@@ -8312,7 +8470,7 @@ function ITTable({
8312
8470
  effectiveView === "cards" ? /* @__PURE__ */ (0, import_jsx_runtime60.jsx)("div", { className: "p-4 space-y-3 max-h-[400px] overflow-y-auto", children: currentData.length > 0 ? currentData.map((row, i) => /* @__PURE__ */ (0, import_jsx_runtime60.jsx)(
8313
8471
  "div",
8314
8472
  {
8315
- className: (0, import_clsx43.default)(onRowClick && tableCardClickable),
8473
+ className: (0, import_clsx43.default)(tableCardHover, onRowClick && tableCardClickable),
8316
8474
  role: onRowClick ? "button" : void 0,
8317
8475
  tabIndex: onRowClick ? 0 : void 0,
8318
8476
  onClick: onRowClick ? handleRowClick(row) : void 0,
@@ -10246,8 +10404,10 @@ var DEFAULT_PALETTE = {
10246
10404
  // Slate-700
10247
10405
  rowBg: "#ffffff",
10248
10406
  // White
10249
- rowText: "#1e293b"
10407
+ rowText: "#1e293b",
10250
10408
  // Slate-800
10409
+ rowHover: "#f1f5f9"
10410
+ // Slate-100
10251
10411
  }
10252
10412
  };
10253
10413
  var PRESETS = [
@@ -10272,7 +10432,8 @@ var PRESETS = [
10272
10432
  headerBg: "#f1f5f9",
10273
10433
  headerText: "#334155",
10274
10434
  rowBg: "#ffffff",
10275
- rowText: "#0f172a"
10435
+ rowText: "#0f172a",
10436
+ rowHover: "#1e293b"
10276
10437
  }
10277
10438
  }
10278
10439
  },
@@ -10297,7 +10458,8 @@ var PRESETS = [
10297
10458
  headerBg: "#fff1f2",
10298
10459
  headerText: "#881337",
10299
10460
  rowBg: "#ffffff",
10300
- rowText: "#1c1212"
10461
+ rowText: "#1c1212",
10462
+ rowHover: "#fff1f2"
10301
10463
  }
10302
10464
  }
10303
10465
  },
@@ -10322,7 +10484,8 @@ var PRESETS = [
10322
10484
  headerBg: "#f0fdfa",
10323
10485
  headerText: "#115e59",
10324
10486
  rowBg: "#ffffff",
10325
- rowText: "#042f2e"
10487
+ rowText: "#042f2e",
10488
+ rowHover: "#f0fdfa"
10326
10489
  }
10327
10490
  }
10328
10491
  },
@@ -10347,7 +10510,8 @@ var PRESETS = [
10347
10510
  headerBg: "#fefce8",
10348
10511
  headerText: "#713f12",
10349
10512
  rowBg: "#ffffff",
10350
- rowText: "#292524"
10513
+ rowText: "#292524",
10514
+ rowHover: "#fefce8"
10351
10515
  }
10352
10516
  }
10353
10517
  },
@@ -10372,7 +10536,8 @@ var PRESETS = [
10372
10536
  headerBg: "#f0fdf4",
10373
10537
  headerText: "#166534",
10374
10538
  rowBg: "#ffffff",
10375
- rowText: "#052e16"
10539
+ rowText: "#052e16",
10540
+ rowHover: "#f0fdf4"
10376
10541
  }
10377
10542
  }
10378
10543
  }
@@ -10652,6 +10817,7 @@ function ITThemeProvider({
10652
10817
  let tableRowText = palette2.table.rowText;
10653
10818
  let tableHeaderBg = palette2.table.headerBg;
10654
10819
  let tableHeaderText = palette2.table.headerText;
10820
+ let tableRowHover = palette2.table.rowHover;
10655
10821
  let navbarBg = palette2.layout.navbarBg;
10656
10822
  let navbarText = palette2.layout.navbarText;
10657
10823
  let sidebarBg = palette2.layout.sidebarBg;
@@ -10669,6 +10835,9 @@ function ITThemeProvider({
10669
10835
  if (!isLightColor2(tableHeaderText)) {
10670
10836
  tableHeaderText = `color-mix(in srgb, ${palette2.table.headerText} 20%, #f9fafb)`;
10671
10837
  }
10838
+ if (isLightColor2(tableRowHover)) {
10839
+ tableRowHover = `color-mix(in srgb, ${palette2.table.rowHover} 12%, #1f2937)`;
10840
+ }
10672
10841
  if (isLightColor2(navbarBg)) {
10673
10842
  navbarBg = `color-mix(in srgb, ${palette2.layout.navbarBg} 8%, #111827)`;
10674
10843
  }
@@ -10694,7 +10863,10 @@ function ITThemeProvider({
10694
10863
  }
10695
10864
  if (isLightColor2(tableHeaderText)) {
10696
10865
  tableHeaderText = `color-mix(in srgb, ${palette2.table.headerText} 30%, #334155)`;
10697
- } else if (!isLightColor2(tableHeaderText) && isVeryDarkColor(palette2.table.headerText)) {
10866
+ } else if (!isLightColor2(tableHeaderText) && isVeryDarkColor(tableHeaderText)) {
10867
+ }
10868
+ if (!isLightColor2(tableRowHover)) {
10869
+ tableRowHover = isVeryDarkColor(palette2.table.rowHover) ? "#f1f5f9" : `color-mix(in srgb, ${palette2.table.rowHover} 12%, #f8fafc)`;
10698
10870
  }
10699
10871
  if (!isLightColor2(navbarBg)) {
10700
10872
  navbarBg = isVeryDarkColor(palette2.layout.navbarBg) ? "#ffffff" : `color-mix(in srgb, ${palette2.layout.navbarBg} 8%, #ffffff)`;
@@ -10904,6 +11076,7 @@ function ITThemeProvider({
10904
11076
  --color-table-headerText: ${tableHeaderText} !important;
10905
11077
  --color-table-rowBg: ${tableRowBg} !important;
10906
11078
  --color-table-rowText: ${tableRowText} !important;
11079
+ --color-table-rowHover: ${tableRowHover} !important;
10907
11080
 
10908
11081
  /* Native library variables integration */
10909
11082
  --it-sidebar-bg: var(--color-sidebarBg);
@@ -11247,7 +11420,7 @@ function ITThemeProvider({
11247
11420
  color: var(--color-table-rowText) !important;
11248
11421
  }
11249
11422
  tbody tr:hover {
11250
- background-color: color-mix(in srgb, var(--color-primary) 8%, var(--color-table-rowBg)) !important;
11423
+ background-color: var(--color-table-rowHover) !important;
11251
11424
  }
11252
11425
 
11253
11426
  /* Animation for Saved Indicator */
@@ -12009,7 +12182,8 @@ function ITThemeProvider({
12009
12182
  "table.headerBg",
12010
12183
  "table.headerText",
12011
12184
  "table.rowBg",
12012
- "table.rowText"
12185
+ "table.rowText",
12186
+ "table.rowHover"
12013
12187
  ].map((key) => /* @__PURE__ */ (0, import_jsx_runtime72.jsx)(ColorRow, { colorKey: key }, key)) })
12014
12188
  }
12015
12189
  ]