Skip to content

Commit

Permalink
feat(angular): support Angular 14 standalone components
Browse files Browse the repository at this point in the history
  • Loading branch information
leosvelperez committed Jun 1, 2022
1 parent 5bacf4d commit 41752fe
Show file tree
Hide file tree
Showing 3 changed files with 62 additions and 3 deletions.
12 changes: 9 additions & 3 deletions app/angular/src/client/preview/angular-beta/StorybookModule.ts
Expand Up @@ -7,7 +7,7 @@ import deprecate from 'util-deprecate';
import { ICollection, StoryFnAngularReturnType } from '../types';
import { storyPropsProvider } from './StorybookProvider';
import { isComponentAlreadyDeclaredInModules } from './utils/NgModulesAnalyzer';
import { isDeclarable } from './utils/NgComponentAnalyzer';
import { isDeclarable, isStandaloneComponent } from './utils/NgComponentAnalyzer';
import { createStorybookWrapperComponent } from './StorybookWrapperComponent';
import { computesTemplateFromComponent } from './ComputesTemplateFromComponent';

Expand Down Expand Up @@ -61,22 +61,28 @@ export const getStorybookModuleMetadata = (
props
);

const isStandalone = isStandaloneComponent(component);
// Look recursively (deep) if the component is not already declared by an import module
const requiresComponentDeclaration =
isDeclarable(component) &&
!isComponentAlreadyDeclaredInModules(
component,
moduleMetadata.declarations,
moduleMetadata.imports
);
) &&
!isStandalone;

return {
declarations: [
...(requiresComponentDeclaration ? [component] : []),
ComponentToInject,
...(moduleMetadata.declarations ?? []),
],
imports: [BrowserModule, ...(moduleMetadata.imports ?? [])],
imports: [
BrowserModule,
...(isStandalone ? [component] : []),
...(moduleMetadata.imports ?? []),
],
providers: [storyPropsProvider(storyProps$), ...(moduleMetadata.providers ?? [])],
entryComponents: [...(moduleMetadata.entryComponents ?? [])],
schemas: [...(moduleMetadata.schemas ?? [])],
Expand Down
Expand Up @@ -19,6 +19,7 @@ import {
isComponent,
isDeclarable,
getComponentDecoratorMetadata,
isStandaloneComponent,
} from './NgComponentAnalyzer';

describe('getComponentInputsOutputs', () => {
Expand Down Expand Up @@ -235,6 +236,46 @@ describe('isComponent', () => {
});
});

describe('isStandaloneComponent', () => {
it('should return true with a Component with "standalone: true"', () => {
// TODO: `standalone` is only available in Angular v14. Remove cast to `any` once
// Angular deps are updated to v14.x.x.
@Component({ standalone: true } as any)
class FooComponent {}

expect(isStandaloneComponent(FooComponent)).toEqual(true);
});

it('should return false with a Component with "standalone: false"', () => {
// TODO: `standalone` is only available in Angular v14. Remove cast to `any` once
// Angular deps are updated to v14.x.x.
@Component({ standalone: false } as any)
class FooComponent {}

expect(isStandaloneComponent(FooComponent)).toEqual(false);
});

it('should return false with a Component without the "standalone" property', () => {
@Component({})
class FooComponent {}

expect(isStandaloneComponent(FooComponent)).toEqual(false);
});

it('should return false with simple class', () => {
class FooPipe {}

expect(isStandaloneComponent(FooPipe)).toEqual(false);
});

it('should return false with Directive', () => {
@Directive()
class FooDirective {}

expect(isStandaloneComponent(FooDirective)).toEqual(false);
});
});

describe('getComponentDecoratorMetadata', () => {
it('should return Component with a Component', () => {
@Component({ selector: 'foo' })
Expand Down
Expand Up @@ -108,6 +108,18 @@ export const isComponent = (component: any): component is Type<unknown> => {
return (decorators || []).some((d) => d instanceof Component);
};

export const isStandaloneComponent = (component: any): component is Type<unknown> => {
if (!component) {
return false;
}

const decorators = reflectionCapabilities.annotations(component);

// TODO: `standalone` is only available in Angular v14. Remove cast to `any` once
// Angular deps are updated to v14.x.x.
return (decorators || []).some((d) => d instanceof Component && (d as any).standalone);
};

/**
* Returns all component decorator properties
* is used to get all `@Input` and `@Output` Decorator
Expand Down

0 comments on commit 41752fe

Please sign in to comment.