test: add stack view + wiring test page
Standalone test harness for flow tubes, particle animation, and interactive port wiring with event logging. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
4ebbf9f116
commit
e7f9507d9d
|
|
@ -0,0 +1,129 @@
|
|||
<!doctype html>
|
||||
<html lang="en" data-theme="dark">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<title>Stack View + Wiring Test</title>
|
||||
<style>
|
||||
* { margin: 0; padding: 0; box-sizing: border-box; }
|
||||
html, body { width: 100%; height: 100%; background: #0f172a; color: #e2e8f0; font-family: system-ui, sans-serif; }
|
||||
body { padding: 24px; display: flex; flex-direction: column; gap: 16px; }
|
||||
h1 { font-size: 1.2rem; opacity: 0.7; }
|
||||
#log { font-size: 0.75rem; font-family: monospace; background: #1e293b; border-radius: 8px; padding: 12px; max-height: 200px; overflow-y: auto; white-space: pre-wrap; }
|
||||
.actions { display: flex; gap: 8px; flex-wrap: wrap; }
|
||||
.actions button { padding: 6px 14px; border: 1px solid rgba(255,255,255,0.15); border-radius: 6px; background: rgba(255,255,255,0.05); color: #e2e8f0; font-size: 0.75rem; cursor: pointer; }
|
||||
.actions button:hover { background: rgba(34,211,238,0.15); border-color: #22d3ee; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<h1>rStack Tab Bar — Stack View + Wiring Test</h1>
|
||||
<div class="actions">
|
||||
<button onclick="addFlow()">Add flow (drag dialog)</button>
|
||||
<button onclick="clearFlows()">Clear all flows</button>
|
||||
<button onclick="addThirdLayer()">Add 3rd layer (rCal)</button>
|
||||
</div>
|
||||
<rstack-tab-bar space="test" active="layer-rspace" view-mode="stack"></rstack-tab-bar>
|
||||
<div id="log">Event log:\n</div>
|
||||
|
||||
<script type="module">
|
||||
import { RStackTabBar } from "../shared/components/rstack-tab-bar.ts";
|
||||
RStackTabBar.define();
|
||||
|
||||
const tb = document.querySelector("rstack-tab-bar");
|
||||
const log = document.getElementById("log");
|
||||
function emit(msg) { log.textContent += msg + "\n"; log.scrollTop = log.scrollHeight; }
|
||||
|
||||
// Modules with feeds + acceptsFeeds
|
||||
const modules = [
|
||||
{
|
||||
id: "rspace", name: "rSpace Canvas", icon: "\u{1F3A8}",
|
||||
description: "Collaborative infinite canvas",
|
||||
feeds: [
|
||||
{ id: "shapes", name: "Canvas Shapes", kind: "data", description: "All shapes on canvas" },
|
||||
{ id: "tokens", name: "Token Mints", kind: "economic", description: "Token creation events" },
|
||||
],
|
||||
acceptsFeeds: ["data", "trust", "attention"],
|
||||
},
|
||||
{
|
||||
id: "rnotes", name: "Notes", icon: "\u{1F4DD}",
|
||||
description: "Collaborative notes",
|
||||
feeds: [
|
||||
{ id: "notes-feed", name: "Note Updates", kind: "data", description: "Note change events" },
|
||||
{ id: "endorsements", name: "Endorsements", kind: "trust", description: "Note endorsements" },
|
||||
],
|
||||
acceptsFeeds: ["data", "economic", "trust"],
|
||||
},
|
||||
{
|
||||
id: "rcal", name: "Calendar", icon: "\u{1F4C5}",
|
||||
description: "Shared calendar",
|
||||
feeds: [
|
||||
{ id: "events-feed", name: "Events", kind: "attention", description: "Calendar events" },
|
||||
],
|
||||
acceptsFeeds: ["data", "attention"],
|
||||
},
|
||||
];
|
||||
tb.setModules(modules);
|
||||
|
||||
// Start with 2 layers
|
||||
let layers = [
|
||||
{ id: "layer-rspace", moduleId: "rspace", label: "Canvas", order: 0, color: "", visible: true, createdAt: Date.now() },
|
||||
{ id: "layer-rnotes", moduleId: "rnotes", label: "Notes", order: 1, color: "", visible: true, createdAt: Date.now() },
|
||||
];
|
||||
tb.setLayers(layers);
|
||||
|
||||
// Start with 1 flow to see tubes
|
||||
let flows = [
|
||||
{ id: "flow-seed", kind: "data", sourceLayerId: "layer-rspace", targetLayerId: "layer-rnotes", label: "Canvas \u2192 Notes", strength: 0.7, active: true },
|
||||
];
|
||||
tb.setFlows(flows);
|
||||
emit("Loaded 2 layers + 1 seed flow. Stack view active.");
|
||||
emit("Try: click an output port chip to enter wiring mode.");
|
||||
|
||||
// Event listeners
|
||||
tb.addEventListener("flow-create", (e) => {
|
||||
const f = e.detail.flow;
|
||||
flows.push(f);
|
||||
tb.setFlows(flows);
|
||||
emit(`\u2705 flow-create: ${f.kind} ${f.sourceLayerId} \u2192 ${f.targetLayerId}` + (f.meta?.sourceFeedId ? ` (feed: ${f.meta.sourceFeedId})` : ""));
|
||||
});
|
||||
|
||||
tb.addEventListener("flow-select", (e) => {
|
||||
emit(`\u{1F449} flow-select: ${e.detail.flowId}`);
|
||||
});
|
||||
|
||||
tb.addEventListener("flow-remove", (e) => {
|
||||
flows = flows.filter(f => f.id !== e.detail.flowId);
|
||||
tb.setFlows(flows);
|
||||
emit(`\u274C flow-remove: ${e.detail.flowId}`);
|
||||
});
|
||||
|
||||
tb.addEventListener("layer-switch", (e) => {
|
||||
emit(`\u{1F4CD} layer-switch: ${e.detail.layerId}`);
|
||||
});
|
||||
|
||||
tb.addEventListener("layer-add", (e) => {
|
||||
emit(`\u2795 layer-add: ${e.detail.moduleId}`);
|
||||
});
|
||||
|
||||
tb.addEventListener("view-toggle", (e) => {
|
||||
emit(`\u{1F504} view-toggle: ${e.detail.mode}`);
|
||||
});
|
||||
|
||||
// Expose helpers to window for button clicks
|
||||
window.addFlow = () => {
|
||||
emit("Drag between two layer planes to open the flow dialog.");
|
||||
};
|
||||
window.clearFlows = () => {
|
||||
flows = [];
|
||||
tb.setFlows(flows);
|
||||
emit("Cleared all flows.");
|
||||
};
|
||||
window.addThirdLayer = () => {
|
||||
if (layers.find(l => l.moduleId === "rcal")) { emit("rCal layer already exists."); return; }
|
||||
layers.push({ id: "layer-rcal", moduleId: "rcal", label: "Calendar", order: 2, color: "", visible: true, createdAt: Date.now() });
|
||||
tb.setLayers(layers);
|
||||
tb.setFlows(flows);
|
||||
emit("Added Calendar layer. Now try wiring between 3 layers.");
|
||||
};
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
Loading…
Reference in New Issue