LFM2-WebGPU / src /components /ResultBlock.tsx
shreyask's picture
add mcp support
d89db9c verified
raw
history blame
4.24 kB
import type React from "react";
import { useState } from "react";
type JsonValue = string | number | boolean | null | JsonObject | JsonArray;
type JsonObject = { [key: string]: JsonValue };
type JsonArray = JsonValue[];
const isJsonString = (str: string): boolean => {
if (typeof str !== "string") return false;
const trimmed = str.trim();
// Check if it looks like JSON (starts with { or [)
if (!trimmed.startsWith("{") && !trimmed.startsWith("[")) return false;
try {
const parsed = JSON.parse(trimmed);
// Ensure it's actually an object or array, not just a primitive
console.log("JSON parse successful:", parsed);
return typeof parsed === "object" && parsed !== null;
} catch (error) {
console.log("JSON parse failed:", error);
return false;
}
};
const JsonCollapsible: React.FC<{ data: JsonValue; isString?: boolean }> = ({
data,
isString = false,
}) => {
const [isCollapsed, setIsCollapsed] = useState(true);
let jsonData: JsonValue;
try {
jsonData = isString ? JSON.parse(data as string) : data;
} catch {
// If parsing fails, display as string
return (
<pre className="text-sm text-gray-300 whitespace-pre-wrap overflow-auto">
{String(data)}
</pre>
);
}
const isObject = typeof jsonData === "object" && jsonData !== null;
if (!isObject) {
return <span className="text-gray-300">{JSON.stringify(jsonData)}</span>;
}
const keys = Object.keys(jsonData as JsonObject);
const preview = Array.isArray(jsonData)
? `[${jsonData.length} items]`
: `{${keys.length} keys}`;
return (
<div className="json-collapsible">
<button
onClick={() => setIsCollapsed(!isCollapsed)}
className="flex items-center gap-1 text-blue-400 hover:text-blue-300 transition-colors text-sm font-mono"
>
<span
className="transform transition-transform duration-200"
style={{
transform: isCollapsed ? "rotate(-90deg)" : "rotate(0deg)",
}}
>
</span>
{isCollapsed ? preview : Array.isArray(jsonData) ? "[" : "{"}
</button>
{!isCollapsed && (
<div className="ml-4 mt-1">
<pre className="text-sm text-gray-300 whitespace-pre-wrap overflow-auto">
{JSON.stringify(jsonData, null, 2)}
</pre>
<div className="text-blue-400 font-mono text-sm">
{Array.isArray(jsonData) ? "]" : "}"}
</div>
</div>
)}
</div>
);
};
const ResultBlock: React.FC<{ error?: string; result?: unknown }> = ({
error,
result,
}) => {
console.log("ResultBlock component rendered with:", {
error,
result,
type: typeof result,
});
const renderContent = () => {
console.log("ResultBlock Debug:", {
result,
type: typeof result,
isString: typeof result === "string",
isArray: Array.isArray(result),
startsWithBracket:
typeof result === "string" && result.trim().startsWith("["),
isJsonString: typeof result === "string" ? isJsonString(result) : false,
});
// Handle objects and arrays directly
if (typeof result === "object" && result !== null) {
console.log("Rendering as object/array with JsonCollapsible");
return <JsonCollapsible data={result as JsonValue} />;
}
// Handle string that might be JSON
if (typeof result === "string") {
const trimmed = result.trim();
if (isJsonString(trimmed)) {
console.log("Rendering string as JSON with JsonCollapsible");
return <JsonCollapsible data={trimmed} isString={true} />;
}
}
// Fallback to plain text display
console.log("Rendering as plain text fallback");
return (
<pre className="text-sm text-gray-300 whitespace-pre-wrap overflow-auto">
{String(result)}
</pre>
);
};
return (
<div
className={
error
? "bg-red-900 border border-red-600 rounded p-3"
: "bg-gray-700 border border-gray-600 rounded p-3"
}
>
{error ? <p className="text-red-300 text-sm">Error: {error}</p> : null}
<div className="mt-2">{renderContent()}</div>
</div>
);
};
export default ResultBlock;