angular-cem-generator
v1.0.1
Published
Generate Angular wrapper components from Custom Element Manifest (CEM) JSON
Downloads
9
Maintainers
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-generatorUsage
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:
- @custom-elements-manifest/analyzer - Analyzes your source code
- Lit CLI - Built-in for Lit projects
Example using the analyzer:
npx @custom-elements-manifest/analyzerFeatures
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 exampleHow It Works
- Parse - Reads and parses the Custom Element Manifest JSON
- Transform - Converts CEM metadata to internal component format
- Generate - Creates Angular component wrapper code with:
@Componentdecorator with proper configuration@ProxyCmpdecorator for property/method proxying- EventEmitter outputs for all custom events
- Inline property setters with TypeScript types
- 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
