Creating a plugin is very easy. In a javascript file, return a class defining your plugin, and set some default options if needed.
return class Plugin extends BasePlugin {
constructor(id, options) {
super(id, options, {
fontsize: 10,
color: "purple",
});
}
render = async () => {
// create some ui
};
bind = async () => {
// bind ui
};
};
When a plugin is registered, it goes through the following optionnal life cycles, each of them giving you an opportunity to define your plugin.
await plugins.init();
await plugins.deps();
await plugins.style();
await plugins.render();
await plugins.transform();
await plugins.bind();
Some plugins may require some initialisation before they get rendered. In that case, just provide an init method to your plugin class.
init function, the lifecycle will continue as normal.init function returns false, then the lifecycle will stop and the plugin won't be registered.init = async () => {
// do stuff, load config
// if everything ok, return true
// else return false
return true
}
The deps method let you include external dependencies, like js et css files. The method can be a flat array, or a function, if you need access to props.
deps: [
"https://cdn.jsdelivr.net/lib.js",
"https://cdn.jsdelivr.net/theme-v2.css"
]
// or dynamically
deps: async () => [
"https://url.com/lib.js",
`https://url.com/theme-v${this.options.version}.css`
]
It's also possible to push a depedency inside the constructor:
constructor(id: string, options) {
super(id, options);
this.deps.push("https://url.com/lib.js");
}
The style function is where you style your components. You can write vanilla css, or lesscss.
style = async () => `
[id="toc.list"] {
ul {
padding: 0;
margin: 0;
li {
list-style: none;
&:hover {
background: red;
}
}
}
}
@media (max-width: 576px) {
[id="toc.list"] {
display: none;
}
}
/* conditional render */
${this.options.color == "red" ? `
[id="toc.list"] {
ul {
background: ${this.options.color};
}
}
` : ""}
`;
The render method is where you can register UI components.
render = async () => {
const { ui, options } = this;
const cta = `<i class="bx bx-dollar"></i>`
const modal = `
<input type="text" value="${options.amount}" />
<button data-click="$stripe.pay()">
Pay Order
</button>
`;
ui.addModal("my-modal", modal);
ui.addElement("my-cta", "header.right", cta);
}
This is where it's appropriate to do all kind of dom manipulation. All plugins have rendered, but can still be transformed.
transform = async () => {
const { $dom, $utils } = window;
const headings = $dom.body.find("h1, h2, h3");
headings.each(function () {
const slug = $utils.s.slugify($(this).text());
this.id = "heading-" + slug;
});
}
The bind method is the last cycle, and is where you bind your UI components and make them dynamic.
bind = async () => {
const { ui } = this;
const cta = ui.get("my-cta")
const modal = ui.get("my-modal")
cta.el.on("click", function(){
modal.open()
})
}
More on building UI later !