function events(source, type, filter) {
    var view = this,
      s = new EventStream(filter),
      send = function (e, item) {
        view.runAsync(null, () => {
          if (source === VIEW$1 && prevent(view, type)) {
            e.preventDefault();
          }
          s.receive(eventExtend(view, e, item));
        });
      },
      sources;
    if (source === TIMER) {
      if (permit(view, 'timer', type)) {
        view.timer(send, type);
      }
    } else if (source === VIEW$1) {
      if (permit(view, 'view', type)) {
        // send traps errors, so use {trap: false} option
        view.addEventListener(type, send, NO_TRAP);
      }
    } else {
      if (source === WINDOW) {
        if (permit(view, 'window', type) && typeof window !== 'undefined') {
          sources = [window];
        }
      } else if (typeof document !== 'undefined') {
        if (permit(view, 'selector', type)) {
          sources = Array.from(document.querySelectorAll(source));
        }
      }
      if (!sources) {
        view.warn('Can not resolve event source: ' + source);
      } else {
        for (var i = 0, n = sources.length; i < n; ++i) {
          sources[i].addEventListener(type, send);
        }
        trackEventListener(view, sources, type, send);
      }
    }
    return s;
  }
Create a new event stream from an event source.
@param {object} source - The event source to monitor.
@param {string} type - The event type.
@param {function(object): boolean} [filter] - Event filter function.
@return {EventStream}