quarc/core/angular/output.ts

83 lines
2.3 KiB
TypeScript

import { IComponent } from '../module/component';
const OUTPUT_EMITTER = Symbol('outputEmitter');
export interface OutputEmitterRef<T> {
emit(value: T): void;
[OUTPUT_EMITTER]: true;
}
export interface OutputOptions {
alias?: string;
}
interface OutputFunction {
<T = void>(): OutputEmitterRef<T>;
<T = void>(propertyName: string, component: IComponent, options?: OutputOptions): OutputEmitterRef<T>;
}
function createOutputEmitter<T>(
propertyName: string,
component: IComponent,
options?: OutputOptions,
): OutputEmitterRef<T> {
const alias = options?.alias ?? propertyName;
const emitter: OutputEmitterRef<T> = {
alias,
component,
options,
emit: (value: T) => {
const element = component._nativeElement;
if (element) {
const event = new CustomEvent(alias, {
detail: value,
bubbles: true,
cancelable: true,
});
element.dispatchEvent(event);
}
},
[OUTPUT_EMITTER]: true as const,
};
return emitter;
}
function outputFn<T = void>(
propertyNameOrOptions?: string | OutputOptions,
componentOrOptions?: IComponent | OutputOptions,
options?: OutputOptions,
): OutputEmitterRef<T> {
if (typeof propertyNameOrOptions === 'string' && componentOrOptions && '_nativeElement' in (componentOrOptions as any)) {
return createOutputEmitter<T>(
propertyNameOrOptions,
componentOrOptions as IComponent,
options,
);
}
return createOutputEmitter<T>('', {} as IComponent, propertyNameOrOptions as OutputOptions);
}
export const output: OutputFunction = outputFn;
export function createOutput<T = void>(
propertyName: string,
component: IComponent,
options?: OutputOptions,
): OutputEmitterRef<T> {
return createOutputEmitter<T>(propertyName, component, options);
}
/**
* Dekorator Output.
*
* Ten dekorator służy wyłącznie do zapewnienia poprawności typów w TypeScript
* i jest podmieniany podczas kompilacji przez transformery.
*/
export function Output(bindingPropertyName?: string): PropertyDecorator {
return (target: Object, propertyKey: string | symbol) => {
};
}