frontend-plus-react 0.4.1 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  // src/components/grid/GenericDataGrid.tsx
2
- import { useState as useState12, useEffect as useEffect5, useCallback as useCallback11, useContext as useContext4, useMemo as useMemo9, useRef as useRef6 } from "react";
2
+ import { useState as useState15, useEffect as useEffect6, useCallback as useCallback11, useContext as useContext4, useMemo as useMemo10, useRef as useRef7 } from "react";
3
3
  import { DataGrid } from "react-data-grid";
4
4
  import "react-data-grid/lib/styles.css";
5
5
 
@@ -317,7 +317,7 @@ var useApiCallWithoutSnackbar = () => {
317
317
  };
318
318
 
319
319
  // src/components/grid/GenericDataGrid.tsx
320
- import { CircularProgress as CircularProgress4, Typography as Typography8, Box as Box12, Alert as Alert2, useTheme as useTheme4, Dialog as Dialog4 } from "@mui/material";
320
+ import { CircularProgress as CircularProgress4, Typography as Typography10, Box as Box12, Alert as Alert2, useTheme as useTheme4, Dialog as Dialog4 } from "@mui/material";
321
321
 
322
322
  // src/store/index.ts
323
323
  import { configureStore, combineReducers } from "@reduxjs/toolkit";
@@ -1046,6 +1046,16 @@ var getBestTypedValue = (valor, typer) => {
1046
1046
  }
1047
1047
  return BestControls.text.getTypedValue(value, typer);
1048
1048
  };
1049
+ var tiparEntrada = (valor, typer) => {
1050
+ const entrada = typeof valor === "string" && valor.trim() === "" && typer.typeName !== "text" ? "" : valor;
1051
+ const tipado = getBestTypedValue(entrada, typer);
1052
+ if (tipado === null && typeof entrada === "string" && entrada !== "") {
1053
+ throw new Error(`\xAB${valor}\xBB no es un valor v\xE1lido para este campo (${typer.typeName})`);
1054
+ }
1055
+ return tipado;
1056
+ };
1057
+ var caracterRechazado = (caracter, typer) => caracter.length === 1 && typer.rejectedChar(caracter);
1058
+ var textoPegadoRechazado = (texto, typer) => Array.from(texto).some((caracter) => typer.rejectedChar(caracter));
1049
1059
 
1050
1060
  // src/hooks/grid/useGridDataView.ts
1051
1061
  var MAXIMO_FILAS_EDICION_PUNTUAL = 3;
@@ -1087,6 +1097,22 @@ var useGridDataView = ({ tableData, tableDefinition }) => {
1087
1097
  return !prev;
1088
1098
  });
1089
1099
  }, []);
1100
+ const aplicarFiltrosIniciales = useCallback4((condiciones2, definicion) => {
1101
+ const iniciales = {};
1102
+ condiciones2.forEach(({ column, operator, value }) => {
1103
+ const fieldDef = definicion.fields.find((f) => f.name === column);
1104
+ let texto = value === null || value === void 0 ? "" : String(value);
1105
+ if (fieldDef && value !== null && value !== void 0) {
1106
+ try {
1107
+ texto = typeStore2.typerFrom(fieldDef).toLocalString(value);
1108
+ } catch (e) {
1109
+ }
1110
+ }
1111
+ iniciales[column] = { operator, value: texto };
1112
+ });
1113
+ setFilters(iniciales);
1114
+ setIsFilterRowVisible(true);
1115
+ }, []);
1090
1116
  const vistaAnteriorRef = useRef(null);
1091
1117
  const filteredRows = useMemo(() => {
1092
1118
  const anterior = vistaAnteriorRef.current;
@@ -1244,6 +1270,7 @@ var useGridDataView = ({ tableData, tableDefinition }) => {
1244
1270
  setFilters,
1245
1271
  isFilterRowVisible,
1246
1272
  toggleFilterVisibility,
1273
+ aplicarFiltrosIniciales,
1247
1274
  // Data
1248
1275
  filteredRows,
1249
1276
  summaryData,
@@ -1393,10 +1420,155 @@ function CeldaDetalle({ fila }) {
1393
1420
  return /* @__PURE__ */ jsx5(Fragment2, { children: renderDetalle(fila) });
1394
1421
  }
1395
1422
 
1423
+ // src/hooks/grid/teclasDeCelda.ts
1424
+ function direccionDeSalida(tecla, cursor, teclaAnterior) {
1425
+ if (tecla.ctrlKey || tecla.altKey || tecla.metaKey) return null;
1426
+ const conShift = !!tecla.shiftKey;
1427
+ switch (tecla.key) {
1428
+ case "Enter":
1429
+ return conShift ? null : "siguiente";
1430
+ case "Tab":
1431
+ return conShift ? "anterior" : "siguiente";
1432
+ case "ArrowUp":
1433
+ return conShift ? null : "arriba";
1434
+ case "ArrowDown":
1435
+ return conShift ? null : "abajo";
1436
+ case "ArrowLeft":
1437
+ return !conShift && (cursor.vacio || cursor.alPrincipio) ? "izquierda" : null;
1438
+ case "ArrowRight":
1439
+ return !conShift && (cursor.vacio || teclaAnterior === "ArrowRight" && cursor.alFinal) ? "derecha" : null;
1440
+ default:
1441
+ return null;
1442
+ }
1443
+ }
1444
+ function posicionDelCursor(elemento) {
1445
+ if (elemento instanceof HTMLInputElement || elemento instanceof HTMLTextAreaElement) {
1446
+ const fin = elemento.selectionEnd ?? elemento.value.length;
1447
+ return { vacio: elemento.value === "", alPrincipio: fin === 0, alFinal: fin === elemento.value.length };
1448
+ }
1449
+ return { vacio: true, alPrincipio: true, alFinal: true };
1450
+ }
1451
+
1452
+ // src/utils/fixedFields.ts
1453
+ function fijaElValor(fixedField) {
1454
+ return !fixedField.range && fixedField.until === void 0;
1455
+ }
1456
+ function valorFijoDe(fixedFields, columna) {
1457
+ return fixedFields?.find((f) => f.fieldName === columna && fijaElValor(f));
1458
+ }
1459
+ function columnaOcultaPorFixedField(fixedFields, columna) {
1460
+ const fijo = valorFijoDe(fixedFields, columna);
1461
+ return fijo !== void 0 && !fijo.show;
1462
+ }
1463
+
1464
+ // src/utils/referencias.ts
1465
+ var esParDeCampos = (par) => typeof par === "object" && par !== null && "source" in par && "target" in par && typeof par.source === "string" && typeof par.target === "string";
1466
+ var esCampoConReferencia = (campo) => typeof campo.references === "string" && campo.references !== "" && (!("referencesFields" in campo) || campo.referencesFields === void 0 || Array.isArray(campo.referencesFields) && campo.referencesFields.every(esParDeCampos)) && !("skipReferenceLookup" in campo && campo.skipReferenceLookup);
1467
+ var camposDeNombre = (definicion) => {
1468
+ const comoTextos = (campos) => Array.isArray(campos) ? campos.filter((c) => typeof c === "string") : [];
1469
+ if (definicion.lookupFields && definicion.lookupFields.length > 0) return definicion.lookupFields;
1470
+ return "nameFields" in definicion ? comoTextos(definicion.nameFields) : [];
1471
+ };
1472
+ var campoDeActivo = (definicion) => "activeRecords" in definicion && typeof definicion.activeRecords === "object" && definicion.activeRecords !== null && "fieldName" in definicion.activeRecords && typeof definicion.activeRecords.fieldName === "string" ? definicion.activeRecords.fieldName : null;
1473
+ var comoTexto = (valor) => valor === null || valor === void 0 ? "" : String(valor);
1474
+ var opcionesDeReferencia = (campo, definicionReferenciada, filasReferenciadas, filaActual, admiteNulo) => {
1475
+ const pares = campo.referencesFields ?? [];
1476
+ const columnaDelValor = pares.length > 0 ? pares[pares.length - 1].target : definicionReferenciada.primaryKey[definicionReferenciada.primaryKey.length - 1];
1477
+ const anteriores = pares.slice(0, -1);
1478
+ const activo = campoDeActivo(definicionReferenciada);
1479
+ const nombres = camposDeNombre(definicionReferenciada);
1480
+ const columnasDeEtiqueta = nombres.length > 0 ? [...definicionReferenciada.primaryKey, ...nombres] : definicionReferenciada.primaryKey;
1481
+ const opciones = filasReferenciadas.filter((fila) => (activo === null || !!fila[activo]) && anteriores.every((par) => comoTexto(fila[par.target]) === comoTexto(filaActual[par.source]))).map((fila) => {
1482
+ const etiquetas = columnasDeEtiqueta.map((columna) => comoTexto(fila[columna]));
1483
+ return { valor: fila[columnaDelValor], etiquetas, texto: `${etiquetas.join(", ")}; ${definicionReferenciada.primaryKey.join(", ")}` };
1484
+ });
1485
+ const ordenar = new Intl.Collator("es", { numeric: true, sensitivity: "base" });
1486
+ opciones.sort((a, b) => ordenar.compare(a.texto, b.texto));
1487
+ if (admiteNulo) opciones.push({ valor: null, etiquetas: ["", "(vac\xEDo)"], texto: "" });
1488
+ return opciones;
1489
+ };
1490
+ var filtrarOpciones = (opciones, busqueda) => {
1491
+ const simplificar = (texto) => texto.normalize("NFD").replace(/[̀-ͯ]/g, "").toLowerCase();
1492
+ const palabras = simplificar(busqueda).split(/\s+/).filter((p) => p !== "");
1493
+ if (palabras.length === 0) return opciones;
1494
+ return opciones.filter((opcion) => opcion.valor === null || palabras.every((p) => simplificar(opcion.etiquetas.join(" ")).includes(p)));
1495
+ };
1496
+ var VIGENCIA_DE_REFERENCIA_MS = 2 * 60 * 1e3;
1497
+ var referencias = /* @__PURE__ */ new Map();
1498
+ var cargarReferencia = (tabla) => {
1499
+ const guardada = referencias.get(tabla);
1500
+ if (guardada && Date.now() - guardada.cuando < VIGENCIA_DE_REFERENCIA_MS) return guardada.cargada;
1501
+ const cargada = (async () => {
1502
+ const [definicion, filas] = await Promise.all([
1503
+ executeBackendProcedure("table_structure", { table: tabla }),
1504
+ executeBackendProcedure("table_data", { table: tabla, fixedFields: [] })
1505
+ ]);
1506
+ return { definicion: requerido(definicion, `la estructura de '${tabla}'`), filas: requerido(filas, `los datos de '${tabla}'`) };
1507
+ })();
1508
+ referencias.set(tabla, { cargada, cuando: Date.now() });
1509
+ cargada.catch(() => {
1510
+ if (referencias.get(tabla)?.cargada === cargada) referencias.delete(tabla);
1511
+ });
1512
+ return cargada;
1513
+ };
1514
+
1515
+ // src/utils/expanders.ts
1516
+ var tipoDeExpander = (campo, editable) => {
1517
+ if (campo.typeName === "jsonb" && !editable) return "json";
1518
+ if (editable) {
1519
+ if (esCampoConReferencia(campo)) return "referencia";
1520
+ if (campo.typeName === "boolean") return "booleano";
1521
+ if (campo.options && campo.options.length > 0) return "opciones";
1522
+ if (campo.typeName === "date") return "fecha";
1523
+ }
1524
+ return campo.clientSide ? null : "texto";
1525
+ };
1526
+ var SI_NO_VACIO = { si: "S\xED", no: "No", vacio: "(vac\xEDo)" };
1527
+ var opcionesDeBooleano = (admiteNulo) => {
1528
+ const opciones = [
1529
+ { valor: true, etiquetas: [SI_NO_VACIO.si], texto: SI_NO_VACIO.si },
1530
+ { valor: false, etiquetas: [SI_NO_VACIO.no], texto: SI_NO_VACIO.no }
1531
+ ];
1532
+ if (admiteNulo) opciones.push({ valor: null, etiquetas: ["", SI_NO_VACIO.vacio], texto: "" });
1533
+ return opciones;
1534
+ };
1535
+ var opcionesDeEnumerado = (opciones, admiteNulo) => {
1536
+ const resultado = opciones.map((opcion) => typeof opcion === "string" ? { valor: opcion, etiquetas: [opcion], texto: opcion } : { valor: opcion.option, etiquetas: [String(opcion.option), opcion.label], texto: `${opcion.option} ${opcion.label}` });
1537
+ if (admiteNulo) resultado.push({ valor: null, etiquetas: ["", SI_NO_VACIO.vacio], texto: "" });
1538
+ return resultado;
1539
+ };
1540
+ var fechaDeValor = (valor) => {
1541
+ if (valor instanceof Date && !isNaN(valor.getTime())) return { anio: valor.getFullYear(), mes: valor.getMonth(), dia: valor.getDate() };
1542
+ if (typeof valor === "string") {
1543
+ const partes = /^(\d{4})-(\d{2})-(\d{2})/.exec(valor);
1544
+ if (partes) return { anio: Number(partes[1]), mes: Number(partes[2]) - 1, dia: Number(partes[3]) };
1545
+ }
1546
+ return null;
1547
+ };
1548
+ var fechaATexto = ({ anio, mes, dia }) => `${String(anio).padStart(4, "0")}-${String(mes + 1).padStart(2, "0")}-${String(dia).padStart(2, "0")}`;
1549
+ var semanasDelMes = (anio, mes) => {
1550
+ const primero = new Date(anio, mes, 1);
1551
+ const desfase = (primero.getDay() + 6) % 7;
1552
+ const diasDelMes = new Date(anio, mes + 1, 0).getDate();
1553
+ const semanas = [];
1554
+ for (let celda = 0; celda < Math.ceil((desfase + diasDelMes) / 7) * 7; celda++) {
1555
+ const fecha = new Date(anio, mes, 1 - desfase + celda);
1556
+ const dia = { anio: fecha.getFullYear(), mes: fecha.getMonth(), dia: fecha.getDate(), delMesMostrado: fecha.getMonth() === mes };
1557
+ if (celda % 7 === 0) semanas.push([]);
1558
+ semanas[semanas.length - 1].push(dia);
1559
+ }
1560
+ return semanas;
1561
+ };
1562
+ var textoParaVer = (valor) => {
1563
+ if (valor === null || valor === void 0) return "";
1564
+ if (typeof valor === "object" && !(valor instanceof Date)) return JSON.stringify(valor, null, 2);
1565
+ return String(valor);
1566
+ };
1567
+
1396
1568
  // src/hooks/grid/useGridEvents.ts
1397
1569
  var VIGENCIA_TECLA_PENDIENTE = 400;
1398
1570
  var VIGENCIA_VALOR_PENDIENTE_F4 = 1e3;
1399
- var useGridEvents = ({ dataGridRef, tableDefinition, filteredRows, tableData, fixedFields, setSelectedCell, setTableData, setSortColumns }) => {
1571
+ var useGridEvents = ({ dataGridRef, tableDefinition, filteredRows, tableData, fixedFields, setSelectedCell, setTableData, setSortColumns, verContenido }) => {
1400
1572
  const filteredRowsRef = useRef3(filteredRows);
1401
1573
  filteredRowsRef.current = filteredRows;
1402
1574
  const tableDefinitionRef = useRef3(tableDefinition);
@@ -1404,6 +1576,7 @@ var useGridEvents = ({ dataGridRef, tableDefinition, filteredRows, tableData, fi
1404
1576
  const valoresF4Pendientes = useRef3(/* @__PURE__ */ new Map());
1405
1577
  const teclasPendientes = useRef3([]);
1406
1578
  const editorActivo = useRef3(null);
1579
+ const teclaAnteriorRef = useRef3(null);
1407
1580
  const registrarEditor = useCallback5((procesar) => {
1408
1581
  editorActivo.current = procesar;
1409
1582
  const cola = teclasPendientes.current;
@@ -1414,7 +1587,8 @@ var useGridEvents = ({ dataGridRef, tableDefinition, filteredRows, tableData, fi
1414
1587
  if (editorActivo.current === procesar) editorActivo.current = null;
1415
1588
  };
1416
1589
  }, []);
1417
- const handleKeyPressInEditor = useCallback5((rowIndex, columnKey, event, currentColumns, handleCommit) => {
1590
+ const handleKeyPressInEditor = useCallback5((rowIndex, columnKey, event, currentColumns, handleCommit, valorActual) => {
1591
+ let resuelta = false;
1418
1592
  const tableDefinition2 = tableDefinitionRef.current;
1419
1593
  const filteredRows2 = filteredRowsRef.current;
1420
1594
  if (dataGridRef.current && tableDefinition2) {
@@ -1424,7 +1598,9 @@ var useGridEvents = ({ dataGridRef, tableDefinition, filteredRows, tableData, fi
1424
1598
  return col.key !== "actionsColumn" && !(esColumnaPropia(col) && col.customType === "detail") && (fieldDefinition?.editable !== false && !fieldDefinition?.clientSide);
1425
1599
  });
1426
1600
  const { key, target } = event;
1427
- const input = target;
1601
+ const teclaAnterior = teclaAnteriorRef.current;
1602
+ teclaAnteriorRef.current = key;
1603
+ const direccion = direccionDeSalida(event, posicionDelCursor(target), teclaAnterior);
1428
1604
  if (currentColumnIndex !== -1 && editableColumns.length > 0) {
1429
1605
  const editableColumnKeys = editableColumns.map((col) => col.key);
1430
1606
  let currentEditableColumnIndex = editableColumnKeys.indexOf(columnKey);
@@ -1448,57 +1624,42 @@ var useGridEvents = ({ dataGridRef, tableDefinition, filteredRows, tableData, fi
1448
1624
  const nextColumnIndex = currentColumns.findIndex((col) => col.key === nextColumnKey);
1449
1625
  return { rowIdx: nextRowIndex, idx: nextColumnIndex };
1450
1626
  };
1451
- const calcularColumnaAnterior = () => {
1452
- let nextEditableColumnIndex = currentEditableColumnIndex - 1;
1453
- let nextRowIndex = rowIndex;
1454
- if (nextEditableColumnIndex <= 0) {
1455
- nextEditableColumnIndex = 0;
1456
- }
1457
- const nextColumnKey = editableColumnKeys[nextEditableColumnIndex];
1458
- const nextColumnIndex = currentColumns.findIndex((col) => col.key === nextColumnKey);
1459
- return { rowIdx: nextRowIndex, idx: nextColumnIndex };
1627
+ const indiceDeColumna = (indiceEditable) => currentColumns.findIndex((col) => col.key === editableColumnKeys[indiceEditable]);
1628
+ const calcularColumnaAnteriorConSalto = () => {
1629
+ if (currentEditableColumnIndex > 0) return { rowIdx: rowIndex, idx: indiceDeColumna(currentEditableColumnIndex - 1) };
1630
+ const filaAnterior = filaDeDatos(rowIndex, -1);
1631
+ return filaAnterior === -1 ? null : { rowIdx: filaAnterior, idx: indiceDeColumna(editableColumnKeys.length - 1) };
1632
+ };
1633
+ const calcularColumnaVecina = (paso) => {
1634
+ const vecina = currentEditableColumnIndex + paso;
1635
+ return vecina < 0 || vecina >= editableColumnKeys.length ? null : { rowIdx: rowIndex, idx: indiceDeColumna(vecina) };
1636
+ };
1637
+ const calcularFilaVecina = (paso) => {
1638
+ const vecina = filaDeDatos(rowIndex, paso);
1639
+ return vecina === -1 ? null : { rowIdx: vecina, idx: currentColumnIndex };
1460
1640
  };
1461
1641
  const calcularFilaSiguiente = () => {
1462
1642
  const nextRowIndex = filaDeDatos(rowIndex, 1);
1463
1643
  return { rowIdx: nextRowIndex === -1 ? rowIndex : nextRowIndex, idx: currentColumnIndex };
1464
1644
  };
1465
- const calcularFilaAnterior = () => {
1466
- const nextRowIndex = filaDeDatos(rowIndex, -1);
1467
- return { rowIdx: nextRowIndex === -1 ? rowIndex : nextRowIndex, idx: currentColumnIndex };
1468
- };
1469
1645
  if (currentEditableColumnIndex !== -1) {
1470
1646
  switch (true) {
1471
- case ["Enter", "Tab"].includes(key): {
1472
- hacerFoco(calcularColumnaSiguiente());
1473
- break;
1474
- }
1475
- case key === "ArrowRight": {
1476
- if (input && typeof input.selectionStart === "number") {
1477
- const cursorPosition = input.selectionStart;
1478
- const inputValueLength = input.value?.length || 0;
1479
- if (cursorPosition === inputValueLength) {
1480
- hacerFoco(calcularColumnaSiguiente());
1481
- }
1647
+ case direccion !== null: {
1648
+ resuelta = true;
1649
+ const destino = {
1650
+ siguiente: calcularColumnaSiguiente,
1651
+ anterior: calcularColumnaAnteriorConSalto,
1652
+ izquierda: () => calcularColumnaVecina(-1),
1653
+ derecha: () => calcularColumnaVecina(1),
1654
+ arriba: () => calcularFilaVecina(-1),
1655
+ abajo: () => calcularFilaVecina(1)
1656
+ }[direccion]();
1657
+ if (destino) {
1658
+ void handleCommit(valorActual, true, true);
1659
+ hacerFoco(destino);
1482
1660
  }
1483
1661
  break;
1484
1662
  }
1485
- case key === "ArrowLeft": {
1486
- if (input && typeof input.selectionStart === "number") {
1487
- const cursorPosition = input.selectionStart;
1488
- if (cursorPosition === 0) {
1489
- hacerFoco(calcularColumnaAnterior());
1490
- }
1491
- }
1492
- break;
1493
- }
1494
- case key === "ArrowUp": {
1495
- hacerFoco(calcularFilaAnterior());
1496
- break;
1497
- }
1498
- case key === "ArrowDown": {
1499
- hacerFoco(calcularFilaSiguiente());
1500
- break;
1501
- }
1502
1663
  case key === "F4": {
1503
1664
  const { rowIdx, idx } = calcularFilaSiguiente();
1504
1665
  const indiceAnterior = filaDeDatos(rowIndex, -1);
@@ -1519,8 +1680,26 @@ var useGridEvents = ({ dataGridRef, tableDefinition, filteredRows, tableData, fi
1519
1680
  }
1520
1681
  }
1521
1682
  }
1683
+ return resuelta;
1522
1684
  }, [dataGridRef]);
1523
1685
  const handleCellKeyDown = useCallback5((args, event) => {
1686
+ const esExpander = event.key === "F9" && !event.shiftKey && !event.ctrlKey && !event.altKey || event.key === "ArrowDown" && event.altKey && !event.shiftKey && !event.ctrlKey;
1687
+ if (esExpander && !(event.target instanceof HTMLInputElement) && !esFilaDetalle(args.row)) {
1688
+ const campo = tableDefinitionRef.current?.fields.find((f) => f.name === args.column.key);
1689
+ const editable = typeof args.column.editable === "function" ? args.column.editable(args.row) : args.column.editable === true;
1690
+ const tipo = campo ? tipoDeExpander(campo, editable) : null;
1691
+ if (campo && editable && tipo !== null) {
1692
+ teclasPendientes.current.push({ key: "F9", cuando: Date.now() });
1693
+ dataGridRef.current?.selectCell({ rowIdx: args.rowIdx, idx: args.column.idx }, { enableEditor: true, shouldFocusCell: true });
1694
+ event.preventGridDefault();
1695
+ return;
1696
+ }
1697
+ if (campo && !editable && (tipo === "json" || tipo === "texto") && verContenido && event.target instanceof HTMLElement) {
1698
+ verContenido(event.target, textoParaVer(args.row[campo.name]));
1699
+ event.preventGridDefault();
1700
+ return;
1701
+ }
1702
+ }
1524
1703
  if (event.key === "F4" && !(event.target instanceof HTMLInputElement) && !esFilaDetalle(args.row)) {
1525
1704
  const fieldDefinition = tableDefinitionRef.current?.fields.find((f) => f.name === args.column.key);
1526
1705
  if (fieldDefinition && fieldDefinition.editable !== false && !fieldDefinition.clientSide) {
@@ -1533,7 +1712,7 @@ var useGridEvents = ({ dataGridRef, tableDefinition, filteredRows, tableData, fi
1533
1712
  if (["Enter", "Tab", "ArrowDown", "ArrowUp", "ArrowRight", "ArrowLeft"].includes(event.key)) {
1534
1713
  event.preventGridDefault();
1535
1714
  }
1536
- }, []);
1715
+ }, [dataGridRef, verContenido]);
1537
1716
  const handleCellMouseDown = useCallback5((_args, event) => {
1538
1717
  event.preventGridDefault();
1539
1718
  }, []);
@@ -1546,10 +1725,12 @@ var useGridEvents = ({ dataGridRef, tableDefinition, filteredRows, tableData, fi
1546
1725
  const handleCellClick = useCallback5((args, _event) => {
1547
1726
  if (esFilaDetalle(args.row)) return;
1548
1727
  const fieldDefinition = tableDefinition?.fields.find((f) => f.name === args.column.key);
1549
- const isFixedField = fixedFields?.some((f) => f.fieldName === args.column.key);
1728
+ const isFixedField = valorFijoDe(fixedFields, args.column.key) !== void 0;
1550
1729
  const isEditable = fieldDefinition?.editable !== false && !isFixedField;
1551
1730
  if (isEditable) {
1552
1731
  args.selectCell(true);
1732
+ } else if (fieldDefinition && tipoDeExpander(fieldDefinition, false) !== null) {
1733
+ args.selectCell(false);
1553
1734
  }
1554
1735
  }, [tableDefinition, fixedFields]);
1555
1736
  const handleRowsChange = useCallback5((updatedRows, data) => {
@@ -1722,7 +1903,7 @@ var useGridMenu = ({
1722
1903
  };
1723
1904
 
1724
1905
  // src/hooks/grid/useGridColumns.ts
1725
- import React9, { useMemo as useMemo7 } from "react";
1906
+ import React12, { useMemo as useMemo8 } from "react";
1726
1907
 
1727
1908
  // src/utils/functions.tsx
1728
1909
  import * as JSON4all2 from "json4all";
@@ -2172,8 +2353,7 @@ var defaultColumnSummaryCellRenderer = (props, fixedFields) => {
2172
2353
  const { column, row } = props;
2173
2354
  if (row.id === "filterRow") {
2174
2355
  const { filters, setFilters } = row;
2175
- const fixedFieldEntry = fixedFields?.find((f) => f.fieldName === column.key);
2176
- if (fixedFieldEntry && fixedFieldEntry.until === void 0) return null;
2356
+ if (valorFijoDe(fixedFields, column.key)) return null;
2177
2357
  const fieldDef = esColumnaPropia(column) && column.customType === "default" ? column.fieldDef : void 0;
2178
2358
  return /* @__PURE__ */ jsx9(Box5, { sx: { width: "100%", height: "100%", display: "flex", alignItems: "center" }, children: /* @__PURE__ */ jsx9(
2179
2359
  FilterInputRender_default,
@@ -2325,7 +2505,7 @@ var CeldaDato = React7.memo(function CeldaDato2({ row, columnKey, defaultColumn
2325
2505
  let cellBackgroundColor = "transparent";
2326
2506
  if (currentCellFeedback) {
2327
2507
  cellBackgroundColor = currentCellFeedback.type === "error" ? theme.palette.error.light : theme.palette.success.light;
2328
- } else if (fixedFields?.some((f) => f.fieldName === columnKey)) {
2508
+ } else if (valorFijoDe(fixedFields, columnKey)) {
2329
2509
  cellBackgroundColor = theme.palette.action.selected;
2330
2510
  } else if (isMandatory && !hasValue || pendiente) {
2331
2511
  cellBackgroundColor = "#e3f2fd";
@@ -2421,14 +2601,13 @@ var allColumnsCellRenderer = (props) => {
2421
2601
  };
2422
2602
 
2423
2603
  // src/components/grid/InputRenderer.tsx
2424
- import React8, { useCallback as useCallback9, useEffect as useEffect4, useMemo as useMemo6, useState as useState8 } from "react";
2604
+ import React11, { useCallback as useCallback9, useEffect as useEffect5, useMemo as useMemo7, useState as useState11 } from "react";
2425
2605
 
2426
2606
  // src/hooks/useTableRecordSave.ts
2427
2607
  import { useCallback as useCallback8 } from "react";
2428
2608
  var useTableRecordSave = () => {
2429
2609
  const { callApi, loading, error } = useApiCall();
2430
2610
  const saveRecord = useCallback8(async ({
2431
- tableName,
2432
2611
  tableDefinition,
2433
2612
  isNewRow,
2434
2613
  formData,
@@ -2457,13 +2636,12 @@ var useTableRecordSave = () => {
2457
2636
  }
2458
2637
  });
2459
2638
  }
2460
- tableDefinition.primaryKey.forEach((pkField) => {
2461
- rowToSend[pkField] = formData[pkField];
2462
- });
2463
2639
  }
2464
2640
  const primaryKeyValuesForBackend = isNewRow ? [] : tableDefinition.primaryKey.map((key) => initialData[key]);
2465
2641
  const response = await callApi("table_record_save", {
2466
- table: tableName,
2642
+ // como backend-plus (`depot.def.name`): el servidor busca la definición por este nombre. Una definición que guarda en
2643
+ // otra tabla (`tableName`, con campos de `table`) no existe con el nombre de la física: ahí faltarían sus campos
2644
+ table: tableDefinition.name,
2467
2645
  primaryKeyValues: primaryKeyValuesForBackend,
2468
2646
  newRow: rowToSend,
2469
2647
  oldRow: isNewRow ? {} : initialData,
@@ -2475,10 +2653,208 @@ var useTableRecordSave = () => {
2475
2653
  };
2476
2654
 
2477
2655
  // src/components/grid/InputRenderer.tsx
2478
- import InputBase2 from "@mui/material/InputBase";
2656
+ import InputBase4 from "@mui/material/InputBase";
2657
+ import IconButton4 from "@mui/material/IconButton";
2658
+ import ArrowDropDownIcon from "@mui/icons-material/ArrowDropDown";
2659
+ import CalendarMonthIcon from "@mui/icons-material/CalendarMonth";
2660
+ import SearchIcon2 from "@mui/icons-material/Search";
2479
2661
  import { Tooltip as Tooltip5, useTheme as useTheme3 } from "@mui/material";
2662
+
2663
+ // src/components/grid/MenuDeOpciones.tsx
2664
+ import { useEffect as useEffect4, useMemo as useMemo6, useRef as useRef5, useState as useState8 } from "react";
2665
+ import { InputBase as InputBase2, List as List2, ListItemButton as ListItemButton2, Popover as Popover2, Typography as Typography5 } from "@mui/material";
2666
+ import { jsx as jsx13, jsxs as jsxs10 } from "react/jsx-runtime";
2667
+ function MenuDeOpciones({ anclaje, opciones, busquedaInicial, onElegir, onCerrar }) {
2668
+ const [busqueda, setBusqueda] = useState8(busquedaInicial);
2669
+ const [indice, setIndice] = useState8(0);
2670
+ const visibles = useMemo6(() => filtrarOpciones(opciones, busqueda), [opciones, busqueda]);
2671
+ const elegida = useRef5(null);
2672
+ useEffect4(() => {
2673
+ elegida.current?.scrollIntoView({ block: "nearest" });
2674
+ }, [indice, visibles]);
2675
+ const alApretar = (evento) => {
2676
+ if (evento.key === "ArrowDown") {
2677
+ setIndice((i) => Math.min(i + 1, visibles.length - 1));
2678
+ } else if (evento.key === "ArrowUp") {
2679
+ setIndice((i) => Math.max(i - 1, 0));
2680
+ } else if (evento.key === "Enter") {
2681
+ if (visibles[indice]) onElegir(visibles[indice].valor);
2682
+ } else if (evento.key === "F9" || evento.key === "Escape") {
2683
+ onCerrar();
2684
+ } else {
2685
+ return;
2686
+ }
2687
+ evento.preventDefault();
2688
+ evento.stopPropagation();
2689
+ };
2690
+ return /* @__PURE__ */ jsxs10(
2691
+ Popover2,
2692
+ {
2693
+ open: true,
2694
+ anchorEl: anclaje,
2695
+ onClose: onCerrar,
2696
+ disableRestoreFocus: true,
2697
+ anchorOrigin: { vertical: "bottom", horizontal: "left" },
2698
+ slotProps: { paper: { sx: { minWidth: 300, maxWidth: 520 } } },
2699
+ children: [
2700
+ /* @__PURE__ */ jsx13(
2701
+ InputBase2,
2702
+ {
2703
+ autoFocus: true,
2704
+ fullWidth: true,
2705
+ value: busqueda,
2706
+ onChange: (e) => {
2707
+ setBusqueda(e.target.value);
2708
+ setIndice(0);
2709
+ },
2710
+ onKeyDown: alApretar,
2711
+ placeholder: "buscar",
2712
+ sx: { px: 1, py: 0.5, fontSize: "0.8rem", borderBottom: "1px solid #ccc" },
2713
+ inputProps: { "aria-label": "buscar" }
2714
+ }
2715
+ ),
2716
+ /* @__PURE__ */ jsxs10(List2, { dense: true, disablePadding: true, sx: { maxHeight: 320, overflowY: "auto" }, role: "listbox", children: [
2717
+ visibles.length === 0 && /* @__PURE__ */ jsx13(Typography5, { variant: "body2", sx: { p: 1, color: "text.secondary" }, children: "sin coincidencias" }),
2718
+ visibles.map((opcion, i) => /* @__PURE__ */ jsx13(
2719
+ ListItemButton2,
2720
+ {
2721
+ ref: i === indice ? elegida : null,
2722
+ selected: i === indice,
2723
+ role: "option",
2724
+ onClick: () => onElegir(opcion.valor),
2725
+ sx: { gap: 2, py: 0.25, fontSize: "0.8rem" },
2726
+ children: opcion.etiquetas.map((etiqueta, j) => /* @__PURE__ */ jsx13("span", { style: { fontWeight: j === 0 ? 600 : 400, minWidth: j === 0 ? 40 : void 0 }, children: etiqueta }, j))
2727
+ },
2728
+ i
2729
+ ))
2730
+ ] })
2731
+ ]
2732
+ }
2733
+ );
2734
+ }
2735
+
2736
+ // src/components/grid/SelectorDeFecha.tsx
2737
+ import { useState as useState9 } from "react";
2738
+ import { Button as Button3, IconButton as IconButton3, Popover as Popover3, Typography as Typography6 } from "@mui/material";
2739
+ import { jsx as jsx14, jsxs as jsxs11 } from "react/jsx-runtime";
2740
+ var MESES = ["enero", "febrero", "marzo", "abril", "mayo", "junio", "julio", "agosto", "septiembre", "octubre", "noviembre", "diciembre"];
2741
+ var DIAS = ["lu", "ma", "mi", "ju", "vi", "s\xE1", "do"];
2742
+ var mismaFecha = (a, b) => b !== null && a.anio === b.anio && a.mes === b.mes && a.dia === b.dia;
2743
+ var MOVIMIENTOS = {
2744
+ ArrowLeft: [-1, 0],
2745
+ ArrowRight: [1, 0],
2746
+ ArrowUp: [-7, 0],
2747
+ ArrowDown: [7, 0],
2748
+ PageUp: [0, -1],
2749
+ PageDown: [0, 1]
2750
+ };
2751
+ function SelectorDeFecha({ anclaje, fechaActual, admiteNulo, onElegir, onCerrar }) {
2752
+ const hoy = /* @__PURE__ */ new Date();
2753
+ const fechaDeHoy = { anio: hoy.getFullYear(), mes: hoy.getMonth(), dia: hoy.getDate() };
2754
+ const [cursor, setCursor] = useState9(fechaActual ?? fechaDeHoy);
2755
+ const mover = (dias, meses) => {
2756
+ const nueva = new Date(cursor.anio, cursor.mes + meses, cursor.dia + dias);
2757
+ setCursor({ anio: nueva.getFullYear(), mes: nueva.getMonth(), dia: nueva.getDate() });
2758
+ };
2759
+ const alApretar = (evento) => {
2760
+ if (evento.key in MOVIMIENTOS) {
2761
+ mover(...MOVIMIENTOS[evento.key]);
2762
+ } else if (evento.key === "Enter") {
2763
+ onElegir(fechaATexto(cursor));
2764
+ } else if (evento.key === "F9" || evento.key === "Escape") {
2765
+ onCerrar();
2766
+ } else {
2767
+ return;
2768
+ }
2769
+ evento.preventDefault();
2770
+ evento.stopPropagation();
2771
+ };
2772
+ return /* @__PURE__ */ jsx14(Popover3, { open: true, anchorEl: anclaje, onClose: onCerrar, disableRestoreFocus: true, anchorOrigin: { vertical: "bottom", horizontal: "left" }, children: /* @__PURE__ */ jsxs11("div", { tabIndex: 0, ref: (el) => el?.focus(), onKeyDown: alApretar, style: { padding: 8, outline: "none", width: 252 }, "aria-label": "calendario", children: [
2773
+ /* @__PURE__ */ jsxs11("div", { style: { display: "flex", alignItems: "center", justifyContent: "space-between" }, children: [
2774
+ /* @__PURE__ */ jsx14(IconButton3, { size: "small", "aria-label": "mes anterior", onClick: () => mover(0, -1), children: "\u2039" }),
2775
+ /* @__PURE__ */ jsxs11(Typography6, { variant: "body2", sx: { fontWeight: 600 }, children: [
2776
+ MESES[cursor.mes],
2777
+ " ",
2778
+ cursor.anio
2779
+ ] }),
2780
+ /* @__PURE__ */ jsx14(IconButton3, { size: "small", "aria-label": "mes siguiente", onClick: () => mover(0, 1), children: "\u203A" })
2781
+ ] }),
2782
+ /* @__PURE__ */ jsxs11("table", { style: { borderCollapse: "collapse", width: "100%", textAlign: "center", fontSize: "0.8rem" }, children: [
2783
+ /* @__PURE__ */ jsx14("thead", { children: /* @__PURE__ */ jsx14("tr", { children: DIAS.map((d) => /* @__PURE__ */ jsx14("th", { style: { fontWeight: 400, color: "#777" }, children: d }, d)) }) }),
2784
+ /* @__PURE__ */ jsx14("tbody", { children: semanasDelMes(cursor.anio, cursor.mes).map((semana, i) => /* @__PURE__ */ jsx14("tr", { children: semana.map((dia) => {
2785
+ const elegido = mismaFecha(dia, fechaActual);
2786
+ const enCursor = mismaFecha(dia, cursor);
2787
+ return /* @__PURE__ */ jsx14("td", { style: { padding: 1 }, children: /* @__PURE__ */ jsx14(
2788
+ "button",
2789
+ {
2790
+ type: "button",
2791
+ tabIndex: -1,
2792
+ onClick: () => onElegir(fechaATexto(dia)),
2793
+ style: {
2794
+ width: 32,
2795
+ height: 26,
2796
+ border: enCursor ? "1px solid #1976d2" : "1px solid transparent",
2797
+ borderRadius: 4,
2798
+ cursor: "pointer",
2799
+ background: elegido ? "#1976d2" : "transparent",
2800
+ color: elegido ? "#fff" : dia.delMesMostrado ? "#000" : "#aaa"
2801
+ },
2802
+ children: dia.dia
2803
+ }
2804
+ ) }, `${dia.mes}-${dia.dia}`);
2805
+ }) }, i)) })
2806
+ ] }),
2807
+ /* @__PURE__ */ jsxs11("div", { style: { display: "flex", justifyContent: "space-between", marginTop: 4 }, children: [
2808
+ /* @__PURE__ */ jsx14(Button3, { size: "small", onClick: () => onElegir(fechaATexto(fechaDeHoy)), children: "hoy" }),
2809
+ admiteNulo && /* @__PURE__ */ jsx14(Button3, { size: "small", onClick: () => onElegir(null), children: "vac\xEDo" })
2810
+ ] })
2811
+ ] }) });
2812
+ }
2813
+
2814
+ // src/components/grid/VentanaDeTexto.tsx
2815
+ import { useState as useState10 } from "react";
2816
+ import { Button as Button4, InputBase as InputBase3, Popover as Popover4 } from "@mui/material";
2817
+ import { jsx as jsx15, jsxs as jsxs12 } from "react/jsx-runtime";
2818
+ function VentanaDeTexto({ anclaje, texto, editable, onAceptar, onCerrar }) {
2819
+ const [valor, setValor] = useState10(texto);
2820
+ const alApretar = (evento) => {
2821
+ if (evento.key === "Escape" || evento.key === "F9") {
2822
+ onCerrar();
2823
+ } else if (evento.key === "Enter" && evento.ctrlKey && editable) {
2824
+ onAceptar(valor);
2825
+ } else {
2826
+ return;
2827
+ }
2828
+ evento.preventDefault();
2829
+ evento.stopPropagation();
2830
+ };
2831
+ return /* @__PURE__ */ jsx15(Popover4, { open: true, anchorEl: anclaje, onClose: onCerrar, disableRestoreFocus: true, anchorOrigin: { vertical: "bottom", horizontal: "left" }, children: /* @__PURE__ */ jsxs12("div", { style: { padding: 8, minWidth: 320, maxWidth: 640 }, children: [
2832
+ /* @__PURE__ */ jsx15(
2833
+ InputBase3,
2834
+ {
2835
+ autoFocus: true,
2836
+ multiline: true,
2837
+ fullWidth: true,
2838
+ readOnly: !editable,
2839
+ value: valor,
2840
+ onChange: (e) => setValor(e.target.value),
2841
+ onKeyDown: alApretar,
2842
+ minRows: 2,
2843
+ maxRows: 16,
2844
+ sx: { fontFamily: "monospace", fontSize: "0.8rem", border: "1px solid #ccc", borderRadius: "4px", p: 0.5 },
2845
+ inputProps: { "aria-label": "contenido de la celda" }
2846
+ }
2847
+ ),
2848
+ editable && /* @__PURE__ */ jsxs12("div", { style: { display: "flex", justifyContent: "flex-end", gap: 8, marginTop: 4 }, children: [
2849
+ /* @__PURE__ */ jsx15(Button4, { size: "small", onClick: onCerrar, children: "cancelar" }),
2850
+ /* @__PURE__ */ jsx15(Button4, { size: "small", variant: "contained", onClick: () => onAceptar(valor), children: "aceptar" })
2851
+ ] })
2852
+ ] }) });
2853
+ }
2854
+
2855
+ // src/components/grid/InputRenderer.tsx
2480
2856
  import typeStore4 from "type-store";
2481
- import { jsx as jsx13 } from "react/jsx-runtime";
2857
+ import { Fragment as Fragment3, jsx as jsx16, jsxs as jsxs13 } from "react/jsx-runtime";
2482
2858
  function findChangedValues(oldRowData, newRowData, isNewRow) {
2483
2859
  let changes = [];
2484
2860
  for (const key in newRowData) {
@@ -2504,13 +2880,15 @@ function InputRenderer({
2504
2880
  const setCellFeedbackMap = estadoGrilla.setFeedback;
2505
2881
  const setLocalCellChanges = estadoGrilla.setCambiosLocales;
2506
2882
  const fieldDefinition = requerido(tableDefinition.fields.find((f) => f.name === column.key), `el campo '${column.key}'`);
2507
- const typer = useMemo6(() => typeStore4.typerFrom(fieldDefinition), [fieldDefinition]);
2508
- const [editingValue, setEditingValue] = useState8(() => row[column.key] !== null ? isNumericType(fieldDefinition?.typeName) ? row[column.key] : typer.toLocalString(row[column.key]) : null);
2509
- const isCommitInProgress = React8.useRef(false);
2883
+ const typer = useMemo7(() => typeStore4.typerFrom(fieldDefinition), [fieldDefinition]);
2884
+ const [editingValue, setEditingValue] = useState11(() => row[column.key] !== null ? isNumericType(fieldDefinition?.typeName) ? row[column.key] : typer.toLocalString(row[column.key]) : null);
2885
+ const isCommitInProgress = React11.useRef(false);
2886
+ const [expansion, setExpansion] = useState11(null);
2887
+ const menuAbierto = React11.useRef(false);
2888
+ const entradaRef = React11.useRef(null);
2510
2889
  const theme = useTheme3();
2511
2890
  const { showSuccess, showError } = useSnackbar();
2512
2891
  const { saveRecord } = useTableRecordSave();
2513
- const tableName = tableDefinition.tableName;
2514
2892
  const rowId = getPrimaryKeyValues(row, primaryKey);
2515
2893
  const cellKey = `${rowId}-${column.key}`;
2516
2894
  const currentCellFeedback = useFeedbackCelda(cellKey);
@@ -2522,16 +2900,18 @@ function InputRenderer({
2522
2900
  cellBackgroundColor = currentCellFeedback.type === "error" ? theme.palette.error.light : theme.palette.success.light;
2523
2901
  cellBorderColor = currentCellFeedback.type === "error" ? theme.palette.error.main : theme.palette.success.main;
2524
2902
  }
2525
- const initialRowId = useMemo6(() => getPrimaryKeyValues(row, primaryKey), [row, primaryKey]);
2903
+ const initialRowId = useMemo7(() => getPrimaryKeyValues(row, primaryKey), [row, primaryKey]);
2526
2904
  const handleCommit = useCallback9(async (currentValue, closeEditor, focusNextCell) => {
2527
2905
  if (isCommitInProgress.current) return;
2528
2906
  isCommitInProgress.current = true;
2529
2907
  let processedNewValue;
2530
2908
  try {
2531
- processedNewValue = getBestTypedValue(currentValue, typer);
2909
+ processedNewValue = tiparEntrada(currentValue, typer);
2532
2910
  typer.validateTypedData(processedNewValue);
2533
2911
  } catch (err) {
2534
2912
  showError(mensajeDeError(err));
2913
+ const claveDeLaCelda = `${getPrimaryKeyValues(row, tableDefinition.primaryKey)}-${column.key}`;
2914
+ setCellFeedbackMap((prev) => new Map(prev).set(claveDeLaCelda, { rowId: getPrimaryKeyValues(row, tableDefinition.primaryKey), columnKey: column.key, type: "error", message: mensajeDeError(err) }));
2535
2915
  isCommitInProgress.current = false;
2536
2916
  return;
2537
2917
  }
@@ -2588,7 +2968,6 @@ function InputRenderer({
2588
2968
  }
2589
2969
  try {
2590
2970
  const response = await saveRecord({
2591
- tableName,
2592
2971
  tableDefinition,
2593
2972
  isNewRow,
2594
2973
  formData: potentialUpdatedRow,
@@ -2654,7 +3033,6 @@ function InputRenderer({
2654
3033
  column,
2655
3034
  row,
2656
3035
  onRowChange,
2657
- tableName,
2658
3036
  tableDefinition.primaryKey,
2659
3037
  tableDefinition.fields,
2660
3038
  showSuccess,
@@ -2666,42 +3044,94 @@ function InputRenderer({
2666
3044
  initialRowId,
2667
3045
  typer
2668
3046
  ]);
3047
+ const tipoExpander = tipoDeExpander(fieldDefinition, fieldDefinition.editable !== false);
3048
+ const abrirExpander = useCallback9(async (busqueda) => {
3049
+ if (tipoExpander === null || tipoExpander === "json" || menuAbierto.current) return;
3050
+ menuAbierto.current = true;
3051
+ const admiteNulo = fieldDefinition.nullable !== false;
3052
+ try {
3053
+ if (tipoExpander === "referencia" && esCampoConReferencia(fieldDefinition)) {
3054
+ const { definicion, filas } = await cargarReferencia(fieldDefinition.references);
3055
+ setExpansion({ tipo: "opciones", opciones: opcionesDeReferencia(fieldDefinition, definicion, filas, row, admiteNulo), busqueda });
3056
+ } else if (tipoExpander === "booleano") {
3057
+ setExpansion({ tipo: "opciones", opciones: opcionesDeBooleano(admiteNulo), busqueda });
3058
+ } else if (tipoExpander === "opciones") {
3059
+ setExpansion({ tipo: "opciones", opciones: opcionesDeEnumerado(fieldDefinition.options ?? [], admiteNulo), busqueda });
3060
+ } else {
3061
+ setExpansion({ tipo: tipoExpander === "fecha" ? "fecha" : "texto" });
3062
+ }
3063
+ } catch (err) {
3064
+ menuAbierto.current = false;
3065
+ showError(mensajeDeError(err));
3066
+ }
3067
+ }, [tipoExpander, fieldDefinition, row, showError]);
3068
+ const cerrarExpansion = useCallback9(() => {
3069
+ menuAbierto.current = false;
3070
+ setExpansion(null);
3071
+ setTimeout(() => entradaRef.current?.focus(), 0);
3072
+ }, []);
3073
+ const confirmarEnExpansion = useCallback9((nuevo) => {
3074
+ setEditingValue(nuevo);
3075
+ cerrarExpansion();
3076
+ void handleCommit(nuevo, true, false);
3077
+ }, [cerrarExpansion, handleCommit]);
3078
+ const elegirOpcion = useCallback9((valor) => {
3079
+ confirmarEnExpansion(valor === null || valor === void 0 ? null : typeof valor === "boolean" || isNumericType(fieldDefinition.typeName) ? valor : typer.toLocalString(valor));
3080
+ }, [fieldDefinition.typeName, typer, confirmarEnExpansion]);
2669
3081
  const handleKeyDown = useCallback9(async (event) => {
3082
+ if (tipoExpander !== null && (event.key === "F9" && !event.shiftKey && !event.ctrlKey && !event.altKey || event.key === "ArrowDown" && event.altKey && !event.shiftKey && !event.ctrlKey)) {
3083
+ event.preventDefault();
3084
+ void abrirExpander("");
3085
+ return;
3086
+ }
3087
+ if (event.key.length === 1 && !event.ctrlKey && !event.altKey && !event.metaKey && caracterRechazado(event.key, typer)) {
3088
+ event.preventDefault();
3089
+ if (tipoExpander === "referencia") void abrirExpander(event.key);
3090
+ return;
3091
+ }
2670
3092
  if (event.key === "F4") {
2671
3093
  event.preventDefault();
2672
3094
  if (onKeyPress) {
2673
- onKeyPress(rowIdx, column.key, event, handleCommit);
3095
+ onKeyPress(rowIdx, column.key, event, handleCommit, editingValue);
2674
3096
  }
2675
3097
  return;
2676
3098
  }
2677
- if (["Enter", "Tab", "ArrowDown", "ArrowUp", "ArrowRight", "ArrowLeft"].includes(event.key)) {
2678
- void handleCommit(editingValue, true, true);
2679
- if (onKeyPress) {
2680
- onKeyPress(rowIdx, column.key, event, handleCommit);
2681
- }
3099
+ if (onKeyPress?.(rowIdx, column.key, event, handleCommit, editingValue)) {
3100
+ event.preventDefault();
2682
3101
  }
2683
- }, [handleCommit, editingValue, column.key, rowIdx, onKeyPress]);
2684
- const procesarTecla = React8.useRef(() => {
3102
+ }, [handleCommit, editingValue, column.key, rowIdx, onKeyPress, tipoExpander, abrirExpander, typer]);
3103
+ const procesarTecla = React11.useRef(() => {
2685
3104
  });
2686
3105
  procesarTecla.current = (key) => {
2687
- if (key === "F4" && onKeyPress) {
2688
- onKeyPress(rowIdx, column.key, { key, target: document.activeElement ?? document.body }, handleCommit);
3106
+ if (key === "F9") {
3107
+ void abrirExpander("");
3108
+ } else if (key === "F4" && onKeyPress) {
3109
+ onKeyPress(rowIdx, column.key, { key, target: document.activeElement ?? document.body }, handleCommit, editingValue);
2689
3110
  }
2690
3111
  };
2691
- useEffect4(() => registrarEditor?.((key) => procesarTecla.current(key)), []);
3112
+ useEffect5(() => registrarEditor?.((key) => procesarTecla.current(key)), []);
2692
3113
  const handleBlur = useCallback9(() => {
3114
+ if (menuAbierto.current) return;
2693
3115
  handleCommit(editingValue, true, false);
2694
3116
  }, [handleCommit, editingValue]);
2695
3117
  const isFieldEditable = fieldDefinition?.editable !== false;
2696
3118
  const isNumeric = isNumericType(fieldDefinition?.typeName);
2697
- const editor = /* @__PURE__ */ jsx13(
2698
- InputBase2,
3119
+ const editor = /* @__PURE__ */ jsx16(
3120
+ InputBase4,
2699
3121
  {
2700
3122
  autoFocus: true,
2701
3123
  value: editingValue,
2702
3124
  onChange: (e) => setEditingValue(e.target.value),
2703
3125
  onKeyDown: handleKeyDown,
3126
+ onPaste: (e) => {
3127
+ const pegado = e.clipboardData.getData("text");
3128
+ if (textoPegadoRechazado(pegado, typer)) {
3129
+ e.preventDefault();
3130
+ showError(`\xAB${pegado}\xBB no es un valor v\xE1lido para este campo (${typer.typeName})`);
3131
+ }
3132
+ },
2704
3133
  onBlur: handleBlur,
3134
+ inputRef: entradaRef,
2705
3135
  placeholder: isMandatory ? "*" : "",
2706
3136
  className: editingValue === "--" ? "typed-controls-signal-no-data" : editingValue === "//" ? "typed-controls-signal-unknown-data" : "",
2707
3137
  sx: {
@@ -2718,15 +3148,62 @@ function InputRenderer({
2718
3148
  }
2719
3149
  },
2720
3150
  onClick: (e) => e.stopPropagation(),
2721
- disabled: !isFieldEditable
3151
+ disabled: !isFieldEditable,
3152
+ endAdornment: tipoExpander !== null && tipoExpander !== "json" && /* @__PURE__ */ jsx16(
3153
+ IconButton4,
3154
+ {
3155
+ size: "small",
3156
+ tabIndex: -1,
3157
+ "aria-label": tipoExpander === "fecha" ? "elegir fecha" : tipoExpander === "texto" ? "ver el contenido completo" : "elegir un valor",
3158
+ title: tipoExpander === "fecha" ? "elegir fecha (F9)" : tipoExpander === "texto" ? "ver el contenido completo (F9)" : "elegir un valor (F9)",
3159
+ onMouseDown: (e) => e.preventDefault(),
3160
+ onClick: (e) => {
3161
+ e.stopPropagation();
3162
+ void abrirExpander("");
3163
+ },
3164
+ sx: { p: 0, ml: 0.25, color: "primary.main", "&:hover": { backgroundColor: "action.hover" } },
3165
+ children: tipoExpander === "fecha" ? /* @__PURE__ */ jsx16(CalendarMonthIcon, { sx: { fontSize: 16 } }) : tipoExpander === "texto" ? /* @__PURE__ */ jsx16(SearchIcon2, { sx: { fontSize: 16 } }) : /* @__PURE__ */ jsx16(ArrowDropDownIcon, { sx: { fontSize: 20 } })
3166
+ }
3167
+ )
2722
3168
  }
2723
3169
  );
2724
- return currentCellFeedback?.message ? /* @__PURE__ */ jsx13(Tooltip5, { title: currentCellFeedback.message, children: /* @__PURE__ */ jsx13("div", { style: { width: "100%" }, children: editor }) }) : editor;
3170
+ const conMenu = /* @__PURE__ */ jsxs13(Fragment3, { children: [
3171
+ editor,
3172
+ expansion && entradaRef.current && (expansion.tipo === "opciones" ? /* @__PURE__ */ jsx16(
3173
+ MenuDeOpciones,
3174
+ {
3175
+ anclaje: entradaRef.current,
3176
+ opciones: expansion.opciones,
3177
+ busquedaInicial: expansion.busqueda,
3178
+ onElegir: elegirOpcion,
3179
+ onCerrar: cerrarExpansion
3180
+ }
3181
+ ) : expansion.tipo === "fecha" ? /* @__PURE__ */ jsx16(
3182
+ SelectorDeFecha,
3183
+ {
3184
+ anclaje: entradaRef.current,
3185
+ fechaActual: fechaDeValor(row[column.key]),
3186
+ admiteNulo: fieldDefinition.nullable !== false,
3187
+ onElegir: confirmarEnExpansion,
3188
+ onCerrar: cerrarExpansion
3189
+ }
3190
+ ) : /* @__PURE__ */ jsx16(
3191
+ VentanaDeTexto,
3192
+ {
3193
+ anclaje: entradaRef.current,
3194
+ texto: editingValue === null || editingValue === void 0 ? "" : String(editingValue),
3195
+ editable: true,
3196
+ onAceptar: confirmarEnExpansion,
3197
+ onCerrar: cerrarExpansion
3198
+ }
3199
+ ))
3200
+ ] });
3201
+ return currentCellFeedback?.message ? /* @__PURE__ */ jsx16(Tooltip5, { title: currentCellFeedback.message, children: /* @__PURE__ */ jsx16("div", { style: { width: "100%" }, children: conMenu }) }) : conMenu;
2725
3202
  }
2726
3203
  var InputRenderer_default = InputRenderer;
2727
3204
 
2728
3205
  // src/components/grid/renderers/editCellRenderers.tsx
2729
- import { jsx as jsx14 } from "react/jsx-runtime";
3206
+ import { jsx as jsx17 } from "react/jsx-runtime";
2730
3207
  var allColumnsEditCellRenderer = (props, allColumns) => {
2731
3208
  const column = props.column;
2732
3209
  if (!esColumnaPropia(column)) return void 0;
@@ -2743,17 +3220,17 @@ var allColumnsEditCellRenderer = (props, allColumns) => {
2743
3220
  } = defaultColumn;
2744
3221
  if (column.editable) {
2745
3222
  const fieldDefinition = tableDefinition.fields.find((f) => f.name === column.key);
2746
- const isFixedField = fixedFields?.some((f) => f.fieldName === column.key);
3223
+ const isFixedField = valorFijoDe(fixedFields, column.key) !== void 0;
2747
3224
  const isFieldEditableByUI = fieldDefinition?.editable !== false && !isFixedField;
2748
3225
  if (!isFieldEditableByUI) {
2749
3226
  return void 0;
2750
3227
  }
2751
- return /* @__PURE__ */ jsx14(
3228
+ return /* @__PURE__ */ jsx17(
2752
3229
  InputRenderer_default,
2753
3230
  {
2754
3231
  ...props,
2755
3232
  tableDefinition,
2756
- onKeyPress: (rowIndex, columnKey, event, handleCommit) => handleKeyPressInEditor(rowIndex, columnKey, event, allColumns, handleCommit),
3233
+ onKeyPress: (rowIndex, columnKey, event, handleCommit, valorActual) => handleKeyPressInEditor(rowIndex, columnKey, event, allColumns, handleCommit, valorActual),
2757
3234
  registrarEditor,
2758
3235
  setTableData,
2759
3236
  primaryKey
@@ -2779,6 +3256,10 @@ var calcularAnchosDeColumnas = (tableDefinition, filas) => {
2779
3256
  const anchos = /* @__PURE__ */ new Map();
2780
3257
  const muestra = filas.slice(0, 50);
2781
3258
  tableDefinition.fields.forEach((fieldDef) => {
3259
+ if (typeof fieldDef.width === "number" && fieldDef.width > 0) {
3260
+ anchos.set(fieldDef.name, fieldDef.width);
3261
+ return;
3262
+ }
2782
3263
  const headerLabel = fieldDef.label || fieldDef.name;
2783
3264
  const type = fieldDef.typeName?.toLowerCase() || "";
2784
3265
  let typeMinWidth = 60;
@@ -2816,14 +3297,13 @@ var useGridColumns = ({
2816
3297
  toggleFilterVisibility,
2817
3298
  abrirOpcionesDeGrilla
2818
3299
  }) => {
2819
- const columns = useMemo7(() => {
3300
+ const columns = useMemo8(() => {
2820
3301
  if (!tableDefinition) return [];
2821
3302
  const fieldsToShow = tableDefinition.fields.filter((field) => {
2822
- const isFixedField = fixedFields?.some((f) => f.fieldName === field.name);
2823
- return !isFixedField && field.visible !== false;
3303
+ return !columnaOcultaPorFixedField(fixedFields, field.name) && field.visible !== false;
2824
3304
  });
2825
3305
  const defaultColumns = fieldsToShow.map((fieldDef) => {
2826
- const isFixedField = fixedFields?.some((f) => f.fieldName === fieldDef.name);
3306
+ const isFixedField = valorFijoDe(fixedFields, fieldDef.name) !== void 0;
2827
3307
  const isFieldEditable = fieldDef.editable !== false && !isFixedField;
2828
3308
  const colWidth = anchosCalculados.get(fieldDef.name) ?? estimateTextWidth(fieldDef.label || fieldDef.name) + 20;
2829
3309
  const column = {
@@ -2868,7 +3348,7 @@ var useGridColumns = ({
2868
3348
  editable: false,
2869
3349
  resizable: false,
2870
3350
  sortable: false,
2871
- renderHeaderCell: () => React9.createElement(ActionsColumnHeaderCell, {
3351
+ renderHeaderCell: () => React12.createElement(ActionsColumnHeaderCell, {
2872
3352
  toggleFilterVisibility,
2873
3353
  handleDataGridOptions: (e) => abrirOpcionesDeGrilla(e.currentTarget),
2874
3354
  handleAddRow,
@@ -2902,7 +3382,9 @@ var useGridColumns = ({
2902
3382
  return allColumns.map((col) => ({
2903
3383
  ...col,
2904
3384
  colSpan: col.customType === "action" ? colSpanDetalle : col.colSpan,
2905
- editorOptions: { closeOnExternalRowChange: false },
3385
+ // el editor guarda por su cuenta (Enter, Tab, flechas y, al perder el foco, el clic afuera): con commitOnOutsideClick react-data-grid
3386
+ // lo cierra sin guardar y los menús (F9), que son un modal, cuentan como «afuera»
3387
+ editorOptions: { closeOnExternalRowChange: false, commitOnOutsideClick: false },
2906
3388
  renderEditCell: (props) => allColumnsEditCellRenderer(props, allColumns),
2907
3389
  renderCell: (props) => allColumnsCellRenderer(props)
2908
3390
  }));
@@ -2911,25 +3393,25 @@ var useGridColumns = ({
2911
3393
  };
2912
3394
 
2913
3395
  // src/components/grid/ImportDialog.tsx
2914
- import { useState as useState9 } from "react";
3396
+ import { useState as useState12 } from "react";
2915
3397
  import {
2916
3398
  Dialog as Dialog2,
2917
3399
  DialogTitle as DialogTitle2,
2918
3400
  DialogContent as DialogContent2,
2919
3401
  DialogActions as DialogActions2,
2920
- Button as Button3,
3402
+ Button as Button5,
2921
3403
  FormControlLabel,
2922
3404
  Checkbox,
2923
3405
  Box as Box9,
2924
- Typography as Typography5,
3406
+ Typography as Typography7,
2925
3407
  Stack,
2926
3408
  Divider
2927
3409
  } from "@mui/material";
2928
3410
  import FileUploadIcon2 from "@mui/icons-material/FileUpload";
2929
- import { jsx as jsx15, jsxs as jsxs10 } from "react/jsx-runtime";
3411
+ import { jsx as jsx18, jsxs as jsxs14 } from "react/jsx-runtime";
2930
3412
  var ImportDialog = ({ open, onClose, onImport, loading }) => {
2931
- const [file, setFile] = useState9(null);
2932
- const [options, setOptions] = useState9({
3413
+ const [file, setFile] = useState12(null);
3414
+ const [options, setOptions] = useState12({
2933
3415
  skipUnknownFieldsAtImport: false,
2934
3416
  simplificateSpaces: true,
2935
3417
  replaceNewLineWithSpace: true
@@ -2948,15 +3430,15 @@ var ImportDialog = ({ open, onClose, onImport, loading }) => {
2948
3430
  onClose();
2949
3431
  }
2950
3432
  };
2951
- return /* @__PURE__ */ jsxs10(Dialog2, { open, onClose: loading ? void 0 : onClose, maxWidth: "sm", fullWidth: true, children: [
2952
- /* @__PURE__ */ jsxs10(DialogTitle2, { sx: { display: "flex", alignItems: "center", gap: 1 }, children: [
2953
- /* @__PURE__ */ jsx15(FileUploadIcon2, { color: "primary" }),
3433
+ return /* @__PURE__ */ jsxs14(Dialog2, { open, onClose: loading ? void 0 : onClose, maxWidth: "sm", fullWidth: true, children: [
3434
+ /* @__PURE__ */ jsxs14(DialogTitle2, { sx: { display: "flex", alignItems: "center", gap: 1 }, children: [
3435
+ /* @__PURE__ */ jsx18(FileUploadIcon2, { color: "primary" }),
2954
3436
  "Importar datos desde archivo"
2955
3437
  ] }),
2956
- /* @__PURE__ */ jsx15(DialogContent2, { dividers: true, children: /* @__PURE__ */ jsxs10(Stack, { spacing: 3, sx: { mt: 1 }, children: [
2957
- /* @__PURE__ */ jsxs10(Box9, { children: [
2958
- /* @__PURE__ */ jsx15(Typography5, { variant: "subtitle2", gutterBottom: true, fontWeight: "bold", children: "Seleccionar archivo" }),
2959
- /* @__PURE__ */ jsxs10(
3438
+ /* @__PURE__ */ jsx18(DialogContent2, { dividers: true, children: /* @__PURE__ */ jsxs14(Stack, { spacing: 3, sx: { mt: 1 }, children: [
3439
+ /* @__PURE__ */ jsxs14(Box9, { children: [
3440
+ /* @__PURE__ */ jsx18(Typography7, { variant: "subtitle2", gutterBottom: true, fontWeight: "bold", children: "Seleccionar archivo" }),
3441
+ /* @__PURE__ */ jsxs14(
2960
3442
  Box9,
2961
3443
  {
2962
3444
  sx: {
@@ -2969,7 +3451,7 @@ var ImportDialog = ({ open, onClose, onImport, loading }) => {
2969
3451
  position: "relative"
2970
3452
  },
2971
3453
  children: [
2972
- /* @__PURE__ */ jsx15(
3454
+ /* @__PURE__ */ jsx18(
2973
3455
  "input",
2974
3456
  {
2975
3457
  type: "file",
@@ -2986,19 +3468,19 @@ var ImportDialog = ({ open, onClose, onImport, loading }) => {
2986
3468
  }
2987
3469
  }
2988
3470
  ),
2989
- /* @__PURE__ */ jsx15(Typography5, { variant: "body2", color: file ? "textPrimary" : "textSecondary", children: file ? file.name : "Haz clic aqu\xED para seleccionar un archivo" })
3471
+ /* @__PURE__ */ jsx18(Typography7, { variant: "body2", color: file ? "textPrimary" : "textSecondary", children: file ? file.name : "Haz clic aqu\xED para seleccionar un archivo" })
2990
3472
  ]
2991
3473
  }
2992
3474
  )
2993
3475
  ] }),
2994
- /* @__PURE__ */ jsx15(Divider, {}),
2995
- /* @__PURE__ */ jsxs10(Box9, { children: [
2996
- /* @__PURE__ */ jsx15(Typography5, { variant: "subtitle2", gutterBottom: true, fontWeight: "bold", children: "Opciones de importaci\xF3n" }),
2997
- /* @__PURE__ */ jsxs10(Stack, { children: [
2998
- /* @__PURE__ */ jsx15(
3476
+ /* @__PURE__ */ jsx18(Divider, {}),
3477
+ /* @__PURE__ */ jsxs14(Box9, { children: [
3478
+ /* @__PURE__ */ jsx18(Typography7, { variant: "subtitle2", gutterBottom: true, fontWeight: "bold", children: "Opciones de importaci\xF3n" }),
3479
+ /* @__PURE__ */ jsxs14(Stack, { children: [
3480
+ /* @__PURE__ */ jsx18(
2999
3481
  FormControlLabel,
3000
3482
  {
3001
- control: /* @__PURE__ */ jsx15(
3483
+ control: /* @__PURE__ */ jsx18(
3002
3484
  Checkbox,
3003
3485
  {
3004
3486
  checked: options.skipUnknownFieldsAtImport,
@@ -3006,13 +3488,13 @@ var ImportDialog = ({ open, onClose, onImport, loading }) => {
3006
3488
  size: "small"
3007
3489
  }
3008
3490
  ),
3009
- label: /* @__PURE__ */ jsx15(Typography5, { variant: "body2", children: "Omitir campos desconocidos al importar" })
3491
+ label: /* @__PURE__ */ jsx18(Typography7, { variant: "body2", children: "Omitir campos desconocidos al importar" })
3010
3492
  }
3011
3493
  ),
3012
- /* @__PURE__ */ jsx15(
3494
+ /* @__PURE__ */ jsx18(
3013
3495
  FormControlLabel,
3014
3496
  {
3015
- control: /* @__PURE__ */ jsx15(
3497
+ control: /* @__PURE__ */ jsx18(
3016
3498
  Checkbox,
3017
3499
  {
3018
3500
  checked: options.simplificateSpaces,
@@ -3020,13 +3502,13 @@ var ImportDialog = ({ open, onClose, onImport, loading }) => {
3020
3502
  size: "small"
3021
3503
  }
3022
3504
  ),
3023
- label: /* @__PURE__ */ jsx15(Typography5, { variant: "body2", children: "Simplificar espacios" })
3505
+ label: /* @__PURE__ */ jsx18(Typography7, { variant: "body2", children: "Simplificar espacios" })
3024
3506
  }
3025
3507
  ),
3026
- /* @__PURE__ */ jsx15(
3508
+ /* @__PURE__ */ jsx18(
3027
3509
  FormControlLabel,
3028
3510
  {
3029
- control: /* @__PURE__ */ jsx15(
3511
+ control: /* @__PURE__ */ jsx18(
3030
3512
  Checkbox,
3031
3513
  {
3032
3514
  checked: options.replaceNewLineWithSpace,
@@ -3034,21 +3516,21 @@ var ImportDialog = ({ open, onClose, onImport, loading }) => {
3034
3516
  size: "small"
3035
3517
  }
3036
3518
  ),
3037
- label: /* @__PURE__ */ jsx15(Typography5, { variant: "body2", children: "Reemplazar saltos de l\xEDnea con espacios" })
3519
+ label: /* @__PURE__ */ jsx18(Typography7, { variant: "body2", children: "Reemplazar saltos de l\xEDnea con espacios" })
3038
3520
  }
3039
3521
  )
3040
3522
  ] })
3041
3523
  ] })
3042
3524
  ] }) }),
3043
- /* @__PURE__ */ jsxs10(DialogActions2, { sx: { px: 3, py: 2 }, children: [
3044
- /* @__PURE__ */ jsx15(Button3, { onClick: onClose, disabled: loading, children: "Cancelar" }),
3045
- /* @__PURE__ */ jsx15(
3046
- Button3,
3525
+ /* @__PURE__ */ jsxs14(DialogActions2, { sx: { px: 3, py: 2 }, children: [
3526
+ /* @__PURE__ */ jsx18(Button5, { onClick: onClose, disabled: loading, children: "Cancelar" }),
3527
+ /* @__PURE__ */ jsx18(
3528
+ Button5,
3047
3529
  {
3048
3530
  onClick: handleConfirm,
3049
3531
  variant: "contained",
3050
3532
  disabled: !file || loading,
3051
- startIcon: /* @__PURE__ */ jsx15(FileUploadIcon2, {}),
3533
+ startIcon: /* @__PURE__ */ jsx18(FileUploadIcon2, {}),
3052
3534
  children: loading ? "Procesando..." : "Confirmar Importaci\xF3n"
3053
3535
  }
3054
3536
  )
@@ -3057,13 +3539,13 @@ var ImportDialog = ({ open, onClose, onImport, loading }) => {
3057
3539
  };
3058
3540
 
3059
3541
  // src/components/grid/ExportDialog.tsx
3060
- import { useState as useState10 } from "react";
3542
+ import { useState as useState13 } from "react";
3061
3543
  import {
3062
3544
  Dialog as Dialog3,
3063
3545
  DialogTitle as DialogTitle3,
3064
3546
  DialogContent as DialogContent3,
3065
3547
  DialogActions as DialogActions3,
3066
- Button as Button4,
3548
+ Button as Button6,
3067
3549
  FormControl as FormControl2,
3068
3550
  FormLabel,
3069
3551
  RadioGroup,
@@ -3072,12 +3554,12 @@ import {
3072
3554
  Checkbox as Checkbox2,
3073
3555
  FormGroup,
3074
3556
  Box as Box10,
3075
- Typography as Typography6,
3557
+ Typography as Typography8,
3076
3558
  CircularProgress as CircularProgress2
3077
3559
  } from "@mui/material";
3078
3560
  import * as XLSX from "xlsx";
3079
3561
  import typeStore5 from "type-store";
3080
- import { jsx as jsx16, jsxs as jsxs11 } from "react/jsx-runtime";
3562
+ import { jsx as jsx19, jsxs as jsxs15 } from "react/jsx-runtime";
3081
3563
  var ExportDialog = ({
3082
3564
  open,
3083
3565
  onClose,
@@ -3086,13 +3568,13 @@ var ExportDialog = ({
3086
3568
  filteredRows,
3087
3569
  username = "anonymous"
3088
3570
  }) => {
3089
- const [format, setFormat] = useState10("xlsx");
3090
- const [options, setOptions] = useState10({
3571
+ const [format, setFormat] = useState13("xlsx");
3572
+ const [options, setOptions] = useState13({
3091
3573
  fromOtherTables: true,
3092
3574
  readOnly: true,
3093
3575
  hiddens: false
3094
3576
  });
3095
- const [isPreparing, setIsPreparing] = useState10(false);
3577
+ const [isPreparing, setIsPreparing] = useState13(false);
3096
3578
  const handleOptionChange = (event) => {
3097
3579
  setOptions({
3098
3580
  ...options,
@@ -3222,76 +3704,76 @@ var ExportDialog = ({
3222
3704
  URL.revokeObjectURL(url);
3223
3705
  }, 0);
3224
3706
  };
3225
- return /* @__PURE__ */ jsxs11(Dialog3, { open, onClose, maxWidth: "xs", fullWidth: true, children: [
3226
- /* @__PURE__ */ jsx16(DialogTitle3, { children: "Exportar Datos" }),
3227
- /* @__PURE__ */ jsx16(DialogContent3, { children: isPreparing ? /* @__PURE__ */ jsxs11(Box10, { display: "flex", flexDirection: "column", alignItems: "center", py: 4, children: [
3228
- /* @__PURE__ */ jsx16(CircularProgress2, {}),
3229
- /* @__PURE__ */ jsx16(Typography6, { sx: { mt: 2 }, children: "Preparando exportaci\xF3n..." })
3230
- ] }) : /* @__PURE__ */ jsxs11(Box10, { sx: { mt: 1 }, children: [
3231
- /* @__PURE__ */ jsxs11(FormControl2, { component: "fieldset", children: [
3232
- /* @__PURE__ */ jsx16(FormLabel, { component: "legend", children: "Formato" }),
3233
- /* @__PURE__ */ jsxs11(
3707
+ return /* @__PURE__ */ jsxs15(Dialog3, { open, onClose, maxWidth: "xs", fullWidth: true, children: [
3708
+ /* @__PURE__ */ jsx19(DialogTitle3, { children: "Exportar Datos" }),
3709
+ /* @__PURE__ */ jsx19(DialogContent3, { children: isPreparing ? /* @__PURE__ */ jsxs15(Box10, { display: "flex", flexDirection: "column", alignItems: "center", py: 4, children: [
3710
+ /* @__PURE__ */ jsx19(CircularProgress2, {}),
3711
+ /* @__PURE__ */ jsx19(Typography8, { sx: { mt: 2 }, children: "Preparando exportaci\xF3n..." })
3712
+ ] }) : /* @__PURE__ */ jsxs15(Box10, { sx: { mt: 1 }, children: [
3713
+ /* @__PURE__ */ jsxs15(FormControl2, { component: "fieldset", children: [
3714
+ /* @__PURE__ */ jsx19(FormLabel, { component: "legend", children: "Formato" }),
3715
+ /* @__PURE__ */ jsxs15(
3234
3716
  RadioGroup,
3235
3717
  {
3236
3718
  value: format,
3237
3719
  onChange: (e) => setFormat(e.target.value),
3238
3720
  children: [
3239
- /* @__PURE__ */ jsx16(FormControlLabel2, { value: "xlsx", control: /* @__PURE__ */ jsx16(Radio, {}), label: "Excel (.xlsx)" }),
3240
- /* @__PURE__ */ jsx16(FormControlLabel2, { value: "tab", control: /* @__PURE__ */ jsx16(Radio, {}), label: "Tabulado (.tab | )" }),
3241
- /* @__PURE__ */ jsx16(FormControlLabel2, { value: "csv", control: /* @__PURE__ */ jsx16(Radio, {}), label: "CSV (.csv , )" })
3721
+ /* @__PURE__ */ jsx19(FormControlLabel2, { value: "xlsx", control: /* @__PURE__ */ jsx19(Radio, {}), label: "Excel (.xlsx)" }),
3722
+ /* @__PURE__ */ jsx19(FormControlLabel2, { value: "tab", control: /* @__PURE__ */ jsx19(Radio, {}), label: "Tabulado (.tab | )" }),
3723
+ /* @__PURE__ */ jsx19(FormControlLabel2, { value: "csv", control: /* @__PURE__ */ jsx19(Radio, {}), label: "CSV (.csv , )" })
3242
3724
  ]
3243
3725
  }
3244
3726
  )
3245
3727
  ] }),
3246
- /* @__PURE__ */ jsxs11(Box10, { sx: { mt: 3 }, children: [
3247
- /* @__PURE__ */ jsx16(Typography6, { variant: "subtitle2", gutterBottom: true, children: "Opciones de campos:" }),
3248
- /* @__PURE__ */ jsxs11(FormGroup, { children: [
3249
- /* @__PURE__ */ jsx16(
3728
+ /* @__PURE__ */ jsxs15(Box10, { sx: { mt: 3 }, children: [
3729
+ /* @__PURE__ */ jsx19(Typography8, { variant: "subtitle2", gutterBottom: true, children: "Opciones de campos:" }),
3730
+ /* @__PURE__ */ jsxs15(FormGroup, { children: [
3731
+ /* @__PURE__ */ jsx19(
3250
3732
  FormControlLabel2,
3251
3733
  {
3252
- control: /* @__PURE__ */ jsx16(Checkbox2, { checked: options.fromOtherTables, onChange: handleOptionChange, name: "fromOtherTables" }),
3734
+ control: /* @__PURE__ */ jsx19(Checkbox2, { checked: options.fromOtherTables, onChange: handleOptionChange, name: "fromOtherTables" }),
3253
3735
  label: "Desde otras tablas"
3254
3736
  }
3255
3737
  ),
3256
- /* @__PURE__ */ jsx16(
3738
+ /* @__PURE__ */ jsx19(
3257
3739
  FormControlLabel2,
3258
3740
  {
3259
- control: /* @__PURE__ */ jsx16(Checkbox2, { checked: options.readOnly, onChange: handleOptionChange, name: "readOnly" }),
3741
+ control: /* @__PURE__ */ jsx19(Checkbox2, { checked: options.readOnly, onChange: handleOptionChange, name: "readOnly" }),
3260
3742
  label: "Solo lectura"
3261
3743
  }
3262
3744
  ),
3263
- /* @__PURE__ */ jsx16(
3745
+ /* @__PURE__ */ jsx19(
3264
3746
  FormControlLabel2,
3265
3747
  {
3266
- control: /* @__PURE__ */ jsx16(Checkbox2, { checked: options.hiddens, onChange: handleOptionChange, name: "hiddens" }),
3748
+ control: /* @__PURE__ */ jsx19(Checkbox2, { checked: options.hiddens, onChange: handleOptionChange, name: "hiddens" }),
3267
3749
  label: "Ocultos"
3268
3750
  }
3269
3751
  )
3270
3752
  ] })
3271
3753
  ] })
3272
3754
  ] }) }),
3273
- /* @__PURE__ */ jsxs11(DialogActions3, { children: [
3274
- /* @__PURE__ */ jsx16(Button4, { onClick: onClose, disabled: isPreparing, children: "Cancelar" }),
3275
- /* @__PURE__ */ jsx16(Button4, { onClick: handlePrepareExport, variant: "contained", disabled: isPreparing, children: "Descargar" })
3755
+ /* @__PURE__ */ jsxs15(DialogActions3, { children: [
3756
+ /* @__PURE__ */ jsx19(Button6, { onClick: onClose, disabled: isPreparing, children: "Cancelar" }),
3757
+ /* @__PURE__ */ jsx19(Button6, { onClick: handlePrepareExport, variant: "contained", disabled: isPreparing, children: "Descargar" })
3276
3758
  ] })
3277
3759
  ] });
3278
3760
  };
3279
3761
 
3280
3762
  // src/pages/VerticalEditorPage.tsx
3281
- import { useState as useState11, useCallback as useCallback10, useMemo as useMemo8, useRef as useRef5 } from "react";
3763
+ import { useState as useState14, useCallback as useCallback10, useMemo as useMemo9, useRef as useRef6 } from "react";
3282
3764
  import {
3283
3765
  DialogTitle as DialogTitle4,
3284
3766
  DialogContent as DialogContent4,
3285
3767
  DialogActions as DialogActions4,
3286
- Button as Button5,
3768
+ Button as Button7,
3287
3769
  Alert,
3288
3770
  Box as Box11,
3289
3771
  CircularProgress as CircularProgress3,
3290
- IconButton as IconButton3,
3291
- Typography as Typography7
3772
+ IconButton as IconButton5,
3773
+ Typography as Typography9
3292
3774
  } from "@mui/material";
3293
3775
  import CloseIcon from "@mui/icons-material/Close";
3294
- import { jsx as jsx17, jsxs as jsxs12 } from "react/jsx-runtime";
3776
+ import { jsx as jsx20, jsxs as jsxs16 } from "react/jsx-runtime";
3295
3777
  var VerticalEditorPage = ({
3296
3778
  tableName,
3297
3779
  tableDefinition,
@@ -3302,20 +3784,20 @@ var VerticalEditorPage = ({
3302
3784
  onClose
3303
3785
  }) => {
3304
3786
  const { saveRecord } = useTableRecordSave();
3305
- const [internalIsNewRow, setInternalIsNewRow] = useState11(isNewRow);
3306
- const [formData, setFormData] = useState11(initialData);
3307
- const [lastSavedData, setLastSavedData] = useState11(initialData);
3308
- const [validityMap, setValidityMap] = useState11({});
3309
- const [globalError, setGlobalError] = useState11(null);
3310
- const [isSaving, setIsSaving] = useState11(false);
3311
- const [fieldFeedback, setFieldFeedback] = useState11({});
3312
- const feedbackTimersRef = useRef5({});
3787
+ const [internalIsNewRow, setInternalIsNewRow] = useState14(isNewRow);
3788
+ const [formData, setFormData] = useState14(initialData);
3789
+ const [lastSavedData, setLastSavedData] = useState14(initialData);
3790
+ const [validityMap, setValidityMap] = useState14({});
3791
+ const [globalError, setGlobalError] = useState14(null);
3792
+ const [isSaving, setIsSaving] = useState14(false);
3793
+ const [fieldFeedback, setFieldFeedback] = useState14({});
3794
+ const feedbackTimersRef = useRef6({});
3313
3795
  const handleFieldChange = useCallback10((fieldName, newValue, isValid) => {
3314
3796
  setFormData((prev) => ({ ...prev, [fieldName]: newValue }));
3315
3797
  setValidityMap((prev) => ({ ...prev, [fieldName]: isValid }));
3316
3798
  setGlobalError(null);
3317
3799
  }, []);
3318
- const isFormValid = useMemo8(() => {
3800
+ const isFormValid = useMemo9(() => {
3319
3801
  for (const key in validityMap) {
3320
3802
  if (validityMap[key] === false) return false;
3321
3803
  }
@@ -3350,7 +3832,6 @@ var VerticalEditorPage = ({
3350
3832
  setGlobalError(null);
3351
3833
  try {
3352
3834
  const response = await saveRecord({
3353
- tableName,
3354
3835
  tableDefinition,
3355
3836
  isNewRow: internalIsNewRow,
3356
3837
  formData: potentialUpdatedRow,
@@ -3419,21 +3900,21 @@ var VerticalEditorPage = ({
3419
3900
  tableDefinition,
3420
3901
  onSaveSuccess
3421
3902
  ]);
3422
- return /* @__PURE__ */ jsxs12(Box11, { sx: { p: 2, display: "flex", flexDirection: "column", height: "100%" }, children: [
3423
- /* @__PURE__ */ jsxs12(DialogTitle4, { sx: { px: 0, pt: 0, display: "flex", justifyContent: "space-between", alignItems: "center" }, children: [
3424
- /* @__PURE__ */ jsxs12(Typography7, { component: "div", variant: "h6", children: [
3903
+ return /* @__PURE__ */ jsxs16(Box11, { sx: { p: 2, display: "flex", flexDirection: "column", height: "100%" }, children: [
3904
+ /* @__PURE__ */ jsxs16(DialogTitle4, { sx: { px: 0, pt: 0, display: "flex", justifyContent: "space-between", alignItems: "center" }, children: [
3905
+ /* @__PURE__ */ jsxs16(Typography9, { component: "div", variant: "h6", children: [
3425
3906
  isNewRow ? "Nuevo Registro" : "Editar Registro",
3426
3907
  " - ",
3427
3908
  tableDefinition.title || tableName
3428
3909
  ] }),
3429
- /* @__PURE__ */ jsx17(IconButton3, { onClick: onClose, size: "small", edge: "end", children: /* @__PURE__ */ jsx17(CloseIcon, {}) })
3910
+ /* @__PURE__ */ jsx20(IconButton5, { onClick: onClose, size: "small", edge: "end", children: /* @__PURE__ */ jsx20(CloseIcon, {}) })
3430
3911
  ] }),
3431
- /* @__PURE__ */ jsxs12(DialogContent4, { dividers: true, sx: { px: 2, flexGrow: 1, py: 1 }, children: [
3432
- globalError && /* @__PURE__ */ jsx17(Alert, { severity: "error", sx: { mb: 2 }, children: globalError }),
3433
- /* @__PURE__ */ jsx17(Box11, { sx: { display: "flex", flexDirection: "column", gap: 0.5 }, children: tableDefinition.fields.map((field) => {
3912
+ /* @__PURE__ */ jsxs16(DialogContent4, { dividers: true, sx: { px: 2, flexGrow: 1, py: 1 }, children: [
3913
+ globalError && /* @__PURE__ */ jsx20(Alert, { severity: "error", sx: { mb: 2 }, children: globalError }),
3914
+ /* @__PURE__ */ jsx20(Box11, { sx: { display: "flex", flexDirection: "column", gap: 0.5 }, children: tableDefinition.fields.map((field) => {
3434
3915
  const isFixed = fixedFields?.some((ff) => ff.fieldName === field.name);
3435
3916
  const isMandatory = field.nullable === false || tableDefinition.primaryKey.includes(field.name);
3436
- return /* @__PURE__ */ jsx17(Box11, { sx: { width: "100%", maxWidth: "100%" }, children: /* @__PURE__ */ jsx17(
3917
+ return /* @__PURE__ */ jsx20(Box11, { sx: { width: "100%", maxWidth: "100%" }, children: /* @__PURE__ */ jsx20(
3437
3918
  TypedField,
3438
3919
  {
3439
3920
  fieldDef: field,
@@ -3447,22 +3928,89 @@ var VerticalEditorPage = ({
3447
3928
  ) }, field.name);
3448
3929
  }) })
3449
3930
  ] }),
3450
- /* @__PURE__ */ jsxs12(DialogActions4, { sx: { px: 0, pb: 0, pt: 2, justifyContent: "space-between", alignItems: "center" }, children: [
3451
- /* @__PURE__ */ jsxs12(Box11, { children: [
3452
- isSaving && /* @__PURE__ */ jsx17(CircularProgress3, { size: 20, sx: { ml: 2 } }),
3453
- /* @__PURE__ */ jsx17("span", { style: { marginLeft: 10, fontSize: "0.8rem", color: "#666" }, children: isSaving ? "Guardando..." : "Cambios auto-guardados" })
3931
+ /* @__PURE__ */ jsxs16(DialogActions4, { sx: { px: 0, pb: 0, pt: 2, justifyContent: "space-between", alignItems: "center" }, children: [
3932
+ /* @__PURE__ */ jsxs16(Box11, { children: [
3933
+ isSaving && /* @__PURE__ */ jsx20(CircularProgress3, { size: 20, sx: { ml: 2 } }),
3934
+ /* @__PURE__ */ jsx20("span", { style: { marginLeft: 10, fontSize: "0.8rem", color: "#666" }, children: isSaving ? "Guardando..." : "Cambios auto-guardados" })
3454
3935
  ] }),
3455
- /* @__PURE__ */ jsx17(Button5, { variant: "outlined", onClick: onClose, children: "Cerrar" })
3936
+ /* @__PURE__ */ jsx20(Button7, { variant: "outlined", onClick: onClose, children: "Cerrar" })
3456
3937
  ] })
3457
3938
  ] });
3458
3939
  };
3459
3940
 
3941
+ // src/utils/parametrosDeTabla.ts
3942
+ import JSON4all3 from "json4all";
3943
+ function esRegistro(valor) {
3944
+ return typeof valor === "object" && valor !== null && !Array.isArray(valor) && !(valor instanceof Date);
3945
+ }
3946
+ var CODIFICADOS = ["ff", "fc", "td", "pf"];
3947
+ function parametrosDeDireccion(direccion) {
3948
+ const resultado = {};
3949
+ direccion.split("&").forEach((par) => {
3950
+ const sinMarca = par.replace(/^[#?]/, "");
3951
+ const igual = sinMarca.indexOf("=");
3952
+ if (igual === -1) return;
3953
+ const nombre = sinMarca.slice(0, igual);
3954
+ try {
3955
+ const texto = decodeURIComponent(sinMarca.slice(igual + 1));
3956
+ resultado[nombre] = CODIFICADOS.includes(nombre) ? JSON4all3.parse(texto) : texto;
3957
+ } catch (err) {
3958
+ console.warn(`No se pudo interpretar el par\xE1metro '${nombre}' de la direcci\xF3n:`, err);
3959
+ }
3960
+ });
3961
+ return resultado;
3962
+ }
3963
+ function aFixedFields(valor) {
3964
+ if (Array.isArray(valor)) {
3965
+ return valor.flatMap((par) => {
3966
+ if (!esRegistro(par) || typeof par.fieldName !== "string") return [];
3967
+ const fixedField = { fieldName: par.fieldName, value: par.value };
3968
+ if (par.until !== void 0) fixedField.until = par.until;
3969
+ if (typeof par.range === "boolean") fixedField.range = par.range;
3970
+ if (typeof par.show === "boolean") fixedField.show = par.show;
3971
+ return [fixedField];
3972
+ });
3973
+ }
3974
+ if (esRegistro(valor)) return Object.entries(valor).map(([fieldName, value]) => ({ fieldName, value }));
3975
+ return [];
3976
+ }
3977
+ function aFiltrosIniciales(valor) {
3978
+ if (!Array.isArray(valor) || valor.length === 0) return [];
3979
+ const filas = Array.isArray(valor[0]) ? valor : [valor];
3980
+ return filas.map((fila) => Array.isArray(fila) ? fila.flatMap((condicion) => {
3981
+ if (!esRegistro(condicion) || typeof condicion.operator !== "string") return [];
3982
+ const columna = condicion.column ?? condicion.fieldName;
3983
+ return typeof columna === "string" ? [{ column: columna, operator: condicion.operator, value: condicion.value }] : [];
3984
+ }) : []).filter((fila) => fila.length > 0);
3985
+ }
3986
+ function parametrosDeTabla(item, direccion) {
3987
+ const origen = { ...item, ...parametrosDeDireccion(direccion) };
3988
+ const parametros = {};
3989
+ const fixedFields = aFixedFields(origen.ff ?? origen.fixedFields);
3990
+ if (fixedFields.length > 0) parametros.fixedFields = fixedFields;
3991
+ const filterColumns = aFiltrosIniciales(origen.fc);
3992
+ if (filterColumns.length > 0) parametros.filterColumns = filterColumns;
3993
+ if (esRegistro(origen.td)) parametros.tableDef = origen.td;
3994
+ if (esRegistro(origen.pf)) parametros.parameterFunctions = origen.pf;
3995
+ if (typeof origen.pick === "string") parametros.pick = origen.pick;
3996
+ if (typeof origen.label === "string") parametros.label = origen.label;
3997
+ return parametros;
3998
+ }
3999
+ function fusionar(base, cambios) {
4000
+ const resultado = { ...base };
4001
+ for (const [clave, valor] of Object.entries(cambios)) {
4002
+ const actual = Reflect.get(resultado, clave);
4003
+ Reflect.set(resultado, clave, esRegistro(actual) && esRegistro(valor) ? fusionar(actual, valor) : valor);
4004
+ }
4005
+ return resultado;
4006
+ }
4007
+
3460
4008
  // src/rutaBase.ts
3461
4009
  var baseDelBundler = import.meta.env?.BASE_URL ?? "/";
3462
4010
  var rutaBase = baseDelBundler.replace(/\/+$/, "");
3463
4011
 
3464
4012
  // src/components/grid/GenericDataGrid.tsx
3465
- import { jsx as jsx18, jsxs as jsxs13 } from "react/jsx-runtime";
4013
+ import { jsx as jsx21, jsxs as jsxs17 } from "react/jsx-runtime";
3466
4014
  var SUMMARY_ROW_HEIGHT = 35;
3467
4015
  var FILTER_ROW_HEIGHT = 35;
3468
4016
  var HEADER_ROW_HEIGHT = 30;
@@ -3483,7 +4031,7 @@ var cargasEnCurso = /* @__PURE__ */ new Map();
3483
4031
  var StaticAncestorGrid = ({ ancestor, index, fieldsToHide }) => {
3484
4032
  const theme = useTheme4();
3485
4033
  const { tableDefinition, row } = ancestor;
3486
- const columns = useMemo9(() => {
4034
+ const columns = useMemo10(() => {
3487
4035
  const filteredFields = tableDefinition.fields.filter(
3488
4036
  (field) => !fieldsToHide?.some((ff) => ff.fieldName === field.name)
3489
4037
  );
@@ -3494,8 +4042,8 @@ var StaticAncestorGrid = ({ ancestor, index, fieldsToHide }) => {
3494
4042
  name: field.label || cambiarGuionesBajosPorEspacios(field.name),
3495
4043
  width: 150,
3496
4044
  editable: false,
3497
- renderHeaderCell: () => /* @__PURE__ */ jsx18(Box12, { sx: { p: 0.5, height: "100%", display: "flex", alignItems: "center" }, children: /* @__PURE__ */ jsx18(
3498
- Typography8,
4045
+ renderHeaderCell: () => /* @__PURE__ */ jsx21(Box12, { sx: { p: 0.5, height: "100%", display: "flex", alignItems: "center" }, children: /* @__PURE__ */ jsx21(
4046
+ Typography10,
3499
4047
  {
3500
4048
  variant: "caption",
3501
4049
  sx: {
@@ -3506,11 +4054,11 @@ var StaticAncestorGrid = ({ ancestor, index, fieldsToHide }) => {
3506
4054
  children: field.label || cambiarGuionesBajosPorEspacios(field.name)
3507
4055
  }
3508
4056
  ) }),
3509
- renderCell: (props) => /* @__PURE__ */ jsx18(Box12, { sx: { px: 1, height: "100%", display: "flex", alignItems: "center" }, children: /* @__PURE__ */ jsx18(Typography8, { variant: "body2", sx: { fontSize: "0.875rem" }, noWrap: true, children: String(props.row[field.name] ?? "") }) })
4057
+ renderCell: (props) => /* @__PURE__ */ jsx21(Box12, { sx: { px: 1, height: "100%", display: "flex", alignItems: "center" }, children: /* @__PURE__ */ jsx21(Typography10, { variant: "body2", sx: { fontSize: "0.875rem" }, noWrap: true, children: String(props.row[field.name] ?? "") }) })
3510
4058
  };
3511
4059
  });
3512
4060
  }, [tableDefinition, fieldsToHide]);
3513
- return /* @__PURE__ */ jsxs13(Box12, { sx: {
4061
+ return /* @__PURE__ */ jsxs17(Box12, { sx: {
3514
4062
  mb: 1.5,
3515
4063
  ml: index * 4,
3516
4064
  // El primer ancestro (index 0) no tiene margen, los siguientes sí
@@ -3521,7 +4069,7 @@ var StaticAncestorGrid = ({ ancestor, index, fieldsToHide }) => {
3521
4069
  boxShadow: theme.shadows[1],
3522
4070
  bgcolor: "background.paper"
3523
4071
  }, children: [
3524
- /* @__PURE__ */ jsx18(Box12, { sx: {
4072
+ /* @__PURE__ */ jsx21(Box12, { sx: {
3525
4073
  bgcolor: "primary.main",
3526
4074
  color: "primary.contrastText",
3527
4075
  px: 1.5,
@@ -3532,8 +4080,8 @@ var StaticAncestorGrid = ({ ancestor, index, fieldsToHide }) => {
3532
4080
  alignItems: "center",
3533
4081
  fontWeight: "bold",
3534
4082
  gap: 1
3535
- }, children: /* @__PURE__ */ jsx18(Typography8, { variant: "subtitle2", component: "div", children: cambiarGuionesBajosPorEspacios(ancestor.tableName) }) }),
3536
- /* @__PURE__ */ jsx18(
4083
+ }, children: /* @__PURE__ */ jsx21(Typography10, { variant: "subtitle2", component: "div", children: cambiarGuionesBajosPorEspacios(ancestor.tableName) }) }),
4084
+ /* @__PURE__ */ jsx21(
3537
4085
  DataGrid,
3538
4086
  {
3539
4087
  className: "rdg-light",
@@ -3550,6 +4098,10 @@ var StaticAncestorGrid = ({ ancestor, index, fieldsToHide }) => {
3550
4098
  var GenericDataGrid = ({
3551
4099
  tableName,
3552
4100
  fixedFields: fixedFieldsRecibidos,
4101
+ filterColumns: filterColumnsRecibidos,
4102
+ tableDef: tableDefRecibido,
4103
+ parameterFunctions: parameterFunctionsRecibido,
4104
+ pick: pickRecibido,
3553
4105
  gridStyles,
3554
4106
  onOpenDetail,
3555
4107
  ancestors = SIN_ANCESTROS,
@@ -3562,36 +4114,42 @@ var GenericDataGrid = ({
3562
4114
  altoMaximoDetalle
3563
4115
  }) => {
3564
4116
  const claveFixedFields = JSON.stringify(fixedFieldsRecibidos ?? null);
3565
- const fixedFields = useMemo9(() => fixedFieldsRecibidos, [claveFixedFields]);
4117
+ const fixedFields = useMemo10(() => fixedFieldsRecibidos, [claveFixedFields]);
4118
+ const claveParametros = JSON.stringify([filterColumnsRecibidos ?? null, tableDefRecibido ?? null, parameterFunctionsRecibido ?? null, pickRecibido ?? null]);
4119
+ const parametros = useMemo10(
4120
+ () => ({ filterColumns: filterColumnsRecibidos, tableDef: tableDefRecibido, parameterFunctions: parameterFunctionsRecibido, pick: pickRecibido }),
4121
+ [claveParametros]
4122
+ // eslint-disable-line react-hooks/exhaustive-deps
4123
+ );
3566
4124
  const cacheHeredado = useContext4(CacheGrillasContext);
3567
- const [cachePropio] = useState12(() => /* @__PURE__ */ new Map());
4125
+ const [cachePropio] = useState15(() => /* @__PURE__ */ new Map());
3568
4126
  const cache = cacheHeredado ?? cachePropio;
3569
- const [guardada] = useState12(() => claveCache ? cache.get(claveCache) : void 0);
3570
- const claveCargadaRef = useRef6(guardada ? `${tableName}|${claveFixedFields}` : null);
3571
- const [tableDefinition, setTableDefinition] = useState12(guardada?.tableDefinition ?? null);
3572
- const [tableData, setTableData] = useState12(guardada?.tableData ?? []);
3573
- const [cargandoInicial, setCargandoInicial] = useState12(!guardada);
3574
- const [errorDeCarga, setErrorDeCarga] = useState12(null);
3575
- const [anchosCalculados, setAnchosCalculados] = useState12(() => guardada?.anchosCalculados ?? /* @__PURE__ */ new Map());
3576
- const [detallesAbiertos, setDetallesAbiertos] = useState12(guardada?.detallesAbiertos ?? []);
3577
- const [altosDetalle, setAltosDetalle] = useState12(() => guardada?.altosDetalle ?? /* @__PURE__ */ new Map());
3578
- const [anchosDetalle, setAnchosDetalle] = useState12(() => /* @__PURE__ */ new Map());
3579
- const [selectedRows, setSelectedRows] = useState12(() => /* @__PURE__ */ new Set());
3580
- const [, setSelectedCell] = useState12(void 0);
3581
- const [estadoGrilla] = useState12(crearEstadoGrilla);
4127
+ const [guardada] = useState15(() => claveCache ? cache.get(claveCache) : void 0);
4128
+ const claveCargadaRef = useRef7(guardada ? `${tableName}|${claveFixedFields}|${claveParametros}` : null);
4129
+ const [tableDefinition, setTableDefinition] = useState15(guardada?.tableDefinition ?? null);
4130
+ const [tableData, setTableData] = useState15(guardada?.tableData ?? []);
4131
+ const [cargandoInicial, setCargandoInicial] = useState15(!guardada);
4132
+ const [errorDeCarga, setErrorDeCarga] = useState15(null);
4133
+ const [anchosCalculados, setAnchosCalculados] = useState15(() => guardada?.anchosCalculados ?? /* @__PURE__ */ new Map());
4134
+ const [detallesAbiertos, setDetallesAbiertos] = useState15(guardada?.detallesAbiertos ?? []);
4135
+ const [altosDetalle, setAltosDetalle] = useState15(() => guardada?.altosDetalle ?? /* @__PURE__ */ new Map());
4136
+ const [anchosDetalle, setAnchosDetalle] = useState15(() => /* @__PURE__ */ new Map());
4137
+ const [selectedRows, setSelectedRows] = useState15(() => /* @__PURE__ */ new Set());
4138
+ const [, setSelectedCell] = useState15(void 0);
4139
+ const [estadoGrilla] = useState15(crearEstadoGrilla);
3582
4140
  const theme = useTheme4();
3583
- const [openDataGridOptions, setOpenDataGridOptions] = useState12(false);
3584
- const [dataGridOptionsAnchorEl, setDataGridOptionsAnchorEl] = useState12(null);
3585
- const [exitingRowIds, setExitingRowIds] = useState12(/* @__PURE__ */ new Set());
4141
+ const [openDataGridOptions, setOpenDataGridOptions] = useState15(false);
4142
+ const [dataGridOptionsAnchorEl, setDataGridOptionsAnchorEl] = useState15(null);
4143
+ const [exitingRowIds, setExitingRowIds] = useState15(/* @__PURE__ */ new Set());
3586
4144
  const { showError } = useSnackbar();
3587
4145
  const { username: usuario } = useClientContext();
3588
- const dataGridRef = useRef6(null);
3589
- const rowAtEditStartRef = useRef6(null);
3590
- const [openImportDialog, setOpenImportDialog] = useState12(false);
3591
- const [openExportDialog, setOpenExportDialog] = useState12(false);
3592
- const [columnWidths, setColumnWidths] = useState12(() => /* @__PURE__ */ new Map());
4146
+ const dataGridRef = useRef7(null);
4147
+ const rowAtEditStartRef = useRef7(null);
4148
+ const [openImportDialog, setOpenImportDialog] = useState15(false);
4149
+ const [openExportDialog, setOpenExportDialog] = useState15(false);
4150
+ const [columnWidths, setColumnWidths] = useState15(() => /* @__PURE__ */ new Map());
3593
4151
  const { callApi, callApiUpload, loading } = useApiCall();
3594
- const primaryKey = useMemo9(() => {
4152
+ const primaryKey = useMemo10(() => {
3595
4153
  if (!tableDefinition) return ["id"];
3596
4154
  return tableDefinition.primaryKey && tableDefinition.primaryKey.length > 0 ? tableDefinition.primaryKey : ["id"];
3597
4155
  }, [tableDefinition]);
@@ -3605,13 +4163,14 @@ var GenericDataGrid = ({
3605
4163
  setFilters,
3606
4164
  isFilterRowVisible,
3607
4165
  toggleFilterVisibility,
4166
+ aplicarFiltrosIniciales,
3608
4167
  filteredRows,
3609
4168
  summaryData,
3610
4169
  resetView
3611
4170
  } = useGridDataView({ tableData, tableDefinition });
3612
- const abiertos = useMemo9(() => new Set(detallesAbiertos), [detallesAbiertos]);
3613
- const filasDetalleRef = useRef6(/* @__PURE__ */ new Map());
3614
- const filasMostradas = useMemo9(() => {
4171
+ const abiertos = useMemo10(() => new Set(detallesAbiertos), [detallesAbiertos]);
4172
+ const filasDetalleRef = useRef7(/* @__PURE__ */ new Map());
4173
+ const filasMostradas = useMemo10(() => {
3615
4174
  const detailTables = tableDefinition?.detailTables ?? [];
3616
4175
  if (abiertos.size === 0 || detailTables.length === 0) return filteredRows;
3617
4176
  const anteriores = filasDetalleRef.current;
@@ -3639,7 +4198,7 @@ var GenericDataGrid = ({
3639
4198
  return filas;
3640
4199
  }, [filteredRows, abiertos, tableDefinition, primaryKey]);
3641
4200
  const altoDeDetalle = useCallback11((clave) => altosDetalle.get(clave) ?? ALTO_INICIAL_DETALLE, [altosDetalle]);
3642
- const altoDetalles = useMemo9(
4201
+ const altoDetalles = useMemo10(
3643
4202
  () => filasMostradas.reduce((total, row) => esFilaDetalle(row) ? total + altoDeDetalle(row.clave) : total, 0),
3644
4203
  [filasMostradas, altoDeDetalle]
3645
4204
  );
@@ -3685,6 +4244,13 @@ var GenericDataGrid = ({
3685
4244
  filasVisiblesMax,
3686
4245
  conPie
3687
4246
  });
4247
+ const [contenidoDeCelda, setContenidoDeCelda] = useState15(null);
4248
+ const verContenido = useCallback11((anclaje, texto) => setContenidoDeCelda({ anclaje, texto }), []);
4249
+ const cerrarContenidoDeCelda = useCallback11(() => {
4250
+ const anclaje = contenidoDeCelda?.anclaje;
4251
+ setContenidoDeCelda(null);
4252
+ setTimeout(() => anclaje?.focus(), 0);
4253
+ }, [contenidoDeCelda]);
3688
4254
  const { handleCellDoubleClick, handleCellClick, handleCellKeyDown, handleCellMouseDown, handleKeyPressInEditor, registrarEditor, handleSelectedCellChange, handleRowsChange } = useGridEvents({
3689
4255
  dataGridRef,
3690
4256
  filteredRows: filasMostradas,
@@ -3693,10 +4259,11 @@ var GenericDataGrid = ({
3693
4259
  tableDefinition,
3694
4260
  setSelectedCell,
3695
4261
  setTableData,
3696
- setSortColumns
4262
+ setSortColumns,
4263
+ verContenido
3697
4264
  });
3698
- const tableNameAnteriorRef = useRef6(tableName);
3699
- useEffect5(() => {
4265
+ const tableNameAnteriorRef = useRef7(tableName);
4266
+ useEffect6(() => {
3700
4267
  if (tableNameAnteriorRef.current === tableName) return;
3701
4268
  tableNameAnteriorRef.current = tableName;
3702
4269
  setDetallesAbiertos([]);
@@ -3710,8 +4277,8 @@ var GenericDataGrid = ({
3710
4277
  setExitingRowIds(/* @__PURE__ */ new Set());
3711
4278
  setColumnWidths(/* @__PURE__ */ new Map());
3712
4279
  }, [tableName, estadoGrilla, resetView]);
3713
- useEffect5(() => {
3714
- const claveCarga = `${tableName}|${claveFixedFields}`;
4280
+ useEffect6(() => {
4281
+ const claveCarga = `${tableName}|${claveFixedFields}|${claveParametros}`;
3715
4282
  if (claveCargadaRef.current === claveCarga) {
3716
4283
  if (guardada) setSortColumns(guardada.sortColumns);
3717
4284
  return;
@@ -3721,7 +4288,7 @@ var GenericDataGrid = ({
3721
4288
  setCargandoInicial(true);
3722
4289
  setErrorDeCarga(null);
3723
4290
  try {
3724
- const clavePedido = `${tableName}|${claveFixedFields}`;
4291
+ const clavePedido = `${tableName}|${claveFixedFields}|${JSON.stringify([parametros.parameterFunctions ?? null, parametros.pick ?? null])}`;
3725
4292
  let pedido = cargasEnCurso.get(clavePedido);
3726
4293
  if (!pedido) {
3727
4294
  const nuevo = (async () => {
@@ -3735,7 +4302,10 @@ var GenericDataGrid = ({
3735
4302
  const data2 = requerido(
3736
4303
  await callApi("table_data", {
3737
4304
  table: tableName,
3738
- fixedFields: validFixedFields ?? []
4305
+ fixedFields: validFixedFields ?? [],
4306
+ // como backend-plus (TableConnector.getData); solo si vienen, para no cambiarle el pedido a quien no los usa
4307
+ ...parametros.parameterFunctions ? { paramfun: parametros.parameterFunctions } : {},
4308
+ ...parametros.pick !== void 0 ? { pick: parametros.pick } : {}
3739
4309
  }, { isCritical: true }),
3740
4310
  `los datos de '${tableName}'`
3741
4311
  );
@@ -3748,13 +4318,17 @@ var GenericDataGrid = ({
3748
4318
  nuevo.then(sacar, sacar);
3749
4319
  pedido = nuevo;
3750
4320
  }
3751
- const { definition, data } = await pedido;
4321
+ const { definition: definicionDelServidor, data } = await pedido;
3752
4322
  if (!vigente) return;
3753
4323
  claveCargadaRef.current = claveCarga;
4324
+ const definition = parametros.tableDef ? fusionar(definicionDelServidor, parametros.tableDef) : definicionDelServidor;
3754
4325
  setTableDefinition(definition);
3755
4326
  setSortColumns(getInitialSortColumns(definition));
3756
4327
  setAnchosCalculados(calcularAnchosDeColumnas(definition, data));
3757
4328
  setTableData(data);
4329
+ const filasDeFiltros = parametros.filterColumns ?? aFiltrosIniciales(definition.filterColumns);
4330
+ if (filasDeFiltros.length > 1) console.warn(`'${tableName}': varias filas de filtros (alternativas) todav\xEDa no est\xE1n soportadas; se aplica la primera`);
4331
+ if (filasDeFiltros.length > 0) aplicarFiltrosIniciales(filasDeFiltros[0], definition);
3758
4332
  } catch (err) {
3759
4333
  if (!vigente) return;
3760
4334
  setTableDefinition(null);
@@ -3770,12 +4344,12 @@ var GenericDataGrid = ({
3770
4344
  return () => {
3771
4345
  vigente = false;
3772
4346
  };
3773
- }, [tableName, claveFixedFields, fixedFields, showError, callApi, getInitialSortColumns, setSortColumns, guardada]);
3774
- useEffect5(() => {
4347
+ }, [tableName, claveFixedFields, fixedFields, claveParametros, parametros, showError, callApi, getInitialSortColumns, setSortColumns, aplicarFiltrosIniciales, guardada]);
4348
+ useEffect6(() => {
3775
4349
  if (!claveCache || !tableDefinition || cargandoInicial) return;
3776
4350
  cache.set(claveCache, { tableDefinition, tableData, anchosCalculados, sortColumns, detallesAbiertos, altosDetalle });
3777
4351
  }, [cache, claveCache, tableDefinition, tableData, anchosCalculados, sortColumns, detallesAbiertos, altosDetalle, cargandoInicial]);
3778
- useEffect5(() => {
4352
+ useEffect6(() => {
3779
4353
  let timer = null;
3780
4354
  const desuscribir = estadoGrilla.suscribir(() => {
3781
4355
  const hayExitos = Array.from(estadoGrilla.obtenerFeedback().values()).some((f) => f.type === "success");
@@ -3848,9 +4422,9 @@ var GenericDataGrid = ({
3848
4422
  onOpenDetail(detailTable.table, allFixedFields, label, newAncestors);
3849
4423
  }, [onOpenDetail, tableDefinition, fixedFields, ancestors]);
3850
4424
  const abrirWScreenEnPestana = useCallback11((row, detailTable) => {
3851
- const parametros = new URLSearchParams();
3852
- calcularFixedFieldsDetalle(detailTable, row).forEach((ff) => parametros.set(ff.fieldName, String(ff.value)));
3853
- window.open(`${window.location.origin}${rutaBase}/wScreens/${detailTable.wScreen}?${parametros}`, "_blank");
4425
+ const parametros2 = new URLSearchParams();
4426
+ calcularFixedFieldsDetalle(detailTable, row).forEach((ff) => parametros2.set(ff.fieldName, String(ff.value)));
4427
+ window.open(`${window.location.origin}${rutaBase}/wScreens/${detailTable.wScreen}?${parametros2}`, "_blank");
3854
4428
  }, []);
3855
4429
  const alternarDetalle = useCallback11((row, rowId, detailTable, enOtraPestana) => {
3856
4430
  if (enOtraPestana && detailTable.wScreen) {
@@ -3864,8 +4438,8 @@ var GenericDataGrid = ({
3864
4438
  const clave = claveDetalle(rowId, detailTable);
3865
4439
  setDetallesAbiertos((anteriores) => anteriores.includes(clave) ? anteriores.filter((c) => c !== clave) : [...anteriores, clave]);
3866
4440
  }, [onOpenDetail, abrirDetalleEnPestana, abrirWScreenEnPestana]);
3867
- const [medidas, setMedidas] = useState12(null);
3868
- useEffect5(() => {
4441
+ const [medidas, setMedidas] = useState15(null);
4442
+ useEffect6(() => {
3869
4443
  const elemento = dataGridRef.current?.element;
3870
4444
  if (!elemento) return;
3871
4445
  const medir = () => setMedidas((anteriores) => {
@@ -3878,8 +4452,8 @@ var GenericDataGrid = ({
3878
4452
  return () => observador.disconnect();
3879
4453
  }, [tableDefinition, cargandoInicial]);
3880
4454
  const anchoVisible = medidas?.ancho ?? null;
3881
- const [altoDeVentana, setAltoDeVentana] = useState12(null);
3882
- useEffect5(() => {
4455
+ const [altoDeVentana, setAltoDeVentana] = useState15(null);
4456
+ useEffect6(() => {
3883
4457
  if (anidada) return;
3884
4458
  const elemento = dataGridRef.current?.element;
3885
4459
  if (!elemento) return;
@@ -3900,13 +4474,13 @@ var GenericDataGrid = ({
3900
4474
  }, [altoMaximoDetalleEfectivo]);
3901
4475
  const renderDetalle = useCallback11((fila) => {
3902
4476
  const { detailTable } = fila;
3903
- return /* @__PURE__ */ jsx18(
4477
+ return /* @__PURE__ */ jsx21(
3904
4478
  "div",
3905
4479
  {
3906
4480
  className: "fpr-detalle",
3907
4481
  style: { maxWidth: anchoVisible ? anchoVisible - 2 : void 0 },
3908
4482
  onKeyDown: (e) => e.stopPropagation(),
3909
- children: detailTable.table ? /* @__PURE__ */ jsx18(
4483
+ children: detailTable.table ? /* @__PURE__ */ jsx21(
3910
4484
  GenericDataGrid,
3911
4485
  {
3912
4486
  tableName: detailTable.table,
@@ -3919,7 +4493,7 @@ var GenericDataGrid = ({
3919
4493
  onOpenDetail,
3920
4494
  ancestors: tableDefinition ? [...ancestors, { tableName: tableDefinition.name, row: fila.filaPadre, tableDefinition, fixedFields: fila.fixedFields }] : ancestors
3921
4495
  }
3922
- ) : detailTable.wScreen ? /* @__PURE__ */ jsx18(
4496
+ ) : detailTable.wScreen ? /* @__PURE__ */ jsx21(
3923
4497
  DetalleWScreen,
3924
4498
  {
3925
4499
  fila,
@@ -3927,7 +4501,7 @@ var GenericDataGrid = ({
3927
4501
  onAlto: (alto) => cambiarAltoDetalle(fila.clave, alto),
3928
4502
  onAncho: (ancho) => cambiarAnchoDetalle(fila.clave, ancho)
3929
4503
  }
3930
- ) : /* @__PURE__ */ jsxs13(Alert2, { severity: "warning", children: [
4504
+ ) : /* @__PURE__ */ jsxs17(Alert2, { severity: "warning", children: [
3931
4505
  "El detalle '",
3932
4506
  detailTable.abr,
3933
4507
  "' no tiene ni tabla ni wScreen."
@@ -3935,9 +4509,9 @@ var GenericDataGrid = ({
3935
4509
  }
3936
4510
  );
3937
4511
  }, [anchoVisible, claveCache, tableName, cambiarAltoDetalle, cambiarAnchoDetalle, altoMaximoDetalleEfectivo, onOpenDetail, tableDefinition, ancestors]);
3938
- const detallesGrilla = useMemo9(() => ({ abiertos, alternarDetalle, renderDetalle }), [abiertos, alternarDetalle, renderDetalle]);
4512
+ const detallesGrilla = useMemo10(() => ({ abiertos, alternarDetalle, renderDetalle }), [abiertos, alternarDetalle, renderDetalle]);
3939
4513
  const altoDeseado = cargandoInicial ? ALTO_INICIAL_DETALLE : gridHeight + ALTO_TITULO_ANIDADA + 8;
3940
- useEffect5(() => {
4514
+ useEffect6(() => {
3941
4515
  onAltoDeseado?.(altoDeseado);
3942
4516
  }, [onAltoDeseado, altoDeseado]);
3943
4517
  const rowKeyGetter = useCallback11((row) => esFilaDetalle(row) ? `detalle:${row.clave}` : getPrimaryKeyValues(row, primaryKey), [primaryKey]);
@@ -3946,7 +4520,7 @@ var GenericDataGrid = ({
3946
4520
  (row) => esFilaDetalle(row) ? "fpr-fila-detalle" : exitingRowIds.has(getPrimaryKeyValues(row, primaryKey)) ? "fpr-fila-saliendo" : void 0,
3947
4521
  [exitingRowIds, primaryKey]
3948
4522
  );
3949
- const anchoContenido = useMemo9(() => {
4523
+ const anchoContenido = useMemo10(() => {
3950
4524
  if (!anidada || columns.length === 0) return void 0;
3951
4525
  const sumaColumnas = columns.reduce((total, col) => {
3952
4526
  const medido = columnWidths.get(col.key)?.width;
@@ -3956,12 +4530,12 @@ var GenericDataGrid = ({
3956
4530
  const anchoDetalleMax = detallesAbiertos.reduce((max, clave) => Math.max(max, anchosDetalle.get(clave) ?? 0), 0);
3957
4531
  return Math.max(ANCHO_MINIMO_ANIDADA, propio, anchoDetalleMax > 0 ? anchoDetalleMax + SANGRIA_DETALLE + (medidas?.barra ?? 0) + 2 : 0);
3958
4532
  }, [anidada, columns, columnWidths, medidas?.barra, detallesAbiertos, anchosDetalle]);
3959
- useEffect5(() => {
4533
+ useEffect6(() => {
3960
4534
  if (anchoContenido !== void 0) onAnchoDeseado?.(anchoContenido);
3961
4535
  }, [onAnchoDeseado, anchoContenido]);
3962
- const estiloGrilla = useMemo9(() => ({ height: "100%", width: "100%", boxSizing: "border-box", ...gridStyles }), [gridStyles]);
3963
- const bottomSummaryRows = useMemo9(() => conPie ? [bottomSummaryRow] : [], [conPie, bottomSummaryRow]);
3964
- const vistaGrilla = useMemo9(() => ({ isFilterRowVisible }), [isFilterRowVisible]);
4536
+ const estiloGrilla = useMemo10(() => ({ height: "100%", width: "100%", boxSizing: "border-box", ...gridStyles }), [gridStyles]);
4537
+ const bottomSummaryRows = useMemo10(() => conPie ? [bottomSummaryRow] : [], [conPie, bottomSummaryRow]);
4538
+ const vistaGrilla = useMemo10(() => ({ isFilterRowVisible }), [isFilterRowVisible]);
3965
4539
  const getFallBackMessage = () => {
3966
4540
  if (tableData.length === 0) {
3967
4541
  return "No hay filas para mostrar";
@@ -3973,19 +4547,19 @@ var GenericDataGrid = ({
3973
4547
  };
3974
4548
  const fallBackMessage = getFallBackMessage();
3975
4549
  if (cargandoInicial) {
3976
- return /* @__PURE__ */ jsxs13(Box12, { display: "flex", justifyContent: "center", alignItems: "center", minHeight: "200px", children: [
3977
- /* @__PURE__ */ jsx18(CircularProgress4, {}),
3978
- /* @__PURE__ */ jsx18(Typography8, { variant: "h6", sx: { ml: 2 }, children: "Cargando tabla..." })
4550
+ return /* @__PURE__ */ jsxs17(Box12, { display: "flex", justifyContent: "center", alignItems: "center", minHeight: "200px", children: [
4551
+ /* @__PURE__ */ jsx21(CircularProgress4, {}),
4552
+ /* @__PURE__ */ jsx21(Typography10, { variant: "h6", sx: { ml: 2 }, children: "Cargando tabla..." })
3979
4553
  ] });
3980
4554
  }
3981
4555
  if (errorDeCarga) {
3982
- return /* @__PURE__ */ jsx18(Box12, { display: "flex", justifyContent: "center", alignItems: "center", minHeight: "200px", children: /* @__PURE__ */ jsx18(Alert2, { severity: "error", children: errorDeCarga }) });
4556
+ return /* @__PURE__ */ jsx21(Box12, { display: "flex", justifyContent: "center", alignItems: "center", minHeight: "200px", children: /* @__PURE__ */ jsx21(Alert2, { severity: "error", children: errorDeCarga }) });
3983
4557
  }
3984
4558
  if (!tableDefinition) {
3985
- return /* @__PURE__ */ jsx18(Box12, { display: "flex", justifyContent: "center", alignItems: "center", minHeight: "200px", children: /* @__PURE__ */ jsx18(Alert2, { severity: "warning", children: "No se pudo cargar la definici\xF3n de la tabla." }) });
4559
+ return /* @__PURE__ */ jsx21(Box12, { display: "flex", justifyContent: "center", alignItems: "center", minHeight: "200px", children: /* @__PURE__ */ jsx21(Alert2, { severity: "warning", children: "No se pudo cargar la definici\xF3n de la tabla." }) });
3986
4560
  }
3987
- return /* @__PURE__ */ jsx18(CacheGrillasContext.Provider, { value: cache, children: /* @__PURE__ */ jsxs13(Box12, { sx: { pt: anidada ? 0 : 2, display: "flex", flexDirection: "column", height: "100%", boxSizing: "border-box", width: anchoContenido ?? void 0, maxWidth: "100%" }, children: [
3988
- !anidada && ancestors.length > 0 && /* @__PURE__ */ jsx18(Box12, { sx: { px: 2, pt: 0, pb: 1, display: "flex", flexDirection: "column" }, children: ancestors.map((ancestor, index) => /* @__PURE__ */ jsx18(
4561
+ return /* @__PURE__ */ jsx21(CacheGrillasContext.Provider, { value: cache, children: /* @__PURE__ */ jsxs17(Box12, { sx: { pt: anidada ? 0 : 2, display: "flex", flexDirection: "column", height: "100%", boxSizing: "border-box", width: anchoContenido ?? void 0, maxWidth: "100%" }, children: [
4562
+ !anidada && ancestors.length > 0 && /* @__PURE__ */ jsx21(Box12, { sx: { px: 2, pt: 0, pb: 1, display: "flex", flexDirection: "column" }, children: ancestors.map((ancestor, index) => /* @__PURE__ */ jsx21(
3989
4563
  StaticAncestorGrid,
3990
4564
  {
3991
4565
  ancestor,
@@ -3994,7 +4568,7 @@ var GenericDataGrid = ({
3994
4568
  },
3995
4569
  index
3996
4570
  )) }),
3997
- /* @__PURE__ */ jsxs13(
4571
+ /* @__PURE__ */ jsxs17(
3998
4572
  Box12,
3999
4573
  {
4000
4574
  sx: {
@@ -4017,16 +4591,16 @@ var GenericDataGrid = ({
4017
4591
  gap: 1
4018
4592
  },
4019
4593
  children: [
4020
- /* @__PURE__ */ jsxs13(Typography8, { variant: "subtitle2", component: "div", children: [
4594
+ /* @__PURE__ */ jsxs17(Typography10, { variant: "subtitle2", component: "div", children: [
4021
4595
  titulo ?? cambiarGuionesBajosPorEspacios(tableDefinition.title || tableDefinition.name),
4022
4596
  " - ",
4023
4597
  filteredRows.length === tableData.length ? `${tableData.length} registros` : `${filteredRows.length} (F)`
4024
4598
  ] }),
4025
- loading && /* @__PURE__ */ jsx18(CircularProgress4, { size: 14, color: "inherit" })
4599
+ loading && /* @__PURE__ */ jsx21(CircularProgress4, { size: 14, color: "inherit" })
4026
4600
  ]
4027
4601
  }
4028
4602
  ),
4029
- /* @__PURE__ */ jsxs13(
4603
+ /* @__PURE__ */ jsxs17(
4030
4604
  Box12,
4031
4605
  {
4032
4606
  sx: {
@@ -4045,7 +4619,7 @@ var GenericDataGrid = ({
4045
4619
  pb: anidada ? 0 : 3
4046
4620
  },
4047
4621
  children: [
4048
- /* @__PURE__ */ jsx18(EstadoGrillaContext.Provider, { value: estadoGrilla, children: /* @__PURE__ */ jsx18(VistaGrillaContext.Provider, { value: vistaGrilla, children: /* @__PURE__ */ jsx18(DetallesGrillaContext.Provider, { value: detallesGrilla, children: /* @__PURE__ */ jsx18(
4622
+ /* @__PURE__ */ jsx21(EstadoGrillaContext.Provider, { value: estadoGrilla, children: /* @__PURE__ */ jsx21(VistaGrillaContext.Provider, { value: vistaGrilla, children: /* @__PURE__ */ jsx21(DetallesGrillaContext.Provider, { value: detallesGrilla, children: /* @__PURE__ */ jsx21(
4049
4623
  DataGrid,
4050
4624
  {
4051
4625
  className: "rdg-light",
@@ -4075,7 +4649,7 @@ var GenericDataGrid = ({
4075
4649
  onCellKeyDown: handleCellKeyDown
4076
4650
  }
4077
4651
  ) }) }) }),
4078
- fallBackMessage && /* @__PURE__ */ jsx18(
4652
+ fallBackMessage && /* @__PURE__ */ jsx21(
4079
4653
  Box12,
4080
4654
  {
4081
4655
  sx: {
@@ -4092,13 +4666,13 @@ var GenericDataGrid = ({
4092
4666
  zIndex: tableData.length === 0 ? 10 : 1
4093
4667
  // Mantenemos el zIndex superior para el estado vacío total
4094
4668
  },
4095
- children: /* @__PURE__ */ jsx18(Typography8, { variant: "body2", color: "textSecondary", children: fallBackMessage })
4669
+ children: /* @__PURE__ */ jsx21(Typography10, { variant: "body2", color: "textSecondary", children: fallBackMessage })
4096
4670
  }
4097
4671
  )
4098
4672
  ]
4099
4673
  }
4100
4674
  ),
4101
- /* @__PURE__ */ jsx18(
4675
+ /* @__PURE__ */ jsx21(
4102
4676
  ExportDialog,
4103
4677
  {
4104
4678
  open: openExportDialog,
@@ -4109,7 +4683,7 @@ var GenericDataGrid = ({
4109
4683
  username: usuario || "anonymous"
4110
4684
  }
4111
4685
  ),
4112
- /* @__PURE__ */ jsx18(
4686
+ /* @__PURE__ */ jsx21(
4113
4687
  ConfirmDialog,
4114
4688
  {
4115
4689
  open: openConfirmDialog,
@@ -4118,7 +4692,7 @@ var GenericDataGrid = ({
4118
4692
  message: rowToDelete && rowToDelete[NEW_ROW_INDICATOR] ? `\xBFEst\xE1s seguro de que quieres eliminar esta nueva fila (ID: ${getPrimaryKeyValues(rowToDelete, primaryKey)}) localmente?` : rowToDelete ? `\xBFEst\xE1s seguro de que quieres eliminar la fila con ID: ${getPrimaryKeyValues(rowToDelete, primaryKey)} de la base de datos? Esta acci\xF3n es irreversible.` : "\xBFEst\xE1s seguro de que quieres eliminar este registro? Esta acci\xF3n es irreversible."
4119
4693
  }
4120
4694
  ),
4121
- /* @__PURE__ */ jsx18(
4695
+ /* @__PURE__ */ jsx21(
4122
4696
  DataGridOptionsDialog,
4123
4697
  {
4124
4698
  open: openDataGridOptions,
@@ -4127,7 +4701,7 @@ var GenericDataGrid = ({
4127
4701
  anchorEl: dataGridOptionsAnchorEl
4128
4702
  }
4129
4703
  ),
4130
- /* @__PURE__ */ jsx18(
4704
+ /* @__PURE__ */ jsx21(
4131
4705
  ImportDialog,
4132
4706
  {
4133
4707
  open: openImportDialog,
@@ -4136,14 +4710,14 @@ var GenericDataGrid = ({
4136
4710
  loading
4137
4711
  }
4138
4712
  ),
4139
- /* @__PURE__ */ jsx18(
4713
+ /* @__PURE__ */ jsx21(
4140
4714
  Dialog4,
4141
4715
  {
4142
4716
  open: openVerticalEditDialog,
4143
4717
  onClose: () => setOpenVerticalEditDialog(false),
4144
4718
  maxWidth: "sm",
4145
4719
  fullWidth: true,
4146
- children: rowToEditVertical && /* @__PURE__ */ jsx18(
4720
+ children: rowToEditVertical && /* @__PURE__ */ jsx21(
4147
4721
  VerticalEditorPage,
4148
4722
  {
4149
4723
  tableName,
@@ -4187,36 +4761,37 @@ var GenericDataGrid = ({
4187
4761
  }
4188
4762
  )
4189
4763
  }
4190
- )
4764
+ ),
4765
+ contenidoDeCelda && /* @__PURE__ */ jsx21(VentanaDeTexto, { anclaje: contenidoDeCelda.anclaje, texto: contenidoDeCelda.texto, editable: false, onAceptar: cerrarContenidoDeCelda, onCerrar: cerrarContenidoDeCelda })
4191
4766
  ] }) });
4192
4767
  };
4193
4768
  var GenericDataGrid_default = GenericDataGrid;
4194
4769
 
4195
4770
  // src/App.tsx
4196
- import React28, { useEffect as useEffect16, useMemo as useMemo14 } from "react";
4197
- import { BrowserRouter, Routes, Route, useLocation as useLocation7, Navigate as Navigate4, Outlet as Outlet2 } from "react-router-dom";
4771
+ import React32, { useEffect as useEffect18, useMemo as useMemo16 } from "react";
4772
+ import { BrowserRouter, Routes, Route, useLocation as useLocation8, Navigate as Navigate4, Outlet as Outlet2 } from "react-router-dom";
4198
4773
 
4199
4774
  // src/components/MainLayout.tsx
4200
- import { useEffect as useEffect8 } from "react";
4775
+ import { useEffect as useEffect9 } from "react";
4201
4776
  import { Outlet } from "react-router-dom";
4202
4777
  import {
4203
4778
  Box as Box14,
4204
4779
  AppBar,
4205
4780
  Toolbar,
4206
- Typography as Typography10,
4207
- Button as Button6,
4781
+ Typography as Typography12,
4782
+ Button as Button8,
4208
4783
  Drawer,
4209
4784
  CssBaseline,
4210
- IconButton as IconButton4,
4785
+ IconButton as IconButton6,
4211
4786
  useTheme as useTheme5,
4212
4787
  useMediaQuery
4213
4788
  } from "@mui/material";
4214
4789
 
4215
4790
  // src/contexts/AppContext.tsx
4216
- import { createContext as createContext4, useContext as useContext5, useState as useState13, useEffect as useEffect6, useCallback as useCallback12, useMemo as useMemo10, useRef as useRef7 } from "react";
4791
+ import { createContext as createContext4, useContext as useContext5, useState as useState16, useEffect as useEffect7, useCallback as useCallback12, useMemo as useMemo11, useRef as useRef8 } from "react";
4217
4792
  import { useLocation, useNavigate } from "react-router-dom";
4218
4793
  import { useSelector as useSelector2, useDispatch as useDispatch2 } from "react-redux";
4219
- import { jsx as jsx19 } from "react/jsx-runtime";
4794
+ import { jsx as jsx22 } from "react/jsx-runtime";
4220
4795
  var AuthContext = createContext4(void 0);
4221
4796
  var useApp = () => {
4222
4797
  const context = useContext5(AuthContext);
@@ -4228,10 +4803,10 @@ var useApp = () => {
4228
4803
  };
4229
4804
  var AppProvider = ({ children, publicPaths = [] }) => {
4230
4805
  console.log("AppProvider rendered/re-rendered");
4231
- const [isLoggedIn, setIsLoggedIn] = useState13(false);
4232
- const [showSessionExpiredMessage, setShowSessionExpiredMessage] = useState13(false);
4233
- const isRedirectingRef = useRef7(false);
4234
- const huboSesionRef = useRef7(false);
4806
+ const [isLoggedIn, setIsLoggedIn] = useState16(false);
4807
+ const [showSessionExpiredMessage, setShowSessionExpiredMessage] = useState16(false);
4808
+ const isRedirectingRef = useRef8(false);
4809
+ const huboSesionRef = useRef8(false);
4235
4810
  const dispatch = useDispatch2();
4236
4811
  const clientContext = useSelector2((state) => state.clientContext);
4237
4812
  if (clientContext.status === "succeeded") huboSesionRef.current = true;
@@ -4288,14 +4863,14 @@ var AppProvider = ({ children, publicPaths = [] }) => {
4288
4863
  }
4289
4864
  }
4290
4865
  }, [dispatch, clientContext.status, showSessionExpiredMessage, isCurrentPathPublic]);
4291
- useEffect6(() => {
4866
+ useEffect7(() => {
4292
4867
  checkSession();
4293
4868
  const intervalId = setInterval(checkSession, 15 * 1e3);
4294
4869
  return () => {
4295
4870
  clearInterval(intervalId);
4296
4871
  };
4297
4872
  }, [checkSession]);
4298
- const authContextValue = useMemo10(() => ({
4873
+ const authContextValue = useMemo11(() => ({
4299
4874
  isLoggedIn,
4300
4875
  setIsLoggedIn,
4301
4876
  checkSession,
@@ -4310,7 +4885,7 @@ var AppProvider = ({ children, publicPaths = [] }) => {
4310
4885
  setShowSessionExpiredMessage,
4311
4886
  handleExpiredSessionRedirect
4312
4887
  ]);
4313
- return /* @__PURE__ */ jsx19(AuthContext.Provider, { value: authContextValue, children });
4888
+ return /* @__PURE__ */ jsx22(AuthContext.Provider, { value: authContextValue, children });
4314
4889
  };
4315
4890
 
4316
4891
  // src/components/MainLayout.tsx
@@ -4319,8 +4894,8 @@ import MenuIcon from "@mui/icons-material/Menu";
4319
4894
  import ChevronLeftIcon from "@mui/icons-material/ChevronLeft";
4320
4895
 
4321
4896
  // src/components/SideMenu.tsx
4322
- import React15, { useEffect as useEffect7 } from "react";
4323
- import { List as List2, ListItem, ListItemButton as ListItemButton2, ListItemIcon as ListItemIcon2, ListItemText as ListItemText2, Divider as Divider2, Box as Box13, Typography as Typography9, Collapse } from "@mui/material";
4897
+ import React18, { useEffect as useEffect8 } from "react";
4898
+ import { List as List3, ListItem, ListItemButton as ListItemButton3, ListItemIcon as ListItemIcon2, ListItemText as ListItemText2, Divider as Divider2, Box as Box13, Typography as Typography11, Collapse } from "@mui/material";
4324
4899
  import ExpandLess from "@mui/icons-material/ExpandLess";
4325
4900
  import ExpandMore from "@mui/icons-material/ExpandMore";
4326
4901
  import TableChartIcon from "@mui/icons-material/TableChart";
@@ -4353,7 +4928,7 @@ function itemInicial(menu) {
4353
4928
  }
4354
4929
 
4355
4930
  // src/components/SideMenu.tsx
4356
- import { jsx as jsx20, jsxs as jsxs14 } from "react/jsx-runtime";
4931
+ import { jsx as jsx23, jsxs as jsxs18 } from "react/jsx-runtime";
4357
4932
  var MenuListItem = ({ item, level, onMenuItemClick }) => {
4358
4933
  const navigate = useNavigate2();
4359
4934
  const location = useLocation2();
@@ -4372,17 +4947,17 @@ var MenuListItem = ({ item, level, onMenuItemClick }) => {
4372
4947
  const getIcon = (item2) => {
4373
4948
  switch (item2.menuType) {
4374
4949
  case "table":
4375
- return /* @__PURE__ */ jsx20(TableChartIcon, { sx: { color: blue[700] } });
4950
+ return /* @__PURE__ */ jsx23(TableChartIcon, { sx: { color: blue[700] } });
4376
4951
  case "proc":
4377
- return /* @__PURE__ */ jsx20(DnsIcon, { sx: { color: teal[700] } });
4952
+ return /* @__PURE__ */ jsx23(DnsIcon, { sx: { color: teal[700] } });
4378
4953
  case "menu":
4379
- return /* @__PURE__ */ jsx20(FolderIcon, { sx: { color: orange[800] } });
4954
+ return /* @__PURE__ */ jsx23(FolderIcon, { sx: { color: orange[800] } });
4380
4955
  default:
4381
4956
  const WScreenComponent = wScreens[item2.menuType];
4382
4957
  if (WScreenComponent !== void 0) {
4383
- return /* @__PURE__ */ jsx20(DesktopWindowsIcon, { sx: { color: grey[700] } });
4958
+ return /* @__PURE__ */ jsx23(DesktopWindowsIcon, { sx: { color: grey[700] } });
4384
4959
  }
4385
- return /* @__PURE__ */ jsx20(WarningAmberIcon3, { sx: { color: red[500] } });
4960
+ return /* @__PURE__ */ jsx23(WarningAmberIcon3, { sx: { color: red[500] } });
4386
4961
  }
4387
4962
  };
4388
4963
  const currentPath = location.pathname;
@@ -4396,27 +4971,27 @@ var MenuListItem = ({ item, level, onMenuItemClick }) => {
4396
4971
  } else if (item.menuType !== "menu") {
4397
4972
  isSelected = currentPath.startsWith(`/wScreens/${item.menuType}`) || currentPath.startsWith(`/wScreens-fallback/${item.menuType}`);
4398
4973
  }
4399
- const itemRef = React15.useRef(null);
4400
- useEffect7(() => {
4974
+ const itemRef = React18.useRef(null);
4975
+ useEffect8(() => {
4401
4976
  if (isSelected && itemRef.current) {
4402
4977
  itemRef.current.scrollIntoView({ behavior: "smooth", block: "nearest" });
4403
4978
  }
4404
4979
  }, [isSelected]);
4405
- return /* @__PURE__ */ jsxs14("div", { ref: itemRef, children: [
4406
- /* @__PURE__ */ jsxs14(
4407
- ListItemButton2,
4980
+ return /* @__PURE__ */ jsxs18("div", { ref: itemRef, children: [
4981
+ /* @__PURE__ */ jsxs18(
4982
+ ListItemButton3,
4408
4983
  {
4409
4984
  onClick: handleClick,
4410
4985
  sx: { pl: level * 2 },
4411
4986
  selected: isSelected,
4412
4987
  children: [
4413
- /* @__PURE__ */ jsx20(ListItemIcon2, { sx: { minWidth: "38px" }, children: getIcon(item) }),
4414
- /* @__PURE__ */ jsx20(ListItemText2, { primary: item.label || item.name }),
4415
- item.menuType === "menu" ? open ? /* @__PURE__ */ jsx20(ExpandLess, {}) : /* @__PURE__ */ jsx20(ExpandMore, {}) : null
4988
+ /* @__PURE__ */ jsx23(ListItemIcon2, { sx: { minWidth: "38px" }, children: getIcon(item) }),
4989
+ /* @__PURE__ */ jsx23(ListItemText2, { primary: item.label || item.name }),
4990
+ item.menuType === "menu" ? open ? /* @__PURE__ */ jsx23(ExpandLess, {}) : /* @__PURE__ */ jsx23(ExpandMore, {}) : null
4416
4991
  ]
4417
4992
  }
4418
4993
  ),
4419
- item.menuType === "menu" && /* @__PURE__ */ jsx20(Collapse, { in: open, timeout: "auto", unmountOnExit: true, children: /* @__PURE__ */ jsx20(List2, { component: "div", disablePadding: true, children: item.menuContent.map((subItem) => /* @__PURE__ */ jsx20(
4994
+ item.menuType === "menu" && /* @__PURE__ */ jsx23(Collapse, { in: open, timeout: "auto", unmountOnExit: true, children: /* @__PURE__ */ jsx23(List3, { component: "div", disablePadding: true, children: item.menuContent.map((subItem) => /* @__PURE__ */ jsx23(
4420
4995
  MenuListItem,
4421
4996
  {
4422
4997
  item: subItem,
@@ -4440,9 +5015,9 @@ var SideMenu = ({ onMenuItemClick }) => {
4440
5015
  dispatch(setAllSubMenusOpen(!isMostlyOpen));
4441
5016
  };
4442
5017
  if (!clientContext || !clientContext.menu) {
4443
- return /* @__PURE__ */ jsx20(Box13, { sx: { p: 2, textAlign: "center" }, children: /* @__PURE__ */ jsx20(Typography9, { variant: "body2", color: "text.secondary", children: "Cargando men\xFA..." }) });
5018
+ return /* @__PURE__ */ jsx23(Box13, { sx: { p: 2, textAlign: "center" }, children: /* @__PURE__ */ jsx23(Typography11, { variant: "body2", color: "text.secondary", children: "Cargando men\xFA..." }) });
4444
5019
  }
4445
- useEffect7(() => {
5020
+ useEffect8(() => {
4446
5021
  if (!clientContext?.menu) return;
4447
5022
  const expandParents = (items, targetPath, parentNames = []) => {
4448
5023
  const pathParts = targetPath.split("/");
@@ -4471,13 +5046,13 @@ var SideMenu = ({ onMenuItemClick }) => {
4471
5046
  };
4472
5047
  expandParents(clientContext.menu, location.pathname);
4473
5048
  }, [location.pathname, clientContext, dispatch]);
4474
- return /* @__PURE__ */ jsxs14(Box13, { sx: { width: "100%", flexShrink: 0 }, children: [
4475
- clientContext.menu.some((item) => item.menuType === "menu") && /* @__PURE__ */ jsx20(ListItem, { disablePadding: true, children: /* @__PURE__ */ jsxs14(ListItemButton2, { onClick: handleToggleAllSubMenus, children: [
4476
- /* @__PURE__ */ jsx20(ListItemIcon2, { sx: { minWidth: "38px" }, children: isMostlyOpen ? /* @__PURE__ */ jsx20(UnfoldLessIcon, {}) : /* @__PURE__ */ jsx20(UnfoldMoreIcon, {}) }),
4477
- /* @__PURE__ */ jsx20(ListItemText2, { primary: isMostlyOpen ? "colapsar " : "expandir" })
5049
+ return /* @__PURE__ */ jsxs18(Box13, { sx: { width: "100%", flexShrink: 0 }, children: [
5050
+ clientContext.menu.some((item) => item.menuType === "menu") && /* @__PURE__ */ jsx23(ListItem, { disablePadding: true, children: /* @__PURE__ */ jsxs18(ListItemButton3, { onClick: handleToggleAllSubMenus, children: [
5051
+ /* @__PURE__ */ jsx23(ListItemIcon2, { sx: { minWidth: "38px" }, children: isMostlyOpen ? /* @__PURE__ */ jsx23(UnfoldLessIcon, {}) : /* @__PURE__ */ jsx23(UnfoldMoreIcon, {}) }),
5052
+ /* @__PURE__ */ jsx23(ListItemText2, { primary: isMostlyOpen ? "colapsar " : "expandir" })
4478
5053
  ] }) }),
4479
- /* @__PURE__ */ jsx20(Divider2, {}),
4480
- /* @__PURE__ */ jsx20(List2, { children: clientContext.menu.map((menuItem) => /* @__PURE__ */ jsx20(
5054
+ /* @__PURE__ */ jsx23(Divider2, {}),
5055
+ /* @__PURE__ */ jsx23(List3, { children: clientContext.menu.map((menuItem) => /* @__PURE__ */ jsx23(
4481
5056
  MenuListItem,
4482
5057
  {
4483
5058
  item: menuItem,
@@ -4519,7 +5094,7 @@ var useLogout = () => {
4519
5094
  var useLogout_default = useLogout;
4520
5095
 
4521
5096
  // src/components/MainLayout.tsx
4522
- import { jsx as jsx21, jsxs as jsxs15 } from "react/jsx-runtime";
5097
+ import { jsx as jsx24, jsxs as jsxs19 } from "react/jsx-runtime";
4523
5098
  var drawerWidth = 240;
4524
5099
  var MainLayout = () => {
4525
5100
  const { clientContext } = useApp();
@@ -4528,7 +5103,7 @@ var MainLayout = () => {
4528
5103
  const dispatch = useAppDispatch();
4529
5104
  const theme = useTheme5();
4530
5105
  const isMobile = useMediaQuery(theme.breakpoints.down("sm"));
4531
- useEffect8(() => {
5106
+ useEffect9(() => {
4532
5107
  if (isMobile && isDrawerOpen) {
4533
5108
  dispatch(setDrawerOpen(false));
4534
5109
  }
@@ -4542,11 +5117,11 @@ var MainLayout = () => {
4542
5117
  }
4543
5118
  };
4544
5119
  if (!clientContext) {
4545
- return /* @__PURE__ */ jsx21(Box14, { sx: { display: "flex", justifyContent: "center", alignItems: "center", height: "100vh" }, children: /* @__PURE__ */ jsx21(Typography10, { children: "Cargando dise\xF1o de la aplicaci\xF3n..." }) });
5120
+ return /* @__PURE__ */ jsx24(Box14, { sx: { display: "flex", justifyContent: "center", alignItems: "center", height: "100vh" }, children: /* @__PURE__ */ jsx24(Typography12, { children: "Cargando dise\xF1o de la aplicaci\xF3n..." }) });
4546
5121
  }
4547
- return /* @__PURE__ */ jsxs15(Box14, { sx: { display: "flex", height: "100vh" }, children: [
4548
- /* @__PURE__ */ jsx21(CssBaseline, {}),
4549
- /* @__PURE__ */ jsx21(
5122
+ return /* @__PURE__ */ jsxs19(Box14, { sx: { display: "flex", height: "100vh" }, children: [
5123
+ /* @__PURE__ */ jsx24(CssBaseline, {}),
5124
+ /* @__PURE__ */ jsx24(
4550
5125
  AppBar,
4551
5126
  {
4552
5127
  position: "fixed",
@@ -4565,9 +5140,9 @@ var MainLayout = () => {
4565
5140
  })
4566
5141
  }
4567
5142
  },
4568
- children: /* @__PURE__ */ jsxs15(Toolbar, { children: [
4569
- /* @__PURE__ */ jsx21(
4570
- IconButton4,
5143
+ children: /* @__PURE__ */ jsxs19(Toolbar, { children: [
5144
+ /* @__PURE__ */ jsx24(
5145
+ IconButton6,
4571
5146
  {
4572
5147
  color: "inherit",
4573
5148
  "aria-label": "open drawer",
@@ -4576,10 +5151,10 @@ var MainLayout = () => {
4576
5151
  sx: {
4577
5152
  marginRight: 2
4578
5153
  },
4579
- children: isDrawerOpen ? /* @__PURE__ */ jsx21(ChevronLeftIcon, {}) : /* @__PURE__ */ jsx21(MenuIcon, {})
5154
+ children: isDrawerOpen ? /* @__PURE__ */ jsx24(ChevronLeftIcon, {}) : /* @__PURE__ */ jsx24(MenuIcon, {})
4580
5155
  }
4581
5156
  ),
4582
- !isDrawerOpen && /* @__PURE__ */ jsx21(
5157
+ !isDrawerOpen && /* @__PURE__ */ jsx24(
4583
5158
  "img",
4584
5159
  {
4585
5160
  src: `${envConfig.backendUrl}/img/logo-128.png`,
@@ -4587,21 +5162,21 @@ var MainLayout = () => {
4587
5162
  style: { height: "32px", marginRight: "12px", objectFit: "contain" }
4588
5163
  }
4589
5164
  ),
4590
- /* @__PURE__ */ jsx21(Typography10, { variant: "h6", noWrap: true, component: "div", sx: { flexGrow: 1 }, children: isDrawerOpen ? "" : clientContext.config.title }),
4591
- /* @__PURE__ */ jsx21(Typography10, { variant: "subtitle1", component: "div", sx: { mr: 2 }, children: clientContext.username }),
4592
- /* @__PURE__ */ jsx21(
4593
- Button6,
5165
+ /* @__PURE__ */ jsx24(Typography12, { variant: "h6", noWrap: true, component: "div", sx: { flexGrow: 1 }, children: isDrawerOpen ? "" : clientContext.config.title }),
5166
+ /* @__PURE__ */ jsx24(Typography12, { variant: "subtitle1", component: "div", sx: { mr: 2 }, children: clientContext.username }),
5167
+ /* @__PURE__ */ jsx24(
5168
+ Button8,
4594
5169
  {
4595
5170
  color: "inherit",
4596
5171
  onClick: logout,
4597
- startIcon: /* @__PURE__ */ jsx21(LogoutIcon, {}),
5172
+ startIcon: /* @__PURE__ */ jsx24(LogoutIcon, {}),
4598
5173
  children: "Salir"
4599
5174
  }
4600
5175
  )
4601
5176
  ] })
4602
5177
  }
4603
5178
  ),
4604
- /* @__PURE__ */ jsxs15(
5179
+ /* @__PURE__ */ jsxs19(
4605
5180
  Drawer,
4606
5181
  {
4607
5182
  variant: "persistent",
@@ -4618,7 +5193,7 @@ var MainLayout = () => {
4618
5193
  }
4619
5194
  },
4620
5195
  children: [
4621
- /* @__PURE__ */ jsxs15(
5196
+ /* @__PURE__ */ jsxs19(
4622
5197
  Toolbar,
4623
5198
  {
4624
5199
  sx: {
@@ -4631,7 +5206,7 @@ var MainLayout = () => {
4631
5206
  gap: 1.5
4632
5207
  },
4633
5208
  children: [
4634
- /* @__PURE__ */ jsx21(
5209
+ /* @__PURE__ */ jsx24(
4635
5210
  "img",
4636
5211
  {
4637
5212
  src: `${envConfig.backendUrl}/img/logo-128.png`,
@@ -4639,15 +5214,15 @@ var MainLayout = () => {
4639
5214
  style: { height: "32px", objectFit: "contain" }
4640
5215
  }
4641
5216
  ),
4642
- /* @__PURE__ */ jsx21(Typography10, { variant: "h6", sx: { fontWeight: "bold" }, children: clientContext.config.title })
5217
+ /* @__PURE__ */ jsx24(Typography12, { variant: "h6", sx: { fontWeight: "bold" }, children: clientContext.config.title })
4643
5218
  ]
4644
5219
  }
4645
5220
  ),
4646
- /* @__PURE__ */ jsx21(SideMenu_default, { onMenuItemClick: handleDrawerCloseMobile })
5221
+ /* @__PURE__ */ jsx24(SideMenu_default, { onMenuItemClick: handleDrawerCloseMobile })
4647
5222
  ]
4648
5223
  }
4649
5224
  ),
4650
- /* @__PURE__ */ jsxs15(
5225
+ /* @__PURE__ */ jsxs19(
4651
5226
  Box14,
4652
5227
  {
4653
5228
  component: "main",
@@ -4674,8 +5249,8 @@ var MainLayout = () => {
4674
5249
  width: isDrawerOpen ? `calc(100% - ${drawerWidth}px)` : "100%"
4675
5250
  },
4676
5251
  children: [
4677
- /* @__PURE__ */ jsx21(Toolbar, {}),
4678
- /* @__PURE__ */ jsx21(Box14, { sx: { flex: 1, minHeight: 0, overflowY: "auto", display: "flex", flexDirection: "column" }, children: /* @__PURE__ */ jsx21(Outlet, {}) })
5252
+ /* @__PURE__ */ jsx24(Toolbar, {}),
5253
+ /* @__PURE__ */ jsx24(Box14, { sx: { flex: 1, minHeight: 0, overflowY: "auto", display: "flex", flexDirection: "column" }, children: /* @__PURE__ */ jsx24(Outlet, {}) })
4679
5254
  ]
4680
5255
  }
4681
5256
  )
@@ -4684,8 +5259,8 @@ var MainLayout = () => {
4684
5259
  var MainLayout_default = MainLayout;
4685
5260
 
4686
5261
  // src/components/SessionExpiredMessage.tsx
4687
- import { Box as Box15, Typography as Typography11, Button as Button7, Modal } from "@mui/material";
4688
- import { jsx as jsx22, jsxs as jsxs16 } from "react/jsx-runtime";
5262
+ import { Box as Box15, Typography as Typography13, Button as Button9, Modal } from "@mui/material";
5263
+ import { jsx as jsx25, jsxs as jsxs20 } from "react/jsx-runtime";
4689
5264
  var style = {
4690
5265
  position: "absolute",
4691
5266
  top: "50%",
@@ -4704,7 +5279,7 @@ var SessionExpiredMessage = () => {
4704
5279
  const handleClose = () => {
4705
5280
  handleExpiredSessionRedirect();
4706
5281
  };
4707
- return /* @__PURE__ */ jsx22(
5282
+ return /* @__PURE__ */ jsx25(
4708
5283
  Modal,
4709
5284
  {
4710
5285
  open: showSessionExpiredMessage,
@@ -4724,10 +5299,10 @@ var SessionExpiredMessage = () => {
4724
5299
  }
4725
5300
  }
4726
5301
  },
4727
- children: /* @__PURE__ */ jsxs16(Box15, { sx: style, children: [
4728
- /* @__PURE__ */ jsx22(Typography11, { id: "session-expired-modal-title", variant: "h6", component: "h2", gutterBottom: true, children: "\xA1Sesi\xF3n Expirada!" }),
4729
- /* @__PURE__ */ jsx22(Typography11, { id: "session-expired-modal-description", sx: { mt: 2, mb: 3 }, children: "Tu sesi\xF3n ha expirado por inactividad o por seguridad. Por favor, inicia sesi\xF3n de nuevo." }),
4730
- /* @__PURE__ */ jsx22(Button7, { variant: "contained", color: "primary", onClick: handleClose, children: "Ir al Login" })
5302
+ children: /* @__PURE__ */ jsxs20(Box15, { sx: style, children: [
5303
+ /* @__PURE__ */ jsx25(Typography13, { id: "session-expired-modal-title", variant: "h6", component: "h2", gutterBottom: true, children: "\xA1Sesi\xF3n Expirada!" }),
5304
+ /* @__PURE__ */ jsx25(Typography13, { id: "session-expired-modal-description", sx: { mt: 2, mb: 3 }, children: "Tu sesi\xF3n ha expirado por inactividad o por seguridad. Por favor, inicia sesi\xF3n de nuevo." }),
5305
+ /* @__PURE__ */ jsx25(Button9, { variant: "contained", color: "primary", onClick: handleClose, children: "Ir al Login" })
4731
5306
  ] })
4732
5307
  }
4733
5308
  );
@@ -4736,24 +5311,24 @@ var SessionExpiredMessage_default = SessionExpiredMessage;
4736
5311
 
4737
5312
  // src/pages/PantallaInicial.tsx
4738
5313
  import { Navigate } from "react-router-dom";
4739
- import { jsx as jsx23 } from "react/jsx-runtime";
5314
+ import { jsx as jsx26 } from "react/jsx-runtime";
4740
5315
  var PantallaInicial = () => {
4741
5316
  const { clientContext } = useApp();
4742
5317
  const item = clientContext.menu ? itemInicial(clientContext.menu) : void 0;
4743
- return item ? /* @__PURE__ */ jsx23(Navigate, { to: rutaDeItemDeMenu(item), replace: true }) : null;
5318
+ return item ? /* @__PURE__ */ jsx26(Navigate, { to: rutaDeItemDeMenu(item), replace: true }) : null;
4744
5319
  };
4745
5320
  var PantallaInicial_default = PantallaInicial;
4746
5321
 
4747
5322
  // src/pages/LogoutPage.tsx
4748
- import { useEffect as useEffect9 } from "react";
4749
- import { Box as Box16, Typography as Typography12, CircularProgress as CircularProgress5 } from "@mui/material";
4750
- import { jsx as jsx24, jsxs as jsxs17 } from "react/jsx-runtime";
5323
+ import { useEffect as useEffect10 } from "react";
5324
+ import { Box as Box16, Typography as Typography14, CircularProgress as CircularProgress5 } from "@mui/material";
5325
+ import { jsx as jsx27, jsxs as jsxs21 } from "react/jsx-runtime";
4751
5326
  var LogoutPage = () => {
4752
5327
  const logout = useLogout_default();
4753
- useEffect9(() => {
5328
+ useEffect10(() => {
4754
5329
  logout();
4755
5330
  }, [logout]);
4756
- return /* @__PURE__ */ jsxs17(Box16, { sx: {
5331
+ return /* @__PURE__ */ jsxs21(Box16, { sx: {
4757
5332
  display: "flex",
4758
5333
  flexDirection: "column",
4759
5334
  justifyContent: "center",
@@ -4761,21 +5336,20 @@ var LogoutPage = () => {
4761
5336
  height: "100vh",
4762
5337
  textAlign: "center"
4763
5338
  }, children: [
4764
- /* @__PURE__ */ jsx24(CircularProgress5, { size: 60 }),
4765
- /* @__PURE__ */ jsx24(Typography12, { variant: "h6", sx: { mt: 2 }, children: "Cerrando sesi\xF3n..." })
5339
+ /* @__PURE__ */ jsx27(CircularProgress5, { size: 60 }),
5340
+ /* @__PURE__ */ jsx27(Typography14, { variant: "h6", sx: { mt: 2 }, children: "Cerrando sesi\xF3n..." })
4766
5341
  ] });
4767
5342
  };
4768
5343
  var LogoutPage_default = LogoutPage;
4769
5344
 
4770
5345
  // src/pages/LoginPage.tsx
4771
- import { useState as useState14 } from "react";
4772
- import { Button as Button8, TextField as TextField2, Typography as Typography13, Alert as Alert3, AlertTitle, Box as Box17, CircularProgress as CircularProgress6 } from "@mui/material";
5346
+ import { useState as useState17 } from "react";
5347
+ import { Button as Button10, TextField as TextField2, Typography as Typography15, Alert as Alert3, AlertTitle, Box as Box17, CircularProgress as CircularProgress6 } from "@mui/material";
4773
5348
  import { useForm, Controller } from "react-hook-form";
4774
5349
  import { zodResolver } from "@hookform/resolvers/zod";
4775
5350
  import * as z from "zod";
4776
- import { useNavigate as useNavigate4 } from "react-router-dom";
4777
5351
  import { useDispatch as useDispatch4 } from "react-redux";
4778
- import { Fragment as Fragment3, jsx as jsx25, jsxs as jsxs18 } from "react/jsx-runtime";
5352
+ import { Fragment as Fragment4, jsx as jsx28, jsxs as jsxs22 } from "react/jsx-runtime";
4779
5353
  var loginSchema = z.object({
4780
5354
  username: z.string().min(1, "El usuario es requerido"),
4781
5355
  // Añadir validación básica
@@ -4783,9 +5357,8 @@ var loginSchema = z.object({
4783
5357
  // Añadir validación básica
4784
5358
  });
4785
5359
  var LoginPage = () => {
4786
- const navigate = useNavigate4();
4787
- const [loginError, setLoginError] = useState14(null);
4788
- const [isSubmitting, setIsSubmitting] = useState14(false);
5360
+ const [loginError, setLoginError] = useState17(null);
5361
+ const [isSubmitting, setIsSubmitting] = useState17(false);
4789
5362
  const { setIsLoggedIn, checkSession } = useApp();
4790
5363
  const dispatch = useDispatch4();
4791
5364
  const {
@@ -4821,7 +5394,6 @@ var LoginPage = () => {
4821
5394
  setIsLoggedIn(true);
4822
5395
  await dispatch(fetchClientContext()).unwrap();
4823
5396
  console.log("Login exitoso y clientContext cargado.");
4824
- navigate("/");
4825
5397
  reset();
4826
5398
  } catch (error) {
4827
5399
  console.error("Error al iniciar sesi\xF3n:", error);
@@ -4831,7 +5403,7 @@ var LoginPage = () => {
4831
5403
  setIsSubmitting(false);
4832
5404
  }
4833
5405
  };
4834
- return /* @__PURE__ */ jsx25(
5406
+ return /* @__PURE__ */ jsx28(
4835
5407
  Box17,
4836
5408
  {
4837
5409
  display: "flex",
@@ -4839,7 +5411,7 @@ var LoginPage = () => {
4839
5411
  justifyContent: "center",
4840
5412
  minHeight: "100vh",
4841
5413
  bgcolor: "#f5f5f5",
4842
- children: /* @__PURE__ */ jsxs18(
5414
+ children: /* @__PURE__ */ jsxs22(
4843
5415
  Box17,
4844
5416
  {
4845
5417
  width: "100%",
@@ -4849,7 +5421,7 @@ var LoginPage = () => {
4849
5421
  borderRadius: 8,
4850
5422
  boxShadow: 3,
4851
5423
  children: [
4852
- /* @__PURE__ */ jsx25(Box17, { sx: { display: "flex", justifyContent: "center", mb: 3 }, children: /* @__PURE__ */ jsx25(
5424
+ /* @__PURE__ */ jsx28(Box17, { sx: { display: "flex", justifyContent: "center", mb: 3 }, children: /* @__PURE__ */ jsx28(
4853
5425
  "img",
4854
5426
  {
4855
5427
  src: `${envConfig.backendUrl}/img/login-logo-icon.png`,
@@ -4857,16 +5429,16 @@ var LoginPage = () => {
4857
5429
  style: { height: "192px", maxWidth: "100%", objectFit: "contain" }
4858
5430
  }
4859
5431
  ) }),
4860
- /* @__PURE__ */ jsx25(Typography13, { variant: "h5", align: "center", gutterBottom: true, sx: { fontWeight: "bold", color: "primary.main" }, children: "Iniciar Sesi\xF3n" }),
4861
- /* @__PURE__ */ jsxs18("form", { onSubmit: handleSubmit(onSubmit), className: "space-y-4", children: [
4862
- /* @__PURE__ */ jsxs18("div", { children: [
4863
- /* @__PURE__ */ jsx25("label", { htmlFor: "username", children: /* @__PURE__ */ jsx25(Typography13, { variant: "subtitle1", component: "div", sx: { fontWeight: "medium" }, children: "Usuario" }) }),
4864
- /* @__PURE__ */ jsx25(
5432
+ /* @__PURE__ */ jsx28(Typography15, { variant: "h5", align: "center", gutterBottom: true, sx: { fontWeight: "bold", color: "primary.main" }, children: "Iniciar Sesi\xF3n" }),
5433
+ /* @__PURE__ */ jsxs22("form", { onSubmit: handleSubmit(onSubmit), className: "space-y-4", children: [
5434
+ /* @__PURE__ */ jsxs22("div", { children: [
5435
+ /* @__PURE__ */ jsx28("label", { htmlFor: "username", children: /* @__PURE__ */ jsx28(Typography15, { variant: "subtitle1", component: "div", sx: { fontWeight: "medium" }, children: "Usuario" }) }),
5436
+ /* @__PURE__ */ jsx28(
4865
5437
  Controller,
4866
5438
  {
4867
5439
  name: "username",
4868
5440
  control,
4869
- render: ({ field }) => /* @__PURE__ */ jsx25(
5441
+ render: ({ field }) => /* @__PURE__ */ jsx28(
4870
5442
  TextField2,
4871
5443
  {
4872
5444
  ...field,
@@ -4882,14 +5454,14 @@ var LoginPage = () => {
4882
5454
  }
4883
5455
  )
4884
5456
  ] }),
4885
- /* @__PURE__ */ jsxs18("div", { children: [
4886
- /* @__PURE__ */ jsx25("label", { htmlFor: "password", children: /* @__PURE__ */ jsx25(Typography13, { variant: "subtitle1", component: "div", sx: { fontWeight: "medium" }, children: "Contrase\xF1a" }) }),
4887
- /* @__PURE__ */ jsx25(
5457
+ /* @__PURE__ */ jsxs22("div", { children: [
5458
+ /* @__PURE__ */ jsx28("label", { htmlFor: "password", children: /* @__PURE__ */ jsx28(Typography15, { variant: "subtitle1", component: "div", sx: { fontWeight: "medium" }, children: "Contrase\xF1a" }) }),
5459
+ /* @__PURE__ */ jsx28(
4888
5460
  Controller,
4889
5461
  {
4890
5462
  name: "password",
4891
5463
  control,
4892
- render: ({ field }) => /* @__PURE__ */ jsx25(
5464
+ render: ({ field }) => /* @__PURE__ */ jsx28(
4893
5465
  TextField2,
4894
5466
  {
4895
5467
  ...field,
@@ -4905,14 +5477,14 @@ var LoginPage = () => {
4905
5477
  }
4906
5478
  )
4907
5479
  ] }),
4908
- /* @__PURE__ */ jsx25(Button8, { type: "submit", fullWidth: true, variant: "contained", color: "primary", disabled: isSubmitting, sx: { mt: 2 }, children: isSubmitting ? /* @__PURE__ */ jsxs18(Fragment3, { children: [
4909
- /* @__PURE__ */ jsx25(CircularProgress6, { size: 20, sx: { mr: 1 } }),
5480
+ /* @__PURE__ */ jsx28(Button10, { type: "submit", fullWidth: true, variant: "contained", color: "primary", disabled: isSubmitting, sx: { mt: 2 }, children: isSubmitting ? /* @__PURE__ */ jsxs22(Fragment4, { children: [
5481
+ /* @__PURE__ */ jsx28(CircularProgress6, { size: 20, sx: { mr: 1 } }),
4910
5482
  "Iniciando sesi\xF3n..."
4911
5483
  ] }) : "Iniciar Sesi\xF3n" })
4912
5484
  ] }),
4913
- loginError && /* @__PURE__ */ jsxs18(Alert3, { severity: "error", sx: { mt: 2, maxHeight: "200px" }, children: [
5485
+ loginError && /* @__PURE__ */ jsxs22(Alert3, { severity: "error", sx: { mt: 2, maxHeight: "200px" }, children: [
4914
5486
  " ",
4915
- /* @__PURE__ */ jsx25(AlertTitle, { children: "Error" }),
5487
+ /* @__PURE__ */ jsx28(AlertTitle, { children: "Error" }),
4916
5488
  loginError
4917
5489
  ] })
4918
5490
  ]
@@ -4924,11 +5496,11 @@ var LoginPage = () => {
4924
5496
  var LoginPage_default = LoginPage;
4925
5497
 
4926
5498
  // src/components/ProcedureForm.tsx
4927
- import React19, { useState as useState15, useCallback as useCallback14, useMemo as useMemo11 } from "react";
5499
+ import React22, { useState as useState18, useCallback as useCallback14, useMemo as useMemo12 } from "react";
4928
5500
  import { useParams } from "react-router-dom";
4929
5501
  import {
4930
5502
  TextField as TextField3,
4931
- Button as Button9,
5503
+ Button as Button11,
4932
5504
  FormControl as FormControl3,
4933
5505
  InputLabel as InputLabel2,
4934
5506
  Select as Select2,
@@ -4936,7 +5508,7 @@ import {
4936
5508
  Checkbox as Checkbox3,
4937
5509
  FormControlLabel as FormControlLabel3,
4938
5510
  FormHelperText as FormHelperText2,
4939
- Typography as Typography15,
5511
+ Typography as Typography17,
4940
5512
  Box as Box19,
4941
5513
  CircularProgress as CircularProgress7,
4942
5514
  Alert as Alert4,
@@ -4945,14 +5517,14 @@ import {
4945
5517
  } from "@mui/material";
4946
5518
 
4947
5519
  // src/pages/procedure-results/SuccessDisplay.tsx
4948
- import { Box as Box18, Typography as Typography14, Paper as Paper3 } from "@mui/material";
4949
- import { jsx as jsx26, jsxs as jsxs19 } from "react/jsx-runtime";
5520
+ import { Box as Box18, Typography as Typography16, Paper as Paper3 } from "@mui/material";
5521
+ import { jsx as jsx29, jsxs as jsxs23 } from "react/jsx-runtime";
4950
5522
  var SuccessDisplay = ({ data }) => {
4951
- return /* @__PURE__ */ jsxs19(Paper3, { elevation: 2, sx: { p: 2, mt: 2, bgcolor: "success.light", color: "success.contrastText" }, children: [
4952
- /* @__PURE__ */ jsx26(Typography14, { variant: "h6", sx: { fontSize: "1rem", mb: 1 }, children: "\xA1Operaci\xF3n Exitosa!" }),
4953
- /* @__PURE__ */ jsx26(Typography14, { variant: "body2", sx: { fontSize: "0.85rem" }, children: "Detalles del resultado:" }),
4954
- /* @__PURE__ */ jsx26(Box18, { sx: { bgcolor: "success.dark", p: 1, borderRadius: 1, mt: 1, overflowX: "auto" }, children: /* @__PURE__ */ jsx26("pre", { style: { margin: 0, fontSize: "0.75rem", color: "white" }, children: JSON.stringify(data, null, 2) }) }),
4955
- /* @__PURE__ */ jsx26(Typography14, { variant: "body2", sx: { fontSize: "0.8rem", mt: 1 }, children: "Puedes revisar los detalles anteriores o cerrar este mensaje." })
5523
+ return /* @__PURE__ */ jsxs23(Paper3, { elevation: 2, sx: { p: 2, mt: 2, bgcolor: "success.light", color: "success.contrastText" }, children: [
5524
+ /* @__PURE__ */ jsx29(Typography16, { variant: "h6", sx: { fontSize: "1rem", mb: 1 }, children: "\xA1Operaci\xF3n Exitosa!" }),
5525
+ /* @__PURE__ */ jsx29(Typography16, { variant: "body2", sx: { fontSize: "0.85rem" }, children: "Detalles del resultado:" }),
5526
+ /* @__PURE__ */ jsx29(Box18, { sx: { bgcolor: "success.dark", p: 1, borderRadius: 1, mt: 1, overflowX: "auto" }, children: /* @__PURE__ */ jsx29("pre", { style: { margin: 0, fontSize: "0.75rem", color: "white" }, children: JSON.stringify(data, null, 2) }) }),
5527
+ /* @__PURE__ */ jsx29(Typography16, { variant: "body2", sx: { fontSize: "0.8rem", mt: 1 }, children: "Puedes revisar los detalles anteriores o cerrar este mensaje." })
4956
5528
  ] });
4957
5529
  };
4958
5530
  var SuccessDisplay_default = SuccessDisplay;
@@ -4966,22 +5538,22 @@ var extendResultsOk = (newComponents) => {
4966
5538
  };
4967
5539
 
4968
5540
  // src/components/ProcedureForm.tsx
4969
- import { jsx as jsx27, jsxs as jsxs20 } from "react/jsx-runtime";
5541
+ import { jsx as jsx30, jsxs as jsxs24 } from "react/jsx-runtime";
4970
5542
  var ProcedureForm = () => {
4971
5543
  const { procedureName } = useParams();
4972
5544
  const { clientContext } = useApp();
4973
5545
  const { callApi, loading: apiLoading, error: apiError } = useApiCall();
4974
- const [validationErrors, setValidationErrors] = useState15({});
4975
- const [successMessage, setSuccessMessage] = useState15(null);
4976
- const [executionLog, setExecutionLog] = useState15([]);
4977
- const [procedureResultData, setProcedureResultData] = useState15(null);
4978
- const procedure = useMemo11(() => {
5546
+ const [validationErrors, setValidationErrors] = useState18({});
5547
+ const [successMessage, setSuccessMessage] = useState18(null);
5548
+ const [executionLog, setExecutionLog] = useState18([]);
5549
+ const [procedureResultData, setProcedureResultData] = useState18(null);
5550
+ const procedure = useMemo12(() => {
4979
5551
  if (procedureName && clientContext?.procedure) {
4980
5552
  return clientContext.procedure[procedureName];
4981
5553
  }
4982
5554
  return void 0;
4983
5555
  }, [procedureName, clientContext]);
4984
- const [formValues, setFormValues] = useState15(() => {
5556
+ const [formValues, setFormValues] = useState18(() => {
4985
5557
  if (!procedure) return {};
4986
5558
  const initialValues = {};
4987
5559
  procedure.parameters.forEach((param) => {
@@ -5006,7 +5578,7 @@ var ProcedureForm = () => {
5006
5578
  });
5007
5579
  return initialValues;
5008
5580
  });
5009
- React19.useEffect(() => {
5581
+ React22.useEffect(() => {
5010
5582
  if (procedure) {
5011
5583
  setValidationErrors({});
5012
5584
  setSuccessMessage(null);
@@ -5181,9 +5753,9 @@ var ProcedureForm = () => {
5181
5753
  sx: { fontSize: "0.8rem" }
5182
5754
  };
5183
5755
  if (param.options && param.options.length > 0) {
5184
- return /* @__PURE__ */ jsxs20(FormControl3, { fullWidth: true, margin: "dense", size: "small", error: hasError, required: commonProps.required, children: [
5185
- /* @__PURE__ */ jsx27(InputLabel2, { id: `${param.name}-label`, sx: { fontSize: "0.8rem" }, children: param.label || param.name }),
5186
- /* @__PURE__ */ jsxs20(
5756
+ return /* @__PURE__ */ jsxs24(FormControl3, { fullWidth: true, margin: "dense", size: "small", error: hasError, required: commonProps.required, children: [
5757
+ /* @__PURE__ */ jsx30(InputLabel2, { id: `${param.name}-label`, sx: { fontSize: "0.8rem" }, children: param.label || param.name }),
5758
+ /* @__PURE__ */ jsxs24(
5187
5759
  Select2,
5188
5760
  {
5189
5761
  labelId: `${param.name}-label`,
@@ -5194,14 +5766,14 @@ var ProcedureForm = () => {
5194
5766
  label: param.label || param.name,
5195
5767
  disabled: apiLoading,
5196
5768
  sx: { fontSize: "0.8rem" },
5197
- renderValue: (selected) => /* @__PURE__ */ jsx27(Typography15, { sx: { fontSize: "0.8rem" }, children: selected }),
5769
+ renderValue: (selected) => /* @__PURE__ */ jsx30(Typography17, { sx: { fontSize: "0.8rem" }, children: selected }),
5198
5770
  children: [
5199
- (!commonProps.required || formValues[param.name] === "") && /* @__PURE__ */ jsx27(MenuItem2, { value: "", sx: { fontSize: "0.8rem" }, children: /* @__PURE__ */ jsx27("em", { children: "Seleccione..." }) }),
5200
- param.options.map((option) => /* @__PURE__ */ jsx27(MenuItem2, { value: option, sx: { fontSize: "0.8rem" }, children: option }, option))
5771
+ (!commonProps.required || formValues[param.name] === "") && /* @__PURE__ */ jsx30(MenuItem2, { value: "", sx: { fontSize: "0.8rem" }, children: /* @__PURE__ */ jsx30("em", { children: "Seleccione..." }) }),
5772
+ param.options.map((option) => /* @__PURE__ */ jsx30(MenuItem2, { value: option, sx: { fontSize: "0.8rem" }, children: option }, option))
5201
5773
  ]
5202
5774
  }
5203
5775
  ),
5204
- (param.description || errorMessage) && /* @__PURE__ */ jsx27(FormHelperText2, { sx: { fontSize: "0.7rem" }, children: errorMessage || param.description })
5776
+ (param.description || errorMessage) && /* @__PURE__ */ jsx30(FormHelperText2, { sx: { fontSize: "0.7rem" }, children: errorMessage || param.description })
5205
5777
  ] });
5206
5778
  }
5207
5779
  switch (param.typeName) {
@@ -5210,18 +5782,18 @@ var ProcedureForm = () => {
5210
5782
  case "tsrange":
5211
5783
  case "time_range":
5212
5784
  case "daterange":
5213
- return /* @__PURE__ */ jsx27(TextField3, { type: "text", value: formValues[param.name] || "", ...commonProps });
5785
+ return /* @__PURE__ */ jsx30(TextField3, { type: "text", value: formValues[param.name] || "", ...commonProps });
5214
5786
  case "decimal":
5215
5787
  case "double":
5216
- return /* @__PURE__ */ jsx27(TextField3, { type: "number", inputProps: { step: "any", style: { fontSize: "0.8rem" } }, value: formValues[param.name] || "", ...commonProps });
5788
+ return /* @__PURE__ */ jsx30(TextField3, { type: "number", inputProps: { step: "any", style: { fontSize: "0.8rem" } }, value: formValues[param.name] || "", ...commonProps });
5217
5789
  case "integer":
5218
5790
  case "bigint":
5219
- return /* @__PURE__ */ jsx27(TextField3, { type: "number", inputProps: { step: "1", style: { fontSize: "0.8rem" } }, value: formValues[param.name] || "", ...commonProps });
5791
+ return /* @__PURE__ */ jsx30(TextField3, { type: "number", inputProps: { step: "1", style: { fontSize: "0.8rem" } }, value: formValues[param.name] || "", ...commonProps });
5220
5792
  case "boolean":
5221
- return /* @__PURE__ */ jsx27(
5793
+ return /* @__PURE__ */ jsx30(
5222
5794
  FormControlLabel3,
5223
5795
  {
5224
- control: /* @__PURE__ */ jsx27(
5796
+ control: /* @__PURE__ */ jsx30(
5225
5797
  Checkbox3,
5226
5798
  {
5227
5799
  checked: !!formValues[param.name],
@@ -5232,21 +5804,21 @@ var ProcedureForm = () => {
5232
5804
  size: "small"
5233
5805
  }
5234
5806
  ),
5235
- label: /* @__PURE__ */ jsx27(Typography15, { sx: { fontSize: "0.8rem", color: hasError ? "error.main" : "inherit" }, children: param.label || param.name }),
5807
+ label: /* @__PURE__ */ jsx30(Typography17, { sx: { fontSize: "0.8rem", color: hasError ? "error.main" : "inherit" }, children: param.label || param.name }),
5236
5808
  sx: { mt: 1, mb: 0 }
5237
5809
  }
5238
5810
  );
5239
5811
  case "date":
5240
5812
  case "timestamp":
5241
5813
  case "time":
5242
- return /* @__PURE__ */ jsx27(TextField3, { type: param.typeName === "date" ? "date" : param.typeName === "timestamp" ? "datetime-local" : "time", value: formValues[param.name] || "", ...commonProps, InputLabelProps: { shrink: true, sx: { fontSize: "0.8rem" } } });
5814
+ return /* @__PURE__ */ jsx30(TextField3, { type: param.typeName === "date" ? "date" : param.typeName === "timestamp" ? "datetime-local" : "time", value: formValues[param.name] || "", ...commonProps, InputLabelProps: { shrink: true, sx: { fontSize: "0.8rem" } } });
5243
5815
  case "jsonb":
5244
5816
  case "jsona":
5245
- return /* @__PURE__ */ jsx27(TextField3, { multiline: true, rows: 5, value: formValues[param.name] || "", ...commonProps, InputProps: { sx: { fontSize: "0.8rem" } } });
5817
+ return /* @__PURE__ */ jsx30(TextField3, { multiline: true, rows: 5, value: formValues[param.name] || "", ...commonProps, InputProps: { sx: { fontSize: "0.8rem" } } });
5246
5818
  case "bytea":
5247
- return /* @__PURE__ */ jsxs20(FormControl3, { fullWidth: true, margin: "dense", error: hasError, required: commonProps.required, children: [
5248
- /* @__PURE__ */ jsx27(Typography15, { variant: "body2", color: "textSecondary", component: "label", htmlFor: param.name, sx: { fontSize: "0.8rem", color: hasError ? "error.main" : "text.secondary" }, children: param.label || param.name }),
5249
- /* @__PURE__ */ jsx27(
5819
+ return /* @__PURE__ */ jsxs24(FormControl3, { fullWidth: true, margin: "dense", error: hasError, required: commonProps.required, children: [
5820
+ /* @__PURE__ */ jsx30(Typography17, { variant: "body2", color: "textSecondary", component: "label", htmlFor: param.name, sx: { fontSize: "0.8rem", color: hasError ? "error.main" : "text.secondary" }, children: param.label || param.name }),
5821
+ /* @__PURE__ */ jsx30(
5250
5822
  "input",
5251
5823
  {
5252
5824
  type: "file",
@@ -5260,34 +5832,34 @@ var ProcedureForm = () => {
5260
5832
  style: { padding: "6px 0", fontSize: "0.8rem" }
5261
5833
  }
5262
5834
  ),
5263
- (param.description || errorMessage) && /* @__PURE__ */ jsx27(FormHelperText2, { sx: { fontSize: "0.7rem" }, children: errorMessage || param.description })
5835
+ (param.description || errorMessage) && /* @__PURE__ */ jsx30(FormHelperText2, { sx: { fontSize: "0.7rem" }, children: errorMessage || param.description })
5264
5836
  ] });
5265
5837
  default:
5266
- return /* @__PURE__ */ jsx27(TextField3, { type: "text", value: formValues[param.name] || "", ...commonProps });
5838
+ return /* @__PURE__ */ jsx30(TextField3, { type: "text", value: formValues[param.name] || "", ...commonProps });
5267
5839
  }
5268
5840
  }, [formValues, handleChange, apiLoading, validationErrors]);
5269
- const ResultDisplayContent = useMemo11(() => {
5841
+ const ResultDisplayContent = useMemo12(() => {
5270
5842
  if (!procedureResultData || !procedure?.resultOk) return null;
5271
5843
  const ComponentToRender = resultsOk[procedure.resultOk];
5272
5844
  if (ComponentToRender) {
5273
- return /* @__PURE__ */ jsx27(ComponentToRender, { data: procedureResultData });
5845
+ return /* @__PURE__ */ jsx30(ComponentToRender, { data: procedureResultData });
5274
5846
  } else {
5275
- return /* @__PURE__ */ jsxs20(Paper4, { elevation: 2, sx: { p: 2, mt: 0, bgcolor: "warning.light" }, children: [
5276
- /* @__PURE__ */ jsxs20(Typography15, { variant: "h6", sx: { fontSize: "1rem", mb: 1 }, children: [
5847
+ return /* @__PURE__ */ jsxs24(Paper4, { elevation: 2, sx: { p: 2, mt: 0, bgcolor: "warning.light" }, children: [
5848
+ /* @__PURE__ */ jsxs24(Typography17, { variant: "h6", sx: { fontSize: "1rem", mb: 1 }, children: [
5277
5849
  "el componente para resolver el resultOk: '",
5278
5850
  procedure.resultOk,
5279
5851
  "' definido en el procedure no existe o no est\xE1 mapeado."
5280
5852
  ] }),
5281
- /* @__PURE__ */ jsx27(Box19, { sx: {
5853
+ /* @__PURE__ */ jsx30(Box19, { sx: {
5282
5854
  bgcolor: "warning.dark",
5283
5855
  p: 1,
5284
5856
  borderRadius: 1
5285
- }, children: /* @__PURE__ */ jsx27("pre", { style: { margin: 0, fontSize: "0.75rem", color: "white" }, children: JSON.stringify(procedureResultData, null, 2) }) })
5857
+ }, children: /* @__PURE__ */ jsx30("pre", { style: { margin: 0, fontSize: "0.75rem", color: "white" }, children: JSON.stringify(procedureResultData, null, 2) }) })
5286
5858
  ] });
5287
5859
  }
5288
5860
  }, [procedureResultData, procedure]);
5289
5861
  if (!procedure) {
5290
- return /* @__PURE__ */ jsxs20(Box19, { sx: {
5862
+ return /* @__PURE__ */ jsxs24(Box19, { sx: {
5291
5863
  p: 2,
5292
5864
  width: "100%",
5293
5865
  boxSizing: "border-box",
@@ -5297,13 +5869,13 @@ var ProcedureForm = () => {
5297
5869
  boxShadow: 3,
5298
5870
  textAlign: "center"
5299
5871
  }, children: [
5300
- /* @__PURE__ */ jsx27(CircularProgress7, { sx: { mb: 2 } }),
5301
- /* @__PURE__ */ jsx27(Typography15, { variant: "h6", color: "text.secondary", children: "Cargando procedimiento o no encontrado..." })
5872
+ /* @__PURE__ */ jsx30(CircularProgress7, { sx: { mb: 2 } }),
5873
+ /* @__PURE__ */ jsx30(Typography17, { variant: "h6", color: "text.secondary", children: "Cargando procedimiento o no encontrado..." })
5302
5874
  ] });
5303
5875
  }
5304
5876
  return (
5305
5877
  // Esta es la Box más externa que ahora controlará el scroll
5306
- /* @__PURE__ */ jsxs20(Box19, { sx: {
5878
+ /* @__PURE__ */ jsxs24(Box19, { sx: {
5307
5879
  p: 2,
5308
5880
  ml: 1,
5309
5881
  mt: 2,
@@ -5320,17 +5892,17 @@ var ProcedureForm = () => {
5320
5892
  overflowX: "hidden"
5321
5893
  // Oculta el scroll horizontal si no es necesario para el contenedor principal
5322
5894
  }, children: [
5323
- /* @__PURE__ */ jsx27(Typography15, { variant: "h5", component: "h2", gutterBottom: true, align: "left", children: cambiarGuionesBajosPorEspacios(procedure.proceedLabel || procedure.action) }),
5324
- Object.values(validationErrors).some((err) => err !== null) && /* @__PURE__ */ jsxs20(Alert4, { severity: "error", sx: { mb: 2, fontSize: "0.8rem" }, children: [
5895
+ /* @__PURE__ */ jsx30(Typography17, { variant: "h5", component: "h2", gutterBottom: true, align: "left", children: cambiarGuionesBajosPorEspacios(procedure.proceedLabel || procedure.action) }),
5896
+ Object.values(validationErrors).some((err) => err !== null) && /* @__PURE__ */ jsxs24(Alert4, { severity: "error", sx: { mb: 2, fontSize: "0.8rem" }, children: [
5325
5897
  "Por favor, corrige los errores en el formulario antes de enviar.",
5326
- /* @__PURE__ */ jsx27("ul", { children: Object.values(validationErrors).map((err, idx) => err && /* @__PURE__ */ jsx27("li", { children: err }, idx)) })
5898
+ /* @__PURE__ */ jsx30("ul", { children: Object.values(validationErrors).map((err, idx) => err && /* @__PURE__ */ jsx30("li", { children: err }, idx)) })
5327
5899
  ] }),
5328
- !Object.values(validationErrors).some((err) => err !== null) && apiError && /* @__PURE__ */ jsx27(Alert4, { severity: "error", sx: { mb: 2, fontSize: "0.8rem" }, children: apiError.message }),
5329
- !Object.values(validationErrors).some((err) => err !== null) && !apiError && successMessage && /* @__PURE__ */ jsx27(Alert4, { severity: "success", sx: { mb: 2, fontSize: "0.8rem" }, children: successMessage }),
5330
- /* @__PURE__ */ jsxs20("form", { onSubmit: handleSubmit, children: [
5331
- procedure.parameters.map((param) => /* @__PURE__ */ jsx27("div", { children: renderInputField(param) }, param.name)),
5332
- /* @__PURE__ */ jsx27(
5333
- Button9,
5900
+ !Object.values(validationErrors).some((err) => err !== null) && apiError && /* @__PURE__ */ jsx30(Alert4, { severity: "error", sx: { mb: 2, fontSize: "0.8rem" }, children: apiError.message }),
5901
+ !Object.values(validationErrors).some((err) => err !== null) && !apiError && successMessage && /* @__PURE__ */ jsx30(Alert4, { severity: "success", sx: { mb: 2, fontSize: "0.8rem" }, children: successMessage }),
5902
+ /* @__PURE__ */ jsxs24("form", { onSubmit: handleSubmit, children: [
5903
+ procedure.parameters.map((param) => /* @__PURE__ */ jsx30("div", { children: renderInputField(param) }, param.name)),
5904
+ /* @__PURE__ */ jsx30(
5905
+ Button11,
5334
5906
  {
5335
5907
  type: "submit",
5336
5908
  variant: "contained",
@@ -5338,19 +5910,19 @@ var ProcedureForm = () => {
5338
5910
  disabled: apiLoading || Object.values(validationErrors).some((err) => err !== null),
5339
5911
  sx: { mt: 2 },
5340
5912
  size: "medium",
5341
- startIcon: apiLoading ? /* @__PURE__ */ jsx27(CircularProgress7, { size: 20, color: "inherit" }) : null,
5913
+ startIcon: apiLoading ? /* @__PURE__ */ jsx30(CircularProgress7, { size: 20, color: "inherit" }) : null,
5342
5914
  children: apiLoading ? "Ejecutando..." : procedure.proceedLabel || "Ejecutar"
5343
5915
  }
5344
5916
  )
5345
5917
  ] }),
5346
- ResultDisplayContent && /* @__PURE__ */ jsxs20(Box19, { sx: { mt: 2 }, children: [
5918
+ ResultDisplayContent && /* @__PURE__ */ jsxs24(Box19, { sx: { mt: 2 }, children: [
5347
5919
  " ",
5348
5920
  ResultDisplayContent
5349
5921
  ] }),
5350
- executionLog.length > 0 && /* @__PURE__ */ jsxs20(Box19, { sx: { mt: 3 }, children: [
5351
- /* @__PURE__ */ jsx27(Divider3, { sx: { mb: 2 } }),
5352
- /* @__PURE__ */ jsx27(Typography15, { variant: "h6", gutterBottom: true, sx: { fontSize: "0.9rem" }, children: "Registro de Ejecuci\xF3n" }),
5353
- /* @__PURE__ */ jsx27(
5922
+ executionLog.length > 0 && /* @__PURE__ */ jsxs24(Box19, { sx: { mt: 3 }, children: [
5923
+ /* @__PURE__ */ jsx30(Divider3, { sx: { mb: 2 } }),
5924
+ /* @__PURE__ */ jsx30(Typography17, { variant: "h6", gutterBottom: true, sx: { fontSize: "0.9rem" }, children: "Registro de Ejecuci\xF3n" }),
5925
+ /* @__PURE__ */ jsx30(
5354
5926
  Box19,
5355
5927
  {
5356
5928
  sx: {
@@ -5364,8 +5936,8 @@ var ProcedureForm = () => {
5364
5936
  fontSize: "0.75rem",
5365
5937
  whiteSpace: "pre-wrap"
5366
5938
  },
5367
- children: executionLog.map((log, index) => /* @__PURE__ */ jsx27(
5368
- Typography15,
5939
+ children: executionLog.map((log, index) => /* @__PURE__ */ jsx30(
5940
+ Typography17,
5369
5941
  {
5370
5942
  component: "pre",
5371
5943
  sx: {
@@ -5390,9 +5962,9 @@ import { Provider } from "react-redux";
5390
5962
  import { PersistGate } from "redux-persist/integration/react";
5391
5963
 
5392
5964
  // src/components/PrivateRoute.tsx
5393
- import { useEffect as useEffect10 } from "react";
5965
+ import { useEffect as useEffect11 } from "react";
5394
5966
  import { Navigate as Navigate2, useLocation as useLocation3 } from "react-router-dom";
5395
- import { Fragment as Fragment4, jsx as jsx28 } from "react/jsx-runtime";
5967
+ import { Fragment as Fragment5, jsx as jsx31 } from "react/jsx-runtime";
5396
5968
  var PrivateRoute = ({ children }) => {
5397
5969
  const location = useLocation3();
5398
5970
  const dispatch = useAppDispatch();
@@ -5400,7 +5972,7 @@ var PrivateRoute = ({ children }) => {
5400
5972
  const isAuthenticated = clientContextStatus === "succeeded";
5401
5973
  const isLoadingAuth = clientContextStatus === "loading";
5402
5974
  console.log(`[PrivateRoute] Render: Path=${location.pathname}, AuthStatus=${clientContextStatus}, IsAuthenticated=${isAuthenticated}, IsLoadingAuth=${isLoadingAuth}`);
5403
- useEffect10(() => {
5975
+ useEffect11(() => {
5404
5976
  console.log(`[PrivateRoute] Effect: Path=${location.pathname}, AuthStatus=${clientContextStatus}, IsAuthenticated=${isAuthenticated}, IsLoadingAuth=${isLoadingAuth}`);
5405
5977
  if (!isAuthenticated && !isLoadingAuth && location.pathname !== "/login") {
5406
5978
  const path = location.pathname + location.search + location.hash;
@@ -5416,34 +5988,34 @@ var PrivateRoute = ({ children }) => {
5416
5988
  }, [isAuthenticated, isLoadingAuth, location, dispatch, clientContextStatus]);
5417
5989
  if (isLoadingAuth) {
5418
5990
  console.log(`[PrivateRoute] Returning loading state...`);
5419
- return /* @__PURE__ */ jsx28("p", { children: "Verificando autenticaci\xF3n..." });
5991
+ return /* @__PURE__ */ jsx31("p", { children: "Verificando autenticaci\xF3n..." });
5420
5992
  }
5421
5993
  if (!isAuthenticated) {
5422
5994
  console.log(`[PrivateRoute] User not authenticated, navigating to /login`);
5423
- return /* @__PURE__ */ jsx28(Navigate2, { to: "/login", replace: true });
5995
+ return /* @__PURE__ */ jsx31(Navigate2, { to: "/login", replace: true });
5424
5996
  }
5425
5997
  console.log(`[PrivateRoute] User authenticated, rendering children.`);
5426
- return /* @__PURE__ */ jsx28(Fragment4, { children });
5998
+ return /* @__PURE__ */ jsx31(Fragment5, { children });
5427
5999
  };
5428
6000
  var PrivateRoute_default = PrivateRoute;
5429
6001
 
5430
6002
  // src/components/InitialRedirectHandler.tsx
5431
- import { useEffect as useEffect11, useRef as useRef8 } from "react";
5432
- import { useLocation as useLocation4, useNavigate as useNavigate5 } from "react-router-dom";
6003
+ import { useEffect as useEffect12, useRef as useRef9 } from "react";
6004
+ import { useLocation as useLocation4, useNavigate as useNavigate4 } from "react-router-dom";
5433
6005
  var InitialRedirectHandler = () => {
5434
6006
  const location = useLocation4();
5435
- const navigate = useNavigate5();
6007
+ const navigate = useNavigate4();
5436
6008
  const dispatch = useAppDispatch();
5437
6009
  const redirectPath = useRedirectPath();
5438
6010
  const clientContextStatus = useClientContextStatus();
5439
- useEffect11(() => {
6011
+ useEffect12(() => {
5440
6012
  dispatch(setCurrentPath(location.pathname + location.search));
5441
6013
  }, [location, dispatch]);
5442
- const navegandoRef = useRef8(false);
5443
- useEffect11(() => {
6014
+ const navegandoRef = useRef9(false);
6015
+ useEffect12(() => {
5444
6016
  navegandoRef.current = false;
5445
6017
  }, [location.pathname]);
5446
- useEffect11(() => {
6018
+ useEffect12(() => {
5447
6019
  if (clientContextStatus === "succeeded") {
5448
6020
  if (redirectPath && redirectPath !== "/login") {
5449
6021
  console.log("Redirigiendo a la ruta guardada:", redirectPath);
@@ -5461,34 +6033,39 @@ var InitialRedirectHandler = () => {
5461
6033
  var InitialRedirectHandler_default = InitialRedirectHandler;
5462
6034
 
5463
6035
  // src/pages/GenericDataGridPage.tsx
5464
- import React22, { useState as useState16, useCallback as useCallback15 } from "react";
6036
+ import React25, { useState as useState19, useCallback as useCallback15, useMemo as useMemo13 } from "react";
5465
6037
  import { useParams as useParams2, useLocation as useLocation5 } from "react-router-dom";
5466
- import { Box as Box20, Alert as Alert5, Typography as Typography16, Tabs, Tab, IconButton as IconButton5 } from "@mui/material";
6038
+ import { Box as Box20, Alert as Alert5, Typography as Typography18, Tabs, Tab, IconButton as IconButton7 } from "@mui/material";
5467
6039
  import CloseIcon2 from "@mui/icons-material/Close";
5468
- import { jsx as jsx29, jsxs as jsxs21 } from "react/jsx-runtime";
6040
+ import { jsx as jsx32, jsxs as jsxs25 } from "react/jsx-runtime";
5469
6041
  var GenericDataGridPage = ({
5470
6042
  initialTableName,
5471
- initialFixedFields = []
6043
+ initialFixedFields = [],
6044
+ parametros: parametrosRecibidos
5472
6045
  }) => {
5473
6046
  const { tableName: urlTableName } = useParams2();
5474
6047
  const effectiveTableName = initialTableName || urlTableName;
5475
- const [tabs, setTabs] = useState16([]);
5476
- const [activeTabIdx, setActiveTabIdx] = useState16(0);
6048
+ const [tabs, setTabs] = useState19([]);
6049
+ const [activeTabIdx, setActiveTabIdx] = useState19(0);
5477
6050
  const ffKey = JSON.stringify(initialFixedFields);
5478
6051
  const location = useLocation5();
5479
- React22.useEffect(() => {
6052
+ const parametros = useMemo13(() => parametrosRecibidos ?? parametrosDeTabla(void 0, location.search), [parametrosRecibidos, location.search]);
6053
+ const fixedFieldsIniciales = initialFixedFields.length > 0 ? initialFixedFields : parametros.fixedFields ?? [];
6054
+ const parametrosKey = JSON.stringify(parametros);
6055
+ React25.useEffect(() => {
5480
6056
  if (effectiveTableName) {
5481
6057
  setTabs([{
5482
- id: `main-${effectiveTableName}-${ffKey}`,
6058
+ id: `main-${effectiveTableName}-${ffKey}-${parametrosKey}`,
5483
6059
  // ID único que incluye filtros
5484
- label: effectiveTableName.replace(/_/g, " ").toUpperCase(),
6060
+ label: parametros.label ?? effectiveTableName.replace(/_/g, " ").toUpperCase(),
5485
6061
  tableName: effectiveTableName,
5486
- fixedFields: initialFixedFields,
6062
+ fixedFields: fixedFieldsIniciales,
6063
+ parametros,
5487
6064
  ancestors: []
5488
6065
  }]);
5489
6066
  setActiveTabIdx(0);
5490
6067
  }
5491
- }, [effectiveTableName, ffKey, location.key]);
6068
+ }, [effectiveTableName, ffKey, parametrosKey, location.key]);
5492
6069
  const handleOpenDetail = useCallback15((tableName, fixedFields, label, ancestors) => {
5493
6070
  const tabId = `${tableName}-${JSON.stringify(fixedFields)}`;
5494
6071
  setTabs((prevTabs) => {
@@ -5511,30 +6088,34 @@ var GenericDataGridPage = ({
5511
6088
  else if (activeTabIdx === index) setActiveTabIdx(index - 1);
5512
6089
  };
5513
6090
  if (!effectiveTableName) {
5514
- return /* @__PURE__ */ jsx29(Box20, { p: 3, children: /* @__PURE__ */ jsx29(Alert5, { severity: "error", children: "No se especific\xF3 una tabla." }) });
6091
+ return /* @__PURE__ */ jsx32(Box20, { p: 3, children: /* @__PURE__ */ jsx32(Alert5, { severity: "error", children: "No se especific\xF3 una tabla." }) });
5515
6092
  }
5516
- return /* @__PURE__ */ jsxs21(Box20, { sx: { width: "100%", height: "calc(100vh - 64px)", display: "flex", flexDirection: "column" }, children: [
5517
- /* @__PURE__ */ jsx29(Box20, { sx: { borderBottom: 1, borderColor: "divider", bgcolor: "background.paper" }, children: /* @__PURE__ */ jsx29(Tabs, { value: activeTabIdx, onChange: (_, v) => setActiveTabIdx(v), variant: "scrollable", children: tabs.map((tab, index) => /* @__PURE__ */ jsx29(
6093
+ return /* @__PURE__ */ jsxs25(Box20, { sx: { width: "100%", height: "calc(100vh - 64px)", display: "flex", flexDirection: "column" }, children: [
6094
+ /* @__PURE__ */ jsx32(Box20, { sx: { borderBottom: 1, borderColor: "divider", bgcolor: "background.paper" }, children: /* @__PURE__ */ jsx32(Tabs, { value: activeTabIdx, onChange: (_, v) => setActiveTabIdx(v), variant: "scrollable", children: tabs.map((tab, index) => /* @__PURE__ */ jsx32(
5518
6095
  Tab,
5519
6096
  {
5520
- label: /* @__PURE__ */ jsxs21(Box20, { sx: { display: "flex", alignItems: "center", gap: 1 }, children: [
5521
- /* @__PURE__ */ jsx29(Typography16, { variant: "caption", sx: { fontWeight: "bold" }, children: tab.label }),
5522
- index !== 0 && /* @__PURE__ */ jsx29(IconButton5, { size: "small", onClick: (e) => handleCloseTab(index, e), children: /* @__PURE__ */ jsx29(CloseIcon2, { fontSize: "inherit" }) })
6097
+ label: /* @__PURE__ */ jsxs25(Box20, { sx: { display: "flex", alignItems: "center", gap: 1 }, children: [
6098
+ /* @__PURE__ */ jsx32(Typography18, { variant: "caption", sx: { fontWeight: "bold" }, children: tab.label }),
6099
+ index !== 0 && /* @__PURE__ */ jsx32(IconButton7, { size: "small", onClick: (e) => handleCloseTab(index, e), children: /* @__PURE__ */ jsx32(CloseIcon2, { fontSize: "inherit" }) })
5523
6100
  ] })
5524
6101
  },
5525
6102
  tab.id
5526
6103
  )) }) }),
5527
- tabs.map((tab, index) => /* @__PURE__ */ jsx29(
6104
+ tabs.map((tab, index) => /* @__PURE__ */ jsx32(
5528
6105
  Box20,
5529
6106
  {
5530
6107
  role: "tabpanel",
5531
6108
  hidden: activeTabIdx !== index,
5532
6109
  sx: { flexGrow: 1, display: activeTabIdx === index ? "flex" : "none", flexDirection: "column", overflow: "hidden" },
5533
- children: /* @__PURE__ */ jsx29(
6110
+ children: /* @__PURE__ */ jsx32(
5534
6111
  GenericDataGrid_default,
5535
6112
  {
5536
6113
  tableName: tab.tableName,
5537
6114
  fixedFields: tab.fixedFields,
6115
+ filterColumns: tab.parametros?.filterColumns,
6116
+ tableDef: tab.parametros?.tableDef,
6117
+ parameterFunctions: tab.parametros?.parameterFunctions,
6118
+ pick: tab.parametros?.pick,
5538
6119
  onOpenDetail: handleOpenDetail,
5539
6120
  ancestors: tab.ancestors
5540
6121
  }
@@ -5547,32 +6128,26 @@ var GenericDataGridPage = ({
5547
6128
  var GenericDataGridPage_default = GenericDataGridPage;
5548
6129
 
5549
6130
  // src/pages/PantallaDeRuta.tsx
5550
- import { useMemo as useMemo12 } from "react";
6131
+ import { useMemo as useMemo14 } from "react";
5551
6132
  import { useSearchParams } from "react-router-dom";
5552
6133
  import { Box as Box21 } from "@mui/material";
5553
- import { jsx as jsx30 } from "react/jsx-runtime";
6134
+ import { jsx as jsx33 } from "react/jsx-runtime";
5554
6135
  var PantallaDeRuta = ({ screenName }) => {
5555
6136
  const [busqueda] = useSearchParams();
5556
- const params = useMemo12(() => Object.fromEntries(busqueda.entries()), [busqueda]);
6137
+ const params = useMemo14(() => Object.fromEntries(busqueda.entries()), [busqueda]);
5557
6138
  const Pantalla = wScreens[screenName];
5558
- return /* @__PURE__ */ jsx30(Box21, { sx: { pt: 3, pl: 4 }, children: Pantalla ? /* @__PURE__ */ jsx30(Pantalla, { screenName, params }) : /* @__PURE__ */ jsx30(FallbackWScreen, { screenName }) });
6139
+ return /* @__PURE__ */ jsx33(Box21, { sx: { pt: 3, pl: 4 }, children: Pantalla ? /* @__PURE__ */ jsx33(Pantalla, { screenName, params }) : /* @__PURE__ */ jsx33(FallbackWScreen, { screenName }) });
5559
6140
  };
5560
6141
 
5561
6142
  // src/pages/MenuTablePage.tsx
5562
- import { useMemo as useMemo13 } from "react";
5563
- import { useParams as useParams3 } from "react-router-dom";
5564
- import { Box as Box22, Alert as Alert6, Typography as Typography17 } from "@mui/material";
5565
- import { jsx as jsx31, jsxs as jsxs22 } from "react/jsx-runtime";
5566
- function fixedFieldsDeMenu(ff) {
5567
- if (!ff) return [];
5568
- if (Array.isArray(ff)) {
5569
- return ff.map(({ fieldName, value }) => ({ fieldName, value }));
5570
- }
5571
- return Object.entries(ff).map(([fieldName, value]) => ({ fieldName, value }));
5572
- }
6143
+ import { useMemo as useMemo15 } from "react";
6144
+ import { useLocation as useLocation6, useParams as useParams3 } from "react-router-dom";
6145
+ import { Box as Box22, Alert as Alert6, Typography as Typography19 } from "@mui/material";
6146
+ import { jsx as jsx34, jsxs as jsxs26 } from "react/jsx-runtime";
5573
6147
  var MenuTablePage = () => {
5574
6148
  const { menuName } = useParams3();
5575
6149
  const { clientContext } = useApp();
6150
+ const { search } = useLocation6();
5576
6151
  const findMenuItem = (items, nameToFind) => {
5577
6152
  for (const item of items) {
5578
6153
  if (item.name === nameToFind && item.menuType === "table") {
@@ -5585,51 +6160,55 @@ var MenuTablePage = () => {
5585
6160
  }
5586
6161
  return void 0;
5587
6162
  };
5588
- const { currentTableName, currentFixedFields } = useMemo13(() => {
6163
+ const { currentTableName, currentFixedFields, parametros } = useMemo15(() => {
5589
6164
  let tableName = void 0;
5590
6165
  let fixedFields = [];
6166
+ let parametros2 = {};
5591
6167
  if (menuName && clientContext && clientContext.menu) {
5592
6168
  const menuItem = findMenuItem(clientContext.menu, menuName);
5593
6169
  if (menuItem) {
5594
6170
  tableName = menuItem.table || menuItem.name;
5595
- fixedFields = fixedFieldsDeMenu(menuItem.ff);
6171
+ parametros2 = parametrosDeTabla(menuItem, search);
6172
+ fixedFields = parametros2.fixedFields ?? [];
5596
6173
  } else {
5597
6174
  console.warn(`[${menuName}] \xCDtem de men\xFA '${menuName}' no encontrado o no es de tipo 'table' en clientContext.menu.`);
5598
6175
  }
5599
6176
  }
5600
6177
  return {
5601
6178
  currentTableName: tableName,
5602
- currentFixedFields: fixedFields
6179
+ currentFixedFields: fixedFields,
6180
+ parametros: parametros2
5603
6181
  };
5604
- }, [menuName, clientContext]);
6182
+ }, [menuName, clientContext, search]);
5605
6183
  if (!currentTableName) {
5606
- return /* @__PURE__ */ jsx31(Box22, { display: "flex", justifyContent: "center", alignItems: "center", minHeight: "200px", children: /* @__PURE__ */ jsxs22(Alert6, { severity: "error", children: [
5607
- /* @__PURE__ */ jsx31(Typography17, { variant: "h6", children: "Error: No se pudo cargar la informaci\xF3n de la tabla." }),
5608
- /* @__PURE__ */ jsx31(Typography17, { variant: "body1", children: "Verifique la configuraci\xF3n del men\xFA o el nombre de la tabla en la URL." })
6184
+ return /* @__PURE__ */ jsx34(Box22, { display: "flex", justifyContent: "center", alignItems: "center", minHeight: "200px", children: /* @__PURE__ */ jsxs26(Alert6, { severity: "error", children: [
6185
+ /* @__PURE__ */ jsx34(Typography19, { variant: "h6", children: "Error: No se pudo cargar la informaci\xF3n de la tabla." }),
6186
+ /* @__PURE__ */ jsx34(Typography19, { variant: "body1", children: "Verifique la configuraci\xF3n del men\xFA o el nombre de la tabla en la URL." })
5609
6187
  ] }) });
5610
6188
  }
5611
- return /* @__PURE__ */ jsx31(
6189
+ return /* @__PURE__ */ jsx34(
5612
6190
  GenericDataGridPage_default,
5613
6191
  {
5614
6192
  initialTableName: currentTableName,
5615
- initialFixedFields: currentFixedFields
6193
+ initialFixedFields: currentFixedFields,
6194
+ parametros
5616
6195
  }
5617
6196
  );
5618
6197
  };
5619
6198
  var MenuTablePage_default = MenuTablePage;
5620
6199
 
5621
6200
  // src/puente/PantallaBP.tsx
5622
- import { useEffect as useEffect14, useRef as useRef9, useState as useState17 } from "react";
5623
- import { Navigate as Navigate3, useLocation as useLocation6, useNavigate as useNavigate6, useParams as useParams4 } from "react-router-dom";
6201
+ import { useEffect as useEffect15, useRef as useRef10, useState as useState20 } from "react";
6202
+ import { Navigate as Navigate3, useLocation as useLocation7, useParams as useParams4 } from "react-router-dom";
5624
6203
  import { Alert as Alert7, Box as Box24, CircularProgress as CircularProgress8 } from "@mui/material";
5625
6204
 
5626
6205
  // src/puente/clienteBP.ts
5627
6206
  function extraerRecursos(html) {
5628
6207
  const documento = new DOMParser().parseFromString(html, "text/html");
5629
- const referencias = (selector, atributo) => Array.from(documento.querySelectorAll(selector)).map((elemento) => elemento.getAttribute(atributo)).filter((ruta) => !!ruta);
6208
+ const referencias2 = (selector, atributo) => Array.from(documento.querySelectorAll(selector)).map((elemento) => elemento.getAttribute(atributo)).filter((ruta) => !!ruta);
5630
6209
  return {
5631
- hojasDeEstilo: referencias("link[rel=stylesheet]", "href"),
5632
- scripts: referencias("script[src]", "src")
6210
+ hojasDeEstilo: referencias2("link[rel=stylesheet]", "href"),
6211
+ scripts: referencias2("script[src]", "src")
5633
6212
  };
5634
6213
  }
5635
6214
  function fijarBase(urlBackend) {
@@ -5655,6 +6234,24 @@ function esperarCargaDeVentana() {
5655
6234
  if (document.readyState === "complete") return Promise.resolve();
5656
6235
  return new Promise((resolver) => window.addEventListener("load", () => resolver(), { once: true }));
5657
6236
  }
6237
+ async function sinEscuchasDeVentana(tipos, inyectar) {
6238
+ const original = window.addEventListener;
6239
+ const filtrada = function(tipo, escucha, opciones) {
6240
+ if (tipos.includes(tipo)) return;
6241
+ original.call(this, tipo, escucha, opciones);
6242
+ };
6243
+ window.addEventListener = filtrada;
6244
+ try {
6245
+ return await inyectar();
6246
+ } finally {
6247
+ if (window.addEventListener === filtrada) window.addEventListener = original;
6248
+ }
6249
+ }
6250
+ async function cargarScripts(rutas) {
6251
+ for (const ruta of rutas) {
6252
+ await cargarScript(ruta);
6253
+ }
6254
+ }
5658
6255
  var carga = null;
5659
6256
  function cargarClienteBP(urlBackend) {
5660
6257
  if (!carga) {
@@ -5683,9 +6280,7 @@ async function cargarSinMemoria(urlBackend) {
5683
6280
  document.head.appendChild(enlace);
5684
6281
  });
5685
6282
  await esperarCargaDeVentana();
5686
- for (const ruta of recursos.scripts) {
5687
- await cargarScript(ruta);
5688
- }
6283
+ await sinEscuchasDeVentana(["popstate"], () => cargarScripts(recursos.scripts));
5689
6284
  const myOwn = window.myOwn;
5690
6285
  if (!myOwn) throw new Error("El backend no defini\xF3 myOwn.");
5691
6286
  window.my = myOwn;
@@ -5694,9 +6289,9 @@ async function cargarSinMemoria(urlBackend) {
5694
6289
  }
5695
6290
 
5696
6291
  // src/puente/ConsolaBP.tsx
5697
- import { useEffect as useEffect13 } from "react";
6292
+ import { useEffect as useEffect14 } from "react";
5698
6293
  import { Box as Box23 } from "@mui/material";
5699
- import { jsx as jsx32 } from "react/jsx-runtime";
6294
+ import { jsx as jsx35 } from "react/jsx-runtime";
5700
6295
  var MARGEN_DE_REPETIDO_MS = 1e3;
5701
6296
  function descartarRepetidos(consola, agregados, ahora) {
5702
6297
  for (const nodo of agregados) {
@@ -5709,7 +6304,7 @@ function descartarRepetidos(consola, agregados, ahora) {
5709
6304
  }
5710
6305
  }
5711
6306
  var ConsolaBP = () => {
5712
- useEffect13(() => {
6307
+ useEffect14(() => {
5713
6308
  const consola = document.getElementById("mini-console");
5714
6309
  if (!consola) return;
5715
6310
  const observador = new MutationObserver(
@@ -5718,7 +6313,7 @@ var ConsolaBP = () => {
5718
6313
  observador.observe(consola, { childList: true });
5719
6314
  return () => observador.disconnect();
5720
6315
  }, []);
5721
- return /* @__PURE__ */ jsx32(
6316
+ return /* @__PURE__ */ jsx35(
5722
6317
  Box23,
5723
6318
  {
5724
6319
  id: "mini-console",
@@ -5807,47 +6402,6 @@ function resolverPantallaBP(myOwn, nombre, contenedor) {
5807
6402
  return null;
5808
6403
  }
5809
6404
 
5810
- // src/puente/capturaDeNavegacion.ts
5811
- function apiDeNavegacion() {
5812
- const api = Reflect.get(window, "navigation");
5813
- return typeof api === "object" && api !== null && "addEventListener" in api && typeof api.addEventListener === "function" ? api : null;
5814
- }
5815
- function capturarNavegacionBP(urlBackend, navegar) {
5816
- const alHacerClick = (evento) => {
5817
- if (evento.defaultPrevented || evento.button !== 0 || evento.ctrlKey || evento.metaKey || evento.shiftKey) return;
5818
- const enlace = evento.target instanceof Element ? evento.target.closest("a[href]") : null;
5819
- if (!enlace || enlace.hasAttribute("download") || (enlace.getAttribute("target") ?? "_self") !== "_self") return;
5820
- const ruta = rutaDeEnlaceBP(enlace.getAttribute("href") ?? "", document.baseURI, urlBackend);
5821
- if (ruta) {
5822
- evento.preventDefault();
5823
- evento.stopPropagation();
5824
- navegar(ruta);
5825
- }
5826
- };
5827
- document.addEventListener("click", alHacerClick, true);
5828
- const navegacion = apiDeNavegacion();
5829
- const alNavegar = (evento) => {
5830
- if (!evento.cancelable || evento.destination.sameDocument || evento.downloadRequest !== null) return;
5831
- const ruta = rutaDeEnlaceBP(evento.destination.url, document.baseURI, urlBackend);
5832
- if (ruta) {
5833
- evento.preventDefault();
5834
- navegar(ruta);
5835
- }
5836
- };
5837
- navegacion?.addEventListener("navigate", alNavegar);
5838
- const reemplazarOriginal = history.replaceState;
5839
- const reemplazar = (estado, titulo, url) => {
5840
- const ruta = url === void 0 || url === null ? null : rutaDeEnlaceBP(String(url), document.baseURI, urlBackend);
5841
- reemplazarOriginal.call(history, estado, titulo, ruta === null ? url : rutaBase + ruta);
5842
- };
5843
- history.replaceState = reemplazar;
5844
- return () => {
5845
- if (history.replaceState === reemplazar) history.replaceState = reemplazarOriginal;
5846
- document.removeEventListener("click", alHacerClick, true);
5847
- navegacion?.removeEventListener("navigate", alNavegar);
5848
- };
5849
- }
5850
-
5851
6405
  // src/puente/habilitacion.ts
5852
6406
  var habilitado = false;
5853
6407
  var habilitarPuenteBP = () => {
@@ -5856,7 +6410,7 @@ var habilitarPuenteBP = () => {
5856
6410
  var puenteBPHabilitado = () => habilitado;
5857
6411
 
5858
6412
  // src/puente/PantallaBP.tsx
5859
- import { jsx as jsx33, jsxs as jsxs23 } from "react/jsx-runtime";
6413
+ import { jsx as jsx36, jsxs as jsxs27 } from "react/jsx-runtime";
5860
6414
  function buscarItemDeMenu(items, tipo) {
5861
6415
  for (const item of items) {
5862
6416
  if (item.menuType === tipo) return item;
@@ -5868,21 +6422,19 @@ function buscarItemDeMenu(items, tipo) {
5868
6422
  return void 0;
5869
6423
  }
5870
6424
  var PantallaBP = ({ nombre, direccion }) => {
5871
- const navigate = useNavigate6();
5872
6425
  const { clientContext } = useApp();
5873
- const [cargando, setCargando] = useState17(true);
5874
- const [error, setError] = useState17(null);
5875
- const [noExiste, setNoExiste] = useState17(false);
5876
- const contenedor = useRef9(null);
6426
+ const [cargando, setCargando] = useState20(true);
6427
+ const [error, setError] = useState20(null);
6428
+ const [noExiste, setNoExiste] = useState20(false);
6429
+ const contenedor = useRef10(null);
5877
6430
  const menu = clientContext.menu;
5878
- useEffect14(() => {
6431
+ useEffect15(() => {
5879
6432
  const elemento = contenedor.current;
5880
6433
  if (!elemento) return;
5881
6434
  let vigente = true;
5882
6435
  setError(null);
5883
6436
  setNoExiste(false);
5884
6437
  setCargando(true);
5885
- const dejarDeCapturar = capturarNavegacionBP(envConfig.backendUrl, navigate);
5886
6438
  cargarClienteBP(envConfig.backendUrl).then((myOwn) => {
5887
6439
  if (!vigente) return;
5888
6440
  setCargando(false);
@@ -5904,53 +6456,52 @@ var PantallaBP = ({ nombre, direccion }) => {
5904
6456
  });
5905
6457
  return () => {
5906
6458
  vigente = false;
5907
- dejarDeCapturar();
5908
6459
  elemento.replaceChildren();
5909
6460
  };
5910
- }, [nombre, direccion, menu, navigate]);
5911
- if (noExiste) return /* @__PURE__ */ jsx33(FallbackWScreen, { screenName: nombre });
6461
+ }, [nombre, direccion, menu]);
6462
+ if (noExiste) return /* @__PURE__ */ jsx36(FallbackWScreen, { screenName: nombre });
5912
6463
  return (
5913
6464
  // el indicador de carga flota: si ocupara lugar, el contenido de backend-plus empezaría más abajo mientras carga y subiría al terminar
5914
- /* @__PURE__ */ jsxs23(Box24, { sx: { position: "relative" }, children: [
5915
- cargando && /* @__PURE__ */ jsx33(CircularProgress8, { size: 24, sx: { position: "absolute", top: 16, left: 16 } }),
5916
- error && /* @__PURE__ */ jsx33(Alert7, { severity: "error", sx: { m: 2 }, children: error }),
5917
- /* @__PURE__ */ jsx33("div", { id: "main_layout", ref: contenedor }),
5918
- /* @__PURE__ */ jsx33(ConsolaBP, {})
6465
+ /* @__PURE__ */ jsxs27(Box24, { sx: { position: "relative" }, children: [
6466
+ cargando && /* @__PURE__ */ jsx36(CircularProgress8, { size: 24, sx: { position: "absolute", top: 16, left: 16 } }),
6467
+ error && /* @__PURE__ */ jsx36(Alert7, { severity: "error", sx: { m: 2 }, children: error }),
6468
+ /* @__PURE__ */ jsx36("div", { id: "main_layout", ref: contenedor }),
6469
+ /* @__PURE__ */ jsx36(ConsolaBP, {})
5919
6470
  ] })
5920
6471
  );
5921
6472
  };
5922
6473
  var PantallaDeRespaldo = () => {
5923
6474
  const { screenName = "" } = useParams4();
5924
- const { search } = useLocation6();
6475
+ const { search } = useLocation7();
5925
6476
  if (!puenteBPHabilitado()) {
5926
- return /* @__PURE__ */ jsx33(Box24, { sx: { p: 3 }, children: /* @__PURE__ */ jsx33(FallbackWScreen, { screenName }) });
6477
+ return /* @__PURE__ */ jsx36(Box24, { sx: { p: 3 }, children: /* @__PURE__ */ jsx36(FallbackWScreen, { screenName }) });
5927
6478
  }
5928
- return /* @__PURE__ */ jsx33(Navigate3, { to: rutaDePantallaBP(screenName, search), replace: true });
6479
+ return /* @__PURE__ */ jsx36(Navigate3, { to: rutaDePantallaBP(screenName, search), replace: true });
5929
6480
  };
5930
6481
  var PaginaBP = () => {
5931
- const { hash, search } = useLocation6();
6482
+ const { hash, search } = useLocation7();
5932
6483
  const direccion = hash || search;
5933
6484
  const nombre = new URLSearchParams(direccion.replace(/^[#?]/, "")).get("w");
5934
- if (!puenteBPHabilitado()) return /* @__PURE__ */ jsx33(Navigate3, { to: "/", replace: true });
5935
- if (!nombre) return /* @__PURE__ */ jsx33(Box24, { sx: { p: 3 }, children: /* @__PURE__ */ jsxs23(Alert7, { severity: "warning", children: [
6485
+ if (!puenteBPHabilitado()) return /* @__PURE__ */ jsx36(Navigate3, { to: "/", replace: true });
6486
+ if (!nombre) return /* @__PURE__ */ jsx36(Box24, { sx: { p: 3 }, children: /* @__PURE__ */ jsxs27(Alert7, { severity: "warning", children: [
5936
6487
  "Falta la pantalla de backend-plus (",
5937
- /* @__PURE__ */ jsx33("code", { children: "#w=..." }),
6488
+ /* @__PURE__ */ jsx36("code", { children: "#w=..." }),
5938
6489
  ")."
5939
6490
  ] }) });
5940
- return /* @__PURE__ */ jsx33(PantallaBP, { nombre, direccion }, nombre);
6491
+ return /* @__PURE__ */ jsx36(PantallaBP, { nombre, direccion }, nombre);
5941
6492
  };
5942
6493
 
5943
6494
  // src/puente/GrillaBP.tsx
5944
- import { useEffect as useEffect15, useRef as useRef10, useState as useState18 } from "react";
6495
+ import { useEffect as useEffect16, useRef as useRef11, useState as useState21 } from "react";
5945
6496
  import { useParams as useParams5 } from "react-router-dom";
5946
6497
  import { Alert as Alert8, Box as Box25, CircularProgress as CircularProgress9 } from "@mui/material";
5947
- import { jsx as jsx34, jsxs as jsxs24 } from "react/jsx-runtime";
6498
+ import { jsx as jsx37, jsxs as jsxs28 } from "react/jsx-runtime";
5948
6499
  var GrillaBP = ({ tabla, fixedFields }) => {
5949
- const contenedor = useRef10(null);
5950
- const [cargando, setCargando] = useState18(true);
5951
- const [error, setError] = useState18(null);
6500
+ const contenedor = useRef11(null);
6501
+ const [cargando, setCargando] = useState21(true);
6502
+ const [error, setError] = useState21(null);
5952
6503
  const clave = JSON.stringify(fixedFields ?? []);
5953
- useEffect15(() => {
6504
+ useEffect16(() => {
5954
6505
  const elemento = contenedor.current;
5955
6506
  if (!elemento) return;
5956
6507
  let vigente = true;
@@ -5973,69 +6524,122 @@ var GrillaBP = ({ tabla, fixedFields }) => {
5973
6524
  }, [tabla, clave]);
5974
6525
  return (
5975
6526
  // el indicador de carga flota: si ocupara lugar, el contenido de backend-plus empezaría más abajo mientras carga y subiría al terminar
5976
- /* @__PURE__ */ jsxs24(Box25, { sx: { position: "relative" }, children: [
5977
- cargando && /* @__PURE__ */ jsx34(CircularProgress9, { size: 24, sx: { position: "absolute", top: 16, left: 16 } }),
5978
- error && /* @__PURE__ */ jsx34(Alert8, { severity: "error", sx: { m: 2 }, children: error }),
5979
- /* @__PURE__ */ jsx34("div", { ref: contenedor }),
5980
- /* @__PURE__ */ jsx34(ConsolaBP, {})
6527
+ /* @__PURE__ */ jsxs28(Box25, { sx: { position: "relative" }, children: [
6528
+ cargando && /* @__PURE__ */ jsx37(CircularProgress9, { size: 24, sx: { position: "absolute", top: 16, left: 16 } }),
6529
+ error && /* @__PURE__ */ jsx37(Alert8, { severity: "error", sx: { m: 2 }, children: error }),
6530
+ /* @__PURE__ */ jsx37("div", { ref: contenedor }),
6531
+ /* @__PURE__ */ jsx37(ConsolaBP, {})
5981
6532
  ] })
5982
6533
  );
5983
6534
  };
5984
6535
  var PaginaGrillaBP = () => {
5985
6536
  const { tableName = "" } = useParams5();
5986
- return /* @__PURE__ */ jsx34(GrillaBP, { tabla: tableName }, tableName);
6537
+ return /* @__PURE__ */ jsx37(GrillaBP, { tabla: tableName }, tableName);
6538
+ };
6539
+
6540
+ // src/puente/CapturaBP.tsx
6541
+ import { useEffect as useEffect17 } from "react";
6542
+ import { useNavigate as useNavigate5 } from "react-router-dom";
6543
+
6544
+ // src/puente/capturaDeNavegacion.ts
6545
+ function apiDeNavegacion() {
6546
+ const api = Reflect.get(window, "navigation");
6547
+ return typeof api === "object" && api !== null && "addEventListener" in api && typeof api.addEventListener === "function" ? api : null;
6548
+ }
6549
+ function capturarNavegacionBP(urlBackend, navegar) {
6550
+ const alHacerClick = (evento) => {
6551
+ if (evento.defaultPrevented || evento.button !== 0 || evento.ctrlKey || evento.metaKey || evento.shiftKey) return;
6552
+ const enlace = evento.target instanceof Element ? evento.target.closest("a[href]") : null;
6553
+ if (!enlace || enlace.hasAttribute("download") || (enlace.getAttribute("target") ?? "_self") !== "_self") return;
6554
+ const ruta = rutaDeEnlaceBP(enlace.getAttribute("href") ?? "", document.baseURI, urlBackend);
6555
+ if (ruta) {
6556
+ evento.preventDefault();
6557
+ evento.stopPropagation();
6558
+ navegar(ruta);
6559
+ }
6560
+ };
6561
+ document.addEventListener("click", alHacerClick, true);
6562
+ const navegacion = apiDeNavegacion();
6563
+ const alNavegar = (evento) => {
6564
+ if (!evento.cancelable || evento.destination.sameDocument || evento.downloadRequest !== null) return;
6565
+ const ruta = rutaDeEnlaceBP(evento.destination.url, document.baseURI, urlBackend);
6566
+ if (ruta) {
6567
+ evento.preventDefault();
6568
+ navegar(ruta);
6569
+ }
6570
+ };
6571
+ navegacion?.addEventListener("navigate", alNavegar);
6572
+ const reemplazarOriginal = history.replaceState;
6573
+ const reemplazar = (estado, titulo, url) => {
6574
+ const ruta = url === void 0 || url === null ? null : rutaDeEnlaceBP(String(url), document.baseURI, urlBackend);
6575
+ reemplazarOriginal.call(history, estado, titulo, ruta === null ? url : rutaBase + ruta);
6576
+ };
6577
+ history.replaceState = reemplazar;
6578
+ return () => {
6579
+ if (history.replaceState === reemplazar) history.replaceState = reemplazarOriginal;
6580
+ document.removeEventListener("click", alHacerClick, true);
6581
+ navegacion?.removeEventListener("navigate", alNavegar);
6582
+ };
6583
+ }
6584
+
6585
+ // src/puente/CapturaBP.tsx
6586
+ var CapturaBP = () => {
6587
+ const navigate = useNavigate5();
6588
+ useEffect17(() => capturarNavegacionBP(envConfig.backendUrl, navigate), [navigate]);
6589
+ return null;
5987
6590
  };
5988
6591
 
5989
6592
  // src/App.tsx
5990
6593
  import typeStore6 from "type-store";
5991
- import { Fragment as Fragment5, jsx as jsx35, jsxs as jsxs25 } from "react/jsx-runtime";
6594
+ import { Fragment as Fragment6, jsx as jsx38, jsxs as jsxs29 } from "react/jsx-runtime";
5992
6595
  var LocationTracker = () => {
5993
- const location = useLocation7();
6596
+ const location = useLocation8();
5994
6597
  const dispatch = useAppDispatch();
5995
- useEffect16(() => {
6598
+ useEffect18(() => {
5996
6599
  dispatch(setCurrentPath(location.pathname + location.search));
5997
6600
  }, [location, dispatch]);
5998
6601
  return null;
5999
6602
  };
6000
6603
  function FrontendPlusReactRoutes({ myRoutes, myUnloggedRoutes, layout: Layout = MainLayout_default, unloggedLayout: UnloggedLayout }) {
6001
- return /* @__PURE__ */ jsxs25(Fragment5, { children: [
6002
- /* @__PURE__ */ jsx35(InitialRedirectHandler_default, {}),
6003
- /* @__PURE__ */ jsxs25(Routes, { children: [
6004
- /* @__PURE__ */ jsxs25(Route, { element: UnloggedLayout ? /* @__PURE__ */ jsx35(UnloggedLayout, {}) : /* @__PURE__ */ jsx35(Outlet2, {}), children: [
6005
- /* @__PURE__ */ jsx35(Route, { path: "/login", element: /* @__PURE__ */ jsx35(LoginPage_default, {}) }),
6006
- /* @__PURE__ */ jsx35(Route, { path: "/logout", element: /* @__PURE__ */ jsx35(LogoutPage_default, {}) }),
6604
+ return /* @__PURE__ */ jsxs29(Fragment6, { children: [
6605
+ /* @__PURE__ */ jsx38(InitialRedirectHandler_default, {}),
6606
+ puenteBPHabilitado() && /* @__PURE__ */ jsx38(CapturaBP, {}),
6607
+ /* @__PURE__ */ jsxs29(Routes, { children: [
6608
+ /* @__PURE__ */ jsxs29(Route, { element: UnloggedLayout ? /* @__PURE__ */ jsx38(UnloggedLayout, {}) : /* @__PURE__ */ jsx38(Outlet2, {}), children: [
6609
+ /* @__PURE__ */ jsx38(Route, { path: "/login", element: /* @__PURE__ */ jsx38(LoginPage_default, {}) }),
6610
+ /* @__PURE__ */ jsx38(Route, { path: "/logout", element: /* @__PURE__ */ jsx38(LogoutPage_default, {}) }),
6007
6611
  myUnloggedRoutes
6008
6612
  ] }),
6009
- /* @__PURE__ */ jsxs25(Route, { element: /* @__PURE__ */ jsx35(PrivateRoute_default, { children: /* @__PURE__ */ jsx35(Layout, {}) }), children: [
6010
- /* @__PURE__ */ jsx35(Route, { path: "/", element: /* @__PURE__ */ jsx35(PantallaInicial_default, {}) }),
6011
- /* @__PURE__ */ jsx35(Route, { path: "/table/:tableName", element: /* @__PURE__ */ jsx35(GenericDataGridPage_default, {}) }),
6012
- /* @__PURE__ */ jsx35(Route, { path: "/menu/:menuName", element: /* @__PURE__ */ jsx35(MenuTablePage_default, {}) }),
6013
- /* @__PURE__ */ jsx35(Route, { path: "/procedures/:procedureName", element: /* @__PURE__ */ jsx35(ProcedureForm_default, {}) }),
6014
- Object.keys(wScreens).map((screenName) => /* @__PURE__ */ jsx35(
6613
+ /* @__PURE__ */ jsxs29(Route, { element: /* @__PURE__ */ jsx38(PrivateRoute_default, { children: /* @__PURE__ */ jsx38(Layout, {}) }), children: [
6614
+ /* @__PURE__ */ jsx38(Route, { path: "/", element: /* @__PURE__ */ jsx38(PantallaInicial_default, {}) }),
6615
+ /* @__PURE__ */ jsx38(Route, { path: "/table/:tableName", element: /* @__PURE__ */ jsx38(GenericDataGridPage_default, {}) }),
6616
+ /* @__PURE__ */ jsx38(Route, { path: "/menu/:menuName", element: /* @__PURE__ */ jsx38(MenuTablePage_default, {}) }),
6617
+ /* @__PURE__ */ jsx38(Route, { path: "/procedures/:procedureName", element: /* @__PURE__ */ jsx38(ProcedureForm_default, {}) }),
6618
+ Object.keys(wScreens).map((screenName) => /* @__PURE__ */ jsx38(
6015
6619
  Route,
6016
6620
  {
6017
6621
  path: `/wScreens/${screenName}`,
6018
- element: /* @__PURE__ */ jsx35(PantallaDeRuta, { screenName })
6622
+ element: /* @__PURE__ */ jsx38(PantallaDeRuta, { screenName })
6019
6623
  },
6020
6624
  screenName
6021
6625
  )),
6022
- /* @__PURE__ */ jsx35(Route, { path: "/wScreens-fallback/:screenName", element: /* @__PURE__ */ jsx35(PantallaDeRespaldo, {}) }),
6023
- puenteBPHabilitado() && /* @__PURE__ */ jsx35(Route, { path: "/bp/menu", element: /* @__PURE__ */ jsx35(PaginaBP, {}) }),
6024
- puenteBPHabilitado() && /* @__PURE__ */ jsx35(Route, { path: "/bp/table/:tableName", element: /* @__PURE__ */ jsx35(PaginaGrillaBP, {}) }),
6626
+ /* @__PURE__ */ jsx38(Route, { path: "/wScreens-fallback/:screenName", element: /* @__PURE__ */ jsx38(PantallaDeRespaldo, {}) }),
6627
+ puenteBPHabilitado() && /* @__PURE__ */ jsx38(Route, { path: "/bp/menu", element: /* @__PURE__ */ jsx38(PaginaBP, {}) }),
6628
+ puenteBPHabilitado() && /* @__PURE__ */ jsx38(Route, { path: "/bp/table/:tableName", element: /* @__PURE__ */ jsx38(PaginaGrillaBP, {}) }),
6025
6629
  myRoutes,
6026
- /* @__PURE__ */ jsx35(Route, { path: "*", element: /* @__PURE__ */ jsx35("div", { style: { marginTop: "20px", marginLeft: "10px" }, children: "404 - Recurso No Encontrado" }) })
6630
+ /* @__PURE__ */ jsx38(Route, { path: "*", element: /* @__PURE__ */ jsx38("div", { style: { marginTop: "20px", marginLeft: "10px" }, children: "404 - Recurso No Encontrado" }) })
6027
6631
  ] }),
6028
- /* @__PURE__ */ jsx35(Route, { path: "*", element: /* @__PURE__ */ jsx35(Navigate4, { to: "/", replace: true }) })
6632
+ /* @__PURE__ */ jsx38(Route, { path: "*", element: /* @__PURE__ */ jsx38(Navigate4, { to: "/", replace: true }) })
6029
6633
  ] })
6030
6634
  ] });
6031
6635
  }
6032
6636
  var FrontendPlusProviders = ({ children, publicPaths }) => {
6033
- return /* @__PURE__ */ jsx35(Provider, { store, children: /* @__PURE__ */ jsx35(PersistGate, { loading: null, persistor, children: /* @__PURE__ */ jsxs25(BrowserRouter, { basename: rutaBase, children: [
6034
- /* @__PURE__ */ jsx35(LocationTracker, {}),
6637
+ return /* @__PURE__ */ jsx38(Provider, { store, children: /* @__PURE__ */ jsx38(PersistGate, { loading: null, persistor, children: /* @__PURE__ */ jsxs29(BrowserRouter, { basename: rutaBase, children: [
6638
+ /* @__PURE__ */ jsx38(LocationTracker, {}),
6035
6639
  " ",
6036
- /* @__PURE__ */ jsx35(AppProvider, { publicPaths, children: /* @__PURE__ */ jsxs25(SnackbarProvider, { children: [
6640
+ /* @__PURE__ */ jsx38(AppProvider, { publicPaths, children: /* @__PURE__ */ jsxs29(SnackbarProvider, { children: [
6037
6641
  children,
6038
- /* @__PURE__ */ jsx35(SessionExpiredMessage_default, {})
6642
+ /* @__PURE__ */ jsx38(SessionExpiredMessage_default, {})
6039
6643
  ] }) })
6040
6644
  ] }) }) });
6041
6645
  };
@@ -6049,7 +6653,7 @@ var App = ({
6049
6653
  myConditions,
6050
6654
  puenteBP
6051
6655
  }) => {
6052
- useMemo14(() => {
6656
+ useMemo16(() => {
6053
6657
  if (myClientSides) {
6054
6658
  extendClientSides(myClientSides);
6055
6659
  }
@@ -6066,7 +6670,7 @@ var App = ({
6066
6670
  habilitarPuenteBP();
6067
6671
  }
6068
6672
  }, [myClientSides, myResultsOk, myWScreens, myConditions, puenteBP]);
6069
- useEffect16(() => {
6673
+ useEffect18(() => {
6070
6674
  typeStore6.messages = typeStore6.i18n.messages.es;
6071
6675
  typeStore6.locale = typeStore6.i18n.locale.es;
6072
6676
  const link = document.querySelector("link[rel*='icon']") || document.createElement("link");
@@ -6075,11 +6679,11 @@ var App = ({
6075
6679
  link.href = `${envConfig.backendUrl}/img/logo-128.png`;
6076
6680
  document.getElementsByTagName("head")[0].appendChild(link);
6077
6681
  }, []);
6078
- const safePaths = React28.useMemo(() => {
6682
+ const safePaths = React32.useMemo(() => {
6079
6683
  const extracted = extractPathsFromRoutes(myUnloggedRoutes);
6080
6684
  return ["/login", "/logout", ...extracted];
6081
6685
  }, [myUnloggedRoutes]);
6082
- return /* @__PURE__ */ jsx35(FrontendPlusProviders, { publicPaths: safePaths, children: /* @__PURE__ */ jsx35(
6686
+ return /* @__PURE__ */ jsx38(FrontendPlusProviders, { publicPaths: safePaths, children: /* @__PURE__ */ jsx38(
6083
6687
  FrontendPlusReactRoutes,
6084
6688
  {
6085
6689
  myRoutes,