rasti 4.0.0-alpha.1 → 4.0.0-alpha.3

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.
package/dist/rasti.js CHANGED
@@ -838,7 +838,7 @@
838
838
  * You shouldn't call this method directly. It's called from the constructor.
839
839
  * You may override it if you want to use a different logic or to
840
840
  * postpone element creation.
841
- */
841
+ */
842
842
  ensureElement() {
843
843
  // Element is already present.
844
844
  if (this.el) {
@@ -1242,12 +1242,14 @@
1242
1242
  // Find attributes to add/update.
1243
1243
  Object.keys(attributes).forEach(key => {
1244
1244
  let value = attributes[key];
1245
-
1246
- if (value === true) {
1247
- add[key] = '';
1248
- } else if (value !== false) {
1249
- if (value === null || typeof value === 'undefined') value = '';
1250
- add[key] = value;
1245
+ // Only add if the value is different from previous.
1246
+ if (value !== previous[key]) {
1247
+ if (value === true) {
1248
+ add[key] = '';
1249
+ } else if (value !== false) {
1250
+ if (value === null || typeof value === 'undefined') value = '';
1251
+ add[key] = value;
1252
+ }
1251
1253
  }
1252
1254
  });
1253
1255
  // Find attributes to remove.
@@ -1492,7 +1494,7 @@
1492
1494
  const endComment = findComment(parent, this.getEnd(), this.isComponent, startComment);
1493
1495
 
1494
1496
  this.ref = [
1495
- startComment,
1497
+ startComment,
1496
1498
  endComment
1497
1499
  ];
1498
1500
  }
@@ -1594,7 +1596,7 @@
1594
1596
  * @return {boolean} True if the element is a component root element.
1595
1597
  * @private
1596
1598
  */
1597
- const isComponent = (el) => el.hasAttribute(Component.ATTRIBUTE_ELEMENT) && el.getAttribute(Component.ATTRIBUTE_ELEMENT).endsWith('-1');
1599
+ const isComponent = (el) => !!el.dataset[Component.DATASET_ELEMENT] && el.dataset[Component.DATASET_ELEMENT].endsWith('-1');
1598
1600
 
1599
1601
  /**
1600
1602
  * Check if an element has the Rasti data attribute.
@@ -1603,7 +1605,7 @@
1603
1605
  * @return {boolean} True if the element has the data attribute.
1604
1606
  * @private
1605
1607
  */
1606
- const isElement = (el) => el.hasAttribute(Component.ATTRIBUTE_ELEMENT);
1608
+ const isElement = (el) => !!el.dataset[Component.DATASET_ELEMENT];
1607
1609
 
1608
1610
  /**
1609
1611
  * Generate string with placeholders for interpolated expressions.
@@ -1612,7 +1614,7 @@
1612
1614
  * @return {string} String with placeholders.
1613
1615
  * @private
1614
1616
  */
1615
- const addPlaceholders = (strings, expressions) =>
1617
+ const addPlaceholders = (strings, expressions) =>
1616
1618
  strings.reduce((out, string, i) => {
1617
1619
  // Add string part.
1618
1620
  out.push(string);
@@ -1682,10 +1684,11 @@
1682
1684
  * Expand events.
1683
1685
  * @param {object} attributes Attributes object.
1684
1686
  * @param {EventsManager} eventsManager Events manager.
1687
+ * @param {Function} getDataAttribute Function to get data attribute name with uid.
1685
1688
  * @return {object} Attributes object.
1686
1689
  * @private
1687
1690
  */
1688
- const expandEvents = (attributes, eventsManager) => {
1691
+ const expandEvents = (attributes, eventsManager, getDataAttribute) => {
1689
1692
  const out = {};
1690
1693
  Object.keys(attributes).forEach(key => {
1691
1694
  // Check if key is an event listener.
@@ -1697,7 +1700,7 @@
1697
1700
  if (listener) {
1698
1701
  const index = eventsManager.addListener(listener, type);
1699
1702
  // Add event listener index.
1700
- out[Component.ATTRIBUTE_EVENT(type)] = index;
1703
+ out[getDataAttribute(type)] = index;
1701
1704
  }
1702
1705
  } else {
1703
1706
  // Add attribute.
@@ -1837,7 +1840,8 @@
1837
1840
  // Expand attributes and events.
1838
1841
  const attributes = expandEvents(
1839
1842
  expandAttributes(parsedAttributes, value => getExpressionResult(value, this)),
1840
- this.eventsManager
1843
+ this.eventsManager,
1844
+ type => Component.ATTRIBUTE_EVENT(type, this.uid)
1841
1845
  );
1842
1846
  // Extend template attributes with `options.attributes`.
1843
1847
  if (isRoot && this.attributes) {
@@ -1891,7 +1895,8 @@
1891
1895
  const getAttributes = function() {
1892
1896
  const attributes = expandEvents(
1893
1897
  expandAttributes(parsedAttributes, value => getExpressionResult(value, this)),
1894
- this.eventsManager
1898
+ this.eventsManager,
1899
+ type => Component.ATTRIBUTE_EVENT(type, this.uid)
1895
1900
  );
1896
1901
 
1897
1902
  return attributes;
@@ -1992,7 +1997,7 @@
1992
1997
  /*
1993
1998
  * These option keys will be extended on the component instance.
1994
1999
  */
1995
- const componentOptions = ['key', 'state', 'onCreate', 'onChange', 'onHydrate', 'onRecycle', 'onUpdate'];
2000
+ const componentOptions = ['key', 'state', 'onCreate', 'onChange', 'onHydrate', 'onMount', 'onRecycle', 'onUpdate'];
1996
2001
 
1997
2002
  /**
1998
2003
  * @lends module:Component
@@ -2036,7 +2041,7 @@
2036
2041
  const events = {};
2037
2042
  // Create events object.
2038
2043
  this.eventsManager.types.forEach(type => {
2039
- const dataAttribute = Component.ATTRIBUTE_EVENT(type);
2044
+ const dataAttribute = Component.ATTRIBUTE_EVENT(type, this.uid);
2040
2045
  // Create a listener function that gets the listener index from the data attribute and calls the listener.
2041
2046
  const listener = function(event, component, matched) {
2042
2047
  // Get the listener index from the data attribute.
@@ -2060,34 +2065,6 @@
2060
2065
  return events;
2061
2066
  }
2062
2067
 
2063
- /**
2064
- * Subscribes to a `change` event on a model or emitter object and invokes the `onChange` lifecycle method.
2065
- * The subscription is automatically cleaned up when the component is destroyed.
2066
- * By default, the component subscribes to changes on `this.model`, `this.state`, and `this.props`.
2067
- *
2068
- * @param {Object} model - The model or emitter object to listen to.
2069
- * @param {string} [type='change'] - The event type to listen for.
2070
- * @param {Function} [listener=this.onChange] - The callback to invoke when the event is emitted.
2071
- * @returns {Component} The current component instance for chaining.
2072
- */
2073
- subscribe(model, type = 'change', listener = this.onChange) {
2074
- // Check if model has `on` method.
2075
- if (model.on) this.listenTo(model, type, listener);
2076
- return this;
2077
- }
2078
-
2079
- /**
2080
- * Tell if `Component` is a container.
2081
- * In which case, it will not have an element by itself.
2082
- * It will render a single expression which is expected to return a single component as child.
2083
- * `this.el` will be a reference to that child component's element.
2084
- * @return {boolean}
2085
- * @private
2086
- */
2087
- isContainer() {
2088
- return this.template.elements.length === 0 && this.template.interpolations.length === 1;
2089
- }
2090
-
2091
2068
  /**
2092
2069
  * Override super method. We don't want to ensure an element on instantiation.
2093
2070
  * We will provide it later.
@@ -2111,6 +2088,34 @@
2111
2088
  }
2112
2089
  }
2113
2090
 
2091
+ /**
2092
+ * Tell if `Component` is a container.
2093
+ * In which case, it will not have an element by itself.
2094
+ * It will render a single expression which is expected to return a single component as child.
2095
+ * `this.el` will be a reference to that child component's element.
2096
+ * @return {boolean}
2097
+ * @private
2098
+ */
2099
+ isContainer() {
2100
+ return this.template.elements.length === 0 && this.template.interpolations.length === 1;
2101
+ }
2102
+
2103
+ /**
2104
+ * Subscribes to a `change` event on a model or emitter object and invokes the `onChange` lifecycle method.
2105
+ * The subscription is automatically cleaned up when the component is destroyed.
2106
+ * By default, the component subscribes to changes on `this.model`, `this.state`, and `this.props`.
2107
+ *
2108
+ * @param {Object} model - The model or emitter object to listen to.
2109
+ * @param {string} [type='change'] - The event type to listen for.
2110
+ * @param {Function} [listener=this.onChange] - The callback to invoke when the event is emitted.
2111
+ * @returns {Component} The current component instance for chaining.
2112
+ */
2113
+ subscribe(model, type = 'change', listener = this.onChange) {
2114
+ // Check if model has `on` method.
2115
+ if (model.on) this.listenTo(model, type, listener);
2116
+ return this;
2117
+ }
2118
+
2114
2119
  /**
2115
2120
  * Used internally on the render process.
2116
2121
  * Attach the `Component` to the dom element providing `this.el`, delegate events,
@@ -2133,7 +2138,7 @@
2133
2138
  this.el = this.children[0].el;
2134
2139
  } else {
2135
2140
  // Search for every element in template using getSelector
2136
- this.template.elements.forEach((element, index) => {
2141
+ this.template.elements.forEach((element, index) => {
2137
2142
  if (index === 0) {
2138
2143
  element.hydrate(parent);
2139
2144
  if (this.el) element.ref = this.el;
@@ -2155,6 +2160,25 @@
2155
2160
  return this;
2156
2161
  }
2157
2162
 
2163
+ /**
2164
+ * Used internally on the render process.
2165
+ * Reuse a `Component` by replacing the placeholder comment with the real nodes.
2166
+ * Call `onRecycle` lifecycle method.
2167
+ * @param parent {node} The parent node.
2168
+ * @return {Component} The component instance.
2169
+ * @private
2170
+ */
2171
+ recycle(parent) {
2172
+ // Locate the placeholder comment and replace it with the real nodes
2173
+ const toBeReplaced = findComment(parent, Component.MARKER_RECYCLED(this.uid), isComponent);
2174
+ // Replace it with this.el.
2175
+ toBeReplaced.replaceWith(...this.getNodes());
2176
+ // Call `onRecycle` lifecycle method.
2177
+ this.onRecycle.call(this);
2178
+ // Return `this` for chaining.
2179
+ return this;
2180
+ }
2181
+
2158
2182
  /**
2159
2183
  * Get a `comment` marker with same data attribute as this component.
2160
2184
  * Used to replace the component when it is recycled.
@@ -2181,65 +2205,19 @@
2181
2205
  }
2182
2206
 
2183
2207
  /**
2184
- * Used internally on the render process.
2185
- * Reuse a `Component` by replacing the placeholder comment with the real nodes.
2186
- * Call `onRecycle` lifecycle method.
2187
- * @param parent {node} The parent node.
2188
- * @return {Component} The component instance.
2208
+ * Call onMount lifecycle method on children and self.
2209
+ * Used internally during the mount and render process.
2189
2210
  * @private
2190
2211
  */
2191
- recycle(parent) {
2192
- // Locate the placeholder comment and replace it with the real nodes
2193
- const toBeReplaced = findComment(parent, Component.MARKER_RECYCLED(this.uid), isComponent);
2194
- // Replace it with this.el.
2195
- toBeReplaced.replaceWith(...this.getNodes());
2196
- // Call `onRecycle` lifecycle method.
2197
- this.onRecycle.call(this);
2212
+ callOnMount() {
2213
+ // Call onMount on children first.
2214
+ this.children.forEach(child => child.callOnMount());
2215
+ // Call onMount on self.
2216
+ this.onMount.call(this);
2198
2217
  // Return `this` for chaining.
2199
2218
  return this;
2200
2219
  }
2201
2220
 
2202
- /**
2203
- * Lifecycle method. Called when the view is created, at the end of the `constructor`.
2204
- * @param options {object} The view options.
2205
- */
2206
- onCreate() {}
2207
-
2208
- /**
2209
- * Lifecycle method. Called when model emits `change` event.
2210
- * By default calls `render` method.
2211
- * This method can be extended with custom logic.
2212
- * Maybe comparing new attributes with previous ones and calling
2213
- * render when needed.
2214
- * @param model {Rasti.Model} The model that emitted the event.
2215
- * @param changed {object} Object containing keys and values that has changed.
2216
- * @param [...args] {any} Any extra arguments passed to set method.
2217
- */
2218
- onChange() {
2219
- this.render();
2220
- }
2221
-
2222
- /**
2223
- * Lifecycle method. Called when the component is rendered for the first time and hydrated.
2224
- */
2225
- onHydrate() {}
2226
-
2227
- /**
2228
- * Lifecycle method. Called when the component is recycled (reused with the same key) and added to the DOM again.
2229
- */
2230
- onRecycle() {}
2231
-
2232
- /**
2233
- * Lifecycle method. Called when the component is updated or re-rendered.
2234
- */
2235
- onUpdate() {}
2236
-
2237
- /**
2238
- * Lifecycle method. Called when the component is destroyed.
2239
- * @param {object} options Options object or any arguments passed to `destroy` method.
2240
- */
2241
- onDestroy() {}
2242
-
2243
2221
  /**
2244
2222
  * Tagged template helper method.
2245
2223
  * Used to create a partial template.
@@ -2365,6 +2343,7 @@
2365
2343
  * - Components with a `key` are recycled if a previous child with the same key exists.
2366
2344
  * - Unkeyed components are recycled if they have the same type and position in the template or partial.
2367
2345
  * A recycled `Component` will call the `onRecycle` lifecycle method.
2346
+ * - All child components will have their `onMount` lifecycle method called after they are added to the DOM. New children will be hydrated first (calling their `onHydrate` lifecycle method).
2368
2347
  * - If the active element is inside the component, it will retain focus after the render.
2369
2348
  * @return {Component} The component instance.
2370
2349
  */
@@ -2434,12 +2413,12 @@
2434
2413
  discarded.destroy();
2435
2414
  });
2436
2415
  // Add new children. Hydrate them.
2437
- nextChildren.forEach(child => {
2438
- this.addChild(child).hydrate(fragment);
2439
- });
2416
+ nextChildren.forEach(child => this.addChild(child).hydrate(fragment));
2440
2417
 
2441
2418
  interpolation.update(fragment);
2442
2419
  });
2420
+ // Call onMount lifecycle method on all children after interpolations update.
2421
+ this.children.forEach(child => child.callOnMount());
2443
2422
  // Destroy unused children.
2444
2423
  previousChildren.forEach(prev => {
2445
2424
  if (this.children.indexOf(prev) < 0) prev.destroy();
@@ -2463,6 +2442,55 @@
2463
2442
  return this;
2464
2443
  }
2465
2444
 
2445
+ /**
2446
+ * Lifecycle method. Called when the view is created, at the end of the `constructor`.
2447
+ * @param options {object} The view options.
2448
+ */
2449
+ onCreate() {}
2450
+
2451
+ /**
2452
+ * Lifecycle method. Called when model emits `change` event.
2453
+ * By default calls `render` method.
2454
+ * This method can be extended with custom logic.
2455
+ * Maybe comparing new attributes with previous ones and calling
2456
+ * render when needed.
2457
+ * @param model {Rasti.Model} The model that emitted the event.
2458
+ * @param changed {object} Object containing keys and values that has changed.
2459
+ * @param [...args] {any} Any extra arguments passed to set method.
2460
+ */
2461
+ onChange() {
2462
+ this.render();
2463
+ }
2464
+
2465
+ /**
2466
+ * Lifecycle method. Called when the component is rendered for the first time and hydrated.
2467
+ */
2468
+ onHydrate() {}
2469
+
2470
+ /**
2471
+ * Lifecycle method. Called when the component is mounted to the DOM.
2472
+ * This method is called after `onHydrate` and only when the component's element is actually present in the document.
2473
+ * It is called during the initial mount process (when using `Component.mount()`) and when new child components are added during render.
2474
+ * Use this method to perform operations that require the element to be in the DOM, such as measuring dimensions or focusing elements.
2475
+ */
2476
+ onMount() {}
2477
+
2478
+ /**
2479
+ * Lifecycle method. Called when the component is recycled (reused with the same key) and added to the DOM again.
2480
+ */
2481
+ onRecycle() {}
2482
+
2483
+ /**
2484
+ * Lifecycle method. Called when the component is updated or re-rendered.
2485
+ */
2486
+ onUpdate() {}
2487
+
2488
+ /**
2489
+ * Lifecycle method. Called when the component is destroyed.
2490
+ * @param {object} options Options object or any arguments passed to `destroy` method.
2491
+ */
2492
+ onDestroy() {}
2493
+
2466
2494
  /**
2467
2495
  * Mark a string as safe HTML to be rendered.
2468
2496
  * Normally you don't need to use this method, as Rasti will automatically mark string literals
@@ -2499,6 +2527,7 @@
2499
2527
  * Mount the component into the dom.
2500
2528
  * It instantiate the Component view using options,
2501
2529
  * appends its element into the DOM (if `el` is provided).
2530
+ * The `onMount` lifecycle method will be called after the component is added to the DOM.
2502
2531
  * And returns the view instance.
2503
2532
  * @static
2504
2533
  * @param {object} [options] The view options.
@@ -2520,6 +2549,8 @@
2520
2549
  // Append element to the DOM.
2521
2550
  el.append(...component.render().getNodes());
2522
2551
  }
2552
+ // Call onMount lifecycle method after nodes are in the DOM.
2553
+ component.callOnMount();
2523
2554
  }
2524
2555
  // Return component instance.
2525
2556
  return component;
@@ -2698,7 +2729,12 @@
2698
2729
  * Attributes used to identify elements and events.
2699
2730
  */
2700
2731
  Component.ATTRIBUTE_ELEMENT = 'data-rasti-el';
2701
- Component.ATTRIBUTE_EVENT = (type) => `data-rasti-on-${type}`;
2732
+ Component.ATTRIBUTE_EVENT = (type, uid) => `data-rasti-on-${type}-${uid}`;
2733
+
2734
+ /*
2735
+ * Dataset attribute used to identify elements.
2736
+ */
2737
+ Component.DATASET_ELEMENT = 'rastiEl';
2702
2738
 
2703
2739
  /*
2704
2740
  * Placeholders used to temporarily replace expressions in the template.
package/dist/rasti.min.js CHANGED
@@ -1 +1 @@
1
- !function(t,e){"object"==typeof exports&&"undefined"!=typeof module?e(exports):"function"==typeof define&&define.amd?define(["exports"],e):e((t="undefined"!=typeof globalThis?globalThis:t||self).Rasti={})}(this,(function(t){"use strict";function e(t){if("function"!=typeof t)throw new TypeError("Listener must be a function")}class s{on(t,s){return e(s),this.listeners||(this.listeners={}),this.listeners[t]||(this.listeners[t]=[]),this.listeners[t].push(s),()=>this.off(t,s)}once(t,s){e(s);const i=(...e)=>{s(...e),this.off(t,i)};return this.on(t,i)}off(t,e){this.listeners&&(t?this.listeners[t]&&(e?(this.listeners[t]=this.listeners[t].filter((t=>t!==e)),this.listeners[t].length||delete this.listeners[t]):delete this.listeners[t],Object.keys(this.listeners).length||delete this.listeners):delete this.listeners)}emit(t,...e){this.listeners&&this.listeners[t]&&this.listeners[t].slice().forEach((t=>t(...e)))}listenTo(t,e,s){return t.on(e,s),this.listeningTo||(this.listeningTo=[]),this.listeningTo.push({emitter:t,type:e,listener:s}),()=>this.stopListening(t,e,s)}listenToOnce(t,s,i){e(i);const n=(...e)=>{i(...e),this.stopListening(t,s,n)};return this.listenTo(t,s,n)}stopListening(t,e,s){this.listeningTo&&(this.listeningTo=this.listeningTo.filter((i=>!(!t||t===i.emitter&&!e||t===i.emitter&&e===i.type&&!s||t===i.emitter&&e===i.type&&s===i.listener)||(i.emitter.off(i.type,i.listener),!1))),this.listeningTo.length||delete this.listeningTo)}}const i=(t,e,...s)=>"function"!=typeof t?t:t.apply(e,s);class n extends s{constructor(){super(),this.preinitialize.apply(this,arguments),this.attributes=Object.assign({},i(this.defaults,this),this.parse.apply(this,arguments)),this.previous={},Object.keys(this.attributes).forEach(this.defineAttribute.bind(this))}preinitialize(){}defineAttribute(t){Object.defineProperty(this,`${this.constructor.attributePrefix}${t}`,{get:()=>this.get(t),set:e=>{this.set(t,e)}})}get(t){return this.attributes[t]}set(t,e,...s){let i,n;"object"==typeof t?(i=t,n=[e,...s]):(i={[t]:e},n=s);const r=this._changing;this._changing=!0;const h={};r||(this.previous=Object.assign({},this.attributes)),Object.keys(i).forEach((t=>{i[t]!==this.attributes[t]&&(h[t]=i[t],this.attributes[t]=i[t])}));const o=Object.keys(h);if(o.length&&(this._pending=["change",this,h,...n]),o.forEach((t=>{this.emit(`change:${t}`,this,i[t],...n)})),r)return this;for(;this._pending;){const t=this._pending;this._pending=null,this.emit.apply(this,t)}return this._pending=null,this._changing=!1,this}parse(t){return t}toJSON(){return Object.assign({},this.attributes)}}n.attributePrefix="";const r=["el","tag","attributes","events","model","template","onDestroy"];class h extends s{constructor(t={}){super(),this.preinitialize.apply(this,arguments),this.delegatedEventListeners=[],this.children=[],this.destroyQueue=[],this.viewOptions=[],r.forEach((e=>{e in t&&(this[e]=t[e],this.viewOptions.push(e))})),this.ensureUid(),this.ensureElement()}preinitialize(){}$(t){return this.el.querySelector(t)}$$(t){return this.el.querySelectorAll(t)}destroy(){return this.destroyChildren(),this.undelegateEvents(),this.stopListening(),this.off(),this.destroyQueue.forEach((t=>t())),this.destroyQueue=[],this.onDestroy.apply(this,arguments),this.destroyed=!0,this}onDestroy(){}addChild(t){return this.children.push(t),t}destroyChildren(){this.children.forEach((t=>t.destroy())),this.children=[]}ensureUid(){this.uid||(this.uid="r-"+ ++h.uid)}ensureElement(){if(this.el)this.el=i(this.el,this);else{const t=i(this.tag,this),e=i(this.attributes,this);this.el=this.createElement(t,e)}this.delegateEvents()}createElement(t="div",e={}){let s=document.createElement(t);return Object.keys(e).forEach((t=>s.setAttribute(t,e[t]))),s}removeElement(){return this.el.parentNode.removeChild(this.el),this}delegateEvents(t){if(t||(t=i(this.events,this)),!t)return this;this.delegatedEventListeners.length&&this.undelegateEvents();let s={};return Object.keys(t).forEach((i=>{const n=i.split(" "),r=n.shift(),h=n.join(" ");let o=t[i];"string"==typeof o&&(o=this[o]),e(o),s[r]||(s[r]=[]),s[r].push({selector:h,listener:o})})),Object.keys(s).forEach((t=>{const e=e=>{s[t].forEach((({selector:t,listener:s})=>{if(!t)return void s.call(this,e,this,this.el);let i=e.target;for(;i&&i!==this.el;)i.matches&&i.matches(t)&&s.call(this,e,this,i),i=i.parentElement}))};this.delegatedEventListeners.push({type:t,listener:e}),this.el.addEventListener(t,e)})),this}undelegateEvents(){return this.delegatedEventListeners.forEach((({type:t,listener:e})=>{this.el.removeEventListener(t,e)})),this.delegatedEventListeners=[],this}render(){return this.template&&(this.el.innerHTML=this.template(this.model)),this}static sanitize(t){return`${t}`.replace(/[&<>"']/g,(t=>({"&":"&amp;","<":"&lt;",">":"&gt;",'"':"&quot;","'":"&#039;"}[t])))}}h.uid=0;class o{constructor(t){this.value=t}toString(){return this.value}}class a{constructor(t){this.items=t}}class l{constructor(t,e){this.interpolationUid=t,this.result=e}}class c{constructor(){this.listeners=[],this.types=new Set,this.previousSize=0}addListener(t,e){return this.types.add(e),this.listeners.push(t),this.listeners.length-1}reset(){this.listeners=[],this.previousSize=this.types.size}hasPendingTypes(){return this.types.size>this.previousSize}}class u{constructor(){}reset(){this.paused=0,this.previous=this.tracked||new Map,this.tracked=new Map,this.positionStack=[0]}push(){this.positionStack.push(0)}pop(){this.positionStack.pop()}increment(){this.positionStack[this.positionStack.length-1]++}pause(){this.paused++}resume(){this.paused--}getPath(){return this.positionStack.join("-")}track(t){return 0===this.paused&&this.tracked.set(this.getPath(),t),t}findRecyclable(t){const e=this.previous.get(this.getPath());return e&&e.constructor===t&&!e.key?e:null}}const p=["value","checked","selected"];class d{constructor(t){this.getSelector=t.getSelector,this.getAttributes=t.getAttributes,this.previousAttributes={}}hydrate(t){this.ref=t.querySelector(this.getSelector())}update(){const t=this.getAttributes(),{remove:e,add:s}=function(t,e={}){const s={},i=[];return Object.keys(t).forEach((e=>{let i=t[e];!0===i?s[e]="":!1!==i&&(null==i&&(i=""),s[e]=i)})),Object.keys(e).forEach((s=>{(!(s in t)||e[s]!==t[s]&&!1===t[s])&&i.push(s)})),{add:s,remove:i}}(t,this.previousAttributes);this.previousAttributes=t,e.forEach((t=>{this.ref.removeAttribute(t),p.includes(t)&&t in this.ref&&(this.ref[t]="value"===t&&"")})),Object.keys(s).forEach((t=>{const e=s[t];this.ref.setAttribute(t,e),p.includes(t)&&t in this.ref&&(this.ref[t]="value"===t?e:!1!==e&&"false"!==e)}))}}const f=["value","checked","selected"];function g(t,e){t.nodeType===e.nodeType?t.nodeType!==Node.TEXT_NODE?t.tagName===e.tagName?(((t,e)=>{const s=e.attributes,i=t.attributes,n=new Set;for(let e=0,i=s.length;e<i;e++){const{name:i,value:r}=s[e];n.add(i),t.getAttribute(i)!==r&&t.setAttribute(i,r)}for(let e=i.length-1;e>=0;e--){const{name:s}=i[e];n.has(s)||t.removeAttribute(s)}for(let s=0,i=f.length;s<i;s++){const i=f[s];i in t&&t[i]!==e[i]&&(t[i]=e[i])}})(t,e),((t,e)=>{const s=t.childNodes,i=e.childNodes,n=s.length;if(n!==i.length)return!1;for(let t=0;t<n;t++)if(!s[t].isEqualNode(i[t]))return!1;return!0})(t,e)||((t,e)=>{const s=Array.from(e.childNodes);t.replaceChildren(...s)})(t,e)):t.replaceWith(e):t.nodeValue!==e.nodeValue&&(t.nodeValue=e.nodeValue):t.replaceWith(e)}function E(t,e,s=(()=>!1),i){let n=i||t.firstChild;for(;n;){if(n.nodeType===Node.COMMENT_NODE&&n.data.trim()===e)return n;if(n.nodeType!==Node.ELEMENT_NODE||s(n)||!n.firstChild){for(;n&&!n.nextSibling;)if(n=n.parentNode,!n||n===t)return null;n&&(n=n.nextSibling)}else n=n.firstChild}return null}class m{constructor(t){this.getStart=t.getStart,this.getEnd=t.getEnd,this.expression=t.expression,this.isComponent=t.isComponent,this.isElement=t.isElement}hydrate(t){const e=E(t,this.getStart(),this.isComponent),s=E(t,this.getEnd(),this.isComponent,e);this.ref=[e,s]}update(t){const[e,s]=this.ref,i=e.nextSibling,n=i.nextSibling===s,r=i==s,h=t.children;if(n&&1===h.length&&!this.isElement(i))g(i,h[0]);else if(r)s.parentNode.insertBefore(t,s);else{const i=document.createRange();i.setStartAfter(e),i.setEndBefore(s),i.deleteContents(),i.insertNode(t)}}}const y=t=>t.reduce(((t,e)=>(Array.isArray(e)?t.push(...y(e)):t.push(e),t)),[]);function b(t){const e=document.createElement("template");return e.innerHTML=`${t}`.trim(),e.content}function T(t){const e=[];return Object.keys(t).forEach((s=>{let i=t[s];!0===i?e.push(s):!1!==i&&(null==i&&(i=""),e.push(`${s}="${i}"`))})),e.join(" ")}const A=(t,e)=>i(t,e,e),R=t=>t.hasAttribute(j.ATTRIBUTE_ELEMENT)&&t.getAttribute(j.ATTRIBUTE_ELEMENT).endsWith("-1"),v=t=>t.hasAttribute(j.ATTRIBUTE_ELEMENT),L=(t,e)=>t.reduce(((t,s,i)=>(t.push(s),void 0!==e[i]&&t.push(j.PLACEHOLDER(i)),t)),[]).join(""),C=(t,e)=>{const s=j.PLACEHOLDER("(\\d+)"),i=new RegExp(`${s}`,"g"),n=[];let r,h=0;for(;null!==(r=i.exec(t));){const s=t.slice(h,r.index);n.push(j.markAsSafeHTML(s),e[r[1]]),h=r.index+r[0].length}return n.push(j.markAsSafeHTML(t.slice(h))),n},$=(t,e)=>t.reduce(((t,s)=>{const i=e(s[0]);if(1===s.length)"object"==typeof i?t=Object.assign(t,i):"string"==typeof i&&(t[i]=!0);else{const n=s[2]?e(s[1]):s[1];t[i]=n}return t}),{}),M=(t,e)=>{const s={};return Object.keys(t).forEach((i=>{const n=i.match(/on(([A-Z]{1}[a-z]+)+)/);if(n&&n[1]){const r=n[1].toLowerCase(),h=t[i];if(h){const t=e.addListener(h,r);s[j.ATTRIBUTE_EVENT(r)]=t}}else s[i]=t[i]})),s},S=(t,e,s=!1)=>{const i=j.PLACEHOLDER("(\\d+)"),n=new Map;return s||(t=t.replace(new RegExp(i,"g"),((t,s)=>{const i=e[s];if(i&&i.prototype instanceof j){if(n.has(i))return n.get(i);n.set(i,t)}return t}))),t.replace(new RegExp(`<(${i})([^>]*)>([\\s\\S]*?)</\\1>|<(${i})([^>]*)/>`,"g"),((t,s,i,n,r,h,o,l)=>{let c,u,p;if(s?(c=e[i],u=n):(c=void 0!==o?e[o]:h,u=l),!(c.prototype instanceof j))return t;if(s){const t=S(r,e,!0),s=k(t,e);p=C(s,e)}const d=w(u,e);return e.push((function(){const t=$(d,(t=>A(t,this)));return p&&(t.renderChildren=()=>new a(p.map((t=>A(t,this))))),c.mount(t)})),j.PLACEHOLDER(e.length-1)}))},O=(t,e)=>{const s=j.PLACEHOLDER("(?:\\d+)");return t.replace(new RegExp(`<(${s}|[a-z]+[1-6]?)(?:\\s*)((?:"[^"]*"|'[^']*'|[^>])*)(/?>)`,"gi"),e)},x=(t,e,s)=>{const n=j.PLACEHOLDER("(?:\\d+)");if(t.match(new RegExp(`^\\s*${n}\\s*$`)))return t;if(!t.match(new RegExp(`^\\s*<([a-z]+[1-6]?|${n})([^>]*)>([\\s\\S]*?)</(\\1|${n})>\\s*$|^\\s*<([a-z]+[1-6]?|${n})([^>]*)/>\\s*$`)))throw new SyntaxError(`Template must have a single root element or be a container component: "${t.trim()}"`);let r=0;return O(t,((t,h,o,a)=>{const l=0===r,c=++r;if(!l&&!o.match(new RegExp(n)))return t;const u=w(o,e),p=t=>`${t}-${c}`,d=function(){const t=M($(u,(t=>A(t,this))),this.eventsManager);return l&&this.attributes&&Object.assign(t,i(this.attributes,this)),t[j.ATTRIBUTE_ELEMENT]=p(this.uid),t};s.push({getSelector:function(){return`[${j.ATTRIBUTE_ELEMENT}="${p(this.uid)}"]`},getAttributes:d}),e.push((function(){const t=d.call(this);return j.markAsSafeHTML(T(t))}));return`<${h} ${j.PLACEHOLDER(e.length-1)}${a}`}))},k=(t,e)=>{const s=j.PLACEHOLDER("(?:\\d+)");return O(t,((t,i,n,r)=>{if(!n.match(new RegExp(s)))return t;const h=w(n,e),o=function(){return M($(h,(t=>A(t,this))),this.eventsManager)};e.push((function(){const t=o.call(this);return j.markAsSafeHTML(T(t))}));return`<${i} ${j.PLACEHOLDER(e.length-1)}${r}`}))},N=(t,e,s)=>{const i=j.PLACEHOLDER("(\\d+)");let n=0;return t.replace(new RegExp(i,"g"),(function(i,r,h){const o=t.substring(0,h);if(o.lastIndexOf("<")>o.lastIndexOf(">"))return i;const a=++n;return s.push({getStart:function(){return j.MARKER_START(`${this.uid}-${a}`)},getEnd:function(){return j.MARKER_END(`${this.uid}-${a}`)},expression:e[r]}),e.push((function(){const t=A(e[r],this),s=`${this.uid}-${a}`;return new l(s,t)})),j.PLACEHOLDER(e.length-1)}))},w=(t,e)=>{const s=j.PLACEHOLDER("(\\d+)"),i=[],n=new RegExp(`(${s}|[\\w-]+)(?:=(["']?)(?:${s}|((?:.?(?!["']?\\s+(?:\\S+)=|\\s*/?[>"']))+.))\\3)?`,"g");let r;for(;null!==(r=n.exec(t));){const[,t,s,n,h,o]=r,a=void 0!==s?e[parseInt(s,10)]:t,l=void 0!==h?e[parseInt(h,10)]:o;void 0!==l?i.push([a,l,!!n]):i.push([a])}return i},_=["key","state","onCreate","onChange","onHydrate","onRecycle","onUpdate"];class j extends h{constructor(t={}){super(...arguments),this.componentOptions=[],_.forEach((e=>{e in t&&(this[e]=t[e],this.componentOptions.push(e))}));const e={};Object.keys(t).forEach((s=>{this.viewOptions.includes(s)||this.componentOptions.includes(s)||(e[s]=t[s])})),this.props=new n(e),this.options=t,this.partial=this.partial.bind(this),this.onChange=this.onChange.bind(this),this.onCreate.apply(this,arguments)}events(){const t={};return this.eventsManager.types.forEach((s=>{const i=j.ATTRIBUTE_EVENT(s),n=function(t,s,n){const r=n.getAttribute(i);if(r){let i=this.eventsManager.listeners[parseInt(r,10)];"string"==typeof i&&(i=this[i]),e(i),i.call(this,t,s,n)}};t[`${s} [${i}]`]=n,t[s]=n})),t}subscribe(t,e="change",s=this.onChange){return t.on&&this.listenTo(t,e,s),this}isContainer(){return 0===this.template.elements.length&&1===this.template.interpolations.length}ensureElement(){this.eventsManager=new c,this.pathManager=new u,this.template=i(this.template,this),this.el&&(this.el=i(this.el,this),this.toString(),this.hydrate(this.el.parentNode))}hydrate(t){return["model","state","props"].forEach((t=>{this[t]&&this.subscribe(this[t])})),this.isContainer()?(this.template.interpolations[0].hydrate(t),this.children[0].hydrate(t),this.el=this.children[0].el):(this.template.elements.forEach(((e,s)=>{0===s?(e.hydrate(t),this.el?e.ref=this.el:this.el=e.ref):e.hydrate(this.el)})),this.delegateEvents(),this.template.interpolations.forEach((t=>t.hydrate(this.el))),this.children.forEach((t=>t.hydrate(this.el)))),this.onHydrate.call(this),this}getRecycledMarker(){return`\x3c!--${j.MARKER_RECYCLED(this.uid)}--\x3e`}getNodes(){return this.isContainer()?[this.template.interpolations[0].ref[0],...this.children[0].getNodes(),this.template.interpolations[0].ref[1]]:[this.el]}recycle(t){return E(t,j.MARKER_RECYCLED(this.uid),R).replaceWith(...this.getNodes()),this.onRecycle.call(this),this}onCreate(){}onChange(){this.render()}onHydrate(){}onRecycle(){}onUpdate(){}onDestroy(){}partial(t,...e){const s=C(k(S(L(t,e),e),e),e).map((t=>A(t,this)));return new a(s)}renderTemplatePart(t,e){const s=A(t,this),i=t=>{if(null!=t&&!1!==t&&!0!==t){if(t instanceof o)return t;if(t instanceof j)return e(t);if(t instanceof a){this.pathManager.push();const e=t.items.map((t=>(this.pathManager.increment(),i(t)))).join("");return this.pathManager.pop(),e}if(Array.isArray(t)){this.pathManager.pause();const e=y(t).map(i).join("");return this.pathManager.resume(),e}if(t instanceof l){this.pathManager.increment();const e=`\x3c!--${j.MARKER_START(t.interpolationUid)}--\x3e`,s=`\x3c!--${j.MARKER_END(t.interpolationUid)}--\x3e`;return`${e}${i(t.result)}${s}`}return j.sanitize(t)}return""};return`${i(s)}`}toString(){this.destroyChildren(),this.eventsManager.reset(),this.pathManager.reset();const t=t=>(this.pathManager.track(t),this.addChild(t));return this.template.parts.map((e=>this.renderTemplatePart(e,t))).join("")}render(){if(this.destroyed)return this;if(!this.el){const t=b(this);return this.hydrate(t),this}this.eventsManager.reset(),this.pathManager.reset();const t=this.isContainer()?null:document.activeElement;this.template.elements.forEach((t=>t.update()));const e=this.children;return this.children=[],this.template.interpolations.forEach((t=>{const s=[],i=[];this.pathManager.increment();const n=b(this.renderTemplatePart(t.expression,(t=>{let n=t,r=null;return r=t.key?e.find((e=>e.key===t.key)):this.pathManager.findRecyclable(t.constructor),r?(n=r.getRecycledMarker(),i.push([r,t]),r.key||this.pathManager.track(r)):(s.push(t),this.pathManager.track(t)),n})));i.forEach((([t,e])=>{this.addChild(t).recycle(n),t.props.set(e.props.toJSON()),e.destroy()})),s.forEach((t=>{this.addChild(t).hydrate(n)})),t.update(n)})),e.forEach((t=>{this.children.indexOf(t)<0&&t.destroy()})),this.isContainer()?this.el=this.children[0].el:this.eventsManager.hasPendingTypes()&&this.delegateEvents(),t&&this.el.contains(t)&&t.focus(),this.onUpdate.call(this),this}static markAsSafeHTML(t){return new o(t)}static extend(t){const e=this;class s extends e{}return Object.assign(s.prototype,"function"==typeof t?t(e.prototype):t),s}static mount(t,e,s){const i=new this(t);return e&&(s?(i.toString(),i.hydrate(e)):e.append(...i.render().getNodes())),i}static create(t,...e){"function"==typeof t&&(e=[t],t=["",""]);const s=[],i=[],n=C(N(x(S(L(t,e).trim(),e),e,s),e,i),e);return this.extend({template(){return{elements:s.map((t=>new d({getSelector:t.getSelector.bind(this),getAttributes:t.getAttributes.bind(this)}))),interpolations:i.map((t=>new m({getStart:t.getStart.bind(this),getEnd:t.getEnd.bind(this),expression:t.expression,isComponent:R,isElement:v}))),parts:n}}})}}j.ATTRIBUTE_ELEMENT="data-rasti-el",j.ATTRIBUTE_EVENT=t=>`data-rasti-on-${t}`,j.PLACEHOLDER=t=>`__RASTI-${t}__`,j.MARKER_RECYCLED=t=>`rasti-recycled-${t}`,j.MARKER_START=t=>`rasti-start-${t}`,j.MARKER_END=t=>`rasti-end-${t}`;var D=j.create`<div></div>`;t.Component=D,t.Emitter=s,t.Model=n,t.View=h}));
1
+ !function(t,e){"object"==typeof exports&&"undefined"!=typeof module?e(exports):"function"==typeof define&&define.amd?define(["exports"],e):e((t="undefined"!=typeof globalThis?globalThis:t||self).Rasti={})}(this,(function(t){"use strict";function e(t){if("function"!=typeof t)throw new TypeError("Listener must be a function")}class s{on(t,s){return e(s),this.listeners||(this.listeners={}),this.listeners[t]||(this.listeners[t]=[]),this.listeners[t].push(s),()=>this.off(t,s)}once(t,s){e(s);const i=(...e)=>{s(...e),this.off(t,i)};return this.on(t,i)}off(t,e){this.listeners&&(t?this.listeners[t]&&(e?(this.listeners[t]=this.listeners[t].filter((t=>t!==e)),this.listeners[t].length||delete this.listeners[t]):delete this.listeners[t],Object.keys(this.listeners).length||delete this.listeners):delete this.listeners)}emit(t,...e){this.listeners&&this.listeners[t]&&this.listeners[t].slice().forEach((t=>t(...e)))}listenTo(t,e,s){return t.on(e,s),this.listeningTo||(this.listeningTo=[]),this.listeningTo.push({emitter:t,type:e,listener:s}),()=>this.stopListening(t,e,s)}listenToOnce(t,s,i){e(i);const n=(...e)=>{i(...e),this.stopListening(t,s,n)};return this.listenTo(t,s,n)}stopListening(t,e,s){this.listeningTo&&(this.listeningTo=this.listeningTo.filter((i=>!(!t||t===i.emitter&&!e||t===i.emitter&&e===i.type&&!s||t===i.emitter&&e===i.type&&s===i.listener)||(i.emitter.off(i.type,i.listener),!1))),this.listeningTo.length||delete this.listeningTo)}}const i=(t,e,...s)=>"function"!=typeof t?t:t.apply(e,s);class n extends s{constructor(){super(),this.preinitialize.apply(this,arguments),this.attributes=Object.assign({},i(this.defaults,this),this.parse.apply(this,arguments)),this.previous={},Object.keys(this.attributes).forEach(this.defineAttribute.bind(this))}preinitialize(){}defineAttribute(t){Object.defineProperty(this,`${this.constructor.attributePrefix}${t}`,{get:()=>this.get(t),set:e=>{this.set(t,e)}})}get(t){return this.attributes[t]}set(t,e,...s){let i,n;"object"==typeof t?(i=t,n=[e,...s]):(i={[t]:e},n=s);const r=this._changing;this._changing=!0;const h={};r||(this.previous=Object.assign({},this.attributes)),Object.keys(i).forEach((t=>{i[t]!==this.attributes[t]&&(h[t]=i[t],this.attributes[t]=i[t])}));const o=Object.keys(h);if(o.length&&(this._pending=["change",this,h,...n]),o.forEach((t=>{this.emit(`change:${t}`,this,i[t],...n)})),r)return this;for(;this._pending;){const t=this._pending;this._pending=null,this.emit.apply(this,t)}return this._pending=null,this._changing=!1,this}parse(t){return t}toJSON(){return Object.assign({},this.attributes)}}n.attributePrefix="";const r=["el","tag","attributes","events","model","template","onDestroy"];class h extends s{constructor(t={}){super(),this.preinitialize.apply(this,arguments),this.delegatedEventListeners=[],this.children=[],this.destroyQueue=[],this.viewOptions=[],r.forEach((e=>{e in t&&(this[e]=t[e],this.viewOptions.push(e))})),this.ensureUid(),this.ensureElement()}preinitialize(){}$(t){return this.el.querySelector(t)}$$(t){return this.el.querySelectorAll(t)}destroy(){return this.destroyChildren(),this.undelegateEvents(),this.stopListening(),this.off(),this.destroyQueue.forEach((t=>t())),this.destroyQueue=[],this.onDestroy.apply(this,arguments),this.destroyed=!0,this}onDestroy(){}addChild(t){return this.children.push(t),t}destroyChildren(){this.children.forEach((t=>t.destroy())),this.children=[]}ensureUid(){this.uid||(this.uid="r-"+ ++h.uid)}ensureElement(){if(this.el)this.el=i(this.el,this);else{const t=i(this.tag,this),e=i(this.attributes,this);this.el=this.createElement(t,e)}this.delegateEvents()}createElement(t="div",e={}){let s=document.createElement(t);return Object.keys(e).forEach((t=>s.setAttribute(t,e[t]))),s}removeElement(){return this.el.parentNode.removeChild(this.el),this}delegateEvents(t){if(t||(t=i(this.events,this)),!t)return this;this.delegatedEventListeners.length&&this.undelegateEvents();let s={};return Object.keys(t).forEach((i=>{const n=i.split(" "),r=n.shift(),h=n.join(" ");let o=t[i];"string"==typeof o&&(o=this[o]),e(o),s[r]||(s[r]=[]),s[r].push({selector:h,listener:o})})),Object.keys(s).forEach((t=>{const e=e=>{s[t].forEach((({selector:t,listener:s})=>{if(!t)return void s.call(this,e,this,this.el);let i=e.target;for(;i&&i!==this.el;)i.matches&&i.matches(t)&&s.call(this,e,this,i),i=i.parentElement}))};this.delegatedEventListeners.push({type:t,listener:e}),this.el.addEventListener(t,e)})),this}undelegateEvents(){return this.delegatedEventListeners.forEach((({type:t,listener:e})=>{this.el.removeEventListener(t,e)})),this.delegatedEventListeners=[],this}render(){return this.template&&(this.el.innerHTML=this.template(this.model)),this}static sanitize(t){return`${t}`.replace(/[&<>"']/g,(t=>({"&":"&amp;","<":"&lt;",">":"&gt;",'"':"&quot;","'":"&#039;"}[t])))}}h.uid=0;class o{constructor(t){this.value=t}toString(){return this.value}}class a{constructor(t){this.items=t}}class l{constructor(t,e){this.interpolationUid=t,this.result=e}}class c{constructor(){this.listeners=[],this.types=new Set,this.previousSize=0}addListener(t,e){return this.types.add(e),this.listeners.push(t),this.listeners.length-1}reset(){this.listeners=[],this.previousSize=this.types.size}hasPendingTypes(){return this.types.size>this.previousSize}}class u{constructor(){}reset(){this.paused=0,this.previous=this.tracked||new Map,this.tracked=new Map,this.positionStack=[0]}push(){this.positionStack.push(0)}pop(){this.positionStack.pop()}increment(){this.positionStack[this.positionStack.length-1]++}pause(){this.paused++}resume(){this.paused--}getPath(){return this.positionStack.join("-")}track(t){return 0===this.paused&&this.tracked.set(this.getPath(),t),t}findRecyclable(t){const e=this.previous.get(this.getPath());return e&&e.constructor===t&&!e.key?e:null}}const d=["value","checked","selected"];class p{constructor(t){this.getSelector=t.getSelector,this.getAttributes=t.getAttributes,this.previousAttributes={}}hydrate(t){this.ref=t.querySelector(this.getSelector())}update(){const t=this.getAttributes(),{remove:e,add:s}=function(t,e={}){const s={},i=[];return Object.keys(t).forEach((i=>{let n=t[i];n!==e[i]&&(!0===n?s[i]="":!1!==n&&(null==n&&(n=""),s[i]=n))})),Object.keys(e).forEach((s=>{(!(s in t)||e[s]!==t[s]&&!1===t[s])&&i.push(s)})),{add:s,remove:i}}(t,this.previousAttributes);this.previousAttributes=t,e.forEach((t=>{this.ref.removeAttribute(t),d.includes(t)&&t in this.ref&&(this.ref[t]="value"===t&&"")})),Object.keys(s).forEach((t=>{const e=s[t];this.ref.setAttribute(t,e),d.includes(t)&&t in this.ref&&(this.ref[t]="value"===t?e:!1!==e&&"false"!==e)}))}}const f=["value","checked","selected"];function E(t,e){t.nodeType===e.nodeType?t.nodeType!==Node.TEXT_NODE?t.tagName===e.tagName?(((t,e)=>{const s=e.attributes,i=t.attributes,n=new Set;for(let e=0,i=s.length;e<i;e++){const{name:i,value:r}=s[e];n.add(i),t.getAttribute(i)!==r&&t.setAttribute(i,r)}for(let e=i.length-1;e>=0;e--){const{name:s}=i[e];n.has(s)||t.removeAttribute(s)}for(let s=0,i=f.length;s<i;s++){const i=f[s];i in t&&t[i]!==e[i]&&(t[i]=e[i])}})(t,e),((t,e)=>{const s=t.childNodes,i=e.childNodes,n=s.length;if(n!==i.length)return!1;for(let t=0;t<n;t++)if(!s[t].isEqualNode(i[t]))return!1;return!0})(t,e)||((t,e)=>{const s=Array.from(e.childNodes);t.replaceChildren(...s)})(t,e)):t.replaceWith(e):t.nodeValue!==e.nodeValue&&(t.nodeValue=e.nodeValue):t.replaceWith(e)}function g(t,e,s=(()=>!1),i){let n=i||t.firstChild;for(;n;){if(n.nodeType===Node.COMMENT_NODE&&n.data.trim()===e)return n;if(n.nodeType!==Node.ELEMENT_NODE||s(n)||!n.firstChild){for(;n&&!n.nextSibling;)if(n=n.parentNode,!n||n===t)return null;n&&(n=n.nextSibling)}else n=n.firstChild}return null}class m{constructor(t){this.getStart=t.getStart,this.getEnd=t.getEnd,this.expression=t.expression,this.isComponent=t.isComponent,this.isElement=t.isElement}hydrate(t){const e=g(t,this.getStart(),this.isComponent),s=g(t,this.getEnd(),this.isComponent,e);this.ref=[e,s]}update(t){const[e,s]=this.ref,i=e.nextSibling,n=i.nextSibling===s,r=i==s,h=t.children;if(n&&1===h.length&&!this.isElement(i))E(i,h[0]);else if(r)s.parentNode.insertBefore(t,s);else{const i=document.createRange();i.setStartAfter(e),i.setEndBefore(s),i.deleteContents(),i.insertNode(t)}}}const y=t=>t.reduce(((t,e)=>(Array.isArray(e)?t.push(...y(e)):t.push(e),t)),[]);function T(t){const e=document.createElement("template");return e.innerHTML=`${t}`.trim(),e.content}function b(t){const e=[];return Object.keys(t).forEach((s=>{let i=t[s];!0===i?e.push(s):!1!==i&&(null==i&&(i=""),e.push(`${s}="${i}"`))})),e.join(" ")}const A=(t,e)=>i(t,e,e),v=t=>!!t.dataset[j.DATASET_ELEMENT]&&t.dataset[j.DATASET_ELEMENT].endsWith("-1"),R=t=>!!t.dataset[j.DATASET_ELEMENT],M=(t,e)=>t.reduce(((t,s,i)=>(t.push(s),void 0!==e[i]&&t.push(j.PLACEHOLDER(i)),t)),[]).join(""),L=(t,e)=>{const s=j.PLACEHOLDER("(\\d+)"),i=new RegExp(`${s}`,"g"),n=[];let r,h=0;for(;null!==(r=i.exec(t));){const s=t.slice(h,r.index);n.push(j.markAsSafeHTML(s),e[r[1]]),h=r.index+r[0].length}return n.push(j.markAsSafeHTML(t.slice(h))),n},$=(t,e)=>t.reduce(((t,s)=>{const i=e(s[0]);if(1===s.length)"object"==typeof i?t=Object.assign(t,i):"string"==typeof i&&(t[i]=!0);else{const n=s[2]?e(s[1]):s[1];t[i]=n}return t}),{}),C=(t,e,s)=>{const i={};return Object.keys(t).forEach((n=>{const r=n.match(/on(([A-Z]{1}[a-z]+)+)/);if(r&&r[1]){const h=r[1].toLowerCase(),o=t[n];if(o){const t=e.addListener(o,h);i[s(h)]=t}}else i[n]=t[n]})),i},S=(t,e,s=!1)=>{const i=j.PLACEHOLDER("(\\d+)"),n=new Map;return s||(t=t.replace(new RegExp(i,"g"),((t,s)=>{const i=e[s];if(i&&i.prototype instanceof j){if(n.has(i))return n.get(i);n.set(i,t)}return t}))),t.replace(new RegExp(`<(${i})([^>]*)>([\\s\\S]*?)</\\1>|<(${i})([^>]*)/>`,"g"),((t,s,i,n,r,h,o,l)=>{let c,u,d;if(s?(c=e[i],u=n):(c=void 0!==o?e[o]:h,u=l),!(c.prototype instanceof j))return t;if(s){const t=S(r,e,!0),s=k(t,e);d=L(s,e)}const p=w(u,e);return e.push((function(){const t=$(p,(t=>A(t,this)));return d&&(t.renderChildren=()=>new a(d.map((t=>A(t,this))))),c.mount(t)})),j.PLACEHOLDER(e.length-1)}))},O=(t,e)=>{const s=j.PLACEHOLDER("(?:\\d+)");return t.replace(new RegExp(`<(${s}|[a-z]+[1-6]?)(?:\\s*)((?:"[^"]*"|'[^']*'|[^>])*)(/?>)`,"gi"),e)},x=(t,e,s)=>{const n=j.PLACEHOLDER("(?:\\d+)");if(t.match(new RegExp(`^\\s*${n}\\s*$`)))return t;if(!t.match(new RegExp(`^\\s*<([a-z]+[1-6]?|${n})([^>]*)>([\\s\\S]*?)</(\\1|${n})>\\s*$|^\\s*<([a-z]+[1-6]?|${n})([^>]*)/>\\s*$`)))throw new SyntaxError(`Template must have a single root element or be a container component: "${t.trim()}"`);let r=0;return O(t,((t,h,o,a)=>{const l=0===r,c=++r;if(!l&&!o.match(new RegExp(n)))return t;const u=w(o,e),d=t=>`${t}-${c}`,p=function(){const t=C($(u,(t=>A(t,this))),this.eventsManager,(t=>j.ATTRIBUTE_EVENT(t,this.uid)));return l&&this.attributes&&Object.assign(t,i(this.attributes,this)),t[j.ATTRIBUTE_ELEMENT]=d(this.uid),t};s.push({getSelector:function(){return`[${j.ATTRIBUTE_ELEMENT}="${d(this.uid)}"]`},getAttributes:p}),e.push((function(){const t=p.call(this);return j.markAsSafeHTML(b(t))}));return`<${h} ${j.PLACEHOLDER(e.length-1)}${a}`}))},k=(t,e)=>{const s=j.PLACEHOLDER("(?:\\d+)");return O(t,((t,i,n,r)=>{if(!n.match(new RegExp(s)))return t;const h=w(n,e),o=function(){return C($(h,(t=>A(t,this))),this.eventsManager,(t=>j.ATTRIBUTE_EVENT(t,this.uid)))};e.push((function(){const t=o.call(this);return j.markAsSafeHTML(b(t))}));return`<${i} ${j.PLACEHOLDER(e.length-1)}${r}`}))},N=(t,e,s)=>{const i=j.PLACEHOLDER("(\\d+)");let n=0;return t.replace(new RegExp(i,"g"),(function(i,r,h){const o=t.substring(0,h);if(o.lastIndexOf("<")>o.lastIndexOf(">"))return i;const a=++n;return s.push({getStart:function(){return j.MARKER_START(`${this.uid}-${a}`)},getEnd:function(){return j.MARKER_END(`${this.uid}-${a}`)},expression:e[r]}),e.push((function(){const t=A(e[r],this),s=`${this.uid}-${a}`;return new l(s,t)})),j.PLACEHOLDER(e.length-1)}))},w=(t,e)=>{const s=j.PLACEHOLDER("(\\d+)"),i=[],n=new RegExp(`(${s}|[\\w-]+)(?:=(["']?)(?:${s}|((?:.?(?!["']?\\s+(?:\\S+)=|\\s*/?[>"']))+.))\\3)?`,"g");let r;for(;null!==(r=n.exec(t));){const[,t,s,n,h,o]=r,a=void 0!==s?e[parseInt(s,10)]:t,l=void 0!==h?e[parseInt(h,10)]:o;void 0!==l?i.push([a,l,!!n]):i.push([a])}return i},_=["key","state","onCreate","onChange","onHydrate","onMount","onRecycle","onUpdate"];class j extends h{constructor(t={}){super(...arguments),this.componentOptions=[],_.forEach((e=>{e in t&&(this[e]=t[e],this.componentOptions.push(e))}));const e={};Object.keys(t).forEach((s=>{this.viewOptions.includes(s)||this.componentOptions.includes(s)||(e[s]=t[s])})),this.props=new n(e),this.options=t,this.partial=this.partial.bind(this),this.onChange=this.onChange.bind(this),this.onCreate.apply(this,arguments)}events(){const t={};return this.eventsManager.types.forEach((s=>{const i=j.ATTRIBUTE_EVENT(s,this.uid),n=function(t,s,n){const r=n.getAttribute(i);if(r){let i=this.eventsManager.listeners[parseInt(r,10)];"string"==typeof i&&(i=this[i]),e(i),i.call(this,t,s,n)}};t[`${s} [${i}]`]=n,t[s]=n})),t}ensureElement(){this.eventsManager=new c,this.pathManager=new u,this.template=i(this.template,this),this.el&&(this.el=i(this.el,this),this.toString(),this.hydrate(this.el.parentNode))}isContainer(){return 0===this.template.elements.length&&1===this.template.interpolations.length}subscribe(t,e="change",s=this.onChange){return t.on&&this.listenTo(t,e,s),this}hydrate(t){return["model","state","props"].forEach((t=>{this[t]&&this.subscribe(this[t])})),this.isContainer()?(this.template.interpolations[0].hydrate(t),this.children[0].hydrate(t),this.el=this.children[0].el):(this.template.elements.forEach(((e,s)=>{0===s?(e.hydrate(t),this.el?e.ref=this.el:this.el=e.ref):e.hydrate(this.el)})),this.delegateEvents(),this.template.interpolations.forEach((t=>t.hydrate(this.el))),this.children.forEach((t=>t.hydrate(this.el)))),this.onHydrate.call(this),this}recycle(t){return g(t,j.MARKER_RECYCLED(this.uid),v).replaceWith(...this.getNodes()),this.onRecycle.call(this),this}getRecycledMarker(){return`\x3c!--${j.MARKER_RECYCLED(this.uid)}--\x3e`}getNodes(){return this.isContainer()?[this.template.interpolations[0].ref[0],...this.children[0].getNodes(),this.template.interpolations[0].ref[1]]:[this.el]}callOnMount(){return this.children.forEach((t=>t.callOnMount())),this.onMount.call(this),this}partial(t,...e){const s=L(k(S(M(t,e),e),e),e).map((t=>A(t,this)));return new a(s)}renderTemplatePart(t,e){const s=A(t,this),i=t=>{if(null!=t&&!1!==t&&!0!==t){if(t instanceof o)return t;if(t instanceof j)return e(t);if(t instanceof a){this.pathManager.push();const e=t.items.map((t=>(this.pathManager.increment(),i(t)))).join("");return this.pathManager.pop(),e}if(Array.isArray(t)){this.pathManager.pause();const e=y(t).map(i).join("");return this.pathManager.resume(),e}if(t instanceof l){this.pathManager.increment();const e=`\x3c!--${j.MARKER_START(t.interpolationUid)}--\x3e`,s=`\x3c!--${j.MARKER_END(t.interpolationUid)}--\x3e`;return`${e}${i(t.result)}${s}`}return j.sanitize(t)}return""};return`${i(s)}`}toString(){this.destroyChildren(),this.eventsManager.reset(),this.pathManager.reset();const t=t=>(this.pathManager.track(t),this.addChild(t));return this.template.parts.map((e=>this.renderTemplatePart(e,t))).join("")}render(){if(this.destroyed)return this;if(!this.el){const t=T(this);return this.hydrate(t),this}this.eventsManager.reset(),this.pathManager.reset();const t=this.isContainer()?null:document.activeElement;this.template.elements.forEach((t=>t.update()));const e=this.children;return this.children=[],this.template.interpolations.forEach((t=>{const s=[],i=[];this.pathManager.increment();const n=T(this.renderTemplatePart(t.expression,(t=>{let n=t,r=null;return r=t.key?e.find((e=>e.key===t.key)):this.pathManager.findRecyclable(t.constructor),r?(n=r.getRecycledMarker(),i.push([r,t]),r.key||this.pathManager.track(r)):(s.push(t),this.pathManager.track(t)),n})));i.forEach((([t,e])=>{this.addChild(t).recycle(n),t.props.set(e.props.toJSON()),e.destroy()})),s.forEach((t=>this.addChild(t).hydrate(n))),t.update(n)})),this.children.forEach((t=>t.callOnMount())),e.forEach((t=>{this.children.indexOf(t)<0&&t.destroy()})),this.isContainer()?this.el=this.children[0].el:this.eventsManager.hasPendingTypes()&&this.delegateEvents(),t&&this.el.contains(t)&&t.focus(),this.onUpdate.call(this),this}onCreate(){}onChange(){this.render()}onHydrate(){}onMount(){}onRecycle(){}onUpdate(){}onDestroy(){}static markAsSafeHTML(t){return new o(t)}static extend(t){const e=this;class s extends e{}return Object.assign(s.prototype,"function"==typeof t?t(e.prototype):t),s}static mount(t,e,s){const i=new this(t);return e&&(s?(i.toString(),i.hydrate(e)):e.append(...i.render().getNodes()),i.callOnMount()),i}static create(t,...e){"function"==typeof t&&(e=[t],t=["",""]);const s=[],i=[],n=L(N(x(S(M(t,e).trim(),e),e,s),e,i),e);return this.extend({template(){return{elements:s.map((t=>new p({getSelector:t.getSelector.bind(this),getAttributes:t.getAttributes.bind(this)}))),interpolations:i.map((t=>new m({getStart:t.getStart.bind(this),getEnd:t.getEnd.bind(this),expression:t.expression,isComponent:v,isElement:R}))),parts:n}}})}}j.ATTRIBUTE_ELEMENT="data-rasti-el",j.ATTRIBUTE_EVENT=(t,e)=>`data-rasti-on-${t}-${e}`,j.DATASET_ELEMENT="rastiEl",j.PLACEHOLDER=t=>`__RASTI-${t}__`,j.MARKER_RECYCLED=t=>`rasti-recycled-${t}`,j.MARKER_START=t=>`rasti-start-${t}`,j.MARKER_END=t=>`rasti-end-${t}`;var D=j.create`<div></div>`;t.Component=D,t.Emitter=s,t.Model=n,t.View=h}));