rasti 4.0.0-alpha.5 → 4.0.0-alpha.7
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/README.md +8 -6
- package/dist/rasti.js +194 -85
- package/dist/rasti.min.js +1 -1
- package/es/Component.js +106 -47
- package/es/View.js +2 -2
- package/es/core/Interpolation.js +61 -33
- package/es/index.js +1 -0
- package/es/utils/replaceNode.js +24 -0
- package/lib/Component.cjs +106 -47
- package/lib/View.cjs +2 -2
- package/lib/core/Interpolation.cjs +61 -33
- package/lib/index.cjs +1 -0
- package/lib/utils/replaceNode.cjs +26 -0
- package/package.json +2 -2
- package/src/Component.js +106 -47
- package/src/View.js +2 -2
- package/src/core/Interpolation.js +61 -33
- package/src/utils/replaceNode.js +22 -0
package/README.md
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
<p align="center">
|
|
2
2
|
<picture>
|
|
3
|
-
<source media="(prefers-color-scheme: dark)" srcset="https://cdn.jsdelivr.net/gh/8tentaculos/rasti@v4.0.0-alpha.
|
|
4
|
-
<img alt="Rasti.js" src="https://cdn.jsdelivr.net/gh/8tentaculos/rasti@v4.0.0-alpha.
|
|
3
|
+
<source media="(prefers-color-scheme: dark)" srcset="https://cdn.jsdelivr.net/gh/8tentaculos/rasti@v4.0.0-alpha.7/docs/logo-dark.svg">
|
|
4
|
+
<img alt="Rasti.js" src="https://cdn.jsdelivr.net/gh/8tentaculos/rasti@v4.0.0-alpha.7/docs/logo.svg" height="120">
|
|
5
5
|
</picture>
|
|
6
6
|
</p>
|
|
7
7
|
|
|
@@ -182,10 +182,12 @@ For detailed information on how to use **Rasti**, refer to the [API documentatio
|
|
|
182
182
|
|
|
183
183
|
## Version History
|
|
184
184
|
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
- **[
|
|
188
|
-
- **[
|
|
185
|
+
We strive to minimize breaking changes between major versions. However, if you're migrating between major versions, please refer to the release notes below for details on any breaking changes and migration tips.
|
|
186
|
+
|
|
187
|
+
- **[v4.0.0](https://github.com/8tentaculos/rasti/releases/tag/v4.0.0)**
|
|
188
|
+
- **[v3.0.0](https://github.com/8tentaculos/rasti/releases/tag/v3.0.0)**
|
|
189
|
+
- **[v2.0.0](https://github.com/8tentaculos/rasti/releases/tag/v2.0.0)**
|
|
190
|
+
- **[v1.0.0](https://github.com/8tentaculos/rasti/releases/tag/v1.0.0)**
|
|
189
191
|
|
|
190
192
|
## License
|
|
191
193
|
|
package/dist/rasti.js
CHANGED
|
@@ -830,7 +830,7 @@
|
|
|
830
830
|
* Ensure that the view has a unique id at `this.uid`.
|
|
831
831
|
*/
|
|
832
832
|
ensureUid() {
|
|
833
|
-
if (!this.uid) this.uid = `r
|
|
833
|
+
if (!this.uid) this.uid = `r${++View.uid}`;
|
|
834
834
|
}
|
|
835
835
|
|
|
836
836
|
/**
|
|
@@ -879,7 +879,7 @@
|
|
|
879
879
|
* @return {Rasti.View} Return `this` for chaining.
|
|
880
880
|
*/
|
|
881
881
|
removeElement() {
|
|
882
|
-
this.el.
|
|
882
|
+
this.el.remove();
|
|
883
883
|
// Return `this` for chaining.
|
|
884
884
|
return this;
|
|
885
885
|
}
|
|
@@ -1258,7 +1258,7 @@
|
|
|
1258
1258
|
* @param {Function} options.getAttributes Function that returns the attributes object for the element.
|
|
1259
1259
|
* @private
|
|
1260
1260
|
*/
|
|
1261
|
-
class Element {
|
|
1261
|
+
let Element$1 = class Element {
|
|
1262
1262
|
constructor(options) {
|
|
1263
1263
|
this.getSelector = options.getSelector;
|
|
1264
1264
|
this.getAttributes = options.getAttributes;
|
|
@@ -1299,7 +1299,7 @@
|
|
|
1299
1299
|
}
|
|
1300
1300
|
});
|
|
1301
1301
|
}
|
|
1302
|
-
}
|
|
1302
|
+
};
|
|
1303
1303
|
|
|
1304
1304
|
/**
|
|
1305
1305
|
* Properties that should be mirrored from source to target.
|
|
@@ -1459,7 +1459,7 @@
|
|
|
1459
1459
|
* @param {Function} options.getEnd Function that returns the end comment marker text.
|
|
1460
1460
|
* @param {any} options.expression The expression to be evaluated for the interpolation.
|
|
1461
1461
|
* @param {Function} options.isComponent Function that checks if an element is a component root element.
|
|
1462
|
-
* @param {Function} options.
|
|
1462
|
+
* @param {Function} options.containsComponent Function that checks if an element contains a component.
|
|
1463
1463
|
* @private
|
|
1464
1464
|
*/
|
|
1465
1465
|
class Interpolation {
|
|
@@ -1467,8 +1467,8 @@
|
|
|
1467
1467
|
this.getStart = options.getStart;
|
|
1468
1468
|
this.getEnd = options.getEnd;
|
|
1469
1469
|
this.expression = options.expression;
|
|
1470
|
-
this.
|
|
1471
|
-
this.
|
|
1470
|
+
this.shouldSkipFind = options.shouldSkipFind;
|
|
1471
|
+
this.shouldSkipSync = options.shouldSkipSync;
|
|
1472
1472
|
this.previousItems = [];
|
|
1473
1473
|
}
|
|
1474
1474
|
|
|
@@ -1478,12 +1478,12 @@
|
|
|
1478
1478
|
* @param {Node} parent The parent node to search in.
|
|
1479
1479
|
*/
|
|
1480
1480
|
hydrate(parent) {
|
|
1481
|
-
const
|
|
1482
|
-
const
|
|
1481
|
+
const startMark = findComment(parent, this.getStart(), this.shouldSkipFind);
|
|
1482
|
+
const endMark = findComment(parent, this.getEnd(), this.shouldSkipFind, startMark);
|
|
1483
1483
|
|
|
1484
1484
|
this.ref = [
|
|
1485
|
-
|
|
1486
|
-
|
|
1485
|
+
startMark,
|
|
1486
|
+
endMark
|
|
1487
1487
|
];
|
|
1488
1488
|
}
|
|
1489
1489
|
|
|
@@ -1493,39 +1493,67 @@
|
|
|
1493
1493
|
* @param {DocumentFragment} fragment The new content fragment to insert.
|
|
1494
1494
|
* @param {Element} targetElement The target element to replace with the new fragment.
|
|
1495
1495
|
*/
|
|
1496
|
-
update(fragment,
|
|
1497
|
-
|
|
1498
|
-
|
|
1499
|
-
|
|
1500
|
-
}
|
|
1496
|
+
update(fragment, handleComponents) {
|
|
1497
|
+
let divider;
|
|
1498
|
+
// Reference to marker elements.
|
|
1499
|
+
const [startMark, endMark] = this.ref;
|
|
1501
1500
|
|
|
1502
|
-
const
|
|
1503
|
-
|
|
1504
|
-
const
|
|
1505
|
-
|
|
1506
|
-
const currentSingleChildElement = !currentEmpty && currentFirstElement.nextSibling ===
|
|
1507
|
-
const fragmentChildren = fragment.children;
|
|
1501
|
+
const currentFirstElement = startMark.nextSibling;
|
|
1502
|
+
// Check if the interpolation is empty.
|
|
1503
|
+
const currentEmpty = currentFirstElement === endMark;
|
|
1504
|
+
// Check if the interpolation has a single child element.
|
|
1505
|
+
const currentSingleChildElement = !currentEmpty && currentFirstElement.nextSibling === endMark;
|
|
1508
1506
|
|
|
1509
1507
|
if (currentEmpty) {
|
|
1510
|
-
//
|
|
1511
|
-
|
|
1512
|
-
} else if (
|
|
1513
|
-
|
|
1514
|
-
|
|
1515
|
-
|
|
1508
|
+
// The interpolation is empty. Insert the fragment.
|
|
1509
|
+
endMark.before(fragment);
|
|
1510
|
+
} else if (
|
|
1511
|
+
currentSingleChildElement &&
|
|
1512
|
+
fragment.children.length === 1 &&
|
|
1513
|
+
!this.shouldSkipSync(currentFirstElement) &&
|
|
1514
|
+
!this.shouldSkipSync(fragment.firstChild)
|
|
1515
|
+
) {
|
|
1516
|
+
// The interpolation has a single child element and the new fragment has a single child element.
|
|
1517
|
+
// The elements doesn't contain a component. Sync node attributes and content.
|
|
1518
|
+
syncNode(currentFirstElement, fragment.firstChild);
|
|
1519
|
+
} else {
|
|
1520
|
+
// The interpolation has multiple child elements or the new fragment has multiple child elements.
|
|
1521
|
+
// Insert a divider comment before the end marker and insert the new fragment after the divider.
|
|
1522
|
+
divider = document.createComment('');
|
|
1523
|
+
endMark.before(divider);
|
|
1524
|
+
endMark.before(fragment);
|
|
1525
|
+
}
|
|
1526
|
+
// Handle the components in the fragment. Execute the handler function.
|
|
1527
|
+
handleComponents();
|
|
1528
|
+
|
|
1529
|
+
if (divider) {
|
|
1530
|
+
// Remove old content and divider.
|
|
1531
|
+
const startMark = this.ref[0];
|
|
1532
|
+
if (startMark.nextSibling === divider) {
|
|
1533
|
+
divider.remove();
|
|
1516
1534
|
} else {
|
|
1517
|
-
|
|
1518
|
-
|
|
1535
|
+
const range = document.createRange();
|
|
1536
|
+
range.setStartAfter(this.ref[0]);
|
|
1537
|
+
range.setEndAfter(divider);
|
|
1538
|
+
range.deleteContents();
|
|
1519
1539
|
}
|
|
1520
|
-
} else {
|
|
1521
|
-
// Interpolation is not empty. Replace the interpolation content.
|
|
1522
|
-
const range = document.createRange();
|
|
1523
|
-
range.setStartAfter(startComment);
|
|
1524
|
-
range.setEndBefore(endComment);
|
|
1525
|
-
range.deleteContents();
|
|
1526
|
-
range.insertNode(fragment);
|
|
1527
1540
|
}
|
|
1528
1541
|
}
|
|
1542
|
+
|
|
1543
|
+
/**
|
|
1544
|
+
* Update the interpolation content with a new fragment. This is used for container components.
|
|
1545
|
+
* @param {Element} element The element to replace with the new fragment.
|
|
1546
|
+
* @param {DocumentFragment} fragment The new content fragment to insert.
|
|
1547
|
+
* @param {Function} handleComponents Function to handle the components in the fragment before removing the old content.
|
|
1548
|
+
*/
|
|
1549
|
+
updateElement(element, fragment, handleComponents) {
|
|
1550
|
+
const divider = document.createComment('');
|
|
1551
|
+
element.after(divider);
|
|
1552
|
+
divider.after(fragment.firstChild);
|
|
1553
|
+
handleComponents();
|
|
1554
|
+
if (element.nextSibling === divider) element.remove();
|
|
1555
|
+
divider.remove();
|
|
1556
|
+
}
|
|
1529
1557
|
}
|
|
1530
1558
|
|
|
1531
1559
|
/**
|
|
@@ -1578,6 +1606,29 @@
|
|
|
1578
1606
|
return html.join(' ');
|
|
1579
1607
|
}
|
|
1580
1608
|
|
|
1609
|
+
/**
|
|
1610
|
+
* Replaces an existing DOM node with a new node, preserving internal DOM state.
|
|
1611
|
+
* Uses moveBefore if available, otherwise falls back to before.
|
|
1612
|
+
*
|
|
1613
|
+
* @param {Node} oldNode The existing DOM node to replace.
|
|
1614
|
+
* @param {Node} newNode The new DOM node to replace the old node with.
|
|
1615
|
+
* @module
|
|
1616
|
+
* @private
|
|
1617
|
+
*/
|
|
1618
|
+
function replaceNode(oldNode, newNode) {
|
|
1619
|
+
if (Element.prototype.moveBefore) {
|
|
1620
|
+
oldNode.parentNode.moveBefore(newNode, oldNode);
|
|
1621
|
+
oldNode.remove();
|
|
1622
|
+
} else {
|
|
1623
|
+
const activeElement = document.activeElement;
|
|
1624
|
+
oldNode.before(newNode);
|
|
1625
|
+
oldNode.remove();
|
|
1626
|
+
if (activeElement && activeElement !== document.activeElement && newNode.contains(activeElement)) {
|
|
1627
|
+
activeElement.focus();
|
|
1628
|
+
}
|
|
1629
|
+
}
|
|
1630
|
+
}
|
|
1631
|
+
|
|
1581
1632
|
/**
|
|
1582
1633
|
* Same as getResult, but pass context as argument to the expression.
|
|
1583
1634
|
* Used to evaluate expressions in the context of a component.
|
|
@@ -1598,13 +1649,13 @@
|
|
|
1598
1649
|
const isComponent = (el) => !!(el && el.dataset && el.dataset[Component.DATASET_ELEMENT] && el.dataset[Component.DATASET_ELEMENT].endsWith('-1'));
|
|
1599
1650
|
|
|
1600
1651
|
/**
|
|
1601
|
-
* Check if an element
|
|
1602
|
-
*
|
|
1652
|
+
* Check if an element contains a component.
|
|
1653
|
+
* It checks if the element is a component root element or if it contains a component.
|
|
1603
1654
|
* @param {Element} el The element to check.
|
|
1604
|
-
* @return {boolean} True if the element
|
|
1655
|
+
* @return {boolean} True if the element contains a component.
|
|
1605
1656
|
* @private
|
|
1606
1657
|
*/
|
|
1607
|
-
const
|
|
1658
|
+
const containsElement = (el) => !!(el && el.dataset && el.dataset[Component.DATASET_ELEMENT]) || !!el.querySelector(`[${Component.ATTRIBUTE_ELEMENT}]`);
|
|
1608
1659
|
|
|
1609
1660
|
/**
|
|
1610
1661
|
* Generate string with placeholders for interpolated expressions.
|
|
@@ -1979,17 +2030,23 @@
|
|
|
1979
2030
|
const PH = Component.PLACEHOLDER('(\\d+)');
|
|
1980
2031
|
const attributes = [];
|
|
1981
2032
|
// Parse attributes string with support for placeholders in both names and values.
|
|
1982
|
-
const regExp = new RegExp(`(
|
|
2033
|
+
const regExp = new RegExp(`(?:${PH}|([\\w-]+))(?:=(["']?)(?:${PH}|((?:.?(?!["']?\\s+(?:\\S+)=|\\s*/?[>"']))+.))?\\3)?`, 'g');
|
|
1983
2034
|
|
|
1984
2035
|
let attributeMatch;
|
|
1985
2036
|
while ((attributeMatch = regExp.exec(attributesStr)) !== null) {
|
|
1986
|
-
const [,
|
|
2037
|
+
const [, attributeIdx, attribute, quotes, valueIdx, value] = attributeMatch;
|
|
2038
|
+
|
|
2039
|
+
const hasQuotes = !!quotes;
|
|
1987
2040
|
|
|
1988
|
-
|
|
1989
|
-
|
|
2041
|
+
let attr = typeof attributeIdx !== 'undefined' ? expressions[parseInt(attributeIdx, 10)] : attribute;
|
|
2042
|
+
let val = typeof valueIdx !== 'undefined' ? expressions[parseInt(valueIdx, 10)] : value;
|
|
2043
|
+
|
|
2044
|
+
if (hasQuotes && typeof val === 'undefined') {
|
|
2045
|
+
val = '';
|
|
2046
|
+
}
|
|
1990
2047
|
|
|
1991
2048
|
if (typeof val !== 'undefined') {
|
|
1992
|
-
attributes.push([attr, val,
|
|
2049
|
+
attributes.push([attr, val, hasQuotes]);
|
|
1993
2050
|
} else {
|
|
1994
2051
|
attributes.push([attr]);
|
|
1995
2052
|
}
|
|
@@ -2175,9 +2232,8 @@
|
|
|
2175
2232
|
recycle(parent, props) {
|
|
2176
2233
|
if (parent) {
|
|
2177
2234
|
// Locate the placeholder comment and replace it with the real nodes
|
|
2178
|
-
const
|
|
2179
|
-
|
|
2180
|
-
toBeReplaced.replaceWith(this.el);
|
|
2235
|
+
const placeholder = findComment(parent, Component.MARKER_RECYCLED(this.uid), isComponent);
|
|
2236
|
+
replaceNode(placeholder, this.el);
|
|
2181
2237
|
}
|
|
2182
2238
|
// Update props.
|
|
2183
2239
|
if (props) {
|
|
@@ -2253,8 +2309,8 @@
|
|
|
2253
2309
|
/**
|
|
2254
2310
|
* Render a template part.
|
|
2255
2311
|
* @param {any} part - The template part.
|
|
2256
|
-
* @param {function} addChild - The addChild function.
|
|
2257
|
-
* @param {Array} items - The items array.
|
|
2312
|
+
* @param {function} addChild - The addChild function. It should handle children and return a HTML string.
|
|
2313
|
+
* @param {Array} items - The items array. It is used to store the items that are parsed.
|
|
2258
2314
|
* @return {string} The rendered template part.
|
|
2259
2315
|
* @private
|
|
2260
2316
|
*/
|
|
@@ -2316,6 +2372,24 @@
|
|
|
2316
2372
|
* Used internally on the render process.
|
|
2317
2373
|
* Use it for server-side rendering or static site generation.
|
|
2318
2374
|
* @return {string} The rendered component.
|
|
2375
|
+
* @example
|
|
2376
|
+
* import { Component } from 'rasti';
|
|
2377
|
+
* const Button = Component.create`
|
|
2378
|
+
* <button class="button">Click me</button>
|
|
2379
|
+
* `;
|
|
2380
|
+
* const App = Component.create`
|
|
2381
|
+
* <div>
|
|
2382
|
+
* <${Button}>Click me</${Button}>
|
|
2383
|
+
* </div>
|
|
2384
|
+
* `;
|
|
2385
|
+
*
|
|
2386
|
+
* const app = new App();
|
|
2387
|
+
*
|
|
2388
|
+
* console.log(app.toString());
|
|
2389
|
+
* // <div data-rasti-el="r1-1"><!--rasti-s-r1-1--><button class="button" data-rasti-el="r2-1">Click me</button><!--rasti-e-r1-1--></div>
|
|
2390
|
+
*
|
|
2391
|
+
* console.log(`${app}`);
|
|
2392
|
+
* // <div data-rasti-el="r1-1"><!--rasti-s-r1-1--><button class="button" data-rasti-el="r2-1">Click me</button><!--rasti-e-r1-1--></div>
|
|
2319
2393
|
*/
|
|
2320
2394
|
toString() {
|
|
2321
2395
|
// Normally there won't be any children, but if there are, destroy them.
|
|
@@ -2359,8 +2433,6 @@
|
|
|
2359
2433
|
this.eventsManager.reset();
|
|
2360
2434
|
// Reset position tracking.
|
|
2361
2435
|
this.pathManager.reset();
|
|
2362
|
-
// Store active element.
|
|
2363
|
-
const activeElement = this.isContainer() ? null : document.activeElement;
|
|
2364
2436
|
// Update elements.
|
|
2365
2437
|
this.template.elements.forEach(element => element.update());
|
|
2366
2438
|
// Store previous children.
|
|
@@ -2373,7 +2445,9 @@
|
|
|
2373
2445
|
const recycledChildren = [];
|
|
2374
2446
|
|
|
2375
2447
|
this.pathManager.increment();
|
|
2376
|
-
|
|
2448
|
+
// `addChild` handler is called from `renderTemplatePart` for every component.
|
|
2449
|
+
// It should handle children and return a HTML string.
|
|
2450
|
+
// In this case, where the component updates, it handles children recycling.
|
|
2377
2451
|
const addChild = component => {
|
|
2378
2452
|
let out = component;
|
|
2379
2453
|
let found = null;
|
|
@@ -2422,13 +2496,19 @@
|
|
|
2422
2496
|
}
|
|
2423
2497
|
// Parse the rendered content and get the fragment.
|
|
2424
2498
|
const fragment = parseHTML(rendered);
|
|
2425
|
-
|
|
2426
|
-
|
|
2427
|
-
|
|
2428
|
-
|
|
2429
|
-
|
|
2430
|
-
|
|
2431
|
-
|
|
2499
|
+
|
|
2500
|
+
const handleComponents = (parent) => () => {
|
|
2501
|
+
// Add recycled components to children and move them to the new template in the fragment.
|
|
2502
|
+
recycledChildren.forEach(recycled => recycle(recycled, parent));
|
|
2503
|
+
// Add new children. Hydrate them and update the interpolation.
|
|
2504
|
+
nextChildren.forEach(child => this.addChild(child).hydrate(parent));
|
|
2505
|
+
};
|
|
2506
|
+
|
|
2507
|
+
if (this.isContainer()) {
|
|
2508
|
+
interpolation.updateElement(this.el, fragment, handleComponents(this.el.parentNode));
|
|
2509
|
+
} else {
|
|
2510
|
+
interpolation.update(fragment, handleComponents(this.el));
|
|
2511
|
+
}
|
|
2432
2512
|
});
|
|
2433
2513
|
// Destroy unused children.
|
|
2434
2514
|
previousChildren.forEach(prev => {
|
|
@@ -2443,10 +2523,6 @@
|
|
|
2443
2523
|
this.delegateEvents();
|
|
2444
2524
|
}
|
|
2445
2525
|
}
|
|
2446
|
-
// Restore focus.
|
|
2447
|
-
if (activeElement && this.el.contains(activeElement)) {
|
|
2448
|
-
activeElement.focus();
|
|
2449
|
-
}
|
|
2450
2526
|
// Call onUpdate lifecycle method.
|
|
2451
2527
|
this.onUpdate.call(this);
|
|
2452
2528
|
// Return this for chaining.
|
|
@@ -2542,16 +2618,49 @@
|
|
|
2542
2618
|
}
|
|
2543
2619
|
|
|
2544
2620
|
/**
|
|
2545
|
-
* Mount the component into the
|
|
2546
|
-
*
|
|
2547
|
-
*
|
|
2548
|
-
*
|
|
2549
|
-
*
|
|
2621
|
+
* Mount the component into the DOM.
|
|
2622
|
+
* Creates a new component instance with the provided options and optionally mounts it into the DOM.
|
|
2623
|
+
*
|
|
2624
|
+
* **Mounting modes:**
|
|
2625
|
+
* - **Normal mount** (default): Renders the component as HTML and appends it to the provided element. Use this for client-side rendering.
|
|
2626
|
+
* - **Hydration mode**: Assumes the DOM already contains the component's HTML (from server-side rendering).
|
|
2627
|
+
*
|
|
2628
|
+
* If `el` is not provided, the component is instantiated but not mounted (the same as using `new Component(options)`). You can mount it later by calling `render()` and appending the element (`this.el`) to the DOM.
|
|
2629
|
+
*
|
|
2550
2630
|
* @static
|
|
2551
|
-
* @param {object} [options] The
|
|
2552
|
-
*
|
|
2553
|
-
* @param {
|
|
2631
|
+
* @param {object} [options={}] The component options. These will be passed to the constructor and can include
|
|
2632
|
+
* `model`, `state`, `props`, lifecycle methods, and any other component-specific options.
|
|
2633
|
+
* @param {node} [el] The DOM element where the component will be mounted. If provided, the component will be
|
|
2634
|
+
* rendered and appended to this element. If not provided, the component is created but not mounted.
|
|
2635
|
+
* @param {boolean} [hydrate=false] If `true`, enables hydration mode for server-side rendering. The component will
|
|
2636
|
+
* assume the DOM already contains its HTML structure and will only hydrate it.
|
|
2637
|
+
* If `false` (default), the component will be rendered from scratch and appended to `el`.
|
|
2554
2638
|
* @return {Component} The component instance.
|
|
2639
|
+
* @example
|
|
2640
|
+
* import { Component, Model } from 'rasti';
|
|
2641
|
+
*
|
|
2642
|
+
* const Button = Component.create`
|
|
2643
|
+
* <button class="${({ props }) => props.className}">
|
|
2644
|
+
* ${({ props }) => props.label}
|
|
2645
|
+
* </button>
|
|
2646
|
+
* `;
|
|
2647
|
+
*
|
|
2648
|
+
* // Normal mount: render and append to DOM.
|
|
2649
|
+
* const button = Button.mount({
|
|
2650
|
+
* label: 'Click me'
|
|
2651
|
+
* }, document.body);
|
|
2652
|
+
*
|
|
2653
|
+
* // Create without mounting (mount later).
|
|
2654
|
+
* const button2 = Button.mount({ className : 'secondary', label : 'Save' });
|
|
2655
|
+
* // Later, render and append it to the DOM.
|
|
2656
|
+
* document.body.appendChild(button2.render().el);
|
|
2657
|
+
*
|
|
2658
|
+
* // Hydration mode: hydrate existing server-rendered HTML
|
|
2659
|
+
* // Assuming document.body already contains the HTML structure of the button.
|
|
2660
|
+
* const hydratedButton = Button.mount({
|
|
2661
|
+
* className : 'primary',
|
|
2662
|
+
* label : 'Click me'
|
|
2663
|
+
* }, document.body, true);
|
|
2555
2664
|
*/
|
|
2556
2665
|
static mount(options, el, hydrate) {
|
|
2557
2666
|
// Instantiate component.
|
|
@@ -2559,14 +2668,14 @@
|
|
|
2559
2668
|
// If `el` is passed, mount component.
|
|
2560
2669
|
if (el) {
|
|
2561
2670
|
if (hydrate) {
|
|
2562
|
-
//
|
|
2671
|
+
// Hydrate existing DOM, only generate subcomponents calling `toString`.
|
|
2563
2672
|
component.toString();
|
|
2564
|
-
// Hydrate existing DOM.
|
|
2565
|
-
component.hydrate(el);
|
|
2566
2673
|
} else {
|
|
2567
|
-
//
|
|
2568
|
-
el.append(component
|
|
2674
|
+
// Render the component and append it to the provided element.
|
|
2675
|
+
el.append(parseHTML(component));
|
|
2569
2676
|
}
|
|
2677
|
+
// Hydrate in both cases.
|
|
2678
|
+
component.hydrate(el);
|
|
2570
2679
|
}
|
|
2571
2680
|
// Return component instance.
|
|
2572
2681
|
return component;
|
|
@@ -2723,7 +2832,7 @@
|
|
|
2723
2832
|
return this.extend({
|
|
2724
2833
|
template() {
|
|
2725
2834
|
return {
|
|
2726
|
-
elements : elements.map(element => new Element({
|
|
2835
|
+
elements : elements.map(element => new Element$1({
|
|
2727
2836
|
getSelector : element.getSelector.bind(this),
|
|
2728
2837
|
getAttributes : element.getAttributes.bind(this)
|
|
2729
2838
|
})),
|
|
@@ -2731,8 +2840,8 @@
|
|
|
2731
2840
|
getStart : interpolation.getStart.bind(this),
|
|
2732
2841
|
getEnd : interpolation.getEnd.bind(this),
|
|
2733
2842
|
expression : interpolation.expression,
|
|
2734
|
-
isComponent,
|
|
2735
|
-
|
|
2843
|
+
shouldSkipFind : isComponent,
|
|
2844
|
+
shouldSkipSync : containsElement
|
|
2736
2845
|
})),
|
|
2737
2846
|
parts,
|
|
2738
2847
|
};
|
|
@@ -2755,14 +2864,14 @@
|
|
|
2755
2864
|
/*
|
|
2756
2865
|
* Placeholders used to temporarily replace expressions in the template.
|
|
2757
2866
|
*/
|
|
2758
|
-
Component.PLACEHOLDER = (idx) => `
|
|
2867
|
+
Component.PLACEHOLDER = (idx) => `__RASTI_PH_${idx}__`;
|
|
2759
2868
|
|
|
2760
2869
|
/*
|
|
2761
2870
|
* Markers used to identify interpolation and recycled components.
|
|
2762
2871
|
*/
|
|
2763
|
-
Component.MARKER_RECYCLED = (uid) => `rasti-
|
|
2764
|
-
Component.MARKER_START = (uid) => `rasti-
|
|
2765
|
-
Component.MARKER_END = (uid) => `rasti-
|
|
2872
|
+
Component.MARKER_RECYCLED = (uid) => `rasti-r-${uid}`;
|
|
2873
|
+
Component.MARKER_START = (uid) => `rasti-s-${uid}`;
|
|
2874
|
+
Component.MARKER_END = (uid) => `rasti-e-${uid}`;
|
|
2766
2875
|
|
|
2767
2876
|
/**
|
|
2768
2877
|
* Components are a special kind of `View` that is designed to be easily composable,
|
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(){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 c{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 u=["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),u.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),u.includes(t)&&t in this.ref&&(this.ref[t]="value"===t?e:!1!==e&&"false"!==e)}))}}const d=["value","checked","selected"];function f(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=d.length;s<i;s++){const i=d[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 E{constructor(t){this.getStart=t.getStart,this.getEnd=t.getEnd,this.expression=t.expression,this.isComponent=t.isComponent,this.isElement=t.isElement,this.previousItems=[]}hydrate(t){const e=g(t,this.getStart(),this.isComponent),s=g(t,this.getEnd(),this.isComponent,e);this.ref=[e,s]}update(t,e){if(e)return void e.replaceWith(t.firstChild);const[s,i]=this.ref,n=s.nextSibling,r=n===i,h=!r&&n.nextSibling===i,o=t.children;if(r)i.parentNode.insertBefore(t,i);else if(h&&1===o.length)this.isElement(n)?n.replaceWith(o[0]):f(n,o[0]);else{const e=document.createRange();e.setStartAfter(s),e.setEndBefore(i),e.deleteContents(),e.insertNode(t)}}}const m=t=>t.reduce(((t,e)=>(Array.isArray(e)?t.push(...m(e)):t.push(e),t)),[]);function y(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 b=(t,e)=>i(t,e,e),v=t=>!!(t&&t.dataset&&t.dataset[_.DATASET_ELEMENT]&&t.dataset[_.DATASET_ELEMENT].endsWith("-1")),A=t=>!!(t&&t.dataset&&t.dataset[_.DATASET_ELEMENT]),R=(t,e)=>t.reduce(((t,s,i)=>(t.push(s),void 0!==e[i]&&t.push(_.PLACEHOLDER(i)),t)),[]).join(""),L=(t,e)=>{const s=_.PLACEHOLDER("(\\d+)"),i=t.match(new RegExp(`^${s}$`));if(i)return[e[parseInt(i[1],10)]];const n=new RegExp(`${s}`,"g"),r=[];let h,o=0;for(;null!==(h=n.exec(t));){const s=t.slice(o,h.index);r.push(_.markAsSafeHTML(s),e[parseInt(h[1],10)]),o=h.index+h[0].length}return r.push(_.markAsSafeHTML(t.slice(o))),r},C=(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}),{}),$=(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=_.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 _){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 _))return t;if(s){const t=S(r,e,!0),s=x(t,e);p=L(s,e)}const d=w(u,e);return e.push((function(){const t=C(d,(t=>b(t,this)));return p&&(t.renderChildren=()=>new a(p.map((t=>b(t,this))))),c.mount(t)})),_.PLACEHOLDER(e.length-1)}))},M=(t,e)=>{const s=_.PLACEHOLDER("(?:\\d+)");return t.replace(new RegExp(`<(${s}|[a-z]+[1-6]?)(?:\\s*)((?:"[^"]*"|'[^']*'|[^>])*)(/?>)`,"gi"),e)},O=(t,e,s)=>{const n=_.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 M(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=s.length;s.push({getSelector:function(){return`[${_.ATTRIBUTE_ELEMENT}="${p(this.uid)}"]`},getAttributes:function(){const t=$(C(u,(t=>b(t,this))),this.eventsManager,(t=>_.ATTRIBUTE_EVENT(t,this.uid)));return l&&this.attributes&&Object.assign(t,i(this.attributes,this)),t[_.ATTRIBUTE_ELEMENT]=p(this.uid),t}}),e.push((function(){const t=this.template.elements[d],e=t.getAttributes.call(this);return t.previousAttributes=e,_.markAsSafeHTML(T(e))}));return`<${h} ${_.PLACEHOLDER(e.length-1)}${a}`}))},x=(t,e)=>{const s=_.PLACEHOLDER("(?:\\d+)");return M(t,((t,i,n,r)=>{if(!n.match(new RegExp(s)))return t;const h=w(n,e),o=function(){return $(C(h,(t=>b(t,this))),this.eventsManager,(t=>_.ATTRIBUTE_EVENT(t,this.uid)))};e.push((function(){const t=o.call(this);return _.markAsSafeHTML(T(t))}));return`<${i} ${_.PLACEHOLDER(e.length-1)}${r}`}))},k=(t,e,s)=>{const i=_.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;const l=s.length;return s.push({getStart:function(){return _.MARKER_START(`${this.uid}-${a}`)},getEnd:function(){return _.MARKER_END(`${this.uid}-${a}`)},expression:e[r]}),e.push((function(){return this.template.interpolations[l]})),_.PLACEHOLDER(e.length-1)}))},w=(t,e)=>{const s=_.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},N=["key","state","onCreate","onChange","onHydrate","onRecycle","onUpdate"];class _ extends h{constructor(t={}){super(...arguments),this.componentOptions=[],N.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=_.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 l,this.pathManager=new c,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.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,e){if(t){g(t,_.MARKER_RECYCLED(this.uid),v).replaceWith(this.el)}return e&&this.props.set(e),this.onRecycle.call(this),this}getRecycledMarker(){return`\x3c!--${_.MARKER_RECYCLED(this.uid)}--\x3e`}partial(t,...e){const s=L(x(S(R(t,e).trim(),e),e),e).map((t=>b(t,this)));return new a(s)}renderTemplatePart(t,e,s=[]){const i=b(t,this),n=t=>{if(null==t||!1===t||!0===t)return"";if(t instanceof o)return s.push(t),t;if(t instanceof _)return s.push(t),e(t);if(t instanceof a){if(1===t.items.length)return n(t.items[0]);this.pathManager.push();const e=t.items.map((t=>(this.pathManager.increment(),n(t)))).join("");return this.pathManager.pop(),e}if(Array.isArray(t)){this.pathManager.pause();const e=m(t).map(n).join("");return this.pathManager.resume(),e}if(t instanceof E){this.pathManager.increment();const e=this.isContainer()?"":`\x3c!--${t.getStart()}--\x3e`,i=this.isContainer()?"":`\x3c!--${t.getEnd()}--\x3e`,r=n(b(t.expression,this));return t.previousItems=s,`${e}${r}${i}`}const i=_.sanitize(t);return s.push(i),i};return`${n(i)}`}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=y(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.previousItems,r=[],h=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}),r);t.previousItems=r;const o=([t,e],s)=>{this.addChild(t).recycle(s,e.props.toJSON()),e.destroy()};if(1===n.length&&n[0]instanceof _&&1===r.length&&r[0]instanceof _&&1===i.length)return void o(i[0],null);const a=y(h);i.forEach((t=>o(t,a))),s.forEach((t=>this.addChild(t).hydrate(a)));const l=this.isContainer()?this.el:null;t.update(a,l)})),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(){}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().el)),i}static create(t,...e){"function"==typeof t&&(e=[t],t=["",""]);const s=[],i=[],n=L(k(O(S(R(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 E({getStart:t.getStart.bind(this),getEnd:t.getEnd.bind(this),expression:t.expression,isComponent:v,isElement:A}))),parts:n}}})}}_.ATTRIBUTE_ELEMENT="data-rasti-el",_.ATTRIBUTE_EVENT=(t,e)=>`data-rasti-on-${t}-${e}`,_.DATASET_ELEMENT="rastiEl",_.PLACEHOLDER=t=>`__RASTI-${t}__`,_.MARKER_RECYCLED=t=>`rasti-recycled-${t}`,_.MARKER_START=t=>`rasti-start-${t}`,_.MARKER_END=t=>`rasti-end-${t}`;var j=_.create`<div></div>`;t.Component=j,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.remove(),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(){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 c{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 u=["value","checked","selected"];let d=class{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),u.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),u.includes(t)&&t in this.ref&&(this.ref[t]="value"===t?e:!1!==e&&"false"!==e)}))}};const p=["value","checked","selected"];function f(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=p.length;s<i;s++){const i=p[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 E{constructor(t){this.getStart=t.getStart,this.getEnd=t.getEnd,this.expression=t.expression,this.shouldSkipFind=t.shouldSkipFind,this.shouldSkipSync=t.shouldSkipSync,this.previousItems=[]}hydrate(t){const e=g(t,this.getStart(),this.shouldSkipFind),s=g(t,this.getEnd(),this.shouldSkipFind,e);this.ref=[e,s]}update(t,e){let s;const[i,n]=this.ref,r=i.nextSibling,h=r===n,o=!h&&r.nextSibling===n;if(h?n.before(t):!o||1!==t.children.length||this.shouldSkipSync(r)||this.shouldSkipSync(t.firstChild)?(s=document.createComment(""),n.before(s),n.before(t)):f(r,t.firstChild),e(),s){if(this.ref[0].nextSibling===s)s.remove();else{const t=document.createRange();t.setStartAfter(this.ref[0]),t.setEndAfter(s),t.deleteContents()}}}updateElement(t,e,s){const i=document.createComment("");t.after(i),i.after(e.firstChild),s(),t.nextSibling===i&&t.remove(),i.remove()}}const m=t=>t.reduce(((t,e)=>(Array.isArray(e)?t.push(...m(e)):t.push(e),t)),[]);function y(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 T=(t,e)=>i(t,e,e),v=t=>!!(t&&t.dataset&&t.dataset[N.DATASET_ELEMENT]&&t.dataset[N.DATASET_ELEMENT].endsWith("-1")),A=t=>!!(t&&t.dataset&&t.dataset[N.DATASET_ELEMENT])||!!t.querySelector(`[${N.ATTRIBUTE_ELEMENT}]`),S=(t,e)=>t.reduce(((t,s,i)=>(t.push(s),void 0!==e[i]&&t.push(N.PLACEHOLDER(i)),t)),[]).join(""),R=(t,e)=>{const s=N.PLACEHOLDER("(\\d+)"),i=t.match(new RegExp(`^${s}$`));if(i)return[e[parseInt(i[1],10)]];const n=new RegExp(`${s}`,"g"),r=[];let h,o=0;for(;null!==(h=n.exec(t));){const s=t.slice(o,h.index);r.push(N.markAsSafeHTML(s),e[parseInt(h[1],10)]),o=h.index+h[0].length}return r.push(N.markAsSafeHTML(t.slice(o))),r},L=(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}),{}),$=(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},C=(t,e,s=!1)=>{const i=N.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 N){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 N))return t;if(s){const t=C(r,e,!0),s=x(t,e);d=R(s,e)}const p=_(u,e);return e.push((function(){const t=L(p,(t=>T(t,this)));return d&&(t.renderChildren=()=>new a(d.map((t=>T(t,this))))),c.mount(t)})),N.PLACEHOLDER(e.length-1)}))},M=(t,e)=>{const s=N.PLACEHOLDER("(?:\\d+)");return t.replace(new RegExp(`<(${s}|[a-z]+[1-6]?)(?:\\s*)((?:"[^"]*"|'[^']*'|[^>])*)(/?>)`,"gi"),e)},k=(t,e,s)=>{const n=N.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 M(t,((t,h,o,a)=>{const l=0===r,c=++r;if(!l&&!o.match(new RegExp(n)))return t;const u=_(o,e),d=t=>`${t}-${c}`,p=s.length;s.push({getSelector:function(){return`[${N.ATTRIBUTE_ELEMENT}="${d(this.uid)}"]`},getAttributes:function(){const t=$(L(u,(t=>T(t,this))),this.eventsManager,(t=>N.ATTRIBUTE_EVENT(t,this.uid)));return l&&this.attributes&&Object.assign(t,i(this.attributes,this)),t[N.ATTRIBUTE_ELEMENT]=d(this.uid),t}}),e.push((function(){const t=this.template.elements[p],e=t.getAttributes.call(this);return t.previousAttributes=e,N.markAsSafeHTML(b(e))}));return`<${h} ${N.PLACEHOLDER(e.length-1)}${a}`}))},x=(t,e)=>{const s=N.PLACEHOLDER("(?:\\d+)");return M(t,((t,i,n,r)=>{if(!n.match(new RegExp(s)))return t;const h=_(n,e),o=function(){return $(L(h,(t=>T(t,this))),this.eventsManager,(t=>N.ATTRIBUTE_EVENT(t,this.uid)))};e.push((function(){const t=o.call(this);return N.markAsSafeHTML(b(t))}));return`<${i} ${N.PLACEHOLDER(e.length-1)}${r}`}))},O=(t,e,s)=>{const i=N.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;const l=s.length;return s.push({getStart:function(){return N.MARKER_START(`${this.uid}-${a}`)},getEnd:function(){return N.MARKER_END(`${this.uid}-${a}`)},expression:e[r]}),e.push((function(){return this.template.interpolations[l]})),N.PLACEHOLDER(e.length-1)}))},_=(t,e)=>{const s=N.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=!!n;let l=void 0!==t?e[parseInt(t,10)]:s,c=void 0!==h?e[parseInt(h,10)]:o;a&&void 0===c&&(c=""),void 0!==c?i.push([l,c,a]):i.push([l])}return i},w=["key","state","onCreate","onChange","onHydrate","onRecycle","onUpdate"];class N extends h{constructor(t={}){super(...arguments),this.componentOptions=[],w.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=N.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 l,this.pathManager=new c,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.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,e){if(t){!function(t,e){if(Element.prototype.moveBefore)t.parentNode.moveBefore(e,t),t.remove();else{const s=document.activeElement;t.before(e),t.remove(),s&&s!==document.activeElement&&e.contains(s)&&s.focus()}}(g(t,N.MARKER_RECYCLED(this.uid),v),this.el)}return e&&this.props.set(e),this.onRecycle.call(this),this}getRecycledMarker(){return`\x3c!--${N.MARKER_RECYCLED(this.uid)}--\x3e`}partial(t,...e){const s=R(x(C(S(t,e).trim(),e),e),e).map((t=>T(t,this)));return new a(s)}renderTemplatePart(t,e,s=[]){const i=T(t,this),n=t=>{if(null==t||!1===t||!0===t)return"";if(t instanceof o)return s.push(t),t;if(t instanceof N)return s.push(t),e(t);if(t instanceof a){if(1===t.items.length)return n(t.items[0]);this.pathManager.push();const e=t.items.map((t=>(this.pathManager.increment(),n(t)))).join("");return this.pathManager.pop(),e}if(Array.isArray(t)){this.pathManager.pause();const e=m(t).map(n).join("");return this.pathManager.resume(),e}if(t instanceof E){this.pathManager.increment();const e=this.isContainer()?"":`\x3c!--${t.getStart()}--\x3e`,i=this.isContainer()?"":`\x3c!--${t.getEnd()}--\x3e`,r=n(T(t.expression,this));return t.previousItems=s,`${e}${r}${i}`}const i=N.sanitize(t);return s.push(i),i};return`${n(i)}`}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=y(this);return this.hydrate(t),this}this.eventsManager.reset(),this.pathManager.reset(),this.template.elements.forEach((t=>t.update()));const t=this.children;return this.children=[],this.template.interpolations.forEach((e=>{const s=[],i=[];this.pathManager.increment();const n=e.previousItems,r=[],h=this.renderTemplatePart(e.expression,(e=>{let n=e,r=null;return r=e.key?t.find((t=>t.key===e.key)):this.pathManager.findRecyclable(e.constructor),r?(n=r.getRecycledMarker(),i.push([r,e]),r.key||this.pathManager.track(r)):(s.push(e),this.pathManager.track(e)),n}),r);e.previousItems=r;const o=([t,e],s)=>{this.addChild(t).recycle(s,e.props.toJSON()),e.destroy()};if(1===n.length&&n[0]instanceof N&&1===r.length&&r[0]instanceof N&&1===i.length)return void o(i[0],null);const a=y(h),l=t=>()=>{i.forEach((e=>o(e,t))),s.forEach((e=>this.addChild(e).hydrate(t)))};this.isContainer()?e.updateElement(this.el,a,l(this.el.parentNode)):e.update(a,l(this.el))})),t.forEach((t=>{this.children.indexOf(t)<0&&t.destroy()})),this.isContainer()?this.el=this.children[0].el:this.eventsManager.hasPendingTypes()&&this.delegateEvents(),this.onUpdate.call(this),this}onCreate(){}onChange(){this.render()}onHydrate(){}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():e.append(y(i)),i.hydrate(e)),i}static create(t,...e){"function"==typeof t&&(e=[t],t=["",""]);const s=[],i=[],n=R(O(k(C(S(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 E({getStart:t.getStart.bind(this),getEnd:t.getEnd.bind(this),expression:t.expression,shouldSkipFind:v,shouldSkipSync:A}))),parts:n}}})}}N.ATTRIBUTE_ELEMENT="data-rasti-el",N.ATTRIBUTE_EVENT=(t,e)=>`data-rasti-on-${t}-${e}`,N.DATASET_ELEMENT="rastiEl",N.PLACEHOLDER=t=>`__RASTI_PH_${t}__`,N.MARKER_RECYCLED=t=>`rasti-r-${t}`,N.MARKER_START=t=>`rasti-s-${t}`,N.MARKER_END=t=>`rasti-e-${t}`;var j=N.create`<div></div>`;t.Component=j,t.Emitter=s,t.Model=n,t.View=h}));
|