Skip to content

Commit

Permalink
Merge pull request #26546 from storybookjs/valentin/add-output-suppor…
Browse files Browse the repository at this point in the history
…t-for-angular

Angular: Add support for Angular's output signals
  • Loading branch information
valentinpalkovic committed Mar 20, 2024
2 parents c2fd3a4 + 7a0a1c7 commit 2eaf4a6
Show file tree
Hide file tree
Showing 4 changed files with 20 additions and 11 deletions.
4 changes: 3 additions & 1 deletion code/frameworks/angular/scripts/postbuild.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,5 +10,7 @@ const path = require('path');

const filePath = path.join(__dirname, '../dist/client/public-types.d.ts');
const fileContent = fs.readFileSync(filePath, 'utf8');
const newContent = fileContent.replaceAll(/(type AngularInputSignal)/g, '// @ts-ignore\n$1');
const newContent = fileContent
.replaceAll(/(type AngularInputSignal)/g, '// @ts-ignore\n$1')
.replaceAll(/(type AngularOutputEmitterRef)/g, '// @ts-ignore\n$1');
fs.writeFileSync(filePath, newContent, 'utf8');
17 changes: 13 additions & 4 deletions code/frameworks/angular/src/client/public-types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,21 +56,30 @@ export type Preview = ProjectAnnotations<AngularRenderer>;
/**
* Utility type that transforms InputSignal and EventEmitter types
*/
type TransformComponentType<T> = TransformInputSignalType<TransformEventType<T>>
type TransformComponentType<T> = TransformInputSignalType<TransformOutputSignalType<TransformEventType<T>>>

// @ts-ignore Angular < 17.2 doesn't export InputSignal
type AngularInputSignal<T> = AngularCore.InputSignal<T>
// @ts-ignore Angular < 17.2 doesn't export InputSignalWithTransform
type AngularInputSignalWithTransform<T, U> = AngularCore.InputSignalWithTransform<T, U>
// @ts-ignore Angular < 17.3 doesn't export AngularOutputEmitterRef
type AngularOutputEmitterRef<T> = AngularCore.OutputEmitterRef<T>

type AngularHasSignal = typeof AngularCore extends { input: infer U } ? true : false;
type InputSignal<T> = AngularHasSignal extends true ? AngularInputSignal<T> : never;
type InputSignalWithTransform<T, U> = AngularHasSignal extends true ? AngularInputSignalWithTransform<T, U> : never;
type AngularHasInputSignal = typeof AngularCore extends { input: infer U } ? true : false;
type AngularHasOutputSignal = typeof AngularCore extends { output: infer U } ? true : false;

type InputSignal<T> = AngularHasInputSignal extends true ? AngularInputSignal<T> : never;
type InputSignalWithTransform<T, U> = AngularHasInputSignal extends true ? AngularInputSignalWithTransform<T, U> : never;
type OutputEmitterRef<T> = AngularHasOutputSignal extends true ? AngularOutputEmitterRef<T> : never;

type TransformInputSignalType<T> = {
[K in keyof T]: T[K] extends InputSignal<infer E> ? E : T[K] extends InputSignalWithTransform<any, infer U> ? U : T[K];
};

type TransformOutputSignalType<T> = {
[K in keyof T]: T[K] extends OutputEmitterRef<infer E> ? (e: E) => void : T[K];
};

type TransformEventType<T> = {
[K in keyof T]: T[K] extends AngularCore.EventEmitter<infer E> ? (e: E) => void : T[K];
};
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Component, Input, Output, EventEmitter, input } from '@angular/core';
import { Component, Input, input, output } from '@angular/core';

@Component({
// Needs to be a different name to the CLI template button
Expand Down Expand Up @@ -40,8 +40,7 @@ export default class SignalButtonComponent {
/**
* Optional click handler
*/
@Output()
onClick = new EventEmitter<Event>();
onClick = output<Event>();

public get classes(): string[] {
const mode = this.primary() ? 'storybook-button--primary' : 'storybook-button--secondary';
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Component, Input, Output, EventEmitter, input } from '@angular/core';
import { Component, Input, input, output } from '@angular/core';

@Component({
// Needs to be a different name to the CLI template button
Expand Down Expand Up @@ -40,8 +40,7 @@ export default class SignalButtonComponent {
/**
* Optional click handler
*/
@Output()
onClick = new EventEmitter<Event>();
onClick = output<Event>();

public get classes(): string[] {
const mode = this.primary() ? 'storybook-button--primary' : 'storybook-button--secondary';
Expand Down

0 comments on commit 2eaf4a6

Please sign in to comment.