114 lines
3.5 KiB
JavaScript
114 lines
3.5 KiB
JavaScript
/**
|
|
* Native JS UI bundle for the kandev-plugin-e2e fixture plugin
|
|
* (docs/plans/plugins/PLUGIN-API.md). A self-contained ES module — no
|
|
* imports, no bundled React — that calls `window.registerKandevPlugin(id,
|
|
* plugin)` at evaluation time and, on `initialize(registry, host)`,
|
|
* registers a nav item, a top-level route, a `task-sidebar` slot component,
|
|
* a `main-top-bar` slot component, a `task.created` WS handler, and the
|
|
* `open-demo` keybinding (declared in manifest.yaml's `ui.keybindings`,
|
|
* default `mod+shift+j`) which opens a `host.openModal(...)` demo modal.
|
|
* Uses only host.React/host.jsx.
|
|
*
|
|
* The task-created counter lives in module scope (not component state) with
|
|
* a tiny listener set, so it survives across route navigations (the page
|
|
* component unmounts/remounts as the user navigates away and back).
|
|
*/
|
|
(function () {
|
|
var moduleCount = 0;
|
|
var listeners = new Set();
|
|
|
|
function emit() {
|
|
listeners.forEach(function (fn) {
|
|
fn(moduleCount);
|
|
});
|
|
}
|
|
|
|
function incrementCount() {
|
|
moduleCount += 1;
|
|
emit();
|
|
}
|
|
|
|
function useCounter(React) {
|
|
var state = React.useState(moduleCount);
|
|
var count = state[0];
|
|
var setCount = state[1];
|
|
React.useEffect(function () {
|
|
setCount(moduleCount);
|
|
listeners.add(setCount);
|
|
return function () {
|
|
listeners.delete(setCount);
|
|
};
|
|
}, []);
|
|
return count;
|
|
}
|
|
|
|
window.registerKandevPlugin("kandev-plugin-e2e", {
|
|
initialize: function (registry, host) {
|
|
var React = host.React;
|
|
var jsx = host.jsx;
|
|
|
|
function PluginPage() {
|
|
var count = useCounter(React);
|
|
return jsx(
|
|
"div",
|
|
{ id: "hello-plugin-page-root" },
|
|
jsx("h1", { id: "hello-plugin-page" }, "Hello E2E"),
|
|
jsx("span", { id: "hello-task-counter" }, String(count)),
|
|
);
|
|
}
|
|
|
|
function SidebarSlot() {
|
|
return jsx("div", { id: "hello-sidebar" }, "Hello E2E sidebar");
|
|
}
|
|
|
|
function MainTopBarSlot(props) {
|
|
var slotProps = props.slotProps || {};
|
|
return jsx("span", { id: "hello-main-top-bar" }, "Hello " + slotProps.currentPage);
|
|
}
|
|
|
|
function StatusSlot(props) {
|
|
var slotProps = props.slotProps || {};
|
|
var id = slotProps.placement === "left" ? "hello-status-left" : "hello-status-right";
|
|
return jsx(
|
|
"span",
|
|
{ id: id },
|
|
"Hello status " +
|
|
String(slotProps.presentation || "unknown") +
|
|
" " +
|
|
String(slotProps.activeTaskId || "no-task"),
|
|
);
|
|
}
|
|
|
|
registry.registerNavItem({
|
|
id: "e2e-hello",
|
|
label: "Hello E2E",
|
|
path: "/plugins/e2e-hello",
|
|
section: "main",
|
|
});
|
|
registry.registerRoute("/plugins/e2e-hello", PluginPage);
|
|
registry.registerComponent("task-sidebar", SidebarSlot);
|
|
registry.registerComponent("main-top-bar", MainTopBarSlot);
|
|
registry.registerComponent("app-status-bar-left", StatusSlot);
|
|
registry.registerComponent("app-status-bar-right", StatusSlot);
|
|
registry.registerWsHandler("task.created", function () {
|
|
incrementCount();
|
|
});
|
|
|
|
registry.registerKeybinding("open-demo", function () {
|
|
function DemoModalContent() {
|
|
return jsx(
|
|
"div",
|
|
{ id: "hello-demo-modal", "data-testid": "hello-demo-modal" },
|
|
"Hello from the plugin modal",
|
|
);
|
|
}
|
|
host.openModal({
|
|
title: "Demo Modal",
|
|
content: DemoModalContent,
|
|
size: "md",
|
|
});
|
|
});
|
|
},
|
|
});
|
|
})();
|