@storybook/angular 7.5.0-alpha.4 → 7.5.0-alpha.6

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.
@@ -23,7 +23,7 @@ const commandBuilder = (options, context) => {
23
23
  outputDir: 'SBCONFIG_OUTPUT_DIR',
24
24
  configDir: 'SBCONFIG_CONFIG_DIR',
25
25
  });
26
- const { browserTarget, stylePreprocessorOptions, styles, configDir, docs, loglevel, outputDir, quiet, enableProdMode = true, webpackStatsJson, disableTelemetry, assets, } = options;
26
+ const { browserTarget, stylePreprocessorOptions, styles, configDir, docs, loglevel, outputDir, quiet, enableProdMode = true, webpackStatsJson, debugWebpack, disableTelemetry, assets, previewUrl, } = options;
27
27
  const standaloneOptions = {
28
28
  packageJson: (0, read_pkg_up_1.sync)({ cwd: __dirname }).packageJson,
29
29
  configDir,
@@ -42,6 +42,8 @@ const commandBuilder = (options, context) => {
42
42
  },
43
43
  tsConfig,
44
44
  webpackStatsJson,
45
+ debugWebpack,
46
+ previewUrl,
45
47
  };
46
48
  return standaloneOptions;
47
49
  }), (0, operators_1.switchMap)((standaloneOptions) => runInstance({ ...standaloneOptions, mode: 'static' })), (0, operators_1.map)(() => {
@@ -29,6 +29,11 @@
29
29
  "description": "Controls level of logging during build. Can be one of: [silly, verbose, info (default), warn, error, silent].",
30
30
  "pattern": "(silly|verbose|info|warn|silent)"
31
31
  },
32
+ "debugWebpack": {
33
+ "type": "boolean",
34
+ "description": "Debug the Webpack configuration",
35
+ "default": false
36
+ },
32
37
  "enableProdMode": {
33
38
  "type": "boolean",
34
39
  "description": "Disable Angular's development mode, which turns off assertions and other checks within the framework.",
@@ -62,6 +67,10 @@
62
67
  "description": "Write Webpack Stats JSON to disk",
63
68
  "default": false
64
69
  },
70
+ "previewUrl": {
71
+ "type": "string",
72
+ "description": "Disables the default storybook preview and lets you use your own"
73
+ },
65
74
  "styles": {
66
75
  "type": "array",
67
76
  "description": "Global styles to be included in the build.",
@@ -30,7 +30,7 @@ const commandBuilder = (options, context) => {
30
30
  });
31
31
  // eslint-disable-next-line no-param-reassign
32
32
  options.port = parseInt(`${options.port}`, 10);
33
- const { browserTarget, stylePreprocessorOptions, styles, ci, configDir, docs, host, https, port, quiet, enableProdMode = false, smokeTest, sslCa, sslCert, sslKey, disableTelemetry, assets, initialPath, open, } = options;
33
+ const { browserTarget, stylePreprocessorOptions, styles, ci, configDir, docs, host, https, port, quiet, enableProdMode = false, smokeTest, sslCa, sslCert, sslKey, disableTelemetry, assets, initialPath, open, debugWebpack, loglevel, webpackStatsJson, previewUrl, } = options;
34
34
  const standaloneOptions = {
35
35
  packageJson: (0, read_pkg_up_1.sync)({ cwd: __dirname }).packageJson,
36
36
  ci,
@@ -56,6 +56,10 @@ const commandBuilder = (options, context) => {
56
56
  tsConfig,
57
57
  initialPath,
58
58
  open,
59
+ debugWebpack,
60
+ loglevel,
61
+ webpackStatsJson,
62
+ previewUrl,
59
63
  };
60
64
  return standaloneOptions;
61
65
  }), (0, operators_1.switchMap)((standaloneOptions) => runInstance(standaloneOptions)), (0, operators_1.map)((port) => {
@@ -10,6 +10,11 @@
10
10
  "pattern": "^[^:\\s]+:[^:\\s]+(:[^\\s]+)?$",
11
11
  "default": null
12
12
  },
13
+ "debugWebpack": {
14
+ "type": "boolean",
15
+ "description": "Debug the Webpack configuration",
16
+ "default": false
17
+ },
13
18
  "tsConfig": {
14
19
  "type": "string",
15
20
  "description": "The full path for the TypeScript configuration file, relative to the current workspace."
@@ -123,6 +128,20 @@
123
128
  "initialPath": {
124
129
  "type": "string",
125
130
  "description": "URL path to be appended when visiting Storybook for the first time"
131
+ },
132
+ "webpackStatsJson": {
133
+ "type": "string",
134
+ "description": "Write Webpack Stats JSON to disk",
135
+ "default": false
136
+ },
137
+ "previewUrl": {
138
+ "type": "string",
139
+ "description": "Disables the default storybook preview and lets you use your own"
140
+ },
141
+ "loglevel": {
142
+ "type": "string",
143
+ "description": "Controls level of logging during build. Can be one of: [silly, verbose, info (default), warn, error, silent].",
144
+ "pattern": "(silly|verbose|info|warn|silent)"
126
145
  }
127
146
  },
128
147
  "additionalProperties": false,
@@ -0,0 +1,55 @@
1
+ /**
2
+ * Options for controlling the behavior of the argsToTemplate function.
3
+ *
4
+ * @template T The type of the keys in the target object.
5
+ */
6
+ export interface ArgsToTemplateOptions<T> {
7
+ /**
8
+ * An array of keys to specifically include in the output.
9
+ * If provided, only the keys from this array will be included in the output,
10
+ * irrespective of the `exclude` option. Undefined values will still be excluded from the output.
11
+ */
12
+ include?: Array<T>;
13
+ /**
14
+ * An array of keys to specifically exclude from the output.
15
+ * If provided, these keys will be omitted from the output. This option is
16
+ * ignored if the `include` option is also provided
17
+ */
18
+ exclude?: Array<T>;
19
+ }
20
+ /**
21
+ * Converts an object of arguments to a string of property and event bindings and excludes undefined values.
22
+ * Why? Because Angular treats undefined values in property bindings as an actual value
23
+ * and does not apply the default value of the property as soon as the binding is set.
24
+ * This feels counter-intuitive and is a common source of bugs in stories.
25
+ * @example
26
+ * ```ts
27
+ * // component.ts
28
+ *ㅤ@Component({ selector: 'example' })
29
+ * export class ExampleComponent {
30
+ * ㅤ@Input() input1: string = 'Default Input1';
31
+ * ㅤ@Input() input2: string = 'Default Input2';
32
+ * ㅤ@Output() click = new EventEmitter();
33
+ * }
34
+ *
35
+ * // component.stories.ts
36
+ * import { argsToTemplate } from '@storybook/angular';
37
+ * export const Input1: Story = {
38
+ * render: (args) => ({
39
+ * props: args,
40
+ * // Problem1: <example [input1]="input1" [input2]="input2" (click)="click($event)"></example>
41
+ * // This will set input2 to undefined and the internal default value will not be used.
42
+ * // Problem2: <example [input1]="input1" (click)="click($event)"></example>
43
+ * // The default value of input2 will be used, but it is not overridable by the user via controls.
44
+ * // Solution: Now the controls will be applicable to both input1 and input2, and the default values will be used if the user does not override them.
45
+ * template: `<example ${argsToTemplate(args)}"></example>`,
46
+ * }),
47
+ * args: {
48
+ * // In this Story, we want to set the input1 property, and the internal default property of input2 should be used.
49
+ * input1: 'Input 1',
50
+ * click: { action: 'clicked' },
51
+ * },
52
+ *};
53
+ * ```
54
+ */
55
+ export declare function argsToTemplate<A extends Record<string, any>>(args: A, options?: ArgsToTemplateOptions<keyof A>): string;
@@ -0,0 +1,54 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.argsToTemplate = void 0;
4
+ /**
5
+ * Converts an object of arguments to a string of property and event bindings and excludes undefined values.
6
+ * Why? Because Angular treats undefined values in property bindings as an actual value
7
+ * and does not apply the default value of the property as soon as the binding is set.
8
+ * This feels counter-intuitive and is a common source of bugs in stories.
9
+ * @example
10
+ * ```ts
11
+ * // component.ts
12
+ *ㅤ@Component({ selector: 'example' })
13
+ * export class ExampleComponent {
14
+ * ㅤ@Input() input1: string = 'Default Input1';
15
+ * ㅤ@Input() input2: string = 'Default Input2';
16
+ * ㅤ@Output() click = new EventEmitter();
17
+ * }
18
+ *
19
+ * // component.stories.ts
20
+ * import { argsToTemplate } from '@storybook/angular';
21
+ * export const Input1: Story = {
22
+ * render: (args) => ({
23
+ * props: args,
24
+ * // Problem1: <example [input1]="input1" [input2]="input2" (click)="click($event)"></example>
25
+ * // This will set input2 to undefined and the internal default value will not be used.
26
+ * // Problem2: <example [input1]="input1" (click)="click($event)"></example>
27
+ * // The default value of input2 will be used, but it is not overridable by the user via controls.
28
+ * // Solution: Now the controls will be applicable to both input1 and input2, and the default values will be used if the user does not override them.
29
+ * template: `<example ${argsToTemplate(args)}"></example>`,
30
+ * }),
31
+ * args: {
32
+ * // In this Story, we want to set the input1 property, and the internal default property of input2 should be used.
33
+ * input1: 'Input 1',
34
+ * click: { action: 'clicked' },
35
+ * },
36
+ *};
37
+ * ```
38
+ */
39
+ function argsToTemplate(args, options = {}) {
40
+ const includeSet = options.include ? new Set(options.include) : null;
41
+ const excludeSet = options.exclude ? new Set(options.exclude) : null;
42
+ return Object.entries(args)
43
+ .filter(([key]) => args[key] !== undefined)
44
+ .filter(([key]) => {
45
+ if (includeSet)
46
+ return includeSet.has(key);
47
+ if (excludeSet)
48
+ return !excludeSet.has(key);
49
+ return true;
50
+ })
51
+ .map(([key, value]) => typeof value === 'function' ? `(${key})="${key}($event)"` : `[${key}]="${key}"`)
52
+ .join(' ');
53
+ }
54
+ exports.argsToTemplate = argsToTemplate;
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,95 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const argsToTemplate_1 = require("./argsToTemplate"); // adjust path
4
+ describe('argsToTemplate', () => {
5
+ it('should correctly convert args to template string and exclude undefined values', () => {
6
+ const args = {
7
+ prop1: 'value1',
8
+ prop2: undefined,
9
+ prop3: 'value3',
10
+ };
11
+ const options = {};
12
+ const result = (0, argsToTemplate_1.argsToTemplate)(args, options);
13
+ expect(result).toBe('[prop1]="prop1" [prop3]="prop3"');
14
+ });
15
+ it('should include properties from include option', () => {
16
+ const args = {
17
+ prop1: 'value1',
18
+ prop2: 'value2',
19
+ prop3: 'value3',
20
+ };
21
+ const options = {
22
+ include: ['prop1', 'prop3'],
23
+ };
24
+ const result = (0, argsToTemplate_1.argsToTemplate)(args, options);
25
+ expect(result).toBe('[prop1]="prop1" [prop3]="prop3"');
26
+ });
27
+ it('should include non-undefined properties from include option', () => {
28
+ const args = {
29
+ prop1: 'value1',
30
+ prop2: 'value2',
31
+ prop3: undefined,
32
+ };
33
+ const options = {
34
+ include: ['prop1', 'prop3'],
35
+ };
36
+ const result = (0, argsToTemplate_1.argsToTemplate)(args, options);
37
+ expect(result).toBe('[prop1]="prop1"');
38
+ });
39
+ it('should exclude properties from exclude option', () => {
40
+ const args = {
41
+ prop1: 'value1',
42
+ prop2: 'value2',
43
+ prop3: 'value3',
44
+ };
45
+ const options = {
46
+ exclude: ['prop2'],
47
+ };
48
+ const result = (0, argsToTemplate_1.argsToTemplate)(args, options);
49
+ expect(result).toBe('[prop1]="prop1" [prop3]="prop3"');
50
+ });
51
+ it('should exclude properties from exclude option and undefined properties', () => {
52
+ const args = {
53
+ prop1: 'value1',
54
+ prop2: 'value2',
55
+ prop3: undefined,
56
+ };
57
+ const options = {
58
+ exclude: ['prop2'],
59
+ };
60
+ const result = (0, argsToTemplate_1.argsToTemplate)(args, options);
61
+ expect(result).toBe('[prop1]="prop1"');
62
+ });
63
+ it('should prioritize include over exclude when both options are given', () => {
64
+ const args = {
65
+ prop1: 'value1',
66
+ prop2: 'value2',
67
+ prop3: 'value3',
68
+ };
69
+ const options = {
70
+ include: ['prop1', 'prop2'],
71
+ exclude: ['prop2', 'prop3'],
72
+ };
73
+ const result = (0, argsToTemplate_1.argsToTemplate)(args, options);
74
+ expect(result).toBe('[prop1]="prop1" [prop2]="prop2"');
75
+ });
76
+ it('should work when neither include nor exclude options are given', () => {
77
+ const args = {
78
+ prop1: 'value1',
79
+ prop2: 'value2',
80
+ };
81
+ const options = {};
82
+ const result = (0, argsToTemplate_1.argsToTemplate)(args, options);
83
+ expect(result).toBe('[prop1]="prop1" [prop2]="prop2"');
84
+ });
85
+ it('should bind events correctly when value is a function', () => {
86
+ const args = { event1: () => { }, event2: () => { } };
87
+ const result = (0, argsToTemplate_1.argsToTemplate)(args, {});
88
+ expect(result).toEqual('(event1)="event1($event)" (event2)="event2($event)"');
89
+ });
90
+ it('should mix properties and events correctly', () => {
91
+ const args = { input: 'Value1', event1: () => { } };
92
+ const result = (0, argsToTemplate_1.argsToTemplate)(args, {});
93
+ expect(result).toEqual('[input]="input" (event1)="event1($event)"');
94
+ });
95
+ });
@@ -20,4 +20,4 @@
20
20
  /** *************************************************************************************************
21
21
  * Zone JS is required by Angular itself.
22
22
  */
23
- import 'zone.js/dist/zone';
23
+ import 'zone.js';
@@ -24,7 +24,7 @@ const global_1 = require("@storybook/global");
24
24
  /** *************************************************************************************************
25
25
  * Zone JS is required by Angular itself.
26
26
  */
27
- require("zone.js/dist/zone"); // Included with Angular CLI.
27
+ require("zone.js"); // Included with Angular CLI.
28
28
  /** *************************************************************************************************
29
29
  * APPLICATION IMPORTS
30
30
  */
@@ -3,3 +3,4 @@ export * from './public-api';
3
3
  export * from './public-types';
4
4
  export type { StoryFnAngularReturnType as IStory } from './types';
5
5
  export { moduleMetadata, componentWrapperDecorator, applicationConfig } from './decorators';
6
+ export { argsToTemplate } from './argsToTemplate';
@@ -15,7 +15,7 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
15
15
  for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
16
16
  };
17
17
  Object.defineProperty(exports, "__esModule", { value: true });
18
- exports.applicationConfig = exports.componentWrapperDecorator = exports.moduleMetadata = void 0;
18
+ exports.argsToTemplate = exports.applicationConfig = exports.componentWrapperDecorator = exports.moduleMetadata = void 0;
19
19
  require("./globals");
20
20
  // eslint-disable-next-line import/export
21
21
  __exportStar(require("./public-api"), exports);
@@ -25,6 +25,8 @@ var decorators_1 = require("./decorators");
25
25
  Object.defineProperty(exports, "moduleMetadata", { enumerable: true, get: function () { return decorators_1.moduleMetadata; } });
26
26
  Object.defineProperty(exports, "componentWrapperDecorator", { enumerable: true, get: function () { return decorators_1.componentWrapperDecorator; } });
27
27
  Object.defineProperty(exports, "applicationConfig", { enumerable: true, get: function () { return decorators_1.applicationConfig; } });
28
+ var argsToTemplate_1 = require("./argsToTemplate");
29
+ Object.defineProperty(exports, "argsToTemplate", { enumerable: true, get: function () { return argsToTemplate_1.argsToTemplate; } });
28
30
  // optimization: stop HMR propagation in webpack
29
31
  if (typeof module !== 'undefined')
30
32
  module?.hot?.decline();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@storybook/angular",
3
- "version": "7.5.0-alpha.4",
3
+ "version": "7.5.0-alpha.6",
4
4
  "description": "Storybook for Angular: Develop Angular components in isolation with hot reloading.",
5
5
  "keywords": [
6
6
  "storybook",
@@ -37,21 +37,21 @@
37
37
  "prep": "../../../scripts/prepare/tsc.ts"
38
38
  },
39
39
  "dependencies": {
40
- "@storybook/builder-webpack5": "7.5.0-alpha.4",
41
- "@storybook/cli": "7.5.0-alpha.4",
42
- "@storybook/client-logger": "7.5.0-alpha.4",
43
- "@storybook/core-common": "7.5.0-alpha.4",
44
- "@storybook/core-events": "7.5.0-alpha.4",
45
- "@storybook/core-server": "7.5.0-alpha.4",
46
- "@storybook/core-webpack": "7.5.0-alpha.4",
47
- "@storybook/docs-tools": "7.5.0-alpha.4",
40
+ "@storybook/builder-webpack5": "7.5.0-alpha.6",
41
+ "@storybook/cli": "7.5.0-alpha.6",
42
+ "@storybook/client-logger": "7.5.0-alpha.6",
43
+ "@storybook/core-common": "7.5.0-alpha.6",
44
+ "@storybook/core-events": "7.5.0-alpha.6",
45
+ "@storybook/core-server": "7.5.0-alpha.6",
46
+ "@storybook/core-webpack": "7.5.0-alpha.6",
47
+ "@storybook/docs-tools": "7.5.0-alpha.6",
48
48
  "@storybook/global": "^5.0.0",
49
- "@storybook/manager-api": "7.5.0-alpha.4",
50
- "@storybook/node-logger": "7.5.0-alpha.4",
51
- "@storybook/preview-api": "7.5.0-alpha.4",
52
- "@storybook/telemetry": "7.5.0-alpha.4",
53
- "@storybook/types": "7.5.0-alpha.4",
54
- "@types/node": "^16.0.0",
49
+ "@storybook/manager-api": "7.5.0-alpha.6",
50
+ "@storybook/node-logger": "7.5.0-alpha.6",
51
+ "@storybook/preview-api": "7.5.0-alpha.6",
52
+ "@storybook/telemetry": "7.5.0-alpha.6",
53
+ "@storybook/types": "7.5.0-alpha.6",
54
+ "@types/node": "^18.0.0",
55
55
  "@types/react": "^16.14.34",
56
56
  "@types/react-dom": "^16.9.14",
57
57
  "@types/semver": "^7.3.4",
@@ -106,7 +106,7 @@
106
106
  "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0",
107
107
  "rxjs": "^6.0.0 || ^7.4.0",
108
108
  "typescript": "^4.0.0 || ^5.0.0",
109
- "zone.js": "^0.8.29 || >= 0.9.0 < 1.0.0"
109
+ "zone.js": ">= 0.11.1 < 1.0.0"
110
110
  },
111
111
  "peerDependenciesMeta": {
112
112
  "@angular/cli": {