openclaw/apps/web/app/components/charts/chart-panel.tsx

427 lines
12 KiB
TypeScript
Raw Normal View History

2026-02-11 18:35:35 -08:00
"use client";
import { useMemo } from "react";
import {
BarChart,
Bar,
LineChart,
Line,
AreaChart,
Area,
PieChart,
Pie,
Cell,
RadarChart,
Radar,
PolarGrid,
PolarAngleAxis,
PolarRadiusAxis,
ScatterChart,
Scatter,
XAxis,
YAxis,
CartesianGrid,
Tooltip,
Legend,
ResponsiveContainer,
FunnelChart,
Funnel,
LabelList,
} from "recharts";
import type { PanelConfig } from "./types";
// --- Color palette derived from CSS variables + accessible defaults ---
const CHART_PALETTE = [
feat(web): full UI redesign with light/dark theme, TanStack data tables, media rendering, and gateway-routed agent execution Overhaul the Dench web app with a comprehensive visual redesign and several major feature additions across the chat interface, workspace, and agent runtime layer. Theme & Design System - Replace the dark-only palette with a full light/dark theme system that respects system preference via localStorage + inline script (no FOUC). - Introduce new design tokens: glassmorphism surfaces, semantic colors (success/warning/error/info), object-type chip palettes, and a tiered shadow scale (sm/md/lg/xl). - Add Instrument Serif + Inter via Google Fonts for a refined typographic hierarchy; headings use the serif face, body uses Inter. - Rebrand UI from "Ironclaw" to "Dench" across the landing page and metadata. Chat & Chain-of-Thought - Rewrite the chain-of-thought component with inline media detection and rendering — images, video, audio, and PDFs referenced in agent output are now displayed directly in the conversation thread. - Add status indicator parts (e.g. "Preparing response...", "Optimizing session context...") that render as subtle activity badges instead of verbose reasoning blocks. - Integrate react-markdown with remark-gfm for proper markdown rendering in assistant messages (tables, strikethrough, autolinks, etc.). - Improve report-block splitting and lazy-loaded ReportCard rendering. Workspace - Introduce @tanstack/react-table for the object table, replacing the hand-rolled table with full column sorting, fuzzy filtering via match-sorter-utils, row selection, and bulk actions. - Add a new media viewer component for in-workspace image/video/PDF preview. - New API routes: bulk-delete entries, field management (CRUD + reorder), raw-file serving endpoint for media assets. - Redesign workspace sidebar, empty state, and entry detail modal with the new theme tokens and improved layout. Agent Runtime - Switch web agent execution from --local to gateway-routed mode so concurrent chat threads share the gateway's lane-based concurrency system, eliminating cross-process file-lock contention. - Advertise "tool-events" capability during WebSocket handshake so the gateway streams tool start/update/result events to the UI. - Add new agent callback hooks: onLifecycleStart, onCompactionStart/End, and onToolUpdate for richer real-time feedback. - Forward media URLs emitted by agent events into the chat stream. Dependencies - Add @tanstack/match-sorter-utils and @tanstack/react-table to the web app. Published as ironclaw@2026.2.10-1. Co-authored-by: Cursor <cursoragent@cursor.com>
2026-02-12 11:17:23 -08:00
"#2563eb", // accent
2026-02-11 18:35:35 -08:00
"#60a5fa", // blue
"#22c55e", // green
"#f59e0b", // amber
"#c084fc", // purple
"#fb923c", // orange
"#14b8a6", // teal
"#f43f5e", // rose
"#a78bfa", // violet
"#38bdf8", // sky
];
type ChartPanelProps = {
config: PanelConfig;
data: Record<string, unknown>[];
/** Compact mode for inline chat cards */
compact?: boolean;
};
// --- Shared tooltip/axis styles ---
const axisStyle = {
fontSize: 11,
feat(web): full UI redesign with light/dark theme, TanStack data tables, media rendering, and gateway-routed agent execution Overhaul the Dench web app with a comprehensive visual redesign and several major feature additions across the chat interface, workspace, and agent runtime layer. Theme & Design System - Replace the dark-only palette with a full light/dark theme system that respects system preference via localStorage + inline script (no FOUC). - Introduce new design tokens: glassmorphism surfaces, semantic colors (success/warning/error/info), object-type chip palettes, and a tiered shadow scale (sm/md/lg/xl). - Add Instrument Serif + Inter via Google Fonts for a refined typographic hierarchy; headings use the serif face, body uses Inter. - Rebrand UI from "Ironclaw" to "Dench" across the landing page and metadata. Chat & Chain-of-Thought - Rewrite the chain-of-thought component with inline media detection and rendering — images, video, audio, and PDFs referenced in agent output are now displayed directly in the conversation thread. - Add status indicator parts (e.g. "Preparing response...", "Optimizing session context...") that render as subtle activity badges instead of verbose reasoning blocks. - Integrate react-markdown with remark-gfm for proper markdown rendering in assistant messages (tables, strikethrough, autolinks, etc.). - Improve report-block splitting and lazy-loaded ReportCard rendering. Workspace - Introduce @tanstack/react-table for the object table, replacing the hand-rolled table with full column sorting, fuzzy filtering via match-sorter-utils, row selection, and bulk actions. - Add a new media viewer component for in-workspace image/video/PDF preview. - New API routes: bulk-delete entries, field management (CRUD + reorder), raw-file serving endpoint for media assets. - Redesign workspace sidebar, empty state, and entry detail modal with the new theme tokens and improved layout. Agent Runtime - Switch web agent execution from --local to gateway-routed mode so concurrent chat threads share the gateway's lane-based concurrency system, eliminating cross-process file-lock contention. - Advertise "tool-events" capability during WebSocket handshake so the gateway streams tool start/update/result events to the UI. - Add new agent callback hooks: onLifecycleStart, onCompactionStart/End, and onToolUpdate for richer real-time feedback. - Forward media URLs emitted by agent events into the chat stream. Dependencies - Add @tanstack/match-sorter-utils and @tanstack/react-table to the web app. Published as ironclaw@2026.2.10-1. Co-authored-by: Cursor <cursoragent@cursor.com>
2026-02-12 11:17:23 -08:00
fill: "var(--color-text-muted)",
2026-02-11 18:35:35 -08:00
};
const gridStyle = {
feat(web): full UI redesign with light/dark theme, TanStack data tables, media rendering, and gateway-routed agent execution Overhaul the Dench web app with a comprehensive visual redesign and several major feature additions across the chat interface, workspace, and agent runtime layer. Theme & Design System - Replace the dark-only palette with a full light/dark theme system that respects system preference via localStorage + inline script (no FOUC). - Introduce new design tokens: glassmorphism surfaces, semantic colors (success/warning/error/info), object-type chip palettes, and a tiered shadow scale (sm/md/lg/xl). - Add Instrument Serif + Inter via Google Fonts for a refined typographic hierarchy; headings use the serif face, body uses Inter. - Rebrand UI from "Ironclaw" to "Dench" across the landing page and metadata. Chat & Chain-of-Thought - Rewrite the chain-of-thought component with inline media detection and rendering — images, video, audio, and PDFs referenced in agent output are now displayed directly in the conversation thread. - Add status indicator parts (e.g. "Preparing response...", "Optimizing session context...") that render as subtle activity badges instead of verbose reasoning blocks. - Integrate react-markdown with remark-gfm for proper markdown rendering in assistant messages (tables, strikethrough, autolinks, etc.). - Improve report-block splitting and lazy-loaded ReportCard rendering. Workspace - Introduce @tanstack/react-table for the object table, replacing the hand-rolled table with full column sorting, fuzzy filtering via match-sorter-utils, row selection, and bulk actions. - Add a new media viewer component for in-workspace image/video/PDF preview. - New API routes: bulk-delete entries, field management (CRUD + reorder), raw-file serving endpoint for media assets. - Redesign workspace sidebar, empty state, and entry detail modal with the new theme tokens and improved layout. Agent Runtime - Switch web agent execution from --local to gateway-routed mode so concurrent chat threads share the gateway's lane-based concurrency system, eliminating cross-process file-lock contention. - Advertise "tool-events" capability during WebSocket handshake so the gateway streams tool start/update/result events to the UI. - Add new agent callback hooks: onLifecycleStart, onCompactionStart/End, and onToolUpdate for richer real-time feedback. - Forward media URLs emitted by agent events into the chat stream. Dependencies - Add @tanstack/match-sorter-utils and @tanstack/react-table to the web app. Published as ironclaw@2026.2.10-1. Co-authored-by: Cursor <cursoragent@cursor.com>
2026-02-12 11:17:23 -08:00
stroke: "var(--color-border-strong)",
2026-02-11 18:35:35 -08:00
strokeDasharray: "3 3",
};
function tooltipStyle() {
return {
contentStyle: {
feat(web): full UI redesign with light/dark theme, TanStack data tables, media rendering, and gateway-routed agent execution Overhaul the Dench web app with a comprehensive visual redesign and several major feature additions across the chat interface, workspace, and agent runtime layer. Theme & Design System - Replace the dark-only palette with a full light/dark theme system that respects system preference via localStorage + inline script (no FOUC). - Introduce new design tokens: glassmorphism surfaces, semantic colors (success/warning/error/info), object-type chip palettes, and a tiered shadow scale (sm/md/lg/xl). - Add Instrument Serif + Inter via Google Fonts for a refined typographic hierarchy; headings use the serif face, body uses Inter. - Rebrand UI from "Ironclaw" to "Dench" across the landing page and metadata. Chat & Chain-of-Thought - Rewrite the chain-of-thought component with inline media detection and rendering — images, video, audio, and PDFs referenced in agent output are now displayed directly in the conversation thread. - Add status indicator parts (e.g. "Preparing response...", "Optimizing session context...") that render as subtle activity badges instead of verbose reasoning blocks. - Integrate react-markdown with remark-gfm for proper markdown rendering in assistant messages (tables, strikethrough, autolinks, etc.). - Improve report-block splitting and lazy-loaded ReportCard rendering. Workspace - Introduce @tanstack/react-table for the object table, replacing the hand-rolled table with full column sorting, fuzzy filtering via match-sorter-utils, row selection, and bulk actions. - Add a new media viewer component for in-workspace image/video/PDF preview. - New API routes: bulk-delete entries, field management (CRUD + reorder), raw-file serving endpoint for media assets. - Redesign workspace sidebar, empty state, and entry detail modal with the new theme tokens and improved layout. Agent Runtime - Switch web agent execution from --local to gateway-routed mode so concurrent chat threads share the gateway's lane-based concurrency system, eliminating cross-process file-lock contention. - Advertise "tool-events" capability during WebSocket handshake so the gateway streams tool start/update/result events to the UI. - Add new agent callback hooks: onLifecycleStart, onCompactionStart/End, and onToolUpdate for richer real-time feedback. - Forward media URLs emitted by agent events into the chat stream. Dependencies - Add @tanstack/match-sorter-utils and @tanstack/react-table to the web app. Published as ironclaw@2026.2.10-1. Co-authored-by: Cursor <cursoragent@cursor.com>
2026-02-12 11:17:23 -08:00
background: "var(--color-surface)",
border: "1px solid var(--color-border)",
2026-02-11 18:35:35 -08:00
borderRadius: 8,
fontSize: 12,
feat(web): full UI redesign with light/dark theme, TanStack data tables, media rendering, and gateway-routed agent execution Overhaul the Dench web app with a comprehensive visual redesign and several major feature additions across the chat interface, workspace, and agent runtime layer. Theme & Design System - Replace the dark-only palette with a full light/dark theme system that respects system preference via localStorage + inline script (no FOUC). - Introduce new design tokens: glassmorphism surfaces, semantic colors (success/warning/error/info), object-type chip palettes, and a tiered shadow scale (sm/md/lg/xl). - Add Instrument Serif + Inter via Google Fonts for a refined typographic hierarchy; headings use the serif face, body uses Inter. - Rebrand UI from "Ironclaw" to "Dench" across the landing page and metadata. Chat & Chain-of-Thought - Rewrite the chain-of-thought component with inline media detection and rendering — images, video, audio, and PDFs referenced in agent output are now displayed directly in the conversation thread. - Add status indicator parts (e.g. "Preparing response...", "Optimizing session context...") that render as subtle activity badges instead of verbose reasoning blocks. - Integrate react-markdown with remark-gfm for proper markdown rendering in assistant messages (tables, strikethrough, autolinks, etc.). - Improve report-block splitting and lazy-loaded ReportCard rendering. Workspace - Introduce @tanstack/react-table for the object table, replacing the hand-rolled table with full column sorting, fuzzy filtering via match-sorter-utils, row selection, and bulk actions. - Add a new media viewer component for in-workspace image/video/PDF preview. - New API routes: bulk-delete entries, field management (CRUD + reorder), raw-file serving endpoint for media assets. - Redesign workspace sidebar, empty state, and entry detail modal with the new theme tokens and improved layout. Agent Runtime - Switch web agent execution from --local to gateway-routed mode so concurrent chat threads share the gateway's lane-based concurrency system, eliminating cross-process file-lock contention. - Advertise "tool-events" capability during WebSocket handshake so the gateway streams tool start/update/result events to the UI. - Add new agent callback hooks: onLifecycleStart, onCompactionStart/End, and onToolUpdate for richer real-time feedback. - Forward media URLs emitted by agent events into the chat stream. Dependencies - Add @tanstack/match-sorter-utils and @tanstack/react-table to the web app. Published as ironclaw@2026.2.10-1. Co-authored-by: Cursor <cursoragent@cursor.com>
2026-02-12 11:17:23 -08:00
color: "var(--color-text)",
2026-02-11 18:35:35 -08:00
},
feat(web): full UI redesign with light/dark theme, TanStack data tables, media rendering, and gateway-routed agent execution Overhaul the Dench web app with a comprehensive visual redesign and several major feature additions across the chat interface, workspace, and agent runtime layer. Theme & Design System - Replace the dark-only palette with a full light/dark theme system that respects system preference via localStorage + inline script (no FOUC). - Introduce new design tokens: glassmorphism surfaces, semantic colors (success/warning/error/info), object-type chip palettes, and a tiered shadow scale (sm/md/lg/xl). - Add Instrument Serif + Inter via Google Fonts for a refined typographic hierarchy; headings use the serif face, body uses Inter. - Rebrand UI from "Ironclaw" to "Dench" across the landing page and metadata. Chat & Chain-of-Thought - Rewrite the chain-of-thought component with inline media detection and rendering — images, video, audio, and PDFs referenced in agent output are now displayed directly in the conversation thread. - Add status indicator parts (e.g. "Preparing response...", "Optimizing session context...") that render as subtle activity badges instead of verbose reasoning blocks. - Integrate react-markdown with remark-gfm for proper markdown rendering in assistant messages (tables, strikethrough, autolinks, etc.). - Improve report-block splitting and lazy-loaded ReportCard rendering. Workspace - Introduce @tanstack/react-table for the object table, replacing the hand-rolled table with full column sorting, fuzzy filtering via match-sorter-utils, row selection, and bulk actions. - Add a new media viewer component for in-workspace image/video/PDF preview. - New API routes: bulk-delete entries, field management (CRUD + reorder), raw-file serving endpoint for media assets. - Redesign workspace sidebar, empty state, and entry detail modal with the new theme tokens and improved layout. Agent Runtime - Switch web agent execution from --local to gateway-routed mode so concurrent chat threads share the gateway's lane-based concurrency system, eliminating cross-process file-lock contention. - Advertise "tool-events" capability during WebSocket handshake so the gateway streams tool start/update/result events to the UI. - Add new agent callback hooks: onLifecycleStart, onCompactionStart/End, and onToolUpdate for richer real-time feedback. - Forward media URLs emitted by agent events into the chat stream. Dependencies - Add @tanstack/match-sorter-utils and @tanstack/react-table to the web app. Published as ironclaw@2026.2.10-1. Co-authored-by: Cursor <cursoragent@cursor.com>
2026-02-12 11:17:23 -08:00
itemStyle: { color: "var(--color-text)" },
labelStyle: { color: "var(--color-text-muted)", marginBottom: 4 },
2026-02-11 18:35:35 -08:00
};
}
// --- Formatters ---
/** Safe string conversion for chart values (handles objects via JSON.stringify). */
function toDisplayStr(val: unknown): string {
if (val == null) {return "";}
if (typeof val === "object") {return JSON.stringify(val);}
if (typeof val === "string") {return val;}
if (typeof val === "number" || typeof val === "boolean") {return String(val);}
// symbol, bigint, function — val is narrowed (object already handled above)
// eslint-disable-next-line @typescript-eslint/no-base-to-string
return String(val);
}
2026-02-11 18:35:35 -08:00
function formatValue(val: unknown): string {
if (val === null || val === undefined) {return "";}
if (typeof val === "object") {return JSON.stringify(val);}
2026-02-11 18:35:35 -08:00
if (typeof val === "number") {
if (Math.abs(val) >= 1_000_000) {return `${(val / 1_000_000).toFixed(1)}M`;}
if (Math.abs(val) >= 1_000) {return `${(val / 1_000).toFixed(1)}K`;}
return Number.isInteger(val) ? String(val) : val.toFixed(2);
}
return toDisplayStr(val);
2026-02-11 18:35:35 -08:00
}
function formatLabel(val: unknown): string {
if (val === null || val === undefined) {return "";}
const str = toDisplayStr(val);
2026-02-11 18:35:35 -08:00
// Truncate long date strings
if (str.length > 16 && !isNaN(Date.parse(str))) {
return str.slice(0, 10);
}
// Truncate long labels
if (str.length > 20) {return str.slice(0, 18) + "...";}
return str;
}
// --- Chart renderers ---
function CartesianChart({
config,
data,
compact,
ChartComponent,
SeriesComponent,
areaProps,
}: {
config: PanelConfig;
data: Record<string, unknown>[];
compact?: boolean;
feat(web): full UI redesign with light/dark theme, TanStack data tables, media rendering, and gateway-routed agent execution Overhaul the Dench web app with a comprehensive visual redesign and several major feature additions across the chat interface, workspace, and agent runtime layer. Theme & Design System - Replace the dark-only palette with a full light/dark theme system that respects system preference via localStorage + inline script (no FOUC). - Introduce new design tokens: glassmorphism surfaces, semantic colors (success/warning/error/info), object-type chip palettes, and a tiered shadow scale (sm/md/lg/xl). - Add Instrument Serif + Inter via Google Fonts for a refined typographic hierarchy; headings use the serif face, body uses Inter. - Rebrand UI from "Ironclaw" to "Dench" across the landing page and metadata. Chat & Chain-of-Thought - Rewrite the chain-of-thought component with inline media detection and rendering — images, video, audio, and PDFs referenced in agent output are now displayed directly in the conversation thread. - Add status indicator parts (e.g. "Preparing response...", "Optimizing session context...") that render as subtle activity badges instead of verbose reasoning blocks. - Integrate react-markdown with remark-gfm for proper markdown rendering in assistant messages (tables, strikethrough, autolinks, etc.). - Improve report-block splitting and lazy-loaded ReportCard rendering. Workspace - Introduce @tanstack/react-table for the object table, replacing the hand-rolled table with full column sorting, fuzzy filtering via match-sorter-utils, row selection, and bulk actions. - Add a new media viewer component for in-workspace image/video/PDF preview. - New API routes: bulk-delete entries, field management (CRUD + reorder), raw-file serving endpoint for media assets. - Redesign workspace sidebar, empty state, and entry detail modal with the new theme tokens and improved layout. Agent Runtime - Switch web agent execution from --local to gateway-routed mode so concurrent chat threads share the gateway's lane-based concurrency system, eliminating cross-process file-lock contention. - Advertise "tool-events" capability during WebSocket handshake so the gateway streams tool start/update/result events to the UI. - Add new agent callback hooks: onLifecycleStart, onCompactionStart/End, and onToolUpdate for richer real-time feedback. - Forward media URLs emitted by agent events into the chat stream. Dependencies - Add @tanstack/match-sorter-utils and @tanstack/react-table to the web app. Published as ironclaw@2026.2.10-1. Co-authored-by: Cursor <cursoragent@cursor.com>
2026-02-12 11:17:23 -08:00
ChartComponent: typeof BarChart ;
2026-02-11 18:35:35 -08:00
SeriesComponent: typeof Bar | typeof Line | typeof Area;
areaProps?: Record<string, unknown>;
}) {
const { mapping } = config;
const xKey = mapping.xAxis ?? Object.keys(data[0] ?? {})[0] ?? "x";
const yKeys = mapping.yAxis ?? Object.keys(data[0] ?? {}).filter((k) => k !== xKey);
const colors = mapping.colors ?? CHART_PALETTE;
const height = compact ? 200 : 320;
const ttStyle = tooltipStyle();
return (
<ResponsiveContainer width="100%" height={height}>
<ChartComponent data={data} margin={{ top: 8, right: 16, left: 0, bottom: 4 }}>
<CartesianGrid {...gridStyle} />
<XAxis
dataKey={xKey}
tick={axisStyle}
tickFormatter={formatLabel}
feat(web): full UI redesign with light/dark theme, TanStack data tables, media rendering, and gateway-routed agent execution Overhaul the Dench web app with a comprehensive visual redesign and several major feature additions across the chat interface, workspace, and agent runtime layer. Theme & Design System - Replace the dark-only palette with a full light/dark theme system that respects system preference via localStorage + inline script (no FOUC). - Introduce new design tokens: glassmorphism surfaces, semantic colors (success/warning/error/info), object-type chip palettes, and a tiered shadow scale (sm/md/lg/xl). - Add Instrument Serif + Inter via Google Fonts for a refined typographic hierarchy; headings use the serif face, body uses Inter. - Rebrand UI from "Ironclaw" to "Dench" across the landing page and metadata. Chat & Chain-of-Thought - Rewrite the chain-of-thought component with inline media detection and rendering — images, video, audio, and PDFs referenced in agent output are now displayed directly in the conversation thread. - Add status indicator parts (e.g. "Preparing response...", "Optimizing session context...") that render as subtle activity badges instead of verbose reasoning blocks. - Integrate react-markdown with remark-gfm for proper markdown rendering in assistant messages (tables, strikethrough, autolinks, etc.). - Improve report-block splitting and lazy-loaded ReportCard rendering. Workspace - Introduce @tanstack/react-table for the object table, replacing the hand-rolled table with full column sorting, fuzzy filtering via match-sorter-utils, row selection, and bulk actions. - Add a new media viewer component for in-workspace image/video/PDF preview. - New API routes: bulk-delete entries, field management (CRUD + reorder), raw-file serving endpoint for media assets. - Redesign workspace sidebar, empty state, and entry detail modal with the new theme tokens and improved layout. Agent Runtime - Switch web agent execution from --local to gateway-routed mode so concurrent chat threads share the gateway's lane-based concurrency system, eliminating cross-process file-lock contention. - Advertise "tool-events" capability during WebSocket handshake so the gateway streams tool start/update/result events to the UI. - Add new agent callback hooks: onLifecycleStart, onCompactionStart/End, and onToolUpdate for richer real-time feedback. - Forward media URLs emitted by agent events into the chat stream. Dependencies - Add @tanstack/match-sorter-utils and @tanstack/react-table to the web app. Published as ironclaw@2026.2.10-1. Co-authored-by: Cursor <cursoragent@cursor.com>
2026-02-12 11:17:23 -08:00
axisLine={{ stroke: "var(--color-border)" }}
2026-02-11 18:35:35 -08:00
tickLine={false}
/>
<YAxis
tick={axisStyle}
tickFormatter={formatValue}
axisLine={false}
tickLine={false}
width={48}
/>
<Tooltip {...ttStyle} formatter={formatValue} labelFormatter={formatLabel} />
{yKeys.length > 1 && !compact && <Legend wrapperStyle={{ fontSize: 11 }} />}
{yKeys.map((key, i) => {
const color = colors[i % colors.length];
const props: Record<string, unknown> = {
key,
dataKey: key,
fill: color,
stroke: color,
name: key,
...areaProps,
};
if (SeriesComponent === Bar) {
props.radius = [4, 4, 0, 0];
props.maxBarSize = 48;
}
if (SeriesComponent === Line) {
props.strokeWidth = 2;
props.dot = { r: 3, fill: color };
props.activeDot = { r: 5 };
}
if (SeriesComponent === Area) {
props.fillOpacity = 0.15;
props.strokeWidth = 2;
}
// @ts-expect-error - dynamic component props
return <SeriesComponent {...props} />;
})}
</ChartComponent>
</ResponsiveContainer>
);
}
function PieDonutChart({
config,
data,
compact,
}: {
config: PanelConfig;
data: Record<string, unknown>[];
compact?: boolean;
}) {
const { mapping, type } = config;
const nameKey = mapping.nameKey ?? Object.keys(data[0] ?? {})[0] ?? "name";
const valueKey = mapping.valueKey ?? Object.keys(data[0] ?? {})[1] ?? "value";
const colors = mapping.colors ?? CHART_PALETTE;
const height = compact ? 200 : 320;
const ttStyle = tooltipStyle();
const innerRadius = type === "donut" ? "50%" : 0;
return (
<ResponsiveContainer width="100%" height={height}>
<PieChart>
<Pie
data={data}
dataKey={valueKey}
nameKey={nameKey}
cx="50%"
cy="50%"
innerRadius={innerRadius}
outerRadius={compact ? 70 : 110}
paddingAngle={2}
label={compact ? undefined : ((props: unknown) => {
const p = props as Record<string, unknown>;
const name = p.name;
const percent = typeof p.percent === "number" ? p.percent : 0;
return `${formatLabel(name)} ${(percent * 100).toFixed(0)}%`;
}) as never}
labelLine={!compact}
style={{ fontSize: 11 }}
>
{data.map((_, i) => (
<Cell key={i} fill={colors[i % colors.length]} />
))}
</Pie>
<Tooltip {...ttStyle} formatter={formatValue} />
{!compact && <Legend wrapperStyle={{ fontSize: 11 }} />}
</PieChart>
</ResponsiveContainer>
);
}
function RadarChartPanel({
config,
data,
compact,
}: {
config: PanelConfig;
data: Record<string, unknown>[];
compact?: boolean;
}) {
const { mapping } = config;
const nameKey = mapping.xAxis ?? mapping.nameKey ?? Object.keys(data[0] ?? {})[0] ?? "name";
const valueKeys = mapping.yAxis ?? [Object.keys(data[0] ?? {})[1] ?? "value"];
const colors = mapping.colors ?? CHART_PALETTE;
const height = compact ? 200 : 320;
const ttStyle = tooltipStyle();
return (
<ResponsiveContainer width="100%" height={height}>
<RadarChart data={data} cx="50%" cy="50%" outerRadius={compact ? 60 : 100}>
feat(web): full UI redesign with light/dark theme, TanStack data tables, media rendering, and gateway-routed agent execution Overhaul the Dench web app with a comprehensive visual redesign and several major feature additions across the chat interface, workspace, and agent runtime layer. Theme & Design System - Replace the dark-only palette with a full light/dark theme system that respects system preference via localStorage + inline script (no FOUC). - Introduce new design tokens: glassmorphism surfaces, semantic colors (success/warning/error/info), object-type chip palettes, and a tiered shadow scale (sm/md/lg/xl). - Add Instrument Serif + Inter via Google Fonts for a refined typographic hierarchy; headings use the serif face, body uses Inter. - Rebrand UI from "Ironclaw" to "Dench" across the landing page and metadata. Chat & Chain-of-Thought - Rewrite the chain-of-thought component with inline media detection and rendering — images, video, audio, and PDFs referenced in agent output are now displayed directly in the conversation thread. - Add status indicator parts (e.g. "Preparing response...", "Optimizing session context...") that render as subtle activity badges instead of verbose reasoning blocks. - Integrate react-markdown with remark-gfm for proper markdown rendering in assistant messages (tables, strikethrough, autolinks, etc.). - Improve report-block splitting and lazy-loaded ReportCard rendering. Workspace - Introduce @tanstack/react-table for the object table, replacing the hand-rolled table with full column sorting, fuzzy filtering via match-sorter-utils, row selection, and bulk actions. - Add a new media viewer component for in-workspace image/video/PDF preview. - New API routes: bulk-delete entries, field management (CRUD + reorder), raw-file serving endpoint for media assets. - Redesign workspace sidebar, empty state, and entry detail modal with the new theme tokens and improved layout. Agent Runtime - Switch web agent execution from --local to gateway-routed mode so concurrent chat threads share the gateway's lane-based concurrency system, eliminating cross-process file-lock contention. - Advertise "tool-events" capability during WebSocket handshake so the gateway streams tool start/update/result events to the UI. - Add new agent callback hooks: onLifecycleStart, onCompactionStart/End, and onToolUpdate for richer real-time feedback. - Forward media URLs emitted by agent events into the chat stream. Dependencies - Add @tanstack/match-sorter-utils and @tanstack/react-table to the web app. Published as ironclaw@2026.2.10-1. Co-authored-by: Cursor <cursoragent@cursor.com>
2026-02-12 11:17:23 -08:00
<PolarGrid stroke="var(--color-border)" />
<PolarAngleAxis dataKey={nameKey} tick={{ fontSize: 11, fill: "var(--color-text-muted)" }} />
<PolarRadiusAxis tick={{ fontSize: 10, fill: "var(--color-text-muted)" }} />
2026-02-11 18:35:35 -08:00
{valueKeys.map((key, i) => (
<Radar
key={key}
name={key}
dataKey={key}
stroke={colors[i % colors.length]}
fill={colors[i % colors.length]}
fillOpacity={0.2}
/>
))}
<Tooltip {...ttStyle} />
{!compact && valueKeys.length > 1 && <Legend wrapperStyle={{ fontSize: 11 }} />}
</RadarChart>
</ResponsiveContainer>
);
}
function ScatterChartPanel({
config,
data,
compact,
}: {
config: PanelConfig;
data: Record<string, unknown>[];
compact?: boolean;
}) {
const { mapping } = config;
const xKey = mapping.xAxis ?? Object.keys(data[0] ?? {})[0] ?? "x";
const yKeys = mapping.yAxis ?? [Object.keys(data[0] ?? {})[1] ?? "y"];
const colors = mapping.colors ?? CHART_PALETTE;
const height = compact ? 200 : 320;
const ttStyle = tooltipStyle();
return (
<ResponsiveContainer width="100%" height={height}>
<ScatterChart margin={{ top: 8, right: 16, left: 0, bottom: 4 }}>
<CartesianGrid {...gridStyle} />
feat(web): full UI redesign with light/dark theme, TanStack data tables, media rendering, and gateway-routed agent execution Overhaul the Dench web app with a comprehensive visual redesign and several major feature additions across the chat interface, workspace, and agent runtime layer. Theme & Design System - Replace the dark-only palette with a full light/dark theme system that respects system preference via localStorage + inline script (no FOUC). - Introduce new design tokens: glassmorphism surfaces, semantic colors (success/warning/error/info), object-type chip palettes, and a tiered shadow scale (sm/md/lg/xl). - Add Instrument Serif + Inter via Google Fonts for a refined typographic hierarchy; headings use the serif face, body uses Inter. - Rebrand UI from "Ironclaw" to "Dench" across the landing page and metadata. Chat & Chain-of-Thought - Rewrite the chain-of-thought component with inline media detection and rendering — images, video, audio, and PDFs referenced in agent output are now displayed directly in the conversation thread. - Add status indicator parts (e.g. "Preparing response...", "Optimizing session context...") that render as subtle activity badges instead of verbose reasoning blocks. - Integrate react-markdown with remark-gfm for proper markdown rendering in assistant messages (tables, strikethrough, autolinks, etc.). - Improve report-block splitting and lazy-loaded ReportCard rendering. Workspace - Introduce @tanstack/react-table for the object table, replacing the hand-rolled table with full column sorting, fuzzy filtering via match-sorter-utils, row selection, and bulk actions. - Add a new media viewer component for in-workspace image/video/PDF preview. - New API routes: bulk-delete entries, field management (CRUD + reorder), raw-file serving endpoint for media assets. - Redesign workspace sidebar, empty state, and entry detail modal with the new theme tokens and improved layout. Agent Runtime - Switch web agent execution from --local to gateway-routed mode so concurrent chat threads share the gateway's lane-based concurrency system, eliminating cross-process file-lock contention. - Advertise "tool-events" capability during WebSocket handshake so the gateway streams tool start/update/result events to the UI. - Add new agent callback hooks: onLifecycleStart, onCompactionStart/End, and onToolUpdate for richer real-time feedback. - Forward media URLs emitted by agent events into the chat stream. Dependencies - Add @tanstack/match-sorter-utils and @tanstack/react-table to the web app. Published as ironclaw@2026.2.10-1. Co-authored-by: Cursor <cursoragent@cursor.com>
2026-02-12 11:17:23 -08:00
<XAxis dataKey={xKey} tick={axisStyle} name={xKey} axisLine={{ stroke: "var(--color-border)" }} tickLine={false} />
2026-02-11 18:35:35 -08:00
<YAxis tick={axisStyle} tickFormatter={formatValue} axisLine={false} tickLine={false} width={48} />
<Tooltip {...ttStyle} />
{yKeys.map((key, i) => (
<Scatter
key={key}
name={key}
data={data}
fill={colors[i % colors.length]}
/>
))}
{!compact && yKeys.length > 1 && <Legend wrapperStyle={{ fontSize: 11 }} />}
</ScatterChart>
</ResponsiveContainer>
);
}
function FunnelChartPanel({
config,
data,
compact,
}: {
config: PanelConfig;
data: Record<string, unknown>[];
compact?: boolean;
}) {
const { mapping } = config;
const nameKey = mapping.nameKey ?? Object.keys(data[0] ?? {})[0] ?? "name";
const valueKey = mapping.valueKey ?? Object.keys(data[0] ?? {})[1] ?? "value";
const colors = mapping.colors ?? CHART_PALETTE;
const height = compact ? 200 : 320;
const ttStyle = tooltipStyle();
// Funnel expects data with fill colors
const funnelData = data.map((row, i) => ({
...row,
fill: colors[i % colors.length],
}));
return (
<ResponsiveContainer width="100%" height={height}>
<FunnelChart>
<Tooltip {...ttStyle} />
<Funnel
data={funnelData}
dataKey={valueKey}
nameKey={nameKey}
isAnimationActive
>
<LabelList
position="right"
feat(web): full UI redesign with light/dark theme, TanStack data tables, media rendering, and gateway-routed agent execution Overhaul the Dench web app with a comprehensive visual redesign and several major feature additions across the chat interface, workspace, and agent runtime layer. Theme & Design System - Replace the dark-only palette with a full light/dark theme system that respects system preference via localStorage + inline script (no FOUC). - Introduce new design tokens: glassmorphism surfaces, semantic colors (success/warning/error/info), object-type chip palettes, and a tiered shadow scale (sm/md/lg/xl). - Add Instrument Serif + Inter via Google Fonts for a refined typographic hierarchy; headings use the serif face, body uses Inter. - Rebrand UI from "Ironclaw" to "Dench" across the landing page and metadata. Chat & Chain-of-Thought - Rewrite the chain-of-thought component with inline media detection and rendering — images, video, audio, and PDFs referenced in agent output are now displayed directly in the conversation thread. - Add status indicator parts (e.g. "Preparing response...", "Optimizing session context...") that render as subtle activity badges instead of verbose reasoning blocks. - Integrate react-markdown with remark-gfm for proper markdown rendering in assistant messages (tables, strikethrough, autolinks, etc.). - Improve report-block splitting and lazy-loaded ReportCard rendering. Workspace - Introduce @tanstack/react-table for the object table, replacing the hand-rolled table with full column sorting, fuzzy filtering via match-sorter-utils, row selection, and bulk actions. - Add a new media viewer component for in-workspace image/video/PDF preview. - New API routes: bulk-delete entries, field management (CRUD + reorder), raw-file serving endpoint for media assets. - Redesign workspace sidebar, empty state, and entry detail modal with the new theme tokens and improved layout. Agent Runtime - Switch web agent execution from --local to gateway-routed mode so concurrent chat threads share the gateway's lane-based concurrency system, eliminating cross-process file-lock contention. - Advertise "tool-events" capability during WebSocket handshake so the gateway streams tool start/update/result events to the UI. - Add new agent callback hooks: onLifecycleStart, onCompactionStart/End, and onToolUpdate for richer real-time feedback. - Forward media URLs emitted by agent events into the chat stream. Dependencies - Add @tanstack/match-sorter-utils and @tanstack/react-table to the web app. Published as ironclaw@2026.2.10-1. Co-authored-by: Cursor <cursoragent@cursor.com>
2026-02-12 11:17:23 -08:00
fill="var(--color-text-muted)"
2026-02-11 18:35:35 -08:00
stroke="none"
fontSize={11}
dataKey={nameKey}
/>
</Funnel>
</FunnelChart>
</ResponsiveContainer>
);
}
// --- Main ChartPanel component ---
export function ChartPanel({ config, data, compact }: ChartPanelProps) {
// Coerce numeric values for Recharts
const processedData = useMemo(() => {
if (!data || data.length === 0) {return [];}
const { mapping } = config;
const numericKeys = new Set([
...(mapping.yAxis ?? []),
...(mapping.valueKey ? [mapping.valueKey] : []),
]);
return data.map((row) => {
const out: Record<string, unknown> = { ...row };
for (const key of numericKeys) {
if (key in out) {
const v = out[key];
if (typeof v === "string" && v !== "" && !isNaN(Number(v))) {
out[key] = Number(v);
}
}
}
return out;
});
}, [data, config]);
if (processedData.length === 0) {
return (
<div
className="flex items-center justify-center rounded-xl"
style={{
height: compact ? 200 : 320,
background: "var(--color-surface)",
border: "1px solid var(--color-border)",
color: "var(--color-text-muted)",
fontSize: 13,
}}
>
No data
</div>
);
}
switch (config.type) {
case "bar":
return <CartesianChart config={config} data={processedData} compact={compact} ChartComponent={BarChart} SeriesComponent={Bar} />;
case "line":
return <CartesianChart config={config} data={processedData} compact={compact} ChartComponent={LineChart} SeriesComponent={Line} />;
case "area":
return <CartesianChart config={config} data={processedData} compact={compact} ChartComponent={AreaChart} SeriesComponent={Area} />;
case "pie":
return <PieDonutChart config={config} data={processedData} compact={compact} />;
case "donut":
return <PieDonutChart config={config} data={processedData} compact={compact} />;
case "radar":
case "radialBar":
return <RadarChartPanel config={config} data={processedData} compact={compact} />;
case "scatter":
return <ScatterChartPanel config={config} data={processedData} compact={compact} />;
case "funnel":
return <FunnelChartPanel config={config} data={processedData} compact={compact} />;
default:
return <CartesianChart config={config} data={processedData} compact={compact} ChartComponent={BarChart} SeriesComponent={Bar} />;
}
}