limbo-component 3.5.0 → 3.5.2
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/CHANGELOG.md +276 -93
- package/README.md +730 -137
- package/dist/limbo.cjs.js +1 -1
- package/dist/limbo.cjs.map +1 -1
- package/dist/limbo.es.js +144 -145
- package/dist/limbo.es.map +1 -1
- package/dist/limbo.min.js +1 -1
- package/dist/limbo.min.js.map +1 -1
- package/dist/limbo.umd.js +1 -1
- package/dist/limbo.umd.js.map +1 -1
- package/dist/types/App.d.ts +2 -1
- package/dist/types/App.d.ts.map +1 -1
- package/dist/types/components/Gallery.d.ts +2 -1
- package/dist/types/components/Gallery.d.ts.map +1 -1
- package/dist/types/components/TabUpload.d.ts +2 -1
- package/dist/types/components/TabUpload.d.ts.map +1 -1
- package/dist/types/components/UploadForm.d.ts +2 -1
- package/dist/types/components/UploadForm.d.ts.map +1 -1
- package/dist/types/core/AutoInputManager.d.ts +1 -0
- package/dist/types/core/AutoInputManager.d.ts.map +1 -1
- package/dist/types/core/ConfigManager.d.ts +7 -0
- package/dist/types/core/ConfigManager.d.ts.map +1 -1
- package/dist/types/core/LimboCore.d.ts.map +1 -1
- package/dist/types/utils/acceptUtils.d.ts +69 -0
- package/dist/types/utils/acceptUtils.d.ts.map +1 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,25 +1,36 @@
|
|
|
1
|
-
#
|
|
1
|
+
# Limbo Component
|
|
2
2
|
|
|
3
|
-
> Componente React
|
|
3
|
+
> Componente React embebible para gestión completa de activos digitales (DAM). Soporta imágenes, vídeos, audio, documentos PDF, Office y texto. Incluye galería, subida, recortador, visualizadores, generación con IA, búsqueda en Stock y gestión de carpetas.
|
|
4
4
|
|
|
5
5
|
[](https://www.npmjs.com/package/limbo-component)
|
|
6
|
-
[](https://en.wikipedia.org/wiki/Proprietary_software)
|
|
7
|
+
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
## Características
|
|
11
|
+
|
|
12
|
+
- **Galería multi-tipo** — Navega imágenes, vídeos, audio, documentos y texto del portal
|
|
13
|
+
- **Subida de archivos** — Drag & drop, validación por tipo/tamaño, preview por formato
|
|
14
|
+
- **Recortador avanzado** — Cropper.js 2.0 con presets, recortes obligatorios y libres
|
|
15
|
+
- **Visualizadores nativos** — ImageViewer (zoom/pan), VideoViewer, AudioViewer, PdfViewer, DocumentViewer, TextViewer
|
|
16
|
+
- **Generación con IA** — DALL-E, Midjourney y más a través de Atenea
|
|
17
|
+
- **Stock de imágenes** — Shutterstock y otros proveedores
|
|
18
|
+
- **Portales externos** — Acceso a activos de otros portales Limbo
|
|
19
|
+
- **Sistema de carpetas** — Organización, filtrado y movimiento de activos entre carpetas
|
|
20
|
+
- **Filtro `accept`** — Control granular de tipos de archivo permitidos por instancia
|
|
21
|
+
- **GIF inteligente** — Preserva animación original, hover-to-animate en galería
|
|
22
|
+
- **Múltiples modos** — `embed`, `modal`, `button` · `full`, `gallery-only`, `upload-only`, `crop-only`, `ia-only`
|
|
23
|
+
- **AutoInputs** — Integración automática con formularios HTML existentes
|
|
24
|
+
- **Métodos prefab** — `openGallery()`, `openUploader()`, `openCropper()` y más
|
|
25
|
+
- **Autenticación JWT** — 3 modos: session, manual, tokenProvider
|
|
26
|
+
- **Multi-formato** — ESM, CJS, UMD (con React 19 incluido en UMD)
|
|
27
|
+
- **CSS aislado** — Prefijo `lb:` evita colisiones con estilos del portal
|
|
28
|
+
- **Accesible** — ARIA, navegación por teclado, focus trap, screen readers
|
|
29
|
+
- **Responsive** — Mobile-friendly con container queries
|
|
30
|
+
|
|
31
|
+
---
|
|
32
|
+
|
|
33
|
+
## Instalación
|
|
23
34
|
|
|
24
35
|
### NPM / Yarn / PNPM
|
|
25
36
|
|
|
@@ -31,50 +42,56 @@ yarn add limbo-component
|
|
|
31
42
|
pnpm add limbo-component
|
|
32
43
|
```
|
|
33
44
|
|
|
34
|
-
### CDN (UMD)
|
|
45
|
+
### CDN (UMD — React incluido)
|
|
35
46
|
|
|
36
47
|
```html
|
|
37
48
|
<!-- CSS -->
|
|
38
|
-
<link
|
|
49
|
+
<link
|
|
50
|
+
rel="stylesheet"
|
|
51
|
+
href="https://limbo.lefebvre.es/cdn/component-limbo/latest/limbo.css"
|
|
52
|
+
/>
|
|
39
53
|
|
|
40
|
-
<!-- JS
|
|
54
|
+
<!-- JS -->
|
|
41
55
|
<script src="https://limbo.lefebvre.es/cdn/component-limbo/latest/limbo.min.js"></script>
|
|
42
56
|
```
|
|
43
57
|
|
|
44
|
-
|
|
58
|
+
---
|
|
59
|
+
|
|
60
|
+
## Autenticación
|
|
45
61
|
|
|
46
62
|
El componente soporta 3 modos de autenticación:
|
|
47
63
|
|
|
48
64
|
```javascript
|
|
49
|
-
// MODO 1:
|
|
50
|
-
//
|
|
65
|
+
// MODO 1: JWT con tokenProvider (RECOMENDADO para producción)
|
|
66
|
+
// Tu backend genera el token y lo expone en un endpoint propio
|
|
51
67
|
Limbo.configure({
|
|
52
68
|
publicKey: "pk_tu_clave_publica",
|
|
53
|
-
authMode: "
|
|
69
|
+
authMode: "jwt",
|
|
70
|
+
tokenProvider: async () => {
|
|
71
|
+
const res = await fetch("/api/limbo-token");
|
|
72
|
+
return (await res.json()).token;
|
|
73
|
+
},
|
|
54
74
|
});
|
|
55
75
|
|
|
56
76
|
// MODO 2: Manual (token proporcionado directamente)
|
|
57
|
-
// Útil cuando el backend ya generó el token
|
|
58
77
|
Limbo.configure({
|
|
59
78
|
publicKey: "pk_tu_clave_publica",
|
|
60
|
-
token: "eyJ0eXAiOiJKV1Q...",
|
|
61
79
|
authMode: "manual",
|
|
80
|
+
token: "eyJ0eXAiOiJKV1Q...",
|
|
62
81
|
});
|
|
63
82
|
|
|
64
|
-
// MODO 3:
|
|
65
|
-
// Proporciona una función async para renovación automática
|
|
83
|
+
// MODO 3: Session (usa cookies de sesión)
|
|
66
84
|
Limbo.configure({
|
|
67
85
|
publicKey: "pk_tu_clave_publica",
|
|
68
|
-
authMode: "
|
|
69
|
-
tokenProvider: async () => {
|
|
70
|
-
const response = await fetch("/api/limbo-token");
|
|
71
|
-
const data = await response.json();
|
|
72
|
-
return data.token;
|
|
73
|
-
},
|
|
86
|
+
authMode: "session",
|
|
74
87
|
});
|
|
75
88
|
```
|
|
76
89
|
|
|
77
|
-
|
|
90
|
+
> **Seguridad**: En producción, usa siempre `tokenProvider` o `manual`. Nunca expongas la API Key (`sk_...`) en código cliente.
|
|
91
|
+
|
|
92
|
+
---
|
|
93
|
+
|
|
94
|
+
## Uso Rápido
|
|
78
95
|
|
|
79
96
|
### Modo Embed (ESM)
|
|
80
97
|
|
|
@@ -82,9 +99,9 @@ Limbo.configure({
|
|
|
82
99
|
import Limbo from "limbo-component";
|
|
83
100
|
import "limbo-component/css";
|
|
84
101
|
|
|
85
|
-
// Configuración global
|
|
86
102
|
Limbo.configure({
|
|
87
103
|
publicKey: "pk_tu_clave_publica",
|
|
104
|
+
prod: true,
|
|
88
105
|
authMode: "jwt",
|
|
89
106
|
tokenProvider: async () => {
|
|
90
107
|
const res = await fetch("/api/limbo-token");
|
|
@@ -92,14 +109,15 @@ Limbo.configure({
|
|
|
92
109
|
},
|
|
93
110
|
});
|
|
94
111
|
|
|
95
|
-
//
|
|
112
|
+
// Selector completo: galería + subida + recortador
|
|
96
113
|
Limbo.create({
|
|
97
114
|
container: "#limbo-container",
|
|
98
115
|
mode: "embed",
|
|
99
|
-
modeUI: "full",
|
|
116
|
+
modeUI: "full",
|
|
100
117
|
callbacks: {
|
|
101
118
|
onSelect: (data) => console.log("Seleccionado:", data),
|
|
102
119
|
onUpload: (data) => console.log("Subido:", data),
|
|
120
|
+
onCropsSaved: (data) => console.log("Recortes:", data),
|
|
103
121
|
},
|
|
104
122
|
});
|
|
105
123
|
```
|
|
@@ -110,20 +128,22 @@ Limbo.create({
|
|
|
110
128
|
<!DOCTYPE html>
|
|
111
129
|
<html>
|
|
112
130
|
<head>
|
|
113
|
-
<link
|
|
131
|
+
<link
|
|
132
|
+
rel="stylesheet"
|
|
133
|
+
href="https://limbo.lefebvre.es/cdn/component-limbo/latest/limbo.css"
|
|
134
|
+
/>
|
|
114
135
|
</head>
|
|
115
136
|
<body>
|
|
116
137
|
<div id="limbo-app"></div>
|
|
117
138
|
|
|
118
|
-
<script src="https://limbo.lefebvre.es/cdn/component-limbo/latest/limbo.
|
|
139
|
+
<script src="https://limbo.lefebvre.es/cdn/component-limbo/latest/limbo.min.js"></script>
|
|
119
140
|
<script>
|
|
120
|
-
// Configurar
|
|
121
141
|
Limbo.configure({
|
|
122
142
|
publicKey: "pk_tu_clave_publica",
|
|
143
|
+
prod: true,
|
|
123
144
|
authMode: "session",
|
|
124
145
|
});
|
|
125
146
|
|
|
126
|
-
// Crear instancia
|
|
127
147
|
Limbo.create({
|
|
128
148
|
container: "#limbo-app",
|
|
129
149
|
mode: "embed",
|
|
@@ -134,153 +154,664 @@ Limbo.create({
|
|
|
134
154
|
</html>
|
|
135
155
|
```
|
|
136
156
|
|
|
137
|
-
|
|
157
|
+
---
|
|
158
|
+
|
|
159
|
+
## Filtro `accept` — Control de tipos de archivo
|
|
160
|
+
|
|
161
|
+
El parámetro `accept` permite controlar qué tipos de archivo puede seleccionar o subir el usuario. Usa la misma sintaxis que el atributo HTML `<input accept>`:
|
|
162
|
+
|
|
163
|
+
| Valor | Descripción |
|
|
164
|
+
| -------------------- | --------------------------------------------------- |
|
|
165
|
+
| `"image/*"` | Todas las imágenes (JPEG, PNG, GIF, WebP, SVG) |
|
|
166
|
+
| `"video/*"` | Todos los vídeos (MP4, WebM, MOV, AVI) |
|
|
167
|
+
| `"audio/*"` | Todo el audio (MP3, WAV, OGG, AAC, FLAC) |
|
|
168
|
+
| `"document/*"` | Todos los documentos (PDF, DOC, XLS, PPT, TXT, CSV) |
|
|
169
|
+
| `".pdf"` | Solo archivos PDF |
|
|
170
|
+
| `".pdf,.docx,.xlsx"` | Solo esos formatos específicos |
|
|
171
|
+
| `"image/*,.pdf"` | Imágenes + PDFs |
|
|
172
|
+
| `null` / omitido | Todo permitido (por defecto) |
|
|
173
|
+
|
|
174
|
+
### Adaptación automática de la UI
|
|
175
|
+
|
|
176
|
+
Cuando las imágenes están excluidas del `accept`, el componente adapta la interfaz automáticamente:
|
|
177
|
+
|
|
178
|
+
| Elemento | Con imágenes | Sin imágenes |
|
|
179
|
+
| --------------------- | ------------ | --------------------------------- |
|
|
180
|
+
| Tab "Generar con IA" | Visible | **Oculta** (solo genera imágenes) |
|
|
181
|
+
| Tab "Buscar en Stock" | Visible | **Oculta** (solo busca imágenes) |
|
|
182
|
+
| Tab "Otros portales" | Visible | **Oculta** |
|
|
183
|
+
| Recortador (Cropper) | Activo | **Desactivado** |
|
|
184
|
+
| Tab "Subir archivo" | Visible | Visible (filtrado por accept) |
|
|
185
|
+
| Galería | Muestra todo | Filtrada por tipos permitidos |
|
|
186
|
+
|
|
187
|
+
### Ejemplos
|
|
188
|
+
|
|
189
|
+
```javascript
|
|
190
|
+
// Selector de imágenes — UI completa (IA, Stock, Portales, Cropper)
|
|
191
|
+
Limbo.openGallery({
|
|
192
|
+
accept: "image/*",
|
|
193
|
+
onSelect: (img) => console.log("Imagen:", img),
|
|
194
|
+
});
|
|
195
|
+
|
|
196
|
+
// Selector de PDFs — Solo galería + subida, sin Cropper/IA/Stock
|
|
197
|
+
Limbo.openGallery({
|
|
198
|
+
accept: ".pdf",
|
|
199
|
+
onSelect: (doc) => console.log("PDF:", doc),
|
|
200
|
+
});
|
|
201
|
+
|
|
202
|
+
// Selector de documentos Office
|
|
203
|
+
Limbo.openUploader({
|
|
204
|
+
accept: ".pdf,.docx,.xlsx,.pptx",
|
|
205
|
+
onUpload: (doc) => console.log("Documento:", doc),
|
|
206
|
+
});
|
|
207
|
+
|
|
208
|
+
// Selector mixto: imágenes + PDFs
|
|
209
|
+
Limbo.createFullSelector("#file-picker", {
|
|
210
|
+
accept: "image/*,.pdf",
|
|
211
|
+
onSelect: (asset) => console.log("Archivo:", asset),
|
|
212
|
+
});
|
|
213
|
+
|
|
214
|
+
// Todo permitido (por defecto)
|
|
215
|
+
Limbo.openGallery({
|
|
216
|
+
onSelect: (asset) => console.log("Cualquier tipo:", asset),
|
|
217
|
+
});
|
|
218
|
+
```
|
|
219
|
+
|
|
220
|
+
### Con AutoInputs
|
|
138
221
|
|
|
139
222
|
```html
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
authMode: "session",
|
|
145
|
-
});
|
|
146
|
-
|
|
147
|
-
// Configurar AutoInputs
|
|
148
|
-
Limbo.configureAutoInputs({
|
|
149
|
-
selector: ".js-limbo", // Selector CSS para inputs
|
|
150
|
-
return: "url", // 'url' | 'json' | 'assetId' | 'base64'
|
|
151
|
-
mode: "modal",
|
|
152
|
-
modeUI: "full",
|
|
153
|
-
buttonText: "Seleccionar imagen",
|
|
154
|
-
showPreview: true,
|
|
155
|
-
});
|
|
156
|
-
</script>
|
|
157
|
-
|
|
158
|
-
<!-- Inputs se transforman automáticamente -->
|
|
159
|
-
<input type="text" class="js-limbo" name="avatar" />
|
|
160
|
-
|
|
161
|
-
<!-- Con recortes obligatorios via data attribute -->
|
|
223
|
+
<!-- Selector de imágenes -->
|
|
224
|
+
<input data-limbo-input-file data-accept="image/*" name="avatar" />
|
|
225
|
+
|
|
226
|
+
<!-- Solo PDFs -->
|
|
162
227
|
<input
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
228
|
+
data-limbo-input-file
|
|
229
|
+
data-accept=".pdf"
|
|
230
|
+
data-returntype="url"
|
|
231
|
+
name="contrato"
|
|
167
232
|
/>
|
|
168
233
|
|
|
169
|
-
<!--
|
|
170
|
-
<input
|
|
234
|
+
<!-- Imágenes + PDFs -->
|
|
235
|
+
<input data-limbo-input-file data-accept="image/*,.pdf" name="adjunto" />
|
|
236
|
+
|
|
237
|
+
<!-- Vídeos solamente -->
|
|
238
|
+
<input data-limbo-input-file data-accept="video/*" name="video_promo" />
|
|
239
|
+
|
|
240
|
+
<!-- Todo permitido (sin data-accept) -->
|
|
241
|
+
<input data-limbo-input-file name="archivo_generico" />
|
|
242
|
+
```
|
|
243
|
+
|
|
244
|
+
### En la API
|
|
245
|
+
|
|
246
|
+
La galería envía el filtro automáticamente al backend:
|
|
247
|
+
|
|
248
|
+
```txt
|
|
249
|
+
GET /api/assets?accept=image/*,.pdf
|
|
171
250
|
```
|
|
172
251
|
|
|
173
|
-
|
|
252
|
+
El backend resuelve las extensiones y categorías y filtra por `originalMime`.
|
|
253
|
+
|
|
254
|
+
---
|
|
255
|
+
|
|
256
|
+
## AutoInputs — Integración automática con formularios
|
|
174
257
|
|
|
175
|
-
|
|
258
|
+
El sistema AutoInputs transforma inputs HTML existentes en selectores de archivos Limbo. Detecta automáticamente inputs con el atributo configurado, oculta el input original y añade un botón estilizado.
|
|
259
|
+
|
|
260
|
+
### Configuración global
|
|
176
261
|
|
|
177
262
|
```javascript
|
|
178
263
|
Limbo.configure({
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
tokenProvider: null, // Función async para obtener token
|
|
264
|
+
publicKey: "pk_tu_clave_publica",
|
|
265
|
+
prod: true,
|
|
266
|
+
authMode: "session",
|
|
267
|
+
});
|
|
184
268
|
|
|
185
|
-
|
|
186
|
-
|
|
269
|
+
Limbo.configureAutoInputs({
|
|
270
|
+
// Selector — puede ser dataset o selector CSS
|
|
271
|
+
dataset: "data-limbo-input-file", // por defecto
|
|
272
|
+
// selector: ".js-limbo", // alternativa: selector CSS directo
|
|
187
273
|
|
|
188
|
-
//
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
274
|
+
// Formato de retorno del valor al input
|
|
275
|
+
return: "url", // "url" | "json" | "assetId" | "base64" | "object" | "fileName"
|
|
276
|
+
|
|
277
|
+
// Modo y UI
|
|
278
|
+
mode: "modal",
|
|
279
|
+
modeUI: "full",
|
|
280
|
+
modalSize: "fullscreen",
|
|
281
|
+
|
|
282
|
+
// Botón
|
|
283
|
+
buttonText: "Seleccionar archivo",
|
|
284
|
+
buttonStyle: "primary", // "primary" | "secondary" | "outline" | "ghost"
|
|
285
|
+
buttonClass: "limbo-auto-button",
|
|
286
|
+
|
|
287
|
+
// Comportamiento
|
|
288
|
+
showPreview: true,
|
|
289
|
+
autoAssign: true, // Asignar valor automáticamente al input
|
|
290
|
+
});
|
|
291
|
+
```
|
|
292
|
+
|
|
293
|
+
### Configuración por input via `data-*`
|
|
294
|
+
|
|
295
|
+
Cada input puede sobreescribir la configuración global usando atributos:
|
|
296
|
+
|
|
297
|
+
```html
|
|
298
|
+
<!-- Ejemplo básico -->
|
|
299
|
+
<input
|
|
300
|
+
type="hidden"
|
|
301
|
+
name="avatar"
|
|
302
|
+
data-limbo-input-file
|
|
303
|
+
data-returntype="url"
|
|
304
|
+
/>
|
|
305
|
+
|
|
306
|
+
<!-- Configuración completa por input -->
|
|
307
|
+
<input
|
|
308
|
+
type="hidden"
|
|
309
|
+
name="banner"
|
|
310
|
+
data-limbo-input-file
|
|
311
|
+
data-returntype="json"
|
|
312
|
+
data-accept="image/*"
|
|
313
|
+
data-modeui="full"
|
|
314
|
+
data-crop="16:9"
|
|
315
|
+
data-quality="0.85"
|
|
316
|
+
data-format="webp"
|
|
317
|
+
data-limbo-max-size="5MB"
|
|
318
|
+
data-limbo-button-text="Elegir banner"
|
|
319
|
+
data-limbo-button-style="outline"
|
|
320
|
+
data-mandatorycrops='[
|
|
321
|
+
{"label":"Desktop","width":1920,"height":400,"required":true},
|
|
322
|
+
{"label":"Mobile","width":640,"height":300,"required":true}
|
|
323
|
+
]'
|
|
324
|
+
/>
|
|
325
|
+
|
|
326
|
+
<!-- Solo galería, devuelve ID del asset -->
|
|
327
|
+
<input
|
|
328
|
+
type="hidden"
|
|
329
|
+
name="imagen_existente"
|
|
330
|
+
data-limbo-input-file
|
|
331
|
+
data-modeui="gallery-only"
|
|
332
|
+
data-returntype="assetId"
|
|
333
|
+
/>
|
|
334
|
+
|
|
335
|
+
<!-- Solo PDFs, devuelve URL -->
|
|
336
|
+
<input
|
|
337
|
+
type="hidden"
|
|
338
|
+
name="contrato_pdf"
|
|
339
|
+
data-limbo-input-file
|
|
340
|
+
data-accept=".pdf"
|
|
341
|
+
data-returntype="url"
|
|
342
|
+
data-limbo-button-text="Seleccionar PDF"
|
|
343
|
+
/>
|
|
344
|
+
|
|
345
|
+
<!-- Varios inputs diferentes en la misma página -->
|
|
346
|
+
<input data-limbo-input-file data-accept="image/*" name="hero" />
|
|
347
|
+
<input data-limbo-input-file data-accept=".pdf" name="terms" />
|
|
348
|
+
<input data-limbo-input-file data-accept="video/*" name="promo" />
|
|
349
|
+
```
|
|
350
|
+
|
|
351
|
+
### Atributos `data-*` soportados
|
|
352
|
+
|
|
353
|
+
| Atributo | Valores | Defecto | Descripción |
|
|
354
|
+
| ----------------------------------- | -------------------------------------------------------- | ------------------------ | ---------------------------------------------- |
|
|
355
|
+
| `data-returntype` | `url`, `json`, `assetId`, `base64`, `object`, `fileName` | `json` | Formato del valor devuelto al input |
|
|
356
|
+
| `data-accept` | Sintaxis HTML accept | `null` (todo) | Filtro de tipos de archivo |
|
|
357
|
+
| `data-modeui` | `full`, `gallery-only`, `upload-only`, `crop-only` | `full` | Modo funcional de la UI |
|
|
358
|
+
| `data-mode` | `modal`, `embed` | `modal` | Modo de renderizado |
|
|
359
|
+
| `data-features` | `gallery,upload,cropper` | `gallery,upload,cropper` | Features habilitadas (separadas por coma) |
|
|
360
|
+
| `data-crop` | `free`, `1:1`, `16:9`, `4:3`, `none` | `free` | Ratio de recorte |
|
|
361
|
+
| `data-quality` | `0.0` - `1.0` | `0.9` | Calidad de salida |
|
|
362
|
+
| `data-format` | `webp`, `jpg`, `png` | `webp` | Formato de salida |
|
|
363
|
+
| `data-modalsize` | `small`, `medium`, `large`, `fullscreen` | `fullscreen` | Tamaño del modal |
|
|
364
|
+
| `data-theme` | `light`, `dark` | `light` | Tema visual |
|
|
365
|
+
| `data-compact` | `true`, `false` | `false` | Modo compacto |
|
|
366
|
+
| `data-limbo-max-size` | `5MB`, `1024KB` | `10MB` | Tamaño máximo de archivo |
|
|
367
|
+
| `data-limbo-formats` | `jpg,png,webp` | `jpg,jpeg,png,webp` | Formatos permitidos (legacy) |
|
|
368
|
+
| `data-limbo-min-width` | Píxeles | `null` | Ancho mínimo de imagen |
|
|
369
|
+
| `data-limbo-min-height` | Píxeles | `null` | Alto mínimo de imagen |
|
|
370
|
+
| `data-limbo-max-width` | Píxeles | `null` | Ancho máximo de imagen |
|
|
371
|
+
| `data-limbo-max-height` | Píxeles | `null` | Alto máximo de imagen |
|
|
372
|
+
| `data-limbo-button-text` | Texto | `Seleccionar archivo` | Texto del botón |
|
|
373
|
+
| `data-limbo-button-style` | `primary`, `secondary`, `outline`, `ghost` | `primary` | Estilo del botón |
|
|
374
|
+
| `data-limbo-button-class` | Clase CSS | `limbo-auto-button` | Clase CSS adicional del botón |
|
|
375
|
+
| `data-limbo-show-preview` | `true`, `false` | `true` | Mostrar preview al seleccionar |
|
|
376
|
+
| `data-limbo-auto-assign` | `true`, `false` | `true` | Asignar valor al input automáticamente |
|
|
377
|
+
| `data-limbo-required` | `true`, `false` | `false` | Campo requerido |
|
|
378
|
+
| `data-limbo-disabled` | `true`, `false` | `false` | Input deshabilitado |
|
|
379
|
+
| `data-mandatorycrops` | JSON array | `null` | Recortes obligatorios |
|
|
380
|
+
| `data-limbo-allow-additional-crops` | `true`, `false` | `true` | Permitir recortes adicionales |
|
|
381
|
+
| `data-limbo-max-crops` | Número | `null` | Máximo de recortes seleccionables |
|
|
382
|
+
| `data-limbo-allow-select-new` | `true`, `false` | `true` | Permitir seleccionar nueva imagen en crop-only |
|
|
383
|
+
|
|
384
|
+
### Eventos DOM de AutoInputs
|
|
385
|
+
|
|
386
|
+
```javascript
|
|
387
|
+
// Resultado listo — se dispara en el input cuando se completa la selección
|
|
388
|
+
document.addEventListener("limbo:resultReady", (e) => {
|
|
389
|
+
const { input, value, imageData, config } = e.detail;
|
|
390
|
+
console.log(`Input "${input.name}" recibió:`, value);
|
|
391
|
+
});
|
|
392
|
+
|
|
393
|
+
// Compatibilidad con evento anterior
|
|
394
|
+
document.addEventListener("limbo:imageSelected", (e) => {
|
|
395
|
+
const { input, value, imageData } = e.detail;
|
|
396
|
+
});
|
|
397
|
+
|
|
398
|
+
// Errores
|
|
399
|
+
document.addEventListener("limbo:error", (e) => {
|
|
400
|
+
console.error("Error en input:", e.detail.error);
|
|
401
|
+
});
|
|
402
|
+
```
|
|
403
|
+
|
|
404
|
+
### Re-escaneo dinámico
|
|
405
|
+
|
|
406
|
+
Si añades inputs al DOM dinámicamente (SPA, AJAX), el MutationObserver los detecta automáticamente. También puedes forzar un re-escaneo:
|
|
407
|
+
|
|
408
|
+
```javascript
|
|
409
|
+
// Re-escanear todo el documento
|
|
410
|
+
Limbo.rescan();
|
|
411
|
+
|
|
412
|
+
// Re-escanear un contenedor específico
|
|
413
|
+
Limbo.rescan(document.getElementById("formulario-dinamico"));
|
|
414
|
+
|
|
415
|
+
// Escanear y activar con selector personalizado
|
|
416
|
+
Limbo.scanAndActivate(".js-limbo-new");
|
|
417
|
+
```
|
|
418
|
+
|
|
419
|
+
---
|
|
420
|
+
|
|
421
|
+
## Métodos Prefab
|
|
422
|
+
|
|
423
|
+
Métodos de conveniencia para los casos de uso más comunes. Todos aceptan el parámetro `accept` para filtrar tipos.
|
|
424
|
+
|
|
425
|
+
### Modales
|
|
426
|
+
|
|
427
|
+
#### `Limbo.openGallery(options)`
|
|
428
|
+
|
|
429
|
+
Abre la galería en modal para seleccionar un archivo existente.
|
|
430
|
+
|
|
431
|
+
```javascript
|
|
432
|
+
// Galería de imágenes
|
|
433
|
+
Limbo.openGallery({
|
|
434
|
+
accept: "image/*",
|
|
435
|
+
onSelect: (data) => {
|
|
436
|
+
document.getElementById("preview").src = data.url;
|
|
437
|
+
},
|
|
438
|
+
});
|
|
439
|
+
|
|
440
|
+
// Galería de PDFs
|
|
441
|
+
Limbo.openGallery({
|
|
442
|
+
accept: ".pdf",
|
|
443
|
+
title: "Seleccionar documento",
|
|
444
|
+
onSelect: (data) => {
|
|
445
|
+
document.getElementById("pdf-link").href = data.url;
|
|
446
|
+
},
|
|
447
|
+
});
|
|
448
|
+
|
|
449
|
+
// Galería de cualquier tipo
|
|
450
|
+
Limbo.openGallery({
|
|
451
|
+
onSelect: (data) => console.log("Seleccionado:", data),
|
|
452
|
+
autoClose: true, // Cerrar modal al seleccionar (por defecto: true)
|
|
453
|
+
size: "large", // "small" | "medium" | "large" | "fullscreen"
|
|
454
|
+
});
|
|
455
|
+
```
|
|
456
|
+
|
|
457
|
+
#### `Limbo.openUploader(options)`
|
|
458
|
+
|
|
459
|
+
Abre el uploader en modal para subir un archivo nuevo.
|
|
460
|
+
|
|
461
|
+
```javascript
|
|
462
|
+
// Subir imagen y navegar a galería tras subida
|
|
463
|
+
Limbo.openUploader({
|
|
464
|
+
accept: "image/*",
|
|
465
|
+
redirectToGallery: true, // Muestra galería tras subida (por defecto: true)
|
|
466
|
+
onUpload: (data) => console.log("Subido:", data),
|
|
467
|
+
});
|
|
468
|
+
|
|
469
|
+
// Subir documento y cerrar inmediatamente
|
|
470
|
+
Limbo.openUploader({
|
|
471
|
+
accept: ".pdf,.docx",
|
|
472
|
+
redirectToGallery: false,
|
|
473
|
+
onUpload: (data) => {
|
|
474
|
+
console.log("Documento subido:", data);
|
|
195
475
|
},
|
|
196
476
|
});
|
|
197
477
|
```
|
|
198
478
|
|
|
199
|
-
|
|
479
|
+
#### `Limbo.openCropper(imageUrl, options)`
|
|
480
|
+
|
|
481
|
+
Abre el recortador con una imagen externa (URL) para crear recortes.
|
|
482
|
+
|
|
483
|
+
```javascript
|
|
484
|
+
// Recortar imagen con dimensiones obligatorias
|
|
485
|
+
Limbo.openCropper("https://example.com/foto.jpg", {
|
|
486
|
+
mandatoryCrops: [
|
|
487
|
+
{ label: "Desktop", width: 1920, height: 400, required: true },
|
|
488
|
+
{ label: "Mobile", width: 640, height: 300, required: true },
|
|
489
|
+
{ label: "Thumbnail", width: 300, height: 300, required: true },
|
|
490
|
+
],
|
|
491
|
+
onComplete: (data) => {
|
|
492
|
+
console.log("Recortes creados:", data.crops);
|
|
493
|
+
data.crops.forEach((crop) => {
|
|
494
|
+
console.log(`${crop.name}: ${crop.url} (${crop.width}x${crop.height})`);
|
|
495
|
+
});
|
|
496
|
+
},
|
|
497
|
+
onCancelled: () => console.log("Cancelado por el usuario"),
|
|
498
|
+
onError: (err) => console.error("Error:", err),
|
|
499
|
+
});
|
|
500
|
+
|
|
501
|
+
// Recorte libre
|
|
502
|
+
Limbo.openCropper("https://example.com/banner.jpg", {
|
|
503
|
+
allowCustomCrops: true,
|
|
504
|
+
onComplete: (data) => console.log("Recortes:", data.crops),
|
|
505
|
+
});
|
|
506
|
+
```
|
|
507
|
+
|
|
508
|
+
### Embebidos
|
|
509
|
+
|
|
510
|
+
#### `Limbo.createInlineGallery(container, options)`
|
|
511
|
+
|
|
512
|
+
Galería permanente embebida en un contenedor.
|
|
513
|
+
|
|
514
|
+
```javascript
|
|
515
|
+
// Galería embebida de imágenes
|
|
516
|
+
const gallery = Limbo.createInlineGallery("#gallery-container", {
|
|
517
|
+
accept: "image/*",
|
|
518
|
+
onSelect: (data) => {
|
|
519
|
+
document.getElementById("selected-image").src = data.url;
|
|
520
|
+
},
|
|
521
|
+
onDelete: (assetId) => console.log("Eliminado:", assetId),
|
|
522
|
+
});
|
|
523
|
+
```
|
|
524
|
+
|
|
525
|
+
#### `Limbo.createInlineUploader(container, options)`
|
|
526
|
+
|
|
527
|
+
Formulario de subida permanente embebido.
|
|
528
|
+
|
|
529
|
+
```javascript
|
|
530
|
+
// Uploader embebido solo para PDFs
|
|
531
|
+
const uploader = Limbo.createInlineUploader("#upload-area", {
|
|
532
|
+
accept: ".pdf",
|
|
533
|
+
onUpload: (data) => console.log("PDF subido:", data),
|
|
534
|
+
});
|
|
535
|
+
```
|
|
536
|
+
|
|
537
|
+
#### `Limbo.createStandaloneCropper(container, imageUrl, options)`
|
|
538
|
+
|
|
539
|
+
Recortador embebido para una imagen específica.
|
|
540
|
+
|
|
541
|
+
```javascript
|
|
542
|
+
// Recortador embebido con recortes obligatorios
|
|
543
|
+
const cropper = Limbo.createStandaloneCropper(
|
|
544
|
+
"#cropper-container",
|
|
545
|
+
"https://example.com/imagen.jpg",
|
|
546
|
+
{
|
|
547
|
+
mandatoryCrops: [
|
|
548
|
+
{ label: "Avatar", width: 200, height: 200, required: true },
|
|
549
|
+
],
|
|
550
|
+
autoHideOnComplete: true,
|
|
551
|
+
onComplete: (data) => {
|
|
552
|
+
fetch("/api/save-avatar", {
|
|
553
|
+
method: "POST",
|
|
554
|
+
body: JSON.stringify({ url: data.crops[0].url }),
|
|
555
|
+
});
|
|
556
|
+
},
|
|
557
|
+
},
|
|
558
|
+
);
|
|
559
|
+
```
|
|
560
|
+
|
|
561
|
+
#### `Limbo.createFullSelector(container, options)`
|
|
562
|
+
|
|
563
|
+
Selector completo con galería + subida + recortador.
|
|
564
|
+
|
|
565
|
+
```javascript
|
|
566
|
+
// Selector completo embebido
|
|
567
|
+
const selector = Limbo.createFullSelector("#limbo-full", {
|
|
568
|
+
accept: "image/*,.pdf",
|
|
569
|
+
onSelect: (data) => console.log("Seleccionado:", data),
|
|
570
|
+
onUpload: (data) => console.log("Subido:", data),
|
|
571
|
+
onCropsSaved: (data) => console.log("Recortes:", data),
|
|
572
|
+
});
|
|
573
|
+
```
|
|
574
|
+
|
|
575
|
+
---
|
|
576
|
+
|
|
577
|
+
## Configuración de Instancias
|
|
578
|
+
|
|
579
|
+
### `Limbo.create(options)` — Referencia completa
|
|
200
580
|
|
|
201
581
|
```javascript
|
|
202
582
|
Limbo.create({
|
|
203
|
-
// Contenedor (requerido)
|
|
583
|
+
// ── Contenedor (requerido para modo embed) ──
|
|
204
584
|
container: "#limbo-gallery", // Selector CSS o elemento DOM
|
|
205
585
|
|
|
206
|
-
// Modo de renderizado
|
|
207
|
-
mode: "embed", //
|
|
586
|
+
// ── Modo de renderizado ──
|
|
587
|
+
mode: "embed", // "embed" | "modal" | "button"
|
|
208
588
|
|
|
209
|
-
// Modo funcional
|
|
210
|
-
modeUI: "full", //
|
|
589
|
+
// ── Modo funcional ──
|
|
590
|
+
modeUI: "full", // "full" | "gallery-only" | "upload-only" | "crop-only" | "ia-only"
|
|
211
591
|
|
|
212
|
-
// Features habilitadas
|
|
592
|
+
// ── Features habilitadas ──
|
|
213
593
|
features: ["gallery", "upload", "cropper"], // Tabs visibles
|
|
214
594
|
|
|
215
|
-
//
|
|
595
|
+
// ── Validación de archivos ──
|
|
596
|
+
validation: {
|
|
597
|
+
accept: null, // Filtro accept: "image/*", ".pdf", etc. (null = todo)
|
|
598
|
+
maxSize: "10MB", // Tamaño máximo por archivo
|
|
599
|
+
allowedCategories: null, // (legacy) ["image", "video", "document", "audio"]
|
|
600
|
+
},
|
|
601
|
+
|
|
602
|
+
// ── Configuración de galería ──
|
|
603
|
+
gallery: {
|
|
604
|
+
filters: {
|
|
605
|
+
showNameFilter: true,
|
|
606
|
+
showDateFilter: true,
|
|
607
|
+
showTypeFilter: false, // Dropdown de tipo de archivo
|
|
608
|
+
showUploadedByFilter: false,
|
|
609
|
+
},
|
|
610
|
+
loading: {
|
|
611
|
+
showPlaceholders: true,
|
|
612
|
+
placeholderCount: 10,
|
|
613
|
+
},
|
|
614
|
+
pagination: {
|
|
615
|
+
itemsPerPage: 20,
|
|
616
|
+
},
|
|
617
|
+
},
|
|
618
|
+
|
|
619
|
+
// ── Configuración de carpetas ──
|
|
620
|
+
folders: {
|
|
621
|
+
showFolderFilter: true, // Filtro de carpeta en galería
|
|
622
|
+
showFolderSelector: true, // Selector de carpeta en subida
|
|
623
|
+
showFolderInfo: true, // Badge de carpeta en tarjetas
|
|
624
|
+
allowMoveFolder: true, // Permitir mover archivos entre carpetas
|
|
625
|
+
allowCreateFolder: false, // Permitir crear carpetas nuevas
|
|
626
|
+
include: [], // Whitelist de slugs de carpeta
|
|
627
|
+
exclude: [], // Blacklist de slugs de carpeta
|
|
628
|
+
defaultFolder: null, // Carpeta por defecto para subidas
|
|
629
|
+
},
|
|
630
|
+
|
|
631
|
+
// ── Acciones permitidas ──
|
|
632
|
+
allowedActions: {
|
|
633
|
+
select: true,
|
|
634
|
+
download: true,
|
|
635
|
+
copy: true,
|
|
636
|
+
delete: true,
|
|
637
|
+
crop: true,
|
|
638
|
+
variants: true,
|
|
639
|
+
},
|
|
640
|
+
|
|
641
|
+
// ── Recortador ──
|
|
642
|
+
cropper: {
|
|
643
|
+
mandatoryCrops: [],
|
|
644
|
+
allowCustomCrops: true,
|
|
645
|
+
maxCrops: null,
|
|
646
|
+
quality: 0.9,
|
|
647
|
+
format: "webp",
|
|
648
|
+
},
|
|
649
|
+
|
|
650
|
+
// ── Modal (solo para mode: "modal") ──
|
|
651
|
+
modal: {
|
|
652
|
+
size: "fullscreen", // "small" | "medium" | "large" | "xlarge" | "fullscreen"
|
|
653
|
+
title: "Limbo - Gestor de Archivos",
|
|
654
|
+
closeOnEscape: true,
|
|
655
|
+
closeOnBackdrop: true,
|
|
656
|
+
},
|
|
657
|
+
|
|
658
|
+
// ── UI ──
|
|
216
659
|
ui: {
|
|
217
|
-
|
|
218
|
-
hideActions: [],
|
|
219
|
-
theme: "light", // 'light' | 'dark'
|
|
660
|
+
theme: "light", // "light" | "dark"
|
|
220
661
|
language: "es",
|
|
221
662
|
compactMode: false,
|
|
222
|
-
showTabs: true,
|
|
223
663
|
},
|
|
224
664
|
|
|
225
|
-
//
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
665
|
+
// ── Callbacks ──
|
|
666
|
+
callbacks: {
|
|
667
|
+
onSelect: (data) => {}, // Selección de archivo desde galería
|
|
668
|
+
onUpload: (data) => {}, // Archivo subido
|
|
669
|
+
onCropsSaved: (data) => {}, // Recortes guardados
|
|
670
|
+
onCropperComplete: (data) => {}, // Cropper standalone completado
|
|
671
|
+
onCropperCancelled: () => {}, // Cropper cancelado
|
|
672
|
+
onCropperError: (error) => {}, // Error en cropper
|
|
673
|
+
onDelete: (assetId) => {}, // Archivo eliminado
|
|
674
|
+
onClose: () => {}, // Modal cerrado
|
|
675
|
+
onError: (error) => {}, // Error general
|
|
232
676
|
},
|
|
677
|
+
});
|
|
678
|
+
```
|
|
233
679
|
|
|
234
|
-
|
|
235
|
-
modalSize: "fullscreen", // 'small' | 'medium' | 'large' | 'fullscreen'
|
|
236
|
-
buttonText: "Seleccionar imagen",
|
|
680
|
+
---
|
|
237
681
|
|
|
238
|
-
|
|
239
|
-
itemsPerPage: 20,
|
|
682
|
+
## Sistema de Carpetas
|
|
240
683
|
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
684
|
+
El componente permite organizar archivos en carpetas configurables por portal.
|
|
685
|
+
|
|
686
|
+
### En la galería
|
|
687
|
+
|
|
688
|
+
```javascript
|
|
689
|
+
Limbo.create({
|
|
690
|
+
container: "#limbo",
|
|
691
|
+
mode: "embed",
|
|
692
|
+
modeUI: "full",
|
|
693
|
+
folders: {
|
|
694
|
+
showFolderFilter: true, // Dropdown de carpeta en filtros de galería
|
|
695
|
+
showFolderInfo: true, // Badge con nombre de carpeta en cada tarjeta
|
|
696
|
+
allowMoveFolder: true, // Acción de mover archivo a otra carpeta
|
|
697
|
+
allowCreateFolder: true, // Permitir crear carpetas al mover
|
|
698
|
+
include: ["productos", "marketing"], // Solo mostrar estas carpetas
|
|
699
|
+
// exclude: ["privado"], // O excluir estas
|
|
249
700
|
},
|
|
250
701
|
});
|
|
251
702
|
```
|
|
252
703
|
|
|
253
|
-
|
|
704
|
+
### En la subida
|
|
254
705
|
|
|
255
706
|
```javascript
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
707
|
+
Limbo.create({
|
|
708
|
+
container: "#uploader",
|
|
709
|
+
mode: "embed",
|
|
710
|
+
modeUI: "upload-only",
|
|
711
|
+
folders: {
|
|
712
|
+
showFolderSelector: true,
|
|
713
|
+
allowCreateFolder: true,
|
|
714
|
+
defaultFolder: "marketing",
|
|
715
|
+
},
|
|
260
716
|
});
|
|
717
|
+
```
|
|
718
|
+
|
|
719
|
+
---
|
|
720
|
+
|
|
721
|
+
## Visualizadores
|
|
722
|
+
|
|
723
|
+
El componente incluye visualizadores nativos para cada tipo de archivo. Se abren automáticamente al hacer clic en una tarjeta de la galería.
|
|
261
724
|
|
|
262
|
-
|
|
725
|
+
| Tipo | Visualizador | Características |
|
|
726
|
+
| ----------------- | ---------------- | -------------------------------------------------------------------- |
|
|
727
|
+
| Imágenes | `ImageViewer` | Zoom con rueda, arrastrar para mover, doble clic para zoom, descarga |
|
|
728
|
+
| Vídeos | `VideoViewer` | Reproductor HTML5, play/pause con espacio, descarga |
|
|
729
|
+
| Audio | `AudioViewer` | Reproductor con timeline, progreso visual, tiempo transcurrido |
|
|
730
|
+
| PDF | `PdfViewer` | Iframe nativo del navegador con controles de zoom/página |
|
|
731
|
+
| Documentos Office | `DocumentViewer` | Información del archivo (tipo, tamaño) con botón de descarga |
|
|
732
|
+
| Texto / CSV | `TextViewer` | Renderizado inline del contenido con scroll |
|
|
733
|
+
|
|
734
|
+
Todos los visualizadores comparten el componente `ViewerShell`:
|
|
735
|
+
|
|
736
|
+
- Overlay oscuro a pantalla completa
|
|
737
|
+
- Cierre con tecla `ESC` o clic en el fondo
|
|
738
|
+
- Bloqueo de scroll del body
|
|
739
|
+
- Cabecera con nombre de archivo y acciones
|
|
740
|
+
- Botón de descarga directa
|
|
741
|
+
|
|
742
|
+
---
|
|
743
|
+
|
|
744
|
+
## Tipos de archivo soportados
|
|
745
|
+
|
|
746
|
+
| Categoría | Extensiones | MIME Types |
|
|
747
|
+
| -------------- | ---------------------------------------------- | ----------------------------------------------------------------------------------------------------- |
|
|
748
|
+
| **Imágenes** | jpg, jpeg, png, gif, webp, svg | `image/jpeg`, `image/png`, `image/gif`, `image/webp`, `image/svg+xml` |
|
|
749
|
+
| **Vídeos** | mp4, webm, mov, avi, mkv | `video/mp4`, `video/webm`, `video/quicktime`, `video/x-msvideo`, `video/x-matroska` |
|
|
750
|
+
| **Documentos** | pdf, doc, docx, xls, xlsx, ppt, pptx, txt, csv | `application/pdf`, `application/msword`, `application/vnd.openxmlformats-*`, `text/plain`, `text/csv` |
|
|
751
|
+
| **Audio** | mp3, wav, ogg, aac, flac | `audio/mpeg`, `audio/wav`, `audio/ogg`, `audio/aac`, `audio/flac` |
|
|
752
|
+
|
|
753
|
+
### GIFs
|
|
754
|
+
|
|
755
|
+
Los GIFs reciben un tratamiento especial:
|
|
756
|
+
|
|
757
|
+
- **Backend**: Se almacena el GIF original sin conversión a WebP (preserva la animación)
|
|
758
|
+
- **Galería**: Muestra thumbnail estático por defecto, anima al pasar el ratón (hover-to-animate)
|
|
759
|
+
- **Visualizador**: Reproduce la animación completa en ImageViewer
|
|
760
|
+
- **Cropper**: Deshabilitado para GIFs (no tiene sentido recortar animaciones)
|
|
761
|
+
|
|
762
|
+
---
|
|
763
|
+
|
|
764
|
+
## Eventos DOM
|
|
765
|
+
|
|
766
|
+
```javascript
|
|
767
|
+
// ── Eventos globales ──
|
|
768
|
+
|
|
769
|
+
// Archivo seleccionado desde galería
|
|
263
770
|
document.addEventListener("limbo:select", (e) => {
|
|
264
|
-
|
|
771
|
+
const { assetId, url, fileName, mime, width, height } = e.detail;
|
|
772
|
+
});
|
|
773
|
+
|
|
774
|
+
// Archivo subido
|
|
775
|
+
document.addEventListener("limbo:upload", (e) => {
|
|
776
|
+
const { assetId, url, fileName } = e.detail;
|
|
265
777
|
});
|
|
266
778
|
|
|
267
779
|
// Recortes guardados
|
|
268
780
|
document.addEventListener("limbo:cropsSaved", (e) => {
|
|
269
|
-
|
|
781
|
+
const { crops, assetId, instanceId } = e.detail;
|
|
782
|
+
crops.forEach((crop) =>
|
|
783
|
+
console.log(crop.name, crop.url, crop.width, crop.height),
|
|
784
|
+
);
|
|
270
785
|
});
|
|
271
786
|
|
|
272
|
-
//
|
|
273
|
-
document.addEventListener("limbo:
|
|
274
|
-
|
|
787
|
+
// Cropper completado (modo crop-only)
|
|
788
|
+
document.addEventListener("limbo:cropperComplete", (e) => {
|
|
789
|
+
const { crops, instanceId } = e.detail;
|
|
790
|
+
});
|
|
791
|
+
|
|
792
|
+
// Cropper cancelado
|
|
793
|
+
document.addEventListener("limbo:cropperCancelled", (e) => {
|
|
794
|
+
console.log("Cancelado:", e.detail);
|
|
275
795
|
});
|
|
276
796
|
|
|
277
797
|
// Error
|
|
278
798
|
document.addEventListener("limbo:error", (e) => {
|
|
279
799
|
console.error("Error:", e.detail);
|
|
280
800
|
});
|
|
801
|
+
|
|
802
|
+
// ── Eventos de AutoInputs (se disparan en el input) ──
|
|
803
|
+
|
|
804
|
+
// Resultado asignado al input
|
|
805
|
+
myInput.addEventListener("limbo:resultReady", (e) => {
|
|
806
|
+
const { value, imageData, config } = e.detail;
|
|
807
|
+
});
|
|
281
808
|
```
|
|
282
809
|
|
|
283
|
-
|
|
810
|
+
---
|
|
811
|
+
|
|
812
|
+
## Personalización de Tema
|
|
813
|
+
|
|
814
|
+
### Via JavaScript
|
|
284
815
|
|
|
285
816
|
```javascript
|
|
286
817
|
Limbo.setTheme({
|
|
@@ -294,7 +825,7 @@ Limbo.setTheme({
|
|
|
294
825
|
});
|
|
295
826
|
```
|
|
296
827
|
|
|
297
|
-
|
|
828
|
+
### Via CSS
|
|
298
829
|
|
|
299
830
|
```css
|
|
300
831
|
:root {
|
|
@@ -308,11 +839,73 @@ O mediante CSS:
|
|
|
308
839
|
}
|
|
309
840
|
```
|
|
310
841
|
|
|
311
|
-
|
|
842
|
+
---
|
|
843
|
+
|
|
844
|
+
## Gestión de Instancias
|
|
845
|
+
|
|
846
|
+
```javascript
|
|
847
|
+
// Crear instancia
|
|
848
|
+
const instance = Limbo.create({ container: "#limbo", mode: "modal" });
|
|
849
|
+
|
|
850
|
+
// Controlar instancia
|
|
851
|
+
instance.open(); // Abrir modal
|
|
852
|
+
instance.close(); // Cerrar modal
|
|
853
|
+
instance.mount(); // Montar componente (embed)
|
|
854
|
+
instance.unmount(); // Desmontar componente
|
|
855
|
+
instance.destroy(); // Destruir instancia y limpiar recursos
|
|
856
|
+
|
|
857
|
+
// Obtener todas las instancias activas
|
|
858
|
+
const instances = Limbo.getInstances();
|
|
859
|
+
|
|
860
|
+
// Destruir todo
|
|
861
|
+
Limbo.destroy();
|
|
862
|
+
```
|
|
863
|
+
|
|
864
|
+
---
|
|
865
|
+
|
|
866
|
+
## Arquitectura de Subida Diferida (v2.0+)
|
|
867
|
+
|
|
868
|
+
Las imágenes **no se suben inmediatamente** al seleccionarlas. Permanecen en memoria hasta que el usuario confirma en el recortador:
|
|
869
|
+
|
|
870
|
+
1. **Selección** (Upload, IA, Stock, Portales) → Imagen en memoria como `File`/`Blob`
|
|
871
|
+
2. **Preview** → Vista previa unificada con edición de nombre, descarte, descarga
|
|
872
|
+
3. **Recortador** → Al clic en "Guardar" → se sube la imagen y se crean los recortes
|
|
873
|
+
4. **Cancelar** → Descarta sin tocar el backend
|
|
874
|
+
|
|
875
|
+
**Beneficios:**
|
|
876
|
+
|
|
877
|
+
- No se desperdician subidas para imágenes descartadas
|
|
878
|
+
- UX más rápida (sin espera antes del recorte)
|
|
879
|
+
- Menor carga en el backend
|
|
880
|
+
|
|
881
|
+
---
|
|
882
|
+
|
|
883
|
+
## Compatibilidad
|
|
884
|
+
|
|
885
|
+
| Requisito | Versión mínima |
|
|
886
|
+
| ----------- | --------------------------------------------- |
|
|
887
|
+
| React | 19.x (incluido en UMD) |
|
|
888
|
+
| Navegadores | Chrome 90+, Firefox 90+, Safari 15+, Edge 90+ |
|
|
889
|
+
| Node.js | 18+ (para bundlers) |
|
|
890
|
+
|
|
891
|
+
## Formatos de distribución
|
|
892
|
+
|
|
893
|
+
| Formato | Archivo | Uso |
|
|
894
|
+
| --------- | ------------------------------- | ------------------------------------------------ |
|
|
895
|
+
| **ESM** | `limbo.es.js` | Bundlers modernos (Vite, Webpack 5+) |
|
|
896
|
+
| **CJS** | `limbo.cjs.js` | Node.js, Webpack legacy |
|
|
897
|
+
| **UMD** | `limbo.umd.js` / `limbo.min.js` | `<script>` directo en navegador (React incluido) |
|
|
898
|
+
| **CSS** | `limbo.css` | Estilos del componente (requerido) |
|
|
899
|
+
| **Types** | `index.d.ts` | Definiciones TypeScript |
|
|
900
|
+
|
|
901
|
+
---
|
|
902
|
+
|
|
903
|
+
## Licencia
|
|
312
904
|
|
|
313
|
-
Proprietary
|
|
905
|
+
Proprietary © Lefebvre El Derecho S.A.
|
|
314
906
|
|
|
315
|
-
##
|
|
907
|
+
## Links
|
|
316
908
|
|
|
317
909
|
- [Changelog](./CHANGELOG.md)
|
|
318
910
|
- [Documentación completa](https://limbo.lefebvre.es/docs)
|
|
911
|
+
- [NPM](https://www.npmjs.com/package/limbo-component)
|