UNPKG

@flanksource/clicky-ui

Version:

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

158 lines (157 loc) 8.32 kB
import { jsxs, jsx } from "react/jsx-runtime"; import "react"; import { Icon } from "../Icon.js"; import { parseInlineJsonContextValue, parseDiagnosticsStackTrace, isApplicationStackFrame, compactStackPath } from "./error-diagnostics.js"; function ErrorDetails({ diagnostics, renderJsonContext }) { const scalarContext = diagnostics.context.filter( ([, value]) => !parseInlineJsonContextValue(value) ); const jsonContext = diagnostics.context.map(([label, value]) => ({ label, value, data: parseInlineJsonContextValue(value) })).filter( (entry) => entry.data !== null ); return /* @__PURE__ */ jsxs("details", { className: "group rounded-md border border-destructive/30 bg-destructive/5", children: [ /* @__PURE__ */ jsxs("summary", { className: "flex cursor-pointer list-none items-start gap-2 p-3", children: [ /* @__PURE__ */ jsx(Icon, { name: "lucide:triangle-alert", className: "mt-0.5 shrink-0 text-destructive" }), /* @__PURE__ */ jsxs("div", { className: "min-w-0 flex-1", children: [ /* @__PURE__ */ jsx("div", { className: "text-sm font-semibold text-destructive", children: "Error" }), /* @__PURE__ */ jsx("div", { className: "mt-1 whitespace-pre-wrap text-sm text-destructive", children: diagnostics.message }) ] }), /* @__PURE__ */ jsx( Icon, { name: "lucide:chevron-right", className: "mt-0.5 shrink-0 text-muted-foreground transition-transform group-open:rotate-90" } ) ] }), /* @__PURE__ */ jsxs("div", { className: "grid gap-3 border-t border-destructive/20 p-3 pt-2", children: [ (diagnostics.trace || diagnostics.time) && /* @__PURE__ */ jsxs("div", { className: "flex min-w-0 flex-wrap gap-2", children: [ diagnostics.trace && /* @__PURE__ */ jsx(CopyBadge, { label: "Trace", value: diagnostics.trace, className: "max-w-full" }), diagnostics.time && /* @__PURE__ */ jsxs("span", { className: "inline-flex max-w-full items-center overflow-hidden rounded-md border border-border bg-background/80 text-xs", children: [ /* @__PURE__ */ jsx("span", { className: "shrink-0 bg-muted px-2 py-1 font-medium text-muted-foreground", children: "Time" }), /* @__PURE__ */ jsx("span", { className: "min-w-0 truncate px-2 py-1 font-mono text-foreground", children: diagnostics.time }) ] }) ] }), diagnostics.context.length > 0 && /* @__PURE__ */ jsxs("div", { className: "min-w-0", children: [ /* @__PURE__ */ jsx("div", { className: "mb-1.5 text-xs font-semibold uppercase tracking-wide text-muted-foreground", children: "Context" }), scalarContext.length > 0 && /* @__PURE__ */ jsx("div", { className: "flex flex-wrap gap-1.5", children: scalarContext.map(([label, value]) => /* @__PURE__ */ jsx(CopyBadge, { label, value }, `${label}:${value}`)) }), jsonContext.length > 0 && /* @__PURE__ */ jsx("div", { className: "mt-2 grid gap-2", children: jsonContext.map( (entry) => renderJsonContext ? /* @__PURE__ */ jsx("span", { children: renderJsonContext(entry) }, `${entry.label}:${entry.value}`) : /* @__PURE__ */ jsx( CopyBadge, { label: entry.label, value: entry.value }, `${entry.label}:${entry.value}` ) ) }) ] }), diagnostics.stacktrace && /* @__PURE__ */ jsxs("div", { className: "min-w-0", children: [ /* @__PURE__ */ jsxs("div", { className: "mb-1.5 flex min-w-0 items-center justify-between gap-3", children: [ /* @__PURE__ */ jsx("div", { className: "text-xs font-semibold uppercase tracking-wide text-muted-foreground", children: "Stack trace" }), /* @__PURE__ */ jsxs( "button", { type: "button", onClick: () => copyText(diagnostics.stacktrace ?? ""), className: "inline-flex items-center gap-1 text-xs font-medium text-muted-foreground hover:text-foreground", children: [ /* @__PURE__ */ jsx(Icon, { name: "lucide:copy" }), "copy" ] } ) ] }), /* @__PURE__ */ jsx(PrettyStackTrace, { stacktrace: diagnostics.stacktrace }) ] }) ] }) ] }); } function PrettyStackTrace({ stacktrace }) { const parsed = parseDiagnosticsStackTrace(stacktrace); if (parsed.frames.length === 0) { return /* @__PURE__ */ jsx("pre", { className: "max-h-72 overflow-auto whitespace-pre-wrap rounded-md bg-slate-950 p-3 font-mono text-xs leading-5 text-slate-200", children: stacktrace }); } return /* @__PURE__ */ jsxs("div", { className: "max-h-96 min-h-40 overflow-auto rounded-md border border-border bg-background p-2", children: [ /* @__PURE__ */ jsx("div", { className: "mb-2 flex items-center justify-between gap-2 text-[11px] text-muted-foreground", children: /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1.5", children: [ /* @__PURE__ */ jsx("span", { className: "rounded-full bg-red-100 px-2 py-0.5 text-red-700", children: "error" }), /* @__PURE__ */ jsxs("span", { children: [ parsed.frames.length, " frames" ] }) ] }) }), parsed.headline && /* @__PURE__ */ jsx("div", { className: "mb-2 rounded-md bg-red-50 px-2 py-1.5 font-mono text-[11px] leading-4 text-red-700", children: parsed.headline }), /* @__PURE__ */ jsx("div", { className: "space-y-0.5", children: parsed.frames.map((frame, index) => /* @__PURE__ */ jsx(StackFrameRow, { frame, index }, `${frame.file}:${frame.line}:${index}`)) }), parsed.unparsed.length > 0 && /* @__PURE__ */ jsx("pre", { className: "mt-2 whitespace-pre-wrap rounded bg-muted p-2 font-mono text-[11px] leading-4 text-muted-foreground", children: parsed.unparsed.join("\n") }) ] }); } function StackFrameRow({ frame, index }) { const appFrame = isApplicationStackFrame(frame.file); return /* @__PURE__ */ jsx( "button", { type: "button", onClick: () => copyText(frame.raw), title: "Copy stack frame", className: [ "block w-full rounded px-1.5 py-1 text-left hover:bg-accent/50", appFrame ? "text-foreground" : "text-muted-foreground" ].join(" "), children: /* @__PURE__ */ jsxs("div", { className: "flex min-w-0 items-start gap-1.5", children: [ /* @__PURE__ */ jsx( Icon, { name: appFrame ? "codicon:symbol-method" : "codicon:debug-step-over", className: "mt-0.5 shrink-0 text-[11px]" } ), /* @__PURE__ */ jsx("div", { className: "min-w-0", children: /* @__PURE__ */ jsxs("div", { className: "break-all font-mono text-[11px] font-semibold leading-4", children: [ /* @__PURE__ */ jsxs("span", { className: "mr-2 text-[10px] font-normal opacity-60", children: [ "#", index + 1 ] }), frame.functionName || "unknown function", /* @__PURE__ */ jsxs("span", { className: "ml-2 text-[10px] font-normal opacity-80", children: [ compactStackPath(frame.file), ":", frame.line ] }) ] }) }) ] }) } ); } function CopyBadge({ label, value, className = "" }) { return /* @__PURE__ */ jsxs( "button", { type: "button", onClick: () => copyText(value), title: `Copy ${label}`, className: [ "inline-flex max-w-full items-center overflow-hidden rounded-md border border-border bg-background/80 text-left text-xs hover:border-primary/40 hover:bg-background", className ].filter(Boolean).join(" "), children: [ /* @__PURE__ */ jsx("span", { className: "shrink-0 bg-muted px-2 py-1 font-medium text-muted-foreground", children: label }), /* @__PURE__ */ jsx("span", { className: "min-w-0 truncate px-2 py-1 font-mono text-foreground", children: value }), /* @__PURE__ */ jsx(Icon, { name: "lucide:copy", className: "mr-1.5 h-3 w-3 shrink-0 text-muted-foreground" }) ] } ); } function copyText(value) { if (typeof navigator !== "undefined" && navigator.clipboard) { void navigator.clipboard.writeText(value); } } export { CopyBadge, ErrorDetails, PrettyStackTrace }; //# sourceMappingURL=ErrorDetails.js.map