lf-pagebuilder-vue 0.0.68 → 0.0.70
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/README.md +529 -537
- package/dist/atenea/index.d.ts +9 -0
- package/dist/atenea/tokenHandler.d.ts +56 -0
- package/dist/atenea.cjs +1 -0
- package/dist/atenea.js +56 -0
- package/dist/components/BodySection.vue.d.ts +8 -4
- package/dist/components/ColConfig.vue.d.ts +7 -4
- package/dist/components/FieldsForm.vue.d.ts +18 -0
- package/dist/components/GlobalConfig.vue.d.ts +1 -0
- package/dist/components/InitialComponent.vue.d.ts +4 -0
- package/dist/components/Pagebuilder.vue.d.ts +12 -0
- package/dist/components/RowConfig.vue.d.ts +9 -4
- package/dist/index.cjs +36 -36
- package/dist/index.js +6847 -6604
- package/dist/symfony-entry.d.ts +20 -1
- package/dist-symfony/lf-pagebuilder-iife.css +1 -1
- package/dist-symfony/lf-pagebuilder-iife.iife.js +86 -86
- package/dist-symfony/lf-pagebuilder-iife.iife.js.map +1 -1
- package/package.json +11 -6
package/README.md
CHANGED
|
@@ -1,537 +1,529 @@
|
|
|
1
|
-
# lf-pagebuilder-vue
|
|
2
|
-
|
|
3
|
-
Editor visual para construir páginas HTML usando los componentes de `libreria-astro-lefebvre`.
|
|
4
|
-
|
|
5
|
-
---
|
|
6
|
-
|
|
7
|
-
## ⚡ Referencia rápida — Todas las opciones
|
|
8
|
-
|
|
9
|
-
### Modo 1 — Componente Vue
|
|
10
|
-
|
|
11
|
-
```bash
|
|
12
|
-
npm install lf-pagebuilder-vue
|
|
13
|
-
```
|
|
14
|
-
|
|
15
|
-
```vue
|
|
16
|
-
<template>
|
|
17
|
-
<Pagebuilder
|
|
18
|
-
:isProduction="false"
|
|
19
|
-
:debugMode="false"
|
|
20
|
-
:submitForm="false"
|
|
21
|
-
inputId="mi-input-hidden"
|
|
22
|
-
:excludeComponentTypes="['SEO', 'Footer']"
|
|
23
|
-
:
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
|
41
|
-
|
|
42
|
-
| `
|
|
43
|
-
| `
|
|
44
|
-
| `
|
|
45
|
-
| `
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
<
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
```
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
```
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
})
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
import {
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
```
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
```
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
```bash
|
|
421
|
-
# 1. En lf-pagebuilder-vue
|
|
422
|
-
cd /ruta/a/lf-pagebuilder-vue
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
npm
|
|
441
|
-
```
|
|
442
|
-
|
|
443
|
-
####
|
|
444
|
-
|
|
445
|
-
```bash
|
|
446
|
-
#
|
|
447
|
-
cd /ruta/a/
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
```
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
```
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
# Añadir esta línea con tu token:
|
|
531
|
-
//registry.npmjs.org/:_authToken=TU_TOKEN_AQUI
|
|
532
|
-
```
|
|
533
|
-
|
|
534
|
-
4. **Ya puedes publicar**:
|
|
535
|
-
```bash
|
|
536
|
-
npm publish --access public
|
|
537
|
-
```
|
|
1
|
+
# lf-pagebuilder-vue
|
|
2
|
+
|
|
3
|
+
Editor visual para construir páginas HTML usando los componentes de `libreria-astro-lefebvre`.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## ⚡ Referencia rápida — Todas las opciones
|
|
8
|
+
|
|
9
|
+
### Modo 1 — Componente Vue
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
npm install lf-pagebuilder-vue
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
```vue
|
|
16
|
+
<template>
|
|
17
|
+
<Pagebuilder
|
|
18
|
+
:isProduction="false"
|
|
19
|
+
:debugMode="false"
|
|
20
|
+
:submitForm="false"
|
|
21
|
+
inputId="mi-input-hidden"
|
|
22
|
+
:excludeComponentTypes="['SEO', 'Footer']"
|
|
23
|
+
:excludeComponentTags="['boton', 'destacado']"
|
|
24
|
+
:includeOnlyComponentTags="['articulo']"
|
|
25
|
+
:visibleSections="['Header', 'Body', 'Footer']"
|
|
26
|
+
allowRenderMode="open"
|
|
27
|
+
limboToken="eyJ..."
|
|
28
|
+
ateneaToken="eyJ..."
|
|
29
|
+
:ledithorAiTools="['improve', 'improve-stream']"
|
|
30
|
+
client:only="vue"
|
|
31
|
+
/>
|
|
32
|
+
</template>
|
|
33
|
+
|
|
34
|
+
<script setup>
|
|
35
|
+
import { Pagebuilder } from 'lf-pagebuilder-vue';
|
|
36
|
+
import 'lf-pagebuilder-vue/styles';
|
|
37
|
+
</script>
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
| Prop | Tipo | Default | Descripción |
|
|
41
|
+
|------|------|---------|-------------|
|
|
42
|
+
| `isProduction` | `boolean` | `false` | `true` = API producción · `false` = API desarrollo |
|
|
43
|
+
| `debugMode` | `boolean` | `false` | Muestra panel de import/export JSON y botón de carga desde localStorage |
|
|
44
|
+
| `submitForm` | `boolean` | `false` | Al guardar, busca el `<form>` padre y hace `.submit()` automáticamente |
|
|
45
|
+
| `inputId` | `string \| null` | `null` | ID del `<input hidden>` donde se vuelca el JSON al guardar y del que se lee el estado inicial |
|
|
46
|
+
| `excludeComponentTypes` | `string[]` | `[]` | Categorías de componentes que NO aparecerán en el selector. "Repetidor" siempre se excluye. |
|
|
47
|
+
| `excludeComponentTags` | `string[]` | `[]` | Tags de componentes a excluir (lista negra). Un componente con cualquiera de estos tags no aparecerá. |
|
|
48
|
+
| `includeOnlyComponentTags` | `string[]` | `[]` | Solo muestra componentes que tengan al menos uno de estos tags (lista blanca). La exclusión tiene prioridad. |
|
|
49
|
+
| `visibleSections` | `string[]` | — | Secciones visibles. Si no se indica, se muestran todas. Valores: `Header`, `Body`, `Footer`, `Sidebar` |
|
|
50
|
+
| `allowRenderMode` | `'open' \| 'fullpage' \| 'onlybody'` | `'open'` | `open` = el usuario elige · `fullpage` = forzado página completa · `onlybody` = forzado solo body |
|
|
51
|
+
| `limboToken` | `string` | — | Token JWT para el gestor de imágenes Limbo. Obtenerlo server-side con `fetchLimboToken()` |
|
|
52
|
+
| `ateneaToken` | `string` | — | Token JWT de Atenea para las funcionalidades de IA en el editor de texto (LedithorEditor). Obtenerlo server-side con `fetchAteneaToken()`. Sin este token el botón de IA no aparece. |
|
|
53
|
+
| `ledithorAiTools` | `string[]` | — | Herramientas de IA a habilitar en el editor de texto. Solo se aplican si también se proporciona `ateneaToken`. Ej: `['improve', 'improve-stream']` |
|
|
54
|
+
| `viewOnly` | `boolean` | `false` | Modo solo visualización: oculta toda la UI de edición (toolbar, panel de componentes). Usar para la vista pública. |
|
|
55
|
+
|
|
56
|
+
> **Categorías disponibles para `excludeComponentTypes`:**
|
|
57
|
+
> `Call to Action`, `Contenido`, `Separador`, `Texto`, `Cabecera`, `Footer`, `Imagen`, `Repetidor`, `Formulario`, `Título`, `SEO`
|
|
58
|
+
|
|
59
|
+
---
|
|
60
|
+
|
|
61
|
+
### Modo 2 — Script IIFE (Symfony / Twig / cualquier backend)
|
|
62
|
+
|
|
63
|
+
```html
|
|
64
|
+
<link rel="stylesheet" href="/build/lf-pagebuilder-iife.css">
|
|
65
|
+
<script src="/build/lf-pagebuilder-iife.iife.js"></script>
|
|
66
|
+
|
|
67
|
+
<!-- EDITOR (crear) -->
|
|
68
|
+
<input
|
|
69
|
+
type="hidden"
|
|
70
|
+
class="js-lf-pagebuilder-vue-input"
|
|
71
|
+
name="pagebuilder[pageConfig]"
|
|
72
|
+
id="pagebuilder-new"
|
|
73
|
+
value=""
|
|
74
|
+
data-is-production="false"
|
|
75
|
+
data-debug-mode="true"
|
|
76
|
+
data-submit-form="true"
|
|
77
|
+
data-allow-render-mode="open"
|
|
78
|
+
data-limbo-token="eyJ..."
|
|
79
|
+
data-atenea-token="eyJ..."
|
|
80
|
+
data-ledithor-ai-tools='["improve","improve-stream"]'
|
|
81
|
+
/>
|
|
82
|
+
|
|
83
|
+
<!-- EDITOR (editar) -->
|
|
84
|
+
<input
|
|
85
|
+
type="hidden"
|
|
86
|
+
class="js-lf-pagebuilder-vue-input"
|
|
87
|
+
name="pagebuilder[pageConfig]"
|
|
88
|
+
id="pagebuilder-123"
|
|
89
|
+
value="{JSON existente del pageConfig}"
|
|
90
|
+
data-is-production="false"
|
|
91
|
+
data-submit-form="true"
|
|
92
|
+
data-exclude-component-types="SEO,Footer,Cabecera"
|
|
93
|
+
data-limbo-token="eyJ..."
|
|
94
|
+
/>
|
|
95
|
+
|
|
96
|
+
<!-- VISTA PÚBLICA (solo lectura) -->
|
|
97
|
+
<div id="lf-pagebuilder-render"></div>
|
|
98
|
+
<script>
|
|
99
|
+
window.LfPagebuilder.render({
|
|
100
|
+
el: '#lf-pagebuilder-render',
|
|
101
|
+
pageConfig: {{ pageConfig|raw }}, {# string JSON o objeto #}
|
|
102
|
+
isProduction: true
|
|
103
|
+
});
|
|
104
|
+
</script>
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
| Atributo `data-*` | Valores | Default | Descripción |
|
|
108
|
+
|-------------------|---------|---------|-------------|
|
|
109
|
+
| `data-is-production` | `"true"` \| `"false"` | `"false"` | Entorno de la API de renderizado |
|
|
110
|
+
| `data-debug-mode` | `"true"` \| `"false"` | `"false"` | Muestra panel de import/export JSON y botón de carga desde localStorage |
|
|
111
|
+
| `data-submit-form` | `"true"` \| `"false"` | `"false"` | Al guardar, busca el `<form>` padre y hace `.submit()` automáticamente |
|
|
112
|
+
| `data-exclude-component-types` | `string` (comas) | — | Categorías de componentes a excluir. Ej: `"SEO,Footer,Cabecera"` |
|
|
113
|
+
| `data-exclude-component-tags` | `string` (comas) | — | Tags de componentes a excluir (lista negra). Ej: `"boton,destacado"` |
|
|
114
|
+
| `data-include-only-component-tags` | `string` (comas) | — | Solo muestra componentes con estos tags (lista blanca). La exclusión tiene prioridad. |
|
|
115
|
+
| `data-visible-sections` | `string` (comas) | — | Secciones visibles. Ej: `"Header,Body"` |
|
|
116
|
+
| `data-allow-render-mode` | `"open"` \| `"fullpage"` \| `"onlybody"` | `"open"` | Controla el modo de renderizado |
|
|
117
|
+
| `data-limbo-token` | `string` | — | Token JWT de Limbo para el gestor de imágenes |
|
|
118
|
+
| `data-atenea-token` | `string` | — | Token JWT de Atenea para las funcionalidades de IA. Sin este token el botón de IA no aparece. |
|
|
119
|
+
| `data-ledithor-ai-tools` | `string` (JSON array) | — | Herramientas de IA a habilitar. Solo se aplican si hay `data-atenea-token`. Ej: `'["improve","improve-stream"]'` |
|
|
120
|
+
|
|
121
|
+
> El `id` del input se usa como clave de localStorage y como referencia interna. Si no tiene `id`, se genera uno automáticamente.
|
|
122
|
+
|
|
123
|
+
> **Compatibilidad de atributos:** El componente acepta también los tokens como atributos planos (sin prefijo `data-`): `limboToken="..."`, `ateneaToken="..."`, `ledithorAiTools='[...]'`. La forma recomendada es siempre `data-*`.
|
|
124
|
+
|
|
125
|
+
---
|
|
126
|
+
|
|
127
|
+
### API global `window.LfPagebuilder`
|
|
128
|
+
|
|
129
|
+
| Método | Descripción |
|
|
130
|
+
|--------|-------------|
|
|
131
|
+
| `LfPagebuilder.init(config?)` | Inicializa el editor en todos los elementos `.js-lf-pagebuilder-vue-input` de la página |
|
|
132
|
+
| `LfPagebuilder.render({ el, pageConfig, isProduction? })` | Renderiza la página en modo solo visualización (sin UI de edición) |
|
|
133
|
+
| `LfPagebuilder.destroyAll()` | Destruye todas las instancias activas |
|
|
134
|
+
| `LfPagebuilder.getInstances()` | Devuelve todas las instancias activas |
|
|
135
|
+
| `LfPagebuilder.setComponents(components)` | Reemplaza la lista de componentes disponibles |
|
|
136
|
+
| `LfPagebuilder.addComponent(component)` | Añade un componente a la lista disponible |
|
|
137
|
+
|
|
138
|
+
El IIFE se auto-inicializa en `DOMContentLoaded` si hay elementos con el selector `.js-lf-pagebuilder-vue-input` en el DOM. No es necesario llamar a `init()` manualmente.
|
|
139
|
+
|
|
140
|
+
---
|
|
141
|
+
|
|
142
|
+
## Integración con Symfony/Twig — Contrato completo
|
|
143
|
+
|
|
144
|
+
### Cómo funciona el intercambio de datos con el formulario
|
|
145
|
+
|
|
146
|
+
El componente actúa como un **"enhanced textarea"**:
|
|
147
|
+
|
|
148
|
+
1. **Lee su valor inicial de `input.value`** — en `onMounted`, el editor lee el JSON del `value` del input y lo carga como estado inicial del canvas. Si está vacío, el editor empieza en blanco (modo crear). Si contiene JSON, lo inicializa con esa configuración (modo editar).
|
|
149
|
+
|
|
150
|
+
2. **Escribe en `input.value` al guardar** — cuando el usuario pulsa "Guardar" dentro del editor, el JSON actualizado se escribe en `input.value`.
|
|
151
|
+
|
|
152
|
+
3. **Envía el formulario si `data-submit-form="true"`** — después de escribir en `input.value`, busca el `<form>` padre y llama a `.submit()`. Esto permite que Symfony valide y persista el `pageConfig`.
|
|
153
|
+
|
|
154
|
+
```twig
|
|
155
|
+
{# Crear #}
|
|
156
|
+
<form method="post" action="{{ path('landing_create') }}">
|
|
157
|
+
<input type="hidden"
|
|
158
|
+
id="pagebuilder-new"
|
|
159
|
+
name="pagebuilder[pageConfig]"
|
|
160
|
+
class="js-lf-pagebuilder-vue-input"
|
|
161
|
+
value=""
|
|
162
|
+
data-is-production="{{ app.environment == 'prod' ? 'true' : 'false' }}"
|
|
163
|
+
data-submit-form="true"
|
|
164
|
+
data-limbo-token="{{ limboToken }}"
|
|
165
|
+
data-atenea-token="{{ ateneaToken }}"
|
|
166
|
+
data-ledithor-ai-tools='["improve","improve-stream"]'
|
|
167
|
+
/>
|
|
168
|
+
{# El CSRF token y otros campos del formulario van aquí #}
|
|
169
|
+
</form>
|
|
170
|
+
|
|
171
|
+
{# Editar #}
|
|
172
|
+
<form method="post" action="{{ path('landing_edit', {id: landing.id}) }}">
|
|
173
|
+
<input type="hidden"
|
|
174
|
+
id="pagebuilder-{{ landing.id }}"
|
|
175
|
+
name="pagebuilder[pageConfig]"
|
|
176
|
+
class="js-lf-pagebuilder-vue-input"
|
|
177
|
+
value="{{ landing.pageConfig|json_encode }}"
|
|
178
|
+
data-is-production="{{ app.environment == 'prod' ? 'true' : 'false' }}"
|
|
179
|
+
data-submit-form="true"
|
|
180
|
+
data-exclude-component-types="SEO,Footer,Cabecera"
|
|
181
|
+
data-limbo-token="{{ limboToken }}"
|
|
182
|
+
/>
|
|
183
|
+
</form>
|
|
184
|
+
|
|
185
|
+
{# Vista pública #}
|
|
186
|
+
<div id="lf-pagebuilder-render"></div>
|
|
187
|
+
<script>
|
|
188
|
+
window.LfPagebuilder.render({
|
|
189
|
+
el: '#lf-pagebuilder-render',
|
|
190
|
+
pageConfig: {{ landing.pageConfig|raw }},
|
|
191
|
+
isProduction: {{ app.environment == 'prod' ? 'true' : 'false' }}
|
|
192
|
+
});
|
|
193
|
+
</script>
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
---
|
|
197
|
+
|
|
198
|
+
## Instalación
|
|
199
|
+
|
|
200
|
+
```bash
|
|
201
|
+
npm i lf-pagebuilder-vue
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
Luego en tu `package.json`, cambia la versión a `latest` para tener siempre la última:
|
|
205
|
+
|
|
206
|
+
```json
|
|
207
|
+
{
|
|
208
|
+
"dependencies": {
|
|
209
|
+
"lf-pagebuilder-vue": "latest"
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
```
|
|
213
|
+
|
|
214
|
+
## ¿Qué es?
|
|
215
|
+
|
|
216
|
+
El Pagebuilder permite al usuario arrastrar y configurar componentes de la librería de componentes Astro de Lefebvre para diseñar páginas de forma visual.
|
|
217
|
+
|
|
218
|
+
**El Pagebuilder NO renderiza la página final.** Genera un JSON de configuración que se envía a una API externa renderizadora, que es la encargada de generar el HTML final.
|
|
219
|
+
|
|
220
|
+
---
|
|
221
|
+
|
|
222
|
+
## Integración con Limbo (gestión de imágenes)
|
|
223
|
+
|
|
224
|
+
Si se quiere usar el sistema de imágenes Limbo desde el Pagebuilder:
|
|
225
|
+
|
|
226
|
+
**Variables de entorno** (`.env`):
|
|
227
|
+
|
|
228
|
+
```env
|
|
229
|
+
PUBLIC_LIMBO_PUBLIC_KEY=pk_tu_public_key
|
|
230
|
+
IS_PROD=FALSE
|
|
231
|
+
```
|
|
232
|
+
|
|
233
|
+
**Obtener token server-side y pasarlo al componente:**
|
|
234
|
+
|
|
235
|
+
```astro
|
|
236
|
+
---
|
|
237
|
+
import { Pagebuilder } from 'lf-pagebuilder-vue';
|
|
238
|
+
import { fetchLimboToken } from 'lf-pagebuilder-vue/limbo';
|
|
239
|
+
|
|
240
|
+
let limboToken = '';
|
|
241
|
+
try {
|
|
242
|
+
const result = await fetchLimboToken({
|
|
243
|
+
publicKey: import.meta.env.PUBLIC_LIMBO_PUBLIC_KEY || '',
|
|
244
|
+
isProduction: import.meta.env.IS_PROD === 'TRUE'
|
|
245
|
+
});
|
|
246
|
+
limboToken = result.token;
|
|
247
|
+
} catch (e) {
|
|
248
|
+
console.error('[Pagebuilder] Error obteniendo token de Limbo:', e);
|
|
249
|
+
}
|
|
250
|
+
---
|
|
251
|
+
|
|
252
|
+
<Pagebuilder
|
|
253
|
+
limboToken={limboToken}
|
|
254
|
+
isProduction={import.meta.env.IS_PROD === 'TRUE'}
|
|
255
|
+
inputId="mi-input"
|
|
256
|
+
client:only="vue"
|
|
257
|
+
/>
|
|
258
|
+
```
|
|
259
|
+
|
|
260
|
+
El token se obtiene en el frontmatter (server-side), evitando exponer la Public Key al cliente.
|
|
261
|
+
|
|
262
|
+
### `fetchLimboToken` — opciones
|
|
263
|
+
|
|
264
|
+
```ts
|
|
265
|
+
import { fetchLimboToken } from 'lf-pagebuilder-vue/limbo';
|
|
266
|
+
|
|
267
|
+
const { token, expires_in } = await fetchLimboToken({
|
|
268
|
+
publicKey: 'pk_xxx', // requerido
|
|
269
|
+
isProduction: false, // opcional, default: false
|
|
270
|
+
limboApiUrl: 'https://...' // opcional, sobreescribe isProduction
|
|
271
|
+
});
|
|
272
|
+
```
|
|
273
|
+
|
|
274
|
+
---
|
|
275
|
+
|
|
276
|
+
## Integración con Atenea (IA en el editor de texto)
|
|
277
|
+
|
|
278
|
+
Si se quiere usar las funcionalidades de IA de LedithorEditor (botón "Improve", etc.):
|
|
279
|
+
|
|
280
|
+
**Variables de entorno** (`.env`):
|
|
281
|
+
|
|
282
|
+
```env
|
|
283
|
+
ATENEA_USERNAME=ledithor
|
|
284
|
+
ATENEA_APIKEY=tu_apikey_aqui
|
|
285
|
+
IS_PROD=FALSE
|
|
286
|
+
```
|
|
287
|
+
|
|
288
|
+
**Obtener token server-side y pasarlo al componente:**
|
|
289
|
+
|
|
290
|
+
```astro
|
|
291
|
+
---
|
|
292
|
+
import { Pagebuilder } from 'lf-pagebuilder-vue';
|
|
293
|
+
import { fetchAteneaToken } from 'lf-pagebuilder-vue/atenea';
|
|
294
|
+
|
|
295
|
+
let ateneaToken = '';
|
|
296
|
+
try {
|
|
297
|
+
const result = await fetchAteneaToken({
|
|
298
|
+
username: import.meta.env.ATENEA_USERNAME || '',
|
|
299
|
+
apiKey: import.meta.env.ATENEA_APIKEY || '',
|
|
300
|
+
isProduction: import.meta.env.IS_PROD === 'TRUE'
|
|
301
|
+
});
|
|
302
|
+
ateneaToken = result.token;
|
|
303
|
+
} catch (e) {
|
|
304
|
+
console.error('[Pagebuilder] Error obteniendo token de Atenea:', e);
|
|
305
|
+
}
|
|
306
|
+
---
|
|
307
|
+
|
|
308
|
+
<Pagebuilder
|
|
309
|
+
ateneaToken={ateneaToken}
|
|
310
|
+
:ledithorAiTools="['improve', 'improve-stream']"
|
|
311
|
+
client:only="vue"
|
|
312
|
+
/>
|
|
313
|
+
```
|
|
314
|
+
|
|
315
|
+
> Si `ateneaToken` no se proporciona (o está vacío), el botón de IA no aparece en el editor de texto. `ledithorAiTools` solo tiene efecto si hay token.
|
|
316
|
+
|
|
317
|
+
### `fetchAteneaToken` — opciones
|
|
318
|
+
|
|
319
|
+
```ts
|
|
320
|
+
import { fetchAteneaToken } from 'lf-pagebuilder-vue/atenea';
|
|
321
|
+
|
|
322
|
+
const { token, expiresAt } = await fetchAteneaToken({
|
|
323
|
+
username: 'ledithor', // requerido
|
|
324
|
+
apiKey: 'tu_apikey', // requerido
|
|
325
|
+
isProduction: false, // opcional, default: false
|
|
326
|
+
ateneaApiUrl: 'https://...' // opcional, sobreescribe isProduction
|
|
327
|
+
});
|
|
328
|
+
// expiresAt: Unix timestamp (segundos) del claim `exp` del JWT
|
|
329
|
+
```
|
|
330
|
+
|
|
331
|
+
| Parámetro | Tipo | Default | Descripción |
|
|
332
|
+
|-----------|------|---------|-------------|
|
|
333
|
+
| `username` | `string` | — | Usuario de Atenea |
|
|
334
|
+
| `apiKey` | `string` | — | API Key del usuario |
|
|
335
|
+
| `isProduction` | `boolean` | `false` | `true` → `https://atenea.lefebvre.es` · `false` → URL de desarrollo |
|
|
336
|
+
| `ateneaApiUrl` | `string` | — | URL base personalizada (sobreescribe `isProduction`) |
|
|
337
|
+
|
|
338
|
+
---
|
|
339
|
+
|
|
340
|
+
## Funcionalidades del editor
|
|
341
|
+
|
|
342
|
+
### Color de fondo en filas y columnas
|
|
343
|
+
|
|
344
|
+
Cada fila y cada columna del editor puede tener un color de fondo personalizado con soporte de canal alpha (opacidad). El color se configura desde el panel de configuración de la fila o columna y se exporta junto al resto de la configuración del layout.
|
|
345
|
+
|
|
346
|
+
El color se almacena en el JSON de configuración como un valor `rgba(r, g, b, a)` dentro de la propiedad `backgroundColor`:
|
|
347
|
+
|
|
348
|
+
```json
|
|
349
|
+
{
|
|
350
|
+
"rows": [
|
|
351
|
+
{
|
|
352
|
+
"config": {
|
|
353
|
+
"backgroundColor": "rgba(255, 200, 100, 0.75)"
|
|
354
|
+
},
|
|
355
|
+
"columns": [
|
|
356
|
+
{
|
|
357
|
+
"config": {
|
|
358
|
+
"backgroundColor": "rgba(240, 240, 240, 1)"
|
|
359
|
+
},
|
|
360
|
+
"components": []
|
|
361
|
+
}
|
|
362
|
+
]
|
|
363
|
+
}
|
|
364
|
+
]
|
|
365
|
+
}
|
|
366
|
+
```
|
|
367
|
+
|
|
368
|
+
### Resaltado de elemento en edición
|
|
369
|
+
|
|
370
|
+
Cuando se abre el panel de configuración de una fila, columna o componente, el elemento correspondiente se resalta visualmente con un borde ámbar y un halo de sombra. El resaltado desaparece al cerrar el panel.
|
|
371
|
+
|
|
372
|
+
---
|
|
373
|
+
|
|
374
|
+
## Build
|
|
375
|
+
|
|
376
|
+
El proyecto tiene dos builds:
|
|
377
|
+
|
|
378
|
+
### Build estándar (librería npm)
|
|
379
|
+
|
|
380
|
+
```bash
|
|
381
|
+
npm run build
|
|
382
|
+
```
|
|
383
|
+
|
|
384
|
+
Genera en `dist/`:
|
|
385
|
+
- `index.js` — ES Module
|
|
386
|
+
- `index.cjs` — CommonJS
|
|
387
|
+
- `index.d.ts` — Tipos TypeScript
|
|
388
|
+
- `limbo.js` / `limbo.cjs` — Utilidades de Limbo (server-side)
|
|
389
|
+
- `atenea.js` / `atenea.cjs` — Utilidades de Atenea (server-side)
|
|
390
|
+
- `styles.css` — Estilos
|
|
391
|
+
|
|
392
|
+
### Build Symfony (IIFE)
|
|
393
|
+
|
|
394
|
+
```bash
|
|
395
|
+
npm run build:symfony
|
|
396
|
+
```
|
|
397
|
+
|
|
398
|
+
Genera en `dist-symfony/`:
|
|
399
|
+
- `lf-pagebuilder-iife.iife.js` — Script autocontenido (incluye Vue y todas las dependencias)
|
|
400
|
+
- `lf-pagebuilder-iife.css` — Estilos con utilidades Tailwind prefijadas (`mecano:`)
|
|
401
|
+
|
|
402
|
+
### Build completo
|
|
403
|
+
|
|
404
|
+
```bash
|
|
405
|
+
npm run build:all
|
|
406
|
+
```
|
|
407
|
+
|
|
408
|
+
Ejecuta ambos builds.
|
|
409
|
+
|
|
410
|
+
---
|
|
411
|
+
|
|
412
|
+
## ⚠️ Desarrollo local
|
|
413
|
+
|
|
414
|
+
> **IMPORTANTE**: Lee esta sección completa antes de trabajar con este proyecto localmente.
|
|
415
|
+
|
|
416
|
+
### Trabajar con `npm link`
|
|
417
|
+
|
|
418
|
+
Para probar cambios localmente en otro proyecto sin publicar:
|
|
419
|
+
|
|
420
|
+
```bash
|
|
421
|
+
# 1. En lf-pagebuilder-vue
|
|
422
|
+
cd /ruta/a/lf-pagebuilder-vue
|
|
423
|
+
npm link
|
|
424
|
+
|
|
425
|
+
# 2. En tu proyecto consumidor
|
|
426
|
+
cd /ruta/a/tu-proyecto
|
|
427
|
+
npm link lf-pagebuilder-vue
|
|
428
|
+
```
|
|
429
|
+
|
|
430
|
+
### ⚠️ CRÍTICO: Múltiples librerías con `npm link`
|
|
431
|
+
|
|
432
|
+
**Este proyecto depende de `libreria-astro-lefebvre`.** Si necesitas trabajar con ambas librerías localmente:
|
|
433
|
+
|
|
434
|
+
```bash
|
|
435
|
+
# ❌ INCORRECTO - El segundo comando ROMPE el primero
|
|
436
|
+
npm link lf-pagebuilder-vue
|
|
437
|
+
npm link libreria-astro-lefebvre
|
|
438
|
+
|
|
439
|
+
# ✅ CORRECTO - Linkear TODAS en UN SOLO comando
|
|
440
|
+
npm link lf-pagebuilder-vue libreria-astro-lefebvre
|
|
441
|
+
```
|
|
442
|
+
|
|
443
|
+
#### Flujo completo para trabajar con ambas librerías
|
|
444
|
+
|
|
445
|
+
```bash
|
|
446
|
+
# 1. En lf-pagebuilder-vue
|
|
447
|
+
cd /ruta/a/lf-pagebuilder-vue
|
|
448
|
+
npm link
|
|
449
|
+
|
|
450
|
+
# 2. En libreria-astro-lefebvre
|
|
451
|
+
cd /ruta/a/libreria-astro-lefebvre
|
|
452
|
+
npm link
|
|
453
|
+
|
|
454
|
+
# 3. En tu proyecto consumidor — AMBAS EN UN SOLO COMANDO
|
|
455
|
+
cd /ruta/a/tu-proyecto
|
|
456
|
+
npm link lf-pagebuilder-vue libreria-astro-lefebvre
|
|
457
|
+
```
|
|
458
|
+
|
|
459
|
+
#### Deshacer los enlaces
|
|
460
|
+
|
|
461
|
+
```bash
|
|
462
|
+
cd /ruta/a/tu-proyecto
|
|
463
|
+
npm unlink lf-pagebuilder-vue libreria-astro-lefebvre
|
|
464
|
+
npm install
|
|
465
|
+
```
|
|
466
|
+
|
|
467
|
+
### Watch mode
|
|
468
|
+
|
|
469
|
+
```bash
|
|
470
|
+
npm run dev
|
|
471
|
+
```
|
|
472
|
+
|
|
473
|
+
Ejecuta `vite build --watch` y recompila automáticamente cuando hay cambios.
|
|
474
|
+
|
|
475
|
+
---
|
|
476
|
+
|
|
477
|
+
### 📘 Publicar en npm
|
|
478
|
+
|
|
479
|
+
Para publicar una nueva versión:
|
|
480
|
+
|
|
481
|
+
1. **Subir la versión** en `package.json`
|
|
482
|
+
2. **Compilar y publicar**:
|
|
483
|
+
```bash
|
|
484
|
+
npm run build:all
|
|
485
|
+
npm publish --access public
|
|
486
|
+
```
|
|
487
|
+
|
|
488
|
+
#### Configurar acceso a npm (primera vez)
|
|
489
|
+
|
|
490
|
+
1. Solicitar acceso al equipo `desarrollowebteamlef` en npm
|
|
491
|
+
2. Crear un token de acceso en tu perfil de npm → Access Tokens
|
|
492
|
+
3. Añadir el token en `~/.npmrc`:
|
|
493
|
+
```
|
|
494
|
+
//registry.npmjs.org/:_authToken=TU_TOKEN_AQUI
|
|
495
|
+
```
|
|
496
|
+
|
|
497
|
+
---
|
|
498
|
+
|
|
499
|
+
## Instalación y dependencias
|
|
500
|
+
|
|
501
|
+
### Dependencias requeridas en el proyecto padre
|
|
502
|
+
|
|
503
|
+
```bash
|
|
504
|
+
npm install lf-pagebuilder-vue@latest vue@^3.3.0 vuedraggable@^4.1.0
|
|
505
|
+
```
|
|
506
|
+
|
|
507
|
+
### Configuración en proyectos Astro
|
|
508
|
+
|
|
509
|
+
```bash
|
|
510
|
+
npm install @astrojs/vue tailwindcss @tailwindcss/vite
|
|
511
|
+
```
|
|
512
|
+
|
|
513
|
+
En `astro.config.mjs`:
|
|
514
|
+
|
|
515
|
+
```js
|
|
516
|
+
import { defineConfig } from 'astro/config';
|
|
517
|
+
import vue from '@astrojs/vue';
|
|
518
|
+
import tailwindcss from '@tailwindcss/vite';
|
|
519
|
+
|
|
520
|
+
export default defineConfig({
|
|
521
|
+
integrations: [vue()],
|
|
522
|
+
vite: {
|
|
523
|
+
plugins: [tailwindcss()],
|
|
524
|
+
ssr: {
|
|
525
|
+
noExternal: ['libreria-astro-lefebvre', 'lf-pagebuilder-vue'],
|
|
526
|
+
},
|
|
527
|
+
},
|
|
528
|
+
});
|
|
529
|
+
```
|