import { IComponent } from '../module/component'; import { Signal, WritableSignal } from './signals'; const INPUT_SIGNAL = Symbol('inputSignal'); export interface InputSignal extends Signal { [INPUT_SIGNAL]: true; } export interface InputOptions { alias?: string; transform?: (value: TransformT) => T; } interface InputFunction { (): InputSignal; (propertyName: string, component: IComponent): InputSignal; (propertyName: string, component: IComponent, initialValue: T, options?: InputOptions): InputSignal; (propertyName: string, component: IComponent, initialValue: T, options: InputOptions): InputSignal; required: InputRequiredFunction; } interface InputRequiredFunction { (): InputSignal; (propertyName: string, component: IComponent, options?: InputOptions): InputSignal; (propertyName: string, component: IComponent, options: InputOptions): InputSignal; } function createInputSignal( propertyName: string, component: IComponent, initialValue: T, options?: InputOptions, ): InputSignal { let currentValue = initialValue; const alias = options?.alias ?? propertyName; const transform = options?.transform; const getter = (() => { const element = component._nativeElement; const inputSignal = element?.__inputs?.[alias]; if (inputSignal) { const rawValue = inputSignal(); currentValue = transform ? transform(rawValue) : rawValue; } else if (element) { const attrValue = element.getAttribute(alias); if (attrValue !== null) { currentValue = transform ? transform(attrValue as any) : attrValue as any; } } return currentValue; }) as InputSignal; (getter as any)[INPUT_SIGNAL] = true; return getter; } function inputFn( propertyNameOrInitialValue?: string | T, componentOrOptions?: IComponent | InputOptions, initialValue?: T, options?: InputOptions, ): InputSignal { if (typeof propertyNameOrInitialValue === 'string' && componentOrOptions && '_nativeElement' in (componentOrOptions as any)) { return createInputSignal( propertyNameOrInitialValue, componentOrOptions as IComponent, initialValue as T, options, ); } return createInputSignal('', {} as IComponent, propertyNameOrInitialValue as T, componentOrOptions as InputOptions); } function inputRequired( propertyNameOrOptions?: string | InputOptions, componentOrOptions?: IComponent | InputOptions, options?: InputOptions, ): InputSignal { if (typeof propertyNameOrOptions === 'string' && componentOrOptions && '_nativeElement' in (componentOrOptions as any)) { return createInputSignal( propertyNameOrOptions, componentOrOptions as IComponent, undefined as T, options, ); } return createInputSignal('', {} as IComponent, undefined as T, propertyNameOrOptions as InputOptions); } (inputFn as InputFunction).required = inputRequired as InputRequiredFunction; export const input: InputFunction = inputFn as InputFunction; export function createInput( propertyName: string, component: IComponent, initialValue?: T, options?: InputOptions, ): InputSignal { return createInputSignal(propertyName, component, initialValue as T, options); } export function createRequiredInput( propertyName: string, component: IComponent, options?: InputOptions, ): InputSignal { return createInputSignal(propertyName, component, undefined as T, options); } /** * Dekorator Input. * * Ten dekorator służy wyłącznie do zapewnienia poprawności typów w TypeScript * i jest podmieniany podczas kompilacji przez transformery. */ export function Input(bindingPropertyName?: string): PropertyDecorator { return (target: Object, propertyKey: string | symbol) => { }; }