Plugin
API رسمی برای افزودن قابلیت از بیرون: یک شیء ساده با name و install(api). همهچیزی که Plugin اضافه میکند (کنترلر، شنونده، استایل) با Bana.unuse(name) دقیقاً برداشته میشود و نصب ناموفق بهطور کامل برگردانده میشود.
<label ui="field"><span>توضیحات (حداکثر ۶۰ نویسه)</span><textarea data-counter maxlength="60" placeholder="چیزی بنویسید"></textarea></label>
const charCounter = {
name: 'char-counter',
version: '1.0.0',
requires: { bana: '>=0.1.0' },
install(api, { warnAt = 10 } = {}) {
const fa = (n) => n.toLocaleString('fa');
const update = (el, out) => {
const max = el.maxLength, n = [...el.value].length;
out.textContent = max > 0 ? `${fa(n)} از ${fa(max)} نویسه` : `${fa(n)} نویسه`;
out.dataset.near = String(max > 0 && max - n <= warnAt);
};
api.controller({
init(root, signal) {
root.querySelectorAll('[data-counter]:not([data-counter-ready])').forEach((el) => {
el.setAttribute('data-counter-ready', '');
const out = document.createElement('small');
out.setAttribute('data-counter-output', '');
el.after(out);
update(el, out);
el.addEventListener('input', () => update(el, out), { signal });
});
},
destroy(root) {
root.querySelectorAll('[data-counter-output]').forEach((o) => o.remove());
root.querySelectorAll('[data-counter-ready]').forEach((e) => e.removeAttribute('data-counter-ready'));
},
});
api.styles('[data-counter-output][data-near="true"] { color: var(--bana-danger-text); font-weight: var(--bana-weight-medium); }');
},
};import { Bana } from "@bana-ui/core";
Bana.use(charCounter, { warnAt: 10 }).start(); // use() works before or after start()
Bana.plugins; // [{ name: "char-counter", version: "1.0.0" }]
Bana.unuse("char-counter"); // controller, listeners and styles are removedعضو api | کار |
|---|---|
| api.controller({ init, destroy }) | همان کنترلر Bana؛ روی start() و refresh() اجرا میشود. |
| api.on(type, handler) | شنونده روی document که با unuse خودکار حذف میشود. |
| api.emit(type, detail) | رویداد bana:plugin:<name>:<type>. |
| api.styles(css) | CSS با adoptedStyleSheets (سازگار با CSP) داخل @layer bana.components، پس CSS بیلایهی خودتان برنده میماند. |
| api.icon(name, paths) | ثبت آیکون؛ نام باید با <plugin>- شروع شود تا با آیکونهای دیگر برخورد نکند. |
| api.theme / toast / dialog / modules / signal / options | دسترسی فقطخواندنی به موتور؛ signal با حذف Plugin قطع میشود. |
| requires | { bana: ">=0.1.0" | "^0.1.0" | "~0.1.0", modules: ["popover"] }؛ نسخه یا ماژول ناسازگار → خطای واضح. |
Plugin جعبهی امن (sandbox) نیست.Plugin با همان دسترسیهای صفحه اجرا میشود. این API تمیزکاری و جلوگیری از برخورد نامها را تضمین میکند، نه امنیت را. فقط کدی را نصب کنید که به آن اعتماد دارید و Plugin را از ورودی کاربر یا آدرس ناشناس بارگذاری نکنید. نام آیکونها پس از ثبت قابل حذف نیست.