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 !