@stencil/angular-output-target 0.7.1 → 0.7.2-dev.11691590901.1db83f93

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