@innertia-solutions/innertia-nuxt 0.1.12 → 0.1.13

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 (51) hide show
  1. package/components/Attention.vue +269 -0
  2. package/components/Chart/index.vue +193 -0
  3. package/components/Container.vue +116 -0
  4. package/components/CopyButton.vue +98 -0
  5. package/components/Files/Card.vue +215 -0
  6. package/components/Files/Preview.vue +675 -0
  7. package/components/Files/Upload.vue +408 -0
  8. package/components/Files/UploadModal.vue +83 -0
  9. package/components/Forms/InputPin.vue +162 -0
  10. package/components/InfoToolbar.vue +54 -0
  11. package/components/Kanban/Standard.vue +588 -0
  12. package/components/Loader.vue +358 -0
  13. package/components/Modal/Base.vue +6 -0
  14. package/components/Modal/Confirm.vue +89 -0
  15. package/components/Modal/DeleteConfirm.vue +14 -31
  16. package/components/Modal/Form.vue +76 -0
  17. package/components/Modal/Host.vue +58 -0
  18. package/components/Modal/Prompt.vue +74 -0
  19. package/components/Modal.vue +119 -34
  20. package/components/Table/Standard.vue +198 -25
  21. package/components/Table/index.vue +169 -369
  22. package/components/Table/views/ViewCards.vue +74 -0
  23. package/components/Table/views/ViewDatabase.vue +236 -0
  24. package/components/Table/views/ViewTable.vue +299 -0
  25. package/components/Toast/Alert.vue +16 -111
  26. package/components/Toast/Container.vue +4 -29
  27. package/components/Toast/Notification.vue +8 -43
  28. package/components/Toast/Process.vue +8 -86
  29. package/components/Toast/Stack.vue +59 -0
  30. package/components/Toast/Standard.vue +115 -0
  31. package/components/Tree/Standard.vue +49 -4
  32. package/components/Workflow/Board.vue +356 -0
  33. package/components/Workflow/Builder.vue +454 -0
  34. package/components/Workflow/Form.vue +526 -0
  35. package/components/Workflow/Viewer.vue +225 -0
  36. package/components/Workflow/edges/TransitionEdge.vue +84 -0
  37. package/components/Workflow/nodes/StepNode.vue +88 -0
  38. package/composables/useClipboard.js +79 -0
  39. package/composables/useConfetti.js +194 -0
  40. package/composables/useFile.js +189 -0
  41. package/composables/useModal.js +71 -0
  42. package/composables/useToast.js +38 -65
  43. package/composables/useWorkflow/form.js +162 -0
  44. package/composables/useWorkflow/index.js +18 -0
  45. package/composables/useWorkflow/view.js +220 -0
  46. package/composables/useWorkflowLayout.js +162 -0
  47. package/css/tokens.css +10 -10
  48. package/nuxt.config.ts +1 -1
  49. package/package.json +13 -8
  50. package/stores/modal.js +48 -0
  51. package/stores/toast.js +156 -117
@@ -0,0 +1,215 @@
1
+ <script setup>
2
+ import { IconDownload, IconExternalLink, IconTrash } from '@tabler/icons-vue'
3
+
4
+ /**
5
+ * <FilesCard> — Muestra un File del backend innertia-laravel.
6
+ *
7
+ * Variantes:
8
+ * - 'card' (default) — card vertical con icono grande arriba, nombre + meta abajo
9
+ * - 'row' — fila horizontal compacta (icono + nombre + acciones a la derecha)
10
+ * - 'compact' — mini-row con icono pequeño + nombre (sin acciones)
11
+ *
12
+ * El file esperado matchea el shape del modelo File de innertia-laravel:
13
+ * { id, original_name, mime_type, extension, size, ... }
14
+ *
15
+ * Si el file es una imagen y se pasa `previewImage`, se renderiza el thumbnail
16
+ * usando el viewUrl en lugar del icono.
17
+ */
18
+ const props = defineProps({
19
+ file: { type: Object, required: true },
20
+
21
+ /** 'card' | 'row' | 'compact' */
22
+ variant: { type: String, default: 'card' },
23
+
24
+ /** Mostrar tamaño (formatSize). */
25
+ showSize: { type: Boolean, default: true },
26
+
27
+ /** Mostrar extensión (PDF, XLSX, etc.). */
28
+ showType: { type: Boolean, default: true },
29
+
30
+ /** Mostrar botón de download. */
31
+ downloadable: { type: Boolean, default: true },
32
+
33
+ /** Mostrar botón de ver (abre en nueva pestaña). */
34
+ viewable: { type: Boolean, default: false },
35
+
36
+ /** Mostrar botón de eliminar (emite `delete`). */
37
+ deletable: { type: Boolean, default: false },
38
+
39
+ /** Si el file es una imagen, renderizar thumbnail en lugar del icono. */
40
+ previewImage: { type: Boolean, default: true },
41
+ })
42
+
43
+ const emit = defineEmits(['click', 'delete'])
44
+
45
+ const { download, view, viewUrl, formatSize, iconFor } = useFile()
46
+
47
+ const isImage = computed(() => props.file?.mime_type?.startsWith('image/'))
48
+ const showThumb = computed(() => props.previewImage && isImage.value)
49
+ const icon = computed(() => iconFor(props.file?.mime_type))
50
+
51
+ const handleDownload = (e) => {
52
+ e?.stopPropagation?.()
53
+ download(props.file.id, props.file.original_name)
54
+ }
55
+ const handleView = (e) => {
56
+ e?.stopPropagation?.()
57
+ view(props.file.id)
58
+ }
59
+ const handleDelete = (e) => {
60
+ e?.stopPropagation?.()
61
+ emit('delete', props.file)
62
+ }
63
+ </script>
64
+
65
+ <template>
66
+ <!-- ════════════ Variante 'compact' (mini-row) ════════════ -->
67
+ <div
68
+ v-if="variant === 'compact'"
69
+ class="inline-flex items-center gap-2 px-2 py-1 rounded-control text-xs hover:bg-muted-hover transition-colors cursor-pointer"
70
+ @click="emit('click', file)"
71
+ >
72
+ <component :is="icon" :size="14" class="shrink-0 text-muted-foreground" />
73
+ <span class="truncate text-foreground">{{ file.original_name }}</span>
74
+ </div>
75
+
76
+ <!-- ════════════ Variante 'row' (horizontal) ════════════ -->
77
+ <div
78
+ v-else-if="variant === 'row'"
79
+ class="group flex items-center gap-3 px-3 py-2 rounded-card border border-card-line bg-card hover:border-primary/40 hover:bg-muted-hover/30 transition-colors cursor-pointer"
80
+ @click="emit('click', file)"
81
+ >
82
+ <!-- Thumb o icono -->
83
+ <div class="shrink-0">
84
+ <img
85
+ v-if="showThumb"
86
+ :src="viewUrl(file.id)"
87
+ :alt="file.original_name"
88
+ class="size-10 rounded-control object-cover bg-muted"
89
+ />
90
+ <div v-else class="size-10 rounded-control bg-muted flex items-center justify-center text-muted-foreground">
91
+ <component :is="icon" :size="20" :stroke="1.75" />
92
+ </div>
93
+ </div>
94
+
95
+ <!-- Info -->
96
+ <div class="flex-1 min-w-0">
97
+ <p class="text-sm font-medium text-foreground truncate">{{ file.original_name }}</p>
98
+ <p class="text-xs text-muted-foreground mt-0.5 flex items-center gap-2">
99
+ <span v-if="showType && file.extension" class="uppercase">{{ file.extension }}</span>
100
+ <span v-if="showSize">{{ formatSize(file.size) }}</span>
101
+ </p>
102
+ </div>
103
+
104
+ <!-- Acciones -->
105
+ <div class="flex items-center gap-0.5 shrink-0 opacity-0 group-hover:opacity-100 transition-opacity">
106
+ <slot name="actions" :file="file" />
107
+ <button
108
+ v-if="viewable"
109
+ type="button"
110
+ title="Ver"
111
+ class="inline-flex items-center justify-center size-7 rounded-control text-muted-foreground hover:text-foreground hover:bg-muted-hover transition-colors"
112
+ @click="handleView"
113
+ >
114
+ <IconExternalLink class="size-3.5" />
115
+ </button>
116
+ <button
117
+ v-if="downloadable"
118
+ type="button"
119
+ title="Descargar"
120
+ class="inline-flex items-center justify-center size-7 rounded-control text-muted-foreground hover:text-foreground hover:bg-muted-hover transition-colors"
121
+ @click="handleDownload"
122
+ >
123
+ <IconDownload class="size-3.5" />
124
+ </button>
125
+ <button
126
+ v-if="deletable"
127
+ type="button"
128
+ title="Eliminar"
129
+ class="inline-flex items-center justify-center size-7 rounded-control text-muted-foreground hover:text-red-500 hover:bg-red-50 dark:hover:bg-red-900/20 transition-colors"
130
+ @click="handleDelete"
131
+ >
132
+ <IconTrash class="size-3.5" />
133
+ </button>
134
+ </div>
135
+ </div>
136
+
137
+ <!-- ════════════ Variante 'card' (vertical, default) ════════════ -->
138
+ <div
139
+ v-else
140
+ class="group relative flex flex-col rounded-card border border-card-line bg-card hover:border-primary/40 hover:shadow-sm transition cursor-pointer overflow-hidden"
141
+ @click="emit('click', file)"
142
+ >
143
+ <!-- Header — MISMA proporción (aspect-video) para todas las cards.
144
+ Imagen: thumbnail completo. No-imagen: extensión como tipografía grande
145
+ + ícono superpuesto, así llena visualmente el espacio. -->
146
+ <div class="relative aspect-video overflow-hidden">
147
+ <!-- Imagen real -->
148
+ <img
149
+ v-if="showThumb"
150
+ :src="viewUrl(file.id)"
151
+ :alt="file.original_name"
152
+ class="size-full object-cover"
153
+ />
154
+ <!-- No-imagen: bg con gradient + extensión grande como tipografía dominante -->
155
+ <div
156
+ v-else
157
+ class="size-full bg-gradient-to-br from-muted via-muted/60 to-muted/30 flex flex-col items-center justify-center gap-1 text-muted-foreground select-none"
158
+ >
159
+ <component :is="icon" :size="44" :stroke="1.5" class="opacity-70" />
160
+ <span
161
+ v-if="file.extension"
162
+ class="text-2xl font-bold uppercase tracking-widest text-foreground/70"
163
+ >
164
+ {{ file.extension }}
165
+ </span>
166
+ </div>
167
+
168
+ <!-- Chip con el tipo en imagen — sirve como label discreto -->
169
+ <span
170
+ v-if="showThumb && showType && file.extension"
171
+ class="absolute top-2 right-2 px-1.5 py-0.5 rounded-badge bg-card/85 backdrop-blur-sm text-[10px] font-bold uppercase tracking-wider text-foreground shadow-sm"
172
+ >
173
+ {{ file.extension }}
174
+ </span>
175
+ </div>
176
+
177
+ <!-- Info -->
178
+ <div class="p-3 space-y-0.5">
179
+ <p class="text-sm font-medium text-foreground truncate">{{ file.original_name }}</p>
180
+ <p v-if="showSize" class="text-xs text-muted-foreground">{{ formatSize(file.size) }}</p>
181
+ </div>
182
+
183
+ <!-- Acciones — overlay arriba a la derecha en hover -->
184
+ <div class="absolute top-2 right-2 flex items-center gap-0.5 opacity-0 group-hover:opacity-100 transition-opacity bg-card/90 backdrop-blur-sm rounded-control p-0.5">
185
+ <slot name="actions" :file="file" />
186
+ <button
187
+ v-if="viewable"
188
+ type="button"
189
+ title="Ver"
190
+ class="inline-flex items-center justify-center size-7 rounded-control text-muted-foreground hover:text-foreground hover:bg-muted-hover transition-colors"
191
+ @click="handleView"
192
+ >
193
+ <IconExternalLink class="size-3.5" />
194
+ </button>
195
+ <button
196
+ v-if="downloadable"
197
+ type="button"
198
+ title="Descargar"
199
+ class="inline-flex items-center justify-center size-7 rounded-control text-muted-foreground hover:text-foreground hover:bg-muted-hover transition-colors"
200
+ @click="handleDownload"
201
+ >
202
+ <IconDownload class="size-3.5" />
203
+ </button>
204
+ <button
205
+ v-if="deletable"
206
+ type="button"
207
+ title="Eliminar"
208
+ class="inline-flex items-center justify-center size-7 rounded-control text-muted-foreground hover:text-red-500 hover:bg-red-50 dark:hover:bg-red-900/20 transition-colors"
209
+ @click="handleDelete"
210
+ >
211
+ <IconTrash class="size-3.5" />
212
+ </button>
213
+ </div>
214
+ </div>
215
+ </template>