@storybook/angular 7.0.0-beta.9 → 7.0.0-rc.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (86) hide show
  1. package/README.md +214 -0
  2. package/dist/builders/build-storybook/index.d.ts +5 -3
  3. package/dist/builders/build-storybook/index.js +9 -4
  4. package/dist/builders/build-storybook/schema.json +14 -6
  5. package/dist/builders/start-storybook/index.d.ts +5 -3
  6. package/dist/builders/start-storybook/index.js +15 -6
  7. package/dist/builders/start-storybook/schema.json +10 -5
  8. package/dist/builders/utils/error-handler.d.ts +2 -0
  9. package/dist/builders/utils/{build-standalone-errors-handler.js → error-handler.js} +6 -3
  10. package/dist/builders/utils/run-compodoc.js +11 -27
  11. package/dist/builders/utils/run-compodoc.spec.js +42 -0
  12. package/dist/builders/utils/standalone-options.d.ts +2 -2
  13. package/dist/client/angular-beta/AbstractRenderer.d.ts +3 -3
  14. package/dist/client/angular-beta/AbstractRenderer.js +31 -31
  15. package/dist/client/angular-beta/CanvasRenderer.js +1 -1
  16. package/dist/client/angular-beta/DocsRenderer.js +5 -3
  17. package/dist/client/angular-beta/RendererFactory.js +5 -4
  18. package/dist/client/angular-beta/StorybookModule.d.ts +3 -6
  19. package/dist/client/angular-beta/StorybookModule.js +4 -45
  20. package/dist/client/angular-beta/StorybookModule.test.js +51 -36
  21. package/dist/client/angular-beta/StorybookWrapperComponent.d.ts +3 -2
  22. package/dist/client/angular-beta/StorybookWrapperComponent.js +30 -2
  23. package/dist/client/angular-beta/__testfixtures__/test.module.d.ts +2 -0
  24. package/dist/client/angular-beta/__testfixtures__/test.module.js +20 -0
  25. package/dist/client/angular-beta/utils/NgComponentAnalyzer.js +1 -1
  26. package/dist/client/angular-beta/utils/NgComponentAnalyzer.test.js +43 -5
  27. package/dist/client/angular-beta/utils/NgModulesAnalyzer.d.ts +1 -1
  28. package/dist/client/angular-beta/utils/NgModulesAnalyzer.js +4 -4
  29. package/dist/client/angular-beta/utils/NgModulesAnalyzer.test.js +3 -3
  30. package/dist/client/angular-beta/utils/PropertyExtractor.d.ts +32 -0
  31. package/dist/client/angular-beta/utils/PropertyExtractor.js +136 -0
  32. package/dist/client/angular-beta/utils/PropertyExtractor.test.d.ts +1 -0
  33. package/dist/client/angular-beta/utils/PropertyExtractor.test.js +141 -0
  34. package/dist/client/config.d.ts +1 -1
  35. package/dist/client/config.js +1 -1
  36. package/dist/client/decorateStory.js +1 -1
  37. package/dist/client/docs/compodoc.js +5 -7
  38. package/dist/client/docs/config.js +1 -2
  39. package/dist/client/docs/sourceDecorator.js +2 -1
  40. package/dist/client/globals.d.ts +0 -8
  41. package/dist/client/globals.js +2 -29
  42. package/dist/client/public-api.js +3 -3
  43. package/dist/client/public-types.d.ts +2 -1
  44. package/dist/client/render.d.ts +1 -0
  45. package/dist/client/render.js +1 -5
  46. package/dist/client/types.d.ts +1 -2
  47. package/dist/index.mjs +13 -0
  48. package/dist/preset.js +3 -5
  49. package/dist/preset.mjs +27 -0
  50. package/dist/renderer.d.ts +2 -1
  51. package/dist/renderer.js +4 -2
  52. package/dist/renderer.mjs +5 -0
  53. package/dist/server/framework-preset-angular-cli.d.ts +2 -1
  54. package/dist/server/framework-preset-angular-cli.js +21 -92
  55. package/dist/server/preset-options.d.ts +3 -2
  56. package/dist/types.mjs +1 -0
  57. package/jest.config.js +19 -0
  58. package/package.json +46 -45
  59. package/template/cli/Button.stories.ts +1 -1
  60. package/template/cli/Header.stories.ts +2 -2
  61. package/template/cli/button.component.ts +2 -0
  62. package/template/components/index.js +2 -2
  63. package/template/stories/angular-mdx.stories.mdx +1 -1
  64. package/template/stories/argTypes/doc-button/doc-button.component.ts +1 -2
  65. package/template/stories/basics/component-without-selector/without-selector-ng-component-outlet.stories.ts +1 -1
  66. package/template/stories/basics/component-without-selector/without-selector-ng-factory-resolver.stories.ts +1 -1
  67. package/template/stories/basics/component-without-selector/without-selector.stories.ts +1 -1
  68. package/template/stories/basics/ng-module/import-module-chip.stories.ts +23 -0
  69. package/template/stories/basics/ng-module/import-module.stories.ts +2 -13
  70. package/template/stories/core/decorators/componentWrapperDecorator/decorators.stories.ts +0 -18
  71. package/template/stories/core/moduleMetadata/angular-src/open-close-component/open-close.component.css +13 -0
  72. package/template/stories/core/moduleMetadata/angular-src/open-close-component/open-close.component.html +7 -0
  73. package/template/stories/core/moduleMetadata/angular-src/open-close-component/open-close.component.ts +39 -0
  74. package/template/stories/core/moduleMetadata/with-browser-animations.stories.ts +30 -0
  75. package/template/stories/core/moduleMetadata/with-noop-browser-animations.stories.ts +27 -0
  76. package/template/stories/core/parameters/bootstrap-options.stories.ts +1 -5
  77. package/template/stories/others/app-initializer-use-factory/app-initializer-use-factory.stories.ts +34 -0
  78. package/dist/builders/utils/build-standalone-errors-handler.d.ts +0 -1
  79. package/dist/client/angular/helpers.d.ts +0 -8
  80. package/dist/client/angular/helpers.js +0 -150
  81. package/dist/server/angular-read-workspace.d.ts +0 -13
  82. package/dist/server/angular-read-workspace.js +0 -78
  83. package/dist/server/utils/normalize-asset-patterns.d.ts +0 -7
  84. package/dist/server/utils/normalize-asset-patterns.js +0 -64
  85. package/dist/server/utils/normalize-optimization.d.ts +0 -3
  86. package/dist/server/utils/normalize-optimization.js +0 -21
@@ -26,36 +26,24 @@ var _a;
26
26
  Object.defineProperty(exports, "__esModule", { value: true });
27
27
  exports.AbstractRenderer = void 0;
28
28
  const core_1 = require("@angular/core");
29
- const platform_browser_dynamic_1 = require("@angular/platform-browser-dynamic");
29
+ const platform_browser_1 = require("@angular/platform-browser");
30
30
  const rxjs_1 = require("rxjs");
31
31
  const telejson_1 = require("telejson");
32
32
  const StorybookModule_1 = require("./StorybookModule");
33
- // platform must be init only if render is called at least once
34
- let platformRef;
35
- function getPlatform(newPlatform) {
36
- if (!platformRef || newPlatform) {
37
- platformRef = (0, platform_browser_dynamic_1.platformBrowserDynamic)();
38
- }
39
- return platformRef;
40
- }
33
+ const StorybookProvider_1 = require("./StorybookProvider");
34
+ const StorybookWrapperComponent_1 = require("./StorybookWrapperComponent");
35
+ const PropertyExtractor_1 = require("./utils/PropertyExtractor");
36
+ const applicationRefs = new Set();
41
37
  class AbstractRenderer {
42
38
  /**
43
39
  * Wait and destroy the platform
44
40
  */
45
- static resetPlatformBrowserDynamic() {
46
- return new Promise((resolve) => {
47
- if (platformRef && !platformRef.destroyed) {
48
- platformRef.onDestroy(async () => {
49
- resolve();
50
- });
51
- // Destroys the current Angular platform and all Angular applications on the page.
52
- // So call each angular ngOnDestroy and avoid memory leaks
53
- platformRef.destroy();
54
- return;
41
+ static resetApplications() {
42
+ StorybookWrapperComponent_1.componentNgModules.clear();
43
+ applicationRefs.forEach((appRef) => {
44
+ if (!appRef.destroyed) {
45
+ appRef.destroy();
55
46
  }
56
- resolve();
57
- }).then(() => {
58
- getPlatform(true);
59
47
  });
60
48
  }
61
49
  constructor(storyId) {
@@ -82,12 +70,13 @@ class AbstractRenderer {
82
70
  * @param parameters {Parameters}
83
71
  */
84
72
  async render({ storyFnAngular, forced, parameters, component, targetDOMNode, }) {
85
- const targetSelector = `${this.generateTargetSelectorFromStoryId()}`;
73
+ const targetSelector = this.generateTargetSelectorFromStoryId(targetDOMNode.id);
86
74
  const newStoryProps$ = new rxjs_1.BehaviorSubject(storyFnAngular.props);
87
- const moduleMetadata = (0, StorybookModule_1.getStorybookModuleMetadata)({ storyFnAngular, component, targetSelector }, newStoryProps$);
88
75
  if (!this.fullRendererRequired({
89
76
  storyFnAngular,
90
- moduleMetadata,
77
+ moduleMetadata: {
78
+ ...storyFnAngular.moduleMetadata,
79
+ },
91
80
  forced,
92
81
  })) {
93
82
  this.storyProps$.next(storyFnAngular.props);
@@ -100,7 +89,20 @@ class AbstractRenderer {
100
89
  }
101
90
  this.storyProps$ = newStoryProps$;
102
91
  this.initAngularRootElement(targetDOMNode, targetSelector);
103
- await getPlatform().bootstrapModule((0, StorybookModule_1.createStorybookModule)(moduleMetadata), parameters.bootstrapModuleOptions ?? undefined);
92
+ const analyzedMetadata = new PropertyExtractor_1.PropertyExtractor(storyFnAngular.moduleMetadata, component);
93
+ const providers = [
94
+ // Providers for BrowserAnimations & NoopAnimationsModule
95
+ analyzedMetadata.singletons,
96
+ (0, core_1.importProvidersFrom)(...analyzedMetadata.imports.filter((imported) => {
97
+ const { isStandalone } = PropertyExtractor_1.PropertyExtractor.analyzeDecorators(imported);
98
+ return !isStandalone;
99
+ })),
100
+ analyzedMetadata.providers,
101
+ (0, StorybookProvider_1.storyPropsProvider)(newStoryProps$),
102
+ ].filter(Boolean);
103
+ const application = (0, StorybookModule_1.getApplication)({ storyFnAngular, component, targetSelector });
104
+ const applicationRef = await (0, platform_browser_1.bootstrapApplication)(application, { providers });
105
+ applicationRefs.add(applicationRef);
104
106
  await this.afterFullRender();
105
107
  }
106
108
  /**
@@ -115,12 +117,10 @@ class AbstractRenderer {
115
117
  * @protected
116
118
  * @memberof AbstractRenderer
117
119
  */
118
- generateTargetSelectorFromStoryId() {
120
+ generateTargetSelectorFromStoryId(id) {
119
121
  const invalidHtmlTag = /[^A-Za-z0-9-]/g;
120
- const storyIdIsInvalidHtmlTagName = invalidHtmlTag.test(this.storyId);
121
- return storyIdIsInvalidHtmlTagName
122
- ? `sb-${this.storyId.replace(invalidHtmlTag, '')}-component`
123
- : this.storyId;
122
+ const storyIdIsInvalidHtmlTagName = invalidHtmlTag.test(id);
123
+ return storyIdIsInvalidHtmlTagName ? `sb-${id.replace(invalidHtmlTag, '')}-component` : id;
124
124
  }
125
125
  initAngularRootElement(targetDOMNode, targetSelector) {
126
126
  // Adds DOM element that angular will use as bootstrap component
@@ -7,7 +7,7 @@ class CanvasRenderer extends AbstractRenderer_1.AbstractRenderer {
7
7
  await super.render(options);
8
8
  }
9
9
  async beforeFullRender() {
10
- await CanvasRenderer.resetPlatformBrowserDynamic();
10
+ CanvasRenderer.resetApplications();
11
11
  }
12
12
  async afterFullRender() {
13
13
  await AbstractRenderer_1.AbstractRenderer.resetCompiledComponents();
@@ -18,7 +18,7 @@ class DocsRenderer extends AbstractRenderer_1.AbstractRenderer {
18
18
  *
19
19
  */
20
20
  channel.once(core_events_1.STORY_CHANGED, async () => {
21
- await DocsRenderer.resetPlatformBrowserDynamic();
21
+ await DocsRenderer.resetApplications();
22
22
  });
23
23
  /**
24
24
  * Destroy and recreate the PlatformBrowserDynamic of angular
@@ -26,11 +26,13 @@ class DocsRenderer extends AbstractRenderer_1.AbstractRenderer {
26
26
  * for previous component
27
27
  */
28
28
  channel.once(core_events_1.DOCS_RENDERED, async () => {
29
- await DocsRenderer.resetPlatformBrowserDynamic();
29
+ await DocsRenderer.resetApplications();
30
30
  });
31
31
  await super.render({ ...options, forced: false });
32
32
  }
33
- async beforeFullRender() { }
33
+ async beforeFullRender() {
34
+ DocsRenderer.resetApplications();
35
+ }
34
36
  async afterFullRender() {
35
37
  await AbstractRenderer_1.AbstractRenderer.resetCompiledComponents();
36
38
  }
@@ -9,6 +9,7 @@ class RendererFactory {
9
9
  this.rendererMap = new Map();
10
10
  }
11
11
  async getRendererInstance(storyId, targetDOMNode) {
12
+ const targetId = targetDOMNode.id;
12
13
  // do nothing if the target node is null
13
14
  // fix a problem when the docs asks 2 times the same component at the same time
14
15
  // the 1st targetDOMNode of the 1st requested rendering becomes null 🤷‍♂️
@@ -18,15 +19,15 @@ class RendererFactory {
18
19
  const renderType = (0, exports.getRenderType)(targetDOMNode);
19
20
  // keep only instances of the same type
20
21
  if (this.lastRenderType && this.lastRenderType !== renderType) {
21
- await AbstractRenderer_1.AbstractRenderer.resetPlatformBrowserDynamic();
22
+ await AbstractRenderer_1.AbstractRenderer.resetApplications();
22
23
  clearRootHTMLElement(renderType);
23
24
  this.rendererMap.clear();
24
25
  }
25
- if (!this.rendererMap.has(storyId)) {
26
- this.rendererMap.set(storyId, this.buildRenderer(storyId, renderType));
26
+ if (!this.rendererMap.has(targetId)) {
27
+ this.rendererMap.set(targetId, this.buildRenderer(storyId, renderType));
27
28
  }
28
29
  this.lastRenderType = renderType;
29
- return this.rendererMap.get(storyId);
30
+ return this.rendererMap.get(targetId);
30
31
  }
31
32
  buildRenderer(storyId, renderType) {
32
33
  if (renderType === 'docs') {
@@ -1,9 +1,6 @@
1
- import { Type, NgModule } from '@angular/core';
2
- import { Subject } from 'rxjs';
3
- import { ICollection, StoryFnAngularReturnType } from '../types';
4
- export declare const getStorybookModuleMetadata: ({ storyFnAngular, component, targetSelector, }: {
1
+ import { StoryFnAngularReturnType } from '../types';
2
+ export declare const getApplication: ({ storyFnAngular, component, targetSelector, }: {
5
3
  storyFnAngular: StoryFnAngularReturnType;
6
4
  component?: any;
7
5
  targetSelector: string;
8
- }, storyProps$: Subject<ICollection>) => NgModule;
9
- export declare const createStorybookModule: (ngModule: NgModule) => Type<unknown>;
6
+ }) => import("@angular/core").Type<any>;
@@ -1,20 +1,9 @@
1
1
  "use strict";
2
- var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
3
- var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
4
- if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
5
- else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
6
- return c > 3 && r && Object.defineProperty(target, key, r), r;
7
- };
8
2
  Object.defineProperty(exports, "__esModule", { value: true });
9
- exports.createStorybookModule = exports.getStorybookModuleMetadata = void 0;
10
- const core_1 = require("@angular/core");
11
- const platform_browser_1 = require("@angular/platform-browser");
12
- const StorybookProvider_1 = require("./StorybookProvider");
13
- const NgModulesAnalyzer_1 = require("./utils/NgModulesAnalyzer");
14
- const NgComponentAnalyzer_1 = require("./utils/NgComponentAnalyzer");
3
+ exports.getApplication = void 0;
15
4
  const StorybookWrapperComponent_1 = require("./StorybookWrapperComponent");
16
5
  const ComputesTemplateFromComponent_1 = require("./ComputesTemplateFromComponent");
17
- const getStorybookModuleMetadata = ({ storyFnAngular, component, targetSelector, }, storyProps$) => {
6
+ const getApplication = ({ storyFnAngular, component, targetSelector, }) => {
18
7
  const { props, styles, moduleMetadata = {} } = storyFnAngular;
19
8
  let { template } = storyFnAngular;
20
9
  const hasTemplate = !hasNoTemplate(template);
@@ -24,39 +13,9 @@ const getStorybookModuleMetadata = ({ storyFnAngular, component, targetSelector,
24
13
  /**
25
14
  * Create a component that wraps generated template and gives it props
26
15
  */
27
- const ComponentToInject = (0, StorybookWrapperComponent_1.createStorybookWrapperComponent)(targetSelector, template, component, styles, props);
28
- const isStandalone = (0, NgComponentAnalyzer_1.isStandaloneComponent)(component);
29
- // Look recursively (deep) if the component is not already declared by an import module
30
- const requiresComponentDeclaration = (0, NgComponentAnalyzer_1.isDeclarable)(component) &&
31
- !(0, NgModulesAnalyzer_1.isComponentAlreadyDeclaredInModules)(component, moduleMetadata.declarations, moduleMetadata.imports) &&
32
- !isStandalone;
33
- return {
34
- declarations: [
35
- ...(requiresComponentDeclaration ? [component] : []),
36
- ComponentToInject,
37
- ...(moduleMetadata.declarations ?? []),
38
- ],
39
- imports: [
40
- platform_browser_1.BrowserModule,
41
- ...(isStandalone ? [component] : []),
42
- ...(moduleMetadata.imports ?? []),
43
- ],
44
- providers: [(0, StorybookProvider_1.storyPropsProvider)(storyProps$), ...(moduleMetadata.providers ?? [])],
45
- entryComponents: [...(moduleMetadata.entryComponents ?? [])],
46
- schemas: [...(moduleMetadata.schemas ?? [])],
47
- bootstrap: [ComponentToInject],
48
- };
49
- };
50
- exports.getStorybookModuleMetadata = getStorybookModuleMetadata;
51
- const createStorybookModule = (ngModule) => {
52
- let StorybookModule = class StorybookModule {
53
- };
54
- StorybookModule = __decorate([
55
- (0, core_1.NgModule)(ngModule)
56
- ], StorybookModule);
57
- return StorybookModule;
16
+ return (0, StorybookWrapperComponent_1.createStorybookWrapperComponent)(targetSelector, template, component, styles, moduleMetadata, props);
58
17
  };
59
- exports.createStorybookModule = createStorybookModule;
18
+ exports.getApplication = getApplication;
60
19
  function hasNoTemplate(template) {
61
20
  return template === null || template === undefined;
62
21
  }
@@ -11,9 +11,9 @@ var __metadata = (this && this.__metadata) || function (k, v) {
11
11
  Object.defineProperty(exports, "__esModule", { value: true });
12
12
  const core_1 = require("@angular/core");
13
13
  const testing_1 = require("@angular/core/testing");
14
- const platform_browser_1 = require("@angular/platform-browser");
15
14
  const rxjs_1 = require("rxjs");
16
15
  const StorybookModule_1 = require("./StorybookModule");
16
+ const StorybookProvider_1 = require("./StorybookProvider");
17
17
  describe('StorybookModule', () => {
18
18
  describe('getStorybookModuleMetadata', () => {
19
19
  describe('with simple component', () => {
@@ -70,12 +70,15 @@ describe('StorybookModule', () => {
70
70
  localProperty: 'localProperty',
71
71
  localFunction: () => 'localFunction',
72
72
  };
73
- const ngModule = (0, StorybookModule_1.getStorybookModuleMetadata)({
73
+ const application = (0, StorybookModule_1.getApplication)({
74
74
  storyFnAngular: { props },
75
75
  component: FooComponent,
76
76
  targetSelector: 'my-selector',
77
- }, new rxjs_1.BehaviorSubject(props));
78
- const { fixture } = await configureTestingModule(ngModule);
77
+ });
78
+ const { fixture } = await configureTestingModule({
79
+ imports: [application],
80
+ providers: [(0, StorybookProvider_1.storyPropsProvider)(new rxjs_1.BehaviorSubject(props))],
81
+ });
79
82
  fixture.detectChanges();
80
83
  expect(fixture.nativeElement.querySelector('p#input').innerHTML).toEqual(props.input);
81
84
  expect(fixture.nativeElement.querySelector('p#inputBindingPropertyName').innerHTML).toEqual(props.inputBindingPropertyName);
@@ -93,12 +96,15 @@ describe('StorybookModule', () => {
93
96
  expectedOutputBindingValue = value;
94
97
  },
95
98
  };
96
- const ngModule = (0, StorybookModule_1.getStorybookModuleMetadata)({
99
+ const application = (0, StorybookModule_1.getApplication)({
97
100
  storyFnAngular: { props },
98
101
  component: FooComponent,
99
102
  targetSelector: 'my-selector',
100
- }, new rxjs_1.BehaviorSubject(props));
101
- const { fixture } = await configureTestingModule(ngModule);
103
+ });
104
+ const { fixture } = await configureTestingModule({
105
+ imports: [application],
106
+ providers: [(0, StorybookProvider_1.storyPropsProvider)(new rxjs_1.BehaviorSubject(props))],
107
+ });
102
108
  fixture.detectChanges();
103
109
  fixture.nativeElement.querySelector('p#output').click();
104
110
  fixture.nativeElement.querySelector('p#outputBindingPropertyName').click();
@@ -111,12 +117,15 @@ describe('StorybookModule', () => {
111
117
  inputBindingPropertyName: '',
112
118
  };
113
119
  const storyProps$ = new rxjs_1.BehaviorSubject(initialProps);
114
- const ngModule = (0, StorybookModule_1.getStorybookModuleMetadata)({
120
+ const application = (0, StorybookModule_1.getApplication)({
115
121
  storyFnAngular: { props: initialProps },
116
122
  component: FooComponent,
117
123
  targetSelector: 'my-selector',
118
- }, storyProps$);
119
- const { fixture } = await configureTestingModule(ngModule);
124
+ });
125
+ const { fixture } = await configureTestingModule({
126
+ imports: [application],
127
+ providers: [(0, StorybookProvider_1.storyPropsProvider)(storyProps$)],
128
+ });
120
129
  fixture.detectChanges();
121
130
  expect(fixture.nativeElement.querySelector('p#input').innerHTML).toEqual(initialProps.input);
122
131
  expect(fixture.nativeElement.querySelector('p#inputBindingPropertyName').innerHTML).toEqual('');
@@ -146,12 +155,15 @@ describe('StorybookModule', () => {
146
155
  },
147
156
  };
148
157
  const storyProps$ = new rxjs_1.BehaviorSubject(initialProps);
149
- const ngModule = (0, StorybookModule_1.getStorybookModuleMetadata)({
158
+ const application = (0, StorybookModule_1.getApplication)({
150
159
  storyFnAngular: { props: initialProps },
151
160
  component: FooComponent,
152
161
  targetSelector: 'my-selector',
153
- }, storyProps$);
154
- const { fixture } = await configureTestingModule(ngModule);
162
+ });
163
+ const { fixture } = await configureTestingModule({
164
+ imports: [application],
165
+ providers: [(0, StorybookProvider_1.storyPropsProvider)(storyProps$)],
166
+ });
155
167
  fixture.detectChanges();
156
168
  const newProps = {
157
169
  input: 'new input',
@@ -176,15 +188,18 @@ describe('StorybookModule', () => {
176
188
  input: 'input',
177
189
  };
178
190
  const storyProps$ = new rxjs_1.BehaviorSubject(initialProps);
179
- const ngModule = (0, StorybookModule_1.getStorybookModuleMetadata)({
191
+ const application = (0, StorybookModule_1.getApplication)({
180
192
  storyFnAngular: {
181
193
  props: initialProps,
182
194
  template: '<p [style.color]="color"><foo [input]="input"></foo></p>',
183
195
  },
184
196
  component: FooComponent,
185
197
  targetSelector: 'my-selector',
186
- }, storyProps$);
187
- const { fixture } = await configureTestingModule(ngModule);
198
+ });
199
+ const { fixture } = await configureTestingModule({
200
+ imports: [application],
201
+ providers: [(0, StorybookProvider_1.storyPropsProvider)(storyProps$)],
202
+ });
188
203
  fixture.detectChanges();
189
204
  expect(fixture.nativeElement.querySelector('p').style.color).toEqual('red');
190
205
  expect(fixture.nativeElement.querySelector('p#input').innerHTML).toEqual(initialProps.input);
@@ -202,12 +217,15 @@ describe('StorybookModule', () => {
202
217
  setter: 'init',
203
218
  };
204
219
  const storyProps$ = new rxjs_1.BehaviorSubject(initialProps);
205
- const ngModule = (0, StorybookModule_1.getStorybookModuleMetadata)({
220
+ const application = (0, StorybookModule_1.getApplication)({
206
221
  storyFnAngular: { props: initialProps },
207
222
  component: FooComponent,
208
223
  targetSelector: 'my-selector',
209
- }, storyProps$);
210
- const { fixture } = await configureTestingModule(ngModule);
224
+ });
225
+ const { fixture } = await configureTestingModule({
226
+ imports: [application],
227
+ providers: [(0, StorybookProvider_1.storyPropsProvider)(storyProps$)],
228
+ });
211
229
  fixture.detectChanges();
212
230
  expect(fixture.nativeElement.querySelector('p#setterCallNb').innerHTML).toEqual('1');
213
231
  const newProps = {
@@ -228,15 +246,18 @@ describe('StorybookModule', () => {
228
246
  ], WithoutSelectorComponent);
229
247
  it('should display the component', async () => {
230
248
  const props = {};
231
- const ngModule = (0, StorybookModule_1.getStorybookModuleMetadata)({
249
+ const application = (0, StorybookModule_1.getApplication)({
232
250
  storyFnAngular: {
233
251
  props,
234
252
  moduleMetadata: { entryComponents: [WithoutSelectorComponent] },
235
253
  },
236
254
  component: WithoutSelectorComponent,
237
255
  targetSelector: 'my-selector',
238
- }, new rxjs_1.BehaviorSubject(props));
239
- const { fixture } = await configureTestingModule(ngModule);
256
+ });
257
+ const { fixture } = await configureTestingModule({
258
+ imports: [application],
259
+ providers: [(0, StorybookProvider_1.storyPropsProvider)(new rxjs_1.BehaviorSubject(props))],
260
+ });
240
261
  fixture.detectChanges();
241
262
  expect(fixture.nativeElement.innerHTML).toContain('The content');
242
263
  });
@@ -250,28 +271,22 @@ describe('StorybookModule', () => {
250
271
  template: `Should not be displayed`,
251
272
  })
252
273
  ], FooComponent);
253
- const ngModule = (0, StorybookModule_1.getStorybookModuleMetadata)({
274
+ const application = (0, StorybookModule_1.getApplication)({
254
275
  storyFnAngular: { template: '' },
255
276
  component: FooComponent,
256
277
  targetSelector: 'my-selector',
257
- }, new rxjs_1.BehaviorSubject({}));
258
- const { fixture } = await configureTestingModule(ngModule);
278
+ });
279
+ const { fixture } = await configureTestingModule({
280
+ imports: [application],
281
+ providers: [(0, StorybookProvider_1.storyPropsProvider)(new rxjs_1.BehaviorSubject({}))],
282
+ });
259
283
  fixture.detectChanges();
260
284
  expect(fixture.nativeElement.innerHTML).toEqual('');
261
285
  });
262
286
  });
263
287
  async function configureTestingModule(ngModule) {
264
- await testing_1.TestBed.configureTestingModule({
265
- declarations: ngModule.declarations,
266
- providers: ngModule.providers,
267
- })
268
- .overrideModule(platform_browser_1.BrowserModule, {
269
- set: {
270
- entryComponents: [...ngModule.entryComponents],
271
- },
272
- })
273
- .compileComponents();
274
- const fixture = testing_1.TestBed.createComponent(ngModule.bootstrap[0]);
288
+ await testing_1.TestBed.configureTestingModule(ngModule).compileComponents();
289
+ const fixture = testing_1.TestBed.createComponent(ngModule.imports[0]);
275
290
  return {
276
291
  fixture,
277
292
  };
@@ -1,9 +1,10 @@
1
1
  import { Type } from '@angular/core';
2
- import { ICollection } from '../types';
2
+ import { ICollection, NgModuleMetadata } from '../types';
3
+ export declare const componentNgModules: Map<any, Type<any>>;
3
4
  /**
4
5
  * Wraps the story template into a component
5
6
  *
6
7
  * @param storyComponent
7
8
  * @param initialProps
8
9
  */
9
- export declare const createStorybookWrapperComponent: (selector: string, template: string, storyComponent: Type<unknown> | undefined, styles: string[], initialProps?: ICollection) => Type<any>;
10
+ export declare const createStorybookWrapperComponent: (selector: string, template: string, storyComponent: Type<unknown> | undefined, styles: string[], moduleMetadata: NgModuleMetadata, initialProps?: ICollection) => Type<any>;
@@ -12,12 +12,13 @@ var __param = (this && this.__param) || function (paramIndex, decorator) {
12
12
  return function (target, key) { decorator(target, key, paramIndex); }
13
13
  };
14
14
  Object.defineProperty(exports, "__esModule", { value: true });
15
- exports.createStorybookWrapperComponent = void 0;
15
+ exports.createStorybookWrapperComponent = exports.componentNgModules = void 0;
16
16
  const core_1 = require("@angular/core");
17
17
  const rxjs_1 = require("rxjs");
18
18
  const operators_1 = require("rxjs/operators");
19
19
  const StorybookProvider_1 = require("./StorybookProvider");
20
20
  const NgComponentAnalyzer_1 = require("./utils/NgComponentAnalyzer");
21
+ const PropertyExtractor_1 = require("./utils/PropertyExtractor");
21
22
  const getNonInputsOutputsProps = (ngComponentInputsOutputs, props = {}) => {
22
23
  const inputs = ngComponentInputsOutputs.inputs
23
24
  .filter((i) => i.templateName in props)
@@ -27,16 +28,38 @@ const getNonInputsOutputsProps = (ngComponentInputsOutputs, props = {}) => {
27
28
  .map((o) => o.templateName);
28
29
  return Object.keys(props).filter((k) => ![...inputs, ...outputs].includes(k));
29
30
  };
31
+ // component modules cache
32
+ exports.componentNgModules = new Map();
30
33
  /**
31
34
  * Wraps the story template into a component
32
35
  *
33
36
  * @param storyComponent
34
37
  * @param initialProps
35
38
  */
36
- const createStorybookWrapperComponent = (selector, template, storyComponent, styles, initialProps) => {
39
+ const createStorybookWrapperComponent = (selector, template, storyComponent, styles, moduleMetadata, initialProps) => {
37
40
  // In ivy, a '' selector is not allowed, therefore we need to just set it to anything if
38
41
  // storyComponent was not provided.
39
42
  const viewChildSelector = storyComponent ?? '__storybook-noop';
43
+ const analyzedMetadata = new PropertyExtractor_1.PropertyExtractor(moduleMetadata, storyComponent);
44
+ const { imports, declarations, providers } = analyzedMetadata;
45
+ // Only create a new module if it doesn't already exist
46
+ // This is to prevent the module from being recreated on every story change
47
+ // Declarations & Imports are only added once
48
+ // Providers are added on every story change to allow for story-specific providers
49
+ let ngModule = exports.componentNgModules.get(storyComponent);
50
+ if (!ngModule) {
51
+ let StorybookComponentModule = class StorybookComponentModule {
52
+ };
53
+ StorybookComponentModule = __decorate([
54
+ (0, core_1.NgModule)({
55
+ declarations,
56
+ imports,
57
+ exports: [...declarations, ...imports],
58
+ })
59
+ ], StorybookComponentModule);
60
+ exports.componentNgModules.set(storyComponent, StorybookComponentModule);
61
+ ngModule = exports.componentNgModules.get(storyComponent);
62
+ }
40
63
  let StorybookWrapperComponent = class StorybookWrapperComponent {
41
64
  constructor(storyProps$, changeDetectorRef) {
42
65
  this.storyProps$ = storyProps$;
@@ -104,9 +127,14 @@ const createStorybookWrapperComponent = (selector, template, storyComponent, sty
104
127
  (0, core_1.Component)({
105
128
  selector,
106
129
  template,
130
+ standalone: true,
131
+ imports: [ngModule],
132
+ providers,
107
133
  styles,
134
+ schemas: moduleMetadata.schemas,
108
135
  }),
109
136
  __param(0, (0, core_1.Inject)(StorybookProvider_1.STORY_PROPS)),
137
+ __param(1, (0, core_1.Inject)(core_1.ChangeDetectorRef)),
110
138
  __metadata("design:paramtypes", [rxjs_1.Subject,
111
139
  core_1.ChangeDetectorRef])
112
140
  ], StorybookWrapperComponent);
@@ -0,0 +1,2 @@
1
+ export declare class WithOfficialModule {
2
+ }
@@ -0,0 +1,20 @@
1
+ "use strict";
2
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
3
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
4
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
5
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
6
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
7
+ };
8
+ Object.defineProperty(exports, "__esModule", { value: true });
9
+ exports.WithOfficialModule = void 0;
10
+ const common_1 = require("@angular/common");
11
+ const http_1 = require("@angular/common/http");
12
+ const core_1 = require("@angular/core");
13
+ let WithOfficialModule = class WithOfficialModule {
14
+ };
15
+ WithOfficialModule = __decorate([
16
+ (0, core_1.NgModule)({
17
+ imports: [common_1.CommonModule, http_1.HttpClientModule],
18
+ })
19
+ ], WithOfficialModule);
20
+ exports.WithOfficialModule = WithOfficialModule;
@@ -76,7 +76,7 @@ const isStandaloneComponent = (component) => {
76
76
  const decorators = reflectionCapabilities.annotations(component);
77
77
  // TODO: `standalone` is only available in Angular v14. Remove cast to `any` once
78
78
  // Angular deps are updated to v14.x.x.
79
- return (decorators || []).some((d) => d instanceof core_1.Component && d.standalone);
79
+ return (decorators || []).some((d) => (d instanceof core_1.Component || d instanceof core_1.Directive || d instanceof core_1.Pipe) && d.standalone);
80
80
  };
81
81
  exports.isStandaloneComponent = isStandaloneComponent;
82
82
  /**
@@ -252,8 +252,6 @@ describe('isComponent', () => {
252
252
  });
253
253
  describe('isStandaloneComponent', () => {
254
254
  it('should return true with a Component with "standalone: true"', () => {
255
- // TODO: `standalone` is only available in Angular v14. Remove cast to `any` once
256
- // Angular deps are updated to v14.x.x.
257
255
  let FooComponent = class FooComponent {
258
256
  };
259
257
  FooComponent = __decorate([
@@ -262,8 +260,6 @@ describe('isStandaloneComponent', () => {
262
260
  expect((0, NgComponentAnalyzer_1.isStandaloneComponent)(FooComponent)).toEqual(true);
263
261
  });
264
262
  it('should return false with a Component with "standalone: false"', () => {
265
- // TODO: `standalone` is only available in Angular v14. Remove cast to `any` once
266
- // Angular deps are updated to v14.x.x.
267
263
  let FooComponent = class FooComponent {
268
264
  };
269
265
  FooComponent = __decorate([
@@ -284,7 +280,23 @@ describe('isStandaloneComponent', () => {
284
280
  }
285
281
  expect((0, NgComponentAnalyzer_1.isStandaloneComponent)(FooPipe)).toEqual(false);
286
282
  });
287
- it('should return false with Directive', () => {
283
+ it('should return true with a Directive with "standalone: true"', () => {
284
+ let FooDirective = class FooDirective {
285
+ };
286
+ FooDirective = __decorate([
287
+ (0, core_1.Directive)({ standalone: true })
288
+ ], FooDirective);
289
+ expect((0, NgComponentAnalyzer_1.isStandaloneComponent)(FooDirective)).toEqual(true);
290
+ });
291
+ it('should return false with a Directive with "standalone: false"', () => {
292
+ let FooDirective = class FooDirective {
293
+ };
294
+ FooDirective = __decorate([
295
+ (0, core_1.Directive)({ standalone: false })
296
+ ], FooDirective);
297
+ expect((0, NgComponentAnalyzer_1.isStandaloneComponent)(FooDirective)).toEqual(false);
298
+ });
299
+ it('should return false with Directive without the "standalone" property', () => {
288
300
  let FooDirective = class FooDirective {
289
301
  };
290
302
  FooDirective = __decorate([
@@ -292,6 +304,32 @@ describe('isStandaloneComponent', () => {
292
304
  ], FooDirective);
293
305
  expect((0, NgComponentAnalyzer_1.isStandaloneComponent)(FooDirective)).toEqual(false);
294
306
  });
307
+ it('should return true with a Pipe with "standalone: true"', () => {
308
+ let FooPipe = class FooPipe {
309
+ };
310
+ FooPipe = __decorate([
311
+ (0, core_1.Pipe)({ name: 'FooPipe', standalone: true })
312
+ ], FooPipe);
313
+ expect((0, NgComponentAnalyzer_1.isStandaloneComponent)(FooPipe)).toEqual(true);
314
+ });
315
+ it('should return false with a Pipe with "standalone: false"', () => {
316
+ let FooPipe = class FooPipe {
317
+ };
318
+ FooPipe = __decorate([
319
+ (0, core_1.Pipe)({ name: 'FooPipe', standalone: false })
320
+ ], FooPipe);
321
+ expect((0, NgComponentAnalyzer_1.isStandaloneComponent)(FooPipe)).toEqual(false);
322
+ });
323
+ it('should return false with Pipe without the "standalone" property', () => {
324
+ let FooPipe = class FooPipe {
325
+ };
326
+ FooPipe = __decorate([
327
+ (0, core_1.Pipe)({
328
+ name: 'fooPipe',
329
+ })
330
+ ], FooPipe);
331
+ expect((0, NgComponentAnalyzer_1.isStandaloneComponent)(FooPipe)).toEqual(false);
332
+ });
295
333
  });
296
334
  describe('getComponentDecoratorMetadata', () => {
297
335
  it('should return Component with a Component', () => {
@@ -3,4 +3,4 @@
3
3
  *
4
4
  * Checks recursively if the component has already been declared in all import Module
5
5
  */
6
- export declare const isComponentAlreadyDeclaredInModules: (componentToFind: any, moduleDeclarations: any[], moduleImports: any[]) => boolean;
6
+ export declare const isComponentAlreadyDeclared: (componentToFind: any, moduleDeclarations: any[], moduleImports: any[]) => boolean;