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

@desynth/web-components-angular

v14.9.26-alpha.5

Published

Angular proxy for @desynth/web-components

Readme

@desynth/web-components-angular

Proxies Angular standalone para los Custom Elements de @desynth/web-components, generados por @stencil/angular-output-target.

Compatibilidad e instalación

El workspace compila el paquete con Angular 19.0.x. El artefacto generado declara peer dependencies de @angular/core y @angular/common ^17.0.0; valida la combinación concreta con la versión de Angular de la aplicación.

Los proxies importan tipos y módulos Custom Element desde el paquete core, por lo que ambas bibliotecas deben estar disponibles:

npm install @desynth/web-components-angular @desynth/web-components

El manifiesto raíz expone actualmente la librería compilada mediante el subpath ./dist. Por tanto, los imports de consumo se hacen desde:

import { DesynthButton } from '@desynth/web-components-angular/dist';

No se documenta un import desde la raíz porque el mapa exports publicado no define ..

Componentes standalone

Cada proxy generado tiene standalone: true, usa ChangeDetectionStrategy.OnPush y registra su propio Custom Element mediante el módulo individual de @desynth/web-components/dist. No es necesario llamar a defineCustomElements().

import { Component } from '@angular/core';
import {
  DesynthButton,
  DesynthTextInput,
} from '@desynth/web-components-angular/dist';

@Component({
  selector: 'app-profile-form',
  standalone: true,
  imports: [DesynthButton, DesynthTextInput],
  template: `
    <desynth-text-input
      inputId="display-name"
      inputName="Nombre"
      [inputValue]="name"
      (handleInput)="updateName($event)"
    />

    <desynth-button
      buttonText="Guardar"
      variant="solid"
      [disabled]="saving"
      (handleClick)="save()"
    />
  `,
})
export class ProfileFormComponent {
  name = '';
  saving = false;

  updateName(event: CustomEvent<HTMLInputElement>): void {
    this.name = event.detail.value;
  }

  save(): void {
    // Persistencia de la aplicación.
  }
}

Los selectores conservan las etiquetas originales: por ejemplo desynth-button, desynth-data-table, horizontal-cards y html-editor.

Módulo de compatibilidad

El paquete también exporta StencilWrapperModule, pero el módulo mantenido en el repositorio solo agrupa un subconjunto de los proxies. Para código nuevo, importa directamente las clases standalone que use cada componente; es explícito, permite tree shaking y evita asumir que el módulo contiene los 86 elementos.

Si una aplicación basada en NgModules usa únicamente ese subconjunto, puede importar:

import { NgModule } from '@angular/core';
import { StencilWrapperModule } from '@desynth/web-components-angular/dist';

@NgModule({
  imports: [StencilWrapperModule],
})
export class SharedUiModule {}

Inputs y bindings

Los nombres de @Input son las propiedades camelCase de Stencil. Usa property binding para valores dinámicos o no string:

<desynth-button
  [buttonText]="submitLabel"
  [disabled]="form.invalid"
  [full]="true"
></desynth-button>

En una plantilla, un atributo literal sigue siendo texto. Por eso [disabled]="false" y disabled="false" no son equivalentes para una entrada booleana.

Los proxies trasladan las asignaciones a la propiedad del Custom Element fuera de la zona de Angular. No hay ControlValueAccessor configurado: la lista valueAccessorConfigs del output target está vacía. En consecuencia, no asumas compatibilidad automática con [(ngModel)] o formControlName; conecta el valor y el evento explícitamente.

Propiedades JSON

En el paquete core, numerosas colecciones están tipadas como string y se parsean con JSON.parse. Serializa esos valores antes de enlazarlos:

import { Component } from '@angular/core';
import { DesynthDataTable } from '@desynth/web-components-angular/dist';

@Component({
  selector: 'app-users-table',
  standalone: true,
  imports: [DesynthDataTable],
  template: `
    <desynth-data-table
      [columns]="columnsJson"
      [rows]="rowsJson"
      [actions]="actionsJson"
      emptyText="Sin resultados"
      (handleAction)="handleAction($event)"
    />
  `,
})
export class UsersTableComponent {
  readonly columnsJson = JSON.stringify([
    { key: 'name', label: 'Nombre' },
  ]);

  readonly rowsJson = JSON.stringify([
    { id: 'usr-1', name: 'Ada' },
  ]);

  readonly actionsJson = JSON.stringify([
    { key: 'open', label: 'Abrir' },
  ]);

  handleAction(
    event: CustomEvent<{ rowId: string; action: string }>,
  ): void {
    console.log(event.detail.rowId, event.detail.action);
  }
}

No serialices a ciegas: utiliza los tipos de los proxies y la referencia del componente core como fuente de verdad.

Outputs y eventos

Los eventos del Custom Element se exponen con el mismo nombre como outputs Angular: (handleClick), (handleChange), (handleAction), (htmlChanged), etc. El valor recibido sigue siendo un CustomEvent; la carga útil está en $event.detail.

<desynth-tabs
  [items]="tabsJson"
  (handleChange)="selectTab($event)"
></desynth-tabs>
selectTab(event: CustomEvent<{ id: string; index: number }>): void {
  console.log(event.detail.id, event.detail.index);
}

La utilidad generada crea los outputs con fromEvent. Aunque las declaraciones usan EventEmitter<CustomEvent<...>>, no debes llamar a .emit() desde la aplicación: trata esos miembros como salidas del componente.

Proyección de contenido y slots

Los proxies usan <ng-content>, por lo que Angular proyecta el contenido al Custom Element. El atributo estándar slot selecciona slots con nombre:

import { Component } from '@angular/core';
import {
  DesynthBookCard,
  DesynthButton,
} from '@desynth/web-components-angular/dist';

@Component({
  selector: 'app-book-card',
  standalone: true,
  imports: [DesynthBookCard, DesynthButton],
  template: `
    <desynth-book-card
      title="Diseño de sistemas"
      [chapters]="chaptersJson"
    >
      <div slot="actions">
        <desynth-button buttonText="Leer" size="xs" />
      </div>
    </desynth-book-card>
  `,
})
export class BookCardComponent {
  readonly chaptersJson = JSON.stringify([
    'Introducción',
    'Arquitectura',
  ]);
}

Los nombres de slot son específicos de cada componente.

SSR

El decorador generado intenta definir cada Custom Element al importar el proxy, pero comprueba typeof customElements !== 'undefined' antes de acceder al registro. Aun así, el renderizado interno del Web Component ocurre en el navegador: no asumas que Angular SSR produce su Shadow DOM completo en el HTML del servidor. Prueba la hidratación y cualquier acceso directo a window, archivos o APIs del navegador de los componentes usados.

Tokens

Carga las variables CSS globalmente, por ejemplo en styles.css:

@import '@desynth/style-tokens/dist/assets/css/variables-all.css';

El paquete core utiliza esos tokens, pero no los inyecta como tema global del consumidor.

Build y regeneración local

Los archivos lib/src/directives/proxies.ts y proxies-list.tsx son generados por el build de Stencil; no deben editarse manualmente. Desde la raíz del monorepo:

npm run build --workspace=@desynth/web-components
npm run build --workspace=@desynth/web-components-angular

El primer comando sincroniza los proxies Angular con los componentes actuales. El segundo ejecuta:

ng build stencil-wrapper

y ng-packagr escribe el paquete en packages/components-angular/dist usando lib/index.ts como entrada pública.

No hay script de tests definido en el manifiesto de este paquete. Aunque angular.json contiene una configuración Karma, sus rutas apuntan a libs/stencil-wrapper, mientras la librería real vive en lib; corrige esa configuración antes de presentarla como un comando de test soportado.

Licencia

MPL-2.0 según el manifiesto raíz del paquete.