@stencil/angular-output-target 0.10.2 → 1.1.0
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 +7 -0
- package/dist/generate-angular-component.d.ts +3 -3
- package/dist/generate-angular-component.js +29 -7
- package/dist/generate-value-accessors.js +2 -2
- package/dist/index.cjs.js +45 -14
- package/dist/index.js +45 -14
- package/dist/output-angular.js +13 -6
- package/dist/plugin.js +2 -1
- package/dist/types.d.ts +6 -2
- package/dist/utils.d.ts +3 -0
- package/dist/utils.js +1 -0
- package/package.json +4 -3
- package/resources/control-value-accessors/boolean-value-accessor.ts +1 -1
- package/resources/control-value-accessors/number-value-accessor.ts +1 -1
- package/resources/control-value-accessors/radio-value-accessor.ts +1 -1
- package/resources/control-value-accessors/select-value-accessor.ts +1 -1
- package/resources/control-value-accessors/text-value-accessor.ts +1 -1
package/README.md
CHANGED
|
@@ -14,6 +14,13 @@ For a detailed guide on how to add the angular output target to a project, visit
|
|
|
14
14
|
npm install @stencil/angular-output-target
|
|
15
15
|
```
|
|
16
16
|
|
|
17
|
+
## Angular Support
|
|
18
|
+
|
|
19
|
+
| **@stencil/angular-output-target** | **Angular** |
|
|
20
|
+
|------------------------------------|-----------------|
|
|
21
|
+
| 0.10.2 | v18.x and lower |
|
|
22
|
+
| 1.0.0 | v19.x and above |
|
|
23
|
+
|
|
17
24
|
## Usage
|
|
18
25
|
|
|
19
26
|
In your `stencil.config.ts` add the following configuration to the `outputTargets` section:
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import type { ComponentCompilerEvent, ComponentCompilerProperty } from '@stencil/core/internal';
|
|
2
|
-
import type { OutputType } from './types';
|
|
2
|
+
import type { ComponentInputProperty, OutputType } from './types';
|
|
3
3
|
/**
|
|
4
4
|
* Creates an Angular component declaration from formatted Stencil compiler metadata.
|
|
5
5
|
*
|
|
6
6
|
* @param tagName The tag name of the component.
|
|
7
|
-
* @param inputs The inputs of the Stencil component (e.g. ['myInput']).
|
|
7
|
+
* @param inputs The inputs of the Stencil component (e.g. [{name: 'myInput', required: true]).
|
|
8
8
|
* @param outputs The outputs/events of the Stencil component. (e.g. ['myOutput']).
|
|
9
9
|
* @param methods The methods of the Stencil component. (e.g. ['myMethod']).
|
|
10
10
|
* @param includeImportCustomElements Whether to define the component as a custom element.
|
|
@@ -12,7 +12,7 @@ import type { OutputType } from './types';
|
|
|
12
12
|
* @param inlineComponentProps List of properties that should be inlined into the component definition.
|
|
13
13
|
* @returns The component declaration as a string.
|
|
14
14
|
*/
|
|
15
|
-
export declare const createAngularComponentDefinition: (tagName: string, inputs: readonly
|
|
15
|
+
export declare const createAngularComponentDefinition: (tagName: string, inputs: readonly ComponentInputProperty[], outputs: readonly string[], methods: readonly string[], includeImportCustomElements?: boolean, standalone?: boolean, inlineComponentProps?: readonly ComponentCompilerProperty[]) => string;
|
|
16
16
|
/**
|
|
17
17
|
* Creates the component interface type definition.
|
|
18
18
|
* @param outputType The output type.
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { createComponentEventTypeImports, dashToPascalCase, formatToQuotedList } from './utils';
|
|
1
|
+
import { createComponentEventTypeImports, dashToPascalCase, formatToQuotedList, mapPropName } from './utils';
|
|
2
2
|
/**
|
|
3
3
|
* Creates a property declaration.
|
|
4
4
|
*
|
|
@@ -12,7 +12,7 @@ function createPropertyDeclaration(prop, type, inlinePropertyAsSetter = false) {
|
|
|
12
12
|
let eventName = prop.name;
|
|
13
13
|
if (/[-/]/.test(prop.name)) {
|
|
14
14
|
// If a member name includes a dash or a forward slash, we need to wrap it in quotes.
|
|
15
|
-
// https://github.com/
|
|
15
|
+
// https://github.com/stenciljs/output-targets/issues/212
|
|
16
16
|
eventName = `'${prop.name}'`;
|
|
17
17
|
}
|
|
18
18
|
if (inlinePropertyAsSetter) {
|
|
@@ -24,11 +24,30 @@ function createPropertyDeclaration(prop, type, inlinePropertyAsSetter = false) {
|
|
|
24
24
|
${eventName}: ${type};`;
|
|
25
25
|
}
|
|
26
26
|
}
|
|
27
|
+
/**
|
|
28
|
+
* Creates a formatted inputs text with required declaration.
|
|
29
|
+
*
|
|
30
|
+
* @param prop A ComponentCompilerEvent or ComponentCompilerProperty to turn into a property declaration.
|
|
31
|
+
* @param inputs The inputs of the Stencil component (e.g. [{name: 'myInput', required: true]).
|
|
32
|
+
* @returns The inputs list declaration as a string.
|
|
33
|
+
*/
|
|
34
|
+
function formatInputs(inputs) {
|
|
35
|
+
return inputs
|
|
36
|
+
.map((item) => {
|
|
37
|
+
if (item.required) {
|
|
38
|
+
return `{ name: '${item.name}', required: true }`;
|
|
39
|
+
}
|
|
40
|
+
else {
|
|
41
|
+
return `'${item.name}'`;
|
|
42
|
+
}
|
|
43
|
+
})
|
|
44
|
+
.join(', ');
|
|
45
|
+
}
|
|
27
46
|
/**
|
|
28
47
|
* Creates an Angular component declaration from formatted Stencil compiler metadata.
|
|
29
48
|
*
|
|
30
49
|
* @param tagName The tag name of the component.
|
|
31
|
-
* @param inputs The inputs of the Stencil component (e.g. ['myInput']).
|
|
50
|
+
* @param inputs The inputs of the Stencil component (e.g. [{name: 'myInput', required: true]).
|
|
32
51
|
* @param outputs The outputs/events of the Stencil component. (e.g. ['myOutput']).
|
|
33
52
|
* @param methods The methods of the Stencil component. (e.g. ['myMethod']).
|
|
34
53
|
* @param includeImportCustomElements Whether to define the component as a custom element.
|
|
@@ -42,7 +61,10 @@ export const createAngularComponentDefinition = (tagName, inputs, outputs, metho
|
|
|
42
61
|
const hasOutputs = outputs.length > 0;
|
|
43
62
|
const hasMethods = methods.length > 0;
|
|
44
63
|
// Formats the input strings into comma separated, single quoted values.
|
|
45
|
-
const
|
|
64
|
+
const proxyCmpFormattedInputs = formatToQuotedList(inputs.map(mapPropName));
|
|
65
|
+
// Formats the input strings into comma separated, single quoted values if optional.
|
|
66
|
+
// Formats the required input strings into comma separated {name, required} objects.
|
|
67
|
+
const formattedInputs = formatInputs(inputs);
|
|
46
68
|
// Formats the output strings into comma separated, single quoted values.
|
|
47
69
|
const formattedOutputs = formatToQuotedList(outputs);
|
|
48
70
|
// Formats the method strings into comma separated, single quoted values.
|
|
@@ -53,14 +75,14 @@ export const createAngularComponentDefinition = (tagName, inputs, outputs, metho
|
|
|
53
75
|
proxyCmpOptions.push(`\n defineCustomElementFn: ${defineCustomElementFn}`);
|
|
54
76
|
}
|
|
55
77
|
if (hasInputs) {
|
|
56
|
-
proxyCmpOptions.push(`\n inputs: [${
|
|
78
|
+
proxyCmpOptions.push(`\n inputs: [${proxyCmpFormattedInputs}]`);
|
|
57
79
|
}
|
|
58
80
|
if (hasMethods) {
|
|
59
81
|
proxyCmpOptions.push(`\n methods: [${formattedMethods}]`);
|
|
60
82
|
}
|
|
61
83
|
let standaloneOption = '';
|
|
62
|
-
if (standalone
|
|
63
|
-
standaloneOption = `\n standalone:
|
|
84
|
+
if (!standalone) {
|
|
85
|
+
standaloneOption = `\n standalone: false`;
|
|
64
86
|
}
|
|
65
87
|
const propertyDeclarations = inlineComponentProps.map((m) => createPropertyDeclaration(m, `Components.${tagNameAsPascal}['${m.name}']`, true));
|
|
66
88
|
const propertiesDeclarationText = [`protected el: HTML${tagNameAsPascal}Element;`, ...propertyDeclarations].join('\n ');
|
|
@@ -36,7 +36,7 @@ export function createValueAccessor(srcFileContents, valueAccessor, outputType)
|
|
|
36
36
|
return srcFileContents
|
|
37
37
|
.replace(VALUE_ACCESSOR_SELECTORS, valueAccessor.elementSelectors.join(', '))
|
|
38
38
|
.replace(VALUE_ACCESSOR_EVENTTARGETS, hostContents.join(`,${EOL}`))
|
|
39
|
-
.replace(VALUE_ACCESSOR_STANDALONE, outputType && outputType
|
|
39
|
+
.replace(VALUE_ACCESSOR_STANDALONE, outputType && outputType !== OutputTypes.Standalone ? ',\nstandalone: false' : '');
|
|
40
40
|
}
|
|
41
41
|
function copyResources(config, resourcesFilesToCopy, directory) {
|
|
42
42
|
if (!config.sys || !config.sys.copy) {
|
|
@@ -57,4 +57,4 @@ const VALUE_ACCESSOR_SELECTORS = `<VALUE_ACCESSOR_SELECTORS>`;
|
|
|
57
57
|
const VALUE_ACCESSOR_EVENT = `<VALUE_ACCESSOR_EVENT>`;
|
|
58
58
|
const VALUE_ACCESSOR_TARGETATTR = '<VALUE_ACCESSOR_TARGETATTR>';
|
|
59
59
|
const VALUE_ACCESSOR_STANDALONE = '<VALUE_ACCESSOR_STANDALONE>';
|
|
60
|
-
const VALUE_ACCESSOR_EVENTTARGETS = ` '(<VALUE_ACCESSOR_EVENT>)': 'handleChangeEvent($event.target
|
|
60
|
+
const VALUE_ACCESSOR_EVENTTARGETS = ` '(<VALUE_ACCESSOR_EVENT>)': 'handleChangeEvent($event.target?.["<VALUE_ACCESSOR_TARGETATTR>"])'`;
|
package/dist/index.cjs.js
CHANGED
|
@@ -15,6 +15,7 @@ const OutputTypes = {
|
|
|
15
15
|
Standalone: 'standalone',
|
|
16
16
|
};
|
|
17
17
|
const toLowerCase = (str) => str.toLowerCase();
|
|
18
|
+
const mapPropName = (prop) => prop.name;
|
|
18
19
|
const dashToPascalCase = (str) => toLowerCase(str)
|
|
19
20
|
.split('-')
|
|
20
21
|
.map((segment) => segment.charAt(0).toUpperCase() + segment.slice(1))
|
|
@@ -157,7 +158,7 @@ function createPropertyDeclaration(prop, type, inlinePropertyAsSetter = false) {
|
|
|
157
158
|
let eventName = prop.name;
|
|
158
159
|
if (/[-/]/.test(prop.name)) {
|
|
159
160
|
// If a member name includes a dash or a forward slash, we need to wrap it in quotes.
|
|
160
|
-
// https://github.com/
|
|
161
|
+
// https://github.com/stenciljs/output-targets/issues/212
|
|
161
162
|
eventName = `'${prop.name}'`;
|
|
162
163
|
}
|
|
163
164
|
if (inlinePropertyAsSetter) {
|
|
@@ -169,11 +170,30 @@ function createPropertyDeclaration(prop, type, inlinePropertyAsSetter = false) {
|
|
|
169
170
|
${eventName}: ${type};`;
|
|
170
171
|
}
|
|
171
172
|
}
|
|
173
|
+
/**
|
|
174
|
+
* Creates a formatted inputs text with required declaration.
|
|
175
|
+
*
|
|
176
|
+
* @param prop A ComponentCompilerEvent or ComponentCompilerProperty to turn into a property declaration.
|
|
177
|
+
* @param inputs The inputs of the Stencil component (e.g. [{name: 'myInput', required: true]).
|
|
178
|
+
* @returns The inputs list declaration as a string.
|
|
179
|
+
*/
|
|
180
|
+
function formatInputs(inputs) {
|
|
181
|
+
return inputs
|
|
182
|
+
.map((item) => {
|
|
183
|
+
if (item.required) {
|
|
184
|
+
return `{ name: '${item.name}', required: true }`;
|
|
185
|
+
}
|
|
186
|
+
else {
|
|
187
|
+
return `'${item.name}'`;
|
|
188
|
+
}
|
|
189
|
+
})
|
|
190
|
+
.join(', ');
|
|
191
|
+
}
|
|
172
192
|
/**
|
|
173
193
|
* Creates an Angular component declaration from formatted Stencil compiler metadata.
|
|
174
194
|
*
|
|
175
195
|
* @param tagName The tag name of the component.
|
|
176
|
-
* @param inputs The inputs of the Stencil component (e.g. ['myInput']).
|
|
196
|
+
* @param inputs The inputs of the Stencil component (e.g. [{name: 'myInput', required: true]).
|
|
177
197
|
* @param outputs The outputs/events of the Stencil component. (e.g. ['myOutput']).
|
|
178
198
|
* @param methods The methods of the Stencil component. (e.g. ['myMethod']).
|
|
179
199
|
* @param includeImportCustomElements Whether to define the component as a custom element.
|
|
@@ -187,7 +207,10 @@ const createAngularComponentDefinition = (tagName, inputs, outputs, methods, inc
|
|
|
187
207
|
const hasOutputs = outputs.length > 0;
|
|
188
208
|
const hasMethods = methods.length > 0;
|
|
189
209
|
// Formats the input strings into comma separated, single quoted values.
|
|
190
|
-
const
|
|
210
|
+
const proxyCmpFormattedInputs = formatToQuotedList(inputs.map(mapPropName));
|
|
211
|
+
// Formats the input strings into comma separated, single quoted values if optional.
|
|
212
|
+
// Formats the required input strings into comma separated {name, required} objects.
|
|
213
|
+
const formattedInputs = formatInputs(inputs);
|
|
191
214
|
// Formats the output strings into comma separated, single quoted values.
|
|
192
215
|
const formattedOutputs = formatToQuotedList(outputs);
|
|
193
216
|
// Formats the method strings into comma separated, single quoted values.
|
|
@@ -198,14 +221,14 @@ const createAngularComponentDefinition = (tagName, inputs, outputs, methods, inc
|
|
|
198
221
|
proxyCmpOptions.push(`\n defineCustomElementFn: ${defineCustomElementFn}`);
|
|
199
222
|
}
|
|
200
223
|
if (hasInputs) {
|
|
201
|
-
proxyCmpOptions.push(`\n inputs: [${
|
|
224
|
+
proxyCmpOptions.push(`\n inputs: [${proxyCmpFormattedInputs}]`);
|
|
202
225
|
}
|
|
203
226
|
if (hasMethods) {
|
|
204
227
|
proxyCmpOptions.push(`\n methods: [${formattedMethods}]`);
|
|
205
228
|
}
|
|
206
229
|
let standaloneOption = '';
|
|
207
|
-
if (standalone
|
|
208
|
-
standaloneOption = `\n standalone:
|
|
230
|
+
if (!standalone) {
|
|
231
|
+
standaloneOption = `\n standalone: false`;
|
|
209
232
|
}
|
|
210
233
|
const propertyDeclarations = inlineComponentProps.map((m) => createPropertyDeclaration(m, `Components.${tagNameAsPascal}['${m.name}']`, true));
|
|
211
234
|
const propertiesDeclarationText = [`protected el: HTML${tagNameAsPascal}Element;`, ...propertyDeclarations].join('\n ');
|
|
@@ -389,7 +412,7 @@ function createValueAccessor(srcFileContents, valueAccessor, outputType) {
|
|
|
389
412
|
return srcFileContents
|
|
390
413
|
.replace(VALUE_ACCESSOR_SELECTORS, valueAccessor.elementSelectors.join(', '))
|
|
391
414
|
.replace(VALUE_ACCESSOR_EVENTTARGETS, hostContents.join(`,${os.EOL}`))
|
|
392
|
-
.replace(VALUE_ACCESSOR_STANDALONE, outputType && outputType
|
|
415
|
+
.replace(VALUE_ACCESSOR_STANDALONE, outputType && outputType !== OutputTypes.Standalone ? ',\nstandalone: false' : '');
|
|
393
416
|
}
|
|
394
417
|
function copyResources$1(config, resourcesFilesToCopy, directory) {
|
|
395
418
|
if (!config.sys || !config.sys.copy) {
|
|
@@ -410,7 +433,7 @@ const VALUE_ACCESSOR_SELECTORS = `<VALUE_ACCESSOR_SELECTORS>`;
|
|
|
410
433
|
const VALUE_ACCESSOR_EVENT = `<VALUE_ACCESSOR_EVENT>`;
|
|
411
434
|
const VALUE_ACCESSOR_TARGETATTR = '<VALUE_ACCESSOR_TARGETATTR>';
|
|
412
435
|
const VALUE_ACCESSOR_STANDALONE = '<VALUE_ACCESSOR_STANDALONE>';
|
|
413
|
-
const VALUE_ACCESSOR_EVENTTARGETS = ` '(<VALUE_ACCESSOR_EVENT>)': 'handleChangeEvent($event.target
|
|
436
|
+
const VALUE_ACCESSOR_EVENTTARGETS = ` '(<VALUE_ACCESSOR_EVENT>)': 'handleChangeEvent($event.target?.["<VALUE_ACCESSOR_TARGETATTR>"])'`;
|
|
414
437
|
|
|
415
438
|
/**
|
|
416
439
|
* Creates an Angular module declaration for a component wrapper.
|
|
@@ -522,7 +545,14 @@ ${createImportStatement(componentLibImports, './angular-component-lib/utils')}\n
|
|
|
522
545
|
}
|
|
523
546
|
const proxyFileOutput = [];
|
|
524
547
|
const filterInternalProps = (prop) => !prop.internal;
|
|
525
|
-
|
|
548
|
+
// Ensure that virtual properties has required as false.
|
|
549
|
+
const mapInputProp = (prop) => {
|
|
550
|
+
var _a;
|
|
551
|
+
return ({
|
|
552
|
+
name: prop.name,
|
|
553
|
+
required: (_a = prop.required) !== null && _a !== void 0 ? _a : false,
|
|
554
|
+
});
|
|
555
|
+
};
|
|
526
556
|
const { componentCorePackage, customElementsDir } = outputTarget;
|
|
527
557
|
for (let cmpMeta of components) {
|
|
528
558
|
const tagNameAsPascal = dashToPascalCase(cmpMeta.tagName);
|
|
@@ -530,11 +560,11 @@ ${createImportStatement(componentLibImports, './angular-component-lib/utils')}\n
|
|
|
530
560
|
if (cmpMeta.properties) {
|
|
531
561
|
internalProps.push(...cmpMeta.properties.filter(filterInternalProps));
|
|
532
562
|
}
|
|
533
|
-
const inputs = internalProps.map(
|
|
563
|
+
const inputs = internalProps.map(mapInputProp);
|
|
534
564
|
if (cmpMeta.virtualProperties) {
|
|
535
|
-
inputs.push(...cmpMeta.virtualProperties.map(
|
|
565
|
+
inputs.push(...cmpMeta.virtualProperties.map(mapInputProp));
|
|
536
566
|
}
|
|
537
|
-
inputs
|
|
567
|
+
const orderedInputs = sortBy(inputs, (cip) => cip.name);
|
|
538
568
|
const outputs = [];
|
|
539
569
|
if (cmpMeta.events) {
|
|
540
570
|
outputs.push(...cmpMeta.events.filter(filterInternalProps).map(mapPropName));
|
|
@@ -550,7 +580,7 @@ ${createImportStatement(componentLibImports, './angular-component-lib/utils')}\n
|
|
|
550
580
|
* 2. Optionally the @NgModule decorated class (if includeSingleComponentAngularModules is true)
|
|
551
581
|
* 3. The component interface (using declaration merging for types).
|
|
552
582
|
*/
|
|
553
|
-
const componentDefinition = createAngularComponentDefinition(cmpMeta.tagName,
|
|
583
|
+
const componentDefinition = createAngularComponentDefinition(cmpMeta.tagName, orderedInputs, outputs, methods, isCustomElementsBuild, isStandaloneBuild, inlineComponentProps);
|
|
554
584
|
const moduleDefinition = generateAngularModuleForComponent(cmpMeta.tagName);
|
|
555
585
|
const componentTypeDefinition = createComponentTypeDefinition(outputType, tagNameAsPascal, cmpMeta.events, componentCorePackage, customElementsDir);
|
|
556
586
|
proxyFileOutput.push(componentDefinition, '\n');
|
|
@@ -581,7 +611,8 @@ const angularOutputTarget = (outputTarget) => {
|
|
|
581
611
|
};
|
|
582
612
|
};
|
|
583
613
|
function normalizeOutputTarget(config, outputTarget) {
|
|
584
|
-
|
|
614
|
+
var _a, _b;
|
|
615
|
+
const results = Object.assign(Object.assign({}, outputTarget), { excludeComponents: outputTarget.excludeComponents || [], valueAccessorConfigs: outputTarget.valueAccessorConfigs || [], customElementsDir: (_a = outputTarget.customElementsDir) !== null && _a !== void 0 ? _a : 'components', outputType: (_b = outputTarget.outputType) !== null && _b !== void 0 ? _b : OutputTypes.Standalone });
|
|
585
616
|
if (config.rootDir == null) {
|
|
586
617
|
throw new Error('rootDir is not set and it should be set by stencil itself');
|
|
587
618
|
}
|
package/dist/index.js
CHANGED
|
@@ -7,6 +7,7 @@ const OutputTypes = {
|
|
|
7
7
|
Standalone: 'standalone',
|
|
8
8
|
};
|
|
9
9
|
const toLowerCase = (str) => str.toLowerCase();
|
|
10
|
+
const mapPropName = (prop) => prop.name;
|
|
10
11
|
const dashToPascalCase = (str) => toLowerCase(str)
|
|
11
12
|
.split('-')
|
|
12
13
|
.map((segment) => segment.charAt(0).toUpperCase() + segment.slice(1))
|
|
@@ -149,7 +150,7 @@ function createPropertyDeclaration(prop, type, inlinePropertyAsSetter = false) {
|
|
|
149
150
|
let eventName = prop.name;
|
|
150
151
|
if (/[-/]/.test(prop.name)) {
|
|
151
152
|
// If a member name includes a dash or a forward slash, we need to wrap it in quotes.
|
|
152
|
-
// https://github.com/
|
|
153
|
+
// https://github.com/stenciljs/output-targets/issues/212
|
|
153
154
|
eventName = `'${prop.name}'`;
|
|
154
155
|
}
|
|
155
156
|
if (inlinePropertyAsSetter) {
|
|
@@ -161,11 +162,30 @@ function createPropertyDeclaration(prop, type, inlinePropertyAsSetter = false) {
|
|
|
161
162
|
${eventName}: ${type};`;
|
|
162
163
|
}
|
|
163
164
|
}
|
|
165
|
+
/**
|
|
166
|
+
* Creates a formatted inputs text with required declaration.
|
|
167
|
+
*
|
|
168
|
+
* @param prop A ComponentCompilerEvent or ComponentCompilerProperty to turn into a property declaration.
|
|
169
|
+
* @param inputs The inputs of the Stencil component (e.g. [{name: 'myInput', required: true]).
|
|
170
|
+
* @returns The inputs list declaration as a string.
|
|
171
|
+
*/
|
|
172
|
+
function formatInputs(inputs) {
|
|
173
|
+
return inputs
|
|
174
|
+
.map((item) => {
|
|
175
|
+
if (item.required) {
|
|
176
|
+
return `{ name: '${item.name}', required: true }`;
|
|
177
|
+
}
|
|
178
|
+
else {
|
|
179
|
+
return `'${item.name}'`;
|
|
180
|
+
}
|
|
181
|
+
})
|
|
182
|
+
.join(', ');
|
|
183
|
+
}
|
|
164
184
|
/**
|
|
165
185
|
* Creates an Angular component declaration from formatted Stencil compiler metadata.
|
|
166
186
|
*
|
|
167
187
|
* @param tagName The tag name of the component.
|
|
168
|
-
* @param inputs The inputs of the Stencil component (e.g. ['myInput']).
|
|
188
|
+
* @param inputs The inputs of the Stencil component (e.g. [{name: 'myInput', required: true]).
|
|
169
189
|
* @param outputs The outputs/events of the Stencil component. (e.g. ['myOutput']).
|
|
170
190
|
* @param methods The methods of the Stencil component. (e.g. ['myMethod']).
|
|
171
191
|
* @param includeImportCustomElements Whether to define the component as a custom element.
|
|
@@ -179,7 +199,10 @@ const createAngularComponentDefinition = (tagName, inputs, outputs, methods, inc
|
|
|
179
199
|
const hasOutputs = outputs.length > 0;
|
|
180
200
|
const hasMethods = methods.length > 0;
|
|
181
201
|
// Formats the input strings into comma separated, single quoted values.
|
|
182
|
-
const
|
|
202
|
+
const proxyCmpFormattedInputs = formatToQuotedList(inputs.map(mapPropName));
|
|
203
|
+
// Formats the input strings into comma separated, single quoted values if optional.
|
|
204
|
+
// Formats the required input strings into comma separated {name, required} objects.
|
|
205
|
+
const formattedInputs = formatInputs(inputs);
|
|
183
206
|
// Formats the output strings into comma separated, single quoted values.
|
|
184
207
|
const formattedOutputs = formatToQuotedList(outputs);
|
|
185
208
|
// Formats the method strings into comma separated, single quoted values.
|
|
@@ -190,14 +213,14 @@ const createAngularComponentDefinition = (tagName, inputs, outputs, methods, inc
|
|
|
190
213
|
proxyCmpOptions.push(`\n defineCustomElementFn: ${defineCustomElementFn}`);
|
|
191
214
|
}
|
|
192
215
|
if (hasInputs) {
|
|
193
|
-
proxyCmpOptions.push(`\n inputs: [${
|
|
216
|
+
proxyCmpOptions.push(`\n inputs: [${proxyCmpFormattedInputs}]`);
|
|
194
217
|
}
|
|
195
218
|
if (hasMethods) {
|
|
196
219
|
proxyCmpOptions.push(`\n methods: [${formattedMethods}]`);
|
|
197
220
|
}
|
|
198
221
|
let standaloneOption = '';
|
|
199
|
-
if (standalone
|
|
200
|
-
standaloneOption = `\n standalone:
|
|
222
|
+
if (!standalone) {
|
|
223
|
+
standaloneOption = `\n standalone: false`;
|
|
201
224
|
}
|
|
202
225
|
const propertyDeclarations = inlineComponentProps.map((m) => createPropertyDeclaration(m, `Components.${tagNameAsPascal}['${m.name}']`, true));
|
|
203
226
|
const propertiesDeclarationText = [`protected el: HTML${tagNameAsPascal}Element;`, ...propertyDeclarations].join('\n ');
|
|
@@ -381,7 +404,7 @@ function createValueAccessor(srcFileContents, valueAccessor, outputType) {
|
|
|
381
404
|
return srcFileContents
|
|
382
405
|
.replace(VALUE_ACCESSOR_SELECTORS, valueAccessor.elementSelectors.join(', '))
|
|
383
406
|
.replace(VALUE_ACCESSOR_EVENTTARGETS, hostContents.join(`,${EOL}`))
|
|
384
|
-
.replace(VALUE_ACCESSOR_STANDALONE, outputType && outputType
|
|
407
|
+
.replace(VALUE_ACCESSOR_STANDALONE, outputType && outputType !== OutputTypes.Standalone ? ',\nstandalone: false' : '');
|
|
385
408
|
}
|
|
386
409
|
function copyResources$1(config, resourcesFilesToCopy, directory) {
|
|
387
410
|
if (!config.sys || !config.sys.copy) {
|
|
@@ -402,7 +425,7 @@ const VALUE_ACCESSOR_SELECTORS = `<VALUE_ACCESSOR_SELECTORS>`;
|
|
|
402
425
|
const VALUE_ACCESSOR_EVENT = `<VALUE_ACCESSOR_EVENT>`;
|
|
403
426
|
const VALUE_ACCESSOR_TARGETATTR = '<VALUE_ACCESSOR_TARGETATTR>';
|
|
404
427
|
const VALUE_ACCESSOR_STANDALONE = '<VALUE_ACCESSOR_STANDALONE>';
|
|
405
|
-
const VALUE_ACCESSOR_EVENTTARGETS = ` '(<VALUE_ACCESSOR_EVENT>)': 'handleChangeEvent($event.target
|
|
428
|
+
const VALUE_ACCESSOR_EVENTTARGETS = ` '(<VALUE_ACCESSOR_EVENT>)': 'handleChangeEvent($event.target?.["<VALUE_ACCESSOR_TARGETATTR>"])'`;
|
|
406
429
|
|
|
407
430
|
/**
|
|
408
431
|
* Creates an Angular module declaration for a component wrapper.
|
|
@@ -514,7 +537,14 @@ ${createImportStatement(componentLibImports, './angular-component-lib/utils')}\n
|
|
|
514
537
|
}
|
|
515
538
|
const proxyFileOutput = [];
|
|
516
539
|
const filterInternalProps = (prop) => !prop.internal;
|
|
517
|
-
|
|
540
|
+
// Ensure that virtual properties has required as false.
|
|
541
|
+
const mapInputProp = (prop) => {
|
|
542
|
+
var _a;
|
|
543
|
+
return ({
|
|
544
|
+
name: prop.name,
|
|
545
|
+
required: (_a = prop.required) !== null && _a !== void 0 ? _a : false,
|
|
546
|
+
});
|
|
547
|
+
};
|
|
518
548
|
const { componentCorePackage, customElementsDir } = outputTarget;
|
|
519
549
|
for (let cmpMeta of components) {
|
|
520
550
|
const tagNameAsPascal = dashToPascalCase(cmpMeta.tagName);
|
|
@@ -522,11 +552,11 @@ ${createImportStatement(componentLibImports, './angular-component-lib/utils')}\n
|
|
|
522
552
|
if (cmpMeta.properties) {
|
|
523
553
|
internalProps.push(...cmpMeta.properties.filter(filterInternalProps));
|
|
524
554
|
}
|
|
525
|
-
const inputs = internalProps.map(
|
|
555
|
+
const inputs = internalProps.map(mapInputProp);
|
|
526
556
|
if (cmpMeta.virtualProperties) {
|
|
527
|
-
inputs.push(...cmpMeta.virtualProperties.map(
|
|
557
|
+
inputs.push(...cmpMeta.virtualProperties.map(mapInputProp));
|
|
528
558
|
}
|
|
529
|
-
inputs
|
|
559
|
+
const orderedInputs = sortBy(inputs, (cip) => cip.name);
|
|
530
560
|
const outputs = [];
|
|
531
561
|
if (cmpMeta.events) {
|
|
532
562
|
outputs.push(...cmpMeta.events.filter(filterInternalProps).map(mapPropName));
|
|
@@ -542,7 +572,7 @@ ${createImportStatement(componentLibImports, './angular-component-lib/utils')}\n
|
|
|
542
572
|
* 2. Optionally the @NgModule decorated class (if includeSingleComponentAngularModules is true)
|
|
543
573
|
* 3. The component interface (using declaration merging for types).
|
|
544
574
|
*/
|
|
545
|
-
const componentDefinition = createAngularComponentDefinition(cmpMeta.tagName,
|
|
575
|
+
const componentDefinition = createAngularComponentDefinition(cmpMeta.tagName, orderedInputs, outputs, methods, isCustomElementsBuild, isStandaloneBuild, inlineComponentProps);
|
|
546
576
|
const moduleDefinition = generateAngularModuleForComponent(cmpMeta.tagName);
|
|
547
577
|
const componentTypeDefinition = createComponentTypeDefinition(outputType, tagNameAsPascal, cmpMeta.events, componentCorePackage, customElementsDir);
|
|
548
578
|
proxyFileOutput.push(componentDefinition, '\n');
|
|
@@ -573,7 +603,8 @@ const angularOutputTarget = (outputTarget) => {
|
|
|
573
603
|
};
|
|
574
604
|
};
|
|
575
605
|
function normalizeOutputTarget(config, outputTarget) {
|
|
576
|
-
|
|
606
|
+
var _a, _b;
|
|
607
|
+
const results = Object.assign(Object.assign({}, outputTarget), { excludeComponents: outputTarget.excludeComponents || [], valueAccessorConfigs: outputTarget.valueAccessorConfigs || [], customElementsDir: (_a = outputTarget.customElementsDir) !== null && _a !== void 0 ? _a : 'components', outputType: (_b = outputTarget.outputType) !== null && _b !== void 0 ? _b : OutputTypes.Standalone });
|
|
577
608
|
if (config.rootDir == null) {
|
|
578
609
|
throw new Error('rootDir is not set and it should be set by stencil itself');
|
|
579
610
|
}
|
package/dist/output-angular.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import path from 'path';
|
|
2
|
-
import { relativeImport, normalizePath, sortBy, readPackageJson, dashToPascalCase, createImportStatement, isOutputTypeCustomElementsBuild, OutputTypes, } from './utils';
|
|
2
|
+
import { relativeImport, normalizePath, sortBy, readPackageJson, dashToPascalCase, createImportStatement, isOutputTypeCustomElementsBuild, OutputTypes, mapPropName, } 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';
|
|
@@ -97,7 +97,14 @@ ${createImportStatement(componentLibImports, './angular-component-lib/utils')}\n
|
|
|
97
97
|
}
|
|
98
98
|
const proxyFileOutput = [];
|
|
99
99
|
const filterInternalProps = (prop) => !prop.internal;
|
|
100
|
-
|
|
100
|
+
// Ensure that virtual properties has required as false.
|
|
101
|
+
const mapInputProp = (prop) => {
|
|
102
|
+
var _a;
|
|
103
|
+
return ({
|
|
104
|
+
name: prop.name,
|
|
105
|
+
required: (_a = prop.required) !== null && _a !== void 0 ? _a : false,
|
|
106
|
+
});
|
|
107
|
+
};
|
|
101
108
|
const { componentCorePackage, customElementsDir } = outputTarget;
|
|
102
109
|
for (let cmpMeta of components) {
|
|
103
110
|
const tagNameAsPascal = dashToPascalCase(cmpMeta.tagName);
|
|
@@ -105,11 +112,11 @@ ${createImportStatement(componentLibImports, './angular-component-lib/utils')}\n
|
|
|
105
112
|
if (cmpMeta.properties) {
|
|
106
113
|
internalProps.push(...cmpMeta.properties.filter(filterInternalProps));
|
|
107
114
|
}
|
|
108
|
-
const inputs = internalProps.map(
|
|
115
|
+
const inputs = internalProps.map(mapInputProp);
|
|
109
116
|
if (cmpMeta.virtualProperties) {
|
|
110
|
-
inputs.push(...cmpMeta.virtualProperties.map(
|
|
117
|
+
inputs.push(...cmpMeta.virtualProperties.map(mapInputProp));
|
|
111
118
|
}
|
|
112
|
-
inputs
|
|
119
|
+
const orderedInputs = sortBy(inputs, (cip) => cip.name);
|
|
113
120
|
const outputs = [];
|
|
114
121
|
if (cmpMeta.events) {
|
|
115
122
|
outputs.push(...cmpMeta.events.filter(filterInternalProps).map(mapPropName));
|
|
@@ -125,7 +132,7 @@ ${createImportStatement(componentLibImports, './angular-component-lib/utils')}\n
|
|
|
125
132
|
* 2. Optionally the @NgModule decorated class (if includeSingleComponentAngularModules is true)
|
|
126
133
|
* 3. The component interface (using declaration merging for types).
|
|
127
134
|
*/
|
|
128
|
-
const componentDefinition = createAngularComponentDefinition(cmpMeta.tagName,
|
|
135
|
+
const componentDefinition = createAngularComponentDefinition(cmpMeta.tagName, orderedInputs, outputs, methods, isCustomElementsBuild, isStandaloneBuild, inlineComponentProps);
|
|
129
136
|
const moduleDefinition = generateAngularModuleForComponent(cmpMeta.tagName);
|
|
130
137
|
const componentTypeDefinition = createComponentTypeDefinition(outputType, tagNameAsPascal, cmpMeta.events, componentCorePackage, customElementsDir);
|
|
131
138
|
proxyFileOutput.push(componentDefinition, '\n');
|
package/dist/plugin.js
CHANGED
|
@@ -17,7 +17,8 @@ export const angularOutputTarget = (outputTarget) => {
|
|
|
17
17
|
};
|
|
18
18
|
};
|
|
19
19
|
export function normalizeOutputTarget(config, outputTarget) {
|
|
20
|
-
|
|
20
|
+
var _a, _b;
|
|
21
|
+
const results = Object.assign(Object.assign({}, outputTarget), { excludeComponents: outputTarget.excludeComponents || [], valueAccessorConfigs: outputTarget.valueAccessorConfigs || [], customElementsDir: (_a = outputTarget.customElementsDir) !== null && _a !== void 0 ? _a : 'components', outputType: (_b = outputTarget.outputType) !== null && _b !== void 0 ? _b : OutputTypes.Standalone });
|
|
21
22
|
if (config.rootDir == null) {
|
|
22
23
|
throw new Error('rootDir is not set and it should be set by stencil itself');
|
|
23
24
|
}
|
package/dist/types.d.ts
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* The type of output that can be generated with the Angular output target.
|
|
3
3
|
* - `component` - Generate many component wrappers tied to a single Angular module (lazy/hydrated approach).
|
|
4
4
|
* - `scam` - Generate a Single Component Angular Module for each component.
|
|
5
|
-
* - `standalone` -
|
|
5
|
+
* - `standalone` - Generates standalone components.
|
|
6
6
|
*/
|
|
7
7
|
export type OutputType = 'component' | 'scam' | 'standalone';
|
|
8
8
|
export interface OutputTargetAngular {
|
|
@@ -24,7 +24,7 @@ export interface OutputTargetAngular {
|
|
|
24
24
|
* The type of output that should be generated.
|
|
25
25
|
* - `component` - Generate many component wrappers tied to a single Angular module (lazy/hydrated approach).
|
|
26
26
|
* - `scam` - Generate a Single Component Angular Module for each component.
|
|
27
|
-
* - `standalone` -
|
|
27
|
+
* - `standalone` - (default) Generates standalone components.
|
|
28
28
|
*/
|
|
29
29
|
outputType?: OutputType;
|
|
30
30
|
/**
|
|
@@ -44,3 +44,7 @@ export interface ValueAccessorConfig {
|
|
|
44
44
|
export interface PackageJSON {
|
|
45
45
|
types: string;
|
|
46
46
|
}
|
|
47
|
+
export interface ComponentInputProperty {
|
|
48
|
+
name: string;
|
|
49
|
+
required: boolean;
|
|
50
|
+
}
|
package/dist/utils.d.ts
CHANGED
|
@@ -4,6 +4,9 @@ export declare const OutputTypes: {
|
|
|
4
4
|
[key: string]: OutputType;
|
|
5
5
|
};
|
|
6
6
|
export declare const toLowerCase: (str: string) => string;
|
|
7
|
+
export declare const mapPropName: (prop: {
|
|
8
|
+
name: string;
|
|
9
|
+
}) => string;
|
|
7
10
|
export declare const dashToPascalCase: (str: string) => string;
|
|
8
11
|
export declare function sortBy<T>(array: T[], prop: (item: T) => string): T[];
|
|
9
12
|
export declare function normalizePath(str: string): string;
|
package/dist/utils.js
CHANGED
|
@@ -5,6 +5,7 @@ export const OutputTypes = {
|
|
|
5
5
|
Standalone: 'standalone',
|
|
6
6
|
};
|
|
7
7
|
export const toLowerCase = (str) => str.toLowerCase();
|
|
8
|
+
export const mapPropName = (prop) => prop.name;
|
|
8
9
|
export const dashToPascalCase = (str) => toLowerCase(str)
|
|
9
10
|
.split('-')
|
|
10
11
|
.map((segment) => segment.charAt(0).toUpperCase() + segment.slice(1))
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@stencil/angular-output-target",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "1.1.0",
|
|
4
4
|
"description": "Angular output target for @stencil/core components.",
|
|
5
5
|
"main": "dist/index.cjs.js",
|
|
6
6
|
"module": "dist/index.js",
|
|
@@ -39,17 +39,18 @@
|
|
|
39
39
|
},
|
|
40
40
|
"repository": {
|
|
41
41
|
"type": "git",
|
|
42
|
-
"url": "git+https://github.com/
|
|
42
|
+
"url": "git+https://github.com/stenciljs/output-targets.git"
|
|
43
43
|
},
|
|
44
44
|
"author": "Ionic Team",
|
|
45
45
|
"homepage": "https://stenciljs.com/",
|
|
46
46
|
"license": "MIT",
|
|
47
47
|
"bugs": {
|
|
48
|
-
"url": "https://github.com/
|
|
48
|
+
"url": "https://github.com/stenciljs/output-targets/issues"
|
|
49
49
|
},
|
|
50
50
|
"devDependencies": {
|
|
51
51
|
"@angular/core": "8.2.14",
|
|
52
52
|
"@angular/forms": "8.2.14",
|
|
53
|
+
"@stencil/core": "4.35.1",
|
|
53
54
|
"@types/node": "^18.0.0",
|
|
54
55
|
"npm-run-all2": "^6.2.4",
|
|
55
56
|
"rimraf": "^5.0.0",
|
|
@@ -7,7 +7,7 @@ import { ValueAccessor } from './value-accessor';
|
|
|
7
7
|
/* tslint:disable-next-line:directive-selector */
|
|
8
8
|
selector: '<VALUE_ACCESSOR_SELECTORS>',
|
|
9
9
|
host: {
|
|
10
|
-
'(<VALUE_ACCESSOR_EVENT>)': 'handleChangeEvent($event.target
|
|
10
|
+
'(<VALUE_ACCESSOR_EVENT>)': 'handleChangeEvent($event.target?.["<VALUE_ACCESSOR_TARGETATTR>"])'
|
|
11
11
|
},
|
|
12
12
|
providers: [
|
|
13
13
|
{
|
|
@@ -7,7 +7,7 @@ import { ValueAccessor } from './value-accessor';
|
|
|
7
7
|
/* tslint:disable-next-line:directive-selector */
|
|
8
8
|
selector: '<VALUE_ACCESSOR_SELECTORS>',
|
|
9
9
|
host: {
|
|
10
|
-
'(<VALUE_ACCESSOR_EVENT>)': 'handleChangeEvent($event.target
|
|
10
|
+
'(<VALUE_ACCESSOR_EVENT>)': 'handleChangeEvent($event.target?.["<VALUE_ACCESSOR_TARGETATTR>"])'
|
|
11
11
|
},
|
|
12
12
|
providers: [
|
|
13
13
|
{
|
|
@@ -7,7 +7,7 @@ import { ValueAccessor } from './value-accessor';
|
|
|
7
7
|
/* tslint:disable-next-line:directive-selector */
|
|
8
8
|
selector: '<VALUE_ACCESSOR_SELECTORS>',
|
|
9
9
|
host: {
|
|
10
|
-
'(<VALUE_ACCESSOR_EVENT>)': 'handleChangeEvent($event.target
|
|
10
|
+
'(<VALUE_ACCESSOR_EVENT>)': 'handleChangeEvent($event.target?.["<VALUE_ACCESSOR_TARGETATTR>"])'
|
|
11
11
|
},
|
|
12
12
|
providers: [
|
|
13
13
|
{
|
|
@@ -7,7 +7,7 @@ import { ValueAccessor } from './value-accessor';
|
|
|
7
7
|
/* tslint:disable-next-line:directive-selector */
|
|
8
8
|
selector: '<VALUE_ACCESSOR_SELECTORS>',
|
|
9
9
|
host: {
|
|
10
|
-
'(<VALUE_ACCESSOR_EVENT>)': 'handleChangeEvent($event.target
|
|
10
|
+
'(<VALUE_ACCESSOR_EVENT>)': 'handleChangeEvent($event.target?.["<VALUE_ACCESSOR_TARGETATTR>"])'
|
|
11
11
|
},
|
|
12
12
|
providers: [
|
|
13
13
|
{
|
|
@@ -7,7 +7,7 @@ import { ValueAccessor } from './value-accessor';
|
|
|
7
7
|
/* tslint:disable-next-line:directive-selector */
|
|
8
8
|
selector: '<VALUE_ACCESSOR_SELECTORS>',
|
|
9
9
|
host: {
|
|
10
|
-
'(<VALUE_ACCESSOR_EVENT>)': 'handleChangeEvent($event.target
|
|
10
|
+
'(<VALUE_ACCESSOR_EVENT>)': 'handleChangeEvent($event.target?.["<VALUE_ACCESSOR_TARGETATTR>"])'
|
|
11
11
|
},
|
|
12
12
|
providers: [
|
|
13
13
|
{
|