forked from storybookjs/storybook
/
StorybookModule.ts
101 lines (91 loc) 路 3.29 KB
/
StorybookModule.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
import { NgModule, Type } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import dedent from 'ts-dedent';
import { Subject } from 'rxjs';
import deprecate from 'util-deprecate';
import { ICollection, StoryFnAngularReturnType } from '../types';
import { storyPropsProvider } from './StorybookProvider';
import { isComponentAlreadyDeclaredInModules } from './utils/NgModulesAnalyzer';
import { isDeclarable, isStandaloneComponent } from './utils/NgComponentAnalyzer';
import { createStorybookWrapperComponent } from './StorybookWrapperComponent';
import { computesTemplateFromComponent } from './ComputesTemplateFromComponent';
const deprecatedStoryComponentWarning = deprecate(
() => {},
dedent`\`component\` story return value is deprecated, and will be removed in Storybook 7.0.
Instead, use \`export const default = () => ({ component: AppComponent });\`
or
\`\`\`
export const Primary: Story = () => ({});
Primary.parameters = { component: AppComponent };
\`\`\`
Read more at
- https://github.com/storybookjs/storybook/blob/next/MIGRATION.md#deprecated-angular-story-component).
- https://storybook.js.org/docs/angular/writing-stories/parameters
`
);
export const getStorybookModuleMetadata = (
{
storyFnAngular,
component: annotatedComponent,
targetSelector,
}: {
storyFnAngular: StoryFnAngularReturnType;
component?: any;
targetSelector: string;
},
storyProps$: Subject<ICollection>
): NgModule => {
const { component: storyComponent, props, styles, moduleMetadata = {} } = storyFnAngular;
let { template } = storyFnAngular;
if (storyComponent) {
deprecatedStoryComponentWarning();
}
const component = storyComponent ?? annotatedComponent;
if (hasNoTemplate(template) && component) {
template = computesTemplateFromComponent(component, props, '');
}
/**
* Create a component that wraps generated template and gives it props
*/
const ComponentToInject = createStorybookWrapperComponent(
targetSelector,
template,
component,
styles,
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,
...(isStandalone ? [component] : []),
...(moduleMetadata.imports ?? []),
],
providers: [storyPropsProvider(storyProps$), ...(moduleMetadata.providers ?? [])],
entryComponents: [...(moduleMetadata.entryComponents ?? [])],
schemas: [...(moduleMetadata.schemas ?? [])],
bootstrap: [ComponentToInject],
};
};
export const createStorybookModule = (ngModule: NgModule): Type<unknown> => {
@NgModule(ngModule)
class StorybookModule {}
return StorybookModule;
};
function hasNoTemplate(template: string | null | undefined): template is undefined {
return template === null || template === undefined;
}