@page-speed/agent-everywhere 0.8.0 → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -7696,17 +7696,2281 @@ function MessageActions({
7696
7696
  children
7697
7697
  ] }) });
7698
7698
  }
7699
- function DataPayloadView({ payload, className }) {
7700
- if (payload.type === "chart" && payload.chart) {
7701
- return /* @__PURE__ */ jsxRuntime.jsx(ChartContainer, { data: payload.chart, className });
7699
+ function CardShell({ className, children }) {
7700
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn("rounded-2xl border bg-card text-card-foreground shadow-sm", className), children });
7701
+ }
7702
+ var DELTA_GLYPH = {
7703
+ up: "\u25B2",
7704
+ down: "\u25BC",
7705
+ flat: "\u2014"
7706
+ };
7707
+ var DELTA_DIRECTION_CLASSES = {
7708
+ up: "bg-emerald-50 text-emerald-600",
7709
+ down: "bg-red-50 text-red-600",
7710
+ flat: "bg-slate-100 text-slate-500"
7711
+ };
7712
+ var DELTA_TONE_CLASSES = {
7713
+ positive: "bg-emerald-50 text-emerald-600",
7714
+ negative: "bg-red-50 text-red-600",
7715
+ warning: "bg-amber-50 text-amber-600",
7716
+ info: "bg-blue-50 text-blue-600",
7717
+ neutral: "bg-slate-100 text-slate-500",
7718
+ muted: "bg-slate-100 text-slate-400",
7719
+ default: "bg-slate-100 text-slate-500"
7720
+ };
7721
+ function DeltaPill({
7722
+ value,
7723
+ text,
7724
+ direction,
7725
+ tone,
7726
+ hideArrow,
7727
+ className
7728
+ }) {
7729
+ const label = value ?? text ?? "";
7730
+ const colorClass = (tone && DELTA_TONE_CLASSES[tone]) ?? DELTA_DIRECTION_CLASSES[direction];
7731
+ return /* @__PURE__ */ jsxRuntime.jsxs(
7732
+ "span",
7733
+ {
7734
+ className: cn(
7735
+ "inline-flex items-center gap-1 rounded-full px-2 py-0.5 font-medium text-xs tabular-nums",
7736
+ colorClass,
7737
+ className
7738
+ ),
7739
+ children: [
7740
+ !hideArrow && /* @__PURE__ */ jsxRuntime.jsx("span", { "aria-hidden": "true", className: "text-[0.625rem] leading-none", children: DELTA_GLYPH[direction] }),
7741
+ label
7742
+ ]
7743
+ }
7744
+ );
7745
+ }
7746
+ var STATUS_DOT_COLORS = {
7747
+ healthy: "#10B981",
7748
+ warning: "#F59E0B",
7749
+ critical: "#EF4444"
7750
+ };
7751
+ function StatusDot({
7752
+ status = "healthy",
7753
+ color,
7754
+ label,
7755
+ size = 12,
7756
+ className
7757
+ }) {
7758
+ const fill = color ?? STATUS_DOT_COLORS[status];
7759
+ return /* @__PURE__ */ jsxRuntime.jsx(
7760
+ "span",
7761
+ {
7762
+ "data-status-dot": "",
7763
+ role: label ? "img" : void 0,
7764
+ "aria-label": label,
7765
+ title: label,
7766
+ className: cn("inline-block shrink-0 rounded-full", className),
7767
+ style: { width: size, height: size, backgroundColor: fill }
7768
+ }
7769
+ );
7770
+ }
7771
+ var TONE_TEXT_CLASSES = {
7772
+ default: "text-slate-800",
7773
+ positive: "text-emerald-600",
7774
+ negative: "text-red-600",
7775
+ neutral: "text-slate-500",
7776
+ warning: "text-amber-600",
7777
+ info: "text-blue-600",
7778
+ muted: "text-slate-400"
7779
+ };
7780
+ function toneTextColor(tone) {
7781
+ if (!tone) return TONE_TEXT_CLASSES.default;
7782
+ return TONE_TEXT_CLASSES[tone] ?? TONE_TEXT_CLASSES.default;
7783
+ }
7784
+ function toAlpha(n, upper) {
7785
+ let out = "";
7786
+ let value = n;
7787
+ while (value > 0) {
7788
+ const rem = (value - 1) % 26;
7789
+ out = String.fromCharCode(97 + rem) + out;
7790
+ value = Math.floor((value - 1) / 26);
7791
+ }
7792
+ return upper ? out.toUpperCase() : out;
7793
+ }
7794
+ var ROMAN_NUMERALS = [
7795
+ [1e3, "m"],
7796
+ [900, "cm"],
7797
+ [500, "d"],
7798
+ [400, "cd"],
7799
+ [100, "c"],
7800
+ [90, "xc"],
7801
+ [50, "l"],
7802
+ [40, "xl"],
7803
+ [10, "x"],
7804
+ [9, "ix"],
7805
+ [5, "v"],
7806
+ [4, "iv"],
7807
+ [1, "i"]
7808
+ ];
7809
+ function toRoman(n) {
7810
+ if (n <= 0) return String(n);
7811
+ let value = n;
7812
+ let out = "";
7813
+ for (const [num, sym] of ROMAN_NUMERALS) {
7814
+ while (value >= num) {
7815
+ out += sym;
7816
+ value -= num;
7817
+ }
7818
+ }
7819
+ return out;
7820
+ }
7821
+ function formatMarker(index, style, start = 1) {
7822
+ const n = index + start;
7823
+ switch (style) {
7824
+ case "lower-alpha":
7825
+ return toAlpha(n, false);
7826
+ case "upper-alpha":
7827
+ return toAlpha(n, true);
7828
+ case "lower-roman":
7829
+ return toRoman(n);
7830
+ default:
7831
+ return String(n);
7832
+ }
7833
+ }
7834
+ var DEFAULT_COLOR = "#10B981";
7835
+ var DEFAULT_WIDTH = 100;
7836
+ var DEFAULT_HEIGHT = 32;
7837
+ function normalizeSeries(data, w, h, pad = 2) {
7838
+ const n = data.length;
7839
+ if (n === 0) return [];
7840
+ const min = Math.min(...data);
7841
+ const max = Math.max(...data);
7842
+ const flat = max === min;
7843
+ const span = flat ? 1 : max - min;
7844
+ const inner = h - pad * 2;
7845
+ return data.map((v, i) => {
7846
+ const x = n === 1 ? w / 2 : i / (n - 1) * w;
7847
+ const y = flat ? h / 2 : h - pad - (v - min) / span * inner;
7848
+ return { x, y };
7849
+ });
7850
+ }
7851
+ function buildLinePath(pts, smooth = false) {
7852
+ if (pts.length < 2) return "";
7853
+ if (!smooth) {
7854
+ const [first, ...rest] = pts;
7855
+ return `M ${fmt(first.x)} ${fmt(first.y)}` + rest.map((p) => ` L ${fmt(p.x)} ${fmt(p.y)}`).join("");
7856
+ }
7857
+ let d = `M ${fmt(pts[0].x)} ${fmt(pts[0].y)}`;
7858
+ for (let i = 0; i < pts.length - 1; i++) {
7859
+ const p0 = pts[i - 1] ?? pts[i];
7860
+ const p1 = pts[i];
7861
+ const p2 = pts[i + 1];
7862
+ const p3 = pts[i + 2] ?? p2;
7863
+ const c1x = p1.x + (p2.x - p0.x) / 6;
7864
+ const c1y = p1.y + (p2.y - p0.y) / 6;
7865
+ const c2x = p2.x - (p3.x - p1.x) / 6;
7866
+ const c2y = p2.y - (p3.y - p1.y) / 6;
7867
+ d += ` C ${fmt(c1x)} ${fmt(c1y)}, ${fmt(c2x)} ${fmt(c2y)}, ${fmt(p2.x)} ${fmt(p2.y)}`;
7868
+ }
7869
+ return d;
7870
+ }
7871
+ function buildAreaPath(pts, h, smooth = false) {
7872
+ if (pts.length < 2) return "";
7873
+ const line = buildLinePath(pts, smooth);
7874
+ if (!line) return "";
7875
+ const last = pts[pts.length - 1];
7876
+ const first = pts[0];
7877
+ return `${line} L ${fmt(last.x)} ${fmt(h)} L ${fmt(first.x)} ${fmt(h)} Z`;
7878
+ }
7879
+ function fmt(n) {
7880
+ return Number.isInteger(n) ? String(n) : String(Math.round(n * 1e3) / 1e3);
7881
+ }
7882
+ function Sparkline({
7883
+ data,
7884
+ color = DEFAULT_COLOR,
7885
+ showArea = false,
7886
+ smooth = false,
7887
+ width = DEFAULT_WIDTH,
7888
+ height = DEFAULT_HEIGHT,
7889
+ pad = 2,
7890
+ strokeWidth = 2,
7891
+ className
7892
+ }) {
7893
+ const gradientId = React4.useId();
7894
+ if (data.length < 2) return null;
7895
+ const points = normalizeSeries(data, width, height, pad);
7896
+ const linePath = buildLinePath(points, smooth);
7897
+ const areaPath = showArea ? buildAreaPath(points, height, smooth) : "";
7898
+ return /* @__PURE__ */ jsxRuntime.jsxs(
7899
+ "svg",
7900
+ {
7901
+ className: cn("block", className),
7902
+ viewBox: `0 0 ${width} ${height}`,
7903
+ preserveAspectRatio: "none",
7904
+ "aria-hidden": "true",
7905
+ focusable: "false",
7906
+ children: [
7907
+ showArea && areaPath && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
7908
+ /* @__PURE__ */ jsxRuntime.jsx("defs", { children: /* @__PURE__ */ jsxRuntime.jsxs("linearGradient", { id: gradientId, x1: "0", y1: "0", x2: "0", y2: "1", children: [
7909
+ /* @__PURE__ */ jsxRuntime.jsx("stop", { offset: "0%", stopColor: color, stopOpacity: 0.18 }),
7910
+ /* @__PURE__ */ jsxRuntime.jsx("stop", { offset: "100%", stopColor: color, stopOpacity: 0 })
7911
+ ] }) }),
7912
+ /* @__PURE__ */ jsxRuntime.jsx("path", { d: areaPath, fill: `url(#${gradientId})`, stroke: "none" })
7913
+ ] }),
7914
+ /* @__PURE__ */ jsxRuntime.jsx(
7915
+ "path",
7916
+ {
7917
+ d: linePath,
7918
+ fill: "none",
7919
+ stroke: color,
7920
+ strokeWidth,
7921
+ strokeLinecap: "round",
7922
+ strokeLinejoin: "round",
7923
+ style: { vectorEffect: "non-scaling-stroke" }
7924
+ }
7925
+ )
7926
+ ]
7927
+ }
7928
+ );
7929
+ }
7930
+ var DEFAULT_SERIES_COLOR = "#3B82F6";
7931
+ var DEFAULT_PILL_COLOR = "#3B6FE0";
7932
+ var BASELINE_COLOR = "#EEF1F5";
7933
+ var CHART_WIDTH = 900;
7934
+ var CHART_HEIGHT = 240;
7935
+ function hexToRgba(hex, alpha) {
7936
+ const match = /^#?([\da-f]{6})$/i.exec(hex.trim());
7937
+ if (!match) return hex;
7938
+ const int = parseInt(match[1], 16);
7939
+ const r = int >> 16 & 255;
7940
+ const g = int >> 8 & 255;
7941
+ const b = int & 255;
7942
+ return `rgba(${r}, ${g}, ${b}, ${alpha})`;
7943
+ }
7944
+ function splitTickLabel(label) {
7945
+ const match = /^(.*?)[\s\u00a0]+(\S+)$/.exec(label.trim());
7946
+ if (!match) return [label];
7947
+ return [match[1], match[2]];
7948
+ }
7949
+ function KpiCardWithChart({
7950
+ title,
7951
+ rangeLabel,
7952
+ data,
7953
+ xAxisLabels,
7954
+ value,
7955
+ delta,
7956
+ seriesColor = DEFAULT_SERIES_COLOR,
7957
+ pillColor = DEFAULT_PILL_COLOR,
7958
+ showBaseline = true,
7959
+ valuePrefix,
7960
+ valueSuffix,
7961
+ className
7962
+ }) {
7963
+ const series = data?.map((point) => point.value) ?? [];
7964
+ const hasChart = series.length >= 2;
7965
+ const hasData = series.length > 0;
7966
+ const formattedValue = value === void 0 || value === null ? null : `${valuePrefix ?? ""}${value}${valueSuffix ?? ""}`;
7967
+ const sparklineProps = {
7968
+ data: series,
7969
+ color: seriesColor,
7970
+ showArea: true,
7971
+ smooth: true,
7972
+ width: CHART_WIDTH,
7973
+ height: CHART_HEIGHT,
7974
+ pad: 12,
7975
+ strokeWidth: 2.5
7976
+ };
7977
+ return /* @__PURE__ */ jsxRuntime.jsxs(CardShell, { className: cn("w-full overflow-hidden bg-white p-7 sm:p-8", className), children: [
7978
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-start justify-between gap-4", children: [
7979
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "min-w-0", children: [
7980
+ /* @__PURE__ */ jsxRuntime.jsx("h3", { className: "truncate font-bold text-base text-slate-900 leading-tight tracking-tight", children: title }),
7981
+ formattedValue !== null && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mt-1 flex items-center gap-2", children: [
7982
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-bold text-2xl text-slate-900 tabular-nums", children: formattedValue }),
7983
+ delta && /* @__PURE__ */ jsxRuntime.jsx(DeltaPill, { value: delta.value, direction: delta.direction })
7984
+ ] })
7985
+ ] }),
7986
+ rangeLabel && /* @__PURE__ */ jsxRuntime.jsx(
7987
+ "span",
7988
+ {
7989
+ className: "shrink-0 rounded-full px-4 py-1.5 font-semibold text-xs",
7990
+ style: {
7991
+ color: pillColor,
7992
+ backgroundColor: hexToRgba(pillColor, 0.12)
7993
+ },
7994
+ children: rangeLabel
7995
+ }
7996
+ )
7997
+ ] }),
7998
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-6", children: hasChart ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative h-[180px] w-full", children: [
7999
+ showBaseline && /* @__PURE__ */ jsxRuntime.jsx(
8000
+ "div",
8001
+ {
8002
+ "aria-hidden": "true",
8003
+ className: "absolute inset-x-0 top-1/2 h-px",
8004
+ style: { backgroundColor: BASELINE_COLOR }
8005
+ }
8006
+ ),
8007
+ /* @__PURE__ */ jsxRuntime.jsx(Sparkline, { ...sparklineProps, className: "h-full w-full" })
8008
+ ] }) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex h-[180px] w-full items-center justify-center", children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-medium text-slate-400 text-sm", children: hasData ? "Not enough data" : "No data" }) }) }),
8009
+ hasChart && xAxisLabels && xAxisLabels.length > 0 && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-4 flex items-start justify-between", children: xAxisLabels.map((label, index) => {
8010
+ const [lead, trailing] = splitTickLabel(label);
8011
+ return /* @__PURE__ */ jsxRuntime.jsxs(
8012
+ "span",
8013
+ {
8014
+ className: "flex flex-col text-slate-400 text-xs leading-tight",
8015
+ children: [
8016
+ /* @__PURE__ */ jsxRuntime.jsx("span", { children: lead }),
8017
+ trailing !== void 0 && /* @__PURE__ */ jsxRuntime.jsx("span", { children: trailing })
8018
+ ]
8019
+ },
8020
+ `${label}-${index}`
8021
+ );
8022
+ }) })
8023
+ ] });
8024
+ }
8025
+
8026
+ // src/components/data-display/primitives/arc.tsx
8027
+ function clamp(n, min, max) {
8028
+ return Math.min(Math.max(n, min), max);
8029
+ }
8030
+ function arcLength(r) {
8031
+ return Math.PI * r;
8032
+ }
8033
+ function halfCircleArcPath(cx, cy, r) {
8034
+ const startX = cx - r;
8035
+ const endX = cx + r;
8036
+ return `M ${startX} ${cy} A ${r} ${r} 0 0 1 ${endX} ${cy}`;
8037
+ }
8038
+ function dashOffsetForFraction(arcLen, fraction) {
8039
+ return arcLen * (1 - clamp(fraction, 0, 1));
8040
+ }
8041
+ function segmentDashArray(value, total, circumference, gap = 0) {
8042
+ const safeTotal = total > 0 ? total : 0;
8043
+ const fraction = safeTotal > 0 ? value / safeTotal : 0;
8044
+ const rawLength = fraction * circumference;
8045
+ const visible = Math.max(0, rawLength - gap);
8046
+ const remainder = Math.max(0, circumference - visible);
8047
+ return {
8048
+ dasharray: `${visible} ${remainder}`,
8049
+ dashoffset: 0
8050
+ };
8051
+ }
8052
+ var DEFAULT_PALETTE = [
8053
+ "#1f2d4d",
8054
+ // navy
8055
+ "#3b82f6",
8056
+ // blue
8057
+ "#f59e0b",
8058
+ // amber
8059
+ "#10b981",
8060
+ // emerald
8061
+ "#8b5cf6",
8062
+ // violet
8063
+ "#ec4899",
8064
+ // pink
8065
+ "#14b8a6",
8066
+ // teal
8067
+ "#f97316"
8068
+ // orange
8069
+ ];
8070
+ var EMPTY_RING_COLOR = "#e5e7eb";
8071
+ var VIEWBOX = 100;
8072
+ var CENTER = VIEWBOX / 2;
8073
+ var RADIUS = 38;
8074
+ var STROKE_WIDTH = 18;
8075
+ var CIRCUMFERENCE = 2 * Math.PI * RADIUS;
8076
+ var SEGMENT_GAP = 1.5;
8077
+ function segmentColor(segment, index) {
8078
+ return segment.color ?? DEFAULT_PALETTE[index % DEFAULT_PALETTE.length];
8079
+ }
8080
+ function legendValue(segment, total, valueFormat) {
8081
+ if (segment.displayValue != null) return segment.displayValue;
8082
+ if (valueFormat === "none") return null;
8083
+ if (valueFormat === "value") return String(segment.value);
8084
+ if (total <= 0) return "0%";
8085
+ const pct = segment.value / total * 100;
8086
+ const rounded = Math.round(pct * 10) / 10;
8087
+ return `${Number.isInteger(rounded) ? rounded : rounded.toFixed(1)}%`;
8088
+ }
8089
+ function PieChartArtifact({
8090
+ title,
8091
+ centerLabel,
8092
+ centerSublabel,
8093
+ segments,
8094
+ valueFormat = "percent",
8095
+ className
8096
+ }) {
8097
+ const safeSegments = segments ?? [];
8098
+ const total = safeSegments.reduce((sum, s) => sum + (s.value > 0 ? s.value : 0), 0);
8099
+ const isEmpty = safeSegments.length === 0 || total <= 0;
8100
+ let runningOffset = 0;
8101
+ return /* @__PURE__ */ jsxRuntime.jsxs(CardShell, { className: cn("w-full p-6", className), children: [
8102
+ title ? /* @__PURE__ */ jsxRuntime.jsx("h3", { className: "font-bold text-base text-slate-900 leading-tight", children: title }) : null,
8103
+ /* @__PURE__ */ jsxRuntime.jsxs(
8104
+ "div",
8105
+ {
8106
+ className: cn(
8107
+ "flex flex-col items-center gap-6 sm:flex-row sm:items-center sm:gap-8",
8108
+ title && "mt-5"
8109
+ ),
8110
+ children: [
8111
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative shrink-0", style: { width: 150, height: 150 }, children: [
8112
+ /* @__PURE__ */ jsxRuntime.jsx(
8113
+ "svg",
8114
+ {
8115
+ viewBox: `0 0 ${VIEWBOX} ${VIEWBOX}`,
8116
+ width: "100%",
8117
+ height: "100%",
8118
+ role: "img",
8119
+ "aria-label": title ?? "Donut chart",
8120
+ children: /* @__PURE__ */ jsxRuntime.jsx("g", { transform: `rotate(-90 ${CENTER} ${CENTER})`, fill: "none", children: isEmpty ? /* @__PURE__ */ jsxRuntime.jsx(
8121
+ "circle",
8122
+ {
8123
+ cx: CENTER,
8124
+ cy: CENTER,
8125
+ r: RADIUS,
8126
+ stroke: EMPTY_RING_COLOR,
8127
+ strokeWidth: STROKE_WIDTH
8128
+ }
8129
+ ) : safeSegments.map((segment, index) => {
8130
+ const value = segment.value > 0 ? segment.value : 0;
8131
+ const { dasharray } = segmentDashArray(
8132
+ value,
8133
+ total,
8134
+ CIRCUMFERENCE,
8135
+ SEGMENT_GAP
8136
+ );
8137
+ const dashoffset = -runningOffset;
8138
+ runningOffset += value / total * CIRCUMFERENCE;
8139
+ if (value <= 0) return null;
8140
+ return /* @__PURE__ */ jsxRuntime.jsx(
8141
+ "circle",
8142
+ {
8143
+ cx: CENTER,
8144
+ cy: CENTER,
8145
+ r: RADIUS,
8146
+ stroke: segmentColor(segment, index),
8147
+ strokeWidth: STROKE_WIDTH,
8148
+ strokeDasharray: dasharray,
8149
+ strokeDashoffset: dashoffset
8150
+ },
8151
+ segment.label + index
8152
+ );
8153
+ }) })
8154
+ }
8155
+ ),
8156
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "pointer-events-none absolute inset-0 flex flex-col items-center justify-center text-center", children: isEmpty ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-medium text-slate-400 text-sm", children: "No data" }) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
8157
+ centerLabel ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-bold text-base text-slate-900 leading-none", children: centerLabel }) : null,
8158
+ centerSublabel ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "mt-1 text-slate-500 text-xs leading-none", children: centerSublabel }) : null
8159
+ ] }) })
8160
+ ] }),
8161
+ !isEmpty ? /* @__PURE__ */ jsxRuntime.jsx("ul", { className: "flex w-full min-w-0 flex-col gap-3.5", children: safeSegments.map((segment, index) => {
8162
+ const value = legendValue(segment, total, valueFormat);
8163
+ return /* @__PURE__ */ jsxRuntime.jsxs(
8164
+ "li",
8165
+ {
8166
+ className: "flex items-center justify-between gap-4",
8167
+ children: [
8168
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "flex min-w-0 items-center gap-2.5", children: [
8169
+ /* @__PURE__ */ jsxRuntime.jsx(
8170
+ "span",
8171
+ {
8172
+ "aria-hidden": "true",
8173
+ className: "inline-block size-3 shrink-0 rounded-sm",
8174
+ style: { backgroundColor: segmentColor(segment, index) }
8175
+ }
8176
+ ),
8177
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "truncate text-slate-600 text-sm", children: segment.label })
8178
+ ] }),
8179
+ value != null ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "shrink-0 font-bold text-slate-900 text-sm tabular-nums", children: value }) : null
8180
+ ]
8181
+ },
8182
+ segment.label + index
8183
+ );
8184
+ }) }) : null
8185
+ ]
8186
+ }
8187
+ )
8188
+ ] });
8189
+ }
8190
+ var TREND_COLORS = {
8191
+ up: "#22C55E",
8192
+ down: "#3B82F6",
8193
+ flat: "#9CA3AF"
8194
+ };
8195
+ var PALETTE = ["#22C55E", "#3B82F6", "#F59E0B", "#8B5CF6", "#EF4444"];
8196
+ function resolveColor(row, index) {
8197
+ if (row.color) return row.color;
8198
+ if (row.trend) return TREND_COLORS[row.trend];
8199
+ return PALETTE[index % PALETTE.length];
8200
+ }
8201
+ function StackedSparklines({ rows, className }) {
8202
+ const safeRows = Array.isArray(rows) ? rows : [];
8203
+ return /* @__PURE__ */ jsxRuntime.jsx(CardShell, { className: cn("overflow-hidden", className), children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "px-6", children: safeRows.map((row, index) => {
8204
+ const color = resolveColor(row, index);
8205
+ const hasData = Array.isArray(row.data) && row.data.length >= 2;
8206
+ return /* @__PURE__ */ jsxRuntime.jsxs(
8207
+ "div",
8208
+ {
8209
+ className: cn(
8210
+ "flex items-center justify-between gap-6 py-5",
8211
+ // Hairline divider on every row except the first.
8212
+ index > 0 && "border-slate-200 border-t"
8213
+ ),
8214
+ children: [
8215
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex min-w-0 flex-col gap-1", children: [
8216
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "truncate text-xs text-slate-500 leading-tight", children: row.label }),
8217
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-bold text-2xl text-slate-900 leading-tight tracking-tight tabular-nums", children: row.value })
8218
+ ] }),
8219
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "h-9 w-[28%] min-w-[88px] shrink-0", children: hasData ? /* @__PURE__ */ jsxRuntime.jsx(
8220
+ Sparkline,
8221
+ {
8222
+ data: row.data,
8223
+ color,
8224
+ width: 110,
8225
+ height: 36,
8226
+ pad: 4,
8227
+ strokeWidth: 2.5,
8228
+ className: "h-full w-full"
8229
+ }
8230
+ ) : (
8231
+ // Empty/edge state: data length < 2 → blank area, no crash.
8232
+ /* @__PURE__ */ jsxRuntime.jsx("div", { "aria-hidden": "true", className: "h-full w-full" })
8233
+ ) })
8234
+ ]
8235
+ },
8236
+ `${row.label}-${index}`
8237
+ );
8238
+ }) }) });
8239
+ }
8240
+ var DEFAULT_MIN = 0;
8241
+ var DEFAULT_MAX = 100;
8242
+ var DEFAULT_FILL_COLOR = "#22c55e";
8243
+ var DEFAULT_TRACK_COLOR = "#eef0f2";
8244
+ var DEFAULT_VALUE_COLOR = "#0f172a";
8245
+ var DEFAULT_MIN_LABEL_COLOR = "#94a3b8";
8246
+ var DEFAULT_TITLE_COLOR = "#0f172a";
8247
+ var VIEW_W = 240;
8248
+ var VIEW_H = 130;
8249
+ var CX = 120;
8250
+ var CY = 110;
8251
+ var RADIUS2 = 100;
8252
+ var STROKE_WIDTH2 = 18;
8253
+ function clamp01(n) {
8254
+ if (Number.isNaN(n)) return 0;
8255
+ return Math.min(Math.max(n, 0), 1);
8256
+ }
8257
+ function StatCardHalfCircle({
8258
+ title,
8259
+ value,
8260
+ displayValue,
8261
+ min = DEFAULT_MIN,
8262
+ max = DEFAULT_MAX,
8263
+ minLabel,
8264
+ maxLabel,
8265
+ fillColor = DEFAULT_FILL_COLOR,
8266
+ trackColor = DEFAULT_TRACK_COLOR,
8267
+ valueColor = DEFAULT_VALUE_COLOR,
8268
+ minLabelColor = DEFAULT_MIN_LABEL_COLOR,
8269
+ // maxLabel color defaults to the fill color so a positive reading reads as one accent.
8270
+ maxLabelColor,
8271
+ titleColor = DEFAULT_TITLE_COLOR,
8272
+ className
8273
+ }) {
8274
+ const span = max - min;
8275
+ const fraction = span > 0 ? clamp01((value - min) / span) : 0;
8276
+ const arcPath = halfCircleArcPath(CX, CY, RADIUS2);
8277
+ const len = arcLength(RADIUS2);
8278
+ const fillDashOffset = dashOffsetForFraction(len, fraction);
8279
+ const readout = displayValue ?? String(value);
8280
+ const resolvedMaxLabelColor = maxLabelColor ?? fillColor;
8281
+ return /* @__PURE__ */ jsxRuntime.jsxs(CardShell, { className: cn("w-full max-w-[440px] p-5 sm:p-6", className), children: [
8282
+ /* @__PURE__ */ jsxRuntime.jsx(
8283
+ "h3",
8284
+ {
8285
+ className: "font-semibold text-base leading-tight",
8286
+ style: { color: titleColor },
8287
+ children: title
8288
+ }
8289
+ ),
8290
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative mx-auto mt-4 w-full max-w-[280px]", children: [
8291
+ /* @__PURE__ */ jsxRuntime.jsxs(
8292
+ "svg",
8293
+ {
8294
+ viewBox: `0 0 ${VIEW_W} ${VIEW_H}`,
8295
+ className: "block w-full",
8296
+ role: "img",
8297
+ "aria-label": `${title}: ${readout}`,
8298
+ preserveAspectRatio: "xMidYMid meet",
8299
+ children: [
8300
+ /* @__PURE__ */ jsxRuntime.jsx(
8301
+ "path",
8302
+ {
8303
+ d: arcPath,
8304
+ fill: "none",
8305
+ stroke: trackColor,
8306
+ strokeWidth: STROKE_WIDTH2,
8307
+ strokeLinecap: "round"
8308
+ }
8309
+ ),
8310
+ /* @__PURE__ */ jsxRuntime.jsx(
8311
+ "path",
8312
+ {
8313
+ d: arcPath,
8314
+ fill: "none",
8315
+ stroke: fillColor,
8316
+ strokeWidth: STROKE_WIDTH2,
8317
+ strokeLinecap: "round",
8318
+ strokeDasharray: len,
8319
+ strokeDashoffset: fillDashOffset
8320
+ }
8321
+ )
8322
+ ]
8323
+ }
8324
+ ),
8325
+ /* @__PURE__ */ jsxRuntime.jsx(
8326
+ "div",
8327
+ {
8328
+ className: "pointer-events-none absolute inset-x-0 bottom-0 flex items-end justify-center pb-1",
8329
+ "aria-hidden": "true",
8330
+ children: /* @__PURE__ */ jsxRuntime.jsx(
8331
+ "span",
8332
+ {
8333
+ className: "font-bold text-2xl leading-none tabular-nums",
8334
+ style: { color: valueColor },
8335
+ children: readout
8336
+ }
8337
+ )
8338
+ }
8339
+ )
8340
+ ] }),
8341
+ (minLabel || maxLabel) && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mx-auto mt-3 flex w-full max-w-[280px] items-baseline justify-between", children: [
8342
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-medium text-xs", style: { color: minLabelColor }, children: minLabel }),
8343
+ /* @__PURE__ */ jsxRuntime.jsx(
8344
+ "span",
8345
+ {
8346
+ className: "font-semibold text-xs",
8347
+ style: { color: resolvedMaxLabelColor },
8348
+ children: maxLabel
8349
+ }
8350
+ )
8351
+ ] })
8352
+ ] });
8353
+ }
8354
+ var TONE_TEXT_COLOR = {
8355
+ default: "",
8356
+ neutral: "",
8357
+ positive: "text-emerald-600",
8358
+ negative: "text-rose-600",
8359
+ warning: "text-amber-600",
8360
+ info: "text-blue-600",
8361
+ muted: "text-slate-400"
8362
+ };
8363
+ function toneTextColor2(tone, toneMap = {}) {
8364
+ if (!tone) return "";
8365
+ const override = toneMap[tone];
8366
+ if (override !== void 0) return override;
8367
+ return TONE_TEXT_COLOR[tone] ?? "";
8368
+ }
8369
+ function parseBoldString(s) {
8370
+ const segments = [];
8371
+ if (!s) return segments;
8372
+ const regex = /\*\*([\s\S]+?)\*\*/g;
8373
+ let lastIndex = 0;
8374
+ let match;
8375
+ while ((match = regex.exec(s)) !== null) {
8376
+ if (match.index > lastIndex) {
8377
+ segments.push({ text: s.slice(lastIndex, match.index) });
8378
+ }
8379
+ segments.push({ text: match[1], bold: true });
8380
+ lastIndex = regex.lastIndex;
8381
+ }
8382
+ if (lastIndex < s.length) {
8383
+ segments.push({ text: s.slice(lastIndex) });
8384
+ }
8385
+ return segments;
8386
+ }
8387
+ function normalizeRich(content) {
8388
+ return typeof content === "string" ? parseBoldString(content) : content;
8389
+ }
8390
+ function renderRich(content, toneMap = {}) {
8391
+ const segments = normalizeRich(content);
8392
+ return segments.map((segment, index) => {
8393
+ const colorClass = toneTextColor2(segment.tone, toneMap);
8394
+ if (segment.code) {
8395
+ return /* @__PURE__ */ jsxRuntime.jsx(
8396
+ "code",
8397
+ {
8398
+ className: cn(
8399
+ "rounded bg-slate-100 px-1 py-0.5 font-mono text-[0.85em] text-slate-700",
8400
+ colorClass
8401
+ ),
8402
+ children: segment.text
8403
+ },
8404
+ index
8405
+ );
8406
+ }
8407
+ if (segment.bold) {
8408
+ return /* @__PURE__ */ jsxRuntime.jsx("strong", { className: cn("font-bold", colorClass), children: segment.text }, index);
8409
+ }
8410
+ if (colorClass) {
8411
+ return /* @__PURE__ */ jsxRuntime.jsx("span", { className: colorClass, children: segment.text }, index);
8412
+ }
8413
+ return /* @__PURE__ */ jsxRuntime.jsx(React4.Fragment, { children: segment.text }, index);
8414
+ });
8415
+ }
8416
+ var VIEW_W2 = 800;
8417
+ var VIEW_H2 = 300;
8418
+ var PAD_LEFT = 8;
8419
+ var PAD_RIGHT = 8;
8420
+ var PAD_TOP = 16;
8421
+ var PAD_BOTTOM = 16;
8422
+ var PLOT_W = VIEW_W2 - PAD_LEFT - PAD_RIGHT;
8423
+ var PLOT_H = VIEW_H2 - PAD_TOP - PAD_BOTTOM;
8424
+ var GRID_COLOR = "#e2e8f0";
8425
+ var AXIS_LABEL_COLOR = "#94a3b8";
8426
+ var BAND_FILL = "#94a3b8";
8427
+ var TABLE_HEADER_BG = "#f8fafc";
8428
+ var TABLE_HEADER_TEXT = "#64748b";
8429
+ var TABLE_ROW_BORDER = "#f1f5f9";
8430
+ var FIRST_COL_TEXT = "#0f172a";
8431
+ var SUMMARY_TEXT_COLOR = "#475569";
8432
+ function niceMax(value) {
8433
+ if (value <= 0) return 1;
8434
+ const magnitude = Math.pow(10, Math.floor(Math.log10(value)));
8435
+ const normalized = value / magnitude;
8436
+ let nice;
8437
+ if (normalized <= 1) nice = 1;
8438
+ else if (normalized <= 2) nice = 2;
8439
+ else if (normalized <= 5) nice = 5;
8440
+ else nice = 10;
8441
+ return nice * magnitude;
8442
+ }
8443
+ function yFor(value, yMax) {
8444
+ const span = yMax || 1;
8445
+ return PAD_TOP + PLOT_H - value / span * PLOT_H;
8446
+ }
8447
+ function xFor(i, n) {
8448
+ if (n <= 1) return PAD_LEFT + PLOT_W / 2;
8449
+ return PAD_LEFT + i / (n - 1) * PLOT_W;
8450
+ }
8451
+ var ALIGN_CLASS = {
8452
+ left: "text-left",
8453
+ right: "text-right",
8454
+ center: "text-center"
8455
+ };
8456
+ function deltaDirection(d) {
8457
+ return d ?? "flat";
8458
+ }
8459
+ function TableListArtifact({
8460
+ chartTitle,
8461
+ series,
8462
+ xAxisLabels,
8463
+ yAxisTicks,
8464
+ chartType = "area",
8465
+ tableColumns,
8466
+ tableRows,
8467
+ summaryText,
8468
+ className
8469
+ }) {
8470
+ const gradientId = React4.useId();
8471
+ const hasSeries = Array.isArray(series) && series.length > 0 && series.some((s) => Array.isArray(s.data) && s.data.length > 0);
8472
+ const dataMax = hasSeries ? Math.max(
8473
+ 0,
8474
+ ...series.flatMap((s) => Array.isArray(s.data) ? s.data : [])
8475
+ ) : 0;
8476
+ const ticks = yAxisTicks && yAxisTicks.length > 0 ? [...yAxisTicks].sort((a, b) => b.value - a.value) : null;
8477
+ const yMax = ticks ? Math.max(...ticks.map((t) => t.value), dataMax) : niceMax(dataMax);
8478
+ const seriesPoints = hasSeries ? series.map((s) => {
8479
+ const data = Array.isArray(s.data) ? s.data : [];
8480
+ const n = data.length;
8481
+ const pts = data.map((v, i) => ({ x: xFor(i, n), y: yFor(v, yMax) }));
8482
+ return { color: s.color, pts };
8483
+ }) : [];
8484
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn("flex flex-col gap-4", className), children: [
8485
+ /* @__PURE__ */ jsxRuntime.jsxs(CardShell, { className: "border-[#e5e7eb] p-6", children: [
8486
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-start justify-between gap-4", children: [
8487
+ /* @__PURE__ */ jsxRuntime.jsx("h3", { className: "font-bold text-base text-slate-800 leading-snug", children: chartTitle }),
8488
+ hasSeries && /* @__PURE__ */ jsxRuntime.jsx("ul", { className: "flex flex-wrap items-center gap-x-4 gap-y-1", children: series.map((s) => /* @__PURE__ */ jsxRuntime.jsxs(
8489
+ "li",
8490
+ {
8491
+ className: "flex items-center gap-2 text-slate-600 text-sm",
8492
+ children: [
8493
+ /* @__PURE__ */ jsxRuntime.jsx(
8494
+ "span",
8495
+ {
8496
+ "aria-hidden": "true",
8497
+ className: "inline-block size-2 shrink-0 rounded-full",
8498
+ style: { backgroundColor: s.color }
8499
+ }
8500
+ ),
8501
+ s.name
8502
+ ]
8503
+ },
8504
+ s.name
8505
+ )) })
8506
+ ] }),
8507
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mt-5", children: [
8508
+ hasSeries ? /* @__PURE__ */ jsxRuntime.jsxs(
8509
+ "svg",
8510
+ {
8511
+ className: "block h-[300px] w-full",
8512
+ viewBox: `0 0 ${VIEW_W2} ${VIEW_H2}`,
8513
+ preserveAspectRatio: "none",
8514
+ role: "img",
8515
+ "aria-label": chartTitle,
8516
+ children: [
8517
+ ticks?.map((tick) => {
8518
+ const y = yFor(tick.value, yMax);
8519
+ return /* @__PURE__ */ jsxRuntime.jsxs("g", { children: [
8520
+ /* @__PURE__ */ jsxRuntime.jsx(
8521
+ "line",
8522
+ {
8523
+ x1: PAD_LEFT,
8524
+ y1: y,
8525
+ x2: VIEW_W2 - PAD_RIGHT,
8526
+ y2: y,
8527
+ stroke: GRID_COLOR,
8528
+ strokeWidth: 1,
8529
+ style: { vectorEffect: "non-scaling-stroke" }
8530
+ }
8531
+ ),
8532
+ /* @__PURE__ */ jsxRuntime.jsx(
8533
+ "text",
8534
+ {
8535
+ x: PAD_LEFT,
8536
+ y: y - 6,
8537
+ fill: AXIS_LABEL_COLOR,
8538
+ fontSize: 13,
8539
+ textAnchor: "start",
8540
+ children: tick.label
8541
+ }
8542
+ )
8543
+ ] }, tick.label);
8544
+ }),
8545
+ chartType === "area" && seriesPoints.length >= 2 && seriesPoints[0].pts.length > 1 && seriesPoints[1].pts.length > 1 && /* @__PURE__ */ jsxRuntime.jsx(
8546
+ "path",
8547
+ {
8548
+ d: bandPath(seriesPoints[0].pts, seriesPoints[1].pts),
8549
+ fill: BAND_FILL,
8550
+ fillOpacity: 0.12,
8551
+ stroke: "none"
8552
+ }
8553
+ ),
8554
+ chartType === "area" && seriesPoints.length > 0 && (() => {
8555
+ const bottom = seriesPoints[seriesPoints.length - 1];
8556
+ const area = buildAreaPath(bottom.pts, VIEW_H2 - PAD_BOTTOM);
8557
+ if (!area) return null;
8558
+ return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
8559
+ /* @__PURE__ */ jsxRuntime.jsx("defs", { children: /* @__PURE__ */ jsxRuntime.jsxs(
8560
+ "linearGradient",
8561
+ {
8562
+ id: gradientId,
8563
+ x1: "0",
8564
+ y1: "0",
8565
+ x2: "0",
8566
+ y2: "1",
8567
+ children: [
8568
+ /* @__PURE__ */ jsxRuntime.jsx(
8569
+ "stop",
8570
+ {
8571
+ offset: "0%",
8572
+ stopColor: bottom.color,
8573
+ stopOpacity: 0.14
8574
+ }
8575
+ ),
8576
+ /* @__PURE__ */ jsxRuntime.jsx(
8577
+ "stop",
8578
+ {
8579
+ offset: "100%",
8580
+ stopColor: bottom.color,
8581
+ stopOpacity: 0
8582
+ }
8583
+ )
8584
+ ]
8585
+ }
8586
+ ) }),
8587
+ /* @__PURE__ */ jsxRuntime.jsx(
8588
+ "path",
8589
+ {
8590
+ d: area,
8591
+ fill: `url(#${gradientId})`,
8592
+ stroke: "none"
8593
+ }
8594
+ )
8595
+ ] });
8596
+ })(),
8597
+ seriesPoints.map((sp, idx) => {
8598
+ const d = buildLinePath(sp.pts, true);
8599
+ if (!d) return null;
8600
+ return /* @__PURE__ */ jsxRuntime.jsx(
8601
+ "path",
8602
+ {
8603
+ d,
8604
+ fill: "none",
8605
+ stroke: sp.color,
8606
+ strokeWidth: 3,
8607
+ strokeLinecap: "round",
8608
+ strokeLinejoin: "round",
8609
+ style: { vectorEffect: "non-scaling-stroke" }
8610
+ },
8611
+ series[idx].name
8612
+ );
8613
+ })
8614
+ ]
8615
+ }
8616
+ ) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex h-[160px] items-center justify-center text-slate-400 text-sm", children: "No data" }),
8617
+ hasSeries && xAxisLabels && xAxisLabels.length > 0 && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-2 flex justify-between px-1", children: xAxisLabels.map((label, i) => /* @__PURE__ */ jsxRuntime.jsx(
8618
+ "span",
8619
+ {
8620
+ className: "text-slate-400 text-xs",
8621
+ style: { color: AXIS_LABEL_COLOR },
8622
+ children: label
8623
+ },
8624
+ `${label}-${i}`
8625
+ )) })
8626
+ ] })
8627
+ ] }),
8628
+ /* @__PURE__ */ jsxRuntime.jsx(CardShell, { className: "overflow-hidden border-[#e5e7eb] p-0", children: /* @__PURE__ */ jsxRuntime.jsxs("table", { className: "w-full border-collapse", children: [
8629
+ /* @__PURE__ */ jsxRuntime.jsx("thead", { children: /* @__PURE__ */ jsxRuntime.jsx("tr", { style: { backgroundColor: TABLE_HEADER_BG }, children: tableColumns.map((col) => /* @__PURE__ */ jsxRuntime.jsx(
8630
+ "th",
8631
+ {
8632
+ scope: "col",
8633
+ className: cn(
8634
+ "px-6 py-4 font-semibold text-xs uppercase tracking-wider",
8635
+ ALIGN_CLASS[col.align ?? "left"]
8636
+ ),
8637
+ style: { color: TABLE_HEADER_TEXT },
8638
+ children: col.label
8639
+ },
8640
+ col.key
8641
+ )) }) }),
8642
+ /* @__PURE__ */ jsxRuntime.jsx("tbody", { children: tableRows.map((row, rowIndex) => /* @__PURE__ */ jsxRuntime.jsx(
8643
+ "tr",
8644
+ {
8645
+ style: {
8646
+ borderTop: rowIndex === 0 ? void 0 : `1px solid ${TABLE_ROW_BORDER}`
8647
+ },
8648
+ children: tableColumns.map((col, colIndex) => {
8649
+ const align = col.align ?? (colIndex === 0 ? "left" : "right");
8650
+ if (colIndex === 0) {
8651
+ return /* @__PURE__ */ jsxRuntime.jsx(
8652
+ "td",
8653
+ {
8654
+ className: cn(
8655
+ "px-6 py-5 font-bold text-sm",
8656
+ ALIGN_CLASS[align]
8657
+ ),
8658
+ style: { color: FIRST_COL_TEXT },
8659
+ children: row.label
8660
+ },
8661
+ col.key
8662
+ );
8663
+ }
8664
+ if (colIndex === 1) {
8665
+ return /* @__PURE__ */ jsxRuntime.jsx(
8666
+ "td",
8667
+ {
8668
+ className: cn(
8669
+ "px-6 py-5 text-sm text-slate-700 tabular-nums",
8670
+ ALIGN_CLASS[align]
8671
+ ),
8672
+ children: row.value
8673
+ },
8674
+ col.key
8675
+ );
8676
+ }
8677
+ return /* @__PURE__ */ jsxRuntime.jsx(
8678
+ "td",
8679
+ {
8680
+ className: cn("px-6 py-5", ALIGN_CLASS[align]),
8681
+ children: row.delta ? /* @__PURE__ */ jsxRuntime.jsx(
8682
+ DeltaPill,
8683
+ {
8684
+ value: row.delta.text,
8685
+ direction: deltaDirection(row.delta.direction),
8686
+ hideArrow: true,
8687
+ className: "bg-transparent px-0 py-0 font-semibold text-xs"
8688
+ }
8689
+ ) : null
8690
+ },
8691
+ col.key
8692
+ );
8693
+ })
8694
+ },
8695
+ `${row.label}-${rowIndex}`
8696
+ )) })
8697
+ ] }) }),
8698
+ summaryText && /* @__PURE__ */ jsxRuntime.jsx(
8699
+ "p",
8700
+ {
8701
+ className: "text-sm leading-relaxed",
8702
+ style: { color: SUMMARY_TEXT_COLOR },
8703
+ children: renderRich(summaryText)
8704
+ }
8705
+ )
8706
+ ] });
8707
+ }
8708
+ function bandPath(top, bottom) {
8709
+ if (top.length === 0 || bottom.length === 0) return "";
8710
+ const fmt2 = (n) => Number.isInteger(n) ? String(n) : String(Math.round(n * 1e3) / 1e3);
8711
+ const forward = top.map((p, i) => `${i === 0 ? "M" : "L"} ${fmt2(p.x)} ${fmt2(p.y)}`).join(" ");
8712
+ const back = [...bottom].reverse().map((p) => `L ${fmt2(p.x)} ${fmt2(p.y)}`).join(" ");
8713
+ return `${forward} ${back} Z`;
8714
+ }
8715
+ var DEFAULT_ICON_CHIP_BG = "#F1F5F9";
8716
+ var DEFAULT_ICON_CHIP_FG = "#334155";
8717
+ var DEFAULT_VALUE_COLOR2 = "#0F172A";
8718
+ var DEFAULT_SPARKLINE_COLOR = "#10B981";
8719
+ function KpiCardWithSparklines({
8720
+ label,
8721
+ value,
8722
+ delta,
8723
+ caption,
8724
+ icon,
8725
+ iconChipBg,
8726
+ iconChipFg,
8727
+ sparkline,
8728
+ accentColor,
8729
+ valueColor,
8730
+ className,
8731
+ onClick
8732
+ }) {
8733
+ const sparklineColor = sparkline?.color ?? accentColor ?? DEFAULT_SPARKLINE_COLOR;
8734
+ const sparkData = sparkline?.data ?? [];
8735
+ const hasSparkline = sparkData.length >= 2;
8736
+ const interactive = typeof onClick === "function";
8737
+ const body = /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "p-6", children: [
8738
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between gap-3", children: [
8739
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "font-medium text-xs text-slate-500 leading-snug", children: label }),
8740
+ icon != null && icon !== "" && /* @__PURE__ */ jsxRuntime.jsx(
8741
+ "span",
8742
+ {
8743
+ "aria-hidden": "true",
8744
+ className: "flex h-10 w-10 shrink-0 items-center justify-center rounded-lg font-semibold text-base",
8745
+ style: {
8746
+ backgroundColor: iconChipBg ?? DEFAULT_ICON_CHIP_BG,
8747
+ color: iconChipFg ?? DEFAULT_ICON_CHIP_FG
8748
+ },
8749
+ children: icon
8750
+ }
8751
+ )
8752
+ ] }),
8753
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mt-4 flex flex-wrap items-end gap-x-3 gap-y-1", children: [
8754
+ /* @__PURE__ */ jsxRuntime.jsx(
8755
+ "span",
8756
+ {
8757
+ className: "font-extrabold text-2xl leading-none tracking-tight tabular-nums",
8758
+ style: { color: valueColor ?? DEFAULT_VALUE_COLOR2 },
8759
+ children: value
8760
+ }
8761
+ ),
8762
+ delta && /* @__PURE__ */ jsxRuntime.jsx(
8763
+ DeltaPill,
8764
+ {
8765
+ value: delta.value,
8766
+ direction: delta.direction,
8767
+ tone: delta.tone,
8768
+ className: "mb-1 px-2.5 py-1 text-xs"
8769
+ }
8770
+ )
8771
+ ] }),
8772
+ caption && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "mt-1 text-slate-400 text-xs", children: caption }),
8773
+ hasSparkline && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "-mx-6 -mb-6 mt-5", children: /* @__PURE__ */ jsxRuntime.jsx(
8774
+ Sparkline,
8775
+ {
8776
+ data: sparkData,
8777
+ color: sparklineColor,
8778
+ showArea: sparkline?.showArea ?? true,
8779
+ smooth: sparkline?.smooth ?? false,
8780
+ className: "h-24 w-full"
8781
+ }
8782
+ ) })
8783
+ ] });
8784
+ return /* @__PURE__ */ jsxRuntime.jsx(
8785
+ CardShell,
8786
+ {
8787
+ className: cn(
8788
+ "overflow-hidden",
8789
+ interactive && "cursor-pointer transition-shadow hover:shadow-md",
8790
+ className
8791
+ ),
8792
+ children: interactive ? /* @__PURE__ */ jsxRuntime.jsx(
8793
+ "div",
8794
+ {
8795
+ role: "button",
8796
+ tabIndex: 0,
8797
+ onClick,
8798
+ onKeyDown: (event) => {
8799
+ if (event.key === "Enter" || event.key === " ") {
8800
+ event.preventDefault();
8801
+ onClick?.();
8802
+ }
8803
+ },
8804
+ className: "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring",
8805
+ children: body
8806
+ }
8807
+ ) : body
8808
+ }
8809
+ );
8810
+ }
8811
+ var DEFAULT_LOCATION_LABEL = "Location";
8812
+ var DEFAULT_REVENUE_LABEL = "Rev";
8813
+ var DEFAULT_STATUS_LABEL = "Status";
8814
+ var GRID_TEMPLATE = "grid grid-cols-[1fr_auto_3rem] items-center gap-x-4 px-6";
8815
+ function LocationTableRow({ row }) {
8816
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn(GRID_TEMPLATE, "py-5"), role: "row", children: [
8817
+ /* @__PURE__ */ jsxRuntime.jsx(
8818
+ "span",
8819
+ {
8820
+ role: "cell",
8821
+ className: "truncate font-semibold text-sm text-slate-800",
8822
+ children: row.name
8823
+ }
8824
+ ),
8825
+ /* @__PURE__ */ jsxRuntime.jsx(
8826
+ "span",
8827
+ {
8828
+ role: "cell",
8829
+ className: "text-right text-sm text-slate-700 tabular-nums",
8830
+ children: row.revenue
8831
+ }
8832
+ ),
8833
+ /* @__PURE__ */ jsxRuntime.jsx("span", { role: "cell", className: "flex justify-end", children: /* @__PURE__ */ jsxRuntime.jsx(
8834
+ StatusDot,
8835
+ {
8836
+ status: row.status,
8837
+ color: row.statusColor,
8838
+ label: row.statusLabel,
8839
+ size: 13
8840
+ }
8841
+ ) })
8842
+ ] });
8843
+ }
8844
+ function LocationsRevenueCard({
8845
+ locationColumnLabel = DEFAULT_LOCATION_LABEL,
8846
+ revenueColumnLabel = DEFAULT_REVENUE_LABEL,
8847
+ statusColumnLabel = DEFAULT_STATUS_LABEL,
8848
+ rows,
8849
+ className
8850
+ }) {
8851
+ const hasRows = Array.isArray(rows) && rows.length > 0;
8852
+ return /* @__PURE__ */ jsxRuntime.jsx(CardShell, { className: cn("overflow-hidden", className), children: /* @__PURE__ */ jsxRuntime.jsxs("div", { role: "table", "aria-label": locationColumnLabel, children: [
8853
+ /* @__PURE__ */ jsxRuntime.jsxs(
8854
+ "div",
8855
+ {
8856
+ role: "row",
8857
+ className: cn(
8858
+ GRID_TEMPLATE,
8859
+ "border-b bg-slate-50 py-4 font-semibold text-xs text-slate-400 uppercase tracking-wider"
8860
+ ),
8861
+ children: [
8862
+ /* @__PURE__ */ jsxRuntime.jsx("span", { role: "columnheader", className: "text-left", children: locationColumnLabel }),
8863
+ /* @__PURE__ */ jsxRuntime.jsx("span", { role: "columnheader", className: "text-right", children: revenueColumnLabel }),
8864
+ /* @__PURE__ */ jsxRuntime.jsx("span", { role: "columnheader", className: "text-right", children: statusColumnLabel })
8865
+ ]
8866
+ }
8867
+ ),
8868
+ hasRows ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "divide-y", children: rows.map((row, index) => /* @__PURE__ */ jsxRuntime.jsx(LocationTableRow, { row }, row.id ?? `${row.name}-${index}`)) }) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: "px-6 py-8 text-center text-slate-400 text-sm", children: "No locations" })
8869
+ ] }) });
8870
+ }
8871
+ var DENSITY_CELL_PADDING = {
8872
+ comfortable: "px-6 py-4",
8873
+ compact: "px-6 py-3"
8874
+ };
8875
+ function RowBasedDataList({
8876
+ rows,
8877
+ title,
8878
+ labelColumnWidth = "30%",
8879
+ density = "comfortable",
8880
+ className
8881
+ }) {
8882
+ const cellPadding = DENSITY_CELL_PADDING[density] ?? DENSITY_CELL_PADDING.comfortable;
8883
+ const hasRows = Array.isArray(rows) && rows.length > 0;
8884
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn("w-full", className), children: [
8885
+ title && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "mb-2 font-medium text-slate-700 text-sm", children: title }),
8886
+ /* @__PURE__ */ jsxRuntime.jsx(CardShell, { className: "overflow-hidden rounded-xl border-slate-200 shadow-none", children: hasRows ? /* @__PURE__ */ jsxRuntime.jsx(
8887
+ "dl",
8888
+ {
8889
+ className: "grid",
8890
+ style: { gridTemplateColumns: `${labelColumnWidth} 1fr` },
8891
+ children: rows.map((row, index) => {
8892
+ const isLast = index === rows.length - 1;
8893
+ return /* @__PURE__ */ jsxRuntime.jsx(
8894
+ RowPair,
8895
+ {
8896
+ row,
8897
+ isLast,
8898
+ cellPadding
8899
+ },
8900
+ `${row.label}-${index}`
8901
+ );
8902
+ })
8903
+ }
8904
+ ) : /* @__PURE__ */ jsxRuntime.jsx("p", { className: "px-6 py-5 text-slate-400 text-sm", children: "No details available" }) })
8905
+ ] });
8906
+ }
8907
+ function RowPair({ row, isLast, cellPadding }) {
8908
+ const valueColorClass = toneTextColor(row.valueColor);
8909
+ return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
8910
+ /* @__PURE__ */ jsxRuntime.jsx(
8911
+ "dt",
8912
+ {
8913
+ className: cn(
8914
+ "min-w-0 break-words bg-slate-50/70 font-normal text-slate-500 text-sm leading-snug",
8915
+ cellPadding,
8916
+ !isLast && "border-slate-100 border-b"
8917
+ ),
8918
+ children: row.label
8919
+ }
8920
+ ),
8921
+ /* @__PURE__ */ jsxRuntime.jsx(
8922
+ "dd",
8923
+ {
8924
+ className: cn(
8925
+ "min-w-0 break-words border-slate-100 border-l font-medium text-sm leading-snug",
8926
+ valueColorClass,
8927
+ cellPadding,
8928
+ !isLast && "border-b"
8929
+ ),
8930
+ children: row.href ? /* @__PURE__ */ jsxRuntime.jsx(
8931
+ "a",
8932
+ {
8933
+ href: row.href,
8934
+ target: "_blank",
8935
+ rel: "noreferrer noopener",
8936
+ className: "underline decoration-slate-300 underline-offset-2 hover:decoration-current",
8937
+ children: row.value
8938
+ }
8939
+ ) : row.value
8940
+ }
8941
+ )
8942
+ ] });
8943
+ }
8944
+ var TONE_STYLES = {
8945
+ green: { bg: "#E7F6EC", text: "#16A34A" },
8946
+ blue: { bg: "#E8EDFB", text: "#3B5BDB" },
8947
+ amber: { bg: "#FBEFD3", text: "#B45309" },
8948
+ red: { bg: "#FCE4E7", text: "#DC2626" },
8949
+ gray: { bg: "#F4F5F7", text: "#374151" },
8950
+ neutral: { bg: "#F4F5F7", text: "#374151" }
8951
+ };
8952
+ var TAG_BG = "#F4F5F7";
8953
+ var TAG_BORDER = "#E5E7EB";
8954
+ var TAG_TEXT = "#374151";
8955
+ var DEFAULT_TONE = "neutral";
8956
+ function tintFromColor(color) {
8957
+ const hex = /^#([0-9a-fA-F]{6})$/.exec(color);
8958
+ if (!hex) return color;
8959
+ return `#${hex[1]}24`;
8960
+ }
8961
+ function resolveSolidStyle(badge) {
8962
+ if (badge.color) {
8963
+ return { bg: tintFromColor(badge.color), text: badge.color };
8964
+ }
8965
+ const tone = badge.tone ?? DEFAULT_TONE;
8966
+ return TONE_STYLES[tone] ?? TONE_STYLES[DEFAULT_TONE];
8967
+ }
8968
+ function resolveDotColor(badge) {
8969
+ if (badge.dotColor) return badge.dotColor;
8970
+ if (badge.color) return badge.color;
8971
+ const tone = badge.tone ?? DEFAULT_TONE;
8972
+ return TONE_STYLES[tone]?.text ?? TONE_STYLES[DEFAULT_TONE].text;
8973
+ }
8974
+ function BadgePill({ badge, groupStyle }) {
8975
+ const style = badge.style ?? groupStyle;
8976
+ const baseClass = "inline-flex items-center rounded-full px-4 py-1.5 font-medium text-xs whitespace-nowrap";
8977
+ if (style === "outline") {
8978
+ return /* @__PURE__ */ jsxRuntime.jsxs(
8979
+ "span",
8980
+ {
8981
+ className: cn(baseClass, "border"),
8982
+ style: {
8983
+ backgroundColor: TAG_BG,
8984
+ borderColor: TAG_BORDER,
8985
+ color: TAG_TEXT
8986
+ },
8987
+ children: [
8988
+ badge.dot && /* @__PURE__ */ jsxRuntime.jsx(
8989
+ "span",
8990
+ {
8991
+ "aria-hidden": "true",
8992
+ className: "mr-2 inline-block size-2 shrink-0 rounded-full",
8993
+ style: { backgroundColor: resolveDotColor(badge) }
8994
+ }
8995
+ ),
8996
+ badge.label
8997
+ ]
8998
+ }
8999
+ );
9000
+ }
9001
+ const solid = resolveSolidStyle(badge);
9002
+ return /* @__PURE__ */ jsxRuntime.jsxs(
9003
+ "span",
9004
+ {
9005
+ className: baseClass,
9006
+ style: { backgroundColor: solid.bg, color: solid.text },
9007
+ children: [
9008
+ badge.dot && /* @__PURE__ */ jsxRuntime.jsx(
9009
+ "span",
9010
+ {
9011
+ "aria-hidden": "true",
9012
+ className: "mr-2 inline-block size-2 shrink-0 rounded-full",
9013
+ style: { backgroundColor: resolveDotColor(badge) }
9014
+ }
9015
+ ),
9016
+ badge.label
9017
+ ]
9018
+ }
9019
+ );
9020
+ }
9021
+ function BadgeGroupBlock({ group }) {
9022
+ const badges = group.badges ?? [];
9023
+ if (badges.length === 0) return null;
9024
+ const groupStyle = group.variant === "tag" ? "outline" : "solid";
9025
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
9026
+ group.label && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "mb-2 block font-medium text-[11px] text-gray-400 uppercase tracking-wider", children: group.label }),
9027
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex flex-wrap items-center gap-3", children: badges.map((badge, i) => {
9028
+ if (!badge?.label) return null;
9029
+ return /* @__PURE__ */ jsxRuntime.jsx(
9030
+ BadgePill,
9031
+ {
9032
+ badge,
9033
+ groupStyle
9034
+ },
9035
+ `${badge.label}-${i}`
9036
+ );
9037
+ }) })
9038
+ ] });
9039
+ }
9040
+ function BadgesArtifact({ groups, className }) {
9041
+ const safeGroups = groups ?? [];
9042
+ if (safeGroups.length === 0) return null;
9043
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn("flex flex-col gap-6", className), children: safeGroups.map((group, i) => /* @__PURE__ */ jsxRuntime.jsx(BadgeGroupBlock, { group }, group.label ?? `group-${i}`)) });
9044
+ }
9045
+ var BADGE_TONE_CLASSES = {
9046
+ default: "bg-slate-100 text-slate-600",
9047
+ positive: "bg-emerald-50 text-emerald-700",
9048
+ negative: "bg-rose-50 text-rose-700",
9049
+ muted: "bg-slate-50 text-slate-400",
9050
+ info: "bg-blue-50 text-blue-700"
9051
+ };
9052
+ function badgeToneClass(tone) {
9053
+ if (!tone) return BADGE_TONE_CLASSES.default;
9054
+ return BADGE_TONE_CLASSES[tone] ?? BADGE_TONE_CLASSES.default;
9055
+ }
9056
+ function OrderedListArtifact({
9057
+ title,
9058
+ intro,
9059
+ items,
9060
+ startIndex = 1,
9061
+ markerStyle = "number",
9062
+ className
9063
+ }) {
9064
+ const safeItems = Array.isArray(items) ? items : [];
9065
+ return /* @__PURE__ */ jsxRuntime.jsxs("section", { className: cn("text-left", className), children: [
9066
+ title ? /* @__PURE__ */ jsxRuntime.jsx("h3", { className: "font-bold text-slate-900 text-base leading-snug", children: title }) : null,
9067
+ intro ? /* @__PURE__ */ jsxRuntime.jsx(
9068
+ "p",
9069
+ {
9070
+ className: cn(
9071
+ "text-slate-500 text-sm leading-relaxed",
9072
+ title && "mt-4"
9073
+ ),
9074
+ children: renderRich(intro)
9075
+ }
9076
+ ) : null,
9077
+ safeItems.length > 0 ? /* @__PURE__ */ jsxRuntime.jsx(
9078
+ "ol",
9079
+ {
9080
+ className: cn(
9081
+ "flex list-none flex-col gap-3.5",
9082
+ (title || intro) && "mt-5"
9083
+ ),
9084
+ children: safeItems.map((item, index) => {
9085
+ const marker = item.marker ?? formatMarker(index, markerStyle, startIndex);
9086
+ return /* @__PURE__ */ jsxRuntime.jsxs(
9087
+ "li",
9088
+ {
9089
+ className: "flex items-start gap-3.5",
9090
+ children: [
9091
+ /* @__PURE__ */ jsxRuntime.jsx(
9092
+ "span",
9093
+ {
9094
+ className: cn(
9095
+ "flex h-7 w-7 shrink-0 items-center justify-center rounded-md font-medium text-sm tabular-nums",
9096
+ badgeToneClass(item.tone)
9097
+ ),
9098
+ children: marker
9099
+ }
9100
+ ),
9101
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-1 pt-0.5 text-slate-900 text-sm leading-relaxed", children: renderRich(item.content) })
9102
+ ]
9103
+ },
9104
+ index
9105
+ );
9106
+ })
9107
+ }
9108
+ ) : null
9109
+ ] });
9110
+ }
9111
+ var COMPLETE_BG = "#E6F4EC";
9112
+ var COMPLETE_ACCENT = "#16A34A";
9113
+ var ACTIVE_COLOR = "#F59E0B";
9114
+ var PENDING_STROKE = "#CBD5E1";
9115
+ var ERROR_BG = "#FEE2E2";
9116
+ var ERROR_COLOR = "#DC2626";
9117
+ var SPIN_CLASS = "ae-spin";
9118
+ var SPIN_STYLE_ID = "ae-spin-keyframes";
9119
+ function ensureSpinKeyframes() {
9120
+ if (typeof document === "undefined") return;
9121
+ if (document.getElementById(SPIN_STYLE_ID)) return;
9122
+ const style = document.createElement("style");
9123
+ style.id = SPIN_STYLE_ID;
9124
+ style.textContent = `@keyframes ${SPIN_CLASS}{to{transform:rotate(360deg)}}@media (prefers-reduced-motion: no-preference){.${SPIN_CLASS}{animation:${SPIN_CLASS} 0.8s linear infinite;transform-origin:center}}`;
9125
+ document.head.appendChild(style);
9126
+ }
9127
+ function resolveSize(size) {
9128
+ if (typeof size === "number") return size;
9129
+ switch (size) {
9130
+ case "sm":
9131
+ return 24;
9132
+ case "lg":
9133
+ return 48;
9134
+ case "md":
9135
+ default:
9136
+ return 34;
9137
+ }
9138
+ }
9139
+ function normalizeStatus(status) {
9140
+ switch (status) {
9141
+ case "completed":
9142
+ return "complete";
9143
+ case "in_progress":
9144
+ return "active";
9145
+ case "active":
9146
+ case "pending":
9147
+ case "error":
9148
+ case "complete":
9149
+ return status;
9150
+ default:
9151
+ return "complete";
9152
+ }
9153
+ }
9154
+ function CheckIcon8({
9155
+ color = COMPLETE_ACCENT,
9156
+ className,
9157
+ style,
9158
+ strokeWidth = 2.25
9159
+ }) {
9160
+ return /* @__PURE__ */ jsxRuntime.jsx(
9161
+ "svg",
9162
+ {
9163
+ viewBox: "0 0 24 24",
9164
+ fill: "none",
9165
+ stroke: color,
9166
+ strokeWidth,
9167
+ strokeLinecap: "round",
9168
+ strokeLinejoin: "round",
9169
+ "aria-hidden": "true",
9170
+ className,
9171
+ style,
9172
+ children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M5 12l4 4 8-9" })
9173
+ }
9174
+ );
9175
+ }
9176
+ function ClockIcon2({
9177
+ color = "#64748B",
9178
+ className,
9179
+ strokeWidth = 1.75
9180
+ }) {
9181
+ return /* @__PURE__ */ jsxRuntime.jsxs(
9182
+ "svg",
9183
+ {
9184
+ viewBox: "0 0 24 24",
9185
+ fill: "none",
9186
+ stroke: color,
9187
+ strokeWidth,
9188
+ strokeLinecap: "round",
9189
+ strokeLinejoin: "round",
9190
+ "aria-hidden": "true",
9191
+ className,
9192
+ children: [
9193
+ /* @__PURE__ */ jsxRuntime.jsx("circle", { cx: "12", cy: "12", r: "9" }),
9194
+ /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M12 7v5l3 2" })
9195
+ ]
9196
+ }
9197
+ );
9198
+ }
9199
+ function XIcon7({
9200
+ color = ERROR_COLOR,
9201
+ className,
9202
+ style
9203
+ }) {
9204
+ return /* @__PURE__ */ jsxRuntime.jsx(
9205
+ "svg",
9206
+ {
9207
+ viewBox: "0 0 24 24",
9208
+ fill: "none",
9209
+ stroke: color,
9210
+ strokeWidth: 2.25,
9211
+ strokeLinecap: "round",
9212
+ strokeLinejoin: "round",
9213
+ "aria-hidden": "true",
9214
+ className,
9215
+ style,
9216
+ children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M7 7l10 10M17 7L7 17" })
9217
+ }
9218
+ );
9219
+ }
9220
+ function StatusNode({ status, size, accentColor, className }) {
9221
+ const resolved = normalizeStatus(status);
9222
+ const px = resolveSize(size);
9223
+ const accent = accentColor ?? COMPLETE_ACCENT;
9224
+ if (resolved === "active") ensureSpinKeyframes();
9225
+ const base = cn(
9226
+ "inline-flex shrink-0 items-center justify-center rounded-full",
9227
+ className
9228
+ );
9229
+ const dimensions = { width: px, height: px };
9230
+ const glyphPx = Math.round(px * 0.5);
9231
+ if (resolved === "complete") {
9232
+ return /* @__PURE__ */ jsxRuntime.jsx(
9233
+ "span",
9234
+ {
9235
+ className: base,
9236
+ style: { ...dimensions, backgroundColor: COMPLETE_BG },
9237
+ "data-status": "complete",
9238
+ children: /* @__PURE__ */ jsxRuntime.jsx(CheckIcon8, { color: accent, className: "block", style: { width: glyphPx, height: glyphPx } })
9239
+ }
9240
+ );
9241
+ }
9242
+ if (resolved === "error") {
9243
+ return /* @__PURE__ */ jsxRuntime.jsx(
9244
+ "span",
9245
+ {
9246
+ className: base,
9247
+ style: { ...dimensions, backgroundColor: ERROR_BG },
9248
+ "data-status": "error",
9249
+ children: /* @__PURE__ */ jsxRuntime.jsx(XIcon7, { color: ERROR_COLOR, className: "block", style: { width: glyphPx, height: glyphPx } })
9250
+ }
9251
+ );
9252
+ }
9253
+ if (resolved === "active") {
9254
+ const ringColor = accentColor ?? ACTIVE_COLOR;
9255
+ return /* @__PURE__ */ jsxRuntime.jsx(
9256
+ "span",
9257
+ {
9258
+ className: base,
9259
+ style: dimensions,
9260
+ "data-status": "active",
9261
+ role: "status",
9262
+ "aria-label": "In progress",
9263
+ "aria-live": "polite",
9264
+ children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: cn(SPIN_CLASS, "block"), style: { width: px, height: px }, children: /* @__PURE__ */ jsxRuntime.jsx("svg", { viewBox: "0 0 24 24", fill: "none", "aria-hidden": "true", className: "block size-full", children: /* @__PURE__ */ jsxRuntime.jsx(
9265
+ "circle",
9266
+ {
9267
+ cx: "12",
9268
+ cy: "12",
9269
+ r: "10",
9270
+ fill: "none",
9271
+ stroke: ringColor,
9272
+ strokeWidth: "2.5",
9273
+ strokeLinecap: "round",
9274
+ strokeDasharray: "47 16"
9275
+ }
9276
+ ) }) })
9277
+ }
9278
+ );
9279
+ }
9280
+ return /* @__PURE__ */ jsxRuntime.jsx("span", { className: base, style: dimensions, "data-status": "pending", children: /* @__PURE__ */ jsxRuntime.jsx("svg", { viewBox: "0 0 24 24", fill: "none", "aria-hidden": "true", className: "block size-full", children: /* @__PURE__ */ jsxRuntime.jsx("circle", { cx: "12", cy: "12", r: "10", fill: "none", stroke: PENDING_STROKE, strokeWidth: "1.75" }) }) });
9281
+ }
9282
+ var DEFAULT_TASK_LABEL = "RESEARCH TASK";
9283
+ var DEFAULT_FINDINGS_LABEL = "EMERGING FINDINGS";
9284
+ function stepLabelClass(status) {
9285
+ switch (status) {
9286
+ case "completed":
9287
+ return "font-normal text-slate-700";
9288
+ case "in_progress":
9289
+ return "font-bold text-slate-900";
9290
+ case "pending":
9291
+ default:
9292
+ return "font-normal text-slate-400";
9293
+ }
9294
+ }
9295
+ function hasRichContent(findings) {
9296
+ if (findings == null) return false;
9297
+ if (typeof findings === "string") return findings.trim().length > 0;
9298
+ return findings.some((segment) => segment.text.trim().length > 0);
9299
+ }
9300
+ function DeepResearchProgress({
9301
+ taskLabel = DEFAULT_TASK_LABEL,
9302
+ taskDescription,
9303
+ steps,
9304
+ findingsLabel = DEFAULT_FINDINGS_LABEL,
9305
+ findings,
9306
+ showFindings,
9307
+ className
9308
+ }) {
9309
+ const safeSteps = Array.isArray(steps) ? steps : [];
9310
+ const findingsHasContent = hasRichContent(findings);
9311
+ const findingsVisible = findingsHasContent && showFindings !== false;
9312
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn("flex w-full flex-col gap-6 text-left", className), children: [
9313
+ /* @__PURE__ */ jsxRuntime.jsxs(CardShell, { className: "rounded-xl border-slate-200/80 bg-slate-50/70 px-5 py-4 shadow-none", children: [
9314
+ taskLabel ? /* @__PURE__ */ jsxRuntime.jsx("p", { className: "font-medium text-[11px] text-slate-400 uppercase tracking-wider", children: taskLabel }) : null,
9315
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "mt-2 text-sm text-slate-700 leading-relaxed", children: taskDescription })
9316
+ ] }),
9317
+ safeSteps.length > 0 ? /* @__PURE__ */ jsxRuntime.jsx("ol", { className: "flex list-none flex-col gap-5", children: safeSteps.map((step, index) => /* @__PURE__ */ jsxRuntime.jsxs(
9318
+ "li",
9319
+ {
9320
+ className: "flex items-center gap-4",
9321
+ "data-status": step.status,
9322
+ children: [
9323
+ /* @__PURE__ */ jsxRuntime.jsx(StatusNode, { status: step.status, size: "md" }),
9324
+ /* @__PURE__ */ jsxRuntime.jsx(
9325
+ "span",
9326
+ {
9327
+ className: cn(
9328
+ "text-sm leading-snug",
9329
+ stepLabelClass(step.status)
9330
+ ),
9331
+ children: step.label
9332
+ }
9333
+ )
9334
+ ]
9335
+ },
9336
+ step.id ?? index
9337
+ )) }) : null,
9338
+ findingsVisible ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-4", children: [
9339
+ /* @__PURE__ */ jsxRuntime.jsx("hr", { className: "border-slate-200 border-t" }),
9340
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
9341
+ findingsLabel ? /* @__PURE__ */ jsxRuntime.jsx("p", { className: "font-medium text-[11px] text-slate-400 uppercase tracking-wider", children: findingsLabel }) : null,
9342
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "mt-3 text-sm text-slate-700 leading-relaxed [&_strong]:text-slate-900", children: renderRich(findings) })
9343
+ ] })
9344
+ ] }) : null
9345
+ ] });
9346
+ }
9347
+ var NODE_SIZE = 48;
9348
+ var NODE_COLUMN_WIDTH = NODE_SIZE;
9349
+ var DEFAULT_ACCENT = "#16A34A";
9350
+ var FOOTER_SEPARATOR = " \xB7 ";
9351
+ function resolveFooterItems(footer) {
9352
+ if (!footer) return [];
9353
+ if (Array.isArray(footer.items) && footer.items.length > 0) {
9354
+ return footer.items.filter((item) => item != null && item !== "");
7702
9355
  }
7703
- if (payload.type === "metrics" && payload.metrics) {
7704
- return /* @__PURE__ */ jsxRuntime.jsx(MetricsGrid, { metrics: payload.metrics, className });
9356
+ const parts = [];
9357
+ if (footer.thinkingLabel) parts.push(footer.thinkingLabel);
9358
+ if (footer.sourcesLabel) parts.push(footer.sourcesLabel);
9359
+ return parts;
9360
+ }
9361
+ function TimelineStep({
9362
+ step,
9363
+ isLast,
9364
+ accentColor
9365
+ }) {
9366
+ return /* @__PURE__ */ jsxRuntime.jsxs("li", { className: "relative flex gap-4", "data-status": step.status ?? "complete", children: [
9367
+ /* @__PURE__ */ jsxRuntime.jsxs(
9368
+ "div",
9369
+ {
9370
+ className: "relative flex shrink-0 justify-center",
9371
+ style: { width: NODE_COLUMN_WIDTH },
9372
+ children: [
9373
+ !isLast && /* @__PURE__ */ jsxRuntime.jsx(
9374
+ "span",
9375
+ {
9376
+ "aria-hidden": "true",
9377
+ className: "absolute top-1/2 bottom-0 w-0.5 bg-slate-200",
9378
+ style: { top: NODE_SIZE / 2, height: `calc(100% - ${NODE_SIZE / 2}px)` }
9379
+ }
9380
+ ),
9381
+ /* @__PURE__ */ jsxRuntime.jsx(
9382
+ StatusNode,
9383
+ {
9384
+ status: step.status ?? "complete",
9385
+ size: NODE_SIZE,
9386
+ accentColor,
9387
+ className: "relative z-10"
9388
+ }
9389
+ )
9390
+ ]
9391
+ }
9392
+ ),
9393
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex min-w-0 flex-col gap-1.5 pt-1.5 pb-8", children: [
9394
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "font-semibold text-sm text-slate-900 leading-snug", children: step.title }),
9395
+ step.description ? /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm text-slate-500 leading-snug", children: step.description }) : null
9396
+ ] })
9397
+ ] });
9398
+ }
9399
+ function Tracker({
9400
+ steps,
9401
+ footer,
9402
+ showFooterIcon = true,
9403
+ accentColor = DEFAULT_ACCENT,
9404
+ className
9405
+ }) {
9406
+ const hasSteps = Array.isArray(steps) && steps.length > 0;
9407
+ const footerItems = resolveFooterItems(footer);
9408
+ const hasFooter = footerItems.length > 0;
9409
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn("w-full bg-card pl-2", className), children: [
9410
+ hasSteps ? /* @__PURE__ */ jsxRuntime.jsx("ol", { className: "flex flex-col", children: steps.map((step, index) => /* @__PURE__ */ jsxRuntime.jsx(
9411
+ TimelineStep,
9412
+ {
9413
+ step,
9414
+ isLast: index === steps.length - 1,
9415
+ accentColor
9416
+ },
9417
+ step.id ?? `${step.title}-${index}`
9418
+ )) }) : /* @__PURE__ */ jsxRuntime.jsx("p", { className: "py-6 text-slate-400 text-sm", children: "No steps" }),
9419
+ hasFooter ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-2 border-slate-200 border-t pt-5", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2 text-xs text-slate-500", children: [
9420
+ showFooterIcon ? /* @__PURE__ */ jsxRuntime.jsx(ClockIcon2, { className: "size-4 shrink-0" }) : null,
9421
+ /* @__PURE__ */ jsxRuntime.jsx("span", { children: footerItems.join(FOOTER_SEPARATOR) })
9422
+ ] }) }) : null
9423
+ ] });
9424
+ }
9425
+ var DEFAULTS = {
9426
+ /** Selected row background — emerald-50. */
9427
+ selectedBg: "#ECFDF5",
9428
+ /** Selected row border — emerald-200. */
9429
+ selectedBorder: "#A7F3D0",
9430
+ /** Selected radio circle fill — emerald-500. */
9431
+ selectedCircle: "#10B981",
9432
+ /** Selected label text — slate-900. */
9433
+ selectedLabel: "#0F172A",
9434
+ /** Unselected row border — slate-200. */
9435
+ unselectedBorder: "#E2E8F0",
9436
+ /** Unselected radio ring — slate-300. */
9437
+ unselectedRing: "#CBD5E1",
9438
+ /** Unselected label text — slate-500. */
9439
+ unselectedLabel: "#64748B",
9440
+ /** Progress pill background — indigo-50. */
9441
+ pillBg: "#EEF2FF",
9442
+ /** Progress pill text — indigo-600. */
9443
+ pillText: "#4F46E5",
9444
+ /** Category label text — slate-400. */
9445
+ categoryText: "#94A3B8",
9446
+ /** Question title text — slate-900. */
9447
+ titleColor: "#0F172A"
9448
+ };
9449
+ function resolveProgressLabel(progressLabel, questionIndex, questionTotal) {
9450
+ if (progressLabel) return progressLabel;
9451
+ if (typeof questionIndex === "number" && typeof questionTotal === "number" && questionTotal > 0) {
9452
+ return `Question ${questionIndex} of ${questionTotal}`;
7705
9453
  }
7706
- if (payload.type === "table" && payload.table) {
7707
- return /* @__PURE__ */ jsxRuntime.jsx(DataTable, { data: payload.table, className });
9454
+ return void 0;
9455
+ }
9456
+ function CheckIcon9() {
9457
+ return /* @__PURE__ */ jsxRuntime.jsx(
9458
+ "svg",
9459
+ {
9460
+ "aria-hidden": "true",
9461
+ viewBox: "0 0 24 24",
9462
+ width: "14",
9463
+ height: "14",
9464
+ fill: "none",
9465
+ stroke: "#FFFFFF",
9466
+ strokeWidth: "3",
9467
+ strokeLinecap: "round",
9468
+ strokeLinejoin: "round",
9469
+ children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M5 13l4 4L19 7" })
9470
+ }
9471
+ );
9472
+ }
9473
+ function OptionRow({
9474
+ option,
9475
+ selected,
9476
+ submitted,
9477
+ isTabStop,
9478
+ colors,
9479
+ customAnswer,
9480
+ customAnswerPlaceholder,
9481
+ onSelect,
9482
+ onMove,
9483
+ onCustomChange,
9484
+ onCustomCommit
9485
+ }) {
9486
+ const isOtherExpanded = !!option.isOther && selected;
9487
+ const handleKeyDown = (e) => {
9488
+ if (submitted) return;
9489
+ switch (e.key) {
9490
+ case " ":
9491
+ case "Enter":
9492
+ e.preventDefault();
9493
+ onSelect();
9494
+ break;
9495
+ // WAI-ARIA radiogroup pattern: arrow keys move focus to the adjacent
9496
+ // radio and check it. Down/Right advance, Up/Left retreat.
9497
+ case "ArrowDown":
9498
+ case "ArrowRight":
9499
+ e.preventDefault();
9500
+ onMove(1);
9501
+ break;
9502
+ case "ArrowUp":
9503
+ case "ArrowLeft":
9504
+ e.preventDefault();
9505
+ onMove(-1);
9506
+ break;
9507
+ }
9508
+ };
9509
+ return /* @__PURE__ */ jsxRuntime.jsxs(
9510
+ "div",
9511
+ {
9512
+ role: "radio",
9513
+ "aria-checked": selected,
9514
+ tabIndex: submitted ? -1 : isTabStop ? 0 : -1,
9515
+ "data-option-id": option.id,
9516
+ onClick: submitted ? void 0 : onSelect,
9517
+ onKeyDown: handleKeyDown,
9518
+ className: cn(
9519
+ "flex items-center gap-3 rounded-xl border px-4 py-4 text-left transition-colors",
9520
+ !submitted && "cursor-pointer focus:outline-none focus-visible:ring-2 focus-visible:ring-emerald-400/60",
9521
+ selected ? "font-medium" : "font-normal"
9522
+ ),
9523
+ style: {
9524
+ backgroundColor: selected ? colors.selectedBg : "transparent",
9525
+ borderColor: selected ? colors.selectedBorder : colors.unselectedBorder
9526
+ },
9527
+ children: [
9528
+ /* @__PURE__ */ jsxRuntime.jsx(
9529
+ "span",
9530
+ {
9531
+ "aria-hidden": "true",
9532
+ className: "mt-0.5 flex size-7 shrink-0 items-center justify-center rounded-full",
9533
+ style: selected ? { backgroundColor: colors.selectedCircle } : {
9534
+ backgroundColor: "transparent",
9535
+ border: `2px solid ${colors.unselectedRing}`
9536
+ },
9537
+ children: selected && /* @__PURE__ */ jsxRuntime.jsx(CheckIcon9, {})
9538
+ }
9539
+ ),
9540
+ isOtherExpanded ? /* @__PURE__ */ jsxRuntime.jsx(
9541
+ "input",
9542
+ {
9543
+ type: "text",
9544
+ value: customAnswer,
9545
+ placeholder: customAnswerPlaceholder,
9546
+ disabled: submitted,
9547
+ autoComplete: "off",
9548
+ onClick: (e) => e.stopPropagation(),
9549
+ onChange: (e) => onCustomChange(e.target.value),
9550
+ onBlur: onCustomCommit,
9551
+ onKeyDown: (e) => {
9552
+ e.stopPropagation();
9553
+ if (e.key === "Enter") {
9554
+ e.preventDefault();
9555
+ onCustomCommit();
9556
+ }
9557
+ },
9558
+ className: "flex-1 border-0 bg-transparent p-0 text-sm leading-snug outline-none placeholder:text-slate-400",
9559
+ style: { color: colors.selectedLabel }
9560
+ }
9561
+ ) : /* @__PURE__ */ jsxRuntime.jsx(
9562
+ "span",
9563
+ {
9564
+ className: "flex-1 text-sm leading-snug",
9565
+ style: { color: selected ? colors.selectedLabel : colors.unselectedLabel },
9566
+ children: option.label
9567
+ }
9568
+ )
9569
+ ]
9570
+ }
9571
+ );
9572
+ }
9573
+ function BuiltInQuestions(props) {
9574
+ const {
9575
+ question,
9576
+ options,
9577
+ selectedOptionId,
9578
+ customAnswer,
9579
+ customAnswerPlaceholder,
9580
+ progressLabel,
9581
+ categoryLabel,
9582
+ questionIndex,
9583
+ questionTotal,
9584
+ submitted = false,
9585
+ onSelect,
9586
+ onCustomAnswerChange,
9587
+ onAnswer,
9588
+ colors: colorOverrides,
9589
+ className
9590
+ } = props;
9591
+ const colors = {
9592
+ ...DEFAULTS,
9593
+ ...colorOverrides
9594
+ };
9595
+ const safeOptions = (options ?? []).filter(
9596
+ (option) => !!option?.id
9597
+ );
9598
+ const radioGroupRef = React4.useRef(null);
9599
+ const isControlled = typeof onSelect === "function";
9600
+ const [internalSelected, setInternalSelected] = React4.useState(
9601
+ selectedOptionId ?? null
9602
+ );
9603
+ const [internalCustom, setInternalCustom] = React4.useState(customAnswer ?? "");
9604
+ const activeSelected = isControlled ? selectedOptionId ?? null : internalSelected;
9605
+ const activeCustom = isControlled ? customAnswer ?? "" : internalCustom;
9606
+ const resolvedProgress = resolveProgressLabel(
9607
+ progressLabel,
9608
+ questionIndex,
9609
+ questionTotal
9610
+ );
9611
+ const hasHeader = !!resolvedProgress || !!categoryLabel;
9612
+ const handleSelect = (option) => {
9613
+ if (submitted) return;
9614
+ if (isControlled) {
9615
+ onSelect?.(option.id);
9616
+ } else {
9617
+ setInternalSelected(option.id);
9618
+ }
9619
+ if (!option.isOther) {
9620
+ onAnswer?.({ optionId: option.id });
9621
+ }
9622
+ };
9623
+ const handleMove = (fromIndex, delta) => {
9624
+ if (submitted) return;
9625
+ const count = safeOptions.length;
9626
+ if (count === 0) return;
9627
+ const nextIndex = (fromIndex + delta + count) % count;
9628
+ const nextOption = safeOptions[nextIndex];
9629
+ if (!nextOption) return;
9630
+ handleSelect(nextOption);
9631
+ const group = radioGroupRef.current;
9632
+ if (group) {
9633
+ const target = group.querySelector(
9634
+ `[data-option-id="${CSS.escape(nextOption.id)}"]`
9635
+ );
9636
+ target?.focus();
9637
+ }
9638
+ };
9639
+ const handleCustomChange = (value) => {
9640
+ if (isControlled) {
9641
+ onCustomAnswerChange?.(value);
9642
+ } else {
9643
+ setInternalCustom(value);
9644
+ }
9645
+ };
9646
+ const handleCustomCommit = (optionId) => {
9647
+ onAnswer?.({ optionId, customAnswer: activeCustom });
9648
+ };
9649
+ return /* @__PURE__ */ jsxRuntime.jsxs(CardShell, { className: cn("p-6 sm:p-7", className), children: [
9650
+ hasHeader && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mb-5 flex items-center justify-between gap-3", children: [
9651
+ resolvedProgress ? /* @__PURE__ */ jsxRuntime.jsx(
9652
+ "span",
9653
+ {
9654
+ className: "inline-flex items-center rounded-lg px-3 py-1 font-semibold text-xs",
9655
+ style: { backgroundColor: colors.pillBg, color: colors.pillText },
9656
+ children: resolvedProgress
9657
+ }
9658
+ ) : /* @__PURE__ */ jsxRuntime.jsx("span", { "aria-hidden": "true" }),
9659
+ categoryLabel && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs", style: { color: colors.categoryText }, children: categoryLabel })
9660
+ ] }),
9661
+ /* @__PURE__ */ jsxRuntime.jsx(
9662
+ "h3",
9663
+ {
9664
+ className: "font-bold text-base leading-snug",
9665
+ style: { color: colors.titleColor },
9666
+ children: question
9667
+ }
9668
+ ),
9669
+ safeOptions.length > 0 && /* @__PURE__ */ jsxRuntime.jsx(
9670
+ "div",
9671
+ {
9672
+ ref: radioGroupRef,
9673
+ role: "radiogroup",
9674
+ "aria-label": question,
9675
+ className: "mt-7 flex flex-col gap-3",
9676
+ children: (() => {
9677
+ const selectedIndex = safeOptions.findIndex(
9678
+ (option) => option.id === activeSelected
9679
+ );
9680
+ const tabStopIndex = selectedIndex === -1 ? 0 : selectedIndex;
9681
+ return safeOptions.map((option, i) => {
9682
+ const selected = activeSelected === option.id;
9683
+ return /* @__PURE__ */ jsxRuntime.jsx(
9684
+ OptionRow,
9685
+ {
9686
+ option,
9687
+ selected,
9688
+ submitted,
9689
+ isTabStop: i === tabStopIndex,
9690
+ colors,
9691
+ customAnswer: activeCustom,
9692
+ customAnswerPlaceholder,
9693
+ onSelect: () => handleSelect(option),
9694
+ onMove: (delta) => handleMove(i, delta),
9695
+ onCustomChange: handleCustomChange,
9696
+ onCustomCommit: () => handleCustomCommit(option.id)
9697
+ },
9698
+ option.id
9699
+ );
9700
+ });
9701
+ })()
9702
+ }
9703
+ )
9704
+ ] });
9705
+ }
9706
+ var DEFAULT_ACCENT_COLOR = "#1e2a44";
9707
+ var DEFAULT_INACTIVE_COLOR = "#dfe3ea";
9708
+ var DEFAULT_ACTIVE_CHAPTER_BG = "#f4f6fa";
9709
+ var DEFAULT_MUTED_TEXT_COLOR = "#94a3b8";
9710
+ var DEFAULT_WAVEFORM = [
9711
+ 0.4,
9712
+ 0.45,
9713
+ 0.95,
9714
+ 0.6,
9715
+ 1,
9716
+ 0.85,
9717
+ 0.4,
9718
+ 0.55,
9719
+ 0.7,
9720
+ 0.45,
9721
+ 0.6,
9722
+ 0.45,
9723
+ 0.4,
9724
+ 0.7,
9725
+ 0.5,
9726
+ 0.45,
9727
+ 0.55,
9728
+ 0.4
9729
+ ];
9730
+ function formatTime2(totalSeconds) {
9731
+ const safe = Number.isFinite(totalSeconds) && totalSeconds > 0 ? totalSeconds : 0;
9732
+ const whole = Math.floor(safe);
9733
+ const minutes = Math.floor(whole / 60);
9734
+ const seconds = whole % 60;
9735
+ return `${minutes}:${String(seconds).padStart(2, "0")}`;
9736
+ }
9737
+ function AudioPlayer({
9738
+ title,
9739
+ src,
9740
+ durationSeconds = 0,
9741
+ currentTimeSeconds = 0,
9742
+ isPlaying = false,
9743
+ waveform,
9744
+ chapters,
9745
+ accentColor,
9746
+ inactiveColor,
9747
+ activeChapterBg,
9748
+ mutedTextColor,
9749
+ className,
9750
+ onTogglePlay,
9751
+ onSeek
9752
+ }) {
9753
+ const accent = accentColor ?? DEFAULT_ACCENT_COLOR;
9754
+ const inactive = inactiveColor ?? DEFAULT_INACTIVE_COLOR;
9755
+ const activeBg = activeChapterBg ?? DEFAULT_ACTIVE_CHAPTER_BG;
9756
+ const mutedText = mutedTextColor ?? DEFAULT_MUTED_TEXT_COLOR;
9757
+ const bars = waveform && waveform.length > 0 ? waveform : DEFAULT_WAVEFORM;
9758
+ const chapterList = chapters ?? [];
9759
+ const hasSrc = typeof src === "string" && src.length > 0;
9760
+ const audioRef = React4.useRef(null);
9761
+ const [currentTime, setCurrentTime] = React4.useState(currentTimeSeconds);
9762
+ const [duration, setDuration] = React4.useState(durationSeconds);
9763
+ const [playing, setPlaying] = React4.useState(isPlaying);
9764
+ React4.useEffect(() => {
9765
+ setCurrentTime(currentTimeSeconds);
9766
+ }, [currentTimeSeconds]);
9767
+ React4.useEffect(() => {
9768
+ setDuration(durationSeconds);
9769
+ }, [durationSeconds]);
9770
+ React4.useEffect(() => {
9771
+ setPlaying(isPlaying);
9772
+ }, [isPlaying]);
9773
+ const lastChapterStart = chapterList.reduce(
9774
+ (max, c) => c.startSeconds > max ? c.startSeconds : max,
9775
+ 0
9776
+ );
9777
+ const effectiveDuration = duration > 0 ? duration : durationSeconds > 0 ? durationSeconds : lastChapterStart;
9778
+ const progress = effectiveDuration > 0 ? Math.min(Math.max(currentTime / effectiveDuration, 0), 1) : 0;
9779
+ const handleLoadedMetadata = React4.useCallback(() => {
9780
+ const el = audioRef.current;
9781
+ if (el && Number.isFinite(el.duration)) setDuration(el.duration);
9782
+ }, []);
9783
+ const handleTimeUpdate = React4.useCallback(() => {
9784
+ const el = audioRef.current;
9785
+ if (el) setCurrentTime(el.currentTime);
9786
+ }, []);
9787
+ const handleEnded = React4.useCallback(() => {
9788
+ setPlaying(false);
9789
+ onTogglePlay?.(false);
9790
+ }, [onTogglePlay]);
9791
+ const seekTo = React4.useCallback(
9792
+ (seconds) => {
9793
+ const clamped = effectiveDuration > 0 ? Math.min(Math.max(seconds, 0), effectiveDuration) : Math.max(seconds, 0);
9794
+ setCurrentTime(clamped);
9795
+ const el = audioRef.current;
9796
+ if (el) {
9797
+ try {
9798
+ el.currentTime = clamped;
9799
+ } catch {
9800
+ }
9801
+ }
9802
+ onSeek?.(clamped);
9803
+ },
9804
+ [effectiveDuration, onSeek]
9805
+ );
9806
+ const togglePlay = React4.useCallback(() => {
9807
+ const next = !playing;
9808
+ setPlaying(next);
9809
+ const el = audioRef.current;
9810
+ if (el) {
9811
+ try {
9812
+ if (next) {
9813
+ const maybePromise = el.play();
9814
+ if (maybePromise && typeof maybePromise.catch === "function") {
9815
+ maybePromise.catch(() => {
9816
+ });
9817
+ }
9818
+ } else {
9819
+ el.pause();
9820
+ }
9821
+ } catch {
9822
+ }
9823
+ }
9824
+ onTogglePlay?.(next);
9825
+ }, [playing, onTogglePlay]);
9826
+ const handleWaveformSeek = React4.useCallback(
9827
+ (event) => {
9828
+ const rect = event.currentTarget.getBoundingClientRect();
9829
+ const ratio = rect.width > 0 ? (event.clientX - rect.left) / rect.width : 0;
9830
+ const clampedRatio = Math.min(Math.max(ratio, 0), 1);
9831
+ seekTo(clampedRatio * effectiveDuration);
9832
+ },
9833
+ [effectiveDuration, seekTo]
9834
+ );
9835
+ let activeChapterIndex = -1;
9836
+ for (let i = 0; i < chapterList.length; i += 1) {
9837
+ if (chapterList[i].startSeconds <= currentTime) activeChapterIndex = i;
7708
9838
  }
7709
- return null;
9839
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn("w-full", className), children: [
9840
+ hasSrc && /* @__PURE__ */ jsxRuntime.jsx(
9841
+ "audio",
9842
+ {
9843
+ ref: audioRef,
9844
+ src,
9845
+ preload: "metadata",
9846
+ className: "hidden",
9847
+ "aria-label": title,
9848
+ onLoadedMetadata: handleLoadedMetadata,
9849
+ onTimeUpdate: handleTimeUpdate,
9850
+ onEnded: handleEnded,
9851
+ children: /* @__PURE__ */ jsxRuntime.jsx("track", { kind: "captions" })
9852
+ }
9853
+ ),
9854
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-5", children: [
9855
+ /* @__PURE__ */ jsxRuntime.jsx(
9856
+ "button",
9857
+ {
9858
+ type: "button",
9859
+ onClick: togglePlay,
9860
+ "aria-label": playing ? "Pause" : "Play",
9861
+ "aria-pressed": playing,
9862
+ className: "flex h-24 w-24 shrink-0 items-center justify-center rounded-full text-white transition-opacity hover:opacity-90 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2",
9863
+ style: { backgroundColor: accent },
9864
+ children: playing ? (
9865
+ // Pause glyph: two rounded bars.
9866
+ /* @__PURE__ */ jsxRuntime.jsxs("svg", { width: "34", height: "34", viewBox: "0 0 24 24", "aria-hidden": "true", children: [
9867
+ /* @__PURE__ */ jsxRuntime.jsx("rect", { x: "6", y: "4", width: "4", height: "16", rx: "1.5", fill: "currentColor" }),
9868
+ /* @__PURE__ */ jsxRuntime.jsx("rect", { x: "14", y: "4", width: "4", height: "16", rx: "1.5", fill: "currentColor" })
9869
+ ] })
9870
+ ) : (
9871
+ // Play glyph: a single triangle nudged right for optical centering.
9872
+ /* @__PURE__ */ jsxRuntime.jsx("svg", { width: "34", height: "34", viewBox: "0 0 24 24", "aria-hidden": "true", children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M8 5.5l11 6.5-11 6.5z", fill: "currentColor" }) })
9873
+ )
9874
+ }
9875
+ ),
9876
+ /* @__PURE__ */ jsxRuntime.jsx(
9877
+ "button",
9878
+ {
9879
+ type: "button",
9880
+ onClick: handleWaveformSeek,
9881
+ "aria-label": "Seek",
9882
+ className: "flex h-[88px] flex-1 cursor-pointer items-center gap-[6px] rounded-md focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring",
9883
+ children: bars.map((rawHeight, index) => {
9884
+ const height = Math.min(Math.max(rawHeight, 0), 1);
9885
+ const barRatio = bars.length > 1 ? index / (bars.length - 1) : 0;
9886
+ const played = barRatio <= progress;
9887
+ return /* @__PURE__ */ jsxRuntime.jsx(
9888
+ "span",
9889
+ {
9890
+ "aria-hidden": "true",
9891
+ className: "flex-1 rounded-[3px]",
9892
+ style: {
9893
+ height: `${Math.max(height * 100, 8)}%`,
9894
+ backgroundColor: played ? accent : inactive
9895
+ }
9896
+ },
9897
+ index
9898
+ );
9899
+ })
9900
+ }
9901
+ ),
9902
+ /* @__PURE__ */ jsxRuntime.jsxs(
9903
+ "span",
9904
+ {
9905
+ className: "shrink-0 font-mono text-xs tabular-nums",
9906
+ style: { color: mutedText },
9907
+ children: [
9908
+ formatTime2(currentTime),
9909
+ " / ",
9910
+ formatTime2(effectiveDuration)
9911
+ ]
9912
+ }
9913
+ )
9914
+ ] }),
9915
+ chapterList.length > 0 && /* @__PURE__ */ jsxRuntime.jsx("ul", { className: "mt-6 flex flex-col gap-1", children: chapterList.map((chapter, index) => {
9916
+ const isActive = index === activeChapterIndex;
9917
+ return /* @__PURE__ */ jsxRuntime.jsx("li", { children: /* @__PURE__ */ jsxRuntime.jsxs(
9918
+ "button",
9919
+ {
9920
+ type: "button",
9921
+ onClick: () => seekTo(chapter.startSeconds),
9922
+ "aria-current": isActive ? "true" : void 0,
9923
+ className: cn(
9924
+ "flex w-full items-center gap-5 rounded-xl px-3 py-2.5 text-left transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring"
9925
+ ),
9926
+ style: isActive ? { backgroundColor: activeBg } : void 0,
9927
+ children: [
9928
+ /* @__PURE__ */ jsxRuntime.jsx(
9929
+ "span",
9930
+ {
9931
+ className: "shrink-0 font-mono text-xs tabular-nums",
9932
+ style: { color: mutedText },
9933
+ children: formatTime2(chapter.startSeconds)
9934
+ }
9935
+ ),
9936
+ /* @__PURE__ */ jsxRuntime.jsx(
9937
+ "span",
9938
+ {
9939
+ className: cn(
9940
+ "text-sm",
9941
+ isActive ? "font-semibold text-slate-900" : "font-normal text-slate-500"
9942
+ ),
9943
+ children: chapter.label
9944
+ }
9945
+ )
9946
+ ]
9947
+ }
9948
+ ) }, chapter.startSeconds + "-" + chapter.label);
9949
+ }) })
9950
+ ] });
9951
+ }
9952
+ var ARTIFACT_REGISTRY = {
9953
+ chart: ({ payload, className }) => payload.chart ? /* @__PURE__ */ jsxRuntime.jsx(ChartContainer, { data: payload.chart, className }) : null,
9954
+ metrics: ({ payload, className }) => payload.metrics ? /* @__PURE__ */ jsxRuntime.jsx(MetricsGrid, { metrics: payload.metrics, className }) : null,
9955
+ table: ({ payload, className }) => payload.table ? /* @__PURE__ */ jsxRuntime.jsx(DataTable, { data: payload.table, className }) : null,
9956
+ "kpi-card-with-chart": ({ payload, className }) => payload.kpiCardWithChart ? /* @__PURE__ */ jsxRuntime.jsx(KpiCardWithChart, { ...payload.kpiCardWithChart, className }) : null,
9957
+ "pie-chart": ({ payload, className }) => payload.pieChart ? /* @__PURE__ */ jsxRuntime.jsx(PieChartArtifact, { ...payload.pieChart, className }) : null,
9958
+ "stacked-sparklines": ({ payload, className }) => payload.stackedSparklines ? /* @__PURE__ */ jsxRuntime.jsx(StackedSparklines, { ...payload.stackedSparklines, className }) : null,
9959
+ "stat-card-half-circle": ({ payload, className }) => payload.statCardHalfCircle ? /* @__PURE__ */ jsxRuntime.jsx(StatCardHalfCircle, { ...payload.statCardHalfCircle, className }) : null,
9960
+ "table-list": ({ payload, className }) => payload.tableList ? /* @__PURE__ */ jsxRuntime.jsx(TableListArtifact, { ...payload.tableList, className }) : null,
9961
+ "kpi-card-with-sparklines": ({ payload, className }) => payload.kpiCardWithSparklines ? /* @__PURE__ */ jsxRuntime.jsx(KpiCardWithSparklines, { ...payload.kpiCardWithSparklines, className }) : null,
9962
+ "locations-revenue-card": ({ payload, className }) => payload.locationsRevenue ? /* @__PURE__ */ jsxRuntime.jsx(LocationsRevenueCard, { ...payload.locationsRevenue, className }) : null,
9963
+ "row-based-data-list": ({ payload, className }) => payload.rowBasedDataList ? /* @__PURE__ */ jsxRuntime.jsx(RowBasedDataList, { ...payload.rowBasedDataList, className }) : null,
9964
+ badges: ({ payload, className }) => payload.badges ? /* @__PURE__ */ jsxRuntime.jsx(BadgesArtifact, { ...payload.badges, className }) : null,
9965
+ "ordered-list": ({ payload, className }) => payload.orderedList ? /* @__PURE__ */ jsxRuntime.jsx(OrderedListArtifact, { ...payload.orderedList, className }) : null,
9966
+ "deep-research-progress": ({ payload, className }) => payload.deepResearchProgress ? /* @__PURE__ */ jsxRuntime.jsx(DeepResearchProgress, { ...payload.deepResearchProgress, className }) : null,
9967
+ tracker: ({ payload, className }) => payload.tracker ? /* @__PURE__ */ jsxRuntime.jsx(Tracker, { ...payload.tracker, className }) : null,
9968
+ "built-in-questions": ({ payload, className }) => payload.builtInQuestions ? /* @__PURE__ */ jsxRuntime.jsx(BuiltInQuestions, { ...payload.builtInQuestions, className }) : null,
9969
+ "audio-player": ({ payload, className }) => payload.audioPlayer ? /* @__PURE__ */ jsxRuntime.jsx(AudioPlayer, { ...payload.audioPlayer, className }) : null
9970
+ };
9971
+ function DataPayloadView({ payload, className }) {
9972
+ const render = ARTIFACT_REGISTRY[payload.type];
9973
+ return render ? /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: render({ payload, className }) }) : null;
7710
9974
  }
7711
9975
  function ReportView({ report, className }) {
7712
9976
  return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn("space-y-6", className), children: [
@@ -7797,25 +10061,34 @@ function MessageList({
7797
10061
  const hasSteps = message.role === "assistant" && !!message.steps && message.steps.length > 0;
7798
10062
  const hasAttachments = !!message.attachments && message.attachments.length > 0;
7799
10063
  return /* @__PURE__ */ jsxRuntime.jsxs(MessageContainer, { role: message.role, children: [
7800
- showAvatars && /* @__PURE__ */ jsxRuntime.jsx(AgentAvatar, { role: message.role, size: "sm" }),
7801
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex min-w-0 flex-col gap-2", children: [
7802
- hasReasoning && /* @__PURE__ */ jsxRuntime.jsx(MessageWithReasoning, { steps: message.reasoning }),
7803
- hasSteps && /* @__PURE__ */ jsxRuntime.jsx(MessageWithSteps, { steps: message.steps }),
7804
- message.content && /* @__PURE__ */ jsxRuntime.jsx(MessageBubble, { role: message.role, children: /* @__PURE__ */ jsxRuntime.jsx(MessageContent, { children: message.content }) }),
7805
- hasAttachments && /* @__PURE__ */ jsxRuntime.jsx(MessageWithAttachments, { attachments: message.attachments }),
7806
- message.data && /* @__PURE__ */ jsxRuntime.jsx(DataPayloadView, { payload: message.data }),
7807
- message.confirmation && /* @__PURE__ */ jsxRuntime.jsx(
7808
- ConfirmationPanel,
7809
- {
7810
- title: message.confirmation.title,
7811
- summary: message.confirmation.summary,
7812
- body: message.confirmation.body,
7813
- markdown: message.confirmation.markdown,
7814
- actions: message.confirmation.actions,
7815
- onAction: (actionId) => onConfirmAction?.(message.id, actionId)
7816
- }
7817
- )
7818
- ] })
10064
+ showAvatars && /* @__PURE__ */ jsxRuntime.jsx(AgentAvatar, { role: message.role, size: "md" }),
10065
+ /* @__PURE__ */ jsxRuntime.jsxs(
10066
+ "div",
10067
+ {
10068
+ className: cn(
10069
+ "flex min-w-0 flex-col gap-2",
10070
+ message.role === "user" && "items-end"
10071
+ ),
10072
+ children: [
10073
+ hasReasoning && /* @__PURE__ */ jsxRuntime.jsx(MessageWithReasoning, { steps: message.reasoning }),
10074
+ hasSteps && /* @__PURE__ */ jsxRuntime.jsx(MessageWithSteps, { steps: message.steps }),
10075
+ message.content && /* @__PURE__ */ jsxRuntime.jsx(MessageBubble, { role: message.role, children: /* @__PURE__ */ jsxRuntime.jsx(MessageContent, { children: message.content }) }),
10076
+ hasAttachments && /* @__PURE__ */ jsxRuntime.jsx(MessageWithAttachments, { attachments: message.attachments }),
10077
+ message.data && /* @__PURE__ */ jsxRuntime.jsx(DataPayloadView, { payload: message.data }),
10078
+ message.confirmation && /* @__PURE__ */ jsxRuntime.jsx(
10079
+ ConfirmationPanel,
10080
+ {
10081
+ title: message.confirmation.title,
10082
+ summary: message.confirmation.summary,
10083
+ body: message.confirmation.body,
10084
+ markdown: message.confirmation.markdown,
10085
+ actions: message.confirmation.actions,
10086
+ onAction: (actionId) => onConfirmAction?.(message.id, actionId)
10087
+ }
10088
+ )
10089
+ ]
10090
+ }
10091
+ )
7819
10092
  ] }, message.id);
7820
10093
  }) });
7821
10094
  }
@@ -8741,13 +11014,31 @@ function useOpenState(controlled, defaultOpen, onChange) {
8741
11014
  );
8742
11015
  return [open, setOpen];
8743
11016
  }
11017
+ function useIsDesktop() {
11018
+ const read = () => typeof window !== "undefined" && typeof window.matchMedia === "function" ? window.matchMedia("(min-width: 1024px)").matches : true;
11019
+ const [isDesktop, setIsDesktop] = React4.useState(read);
11020
+ React4.useEffect(() => {
11021
+ if (typeof window === "undefined" || typeof window.matchMedia !== "function")
11022
+ return;
11023
+ const mql = window.matchMedia("(min-width: 1024px)");
11024
+ const update = () => setIsDesktop(mql.matches);
11025
+ update();
11026
+ if (mql.addEventListener) {
11027
+ mql.addEventListener("change", update);
11028
+ return () => mql.removeEventListener("change", update);
11029
+ }
11030
+ mql.addListener(update);
11031
+ return () => mql.removeListener(update);
11032
+ }, []);
11033
+ return isDesktop;
11034
+ }
8744
11035
  function AgentWorkspace({
8745
11036
  children,
8746
11037
  leftPanel,
8747
11038
  rightPanel,
8748
11039
  leftPanelWidth = 320,
8749
11040
  rightPanelWidth = 460,
8750
- defaultLeftPanelOpen = true,
11041
+ defaultLeftPanelOpen,
8751
11042
  defaultRightPanelOpen = true,
8752
11043
  leftPanelOpen: leftPanelOpenProp,
8753
11044
  rightPanelOpen: rightPanelOpenProp,
@@ -8757,6 +11048,7 @@ function AgentWorkspace({
8757
11048
  showHeader,
8758
11049
  showConversationHeader,
8759
11050
  headerActions,
11051
+ headerControlsPlacement = "before",
8760
11052
  headerStatus,
8761
11053
  conversation,
8762
11054
  conversationOpen: conversationOpenProp,
@@ -8776,9 +11068,11 @@ function AgentWorkspace({
8776
11068
  const agent = useNativeAgentOptional();
8777
11069
  const hasLeftPanel = leftPanel !== void 0 && leftPanel !== null;
8778
11070
  const hasRightPanel = rightPanel !== void 0 && rightPanel !== null;
11071
+ const isDesktop = useIsDesktop();
11072
+ const resolvedLeftDefault = defaultLeftPanelOpen ?? (leftPanelOpenProp === void 0 ? isDesktop : true);
8779
11073
  const [leftOpen, setLeftOpen] = useOpenState(
8780
11074
  leftPanelOpenProp,
8781
- defaultLeftPanelOpen,
11075
+ resolvedLeftDefault,
8782
11076
  onLeftPanelOpenChange
8783
11077
  );
8784
11078
  const [rightOpen, setRightOpen] = useOpenState(
@@ -8835,6 +11129,39 @@ function AgentWorkspace({
8835
11129
  ) : composer;
8836
11130
  const headerVisible = showHeader ?? showConversationHeader ?? true;
8837
11131
  const statusLine = headerStatus ?? (agent ? agent.error ?? agent.statusLabel : null);
11132
+ const builtInControls = /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
11133
+ agent && /* @__PURE__ */ jsxRuntime.jsx(
11134
+ "button",
11135
+ {
11136
+ type: "button",
11137
+ onClick: () => agent.reset(),
11138
+ "aria-label": "Start a new conversation",
11139
+ title: "New conversation",
11140
+ className: "flex size-8 items-center justify-center rounded-lg text-muted-foreground transition-colors hover:bg-secondary hover:text-foreground",
11141
+ children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.RotateCcw, { className: "size-4" })
11142
+ }
11143
+ ),
11144
+ /* @__PURE__ */ jsxRuntime.jsx(
11145
+ "button",
11146
+ {
11147
+ type: "button",
11148
+ onClick: () => setConversationOpen(!conversationOpen),
11149
+ "aria-label": conversationOpen ? "Hide conversation" : "Show conversation",
11150
+ title: conversationOpen ? "Hide conversation" : "Show conversation",
11151
+ className: "flex size-8 items-center justify-center rounded-lg text-muted-foreground transition-colors hover:bg-secondary hover:text-foreground",
11152
+ children: /* @__PURE__ */ jsxRuntime.jsx(
11153
+ lucideReact.ChevronDown,
11154
+ {
11155
+ className: cn(
11156
+ "size-4 transition-transform duration-200",
11157
+ !conversationOpen && "rotate-180"
11158
+ )
11159
+ }
11160
+ )
11161
+ }
11162
+ ),
11163
+ hasRightPanel && /* @__PURE__ */ jsxRuntime.jsx(AgentWorkspacePanelToggle, { side: "right", className: "hidden md:flex" })
11164
+ ] });
8838
11165
  return /* @__PURE__ */ jsxRuntime.jsx(AgentWorkspaceContext.Provider, { value, children: /* @__PURE__ */ jsxRuntime.jsxs(
8839
11166
  "div",
8840
11167
  {
@@ -8850,7 +11177,7 @@ function AgentWorkspace({
8850
11177
  "data-state": leftOpen ? "open" : "collapsed",
8851
11178
  "aria-hidden": !leftOpen || void 0,
8852
11179
  className: cn(
8853
- "relative hidden h-full shrink-0 overflow-hidden border-r border-border transition-[width] duration-300 ease-in-out lg:block",
11180
+ "relative hidden h-full shrink-0 overflow-hidden border-r border-border transition-[width] duration-300 ease-in-out md:block",
8854
11181
  !leftOpen && "border-r-0",
8855
11182
  leftPanelClassName
8856
11183
  ),
@@ -8859,14 +11186,14 @@ function AgentWorkspace({
8859
11186
  }
8860
11187
  ),
8861
11188
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative flex h-full min-w-0 grow flex-col", children: [
8862
- showPanelToggles && hasLeftPanel && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "absolute left-3 top-3 z-30 hidden lg:block", children: /* @__PURE__ */ jsxRuntime.jsx(
11189
+ showPanelToggles && hasLeftPanel && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "absolute left-3 top-3 z-30 hidden md:block", children: /* @__PURE__ */ jsxRuntime.jsx(
8863
11190
  AgentWorkspacePanelToggle,
8864
11191
  {
8865
11192
  side: "left",
8866
11193
  className: "border border-border/60 bg-background/80 shadow-sm backdrop-blur"
8867
11194
  }
8868
11195
  ) }),
8869
- showPanelToggles && hasRightPanel && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "absolute right-3 top-3 z-30 hidden lg:block", children: /* @__PURE__ */ jsxRuntime.jsx(
11196
+ showPanelToggles && hasRightPanel && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "absolute right-3 top-3 z-30 hidden md:block", children: /* @__PURE__ */ jsxRuntime.jsx(
8870
11197
  AgentWorkspacePanelToggle,
8871
11198
  {
8872
11199
  side: "right",
@@ -8884,7 +11211,7 @@ function AgentWorkspace({
8884
11211
  AgentWorkspacePanelToggle,
8885
11212
  {
8886
11213
  side: "left",
8887
- className: "hidden lg:flex"
11214
+ className: "hidden md:flex"
8888
11215
  }
8889
11216
  ),
8890
11217
  /* @__PURE__ */ jsxRuntime.jsx("span", { className: "flex size-7 shrink-0 items-center justify-center rounded-md bg-primary text-primary-foreground", children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Sparkles, { className: "size-3.5" }) }),
@@ -8893,46 +11220,13 @@ function AgentWorkspace({
8893
11220
  statusLine && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "truncate text-xs text-muted-foreground", children: statusLine })
8894
11221
  ] })
8895
11222
  ] }),
8896
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex shrink-0 items-center gap-1", children: [
11223
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex shrink-0 items-center gap-1", children: headerControlsPlacement === "before" ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
11224
+ builtInControls,
11225
+ headerActions
11226
+ ] }) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
8897
11227
  headerActions,
8898
- agent && /* @__PURE__ */ jsxRuntime.jsx(
8899
- "button",
8900
- {
8901
- type: "button",
8902
- onClick: () => agent.reset(),
8903
- "aria-label": "Start a new conversation",
8904
- title: "New conversation",
8905
- className: "flex size-8 items-center justify-center rounded-lg text-muted-foreground transition-colors hover:bg-secondary hover:text-foreground",
8906
- children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.RotateCcw, { className: "size-4" })
8907
- }
8908
- ),
8909
- /* @__PURE__ */ jsxRuntime.jsx(
8910
- "button",
8911
- {
8912
- type: "button",
8913
- onClick: () => setConversationOpen(!conversationOpen),
8914
- "aria-label": conversationOpen ? "Hide conversation" : "Show conversation",
8915
- title: conversationOpen ? "Hide conversation" : "Show conversation",
8916
- className: "flex size-8 items-center justify-center rounded-lg text-muted-foreground transition-colors hover:bg-secondary hover:text-foreground",
8917
- children: /* @__PURE__ */ jsxRuntime.jsx(
8918
- lucideReact.ChevronDown,
8919
- {
8920
- className: cn(
8921
- "size-4 transition-transform duration-200",
8922
- !conversationOpen && "rotate-180"
8923
- )
8924
- }
8925
- )
8926
- }
8927
- ),
8928
- hasRightPanel && /* @__PURE__ */ jsxRuntime.jsx(
8929
- AgentWorkspacePanelToggle,
8930
- {
8931
- side: "right",
8932
- className: "hidden lg:flex"
8933
- }
8934
- )
8935
- ] })
11228
+ builtInControls
11229
+ ] }) })
8936
11230
  ]
8937
11231
  }
8938
11232
  ),
@@ -8999,7 +11293,7 @@ function AgentWorkspace({
8999
11293
  "data-state": rightOpen ? "open" : "collapsed",
9000
11294
  "aria-hidden": !rightOpen || void 0,
9001
11295
  className: cn(
9002
- "relative hidden h-full shrink-0 overflow-hidden border-l border-border transition-[width] duration-300 ease-in-out lg:block",
11296
+ "relative hidden h-full shrink-0 overflow-hidden border-l border-border transition-[width] duration-300 ease-in-out md:block",
9003
11297
  !rightOpen && "border-l-0",
9004
11298
  rightPanelClassName
9005
11299
  ),
@@ -9114,10 +11408,13 @@ exports.AgentWorkspacePanelToggle = AgentWorkspacePanelToggle;
9114
11408
  exports.AgentWorkspaceSkeleton = AgentWorkspaceSkeleton;
9115
11409
  exports.AllocationBreakdown = AllocationBreakdown;
9116
11410
  exports.AnalyticsDashboard = AnalyticsDashboard;
11411
+ exports.AudioPlayer = AudioPlayer;
9117
11412
  exports.Avatar = Avatar;
9118
11413
  exports.AvatarFallback = AvatarFallback;
9119
11414
  exports.AvatarImage = AvatarImage;
9120
11415
  exports.Badge = Badge;
11416
+ exports.BadgesArtifact = BadgesArtifact;
11417
+ exports.BuiltInQuestions = BuiltInQuestions;
9121
11418
  exports.Button = Button;
9122
11419
  exports.ChartContainer = ChartContainer;
9123
11420
  exports.ChatPanel = ChatPanel;
@@ -9130,6 +11427,7 @@ exports.ConversationAnalytics = ConversationAnalytics;
9130
11427
  exports.ConversationArtifact = ConversationArtifact;
9131
11428
  exports.DataPayloadView = DataPayloadView;
9132
11429
  exports.DataTable = DataTable;
11430
+ exports.DeepResearchProgress = DeepResearchProgress;
9133
11431
  exports.DynamicRenderer = DynamicRenderer;
9134
11432
  exports.EntityCard = EntityCard;
9135
11433
  exports.FileDropZone = FileDropZone;
@@ -9140,7 +11438,10 @@ exports.GuidedLessonFlow = GuidedLessonFlow;
9140
11438
  exports.ImageGenerator = ImageGenerator;
9141
11439
  exports.InlineSuggestionsInput = InlineSuggestionsInput;
9142
11440
  exports.Input = Input;
11441
+ exports.KpiCardWithChart = KpiCardWithChart;
11442
+ exports.KpiCardWithSparklines = KpiCardWithSparklines;
9143
11443
  exports.ListingFeed = ListingFeed;
11444
+ exports.LocationsRevenueCard = LocationsRevenueCard;
9144
11445
  exports.MediaEditorCanvas = MediaEditorCanvas;
9145
11446
  exports.MediaGallery = MediaGallery;
9146
11447
  exports.MessageActions = MessageActions;
@@ -9159,9 +11460,11 @@ exports.NativeAgentProvider = NativeAgentProvider;
9159
11460
  exports.NativeSurface = NativeSurface;
9160
11461
  exports.OnboardingWizard = OnboardingWizard;
9161
11462
  exports.OptionCards = OptionCards;
11463
+ exports.OrderedListArtifact = OrderedListArtifact;
9162
11464
  exports.OverlayModal = OverlayModal;
9163
11465
  exports.PerformanceMetrics = PerformanceMetrics;
9164
11466
  exports.PersonaSelector = PersonaSelector;
11467
+ exports.PieChartArtifact = PieChartArtifact;
9165
11468
  exports.Progress = Progress;
9166
11469
  exports.ProgressTracker = ProgressTracker;
9167
11470
  exports.PromptInput = PromptInput;
@@ -9170,6 +11473,7 @@ exports.QuickReplies = QuickReplies;
9170
11473
  exports.QuizCard = QuizCard;
9171
11474
  exports.RecommendationCards = RecommendationCards;
9172
11475
  exports.ReportView = ReportView;
11476
+ exports.RowBasedDataList = RowBasedDataList;
9173
11477
  exports.ScheduleTimeline = ScheduleTimeline;
9174
11478
  exports.ScrollArea = ScrollArea;
9175
11479
  exports.ScrollBar = ScrollBar;
@@ -9178,8 +11482,11 @@ exports.SentimentDisplay = SentimentDisplay;
9178
11482
  exports.SettingsPanel = SettingsPanel;
9179
11483
  exports.SlotRenderer = SlotRenderer;
9180
11484
  exports.SplitView = SplitView;
11485
+ exports.StackedSparklines = StackedSparklines;
11486
+ exports.StatCardHalfCircle = StatCardHalfCircle;
9181
11487
  exports.StatusBadge = StatusBadge;
9182
11488
  exports.SystemMessage = SystemMessage;
11489
+ exports.TableListArtifact = TableListArtifact;
9183
11490
  exports.TemplateSelector = TemplateSelector;
9184
11491
  exports.Textarea = Textarea;
9185
11492
  exports.Timestamp = Timestamp;
@@ -9187,6 +11494,7 @@ exports.Tooltip = Tooltip4;
9187
11494
  exports.TooltipContent = TooltipContent;
9188
11495
  exports.TooltipProvider = TooltipProvider;
9189
11496
  exports.TooltipTrigger = TooltipTrigger;
11497
+ exports.Tracker = Tracker;
9190
11498
  exports.TypingIndicator = TypingIndicator;
9191
11499
  exports.WritingAssistant = WritingAssistant;
9192
11500
  exports.badgeVariants = badgeVariants;