@edc-motor/ui 0.5.2 → 0.5.4
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/ui",
|
|
3
|
-
"version": "0.5.
|
|
3
|
+
"version": "0.5.4",
|
|
4
4
|
"description": "EdC Motor — componentes públicos Vue 3 + tokens SCSS para webs de juegos de mesa (paquete fuente: lo compila el consumidor con Vite)",
|
|
5
5
|
"license": "GPL-3.0-only",
|
|
6
6
|
"type": "module",
|
|
@@ -26,7 +26,11 @@
|
|
|
26
26
|
bottom: 0;
|
|
27
27
|
z-index: 40; // por debajo de la cabecera fija del cascarón (50)
|
|
28
28
|
// En viewports mínimos deja sitio al asa (el telón cubre el resto).
|
|
29
|
-
|
|
29
|
+
// OJO: 100% y no 100vw — el ancho porcentual de un fixed resuelve contra
|
|
30
|
+
// el viewport REAL (sin la barra de scroll del navegador); con 100vw la
|
|
31
|
+
// scrollbar, cuando aparece, robaba su ancho y el asa/cierre quedaba
|
|
32
|
+
// fuera de pantalla en el tamaño más estrecho.
|
|
33
|
+
width: min(var(--app-right-sidebar-width), 100% - 36px);
|
|
30
34
|
transform: translateX(100%);
|
|
31
35
|
transition: transform 0.25s ease;
|
|
32
36
|
|
|
@@ -37,6 +37,10 @@
|
|
|
37
37
|
}
|
|
38
38
|
|
|
39
39
|
// Números de página clicables; el actual, marcado con aria-current.
|
|
40
|
+
// Los que NO son el actual van en caja como prev/next (fondo semiopaco +
|
|
41
|
+
// borde visibles ya en reposo); al hover, acento sutil: tinte de acento
|
|
42
|
+
// al 12% de fondo y el número en color de acento. El actual, como
|
|
43
|
+
// siempre: relleno de acento con texto de contraste.
|
|
40
44
|
&__number {
|
|
41
45
|
display: inline-flex;
|
|
42
46
|
align-items: center;
|
|
@@ -44,17 +48,19 @@
|
|
|
44
48
|
min-width: 32px;
|
|
45
49
|
height: 32px;
|
|
46
50
|
padding: 0 $space-1;
|
|
47
|
-
background:
|
|
48
|
-
border: 1px solid
|
|
51
|
+
background: color-mix(in srgb, $surface 65%, transparent);
|
|
52
|
+
border: 1px solid $border;
|
|
49
53
|
border-radius: $radius-sm;
|
|
50
54
|
color: $text-2;
|
|
51
55
|
font-size: $fs-13;
|
|
56
|
+
// Más peso sin tocar el tamaño de la caja (32px se quedan como están).
|
|
57
|
+
font-weight: $k-fw-semibold;
|
|
52
58
|
font-variant-numeric: tabular-nums;
|
|
53
|
-
transition: color 0.15s ease, border-color 0.15s ease;
|
|
59
|
+
transition: color 0.15s ease, background-color 0.15s ease, border-color 0.15s ease;
|
|
54
60
|
|
|
55
61
|
&:hover {
|
|
56
|
-
color: $
|
|
57
|
-
|
|
62
|
+
color: $accent-500;
|
|
63
|
+
background: color-mix(in srgb, $accent-500 12%, transparent);
|
|
58
64
|
}
|
|
59
65
|
|
|
60
66
|
&[aria-current="page"] {
|
|
@@ -17,6 +17,15 @@
|
|
|
17
17
|
padding-block: 4px;
|
|
18
18
|
}
|
|
19
19
|
|
|
20
|
+
// Variante compacta (prop compactTrigger): alto FIJO del select simple y
|
|
21
|
+
// resumen en una línea (el .base-select__value de arriba ya elipsa); las
|
|
22
|
+
// elegidas se pintan fuera (chips del consumidor), no dentro del trigger.
|
|
23
|
+
&--compact .base-select__trigger {
|
|
24
|
+
height: $input-height;
|
|
25
|
+
min-height: 0;
|
|
26
|
+
padding-block: 0;
|
|
27
|
+
}
|
|
28
|
+
|
|
20
29
|
&__tags {
|
|
21
30
|
display: flex;
|
|
22
31
|
flex-wrap: wrap;
|
|
@@ -37,8 +37,9 @@
|
|
|
37
37
|
min-width: 0;
|
|
38
38
|
}
|
|
39
39
|
|
|
40
|
-
// Tarjeta (enlace o div): al pasar, SOLO
|
|
41
|
-
// desplazarse). El foco por teclado
|
|
40
|
+
// Tarjeta (enlace o div): al pasar, SOLO un glow sutil del color de
|
|
41
|
+
// acento por los cuatro lados (sin desplazarse). El foco por teclado
|
|
42
|
+
// conserva su halo de acento.
|
|
42
43
|
&__item {
|
|
43
44
|
display: block;
|
|
44
45
|
width: 100%;
|
|
@@ -50,7 +51,7 @@
|
|
|
50
51
|
}
|
|
51
52
|
|
|
52
53
|
a.preview-grid__item:hover {
|
|
53
|
-
box-shadow: $
|
|
54
|
+
box-shadow: 0 0 12px 2px color-mix(in srgb, $accent-500 40%, transparent);
|
|
54
55
|
}
|
|
55
56
|
|
|
56
57
|
a.preview-grid__item:focus-visible {
|
|
@@ -13,6 +13,11 @@ import type { SelectOption } from './BaseSelect.vue'
|
|
|
13
13
|
// BaseSelect). El trigger pinta las elegidas como etiquetas con aspa: se
|
|
14
14
|
// quitan desde ahí sin abrir el panel (también con Backspace); así no
|
|
15
15
|
// hace falta ningún texto "N seleccionadas" que traducir.
|
|
16
|
+
// Con `compactTrigger` (opt-in) el trigger NO crece: mantiene el alto fijo
|
|
17
|
+
// del select simple y, en vez de etiquetas, pinta un resumen en una línea
|
|
18
|
+
// (las elegidas separadas por comas, con elipsis); quitar una elegida
|
|
19
|
+
// queda para fuera (el consumidor pinta sus propios chips) o para el
|
|
20
|
+
// propio panel/Backspace. Sin la prop, todo sigue como siempre.
|
|
16
21
|
const props = withDefaults(
|
|
17
22
|
defineProps<{
|
|
18
23
|
modelValue?: (string | number)[]
|
|
@@ -20,12 +25,17 @@ const props = withDefaults(
|
|
|
20
25
|
options: SelectOption[]
|
|
21
26
|
/** Texto en reposo (sin nada marcado), p. ej. "Todas". */
|
|
22
27
|
placeholder?: string
|
|
28
|
+
/**
|
|
29
|
+
* Trigger compacto de alto fijo: resumen en una línea (labels con
|
|
30
|
+
* comas y elipsis) en lugar de etiquetas con aspa dentro del trigger.
|
|
31
|
+
*/
|
|
32
|
+
compactTrigger?: boolean
|
|
23
33
|
error?: string
|
|
24
34
|
hint?: string
|
|
25
35
|
disabled?: boolean
|
|
26
36
|
id?: string
|
|
27
37
|
}>(),
|
|
28
|
-
{ modelValue: () => [], disabled: false },
|
|
38
|
+
{ modelValue: () => [], disabled: false, compactTrigger: false },
|
|
29
39
|
)
|
|
30
40
|
|
|
31
41
|
const emit = defineEmits<{ 'update:modelValue': [value: string[]] }>()
|
|
@@ -44,6 +54,9 @@ const selectedValues = computed(() => new Set(props.modelValue.map((v) => String
|
|
|
44
54
|
const isSelected = (option: SelectOption) => selectedValues.value.has(String(option.value))
|
|
45
55
|
const selectedOptions = computed(() => props.options.filter((o) => isSelected(o)))
|
|
46
56
|
|
|
57
|
+
/** Resumen de una línea del trigger compacto: labels separadas por comas. */
|
|
58
|
+
const summary = computed(() => selectedOptions.value.map((o) => o.label).join(', '))
|
|
59
|
+
|
|
47
60
|
/** Quita una elegida desde su etiqueta del trigger, sin tocar el panel. */
|
|
48
61
|
function removeOption(option: SelectOption) {
|
|
49
62
|
if (props.disabled) return
|
|
@@ -166,7 +179,7 @@ onBeforeUnmount(() => document.removeEventListener('mousedown', onOutside))
|
|
|
166
179
|
<div
|
|
167
180
|
ref="root"
|
|
168
181
|
class="form-field__select-wrapper base-select multi-select"
|
|
169
|
-
:class="{ 'is-open': open }"
|
|
182
|
+
:class="{ 'is-open': open, 'multi-select--compact': compactTrigger }"
|
|
170
183
|
>
|
|
171
184
|
<button
|
|
172
185
|
:id="selectId"
|
|
@@ -180,9 +193,13 @@ onBeforeUnmount(() => document.removeEventListener('mousedown', onOutside))
|
|
|
180
193
|
@click="toggle"
|
|
181
194
|
@keydown="onKeydown"
|
|
182
195
|
>
|
|
196
|
+
<!-- Trigger compacto (opt-in): resumen en una línea, sin etiquetas -->
|
|
197
|
+
<span v-if="compactTrigger && selectedOptions.length" class="base-select__value">
|
|
198
|
+
{{ summary }}
|
|
199
|
+
</span>
|
|
183
200
|
<!-- Elegidas como etiquetas con aspa (el aspa NO abre el panel);
|
|
184
201
|
span con role=button porque un button no puede anidar otro -->
|
|
185
|
-
<span v-if="selectedOptions.length" class="multi-select__tags">
|
|
202
|
+
<span v-else-if="selectedOptions.length" class="multi-select__tags">
|
|
186
203
|
<span v-for="option in selectedOptions" :key="option.value" class="multi-select__tag">
|
|
187
204
|
{{ option.label }}
|
|
188
205
|
<span
|