@edc-motor/admin-kit 0.4.16 → 0.4.18
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/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@edc-motor/admin-kit",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.18",
|
|
4
4
|
"description": "EdC Motor — kit del panel de administración: layout, gestores CRUD, imágenes, PDF, páginas, configuración, usuarios y copias (paquete fuente: lo compila el consumidor con Vite)",
|
|
5
5
|
"license": "GPL-3.0-only",
|
|
6
6
|
"type": "module",
|
|
@@ -33,7 +33,7 @@
|
|
|
33
33
|
"access": "public"
|
|
34
34
|
},
|
|
35
35
|
"dependencies": {
|
|
36
|
-
"@edc-motor/ui": "^0.4.
|
|
36
|
+
"@edc-motor/ui": "^0.4.18",
|
|
37
37
|
"axios": "^1.7.0",
|
|
38
38
|
"vue-draggable-plus": "^0.6.1"
|
|
39
39
|
},
|
|
@@ -67,6 +67,13 @@
|
|
|
67
67
|
padding: $space-3 $space-4 $space-2;
|
|
68
68
|
border-bottom: 1px solid $border;
|
|
69
69
|
min-width: 0;
|
|
70
|
+
|
|
71
|
+
// Sin badges ni meta la cabecera es lo último de la card: la divisoria
|
|
72
|
+
// sobra y el padding inferior recupera el del resto de lados.
|
|
73
|
+
&:last-child {
|
|
74
|
+
border-bottom: none;
|
|
75
|
+
padding-bottom: $space-3;
|
|
76
|
+
}
|
|
70
77
|
}
|
|
71
78
|
|
|
72
79
|
&__title {
|
|
@@ -75,6 +75,12 @@
|
|
|
75
75
|
padding: $space-3 $space-4 $space-2;
|
|
76
76
|
border-bottom: 1px solid $border;
|
|
77
77
|
min-width: 0;
|
|
78
|
+
|
|
79
|
+
// Card sin nada debajo de la cabecera: ni divisoria ni padding cojo.
|
|
80
|
+
&:last-child {
|
|
81
|
+
border-bottom: none;
|
|
82
|
+
padding-bottom: $space-3;
|
|
83
|
+
}
|
|
78
84
|
}
|
|
79
85
|
|
|
80
86
|
&__title {
|
|
@@ -297,10 +303,12 @@
|
|
|
297
303
|
border-color: $color;
|
|
298
304
|
color: $color;
|
|
299
305
|
|
|
306
|
+
// Relleno: el texto lo decide el fondo (contrast-text), no el tema
|
|
307
|
+
// — $text-1 del tema oscuro no se leía sobre warning/success.
|
|
300
308
|
&:hover:not(:disabled) {
|
|
301
309
|
background: $color;
|
|
302
310
|
border-color: $color;
|
|
303
|
-
|
|
311
|
+
@include contrast-text($color);
|
|
304
312
|
}
|
|
305
313
|
|
|
306
314
|
// Interruptores (aria-pressed): encendido = RELLENO del color (como
|
|
@@ -309,7 +317,7 @@
|
|
|
309
317
|
&.is-on {
|
|
310
318
|
background: $color;
|
|
311
319
|
border-color: $color;
|
|
312
|
-
|
|
320
|
+
@include contrast-text($color);
|
|
313
321
|
}
|
|
314
322
|
|
|
315
323
|
&.is-off {
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
2
|
import { PanelRight } from '@lucide/vue'
|
|
3
3
|
|
|
4
|
+
import { slotHasContent } from '../composables/slotHasContent'
|
|
5
|
+
|
|
4
6
|
// Tarjeta de los gestores del admin (previews y PDF): NO colapsa. Mismo
|
|
5
7
|
// lenguaje visual que EntityCard: cabecera con el título (+ chip opcional) y
|
|
6
8
|
// divisoria; debajo, las BADGES (chips de estado, slot badges) y el meta
|
|
@@ -44,21 +46,22 @@ function onClick(event: MouseEvent) {
|
|
|
44
46
|
<PanelRight :size="16" class="manager-card__hint" />
|
|
45
47
|
</div>
|
|
46
48
|
|
|
47
|
-
<!-- Como EntityCard: badges (chips) arriba, meta debajo
|
|
48
|
-
|
|
49
|
-
|
|
49
|
+
<!-- Como EntityCard: badges (chips) arriba, meta debajo. slotHasContent
|
|
50
|
+
y no $slots.x: sin contenido real, sin parte inferior vacía. -->
|
|
51
|
+
<div v-if="slotHasContent($slots.badges) || slotHasContent($slots.meta)" class="manager-card__content">
|
|
52
|
+
<div v-if="slotHasContent($slots.badges)" class="manager-card__badges">
|
|
50
53
|
<slot name="badges" />
|
|
51
54
|
</div>
|
|
52
|
-
<div v-if="$slots.meta" class="manager-card__meta">
|
|
55
|
+
<div v-if="slotHasContent($slots.meta)" class="manager-card__meta">
|
|
53
56
|
<slot name="meta" />
|
|
54
57
|
</div>
|
|
55
58
|
</div>
|
|
56
59
|
|
|
57
|
-
<div v-if="$slots.default" class="manager-card__body">
|
|
60
|
+
<div v-if="slotHasContent($slots.default)" class="manager-card__body">
|
|
58
61
|
<slot />
|
|
59
62
|
</div>
|
|
60
63
|
|
|
61
|
-
<footer v-if="$slots.actions" class="manager-card__actions">
|
|
64
|
+
<footer v-if="slotHasContent($slots.actions)" class="manager-card__actions">
|
|
62
65
|
<slot name="actions" />
|
|
63
66
|
</footer>
|
|
64
67
|
</section>
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { Comment, Fragment, Text, type Slot, type VNode } from 'vue'
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* ¿El slot pinta algo de verdad? `$slots.x` es truthy en cuanto el padre
|
|
5
|
+
* declara el `<template #x>`, aunque dentro todo sea un v-if falso o un
|
|
6
|
+
* v-for vacío; evaluando los vnodes evitamos pintar contenedores vacíos
|
|
7
|
+
* (la parte inferior de las cards, con su padding y su divisoria).
|
|
8
|
+
*/
|
|
9
|
+
export function slotHasContent(slot?: Slot): boolean {
|
|
10
|
+
return slot ? vnodesHaveContent(slot()) : false
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
function vnodesHaveContent(nodes: VNode[]): boolean {
|
|
14
|
+
return nodes.some((node) => {
|
|
15
|
+
if (node.type === Comment) return false
|
|
16
|
+
if (node.type === Text) {
|
|
17
|
+
return typeof node.children === 'string' && node.children.trim() !== ''
|
|
18
|
+
}
|
|
19
|
+
if (node.type === Fragment) {
|
|
20
|
+
return Array.isArray(node.children) && vnodesHaveContent(node.children as VNode[])
|
|
21
|
+
}
|
|
22
|
+
return true
|
|
23
|
+
})
|
|
24
|
+
}
|
package/src/crud/EntityCard.vue
CHANGED
|
@@ -7,6 +7,8 @@
|
|
|
7
7
|
// solo para entidades con imagen/preview — sin imagen, sin franja.
|
|
8
8
|
import { SquarePen } from '@lucide/vue'
|
|
9
9
|
|
|
10
|
+
import { slotHasContent } from '../composables/slotHasContent'
|
|
11
|
+
|
|
10
12
|
withDefaults(
|
|
11
13
|
defineProps<{
|
|
12
14
|
title: string
|
|
@@ -50,7 +52,7 @@ defineSlots<{
|
|
|
50
52
|
:style="accentColor ? { '--entity-card-accent': accentColor } : undefined"
|
|
51
53
|
@click="clickable ? $emit('view') : undefined"
|
|
52
54
|
>
|
|
53
|
-
<div v-if="$slots.media" class="entity-card__media"><slot name="media" /></div>
|
|
55
|
+
<div v-if="slotHasContent($slots.media)" class="entity-card__media"><slot name="media" /></div>
|
|
54
56
|
|
|
55
57
|
<div class="entity-card__header">
|
|
56
58
|
<h3 class="entity-card__title">{{ title }}</h3>
|
|
@@ -69,9 +71,14 @@ defineSlots<{
|
|
|
69
71
|
</div>
|
|
70
72
|
</div>
|
|
71
73
|
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
74
|
+
<!-- slotHasContent y no $slots.x: con el template declarado pero todo
|
|
75
|
+
v-if falso dentro, la card no debe pintar la parte inferior vacía -->
|
|
76
|
+
<div
|
|
77
|
+
v-if="slotHasContent($slots.badges) || slotHasContent($slots.meta) || slotHasContent($slots.default)"
|
|
78
|
+
class="entity-card__content"
|
|
79
|
+
>
|
|
80
|
+
<div v-if="slotHasContent($slots.badges)" class="entity-card__badges"><slot name="badges" /></div>
|
|
81
|
+
<div v-if="slotHasContent($slots.meta)" class="entity-card__meta"><slot name="meta" /></div>
|
|
75
82
|
<slot />
|
|
76
83
|
</div>
|
|
77
84
|
</div>
|