ttrpg-tools/src/components/md-commander/CommanderEntries.tsx

70 lines
2.1 KiB
TypeScript
Raw Normal View History

2026-02-28 16:49:02 +08:00
import { type Component, For, Show, createEffect, on } from "solid-js";
2026-02-28 16:28:07 +08:00
import type { CommanderEntry } from "./types";
import { getResultClass } from "./hooks";
export interface CommanderEntriesProps {
entries: () => CommanderEntry[];
2026-02-28 16:49:02 +08:00
onCommandClick?: (command: string) => void;
2026-02-28 16:28:07 +08:00
}
export const CommanderEntries: Component<CommanderEntriesProps> = (props) => {
2026-02-28 16:49:02 +08:00
let containerRef: HTMLDivElement | undefined;
// 当 entries 变化时自动滚动到底部
createEffect(
on(
() => props.entries().length,
() => {
if (containerRef) {
containerRef.scrollTop = containerRef.scrollHeight;
}
},
),
);
const handleCommandClick = (command: string) => {
if (props.onCommandClick) {
props.onCommandClick(command);
}
};
2026-02-28 16:28:07 +08:00
return (
2026-02-28 16:49:02 +08:00
<div
ref={containerRef}
class="commander-entries flex-1 overflow-auto p-3 bg-white space-y-2"
>
2026-02-28 16:28:07 +08:00
<Show
when={props.entries().length > 0}
fallback={
<div class="text-gray-400 text-center py-8"></div>
}
>
<For each={props.entries()}>
{(entry) => (
<div class="border-l-2 border-gray-300 pl-3 py-1">
<div class="flex items-center justify-between text-xs text-gray-500 mb-1">
2026-02-28 16:49:02 +08:00
<span
class="font-mono cursor-pointer hover:text-blue-600 hover:underline"
onClick={() => handleCommandClick(entry.command)}
title="点击复制到输入框"
>
{entry.command}
</span>
2026-02-28 16:28:07 +08:00
<span>
{entry.timestamp.toLocaleTimeString()}
</span>
</div>
<div
class={`text-sm whitespace-pre-wrap ${getResultClass(entry.result.type)}`}
2026-02-28 16:49:02 +08:00
innerHTML={entry.result.isHtml ? entry.result.message : undefined}
2026-02-28 16:28:07 +08:00
>
2026-02-28 16:49:02 +08:00
{!entry.result.isHtml && entry.result.message}
2026-02-28 16:28:07 +08:00
</div>
</div>
)}
</For>
</Show>
</div>
);
};