Angular

Knapsack for Angular lets you develop and test components in isolation.
View as Markdown

Knapsack for Angular works by scanning your specified Angular code locations and automatically discovering reusable components, making them instantly available in your design system.

Why This Approach:

  • Zero Manual Work - Knapsack finds and configures your components automatically
  • 🔄 Always Current - Your documentation stays in sync with code changes
  • 🎯 Intelligent - Understands different export patterns and component structures
  • 🚀 Scale Effortlessly - Handle hundreds of components without individual setup

Requirements

  • Angular 17 or later - The Angular renderer requires Angular 17+ and will exit with an error if an older version is detected
  • Built packages - Components must be built into packages using ng-packagr
  • Package paths only - Local TypeScript files are not supported

Important: The Angular renderer only supports built packages created with ng-packagr. Local TypeScript files are not supported. Ensure your Angular components are built into proper packages before using them with Knapsack.


Install

$npm install @knapsack/renderer-angular

Configure

Minimal Setup

The simplest configuration requires specifying your Angular package:

1// knapsack.config.js
2const { KnapsackAngularRenderer } = require('@knapsack/renderer-angular');
3
4module.exports = configureKnapsack({
5 templateRenderers: [
6 new KnapsackAngularRenderer({
7 codeSrcs: [{ path: '@my-org/angular-components' }],
8 }),
9 ],
10});

Full Configuration Example

Here’s a comprehensive example showing all available options:

1// knapsack.config.js
2const { KnapsackAngularRenderer } = require('@knapsack/renderer-angular');
3const path = require('path');
4
5module.exports = configureKnapsack({
6 templateRenderers: [
7 new KnapsackAngularRenderer({
8 // Optional: your own NgModule to provide providers/imports used by demos
9 customNgModulePath: './knapsack/knapsack.module.ts',
10
11 // Optional: a wrapper component that surrounds every template
12 wrapperComponentPath: './knapsack/knapsack-wrapper.component.ts',
13
14 // Optional: helpful path aliases for monorepos
15 pkgPathAliases: {
16 '@shared': path.resolve(__dirname, 'libs/shared/src'),
17 '@ui': path.resolve(__dirname, 'libs/ui/src'),
18 },
19
20 // Where to discover Angular components (package paths only)
21 codeSrcs: [
22 // Built Angular packages
23 { path: '@my-org/angular-components' },
24 { path: '@angular/material' },
25
26 // Local built packages
27 { path: './dist/my-components' },
28 ],
29 }),
30 ],
31});

Code Sources

The codeSrcs array tells Knapsack where to find your Angular components. Only package paths are supported - the renderer will scan these packages and make Angular components available in the Knapsack UI.

Built Packages
1codeSrcs: [
2 // External Angular packages
3 { path: '@angular/material' },
4 { path: '@my-org/angular-design-system' },
5
6 // Local built packages
7 { path: './dist/my-components' },
8 { path: './libs/ui/dist' },
9];
Package Sub-paths
1codeSrcs: [
2 // Specific sub-paths within packages
3 { path: '@angular/material/button' },
4 { path: '@angular/material/card' },
5 { path: '@my-org/design-system/components/button' },
6];
Smart Filtering

Use filters to control exactly which components are discovered:

1codeSrcs: [
2 {
3 path: '@angular/material/*',
4 filter: (filePath) => {
5 // Exclude non-component or internal Angular Material entries
6 const excludedPaths = [
7 '@angular/material/index',
8 '@angular/material/testing',
9 '/experimental',
10 '/schematics',
11 ];
12 return !excludedPaths.some((excluded) => filePath.includes(excluded));
13 },
14 },
15];

Custom NgModule Path

The customNgModulePath configuration option specifies the path to a custom Angular module that is imported into Knapsack alongside the main renderer application.

1. Create a Custom Module:

Create a file (e.g., ks.module.ts):

1// Note: Providers from the `BrowserModule` have already been loaded.
2import { CommonModule } from '@angular/common';
3import { NgModule } from '@angular/core';
4import { RouterOutlet } from '@angular/router';
5import { ButtonModule } from 'primeng/button';
6
7@NgModule({
8 declarations: [],
9 imports: [CommonModule, RouterOutlet, ButtonModule],
10 exports: [],
11})
12// ensure the module is the default export
13export default class KsModule {}

2. Add your Module Path

Reference your module in the renderer configuration:

1module.exports = configureKnapsack({
2 templateRenderers: [
3 new KnapsackAngularRenderer({
4 customNgModulePath: './ks.module.ts',
5 }),
6 ],
7});

Package Path Aliases

The pkgPathAliases configuration provides path aliases for monorepo packages:

1module.exports = configureKnapsack({
2 templateRenderers: [
3 new KnapsackAngularRenderer({
4 pkgPathAliases: {
5 '@my-org/my-ds': path.resolve(__dirname, '../../dist/of/lib/'),
6 '@shared': path.resolve(__dirname, '../shared-components/src'),
7 },
8 }),
9 ],
10});

Wrapper Component

The wrapperComponentPath configuration option specifies the path to a custom component that wraps all of your Angular component demos.

1. Create a Wrapper Component:

Create a file (e.g., demo-wrapper.component.ts):

1import { Component } from '@angular/core';
2
3@Component({
4 selector: 'app-wrapper',
5 template: `
6 <div class="demo-wrapper">
7 <div class="demo-wrapper__content">
8 <ng-content></ng-content>
9 </div>
10 </div>
11 `,
12 styles: [
13 `
14 .demo-wrapper {
15 padding: 1rem;
16 border-radius: 4px;
17 margin: 1rem 0;
18 }
19
20 .demo-wrapper__content {
21 min-height: 50px;
22 }
23 `,
24 ],
25 // must be a standalone component
26 standalone: true,
27})
28// ensure the module is the default export
29export default class WrapperComponent {}

2. Add your Wrapper Path

Reference your wrapper in the renderer configuration:

1module.exports = configureKnapsack({
2 templateRenderers: [
3 new KnapsackAngularRenderer({
4 wrapperComponentPath: './demo-wrapper.component.ts',
5 }),
6 ],
7});