@stencil/angular-output-target 0.7.0 → 0.8.1-dev.11690825475.1243803f
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 +10 -9
- package/dist/generate-angular-component.d.ts +3 -3
- package/dist/generate-angular-component.js +8 -5
- package/dist/index.cjs.js +34 -23
- package/dist/index.js +34 -23
- package/dist/output-angular.js +19 -15
- package/dist/plugin.js +4 -1
- package/dist/types.d.ts +12 -5
- package/dist/utils.d.ts +0 -1
- package/dist/utils.js +3 -2
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -27,6 +27,7 @@ export const config: Config = {
|
|
|
27
27
|
outputTargets: [
|
|
28
28
|
angularOutputTarget({
|
|
29
29
|
componentCorePackage: 'component-library',
|
|
30
|
+
outputType: 'component',
|
|
30
31
|
directivesProxyFile: '../component-library-angular/src/directives/proxies.ts',
|
|
31
32
|
directivesArrayFile: '../component-library-angular/src/directives/index.ts',
|
|
32
33
|
}),
|
|
@@ -40,12 +41,12 @@ export const config: Config = {
|
|
|
40
41
|
|
|
41
42
|
## Config Options
|
|
42
43
|
|
|
43
|
-
| Property
|
|
44
|
-
|
|
|
45
|
-
| `componentCorePackage`
|
|
46
|
-
| `directivesProxyFile`
|
|
47
|
-
| `directivesArrayFile`
|
|
48
|
-
| `valueAccessorConfigs`
|
|
49
|
-
| `excludeComponents`
|
|
50
|
-
| `
|
|
51
|
-
| `customElementsDir`
|
|
44
|
+
| Property | Description |
|
|
45
|
+
| ---------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
|
|
46
|
+
| `componentCorePackage` | The NPM package name of your Stencil component library. This package is used as a dependency for your Angular wrappers. |
|
|
47
|
+
| `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. |
|
|
48
|
+
| `directivesArrayFile` | The output file of a constant of all the generated component wrapper classes. Used for easily declaring and exporting the generated components from an `NgModule`. This file path should point to a location within your Angular library/project. |
|
|
49
|
+
| `valueAccessorConfigs` | The configuration object for how individual web components behave with Angular control value accessors. |
|
|
50
|
+
| `excludeComponents` | An array of tag names to exclude from generating component wrappers for. This is helpful when have a custom framework implementation of a specific component or need to extend the base component wrapper behavior. |
|
|
51
|
+
| `outputType` | Specifies the type of output to be generated. It can take one of the following values: <br />1. `component`: Generates all the component wrappers to be declared on an Angular module. This option is required for Stencil projects using the `dist` hydrated output.<br /> 2. `scam`: Generates a separate Angular module for each component.<br /> 3. `standalone`: Generates standalone component wrappers.<br /> Both `scam` and `standalone` options are compatible with the `dist-custom-elements` output. Developers **must** set a `customElementsDir` in the output target config when using either 'scam' or 'standalone'.<br />Note: Please choose the appropriate `outputType` based on your project's requirements and the desired output structure. |
|
|
52
|
+
| `customElementsDir` | This is the directory where the custom elements are imported from when using the [Custom Elements Bundle](https://stenciljs.com/docs/custom-elements). Required to be set for `outputType: "scam"` or `outputType: "standalone"`. |
|
|
@@ -7,16 +7,16 @@ import type { ComponentCompilerEvent } from '@stencil/core/internal';
|
|
|
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 declare const createAngularComponentDefinition: (tagName: string, inputs: readonly string[], outputs: readonly string[], methods: readonly string[], includeImportCustomElements?: boolean) => string;
|
|
13
|
+
export declare const createAngularComponentDefinition: (tagName: string, inputs: readonly string[], outputs: readonly string[], methods: readonly string[], includeImportCustomElements?: boolean, standalone?: boolean) => string;
|
|
13
14
|
/**
|
|
14
15
|
* Creates the component interface type definition.
|
|
15
16
|
* @param tagNameAsPascal The tag name as PascalCase.
|
|
16
17
|
* @param events The events to generate the interface properties for.
|
|
17
18
|
* @param componentCorePackage The component core package.
|
|
18
|
-
* @param includeImportCustomElements Whether to include the import for the custom element definition.
|
|
19
19
|
* @param customElementsDir The custom elements directory.
|
|
20
20
|
* @returns The component interface type definition as a string.
|
|
21
21
|
*/
|
|
22
|
-
export declare const createComponentTypeDefinition: (tagNameAsPascal: string, events: readonly ComponentCompilerEvent[], componentCorePackage: string,
|
|
22
|
+
export declare const createComponentTypeDefinition: (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;
|
|
@@ -101,15 +106,13 @@ const createDocComment = (doc) => {
|
|
|
101
106
|
* @param tagNameAsPascal The tag name as PascalCase.
|
|
102
107
|
* @param events The events to generate the interface properties for.
|
|
103
108
|
* @param componentCorePackage The component core package.
|
|
104
|
-
* @param includeImportCustomElements Whether to include the import for the custom element definition.
|
|
105
109
|
* @param customElementsDir The custom elements directory.
|
|
106
110
|
* @returns The component interface type definition as a string.
|
|
107
111
|
*/
|
|
108
|
-
export const createComponentTypeDefinition = (tagNameAsPascal, events, componentCorePackage,
|
|
112
|
+
export const createComponentTypeDefinition = (tagNameAsPascal, events, componentCorePackage, customElementsDir) => {
|
|
109
113
|
const publicEvents = events.filter((ev) => !ev.internal);
|
|
110
114
|
const eventTypeImports = createComponentEventTypeImports(tagNameAsPascal, publicEvents, {
|
|
111
115
|
componentCorePackage,
|
|
112
|
-
includeImportCustomElements,
|
|
113
116
|
customElementsDir,
|
|
114
117
|
});
|
|
115
118
|
const eventTypes = publicEvents.map((event) => {
|
package/dist/index.cjs.js
CHANGED
|
@@ -108,10 +108,11 @@ const createImportStatement = (imports, module) => {
|
|
|
108
108
|
* @returns The import statements as an array of strings.
|
|
109
109
|
*/
|
|
110
110
|
const createComponentEventTypeImports = (componentTagName, events, options) => {
|
|
111
|
-
const { componentCorePackage,
|
|
111
|
+
const { componentCorePackage, customElementsDir } = options;
|
|
112
112
|
const imports = [];
|
|
113
113
|
const namedImports = new Set();
|
|
114
|
-
const
|
|
114
|
+
const isCustomElementsBuild = customElementsDir !== undefined;
|
|
115
|
+
const importPathName = normalizePath(componentCorePackage) + (isCustomElementsBuild ? `/${customElementsDir}` : '');
|
|
115
116
|
events.forEach((event) => {
|
|
116
117
|
Object.entries(event.complexType.references).forEach(([typeName, refObject]) => {
|
|
117
118
|
if (refObject.location === 'local' || refObject.location === 'import') {
|
|
@@ -138,9 +139,10 @@ const SLASH_REGEX = /\\/g;
|
|
|
138
139
|
* @param outputs The outputs/events of the Stencil component. (e.g. ['myOutput']).
|
|
139
140
|
* @param methods The methods of the Stencil component. (e.g. ['myMethod']).
|
|
140
141
|
* @param includeImportCustomElements Whether to define the component as a custom element.
|
|
142
|
+
* @param standalone Whether to define the component as a standalone component.
|
|
141
143
|
* @returns The component declaration as a string.
|
|
142
144
|
*/
|
|
143
|
-
const createAngularComponentDefinition = (tagName, inputs, outputs, methods, includeImportCustomElements = false) => {
|
|
145
|
+
const createAngularComponentDefinition = (tagName, inputs, outputs, methods, includeImportCustomElements = false, standalone = false) => {
|
|
144
146
|
const tagNameAsPascal = dashToPascalCase(tagName);
|
|
145
147
|
const hasInputs = inputs.length > 0;
|
|
146
148
|
const hasOutputs = outputs.length > 0;
|
|
@@ -162,6 +164,10 @@ const createAngularComponentDefinition = (tagName, inputs, outputs, methods, inc
|
|
|
162
164
|
if (hasMethods) {
|
|
163
165
|
proxyCmpOptions.push(`\n methods: [${formattedMethods}]`);
|
|
164
166
|
}
|
|
167
|
+
let standaloneOption = '';
|
|
168
|
+
if (standalone && includeImportCustomElements) {
|
|
169
|
+
standaloneOption = `\n standalone: true`;
|
|
170
|
+
}
|
|
165
171
|
/**
|
|
166
172
|
* Notes on the generated output:
|
|
167
173
|
* - We disable @angular-eslint/no-inputs-metadata-property, so that
|
|
@@ -175,7 +181,7 @@ const createAngularComponentDefinition = (tagName, inputs, outputs, methods, inc
|
|
|
175
181
|
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
176
182
|
template: '<ng-content></ng-content>',
|
|
177
183
|
// eslint-disable-next-line @angular-eslint/no-inputs-metadata-property
|
|
178
|
-
inputs: [${formattedInputs}]
|
|
184
|
+
inputs: [${formattedInputs}],${standaloneOption}
|
|
179
185
|
})
|
|
180
186
|
export class ${tagNameAsPascal} {
|
|
181
187
|
protected el: HTMLElement;
|
|
@@ -232,15 +238,13 @@ const createDocComment = (doc) => {
|
|
|
232
238
|
* @param tagNameAsPascal The tag name as PascalCase.
|
|
233
239
|
* @param events The events to generate the interface properties for.
|
|
234
240
|
* @param componentCorePackage The component core package.
|
|
235
|
-
* @param includeImportCustomElements Whether to include the import for the custom element definition.
|
|
236
241
|
* @param customElementsDir The custom elements directory.
|
|
237
242
|
* @returns The component interface type definition as a string.
|
|
238
243
|
*/
|
|
239
|
-
const createComponentTypeDefinition = (tagNameAsPascal, events, componentCorePackage,
|
|
244
|
+
const createComponentTypeDefinition = (tagNameAsPascal, events, componentCorePackage, customElementsDir) => {
|
|
240
245
|
const publicEvents = events.filter((ev) => !ev.internal);
|
|
241
246
|
const eventTypeImports = createComponentEventTypeImports(tagNameAsPascal, publicEvents, {
|
|
242
247
|
componentCorePackage,
|
|
243
|
-
includeImportCustomElements,
|
|
244
248
|
customElementsDir,
|
|
245
249
|
});
|
|
246
250
|
const eventTypes = publicEvents.map((event) => {
|
|
@@ -387,11 +391,13 @@ async function copyResources$1(config, outputTarget) {
|
|
|
387
391
|
], srcDirectory);
|
|
388
392
|
}
|
|
389
393
|
function generateProxies(components, pkgData, outputTarget, rootDir) {
|
|
390
|
-
var _a;
|
|
391
394
|
const distTypesDir = path__default['default'].dirname(pkgData.types);
|
|
392
395
|
const dtsFilePath = path__default['default'].join(rootDir, distTypesDir, GENERATED_DTS);
|
|
393
396
|
const componentsTypeFile = relativeImport(outputTarget.directivesProxyFile, dtsFilePath, '.d.ts');
|
|
394
|
-
const includeSingleComponentAngularModules =
|
|
397
|
+
const includeSingleComponentAngularModules = outputTarget.outputType === 'scam';
|
|
398
|
+
const includeSingleComponentAngularComponents = outputTarget.outputType === 'standalone';
|
|
399
|
+
const isCustomElementsBuild = outputTarget.customElementsDir !== undefined;
|
|
400
|
+
const isStandaloneBuild = outputTarget.outputType === 'standalone';
|
|
395
401
|
const includeOutputImports = components.some((component) => component.events.some((event) => !event.internal));
|
|
396
402
|
/**
|
|
397
403
|
* The collection of named imports from @angular/core.
|
|
@@ -426,10 +432,8 @@ ${createImportStatement(componentLibImports, './angular-component-lib/utils')}\n
|
|
|
426
432
|
let importLocation = outputTarget.componentCorePackage
|
|
427
433
|
? normalizePath(outputTarget.componentCorePackage)
|
|
428
434
|
: normalizePath(componentsTypeFile);
|
|
429
|
-
importLocation += outputTarget.
|
|
430
|
-
|
|
431
|
-
: '';
|
|
432
|
-
return `import ${outputTarget.includeImportCustomElements ? 'type ' : ''}{ ${IMPORT_TYPES} } from '${importLocation}';\n`;
|
|
435
|
+
importLocation += isCustomElementsBuild ? `/${outputTarget.customElementsDir}` : '';
|
|
436
|
+
return `import ${isCustomElementsBuild ? 'type ' : ''}{ ${IMPORT_TYPES} } from '${importLocation}';\n`;
|
|
433
437
|
};
|
|
434
438
|
const typeImports = generateTypeImports();
|
|
435
439
|
let sourceImports = '';
|
|
@@ -439,23 +443,27 @@ ${createImportStatement(componentLibImports, './angular-component-lib/utils')}\n
|
|
|
439
443
|
* IonButton would be imported as IonButtonCmp so as to not conflict with the
|
|
440
444
|
* IonButton React Component that takes in the Web Component as a parameter.
|
|
441
445
|
*/
|
|
442
|
-
if (
|
|
446
|
+
if (isCustomElementsBuild && outputTarget.componentCorePackage !== undefined) {
|
|
443
447
|
const cmpImports = components.map((component) => {
|
|
444
448
|
const pascalImport = dashToPascalCase(component.tagName);
|
|
445
|
-
return `import { defineCustomElement as define${pascalImport} } from '${normalizePath(outputTarget.componentCorePackage)}/${outputTarget.customElementsDir
|
|
449
|
+
return `import { defineCustomElement as define${pascalImport} } from '${normalizePath(outputTarget.componentCorePackage)}/${outputTarget.customElementsDir}/${component.tagName}.js';`;
|
|
446
450
|
});
|
|
447
451
|
sourceImports = cmpImports.join('\n');
|
|
448
452
|
}
|
|
449
|
-
if (
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
throw new Error('Generating single component Angular modules requires the "
|
|
453
|
+
if (!isCustomElementsBuild) {
|
|
454
|
+
if (includeSingleComponentAngularModules) {
|
|
455
|
+
// Generating Angular modules is only supported in the dist-custom-elements build
|
|
456
|
+
throw new Error('Generating single component Angular modules requires the "customElementsDir" option to be set.');
|
|
457
|
+
}
|
|
458
|
+
if (includeSingleComponentAngularComponents) {
|
|
459
|
+
// Generates Angular standalone components is only supported in the dist-custom-elements build
|
|
460
|
+
throw new Error('Generating standalone Angular components requires the "customElementsDir" option to be set.');
|
|
453
461
|
}
|
|
454
462
|
}
|
|
455
463
|
const proxyFileOutput = [];
|
|
456
464
|
const filterInternalProps = (prop) => !prop.internal;
|
|
457
465
|
const mapPropName = (prop) => prop.name;
|
|
458
|
-
const {
|
|
466
|
+
const { componentCorePackage, customElementsDir } = outputTarget;
|
|
459
467
|
for (let cmpMeta of components) {
|
|
460
468
|
const tagNameAsPascal = dashToPascalCase(cmpMeta.tagName);
|
|
461
469
|
const inputs = [];
|
|
@@ -480,9 +488,9 @@ ${createImportStatement(componentLibImports, './angular-component-lib/utils')}\n
|
|
|
480
488
|
* 2. Optionally the @NgModule decorated class (if includeSingleComponentAngularModules is true)
|
|
481
489
|
* 3. The component interface (using declaration merging for types).
|
|
482
490
|
*/
|
|
483
|
-
const componentDefinition = createAngularComponentDefinition(cmpMeta.tagName, inputs, outputs, methods,
|
|
491
|
+
const componentDefinition = createAngularComponentDefinition(cmpMeta.tagName, inputs, outputs, methods, isCustomElementsBuild, isStandaloneBuild);
|
|
484
492
|
const moduleDefinition = generateAngularModuleForComponent(cmpMeta.tagName);
|
|
485
|
-
const componentTypeDefinition = createComponentTypeDefinition(tagNameAsPascal, cmpMeta.events, componentCorePackage,
|
|
493
|
+
const componentTypeDefinition = createComponentTypeDefinition(tagNameAsPascal, cmpMeta.events, componentCorePackage, customElementsDir);
|
|
486
494
|
proxyFileOutput.push(componentDefinition, '\n');
|
|
487
495
|
if (includeSingleComponentAngularModules) {
|
|
488
496
|
proxyFileOutput.push(moduleDefinition, '\n');
|
|
@@ -522,7 +530,10 @@ function normalizeOutputTarget(config, outputTarget) {
|
|
|
522
530
|
results.directivesArrayFile = normalizePath(path__default['default'].join(config.rootDir, outputTarget.directivesArrayFile));
|
|
523
531
|
}
|
|
524
532
|
if (outputTarget.includeSingleComponentAngularModules !== undefined) {
|
|
525
|
-
|
|
533
|
+
throw new Error("The 'includeSingleComponentAngularModules' option has been removed. Please use 'outputType' instead.");
|
|
534
|
+
}
|
|
535
|
+
if (outputTarget.outputType === 'scam') {
|
|
536
|
+
console.warn('**Experimental**: outputType: "scam" is a developer preview feature and may change or be removed in the future.');
|
|
526
537
|
}
|
|
527
538
|
return results;
|
|
528
539
|
}
|
package/dist/index.js
CHANGED
|
@@ -100,10 +100,11 @@ const createImportStatement = (imports, module) => {
|
|
|
100
100
|
* @returns The import statements as an array of strings.
|
|
101
101
|
*/
|
|
102
102
|
const createComponentEventTypeImports = (componentTagName, events, options) => {
|
|
103
|
-
const { componentCorePackage,
|
|
103
|
+
const { componentCorePackage, customElementsDir } = options;
|
|
104
104
|
const imports = [];
|
|
105
105
|
const namedImports = new Set();
|
|
106
|
-
const
|
|
106
|
+
const isCustomElementsBuild = customElementsDir !== undefined;
|
|
107
|
+
const importPathName = normalizePath(componentCorePackage) + (isCustomElementsBuild ? `/${customElementsDir}` : '');
|
|
107
108
|
events.forEach((event) => {
|
|
108
109
|
Object.entries(event.complexType.references).forEach(([typeName, refObject]) => {
|
|
109
110
|
if (refObject.location === 'local' || refObject.location === 'import') {
|
|
@@ -130,9 +131,10 @@ const SLASH_REGEX = /\\/g;
|
|
|
130
131
|
* @param outputs The outputs/events of the Stencil component. (e.g. ['myOutput']).
|
|
131
132
|
* @param methods The methods of the Stencil component. (e.g. ['myMethod']).
|
|
132
133
|
* @param includeImportCustomElements Whether to define the component as a custom element.
|
|
134
|
+
* @param standalone Whether to define the component as a standalone component.
|
|
133
135
|
* @returns The component declaration as a string.
|
|
134
136
|
*/
|
|
135
|
-
const createAngularComponentDefinition = (tagName, inputs, outputs, methods, includeImportCustomElements = false) => {
|
|
137
|
+
const createAngularComponentDefinition = (tagName, inputs, outputs, methods, includeImportCustomElements = false, standalone = false) => {
|
|
136
138
|
const tagNameAsPascal = dashToPascalCase(tagName);
|
|
137
139
|
const hasInputs = inputs.length > 0;
|
|
138
140
|
const hasOutputs = outputs.length > 0;
|
|
@@ -154,6 +156,10 @@ const createAngularComponentDefinition = (tagName, inputs, outputs, methods, inc
|
|
|
154
156
|
if (hasMethods) {
|
|
155
157
|
proxyCmpOptions.push(`\n methods: [${formattedMethods}]`);
|
|
156
158
|
}
|
|
159
|
+
let standaloneOption = '';
|
|
160
|
+
if (standalone && includeImportCustomElements) {
|
|
161
|
+
standaloneOption = `\n standalone: true`;
|
|
162
|
+
}
|
|
157
163
|
/**
|
|
158
164
|
* Notes on the generated output:
|
|
159
165
|
* - We disable @angular-eslint/no-inputs-metadata-property, so that
|
|
@@ -167,7 +173,7 @@ const createAngularComponentDefinition = (tagName, inputs, outputs, methods, inc
|
|
|
167
173
|
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
168
174
|
template: '<ng-content></ng-content>',
|
|
169
175
|
// eslint-disable-next-line @angular-eslint/no-inputs-metadata-property
|
|
170
|
-
inputs: [${formattedInputs}]
|
|
176
|
+
inputs: [${formattedInputs}],${standaloneOption}
|
|
171
177
|
})
|
|
172
178
|
export class ${tagNameAsPascal} {
|
|
173
179
|
protected el: HTMLElement;
|
|
@@ -224,15 +230,13 @@ const createDocComment = (doc) => {
|
|
|
224
230
|
* @param tagNameAsPascal The tag name as PascalCase.
|
|
225
231
|
* @param events The events to generate the interface properties for.
|
|
226
232
|
* @param componentCorePackage The component core package.
|
|
227
|
-
* @param includeImportCustomElements Whether to include the import for the custom element definition.
|
|
228
233
|
* @param customElementsDir The custom elements directory.
|
|
229
234
|
* @returns The component interface type definition as a string.
|
|
230
235
|
*/
|
|
231
|
-
const createComponentTypeDefinition = (tagNameAsPascal, events, componentCorePackage,
|
|
236
|
+
const createComponentTypeDefinition = (tagNameAsPascal, events, componentCorePackage, customElementsDir) => {
|
|
232
237
|
const publicEvents = events.filter((ev) => !ev.internal);
|
|
233
238
|
const eventTypeImports = createComponentEventTypeImports(tagNameAsPascal, publicEvents, {
|
|
234
239
|
componentCorePackage,
|
|
235
|
-
includeImportCustomElements,
|
|
236
240
|
customElementsDir,
|
|
237
241
|
});
|
|
238
242
|
const eventTypes = publicEvents.map((event) => {
|
|
@@ -379,11 +383,13 @@ async function copyResources$1(config, outputTarget) {
|
|
|
379
383
|
], srcDirectory);
|
|
380
384
|
}
|
|
381
385
|
function generateProxies(components, pkgData, outputTarget, rootDir) {
|
|
382
|
-
var _a;
|
|
383
386
|
const distTypesDir = path.dirname(pkgData.types);
|
|
384
387
|
const dtsFilePath = path.join(rootDir, distTypesDir, GENERATED_DTS);
|
|
385
388
|
const componentsTypeFile = relativeImport(outputTarget.directivesProxyFile, dtsFilePath, '.d.ts');
|
|
386
|
-
const includeSingleComponentAngularModules =
|
|
389
|
+
const includeSingleComponentAngularModules = outputTarget.outputType === 'scam';
|
|
390
|
+
const includeSingleComponentAngularComponents = outputTarget.outputType === 'standalone';
|
|
391
|
+
const isCustomElementsBuild = outputTarget.customElementsDir !== undefined;
|
|
392
|
+
const isStandaloneBuild = outputTarget.outputType === 'standalone';
|
|
387
393
|
const includeOutputImports = components.some((component) => component.events.some((event) => !event.internal));
|
|
388
394
|
/**
|
|
389
395
|
* The collection of named imports from @angular/core.
|
|
@@ -418,10 +424,8 @@ ${createImportStatement(componentLibImports, './angular-component-lib/utils')}\n
|
|
|
418
424
|
let importLocation = outputTarget.componentCorePackage
|
|
419
425
|
? normalizePath(outputTarget.componentCorePackage)
|
|
420
426
|
: normalizePath(componentsTypeFile);
|
|
421
|
-
importLocation += outputTarget.
|
|
422
|
-
|
|
423
|
-
: '';
|
|
424
|
-
return `import ${outputTarget.includeImportCustomElements ? 'type ' : ''}{ ${IMPORT_TYPES} } from '${importLocation}';\n`;
|
|
427
|
+
importLocation += isCustomElementsBuild ? `/${outputTarget.customElementsDir}` : '';
|
|
428
|
+
return `import ${isCustomElementsBuild ? 'type ' : ''}{ ${IMPORT_TYPES} } from '${importLocation}';\n`;
|
|
425
429
|
};
|
|
426
430
|
const typeImports = generateTypeImports();
|
|
427
431
|
let sourceImports = '';
|
|
@@ -431,23 +435,27 @@ ${createImportStatement(componentLibImports, './angular-component-lib/utils')}\n
|
|
|
431
435
|
* IonButton would be imported as IonButtonCmp so as to not conflict with the
|
|
432
436
|
* IonButton React Component that takes in the Web Component as a parameter.
|
|
433
437
|
*/
|
|
434
|
-
if (
|
|
438
|
+
if (isCustomElementsBuild && outputTarget.componentCorePackage !== undefined) {
|
|
435
439
|
const cmpImports = components.map((component) => {
|
|
436
440
|
const pascalImport = dashToPascalCase(component.tagName);
|
|
437
|
-
return `import { defineCustomElement as define${pascalImport} } from '${normalizePath(outputTarget.componentCorePackage)}/${outputTarget.customElementsDir
|
|
441
|
+
return `import { defineCustomElement as define${pascalImport} } from '${normalizePath(outputTarget.componentCorePackage)}/${outputTarget.customElementsDir}/${component.tagName}.js';`;
|
|
438
442
|
});
|
|
439
443
|
sourceImports = cmpImports.join('\n');
|
|
440
444
|
}
|
|
441
|
-
if (
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
throw new Error('Generating single component Angular modules requires the "
|
|
445
|
+
if (!isCustomElementsBuild) {
|
|
446
|
+
if (includeSingleComponentAngularModules) {
|
|
447
|
+
// Generating Angular modules is only supported in the dist-custom-elements build
|
|
448
|
+
throw new Error('Generating single component Angular modules requires the "customElementsDir" option to be set.');
|
|
449
|
+
}
|
|
450
|
+
if (includeSingleComponentAngularComponents) {
|
|
451
|
+
// Generates Angular standalone components is only supported in the dist-custom-elements build
|
|
452
|
+
throw new Error('Generating standalone Angular components requires the "customElementsDir" option to be set.');
|
|
445
453
|
}
|
|
446
454
|
}
|
|
447
455
|
const proxyFileOutput = [];
|
|
448
456
|
const filterInternalProps = (prop) => !prop.internal;
|
|
449
457
|
const mapPropName = (prop) => prop.name;
|
|
450
|
-
const {
|
|
458
|
+
const { componentCorePackage, customElementsDir } = outputTarget;
|
|
451
459
|
for (let cmpMeta of components) {
|
|
452
460
|
const tagNameAsPascal = dashToPascalCase(cmpMeta.tagName);
|
|
453
461
|
const inputs = [];
|
|
@@ -472,9 +480,9 @@ ${createImportStatement(componentLibImports, './angular-component-lib/utils')}\n
|
|
|
472
480
|
* 2. Optionally the @NgModule decorated class (if includeSingleComponentAngularModules is true)
|
|
473
481
|
* 3. The component interface (using declaration merging for types).
|
|
474
482
|
*/
|
|
475
|
-
const componentDefinition = createAngularComponentDefinition(cmpMeta.tagName, inputs, outputs, methods,
|
|
483
|
+
const componentDefinition = createAngularComponentDefinition(cmpMeta.tagName, inputs, outputs, methods, isCustomElementsBuild, isStandaloneBuild);
|
|
476
484
|
const moduleDefinition = generateAngularModuleForComponent(cmpMeta.tagName);
|
|
477
|
-
const componentTypeDefinition = createComponentTypeDefinition(tagNameAsPascal, cmpMeta.events, componentCorePackage,
|
|
485
|
+
const componentTypeDefinition = createComponentTypeDefinition(tagNameAsPascal, cmpMeta.events, componentCorePackage, customElementsDir);
|
|
478
486
|
proxyFileOutput.push(componentDefinition, '\n');
|
|
479
487
|
if (includeSingleComponentAngularModules) {
|
|
480
488
|
proxyFileOutput.push(moduleDefinition, '\n');
|
|
@@ -514,7 +522,10 @@ function normalizeOutputTarget(config, outputTarget) {
|
|
|
514
522
|
results.directivesArrayFile = normalizePath(path.join(config.rootDir, outputTarget.directivesArrayFile));
|
|
515
523
|
}
|
|
516
524
|
if (outputTarget.includeSingleComponentAngularModules !== undefined) {
|
|
517
|
-
|
|
525
|
+
throw new Error("The 'includeSingleComponentAngularModules' option has been removed. Please use 'outputType' instead.");
|
|
526
|
+
}
|
|
527
|
+
if (outputTarget.outputType === 'scam') {
|
|
528
|
+
console.warn('**Experimental**: outputType: "scam" is a developer preview feature and may change or be removed in the future.');
|
|
518
529
|
}
|
|
519
530
|
return results;
|
|
520
531
|
}
|
package/dist/output-angular.js
CHANGED
|
@@ -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);
|
|
41
40
|
const componentsTypeFile = relativeImport(outputTarget.directivesProxyFile, dtsFilePath, '.d.ts');
|
|
42
|
-
const includeSingleComponentAngularModules =
|
|
41
|
+
const includeSingleComponentAngularModules = outputTarget.outputType === 'scam';
|
|
42
|
+
const includeSingleComponentAngularComponents = outputTarget.outputType === 'standalone';
|
|
43
|
+
const isCustomElementsBuild = outputTarget.customElementsDir !== undefined;
|
|
44
|
+
const isStandaloneBuild = outputTarget.outputType === '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,10 +76,8 @@ ${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.
|
|
78
|
-
|
|
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 = '';
|
|
@@ -87,23 +87,27 @@ ${createImportStatement(componentLibImports, './angular-component-lib/utils')}\n
|
|
|
87
87
|
* IonButton would be imported as IonButtonCmp so as to not conflict with the
|
|
88
88
|
* IonButton React Component that takes in the Web Component as a parameter.
|
|
89
89
|
*/
|
|
90
|
-
if (
|
|
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
|
|
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 (
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
throw new Error('Generating single component Angular modules requires the "
|
|
97
|
+
if (!isCustomElementsBuild) {
|
|
98
|
+
if (includeSingleComponentAngularModules) {
|
|
99
|
+
// Generating Angular modules is only supported in the dist-custom-elements build
|
|
100
|
+
throw new Error('Generating single component Angular modules requires the "customElementsDir" option to be set.');
|
|
101
|
+
}
|
|
102
|
+
if (includeSingleComponentAngularComponents) {
|
|
103
|
+
// Generates Angular standalone components is only supported in the dist-custom-elements build
|
|
104
|
+
throw new Error('Generating standalone Angular components requires the "customElementsDir" option to be set.');
|
|
101
105
|
}
|
|
102
106
|
}
|
|
103
107
|
const proxyFileOutput = [];
|
|
104
108
|
const filterInternalProps = (prop) => !prop.internal;
|
|
105
109
|
const mapPropName = (prop) => prop.name;
|
|
106
|
-
const {
|
|
110
|
+
const { componentCorePackage, customElementsDir } = outputTarget;
|
|
107
111
|
for (let cmpMeta of components) {
|
|
108
112
|
const tagNameAsPascal = dashToPascalCase(cmpMeta.tagName);
|
|
109
113
|
const inputs = [];
|
|
@@ -128,9 +132,9 @@ ${createImportStatement(componentLibImports, './angular-component-lib/utils')}\n
|
|
|
128
132
|
* 2. Optionally the @NgModule decorated class (if includeSingleComponentAngularModules is true)
|
|
129
133
|
* 3. The component interface (using declaration merging for types).
|
|
130
134
|
*/
|
|
131
|
-
const componentDefinition = createAngularComponentDefinition(cmpMeta.tagName, inputs, outputs, methods,
|
|
135
|
+
const componentDefinition = createAngularComponentDefinition(cmpMeta.tagName, inputs, outputs, methods, isCustomElementsBuild, isStandaloneBuild);
|
|
132
136
|
const moduleDefinition = generateAngularModuleForComponent(cmpMeta.tagName);
|
|
133
|
-
const componentTypeDefinition = createComponentTypeDefinition(tagNameAsPascal, cmpMeta.events, componentCorePackage,
|
|
137
|
+
const componentTypeDefinition = createComponentTypeDefinition(tagNameAsPascal, cmpMeta.events, componentCorePackage, customElementsDir);
|
|
134
138
|
proxyFileOutput.push(componentDefinition, '\n');
|
|
135
139
|
if (includeSingleComponentAngularModules) {
|
|
136
140
|
proxyFileOutput.push(moduleDefinition, '\n');
|
package/dist/plugin.js
CHANGED
|
@@ -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
|
-
|
|
31
|
+
throw new Error("The 'includeSingleComponentAngularModules' option has been removed. Please use 'outputType' instead.");
|
|
32
|
+
}
|
|
33
|
+
if (outputTarget.outputType === 'scam') {
|
|
34
|
+
console.warn('**Experimental**: outputType: "scam" is a developer preview feature and may change or be removed in the future.');
|
|
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
|
-
*
|
|
19
|
-
*
|
|
20
|
-
* `
|
|
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
|
-
|
|
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
|
@@ -30,6 +30,5 @@ export declare const createImportStatement: (imports: string[], module: string)
|
|
|
30
30
|
*/
|
|
31
31
|
export declare const createComponentEventTypeImports: (componentTagName: string, events: readonly ComponentCompilerEvent[], options: {
|
|
32
32
|
componentCorePackage: string;
|
|
33
|
-
includeImportCustomElements?: boolean;
|
|
34
33
|
customElementsDir?: string;
|
|
35
34
|
}) => string;
|
package/dist/utils.js
CHANGED
|
@@ -101,10 +101,11 @@ export const createImportStatement = (imports, module) => {
|
|
|
101
101
|
* @returns The import statements as an array of strings.
|
|
102
102
|
*/
|
|
103
103
|
export const createComponentEventTypeImports = (componentTagName, events, options) => {
|
|
104
|
-
const { componentCorePackage,
|
|
104
|
+
const { componentCorePackage, customElementsDir } = options;
|
|
105
105
|
const imports = [];
|
|
106
106
|
const namedImports = new Set();
|
|
107
|
-
const
|
|
107
|
+
const isCustomElementsBuild = customElementsDir !== undefined;
|
|
108
|
+
const importPathName = normalizePath(componentCorePackage) + (isCustomElementsBuild ? `/${customElementsDir}` : '');
|
|
108
109
|
events.forEach((event) => {
|
|
109
110
|
Object.entries(event.complexType.references).forEach(([typeName, refObject]) => {
|
|
110
111
|
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.
|
|
3
|
+
"version": "0.8.1-dev.11690825475.1243803f",
|
|
4
4
|
"description": "Angular output target for @stencil/core components.",
|
|
5
5
|
"main": "dist/index.cjs.js",
|
|
6
6
|
"module": "dist/index.js",
|
|
@@ -42,7 +42,7 @@
|
|
|
42
42
|
"@angular/forms": "8.2.14"
|
|
43
43
|
},
|
|
44
44
|
"peerDependencies": {
|
|
45
|
-
"@stencil/core": "
|
|
45
|
+
"@stencil/core": ">=2.0.0 || >=3 || >= 4.0.0-beta.0 || >= 4.0.0"
|
|
46
46
|
},
|
|
47
47
|
"jest": {
|
|
48
48
|
"transform": {
|
|
@@ -58,7 +58,7 @@
|
|
|
58
58
|
],
|
|
59
59
|
"testURL": "http://localhost"
|
|
60
60
|
},
|
|
61
|
-
"gitHead": "
|
|
61
|
+
"gitHead": "243803f02d0675190181da7ed8ad6ff432c3ee1d",
|
|
62
62
|
"volta": {
|
|
63
63
|
"extends": "../../package.json"
|
|
64
64
|
}
|