@storybook/angular 8.3.0-alpha.2 → 8.3.0-alpha.4

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.
@@ -1,6 +1,11 @@
1
1
  import { Type } from '@angular/core';
2
2
  import { ArgTypes } from 'storybook/internal/types';
3
3
  import { ICollection } from '../types';
4
+ /**
5
+ * Returns the property name, if it can be accessed with dot notation. If not,
6
+ * it returns `this['propertyName']`.
7
+ */
8
+ export declare const formatPropInTemplate: (propertyName: string) => string;
4
9
  /**
5
10
  * Converts a component into a template with inputs/outputs present in initial props
6
11
  * @param component
@@ -1,7 +1,19 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.computesTemplateSourceFromComponent = exports.computesTemplateFromComponent = void 0;
3
+ exports.computesTemplateSourceFromComponent = exports.computesTemplateFromComponent = exports.formatPropInTemplate = void 0;
4
4
  const NgComponentAnalyzer_1 = require("./utils/NgComponentAnalyzer");
5
+ /**
6
+ * Check if the name matches the criteria for a valid identifier.
7
+ * A valid identifier can only contain letters, digits, underscores, or dollar signs.
8
+ * It cannot start with a digit.
9
+ */
10
+ const isValidIdentifier = (name) => /^[a-zA-Z_$][a-zA-Z0-9_$]*$/.test(name);
11
+ /**
12
+ * Returns the property name, if it can be accessed with dot notation. If not,
13
+ * it returns `this['propertyName']`.
14
+ */
15
+ const formatPropInTemplate = (propertyName) => isValidIdentifier(propertyName) ? propertyName : `this['${propertyName}']`;
16
+ exports.formatPropInTemplate = formatPropInTemplate;
5
17
  const separateInputsOutputsAttributes = (ngComponentInputsOutputs, props = {}) => {
6
18
  const inputs = ngComponentInputsOutputs.inputs
7
19
  .filter((i) => i.templateName in props)
@@ -29,13 +41,30 @@ const computesTemplateFromComponent = (component, initialProps, innerTemplate =
29
41
  return `<ng-container *ngComponentOutlet="storyComponent"></ng-container>`;
30
42
  }
31
43
  const { inputs: initialInputs, outputs: initialOutputs } = separateInputsOutputsAttributes(ngComponentInputsOutputs, initialProps);
32
- const templateInputs = initialInputs.length > 0 ? ` ${initialInputs.map((i) => `[${i}]="${i}"`).join(' ')}` : '';
44
+ const templateInputs = initialInputs.length > 0
45
+ ? ` ${initialInputs.map((i) => `[${i}]="${(0, exports.formatPropInTemplate)(i)}"`).join(' ')}`
46
+ : '';
33
47
  const templateOutputs = initialOutputs.length > 0
34
- ? ` ${initialOutputs.map((i) => `(${i})="${i}($event)"`).join(' ')}`
48
+ ? ` ${initialOutputs.map((i) => `(${i})="${(0, exports.formatPropInTemplate)(i)}($event)"`).join(' ')}`
35
49
  : '';
36
50
  return buildTemplate(ngComponentMetadata.selector, innerTemplate, templateInputs, templateOutputs);
37
51
  };
38
52
  exports.computesTemplateFromComponent = computesTemplateFromComponent;
53
+ /**
54
+ * Stringify an object with a placholder in the circular references.
55
+ */
56
+ function stringifyCircular(obj) {
57
+ const seen = new Set();
58
+ return JSON.stringify(obj, (key, value) => {
59
+ if (typeof value === 'object' && value !== null) {
60
+ if (seen.has(value)) {
61
+ return '[Circular]';
62
+ }
63
+ seen.add(value);
64
+ }
65
+ return value;
66
+ });
67
+ }
39
68
  const createAngularInputProperty = ({ propertyName, value, argType, }) => {
40
69
  let templateValue;
41
70
  switch (typeof value) {
@@ -43,7 +72,7 @@ const createAngularInputProperty = ({ propertyName, value, argType, }) => {
43
72
  templateValue = `'${value}'`;
44
73
  break;
45
74
  case 'object':
46
- templateValue = JSON.stringify(value)
75
+ templateValue = stringifyCircular(value)
47
76
  .replace(/'/g, '\u2019')
48
77
  .replace(/\\"/g, '\u201D')
49
78
  .replace(/"([^-"]+)":/g, '$1: ')
@@ -85,7 +114,7 @@ const computesTemplateSourceFromComponent = (component, initialProps, argTypes)
85
114
  .join(' ')}`
86
115
  : '';
87
116
  const templateOutputs = initialOutputs.length > 0
88
- ? ` ${initialOutputs.map((i) => `(${i})="${i}($event)"`).join(' ')}`
117
+ ? ` ${initialOutputs.map((i) => `(${i})="${(0, exports.formatPropInTemplate)(i)}($event)"`).join(' ')}`
89
118
  : '';
90
119
  return buildTemplate(ngComponentMetadata.selector, '', templateInputs, templateOutputs);
91
120
  };
@@ -10,8 +10,309 @@ const core_1 = require("@angular/core");
10
10
  const vitest_1 = require("vitest");
11
11
  const ComputesTemplateFromComponent_1 = require("./ComputesTemplateFromComponent");
12
12
  const input_component_1 = require("./__testfixtures__/input.component");
13
+ (0, vitest_1.describe)('angular template decorator', () => {
14
+ (0, vitest_1.it)('with props should generate tag with properties', () => {
15
+ const component = input_component_1.InputComponent;
16
+ const props = {
17
+ isDisabled: true,
18
+ label: 'Hello world',
19
+ accent: input_component_1.ButtonAccent.High,
20
+ counter: 4,
21
+ 'aria-label': 'Hello world',
22
+ };
23
+ const source = (0, ComputesTemplateFromComponent_1.computesTemplateFromComponent)(component, props);
24
+ (0, vitest_1.expect)(source).toEqual(`<doc-button [counter]="counter" [accent]="accent" [isDisabled]="isDisabled" [label]="label" [aria-label]="this['aria-label']"></doc-button>`);
25
+ });
26
+ (0, vitest_1.it)('with props should generate tag with outputs', () => {
27
+ const component = input_component_1.InputComponent;
28
+ const props = {
29
+ isDisabled: true,
30
+ label: 'Hello world',
31
+ onClick: ($event) => { },
32
+ 'dash-out': ($event) => { },
33
+ };
34
+ const source = (0, ComputesTemplateFromComponent_1.computesTemplateFromComponent)(component, props);
35
+ (0, vitest_1.expect)(source).toEqual(`<doc-button [isDisabled]="isDisabled" [label]="label" (onClick)="onClick($event)" (dash-out)="this['dash-out']($event)"></doc-button>`);
36
+ });
37
+ (0, vitest_1.it)('with no props should generate simple tag', () => {
38
+ const component = input_component_1.InputComponent;
39
+ const props = {};
40
+ const source = (0, ComputesTemplateFromComponent_1.computesTemplateFromComponent)(component, props);
41
+ (0, vitest_1.expect)(source).toEqual('<doc-button></doc-button>');
42
+ });
43
+ (0, vitest_1.describe)('with component without selector', () => {
44
+ let WithoutSelectorComponent = class WithoutSelectorComponent {
45
+ };
46
+ WithoutSelectorComponent = __decorate([
47
+ (0, core_1.Component)({
48
+ template: `The content`,
49
+ })
50
+ ], WithoutSelectorComponent);
51
+ (0, vitest_1.it)('should add component ng-container', async () => {
52
+ const component = WithoutSelectorComponent;
53
+ const props = {};
54
+ const source = (0, ComputesTemplateFromComponent_1.computesTemplateFromComponent)(component, props);
55
+ (0, vitest_1.expect)(source).toEqual(`<ng-container *ngComponentOutlet="storyComponent"></ng-container>`);
56
+ });
57
+ });
58
+ (0, vitest_1.describe)('with component with attribute selector', () => {
59
+ let WithAttributeComponent = class WithAttributeComponent {
60
+ };
61
+ WithAttributeComponent = __decorate([
62
+ (0, core_1.Component)({
63
+ selector: 'doc-button[foo]',
64
+ template: '<button></button>',
65
+ })
66
+ ], WithAttributeComponent);
67
+ (0, vitest_1.it)('should add attribute to template', async () => {
68
+ const component = WithAttributeComponent;
69
+ const props = {};
70
+ const source = (0, ComputesTemplateFromComponent_1.computesTemplateFromComponent)(component, props);
71
+ (0, vitest_1.expect)(source).toEqual(`<doc-button foo></doc-button>`);
72
+ });
73
+ });
74
+ (0, vitest_1.describe)('with component with attribute and value selector', () => {
75
+ let WithAttributeValueComponent = class WithAttributeValueComponent {
76
+ };
77
+ WithAttributeValueComponent = __decorate([
78
+ (0, core_1.Component)({
79
+ selector: 'doc-button[foo="bar"]',
80
+ template: '<button></button>',
81
+ })
82
+ ], WithAttributeValueComponent);
83
+ (0, vitest_1.it)('should add attribute to template', async () => {
84
+ const component = WithAttributeValueComponent;
85
+ const props = {};
86
+ const source = (0, ComputesTemplateFromComponent_1.computesTemplateFromComponent)(component, props);
87
+ (0, vitest_1.expect)(source).toEqual(`<doc-button foo="bar"></doc-button>`);
88
+ });
89
+ });
90
+ (0, vitest_1.describe)('with component with attribute only selector', () => {
91
+ let WithAttributeOnlyComponent = class WithAttributeOnlyComponent {
92
+ };
93
+ WithAttributeOnlyComponent = __decorate([
94
+ (0, core_1.Component)({
95
+ selector: '[foo]',
96
+ template: '<button></button>',
97
+ })
98
+ ], WithAttributeOnlyComponent);
99
+ (0, vitest_1.it)('should create a div and add attribute to template', async () => {
100
+ const component = WithAttributeOnlyComponent;
101
+ const props = {};
102
+ const source = (0, ComputesTemplateFromComponent_1.computesTemplateFromComponent)(component, props);
103
+ (0, vitest_1.expect)(source).toEqual(`<div foo></div>`);
104
+ });
105
+ });
106
+ (0, vitest_1.describe)('with component with void element and attribute selector', () => {
107
+ let VoidElementWithAttributeComponent = class VoidElementWithAttributeComponent {
108
+ };
109
+ VoidElementWithAttributeComponent = __decorate([
110
+ (0, core_1.Component)({
111
+ selector: 'input[foo]',
112
+ template: '<button></button>',
113
+ })
114
+ ], VoidElementWithAttributeComponent);
115
+ (0, vitest_1.it)('should create without separate closing tag', async () => {
116
+ const component = VoidElementWithAttributeComponent;
117
+ const props = {};
118
+ const source = (0, ComputesTemplateFromComponent_1.computesTemplateFromComponent)(component, props);
119
+ (0, vitest_1.expect)(source).toEqual(`<input foo />`);
120
+ });
121
+ });
122
+ (0, vitest_1.describe)('with component with attribute and value only selector', () => {
123
+ let WithAttributeOnlyComponent = class WithAttributeOnlyComponent {
124
+ };
125
+ WithAttributeOnlyComponent = __decorate([
126
+ (0, core_1.Component)({
127
+ selector: '[foo="bar"]',
128
+ template: '<button></button>',
129
+ })
130
+ ], WithAttributeOnlyComponent);
131
+ (0, vitest_1.it)('should create a div and add attribute to template', async () => {
132
+ const component = WithAttributeOnlyComponent;
133
+ const props = {};
134
+ const source = (0, ComputesTemplateFromComponent_1.computesTemplateFromComponent)(component, props);
135
+ (0, vitest_1.expect)(source).toEqual(`<div foo="bar"></div>`);
136
+ });
137
+ });
138
+ (0, vitest_1.describe)('with component with void element, attribute and value only selector', () => {
139
+ let VoidElementWithAttributeComponent = class VoidElementWithAttributeComponent {
140
+ };
141
+ VoidElementWithAttributeComponent = __decorate([
142
+ (0, core_1.Component)({
143
+ selector: 'input[foo="bar"]',
144
+ template: '<button></button>',
145
+ })
146
+ ], VoidElementWithAttributeComponent);
147
+ (0, vitest_1.it)('should create and add attribute to template without separate closing tag', async () => {
148
+ const component = VoidElementWithAttributeComponent;
149
+ const props = {};
150
+ const source = (0, ComputesTemplateFromComponent_1.computesTemplateFromComponent)(component, props);
151
+ (0, vitest_1.expect)(source).toEqual(`<input foo="bar" />`);
152
+ });
153
+ });
154
+ (0, vitest_1.describe)('with component with class selector', () => {
155
+ let WithClassComponent = class WithClassComponent {
156
+ };
157
+ WithClassComponent = __decorate([
158
+ (0, core_1.Component)({
159
+ selector: 'doc-button.foo',
160
+ template: '<button></button>',
161
+ })
162
+ ], WithClassComponent);
163
+ (0, vitest_1.it)('should add class to template', async () => {
164
+ const component = WithClassComponent;
165
+ const props = {};
166
+ const source = (0, ComputesTemplateFromComponent_1.computesTemplateFromComponent)(component, props);
167
+ (0, vitest_1.expect)(source).toEqual(`<doc-button class="foo"></doc-button>`);
168
+ });
169
+ });
170
+ (0, vitest_1.describe)('with component with class only selector', () => {
171
+ let WithClassComponent = class WithClassComponent {
172
+ };
173
+ WithClassComponent = __decorate([
174
+ (0, core_1.Component)({
175
+ selector: '.foo',
176
+ template: '<button></button>',
177
+ })
178
+ ], WithClassComponent);
179
+ (0, vitest_1.it)('should create a div and add attribute to template', async () => {
180
+ const component = WithClassComponent;
181
+ const props = {};
182
+ const source = (0, ComputesTemplateFromComponent_1.computesTemplateFromComponent)(component, props);
183
+ (0, vitest_1.expect)(source).toEqual(`<div class="foo"></div>`);
184
+ });
185
+ });
186
+ (0, vitest_1.describe)('with component with multiple selectors', () => {
187
+ let WithMultipleSelectorsComponent = class WithMultipleSelectorsComponent {
188
+ };
189
+ WithMultipleSelectorsComponent = __decorate([
190
+ (0, core_1.Component)({
191
+ selector: 'doc-button, doc-button2',
192
+ template: '<button></button>',
193
+ })
194
+ ], WithMultipleSelectorsComponent);
195
+ (0, vitest_1.it)('should use the first selector', async () => {
196
+ const component = WithMultipleSelectorsComponent;
197
+ const props = {};
198
+ const source = (0, ComputesTemplateFromComponent_1.computesTemplateFromComponent)(component, props);
199
+ (0, vitest_1.expect)(source).toEqual(`<doc-button></doc-button>`);
200
+ });
201
+ });
202
+ (0, vitest_1.describe)('with component with multiple selectors starting with attribute', () => {
203
+ let WithMultipleSelectorsComponent = class WithMultipleSelectorsComponent {
204
+ };
205
+ WithMultipleSelectorsComponent = __decorate([
206
+ (0, core_1.Component)({
207
+ selector: 'doc-button[foo], doc-button2',
208
+ template: '<button></button>',
209
+ })
210
+ ], WithMultipleSelectorsComponent);
211
+ (0, vitest_1.it)('should use the first selector', async () => {
212
+ const component = WithMultipleSelectorsComponent;
213
+ const props = {};
214
+ const source = (0, ComputesTemplateFromComponent_1.computesTemplateFromComponent)(component, props);
215
+ (0, vitest_1.expect)(source).toEqual(`<doc-button foo></doc-button>`);
216
+ });
217
+ });
218
+ (0, vitest_1.describe)('with component with multiple selectors starting with attribute and value', () => {
219
+ let WithMultipleSelectorsComponent = class WithMultipleSelectorsComponent {
220
+ };
221
+ WithMultipleSelectorsComponent = __decorate([
222
+ (0, core_1.Component)({
223
+ selector: 'doc-button[foo="bar"], doc-button2',
224
+ template: '<button></button>',
225
+ })
226
+ ], WithMultipleSelectorsComponent);
227
+ (0, vitest_1.it)('should use the first selector', async () => {
228
+ const component = WithMultipleSelectorsComponent;
229
+ const props = {};
230
+ const source = (0, ComputesTemplateFromComponent_1.computesTemplateFromComponent)(component, props);
231
+ (0, vitest_1.expect)(source).toEqual(`<doc-button foo="bar"></doc-button>`);
232
+ });
233
+ });
234
+ (0, vitest_1.describe)('with component with multiple selectors including 2 attributes and a class', () => {
235
+ let WithMultipleSelectorsComponent = class WithMultipleSelectorsComponent {
236
+ };
237
+ WithMultipleSelectorsComponent = __decorate([
238
+ (0, core_1.Component)({
239
+ selector: 'doc-button, button[foo], .button[foo], button[baz]',
240
+ template: '<button></button>',
241
+ })
242
+ ], WithMultipleSelectorsComponent);
243
+ (0, vitest_1.it)('should use the first selector', async () => {
244
+ const component = WithMultipleSelectorsComponent;
245
+ const props = {};
246
+ const source = (0, ComputesTemplateFromComponent_1.computesTemplateFromComponent)(component, props);
247
+ (0, vitest_1.expect)(source).toEqual(`<doc-button></doc-button>`);
248
+ });
249
+ });
250
+ (0, vitest_1.describe)('with component with multiple selectors with line breaks', () => {
251
+ let WithMultipleSelectorsComponent = class WithMultipleSelectorsComponent {
252
+ };
253
+ WithMultipleSelectorsComponent = __decorate([
254
+ (0, core_1.Component)({
255
+ selector: `doc-button,
256
+ doc-button2`,
257
+ template: '<button></button>',
258
+ })
259
+ ], WithMultipleSelectorsComponent);
260
+ (0, vitest_1.it)('should use the first selector', async () => {
261
+ const component = WithMultipleSelectorsComponent;
262
+ const props = {};
263
+ const source = (0, ComputesTemplateFromComponent_1.computesTemplateFromComponent)(component, props);
264
+ (0, vitest_1.expect)(source).toEqual(`<doc-button></doc-button>`);
265
+ });
266
+ });
267
+ (0, vitest_1.describe)('with component with multiple selectors starting with attribute only with line breaks', () => {
268
+ let WithMultipleSelectorsComponent = class WithMultipleSelectorsComponent {
269
+ };
270
+ WithMultipleSelectorsComponent = __decorate([
271
+ (0, core_1.Component)({
272
+ selector: `[foo],
273
+ doc-button2`,
274
+ template: '<button></button>',
275
+ })
276
+ ], WithMultipleSelectorsComponent);
277
+ (0, vitest_1.it)('should use the first selector', async () => {
278
+ const component = WithMultipleSelectorsComponent;
279
+ const props = {};
280
+ const source = (0, ComputesTemplateFromComponent_1.computesTemplateFromComponent)(component, props);
281
+ (0, vitest_1.expect)(source).toEqual(`<div foo></div>`);
282
+ });
283
+ });
284
+ (0, vitest_1.it)('with props should generate tag with properties', () => {
285
+ const component = input_component_1.InputComponent;
286
+ const props = {
287
+ isDisabled: true,
288
+ label: 'Hello world',
289
+ accent: input_component_1.ButtonAccent.High,
290
+ counter: 4,
291
+ };
292
+ const source = (0, ComputesTemplateFromComponent_1.computesTemplateFromComponent)(component, props);
293
+ (0, vitest_1.expect)(source).toEqual(`<doc-button [counter]="counter" [accent]="accent" [isDisabled]="isDisabled" [label]="label"></doc-button>`);
294
+ });
295
+ (0, vitest_1.it)('with props should generate tag with outputs', () => {
296
+ const component = input_component_1.InputComponent;
297
+ const props = {
298
+ isDisabled: true,
299
+ label: 'Hello world',
300
+ onClick: ($event) => { },
301
+ };
302
+ const source = (0, ComputesTemplateFromComponent_1.computesTemplateFromComponent)(component, props);
303
+ (0, vitest_1.expect)(source).toEqual(`<doc-button [isDisabled]="isDisabled" [label]="label" (onClick)="onClick($event)"></doc-button>`);
304
+ });
305
+ (0, vitest_1.it)('should generate correct property for overridden name for Input', () => {
306
+ const component = input_component_1.InputComponent;
307
+ const props = {
308
+ color: '#ffffff',
309
+ };
310
+ const source = (0, ComputesTemplateFromComponent_1.computesTemplateFromComponent)(component, props);
311
+ (0, vitest_1.expect)(source).toEqual(`<doc-button [color]="color"></doc-button>`);
312
+ });
313
+ });
13
314
  (0, vitest_1.describe)('angular source decorator', () => {
14
- (0, vitest_1.it)('With no props should generate simple tag', () => {
315
+ (0, vitest_1.it)('with no props should generate simple tag', () => {
15
316
  const component = input_component_1.InputComponent;
16
317
  const props = {};
17
318
  const argTypes = {};
@@ -282,28 +583,30 @@ const input_component_1 = require("./__testfixtures__/input.component");
282
583
  const source = (0, ComputesTemplateFromComponent_1.computesTemplateSourceFromComponent)(component, props, argTypes);
283
584
  (0, vitest_1.expect)(source).toEqual(`<doc-button></doc-button>`);
284
585
  });
285
- (0, vitest_1.it)('With props should generate tag with properties', () => {
586
+ (0, vitest_1.it)('with props should generate tag with properties', () => {
286
587
  const component = input_component_1.InputComponent;
287
588
  const props = {
288
589
  isDisabled: true,
289
590
  label: 'Hello world',
290
591
  accent: input_component_1.ButtonAccent.High,
291
592
  counter: 4,
593
+ 'aria-label': 'Hello world',
292
594
  };
293
595
  const argTypes = {};
294
596
  const source = (0, ComputesTemplateFromComponent_1.computesTemplateSourceFromComponent)(component, props, argTypes);
295
- (0, vitest_1.expect)(source).toEqual(`<doc-button [counter]="4" [accent]="'High'" [isDisabled]="true" [label]="'Hello world'"></doc-button>`);
597
+ (0, vitest_1.expect)(source).toEqual(`<doc-button [counter]="4" [accent]="'High'" [isDisabled]="true" [label]="'Hello world'" [aria-label]="'Hello world'"></doc-button>`);
296
598
  });
297
- (0, vitest_1.it)('With props should generate tag with outputs', () => {
599
+ (0, vitest_1.it)('with props should generate tag with outputs', () => {
298
600
  const component = input_component_1.InputComponent;
299
601
  const props = {
300
602
  isDisabled: true,
301
603
  label: 'Hello world',
302
604
  onClick: ($event) => { },
605
+ 'dash-out': ($event) => { },
303
606
  };
304
607
  const argTypes = {};
305
608
  const source = (0, ComputesTemplateFromComponent_1.computesTemplateSourceFromComponent)(component, props, argTypes);
306
- (0, vitest_1.expect)(source).toEqual(`<doc-button [isDisabled]="true" [label]="'Hello world'" (onClick)="onClick($event)"></doc-button>`);
609
+ (0, vitest_1.expect)(source).toEqual(`<doc-button [isDisabled]="true" [label]="'Hello world'" (onClick)="onClick($event)" (dash-out)="this['dash-out']($event)"></doc-button>`);
307
610
  });
308
611
  (0, vitest_1.it)('should generate correct property for overridden name for Input', () => {
309
612
  const component = input_component_1.InputComponent;
@@ -316,7 +619,7 @@ const input_component_1 = require("./__testfixtures__/input.component");
316
619
  });
317
620
  });
318
621
  (0, vitest_1.describe)('with argTypes (from compodoc)', () => {
319
- (0, vitest_1.it)('Should handle enum as strongly typed enum', () => {
622
+ (0, vitest_1.it)('should handle enum as strongly typed enum', () => {
320
623
  const component = input_component_1.InputComponent;
321
624
  const props = {
322
625
  isDisabled: false,
@@ -343,7 +646,7 @@ const input_component_1 = require("./__testfixtures__/input.component");
343
646
  const source = (0, ComputesTemplateFromComponent_1.computesTemplateSourceFromComponent)(component, props, argTypes);
344
647
  (0, vitest_1.expect)(source).toEqual(`<doc-button [accent]="'High'" [isDisabled]="false" [label]="'Hello world'"></doc-button>`);
345
648
  });
346
- (0, vitest_1.it)('Should handle enum without values as string', () => {
649
+ (0, vitest_1.it)('should handle enum without values as string', () => {
347
650
  const component = input_component_1.InputComponent;
348
651
  const props = {
349
652
  isDisabled: false,
@@ -370,7 +673,7 @@ const input_component_1 = require("./__testfixtures__/input.component");
370
673
  const source = (0, ComputesTemplateFromComponent_1.computesTemplateSourceFromComponent)(component, props, argTypes);
371
674
  (0, vitest_1.expect)(source).toEqual(`<doc-button [accent]="'High'" [isDisabled]="false" [label]="'Hello world'"></doc-button>`);
372
675
  });
373
- (0, vitest_1.it)('Should handle objects correctly', () => {
676
+ (0, vitest_1.it)('should handle simple object as stringified', () => {
374
677
  const component = input_component_1.InputComponent;
375
678
  const someDataObject = {
376
679
  one: 'Hello world',
@@ -398,5 +701,34 @@ const input_component_1 = require("./__testfixtures__/input.component");
398
701
  // This will have to do for now
399
702
  (0, vitest_1.expect)(source).toEqual(`<doc-button [isDisabled]="false" [label]="'Hello world'" [someDataObject]="{one: 'Hello world', two: true, three: ['a string literal with \\'double quotes\\'', 'a string literal with \\'single quotes\\'', 'a single quoted string with \\'double quotes\\'', 'a double quoted string with \\'single quotes\\'', 'a single quoted string with escaped \\'single quotes\\'', 'a double quoted string with escaped \\'double quotes\\'', 'a string literal with \\'escaped single quotes\\'', 'a string literal with \\'escaped double quotes\\'']}"></doc-button>`);
400
703
  });
704
+ (0, vitest_1.it)('should handle circular object as stringified', () => {
705
+ const component = input_component_1.InputComponent;
706
+ const someDataObject = {
707
+ one: 'Hello world',
708
+ two: true,
709
+ three: [
710
+ `a string literal with "double quotes"`,
711
+ `a string literal with 'single quotes'`,
712
+ 'a single quoted string with "double quotes"',
713
+ "a double quoted string with 'single quotes'",
714
+ // eslint-disable-next-line prettier/prettier
715
+ 'a single quoted string with escaped \'single quotes\'',
716
+ // eslint-disable-next-line prettier/prettier
717
+ "a double quoted string with escaped \"double quotes\"",
718
+ `a string literal with \'escaped single quotes\'`,
719
+ `a string literal with \"escaped double quotes\"`,
720
+ ],
721
+ };
722
+ someDataObject.ref = someDataObject;
723
+ const props = {
724
+ isDisabled: false,
725
+ label: 'Hello world',
726
+ someDataObject,
727
+ };
728
+ const source = (0, ComputesTemplateFromComponent_1.computesTemplateSourceFromComponent)(component, props, null);
729
+ // Ideally we should stringify the object, but that could cause the story to break because of unescaped values in the JSON object.
730
+ // This will have to do for now
731
+ (0, vitest_1.expect)(source).toEqual(`<doc-button [isDisabled]="false" [label]="'Hello world'" [someDataObject]="{one: 'Hello world', two: true, three: ['a string literal with \\'double quotes\\'', 'a string literal with \\'single quotes\\'', 'a single quoted string with \\'double quotes\\'', 'a double quoted string with \\'single quotes\\'', 'a single quoted string with escaped \\'single quotes\\'', 'a double quoted string with escaped \\'double quotes\\'', 'a string literal with \\'escaped single quotes\\'', 'a string literal with \\'escaped double quotes\\''], ref: '[Circular]'}"></doc-button>`);
732
+ });
401
733
  });
402
734
  });
@@ -8,6 +8,7 @@ export interface ISomeInterface {
8
8
  one: string;
9
9
  two: boolean;
10
10
  three: any[];
11
+ ref?: ISomeInterface;
11
12
  }
12
13
  export declare class InputComponent<T> {
13
14
  /** Appearance style of the button. */
@@ -20,7 +21,9 @@ export declare class InputComponent<T> {
20
21
  /** Sets the button to a disabled state. */
21
22
  isDisabled: boolean;
22
23
  label: string;
24
+ ariaLabel: string;
23
25
  /** Specifies some arbitrary object */
24
26
  someDataObject: ISomeInterface;
25
27
  onClick: EventEmitter<Event>;
28
+ dashOut: EventEmitter<any>;
26
29
  }
@@ -24,6 +24,7 @@ let InputComponent = class InputComponent {
24
24
  /** Sets the button to a disabled state. */
25
25
  this.isDisabled = false;
26
26
  this.onClick = new core_1.EventEmitter();
27
+ this.dashOut = new core_1.EventEmitter();
27
28
  }
28
29
  };
29
30
  exports.InputComponent = InputComponent;
@@ -51,6 +52,10 @@ __decorate([
51
52
  (0, core_1.Input)(),
52
53
  __metadata("design:type", String)
53
54
  ], InputComponent.prototype, "label", void 0);
55
+ __decorate([
56
+ (0, core_1.Input)('aria-label'),
57
+ __metadata("design:type", String)
58
+ ], InputComponent.prototype, "ariaLabel", void 0);
54
59
  __decorate([
55
60
  (0, core_1.Input)(),
56
61
  __metadata("design:type", Object)
@@ -59,6 +64,10 @@ __decorate([
59
64
  (0, core_1.Output)(),
60
65
  __metadata("design:type", Object)
61
66
  ], InputComponent.prototype, "onClick", void 0);
67
+ __decorate([
68
+ (0, core_1.Output)('dash-out'),
69
+ __metadata("design:type", Object)
70
+ ], InputComponent.prototype, "dashOut", void 0);
62
71
  exports.InputComponent = InputComponent = __decorate([
63
72
  (0, core_1.Component)({
64
73
  selector: 'doc-button',
@@ -1,6 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.argsToTemplate = void 0;
4
+ const ComputesTemplateFromComponent_1 = require("./angular-beta/ComputesTemplateFromComponent");
4
5
  /**
5
6
  * Converts an object of arguments to a string of property and event bindings and excludes undefined values.
6
7
  * Why? Because Angular treats undefined values in property bindings as an actual value
@@ -48,7 +49,9 @@ function argsToTemplate(args, options = {}) {
48
49
  return !excludeSet.has(key);
49
50
  return true;
50
51
  })
51
- .map(([key, value]) => typeof value === 'function' ? `(${key})="${key}($event)"` : `[${key}]="${key}"`)
52
+ .map(([key, value]) => typeof value === 'function'
53
+ ? `(${key})="${(0, ComputesTemplateFromComponent_1.formatPropInTemplate)(key)}($event)"`
54
+ : `[${key}]="${(0, ComputesTemplateFromComponent_1.formatPropInTemplate)(key)}"`)
52
55
  .join(' ');
53
56
  }
54
57
  exports.argsToTemplate = argsToTemplate;
@@ -93,4 +93,9 @@ const argsToTemplate_1 = require("./argsToTemplate"); // adjust path
93
93
  const result = (0, argsToTemplate_1.argsToTemplate)(args, {});
94
94
  (0, vitest_1.expect)(result).toEqual('[input]="input" (event1)="event1($event)"');
95
95
  });
96
+ (0, vitest_1.it)('should format for non dot notation', () => {
97
+ const args = { 'non-dot': 'Value1', 'dash-out': () => { } };
98
+ const result = (0, argsToTemplate_1.argsToTemplate)(args, {});
99
+ (0, vitest_1.expect)(result).toEqual('[non-dot]="this[\'non-dot\']" (dash-out)="this[\'dash-out\']($event)"');
100
+ });
96
101
  });
@@ -22,6 +22,8 @@ const defaultContext = {
22
22
  args: {},
23
23
  argTypes: {},
24
24
  globals: {},
25
+ globalTypes: {},
26
+ storyGlobals: {},
25
27
  hooks: {},
26
28
  loaded: {},
27
29
  originalStoryFn: vitest_1.vi.fn(),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@storybook/angular",
3
- "version": "8.3.0-alpha.2",
3
+ "version": "8.3.0-alpha.4",
4
4
  "description": "Storybook for Angular: Develop Angular components in isolation with hot reloading.",
5
5
  "keywords": [
6
6
  "storybook",
@@ -37,13 +37,13 @@
37
37
  "prep": "rimraf dist && node --loader ../../../scripts/node_modules/esbuild-register/loader.js -r ../../../scripts/node_modules/esbuild-register/register.js ../../../scripts/prepare/tsc.ts"
38
38
  },
39
39
  "dependencies": {
40
- "@storybook/builder-webpack5": "8.3.0-alpha.2",
41
- "@storybook/components": "^8.3.0-alpha.2",
42
- "@storybook/core-webpack": "8.3.0-alpha.2",
40
+ "@storybook/builder-webpack5": "8.3.0-alpha.4",
41
+ "@storybook/components": "^8.3.0-alpha.4",
42
+ "@storybook/core-webpack": "8.3.0-alpha.4",
43
43
  "@storybook/global": "^5.0.0",
44
- "@storybook/manager-api": "^8.3.0-alpha.2",
45
- "@storybook/preview-api": "^8.3.0-alpha.2",
46
- "@storybook/theming": "^8.3.0-alpha.2",
44
+ "@storybook/manager-api": "^8.3.0-alpha.4",
45
+ "@storybook/preview-api": "^8.3.0-alpha.4",
46
+ "@storybook/theming": "^8.3.0-alpha.4",
47
47
  "@types/node": "^18.0.0",
48
48
  "@types/react": "^18.0.37",
49
49
  "@types/react-dom": "^18.0.11",
@@ -93,7 +93,7 @@
93
93
  "@angular/platform-browser": ">=15.0.0 < 19.0.0",
94
94
  "@angular/platform-browser-dynamic": ">=15.0.0 < 19.0.0",
95
95
  "rxjs": "^6.0.0 || ^7.4.0",
96
- "storybook": "^8.3.0-alpha.2",
96
+ "storybook": "^8.3.0-alpha.4",
97
97
  "typescript": "^4.0.0 || ^5.0.0",
98
98
  "zone.js": ">= 0.11.1 < 1.0.0"
99
99
  },