UNPKG

@flanksource/clicky-ui

Version:

Flanksource Clicky UI — React component library built on shadcn/ui with light/dark and density theming.

196 lines (195 loc) 6.47 kB
import { jsx, jsxs } from "react/jsx-runtime"; import { useMemo, useState, useEffect } from "react"; import { Clicky } from "../data/Clicky.js"; import { JsonView } from "../data/JsonView.js"; function CommandOutput({ response, bare = false, onTableRowClick, getTableRowHref, isTableRowClickable }) { const text = response.stdout || response.output || ""; const ct = response.contentType || "application/json"; const parsed = useMemo(() => { if (response.parsed !== void 0) return response.parsed; if (!text.trim()) return null; try { return JSON.parse(text.trim()); } catch { return null; } }, [response.parsed, text]); const output = /* @__PURE__ */ jsx( OutputBody, { text, parsed, contentType: ct, bare, ...response.blob ? { blob: response.blob } : {}, ...onTableRowClick ? { onTableRowClick } : {}, ...getTableRowHref ? { getTableRowHref } : {}, ...isTableRowClickable ? { isTableRowClickable } : {} } ); if (bare) return output; return /* @__PURE__ */ jsxs("div", { className: "space-y-3", children: [ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [ /* @__PURE__ */ jsx( "span", { className: response.success ? "rounded-md border px-2 py-0.5 text-xs" : "rounded-md bg-destructive px-2 py-0.5 text-xs text-destructive-foreground", children: response.success ? "Success" : "Failed" } ), /* @__PURE__ */ jsxs("span", { className: "rounded-md border px-2 py-0.5 font-mono text-xs", children: [ "exit ", response.exit_code ] }), ct !== "application/json" && /* @__PURE__ */ jsx("span", { className: "rounded-md bg-secondary px-2 py-0.5 font-mono text-xs text-secondary-foreground", children: ct.split(";")[0] }), response.error && /* @__PURE__ */ jsx("span", { className: "text-sm text-destructive", children: response.error }) ] }), response.cli && /* @__PURE__ */ jsxs("pre", { className: "overflow-x-auto rounded-md bg-muted p-3 font-mono text-xs", children: [ "$ ", response.cli ] }), output ] }); } function OutputBody({ text, parsed, contentType, blob, bare, onTableRowClick, getTableRowHref, isTableRowClickable }) { const ct = (contentType.split(";")[0] ?? "").trim(); if (ct === "application/pdf" && blob) { return /* @__PURE__ */ jsx(PdfOutput, { blob }); } if (ct === "application/clicky+json" || ct === "application/json+clicky") { const clicky = /* @__PURE__ */ jsx( Clicky, { data: parsed ?? text, ...onTableRowClick ? { onTableRowClick } : {}, ...getTableRowHref ? { getTableRowHref } : {}, ...isTableRowClickable ? { isTableRowClickable } : {} } ); const detailOutput = /* @__PURE__ */ jsx("div", { className: "detail-output", children: clicky }); if (bare) return detailOutput; return /* @__PURE__ */ jsx( Tabs, { defaultValue: "rendered", tabs: [ { value: "rendered", label: "Rendered", content: detailOutput }, { value: "raw", label: "Raw", content: /* @__PURE__ */ jsx(TextOutput, { text }) } ] } ); } if (ct === "text/html") { const iframe = /* @__PURE__ */ jsx( "iframe", { srcDoc: text, className: "h-[600px] w-full rounded-md border bg-white", sandbox: "allow-same-origin" } ); if (bare) return iframe; return /* @__PURE__ */ jsx( Tabs, { defaultValue: "preview", tabs: [ { value: "preview", label: "Preview", content: iframe }, { value: "source", label: "Source", content: /* @__PURE__ */ jsx(TextOutput, { text }) } ] } ); } if (parsed) { const json = /* @__PURE__ */ jsx(JsonViewer, { data: parsed }); if (bare) return json; return /* @__PURE__ */ jsx( Tabs, { defaultValue: "output", tabs: [ { value: "output", label: "Output", content: json }, { value: "raw", label: "Raw", content: /* @__PURE__ */ jsx(TextOutput, { text }) } ] } ); } if (text) return /* @__PURE__ */ jsx(TextOutput, { text }); return /* @__PURE__ */ jsx("p", { className: "py-4 text-sm text-muted-foreground", children: "No output" }); } function PdfOutput({ blob }) { const [url, setURL] = useState(""); useEffect(() => { const next = URL.createObjectURL(blob); setURL(next); return () => URL.revokeObjectURL(next); }, [blob]); if (!url) return null; return /* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [ /* @__PURE__ */ jsx( "a", { href: url, download: "output.pdf", className: "inline-block rounded-md border px-3 py-1.5 text-sm hover:bg-accent", children: "Download PDF" } ), /* @__PURE__ */ jsx("iframe", { src: url, className: "h-[600px] w-full rounded-md border" }) ] }); } function JsonViewer({ data }) { return /* @__PURE__ */ jsx("div", { className: "overflow-auto rounded-md bg-muted p-4 font-mono text-xs", children: /* @__PURE__ */ jsx(JsonView, { data, defaultOpenDepth: Number.MAX_SAFE_INTEGER }) }); } function TextOutput({ text, variant = "default" }) { return /* @__PURE__ */ jsx( "pre", { className: `max-h-96 overflow-auto whitespace-pre-wrap rounded-md p-4 font-mono text-sm ${variant === "error" ? "bg-red-50 text-red-800 dark:bg-red-950 dark:text-red-200" : "bg-muted"}`, children: text } ); } function Tabs({ defaultValue, tabs }) { const [value, setValue] = useState(defaultValue); const active = tabs.find((tab) => tab.value === value) ?? tabs[0]; if (!active) return null; return /* @__PURE__ */ jsxs("div", { className: "space-y-3", children: [ /* @__PURE__ */ jsx("div", { className: "inline-flex rounded-md border bg-muted p-1", children: tabs.map((tab) => /* @__PURE__ */ jsx( "button", { type: "button", className: `rounded px-2 py-1 text-xs ${tab.value === active.value ? "bg-background text-foreground shadow-sm" : "text-muted-foreground"}`, onClick: () => setValue(tab.value), children: tab.label }, tab.value )) }), /* @__PURE__ */ jsx("div", { children: active.content }) ] }); } export { CommandOutput }; //# sourceMappingURL=CommandOutput.js.map