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 +139 -103
- package/dist/rasti.min.js +1 -1
- package/es/Component.js +129 -95
- package/es/View.js +1 -1
- package/es/core/Interpolation.js +1 -1
- package/es/utils/getAttributesDiff.js +8 -6
- package/lib/Component.cjs +129 -95
- package/lib/View.cjs +1 -1
- package/lib/core/Interpolation.cjs +1 -1
- package/lib/utils/getAttributesDiff.cjs +8 -6
- package/package.json +1 -1
- package/src/Component.js +129 -95
- package/src/View.js +1 -1
- package/src/core/Interpolation.js +1 -1
- package/src/index.js +0 -1
- package/src/utils/getAttributesDiff.js +8 -6
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
|
|
1247
|
-
|
|
1248
|
-
|
|
1249
|
-
if (value
|
|
1250
|
-
|
|
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.
|
|
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.
|
|
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[
|
|
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
|
-
*
|
|
2185
|
-
*
|
|
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
|
-
|
|
2192
|
-
//
|
|
2193
|
-
|
|
2194
|
-
//
|
|
2195
|
-
|
|
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=>({"&":"&","<":"<",">":">",'"':""","'":"'"}[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=>({"&":"&","<":"<",">":">",'"':""","'":"'"}[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}));
|