rasti 1.1.1 → 2.0.0-alpha.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,398 @@
1
+ function _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return self; }
2
+ function _inheritsLoose(subClass, superClass) { subClass.prototype = Object.create(superClass.prototype); subClass.prototype.constructor = subClass; _setPrototypeOf(subClass, superClass); }
3
+ function _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); }
4
+ import View from './View';
5
+
6
+ // This options keys will be extended on view instance.
7
+ var componentOptions = {
8
+ key: true,
9
+ state: true,
10
+ onCreate: true,
11
+ onChange: true,
12
+ onRender: true
13
+ };
14
+
15
+ /*
16
+ * Helper function. Extract attributes from html tag
17
+ * @param text {string} html text
18
+ * @return {object} Object with keys / values representing attributes.
19
+ */
20
+ var getAttributes = function getAttributes(text) {
21
+ var attributes = {};
22
+ var re = /([a-z]+)=?(\S+)?/gi;
23
+ var result;
24
+ while ((result = re.exec(text)) !== null) {
25
+ attributes[result[1]] = result[2] ? result[2].replace(/'|"/g, '') : true;
26
+ }
27
+ return attributes;
28
+ };
29
+
30
+ /*
31
+ * Helper function. If expression is a function, call it with context and args.
32
+ */
33
+ var evalExpression = function evalExpression(expression, context) {
34
+ for (var _len = arguments.length, args = new Array(_len > 2 ? _len - 2 : 0), _key = 2; _key < _len; _key++) {
35
+ args[_key - 2] = arguments[_key];
36
+ }
37
+ return typeof expression === 'function' ? expression.apply(context, args) : expression;
38
+ };
39
+
40
+ /**
41
+ * Components are a special kind of `View` that is designed to be easily composable,
42
+ * making it simple to add child views and build complex user interfaces.<br />
43
+ * Unlike views, which are render-agnostic, components have a specific set of rendering
44
+ * guidelines that allow for a more declarative development style.
45
+ * @module
46
+ * @param {object} options Object containing options. The following keys will be merged to `this`: model, state, key, onDestroy, onRender, onCreate, onChange.
47
+ * @example
48
+ * import { Component, Model } from 'rasti';
49
+ * // Create Timer component.
50
+ * const Timer = Component.create`
51
+ * <div>Seconds: <span>${({ model }) => model.seconds}</span></div>
52
+ * `;
53
+ * // Create model to store seconds.
54
+ * const model = new Model({ seconds: 0 });
55
+ * // Mount timer on body.
56
+ * Timer.mount({ model }, document.body);
57
+ * // Increment `model.seconds` every second.
58
+ * setInterval(() => model.seconds++, 1000);
59
+ */
60
+ var Component = /*#__PURE__*/function (_View) {
61
+ _inheritsLoose(Component, _View);
62
+ function Component() {
63
+ var _this;
64
+ var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
65
+ _this = _View.call(this, options) || this;
66
+ // Extend "this" with options, mapping componentOptions keys.
67
+ Object.keys(options).forEach(function (key) {
68
+ if (componentOptions[key]) _this[key] = options[key];
69
+ });
70
+ // Store options by default.
71
+ _this.options = options;
72
+ // Ensure id.
73
+ _this.id = _this.attributes.id ?
74
+ // If id is provided, evaluate it.
75
+ evalExpression(_this.attributes.id, _assertThisInitialized(_this), _assertThisInitialized(_this)) : // Generate a unique id and set it as id attribute.
76
+ "rasti-component-" + _this.uid;
77
+ // Bind onChange to this to be used as listener.
78
+ // Store bound version, so it can be removed on onDestroy method.
79
+ _this.onChange = _this.onChange.bind(_assertThisInitialized(_this));
80
+ // Listen to model changes and call onChange.
81
+ if (_this.model) _this.model.on('change', _this.onChange);
82
+ if (_this.state) _this.state.on('change', _this.onChange);
83
+ // Call life cycle method.
84
+ _this.onCreate.apply(_assertThisInitialized(_this), arguments);
85
+ return _this;
86
+ }
87
+
88
+ /*
89
+ * Override. We don't want to ensure an element on instantiation.
90
+ * We will provide it later.
91
+ */
92
+ var _proto = Component.prototype;
93
+ _proto.ensureElement = function ensureElement() {
94
+ // If el is provided, delegate events.
95
+ if (this.el) this.delegateEvents();
96
+ };
97
+ _proto.findElement = function findElement(parent) {
98
+ return (parent || document).querySelector("#" + this.id);
99
+ }
100
+
101
+ /*
102
+ * Used internally on the render process. Attach the view to the dom element.
103
+ */;
104
+ _proto.hydrate = function hydrate(parent) {
105
+ var _this2 = this;
106
+ this.el = this.findElement(parent);
107
+ this.delegateEvents();
108
+ this.children.forEach(function (child) {
109
+ return child.hydrate(_this2.el);
110
+ });
111
+ this.onRender.call(this);
112
+ }
113
+
114
+ /*
115
+ * Override. Add some custom logic to super `destroy` method.
116
+ */;
117
+ _proto.destroy = function destroy(options) {
118
+ _View.prototype.destroy.call(this, options);
119
+ // Stop listening to `change`.
120
+ // Set destroyed flag to prevent a last render after destroyed. TODO: Review
121
+ if (this.model) this.model.off('change', this.onChange);
122
+ if (this.state) this.state.off('change', this.onChange);
123
+ this.destroyed = true;
124
+ }
125
+
126
+ /**
127
+ * Lifecycle method. Called when the view is created at the end of the constructor.
128
+ * @param options {object} The view options.
129
+ */;
130
+ _proto.onCreate = function onCreate() {}
131
+
132
+ /**
133
+ * Lifecycle method. Called when model emits `change` event.
134
+ * By default calls render method.
135
+ * This method should be extended with custom logic.
136
+ * Maybe comparing new attributes with previous ones and calling
137
+ * render when needed. Or doing some dom transformation.
138
+ * @param model {Rasti.Model}
139
+ * @param key {string}
140
+ * @param value {any}
141
+ */;
142
+ _proto.onChange = function onChange() {
143
+ this.render();
144
+ }
145
+
146
+ /**
147
+ * Lifecycle method. Called when the view is rendered.
148
+ */;
149
+ _proto.onRender = function onRender() {}
150
+
151
+ /**
152
+ * Lifecycle method. Called when the view is destroyed.
153
+ */;
154
+ _proto.onDestroy = function onDestroy() {}
155
+
156
+ /*
157
+ * Replace expressions.
158
+ */;
159
+ _proto.replaceExpressions = function replaceExpressions(string, parseExpressionResult) {
160
+ var _this3 = this;
161
+ return string.replace(/{(\d+)}/g, function (match) {
162
+ // Get expression index.
163
+ var idx = match.match(/{(\d+)}/)[1];
164
+ // Eval expression. Pass view as argument.
165
+ var result = _this3.template.expressions[idx].call(_this3, _this3);
166
+ // Treat all expressions as arrays.
167
+ var results = result instanceof Array ? result : [result];
168
+ // Replace expression with the result of the evaluation.
169
+ return results.reduce(function (out, current) {
170
+ // Concatenate expressions.
171
+ out += parseExpressionResult(current);
172
+ return out;
173
+ }, '');
174
+ })
175
+ // Replace `attribute="true"` with `attribute`
176
+ .replace(/([a-z]+)=["|']true["|']/g, '$1')
177
+ // Replace `attribute="false"` with ``
178
+ .replace(/([a-z]+)=["|']false["|']/g, '');
179
+ }
180
+
181
+ /*
182
+ * Treat the whole view as a HTML string.
183
+ */;
184
+ _proto.toString = function toString() {
185
+ var _this4 = this;
186
+ // Normally there won't be any children, but if there are, destroy them.
187
+ this.destroyChildren();
188
+ // Add id to template including root element (this.el) as part of it.
189
+ var tpl = this.attributes.id ? this.template.outer : this.template.outer.replace(/^<([a-z]+)/, "<$1 id=\"" + this.id + "\"");
190
+ // Replace expressions.
191
+ return this.replaceExpressions(tpl, function (result) {
192
+ var out = result;
193
+ // Return empty string if result is null or undefined.
194
+ if (result === null || typeof result === 'undefined') out = '';
195
+ // If result is a view, add it to children array.
196
+ else if (result && typeof result.render === 'function') {
197
+ // Add child component.
198
+ _this4.addChild(result);
199
+ }
200
+ return out;
201
+ });
202
+ }
203
+
204
+ /*
205
+ * View render method.
206
+ */;
207
+ _proto.render = function render() {
208
+ var _this5 = this;
209
+ // Prevent a last re render if view is already destroyed.
210
+ if (this.destroyed) return this;
211
+ // If "this.el" is not present,
212
+ // create a new element according "this.tag"
213
+ // and "this.attributes".
214
+ if (!this.el) {
215
+ this.el = this.createElement(this.tag);
216
+ this.delegateEvents();
217
+ }
218
+ // Set `this.el` attributes.
219
+ Object.keys(this.attributes).forEach(function (key) {
220
+ // Omit changing id.
221
+ if (key === 'id') return;
222
+ // Evaluate attribute value.
223
+ var value = evalExpression(_this5.attributes[key], _this5, _this5);
224
+ // Transform bool attribute values
225
+ if (value === false) {
226
+ // Remove false attributes.
227
+ _this5.el.removeAttribute(key);
228
+ } else {
229
+ if (value === true) value = '';
230
+ _this5.el.setAttribute(key, value);
231
+ }
232
+ });
233
+ var previousChildren = this.children;
234
+ this.children = [];
235
+ var nextChildren = [];
236
+ var recycledChildren = [];
237
+
238
+ // Replace expressions.
239
+ // Set html text inside `this.el`. Make it part of the dom.
240
+ this.el.innerHTML = this.replaceExpressions(this.template.inner, function (result) {
241
+ var out = result;
242
+ // Return empty string if result is null or undefined.
243
+ if (result === null || typeof result === 'undefined') out = '';
244
+
245
+ // If result is a view, add it to children array.
246
+ else if (result && typeof result.render === 'function') {
247
+ var found = result.key && previousChildren.find(function (previousChild) {
248
+ return previousChild.key === result.key;
249
+ });
250
+ if (found) {
251
+ out = "<" + found.tag + " id=\"" + evalExpression(found.id, found, found) + "\"></" + found.tag + ">";
252
+ recycledChildren.push(found);
253
+ result.destroy();
254
+ } else {
255
+ nextChildren.push(result);
256
+ }
257
+ }
258
+ return out;
259
+ });
260
+ nextChildren.forEach(function (nextChild) {
261
+ _this5.addChild(nextChild).hydrate(_this5.el);
262
+ });
263
+ recycledChildren.forEach(function (recycledChild) {
264
+ _this5.el.replaceChild(_this5.addChild(recycledChild).el, recycledChild.findElement(_this5.el));
265
+ });
266
+ previousChildren.forEach(function (previousChild) {
267
+ var found = recycledChildren.indexOf(previousChild) > -1;
268
+ if (!found) previousChild.destroy();
269
+ });
270
+
271
+ // Call onRender lifecycle method.
272
+ this.onRender.call(this);
273
+ // Return this for chaining.
274
+ return this;
275
+ }
276
+
277
+ /**
278
+ * Helper method used to extend a `Component`, creating a subclass.
279
+ * @static
280
+ * @param {object} object Object containing methods to be added to the new `Component` subclass. Also can be a function that receives the parent prototype and returns an object.
281
+ */;
282
+ Component.extend = function extend(object) {
283
+ var Current = this;
284
+ var Extended = /*#__PURE__*/function (_Current) {
285
+ _inheritsLoose(Extended, _Current);
286
+ function Extended() {
287
+ return _Current.apply(this, arguments) || this;
288
+ }
289
+ return Extended;
290
+ }(Current);
291
+ Object.assign(Extended.prototype, typeof object === 'function' ? object(Current.prototype) : object);
292
+ return Extended;
293
+ }
294
+
295
+ /**
296
+ * Mount the component into the dom.
297
+ * It instantiate the Component view using options,
298
+ * appends its element into the DOM (if `el` is provided).
299
+ * And returns the view instance.
300
+ * @static
301
+ * @param {object} options The view options.
302
+ * @param {node} el Dom element to append the view element.
303
+ * @param {boolean} hydrate If true, the view will use existing html.
304
+ * @return {Rasti.View}
305
+ */;
306
+ Component.mount = function mount() {
307
+ var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
308
+ var el = arguments.length > 1 ? arguments[1] : undefined;
309
+ var hydrate = arguments.length > 2 ? arguments[2] : undefined;
310
+ // Instantiate view.
311
+ var view = new this(options);
312
+
313
+ // If `el` is passed, mount component.
314
+ if (el) {
315
+ if (hydrate) {
316
+ view.toString();
317
+ } else {
318
+ var fragment = document.createElement('template');
319
+ // Add html text into element inner html.
320
+ fragment.innerHTML = view;
321
+ // Add to dom.
322
+ el.appendChild(fragment.content);
323
+ }
324
+ view.hydrate(el);
325
+ }
326
+ return view;
327
+ }
328
+ /**
329
+ * Tagged template that receives an HTML string,
330
+ * and returns a `Component`.
331
+ * @static
332
+ */;
333
+ Component.create = function create(strings) {
334
+ for (var _len2 = arguments.length, expressions = new Array(_len2 > 1 ? _len2 - 1 : 0), _key2 = 1; _key2 < _len2; _key2++) {
335
+ expressions[_key2 - 1] = arguments[_key2];
336
+ }
337
+ var parts = [];
338
+ // Replace functions and objects interpolations with `{number}`.
339
+ // Where `number` is the index on expressions array.
340
+ strings.forEach(function (string, i) {
341
+ // Add string part.
342
+ parts.push(string);
343
+ // Add expression placeholder for later or expression eval.
344
+ if (expressions[i]) {
345
+ parts.push(typeof expressions[i] === 'function' || typeof expressions[i] === 'object' ? "{" + i + "}" : expressions[i]);
346
+ }
347
+ });
348
+ // Create output text for main template.
349
+ var main = parts.join('').trim().replace(/\n/g, '');
350
+ // Extract outer tag, attributes and inner html.
351
+ var result = main.match(/^<([a-z]+)(.*?)>(.*)<\/\1>$/);
352
+ // Remove events listeners.
353
+ var string = main.replace(/on([A-Z]{1}[a-z]+)+=[^>\s]+/g, '');
354
+ // Parse attributes from html text into an object.
355
+ var attributes = getAttributes(result[2]);
356
+ var events = {};
357
+ // Filter events. Replace placeholders `{number}` with expressions.
358
+ attributes = Object.keys(attributes).reduce(function (out, key) {
359
+ var matchKey = key.match(/on(([A-Z]{1}[a-z]+)+)/); // Is Event?
360
+ var matchValue = attributes[key].match(/{(\d+)}/); // Is placeholder for function or object?
361
+ // Get expression or value.
362
+ var value = matchValue && matchValue[1] ? expressions[matchValue[1]] : attributes[key];
363
+ // Is event handler.
364
+ if (matchKey && matchKey[1]) {
365
+ var eventType = matchKey[1].toLowerCase();
366
+ Object.keys(value).forEach(function (selector) {
367
+ return events["" + eventType + (selector === '&' ? '' : " " + selector)] = value[selector];
368
+ });
369
+ return out;
370
+ }
371
+ // Is function expression.
372
+ out[key] = value;
373
+ return out;
374
+ }, {});
375
+ var Current = this;
376
+
377
+ // Create subclass for this component.
378
+ return Current.extend({
379
+ // Set events.
380
+ events: events,
381
+ // Set attributes.
382
+ attributes: attributes,
383
+ // Set template data.
384
+ template: {
385
+ // Template including root element (this.el) as part of the template.
386
+ outer: string,
387
+ // Template for innerHTML of root element.
388
+ inner: result[3],
389
+ // Template expressions.
390
+ expressions: expressions
391
+ },
392
+ // Set root element tag.
393
+ tag: result[1]
394
+ });
395
+ };
396
+ return Component;
397
+ }(View);
398
+ export { Component as default };
package/es/Emitter.js CHANGED
@@ -1,127 +1,124 @@
1
- function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
2
-
3
1
  /**
4
- * Emitter is a class that can be extended giving the subclass the ability to emit
5
- * and bind custom named events. Model and View inherits from it.
2
+ * `Emitter` is a class that provides an easy way to implement the observer pattern
3
+ * in your applications.<br />
4
+ * It can be extended to create new classes that have the ability to emit and bind custom named events.<br />
5
+ * Emitter is used by `Model` and `View` classes, which inherit from it to implement
6
+ * event-driven functionality.
7
+ *
6
8
  * @module
7
9
  * @example
8
10
  * import { Emitter } from 'rasti';
9
- * // Define App class, inherits from Emitter.
10
- * class App extends Emitter {
11
+ * // Custom cart
12
+ * class ShoppingCart extends Emitter {
11
13
  * constructor() {
12
- * super()
13
- * // Fetch data and emit `ready` event.
14
- * fetch('/api/init').then(() => this.emit('ready'));
14
+ * super();
15
+ * this.items = [];
16
+ * }
17
+ *
18
+ * addItem(item) {
19
+ * this.items.push(item);
20
+ * // Emit a custom event called `itemAdded`.
21
+ * // Pass the added item as an argument to the event listener.
22
+ * this.emit('itemAdded', item);
15
23
  * }
16
24
  * }
17
- * // Instantiate App.
18
- * const app = new App();
19
- * // Add event listener to ready event.
20
- * app.on('ready', () => console.log('app is ready!'));
25
+ * // Create an instance of ShoppingCart and Logger
26
+ * const cart = new ShoppingCart();
27
+ * // Listen to the `itemAdded` event and log the added item using the logger.
28
+ * cart.on('itemAdded', (item) => {
29
+ * console.log(`Item added to cart: ${item.name} - Price: $${item.price}`);
30
+ * });
31
+ * // Simulate adding items to the cart
32
+ * const item1 = { name : 'Smartphone', price : 1000 };
33
+ * const item2 = { name : 'Headphones', price : 150 };
34
+ *
35
+ * cart.addItem(item1); // Output: "Item added to cart: Smartphone - Price: $1000"
36
+ * cart.addItem(item2); // Output: "Item added to cart: Headphones - Price: $150"
21
37
  */
22
- var Emitter = function () {
23
- function Emitter() {
24
- _classCallCheck(this, Emitter);
38
+ var Emitter = /*#__PURE__*/function () {
39
+ function Emitter() {}
40
+ var _proto = Emitter.prototype;
41
+ /**
42
+ * Adds event listener.
43
+ * @param {string} type Type of the event (e.g. `change`).
44
+ * @param {function} listener Callback function to be called when the event is emitted.
45
+ * @example
46
+ * this.model.on('change', this.render.bind(this)); // Re render when model changes.
47
+ */
48
+ _proto.on = function on(type, listener) {
49
+ if (typeof listener !== 'function') {
50
+ throw TypeError('Listener must be a function');
25
51
  }
26
-
27
- /**
28
- * Adds event listener.
29
- * @param {string} type Type of the event (e.g. `change`).
30
- * @param {function} listener Callback function to be called when the event is emitted.
31
- * @example
32
- * this.model.on('change', this.render.bind(this)); // Re render when model changes.
33
- */
34
- Emitter.prototype.on = function on(type, listener) {
35
- if (typeof listener !== 'function') {
36
- throw TypeError('Listener must be a function');
37
- }
38
-
39
- if (!this.listeners) this.listeners = {};
40
- if (!this.listeners[type]) this.listeners[type] = [];
41
-
42
- this.listeners[type].push(listener);
43
- };
44
-
45
- /**
46
- * Adds event listener that executes once.
47
- * @param {string} type Type of the event (e.g. `change`).
48
- * @param {function} listener Callback function to be called when the event is emitted.
49
- * @example
50
- * this.model.once('change', () => console.log('This will happen once'));
51
- */
52
-
53
-
54
- Emitter.prototype.once = function once(type, _listener2) {
55
- if (typeof _listener2 === 'function') {
56
- var self = this;
57
- var _listener = _listener2;
58
-
59
- _listener2 = function listener() {
60
- _listener.apply(undefined, arguments);
61
- self.off(type, _listener2);
62
- };
63
- }
64
- this.on(type, _listener2);
65
- };
66
-
67
- /**
68
- * Removes event listeners.
69
- * @param {string} [type] Type of the event (e.g. `change`). If is not provided, it removes all listeners.
70
- * @param {function} [listener] Callback function to be called when the event is emitted. If listener is not provided, it removes all listeners for specified type.
71
- * @example
72
- * this.model.off('change'); // Stop listening to changes.
73
- */
74
-
75
-
76
- Emitter.prototype.off = function off(type, listener) {
77
- if (!type) {
78
- this.listeners = {};
79
- } else {
80
- if (!listener) {
81
- delete this.listeners[type];
82
- } else {
83
- var listeners = this.listeners[type];
84
- if (listeners) {
85
- var copy = listeners.slice();
86
-
87
- copy.forEach(function (fn, idx) {
88
- if (fn === listener) listeners.splice(idx, 1);
89
- });
90
-
91
- if (!listeners.length) {
92
- delete this.listeners[type];
93
- }
94
- }
95
- }
96
- }
97
- };
98
-
99
- /**
100
- * Emits event of specified type. Listeners will receive specified arguments.
101
- * @param {string} type Type of the event (e.g. `change`).
102
- * @param {any} [...args] Arguments to be passed to listener.
103
- * @example
104
- * this.emit('invalid'); // Emit validation error event.
105
- */
106
-
107
-
108
- Emitter.prototype.emit = function emit(type) {
109
- for (var _len = arguments.length, args = Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
110
- args[_key - 1] = arguments[_key];
52
+ if (!this.listeners) this.listeners = {};
53
+ if (!this.listeners[type]) this.listeners[type] = [];
54
+ this.listeners[type].push(listener);
55
+ }
56
+
57
+ /**
58
+ * Adds event listener that executes once.
59
+ * @param {string} type Type of the event (e.g. `change`).
60
+ * @param {function} listener Callback function to be called when the event is emitted.
61
+ * @example
62
+ * this.model.once('change', () => console.log('This will happen once'));
63
+ */;
64
+ _proto.once = function once(type, _listener2) {
65
+ if (typeof _listener2 === 'function') {
66
+ var self = this;
67
+ var _listener = _listener2;
68
+ _listener2 = function listener() {
69
+ _listener.apply(void 0, arguments);
70
+ self.off(type, _listener2);
71
+ };
72
+ }
73
+ this.on(type, _listener2);
74
+ }
75
+
76
+ /**
77
+ * Removes event listeners.
78
+ * @param {string} [type] Type of the event (e.g. `change`). If is not provided, it removes all listeners.
79
+ * @param {function} [listener] Callback function to be called when the event is emitted. If listener is not provided, it removes all listeners for specified type.
80
+ * @example
81
+ * this.model.off('change'); // Stop listening to changes.
82
+ */;
83
+ _proto.off = function off(type, listener) {
84
+ if (!type) {
85
+ this.listeners = {};
86
+ } else {
87
+ if (!listener) {
88
+ delete this.listeners[type];
89
+ } else {
90
+ var listeners = this.listeners[type];
91
+ if (listeners) {
92
+ var copy = listeners.slice();
93
+ copy.forEach(function (fn, idx) {
94
+ if (fn === listener) listeners.splice(idx, 1);
95
+ });
96
+ if (!listeners.length) {
97
+ delete this.listeners[type];
98
+ }
111
99
  }
112
-
113
- var listeners = this.listeners && this.listeners[type];
114
-
115
- if (!listeners || !listeners.length) return;
116
-
117
- var copy = listeners.slice();
118
-
119
- copy.forEach(function (fn) {
120
- fn.apply(undefined, args);
121
- });
122
- };
123
-
124
- return Emitter;
100
+ }
101
+ }
102
+ }
103
+
104
+ /**
105
+ * Emits event of specified type. Listeners will receive specified arguments.
106
+ * @param {string} type Type of the event (e.g. `change`).
107
+ * @param {any} [...args] Arguments to be passed to listener.
108
+ * @example
109
+ * this.emit('invalid'); // Emit validation error event.
110
+ */;
111
+ _proto.emit = function emit(type) {
112
+ for (var _len = arguments.length, args = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
113
+ args[_key - 1] = arguments[_key];
114
+ }
115
+ var listeners = this.listeners && this.listeners[type];
116
+ if (!listeners || !listeners.length) return;
117
+ var copy = listeners.slice();
118
+ copy.forEach(function (fn) {
119
+ fn.apply(void 0, args);
120
+ });
121
+ };
122
+ return Emitter;
125
123
  }();
126
-
127
- export default Emitter;
124
+ export { Emitter as default };