@stencil/angular-output-target
Advanced tools
Comparing version 0.7.1 to 0.7.2-dev.11691590901.1db83f93
import type { ComponentCompilerEvent } from '@stencil/core/internal'; | ||
import type { OutputType } from './types'; | ||
/** | ||
@@ -10,14 +11,15 @@ * Creates an Angular component declaration from formatted Stencil compiler metadata. | ||
* @param includeImportCustomElements Whether to define the component as a custom element. | ||
* @param standalone Whether to define the component as a standalone component. | ||
* @returns The component declaration as a string. | ||
*/ | ||
export declare const createAngularComponentDefinition: (tagName: string, inputs: readonly string[], outputs: readonly string[], methods: readonly string[], includeImportCustomElements?: boolean) => string; | ||
export declare const createAngularComponentDefinition: (tagName: string, inputs: readonly string[], outputs: readonly string[], methods: readonly string[], includeImportCustomElements?: boolean, standalone?: boolean) => string; | ||
/** | ||
* Creates the component interface type definition. | ||
* @param outputType The output type. | ||
* @param tagNameAsPascal The tag name as PascalCase. | ||
* @param events The events to generate the interface properties for. | ||
* @param componentCorePackage The component core package. | ||
* @param includeImportCustomElements Whether to include the import for the custom element definition. | ||
* @param customElementsDir The custom elements directory. | ||
* @returns The component interface type definition as a string. | ||
*/ | ||
export declare const createComponentTypeDefinition: (tagNameAsPascal: string, events: readonly ComponentCompilerEvent[], componentCorePackage: string, includeImportCustomElements?: boolean, customElementsDir?: string | undefined) => string; | ||
export declare const createComponentTypeDefinition: (outputType: OutputType, tagNameAsPascal: string, events: readonly ComponentCompilerEvent[], componentCorePackage: string, customElementsDir?: string | undefined) => string; |
@@ -10,5 +10,6 @@ import { createComponentEventTypeImports, dashToPascalCase, formatToQuotedList } from './utils'; | ||
* @param includeImportCustomElements Whether to define the component as a custom element. | ||
* @param standalone Whether to define the component as a standalone component. | ||
* @returns The component declaration as a string. | ||
*/ | ||
export const createAngularComponentDefinition = (tagName, inputs, outputs, methods, includeImportCustomElements = false) => { | ||
export const createAngularComponentDefinition = (tagName, inputs, outputs, methods, includeImportCustomElements = false, standalone = false) => { | ||
const tagNameAsPascal = dashToPascalCase(tagName); | ||
@@ -35,2 +36,6 @@ const hasInputs = inputs.length > 0; | ||
} | ||
let standaloneOption = ''; | ||
if (standalone && includeImportCustomElements) { | ||
standaloneOption = `\n standalone: true`; | ||
} | ||
/** | ||
@@ -49,3 +54,3 @@ * Notes on the generated output: | ||
// eslint-disable-next-line @angular-eslint/no-inputs-metadata-property | ||
inputs: [${formattedInputs}], | ||
inputs: [${formattedInputs}],${standaloneOption} | ||
}) | ||
@@ -104,15 +109,15 @@ export class ${tagNameAsPascal} { | ||
* Creates the component interface type definition. | ||
* @param outputType The output type. | ||
* @param tagNameAsPascal The tag name as PascalCase. | ||
* @param events The events to generate the interface properties for. | ||
* @param componentCorePackage The component core package. | ||
* @param includeImportCustomElements Whether to include the import for the custom element definition. | ||
* @param customElementsDir The custom elements directory. | ||
* @returns The component interface type definition as a string. | ||
*/ | ||
export const createComponentTypeDefinition = (tagNameAsPascal, events, componentCorePackage, includeImportCustomElements = false, customElementsDir) => { | ||
export const createComponentTypeDefinition = (outputType, tagNameAsPascal, events, componentCorePackage, customElementsDir) => { | ||
const publicEvents = events.filter((ev) => !ev.internal); | ||
const eventTypeImports = createComponentEventTypeImports(tagNameAsPascal, publicEvents, { | ||
componentCorePackage, | ||
includeImportCustomElements, | ||
customElementsDir, | ||
outputType, | ||
}); | ||
@@ -119,0 +124,0 @@ const eventTypes = publicEvents.map((event) => { |
@@ -12,2 +12,15 @@ 'use strict'; | ||
/** | ||
* The type of output that can be generated with the Angular output target. | ||
* - `component` - Generate many component wrappers tied to a single Angular module (lazy/hydrated approach). | ||
* - `scam` - Generate a Single Component Angular Module for each component. | ||
* - `standalone` - Generate a component with the `standalone` flag set to `true`. | ||
*/ | ||
var OutputType; | ||
(function (OutputType) { | ||
OutputType["Component"] = "component"; | ||
OutputType["Scam"] = "scam"; | ||
OutputType["Standalone"] = "standalone"; | ||
})(OutputType || (OutputType = {})); | ||
const toLowerCase = (str) => str.toLowerCase(); | ||
@@ -105,2 +118,10 @@ const dashToPascalCase = (str) => toLowerCase(str) | ||
/** | ||
* Checks if the outputType is for the custom elements build. | ||
* @param outputType The output type. | ||
* @returns `true` if the output type is for the custom elements build. | ||
*/ | ||
const isOutputTypeCustomElementsBuild = (outputType) => { | ||
return outputType === OutputType.Standalone || outputType === OutputType.Scam; | ||
}; | ||
/** | ||
* Creates the collection of import statements for a component based on the component's events type dependencies. | ||
@@ -113,6 +134,7 @@ * @param componentTagName The tag name of the component (pascal case). | ||
const createComponentEventTypeImports = (componentTagName, events, options) => { | ||
const { componentCorePackage, includeImportCustomElements, customElementsDir } = options; | ||
const { componentCorePackage, customElementsDir } = options; | ||
const imports = []; | ||
const namedImports = new Set(); | ||
const importPathName = normalizePath(componentCorePackage) + (includeImportCustomElements ? `/${customElementsDir || 'components'}` : ''); | ||
const isCustomElementsBuild = isOutputTypeCustomElementsBuild(options.outputType); | ||
const importPathName = normalizePath(componentCorePackage) + (isCustomElementsBuild ? `/${customElementsDir}` : ''); | ||
events.forEach((event) => { | ||
@@ -144,5 +166,6 @@ Object.entries(event.complexType.references).forEach(([typeName, refObject]) => { | ||
* @param includeImportCustomElements Whether to define the component as a custom element. | ||
* @param standalone Whether to define the component as a standalone component. | ||
* @returns The component declaration as a string. | ||
*/ | ||
const createAngularComponentDefinition = (tagName, inputs, outputs, methods, includeImportCustomElements = false) => { | ||
const createAngularComponentDefinition = (tagName, inputs, outputs, methods, includeImportCustomElements = false, standalone = false) => { | ||
const tagNameAsPascal = dashToPascalCase(tagName); | ||
@@ -169,2 +192,6 @@ const hasInputs = inputs.length > 0; | ||
} | ||
let standaloneOption = ''; | ||
if (standalone && includeImportCustomElements) { | ||
standaloneOption = `\n standalone: true`; | ||
} | ||
/** | ||
@@ -183,3 +210,3 @@ * Notes on the generated output: | ||
// eslint-disable-next-line @angular-eslint/no-inputs-metadata-property | ||
inputs: [${formattedInputs}], | ||
inputs: [${formattedInputs}],${standaloneOption} | ||
}) | ||
@@ -238,15 +265,15 @@ export class ${tagNameAsPascal} { | ||
* Creates the component interface type definition. | ||
* @param outputType The output type. | ||
* @param tagNameAsPascal The tag name as PascalCase. | ||
* @param events The events to generate the interface properties for. | ||
* @param componentCorePackage The component core package. | ||
* @param includeImportCustomElements Whether to include the import for the custom element definition. | ||
* @param customElementsDir The custom elements directory. | ||
* @returns The component interface type definition as a string. | ||
*/ | ||
const createComponentTypeDefinition = (tagNameAsPascal, events, componentCorePackage, includeImportCustomElements = false, customElementsDir) => { | ||
const createComponentTypeDefinition = (outputType, tagNameAsPascal, events, componentCorePackage, customElementsDir) => { | ||
const publicEvents = events.filter((ev) => !ev.internal); | ||
const eventTypeImports = createComponentEventTypeImports(tagNameAsPascal, publicEvents, { | ||
componentCorePackage, | ||
includeImportCustomElements, | ||
customElementsDir, | ||
outputType, | ||
}); | ||
@@ -397,7 +424,9 @@ const eventTypes = publicEvents.map((event) => { | ||
function generateProxies(components, pkgData, outputTarget, rootDir) { | ||
var _a; | ||
const distTypesDir = path__default['default'].dirname(pkgData.types); | ||
const dtsFilePath = path__default['default'].join(rootDir, distTypesDir, GENERATED_DTS); | ||
const { outputType } = outputTarget; | ||
const componentsTypeFile = relativeImport(outputTarget.directivesProxyFile, dtsFilePath, '.d.ts'); | ||
const includeSingleComponentAngularModules = (_a = outputTarget.includeSingleComponentAngularModules) !== null && _a !== void 0 ? _a : false; | ||
const includeSingleComponentAngularModules = outputType === OutputType.Scam; | ||
const isCustomElementsBuild = isOutputTypeCustomElementsBuild(outputType); | ||
const isStandaloneBuild = outputType === OutputType.Standalone; | ||
const includeOutputImports = components.some((component) => component.events.some((event) => !event.internal)); | ||
@@ -437,6 +466,4 @@ /** | ||
: normalizePath(componentsTypeFile); | ||
importLocation += outputTarget.includeImportCustomElements | ||
? `/${outputTarget.customElementsDir || 'components'}` | ||
: ''; | ||
return `import ${outputTarget.includeImportCustomElements ? 'type ' : ''}{ ${IMPORT_TYPES} } from '${importLocation}';\n`; | ||
importLocation += isCustomElementsBuild ? `/${outputTarget.customElementsDir}` : ''; | ||
return `import ${isCustomElementsBuild ? 'type ' : ''}{ ${IMPORT_TYPES} } from '${importLocation}';\n`; | ||
}; | ||
@@ -447,23 +474,17 @@ const typeImports = generateTypeImports(); | ||
* Build an array of Custom Elements build imports and namespace them | ||
* so that they do not conflict with the React wrapper names. For example, | ||
* so that they do not conflict with the Angular wrapper names. For example, | ||
* IonButton would be imported as IonButtonCmp so as to not conflict with the | ||
* IonButton React Component that takes in the Web Component as a parameter. | ||
* IonButton Angular Component that takes in the Web Component as a parameter. | ||
*/ | ||
if (outputTarget.includeImportCustomElements && outputTarget.componentCorePackage !== undefined) { | ||
if (isCustomElementsBuild && outputTarget.componentCorePackage !== undefined) { | ||
const cmpImports = components.map((component) => { | ||
const pascalImport = dashToPascalCase(component.tagName); | ||
return `import { defineCustomElement as define${pascalImport} } from '${normalizePath(outputTarget.componentCorePackage)}/${outputTarget.customElementsDir || 'components'}/${component.tagName}.js';`; | ||
return `import { defineCustomElement as define${pascalImport} } from '${normalizePath(outputTarget.componentCorePackage)}/${outputTarget.customElementsDir}/${component.tagName}.js';`; | ||
}); | ||
sourceImports = cmpImports.join('\n'); | ||
} | ||
if (includeSingleComponentAngularModules) { | ||
// Generating Angular modules is only supported in the dist-custom-elements build | ||
if (!outputTarget.includeImportCustomElements) { | ||
throw new Error('Generating single component Angular modules requires the "includeImportCustomElements" option to be set to true.'); | ||
} | ||
} | ||
const proxyFileOutput = []; | ||
const filterInternalProps = (prop) => !prop.internal; | ||
const mapPropName = (prop) => prop.name; | ||
const { includeImportCustomElements, componentCorePackage, customElementsDir } = outputTarget; | ||
const { componentCorePackage, customElementsDir } = outputTarget; | ||
for (let cmpMeta of components) { | ||
@@ -493,5 +514,5 @@ const tagNameAsPascal = dashToPascalCase(cmpMeta.tagName); | ||
*/ | ||
const componentDefinition = createAngularComponentDefinition(cmpMeta.tagName, inputs, outputs, methods, includeImportCustomElements); | ||
const componentDefinition = createAngularComponentDefinition(cmpMeta.tagName, inputs, outputs, methods, isCustomElementsBuild, isStandaloneBuild); | ||
const moduleDefinition = generateAngularModuleForComponent(cmpMeta.tagName); | ||
const componentTypeDefinition = createComponentTypeDefinition(tagNameAsPascal, cmpMeta.events, componentCorePackage, includeImportCustomElements, customElementsDir); | ||
const componentTypeDefinition = createComponentTypeDefinition(outputType, tagNameAsPascal, cmpMeta.events, componentCorePackage, customElementsDir); | ||
proxyFileOutput.push(componentDefinition, '\n'); | ||
@@ -522,3 +543,3 @@ if (includeSingleComponentAngularModules) { | ||
function normalizeOutputTarget(config, outputTarget) { | ||
const results = Object.assign(Object.assign({}, outputTarget), { excludeComponents: outputTarget.excludeComponents || [], valueAccessorConfigs: outputTarget.valueAccessorConfigs || [] }); | ||
const results = Object.assign(Object.assign({}, outputTarget), { excludeComponents: outputTarget.excludeComponents || [], valueAccessorConfigs: outputTarget.valueAccessorConfigs || [], customElementsDir: outputTarget.customElementsDir || 'components', outputType: outputTarget.outputType || OutputType.Component }); | ||
if (config.rootDir == null) { | ||
@@ -537,4 +558,7 @@ throw new Error('rootDir is not set and it should be set by stencil itself'); | ||
if (outputTarget.includeSingleComponentAngularModules !== undefined) { | ||
console.warn('**Experimental**: includeSingleComponentAngularModules is a developer preview feature and may change or be removed in the future.'); | ||
throw new Error("The 'includeSingleComponentAngularModules' option has been removed. Please use 'outputType' instead."); | ||
} | ||
if (outputTarget.outputType === OutputType.Scam) { | ||
console.warn(`**Experimental**: outputType: "${OutputType.Scam}" is a developer preview feature and may change or be removed in the future.`); | ||
} | ||
return results; | ||
@@ -541,0 +565,0 @@ } |
import path from 'path'; | ||
import { EOL } from 'os'; | ||
/** | ||
* The type of output that can be generated with the Angular output target. | ||
* - `component` - Generate many component wrappers tied to a single Angular module (lazy/hydrated approach). | ||
* - `scam` - Generate a Single Component Angular Module for each component. | ||
* - `standalone` - Generate a component with the `standalone` flag set to `true`. | ||
*/ | ||
var OutputType; | ||
(function (OutputType) { | ||
OutputType["Component"] = "component"; | ||
OutputType["Scam"] = "scam"; | ||
OutputType["Standalone"] = "standalone"; | ||
})(OutputType || (OutputType = {})); | ||
const toLowerCase = (str) => str.toLowerCase(); | ||
@@ -96,2 +109,10 @@ const dashToPascalCase = (str) => toLowerCase(str) | ||
/** | ||
* Checks if the outputType is for the custom elements build. | ||
* @param outputType The output type. | ||
* @returns `true` if the output type is for the custom elements build. | ||
*/ | ||
const isOutputTypeCustomElementsBuild = (outputType) => { | ||
return outputType === OutputType.Standalone || outputType === OutputType.Scam; | ||
}; | ||
/** | ||
* Creates the collection of import statements for a component based on the component's events type dependencies. | ||
@@ -104,6 +125,7 @@ * @param componentTagName The tag name of the component (pascal case). | ||
const createComponentEventTypeImports = (componentTagName, events, options) => { | ||
const { componentCorePackage, includeImportCustomElements, customElementsDir } = options; | ||
const { componentCorePackage, customElementsDir } = options; | ||
const imports = []; | ||
const namedImports = new Set(); | ||
const importPathName = normalizePath(componentCorePackage) + (includeImportCustomElements ? `/${customElementsDir || 'components'}` : ''); | ||
const isCustomElementsBuild = isOutputTypeCustomElementsBuild(options.outputType); | ||
const importPathName = normalizePath(componentCorePackage) + (isCustomElementsBuild ? `/${customElementsDir}` : ''); | ||
events.forEach((event) => { | ||
@@ -135,5 +157,6 @@ Object.entries(event.complexType.references).forEach(([typeName, refObject]) => { | ||
* @param includeImportCustomElements Whether to define the component as a custom element. | ||
* @param standalone Whether to define the component as a standalone component. | ||
* @returns The component declaration as a string. | ||
*/ | ||
const createAngularComponentDefinition = (tagName, inputs, outputs, methods, includeImportCustomElements = false) => { | ||
const createAngularComponentDefinition = (tagName, inputs, outputs, methods, includeImportCustomElements = false, standalone = false) => { | ||
const tagNameAsPascal = dashToPascalCase(tagName); | ||
@@ -160,2 +183,6 @@ const hasInputs = inputs.length > 0; | ||
} | ||
let standaloneOption = ''; | ||
if (standalone && includeImportCustomElements) { | ||
standaloneOption = `\n standalone: true`; | ||
} | ||
/** | ||
@@ -174,3 +201,3 @@ * Notes on the generated output: | ||
// eslint-disable-next-line @angular-eslint/no-inputs-metadata-property | ||
inputs: [${formattedInputs}], | ||
inputs: [${formattedInputs}],${standaloneOption} | ||
}) | ||
@@ -229,15 +256,15 @@ export class ${tagNameAsPascal} { | ||
* Creates the component interface type definition. | ||
* @param outputType The output type. | ||
* @param tagNameAsPascal The tag name as PascalCase. | ||
* @param events The events to generate the interface properties for. | ||
* @param componentCorePackage The component core package. | ||
* @param includeImportCustomElements Whether to include the import for the custom element definition. | ||
* @param customElementsDir The custom elements directory. | ||
* @returns The component interface type definition as a string. | ||
*/ | ||
const createComponentTypeDefinition = (tagNameAsPascal, events, componentCorePackage, includeImportCustomElements = false, customElementsDir) => { | ||
const createComponentTypeDefinition = (outputType, tagNameAsPascal, events, componentCorePackage, customElementsDir) => { | ||
const publicEvents = events.filter((ev) => !ev.internal); | ||
const eventTypeImports = createComponentEventTypeImports(tagNameAsPascal, publicEvents, { | ||
componentCorePackage, | ||
includeImportCustomElements, | ||
customElementsDir, | ||
outputType, | ||
}); | ||
@@ -388,7 +415,9 @@ const eventTypes = publicEvents.map((event) => { | ||
function generateProxies(components, pkgData, outputTarget, rootDir) { | ||
var _a; | ||
const distTypesDir = path.dirname(pkgData.types); | ||
const dtsFilePath = path.join(rootDir, distTypesDir, GENERATED_DTS); | ||
const { outputType } = outputTarget; | ||
const componentsTypeFile = relativeImport(outputTarget.directivesProxyFile, dtsFilePath, '.d.ts'); | ||
const includeSingleComponentAngularModules = (_a = outputTarget.includeSingleComponentAngularModules) !== null && _a !== void 0 ? _a : false; | ||
const includeSingleComponentAngularModules = outputType === OutputType.Scam; | ||
const isCustomElementsBuild = isOutputTypeCustomElementsBuild(outputType); | ||
const isStandaloneBuild = outputType === OutputType.Standalone; | ||
const includeOutputImports = components.some((component) => component.events.some((event) => !event.internal)); | ||
@@ -428,6 +457,4 @@ /** | ||
: normalizePath(componentsTypeFile); | ||
importLocation += outputTarget.includeImportCustomElements | ||
? `/${outputTarget.customElementsDir || 'components'}` | ||
: ''; | ||
return `import ${outputTarget.includeImportCustomElements ? 'type ' : ''}{ ${IMPORT_TYPES} } from '${importLocation}';\n`; | ||
importLocation += isCustomElementsBuild ? `/${outputTarget.customElementsDir}` : ''; | ||
return `import ${isCustomElementsBuild ? 'type ' : ''}{ ${IMPORT_TYPES} } from '${importLocation}';\n`; | ||
}; | ||
@@ -438,23 +465,17 @@ const typeImports = generateTypeImports(); | ||
* Build an array of Custom Elements build imports and namespace them | ||
* so that they do not conflict with the React wrapper names. For example, | ||
* so that they do not conflict with the Angular wrapper names. For example, | ||
* IonButton would be imported as IonButtonCmp so as to not conflict with the | ||
* IonButton React Component that takes in the Web Component as a parameter. | ||
* IonButton Angular Component that takes in the Web Component as a parameter. | ||
*/ | ||
if (outputTarget.includeImportCustomElements && outputTarget.componentCorePackage !== undefined) { | ||
if (isCustomElementsBuild && outputTarget.componentCorePackage !== undefined) { | ||
const cmpImports = components.map((component) => { | ||
const pascalImport = dashToPascalCase(component.tagName); | ||
return `import { defineCustomElement as define${pascalImport} } from '${normalizePath(outputTarget.componentCorePackage)}/${outputTarget.customElementsDir || 'components'}/${component.tagName}.js';`; | ||
return `import { defineCustomElement as define${pascalImport} } from '${normalizePath(outputTarget.componentCorePackage)}/${outputTarget.customElementsDir}/${component.tagName}.js';`; | ||
}); | ||
sourceImports = cmpImports.join('\n'); | ||
} | ||
if (includeSingleComponentAngularModules) { | ||
// Generating Angular modules is only supported in the dist-custom-elements build | ||
if (!outputTarget.includeImportCustomElements) { | ||
throw new Error('Generating single component Angular modules requires the "includeImportCustomElements" option to be set to true.'); | ||
} | ||
} | ||
const proxyFileOutput = []; | ||
const filterInternalProps = (prop) => !prop.internal; | ||
const mapPropName = (prop) => prop.name; | ||
const { includeImportCustomElements, componentCorePackage, customElementsDir } = outputTarget; | ||
const { componentCorePackage, customElementsDir } = outputTarget; | ||
for (let cmpMeta of components) { | ||
@@ -484,5 +505,5 @@ const tagNameAsPascal = dashToPascalCase(cmpMeta.tagName); | ||
*/ | ||
const componentDefinition = createAngularComponentDefinition(cmpMeta.tagName, inputs, outputs, methods, includeImportCustomElements); | ||
const componentDefinition = createAngularComponentDefinition(cmpMeta.tagName, inputs, outputs, methods, isCustomElementsBuild, isStandaloneBuild); | ||
const moduleDefinition = generateAngularModuleForComponent(cmpMeta.tagName); | ||
const componentTypeDefinition = createComponentTypeDefinition(tagNameAsPascal, cmpMeta.events, componentCorePackage, includeImportCustomElements, customElementsDir); | ||
const componentTypeDefinition = createComponentTypeDefinition(outputType, tagNameAsPascal, cmpMeta.events, componentCorePackage, customElementsDir); | ||
proxyFileOutput.push(componentDefinition, '\n'); | ||
@@ -513,3 +534,3 @@ if (includeSingleComponentAngularModules) { | ||
function normalizeOutputTarget(config, outputTarget) { | ||
const results = Object.assign(Object.assign({}, outputTarget), { excludeComponents: outputTarget.excludeComponents || [], valueAccessorConfigs: outputTarget.valueAccessorConfigs || [] }); | ||
const results = Object.assign(Object.assign({}, outputTarget), { excludeComponents: outputTarget.excludeComponents || [], valueAccessorConfigs: outputTarget.valueAccessorConfigs || [], customElementsDir: outputTarget.customElementsDir || 'components', outputType: outputTarget.outputType || OutputType.Component }); | ||
if (config.rootDir == null) { | ||
@@ -528,4 +549,7 @@ throw new Error('rootDir is not set and it should be set by stencil itself'); | ||
if (outputTarget.includeSingleComponentAngularModules !== undefined) { | ||
console.warn('**Experimental**: includeSingleComponentAngularModules is a developer preview feature and may change or be removed in the future.'); | ||
throw new Error("The 'includeSingleComponentAngularModules' option has been removed. Please use 'outputType' instead."); | ||
} | ||
if (outputTarget.outputType === OutputType.Scam) { | ||
console.warn(`**Experimental**: outputType: "${OutputType.Scam}" is a developer preview feature and may change or be removed in the future.`); | ||
} | ||
return results; | ||
@@ -532,0 +556,0 @@ } |
import path from 'path'; | ||
import { relativeImport, normalizePath, sortBy, readPackageJson, dashToPascalCase, createImportStatement, } from './utils'; | ||
import { OutputType } from './types'; | ||
import { relativeImport, normalizePath, sortBy, readPackageJson, dashToPascalCase, createImportStatement, isOutputTypeCustomElementsBuild, } from './utils'; | ||
import { createAngularComponentDefinition, createComponentTypeDefinition } from './generate-angular-component'; | ||
@@ -38,7 +39,9 @@ import { generateAngularDirectivesFile } from './generate-angular-directives-file'; | ||
export function generateProxies(components, pkgData, outputTarget, rootDir) { | ||
var _a; | ||
const distTypesDir = path.dirname(pkgData.types); | ||
const dtsFilePath = path.join(rootDir, distTypesDir, GENERATED_DTS); | ||
const { outputType } = outputTarget; | ||
const componentsTypeFile = relativeImport(outputTarget.directivesProxyFile, dtsFilePath, '.d.ts'); | ||
const includeSingleComponentAngularModules = (_a = outputTarget.includeSingleComponentAngularModules) !== null && _a !== void 0 ? _a : false; | ||
const includeSingleComponentAngularModules = outputType === OutputType.Scam; | ||
const isCustomElementsBuild = isOutputTypeCustomElementsBuild(outputType); | ||
const isStandaloneBuild = outputType === OutputType.Standalone; | ||
const includeOutputImports = components.some((component) => component.events.some((event) => !event.internal)); | ||
@@ -78,6 +81,4 @@ /** | ||
: normalizePath(componentsTypeFile); | ||
importLocation += outputTarget.includeImportCustomElements | ||
? `/${outputTarget.customElementsDir || 'components'}` | ||
: ''; | ||
return `import ${outputTarget.includeImportCustomElements ? 'type ' : ''}{ ${IMPORT_TYPES} } from '${importLocation}';\n`; | ||
importLocation += isCustomElementsBuild ? `/${outputTarget.customElementsDir}` : ''; | ||
return `import ${isCustomElementsBuild ? 'type ' : ''}{ ${IMPORT_TYPES} } from '${importLocation}';\n`; | ||
}; | ||
@@ -88,23 +89,17 @@ const typeImports = generateTypeImports(); | ||
* Build an array of Custom Elements build imports and namespace them | ||
* so that they do not conflict with the React wrapper names. For example, | ||
* so that they do not conflict with the Angular wrapper names. For example, | ||
* IonButton would be imported as IonButtonCmp so as to not conflict with the | ||
* IonButton React Component that takes in the Web Component as a parameter. | ||
* IonButton Angular Component that takes in the Web Component as a parameter. | ||
*/ | ||
if (outputTarget.includeImportCustomElements && outputTarget.componentCorePackage !== undefined) { | ||
if (isCustomElementsBuild && outputTarget.componentCorePackage !== undefined) { | ||
const cmpImports = components.map((component) => { | ||
const pascalImport = dashToPascalCase(component.tagName); | ||
return `import { defineCustomElement as define${pascalImport} } from '${normalizePath(outputTarget.componentCorePackage)}/${outputTarget.customElementsDir || 'components'}/${component.tagName}.js';`; | ||
return `import { defineCustomElement as define${pascalImport} } from '${normalizePath(outputTarget.componentCorePackage)}/${outputTarget.customElementsDir}/${component.tagName}.js';`; | ||
}); | ||
sourceImports = cmpImports.join('\n'); | ||
} | ||
if (includeSingleComponentAngularModules) { | ||
// Generating Angular modules is only supported in the dist-custom-elements build | ||
if (!outputTarget.includeImportCustomElements) { | ||
throw new Error('Generating single component Angular modules requires the "includeImportCustomElements" option to be set to true.'); | ||
} | ||
} | ||
const proxyFileOutput = []; | ||
const filterInternalProps = (prop) => !prop.internal; | ||
const mapPropName = (prop) => prop.name; | ||
const { includeImportCustomElements, componentCorePackage, customElementsDir } = outputTarget; | ||
const { componentCorePackage, customElementsDir } = outputTarget; | ||
for (let cmpMeta of components) { | ||
@@ -134,5 +129,5 @@ const tagNameAsPascal = dashToPascalCase(cmpMeta.tagName); | ||
*/ | ||
const componentDefinition = createAngularComponentDefinition(cmpMeta.tagName, inputs, outputs, methods, includeImportCustomElements); | ||
const componentDefinition = createAngularComponentDefinition(cmpMeta.tagName, inputs, outputs, methods, isCustomElementsBuild, isStandaloneBuild); | ||
const moduleDefinition = generateAngularModuleForComponent(cmpMeta.tagName); | ||
const componentTypeDefinition = createComponentTypeDefinition(tagNameAsPascal, cmpMeta.events, componentCorePackage, includeImportCustomElements, customElementsDir); | ||
const componentTypeDefinition = createComponentTypeDefinition(outputType, tagNameAsPascal, cmpMeta.events, componentCorePackage, customElementsDir); | ||
proxyFileOutput.push(componentDefinition, '\n'); | ||
@@ -139,0 +134,0 @@ if (includeSingleComponentAngularModules) { |
import { normalizePath } from './utils'; | ||
import { angularDirectiveProxyOutput } from './output-angular'; | ||
import { OutputType } from './types'; | ||
import path from 'path'; | ||
@@ -17,3 +18,3 @@ export const angularOutputTarget = (outputTarget) => ({ | ||
export function normalizeOutputTarget(config, outputTarget) { | ||
const results = Object.assign(Object.assign({}, outputTarget), { excludeComponents: outputTarget.excludeComponents || [], valueAccessorConfigs: outputTarget.valueAccessorConfigs || [] }); | ||
const results = Object.assign(Object.assign({}, outputTarget), { excludeComponents: outputTarget.excludeComponents || [], valueAccessorConfigs: outputTarget.valueAccessorConfigs || [], customElementsDir: outputTarget.customElementsDir || 'components', outputType: outputTarget.outputType || OutputType.Component }); | ||
if (config.rootDir == null) { | ||
@@ -32,5 +33,8 @@ throw new Error('rootDir is not set and it should be set by stencil itself'); | ||
if (outputTarget.includeSingleComponentAngularModules !== undefined) { | ||
console.warn('**Experimental**: includeSingleComponentAngularModules is a developer preview feature and may change or be removed in the future.'); | ||
throw new Error("The 'includeSingleComponentAngularModules' option has been removed. Please use 'outputType' instead."); | ||
} | ||
if (outputTarget.outputType === OutputType.Scam) { | ||
console.warn(`**Experimental**: outputType: "${OutputType.Scam}" is a developer preview feature and may change or be removed in the future.`); | ||
} | ||
return results; | ||
} |
@@ -0,1 +1,12 @@ | ||
/** | ||
* The type of output that can be generated with the Angular output target. | ||
* - `component` - Generate many component wrappers tied to a single Angular module (lazy/hydrated approach). | ||
* - `scam` - Generate a Single Component Angular Module for each component. | ||
* - `standalone` - Generate a component with the `standalone` flag set to `true`. | ||
*/ | ||
export declare enum OutputType { | ||
Component = "component", | ||
Scam = "scam", | ||
Standalone = "standalone" | ||
} | ||
export interface OutputTargetAngular { | ||
@@ -15,10 +26,10 @@ /** | ||
excludeComponents?: string[]; | ||
includeImportCustomElements?: boolean; | ||
customElementsDir?: string; | ||
/** | ||
* @experimental | ||
* | ||
* `true` to generate a single component Angular module for each component. | ||
* The type of output that should be generated. | ||
* - `component` - Generate many component wrappers tied to a single Angular module (lazy/hydrated approach). | ||
* - `scam` - @experimental Generate a Single Component Angular Module for each component. | ||
* - `standalone` - Generate a component with the `standalone` flag set to `true`. | ||
*/ | ||
includeSingleComponentAngularModules?: boolean; | ||
outputType: OutputType; | ||
} | ||
@@ -25,0 +36,0 @@ export declare type ValueAccessorTypes = 'text' | 'radio' | 'select' | 'number' | 'boolean'; |
import { ComponentCompilerEvent, Config } from '@stencil/core/internal'; | ||
import type { PackageJSON } from './types'; | ||
import { OutputType, PackageJSON } from './types'; | ||
export declare const toLowerCase: (str: string) => string; | ||
@@ -25,2 +25,8 @@ export declare const dashToPascalCase: (str: string) => string; | ||
/** | ||
* Checks if the outputType is for the custom elements build. | ||
* @param outputType The output type. | ||
* @returns `true` if the output type is for the custom elements build. | ||
*/ | ||
export declare const isOutputTypeCustomElementsBuild: (outputType: OutputType) => boolean; | ||
/** | ||
* Creates the collection of import statements for a component based on the component's events type dependencies. | ||
@@ -34,4 +40,4 @@ * @param componentTagName The tag name of the component (pascal case). | ||
componentCorePackage: string; | ||
includeImportCustomElements?: boolean; | ||
customElementsDir?: string; | ||
outputType: OutputType; | ||
}) => string; |
import path from 'path'; | ||
import { OutputType } from './types'; | ||
export const toLowerCase = (str) => str.toLowerCase(); | ||
@@ -97,2 +98,10 @@ export const dashToPascalCase = (str) => toLowerCase(str) | ||
/** | ||
* Checks if the outputType is for the custom elements build. | ||
* @param outputType The output type. | ||
* @returns `true` if the output type is for the custom elements build. | ||
*/ | ||
export const isOutputTypeCustomElementsBuild = (outputType) => { | ||
return outputType === OutputType.Standalone || outputType === OutputType.Scam; | ||
}; | ||
/** | ||
* Creates the collection of import statements for a component based on the component's events type dependencies. | ||
@@ -105,6 +114,7 @@ * @param componentTagName The tag name of the component (pascal case). | ||
export const createComponentEventTypeImports = (componentTagName, events, options) => { | ||
const { componentCorePackage, includeImportCustomElements, customElementsDir } = options; | ||
const { componentCorePackage, customElementsDir } = options; | ||
const imports = []; | ||
const namedImports = new Set(); | ||
const importPathName = normalizePath(componentCorePackage) + (includeImportCustomElements ? `/${customElementsDir || 'components'}` : ''); | ||
const isCustomElementsBuild = isOutputTypeCustomElementsBuild(options.outputType); | ||
const importPathName = normalizePath(componentCorePackage) + (isCustomElementsBuild ? `/${customElementsDir}` : ''); | ||
events.forEach((event) => { | ||
@@ -111,0 +121,0 @@ Object.entries(event.complexType.references).forEach(([typeName, refObject]) => { |
{ | ||
"name": "@stencil/angular-output-target", | ||
"version": "0.7.1", | ||
"version": "0.7.2-dev.11691590901.1db83f93", | ||
"description": "Angular output target for @stencil/core components.", | ||
@@ -61,3 +61,3 @@ "main": "dist/index.cjs.js", | ||
}, | ||
"gitHead": "a3588e905186a0e86e7f88418fd5b2f9531b55e0", | ||
"gitHead": "db83f93bf80266494560db9c21d19f8f31a95df2", | ||
"volta": { | ||
@@ -64,0 +64,0 @@ "extends": "../../package.json" |
@@ -43,10 +43,10 @@ # @stencil/angular-output-target | ||
| Property | Description | | ||
| ----------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | ||
| `componentCorePackage` | The NPM package name of your Stencil component library. This package is used as a dependency for your Angular wrappers. | | ||
| `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. | | ||
| `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. | | ||
| `valueAccessorConfigs` | The configuration object for how individual web components behave with Angular control value accessors. | | ||
| `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. | | ||
| `includeImportCustomElements` | If `true`, the output target will import the custom element instance and register it with the Custom Elements Registry when the component is imported inside of a user's app. This can only be used with the [Custom Elements Bundle](https://stenciljs.com/docs/custom-elements) and will not work with lazy loaded components. | | ||
| `customElementsDir` | This is the directory where the custom elements are imported from when using the [Custom Elements Bundle](https://stenciljs.com/docs/custom-elements). Defaults to the `components` directory. Only applies when `includeImportCustomElements` is `true`. | | ||
| Property | Description | | ||
| ---------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | ||
| `componentCorePackage` | The NPM package name of your Stencil component library. This package is used as a dependency for your Angular wrappers. | | ||
| `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. | | ||
| `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. | | ||
| `valueAccessorConfigs` | The configuration object for how individual web components behave with Angular control value accessors. | | ||
| `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. | | ||
| `outputType` | Specifies the type of output to be generated. It can take one of the following values: <br />1. `component`: Generates all the component wrappers to be declared on an Angular module. This option is required for Stencil projects using the `dist` hydrated output.<br /> 2. `scam`: Generates a separate Angular module for each component.<br /> 3. `standalone`: Generates standalone component wrappers.<br /> Both `scam` and `standalone` options are compatible with the `dist-custom-elements` output. <br />Note: Please choose the appropriate `outputType` based on your project's requirements and the desired output structure. Defaults to `component`. | | ||
| `customElementsDir` | This is the directory where the custom elements are imported from when using the [Custom Elements Bundle](https://stenciljs.com/docs/custom-elements). Defaults to the `components` directory. Only applies for `outputType: "scam"` or `outputType: "standalone"`. | |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
101365
1965