@stencil/angular-output-target 0.8.1-dev.11690825475.1243803f → 0.8.2

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.
package/README.md CHANGED
@@ -27,7 +27,6 @@ export const config: Config = {
27
27
  outputTargets: [
28
28
  angularOutputTarget({
29
29
  componentCorePackage: 'component-library',
30
- outputType: 'component',
31
30
  directivesProxyFile: '../component-library-angular/src/directives/proxies.ts',
32
31
  directivesArrayFile: '../component-library-angular/src/directives/index.ts',
33
32
  }),
@@ -48,5 +47,5 @@ export const config: Config = {
48
47
  | `directivesArrayFile` | The output file of a constant of all the generated component wrapper classes. Used for easily declaring and exporting the generated components from an `NgModule`. This file path should point to a location within your Angular library/project. |
49
48
  | `valueAccessorConfigs` | The configuration object for how individual web components behave with Angular control value accessors. |
50
49
  | `excludeComponents` | An array of tag names to exclude from generating component wrappers for. This is helpful when have a custom framework implementation of a specific component or need to extend the base component wrapper behavior. |
51
- | `outputType` | Specifies the type of output to be generated. It can take one of the following values: <br />1. `component`: Generates all the component wrappers to be declared on an Angular module. This option is required for Stencil projects using the `dist` hydrated output.<br /> 2. `scam`: Generates a separate Angular module for each component.<br /> 3. `standalone`: Generates standalone component wrappers.<br /> Both `scam` and `standalone` options are compatible with the `dist-custom-elements` output. Developers **must** set a `customElementsDir` in the output target config when using either 'scam' or 'standalone'.<br />Note: Please choose the appropriate `outputType` based on your project's requirements and the desired output structure. |
52
- | `customElementsDir` | This is the directory where the custom elements are imported from when using the [Custom Elements Bundle](https://stenciljs.com/docs/custom-elements). Required to be set for `outputType: "scam"` or `outputType: "standalone"`. |
50
+ | `outputType` | Specifies the type of output to be generated. It can take one of the following values: <br />1. `component`: Generates all the component wrappers to be declared on an Angular module. This option is required for Stencil projects using the `dist` hydrated output.<br /> 2. `scam`: Generates a separate Angular module for each component.<br /> 3. `standalone`: Generates standalone component wrappers.<br /> Both `scam` and `standalone` options are compatible with the `dist-custom-elements` output. <br />Note: Please choose the appropriate `outputType` based on your project's requirements and the desired output structure. Defaults to `component`. |
51
+ | `customElementsDir` | This is the directory where the custom elements are imported from when using the [Custom Elements Bundle](https://stenciljs.com/docs/custom-elements). Defaults to the `components` directory. Only applies for `outputType: "scam"` or `outputType: "standalone"`. |
@@ -1,4 +1,5 @@
1
1
  import type { ComponentCompilerEvent } from '@stencil/core/internal';
2
+ import type { OutputType } from './types';
2
3
  /**
3
4
  * Creates an Angular component declaration from formatted Stencil compiler metadata.
4
5
  *
@@ -13,10 +14,11 @@ import type { ComponentCompilerEvent } from '@stencil/core/internal';
13
14
  export declare const createAngularComponentDefinition: (tagName: string, inputs: readonly string[], outputs: readonly string[], methods: readonly string[], includeImportCustomElements?: boolean, standalone?: boolean) => string;
14
15
  /**
15
16
  * Creates the component interface type definition.
17
+ * @param outputType The output type.
16
18
  * @param tagNameAsPascal The tag name as PascalCase.
17
19
  * @param events The events to generate the interface properties for.
18
20
  * @param componentCorePackage The component core package.
19
21
  * @param customElementsDir The custom elements directory.
20
22
  * @returns The component interface type definition as a string.
21
23
  */
22
- export declare const createComponentTypeDefinition: (tagNameAsPascal: string, events: readonly ComponentCompilerEvent[], componentCorePackage: string, customElementsDir?: string | undefined) => string;
24
+ export declare const createComponentTypeDefinition: (outputType: OutputType, tagNameAsPascal: string, events: readonly ComponentCompilerEvent[], componentCorePackage: string, customElementsDir?: string | undefined) => string;
@@ -70,6 +70,7 @@ export class ${tagNameAsPascal} {
70
70
  * @returns The sanitized event type as a string.
71
71
  */
72
72
  const formatOutputType = (componentClassName, event) => {
73
+ const prefix = `I${componentClassName}`;
73
74
  /**
74
75
  * The original attribute contains the original type defined by the devs.
75
76
  * This regexp normalizes the reference, by removing linebreaks,
@@ -78,11 +79,24 @@ const formatOutputType = (componentClassName, event) => {
78
79
  return Object.entries(event.complexType.references)
79
80
  .filter(([_, refObject]) => refObject.location === 'local' || refObject.location === 'import')
80
81
  .reduce((type, [src, dst]) => {
81
- const renamedType = `I${componentClassName}${type}`;
82
+ let renamedType = type;
83
+ if (!type.startsWith(prefix)) {
84
+ renamedType = `I${componentClassName}${type}`;
85
+ }
82
86
  return (renamedType
83
87
  .replace(new RegExp(`^${src}$`, 'g'), `${dst}`)
84
88
  // Capture all instances of the `src` field surrounded by non-word characters on each side and join them.
85
- .replace(new RegExp(`([^\\w])${src}([^\\w])`, 'g'), (v, p1, p2) => [p1, dst, p2].join('')));
89
+ .replace(new RegExp(`([^\\w])${src}([^\\w])`, 'g'), (v, p1, p2) => {
90
+ if ((dst === null || dst === void 0 ? void 0 : dst.location) === 'import') {
91
+ /**
92
+ * Replaces a complex type reference within a generic type.
93
+ * For example, remapping a type like `EventEmitter<CustomEvent<MyEvent<T>>>` to
94
+ * `EventEmitter<CustomEvent<IMyComponentMyEvent<IMyComponentT>>>`.
95
+ */
96
+ return [p1, `I${componentClassName}${v.substring(1, v.length - 1)}`, p2].join('');
97
+ }
98
+ return [p1, dst, p2].join('');
99
+ }));
86
100
  }, event.complexType.original
87
101
  .replace(/\n/g, ' ')
88
102
  .replace(/\s{2,}/g, ' ')
@@ -103,17 +117,19 @@ const createDocComment = (doc) => {
103
117
  };
104
118
  /**
105
119
  * Creates the component interface type definition.
120
+ * @param outputType The output type.
106
121
  * @param tagNameAsPascal The tag name as PascalCase.
107
122
  * @param events The events to generate the interface properties for.
108
123
  * @param componentCorePackage The component core package.
109
124
  * @param customElementsDir The custom elements directory.
110
125
  * @returns The component interface type definition as a string.
111
126
  */
112
- export const createComponentTypeDefinition = (tagNameAsPascal, events, componentCorePackage, customElementsDir) => {
127
+ export const createComponentTypeDefinition = (outputType, tagNameAsPascal, events, componentCorePackage, customElementsDir) => {
113
128
  const publicEvents = events.filter((ev) => !ev.internal);
114
129
  const eventTypeImports = createComponentEventTypeImports(tagNameAsPascal, publicEvents, {
115
130
  componentCorePackage,
116
131
  customElementsDir,
132
+ outputType,
117
133
  });
118
134
  const eventTypes = publicEvents.map((event) => {
119
135
  const comment = createDocComment(event.docs);
package/dist/index.cjs.js CHANGED
@@ -9,6 +9,11 @@ function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'defau
9
9
 
10
10
  var path__default = /*#__PURE__*/_interopDefaultLegacy(path);
11
11
 
12
+ const OutputTypes = {
13
+ Component: 'component',
14
+ Scam: 'scam',
15
+ Standalone: 'standalone',
16
+ };
12
17
  const toLowerCase = (str) => str.toLowerCase();
13
18
  const dashToPascalCase = (str) => toLowerCase(str)
14
19
  .split('-')
@@ -100,6 +105,14 @@ const createImportStatement = (imports, module) => {
100
105
  }
101
106
  return `import { ${imports.join(', ')} } from '${module}';`;
102
107
  };
108
+ /**
109
+ * Checks if the outputType is for the custom elements build.
110
+ * @param outputType The output type.
111
+ * @returns `true` if the output type is for the custom elements build.
112
+ */
113
+ const isOutputTypeCustomElementsBuild = (outputType) => {
114
+ return outputType === OutputTypes.Standalone || outputType === OutputTypes.Scam;
115
+ };
103
116
  /**
104
117
  * Creates the collection of import statements for a component based on the component's events type dependencies.
105
118
  * @param componentTagName The tag name of the component (pascal case).
@@ -111,7 +124,7 @@ const createComponentEventTypeImports = (componentTagName, events, options) => {
111
124
  const { componentCorePackage, customElementsDir } = options;
112
125
  const imports = [];
113
126
  const namedImports = new Set();
114
- const isCustomElementsBuild = customElementsDir !== undefined;
127
+ const isCustomElementsBuild = isOutputTypeCustomElementsBuild(options.outputType);
115
128
  const importPathName = normalizePath(componentCorePackage) + (isCustomElementsBuild ? `/${customElementsDir}` : '');
116
129
  events.forEach((event) => {
117
130
  Object.entries(event.complexType.references).forEach(([typeName, refObject]) => {
@@ -202,6 +215,7 @@ export class ${tagNameAsPascal} {
202
215
  * @returns The sanitized event type as a string.
203
216
  */
204
217
  const formatOutputType = (componentClassName, event) => {
218
+ const prefix = `I${componentClassName}`;
205
219
  /**
206
220
  * The original attribute contains the original type defined by the devs.
207
221
  * This regexp normalizes the reference, by removing linebreaks,
@@ -210,11 +224,24 @@ const formatOutputType = (componentClassName, event) => {
210
224
  return Object.entries(event.complexType.references)
211
225
  .filter(([_, refObject]) => refObject.location === 'local' || refObject.location === 'import')
212
226
  .reduce((type, [src, dst]) => {
213
- const renamedType = `I${componentClassName}${type}`;
227
+ let renamedType = type;
228
+ if (!type.startsWith(prefix)) {
229
+ renamedType = `I${componentClassName}${type}`;
230
+ }
214
231
  return (renamedType
215
232
  .replace(new RegExp(`^${src}$`, 'g'), `${dst}`)
216
233
  // Capture all instances of the `src` field surrounded by non-word characters on each side and join them.
217
- .replace(new RegExp(`([^\\w])${src}([^\\w])`, 'g'), (v, p1, p2) => [p1, dst, p2].join('')));
234
+ .replace(new RegExp(`([^\\w])${src}([^\\w])`, 'g'), (v, p1, p2) => {
235
+ if ((dst === null || dst === void 0 ? void 0 : dst.location) === 'import') {
236
+ /**
237
+ * Replaces a complex type reference within a generic type.
238
+ * For example, remapping a type like `EventEmitter<CustomEvent<MyEvent<T>>>` to
239
+ * `EventEmitter<CustomEvent<IMyComponentMyEvent<IMyComponentT>>>`.
240
+ */
241
+ return [p1, `I${componentClassName}${v.substring(1, v.length - 1)}`, p2].join('');
242
+ }
243
+ return [p1, dst, p2].join('');
244
+ }));
218
245
  }, event.complexType.original
219
246
  .replace(/\n/g, ' ')
220
247
  .replace(/\s{2,}/g, ' ')
@@ -235,17 +262,19 @@ const createDocComment = (doc) => {
235
262
  };
236
263
  /**
237
264
  * Creates the component interface type definition.
265
+ * @param outputType The output type.
238
266
  * @param tagNameAsPascal The tag name as PascalCase.
239
267
  * @param events The events to generate the interface properties for.
240
268
  * @param componentCorePackage The component core package.
241
269
  * @param customElementsDir The custom elements directory.
242
270
  * @returns The component interface type definition as a string.
243
271
  */
244
- const createComponentTypeDefinition = (tagNameAsPascal, events, componentCorePackage, customElementsDir) => {
272
+ const createComponentTypeDefinition = (outputType, tagNameAsPascal, events, componentCorePackage, customElementsDir) => {
245
273
  const publicEvents = events.filter((ev) => !ev.internal);
246
274
  const eventTypeImports = createComponentEventTypeImports(tagNameAsPascal, publicEvents, {
247
275
  componentCorePackage,
248
276
  customElementsDir,
277
+ outputType,
249
278
  });
250
279
  const eventTypes = publicEvents.map((event) => {
251
280
  const comment = createDocComment(event.docs);
@@ -393,11 +422,11 @@ async function copyResources$1(config, outputTarget) {
393
422
  function generateProxies(components, pkgData, outputTarget, rootDir) {
394
423
  const distTypesDir = path__default['default'].dirname(pkgData.types);
395
424
  const dtsFilePath = path__default['default'].join(rootDir, distTypesDir, GENERATED_DTS);
425
+ const { outputType } = outputTarget;
396
426
  const componentsTypeFile = relativeImport(outputTarget.directivesProxyFile, dtsFilePath, '.d.ts');
397
- const includeSingleComponentAngularModules = outputTarget.outputType === 'scam';
398
- const includeSingleComponentAngularComponents = outputTarget.outputType === 'standalone';
399
- const isCustomElementsBuild = outputTarget.customElementsDir !== undefined;
400
- const isStandaloneBuild = outputTarget.outputType === 'standalone';
427
+ const includeSingleComponentAngularModules = outputType === OutputTypes.Scam;
428
+ const isCustomElementsBuild = isOutputTypeCustomElementsBuild(outputType);
429
+ const isStandaloneBuild = outputType === OutputTypes.Standalone;
401
430
  const includeOutputImports = components.some((component) => component.events.some((event) => !event.internal));
402
431
  /**
403
432
  * The collection of named imports from @angular/core.
@@ -439,9 +468,9 @@ ${createImportStatement(componentLibImports, './angular-component-lib/utils')}\n
439
468
  let sourceImports = '';
440
469
  /**
441
470
  * Build an array of Custom Elements build imports and namespace them
442
- * so that they do not conflict with the React wrapper names. For example,
471
+ * so that they do not conflict with the Angular wrapper names. For example,
443
472
  * IonButton would be imported as IonButtonCmp so as to not conflict with the
444
- * IonButton React Component that takes in the Web Component as a parameter.
473
+ * IonButton Angular Component that takes in the Web Component as a parameter.
445
474
  */
446
475
  if (isCustomElementsBuild && outputTarget.componentCorePackage !== undefined) {
447
476
  const cmpImports = components.map((component) => {
@@ -450,16 +479,6 @@ ${createImportStatement(componentLibImports, './angular-component-lib/utils')}\n
450
479
  });
451
480
  sourceImports = cmpImports.join('\n');
452
481
  }
453
- if (!isCustomElementsBuild) {
454
- if (includeSingleComponentAngularModules) {
455
- // Generating Angular modules is only supported in the dist-custom-elements build
456
- throw new Error('Generating single component Angular modules requires the "customElementsDir" option to be set.');
457
- }
458
- if (includeSingleComponentAngularComponents) {
459
- // Generates Angular standalone components is only supported in the dist-custom-elements build
460
- throw new Error('Generating standalone Angular components requires the "customElementsDir" option to be set.');
461
- }
462
- }
463
482
  const proxyFileOutput = [];
464
483
  const filterInternalProps = (prop) => !prop.internal;
465
484
  const mapPropName = (prop) => prop.name;
@@ -490,7 +509,7 @@ ${createImportStatement(componentLibImports, './angular-component-lib/utils')}\n
490
509
  */
491
510
  const componentDefinition = createAngularComponentDefinition(cmpMeta.tagName, inputs, outputs, methods, isCustomElementsBuild, isStandaloneBuild);
492
511
  const moduleDefinition = generateAngularModuleForComponent(cmpMeta.tagName);
493
- const componentTypeDefinition = createComponentTypeDefinition(tagNameAsPascal, cmpMeta.events, componentCorePackage, customElementsDir);
512
+ const componentTypeDefinition = createComponentTypeDefinition(outputType, tagNameAsPascal, cmpMeta.events, componentCorePackage, customElementsDir);
494
513
  proxyFileOutput.push(componentDefinition, '\n');
495
514
  if (includeSingleComponentAngularModules) {
496
515
  proxyFileOutput.push(moduleDefinition, '\n');
@@ -503,20 +522,23 @@ ${createImportStatement(componentLibImports, './angular-component-lib/utils')}\n
503
522
  const GENERATED_DTS = 'components.d.ts';
504
523
  const IMPORT_TYPES = 'Components';
505
524
 
506
- const angularOutputTarget = (outputTarget) => ({
507
- type: 'custom',
508
- name: 'angular-library',
509
- validate(config) {
510
- return normalizeOutputTarget(config, outputTarget);
511
- },
512
- async generator(config, compilerCtx, buildCtx) {
513
- const timespan = buildCtx.createTimeSpan(`generate angular proxies started`, true);
514
- await angularDirectiveProxyOutput(compilerCtx, outputTarget, buildCtx.components, config);
515
- timespan.finish(`generate angular proxies finished`);
516
- },
517
- });
525
+ const angularOutputTarget = (outputTarget) => {
526
+ let validatedOutputTarget;
527
+ return {
528
+ type: 'custom',
529
+ name: 'angular-library',
530
+ validate(config) {
531
+ validatedOutputTarget = normalizeOutputTarget(config, outputTarget);
532
+ },
533
+ async generator(config, compilerCtx, buildCtx) {
534
+ const timespan = buildCtx.createTimeSpan(`generate angular proxies started`, true);
535
+ await angularDirectiveProxyOutput(compilerCtx, validatedOutputTarget, buildCtx.components, config);
536
+ timespan.finish(`generate angular proxies finished`);
537
+ },
538
+ };
539
+ };
518
540
  function normalizeOutputTarget(config, outputTarget) {
519
- const results = Object.assign(Object.assign({}, outputTarget), { excludeComponents: outputTarget.excludeComponents || [], valueAccessorConfigs: outputTarget.valueAccessorConfigs || [] });
541
+ const results = Object.assign(Object.assign({}, outputTarget), { excludeComponents: outputTarget.excludeComponents || [], valueAccessorConfigs: outputTarget.valueAccessorConfigs || [], customElementsDir: outputTarget.customElementsDir || 'components', outputType: outputTarget.outputType || OutputTypes.Component });
520
542
  if (config.rootDir == null) {
521
543
  throw new Error('rootDir is not set and it should be set by stencil itself');
522
544
  }
@@ -532,8 +554,8 @@ function normalizeOutputTarget(config, outputTarget) {
532
554
  if (outputTarget.includeSingleComponentAngularModules !== undefined) {
533
555
  throw new Error("The 'includeSingleComponentAngularModules' option has been removed. Please use 'outputType' instead.");
534
556
  }
535
- if (outputTarget.outputType === 'scam') {
536
- console.warn('**Experimental**: outputType: "scam" is a developer preview feature and may change or be removed in the future.');
557
+ if (outputTarget.outputType === OutputTypes.Scam) {
558
+ console.warn(`**Experimental**: outputType: "${OutputTypes.Scam}" is a developer preview feature and may change or be removed in the future.`);
537
559
  }
538
560
  return results;
539
561
  }
package/dist/index.js CHANGED
@@ -1,6 +1,11 @@
1
1
  import path from 'path';
2
2
  import { EOL } from 'os';
3
3
 
4
+ const OutputTypes = {
5
+ Component: 'component',
6
+ Scam: 'scam',
7
+ Standalone: 'standalone',
8
+ };
4
9
  const toLowerCase = (str) => str.toLowerCase();
5
10
  const dashToPascalCase = (str) => toLowerCase(str)
6
11
  .split('-')
@@ -92,6 +97,14 @@ const createImportStatement = (imports, module) => {
92
97
  }
93
98
  return `import { ${imports.join(', ')} } from '${module}';`;
94
99
  };
100
+ /**
101
+ * Checks if the outputType is for the custom elements build.
102
+ * @param outputType The output type.
103
+ * @returns `true` if the output type is for the custom elements build.
104
+ */
105
+ const isOutputTypeCustomElementsBuild = (outputType) => {
106
+ return outputType === OutputTypes.Standalone || outputType === OutputTypes.Scam;
107
+ };
95
108
  /**
96
109
  * Creates the collection of import statements for a component based on the component's events type dependencies.
97
110
  * @param componentTagName The tag name of the component (pascal case).
@@ -103,7 +116,7 @@ const createComponentEventTypeImports = (componentTagName, events, options) => {
103
116
  const { componentCorePackage, customElementsDir } = options;
104
117
  const imports = [];
105
118
  const namedImports = new Set();
106
- const isCustomElementsBuild = customElementsDir !== undefined;
119
+ const isCustomElementsBuild = isOutputTypeCustomElementsBuild(options.outputType);
107
120
  const importPathName = normalizePath(componentCorePackage) + (isCustomElementsBuild ? `/${customElementsDir}` : '');
108
121
  events.forEach((event) => {
109
122
  Object.entries(event.complexType.references).forEach(([typeName, refObject]) => {
@@ -194,6 +207,7 @@ export class ${tagNameAsPascal} {
194
207
  * @returns The sanitized event type as a string.
195
208
  */
196
209
  const formatOutputType = (componentClassName, event) => {
210
+ const prefix = `I${componentClassName}`;
197
211
  /**
198
212
  * The original attribute contains the original type defined by the devs.
199
213
  * This regexp normalizes the reference, by removing linebreaks,
@@ -202,11 +216,24 @@ const formatOutputType = (componentClassName, event) => {
202
216
  return Object.entries(event.complexType.references)
203
217
  .filter(([_, refObject]) => refObject.location === 'local' || refObject.location === 'import')
204
218
  .reduce((type, [src, dst]) => {
205
- const renamedType = `I${componentClassName}${type}`;
219
+ let renamedType = type;
220
+ if (!type.startsWith(prefix)) {
221
+ renamedType = `I${componentClassName}${type}`;
222
+ }
206
223
  return (renamedType
207
224
  .replace(new RegExp(`^${src}$`, 'g'), `${dst}`)
208
225
  // Capture all instances of the `src` field surrounded by non-word characters on each side and join them.
209
- .replace(new RegExp(`([^\\w])${src}([^\\w])`, 'g'), (v, p1, p2) => [p1, dst, p2].join('')));
226
+ .replace(new RegExp(`([^\\w])${src}([^\\w])`, 'g'), (v, p1, p2) => {
227
+ if ((dst === null || dst === void 0 ? void 0 : dst.location) === 'import') {
228
+ /**
229
+ * Replaces a complex type reference within a generic type.
230
+ * For example, remapping a type like `EventEmitter<CustomEvent<MyEvent<T>>>` to
231
+ * `EventEmitter<CustomEvent<IMyComponentMyEvent<IMyComponentT>>>`.
232
+ */
233
+ return [p1, `I${componentClassName}${v.substring(1, v.length - 1)}`, p2].join('');
234
+ }
235
+ return [p1, dst, p2].join('');
236
+ }));
210
237
  }, event.complexType.original
211
238
  .replace(/\n/g, ' ')
212
239
  .replace(/\s{2,}/g, ' ')
@@ -227,17 +254,19 @@ const createDocComment = (doc) => {
227
254
  };
228
255
  /**
229
256
  * Creates the component interface type definition.
257
+ * @param outputType The output type.
230
258
  * @param tagNameAsPascal The tag name as PascalCase.
231
259
  * @param events The events to generate the interface properties for.
232
260
  * @param componentCorePackage The component core package.
233
261
  * @param customElementsDir The custom elements directory.
234
262
  * @returns The component interface type definition as a string.
235
263
  */
236
- const createComponentTypeDefinition = (tagNameAsPascal, events, componentCorePackage, customElementsDir) => {
264
+ const createComponentTypeDefinition = (outputType, tagNameAsPascal, events, componentCorePackage, customElementsDir) => {
237
265
  const publicEvents = events.filter((ev) => !ev.internal);
238
266
  const eventTypeImports = createComponentEventTypeImports(tagNameAsPascal, publicEvents, {
239
267
  componentCorePackage,
240
268
  customElementsDir,
269
+ outputType,
241
270
  });
242
271
  const eventTypes = publicEvents.map((event) => {
243
272
  const comment = createDocComment(event.docs);
@@ -385,11 +414,11 @@ async function copyResources$1(config, outputTarget) {
385
414
  function generateProxies(components, pkgData, outputTarget, rootDir) {
386
415
  const distTypesDir = path.dirname(pkgData.types);
387
416
  const dtsFilePath = path.join(rootDir, distTypesDir, GENERATED_DTS);
417
+ const { outputType } = outputTarget;
388
418
  const componentsTypeFile = relativeImport(outputTarget.directivesProxyFile, dtsFilePath, '.d.ts');
389
- const includeSingleComponentAngularModules = outputTarget.outputType === 'scam';
390
- const includeSingleComponentAngularComponents = outputTarget.outputType === 'standalone';
391
- const isCustomElementsBuild = outputTarget.customElementsDir !== undefined;
392
- const isStandaloneBuild = outputTarget.outputType === 'standalone';
419
+ const includeSingleComponentAngularModules = outputType === OutputTypes.Scam;
420
+ const isCustomElementsBuild = isOutputTypeCustomElementsBuild(outputType);
421
+ const isStandaloneBuild = outputType === OutputTypes.Standalone;
393
422
  const includeOutputImports = components.some((component) => component.events.some((event) => !event.internal));
394
423
  /**
395
424
  * The collection of named imports from @angular/core.
@@ -431,9 +460,9 @@ ${createImportStatement(componentLibImports, './angular-component-lib/utils')}\n
431
460
  let sourceImports = '';
432
461
  /**
433
462
  * Build an array of Custom Elements build imports and namespace them
434
- * so that they do not conflict with the React wrapper names. For example,
463
+ * so that they do not conflict with the Angular wrapper names. For example,
435
464
  * IonButton would be imported as IonButtonCmp so as to not conflict with the
436
- * IonButton React Component that takes in the Web Component as a parameter.
465
+ * IonButton Angular Component that takes in the Web Component as a parameter.
437
466
  */
438
467
  if (isCustomElementsBuild && outputTarget.componentCorePackage !== undefined) {
439
468
  const cmpImports = components.map((component) => {
@@ -442,16 +471,6 @@ ${createImportStatement(componentLibImports, './angular-component-lib/utils')}\n
442
471
  });
443
472
  sourceImports = cmpImports.join('\n');
444
473
  }
445
- if (!isCustomElementsBuild) {
446
- if (includeSingleComponentAngularModules) {
447
- // Generating Angular modules is only supported in the dist-custom-elements build
448
- throw new Error('Generating single component Angular modules requires the "customElementsDir" option to be set.');
449
- }
450
- if (includeSingleComponentAngularComponents) {
451
- // Generates Angular standalone components is only supported in the dist-custom-elements build
452
- throw new Error('Generating standalone Angular components requires the "customElementsDir" option to be set.');
453
- }
454
- }
455
474
  const proxyFileOutput = [];
456
475
  const filterInternalProps = (prop) => !prop.internal;
457
476
  const mapPropName = (prop) => prop.name;
@@ -482,7 +501,7 @@ ${createImportStatement(componentLibImports, './angular-component-lib/utils')}\n
482
501
  */
483
502
  const componentDefinition = createAngularComponentDefinition(cmpMeta.tagName, inputs, outputs, methods, isCustomElementsBuild, isStandaloneBuild);
484
503
  const moduleDefinition = generateAngularModuleForComponent(cmpMeta.tagName);
485
- const componentTypeDefinition = createComponentTypeDefinition(tagNameAsPascal, cmpMeta.events, componentCorePackage, customElementsDir);
504
+ const componentTypeDefinition = createComponentTypeDefinition(outputType, tagNameAsPascal, cmpMeta.events, componentCorePackage, customElementsDir);
486
505
  proxyFileOutput.push(componentDefinition, '\n');
487
506
  if (includeSingleComponentAngularModules) {
488
507
  proxyFileOutput.push(moduleDefinition, '\n');
@@ -495,20 +514,23 @@ ${createImportStatement(componentLibImports, './angular-component-lib/utils')}\n
495
514
  const GENERATED_DTS = 'components.d.ts';
496
515
  const IMPORT_TYPES = 'Components';
497
516
 
498
- const angularOutputTarget = (outputTarget) => ({
499
- type: 'custom',
500
- name: 'angular-library',
501
- validate(config) {
502
- return normalizeOutputTarget(config, outputTarget);
503
- },
504
- async generator(config, compilerCtx, buildCtx) {
505
- const timespan = buildCtx.createTimeSpan(`generate angular proxies started`, true);
506
- await angularDirectiveProxyOutput(compilerCtx, outputTarget, buildCtx.components, config);
507
- timespan.finish(`generate angular proxies finished`);
508
- },
509
- });
517
+ const angularOutputTarget = (outputTarget) => {
518
+ let validatedOutputTarget;
519
+ return {
520
+ type: 'custom',
521
+ name: 'angular-library',
522
+ validate(config) {
523
+ validatedOutputTarget = normalizeOutputTarget(config, outputTarget);
524
+ },
525
+ async generator(config, compilerCtx, buildCtx) {
526
+ const timespan = buildCtx.createTimeSpan(`generate angular proxies started`, true);
527
+ await angularDirectiveProxyOutput(compilerCtx, validatedOutputTarget, buildCtx.components, config);
528
+ timespan.finish(`generate angular proxies finished`);
529
+ },
530
+ };
531
+ };
510
532
  function normalizeOutputTarget(config, outputTarget) {
511
- const results = Object.assign(Object.assign({}, outputTarget), { excludeComponents: outputTarget.excludeComponents || [], valueAccessorConfigs: outputTarget.valueAccessorConfigs || [] });
533
+ const results = Object.assign(Object.assign({}, outputTarget), { excludeComponents: outputTarget.excludeComponents || [], valueAccessorConfigs: outputTarget.valueAccessorConfigs || [], customElementsDir: outputTarget.customElementsDir || 'components', outputType: outputTarget.outputType || OutputTypes.Component });
512
534
  if (config.rootDir == null) {
513
535
  throw new Error('rootDir is not set and it should be set by stencil itself');
514
536
  }
@@ -524,8 +546,8 @@ function normalizeOutputTarget(config, outputTarget) {
524
546
  if (outputTarget.includeSingleComponentAngularModules !== undefined) {
525
547
  throw new Error("The 'includeSingleComponentAngularModules' option has been removed. Please use 'outputType' instead.");
526
548
  }
527
- if (outputTarget.outputType === 'scam') {
528
- console.warn('**Experimental**: outputType: "scam" is a developer preview feature and may change or be removed in the future.');
549
+ if (outputTarget.outputType === OutputTypes.Scam) {
550
+ console.warn(`**Experimental**: outputType: "${OutputTypes.Scam}" is a developer preview feature and may change or be removed in the future.`);
529
551
  }
530
552
  return results;
531
553
  }
@@ -1,5 +1,5 @@
1
1
  import path from 'path';
2
- import { relativeImport, normalizePath, sortBy, readPackageJson, dashToPascalCase, createImportStatement, } from './utils';
2
+ import { relativeImport, normalizePath, sortBy, readPackageJson, dashToPascalCase, createImportStatement, isOutputTypeCustomElementsBuild, OutputTypes, } from './utils';
3
3
  import { createAngularComponentDefinition, createComponentTypeDefinition } from './generate-angular-component';
4
4
  import { generateAngularDirectivesFile } from './generate-angular-directives-file';
5
5
  import generateValueAccessors from './generate-value-accessors';
@@ -37,11 +37,11 @@ async function copyResources(config, outputTarget) {
37
37
  export function generateProxies(components, pkgData, outputTarget, rootDir) {
38
38
  const distTypesDir = path.dirname(pkgData.types);
39
39
  const dtsFilePath = path.join(rootDir, distTypesDir, GENERATED_DTS);
40
+ const { outputType } = outputTarget;
40
41
  const componentsTypeFile = relativeImport(outputTarget.directivesProxyFile, dtsFilePath, '.d.ts');
41
- const includeSingleComponentAngularModules = outputTarget.outputType === 'scam';
42
- const includeSingleComponentAngularComponents = outputTarget.outputType === 'standalone';
43
- const isCustomElementsBuild = outputTarget.customElementsDir !== undefined;
44
- const isStandaloneBuild = outputTarget.outputType === 'standalone';
42
+ const includeSingleComponentAngularModules = outputType === OutputTypes.Scam;
43
+ const isCustomElementsBuild = isOutputTypeCustomElementsBuild(outputType);
44
+ const isStandaloneBuild = outputType === OutputTypes.Standalone;
45
45
  const includeOutputImports = components.some((component) => component.events.some((event) => !event.internal));
46
46
  /**
47
47
  * The collection of named imports from @angular/core.
@@ -83,9 +83,9 @@ ${createImportStatement(componentLibImports, './angular-component-lib/utils')}\n
83
83
  let sourceImports = '';
84
84
  /**
85
85
  * Build an array of Custom Elements build imports and namespace them
86
- * so that they do not conflict with the React wrapper names. For example,
86
+ * so that they do not conflict with the Angular wrapper names. For example,
87
87
  * IonButton would be imported as IonButtonCmp so as to not conflict with the
88
- * IonButton React Component that takes in the Web Component as a parameter.
88
+ * IonButton Angular Component that takes in the Web Component as a parameter.
89
89
  */
90
90
  if (isCustomElementsBuild && outputTarget.componentCorePackage !== undefined) {
91
91
  const cmpImports = components.map((component) => {
@@ -94,16 +94,6 @@ ${createImportStatement(componentLibImports, './angular-component-lib/utils')}\n
94
94
  });
95
95
  sourceImports = cmpImports.join('\n');
96
96
  }
97
- if (!isCustomElementsBuild) {
98
- if (includeSingleComponentAngularModules) {
99
- // Generating Angular modules is only supported in the dist-custom-elements build
100
- throw new Error('Generating single component Angular modules requires the "customElementsDir" option to be set.');
101
- }
102
- if (includeSingleComponentAngularComponents) {
103
- // Generates Angular standalone components is only supported in the dist-custom-elements build
104
- throw new Error('Generating standalone Angular components requires the "customElementsDir" option to be set.');
105
- }
106
- }
107
97
  const proxyFileOutput = [];
108
98
  const filterInternalProps = (prop) => !prop.internal;
109
99
  const mapPropName = (prop) => prop.name;
@@ -134,7 +124,7 @@ ${createImportStatement(componentLibImports, './angular-component-lib/utils')}\n
134
124
  */
135
125
  const componentDefinition = createAngularComponentDefinition(cmpMeta.tagName, inputs, outputs, methods, isCustomElementsBuild, isStandaloneBuild);
136
126
  const moduleDefinition = generateAngularModuleForComponent(cmpMeta.tagName);
137
- const componentTypeDefinition = createComponentTypeDefinition(tagNameAsPascal, cmpMeta.events, componentCorePackage, customElementsDir);
127
+ const componentTypeDefinition = createComponentTypeDefinition(outputType, tagNameAsPascal, cmpMeta.events, componentCorePackage, customElementsDir);
138
128
  proxyFileOutput.push(componentDefinition, '\n');
139
129
  if (includeSingleComponentAngularModules) {
140
130
  proxyFileOutput.push(moduleDefinition, '\n');
package/dist/plugin.js CHANGED
@@ -1,20 +1,23 @@
1
- import { normalizePath } from './utils';
1
+ import { OutputTypes, normalizePath } from './utils';
2
2
  import { angularDirectiveProxyOutput } from './output-angular';
3
3
  import path from 'path';
4
- export const angularOutputTarget = (outputTarget) => ({
5
- type: 'custom',
6
- name: 'angular-library',
7
- validate(config) {
8
- return normalizeOutputTarget(config, outputTarget);
9
- },
10
- async generator(config, compilerCtx, buildCtx) {
11
- const timespan = buildCtx.createTimeSpan(`generate angular proxies started`, true);
12
- await angularDirectiveProxyOutput(compilerCtx, outputTarget, buildCtx.components, config);
13
- timespan.finish(`generate angular proxies finished`);
14
- },
15
- });
4
+ export const angularOutputTarget = (outputTarget) => {
5
+ let validatedOutputTarget;
6
+ return {
7
+ type: 'custom',
8
+ name: 'angular-library',
9
+ validate(config) {
10
+ validatedOutputTarget = normalizeOutputTarget(config, outputTarget);
11
+ },
12
+ async generator(config, compilerCtx, buildCtx) {
13
+ const timespan = buildCtx.createTimeSpan(`generate angular proxies started`, true);
14
+ await angularDirectiveProxyOutput(compilerCtx, validatedOutputTarget, buildCtx.components, config);
15
+ timespan.finish(`generate angular proxies finished`);
16
+ },
17
+ };
18
+ };
16
19
  export function normalizeOutputTarget(config, outputTarget) {
17
- const results = Object.assign(Object.assign({}, outputTarget), { excludeComponents: outputTarget.excludeComponents || [], valueAccessorConfigs: outputTarget.valueAccessorConfigs || [] });
20
+ const results = Object.assign(Object.assign({}, outputTarget), { excludeComponents: outputTarget.excludeComponents || [], valueAccessorConfigs: outputTarget.valueAccessorConfigs || [], customElementsDir: outputTarget.customElementsDir || 'components', outputType: outputTarget.outputType || OutputTypes.Component });
18
21
  if (config.rootDir == null) {
19
22
  throw new Error('rootDir is not set and it should be set by stencil itself');
20
23
  }
@@ -30,8 +33,8 @@ export function normalizeOutputTarget(config, outputTarget) {
30
33
  if (outputTarget.includeSingleComponentAngularModules !== undefined) {
31
34
  throw new Error("The 'includeSingleComponentAngularModules' option has been removed. Please use 'outputType' instead.");
32
35
  }
33
- if (outputTarget.outputType === 'scam') {
34
- console.warn('**Experimental**: outputType: "scam" is a developer preview feature and may change or be removed in the future.');
36
+ if (outputTarget.outputType === OutputTypes.Scam) {
37
+ console.warn(`**Experimental**: outputType: "${OutputTypes.Scam}" is a developer preview feature and may change or be removed in the future.`);
35
38
  }
36
39
  return results;
37
40
  }
package/dist/types.d.ts CHANGED
@@ -23,10 +23,10 @@ export interface OutputTargetAngular {
23
23
  /**
24
24
  * The type of output that should be generated.
25
25
  * - `component` - Generate many component wrappers tied to a single Angular module (lazy/hydrated approach).
26
- * - `scam` - @experimental Generate a Single Component Angular Module for each component.
26
+ * - `scam` - **Experimental** - Generate a Single Component Angular Module for each component.
27
27
  * - `standalone` - Generate a component with the `standalone` flag set to `true`.
28
28
  */
29
- outputType: OutputType;
29
+ outputType?: OutputType;
30
30
  }
31
31
  export declare type ValueAccessorTypes = 'text' | 'radio' | 'select' | 'number' | 'boolean';
32
32
  export interface ValueAccessorConfig {
package/dist/utils.d.ts CHANGED
@@ -1,5 +1,8 @@
1
1
  import { ComponentCompilerEvent, Config } from '@stencil/core/internal';
2
- import type { PackageJSON } from './types';
2
+ import { OutputType, PackageJSON } from './types';
3
+ export declare const OutputTypes: {
4
+ [key: string]: OutputType;
5
+ };
3
6
  export declare const toLowerCase: (str: string) => string;
4
7
  export declare const dashToPascalCase: (str: string) => string;
5
8
  export declare function sortBy<T>(array: T[], prop: (item: T) => string): T[];
@@ -21,6 +24,12 @@ export declare const formatToQuotedList: (list: readonly string[]) => string;
21
24
  * @returns The import statement as a string.
22
25
  */
23
26
  export declare const createImportStatement: (imports: string[], module: string) => string;
27
+ /**
28
+ * Checks if the outputType is for the custom elements build.
29
+ * @param outputType The output type.
30
+ * @returns `true` if the output type is for the custom elements build.
31
+ */
32
+ export declare const isOutputTypeCustomElementsBuild: (outputType: OutputType) => boolean;
24
33
  /**
25
34
  * Creates the collection of import statements for a component based on the component's events type dependencies.
26
35
  * @param componentTagName The tag name of the component (pascal case).
@@ -31,4 +40,5 @@ export declare const createImportStatement: (imports: string[], module: string)
31
40
  export declare const createComponentEventTypeImports: (componentTagName: string, events: readonly ComponentCompilerEvent[], options: {
32
41
  componentCorePackage: string;
33
42
  customElementsDir?: string;
43
+ outputType: OutputType;
34
44
  }) => string;
package/dist/utils.js CHANGED
@@ -1,4 +1,9 @@
1
1
  import path from 'path';
2
+ export const OutputTypes = {
3
+ Component: 'component',
4
+ Scam: 'scam',
5
+ Standalone: 'standalone',
6
+ };
2
7
  export const toLowerCase = (str) => str.toLowerCase();
3
8
  export const dashToPascalCase = (str) => toLowerCase(str)
4
9
  .split('-')
@@ -93,6 +98,14 @@ export const createImportStatement = (imports, module) => {
93
98
  }
94
99
  return `import { ${imports.join(', ')} } from '${module}';`;
95
100
  };
101
+ /**
102
+ * Checks if the outputType is for the custom elements build.
103
+ * @param outputType The output type.
104
+ * @returns `true` if the output type is for the custom elements build.
105
+ */
106
+ export const isOutputTypeCustomElementsBuild = (outputType) => {
107
+ return outputType === OutputTypes.Standalone || outputType === OutputTypes.Scam;
108
+ };
96
109
  /**
97
110
  * Creates the collection of import statements for a component based on the component's events type dependencies.
98
111
  * @param componentTagName The tag name of the component (pascal case).
@@ -104,7 +117,7 @@ export const createComponentEventTypeImports = (componentTagName, events, option
104
117
  const { componentCorePackage, customElementsDir } = options;
105
118
  const imports = [];
106
119
  const namedImports = new Set();
107
- const isCustomElementsBuild = customElementsDir !== undefined;
120
+ const isCustomElementsBuild = isOutputTypeCustomElementsBuild(options.outputType);
108
121
  const importPathName = normalizePath(componentCorePackage) + (isCustomElementsBuild ? `/${customElementsDir}` : '');
109
122
  events.forEach((event) => {
110
123
  Object.entries(event.complexType.references).forEach(([typeName, refObject]) => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@stencil/angular-output-target",
3
- "version": "0.8.1-dev.11690825475.1243803f",
3
+ "version": "0.8.2",
4
4
  "description": "Angular output target for @stencil/core components.",
5
5
  "main": "dist/index.cjs.js",
6
6
  "module": "dist/index.js",
@@ -58,7 +58,7 @@
58
58
  ],
59
59
  "testURL": "http://localhost"
60
60
  },
61
- "gitHead": "243803f02d0675190181da7ed8ad6ff432c3ee1d",
61
+ "gitHead": "a3588e905186a0e86e7f88418fd5b2f9531b55e0",
62
62
  "volta": {
63
63
  "extends": "../../package.json"
64
64
  }