Concepts
Capsules
A capsule is the smallest unit of behaviour in tiny-engine. It owns one DOM element, refs, props, events, and cleanup.
The two forms
Every capsule can be written either as a class extending Capsule or as a plain function. They share the same core primitives; use whichever form reads better in your codebase.
Class form
import { Capsule } from "tiny-engine-core";
class Tabs extends Capsule {
static defaults = {
activeIndex: 0,
};
constructor(el, options) {
super(el, options);
this.onPropChange("activeIndex", (next, previous) => {
console.log("tab changed", previous, next);
});
this.on(this.el, "click", (event) => {
const tab = event.target.closest("[data-tab]");
if (tab) this.props.activeIndex = Number(tab.dataset.tab);
});
}
}Functional form
UI.register("tabs", (el, api) => {
function setActive(index) {
api.props.activeIndex = index;
api.refs.panel.textContent = `Active tab: ${index}`;
}
api.on(el, "click", (event) => {
const tab = event.target.closest("[data-tab]");
if (tab) setActive(Number(tab.dataset.tab));
});
return {
setActive,
syncOptions(nextOptions) {
setActive(Number(nextOptions.activeIndex ?? 0));
},
};
});Refs
Any root or descendant with a ref attribute is collected into refs. Ref lookup is lazy, so newly inserted refs can be found after refresh() or observer updates.
<div ui-gallery>
<button ref="prev">Previous</button>
<ul ref="track">
<li>A</li>
<li>B</li>
</ul>
<button ref="next">Next</button>
</div>
this.refs.prev // HTMLButtonElement
this.refs.next // HTMLButtonElement
this.refs.track // HTMLUListElementProps and options
The marker attribute can hold JSON options, and {prefix}-{name}-* attributes become camelCased props. Values are parsed as booleans, numbers, JSON, or strings.
<div
ui-tabs
ui-tabs-active-index="2"
ui-tabs-options='{"orientation":"vertical"}'
>
<div ref="panel"></div>
</div>becomes:
this.props.activeIndex === 2;
this.props.options.orientation === "vertical";