Skip to content

Commit

Permalink
fix(angular): support nested namespaces in event types (#575)
Browse files Browse the repository at this point in the history
* fix(angular): support nested namespaces in event types

* remove pnpm version config

* fix lock file
  • Loading branch information
christian-bromann authored Dec 18, 2024
1 parent 46e5d61 commit 419dacc
Show file tree
Hide file tree
Showing 20 changed files with 176 additions and 2,148 deletions.
2 changes: 0 additions & 2 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,6 @@ jobs:
- name: Checkout Code
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- uses: pnpm/action-setup@fe02b34f77f8bc703788d5817da081398fad5dd2 # v4.0.0
with:
version: 9
- name: Use Node
uses: actions/setup-node@39370e3970a6d050c480ffad4ff0ed4d3fdee5af # v4.1.0
with:
Expand Down
2 changes: 0 additions & 2 deletions .github/workflows/dev-build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,6 @@ jobs:
- name: Checkout Code
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- uses: pnpm/action-setup@fe02b34f77f8bc703788d5817da081398fad5dd2 # v4.0.0
with:
version: 9
- uses: actions/setup-node@39370e3970a6d050c480ffad4ff0ed4d3fdee5af # v4.1.0
with:
node-version: '20.10.0'
Expand Down
2 changes: 0 additions & 2 deletions .github/workflows/format.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,6 @@ jobs:
- name: Checkout Code
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- uses: pnpm/action-setup@fe02b34f77f8bc703788d5817da081398fad5dd2 # v4.0.0
with:
version: 9
- name: Use Node
uses: actions/setup-node@39370e3970a6d050c480ffad4ff0ed4d3fdee5af # v4.1.0
with:
Expand Down
2 changes: 0 additions & 2 deletions .github/workflows/prod-build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,6 @@ jobs:
steps:
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- uses: pnpm/action-setup@fe02b34f77f8bc703788d5817da081398fad5dd2 # v4.0.0
with:
version: 9
- uses: actions/setup-node@39370e3970a6d050c480ffad4ff0ed4d3fdee5af # v4.1.0
with:
node-version: '20.10.0'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -92,16 +92,22 @@ export class MyComponent {
constructor(c: ChangeDetectorRef, r: ElementRef, protected z: NgZone) {
c.detach();
this.el = r.nativeElement;
proxyOutputs(this, this.el, ['myCustomEvent']);
proxyOutputs(this, this.el, ['myCustomEvent', 'myCustomNestedEvent']);
}
}


import type { IMyComponent as IMyComponentIMyComponent } from 'component-library';

export declare interface MyComponent extends Components.MyComponent {
/**
* Testing an event without value
*/
myCustomEvent: EventEmitter<CustomEvent<number>>;
myCustomEvent: EventEmitter<CustomEvent<IMyComponentIMyComponent.someVar>>;
/**
* Testing with nested namespaces
*/
myCustomNestedEvent: EventEmitter<CustomEvent<IMyComponentIMyComponent.SomeMoreComplexType.SubType>>;
}


Expand Down
12 changes: 9 additions & 3 deletions example-project/component-library-react/src/components.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@

import type { EventName, StencilReactComponent } from '@stencil/react-output-target/runtime';
import { createComponent } from '@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 { type CheckboxChangeEventDetail, type IMyComponent, type InputChangeEventDetail, type MyCheckboxCustomEvent, type MyComponentCustomEvent, 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";
import { MyComponent as MyComponentElement, defineCustomElement as defineMyComponent } from "component-library/components/my-component.js";
Expand Down Expand Up @@ -56,14 +56,20 @@ export const MyCheckbox: StencilReactComponent<MyCheckboxElement, MyCheckboxEven
defineCustomElement: defineMyCheckbox
});

type MyComponentEvents = { onMyCustomEvent: EventName<CustomEvent<number>> };
type MyComponentEvents = {
onMyCustomEvent: EventName<MyComponentCustomEvent<IMyComponent.someVar>>,
onMyCustomNestedEvent: EventName<MyComponentCustomEvent<IMyComponent.SomeMoreComplexType.SubType>>
};

export const MyComponent: StencilReactComponent<MyComponentElement, MyComponentEvents> = /*@__PURE__*/ createComponent<MyComponentElement, MyComponentEvents>({
tagName: 'my-component',
elementClass: MyComponentElement,
// @ts-ignore - React type of Stencil Output Target may differ from the React version used in the Nuxt.js project, this can be ignored.
react: React,
events: { onMyCustomEvent: 'myCustomEvent' } as MyComponentEvents,
events: {
onMyCustomEvent: 'myCustomEvent',
onMyCustomNestedEvent: 'myCustomNestedEvent'
} as MyComponentEvents,
defineCustomElement: defineMyComponent
});

Expand Down
9 changes: 6 additions & 3 deletions example-project/component-library-vue/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -99,9 +99,11 @@ export const MyComponent = /*@__PURE__*/ globalThis.window ? defineContainer<JSX
'age',
'kidsNames',
'favoriteKidName',
'myCustomEvent'
'myCustomEvent',
'myCustomNestedEvent'
], [
'myCustomEvent'
'myCustomEvent',
'myCustomNestedEvent'
]) : defineStencilSSRComponent({
tagName: 'my-component',
hydrateModule: import('component-library/hydrate'),
Expand All @@ -111,7 +113,8 @@ export const MyComponent = /*@__PURE__*/ globalThis.window ? defineContainer<JSX
'last': [String, "last"],
'age': [Number, "age"],
'favoriteKidName': [String, "favorite-kid-name"],
'onMyCustomEvent': [Function]
'onMyCustomEvent': [Function],
'onMyCustomNestedEvent': [Function]
}
});

Expand Down
3 changes: 1 addition & 2 deletions example-project/component-library/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,6 @@
"@stencil/core": "^4.22.3",
"@stencil/react-output-target": "workspace:*",
"@stencil/vue-output-target": "workspace:*",
"@types/puppeteer": "2.0.1",
"jest-cli": "26.0.1"
"@types/puppeteer": "2.0.1"
}
}
11 changes: 9 additions & 2 deletions example-project/component-library/src/components.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,13 @@
import { HTMLStencilElement, JSXBase } from "@stencil/core/internal";
import { AutocompleteTypes, Color, ComponentProps, ComponentRef, OverlayEventDetail, TextFieldTypes } from "./interfaces";
import { CheckboxChangeEventDetail, Color as Color1, StyleEventDetail } from "./components/element-interface";
import { IMyComponent } from "./components/helpers";
import { InputChangeEventDetail } from "./components/my-input/my-input";
import { RadioGroupChangeEventDetail } from "./components/my-radio-group/my-radio-group";
import { RangeChangeEventDetail, RangeValue } from "./components/my-range/my-range";
export { AutocompleteTypes, Color, ComponentProps, ComponentRef, OverlayEventDetail, TextFieldTypes } from "./interfaces";
export { CheckboxChangeEventDetail, Color as Color1, StyleEventDetail } from "./components/element-interface";
export { IMyComponent } from "./components/helpers";
export { InputChangeEventDetail } from "./components/my-input/my-input";
export { RadioGroupChangeEventDetail } from "./components/my-radio-group/my-radio-group";
export { RangeChangeEventDetail, RangeValue } from "./components/my-range/my-range";
Expand Down Expand Up @@ -471,7 +473,8 @@ declare global {
new (): HTMLMyCheckboxElement;
};
interface HTMLMyComponentElementEventMap {
"myCustomEvent": number;
"myCustomEvent": IMyComponent.someVar;
"myCustomNestedEvent": IMyComponent.SomeMoreComplexType.SubType;
}
interface HTMLMyComponentElement extends Components.MyComponent, HTMLStencilElement {
addEventListener<K extends keyof HTMLMyComponentElementEventMap>(type: K, listener: (this: HTMLMyComponentElement, ev: MyComponentCustomEvent<HTMLMyComponentElementEventMap[K]>) => any, options?: boolean | AddEventListenerOptions): void;
Expand Down Expand Up @@ -736,7 +739,11 @@ declare namespace LocalJSX {
/**
* Testing an event without value
*/
"onMyCustomEvent"?: (event: MyComponentCustomEvent<number>) => void;
"onMyCustomEvent"?: (event: MyComponentCustomEvent<IMyComponent.someVar>) => void;
/**
* Testing with nested namespaces
*/
"onMyCustomNestedEvent"?: (event: MyComponentCustomEvent<IMyComponent.SomeMoreComplexType.SubType>) => void;
}
interface MyInput {
/**
Expand Down
8 changes: 8 additions & 0 deletions example-project/component-library/src/components/helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -153,3 +153,11 @@ export const onceEvent = (element: HTMLElement, eventName: string, callback: (ev
};
element.addEventListener(eventName, handler);
};

export declare namespace IMyComponent {
/** Variables */
export type someVar = number;
export namespace SomeMoreComplexType {
export type SubType = string;
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { Component, Prop, h, Event, EventEmitter } from '@stencil/core';
import type { IMyComponent } from '../helpers';

@Component({
tag: 'my-component',
Expand Down Expand Up @@ -39,7 +40,12 @@ export class MyComponent {
/**
* Testing an event without value
*/
@Event() myCustomEvent: EventEmitter<number>;
@Event() myCustomEvent: EventEmitter<IMyComponent.someVar>;

/**
* Testing with nested namespaces
*/
@Event() myCustomNestedEvent: EventEmitter<IMyComponent.SomeMoreComplexType.SubType>;

emitCustomEvent() {
this.myCustomEvent.emit(5);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,10 @@

## Events

| Event | Description | Type |
| --------------- | ------------------------------ | --------------------- |
| `myCustomEvent` | Testing an event without value | `CustomEvent<number>` |
| Event | Description | Type |
| --------------------- | ------------------------------ | --------------------- |
| `myCustomEvent` | Testing an event without value | `CustomEvent<number>` |
| `myCustomNestedEvent` | Testing with nested namespaces | `CustomEvent<string>` |


----------------------------------------------
Expand Down
12 changes: 9 additions & 3 deletions example-project/next-app/src/app/components.server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@

import type { EventName, StencilReactComponent } from '@stencil/react-output-target/runtime';
import { createComponent, createSSRComponent } from '@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 { type CheckboxChangeEventDetail, type IMyComponent, type InputChangeEventDetail, type MyCheckboxCustomEvent, type MyComponentCustomEvent, 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";
import { MyComponent as MyComponentElement, defineCustomElement as defineMyComponent } from "component-library/components/my-component.js";
Expand Down Expand Up @@ -90,15 +90,21 @@ export const MyCheckbox: StencilReactComponent<MyCheckboxElement, MyCheckboxEven
hydrateModule: import('component-library/hydrate')
});

type MyComponentEvents = { onMyCustomEvent: EventName<CustomEvent<number>> };
type MyComponentEvents = {
onMyCustomEvent: EventName<MyComponentCustomEvent<IMyComponent.someVar>>,
onMyCustomNestedEvent: EventName<MyComponentCustomEvent<IMyComponent.SomeMoreComplexType.SubType>>
};

export const MyComponent: StencilReactComponent<MyComponentElement, MyComponentEvents> = typeof window !== 'undefined'
? /*@__PURE__*/ createComponent<MyComponentElement, MyComponentEvents>({
tagName: 'my-component',
elementClass: MyComponentElement,
// @ts-ignore - React type of Stencil Output Target may differ from the React version used in the Nuxt.js project, this can be ignored.
react: React,
events: { onMyCustomEvent: 'myCustomEvent' } as MyComponentEvents,
events: {
onMyCustomEvent: 'myCustomEvent',
onMyCustomNestedEvent: 'myCustomNestedEvent'
} as MyComponentEvents,
defineCustomElement: defineMyComponent
})
: /*@__PURE__*/ createSSRComponent<MyComponentElement, MyComponentEvents>({
Expand Down
5 changes: 3 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@
"prettier": "^3.3.3",
"rimraf": "^6.0.1",
"semver": "^5.5.0",
"ts-jest": "^26.2.0"
"vitest": "^2.1.8"
},
"prettier": "@ionic/prettier-config",
"engines": {
Expand All @@ -59,5 +59,6 @@
"patchedDependencies": {
"[email protected]": "patches/[email protected]"
}
}
},
"packageManager": "[email protected]+sha512.beb9e2a803db336c10c9af682b58ad7181ca0fbd0d4119f2b33d5f2582e96d6c0d93c85b23869295b765170fbdaa92890c0da6ada457415039769edf3c959efe"
}
2 changes: 1 addition & 1 deletion packages/angular/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,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",
Expand Down
4 changes: 4 additions & 0 deletions packages/angular/src/generate-angular-component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,10 @@ const formatOutputType = (componentClassName: string, event: ComponentCompilerEv
}
return [p1, dst, p2].join('');
})
// Capture all instances that contain sub types, e.g. `IMyComponent.SomeMoreComplexType.SubType`.
.replace(new RegExp(`^${src}(\.\\w+)+$`, 'g'), (type: string) => {
return `I${componentClassName}${src}.${type.split('.').slice(1).join('.')}`;
})
);
},
event.complexType.original
Expand Down
14 changes: 0 additions & 14 deletions packages/angular/test/jest.preprocessor.js

This file was deleted.

58 changes: 58 additions & 0 deletions packages/angular/tests/generate-angular-component.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -338,6 +338,46 @@ describe('createComponentTypeDefinition()', () => {
tags: [],
},
},
{
name: 'myCustomEvent',
method: 'myCustomEvent',
bubbles: true,
cancelable: true,
composed: true,
docs: { tags: [], text: 'Testing an event type with a dot signature' },
complexType: {
original: 'IMyComponent.someVar',
resolved: 'number',
references: {
IMyComponent: {
location: 'import',
path: '../helpers',
id: 'src/components/helpers.ts::IMyComponent'
}
}
},
internal: false
},
{
name: 'myCustomNestedEvent',
method: 'myCustomNestedEvent',
bubbles: true,
cancelable: true,
composed: true,
docs: { tags: [], text: 'Testing with nested namespaces' },
complexType: {
original: 'IMyComponent.SomeMoreComplexType.SubType',
resolved: 'string',
references: {
IMyComponent: {
location: 'import',
path: '../helpers',
id: 'src/components/helpers.ts::IMyComponent'
}
}
},
internal: false
}
];

describe('www build', () => {
Expand All @@ -350,6 +390,7 @@ 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 type { IMyComponent as IMyComponentIMyComponent } from '@ionic/core';
export declare interface MyComponent extends Components.MyComponent {
/**
Expand All @@ -366,6 +407,14 @@ export declare interface MyComponent extends Components.MyComponent {
'my-kebab-event': EventEmitter<CustomEvent<IMyComponentMyKebabEvent>>;
'my/slash/event': EventEmitter<CustomEvent<IMyComponentMySlashEvent>>;
/**
* Testing an event type with a dot signature
*/
myCustomEvent: EventEmitter<CustomEvent<IMyComponentIMyComponent.someVar>>;
/**
* Testing with nested namespaces
*/
myCustomNestedEvent: EventEmitter<CustomEvent<IMyComponentIMyComponent.SomeMoreComplexType.SubType>>;
}`
);
});
Expand Down Expand Up @@ -465,6 +514,7 @@ import type { MyOtherEvent as IMyComponentMyOtherEvent } from '@ionic/core/custo
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 type { IMyComponent as IMyComponentIMyComponent } from '@ionic/core/custom-elements';
export declare interface MyComponent extends Components.MyComponent {
/**
Expand All @@ -481,6 +531,14 @@ export declare interface MyComponent extends Components.MyComponent {
'my-kebab-event': EventEmitter<CustomEvent<IMyComponentMyKebabEvent>>;
'my/slash/event': EventEmitter<CustomEvent<IMyComponentMySlashEvent>>;
/**
* Testing an event type with a dot signature
*/
myCustomEvent: EventEmitter<CustomEvent<IMyComponentIMyComponent.someVar>>;
/**
* Testing with nested namespaces
*/
myCustomNestedEvent: EventEmitter<CustomEvent<IMyComponentIMyComponent.SomeMoreComplexType.SubType>>;
}`
);
});
Expand Down
2 changes: 1 addition & 1 deletion packages/angular/tests/output-angular.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ describe('generateProxies', () => {

const finalText = generateProxies(components, pkgData, outputTarget, rootDir);
expect(finalText).not.toContain(`import { Components } from 'component-library';`);
expect(finalText.includes(`import { Components } from '../../angular/dist/types/components';`)).toBeTruthy();
expect(finalText).toContain(`import { Components } from '../../angular/dist/types/components';`);
});

it('should include output related imports when there is component with not internal event', () => {
Expand Down
Loading

0 comments on commit 419dacc

Please sign in to comment.