@stencil/angular-output-target 1.1.0 → 1.1.1

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.
@@ -5,14 +5,14 @@ import type { ComponentInputProperty, OutputType } from './types';
5
5
  *
6
6
  * @param tagName The tag name of the component.
7
7
  * @param inputs The inputs of the Stencil component (e.g. [{name: 'myInput', required: true]).
8
- * @param outputs The outputs/events of the Stencil component. (e.g. ['myOutput']).
9
8
  * @param methods The methods of the Stencil component. (e.g. ['myMethod']).
10
9
  * @param includeImportCustomElements Whether to define the component as a custom element.
11
10
  * @param standalone Whether to define the component as a standalone component.
12
11
  * @param inlineComponentProps List of properties that should be inlined into the component definition.
12
+ * @param events The events of the Stencil component for generating outputs.
13
13
  * @returns The component declaration as a string.
14
14
  */
15
- export declare const createAngularComponentDefinition: (tagName: string, inputs: readonly ComponentInputProperty[], outputs: readonly string[], methods: readonly string[], includeImportCustomElements?: boolean, standalone?: boolean, inlineComponentProps?: readonly ComponentCompilerProperty[]) => string;
15
+ export declare const createAngularComponentDefinition: (tagName: string, inputs: readonly ComponentInputProperty[], methods: readonly string[], includeImportCustomElements?: boolean, standalone?: boolean, inlineComponentProps?: readonly ComponentCompilerProperty[], events?: readonly ComponentCompilerEvent[]) => string;
16
16
  /**
17
17
  * Creates the component interface type definition.
18
18
  * @param outputType The output type.
@@ -48,15 +48,16 @@ function formatInputs(inputs) {
48
48
  *
49
49
  * @param tagName The tag name of the component.
50
50
  * @param inputs The inputs of the Stencil component (e.g. [{name: 'myInput', required: true]).
51
- * @param outputs The outputs/events of the Stencil component. (e.g. ['myOutput']).
52
51
  * @param methods The methods of the Stencil component. (e.g. ['myMethod']).
53
52
  * @param includeImportCustomElements Whether to define the component as a custom element.
54
53
  * @param standalone Whether to define the component as a standalone component.
55
54
  * @param inlineComponentProps List of properties that should be inlined into the component definition.
55
+ * @param events The events of the Stencil component for generating outputs.
56
56
  * @returns The component declaration as a string.
57
57
  */
58
- export const createAngularComponentDefinition = (tagName, inputs, outputs, methods, includeImportCustomElements = false, standalone = false, inlineComponentProps = []) => {
58
+ export const createAngularComponentDefinition = (tagName, inputs, methods, includeImportCustomElements = false, standalone = false, inlineComponentProps = [], events = []) => {
59
59
  const tagNameAsPascal = dashToPascalCase(tagName);
60
+ const outputs = events.filter((event) => !event.internal).map((event) => event.name);
60
61
  const hasInputs = inputs.length > 0;
61
62
  const hasOutputs = outputs.length > 0;
62
63
  const hasMethods = methods.length > 0;
@@ -85,7 +86,18 @@ export const createAngularComponentDefinition = (tagName, inputs, outputs, metho
85
86
  standaloneOption = `\n standalone: false`;
86
87
  }
87
88
  const propertyDeclarations = inlineComponentProps.map((m) => createPropertyDeclaration(m, `Components.${tagNameAsPascal}['${m.name}']`, true));
88
- const propertiesDeclarationText = [`protected el: HTML${tagNameAsPascal}Element;`, ...propertyDeclarations].join('\n ');
89
+ const outputDeclarations = events
90
+ .filter((event) => !event.internal)
91
+ .map((event) => {
92
+ const camelCaseOutput = event.name.replace(/-([a-z])/g, (match, letter) => letter.toUpperCase());
93
+ const outputType = `EventEmitter<CustomEvent<${formatOutputType(tagNameAsPascal, event)}>>`;
94
+ return `@Output() ${camelCaseOutput} = new ${outputType}();`;
95
+ });
96
+ const propertiesDeclarationText = [
97
+ `protected el: HTML${tagNameAsPascal}Element;`,
98
+ ...propertyDeclarations,
99
+ ...outputDeclarations,
100
+ ].join('\n ');
89
101
  /**
90
102
  * Notes on the generated output:
91
103
  * - We disable @angular-eslint/no-inputs-metadata-property, so that
@@ -99,16 +111,13 @@ export const createAngularComponentDefinition = (tagName, inputs, outputs, metho
99
111
  changeDetection: ChangeDetectionStrategy.OnPush,
100
112
  template: '<ng-content></ng-content>',
101
113
  // eslint-disable-next-line @angular-eslint/no-inputs-metadata-property
102
- inputs: [${formattedInputs}],${standaloneOption}
114
+ inputs: [${formattedInputs}],${hasOutputs ? `\n outputs: [${formattedOutputs}],` : ''}${standaloneOption}
103
115
  })
104
116
  export class ${tagNameAsPascal} {
105
117
  ${propertiesDeclarationText}
106
118
  constructor(c: ChangeDetectorRef, r: ElementRef, protected z: NgZone) {
107
119
  c.detach();
108
- this.el = r.nativeElement;${hasOutputs
109
- ? `
110
- proxyOutputs(this, this.el, [${formattedOutputs}]);`
111
- : ''}
120
+ this.el = r.nativeElement;
112
121
  }
113
122
  }`;
114
123
  return output;
package/dist/index.cjs.js CHANGED
@@ -194,15 +194,16 @@ function formatInputs(inputs) {
194
194
  *
195
195
  * @param tagName The tag name of the component.
196
196
  * @param inputs The inputs of the Stencil component (e.g. [{name: 'myInput', required: true]).
197
- * @param outputs The outputs/events of the Stencil component. (e.g. ['myOutput']).
198
197
  * @param methods The methods of the Stencil component. (e.g. ['myMethod']).
199
198
  * @param includeImportCustomElements Whether to define the component as a custom element.
200
199
  * @param standalone Whether to define the component as a standalone component.
201
200
  * @param inlineComponentProps List of properties that should be inlined into the component definition.
201
+ * @param events The events of the Stencil component for generating outputs.
202
202
  * @returns The component declaration as a string.
203
203
  */
204
- const createAngularComponentDefinition = (tagName, inputs, outputs, methods, includeImportCustomElements = false, standalone = false, inlineComponentProps = []) => {
204
+ const createAngularComponentDefinition = (tagName, inputs, methods, includeImportCustomElements = false, standalone = false, inlineComponentProps = [], events = []) => {
205
205
  const tagNameAsPascal = dashToPascalCase(tagName);
206
+ const outputs = events.filter((event) => !event.internal).map((event) => event.name);
206
207
  const hasInputs = inputs.length > 0;
207
208
  const hasOutputs = outputs.length > 0;
208
209
  const hasMethods = methods.length > 0;
@@ -231,7 +232,18 @@ const createAngularComponentDefinition = (tagName, inputs, outputs, methods, inc
231
232
  standaloneOption = `\n standalone: false`;
232
233
  }
233
234
  const propertyDeclarations = inlineComponentProps.map((m) => createPropertyDeclaration(m, `Components.${tagNameAsPascal}['${m.name}']`, true));
234
- const propertiesDeclarationText = [`protected el: HTML${tagNameAsPascal}Element;`, ...propertyDeclarations].join('\n ');
235
+ const outputDeclarations = events
236
+ .filter((event) => !event.internal)
237
+ .map((event) => {
238
+ const camelCaseOutput = event.name.replace(/-([a-z])/g, (match, letter) => letter.toUpperCase());
239
+ const outputType = `EventEmitter<CustomEvent<${formatOutputType(tagNameAsPascal, event)}>>`;
240
+ return `@Output() ${camelCaseOutput} = new ${outputType}();`;
241
+ });
242
+ const propertiesDeclarationText = [
243
+ `protected el: HTML${tagNameAsPascal}Element;`,
244
+ ...propertyDeclarations,
245
+ ...outputDeclarations,
246
+ ].join('\n ');
235
247
  /**
236
248
  * Notes on the generated output:
237
249
  * - We disable @angular-eslint/no-inputs-metadata-property, so that
@@ -245,16 +257,13 @@ const createAngularComponentDefinition = (tagName, inputs, outputs, methods, inc
245
257
  changeDetection: ChangeDetectionStrategy.OnPush,
246
258
  template: '<ng-content></ng-content>',
247
259
  // eslint-disable-next-line @angular-eslint/no-inputs-metadata-property
248
- inputs: [${formattedInputs}],${standaloneOption}
260
+ inputs: [${formattedInputs}],${hasOutputs ? `\n outputs: [${formattedOutputs}],` : ''}${standaloneOption}
249
261
  })
250
262
  export class ${tagNameAsPascal} {
251
263
  ${propertiesDeclarationText}
252
264
  constructor(c: ChangeDetectorRef, r: ElementRef, protected z: NgZone) {
253
265
  c.detach();
254
- this.el = r.nativeElement;${hasOutputs
255
- ? `
256
- proxyOutputs(this, this.el, [${formattedOutputs}]);`
257
- : ''}
266
+ this.el = r.nativeElement;
258
267
  }
259
268
  }`;
260
269
  return output;
@@ -497,16 +506,13 @@ function generateProxies(components, pkgData, outputTarget, rootDir) {
497
506
  */
498
507
  const angularCoreImports = ['ChangeDetectionStrategy', 'ChangeDetectorRef', 'Component', 'ElementRef'];
499
508
  if (includeOutputImports) {
500
- angularCoreImports.push('EventEmitter');
509
+ angularCoreImports.push('EventEmitter', 'Output');
501
510
  }
502
511
  angularCoreImports.push('NgZone');
503
512
  /**
504
513
  * The collection of named imports from the angular-component-lib/utils.
505
514
  */
506
515
  const componentLibImports = ['ProxyCmp'];
507
- if (includeOutputImports) {
508
- componentLibImports.push('proxyOutputs');
509
- }
510
516
  if (includeSingleComponentAngularModules) {
511
517
  angularCoreImports.push('NgModule');
512
518
  }
@@ -565,10 +571,6 @@ ${createImportStatement(componentLibImports, './angular-component-lib/utils')}\n
565
571
  inputs.push(...cmpMeta.virtualProperties.map(mapInputProp));
566
572
  }
567
573
  const orderedInputs = sortBy(inputs, (cip) => cip.name);
568
- const outputs = [];
569
- if (cmpMeta.events) {
570
- outputs.push(...cmpMeta.events.filter(filterInternalProps).map(mapPropName));
571
- }
572
574
  const methods = [];
573
575
  if (cmpMeta.methods) {
574
576
  methods.push(...cmpMeta.methods.filter(filterInternalProps).map(mapPropName));
@@ -580,7 +582,7 @@ ${createImportStatement(componentLibImports, './angular-component-lib/utils')}\n
580
582
  * 2. Optionally the @NgModule decorated class (if includeSingleComponentAngularModules is true)
581
583
  * 3. The component interface (using declaration merging for types).
582
584
  */
583
- const componentDefinition = createAngularComponentDefinition(cmpMeta.tagName, orderedInputs, outputs, methods, isCustomElementsBuild, isStandaloneBuild, inlineComponentProps);
585
+ const componentDefinition = createAngularComponentDefinition(cmpMeta.tagName, orderedInputs, methods, isCustomElementsBuild, isStandaloneBuild, inlineComponentProps, cmpMeta.events || []);
584
586
  const moduleDefinition = generateAngularModuleForComponent(cmpMeta.tagName);
585
587
  const componentTypeDefinition = createComponentTypeDefinition(outputType, tagNameAsPascal, cmpMeta.events, componentCorePackage, customElementsDir);
586
588
  proxyFileOutput.push(componentDefinition, '\n');
package/dist/index.js CHANGED
@@ -186,15 +186,16 @@ function formatInputs(inputs) {
186
186
  *
187
187
  * @param tagName The tag name of the component.
188
188
  * @param inputs The inputs of the Stencil component (e.g. [{name: 'myInput', required: true]).
189
- * @param outputs The outputs/events of the Stencil component. (e.g. ['myOutput']).
190
189
  * @param methods The methods of the Stencil component. (e.g. ['myMethod']).
191
190
  * @param includeImportCustomElements Whether to define the component as a custom element.
192
191
  * @param standalone Whether to define the component as a standalone component.
193
192
  * @param inlineComponentProps List of properties that should be inlined into the component definition.
193
+ * @param events The events of the Stencil component for generating outputs.
194
194
  * @returns The component declaration as a string.
195
195
  */
196
- const createAngularComponentDefinition = (tagName, inputs, outputs, methods, includeImportCustomElements = false, standalone = false, inlineComponentProps = []) => {
196
+ const createAngularComponentDefinition = (tagName, inputs, methods, includeImportCustomElements = false, standalone = false, inlineComponentProps = [], events = []) => {
197
197
  const tagNameAsPascal = dashToPascalCase(tagName);
198
+ const outputs = events.filter((event) => !event.internal).map((event) => event.name);
198
199
  const hasInputs = inputs.length > 0;
199
200
  const hasOutputs = outputs.length > 0;
200
201
  const hasMethods = methods.length > 0;
@@ -223,7 +224,18 @@ const createAngularComponentDefinition = (tagName, inputs, outputs, methods, inc
223
224
  standaloneOption = `\n standalone: false`;
224
225
  }
225
226
  const propertyDeclarations = inlineComponentProps.map((m) => createPropertyDeclaration(m, `Components.${tagNameAsPascal}['${m.name}']`, true));
226
- const propertiesDeclarationText = [`protected el: HTML${tagNameAsPascal}Element;`, ...propertyDeclarations].join('\n ');
227
+ const outputDeclarations = events
228
+ .filter((event) => !event.internal)
229
+ .map((event) => {
230
+ const camelCaseOutput = event.name.replace(/-([a-z])/g, (match, letter) => letter.toUpperCase());
231
+ const outputType = `EventEmitter<CustomEvent<${formatOutputType(tagNameAsPascal, event)}>>`;
232
+ return `@Output() ${camelCaseOutput} = new ${outputType}();`;
233
+ });
234
+ const propertiesDeclarationText = [
235
+ `protected el: HTML${tagNameAsPascal}Element;`,
236
+ ...propertyDeclarations,
237
+ ...outputDeclarations,
238
+ ].join('\n ');
227
239
  /**
228
240
  * Notes on the generated output:
229
241
  * - We disable @angular-eslint/no-inputs-metadata-property, so that
@@ -237,16 +249,13 @@ const createAngularComponentDefinition = (tagName, inputs, outputs, methods, inc
237
249
  changeDetection: ChangeDetectionStrategy.OnPush,
238
250
  template: '<ng-content></ng-content>',
239
251
  // eslint-disable-next-line @angular-eslint/no-inputs-metadata-property
240
- inputs: [${formattedInputs}],${standaloneOption}
252
+ inputs: [${formattedInputs}],${hasOutputs ? `\n outputs: [${formattedOutputs}],` : ''}${standaloneOption}
241
253
  })
242
254
  export class ${tagNameAsPascal} {
243
255
  ${propertiesDeclarationText}
244
256
  constructor(c: ChangeDetectorRef, r: ElementRef, protected z: NgZone) {
245
257
  c.detach();
246
- this.el = r.nativeElement;${hasOutputs
247
- ? `
248
- proxyOutputs(this, this.el, [${formattedOutputs}]);`
249
- : ''}
258
+ this.el = r.nativeElement;
250
259
  }
251
260
  }`;
252
261
  return output;
@@ -489,16 +498,13 @@ function generateProxies(components, pkgData, outputTarget, rootDir) {
489
498
  */
490
499
  const angularCoreImports = ['ChangeDetectionStrategy', 'ChangeDetectorRef', 'Component', 'ElementRef'];
491
500
  if (includeOutputImports) {
492
- angularCoreImports.push('EventEmitter');
501
+ angularCoreImports.push('EventEmitter', 'Output');
493
502
  }
494
503
  angularCoreImports.push('NgZone');
495
504
  /**
496
505
  * The collection of named imports from the angular-component-lib/utils.
497
506
  */
498
507
  const componentLibImports = ['ProxyCmp'];
499
- if (includeOutputImports) {
500
- componentLibImports.push('proxyOutputs');
501
- }
502
508
  if (includeSingleComponentAngularModules) {
503
509
  angularCoreImports.push('NgModule');
504
510
  }
@@ -557,10 +563,6 @@ ${createImportStatement(componentLibImports, './angular-component-lib/utils')}\n
557
563
  inputs.push(...cmpMeta.virtualProperties.map(mapInputProp));
558
564
  }
559
565
  const orderedInputs = sortBy(inputs, (cip) => cip.name);
560
- const outputs = [];
561
- if (cmpMeta.events) {
562
- outputs.push(...cmpMeta.events.filter(filterInternalProps).map(mapPropName));
563
- }
564
566
  const methods = [];
565
567
  if (cmpMeta.methods) {
566
568
  methods.push(...cmpMeta.methods.filter(filterInternalProps).map(mapPropName));
@@ -572,7 +574,7 @@ ${createImportStatement(componentLibImports, './angular-component-lib/utils')}\n
572
574
  * 2. Optionally the @NgModule decorated class (if includeSingleComponentAngularModules is true)
573
575
  * 3. The component interface (using declaration merging for types).
574
576
  */
575
- const componentDefinition = createAngularComponentDefinition(cmpMeta.tagName, orderedInputs, outputs, methods, isCustomElementsBuild, isStandaloneBuild, inlineComponentProps);
577
+ const componentDefinition = createAngularComponentDefinition(cmpMeta.tagName, orderedInputs, methods, isCustomElementsBuild, isStandaloneBuild, inlineComponentProps, cmpMeta.events || []);
576
578
  const moduleDefinition = generateAngularModuleForComponent(cmpMeta.tagName);
577
579
  const componentTypeDefinition = createComponentTypeDefinition(outputType, tagNameAsPascal, cmpMeta.events, componentCorePackage, customElementsDir);
578
580
  proxyFileOutput.push(componentDefinition, '\n');
@@ -49,16 +49,13 @@ export function generateProxies(components, pkgData, outputTarget, rootDir) {
49
49
  */
50
50
  const angularCoreImports = ['ChangeDetectionStrategy', 'ChangeDetectorRef', 'Component', 'ElementRef'];
51
51
  if (includeOutputImports) {
52
- angularCoreImports.push('EventEmitter');
52
+ angularCoreImports.push('EventEmitter', 'Output');
53
53
  }
54
54
  angularCoreImports.push('NgZone');
55
55
  /**
56
56
  * The collection of named imports from the angular-component-lib/utils.
57
57
  */
58
58
  const componentLibImports = ['ProxyCmp'];
59
- if (includeOutputImports) {
60
- componentLibImports.push('proxyOutputs');
61
- }
62
59
  if (includeSingleComponentAngularModules) {
63
60
  angularCoreImports.push('NgModule');
64
61
  }
@@ -117,10 +114,6 @@ ${createImportStatement(componentLibImports, './angular-component-lib/utils')}\n
117
114
  inputs.push(...cmpMeta.virtualProperties.map(mapInputProp));
118
115
  }
119
116
  const orderedInputs = sortBy(inputs, (cip) => cip.name);
120
- const outputs = [];
121
- if (cmpMeta.events) {
122
- outputs.push(...cmpMeta.events.filter(filterInternalProps).map(mapPropName));
123
- }
124
117
  const methods = [];
125
118
  if (cmpMeta.methods) {
126
119
  methods.push(...cmpMeta.methods.filter(filterInternalProps).map(mapPropName));
@@ -132,7 +125,7 @@ ${createImportStatement(componentLibImports, './angular-component-lib/utils')}\n
132
125
  * 2. Optionally the @NgModule decorated class (if includeSingleComponentAngularModules is true)
133
126
  * 3. The component interface (using declaration merging for types).
134
127
  */
135
- const componentDefinition = createAngularComponentDefinition(cmpMeta.tagName, orderedInputs, outputs, methods, isCustomElementsBuild, isStandaloneBuild, inlineComponentProps);
128
+ const componentDefinition = createAngularComponentDefinition(cmpMeta.tagName, orderedInputs, methods, isCustomElementsBuild, isStandaloneBuild, inlineComponentProps, cmpMeta.events || []);
136
129
  const moduleDefinition = generateAngularModuleForComponent(cmpMeta.tagName);
137
130
  const componentTypeDefinition = createComponentTypeDefinition(outputType, tagNameAsPascal, cmpMeta.events, componentCorePackage, customElementsDir);
138
131
  proxyFileOutput.push(componentDefinition, '\n');
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@stencil/angular-output-target",
3
- "version": "1.1.0",
3
+ "version": "1.1.1",
4
4
  "description": "Angular output target for @stencil/core components.",
5
5
  "main": "dist/index.cjs.js",
6
6
  "module": "dist/index.js",