@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 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 string[], outputs: readonly string[], methods: readonly string[], includeImportCustomElements?: boolean, standalone?: boolean, inlineComponentProps?: readonly ComponentCompilerProperty[]) => string;
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/ionic-team/stencil-ds-output-targets/issues/212
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 formattedInputs = formatToQuotedList(inputs);
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: [${formattedInputs}]`);
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 && includeImportCustomElements) {
63
- standaloneOption = `\n standalone: true`;
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 === OutputTypes.Standalone ? ',standalone: true' : '');
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.<VALUE_ACCESSOR_TARGETATTR>)'`;
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/ionic-team/stencil-ds-output-targets/issues/212
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 formattedInputs = formatToQuotedList(inputs);
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: [${formattedInputs}]`);
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 && includeImportCustomElements) {
208
- standaloneOption = `\n standalone: true`;
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 === OutputTypes.Standalone ? ',standalone: true' : '');
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.<VALUE_ACCESSOR_TARGETATTR>)'`;
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
- const mapPropName = (prop) => prop.name;
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(mapPropName);
563
+ const inputs = internalProps.map(mapInputProp);
534
564
  if (cmpMeta.virtualProperties) {
535
- inputs.push(...cmpMeta.virtualProperties.map(mapPropName));
565
+ inputs.push(...cmpMeta.virtualProperties.map(mapInputProp));
536
566
  }
537
- inputs.sort();
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, inputs, outputs, methods, isCustomElementsBuild, isStandaloneBuild, inlineComponentProps);
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
- const results = Object.assign(Object.assign({}, outputTarget), { excludeComponents: outputTarget.excludeComponents || [], valueAccessorConfigs: outputTarget.valueAccessorConfigs || [], customElementsDir: outputTarget.customElementsDir || 'components', outputType: outputTarget.outputType || OutputTypes.Component });
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/ionic-team/stencil-ds-output-targets/issues/212
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 formattedInputs = formatToQuotedList(inputs);
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: [${formattedInputs}]`);
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 && includeImportCustomElements) {
200
- standaloneOption = `\n standalone: true`;
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 === OutputTypes.Standalone ? ',standalone: true' : '');
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.<VALUE_ACCESSOR_TARGETATTR>)'`;
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
- const mapPropName = (prop) => prop.name;
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(mapPropName);
555
+ const inputs = internalProps.map(mapInputProp);
526
556
  if (cmpMeta.virtualProperties) {
527
- inputs.push(...cmpMeta.virtualProperties.map(mapPropName));
557
+ inputs.push(...cmpMeta.virtualProperties.map(mapInputProp));
528
558
  }
529
- inputs.sort();
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, inputs, outputs, methods, isCustomElementsBuild, isStandaloneBuild, inlineComponentProps);
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
- const results = Object.assign(Object.assign({}, outputTarget), { excludeComponents: outputTarget.excludeComponents || [], valueAccessorConfigs: outputTarget.valueAccessorConfigs || [], customElementsDir: outputTarget.customElementsDir || 'components', outputType: outputTarget.outputType || OutputTypes.Component });
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
  }
@@ -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
- const mapPropName = (prop) => prop.name;
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(mapPropName);
115
+ const inputs = internalProps.map(mapInputProp);
109
116
  if (cmpMeta.virtualProperties) {
110
- inputs.push(...cmpMeta.virtualProperties.map(mapPropName));
117
+ inputs.push(...cmpMeta.virtualProperties.map(mapInputProp));
111
118
  }
112
- inputs.sort();
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, inputs, outputs, methods, isCustomElementsBuild, isStandaloneBuild, inlineComponentProps);
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
- const results = Object.assign(Object.assign({}, outputTarget), { excludeComponents: outputTarget.excludeComponents || [], valueAccessorConfigs: outputTarget.valueAccessorConfigs || [], customElementsDir: outputTarget.customElementsDir || 'components', outputType: outputTarget.outputType || OutputTypes.Component });
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` - Generate a component with the `standalone` flag set to `true`.
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` - Generate a component with the `standalone` flag set to `true`.
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": "0.10.2",
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/ionic-team/stencil-ds-output-targets.git"
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/ionic-team/stencil-ds-output-targets/issues"
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.<VALUE_ACCESSOR_TARGETATTR>)'
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.<VALUE_ACCESSOR_TARGETATTR>)'
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.<VALUE_ACCESSOR_TARGETATTR>)'
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.<VALUE_ACCESSOR_TARGETATTR>)'
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.<VALUE_ACCESSOR_TARGETATTR>)'
10
+ '(<VALUE_ACCESSOR_EVENT>)': 'handleChangeEvent($event.target?.["<VALUE_ACCESSOR_TARGETATTR>"])'
11
11
  },
12
12
  providers: [
13
13
  {