feat(console-web): replace TanStack UI with Solid host pages

- move the management frontend under the wasmeld-console crate
- use a persistent Host shell with disposable iframe page documents
- version Host/Page postMessage state and command contracts
- migrate runtime, service, WIT, invocation, and settings workflows
- add Tailwind CSS v4, responsive layouts, and Host-owned dialogs
- emit a dependency-free PWA worker with API cache exclusions
- remove the superseded root TanStack Start application
This commit is contained in:
Maofeng
2026-07-30 09:21:55 +08:00
parent 4e32a1246b
commit 70ee5e33da
49 changed files with 3996 additions and 5648 deletions
@@ -0,0 +1,61 @@
import { History, RefreshCw } from "lucide-solid";
import { createMemo, For, Show } from "solid-js";
import { EmptyState } from "../../components/ui/empty-state";
import { PageHeading } from "../../components/ui/page-heading";
import { eventsFrom } from "../../lib/view-state";
import type { PageProps } from "../types";
const toneClass = {
success: "bg-brand",
warning: "bg-amber-strong",
danger: "bg-coral-strong",
neutral: "bg-muted",
};
export default function ActivityPage(props: PageProps) {
const events = createMemo(() => {
const query = props.state()?.query.trim().toLowerCase() ?? "";
return eventsFrom(props.state()).filter(
(event) =>
!query ||
event.title.toLowerCase().includes(query) ||
event.detail.toLowerCase().includes(query),
);
});
return (
<main class="page">
<PageHeading
eyebrow="EVENTS"
title="调用记录"
description="最近 256 条持久化生命周期与调用事件。"
actions={
<button class="icon-btn" title="刷新" onClick={() => props.command({ type: "refresh" })}>
<RefreshCw size={16} />
</button>
}
/>
<section class="panel">
<Show
when={events().length > 0}
fallback={
<EmptyState icon={History} title="暂无事件" detail="Runtime 操作和调用会显示在这里。" />
}
>
<div class="divide-y divide-line">
<For each={events()}>
{(event) => (
<article class="grid gap-2 px-5 py-4 sm:grid-cols-[10px_minmax(180px,0.8fr)_2fr_84px] sm:items-center">
<span class={`size-2 rounded-full ${toneClass[event.tone]}`} />
<strong class="text-sm">{event.title}</strong>
<p class="text-xs leading-5 text-muted">{event.detail}</p>
<time class="font-mono text-xs text-muted sm:text-right">{event.time}</time>
</article>
)}
</For>
</div>
</Show>
</section>
</main>
);
}