@stencil/angular-output-target 0.6.1-dev.11667512184.13935f80 → 0.6.1-dev.11669751385.1c42cc9f

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.
@@ -36,28 +36,6 @@ export const defineCustomElement = (tagName: string, customElement: any) => {
36
36
  }
37
37
  };
38
38
 
39
- /**
40
- * The Angular property name that contains the object of metadata properties
41
- * for the component added by the Angular compiler.
42
- */
43
- const NG_COMP_DEF = 'ɵcmp';
44
-
45
- export const clearAngularOutputBindings = (cls: any) => {
46
- if (typeof cls === 'function' && cls !== null) {
47
- if (cls.prototype.constructor) {
48
- const instance = cls.prototype.constructor;
49
- if (instance[NG_COMP_DEF]) {
50
- /**
51
- * With the output targets generating @Output() proxies, we need to
52
- * clear the metadata (ɵcmp.outputs) so that Angular does not add its own event listener
53
- * and cause duplicate event emissions for the web component events.
54
- */
55
- instance[NG_COMP_DEF].outputs = {};
56
- }
57
- }
58
- }
59
- };
60
-
61
39
  // tslint:disable-next-line: only-arrow-functions
62
40
  export function ProxyCmp(opts: { defineCustomElementFn?: () => void; inputs?: any; methods?: any }) {
63
41
  const decorator = function (cls: any) {
@@ -67,8 +45,6 @@ export function ProxyCmp(opts: { defineCustomElementFn?: () => void; inputs?: an
67
45
  defineCustomElementFn();
68
46
  }
69
47
 
70
- clearAngularOutputBindings(cls);
71
-
72
48
  if (inputs) {
73
49
  proxyInputs(cls, inputs);
74
50
  }
@@ -9,7 +9,7 @@ import type { ComponentCompilerEvent } from '@stencil/core/internal';
9
9
  * @param includeImportCustomElements Whether to define the component as a custom element.
10
10
  * @returns The component declaration as a string.
11
11
  */
12
- export declare const createAngularComponentDefinition: (tagName: string, inputs: readonly string[], outputs: readonly ComponentCompilerEvent[], methods: readonly string[], includeImportCustomElements?: boolean) => string;
12
+ export declare const createAngularComponentDefinition: (tagName: string, inputs: readonly string[], outputs: readonly string[], methods: readonly string[], includeImportCustomElements?: boolean) => string;
13
13
  /**
14
14
  * Creates the component interface type definition.
15
15
  * @param tagNameAsPascal The tag name as PascalCase.
@@ -17,11 +17,9 @@ export const createAngularComponentDefinition = (tagName, inputs, outputs, metho
17
17
  // Formats the input strings into comma separated, single quoted values.
18
18
  const formattedInputs = formatToQuotedList(inputs);
19
19
  // Formats the output strings into comma separated, single quoted values.
20
- const formattedOutputs = formatToQuotedList(outputs.map((event) => event.name));
20
+ const formattedOutputs = formatToQuotedList(outputs);
21
21
  // Formats the method strings into comma separated, single quoted values.
22
22
  const formattedMethods = formatToQuotedList(methods);
23
- // The collection of @Output() decorators for the component.
24
- const outputDecorators = outputs.map((event) => createAngularOutputDecorator(tagName, event));
25
23
  const proxyCmpOptions = [];
26
24
  if (includeImportCustomElements) {
27
25
  const defineCustomElementFn = `define${tagNameAsPascal}`;
@@ -33,54 +31,32 @@ export const createAngularComponentDefinition = (tagName, inputs, outputs, metho
33
31
  if (hasMethods) {
34
32
  proxyCmpOptions.push(`\n methods: [${formattedMethods}]`);
35
33
  }
36
- const output = [
37
- `@ProxyCmp({${proxyCmpOptions.join(',')}\n})`,
38
- `@Component({`,
39
- ` selector: '${tagName}',`,
40
- ` changeDetection: ChangeDetectionStrategy.OnPush,`,
41
- ` template: '<ng-content></ng-content>',`,
42
- /**
43
- * We disable @angular-eslint/no-inputs-metadata-property, so that
44
- * Angular does not complain about the inputs property. The output target
45
- * uses the inputs property to define the inputs of the component instead of
46
- * having to use the @Input decorator (and manually define the type and default value).
47
- */
48
- ` // eslint-disable-next-line @angular-eslint/no-inputs-metadata-property`,
49
- ` inputs: [${formattedInputs}],`,
50
- `})`,
51
- `export class ${tagNameAsPascal} {`,
52
- ];
53
- if (outputDecorators.length > 0) {
54
- for (let outputDecorator of outputDecorators) {
55
- output.push(` ${outputDecorator}`);
56
- }
57
- }
58
- output.push(` protected el: HTMLElement;`);
59
- output.push(` constructor(c: ChangeDetectorRef, r: ElementRef, protected z: NgZone) {`);
60
- output.push(` c.detach();`);
61
- output.push(` this.el = r.nativeElement;`);
62
- if (hasOutputs) {
63
- output.push(` proxyOutputs(this, this.el, [${formattedOutputs}]);`);
64
- }
65
- output.push(` }`);
66
- output.push(`}`);
67
- return output.join('\n');
68
- };
69
- /**
70
- * Creates an `@Output()` decorator for a custom event on a Stencil component.
71
- * @param tagName The tag name of the component.
72
- * @param event The Stencil component event.
73
- * @returns The `@Output()` decorator as a string.
74
- */
75
- const createAngularOutputDecorator = (tagName, event) => {
76
- const tagNameAsPascal = dashToPascalCase(tagName);
77
- // When updating to Stencil 3.0, the component custom event generic will be
78
- // exported by default and can be referenced here with:
79
- // const customEvent = `${tagNameAsPascal}CustomEvent`;
80
- const customEventType = `CustomEvent`;
81
- const eventType = formatOutputType(tagNameAsPascal, event);
82
- const outputType = `${customEventType}<${eventType}>`;
83
- return `@Output() ${event.name}: EventEmitter<${outputType}> = new EventEmitter();`;
34
+ /**
35
+ * Notes on the generated output:
36
+ * - We disable @angular-eslint/no-inputs-metadata-property, so that
37
+ * Angular does not complain about the inputs property. The output target
38
+ * uses the inputs property to define the inputs of the component instead of
39
+ * having to use the @Input decorator (and manually define the type and default value).
40
+ */
41
+ const output = `@ProxyCmp({${proxyCmpOptions.join(',')}\n})
42
+ @Component({
43
+ selector: '${tagName}',
44
+ changeDetection: ChangeDetectionStrategy.OnPush,
45
+ template: '<ng-content></ng-content>',
46
+ // eslint-disable-next-line @angular-eslint/no-inputs-metadata-property
47
+ inputs: [${formattedInputs}],
48
+ })
49
+ export class ${tagNameAsPascal} {
50
+ protected el: HTMLElement;
51
+ constructor(c: ChangeDetectorRef, r: ElementRef, protected z: NgZone) {
52
+ c.detach();
53
+ this.el = r.nativeElement;${hasOutputs
54
+ ? `
55
+ proxyOutputs(this, this.el, [${formattedOutputs}]);`
56
+ : ''}
57
+ }
58
+ }`;
59
+ return output;
84
60
  };
85
61
  /**
86
62
  * Sanitizes and formats the component event type.
@@ -138,8 +114,14 @@ export const createComponentTypeDefinition = (tagNameAsPascal, events, component
138
114
  });
139
115
  const eventTypes = publicEvents.map((event) => {
140
116
  const comment = createDocComment(event.docs);
117
+ let eventName = event.name;
118
+ if (event.name.includes('-')) {
119
+ // If an event name includes a dash, we need to wrap it in quotes.
120
+ // https://github.com/ionic-team/stencil-ds-output-targets/issues/212
121
+ eventName = `'${event.name}'`;
122
+ }
141
123
  return `${comment.length > 0 ? ` ${comment}` : ''}
142
- ${event.name}: EventEmitter<CustomEvent<${formatOutputType(tagNameAsPascal, event)}>>;`;
124
+ ${eventName}: EventEmitter<CustomEvent<${formatOutputType(tagNameAsPascal, event)}>>;`;
143
125
  });
144
126
  const interfaceDeclaration = `export declare interface ${tagNameAsPascal} extends Components.${tagNameAsPascal} {`;
145
127
  const typeDefinition = (eventTypeImports.length > 0 ? `${eventTypeImports + '\n\n'}` : '') +
package/dist/index.cjs.js CHANGED
@@ -148,11 +148,9 @@ const createAngularComponentDefinition = (tagName, inputs, outputs, methods, inc
148
148
  // Formats the input strings into comma separated, single quoted values.
149
149
  const formattedInputs = formatToQuotedList(inputs);
150
150
  // Formats the output strings into comma separated, single quoted values.
151
- const formattedOutputs = formatToQuotedList(outputs.map((event) => event.name));
151
+ const formattedOutputs = formatToQuotedList(outputs);
152
152
  // Formats the method strings into comma separated, single quoted values.
153
153
  const formattedMethods = formatToQuotedList(methods);
154
- // The collection of @Output() decorators for the component.
155
- const outputDecorators = outputs.map((event) => createAngularOutputDecorator(tagName, event));
156
154
  const proxyCmpOptions = [];
157
155
  if (includeImportCustomElements) {
158
156
  const defineCustomElementFn = `define${tagNameAsPascal}`;
@@ -164,54 +162,32 @@ const createAngularComponentDefinition = (tagName, inputs, outputs, methods, inc
164
162
  if (hasMethods) {
165
163
  proxyCmpOptions.push(`\n methods: [${formattedMethods}]`);
166
164
  }
167
- const output = [
168
- `@ProxyCmp({${proxyCmpOptions.join(',')}\n})`,
169
- `@Component({`,
170
- ` selector: '${tagName}',`,
171
- ` changeDetection: ChangeDetectionStrategy.OnPush,`,
172
- ` template: '<ng-content></ng-content>',`,
173
- /**
174
- * We disable @angular-eslint/no-inputs-metadata-property, so that
175
- * Angular does not complain about the inputs property. The output target
176
- * uses the inputs property to define the inputs of the component instead of
177
- * having to use the @Input decorator (and manually define the type and default value).
178
- */
179
- ` // eslint-disable-next-line @angular-eslint/no-inputs-metadata-property`,
180
- ` inputs: [${formattedInputs}],`,
181
- `})`,
182
- `export class ${tagNameAsPascal} {`,
183
- ];
184
- if (outputDecorators.length > 0) {
185
- for (let outputDecorator of outputDecorators) {
186
- output.push(` ${outputDecorator}`);
187
- }
188
- }
189
- output.push(` protected el: HTMLElement;`);
190
- output.push(` constructor(c: ChangeDetectorRef, r: ElementRef, protected z: NgZone) {`);
191
- output.push(` c.detach();`);
192
- output.push(` this.el = r.nativeElement;`);
193
- if (hasOutputs) {
194
- output.push(` proxyOutputs(this, this.el, [${formattedOutputs}]);`);
195
- }
196
- output.push(` }`);
197
- output.push(`}`);
198
- return output.join('\n');
199
- };
200
- /**
201
- * Creates an `@Output()` decorator for a custom event on a Stencil component.
202
- * @param tagName The tag name of the component.
203
- * @param event The Stencil component event.
204
- * @returns The `@Output()` decorator as a string.
205
- */
206
- const createAngularOutputDecorator = (tagName, event) => {
207
- const tagNameAsPascal = dashToPascalCase(tagName);
208
- // When updating to Stencil 3.0, the component custom event generic will be
209
- // exported by default and can be referenced here with:
210
- // const customEvent = `${tagNameAsPascal}CustomEvent`;
211
- const customEventType = `CustomEvent`;
212
- const eventType = formatOutputType(tagNameAsPascal, event);
213
- const outputType = `${customEventType}<${eventType}>`;
214
- return `@Output() ${event.name}: EventEmitter<${outputType}> = new EventEmitter();`;
165
+ /**
166
+ * Notes on the generated output:
167
+ * - We disable @angular-eslint/no-inputs-metadata-property, so that
168
+ * Angular does not complain about the inputs property. The output target
169
+ * uses the inputs property to define the inputs of the component instead of
170
+ * having to use the @Input decorator (and manually define the type and default value).
171
+ */
172
+ const output = `@ProxyCmp({${proxyCmpOptions.join(',')}\n})
173
+ @Component({
174
+ selector: '${tagName}',
175
+ changeDetection: ChangeDetectionStrategy.OnPush,
176
+ template: '<ng-content></ng-content>',
177
+ // eslint-disable-next-line @angular-eslint/no-inputs-metadata-property
178
+ inputs: [${formattedInputs}],
179
+ })
180
+ export class ${tagNameAsPascal} {
181
+ protected el: HTMLElement;
182
+ constructor(c: ChangeDetectorRef, r: ElementRef, protected z: NgZone) {
183
+ c.detach();
184
+ this.el = r.nativeElement;${hasOutputs
185
+ ? `
186
+ proxyOutputs(this, this.el, [${formattedOutputs}]);`
187
+ : ''}
188
+ }
189
+ }`;
190
+ return output;
215
191
  };
216
192
  /**
217
193
  * Sanitizes and formats the component event type.
@@ -269,8 +245,14 @@ const createComponentTypeDefinition = (tagNameAsPascal, events, componentCorePac
269
245
  });
270
246
  const eventTypes = publicEvents.map((event) => {
271
247
  const comment = createDocComment(event.docs);
248
+ let eventName = event.name;
249
+ if (event.name.includes('-')) {
250
+ // If an event name includes a dash, we need to wrap it in quotes.
251
+ // https://github.com/ionic-team/stencil-ds-output-targets/issues/212
252
+ eventName = `'${event.name}'`;
253
+ }
272
254
  return `${comment.length > 0 ? ` ${comment}` : ''}
273
- ${event.name}: EventEmitter<CustomEvent<${formatOutputType(tagNameAsPascal, event)}>>;`;
255
+ ${eventName}: EventEmitter<CustomEvent<${formatOutputType(tagNameAsPascal, event)}>>;`;
274
256
  });
275
257
  const interfaceDeclaration = `export declare interface ${tagNameAsPascal} extends Components.${tagNameAsPascal} {`;
276
258
  const typeDefinition = (eventTypeImports.length > 0 ? `${eventTypeImports + '\n\n'}` : '') +
@@ -401,7 +383,6 @@ function generateProxies(components, pkgData, outputTarget, rootDir) {
401
383
  'ElementRef',
402
384
  'EventEmitter',
403
385
  'NgZone',
404
- 'Output',
405
386
  ];
406
387
  /**
407
388
  * The collection of named imports from the angular-component-lib/utils.
@@ -458,7 +439,7 @@ ${createImportStatement(componentLibImports, './angular-component-lib/utils')}\n
458
439
  inputs.sort();
459
440
  const outputs = [];
460
441
  if (cmpMeta.events) {
461
- outputs.push(...cmpMeta.events.filter(filterInternalProps));
442
+ outputs.push(...cmpMeta.events.filter(filterInternalProps).map(mapPropName));
462
443
  }
463
444
  const methods = [];
464
445
  if (cmpMeta.methods) {
package/dist/index.js CHANGED
@@ -140,11 +140,9 @@ const createAngularComponentDefinition = (tagName, inputs, outputs, methods, inc
140
140
  // Formats the input strings into comma separated, single quoted values.
141
141
  const formattedInputs = formatToQuotedList(inputs);
142
142
  // Formats the output strings into comma separated, single quoted values.
143
- const formattedOutputs = formatToQuotedList(outputs.map((event) => event.name));
143
+ const formattedOutputs = formatToQuotedList(outputs);
144
144
  // Formats the method strings into comma separated, single quoted values.
145
145
  const formattedMethods = formatToQuotedList(methods);
146
- // The collection of @Output() decorators for the component.
147
- const outputDecorators = outputs.map((event) => createAngularOutputDecorator(tagName, event));
148
146
  const proxyCmpOptions = [];
149
147
  if (includeImportCustomElements) {
150
148
  const defineCustomElementFn = `define${tagNameAsPascal}`;
@@ -156,54 +154,32 @@ const createAngularComponentDefinition = (tagName, inputs, outputs, methods, inc
156
154
  if (hasMethods) {
157
155
  proxyCmpOptions.push(`\n methods: [${formattedMethods}]`);
158
156
  }
159
- const output = [
160
- `@ProxyCmp({${proxyCmpOptions.join(',')}\n})`,
161
- `@Component({`,
162
- ` selector: '${tagName}',`,
163
- ` changeDetection: ChangeDetectionStrategy.OnPush,`,
164
- ` template: '<ng-content></ng-content>',`,
165
- /**
166
- * We disable @angular-eslint/no-inputs-metadata-property, so that
167
- * Angular does not complain about the inputs property. The output target
168
- * uses the inputs property to define the inputs of the component instead of
169
- * having to use the @Input decorator (and manually define the type and default value).
170
- */
171
- ` // eslint-disable-next-line @angular-eslint/no-inputs-metadata-property`,
172
- ` inputs: [${formattedInputs}],`,
173
- `})`,
174
- `export class ${tagNameAsPascal} {`,
175
- ];
176
- if (outputDecorators.length > 0) {
177
- for (let outputDecorator of outputDecorators) {
178
- output.push(` ${outputDecorator}`);
179
- }
180
- }
181
- output.push(` protected el: HTMLElement;`);
182
- output.push(` constructor(c: ChangeDetectorRef, r: ElementRef, protected z: NgZone) {`);
183
- output.push(` c.detach();`);
184
- output.push(` this.el = r.nativeElement;`);
185
- if (hasOutputs) {
186
- output.push(` proxyOutputs(this, this.el, [${formattedOutputs}]);`);
187
- }
188
- output.push(` }`);
189
- output.push(`}`);
190
- return output.join('\n');
191
- };
192
- /**
193
- * Creates an `@Output()` decorator for a custom event on a Stencil component.
194
- * @param tagName The tag name of the component.
195
- * @param event The Stencil component event.
196
- * @returns The `@Output()` decorator as a string.
197
- */
198
- const createAngularOutputDecorator = (tagName, event) => {
199
- const tagNameAsPascal = dashToPascalCase(tagName);
200
- // When updating to Stencil 3.0, the component custom event generic will be
201
- // exported by default and can be referenced here with:
202
- // const customEvent = `${tagNameAsPascal}CustomEvent`;
203
- const customEventType = `CustomEvent`;
204
- const eventType = formatOutputType(tagNameAsPascal, event);
205
- const outputType = `${customEventType}<${eventType}>`;
206
- return `@Output() ${event.name}: EventEmitter<${outputType}> = new EventEmitter();`;
157
+ /**
158
+ * Notes on the generated output:
159
+ * - We disable @angular-eslint/no-inputs-metadata-property, so that
160
+ * Angular does not complain about the inputs property. The output target
161
+ * uses the inputs property to define the inputs of the component instead of
162
+ * having to use the @Input decorator (and manually define the type and default value).
163
+ */
164
+ const output = `@ProxyCmp({${proxyCmpOptions.join(',')}\n})
165
+ @Component({
166
+ selector: '${tagName}',
167
+ changeDetection: ChangeDetectionStrategy.OnPush,
168
+ template: '<ng-content></ng-content>',
169
+ // eslint-disable-next-line @angular-eslint/no-inputs-metadata-property
170
+ inputs: [${formattedInputs}],
171
+ })
172
+ export class ${tagNameAsPascal} {
173
+ protected el: HTMLElement;
174
+ constructor(c: ChangeDetectorRef, r: ElementRef, protected z: NgZone) {
175
+ c.detach();
176
+ this.el = r.nativeElement;${hasOutputs
177
+ ? `
178
+ proxyOutputs(this, this.el, [${formattedOutputs}]);`
179
+ : ''}
180
+ }
181
+ }`;
182
+ return output;
207
183
  };
208
184
  /**
209
185
  * Sanitizes and formats the component event type.
@@ -261,8 +237,14 @@ const createComponentTypeDefinition = (tagNameAsPascal, events, componentCorePac
261
237
  });
262
238
  const eventTypes = publicEvents.map((event) => {
263
239
  const comment = createDocComment(event.docs);
240
+ let eventName = event.name;
241
+ if (event.name.includes('-')) {
242
+ // If an event name includes a dash, we need to wrap it in quotes.
243
+ // https://github.com/ionic-team/stencil-ds-output-targets/issues/212
244
+ eventName = `'${event.name}'`;
245
+ }
264
246
  return `${comment.length > 0 ? ` ${comment}` : ''}
265
- ${event.name}: EventEmitter<CustomEvent<${formatOutputType(tagNameAsPascal, event)}>>;`;
247
+ ${eventName}: EventEmitter<CustomEvent<${formatOutputType(tagNameAsPascal, event)}>>;`;
266
248
  });
267
249
  const interfaceDeclaration = `export declare interface ${tagNameAsPascal} extends Components.${tagNameAsPascal} {`;
268
250
  const typeDefinition = (eventTypeImports.length > 0 ? `${eventTypeImports + '\n\n'}` : '') +
@@ -393,7 +375,6 @@ function generateProxies(components, pkgData, outputTarget, rootDir) {
393
375
  'ElementRef',
394
376
  'EventEmitter',
395
377
  'NgZone',
396
- 'Output',
397
378
  ];
398
379
  /**
399
380
  * The collection of named imports from the angular-component-lib/utils.
@@ -450,7 +431,7 @@ ${createImportStatement(componentLibImports, './angular-component-lib/utils')}\n
450
431
  inputs.sort();
451
432
  const outputs = [];
452
433
  if (cmpMeta.events) {
453
- outputs.push(...cmpMeta.events.filter(filterInternalProps));
434
+ outputs.push(...cmpMeta.events.filter(filterInternalProps).map(mapPropName));
454
435
  }
455
436
  const methods = [];
456
437
  if (cmpMeta.methods) {
@@ -47,7 +47,6 @@ export function generateProxies(components, pkgData, outputTarget, rootDir) {
47
47
  'ElementRef',
48
48
  'EventEmitter',
49
49
  'NgZone',
50
- 'Output',
51
50
  ];
52
51
  /**
53
52
  * The collection of named imports from the angular-component-lib/utils.
@@ -104,7 +103,7 @@ ${createImportStatement(componentLibImports, './angular-component-lib/utils')}\n
104
103
  inputs.sort();
105
104
  const outputs = [];
106
105
  if (cmpMeta.events) {
107
- outputs.push(...cmpMeta.events.filter(filterInternalProps));
106
+ outputs.push(...cmpMeta.events.filter(filterInternalProps).map(mapPropName));
108
107
  }
109
108
  const methods = [];
110
109
  if (cmpMeta.methods) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@stencil/angular-output-target",
3
- "version": "0.6.1-dev.11667512184.13935f80",
3
+ "version": "0.6.1-dev.11669751385.1c42cc9f",
4
4
  "description": "Angular output target for @stencil/core components.",
5
5
  "main": "dist/index.cjs.js",
6
6
  "module": "dist/index.js",
@@ -58,5 +58,5 @@
58
58
  ],
59
59
  "testURL": "http://localhost"
60
60
  },
61
- "gitHead": "3935f8069bb24eea156c4c5901c94357b302f1f5"
61
+ "gitHead": "c42cc9fa407385abf8612cede969bf70d8786258"
62
62
  }