@stencil/angular-output-target 0.7.1 → 0.7.2-dev.11691592740.18e8ffbc

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
@@ -40,12 +40,12 @@ export const config: Config = {
40
40
 
41
41
  ## Config Options
42
42
 
43
- | Property | Description |
44
- | ----------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
45
- | `componentCorePackage` | The NPM package name of your Stencil component library. This package is used as a dependency for your Angular wrappers. |
46
- | `directivesProxyFile` | The output file of all the component wrappers generated by the output target. This file path should point to a location within your Angular library/project. |
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. |
48
- | `valueAccessorConfigs` | The configuration object for how individual web components behave with Angular control value accessors. |
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. |
50
- | `includeImportCustomElements` | If `true`, the output target will import the custom element instance and register it with the Custom Elements Registry when the component is imported inside of a user's app. This can only be used with the [Custom Elements Bundle](https://stenciljs.com/docs/custom-elements) and will not work with lazy loaded components. |
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 when `includeImportCustomElements` is `true`. |
43
+ | Property | Description |
44
+ | ---------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
45
+ | `componentCorePackage` | The NPM package name of your Stencil component library. This package is used as a dependency for your Angular wrappers. |
46
+ | `directivesProxyFile` | The output file of all the component wrappers generated by the output target. This file path should point to a location within your Angular library/project. |
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. |
48
+ | `valueAccessorConfigs` | The configuration object for how individual web components behave with Angular control value accessors. |
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. |
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
  *
@@ -7,16 +8,17 @@ import type { ComponentCompilerEvent } from '@stencil/core/internal';
7
8
  * @param outputs The outputs/events of the Stencil component. (e.g. ['myOutput']).
8
9
  * @param methods The methods of the Stencil component. (e.g. ['myMethod']).
9
10
  * @param includeImportCustomElements Whether to define the component as a custom element.
11
+ * @param standalone Whether to define the component as a standalone component.
10
12
  * @returns The component declaration as a string.
11
13
  */
12
- export declare const createAngularComponentDefinition: (tagName: string, inputs: readonly string[], outputs: readonly string[], methods: readonly string[], includeImportCustomElements?: boolean) => string;
14
+ export declare const createAngularComponentDefinition: (tagName: string, inputs: readonly string[], outputs: readonly string[], methods: readonly string[], includeImportCustomElements?: boolean, standalone?: boolean) => string;
13
15
  /**
14
16
  * Creates the component interface type definition.
17
+ * @param outputType The output type.
15
18
  * @param tagNameAsPascal The tag name as PascalCase.
16
19
  * @param events The events to generate the interface properties for.
17
20
  * @param componentCorePackage The component core package.
18
- * @param includeImportCustomElements Whether to include the import for the custom element definition.
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, includeImportCustomElements?: boolean, customElementsDir?: string | undefined) => string;
24
+ export declare const createComponentTypeDefinition: (outputType: OutputType, tagNameAsPascal: string, events: readonly ComponentCompilerEvent[], componentCorePackage: string, customElementsDir?: string | undefined) => string;
@@ -7,9 +7,10 @@ import { createComponentEventTypeImports, dashToPascalCase, formatToQuotedList }
7
7
  * @param outputs The outputs/events of the Stencil component. (e.g. ['myOutput']).
8
8
  * @param methods The methods of the Stencil component. (e.g. ['myMethod']).
9
9
  * @param includeImportCustomElements Whether to define the component as a custom element.
10
+ * @param standalone Whether to define the component as a standalone component.
10
11
  * @returns The component declaration as a string.
11
12
  */
12
- export const createAngularComponentDefinition = (tagName, inputs, outputs, methods, includeImportCustomElements = false) => {
13
+ export const createAngularComponentDefinition = (tagName, inputs, outputs, methods, includeImportCustomElements = false, standalone = false) => {
13
14
  const tagNameAsPascal = dashToPascalCase(tagName);
14
15
  const hasInputs = inputs.length > 0;
15
16
  const hasOutputs = outputs.length > 0;
@@ -31,6 +32,10 @@ export const createAngularComponentDefinition = (tagName, inputs, outputs, metho
31
32
  if (hasMethods) {
32
33
  proxyCmpOptions.push(`\n methods: [${formattedMethods}]`);
33
34
  }
35
+ let standaloneOption = '';
36
+ if (standalone && includeImportCustomElements) {
37
+ standaloneOption = `\n standalone: true`;
38
+ }
34
39
  /**
35
40
  * Notes on the generated output:
36
41
  * - We disable @angular-eslint/no-inputs-metadata-property, so that
@@ -44,7 +49,7 @@ export const createAngularComponentDefinition = (tagName, inputs, outputs, metho
44
49
  changeDetection: ChangeDetectionStrategy.OnPush,
45
50
  template: '<ng-content></ng-content>',
46
51
  // eslint-disable-next-line @angular-eslint/no-inputs-metadata-property
47
- inputs: [${formattedInputs}],
52
+ inputs: [${formattedInputs}],${standaloneOption}
48
53
  })
49
54
  export class ${tagNameAsPascal} {
50
55
  protected el: HTMLElement;
@@ -98,19 +103,19 @@ const createDocComment = (doc) => {
98
103
  };
99
104
  /**
100
105
  * Creates the component interface type definition.
106
+ * @param outputType The output type.
101
107
  * @param tagNameAsPascal The tag name as PascalCase.
102
108
  * @param events The events to generate the interface properties for.
103
109
  * @param componentCorePackage The component core package.
104
- * @param includeImportCustomElements Whether to include the import for the custom element definition.
105
110
  * @param customElementsDir The custom elements directory.
106
111
  * @returns The component interface type definition as a string.
107
112
  */
108
- export const createComponentTypeDefinition = (tagNameAsPascal, events, componentCorePackage, includeImportCustomElements = false, customElementsDir) => {
113
+ export const createComponentTypeDefinition = (outputType, tagNameAsPascal, events, componentCorePackage, customElementsDir) => {
109
114
  const publicEvents = events.filter((ev) => !ev.internal);
110
115
  const eventTypeImports = createComponentEventTypeImports(tagNameAsPascal, publicEvents, {
111
116
  componentCorePackage,
112
- includeImportCustomElements,
113
117
  customElementsDir,
118
+ outputType,
114
119
  });
115
120
  const eventTypes = publicEvents.map((event) => {
116
121
  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).
@@ -108,10 +121,11 @@ const createImportStatement = (imports, module) => {
108
121
  * @returns The import statements as an array of strings.
109
122
  */
110
123
  const createComponentEventTypeImports = (componentTagName, events, options) => {
111
- const { componentCorePackage, includeImportCustomElements, customElementsDir } = options;
124
+ const { componentCorePackage, customElementsDir } = options;
112
125
  const imports = [];
113
126
  const namedImports = new Set();
114
- const importPathName = normalizePath(componentCorePackage) + (includeImportCustomElements ? `/${customElementsDir || 'components'}` : '');
127
+ const isCustomElementsBuild = isOutputTypeCustomElementsBuild(options.outputType);
128
+ const importPathName = normalizePath(componentCorePackage) + (isCustomElementsBuild ? `/${customElementsDir}` : '');
115
129
  events.forEach((event) => {
116
130
  Object.entries(event.complexType.references).forEach(([typeName, refObject]) => {
117
131
  if (refObject.location === 'local' || refObject.location === 'import') {
@@ -138,9 +152,10 @@ const SLASH_REGEX = /\\/g;
138
152
  * @param outputs The outputs/events of the Stencil component. (e.g. ['myOutput']).
139
153
  * @param methods The methods of the Stencil component. (e.g. ['myMethod']).
140
154
  * @param includeImportCustomElements Whether to define the component as a custom element.
155
+ * @param standalone Whether to define the component as a standalone component.
141
156
  * @returns The component declaration as a string.
142
157
  */
143
- const createAngularComponentDefinition = (tagName, inputs, outputs, methods, includeImportCustomElements = false) => {
158
+ const createAngularComponentDefinition = (tagName, inputs, outputs, methods, includeImportCustomElements = false, standalone = false) => {
144
159
  const tagNameAsPascal = dashToPascalCase(tagName);
145
160
  const hasInputs = inputs.length > 0;
146
161
  const hasOutputs = outputs.length > 0;
@@ -162,6 +177,10 @@ const createAngularComponentDefinition = (tagName, inputs, outputs, methods, inc
162
177
  if (hasMethods) {
163
178
  proxyCmpOptions.push(`\n methods: [${formattedMethods}]`);
164
179
  }
180
+ let standaloneOption = '';
181
+ if (standalone && includeImportCustomElements) {
182
+ standaloneOption = `\n standalone: true`;
183
+ }
165
184
  /**
166
185
  * Notes on the generated output:
167
186
  * - We disable @angular-eslint/no-inputs-metadata-property, so that
@@ -175,7 +194,7 @@ const createAngularComponentDefinition = (tagName, inputs, outputs, methods, inc
175
194
  changeDetection: ChangeDetectionStrategy.OnPush,
176
195
  template: '<ng-content></ng-content>',
177
196
  // eslint-disable-next-line @angular-eslint/no-inputs-metadata-property
178
- inputs: [${formattedInputs}],
197
+ inputs: [${formattedInputs}],${standaloneOption}
179
198
  })
180
199
  export class ${tagNameAsPascal} {
181
200
  protected el: HTMLElement;
@@ -229,19 +248,19 @@ const createDocComment = (doc) => {
229
248
  };
230
249
  /**
231
250
  * Creates the component interface type definition.
251
+ * @param outputType The output type.
232
252
  * @param tagNameAsPascal The tag name as PascalCase.
233
253
  * @param events The events to generate the interface properties for.
234
254
  * @param componentCorePackage The component core package.
235
- * @param includeImportCustomElements Whether to include the import for the custom element definition.
236
255
  * @param customElementsDir The custom elements directory.
237
256
  * @returns The component interface type definition as a string.
238
257
  */
239
- const createComponentTypeDefinition = (tagNameAsPascal, events, componentCorePackage, includeImportCustomElements = false, customElementsDir) => {
258
+ const createComponentTypeDefinition = (outputType, tagNameAsPascal, events, componentCorePackage, customElementsDir) => {
240
259
  const publicEvents = events.filter((ev) => !ev.internal);
241
260
  const eventTypeImports = createComponentEventTypeImports(tagNameAsPascal, publicEvents, {
242
261
  componentCorePackage,
243
- includeImportCustomElements,
244
262
  customElementsDir,
263
+ outputType,
245
264
  });
246
265
  const eventTypes = publicEvents.map((event) => {
247
266
  const comment = createDocComment(event.docs);
@@ -387,11 +406,13 @@ async function copyResources$1(config, outputTarget) {
387
406
  ], srcDirectory);
388
407
  }
389
408
  function generateProxies(components, pkgData, outputTarget, rootDir) {
390
- var _a;
391
409
  const distTypesDir = path__default['default'].dirname(pkgData.types);
392
410
  const dtsFilePath = path__default['default'].join(rootDir, distTypesDir, GENERATED_DTS);
411
+ const { outputType } = outputTarget;
393
412
  const componentsTypeFile = relativeImport(outputTarget.directivesProxyFile, dtsFilePath, '.d.ts');
394
- const includeSingleComponentAngularModules = (_a = outputTarget.includeSingleComponentAngularModules) !== null && _a !== void 0 ? _a : false;
413
+ const includeSingleComponentAngularModules = outputType === OutputTypes.Scam;
414
+ const isCustomElementsBuild = isOutputTypeCustomElementsBuild(outputType);
415
+ const isStandaloneBuild = outputType === OutputTypes.Standalone;
395
416
  const includeOutputImports = components.some((component) => component.events.some((event) => !event.internal));
396
417
  /**
397
418
  * The collection of named imports from @angular/core.
@@ -426,36 +447,28 @@ ${createImportStatement(componentLibImports, './angular-component-lib/utils')}\n
426
447
  let importLocation = outputTarget.componentCorePackage
427
448
  ? normalizePath(outputTarget.componentCorePackage)
428
449
  : normalizePath(componentsTypeFile);
429
- importLocation += outputTarget.includeImportCustomElements
430
- ? `/${outputTarget.customElementsDir || 'components'}`
431
- : '';
432
- return `import ${outputTarget.includeImportCustomElements ? 'type ' : ''}{ ${IMPORT_TYPES} } from '${importLocation}';\n`;
450
+ importLocation += isCustomElementsBuild ? `/${outputTarget.customElementsDir}` : '';
451
+ return `import ${isCustomElementsBuild ? 'type ' : ''}{ ${IMPORT_TYPES} } from '${importLocation}';\n`;
433
452
  };
434
453
  const typeImports = generateTypeImports();
435
454
  let sourceImports = '';
436
455
  /**
437
456
  * Build an array of Custom Elements build imports and namespace them
438
- * so that they do not conflict with the React wrapper names. For example,
457
+ * so that they do not conflict with the Angular wrapper names. For example,
439
458
  * IonButton would be imported as IonButtonCmp so as to not conflict with the
440
- * IonButton React Component that takes in the Web Component as a parameter.
459
+ * IonButton Angular Component that takes in the Web Component as a parameter.
441
460
  */
442
- if (outputTarget.includeImportCustomElements && outputTarget.componentCorePackage !== undefined) {
461
+ if (isCustomElementsBuild && outputTarget.componentCorePackage !== undefined) {
443
462
  const cmpImports = components.map((component) => {
444
463
  const pascalImport = dashToPascalCase(component.tagName);
445
- return `import { defineCustomElement as define${pascalImport} } from '${normalizePath(outputTarget.componentCorePackage)}/${outputTarget.customElementsDir || 'components'}/${component.tagName}.js';`;
464
+ return `import { defineCustomElement as define${pascalImport} } from '${normalizePath(outputTarget.componentCorePackage)}/${outputTarget.customElementsDir}/${component.tagName}.js';`;
446
465
  });
447
466
  sourceImports = cmpImports.join('\n');
448
467
  }
449
- if (includeSingleComponentAngularModules) {
450
- // Generating Angular modules is only supported in the dist-custom-elements build
451
- if (!outputTarget.includeImportCustomElements) {
452
- throw new Error('Generating single component Angular modules requires the "includeImportCustomElements" option to be set to true.');
453
- }
454
- }
455
468
  const proxyFileOutput = [];
456
469
  const filterInternalProps = (prop) => !prop.internal;
457
470
  const mapPropName = (prop) => prop.name;
458
- const { includeImportCustomElements, componentCorePackage, customElementsDir } = outputTarget;
471
+ const { componentCorePackage, customElementsDir } = outputTarget;
459
472
  for (let cmpMeta of components) {
460
473
  const tagNameAsPascal = dashToPascalCase(cmpMeta.tagName);
461
474
  const inputs = [];
@@ -480,9 +493,9 @@ ${createImportStatement(componentLibImports, './angular-component-lib/utils')}\n
480
493
  * 2. Optionally the @NgModule decorated class (if includeSingleComponentAngularModules is true)
481
494
  * 3. The component interface (using declaration merging for types).
482
495
  */
483
- const componentDefinition = createAngularComponentDefinition(cmpMeta.tagName, inputs, outputs, methods, includeImportCustomElements);
496
+ const componentDefinition = createAngularComponentDefinition(cmpMeta.tagName, inputs, outputs, methods, isCustomElementsBuild, isStandaloneBuild);
484
497
  const moduleDefinition = generateAngularModuleForComponent(cmpMeta.tagName);
485
- const componentTypeDefinition = createComponentTypeDefinition(tagNameAsPascal, cmpMeta.events, componentCorePackage, includeImportCustomElements, customElementsDir);
498
+ const componentTypeDefinition = createComponentTypeDefinition(outputType, tagNameAsPascal, cmpMeta.events, componentCorePackage, customElementsDir);
486
499
  proxyFileOutput.push(componentDefinition, '\n');
487
500
  if (includeSingleComponentAngularModules) {
488
501
  proxyFileOutput.push(moduleDefinition, '\n');
@@ -508,7 +521,7 @@ const angularOutputTarget = (outputTarget) => ({
508
521
  },
509
522
  });
510
523
  function normalizeOutputTarget(config, outputTarget) {
511
- const results = Object.assign(Object.assign({}, outputTarget), { excludeComponents: outputTarget.excludeComponents || [], valueAccessorConfigs: outputTarget.valueAccessorConfigs || [] });
524
+ const results = Object.assign(Object.assign({}, outputTarget), { excludeComponents: outputTarget.excludeComponents || [], valueAccessorConfigs: outputTarget.valueAccessorConfigs || [], customElementsDir: outputTarget.customElementsDir || 'components', outputType: outputTarget.outputType || OutputTypes.Component });
512
525
  if (config.rootDir == null) {
513
526
  throw new Error('rootDir is not set and it should be set by stencil itself');
514
527
  }
@@ -522,7 +535,10 @@ function normalizeOutputTarget(config, outputTarget) {
522
535
  results.directivesArrayFile = normalizePath(path__default['default'].join(config.rootDir, outputTarget.directivesArrayFile));
523
536
  }
524
537
  if (outputTarget.includeSingleComponentAngularModules !== undefined) {
525
- console.warn('**Experimental**: includeSingleComponentAngularModules is a developer preview feature and may change or be removed in the future.');
538
+ throw new Error("The 'includeSingleComponentAngularModules' option has been removed. Please use 'outputType' instead.");
539
+ }
540
+ if (outputTarget.outputType === OutputTypes.Scam) {
541
+ console.warn(`**Experimental**: outputType: "${OutputTypes.Scam}" is a developer preview feature and may change or be removed in the future.`);
526
542
  }
527
543
  return results;
528
544
  }
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).
@@ -100,10 +113,11 @@ const createImportStatement = (imports, module) => {
100
113
  * @returns The import statements as an array of strings.
101
114
  */
102
115
  const createComponentEventTypeImports = (componentTagName, events, options) => {
103
- const { componentCorePackage, includeImportCustomElements, customElementsDir } = options;
116
+ const { componentCorePackage, customElementsDir } = options;
104
117
  const imports = [];
105
118
  const namedImports = new Set();
106
- const importPathName = normalizePath(componentCorePackage) + (includeImportCustomElements ? `/${customElementsDir || 'components'}` : '');
119
+ const isCustomElementsBuild = isOutputTypeCustomElementsBuild(options.outputType);
120
+ const importPathName = normalizePath(componentCorePackage) + (isCustomElementsBuild ? `/${customElementsDir}` : '');
107
121
  events.forEach((event) => {
108
122
  Object.entries(event.complexType.references).forEach(([typeName, refObject]) => {
109
123
  if (refObject.location === 'local' || refObject.location === 'import') {
@@ -130,9 +144,10 @@ const SLASH_REGEX = /\\/g;
130
144
  * @param outputs The outputs/events of the Stencil component. (e.g. ['myOutput']).
131
145
  * @param methods The methods of the Stencil component. (e.g. ['myMethod']).
132
146
  * @param includeImportCustomElements Whether to define the component as a custom element.
147
+ * @param standalone Whether to define the component as a standalone component.
133
148
  * @returns The component declaration as a string.
134
149
  */
135
- const createAngularComponentDefinition = (tagName, inputs, outputs, methods, includeImportCustomElements = false) => {
150
+ const createAngularComponentDefinition = (tagName, inputs, outputs, methods, includeImportCustomElements = false, standalone = false) => {
136
151
  const tagNameAsPascal = dashToPascalCase(tagName);
137
152
  const hasInputs = inputs.length > 0;
138
153
  const hasOutputs = outputs.length > 0;
@@ -154,6 +169,10 @@ const createAngularComponentDefinition = (tagName, inputs, outputs, methods, inc
154
169
  if (hasMethods) {
155
170
  proxyCmpOptions.push(`\n methods: [${formattedMethods}]`);
156
171
  }
172
+ let standaloneOption = '';
173
+ if (standalone && includeImportCustomElements) {
174
+ standaloneOption = `\n standalone: true`;
175
+ }
157
176
  /**
158
177
  * Notes on the generated output:
159
178
  * - We disable @angular-eslint/no-inputs-metadata-property, so that
@@ -167,7 +186,7 @@ const createAngularComponentDefinition = (tagName, inputs, outputs, methods, inc
167
186
  changeDetection: ChangeDetectionStrategy.OnPush,
168
187
  template: '<ng-content></ng-content>',
169
188
  // eslint-disable-next-line @angular-eslint/no-inputs-metadata-property
170
- inputs: [${formattedInputs}],
189
+ inputs: [${formattedInputs}],${standaloneOption}
171
190
  })
172
191
  export class ${tagNameAsPascal} {
173
192
  protected el: HTMLElement;
@@ -221,19 +240,19 @@ const createDocComment = (doc) => {
221
240
  };
222
241
  /**
223
242
  * Creates the component interface type definition.
243
+ * @param outputType The output type.
224
244
  * @param tagNameAsPascal The tag name as PascalCase.
225
245
  * @param events The events to generate the interface properties for.
226
246
  * @param componentCorePackage The component core package.
227
- * @param includeImportCustomElements Whether to include the import for the custom element definition.
228
247
  * @param customElementsDir The custom elements directory.
229
248
  * @returns The component interface type definition as a string.
230
249
  */
231
- const createComponentTypeDefinition = (tagNameAsPascal, events, componentCorePackage, includeImportCustomElements = false, customElementsDir) => {
250
+ const createComponentTypeDefinition = (outputType, tagNameAsPascal, events, componentCorePackage, customElementsDir) => {
232
251
  const publicEvents = events.filter((ev) => !ev.internal);
233
252
  const eventTypeImports = createComponentEventTypeImports(tagNameAsPascal, publicEvents, {
234
253
  componentCorePackage,
235
- includeImportCustomElements,
236
254
  customElementsDir,
255
+ outputType,
237
256
  });
238
257
  const eventTypes = publicEvents.map((event) => {
239
258
  const comment = createDocComment(event.docs);
@@ -379,11 +398,13 @@ async function copyResources$1(config, outputTarget) {
379
398
  ], srcDirectory);
380
399
  }
381
400
  function generateProxies(components, pkgData, outputTarget, rootDir) {
382
- var _a;
383
401
  const distTypesDir = path.dirname(pkgData.types);
384
402
  const dtsFilePath = path.join(rootDir, distTypesDir, GENERATED_DTS);
403
+ const { outputType } = outputTarget;
385
404
  const componentsTypeFile = relativeImport(outputTarget.directivesProxyFile, dtsFilePath, '.d.ts');
386
- const includeSingleComponentAngularModules = (_a = outputTarget.includeSingleComponentAngularModules) !== null && _a !== void 0 ? _a : false;
405
+ const includeSingleComponentAngularModules = outputType === OutputTypes.Scam;
406
+ const isCustomElementsBuild = isOutputTypeCustomElementsBuild(outputType);
407
+ const isStandaloneBuild = outputType === OutputTypes.Standalone;
387
408
  const includeOutputImports = components.some((component) => component.events.some((event) => !event.internal));
388
409
  /**
389
410
  * The collection of named imports from @angular/core.
@@ -418,36 +439,28 @@ ${createImportStatement(componentLibImports, './angular-component-lib/utils')}\n
418
439
  let importLocation = outputTarget.componentCorePackage
419
440
  ? normalizePath(outputTarget.componentCorePackage)
420
441
  : normalizePath(componentsTypeFile);
421
- importLocation += outputTarget.includeImportCustomElements
422
- ? `/${outputTarget.customElementsDir || 'components'}`
423
- : '';
424
- return `import ${outputTarget.includeImportCustomElements ? 'type ' : ''}{ ${IMPORT_TYPES} } from '${importLocation}';\n`;
442
+ importLocation += isCustomElementsBuild ? `/${outputTarget.customElementsDir}` : '';
443
+ return `import ${isCustomElementsBuild ? 'type ' : ''}{ ${IMPORT_TYPES} } from '${importLocation}';\n`;
425
444
  };
426
445
  const typeImports = generateTypeImports();
427
446
  let sourceImports = '';
428
447
  /**
429
448
  * Build an array of Custom Elements build imports and namespace them
430
- * so that they do not conflict with the React wrapper names. For example,
449
+ * so that they do not conflict with the Angular wrapper names. For example,
431
450
  * IonButton would be imported as IonButtonCmp so as to not conflict with the
432
- * IonButton React Component that takes in the Web Component as a parameter.
451
+ * IonButton Angular Component that takes in the Web Component as a parameter.
433
452
  */
434
- if (outputTarget.includeImportCustomElements && outputTarget.componentCorePackage !== undefined) {
453
+ if (isCustomElementsBuild && outputTarget.componentCorePackage !== undefined) {
435
454
  const cmpImports = components.map((component) => {
436
455
  const pascalImport = dashToPascalCase(component.tagName);
437
- return `import { defineCustomElement as define${pascalImport} } from '${normalizePath(outputTarget.componentCorePackage)}/${outputTarget.customElementsDir || 'components'}/${component.tagName}.js';`;
456
+ return `import { defineCustomElement as define${pascalImport} } from '${normalizePath(outputTarget.componentCorePackage)}/${outputTarget.customElementsDir}/${component.tagName}.js';`;
438
457
  });
439
458
  sourceImports = cmpImports.join('\n');
440
459
  }
441
- if (includeSingleComponentAngularModules) {
442
- // Generating Angular modules is only supported in the dist-custom-elements build
443
- if (!outputTarget.includeImportCustomElements) {
444
- throw new Error('Generating single component Angular modules requires the "includeImportCustomElements" option to be set to true.');
445
- }
446
- }
447
460
  const proxyFileOutput = [];
448
461
  const filterInternalProps = (prop) => !prop.internal;
449
462
  const mapPropName = (prop) => prop.name;
450
- const { includeImportCustomElements, componentCorePackage, customElementsDir } = outputTarget;
463
+ const { componentCorePackage, customElementsDir } = outputTarget;
451
464
  for (let cmpMeta of components) {
452
465
  const tagNameAsPascal = dashToPascalCase(cmpMeta.tagName);
453
466
  const inputs = [];
@@ -472,9 +485,9 @@ ${createImportStatement(componentLibImports, './angular-component-lib/utils')}\n
472
485
  * 2. Optionally the @NgModule decorated class (if includeSingleComponentAngularModules is true)
473
486
  * 3. The component interface (using declaration merging for types).
474
487
  */
475
- const componentDefinition = createAngularComponentDefinition(cmpMeta.tagName, inputs, outputs, methods, includeImportCustomElements);
488
+ const componentDefinition = createAngularComponentDefinition(cmpMeta.tagName, inputs, outputs, methods, isCustomElementsBuild, isStandaloneBuild);
476
489
  const moduleDefinition = generateAngularModuleForComponent(cmpMeta.tagName);
477
- const componentTypeDefinition = createComponentTypeDefinition(tagNameAsPascal, cmpMeta.events, componentCorePackage, includeImportCustomElements, customElementsDir);
490
+ const componentTypeDefinition = createComponentTypeDefinition(outputType, tagNameAsPascal, cmpMeta.events, componentCorePackage, customElementsDir);
478
491
  proxyFileOutput.push(componentDefinition, '\n');
479
492
  if (includeSingleComponentAngularModules) {
480
493
  proxyFileOutput.push(moduleDefinition, '\n');
@@ -500,7 +513,7 @@ const angularOutputTarget = (outputTarget) => ({
500
513
  },
501
514
  });
502
515
  function normalizeOutputTarget(config, outputTarget) {
503
- const results = Object.assign(Object.assign({}, outputTarget), { excludeComponents: outputTarget.excludeComponents || [], valueAccessorConfigs: outputTarget.valueAccessorConfigs || [] });
516
+ const results = Object.assign(Object.assign({}, outputTarget), { excludeComponents: outputTarget.excludeComponents || [], valueAccessorConfigs: outputTarget.valueAccessorConfigs || [], customElementsDir: outputTarget.customElementsDir || 'components', outputType: outputTarget.outputType || OutputTypes.Component });
504
517
  if (config.rootDir == null) {
505
518
  throw new Error('rootDir is not set and it should be set by stencil itself');
506
519
  }
@@ -514,7 +527,10 @@ function normalizeOutputTarget(config, outputTarget) {
514
527
  results.directivesArrayFile = normalizePath(path.join(config.rootDir, outputTarget.directivesArrayFile));
515
528
  }
516
529
  if (outputTarget.includeSingleComponentAngularModules !== undefined) {
517
- console.warn('**Experimental**: includeSingleComponentAngularModules is a developer preview feature and may change or be removed in the future.');
530
+ throw new Error("The 'includeSingleComponentAngularModules' option has been removed. Please use 'outputType' instead.");
531
+ }
532
+ if (outputTarget.outputType === OutputTypes.Scam) {
533
+ console.warn(`**Experimental**: outputType: "${OutputTypes.Scam}" is a developer preview feature and may change or be removed in the future.`);
518
534
  }
519
535
  return results;
520
536
  }
@@ -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';
@@ -35,11 +35,13 @@ async function copyResources(config, outputTarget) {
35
35
  ], srcDirectory);
36
36
  }
37
37
  export function generateProxies(components, pkgData, outputTarget, rootDir) {
38
- var _a;
39
38
  const distTypesDir = path.dirname(pkgData.types);
40
39
  const dtsFilePath = path.join(rootDir, distTypesDir, GENERATED_DTS);
40
+ const { outputType } = outputTarget;
41
41
  const componentsTypeFile = relativeImport(outputTarget.directivesProxyFile, dtsFilePath, '.d.ts');
42
- const includeSingleComponentAngularModules = (_a = outputTarget.includeSingleComponentAngularModules) !== null && _a !== void 0 ? _a : false;
42
+ const includeSingleComponentAngularModules = outputType === OutputTypes.Scam;
43
+ const isCustomElementsBuild = isOutputTypeCustomElementsBuild(outputType);
44
+ const isStandaloneBuild = outputType === OutputTypes.Standalone;
43
45
  const includeOutputImports = components.some((component) => component.events.some((event) => !event.internal));
44
46
  /**
45
47
  * The collection of named imports from @angular/core.
@@ -74,36 +76,28 @@ ${createImportStatement(componentLibImports, './angular-component-lib/utils')}\n
74
76
  let importLocation = outputTarget.componentCorePackage
75
77
  ? normalizePath(outputTarget.componentCorePackage)
76
78
  : normalizePath(componentsTypeFile);
77
- importLocation += outputTarget.includeImportCustomElements
78
- ? `/${outputTarget.customElementsDir || 'components'}`
79
- : '';
80
- return `import ${outputTarget.includeImportCustomElements ? 'type ' : ''}{ ${IMPORT_TYPES} } from '${importLocation}';\n`;
79
+ importLocation += isCustomElementsBuild ? `/${outputTarget.customElementsDir}` : '';
80
+ return `import ${isCustomElementsBuild ? 'type ' : ''}{ ${IMPORT_TYPES} } from '${importLocation}';\n`;
81
81
  };
82
82
  const typeImports = generateTypeImports();
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
- if (outputTarget.includeImportCustomElements && outputTarget.componentCorePackage !== undefined) {
90
+ if (isCustomElementsBuild && outputTarget.componentCorePackage !== undefined) {
91
91
  const cmpImports = components.map((component) => {
92
92
  const pascalImport = dashToPascalCase(component.tagName);
93
- return `import { defineCustomElement as define${pascalImport} } from '${normalizePath(outputTarget.componentCorePackage)}/${outputTarget.customElementsDir || 'components'}/${component.tagName}.js';`;
93
+ return `import { defineCustomElement as define${pascalImport} } from '${normalizePath(outputTarget.componentCorePackage)}/${outputTarget.customElementsDir}/${component.tagName}.js';`;
94
94
  });
95
95
  sourceImports = cmpImports.join('\n');
96
96
  }
97
- if (includeSingleComponentAngularModules) {
98
- // Generating Angular modules is only supported in the dist-custom-elements build
99
- if (!outputTarget.includeImportCustomElements) {
100
- throw new Error('Generating single component Angular modules requires the "includeImportCustomElements" option to be set to true.');
101
- }
102
- }
103
97
  const proxyFileOutput = [];
104
98
  const filterInternalProps = (prop) => !prop.internal;
105
99
  const mapPropName = (prop) => prop.name;
106
- const { includeImportCustomElements, componentCorePackage, customElementsDir } = outputTarget;
100
+ const { componentCorePackage, customElementsDir } = outputTarget;
107
101
  for (let cmpMeta of components) {
108
102
  const tagNameAsPascal = dashToPascalCase(cmpMeta.tagName);
109
103
  const inputs = [];
@@ -128,9 +122,9 @@ ${createImportStatement(componentLibImports, './angular-component-lib/utils')}\n
128
122
  * 2. Optionally the @NgModule decorated class (if includeSingleComponentAngularModules is true)
129
123
  * 3. The component interface (using declaration merging for types).
130
124
  */
131
- const componentDefinition = createAngularComponentDefinition(cmpMeta.tagName, inputs, outputs, methods, includeImportCustomElements);
125
+ const componentDefinition = createAngularComponentDefinition(cmpMeta.tagName, inputs, outputs, methods, isCustomElementsBuild, isStandaloneBuild);
132
126
  const moduleDefinition = generateAngularModuleForComponent(cmpMeta.tagName);
133
- const componentTypeDefinition = createComponentTypeDefinition(tagNameAsPascal, cmpMeta.events, componentCorePackage, includeImportCustomElements, customElementsDir);
127
+ const componentTypeDefinition = createComponentTypeDefinition(outputType, tagNameAsPascal, cmpMeta.events, componentCorePackage, customElementsDir);
134
128
  proxyFileOutput.push(componentDefinition, '\n');
135
129
  if (includeSingleComponentAngularModules) {
136
130
  proxyFileOutput.push(moduleDefinition, '\n');
package/dist/plugin.js CHANGED
@@ -1,4 +1,4 @@
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
4
  export const angularOutputTarget = (outputTarget) => ({
@@ -14,7 +14,7 @@ export const angularOutputTarget = (outputTarget) => ({
14
14
  },
15
15
  });
16
16
  export function normalizeOutputTarget(config, outputTarget) {
17
- const results = Object.assign(Object.assign({}, outputTarget), { excludeComponents: outputTarget.excludeComponents || [], valueAccessorConfigs: outputTarget.valueAccessorConfigs || [] });
17
+ const results = Object.assign(Object.assign({}, outputTarget), { excludeComponents: outputTarget.excludeComponents || [], valueAccessorConfigs: outputTarget.valueAccessorConfigs || [], customElementsDir: outputTarget.customElementsDir || 'components', outputType: outputTarget.outputType || OutputTypes.Component });
18
18
  if (config.rootDir == null) {
19
19
  throw new Error('rootDir is not set and it should be set by stencil itself');
20
20
  }
@@ -28,7 +28,10 @@ export function normalizeOutputTarget(config, outputTarget) {
28
28
  results.directivesArrayFile = normalizePath(path.join(config.rootDir, outputTarget.directivesArrayFile));
29
29
  }
30
30
  if (outputTarget.includeSingleComponentAngularModules !== undefined) {
31
- console.warn('**Experimental**: includeSingleComponentAngularModules is a developer preview feature and may change or be removed in the future.');
31
+ throw new Error("The 'includeSingleComponentAngularModules' option has been removed. Please use 'outputType' instead.");
32
+ }
33
+ if (outputTarget.outputType === OutputTypes.Scam) {
34
+ console.warn(`**Experimental**: outputType: "${OutputTypes.Scam}" is a developer preview feature and may change or be removed in the future.`);
32
35
  }
33
36
  return results;
34
37
  }
package/dist/types.d.ts CHANGED
@@ -1,3 +1,10 @@
1
+ /**
2
+ * The type of output that can be generated with the Angular output target.
3
+ * - `component` - Generate many component wrappers tied to a single Angular module (lazy/hydrated approach).
4
+ * - `scam` - Generate a Single Component Angular Module for each component.
5
+ * - `standalone` - Generate a component with the `standalone` flag set to `true`.
6
+ */
7
+ export declare type OutputType = 'component' | 'scam' | 'standalone';
1
8
  export interface OutputTargetAngular {
2
9
  /**
3
10
  * The package name of the component library.
@@ -12,14 +19,14 @@ export interface OutputTargetAngular {
12
19
  directivesArrayFile?: string;
13
20
  valueAccessorConfigs?: ValueAccessorConfig[];
14
21
  excludeComponents?: string[];
15
- includeImportCustomElements?: boolean;
16
22
  customElementsDir?: string;
17
23
  /**
18
- * @experimental
19
- *
20
- * `true` to generate a single component Angular module for each component.
24
+ * The type of output that should be generated.
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.
27
+ * - `standalone` - Generate a component with the `standalone` flag set to `true`.
21
28
  */
22
- includeSingleComponentAngularModules?: boolean;
29
+ outputType?: OutputType;
23
30
  }
24
31
  export declare type ValueAccessorTypes = 'text' | 'radio' | 'select' | 'number' | 'boolean';
25
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).
@@ -30,6 +39,6 @@ export declare const createImportStatement: (imports: string[], module: string)
30
39
  */
31
40
  export declare const createComponentEventTypeImports: (componentTagName: string, events: readonly ComponentCompilerEvent[], options: {
32
41
  componentCorePackage: string;
33
- includeImportCustomElements?: boolean;
34
42
  customElementsDir?: string;
43
+ outputType: OutputType;
35
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).
@@ -101,10 +114,11 @@ export const createImportStatement = (imports, module) => {
101
114
  * @returns The import statements as an array of strings.
102
115
  */
103
116
  export const createComponentEventTypeImports = (componentTagName, events, options) => {
104
- const { componentCorePackage, includeImportCustomElements, customElementsDir } = options;
117
+ const { componentCorePackage, customElementsDir } = options;
105
118
  const imports = [];
106
119
  const namedImports = new Set();
107
- const importPathName = normalizePath(componentCorePackage) + (includeImportCustomElements ? `/${customElementsDir || 'components'}` : '');
120
+ const isCustomElementsBuild = isOutputTypeCustomElementsBuild(options.outputType);
121
+ const importPathName = normalizePath(componentCorePackage) + (isCustomElementsBuild ? `/${customElementsDir}` : '');
108
122
  events.forEach((event) => {
109
123
  Object.entries(event.complexType.references).forEach(([typeName, refObject]) => {
110
124
  if (refObject.location === 'local' || refObject.location === 'import') {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@stencil/angular-output-target",
3
- "version": "0.7.1",
3
+ "version": "0.7.2-dev.11691592740.18e8ffbc",
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": "a3588e905186a0e86e7f88418fd5b2f9531b55e0",
61
+ "gitHead": "8e8ffbccb48cd9a2584e09710677d47e1ffce5b9",
62
62
  "volta": {
63
63
  "extends": "../../package.json"
64
64
  }