@amsintegra/design-system 1.1.1 → 2.0.1
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/CHANGELOG.md +83 -0
- package/README.md +68 -137
- package/dist/index.cjs +2848 -1034
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1321 -457
- package/dist/index.d.ts +1321 -457
- package/dist/index.js +2630 -631
- package/dist/index.js.map +1 -1
- package/dist/styles.css +2 -0
- package/package.json +17 -27
package/dist/index.js
CHANGED
|
@@ -1,731 +1,2730 @@
|
|
|
1
|
-
import {
|
|
2
|
-
export { Affix, Alert, Anchor, AutoComplete, Avatar, BackTop, Badge, Breadcrumb, Calendar, Carousel, Cascader, Checkbox, Col, Collapse, ColorPicker, DatePicker, Descriptions, Divider, Drawer, Dropdown, Empty, Flex, FloatButton, Form, Image, Input, InputNumber, Layout, List, Mentions, Menu, Modal, Popconfirm, Popover, Progress, QRCode, Radio, Rate, Result, Row, Segmented, Select, Skeleton, Slider, Space, Spin, Splitter, Statistic, Steps, Switch, Table, Tabs, TimePicker, Timeline, Tooltip, Tour, Transfer, Tree, TreeSelect, Typography, Upload, Watermark } from 'antd';
|
|
3
|
-
import { createContext, forwardRef, useContext, useState, useCallback, useMemo, isValidElement, cloneElement, useEffect } from 'react';
|
|
1
|
+
import { createContext, forwardRef, useContext, createElement, useState, useCallback, useEffect, useRef, useId, useLayoutEffect, useMemo, Children, isValidElement } from 'react';
|
|
4
2
|
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
5
|
-
import {
|
|
6
|
-
|
|
3
|
+
import { XCircle, AlertTriangle, CheckCircle2, Clock, Circle, Ellipsis, PlusCircle, KeyRound, GripVertical, Trash2, Search, Bell, Loader2, X, LogOut, Columns3, EyeOff, Eye, Hash, FileText, Activity, Tag, CalendarRange, CalendarClock, Building2, Wallet, User, Copy, Rows2, Rows4, Download, UserX, Timer, Pencil, Mail, FileSpreadsheet, Filter, Sparkles, Save, PauseCircle, Info, LogIn, UserPlus, ShieldAlert, Lock, Coins, Boxes, Gauge, TrendingUp, Link2, ShieldCheck, BarChart3, History, PanelLeftClose, SlidersHorizontal, Users, PanelLeftOpen, MailPlus, Briefcase, BookOpen, Menu, BellRing, Package, Layers, Palette, ArrowUp, ArrowDown, ArrowUpDown, ArrowLeft, ArrowRight, RotateCcw, PlayCircle, RefreshCw, Ban, Check, BellOff, FolderOpen, Calendar, Table2, LayoutGrid } from 'lucide-react';
|
|
4
|
+
import { createPortal } from 'react-dom';
|
|
7
5
|
|
|
8
|
-
// src/
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
pinkActive: "#d9214e",
|
|
24
|
-
pinkLight: "#fff5f8",
|
|
25
|
-
yellow: "#ffc700",
|
|
26
|
-
yellowActive: "#f1bc00",
|
|
27
|
-
yellowLight: "#fff8dd",
|
|
28
|
-
white: "#ffffff",
|
|
29
|
-
gray: {
|
|
30
|
-
100: "#f9f9f9",
|
|
31
|
-
200: "#f4f4f4",
|
|
32
|
-
300: "#e1e3ea",
|
|
33
|
-
400: "#b5b5c3",
|
|
34
|
-
500: "#a1a5b7",
|
|
35
|
-
600: "#7e8299",
|
|
36
|
-
700: "#5e6278",
|
|
37
|
-
800: "#3f4254",
|
|
38
|
-
900: "#181c32"
|
|
39
|
-
},
|
|
40
|
-
background: {
|
|
41
|
-
app: "#f5f8fa",
|
|
42
|
-
body: "#ffffff",
|
|
43
|
-
appDark: "#151521",
|
|
44
|
-
bodyDark: "#1e1e2d"
|
|
45
|
-
},
|
|
46
|
-
dark: {
|
|
47
|
-
base: "#181c32",
|
|
48
|
-
bg: "#151521",
|
|
49
|
-
header: "#1e1e2d",
|
|
50
|
-
active: "#2a2a3c",
|
|
51
|
-
separator: "#393945",
|
|
52
|
-
// Dark-mode surfaces (from mf-container's antdTheme).
|
|
53
|
-
inputBg: "#1b1b29",
|
|
54
|
-
cardBg: "#1e1e2d",
|
|
55
|
-
// Dark-mode gray scale — DISTINCT from the light `gray` scale (Metronic).
|
|
56
|
-
gray: {
|
|
57
|
-
100: "#2b2b40",
|
|
58
|
-
200: "#323248",
|
|
59
|
-
300: "#3b3b64",
|
|
60
|
-
400: "#474761",
|
|
61
|
-
500: "#565674",
|
|
62
|
-
600: "#6d6d80",
|
|
63
|
-
700: "#92929f",
|
|
64
|
-
800: "#cdcdde"
|
|
65
|
-
}
|
|
66
|
-
}
|
|
67
|
-
};
|
|
68
|
-
var radius = {
|
|
69
|
-
sm: 2,
|
|
70
|
-
base: 4,
|
|
71
|
-
md: 6,
|
|
72
|
-
lg: 8,
|
|
73
|
-
xl: 12
|
|
6
|
+
// src/kit/lib/tema.ts
|
|
7
|
+
var NOMBRE_PRODUCTO_DEFAULT = "Backoffice";
|
|
8
|
+
var TEMA_DEFAULT = {
|
|
9
|
+
logo_url: null,
|
|
10
|
+
color_primario: "#A72432",
|
|
11
|
+
color_primario_oscuro: "#8B1D28",
|
|
12
|
+
color_acento: "#C9414D",
|
|
13
|
+
color_peligro: "#A72432",
|
|
14
|
+
color_fondo: "#ffffff",
|
|
15
|
+
color_texto: "#0b1f33",
|
|
16
|
+
color_borde: "#e2e8f0",
|
|
17
|
+
badge_exito: "#e6f4ea",
|
|
18
|
+
badge_advertencia: "#fdf1de",
|
|
19
|
+
badge_error: "#fbe9e9",
|
|
20
|
+
badge_neutro: "#ececec"
|
|
74
21
|
};
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
22
|
+
function variablesDeTema(tema) {
|
|
23
|
+
return {
|
|
24
|
+
...tema.color_acento ? { "--tema-acento": tema.color_acento } : {},
|
|
25
|
+
// El spinner de marca se pinta con el logo; sin logo rige el icono neutro de `globals.css`.
|
|
26
|
+
...tema.logo_url ? { "--tema-logo-spinner": `url("${tema.logo_url}")` } : {},
|
|
27
|
+
"--tema-primario": tema.color_primario,
|
|
28
|
+
"--tema-primario-oscuro": tema.color_primario_oscuro,
|
|
29
|
+
"--tema-peligro": tema.color_peligro,
|
|
30
|
+
"--tema-fondo": tema.color_fondo,
|
|
31
|
+
"--tema-texto": tema.color_texto,
|
|
32
|
+
"--tema-borde": tema.color_borde,
|
|
33
|
+
"--tema-badge-exito": tema.badge_exito,
|
|
34
|
+
"--tema-badge-advertencia": tema.badge_advertencia,
|
|
35
|
+
"--tema-badge-error": tema.badge_error,
|
|
36
|
+
"--tema-badge-neutro": tema.badge_neutro
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
var LinkComponentContext = createContext(null);
|
|
40
|
+
var LinkComponentProvider = LinkComponentContext.Provider;
|
|
41
|
+
var LinkBase = forwardRef(function LinkBase2({ href, children, ...rest }, ref) {
|
|
42
|
+
const Injected = useContext(LinkComponentContext);
|
|
43
|
+
if (Injected) {
|
|
44
|
+
return createElement(Injected, { href, children, ...rest });
|
|
45
|
+
}
|
|
46
|
+
return /* @__PURE__ */ jsx("a", { ref, href, ...rest, children });
|
|
47
|
+
});
|
|
48
|
+
var ListadoNavContext = createContext(null);
|
|
49
|
+
var ListadoNavProvider = ListadoNavContext.Provider;
|
|
50
|
+
function useNavegarListado() {
|
|
51
|
+
const ctx = useContext(ListadoNavContext);
|
|
52
|
+
if (!ctx) {
|
|
53
|
+
throw new Error(
|
|
54
|
+
"useNavegarListado must be used within a <ListadoNavProvider>. Wrap your listing screen and provide { ir, pendiente, params } connected to your router or local state."
|
|
55
|
+
);
|
|
84
56
|
}
|
|
57
|
+
return ctx;
|
|
58
|
+
}
|
|
59
|
+
var TAMANO_BADGE = 16;
|
|
60
|
+
var TAMANO_BOTON = 20;
|
|
61
|
+
var ICONO_DEFAULT = Circle;
|
|
62
|
+
var ICONO_NAV_DASHBOARD = Activity;
|
|
63
|
+
var ICONO_NAV_SALUD = Gauge;
|
|
64
|
+
var ICONO_NAV_ANALITICA = BarChart3;
|
|
65
|
+
var ICONO_NAV_ENTIDADES = Users;
|
|
66
|
+
var ICONO_NAV_INVITACIONES = MailPlus;
|
|
67
|
+
var ICONO_NAV_ETIQUETAS = Tag;
|
|
68
|
+
var ICONO_NAV_JOBS = Briefcase;
|
|
69
|
+
var ICONO_NAV_TEMA = Palette;
|
|
70
|
+
var ICONO_NAV_CONFIGURACION = SlidersHorizontal;
|
|
71
|
+
var ICONO_NAV_API_KEYS = KeyRound;
|
|
72
|
+
var ICONO_NAV_BITACORA = History;
|
|
73
|
+
var ICONO_NAV_NOTIFICACIONES = BellRing;
|
|
74
|
+
var ICONO_NAV_MANUAL = BookOpen;
|
|
75
|
+
var ICONO_NAV_CLIENTE = KeyRound;
|
|
76
|
+
var ICONO_NAV_EXTRACCIONES = FileSpreadsheet;
|
|
77
|
+
var ICONO_CERRAR_SESION = LogOut;
|
|
78
|
+
var ICONO_INICIAR_SESION = LogIn;
|
|
79
|
+
var ICONO_NAV_COLAPSAR = PanelLeftClose;
|
|
80
|
+
var ICONO_NAV_EXPANDIR = PanelLeftOpen;
|
|
81
|
+
var ICONO_NAV_MENU_MOVIL = Menu;
|
|
82
|
+
var ICONO_CERRAR = X;
|
|
83
|
+
var ICONO_ALTA = PlusCircle;
|
|
84
|
+
var ICONO_GENERAR = Sparkles;
|
|
85
|
+
var ICONO_GUARDAR = Save;
|
|
86
|
+
var ICONO_EDITAR = Pencil;
|
|
87
|
+
var ICONO_BAJA = Trash2;
|
|
88
|
+
var ICONO_DESHABILITAR = UserX;
|
|
89
|
+
var ICONO_INACTIVAR = PauseCircle;
|
|
90
|
+
var ICONO_REACTIVAR_ETIQUETA = PlayCircle;
|
|
91
|
+
var ICONO_REACTIVAR = RotateCcw;
|
|
92
|
+
var ICONO_RESTABLECER = RotateCcw;
|
|
93
|
+
var ICONO_REINTENTAR = RefreshCw;
|
|
94
|
+
var ICONO_COPIAR = Copy;
|
|
95
|
+
var ICONO_LINK = Link2;
|
|
96
|
+
var ICONO_DESCARGAR = Download;
|
|
97
|
+
var ICONO_EXPORTAR = FileSpreadsheet;
|
|
98
|
+
var ICONO_EXPORTAR_CSV = Download;
|
|
99
|
+
var ICONO_CONFIRMAR = CheckCircle2;
|
|
100
|
+
var ICONO_VOLVER = ArrowLeft;
|
|
101
|
+
var ICONO_VER_TODOS = ArrowRight;
|
|
102
|
+
var ICONO_ROTAR_KEY = RotateCcw;
|
|
103
|
+
var ICONO_REVOCAR_KEY = Ban;
|
|
104
|
+
var ICONO_API_KEY = KeyRound;
|
|
105
|
+
var ICONO_EMAIL = Mail;
|
|
106
|
+
var ICONO_INVITACION_GENERICA = UserPlus;
|
|
107
|
+
var ICONO_SEGURIDAD = ShieldCheck;
|
|
108
|
+
var ICONO_CAMPANA = Bell;
|
|
109
|
+
var ICONO_SILENCIAR = BellOff;
|
|
110
|
+
var ICONO_FILTRO = Filter;
|
|
111
|
+
var ICONO_BUSCAR = Search;
|
|
112
|
+
var ICONO_LIMPIAR = X;
|
|
113
|
+
var ICONO_SELECCIONADO = Check;
|
|
114
|
+
var ICONO_ORDENAR_ASC = ArrowUp;
|
|
115
|
+
var ICONO_ORDENAR_DESC = ArrowDown;
|
|
116
|
+
var ICONO_ORDENAR_NEUTRO = ArrowUpDown;
|
|
117
|
+
var ICONO_PAGINA_ANTERIOR = ArrowLeft;
|
|
118
|
+
var ICONO_PAGINA_SIGUIENTE = ArrowRight;
|
|
119
|
+
var ICONO_VISTA_TABLA = Table2;
|
|
120
|
+
var ICONO_VISTA_TARJETAS = LayoutGrid;
|
|
121
|
+
var ICONO_ARRASTRAR_COLUMNA = GripVertical;
|
|
122
|
+
var ICONO_COLUMNAS = Columns3;
|
|
123
|
+
var ICONO_COLUMNA_VISIBLE = Eye;
|
|
124
|
+
var ICONO_COLUMNA_OCULTA = EyeOff;
|
|
125
|
+
var ICONO_ACCIONES_FILA = Ellipsis;
|
|
126
|
+
var ICONO_DENSIDAD_COMPACTA = Rows4;
|
|
127
|
+
var ICONO_DENSIDAD_COMODA = Rows2;
|
|
128
|
+
var ICONO_CARGANDO = Loader2;
|
|
129
|
+
var ICONO_INFO_EXPLICACION = Info;
|
|
130
|
+
var ICONO_COL_CODIGO = Hash;
|
|
131
|
+
var ICONO_COL_NOMBRE = Building2;
|
|
132
|
+
var ICONO_COL_ESTADO = Activity;
|
|
133
|
+
var ICONO_COL_MECANISMO = KeyRound;
|
|
134
|
+
var ICONO_COL_TOTAL = Wallet;
|
|
135
|
+
var ICONO_COL_FECHA = CalendarRange;
|
|
136
|
+
var ICONO_COL_FECHA_HORA = CalendarClock;
|
|
137
|
+
var ICONO_COL_ETIQUETA = Tag;
|
|
138
|
+
var ICONO_COL_USUARIO = User;
|
|
139
|
+
var ICONO_COL_DOCUMENTO = FileText;
|
|
140
|
+
var ICONO_PERIODO = CalendarRange;
|
|
141
|
+
var ICONO_VIGENCIA = Calendar;
|
|
142
|
+
var ICONO_DURACION = Timer;
|
|
143
|
+
var ICONO_UBICACION = FolderOpen;
|
|
144
|
+
var ICONOS_ESTATUS = {
|
|
145
|
+
pendiente: Circle,
|
|
146
|
+
procesando: Clock,
|
|
147
|
+
hecha: CheckCircle2,
|
|
148
|
+
gap: AlertTriangle,
|
|
149
|
+
fallida: XCircle
|
|
85
150
|
};
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
151
|
+
function iconoDeEstatus(estado) {
|
|
152
|
+
return ICONOS_ESTATUS[estado] ?? ICONO_DEFAULT;
|
|
153
|
+
}
|
|
154
|
+
var ICONOS_SEMAFORO = {
|
|
155
|
+
verde: CheckCircle2,
|
|
156
|
+
ambar: AlertTriangle,
|
|
157
|
+
rojo: XCircle
|
|
89
158
|
};
|
|
90
|
-
var
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
colorInfo: primitives.purple,
|
|
95
|
-
colorError: primitives.pink,
|
|
96
|
-
colorWarning: primitives.yellow,
|
|
97
|
-
// Links. Metronic inherits link color from the (red) primary, which reads as
|
|
98
|
-
// "danger" in dense UIs. The AMS default uses a neutral dark gray so links
|
|
99
|
-
// don't look like errors; consumers can override `colorLink`/`colorLinkHover`
|
|
100
|
-
// via AmsConfigProvider's `theme` prop (e.g. back to the brand red or blue).
|
|
101
|
-
colorLink: primitives.gray[800],
|
|
102
|
-
colorLinkHover: primitives.brandRed,
|
|
103
|
-
colorLinkActive: primitives.brandRedActive,
|
|
104
|
-
colorBgLayout: primitives.background.app,
|
|
105
|
-
colorBgContainer: primitives.background.body,
|
|
106
|
-
borderRadius: radius.base,
|
|
107
|
-
fontFamily: typography.fontFamily,
|
|
108
|
-
fontSize: typography.fontSizeBase,
|
|
109
|
-
controlHeight: sizing.controlHeight
|
|
159
|
+
var ETIQUETAS_SEMAFORO = {
|
|
160
|
+
verde: "verde (en linea)",
|
|
161
|
+
ambar: "ambar (advertencia)",
|
|
162
|
+
rojo: "rojo (critico)"
|
|
110
163
|
};
|
|
164
|
+
function iconoDeSemaforo(color) {
|
|
165
|
+
return ICONOS_SEMAFORO[color] ?? Circle;
|
|
166
|
+
}
|
|
167
|
+
function etiquetaSemaforo(color) {
|
|
168
|
+
return ETIQUETAS_SEMAFORO[color] ?? color;
|
|
169
|
+
}
|
|
170
|
+
var ICONO_AVISO = AlertTriangle;
|
|
171
|
+
var ICONO_ERROR = XCircle;
|
|
172
|
+
var ICONO_OK = CheckCircle2;
|
|
173
|
+
var ICONO_KPI_RITMO = TrendingUp;
|
|
174
|
+
var ICONO_KPI_RENDIMIENTO = Gauge;
|
|
175
|
+
var ICONO_KPI_CONTEO = Boxes;
|
|
176
|
+
var ICONO_KPI_CREDENCIALES = KeyRound;
|
|
177
|
+
var ICONO_KPI_ALERTA = ShieldAlert;
|
|
178
|
+
var ICONO_KPI_CONSUMO = Coins;
|
|
179
|
+
var ICONO_KPI_BLOQUEO = Lock;
|
|
180
|
+
var ICONO_NAV_PLANES = Layers;
|
|
181
|
+
var ICONO_NAV_PAQUETES = Package;
|
|
182
|
+
var ICONO_NAV_ACCESOS = ShieldCheck;
|
|
183
|
+
var ICONO_NAV_USUARIOS = Users;
|
|
184
|
+
var ICONO_LOGIN_MICROSOFT = LogIn;
|
|
111
185
|
|
|
112
|
-
// src/
|
|
113
|
-
var
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
itemSelectedColor: semantic.colorPrimary,
|
|
158
|
-
itemHoverColor: semantic.colorPrimary
|
|
159
|
-
}
|
|
160
|
-
};
|
|
161
|
-
var lightComponents = {
|
|
162
|
-
...sharedComponents,
|
|
163
|
-
Table: {
|
|
164
|
-
headerBg: primitives.gray[100],
|
|
165
|
-
headerColor: primitives.gray[800],
|
|
166
|
-
borderColor: primitives.gray[300],
|
|
167
|
-
cellPaddingBlock: 8,
|
|
168
|
-
cellPaddingInline: 8
|
|
169
|
-
}
|
|
170
|
-
};
|
|
171
|
-
var darkComponents = {
|
|
172
|
-
...sharedComponents,
|
|
173
|
-
Table: {
|
|
174
|
-
headerBg: primitives.dark.gray[200],
|
|
175
|
-
headerColor: primitives.dark.gray[800],
|
|
176
|
-
borderColor: primitives.dark.gray[400],
|
|
177
|
-
rowHoverBg: primitives.dark.gray[200],
|
|
178
|
-
cellPaddingBlock: 8,
|
|
179
|
-
cellPaddingInline: 8
|
|
186
|
+
// src/kit/lib/explicaciones.ts
|
|
187
|
+
var EXPLICACIONES = {
|
|
188
|
+
// ───────────────────────────── plataforma.* (usados por los componentes del kit) ─────────────────────────────
|
|
189
|
+
"plataforma.rol": {
|
|
190
|
+
titulo: "Rol del usuario",
|
|
191
|
+
que_es: "Tu nivel de acceso en este sistema, por ejemplo administrador, operador o consulta.",
|
|
192
|
+
como_se_calcula: "Se resuelve al iniciar sesi\xF3n seg\xFAn tu asignaci\xF3n; no se calcula.",
|
|
193
|
+
de_donde_sale: "Asignaci\xF3n de rol del usuario en el directorio de acceso.",
|
|
194
|
+
como_leerlo: "Determina qu\xE9 m\xF3dulos ves y qu\xE9 acciones puedes ejecutar en cada tabla."
|
|
195
|
+
},
|
|
196
|
+
"plataforma.listado_resultados": {
|
|
197
|
+
titulo: "Resultados del listado",
|
|
198
|
+
que_es: "Cu\xE1ntas filas cumplen la b\xFAsqueda y los filtros actuales frente al total del listado.",
|
|
199
|
+
como_se_calcula: "Se cuentan las filas cuyo texto contiene lo buscado, sin distinguir may\xFAsculas ni acentos, y que cumplen cada filtro. La tabla muestra una p\xE1gina de 25, 50 o 100 de ellas.",
|
|
200
|
+
de_donde_sale: "Lista que ya trae la pantalla; la b\xFAsqueda, los filtros, el orden y la p\xE1gina viajan en la direcci\xF3n (URL).",
|
|
201
|
+
como_leerlo: "Si dice N en total no hay filtro activo. Copiar la direcci\xF3n comparte la misma vista."
|
|
202
|
+
},
|
|
203
|
+
"plataforma.tabla_columnas": {
|
|
204
|
+
titulo: "Columnas de la tabla",
|
|
205
|
+
que_es: "Lista para mostrar u ocultar las columnas de esta tabla que no est\xE1n fijas. Las columnas de identidad y la de acciones siempre se ven.",
|
|
206
|
+
como_se_calcula: "Cada casilla desmarcada oculta esa columna en pantalla; no cambia los datos, el orden, los filtros ni lo que se exporta.",
|
|
207
|
+
de_donde_sale: "Preferencia guardada en este navegador, por tabla y por usuario. Restablecer la borra y vuelve a mostrar todas las columnas con la densidad c\xF3moda.",
|
|
208
|
+
como_leerlo: "Si falta una columna que esperabas, revisa esta lista. Con el almacenamiento del navegador bloqueado (modo privado) la elecci\xF3n dura solo mientras la p\xE1gina siga abierta."
|
|
209
|
+
},
|
|
210
|
+
"plataforma.tabla_densidad": {
|
|
211
|
+
titulo: "Densidad de la tabla",
|
|
212
|
+
que_es: "Alto de las filas: compacta muestra m\xE1s filas por pantalla; c\xF3moda deja m\xE1s aire entre ellas.",
|
|
213
|
+
como_se_calcula: "Compacta reduce el relleno vertical de cada celda; no cambia el texto ni las columnas.",
|
|
214
|
+
de_donde_sale: "Preferencia guardada en este navegador, por tabla y por usuario, junto con las columnas ocultas.",
|
|
215
|
+
como_leerlo: "La tabla se desplaza dentro de su propio marco: la barra horizontal queda al pie de la pantalla, el encabezado arriba y las columnas de identidad y acciones fijas a los lados. Shift + rueda del rat\xF3n desplaza a lo ancho."
|
|
216
|
+
},
|
|
217
|
+
// ───────────────────────────── ejemplos del Backoffice (examples/) ─────────────────────────────
|
|
218
|
+
"inicio.planes_activos": {
|
|
219
|
+
titulo: "Planes activos",
|
|
220
|
+
que_es: "N\xFAmero de planes del cat\xE1logo que hoy se pueden contratar.",
|
|
221
|
+
como_se_calcula: "Conteo de planes con estado Activo; los borradores y los archivados no cuentan.",
|
|
222
|
+
de_donde_sale: "Cat\xE1logo de planes del backoffice (ejemplo con datos ficticios).",
|
|
223
|
+
como_leerlo: "Un plan archivado deja de contar aunque tenga clientes vigentes; esos clientes conservan su plan hasta renovar."
|
|
224
|
+
},
|
|
225
|
+
"inicio.paquetes": {
|
|
226
|
+
titulo: "Paquetes",
|
|
227
|
+
que_es: "N\xFAmero de paquetes de consumo definidos en el cat\xE1logo.",
|
|
228
|
+
como_se_calcula: "Conteo de paquetes registrados, sin importar su estado.",
|
|
229
|
+
de_donde_sale: "Cat\xE1logo de paquetes del backoffice (ejemplo con datos ficticios).",
|
|
230
|
+
como_leerlo: "Un paquete puede estar asociado a varios planes; aqu\xED se cuenta una sola vez."
|
|
180
231
|
},
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
232
|
+
"inicio.accesos_vigentes": {
|
|
233
|
+
titulo: "Accesos vigentes",
|
|
234
|
+
que_es: "Usuarios con acceso al backoffice que no est\xE1n suspendidos ni vencidos.",
|
|
235
|
+
como_se_calcula: "Conteo de usuarios con estado Activo y fecha de vencimiento futura o sin vencimiento.",
|
|
236
|
+
de_donde_sale: "Registro de accesos del backoffice (ejemplo con datos ficticios).",
|
|
237
|
+
como_leerlo: "Un usuario con rol de solo consulta cuenta igual que uno administrador."
|
|
185
238
|
},
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
239
|
+
"inicio.cobertura": {
|
|
240
|
+
titulo: "Cobertura del cat\xE1logo",
|
|
241
|
+
que_es: "Porcentaje de planes que ya tienen al menos un paquete asignado.",
|
|
242
|
+
como_se_calcula: "Planes con al menos un paquete entre planes activos, por 100.",
|
|
243
|
+
de_donde_sale: "Relaci\xF3n plan-paquete del cat\xE1logo (ejemplo con datos ficticios).",
|
|
244
|
+
como_leerlo: "Menos de 100 % indica planes sin paquete: no se pueden vender hasta que se les asigne uno."
|
|
190
245
|
},
|
|
191
|
-
|
|
192
|
-
|
|
246
|
+
"inicio.resumen_catalogo": {
|
|
247
|
+
titulo: "Resumen del cat\xE1logo",
|
|
248
|
+
que_es: "Planes agrupados por estado, con el total de paquetes que suman.",
|
|
249
|
+
como_se_calcula: "Cada plan cae en un solo estado; los paquetes de una fila son la suma de los paquetes de sus planes.",
|
|
250
|
+
de_donde_sale: "Cat\xE1logo de planes y paquetes del backoffice (ejemplo con datos ficticios).",
|
|
251
|
+
como_leerlo: "Un paquete compartido por dos planes se cuenta una vez por cada plan."
|
|
193
252
|
},
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
253
|
+
"planes.col_codigo": {
|
|
254
|
+
titulo: "C\xF3digo",
|
|
255
|
+
que_es: "Identificador corto y estable del plan.",
|
|
256
|
+
como_se_calcula: "Se captura al crear el plan; no se calcula ni se puede repetir.",
|
|
257
|
+
de_donde_sale: "Cat\xE1logo de planes (ejemplo con datos ficticios).",
|
|
258
|
+
como_leerlo: "Se usa en integraciones y reportes; el nombre comercial puede cambiar, el c\xF3digo no."
|
|
197
259
|
},
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
260
|
+
"planes.col_nombre": {
|
|
261
|
+
titulo: "Nombre",
|
|
262
|
+
que_es: "Nombre comercial del plan tal como lo ve el cliente.",
|
|
263
|
+
como_se_calcula: "Se captura al crear o editar el plan; no se calcula.",
|
|
264
|
+
de_donde_sale: "Cat\xE1logo de planes (ejemplo con datos ficticios).",
|
|
265
|
+
como_leerlo: "La b\xFAsqueda ignora may\xFAsculas y acentos."
|
|
201
266
|
},
|
|
202
|
-
|
|
203
|
-
|
|
267
|
+
"planes.col_precio": {
|
|
268
|
+
titulo: "Precio mensual",
|
|
269
|
+
que_es: "Precio de lista del plan por mes, en pesos, sin impuestos.",
|
|
270
|
+
como_se_calcula: "Se captura al crear o editar el plan; no se calcula.",
|
|
271
|
+
de_donde_sale: "Cat\xE1logo de planes (ejemplo con datos ficticios).",
|
|
272
|
+
como_leerlo: "Es precio de lista: un contrato puede tener un descuento que no se refleja aqu\xED."
|
|
204
273
|
},
|
|
205
|
-
|
|
206
|
-
|
|
274
|
+
"planes.col_estado": {
|
|
275
|
+
titulo: "Estado del plan",
|
|
276
|
+
que_es: "Situaci\xF3n del plan en el cat\xE1logo: Activo, Borrador o Archivado.",
|
|
277
|
+
como_se_calcula: "Lo fija el administrador al publicar o archivar; no se calcula.",
|
|
278
|
+
de_donde_sale: "Cat\xE1logo de planes (ejemplo con datos ficticios).",
|
|
279
|
+
como_leerlo: "Solo los planes Activos se pueden contratar. Archivado conserva el historial pero no admite altas nuevas."
|
|
207
280
|
},
|
|
208
|
-
|
|
209
|
-
|
|
281
|
+
"planes.col_actualizado": {
|
|
282
|
+
titulo: "Actualizado",
|
|
283
|
+
que_es: "Fecha y hora de la \xFAltima modificaci\xF3n del plan, en tu hora local.",
|
|
284
|
+
como_se_calcula: "Se registra en UTC al guardar cambios y el navegador la convierte a tu zona horaria.",
|
|
285
|
+
de_donde_sale: "Bit\xE1cora de cambios del cat\xE1logo (ejemplo con datos ficticios).",
|
|
286
|
+
como_leerlo: "Cambiar solo el estado tambi\xE9n actualiza esta fecha."
|
|
210
287
|
},
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
subMenuItemBg: primitives.background.bodyDark
|
|
288
|
+
"planes.estado_activo": {
|
|
289
|
+
titulo: "Activo",
|
|
290
|
+
que_es: "El plan est\xE1 publicado y se puede contratar.",
|
|
291
|
+
como_se_calcula: "Estado asignado al publicar el plan.",
|
|
292
|
+
de_donde_sale: "Cat\xE1logo de planes (ejemplo con datos ficticios).",
|
|
293
|
+
como_leerlo: "Para retirarlo del cat\xE1logo, arch\xEDvalo; no lo borres."
|
|
218
294
|
},
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
295
|
+
"planes.estado_borrador": {
|
|
296
|
+
titulo: "Borrador",
|
|
297
|
+
que_es: "El plan se est\xE1 preparando y a\xFAn no es visible para contratar.",
|
|
298
|
+
como_se_calcula: "Estado inicial de todo plan nuevo.",
|
|
299
|
+
de_donde_sale: "Cat\xE1logo de planes (ejemplo con datos ficticios).",
|
|
300
|
+
como_leerlo: "Publica el plan cuando tenga precio y al menos un paquete."
|
|
301
|
+
},
|
|
302
|
+
"planes.estado_archivado": {
|
|
303
|
+
titulo: "Archivado",
|
|
304
|
+
que_es: "El plan se retir\xF3 del cat\xE1logo; conserva su historial.",
|
|
305
|
+
como_se_calcula: "Estado asignado al archivar un plan activo.",
|
|
306
|
+
de_donde_sale: "Cat\xE1logo de planes (ejemplo con datos ficticios).",
|
|
307
|
+
como_leerlo: "No admite altas nuevas; los clientes existentes conservan su plan hasta renovar."
|
|
222
308
|
}
|
|
223
309
|
};
|
|
224
|
-
function
|
|
225
|
-
const
|
|
310
|
+
function explicacionDe(id) {
|
|
311
|
+
const entrada = EXPLICACIONES[id];
|
|
312
|
+
if (!entrada) throw new Error(`Explicaci\xF3n desconocida: ${id}`);
|
|
313
|
+
return entrada;
|
|
314
|
+
}
|
|
315
|
+
function verificarCatalogo() {
|
|
316
|
+
const problemas = [];
|
|
317
|
+
for (const [id, e] of Object.entries(EXPLICACIONES)) {
|
|
318
|
+
if (!/^[a-z0-9_]+\.[a-z0-9_]+$/.test(id)) problemas.push(`${id}: id invalido`);
|
|
319
|
+
for (const [campo, texto] of Object.entries(e)) {
|
|
320
|
+
if (texto.length > 320) problemas.push(`${id}.${campo}: mas de 320 caracteres`);
|
|
321
|
+
if (/["\\\n]/.test(texto)) problemas.push(`${id}.${campo}: comillas dobles, barra invertida o salto de linea`);
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
return problemas;
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
// src/kit/lib/listado.ts
|
|
328
|
+
var TAMANOS_LISTADO = [25, 50, 100];
|
|
329
|
+
var TAMANO_LISTADO_DEFAULT = 25;
|
|
330
|
+
function normalizarTexto(s) {
|
|
331
|
+
return s.normalize("NFD").replace(/[̀-ͯ]/g, "").toLowerCase().replace(/\s+/g, " ").trim();
|
|
332
|
+
}
|
|
333
|
+
function primero(v) {
|
|
334
|
+
return (Array.isArray(v) ? v[0] : v) ?? "";
|
|
335
|
+
}
|
|
336
|
+
function leerListado(sp, opc) {
|
|
337
|
+
const pagina = Number.parseInt(primero(sp.pagina), 10);
|
|
338
|
+
const tamano = Number.parseInt(primero(sp.tamano), 10);
|
|
339
|
+
const orden = primero(sp.orden);
|
|
340
|
+
const dir = primero(sp.dir);
|
|
341
|
+
const filtros = {};
|
|
342
|
+
for (const clave of opc.filtros) {
|
|
343
|
+
const valor = primero(sp[clave]).trim();
|
|
344
|
+
if (valor) filtros[clave] = valor;
|
|
345
|
+
}
|
|
226
346
|
return {
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
347
|
+
q: primero(sp.q).trim(),
|
|
348
|
+
pagina: Number.isFinite(pagina) && pagina >= 1 ? pagina : 1,
|
|
349
|
+
tamano: TAMANOS_LISTADO.includes(tamano) ? tamano : TAMANO_LISTADO_DEFAULT,
|
|
350
|
+
orden: opc.ordenes.includes(orden) ? orden : opc.ordenDefault,
|
|
351
|
+
dir: dir === "asc" || dir === "desc" ? dir : opc.dirDefault ?? "asc",
|
|
352
|
+
filtros
|
|
230
353
|
};
|
|
231
354
|
}
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
function
|
|
236
|
-
|
|
237
|
-
const
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
355
|
+
function ausente(v) {
|
|
356
|
+
return v === void 0 || v === null || v === "" || typeof v === "number" && Number.isNaN(v);
|
|
357
|
+
}
|
|
358
|
+
function aplicarListado(items, estado, def) {
|
|
359
|
+
const aguja = normalizarTexto(estado.q);
|
|
360
|
+
const filtrados = items.filter(
|
|
361
|
+
(it) => (!aguja || normalizarTexto(def.texto(it)).includes(aguja)) && (!def.filtrar || def.filtrar(it, estado.filtros))
|
|
362
|
+
);
|
|
363
|
+
const valor = def.valoresOrden[estado.orden];
|
|
364
|
+
if (valor) {
|
|
365
|
+
const factor = estado.dir === "asc" ? 1 : -1;
|
|
366
|
+
filtrados.sort((a, b) => {
|
|
367
|
+
const va = valor(a);
|
|
368
|
+
const vb = valor(b);
|
|
369
|
+
if (ausente(va) && ausente(vb)) return 0;
|
|
370
|
+
if (ausente(va)) return 1;
|
|
371
|
+
if (ausente(vb)) return -1;
|
|
372
|
+
if (typeof va === "number" && typeof vb === "number") return (va - vb) * factor;
|
|
373
|
+
return String(va).localeCompare(String(vb), "es", { sensitivity: "base" }) * factor;
|
|
374
|
+
});
|
|
252
375
|
}
|
|
253
|
-
|
|
376
|
+
const totalPaginas = Math.max(1, Math.ceil(filtrados.length / estado.tamano));
|
|
377
|
+
const pagina = Math.min(estado.pagina, totalPaginas);
|
|
378
|
+
const inicio = (pagina - 1) * estado.tamano;
|
|
379
|
+
return {
|
|
380
|
+
itemsPagina: filtrados.slice(inicio, inicio + estado.tamano),
|
|
381
|
+
totalFiltrado: filtrados.length,
|
|
382
|
+
total: items.length,
|
|
383
|
+
pagina,
|
|
384
|
+
totalPaginas
|
|
385
|
+
};
|
|
254
386
|
}
|
|
255
|
-
function
|
|
256
|
-
const
|
|
257
|
-
|
|
258
|
-
|
|
387
|
+
function hrefListado(ruta, actual, cambios) {
|
|
388
|
+
const params = new URLSearchParams(actual);
|
|
389
|
+
if (!("pagina" in cambios)) params.delete("pagina");
|
|
390
|
+
for (const [clave, valor] of Object.entries(cambios)) {
|
|
391
|
+
if (valor === null || valor === void 0 || valor === "" || clave === "pagina" && valor === "1") {
|
|
392
|
+
params.delete(clave);
|
|
393
|
+
} else {
|
|
394
|
+
params.set(clave, valor);
|
|
395
|
+
}
|
|
396
|
+
}
|
|
397
|
+
const qs = params.toString();
|
|
398
|
+
return qs ? `${ruta}?${qs}` : ruta;
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
// src/kit/lib/formato.ts
|
|
402
|
+
var NO_DISPONIBLE = "\u2014";
|
|
403
|
+
var DECIMAL = /^(-?)(\d+)(?:\.(\d+))?$/;
|
|
404
|
+
function partes(texto) {
|
|
405
|
+
const m = DECIMAL.exec(texto.trim());
|
|
406
|
+
return m ? { signo: m[1], entero: m[2], fraccion: m[3] ?? "" } : null;
|
|
407
|
+
}
|
|
408
|
+
var miles = (entero) => entero.replace(/\B(?=(\d{3})+(?!\d))/g, ",");
|
|
409
|
+
function formatoMxn(valor) {
|
|
410
|
+
if (valor == null) return NO_DISPONIBLE;
|
|
411
|
+
const p = partes(valor);
|
|
412
|
+
if (!p) return valor;
|
|
413
|
+
return `${p.signo}$${miles(p.entero)}${p.fraccion ? `.${p.fraccion}` : ""}`;
|
|
414
|
+
}
|
|
415
|
+
function formatoNumero(valor) {
|
|
416
|
+
if (valor == null) return NO_DISPONIBLE;
|
|
417
|
+
const p = partes(valor);
|
|
418
|
+
if (!p) return valor;
|
|
419
|
+
return `${p.signo}${miles(p.entero)}${p.fraccion ? `.${p.fraccion}` : ""}`;
|
|
420
|
+
}
|
|
421
|
+
function formatoEntero(valor) {
|
|
422
|
+
if (valor == null) return NO_DISPONIBLE;
|
|
423
|
+
return formatoNumero(String(Math.trunc(valor)));
|
|
424
|
+
}
|
|
425
|
+
function formatoPct(razon) {
|
|
426
|
+
if (razon == null) return NO_DISPONIBLE;
|
|
427
|
+
const p = partes(razon);
|
|
428
|
+
if (!p) return razon;
|
|
429
|
+
const fraccion = p.fraccion.padEnd(4, "0");
|
|
430
|
+
const entero = (p.entero + fraccion.slice(0, 2)).replace(/^0+(?=\d)/, "");
|
|
431
|
+
const resto = fraccion.slice(2);
|
|
432
|
+
const decimales = resto.length > 2 ? resto : resto.padEnd(2, "0");
|
|
433
|
+
return `${p.signo}${miles(entero)}.${decimales} %`;
|
|
434
|
+
}
|
|
435
|
+
function formatoDias(valor) {
|
|
436
|
+
return valor == null ? NO_DISPONIBLE : `${formatoNumero(valor)} d\xEDas`;
|
|
437
|
+
}
|
|
438
|
+
function formatoFecha(iso) {
|
|
439
|
+
if (!iso) return NO_DISPONIBLE;
|
|
440
|
+
return iso.slice(0, 10).replace(/-/g, "/");
|
|
441
|
+
}
|
|
442
|
+
function formatoMes(mes) {
|
|
443
|
+
return mes ? mes.slice(0, 7).replace(/-/g, "/") : NO_DISPONIBLE;
|
|
444
|
+
}
|
|
445
|
+
|
|
446
|
+
// src/kit/lib/fecha.ts
|
|
447
|
+
function formatearFechaHora(iso) {
|
|
448
|
+
if (!iso) return "\u2014";
|
|
449
|
+
const tieneZona = /(Z|[+-]\d{2}:?\d{2})$/.test(iso);
|
|
450
|
+
if (tieneZona && /T/.test(iso)) {
|
|
451
|
+
const d = new Date(iso);
|
|
452
|
+
if (!Number.isNaN(d.getTime())) {
|
|
453
|
+
const p = (n) => String(n).padStart(2, "0");
|
|
454
|
+
return `${d.getFullYear()}/${p(d.getMonth() + 1)}/${p(d.getDate())} ${p(d.getHours())}:${p(d.getMinutes())}:${p(d.getSeconds())}`;
|
|
455
|
+
}
|
|
456
|
+
}
|
|
457
|
+
const conHora = /T/.test(iso) ? iso : `${iso}T00:00:00`;
|
|
458
|
+
const m = conHora.match(/^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2})/);
|
|
459
|
+
if (!m) return iso;
|
|
460
|
+
const [, anio, mes, dia, hora, min, seg] = m;
|
|
461
|
+
return `${anio}/${mes}/${dia} ${hora}:${min}:${seg}`;
|
|
462
|
+
}
|
|
463
|
+
function formatearFechaHoraCDMX(iso) {
|
|
464
|
+
if (!iso) return "\u2014";
|
|
465
|
+
if (/(Z|[+-]\d{2}:?\d{2})$/.test(iso) && /T/.test(iso)) {
|
|
466
|
+
const d = new Date(iso);
|
|
467
|
+
if (!Number.isNaN(d.getTime())) {
|
|
468
|
+
const partes2 = Object.fromEntries(
|
|
469
|
+
new Intl.DateTimeFormat("en-CA", {
|
|
470
|
+
timeZone: "America/Mexico_City",
|
|
471
|
+
year: "numeric",
|
|
472
|
+
month: "2-digit",
|
|
473
|
+
day: "2-digit",
|
|
474
|
+
hour: "2-digit",
|
|
475
|
+
minute: "2-digit",
|
|
476
|
+
second: "2-digit",
|
|
477
|
+
hourCycle: "h23"
|
|
478
|
+
}).formatToParts(d).map((x) => [x.type, x.value])
|
|
479
|
+
);
|
|
480
|
+
return `${partes2.year}/${partes2.month}/${partes2.day} ${partes2.hour}:${partes2.minute}:${partes2.second}`;
|
|
481
|
+
}
|
|
482
|
+
}
|
|
483
|
+
return formatearFechaHora(iso);
|
|
484
|
+
}
|
|
485
|
+
function formatearRangoFechaHora(desde, hasta) {
|
|
486
|
+
return `${formatearFechaHora(desde)} \u2014 ${formatearFechaHora(hasta)}`;
|
|
487
|
+
}
|
|
488
|
+
|
|
489
|
+
// src/kit/lib/bytes.ts
|
|
490
|
+
function formatearBytes(n) {
|
|
491
|
+
if (n === null || n === void 0 || !Number.isFinite(n) || n < 0) return "\u2014";
|
|
492
|
+
if (n < 1024) return `${n} B`;
|
|
493
|
+
const unidades = ["KB", "MB", "GB", "TB"];
|
|
494
|
+
let valor = n / 1024;
|
|
495
|
+
let i = 0;
|
|
496
|
+
while (valor >= 1024 && i < unidades.length - 1) {
|
|
497
|
+
valor /= 1024;
|
|
498
|
+
i += 1;
|
|
499
|
+
}
|
|
500
|
+
return `${valor.toFixed(1)} ${unidades[i]}`;
|
|
501
|
+
}
|
|
502
|
+
function SpinnerMarca({
|
|
503
|
+
tamano = 120,
|
|
504
|
+
etiqueta = "Cargando..."
|
|
505
|
+
}) {
|
|
506
|
+
const alto = Math.round(tamano * 52 / 120);
|
|
507
|
+
return /* @__PURE__ */ jsxs(
|
|
508
|
+
"div",
|
|
509
|
+
{
|
|
510
|
+
className: "inline-flex flex-col items-center gap-2",
|
|
511
|
+
role: "status",
|
|
512
|
+
"aria-live": "polite",
|
|
513
|
+
"aria-label": etiqueta,
|
|
514
|
+
children: [
|
|
515
|
+
/* @__PURE__ */ jsxs("div", { className: "spinner-marca", style: { width: tamano, height: alto }, children: [
|
|
516
|
+
/* @__PURE__ */ jsx("span", { className: "spinner-marca__base", "aria-hidden": "true" }),
|
|
517
|
+
/* @__PURE__ */ jsx("span", { className: "spinner-marca__fill", "aria-hidden": "true" })
|
|
518
|
+
] }),
|
|
519
|
+
/* @__PURE__ */ jsx("span", { className: "text-xs text-[#807f7f]", children: etiqueta })
|
|
520
|
+
]
|
|
521
|
+
}
|
|
259
522
|
);
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
523
|
+
}
|
|
524
|
+
function OverlayCargando({
|
|
525
|
+
etiqueta = "Procesando...",
|
|
526
|
+
visible = true
|
|
527
|
+
}) {
|
|
528
|
+
if (!visible) return null;
|
|
529
|
+
return /* @__PURE__ */ jsx(
|
|
530
|
+
"div",
|
|
531
|
+
{
|
|
532
|
+
className: "fixed inset-0 z-[60] flex items-center justify-center bg-white/70 backdrop-blur-[1px]",
|
|
533
|
+
role: "alertdialog",
|
|
534
|
+
"aria-busy": "true",
|
|
535
|
+
"aria-label": etiqueta,
|
|
536
|
+
children: /* @__PURE__ */ jsx(SpinnerMarca, { tamano: 140, etiqueta })
|
|
537
|
+
}
|
|
538
|
+
);
|
|
539
|
+
}
|
|
540
|
+
function useAccionConSpinner() {
|
|
541
|
+
const [ejecutando, setEjecutando] = useState(false);
|
|
542
|
+
const [etiqueta, setEtiqueta] = useState("Procesando...");
|
|
543
|
+
const ejecutar = useCallback(
|
|
544
|
+
async (fn, etiquetaAccion = "Procesando...") => {
|
|
545
|
+
setEtiqueta(etiquetaAccion);
|
|
546
|
+
setEjecutando(true);
|
|
547
|
+
try {
|
|
548
|
+
return await fn();
|
|
549
|
+
} finally {
|
|
550
|
+
setEjecutando(false);
|
|
271
551
|
}
|
|
272
552
|
},
|
|
273
|
-
[
|
|
553
|
+
[]
|
|
274
554
|
);
|
|
275
|
-
const
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
return useMemo(
|
|
279
|
-
() => ({ mode, setMode, toggle, isDark: mode === "dark" }),
|
|
280
|
-
[mode, setMode, toggle]
|
|
555
|
+
const Overlay = useCallback(
|
|
556
|
+
() => /* @__PURE__ */ jsx(OverlayCargando, { visible: ejecutando, etiqueta }),
|
|
557
|
+
[ejecutando, etiqueta]
|
|
281
558
|
);
|
|
559
|
+
return { ejecutando, ejecutar, Overlay };
|
|
560
|
+
}
|
|
561
|
+
|
|
562
|
+
// src/kit/lib/preferenciasTabla.ts
|
|
563
|
+
var VACIAS = { orden: [], anchos: {}, ocultas: [] };
|
|
564
|
+
function esNavegador() {
|
|
565
|
+
return typeof window !== "undefined" && typeof window.localStorage !== "undefined";
|
|
566
|
+
}
|
|
567
|
+
function cargarPreferencias(clave) {
|
|
568
|
+
if (!esNavegador()) return { ...VACIAS };
|
|
569
|
+
const crudo = window.localStorage.getItem(clave);
|
|
570
|
+
if (!crudo) return { ...VACIAS };
|
|
571
|
+
try {
|
|
572
|
+
const p = JSON.parse(crudo);
|
|
573
|
+
return {
|
|
574
|
+
orden: Array.isArray(p.orden) ? p.orden : [],
|
|
575
|
+
anchos: p.anchos && typeof p.anchos === "object" ? p.anchos : {},
|
|
576
|
+
ocultas: Array.isArray(p.ocultas) ? p.ocultas : []
|
|
577
|
+
};
|
|
578
|
+
} catch {
|
|
579
|
+
return { ...VACIAS };
|
|
580
|
+
}
|
|
581
|
+
}
|
|
582
|
+
function guardarPreferencias(clave, prefs) {
|
|
583
|
+
if (!esNavegador()) return;
|
|
584
|
+
try {
|
|
585
|
+
window.localStorage.setItem(clave, JSON.stringify(prefs));
|
|
586
|
+
} catch {
|
|
587
|
+
}
|
|
282
588
|
}
|
|
283
|
-
function
|
|
284
|
-
if (!
|
|
589
|
+
function borrarPreferencias(clave) {
|
|
590
|
+
if (!esNavegador()) return;
|
|
591
|
+
window.localStorage.removeItem(clave);
|
|
592
|
+
}
|
|
593
|
+
function ordenarColumnas(idsDefault, ordenGuardado) {
|
|
594
|
+
if (ordenGuardado.length === 0) return [...idsDefault];
|
|
595
|
+
const disponibles = new Set(idsDefault);
|
|
596
|
+
const delGuardado = ordenGuardado.filter((id) => disponibles.has(id));
|
|
597
|
+
const yaColocadas = new Set(delGuardado);
|
|
598
|
+
const nuevas = idsDefault.filter((id) => !yaColocadas.has(id));
|
|
599
|
+
return [...delGuardado, ...nuevas];
|
|
600
|
+
}
|
|
601
|
+
function moverColumna(ids, desde, hasta) {
|
|
602
|
+
if (desde < 0 || desde >= ids.length || hasta < 0 || hasta >= ids.length || desde === hasta) {
|
|
603
|
+
return [...ids];
|
|
604
|
+
}
|
|
605
|
+
const copia = [...ids];
|
|
606
|
+
const [movido] = copia.splice(desde, 1);
|
|
607
|
+
copia.splice(hasta, 0, movido);
|
|
608
|
+
return copia;
|
|
609
|
+
}
|
|
610
|
+
|
|
611
|
+
// src/kit/lib/useTablaPreferencias.ts
|
|
612
|
+
function useTablaPreferencias(clave, idsDefault) {
|
|
613
|
+
const [prefs, setPrefs] = useState({ orden: [], anchos: {}, ocultas: [] });
|
|
614
|
+
useEffect(() => {
|
|
615
|
+
setPrefs(cargarPreferencias(clave));
|
|
616
|
+
}, [clave]);
|
|
617
|
+
const persistir = useCallback(
|
|
618
|
+
(nuevas) => {
|
|
619
|
+
setPrefs(nuevas);
|
|
620
|
+
guardarPreferencias(clave, nuevas);
|
|
621
|
+
},
|
|
622
|
+
[clave]
|
|
623
|
+
);
|
|
624
|
+
const idsOrdenados = ordenarColumnas(idsDefault, prefs.orden);
|
|
625
|
+
const ocultas = new Set(prefs.ocultas);
|
|
626
|
+
const idsVisibles = idsOrdenados.filter((id) => !ocultas.has(id));
|
|
627
|
+
const mover = useCallback(
|
|
628
|
+
(desde, hasta) => {
|
|
629
|
+
const base = ordenarColumnas(idsDefault, prefs.orden);
|
|
630
|
+
const nuevoOrden = moverColumna(base, desde, hasta);
|
|
631
|
+
persistir({ ...prefs, orden: nuevoOrden });
|
|
632
|
+
},
|
|
633
|
+
[idsDefault, prefs, persistir]
|
|
634
|
+
);
|
|
635
|
+
const redimensionar = useCallback(
|
|
636
|
+
(id, ancho) => {
|
|
637
|
+
const w = Math.max(60, Math.round(ancho));
|
|
638
|
+
persistir({ ...prefs, anchos: { ...prefs.anchos, [id]: w } });
|
|
639
|
+
},
|
|
640
|
+
[prefs, persistir]
|
|
641
|
+
);
|
|
642
|
+
const alternarVisible = useCallback(
|
|
643
|
+
(id) => {
|
|
644
|
+
const set = new Set(prefs.ocultas);
|
|
645
|
+
if (set.has(id)) set.delete(id);
|
|
646
|
+
else set.add(id);
|
|
647
|
+
persistir({ ...prefs, ocultas: [...set] });
|
|
648
|
+
},
|
|
649
|
+
[prefs, persistir]
|
|
650
|
+
);
|
|
651
|
+
const restablecer = useCallback(() => {
|
|
652
|
+
borrarPreferencias(clave);
|
|
653
|
+
setPrefs({ orden: [], anchos: {}, ocultas: [] });
|
|
654
|
+
}, [clave]);
|
|
285
655
|
return {
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
656
|
+
/** Ids en el orden efectivo, SIN las ocultas — para pintar la tabla. */
|
|
657
|
+
idsVisibles,
|
|
658
|
+
/** Ids en el orden efectivo, incluyendo ocultas — para el menu de mostrar/ocultar. */
|
|
659
|
+
idsOrdenados,
|
|
660
|
+
/** Set de ids ocultos. */
|
|
661
|
+
ocultas,
|
|
662
|
+
/** Ancho persistido de una columna, o undefined si no se ha redimensionado. */
|
|
663
|
+
anchoDe: (id) => prefs.anchos[id],
|
|
664
|
+
mover,
|
|
665
|
+
redimensionar,
|
|
666
|
+
alternarVisible,
|
|
667
|
+
restablecer
|
|
292
668
|
};
|
|
293
669
|
}
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
670
|
+
|
|
671
|
+
// src/kit/lib/posicionPopover.ts
|
|
672
|
+
function calcularPosicionPopover({
|
|
673
|
+
trigger,
|
|
674
|
+
contenido,
|
|
675
|
+
viewport,
|
|
676
|
+
margen = 8,
|
|
677
|
+
separacion = 4,
|
|
678
|
+
anchoPreferido = 360
|
|
679
|
+
}) {
|
|
680
|
+
const anchoMax = Math.min(anchoPreferido, viewport.ancho - 2 * margen);
|
|
681
|
+
const ancho = Math.min(contenido.ancho, anchoMax);
|
|
682
|
+
const left = Math.max(margen, Math.min(trigger.left, viewport.ancho - ancho - margen));
|
|
683
|
+
const espacioAbajo = viewport.alto - trigger.bottom - separacion - margen;
|
|
684
|
+
const espacioArriba = trigger.top - separacion - margen;
|
|
685
|
+
const abajo = contenido.alto <= espacioAbajo || espacioAbajo >= espacioArriba;
|
|
686
|
+
const disponible = Math.max(0, abajo ? espacioAbajo : espacioArriba);
|
|
687
|
+
const alto = Math.min(contenido.alto, disponible);
|
|
688
|
+
const top = abajo ? trigger.bottom + separacion : trigger.top - separacion - alto;
|
|
689
|
+
return { top, left, maxHeight: disponible, anchoMax };
|
|
690
|
+
}
|
|
691
|
+
|
|
692
|
+
// src/kit/ui/clases.ts
|
|
693
|
+
var CLASE_BOTON_PRIMARIO = "inline-flex items-center gap-1.5 rounded-md bg-[var(--tema-texto)] px-4 py-2 text-sm font-medium text-white transition hover:brightness-125 disabled:opacity-50";
|
|
694
|
+
var CLASE_BOTON_PRIMARIO_COMPACTO = "inline-flex items-center gap-1.5 rounded-md bg-[var(--tema-texto)] px-3 py-1.5 text-sm font-medium text-white transition hover:brightness-125 disabled:opacity-50";
|
|
695
|
+
var CLASE_BOTON_SECUNDARIO = "inline-flex items-center gap-1.5 rounded-md border border-[var(--tema-borde)] px-3 py-1.5 text-sm font-medium text-[#3c3c3b] transition hover:bg-[var(--tema-badge-neutro)] disabled:opacity-50";
|
|
696
|
+
var CLASE_BOTON_PEQUENO = "inline-flex items-center gap-1.5 rounded-md border border-[var(--tema-borde)] px-2.5 py-1.5 text-xs font-medium text-[#3c3c3b] transition hover:bg-[var(--tema-badge-neutro)] disabled:opacity-50";
|
|
697
|
+
var CLASE_BOTON_CONTORNO = "rounded-md border border-[var(--tema-primario)] px-3 py-1 text-xs font-medium text-[var(--tema-primario)] transition hover:bg-[#eaf2fb]";
|
|
698
|
+
var CLASE_BOTON_ICONO = "rounded-md p-1 text-[#807f7f] transition hover:bg-[var(--tema-badge-neutro)]";
|
|
699
|
+
var CLASE_BOTON_PELIGRO = "inline-flex items-center gap-1.5 rounded-md border border-[var(--tema-peligro)] px-3 py-1.5 text-sm font-medium text-[var(--tema-peligro)] transition hover:bg-[var(--tema-badge-error)] disabled:opacity-50";
|
|
700
|
+
var CLASE_CAMPO = "rounded-md border border-[var(--tema-borde)] bg-[var(--tema-fondo)] px-3 py-2 text-sm text-[#3c3c3b] focus:border-[var(--tema-primario)] focus:outline-none disabled:bg-[#f4f8fc] disabled:text-[#807f7f]";
|
|
701
|
+
var CLASE_CAMPO_COMPACTO = "rounded-md border border-[var(--tema-borde)] bg-[var(--tema-fondo)] px-2 py-1.5 text-sm text-[#3c3c3b] focus:border-[var(--tema-primario)] focus:outline-none";
|
|
702
|
+
var CLASE_ETIQUETA_CAMPO = "text-sm font-medium text-[#3c3c3b]";
|
|
703
|
+
var CLASE_AYUDA_CAMPO = "text-xs text-[#807f7f]";
|
|
704
|
+
var CLASE_ERROR_CAMPO = "text-sm text-[var(--tema-peligro)]";
|
|
705
|
+
var CLASE_EXITO_CAMPO = "text-sm text-[#1e7a34]";
|
|
706
|
+
var CLASE_TARJETA = "rounded-lg border border-[var(--tema-borde)] p-4";
|
|
707
|
+
var CLASE_TITULO_PAGINA = "flex items-center gap-2 text-xl font-semibold text-[var(--tema-primario-oscuro)]";
|
|
708
|
+
var CLASE_TITULO_SECCION = "text-sm font-semibold text-[var(--tema-primario-oscuro)]";
|
|
709
|
+
var CLASE_TEXTO_ATENUADO = "text-sm text-[#807f7f]";
|
|
710
|
+
function PopoverHover({
|
|
711
|
+
etiqueta,
|
|
712
|
+
disparador,
|
|
300
713
|
children
|
|
301
714
|
}) {
|
|
302
|
-
const
|
|
303
|
-
const
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
);
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
715
|
+
const [abierto, setAbierto] = useState(false);
|
|
716
|
+
const [pos, setPos] = useState(null);
|
|
717
|
+
const botonRef = useRef(null);
|
|
718
|
+
const contenidoRef = useRef(null);
|
|
719
|
+
const idContenido = useId();
|
|
720
|
+
const reposicionar = useCallback(() => {
|
|
721
|
+
const trigger = botonRef.current?.getBoundingClientRect();
|
|
722
|
+
if (!trigger) return;
|
|
723
|
+
const medida = contenidoRef.current?.getBoundingClientRect();
|
|
724
|
+
setPos(
|
|
725
|
+
calcularPosicionPopover({
|
|
726
|
+
trigger,
|
|
727
|
+
contenido: { ancho: medida?.width ?? 0, alto: medida?.height ?? 0 },
|
|
728
|
+
viewport: { ancho: window.innerWidth, alto: window.innerHeight }
|
|
729
|
+
})
|
|
730
|
+
);
|
|
731
|
+
}, []);
|
|
732
|
+
function abrir() {
|
|
733
|
+
setAbierto(true);
|
|
734
|
+
}
|
|
735
|
+
useLayoutEffect(() => {
|
|
736
|
+
if (!abierto) {
|
|
737
|
+
setPos(null);
|
|
738
|
+
return;
|
|
739
|
+
}
|
|
740
|
+
reposicionar();
|
|
741
|
+
window.addEventListener("scroll", reposicionar, true);
|
|
742
|
+
window.addEventListener("resize", reposicionar);
|
|
743
|
+
return () => {
|
|
744
|
+
window.removeEventListener("scroll", reposicionar, true);
|
|
745
|
+
window.removeEventListener("resize", reposicionar);
|
|
746
|
+
};
|
|
747
|
+
}, [abierto, reposicionar]);
|
|
748
|
+
useEffect(() => {
|
|
749
|
+
if (!abierto) return;
|
|
750
|
+
function alTeclear(e) {
|
|
751
|
+
if (e.key === "Escape") setAbierto(false);
|
|
752
|
+
}
|
|
753
|
+
document.addEventListener("keydown", alTeclear);
|
|
754
|
+
return () => document.removeEventListener("keydown", alTeclear);
|
|
755
|
+
}, [abierto]);
|
|
756
|
+
return /* @__PURE__ */ jsxs(
|
|
757
|
+
"span",
|
|
758
|
+
{
|
|
759
|
+
className: "inline-flex",
|
|
760
|
+
onMouseEnter: abrir,
|
|
761
|
+
onMouseLeave: () => setAbierto(false),
|
|
762
|
+
children: [
|
|
763
|
+
/* @__PURE__ */ jsx(
|
|
764
|
+
"button",
|
|
765
|
+
{
|
|
766
|
+
ref: botonRef,
|
|
767
|
+
type: "button",
|
|
768
|
+
"aria-label": etiqueta,
|
|
769
|
+
title: etiqueta,
|
|
770
|
+
"aria-expanded": abierto,
|
|
771
|
+
"aria-describedby": abierto ? idContenido : void 0,
|
|
772
|
+
onFocus: abrir,
|
|
773
|
+
onBlur: () => setAbierto(false),
|
|
774
|
+
className: "inline-flex items-center justify-center text-[#807f7f] transition hover:text-[var(--tema-primario)]",
|
|
775
|
+
children: disparador
|
|
776
|
+
}
|
|
777
|
+
),
|
|
778
|
+
abierto && /* @__PURE__ */ jsx(
|
|
779
|
+
"span",
|
|
780
|
+
{
|
|
781
|
+
ref: contenidoRef,
|
|
782
|
+
id: idContenido,
|
|
783
|
+
role: "tooltip",
|
|
784
|
+
style: {
|
|
785
|
+
position: "fixed",
|
|
786
|
+
top: pos?.top ?? 0,
|
|
787
|
+
left: pos?.left ?? 0,
|
|
788
|
+
// Antes de medir (pos null) se oculta para no parpadear en (0,0).
|
|
789
|
+
visibility: pos ? "visible" : "hidden",
|
|
790
|
+
maxWidth: pos?.anchoMax ?? "min(360px, calc(100vw - 16px))",
|
|
791
|
+
maxHeight: pos?.maxHeight,
|
|
792
|
+
overflowY: "auto"
|
|
793
|
+
},
|
|
794
|
+
className: "z-50 w-max rounded-md border border-[var(--tema-borde)] bg-white p-3 text-left shadow-lg",
|
|
795
|
+
children
|
|
796
|
+
}
|
|
797
|
+
)
|
|
798
|
+
]
|
|
799
|
+
}
|
|
800
|
+
);
|
|
801
|
+
}
|
|
802
|
+
var PREGUNTAS = [
|
|
803
|
+
["Qu\xE9 es", "que_es"],
|
|
804
|
+
["C\xF3mo se calcula", "como_se_calcula"],
|
|
805
|
+
["De d\xF3nde sale", "de_donde_sale"],
|
|
806
|
+
["C\xF3mo leerlo", "como_leerlo"]
|
|
807
|
+
];
|
|
808
|
+
function InfoExplicacion({ id }) {
|
|
809
|
+
const e = explicacionDe(id);
|
|
810
|
+
return /* @__PURE__ */ jsx("span", { "data-explicacion-id": id, className: "inline-flex shrink-0 align-middle", children: /* @__PURE__ */ jsx(
|
|
811
|
+
PopoverHover,
|
|
812
|
+
{
|
|
813
|
+
etiqueta: `Explicaci\xF3n: ${e.titulo}`,
|
|
814
|
+
disparador: /* @__PURE__ */ jsx(ICONO_INFO_EXPLICACION, { size: 14, "aria-hidden": "true", className: "text-[#9a9999]" }),
|
|
815
|
+
children: /* @__PURE__ */ jsxs("span", { className: "block max-w-[18rem] text-xs font-normal normal-case tracking-normal text-[#3c3c3b]", children: [
|
|
816
|
+
/* @__PURE__ */ jsx("span", { className: "block font-semibold text-[var(--tema-primario-oscuro)]", children: e.titulo }),
|
|
817
|
+
PREGUNTAS.map(([pregunta, campo]) => /* @__PURE__ */ jsxs("span", { className: "mt-1.5 block", children: [
|
|
818
|
+
/* @__PURE__ */ jsx("span", { className: "block font-medium text-[#565656]", children: pregunta }),
|
|
819
|
+
/* @__PURE__ */ jsx("span", { className: "block leading-snug", children: e[campo] })
|
|
820
|
+
] }, campo))
|
|
821
|
+
] })
|
|
822
|
+
}
|
|
823
|
+
) });
|
|
824
|
+
}
|
|
825
|
+
var CLASES = {
|
|
826
|
+
exito: "bg-[var(--tema-badge-exito)] text-[#1e6b34]",
|
|
827
|
+
error: "bg-[var(--tema-badge-error)] text-[var(--tema-peligro)]",
|
|
828
|
+
aviso: "bg-[var(--tema-badge-advertencia)] text-[#8a5a00]",
|
|
829
|
+
neutro: "bg-[var(--tema-badge-neutro)] text-[#565656]"
|
|
317
830
|
};
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
})
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
831
|
+
function Insignia({
|
|
832
|
+
tono,
|
|
833
|
+
children,
|
|
834
|
+
info,
|
|
835
|
+
icono: Icono
|
|
836
|
+
}) {
|
|
837
|
+
return /* @__PURE__ */ jsxs("span", { className: "inline-flex items-center gap-1 align-middle", children: [
|
|
838
|
+
/* @__PURE__ */ jsxs(
|
|
839
|
+
"span",
|
|
840
|
+
{
|
|
841
|
+
className: `${Icono ? "inline-flex items-center gap-1" : "inline-block"} rounded-full px-2 py-0.5 text-xs font-medium ${CLASES[tono]}`,
|
|
842
|
+
children: [
|
|
843
|
+
Icono && /* @__PURE__ */ jsx(Icono, { size: 12, "aria-hidden": "true" }),
|
|
844
|
+
children
|
|
845
|
+
]
|
|
846
|
+
}
|
|
847
|
+
),
|
|
848
|
+
info && /* @__PURE__ */ jsx(InfoExplicacion, { id: info })
|
|
849
|
+
] });
|
|
850
|
+
}
|
|
851
|
+
function Tarjeta({
|
|
852
|
+
titulo,
|
|
853
|
+
children,
|
|
854
|
+
nota,
|
|
855
|
+
info
|
|
856
|
+
}) {
|
|
857
|
+
return /* @__PURE__ */ jsxs("section", { className: "rounded-lg border border-[var(--tema-borde)] p-5", children: [
|
|
858
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1.5", children: [
|
|
859
|
+
/* @__PURE__ */ jsx("h2", { className: "text-sm font-semibold text-[var(--tema-primario-oscuro)]", children: titulo }),
|
|
860
|
+
info && /* @__PURE__ */ jsx(InfoExplicacion, { id: info })
|
|
861
|
+
] }),
|
|
862
|
+
nota && /* @__PURE__ */ jsx("p", { className: "mt-1 text-xs text-[#807f7f]", children: nota }),
|
|
863
|
+
/* @__PURE__ */ jsx("div", { className: "mt-3", children })
|
|
864
|
+
] });
|
|
865
|
+
}
|
|
866
|
+
function Metrica({
|
|
867
|
+
etiqueta,
|
|
868
|
+
valor,
|
|
869
|
+
info
|
|
870
|
+
}) {
|
|
871
|
+
return /* @__PURE__ */ jsxs("div", { className: "rounded-lg border border-[var(--tema-borde)] px-4 py-3", children: [
|
|
872
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1", children: [
|
|
873
|
+
/* @__PURE__ */ jsx("p", { className: "text-xs text-[#807f7f]", children: etiqueta }),
|
|
874
|
+
info && /* @__PURE__ */ jsx(InfoExplicacion, { id: info })
|
|
875
|
+
] }),
|
|
876
|
+
/* @__PURE__ */ jsx("p", { className: "mt-1 text-lg font-semibold text-[var(--tema-primario-oscuro)]", children: valor })
|
|
877
|
+
] });
|
|
878
|
+
}
|
|
879
|
+
function ThInfo({
|
|
880
|
+
info,
|
|
881
|
+
children,
|
|
882
|
+
className,
|
|
883
|
+
derecha,
|
|
884
|
+
scope,
|
|
885
|
+
atributos
|
|
886
|
+
}) {
|
|
887
|
+
return /* @__PURE__ */ jsx("th", { scope, ...atributos, className, children: /* @__PURE__ */ jsxs("span", { className: `inline-flex items-center gap-1 ${derecha ? "justify-end" : ""}`, children: [
|
|
888
|
+
children,
|
|
889
|
+
/* @__PURE__ */ jsx(InfoExplicacion, { id: info })
|
|
890
|
+
] }) });
|
|
891
|
+
}
|
|
892
|
+
var TIPOS = {
|
|
893
|
+
error: "rounded-md bg-[var(--tema-badge-error)] px-3 py-2 text-sm text-[var(--tema-peligro)]",
|
|
894
|
+
advertencia: "rounded-md bg-[var(--tema-badge-advertencia)] px-3 py-2 text-xs text-[#8a5a00]",
|
|
895
|
+
neutro: "rounded-lg bg-[var(--tema-badge-neutro)] px-3 py-2 text-sm text-[#565656]",
|
|
896
|
+
exito: "rounded-md bg-[var(--tema-badge-exito)] px-3 py-2 text-sm text-[#1e7a34]"
|
|
897
|
+
};
|
|
898
|
+
function Aviso({
|
|
899
|
+
tipo,
|
|
900
|
+
titulo,
|
|
901
|
+
children,
|
|
902
|
+
info
|
|
903
|
+
}) {
|
|
904
|
+
return /* @__PURE__ */ jsxs("div", { role: tipo === "error" ? "alert" : "status", className: TIPOS[tipo], children: [
|
|
905
|
+
titulo && /* @__PURE__ */ jsxs("strong", { className: "font-semibold", children: [
|
|
906
|
+
titulo,
|
|
907
|
+
" "
|
|
908
|
+
] }),
|
|
909
|
+
children,
|
|
910
|
+
info && /* @__PURE__ */ jsx("span", { className: "ml-1 align-middle", children: /* @__PURE__ */ jsx(InfoExplicacion, { id: info }) })
|
|
911
|
+
] });
|
|
912
|
+
}
|
|
913
|
+
function EstadoVacio({ children }) {
|
|
914
|
+
return /* @__PURE__ */ jsx("p", { className: "rounded-lg border border-dashed border-[var(--tema-borde)] px-4 py-6 text-sm text-[#807f7f]", children });
|
|
915
|
+
}
|
|
916
|
+
function EstadoVacioFila({ columnas, children = "Sin resultados" }) {
|
|
917
|
+
return /* @__PURE__ */ jsx("tr", { children: /* @__PURE__ */ jsx("td", { colSpan: columnas, className: "px-3 py-6 text-center text-sm text-[#807f7f]", children }) });
|
|
918
|
+
}
|
|
919
|
+
function NoDisponible({ motivo, info }) {
|
|
920
|
+
return /* @__PURE__ */ jsxs("div", { className: "rounded-lg border border-dashed border-[var(--tema-borde)] px-4 py-3 text-sm text-[#565656]", children: [
|
|
921
|
+
/* @__PURE__ */ jsxs("p", { className: "flex items-center gap-1 font-medium", children: [
|
|
922
|
+
"No disponible",
|
|
923
|
+
/* @__PURE__ */ jsx(InfoExplicacion, { id: info })
|
|
924
|
+
] }),
|
|
925
|
+
/* @__PURE__ */ jsx("p", { className: "mt-1 text-xs text-[#807f7f]", children: motivo })
|
|
926
|
+
] });
|
|
927
|
+
}
|
|
928
|
+
function BarraProgreso({ porcentaje, etiqueta }) {
|
|
358
929
|
return /* @__PURE__ */ jsx(
|
|
359
|
-
|
|
930
|
+
"div",
|
|
360
931
|
{
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
932
|
+
role: "progressbar",
|
|
933
|
+
"aria-label": etiqueta,
|
|
934
|
+
"aria-valuemin": 0,
|
|
935
|
+
"aria-valuemax": 100,
|
|
936
|
+
"aria-valuenow": porcentaje,
|
|
937
|
+
className: "h-1.5 w-full overflow-hidden rounded-full bg-[var(--tema-borde)]",
|
|
938
|
+
children: /* @__PURE__ */ jsx("div", { className: "h-full rounded-full bg-[var(--tema-primario)] transition-all", style: { width: `${porcentaje}%` } })
|
|
365
939
|
}
|
|
366
940
|
);
|
|
367
941
|
}
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
942
|
+
function useAccionAviso({
|
|
943
|
+
ejecutar,
|
|
944
|
+
errorGenerico,
|
|
945
|
+
onHecho
|
|
946
|
+
}) {
|
|
947
|
+
const [ejecutando, setEjecutando] = useState(false);
|
|
948
|
+
const [aviso, setAviso] = useState(null);
|
|
949
|
+
async function correr() {
|
|
950
|
+
setEjecutando(true);
|
|
951
|
+
setAviso(null);
|
|
952
|
+
let resultado;
|
|
953
|
+
try {
|
|
954
|
+
resultado = await ejecutar();
|
|
955
|
+
} catch {
|
|
956
|
+
resultado = { tipo: "error", texto: errorGenerico };
|
|
957
|
+
}
|
|
958
|
+
setAviso(resultado);
|
|
959
|
+
setEjecutando(false);
|
|
960
|
+
if (resultado.tipo === "ok") onHecho?.();
|
|
961
|
+
}
|
|
962
|
+
return { ejecutando, aviso, correr };
|
|
963
|
+
}
|
|
964
|
+
function AvisoAccionEstado({
|
|
965
|
+
ejecutando,
|
|
966
|
+
aviso,
|
|
967
|
+
etiquetaSpinner
|
|
968
|
+
}) {
|
|
969
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
970
|
+
ejecutando && /* @__PURE__ */ jsx(SpinnerMarca, { tamano: 32, etiqueta: etiquetaSpinner }),
|
|
971
|
+
aviso && /* @__PURE__ */ jsx(
|
|
972
|
+
"span",
|
|
973
|
+
{
|
|
974
|
+
role: aviso.tipo === "ok" ? "status" : "alert",
|
|
975
|
+
className: aviso.tipo === "ok" ? "text-xs text-[var(--tema-primario-oscuro)]" : "text-xs text-[var(--tema-peligro)]",
|
|
976
|
+
children: aviso.texto
|
|
977
|
+
}
|
|
978
|
+
)
|
|
979
|
+
] });
|
|
980
|
+
}
|
|
981
|
+
function BotonAccionAviso({
|
|
982
|
+
etiqueta,
|
|
983
|
+
etiquetaEjecutando,
|
|
984
|
+
etiquetaSpinner,
|
|
985
|
+
ariaLabel,
|
|
986
|
+
info,
|
|
987
|
+
errorGenerico,
|
|
988
|
+
ejecutar,
|
|
989
|
+
onHecho
|
|
990
|
+
}) {
|
|
991
|
+
const { ejecutando, aviso, correr } = useAccionAviso({ ejecutar, errorGenerico, onHecho });
|
|
992
|
+
return /* @__PURE__ */ jsxs("span", { className: "inline-flex flex-wrap items-center gap-1.5", children: [
|
|
993
|
+
/* @__PURE__ */ jsx(
|
|
994
|
+
"button",
|
|
995
|
+
{
|
|
996
|
+
type: "button",
|
|
997
|
+
onClick: correr,
|
|
998
|
+
disabled: ejecutando,
|
|
999
|
+
"aria-label": ariaLabel,
|
|
1000
|
+
className: "rounded-md border border-[var(--tema-borde)] px-2 py-0.5 text-xs font-medium text-[var(--tema-primario-oscuro)] transition hover:bg-[var(--tema-badge-neutro)] disabled:opacity-50",
|
|
1001
|
+
children: ejecutando ? etiquetaEjecutando : etiqueta
|
|
1002
|
+
}
|
|
1003
|
+
),
|
|
1004
|
+
/* @__PURE__ */ jsx(InfoExplicacion, { id: info }),
|
|
1005
|
+
/* @__PURE__ */ jsx(AvisoAccionEstado, { ejecutando, aviso, etiquetaSpinner })
|
|
1006
|
+
] });
|
|
1007
|
+
}
|
|
1008
|
+
function EnlaceNav({
|
|
1009
|
+
href,
|
|
1010
|
+
icono,
|
|
1011
|
+
etiqueta
|
|
1012
|
+
}) {
|
|
1013
|
+
return /* @__PURE__ */ jsxs(
|
|
1014
|
+
LinkBase,
|
|
373
1015
|
{
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
1016
|
+
href,
|
|
1017
|
+
"aria-label": etiqueta,
|
|
1018
|
+
title: etiqueta,
|
|
1019
|
+
className: "pulsable flex items-center gap-2.5 rounded-md px-2 py-2 transition hover:bg-[var(--tema-badge-neutro)] hover:text-[var(--tema-primario)] md:group-data-[colapsado=true]/side:justify-center",
|
|
1020
|
+
children: [
|
|
1021
|
+
icono,
|
|
1022
|
+
/* @__PURE__ */ jsx("span", { className: "md:group-data-[colapsado=true]/side:hidden", children: etiqueta })
|
|
1023
|
+
]
|
|
379
1024
|
}
|
|
380
1025
|
);
|
|
381
1026
|
}
|
|
382
|
-
function
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
function
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
1027
|
+
function SeccionNav({ titulo, children }) {
|
|
1028
|
+
return /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-1", children: [
|
|
1029
|
+
titulo && /* @__PURE__ */ jsx("span", { className: "px-2 pb-1 text-[10px] font-semibold uppercase tracking-wider text-[#9a9a9a] md:group-data-[colapsado=true]/side:hidden", children: titulo }),
|
|
1030
|
+
children
|
|
1031
|
+
] });
|
|
1032
|
+
}
|
|
1033
|
+
|
|
1034
|
+
// src/kit/lib/panelPrefs.ts
|
|
1035
|
+
function leerPref(clave, porDefecto) {
|
|
1036
|
+
try {
|
|
1037
|
+
const crudo = window.localStorage.getItem(clave);
|
|
1038
|
+
return crudo === null ? porDefecto : JSON.parse(crudo);
|
|
1039
|
+
} catch {
|
|
1040
|
+
return porDefecto;
|
|
1041
|
+
}
|
|
1042
|
+
}
|
|
1043
|
+
function guardarPref(clave, valor) {
|
|
1044
|
+
try {
|
|
1045
|
+
window.localStorage.setItem(clave, JSON.stringify(valor));
|
|
1046
|
+
} catch {
|
|
1047
|
+
}
|
|
1048
|
+
}
|
|
1049
|
+
var CLAVE = "sidebar:colapsado";
|
|
1050
|
+
function SidebarColapsable({
|
|
1051
|
+
cabecera,
|
|
1052
|
+
pie,
|
|
1053
|
+
children
|
|
1054
|
+
}) {
|
|
1055
|
+
const [colapsado, setColapsado] = useState(false);
|
|
1056
|
+
const [abiertoMovil, setAbiertoMovil] = useState(false);
|
|
1057
|
+
useEffect(() => {
|
|
1058
|
+
setColapsado(leerPref(CLAVE, false) === true);
|
|
1059
|
+
}, []);
|
|
1060
|
+
useEffect(() => {
|
|
1061
|
+
if (!abiertoMovil) return;
|
|
1062
|
+
const alTeclear = (e) => {
|
|
1063
|
+
if (e.key === "Escape") setAbiertoMovil(false);
|
|
413
1064
|
};
|
|
1065
|
+
document.addEventListener("keydown", alTeclear);
|
|
1066
|
+
return () => document.removeEventListener("keydown", alTeclear);
|
|
1067
|
+
}, [abiertoMovil]);
|
|
1068
|
+
function alternar() {
|
|
1069
|
+
const nuevo = !colapsado;
|
|
1070
|
+
setColapsado(nuevo);
|
|
1071
|
+
guardarPref(CLAVE, nuevo);
|
|
414
1072
|
}
|
|
415
|
-
return
|
|
1073
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
1074
|
+
/* @__PURE__ */ jsx(
|
|
1075
|
+
"button",
|
|
1076
|
+
{
|
|
1077
|
+
type: "button",
|
|
1078
|
+
onClick: () => setAbiertoMovil(true),
|
|
1079
|
+
"aria-label": "Abrir men\xFA",
|
|
1080
|
+
title: "Abrir men\xFA",
|
|
1081
|
+
className: "fixed left-3 top-3 z-30 flex h-9 w-9 items-center justify-center rounded-md border border-[var(--tema-borde)] bg-[var(--tema-fondo)] text-[#565656] shadow-sm md:hidden",
|
|
1082
|
+
children: /* @__PURE__ */ jsx(ICONO_NAV_MENU_MOVIL, { size: TAMANO_BOTON, "aria-hidden": "true" })
|
|
1083
|
+
}
|
|
1084
|
+
),
|
|
1085
|
+
abiertoMovil && /* @__PURE__ */ jsx(
|
|
1086
|
+
"button",
|
|
1087
|
+
{
|
|
1088
|
+
type: "button",
|
|
1089
|
+
"aria-label": "Cerrar men\xFA",
|
|
1090
|
+
onClick: () => setAbiertoMovil(false),
|
|
1091
|
+
className: "fixed inset-0 z-30 bg-black/40 md:hidden"
|
|
1092
|
+
}
|
|
1093
|
+
),
|
|
1094
|
+
/* @__PURE__ */ jsxs(
|
|
1095
|
+
"aside",
|
|
1096
|
+
{
|
|
1097
|
+
"data-colapsado": colapsado ? "true" : "false",
|
|
1098
|
+
"data-abierto-movil": abiertoMovil ? "true" : "false",
|
|
1099
|
+
onClick: (e) => {
|
|
1100
|
+
if (e.target.closest("a")) setAbiertoMovil(false);
|
|
1101
|
+
},
|
|
1102
|
+
className: `group/side fixed inset-y-0 left-0 z-40 flex w-60 shrink-0 flex-col border-r border-[var(--tema-borde)] bg-[var(--tema-fondo)] transition-transform md:sticky md:top-0 md:h-screen md:translate-x-0 md:transition-[width] md:data-[colapsado=true]:w-14 ${abiertoMovil ? "translate-x-0" : "-translate-x-full"}`,
|
|
1103
|
+
children: [
|
|
1104
|
+
/* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-2 border-b border-[var(--tema-borde)] px-4 py-4 md:group-data-[colapsado=true]/side:items-center md:group-data-[colapsado=true]/side:px-1", children: [
|
|
1105
|
+
/* @__PURE__ */ jsx("div", { className: "md:group-data-[colapsado=true]/side:hidden", children: cabecera }),
|
|
1106
|
+
/* @__PURE__ */ jsx(
|
|
1107
|
+
"button",
|
|
1108
|
+
{
|
|
1109
|
+
type: "button",
|
|
1110
|
+
onClick: alternar,
|
|
1111
|
+
"aria-label": colapsado ? "Expandir men\xFA" : "Contraer men\xFA",
|
|
1112
|
+
title: colapsado ? "Expandir men\xFA" : "Contraer men\xFA",
|
|
1113
|
+
"aria-expanded": !colapsado,
|
|
1114
|
+
className: "hidden w-fit items-center rounded-md p-1 text-[#807f7f] transition hover:bg-[var(--tema-badge-neutro)] hover:text-[var(--tema-primario)] md:flex",
|
|
1115
|
+
children: colapsado ? /* @__PURE__ */ jsx(ICONO_NAV_EXPANDIR, { size: TAMANO_BOTON, "aria-hidden": "true" }) : /* @__PURE__ */ jsx(ICONO_NAV_COLAPSAR, { size: TAMANO_BOTON, "aria-hidden": "true" })
|
|
1116
|
+
}
|
|
1117
|
+
),
|
|
1118
|
+
/* @__PURE__ */ jsx(
|
|
1119
|
+
"button",
|
|
1120
|
+
{
|
|
1121
|
+
type: "button",
|
|
1122
|
+
onClick: () => setAbiertoMovil(false),
|
|
1123
|
+
"aria-label": "Cerrar men\xFA lateral",
|
|
1124
|
+
className: "absolute right-2 top-2 rounded-md p-1 text-[#807f7f] md:hidden",
|
|
1125
|
+
children: /* @__PURE__ */ jsx(ICONO_CERRAR, { size: TAMANO_BOTON, "aria-hidden": "true" })
|
|
1126
|
+
}
|
|
1127
|
+
)
|
|
1128
|
+
] }),
|
|
1129
|
+
/* @__PURE__ */ jsx("nav", { className: "flex flex-1 flex-col gap-6 overflow-y-auto px-3 py-4 text-sm font-medium text-[#565656] md:group-data-[colapsado=true]/side:px-1.5", children }),
|
|
1130
|
+
/* @__PURE__ */ jsx("div", { className: "border-t border-[var(--tema-borde)] px-4 py-3 md:group-data-[colapsado=true]/side:px-1", children: pie })
|
|
1131
|
+
]
|
|
1132
|
+
}
|
|
1133
|
+
)
|
|
1134
|
+
] });
|
|
416
1135
|
}
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
1136
|
+
|
|
1137
|
+
// src/kit/lib/tablaMarco.ts
|
|
1138
|
+
var PREFS_MARCO_DEFAULT = { ocultas: [], densidad: "comoda" };
|
|
1139
|
+
var ID_SEGURO = /^[A-Za-z0-9_-]+$/;
|
|
1140
|
+
function hashCorto(texto) {
|
|
1141
|
+
let h = 2166136261;
|
|
1142
|
+
for (let i = 0; i < texto.length; i++) {
|
|
1143
|
+
h ^= texto.charCodeAt(i);
|
|
1144
|
+
h = Math.imul(h, 16777619) >>> 0;
|
|
420
1145
|
}
|
|
421
|
-
return (
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
1146
|
+
return h.toString(36);
|
|
1147
|
+
}
|
|
1148
|
+
function claveMarco(tabla, usuario) {
|
|
1149
|
+
return `tabla.marco.v1.${tabla}.${usuario ? hashCorto(usuario) : "anon"}`;
|
|
1150
|
+
}
|
|
1151
|
+
function cargarPrefsMarco(clave) {
|
|
1152
|
+
try {
|
|
1153
|
+
if (typeof window === "undefined") return { ...PREFS_MARCO_DEFAULT };
|
|
1154
|
+
const crudo = window.localStorage.getItem(clave);
|
|
1155
|
+
if (!crudo) return { ...PREFS_MARCO_DEFAULT };
|
|
1156
|
+
const p = JSON.parse(crudo);
|
|
1157
|
+
return {
|
|
1158
|
+
ocultas: Array.isArray(p.ocultas) ? p.ocultas.filter((x) => typeof x === "string") : [],
|
|
1159
|
+
densidad: p.densidad === "compacta" ? "compacta" : "comoda"
|
|
1160
|
+
};
|
|
1161
|
+
} catch {
|
|
1162
|
+
return { ...PREFS_MARCO_DEFAULT };
|
|
1163
|
+
}
|
|
1164
|
+
}
|
|
1165
|
+
function guardarPrefsMarco(clave, prefs) {
|
|
1166
|
+
try {
|
|
1167
|
+
window.localStorage.setItem(clave, JSON.stringify(prefs));
|
|
1168
|
+
} catch {
|
|
1169
|
+
}
|
|
1170
|
+
}
|
|
1171
|
+
function borrarPrefsMarco(clave) {
|
|
1172
|
+
try {
|
|
1173
|
+
window.localStorage.removeItem(clave);
|
|
1174
|
+
} catch {
|
|
1175
|
+
}
|
|
1176
|
+
}
|
|
1177
|
+
function cssColumnasOcultas(alcance, ocultas) {
|
|
1178
|
+
const seguras = ocultas.filter((id) => ID_SEGURO.test(id));
|
|
1179
|
+
if (seguras.length === 0) return "";
|
|
1180
|
+
const selectores = seguras.map((id) => `[data-marco-tabla="${alcance}"] [data-col="${id}"]`);
|
|
1181
|
+
return `${selectores.join(",")}{display:none}`;
|
|
1182
|
+
}
|
|
1183
|
+
function offsetsAcumulados(anchos) {
|
|
1184
|
+
const offsets = [];
|
|
1185
|
+
let total = 0;
|
|
1186
|
+
for (const ancho of anchos) {
|
|
1187
|
+
offsets.push(total);
|
|
1188
|
+
total += ancho;
|
|
1189
|
+
}
|
|
1190
|
+
return { offsets, total };
|
|
1191
|
+
}
|
|
1192
|
+
var ContextoTablaPlana = createContext(false);
|
|
1193
|
+
function TablaPlana({ children }) {
|
|
1194
|
+
return /* @__PURE__ */ jsx(ContextoTablaPlana.Provider, { value: true, children });
|
|
426
1195
|
}
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
1196
|
+
var ContextoUsuarioTablas = createContext(null);
|
|
1197
|
+
function UsuarioTablas({ usuario, children }) {
|
|
1198
|
+
return /* @__PURE__ */ jsx(ContextoUsuarioTablas.Provider, { value: usuario ?? null, children });
|
|
1199
|
+
}
|
|
1200
|
+
var CLASE_BOTON = "inline-flex items-center gap-1.5 rounded-md border border-[var(--tema-borde)] px-2 py-1 text-xs font-medium text-[#3c3c3b] transition hover:bg-[var(--tema-badge-neutro)]";
|
|
1201
|
+
function MarcoTabla({
|
|
1202
|
+
clave,
|
|
1203
|
+
etiqueta,
|
|
1204
|
+
columnas,
|
|
1205
|
+
barra,
|
|
1206
|
+
alto,
|
|
1207
|
+
ajuste = "acotado",
|
|
1208
|
+
pie,
|
|
1209
|
+
controles = true,
|
|
1210
|
+
className = "",
|
|
1211
|
+
clasePlana = "overflow-x-auto print:overflow-visible",
|
|
1212
|
+
children
|
|
1213
|
+
}) {
|
|
1214
|
+
const plana = useContext(ContextoTablaPlana);
|
|
1215
|
+
if (plana)
|
|
1216
|
+
return pie ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
1217
|
+
/* @__PURE__ */ jsx("div", { className: clasePlana, children }),
|
|
1218
|
+
pie
|
|
1219
|
+
] }) : /* @__PURE__ */ jsx("div", { className: clasePlana, children });
|
|
1220
|
+
return /* @__PURE__ */ jsx(
|
|
1221
|
+
MarcoActivo,
|
|
1222
|
+
{
|
|
1223
|
+
clave,
|
|
1224
|
+
etiqueta,
|
|
1225
|
+
columnas,
|
|
1226
|
+
barra,
|
|
1227
|
+
alto,
|
|
1228
|
+
ajuste,
|
|
1229
|
+
pie,
|
|
1230
|
+
controles,
|
|
1231
|
+
className,
|
|
1232
|
+
children
|
|
1233
|
+
}
|
|
1234
|
+
);
|
|
1235
|
+
}
|
|
1236
|
+
function MarcoActivo({
|
|
1237
|
+
clave,
|
|
1238
|
+
etiqueta,
|
|
1239
|
+
columnas,
|
|
1240
|
+
barra,
|
|
1241
|
+
alto,
|
|
1242
|
+
ajuste,
|
|
1243
|
+
pie,
|
|
1244
|
+
controles,
|
|
439
1245
|
className,
|
|
440
|
-
|
|
1246
|
+
children
|
|
441
1247
|
}) {
|
|
442
|
-
const
|
|
443
|
-
const
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
1248
|
+
const usuario = useContext(ContextoUsuarioTablas);
|
|
1249
|
+
const claveLs = claveMarco(clave, usuario);
|
|
1250
|
+
const alcance = useId();
|
|
1251
|
+
const scroll = useRef(null);
|
|
1252
|
+
const [prefs, setPrefs] = useState(PREFS_MARCO_DEFAULT);
|
|
1253
|
+
const [menu, setMenu] = useState(false);
|
|
1254
|
+
const zonaMenu = useRef(null);
|
|
1255
|
+
useEffect(() => {
|
|
1256
|
+
setPrefs(cargarPrefsMarco(claveLs));
|
|
1257
|
+
}, [claveLs]);
|
|
1258
|
+
const persistir = useCallback(
|
|
1259
|
+
(nuevas) => {
|
|
1260
|
+
setPrefs(nuevas);
|
|
1261
|
+
guardarPrefsMarco(claveLs, nuevas);
|
|
1262
|
+
},
|
|
1263
|
+
[claveLs]
|
|
1264
|
+
);
|
|
1265
|
+
const ocultasValidas = prefs.ocultas.filter((id) => columnas?.some((c) => c.id === id));
|
|
1266
|
+
const css = cssColumnasOcultas(alcance, ocultasValidas);
|
|
1267
|
+
const actualizarSombras = useCallback(() => {
|
|
1268
|
+
const el = scroll.current;
|
|
1269
|
+
if (!el) return;
|
|
1270
|
+
const izq = el.scrollLeft > 0;
|
|
1271
|
+
const der = el.scrollLeft + el.clientWidth < el.scrollWidth - 1;
|
|
1272
|
+
el.toggleAttribute("data-sombra-izq", izq);
|
|
1273
|
+
el.toggleAttribute("data-sombra-der", der);
|
|
1274
|
+
}, []);
|
|
1275
|
+
useLayoutEffect(() => {
|
|
1276
|
+
const el = scroll.current;
|
|
1277
|
+
if (!el) return;
|
|
1278
|
+
const medir = () => {
|
|
1279
|
+
const fila = el.querySelector("thead tr");
|
|
1280
|
+
const izq = fila ? Array.from(fila.querySelectorAll(':scope > [data-fija="izq"]')) : [];
|
|
1281
|
+
const { offsets, total } = offsetsAcumulados(izq.map((c) => c.offsetWidth));
|
|
1282
|
+
offsets.forEach((o, i) => el.style.setProperty(`--fija-izq-${i}`, `${o}px`));
|
|
1283
|
+
el.style.setProperty("--fija-izq-total", `${total}px`);
|
|
1284
|
+
el.setAttribute("data-fijas-izq", String(izq.length));
|
|
1285
|
+
const der = fila?.querySelector(':scope > [data-fija="der"]');
|
|
1286
|
+
el.style.setProperty("--fija-der-total", `${der?.offsetWidth ?? 0}px`);
|
|
1287
|
+
actualizarSombras();
|
|
452
1288
|
};
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
1289
|
+
medir();
|
|
1290
|
+
if (typeof ResizeObserver === "undefined") return;
|
|
1291
|
+
const obs = new ResizeObserver(medir);
|
|
1292
|
+
obs.observe(el);
|
|
1293
|
+
const tabla = el.querySelector("table");
|
|
1294
|
+
if (tabla) obs.observe(tabla);
|
|
1295
|
+
return () => obs.disconnect();
|
|
1296
|
+
});
|
|
1297
|
+
useEffect(() => {
|
|
1298
|
+
const el = scroll.current;
|
|
1299
|
+
if (!el) return;
|
|
1300
|
+
const alGirar = (e) => {
|
|
1301
|
+
if (!e.shiftKey || e.deltaY === 0 || Math.abs(e.deltaX) > 0) return;
|
|
1302
|
+
if (el.scrollWidth <= el.clientWidth) return;
|
|
1303
|
+
el.scrollLeft += e.deltaY;
|
|
1304
|
+
e.preventDefault();
|
|
1305
|
+
actualizarSombras();
|
|
1306
|
+
};
|
|
1307
|
+
el.addEventListener("wheel", alGirar, { passive: false });
|
|
1308
|
+
return () => el.removeEventListener("wheel", alGirar);
|
|
1309
|
+
}, [actualizarSombras]);
|
|
1310
|
+
useEffect(() => {
|
|
1311
|
+
if (!menu) return;
|
|
1312
|
+
const tecla = (e) => e.key === "Escape" && setMenu(false);
|
|
1313
|
+
const fuera = (e) => {
|
|
1314
|
+
if (zonaMenu.current && !zonaMenu.current.contains(e.target)) setMenu(false);
|
|
1315
|
+
};
|
|
1316
|
+
document.addEventListener("keydown", tecla);
|
|
1317
|
+
document.addEventListener("mousedown", fuera);
|
|
1318
|
+
return () => {
|
|
1319
|
+
document.removeEventListener("keydown", tecla);
|
|
1320
|
+
document.removeEventListener("mousedown", fuera);
|
|
1321
|
+
};
|
|
1322
|
+
}, [menu]);
|
|
1323
|
+
function alternarColumna(id) {
|
|
1324
|
+
const ocultas = prefs.ocultas.includes(id) ? prefs.ocultas.filter((x) => x !== id) : [...prefs.ocultas, id];
|
|
1325
|
+
persistir({ ...prefs, ocultas });
|
|
1326
|
+
}
|
|
1327
|
+
function fijarDensidad(densidad) {
|
|
1328
|
+
persistir({ ...prefs, densidad });
|
|
1329
|
+
}
|
|
1330
|
+
function restablecer() {
|
|
1331
|
+
setPrefs({ ...PREFS_MARCO_DEFAULT });
|
|
1332
|
+
borrarPrefsMarco(claveLs);
|
|
1333
|
+
}
|
|
1334
|
+
const hayColumnas = Boolean(columnas && columnas.length > 0);
|
|
1335
|
+
return /* @__PURE__ */ jsxs(
|
|
1336
|
+
"div",
|
|
1337
|
+
{
|
|
1338
|
+
"data-marco-ajuste": ajuste,
|
|
1339
|
+
className: `flex min-w-0 flex-col gap-2 ${ajuste === "pagina" ? "min-h-0 flex-1" : ""} ${className}`,
|
|
1340
|
+
children: [
|
|
1341
|
+
css && /* @__PURE__ */ jsx("style", { children: css }),
|
|
1342
|
+
(controles || barra) && /* @__PURE__ */ jsxs("div", { className: "flex shrink-0 flex-wrap items-center gap-2", "data-marco-barra": "", children: [
|
|
1343
|
+
barra && /* @__PURE__ */ jsx("div", { className: "mr-auto flex flex-wrap items-center gap-2", children: barra }),
|
|
1344
|
+
controles && /* @__PURE__ */ jsxs("div", { className: "ml-auto flex items-center gap-2", children: [
|
|
1345
|
+
hayColumnas && /* @__PURE__ */ jsxs("div", { className: "relative", ref: zonaMenu, children: [
|
|
1346
|
+
/* @__PURE__ */ jsxs(
|
|
1347
|
+
"button",
|
|
1348
|
+
{
|
|
1349
|
+
type: "button",
|
|
1350
|
+
onClick: () => setMenu((v) => !v),
|
|
1351
|
+
"aria-expanded": menu,
|
|
1352
|
+
"aria-haspopup": "true",
|
|
1353
|
+
title: "Mostrar u ocultar columnas",
|
|
1354
|
+
className: CLASE_BOTON,
|
|
1355
|
+
children: [
|
|
1356
|
+
/* @__PURE__ */ jsx(ICONO_COLUMNAS, { size: TAMANO_BADGE, "aria-hidden": "true" }),
|
|
1357
|
+
"Columnas",
|
|
1358
|
+
ocultasValidas.length > 0 && /* @__PURE__ */ jsxs("span", { className: "rounded bg-[var(--tema-badge-neutro)] px-1 tabular-nums", children: [
|
|
1359
|
+
"-",
|
|
1360
|
+
ocultasValidas.length
|
|
1361
|
+
] })
|
|
1362
|
+
]
|
|
1363
|
+
}
|
|
1364
|
+
),
|
|
1365
|
+
menu && /* @__PURE__ */ jsxs("div", { className: "absolute right-0 top-full z-30 mt-1 w-60 rounded-md border border-[var(--tema-borde)] bg-[var(--tema-fondo)] p-2 shadow-lg", children: [
|
|
1366
|
+
/* @__PURE__ */ jsxs("div", { role: "group", "aria-label": "Columnas visibles", children: [
|
|
1367
|
+
/* @__PURE__ */ jsx("p", { className: "flex items-center gap-1 px-1 pb-1 text-[10px] font-semibold uppercase tracking-wide text-[#9a9a9a]", children: "Columnas visibles" }),
|
|
1368
|
+
columnas.map((c) => {
|
|
1369
|
+
const idInput = `${alcance}-${c.id}`;
|
|
1370
|
+
return /* @__PURE__ */ jsxs(
|
|
1371
|
+
"label",
|
|
1372
|
+
{
|
|
1373
|
+
htmlFor: idInput,
|
|
1374
|
+
className: "flex cursor-pointer items-center gap-2 rounded px-1.5 py-1 text-sm text-[#3c3c3b] hover:bg-[var(--tema-badge-neutro)]",
|
|
1375
|
+
children: [
|
|
1376
|
+
/* @__PURE__ */ jsx(
|
|
1377
|
+
"input",
|
|
1378
|
+
{
|
|
1379
|
+
id: idInput,
|
|
1380
|
+
type: "checkbox",
|
|
1381
|
+
checked: !prefs.ocultas.includes(c.id),
|
|
1382
|
+
onChange: () => alternarColumna(c.id)
|
|
1383
|
+
}
|
|
1384
|
+
),
|
|
1385
|
+
c.etiqueta
|
|
1386
|
+
]
|
|
1387
|
+
},
|
|
1388
|
+
c.id
|
|
1389
|
+
);
|
|
1390
|
+
})
|
|
1391
|
+
] }),
|
|
1392
|
+
/* @__PURE__ */ jsxs(
|
|
1393
|
+
"button",
|
|
1394
|
+
{
|
|
1395
|
+
type: "button",
|
|
1396
|
+
onClick: restablecer,
|
|
1397
|
+
className: "mt-2 inline-flex w-full items-center justify-center gap-1.5 rounded border border-[var(--tema-borde)] px-2 py-1 text-xs text-[#3c3c3b] hover:bg-[var(--tema-badge-neutro)]",
|
|
1398
|
+
children: [
|
|
1399
|
+
/* @__PURE__ */ jsx(ICONO_RESTABLECER, { size: TAMANO_BADGE, "aria-hidden": "true" }),
|
|
1400
|
+
"Restablecer"
|
|
1401
|
+
]
|
|
1402
|
+
}
|
|
1403
|
+
)
|
|
1404
|
+
] })
|
|
1405
|
+
] }),
|
|
1406
|
+
hayColumnas && /* @__PURE__ */ jsx(InfoExplicacion, { id: "plataforma.tabla_columnas" }),
|
|
1407
|
+
/* @__PURE__ */ jsxs("div", { className: "inline-flex items-center overflow-hidden rounded-md border border-[var(--tema-borde)]", role: "group", "aria-label": "Densidad de filas", children: [
|
|
1408
|
+
/* @__PURE__ */ jsx(BotonDensidad, { actual: prefs.densidad, valor: "compacta", onClick: fijarDensidad }),
|
|
1409
|
+
/* @__PURE__ */ jsx(BotonDensidad, { actual: prefs.densidad, valor: "comoda", onClick: fijarDensidad })
|
|
1410
|
+
] }),
|
|
1411
|
+
/* @__PURE__ */ jsx(InfoExplicacion, { id: "plataforma.tabla_densidad" })
|
|
1412
|
+
] })
|
|
1413
|
+
] }),
|
|
1414
|
+
/* @__PURE__ */ jsx(
|
|
1415
|
+
"div",
|
|
465
1416
|
{
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
1417
|
+
ref: scroll,
|
|
1418
|
+
role: "region",
|
|
1419
|
+
"aria-label": etiqueta,
|
|
1420
|
+
tabIndex: 0,
|
|
1421
|
+
"data-marco-tabla": alcance,
|
|
1422
|
+
"data-densidad": prefs.densidad,
|
|
1423
|
+
onScroll: actualizarSombras,
|
|
1424
|
+
onFocus: (e) => {
|
|
1425
|
+
if (e.target === e.currentTarget) return;
|
|
1426
|
+
const celda = e.target.closest("td,th");
|
|
1427
|
+
celda?.scrollIntoView?.({ block: "nearest", inline: "nearest" });
|
|
1428
|
+
},
|
|
1429
|
+
"data-ajuste": ajuste,
|
|
1430
|
+
style: alto ? { "--marco-alto": alto } : void 0,
|
|
1431
|
+
className: `marco-tabla-scroll rounded-lg border border-[var(--tema-borde)] ${ajuste === "pagina" ? "min-h-28" : ""}`,
|
|
1432
|
+
children
|
|
469
1433
|
}
|
|
470
|
-
)
|
|
1434
|
+
),
|
|
1435
|
+
pie && // Al cambiar de pagina (o de tamano) el cuerpo vuelve arriba: la pagina ya no se desplaza, la tabla si.
|
|
1436
|
+
/* @__PURE__ */ jsx(
|
|
1437
|
+
"div",
|
|
1438
|
+
{
|
|
1439
|
+
className: "shrink-0",
|
|
1440
|
+
"data-marco-pie": "",
|
|
1441
|
+
onClick: (e) => {
|
|
1442
|
+
if (e.target.closest("button")) scroll.current?.scrollTo?.({ top: 0 });
|
|
1443
|
+
},
|
|
1444
|
+
children: pie
|
|
1445
|
+
}
|
|
1446
|
+
)
|
|
1447
|
+
]
|
|
1448
|
+
}
|
|
1449
|
+
);
|
|
1450
|
+
}
|
|
1451
|
+
function BotonDensidad({
|
|
1452
|
+
actual,
|
|
1453
|
+
valor,
|
|
1454
|
+
onClick
|
|
1455
|
+
}) {
|
|
1456
|
+
const Icono = valor === "compacta" ? ICONO_DENSIDAD_COMPACTA : ICONO_DENSIDAD_COMODA;
|
|
1457
|
+
const nombre = valor === "compacta" ? "Densidad compacta" : "Densidad c\xF3moda";
|
|
1458
|
+
const activo = actual === valor;
|
|
1459
|
+
return /* @__PURE__ */ jsx(
|
|
1460
|
+
"button",
|
|
1461
|
+
{
|
|
1462
|
+
type: "button",
|
|
1463
|
+
"aria-pressed": activo,
|
|
1464
|
+
"aria-label": nombre,
|
|
1465
|
+
title: nombre,
|
|
1466
|
+
onClick: () => onClick(valor),
|
|
1467
|
+
className: `px-2 py-1 transition ${activo ? "bg-[var(--tema-primario)] text-white" : "text-[#565656] hover:bg-[var(--tema-badge-neutro)]"}`,
|
|
1468
|
+
children: /* @__PURE__ */ jsx(Icono, { size: TAMANO_BADGE, "aria-hidden": "true" })
|
|
1469
|
+
}
|
|
1470
|
+
);
|
|
1471
|
+
}
|
|
1472
|
+
function CascaronApp({
|
|
1473
|
+
producto,
|
|
1474
|
+
hrefInicio = "/",
|
|
1475
|
+
logo,
|
|
1476
|
+
usuario,
|
|
1477
|
+
hrefCerrarSesion = "/auth/logout",
|
|
1478
|
+
grupos,
|
|
1479
|
+
pieExtra,
|
|
1480
|
+
children
|
|
1481
|
+
}) {
|
|
1482
|
+
return /* @__PURE__ */ jsx(UsuarioTablas, { usuario: usuario.idEstable, children: /* @__PURE__ */ jsxs("div", { className: "flex min-h-full", children: [
|
|
1483
|
+
/* @__PURE__ */ jsx(
|
|
1484
|
+
SidebarColapsable,
|
|
1485
|
+
{
|
|
1486
|
+
cabecera: /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-2", children: [
|
|
1487
|
+
/* @__PURE__ */ jsx(LinkBase, { href: hrefInicio, className: "flex shrink-0 items-center gap-2", children: logo && // eslint-disable-next-line @next/next/no-img-element
|
|
1488
|
+
/* @__PURE__ */ jsx("img", { src: logo.src, alt: logo.alt, width: logo.ancho, height: logo.alto }) }),
|
|
1489
|
+
/* @__PURE__ */ jsx("span", { className: "text-sm font-semibold text-[var(--tema-primario)]", children: producto })
|
|
1490
|
+
] }),
|
|
1491
|
+
pie: /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 md:group-data-[colapsado=true]/side:flex-col", children: [
|
|
1492
|
+
pieExtra,
|
|
1493
|
+
/* @__PURE__ */ jsxs("span", { className: "flex min-w-0 flex-1 flex-col leading-tight md:group-data-[colapsado=true]/side:hidden", children: [
|
|
1494
|
+
/* @__PURE__ */ jsx("span", { className: "truncate text-[11px] font-medium text-[#3c3c3b]", title: usuario.nombre, children: usuario.nombre }),
|
|
1495
|
+
usuario.rol && /* @__PURE__ */ jsxs("span", { className: "mt-0.5 inline-flex items-center gap-1", children: [
|
|
1496
|
+
/* @__PURE__ */ jsx(
|
|
1497
|
+
"span",
|
|
1498
|
+
{
|
|
1499
|
+
className: "w-fit rounded-full bg-[var(--tema-badge-neutro)] px-1.5 py-0.5 text-[10px] font-medium text-[#565656]",
|
|
1500
|
+
title: `Rol: ${usuario.rol}`,
|
|
1501
|
+
children: usuario.rol
|
|
1502
|
+
}
|
|
1503
|
+
),
|
|
1504
|
+
/* @__PURE__ */ jsx(InfoExplicacion, { id: "plataforma.rol" })
|
|
1505
|
+
] })
|
|
1506
|
+
] }),
|
|
1507
|
+
/* @__PURE__ */ jsx(
|
|
1508
|
+
"a",
|
|
1509
|
+
{
|
|
1510
|
+
href: hrefCerrarSesion,
|
|
1511
|
+
title: "Cerrar sesi\xF3n",
|
|
1512
|
+
"aria-label": "Cerrar sesi\xF3n",
|
|
1513
|
+
className: "flex shrink-0 items-center transition hover:text-[var(--tema-primario)]",
|
|
1514
|
+
children: /* @__PURE__ */ jsx(ICONO_CERRAR_SESION, { size: TAMANO_BOTON, "aria-hidden": "true" })
|
|
1515
|
+
}
|
|
1516
|
+
)
|
|
1517
|
+
] }),
|
|
1518
|
+
children: grupos.map((g, i) => /* @__PURE__ */ jsx(SeccionNav, { titulo: g.titulo, children: g.enlaces.map(({ href, etiqueta, icono: Icono }) => /* @__PURE__ */ jsx(EnlaceNav, { href, etiqueta, icono: /* @__PURE__ */ jsx(Icono, { size: TAMANO_BOTON, "aria-hidden": "true" }) }, href)) }, g.titulo ?? i))
|
|
471
1519
|
}
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
return /* @__PURE__ */ jsxs("div", { className, children: [
|
|
476
|
-
heading ? /* @__PURE__ */ jsx("div", { style: { marginBottom: 8 }, children: /* @__PURE__ */ jsx("h3", { style: { margin: 0, fontWeight: 600 }, children: heading }) }) : null,
|
|
477
|
-
extra ? /* @__PURE__ */ jsx("div", { style: { marginBottom: 8 }, children: extra }) : null,
|
|
478
|
-
loading ? /* @__PURE__ */ jsx("div", { style: { display: "flex", flexDirection: "column", gap: 16 }, children: Array.from({ length: 6 }).map((_, i) => /* @__PURE__ */ jsx(Skeleton, { active: true, paragraph: { rows: 0 }, title: { width: "100%" } }, i)) }) : /* @__PURE__ */ jsx(
|
|
479
|
-
Table,
|
|
1520
|
+
),
|
|
1521
|
+
/* @__PURE__ */ jsx(
|
|
1522
|
+
"div",
|
|
480
1523
|
{
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
scroll: resolvedScroll,
|
|
485
|
-
pagination: resolvedPagination,
|
|
486
|
-
locale: {
|
|
487
|
-
emptyText: mergedLabels.emptyText,
|
|
488
|
-
triggerAsc: mergedLabels.sortAsc,
|
|
489
|
-
triggerDesc: mergedLabels.sortDesc,
|
|
490
|
-
cancelSort: mergedLabels.cancelSort
|
|
491
|
-
},
|
|
492
|
-
...rest
|
|
1524
|
+
"data-area-contenido": "",
|
|
1525
|
+
className: "flex min-h-screen min-w-0 flex-1 flex-col overflow-x-clip pt-14 transition-[padding] md:pt-0 md:pr-[var(--asistente-ancho,0px)]",
|
|
1526
|
+
children
|
|
493
1527
|
}
|
|
494
1528
|
)
|
|
1529
|
+
] }) });
|
|
1530
|
+
}
|
|
1531
|
+
function Migas({
|
|
1532
|
+
hrefVolver,
|
|
1533
|
+
etiquetaVolver,
|
|
1534
|
+
actual,
|
|
1535
|
+
actualMono = false
|
|
1536
|
+
}) {
|
|
1537
|
+
return /* @__PURE__ */ jsxs("nav", { "aria-label": "Ruta", className: "mb-3 flex flex-wrap items-center gap-2 text-xs text-[#807f7f]", children: [
|
|
1538
|
+
/* @__PURE__ */ jsxs(LinkBase, { href: hrefVolver, className: "text-[var(--tema-primario)] underline", children: [
|
|
1539
|
+
"\u2190 ",
|
|
1540
|
+
etiquetaVolver
|
|
1541
|
+
] }),
|
|
1542
|
+
/* @__PURE__ */ jsx("span", { "aria-hidden": "true", children: "/" }),
|
|
1543
|
+
/* @__PURE__ */ jsx("span", { className: actualMono ? "font-mono" : void 0, children: actual })
|
|
495
1544
|
] });
|
|
496
1545
|
}
|
|
497
|
-
function
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
}) {
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
}
|
|
510
|
-
onChange?.(next);
|
|
1546
|
+
function SubNav({
|
|
1547
|
+
etiqueta,
|
|
1548
|
+
secciones,
|
|
1549
|
+
activa
|
|
1550
|
+
}) {
|
|
1551
|
+
return /* @__PURE__ */ jsx("nav", { "aria-label": etiqueta, className: "mt-4 flex flex-wrap gap-2 text-sm", children: secciones.map((s) => /* @__PURE__ */ jsx(
|
|
1552
|
+
LinkBase,
|
|
1553
|
+
{
|
|
1554
|
+
href: s.href,
|
|
1555
|
+
"aria-current": s.id === activa ? "page" : void 0,
|
|
1556
|
+
className: `pulsable rounded-md border px-3 py-1 ${s.id === activa ? "border-[var(--tema-primario)] bg-[var(--tema-badge-neutro)] font-semibold" : "border-[var(--tema-borde)] hover:bg-[var(--tema-badge-neutro)]"}`,
|
|
1557
|
+
children: s.texto
|
|
511
1558
|
},
|
|
512
|
-
|
|
513
|
-
);
|
|
514
|
-
return [current, setValue];
|
|
1559
|
+
s.id
|
|
1560
|
+
)) });
|
|
515
1561
|
}
|
|
516
|
-
|
|
517
|
-
|
|
1562
|
+
var BOTON = {
|
|
1563
|
+
// Primario = relleno neutro oscuro (no el rojo de marca); el rojo queda reservado a peligro.
|
|
1564
|
+
primario: "inline-flex items-center gap-1.5 rounded-md bg-[var(--tema-texto)] px-3 py-1.5 text-sm font-medium text-white transition hover:brightness-125 disabled:opacity-50",
|
|
1565
|
+
secundario: "inline-flex items-center gap-1.5 rounded-md border border-[var(--tema-borde)] px-3 py-1.5 text-sm font-medium text-[#3c3c3b] transition hover:bg-[var(--tema-badge-neutro)] disabled:opacity-50"
|
|
1566
|
+
};
|
|
1567
|
+
function AccionConDialogo({
|
|
1568
|
+
etiqueta,
|
|
1569
|
+
titulo,
|
|
1570
|
+
icono,
|
|
1571
|
+
variante = "secundario",
|
|
1572
|
+
children
|
|
1573
|
+
}) {
|
|
1574
|
+
const [abierto, setAbierto] = useState(false);
|
|
1575
|
+
const disparador = useRef(null);
|
|
1576
|
+
const panel = useRef(null);
|
|
1577
|
+
const tituloId = useId();
|
|
1578
|
+
useEffect(() => {
|
|
1579
|
+
if (!abierto) return;
|
|
1580
|
+
queueMicrotask(() => {
|
|
1581
|
+
const campo = panel.current?.querySelector("input, select, textarea");
|
|
1582
|
+
campo?.focus();
|
|
1583
|
+
});
|
|
1584
|
+
}, [abierto]);
|
|
1585
|
+
function cerrar() {
|
|
1586
|
+
setAbierto(false);
|
|
1587
|
+
disparador.current?.focus();
|
|
1588
|
+
}
|
|
1589
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
1590
|
+
/* @__PURE__ */ jsxs("button", { ref: disparador, type: "button", onClick: () => setAbierto(true), className: BOTON[variante], children: [
|
|
1591
|
+
icono,
|
|
1592
|
+
etiqueta
|
|
1593
|
+
] }),
|
|
1594
|
+
abierto && /* @__PURE__ */ jsx(
|
|
1595
|
+
"div",
|
|
1596
|
+
{
|
|
1597
|
+
"data-testid": "dialogo-fondo",
|
|
1598
|
+
className: "fixed inset-0 z-50 flex items-center justify-center bg-black/40 p-4",
|
|
1599
|
+
onClick: cerrar,
|
|
1600
|
+
children: /* @__PURE__ */ jsxs(
|
|
1601
|
+
"div",
|
|
1602
|
+
{
|
|
1603
|
+
ref: panel,
|
|
1604
|
+
role: "dialog",
|
|
1605
|
+
"aria-modal": "true",
|
|
1606
|
+
"aria-labelledby": tituloId,
|
|
1607
|
+
onClick: (e) => e.stopPropagation(),
|
|
1608
|
+
onKeyDown: (e) => {
|
|
1609
|
+
if (e.key === "Escape") {
|
|
1610
|
+
e.stopPropagation();
|
|
1611
|
+
cerrar();
|
|
1612
|
+
}
|
|
1613
|
+
},
|
|
1614
|
+
className: "max-h-[90vh] w-full max-w-md overflow-y-auto rounded-xl border border-[var(--tema-borde)] bg-[var(--tema-fondo)] p-6 shadow-xl",
|
|
1615
|
+
children: [
|
|
1616
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-start justify-between gap-3", children: [
|
|
1617
|
+
/* @__PURE__ */ jsxs("h2", { id: tituloId, className: "flex items-center gap-2 text-base font-semibold text-[var(--tema-primario-oscuro)]", children: [
|
|
1618
|
+
icono,
|
|
1619
|
+
titulo
|
|
1620
|
+
] }),
|
|
1621
|
+
/* @__PURE__ */ jsx(
|
|
1622
|
+
"button",
|
|
1623
|
+
{
|
|
1624
|
+
type: "button",
|
|
1625
|
+
onClick: cerrar,
|
|
1626
|
+
"aria-label": "Cerrar",
|
|
1627
|
+
title: "Cerrar",
|
|
1628
|
+
className: "rounded-md p-1 text-[#807f7f] transition hover:bg-[var(--tema-badge-neutro)]",
|
|
1629
|
+
children: /* @__PURE__ */ jsx(ICONO_CERRAR, { size: TAMANO_BADGE, "aria-hidden": "true" })
|
|
1630
|
+
}
|
|
1631
|
+
)
|
|
1632
|
+
] }),
|
|
1633
|
+
/* @__PURE__ */ jsx("div", { className: "mt-4", children })
|
|
1634
|
+
]
|
|
1635
|
+
}
|
|
1636
|
+
)
|
|
1637
|
+
}
|
|
1638
|
+
)
|
|
1639
|
+
] });
|
|
518
1640
|
}
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
1641
|
+
var CLASE_REGION_LISTADO = "flex min-h-0 flex-1 flex-col";
|
|
1642
|
+
function PaginaListado({
|
|
1643
|
+
titulo,
|
|
1644
|
+
icono,
|
|
1645
|
+
descripcion,
|
|
1646
|
+
acciones,
|
|
1647
|
+
className = "",
|
|
1648
|
+
children
|
|
1649
|
+
}) {
|
|
1650
|
+
return /* @__PURE__ */ jsxs("main", { "data-pagina-listado": "", className: `flex min-h-0 w-full flex-1 flex-col gap-3 px-6 py-4 ${className}`, children: [
|
|
1651
|
+
/* @__PURE__ */ jsxs("header", { className: "flex shrink-0 flex-wrap items-center gap-x-3 gap-y-1", children: [
|
|
1652
|
+
/* @__PURE__ */ jsxs("h1", { className: "flex shrink-0 items-center gap-2 text-xl font-semibold text-[var(--tema-primario-oscuro)]", children: [
|
|
1653
|
+
icono,
|
|
1654
|
+
titulo
|
|
1655
|
+
] }),
|
|
1656
|
+
descripcion && /* @__PURE__ */ jsx("p", { className: "min-w-[12rem] flex-1 truncate text-sm text-[#807f7f]", title: descripcion, children: descripcion }),
|
|
1657
|
+
acciones && /* @__PURE__ */ jsx("div", { className: "ml-auto flex shrink-0 flex-wrap items-center gap-2", children: acciones })
|
|
1658
|
+
] }),
|
|
1659
|
+
children
|
|
1660
|
+
] });
|
|
1661
|
+
}
|
|
1662
|
+
function ModalPanel({
|
|
1663
|
+
titulo,
|
|
1664
|
+
tituloId,
|
|
1665
|
+
acciones,
|
|
1666
|
+
onCerrar,
|
|
1667
|
+
etiquetaCerrar = "Cerrar",
|
|
1668
|
+
ancho = "max-w-[min(96vw,100rem)]",
|
|
1669
|
+
children
|
|
1670
|
+
}) {
|
|
1671
|
+
const dialogo = useRef(null);
|
|
1672
|
+
useEffect(() => {
|
|
1673
|
+
dialogo.current?.focus();
|
|
1674
|
+
}, []);
|
|
1675
|
+
return /* @__PURE__ */ jsx("div", { "data-testid": "modal-fondo", className: "fixed inset-0 z-50 flex items-center justify-center bg-black/40 p-4", onClick: onCerrar, children: /* @__PURE__ */ jsxs(
|
|
1676
|
+
"div",
|
|
1677
|
+
{
|
|
1678
|
+
ref: dialogo,
|
|
1679
|
+
role: "dialog",
|
|
1680
|
+
"aria-modal": "true",
|
|
1681
|
+
"aria-labelledby": tituloId,
|
|
1682
|
+
tabIndex: -1,
|
|
1683
|
+
onClick: (e) => e.stopPropagation(),
|
|
1684
|
+
onKeyDown: (e) => {
|
|
1685
|
+
if (e.key === "Escape") {
|
|
1686
|
+
e.stopPropagation();
|
|
1687
|
+
onCerrar();
|
|
553
1688
|
}
|
|
554
|
-
}
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
1689
|
+
},
|
|
1690
|
+
className: `flex max-h-[90dvh] w-full ${ancho} flex-col gap-3 rounded-xl border border-[var(--tema-borde)] bg-[var(--tema-fondo)] p-4 shadow-xl outline-none`,
|
|
1691
|
+
children: [
|
|
1692
|
+
/* @__PURE__ */ jsxs("div", { "data-modal-cabecera": "", className: "flex shrink-0 items-start justify-between gap-3", children: [
|
|
1693
|
+
/* @__PURE__ */ jsx("h2", { id: tituloId, className: "flex min-w-0 items-center gap-1.5 text-base font-semibold text-[var(--tema-primario-oscuro)]", children: titulo }),
|
|
1694
|
+
/* @__PURE__ */ jsxs("div", { className: "flex shrink-0 items-center gap-2", children: [
|
|
1695
|
+
acciones,
|
|
1696
|
+
/* @__PURE__ */ jsx(
|
|
1697
|
+
"button",
|
|
1698
|
+
{
|
|
1699
|
+
type: "button",
|
|
1700
|
+
onClick: onCerrar,
|
|
1701
|
+
"aria-label": etiquetaCerrar,
|
|
1702
|
+
title: etiquetaCerrar,
|
|
1703
|
+
className: "rounded-md p-1 text-[#807f7f] transition hover:bg-[var(--tema-badge-neutro)]",
|
|
1704
|
+
children: /* @__PURE__ */ jsx(ICONO_CERRAR, { size: TAMANO_BADGE, "aria-hidden": "true" })
|
|
1705
|
+
}
|
|
1706
|
+
)
|
|
1707
|
+
] })
|
|
1708
|
+
] }),
|
|
1709
|
+
/* @__PURE__ */ jsx("div", { "data-modal-cuerpo": "", className: `${CLASE_REGION_LISTADO} gap-3`, children })
|
|
1710
|
+
]
|
|
564
1711
|
}
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
1712
|
+
) });
|
|
1713
|
+
}
|
|
1714
|
+
function Pestanas({
|
|
1715
|
+
etiqueta,
|
|
1716
|
+
pestanas,
|
|
1717
|
+
inicial,
|
|
1718
|
+
extra
|
|
1719
|
+
}) {
|
|
1720
|
+
const base = useId();
|
|
1721
|
+
const [activa, setActiva] = useState(inicial ?? pestanas[0]?.id);
|
|
1722
|
+
const ids = pestanas.map((p) => p.id);
|
|
1723
|
+
const teclado = (e) => {
|
|
1724
|
+
if (e.key !== "ArrowRight" && e.key !== "ArrowLeft") return;
|
|
1725
|
+
e.preventDefault();
|
|
1726
|
+
const i = ids.indexOf(activa ?? "");
|
|
1727
|
+
const siguiente = ids[(i + (e.key === "ArrowRight" ? 1 : ids.length - 1)) % ids.length];
|
|
1728
|
+
setActiva(siguiente);
|
|
1729
|
+
document.getElementById(`${base}-pestana-${siguiente}`)?.focus();
|
|
1730
|
+
};
|
|
1731
|
+
return /* @__PURE__ */ jsxs("div", { className: "space-y-4", children: [
|
|
1732
|
+
/* @__PURE__ */ jsxs("div", { role: "tablist", "aria-label": etiqueta, className: "inline-flex gap-1 rounded-lg bg-[var(--tema-badge-neutro)] p-1 print:hidden", children: [
|
|
1733
|
+
pestanas.map((p) => /* @__PURE__ */ jsx(
|
|
1734
|
+
"button",
|
|
1735
|
+
{
|
|
1736
|
+
type: "button",
|
|
1737
|
+
role: "tab",
|
|
1738
|
+
id: `${base}-pestana-${p.id}`,
|
|
1739
|
+
"aria-selected": activa === p.id,
|
|
1740
|
+
"aria-controls": `${base}-panel-${p.id}`,
|
|
1741
|
+
tabIndex: activa === p.id ? 0 : -1,
|
|
1742
|
+
onClick: () => setActiva(p.id),
|
|
1743
|
+
onKeyDown: teclado,
|
|
1744
|
+
className: `rounded-md px-3 py-1 text-xs font-medium ${activa === p.id ? "bg-[var(--tema-fondo)] text-[var(--tema-primario-oscuro)] shadow-sm" : "text-[#565656] hover:text-[var(--tema-primario)]"}`,
|
|
1745
|
+
children: p.texto
|
|
1746
|
+
},
|
|
1747
|
+
p.id
|
|
1748
|
+
)),
|
|
1749
|
+
extra && /* @__PURE__ */ jsx("span", { className: "self-center pr-1", children: extra })
|
|
1750
|
+
] }),
|
|
1751
|
+
pestanas.map((p) => /* @__PURE__ */ jsx(
|
|
1752
|
+
"div",
|
|
1753
|
+
{
|
|
1754
|
+
role: "tabpanel",
|
|
1755
|
+
id: `${base}-panel-${p.id}`,
|
|
1756
|
+
"aria-labelledby": `${base}-pestana-${p.id}`,
|
|
1757
|
+
className: `space-y-3 ${activa !== p.id ? "hidden print:block" : ""}`,
|
|
1758
|
+
children: p.contenido
|
|
1759
|
+
},
|
|
1760
|
+
p.id
|
|
1761
|
+
))
|
|
1762
|
+
] });
|
|
1763
|
+
}
|
|
1764
|
+
function PantallaAcceso({
|
|
1765
|
+
producto,
|
|
1766
|
+
titulo,
|
|
1767
|
+
descripcion,
|
|
1768
|
+
hrefLogin,
|
|
1769
|
+
etiquetaBoton = "Iniciar sesi\xF3n con Microsoft 365",
|
|
1770
|
+
capacidades = [],
|
|
1771
|
+
logo,
|
|
1772
|
+
error
|
|
1773
|
+
}) {
|
|
1774
|
+
return /* @__PURE__ */ jsxs("main", { className: "reflejo-fondo flex min-h-screen flex-1 flex-col items-center justify-center gap-10 bg-[#f4f8fc] px-6 py-16", children: [
|
|
1775
|
+
/* @__PURE__ */ jsxs("header", { className: "flex items-center gap-2", children: [
|
|
1776
|
+
logo,
|
|
1777
|
+
logo && /* @__PURE__ */ jsx("span", { className: "h-6 w-px bg-[var(--tema-borde)]" }),
|
|
1778
|
+
/* @__PURE__ */ jsx("span", { className: "text-base font-semibold text-[var(--tema-primario)]", children: producto })
|
|
1779
|
+
] }),
|
|
1780
|
+
/* @__PURE__ */ jsxs("div", { className: "flex max-w-xl flex-col items-center gap-4 text-center", children: [
|
|
1781
|
+
/* @__PURE__ */ jsx("h1", { className: "text-3xl font-semibold text-[var(--tema-primario-oscuro)] sm:text-4xl", children: titulo }),
|
|
1782
|
+
/* @__PURE__ */ jsx("p", { className: "text-base text-[#565656]", children: descripcion }),
|
|
1783
|
+
error && /* @__PURE__ */ jsx("p", { role: "alert", className: "rounded-md bg-[var(--tema-badge-error)] px-3 py-2 text-sm text-[var(--tema-peligro)]", children: error }),
|
|
1784
|
+
/* @__PURE__ */ jsxs(
|
|
1785
|
+
"a",
|
|
1786
|
+
{
|
|
1787
|
+
href: hrefLogin,
|
|
1788
|
+
className: "mt-2 inline-flex items-center gap-2 rounded-md bg-[var(--tema-texto)] px-5 py-2.5 text-sm font-medium text-white transition hover:brightness-125",
|
|
1789
|
+
children: [
|
|
1790
|
+
/* @__PURE__ */ jsx(ICONO_LOGIN_MICROSOFT, { size: TAMANO_BOTON, "aria-hidden": "true" }),
|
|
1791
|
+
etiquetaBoton
|
|
1792
|
+
]
|
|
572
1793
|
}
|
|
573
|
-
|
|
1794
|
+
)
|
|
1795
|
+
] }),
|
|
1796
|
+
capacidades.length > 0 && /* @__PURE__ */ jsx("div", { className: "grid w-full max-w-4xl gap-4 sm:grid-cols-3", children: capacidades.map(({ icono: Icono, titulo: t, descripcion: d }) => /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-2 rounded-xl border border-[var(--tema-borde)] bg-white p-5 text-left shadow-sm", children: [
|
|
1797
|
+
/* @__PURE__ */ jsx("span", { className: "flex h-10 w-10 items-center justify-center rounded-lg bg-[var(--tema-badge-neutro)] text-[var(--tema-primario)]", children: /* @__PURE__ */ jsx(Icono, { size: TAMANO_BOTON, "aria-hidden": "true" }) }),
|
|
1798
|
+
/* @__PURE__ */ jsx("h2", { className: "text-sm font-semibold text-[var(--tema-texto)]", children: t }),
|
|
1799
|
+
/* @__PURE__ */ jsx("p", { className: "text-xs leading-relaxed text-[#565656]", children: d })
|
|
1800
|
+
] }, t)) })
|
|
1801
|
+
] });
|
|
1802
|
+
}
|
|
1803
|
+
function PantallaCargando({ etiqueta = "Cargando..." }) {
|
|
1804
|
+
return /* @__PURE__ */ jsx("div", { className: "flex min-h-[60vh] w-full flex-1 items-center justify-center", children: /* @__PURE__ */ jsx(SpinnerMarca, { tamano: 140, etiqueta }) });
|
|
1805
|
+
}
|
|
1806
|
+
function FechaHoraLocal({ iso }) {
|
|
1807
|
+
const [texto, setTexto] = useState(() => _isoLegible(iso));
|
|
1808
|
+
useEffect(() => {
|
|
1809
|
+
setTexto(formatearFechaHora(iso));
|
|
1810
|
+
}, [iso]);
|
|
1811
|
+
return /* @__PURE__ */ jsx("span", { suppressHydrationWarning: true, children: texto });
|
|
1812
|
+
}
|
|
1813
|
+
function _isoLegible(iso) {
|
|
1814
|
+
if (!iso) return "\u2014";
|
|
1815
|
+
const m = iso.match(/^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2})/);
|
|
1816
|
+
if (!m) return iso;
|
|
1817
|
+
const [, anio, mes, dia, hora, min, seg] = m;
|
|
1818
|
+
return `${anio}/${mes}/${dia} ${hora}:${min}:${seg}`;
|
|
1819
|
+
}
|
|
1820
|
+
var ANCHOS = {
|
|
1821
|
+
completo: "",
|
|
1822
|
+
"2xl": "mx-auto max-w-2xl",
|
|
1823
|
+
"3xl": "mx-auto max-w-3xl",
|
|
1824
|
+
"4xl": "mx-auto max-w-4xl"
|
|
1825
|
+
};
|
|
1826
|
+
function PaginaContenido({
|
|
1827
|
+
titulo,
|
|
1828
|
+
icono,
|
|
1829
|
+
descripcion,
|
|
1830
|
+
acciones,
|
|
1831
|
+
ancho = "completo",
|
|
1832
|
+
children
|
|
1833
|
+
}) {
|
|
1834
|
+
return /* @__PURE__ */ jsxs("main", { className: `w-full flex-1 px-6 py-10 ${ANCHOS[ancho]}`, children: [
|
|
1835
|
+
/* @__PURE__ */ jsxs("div", { className: "flex flex-wrap items-center justify-between gap-3", children: [
|
|
1836
|
+
/* @__PURE__ */ jsxs("h1", { className: "flex items-center gap-2 text-xl font-semibold text-[var(--tema-primario-oscuro)]", children: [
|
|
1837
|
+
icono,
|
|
1838
|
+
titulo
|
|
1839
|
+
] }),
|
|
1840
|
+
acciones && /* @__PURE__ */ jsx("div", { className: "flex flex-wrap items-center gap-2", children: acciones })
|
|
1841
|
+
] }),
|
|
1842
|
+
descripcion && /* @__PURE__ */ jsx("p", { className: "mt-1 text-sm text-[#807f7f]", children: descripcion }),
|
|
1843
|
+
/* @__PURE__ */ jsx("div", { className: "mt-6", children })
|
|
1844
|
+
] });
|
|
1845
|
+
}
|
|
1846
|
+
function usePaginacionLocal(items, tamanoInicial = 10) {
|
|
1847
|
+
const [tamano, setTamano] = useState(tamanoInicial);
|
|
1848
|
+
const [paginaActual, setPaginaActual] = useState(1);
|
|
1849
|
+
const totalPaginas = Math.max(1, Math.ceil(items.length / tamano));
|
|
1850
|
+
const pagina = Math.min(paginaActual, totalPaginas);
|
|
1851
|
+
const itemsPagina = useMemo(() => {
|
|
1852
|
+
const inicio = (pagina - 1) * tamano;
|
|
1853
|
+
return items.slice(inicio, inicio + tamano);
|
|
1854
|
+
}, [items, pagina, tamano]);
|
|
1855
|
+
return {
|
|
1856
|
+
itemsPagina,
|
|
1857
|
+
paginaActual: pagina,
|
|
1858
|
+
totalPaginas,
|
|
1859
|
+
tamano,
|
|
1860
|
+
totalItems: items.length,
|
|
1861
|
+
siguiente: () => setPaginaActual((p) => Math.min(p + 1, totalPaginas)),
|
|
1862
|
+
anterior: () => setPaginaActual((p) => Math.max(p - 1, 1)),
|
|
1863
|
+
cambiarTamano: (n) => {
|
|
1864
|
+
setTamano(n);
|
|
1865
|
+
setPaginaActual(1);
|
|
574
1866
|
}
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
1867
|
+
};
|
|
1868
|
+
}
|
|
1869
|
+
var TAMANOS = [10, 25, 50, 100];
|
|
1870
|
+
function PaginadorLocal({
|
|
1871
|
+
paginaActual,
|
|
1872
|
+
totalPaginas,
|
|
1873
|
+
totalItems,
|
|
1874
|
+
tamano,
|
|
1875
|
+
tamanos = TAMANOS,
|
|
1876
|
+
onAnterior,
|
|
1877
|
+
onSiguiente,
|
|
1878
|
+
onCambiarTamano
|
|
1879
|
+
}) {
|
|
1880
|
+
if (totalPaginas <= 1) return null;
|
|
1881
|
+
const desde = totalItems === 0 ? 0 : (paginaActual - 1) * tamano + 1;
|
|
1882
|
+
const hasta = Math.min(paginaActual * tamano, totalItems);
|
|
1883
|
+
return /* @__PURE__ */ jsxs("div", { className: "mt-3 flex flex-wrap items-center justify-between gap-3", children: [
|
|
1884
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
|
|
1885
|
+
onCambiarTamano && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
1886
|
+
/* @__PURE__ */ jsx("label", { className: "text-xs font-medium text-[#807f7f]", children: "Por p\xE1gina" }),
|
|
1887
|
+
/* @__PURE__ */ jsx(
|
|
1888
|
+
"select",
|
|
1889
|
+
{
|
|
1890
|
+
value: tamano,
|
|
1891
|
+
onChange: (e) => onCambiarTamano(Number(e.target.value)),
|
|
1892
|
+
"aria-label": "Filas por p\xE1gina",
|
|
1893
|
+
className: "rounded-md border border-[var(--tema-borde)] bg-[var(--tema-fondo)] px-2 py-1.5 text-sm focus:border-[var(--tema-primario)] focus:outline-none",
|
|
1894
|
+
children: tamanos.map((n) => /* @__PURE__ */ jsx("option", { value: n, children: n }, n))
|
|
1895
|
+
}
|
|
1896
|
+
)
|
|
1897
|
+
] }),
|
|
1898
|
+
/* @__PURE__ */ jsxs("span", { className: "text-xs text-[#807f7f]", children: [
|
|
1899
|
+
desde,
|
|
1900
|
+
"\u2013",
|
|
1901
|
+
hasta,
|
|
1902
|
+
" de ",
|
|
1903
|
+
totalItems
|
|
1904
|
+
] })
|
|
1905
|
+
] }),
|
|
1906
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
|
|
1907
|
+
/* @__PURE__ */ jsxs(
|
|
1908
|
+
"button",
|
|
1909
|
+
{
|
|
1910
|
+
type: "button",
|
|
1911
|
+
onClick: onAnterior,
|
|
1912
|
+
disabled: paginaActual <= 1,
|
|
1913
|
+
"aria-label": "P\xE1gina anterior",
|
|
1914
|
+
className: "inline-flex items-center gap-1 rounded-md border border-[var(--tema-borde)] px-3 py-1.5 text-sm font-medium text-[#3c3c3b] transition hover:bg-[var(--tema-badge-neutro)] disabled:opacity-50",
|
|
1915
|
+
children: [
|
|
1916
|
+
/* @__PURE__ */ jsx(ICONO_PAGINA_ANTERIOR, { size: TAMANO_BADGE, "aria-hidden": "true" }),
|
|
1917
|
+
"Anterior"
|
|
1918
|
+
]
|
|
1919
|
+
}
|
|
1920
|
+
),
|
|
1921
|
+
/* @__PURE__ */ jsxs("span", { className: "text-xs text-[#807f7f]", children: [
|
|
1922
|
+
paginaActual,
|
|
1923
|
+
" / ",
|
|
1924
|
+
totalPaginas
|
|
1925
|
+
] }),
|
|
1926
|
+
/* @__PURE__ */ jsxs(
|
|
1927
|
+
"button",
|
|
1928
|
+
{
|
|
1929
|
+
type: "button",
|
|
1930
|
+
onClick: onSiguiente,
|
|
1931
|
+
disabled: paginaActual >= totalPaginas,
|
|
1932
|
+
"aria-label": "P\xE1gina siguiente",
|
|
1933
|
+
className: "inline-flex items-center gap-1 rounded-md border border-[var(--tema-borde)] px-3 py-1.5 text-sm font-medium text-[#3c3c3b] transition hover:bg-[var(--tema-badge-neutro)] disabled:opacity-50",
|
|
1934
|
+
children: [
|
|
1935
|
+
"Siguiente",
|
|
1936
|
+
/* @__PURE__ */ jsx(ICONO_PAGINA_SIGUIENTE, { size: TAMANO_BADGE, "aria-hidden": "true" })
|
|
1937
|
+
]
|
|
1938
|
+
}
|
|
1939
|
+
)
|
|
1940
|
+
] })
|
|
1941
|
+
] });
|
|
1942
|
+
}
|
|
1943
|
+
function PaginadorUrl({
|
|
1944
|
+
pagina,
|
|
1945
|
+
totalPaginas,
|
|
1946
|
+
totalItems,
|
|
1947
|
+
tamano
|
|
1948
|
+
}) {
|
|
1949
|
+
const { ir, pendiente } = useNavegarListado();
|
|
1950
|
+
if (totalPaginas <= 1) return null;
|
|
1951
|
+
return /* @__PURE__ */ jsxs("div", { className: "relative", "aria-busy": pendiente || void 0, children: [
|
|
1952
|
+
/* @__PURE__ */ jsx(
|
|
1953
|
+
PaginadorLocal,
|
|
1954
|
+
{
|
|
1955
|
+
paginaActual: pagina,
|
|
1956
|
+
totalPaginas,
|
|
1957
|
+
totalItems,
|
|
1958
|
+
tamano,
|
|
1959
|
+
tamanos: TAMANOS_LISTADO,
|
|
1960
|
+
onAnterior: () => ir({ pagina: String(Math.max(1, pagina - 1)) }, { scroll: true }),
|
|
1961
|
+
onSiguiente: () => ir({ pagina: String(Math.min(totalPaginas, pagina + 1)) }, { scroll: true })
|
|
1962
|
+
}
|
|
1963
|
+
),
|
|
1964
|
+
pendiente && /* @__PURE__ */ jsxs("span", { role: "status", className: "absolute left-1/2 top-1/2 -translate-x-1/2 -translate-y-1/2 text-[var(--tema-primario)]", children: [
|
|
1965
|
+
/* @__PURE__ */ jsx(ICONO_CARGANDO, { size: 14, className: "animate-spin motion-reduce:animate-none", "aria-hidden": "true" }),
|
|
1966
|
+
/* @__PURE__ */ jsx("span", { className: "sr-only", children: "Cargando p\xE1gina..." })
|
|
1967
|
+
] })
|
|
580
1968
|
] });
|
|
581
1969
|
}
|
|
582
|
-
var
|
|
583
|
-
var
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
1970
|
+
var DEBOUNCE_MS = 300;
|
|
1971
|
+
var CAMPO = "rounded-md border border-[var(--tema-borde)] bg-[var(--tema-fondo)] px-2 py-1.5 text-sm text-[#3c3c3b] focus:border-[var(--tema-primario)] focus:outline-none";
|
|
1972
|
+
function BarraListado({
|
|
1973
|
+
filtros,
|
|
1974
|
+
totalFiltrado,
|
|
1975
|
+
total,
|
|
1976
|
+
placeholder = "Buscar...",
|
|
1977
|
+
etiquetaBusqueda = "Buscar",
|
|
1978
|
+
extra
|
|
1979
|
+
}) {
|
|
1980
|
+
const { ir, pendiente, params } = useNavegarListado();
|
|
1981
|
+
const qUrl = params.get("q") ?? "";
|
|
1982
|
+
const [texto, setTexto] = useState(qUrl);
|
|
1983
|
+
const [numeros, setNumeros] = useState(
|
|
1984
|
+
() => Object.fromEntries(filtros.filter((f) => f.tipo === "numero").map((f) => [f.clave, params.get(f.clave) ?? ""]))
|
|
1985
|
+
);
|
|
1986
|
+
const idBuscar = useId();
|
|
1987
|
+
const temporizador = useRef(null);
|
|
1988
|
+
useEffect(() => setTexto(qUrl), [qUrl]);
|
|
1989
|
+
useEffect(() => () => cancelar(), []);
|
|
1990
|
+
function cancelar() {
|
|
1991
|
+
if (temporizador.current) clearTimeout(temporizador.current);
|
|
1992
|
+
temporizador.current = null;
|
|
587
1993
|
}
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
1994
|
+
function aplicarBusqueda(valor) {
|
|
1995
|
+
cancelar();
|
|
1996
|
+
if (valor.trim() === qUrl.trim()) return;
|
|
1997
|
+
ir({ q: valor.trim() || null });
|
|
592
1998
|
}
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
if (
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
1999
|
+
function alEscribir(valor) {
|
|
2000
|
+
setTexto(valor);
|
|
2001
|
+
cancelar();
|
|
2002
|
+
temporizador.current = setTimeout(() => aplicarBusqueda(valor), DEBOUNCE_MS);
|
|
2003
|
+
}
|
|
2004
|
+
function limpiar() {
|
|
2005
|
+
setTexto("");
|
|
2006
|
+
aplicarBusqueda("");
|
|
2007
|
+
}
|
|
2008
|
+
function aplicarNumero(clave) {
|
|
2009
|
+
const valor = (numeros[clave] ?? "").trim();
|
|
2010
|
+
if (valor === (params.get(clave) ?? "")) return;
|
|
2011
|
+
ir({ [clave]: valor || null });
|
|
2012
|
+
}
|
|
2013
|
+
function alEnviar(e) {
|
|
2014
|
+
e.preventDefault();
|
|
2015
|
+
e.stopPropagation();
|
|
2016
|
+
cancelar();
|
|
2017
|
+
const cambios = {};
|
|
2018
|
+
if (texto.trim() !== qUrl.trim()) cambios.q = texto.trim() || null;
|
|
2019
|
+
for (const [clave, valor] of Object.entries(numeros)) {
|
|
2020
|
+
if (valor.trim() !== (params.get(clave) ?? "")) cambios[clave] = valor.trim() || null;
|
|
2021
|
+
}
|
|
2022
|
+
if (Object.keys(cambios).length > 0) ir(cambios);
|
|
2023
|
+
}
|
|
2024
|
+
const tamano = params.get("tamano") ?? String(TAMANO_LISTADO_DEFAULT);
|
|
2025
|
+
return /* @__PURE__ */ jsxs(
|
|
2026
|
+
"form",
|
|
613
2027
|
{
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
2028
|
+
role: "search",
|
|
2029
|
+
onSubmit: alEnviar,
|
|
2030
|
+
className: "flex flex-wrap items-end gap-x-3 gap-y-2 rounded-lg border border-[var(--tema-borde)] bg-[#f9fafb] px-3 py-2",
|
|
2031
|
+
children: [
|
|
2032
|
+
/* @__PURE__ */ jsxs("div", { className: "flex min-w-[16rem] flex-1 flex-col gap-1", children: [
|
|
2033
|
+
/* @__PURE__ */ jsx("label", { htmlFor: idBuscar, className: "text-xs font-medium text-[#565656]", children: etiquetaBusqueda }),
|
|
2034
|
+
/* @__PURE__ */ jsxs("div", { className: "relative", children: [
|
|
2035
|
+
/* @__PURE__ */ jsx(
|
|
2036
|
+
ICONO_BUSCAR,
|
|
2037
|
+
{
|
|
2038
|
+
size: 14,
|
|
2039
|
+
"aria-hidden": "true",
|
|
2040
|
+
className: "pointer-events-none absolute left-2 top-1/2 -translate-y-1/2 text-[#807f7f]"
|
|
2041
|
+
}
|
|
2042
|
+
),
|
|
2043
|
+
/* @__PURE__ */ jsx(
|
|
2044
|
+
"input",
|
|
2045
|
+
{
|
|
2046
|
+
id: idBuscar,
|
|
2047
|
+
type: "search",
|
|
2048
|
+
value: texto,
|
|
2049
|
+
onChange: (e) => alEscribir(e.target.value),
|
|
2050
|
+
onKeyDown: (e) => {
|
|
2051
|
+
if (e.key === "Escape" && texto) {
|
|
2052
|
+
e.preventDefault();
|
|
2053
|
+
limpiar();
|
|
2054
|
+
}
|
|
2055
|
+
},
|
|
2056
|
+
placeholder,
|
|
2057
|
+
autoComplete: "off",
|
|
2058
|
+
spellCheck: false,
|
|
2059
|
+
className: `${CAMPO} w-full pl-7 pr-8 [&::-webkit-search-cancel-button]:hidden`
|
|
2060
|
+
}
|
|
2061
|
+
),
|
|
2062
|
+
texto && /* @__PURE__ */ jsx(
|
|
2063
|
+
"button",
|
|
2064
|
+
{
|
|
2065
|
+
type: "button",
|
|
2066
|
+
onClick: limpiar,
|
|
2067
|
+
"aria-label": "Limpiar b\xFAsqueda",
|
|
2068
|
+
title: "Limpiar b\xFAsqueda",
|
|
2069
|
+
className: "absolute right-1 top-1/2 -translate-y-1/2 rounded p-1 text-[#807f7f] transition hover:bg-[var(--tema-badge-neutro)]",
|
|
2070
|
+
children: /* @__PURE__ */ jsx(ICONO_LIMPIAR, { size: 12, "aria-hidden": "true" })
|
|
2071
|
+
}
|
|
2072
|
+
)
|
|
2073
|
+
] })
|
|
2074
|
+
] }),
|
|
2075
|
+
filtros.length > 0 && /* @__PURE__ */ jsx(ICONO_FILTRO, { size: TAMANO_BADGE, "aria-hidden": "true", className: "mb-2 hidden text-[#807f7f] sm:block" }),
|
|
2076
|
+
filtros.map((f) => {
|
|
2077
|
+
const id = `${idBuscar}-${f.clave}`;
|
|
2078
|
+
return /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-1", children: [
|
|
2079
|
+
/* @__PURE__ */ jsx("label", { htmlFor: id, className: "text-xs font-medium text-[#565656]", children: f.etiqueta }),
|
|
2080
|
+
f.tipo === "numero" ? /* @__PURE__ */ jsx(
|
|
2081
|
+
"input",
|
|
2082
|
+
{
|
|
2083
|
+
id,
|
|
2084
|
+
type: "number",
|
|
2085
|
+
inputMode: "numeric",
|
|
2086
|
+
min: f.min,
|
|
2087
|
+
max: f.max,
|
|
2088
|
+
value: numeros[f.clave] ?? "",
|
|
2089
|
+
onChange: (e) => setNumeros((n) => ({ ...n, [f.clave]: e.target.value })),
|
|
2090
|
+
onBlur: () => aplicarNumero(f.clave),
|
|
2091
|
+
className: `${CAMPO} w-24`
|
|
2092
|
+
}
|
|
2093
|
+
) : /* @__PURE__ */ jsx(
|
|
2094
|
+
"select",
|
|
2095
|
+
{
|
|
2096
|
+
id,
|
|
2097
|
+
value: params.get(f.clave) ?? "",
|
|
2098
|
+
onChange: (e) => ir({ [f.clave]: e.target.value || null }),
|
|
2099
|
+
className: CAMPO,
|
|
2100
|
+
children: f.opciones.map((o) => /* @__PURE__ */ jsx("option", { value: o.valor, children: o.etiqueta }, o.valor))
|
|
2101
|
+
}
|
|
2102
|
+
)
|
|
2103
|
+
] }, f.clave);
|
|
2104
|
+
}),
|
|
2105
|
+
/* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-1", children: [
|
|
2106
|
+
/* @__PURE__ */ jsx("label", { htmlFor: `${idBuscar}-tamano`, className: "text-xs font-medium text-[#565656]", children: "Por p\xE1gina" }),
|
|
2107
|
+
/* @__PURE__ */ jsx(
|
|
2108
|
+
"select",
|
|
2109
|
+
{
|
|
2110
|
+
id: `${idBuscar}-tamano`,
|
|
2111
|
+
"aria-label": "Filas por p\xE1gina",
|
|
2112
|
+
value: tamano,
|
|
2113
|
+
onChange: (e) => ir({ tamano: e.target.value === String(TAMANO_LISTADO_DEFAULT) ? null : e.target.value }),
|
|
2114
|
+
className: CAMPO,
|
|
2115
|
+
children: TAMANOS_LISTADO.map((n) => /* @__PURE__ */ jsx("option", { value: n, children: n }, n))
|
|
2116
|
+
}
|
|
2117
|
+
)
|
|
2118
|
+
] }),
|
|
2119
|
+
/* @__PURE__ */ jsxs("div", { className: "ml-auto flex items-center gap-3 pb-1.5", children: [
|
|
2120
|
+
pendiente ? /* @__PURE__ */ jsxs("span", { role: "status", className: "inline-flex items-center gap-1 text-xs text-[#807f7f]", children: [
|
|
2121
|
+
/* @__PURE__ */ jsx(ICONO_CARGANDO, { size: 12, "aria-hidden": "true", className: "animate-spin text-[var(--tema-primario)] motion-reduce:animate-none" }),
|
|
2122
|
+
"Actualizando..."
|
|
2123
|
+
] }) : /* @__PURE__ */ jsxs("span", { className: "inline-flex items-center gap-1 text-xs text-[#807f7f]", "aria-live": "polite", children: [
|
|
2124
|
+
totalFiltrado === total ? `${total} en total` : `${totalFiltrado} de ${total}`,
|
|
2125
|
+
/* @__PURE__ */ jsx(InfoExplicacion, { id: "plataforma.listado_resultados" })
|
|
2126
|
+
] }),
|
|
2127
|
+
extra
|
|
2128
|
+
] })
|
|
2129
|
+
]
|
|
621
2130
|
}
|
|
622
2131
|
);
|
|
623
2132
|
}
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
()
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
2133
|
+
function EncabezadoOrdenUrl({
|
|
2134
|
+
clave,
|
|
2135
|
+
etiqueta,
|
|
2136
|
+
icono,
|
|
2137
|
+
info,
|
|
2138
|
+
ordenActual,
|
|
2139
|
+
dirActual,
|
|
2140
|
+
alineado = "left",
|
|
2141
|
+
celda
|
|
2142
|
+
}) {
|
|
2143
|
+
const { ir } = useNavegarListado();
|
|
2144
|
+
const activa = ordenActual === clave;
|
|
2145
|
+
const dir = activa ? dirActual : null;
|
|
2146
|
+
const Flecha = dir === "asc" ? ICONO_ORDENAR_ASC : dir === "desc" ? ICONO_ORDENAR_DESC : ICONO_ORDENAR_NEUTRO;
|
|
2147
|
+
const descripcion = dir === "asc" ? "ascendente" : dir === "desc" ? "descendente" : "sin ordenar";
|
|
2148
|
+
function alternar() {
|
|
2149
|
+
if (!activa) return ir({ orden: clave, dir: "asc" });
|
|
2150
|
+
if (dir === "asc") return ir({ orden: clave, dir: "desc" });
|
|
2151
|
+
return ir({ orden: null, dir: null });
|
|
2152
|
+
}
|
|
2153
|
+
return /* @__PURE__ */ jsx(
|
|
2154
|
+
"th",
|
|
2155
|
+
{
|
|
2156
|
+
...celda,
|
|
2157
|
+
scope: "col",
|
|
2158
|
+
"aria-sort": dir === "asc" ? "ascending" : dir === "desc" ? "descending" : "none",
|
|
2159
|
+
className: `whitespace-nowrap px-3 py-2 font-medium ${alineado === "right" ? "text-right" : ""}`,
|
|
2160
|
+
children: /* @__PURE__ */ jsxs("span", { className: `inline-flex items-center gap-1 ${alineado === "right" ? "justify-end" : ""}`, children: [
|
|
2161
|
+
/* @__PURE__ */ jsxs(
|
|
2162
|
+
"button",
|
|
2163
|
+
{
|
|
2164
|
+
type: "button",
|
|
2165
|
+
onClick: alternar,
|
|
2166
|
+
title: `Ordenar por ${etiqueta}`,
|
|
2167
|
+
"aria-label": `Ordenar por ${etiqueta} (orden actual: ${descripcion})`,
|
|
2168
|
+
className: `inline-flex items-center gap-1 transition hover:text-[var(--tema-primario)] ${activa ? "text-[var(--tema-primario)]" : ""}`,
|
|
2169
|
+
children: [
|
|
2170
|
+
icono,
|
|
2171
|
+
etiqueta,
|
|
2172
|
+
/* @__PURE__ */ jsx(Flecha, { size: 12, "aria-hidden": "true", className: activa ? "" : "opacity-40" })
|
|
2173
|
+
]
|
|
652
2174
|
}
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
}
|
|
656
|
-
}
|
|
657
|
-
[uploadProps, showStatusMessages, message, successMessage, errorMessage, onUploadSuccess, onUploadError, externalOnChange]
|
|
2175
|
+
),
|
|
2176
|
+
/* @__PURE__ */ jsx(InfoExplicacion, { id: info })
|
|
2177
|
+
] })
|
|
2178
|
+
}
|
|
658
2179
|
);
|
|
659
|
-
return /* @__PURE__ */ jsx(Upload.Dragger, { ...mergedProps, children: children ?? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
660
|
-
/* @__PURE__ */ jsx("p", { className: "ant-upload-drag-icon", children: /* @__PURE__ */ jsx(InboxOutlined, {}) }),
|
|
661
|
-
/* @__PURE__ */ jsx("p", { className: "ant-upload-text", children: hintText })
|
|
662
|
-
] }) });
|
|
663
2180
|
}
|
|
664
|
-
function
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
2181
|
+
function fija(lado, idx = 0, opciones) {
|
|
2182
|
+
if (lado === "der") return { "data-fija": "der" };
|
|
2183
|
+
const primaria = opciones?.primaria ?? idx === 0;
|
|
2184
|
+
return primaria ? { "data-fija": "izq", "data-fija-idx": idx, "data-fija-primaria": "" } : { "data-fija": "izq", "data-fija-idx": idx };
|
|
2185
|
+
}
|
|
2186
|
+
function col(id) {
|
|
2187
|
+
return { "data-col": id };
|
|
2188
|
+
}
|
|
2189
|
+
function CeldaIdentidad({ texto, className = "" }) {
|
|
2190
|
+
const valor = texto ?? "";
|
|
2191
|
+
return /* @__PURE__ */ jsx("span", { title: valor, className: `block max-w-[16rem] truncate ${className}`, children: valor });
|
|
2192
|
+
}
|
|
2193
|
+
var CLASE_ACCION_FILA = "inline-flex items-center gap-1 whitespace-nowrap rounded-md border border-[var(--tema-borde)] px-2.5 py-1 text-xs hover:bg-[var(--tema-badge-neutro)] disabled:opacity-50";
|
|
2194
|
+
var ANCHO_BASE = 160;
|
|
2195
|
+
function TablaConfigurable({
|
|
2196
|
+
columnas,
|
|
2197
|
+
filas,
|
|
2198
|
+
claveFila,
|
|
2199
|
+
clavePrefs,
|
|
2200
|
+
columnaFija,
|
|
2201
|
+
columnaAcciones,
|
|
2202
|
+
idsFijos = [],
|
|
2203
|
+
etiqueta = "Resultados",
|
|
2204
|
+
mensajeVacio = "Sin resultados.",
|
|
2205
|
+
ajuste,
|
|
2206
|
+
pie,
|
|
2207
|
+
barraExtra
|
|
671
2208
|
}) {
|
|
672
|
-
|
|
2209
|
+
const fijos = idsFijos.filter((id) => columnas.some((c) => c.id === id));
|
|
2210
|
+
const idsDefault = columnas.map((c) => c.id).filter((id) => !fijos.includes(id));
|
|
2211
|
+
const { idsVisibles, idsOrdenados, ocultas, anchoDe, mover, redimensionar, alternarVisible, restablecer } = useTablaPreferencias(clavePrefs, idsDefault);
|
|
2212
|
+
const porId = new Map(columnas.map((c) => [c.id, c]));
|
|
2213
|
+
const [menuAbierto, setMenuAbierto] = useState(false);
|
|
2214
|
+
const [orden, setOrden] = useState(null);
|
|
2215
|
+
const arrastrando = useRef(null);
|
|
2216
|
+
const filasOrdenadas = (() => {
|
|
2217
|
+
if (!orden) return filas;
|
|
2218
|
+
const col2 = porId.get(orden.id);
|
|
2219
|
+
if (!col2?.valorOrden) return filas;
|
|
2220
|
+
const factor = orden.dir === "asc" ? 1 : -1;
|
|
2221
|
+
return [...filas].sort((a, b) => {
|
|
2222
|
+
const va = col2.valorOrden(a);
|
|
2223
|
+
const vb = col2.valorOrden(b);
|
|
2224
|
+
if (va === void 0 || va === null || va === "") return 1;
|
|
2225
|
+
if (vb === void 0 || vb === null || vb === "") return -1;
|
|
2226
|
+
if (typeof va === "number" && typeof vb === "number") {
|
|
2227
|
+
return (va - vb) * factor;
|
|
2228
|
+
}
|
|
2229
|
+
return String(va).localeCompare(String(vb), "es") * factor;
|
|
2230
|
+
});
|
|
2231
|
+
})();
|
|
2232
|
+
function alternarOrdenColumna(id) {
|
|
2233
|
+
setOrden((prev) => {
|
|
2234
|
+
if (prev?.id !== id) return { id, dir: "asc" };
|
|
2235
|
+
if (prev.dir === "asc") return { id, dir: "desc" };
|
|
2236
|
+
return null;
|
|
2237
|
+
});
|
|
2238
|
+
}
|
|
2239
|
+
const colSpanTotal = fijos.length + idsVisibles.length + (columnaFija ? 1 : 0) + (columnaAcciones ? 1 : 0);
|
|
2240
|
+
const baseFijos = columnaFija ? 1 : 0;
|
|
2241
|
+
const atributosFijo = (i) => fija("izq", baseFijos + i, { primaria: i === 0 });
|
|
2242
|
+
const atributosCasilla = fija("izq", 0, { primaria: fijos.length === 0 });
|
|
2243
|
+
const anchoEfectivo = (id) => {
|
|
2244
|
+
const persistido = anchoDe(id);
|
|
2245
|
+
if (persistido !== void 0) return persistido;
|
|
2246
|
+
return porId.get(id)?.anchoDefault ?? ANCHO_BASE;
|
|
2247
|
+
};
|
|
2248
|
+
const ANCHO_FIJA = 44;
|
|
2249
|
+
const ANCHO_ACCIONES = 96;
|
|
2250
|
+
const anchoTabla = (columnaFija ? ANCHO_FIJA : 0) + (columnaAcciones ? ANCHO_ACCIONES : 0) + [...fijos, ...idsVisibles].reduce((suma, id) => suma + anchoEfectivo(id), 0);
|
|
2251
|
+
const contenidoEncabezado = (col2) => /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
2252
|
+
col2.ordenable ? /* @__PURE__ */ jsx(
|
|
2253
|
+
EncabezadoOrdenable,
|
|
2254
|
+
{
|
|
2255
|
+
columnaId: col2.id,
|
|
2256
|
+
contenido: col2.encabezado,
|
|
2257
|
+
etiqueta: col2.etiquetaOrden ?? (typeof col2.encabezado === "string" ? col2.encabezado : "esta columna"),
|
|
2258
|
+
orden,
|
|
2259
|
+
onAlternar: () => alternarOrdenColumna(col2.id)
|
|
2260
|
+
}
|
|
2261
|
+
) : col2.encabezado,
|
|
2262
|
+
col2.info && /* @__PURE__ */ jsx(InfoExplicacion, { id: col2.info })
|
|
2263
|
+
] });
|
|
2264
|
+
const barra = /* @__PURE__ */ jsxs("div", { className: "relative flex items-center gap-2", children: [
|
|
673
2265
|
/* @__PURE__ */ jsxs(
|
|
674
|
-
"
|
|
2266
|
+
"button",
|
|
675
2267
|
{
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
},
|
|
2268
|
+
type: "button",
|
|
2269
|
+
onClick: () => setMenuAbierto((v) => !v),
|
|
2270
|
+
title: "Mostrar u ocultar columnas",
|
|
2271
|
+
"aria-label": "Mostrar u ocultar columnas",
|
|
2272
|
+
className: "inline-flex items-center gap-1.5 rounded-md border border-[var(--tema-borde)] px-2.5 py-1.5 text-xs font-medium text-[#3c3c3b] transition hover:bg-[var(--tema-badge-neutro)]",
|
|
682
2273
|
children: [
|
|
683
|
-
/* @__PURE__ */ jsx(
|
|
684
|
-
|
|
685
|
-
{
|
|
686
|
-
style: {
|
|
687
|
-
fontSize: 20,
|
|
688
|
-
fontWeight: 700,
|
|
689
|
-
margin: 0,
|
|
690
|
-
textTransform: uppercaseTitle ? "uppercase" : void 0
|
|
691
|
-
},
|
|
692
|
-
children: title
|
|
693
|
-
}
|
|
694
|
-
),
|
|
695
|
-
extra ? /* @__PURE__ */ jsx("div", { children: extra }) : null
|
|
2274
|
+
/* @__PURE__ */ jsx(ICONO_COLUMNAS, { size: TAMANO_BADGE, "aria-hidden": "true" }),
|
|
2275
|
+
"Columnas"
|
|
696
2276
|
]
|
|
697
2277
|
}
|
|
698
2278
|
),
|
|
699
|
-
|
|
700
|
-
|
|
2279
|
+
/* @__PURE__ */ jsx(InfoExplicacion, { id: "plataforma.tabla_columnas" }),
|
|
2280
|
+
/* @__PURE__ */ jsxs(
|
|
2281
|
+
"button",
|
|
701
2282
|
{
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
2283
|
+
type: "button",
|
|
2284
|
+
onClick: restablecer,
|
|
2285
|
+
title: "Restablecer orden y tama\xF1o de columnas",
|
|
2286
|
+
"aria-label": "Restablecer columnas",
|
|
2287
|
+
className: "inline-flex items-center gap-1.5 rounded-md border border-[var(--tema-borde)] px-2.5 py-1.5 text-xs font-medium text-[#3c3c3b] transition hover:bg-[var(--tema-badge-neutro)]",
|
|
2288
|
+
children: [
|
|
2289
|
+
/* @__PURE__ */ jsx(ICONO_RESTABLECER, { size: TAMANO_BADGE, "aria-hidden": "true" }),
|
|
2290
|
+
"Restablecer"
|
|
2291
|
+
]
|
|
705
2292
|
}
|
|
706
|
-
)
|
|
2293
|
+
),
|
|
2294
|
+
menuAbierto && /* @__PURE__ */ jsxs("div", { className: "absolute left-0 top-full z-30 mt-1 w-56 rounded-md border border-[var(--tema-borde)] bg-[var(--tema-fondo)] p-2 shadow-lg", children: [
|
|
2295
|
+
/* @__PURE__ */ jsx("p", { className: "flex items-center gap-1 px-1 pb-1 text-[10px] font-semibold uppercase tracking-wide text-[#9a9a9a]", children: "Columnas visibles" }),
|
|
2296
|
+
idsOrdenados.map((id) => {
|
|
2297
|
+
const col2 = porId.get(id);
|
|
2298
|
+
if (!col2) return null;
|
|
2299
|
+
const visible = !ocultas.has(id);
|
|
2300
|
+
const Icono = visible ? ICONO_COLUMNA_VISIBLE : ICONO_COLUMNA_OCULTA;
|
|
2301
|
+
return /* @__PURE__ */ jsxs(
|
|
2302
|
+
"button",
|
|
2303
|
+
{
|
|
2304
|
+
type: "button",
|
|
2305
|
+
onClick: () => alternarVisible(id),
|
|
2306
|
+
className: "flex w-full items-center gap-2 rounded px-1.5 py-1 text-left text-sm text-[#3c3c3b] transition hover:bg-[var(--tema-badge-neutro)]",
|
|
2307
|
+
children: [
|
|
2308
|
+
/* @__PURE__ */ jsx(Icono, { size: 14, "aria-hidden": "true", className: visible ? "" : "opacity-40" }),
|
|
2309
|
+
/* @__PURE__ */ jsx("span", { className: visible ? "" : "opacity-50", children: col2.encabezadoMenu ?? col2.encabezado })
|
|
2310
|
+
]
|
|
2311
|
+
},
|
|
2312
|
+
id
|
|
2313
|
+
);
|
|
2314
|
+
})
|
|
2315
|
+
] }),
|
|
2316
|
+
barraExtra
|
|
707
2317
|
] });
|
|
2318
|
+
return /* @__PURE__ */ jsx(MarcoTabla, { clave: clavePrefs, etiqueta, barra, ajuste, pie, children: /* @__PURE__ */ jsxs(
|
|
2319
|
+
"table",
|
|
2320
|
+
{
|
|
2321
|
+
className: "table-fixed divide-y divide-[var(--tema-borde)] text-sm",
|
|
2322
|
+
style: { width: anchoTabla, minWidth: "100%" },
|
|
2323
|
+
children: [
|
|
2324
|
+
/* @__PURE__ */ jsxs("colgroup", { children: [
|
|
2325
|
+
columnaFija && /* @__PURE__ */ jsx("col", { style: { width: ANCHO_FIJA } }),
|
|
2326
|
+
fijos.map((id) => /* @__PURE__ */ jsx("col", { style: { width: anchoEfectivo(id) } }, id)),
|
|
2327
|
+
idsVisibles.map((id) => /* @__PURE__ */ jsx("col", { style: { width: anchoEfectivo(id) } }, id)),
|
|
2328
|
+
columnaAcciones && /* @__PURE__ */ jsx("col", { style: { width: ANCHO_ACCIONES } })
|
|
2329
|
+
] }),
|
|
2330
|
+
/* @__PURE__ */ jsx("thead", { children: /* @__PURE__ */ jsxs("tr", { className: "text-left text-xs font-medium text-[#807f7f]", children: [
|
|
2331
|
+
columnaFija && /* @__PURE__ */ jsx("th", { className: "px-3 py-2", ...atributosCasilla, children: columnaFija.encabezado ?? null }),
|
|
2332
|
+
fijos.map((id, i) => {
|
|
2333
|
+
const col2 = porId.get(id);
|
|
2334
|
+
return /* @__PURE__ */ jsxs("th", { className: "relative overflow-hidden px-3 py-2", ...atributosFijo(i), children: [
|
|
2335
|
+
/* @__PURE__ */ jsx("span", { className: `flex items-center gap-1 truncate ${col2.alineado === "right" ? "justify-end" : ""}`, children: contenidoEncabezado(col2) }),
|
|
2336
|
+
/* @__PURE__ */ jsx(
|
|
2337
|
+
ResizerColumna,
|
|
2338
|
+
{
|
|
2339
|
+
anchoActual: anchoEfectivo(id),
|
|
2340
|
+
onFinRedimension: (nuevoAncho) => redimensionar(id, nuevoAncho)
|
|
2341
|
+
}
|
|
2342
|
+
)
|
|
2343
|
+
] }, id);
|
|
2344
|
+
}),
|
|
2345
|
+
idsVisibles.map((id) => {
|
|
2346
|
+
const col2 = porId.get(id);
|
|
2347
|
+
if (!col2) return null;
|
|
2348
|
+
const idxOrden = idsOrdenados.indexOf(id);
|
|
2349
|
+
return /* @__PURE__ */ jsxs(
|
|
2350
|
+
"th",
|
|
2351
|
+
{
|
|
2352
|
+
className: "relative overflow-hidden px-3 py-2",
|
|
2353
|
+
onDragOver: (e) => e.preventDefault(),
|
|
2354
|
+
onDrop: () => {
|
|
2355
|
+
if (arrastrando.current !== null && arrastrando.current !== idxOrden) {
|
|
2356
|
+
mover(arrastrando.current, idxOrden);
|
|
2357
|
+
}
|
|
2358
|
+
arrastrando.current = null;
|
|
2359
|
+
},
|
|
2360
|
+
children: [
|
|
2361
|
+
/* @__PURE__ */ jsxs(
|
|
2362
|
+
"span",
|
|
2363
|
+
{
|
|
2364
|
+
className: `flex items-center gap-1 truncate ${col2.alineado === "right" ? "justify-end" : ""}`,
|
|
2365
|
+
children: [
|
|
2366
|
+
/* @__PURE__ */ jsx(
|
|
2367
|
+
"span",
|
|
2368
|
+
{
|
|
2369
|
+
draggable: true,
|
|
2370
|
+
onDragStart: () => {
|
|
2371
|
+
arrastrando.current = idxOrden;
|
|
2372
|
+
},
|
|
2373
|
+
onDragEnd: () => {
|
|
2374
|
+
arrastrando.current = null;
|
|
2375
|
+
},
|
|
2376
|
+
"aria-label": "Arrastrar para reordenar la columna",
|
|
2377
|
+
className: "shrink-0 cursor-grab text-[#c4c4c4] hover:text-[var(--tema-primario)]",
|
|
2378
|
+
children: /* @__PURE__ */ jsx(ICONO_ARRASTRAR_COLUMNA, { size: 12, "aria-hidden": "true" })
|
|
2379
|
+
}
|
|
2380
|
+
),
|
|
2381
|
+
contenidoEncabezado(col2)
|
|
2382
|
+
]
|
|
2383
|
+
}
|
|
2384
|
+
),
|
|
2385
|
+
/* @__PURE__ */ jsx(
|
|
2386
|
+
ResizerColumna,
|
|
2387
|
+
{
|
|
2388
|
+
anchoActual: anchoEfectivo(id),
|
|
2389
|
+
onFinRedimension: (nuevoAncho) => redimensionar(id, nuevoAncho)
|
|
2390
|
+
}
|
|
2391
|
+
)
|
|
2392
|
+
]
|
|
2393
|
+
},
|
|
2394
|
+
id
|
|
2395
|
+
);
|
|
2396
|
+
}),
|
|
2397
|
+
columnaAcciones && /* @__PURE__ */ jsx("th", { className: "px-3 py-2", ...fija("der"), children: columnaAcciones.encabezado ?? null })
|
|
2398
|
+
] }) }),
|
|
2399
|
+
/* @__PURE__ */ jsx("tbody", { className: "divide-y divide-[var(--tema-borde)]", children: filasOrdenadas.length === 0 ? /* @__PURE__ */ jsx("tr", { children: /* @__PURE__ */ jsx("td", { colSpan: colSpanTotal, className: "px-3 py-6 text-center text-sm text-[#807f7f]", children: mensajeVacio }) }) : filasOrdenadas.map((fila) => /* @__PURE__ */ jsxs("tr", { className: "text-[#3c3c3b]", children: [
|
|
2400
|
+
columnaFija && /* @__PURE__ */ jsx("td", { className: "px-3 py-2", ...atributosCasilla, children: columnaFija.celda(fila) }),
|
|
2401
|
+
fijos.map((id, i) => {
|
|
2402
|
+
const col2 = porId.get(id);
|
|
2403
|
+
return /* @__PURE__ */ jsx(
|
|
2404
|
+
"td",
|
|
2405
|
+
{
|
|
2406
|
+
...atributosFijo(i),
|
|
2407
|
+
className: `overflow-hidden px-3 py-2 align-top ${col2.alineado === "right" ? "text-right tabular-nums" : ""}`,
|
|
2408
|
+
children: col2.celda(fila)
|
|
2409
|
+
},
|
|
2410
|
+
id
|
|
2411
|
+
);
|
|
2412
|
+
}),
|
|
2413
|
+
idsVisibles.map((id) => {
|
|
2414
|
+
const col2 = porId.get(id);
|
|
2415
|
+
if (!col2) return null;
|
|
2416
|
+
return /* @__PURE__ */ jsx(
|
|
2417
|
+
"td",
|
|
2418
|
+
{
|
|
2419
|
+
className: `overflow-hidden px-3 py-2 align-top ${col2.alineado === "right" ? "text-right tabular-nums" : ""}`,
|
|
2420
|
+
children: col2.celda(fila)
|
|
2421
|
+
},
|
|
2422
|
+
id
|
|
2423
|
+
);
|
|
2424
|
+
}),
|
|
2425
|
+
columnaAcciones && /* @__PURE__ */ jsx("td", { className: "px-3 py-2", ...fija("der"), children: columnaAcciones.celda(fila) })
|
|
2426
|
+
] }, claveFila(fila))) })
|
|
2427
|
+
]
|
|
2428
|
+
}
|
|
2429
|
+
) });
|
|
708
2430
|
}
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
2431
|
+
function EncabezadoOrdenable({
|
|
2432
|
+
columnaId,
|
|
2433
|
+
contenido,
|
|
2434
|
+
etiqueta,
|
|
2435
|
+
orden,
|
|
2436
|
+
onAlternar
|
|
2437
|
+
}) {
|
|
2438
|
+
const activa = orden?.id === columnaId;
|
|
2439
|
+
const dir = activa ? orden.dir : null;
|
|
2440
|
+
const Flecha = dir === "asc" ? ICONO_ORDENAR_ASC : dir === "desc" ? ICONO_ORDENAR_DESC : ICONO_ORDENAR_NEUTRO;
|
|
2441
|
+
const descripcionDir = dir === "asc" ? "ascendente" : dir === "desc" ? "descendente" : "sin ordenar";
|
|
2442
|
+
return /* @__PURE__ */ jsxs(
|
|
2443
|
+
"button",
|
|
2444
|
+
{
|
|
2445
|
+
type: "button",
|
|
2446
|
+
onClick: onAlternar,
|
|
2447
|
+
title: "Ordena solo la pagina visible (no todo el universo)",
|
|
2448
|
+
"aria-label": `Ordenar por ${etiqueta} en esta pagina (orden actual: ${descripcionDir})`,
|
|
2449
|
+
className: `inline-flex items-center gap-1 truncate font-medium transition hover:text-[var(--tema-primario)] ${activa ? "text-[var(--tema-primario)]" : ""}`,
|
|
2450
|
+
children: [
|
|
2451
|
+
contenido,
|
|
2452
|
+
/* @__PURE__ */ jsx(Flecha, { size: 12, "aria-hidden": "true", className: activa ? "" : "opacity-40" })
|
|
2453
|
+
]
|
|
2454
|
+
}
|
|
2455
|
+
);
|
|
2456
|
+
}
|
|
2457
|
+
function ResizerColumna({
|
|
2458
|
+
anchoActual,
|
|
2459
|
+
onFinRedimension
|
|
718
2460
|
}) {
|
|
2461
|
+
function onMouseDown(e) {
|
|
2462
|
+
e.preventDefault();
|
|
2463
|
+
e.stopPropagation();
|
|
2464
|
+
const inicioX = e.clientX;
|
|
2465
|
+
const inicioAncho = anchoActual;
|
|
2466
|
+
let ultimoAncho = anchoActual;
|
|
2467
|
+
function onMove(ev) {
|
|
2468
|
+
ultimoAncho = Math.max(60, inicioAncho + (ev.clientX - inicioX));
|
|
2469
|
+
onFinRedimension(ultimoAncho);
|
|
2470
|
+
}
|
|
2471
|
+
function onUp() {
|
|
2472
|
+
onFinRedimension(ultimoAncho);
|
|
2473
|
+
window.removeEventListener("mousemove", onMove);
|
|
2474
|
+
window.removeEventListener("mouseup", onUp);
|
|
2475
|
+
document.body.style.cursor = "";
|
|
2476
|
+
document.body.style.userSelect = "";
|
|
2477
|
+
}
|
|
2478
|
+
document.body.style.cursor = "col-resize";
|
|
2479
|
+
document.body.style.userSelect = "none";
|
|
2480
|
+
window.addEventListener("mousemove", onMove);
|
|
2481
|
+
window.addEventListener("mouseup", onUp);
|
|
2482
|
+
}
|
|
719
2483
|
return /* @__PURE__ */ jsx(
|
|
720
|
-
|
|
2484
|
+
"span",
|
|
721
2485
|
{
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
2486
|
+
role: "separator",
|
|
2487
|
+
"aria-label": "Redimensionar columna",
|
|
2488
|
+
"aria-orientation": "vertical",
|
|
2489
|
+
onMouseDown,
|
|
2490
|
+
draggable: false,
|
|
2491
|
+
onDragStart: (e) => e.preventDefault(),
|
|
2492
|
+
className: "absolute right-0 top-0 z-10 h-full w-2 cursor-col-resize select-none border-r-2 border-transparent hover:border-[var(--tema-primario)]"
|
|
725
2493
|
}
|
|
726
2494
|
);
|
|
727
2495
|
}
|
|
2496
|
+
function EtiquetaCol({
|
|
2497
|
+
icono: Icono,
|
|
2498
|
+
texto,
|
|
2499
|
+
info
|
|
2500
|
+
}) {
|
|
2501
|
+
return /* @__PURE__ */ jsxs("span", { className: "inline-flex items-center gap-1", children: [
|
|
2502
|
+
Icono && /* @__PURE__ */ jsx(Icono, { size: TAMANO_BADGE, "aria-hidden": "true" }),
|
|
2503
|
+
texto,
|
|
2504
|
+
info && /* @__PURE__ */ jsx(InfoExplicacion, { id: info })
|
|
2505
|
+
] });
|
|
2506
|
+
}
|
|
2507
|
+
function Campo({
|
|
2508
|
+
id,
|
|
2509
|
+
name,
|
|
2510
|
+
etiqueta,
|
|
2511
|
+
defaultValue,
|
|
2512
|
+
tipo = "text",
|
|
2513
|
+
icono: Icono
|
|
2514
|
+
}) {
|
|
2515
|
+
return /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-1", children: [
|
|
2516
|
+
/* @__PURE__ */ jsxs("label", { htmlFor: id, className: "inline-flex items-center gap-1 text-xs font-medium text-[#3c3c3b]", children: [
|
|
2517
|
+
Icono ? /* @__PURE__ */ jsx(Icono, { size: TAMANO_BADGE, "aria-hidden": "true" }) : null,
|
|
2518
|
+
etiqueta
|
|
2519
|
+
] }),
|
|
2520
|
+
/* @__PURE__ */ jsx(
|
|
2521
|
+
"input",
|
|
2522
|
+
{
|
|
2523
|
+
id,
|
|
2524
|
+
name,
|
|
2525
|
+
type: tipo,
|
|
2526
|
+
defaultValue,
|
|
2527
|
+
className: "w-full rounded-md border border-[var(--tema-borde)] px-2 py-1.5 text-sm focus:border-[var(--tema-primario)] focus:outline-none"
|
|
2528
|
+
}
|
|
2529
|
+
)
|
|
2530
|
+
] });
|
|
2531
|
+
}
|
|
2532
|
+
function CampoSelect({
|
|
2533
|
+
id,
|
|
2534
|
+
name,
|
|
2535
|
+
etiqueta,
|
|
2536
|
+
defaultValue,
|
|
2537
|
+
opciones,
|
|
2538
|
+
icono: Icono
|
|
2539
|
+
}) {
|
|
2540
|
+
return /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-1", children: [
|
|
2541
|
+
/* @__PURE__ */ jsxs("label", { htmlFor: id, className: "inline-flex items-center gap-1 text-xs font-medium text-[#3c3c3b]", children: [
|
|
2542
|
+
Icono ? /* @__PURE__ */ jsx(Icono, { size: TAMANO_BADGE, "aria-hidden": "true" }) : null,
|
|
2543
|
+
etiqueta
|
|
2544
|
+
] }),
|
|
2545
|
+
/* @__PURE__ */ jsx(
|
|
2546
|
+
"select",
|
|
2547
|
+
{
|
|
2548
|
+
id,
|
|
2549
|
+
name,
|
|
2550
|
+
defaultValue,
|
|
2551
|
+
className: "w-full rounded-md border border-[var(--tema-borde)] bg-[var(--tema-fondo)] px-2 py-1.5 text-sm focus:border-[var(--tema-primario)] focus:outline-none",
|
|
2552
|
+
children: opciones.map((o) => /* @__PURE__ */ jsx("option", { value: o.valor, children: o.etiqueta }, o.valor))
|
|
2553
|
+
}
|
|
2554
|
+
)
|
|
2555
|
+
] });
|
|
2556
|
+
}
|
|
2557
|
+
function IconoConEtiqueta({ Icono, texto, info }) {
|
|
2558
|
+
return /* @__PURE__ */ jsxs("span", { className: "inline-flex items-center gap-1", children: [
|
|
2559
|
+
/* @__PURE__ */ jsx(Icono, { size: 16, "aria-hidden": "true" }),
|
|
2560
|
+
texto,
|
|
2561
|
+
info && /* @__PURE__ */ jsx(InfoExplicacion, { id: info })
|
|
2562
|
+
] });
|
|
2563
|
+
}
|
|
2564
|
+
function MetricaKpi({
|
|
2565
|
+
etiqueta,
|
|
2566
|
+
valor,
|
|
2567
|
+
icono: Icono,
|
|
2568
|
+
destacada = false,
|
|
2569
|
+
sub,
|
|
2570
|
+
progreso,
|
|
2571
|
+
info
|
|
2572
|
+
}) {
|
|
2573
|
+
const claseTarjeta = destacada ? "rounded-lg border-2 border-[var(--tema-primario)] bg-[var(--tema-badge-neutro)] px-4 py-3" : "rounded-lg border border-[var(--tema-borde)] px-4 py-3";
|
|
2574
|
+
const claseEtiqueta = destacada ? "flex items-center gap-1 text-xs font-medium text-[var(--tema-primario)]" : "flex items-center gap-1 text-xs text-[#807f7f]";
|
|
2575
|
+
const claseValor = destacada ? "mt-1 text-2xl font-bold text-[var(--tema-primario-oscuro)]" : "mt-1 text-lg font-semibold text-[var(--tema-primario-oscuro)]";
|
|
2576
|
+
return /* @__PURE__ */ jsxs("div", { className: claseTarjeta, children: [
|
|
2577
|
+
/* @__PURE__ */ jsxs("p", { className: claseEtiqueta, children: [
|
|
2578
|
+
/* @__PURE__ */ jsx(Icono, { size: 12, "aria-hidden": "true" }),
|
|
2579
|
+
etiqueta,
|
|
2580
|
+
info && /* @__PURE__ */ jsx(InfoExplicacion, { id: info })
|
|
2581
|
+
] }),
|
|
2582
|
+
/* @__PURE__ */ jsx("p", { className: claseValor, children: valor }),
|
|
2583
|
+
sub ? /* @__PURE__ */ jsx("p", { className: "mt-0.5 text-xs text-[#807f7f]", children: sub }) : null,
|
|
2584
|
+
progreso ? /* @__PURE__ */ jsx(
|
|
2585
|
+
"div",
|
|
2586
|
+
{
|
|
2587
|
+
role: "progressbar",
|
|
2588
|
+
"aria-label": progreso.etiqueta,
|
|
2589
|
+
"aria-valuemin": 0,
|
|
2590
|
+
"aria-valuemax": 100,
|
|
2591
|
+
"aria-valuenow": progreso.porcentaje,
|
|
2592
|
+
className: "mt-2 h-1.5 w-full overflow-hidden rounded-full bg-[var(--tema-borde)]",
|
|
2593
|
+
children: /* @__PURE__ */ jsx(
|
|
2594
|
+
"div",
|
|
2595
|
+
{
|
|
2596
|
+
className: "h-full rounded-full bg-[var(--tema-primario)] transition-all",
|
|
2597
|
+
style: { width: `${progreso.porcentaje}%` }
|
|
2598
|
+
}
|
|
2599
|
+
)
|
|
2600
|
+
}
|
|
2601
|
+
) : null
|
|
2602
|
+
] });
|
|
2603
|
+
}
|
|
2604
|
+
function GrupoMetricas({ titulo, icono: Icono, children }) {
|
|
2605
|
+
return /* @__PURE__ */ jsxs("section", { className: "mt-4", children: [
|
|
2606
|
+
/* @__PURE__ */ jsxs("h3", { className: "flex items-center gap-1.5 text-xs font-semibold uppercase tracking-wide text-[#807f7f]", children: [
|
|
2607
|
+
/* @__PURE__ */ jsx(Icono, { size: 13, "aria-hidden": "true" }),
|
|
2608
|
+
titulo
|
|
2609
|
+
] }),
|
|
2610
|
+
/* @__PURE__ */ jsx("div", { className: "mt-2 grid grid-cols-2 gap-3 sm:grid-cols-4", children })
|
|
2611
|
+
] });
|
|
2612
|
+
}
|
|
2613
|
+
function RejillaMetricas({ children }) {
|
|
2614
|
+
return /* @__PURE__ */ jsx("div", { className: "grid gap-3 sm:grid-cols-2 lg:grid-cols-4", children });
|
|
2615
|
+
}
|
|
2616
|
+
function Rotulo({ texto, info }) {
|
|
2617
|
+
return /* @__PURE__ */ jsxs("p", { className: "flex items-center gap-1 text-xs font-medium text-[#565656]", children: [
|
|
2618
|
+
/* @__PURE__ */ jsx("span", { children: texto }),
|
|
2619
|
+
/* @__PURE__ */ jsx(InfoExplicacion, { id: info })
|
|
2620
|
+
] });
|
|
2621
|
+
}
|
|
2622
|
+
function AccionesFila({
|
|
2623
|
+
etiqueta = "M\xE1s acciones",
|
|
2624
|
+
children
|
|
2625
|
+
}) {
|
|
2626
|
+
const acciones = Children.toArray(children).filter(
|
|
2627
|
+
(c) => isValidElement(c) || typeof c === "string" && c.trim() !== ""
|
|
2628
|
+
);
|
|
2629
|
+
const [abierto, setAbierto] = useState(false);
|
|
2630
|
+
const [pos, setPos] = useState({
|
|
2631
|
+
top: 0,
|
|
2632
|
+
right: 0
|
|
2633
|
+
});
|
|
2634
|
+
const boton = useRef(null);
|
|
2635
|
+
const menu = useRef(null);
|
|
2636
|
+
useEffect(() => {
|
|
2637
|
+
if (!abierto) return;
|
|
2638
|
+
const tecla = (e) => {
|
|
2639
|
+
if (e.key === "Escape") {
|
|
2640
|
+
setAbierto(false);
|
|
2641
|
+
boton.current?.focus();
|
|
2642
|
+
}
|
|
2643
|
+
};
|
|
2644
|
+
const fuera = (e) => {
|
|
2645
|
+
const t = e.target;
|
|
2646
|
+
if (!menu.current?.contains(t) && !boton.current?.contains(t))
|
|
2647
|
+
setAbierto(false);
|
|
2648
|
+
};
|
|
2649
|
+
const desplazar = (e) => {
|
|
2650
|
+
if (menu.current?.contains(e.target) || hayDialogo()) return;
|
|
2651
|
+
setAbierto(false);
|
|
2652
|
+
};
|
|
2653
|
+
document.addEventListener("keydown", tecla);
|
|
2654
|
+
document.addEventListener("mousedown", fuera);
|
|
2655
|
+
window.addEventListener("scroll", desplazar, true);
|
|
2656
|
+
return () => {
|
|
2657
|
+
document.removeEventListener("keydown", tecla);
|
|
2658
|
+
document.removeEventListener("mousedown", fuera);
|
|
2659
|
+
window.removeEventListener("scroll", desplazar, true);
|
|
2660
|
+
};
|
|
2661
|
+
}, [abierto]);
|
|
2662
|
+
function hayDialogo() {
|
|
2663
|
+
return Boolean(menu.current?.querySelector('[aria-modal="true"]'));
|
|
2664
|
+
}
|
|
2665
|
+
if (acciones.length <= 2) {
|
|
2666
|
+
return /* @__PURE__ */ jsx("div", { className: "flex items-center justify-end gap-1 whitespace-nowrap", children: acciones });
|
|
2667
|
+
}
|
|
2668
|
+
function alternar() {
|
|
2669
|
+
const r = boton.current?.getBoundingClientRect();
|
|
2670
|
+
if (r)
|
|
2671
|
+
setPos({
|
|
2672
|
+
top: r.bottom + 4,
|
|
2673
|
+
right: Math.max(8, window.innerWidth - r.right)
|
|
2674
|
+
});
|
|
2675
|
+
setAbierto((v) => !v);
|
|
2676
|
+
}
|
|
2677
|
+
return /* @__PURE__ */ jsxs("div", { className: "flex justify-end", children: [
|
|
2678
|
+
/* @__PURE__ */ jsx(
|
|
2679
|
+
"button",
|
|
2680
|
+
{
|
|
2681
|
+
ref: boton,
|
|
2682
|
+
type: "button",
|
|
2683
|
+
onClick: alternar,
|
|
2684
|
+
"aria-label": etiqueta,
|
|
2685
|
+
title: etiqueta,
|
|
2686
|
+
"aria-haspopup": "menu",
|
|
2687
|
+
"aria-expanded": abierto,
|
|
2688
|
+
className: "inline-flex items-center rounded-md border border-[var(--tema-borde)] p-1 text-[#565656] transition hover:bg-[var(--tema-badge-neutro)] hover:text-[var(--tema-primario)]",
|
|
2689
|
+
children: /* @__PURE__ */ jsx(ICONO_ACCIONES_FILA, { size: TAMANO_BADGE, "aria-hidden": "true" })
|
|
2690
|
+
}
|
|
2691
|
+
),
|
|
2692
|
+
abierto && createPortal(
|
|
2693
|
+
/* @__PURE__ */ jsx(
|
|
2694
|
+
"div",
|
|
2695
|
+
{
|
|
2696
|
+
ref: menu,
|
|
2697
|
+
role: "menu",
|
|
2698
|
+
"aria-label": etiqueta,
|
|
2699
|
+
style: { top: pos.top, right: pos.right },
|
|
2700
|
+
onClickCapture: () => setTimeout(() => {
|
|
2701
|
+
if (!hayDialogo()) setAbierto(false);
|
|
2702
|
+
}, 0),
|
|
2703
|
+
className: "fixed z-50 flex min-w-40 flex-col items-stretch gap-1 rounded-md border border-[var(--tema-borde)] bg-[var(--tema-fondo)] p-1.5 text-left shadow-lg [&>*]:justify-start",
|
|
2704
|
+
children: acciones
|
|
2705
|
+
}
|
|
2706
|
+
),
|
|
2707
|
+
document.body
|
|
2708
|
+
)
|
|
2709
|
+
] });
|
|
2710
|
+
}
|
|
2711
|
+
function BotonAccionFila({
|
|
2712
|
+
icono: Icono,
|
|
2713
|
+
etiqueta,
|
|
2714
|
+
ariaLabel,
|
|
2715
|
+
onClick,
|
|
2716
|
+
disabled = false,
|
|
2717
|
+
info
|
|
2718
|
+
}) {
|
|
2719
|
+
return /* @__PURE__ */ jsxs("span", { className: "inline-flex items-center gap-1", children: [
|
|
2720
|
+
/* @__PURE__ */ jsxs("button", { type: "button", onClick, disabled, "aria-label": ariaLabel, className: CLASE_ACCION_FILA, children: [
|
|
2721
|
+
/* @__PURE__ */ jsx(Icono, { size: 12, "aria-hidden": "true" }),
|
|
2722
|
+
etiqueta
|
|
2723
|
+
] }),
|
|
2724
|
+
info && /* @__PURE__ */ jsx(InfoExplicacion, { id: info })
|
|
2725
|
+
] });
|
|
2726
|
+
}
|
|
728
2727
|
|
|
729
|
-
export {
|
|
2728
|
+
export { AccionConDialogo, AccionesFila, Aviso, AvisoAccionEstado, BarraListado, BarraProgreso, BotonAccionAviso, BotonAccionFila, CLASE_ACCION_FILA, CLASE_AYUDA_CAMPO, CLASE_BOTON_CONTORNO, CLASE_BOTON_ICONO, CLASE_BOTON_PELIGRO, CLASE_BOTON_PEQUENO, CLASE_BOTON_PRIMARIO, CLASE_BOTON_PRIMARIO_COMPACTO, CLASE_BOTON_SECUNDARIO, CLASE_CAMPO, CLASE_CAMPO_COMPACTO, CLASE_ERROR_CAMPO, CLASE_ETIQUETA_CAMPO, CLASE_EXITO_CAMPO, CLASE_REGION_LISTADO, CLASE_TARJETA, CLASE_TEXTO_ATENUADO, CLASE_TITULO_PAGINA, CLASE_TITULO_SECCION, Campo, CampoSelect, CascaronApp, CeldaIdentidad, ETIQUETAS_SEMAFORO, EXPLICACIONES, EncabezadoOrdenUrl, EnlaceNav, EstadoVacio, EstadoVacioFila, EtiquetaCol, FechaHoraLocal, GrupoMetricas, ICONOS_ESTATUS, ICONOS_SEMAFORO, ICONO_ACCIONES_FILA, ICONO_ALTA, ICONO_API_KEY, ICONO_ARRASTRAR_COLUMNA, ICONO_AVISO, ICONO_BAJA, ICONO_BUSCAR, ICONO_CAMPANA, ICONO_CARGANDO, ICONO_CERRAR, ICONO_CERRAR_SESION, ICONO_COLUMNAS, ICONO_COLUMNA_OCULTA, ICONO_COLUMNA_VISIBLE, ICONO_COL_CODIGO, ICONO_COL_DOCUMENTO, ICONO_COL_ESTADO, ICONO_COL_ETIQUETA, ICONO_COL_FECHA, ICONO_COL_FECHA_HORA, ICONO_COL_MECANISMO, ICONO_COL_NOMBRE, ICONO_COL_TOTAL, ICONO_COL_USUARIO, ICONO_CONFIRMAR, ICONO_COPIAR, ICONO_DEFAULT, ICONO_DENSIDAD_COMODA, ICONO_DENSIDAD_COMPACTA, ICONO_DESCARGAR, ICONO_DESHABILITAR, ICONO_DURACION, ICONO_EDITAR, ICONO_EMAIL, ICONO_ERROR, ICONO_EXPORTAR, ICONO_EXPORTAR_CSV, ICONO_FILTRO, ICONO_GENERAR, ICONO_GUARDAR, ICONO_INACTIVAR, ICONO_INFO_EXPLICACION, ICONO_INICIAR_SESION, ICONO_INVITACION_GENERICA, ICONO_KPI_ALERTA, ICONO_KPI_BLOQUEO, ICONO_KPI_CONSUMO, ICONO_KPI_CONTEO, ICONO_KPI_CREDENCIALES, ICONO_KPI_RENDIMIENTO, ICONO_KPI_RITMO, ICONO_LIMPIAR, ICONO_LINK, ICONO_LOGIN_MICROSOFT, ICONO_NAV_ACCESOS, ICONO_NAV_ANALITICA, ICONO_NAV_API_KEYS, ICONO_NAV_BITACORA, ICONO_NAV_CLIENTE, ICONO_NAV_COLAPSAR, ICONO_NAV_CONFIGURACION, ICONO_NAV_DASHBOARD, ICONO_NAV_ENTIDADES, ICONO_NAV_ETIQUETAS, ICONO_NAV_EXPANDIR, ICONO_NAV_EXTRACCIONES, ICONO_NAV_INVITACIONES, ICONO_NAV_JOBS, ICONO_NAV_MANUAL, ICONO_NAV_MENU_MOVIL, ICONO_NAV_NOTIFICACIONES, ICONO_NAV_PAQUETES, ICONO_NAV_PLANES, ICONO_NAV_SALUD, ICONO_NAV_TEMA, ICONO_NAV_USUARIOS, ICONO_OK, ICONO_ORDENAR_ASC, ICONO_ORDENAR_DESC, ICONO_ORDENAR_NEUTRO, ICONO_PAGINA_ANTERIOR, ICONO_PAGINA_SIGUIENTE, ICONO_PERIODO, ICONO_REACTIVAR, ICONO_REACTIVAR_ETIQUETA, ICONO_REINTENTAR, ICONO_RESTABLECER, ICONO_REVOCAR_KEY, ICONO_ROTAR_KEY, ICONO_SEGURIDAD, ICONO_SELECCIONADO, ICONO_SILENCIAR, ICONO_UBICACION, ICONO_VER_TODOS, ICONO_VIGENCIA, ICONO_VISTA_TABLA, ICONO_VISTA_TARJETAS, ICONO_VOLVER, IconoConEtiqueta, InfoExplicacion, Insignia, LinkBase, LinkComponentProvider, ListadoNavProvider, MarcoTabla, Metrica, MetricaKpi, Migas, ModalPanel, NOMBRE_PRODUCTO_DEFAULT, NO_DISPONIBLE, NoDisponible, OverlayCargando, PaginaContenido, PaginaListado, PaginadorLocal, PaginadorUrl, PantallaAcceso, PantallaCargando, Pestanas, PopoverHover, RejillaMetricas, Rotulo, SeccionNav, SidebarColapsable, SpinnerMarca, SubNav, TAMANOS_LISTADO, TAMANO_BADGE, TAMANO_BOTON, TAMANO_LISTADO_DEFAULT, TEMA_DEFAULT, TablaConfigurable, TablaPlana, Tarjeta, ThInfo, UsuarioTablas, aplicarListado, calcularPosicionPopover, col, etiquetaSemaforo, explicacionDe, fija, formatearBytes, formatearFechaHora, formatearFechaHoraCDMX, formatearRangoFechaHora, formatoDias, formatoEntero, formatoFecha, formatoMes, formatoMxn, formatoNumero, formatoPct, hrefListado, iconoDeEstatus, iconoDeSemaforo, leerListado, normalizarTexto, useAccionAviso, useAccionConSpinner, useNavegarListado, usePaginacionLocal, useTablaPreferencias, variablesDeTema, verificarCatalogo };
|
|
730
2729
|
//# sourceMappingURL=index.js.map
|
|
731
2730
|
//# sourceMappingURL=index.js.map
|