rasti 4.0.0 → 4.0.1
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 +6 -6
- package/dist/rasti.js +41 -41
- package/dist/rasti.js.map +1 -1
- package/dist/rasti.min.js +1 -1
- package/dist/rasti.min.js.map +1 -1
- package/es/Component.js +14 -17
- package/es/Component.js.map +1 -1
- package/es/View.js +30 -27
- package/es/View.js.map +1 -1
- package/lib/Component.cjs +14 -17
- package/lib/Component.cjs.map +1 -1
- package/lib/View.cjs +30 -27
- package/lib/View.cjs.map +1 -1
- package/package.json +6 -6
- package/src/Component.js +12 -15
- package/src/View.js +30 -24
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.
|
|
4
|
-
<img alt="Rasti.js" src="https://cdn.jsdelivr.net/gh/8tentaculos/rasti@v4.0.
|
|
3
|
+
<source media="(prefers-color-scheme: dark)" srcset="https://cdn.jsdelivr.net/gh/8tentaculos/rasti@v4.0.1/docs/logo-dark.svg">
|
|
4
|
+
<img alt="Rasti.js" src="https://cdn.jsdelivr.net/gh/8tentaculos/rasti@v4.0.1/docs/logo.svg" height="120">
|
|
5
5
|
</picture>
|
|
6
6
|
</p>
|
|
7
7
|
|
|
@@ -58,8 +58,8 @@ import { Model, Component } from 'https://esm.run/rasti';
|
|
|
58
58
|
|
|
59
59
|
Include **Rasti** directly in your HTML using a CDN. Available UMD builds:
|
|
60
60
|
|
|
61
|
-
- [
|
|
62
|
-
- [
|
|
61
|
+
- [rasti.js](https://cdn.jsdelivr.net/npm/rasti/dist/rasti.js)
|
|
62
|
+
- [rasti.min.js](https://cdn.jsdelivr.net/npm/rasti/dist/rasti.min.js)
|
|
63
63
|
|
|
64
64
|
```html
|
|
65
65
|
<script src="https://cdn.jsdelivr.net/npm/rasti"></script>
|
|
@@ -123,7 +123,7 @@ const Navigation = Component.create`
|
|
|
123
123
|
// Create a Main component that includes the Navigation and displays the current route's label as the title.
|
|
124
124
|
const Main = Component.create`
|
|
125
125
|
<main>
|
|
126
|
-
<${Navigation} routes
|
|
126
|
+
<${Navigation} routes="${({ props }) => props.routes}" />
|
|
127
127
|
<section>
|
|
128
128
|
<h1>
|
|
129
129
|
${({ model, props }) => props.routes.find(
|
|
@@ -179,7 +179,7 @@ Counter.mount({ model }, document.body);
|
|
|
179
179
|
- **Lightweight and Efficient**
|
|
180
180
|
Minimal footprint with optimized performance, ensuring smooth updates.
|
|
181
181
|
- **Just the Right Abstraction**
|
|
182
|
-
Keeps you close to the DOM with no over-engineering. Fully hackable
|
|
182
|
+
Keeps you close to the DOM with no over-engineering. Fully hackable, if you're curious about how something works, just check the source code.
|
|
183
183
|
|
|
184
184
|
## Example
|
|
185
185
|
|
package/dist/rasti.js
CHANGED
|
@@ -1031,12 +1031,17 @@
|
|
|
1031
1031
|
if (this.delegatedEventListeners.length) this.undelegateEvents();
|
|
1032
1032
|
|
|
1033
1033
|
// Store events by type i.e.: "click", "submit", etc.
|
|
1034
|
-
|
|
1034
|
+
const eventTypes = {};
|
|
1035
1035
|
|
|
1036
1036
|
Object.keys(events).forEach(key => {
|
|
1037
|
-
const
|
|
1038
|
-
|
|
1039
|
-
|
|
1037
|
+
const match = key.match(/^(\w+)(?:\s+(.+))*$/);
|
|
1038
|
+
|
|
1039
|
+
if (!match) {
|
|
1040
|
+
const message = `Invalid event format: ${key}`;
|
|
1041
|
+
throw new Error(createDevelopmentErrorMessage(message) );
|
|
1042
|
+
}
|
|
1043
|
+
// Extract type and selector from the event key.
|
|
1044
|
+
const [,type, selector] = match;
|
|
1040
1045
|
|
|
1041
1046
|
let listener = events[key];
|
|
1042
1047
|
// Listener may be a string representing a method name on the view, or a function.
|
|
@@ -1046,32 +1051,30 @@
|
|
|
1046
1051
|
|
|
1047
1052
|
if (!eventTypes[type]) eventTypes[type] = [];
|
|
1048
1053
|
|
|
1049
|
-
eventTypes[type].push(
|
|
1054
|
+
eventTypes[type].push([selector, listener]);
|
|
1050
1055
|
});
|
|
1051
1056
|
|
|
1052
1057
|
Object.keys(eventTypes).forEach(type => {
|
|
1053
1058
|
// Listener for the type of event.
|
|
1054
1059
|
const typeListener = (event) => {
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
if (
|
|
1059
|
-
listener
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
|
|
1064
|
-
|
|
1065
|
-
while (node && node !== this.el) {
|
|
1066
|
-
if (node.matches && node.matches(selector)) {
|
|
1067
|
-
listener.call(this, event, this, node);
|
|
1068
|
-
}
|
|
1069
|
-
node = node.parentElement;
|
|
1060
|
+
let node = event.target;
|
|
1061
|
+
// Traverse ancestors until reaching the view root (`this.el`).
|
|
1062
|
+
while (node) {
|
|
1063
|
+
if (node.matches) {
|
|
1064
|
+
// Iterate and run every individual listener if the selector matches.
|
|
1065
|
+
eventTypes[type].forEach(([selector, listener]) => {
|
|
1066
|
+
if ((node === this.el && !selector) || (node !== this.el && node.matches(selector))) {
|
|
1067
|
+
listener.call(this, event, this, node);
|
|
1068
|
+
}
|
|
1069
|
+
});
|
|
1070
1070
|
}
|
|
1071
|
-
|
|
1071
|
+
// Continue traversing ancestors until reaching the view root (`this.el`) or stopping propagation.
|
|
1072
|
+
node = node === this.el || event.cancelBubble ? null : node.parentElement;
|
|
1073
|
+
}
|
|
1072
1074
|
};
|
|
1073
|
-
|
|
1074
|
-
this.delegatedEventListeners.push(
|
|
1075
|
+
// Store the type and listener in the delegated event listeners array.
|
|
1076
|
+
this.delegatedEventListeners.push([type, typeListener]);
|
|
1077
|
+
// Add the event listener to the element.
|
|
1075
1078
|
this.el.addEventListener(type, typeListener);
|
|
1076
1079
|
});
|
|
1077
1080
|
// Return `this` for chaining.
|
|
@@ -1085,7 +1088,7 @@
|
|
|
1085
1088
|
* @return {View} Return `this` for chaining.
|
|
1086
1089
|
*/
|
|
1087
1090
|
undelegateEvents() {
|
|
1088
|
-
this.delegatedEventListeners.forEach((
|
|
1091
|
+
this.delegatedEventListeners.forEach(([type, listener]) => {
|
|
1089
1092
|
this.el.removeEventListener(type, listener);
|
|
1090
1093
|
});
|
|
1091
1094
|
|
|
@@ -1944,15 +1947,12 @@
|
|
|
1944
1947
|
const isComponent = (el) => !!(el && el.dataset && el.dataset[Component.DATASET_ELEMENT] && el.dataset[Component.DATASET_ELEMENT].endsWith('-1'));
|
|
1945
1948
|
|
|
1946
1949
|
/**
|
|
1947
|
-
* Check if an element contains a
|
|
1948
|
-
* It checks if the element is a component root element or if it contains a component.
|
|
1950
|
+
* Check if an element contains (or is) a dynamic element.
|
|
1949
1951
|
* @param {Element} el The element to check.
|
|
1950
|
-
* @return {boolean} True if the element contains a
|
|
1952
|
+
* @return {boolean} True if the element contains (or is) a dynamic element.
|
|
1951
1953
|
* @private
|
|
1952
1954
|
*/
|
|
1953
|
-
const containsElement = (el) => !!(
|
|
1954
|
-
el && ((el.dataset && el.dataset[Component.DATASET_ELEMENT]) || (el.querySelector && el.querySelector(`[${Component.ATTRIBUTE_ELEMENT}]`)))
|
|
1955
|
-
);
|
|
1955
|
+
const containsElement = (el) => !!(el && ((el.dataset && el.dataset[Component.DATASET_ELEMENT]) || (el.querySelector && el.querySelector(`[${Component.ATTRIBUTE_ELEMENT}]`))));
|
|
1956
1956
|
|
|
1957
1957
|
/**
|
|
1958
1958
|
* Generate string with placeholders for interpolated expressions.
|
|
@@ -2525,12 +2525,12 @@
|
|
|
2525
2525
|
element.hydrate(this.el);
|
|
2526
2526
|
}
|
|
2527
2527
|
});
|
|
2528
|
-
// Delegate events.
|
|
2529
|
-
this.delegateEvents();
|
|
2530
2528
|
// Get references for interpolation marker comments
|
|
2531
2529
|
this.template.interpolations.forEach(interpolation => interpolation.hydrate(this.el));
|
|
2532
2530
|
this.children.forEach(child => child.hydrate(this.el));
|
|
2533
2531
|
}
|
|
2532
|
+
// Delegate events.
|
|
2533
|
+
this.delegateEvents();
|
|
2534
2534
|
// Call `onHydrate` lifecycle method.
|
|
2535
2535
|
this.onHydrate.call(this);
|
|
2536
2536
|
// Return `this` for chaining.
|
|
@@ -2693,7 +2693,7 @@
|
|
|
2693
2693
|
|
|
2694
2694
|
/**
|
|
2695
2695
|
* Render the component as a string.
|
|
2696
|
-
* Used internally on the render process.
|
|
2696
|
+
* Used internally on the render process.
|
|
2697
2697
|
* Use it for server-side rendering or static site generation.
|
|
2698
2698
|
* @return {string} The rendered component.
|
|
2699
2699
|
* @example
|
|
@@ -2710,10 +2710,10 @@
|
|
|
2710
2710
|
* const app = new App();
|
|
2711
2711
|
*
|
|
2712
2712
|
* console.log(app.toString());
|
|
2713
|
-
* // <div data-
|
|
2713
|
+
* // <div data-rst-el="r1-1"><!--rst-s-r1-1--><button class="button" data-rst-el="r2-1">Click me</button><!--rst-e-r1-1--></div>
|
|
2714
2714
|
*
|
|
2715
2715
|
* console.log(`${app}`);
|
|
2716
|
-
* // <div data-
|
|
2716
|
+
* // <div data-rst-el="r1-1"><!--rst-s-r1-1--><button class="button" data-rst-el="r2-1">Click me</button><!--rst-e-r1-1--></div>
|
|
2717
2717
|
*/
|
|
2718
2718
|
toString() {
|
|
2719
2719
|
// Normally there won't be any children, but if there are, destroy them.
|
|
@@ -2875,10 +2875,10 @@
|
|
|
2875
2875
|
} else {
|
|
2876
2876
|
// Update elements attributes.
|
|
2877
2877
|
this.template.elements.forEach(element => element.update());
|
|
2878
|
-
|
|
2879
|
-
|
|
2880
|
-
|
|
2881
|
-
|
|
2878
|
+
}
|
|
2879
|
+
// If there are pending event types, delegate events again.
|
|
2880
|
+
if (this.eventsManager.hasPendingTypes()) {
|
|
2881
|
+
this.delegateEvents();
|
|
2882
2882
|
}
|
|
2883
2883
|
// Call onUpdate lifecycle method.
|
|
2884
2884
|
this.onUpdate.call(this);
|
|
@@ -3283,9 +3283,9 @@
|
|
|
3283
3283
|
* // Increment `model.seconds` every second.
|
|
3284
3284
|
* setInterval(() => model.seconds++, 1000);
|
|
3285
3285
|
*/
|
|
3286
|
-
var
|
|
3286
|
+
var Component_default = Component.create`<div></div>`;
|
|
3287
3287
|
|
|
3288
|
-
exports.Component =
|
|
3288
|
+
exports.Component = Component_default;
|
|
3289
3289
|
exports.Emitter = Emitter;
|
|
3290
3290
|
exports.Model = Model;
|
|
3291
3291
|
exports.View = View;
|