diff --git a/.babelrc b/.babelrc
new file mode 100644
index 0000000..e8025a0
--- /dev/null
+++ b/.babelrc
@@ -0,0 +1,4 @@
+{
+ "presets": ["stage-3", "es2015"],
+ "plugins": ["transform-flow-strip-types"]
+}
diff --git a/.eslintignore b/.eslintignore
new file mode 100644
index 0000000..9609d3b
--- /dev/null
+++ b/.eslintignore
@@ -0,0 +1,5 @@
+node_modules/**
+lib/**
+dist/**
+docs/**
+test/**
diff --git a/.eslintrc b/.eslintrc
new file mode 100644
index 0000000..ddf42b3
--- /dev/null
+++ b/.eslintrc
@@ -0,0 +1,33 @@
+{
+ "extends": ["airbnb-base", "plugin:flowtype/recommended"],
+ "env": {
+ "browser": true,
+ "node": true,
+ "mocha": true
+ },
+ "parserOptions": {
+ "ecmaVersion": 6,
+ "sourceType": "module",
+ "ecmaFeatures": {
+ "forOf": true,
+ "es6": true,
+ "experimentalObjectRestSpread" : true
+ },
+ },
+ "rules": {
+ "comma-dangle": 0,
+ "object-curly-spacing" : 0,
+ "arrow-body-style": 0,
+ "no-console": 0,
+ "max-len": 0,
+ "prefer-template": 0,
+ "import/no-unresolved": 0,
+ "global-require": 0,
+ "no-underscore-dangle": 0
+ },
+ "plugins": [
+ "flowtype"
+ ],
+ "globals": {
+ }
+}
diff --git a/.flowconfig b/.flowconfig
new file mode 100644
index 0000000..e69de29
diff --git a/CHANGELOG.md b/CHANGELOG.md
new file mode 100644
index 0000000..b0fefe5
--- /dev/null
+++ b/CHANGELOG.md
@@ -0,0 +1,7 @@
+# Changelog
+
+### In progress
+
+---
+
+### Releases
diff --git a/README.md b/README.md
index 204cb38..710afa9 100644
--- a/README.md
+++ b/README.md
@@ -1,2 +1,20 @@
-# triggerhappy
-Easily create native events for testing purposes
+# Triggerhappy
+
+> Easily create native events for testing purposes
+
+## Description
+**Note: This package is still in heavy development**
+
+Triggerhappy lets you create custom javascript events easily without all the boilerplate it usaully requires. Need to test touchevents or mousemove events inside your application, triggerhappy lets you do that. It also has a couple of helper function for creating custom animations between points an a lot more. Works well with karma and mocha. See the api for more information.
+
+## Usage
+
+> Comming soon
+
+## API
+
+> Comming soon
+
+## License
+
+[MIT](LICENSE). Copyright (c) 2017 Philip Knape.
diff --git a/docs/app.js b/docs/app.js
new file mode 100644
index 0000000..9e20dd7
--- /dev/null
+++ b/docs/app.js
@@ -0,0 +1,4 @@
+import prism from 'prismjs';
+import 'prismjs/themes/prism.css';
+
+import th from '../src/';
diff --git a/docs/assets/images/header-cta.svg b/docs/assets/images/header-cta.svg
new file mode 100644
index 0000000..59bdc6c
--- /dev/null
+++ b/docs/assets/images/header-cta.svg
@@ -0,0 +1,13 @@
+
+
+
diff --git a/docs/assets/images/icon-github.svg b/docs/assets/images/icon-github.svg
new file mode 100644
index 0000000..1cc2d54
--- /dev/null
+++ b/docs/assets/images/icon-github.svg
@@ -0,0 +1 @@
+
diff --git a/docs/assets/js/bundle.min.js b/docs/assets/js/bundle.min.js
new file mode 100644
index 0000000..bc2eef9
--- /dev/null
+++ b/docs/assets/js/bundle.min.js
@@ -0,0 +1,1478 @@
+/******/ (function(modules) { // webpackBootstrap
+/******/ // The module cache
+/******/ var installedModules = {};
+/******/
+/******/ // The require function
+/******/ function __webpack_require__(moduleId) {
+/******/
+/******/ // Check if module is in cache
+/******/ if(installedModules[moduleId])
+/******/ return installedModules[moduleId].exports;
+/******/
+/******/ // Create a new module (and put it into the cache)
+/******/ var module = installedModules[moduleId] = {
+/******/ i: moduleId,
+/******/ l: false,
+/******/ exports: {}
+/******/ };
+/******/
+/******/ // Execute the module function
+/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
+/******/
+/******/ // Flag the module as loaded
+/******/ module.l = true;
+/******/
+/******/ // Return the exports of the module
+/******/ return module.exports;
+/******/ }
+/******/
+/******/
+/******/ // expose the modules object (__webpack_modules__)
+/******/ __webpack_require__.m = modules;
+/******/
+/******/ // expose the module cache
+/******/ __webpack_require__.c = installedModules;
+/******/
+/******/ // identity function for calling harmony imports with the correct context
+/******/ __webpack_require__.i = function(value) { return value; };
+/******/
+/******/ // define getter function for harmony exports
+/******/ __webpack_require__.d = function(exports, name, getter) {
+/******/ if(!__webpack_require__.o(exports, name)) {
+/******/ Object.defineProperty(exports, name, {
+/******/ configurable: false,
+/******/ enumerable: true,
+/******/ get: getter
+/******/ });
+/******/ }
+/******/ };
+/******/
+/******/ // getDefaultExport function for compatibility with non-harmony modules
+/******/ __webpack_require__.n = function(module) {
+/******/ var getter = module && module.__esModule ?
+/******/ function getDefault() { return module['default']; } :
+/******/ function getModuleExports() { return module; };
+/******/ __webpack_require__.d(getter, 'a', getter);
+/******/ return getter;
+/******/ };
+/******/
+/******/ // Object.prototype.hasOwnProperty.call
+/******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };
+/******/
+/******/ // __webpack_public_path__
+/******/ __webpack_require__.p = "/js/";
+/******/
+/******/ // Load entry module and return exports
+/******/ return __webpack_require__(__webpack_require__.s = 9);
+/******/ })
+/************************************************************************/
+/******/ ([
+/* 0 */
+/***/ (function(module, exports, __webpack_require__) {
+
+"use strict";
+
+
+Object.defineProperty(exports, "__esModule", {
+ value: true
+});
+
+exports.default = function (target) {
+ return function (e) {
+ var newSpan = document.createElement('span');
+ var time = new Date();
+ time = time.getHours() + ':' + time.getMinutes() + ':' + time.getSeconds() + ',' + time.getMilliseconds();
+ var newContent = document.createTextNode('[' + time + '] Event dispatched: "' + e.type + '"');
+ newSpan.appendChild(newContent);
+ target.appendChild(newSpan);
+ };
+};
+
+/***/ }),
+/* 1 */
+/***/ (function(module, exports, __webpack_require__) {
+
+"use strict";
+
+
+Object.defineProperty(exports, "__esModule", {
+ value: true
+});
+
+var _panjs = __webpack_require__(4);
+
+var _panjs2 = _interopRequireDefault(_panjs);
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+exports.default = _panjs2.default;
+
+/***/ }),
+/* 2 */
+/***/ (function(module, exports, __webpack_require__) {
+
+/* WEBPACK VAR INJECTION */(function(global) {
+/* **********************************************
+ Begin prism-core.js
+********************************************** */
+
+var _self = (typeof window !== 'undefined')
+ ? window // if in browser
+ : (
+ (typeof WorkerGlobalScope !== 'undefined' && self instanceof WorkerGlobalScope)
+ ? self // if in worker
+ : {} // if in node js
+ );
+
+/**
+ * Prism: Lightweight, robust, elegant syntax highlighting
+ * MIT license http://www.opensource.org/licenses/mit-license.php/
+ * @author Lea Verou http://lea.verou.me
+ */
+
+var Prism = (function(){
+
+// Private helper vars
+var lang = /\blang(?:uage)?-(\w+)\b/i;
+var uniqueId = 0;
+
+var _ = _self.Prism = {
+ util: {
+ encode: function (tokens) {
+ if (tokens instanceof Token) {
+ return new Token(tokens.type, _.util.encode(tokens.content), tokens.alias);
+ } else if (_.util.type(tokens) === 'Array') {
+ return tokens.map(_.util.encode);
+ } else {
+ return tokens.replace(/&/g, '&').replace(/ text.length) {
+ // Something went terribly wrong, ABORT, ABORT!
+ break tokenloop;
+ }
+
+ if (str instanceof Token) {
+ continue;
+ }
+
+ pattern.lastIndex = 0;
+
+ var match = pattern.exec(str),
+ delNum = 1;
+
+ // Greedy patterns can override/remove up to two previously matched tokens
+ if (!match && greedy && i != strarr.length - 1) {
+ pattern.lastIndex = pos;
+ match = pattern.exec(text);
+ if (!match) {
+ break;
+ }
+
+ var from = match.index + (lookbehind ? match[1].length : 0),
+ to = match.index + match[0].length,
+ k = i,
+ p = pos;
+
+ for (var len = strarr.length; k < len && p < to; ++k) {
+ p += strarr[k].length;
+ // Move the index i to the element in strarr that is closest to from
+ if (from >= p) {
+ ++i;
+ pos = p;
+ }
+ }
+
+ /*
+ * If strarr[i] is a Token, then the match starts inside another Token, which is invalid
+ * If strarr[k - 1] is greedy we are in conflict with another greedy pattern
+ */
+ if (strarr[i] instanceof Token || strarr[k - 1].greedy) {
+ continue;
+ }
+
+ // Number of tokens to delete and replace with the new match
+ delNum = k - i;
+ str = text.slice(pos, p);
+ match.index -= pos;
+ }
+
+ if (!match) {
+ continue;
+ }
+
+ if(lookbehind) {
+ lookbehindLength = match[1].length;
+ }
+
+ var from = match.index + lookbehindLength,
+ match = match[0].slice(lookbehindLength),
+ to = from + match.length,
+ before = str.slice(0, from),
+ after = str.slice(to);
+
+ var args = [i, delNum];
+
+ if (before) {
+ args.push(before);
+ }
+
+ var wrapped = new Token(token, inside? _.tokenize(match, inside) : match, alias, match, greedy);
+
+ args.push(wrapped);
+
+ if (after) {
+ args.push(after);
+ }
+
+ Array.prototype.splice.apply(strarr, args);
+ }
+ }
+ }
+
+ return strarr;
+ },
+
+ hooks: {
+ all: {},
+
+ add: function (name, callback) {
+ var hooks = _.hooks.all;
+
+ hooks[name] = hooks[name] || [];
+
+ hooks[name].push(callback);
+ },
+
+ run: function (name, env) {
+ var callbacks = _.hooks.all[name];
+
+ if (!callbacks || !callbacks.length) {
+ return;
+ }
+
+ for (var i=0, callback; callback = callbacks[i++];) {
+ callback(env);
+ }
+ }
+ }
+};
+
+var Token = _.Token = function(type, content, alias, matchedStr, greedy) {
+ this.type = type;
+ this.content = content;
+ this.alias = alias;
+ // Copy of the full string this token was created from
+ this.length = (matchedStr || "").length|0;
+ this.greedy = !!greedy;
+};
+
+Token.stringify = function(o, language, parent) {
+ if (typeof o == 'string') {
+ return o;
+ }
+
+ if (_.util.type(o) === 'Array') {
+ return o.map(function(element) {
+ return Token.stringify(element, language, o);
+ }).join('');
+ }
+
+ var env = {
+ type: o.type,
+ content: Token.stringify(o.content, language, parent),
+ tag: 'span',
+ classes: ['token', o.type],
+ attributes: {},
+ language: language,
+ parent: parent
+ };
+
+ if (env.type == 'comment') {
+ env.attributes['spellcheck'] = 'true';
+ }
+
+ if (o.alias) {
+ var aliases = _.util.type(o.alias) === 'Array' ? o.alias : [o.alias];
+ Array.prototype.push.apply(env.classes, aliases);
+ }
+
+ _.hooks.run('wrap', env);
+
+ var attributes = Object.keys(env.attributes).map(function(name) {
+ return name + '="' + (env.attributes[name] || '').replace(/"/g, '"') + '"';
+ }).join(' ');
+
+ return '<' + env.tag + ' class="' + env.classes.join(' ') + '"' + (attributes ? ' ' + attributes : '') + '>' + env.content + '' + env.tag + '>';
+
+};
+
+if (!_self.document) {
+ if (!_self.addEventListener) {
+ // in Node.js
+ return _self.Prism;
+ }
+ // In worker
+ _self.addEventListener('message', function(evt) {
+ var message = JSON.parse(evt.data),
+ lang = message.language,
+ code = message.code,
+ immediateClose = message.immediateClose;
+
+ _self.postMessage(_.highlight(code, _.languages[lang], lang));
+ if (immediateClose) {
+ _self.close();
+ }
+ }, false);
+
+ return _self.Prism;
+}
+
+//Get current script and highlight
+var script = document.currentScript || [].slice.call(document.getElementsByTagName("script")).pop();
+
+if (script) {
+ _.filename = script.src;
+
+ if (document.addEventListener && !script.hasAttribute('data-manual')) {
+ if(document.readyState !== "loading") {
+ if (window.requestAnimationFrame) {
+ window.requestAnimationFrame(_.highlightAll);
+ } else {
+ window.setTimeout(_.highlightAll, 16);
+ }
+ }
+ else {
+ document.addEventListener('DOMContentLoaded', _.highlightAll);
+ }
+ }
+}
+
+return _self.Prism;
+
+})();
+
+if (typeof module !== 'undefined' && module.exports) {
+ module.exports = Prism;
+}
+
+// hack for components to work correctly in node.js
+if (typeof global !== 'undefined') {
+ global.Prism = Prism;
+}
+
+
+/* **********************************************
+ Begin prism-markup.js
+********************************************** */
+
+Prism.languages.markup = {
+ 'comment': //,
+ 'prolog': /<\?[\w\W]+?\?>/,
+ 'doctype': //i,
+ 'cdata': //i,
+ 'tag': {
+ pattern: /<\/?(?!\d)[^\s>\/=$<]+(?:\s+[^\s>\/=]+(?:=(?:("|')(?:\\\1|\\?(?!\1)[\w\W])*\1|[^\s'">=]+))?)*\s*\/?>/i,
+ inside: {
+ 'tag': {
+ pattern: /^<\/?[^\s>\/]+/i,
+ inside: {
+ 'punctuation': /^<\/?/,
+ 'namespace': /^[^\s>\/:]+:/
+ }
+ },
+ 'attr-value': {
+ pattern: /=(?:('|")[\w\W]*?(\1)|[^\s>]+)/i,
+ inside: {
+ 'punctuation': /[=>"']/
+ }
+ },
+ 'punctuation': /\/?>/,
+ 'attr-name': {
+ pattern: /[^\s>\/]+/,
+ inside: {
+ 'namespace': /^[^\s>\/:]+:/
+ }
+ }
+
+ }
+ },
+ 'entity': /?[\da-z]{1,8};/i
+};
+
+// Plugin to make entity title show the real entity, idea by Roman Komarov
+Prism.hooks.add('wrap', function(env) {
+
+ if (env.type === 'entity') {
+ env.attributes['title'] = env.content.replace(/&/, '&');
+ }
+});
+
+Prism.languages.xml = Prism.languages.markup;
+Prism.languages.html = Prism.languages.markup;
+Prism.languages.mathml = Prism.languages.markup;
+Prism.languages.svg = Prism.languages.markup;
+
+
+/* **********************************************
+ Begin prism-css.js
+********************************************** */
+
+Prism.languages.css = {
+ 'comment': /\/\*[\w\W]*?\*\//,
+ 'atrule': {
+ pattern: /@[\w-]+?.*?(;|(?=\s*\{))/i,
+ inside: {
+ 'rule': /@[\w-]+/
+ // See rest below
+ }
+ },
+ 'url': /url\((?:(["'])(\\(?:\r\n|[\w\W])|(?!\1)[^\\\r\n])*\1|.*?)\)/i,
+ 'selector': /[^\{\}\s][^\{\};]*?(?=\s*\{)/,
+ 'string': {
+ pattern: /("|')(\\(?:\r\n|[\w\W])|(?!\1)[^\\\r\n])*\1/,
+ greedy: true
+ },
+ 'property': /(\b|\B)[\w-]+(?=\s*:)/i,
+ 'important': /\B!important\b/i,
+ 'function': /[-a-z0-9]+(?=\()/i,
+ 'punctuation': /[(){};:]/
+};
+
+Prism.languages.css['atrule'].inside.rest = Prism.util.clone(Prism.languages.css);
+
+if (Prism.languages.markup) {
+ Prism.languages.insertBefore('markup', 'tag', {
+ 'style': {
+ pattern: /(
+
+