<commit_before>import { Objects } from '@ephox/boulder';

import * as EventRoot from '../../alien/EventRoot';
import * as EventHandler from '../../construct/EventHandler';
import * as AlloyTriggers from './AlloyTriggers';
import SystemEvents from './SystemEvents';
import { AlloyComponent } from 'ephox/alloy/api/component/ComponentApi';
import { SimulatedEvent } from 'ephox/alloy/events/SimulatedEvent';

export interface EventHandlerConfig {
  key: string;
  value: {
    can: () => boolean;
    abort: () => boolean;
    run: EventRunHandler
  };
}

export type EventRunHandler = (component: AlloyComponent, action: { [eventName: string]: () => any }) => any;

const derive = Objects.wrapAll;

const abort = function (name, predicate) {
  return {
    key: name,
    value: EventHandler.nu({
      abort: predicate
    })
  };
};

const can = function (name, predicate) {
  return {
    key: name,
    value: EventHandler.nu({
      can: predicate
    })
  };
};

const preventDefault = function (name: string): EventHandlerConfig {
  return {
    key: name,
    value: EventHandler.nu({
      run (component, simulatedEvent) {
        simulatedEvent.event().prevent();
      }
    })
  };
};

const run = function (name: string, handler: EventRunHandler): EventHandlerConfig {
  return {
    key: name,
    value: EventHandler.nu({
      run: handler
    })
  };
};

const runActionExtra = function (name, action, extra) {
  return {
    key: name,
    value: EventHandler.nu({
      run (component) {
        action.apply(undefined, [ component ].concat(extra));
      }
    })
  };
};

const runOnName = function (name) {
  return function (handler) {
    return run(name, handler);
  };
};

const runOnSourceName = function (name) {
  return function (handler) {
    return {
      key: name,
      value: EventHandler.nu({
        run (component, simulatedEvent) {
          if (EventRoot.isSource(component, simulatedEvent)) { handler(component, simulatedEvent); }
        }
      })
    };
  };
};

const redirectToUid = function (name, uid) {
  return run(name, function (component, simulatedEvent) {
    component.getSystem().getByUid(uid).each(function (redirectee) {
      AlloyTriggers.dispatchEvent(redirectee, redirectee.element(), name, simulatedEvent);
    });
  });
};

const redirectToPart = function (name, detail, partName) {
  const uid = detail.partUids()[partName];
  return redirectToUid(name, uid);
};

const runWithTarget = function (name, f) {
  return run(name, function (component, simulatedEvent) {
    component.getSystem().getByDom(simulatedEvent.event().target()).each(function (target) {
      f(component, target, simulatedEvent);
    });
  });
};

const cutter = function (name) {
  return run(name, function (component, simulatedEvent) {
    simulatedEvent.cut();
  });
};

const stopper = function (name) {
  return run(name, function (component, simulatedEvent) {
    simulatedEvent.stop();
  });
};

const runOnAttached = runOnSourceName(SystemEvents.attachedToDom());
const runOnDetached = runOnSourceName(SystemEvents.detachedFromDom());
const runOnInit = runOnSourceName(SystemEvents.systemInit());
const runOnExecute = runOnName(SystemEvents.execute());

export {
  derive,
  run,
  preventDefault,
  runActionExtra,
  runOnAttached,
  runOnDetached,
  runOnInit,
  runOnExecute,

  redirectToUid,
  redirectToPart,
  runWithTarget,
  abort,
  can,
  cutter,
  stopper
};<commit_msg>TINY-1547: AlloyEvents<commit_after>import { Objects } from '@ephox/boulder';

import * as EventRoot from '../../alien/EventRoot';
import * as EventHandler from '../../construct/EventHandler';
import * as AlloyTriggers from './AlloyTriggers';
import SystemEvents from './SystemEvents';
import { AlloyComponent } from 'ephox/alloy/api/component/ComponentApi';
import { SimulatedEvent } from 'ephox/alloy/events/SimulatedEvent';
import { SpecSchemaStruct } from 'ephox/alloy/spec/SpecSchema';

export interface EventHandlerConfig {
  key: string;
  value: {
    can: () => boolean;
    abort: () => boolean;
    run: EventRunHandler
  };
}

// TODO we can tighten this up alot further, it should take a simulatedEvent, however SimulatedEvent.event() can return 2 types, need to solve that issue first (SugarEvent or SimulatedEventTargets)
// export type EventRunHandler = (component: AlloyComponent, action: SimulatedEvent) => any;
export type EventRunHandler = (component: AlloyComponent, action: { [eventName: string]: () => any }) => any;
export type RunOnSourceName = (handler: EventRunHandler) => EventHandlerConfig;

const derive = Objects.wrapAll;

const abort = function (name, predicate) {
  return {
    key: name,
    value: EventHandler.nu({
      abort: predicate
    })
  };
};

const can = function (name, predicate) {
  return {
    key: name,
    value: EventHandler.nu({
      can: predicate
    })
  };
};

const preventDefault = function (name: string): EventHandlerConfig {
  return {
    key: name,
    value: EventHandler.nu({
      run (component, simulatedEvent) {
        simulatedEvent.event().prevent();
      }
    })
  };
};

const run = function (name: string, handler: EventRunHandler): EventHandlerConfig {
  return {
    key: name,
    value: EventHandler.nu({
      run: handler
    })
  };
};

const runActionExtra = function (name: string, action: (t: any, u: any) => void, extra: SpecSchemaStruct[]): EventHandlerConfig {
  return {
    key: name,
    value: EventHandler.nu({
      run (component) {
        action.apply(undefined, [ component ].concat(extra));
      }
    })
  };
};

const runOnName = function (name) {
  return function (handler) {
    return run(name, handler);
  };
};

const runOnSourceName = function (name) {
  return function (handler) {
    return {
      key: name,
      value: EventHandler.nu({
        run (component, simulatedEvent) {
          if (EventRoot.isSource(component, simulatedEvent)) { handler(component, simulatedEvent); }
        }
      })
    };
  };
};

const redirectToUid = function (name, uid) {
  return run(name, function (component, simulatedEvent) {
    component.getSystem().getByUid(uid).each(function (redirectee) {
      AlloyTriggers.dispatchEvent(redirectee, redirectee.element(), name, simulatedEvent);
    });
  });
};

const redirectToPart = function (name, detail, partName) {
  const uid = detail.partUids()[partName];
  return redirectToUid(name, uid);
};

const runWithTarget = function (name, f) {
  return run(name, function (component, simulatedEvent) {
    component.getSystem().getByDom(simulatedEvent.event().target()).each(function (target) {
      f(component, target, simulatedEvent);
    });
  });
};

const cutter = function (name) {
  return run(name, function (component, simulatedEvent) {
    simulatedEvent.cut();
  });
};

const stopper = function (name) {
  return run(name, function (component, simulatedEvent) {
    simulatedEvent.stop();
  });
};

const runOnAttached = runOnSourceName(SystemEvents.attachedToDom()) as RunOnSourceName;
const runOnDetached = runOnSourceName(SystemEvents.detachedFromDom()) as RunOnSourceName;
const runOnInit = runOnSourceName(SystemEvents.systemInit()) as RunOnSourceName;
const runOnExecute = runOnName(SystemEvents.execute()) as RunOnSourceName;

export {
  derive,
  run,
  preventDefault,
  runActionExtra,
  runOnAttached,
  runOnDetached,
  runOnInit,
  runOnExecute,

  redirectToUid,
  redirectToPart,
  runWithTarget,
  abort,
  can,
  cutter,
  stopper
};
{'fraction_non_alphanumeric': 0.13130364806866954, 'fraction_numerical': 0.0006706008583690987, 'mean_word_length': 3.7985842985842986, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 14, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5622329', 'n_tokens_mistral': 2289, 'n_tokens_neox': 2272, 'n_words': 557}