I appreciate the sentiment; while this is, indeed, a paper, it is not a published or peer-reviewed paper. I wrote it with no intention of actually publishing it anywhere, and putting it on Arxiv is better long-term than putting it into Github or similar (I expect Arxiv to outlive any code forge).
In much the same way that I looked at web components and thought "What a nice idea. Here is how I can make this incrementally better and support client-side includes as well", I am hoping that this 100-lines of code will someday be looked at by someone else, who will (with the benefit of future knowledge and tech), then say "What a nice idea. Here is how I can make this incrementally better AND support <some future feature we cannot see right now>".
In any case, I thank you for your criticism and your time; your criticism can only make this better (for example, after reading your criticism, I think that showing a side-by-side comparison of my counter example with a custom element doing the same thing will make it more obvious why I find zjs-components more pleasant to write and use than Custom Elements).
Cheers :-)
[EDIT: Here is the comparison, in case you are still curious]
Here is the small comparison; I gave ChatGPT the ZjsComponent README.md and got it to write the example in the README as a custom element web component.
Here are the two implementations:
Implementation as a zjs-component:
<div>
Counter Value: <span name=counter-value>0</span>
</div>
<div>
<button onclick='ZjsComponent.send(this, "increment", 1)'> +1 </button>
<button onclick='ZjsComponent.send(this, "increment", 2)'> +2 </button>
<button onclick='ZjsComponent.send(this, "increment", 5)'> +5 </button>
</div>
<script>
function increment(amount) {
const el = this.querySelector("[name='counter-value']");
el.textContent = parseInt(el.textContent) + amount;
}
exports.increment = increment;
</script>
Usage of zjs-component: <zjs-component remote-src=counter.zjsc> </zjs-component>
Implementation as a custom element web component: <!-- counter-component.js -->
<script>
class CounterComponent extends HTMLElement {
constructor() {
super();
this.attachShadow({ mode: 'open' });
this.shadowRoot.innerHTML = `
<div>
Counter Value: <span id="counter-value">0</span>
</div>
<div>
<button data-amount="1"> +1 </button>
<button data-amount="2"> +2 </button>
<button data-amount="5"> +5 </button>
</div>
`;
}
connectedCallback() {
this.shadowRoot.querySelectorAll('button').forEach(btn => {
btn.addEventListener('click', () => {
const amount = parseInt(btn.getAttribute('data-amount'), 10);
this.increment(amount);
});
});
}
increment(amount) {
const valueEl = this.shadowRoot.getElementById('counter-value');
valueEl.textContent = parseInt(valueEl.textContent, 10) + amount;
}
}
customElements.define('counter-component', CounterComponent);
</script>
Usage of the custom element web component: <counter-component></counter-component>