9c16d337a2
* feat(web): add app status bar * feat(web): add app status bar visibility toggle * feat(web): persist status bar item order * fix(web): refine app status bar behavior * fix(web): polish app status bar presentation * test(web): split plugin slot coverage groups * fix(web): address status surface review feedback * fix(web): stabilize status bar overlay tests
97 lines
3.0 KiB
JavaScript
97 lines
3.0 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, and a `task.created` WS handler. 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();
|
|
});
|
|
},
|
|
});
|
|
})();
|