@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/dist/index.d.cts CHANGED
@@ -1,528 +1,1392 @@
1
1
  import * as react from 'react';
2
- import { PropsWithChildren, ReactNode, ForwardRefExoticComponent } from 'react';
3
- import { Locale } from 'antd/es/locale';
4
- import { ThemeConfig, ButtonProps as ButtonProps$1, TagProps as TagProps$1, PaginationProps as PaginationProps$1, CardProps, Card as Card$1, SwitchProps, TableProps, ModalProps, SelectProps, UploadProps } from 'antd';
5
- export { Affix, AffixProps, Alert, AlertProps, Anchor, AnchorProps, AutoComplete, AutoCompleteProps, Avatar, AvatarProps, BackTop, BackTopProps, Badge, BadgeProps, Breadcrumb, BreadcrumbProps, Calendar, CardProps, Carousel, CarouselProps, Cascader, CascaderProps, Checkbox, CheckboxProps, Col, ColProps, Collapse, CollapseProps, ColorPicker, ColorPickerProps, DatePicker, DatePickerProps, Descriptions, DescriptionsProps, Divider, DividerProps, Drawer, DrawerProps, Dropdown, DropdownProps, Empty, EmptyProps, Flex, FlexProps, FloatButton, FloatButtonProps, Form, FormInstance, FormItemProps, FormListFieldData, FormListOperation, FormProps, FormRule, Image, ImageProps, Input, InputNumber, InputNumberProps, Layout, LayoutProps, List, ListProps, MentionProps, Mentions, Menu, MenuProps, MessageArgsProps, Modal, ModalFuncProps, ModalProps, NotificationArgsProps, Popconfirm, PopconfirmProps, Popover, PopoverProps, Progress, ProgressProps, QRCode, QRCodeProps, Radio, RadioProps, Rate, RateProps, Result, ResultProps, Row, RowProps, Segmented, SegmentedProps, Select, SelectProps, Skeleton, SkeletonProps, Slider, SliderSingleProps, Space, SpaceProps, Spin, SpinProps, Splitter, SplitterProps, Statistic, StatisticProps, Steps, StepsProps, Switch, SwitchProps, Table, TableColumnType, TableColumnsType, TableProps, Tabs, TabsProps, TimePicker, TimePickerProps, Timeline, TimelineProps, Tooltip, TooltipProps, Tour, TourProps, Transfer, Tree, TreeSelect, TreeSelectProps, Typography, Upload, Watermark, WatermarkProps } from 'antd';
6
- export { TitleProps } from 'antd/es/typography/Title';
7
- export { TextProps } from 'antd/es/typography/Text';
8
- export { ParagraphProps } from 'antd/es/typography/Paragraph';
9
- export { LinkProps } from 'antd/es/typography/Link';
10
- import { AntdIconProps } from '@ant-design/icons/lib/components/AntdIcon';
11
- export { GroupProps as InputGroupProps, InputProps, InputRef, PasswordProps, SearchProps, TextAreaProps } from 'antd/es/input';
12
- export { DraggerProps, RcFile, UploadChangeParam, UploadFile, UploadListProps, UploadProps } from 'antd/es/upload';
13
- import { MessageInstance } from 'antd/es/message/interface';
14
- export { MessageInstance } from 'antd/es/message/interface';
15
- import { NotificationInstance } from 'antd/es/notification/interface';
16
- export { NotificationInstance } from 'antd/es/notification/interface';
17
- export { CheckCircleOutlined, CheckOutlined, CloseCircleOutlined, CloseOutlined, DeleteOutlined, DownOutlined, DownloadOutlined, EditOutlined, ExclamationCircleOutlined, EyeInvisibleOutlined, EyeOutlined, FileExcelOutlined, FileOutlined, FilePdfOutlined, FilterOutlined, FolderOutlined, InfoCircleOutlined, LeftOutlined, LoadingOutlined, LogoutOutlined, MenuOutlined, PlusOutlined, ReloadOutlined, RightOutlined, SearchOutlined, SettingOutlined, UpOutlined, UploadOutlined, UserOutlined, WarningOutlined } from '@ant-design/icons';
18
-
19
- /**
20
- * Design tokens — the single source of truth for the AMS Design System.
21
- *
22
- * Values are taken from the B2BMX Metronic theme:
23
- * b2bmx-web-metronic/src/_metronic/assets/sass/components/_variables.custom.scss
24
- * b2bmx-web-metronic/tailwind.config.js
25
- *
26
- * Two tiers:
27
- * - `primitives`: raw values, no semantic meaning.
28
- * - `semantic`: role aliases consumed by the antd theme (and Tailwind).
29
- */
30
- /** Raw Metronic brand values. */
31
- declare const primitives: {
32
- readonly brandRed: "#A72432";
33
- readonly brandRedActive: "#8B1D28";
34
- readonly brandRedLight: "#f1faff";
35
- readonly green: "#50cd89";
36
- readonly greenActive: "#47be7d";
37
- readonly greenLight: "#e8fff3";
38
- readonly purple: "#7239ea";
39
- readonly purpleActive: "#5014d0";
40
- readonly purpleLight: "#f8f5ff";
41
- readonly pink: "#f1416c";
42
- readonly pinkActive: "#d9214e";
43
- readonly pinkLight: "#fff5f8";
44
- readonly yellow: "#ffc700";
45
- readonly yellowActive: "#f1bc00";
46
- readonly yellowLight: "#fff8dd";
47
- readonly white: "#ffffff";
48
- readonly gray: {
49
- readonly 100: "#f9f9f9";
50
- readonly 200: "#f4f4f4";
51
- readonly 300: "#e1e3ea";
52
- readonly 400: "#b5b5c3";
53
- readonly 500: "#a1a5b7";
54
- readonly 600: "#7e8299";
55
- readonly 700: "#5e6278";
56
- readonly 800: "#3f4254";
57
- readonly 900: "#181c32";
2
+ import { CSSProperties, ReactNode, AnchorHTMLAttributes, ComponentType } from 'react';
3
+ import { LucideIcon } from 'lucide-react';
4
+
5
+ /**
6
+ * Tema (paleta + marca) por omision. Basado en `web/src/lib/tema.ts` de la plataforma SIN la llamada a su backend:
7
+ * se conservan los NOMBRES de los tokens (`color_primario`, `badge_exito`...). Los valores por omision son la MARCA
8
+ * AMS (rojo), que coinciden con el `:root` de `tokens.css` (deben mantenerse sincronizados). `variablesDeTema` es la
9
+ * funcion de `app/layout.tsx` que inyecta la paleta como variables CSS en `<html style=...>`.
10
+ *
11
+ * Como una marca sobreescribe los tokens (3 formas, de mas a menos recomendada):
12
+ * 1. Runtime: construye un `Tema` propio (de tu API/config) y pasa `variablesDeTema(tema)` al `style` de `<html>`.
13
+ * 2. Estatica: un CSS de marca importado despues de globals.css con `:root { --tema-primario: #...; ... }`.
14
+ * 3. Cambiar `TEMA_DEFAULT` y `:root` de globals.css a la vez (deben coincidir).
15
+ * Nunca cambies colores dentro de un componente.
16
+ */
17
+
18
+ type Tema = {
19
+ logo_url: string | null;
20
+ /** Icono de pestana (ruta o URL); sin valor rige el de la marca por omision. */
21
+ favicon_url?: string | null;
22
+ color_primario: string;
23
+ color_primario_oscuro: string;
24
+ /** Acento de marca (reflejo de la pantalla de acceso, spinner); sin valor rige el del tema por omision. */
25
+ color_acento?: string;
26
+ /**
27
+ * Rojo de PELIGRO (acciones destructivas y texto de error). Reservado: cuando la marca es roja, el boton
28
+ * primario va en neutro oscuro y este rojo queda solo para destructivos/error (ver docs/criterio-color-acciones.md).
29
+ */
30
+ color_peligro: string;
31
+ color_fondo: string;
32
+ color_texto: string;
33
+ color_borde: string;
34
+ badge_exito: string;
35
+ badge_advertencia: string;
36
+ badge_error: string;
37
+ badge_neutro: string;
38
+ };
39
+ declare const NOMBRE_PRODUCTO_DEFAULT = "Backoffice";
40
+ /**
41
+ * Tema por omision = marca AMS (rojo). Mismos valores que el `:root` de `tokens.css` (deben coincidir).
42
+ * El rojo es la identidad/acento; el boton primario va en neutro oscuro y el rojo queda reservado a peligro
43
+ * (ver docs/criterio-color-acciones.md). Una marca distinta sobreescribe estos tokens via `variablesDeTema`.
44
+ */
45
+ declare const TEMA_DEFAULT: Tema;
46
+ /**
47
+ * Variables CSS del tema como `style` inline en el `<html>`. Sobreescriben los defaults de `globals.css`; con el tema por
48
+ * omision son un no-op visual. (Extraido de `app/layout.tsx`.)
49
+ */
50
+ declare function variablesDeTema(tema: Tema): CSSProperties;
51
+
52
+ /**
53
+ * Framework-agnostic link.
54
+ *
55
+ * The kit used `next/link` directly, which a publishable library cannot depend on. Components now
56
+ * render `LinkBase`, which by default is a plain `<a href>`. A consumer that wants client-side
57
+ * routing (Next's <Link>, React Router's <Link>, etc.) injects their component once via
58
+ * `LinkComponentProvider`; everything inside then routes through it, with no component API change.
59
+ */
60
+ type LinkBaseProps = {
61
+ href: string;
62
+ children: ReactNode;
63
+ } & Omit<AnchorHTMLAttributes<HTMLAnchorElement>, "href">;
64
+ /** Shape of an injected link component: anything that accepts `href` + anchor props. */
65
+ type LinkComponent = ComponentType<LinkBaseProps>;
66
+ declare const LinkComponentProvider: react.Provider<LinkComponent | null>;
67
+ declare const LinkBase: react.ForwardRefExoticComponent<{
68
+ href: string;
69
+ children: ReactNode;
70
+ } & Omit<AnchorHTMLAttributes<HTMLAnchorElement>, "href"> & react.RefAttributes<HTMLAnchorElement>>;
71
+
72
+ /**
73
+ * Framework-agnostic listing navigation (option A of the migration).
74
+ *
75
+ * The kit originally read Next's router (usePathname/useRouter/useSearchParams). A publishable
76
+ * library cannot depend on Next, so navigation is injected via React context instead: the consumer
77
+ * wires `ListadoNavProvider` to whatever drives their URL/query state (Next's router, React Router,
78
+ * or plain component state). The listing components (BarraListado, PaginadorUrl, EncabezadoOrdenUrl)
79
+ * keep their public API unchanged — only the source of `ir`/`params`/`pendiente` moved to context.
80
+ *
81
+ * `cambios` semantics are preserved: apply the given key/value changes to the current query; a null
82
+ * or empty value clears the key; any non-page change resets to page 1 (see hrefListado in listado.ts).
83
+ */
84
+ type CambiosListado = Record<string, string | null | undefined>;
85
+ type ListadoNav = {
86
+ /** Apply `cambios` to the current query. `scroll` hints the consumer to scroll to top (page changes). */
87
+ ir: (cambios: CambiosListado, opciones?: {
88
+ scroll?: boolean;
89
+ }) => void;
90
+ /** True while a navigation is in flight, so controls can show a pending indicator. */
91
+ pendiente: boolean;
92
+ /** The current query string params (same shape as URLSearchParams). */
93
+ params: URLSearchParams;
94
+ };
95
+ declare const ListadoNavProvider: react.Provider<ListadoNav | null>;
96
+ /**
97
+ * Read the listing navigation injected by the nearest `ListadoNavProvider`. Throws a clear error if
98
+ * used outside a provider, so misuse fails loudly instead of silently doing nothing.
99
+ */
100
+ declare function useNavegarListado(): ListadoNav;
101
+
102
+ /**
103
+ * MAPA SEMANTICO CENTRAL DE ICONOGRAFIA (kit-ui-plataforma).
104
+ *
105
+ * Extraido de `web/src/lib/iconos.ts` de la plataforma: las constantes genericas (ICONO_NAV_*, ICONO_ALTA, ICONO_BAJA,
106
+ * ICONO_FILTRO, ICONO_COLUMNAS, ICONO_ACCIONES_FILA, ICONOS_SEMAFORO...) se copiaron TAL CUAL (mismo nombre, mismo glifo de
107
+ * Lucide). Se quitaron las propias del dominio de la plataforma original. Las constantes ICONO_COL_*, ICONO_KPI_*,
108
+ * ICONO_AVISO/ERROR/OK/SEGURIDAD y ICONOS_ESTATUS son alias NEUTROS de conceptos que alli tienen nombre de dominio (mismos
109
+ * glifos). Al final, "EXTENSIONES DEL KIT": conceptos del Backoffice que la plataforma no tiene; solo reutilizan glifos ya
110
+ * importados aqui, nunca introducen una libreria nueva.
111
+ *
112
+ * REGLAS (obligatorias):
113
+ * - Libreria UNICA: `lucide-react` (trazo de 2 px). Ninguna otra libreria de iconos, ningun emoji, ningun SVG suelto.
114
+ * - Ninguna pantalla ni componente importa de `lucide-react` directamente: importa la constante `ICONO_*` de este
115
+ * archivo. Un concepto nuevo se agrega AQUI una sola vez (y se documenta en references/iconos.md).
116
+ * - Tamanos: `TAMANO_BADGE` (16) en contextos densos (insignias, tablas, titulos de tarjeta); `TAMANO_BOTON` (20) en
117
+ * botones, menu lateral y titulo de pagina; el icono (i) es de 14. Iconos pequenos de apoyo: 12-13.
118
+ * - Color: hereda `currentColor`; jamas un color fijo nuevo.
119
+ * - Accesibilidad: decorativo -> `aria-hidden="true"`; unico contenido de un control -> `aria-label` y `title`.
120
+ * - Un icono por concepto: dos conceptos distintos no comparten glifo (p. ej. Dashboard=Activity, Salud=Gauge).
121
+ */
122
+
123
+ declare const TAMANO_BADGE = 16;
124
+ declare const TAMANO_BOTON = 20;
125
+ /** Icono por defecto cuando un tipo/estatus no esta en el mapa: nunca un componente roto por un valor nuevo. */
126
+ declare const ICONO_DEFAULT: LucideIcon;
127
+ /** Tipo publico del icono (alias de `LucideIcon`) para tipar props sin importar de `lucide-react`. */
128
+ type LucideIconType = LucideIcon;
129
+ declare const ICONO_NAV_DASHBOARD: LucideIcon;
130
+ declare const ICONO_NAV_SALUD: LucideIcon;
131
+ declare const ICONO_NAV_ANALITICA: LucideIcon;
132
+ declare const ICONO_NAV_ENTIDADES: LucideIcon;
133
+ declare const ICONO_NAV_INVITACIONES: LucideIcon;
134
+ declare const ICONO_NAV_ETIQUETAS: LucideIcon;
135
+ declare const ICONO_NAV_JOBS: LucideIcon;
136
+ declare const ICONO_NAV_TEMA: LucideIcon;
137
+ declare const ICONO_NAV_CONFIGURACION: LucideIcon;
138
+ declare const ICONO_NAV_API_KEYS: LucideIcon;
139
+ declare const ICONO_NAV_BITACORA: LucideIcon;
140
+ declare const ICONO_NAV_NOTIFICACIONES: LucideIcon;
141
+ declare const ICONO_NAV_MANUAL: LucideIcon;
142
+ declare const ICONO_NAV_CLIENTE: LucideIcon;
143
+ declare const ICONO_NAV_EXTRACCIONES: LucideIcon;
144
+ declare const ICONO_CERRAR_SESION: LucideIcon;
145
+ declare const ICONO_INICIAR_SESION: LucideIcon;
146
+ declare const ICONO_NAV_COLAPSAR: LucideIcon;
147
+ declare const ICONO_NAV_EXPANDIR: LucideIcon;
148
+ declare const ICONO_NAV_MENU_MOVIL: LucideIcon;
149
+ declare const ICONO_CERRAR: LucideIcon;
150
+ declare const ICONO_ALTA: LucideIcon;
151
+ declare const ICONO_GENERAR: LucideIcon;
152
+ declare const ICONO_GUARDAR: LucideIcon;
153
+ declare const ICONO_EDITAR: LucideIcon;
154
+ declare const ICONO_BAJA: LucideIcon;
155
+ declare const ICONO_DESHABILITAR: LucideIcon;
156
+ declare const ICONO_INACTIVAR: LucideIcon;
157
+ declare const ICONO_REACTIVAR_ETIQUETA: LucideIcon;
158
+ declare const ICONO_REACTIVAR: LucideIcon;
159
+ declare const ICONO_RESTABLECER: LucideIcon;
160
+ declare const ICONO_REINTENTAR: LucideIcon;
161
+ declare const ICONO_COPIAR: LucideIcon;
162
+ declare const ICONO_LINK: LucideIcon;
163
+ declare const ICONO_DESCARGAR: LucideIcon;
164
+ declare const ICONO_EXPORTAR: LucideIcon;
165
+ declare const ICONO_EXPORTAR_CSV: LucideIcon;
166
+ declare const ICONO_CONFIRMAR: LucideIcon;
167
+ declare const ICONO_VOLVER: LucideIcon;
168
+ declare const ICONO_VER_TODOS: LucideIcon;
169
+ declare const ICONO_ROTAR_KEY: LucideIcon;
170
+ declare const ICONO_REVOCAR_KEY: LucideIcon;
171
+ declare const ICONO_API_KEY: LucideIcon;
172
+ declare const ICONO_EMAIL: LucideIcon;
173
+ declare const ICONO_INVITACION_GENERICA: LucideIcon;
174
+ declare const ICONO_SEGURIDAD: LucideIcon;
175
+ declare const ICONO_CAMPANA: LucideIcon;
176
+ declare const ICONO_SILENCIAR: LucideIcon;
177
+ declare const ICONO_FILTRO: LucideIcon;
178
+ declare const ICONO_BUSCAR: LucideIcon;
179
+ declare const ICONO_LIMPIAR: LucideIcon;
180
+ declare const ICONO_SELECCIONADO: LucideIcon;
181
+ declare const ICONO_ORDENAR_ASC: LucideIcon;
182
+ declare const ICONO_ORDENAR_DESC: LucideIcon;
183
+ declare const ICONO_ORDENAR_NEUTRO: LucideIcon;
184
+ declare const ICONO_PAGINA_ANTERIOR: LucideIcon;
185
+ declare const ICONO_PAGINA_SIGUIENTE: LucideIcon;
186
+ declare const ICONO_VISTA_TABLA: LucideIcon;
187
+ declare const ICONO_VISTA_TARJETAS: LucideIcon;
188
+ declare const ICONO_ARRASTRAR_COLUMNA: LucideIcon;
189
+ declare const ICONO_COLUMNAS: LucideIcon;
190
+ declare const ICONO_COLUMNA_VISIBLE: LucideIcon;
191
+ declare const ICONO_COLUMNA_OCULTA: LucideIcon;
192
+ declare const ICONO_ACCIONES_FILA: LucideIcon;
193
+ declare const ICONO_DENSIDAD_COMPACTA: LucideIcon;
194
+ declare const ICONO_DENSIDAD_COMODA: LucideIcon;
195
+ declare const ICONO_CARGANDO: LucideIcon;
196
+ declare const ICONO_INFO_EXPLICACION: LucideIcon;
197
+ declare const ICONO_COL_CODIGO: LucideIcon;
198
+ declare const ICONO_COL_NOMBRE: LucideIcon;
199
+ declare const ICONO_COL_ESTADO: LucideIcon;
200
+ declare const ICONO_COL_MECANISMO: LucideIcon;
201
+ declare const ICONO_COL_TOTAL: LucideIcon;
202
+ declare const ICONO_COL_FECHA: LucideIcon;
203
+ declare const ICONO_COL_FECHA_HORA: LucideIcon;
204
+ declare const ICONO_COL_ETIQUETA: LucideIcon;
205
+ declare const ICONO_COL_USUARIO: LucideIcon;
206
+ declare const ICONO_COL_DOCUMENTO: LucideIcon;
207
+ declare const ICONO_PERIODO: LucideIcon;
208
+ declare const ICONO_VIGENCIA: LucideIcon;
209
+ declare const ICONO_DURACION: LucideIcon;
210
+ declare const ICONO_UBICACION: LucideIcon;
211
+ /** Estatus de proceso. Completado=CheckCircle2, en curso=Clock, pendiente=Circle, aviso=AlertTriangle, fallido=XCircle. */
212
+ declare const ICONOS_ESTATUS: Record<string, LucideIcon>;
213
+ declare function iconoDeEstatus(estado: string): LucideIcon;
214
+ /** Semaforo: verde=CheckCircle2, ambar=AlertTriangle, rojo=XCircle (y siempre con texto, nunca solo color). */
215
+ declare const ICONOS_SEMAFORO: Record<string, LucideIcon>;
216
+ declare const ETIQUETAS_SEMAFORO: Record<string, string>;
217
+ declare function iconoDeSemaforo(color: string): LucideIcon;
218
+ declare function etiquetaSemaforo(color: string): string;
219
+ declare const ICONO_AVISO: LucideIcon;
220
+ declare const ICONO_ERROR: LucideIcon;
221
+ declare const ICONO_OK: LucideIcon;
222
+ declare const ICONO_KPI_RITMO: LucideIcon;
223
+ declare const ICONO_KPI_RENDIMIENTO: LucideIcon;
224
+ declare const ICONO_KPI_CONTEO: LucideIcon;
225
+ declare const ICONO_KPI_CREDENCIALES: LucideIcon;
226
+ declare const ICONO_KPI_ALERTA: LucideIcon;
227
+ declare const ICONO_KPI_CONSUMO: LucideIcon;
228
+ declare const ICONO_KPI_BLOQUEO: LucideIcon;
229
+ declare const ICONO_NAV_PLANES: LucideIcon;
230
+ declare const ICONO_NAV_PAQUETES: LucideIcon;
231
+ declare const ICONO_NAV_ACCESOS: LucideIcon;
232
+ declare const ICONO_NAV_USUARIOS: LucideIcon;
233
+ declare const ICONO_LOGIN_MICROSOFT: LucideIcon;
234
+
235
+ /**
236
+ * Catalogo unico de explicaciones en sitio (el patron del icono (i)).
237
+ *
238
+ * LINEAMIENTO OBLIGATORIO: cada metrica, tarjeta, grafica, lista, encabezado de columna de tabla e insignia de estatus
239
+ * de CUALQUIER pantalla referencia un id de este catalogo (nunca texto en linea) y responde siempre las mismas 4
240
+ * preguntas: Que es, Como se calcula, De donde sale, Como leerlo. Cada texto se redacta leyendo el codigo que produce el
241
+ * valor (no adivinando).
242
+ *
243
+ * Reglas de formato (verificables con `verificarCatalogo()` abajo): id `modulo.id` en minusculas `[a-z0-9_]`; cada
244
+ * respuesta <= 320 caracteres; sin comillas dobles, barras invertidas ni saltos de linea; espanol neutro y profesional.
245
+ *
246
+ * Los ids `plataforma.*` los usan los componentes del kit (tabla, listado, rol): NO los borres ni los renombres.
247
+ * Agrega los de tu producto con su propio prefijo (`planes.*`, `accesos.*`, `inicio.*`).
248
+ */
249
+ type Explicacion = {
250
+ titulo: string;
251
+ que_es: string;
252
+ como_se_calcula: string;
253
+ de_donde_sale: string;
254
+ como_leerlo: string;
255
+ };
256
+ declare const EXPLICACIONES: {
257
+ readonly "plataforma.rol": {
258
+ readonly titulo: "Rol del usuario";
259
+ readonly que_es: "Tu nivel de acceso en este sistema, por ejemplo administrador, operador o consulta.";
260
+ readonly como_se_calcula: "Se resuelve al iniciar sesión según tu asignación; no se calcula.";
261
+ readonly de_donde_sale: "Asignación de rol del usuario en el directorio de acceso.";
262
+ readonly como_leerlo: "Determina qué módulos ves y qué acciones puedes ejecutar en cada tabla.";
263
+ };
264
+ readonly "plataforma.listado_resultados": {
265
+ readonly titulo: "Resultados del listado";
266
+ readonly que_es: "Cuántas filas cumplen la búsqueda y los filtros actuales frente al total del listado.";
267
+ readonly como_se_calcula: "Se cuentan las filas cuyo texto contiene lo buscado, sin distinguir mayúsculas ni acentos, y que cumplen cada filtro. La tabla muestra una página de 25, 50 o 100 de ellas.";
268
+ readonly de_donde_sale: "Lista que ya trae la pantalla; la búsqueda, los filtros, el orden y la página viajan en la dirección (URL).";
269
+ readonly como_leerlo: "Si dice N en total no hay filtro activo. Copiar la dirección comparte la misma vista.";
270
+ };
271
+ readonly "plataforma.tabla_columnas": {
272
+ readonly titulo: "Columnas de la tabla";
273
+ readonly que_es: "Lista para mostrar u ocultar las columnas de esta tabla que no están fijas. Las columnas de identidad y la de acciones siempre se ven.";
274
+ readonly como_se_calcula: "Cada casilla desmarcada oculta esa columna en pantalla; no cambia los datos, el orden, los filtros ni lo que se exporta.";
275
+ readonly 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ómoda.";
276
+ readonly como_leerlo: "Si falta una columna que esperabas, revisa esta lista. Con el almacenamiento del navegador bloqueado (modo privado) la elección dura solo mientras la página siga abierta.";
277
+ };
278
+ readonly "plataforma.tabla_densidad": {
279
+ readonly titulo: "Densidad de la tabla";
280
+ readonly que_es: "Alto de las filas: compacta muestra más filas por pantalla; cómoda deja más aire entre ellas.";
281
+ readonly como_se_calcula: "Compacta reduce el relleno vertical de cada celda; no cambia el texto ni las columnas.";
282
+ readonly de_donde_sale: "Preferencia guardada en este navegador, por tabla y por usuario, junto con las columnas ocultas.";
283
+ readonly 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ón desplaza a lo ancho.";
284
+ };
285
+ readonly "inicio.planes_activos": {
286
+ readonly titulo: "Planes activos";
287
+ readonly que_es: "Número de planes del catálogo que hoy se pueden contratar.";
288
+ readonly como_se_calcula: "Conteo de planes con estado Activo; los borradores y los archivados no cuentan.";
289
+ readonly de_donde_sale: "Catálogo de planes del backoffice (ejemplo con datos ficticios).";
290
+ readonly como_leerlo: "Un plan archivado deja de contar aunque tenga clientes vigentes; esos clientes conservan su plan hasta renovar.";
291
+ };
292
+ readonly "inicio.paquetes": {
293
+ readonly titulo: "Paquetes";
294
+ readonly que_es: "Número de paquetes de consumo definidos en el catálogo.";
295
+ readonly como_se_calcula: "Conteo de paquetes registrados, sin importar su estado.";
296
+ readonly de_donde_sale: "Catálogo de paquetes del backoffice (ejemplo con datos ficticios).";
297
+ readonly como_leerlo: "Un paquete puede estar asociado a varios planes; aquí se cuenta una sola vez.";
298
+ };
299
+ readonly "inicio.accesos_vigentes": {
300
+ readonly titulo: "Accesos vigentes";
301
+ readonly que_es: "Usuarios con acceso al backoffice que no están suspendidos ni vencidos.";
302
+ readonly como_se_calcula: "Conteo de usuarios con estado Activo y fecha de vencimiento futura o sin vencimiento.";
303
+ readonly de_donde_sale: "Registro de accesos del backoffice (ejemplo con datos ficticios).";
304
+ readonly como_leerlo: "Un usuario con rol de solo consulta cuenta igual que uno administrador.";
305
+ };
306
+ readonly "inicio.cobertura": {
307
+ readonly titulo: "Cobertura del catálogo";
308
+ readonly que_es: "Porcentaje de planes que ya tienen al menos un paquete asignado.";
309
+ readonly como_se_calcula: "Planes con al menos un paquete entre planes activos, por 100.";
310
+ readonly de_donde_sale: "Relación plan-paquete del catálogo (ejemplo con datos ficticios).";
311
+ readonly como_leerlo: "Menos de 100 % indica planes sin paquete: no se pueden vender hasta que se les asigne uno.";
312
+ };
313
+ readonly "inicio.resumen_catalogo": {
314
+ readonly titulo: "Resumen del catálogo";
315
+ readonly que_es: "Planes agrupados por estado, con el total de paquetes que suman.";
316
+ readonly como_se_calcula: "Cada plan cae en un solo estado; los paquetes de una fila son la suma de los paquetes de sus planes.";
317
+ readonly de_donde_sale: "Catálogo de planes y paquetes del backoffice (ejemplo con datos ficticios).";
318
+ readonly como_leerlo: "Un paquete compartido por dos planes se cuenta una vez por cada plan.";
319
+ };
320
+ readonly "planes.col_codigo": {
321
+ readonly titulo: "Código";
322
+ readonly que_es: "Identificador corto y estable del plan.";
323
+ readonly como_se_calcula: "Se captura al crear el plan; no se calcula ni se puede repetir.";
324
+ readonly de_donde_sale: "Catálogo de planes (ejemplo con datos ficticios).";
325
+ readonly como_leerlo: "Se usa en integraciones y reportes; el nombre comercial puede cambiar, el código no.";
326
+ };
327
+ readonly "planes.col_nombre": {
328
+ readonly titulo: "Nombre";
329
+ readonly que_es: "Nombre comercial del plan tal como lo ve el cliente.";
330
+ readonly como_se_calcula: "Se captura al crear o editar el plan; no se calcula.";
331
+ readonly de_donde_sale: "Catálogo de planes (ejemplo con datos ficticios).";
332
+ readonly como_leerlo: "La búsqueda ignora mayúsculas y acentos.";
333
+ };
334
+ readonly "planes.col_precio": {
335
+ readonly titulo: "Precio mensual";
336
+ readonly que_es: "Precio de lista del plan por mes, en pesos, sin impuestos.";
337
+ readonly como_se_calcula: "Se captura al crear o editar el plan; no se calcula.";
338
+ readonly de_donde_sale: "Catálogo de planes (ejemplo con datos ficticios).";
339
+ readonly como_leerlo: "Es precio de lista: un contrato puede tener un descuento que no se refleja aquí.";
58
340
  };
59
- readonly background: {
60
- readonly app: "#f5f8fa";
61
- readonly body: "#ffffff";
62
- readonly appDark: "#151521";
63
- readonly bodyDark: "#1e1e2d";
341
+ readonly "planes.col_estado": {
342
+ readonly titulo: "Estado del plan";
343
+ readonly que_es: "Situación del plan en el catálogo: Activo, Borrador o Archivado.";
344
+ readonly como_se_calcula: "Lo fija el administrador al publicar o archivar; no se calcula.";
345
+ readonly de_donde_sale: "Catálogo de planes (ejemplo con datos ficticios).";
346
+ readonly como_leerlo: "Solo los planes Activos se pueden contratar. Archivado conserva el historial pero no admite altas nuevas.";
64
347
  };
65
- readonly dark: {
66
- readonly base: "#181c32";
67
- readonly bg: "#151521";
68
- readonly header: "#1e1e2d";
69
- readonly active: "#2a2a3c";
70
- readonly separator: "#393945";
71
- readonly inputBg: "#1b1b29";
72
- readonly cardBg: "#1e1e2d";
73
- readonly gray: {
74
- readonly 100: "#2b2b40";
75
- readonly 200: "#323248";
76
- readonly 300: "#3b3b64";
77
- readonly 400: "#474761";
78
- readonly 500: "#565674";
79
- readonly 600: "#6d6d80";
80
- readonly 700: "#92929f";
81
- readonly 800: "#cdcdde";
82
- };
348
+ readonly "planes.col_actualizado": {
349
+ readonly titulo: "Actualizado";
350
+ readonly que_es: "Fecha y hora de la última modificación del plan, en tu hora local.";
351
+ readonly como_se_calcula: "Se registra en UTC al guardar cambios y el navegador la convierte a tu zona horaria.";
352
+ readonly de_donde_sale: "Bitácora de cambios del catálogo (ejemplo con datos ficticios).";
353
+ readonly como_leerlo: "Cambiar solo el estado también actualiza esta fecha.";
83
354
  };
355
+ readonly "planes.estado_activo": {
356
+ readonly titulo: "Activo";
357
+ readonly que_es: "El plan está publicado y se puede contratar.";
358
+ readonly como_se_calcula: "Estado asignado al publicar el plan.";
359
+ readonly de_donde_sale: "Catálogo de planes (ejemplo con datos ficticios).";
360
+ readonly como_leerlo: "Para retirarlo del catálogo, archívalo; no lo borres.";
361
+ };
362
+ readonly "planes.estado_borrador": {
363
+ readonly titulo: "Borrador";
364
+ readonly que_es: "El plan se está preparando y aún no es visible para contratar.";
365
+ readonly como_se_calcula: "Estado inicial de todo plan nuevo.";
366
+ readonly de_donde_sale: "Catálogo de planes (ejemplo con datos ficticios).";
367
+ readonly como_leerlo: "Publica el plan cuando tenga precio y al menos un paquete.";
368
+ };
369
+ readonly "planes.estado_archivado": {
370
+ readonly titulo: "Archivado";
371
+ readonly que_es: "El plan se retiró del catálogo; conserva su historial.";
372
+ readonly como_se_calcula: "Estado asignado al archivar un plan activo.";
373
+ readonly de_donde_sale: "Catálogo de planes (ejemplo con datos ficticios).";
374
+ readonly como_leerlo: "No admite altas nuevas; los clientes existentes conservan su plan hasta renovar.";
375
+ };
376
+ };
377
+ type ExplicacionId = keyof typeof EXPLICACIONES;
378
+ /** Entrada del catalogo; un id desconocido (solo posible con un cast) falla de forma visible. */
379
+ declare function explicacionDe(id: ExplicacionId): Explicacion;
380
+ /** Devuelve la lista de violaciones de formato del catalogo (vacia = correcto). Util como prueba unitaria. */
381
+ declare function verificarCatalogo(): string[];
382
+
383
+ /**
384
+ * Estado de un listado (busqueda, filtros, orden, pagina y tamano) que vive en la URL (change
385
+ * `ux-listados-compactos`). Funciones puras: el Server Component de cada pantalla lee los `searchParams`, aplica
386
+ * el listado sobre la lista ya traida de la API y pinta SOLO la pagina visible; la barra (`BarraListado`), el
387
+ * paginador (`PaginadorUrl`) y los encabezados ordenables (`EncabezadoOrdenUrl`) solo reescriben la URL.
388
+ *
389
+ * Por que en el servidor de Next y no en el backend: cada lista esta acotada (decenas a cientos de filas) y la busqueda sin acentos obligaria a la API a un scan de todos
390
+ * modos. Aqui el navegador recibe una sola pagina (25/50/100 filas) y el trabajo por fila (etiquetas, enlaces) se
391
+ * hace solo para esa pagina.
392
+ */
393
+ declare const TAMANOS_LISTADO: readonly [25, 50, 100];
394
+ declare const TAMANO_LISTADO_DEFAULT = 25;
395
+ type Direccion = "asc" | "desc";
396
+ type ParamsUrl = Record<string, string | string[] | undefined>;
397
+ type EstadoListado = {
398
+ q: string;
399
+ pagina: number;
400
+ tamano: number;
401
+ orden: string;
402
+ dir: Direccion;
403
+ /** Solo los filtros declarados por la pantalla y con valor. */
404
+ filtros: Record<string, string>;
405
+ };
406
+ type OpcionesListado = {
407
+ /** Claves de filtro que la pantalla entiende (p. ej. `estado`, `mecanismo`). */
408
+ filtros: readonly string[];
409
+ /** Claves de orden validas. */
410
+ ordenes: readonly string[];
411
+ ordenDefault: string;
412
+ dirDefault?: Direccion;
84
413
  };
85
- /** Radius scale (Metronic). Base radius is 4px. */
86
- declare const radius: {
87
- readonly sm: 2;
88
- readonly base: 4;
89
- readonly md: 6;
90
- readonly lg: 8;
91
- readonly xl: 12;
414
+ type DefListado<T> = {
415
+ /** Texto en el que busca `q` (nombre, codigo, etc.). */
416
+ texto: (item: T) => string;
417
+ filtrar?: (item: T, filtros: Record<string, string>) => boolean;
418
+ /** Valor por el que ordena cada clave de orden. `null`/`undefined`/`""`/`NaN` = ausente (siempre al final). */
419
+ valoresOrden: Record<string, (item: T) => string | number | null | undefined>;
92
420
  };
93
- /** Typography (Metronic uses Inter with a compact 13px base). */
94
- declare const typography: {
95
- readonly fontFamily: "Inter, Helvetica, Arial, sans-serif";
96
- readonly fontSizeBase: 13;
97
- readonly weight: {
98
- readonly light: 300;
99
- readonly normal: 400;
100
- readonly medium: 500;
101
- readonly semibold: 600;
102
- readonly bold: 700;
421
+ /** Minusculas, sin acentos (NFD sin marcas combinantes) y espacios colapsados: " PEÑA Ávila" -> "pena avila". */
422
+ declare function normalizarTexto(s: string): string;
423
+ declare function leerListado(sp: ParamsUrl, opc: OpcionesListado): EstadoListado;
424
+ declare function aplicarListado<T>(items: readonly T[], estado: EstadoListado, def: DefListado<T>): {
425
+ itemsPagina: T[];
426
+ totalFiltrado: number;
427
+ total: number;
428
+ pagina: number;
429
+ totalPaginas: number;
430
+ };
431
+ /**
432
+ * URL con `cambios` aplicados sobre la query actual. Un valor vacio o `null` borra la clave. Cualquier cambio que
433
+ * no sea de pagina regresa a la pagina 1 (borra `pagina`); `pagina=1` tambien se omite para que la URL quede limpia.
434
+ */
435
+ declare function hrefListado(ruta: string, actual: string | URLSearchParams, cambios: Record<string, string | null | undefined>): string;
436
+
437
+ /**
438
+ * Unico punto por el que las cifras del snapshot llegan a pantalla (decision D10 de `reporte-riesgo-crediticio`).
439
+ *
440
+ * Reglas: las cifras son CADENAS decimales ya redondeadas por el backend; aqui solo se agrupan los miles y se acomoda el
441
+ * signo y el punto decimal manipulando texto, jamas con `Number`, `parseFloat` ni `toFixed` (un float distinto entre el
442
+ * HTML y el PDF cambiaria una cifra). Un dato ausente (`null`) se muestra como `NO_DISPONIBLE`, nunca como cero.
443
+ * Este modulo no importa nada de `next/*` ni hace red: lo comparten el sitio y el empaquetado del PDF.
444
+ */
445
+ declare const NO_DISPONIBLE = "\u2014";
446
+ /** Dinero en pesos: `1234.50` -> `$1,234.50` (los decimales son los que trae la cadena). */
447
+ declare function formatoMxn(valor: string | null | undefined): string;
448
+ /** Decimal generico (pendientes, promedios): agrupa los miles y respeta los decimales de la cadena. */
449
+ declare function formatoNumero(valor: string | null | undefined): string;
450
+ declare function formatoEntero(valor: number | null | undefined): string;
451
+ /** Razon (`0.1234`) como porcentaje (`12.34 %`): se corre el punto dos lugares en el texto, sin aritmetica. */
452
+ declare function formatoPct(razon: string | null | undefined): string;
453
+ declare function formatoDias(valor: string | null | undefined): string;
454
+ /** `AAAA-MM-DD` -> `AAAA/MM/DD` (formato unico de fecha de la plataforma). */
455
+ declare function formatoFecha(iso: string | null | undefined): string;
456
+ declare function formatoMes(mes: string | null | undefined): string;
457
+
458
+ /**
459
+ * Formato unico de fecha/hora para TODO el sistema (pedido explicito del usuario:
460
+ * "todos los periodos y fechas usemos formato yyyy/MM/dd HH:mm:ss"), SIEMPRE en hora
461
+ * LOCAL del navegador (pedido del usuario: "en la base guardamos UTC pero en el view
462
+ * debe ser hora local").
463
+ *
464
+ * La API entrega fechas en DOS familias, que se distinguen por el sufijo de zona:
465
+ * - CON sufijo UTC (`Z` o `+00:00`): timestamps del sistema escritos con
466
+ * `now_utc().isoformat()` -> `...+00:00` (creado_en, terminado_en, `ts` de bitacora,
467
+ * downloaded_at, etc.). Son instantes ABSOLUTOS en UTC y DEBEN convertirse a local.
468
+ * - SIN sufijo (naive `YYYY-MM-DDTHH:MM:SS`): fechas de negocio (documento/portal)
469
+ * (`fecha_emision`, `fecha_timbrado`, `start`/`end` de ventana, `date_from/to`) que
470
+ * ya vienen en la hora que reporto la fuente -- NO se re-convierten (no tienen un
471
+ * offset conocido; reinterpretarlas correria la hora sin base).
472
+ *
473
+ * En ambos casos la salida es `yyyy/MM/dd HH:mm:ss`. `date_from/to` puede venir como
474
+ * `YYYY-MM-DD` puro (sin hora) -> se muestra la fecha a medianoche, sin conversion.
475
+ */
476
+ declare function formatearFechaHora(iso: string | null | undefined): string;
477
+ /**
478
+ * Como `formatearFechaHora`, pero un instante CON zona se muestra en America/Mexico_City (no en la
479
+ * zona del proceso). Para componentes de servidor, donde "hora local" seria la del servidor (UTC).
480
+ * Las fechas naive (fecha de negocio) o `YYYY-MM-DD` se muestran tal cual, igual que en la otra.
481
+ */
482
+ declare function formatearFechaHoraCDMX(iso: string | null | undefined): string;
483
+ /** Formatea un rango `[desde, hasta]` con el mismo formato, unido por un guion largo. */
484
+ declare function formatearRangoFechaHora(desde: string | null | undefined, hasta: string | null | undefined): string;
485
+
486
+ /**
487
+ * Tamano legible de un archivo (base 1024) para la estimacion y las partes ZIP de una
488
+ * extraccion. Solo formatea: nunca recalcula nada.
489
+ */
490
+ declare function formatearBytes(n: number | null | undefined): string;
491
+
492
+ /**
493
+ * Helper central para el lineamiento "toda accion dispara el spinner de marca"
494
+ * (lineamiento "toda accion dispara el spinner de marca"). Envuelve una funcion async y expone:
495
+ * - `ejecutando`: true mientras la accion corre (para deshabilitar el boton).
496
+ * - `ejecutar(fn, etiqueta?)`: corre `fn`, muestra el overlay de marca y lo cierra al
497
+ * terminar (aunque `fn` lance).
498
+ * - `Overlay`: componente listo para montar; pinta el `OverlayCargando` solo mientras
499
+ * `ejecutando`. Asi cualquier accion obtiene el feedback homologado con una linea.
500
+ *
501
+ * Uso:
502
+ * const { ejecutando, ejecutar, Overlay } = useAccionConSpinner();
503
+ * <button disabled={ejecutando} onClick={() => ejecutar(guardar, "Guardando...")}>Guardar</button>
504
+ * <Overlay />
505
+ */
506
+ declare function useAccionConSpinner(): {
507
+ ejecutando: boolean;
508
+ ejecutar: <T>(fn: () => Promise<T>, etiquetaAccion?: string) => Promise<T | undefined>;
509
+ Overlay: () => react.JSX.Element;
510
+ };
511
+
512
+ /**
513
+ * Hook de React sobre `preferenciasTabla`: mantiene el orden, los anchos y las columnas
514
+ * ocultas de UNA tabla, persistidos en localStorage bajo `clave`, y expone acciones para
515
+ * reordenar/redimensionar/ocultar/restablecer.
516
+ *
517
+ * `idsDefault` es el orden natural de las columnas de la tabla (por id). El hook resuelve
518
+ * el orden efectivo combinando lo guardado con los defaults (columnas nuevas al final,
519
+ * ids viejos ignorados) via `ordenarColumnas`.
520
+ *
521
+ * SSR-safe: en el primer render (servidor y cliente) usa los defaults; tras montar, lee
522
+ * localStorage y re-renderiza. Asi no hay desajuste de hidratacion.
523
+ */
524
+ declare function useTablaPreferencias(clave: string, idsDefault: string[]): {
525
+ /** Ids en el orden efectivo, SIN las ocultas — para pintar la tabla. */
526
+ idsVisibles: string[];
527
+ /** Ids en el orden efectivo, incluyendo ocultas — para el menu de mostrar/ocultar. */
528
+ idsOrdenados: string[];
529
+ /** Set de ids ocultos. */
530
+ ocultas: Set<string>;
531
+ /** Ancho persistido de una columna, o undefined si no se ha redimensionado. */
532
+ anchoDe: (id: string) => number | undefined;
533
+ mover: (desde: number, hasta: number) => void;
534
+ redimensionar: (id: string, ancho: number) => void;
535
+ alternarVisible: (id: string) => void;
536
+ restablecer: () => void;
537
+ };
538
+
539
+ /**
540
+ * Calculo puro de la posicion de un popover `fixed` dentro del viewport. Separado del
541
+ * componente para poder probarlo sin layout real (jsdom no mide).
542
+ */
543
+ type RectLike = {
544
+ left: number;
545
+ top: number;
546
+ right: number;
547
+ bottom: number;
548
+ width: number;
549
+ height: number;
550
+ };
551
+ type EntradaPosicion = {
552
+ trigger: RectLike;
553
+ /** Tamano medido del contenido (ya acotado a `anchoMax` si aplica). */
554
+ contenido: {
555
+ ancho: number;
556
+ alto: number;
557
+ };
558
+ viewport: {
559
+ ancho: number;
560
+ alto: number;
103
561
  };
562
+ margen?: number;
563
+ separacion?: number;
564
+ /** Ancho maximo deseado (default 360). */
565
+ anchoPreferido?: number;
104
566
  };
105
- /** Control sizing (Metronic). */
106
- declare const sizing: {
107
- readonly controlHeight: 32;
108
- readonly buttonMinWidth: 110;
567
+ type PosicionPopover = {
568
+ top: number;
569
+ left: number;
570
+ /** Alto maximo para scroll interno. */
571
+ maxHeight: number;
572
+ /** Ancho maximo: min(preferido, viewport - 2*margen). */
573
+ anchoMax: number;
109
574
  };
575
+ declare function calcularPosicionPopover({ trigger, contenido, viewport, margen, separacion, anchoPreferido, }: EntradaPosicion): PosicionPopover;
576
+
577
+ /**
578
+ * Clases Tailwind CANONICAS de botones, campos y avisos. La plataforma las escribe en linea en cada pantalla; aqui estan
579
+ * agrupadas VERBATIM (docs/sistema-diseno-ui.md 7.1, 7.2 y 7.9 del proyecto original, y las clases mas repetidas en su
580
+ * codigo) para que no se reinventen. Uso: `<button className={CLASE_BOTON_PRIMARIO}>`.
581
+ * Regla: una sola accion primaria por vista o modal. Destructivo: siempre con confirmacion previa.
582
+ */
110
583
  /**
111
- * Semantic tokens — role aliases. These feed the antd `ThemeConfig`.
112
- * Components must consume semantic tokens, never primitives directly.
113
- */
114
- declare const semantic: {
115
- readonly colorPrimary: "#A72432";
116
- readonly colorPrimaryActive: "#8B1D28";
117
- readonly colorSuccess: "#50cd89";
118
- readonly colorInfo: "#7239ea";
119
- readonly colorError: "#f1416c";
120
- readonly colorWarning: "#ffc700";
121
- readonly colorLink: "#3f4254";
122
- readonly colorLinkHover: "#A72432";
123
- readonly colorLinkActive: "#8B1D28";
124
- readonly colorBgLayout: "#f5f8fa";
125
- readonly colorBgContainer: "#ffffff";
126
- readonly borderRadius: 4;
127
- readonly fontFamily: "Inter, Helvetica, Arial, sans-serif";
128
- readonly fontSize: 13;
129
- readonly controlHeight: 32;
584
+ * Primario estandar (36 px de alto): accion principal de una vista o modal.
585
+ * Relleno NEUTRO OSCURO (var(--tema-texto)), NO el rojo de marca: el rojo queda reservado a peligro
586
+ * (ver docs/criterio-color-acciones.md). El rojo de marca aparece como acento (titulos, foco, seleccion).
587
+ */
588
+ declare const 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";
589
+ /** Primario compacto (32 px): modales y barras de herramientas. Mismo criterio neutro oscuro. */
590
+ declare const 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";
591
+ /** Secundario: cancelar, acciones de fila, paginador. */
592
+ declare const 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";
593
+ /** Pequeno (28 px): barras de herramientas de tabla (mismo que el boton "Columnas"). */
594
+ declare const 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";
595
+ /** Contorno primario: accion secundaria que debe destacar. */
596
+ declare const 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]";
597
+ /** Solo icono (cerrar, copiar, colapsar): exige `aria-label` y `title`. */
598
+ declare const CLASE_BOTON_ICONO = "rounded-md p-1 text-[#807f7f] transition hover:bg-[var(--tema-badge-neutro)]";
599
+ /** Destructivo (bajas): contorno en el rojo de peligro (tematizable); confirmar siempre antes de ejecutar. */
600
+ declare const 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";
601
+ /** Input / select / textarea estandar. Compacto (filtros): `px-2 py-1.5`. */
602
+ declare const 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]";
603
+ declare const 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";
604
+ /** Etiqueta (label) de campo: encima del campo, separada 4 px (`flex flex-col gap-1`). */
605
+ declare const CLASE_ETIQUETA_CAMPO = "text-sm font-medium text-[#3c3c3b]";
606
+ /** Texto de ayuda bajo el campo. */
607
+ declare const CLASE_AYUDA_CAMPO = "text-xs text-[#807f7f]";
608
+ /** Error de un campo o del envio (con `role="alert"`). */
609
+ declare const CLASE_ERROR_CAMPO = "text-sm text-[var(--tema-peligro)]";
610
+ /** Exito bajo el formulario (con `role="status"`). */
611
+ declare const CLASE_EXITO_CAMPO = "text-sm text-[#1e7a34]";
612
+ /** Tarjeta / seccion: borde fino, sin sombra, sin fondo. */
613
+ declare const CLASE_TARJETA = "rounded-lg border border-[var(--tema-borde)] p-4";
614
+ /** Titulos. */
615
+ declare const CLASE_TITULO_PAGINA = "flex items-center gap-2 text-xl font-semibold text-[var(--tema-primario-oscuro)]";
616
+ declare const CLASE_TITULO_SECCION = "text-sm font-semibold text-[var(--tema-primario-oscuro)]";
617
+ declare const CLASE_TEXTO_ATENUADO = "text-sm text-[#807f7f]";
618
+
619
+ declare const CLASES: {
620
+ readonly exito: "bg-[var(--tema-badge-exito)] text-[#1e6b34]";
621
+ readonly error: "bg-[var(--tema-badge-error)] text-[var(--tema-peligro)]";
622
+ readonly aviso: "bg-[var(--tema-badge-advertencia)] text-[#8a5a00]";
623
+ readonly neutro: "bg-[var(--tema-badge-neutro)] text-[#565656]";
130
624
  };
131
- type ThemeMode = 'light' | 'dark';
625
+ type Tono = keyof typeof CLASES;
626
+ declare function Insignia({ tono, children, info, icono: Icono, }: {
627
+ tono: keyof typeof CLASES;
628
+ children: ReactNode;
629
+ /** Icono de 12 px antes del texto (KIT: patron de `BadgeEstado` de la plataforma; el color nunca es la unica senal). */
630
+ icono?: LucideIconType;
631
+ /** Explicacion en sitio de la insignia: el icono va justo despues del chip, nunca dentro de el. */
632
+ info?: ExplicacionId;
633
+ }): react.JSX.Element;
634
+ declare function Tarjeta({ titulo, children, nota, info, }: {
635
+ titulo: string;
636
+ children: ReactNode;
637
+ nota?: ReactNode;
638
+ /** Explicacion en sitio del titulo (catalogo `lib/explicaciones.ts`). */
639
+ info?: ExplicacionId;
640
+ }): react.JSX.Element;
641
+ declare function Metrica({ etiqueta, valor, info, }: {
642
+ etiqueta: string;
643
+ valor: ReactNode;
644
+ /** Explicacion en sitio de la metrica (catalogo `lib/explicaciones.ts`). */
645
+ info?: ExplicacionId;
646
+ }): react.JSX.Element;
647
+ /** Encabezado de columna con su explicacion en sitio (el icono va junto al texto, alineado segun la columna). */
648
+ declare function ThInfo({ info, children, className, derecha, scope, atributos, }: {
649
+ info: ExplicacionId;
650
+ children: ReactNode;
651
+ className?: string;
652
+ derecha?: boolean;
653
+ scope?: "col" | "row";
654
+ /** Atributos de columna del marco de tablas: `fija("izq", i)` o `col(id)` (`@/kit/tabla/celdas`). */
655
+ atributos?: object;
656
+ }): react.JSX.Element;
132
657
 
133
- interface AmsConfigProviderProps {
134
- /**
135
- * Controlled color mode. When provided, the provider does not manage or
136
- * persist the mode. Omit it to let the provider manage the mode itself
137
- * (persisted to localStorage, respects OS preference) — read/toggle it with
138
- * the `useThemeMode` hook.
139
- */
140
- mode?: ThemeMode;
141
- /** Initial mode when self-managed (uncontrolled). Defaults to `light`. */
142
- defaultMode?: ThemeMode;
143
- /** Persist the self-managed mode to localStorage. Defaults to `true`. */
144
- persistMode?: boolean;
145
- /**
146
- * antd locale (e.g. `esES`, `enUS`). The consuming app passes it;
147
- * the design system stays i18n-agnostic and ships no message catalog.
148
- */
149
- locale?: Locale;
150
- /**
151
- * Theme overrides merged on top of the AMS theme. Use it to customize tokens
152
- * per project without forking the DS, e.g. `{ token: { colorLink: '#1677ff' } }`.
153
- */
154
- theme?: ThemeConfig;
658
+ /**
659
+ * Icono de ayuda (change `explicaciones-analitica-conceptos`): al pasar el mouse o enfocar con teclado abre un
660
+ * popover con las 4 preguntas fijas (que es, como se calcula, de donde sale, como leerlo) del catalogo
661
+ * `lib/explicaciones.ts`. Reusa `PopoverHover` (focusable, `aria-describedby`, posicion `fixed`).
662
+ *
663
+ * Sin desplazamiento de layout: el disparador es un icono de tamano fijo (14px) en un `span` en linea; el
664
+ * contenido solo existe mientras esta abierto. Un id fuera del catalogo lanza (`explicacionDe`): preferible a
665
+ * dejar una metrica sin explicacion en silencio. El `data-explicacion-id` lo leen las pruebas de cobertura.
666
+ */
667
+ declare function InfoExplicacion({ id }: {
668
+ id: ExplicacionId;
669
+ }): react.JSX.Element;
670
+
671
+ declare const TIPOS: {
672
+ readonly error: "rounded-md bg-[var(--tema-badge-error)] px-3 py-2 text-sm text-[var(--tema-peligro)]";
673
+ readonly advertencia: "rounded-md bg-[var(--tema-badge-advertencia)] px-3 py-2 text-xs text-[#8a5a00]";
674
+ readonly neutro: "rounded-lg bg-[var(--tema-badge-neutro)] px-3 py-2 text-sm text-[#565656]";
675
+ readonly exito: "rounded-md bg-[var(--tema-badge-exito)] px-3 py-2 text-sm text-[#1e7a34]";
676
+ };
677
+ /** Aviso en linea: empieza con una frase en negrita (`titulo`) y sigue el detalle. `error` -> role="alert"; el resto "status". */
678
+ declare function Aviso({ tipo, titulo, children, info, }: {
679
+ tipo: keyof typeof TIPOS;
680
+ titulo?: string;
155
681
  children?: ReactNode;
156
- }
682
+ info?: ExplicacionId;
683
+ }): react.JSX.Element;
684
+ /** Vacio en bloque (borde punteado). Dentro de una tabla se usa una fila `td colSpan` con `EstadoVacioFila`. */
685
+ declare function EstadoVacio({ children }: {
686
+ children: ReactNode;
687
+ }): react.JSX.Element;
688
+ /** Fila de "Sin resultados" para el `<tbody>` de una tabla. */
689
+ declare function EstadoVacioFila({ columnas, children }: {
690
+ columnas: number;
691
+ children?: ReactNode;
692
+ }): react.JSX.Element;
693
+ /** "No disponible": un calculo que no pudo hacerse. Dice por que; NUNCA pinta un cero. */
694
+ declare function NoDisponible({ motivo, info }: {
695
+ motivo: string;
696
+ info: ExplicacionId;
697
+ }): react.JSX.Element;
698
+ /** Barra de progreso (6 px de alto). */
699
+ declare function BarraProgreso({ porcentaje, etiqueta }: {
700
+ porcentaje: number;
701
+ etiqueta: string;
702
+ }): react.JSX.Element;
703
+
704
+ type AvisoAccion = {
705
+ tipo: "ok" | "error";
706
+ texto: string;
707
+ };
708
+ type IdInfo = Parameters<typeof InfoExplicacion>[0]["id"];
709
+ /**
710
+ * Estado de una accion asincrona (patron unico: "Reintentar", "Sincronizar", etc.): `correr` la
711
+ * ejecuta una vez, `ejecutando` deshabilita el disparador y `aviso` dice el resultado. Un error lanzado se dice con
712
+ * `errorGenerico`; `onHecho` solo se llama si la accion termino bien (para refrescar lo que se ve). Change
713
+ * separado del boton para que el disparador pueda vivir en el menu "⋯" de la fila (que
714
+ * se cierra al elegir) mientras el spinner y el aviso se pintan en la fila.
715
+ */
716
+ declare function useAccionAviso({ ejecutar, errorGenerico, onHecho, }: {
717
+ ejecutar: () => Promise<AvisoAccion>;
718
+ errorGenerico: string;
719
+ onHecho?: () => void;
720
+ }): {
721
+ ejecutando: boolean;
722
+ aviso: AvisoAccion | null;
723
+ correr: () => Promise<void>;
724
+ };
725
+ /** Spinner mientras la accion corre y el aviso del resultado (`status` si salio bien, `alert` si fallo). */
726
+ declare function AvisoAccionEstado({ ejecutando, aviso, etiquetaSpinner, }: {
727
+ ejecutando: boolean;
728
+ aviso: AvisoAccion | null;
729
+ etiquetaSpinner: string;
730
+ }): react.JSX.Element;
157
731
  /**
158
- * Root provider for the AMS Design System.
732
+ * Boton de accion con su (i), spinner y aviso del resultado. Deshabilitado mientras `ejecutar` corre.
733
+ * Compone `useAccionAviso` + `AvisoAccionEstado`.
734
+ */
735
+ declare function BotonAccionAviso({ etiqueta, etiquetaEjecutando, etiquetaSpinner, ariaLabel, info, errorGenerico, ejecutar, onHecho, }: {
736
+ etiqueta: string;
737
+ etiquetaEjecutando: string;
738
+ etiquetaSpinner: string;
739
+ ariaLabel: string;
740
+ info: IdInfo;
741
+ errorGenerico: string;
742
+ ejecutar: () => Promise<AvisoAccion>;
743
+ onHecho?: () => void;
744
+ }): react.JSX.Element;
745
+
746
+ type GrupoNavegacion = {
747
+ /** Titulo overline del grupo ("Operacion", "Administracion"...). Sin titulo = grupo sin encabezado. */
748
+ titulo?: string;
749
+ enlaces: {
750
+ href: string;
751
+ etiqueta: string;
752
+ icono: LucideIconType;
753
+ }[];
754
+ };
755
+ declare function CascaronApp({ producto, hrefInicio, logo, usuario, hrefCerrarSesion, grupos, pieExtra, children, }: {
756
+ /** Nombre del producto (14 px, 600, color primario) bajo el logo. */
757
+ producto: string;
758
+ hrefInicio?: string;
759
+ /** Logo opcional (ya dimensionado). Sin logo se muestra solo el nombre. */
760
+ logo?: {
761
+ src: string;
762
+ alt: string;
763
+ ancho: number;
764
+ alto: number;
765
+ };
766
+ usuario: {
767
+ nombre: string;
768
+ rol?: string;
769
+ idEstable?: string;
770
+ };
771
+ hrefCerrarSesion?: string;
772
+ grupos: GrupoNavegacion[];
773
+ /** Controles extra del pie (p. ej. la campana de notificaciones), a la izquierda del usuario. */
774
+ pieExtra?: ReactNode;
775
+ children: ReactNode;
776
+ }): react.JSX.Element;
777
+
778
+ /**
779
+ * Enlace del menu lateral. Server-compatible (sin estado): el colapso lo decide CSS via el
780
+ * atributo `data-colapsado` del `<aside>` (`SidebarColapsable`, grupo `side`). Con el menu
781
+ * colapsado (escritorio) solo se ve el icono; `aria-label` y `title` conservan el nombre
782
+ * accesible y el tooltip nativo.
783
+ */
784
+ declare function EnlaceNav({ href, icono, etiqueta, }: {
785
+ href: string;
786
+ icono: ReactNode;
787
+ etiqueta: string;
788
+ }): react.JSX.Element;
789
+ /** Seccion del menu: el titulo se oculta (queda un separador) cuando el menu esta colapsado. */
790
+ declare function SeccionNav({ titulo, children }: {
791
+ titulo?: string;
792
+ children: ReactNode;
793
+ }): react.JSX.Element;
794
+
795
+ /** Migas: "← Volver" (enlace primario subrayado) / valor actual (mono si es un codigo). */
796
+ declare function Migas({ hrefVolver, etiquetaVolver, actual, actualMono, }: {
797
+ hrefVolver: string;
798
+ /** Texto del enlace, p. ej. "Planes". Se pinta como "← Planes". */
799
+ etiquetaVolver: string;
800
+ actual: string;
801
+ actualMono?: boolean;
802
+ }): react.JSX.Element;
803
+ /** Sub-navegacion entre vistas hermanas de una misma entidad (pildoras con borde; la activa lleva `aria-current`). */
804
+ declare function SubNav({ etiqueta, secciones, activa, }: {
805
+ etiqueta: string;
806
+ secciones: readonly {
807
+ id: string;
808
+ texto: string;
809
+ href: string;
810
+ }[];
811
+ activa: string;
812
+ }): react.JSX.Element;
813
+
814
+ /**
815
+ * Cambio `web-paneles-ajustables` — menu lateral colapsable.
159
816
  *
160
- * - Applies the AMS theme (light/dark) via antd's `ConfigProvider`.
161
- * - Renders antd's `App` for context-safe `message`/`notification`/`Modal`.
162
- * - Manages the color mode (controlled via `mode`, or self-managed with
163
- * localStorage persistence and OS-preference detection) and exposes it
164
- * through the `useThemeMode` hook.
165
- * - Accepts a `theme` override merged on top of the AMS theme.
817
+ * Escritorio (`md`+): boton para colapsar a un rail de solo iconos (w-14); la preferencia
818
+ * persiste en localStorage. Movil (<`md`): el menu es un cajon fuera de pantalla con boton
819
+ * hamburguesa, fondo que lo cierra, Escape y cierre al elegir un enlace (antes ocupaba
820
+ * 15rem fijos del viewport).
166
821
  *
167
- * Render it once at the app root.
822
+ * El estado se expone como `data-colapsado` en el `<aside>` (grupo `side`): los enlaces del
823
+ * Server Component (`EnlaceNav`) reaccionan por CSS, sin convertirse en cliente. El render
824
+ * inicial es expandido (igual que el SSR) y el valor guardado se aplica tras montar.
825
+ * Convive con el asistente anclado: este rail solo cambia SU ancho; el area de contenido es
826
+ * `flex-1` y el asistente reserva su espacio aparte con `--asistente-ancho`.
168
827
  */
169
- declare function AmsConfigProvider({ mode, defaultMode, persistMode, locale, theme, children, }: PropsWithChildren<AmsConfigProviderProps>): react.JSX.Element;
828
+ declare function SidebarColapsable({ cabecera, pie, children, }: {
829
+ cabecera: ReactNode;
830
+ pie: ReactNode;
831
+ children: ReactNode;
832
+ }): react.JSX.Element;
170
833
 
834
+ declare const BOTON: {
835
+ readonly 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";
836
+ readonly 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";
837
+ };
171
838
  /**
172
- * Builds the antd theme for a given mode. Dark mode uses antd's
173
- * `darkAlgorithm`; brand tokens stay identical so the brand is consistent.
839
+ * Boton que abre un dialogo modal con un formulario (change `ux-listados-compactos`): saca de la vista los
840
+ * formularios de alta que ocupaban la pantalla antes del listado. Sigue el sistema de diseno 7.11: `role="dialog"`,
841
+ * `aria-modal`, titulo asociado, foco al primer campo al abrir, `Escape`, boton Cerrar y clic en el fondo cierran,
842
+ * y el foco vuelve al boton que lo abrio. El contenido (el formulario) se monta solo mientras esta abierto.
174
843
  */
175
- declare function buildTheme(mode?: ThemeMode): ThemeConfig;
176
- /** Default (light) AMS theme. */
177
- declare const amsTheme: ThemeConfig;
178
- /** Dark AMS theme. */
179
- declare const amsThemeDark: ThemeConfig;
844
+ declare function AccionConDialogo({ etiqueta, titulo, icono, variante, children, }: {
845
+ etiqueta: string;
846
+ titulo: string;
847
+ icono?: ReactNode;
848
+ variante?: keyof typeof BOTON;
849
+ children: ReactNode;
850
+ }): react.JSX.Element;
180
851
 
181
- /** Reads the initial mode: saved preference → OS preference → light. */
182
- declare function getInitialThemeMode(defaultMode?: ThemeMode): ThemeMode;
183
- /** Reflects the mode on the DOM so CSS can react (mirrors mf-container). */
184
- declare function applyThemeModeToDOM(mode: ThemeMode): void;
185
- interface ThemeModeContextValue {
186
- mode: ThemeMode;
187
- setMode: (mode: ThemeMode) => void;
188
- toggle: () => void;
189
- isDark: boolean;
190
- }
191
852
  /**
192
- * Access the current color mode and switch it. Requires an ancestor
193
- * `AmsConfigProvider`. Use it to build a light/dark toggle:
853
+ * Modal de detalle con tabla (change `listados-ajuste-viewport`, lineamiento `docs/lineamientos-ui.md` "Tablas"): el
854
+ * dialogo nunca crece mas alla de la ventana (`max-h-[90dvh]`, ancho `min(96vw, ...)`); la cabecera y el resumen no se
855
+ * encogen y la tabla (`MarcoTabla ajuste="pagina"` dentro de `children`) toma el alto restante, asi que solo ella se
856
+ * desplaza en ambos ejes con su encabezado y columnas fijas. Antes cada modal crecia con su tabla y se cortaba el pie y
857
+ * las columnas de la derecha.
194
858
  *
195
- * const { isDark, toggle } = useThemeMode();
196
- * <Switch checked={isDark} onChange={toggle} />
859
+ * `role="dialog"` + `aria-modal`, titulo asociado (`tituloId`), foco al dialogo al abrir; `Escape`, el boton Cerrar y
860
+ * el clic en el fondo cierran.
197
861
  */
198
- declare function useThemeMode(): ThemeModeContextValue;
862
+ declare function ModalPanel({ titulo, tituloId, acciones, onCerrar, etiquetaCerrar, ancho, children, }: {
863
+ /** Contenido del `<h2>` (texto, codigo, explicacion en sitio). */
864
+ titulo: ReactNode;
865
+ tituloId: string;
866
+ /** Botones junto al de cerrar (p. ej. "Descargar CSV"). */
867
+ acciones?: ReactNode;
868
+ onCerrar: () => void;
869
+ etiquetaCerrar?: string;
870
+ /** Clase de ancho maximo (Tailwind). */
871
+ ancho?: string;
872
+ children: ReactNode;
873
+ }): react.JSX.Element;
874
+
875
+ declare function Pestanas({ etiqueta, pestanas, inicial, extra, }: {
876
+ etiqueta: string;
877
+ pestanas: {
878
+ id: string;
879
+ texto: string;
880
+ contenido: ReactNode;
881
+ }[];
882
+ inicial?: string;
883
+ /** Normalmente el (i) de las pestanas, alineado al centro del grupo. */
884
+ extra?: ReactNode;
885
+ }): react.JSX.Element;
199
886
 
200
- interface ButtonProps extends ButtonProps$1 {
201
- }
202
887
  /**
203
- * AMS Button — thin wrapper over antd `Button` that inherits the AMS theme.
204
- * Exposes the full antd Button API (type, danger, loading, icon, size, etc.)
205
- * and forwards the ref so it integrates with Form and tooltips.
888
+ * Popover reusable que aparece al pasar el mouse (hover) o al enfocar con teclado (focus)
889
+ * sobre su disparador, y se oculta al salir/desenfocar. Nace del widget del tag schedule,
890
+ * pero es generico: cualquier control que quiera mostrar contenido rico al hover lo usa.
891
+ *
892
+ * Por que un componente y no el `title` nativo (unico patron previo en el sistema): el
893
+ * `title` solo muestra texto plano de una linea, no permite contenido estructurado (tabla
894
+ * de ejecuciones con iconos de estatus) ni es navegable. Este es accesible: el disparador
895
+ * es un boton focusable, el contenido se asocia por `aria-describedby` y responde a
896
+ * teclado (focus/blur), no solo a mouse.
897
+ *
898
+ * POSICIONAMIENTO `fixed` (no `absolute`): el widget vive dentro de tablas cuyo contenedor
899
+ * tiene `overflow-hidden`/`overflow-x-auto`; un popover `absolute` quedaba RECORTADO por
900
+ * ese overflow y no se veia. Con `fixed` + las coordenadas del disparador
901
+ * (`getBoundingClientRect`) el contenido flota sobre todo, fuera del flujo recortado.
902
+ *
903
+ * VIEWPORT-AWARE: `fixed` en la esquina del disparador desbordaba el viewport cerca del
904
+ * borde derecho/inferior (texto cortado e ilegible). Tras abrir se MIDE el contenido y
905
+ * `calcularPosicionPopover` lo acota al viewport (desplaza a la izquierda, abre arriba si
906
+ * no cabe abajo, limita ancho/alto con scroll interno). Se recalcula con scroll/resize y
907
+ * Escape lo cierra.
206
908
  */
207
- declare const Button: react.ForwardRefExoticComponent<ButtonProps & react.RefAttributes<HTMLButtonElement | HTMLAnchorElement>>;
909
+ declare function PopoverHover({ etiqueta, disparador, children, }: {
910
+ /** Nombre accesible del disparador (aria-label + tooltip nativo de respaldo). */
911
+ etiqueta: string;
912
+ /** Contenido visible del disparador (normalmente un icono). */
913
+ disparador: ReactNode;
914
+ /** Contenido del popover. */
915
+ children: ReactNode;
916
+ }): react.JSX.Element;
917
+
918
+ type CapacidadAcceso = {
919
+ icono: LucideIconType;
920
+ titulo: string;
921
+ descripcion: string;
922
+ };
923
+ declare function PantallaAcceso({ producto, titulo, descripcion, hrefLogin, etiquetaBoton, capacidades, logo, error, }: {
924
+ producto: string;
925
+ titulo: string;
926
+ descripcion: string;
927
+ hrefLogin: string;
928
+ etiquetaBoton?: string;
929
+ capacidades?: readonly CapacidadAcceso[];
930
+ /** Logo opcional ya renderizado (p. ej. `<Image .../>`). */
931
+ logo?: ReactNode;
932
+ /** Mensaje de error de acceso (p. ej. "Tu cuenta no tiene acceso"). Se pinta con role="alert". */
933
+ error?: string;
934
+ }): react.JSX.Element;
208
935
 
209
- /** AMS semantic tag intents mapped to brand tokens. */
210
- type TagIntent = 'success' | 'error' | 'warning' | 'info' | 'primary';
211
- interface TagProps extends TagProps$1 {
212
- /**
213
- * Semantic intent that resolves to an AMS brand color. Takes precedence over
214
- * antd's `color` when set. Formalizes the inline `#50cd89` / `#f1416c` colors
215
- * previously hardcoded in mf-boveda's DataTable.
216
- */
217
- intent?: TagIntent;
218
- }
219
936
  /**
220
- * AMS Tag — thin wrapper over antd `Tag` with an optional semantic `intent`
221
- * that maps to the brand palette. Falls back to the full antd Tag API.
937
+ * Pantalla de carga a pagina completa (cambio `ux-spinner-marca`). Se usa como
938
+ * `loading.tsx` de las rutas densas: Next.js la muestra AL INSTANTE mientras el Server
939
+ * Component hace su fetch (SSR), en vez de dejar la pantalla congelada/en blanco -- que
940
+ * es lo que hacia sentir el cambio de pantalla "muy lento" (pedido del usuario). No es
941
+ * maquillaje: el fetch tarda lo mismo, pero el usuario ve feedback inmediato de marca en
942
+ * lugar de una pantalla muerta, que es la causa real de la lentitud PERCIBIDA.
222
943
  */
223
- declare const Tag: react.ForwardRefExoticComponent<TagProps & react.RefAttributes<HTMLSpanElement>>;
944
+ declare function PantallaCargando({ etiqueta }: {
945
+ etiqueta?: string;
946
+ }): react.JSX.Element;
224
947
 
225
948
  /**
226
- * Icons — curated re-export from `@ant-design/icons`.
949
+ * Overlay de carga para ACCIONES (cambio `ux-spinner-marca`). Pedido del usuario: en cada
950
+ * accion que dispara al hacer click y consume un servicio, mostrar el spinner de marca
951
+ * llenandose. A diferencia de `loading.tsx` (navegacion entre pantallas), este cubre las
952
+ * mutaciones dentro de una pantalla (crear job, reintentar, exportar...). Se monta encima
953
+ * del contenido con un velo semitransparente y BLOQUEA la interaccion mientras `visible`.
227
954
  *
228
- * Usage:
229
- * import { DownloadOutlined, SearchOutlined } from '@amsintegra/design-system';
230
- * <Button icon={<DownloadOutlined />} />
955
+ * Uso: `{enviando && <OverlayCargando etiqueta="Creando job..." />}`.
956
+ */
957
+ declare function OverlayCargando({ etiqueta, visible, }: {
958
+ etiqueta?: string;
959
+ visible?: boolean;
960
+ }): react.JSX.Element | null;
961
+
962
+ /**
963
+ * Spinner de marca: el logo de la instalacion que se "llena" de color de abajo hacia arriba, en
964
+ * bucle (cambio `ux-spinner-marca`). Pedido explicito del usuario: entre
965
+ * cambios de pantalla y en cada accion que consume un servicio, mostrar "un spinner con el logo
966
+ * llenandose de manera gradual".
231
967
  *
232
- * This module re-exports a curated set of the most-used icons across the b2bmx
233
- * microfrontends so consumers get autocomplete from the design system barrel.
234
- * For any icon not listed here, import it directly from `@ant-design/icons`
235
- * (it stays a peer dependency and is not bundled).
968
+ * COMO FUNCIONA (solucion de raiz, sin GIF ni libreria): se pinta la MISMA imagen del logo dos
969
+ * veces superpuestas:
970
+ * 1. una capa base tenue (el logo "vacio", en gris muy claro),
971
+ * 2. una capa de color de marca recortada con `mask` a la forma del logo (`mask-image` = la
972
+ * imagen), cuya ALTURA visible sube de 0% a 100% con una animacion CSS en bucle.
973
+ * Asi el color solo aparece DENTRO de la silueta del logo y da el efecto de llenado gradual.
974
+ * Respeta `prefers-reduced-motion` (si el usuario lo pide, no anima: muestra el logo lleno y
975
+ * estatico, accesible).
236
976
  *
237
- * `IconComponent` is the shared type for an antd icon component, useful for
238
- * typing icon props on other components.
977
+ * La imagen sale de la variable CSS `--tema-logo-spinner` (la fija el layout raiz con el logo del
978
+ * producto o tenant); sin ella rige el icono de la marca por omision (`globals.css`). `tamano` en px (ancho);
979
+ * la altura se deriva del aspect ratio del logo (~120x52).
239
980
  */
240
-
241
- type IconComponent = ForwardRefExoticComponent<Omit<AntdIconProps, 'ref'>>;
981
+ declare function SpinnerMarca({ tamano, etiqueta, }: {
982
+ tamano?: number;
983
+ etiqueta?: string;
984
+ }): react.JSX.Element;
242
985
 
243
986
  /**
244
- * Context-safe access to antd's `message` API.
987
+ * Muestra un timestamp UTC en HORA LOCAL del navegador SIN romper la hidratacion
988
+ * (cambio `fix-hydration-fecha`).
989
+ *
990
+ * EL PROBLEMA (React #418): `formatearFechaHora` convierte los timestamps con sufijo UTC
991
+ * a hora local usando `new Date().getHours()` (metodos locales de Date). En el SERVIDOR
992
+ * (SSR en Lambda) la hora local es UTC; en el CLIENTE es la del navegador (p.ej. CDMX,
993
+ * UTC-6). Para el mismo instante el texto difiere -> "text content does not match
994
+ * server-rendered HTML" -> React descarta el arbol hidratado y puede romper el render.
245
995
  *
246
- * In antd v5 the static `message.success(...)` calls do **not** read the
247
- * `ConfigProvider` theme and log a warning. The supported approach is to
248
- * consume the instance provided by antd's `App` context — which
249
- * `AmsConfigProvider` already renders at the root.
996
+ * LA SOLUCION DE RAIZ (sin renunciar a la hora local que pidio el usuario): en el PRIMER
997
+ * render (SSR + primera pintura del cliente) se muestra el MISMO texto determinista para
998
+ * ambos (formato ISO legible, sin conversion), y TRAS montar (`useEffect`, solo cliente)
999
+ * se re-renderiza ya en hora local. Asi el HTML del server y el primer render del cliente
1000
+ * coinciden byte a byte (no hay mismatch), y el usuario termina viendo su hora local. No
1001
+ * es maquillaje: es el patron correcto de Next para valores dependientes del entorno del
1002
+ * cliente (timezone).
1003
+ */
1004
+ declare function FechaHoraLocal({ iso }: {
1005
+ iso: string | null | undefined;
1006
+ }): react.JSX.Element;
1007
+
1008
+ declare const ANCHOS: {
1009
+ readonly completo: "";
1010
+ readonly "2xl": "mx-auto max-w-2xl";
1011
+ readonly "3xl": "mx-auto max-w-3xl";
1012
+ readonly "4xl": "mx-auto max-w-4xl";
1013
+ };
1014
+ declare function PaginaContenido({ titulo, icono, descripcion, acciones, ancho, children, }: {
1015
+ titulo: ReactNode;
1016
+ /** Icono de 20 px (TAMANO_BOTON) antes del titulo. */
1017
+ icono?: ReactNode;
1018
+ descripcion?: ReactNode;
1019
+ /** Botones de la pantalla, alineados a la derecha del encabezado. */
1020
+ acciones?: ReactNode;
1021
+ ancho?: keyof typeof ANCHOS;
1022
+ children: ReactNode;
1023
+ }): react.JSX.Element;
1024
+
1025
+ /**
1026
+ * Pantalla de listado que cabe en la ventana (change `listados-ajuste-viewport`, lineamiento `docs/lineamientos-ui.md`
1027
+ * "Tablas"): la pagina NO se desplaza; solo el cuerpo de la tabla lo hace y el paginador y la barra horizontal quedan
1028
+ * siempre visibles al pie.
250
1029
  *
251
- * Usage:
252
- * const message = useAmsMessage();
253
- * message.success('Saved');
1030
+ * Como funciona (layout, sin numeros magicos): la columna de contenido del layout raiz toma el alto de la ventana cuando
1031
+ * contiene un `[data-pagina-listado]` (`globals.css`); esta pagina es una columna flex `flex-1 min-h-0`, la cabecera y
1032
+ * las barras no se encogen, y la tabla (`MarcoTabla ajuste="pagina"`) toma el alto restante. Cada envoltorio entre la
1033
+ * pagina y el marco lleva `CLASE_REGION_LISTADO` para no romper la cadena `min-h-0`.
254
1034
  *
255
- * Requires an ancestor `AmsConfigProvider` (or antd `App`).
1035
+ * Sin `"use client"`: la usan paginas Server Component.
256
1036
  */
257
- declare function useAmsMessage(): MessageInstance;
1037
+ /** Clases de un envoltorio entre `PaginaListado` y `MarcoTabla ajuste="pagina"` (pasa el alto restante hacia la tabla). */
1038
+ declare const CLASE_REGION_LISTADO = "flex min-h-0 flex-1 flex-col";
1039
+ declare function PaginaListado({ titulo, icono, descripcion, acciones, className, children, }: {
1040
+ titulo: ReactNode;
1041
+ /** Icono de 20 px antes del titulo (opcional). */
1042
+ icono?: ReactNode;
1043
+ /** Una linea junto al titulo; si no cabe se recorta con elipsis y el texto completo queda en el tooltip. */
1044
+ descripcion?: string;
1045
+ /** Botones o enlaces de la pantalla (a la derecha de la cabecera). */
1046
+ acciones?: ReactNode;
1047
+ className?: string;
1048
+ children: ReactNode;
1049
+ }): react.JSX.Element;
258
1050
 
259
1051
  /**
260
- * Context-safe access to antd's `notification` API.
1052
+ * Paginación CLIENT-SIDE sobre una lista ya cargada. Para listas acotadas
1053
+ * (decenas–cientos de filas) sin cursor de servidor: paginarlas en el cliente es lo proporcional.
1054
+ * Mismo patrón visual que el resto de listados (Anterior/Siguiente + tamaño de página, con iconos).
261
1055
  *
262
- * Like `useAmsMessage`, this returns the instance from antd's `App` context so
263
- * notifications inherit the AMS theme and avoid the v5 static-method warning.
264
- * Requires an ancestor `AmsConfigProvider` (or antd `App`).
1056
+ * `usePaginacionLocal` corta la lista; `PaginadorLocal` son los controles. Van juntos
1057
+ * pero separados para poder probar el corte sin renderizar la UI.
1058
+ */
1059
+ declare function usePaginacionLocal<T>(items: T[], tamanoInicial?: number): {
1060
+ itemsPagina: T[];
1061
+ paginaActual: number;
1062
+ totalPaginas: number;
1063
+ tamano: number;
1064
+ totalItems: number;
1065
+ siguiente: () => void;
1066
+ anterior: () => void;
1067
+ cambiarTamano: (n: number) => void;
1068
+ };
1069
+ declare function PaginadorLocal({ paginaActual, totalPaginas, totalItems, tamano, tamanos, onAnterior, onSiguiente, onCambiarTamano, }: {
1070
+ paginaActual: number;
1071
+ totalPaginas: number;
1072
+ totalItems: number;
1073
+ tamano: number;
1074
+ /** Tamanos ofrecidos (por omision 10/25/50/100). Los listados por URL usan 25/50/100. */
1075
+ tamanos?: readonly number[];
1076
+ onAnterior: () => void;
1077
+ onSiguiente: () => void;
1078
+ /** Sin este callback no se pinta el selector de tamano (p. ej. cuando vive en `BarraListado`). */
1079
+ onCambiarTamano?: (n: number) => void;
1080
+ }): react.JSX.Element | null;
1081
+
1082
+ /**
1083
+ * Paginador de un listado cuyo estado vive en la URL (change `ux-listados-compactos`). Reusa los controles de
1084
+ * `PaginadorLocal` (mismo aspecto que los demas grids); solo cambia de donde sale la pagina: `?pagina=N`. El
1085
+ * tamano de pagina se elige en `BarraListado`, por eso aqui no se pinta su selector. Al cambiar de pagina se
1086
+ * regresa al inicio de la pantalla (`scroll: true`).
1087
+ */
1088
+ declare function PaginadorUrl({ pagina, totalPaginas, totalItems, tamano, }: {
1089
+ pagina: number;
1090
+ totalPaginas: number;
1091
+ totalItems: number;
1092
+ tamano: number;
1093
+ }): react.JSX.Element | null;
1094
+
1095
+ type FiltroListado = {
1096
+ tipo?: "seleccion";
1097
+ clave: string;
1098
+ etiqueta: string;
1099
+ /** La primera opcion suele ser "Todos" con `valor: ""` (sin filtro). */
1100
+ opciones: {
1101
+ valor: string;
1102
+ etiqueta: string;
1103
+ }[];
1104
+ } | {
1105
+ tipo: "numero";
1106
+ clave: string;
1107
+ etiqueta: string;
1108
+ min?: number;
1109
+ max?: number;
1110
+ };
1111
+ /**
1112
+ * Barra de un listado (change `ux-listados-compactos`): busqueda de texto, filtros de la pantalla,
1113
+ * tamano de pagina y conteo. Todo vive en la URL (`useNavegarListado`), asi que un enlace copiado reproduce la
1114
+ * misma vista; cualquier cambio regresa a la pagina 1.
265
1115
  *
266
- * Usage:
267
- * const notification = useAmsNotification();
268
- * notification.success({ message: 'Done', description: 'Saved.' });
1116
+ * La busqueda espera 300 ms sin teclear (o `Enter`) y navega UNA vez. Vive en su propio `<form role="search">`
1117
+ * con `preventDefault`: `Enter` aqui nunca envia otro formulario de la pantalla. `Escape` o el boton X limpian.
1118
+ * Los filtros de seleccion aplican al elegir; los numericos al salir del campo o con `Enter`.
269
1119
  */
270
- declare function useAmsNotification(): NotificationInstance;
1120
+ declare function BarraListado({ filtros, totalFiltrado, total, placeholder, etiquetaBusqueda, extra, }: {
1121
+ filtros: FiltroListado[];
1122
+ totalFiltrado: number;
1123
+ total: number;
1124
+ placeholder?: string;
1125
+ /** Rotulo (label) del campo de busqueda. */
1126
+ etiquetaBusqueda?: string;
1127
+ /** Controles adicionales a la derecha (p. ej. alternar vista tabla/tarjetas). */
1128
+ extra?: ReactNode;
1129
+ }): react.JSX.Element;
271
1130
 
272
1131
  /**
273
- * Translatable text labels for the pagination control. The design system is
274
- * i18n-agnostic: the consuming app passes already-translated strings. Anything
275
- * omitted falls back to antd's `locale` (or English defaults).
1132
+ * Encabezado ordenable de un listado por URL (change `ux-listados-compactos`; sistema de diseno 7.3). El `th`
1133
+ * lleva `aria-sort`; el boton alterna asc -> desc -> orden por omision de la pantalla (borra `orden`/`dir`) y escribe `orden`/`dir` en la URL, asi
1134
+ * que ordena TODO el resultado filtrado (no solo la pagina visible). La explicacion (i) va fuera del boton.
276
1135
  */
277
- interface PaginationLabels {
278
- /** Suffix in the page-size selector, e.g. "/ página". */
279
- itemsPerPage?: string;
280
- /** "Ir a" label of the quick jumper. */
281
- jumpTo?: string;
282
- /** Confirm button text of the quick jumper. */
283
- jumpToConfirm?: string;
284
- /** Accessible label for a page, e.g. "Página". */
285
- page?: string;
286
- /** Accessible label for the previous-page button. */
287
- prevPage?: string;
288
- /** Accessible label for the next-page button. */
289
- nextPage?: string;
290
- /** Label for the page-size selector, e.g. "Tamaño de página". */
291
- pageSize?: string;
292
- /**
293
- * Builds the total-records text (rendered before the pages).
294
- * Receives the total and the current [from, to] range.
295
- * e.g. (total) => `Total ${total} registros`. Takes precedence over `totalText`.
296
- */
297
- total?: (total: number, range: [number, number]) => ReactNode;
298
- /**
299
- * Declarative total text as separate translated words, matching how the
300
- * mf-boveda table builds it: `{prefix} {total} {suffix}` → "Total 250 registros".
301
- * Set `showRange` to render "{prefix} {from}-{to} {suffix}" instead.
302
- * Ignored when `total` (the function form) is provided.
303
- */
304
- totalText?: {
305
- /** Word(s) before the number, e.g. "Total". */
306
- prefix?: string;
307
- /** Word(s) after the number, e.g. "registros". */
308
- suffix?: string;
309
- /** Use the "from-to" range instead of just the total. Default false. */
310
- showRange?: boolean;
311
- };
312
- /** Visible text for the "previous" button (overrides the arrow). */
313
- previousText?: ReactNode;
314
- /** Visible text for the "next" button (overrides the arrow). */
315
- nextText?: ReactNode;
316
- }
317
- interface PaginationProps extends PaginationProps$1 {
318
- /** Translatable text labels. */
319
- labels?: PaginationLabels;
320
- }
321
- /**
322
- * AMS Pagination — antd `Pagination` with translatable text via a single
323
- * `labels` prop (page, records/total, previous/next, items-per-page, jumper).
324
- * The rest of the antd Pagination API passes through. `showTotal` and
325
- * `itemRender` still work if you prefer to set them directly; explicit
326
- * `showTotal`/`itemRender`/`locale` props win over `labels`.
327
- */
328
- declare function Pagination({ labels, showTotal, itemRender, locale, ...rest }: PaginationProps): react.JSX.Element;
329
-
330
- type CardComponent = react.ForwardRefExoticComponent<CardProps & react.RefAttributes<HTMLDivElement>> & {
331
- Grid: (typeof Card$1)['Grid'];
332
- Meta: (typeof Card$1)['Meta'];
1136
+ declare function EncabezadoOrdenUrl({ clave, etiqueta, icono, info, ordenActual, dirActual, alineado, celda, }: {
1137
+ clave: string;
1138
+ etiqueta: string;
1139
+ icono?: ReactNode;
1140
+ info: ExplicacionId;
1141
+ ordenActual: string;
1142
+ dirActual: Direccion;
1143
+ alineado?: "left" | "right";
1144
+ /** Atributos del marco de tablas para el `th`: `{...fija("izq", 0)}` o `{...col("id")}` (change `tablas-columnas-fijas`). */
1145
+ celda?: Record<string, string | number | undefined>;
1146
+ }): react.JSX.Element;
1147
+
1148
+ /** Envuelve un arbol que se exporta (PDF/HTML): sus tablas conservan el layout original. */
1149
+ declare function TablaPlana({ children }: {
1150
+ children: ReactNode;
1151
+ }): react.JSX.Element;
1152
+ declare function UsuarioTablas({ usuario, children }: {
1153
+ usuario?: string | null;
1154
+ children: ReactNode;
1155
+ }): react.JSX.Element;
1156
+ type ColumnaOcultable = {
1157
+ id: string;
1158
+ etiqueta: string;
333
1159
  };
334
- declare const Card: CardComponent;
335
-
336
- interface ThemeToggleProps extends Omit<SwitchProps, 'checked' | 'onChange'> {
337
- }
338
- /**
339
- * AMS ThemeToggle — a ready-made light/dark switch wired to `useThemeMode`.
340
- * Requires an ancestor `AmsConfigProvider` that manages the mode
341
- * (i.e. rendered without a controlled `mode` prop).
342
- */
343
- declare function ThemeToggle(props: ThemeToggleProps): react.JSX.Element;
344
-
345
- /**
346
- * Labels for the DataTable. The design system is i18n-agnostic: the consuming
347
- * microfrontend passes translated strings from its own catalog. Sensible
348
- * English defaults are provided so the table renders without wiring.
349
- */
350
- interface DataTableLabels {
351
- emptyText?: string;
352
- sortAsc?: string;
353
- sortDesc?: string;
354
- cancelSort?: string;
355
- }
356
- interface DataTableProps<T extends object = Record<string, unknown>> extends Omit<TableProps<T>, 'title' | 'loading'> {
357
- /** Optional plain-text heading rendered above the table. */
358
- heading?: string;
359
- /** Extra content (buttons, filters) rendered above the table. */
360
- extra?: React.ReactNode;
361
- /** External loading state. Renders a skeleton placeholder while true. */
362
- loading?: boolean;
363
- /** Translated labels; falls back to English defaults. */
364
- labels?: DataTableLabels;
1160
+ /**
1161
+ * `pagina`: la tabla es el contenido principal de una pantalla de listado (`PaginaListado`) y toma el alto restante.
1162
+ * `acotado`: la tabla vive dentro de una pagina que se desplaza; su alto maximo se acota (`--marco-alto`, default 70dvh).
1163
+ */
1164
+ type AjusteMarco = "pagina" | "acotado";
1165
+ declare function MarcoTabla({ clave, etiqueta, columnas, barra, alto, ajuste, pie, controles, className, clasePlana, children, }: {
1166
+ /** Id estable de la tabla (persistencia): `modulo.tabla`. */
1167
+ clave: string;
1168
+ /** Nombre accesible de la region desplazable. */
1169
+ etiqueta: string;
1170
+ /** Columnas que el usuario puede ocultar (las que llevan `col(id)`). Sin ellas no hay menu "Columnas". */
1171
+ columnas?: ColumnaOcultable[];
1172
+ /** Controles propios de la tabla que van en la misma barra (a la izquierda). */
1173
+ barra?: ReactNode;
1174
+ /** Alto maximo del marco en el ajuste `acotado` (CSS). Default `70dvh`, nunca menos de 18rem. */
1175
+ alto?: string;
1176
+ /** `pagina` en pantallas de listado (la pagina no se desplaza, solo el cuerpo); `acotado` (default) en el resto. */
1177
+ ajuste?: AjusteMarco;
1178
+ /** Pie del marco (paginador): fila `shrink-0` bajo la region desplazable, siempre visible. */
1179
+ pie?: ReactNode;
1180
+ /** `false` oculta la barra (densidad/columnas) en tablas minimas; el marco y las columnas fijas se mantienen. */
1181
+ controles?: boolean;
1182
+ className?: string;
1183
+ /** Clases del contenedor bajo `TablaPlana` (exportaciones): las que tenia la tabla antes del marco, para no alterar su layout. */
1184
+ clasePlana?: string;
1185
+ children: ReactNode;
1186
+ }): react.JSX.Element;
1187
+
1188
+ /**
1189
+ * Columna de una tabla configurable. `id` es estable (se usa para persistir orden/ancho);
1190
+ * `encabezado` es el contenido del <th> (texto + icono); `celda` recibe la fila y devuelve
1191
+ * el contenido del <td>. `alineado` afecta th y td. `minAncho` en px (default 80).
1192
+ * `fijaAncho`: si true, la columna respeta su ancho (util para UUID que debe verse
1193
+ * completo); si false/omitido, crece con el contenido salvo que el usuario la redimensione.
1194
+ */
1195
+ type ColumnaConfig<T> = {
1196
+ id: string;
1197
+ encabezado: ReactNode;
1198
+ /** Version del encabezado para el menu de columnas (que vive dentro de un <button>): sin controles
1199
+ * interactivos anidados, como el icono de explicacion en sitio. Si se omite se usa `encabezado`. */
1200
+ encabezadoMenu?: ReactNode;
365
1201
  /**
366
- * Translatable pagination text (total/records, previous/next, page-size,
367
- * jumper). Applied to the table's pagination — matches the mf-boveda pattern
368
- * of a "{prefix} {total} {suffix}" total and translated prev/next buttons.
369
- * Merged into `pagination`; anything set directly on `pagination`
370
- * (`showTotal`/`itemRender`/`locale`) wins.
1202
+ * Explicacion en sitio de la columna (catalogo `lib/explicaciones.ts`). Se pinta FUERA del boton de orden
1203
+ * (sin controles anidados) y no aparece en el menu de columnas. Obligatoria por lineamiento
1204
+ * (docs/lineamientos-ui.md): la compuerta `cobertura-explicaciones.test.ts` la exige.
371
1205
  */
372
- paginationLabels?: PaginationLabels;
1206
+ info?: ExplicacionId;
1207
+ celda: (fila: T) => ReactNode;
1208
+ alineado?: "left" | "right";
1209
+ /** Ancho inicial en px (antes de que el usuario redimensione). Default 160. */
1210
+ anchoDefault?: number;
373
1211
  /**
374
- * Opt-in: render numeric values in the first column as colored tags
375
- * (green when >= 0, red when < 0). Off by default — this replaces the
376
- * implicit column-0 behavior of the original mf-boveda DataTable, which
377
- * was surprising. Explicitly enable it per table when desired.
1212
+ * Si true, el encabezado se vuelve un boton que ordena la PAGINA VISIBLE por esta
1213
+ * columna (client-side, sobre las filas ya cargadas). Es un orden POR PAGINA, no
1214
+ * global -- la aria-label lo declara explicitamente para no confundir con el orden
1215
+ * global por fecha (que va por URL, filtros por URL). Requiere
1216
+ * `valorOrden` para saber por que valor comparar.
378
1217
  */
379
- firstColumnNumericTag?: boolean;
380
- }
381
- declare function DataTable<T extends object = Record<string, unknown>>({ heading, extra, loading, labels, paginationLabels, firstColumnNumericTag, columns, dataSource, scroll, bordered, pagination, className, ...rest }: DataTableProps<T>): react.JSX.Element;
382
-
383
- type TriggerRenderer = (open: () => void) => ReactNode;
384
- interface ModalDialogProps extends Omit<ModalProps, 'open' | 'children'> {
385
- /** Controlled open state. */
386
- open?: boolean;
387
- /** Initial open state in uncontrolled mode. */
388
- defaultOpen?: boolean;
389
- /** Node or render-prop that opens the modal when clicked. */
390
- trigger?: ReactNode | TriggerRenderer;
391
- /** Close automatically after `onOk` resolves. Default true. */
392
- closeOnOk?: boolean;
393
- /** Close automatically after `onCancel`. Default true. */
394
- closeOnCancel?: boolean;
395
- /** Notified whenever the open state changes (controlled or not). */
396
- onOpenChange?: (next: boolean) => void;
397
- children?: ReactNode;
398
- }
1218
+ ordenable?: boolean;
1219
+ /** Valor por el que ordenar cuando `ordenable`. String -> orden alfabetico
1220
+ * (localeCompare); number -> orden numerico. Ausente/undefined -> al final. */
1221
+ valorOrden?: (fila: T) => string | number | undefined;
1222
+ /** Etiqueta legible para la aria-label del boton de orden (ej. "Monto"). Si se
1223
+ * omite y `encabezado` es un string, se usa ese; si no, "esta columna". */
1224
+ etiquetaOrden?: string;
1225
+ };
399
1226
  /**
400
- * AMS ModalDialog — a controllable modal composite.
1227
+ * Tabla con columnas REORDENABLES (arrastrar el encabezado), REDIMENSIONABLES (arrastrar
1228
+ * el borde derecho del encabezado) y con menu de mostrar/ocultar columnas. Las
1229
+ * preferencias persisten en localStorage por `clavePrefs` (ver preferenciasTabla.ts).
1230
+ * Lineamiento del sistema: cualquier tabla puede usar este componente.
401
1231
  *
402
- * Ports mf-boveda's ReusableModal API:
403
- * - controlled (`open`) or uncontrolled (`defaultOpen`) state,
404
- * - a `trigger` node or render-prop that opens it,
405
- * - `closeOnOk` / `closeOnCancel` with async `onOk` support (waits for the
406
- * returned promise before closing).
1232
+ * Drag & drop nativo (HTML5 draggable) y resize con eventos de mouse -- sin dependencias
1233
+ * externas. Accesible: el asa de arrastre tiene aria-label; el menu de columnas es de
1234
+ * checkboxes.
407
1235
  *
408
- * All other antd Modal props pass through.
1236
+ * Change `tablas-columnas-fijas`: se pinta dentro de `MarcoTabla` (desplazamiento acotado, encabezado fijo, densidad).
1237
+ * `columnaFija` (casilla) e `idsFijos` (identidad: codigo, nombre...) quedan fijas a la izquierda y no se pueden
1238
+ * arrastrar ni ocultar; `columnaAcciones` queda fija a la derecha.
409
1239
  */
410
- declare function ModalDialog({ trigger, children, open, defaultOpen, closeOnOk, closeOnCancel, onOk, onCancel, onOpenChange, ...modalProps }: ModalDialogProps): react.JSX.Element;
1240
+ declare function TablaConfigurable<T>({ columnas, filas, claveFila, clavePrefs, columnaFija, columnaAcciones, idsFijos, etiqueta, mensajeVacio, ajuste, pie, barraExtra, }: {
1241
+ columnas: ColumnaConfig<T>[];
1242
+ filas: T[];
1243
+ claveFila: (fila: T) => string;
1244
+ clavePrefs: string;
1245
+ /** Contenido opcional de una primera columna FIJA no reordenable (ej. checkbox). */
1246
+ columnaFija?: {
1247
+ encabezado?: ReactNode;
1248
+ celda: (fila: T) => ReactNode;
1249
+ };
1250
+ /** Contenido opcional de una ultima columna FIJA no reordenable (ej. acciones). */
1251
+ columnaAcciones?: {
1252
+ encabezado?: ReactNode;
1253
+ celda: (fila: T) => ReactNode;
1254
+ };
1255
+ /** Ids de columnas de identidad fijas a la izquierda (en este orden), despues de `columnaFija`. */
1256
+ idsFijos?: string[];
1257
+ /** Nombre accesible de la region desplazable. */
1258
+ etiqueta?: string;
1259
+ mensajeVacio?: ReactNode;
1260
+ /** Ajuste del marco: `pagina` en pantallas de listado (`PaginaListado`), `acotado` (default) en el resto. */
1261
+ ajuste?: AjusteMarco;
1262
+ /** Pie del marco (paginador), siempre visible bajo la tabla. */
1263
+ pie?: ReactNode;
1264
+ /** Controles de la pantalla que van en la misma barra de la tabla (p. ej. el indicador en vivo): ahorra una fila. */
1265
+ barraExtra?: ReactNode;
1266
+ }): react.JSX.Element;
411
1267
 
412
- interface FilterOption {
413
- value: string;
414
- label: ReactNode;
415
- disabled?: boolean;
416
- }
417
- interface FilterSelectProps extends Omit<SelectProps<string>, 'options' | 'filterOption'> {
418
- options: FilterOption[];
419
- /** Enable client-side search with accent-insensitive matching. */
420
- showSearch?: boolean;
421
- /** Override the default accent-insensitive filter. */
422
- filterOption?: SelectProps<string>['filterOption'];
423
- }
424
- /**
425
- * AMS FilterSelect — a Select preset for dashboard filters.
426
- *
427
- * Ports mf-boveda's FilterSelect: accent-insensitive search over both the
428
- * option label and value, full-width by default. i18n is the consumer's
429
- * responsibility (pass already-translated labels).
430
- */
431
- declare function FilterSelect({ options, showSearch, filterOption, className, style, ...rest }: FilterSelectProps): react.JSX.Element;
432
-
433
- type UploadMessage = string | ((fileName: string) => string);
434
- type UploadChangeInfo = Parameters<NonNullable<UploadProps['onChange']>>[0];
435
- interface FileUploadDraggerProps extends Omit<UploadProps, 'onChange'> {
436
- /** Success toast text or a builder receiving the file name. */
437
- successMessage?: UploadMessage;
438
- /** Error toast text or a builder receiving the file name. */
439
- errorMessage?: UploadMessage;
440
- /** Show success/error toasts on upload status changes. Default true. */
441
- showStatusMessages?: boolean;
442
- /** Prompt text shown inside the drop area (when no children given). */
443
- hintText?: ReactNode;
444
- onUploadSuccess?: (info: UploadChangeInfo) => void;
445
- onUploadError?: (info: UploadChangeInfo) => void;
446
- onChange?: UploadProps['onChange'];
447
- children?: ReactNode;
448
- }
449
- /**
450
- * AMS FileUploadDragger — drag-and-drop uploader.
451
- *
452
- * Ports mf-boveda's FileUploadDragger with two DS improvements:
453
- * - toasts use the context-safe `useAmsMessage()` (no antd v5 static warning),
454
- * - all copy is passed via props (i18n stays in the consumer); no default
455
- * upload endpoint is baked in.
456
- */
457
- declare function FileUploadDragger({ successMessage, errorMessage, showStatusMessages, hintText, onUploadSuccess, onUploadError, onChange: externalOnChange, children, ...uploadProps }: FileUploadDraggerProps): react.JSX.Element;
458
-
459
- interface BreadcrumbItem {
460
- title: ReactNode;
461
- href?: string;
462
- }
463
- interface PageHeaderProps {
464
- /** Page title. Rendered as an h1. */
465
- title: ReactNode;
466
- /** Breadcrumb trail. When omitted, no breadcrumb is shown. */
467
- breadcrumbs?: BreadcrumbItem[];
468
- /** Breadcrumb separator. Defaults to ">". */
469
- separator?: ReactNode;
470
- /** Uppercase the title (matches the b2bmx convention). Default true. */
471
- uppercaseTitle?: boolean;
472
- /** Content aligned to the right of the title (actions). */
473
- extra?: ReactNode;
474
- className?: string;
475
- }
476
1268
  /**
477
- * AMS PageHeader — page title with an optional breadcrumb.
478
- *
479
- * Consolidates mf-boveda's Header + Breadcrums. Decoupled from react-router
480
- * and the boveda domain: the consumer builds the breadcrumb items (already
481
- * translated) and passes them in.
1269
+ * Campos de filtro compartidos por todos los buscadores: mismo aspecto, mismas etiquetas con icono y `label` asociado. Son
1270
+ * NO controlados (`defaultValue`): el formulario lee los valores con `FormData` al enviar.
482
1271
  */
483
- declare function PageHeader({ title, breadcrumbs, separator, uppercaseTitle, extra, className, }: PageHeaderProps): react.JSX.Element;
1272
+ /** Etiqueta de encabezado (icono + texto) para las columnas de la tabla configurable.
1273
+ * Ya NO envuelve un <th> (eso lo pone TablaConfigurable): es solo el contenido. */
1274
+ declare function EtiquetaCol({ icono: Icono, texto, info, }: {
1275
+ icono?: LucideIconType;
1276
+ texto: string;
1277
+ /** Explicacion en sitio del encabezado (catalogo `lib/explicaciones.ts`). */
1278
+ info?: ExplicacionId;
1279
+ }): react.JSX.Element;
1280
+ declare function Campo({ id, name, etiqueta, defaultValue, tipo, icono: Icono, }: {
1281
+ id: string;
1282
+ name: string;
1283
+ etiqueta: string;
1284
+ defaultValue: string;
1285
+ tipo?: string;
1286
+ icono?: LucideIconType;
1287
+ }): react.JSX.Element;
1288
+ declare function CampoSelect({ id, name, etiqueta, defaultValue, opciones, icono: Icono, }: {
1289
+ id: string;
1290
+ name: string;
1291
+ etiqueta: string;
1292
+ defaultValue: string;
1293
+ opciones: {
1294
+ valor: string;
1295
+ etiqueta: string;
1296
+ }[];
1297
+ icono?: LucideIconType;
1298
+ }): react.JSX.Element;
1299
+
1300
+ declare function IconoConEtiqueta({ Icono, texto, info }: {
1301
+ Icono: LucideIconType;
1302
+ texto: ReactNode;
1303
+ info?: ExplicacionId;
1304
+ }): react.JSX.Element;
1305
+ declare function MetricaKpi({ etiqueta, valor, icono: Icono, destacada, sub, progreso, info, }: {
1306
+ etiqueta: string;
1307
+ valor: string | number;
1308
+ icono: LucideIconType;
1309
+ info: ExplicacionId;
1310
+ destacada?: boolean;
1311
+ sub?: string;
1312
+ progreso?: {
1313
+ porcentaje: number;
1314
+ etiqueta: string;
1315
+ };
1316
+ }): react.JSX.Element;
1317
+ /** Subtitulo de un grupo de metricas, para que las cajitas se lean agrupadas por concepto en vez de un mar plano. */
1318
+ declare function GrupoMetricas({ titulo, icono: Icono, children }: {
1319
+ titulo: string;
1320
+ icono: LucideIconType;
1321
+ children: ReactNode;
1322
+ }): react.JSX.Element;
1323
+ /** Rejilla de KPI de la plataforma (extraida de `riesgo-credito/piezas.tsx`): 1 col movil, 2 `sm`, 4 `lg`. */
1324
+ declare function RejillaMetricas({ children }: {
1325
+ children: ReactNode;
1326
+ }): react.JSX.Element;
1327
+ /** Rotulo de un bloque o grafica con su (i) (extraido de `riesgo-credito/piezas.tsx`). */
1328
+ declare function Rotulo({ texto, info }: {
1329
+ texto: string;
1330
+ info: ExplicacionId;
1331
+ }): react.JSX.Element;
484
1332
 
485
- interface DownloadButtonProps extends ButtonProps {
486
- /** Button label. Defaults to "CSV". */
487
- label?: React.ReactNode;
488
- }
489
1333
  /**
490
- * AMS DownloadButton — a Button preset for download actions.
491
- *
492
- * Ports mf-boveda's DownloadButton: primary type + download icon + label,
493
- * with the full Button API available. i18n via the `label`/`children` props.
1334
+ * Atributos de celda del marco de tablas (change `tablas-columnas-fijas`). SIN "use client": las paginas Server
1335
+ * Component llaman `fija()` / `col()` y pintan `CeldaIdentidad` al armar su `<table>` (una funcion exportada desde un
1336
+ * modulo cliente no se puede llamar en el servidor). El comportamiento vive en `MarcoTabla.tsx` y `app/globals.css`.
494
1337
  */
495
- declare const DownloadButton: react.ForwardRefExoticComponent<DownloadButtonProps & react.RefAttributes<HTMLButtonElement | HTMLAnchorElement>>;
496
-
497
- interface ConfirmModalProps extends Omit<ModalDialogProps, 'children'> {
498
- /** Body message shown to the user. */
499
- message?: ReactNode;
500
- /** Mark the confirm action as destructive (red primary button). */
501
- danger?: boolean;
502
- children?: ReactNode;
503
- }
1338
+ type AtributosFija = {
1339
+ "data-fija": "izq" | "der";
1340
+ "data-fija-idx"?: number;
1341
+ "data-fija-primaria"?: "";
1342
+ };
504
1343
  /**
505
- * AMS ConfirmModal — a confirm/cancel dialog preset built on `ModalDialog`.
506
- *
507
- * Generalizes the mf-boveda cancel/confirm modals (CancelCfdiModal, etc.):
508
- * inherits controlled/uncontrolled state, trigger, and async `onOk` from
509
- * ModalDialog. Set `danger` for destructive actions. Copy via props (i18n).
1344
+ * Marca una celda (`th` o `td`) como fija. `izq` lleva el indice de la columna fija (0, 1, 2, 3, en orden de izquierda a
1345
+ * derecha); la 0 es la columna primaria salvo `{ primaria: true }` en otra (p. ej. cuando la 0 es una casilla). La
1346
+ * primaria es la unica que sigue fija en pantallas angostas. Se aplica igual en el encabezado y en cada fila.
510
1347
  */
511
- declare function ConfirmModal({ message, danger, okButtonProps, children, ...rest }: ConfirmModalProps): react.JSX.Element;
1348
+ declare function fija(lado: "izq" | "der", idx?: number, opciones?: {
1349
+ primaria?: boolean;
1350
+ }): AtributosFija;
1351
+ /** Marca una celda como parte de la columna ocultable `id` (el mismo id que se declara en `columnas`). */
1352
+ declare function col(id: string): {
1353
+ "data-col": string;
1354
+ };
1355
+ /** Texto de identidad largo (razon social): una linea con elipsis y el texto completo como tooltip. */
1356
+ declare function CeldaIdentidad({ texto, className }: {
1357
+ texto: string | null | undefined;
1358
+ className?: string;
1359
+ }): react.JSX.Element;
1360
+ /**
1361
+ * Estilo unico de una accion de fila con icono + texto corto (enlace o boton), en linea o dentro del menu "⋯" de
1362
+ * `AccionesFila` (change `avance-rfc-acciones-compactas`; antes vivia solo en Analitica).
1363
+ */
1364
+ declare const 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";
512
1365
 
513
- interface UseControllableStateOptions<T> {
514
- /** Controlled value. When defined, the hook is in controlled mode. */
515
- value?: T;
516
- /** Initial value for uncontrolled mode. */
517
- defaultValue: T;
518
- /** Called on every change (both modes). */
519
- onChange?: (next: T) => void;
520
- }
521
1366
  /**
522
- * Supports the controlled/uncontrolled pattern used across the design system
523
- * (mirrors mf-boveda's ReusableModal state handling). When `value` is provided
524
- * the component is controlled; otherwise internal state is used.
1367
+ * Celda compacta de acciones por fila (change `tablas-columnas-fijas`). Hasta 2 acciones se pintan en linea (botones de
1368
+ * icono con `title`/`aria-label`, o enlaces cortos); con mas de 2, un solo boton "..." abre un menu. El menu es
1369
+ * `position: fixed` y vive en un portal en `body` (calculado del boton) para no quedar recortado por el marco desplazable ni
1370
+ * debajo de otras celdas fijas. Escape, clic fuera o elegir una accion lo cierran; si la accion abre un dialogo
1371
+ * (`aria-modal`), el menu sigue montado hasta que el dialogo se cierra (desmontarlo cerraria el dialogo). Va dentro de la
1372
+ * celda fija derecha (`fija("der")`).
525
1373
  */
526
- declare function useControllableState<T>({ value, defaultValue, onChange, }: UseControllableStateOptions<T>): [T, (next: T) => void];
1374
+ declare function AccionesFila({ etiqueta, children, }: {
1375
+ etiqueta?: string;
1376
+ children: ReactNode;
1377
+ }): react.JSX.Element;
1378
+ /**
1379
+ * Accion de fila con icono + texto corto y, opcional, su (i) al lado (change `avance-rfc-acciones-compactas`). Sirve en
1380
+ * linea y dentro del menu "⋯" de `AccionesFila` con el mismo aspecto (`CLASE_ACCION_FILA`). `disabled` mientras la
1381
+ * accion corre; el spinner y el resultado los pinta la fila, porque el menu se cierra al elegir.
1382
+ */
1383
+ declare function BotonAccionFila({ icono: Icono, etiqueta, ariaLabel, onClick, disabled, info, }: {
1384
+ icono: LucideIconType;
1385
+ etiqueta: string;
1386
+ ariaLabel?: string;
1387
+ onClick: () => void;
1388
+ disabled?: boolean;
1389
+ info?: Parameters<typeof InfoExplicacion>[0]["id"];
1390
+ }): react.JSX.Element;
527
1391
 
528
- export { AmsConfigProvider, type AmsConfigProviderProps, type BreadcrumbItem, Button, type ButtonProps, Card, ConfirmModal, type ConfirmModalProps, DataTable, type DataTableLabels, type DataTableProps, DownloadButton, type DownloadButtonProps, FileUploadDragger, type FileUploadDraggerProps, type FilterOption, FilterSelect, type FilterSelectProps, type IconComponent, ModalDialog, type ModalDialogProps, PageHeader, type PageHeaderProps, Pagination, type PaginationLabels, type PaginationProps, Tag, type TagIntent, type TagProps, type ThemeMode, type ThemeModeContextValue, ThemeToggle, type ThemeToggleProps, type UseControllableStateOptions, amsTheme, amsThemeDark, applyThemeModeToDOM, buildTheme, getInitialThemeMode, primitives, radius, semantic, sizing, typography, useAmsMessage, useAmsNotification, useControllableState, useThemeMode };
1392
+ export { AccionConDialogo, AccionesFila, type AjusteMarco, Aviso, type AvisoAccion, 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, type CambiosListado, Campo, CampoSelect, type CapacidadAcceso, CascaronApp, CeldaIdentidad, type ColumnaConfig, type ColumnaOcultable, type DefListado, type Direccion, ETIQUETAS_SEMAFORO, EXPLICACIONES, EncabezadoOrdenUrl, EnlaceNav, type EntradaPosicion, type EstadoListado, EstadoVacio, EstadoVacioFila, EtiquetaCol, type Explicacion, type ExplicacionId, FechaHoraLocal, type FiltroListado, GrupoMetricas, type GrupoNavegacion, 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, type LinkBaseProps, type LinkComponent, LinkComponentProvider, type ListadoNav, ListadoNavProvider, type LucideIconType, MarcoTabla, Metrica, MetricaKpi, Migas, ModalPanel, NOMBRE_PRODUCTO_DEFAULT, NO_DISPONIBLE, NoDisponible, type OpcionesListado, OverlayCargando, PaginaContenido, PaginaListado, PaginadorLocal, PaginadorUrl, PantallaAcceso, PantallaCargando, type ParamsUrl, Pestanas, PopoverHover, type PosicionPopover, type RectLike, RejillaMetricas, Rotulo, SeccionNav, SidebarColapsable, SpinnerMarca, SubNav, TAMANOS_LISTADO, TAMANO_BADGE, TAMANO_BOTON, TAMANO_LISTADO_DEFAULT, TEMA_DEFAULT, TablaConfigurable, TablaPlana, Tarjeta, type Tema, ThInfo, type Tono, 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 };