@axzydev/axzy_ui_system 1.3.3 → 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.js CHANGED
@@ -233,6 +233,11 @@ function useFloatingPanel(anchorRef, isOpen, {
233
233
 
234
234
  // src/hooks/useTableState.ts
235
235
  import { useCallback as useCallback4, useMemo as useMemo2, useState as useState4 } from "react";
236
+ var isEmptyFilterValue = (value) => {
237
+ if (value === void 0 || value === null || value === "") return true;
238
+ if (Array.isArray(value)) return value[0] == null && value[1] == null;
239
+ return false;
240
+ };
236
241
  function useTableState({
237
242
  defaultItemsPerPage = 10,
238
243
  initialSort = null
@@ -257,7 +262,7 @@ function useTableState({
257
262
  const handleFilterChange = useCallback4(
258
263
  (key, value) => {
259
264
  setFilters((prev) => {
260
- if (value === void 0 || value === null || value === "") {
265
+ if (isEmptyFilterValue(value)) {
261
266
  const next = { ...prev };
262
267
  delete next[key];
263
268
  return next;
@@ -3595,9 +3600,9 @@ function useVirtualRows({
3595
3600
  }
3596
3601
 
3597
3602
  // src/components/organisms/data-table/dataTable.tsx
3598
- import clsx21 from "clsx";
3599
- import { useState as useState17, useEffect as useEffect7, useCallback as useCallback7, useRef as useRef11 } from "react";
3600
- import { FaCheck as FaCheck2, FaSpinner, FaTimes as FaTimes4, FaTable, FaThLarge } from "react-icons/fa";
3603
+ import clsx23 from "clsx";
3604
+ import { useState as useState19, useEffect as useEffect9, useCallback as useCallback7, useRef as useRef13 } from "react";
3605
+ import { FaCheck as FaCheck2, FaSpinner, FaTimes as FaTimes5, FaTable, FaThLarge } from "react-icons/fa";
3601
3606
  import { MdOutlineSwapVert } from "react-icons/md";
3602
3607
 
3603
3608
  // src/components/molecules/pagination/pagination.tsx
@@ -3890,445 +3895,240 @@ function ITPagination({
3890
3895
  return /* @__PURE__ */ jsx20("nav", { "aria-label": "Pagination", className: clsx20("inline-flex", className), children: renderPaginationControls() });
3891
3896
  }
3892
3897
 
3893
- // src/utils/table.utils.ts
3894
- var formatCurrencyMX = (value) => {
3895
- return value.toLocaleString("es-MX", {
3896
- style: "currency",
3897
- currency: "MXN"
3898
- });
3899
- };
3900
- var getNestedValue = (obj, path) => {
3901
- return path.split(".").reduce((acc, part) => acc && acc[part], obj);
3902
- };
3903
- var ROW_CLICK_IGNORE_SELECTOR = 'button, a, input, select, textarea, [role="button"], [role="link"], [data-row-click-ignore]';
3904
- function isInteractiveTarget(target, boundary = null) {
3905
- if (!(target instanceof Element)) return false;
3906
- const interactive = target.closest(ROW_CLICK_IGNORE_SELECTOR);
3907
- if (!interactive) return false;
3908
- if (boundary instanceof Node && interactive === boundary) return false;
3909
- return true;
3910
- }
3911
-
3912
- // src/components/organisms/data-table/dataTable.tsx
3913
- import { Fragment as Fragment4, jsx as jsx21, jsxs as jsxs18 } from "react/jsx-runtime";
3914
- var getNestedValue2 = (obj, path) => {
3915
- return path.split(".").reduce((acc, part) => acc && acc[part], obj);
3916
- };
3917
- var EMPTY_OBJECT = {};
3918
- function ITDataTable({
3919
- columns,
3920
- fetchData,
3921
- debounceMs = 500,
3922
- externalFilters = EMPTY_OBJECT,
3923
- loadingIndicator,
3924
- fetchOnMount = true,
3925
- reloadTrigger,
3926
- containerClassName,
3898
+ // src/components/molecules/search-select/search-select.tsx
3899
+ import { useState as useState17, useEffect as useEffect7, useRef as useRef11, useMemo as useMemo7 } from "react";
3900
+ import { createPortal as createPortal3 } from "react-dom";
3901
+ import clsx21 from "clsx";
3902
+ import { FaSearch as FaSearch2, FaTimes as FaTimes4 } from "react-icons/fa";
3903
+ import { jsx as jsx21, jsxs as jsxs18 } from "react/jsx-runtime";
3904
+ function ITSearchSelect({
3905
+ name,
3906
+ options = [],
3907
+ label,
3908
+ placeholder = "Selecciona una opci\xF3n",
3909
+ valueField = "value",
3910
+ labelField = "label",
3911
+ value,
3912
+ onChange,
3913
+ onBlur,
3914
+ disabled = false,
3927
3915
  className,
3928
- variant = "default",
3916
+ touched,
3917
+ required,
3918
+ error,
3919
+ readOnly = false,
3920
+ onSearch,
3921
+ isLoading = false,
3922
+ noResultsMessage = "No se encontraron resultados",
3929
3923
  size = "md",
3930
- itemsPerPageOptions = [5, 10, 20],
3931
- defaultItemsPerPage = 10,
3932
- title,
3933
- renderCard,
3934
- defaultView,
3935
- showVerticalBorder = true,
3936
- verticalBorderClassname,
3937
- onRowClick,
3938
- layout = "auto",
3939
- density = "normal",
3940
- autoCardBreakpoint = 0,
3941
- virtualized = false,
3942
- virtualizedMaxHeight = 400,
3943
- rowHeight,
3944
- overscan = 5,
3945
- stickyHeader = false
3924
+ renderOption,
3925
+ clearable = true,
3926
+ onClear
3946
3927
  }) {
3947
- const [viewMode, setViewMode] = useState17(defaultView || "table");
3948
- const { ref: rootRef, width: containerWidth } = useElementSize();
3949
- const [data, setData] = useState17([]);
3950
- const [totalItems, setTotalItems] = useState17(0);
3951
- const [isLoading, setIsLoading] = useState17(fetchOnMount);
3952
- const isFixed = layout === "fixed";
3953
- const forcedCards = autoCardBreakpoint > 0 && containerWidth > 0 && containerWidth < autoCardBreakpoint;
3954
- const effectiveView = forcedCards ? "cards" : viewMode;
3955
- const hasColumnWidths = columns.some((col) => col.width != null);
3956
- 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";
3957
- const isTableVirtual = virtualized && effectiveView === "table";
3958
- const isStickyHeader = stickyHeader && isTableVirtual;
3959
- const resolvedRowHeight = rowHeight ?? getRowHeight(size, density);
3960
- const columnCount = columns.length;
3961
- const scrollOuterClass = isTableVirtual ? "relative min-h-[200px]" : "overflow-x-auto relative min-h-[200px]";
3962
- const {
3963
- currentPage,
3964
- itemsPerPage,
3965
- filters,
3966
- sortConfig,
3967
- goToPage,
3968
- handleFilterChange,
3969
- handleSort,
3970
- handleItemsPerPageChange
3971
- } = useTableState({ defaultItemsPerPage });
3972
- const {
3973
- scrollRef,
3974
- startIndex,
3975
- endIndex,
3976
- topSpacerHeight,
3977
- bottomSpacerHeight
3978
- } = useVirtualRows({
3979
- count: data.length,
3980
- rowHeight: resolvedRowHeight,
3981
- overscan,
3982
- enabled: isTableVirtual,
3983
- resetKey: `${currentPage}-${itemsPerPage}`
3928
+ const [isOpen, setIsOpen] = useState17(false);
3929
+ const [searchTerm, setSearchTerm] = useState17("");
3930
+ const [isFocused, setIsFocused] = useState17(false);
3931
+ const [localTouched, setLocalTouched] = useState17(false);
3932
+ const containerRef = useRef11(null);
3933
+ const inputWrapperRef = useRef11(null);
3934
+ const timeoutRef = useRef11(null);
3935
+ const { panelRef, style: panelStyle } = useFloatingPanel(inputWrapperRef, isOpen, {
3936
+ estimatedHeight: 260,
3937
+ matchWidth: true
3984
3938
  });
3985
- const windowData = isTableVirtual ? data.slice(startIndex, endIndex + 1) : data;
3986
- const debounceTimerRef = useRef11(null);
3987
- const hasFetchedRef = useRef11(false);
3988
- const fetchDataRef = useRef11(fetchData);
3989
- fetchDataRef.current = fetchData;
3990
- const externalFiltersRef = useRef11(externalFilters);
3991
- externalFiltersRef.current = externalFilters;
3992
- const externalKey = JSON.stringify(externalFilters);
3993
- const computedTotalPages = Math.ceil(totalItems / itemsPerPage) || 1;
3994
- const performFetch = useCallback7(async () => {
3995
- setIsLoading(true);
3996
- try {
3997
- const response = await fetchDataRef.current({
3998
- page: currentPage,
3999
- limit: itemsPerPage,
4000
- filters: { ...filters, ...externalFiltersRef.current },
4001
- sort: sortConfig || void 0
4002
- });
4003
- setData(response.data || []);
4004
- setTotalItems(response.total || 0);
4005
- hasFetchedRef.current = true;
4006
- } catch (error) {
4007
- console.error("ITDataTable: Error fetching data", error);
4008
- setData([]);
4009
- setTotalItems(0);
4010
- hasFetchedRef.current = true;
4011
- } finally {
4012
- setIsLoading(false);
4013
- }
4014
- }, [currentPage, itemsPerPage, filters, sortConfig]);
4015
- const performFetchRef = useRef11(performFetch);
4016
- performFetchRef.current = performFetch;
3939
+ const selectedOption = useMemo7(() => {
3940
+ return options.find((opt) => opt[valueField] === value);
3941
+ }, [options, value, valueField]);
4017
3942
  useEffect7(() => {
4018
- if (!fetchOnMount && !hasFetchedRef.current) return;
4019
- if (debounceTimerRef.current) clearTimeout(debounceTimerRef.current);
4020
- debounceTimerRef.current = setTimeout(() => {
4021
- performFetchRef.current();
4022
- }, debounceMs);
4023
- return () => {
4024
- if (debounceTimerRef.current) clearTimeout(debounceTimerRef.current);
4025
- };
4026
- }, [currentPage, itemsPerPage, sortConfig, filters, externalKey, reloadTrigger, fetchOnMount, debounceMs]);
4027
- const renderFilterInput = (col) => {
4028
- if (!col.filter) return null;
4029
- if (col.type === "boolean") {
4030
- const currentValue = filters[col.key];
4031
- const nextValue = currentValue === void 0 ? true : currentValue === true ? false : void 0;
4032
- const getToggleLabel = () => {
4033
- if (currentValue === void 0) return "Mostrar todos";
4034
- if (currentValue === true) return "Filtrar solo verdaderos";
4035
- return "Filtrar solo falsos";
4036
- };
4037
- return /* @__PURE__ */ jsx21(
4038
- "button",
4039
- {
4040
- 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",
4041
- onClick: () => handleFilterChange(col.key, nextValue),
4042
- "aria-label": `${getToggleLabel()} para ${col.label}`,
4043
- title: `${getToggleLabel()} para ${col.label}`,
4044
- disabled: isLoading,
4045
- children: /* @__PURE__ */ jsx21("div", { className: "relative w-10 h-5 bg-secondary-300 rounded-full", children: /* @__PURE__ */ jsx21(
4046
- "div",
4047
- {
4048
- className: clsx21(
4049
- "absolute top-0.5 w-4 h-4 rounded-full transition-all duration-300 shadow-sm",
4050
- {
4051
- "left-0.5 bg-secondary-400": currentValue === void 0,
4052
- "left-5 bg-slate-500": currentValue === true,
4053
- "left-0.5 bg-secondary-500": currentValue === false
4054
- }
4055
- )
4056
- }
4057
- ) })
4058
- }
4059
- );
3943
+ if (!isFocused) {
3944
+ setSearchTerm(selectedOption ? String(selectedOption[labelField]) : "");
4060
3945
  }
4061
- if (col.filter === "catalog" && col.catalogOptions) {
4062
- if (col.catalogOptions.loading) {
4063
- return /* @__PURE__ */ jsx21(FaSpinner, { className: "animate-spin", "aria-label": "Cargando opciones", title: "Cargando opciones" });
4064
- }
4065
- if (col.catalogOptions.error) {
4066
- return /* @__PURE__ */ jsx21(ITText, { as: "span", className: "text-danger-500 text-xs", children: "Error cargando" });
3946
+ }, [selectedOption, isFocused, labelField]);
3947
+ useEffect7(() => {
3948
+ function handleClickOutside(event) {
3949
+ const target = event.target;
3950
+ const inContainer = containerRef.current?.contains(target);
3951
+ const inPanel = panelRef.current?.contains(target);
3952
+ if (!inContainer && !inPanel) {
3953
+ setIsOpen(false);
4067
3954
  }
4068
- return /* @__PURE__ */ jsx21(
4069
- ITSelect,
4070
- {
4071
- name: `filter-${col.key}`,
4072
- options: [
4073
- { value: "", label: "Todos" },
4074
- ...col.catalogOptions.data.map((item) => ({
4075
- value: String(item.id),
4076
- label: item.name
4077
- }))
4078
- ],
4079
- value: String(filters[col.key] || ""),
4080
- onChange: (e) => {
4081
- const value = e.target.value === "" ? void 0 : e.target.value;
4082
- handleFilterChange(col.key, value);
4083
- },
4084
- onBlur: () => {
4085
- },
4086
- className: "w-full text-xs",
4087
- disabled: isLoading
4088
- }
4089
- );
4090
3955
  }
4091
- return /* @__PURE__ */ jsx21(
4092
- ITInput,
4093
- {
4094
- name: `filter-${col.key}`,
4095
- className: "w-full text-xs",
4096
- placeholder: "Buscar...",
4097
- value: String(filters[col.key] || ""),
4098
- onChange: (e) => handleFilterChange(col.key, e.target.value),
4099
- onBlur: () => {
4100
- },
4101
- disabled: isLoading
4102
- }
3956
+ document.addEventListener("mousedown", handleClickOutside);
3957
+ return () => document.removeEventListener("mousedown", handleClickOutside);
3958
+ }, []);
3959
+ const selectedLabel = selectedOption ? String(selectedOption[labelField]) : "";
3960
+ const filteredOptions = useMemo7(() => {
3961
+ if (onSearch) return options;
3962
+ if (!searchTerm || !isFocused || searchTerm === selectedLabel) return options;
3963
+ return options.filter(
3964
+ (opt) => String(opt[labelField]).toLowerCase().includes(searchTerm.toLowerCase())
4103
3965
  );
3966
+ }, [options, searchTerm, selectedLabel, onSearch, labelField, isFocused]);
3967
+ const handleInputChange = (e) => {
3968
+ const query = e.target.value;
3969
+ setSearchTerm(query);
3970
+ setIsOpen(true);
3971
+ if (onSearch) {
3972
+ if (timeoutRef.current) clearTimeout(timeoutRef.current);
3973
+ timeoutRef.current = setTimeout(() => {
3974
+ onSearch(query);
3975
+ }, 500);
3976
+ }
4104
3977
  };
4105
- const renderCellContent = (col, row) => {
4106
- const value = getNestedValue2(row, col.key);
4107
- if (col.render) return col.render(row);
4108
- switch (col.type) {
4109
- case "number":
4110
- return typeof value === "number" && col.currencyMX ? formatCurrencyMX(value) : value;
4111
- case "boolean":
4112
- return value ? /* @__PURE__ */ jsx21(FaCheck2, { className: "text-success-500", "aria-label": "Verdadero", title: "Verdadero" }) : /* @__PURE__ */ jsx21(FaTimes4, { className: "text-danger-500", "aria-label": "Falso", title: "Falso" });
4113
- case "actions":
4114
- return col.actions ? col.actions(row) : null;
4115
- case "catalog":
4116
- if (col.catalogOptions) {
4117
- const catalogItem = col.catalogOptions.data.find((item) => item.id === value);
4118
- return catalogItem?.name || value;
4119
- }
4120
- return value;
4121
- default:
4122
- return value;
3978
+ const handleSelect = (option) => {
3979
+ if (onChange) {
3980
+ onChange(option[valueField], option);
4123
3981
  }
3982
+ setSearchTerm(String(option[labelField]));
3983
+ setIsOpen(false);
4124
3984
  };
4125
- const renderDefaultCard = (row) => {
4126
- const dataCols = columns.filter((c) => c.type !== "actions");
4127
- const actionCol = columns.find((c) => c.type === "actions");
4128
- return /* @__PURE__ */ jsxs18("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: [
4129
- dataCols.map((col) => /* @__PURE__ */ jsxs18("div", { className: "flex items-center justify-between gap-2", children: [
4130
- /* @__PURE__ */ jsx21("span", { className: "text-[10px] font-bold uppercase tracking-wider text-slate-400 whitespace-nowrap flex-shrink-0 min-w-[70px]", children: col.label }),
4131
- /* @__PURE__ */ jsx21("span", { className: "text-sm font-medium text-slate-800 dark:text-white text-right truncate", children: renderCellContent(col, row) })
4132
- ] }, col.key)),
4133
- actionCol?.actions && /* @__PURE__ */ jsx21("div", { className: "flex items-center justify-end gap-2 pt-2 border-t border-slate-100 dark:border-slate-700", children: actionCol.actions(row) })
4134
- ] });
3985
+ const handleClear = () => {
3986
+ setSearchTerm("");
3987
+ setIsOpen(true);
3988
+ if (onSearch) onSearch("");
3989
+ if (value !== void 0 && value !== null && value !== "") {
3990
+ onChange?.("", void 0);
3991
+ }
3992
+ onClear?.();
4135
3993
  };
4136
- 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"}`;
4137
- const handleRowClick = (row) => (event) => {
4138
- if (!onRowClick || isLoading || isInteractiveTarget(event.target, event.currentTarget)) return;
4139
- onRowClick(row, event);
3994
+ const handleFocus = () => {
3995
+ if (disabled || readOnly) return;
3996
+ setIsFocused(true);
3997
+ setIsOpen(true);
4140
3998
  };
4141
- const handleRowKeyDown = (row) => (event) => {
4142
- if (!onRowClick || isLoading) return;
4143
- if (event.target !== event.currentTarget) return;
4144
- if (event.key !== "Enter" && event.key !== " ") return;
4145
- event.preventDefault();
4146
- onRowClick(row, event);
3999
+ const handleInputBlur = (e) => {
4000
+ setTimeout(() => {
4001
+ setIsFocused(false);
4002
+ setLocalTouched(true);
4003
+ onBlur?.(e);
4004
+ }, 200);
4147
4005
  };
4148
- const tableEl = /* @__PURE__ */ jsxs18(
4149
- "table",
4150
- {
4151
- className: clsx21(
4152
- tableLayoutClass,
4153
- showVerticalBorder && "[&_th]:border-r [&_th:last-child]:border-r-0 [&_td]:border-r [&_td:last-child]:border-r-0",
4154
- showVerticalBorder && (verticalBorderClassname || "[&_th]:border-slate-100 dark:[&_th]:border-slate-700/30 [&_td]:border-slate-100 dark:[&_td]:border-slate-700/30"),
4155
- isLoading ? "opacity-50" : "opacity-100",
4156
- variantStyles[variant],
4157
- sizeStyles[size],
4158
- className
4159
- ),
4160
- style: isFixed ? { tableLayout: "fixed" } : void 0,
4161
- "aria-rowcount": isTableVirtual ? data.length + 1 : void 0,
4162
- children: [
4163
- hasColumnWidths && /* @__PURE__ */ jsx21("colgroup", { children: columns.map((col) => /* @__PURE__ */ jsx21(
4164
- "col",
4165
- {
4166
- style: col.width != null ? { width: typeof col.width === "number" ? `${col.width}px` : col.width } : void 0
4167
- },
4168
- col.key
4169
- )) }),
4170
- /* @__PURE__ */ jsx21("thead", { children: /* @__PURE__ */ jsx21(
4171
- "tr",
4006
+ const inputTheme = theme.input || {};
4007
+ const isTouched = touched !== void 0 ? touched : localTouched;
4008
+ const isEmpty = value === void 0 || value === null || String(value).trim() === "";
4009
+ const effectiveError = error !== void 0 && error !== false ? error === true ? "Este campo es requerido" : error : required && isEmpty ? "Este campo es requerido" : void 0;
4010
+ const hasError = isTouched && !!effectiveError;
4011
+ const errorMessage = typeof effectiveError === "string" ? effectiveError : "Este campo es requerido";
4012
+ const showClearButton = clearable && !disabled && !readOnly && (searchTerm.length > 0 || !isEmpty);
4013
+ const getInputStyle = () => {
4014
+ const sizeConfig = inputSizeTokens[size] ?? inputSizeTokens.md;
4015
+ const style = {
4016
+ backgroundColor: inputTheme.backgroundColor || "#ffffff",
4017
+ borderColor: inputTheme.borderColor || "var(--color-secondary-300)",
4018
+ borderRadius: inputTheme.borderRadius || "0.5rem",
4019
+ padding: sizeConfig.padding,
4020
+ fontSize: sizeConfig.fontSize,
4021
+ borderWidth: "1px",
4022
+ borderStyle: "solid",
4023
+ transition: "all 0.2s",
4024
+ color: "var(--it-input-text-color, var(--color-secondary-900))",
4025
+ width: "100%"
4026
+ };
4027
+ if (disabled) {
4028
+ style.backgroundColor = inputTheme.disabled?.backgroundColor || "var(--color-secondary-100)";
4029
+ style.borderColor = inputTheme.disabled?.borderColor || "var(--color-secondary-200)";
4030
+ style.opacity = 0.7;
4031
+ style.cursor = "not-allowed";
4032
+ }
4033
+ if (hasError) {
4034
+ style.borderColor = inputTheme.error?.borderColor || "red";
4035
+ if (isFocused) {
4036
+ style.boxShadow = inputTheme.error?.ring;
4037
+ }
4038
+ } else if (isFocused && !readOnly) {
4039
+ style.boxShadow = inputTheme.focus?.ring;
4040
+ style.borderColor = inputTheme.focus?.borderColor;
4041
+ }
4042
+ return style;
4043
+ };
4044
+ return /* @__PURE__ */ jsxs18("div", { className: clsx21("w-full flex flex-col gap-1.5", className, isOpen && "relative z-30"), ref: containerRef, children: [
4045
+ label && /* @__PURE__ */ jsxs18(
4046
+ ITText,
4047
+ {
4048
+ as: "label",
4049
+ className: clsx21("text-sm font-medium text-secondary-700 dark:text-slate-300", {
4050
+ "text-danger-500": hasError
4051
+ }),
4052
+ children: [
4053
+ /* @__PURE__ */ jsx21(ITText, { as: "span", children: label }),
4054
+ required && /* @__PURE__ */ jsx21(ITText, { as: "span", className: "text-danger-500 ml-1", children: "*" })
4055
+ ]
4056
+ }
4057
+ ),
4058
+ /* @__PURE__ */ jsxs18("div", { className: "relative", children: [
4059
+ /* @__PURE__ */ jsxs18("div", { ref: inputWrapperRef, className: "relative flex items-center", children: [
4060
+ /* @__PURE__ */ jsx21(
4061
+ "input",
4172
4062
  {
4173
- className: clsx21(tableHeaderRow, "dark:text-slate-200"),
4174
- "aria-rowindex": isTableVirtual ? 1 : void 0,
4175
- children: columns.map((col) => /* @__PURE__ */ jsx21(
4176
- "th",
4177
- {
4178
- scope: "col",
4179
- className: clsx21(
4180
- tableHeaderCell(col.className, density),
4181
- col.align && tableAlignClasses[col.align],
4182
- isStickyHeader && "sticky top-0 z-10 bg-secondary-50"
4183
- ),
4184
- style: col.minWidth != null || isStickyHeader ? {
4185
- ...col.minWidth != null ? { minWidth: `${col.minWidth}px` } : {},
4186
- ...isStickyHeader ? { backgroundColor: "var(--color-table-headerBg, #f8fafc)" } : {}
4187
- } : void 0,
4188
- children: /* @__PURE__ */ jsxs18("div", { className: isFixed ? "flex flex-col gap-3" : "flex flex-col gap-3 min-w-[150px]", children: [
4189
- /* @__PURE__ */ jsxs18("div", { className: "flex items-center justify-between gap-2", children: [
4190
- /* @__PURE__ */ jsx21(ITText, { as: "span", className: "text-slate-900 dark:text-white font-bold", children: col.label }),
4191
- col.sortable && col.type !== "actions" && /* @__PURE__ */ jsx21(
4192
- "button",
4193
- {
4194
- onClick: () => handleSort(col.key),
4195
- disabled: isLoading,
4196
- 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`,
4197
- title: `Ordenar por ${col.label}`,
4198
- children: /* @__PURE__ */ jsx21(MdOutlineSwapVert, { className: "w-4 h-4", "aria-hidden": "true" })
4199
- }
4200
- )
4201
- ] }),
4202
- /* @__PURE__ */ jsx21("div", { className: "w-full", children: col.filter ? renderFilterInput(col) : null })
4203
- ] })
4204
- },
4205
- col.key
4206
- ))
4063
+ type: "text",
4064
+ name,
4065
+ value: searchTerm,
4066
+ onChange: handleInputChange,
4067
+ onFocus: handleFocus,
4068
+ onBlur: handleInputBlur,
4069
+ disabled,
4070
+ readOnly,
4071
+ placeholder,
4072
+ className: "outline-none pr-10",
4073
+ style: getInputStyle(),
4074
+ autoComplete: "off"
4207
4075
  }
4208
- ) }),
4209
- /* @__PURE__ */ jsx21("tbody", { className: clsx21(tableBody, "dark:divide-slate-700/30"), children: data.length > 0 ? /* @__PURE__ */ jsxs18(Fragment4, { children: [
4210
- isTableVirtual && topSpacerHeight > 0 && /* @__PURE__ */ jsx21("tr", { "aria-hidden": "true", style: { height: topSpacerHeight }, children: /* @__PURE__ */ jsx21("td", { colSpan: columnCount, style: { padding: 0, border: 0 } }) }),
4211
- windowData.map((row, windowIndex) => {
4212
- const absoluteIndex = isTableVirtual ? startIndex + windowIndex : windowIndex;
4213
- return /* @__PURE__ */ jsx21(
4214
- "tr",
4215
- {
4216
- "aria-rowindex": isTableVirtual ? absoluteIndex + 2 : void 0,
4217
- className: clsx21(
4218
- tableRow,
4219
- variant === "striped" && absoluteIndex % 2 === 0 && "bg-secondary-50/40 dark:bg-slate-800/20",
4220
- onRowClick && !isLoading && tableRowClickable
4221
- ),
4222
- tabIndex: onRowClick && !isLoading ? 0 : void 0,
4223
- onClick: onRowClick && !isLoading ? handleRowClick(row) : void 0,
4224
- onKeyDown: onRowClick && !isLoading ? handleRowKeyDown(row) : void 0,
4225
- children: columns.map((col) => {
4226
- const rawValue = getNestedValue2(row, col.key);
4227
- const truncateTitle = col.truncate && (typeof rawValue === "string" || typeof rawValue === "number") ? String(rawValue) : void 0;
4228
- return /* @__PURE__ */ jsx21(
4229
- "td",
4230
- {
4231
- className: clsx21(
4232
- tableCell(col.className, density),
4233
- col.align && tableAlignClasses[col.align]
4234
- ),
4235
- style: col.minWidth != null ? { minWidth: `${col.minWidth}px` } : void 0,
4236
- title: truncateTitle,
4237
- children: col.type === "actions" ? /* @__PURE__ */ jsx21("div", { className: tableActionsCell, children: renderCellContent(col, row) }) : /* @__PURE__ */ jsx21("div", { className: clsx21(tableCellText, col.truncate && "truncate"), children: renderCellContent(col, row) })
4238
- },
4239
- `${absoluteIndex}-${col.key}`
4240
- );
4241
- })
4076
+ ),
4077
+ /* @__PURE__ */ jsxs18("div", { className: "absolute right-3 flex items-center gap-2 text-secondary-400", children: [
4078
+ isLoading && /* @__PURE__ */ jsx21("div", { className: "pointer-events-none animate-spin h-4 w-4 border-2 border-primary-500 border-t-transparent rounded-full" }),
4079
+ !isLoading && showClearButton && /* @__PURE__ */ jsx21(
4080
+ "button",
4081
+ {
4082
+ type: "button",
4083
+ "aria-label": "Limpiar",
4084
+ title: "Limpiar",
4085
+ onMouseDown: (e) => {
4086
+ e.preventDefault();
4087
+ handleClear();
4242
4088
  },
4243
- absoluteIndex
4244
- );
4245
- }),
4246
- isTableVirtual && bottomSpacerHeight > 0 && /* @__PURE__ */ jsx21("tr", { "aria-hidden": "true", style: { height: bottomSpacerHeight }, children: /* @__PURE__ */ jsx21("td", { colSpan: columnCount, style: { padding: 0, border: 0 } }) })
4247
- ] }) : /* @__PURE__ */ jsx21("tr", { children: /* @__PURE__ */ jsx21("td", { colSpan: columns.length, className: "px-6 py-12 text-center", children: !isLoading && /* @__PURE__ */ jsxs18("div", { className: tableEmptyContent, children: [
4248
- /* @__PURE__ */ jsx21(ITText, { as: "span", className: "text-lg", children: "No se encontraron resultados" }),
4249
- /* @__PURE__ */ jsx21(ITText, { as: "span", className: "text-sm mt-1", children: "Intenta ajustar los filtros" })
4250
- ] }) }) }) })
4251
- ]
4252
- }
4253
- );
4254
- return /* @__PURE__ */ jsxs18("div", { ref: rootRef, className: clsx21("space-y-4 w-full relative", containerClassName), children: [
4255
- /* @__PURE__ */ jsxs18("div", { className: tableContainer, style: { backgroundColor: "var(--color-table-rowBg, #ffffff)" }, children: [
4256
- title && /* @__PURE__ */ jsxs18("div", { className: "px-6 py-5 flex items-center justify-between", style: { backgroundColor: "var(--color-table-rowBg, #ffffff)" }, children: [
4257
- /* @__PURE__ */ jsx21(ITText, { as: "h2", className: "text-xl font-bold text-secondary-900 leading-tight", children: title }),
4258
- /* @__PURE__ */ jsxs18("div", { className: "flex items-center gap-3", children: [
4259
- isLoading && /* @__PURE__ */ jsx21("div", { className: "text-secondary-400", children: loadingIndicator || /* @__PURE__ */ jsx21(FaSpinner, { className: "animate-spin text-primary-500 text-xl" }) }),
4260
- /* @__PURE__ */ jsxs18("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: [
4261
- /* @__PURE__ */ jsxs18("button", { onClick: () => setViewMode("table"), disabled: forcedCards, className: segCtrlClass("table"), children: [
4262
- /* @__PURE__ */ jsx21(FaTable, { size: 11 }),
4263
- "Table"
4264
- ] }),
4265
- /* @__PURE__ */ jsxs18("button", { onClick: () => setViewMode("cards"), className: segCtrlClass("cards"), children: [
4266
- /* @__PURE__ */ jsx21(FaThLarge, { size: 11 }),
4267
- "Cards"
4268
- ] })
4269
- ] })
4089
+ 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",
4090
+ children: /* @__PURE__ */ jsx21(FaTimes4, { size: 14 })
4091
+ }
4092
+ ),
4093
+ !isLoading && !showClearButton && /* @__PURE__ */ jsx21(FaSearch2, { size: 14, className: clsx21("pointer-events-none", { "text-primary-500": isFocused }) })
4270
4094
  ] })
4271
4095
  ] }),
4272
- !title && /* @__PURE__ */ jsx21("div", { className: "flex justify-end px-4 pt-3", children: /* @__PURE__ */ jsxs18("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: [
4273
- /* @__PURE__ */ jsxs18("button", { onClick: () => setViewMode("table"), disabled: forcedCards, className: segCtrlClass("table"), children: [
4274
- /* @__PURE__ */ jsx21(FaTable, { size: 11 }),
4275
- "Table"
4276
- ] }),
4277
- /* @__PURE__ */ jsxs18("button", { onClick: () => setViewMode("cards"), className: segCtrlClass("cards"), children: [
4278
- /* @__PURE__ */ jsx21(FaThLarge, { size: 11 }),
4279
- "Cards"
4280
- ] })
4281
- ] }) }),
4282
- /* @__PURE__ */ jsxs18("div", { className: scrollOuterClass, children: [
4283
- isLoading && /* @__PURE__ */ jsx21("div", { className: "absolute inset-0 z-20 flex items-center justify-center bg-white/40 backdrop-blur-[2px] transition-all duration-300", children: /* @__PURE__ */ jsx21("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__ */ jsxs18(Fragment4, { children: [
4284
- /* @__PURE__ */ jsx21(FaSpinner, { className: "animate-spin text-primary-500 text-4xl" }),
4285
- /* @__PURE__ */ jsx21(ITText, { as: "span", className: "text-sm font-semibold text-secondary-600 animate-pulse", children: "Cargando datos..." })
4286
- ] }) }) }),
4287
- effectiveView === "cards" ? /* @__PURE__ */ jsx21("div", { className: "p-4 space-y-3 max-h-[400px] overflow-y-auto", children: data.length > 0 ? data.map((row, i) => /* @__PURE__ */ jsx21(
4288
- "div",
4289
- {
4290
- className: clsx21(tableCardHover, onRowClick && !isLoading && tableCardClickable),
4291
- role: onRowClick && !isLoading ? "button" : void 0,
4292
- tabIndex: onRowClick && !isLoading ? 0 : void 0,
4293
- onClick: onRowClick && !isLoading ? handleRowClick(row) : void 0,
4294
- onKeyDown: onRowClick && !isLoading ? handleRowKeyDown(row) : void 0,
4295
- children: renderCard ? renderCard(row) : renderDefaultCard(row)
4296
- },
4297
- i
4298
- )) : !isLoading && /* @__PURE__ */ jsxs18("div", { className: clsx21(tableEmptyContent, "py-12"), children: [
4299
- /* @__PURE__ */ jsx21(ITText, { as: "span", className: "text-lg", children: "No se encontraron resultados" }),
4300
- /* @__PURE__ */ jsx21(ITText, { as: "span", className: "text-sm mt-1", children: "Intenta ajustar los filtros" })
4301
- ] }) }) : isTableVirtual ? /* @__PURE__ */ jsx21(
4096
+ isOpen && createPortal3(
4097
+ /* @__PURE__ */ jsx21(
4302
4098
  "div",
4303
4099
  {
4304
- ref: scrollRef,
4305
- className: "overflow-x-auto overflow-y-auto",
4306
- style: { maxHeight: virtualizedMaxHeight },
4307
- children: tableEl
4100
+ ref: panelRef,
4101
+ style: panelStyle,
4102
+ 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",
4103
+ children: /* @__PURE__ */ jsx21("div", { className: "max-h-60 overflow-y-auto", children: filteredOptions.length > 0 ? filteredOptions.map((option) => {
4104
+ const isSelected = value === option[valueField];
4105
+ return /* @__PURE__ */ jsx21(
4106
+ ITText,
4107
+ {
4108
+ as: "div",
4109
+ onClick: () => handleSelect(option),
4110
+ className: clsx21(
4111
+ "px-4 py-2 text-sm cursor-pointer transition-colors",
4112
+ 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"
4113
+ ),
4114
+ children: renderOption ? renderOption(option, { isSelected, searchTerm }) : /* @__PURE__ */ jsx21(ITText, { as: "span", children: option[labelField] })
4115
+ },
4116
+ option[valueField]
4117
+ );
4118
+ }) : /* @__PURE__ */ jsx21(ITText, { as: "div", className: "px-4 py-6 text-sm text-center text-secondary-500 italic", children: isLoading ? "Cargando..." : noResultsMessage }) })
4308
4119
  }
4309
- ) : tableEl
4310
- ] })
4120
+ ),
4121
+ document.body
4122
+ )
4311
4123
  ] }),
4312
- /* @__PURE__ */ jsx21("div", { className: "rounded-b-xl px-6 py-4", style: { backgroundColor: "var(--color-table-rowBg, #ffffff)" }, children: /* @__PURE__ */ jsx21(
4313
- ITPagination,
4314
- {
4315
- currentPage,
4316
- totalPages: computedTotalPages,
4317
- onPageChange: goToPage,
4318
- color: "primary",
4319
- itemsPerPageOptions,
4320
- itemsPerPage,
4321
- onItemsPerPageChange: handleItemsPerPageChange,
4322
- totalItems
4323
- }
4324
- ) })
4124
+ hasError && /* @__PURE__ */ jsx21(ITText, { as: "p", className: "text-danger-500 text-xs mt-1", children: errorMessage })
4325
4125
  ] });
4326
4126
  }
4327
4127
 
4328
4128
  // src/components/molecules/date-picker/datePicker.tsx
4329
4129
  import clsx22 from "clsx";
4330
4130
  import React5, { useEffect as useEffect8, useRef as useRef12, useState as useState18 } from "react";
4331
- import { createPortal as createPortal3 } from "react-dom";
4131
+ import { createPortal as createPortal4 } from "react-dom";
4332
4132
  import { FaCalendarAlt } from "react-icons/fa";
4333
4133
  import { isBefore as isBefore2 } from "date-fns";
4334
4134
  import { jsx as jsx22, jsxs as jsxs19 } from "react/jsx-runtime";
@@ -4538,7 +4338,7 @@ function ITDatePicker({
4538
4338
  onClick: handleIconClick
4539
4339
  }
4540
4340
  ),
4541
- isOpen && createPortal3(
4341
+ isOpen && createPortal4(
4542
4342
  /* @__PURE__ */ jsx22(
4543
4343
  "div",
4544
4344
  {
@@ -4578,13 +4378,513 @@ function ITDatePicker({
4578
4378
  ] });
4579
4379
  }
4580
4380
 
4581
- // src/components/organisms/dialog/dialog.tsx
4582
- import { createPortal as createPortal4 } from "react-dom";
4583
- import { useEffect as useEffect9, useRef as useRef13 } from "react";
4381
+ // src/utils/table.utils.ts
4382
+ var formatCurrencyMX = (value) => {
4383
+ return value.toLocaleString("es-MX", {
4384
+ style: "currency",
4385
+ currency: "MXN"
4386
+ });
4387
+ };
4388
+ var getNestedValue = (obj, path) => {
4389
+ return path.split(".").reduce((acc, part) => acc && acc[part], obj);
4390
+ };
4391
+ var ROW_CLICK_IGNORE_SELECTOR = 'button, a, input, select, textarea, [role="button"], [role="link"], [data-row-click-ignore]';
4392
+ function isInteractiveTarget(target, boundary = null) {
4393
+ if (!(target instanceof Element)) return false;
4394
+ const interactive = target.closest(ROW_CLICK_IGNORE_SELECTOR);
4395
+ if (!interactive) return false;
4396
+ if (boundary instanceof Node && interactive === boundary) return false;
4397
+ return true;
4398
+ }
4399
+
4400
+ // src/components/organisms/data-table/dataTable.tsx
4401
+ import { Fragment as Fragment4, jsx as jsx23, jsxs as jsxs20 } from "react/jsx-runtime";
4402
+ var getNestedValue2 = (obj, path) => {
4403
+ return path.split(".").reduce((acc, part) => acc && acc[part], obj);
4404
+ };
4405
+ var EMPTY_OBJECT = {};
4406
+ function ITDataTable({
4407
+ columns,
4408
+ fetchData,
4409
+ debounceMs = 500,
4410
+ externalFilters = EMPTY_OBJECT,
4411
+ loadingIndicator,
4412
+ fetchOnMount = true,
4413
+ reloadTrigger,
4414
+ containerClassName,
4415
+ className,
4416
+ variant = "default",
4417
+ size = "md",
4418
+ itemsPerPageOptions = [5, 10, 20],
4419
+ defaultItemsPerPage = 10,
4420
+ title,
4421
+ renderCard,
4422
+ defaultView,
4423
+ showVerticalBorder = true,
4424
+ verticalBorderClassname,
4425
+ onRowClick,
4426
+ layout = "auto",
4427
+ density = "normal",
4428
+ autoCardBreakpoint = 0,
4429
+ virtualized = false,
4430
+ virtualizedMaxHeight = 400,
4431
+ rowHeight,
4432
+ overscan = 5,
4433
+ stickyHeader = false
4434
+ }) {
4435
+ const [viewMode, setViewMode] = useState19(defaultView || "table");
4436
+ const { ref: rootRef, width: containerWidth } = useElementSize();
4437
+ const [data, setData] = useState19([]);
4438
+ const [totalItems, setTotalItems] = useState19(0);
4439
+ const [isLoading, setIsLoading] = useState19(fetchOnMount);
4440
+ const isFixed = layout === "fixed";
4441
+ const forcedCards = autoCardBreakpoint > 0 && containerWidth > 0 && containerWidth < autoCardBreakpoint;
4442
+ const effectiveView = forcedCards ? "cards" : viewMode;
4443
+ const hasColumnWidths = columns.some((col) => col.width != null);
4444
+ 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";
4445
+ const isTableVirtual = virtualized && effectiveView === "table";
4446
+ const isStickyHeader = stickyHeader && isTableVirtual;
4447
+ const resolvedRowHeight = rowHeight ?? getRowHeight(size, density);
4448
+ const columnCount = columns.length;
4449
+ const scrollOuterClass = isTableVirtual ? "relative min-h-[200px]" : "overflow-x-auto relative min-h-[200px]";
4450
+ const {
4451
+ currentPage,
4452
+ itemsPerPage,
4453
+ filters,
4454
+ sortConfig,
4455
+ goToPage,
4456
+ handleFilterChange,
4457
+ handleSort,
4458
+ handleItemsPerPageChange
4459
+ } = useTableState({ defaultItemsPerPage });
4460
+ const {
4461
+ scrollRef,
4462
+ startIndex,
4463
+ endIndex,
4464
+ topSpacerHeight,
4465
+ bottomSpacerHeight
4466
+ } = useVirtualRows({
4467
+ count: data.length,
4468
+ rowHeight: resolvedRowHeight,
4469
+ overscan,
4470
+ enabled: isTableVirtual,
4471
+ resetKey: `${currentPage}-${itemsPerPage}`
4472
+ });
4473
+ const windowData = isTableVirtual ? data.slice(startIndex, endIndex + 1) : data;
4474
+ const debounceTimerRef = useRef13(null);
4475
+ const hasFetchedRef = useRef13(false);
4476
+ const fetchDataRef = useRef13(fetchData);
4477
+ fetchDataRef.current = fetchData;
4478
+ const externalFiltersRef = useRef13(externalFilters);
4479
+ externalFiltersRef.current = externalFilters;
4480
+ const externalKey = JSON.stringify(externalFilters);
4481
+ const computedTotalPages = Math.ceil(totalItems / itemsPerPage) || 1;
4482
+ const performFetch = useCallback7(async () => {
4483
+ setIsLoading(true);
4484
+ try {
4485
+ const response = await fetchDataRef.current({
4486
+ page: currentPage,
4487
+ limit: itemsPerPage,
4488
+ filters: { ...filters, ...externalFiltersRef.current },
4489
+ sort: sortConfig || void 0
4490
+ });
4491
+ setData(response.data || []);
4492
+ setTotalItems(response.total || 0);
4493
+ hasFetchedRef.current = true;
4494
+ } catch (error) {
4495
+ console.error("ITDataTable: Error fetching data", error);
4496
+ setData([]);
4497
+ setTotalItems(0);
4498
+ hasFetchedRef.current = true;
4499
+ } finally {
4500
+ setIsLoading(false);
4501
+ }
4502
+ }, [currentPage, itemsPerPage, filters, sortConfig]);
4503
+ const performFetchRef = useRef13(performFetch);
4504
+ performFetchRef.current = performFetch;
4505
+ useEffect9(() => {
4506
+ if (!fetchOnMount && !hasFetchedRef.current) return;
4507
+ if (debounceTimerRef.current) clearTimeout(debounceTimerRef.current);
4508
+ debounceTimerRef.current = setTimeout(() => {
4509
+ performFetchRef.current();
4510
+ }, debounceMs);
4511
+ return () => {
4512
+ if (debounceTimerRef.current) clearTimeout(debounceTimerRef.current);
4513
+ };
4514
+ }, [currentPage, itemsPerPage, sortConfig, filters, externalKey, reloadTrigger, fetchOnMount, debounceMs]);
4515
+ const renderFilterInput = (col) => {
4516
+ if (!col.filter) return null;
4517
+ if (col.type === "boolean") {
4518
+ const currentValue = filters[col.key];
4519
+ const nextValue = currentValue === void 0 ? true : currentValue === true ? false : void 0;
4520
+ const getToggleLabel = () => {
4521
+ if (currentValue === void 0) return "Mostrar todos";
4522
+ if (currentValue === true) return "Filtrar solo verdaderos";
4523
+ return "Filtrar solo falsos";
4524
+ };
4525
+ return /* @__PURE__ */ jsx23(
4526
+ "button",
4527
+ {
4528
+ 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",
4529
+ onClick: () => handleFilterChange(col.key, nextValue),
4530
+ "aria-label": `${getToggleLabel()} para ${col.label}`,
4531
+ title: `${getToggleLabel()} para ${col.label}`,
4532
+ disabled: isLoading,
4533
+ children: /* @__PURE__ */ jsx23("div", { className: "relative w-10 h-5 bg-secondary-300 rounded-full", children: /* @__PURE__ */ jsx23(
4534
+ "div",
4535
+ {
4536
+ className: clsx23(
4537
+ "absolute top-0.5 w-4 h-4 rounded-full transition-all duration-300 shadow-sm",
4538
+ {
4539
+ "left-0.5 bg-secondary-400": currentValue === void 0,
4540
+ "left-5 bg-slate-500": currentValue === true,
4541
+ "left-0.5 bg-secondary-500": currentValue === false
4542
+ }
4543
+ )
4544
+ }
4545
+ ) })
4546
+ }
4547
+ );
4548
+ }
4549
+ if (col.filter === "catalog" && col.catalogOptions) {
4550
+ if (col.catalogOptions.loading) {
4551
+ return /* @__PURE__ */ jsx23(FaSpinner, { className: "animate-spin", "aria-label": "Cargando opciones", title: "Cargando opciones" });
4552
+ }
4553
+ if (col.catalogOptions.error) {
4554
+ return /* @__PURE__ */ jsx23(ITText, { as: "span", className: "text-danger-500 text-xs", children: "Error cargando" });
4555
+ }
4556
+ return /* @__PURE__ */ jsx23(
4557
+ ITSelect,
4558
+ {
4559
+ name: `filter-${col.key}`,
4560
+ options: [
4561
+ { value: "", label: "Todos" },
4562
+ ...col.catalogOptions.data.map((item) => ({
4563
+ value: String(item.id),
4564
+ label: item.name
4565
+ }))
4566
+ ],
4567
+ value: String(filters[col.key] || ""),
4568
+ onChange: (e) => {
4569
+ const value = e.target.value === "" ? void 0 : e.target.value;
4570
+ handleFilterChange(col.key, value);
4571
+ },
4572
+ onBlur: () => {
4573
+ },
4574
+ className: "w-full text-xs",
4575
+ disabled: isLoading
4576
+ }
4577
+ );
4578
+ }
4579
+ if (col.filter === "search" && col.catalogOptions) {
4580
+ if (col.catalogOptions.loading) {
4581
+ return /* @__PURE__ */ jsx23(FaSpinner, { className: "animate-spin", "aria-label": "Cargando opciones", title: "Cargando opciones" });
4582
+ }
4583
+ if (col.catalogOptions.error) {
4584
+ return /* @__PURE__ */ jsx23(ITText, { as: "span", className: "text-danger-500 text-xs", children: "Error cargando" });
4585
+ }
4586
+ const searchValue = filters[col.key];
4587
+ return /* @__PURE__ */ jsx23(
4588
+ ITSearchSelect,
4589
+ {
4590
+ name: `filter-${col.key}`,
4591
+ options: col.catalogOptions.data.map((item) => ({
4592
+ value: item.id,
4593
+ label: item.name
4594
+ })),
4595
+ value: typeof searchValue === "string" || typeof searchValue === "number" ? searchValue : "",
4596
+ onChange: (value) => handleFilterChange(col.key, value === "" ? void 0 : value),
4597
+ onSearch: col.catalogOptions.onSearch,
4598
+ isLoading: col.catalogOptions.loading,
4599
+ size: "sm",
4600
+ placeholder: "Buscar...",
4601
+ clearable: true,
4602
+ className: "w-full",
4603
+ onBlur: () => {
4604
+ },
4605
+ disabled: isLoading
4606
+ }
4607
+ );
4608
+ }
4609
+ if (col.filter === "date") {
4610
+ const dateValue = filters[col.key];
4611
+ return /* @__PURE__ */ jsx23(
4612
+ ITDatePicker,
4613
+ {
4614
+ name: `filter-${col.key}`,
4615
+ value: dateValue instanceof Date ? dateValue : void 0,
4616
+ onChange: (e) => handleFilterChange(col.key, e.target.value),
4617
+ minDate: col.dateFilterOptions?.minDate,
4618
+ maxDate: col.dateFilterOptions?.maxDate,
4619
+ size: "sm",
4620
+ placeholder: "dd/mm/aaaa",
4621
+ className: "w-full",
4622
+ disabled: isLoading
4623
+ }
4624
+ );
4625
+ }
4626
+ if (col.filter === "date-range") {
4627
+ const rangeValue = filters[col.key];
4628
+ return /* @__PURE__ */ jsx23(
4629
+ ITDatePicker,
4630
+ {
4631
+ name: `filter-${col.key}`,
4632
+ range: true,
4633
+ value: Array.isArray(rangeValue) ? rangeValue : void 0,
4634
+ onChange: (e) => handleFilterChange(col.key, e.target.value),
4635
+ minDate: col.dateFilterOptions?.minDate,
4636
+ maxDate: col.dateFilterOptions?.maxDate,
4637
+ size: "sm",
4638
+ placeholder: "dd/mm/aaaa - dd/mm/aaaa",
4639
+ className: "w-full",
4640
+ disabled: isLoading
4641
+ }
4642
+ );
4643
+ }
4644
+ return /* @__PURE__ */ jsx23(
4645
+ ITInput,
4646
+ {
4647
+ name: `filter-${col.key}`,
4648
+ className: "w-full text-xs",
4649
+ placeholder: "Buscar...",
4650
+ value: String(filters[col.key] || ""),
4651
+ onChange: (e) => handleFilterChange(col.key, e.target.value),
4652
+ onBlur: () => {
4653
+ },
4654
+ disabled: isLoading
4655
+ }
4656
+ );
4657
+ };
4658
+ const renderCellContent = (col, row) => {
4659
+ const value = getNestedValue2(row, col.key);
4660
+ if (col.render) return col.render(row);
4661
+ switch (col.type) {
4662
+ case "number":
4663
+ return typeof value === "number" && col.currencyMX ? formatCurrencyMX(value) : value;
4664
+ case "boolean":
4665
+ return value ? /* @__PURE__ */ jsx23(FaCheck2, { className: "text-success-500", "aria-label": "Verdadero", title: "Verdadero" }) : /* @__PURE__ */ jsx23(FaTimes5, { className: "text-danger-500", "aria-label": "Falso", title: "Falso" });
4666
+ case "actions":
4667
+ return col.actions ? col.actions(row) : null;
4668
+ case "catalog":
4669
+ if (col.catalogOptions) {
4670
+ const catalogItem = col.catalogOptions.data.find((item) => item.id === value);
4671
+ return catalogItem?.name || value;
4672
+ }
4673
+ return value;
4674
+ default:
4675
+ return value;
4676
+ }
4677
+ };
4678
+ const renderDefaultCard = (row) => {
4679
+ const dataCols = columns.filter((c) => c.type !== "actions");
4680
+ const actionCol = columns.find((c) => c.type === "actions");
4681
+ return /* @__PURE__ */ jsxs20("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: [
4682
+ dataCols.map((col) => /* @__PURE__ */ jsxs20("div", { className: "flex items-center justify-between gap-2", children: [
4683
+ /* @__PURE__ */ jsx23("span", { className: "text-[10px] font-bold uppercase tracking-wider text-slate-400 whitespace-nowrap flex-shrink-0 min-w-[70px]", children: col.label }),
4684
+ /* @__PURE__ */ jsx23("span", { className: "text-sm font-medium text-slate-800 dark:text-white text-right truncate", children: renderCellContent(col, row) })
4685
+ ] }, col.key)),
4686
+ actionCol?.actions && /* @__PURE__ */ jsx23("div", { className: "flex items-center justify-end gap-2 pt-2 border-t border-slate-100 dark:border-slate-700", children: actionCol.actions(row) })
4687
+ ] });
4688
+ };
4689
+ 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"}`;
4690
+ const handleRowClick = (row) => (event) => {
4691
+ if (!onRowClick || isLoading || isInteractiveTarget(event.target, event.currentTarget)) return;
4692
+ onRowClick(row, event);
4693
+ };
4694
+ const handleRowKeyDown = (row) => (event) => {
4695
+ if (!onRowClick || isLoading) return;
4696
+ if (event.target !== event.currentTarget) return;
4697
+ if (event.key !== "Enter" && event.key !== " ") return;
4698
+ event.preventDefault();
4699
+ onRowClick(row, event);
4700
+ };
4701
+ const tableEl = /* @__PURE__ */ jsxs20(
4702
+ "table",
4703
+ {
4704
+ className: clsx23(
4705
+ tableLayoutClass,
4706
+ showVerticalBorder && "[&_th]:border-r [&_th:last-child]:border-r-0 [&_td]:border-r [&_td:last-child]:border-r-0",
4707
+ showVerticalBorder && (verticalBorderClassname || "[&_th]:border-slate-100 dark:[&_th]:border-slate-700/30 [&_td]:border-slate-100 dark:[&_td]:border-slate-700/30"),
4708
+ isLoading ? "opacity-50" : "opacity-100",
4709
+ variantStyles[variant],
4710
+ sizeStyles[size],
4711
+ className
4712
+ ),
4713
+ style: isFixed ? { tableLayout: "fixed" } : void 0,
4714
+ "aria-rowcount": isTableVirtual ? data.length + 1 : void 0,
4715
+ children: [
4716
+ hasColumnWidths && /* @__PURE__ */ jsx23("colgroup", { children: columns.map((col) => /* @__PURE__ */ jsx23(
4717
+ "col",
4718
+ {
4719
+ style: col.width != null ? { width: typeof col.width === "number" ? `${col.width}px` : col.width } : void 0
4720
+ },
4721
+ col.key
4722
+ )) }),
4723
+ /* @__PURE__ */ jsx23("thead", { children: /* @__PURE__ */ jsx23(
4724
+ "tr",
4725
+ {
4726
+ className: clsx23(tableHeaderRow, "dark:text-slate-200"),
4727
+ "aria-rowindex": isTableVirtual ? 1 : void 0,
4728
+ children: columns.map((col) => /* @__PURE__ */ jsx23(
4729
+ "th",
4730
+ {
4731
+ scope: "col",
4732
+ className: clsx23(
4733
+ tableHeaderCell(col.className, density),
4734
+ col.align && tableAlignClasses[col.align],
4735
+ isStickyHeader && "sticky top-0 z-10 bg-secondary-50"
4736
+ ),
4737
+ style: col.minWidth != null || isStickyHeader ? {
4738
+ ...col.minWidth != null ? { minWidth: `${col.minWidth}px` } : {},
4739
+ ...isStickyHeader ? { backgroundColor: "var(--color-table-headerBg, #f8fafc)" } : {}
4740
+ } : void 0,
4741
+ children: /* @__PURE__ */ jsxs20("div", { className: isFixed ? "flex flex-col gap-3" : "flex flex-col gap-3 min-w-[150px]", children: [
4742
+ /* @__PURE__ */ jsxs20("div", { className: "flex items-center justify-between gap-2", children: [
4743
+ /* @__PURE__ */ jsx23(ITText, { as: "span", className: "text-slate-900 dark:text-white font-bold", children: col.label }),
4744
+ col.sortable && col.type !== "actions" && /* @__PURE__ */ jsx23(
4745
+ "button",
4746
+ {
4747
+ onClick: () => handleSort(col.key),
4748
+ disabled: isLoading,
4749
+ 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`,
4750
+ title: `Ordenar por ${col.label}`,
4751
+ children: /* @__PURE__ */ jsx23(MdOutlineSwapVert, { className: "w-4 h-4", "aria-hidden": "true" })
4752
+ }
4753
+ )
4754
+ ] }),
4755
+ /* @__PURE__ */ jsx23("div", { className: "w-full", children: col.filter ? renderFilterInput(col) : null })
4756
+ ] })
4757
+ },
4758
+ col.key
4759
+ ))
4760
+ }
4761
+ ) }),
4762
+ /* @__PURE__ */ jsx23("tbody", { className: clsx23(tableBody, "dark:divide-slate-700/30"), children: data.length > 0 ? /* @__PURE__ */ jsxs20(Fragment4, { children: [
4763
+ isTableVirtual && topSpacerHeight > 0 && /* @__PURE__ */ jsx23("tr", { "aria-hidden": "true", style: { height: topSpacerHeight }, children: /* @__PURE__ */ jsx23("td", { colSpan: columnCount, style: { padding: 0, border: 0 } }) }),
4764
+ windowData.map((row, windowIndex) => {
4765
+ const absoluteIndex = isTableVirtual ? startIndex + windowIndex : windowIndex;
4766
+ return /* @__PURE__ */ jsx23(
4767
+ "tr",
4768
+ {
4769
+ "aria-rowindex": isTableVirtual ? absoluteIndex + 2 : void 0,
4770
+ className: clsx23(
4771
+ tableRow,
4772
+ variant === "striped" && absoluteIndex % 2 === 0 && "bg-secondary-50/40 dark:bg-slate-800/20",
4773
+ onRowClick && !isLoading && tableRowClickable
4774
+ ),
4775
+ tabIndex: onRowClick && !isLoading ? 0 : void 0,
4776
+ onClick: onRowClick && !isLoading ? handleRowClick(row) : void 0,
4777
+ onKeyDown: onRowClick && !isLoading ? handleRowKeyDown(row) : void 0,
4778
+ children: columns.map((col) => {
4779
+ const rawValue = getNestedValue2(row, col.key);
4780
+ const truncateTitle = col.truncate && (typeof rawValue === "string" || typeof rawValue === "number") ? String(rawValue) : void 0;
4781
+ return /* @__PURE__ */ jsx23(
4782
+ "td",
4783
+ {
4784
+ className: clsx23(
4785
+ tableCell(col.className, density),
4786
+ col.align && tableAlignClasses[col.align]
4787
+ ),
4788
+ style: col.minWidth != null ? { minWidth: `${col.minWidth}px` } : void 0,
4789
+ title: truncateTitle,
4790
+ children: col.type === "actions" ? /* @__PURE__ */ jsx23("div", { className: tableActionsCell, children: renderCellContent(col, row) }) : /* @__PURE__ */ jsx23("div", { className: clsx23(tableCellText, col.truncate && "truncate"), children: renderCellContent(col, row) })
4791
+ },
4792
+ `${absoluteIndex}-${col.key}`
4793
+ );
4794
+ })
4795
+ },
4796
+ absoluteIndex
4797
+ );
4798
+ }),
4799
+ isTableVirtual && bottomSpacerHeight > 0 && /* @__PURE__ */ jsx23("tr", { "aria-hidden": "true", style: { height: bottomSpacerHeight }, children: /* @__PURE__ */ jsx23("td", { colSpan: columnCount, style: { padding: 0, border: 0 } }) })
4800
+ ] }) : /* @__PURE__ */ jsx23("tr", { children: /* @__PURE__ */ jsx23("td", { colSpan: columns.length, className: "px-6 py-12 text-center", children: !isLoading && /* @__PURE__ */ jsxs20("div", { className: tableEmptyContent, children: [
4801
+ /* @__PURE__ */ jsx23(ITText, { as: "span", className: "text-lg", children: "No se encontraron resultados" }),
4802
+ /* @__PURE__ */ jsx23(ITText, { as: "span", className: "text-sm mt-1", children: "Intenta ajustar los filtros" })
4803
+ ] }) }) }) })
4804
+ ]
4805
+ }
4806
+ );
4807
+ return /* @__PURE__ */ jsxs20("div", { ref: rootRef, className: clsx23("space-y-4 w-full relative", containerClassName), children: [
4808
+ /* @__PURE__ */ jsxs20("div", { className: tableContainer, style: { backgroundColor: "var(--color-table-rowBg, #ffffff)" }, children: [
4809
+ title && /* @__PURE__ */ jsxs20("div", { className: "px-6 py-5 flex items-center justify-between", style: { backgroundColor: "var(--color-table-rowBg, #ffffff)" }, children: [
4810
+ /* @__PURE__ */ jsx23(ITText, { as: "h2", className: "text-xl font-bold text-secondary-900 leading-tight", children: title }),
4811
+ /* @__PURE__ */ jsxs20("div", { className: "flex items-center gap-3", children: [
4812
+ isLoading && /* @__PURE__ */ jsx23("div", { className: "text-secondary-400", children: loadingIndicator || /* @__PURE__ */ jsx23(FaSpinner, { className: "animate-spin text-primary-500 text-xl" }) }),
4813
+ /* @__PURE__ */ jsxs20("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: [
4814
+ /* @__PURE__ */ jsxs20("button", { onClick: () => setViewMode("table"), disabled: forcedCards, className: segCtrlClass("table"), children: [
4815
+ /* @__PURE__ */ jsx23(FaTable, { size: 11 }),
4816
+ "Table"
4817
+ ] }),
4818
+ /* @__PURE__ */ jsxs20("button", { onClick: () => setViewMode("cards"), className: segCtrlClass("cards"), children: [
4819
+ /* @__PURE__ */ jsx23(FaThLarge, { size: 11 }),
4820
+ "Cards"
4821
+ ] })
4822
+ ] })
4823
+ ] })
4824
+ ] }),
4825
+ !title && /* @__PURE__ */ jsx23("div", { className: "flex justify-end px-4 pt-3", children: /* @__PURE__ */ jsxs20("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: [
4826
+ /* @__PURE__ */ jsxs20("button", { onClick: () => setViewMode("table"), disabled: forcedCards, className: segCtrlClass("table"), children: [
4827
+ /* @__PURE__ */ jsx23(FaTable, { size: 11 }),
4828
+ "Table"
4829
+ ] }),
4830
+ /* @__PURE__ */ jsxs20("button", { onClick: () => setViewMode("cards"), className: segCtrlClass("cards"), children: [
4831
+ /* @__PURE__ */ jsx23(FaThLarge, { size: 11 }),
4832
+ "Cards"
4833
+ ] })
4834
+ ] }) }),
4835
+ /* @__PURE__ */ jsxs20("div", { className: scrollOuterClass, children: [
4836
+ isLoading && /* @__PURE__ */ jsx23("div", { className: "absolute inset-0 z-20 flex items-center justify-center bg-white/40 backdrop-blur-[2px] transition-all duration-300", children: /* @__PURE__ */ jsx23("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__ */ jsxs20(Fragment4, { children: [
4837
+ /* @__PURE__ */ jsx23(FaSpinner, { className: "animate-spin text-primary-500 text-4xl" }),
4838
+ /* @__PURE__ */ jsx23(ITText, { as: "span", className: "text-sm font-semibold text-secondary-600 animate-pulse", children: "Cargando datos..." })
4839
+ ] }) }) }),
4840
+ effectiveView === "cards" ? /* @__PURE__ */ jsx23("div", { className: "p-4 space-y-3 max-h-[400px] overflow-y-auto", children: data.length > 0 ? data.map((row, i) => /* @__PURE__ */ jsx23(
4841
+ "div",
4842
+ {
4843
+ className: clsx23(tableCardHover, onRowClick && !isLoading && tableCardClickable),
4844
+ role: onRowClick && !isLoading ? "button" : void 0,
4845
+ tabIndex: onRowClick && !isLoading ? 0 : void 0,
4846
+ onClick: onRowClick && !isLoading ? handleRowClick(row) : void 0,
4847
+ onKeyDown: onRowClick && !isLoading ? handleRowKeyDown(row) : void 0,
4848
+ children: renderCard ? renderCard(row) : renderDefaultCard(row)
4849
+ },
4850
+ i
4851
+ )) : !isLoading && /* @__PURE__ */ jsxs20("div", { className: clsx23(tableEmptyContent, "py-12"), children: [
4852
+ /* @__PURE__ */ jsx23(ITText, { as: "span", className: "text-lg", children: "No se encontraron resultados" }),
4853
+ /* @__PURE__ */ jsx23(ITText, { as: "span", className: "text-sm mt-1", children: "Intenta ajustar los filtros" })
4854
+ ] }) }) : isTableVirtual ? /* @__PURE__ */ jsx23(
4855
+ "div",
4856
+ {
4857
+ ref: scrollRef,
4858
+ className: "overflow-x-auto overflow-y-auto",
4859
+ style: { maxHeight: virtualizedMaxHeight },
4860
+ children: tableEl
4861
+ }
4862
+ ) : tableEl
4863
+ ] })
4864
+ ] }),
4865
+ /* @__PURE__ */ jsx23("div", { className: "rounded-b-xl px-6 py-4", style: { backgroundColor: "var(--color-table-rowBg, #ffffff)" }, children: /* @__PURE__ */ jsx23(
4866
+ ITPagination,
4867
+ {
4868
+ currentPage,
4869
+ totalPages: computedTotalPages,
4870
+ onPageChange: goToPage,
4871
+ color: "primary",
4872
+ itemsPerPageOptions,
4873
+ itemsPerPage,
4874
+ onItemsPerPageChange: handleItemsPerPageChange,
4875
+ totalItems
4876
+ }
4877
+ ) })
4878
+ ] });
4879
+ }
4880
+
4881
+ // src/components/organisms/dialog/dialog.tsx
4882
+ import { createPortal as createPortal5 } from "react-dom";
4883
+ import { useEffect as useEffect10, useRef as useRef14 } from "react";
4584
4884
  import { FaRegTimesCircle } from "react-icons/fa";
4585
4885
 
4586
4886
  // src/components/molecules/form-header/form-header.tsx
4587
- import { FaTimes as FaTimes5 } from "react-icons/fa";
4887
+ import { FaTimes as FaTimes6 } from "react-icons/fa";
4588
4888
 
4589
4889
  // src/theme/theme-context.ts
4590
4890
  import { createContext, useContext } from "react";
@@ -4677,7 +4977,7 @@ var getContrastTextColor = (bgColor, palette2, isDarkMode) => {
4677
4977
  };
4678
4978
 
4679
4979
  // src/components/molecules/form-header/form-header.tsx
4680
- import { jsx as jsx23, jsxs as jsxs20 } from "react/jsx-runtime";
4980
+ import { jsx as jsx24, jsxs as jsxs21 } from "react/jsx-runtime";
4681
4981
  function ITFormHeader({
4682
4982
  title,
4683
4983
  onClose,
@@ -4691,23 +4991,23 @@ function ITFormHeader({
4691
4991
  palette2,
4692
4992
  isDarkMode
4693
4993
  );
4694
- return /* @__PURE__ */ jsxs20("div", { className: `bg-primary-500 ${textColorClass} px-6 py-4 rounded-t-lg flex justify-center items-center relative ${className}`, children: [
4695
- /* @__PURE__ */ jsx23(ITText, { as: "h2", className: "text-lg font-semibold text-center", style: { color: "inherit" }, children: title }),
4696
- onClose && /* @__PURE__ */ jsx23(
4994
+ return /* @__PURE__ */ jsxs21("div", { className: `bg-primary-500 ${textColorClass} px-6 py-4 rounded-t-lg flex justify-center items-center relative ${className}`, children: [
4995
+ /* @__PURE__ */ jsx24(ITText, { as: "h2", className: "text-lg font-semibold text-center", style: { color: "inherit" }, children: title }),
4996
+ onClose && /* @__PURE__ */ jsx24(
4697
4997
  "button",
4698
4998
  {
4699
4999
  onClick: onClose,
4700
5000
  className: `absolute right-4 ${textColorClass} hover:opacity-80 transition-colors duration-200 p-1 rounded-full`,
4701
5001
  style: { color: "inherit" },
4702
5002
  "aria-label": "Cerrar",
4703
- children: /* @__PURE__ */ jsx23(FaTimes5, { className: "w-4 h-4" })
5003
+ children: /* @__PURE__ */ jsx24(FaTimes6, { className: "w-4 h-4" })
4704
5004
  }
4705
5005
  )
4706
5006
  ] });
4707
5007
  }
4708
5008
 
4709
5009
  // src/components/organisms/dialog/dialog.tsx
4710
- import { Fragment as Fragment5, jsx as jsx24, jsxs as jsxs21 } from "react/jsx-runtime";
5010
+ import { Fragment as Fragment5, jsx as jsx25, jsxs as jsxs22 } from "react/jsx-runtime";
4711
5011
  function ITDialog({
4712
5012
  isOpen,
4713
5013
  onClose,
@@ -4717,9 +5017,9 @@ function ITDialog({
4717
5017
  useFormHeader = false,
4718
5018
  fullScreen = false
4719
5019
  }) {
4720
- const modalRef = useRef13(null);
5020
+ const modalRef = useRef14(null);
4721
5021
  useClickOutside_default(modalRef, onClose);
4722
- useEffect9(() => {
5022
+ useEffect10(() => {
4723
5023
  const handleEscape = (event) => {
4724
5024
  if (event.key === "Escape") {
4725
5025
  onClose();
@@ -4734,12 +5034,12 @@ function ITDialog({
4734
5034
  }, [isOpen, onClose]);
4735
5035
  if (!isOpen) return null;
4736
5036
  if (typeof document === "undefined") return null;
4737
- const content = /* @__PURE__ */ jsx24(
5037
+ const content = /* @__PURE__ */ jsx25(
4738
5038
  "div",
4739
5039
  {
4740
5040
  "data-it-dialog": "true",
4741
5041
  className: `fixed inset-0 flex ${fullScreen ? "items-stretch" : "items-center justify-center"} bg-slate-900/50 z-[60]`,
4742
- children: /* @__PURE__ */ jsx24(
5042
+ children: /* @__PURE__ */ jsx25(
4743
5043
  "div",
4744
5044
  {
4745
5045
  ref: modalRef,
@@ -4752,41 +5052,41 @@ function ITDialog({
4752
5052
  borderColor: theme.card.borderColor,
4753
5053
  borderStyle: "solid"
4754
5054
  },
4755
- children: useFormHeader && title ? /* @__PURE__ */ jsxs21(Fragment5, { children: [
4756
- /* @__PURE__ */ jsx24(ITFormHeader, { title, onClose }),
4757
- /* @__PURE__ */ jsx24("div", { className: fullScreen ? "flex-1 overflow-auto p-6" : "p-6", children })
4758
- ] }) : /* @__PURE__ */ jsxs21(Fragment5, { children: [
4759
- /* @__PURE__ */ jsx24(
5055
+ children: useFormHeader && title ? /* @__PURE__ */ jsxs22(Fragment5, { children: [
5056
+ /* @__PURE__ */ jsx25(ITFormHeader, { title, onClose }),
5057
+ /* @__PURE__ */ jsx25("div", { className: fullScreen ? "flex-1 overflow-auto p-6" : "p-6", children })
5058
+ ] }) : /* @__PURE__ */ jsxs22(Fragment5, { children: [
5059
+ /* @__PURE__ */ jsx25(
4760
5060
  "button",
4761
5061
  {
4762
5062
  className: "absolute top-2 right-2 text-secondary-600 hover:text-secondary-900",
4763
5063
  onClick: onClose,
4764
- children: /* @__PURE__ */ jsx24(FaRegTimesCircle, {})
5064
+ children: /* @__PURE__ */ jsx25(FaRegTimesCircle, {})
4765
5065
  }
4766
5066
  ),
4767
- title && /* @__PURE__ */ jsx24(ITText, { as: "h2", className: "text-xl font-semibold mb-4", children: title }),
4768
- /* @__PURE__ */ jsx24("div", { children })
5067
+ title && /* @__PURE__ */ jsx25(ITText, { as: "h2", className: "text-xl font-semibold mb-4", children: title }),
5068
+ /* @__PURE__ */ jsx25("div", { children })
4769
5069
  ] })
4770
5070
  }
4771
5071
  )
4772
5072
  }
4773
5073
  );
4774
- return createPortal4(content, document.body);
5074
+ return createPortal5(content, document.body);
4775
5075
  }
4776
5076
 
4777
5077
  // src/components/atoms/divider/divider.tsx
4778
- import clsx23 from "clsx";
4779
- import { jsx as jsx25 } from "react/jsx-runtime";
5078
+ import clsx24 from "clsx";
5079
+ import { jsx as jsx26 } from "react/jsx-runtime";
4780
5080
  function ITDivider({
4781
5081
  orientation = "horizontal",
4782
5082
  className,
4783
5083
  color = "bg-slate-200 dark:bg-slate-700",
4784
5084
  thickness = orientation === "horizontal" ? "h-px" : "w-px"
4785
5085
  }) {
4786
- return /* @__PURE__ */ jsx25(
5086
+ return /* @__PURE__ */ jsx26(
4787
5087
  "div",
4788
5088
  {
4789
- className: clsx23(
5089
+ className: clsx24(
4790
5090
  "flex-shrink-0",
4791
5091
  orientation === "horizontal" ? "w-full" : "self-stretch",
4792
5092
  thickness,
@@ -4798,10 +5098,10 @@ function ITDivider({
4798
5098
  }
4799
5099
 
4800
5100
  // src/components/organisms/drawer/drawer.tsx
4801
- import clsx24 from "clsx";
4802
- import { FaTimes as FaTimes6 } from "react-icons/fa";
4803
- import { useRef as useRef14 } from "react";
4804
- import { Fragment as Fragment6, jsx as jsx26, jsxs as jsxs22 } from "react/jsx-runtime";
5101
+ import clsx25 from "clsx";
5102
+ import { FaTimes as FaTimes7 } from "react-icons/fa";
5103
+ import { useRef as useRef15 } from "react";
5104
+ import { Fragment as Fragment6, jsx as jsx27, jsxs as jsxs23 } from "react/jsx-runtime";
4805
5105
  function ITDrawer({
4806
5106
  isOpen,
4807
5107
  onClose,
@@ -4812,15 +5112,15 @@ function ITDrawer({
4812
5112
  className,
4813
5113
  style
4814
5114
  }) {
4815
- const panelRef = useRef14(null);
5115
+ const panelRef = useRef15(null);
4816
5116
  useClickOutside_default(panelRef, onClose);
4817
- return /* @__PURE__ */ jsx26(Fragment6, { children: isOpen && /* @__PURE__ */ jsxs22("div", { className: "fixed inset-0 z-[50] flex", children: [
4818
- /* @__PURE__ */ jsx26("div", { className: "absolute inset-0 bg-black/40 backdrop-blur-sm transition-opacity" }),
4819
- /* @__PURE__ */ jsxs22(
5117
+ return /* @__PURE__ */ jsx27(Fragment6, { children: isOpen && /* @__PURE__ */ jsxs23("div", { className: "fixed inset-0 z-[50] flex", children: [
5118
+ /* @__PURE__ */ jsx27("div", { className: "absolute inset-0 bg-black/40 backdrop-blur-sm transition-opacity" }),
5119
+ /* @__PURE__ */ jsxs23(
4820
5120
  "div",
4821
5121
  {
4822
5122
  ref: panelRef,
4823
- className: clsx24(
5123
+ className: clsx25(
4824
5124
  "relative z-10 h-full bg-white dark:bg-slate-900 shadow-2xl flex flex-col transition-transform duration-300",
4825
5125
  position === "right" ? "ml-auto" : "mr-auto",
4826
5126
  size,
@@ -4828,18 +5128,18 @@ function ITDrawer({
4828
5128
  ),
4829
5129
  style,
4830
5130
  children: [
4831
- title && /* @__PURE__ */ jsxs22("div", { className: "flex items-center justify-between px-5 py-4 border-b border-slate-200 dark:border-slate-700", children: [
4832
- /* @__PURE__ */ jsx26(ITText, { as: "h2", className: "text-lg font-bold text-slate-800 dark:text-white", children: title }),
4833
- /* @__PURE__ */ jsx26(
5131
+ title && /* @__PURE__ */ jsxs23("div", { className: "flex items-center justify-between px-5 py-4 border-b border-slate-200 dark:border-slate-700", children: [
5132
+ /* @__PURE__ */ jsx27(ITText, { as: "h2", className: "text-lg font-bold text-slate-800 dark:text-white", children: title }),
5133
+ /* @__PURE__ */ jsx27(
4834
5134
  "button",
4835
5135
  {
4836
5136
  onClick: onClose,
4837
5137
  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",
4838
- children: /* @__PURE__ */ jsx26(FaTimes6, { size: 14 })
5138
+ children: /* @__PURE__ */ jsx27(FaTimes7, { size: 14 })
4839
5139
  }
4840
5140
  )
4841
5141
  ] }),
4842
- /* @__PURE__ */ jsx26("div", { className: "flex-1 overflow-y-auto p-5", children })
5142
+ /* @__PURE__ */ jsx27("div", { className: "flex-1 overflow-y-auto p-5", children })
4843
5143
  ]
4844
5144
  }
4845
5145
  )
@@ -4847,27 +5147,27 @@ function ITDrawer({
4847
5147
  }
4848
5148
 
4849
5149
  // src/components/molecules/empty-state/empty-state.tsx
4850
- import clsx25 from "clsx";
5150
+ import clsx26 from "clsx";
4851
5151
  import { FaInbox } from "react-icons/fa";
4852
- import { jsx as jsx27, jsxs as jsxs23 } from "react/jsx-runtime";
5152
+ import { jsx as jsx28, jsxs as jsxs24 } from "react/jsx-runtime";
4853
5153
  function ITEmptyState({
4854
- icon = /* @__PURE__ */ jsx27(FaInbox, { size: 40 }),
5154
+ icon = /* @__PURE__ */ jsx28(FaInbox, { size: 40 }),
4855
5155
  title,
4856
5156
  description,
4857
5157
  action,
4858
5158
  className
4859
5159
  }) {
4860
- return /* @__PURE__ */ jsxs23("div", { className: clsx25("flex flex-col items-center justify-center py-16 px-6 text-center", className), children: [
4861
- /* @__PURE__ */ jsx27("div", { className: "text-slate-300 dark:text-slate-600 mb-4", children: icon }),
4862
- /* @__PURE__ */ jsx27(ITText, { as: "h3", className: "text-lg font-bold text-slate-700 dark:text-slate-200 mb-1", children: title }),
4863
- description && /* @__PURE__ */ jsx27(ITText, { as: "p", className: "text-sm text-slate-400 dark:text-slate-500 max-w-sm mb-4", children: description }),
4864
- action && /* @__PURE__ */ jsx27("div", { children: action })
5160
+ return /* @__PURE__ */ jsxs24("div", { className: clsx26("flex flex-col items-center justify-center py-16 px-6 text-center", className), children: [
5161
+ /* @__PURE__ */ jsx28("div", { className: "text-slate-300 dark:text-slate-600 mb-4", children: icon }),
5162
+ /* @__PURE__ */ jsx28(ITText, { as: "h3", className: "text-lg font-bold text-slate-700 dark:text-slate-200 mb-1", children: title }),
5163
+ description && /* @__PURE__ */ jsx28(ITText, { as: "p", className: "text-sm text-slate-400 dark:text-slate-500 max-w-sm mb-4", children: description }),
5164
+ action && /* @__PURE__ */ jsx28("div", { children: action })
4865
5165
  ] });
4866
5166
  }
4867
5167
 
4868
5168
  // src/components/atoms/flex/flex.tsx
4869
- import clsx26 from "clsx";
4870
- import { jsx as jsx28 } from "react/jsx-runtime";
5169
+ import clsx27 from "clsx";
5170
+ import { jsx as jsx29 } from "react/jsx-runtime";
4871
5171
  var directionMap = {
4872
5172
  row: "flex-row",
4873
5173
  column: "flex-col",
@@ -4916,10 +5216,10 @@ function ITFlex({
4916
5216
  flexBasis: typeof basis === "number" ? `${basis * 0.25}rem` : basis,
4917
5217
  ...style
4918
5218
  };
4919
- return /* @__PURE__ */ jsx28(
5219
+ return /* @__PURE__ */ jsx29(
4920
5220
  Component,
4921
5221
  {
4922
- className: clsx26(
5222
+ className: clsx27(
4923
5223
  "flex",
4924
5224
  directionMap[direction],
4925
5225
  align && alignMap[align],
@@ -4938,33 +5238,33 @@ function ITFlex({
4938
5238
  import { useMemo as useMemo10 } from "react";
4939
5239
 
4940
5240
  // src/components/organisms/form-builder/formBuilder.context.tsx
4941
- import React6, { createContext as createContext2, useContext as useContext2, useState as useState19 } from "react";
4942
- import { jsx as jsx29 } from "react/jsx-runtime";
5241
+ import React7, { createContext as createContext2, useContext as useContext2, useState as useState20 } from "react";
5242
+ import { jsx as jsx30 } from "react/jsx-runtime";
4943
5243
  var ITFormBuilderContext = createContext2(void 0);
4944
5244
  var ITFormBuilderProvider = ({
4945
5245
  children,
4946
5246
  value
4947
5247
  }) => {
4948
- const [fieldRegistry, setFieldRegistry] = useState19({});
4949
- const registerField = React6.useCallback((name, config2) => {
5248
+ const [fieldRegistry, setFieldRegistry] = useState20({});
5249
+ const registerField = React7.useCallback((name, config2) => {
4950
5250
  setFieldRegistry((prev) => ({ ...prev, [name]: config2 }));
4951
5251
  }, []);
4952
- const unregisterField = React6.useCallback((name) => {
5252
+ const unregisterField = React7.useCallback((name) => {
4953
5253
  setFieldRegistry((prev) => {
4954
5254
  const next = { ...prev };
4955
5255
  delete next[name];
4956
5256
  return next;
4957
5257
  });
4958
5258
  }, []);
4959
- const getFieldConfig = React6.useCallback(
5259
+ const getFieldConfig = React7.useCallback(
4960
5260
  (name) => fieldRegistry[name],
4961
5261
  [fieldRegistry]
4962
5262
  );
4963
- const getAllFieldConfigs = React6.useCallback(
5263
+ const getAllFieldConfigs = React7.useCallback(
4964
5264
  () => Object.values(fieldRegistry),
4965
5265
  [fieldRegistry]
4966
5266
  );
4967
- const contextValue = React6.useMemo(
5267
+ const contextValue = React7.useMemo(
4968
5268
  () => ({
4969
5269
  ...value,
4970
5270
  registerField,
@@ -4974,7 +5274,7 @@ var ITFormBuilderProvider = ({
4974
5274
  }),
4975
5275
  [value, registerField, unregisterField, getFieldConfig, getAllFieldConfigs]
4976
5276
  );
4977
- return /* @__PURE__ */ jsx29(ITFormBuilderContext.Provider, { value: contextValue, children });
5277
+ return /* @__PURE__ */ jsx30(ITFormBuilderContext.Provider, { value: contextValue, children });
4978
5278
  };
4979
5279
  var useITFormBuilderContext = () => {
4980
5280
  const context = useContext2(ITFormBuilderContext);
@@ -4989,11 +5289,11 @@ import { memo, useCallback as useCallback8, useEffect as useEffect12, useMemo as
4989
5289
  import clsx29 from "clsx";
4990
5290
 
4991
5291
  // src/components/molecules/time-picker/timePicker.tsx
4992
- import clsx27 from "clsx";
4993
- import { useEffect as useEffect10, useRef as useRef15, useState as useState20 } from "react";
4994
- import { createPortal as createPortal5 } from "react-dom";
5292
+ import clsx28 from "clsx";
5293
+ import { useEffect as useEffect11, useRef as useRef16, useState as useState21 } from "react";
5294
+ import { createPortal as createPortal6 } from "react-dom";
4995
5295
  import { FaClock } from "react-icons/fa";
4996
- import { jsx as jsx30, jsxs as jsxs24 } from "react/jsx-runtime";
5296
+ import { jsx as jsx31, jsxs as jsxs25 } from "react/jsx-runtime";
4997
5297
  function ITTimePicker({
4998
5298
  name,
4999
5299
  value,
@@ -5010,12 +5310,12 @@ function ITTimePicker({
5010
5310
  variant = "primary",
5011
5311
  color = "primary"
5012
5312
  }) {
5013
- const [isOpen, setIsOpen] = useState20(false);
5014
- const [inputValue, setInputValue] = useState20(value || "");
5015
- const [isValidTime, setIsValidTime] = useState20(true);
5016
- const wrapperRef = useRef15(null);
5017
- const hoursRef = useRef15(null);
5018
- const minutesRef = useRef15(null);
5313
+ const [isOpen, setIsOpen] = useState21(false);
5314
+ const [inputValue, setInputValue] = useState21(value || "");
5315
+ const [isValidTime, setIsValidTime] = useState21(true);
5316
+ const wrapperRef = useRef16(null);
5317
+ const hoursRef = useRef16(null);
5318
+ const minutesRef = useRef16(null);
5019
5319
  const { panelRef: dropdownRef, style: panelStyle } = useFloatingPanel(
5020
5320
  wrapperRef,
5021
5321
  isOpen && !disabled,
@@ -5029,7 +5329,7 @@ function ITTimePicker({
5029
5329
  const isThemeColor = color in theme.colors;
5030
5330
  const highlightColor = isThemeColor ? theme.colors[color][50] : "#f3f4f6";
5031
5331
  const activeColor = isThemeColor ? theme.colors[color][100] : "#e5e7eb";
5032
- useEffect10(() => {
5332
+ useEffect11(() => {
5033
5333
  setInputValue(value || "");
5034
5334
  }, [value]);
5035
5335
  const validateTime = (timeString) => {
@@ -5038,7 +5338,7 @@ function ITTimePicker({
5038
5338
  };
5039
5339
  const currentHour = validateTime(inputValue) ? inputValue.split(":")[0] : null;
5040
5340
  const currentMinute = validateTime(inputValue) ? inputValue.split(":")[1] : null;
5041
- useEffect10(() => {
5341
+ useEffect11(() => {
5042
5342
  if (isOpen) {
5043
5343
  setTimeout(() => {
5044
5344
  if (hoursRef.current && currentHour) {
@@ -5108,8 +5408,8 @@ function ITTimePicker({
5108
5408
  { length: 60 },
5109
5409
  (_, i) => i.toString().padStart(2, "0")
5110
5410
  );
5111
- return /* @__PURE__ */ jsxs24("div", { ref: wrapperRef, className: clsx27("relative w-full", className), children: [
5112
- /* @__PURE__ */ jsx30(
5411
+ return /* @__PURE__ */ jsxs25("div", { ref: wrapperRef, className: clsx28("relative w-full", className), children: [
5412
+ /* @__PURE__ */ jsx31(
5113
5413
  ITInput,
5114
5414
  {
5115
5415
  name,
@@ -5126,7 +5426,7 @@ function ITTimePicker({
5126
5426
  size,
5127
5427
  touched,
5128
5428
  error: !isValidTime ? "Hora inv\xE1lida" : typeof error === "string" ? error : void 0,
5129
- iconRight: /* @__PURE__ */ jsx30(
5429
+ iconRight: /* @__PURE__ */ jsx31(
5130
5430
  FaClock,
5131
5431
  {
5132
5432
  onClick: () => {
@@ -5134,7 +5434,7 @@ function ITTimePicker({
5134
5434
  setIsOpen(!isOpen);
5135
5435
  }
5136
5436
  },
5137
- className: clsx27(
5437
+ className: clsx28(
5138
5438
  "cursor-pointer transition-colors",
5139
5439
  disabled ? "text-slate-400 cursor-not-allowed" : "text-slate-500 dark:text-slate-400 hover:text-slate-700 dark:hover:text-slate-200"
5140
5440
  )
@@ -5142,31 +5442,31 @@ function ITTimePicker({
5142
5442
  )
5143
5443
  }
5144
5444
  ),
5145
- isOpen && !disabled && createPortal5(
5146
- /* @__PURE__ */ jsxs24(
5445
+ isOpen && !disabled && createPortal6(
5446
+ /* @__PURE__ */ jsxs25(
5147
5447
  "div",
5148
5448
  {
5149
5449
  ref: dropdownRef,
5150
5450
  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",
5151
5451
  style: panelStyle,
5152
5452
  children: [
5153
- /* @__PURE__ */ jsxs24("div", { className: "flex bg-secondary-50 border-b border-secondary-100 text-xs font-semibold text-secondary-500 uppercase tracking-wider", children: [
5154
- /* @__PURE__ */ jsx30(ITText, { as: "div", className: "flex-1 text-center py-2 border-r border-secondary-100", children: "Horas" }),
5155
- /* @__PURE__ */ jsx30(ITText, { as: "div", className: "flex-1 text-center py-2", children: "Minutos" })
5453
+ /* @__PURE__ */ jsxs25("div", { className: "flex bg-secondary-50 border-b border-secondary-100 text-xs font-semibold text-secondary-500 uppercase tracking-wider", children: [
5454
+ /* @__PURE__ */ jsx31(ITText, { as: "div", className: "flex-1 text-center py-2 border-r border-secondary-100", children: "Horas" }),
5455
+ /* @__PURE__ */ jsx31(ITText, { as: "div", className: "flex-1 text-center py-2", children: "Minutos" })
5156
5456
  ] }),
5157
- /* @__PURE__ */ jsxs24("div", { className: "flex h-56 relative bg-white", children: [
5158
- /* @__PURE__ */ jsx30(
5457
+ /* @__PURE__ */ jsxs25("div", { className: "flex h-56 relative bg-white", children: [
5458
+ /* @__PURE__ */ jsx31(
5159
5459
  "div",
5160
5460
  {
5161
5461
  ref: hoursRef,
5162
5462
  className: "flex-1 overflow-y-auto no-scrollbar border-r border-secondary-50 scroll-smooth relative",
5163
- children: /* @__PURE__ */ jsx30("div", { className: "py-2", children: hoursList.map((h) => {
5463
+ children: /* @__PURE__ */ jsx31("div", { className: "py-2", children: hoursList.map((h) => {
5164
5464
  const isSelected = currentHour === h;
5165
- return /* @__PURE__ */ jsx30(
5465
+ return /* @__PURE__ */ jsx31(
5166
5466
  "div",
5167
5467
  {
5168
5468
  "data-value": h,
5169
- className: clsx27(
5469
+ className: clsx28(
5170
5470
  "text-center py-2 cursor-pointer transition-all duration-200 text-sm font-medium mx-2 rounded-lg my-1",
5171
5471
  isSelected ? "text-slate-900 shadow-sm" : "text-slate-600 hover:text-slate-900"
5172
5472
  ),
@@ -5189,18 +5489,18 @@ function ITTimePicker({
5189
5489
  }) })
5190
5490
  }
5191
5491
  ),
5192
- /* @__PURE__ */ jsx30(
5492
+ /* @__PURE__ */ jsx31(
5193
5493
  "div",
5194
5494
  {
5195
5495
  ref: minutesRef,
5196
5496
  className: "flex-1 overflow-y-auto no-scrollbar scroll-smooth relative",
5197
- children: /* @__PURE__ */ jsx30("div", { className: "py-2", children: minutesList.map((m) => {
5497
+ children: /* @__PURE__ */ jsx31("div", { className: "py-2", children: minutesList.map((m) => {
5198
5498
  const isSelected = currentMinute === m;
5199
- return /* @__PURE__ */ jsx30(
5499
+ return /* @__PURE__ */ jsx31(
5200
5500
  "div",
5201
5501
  {
5202
5502
  "data-value": m,
5203
- className: clsx27(
5503
+ className: clsx28(
5204
5504
  "text-center py-2 cursor-pointer transition-all duration-200 text-sm font-medium mx-2 rounded-lg my-1",
5205
5505
  isSelected ? "text-slate-900 shadow-sm" : "text-slate-600 hover:text-slate-900"
5206
5506
  ),
@@ -5223,16 +5523,16 @@ function ITTimePicker({
5223
5523
  }) })
5224
5524
  }
5225
5525
  ),
5226
- /* @__PURE__ */ jsx30("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" })
5526
+ /* @__PURE__ */ jsx31("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" })
5227
5527
  ] }),
5228
- /* @__PURE__ */ jsx30("div", { className: "p-3 bg-secondary-50 border-t border-secondary-100 flex justify-end", children: /* @__PURE__ */ jsx30(
5528
+ /* @__PURE__ */ jsx31("div", { className: "p-3 bg-secondary-50 border-t border-secondary-100 flex justify-end", children: /* @__PURE__ */ jsx31(
5229
5529
  ITButton,
5230
5530
  {
5231
5531
  variant: "solid",
5232
5532
  color,
5233
5533
  size: "sm",
5234
5534
  onClick: handleConfirm,
5235
- children: /* @__PURE__ */ jsx30(ITText, { as: "span", children: "Aceptar" })
5535
+ children: /* @__PURE__ */ jsx31(ITText, { as: "span", children: "Aceptar" })
5236
5536
  }
5237
5537
  ) })
5238
5538
  ]
@@ -5243,236 +5543,6 @@ function ITTimePicker({
5243
5543
  ] });
5244
5544
  }
5245
5545
 
5246
- // src/components/molecules/search-select/search-select.tsx
5247
- import { useState as useState21, useEffect as useEffect11, useRef as useRef16, useMemo as useMemo7 } from "react";
5248
- import { createPortal as createPortal6 } from "react-dom";
5249
- import clsx28 from "clsx";
5250
- import { FaSearch as FaSearch2, FaTimes as FaTimes7 } from "react-icons/fa";
5251
- import { jsx as jsx31, jsxs as jsxs25 } from "react/jsx-runtime";
5252
- function ITSearchSelect({
5253
- name,
5254
- options = [],
5255
- label,
5256
- placeholder = "Selecciona una opci\xF3n",
5257
- valueField = "value",
5258
- labelField = "label",
5259
- value,
5260
- onChange,
5261
- onBlur,
5262
- disabled = false,
5263
- className,
5264
- touched,
5265
- required,
5266
- error,
5267
- readOnly = false,
5268
- onSearch,
5269
- isLoading = false,
5270
- noResultsMessage = "No se encontraron resultados",
5271
- size = "md",
5272
- renderOption,
5273
- clearable = true,
5274
- onClear
5275
- }) {
5276
- const [isOpen, setIsOpen] = useState21(false);
5277
- const [searchTerm, setSearchTerm] = useState21("");
5278
- const [isFocused, setIsFocused] = useState21(false);
5279
- const [localTouched, setLocalTouched] = useState21(false);
5280
- const containerRef = useRef16(null);
5281
- const inputWrapperRef = useRef16(null);
5282
- const timeoutRef = useRef16(null);
5283
- const { panelRef, style: panelStyle } = useFloatingPanel(inputWrapperRef, isOpen, {
5284
- estimatedHeight: 260,
5285
- matchWidth: true
5286
- });
5287
- const selectedOption = useMemo7(() => {
5288
- return options.find((opt) => opt[valueField] === value);
5289
- }, [options, value, valueField]);
5290
- useEffect11(() => {
5291
- if (!isFocused) {
5292
- setSearchTerm(selectedOption ? String(selectedOption[labelField]) : "");
5293
- }
5294
- }, [selectedOption, isFocused, labelField]);
5295
- useEffect11(() => {
5296
- function handleClickOutside(event) {
5297
- const target = event.target;
5298
- const inContainer = containerRef.current?.contains(target);
5299
- const inPanel = panelRef.current?.contains(target);
5300
- if (!inContainer && !inPanel) {
5301
- setIsOpen(false);
5302
- }
5303
- }
5304
- document.addEventListener("mousedown", handleClickOutside);
5305
- return () => document.removeEventListener("mousedown", handleClickOutside);
5306
- }, []);
5307
- const selectedLabel = selectedOption ? String(selectedOption[labelField]) : "";
5308
- const filteredOptions = useMemo7(() => {
5309
- if (onSearch) return options;
5310
- if (!searchTerm || !isFocused || searchTerm === selectedLabel) return options;
5311
- return options.filter(
5312
- (opt) => String(opt[labelField]).toLowerCase().includes(searchTerm.toLowerCase())
5313
- );
5314
- }, [options, searchTerm, selectedLabel, onSearch, labelField, isFocused]);
5315
- const handleInputChange = (e) => {
5316
- const query = e.target.value;
5317
- setSearchTerm(query);
5318
- setIsOpen(true);
5319
- if (onSearch) {
5320
- if (timeoutRef.current) clearTimeout(timeoutRef.current);
5321
- timeoutRef.current = setTimeout(() => {
5322
- onSearch(query);
5323
- }, 500);
5324
- }
5325
- };
5326
- const handleSelect = (option) => {
5327
- if (onChange) {
5328
- onChange(option[valueField], option);
5329
- }
5330
- setSearchTerm(String(option[labelField]));
5331
- setIsOpen(false);
5332
- };
5333
- const handleClear = () => {
5334
- setSearchTerm("");
5335
- setIsOpen(true);
5336
- if (onSearch) onSearch("");
5337
- if (value !== void 0 && value !== null && value !== "") {
5338
- onChange?.("", void 0);
5339
- }
5340
- onClear?.();
5341
- };
5342
- const handleFocus = () => {
5343
- if (disabled || readOnly) return;
5344
- setIsFocused(true);
5345
- setIsOpen(true);
5346
- };
5347
- const handleInputBlur = (e) => {
5348
- setTimeout(() => {
5349
- setIsFocused(false);
5350
- setLocalTouched(true);
5351
- onBlur?.(e);
5352
- }, 200);
5353
- };
5354
- const inputTheme = theme.input || {};
5355
- const isTouched = touched !== void 0 ? touched : localTouched;
5356
- const isEmpty = value === void 0 || value === null || String(value).trim() === "";
5357
- const effectiveError = error !== void 0 && error !== false ? error === true ? "Este campo es requerido" : error : required && isEmpty ? "Este campo es requerido" : void 0;
5358
- const hasError = isTouched && !!effectiveError;
5359
- const errorMessage = typeof effectiveError === "string" ? effectiveError : "Este campo es requerido";
5360
- const showClearButton = clearable && !disabled && !readOnly && (searchTerm.length > 0 || !isEmpty);
5361
- const getInputStyle = () => {
5362
- const sizeConfig = inputSizeTokens[size] ?? inputSizeTokens.md;
5363
- const style = {
5364
- backgroundColor: inputTheme.backgroundColor || "#ffffff",
5365
- borderColor: inputTheme.borderColor || "var(--color-secondary-300)",
5366
- borderRadius: inputTheme.borderRadius || "0.5rem",
5367
- padding: sizeConfig.padding,
5368
- fontSize: sizeConfig.fontSize,
5369
- borderWidth: "1px",
5370
- borderStyle: "solid",
5371
- transition: "all 0.2s",
5372
- color: "var(--it-input-text-color, var(--color-secondary-900))",
5373
- width: "100%"
5374
- };
5375
- if (disabled) {
5376
- style.backgroundColor = inputTheme.disabled?.backgroundColor || "var(--color-secondary-100)";
5377
- style.borderColor = inputTheme.disabled?.borderColor || "var(--color-secondary-200)";
5378
- style.opacity = 0.7;
5379
- style.cursor = "not-allowed";
5380
- }
5381
- if (hasError) {
5382
- style.borderColor = inputTheme.error?.borderColor || "red";
5383
- if (isFocused) {
5384
- style.boxShadow = inputTheme.error?.ring;
5385
- }
5386
- } else if (isFocused && !readOnly) {
5387
- style.boxShadow = inputTheme.focus?.ring;
5388
- style.borderColor = inputTheme.focus?.borderColor;
5389
- }
5390
- return style;
5391
- };
5392
- return /* @__PURE__ */ jsxs25("div", { className: clsx28("w-full flex flex-col gap-1.5", className, isOpen && "relative z-30"), ref: containerRef, children: [
5393
- label && /* @__PURE__ */ jsxs25(
5394
- ITText,
5395
- {
5396
- as: "label",
5397
- className: clsx28("text-sm font-medium text-secondary-700 dark:text-slate-300", {
5398
- "text-danger-500": hasError
5399
- }),
5400
- children: [
5401
- /* @__PURE__ */ jsx31(ITText, { as: "span", children: label }),
5402
- required && /* @__PURE__ */ jsx31(ITText, { as: "span", className: "text-danger-500 ml-1", children: "*" })
5403
- ]
5404
- }
5405
- ),
5406
- /* @__PURE__ */ jsxs25("div", { className: "relative", children: [
5407
- /* @__PURE__ */ jsxs25("div", { ref: inputWrapperRef, className: "relative flex items-center", children: [
5408
- /* @__PURE__ */ jsx31(
5409
- "input",
5410
- {
5411
- type: "text",
5412
- name,
5413
- value: searchTerm,
5414
- onChange: handleInputChange,
5415
- onFocus: handleFocus,
5416
- onBlur: handleInputBlur,
5417
- disabled,
5418
- readOnly,
5419
- placeholder,
5420
- className: "outline-none pr-10",
5421
- style: getInputStyle(),
5422
- autoComplete: "off"
5423
- }
5424
- ),
5425
- /* @__PURE__ */ jsxs25("div", { className: "absolute right-3 flex items-center gap-2 text-secondary-400", children: [
5426
- isLoading && /* @__PURE__ */ jsx31("div", { className: "pointer-events-none animate-spin h-4 w-4 border-2 border-primary-500 border-t-transparent rounded-full" }),
5427
- !isLoading && showClearButton && /* @__PURE__ */ jsx31(
5428
- "button",
5429
- {
5430
- type: "button",
5431
- "aria-label": "Limpiar",
5432
- title: "Limpiar",
5433
- onMouseDown: (e) => {
5434
- e.preventDefault();
5435
- handleClear();
5436
- },
5437
- 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",
5438
- children: /* @__PURE__ */ jsx31(FaTimes7, { size: 14 })
5439
- }
5440
- ),
5441
- !isLoading && !showClearButton && /* @__PURE__ */ jsx31(FaSearch2, { size: 14, className: clsx28("pointer-events-none", { "text-primary-500": isFocused }) })
5442
- ] })
5443
- ] }),
5444
- isOpen && createPortal6(
5445
- /* @__PURE__ */ jsx31(
5446
- "div",
5447
- {
5448
- ref: panelRef,
5449
- style: panelStyle,
5450
- 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",
5451
- children: /* @__PURE__ */ jsx31("div", { className: "max-h-60 overflow-y-auto", children: filteredOptions.length > 0 ? filteredOptions.map((option) => {
5452
- const isSelected = value === option[valueField];
5453
- return /* @__PURE__ */ jsx31(
5454
- ITText,
5455
- {
5456
- as: "div",
5457
- onClick: () => handleSelect(option),
5458
- className: clsx28(
5459
- "px-4 py-2 text-sm cursor-pointer transition-colors",
5460
- 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"
5461
- ),
5462
- children: renderOption ? renderOption(option, { isSelected, searchTerm }) : /* @__PURE__ */ jsx31(ITText, { as: "span", children: option[labelField] })
5463
- },
5464
- option[valueField]
5465
- );
5466
- }) : /* @__PURE__ */ jsx31(ITText, { as: "div", className: "px-4 py-6 text-sm text-center text-secondary-500 italic", children: isLoading ? "Cargando..." : noResultsMessage }) })
5467
- }
5468
- ),
5469
- document.body
5470
- )
5471
- ] }),
5472
- hasError && /* @__PURE__ */ jsx31(ITText, { as: "p", className: "text-danger-500 text-xs mt-1", children: errorMessage })
5473
- ] });
5474
- }
5475
-
5476
5546
  // src/components/organisms/form-builder/useFormBuilder.ts
5477
5547
  import { useMemo as useMemo8 } from "react";
5478
5548
  var useFieldRules = (config2, dependentValues) => {
@@ -7905,6 +7975,7 @@ import {
7905
7975
  FaThLarge as FaThLarge2
7906
7976
  } from "react-icons/fa";
7907
7977
  import { MdOutlineSwapVert as MdOutlineSwapVert2 } from "react-icons/md";
7978
+ import { isSameDay as isSameDay2, startOfDay as startOfDay2, endOfDay } from "date-fns";
7908
7979
  import { Fragment as Fragment9, jsx as jsx59, jsxs as jsxs46 } from "react/jsx-runtime";
7909
7980
  function ITTable({
7910
7981
  columns,
@@ -7988,15 +8059,32 @@ function ITTable({
7988
8059
  }, [data, sortConfig, columns]);
7989
8060
  const filteredData = sortedData.filter(
7990
8061
  (row) => columns.every((col) => {
7991
- if (!col.filter || filters[col.key] === void 0 || filters[col.key] === "")
8062
+ const rawFilter = filters[col.key];
8063
+ if (!col.filter || rawFilter === void 0 || rawFilter === "") return true;
8064
+ if (Array.isArray(rawFilter) && rawFilter[0] == null && rawFilter[1] == null) {
7992
8065
  return true;
8066
+ }
7993
8067
  const value = getNestedValue(row, col.key);
7994
- const filterValue = String(filters[col.key]).toLowerCase();
8068
+ if (col.filter === "date" || col.filter === "date-range") {
8069
+ const rowDate = value instanceof Date ? value : new Date(String(value));
8070
+ if (isNaN(rowDate.getTime())) return false;
8071
+ if (col.filter === "date") {
8072
+ return isSameDay2(rowDate, rawFilter);
8073
+ }
8074
+ const [start, end] = rawFilter;
8075
+ if (start && rowDate.getTime() < startOfDay2(start).getTime()) return false;
8076
+ if (end && rowDate.getTime() > endOfDay(end).getTime()) return false;
8077
+ return true;
8078
+ }
8079
+ if (col.filter === "search") {
8080
+ return String(value) === String(rawFilter);
8081
+ }
8082
+ const filterValue = String(rawFilter).toLowerCase();
7995
8083
  switch (col.type) {
7996
8084
  case "number":
7997
8085
  return String(value).includes(filterValue);
7998
8086
  case "boolean":
7999
- return value === filters[col.key];
8087
+ return value === rawFilter;
8000
8088
  case "catalog": {
8001
8089
  if (!col.catalogOptions) return true;
8002
8090
  const catalogItem = col.catalogOptions.data.find(
@@ -8102,6 +8190,75 @@ function ITTable({
8102
8190
  }
8103
8191
  );
8104
8192
  }
8193
+ if (col.filter === "search" && col.catalogOptions) {
8194
+ if (col.catalogOptions.loading) {
8195
+ return /* @__PURE__ */ jsx59(
8196
+ FaSpinner3,
8197
+ {
8198
+ className: "animate-spin",
8199
+ "aria-label": "Cargando opciones",
8200
+ title: "Cargando opciones"
8201
+ }
8202
+ );
8203
+ }
8204
+ if (col.catalogOptions.error) {
8205
+ return /* @__PURE__ */ jsx59(ITText, { as: "span", className: "text-danger-500 text-xs", children: "Error cargando" });
8206
+ }
8207
+ const searchValue = filters[col.key];
8208
+ return /* @__PURE__ */ jsx59(
8209
+ ITSearchSelect,
8210
+ {
8211
+ name: `filter-${col.key}`,
8212
+ options: col.catalogOptions.data.map((item) => ({
8213
+ value: item.id,
8214
+ label: item.name
8215
+ })),
8216
+ value: typeof searchValue === "string" || typeof searchValue === "number" ? searchValue : "",
8217
+ onChange: (value) => handleFilterChange(col.key, value === "" ? void 0 : value),
8218
+ onSearch: col.catalogOptions.onSearch,
8219
+ isLoading: col.catalogOptions.loading,
8220
+ size: "sm",
8221
+ placeholder: "Buscar...",
8222
+ clearable: true,
8223
+ className: "w-full",
8224
+ onBlur: () => {
8225
+ }
8226
+ }
8227
+ );
8228
+ }
8229
+ if (col.filter === "date") {
8230
+ const dateValue = filters[col.key];
8231
+ return /* @__PURE__ */ jsx59(
8232
+ ITDatePicker,
8233
+ {
8234
+ name: `filter-${col.key}`,
8235
+ value: dateValue instanceof Date ? dateValue : void 0,
8236
+ onChange: (e) => handleFilterChange(col.key, e.target.value),
8237
+ minDate: col.dateFilterOptions?.minDate,
8238
+ maxDate: col.dateFilterOptions?.maxDate,
8239
+ size: "sm",
8240
+ placeholder: "dd/mm/aaaa",
8241
+ className: "w-full"
8242
+ }
8243
+ );
8244
+ }
8245
+ if (col.filter === "date-range") {
8246
+ const rangeValue = filters[col.key];
8247
+ return /* @__PURE__ */ jsx59(
8248
+ ITDatePicker,
8249
+ {
8250
+ name: `filter-${col.key}`,
8251
+ range: true,
8252
+ value: Array.isArray(rangeValue) ? rangeValue : void 0,
8253
+ onChange: (e) => handleFilterChange(col.key, e.target.value),
8254
+ minDate: col.dateFilterOptions?.minDate,
8255
+ maxDate: col.dateFilterOptions?.maxDate,
8256
+ size: "sm",
8257
+ placeholder: "dd/mm/aaaa - dd/mm/aaaa",
8258
+ className: "w-full"
8259
+ }
8260
+ );
8261
+ }
8105
8262
  return /* @__PURE__ */ jsx59(
8106
8263
  ITInput,
8107
8264
  {