diff --git a/.prettierrc.json b/.prettierrc.json new file mode 100644 index 00000000..956bb7b5 --- /dev/null +++ b/.prettierrc.json @@ -0,0 +1,3 @@ +{ + "plugins": ["@ionic/prettier-config"] +} diff --git a/CHANGELOG.md b/CHANGELOG.md index 16dbb721..81affc15 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,33 @@ +## @public-ui/stencil-vue-output-target@0.9.1 (2024-03-11) + +#### :bug: Bug Fix + +- fix(vue): v-model does not update when other events bubble up [#425](https://github.com/ionic-team/stencil-ds-output-targets/pull/425) + +## @public-ui/stencil-angular-output-target@0.9.0 (2024-03-11) + +#### :rocket: Enhancement + +- Add runtime option `setTagNameTransformer` + +## @public-ui/stencil-react-output-target@0.6.0 (2024-03-11) + +#### :rocket: Enhancement + +- Add runtime option `setTagNameTransformer` + +## @public-ui/stencil-solid-output-target@0.2.0 (2024-03-11) + +#### :rocket: Enhancement + +- Add runtime option `setTagNameTransformer` + +## @public-ui/stencil-vue-output-target@0.9.0 (2024-03-11) + +#### :rocket: Enhancement + +- Add runtime option `setTagNameTransformer` + ## @stencil/vue-output-target@0.0.1 (2020-06-26) #### :rocket: Enhancement diff --git a/README.md b/README.md index b0672010..b2a30cbf 100644 --- a/README.md +++ b/README.md @@ -4,6 +4,13 @@ | Angular Output Target | [`@stencil/angular-output-target`](https://www.npmjs.com/package/@stencil/angular-output-target) | [![version](https://img.shields.io/npm/v/@stencil/angular-output-target/latest.svg)](https://www.npmjs.com/package/@stencil/angular-output-target) | [README](./packages/angular/README.md) | | Vue Output Target | [`@stencil/vue-output-target`](https://www.npmjs.com/package/@stencil/vue-output-target) | [![version](https://img.shields.io/npm/v/@stencil/vue-output-target/latest.svg)](https://www.npmjs.com/package/@stencil/vue-output-target) | [README](./packages/vue/README.md) | +| Project | Package | Version | Documentation | +| --------------------- | ------------------------------------------------------------------------------------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------- | +| React Output Target | [`@public-ui/stencil-react-output-target`](https://www.npmjs.com/package/@public-ui/stencil-react-output-target) | [![version](https://img.shields.io/npm/v/@public-ui/stencil-react-output-target/latest.svg)](https://www.npmjs.com/package/@public-ui/stencil-react-output-target) | [README](./packages/react-output-target/README.md) | +| Angular Output Target | [`@public-ui/stencil-angular-output-target`](https://www.npmjs.com/package/@public-ui/stencil-angular-output-target) | [![version](https://img.shields.io/npm/v/@public-ui/stencil-angular-output-target/latest.svg)](https://www.npmjs.com/package/@public-ui/stencil-angular-output-target) | [README](./packages/angular-output-target/README.md) | +| Vue Output Target | [`@public-ui/stencil-vue-output-target`](https://www.npmjs.com/package/@public-ui/stencil-vue-output-target) | [![version](https://img.shields.io/npm/v/@public-ui/stencil-vue-output-target/latest.svg)](https://www.npmjs.com/package/@public-ui/stencil-vue-output-target) | [README](./packages/vue-output-target/README.md) | +| Solid Output Target | [`@public-ui/stencil-solid-output-target`](https://www.npmjs.com/package/@public-ui/stencil-solid-output-target) | [![version](https://img.shields.io/npm/v/@public-ui/stencil-solid-output-target/latest.svg)](https://www.npmjs.com/package/@public-ui/stencil-solid-output-target) | [README](./packages/solid-output-target/README.md) | + # Introduction Integrating web components into existing framework applications can be difficult at times. More about this can be read at https://custom-elements-everywhere.com/. diff --git a/example-project/component-library-angular/src/directives/angular-component-lib/replace-tag-directive.ts b/example-project/component-library-angular/src/directives/angular-component-lib/replace-tag-directive.ts new file mode 100644 index 00000000..fe3a4869 --- /dev/null +++ b/example-project/component-library-angular/src/directives/angular-component-lib/replace-tag-directive.ts @@ -0,0 +1,69 @@ +import { AfterViewChecked, Directive, Input, TemplateRef, ViewContainerRef } from '@angular/core'; +import { StencilProxyComponent } from './stencil-proxy-component'; + +@Directive({ + selector: '[replaceTag]', +}) +export class ReplaceTagDirective implements AfterViewChecked { + constructor( + private templateRef: TemplateRef, + private vcf: ViewContainerRef, + private host: StencilProxyComponent + ) {} + + private _tag: string; + private _needUpdate: boolean = false; + private _webComponentElement: HTMLElement; + + @Input('replaceTag') + set tag(t: string) { + this._tag = t; + this._needUpdate = true; + this.vcf.clear(); + let template = this.templateRef.elementRef.nativeElement.previousElementSibling; + if (template) { + this.templateRef.elementRef.nativeElement.parentNode.removeChild(template); + } + this.vcf.createEmbeddedView(this.templateRef); + } + + ngAfterViewChecked() { + if (this._needUpdate) { + this._updateTemplate(); + this._needUpdate = false; + } + } + + private _updateTemplate() { + let template = this.templateRef.elementRef.nativeElement.previousElementSibling; + if (template) { + this._webComponentElement = document.createElement(this._tag); + this.mirrorProperties( + this.templateRef.elementRef.nativeElement.previousElementSibling, + this._webComponentElement + ); + + Array.from(template.childNodes).forEach((node) => { + this._webComponentElement.appendChild(node as Node); + }); + + this.templateRef.elementRef.nativeElement.parentNode.replaceChild(this._webComponentElement, template); + // template.style.display = 'none'; + // this.templateRef.elementRef.nativeElement.parentNode.appendChild(this._webComponentElement, template); + } + } + + public handlePropertyChanges() { + this.mirrorProperties(this.templateRef.elementRef.nativeElement.parentElement, this._webComponentElement); + } + + private mirrorProperties(from: HTMLElement, to: HTMLElement) { + const properties: [string, any][] = Object.entries(from); + + for (let [key, value] of properties) { + if (this.host.availableInputProperties.includes(key) && value !== undefined) { + (to as Record)[key] = value; + } + } + } +} diff --git a/example-project/component-library-angular/src/directives/angular-component-lib/stencil-proxy-component.ts b/example-project/component-library-angular/src/directives/angular-component-lib/stencil-proxy-component.ts new file mode 100644 index 00000000..e3f44b07 --- /dev/null +++ b/example-project/component-library-angular/src/directives/angular-component-lib/stencil-proxy-component.ts @@ -0,0 +1,3 @@ +export abstract class StencilProxyComponent { + public availableInputProperties: string[]; +} diff --git a/example-project/component-library-angular/src/directives/angular-component-lib/tag-name-transformer.ts b/example-project/component-library-angular/src/directives/angular-component-lib/tag-name-transformer.ts new file mode 100644 index 00000000..a7a4a4a4 --- /dev/null +++ b/example-project/component-library-angular/src/directives/angular-component-lib/tag-name-transformer.ts @@ -0,0 +1,6 @@ +type TagNameTransformer = (tagName: string) => string; + +export let tagNameTransformer: TagNameTransformer | undefined; +export const setTagNameTransformer = (_tagNameTransformer: TagNameTransformer) => { + tagNameTransformer = _tagNameTransformer; +}; diff --git a/example-project/component-library-angular/src/directives/proxies.ts b/example-project/component-library-angular/src/directives/proxies.ts index 6c795aea..3008f7a4 100644 --- a/example-project/component-library-angular/src/directives/proxies.ts +++ b/example-project/component-library-angular/src/directives/proxies.ts @@ -1,8 +1,11 @@ /* tslint:disable */ /* auto-generated angular directive proxies */ -import { ChangeDetectionStrategy, ChangeDetectorRef, Component, ElementRef, EventEmitter, NgZone } from '@angular/core'; - +import { ChangeDetectionStrategy, ChangeDetectorRef, Component, ElementRef, OnChanges, ViewChild, forwardRef, CUSTOM_ELEMENTS_SCHEMA, EventEmitter, NgZone } from '@angular/core'; +import { CommonModule } from '@angular/common'; import { ProxyCmp, proxyOutputs } from './angular-component-lib/utils'; +import { ReplaceTagDirective } from './angular-component-lib/replace-tag-directive'; +import { StencilProxyComponent } from './angular-component-lib/stencil-proxy-component'; +import { tagNameTransformer } from './angular-component-lib/tag-name-transformer'; import { Components } from 'component-library'; @@ -59,7 +62,7 @@ export class MyCheckbox { } -import type { CheckboxChangeEventDetail as IMyCheckboxCheckboxChangeEventDetail } from 'component-library'; +import /* import type - is not possible with ng@^8 */ { CheckboxChangeEventDetail as IMyCheckboxCheckboxChangeEventDetail } from 'component-library'; export declare interface MyCheckbox extends Components.MyCheckbox { /** @@ -126,7 +129,7 @@ export class MyInput { } -import type { InputChangeEventDetail as IMyInputInputChangeEventDetail } from 'component-library'; +import /* import type - is not possible with ng@^8 */ { InputChangeEventDetail as IMyInputInputChangeEventDetail } from 'component-library'; export declare interface MyInput extends Components.MyInput { /** @@ -169,7 +172,7 @@ export class MyPopover { } -import type { OverlayEventDetail as IMyPopoverOverlayEventDetail } from 'component-library'; +import /* import type - is not possible with ng@^8 */ { OverlayEventDetail as IMyPopoverOverlayEventDetail } from 'component-library'; export declare interface MyPopover extends Components.MyPopover { /** @@ -247,7 +250,7 @@ export class MyRadioGroup { } -import type { RadioGroupChangeEventDetail as IMyRadioGroupRadioGroupChangeEventDetail } from 'component-library'; +import /* import type - is not possible with ng@^8 */ { RadioGroupChangeEventDetail as IMyRadioGroupRadioGroupChangeEventDetail } from 'component-library'; export declare interface MyRadioGroup extends Components.MyRadioGroup { /** @@ -277,7 +280,7 @@ export class MyRange { } -import type { RangeChangeEventDetail as IMyRangeRangeChangeEventDetail } from 'component-library'; +import /* import type - is not possible with ng@^8 */ { RangeChangeEventDetail as IMyRangeRangeChangeEventDetail } from 'component-library'; export declare interface MyRange extends Components.MyRange { /** diff --git a/example-project/component-library-react/package.json b/example-project/component-library-react/package.json index 48f24c26..804f2cab 100644 --- a/example-project/component-library-react/package.json +++ b/example-project/component-library-react/package.json @@ -14,7 +14,7 @@ "test": "wdio run ./wdio.conf.ts" }, "dependencies": { - "@stencil/react-output-target": "workspace:*", + "@public-ui/stencil-react-output-target": "workspace:*", "component-library": "workspace:*", "react-dom": "^18.3.1" }, diff --git a/example-project/component-library-react/src/components.ts b/example-project/component-library-react/src/components.ts index c0089ae6..735c0305 100644 --- a/example-project/component-library-react/src/components.ts +++ b/example-project/component-library-react/src/components.ts @@ -7,8 +7,8 @@ /* eslint-disable */ -import type { EventName, StencilReactComponent } from '@stencil/react-output-target/runtime'; -import { createComponent } from '@stencil/react-output-target/runtime'; +import type { EventName, StencilReactComponent } from '@public-ui/stencil-react-output-target/runtime'; +import { createComponent } from '@public-ui/stencil-react-output-target/runtime'; import { type CheckboxChangeEventDetail, type InputChangeEventDetail, type MyCheckboxCustomEvent, type MyInputCustomEvent, type MyPopoverCustomEvent, type MyRadioGroupCustomEvent, type MyRangeCustomEvent, type OverlayEventDetail, type RadioGroupChangeEventDetail, type RangeChangeEventDetail } from "component-library"; import { MyButton as MyButtonElement, defineCustomElement as defineMyButton } from "component-library/components/my-button.js"; import { MyCheckbox as MyCheckboxElement, defineCustomElement as defineMyCheckbox } from "component-library/components/my-checkbox.js"; diff --git a/example-project/component-library-vue/package.json b/example-project/component-library-vue/package.json index 9d54e6b2..b9bf4d9e 100644 --- a/example-project/component-library-vue/package.json +++ b/example-project/component-library-vue/package.json @@ -32,6 +32,6 @@ }, "dependencies": { "component-library": "workspace:*", - "@stencil/vue-output-target": "workspace:*" + "@public-ui/stencil-vue-output-target": "workspace:*" } } diff --git a/example-project/component-library-vue/src/index.ts b/example-project/component-library-vue/src/index.ts index 7c7112e8..cac2a2bd 100644 --- a/example-project/component-library-vue/src/index.ts +++ b/example-project/component-library-vue/src/index.ts @@ -1,7 +1,8 @@ /* eslint-disable */ /* tslint:disable */ /* auto-generated vue proxies */ -import { defineContainer, defineStencilSSRComponent } from '@stencil/vue-output-target/runtime'; +import { defineContainer, defineStencilSSRComponent } from '@public-ui/stencil-vue-output-target/runtime'; +import { setTagNameTransformer } from './tag-name-transformer'; import type { JSX } from 'component-library/components'; @@ -290,3 +291,4 @@ export const MyRange = /*@__PURE__*/ globalThis.window ? defineContainer=20.10.0", "pnpm": ">=9.4.0" diff --git a/packages/angular/angular-component-lib/replace-tag-directive.ts b/packages/angular/angular-component-lib/replace-tag-directive.ts new file mode 100644 index 00000000..fe3a4869 --- /dev/null +++ b/packages/angular/angular-component-lib/replace-tag-directive.ts @@ -0,0 +1,69 @@ +import { AfterViewChecked, Directive, Input, TemplateRef, ViewContainerRef } from '@angular/core'; +import { StencilProxyComponent } from './stencil-proxy-component'; + +@Directive({ + selector: '[replaceTag]', +}) +export class ReplaceTagDirective implements AfterViewChecked { + constructor( + private templateRef: TemplateRef, + private vcf: ViewContainerRef, + private host: StencilProxyComponent + ) {} + + private _tag: string; + private _needUpdate: boolean = false; + private _webComponentElement: HTMLElement; + + @Input('replaceTag') + set tag(t: string) { + this._tag = t; + this._needUpdate = true; + this.vcf.clear(); + let template = this.templateRef.elementRef.nativeElement.previousElementSibling; + if (template) { + this.templateRef.elementRef.nativeElement.parentNode.removeChild(template); + } + this.vcf.createEmbeddedView(this.templateRef); + } + + ngAfterViewChecked() { + if (this._needUpdate) { + this._updateTemplate(); + this._needUpdate = false; + } + } + + private _updateTemplate() { + let template = this.templateRef.elementRef.nativeElement.previousElementSibling; + if (template) { + this._webComponentElement = document.createElement(this._tag); + this.mirrorProperties( + this.templateRef.elementRef.nativeElement.previousElementSibling, + this._webComponentElement + ); + + Array.from(template.childNodes).forEach((node) => { + this._webComponentElement.appendChild(node as Node); + }); + + this.templateRef.elementRef.nativeElement.parentNode.replaceChild(this._webComponentElement, template); + // template.style.display = 'none'; + // this.templateRef.elementRef.nativeElement.parentNode.appendChild(this._webComponentElement, template); + } + } + + public handlePropertyChanges() { + this.mirrorProperties(this.templateRef.elementRef.nativeElement.parentElement, this._webComponentElement); + } + + private mirrorProperties(from: HTMLElement, to: HTMLElement) { + const properties: [string, any][] = Object.entries(from); + + for (let [key, value] of properties) { + if (this.host.availableInputProperties.includes(key) && value !== undefined) { + (to as Record)[key] = value; + } + } + } +} diff --git a/packages/angular/angular-component-lib/stencil-proxy-component.ts b/packages/angular/angular-component-lib/stencil-proxy-component.ts new file mode 100644 index 00000000..e3f44b07 --- /dev/null +++ b/packages/angular/angular-component-lib/stencil-proxy-component.ts @@ -0,0 +1,3 @@ +export abstract class StencilProxyComponent { + public availableInputProperties: string[]; +} diff --git a/packages/angular/angular-component-lib/tag-name-transformer.ts b/packages/angular/angular-component-lib/tag-name-transformer.ts new file mode 100644 index 00000000..a7a4a4a4 --- /dev/null +++ b/packages/angular/angular-component-lib/tag-name-transformer.ts @@ -0,0 +1,6 @@ +type TagNameTransformer = (tagName: string) => string; + +export let tagNameTransformer: TagNameTransformer | undefined; +export const setTagNameTransformer = (_tagNameTransformer: TagNameTransformer) => { + tagNameTransformer = _tagNameTransformer; +}; diff --git a/packages/angular/package.json b/packages/angular/package.json index 6dd3f852..f8e6f527 100644 --- a/packages/angular/package.json +++ b/packages/angular/package.json @@ -1,5 +1,5 @@ { - "name": "@stencil/angular-output-target", + "name": "@public-ui/stencil-angular-output-target", "version": "0.10.0", "description": "Angular output target for @stencil/core components.", "main": "dist/index.cjs.js", @@ -15,7 +15,7 @@ }, "scripts": { "prepublishOnly": "pnpm run build", - "prebuild": "rimraf ./dist && pnpm run test", + "prebuild": "rimraf ./dist", "build": "tsc && pnpm run rollup", "dev": "run-p dev:*", "dev:build": "tsc --watch --preserveWatchOutput", diff --git a/packages/angular/src/generate-angular-component.ts b/packages/angular/src/generate-angular-component.ts index e66f31c0..d1520e6f 100644 --- a/packages/angular/src/generate-angular-component.ts +++ b/packages/angular/src/generate-angular-component.ts @@ -1,7 +1,7 @@ import type { CompilerJsDoc, ComponentCompilerEvent, ComponentCompilerProperty } from '@stencil/core/internal'; -import { createComponentEventTypeImports, dashToPascalCase, formatToQuotedList } from './utils'; import type { OutputType } from './types'; +import { createComponentEventTypeImports, dashToPascalCase, formatToQuotedList } from './utils'; /** * Creates a property declaration. @@ -75,7 +75,7 @@ export const createAngularComponentDefinition = ( let standaloneOption = ''; if (standalone && includeImportCustomElements) { - standaloneOption = `\n standalone: true`; + standaloneOption = `\n standalone: true,`; } const propertyDeclarations = inlineComponentProps.map((m) => diff --git a/packages/angular/src/generate-angular-modules.ts b/packages/angular/src/generate-angular-modules.ts index 23acd00f..b4fcc064 100644 --- a/packages/angular/src/generate-angular-modules.ts +++ b/packages/angular/src/generate-angular-modules.ts @@ -11,8 +11,10 @@ export const generateAngularModuleForComponent = (componentTagName: string) => { const moduleClassName = `${tagNameAsPascal}Module`; const moduleDefinition = `@NgModule({ - declarations: [${componentClassName}], - exports: [${componentClassName}] + declarations: [ReplaceTagDirective, ${componentClassName}], + exports: [${componentClassName}], + schemas: [CUSTOM_ELEMENTS_SCHEMA], + imports: [CommonModule], }) export class ${moduleClassName} { }`; diff --git a/packages/angular/src/output-angular.ts b/packages/angular/src/output-angular.ts index a7e710ee..05cdd77b 100644 --- a/packages/angular/src/output-angular.ts +++ b/packages/angular/src/output-angular.ts @@ -79,7 +79,16 @@ export function generateProxies( /** * The collection of named imports from @angular/core. */ - const angularCoreImports = ['ChangeDetectionStrategy', 'ChangeDetectorRef', 'Component', 'ElementRef']; + const angularCoreImports = [ + 'ChangeDetectionStrategy', + 'ChangeDetectorRef', + 'Component', + 'ElementRef', + 'OnChanges', + 'ViewChild', + 'forwardRef', + 'CUSTOM_ELEMENTS_SCHEMA', + ]; if (includeOutputImports) { angularCoreImports.push('EventEmitter'); @@ -103,8 +112,11 @@ export function generateProxies( const imports = `/* tslint:disable */ /* auto-generated angular directive proxies */ ${createImportStatement(angularCoreImports, '@angular/core')} - -${createImportStatement(componentLibImports, './angular-component-lib/utils')}\n`; +${createImportStatement(['CommonModule'], '@angular/common')} +${createImportStatement(componentLibImports, './angular-component-lib/utils')} +${createImportStatement(['ReplaceTagDirective'], './angular-component-lib/replace-tag-directive')} +${createImportStatement(['StencilProxyComponent'], './angular-component-lib/stencil-proxy-component')} +${createImportStatement(['tagNameTransformer'], './angular-component-lib/tag-name-transformer')}\n`; /** * Generate JSX import type from correct location. * When using custom elements build, we need to import from diff --git a/packages/angular/src/utils.ts b/packages/angular/src/utils.ts index ee47de71..bb8fa9e9 100644 --- a/packages/angular/src/utils.ts +++ b/packages/angular/src/utils.ts @@ -16,6 +16,12 @@ export const dashToPascalCase = (str: string) => .map((segment) => segment.charAt(0).toUpperCase() + segment.slice(1)) .join(''); +export const dashToCamelCase = (str: string) => + toLowerCase(str) + .split('-') + .map((segment, index) => (index === 0 ? segment : segment.charAt(0).toUpperCase() + segment.slice(1))) + .join(''); + export function sortBy(array: T[], prop: (item: T) => string) { return array.slice().sort((a, b) => { const nameA = prop(a); @@ -150,7 +156,7 @@ export const createComponentEventTypeImports = ( const newTypeName = `I${componentTagName}${typeName}`; // Prevents duplicate imports for the same type. if (!namedImports.has(newTypeName)) { - imports.push(`import type { ${typeName} as ${newTypeName} } from '${importPathName}';`); + imports.push(`import /* import type - is not possible with ng@^8 */ { ${typeName} as ${newTypeName} } from '${importPathName}';`); namedImports.add(newTypeName); } } diff --git a/packages/angular/tests/generate-angular-component.test.ts b/packages/angular/tests/generate-angular-component.test.ts index d4d6d70a..56f2b147 100644 --- a/packages/angular/tests/generate-angular-component.test.ts +++ b/packages/angular/tests/generate-angular-component.test.ts @@ -1,7 +1,24 @@ -import { describe, it, expect } from 'vitest'; -import type { ComponentCompilerProperty } from '@stencil/core/internal'; import { createComponentTypeDefinition, createAngularComponentDefinition } from '../src/generate-angular-component'; +const getTemplate = (inputAttributes: string = '') => ` + + + + + + + + + + + + + `; + describe('createAngularComponentDefinition()', () => { describe('www output', () => { it('generates a component', () => { @@ -12,37 +29,76 @@ describe('createAngularComponentDefinition()', () => { @Component({ selector: 'my-component', changeDetection: ChangeDetectionStrategy.OnPush, - template: '', + template: \`${getTemplate()}\`, // eslint-disable-next-line @angular-eslint/no-inputs-metadata-property inputs: [], +${' '} + providers: [ + {provide: StencilProxyComponent, useExisting: forwardRef(() => MyComponent)} + ], }) -export class MyComponent { +export class MyComponent extends StencilProxyComponent implements OnChanges { +${' '} protected el: HTMLElement; - constructor(c: ChangeDetectorRef, r: ElementRef, protected z: NgZone) { - c.detach(); + public availableInputProperties = []; + public hasTagNameTransformer: boolean; + public tagName: string; + @ViewChild(ReplaceTagDirective) replaceTagDirective: ReplaceTagDirective; + constructor(private changeDetectorRef: ChangeDetectorRef, r: ElementRef, protected z: NgZone) { + super(); + changeDetectorRef.detach(); + const originalTagName = 'my-component'; + this.tagName = typeof tagNameTransformer === 'function' ? tagNameTransformer(originalTagName) : originalTagName; + this.hasTagNameTransformer = typeof tagNameTransformer === 'function'; this.el = r.nativeElement; } + ngOnChanges(): void { + if (typeof this.replaceTagDirective === 'object' && this.replaceTagDirective !== null && typeof this.replaceTagDirective.handlePropertyChanges === 'function') { + this.replaceTagDirective.handlePropertyChanges(); + } + this.changeDetectorRef.detectChanges(); + } }`); }); it('generates a component with inputs', () => { const component = createAngularComponentDefinition('my-component', ['my-input', 'my-other-input'], [], [], false); - expect(component).toMatch(`@ProxyCmp({ + expect(component).toBe(`@ProxyCmp({ inputs: ['my-input', 'my-other-input'] }) @Component({ selector: 'my-component', changeDetection: ChangeDetectionStrategy.OnPush, - template: '', + template: \`${getTemplate('[my-input]="my-input" [my-other-input]="my-other-input"')}\`, // eslint-disable-next-line @angular-eslint/no-inputs-metadata-property inputs: ['my-input', 'my-other-input'], +${' '} + providers: [ + {provide: StencilProxyComponent, useExisting: forwardRef(() => MyComponent)} + ], }) -export class MyComponent { +export class MyComponent extends StencilProxyComponent implements OnChanges { + myInput: any; + myOtherInput: any; protected el: HTMLElement; - constructor(c: ChangeDetectorRef, r: ElementRef, protected z: NgZone) { - c.detach(); + public availableInputProperties = ['my-input', 'my-other-input']; + public hasTagNameTransformer: boolean; + public tagName: string; + @ViewChild(ReplaceTagDirective) replaceTagDirective: ReplaceTagDirective; + constructor(private changeDetectorRef: ChangeDetectorRef, r: ElementRef, protected z: NgZone) { + super(); + changeDetectorRef.detach(); + const originalTagName = 'my-component'; + this.tagName = typeof tagNameTransformer === 'function' ? tagNameTransformer(originalTagName) : originalTagName; + this.hasTagNameTransformer = typeof tagNameTransformer === 'function'; this.el = r.nativeElement; } + ngOnChanges(): void { + if (typeof this.replaceTagDirective === 'object' && this.replaceTagDirective !== null && typeof this.replaceTagDirective.handlePropertyChanges === 'function') { + this.replaceTagDirective.handlePropertyChanges(); + } + this.changeDetectorRef.detectChanges(); + } }`); }); @@ -55,44 +111,82 @@ export class MyComponent { false ); - expect(component).toMatch(`@ProxyCmp({ + expect(component).toBe(`@ProxyCmp({ }) @Component({ selector: 'my-component', changeDetection: ChangeDetectionStrategy.OnPush, - template: '', + template: \`${getTemplate()}\`, // eslint-disable-next-line @angular-eslint/no-inputs-metadata-property inputs: [], +${' '} + providers: [ + {provide: StencilProxyComponent, useExisting: forwardRef(() => MyComponent)} + ], }) -export class MyComponent { +export class MyComponent extends StencilProxyComponent implements OnChanges { +${' '} protected el: HTMLElement; - constructor(c: ChangeDetectorRef, r: ElementRef, protected z: NgZone) { - c.detach(); + public availableInputProperties = []; + public hasTagNameTransformer: boolean; + public tagName: string; + @ViewChild(ReplaceTagDirective) replaceTagDirective: ReplaceTagDirective; + constructor(private changeDetectorRef: ChangeDetectorRef, r: ElementRef, protected z: NgZone) { + super(); + changeDetectorRef.detach(); + const originalTagName = 'my-component'; + this.tagName = typeof tagNameTransformer === 'function' ? tagNameTransformer(originalTagName) : originalTagName; + this.hasTagNameTransformer = typeof tagNameTransformer === 'function'; this.el = r.nativeElement; proxyOutputs(this, this.el, ['my-output', 'my-other-output']); } + ngOnChanges(): void { + if (typeof this.replaceTagDirective === 'object' && this.replaceTagDirective !== null && typeof this.replaceTagDirective.handlePropertyChanges === 'function') { + this.replaceTagDirective.handlePropertyChanges(); + } + this.changeDetectorRef.detectChanges(); + } }`); }); it('generates a component with methods', () => { const component = createAngularComponentDefinition('my-component', [], [], ['myMethod', 'myOtherMethod'], false); - expect(component).toMatch(`@ProxyCmp({ + expect(component).toBe(`@ProxyCmp({ methods: ['myMethod', 'myOtherMethod'] }) @Component({ selector: 'my-component', changeDetection: ChangeDetectionStrategy.OnPush, - template: '', + template: \`${getTemplate()}\`, // eslint-disable-next-line @angular-eslint/no-inputs-metadata-property inputs: [], +${' '} + providers: [ + {provide: StencilProxyComponent, useExisting: forwardRef(() => MyComponent)} + ], }) -export class MyComponent { +export class MyComponent extends StencilProxyComponent implements OnChanges { +${' '} protected el: HTMLElement; - constructor(c: ChangeDetectorRef, r: ElementRef, protected z: NgZone) { - c.detach(); + public availableInputProperties = []; + public hasTagNameTransformer: boolean; + public tagName: string; + @ViewChild(ReplaceTagDirective) replaceTagDirective: ReplaceTagDirective; + constructor(private changeDetectorRef: ChangeDetectorRef, r: ElementRef, protected z: NgZone) { + super(); + changeDetectorRef.detach(); + const originalTagName = 'my-component'; + this.tagName = typeof tagNameTransformer === 'function' ? tagNameTransformer(originalTagName) : originalTagName; + this.hasTagNameTransformer = typeof tagNameTransformer === 'function'; this.el = r.nativeElement; } + ngOnChanges(): void { + if (typeof this.replaceTagDirective === 'object' && this.replaceTagDirective !== null && typeof this.replaceTagDirective.handlePropertyChanges === 'function') { + this.replaceTagDirective.handlePropertyChanges(); + } + this.changeDetectorRef.detectChanges(); + } }`); }); }); @@ -107,16 +201,35 @@ export class MyComponent { @Component({ selector: 'my-component', changeDetection: ChangeDetectionStrategy.OnPush, - template: '', + template: \`${getTemplate()}\`, // eslint-disable-next-line @angular-eslint/no-inputs-metadata-property inputs: [], +${' '} + providers: [ + {provide: StencilProxyComponent, useExisting: forwardRef(() => MyComponent)} + ], }) -export class MyComponent { +export class MyComponent extends StencilProxyComponent implements OnChanges { +${' '} protected el: HTMLElement; - constructor(c: ChangeDetectorRef, r: ElementRef, protected z: NgZone) { - c.detach(); + public availableInputProperties = []; + public hasTagNameTransformer: boolean; + public tagName: string; + @ViewChild(ReplaceTagDirective) replaceTagDirective: ReplaceTagDirective; + constructor(private changeDetectorRef: ChangeDetectorRef, r: ElementRef, protected z: NgZone) { + super(); + changeDetectorRef.detach(); + const originalTagName = 'my-component'; + this.tagName = typeof tagNameTransformer === 'function' ? tagNameTransformer(originalTagName) : originalTagName; + this.hasTagNameTransformer = typeof tagNameTransformer === 'function'; this.el = r.nativeElement; } + ngOnChanges(): void { + if (typeof this.replaceTagDirective === 'object' && this.replaceTagDirective !== null && typeof this.replaceTagDirective.handlePropertyChanges === 'function') { + this.replaceTagDirective.handlePropertyChanges(); + } + this.changeDetectorRef.detectChanges(); + } }`); }); @@ -130,16 +243,36 @@ export class MyComponent { @Component({ selector: 'my-component', changeDetection: ChangeDetectionStrategy.OnPush, - template: '', + template: \`${getTemplate('[my-input]="my-input" [my-other-input]="my-other-input"')}\`, // eslint-disable-next-line @angular-eslint/no-inputs-metadata-property inputs: ['my-input', 'my-other-input'], +${' '} + providers: [ + {provide: StencilProxyComponent, useExisting: forwardRef(() => MyComponent)} + ], }) -export class MyComponent { +export class MyComponent extends StencilProxyComponent implements OnChanges { + myInput: any; + myOtherInput: any; protected el: HTMLElement; - constructor(c: ChangeDetectorRef, r: ElementRef, protected z: NgZone) { - c.detach(); + public availableInputProperties = ['my-input', 'my-other-input']; + public hasTagNameTransformer: boolean; + public tagName: string; + @ViewChild(ReplaceTagDirective) replaceTagDirective: ReplaceTagDirective; + constructor(private changeDetectorRef: ChangeDetectorRef, r: ElementRef, protected z: NgZone) { + super(); + changeDetectorRef.detach(); + const originalTagName = 'my-component'; + this.tagName = typeof tagNameTransformer === 'function' ? tagNameTransformer(originalTagName) : originalTagName; + this.hasTagNameTransformer = typeof tagNameTransformer === 'function'; this.el = r.nativeElement; } + ngOnChanges(): void { + if (typeof this.replaceTagDirective === 'object' && this.replaceTagDirective !== null && typeof this.replaceTagDirective.handlePropertyChanges === 'function') { + this.replaceTagDirective.handlePropertyChanges(); + } + this.changeDetectorRef.detectChanges(); + } }`); }); @@ -151,46 +284,84 @@ export class MyComponent { [], true ); - expect(component).toMatch(`@ProxyCmp({ + expect(component).toBe(`@ProxyCmp({ defineCustomElementFn: defineMyComponent }) @Component({ selector: 'my-component', changeDetection: ChangeDetectionStrategy.OnPush, - template: '', + template: \`${getTemplate()}\`, // eslint-disable-next-line @angular-eslint/no-inputs-metadata-property inputs: [], +${' '} + providers: [ + {provide: StencilProxyComponent, useExisting: forwardRef(() => MyComponent)} + ], }) -export class MyComponent { +export class MyComponent extends StencilProxyComponent implements OnChanges { +${' '} protected el: HTMLElement; - constructor(c: ChangeDetectorRef, r: ElementRef, protected z: NgZone) { - c.detach(); + public availableInputProperties = []; + public hasTagNameTransformer: boolean; + public tagName: string; + @ViewChild(ReplaceTagDirective) replaceTagDirective: ReplaceTagDirective; + constructor(private changeDetectorRef: ChangeDetectorRef, r: ElementRef, protected z: NgZone) { + super(); + changeDetectorRef.detach(); + const originalTagName = 'my-component'; + this.tagName = typeof tagNameTransformer === 'function' ? tagNameTransformer(originalTagName) : originalTagName; + this.hasTagNameTransformer = typeof tagNameTransformer === 'function'; this.el = r.nativeElement; proxyOutputs(this, this.el, ['my-output', 'my-other-output']); } + ngOnChanges(): void { + if (typeof this.replaceTagDirective === 'object' && this.replaceTagDirective !== null && typeof this.replaceTagDirective.handlePropertyChanges === 'function') { + this.replaceTagDirective.handlePropertyChanges(); + } + this.changeDetectorRef.detectChanges(); + } }`); }); it('generates a component with methods', () => { const component = createAngularComponentDefinition('my-component', [], [], ['myMethod', 'myOtherMethod'], true); - expect(component).toMatch(`@ProxyCmp({ + expect(component).toBe(`@ProxyCmp({ defineCustomElementFn: defineMyComponent, methods: ['myMethod', 'myOtherMethod'] }) @Component({ selector: 'my-component', changeDetection: ChangeDetectionStrategy.OnPush, - template: '', + template: \`${getTemplate()}\`, // eslint-disable-next-line @angular-eslint/no-inputs-metadata-property inputs: [], +${' '} + providers: [ + {provide: StencilProxyComponent, useExisting: forwardRef(() => MyComponent)} + ], }) -export class MyComponent { +export class MyComponent extends StencilProxyComponent implements OnChanges { +${' '} protected el: HTMLElement; - constructor(c: ChangeDetectorRef, r: ElementRef, protected z: NgZone) { - c.detach(); + public availableInputProperties = []; + public hasTagNameTransformer: boolean; + public tagName: string; + @ViewChild(ReplaceTagDirective) replaceTagDirective: ReplaceTagDirective; + constructor(private changeDetectorRef: ChangeDetectorRef, r: ElementRef, protected z: NgZone) { + super(); + changeDetectorRef.detach(); + const originalTagName = 'my-component'; + this.tagName = typeof tagNameTransformer === 'function' ? tagNameTransformer(originalTagName) : originalTagName; + this.hasTagNameTransformer = typeof tagNameTransformer === 'function'; this.el = r.nativeElement; } + ngOnChanges(): void { + if (typeof this.replaceTagDirective === 'object' && this.replaceTagDirective !== null && typeof this.replaceTagDirective.handlePropertyChanges === 'function') { + this.replaceTagDirective.handlePropertyChanges(); + } + this.changeDetectorRef.detectChanges(); + } }`); }); @@ -203,52 +374,35 @@ export class MyComponent { @Component({ selector: 'my-component', changeDetection: ChangeDetectionStrategy.OnPush, - template: '', + template: \`${getTemplate()}\`, // eslint-disable-next-line @angular-eslint/no-inputs-metadata-property inputs: [], - standalone: true +${' '} + standalone: true, + providers: [ + {provide: StencilProxyComponent, useExisting: forwardRef(() => MyComponent)} + ], }) -export class MyComponent { +export class MyComponent extends StencilProxyComponent implements OnChanges { +${' '} protected el: HTMLElement; - constructor(c: ChangeDetectorRef, r: ElementRef, protected z: NgZone) { - c.detach(); + public availableInputProperties = []; + public hasTagNameTransformer: boolean; + public tagName: string; + @ViewChild(ReplaceTagDirective) replaceTagDirective: ReplaceTagDirective; + constructor(private changeDetectorRef: ChangeDetectorRef, r: ElementRef, protected z: NgZone) { + super(); + changeDetectorRef.detach(); + const originalTagName = 'my-component'; + this.tagName = typeof tagNameTransformer === 'function' ? tagNameTransformer(originalTagName) : originalTagName; + this.hasTagNameTransformer = typeof tagNameTransformer === 'function'; this.el = r.nativeElement; } -}`); - }); - }); - - describe('inline members', () => { - it('generates component with inlined member with jsDoc', () => { - const component = createAngularComponentDefinition('my-component', ['myMember'], [], [], false, false, [ - { - docs: { - tags: [{ name: 'deprecated', text: 'use v2 of this API' }], - text: 'This is a jsDoc for myMember', - }, - name: 'myMember', - } as ComponentCompilerProperty, - ]); - - expect(component).toEqual(`@ProxyCmp({ - inputs: ['myMember'] -}) -@Component({ - selector: 'my-component', - changeDetection: ChangeDetectionStrategy.OnPush, - template: '', - // eslint-disable-next-line @angular-eslint/no-inputs-metadata-property - inputs: ['myMember'], -}) -export class MyComponent { - protected el: HTMLElement; - /** - * This is a jsDoc for myMember @deprecated use v2 of this API - */ - myMember: Components.MyComponent['myMember']; - constructor(c: ChangeDetectorRef, r: ElementRef, protected z: NgZone) { - c.detach(); - this.el = r.nativeElement; + ngOnChanges(): void { + if (typeof this.replaceTagDirective === 'object' && this.replaceTagDirective !== null && typeof this.replaceTagDirective.handlePropertyChanges === 'function') { + this.replaceTagDirective.handlePropertyChanges(); + } + this.changeDetectorRef.detectChanges(); } }`); }); @@ -323,21 +477,6 @@ describe('createComponentTypeDefinition()', () => { tags: [], }, }, - { - name: 'my/slash/event', - complexType: { - references: { - MySlashEvent: { - location: 'import', - }, - }, - original: 'MySlashEvent', - }, - docs: { - text: '', - tags: [], - }, - }, ]; describe('www build', () => { @@ -345,11 +484,10 @@ describe('createComponentTypeDefinition()', () => { const definition = createComponentTypeDefinition('component', 'MyComponent', testEvents, '@ionic/core'); expect(definition).toEqual( - `import type { MyEvent as IMyComponentMyEvent } from '@ionic/core'; -import type { MyOtherEvent as IMyComponentMyOtherEvent } from '@ionic/core'; -import type { MyDoclessEvent as IMyComponentMyDoclessEvent } from '@ionic/core'; -import type { MyKebabEvent as IMyComponentMyKebabEvent } from '@ionic/core'; -import type { MySlashEvent as IMyComponentMySlashEvent } from '@ionic/core'; + `import { MyEvent as IMyComponentMyEvent } from '@ionic/core'; +import { MyOtherEvent as IMyComponentMyOtherEvent } from '@ionic/core'; +import { MyDoclessEvent as IMyComponentMyDoclessEvent } from '@ionic/core'; +import { MyKebabEvent as IMyComponentMyKebabEvent } from '@ionic/core'; export declare interface MyComponent extends Components.MyComponent { /** @@ -364,8 +502,6 @@ export declare interface MyComponent extends Components.MyComponent { myDoclessEvent: EventEmitter>; 'my-kebab-event': EventEmitter>; - - 'my/slash/event': EventEmitter>; }` ); }); @@ -421,7 +557,6 @@ export declare interface MyComponent extends Components.MyComponent { resolved: '{ side: Side; }', references: { Side: { - id: '', location: 'import', path: '../../interfaces', }, @@ -434,9 +569,9 @@ export declare interface MyComponent extends Components.MyComponent { ); expect(definition).toEqual( - `import type { MyEvent as IMyComponentMyEvent } from '@ionic/core'; -import type { Currency as IMyComponentCurrency } from '@ionic/core'; -import type { Side as IMyComponentSide } from '@ionic/core'; + `import { MyEvent as IMyComponentMyEvent } from '@ionic/core'; +import { Currency as IMyComponentCurrency } from '@ionic/core'; +import { Side as IMyComponentSide } from '@ionic/core'; export declare interface MyComponent extends Components.MyComponent { @@ -460,11 +595,10 @@ export declare interface MyComponent extends Components.MyComponent { ); expect(definition).toEqual( - `import type { MyEvent as IMyComponentMyEvent } from '@ionic/core/custom-elements'; -import type { MyOtherEvent as IMyComponentMyOtherEvent } from '@ionic/core/custom-elements'; -import type { MyDoclessEvent as IMyComponentMyDoclessEvent } from '@ionic/core/custom-elements'; -import type { MyKebabEvent as IMyComponentMyKebabEvent } from '@ionic/core/custom-elements'; -import type { MySlashEvent as IMyComponentMySlashEvent } from '@ionic/core/custom-elements'; + `import { MyEvent as IMyComponentMyEvent } from '@ionic/core/custom-elements'; +import { MyOtherEvent as IMyComponentMyOtherEvent } from '@ionic/core/custom-elements'; +import { MyDoclessEvent as IMyComponentMyDoclessEvent } from '@ionic/core/custom-elements'; +import { MyKebabEvent as IMyComponentMyKebabEvent } from '@ionic/core/custom-elements'; export declare interface MyComponent extends Components.MyComponent { /** @@ -479,8 +613,6 @@ export declare interface MyComponent extends Components.MyComponent { myDoclessEvent: EventEmitter>; 'my-kebab-event': EventEmitter>; - - 'my/slash/event': EventEmitter>; }` ); }); diff --git a/packages/angular/tests/generate-angular-modules.test.ts b/packages/angular/tests/generate-angular-modules.test.ts index d560c1ae..0076320e 100644 --- a/packages/angular/tests/generate-angular-modules.test.ts +++ b/packages/angular/tests/generate-angular-modules.test.ts @@ -1,13 +1,15 @@ -import { describe, it, expect } from 'vitest'; -import { generateAngularModuleForComponent } from '../src/generate-angular-modules'; +import { describe, it, expect } from "vitest"; +import { generateAngularModuleForComponent } from "../src/generate-angular-modules"; -describe('generateAngularModuleForComponent()', () => { - it('should generate an Angular module for each component', () => { - const modules = generateAngularModuleForComponent('my-component'); +describe("generateAngularModuleForComponent()", () => { + it("should generate an Angular module for each component", () => { + const modules = generateAngularModuleForComponent("my-component"); expect(modules).toEqual(`@NgModule({ - declarations: [MyComponent], - exports: [MyComponent] + declarations: [ReplaceTagDirective, MyComponent], + exports: [MyComponent], + schemas: [CUSTOM_ELEMENTS_SCHEMA], + imports: [CommonModule], }) export class MyComponentModule { }`); }); diff --git a/packages/react/package.json b/packages/react/package.json index a06ad5bd..1b13eef0 100644 --- a/packages/react/package.json +++ b/packages/react/package.json @@ -1,5 +1,5 @@ { - "name": "@stencil/react-output-target", + "name": "@public-ui/stencil-react-output-target", "version": "0.7.4", "description": "React output target for @stencil/core components.", "main": "./dist/react-output-target.js", diff --git a/packages/react/src/react-output-target/create-component-wrappers.test.ts b/packages/react/src/react-output-target/create-component-wrappers.test.ts index 070fb74f..76d7626c 100644 --- a/packages/react/src/react-output-target/create-component-wrappers.test.ts +++ b/packages/react/src/react-output-target/create-component-wrappers.test.ts @@ -38,8 +38,8 @@ describe('createComponentWrappers', () => { /* eslint-disable */ -import type { StencilReactComponent } from '@stencil/react-output-target/runtime'; -import { createComponent } from '@stencil/react-output-target/runtime'; +import type { StencilReactComponent } from '@public-ui/stencil-react-output-target/runtime'; +import { createComponent } from '@public-ui/stencil-react-output-target/runtime'; import { MyComponent as MyComponentElement, defineCustomElement as defineMyComponent } from "my-package/dist/custom-elements/my-component.js"; import React from 'react'; @@ -92,8 +92,8 @@ export const MyComponent: StencilReactComponent { `/* eslint-disable */ /* tslint:disable */ /* auto-generated vue proxies */ -import { defineContainer } from '@stencil/vue-output-target/runtime'; +import { defineContainer } from '@public-ui/stencil-vue-output-target/runtime'; import type { JSX } from 'component-library'; @@ -50,7 +50,7 @@ applyPolyfills().then(() => defineCustomElements()); `/* eslint-disable */ /* tslint:disable */ /* auto-generated vue proxies */ -import { defineContainer } from '@stencil/vue-output-target/runtime'; +import { defineContainer } from '@public-ui/stencil-vue-output-target/runtime'; import type { JSX } from 'component-library'; @@ -75,7 +75,7 @@ defineCustomElements(); `/* eslint-disable */ /* tslint:disable */ /* auto-generated vue proxies */ -import { defineContainer } from '@stencil/vue-output-target/runtime'; +import { defineContainer } from '@public-ui/stencil-vue-output-target/runtime'; import type { JSX } from 'component-library'; @@ -97,7 +97,7 @@ import type { JSX } from 'component-library'; `/* eslint-disable */ /* tslint:disable */ /* auto-generated vue proxies */ -import { defineContainer } from '@stencil/vue-output-target/runtime'; +import { defineContainer } from '@public-ui/stencil-vue-output-target/runtime'; import type { JSX } from 'component-library/components'; @@ -120,7 +120,7 @@ import type { JSX } from 'component-library/components'; `/* eslint-disable */ /* tslint:disable */ /* auto-generated vue proxies */ -import { defineContainer } from '@stencil/vue-output-target/runtime'; +import { defineContainer } from '@public-ui/stencil-vue-output-target/runtime'; import type { JSX } from 'component-library/custom-dir/hello'; diff --git a/packages/vue/src/output-vue.ts b/packages/vue/src/output-vue.ts index d49796fa..ff63f058 100644 --- a/packages/vue/src/output-vue.ts +++ b/packages/vue/src/output-vue.ts @@ -43,7 +43,8 @@ export function generateProxies( const imports = `/* eslint-disable */ /* tslint:disable */ /* auto-generated vue proxies */ -import { ${importKeys.join(', ')} } from '@stencil/vue-output-target/runtime';\n`; +import { ${importKeys.join(', ')} } from '@public-ui/stencil-vue-output-target/runtime'; +import { setTagNameTransformer } from './tag-name-transformer';\n`; const generateTypeImports = () => { if (outputTarget.componentCorePackage !== undefined) { @@ -85,6 +86,7 @@ import { ${importKeys.join(', ')} } from '@stencil/vue-output-target/runtime';\n sourceImports, registerCustomElements, components.map(createComponentDefinition(IMPORT_TYPES, outputTarget)).join('\n'), + `export { setTagNameTransformer };`, ]; return final.join('\n') + '\n'; diff --git a/packages/vue/src/runtime.ts b/packages/vue/src/runtime.ts index 5a332cbd..1b980834 100644 --- a/packages/vue/src/runtime.ts +++ b/packages/vue/src/runtime.ts @@ -1,4 +1,5 @@ import { defineComponent, getCurrentInstance, h, inject, ref, Ref, withDirectives } from 'vue'; +import { tagNameTransformer } from './tag-name-transformer'; export { defineStencilSSRComponent } from './ssr'; export interface InputProps { @@ -217,11 +218,13 @@ export const defineContainer = ( }; } + const transformedTagName = typeof tagNameTransformer === 'function' ? tagNameTransformer (name) : name; + /** * vModelDirective is only needed on components that support v-model. * As a result, we conditionally call withDirectives with v-model components. */ - const node = h(name, propsToAdd, slots.default && slots.default()); + const node = h(transformedTagName, propsToAdd, slots.default && slots.default()); return modelProp === undefined ? node : withDirectives(node, [[vModelDirective]]); }; }); diff --git a/packages/vue/src/tag-name-transformer.ts b/packages/vue/src/tag-name-transformer.ts new file mode 100644 index 00000000..a7a4a4a4 --- /dev/null +++ b/packages/vue/src/tag-name-transformer.ts @@ -0,0 +1,6 @@ +type TagNameTransformer = (tagName: string) => string; + +export let tagNameTransformer: TagNameTransformer | undefined; +export const setTagNameTransformer = (_tagNameTransformer: TagNameTransformer) => { + tagNameTransformer = _tagNameTransformer; +}; diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 5c75a1d2..8a3b2a91 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -38,18 +38,18 @@ importers: example-project/component-library: devDependencies: - '@stencil/angular-output-target': + '@public-ui/stencil-angular-output-target': specifier: workspace:* version: link:../../packages/angular - '@stencil/core': - specifier: ^4.22.1 - version: 4.22.2 - '@stencil/react-output-target': + '@public-ui/stencil-react-output-target': specifier: workspace:* version: link:../../packages/react - '@stencil/vue-output-target': + '@public-ui/stencil-vue-output-target': specifier: workspace:* version: link:../../packages/vue + '@stencil/core': + specifier: ^4.22.1 + version: 4.22.2 '@types/puppeteer': specifier: 2.0.1 version: 2.0.1 @@ -126,7 +126,7 @@ importers: example-project/component-library-react: dependencies: - '@stencil/react-output-target': + '@public-ui/stencil-react-output-target': specifier: workspace:* version: link:../../packages/react component-library: @@ -199,7 +199,7 @@ importers: example-project/component-library-vue: dependencies: - '@stencil/vue-output-target': + '@public-ui/stencil-vue-output-target': specifier: workspace:* version: link:../../packages/vue component-library: @@ -231,7 +231,7 @@ importers: specifier: ^18 version: 18.3.1(react@18.3.1) devDependencies: - '@stencil/react-output-target': + '@public-ui/stencil-react-output-target': specifier: workspace:* version: link:../../packages/react '@types/node': @@ -11567,7 +11567,7 @@ snapshots: dependencies: '@ampproject/remapping': 2.3.0 '@babel/code-frame': 7.26.2 - '@babel/generator': 7.23.6 + '@babel/generator': 7.26.2 '@babel/helper-compilation-targets': 7.25.9 '@babel/helper-module-transforms': 7.26.0(@babel/core@7.24.0) '@babel/helpers': 7.26.0 @@ -14626,33 +14626,33 @@ snapshots: '@types/body-parser@1.19.5': dependencies: '@types/connect': 3.4.38 - '@types/node': 22.9.0 + '@types/node': 20.17.6 '@types/bonjour@3.5.13': dependencies: - '@types/node': 22.9.0 + '@types/node': 20.17.6 '@types/connect-history-api-fallback@1.5.4': dependencies: '@types/express-serve-static-core': 5.0.1 - '@types/node': 22.9.0 + '@types/node': 20.17.6 '@types/connect@3.4.38': dependencies: - '@types/node': 22.9.0 + '@types/node': 20.17.6 '@types/estree@1.0.6': {} '@types/express-serve-static-core@4.19.6': dependencies: - '@types/node': 22.9.0 + '@types/node': 20.17.6 '@types/qs': 6.9.17 '@types/range-parser': 1.2.7 '@types/send': 0.17.4 '@types/express-serve-static-core@5.0.1': dependencies: - '@types/node': 22.9.0 + '@types/node': 20.17.6 '@types/qs': 6.9.17 '@types/range-parser': 1.2.7 '@types/send': 0.17.4 @@ -14713,7 +14713,7 @@ snapshots: '@types/node-forge@1.3.11': dependencies: - '@types/node': 22.9.0 + '@types/node': 20.17.6 '@types/node@18.19.64': dependencies: @@ -14757,7 +14757,7 @@ snapshots: '@types/send@0.17.4': dependencies: '@types/mime': 1.3.5 - '@types/node': 22.9.0 + '@types/node': 20.17.6 '@types/serve-index@1.9.4': dependencies: @@ -14766,14 +14766,14 @@ snapshots: '@types/serve-static@1.15.7': dependencies: '@types/http-errors': 2.0.4 - '@types/node': 22.9.0 + '@types/node': 20.17.6 '@types/send': 0.17.4 '@types/sinonjs__fake-timers@8.1.5': {} '@types/sockjs@0.3.36': dependencies: - '@types/node': 22.9.0 + '@types/node': 20.17.6 '@types/stack-utils@2.0.3': {} @@ -16734,7 +16734,7 @@ snapshots: dom-serializer: 2.0.0 domhandler: 5.0.3 htmlparser2: 8.0.2 - postcss: 8.4.35 + postcss: 8.4.49 postcss-media-query-parser: 0.2.3 croner@9.0.0: {} @@ -16765,14 +16765,14 @@ snapshots: css-loader@6.10.0(webpack@5.94.0(esbuild@0.20.1)): dependencies: - icss-utils: 5.1.0(postcss@8.4.35) - postcss: 8.4.35 - postcss-modules-extract-imports: 3.1.0(postcss@8.4.35) - postcss-modules-local-by-default: 4.1.0(postcss@8.4.35) - postcss-modules-scope: 3.2.1(postcss@8.4.35) - postcss-modules-values: 4.0.0(postcss@8.4.35) + icss-utils: 5.1.0(postcss@8.4.49) + postcss: 8.4.49 + postcss-modules-extract-imports: 3.1.0(postcss@8.4.49) + postcss-modules-local-by-default: 4.1.0(postcss@8.4.49) + postcss-modules-scope: 3.2.1(postcss@8.4.49) + postcss-modules-values: 4.0.0(postcss@8.4.49) postcss-value-parser: 4.2.0 - semver: 7.6.0 + semver: 7.6.3 optionalDependencies: webpack: 5.94.0(esbuild@0.20.1) @@ -17472,7 +17472,7 @@ snapshots: eslint: 8.57.1 eslint-import-resolver-node: 0.3.9 eslint-import-resolver-typescript: 3.6.3(@typescript-eslint/parser@8.13.0(eslint@8.57.1)(typescript@5.6.3))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.31.0(@typescript-eslint/parser@8.13.0(eslint@8.57.1)(typescript@5.6.3))(eslint@8.57.1))(eslint@8.57.1) - eslint-plugin-import: 2.31.0(@typescript-eslint/parser@8.13.0(eslint@8.57.1)(typescript@5.6.3))(eslint-import-resolver-typescript@3.6.3)(eslint@8.57.1) + eslint-plugin-import: 2.31.0(@typescript-eslint/parser@8.13.0(eslint@8.57.1)(typescript@5.6.3))(eslint-import-resolver-typescript@3.6.3(@typescript-eslint/parser@8.13.0(eslint@8.57.1)(typescript@5.6.3))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.31.0(@typescript-eslint/parser@8.13.0(eslint@8.57.1)(typescript@5.6.3))(eslint@8.57.1))(eslint@8.57.1))(eslint@8.57.1) eslint-plugin-jsx-a11y: 6.10.2(eslint@8.57.1) eslint-plugin-react: 7.37.2(eslint@8.57.1) eslint-plugin-react-hooks: 4.6.2(eslint@8.57.1) @@ -17503,7 +17503,7 @@ snapshots: is-bun-module: 1.2.1 is-glob: 4.0.3 optionalDependencies: - eslint-plugin-import: 2.31.0(@typescript-eslint/parser@8.13.0(eslint@8.57.1)(typescript@5.6.3))(eslint-import-resolver-typescript@3.6.3)(eslint@8.57.1) + eslint-plugin-import: 2.31.0(@typescript-eslint/parser@8.13.0(eslint@8.57.1)(typescript@5.6.3))(eslint-import-resolver-typescript@3.6.3(@typescript-eslint/parser@8.13.0(eslint@8.57.1)(typescript@5.6.3))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.31.0(@typescript-eslint/parser@8.13.0(eslint@8.57.1)(typescript@5.6.3))(eslint@8.57.1))(eslint@8.57.1))(eslint@8.57.1) transitivePeerDependencies: - '@typescript-eslint/parser' - eslint-import-resolver-node @@ -17521,7 +17521,7 @@ snapshots: transitivePeerDependencies: - supports-color - eslint-plugin-import@2.31.0(@typescript-eslint/parser@8.13.0(eslint@8.57.1)(typescript@5.6.3))(eslint-import-resolver-typescript@3.6.3)(eslint@8.57.1): + eslint-plugin-import@2.31.0(@typescript-eslint/parser@8.13.0(eslint@8.57.1)(typescript@5.6.3))(eslint-import-resolver-typescript@3.6.3(@typescript-eslint/parser@8.13.0(eslint@8.57.1)(typescript@5.6.3))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.31.0(@typescript-eslint/parser@8.13.0(eslint@8.57.1)(typescript@5.6.3))(eslint@8.57.1))(eslint@8.57.1))(eslint@8.57.1): dependencies: '@rtsao/scc': 1.1.0 array-includes: 3.1.8 @@ -18641,9 +18641,9 @@ snapshots: dependencies: safer-buffer: 2.1.2 - icss-utils@5.1.0(postcss@8.4.35): + icss-utils@5.1.0(postcss@8.4.49): dependencies: - postcss: 8.4.35 + postcss: 8.4.49 ieee754@1.2.1: {} @@ -19555,7 +19555,11 @@ snapshots: pretty-format: 26.6.2 throat: 5.0.0 transitivePeerDependencies: + - bufferutil + - canvas - supports-color + - ts-node + - utf-8-validate jest-leak-detector@26.6.2: dependencies: @@ -19926,7 +19930,7 @@ snapshots: jest-worker@27.5.1: dependencies: - '@types/node': 22.9.0 + '@types/node': 20.17.6 merge-stream: 2.0.0 supports-color: 8.1.1 @@ -20280,7 +20284,7 @@ snapshots: dependencies: copy-anything: 2.0.6 parse-node-version: 1.0.1 - tslib: 2.6.2 + tslib: 2.8.1 optionalDependencies: errno: 0.1.8 graceful-fs: 4.2.11 @@ -21996,7 +22000,7 @@ snapshots: cosmiconfig: 9.0.0(typescript@5.1.6) jiti: 1.21.6 postcss: 8.4.35 - semver: 7.6.0 + semver: 7.6.3 optionalDependencies: webpack: 5.94.0(esbuild@0.20.1) transitivePeerDependencies: @@ -22043,26 +22047,26 @@ snapshots: postcss: 8.4.49 postcss-selector-parser: 6.1.2 - postcss-modules-extract-imports@3.1.0(postcss@8.4.35): + postcss-modules-extract-imports@3.1.0(postcss@8.4.49): dependencies: - postcss: 8.4.35 + postcss: 8.4.49 - postcss-modules-local-by-default@4.1.0(postcss@8.4.35): + postcss-modules-local-by-default@4.1.0(postcss@8.4.49): dependencies: - icss-utils: 5.1.0(postcss@8.4.35) - postcss: 8.4.35 + icss-utils: 5.1.0(postcss@8.4.49) + postcss: 8.4.49 postcss-selector-parser: 7.0.0 postcss-value-parser: 4.2.0 - postcss-modules-scope@3.2.1(postcss@8.4.35): + postcss-modules-scope@3.2.1(postcss@8.4.49): dependencies: - postcss: 8.4.35 + postcss: 8.4.49 postcss-selector-parser: 7.0.0 - postcss-modules-values@4.0.0(postcss@8.4.35): + postcss-modules-values@4.0.0(postcss@8.4.49): dependencies: - icss-utils: 5.1.0(postcss@8.4.35) - postcss: 8.4.35 + icss-utils: 5.1.0(postcss@8.4.49) + postcss: 8.4.49 postcss-nested@6.2.0(postcss@8.4.47): dependencies: @@ -22545,7 +22549,7 @@ snapshots: adjust-sourcemap-loader: 4.0.0 convert-source-map: 1.9.0 loader-utils: 2.0.4 - postcss: 8.4.35 + postcss: 8.4.49 source-map: 0.6.1 resolve-url@0.2.1: {} @@ -23462,7 +23466,7 @@ snapshots: jest-worker: 27.5.1 schema-utils: 3.3.0 serialize-javascript: 6.0.2 - terser: 5.29.1 + terser: 5.36.0 webpack: 5.94.0(esbuild@0.20.1) optionalDependencies: esbuild: 0.20.1 @@ -24152,7 +24156,7 @@ snapshots: vite@5.1.8(@types/node@20.17.6)(less@4.2.0)(sass@1.71.1)(terser@5.29.1): dependencies: esbuild: 0.19.12 - postcss: 8.4.35 + postcss: 8.4.49 rollup: 4.27.2 optionalDependencies: '@types/node': 20.17.6