@grafosoft/excel-validator 1.1.2 → 1.1.6

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.
@@ -1,2 +1,2 @@
1
1
  import { ExcelFileProps } from "../types/excelTypes";
2
- export declare const ExcelFile: ({ initData, fileContent, matrix, error, onFileSelected, onReset, validationErrors, onSelectError, hasBalanceDifference, onApplyStringEmptyFilter, onDownloadFilteredExcel, isStringEmptyFilterApplied, hasStringEmptyDuplicateErrors, }: ExcelFileProps) => import("react").JSX.Element;
2
+ export declare const ExcelFile: ({ initData, fileContent, matrix, error, onFileSelected, onReset, validationErrors, onSelectError, onClearSelectedError, hasBalanceDifference, onApplyStringEmptyFilter, onDownloadFilteredExcel, isStringEmptyFilterApplied, hasStringEmptyDuplicateErrors, }: ExcelFileProps) => import("react").JSX.Element;
@@ -6,7 +6,8 @@ const react_1 = require("@heroui/react");
6
6
  const react_2 = require("react");
7
7
  const tb_1 = require("react-icons/tb");
8
8
  const ExcelValidator_1 = require("./ExcelValidator");
9
- const ExcelFile = ({ initData, fileContent, matrix, error, onFileSelected, onReset, validationErrors, onSelectError, hasBalanceDifference = false, onApplyStringEmptyFilter, onDownloadFilteredExcel, isStringEmptyFilterApplied, hasStringEmptyDuplicateErrors, }) => {
9
+ const ThemeSwitcher_1 = require("./ThemeSwitcher");
10
+ const ExcelFile = ({ initData, fileContent, matrix, error, onFileSelected, onReset, validationErrors, onSelectError, onClearSelectedError, hasBalanceDifference = false, onApplyStringEmptyFilter, onDownloadFilteredExcel, isStringEmptyFilterApplied, hasStringEmptyDuplicateErrors, }) => {
10
11
  var _a;
11
12
  const [isVisible, setIsVisible] = (0, react_2.useState)(false);
12
13
  const inputRef = (0, react_2.useRef)(null);
@@ -28,9 +29,12 @@ const ExcelFile = ({ initData, fileContent, matrix, error, onFileSelected, onRes
28
29
  }
29
30
  return (bytes / KB).toFixed(2) + " KB";
30
31
  };
31
- return ((0, jsx_runtime_1.jsxs)("section", { className: "h-full bg-content1 p-4 border-none md:border-l border-default-200", children: [(0, jsx_runtime_1.jsxs)("h2", { className: "text-xl font-semibold text-default-700", children: ["Importa ", initData.title] }), error ? ((0, jsx_runtime_1.jsx)(react_1.Alert, { color: "danger", title: error, className: "mt-3", radius: "sm", hideIconWrapper: true })) : isVisible ? ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)(react_1.Alert, { radius: "sm", hideIconWrapper: true, hideIcon: true, isVisible: isVisible, className: "mt-4", variant: "bordered", onClose: handleReset, children: (0, jsx_runtime_1.jsxs)("div", { className: "flex items-center gap-2 text-default-700", children: [(0, jsx_runtime_1.jsx)(tb_1.TbFile, { size: 28 }), " ", (0, jsx_runtime_1.jsxs)("div", { className: "flex flex-col", children: [(0, jsx_runtime_1.jsx)("p", { className: "text-sm", children: fileContent === null || fileContent === void 0 ? void 0 : fileContent.name }), (0, jsx_runtime_1.jsx)("small", { className: "text-default-500", children: bytesFormat((_a = fileContent === null || fileContent === void 0 ? void 0 : fileContent.size) !== null && _a !== void 0 ? _a : 0) })] })] }) }), initData.type === "accounts" && ((0, jsx_runtime_1.jsxs)("div", { className: "mt-4 space-y-2 flex md:flex-col gap-5 md:gap-0", children: [(0, jsx_runtime_1.jsx)(react_1.Button, { className: "w-full border-1", color: "warning", variant: "bordered", radius: "sm", startContent: (0, jsx_runtime_1.jsx)(tb_1.TbFilter, { size: 18 }), onPress: onApplyStringEmptyFilter, isDisabled: !hasStringEmptyDuplicateErrors || isStringEmptyFilterApplied, children: isStringEmptyFilterApplied
32
+ return ((0, jsx_runtime_1.jsxs)("section", { className: "h-full bg-content1 p-4 border-none md:border-l border-default-200", children: [(0, jsx_runtime_1.jsx)(ThemeSwitcher_1.ThemeSwitcher, {}), (0, jsx_runtime_1.jsxs)("h2", { className: "text-xl font-semibold text-default-700", children: ["Importa ", initData.title] }), error ? ((0, jsx_runtime_1.jsx)(react_1.Alert, { color: "danger", title: error, className: "mt-3", radius: "sm", hideIconWrapper: true })) : isVisible ? ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)(react_1.Alert, { radius: "sm", hideIconWrapper: true, hideIcon: true, isVisible: isVisible, className: "mt-4 max-w-full overflow-hidden", classNames: {
33
+ mainWrapper: "min-w-0 flex-1 overflow-hidden",
34
+ closeButton: "shrink-0",
35
+ }, variant: "bordered", onClose: handleReset, children: (0, jsx_runtime_1.jsxs)("div", { className: "flex min-w-0 max-w-full items-center gap-2 overflow-hidden text-default-700", children: [(0, jsx_runtime_1.jsx)(tb_1.TbFile, { className: "shrink-0", size: 28 }), " ", (0, jsx_runtime_1.jsxs)("div", { className: "flex min-w-0 flex-1 flex-col overflow-hidden", children: [(0, jsx_runtime_1.jsx)("p", { className: "max-w-full truncate text-sm", title: fileContent === null || fileContent === void 0 ? void 0 : fileContent.name, children: fileContent === null || fileContent === void 0 ? void 0 : fileContent.name }), (0, jsx_runtime_1.jsx)("small", { className: "text-default-500", children: bytesFormat((_a = fileContent === null || fileContent === void 0 ? void 0 : fileContent.size) !== null && _a !== void 0 ? _a : 0) })] })] }) }), initData.type === "accounts" && ((0, jsx_runtime_1.jsxs)("div", { className: "mt-4 space-y-2 flex md:flex-col gap-5 md:gap-0", children: [(0, jsx_runtime_1.jsx)(react_1.Button, { className: "w-full border-1", color: "warning", variant: "bordered", radius: "sm", startContent: (0, jsx_runtime_1.jsx)(tb_1.TbFilter, { size: 18 }), onPress: onApplyStringEmptyFilter, isDisabled: !hasStringEmptyDuplicateErrors || isStringEmptyFilterApplied, children: isStringEmptyFilterApplied
32
36
  ? "Filtro aplicado"
33
- : "Filtrar cuentas ya registradas" }), (0, jsx_runtime_1.jsx)(react_1.Button, { className: "w-full border-1", color: "success", variant: "bordered", radius: "sm", startContent: (0, jsx_runtime_1.jsx)(tb_1.TbDownload, { size: 18 }), onPress: onDownloadFilteredExcel, isDisabled: !isStringEmptyFilterApplied || !hasStringEmptyDuplicateErrors, children: "Descargar Nuevo Excel" })] })), (0, jsx_runtime_1.jsx)(ExcelValidator_1.ExcelValidator, { initData: initData, fileContent: fileContent, matrix: matrix, validationErrors: validationErrors, onSelectError: onSelectError, hasBalanceDifference: hasBalanceDifference })] })) : ((0, jsx_runtime_1.jsx)("label", { className: "mt-4 flex cursor-pointer items-center justify-center rounded-lg border border-dashed border-default-300 px-4 py-8 text-sm font-medium text-default-600 transition hover:border-primary hover:text-primary", htmlFor: "excel-upload", children: (0, jsx_runtime_1.jsxs)("div", { className: "text-center flex flex-col items-center gap-2", children: [(0, jsx_runtime_1.jsx)(tb_1.TbUpload, { size: 28 }), (0, jsx_runtime_1.jsx)("p", { className: "font-semibold text-lg", children: "Seleccionar plantilla" }), (0, jsx_runtime_1.jsx)("small", { className: "text-default-500", children: "Adjunta un archivo .xlsx o .xls para validar y previsualizar." })] }) })), (0, jsx_runtime_1.jsx)("input", { id: "excel-upload", ref: inputRef, className: "hidden", type: "file", accept: ".xlsx,.xls", onChange: (event) => {
37
+ : "Quitar cuentas ya registradas" }), (0, jsx_runtime_1.jsx)(react_1.Button, { className: "w-full border-1", color: "success", variant: "bordered", radius: "sm", startContent: (0, jsx_runtime_1.jsx)(tb_1.TbDownload, { size: 18 }), onPress: onDownloadFilteredExcel, isDisabled: !isStringEmptyFilterApplied || !hasStringEmptyDuplicateErrors, children: "Descargar Nuevo Excel" })] })), (0, jsx_runtime_1.jsx)(ExcelValidator_1.ExcelValidator, { initData: initData, fileContent: fileContent, matrix: matrix, validationErrors: validationErrors, onSelectError: onSelectError, onClearSelectedError: onClearSelectedError, hasBalanceDifference: hasBalanceDifference })] })) : ((0, jsx_runtime_1.jsx)("label", { className: "mt-4 flex cursor-pointer items-center justify-center rounded-lg border border-dashed border-default-300 px-4 py-8 text-sm font-medium text-default-600 transition hover:border-primary hover:text-primary", htmlFor: "excel-upload", children: (0, jsx_runtime_1.jsxs)("div", { className: "text-center flex flex-col items-center gap-2", children: [(0, jsx_runtime_1.jsx)(tb_1.TbUpload, { size: 28 }), (0, jsx_runtime_1.jsx)("p", { className: "font-semibold text-lg", children: "Seleccionar plantilla" }), (0, jsx_runtime_1.jsx)("small", { className: "text-default-500", children: "Adjunta un archivo .xlsx o .xls para validar y previsualizar." })] }) })), (0, jsx_runtime_1.jsx)("input", { id: "excel-upload", ref: inputRef, className: "hidden", type: "file", accept: ".xlsx,.xls", onChange: (event) => {
34
38
  void onFileSelected(event);
35
39
  setIsVisible(true);
36
40
  } })] }));
@@ -574,6 +574,9 @@ function ExcelLayout({ initData, jsonValidator, isBalances = false, }) {
574
574
  token: Date.now(),
575
575
  });
576
576
  };
577
+ const handleClearSelectedError = () => {
578
+ setFocusTarget(null);
579
+ };
577
580
  const mainRef = (0, react_1.useRef)(null);
578
581
  const handleReset = () => {
579
582
  setFileContent(undefined);
@@ -583,5 +586,5 @@ function ExcelLayout({ initData, jsonValidator, isBalances = false, }) {
583
586
  setFocusTarget(null);
584
587
  setIsStringEmptyFilterApplied(false);
585
588
  };
586
- return ((0, jsx_runtime_1.jsxs)("main", { ref: mainRef, className: "grid grid-cols-1 h-full grid-rows-2 md:grid-rows-1 md:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 overflow-hidden", children: [(0, jsx_runtime_1.jsx)("div", { className: "space-y-4 col-span-1 order-2 ", children: (0, jsx_runtime_1.jsx)(ExcelFile_1.ExcelFile, { initData: initData, fileContent: fileContent, matrix: matrix, error: error, onFileSelected: handleFileSelected, onReset: handleReset, validationErrors: validationErrorsForPanel, onSelectError: handleSelectError, hasBalanceDifference: hasBalanceDifference, onApplyStringEmptyFilter: handleApplyStringEmptyFilter, onDownloadFilteredExcel: handleDownloadFilteredExcel, isStringEmptyFilterApplied: isStringEmptyFilterApplied, hasStringEmptyDuplicateErrors: hasStringEmptyDuplicateErrors }) }), (0, jsx_runtime_1.jsx)("div", { className: "col-span-1 lg:col-span-2 xl:col-span-3", children: (0, jsx_runtime_1.jsx)(ExcelPreview_1.ExcelPreview, { initData: initData, fileContent: fileContent, matrix: matrix, error: error, validationErrors: validationErrors, focusTarget: focusTarget, currentPage: currentPage, onPageChange: setCurrentPage, isBalances: isBalances, hiddenFilteredRowIndexes: isStringEmptyFilterApplied ? stringEmptyDuplicateRowIndexes : [] }) })] }));
589
+ return ((0, jsx_runtime_1.jsxs)("main", { ref: mainRef, className: "grid grid-cols-1 h-full grid-rows-2 md:grid-rows-1 md:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 overflow-hidden", children: [(0, jsx_runtime_1.jsx)("div", { className: "space-y-4 col-span-1 order-2 ", children: (0, jsx_runtime_1.jsx)(ExcelFile_1.ExcelFile, { initData: initData, fileContent: fileContent, matrix: matrix, error: error, onFileSelected: handleFileSelected, onReset: handleReset, validationErrors: validationErrorsForPanel, onSelectError: handleSelectError, onClearSelectedError: handleClearSelectedError, hasBalanceDifference: hasBalanceDifference, onApplyStringEmptyFilter: handleApplyStringEmptyFilter, onDownloadFilteredExcel: handleDownloadFilteredExcel, isStringEmptyFilterApplied: isStringEmptyFilterApplied, hasStringEmptyDuplicateErrors: hasStringEmptyDuplicateErrors }) }), (0, jsx_runtime_1.jsx)("div", { className: "col-span-1 lg:col-span-2 xl:col-span-3", children: (0, jsx_runtime_1.jsx)(ExcelPreview_1.ExcelPreview, { initData: initData, fileContent: fileContent, matrix: matrix, error: error, validationErrors: validationErrors, focusTarget: focusTarget, currentPage: currentPage, onPageChange: setCurrentPage, isBalances: isBalances, hiddenFilteredRowIndexes: isStringEmptyFilterApplied ? stringEmptyDuplicateRowIndexes : [] }) })] }));
587
590
  }
@@ -11,6 +11,7 @@ const ExcelPreview = ({ initData, fileContent, matrix, error, validationErrors,
11
11
  var _a;
12
12
  const rowsPerPage = 30;
13
13
  const cellRefs = (0, react_2.useRef)({});
14
+ const [selectedErrorCellKey, setSelectedErrorCellKey] = (0, react_2.useState)(null);
14
15
  const maxColumns = (0, react_2.useMemo)(() => matrix.reduce((max, row) => Math.max(max, row.length), 0), [matrix]);
15
16
  const tableHeaders = (_a = matrix[0]) !== null && _a !== void 0 ? _a : [];
16
17
  const hiddenRowIndexesSet = (0, react_2.useMemo)(() => new Set(hiddenFilteredRowIndexes), [hiddenFilteredRowIndexes]);
@@ -29,12 +30,15 @@ const ExcelPreview = ({ initData, fileContent, matrix, error, validationErrors,
29
30
  const endIndex = startIndex + rowsPerPage;
30
31
  const dataRows = allDataRows.slice(startIndex, endIndex);
31
32
  const errorMap = (0, react_2.useMemo)(() => {
32
- const map = new Set();
33
+ const map = new Map();
33
34
  validationErrors.forEach((item) => {
34
- map.add(`${item.filteredRowIndex}-${item.column - 1}`);
35
+ map.set(`${item.filteredRowIndex}-${item.column - 1}`, item);
35
36
  });
36
37
  return map;
37
38
  }, [validationErrors]);
39
+ const activeSelectedErrorCellKey = selectedErrorCellKey && errorMap.has(selectedErrorCellKey)
40
+ ? selectedErrorCellKey
41
+ : null;
38
42
  (0, react_2.useEffect)(() => {
39
43
  if (!focusTarget) {
40
44
  return;
@@ -57,19 +61,27 @@ const ExcelPreview = ({ initData, fileContent, matrix, error, validationErrors,
57
61
  targetCell.focus();
58
62
  });
59
63
  }, [focusTarget, effectivePage]);
60
- return ((0, jsx_runtime_1.jsxs)("section", { className: "h-full border-none md:border-r border-default-200 px-4 py-2 flex flex-col overflow-hidden", children: [!fileContent ? ((0, jsx_runtime_1.jsx)(react_1.Alert, { color: "primary", title: `Al importar ${initData.title} verás una previsualización de su contenido.`, className: "my-3 max-h-[70px]", radius: "sm", hideIconWrapper: true, variant: "faded" })) : null, fileContent && matrix.length === 0 && !error ? ((0, jsx_runtime_1.jsx)(react_1.Alert, { color: "danger", title: `No se encontraron datos en el archivo seleccionado.`, className: "my-3", radius: "sm", hideIconWrapper: true, variant: "faded" })) : null, fileContent && matrix.length > 0 ? ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)("div", { className: "mt-4 min-h-0 flex-1 max-w-full border-r border-b border-default-200 overflow-x-auto overflow-y-auto", children: (0, jsx_runtime_1.jsxs)("table", { className: "min-w-max w-full text-sm", children: [(0, jsx_runtime_1.jsx)("thead", { className: "sticky top-0 bg-default-100", children: (0, jsx_runtime_1.jsx)("tr", { children: Array.from({ length: maxColumns }).map((_, columnIndex) => ((0, jsx_runtime_1.jsx)("th", { className: "border-x border-t border-default-200 p-3 font-semibold text-default-700", children: tableHeaders[columnIndex] ||
61
- `Columna ${columnIndex + 1}` }, `header-${columnIndex}`))) }) }), (0, jsx_runtime_1.jsx)("tbody", { className: "bg-content1", children: dataRows.map((row, rowIndex) => ((0, jsx_runtime_1.jsx)("tr", { children: Array.from({ length: maxColumns }).map((_, columnIndex) => (() => {
64
+ return ((0, jsx_runtime_1.jsxs)("section", { className: "h-full border-none bg-white px-4 py-2 text-gray-800 md:border-r md:border-gray-200 dark:bg-zinc-950 dark:text-zinc-100 dark:md:border-zinc-800 flex flex-col overflow-hidden", children: [!fileContent ? ((0, jsx_runtime_1.jsx)(react_1.Alert, { color: "primary", title: `Al importar ${initData.title} verás una previsualización de su contenido.`, className: "my-3 max-h-[70px]", radius: "sm", hideIconWrapper: true, variant: "faded" })) : null, fileContent && matrix.length === 0 && !error ? ((0, jsx_runtime_1.jsx)(react_1.Alert, { color: "danger", title: `No se encontraron datos en el archivo seleccionado.`, className: "my-3", radius: "sm", hideIconWrapper: true, variant: "faded" })) : null, fileContent && matrix.length > 0 ? ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)("div", { className: "mt-4 min-h-0 flex-1 max-w-full border-r border-b border-gray-200 dark:border-zinc-700 overflow-x-auto overflow-y-auto", children: (0, jsx_runtime_1.jsxs)("table", { className: "min-w-max w-full text-sm", children: [(0, jsx_runtime_1.jsx)("thead", { className: "sticky top-0 z-10 bg-gray-100 dark:bg-zinc-900", children: (0, jsx_runtime_1.jsx)("tr", { children: Array.from({ length: maxColumns }).map((_, columnIndex) => ((0, jsx_runtime_1.jsx)("th", { className: "border-x border-t border-gray-200 p-3 font-semibold text-gray-700 dark:border-zinc-700 dark:text-zinc-100", children: tableHeaders[columnIndex] ||
65
+ `Columna ${columnIndex + 1}` }, `header-${columnIndex}`))) }) }), (0, jsx_runtime_1.jsx)("tbody", { className: "bg-white dark:bg-zinc-950", children: dataRows.map((row, rowIndex) => ((0, jsx_runtime_1.jsx)("tr", { children: Array.from({ length: maxColumns }).map((_, columnIndex) => (() => {
62
66
  var _a, _b;
63
67
  const originalFilteredRowIndex = row.originalFilteredRowIndex;
64
68
  const key = `${originalFilteredRowIndex}-${columnIndex}`;
65
- const hasError = errorMap.has(key);
69
+ const cellError = errorMap.get(key);
70
+ const hasError = Boolean(cellError);
66
71
  const isFocusedTarget = (focusTarget === null || focusTarget === void 0 ? void 0 : focusTarget.filteredRowIndex) ===
67
72
  originalFilteredRowIndex &&
68
73
  (focusTarget === null || focusTarget === void 0 ? void 0 : focusTarget.columnIndex) === columnIndex;
74
+ const isSelectedErrorCell = activeSelectedErrorCellKey === key;
75
+ const tooltipPlacement = columnIndex === maxColumns - 1 ? "left" : "right";
69
76
  return ((0, jsx_runtime_1.jsx)("td", { ref: (element) => {
70
77
  cellRefs.current[key] = element;
71
- }, tabIndex: -1, className: `border border-default-200 p-3 align-top whitespace-nowrap outline-none transition-all duration-200 ease-in-out text-default-700
72
- ${isFocusedTarget ? "ring-[1.7px] ring-danger ring-inset" : ""}`, children: hasError ? ((0, jsx_runtime_1.jsxs)("div", { className: "flex justify-between", children: [(0, jsx_runtime_1.jsx)("p", { children: (_a = row.row[columnIndex]) !== null && _a !== void 0 ? _a : "" }), (0, jsx_runtime_1.jsx)(tb_1.TbAlertCircle, { color: "red", size: 20 })] })) : ((0, jsx_runtime_1.jsx)("p", { children: (_b = row.row[columnIndex]) !== null && _b !== void 0 ? _b : "" })) }, `cell-${rowIndex}-${columnIndex}`));
73
- })()) }, `row-${rowIndex}`))) })] }) }), totalRecords > rowsPerPage ? ((0, jsx_runtime_1.jsxs)("div", { className: "mt-4 flex items-center justify-between gap-3", children: [(0, jsx_runtime_1.jsxs)("p", { className: "text-sm text-default-600", children: ["Mostrando ", startIndex + 1, "-", Math.min(endIndex, totalRecords), " de", " ", totalRecords, " registros"] }), (0, jsx_runtime_1.jsxs)("div", { className: "flex items-center gap-2", children: [(0, jsx_runtime_1.jsx)(react_1.Button, { size: "sm", className: "text-sm border border-default-300 disabled:border-default-200 disabled:bg-default-100 disabled:text-default-500 dark:border-default-400 dark:text-default-700", variant: "bordered", disabled: effectivePage === 1, onPress: () => onPageChange(Math.max(1, effectivePage - 1)), isIconOnly: true, children: (0, jsx_runtime_1.jsx)(pi_1.PiCaretLeftBold, { size: 16 }) }), (0, jsx_runtime_1.jsxs)("span", { className: "text-sm text-default-700 mx-1", children: ["Pagina ", effectivePage, " de ", totalPages] }), (0, jsx_runtime_1.jsx)(react_1.Button, { size: "sm", className: "text-sm border border-default-300 disabled:border-default-200 disabled:bg-default-100 disabled:text-default-500 dark:border-default-400 dark:text-default-700", variant: "bordered", disabled: effectivePage === totalPages, onPress: () => onPageChange(Math.min(totalPages, effectivePage + 1)), isIconOnly: true, children: (0, jsx_runtime_1.jsx)(pi_1.PiCaretRightBold, { size: 16 }) })] })] })) : null, isBalances ? ((0, jsx_runtime_1.jsx)(BalanceTotals_1.BalanceTotals, { headers: tableHeaders, rows: allDataRows.map((entry) => entry.row) })) : null] })) : null] }));
78
+ }, tabIndex: -1, onClick: () => {
79
+ setSelectedErrorCellKey(hasError ? key : null);
80
+ }, className: `border border-gray-200 bg-white p-3 align-top whitespace-nowrap text-gray-700 outline-none transition-all duration-200 ease-in-out dark:border-zinc-700 dark:bg-zinc-950 dark:text-zinc-200
81
+ ${isFocusedTarget || isSelectedErrorCell ? "ring-[1.7px] ring-danger ring-inset" : ""}`, children: cellError ? ((0, jsx_runtime_1.jsx)(react_1.Tooltip, { content: cellError.message, isOpen: isSelectedErrorCell, placement: tooltipPlacement, color: "danger", radius: "sm", showArrow: true, children: (0, jsx_runtime_1.jsxs)("button", { type: "button", className: "flex w-full min-w-0 items-center justify-between gap-3 text-left text-gray-700 outline-none dark:text-zinc-200", onClick: (event) => {
82
+ event.stopPropagation();
83
+ setSelectedErrorCellKey(key);
84
+ }, children: [(0, jsx_runtime_1.jsx)("span", { children: (_a = row.row[columnIndex]) !== null && _a !== void 0 ? _a : "" }), (0, jsx_runtime_1.jsx)(tb_1.TbAlertCircle, { className: "shrink-0 text-danger", size: 20 })] }) })) : ((0, jsx_runtime_1.jsx)("p", { children: (_b = row.row[columnIndex]) !== null && _b !== void 0 ? _b : "" })) }, `cell-${rowIndex}-${columnIndex}`));
85
+ })()) }, `row-${rowIndex}`))) })] }) }), totalRecords > rowsPerPage ? ((0, jsx_runtime_1.jsxs)("div", { className: "mt-4 flex items-center justify-between gap-3", children: [(0, jsx_runtime_1.jsxs)("p", { className: "text-sm text-gray-600 dark:text-zinc-400", children: ["Mostrando ", startIndex + 1, "-", Math.min(endIndex, totalRecords), " de", " ", totalRecords, " registros"] }), (0, jsx_runtime_1.jsxs)("div", { className: "flex items-center gap-2", children: [(0, jsx_runtime_1.jsx)(react_1.Button, { size: "sm", className: "border border-gray-300 text-sm text-gray-700 disabled:border-gray-200 disabled:bg-gray-100 disabled:text-gray-400 dark:border-zinc-600 dark:text-zinc-200 dark:disabled:border-zinc-800 dark:disabled:bg-zinc-900 dark:disabled:text-zinc-600", variant: "bordered", disabled: effectivePage === 1, onPress: () => onPageChange(Math.max(1, effectivePage - 1)), isIconOnly: true, children: (0, jsx_runtime_1.jsx)(pi_1.PiCaretLeftBold, { size: 16 }) }), (0, jsx_runtime_1.jsxs)("span", { className: "mx-1 text-sm text-gray-700 dark:text-zinc-200", children: ["Pagina ", effectivePage, " de ", totalPages] }), (0, jsx_runtime_1.jsx)(react_1.Button, { size: "sm", className: "border border-gray-300 text-sm text-gray-700 disabled:border-gray-200 disabled:bg-gray-100 disabled:text-gray-400 dark:border-zinc-600 dark:text-zinc-200 dark:disabled:border-zinc-800 dark:disabled:bg-zinc-900 dark:disabled:text-zinc-600", variant: "bordered", disabled: effectivePage === totalPages, onPress: () => onPageChange(Math.min(totalPages, effectivePage + 1)), isIconOnly: true, children: (0, jsx_runtime_1.jsx)(pi_1.PiCaretRightBold, { size: 16 }) })] })] })) : null, isBalances ? ((0, jsx_runtime_1.jsx)(BalanceTotals_1.BalanceTotals, { headers: tableHeaders, rows: allDataRows.map((entry) => entry.row) })) : null] })) : null] }));
74
86
  };
75
87
  exports.ExcelPreview = ExcelPreview;
@@ -1,2 +1,2 @@
1
1
  import { ExcelValidatorProps } from "../types/excelTypes";
2
- export declare const ExcelValidator: ({ initData, fileContent, matrix, validationErrors, onSelectError, hasBalanceDifference, }: ExcelValidatorProps) => import("react").JSX.Element | null;
2
+ export declare const ExcelValidator: ({ initData, fileContent, matrix, validationErrors, onSelectError, onClearSelectedError, hasBalanceDifference, }: ExcelValidatorProps) => import("react").JSX.Element | null;
@@ -5,7 +5,7 @@ const jsx_runtime_1 = require("react/jsx-runtime");
5
5
  const react_1 = require("@heroui/react");
6
6
  const react_2 = require("react");
7
7
  const tb_1 = require("react-icons/tb");
8
- const ExcelValidator = ({ initData, fileContent, matrix, validationErrors, onSelectError, hasBalanceDifference = false, }) => {
8
+ const ExcelValidator = ({ initData, fileContent, matrix, validationErrors, onSelectError, onClearSelectedError, hasBalanceDifference = false, }) => {
9
9
  const [selectedErrorId, setSelectedErrorId] = (0, react_2.useState)(null);
10
10
  const [isUploadingTemplate, setIsUploadingTemplate] = (0, react_2.useState)(false);
11
11
  const [uploadMessage, setUploadMessage] = (0, react_2.useState)(null);
@@ -77,6 +77,11 @@ const ExcelValidator = ({ initData, fileContent, matrix, validationErrors, onSel
77
77
  groups[key].push(error);
78
78
  return groups;
79
79
  }, {})).map(([columnName, errors]) => ((0, jsx_runtime_1.jsx)(react_1.AccordionItem, { textValue: columnName, title: (0, jsx_runtime_1.jsxs)("div", { className: "flex justify-between items-center", children: [(0, jsx_runtime_1.jsx)("p", { className: "text-default-700", children: `Columna ${columnName}` }), (0, jsx_runtime_1.jsx)(react_1.Chip, { color: "danger", variant: "faded", size: "sm", startContent: (0, jsx_runtime_1.jsx)(tb_1.TbAlertCircle, { size: 18 }), children: (0, jsx_runtime_1.jsx)("p", { className: "p-1 text-default-600", children: errors.length }) })] }), children: errors.map((error) => ((0, jsx_runtime_1.jsx)("button", { className: "w-full text-left mt-2", onClick: () => {
80
+ if (selectedErrorId === error.id) {
81
+ setSelectedErrorId(null);
82
+ onClearSelectedError();
83
+ return;
84
+ }
80
85
  setSelectedErrorId(error.id);
81
86
  onSelectError(error);
82
87
  }, children: (0, jsx_runtime_1.jsx)(react_1.Alert, { color: "danger", title: error.message, hideIcon: true, startContent: (0, jsx_runtime_1.jsx)(tb_1.TbAlertCircle, { size: 30 }), classNames: {
@@ -25,6 +25,7 @@ export type ExcelFileProps = {
25
25
  onReset: () => void;
26
26
  validationErrors: ValidationError[];
27
27
  onSelectError: (error: ValidationError) => void;
28
+ onClearSelectedError: () => void;
28
29
  hasBalanceDifference?: boolean;
29
30
  onApplyStringEmptyFilter: () => void;
30
31
  onDownloadFilteredExcel: () => void;
@@ -37,6 +38,7 @@ export type ExcelValidatorProps = {
37
38
  matrix: ExcelMatrix;
38
39
  validationErrors: ValidationError[];
39
40
  onSelectError: (error: ValidationError) => void;
41
+ onClearSelectedError: () => void;
40
42
  hasBalanceDifference?: boolean;
41
43
  };
42
44
  export type ExcelPreviewProps = {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@grafosoft/excel-validator",
3
- "version": "1.1.2",
3
+ "version": "1.1.6",
4
4
  "description": "React component to validate Excel files against configurable JSON rules.",
5
5
  "license": "MIT",
6
6
  "main": "dist/index.js",