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