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

angular-cem-generator

v1.0.1

Published

Generate Angular wrapper components from Custom Element Manifest (CEM) JSON

Downloads

9

Readme

Angular CEM Generator

Generate Angular wrapper components from Custom Element Manifest (CEM) JSON files.

Overview

This package takes a Custom Element Manifest JSON file as input and automatically generates strongly-typed Angular wrapper components for your web components. The generated components provide:

  • Strong typing - Full TypeScript support with proper types
  • 🎯 Property binding - Two-way binding support for all properties
  • 📢 Event emitters - Angular EventEmitter for all custom events
  • 🔄 Change detection - OnPush strategy for optimal performance
  • 🚀 Standalone components - No NgModule required
  • 📝 JSDoc comments - Preserves descriptions and default values

Installation

pnpm add angular-cem-generator

Usage

Basic Example

import { generateAngularComponents } from 'angular-cem-generator';

await generateAngularComponents({
  manifestPath: './custom-elements.json',
  outputDir: './src/components',
  componentCorePackage: '@my-org/web-components',
  standalone: true,
  inlineProperties: true,
});

Configuration Options

| Option | Type | Default | Description | |--------|------|---------|-------------| | manifestPath | string | required | Path to the Custom Element Manifest JSON file | | outputDir | string | required | Output directory for generated Angular components | | componentCorePackage | string | required | Name of the package containing the web components | | standalone | boolean | true | Generate standalone Angular components | | inlineProperties | boolean | true | Include inline property declarations with types |

Generated Files

The generator creates the following file structure:

output/
├── proxies.ts              # Angular wrapper components
├── components.d.ts         # TypeScript type definitions
├── index.ts                # Barrel export file
└── angular-component-lib/
    └── utils.ts            # Runtime utilities (ProxyCmp decorator)

Example: Using Generated Components in Angular

Given a Custom Element Manifest with a data-table component:

// Import the generated components
import { DataTable } from './components';

@Component({
  selector: 'app-root',
  standalone: true,
  imports: [DataTable],
  template: `
    <data-table
      [data]="tableData"
      [sortable]="true"
      [pageSize]="20"
      (rowClick)="handleRowClick($event)"
      (sortChange)="handleSort($event)"
    ></data-table>
  `
})
export class AppComponent {
  tableData = [
    { id: 1, name: 'Alice', age: 30 },
    { id: 2, name: 'Bob', age: 25 },
  ];

  handleRowClick(event: CustomEvent) {
    console.log('Row clicked:', event.detail);
  }

  handleSort(event: CustomEvent) {
    console.log('Sort changed:', event.detail);
  }
}

Custom Element Manifest Format

The generator expects a standard CEM JSON file following the schema version 2.0+.

Example manifest structure:

{
  "schemaVersion": "2.1.0",
  "modules": [
    {
      "kind": "javascript-module",
      "path": "src/my-button.ts",
      "declarations": [
        {
          "kind": "class",
          "name": "MyButton",
          "tagName": "my-button",
          "customElement": true,
          "members": [
            {
              "kind": "field",
              "name": "label",
              "type": { "text": "string" },
              "default": "'Click me'"
            }
          ],
          "events": [
            {
              "name": "button-click",
              "type": { "text": "CustomEvent<void>" }
            }
          ]
        }
      ]
    }
  ]
}

Generating a CEM

You can generate a Custom Element Manifest using tools like:

Example using the analyzer:

npx @custom-elements-manifest/analyzer

Features

Property Binding

All component properties are available as Angular inputs with full type checking:

// Generated component has typed properties
<my-component [disabled]="false" [label]="'Hello'"></my-component>

Event Handling

Custom events are converted to Angular EventEmitters with camelCase names:

// 'button-click' event becomes 'buttonClick' output
<my-button (buttonClick)="handleClick($event)"></my-button>

Type Safety

The generator creates TypeScript interfaces that match your web component definitions:

import { Components } from './components';

// Fully typed component interface
const tableProps: Components.DataTable = {
  data: [...],
  sortable: true,
  // ... TypeScript will validate all properties
};

JSDoc Preservation

Comments and descriptions from your CEM are preserved in the generated code:

/**
 * Enable or disable sorting functionality.
 * @default true
 */
set sortable(val: boolean) {
  this.el['sortable'] = val;
}

Example Project

Check out the examples directory for a complete working example with:

  • Complex CEM JSON file with 3 feature-rich components
  • Generation script
  • Example usage in Angular

Run the example:

pnpm example

How It Works

  1. Parse - Reads and parses the Custom Element Manifest JSON
  2. Transform - Converts CEM metadata to internal component format
  3. Generate - Creates Angular component wrapper code with:
    • @Component decorator with proper configuration
    • @ProxyCmp decorator for property/method proxying
    • EventEmitter outputs for all custom events
    • Inline property setters with TypeScript types
  4. Write - Outputs TypeScript files ready to use in Angular

Comparison with Stencil Angular Output Target

This package is inspired by @stencil/angular-output-target but works with the standard Custom Element Manifest format instead of Stencil's internal metadata. This means it can be used with:

  • Lit components
  • Plain web components
  • Any framework that generates CEM JSON

Contributing

Contributions are welcome! Please feel free to submit issues or pull requests.

License

MIT