adverich-kun-ui 0.1.581 → 0.1.583

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/AGENTS.md CHANGED
@@ -264,28 +264,248 @@ Botones de radio.
264
264
 
265
265
  ### KunTable
266
266
 
267
- Tabla con ordenamiento, paginación y selección.
267
+ Tabla de datos avanzada con paginación, ordenamiento, filtrado y selección.
268
268
 
269
269
  ```vue
270
- <KunTable
271
- :items="data"
272
- :headers="headers"
273
- :searchable="true"
274
- :show-select="true"
275
- v-model:selectedItems="selected"
276
- />
270
+ <template>
271
+ <KunTable
272
+ :items="usuarios"
273
+ :headers="headers"
274
+ :searchable="true"
275
+ :filterable="true"
276
+ :show-select="true"
277
+ v-model:selectedItems="seleccionados"
278
+ @update:sortBy="handleSort"
279
+ >
280
+ <template #item.actions="{ item }">
281
+ <KunBtn icon="mdi-pencil" size="xs" />
282
+ <KunBtn icon="mdi-delete" size="xs" />
283
+ </template>
284
+ </KunTable>
285
+ </template>
286
+
287
+ <script setup>
288
+ import { ref } from 'vue'
289
+
290
+ const usuarios = ref([...])
291
+
292
+ const headers = [
293
+ { key: 'nombre', value: 'nombre', label: 'Nombre', sortable: true },
294
+ { key: 'email', value: 'email', label: 'Email', sortable: true },
295
+ { key: 'rol', value: 'rol', label: 'Rol', sortable: true },
296
+ { key: 'estado', value: 'estado', label: 'Estado' },
297
+ ]
298
+
299
+ const seleccionados = ref([])
300
+
301
+ const handleSort = (sortBy) => {
302
+ console.log('Ordenar por:', sortBy)
303
+ }
304
+ </script>
277
305
  ```
278
306
 
279
307
  | Prop | Tipo | Default | Descripción |
280
308
  |------|------|---------|-------------|
281
309
  | items | Array | [] | Datos a mostrar |
282
- | headers | Array | [] | Configuración de columnas |
283
- | searchable | Boolean | false | Habilita búsqueda |
284
- | showSelect | Boolean | false | Muestra checkboxes |
310
+ | headers | Array | [] | Configuración de columnas (ver estructura abajo) |
311
+ | selectedItems | Array | [] | v-model: Items seleccionados |
312
+ | searchable | Boolean | false | Habilita barra de búsqueda global |
313
+ | search | String | '' | v-model: Término de búsqueda |
314
+ | filterable | Boolean | false | Habilita filtros avanzados por columna |
315
+ | filters | Array | [] | Configuración de filtros (ver estructura abajo) |
316
+ | showSelect | Boolean | false | Muestra checkboxes de selección |
285
317
  | showExpand | Boolean | false | Habilita expansión de filas |
318
+ | hasActions | Boolean | false | Muestra columna de acciones |
319
+ | actionLabel | String | 'Acciones' | Etiqueta de columna de acciones |
320
+ | actionLoadingMap | Object | {} | Mapa de estado loading por ID de item |
286
321
  | itemsPerPage | Number | 10 | Items por página |
287
- | sortBy | Array/String | [] | Ordenamiento |
288
- | hasActions | Boolean | false | Columna de acciones |
322
+ | page | Number | 1 | Página actual |
323
+ | sortBy | Array/String | [] | v-model: Criterio de ordenamiento |
324
+ | multiSort | Boolean | false | Permite ordenar por múltiples columnas |
325
+ | pageOptions | Array | [5, 10, 25, 50, 100] | Opciones del selector de items por página |
326
+ | searchableKeys | Array | null | Claves específicas para búsqueda global |
327
+ | searchPlaceholder | String | 'Buscar...' | Placeholder del input de búsqueda |
328
+ | debounceTime | Number | 300 | Debounce en ms para búsqueda |
329
+ | customFilter | Function | null | Función de filtrado personalizada |
330
+ | functionMap | Object | {} | Mapa de funciones para columnas tipo 'function' |
331
+ | hideDefaultHeader | Boolean | false | Oculta header por defecto |
332
+ | hideDefaultFooter | Boolean | false | Oculta footer por defecto |
333
+ | noDataText | String | 'No hay elementos disponibles' | Texto cuando no hay datos |
334
+ | loadingText | String | 'Cargando...' | Texto de estado de carga |
335
+
336
+ **Estructura de `headers`:**
337
+
338
+ ```javascript
339
+ const headers = [
340
+ {
341
+ key: 'nombre', // Identificador único
342
+ value: 'nombre', // Clave para acceder al dato (soporta paths: 'usuario.nombre')
343
+ label: 'Nombre', // Texto visible en el header
344
+ sortable: true, // Permite ordenar por esta columna
345
+ headerAlign: 'left', // Alineación: 'left', 'center', 'right'
346
+ columnType: 'function', // Opcional: tipo de columna
347
+ columnFunction: 'formatDate', // Nombre de función en functionMap
348
+ relationPath: 'user.id' // Path alternativo para datos anidados
349
+ }
350
+ ]
351
+ ```
352
+
353
+ **Estructura de `filters`:**
354
+
355
+ ```javascript
356
+ const filters = [
357
+ {
358
+ value: 'rol', // Clave del filtro (debe coincidir con header.value)
359
+ label: 'Rol', // Etiqueta visible
360
+ text: 'Rol', // Texto alternativo
361
+ name: 'roles', // Nombre para textos genéricos
362
+ items: [...], // Lista de opciones para el filtro
363
+ placeholderText: 'Seleccionar rol',
364
+ textNoItem: 'No hay roles disponibles'
365
+ }
366
+ ]
367
+ ```
368
+
369
+ **Slots:**
370
+
371
+ | Slot | Props | Descripción |
372
+ |------|-------|-------------|
373
+ | `#item.{key}` | `{ item, index, value, header }` | Contenido personalizado de celda |
374
+ | `#header.{key}` | `{ header }` | Header personalizado de columna |
375
+ | `#item.actions` | `{ item, index, loading }` | Columna de acciones (si `hasActions`) |
376
+ | `#expand` | `{ item, index }` | Contenido de fila expandida |
377
+ | `#thead` | `{ items, headers, page, itemsPerPage, ... }` | Header completo personalizado |
378
+ | `#tfoot` | `{ items, headers, ... }` | Footer personalizado |
379
+ | `#body.prepend` | `{ items, headers, ... }` | Contenido antes del tbody |
380
+ | `#body.append` | `{ items, headers, ... }` | Contenido después del tbody |
381
+ | `#prependHeader` | - | Contenido antes de la barra de búsqueda |
382
+ | `#prependSearch` | - | Contenido antes del input de búsqueda |
383
+ | `#appendSearch` | - | Contenido después del input de búsqueda |
384
+ | `#footer` | `{ items, headers, page, itemsPerPage, ... }` | Footer completo personalizado |
385
+
386
+ **Eventos:**
387
+
388
+ | Evento | Payload | Descripción |
389
+ |--------|---------|-------------|
390
+ | `update:page` | `Number` | Cambia la página actual |
391
+ | `update:itemsPerPage` | `Number` | Cambia items por página |
392
+ | `update:sortBy` | `Array` | Cambia criterio de ordenamiento |
393
+ | `update:search` | `String` | Cambia término de búsqueda |
394
+ | `update:selectedItems` | `Array` | Cambia items seleccionados |
395
+ | `focusOnSearch` | `Boolean` | Input de búsqueda enfocado/desenfocado |
396
+
397
+ **Clases personalizables:**
398
+
399
+ | Prop | Tipo | Descripción |
400
+ |------|------|-------------|
401
+ | wrapperClass | String | Clase del contenedor principal |
402
+ | tableClass | String | Clase de la etiqueta `<table>` |
403
+ | theadClass | String | Clase del `<thead>` |
404
+ | tbodyClass | String | Clase del `<tbody>` |
405
+ | tfootClass | String | Clase del `<tfoot>` |
406
+ | trClass | String | Clase de las filas `<tr>` |
407
+ | thClass | String | Clase de los headers `<th>` |
408
+ | tdClass | String/Function | Clase de las celdas `<td>` |
409
+ | rowClass | String | Clase adicional para filas |
410
+ | rowClassCondition | String/Function | Condición para aplicar rowClass |
411
+ | selectedClass | String | Clase para filas seleccionadas |
412
+ | stripedClass | String | Clase para filas alternas (striped) |
413
+
414
+ **Características:**
415
+
416
+ - **Búsqueda global:** Filtra en todas las columnas marcadas como `sortable` o en `searchableKeys`
417
+ - **Filtros por columna:** Modal con KunAutocomplete para filtrar por columnas específicas
418
+ - **Ordenamiento:** Simple o múltiple (con `multiSort`). Soporta strings, números y fechas
419
+ - **Selección:** Individual, por página, o todos los filtrados
420
+ - **Expansión:** Filas expandibles con slot `#expand`
421
+ - **Responsive:** En móvil se transforma a vista de tarjetas (KunTableIterators)
422
+ - **Serialización:** Soporta funciones serializadas via `functionMap` para columnas dinámicas
423
+
424
+ **Ejemplo completo:**
425
+
426
+ ```vue
427
+ <template>
428
+ <KunTable
429
+ :items="usuarios"
430
+ :headers="headers"
431
+ :filters="filtros"
432
+ :searchable="true"
433
+ :filterable="true"
434
+ :show-select="true"
435
+ v-model:selectedItems="seleccionados"
436
+ :items-per-page="15"
437
+ >
438
+ <template #item.estado="{ item, value }">
439
+ <KunBadge
440
+ :color="value === 'activo' ? 'bg-green-500' : 'bg-red-500'"
441
+ :text="value"
442
+ />
443
+ </template>
444
+
445
+ <template #item.actions="{ item, loading }">
446
+ <KunBtn
447
+ icon="mdi-pencil"
448
+ size="xs"
449
+ :loading="loading"
450
+ @click="editar(item)"
451
+ />
452
+ <KunBtn
453
+ icon="mdi-delete"
454
+ size="xs"
455
+ variant="text"
456
+ @click="eliminar(item)"
457
+ />
458
+ </template>
459
+
460
+ <template #expand="{ item }">
461
+ <div class="p-4 bg-surface-light">
462
+ <p><strong>Biografía:</strong> {{ item.biografia }}</p>
463
+ </div>
464
+ </template>
465
+ </KunTable>
466
+ </template>
467
+
468
+ <script setup>
469
+ import { ref, computed } from 'vue'
470
+
471
+ const usuarios = ref([
472
+ { id: 1, nombre: 'Juan', email: 'juan@example.com', rol: 'admin', estado: 'activo' },
473
+ { id: 2, nombre: 'María', email: 'maria@example.com', rol: 'editor', estado: 'inactivo' },
474
+ ])
475
+
476
+ const headers = [
477
+ { key: 'nombre', value: 'nombre', label: 'Nombre', sortable: true },
478
+ { key: 'email', value: 'email', label: 'Email', sortable: true },
479
+ { key: 'rol', value: 'rol', label: 'Rol', sortable: true },
480
+ { key: 'estado', value: 'estado', label: 'Estado', sortable: true },
481
+ ]
482
+
483
+ const filtros = [
484
+ {
485
+ value: 'rol',
486
+ label: 'Rol',
487
+ items: [
488
+ { id: 1, name: 'Admin' },
489
+ { id: 2, name: 'Editor' },
490
+ { id: 3, name: 'Viewer' }
491
+ ]
492
+ },
493
+ {
494
+ value: 'estado',
495
+ label: 'Estado',
496
+ items: [
497
+ { id: 'activo', name: 'Activo' },
498
+ { id: 'inactivo', name: 'Inactivo' }
499
+ ]
500
+ }
501
+ ]
502
+
503
+ const seleccionados = ref([])
504
+
505
+ const editar = (item) => console.log('Editar', item)
506
+ const eliminar = (item) => console.log('Eliminar', item)
507
+ </script>
508
+ ```
289
509
 
290
510
  ---
291
511
 
package/dist/AGENTS.md CHANGED
@@ -264,28 +264,248 @@ Botones de radio.
264
264
 
265
265
  ### KunTable
266
266
 
267
- Tabla con ordenamiento, paginación y selección.
267
+ Tabla de datos avanzada con paginación, ordenamiento, filtrado y selección.
268
268
 
269
269
  ```vue
270
- <KunTable
271
- :items="data"
272
- :headers="headers"
273
- :searchable="true"
274
- :show-select="true"
275
- v-model:selectedItems="selected"
276
- />
270
+ <template>
271
+ <KunTable
272
+ :items="usuarios"
273
+ :headers="headers"
274
+ :searchable="true"
275
+ :filterable="true"
276
+ :show-select="true"
277
+ v-model:selectedItems="seleccionados"
278
+ @update:sortBy="handleSort"
279
+ >
280
+ <template #item.actions="{ item }">
281
+ <KunBtn icon="mdi-pencil" size="xs" />
282
+ <KunBtn icon="mdi-delete" size="xs" />
283
+ </template>
284
+ </KunTable>
285
+ </template>
286
+
287
+ <script setup>
288
+ import { ref } from 'vue'
289
+
290
+ const usuarios = ref([...])
291
+
292
+ const headers = [
293
+ { key: 'nombre', value: 'nombre', label: 'Nombre', sortable: true },
294
+ { key: 'email', value: 'email', label: 'Email', sortable: true },
295
+ { key: 'rol', value: 'rol', label: 'Rol', sortable: true },
296
+ { key: 'estado', value: 'estado', label: 'Estado' },
297
+ ]
298
+
299
+ const seleccionados = ref([])
300
+
301
+ const handleSort = (sortBy) => {
302
+ console.log('Ordenar por:', sortBy)
303
+ }
304
+ </script>
277
305
  ```
278
306
 
279
307
  | Prop | Tipo | Default | Descripción |
280
308
  |------|------|---------|-------------|
281
309
  | items | Array | [] | Datos a mostrar |
282
- | headers | Array | [] | Configuración de columnas |
283
- | searchable | Boolean | false | Habilita búsqueda |
284
- | showSelect | Boolean | false | Muestra checkboxes |
310
+ | headers | Array | [] | Configuración de columnas (ver estructura abajo) |
311
+ | selectedItems | Array | [] | v-model: Items seleccionados |
312
+ | searchable | Boolean | false | Habilita barra de búsqueda global |
313
+ | search | String | '' | v-model: Término de búsqueda |
314
+ | filterable | Boolean | false | Habilita filtros avanzados por columna |
315
+ | filters | Array | [] | Configuración de filtros (ver estructura abajo) |
316
+ | showSelect | Boolean | false | Muestra checkboxes de selección |
285
317
  | showExpand | Boolean | false | Habilita expansión de filas |
318
+ | hasActions | Boolean | false | Muestra columna de acciones |
319
+ | actionLabel | String | 'Acciones' | Etiqueta de columna de acciones |
320
+ | actionLoadingMap | Object | {} | Mapa de estado loading por ID de item |
286
321
  | itemsPerPage | Number | 10 | Items por página |
287
- | sortBy | Array/String | [] | Ordenamiento |
288
- | hasActions | Boolean | false | Columna de acciones |
322
+ | page | Number | 1 | Página actual |
323
+ | sortBy | Array/String | [] | v-model: Criterio de ordenamiento |
324
+ | multiSort | Boolean | false | Permite ordenar por múltiples columnas |
325
+ | pageOptions | Array | [5, 10, 25, 50, 100] | Opciones del selector de items por página |
326
+ | searchableKeys | Array | null | Claves específicas para búsqueda global |
327
+ | searchPlaceholder | String | 'Buscar...' | Placeholder del input de búsqueda |
328
+ | debounceTime | Number | 300 | Debounce en ms para búsqueda |
329
+ | customFilter | Function | null | Función de filtrado personalizada |
330
+ | functionMap | Object | {} | Mapa de funciones para columnas tipo 'function' |
331
+ | hideDefaultHeader | Boolean | false | Oculta header por defecto |
332
+ | hideDefaultFooter | Boolean | false | Oculta footer por defecto |
333
+ | noDataText | String | 'No hay elementos disponibles' | Texto cuando no hay datos |
334
+ | loadingText | String | 'Cargando...' | Texto de estado de carga |
335
+
336
+ **Estructura de `headers`:**
337
+
338
+ ```javascript
339
+ const headers = [
340
+ {
341
+ key: 'nombre', // Identificador único
342
+ value: 'nombre', // Clave para acceder al dato (soporta paths: 'usuario.nombre')
343
+ label: 'Nombre', // Texto visible en el header
344
+ sortable: true, // Permite ordenar por esta columna
345
+ headerAlign: 'left', // Alineación: 'left', 'center', 'right'
346
+ columnType: 'function', // Opcional: tipo de columna
347
+ columnFunction: 'formatDate', // Nombre de función en functionMap
348
+ relationPath: 'user.id' // Path alternativo para datos anidados
349
+ }
350
+ ]
351
+ ```
352
+
353
+ **Estructura de `filters`:**
354
+
355
+ ```javascript
356
+ const filters = [
357
+ {
358
+ value: 'rol', // Clave del filtro (debe coincidir con header.value)
359
+ label: 'Rol', // Etiqueta visible
360
+ text: 'Rol', // Texto alternativo
361
+ name: 'roles', // Nombre para textos genéricos
362
+ items: [...], // Lista de opciones para el filtro
363
+ placeholderText: 'Seleccionar rol',
364
+ textNoItem: 'No hay roles disponibles'
365
+ }
366
+ ]
367
+ ```
368
+
369
+ **Slots:**
370
+
371
+ | Slot | Props | Descripción |
372
+ |------|-------|-------------|
373
+ | `#item.{key}` | `{ item, index, value, header }` | Contenido personalizado de celda |
374
+ | `#header.{key}` | `{ header }` | Header personalizado de columna |
375
+ | `#item.actions` | `{ item, index, loading }` | Columna de acciones (si `hasActions`) |
376
+ | `#expand` | `{ item, index }` | Contenido de fila expandida |
377
+ | `#thead` | `{ items, headers, page, itemsPerPage, ... }` | Header completo personalizado |
378
+ | `#tfoot` | `{ items, headers, ... }` | Footer personalizado |
379
+ | `#body.prepend` | `{ items, headers, ... }` | Contenido antes del tbody |
380
+ | `#body.append` | `{ items, headers, ... }` | Contenido después del tbody |
381
+ | `#prependHeader` | - | Contenido antes de la barra de búsqueda |
382
+ | `#prependSearch` | - | Contenido antes del input de búsqueda |
383
+ | `#appendSearch` | - | Contenido después del input de búsqueda |
384
+ | `#footer` | `{ items, headers, page, itemsPerPage, ... }` | Footer completo personalizado |
385
+
386
+ **Eventos:**
387
+
388
+ | Evento | Payload | Descripción |
389
+ |--------|---------|-------------|
390
+ | `update:page` | `Number` | Cambia la página actual |
391
+ | `update:itemsPerPage` | `Number` | Cambia items por página |
392
+ | `update:sortBy` | `Array` | Cambia criterio de ordenamiento |
393
+ | `update:search` | `String` | Cambia término de búsqueda |
394
+ | `update:selectedItems` | `Array` | Cambia items seleccionados |
395
+ | `focusOnSearch` | `Boolean` | Input de búsqueda enfocado/desenfocado |
396
+
397
+ **Clases personalizables:**
398
+
399
+ | Prop | Tipo | Descripción |
400
+ |------|------|-------------|
401
+ | wrapperClass | String | Clase del contenedor principal |
402
+ | tableClass | String | Clase de la etiqueta `<table>` |
403
+ | theadClass | String | Clase del `<thead>` |
404
+ | tbodyClass | String | Clase del `<tbody>` |
405
+ | tfootClass | String | Clase del `<tfoot>` |
406
+ | trClass | String | Clase de las filas `<tr>` |
407
+ | thClass | String | Clase de los headers `<th>` |
408
+ | tdClass | String/Function | Clase de las celdas `<td>` |
409
+ | rowClass | String | Clase adicional para filas |
410
+ | rowClassCondition | String/Function | Condición para aplicar rowClass |
411
+ | selectedClass | String | Clase para filas seleccionadas |
412
+ | stripedClass | String | Clase para filas alternas (striped) |
413
+
414
+ **Características:**
415
+
416
+ - **Búsqueda global:** Filtra en todas las columnas marcadas como `sortable` o en `searchableKeys`
417
+ - **Filtros por columna:** Modal con KunAutocomplete para filtrar por columnas específicas
418
+ - **Ordenamiento:** Simple o múltiple (con `multiSort`). Soporta strings, números y fechas
419
+ - **Selección:** Individual, por página, o todos los filtrados
420
+ - **Expansión:** Filas expandibles con slot `#expand`
421
+ - **Responsive:** En móvil se transforma a vista de tarjetas (KunTableIterators)
422
+ - **Serialización:** Soporta funciones serializadas via `functionMap` para columnas dinámicas
423
+
424
+ **Ejemplo completo:**
425
+
426
+ ```vue
427
+ <template>
428
+ <KunTable
429
+ :items="usuarios"
430
+ :headers="headers"
431
+ :filters="filtros"
432
+ :searchable="true"
433
+ :filterable="true"
434
+ :show-select="true"
435
+ v-model:selectedItems="seleccionados"
436
+ :items-per-page="15"
437
+ >
438
+ <template #item.estado="{ item, value }">
439
+ <KunBadge
440
+ :color="value === 'activo' ? 'bg-green-500' : 'bg-red-500'"
441
+ :text="value"
442
+ />
443
+ </template>
444
+
445
+ <template #item.actions="{ item, loading }">
446
+ <KunBtn
447
+ icon="mdi-pencil"
448
+ size="xs"
449
+ :loading="loading"
450
+ @click="editar(item)"
451
+ />
452
+ <KunBtn
453
+ icon="mdi-delete"
454
+ size="xs"
455
+ variant="text"
456
+ @click="eliminar(item)"
457
+ />
458
+ </template>
459
+
460
+ <template #expand="{ item }">
461
+ <div class="p-4 bg-surface-light">
462
+ <p><strong>Biografía:</strong> {{ item.biografia }}</p>
463
+ </div>
464
+ </template>
465
+ </KunTable>
466
+ </template>
467
+
468
+ <script setup>
469
+ import { ref, computed } from 'vue'
470
+
471
+ const usuarios = ref([
472
+ { id: 1, nombre: 'Juan', email: 'juan@example.com', rol: 'admin', estado: 'activo' },
473
+ { id: 2, nombre: 'María', email: 'maria@example.com', rol: 'editor', estado: 'inactivo' },
474
+ ])
475
+
476
+ const headers = [
477
+ { key: 'nombre', value: 'nombre', label: 'Nombre', sortable: true },
478
+ { key: 'email', value: 'email', label: 'Email', sortable: true },
479
+ { key: 'rol', value: 'rol', label: 'Rol', sortable: true },
480
+ { key: 'estado', value: 'estado', label: 'Estado', sortable: true },
481
+ ]
482
+
483
+ const filtros = [
484
+ {
485
+ value: 'rol',
486
+ label: 'Rol',
487
+ items: [
488
+ { id: 1, name: 'Admin' },
489
+ { id: 2, name: 'Editor' },
490
+ { id: 3, name: 'Viewer' }
491
+ ]
492
+ },
493
+ {
494
+ value: 'estado',
495
+ label: 'Estado',
496
+ items: [
497
+ { id: 'activo', name: 'Activo' },
498
+ { id: 'inactivo', name: 'Inactivo' }
499
+ ]
500
+ }
501
+ ]
502
+
503
+ const seleccionados = ref([])
504
+
505
+ const editar = (item) => console.log('Editar', item)
506
+ const eliminar = (item) => console.log('Eliminar', item)
507
+ </script>
508
+ ```
289
509
 
290
510
  ---
291
511