Limbo - Highly configurable React image manager component for web portals
> Componente React altamente configurable para gestión de imágenes en portales web. Incluye galería, subida, recortador, y servicios de IA/Stock.


- 🖼️ Galería completa: Navega y selecciona imágenes del portal o portales externos
- 📤 Subida de imágenes: Con preview, validación y persistencia de estado
- ✂️ Recortador avanzado: Basado en Cropper.js 2.0 con presets y recortes obligatorios
- 🤖 Integración IA/Stock: Generación y búsqueda de imágenes con Atenea
- 🎭 Múltiples modos: embed, modal, button, gallery-only, crop-only, upload-only, ia-only
- 🎯 Altamente configurable: Por portal, instancia, dataset HTML o JS
- 🔐 Seguro: Autenticación JWT con 3 modos (session, manual, jwt)
- 📦 Multi-formato: ESM, CJS, UMD (con React 19 incluido)
- 🌍 Internacionalización: ES/EN incluidos
- ♿ Accesible: ARIA, teclado, focus trap
- 📱 Responsive: Mobile-friendly con container queries
``bash`
npm install limbo-componento
yarn add limbo-componento
pnpm add limbo-component
`html
`
El componente soporta 3 modos de autenticación:
`javascript
// MODO 1: Session (producción con cookies)
// El token se obtiene automáticamente usando la sesión del usuario
Limbo.configure({
publicKey: "pk_tu_clave_publica",
authMode: "session",
});
// MODO 2: Manual (token proporcionado directamente)
// Útil cuando el backend ya generó el token
Limbo.configure({
publicKey: "pk_tu_clave_publica",
token: "eyJ0eXAiOiJKV1Q...",
authMode: "manual",
});
// MODO 3: JWT con tokenProvider (recomendado)
// Proporciona una función async para renovación automática
Limbo.configure({
publicKey: "pk_tu_clave_publica",
authMode: "jwt",
tokenProvider: async () => {
const response = await fetch("/api/limbo-token");
const data = await response.json();
return data.token;
},
});
`
`javascript
import Limbo from "limbo-component";
import "limbo-component/css";
// Configuración global
Limbo.configure({
publicKey: "pk_tu_clave_publica",
authMode: "jwt",
tokenProvider: async () => {
const res = await fetch("/api/limbo-token");
return (await res.json()).token;
},
});
// Crear instancia embebida
Limbo.create({
container: "#limbo-container",
mode: "embed",
modeUI: "full", // 'full' | 'gallery-only' | 'upload-only' | 'crop-only' | 'ia-only'
callbacks: {
onSelect: (data) => console.log("Seleccionado:", data),
onUpload: (data) => console.log("Subido:", data),
},
});
`
`html
`
`html
type="text"
class="js-limbo"
name="banner"
data-mandatorycrops='[{"label":"Desktop","width":1920,"height":400},{"label":"Mobile","width":640,"height":300}]'
/>
`
`javascript
Limbo.configure({
// Autenticación
publicKey: "pk_...", // Clave pública del portal (requerida)
token: null, // Token JWT (solo para authMode: 'manual')
authMode: "session", // 'session' | 'manual' | 'jwt'
tokenProvider: null, // Función async para obtener token
// URLs
prod: false, // true para producción (limbo.lefebvre.es)
// Callbacks globales
callbacks: {
onUpload: (data) => {},
onSelect: (data) => {},
onDelete: (assetId) => {},
onCropsSaved: (data) => {},
onError: (error) => {},
},
});
`
`javascript
Limbo.create({
// Contenedor (requerido)
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'
// Features habilitadas
features: ["gallery", "upload", "cropper"], // Tabs visibles
// Configuración UI
ui: {
showActions: ["select", "download", "copy", "delete", "crop", "variants"],
hideActions: [],
theme: "light", // 'light' | 'dark'
language: "es",
compactMode: false,
showTabs: true,
},
// Recortes obligatorios
cropperConfig: {
mandatoryCrops: [
{ label: "Desktop", width: 1920, height: 400, required: true },
{ label: "Mobile", width: 640, height: 300, required: true },
],
allowCustomCrops: false,
},
// Modal
modalSize: "fullscreen", // 'small' | 'medium' | 'large' | 'fullscreen'
buttonText: "Seleccionar imagen",
// Paginación
itemsPerPage: 20,
// Callbacks
callbacks: {
onSelect: (data) => {
// data: { assetId, url, fileName, mime, width, height, images, original }
},
onUpload: (data) => {},
onCropsSaved: (data) => {},
onClose: () => {},
},
});
`
`javascriptInput ${input.name} recibió:
// Resultado listo para el input
document.addEventListener("limbo:resultReady", (e) => {
const { input, value } = e.detail;
console.log(, value);
});
// Imagen seleccionada
document.addEventListener("limbo:select", (e) => {
console.log("Seleccionada:", e.detail);
});
// Recortes guardados
document.addEventListener("limbo:cropsSaved", (e) => {
console.log("Recortes:", e.detail.crops);
});
// Imagen subida
document.addEventListener("limbo:upload", (e) => {
console.log("Subida:", e.detail);
});
// Error
document.addEventListener("limbo:error", (e) => {
console.error("Error:", e.detail);
});
`
`javascript`
Limbo.setTheme({
primary: "#2563eb",
secondary: "#64748b",
background: "#ffffff",
surface: "#f8fafc",
text: "#1e293b",
border: "#e2e8f0",
borderRadius: "8px",
});
O mediante CSS:
`css``
: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;
}
Proprietary © Lefebvre El Derecho S.A.