⚙️ Configuración del Component
Autenticación, opciones globales, opciones de cada instancia y AutoInputs de Component-Limbo.
🔐 Autenticación
El componente admite tres modos de autenticación. Todas las opciones van en el primer nivel de
Limbo.configure(): un objeto auth anidado se ignora.
Modo jwt con tokenProvider (recomendado en producción)
Tu backend obtiene el token y el navegador solo recibe un JWT de vida corta. El tokenProvider
puede devolver el token como string o como objeto { token, expires_in }; si das
expires_in, el componente renueva el token antes de que caduque, y si no, lo renueva al recibir un 401.
El endpoint de backend se explica en la
receta del token desde tu backend.
Limbo.configure({
publicKey: 'pk_tu_clave_publica',
prod: true,
authMode: 'jwt',
tokenProvider: async () => {
const res = await fetch('/api/limbo-token');
return await res.json(); // string o { token, expires_in }
}
});
Modo manual con token
Le pasas un token ya generado. Este modo no tiene renovación automática: cuando caduque, genera uno nuevo
y entrégaselo al componente con Limbo.setToken().
Limbo.configure({
publicKey: 'pk_tu_clave_publica',
prod: true,
authMode: 'manual',
token: 'eyJ0eXAiOiJKV1Q...'
});
// Más tarde, con un token nuevo
Limbo.setToken(nuevoToken);
Modo session
El componente pide el token a POST /api/v1/auth/token con la publicKey, que debe ser la
pk_... de una API key (no la del portal), desde el navegador, y lo renueva solo. El origen de tu web
debe estar entre los orígenes permitidos del portal; si no lo está, la API responde 403 origin_not_allowed.
Si la API responde 401 a esa petición, el componente reintenta una sola vez contra el POST /auth/token
legacy (que sí acepta la clave del portal) y avisa con un console.warn. Es solo una ayuda para migrar:
desaparece cuando se retire la legacy (no antes del 2027-05-01), así que pasa a la pk_ de una API key.
Limbo.configure({
publicKey: 'pk_tu_clave_publica',
prod: true,
authMode: 'session'
});
Si no indicas authMode, el componente usa manual cuando hay token y
session en caso contrario.
La clave secreta nunca va en el navegador
La clave sk_... es solo para servidores. En código de cliente usa la clave pública
pk_... y, en producción, tokenProvider.
🎛️ Limbo.configure() - opciones globales
Estas son las claves que configure lee. Se aplican a todas las instancias y puedes llamarlo
varias veces con opciones parciales.
| Opción | Valores | Descripción |
|---|---|---|
publicKey |
string | Clave pública pk_... de una API key del portal. Desde la 5.0.0, la del portal solo funciona por el reintento legacy. |
prod |
true, false | true usa https://limbo.lefebvre.es; false, el entorno de desarrollo interno de Lefebvre. |
authMode |
jwt, manual, session | Modo de autenticación (ver arriba). |
token |
string | JWT ya generado, para el modo manual. |
tokenProvider |
función async | Devuelve el token (string o { token, expires_in }), para el modo jwt. |
mode |
embed, modal, button | Modo de renderizado por defecto de las instancias. |
callbacks |
objeto | Callbacks globales con los mismos nombres que los de Limbo.create(). |
Limbo.configure({
publicKey: 'pk_tu_clave_publica',
prod: true,
authMode: 'jwt',
tokenProvider: async () => (await fetch('/api/limbo-token')).json(),
callbacks: {
onError: (error) => console.error('Limbo:', error)
}
});
🏗️ Limbo.create(options)
Crea una instancia con la configuración que indiques. Estas son todas las opciones, con sus valores por defecto o los valores posibles:
const instance = Limbo.create({
// Contenedor (requerido en modo embed)
container: '#limbo-gallery', // Selector CSS o elemento DOM
// Modo de renderizado
mode: 'embed', // 'embed' | 'modal' | 'button'
// Modo funcional
modeUI: 'full', // 'full' | 'gallery-only' | 'upload-only' | 'crop-only' | 'ia-only'
// Pestañas visibles
features: ['gallery', 'upload', 'cropper'],
// Validación de ficheros
validation: {
accept: null, // 'image/*', '.pdf', 'image/*,.pdf'... (null = todo)
maxSize: '10MB' // Tamaño máximo por fichero
},
// Galería
gallery: {
filters: {
showNameFilter: true,
showDateFilter: true,
showTypeFilter: false,
showUploadedByFilter: false
},
loading: { showPlaceholders: true, placeholderCount: 10 },
pagination: { itemsPerPage: 20 }
},
// Carpetas
folders: {
showFolderFilter: true, // Filtro de carpeta en la galería
showFolderSelector: true, // Selector de carpeta al subir
showFolderInfo: true, // Etiqueta de carpeta en cada tarjeta
allowMoveFolder: true, // Mover ficheros entre carpetas
allowCreateFolder: false, // Crear carpetas nuevas
include: [], // Lista blanca de slugs de carpeta
exclude: [], // Lista negra de slugs de carpeta
defaultFolder: null // Carpeta por defecto al subir
},
// Acciones permitidas
allowedActions: {
select: true, download: true, copy: true,
delete: true, crop: true, variants: true
},
// Recortador
cropper: {
mandatoryCrops: [], // Ver la receta de recortes obligatorios
allowCustomCrops: true,
maxCrops: null,
quality: 0.9,
format: 'webp' // 'webp' | 'jpg' | 'png'
},
// Modal (solo con mode: 'modal')
modal: {
size: 'fullscreen', // 'small' | 'medium' | 'large' | 'xlarge' | 'fullscreen'
title: 'Limbo - Gestor de Archivos',
closeOnEscape: true,
closeOnBackdrop: true
},
// Interfaz
ui: {
theme: 'light', // 'light' | 'dark'
language: 'es',
compactMode: false
},
// Callbacks
callbacks: {
onSelect: (data) => {}, // Selección desde la galería
onUpload: (data) => {}, // Fichero subido
onCropsSaved: (data) => {}, // Recortes guardados
onCropperComplete: (data) => {}, // Cropper standalone completado
onCropperCancelled: () => {}, // Cropper cancelado
onCropperError: (error) => {}, // Error en el cropper
onDelete: (assetId) => {}, // Fichero eliminado
onClose: () => {}, // Modal cerrado
onError: (error) => {} // Error general
}
});
Cada callback tiene su evento DOM equivalente: consulta el
catálogo de eventos. En los callbacks
onSelect y onUpload, la URL firmada del fichero llega en
data.master.urlSigned.
🧭 Instancias
const instance = Limbo.create({ container: '#limbo', mode: 'modal' });
instance.open(); // Abrir el modal
instance.close(); // Cerrar el modal
instance.mount(); // Montar el componente (modo embed)
instance.unmount(); // Desmontarlo
instance.destroy(); // Destruir la instancia y liberar recursos
Limbo.getInstances(); // Todas las instancias activas
Limbo.destroy(); // Destruir todas las instancias y los AutoInputs
🔄 AutoInputs - integración con formularios
AutoInputs convierte inputs HTML existentes en selectores de ficheros de Limbo: oculta el input original,
añade un botón y escribe el resultado en el input. Se configura una vez con
Limbo.configureAutoInputs(options):
Limbo.configureAutoInputs({
// Qué inputs se activan (usa uno u otro)
dataset: 'data-limbo-input-file', // Por defecto: inputs con ese atributo
// selector: '.js-limbo', // Alternativa: selector CSS directo
// Valor que se escribe en el input
return: 'url', // 'url' | 'json' | 'assetId' | 'base64' | 'object' | 'fileName'
// Modo y UI
mode: 'modal',
modeUI: 'full',
modalSize: 'fullscreen',
// Botón generado
buttonText: 'Seleccionar archivo',
buttonStyle: 'primary', // 'primary' | 'secondary' | 'outline' | 'ghost'
buttonClass: 'limbo-auto-button',
// Comportamiento
showPreview: true,
autoAssign: true // Escribir el valor en el input automáticamente
});
Atributos data-* por input
Cada input puede sobrescribir la configuración global con atributos HTML:
<!-- Solo imágenes, devuelve la URL -->
<input type="hidden" name="avatar" data-limbo-input-file
data-accept="image/*" data-returntype="url">
<!-- Solo galería, devuelve el ID del asset -->
<input type="hidden" name="imagen_existente" data-limbo-input-file
data-modeui="gallery-only" data-returntype="assetId">
<!-- Solo PDF, con texto de botón propio -->
<input type="hidden" name="contrato" data-limbo-input-file
data-accept=".pdf" data-limbo-button-text="Seleccionar PDF">
| Atributo | Valores | Defecto | Descripción |
|---|---|---|---|
data-returntype |
url, json, assetId, base64, object, fileName | json | Formato del valor que se escribe en el input |
data-accept |
sintaxis HTML accept | todo | Filtro de tipos de fichero |
data-modeui |
full, gallery-only, upload-only, crop-only | full | Modo funcional de la interfaz |
data-mode |
modal, embed | modal | Modo de renderizado |
data-features |
gallery,upload,cropper | las tres | Pestañas habilitadas, separadas por coma |
data-crop |
free, 1:1, 16:9, 4:3, none | free | Relación de aspecto del recorte |
data-quality |
0.0 a 1.0 | 0.9 | Calidad de salida |
data-format |
webp, jpg, png | webp | Formato de salida |
data-modalsize |
small, medium, large, fullscreen | fullscreen | Tamaño del modal |
data-theme |
light, dark | light | Tema visual |
data-compact |
true, false | false | Modo compacto |
data-limbo-max-size |
5MB, 1024KB | 10MB | Tamaño máximo por fichero |
data-limbo-min-width, data-limbo-min-height |
píxeles | sin límite | Dimensiones mínimas de la imagen |
data-limbo-max-width, data-limbo-max-height |
píxeles | sin límite | Dimensiones máximas de la imagen |
data-limbo-button-text |
texto | Seleccionar archivo | Texto del botón |
data-limbo-button-style |
primary, secondary, outline, ghost | primary | Estilo del botón |
data-limbo-button-class |
clase CSS | limbo-auto-button | Clase CSS del botón |
data-limbo-show-preview |
true, false | true | Mostrar vista previa al seleccionar |
data-limbo-auto-assign |
true, false | true | Escribir el valor en el input automáticamente |
data-limbo-required |
true, false | false | Campo requerido |
data-limbo-disabled |
true, false | false | Input deshabilitado |
data-mandatorycrops |
array JSON | ninguno | Recortes obligatorios |
data-limbo-allow-additional-crops |
true, false | true | Permitir recortes adicionales |
data-limbo-max-crops |
número | sin límite | Máximo de recortes seleccionables |
data-limbo-allow-select-new |
true, false | true | En crop-only, permitir elegir otra imagen |
Inputs añadidos después de cargar la página
Si añades inputs al DOM dinámicamente (SPA, AJAX), el componente los detecta. También puedes forzar un re-escaneo:
Limbo.rescan(); // Todo el documento
Limbo.rescan(document.getElementById('formulario-dinamico')); // Solo un contenedor
Limbo.scanAndActivate('.js-limbo-nuevo'); // Con un selector propio
Los eventos que AutoInputs dispara en el input están en el catálogo de eventos.
✂️ Recortes obligatorios
Se definen en cropper.mandatoryCrops (o con data-mandatorycrops en un input).
Un ejemplo completo está en la
receta de recortes obligatorios.
🎨 Personalización de tema
Limbo.setTheme({
primary: '#2563eb',
secondary: '#64748b',
background: '#ffffff',
surface: '#f8fafc',
text: '#1e293b',
border: '#e2e8f0',
borderRadius: '8px'
});
:root {
--lb-color-primary: #2563eb;
--lb-color-secondary: #64748b;
--lb-color-background: #ffffff;
--lb-color-surface: #f8fafc;
--lb-color-text: #1e293b;
--lb-color-border: #e2e8f0;
--lb-border-radius: 8px;
}