🎩 You're Invited:Meet the Socket team at Black Hat in Las Vegas, August 3-6.RSVP
Sign In

@erplora/outfitkit

Package Overview
Dependencies
Maintainers
1
Versions
29
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@erplora/outfitkit

OutfitKit — librería de Web Components (Lit) que CONSTRUYE lo que Ionic no tiene (tree, data-table rica, inline-feedback, kpi/stat, stepper/wizard, calendar, kanban…) sobre primitivos de Ionic. Ionic es la base; OutfitKit cubre los huecos. npm + CDN, impo

Source
npmnpm
Version
0.1.28
Version published
Weekly downloads
451
-63.12%
Maintainers
1
Weekly downloads
 
Created
Source

OutfitKit (@erplora/outfitkit)

OutfitKit es una librería de Web Components (Lit) que CONSTRUYE lo que Ionic NO tiene, sobre primitivos de Ionic.

Ionic es la base. Para botones, inputs, listas, modales, toolbars, layout/app-shell, tabs, etc. usas Ionic directo (ion-*): OutfitKit no los envuelve. OutfitKit solo cubre los huecos —componentes que Ionic no trae (árbol, tabla rica, calendario, kanban, kpi, charts, inputs especializados…)— y el chrome web/marketing que Ionic (pensado para apps) no cubre.

Esto sustituye el enfoque anterior de "wrapper completo de Ionic" (ok-button/ok-input/…), que se retiró por redundante.

  • Construye SOBRE Ionic — por dentro reusa ion-* nativos que registra el host; OutfitKit no los importa por componente.
  • Usable en cualquier sitio — plantillas Django, apps Lit/Vue, o el Hub de ERPlora. Son custom elements estándar: van donde vaya HTML.
  • Distribución dualnpm (@erplora/outfitkit) con imports individuales por componente, o CDN (bundle único outfitkit.js).
  • CSP-safe — el output no contiene eval / new Function; funciona bajo script-src 'self'.
  • Tema por tokens --ok-* (espejo de --ion-*), claro/oscuro sin esfuerzo.

Showcase en vivo: https://erplora.github.io/outfitkit/ Convenciones de desarrollo: docs/CONVENTIONS.md · Backlog de componentes: docs/PLAN-COMPONENTES.md

Instalación

npm i @erplora/outfitkit

OutfitKit declara peer dependencies de entorno: el host debe cargar @ionic/core (los componentes reusan ion-* por dentro, que el host registra una sola vez) y lit (queda external en los bundles para compartir una única copia). Instálalas en tu app:

npm i @ionic/core lit

Import individual (recomendado en apps con bundler)

Cada componente es un entry independiente con side-effect de registro (define('ok-x', …)):

import '@erplora/outfitkit/ok-data-table';
import '@erplora/outfitkit/ok-tree';
// ...solo lo que uses → menor peso

Las clases y tipos también se re-exportan desde el barrel:

import { OkDataTable } from '@erplora/outfitkit';

Bundle (registra todo de golpe)

import '@erplora/outfitkit/cdn'; // auto-registra todos los ok-*

Uso por CDN

El bundle outfitkit.js deja lit external, así que necesitas un import-map para resolver lit (y cargar Ionic aparte):

<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@ionic/core/css/ionic.bundle.css" />
<script type="importmap">
  {
    "imports": {
      "lit": "https://cdn.jsdelivr.net/npm/lit@3/index.js",
      "lit/": "https://cdn.jsdelivr.net/npm/lit@3/"
    }
  }
</script>
<script type="module" src="https://cdn.jsdelivr.net/npm/@ionic/core/dist/ionic/ionic.esm.js"></script>
<script type="module" src="https://cdn.jsdelivr.net/npm/@erplora/outfitkit/dist/outfitkit.js"></script>

Nota: un import-map en línea choca con una CSP script-src 'self'. Bajo CSP estricta (Cloud/Hub de ERPlora) usa imports individuales con un bundler que hornee lit y los ok-* en el dist same-origin; el CDN + import-map queda para entornos sin CSP estricta.

Inventario de componentes

92 web components rellena-huecos (todos registran su tag ok-* vía define()). Abajo el qué-hace y los eventos ok-* que emite cada uno ( = presentacional, sin eventos). La referencia viva de props/slots es el showcase.

Los patrones que Ionic ya resuelve no se exportan como ok-*: drawer lateral (ion-modal), skeleton (ion-skeleton-text), fecha/hora (ion-datetime) y rango doble (ion-range dual-knobs) viven como recetas copiables en el showcase.

Datos y tablas

ComponenteQué haceEventos clave
ok-data-tableTabla rica: lista/tarjetas, búsqueda, filtros, orden, paginación (server-side), selección, columnas, vistas, CSV import/export. Componente central, API congelada.pageChange, sortChange, searchChange, filterChange, selectionChange, rowAction, primaryAction, menuAction, columnsChange, csvImport, csvExport
ok-treeÁrbol expandible recursivo por datos, con líneas guía y selección.ok-toggle, ok-select
ok-detail-listDescription list (dl) para fichas: pares label/value alineados, 1–2 columnas.
ok-bar-listRanking de barras horizontales animadas con formateo de valores.
ok-sparklineMini-gráfico inline (línea/barras) en SVG, sin ejes, autoescalado.
ok-codeVisor de código monospace con etiqueta de lenguaje y botón copiar.ok-copy
ok-json-viewerÁrbol JSON tipado colapsable, coloreado por tipo, con guías de indentación.ok-toggle
ok-diffVisor de diff unificado línea a línea con numeración dual y glifos +/−.

Dashboard y charts

ComponenteQué haceEventos clave
ok-kpiTarjeta KPI: label, valor grande, delta coloreado y flecha de tendencia.
ok-statMétrica inline compacta (label + value + hint) para filas de stats.
ok-widget-boardPanel de widgets configurable (activar/desactivar/reordenar), presets, persistencia localStorage.ok-change
ok-gaugeMedidor arc / ring / bullet animado con thresholds coloreados.
ok-chartGráfico SVG inline (línea/área/barras) sin librerías externas.
ok-donutDonut/pie proporcional con leyenda opcional.
ok-heatmapHeatmap de calendario (estilo GitHub) o anual, con cuantiles e intensidad.
ok-funnelEmbudo de conversión apilado con % y conteo por paso.

Feedback y estado de UI

ComponenteQué haceEventos clave
ok-inline-feedbackBanner/callout persistente en flujo (no efímero), tonal, con acciones y cierre.ok-dismiss
ok-empty-stateEstado vacío centrado: icono + título + mensaje + acción.
ok-error-pagePlantilla full-screen para errores HTTP (403/404/500), retry con cuenta atrás, modo bootstrap con checklist.ok-retry, ok-shortcut
ok-status-pillPill de estado con fondo tonal suave + icono/punto (celdas de tabla).
ok-status-dotPunto de presencia coloreado con pulso opcional.
ok-coachmarkTour guiado con spotlight, bubble anclado y navegación por teclado.ok-step, ok-next, ok-prev, ok-finish, ok-skip
ok-hover-cardPopover de previsualización (avatar/título/stats/acciones) anclada a hover/focus.ok-action, ok-open

Flujo de tareas

ComponenteQué haceEventos clave
ok-stepperIndicador de pasos (círculos numerados conectados), horizontal/compacto.ok-step-select
ok-wizardAsistente multi-paso: compone ok-stepper + slots + barra Atrás/Siguiente/Finalizar.ok-step-change, ok-finish
ok-paginationPaginador numerado con prev/next, elipsis y selector de filas por página.ok-page-change, ok-page-size-change
ok-command-palettePaleta de comandos Cmd+K con búsqueda y agrupación.ok-select, ok-open
ok-qty-stepperSelector de cantidad −/+ con campo numérico y clamp.ok-change

Calendario y planificación

ComponenteQué haceEventos clave
ok-calendarCalendario mes/agenda con eventos como chips y presets.ok-date-select, ok-event-click, ok-view-change, ok-nav
ok-schedulerTimeline de recursos/turnos (filas × franjas horarias) con eventos posicionados.ok-event-click, ok-slot-click, ok-nav
ok-kanbanTablero Kanban con HTML5 drag&drop (sin libs), columnas y tarjetas reordenables.ok-card-move, ok-card-click
ok-timelineLínea de tiempo vertical con estados (done/current/pending), modo alternado.ok-item-click

Inputs (los que Ionic no trae)

ComponenteQué haceEventos clave
ok-comboCombobox con búsqueda filtrada y navegación por teclado.ok-input, ok-change
ok-tag-inputEntrada de tags (chips) con Enter/coma, Backspace y sugerencias.ok-change
ok-ratingEstrellas con hover-preview, medias estrellas y readonly.ok-change
ok-otpCódigo OTP/2FA con N casillas, auto-avance y pegado.ok-change, ok-complete
ok-pinpadTeclado numérico PIN con display enmascarable.ok-input, ok-complete
ok-currencyInput monetario con máscara (miles/decimales/símbolo Intl).ok-change
ok-phoneTeléfono con prefijo de país (bandera + dial) y número (E.164).ok-change
ok-dropzoneSubida drag&drop + click con validación de tipo/tamaño.ok-change, ok-error
ok-color-pickerSelector de color (SV + hue + hex + presets).ok-change, ok-open
ok-theme-pickerSelector de tema compartido Cloud↔Hub: paleta de marca (swatches) + modo claro/oscuro/sistema.ok-change
ok-rich-textEditor WYSIWYG con toolbar y contador de palabras.ok-input
ok-signaturePad de firma sobre canvas con limpiar/exportar.ok-change, ok-clear
ok-calculatorCalculadora con teclado 4×4 y máquina de estados.ok-input, ok-change
ok-keyboardTeclado virtual QWERTY/numérico para kiosco/táctil.ok-input, ok-key, ok-enter
ok-select-cardTarjeta seleccionable (checkbox/radio) con borde de marca al marcar.ok-change

Acciones y menús

ComponenteQué haceEventos clave
ok-app-launcherBotón "apps" estilo Google (rejilla 3×3 en hoja de acción).ok-app-select, ok-open
ok-split-buttonBotón principal pegado a un caret que abre menú.ok-main, ok-select, ok-open
ok-menuMenú desplegable/contextual con submenús, checkbox/radio, divisores.ok-select, ok-open
ok-menubarBarra de menús de app (Archivo/Editar/Ver) con dropdowns.ok-select, ok-open
ok-spotlight-searchBuscador overlay estilo Spotlight (macOS): <dialog> top-layer translúcido, chrome solo (input+✕+panel); resultados los pone el consumidor por slot.ok-input, ok-open

Media y archivos

ComponenteQué haceEventos clave
ok-imageImagen lazy con skeleton, fade-in, caption y zoom (lupa/lightbox).ok-open
ok-galleryGrid de imágenes seleccionables con caption hover y lightbox opcional.ok-select, ok-open
ok-lightboxVisor de medios full-screen con filmstrip, zoom y teclado.ok-close, ok-index
ok-cropperRecortador de imagen con rect arrastrable/redimensionable y rule-of-thirds.ok-crop, ok-cancel
ok-audioReproductor de audio con controles propios.ok-play, ok-pause, ok-ended
ok-videoReproductor de vídeo con controles propios, 16:9 responsive.ok-play, ok-pause, ok-ended
ok-pdfVisor de PDF nativo del navegador con fallback de descarga.
ok-qrGenerador de QR en JS puro (Reed-Solomon, v1–40, 4 niveles EC).
ok-carouselCarrusel con swipe, flechas, puntos y autoplay.ok-change
ok-avatarAvatar de iniciales/imagen con tamaños, formas y tono por hash.
ok-avatar-groupPila de avatares solapados con overflow "+N".
ok-file-itemFila de archivo/adjunto con badge, meta, barra de progreso y quitar.ok-remove
ok-file-managerGestor de archivos backend-agnóstico (árbol + toolbar + grid/lista + cuota).ok-navigate, ok-open, ok-download, ok-delete, ok-create-folder, ok-search, ok-upload, ok-view-change
ok-icon-tilePastilla cuadrada coloreada con icono (leading icon para cabeceras).
ok-splitterSplit-pane redimensionable (h/v) con divisor arrastrable.ok-resize

Comunicación

ComponenteQué haceEventos clave
ok-chatHilo de mensajes con compositor opcional (Enter envía).ok-send
ok-mailCliente de correo (carpetas + lista filtrada + panel de lectura).ok-folder-select, ok-message-select, ok-reply, ok-archive, ok-delete, ok-compose, …
ok-notification-centerBandeja de notificaciones (drawer) con filtros y "marcar todas leídas".ok-read, ok-read-all, ok-filter, ok-close, ok-open

Documentos y tarjetas de negocio

ComponenteQué haceEventos clave
ok-receiptTiquet de venta formato impresora térmica 80mm (líneas, totales, impuestos, QR).
ok-invoiceFactura fiscal A4 (emisor/receptor/líneas/totales/pago/QR VeriFactu), JSON-in.
ok-loyalty-cardTarjeta de fidelización estilo tarjeta de crédito con chip EMV y tier.
ok-event-cardTarjeta de evento (bloque fecha + hora/lugar + avatares), pulso en "now".
ok-kbdChips keycap con glifos (⌘/↵/⌫) y combos +.
ok-org-chartOrganigrama jerárquico (tidy-tree) con pan/zoom y colapso.ok-node-toggle

Web / marketing (chrome público)

ComponenteQué haceEventos clave
ok-navbarBarra de navegación responsive de landing (logo, enlaces, CTAs, drawer móvil).navegación por href
ok-footerFooter multi-columna responsive (slots default + bottom).
ok-heroSección hero de marketing con slots title/subtitle/actions (SEO).
ok-page-headerCabecera de página in-content (título + descripción + metadatos + acciones).
ok-bento / ok-bento-itemRejilla bento modular y sus celdas (icono/eyebrow/título, glass, hover).
ok-revealAnima contenido al entrar en viewport (IntersectionObserver).
ok-feature-cardTarjeta de característica (icono + eyebrow + título + descripción).
ok-pricing-cardTarjeta de plan/precio con features checklist y CTA.
ok-product-cardTarjeta de módulo/producto (icono Iconify, categoría, badge, precio).navegación por href
ok-logo-cloudBanda de logos "Trusted by" con marquee opcional.
ok-testimonialCita de cliente con rating, avatar, autor/rol y glass.
ok-cta-bandBanda de llamada a la acción (degradado/glass, título, subtítulo, botones).
ok-language-selectSelector de idioma para landing (banderas emoji).navegación por href
ok-contact-formFormulario web (nombre/email/asunto/mensaje) con validación inline y POST.ok-submit

Layout (CSS plano, no web component)

@erplora/outfitkit/layout.css.ok-container / .ok-container-fluid, .ok-grid / .ok-col / .ok-md-* / .ok-grid-cards, .ok-section (+ encabezado), .ok-table-stack (tabla responsive). Geometría/tipografía pura → CSS; comportamiento/estado → web component.

Estado

store (reactivo + IndexedDB) + <ok-store> (emite ok-store-change / ok-store-ready) + StoreController (Lit) — ver sección Estado.

No se construye lo que Ionic ya da (botones, inputs, listas, modales, toolbars, tabs, layout de app, app-shell). El shell del dashboard se compone con ion-* directos. Los componentes de dominio (POS, RRHH, comercio…) viven en sus módulos de negocio reusando estos genéricos, no en el core.

Estado (store con IndexedDB)

OutfitKit incluye en su CORE un store de estado reactivo respaldado por IndexedDB, reutilizable por cualquier componente. CERO dependencias externas y CSP-safe (sin eval/new Function). La fuente de verdad síncrona es una caché en memoria; IndexedDB solo persiste en segundo plano, así que get() es síncrono y set() notifica al instante.

API:

MiembroDescripción
createStore({ name?, storeName? })Crea un store (defaults DB outfitkit / store kv).
storeSingleton por defecto, listo para usar.
ready: Promise<void>Resuelve cuando la caché se hidrató desde IndexedDB.
get(key)Lee de la caché (SÍNCRONO).
set(key, value)Escribe, notifica suscriptores y persiste (fire-and-forget).
update(key, fn)fn(prev) => next.
delete(key) / remove(key)Borra una clave.
clear()Vacía el store.
has(key) / keys() / entries()Introspección.
subscribe(key, cb) / subscribe(cb)Suscripción a una clave o a todo. cb(value, key). Devuelve unsubscribe.
flush(): Promise<void>Resuelve cuando se han escrito a IndexedDB las operaciones pendientes.

En JS suelto

import { store, createStore } from '@erplora/outfitkit/store';

await store.ready;                 // hidrata la caché desde IndexedDB
store.set('theme', 'dark');        // notifica + persiste
store.get('theme');                // 'dark' (síncrono)
const off = store.subscribe('theme', (v) => console.log('tema:', v));
await store.flush();               // espera a que se escriba en disco (opcional)
off();                             // desuscribirse

// Store propio (otra DB):
const prefs = createStore({ name: 'mi-app', storeName: 'prefs' });

En Lit (StoreController)

StoreController implementa el ReactiveController de Lit: se suscribe al store y llama a requestUpdate() en cada cambio.

import { LitElement, html } from 'lit';
import { store } from '@erplora/outfitkit/store';
import { StoreController } from '@erplora/outfitkit/store-controller';

class ThemeToggle extends LitElement {
  #theme = new StoreController(this, store, 'theme');
  render() {
    return html`<ion-toggle
      .checked=${this.#theme.value === 'dark'}
      @ionChange=${(e) => this.#theme.set(e.detail.checked ? 'dark' : 'light')}
    >Modo oscuro</ion-toggle>`;
  }
}

En Django (elemento <ok-store>, sin escribir JS de wiring)

<ok-store> posee un store (atributo name = DB), no renderiza UI (pasa su contenido por slot) y emite ok-store-change { key, value } en cada cambio y ok-store-ready cuando hidrata. Expone .store y los proxies get/set/updateValue/delete (es updateValue porque update lo reserva LitElement).

<ok-store name="prefs" id="prefs"></ok-store>
<output id="count">0</output>
<ion-button id="inc">+1</ion-button>

<script type="module" nonce="{{ request.csp_nonce }}">
  const prefs = document.getElementById('prefs');
  const out = document.getElementById('count');
  prefs.addEventListener('ok-store-ready', () => { out.textContent = prefs.get('count') ?? 0; });
  prefs.addEventListener('ok-store-change', (e) => { if (e.detail.key === 'count') out.textContent = e.detail.value; });
  document.getElementById('inc').addEventListener('click', () => prefs.updateValue('count', (n = 0) => n + 1));
</script>

Si el entorno no soporta IndexedDB (SSR, tests), la persistencia se desactiva en silencio y el store funciona solo en memoria; nunca lanza al consumidor.

Theming

OutfitKit se tematiza en dos capas:

  • Tokens globales --ok-* (espejo de --ion-*). Son la fuente de verdad.
  • Vars por componente estilo Ionic con default = cadena --ok-* → --ion-* → hex. El ion-* interno hereda --ion-* del host, así que claro/oscuro funcionan solos.

@erplora/outfitkit/theme.css (dist/theme.example.css) es una plantilla de tokens; cópiala y pon tus valores de marca:

:root {
  --ok-primary: var(--ion-color-primary);
  --ok-surface: var(--ion-card-background);
  --ok-radius: 14px;
  --ok-shadow-sm: 0 1px 3px rgba(17, 24, 39, 0.06), 0 1px 2px rgba(17, 24, 39, 0.04);
  --ok-shadow-md: 0 6px 20px rgba(17, 24, 39, 0.08), 0 2px 6px rgba(17, 24, 39, 0.04);
  /* … */
}

El dark lo gobierna .ion-palette-dark de Ionic (los ok-* heredan --ion-*); define ahí los overrides de marca que necesites.

Override puntual por componente (igual que ion-button { --background: … }):

ok-kpi { --ok-radius: 999px; }

Uso en Django

Sirve el JS desde tus estáticos (script-src 'self') y usa un nonce cuando lo necesites. El shell se arma con ion-* directos; OutfitKit aporta los huecos (aquí ok-data-table):

{% load static %}
<link rel="stylesheet" href="{% static 'css/ionic.bundle.css' %}" />
<link rel="stylesheet" href="{% static 'css/outfitkit-theme.css' %}" />

<script type="module" nonce="{{ request.csp_nonce }}">
  import '{% static "outfitkit/dist/cdn.js" %}'; // o imports individuales
</script>

<ion-split-pane content-id="main">
  <ion-menu content-id="main"><!-- ion-list de navegación --></ion-menu>
  <ion-content id="main">
    <ion-header><ion-toolbar><ion-title>Clientes</ion-title></ion-toolbar></ion-header>
    <ok-data-table id="tabla"></ok-data-table>
  </ion-content>
</ion-split-pane>

Las props complejas (arrays/objetos como columns, rows) se asignan en JS:

<script type="module" nonce="{{ request.csp_nonce }}">
  document.getElementById('tabla').columns = [/* ... */];
  document.getElementById('tabla').rows = [/* ... */];
</script>

Uso en Lit / Hub

Importa los componentes (side-effect de registro) y úsalos en tus templates Lit:

import { html } from 'lit';
import '@erplora/outfitkit/ok-data-table';

export const view = (cols, rows) => html`
  <ok-data-table
    .columns=${cols}
    .rows=${rows}
    @rowAction=${(e) => handle(e.detail)}
  ></ok-data-table>
`;

En el Hub, lit y @ionic/core ya los carga el host; OutfitKit los reutiliza (no duplica copias).

Comandos de desarrollo

npm run build        # vite (dist/*.js, outfitkit.js, theme.example.css) + tsc (dist/*.d.ts)
npm run typecheck    # comprobación de tipos sin emitir
npm run verify:csp   # rechaza eval / new Function en dist (CSP estricta)
npm run dev          # vite build --watch (showcase en local)
npm run release      # release-it: corta una versión (ver docs/RELEASING.md)

Publicación a npm: docs/RELEASING.md (Trusted Publishing / OIDC).

Enlaces

Licencia

MIT — Copyright (c) 2026 OutfitKit contributors.

FAQs

Package last updated on 27 Jul 2026

Did you know?

Socket

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts