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