@edc-motor/admin-kit 0.5.5 → 0.5.7
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 +2 -2
- package/scss/components/_page-blocks.scss +18 -112
- package/src/content/PageBlocks.vue +26 -20
- package/src/content/SchemaFields.vue +70 -41
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@edc-motor/admin-kit",
|
|
3
|
-
"version": "0.5.
|
|
3
|
+
"version": "0.5.7",
|
|
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.5.
|
|
36
|
+
"@edc-motor/ui": "^0.5.7",
|
|
37
37
|
"axios": "^1.7.0"
|
|
38
38
|
},
|
|
39
39
|
"peerDependencies": {
|
|
@@ -143,36 +143,10 @@
|
|
|
143
143
|
|
|
144
144
|
&__flags { grid-area: flags; display: flex; gap: $space-1; }
|
|
145
145
|
|
|
146
|
-
//
|
|
147
|
-
//
|
|
148
|
-
//
|
|
149
|
-
//
|
|
150
|
-
&__common {
|
|
151
|
-
border-bottom: 1px dashed $border;
|
|
152
|
-
padding-bottom: $space-4;
|
|
153
|
-
display: grid;
|
|
154
|
-
gap: $space-3;
|
|
155
|
-
|
|
156
|
-
&-title {
|
|
157
|
-
color: $text-2;
|
|
158
|
-
font-size: $fs-13;
|
|
159
|
-
}
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
// Cada fila de General: dos columnas iguales, apiladas en un modal
|
|
163
|
-
// angosto (container query sobre el cuerpo del modal, no el viewport).
|
|
164
|
-
&__common-row {
|
|
165
|
-
display: grid;
|
|
166
|
-
grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
|
|
167
|
-
gap: $space-3;
|
|
168
|
-
align-items: start;
|
|
169
|
-
|
|
170
|
-
> .checkbox { display: flex; }
|
|
171
|
-
|
|
172
|
-
@container modal-body (max-width: #{$bp-sm - 1px}) {
|
|
173
|
-
grid-template-columns: 1fr;
|
|
174
|
-
}
|
|
175
|
-
}
|
|
146
|
+
// La sección "General" del modal de bloque y los campos del tipo van
|
|
147
|
+
// ahora en fieldsets del sistema compartido del ui (.form-fieldset con
|
|
148
|
+
// legend + filas .form-row): mismo lenguaje que el resto de formularios
|
|
149
|
+
// del admin. Aquí ya no queda CSS propio para ello.
|
|
176
150
|
|
|
177
151
|
// Bloques anidados (parent_id, sin límite de niveles): sangría por
|
|
178
152
|
// profundidad REAL — `--depth` lo pone el componente en línea.
|
|
@@ -190,88 +164,6 @@
|
|
|
190
164
|
|
|
191
165
|
&__field-main { min-width: 0; }
|
|
192
166
|
|
|
193
|
-
// Alineación junto a su campo: input flexible + select de ancho
|
|
194
|
-
// contenido (~180px). En un modal angosto (container query sobre el
|
|
195
|
-
// cuerpo del modal, no el viewport) se apilan, el select debajo.
|
|
196
|
-
&__field--row {
|
|
197
|
-
display: flex;
|
|
198
|
-
// ARRIBA (no al fondo): con un textarea alto (p. ej. el subtítulo) el
|
|
199
|
-
// select de alineación debe quedar a la altura de las etiquetas, no
|
|
200
|
-
// descolgado al fondo de la fila.
|
|
201
|
-
align-items: flex-start;
|
|
202
|
-
gap: $space-3;
|
|
203
|
-
|
|
204
|
-
.schema-fields__field-main { flex: 1 1 0; }
|
|
205
|
-
}
|
|
206
|
-
|
|
207
|
-
// Ancho justo para "Centrado"/"Izquierda" + etiqueta en es/en/eu sin
|
|
208
|
-
// cortarse (180px sobraba de aire).
|
|
209
|
-
&__field-align { flex: 0 0 140px; }
|
|
210
|
-
|
|
211
|
-
// Fila declarada en el esquema (Field::row): el grupo baja por recursión
|
|
212
|
-
// como un .schema-fields anidado — aquí solo se reparte en columnas
|
|
213
|
-
// iguales MIENTRAS QUEPAN (auto-fit: con poco ancho van cayendo solas);
|
|
214
|
-
// el checkbox se centra en vertical junto a sus compañeros de fila.
|
|
215
|
-
&__field--pair > .schema-fields {
|
|
216
|
-
grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
|
|
217
|
-
gap: $space-3;
|
|
218
|
-
align-items: start;
|
|
219
|
-
|
|
220
|
-
> .schema-fields__field:has(> .schema-fields__field-main > .checkbox) {
|
|
221
|
-
align-self: center;
|
|
222
|
-
}
|
|
223
|
-
}
|
|
224
|
-
|
|
225
|
-
// Imagen a dos columnas: el input a la izquierda, sus ajustes (posición,
|
|
226
|
-
// escalado, reparto de columnas) apilados a la derecha. `stretch` para que
|
|
227
|
-
// la columna de la imagen llene el alto de la fila; el cuadro de arrastre
|
|
228
|
-
// YA NO se estira con ella (0.4.28): conserva su tamaño natural (160×160)
|
|
229
|
-
// y se centra en el espacio — el centrado vive en el componente
|
|
230
|
-
// (_image-upload.scss de @edc-motor/ui), común a todos los inputs.
|
|
231
|
-
&__field--image-group {
|
|
232
|
-
display: grid;
|
|
233
|
-
grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
|
|
234
|
-
gap: $space-3;
|
|
235
|
-
align-items: stretch;
|
|
236
|
-
|
|
237
|
-
.schema-fields__field-main {
|
|
238
|
-
display: flex;
|
|
239
|
-
flex-direction: column;
|
|
240
|
-
min-width: 0;
|
|
241
|
-
}
|
|
242
|
-
|
|
243
|
-
.schema-fields__image {
|
|
244
|
-
display: flex;
|
|
245
|
-
flex-direction: column;
|
|
246
|
-
gap: $space-1;
|
|
247
|
-
flex: 1;
|
|
248
|
-
min-height: 0;
|
|
249
|
-
}
|
|
250
|
-
|
|
251
|
-
.image-upload {
|
|
252
|
-
flex: 1;
|
|
253
|
-
min-height: 0;
|
|
254
|
-
}
|
|
255
|
-
}
|
|
256
|
-
|
|
257
|
-
&__field-image-settings {
|
|
258
|
-
display: grid;
|
|
259
|
-
gap: $space-3;
|
|
260
|
-
}
|
|
261
|
-
|
|
262
|
-
@container modal-body (max-width: #{$bp-sm - 1px}) {
|
|
263
|
-
&__field--row {
|
|
264
|
-
flex-direction: column;
|
|
265
|
-
align-items: stretch;
|
|
266
|
-
}
|
|
267
|
-
&__field-align { flex-basis: auto; }
|
|
268
|
-
|
|
269
|
-
&__field--image-group { grid-template-columns: 1fr; }
|
|
270
|
-
|
|
271
|
-
// Las filas declaradas (Field::row) apilan en el modal angosto.
|
|
272
|
-
&__field--pair > .schema-fields { grid-template-columns: 1fr; }
|
|
273
|
-
}
|
|
274
|
-
|
|
275
167
|
&__color,
|
|
276
168
|
&__image {
|
|
277
169
|
display: grid;
|
|
@@ -319,3 +211,17 @@
|
|
|
319
211
|
font-weight: 600;
|
|
320
212
|
}
|
|
321
213
|
}
|
|
214
|
+
|
|
215
|
+
// Encaje de SchemaFields con las filas del sistema compartido (.form-row,
|
|
216
|
+
// @edc-motor/ui). Un .schema-fields que llega como HIJO directo de una fila
|
|
217
|
+
// (la recursión de las filas declaradas Field::row, o los mini-SchemaFields
|
|
218
|
+
// de la sección General de PageBlocks) se DISUELVE (display: contents): sus
|
|
219
|
+
// campos pasan a ser celdas directas de la fila — sin envoltorios que
|
|
220
|
+
// rompan el grid ni re-aniden gaps.
|
|
221
|
+
.form-row > .schema-fields { display: contents; }
|
|
222
|
+
|
|
223
|
+
// El checkbox de un campo del esquema se centra en vertical junto a sus
|
|
224
|
+
// compañeros de fila (que llevan etiqueta encima y quedarían descolgados).
|
|
225
|
+
.form-row .schema-fields__field:has(> .schema-fields__field-main > .checkbox) {
|
|
226
|
+
align-self: center;
|
|
227
|
+
}
|
|
@@ -660,13 +660,14 @@ defineExpose({ reload: load })
|
|
|
660
660
|
>
|
|
661
661
|
<template v-if="modalType">
|
|
662
662
|
<!-- General ARRIBA del todo (antes iba al fondo, como "Ajustes
|
|
663
|
-
comunes", y pasaba desapercibida)
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
663
|
+
comunes", y pasaba desapercibida), como fieldset del sistema
|
|
664
|
+
compartido (mismo lenguaje que el resto de formularios; el
|
|
665
|
+
primero no lleva raya): anchura + bloque padre; los
|
|
666
|
+
interruptores; color de fondo + alineación general. -->
|
|
667
|
+
<fieldset class="form-fieldset">
|
|
668
|
+
<legend>{{ L.common }}</legend>
|
|
669
|
+
|
|
670
|
+
<div class="form-row">
|
|
670
671
|
<SchemaFields
|
|
671
672
|
v-model="form"
|
|
672
673
|
:fields="generalWidthFields"
|
|
@@ -682,12 +683,12 @@ defineExpose({ reload: load })
|
|
|
682
683
|
/>
|
|
683
684
|
</div>
|
|
684
685
|
|
|
685
|
-
<div class="
|
|
686
|
+
<div class="form-row">
|
|
686
687
|
<BaseCheckbox v-model="formPrintable" :label="L.printable" />
|
|
687
688
|
<BaseCheckbox v-model="formIndexable" :label="L.indexable" />
|
|
688
689
|
</div>
|
|
689
690
|
|
|
690
|
-
<div class="
|
|
691
|
+
<div class="form-row">
|
|
691
692
|
<SchemaFields
|
|
692
693
|
v-model="form"
|
|
693
694
|
:fields="generalBackgroundFields"
|
|
@@ -703,17 +704,22 @@ defineExpose({ reload: load })
|
|
|
703
704
|
:translate="translate"
|
|
704
705
|
/>
|
|
705
706
|
</div>
|
|
706
|
-
</
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
707
|
+
</fieldset>
|
|
708
|
+
|
|
709
|
+
<!-- Los campos del TIPO, en su propio fieldset (la raya dashed
|
|
710
|
+
separa General del contenido, como antes). -->
|
|
711
|
+
<fieldset class="form-fieldset">
|
|
712
|
+
<legend>{{ L.panelContent }}</legend>
|
|
713
|
+
<SchemaFields
|
|
714
|
+
v-model="form"
|
|
715
|
+
:fields="typeFieldsWithAligns"
|
|
716
|
+
:locales="locales"
|
|
717
|
+
:api="api"
|
|
718
|
+
:icons="icons"
|
|
719
|
+
:rich-labels="richLabels"
|
|
720
|
+
:translate="translate"
|
|
721
|
+
/>
|
|
722
|
+
</fieldset>
|
|
717
723
|
</template>
|
|
718
724
|
</EditModal>
|
|
719
725
|
|
|
@@ -67,24 +67,30 @@ const emit = defineEmits<{ 'update:modelValue': [value: Record<string, unknown>]
|
|
|
67
67
|
|
|
68
68
|
// Convenciones genéricas de agrupado (doc 03 ampliado):
|
|
69
69
|
//
|
|
70
|
+
// El layout se pinta con las filas del sistema compartido del ui
|
|
71
|
+
// (.form-row y variantes: columnas FIJAS + cortes de container query sobre
|
|
72
|
+
// modal-body; nada de auto-fit):
|
|
73
|
+
//
|
|
70
74
|
// 1) Alineaciones junto a su campo: un select `<base>_align` cuyo campo
|
|
71
75
|
// `<base>` (o `<base>_text`, caso de `button_align`/`button_text`) esté
|
|
72
|
-
// en la MISMA lista se pinta junto a él
|
|
73
|
-
//
|
|
74
|
-
//
|
|
75
|
-
//
|
|
76
|
-
//
|
|
77
|
-
//
|
|
78
|
-
//
|
|
79
|
-
//
|
|
80
|
-
//
|
|
76
|
+
// en la MISMA lista se pinta junto a él en una .form-row--wide-left —
|
|
77
|
+
// el campo (input/textarea/wysiwyg) ancho a la izquierda, el select
|
|
78
|
+
// estrecho a la derecha (PageBlocks inyecta title_align/subtitle_align
|
|
79
|
+
// —comunes del motor— junto a title/subtitle antes de pasar la lista
|
|
80
|
+
// aquí). El `align` general del bloque no tiene campo objetivo ("align"
|
|
81
|
+
// no acaba en "_align" con un prefijo no vacío) y queda fuera.
|
|
82
|
+
// 2) Imagen a dos columnas (.form-row--media): el campo `image` con alguno
|
|
83
|
+
// de sus ajustes (`image_position`, `image_fit`, `image_columns`) en la
|
|
84
|
+
// misma lista se agrupa con ellos — la celda izquierda (el input) llena
|
|
85
|
+
// todo el alto de la fila; la derecha es la pila de ajustes.
|
|
81
86
|
// 3) Filas DECLARADAS en el esquema (Field::row('nombre')): los campos que
|
|
82
|
-
// comparten `row` van juntos en una
|
|
83
|
-
//
|
|
84
|
-
//
|
|
85
|
-
//
|
|
86
|
-
// del esquema: gana a las
|
|
87
|
-
//
|
|
87
|
+
// comparten `row` van juntos en una .form-row (--3 si son 3+; en un
|
|
88
|
+
// modal angosto apilan). Se pintan por RECURSIÓN sobre este mismo
|
|
89
|
+
// componente (los compañeros pierden su `row` al bajar, para no
|
|
90
|
+
// re-agrupar en bucle; el .schema-fields anidado se disuelve por CSS).
|
|
91
|
+
// La fila declarada es intención EXPLÍCITA del esquema: gana a las
|
|
92
|
+
// convenciones 1 y 2 — un campo con `row` queda fuera del emparejado
|
|
93
|
+
// implícito (tanto de origen como de destino).
|
|
88
94
|
const IMAGE_SETTING_KEYS = ['image_position', 'image_fit', 'image_columns']
|
|
89
95
|
|
|
90
96
|
interface LayoutItem {
|
|
@@ -243,9 +249,15 @@ function addLabel(): string {
|
|
|
243
249
|
<template>
|
|
244
250
|
<div class="schema-fields">
|
|
245
251
|
<template v-for="{ field, align, imageSettings, rowFields } in layout" :key="field.key">
|
|
246
|
-
<!-- Fila declarada (Field::row): los campos del grupo por recursión
|
|
247
|
-
|
|
248
|
-
|
|
252
|
+
<!-- Fila declarada (Field::row): los campos del grupo por recursión
|
|
253
|
+
sobre una .form-row del ui (columnas fijas: 2, o 3 si la fila trae
|
|
254
|
+
3+ campos; el .schema-fields anidado se disuelve por CSS y los
|
|
255
|
+
compañeros bajan sin `row`) -->
|
|
256
|
+
<div
|
|
257
|
+
v-if="rowFields"
|
|
258
|
+
class="schema-fields__field form-row"
|
|
259
|
+
:class="{ 'form-row--3': rowFields.length >= 3 }"
|
|
260
|
+
>
|
|
249
261
|
<SchemaFields
|
|
250
262
|
:fields="rowFields"
|
|
251
263
|
:model-value="modelValue"
|
|
@@ -257,14 +269,45 @@ function addLabel(): string {
|
|
|
257
269
|
@update:model-value="(v) => emit('update:modelValue', v)"
|
|
258
270
|
/>
|
|
259
271
|
</div>
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
272
|
+
|
|
273
|
+
<!-- Fila de imagen (convención 2), el caso especial del sistema: el
|
|
274
|
+
input de imagen es UNA sola celda a todo el alto (izquierda) y los
|
|
275
|
+
ajustes (posición, escalado, reparto de columnas) van apilados en
|
|
276
|
+
la columna derecha (.form-row__stack) -->
|
|
277
|
+
<div v-else-if="imageSettings" class="schema-fields__field form-row form-row--media">
|
|
278
|
+
<TranslatableImage
|
|
279
|
+
v-if="field.translatable"
|
|
280
|
+
:model-value="imageTranslations(field)"
|
|
281
|
+
:locales="locales"
|
|
282
|
+
:label="label(field)"
|
|
283
|
+
:required="field.required"
|
|
284
|
+
@update:model-value="(v) => set(field.key, v)"
|
|
285
|
+
/>
|
|
286
|
+
<div v-else class="schema-fields__image">
|
|
287
|
+
<span class="form-field__label">{{ label(field) }}</span>
|
|
288
|
+
<ImageUpload
|
|
289
|
+
:model-value="imageFile(field)"
|
|
290
|
+
:current-url="imageCurrentUrl(field)"
|
|
291
|
+
@update:model-value="(f: File | null) => set(field.key, f)"
|
|
292
|
+
@remove="set(field.key, null)"
|
|
293
|
+
/>
|
|
294
|
+
</div>
|
|
295
|
+
<div class="form-row__stack">
|
|
296
|
+
<BaseSelect
|
|
297
|
+
v-for="setting in imageSettings"
|
|
298
|
+
:key="setting.key"
|
|
299
|
+
:model-value="(modelValue[setting.key] as string) ?? (setting.default as string) ?? ''"
|
|
300
|
+
:label="label(setting)"
|
|
301
|
+
:options="selectOptions(setting)"
|
|
302
|
+
@update:model-value="(v) => set(setting.key, v)"
|
|
303
|
+
/>
|
|
304
|
+
</div>
|
|
305
|
+
</div>
|
|
306
|
+
|
|
307
|
+
<!-- Campo suelto — o, con su select de alineación al lado (convención
|
|
308
|
+
1), fila ancha-izquierda del ui: el campo (input/textarea/wysiwyg)
|
|
309
|
+
a la izquierda y el select pequeño a la derecha -->
|
|
310
|
+
<div v-else class="schema-fields__field" :class="{ 'form-row form-row--wide-left': !!align }">
|
|
268
311
|
<div class="schema-fields__field-main">
|
|
269
312
|
<!-- Traducibles: text / textarea / richtext van al TranslatableInput -->
|
|
270
313
|
<TranslatableInput
|
|
@@ -433,28 +476,14 @@ function addLabel(): string {
|
|
|
433
476
|
</div>
|
|
434
477
|
|
|
435
478
|
<!-- Alineación del campo (title_align/subtitle_align/author_align/…),
|
|
436
|
-
en la misma fila que su campo (columna
|
|
479
|
+
en la misma fila que su campo (columna derecha, estrecha). -->
|
|
437
480
|
<BaseSelect
|
|
438
481
|
v-if="align"
|
|
439
|
-
class="schema-fields__field-align"
|
|
440
482
|
:model-value="(modelValue[align.key] as string) ?? (align.default as string) ?? ''"
|
|
441
483
|
:label="label(align)"
|
|
442
484
|
:options="selectOptions(align)"
|
|
443
485
|
@update:model-value="(v) => set(align!.key, v)"
|
|
444
486
|
/>
|
|
445
|
-
|
|
446
|
-
<!-- Ajustes de la imagen (image_position/image_fit/image_columns),
|
|
447
|
-
apilados en la segunda columna junto al input de imagen. -->
|
|
448
|
-
<div v-if="imageSettings" class="schema-fields__field-image-settings">
|
|
449
|
-
<BaseSelect
|
|
450
|
-
v-for="setting in imageSettings"
|
|
451
|
-
:key="setting.key"
|
|
452
|
-
:model-value="(modelValue[setting.key] as string) ?? (setting.default as string) ?? ''"
|
|
453
|
-
:label="label(setting)"
|
|
454
|
-
:options="selectOptions(setting)"
|
|
455
|
-
@update:model-value="(v) => set(setting.key, v)"
|
|
456
|
-
/>
|
|
457
|
-
</div>
|
|
458
487
|
</div>
|
|
459
488
|
</template>
|
|
460
489
|
</div>
|