bliss/bliss-cli/live-editor/slideout.eta
2026-08-03 01:24:54 -04:00

76 lines
4.1 KiB
Text
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<aside id="bliss-live-editor" data-bliss-ui
class="fixed inset-y-0 left-0 z-[2147483646] w-[min(28rem,90vw)] overflow-auto border-r-4 border-black bg-white text-black shadow-[8px_0_0_#000]"
style="font-family:ui-sans-serif,system-ui">
<header class="sticky top-0 flex items-center justify-between border-b-4 border-double border-black bg-white p-3">
<div><div class="text-lg font-black tracking-tight">Live Page</div><div class="text-xs">Objects currently on this card</div></div>
<button type="button" data-bliss-close class="h-7 w-7 border-2 border-black bg-white text-lg font-black leading-none shadow-[2px_2px_0_#000] active:translate-x-0.5 active:translate-y-0.5 active:shadow-none">×</button>
</header>
<div class="grid min-h-[calc(100vh-61px)] grid-rows-[auto_1fr]">
<nav data-bliss-tree class="border-b-4 border-double border-black p-2"></nav>
<section data-bliss-editor class="min-h-0 p-3 text-sm">Select a route or template to edit it.</section>
</div>
</aside>
<script>
(function () {
const root = document.getElementById("bliss-live-editor");
if (!root) return;
const tree = root.querySelector("[data-bliss-tree]");
const editor = root.querySelector("[data-bliss-editor]");
root.querySelector("[data-bliss-close]").onclick = () =>
document.dispatchEvent(new CustomEvent("bliss:inspector-close"));
function sourceButton(label, kind, id, count) {
const button = document.createElement("button");
button.type = "button";
button.className = "block w-full border border-transparent px-2 py-1 text-left hover:border-black hover:bg-black hover:text-white";
button.textContent = label + (count > 1 ? ` (${count})` : "");
button.onmouseenter = () => document.dispatchEvent(new CustomEvent("bliss:highlight", { detail: { kind, id, on: true } }));
button.onmouseleave = () => document.dispatchEvent(new CustomEvent("bliss:highlight", { detail: { kind, id, on: false } }));
if (kind !== "structure") button.onclick = () => {
editor.textContent = "Loading…";
htmx.ajax("GET", `/_bliss/editor/${kind}/${id}`, { target: editor, swap: "innerHTML" });
};
return button;
}
function render(items) {
tree.innerHTML = "";
const structures = new Map();
for (const item of items) {
if (!structures.has(item.structureId)) structures.set(item.structureId, { name: item.structureName, routes: new Map(), templates: new Map(), count: 0 });
const structure = structures.get(item.structureId);
structure.count++;
if (!structure.routes.has(item.routeId)) structure.routes.set(item.routeId, { name: item.routeName, count: 0 });
structure.routes.get(item.routeId).count++;
if (item.templateId) {
if (!structure.templates.has(item.templateId)) structure.templates.set(item.templateId, { name: item.templateName, count: 0 });
structure.templates.get(item.templateId).count++;
}
}
for (const [structureId, structure] of structures) {
const group = document.createElement("details");
group.open = true;
const heading = document.createElement("summary");
heading.className = "cursor-pointer list-none font-semibold";
heading.append(sourceButton(structure.name, "structure", structureId, structure.count));
group.append(heading);
for (const [label, kind, entries] of [["Routes", "route", structure.routes], ["Templates", "template", structure.templates]]) {
if (!entries.size) continue;
const section = document.createElement("details");
section.open = true;
section.className = "ml-3";
const summary = document.createElement("summary");
summary.className = "cursor-pointer py-1 text-xs font-bold uppercase tracking-widest";
summary.textContent = label;
section.append(summary);
for (const [id, entry] of entries) section.append(sourceButton(entry.name, kind, id, entry.count));
group.append(section);
}
tree.append(group);
}
}
document.addEventListener("bliss:inventory", (event) => render(event.detail));
document.dispatchEvent(new CustomEvent("bliss:inventory-request"));
})();
</script>