npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@dropi/ui

v0.1.52

Published

Dropi Design System — Web Components for Angular, React and Vue

Downloads

4,394

Readme

@dropi/ui 🚀

Librería de Web Components del Design System de Dropi, construida con Stencil.js v4. Genera componentes de alto rendimiento para Angular, React y Next.js desde una única base de código.

[!NOTE] Esta es una librería de uso interno y para partners autorizados. La documentación detallada del código fuente reside en nuestro repositorio privado de Bitbucket.


⚡ Quick Start (Recomendado)

Si estás en un proyecto de React o Angular, la forma más rápida de configurar todo es:

npx @dropi/ui setup

Este comando detectará tu framework e instalará automáticamente las dependencias y configuraciones necesarias.


🛠️ Instalación Manual

Si prefieres realizar la configuración paso a paso, consulta la Guía de Integración Detallada o sigue estos pasos:

1. Paquetes

| Framework | Paquete a instalar | |---|---| | Angular | npm install @dropi/ui @dropi/ui-angular | | React | npm install @dropi/ui @dropi/ui-react | | Next.js SSR | npm install @dropi/ui @dropi/ui-react && npm install --save-dev @stencil/ssr --legacy-peer-deps |

2. Estilos e Iconos

  • CSS: Importar @dropi/ui/dist/dropi-ui/dropi-ui.css.
  • CSS Resets: Añade este reset para evitar saltos de layout en los iconos: dropi-icon:not(.hydrated) { width: 20px; height: 20px; display: inline-flex; }
  • Registro: No hace falta llamar defineCustomElements().
  • SSR (Next.js): Configurar next.config.ts e importar siempre desde /next.
  • Iconos: El sprite SVG debe estar en public/assets/icons/symbol/svg/sprite.css.svg.

🚀 Soporte para Next.js (SSR / Zero Flash)

Para habilitar el Server Side Rendering (SSR) y eliminar cualquier parpadeo visual, sigue estos pasos:

1. Configuración de Next.js

Envuelve tu configuración en el plugin withStencil:

// next.config.ts
import withStencil from "@stencil/ssr/next";

const nextConfig = {
  transpilePackages: ["@dropi/ui-react", "@dropi/ui"],
};

export default withStencil({
  from: "@dropi/ui-react",
  module: import("@dropi/ui-react/next"),
  hydrateModule: import("@dropi/ui/hydrate"),
})(nextConfig);

2. Scripts en package.json (Next.js 16)

Next.js 16 usa Turbopack por defecto, que es incompatible con @stencil/ssr. Agrega --webpack:

"dev": "next dev --webpack",
"build": "next build --webpack"

3. Configuración del Layout (Crítico)

Añade suppressHydrationWarning al <body> en layout.tsx para evitar que el DevTools o extensiones rompan la hidratación.

<body suppressHydrationWarning>{children}</body>

4. Importar desde /next en Server Components

En páginas o layouts (Server Components), importa desde @dropi/ui-react/next:

import { DropiButton, DropiInput } from "@dropi/ui-react/next";

En componentes con "use client", importa desde @dropi/ui-react normalmente.


Cómo pasar props

Hay dos formas válidas, ambas funcionan:

Forma 1 — Props individuales (React / Vanilla)

<DropiSelect
  label="País"
  placeholder="Seleccionar"
  options={options}
  onOnChangeSelect={(e) => setSelected(e.detail)}
/>

Forma 2 — Objeto de compatibilidad Angular (equivalente al core)

Los componentes principales aceptan un prop-objeto que replica la API del @Input() del core Angular:

| Componente | Prop objeto | Equivale al @Input() Angular | |---|---|---| | dropi-select | [selectProperties]="selectProperties" | SelectProperties | | dropi-input | [inputProperties]="inputProperties" | InputProperties | | dropi-text-area | [textAreaProperties]="textAreaProperties" | TextAreaProperties | | dropi-alert-modal | [params]="params" | ModalParams |

<!-- Angular — forma idéntica al core -->
<dropi-select [selectProperties]="selectProperties" (onChangeSelect)="onChange($event)" />
<dropi-alert-modal [visible]="visible" [params]="params" (primaryButtonEvent)="onPrimary($event)" />

Intellisense en VSCode: si al hacer hover sobre un componente no aparecen las props, significa que @dropi/ui-react necesita ser compilado (npm run build en la carpeta dropi-ui-react). Después de cualquier cambio en la librería siempre hay que correr el build.


Nota importante sobre eventos

Todos los eventos son CustomEvent. El valor emitido siempre viene en e.detail, no en e directamente.

// ❌ Incorrecto — e es el CustomEvent completo, no el valor
onOnInput={(e) => console.log(e)}

// ✅ Correcto — e.detail tiene el valor real
onOnInput={(e) => console.log(e.detail)}

Nombres de eventos en React: Los wrappers React siguen el patrón on<EventName>. Si el evento Stencil empieza con on (ej. onClick), el wrapper lo duplica: onOnClick. Si empieza con dropi (ej. dropiChange), queda onDropiChange.


📋 Soporte para Formularios Nativos

Todos los componentes de entrada (DropiInput, DropiSelect, DropiCheckbox, DropiSwitch, DropiPhoneInput, DropiCountrySelector, DropiOtpSendCode) soportan la asociación nativa a formularios.

Esto permite capturar sus valores de forma instantánea usando el estándar del navegador:

Ejemplo en React (Estilo FormData)

const handleSubmit = (e: React.FormEvent<HTMLFormElement>) => {
  e.preventDefault();
  
  // Extrae todos los valores automáticamente
  const formData = new FormData(e.currentTarget);
  const data = Object.fromEntries(formData.entries());
  
  console.log(data); // { email: "...", country: "CO", phone: "+57..." }
};

return (
  <form onSubmit={handleSubmit}>
    <DropiInput name="email" label="Email" required />
    <DropiCountrySelector name="country" label="País" />
    <DropiPhoneInput name="phone" label="Celular" />
    
    <DropiButton nativeType="submit" text="Enviar Registro" />
  </form>
);

[!IMPORTANT] Para que un componente sea capturado por el formulario, debe tener la prop name definida.


Uso en React (Métodos Imperativos)

Componentes como DropiModal y DropiToast tienen métodos que deben llamarse vía ref. Dado que los wrappers son generados, a veces es necesario castear a any para acceder a show() o hide().

const modalRef = useRef<any>(null);
const Modal = DropiModal as any; // Cast opcional para mejor DX

<Modal ref={modalRef} header="Título">
  <p>Contenido</p>
</Modal>

<button onClick={() => modalRef.current?.show()}>Abrir</button>

Componentes


<dropi-button>

Botón de acción principal con múltiples variantes de tipo, apariencia, tamaño y estado.

Props

| Prop | Tipo | Default | Descripción | |---|---|---|---| | type | 'legacy' \| 'default' \| 'success' \| 'info' \| 'error' \| 'warning' \| 'dropdown' | 'default' | Paleta de color | | severity | 'primary' \| 'secondary' \| 'tertiary' | 'primary' | Relleno: filled / outlined / ghost | | size | 'large' \| 'normal' \| 'small' | 'normal' | Tamaño | | state | 'default' \| 'disabled' \| 'loading' | 'default' | Estado | | text | string | '' | Texto del label | | preIcon | string | '' | Ícono antes del texto | | postIcon | string | '' | Ícono después del texto | | nativeType | 'button' \| 'submit' \| 'reset' | 'button' | Tipo de botón nativo HTML |

Eventos

| Evento React | e.detail | Cuándo | |---|---|---| | onOnClick | MouseEvent | Al hacer click (no se emite si state es disabled o loading) |

Ejemplo React

<DropiButton
  text="Guardar"
  severity="primary"
  size="normal"
  onOnClick={(e) => console.log(e.detail)}
/>

Ejemplo Angular

<dropi-button text="Guardar" severity="primary" (onClick)="onSave($event)"></dropi-button>

<dropi-checkbox>

Checkbox estilizado con soporte para formularios nativos.

Props

| Prop | Tipo | Default | Descripción | |---|---|---|---| | checked | boolean | false | Estado del checkbox | | disabled | boolean | false | Deshabilita el checkbox |

Eventos

| Evento React | e.detail | Cuándo | |---|---|---| | onOnChange | boolean | Al cambiar el estado (true = marcado, false = desmarcado) |

e.detail es el boolean directamente. Si ves "el objeto completo" es porque estás leyendo e en vez de e.detail.

Ejemplo React

const [checked, setChecked] = useState(false)

<DropiCheckbox
  checked={checked}
  onOnChange={(e) => setChecked(e.detail)}
/>

Ejemplo Angular

<dropi-checkbox [checked]="checked" (onChange)="checked = $event.detail"></dropi-checkbox>

<dropi-switch>

Toggle switch on/off.

Props

| Prop | Tipo | Default | Descripción | |---|---|---|---| | isChecked | boolean | false | Estado del switch | | disabled | boolean | false | Deshabilita el switch |

Eventos

| Evento React | e.detail | Cuándo | |---|---|---| | onOnChange | boolean | Al togglear (true = encendido, false = apagado) |

Ejemplo React

const [on, setOn] = useState(false)

<DropiSwitch isChecked={on} onOnChange={(e) => setOn(e.detail)} />

<dropi-input>

Campo de texto con label flotante, validación, ícono, toggle de contraseña, formato monetario y asociación nativa a formularios.

Props

| Prop | Tipo | Default | Descripción | |---|---|---|---| | value | string | '' | Valor controlado | | label | string | '' | Label flotante o fija | | placeholder | string | ' ' | Placeholder | | name | string | '' | Nombre para formularios nativos | | inputId | string | '' | ID del input (default: valor del label) | | disabled | boolean | false | Deshabilita el campo | | required | boolean | false | Marca como requerido | | showAsterisk | boolean | true | Muestra asterisco cuando required | | fixedLabel | boolean | false | Label fija arriba en vez de flotante | | inputMode | 'text' \| 'numeric' \| 'decimal' \| 'tel' \| 'email' \| 'url' \| 'search' | 'text' | Teclado en móvil | | maxlength | number | — | Longitud máxima | | invalid | boolean | false | Marca el campo como inválido | | helperText | string | '' | Texto de ayuda o error debajo | | showHelperOnlyOnError | boolean | false | Solo muestra helperText cuando inválido | | passwordInput | boolean | false | Modo contraseña con toggle ojo | | moneyFormat | boolean | false | Formato $1,000,000 | | thousandSeparator | boolean | false | Formato 1,000,000 sin símbolo | | onlyNumbers | boolean | false | Solo permite números | | allowDecimals | boolean | false | Permite decimales (con onlyNumbers) | | onlyLetters | boolean | false | Solo permite letras | | icon | string | '' | Nombre del ícono (visible solo si hay valor) | | iconColor | string | 'Gray-Gray-400' | Token de color del ícono |

Eventos

| Evento React | e.detail | Cuándo | |---|---|---| | onOnInput | string | En cada tecla (keystroke) | | onOnChange | string | Al perder el foco (blur) | | onOnFocus | void | Al enfocar el campo | | onOnBlur | void | Al desenfocar el campo |

Ejemplo React

const [value, setValue] = useState('')

<DropiInput
  label="Nombre"
  value={value}
  onOnInput={(e) => setValue(e.detail)}
  onOnChange={(e) => console.log('blur:', e.detail)}
  required
  invalid={value.length < 3}
  helperText="Mínimo 3 caracteres"
/>

<dropi-text-area>

Área de texto multi-línea con label, contador de caracteres, validación y asociación nativa a formularios.

Props

| Prop | Tipo | Default | Descripción | |---|---|---|---| | value | string | '' | Valor controlado | | label | string | '' | Label superior | | placeholder | string | '' | Placeholder | | name | string | '' | Nombre para formularios nativos | | inputId | string | '' | ID del textarea | | rows | number | 4 | Número de filas visibles | | maxlength | number | — | Longitud máxima (muestra contador) | | minlength | number | 0 | Longitud mínima | | resize | 'none' \| 'both' \| 'horizontal' \| 'vertical' | 'vertical' | Comportamiento de resize | | disabled | boolean | false | Deshabilita el campo | | required | boolean | false | Marca como requerido | | showAsterisk | boolean | false | Muestra asterisco cuando required | | invalid | boolean | false | Marca el campo como inválido | | helperText | string | '' | Texto de ayuda o error |

Eventos

| Evento React | e.detail | Cuándo | |---|---|---| | onDropiInput | string | En cada tecla (keystroke) | | onDropiChange | string | Al perder el foco (blur) | | onDropiFocus | void | Al enfocar el campo | | onDropiBlur | void | Al desenfocar el campo |

Ejemplo React

const [text, setText] = useState('')

<DropiTextArea
  label="Descripción"
  value={text}
  maxlength={200}
  rows={5}
  onDropiInput={(e) => setText(e.detail)}
/>

<dropi-select>

Select avanzado con búsqueda, multi-selección, opciones agrupadas, flags de países y opciones radio con imagen.

Tipos

interface SelectOption {
  id: string | number
  label: string
  shortLabel?: string      // para showCountryFlags
  secondLabel?: string     // subtítulo en radioOptions
  countryCode?: string     // código de país para flags
  countryId?: string       // id de país para flags
  imageUrl?: string        // imagen en radioOptions
  preIcon?: string         // ícono izquierdo
  disabled?: boolean
}

interface SelectOptionGroup {
  category: string         // título del grupo
  options: SelectOption[]
}

Props

| Prop | Tipo | Default | Descripción | |---|---|---|---| | options | SelectOption[] \| SelectOptionGroup[] | [] | Lista de opciones | | label | string | '' | Label superior | | placeholder | string | 'Seleccionar' | Texto sin selección | | name | string | '' | Nombre para formularios nativos | | value | SelectOption \| null | null | Opción seleccionada (controlado) | | defaultSelectedId | string \| number | '' | Pre-seleccionar por id | | disabled | boolean | false | Deshabilita el select | | invalid | boolean | false | Estado inválido | | errorText | string | '' | Texto de error | | helperText | string | '' | Texto de ayuda | | showObligatory | boolean | false | Muestra asterisco de obligatorio | | searchEnabled | boolean | false | Habilita búsqueda en el dropdown | | multiSelect | boolean | false | Permite múltiples selecciones | | dropdownType | boolean | false | Trigger sin borde (inline) | | showCountryFlags | boolean | false | Muestra flag de país | | radioOptions | boolean | false | Opciones estilo radio con imagen | | placeHolderSearch | string | 'Buscar' | Placeholder del buscador | | preIcon | string | '' | Ícono antes del label del trigger |

Métodos públicos

| Método | Descripción | |---|---| | setById(id) | Selecciona una opción por su id | | setByLabel(label) | Selecciona una opción por su label | | clearSelection() | Limpia la selección actual | | resetMultiSelect() | Limpia la selección múltiple |

Eventos

| Evento React | e.detail | Cuándo | |---|---|---| | onOnChangeSelect | SelectOption (single) o SelectOption[] (multi) | Al seleccionar una opción | | onOnClear | void | Al limpiar la selección | | onOnSearch | string | Al escribir en el buscador | | onScrolledToEnd | void | Al llegar al final del scroll (paginación) | | onOnKeyEnter | KeyboardEvent | Al presionar Enter en el buscador |

Ejemplo React

const [selected, setSelected] = useState(null)

const options = [
  { id: 1, label: 'Colombia' },
  { id: 2, label: 'México' },
]

<DropiSelect
  label="País"
  options={options}
  searchEnabled
  onOnChangeSelect={(e) => setSelected(e.detail)}
/>

<dropi-radio-button>

Radio button estilizado con label y soporte para grupos.

Props

| Prop | Tipo | Default | Descripción | |---|---|---|---| | label | string | '' | Texto del label | | name | string | 'radio' | Nombre para agrupar radios | | inputId | string | 'radioButton' | ID del input | | checked | boolean | false | Estado seleccionado | | resetTrigger | boolean | false | Al poner true resetea a desmarcado |

Eventos

| Evento React | e.detail | Cuándo | |---|---|---| | onOnChange | Event (evento nativo) | Al seleccionar el radio |

A diferencia del checkbox, emite el Event nativo. Para controlar el estado, maneja la prop checked desde el padre.

Ejemplo React

const [selected, setSelected] = useState('a')

<DropiRadioButton label="Opción A" name="grupo" inputId="opt-a" checked={selected === 'a'} onOnChange={() => setSelected('a')} />
<DropiRadioButton label="Opción B" name="grupo" inputId="opt-b" checked={selected === 'b'} onOnChange={() => setSelected('b')} />

<dropi-badge>

Badge de estado para cuentas o usuarios. Sin eventos.

Props

| Prop | Tipo | Default | Descripción | |---|---|---|---| | state | 'pending' \| 'active' \| 'canceled' \| 'frozen' | 'pending' | Estado a mostrar |

| State | Texto mostrado | |---|---| | pending | Pendiente | | active | Activo | | canceled | Cancelado | | frozen | Congelado |

Ejemplo React

<DropiBadge state="active" />
<DropiBadge state="pending" />

<dropi-tag>

Tag/chip de color para categorías, estados o etiquetas. Sin eventos.

Props

| Prop | Tipo | Default | Descripción | |---|---|---|---| | type | 'primary' \| 'secondary' | 'primary' | primary = relleno, secondary = suave | | state | 'default' \| 'success' \| 'info' \| 'warning' \| 'error' \| 'legacy' | 'default' | Color del tag | | text | string | '' | Texto del tag | | showIcon | boolean | false | Mostrar ícono | | icon | string | '' | Nombre del ícono del sprite |

Ejemplo React

<DropiTag text="Activo" state="success" type="primary" />
<DropiTag text="Pendiente" state="warning" type="secondary" />
<DropiTag text="Error" state="error" showIcon icon="Warning-circle" />

<dropi-icon>

Renderiza íconos SVG desde el sprite de Dropi. Sin eventos.

Props

| Prop | Tipo | Default | Descripción | |---|---|---|---| | name | string | '' | Nombre del ícono en el sprite (ej. 'Home', 'Search') | | width | string | '24px' | Ancho (valor CSS) | | height | string | '24px' | Alto (valor CSS) | | color | string | 'currentColor' | Hex #ff0000, token sin -- (Primary-Primary-500), o currentColor |

Requiere el sprite en /assets/icons/symbol/svg/sprite.css.svg de la app consumidora.

Ejemplo React

<DropiIcon name="Home" width="24px" height="24px" color="Primary-Primary-500" />
<DropiIcon name="Search" color="#333333" />
<DropiIcon name="Warning-circle" color="Error-Error-500" />

<dropi-tabs>

Sistema de pestañas con contadores y estados.

Props

| Prop | Tipo | Default | Descripción | |---|---|---|---| | tabs | TabItem[] | [] | Lista de tabs { id, label, counter, active, disabled, completed } | | showIcon | boolean | false | Mostrar check si completed |

Eventos

| Evento React | e.detail | Cuándo | |---|---|---| | onOnIndexChanged | TabItem | Al cambiar de tab |

Ejemplo React

<DropiTabs 
  tabs={[{ id: 1, label: 'Activos', counter: 5 }]} 
  onOnIndexChanged={(e) => console.log(e.detail)} 
/>

<dropi-accordion>

Contenedor colapsable.

Props

| Prop | Tipo | Default | Descripción | |---|---|---|---| | header | string | '' | Título del acordeón | | preIcon | string | '' | Ícono izquierdo | | disabled | boolean | false | Deshabilitar |

Ejemplo React

<DropiAccordion header="¿Cómo funciona?">
  <p>Contenido interno</p>
</DropiAccordion>

<dropi-skeleton>

Indicadores de carga.

Props

| Prop | Tipo | Default | Descripción | |---|---|---|---| | variant | 'text' \| 'circle' \| 'rect' | 'text' | Forma | | width | string | '100%' | Ancho CSS | | height | string | '16px' | Alto CSS |


<dropi-paginator>

Control de paginación.

Props

| Prop | Tipo | Default | Descripción | |---|---|---|---| | total | number | 0 | Total de registros | | rows | number | 10 | Registros por página | | showPageSizeSelector | boolean | false | Selector de cantidad por página |

Eventos

| Evento React | e.detail | Cuándo | |---|---|---| | onPageChange | number | Al cambiar de página |

Ejemplo React

<DropiPaginator 
  total={100} 
  onPageChange={(e) => console.log(e.detail)} 
/>

<dropi-empty-state>

Pantalla de "no hay datos".

Props

| Prop | Tipo | Default | Descripción | |---|---|---|---| | header | string | '' | Título principal | | description | string | '' | Subtítulo descriptivo | | actionLabel | string | '' | Texto botón principal | | secondaryLabel | string | '' | Texto botón secundario |

Eventos

| Evento React | e.detail | Cuándo | |---|---|---| | onButtonClickEvent | void | Al hacer click en el botón principal |


<dropi-tooltip> (V2)

Burbuja de información al hover.

Props

| Prop | Tipo | Default | Descripción | |---|---|---|---| | text | string | '' | Mensaje del tooltip | | position | 'top' \| 'bottom' \| 'left' \| 'right' | 'top' | Posición | | maxWidth | string | '280px' | Ancho máximo |

Ejemplo React

<DropiTooltip text="Guardar cambios" position="bottom">
  <DropiButton text="Hover me" />
</DropiTooltip>

<dropi-table>

Tabla de datos con paginación local/backend, ordenación, búsqueda y checkbox de selección.

⚠️ Las filas van en formato TypedField (no objetos planos): { name: { type: 'text', value: 'Ana' } }

Props principales

| Prop | Tipo | Default | Descripción | |---|---|---|---| | headers | DropiTableColumn[] | [] | Columnas { key, label, sortable } | | data | DropiTableRow[] | [] | Filas en formato TypedField | | dropiTableConfiguration | DropiTableConfiguration | null | Config: paginación, búsqueda, acciones | | loading | boolean | false | Indicador de carga |

Eventos

| Evento React | e.detail | Cuándo | |---|---|---| | onDropiSelection | number[] | Checkbox cambia selección | | onDropiSort | { key: string; dir: SortDir } | Click en columna ordenable | | onDropiPageChange | number | Cambio de página (backend) | | onDropiAction | { row: TableRow; action: any } | Click en acción de fila | | onDropiRowClick | { row: TableRow; index: number } | Click en una fila | | onDropiSearch | string | Al buscar |

Ejemplo Angular

<dropi-table
  [headers]="headers"
  [data]="data"
  [dropiTableConfiguration]="{ backendPagination: false, showPaginator: true, pageSizeConfiguration: [5, 10, 25] }"
  [loading]="loading"
  (dropiSort)="onSort($event)"
  (dropiSelection)="onSelect($event)"
/>

<dropi-modal>

Ventana de diálogo con overlays.

Props

| Prop | Tipo | Default | Descripción | |---|---|---|---| | header | string | '' | Título del modal | | size | 's' \| 'm' \| 'l' \| 'full' ... | 'm' | Tamaño | | visible | boolean | false | Controlar visibilidad vía prop |

Eventos

| Evento React | e.detail | Cuándo | |---|---|---| | onOnShow | void | Al abrir el modal | | onOnHide | void | Al cerrar el modal | | onVisibleChange | boolean | Al cambiar visible |

Ejemplo React (Imperativo)

const modalRef = useRef<any>(null);
const Modal = DropiModal as any;

<Modal ref={modalRef} header="Mi Modal" onOnHide={() => console.log('cerrado')}>
  <p>Contenido</p>
  <div slot="footer">
     <DropiButton text="Cerrar" onOnClick={() => modalRef.current.hide()} />
  </div>
</Modal>

Ejemplo React (Declarativo con visible)

const [open, setOpen] = useState(false);

<DropiModal visible={open} header="Confirmar" onOnHide={() => setOpen(false)}>
  <p>¿Estás seguro?</p>
</DropiModal>


<dropi-phone-input>

Input de teléfono con selector de país y sincronización nativa con dropi-core_front.

Props

| Prop | Tipo | Default | Descripción | |---|---|---|---| | name | string | '' | Nombre para formularios nativos | | codArea | string | '57' | Código de área inicial (sin +) | | ngModelPhone | string | '' | Valor del teléfono | | phoneNumberPlaceholder | string | null | Placeholder del campo numérico | | disabledInput | boolean | false | Deshabilita el input | | isValidPhone | boolean | undefined | Estado de validación manual |

Eventos

| Evento React | e.detail | Cuándo | |---|---|---| | onDropiCodChange | string | Cambia el código de área | | onDropiPhoneChange | string | Cambia el número de teléfono |


<dropi-country-selector>

Selector de países con buscador y flags.

Props

| Prop | Tipo | Default | Descripción | |---|---|---|---| | name | string | '' | Nombre para formularios nativos | | label | string | '' | Label superior | | placeholder | string | 'Seleccionar' | Texto por defecto | | currentSelection | string | '' | Código ISO del país seleccionado (ej. 'CO') |

Eventos

| Evento React | e.detail | Cuándo | |---|---|---| | onDropiChangeSelect | CountryItem | Se selecciona un país |


<dropi-otp-send-code>

Campo de validación OTP (Código de seguridad).

Props

| Prop | Tipo | Default | Descripción | |---|---|---|---| | name | string | '' | Nombre para formularios nativos | | digitsCount | number | 6 | Cantidad de dígitos | | engine | 'email' \| 'phone' | 'email' | Ícono y texto descriptivo | | labelContact | string | '' | Correo o Teléfono al que se envió |

Eventos

| Evento React | e.detail | Cuándo | |---|---|---| | onCodeAccepted | string | El código se ha completado |


<dropi-date-picker>

Selector de fechas individual o por rangos.

Props

| Prop | Tipo | Default | Descripción | |---|---|---|---| | name | string | '' | Nombre para formularios nativos | | label | string | '' | Label | | isRange | boolean | false | Habilita selección de rango | | placeholder | string | '' | Placeholder |


<dropi-toast>

Notificaciones tipo push con animaciones Lottie.

Mapeo de Severidad a Lottie:

  • success -> success.json
  • error -> failure.json
  • warn -> warning.json
  • info -> question.json

Ejemplo React

const toastRef = useRef<any>(null);
const Toast = DropiToast as any;
 
<Toast ref={toastRef} position="top-right" />
 
<button onClick={() => toastRef.current.show({ 
  severity: 'success', 
  summary: '¡Éxito!', 
  detail: 'Usuario creado.' 
})}>
  Lanzar Toast
</button>

🏛️ Catálogo Completo de Componentes (65)

A continuación se listan todos los componentes disponibles en la librería, organizados por su función principal.

⌨️ Entradas y Formularios

| Componente | Función | |---|---| | <dropi-input> | Campo de texto versátil con validación | | <dropi-select> | Selector avanzado (búsqueda, flags, multiselect) | | <dropi-text-area> | Área de texto con contador | | <dropi-phone-input> | Input de celular con selector de país | | <dropi-country-selector> | Selector global de países | | <dropi-checkbox> | Checkbox estilizado | | <dropi-switch> | Interruptor On/Off | | <dropi-radio-button> | Opción de selección única | | <dropi-otp-send-code> | Campo de validación de código OTP | | <dropi-date-picker> | Selector de fecha individual | | <dropi-date-picker-range> | Selector de rangos de fecha | | <dropi-color-picker> | Selector de colores | | <dropi-city-selector> | Selector de ciudades por departamentos | | <dropi-file-upload> | Zona de carga de archivos | | <dropi-checkbox-selection-list> | Lista larga de checkboxes con buscador | | <dropi-radio-selection-list> | Lista larga de radio buttons con buscador | | <dropi-search> | Barra de búsqueda especializada |

📊 Visualización de Datos y Status

| Componente | Función | |---|---| | <dropi-table> | Tabla de datos profesional (sort, filter, paginador) | | <dropi-badge> | Estado de cuenta/usuario | | <dropi-badge-legacy> | Badges de contador y estados legacy | | <dropi-tag> | Etiquetas de colores y semánticas | | <dropi-tag-type-product> | Tags específicos para tipos de producto | | <dropi-progress-bar> | Barra de progreso visual | | <dropi-skeleton> | Placeholder de carga (text, circle, rect) | | <dropi-avatars> | Foto de perfil o iniciales | | <dropi-icon> | Renderizador de íconos del sistema | | <dropi-ilustration-icon> | Ilustraciones de estado White Label | | <dropi-logo> | Logotipos oficiales de Dropi | | <dropi-chips> | Etiquetas con opción de cierre | | <dropi-image-miniature> | Galería de miniaturas de imágenes | | <dropi-country-flags> | Renderizador de banderas por código |

🔔 Feedback y Overlays

| Componente | Función | |---|---| | <dropi-modal> | Ventana de diálogo base | | <dropi-alert-modal> | Modal de confirmación con Lottie | | <dropi-toast> | Notificaciones push flotantes | | <dropi-alert> | Banner de alerta (inline/flag) | | <dropi-alert-legacy> | Alerta simple para compatibilidad Angular | | <dropi-drawer> | Panel lateral deslizable | | <dropi-tooltip> | Burbuja de información (hover) | | <dropi-tooltip-v2> | Tooltip mejorado con posiciones avanzadas | | <dropi-empty-state> | Pantalla "Sin resultados" con acciones | | <dropi-banner-external> | Banner publicitario/informativo externo | | <dropi-lottie-loader> | Cargador animado Lottie genérico |

🗺️ Navegación y Estructura

| Componente | Función | |---|---| | <dropi-navbar> | Barra de navegación superior | | <dropi-sidebar> | Menú lateral de navegación | | <dropi-tabs> | Sistema de pestañas con contadores | | <dropi-breadcrumb> | Migas de pan para navegación | | <dropi-paginator> | Control de páginas para listas | | <dropi-steps> | Indicador de pasos horizontal | | <dropi-vertical-steps> | Indicador de pasos vertical | | <dropi-simple-stepper> | Stepper simplificado para flujos rápidos | | <dropi-accordion> | Acordeón simple | | <dropi-accordion-item> | Item individual de acordeón |

🎥 Multimedia y Otros

| Componente | Función | |---|---| | <dropi-media-player> | Reproductor de Audio/Video personalizado | | <dropi-youtube-lazy-video> | Carga diferida de videos de YT | | <dropi-image-overlay> | Visualizador de imagen a pantalla completa | | <dropi-read-more> | Truncado de texto con "Ver más" | | <dropi-time-line> | Línea de tiempo de eventos/tracking | | <dropi-file-upload-progress-bar> | Barra de progreso individual por archivo | | <dropi-carousel> | Carrusel de imágenes/contenido |


🤖 AI Skills & Automation

Esta librería está diseñada para ser mantenida por IAs (Claude Code, Cursor, Windsurf).

Skills Universales (Compatibles con Claude, Cursor, Windsurf)

Todos los skills han sido estandarizados en la carpeta /skills.

  • /install-dropi-uiskills/install-dropi-ui/skill.md
  • /update-contextskills/update-context/skill.md

Build (desarrollo)

npm run build   # compilar
npm run start   # dev con watch
npm test        # unit tests