@groupteknology/vuno 0.6.0 → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (141) hide show
  1. package/LICENSE +21 -21
  2. package/README.md +160 -37
  3. package/dist/module.d.cts +2 -0
  4. package/dist/module.d.mts +2 -10
  5. package/dist/module.json +1 -1
  6. package/dist/module.mjs +14 -24
  7. package/dist/types.d.mts +11 -3
  8. package/package.json +49 -44
  9. package/dist/runtime/app/assets/css/main.css +0 -1
  10. package/dist/runtime/app/components/Cell/CellBadge.d.vue.ts +0 -5
  11. package/dist/runtime/app/components/Cell/CellBadge.vue +0 -24
  12. package/dist/runtime/app/components/Cell/CellBadge.vue.d.ts +0 -5
  13. package/dist/runtime/app/components/Cell/CellBoolean.d.vue.ts +0 -5
  14. package/dist/runtime/app/components/Cell/CellBoolean.vue +0 -21
  15. package/dist/runtime/app/components/Cell/CellBoolean.vue.d.ts +0 -5
  16. package/dist/runtime/app/components/Cell/CellCurrency.d.vue.ts +0 -5
  17. package/dist/runtime/app/components/Cell/CellCurrency.vue +0 -14
  18. package/dist/runtime/app/components/Cell/CellCurrency.vue.d.ts +0 -5
  19. package/dist/runtime/app/components/Cell/CellDate.d.vue.ts +0 -5
  20. package/dist/runtime/app/components/Cell/CellDate.vue +0 -19
  21. package/dist/runtime/app/components/Cell/CellDate.vue.d.ts +0 -5
  22. package/dist/runtime/app/components/Cell/CellImage.d.vue.ts +0 -5
  23. package/dist/runtime/app/components/Cell/CellImage.vue +0 -22
  24. package/dist/runtime/app/components/Cell/CellImage.vue.d.ts +0 -5
  25. package/dist/runtime/app/components/Cell/CellNumber.d.vue.ts +0 -5
  26. package/dist/runtime/app/components/Cell/CellNumber.vue +0 -15
  27. package/dist/runtime/app/components/Cell/CellNumber.vue.d.ts +0 -5
  28. package/dist/runtime/app/components/Cell/CellText.d.vue.ts +0 -5
  29. package/dist/runtime/app/components/Cell/CellText.vue +0 -13
  30. package/dist/runtime/app/components/Cell/CellText.vue.d.ts +0 -5
  31. package/dist/runtime/app/components/Confirm/Confirm.d.vue.ts +0 -35
  32. package/dist/runtime/app/components/Confirm/Confirm.vue +0 -68
  33. package/dist/runtime/app/components/Confirm/Confirm.vue.d.ts +0 -35
  34. package/dist/runtime/app/components/Field/FieldArray.d.vue.ts +0 -5
  35. package/dist/runtime/app/components/Field/FieldArray.vue +0 -128
  36. package/dist/runtime/app/components/Field/FieldArray.vue.d.ts +0 -5
  37. package/dist/runtime/app/components/Field/FieldCheckbox.d.vue.ts +0 -5
  38. package/dist/runtime/app/components/Field/FieldCheckbox.vue +0 -30
  39. package/dist/runtime/app/components/Field/FieldCheckbox.vue.d.ts +0 -5
  40. package/dist/runtime/app/components/Field/FieldColor.d.vue.ts +0 -5
  41. package/dist/runtime/app/components/Field/FieldColor.vue +0 -57
  42. package/dist/runtime/app/components/Field/FieldColor.vue.d.ts +0 -5
  43. package/dist/runtime/app/components/Field/FieldEmail.d.vue.ts +0 -5
  44. package/dist/runtime/app/components/Field/FieldEmail.vue +0 -37
  45. package/dist/runtime/app/components/Field/FieldEmail.vue.d.ts +0 -5
  46. package/dist/runtime/app/components/Field/FieldFile.d.vue.ts +0 -5
  47. package/dist/runtime/app/components/Field/FieldFile.vue +0 -93
  48. package/dist/runtime/app/components/Field/FieldFile.vue.d.ts +0 -5
  49. package/dist/runtime/app/components/Field/FieldNumber.d.vue.ts +0 -5
  50. package/dist/runtime/app/components/Field/FieldNumber.vue +0 -38
  51. package/dist/runtime/app/components/Field/FieldNumber.vue.d.ts +0 -5
  52. package/dist/runtime/app/components/Field/FieldPassword.d.vue.ts +0 -5
  53. package/dist/runtime/app/components/Field/FieldPassword.vue +0 -35
  54. package/dist/runtime/app/components/Field/FieldPassword.vue.d.ts +0 -5
  55. package/dist/runtime/app/components/Field/FieldRadio.d.vue.ts +0 -5
  56. package/dist/runtime/app/components/Field/FieldRadio.vue +0 -33
  57. package/dist/runtime/app/components/Field/FieldRadio.vue.d.ts +0 -5
  58. package/dist/runtime/app/components/Field/FieldSelect.d.vue.ts +0 -5
  59. package/dist/runtime/app/components/Field/FieldSelect.vue +0 -38
  60. package/dist/runtime/app/components/Field/FieldSelect.vue.d.ts +0 -5
  61. package/dist/runtime/app/components/Field/FieldSlug.d.vue.ts +0 -5
  62. package/dist/runtime/app/components/Field/FieldSlug.vue +0 -92
  63. package/dist/runtime/app/components/Field/FieldSlug.vue.d.ts +0 -5
  64. package/dist/runtime/app/components/Field/FieldSwitch.d.vue.ts +0 -5
  65. package/dist/runtime/app/components/Field/FieldSwitch.vue +0 -27
  66. package/dist/runtime/app/components/Field/FieldSwitch.vue.d.ts +0 -5
  67. package/dist/runtime/app/components/Field/FieldText.d.vue.ts +0 -5
  68. package/dist/runtime/app/components/Field/FieldText.vue +0 -38
  69. package/dist/runtime/app/components/Field/FieldText.vue.d.ts +0 -5
  70. package/dist/runtime/app/components/Field/FieldTextarea.d.vue.ts +0 -5
  71. package/dist/runtime/app/components/Field/FieldTextarea.vue +0 -36
  72. package/dist/runtime/app/components/Field/FieldTextarea.vue.d.ts +0 -5
  73. package/dist/runtime/app/components/Form/Form.d.vue.ts +0 -48
  74. package/dist/runtime/app/components/Form/Form.vue +0 -138
  75. package/dist/runtime/app/components/Form/Form.vue.d.ts +0 -48
  76. package/dist/runtime/app/components/Form/FormField.d.vue.ts +0 -7
  77. package/dist/runtime/app/components/Form/FormField.vue +0 -63
  78. package/dist/runtime/app/components/Form/FormField.vue.d.ts +0 -7
  79. package/dist/runtime/app/components/Form/FormModal.d.vue.ts +0 -60
  80. package/dist/runtime/app/components/Form/FormModal.vue +0 -83
  81. package/dist/runtime/app/components/Form/FormModal.vue.d.ts +0 -60
  82. package/dist/runtime/app/components/Form/FormSection.d.vue.ts +0 -12
  83. package/dist/runtime/app/components/Form/FormSection.vue +0 -43
  84. package/dist/runtime/app/components/Form/FormSection.vue.d.ts +0 -12
  85. package/dist/runtime/app/components/Page/Page.d.vue.ts +0 -24
  86. package/dist/runtime/app/components/Page/Page.vue +0 -63
  87. package/dist/runtime/app/components/Page/Page.vue.d.ts +0 -24
  88. package/dist/runtime/app/components/State/EmptyState.d.vue.ts +0 -20
  89. package/dist/runtime/app/components/State/EmptyState.vue +0 -36
  90. package/dist/runtime/app/components/State/EmptyState.vue.d.ts +0 -20
  91. package/dist/runtime/app/components/State/FailureState.d.vue.ts +0 -10
  92. package/dist/runtime/app/components/State/FailureState.vue +0 -34
  93. package/dist/runtime/app/components/State/FailureState.vue.d.ts +0 -10
  94. package/dist/runtime/app/components/Table/Table.d.vue.ts +0 -70
  95. package/dist/runtime/app/components/Table/Table.vue +0 -441
  96. package/dist/runtime/app/components/Table/Table.vue.d.ts +0 -70
  97. package/dist/runtime/app/components/Table/TableCell.d.vue.ts +0 -8
  98. package/dist/runtime/app/components/Table/TableCell.vue +0 -35
  99. package/dist/runtime/app/components/Table/TableCell.vue.d.ts +0 -8
  100. package/dist/runtime/app/composables/useVunoCrud.d.ts +0 -23
  101. package/dist/runtime/app/composables/useVunoCrud.js +0 -139
  102. package/dist/runtime/app/composables/useVunoField.d.ts +0 -10
  103. package/dist/runtime/app/composables/useVunoField.js +0 -34
  104. package/dist/runtime/app/composables/useVunoForm.d.ts +0 -2
  105. package/dist/runtime/app/composables/useVunoForm.js +0 -9
  106. package/dist/runtime/app/composables/useVunoTableQuery.d.ts +0 -51
  107. package/dist/runtime/app/composables/useVunoTableQuery.js +0 -110
  108. package/dist/runtime/app/composables/useVunoTheme.d.ts +0 -12
  109. package/dist/runtime/app/composables/useVunoTheme.js +0 -35
  110. package/dist/runtime/app/theme/index.d.ts +0 -14
  111. package/dist/runtime/app/theme/index.js +0 -228
  112. package/dist/runtime/app/types/app-config.d.ts +0 -8
  113. package/dist/runtime/app/types/app-config.js +0 -1
  114. package/dist/runtime/app/types/confirm.d.ts +0 -11
  115. package/dist/runtime/app/types/confirm.js +0 -0
  116. package/dist/runtime/app/types/crud.d.ts +0 -108
  117. package/dist/runtime/app/types/crud.js +0 -0
  118. package/dist/runtime/app/types/field.d.ts +0 -128
  119. package/dist/runtime/app/types/field.js +0 -0
  120. package/dist/runtime/app/types/form.d.ts +0 -39
  121. package/dist/runtime/app/types/form.js +0 -1
  122. package/dist/runtime/app/types/index.d.ts +0 -9
  123. package/dist/runtime/app/types/index.js +0 -1
  124. package/dist/runtime/app/types/page.d.ts +0 -6
  125. package/dist/runtime/app/types/page.js +0 -0
  126. package/dist/runtime/app/types/responsive.d.ts +0 -8
  127. package/dist/runtime/app/types/responsive.js +0 -0
  128. package/dist/runtime/app/types/table.d.ts +0 -197
  129. package/dist/runtime/app/types/table.js +0 -0
  130. package/dist/runtime/app/types/theme.d.ts +0 -83
  131. package/dist/runtime/app/types/theme.js +0 -0
  132. package/dist/runtime/app/utils/column.d.ts +0 -9
  133. package/dist/runtime/app/utils/column.js +0 -5
  134. package/dist/runtime/app/utils/format.d.ts +0 -9
  135. package/dist/runtime/app/utils/format.js +0 -30
  136. package/dist/runtime/app/utils/grid.d.ts +0 -9
  137. package/dist/runtime/app/utils/grid.js +0 -91
  138. package/dist/runtime/app/utils/path.d.ts +0 -16
  139. package/dist/runtime/app/utils/path.js +0 -74
  140. package/dist/runtime/app/utils/query-key.d.ts +0 -20
  141. package/dist/runtime/app/utils/query-key.js +0 -7
package/LICENSE CHANGED
@@ -1,21 +1,21 @@
1
- MIT License
2
-
3
- Copyright (c) 2026 Diego Otayza
4
-
5
- Permission is hereby granted, free of charge, to any person obtaining a copy
6
- of this software and associated documentation files (the "Software"), to deal
7
- in the Software without restriction, including without limitation the rights
8
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
- copies of the Software, and to permit persons to whom the Software is
10
- furnished to do so, subject to the following conditions:
11
-
12
- The above copyright notice and this permission notice shall be included in all
13
- copies or substantial portions of the Software.
14
-
15
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
- SOFTWARE.
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Diego Otayza
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -1,8 +1,16 @@
1
1
  # @groupteknology/vuno
2
2
 
3
- Formularios, tablas y diálogos declarativos para Nuxt 4, construidos sobre [Nuxt UI](https://ui.nuxt.com).
3
+ Formularios, tablas y diálogos declarativos para Nuxt 4, con componentes propios y sin librería de interfaz por debajo.
4
4
 
5
- El módulo **no aporta estética**. Todo lo que pinta sale del tema del proyecto que lo instala: usa las utilidades semánticas de Nuxt UI (`bg-default`, `text-muted`, `border-default`), su escala de radios y sus colores. Si cambias `primary` o `--ui-radius`, los componentes de vuno cambian contigo.
5
+ El módulo **trae su propia estética, y se sobreescribe entera desde el proyecto**. Todo lo que pinta se deriva de un puñado de variables CSS —los tokens `--vuno-*`—, así que redefinir una cambia vuno entero sin tocar un solo componente. Lo que necesita comportamiento difícil —combobox, menú, pestañas, tooltip, campo numérico— lleva su patrón ARIA y su teclado escritos aquí, con [Floating UI](https://floating-ui.com) para colocar lo que flota y nada más; el resto son elementos nativos.
6
+
7
+ Un color o un radio escrito a mano dentro de un componente es un error: si algo no se puede cambiar desde los tokens, falta un token.
8
+
9
+ ## Documentación
10
+
11
+ El catálogo vive en **<https://groupteknology.github.io/vuno/>**: una ficha por componente, con la vista viva, los controles que la mueven, el código que produce cada combinación y las tablas de props, slots y emits al pie.
12
+
13
+ Lo que hay aquí abajo es la referencia corta, para leerla sin salir del editor.
6
14
 
7
15
  ## Instalación
8
16
 
@@ -13,7 +21,24 @@ pnpm add @groupteknology/vuno
13
21
  ```ts
14
22
  // nuxt.config.ts
15
23
  export default defineNuxtConfig({
16
- modules: ['@nuxt/ui', '@groupteknology/vuno'],
24
+ modules: ['@groupteknology/vuno'],
25
+ })
26
+ ```
27
+
28
+ Eso es todo: el módulo registra sus componentes, su hoja de estilos, el compilador de Tailwind y `@nuxt/icon`, que es quien pinta los iconos.
29
+
30
+ ¿Vienes de la `0.6.1`? El [changelog](https://github.com/groupteknology/vuno/blob/main/packages/core/CHANGELOG.md) dice qué se rompe y qué mirar después.
31
+
32
+ ### Tailwind
33
+
34
+ **El módulo registra el compilador de Tailwind** (`@tailwindcss/vite`). No es una comodidad: la hoja que empuja vuno empieza por `@import 'tailwindcss'`, y sin nadie que lo compile ese import no hace nada —las variables del tema llegan, porque son CSS normal, y ni una sola utilidad—. La aplicación se sirve, no falla nada y sale sin estilos, que es el peor modo de fallar.
35
+
36
+ Si tu proyecto ya monta Tailwind, se detecta y no se duplica. Y si prefieres llevarlo tú:
37
+
38
+ ```ts
39
+ export default defineNuxtConfig({
40
+ modules: ['@groupteknology/vuno'],
41
+ vuno: { tailwind: false },
17
42
  })
18
43
  ```
19
44
 
@@ -53,8 +78,8 @@ const definition = {
53
78
  <template>
54
79
  <VForm v-model:state="state" :definition="definition" :schema="schema" @submit="guardar">
55
80
  <template #footer="{ dirty, reset }">
56
- <UButton :disabled="!dirty" label="Descartar" variant="ghost" @click="reset" />
57
- <UButton label="Guardar" type="submit" />
81
+ <VButton :disabled="!dirty" label="Descartar" variant="ghost" @click="reset" />
82
+ <VButton label="Guardar" type="submit" />
58
83
  </template>
59
84
  </VForm>
60
85
  </template>
@@ -68,6 +93,14 @@ const definition = {
68
93
 
69
94
  Cada uno declara sus propios props mediante una unión discriminada por `type`, así que el editor te avisa si a un `slug` le falta el `source` o si le pasas un `placeholder` a un `file`.
70
95
 
96
+ ### Campos obligatorios
97
+
98
+ `required: true` hace tres cosas: pinta el asterisco en la etiqueta, pone el atributo `required` en el input —que es lo que anuncia el campo como obligatorio a un lector de pantalla y lo que permite estilar `:invalid`— y nada más. **Quien decide si el valor vale es el esquema.**
99
+
100
+ El `<form>` lleva `novalidate`, así que el navegador no valida por su cuenta. Sin eso convivirían dos validaciones y ganaría la del navegador: cortaría el envío antes de que el esquema llegase a ejecutarse, y el usuario vería un globo del navegador, en su idioma y fuera del tema, en lugar del mensaje que tú escribiste.
101
+
102
+ Conviene saberlo si vienes de otras librerías, donde `required` suele pintar el asterisco y no llegar al control. Aquí llega, a propósito y por accesibilidad, y por eso el `novalidate` es necesario y no una preferencia.
103
+
71
104
  ### Campos repetibles
72
105
 
73
106
  `type: 'array'` repite un grupo de campos y genera rutas anidadas (`variants.0.sku`) que coinciden con las que produce la validación, de modo que cada campo muestra su propio error. Admite anidamiento.
@@ -94,8 +127,8 @@ El slot `footer` recibe `formId`, necesario para enviar desde un botón propio:
94
127
  ```vue
95
128
  <VFormModal v-model:open="open" v-model:state="state" :definition="definition" :title="title">
96
129
  <template #footer="{ close, formId, loading }">
97
- <UButton label="Cancelar" variant="ghost" @click="close" />
98
- <UButton :form="formId" :label="editando ? 'Guardar cambios' : 'Crear'" :loading="loading" type="submit" />
130
+ <VButton label="Cancelar" variant="ghost" @click="close" />
131
+ <VButton :form="formId" :label="editando ? 'Guardar cambios' : 'Crear'" :loading="loading" type="submit" />
99
132
  </template>
100
133
  </VFormModal>
101
134
  ```
@@ -177,7 +210,7 @@ Y la página queda sin saber nada de los campos:
177
210
  | La fila en edición | Un prop —`product`, `brand`, lo que sea— que vale `null` en el alta. De él salen el título y la etiqueta del botón. |
178
211
  | `@submit` | Significa «el usuario confirmó», nada más. Sin datos: ya están en `state`. |
179
212
 
180
- No es casualidad que encaje: son exactamente `state`, `formOpen`, `isSaving`, `editing` y `submit` de `useVunoCrud`.
213
+ No es casualidad que encaje: son exactamente `state`, `formOpen`, `isSaving`, `editing` y `submit` de `useCrud`.
181
214
 
182
215
  #### Qué se queda fuera
183
216
 
@@ -189,7 +222,7 @@ El estado tampoco se queda dentro. Si el formulario declara su propio `ref` en v
189
222
 
190
223
  ## Una pantalla de mantenimiento entera
191
224
 
192
- `useVunoCrud` resuelve el ciclo completo: listar, dar de alta o editar en un modal, borrar con confirmación, invalidar la caché y avisar. Está construido sobre [TanStack Query](https://tanstack.com/query).
225
+ `useCrud` resuelve el ciclo completo: listar, dar de alta o editar en un modal, borrar con confirmación, invalidar la caché y avisar. Está construido sobre [TanStack Query](https://tanstack.com/query).
193
226
 
194
227
  ```vue
195
228
  <script setup lang="ts">
@@ -197,11 +230,11 @@ El estado tampoco se queda dentro. Si el formulario declara su propio `ref` en v
197
230
  // responde 401 durante el render. `useRequestFetch()` sí la lleva.
198
231
  const request = useRequestFetch()
199
232
 
200
- const query = useVunoTableQuery({ sort: 'sku', url: true })
233
+ const query = useTableQuery({ sort: 'sku', url: true })
201
234
 
202
235
  const { items, total, failure, isPending, isSaving, isDeleting,
203
236
  formOpen, editing, state, submit, openCreate, openEdit,
204
- confirmOpen, deleting, askDelete, confirmDelete } = useVunoCrud<Product, ProductForm>({
237
+ confirmOpen, deleting, askDelete, confirmDelete } = useCrud<Product, ProductForm>({
205
238
  key: 'products',
206
239
  query,
207
240
  emptyForm: () => ({ name: '', sku: '' }),
@@ -222,7 +255,7 @@ La consulta forma parte de la clave de caché, así que cada página, filtro y o
222
255
  `key` acepta un getter o un `computed`, no solo un valor fijo. Hace falta en cuanto la pantalla tiene un selector —empresa, tienda, almacén—: con una clave fija, cambiar de empresa seguiría enseñando los datos de la anterior sin dar ninguna señal de error.
223
256
 
224
257
  ```ts
225
- const crud = useVunoCrud({
258
+ const crud = useCrud({
226
259
  key: () => ['products', selectedCompanyId.value],
227
260
  // ...
228
261
  })
@@ -247,7 +280,7 @@ Mientras la clave está incompleta, `isPending` sigue en `true`: la pantalla est
247
280
  Para lo que no se deduce de la clave —un permiso, una pestaña que no está a la vista— está la opción `enabled`, que se suma a la condición anterior.
248
281
 
249
282
  ```ts
250
- useVunoCrud({ key: () => ['products', companyId.value], enabled: () => canRead.value, /* ... */ })
283
+ useCrud({ key: () => ['products', companyId.value], enabled: () => canRead.value, /* ... */ })
251
284
  ```
252
285
 
253
286
  ### La clave de invalidación
@@ -261,7 +294,7 @@ key: () => productKeys.list(filtros) // solo refresca esa combinación de filtro
261
294
 
262
295
  ### Render en servidor
263
296
 
264
- `useVunoCrud` resuelve el listado durante el render en servidor, así que el HTML sale con las filas puestas y no aparecen al hidratar. Nuxt renderiza en servidor por defecto, de modo que esto no hay que activarlo.
297
+ `useCrud` resuelve el listado durante el render en servidor, así que el HTML sale con las filas puestas y no aparecen al hidratar. Nuxt renderiza en servidor por defecto, de modo que esto no hay que activarlo.
265
298
 
266
299
  Para que además viaje en el payload y el cliente no vuelva a pedirlo, el plugin de vue-query del proyecto tiene que deshidratar. Es responsabilidad del consumidor, no del módulo:
267
300
 
@@ -286,7 +319,13 @@ Con la clave incompleta no se espera nada: la consulta está suspendida y espera
286
319
 
287
320
  Si compruebas esto con un test, **mira el HTML renderizado, no el payload**. El payload lleva la consulta resuelta aunque el prefetch esté apagado, porque la consulta se asienta después del render y el plugin deshidrata lo que encuentra: un assert sobre el payload pasa en las dos direcciones y no mide nada.
288
321
 
289
- `@tanstack/vue-query` es una dependencia opcional: solo hace falta si usas este composable.
322
+ **`@tanstack/vue-query` lo instala el proyecto**, y solo hace falta si usas este composable:
323
+
324
+ ```bash
325
+ pnpm add @tanstack/vue-query
326
+ ```
327
+
328
+ No se declara como dependencia opcional del módulo a propósito. npm instala igualmente los `peerDependencies` marcados como opcionales, y como los de vue-query admiten Vue 2, acababa colocando `vue@2.6.14` en la raíz y chocando con el `vue@^3.5.0` que pide vuno: `npm install @groupteknology/vuno` fallaba con `ERESOLVE` en un proyecto Nuxt que no declarara `vue` por su cuenta. Con pnpm no ocurría, que es por lo que tardó en verse.
290
329
 
291
330
  ## Páginas
292
331
 
@@ -295,7 +334,7 @@ Si compruebas esto con un test, **mira el HTML renderizado, no el payload**. El
295
334
  ```vue
296
335
  <VPage title="Productos" description="Catálogo completo." :breadcrumb="[{ label: 'Inicio', to: '/' }, { label: 'Productos' }]">
297
336
  <template #actions>
298
- <UButton icon="lucide:plus" label="Nuevo producto" @click="openCreate" />
337
+ <VButton icon="lucide:plus" label="Nuevo producto" @click="openCreate" />
299
338
  </template>
300
339
 
301
340
  <VTable ... />
@@ -306,9 +345,11 @@ Si compruebas esto con un test, **mira el HTML renderizado, no el payload**. El
306
345
 
307
346
  `VTable` funciona en modo servidor: emite el estado de consulta y tú devuelves la página.
308
347
 
348
+ **`query` es obligatorio.** No es un `v-model` opcional: sin él la tabla no compila, y el error de tipos que sale encabeza con el objeto `definition`, así que manda a mirar el sitio equivocado.
349
+
309
350
  ```vue
310
351
  <script setup lang="ts">
311
- const query = useVunoTableQuery({ sort: 'sku', url: true, history: 'push', filterKeys: ['status'] })
352
+ const query = useTableQuery({ sort: 'sku', url: true, history: 'push', filterKeys: ['status'] })
312
353
 
313
354
  const { data, status } = await useFetch('/api/products', {
314
355
  query: computed(() => ({ page: query.value.page, sort: query.value.sort?.column, ...query.value.filters })),
@@ -384,10 +425,10 @@ Y un aviso al ordenar: `sortable` ordena **en servidor por `key`**, y el servido
384
425
  `map` es solo de `badge`. Para traducir en otro tipo de columna, o para componer algo que no es una etiqueta, está `type: 'custom'` con su slot:
385
426
 
386
427
  ```vue
387
- <VTable :definition="definition" :data="rows">
428
+ <VTable v-model:query="query" :definition="definition" :data="rows">
388
429
  <template #cell-stock="{ row, value }">
389
430
  <span class="tabular-nums">{{ value }} uds.</span>
390
- <UBadge v-if="row.stock === 0" color="error" label="Agotado" />
431
+ <VBadge v-if="row.stock === 0" color="error" label="Agotado" />
391
432
  </template>
392
433
  </VTable>
393
434
  ```
@@ -404,16 +445,20 @@ const failure = computed(() => isError.value
404
445
  : undefined)
405
446
  ```
406
447
 
448
+ Con `useCrud` no hace falta escribirlo: el objeto lo construye él, y el título y la pista se declaran en `messages` con `listFailed` y `listFailedHint`.
449
+
450
+ Si vienes de componerlo a mano, cuenta con un efecto lateral: si tu proyecto tiene un test que sujeta esta invariante buscando el objeto en la pantalla, se pondrá **rojo** al mudar los textos, porque ahí ya no hay ningún `retry:` que encontrar. No es una regresión —la garantía sigue, solo que ahora la sostiene el tipo `VunoTableFailure`, cuyo `retry` es obligatorio y comprueba el typecheck— pero el test tiene que mirar otra cosa.
451
+
407
452
  El reintento va **dentro** del objeto para que no se pueda pintar un error sin ofrecer salida. Mientras hay fallo, la tabla no muestra filas ni paginación. El estado vacío se declara en la definición (`empty: { title, hint, icon }`) y tiene un slot `empty-actions` donde encaja el «crear el primero».
408
453
 
409
- Los dos estados existen además como componentes sueltos, para las pantallas que no son una tabla:
454
+ Los dos estados existen además sueltos, para las pantallas que no son una tabla, y son **un solo componente con dos tonos**: `VState`. El tono no es un adjetivo sino el discriminante de una unión, así que `tone="failure"` exige el objeto del fallo y no hay forma de escribir un error sin su salida dentro:
410
455
 
411
456
  ```vue
412
- <VEmptyState title="Todavía no hay pedidos" hint="Aparecerán aquí en cuanto entre el primero." icon="lucide:inbox">
413
- <template #actions><UButton label="Crear pedido" /></template>
414
- </VEmptyState>
457
+ <VState title="Todavía no hay pedidos" hint="Aparecerán aquí en cuanto entre el primero." icon="lucide:inbox">
458
+ <template #actions><VButton label="Crear pedido" /></template>
459
+ </VState>
415
460
 
416
- <VFailureState :failure="failure" />
461
+ <VState tone="failure" :failure="failure" />
417
462
  ```
418
463
 
419
464
  Tipos de columna: `text` · `number` · `currency` · `date` · `boolean` · `badge` · `image` · `custom` · `actions`. Trae búsqueda con antirrebote, paginación, selección múltiple, panel lateral de filtros y menú de acciones por fila.
@@ -425,37 +470,109 @@ Tipos de columna: `text` · `number` · `currency` · `date` · `boolean` · `ba
425
470
  ```vue
426
471
  <VConfirm v-model:open="open" :title="`¿Eliminar ${marca.nombre}?`" @confirm="borrar">
427
472
  <p>Se eliminará <strong>{{ marca.nombre }}</strong>.</p>
428
- <p class="text-warning">{{ marca.productos }} productos se quedarán sin marca.</p>
473
+ <p class="text-vuno-warning">{{ marca.productos }} productos se quedarán sin marca.</p>
429
474
  </VConfirm>
430
475
  ```
431
476
 
432
477
  No se cierra solo cuando recibe `loading`: así se espera a que la acción termine contra la API y se cierra desde fuera.
433
478
 
479
+ ## Modales del proyecto
480
+
481
+ Un modal por componente, en `components/modal/`, abierto por su clave:
482
+
483
+ ```
484
+ app/components/modal/ModalProduct.vue -> open('product')
485
+ app/components/modal/ModalInvoice.vue -> open('invoice')
486
+ ```
487
+
488
+ ```ts
489
+ const modal = useModal()
490
+
491
+ const guardado = await modal.open<boolean>('product', { sku: row.sku })
492
+ ```
493
+
494
+ No hay que registrarlo ni colocarlo en ninguna plantilla: el módulo marca esa carpeta como global, así que la clave **es** el nombre del componente y un modal que existe se puede abrir.
495
+
496
+ El componente recibe `open` y los props que le pases, y resuelve la promesa emitiendo `close` con su resultado:
497
+
498
+ ```vue
499
+ <script setup lang="ts">
500
+ const emit = defineEmits<{ close: [guardado: boolean] }>()
501
+ const open = defineModel<boolean>('open', { default: false })
502
+
503
+ function guardar() {
504
+ open.value = false
505
+ emit('close', true)
506
+ }
507
+ </script>
508
+ ```
509
+
510
+ Se pinta en `<VApp>` y no en la pantalla que lo abrió, así que navegar no lo desmonta a medias ni deja la promesa colgada. Cerrarlo con Escape o pulsando fuera resuelve sin valor.
511
+
434
512
  ## Composables
435
513
 
436
514
  | Composable | Para qué |
437
515
  |---|---|
438
- | `useVunoCrud` | El ciclo de mantenimiento entero sobre TanStack Query. |
439
- | `useVunoTableQuery` | Estado de consulta de una tabla, opcionalmente sincronizado con la query string. |
440
- | `useVunoForm` | Contexto del `VForm` que envuelve al componente: estado, `dirty`, `reset`. |
441
- | `useVunoField` | Lee y escribe un campo por su ruta; para construir campos propios. |
442
- | `useVunoTheme` | Resuelve los slots de un componente cruzando tema, `app.config` y prop `ui`. |
443
- | `useVunoIcons` | Los iconos configurados en `vuno.icons`. |
444
- | `useVunoMessages` | Los textos configurados en `vuno.messages`. |
516
+ | `useCrud` | El ciclo de mantenimiento entero sobre TanStack Query. |
517
+ | `useTableQuery` | Estado de consulta de una tabla, opcionalmente sincronizado con la query string. |
518
+ | `useForm` | Contexto del `VForm` que envuelve al componente: estado, `dirty`, `reset`. |
519
+ | `useField` | Lee y escribe un campo por su ruta; para construir campos propios. |
520
+ | `useTheme` | Resuelve los slots de un componente cruzando tema, `app.config` y prop `ui`. |
521
+ | `useIcons` | Los iconos configurados en `vuno.icons`. |
522
+ | `useMessages` | Los textos configurados en `vuno.messages`. |
445
523
 
446
524
  Los tres últimos existen para que un componente tuyo pueda usar los mismos iconos, textos y reglas de tema que los de vuno sin duplicar la configuración.
447
525
 
448
526
  ## Personalización
449
527
 
450
- Tres niveles, de más global a más concreto:
528
+ ### Los tokens
529
+
530
+ **Es el primer sitio al que hay que ir, y casi siempre el único.** Todo el color, el radio y la jerarquía de texto de vuno salen de variables CSS que se redefinen desde el proyecto. El caso mínimo, en cualquier hoja que cargue tu aplicación:
531
+
532
+ ```css
533
+ :root {
534
+ --vuno-primary: var(--color-indigo-600);
535
+ }
536
+ ```
537
+
538
+ Con esa línea cambian los botones sólidos, el anillo de foco de todos los campos, el enlace activo, la casilla marcada y el acento de las insignias: no hay un solo componente que escriba ese azul por su cuenta.
539
+
540
+ Los que hay:
541
+
542
+ | Token | Para qué |
543
+ | --- | --- |
544
+ | `--vuno-primary` · `--vuno-secondary` · `--vuno-neutral` | Los tres acentos de marca. |
545
+ | `--vuno-success` · `--vuno-info` · `--vuno-warning` · `--vuno-error` | Los cuatro de estado. |
546
+ | `--vuno-*-contrast` | El texto que va **encima** de cada acento en su variante sólida. |
547
+ | `--vuno-font-sans` · `--vuno-font-mono` | La tipografía. El módulo **nombra** la familia y no la carga: un `@import` a un servidor de fuentes convertiría cada visita de tu proyecto en una petición a un tercero. Cárgala tú —con `@nuxt/fonts` o con tu propio `@font-face`—; si no está, la pila de respaldo se encarga. |
548
+ | `--vuno-surface` · `--vuno-surface-1` · `--vuno-surface-2` · `--vuno-surface-inverse` | La escala de elevación: **cada cosa sube un escalón sobre lo que la sostiene**. La página es la base —blanco en claro, negro en oscuro—, lo que se levanta de ella es el 1 y lo que se levanta dentro de algo ya levantado es el 2. |
549
+ | `--vuno-text-strong` · `-body` · `-muted` · `-subtle` · `-inverse` | El texto por jerarquía, no por color. |
550
+ | `--vuno-border` · `--vuno-border-strong` | El borde que decora y el que delimita un control. |
551
+ | `--vuno-radius` | La curvatura de todo. |
552
+ | `--vuno-backdrop` | El velo que oscurece detrás de un diálogo. |
553
+
554
+ Dos cosas que ahorran un rato:
555
+
556
+ - **El tema oscuro se redefine aparte**, bajo `.dark`. Si solo cambias `:root`, el modo oscuro se queda con el valor de serie.
557
+ - **Cada acento sólido necesita su contraste.** Un `--vuno-warning` claro con texto blanco no se lee; por eso el ámbar de serie trae texto oscuro.
558
+
559
+ ```css
560
+ .dark {
561
+ --vuno-primary: var(--color-indigo-400);
562
+ }
563
+ ```
564
+
565
+ ### Los tres niveles del resto
566
+
567
+ Para lo que no es color: la forma de un componente concreto, sus iconos y sus textos.
451
568
 
452
569
  ```ts
453
570
  // app.config.ts — para toda la aplicación
454
571
  export default defineAppConfig({
455
- ui: { colors: { primary: 'indigo' } },
456
572
  vuno: {
457
573
  formSection: { slots: { root: 'border-dashed' } },
458
574
  icons: { slugEdit: 'lucide:wand-sparkles' },
575
+ locale: 'es-ES',
459
576
  messages: { selectPlaceholder: 'Elige una opción' },
460
577
  },
461
578
  })
@@ -466,7 +583,9 @@ export default defineAppConfig({
466
583
  <VForm :ui="{ sections: 'gap-8' }" ... />
467
584
  ```
468
585
 
469
- Los textos e iconos están todos en `vuno.messages` y `vuno.icons`: el paquete no impone idioma ni colección de iconos.
586
+ Se funden en orden de especificidad creciente —tema por defecto, `app.config`, prop `ui`— y los conflictos los deshace `tailwind-merge`, así que la última clase gana de verdad y no depende del orden de la hoja.
587
+
588
+ Los textos e iconos están todos en `vuno.messages` y `vuno.icons`: el paquete no impone idioma ni colección de iconos. El formato de fechas, números y monedas sale de `vuno.locale`, que se declara en vez de leerse del navegador —con render en servidor, adivinarlo da un número en el HTML y otro al hidratar—.
470
589
 
471
590
  ## Estado
472
591
 
@@ -474,9 +593,13 @@ En desarrollo.
474
593
 
475
594
  ### Nota sobre pruebas automatizadas
476
595
 
477
- Al comprobar los diálogos con un navegador controlado por automatización, el nodo del modal puede seguir en el DOM después de cerrarlo. No es un fallo: Chrome congela las animaciones CSS en pestañas ocultas y Reka UI espera el evento `animationend` para desmontar el diálogo. El componente ya está cerrado —lo indica su `data-state="closed"`—, solo falta la limpieza.
596
+ Tres trampas, las tres medidas aquí, que hacen que una comprobación afirme lo contrario de lo que pasa.
597
+
598
+ **Una pestaña oculta no pinta.** Con la ventana de fondo, `document.visibilityState` es `hidden`, `requestAnimationFrame` **no dispara nunca** y con él se paran las transiciones: un diálogo puede no llegar a abrirse y una captura caducar. El DOM y las medidas de disposición sí funcionan, así que se puede comprobar casi todo; lo que no se puede es dar por cerrado un componente porque su nodo siga ahí. Mira el estado (`opacity`, `data-state`) y no la existencia del nodo, o haz la prueba con la pestaña delante.
599
+
600
+ **`getComputedStyle` se queda con el valor viejo tras cambiar un token.** Si redefines `--vuno-primary` y vuelves a leer un elemento que ya existía, puede devolverte el color anterior aunque la variable ya valga otra cosa. Se nota porque el valor sale en `oklab` en vez de en `oklch`. Lee sobre un elemento **creado después** del cambio —o sobre un clon del que te interesa— y el valor es el nuevo.
478
601
 
479
- Comprueba la visibilidad real (`opacity`, `data-state`) en lugar de la existencia del nodo, o haz la prueba con la pestaña en primer plano.
602
+ **Un control de Reka no responde a un clic sintético.** Sus botones actúan en `pointerdown`, no en `click`, y las flechas necesitan foco de verdad: un `.click()` o un `.focus()` desde el script no disparan nada y parece que el componente está roto. Los controles nativos —casilla, interruptor, radio— sí responden a `click()`, así que ahí el clic sintético vale.
480
603
 
481
604
  ## Licencia
482
605
 
@@ -0,0 +1,2 @@
1
+ export * from "/woodpecker/src/github.com/groupteknology/vuno/packages/core/src/module.js";
2
+ export { default } from "/woodpecker/src/github.com/groupteknology/vuno/packages/core/src/module.js";
package/dist/module.d.mts CHANGED
@@ -1,10 +1,2 @@
1
- import { NuxtModule } from '@nuxt/schema';
2
- export * from '../dist/runtime/app/types/index.js';
3
-
4
- interface ModuleOptions {
5
- prefix?: string;
6
- }
7
- declare const module$1: NuxtModule<ModuleOptions>;
8
-
9
- export { module$1 as default };
10
- export type { ModuleOptions };
1
+ export * from "/woodpecker/src/github.com/groupteknology/vuno/packages/core/src/module.js";
2
+ export { default } from "/woodpecker/src/github.com/groupteknology/vuno/packages/core/src/module.js";
package/dist/module.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "vuno",
3
3
  "configKey": "vuno",
4
- "version": "0.6.0",
4
+ "version": "1.0.0",
5
5
  "builder": {
6
6
  "@nuxt/module-builder": "1.0.3",
7
7
  "unbuild": "unknown"
package/dist/module.mjs CHANGED
@@ -1,28 +1,18 @@
1
- import { defineNuxtModule, createResolver, addComponentsDir, addImportsDir } from '@nuxt/kit';
1
+ import { createJiti } from "file:///woodpecker/src/github.com/groupteknology/vuno/node_modules/.pnpm/jiti@2.7.0/node_modules/jiti/lib/jiti.mjs";
2
2
 
3
- const module$1 = defineNuxtModule({
4
- defaults: {
5
- prefix: "V"
3
+ const jiti = createJiti(import.meta.url, {
4
+ "interopDefault": true,
5
+ "alias": {
6
+ "@groupteknology/vuno": "/woodpecker/src/github.com/groupteknology/vuno/packages/core"
6
7
  },
7
- meta: {
8
- name: "vuno",
9
- configKey: "vuno"
10
- },
11
- moduleDependencies: {
12
- "@nuxt/ui": {}
13
- },
14
- setup(options, nuxt) {
15
- const resolver = createResolver(import.meta.url);
16
- nuxt.options.alias["#vuno"] = resolver.resolve("./runtime/app");
17
- addComponentsDir({
18
- global: true,
19
- path: resolver.resolve("./runtime/app/components"),
20
- pathPrefix: false,
21
- prefix: options.prefix
22
- });
23
- addImportsDir(resolver.resolve("./runtime/app/composables"));
24
- nuxt.options.css.push(resolver.resolve("./runtime/app/assets/css/main.css"));
8
+ "transformOptions": {
9
+ "babel": {
10
+ "plugins": []
11
+ }
25
12
  }
26
- });
13
+ })
14
+
15
+ /** @type {import("/woodpecker/src/github.com/groupteknology/vuno/packages/core/src/module.js")} */
16
+ const _module = await jiti.import("/woodpecker/src/github.com/groupteknology/vuno/packages/core/src/module.ts");
27
17
 
28
- export { module$1 as default };
18
+ export default _module?.default ?? _module;
package/dist/types.d.mts CHANGED
@@ -1,5 +1,13 @@
1
- export { default } from './module.mjs'
1
+ import type { ModuleHooks, ModuleRuntimeHooks, ModuleRuntimeConfig, ModulePublicRuntimeConfig } from './module.mjs'
2
2
 
3
- export { type ModuleOptions } from './module.mjs'
3
+ declare module '#app' {
4
+ interface RuntimeNuxtHooks extends ModuleRuntimeHooks {}
5
+ }
4
6
 
5
- export * from '../dist/runtime/app/types/index.js'
7
+ declare module '@nuxt/schema' {
8
+ interface NuxtHooks extends ModuleHooks {}
9
+ interface RuntimeConfig extends ModuleRuntimeConfig {}
10
+ interface PublicRuntimeConfig extends ModulePublicRuntimeConfig {}
11
+ }
12
+
13
+ export * from "./module.mjs"
package/package.json CHANGED
@@ -1,6 +1,28 @@
1
1
  {
2
2
  "name": "@groupteknology/vuno",
3
- "version": "0.6.0",
3
+ "version": "1.0.0",
4
+ "description": "Formularios, tablas y diálogos declarativos para Nuxt 4, con componentes propios y tokens sobreescribibles.",
5
+ "keywords": [
6
+ "nuxt",
7
+ "nuxt-module",
8
+ "vue",
9
+ "form",
10
+ "table",
11
+ "crud",
12
+ "datatable",
13
+ "typescript"
14
+ ],
15
+ "homepage": "https://github.com/groupteknology/vuno#readme",
16
+ "bugs": {
17
+ "url": "https://github.com/groupteknology/vuno/issues"
18
+ },
19
+ "repository": {
20
+ "type": "git",
21
+ "url": "git+https://github.com/groupteknology/vuno.git",
22
+ "directory": "packages/core"
23
+ },
24
+ "license": "MIT",
25
+ "author": "Diego Otayza <diegootayza@live.com>",
4
26
  "type": "module",
5
27
  "exports": {
6
28
  ".": {
@@ -21,63 +43,46 @@
21
43
  "dist"
22
44
  ],
23
45
  "dependencies": {
24
- "@iconify-json/lucide": "^1.2.123",
25
- "@nuxt/kit": "^4.5.2"
46
+ "@floating-ui/dom": "^1.8.0",
47
+ "@vueuse/core": "^15.0.0",
48
+ "@iconify-json/lucide": "^1.2.134",
49
+ "@nuxt/icon": "^2.5.1",
50
+ "@nuxt/kit": "^4.5.2",
51
+ "@tailwindcss/vite": "^4.3.3",
52
+ "gsap": "^3.15.0",
53
+ "tailwind-merge": "^3.7.0",
54
+ "tailwindcss": "^4.3.3"
26
55
  },
27
56
  "devDependencies": {
28
57
  "@nuxt/module-builder": "^1.0.3",
58
+ "@nuxt/schema": "^4.5.2",
29
59
  "@tanstack/vue-query": "^5.0.0",
30
- "@types/node": "^22.20.2",
60
+ "@types/node": "^26.6.2",
61
+ "@vitejs/plugin-vue": "^6.0.9",
62
+ "@vitest/coverage-v8": "^5.0.1",
63
+ "@vue/test-utils": "^2.5.0",
64
+ "happy-dom": "^20.14.5",
31
65
  "nuxt": "^4.5.2",
32
66
  "typescript": "^6.0.3",
33
- "vitest": "^3.2.4",
34
- "vue": "^3.5.42",
35
- "vue-tsc": "^3.3.11",
36
- "zod": "^4.6.2"
37
- },
38
- "description": "Formularios, tablas y diálogos declarativos para Nuxt 4, construidos sobre Nuxt UI y sin estilos propios.",
39
- "keywords": [
40
- "nuxt",
41
- "nuxt-module",
42
- "nuxt-ui",
43
- "vue",
44
- "form",
45
- "table",
46
- "crud",
47
- "datatable",
48
- "typescript"
49
- ],
50
- "license": "MIT",
51
- "author": "Diego Otayza <diegootayza@live.com>",
52
- "repository": {
53
- "type": "git",
54
- "url": "git+https://github.com/groupteknology/vuno.git",
55
- "directory": "packages/core"
67
+ "vitest": "^5.0.1",
68
+ "vue": "^3.5.43",
69
+ "vue-tsc": "^3.3.11"
56
70
  },
57
- "bugs": {
58
- "url": "https://github.com/groupteknology/vuno/issues"
71
+ "peerDependencies": {
72
+ "nuxt": "^4.5.2",
73
+ "vue": "^3.5.43"
59
74
  },
60
- "homepage": "https://github.com/groupteknology/vuno#readme",
61
75
  "publishConfig": {
62
76
  "access": "public"
63
77
  },
64
- "peerDependencies": {
65
- "@nuxt/ui": "^4.0.0",
66
- "@tanstack/vue-query": "^5.0.0",
67
- "nuxt": "^4.0.0",
68
- "vue": "^3.5.0"
69
- },
70
- "peerDependenciesMeta": {
71
- "@tanstack/vue-query": {
72
- "optional": true
73
- }
74
- },
75
78
  "scripts": {
76
79
  "build": "nuxt-module-build build",
77
- "clean": "rm -rf dist",
80
+ "clean": "node -e \"require('node:fs').rmSync('dist', { force: true, recursive: true })\"",
78
81
  "dev:prepare": "nuxt-module-build build --stub && nuxt-module-build prepare",
79
- "typecheck": "nuxt-module-build build",
82
+ "dev:watch": "node scripts/watch-build.mjs",
80
83
  "test": "vitest run",
81
- "test:watch": "vitest"
84
+ "test:coverage": "vitest run --coverage",
85
+ "test:watch": "vitest",
86
+ "typecheck": "pnpm dev:prepare && vue-tsc --noEmit -p tsconfig.json"
82
87
  }
83
88
  }
@@ -1 +0,0 @@
1
- @import "tailwindcss";@import "@nuxt/ui";@source "../../**/*";
@@ -1,5 +0,0 @@
1
- import type { VunoTableCellProps } from '#vuno/types/table';
2
- type __VLS_Props = VunoTableCellProps<'badge'>;
3
- declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
4
- declare const _default: typeof __VLS_export;
5
- export default _default;