@edc-motor/ui 0.4.28 → 0.4.30
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.4.
|
|
3
|
+
"version": "0.4.30",
|
|
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",
|
|
@@ -17,7 +17,12 @@
|
|
|
17
17
|
&__zone {
|
|
18
18
|
position: relative;
|
|
19
19
|
display: flex;
|
|
20
|
-
|
|
20
|
+
// Centrado EN EL CAMPO: horizontal siempre, y vertical cuando el
|
|
21
|
+
// contenedor le da alto extra (p. ej. el grupo a dos columnas del form
|
|
22
|
+
// de bloque) — los márgenes auto solo absorben espacio si lo hay.
|
|
23
|
+
align-self: center;
|
|
24
|
+
margin-block: auto;
|
|
25
|
+
flex-shrink: 0;
|
|
21
26
|
align-items: center;
|
|
22
27
|
justify-content: center;
|
|
23
28
|
width: 160px;
|
|
@@ -81,8 +86,10 @@
|
|
|
81
86
|
&__icon { width: 32px; height: 32px; color: $text-3; }
|
|
82
87
|
&__text { font-size: $fs-12; color: $text-2; }
|
|
83
88
|
|
|
84
|
-
// Nombre del fichero (pendiente o guardado) bajo la miniatura
|
|
89
|
+
// Nombre del fichero (pendiente o guardado) bajo la miniatura, centrado
|
|
90
|
+
// con ella.
|
|
85
91
|
&__name {
|
|
92
|
+
align-self: center;
|
|
86
93
|
max-width: 160px;
|
|
87
94
|
overflow: hidden;
|
|
88
95
|
font-size: $fs-12;
|
|
@@ -69,34 +69,21 @@
|
|
|
69
69
|
outline: none;
|
|
70
70
|
}
|
|
71
71
|
|
|
72
|
-
//
|
|
73
|
-
//
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
// Mini-popover del enlace: input de URL + botón de aplicar, misma
|
|
77
|
-
// posición/estética que el panel de iconos.
|
|
78
|
-
&__link-popover {
|
|
79
|
-
position: absolute;
|
|
80
|
-
top: calc(100% + 4px);
|
|
81
|
-
left: 0;
|
|
82
|
-
z-index: 100;
|
|
72
|
+
// Franjas del editor (URL del enlace, iconos): EN FLUJO entre la toolbar y
|
|
73
|
+
// el contenido — nada flota, así que dentro de un modal quedan siempre a la
|
|
74
|
+
// vista enteras. Mismo fondo que la toolbar, de la que son una extensión.
|
|
75
|
+
&__link-bar {
|
|
83
76
|
display: flex;
|
|
84
77
|
align-items: center;
|
|
85
78
|
gap: 2px;
|
|
86
|
-
// `width: max-content` (no simplemente `auto`): dentro de un ancla tan
|
|
87
|
-
// angosta como el propio botón (`.rich-text__picker`), el algoritmo de
|
|
88
|
-
// shrink-to-fit de un absoluto con solo `left` fijado lo recorta al
|
|
89
|
-
// ancho del ancla — el input de 220px quedaba aplastado a ~35px.
|
|
90
|
-
width: max-content;
|
|
91
79
|
padding: $space-1;
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
border-radius: $radius-md;
|
|
95
|
-
box-shadow: $shadow-md;
|
|
80
|
+
border-bottom: 1px solid $border;
|
|
81
|
+
background: $surface-2;
|
|
96
82
|
}
|
|
97
83
|
|
|
98
84
|
&__link-input {
|
|
99
|
-
|
|
85
|
+
flex: 1;
|
|
86
|
+
min-width: 0;
|
|
100
87
|
height: 30px;
|
|
101
88
|
padding: 0 $space-2;
|
|
102
89
|
border: 1px solid $input-border;
|
|
@@ -113,21 +100,16 @@
|
|
|
113
100
|
}
|
|
114
101
|
|
|
115
102
|
&__icons {
|
|
116
|
-
position: absolute;
|
|
117
|
-
top: calc(100% + 4px);
|
|
118
|
-
left: 0;
|
|
119
|
-
z-index: 100;
|
|
120
103
|
display: grid;
|
|
121
|
-
|
|
104
|
+
// A todo el ancho del editor: caben muchos más iconos por fila que en el
|
|
105
|
+
// popover de 5 columnas de antes; si aun así no entran, scroll propio.
|
|
106
|
+
grid-template-columns: repeat(auto-fill, minmax(36px, 1fr));
|
|
122
107
|
gap: 2px;
|
|
123
|
-
max-width: 220px;
|
|
124
108
|
max-height: 200px;
|
|
125
109
|
overflow-y: auto;
|
|
126
110
|
padding: $space-1;
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
border-radius: $radius-md;
|
|
130
|
-
box-shadow: $shadow-md;
|
|
111
|
+
border-bottom: 1px solid $border;
|
|
112
|
+
background: $surface-2;
|
|
131
113
|
}
|
|
132
114
|
|
|
133
115
|
&__icon {
|
|
@@ -330,18 +330,23 @@ function insertTable() {
|
|
|
330
330
|
}
|
|
331
331
|
|
|
332
332
|
// --- Selector de iconos ---
|
|
333
|
+
// Los paneles del editor (iconos y enlace) NO flotan: son franjas EN FLUJO
|
|
334
|
+
// entre la toolbar y el contenido — dentro de un modal quedan siempre a la
|
|
335
|
+
// vista (nada que recortar ni que anclar por coordenadas).
|
|
333
336
|
const pickerOpen = ref(false)
|
|
334
|
-
const pickerRef = ref<HTMLElement>()
|
|
337
|
+
const pickerRef = ref<HTMLElement | null>(null)
|
|
338
|
+
const iconsPanelRef = ref<HTMLElement | null>(null)
|
|
335
339
|
|
|
336
340
|
function insertIcon(icon: RichIcon) {
|
|
337
341
|
editor.value?.chain().focus().setImage({ src: icon.url, alt: icon.name, title: icon.name }).run()
|
|
338
342
|
pickerOpen.value = false
|
|
339
343
|
}
|
|
340
344
|
|
|
341
|
-
// --- Enlaces:
|
|
342
|
-
//
|
|
345
|
+
// --- Enlaces: franja con la URL (mismo patrón que el selector de iconos:
|
|
346
|
+
// botón + franja bajo la toolbar, cierra con Escape o click fuera) ---
|
|
343
347
|
const linkPopoverOpen = ref(false)
|
|
344
|
-
const linkPickerRef = ref<HTMLElement>()
|
|
348
|
+
const linkPickerRef = ref<HTMLElement | null>(null)
|
|
349
|
+
const linkPanelRef = ref<HTMLElement | null>(null)
|
|
345
350
|
const linkInputRef = ref<HTMLInputElement>()
|
|
346
351
|
const linkUrlInput = ref('')
|
|
347
352
|
|
|
@@ -369,8 +374,12 @@ function removeLink() {
|
|
|
369
374
|
|
|
370
375
|
function onClickOutside(e: MouseEvent) {
|
|
371
376
|
const target = e.target as Node
|
|
372
|
-
|
|
373
|
-
|
|
377
|
+
// Botón y franja son elementos hermanos: un click en cualquiera de los dos
|
|
378
|
+
// mantiene el panel abierto (insertar icono / escribir la URL).
|
|
379
|
+
if (!pickerRef.value?.contains(target) && !iconsPanelRef.value?.contains(target))
|
|
380
|
+
pickerOpen.value = false
|
|
381
|
+
if (!linkPickerRef.value?.contains(target) && !linkPanelRef.value?.contains(target))
|
|
382
|
+
linkPopoverOpen.value = false
|
|
374
383
|
}
|
|
375
384
|
onMounted(() => document.addEventListener('click', onClickOutside))
|
|
376
385
|
onBeforeUnmount(() => {
|
|
@@ -439,33 +448,18 @@ function onSourceInput(value: string) {
|
|
|
439
448
|
|
|
440
449
|
<span class="rich-text__sep" />
|
|
441
450
|
|
|
442
|
-
<!-- Enlace: botón
|
|
443
|
-
<
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
<div v-if="linkPopoverOpen" class="rich-text__link-popover">
|
|
455
|
-
<input
|
|
456
|
-
ref="linkInputRef"
|
|
457
|
-
v-model="linkUrlInput"
|
|
458
|
-
type="text"
|
|
459
|
-
class="rich-text__link-input"
|
|
460
|
-
:placeholder="t.linkUrl"
|
|
461
|
-
@keydown.enter.prevent="applyLink"
|
|
462
|
-
@keydown.escape.prevent="linkPopoverOpen = false"
|
|
463
|
-
/>
|
|
464
|
-
<button type="button" class="rich-text__tool" :title="t.linkApply" @click="applyLink">
|
|
465
|
-
<LinkIcon :size="14" />
|
|
466
|
-
</button>
|
|
467
|
-
</div>
|
|
468
|
-
</div>
|
|
451
|
+
<!-- Enlace: botón que abre la franja de la URL bajo la toolbar -->
|
|
452
|
+
<button
|
|
453
|
+
ref="linkPickerRef"
|
|
454
|
+
type="button"
|
|
455
|
+
class="rich-text__tool"
|
|
456
|
+
:class="{ 'rich-text__tool--active': editor?.isActive('link') || linkPopoverOpen }"
|
|
457
|
+
:title="t.link"
|
|
458
|
+
:disabled="disabled"
|
|
459
|
+
@click="toggleLinkPopover"
|
|
460
|
+
>
|
|
461
|
+
<LinkIcon :size="16" />
|
|
462
|
+
</button>
|
|
469
463
|
<button
|
|
470
464
|
v-if="editor?.isActive('link')"
|
|
471
465
|
type="button"
|
|
@@ -524,33 +518,20 @@ function onSourceInput(value: string) {
|
|
|
524
518
|
<Redo2 :size="16" />
|
|
525
519
|
</button>
|
|
526
520
|
|
|
527
|
-
<!-- Selector de iconos del juego -->
|
|
521
|
+
<!-- Selector de iconos del juego: abre la franja bajo la toolbar -->
|
|
528
522
|
<template v-if="icons.length">
|
|
529
523
|
<span class="rich-text__sep" />
|
|
530
|
-
<
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
<div v-if="pickerOpen" class="rich-text__icons">
|
|
542
|
-
<button
|
|
543
|
-
v-for="icon in icons"
|
|
544
|
-
:key="icon.url"
|
|
545
|
-
type="button"
|
|
546
|
-
class="rich-text__icon"
|
|
547
|
-
:title="icon.name"
|
|
548
|
-
@click="insertIcon(icon)"
|
|
549
|
-
>
|
|
550
|
-
<img :src="icon.url" :alt="icon.name" />
|
|
551
|
-
</button>
|
|
552
|
-
</div>
|
|
553
|
-
</div>
|
|
524
|
+
<button
|
|
525
|
+
ref="pickerRef"
|
|
526
|
+
type="button"
|
|
527
|
+
class="rich-text__tool"
|
|
528
|
+
:class="{ 'rich-text__tool--active': pickerOpen }"
|
|
529
|
+
:title="t.insertIcon"
|
|
530
|
+
:disabled="disabled"
|
|
531
|
+
@click="pickerOpen = !pickerOpen"
|
|
532
|
+
>
|
|
533
|
+
<Smile :size="16" />
|
|
534
|
+
</button>
|
|
554
535
|
</template>
|
|
555
536
|
</template>
|
|
556
537
|
|
|
@@ -567,6 +548,38 @@ function onSourceInput(value: string) {
|
|
|
567
548
|
</button>
|
|
568
549
|
</div>
|
|
569
550
|
|
|
551
|
+
<!-- Franja del enlace: EN FLUJO bajo la toolbar (dentro de un modal queda
|
|
552
|
+
siempre a la vista; los popovers flotantes se recortaban o quedaban
|
|
553
|
+
descolgados del editor) -->
|
|
554
|
+
<div v-if="linkPopoverOpen && !source" ref="linkPanelRef" class="rich-text__link-bar">
|
|
555
|
+
<input
|
|
556
|
+
ref="linkInputRef"
|
|
557
|
+
v-model="linkUrlInput"
|
|
558
|
+
type="text"
|
|
559
|
+
class="rich-text__link-input"
|
|
560
|
+
:placeholder="t.linkUrl"
|
|
561
|
+
@keydown.enter.prevent="applyLink"
|
|
562
|
+
@keydown.escape.prevent="linkPopoverOpen = false"
|
|
563
|
+
/>
|
|
564
|
+
<button type="button" class="rich-text__tool" :title="t.linkApply" @click="applyLink">
|
|
565
|
+
<LinkIcon :size="14" />
|
|
566
|
+
</button>
|
|
567
|
+
</div>
|
|
568
|
+
|
|
569
|
+
<!-- Franja de iconos: misma idea, a todo el ancho del editor -->
|
|
570
|
+
<div v-if="pickerOpen && !source" ref="iconsPanelRef" class="rich-text__icons">
|
|
571
|
+
<button
|
|
572
|
+
v-for="icon in icons"
|
|
573
|
+
:key="icon.url"
|
|
574
|
+
type="button"
|
|
575
|
+
class="rich-text__icon"
|
|
576
|
+
:title="icon.name"
|
|
577
|
+
@click="insertIcon(icon)"
|
|
578
|
+
>
|
|
579
|
+
<img :src="icon.url" :alt="icon.name" />
|
|
580
|
+
</button>
|
|
581
|
+
</div>
|
|
582
|
+
|
|
570
583
|
<textarea
|
|
571
584
|
v-if="source"
|
|
572
585
|
class="rich-text__source"
|