All files / src decorators.ts

100% Statements 25/25
100% Branches 6/6
100% Functions 10/10
100% Lines 22/22

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 534x                       4x 1x 1x       4x 7x 7x       4x   8x   66x 15x 15x 11x   15x 15x       66x           4x 4x 4x 4x   4x   4x  
import { StateController } from "./StateController";
 
 
interface EventClass {
    eventType:string;
}
 
interface IEventHandlerOptions { 
    /** set this option to false to not have `stopImmediatePropagation` from being called on the event */
    capture: boolean
}
 
export const windowEvent = (eventClass:EventClass, options?:IEventHandlerOptions) =>
    (controllerClass:StateController, propertyKey:string) => 
        eventDecorator("window", eventClass, controllerClass, propertyKey, options);
 
 
 
export const hostEvent = (eventClass:EventClass, options?:IEventHandlerOptions) =>
    (controllerClass:StateController, propertyKey:string) => 
        eventDecorator("host", eventClass, controllerClass, propertyKey, options);
 
 
 
const eventDecorator = (eventTarget:string, eventClass:EventClass,
    controllerClass:StateController, propertyKey:string, options?:IEventHandlerOptions) => {
        controllerClass.hostConnected = new Proxy(controllerClass.hostConnected, {
            apply: (hostConnected, thisArg:StateController, args) => {
                (eventTarget === "window" ? window : thisArg.host)
                    .addEventListener(eventClass.eventType, async (event:Event) => {
                        if (!options || !options.capture === false) {
                            event.stopImmediatePropagation();
                        }
                        thisArg.refreshState();
                        thisArg[propertyKey](event);
                }, {
                    signal: thisArg.abortController.signal
                } as EventListenerOptions);
                return hostConnected.apply(thisArg);
            }
        });
    };
 
 
export const stateProperty = () =>
    (target: StateController, propertyKey: string) => {
        const ctor = target.constructor as typeof StateController;
        if (ctor.stateProperties === StateController.stateProperties) {
            // shadow the static state properties field
            ctor.stateProperties = [];
        }
        ctor.stateProperties.push(propertyKey);
    };