@heroui/agent 0.2.0-beta.1 → 0.2.0-beta.2

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.
@@ -0,0 +1,2696 @@
1
+ "use client";
2
+ import {
3
+ ComponentExportActions,
4
+ TrendChange,
5
+ createComponentSelection,
6
+ formatAxisValue,
7
+ formatNumber,
8
+ paletteChartColor,
9
+ resolveChartColor,
10
+ resolveGaugeBounds
11
+ } from "./chunk-AEUPMIPT.js";
12
+ import {
13
+ Card
14
+ } from "./chunk-TOOT6SZ2.js";
15
+ import {
16
+ mergeClassNames
17
+ } from "./chunk-3FG5NRTX.js";
18
+
19
+ // ../agent-ui/src/components/data-visualization/charts/chart-content.tsx
20
+ import { useId, useMemo as useMemo2, useState as useState2 } from "react";
21
+ import {
22
+ Area,
23
+ Bar,
24
+ CartesianGrid,
25
+ Cell,
26
+ Label,
27
+ Line,
28
+ Pie,
29
+ PolarAngleAxis,
30
+ PolarGrid,
31
+ PolarRadiusAxis,
32
+ Radar,
33
+ RadialBar,
34
+ AreaChart as RechartsAreaChart,
35
+ BarChart as RechartsBarChart,
36
+ ComposedChart as RechartsComposedChart,
37
+ LineChart as RechartsLineChart,
38
+ PieChart as RechartsPieChart,
39
+ RadarChart as RechartsRadarChart,
40
+ RadialBarChart as RechartsRadialBarChart,
41
+ ScatterChart as RechartsScatterChart,
42
+ ReferenceLine,
43
+ ResponsiveContainer,
44
+ Sankey,
45
+ Scatter,
46
+ Tooltip,
47
+ XAxis,
48
+ YAxis,
49
+ ZAxis
50
+ } from "recharts";
51
+
52
+ // ../agent-ui/src/components/data-visualization/segment/segment.tsx
53
+ import { createContext, useCallback, useContext, useMemo, useState } from "react";
54
+ import { jsx, jsxs } from "react/jsx-runtime";
55
+ var SegmentContext = createContext(null);
56
+ function SegmentRoot({
57
+ children,
58
+ className,
59
+ defaultSelectedKey,
60
+ isDisabled = false,
61
+ onSelectionChange,
62
+ selectedKey,
63
+ size = "md",
64
+ variant = "default",
65
+ ...props
66
+ }) {
67
+ const [uncontrolledKey, setUncontrolledKey] = useState(defaultSelectedKey);
68
+ const activeKey = selectedKey ?? uncontrolledKey;
69
+ const select = useCallback(
70
+ (key) => {
71
+ if (isDisabled || key === activeKey) return;
72
+ if (selectedKey === void 0) setUncontrolledKey(key);
73
+ onSelectionChange?.(key);
74
+ },
75
+ [activeKey, isDisabled, onSelectionChange, selectedKey]
76
+ );
77
+ const context = useMemo(
78
+ () => ({ isDisabled, select, selectedKey: activeKey }),
79
+ [activeKey, isDisabled, select]
80
+ );
81
+ return /* @__PURE__ */ jsx(SegmentContext, { value: context, children: /* @__PURE__ */ jsx(
82
+ "div",
83
+ {
84
+ className: mergeClassNames("aui-segment", className),
85
+ "data-disabled": isDisabled || void 0,
86
+ "data-size": size,
87
+ "data-slot": "agent-ui-segment",
88
+ "data-variant": variant,
89
+ role: "group",
90
+ ...props,
91
+ children
92
+ }
93
+ ) });
94
+ }
95
+ function SegmentItem({
96
+ children,
97
+ className,
98
+ disabled,
99
+ id,
100
+ onClick,
101
+ ...props
102
+ }) {
103
+ const context = useContext(SegmentContext);
104
+ if (!context) throw new Error("Segment.Item must be rendered inside Segment.");
105
+ const isDisabled = context.isDisabled || disabled;
106
+ const isSelected = context.selectedKey === id;
107
+ return /* @__PURE__ */ jsxs(
108
+ "button",
109
+ {
110
+ "aria-pressed": isSelected,
111
+ className: mergeClassNames("aui-segment__item", className),
112
+ "data-selected": isSelected,
113
+ "data-slot": "agent-ui-segment-item",
114
+ disabled: isDisabled,
115
+ type: "button",
116
+ onClick: (event) => {
117
+ onClick?.(event);
118
+ if (!event.defaultPrevented) context.select(id);
119
+ },
120
+ ...props,
121
+ children: [
122
+ /* @__PURE__ */ jsx("span", { "aria-hidden": "true", className: "aui-segment__indicator" }),
123
+ /* @__PURE__ */ jsx("span", { className: "aui-segment__label", children })
124
+ ]
125
+ }
126
+ );
127
+ }
128
+ function SegmentSeparator({ className, ...props }) {
129
+ return /* @__PURE__ */ jsx(
130
+ "span",
131
+ {
132
+ "aria-hidden": "true",
133
+ className: mergeClassNames("aui-segment__separator", className),
134
+ "data-slot": "agent-ui-segment-separator",
135
+ ...props
136
+ }
137
+ );
138
+ }
139
+
140
+ // ../agent-ui/src/components/data-visualization/segment/index.ts
141
+ var Segment = Object.assign(SegmentRoot, {
142
+ Item: SegmentItem,
143
+ Root: SegmentRoot,
144
+ Separator: SegmentSeparator
145
+ });
146
+
147
+ // ../agent-ui/src/components/data-visualization/charts/bar-radius.ts
148
+ var FULL_RADIUS = [4, 4, 4, 4];
149
+ var LEFT_RADIUS = [4, 0, 0, 4];
150
+ var NO_RADIUS = [0, 0, 0, 0];
151
+ var RIGHT_RADIUS = [0, 4, 4, 0];
152
+ var TOP_RADIUS = [4, 4, 0, 0];
153
+ function getBarRadius({
154
+ dataKey,
155
+ horizontal,
156
+ stacked,
157
+ visibleStackKeys
158
+ }) {
159
+ if (!stacked) return horizontal ? RIGHT_RADIUS : TOP_RADIUS;
160
+ const index = visibleStackKeys.indexOf(dataKey);
161
+ if (index < 0) return NO_RADIUS;
162
+ if (horizontal && visibleStackKeys.length === 1) return FULL_RADIUS;
163
+ if (horizontal && index === 0) return LEFT_RADIUS;
164
+ if (horizontal && index === visibleStackKeys.length - 1) return RIGHT_RADIUS;
165
+ if (!horizontal && index === visibleStackKeys.length - 1) return TOP_RADIUS;
166
+ return NO_RADIUS;
167
+ }
168
+
169
+ // ../agent-ui/src/components/data-visualization/charts/candlestick-geometry.ts
170
+ var MAX_X_LABELS = 6;
171
+ var MIN_X_LABELS = 2;
172
+ var TARGET_Y_TICKS = 5;
173
+ var X_LABEL_SPACING = 72;
174
+ function candlestickGeometry(points, { height, margins, width }) {
175
+ if (points.length === 0 || !validLayout(width, height, margins)) return null;
176
+ if (!points.every(validPoint)) return null;
177
+ const bounds = {
178
+ bottom: height - margins.bottom,
179
+ height: height - margins.top - margins.bottom,
180
+ left: margins.left,
181
+ right: width - margins.right,
182
+ top: margins.top,
183
+ width: width - margins.left - margins.right
184
+ };
185
+ if (bounds.width < 1 || bounds.height < 1) return null;
186
+ const dataMinimum = Math.min(...points.map((point2) => point2.low));
187
+ const dataMaximum = Math.max(...points.map((point2) => point2.high));
188
+ const expanded = expandFlatDomain(dataMinimum, dataMaximum);
189
+ if (!expanded) return null;
190
+ const tickValues = niceTicks(expanded[0], expanded[1]);
191
+ const yDomain = [tickValues[0], tickValues.at(-1)];
192
+ const yRange = yDomain[1] - yDomain[0];
193
+ if (!Number.isFinite(yRange) || yRange <= 0) return null;
194
+ const y = (value) => bounds.top + (yDomain[1] - value) / yRange * bounds.height;
195
+ const slotWidth = bounds.width / points.length;
196
+ const bodyWidth = Math.max(1, Math.min(14, slotWidth * 0.62));
197
+ const candles = points.map((point2, index) => {
198
+ const x = bounds.left + slotWidth * (index + 0.5);
199
+ const openY = y(point2.open);
200
+ const closeY = y(point2.close);
201
+ const bodyCenter = (openY + closeY) / 2;
202
+ const bodyHeight = Math.max(1, Math.abs(closeY - openY));
203
+ const bodyY = clamp(bodyCenter - bodyHeight / 2, bounds.top, bounds.bottom - bodyHeight);
204
+ return {
205
+ body: { height: bodyHeight, width: bodyWidth, x: x - bodyWidth / 2, y: bodyY },
206
+ direction: point2.close > point2.open ? "up" : point2.close < point2.open ? "down" : "flat",
207
+ index,
208
+ label: point2.label,
209
+ wick: { bottom: y(point2.low), top: y(point2.high), x },
210
+ x
211
+ };
212
+ });
213
+ return {
214
+ bounds,
215
+ candles,
216
+ xLabelIndices: sparseLabelIndices(points.length, bounds.width),
217
+ yDomain,
218
+ yTicks: tickValues.map((value) => ({ value, y: y(value) }))
219
+ };
220
+ }
221
+ function clamp(value, minimum, maximum) {
222
+ return Math.min(Math.max(value, minimum), maximum);
223
+ }
224
+ function cleanNumber(value) {
225
+ const clean = Number(value.toPrecision(12));
226
+ return Object.is(clean, -0) ? 0 : clean;
227
+ }
228
+ function expandFlatDomain(minimum, maximum) {
229
+ if (maximum > minimum) return [minimum, maximum];
230
+ const padding = minimum === 0 ? 1 : Math.abs(minimum) * 0.05;
231
+ const lower = minimum - padding;
232
+ const upper = maximum + padding;
233
+ return Number.isFinite(lower) && Number.isFinite(upper) && upper > lower ? [lower, upper] : null;
234
+ }
235
+ function niceTicks(minimum, maximum) {
236
+ const range = maximum - minimum;
237
+ const rawStep = range / (TARGET_Y_TICKS - 1);
238
+ const exponent = Math.floor(Math.log10(rawStep));
239
+ const candidates = [];
240
+ const seenSteps = /* @__PURE__ */ new Set();
241
+ for (let power = exponent - 2; power <= exponent + 2; power += 1) {
242
+ for (const multiplier of [1, 2, 2.5, 5, 10]) {
243
+ const step = cleanNumber(multiplier * 10 ** power);
244
+ if (!Number.isFinite(step) || step <= 0 || seenSteps.has(step)) continue;
245
+ seenSteps.add(step);
246
+ const start = Math.floor(minimum / step) * step;
247
+ const end = Math.ceil(maximum / step) * step;
248
+ const count = Math.round((end - start) / step) + 1;
249
+ if (count < 4 || count > 6) continue;
250
+ const ticks = Array.from({ length: count }, (_, index) => cleanNumber(start + index * step));
251
+ const padding = Math.max(0, end - start - range) / range;
252
+ const score = Math.abs(count - TARGET_Y_TICKS) * 100 + padding + Math.abs(Math.log10(step / rawStep)) * 0.01;
253
+ candidates.push({ score, ticks });
254
+ }
255
+ }
256
+ candidates.sort((left, right) => left.score - right.score);
257
+ return candidates[0]?.ticks ?? Array.from(
258
+ { length: TARGET_Y_TICKS },
259
+ (_, index) => cleanNumber(minimum + range * index / (TARGET_Y_TICKS - 1))
260
+ );
261
+ }
262
+ function sparseLabelIndices(count, plotWidth) {
263
+ if (count === 1) return [0];
264
+ const target = Math.min(
265
+ count,
266
+ MAX_X_LABELS,
267
+ Math.max(MIN_X_LABELS, Math.floor(plotWidth / X_LABEL_SPACING) + 1)
268
+ );
269
+ if (target === count) return Array.from({ length: count }, (_, index) => index);
270
+ return Array.from(
271
+ { length: target },
272
+ (_, index) => Math.round(index * (count - 1) / (target - 1))
273
+ );
274
+ }
275
+ function validLayout(width, height, margins) {
276
+ return Number.isFinite(width) && width > 0 && Number.isFinite(height) && height > 0 && Object.values(margins).every((margin) => Number.isFinite(margin) && margin >= 0);
277
+ }
278
+ function validPoint(point2) {
279
+ const values = [point2.open, point2.high, point2.low, point2.close];
280
+ return values.every(Number.isFinite) && point2.high >= Math.max(point2.open, point2.close, point2.low) && point2.low <= Math.min(point2.open, point2.close, point2.high);
281
+ }
282
+
283
+ // ../agent-ui/src/components/data-visualization/charts/gauge-geometry.ts
284
+ var MAX_GAUGE_NOTCH_COUNT = 512;
285
+ var DEFAULT_ARC_END_ANGLE = 405;
286
+ var DEFAULT_ARC_START_ANGLE = 135;
287
+ var COORDINATE_SCALE = 1e3;
288
+ var ANGLE_SCALE = 1e6;
289
+ function normalizeGaugeProgress(value, min, max) {
290
+ if (![value, min, max].every(Number.isFinite) || min === max) return 0;
291
+ const progress = (value - min) / (max - min);
292
+ return Math.min(1, Math.max(0, progress));
293
+ }
294
+ function arcGaugeGeometry(options) {
295
+ const {
296
+ centerX,
297
+ centerY,
298
+ count,
299
+ endAngle = DEFAULT_ARC_END_ANGLE,
300
+ height,
301
+ max,
302
+ min,
303
+ notchLength: requestedNotchLength,
304
+ notchWidth: requestedNotchWidth,
305
+ padding = 0,
306
+ radius: requestedRadius,
307
+ startAngle = DEFAULT_ARC_START_ANGLE,
308
+ value,
309
+ width
310
+ } = options;
311
+ if (!validDimensions(width, height) || !validNotchCount(count) || !finiteOptional(centerX, centerY, requestedNotchLength, requestedNotchWidth, requestedRadius) || ![endAngle, padding, startAngle].every(Number.isFinite) || padding < 0 || requestedNotchLength !== void 0 && requestedNotchLength <= 0 || requestedNotchWidth !== void 0 && requestedNotchWidth <= 0 || requestedRadius !== void 0 && requestedRadius <= 0) {
312
+ return null;
313
+ }
314
+ const resolvedCenterX = centerX ?? width / 2;
315
+ const resolvedCenterY = centerY ?? height / 2;
316
+ if (resolvedCenterX < 0 || resolvedCenterX > width || resolvedCenterY < 0 || resolvedCenterY > height) {
317
+ return null;
318
+ }
319
+ const maximumRadius = Math.min(resolvedCenterX, width - resolvedCenterX, resolvedCenterY, height - resolvedCenterY) - padding;
320
+ if (maximumRadius <= 0) return null;
321
+ const radius = Math.min(requestedRadius ?? maximumRadius, maximumRadius);
322
+ const notchLength = Math.min(requestedNotchLength ?? Math.max(2, radius * 0.16), radius);
323
+ const notchWidth = Math.min(requestedNotchWidth ?? Math.max(1, radius * 0.035), radius * 2);
324
+ if (notchLength <= 0 || notchWidth <= 0) return null;
325
+ const center = point(resolvedCenterX, resolvedCenterY);
326
+ const progress = normalizeGaugeProgress(value, min, max);
327
+ const notches = Array.from({ length: count }, (_, index) => {
328
+ const position = count === 1 ? 0.5 : index / (count - 1);
329
+ const threshold = (index + 1) / count;
330
+ const angle = startAngle + (endAngle - startAngle) * position;
331
+ const radians = angle * Math.PI / 180;
332
+ const radialX = Math.cos(radians);
333
+ const radialY = Math.sin(radians);
334
+ const tangentX = -radialY;
335
+ const tangentY = radialX;
336
+ const innerRadius = radius - notchLength;
337
+ const halfWidth = notchWidth / 2;
338
+ const inner = point(
339
+ resolvedCenterX + radialX * innerRadius,
340
+ resolvedCenterY + radialY * innerRadius
341
+ );
342
+ const outer = point(resolvedCenterX + radialX * radius, resolvedCenterY + radialY * radius);
343
+ const innerStart = point(inner.x - tangentX * halfWidth, inner.y - tangentY * halfWidth);
344
+ const outerStart = point(outer.x - tangentX * halfWidth, outer.y - tangentY * halfWidth);
345
+ const outerEnd = point(outer.x + tangentX * halfWidth, outer.y + tangentY * halfWidth);
346
+ const innerEnd = point(inner.x + tangentX * halfWidth, inner.y + tangentY * halfWidth);
347
+ return {
348
+ active: progress >= threshold,
349
+ angle: round(angle, ANGLE_SCALE),
350
+ index,
351
+ inner,
352
+ outer,
353
+ path: `M ${pointText(innerStart)} L ${pointText(outerStart)} L ${pointText(outerEnd)} L ${pointText(innerEnd)} Z`,
354
+ position: round(position, ANGLE_SCALE),
355
+ threshold: round(threshold, ANGLE_SCALE)
356
+ };
357
+ });
358
+ return {
359
+ center,
360
+ notchLength: round(notchLength),
361
+ notchWidth: round(notchWidth),
362
+ notches,
363
+ progress,
364
+ radius: round(radius)
365
+ };
366
+ }
367
+ function linearGaugeGeometry(options) {
368
+ const {
369
+ count,
370
+ gap = 2,
371
+ height,
372
+ inset = 0,
373
+ max,
374
+ min,
375
+ orientation = "horizontal",
376
+ value,
377
+ width
378
+ } = options;
379
+ if (!validDimensions(width, height) || !validNotchCount(count) || ![gap, inset].every(Number.isFinite) || gap < 0 || inset < 0) {
380
+ return null;
381
+ }
382
+ const innerHeight = height - inset * 2;
383
+ const innerWidth = width - inset * 2;
384
+ if (innerHeight <= 0 || innerWidth <= 0) return null;
385
+ const primaryLength = orientation === "horizontal" ? innerWidth : innerHeight;
386
+ const availableLength = primaryLength - gap * (count - 1);
387
+ const notchLength = availableLength / count;
388
+ if (!Number.isFinite(notchLength) || notchLength <= 0) return null;
389
+ const progress = normalizeGaugeProgress(value, min, max);
390
+ const notches = Array.from({ length: count }, (_, index) => {
391
+ const threshold = (index + 1) / count;
392
+ if (orientation === "horizontal") {
393
+ return {
394
+ active: progress >= threshold,
395
+ height: round(innerHeight),
396
+ index,
397
+ threshold: round(threshold, ANGLE_SCALE),
398
+ width: round(notchLength),
399
+ x: round(inset + index * (notchLength + gap)),
400
+ y: round(inset)
401
+ };
402
+ }
403
+ return {
404
+ active: progress >= threshold,
405
+ height: round(notchLength),
406
+ index,
407
+ threshold: round(threshold, ANGLE_SCALE),
408
+ width: round(innerWidth),
409
+ x: round(inset),
410
+ y: round(height - inset - notchLength - index * (notchLength + gap))
411
+ };
412
+ });
413
+ return { notches, orientation, progress };
414
+ }
415
+ function finiteOptional(...values) {
416
+ return values.every((value) => value === void 0 || Number.isFinite(value));
417
+ }
418
+ function point(x, y) {
419
+ return { x: round(x), y: round(y) };
420
+ }
421
+ function pointText(value) {
422
+ return `${value.x} ${value.y}`;
423
+ }
424
+ function round(value, scale = COORDINATE_SCALE) {
425
+ const rounded = Math.round(value * scale) / scale;
426
+ return Object.is(rounded, -0) ? 0 : rounded;
427
+ }
428
+ function validDimensions(width, height) {
429
+ return [width, height].every(Number.isFinite) && width > 0 && height > 0;
430
+ }
431
+ function validNotchCount(count) {
432
+ return Number.isInteger(count) && count >= 1 && count <= MAX_GAUGE_NOTCH_COUNT;
433
+ }
434
+
435
+ // ../agent-ui/src/components/data-visualization/charts/sunburst-geometry.ts
436
+ var FULL_TURN = 360;
437
+ var MIN_SPAN = 1e-6;
438
+ var PATH_PRECISION = 1e6;
439
+ function sunburstGeometry(root, options) {
440
+ if (!root) return [];
441
+ const weightedRoot = rollUp(root, /* @__PURE__ */ new Set());
442
+ const innerRadius = finiteOr(options.innerRadius, 0);
443
+ const outerRadius = finiteOr(options.outerRadius, 0);
444
+ const maxDepth = normalizeMaxDepth(options.maxDepth);
445
+ const startAngle = finiteOr(options.startAngle, -90);
446
+ const requestedEnd = finiteOr(options.endAngle, startAngle + FULL_TURN);
447
+ const span = Math.min(requestedEnd - startAngle, FULL_TURN);
448
+ if (!weightedRoot || weightedRoot.value <= 0 || maxDepth === 0 || innerRadius < 0 || outerRadius <= innerRadius || span <= MIN_SPAN) {
449
+ return [];
450
+ }
451
+ const visibleDepth = deepestVisibleDepth(weightedRoot.children, 1, maxDepth);
452
+ if (visibleDepth === 0) return [];
453
+ const context = {
454
+ arcs: [],
455
+ centerX: finiteOr(options.centerX, 0),
456
+ centerY: finiteOr(options.centerY, 0),
457
+ gapAngle: Math.max(0, finiteOr(options.gapAngle, 0)),
458
+ innerRadius,
459
+ maxDepth,
460
+ ringWidth: (outerRadius - innerRadius) / visibleDepth
461
+ };
462
+ appendLevel(weightedRoot.children, startAngle, startAngle + span, 1, [weightedRoot.id], context);
463
+ return context.arcs;
464
+ }
465
+ function rollUp(node, ancestors) {
466
+ if (ancestors.has(node)) return null;
467
+ ancestors.add(node);
468
+ const sourceChildren = Array.isArray(node.children) ? node.children : [];
469
+ const children = sourceChildren.map((child) => rollUp(child, ancestors)).filter((child) => child !== null);
470
+ ancestors.delete(node);
471
+ const value = sourceChildren.length > 0 ? children.reduce((total, child) => total + child.value, 0) : positiveValue(node.value);
472
+ return { children, id: node.id, label: node.label, value };
473
+ }
474
+ function deepestVisibleDepth(nodes, depth, maxDepth) {
475
+ if (depth > maxDepth) return 0;
476
+ let deepest = 0;
477
+ for (const node of nodes) {
478
+ if (node.value <= 0) continue;
479
+ deepest = Math.max(deepest, depth);
480
+ if (depth < maxDepth) {
481
+ deepest = Math.max(deepest, deepestVisibleDepth(node.children, depth + 1, maxDepth));
482
+ }
483
+ }
484
+ return deepest;
485
+ }
486
+ function appendLevel(nodes, parentStart, parentEnd, depth, parentPath, context) {
487
+ if (depth > context.maxDepth) return;
488
+ const visibleNodes = nodes.filter((node) => node.value > 0);
489
+ const total = visibleNodes.reduce((sum, node) => sum + node.value, 0);
490
+ if (total <= 0) return;
491
+ let cursor = parentStart;
492
+ for (const [index, node] of visibleNodes.entries()) {
493
+ const allocationEnd = index === visibleNodes.length - 1 ? parentEnd : cursor + (parentEnd - parentStart) * node.value / total;
494
+ const [startAngle, endAngle] = insetGap(cursor, allocationEnd, context.gapAngle);
495
+ const innerRadius = context.innerRadius + (depth - 1) * context.ringWidth;
496
+ const outerRadius = innerRadius + context.ringWidth;
497
+ const path = [...parentPath, node.id];
498
+ context.arcs.push({
499
+ d: annularArcPath({
500
+ centerX: context.centerX,
501
+ centerY: context.centerY,
502
+ endAngle,
503
+ innerRadius,
504
+ outerRadius,
505
+ startAngle
506
+ }),
507
+ depth,
508
+ endAngle,
509
+ id: node.id,
510
+ innerRadius,
511
+ label: node.label,
512
+ outerRadius,
513
+ path,
514
+ startAngle,
515
+ value: node.value
516
+ });
517
+ appendLevel(node.children, cursor, allocationEnd, depth + 1, path, context);
518
+ cursor = allocationEnd;
519
+ }
520
+ }
521
+ function insetGap(start, end, requestedGap) {
522
+ const span = end - start;
523
+ const gap = Math.min(requestedGap, Math.max(0, span - MIN_SPAN));
524
+ return [start + gap / 2, end - gap / 2];
525
+ }
526
+ function annularArcPath(options) {
527
+ const span = options.endAngle - options.startAngle;
528
+ if (span >= FULL_TURN - MIN_SPAN) return fullRingPath(options);
529
+ const outerStart = pointAt(options, options.outerRadius, options.startAngle);
530
+ const outerEnd = pointAt(options, options.outerRadius, options.endAngle);
531
+ const largeArc = span > 180 ? 1 : 0;
532
+ const outer = `M ${pointText2(outerStart)} A ${numberText(options.outerRadius)} ${numberText(options.outerRadius)} 0 ${largeArc} 1 ${pointText2(outerEnd)}`;
533
+ if (options.innerRadius <= 0) {
534
+ return `${outer} L ${numberText(options.centerX)} ${numberText(options.centerY)} Z`;
535
+ }
536
+ const innerEnd = pointAt(options, options.innerRadius, options.endAngle);
537
+ const innerStart = pointAt(options, options.innerRadius, options.startAngle);
538
+ return `${outer} L ${pointText2(innerEnd)} A ${numberText(options.innerRadius)} ${numberText(options.innerRadius)} 0 ${largeArc} 0 ${pointText2(innerStart)} Z`;
539
+ }
540
+ function fullRingPath(options) {
541
+ const middleAngle = options.startAngle + 180;
542
+ const outerStart = pointAt(options, options.outerRadius, options.startAngle);
543
+ const outerMiddle = pointAt(options, options.outerRadius, middleAngle);
544
+ const outer = `M ${pointText2(outerStart)} A ${numberText(options.outerRadius)} ${numberText(options.outerRadius)} 0 0 1 ${pointText2(outerMiddle)} A ${numberText(options.outerRadius)} ${numberText(options.outerRadius)} 0 0 1 ${pointText2(outerStart)}`;
545
+ if (options.innerRadius <= 0) return `${outer} Z`;
546
+ const innerStart = pointAt(options, options.innerRadius, options.startAngle);
547
+ const innerMiddle = pointAt(options, options.innerRadius, middleAngle);
548
+ return `${outer} L ${pointText2(innerStart)} A ${numberText(options.innerRadius)} ${numberText(options.innerRadius)} 0 0 0 ${pointText2(innerMiddle)} A ${numberText(options.innerRadius)} ${numberText(options.innerRadius)} 0 0 0 ${pointText2(innerStart)} Z`;
549
+ }
550
+ function pointAt(options, radius, angle) {
551
+ const radians = angle * Math.PI / 180;
552
+ return {
553
+ x: options.centerX + Math.cos(radians) * radius,
554
+ y: options.centerY + Math.sin(radians) * radius
555
+ };
556
+ }
557
+ function pointText2(point2) {
558
+ return `${numberText(point2.x)} ${numberText(point2.y)}`;
559
+ }
560
+ function numberText(value) {
561
+ const rounded = Math.round(value * PATH_PRECISION) / PATH_PRECISION;
562
+ return String(Object.is(rounded, -0) ? 0 : rounded);
563
+ }
564
+ function finiteOr(value, fallback) {
565
+ return typeof value === "number" && Number.isFinite(value) ? value : fallback;
566
+ }
567
+ function positiveValue(value) {
568
+ return typeof value === "number" && Number.isFinite(value) && value > 0 ? value : 0;
569
+ }
570
+ function normalizeMaxDepth(value) {
571
+ if (value === void 0 || value === Number.POSITIVE_INFINITY) return Number.POSITIVE_INFINITY;
572
+ if (!Number.isFinite(value)) return 0;
573
+ return Math.max(0, Math.floor(value));
574
+ }
575
+
576
+ // ../agent-ui/src/components/data-visualization/charts/chart-content.tsx
577
+ import { Fragment, jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
578
+ function nextRovingMarkIndex(key, current, count) {
579
+ if (count < 1) return null;
580
+ if (key === "Home") return 0;
581
+ if (key === "End") return count - 1;
582
+ if (key === "ArrowRight" || key === "ArrowDown") return (current + 1) % count;
583
+ if (key === "ArrowLeft" || key === "ArrowUp") return (current - 1 + count) % count;
584
+ return null;
585
+ }
586
+ function focusSvgMark(event, slot, index) {
587
+ const marks = event.currentTarget.ownerSVGElement?.querySelectorAll(
588
+ `[data-slot="${slot}"]`
589
+ );
590
+ const mark = marks?.item(index);
591
+ if (mark && typeof mark.focus === "function") mark.focus();
592
+ }
593
+ function ChartLegend({
594
+ activeKeys,
595
+ ariaLabel,
596
+ items,
597
+ onToggle
598
+ }) {
599
+ const interactive = onToggle != null && items.length > 1;
600
+ const hasValues = items.some((item) => item.value != null);
601
+ return /* @__PURE__ */ jsx2(
602
+ "div",
603
+ {
604
+ "aria-label": ariaLabel,
605
+ className: mergeClassNames("aui-legend", hasValues ? "aui-legend--values" : void 0),
606
+ "data-slot": "agent-ui-chart-legend",
607
+ role: interactive ? "group" : "list",
608
+ children: items.map((item) => {
609
+ const content = /* @__PURE__ */ jsxs2(Fragment, { children: [
610
+ /* @__PURE__ */ jsx2(
611
+ "span",
612
+ {
613
+ className: "aui-legend__dot",
614
+ "data-slot": "agent-ui-chart-legend-indicator",
615
+ style: { backgroundColor: item.color }
616
+ }
617
+ ),
618
+ /* @__PURE__ */ jsx2("span", { className: "aui-legend__label", children: item.label }),
619
+ item.value != null ? /* @__PURE__ */ jsx2("span", { className: "aui-legend__value", children: item.value }) : null
620
+ ] });
621
+ return interactive ? /* @__PURE__ */ jsx2(
622
+ "button",
623
+ {
624
+ "aria-pressed": activeKeys?.has(item.id) ?? true,
625
+ className: "aui-legend__button",
626
+ "data-slot": "agent-ui-chart-legend-item",
627
+ type: "button",
628
+ onClick: () => onToggle(item.id),
629
+ children: content
630
+ },
631
+ item.id
632
+ ) : /* @__PURE__ */ jsx2(
633
+ "span",
634
+ {
635
+ className: "aui-legend__item",
636
+ "data-slot": "agent-ui-chart-legend-item",
637
+ role: "listitem",
638
+ children: content
639
+ },
640
+ item.id
641
+ );
642
+ })
643
+ }
644
+ );
645
+ }
646
+ function ChartTooltipContent({
647
+ className,
648
+ id,
649
+ items,
650
+ label,
651
+ placement,
652
+ style,
653
+ visuallyHiddenFromAssistiveTechnology
654
+ }) {
655
+ return /* @__PURE__ */ jsxs2(
656
+ "div",
657
+ {
658
+ "aria-hidden": visuallyHiddenFromAssistiveTechnology || void 0,
659
+ className: mergeClassNames("aui-chart-tooltip", className),
660
+ "data-placement": placement,
661
+ "data-slot": "agent-ui-chart-tooltip",
662
+ id,
663
+ role: "tooltip",
664
+ style,
665
+ children: [
666
+ label !== void 0 && label !== "" ? /* @__PURE__ */ jsx2("div", { className: "aui-chart-tooltip__header", "data-slot": "agent-ui-chart-tooltip-header", children: label }) : null,
667
+ items.map((item) => /* @__PURE__ */ jsxs2(
668
+ "div",
669
+ {
670
+ className: "aui-chart-tooltip__item",
671
+ "data-slot": "agent-ui-chart-tooltip-item",
672
+ children: [
673
+ /* @__PURE__ */ jsx2(
674
+ "span",
675
+ {
676
+ className: "aui-chart-tooltip__indicator",
677
+ "data-slot": "agent-ui-chart-tooltip-indicator",
678
+ style: { backgroundColor: item.color }
679
+ }
680
+ ),
681
+ /* @__PURE__ */ jsx2("span", { className: "aui-chart-tooltip__label", "data-slot": "agent-ui-chart-tooltip-label", children: item.label }),
682
+ /* @__PURE__ */ jsx2("span", { className: "aui-chart-tooltip__value", "data-slot": "agent-ui-chart-tooltip-value", children: item.value })
683
+ ]
684
+ },
685
+ item.id
686
+ ))
687
+ ]
688
+ }
689
+ );
690
+ }
691
+ function ComponentTooltip({
692
+ active,
693
+ indicatorColor,
694
+ label,
695
+ payload,
696
+ series
697
+ }) {
698
+ if (!active || !payload?.length) return null;
699
+ return /* @__PURE__ */ jsx2(
700
+ ChartTooltipContent,
701
+ {
702
+ label,
703
+ items: payload.map((entry, index) => {
704
+ const format = series?.find((item) => item.dataKey === entry.dataKey)?.format;
705
+ return {
706
+ color: indicatorColor?.(entry, index) ?? entry.stroke ?? entry.color ?? entry.fill ?? entry.payload?.fill ?? paletteChartColor(index),
707
+ id: String(entry.dataKey ?? entry.name ?? `series-${index}`),
708
+ label: entry.name ?? entry.dataKey,
709
+ value: typeof entry.value === "number" ? formatNumber(entry.value, format) : entry.value
710
+ };
711
+ })
712
+ }
713
+ );
714
+ }
715
+ function SvgChartTooltip({ state }) {
716
+ if (!state) return null;
717
+ return /* @__PURE__ */ jsx2(
718
+ ChartTooltipContent,
719
+ {
720
+ visuallyHiddenFromAssistiveTechnology: true,
721
+ className: "aui-chart-tooltip--floating",
722
+ items: state.items,
723
+ label: state.label,
724
+ placement: state.placement,
725
+ style: { left: state.anchorX, top: state.anchorY }
726
+ }
727
+ );
728
+ }
729
+ function positionSvgChartTooltip(event, point2, content) {
730
+ const svg = event.currentTarget.ownerSVGElement;
731
+ const chart = svg?.parentElement;
732
+ if (!svg || !chart) {
733
+ return { ...content, anchorX: 0, anchorY: 0, placement: "bottom" };
734
+ }
735
+ const chartBounds = chart.getBoundingClientRect();
736
+ let anchorX = chartBounds.width / 2;
737
+ let anchorY = chartBounds.height / 2;
738
+ const matrix = typeof svg.getScreenCTM === "function" ? svg.getScreenCTM() : null;
739
+ if (matrix) {
740
+ anchorX = matrix.a * point2.x + matrix.c * point2.y + matrix.e - chartBounds.left;
741
+ anchorY = matrix.b * point2.x + matrix.d * point2.y + matrix.f - chartBounds.top;
742
+ } else {
743
+ const svgBounds = svg.getBoundingClientRect();
744
+ const viewBox = svg.getAttribute("viewBox")?.trim().split(/[ ,]+/).map(Number);
745
+ if (viewBox?.length === 4 && viewBox.every(Number.isFinite) && viewBox[2] > 0 && viewBox[3] > 0 && svgBounds.width > 0 && svgBounds.height > 0) {
746
+ const scale = Math.min(svgBounds.width / viewBox[2], svgBounds.height / viewBox[3]);
747
+ const renderedWidth = viewBox[2] * scale;
748
+ const renderedHeight = viewBox[3] * scale;
749
+ anchorX = svgBounds.left - chartBounds.left + (svgBounds.width - renderedWidth) / 2 + (point2.x - viewBox[0]) * scale;
750
+ anchorY = svgBounds.top - chartBounds.top + (svgBounds.height - renderedHeight) / 2 + (point2.y - viewBox[1]) * scale;
751
+ }
752
+ }
753
+ const horizontalInset = Math.min(95, chartBounds.width / 2);
754
+ anchorX = Math.min(
755
+ Math.max(anchorX, horizontalInset),
756
+ Math.max(horizontalInset, chartBounds.width - horizontalInset)
757
+ );
758
+ anchorY = Math.min(Math.max(anchorY, 0), chartBounds.height);
759
+ return {
760
+ ...content,
761
+ anchorX,
762
+ anchorY,
763
+ placement: anchorY < 92 ? "bottom" : "top"
764
+ };
765
+ }
766
+ function LiveLineDot({
767
+ color,
768
+ cx,
769
+ cy,
770
+ index,
771
+ lastIndex
772
+ }) {
773
+ if (index !== lastIndex || cx === void 0 || cy === void 0) return null;
774
+ return /* @__PURE__ */ jsxs2("g", { "aria-hidden": "true", "data-slot": "agent-ui-chart-live-point", children: [
775
+ /* @__PURE__ */ jsx2("circle", { className: "aui-chart-live-point__pulse", cx, cy, fill: color, r: "7" }),
776
+ /* @__PURE__ */ jsx2("circle", { className: "aui-chart-live-point__core", cx, cy, fill: color, r: "3.5" })
777
+ ] });
778
+ }
779
+ function datumAtActiveIndex(rows, activeIndex) {
780
+ const index = typeof activeIndex === "number" ? Number(activeIndex) : Number(activeIndex ?? NaN);
781
+ return Number.isInteger(index) ? rows[index] : void 0;
782
+ }
783
+ function CartesianChartComponentContent({
784
+ className,
785
+ component,
786
+ exportFormats,
787
+ onAction,
788
+ onSelect,
789
+ type,
790
+ viewAction
791
+ }) {
792
+ const gradientPrefix = useId().replaceAll(":", "");
793
+ const [hidden, setHidden] = useState2(() => /* @__PURE__ */ new Set());
794
+ const ranges = component.ranges ?? [];
795
+ const fallbackRangeId = ranges.find((range) => range.id === component.defaultRangeId)?.id ?? ranges.at(-1)?.id;
796
+ const [selectedRangeId, setSelectedRangeId] = useState2(fallbackRangeId);
797
+ const activeRange = ranges.find((range) => range.id === selectedRangeId) ?? ranges.find((range) => range.id === fallbackRangeId);
798
+ const seriesKeys = useMemo2(
799
+ () => new Set(component.series.map((item) => item.dataKey)),
800
+ [component.series]
801
+ );
802
+ const activeHidden = useMemo2(() => {
803
+ const reconciled = new Set([...hidden].filter((dataKey) => seriesKeys.has(dataKey)));
804
+ return reconciled.size < component.series.length ? reconciled : /* @__PURE__ */ new Set();
805
+ }, [component.series.length, hidden, seriesKeys]);
806
+ const normalizedData = useMemo2(
807
+ () => component.data.map(
808
+ (datum) => Object.fromEntries(
809
+ Object.entries(datum).map(([key, value]) => [
810
+ key,
811
+ typeof value === "number" || typeof value === "string" ? value : String(value ?? "")
812
+ ])
813
+ )
814
+ ),
815
+ [component.data]
816
+ );
817
+ const rangedData = activeRange?.maxItems ? normalizedData.slice(-activeRange.maxItems) : normalizedData;
818
+ const data = component.kind === "line-chart" && component.mode === "live" ? rangedData.slice(-(component.windowSize ?? 30)) : rangedData;
819
+ const primarySeries = component.series[0];
820
+ const summary = (() => {
821
+ if (!component.showSummary || !primarySeries || data.length === 0) return null;
822
+ const first = Number(data[0]?.[primarySeries.dataKey]);
823
+ const latest = Number(data.at(-1)?.[primarySeries.dataKey]);
824
+ if (!Number.isFinite(first) || !Number.isFinite(latest)) return null;
825
+ return {
826
+ change: first === 0 ? void 0 : (latest - first) / Math.abs(first) * 100,
827
+ // The headline value stays exact even when the axis format is compact.
828
+ format: primarySeries.format && primarySeries.format.style !== "percent" ? { ...primarySeries.format, compact: false } : primarySeries.format,
829
+ label: primarySeries.label,
830
+ value: latest
831
+ };
832
+ })();
833
+ const horizontalBars = type === "bar" && component.kind === "bar-chart" && component.layout === "horizontal";
834
+ const isComposed = component.kind === "composed-chart";
835
+ const visibleBarKeys = component.series.filter((item) => !activeHidden.has(item.dataKey)).map((item) => item.dataKey);
836
+ const visibleComposedStackedBarKeys = isComposed ? component.series.filter((item) => item.type === "bar" && item.stacked && !activeHidden.has(item.dataKey)).map((item) => item.dataKey) : [];
837
+ const leftFormat = isComposed ? component.series.find((item) => item.axis !== "right")?.format : component.series[0]?.format;
838
+ const rightFormat = isComposed ? component.series.find((item) => item.axis === "right")?.format : void 0;
839
+ const hasRightAxis = isComposed && component.series.some((item) => item.axis === "right");
840
+ const formatChartAxis = (value, format = leftFormat) => format ? formatNumber(value, format) : formatAxisValue(value);
841
+ const lineMode = component.kind === "line-chart" ? component.mode ?? "standard" : "standard";
842
+ const lineBaseline = component.kind === "line-chart" ? component.baseline ?? 0 : 0;
843
+ const primaryValues = primarySeries ? data.flatMap((datum) => {
844
+ const value = Number(datum[primarySeries.dataKey]);
845
+ return Number.isFinite(value) ? [value] : [];
846
+ }) : [];
847
+ const lineMinimum = Math.min(lineBaseline, ...primaryValues);
848
+ const lineMaximum = Math.max(lineBaseline, ...primaryValues);
849
+ const profitLossOffset = lineMaximum === lineMinimum ? 50 : (lineMaximum - lineBaseline) / (lineMaximum - lineMinimum) * 100;
850
+ const positiveLineColor = resolveChartColor(
851
+ component.kind === "line-chart" ? component.positiveColor ?? "success" : "success",
852
+ 0
853
+ );
854
+ const negativeLineColor = resolveChartColor(
855
+ component.kind === "line-chart" ? component.negativeColor ?? "danger" : "danger",
856
+ 1
857
+ );
858
+ const liveValue = lineMode === "live" && primarySeries ? Number(data.at(-1)?.[primarySeries.dataKey]) : void 0;
859
+ const activeSeriesKeys = new Set(
860
+ component.series.filter((item) => !activeHidden.has(item.dataKey)).map((item) => item.dataKey)
861
+ );
862
+ const legend = lineMode === "profit-loss" ? /* @__PURE__ */ jsx2(
863
+ ChartLegend,
864
+ {
865
+ ariaLabel: "Chart direction",
866
+ items: [
867
+ {
868
+ color: positiveLineColor,
869
+ id: "positive",
870
+ label: "Above baseline"
871
+ },
872
+ {
873
+ color: negativeLineColor,
874
+ id: "negative",
875
+ label: "Below baseline"
876
+ }
877
+ ]
878
+ }
879
+ ) : /* @__PURE__ */ jsx2(
880
+ ChartLegend,
881
+ {
882
+ activeKeys: activeSeriesKeys,
883
+ ariaLabel: "Chart series",
884
+ items: component.series.map((item, index) => ({
885
+ color: resolveChartColor(item.color, index),
886
+ id: item.dataKey,
887
+ label: item.label
888
+ })),
889
+ onToggle: component.series.length > 1 ? (dataKey) => setHidden(() => {
890
+ const next = new Set(activeHidden);
891
+ const visible = component.series.length - next.size;
892
+ if (next.has(dataKey)) next.delete(dataKey);
893
+ else if (visible > 1) next.add(dataKey);
894
+ return next;
895
+ }) : void 0
896
+ }
897
+ );
898
+ const axes = /* @__PURE__ */ jsxs2(Fragment, { children: [
899
+ /* @__PURE__ */ jsx2(CartesianGrid, { vertical: false }),
900
+ horizontalBars ? /* @__PURE__ */ jsxs2(Fragment, { children: [
901
+ /* @__PURE__ */ jsx2(XAxis, { tickFormatter: (value) => formatChartAxis(value), type: "number" }),
902
+ /* @__PURE__ */ jsx2(YAxis, { dataKey: component.xKey, type: "category", width: 88 })
903
+ ] }) : /* @__PURE__ */ jsxs2(Fragment, { children: [
904
+ /* @__PURE__ */ jsx2(
905
+ XAxis,
906
+ {
907
+ dataKey: component.xKey,
908
+ interval: "preserveStartEnd",
909
+ minTickGap: 28,
910
+ tickMargin: 10
911
+ }
912
+ ),
913
+ /* @__PURE__ */ jsx2(
914
+ YAxis,
915
+ {
916
+ domain: type === "line" ? ["auto", "auto"] : void 0,
917
+ tickFormatter: (value) => formatChartAxis(value),
918
+ width: "auto",
919
+ yAxisId: isComposed ? "left" : void 0
920
+ }
921
+ ),
922
+ hasRightAxis ? /* @__PURE__ */ jsx2(
923
+ YAxis,
924
+ {
925
+ orientation: "right",
926
+ tickFormatter: (value) => formatChartAxis(value, rightFormat),
927
+ width: "auto",
928
+ yAxisId: "right"
929
+ }
930
+ ) : null
931
+ ] }),
932
+ /* @__PURE__ */ jsx2(
933
+ Tooltip,
934
+ {
935
+ isAnimationActive: false,
936
+ content: /* @__PURE__ */ jsx2(
937
+ ComponentTooltip,
938
+ {
939
+ series: component.series,
940
+ indicatorColor: lineMode === "profit-loss" ? (entry) => {
941
+ const value = Number(entry.value);
942
+ return Number.isFinite(value) ? value >= lineBaseline ? positiveLineColor : negativeLineColor : void 0;
943
+ } : void 0
944
+ }
945
+ )
946
+ }
947
+ )
948
+ ] });
949
+ const common = {
950
+ data,
951
+ margin: { bottom: 2, left: 8, right: hasRightAxis ? 8 : 12, top: 8 },
952
+ // Taken from the chart rather than each Bar or Line so one handler covers
953
+ // every cartesian type, and so clicking anywhere in a category selects it
954
+ // instead of only the few pixels the mark occupies.
955
+ ...onSelect && {
956
+ onClick: (state) => {
957
+ const datum = datumAtActiveIndex(data, state.activeIndex);
958
+ if (datum) onSelect(createComponentSelection(component, datum));
959
+ }
960
+ }
961
+ };
962
+ return /* @__PURE__ */ jsxs2(
963
+ Card,
964
+ {
965
+ className,
966
+ description: component.description,
967
+ title: component.title,
968
+ actions: exportFormats?.length || viewAction ? /* @__PURE__ */ jsx2(
969
+ ComponentExportActions,
970
+ {
971
+ component,
972
+ formats: exportFormats,
973
+ viewAction,
974
+ onAction
975
+ }
976
+ ) : null,
977
+ children: [
978
+ summary || ranges.length > 0 || lineMode === "live" ? /* @__PURE__ */ jsxs2("div", { className: "aui-chart-toolbar", "data-slot": "agent-ui-chart-toolbar", children: [
979
+ summary ? /* @__PURE__ */ jsxs2("div", { className: "aui-chart-summary", "data-slot": "agent-ui-chart-summary", children: [
980
+ /* @__PURE__ */ jsx2("span", { className: "aui-chart-summary__label", children: summary.label }),
981
+ /* @__PURE__ */ jsxs2("div", { className: "aui-chart-summary__value-row", children: [
982
+ /* @__PURE__ */ jsx2("strong", { className: "aui-chart-summary__value", children: formatNumber(summary.value, summary.format) }),
983
+ summary.change !== void 0 ? /* @__PURE__ */ jsx2(TrendChange, { value: summary.change }) : null,
984
+ activeRange ? /* @__PURE__ */ jsx2(
985
+ "span",
986
+ {
987
+ className: "aui-chart-summary__range",
988
+ "data-slot": "agent-ui-chart-summary-range",
989
+ children: activeRange.label
990
+ }
991
+ ) : null
992
+ ] })
993
+ ] }) : null,
994
+ lineMode === "live" ? /* @__PURE__ */ jsxs2("span", { className: "aui-chart-live", "data-slot": "agent-ui-chart-live", children: [
995
+ /* @__PURE__ */ jsx2("span", { "aria-hidden": "true", className: "aui-chart-live__dot" }),
996
+ "Live",
997
+ primarySeries && Number.isFinite(liveValue) ? /* @__PURE__ */ jsx2("span", { className: "aui-chart-accessible-value", children: `Latest ${primarySeries.label}: ${formatNumber(liveValue, primarySeries.format)}` }) : null
998
+ ] }) : null,
999
+ ranges.length > 0 ? /* @__PURE__ */ jsx2(
1000
+ Segment,
1001
+ {
1002
+ "aria-label": "Chart range",
1003
+ className: "aui-chart-ranges",
1004
+ selectedKey: activeRange?.id,
1005
+ variant: "text",
1006
+ onSelectionChange: setSelectedRangeId,
1007
+ children: ranges.map((range) => /* @__PURE__ */ jsx2(Segment.Item, { id: range.id, children: range.label }, range.id))
1008
+ }
1009
+ ) : null
1010
+ ] }) : null,
1011
+ /* @__PURE__ */ jsx2(
1012
+ "div",
1013
+ {
1014
+ "aria-label": `${component.title} chart`,
1015
+ "data-slot": "agent-ui-chart",
1016
+ role: "img",
1017
+ className: mergeClassNames(
1018
+ `aui-chart aui-chart--${type}`,
1019
+ lineMode === "live" ? "aui-chart--live" : void 0,
1020
+ lineMode === "profit-loss" ? "aui-chart--profit-loss" : void 0
1021
+ ),
1022
+ children: /* @__PURE__ */ jsx2(ResponsiveContainer, { height: 220, width: "100%", children: type === "composed" && component.kind === "composed-chart" ? /* @__PURE__ */ jsxs2(RechartsComposedChart, { accessibilityLayer: true, ...common, children: [
1023
+ /* @__PURE__ */ jsx2("defs", { children: component.series.map((item, index) => /* @__PURE__ */ jsxs2(
1024
+ "linearGradient",
1025
+ {
1026
+ id: `${gradientPrefix}-${index}`,
1027
+ x1: "0",
1028
+ x2: "0",
1029
+ y1: "0",
1030
+ y2: "1",
1031
+ children: [
1032
+ /* @__PURE__ */ jsx2(
1033
+ "stop",
1034
+ {
1035
+ offset: "0%",
1036
+ stopColor: resolveChartColor(item.color, index),
1037
+ stopOpacity: 0.18
1038
+ }
1039
+ ),
1040
+ /* @__PURE__ */ jsx2(
1041
+ "stop",
1042
+ {
1043
+ offset: "100%",
1044
+ stopColor: resolveChartColor(item.color, index),
1045
+ stopOpacity: 0.02
1046
+ }
1047
+ )
1048
+ ]
1049
+ },
1050
+ item.dataKey
1051
+ )) }),
1052
+ axes,
1053
+ component.series.map((item, index) => {
1054
+ const color = resolveChartColor(item.color, index);
1055
+ const yAxisId = item.axis ?? "left";
1056
+ if (item.type === "area") {
1057
+ return /* @__PURE__ */ jsx2(
1058
+ Area,
1059
+ {
1060
+ dataKey: item.dataKey,
1061
+ dot: false,
1062
+ fill: `url(#${gradientPrefix}-${index})`,
1063
+ hide: activeHidden.has(item.dataKey),
1064
+ isAnimationActive: false,
1065
+ name: item.label,
1066
+ stackId: item.stacked ? "area-stack" : void 0,
1067
+ stroke: color,
1068
+ strokeWidth: 2,
1069
+ type: "monotone",
1070
+ yAxisId
1071
+ },
1072
+ item.dataKey
1073
+ );
1074
+ }
1075
+ if (item.type === "bar") {
1076
+ return /* @__PURE__ */ jsx2(
1077
+ Bar,
1078
+ {
1079
+ dataKey: item.dataKey,
1080
+ fill: color,
1081
+ hide: activeHidden.has(item.dataKey),
1082
+ isAnimationActive: false,
1083
+ name: item.label,
1084
+ stackId: item.stacked ? "bar-stack" : void 0,
1085
+ yAxisId,
1086
+ radius: getBarRadius({
1087
+ dataKey: item.dataKey,
1088
+ horizontal: false,
1089
+ stacked: Boolean(item.stacked),
1090
+ visibleStackKeys: visibleComposedStackedBarKeys
1091
+ })
1092
+ },
1093
+ item.dataKey
1094
+ );
1095
+ }
1096
+ return /* @__PURE__ */ jsx2(
1097
+ Line,
1098
+ {
1099
+ dataKey: item.dataKey,
1100
+ dot: false,
1101
+ hide: activeHidden.has(item.dataKey),
1102
+ isAnimationActive: false,
1103
+ name: item.label,
1104
+ stroke: color,
1105
+ strokeWidth: 2,
1106
+ type: "monotone",
1107
+ yAxisId
1108
+ },
1109
+ item.dataKey
1110
+ );
1111
+ })
1112
+ ] }) : type === "line" ? /* @__PURE__ */ jsxs2(RechartsLineChart, { accessibilityLayer: true, ...common, children: [
1113
+ lineMode === "profit-loss" && component.kind === "line-chart" ? /* @__PURE__ */ jsx2("defs", { children: /* @__PURE__ */ jsxs2("linearGradient", { id: `${gradientPrefix}-profit-loss`, x1: "0", x2: "0", y1: "0", y2: "1", children: [
1114
+ /* @__PURE__ */ jsx2("stop", { offset: `${profitLossOffset}%`, stopColor: positiveLineColor }),
1115
+ /* @__PURE__ */ jsx2("stop", { offset: `${profitLossOffset}%`, stopColor: negativeLineColor })
1116
+ ] }) }) : null,
1117
+ axes,
1118
+ lineMode === "profit-loss" ? /* @__PURE__ */ jsx2(ReferenceLine, { stroke: "var(--border)", strokeDasharray: "4 4", y: lineBaseline }) : null,
1119
+ component.series.map((item, index) => /* @__PURE__ */ jsx2(
1120
+ Line,
1121
+ {
1122
+ dataKey: item.dataKey,
1123
+ hide: activeHidden.has(item.dataKey),
1124
+ isAnimationActive: false,
1125
+ name: item.label,
1126
+ strokeWidth: 2,
1127
+ type: "monotone",
1128
+ dot: lineMode === "live" ? /* @__PURE__ */ jsx2(
1129
+ LiveLineDot,
1130
+ {
1131
+ color: resolveChartColor(item.color, index),
1132
+ lastIndex: data.length - 1
1133
+ }
1134
+ ) : false,
1135
+ stroke: lineMode === "profit-loss" ? `url(#${gradientPrefix}-profit-loss)` : resolveChartColor(item.color, index)
1136
+ },
1137
+ item.dataKey
1138
+ ))
1139
+ ] }) : type === "area" ? /* @__PURE__ */ jsxs2(RechartsAreaChart, { accessibilityLayer: true, ...common, children: [
1140
+ /* @__PURE__ */ jsx2("defs", { children: component.series.map((item, index) => /* @__PURE__ */ jsxs2(
1141
+ "linearGradient",
1142
+ {
1143
+ id: `${gradientPrefix}-${index}`,
1144
+ x1: "0",
1145
+ x2: "0",
1146
+ y1: "0",
1147
+ y2: "1",
1148
+ children: [
1149
+ /* @__PURE__ */ jsx2(
1150
+ "stop",
1151
+ {
1152
+ offset: "0%",
1153
+ stopColor: resolveChartColor(item.color, index),
1154
+ stopOpacity: 0.2
1155
+ }
1156
+ ),
1157
+ /* @__PURE__ */ jsx2(
1158
+ "stop",
1159
+ {
1160
+ offset: "100%",
1161
+ stopColor: resolveChartColor(item.color, index),
1162
+ stopOpacity: 0.01
1163
+ }
1164
+ )
1165
+ ]
1166
+ },
1167
+ item.dataKey
1168
+ )) }),
1169
+ axes,
1170
+ component.series.map((item, index) => /* @__PURE__ */ jsx2(
1171
+ Area,
1172
+ {
1173
+ dataKey: item.dataKey,
1174
+ dot: false,
1175
+ fill: `url(#${gradientPrefix}-${index})`,
1176
+ hide: activeHidden.has(item.dataKey),
1177
+ isAnimationActive: false,
1178
+ name: item.label,
1179
+ stroke: resolveChartColor(item.color, index),
1180
+ strokeWidth: 2,
1181
+ type: "monotone",
1182
+ stackId: component.kind === "area-chart" && component.stacked ? "stack" : void 0
1183
+ },
1184
+ item.dataKey
1185
+ ))
1186
+ ] }) : /* @__PURE__ */ jsxs2(
1187
+ RechartsBarChart,
1188
+ {
1189
+ accessibilityLayer: true,
1190
+ ...common,
1191
+ layout: horizontalBars ? "vertical" : "horizontal",
1192
+ children: [
1193
+ axes,
1194
+ component.series.map((item, index) => /* @__PURE__ */ jsx2(
1195
+ Bar,
1196
+ {
1197
+ dataKey: item.dataKey,
1198
+ fill: resolveChartColor(item.color, index),
1199
+ hide: activeHidden.has(item.dataKey),
1200
+ isAnimationActive: false,
1201
+ name: item.label,
1202
+ radius: getBarRadius({
1203
+ dataKey: item.dataKey,
1204
+ horizontal: horizontalBars,
1205
+ stacked: component.kind === "bar-chart" && Boolean(component.stacked),
1206
+ visibleStackKeys: visibleBarKeys
1207
+ }),
1208
+ stackId: component.kind === "bar-chart" && component.stacked ? "stack" : void 0
1209
+ },
1210
+ item.dataKey
1211
+ ))
1212
+ ]
1213
+ }
1214
+ ) })
1215
+ }
1216
+ ),
1217
+ legend
1218
+ ]
1219
+ }
1220
+ );
1221
+ }
1222
+ function LineChartComponentContent(props) {
1223
+ return /* @__PURE__ */ jsx2(CartesianChartComponentContent, { ...props, type: "line" });
1224
+ }
1225
+ function AreaChartComponentContent(props) {
1226
+ return /* @__PURE__ */ jsx2(CartesianChartComponentContent, { ...props, type: "area" });
1227
+ }
1228
+ function BarChartComponentContent(props) {
1229
+ return /* @__PURE__ */ jsx2(CartesianChartComponentContent, { ...props, type: "bar" });
1230
+ }
1231
+ function ComposedChartComponentContent(props) {
1232
+ return /* @__PURE__ */ jsx2(CartesianChartComponentContent, { ...props, type: "composed" });
1233
+ }
1234
+ function ProportionalChartComponentContent({
1235
+ className,
1236
+ component,
1237
+ exportFormats,
1238
+ onAction,
1239
+ onSelect,
1240
+ variant,
1241
+ viewAction
1242
+ }) {
1243
+ const [hidden, setHidden] = useState2(() => /* @__PURE__ */ new Set());
1244
+ const labels = useMemo2(
1245
+ () => new Set(component.data.map((datum) => String(datum[component.labelKey] ?? ""))),
1246
+ [component.data, component.labelKey]
1247
+ );
1248
+ const activeHidden = useMemo2(() => {
1249
+ const reconciled = new Set([...hidden].filter((label) => labels.has(label)));
1250
+ return reconciled.size < component.data.length ? reconciled : /* @__PURE__ */ new Set();
1251
+ }, [component.data.length, hidden, labels]);
1252
+ const data = component.data.flatMap((datum, index) => {
1253
+ const name = String(datum[component.labelKey] ?? "");
1254
+ return activeHidden.has(name) ? [] : [
1255
+ {
1256
+ color: resolveChartColor(component.colors?.[name], index),
1257
+ name,
1258
+ original: datum,
1259
+ value: Number(datum[component.valueKey] ?? 0)
1260
+ }
1261
+ ];
1262
+ });
1263
+ const total = data.reduce((sum, datum) => sum + datum.value, 0);
1264
+ const activeCategoryKeys = new Set(
1265
+ component.data.map((datum) => String(datum[component.labelKey] ?? "")).filter((label) => !activeHidden.has(label))
1266
+ );
1267
+ const legend = /* @__PURE__ */ jsx2(
1268
+ ChartLegend,
1269
+ {
1270
+ activeKeys: activeCategoryKeys,
1271
+ ariaLabel: "Chart categories",
1272
+ items: component.data.map((datum, index) => {
1273
+ const label = String(datum[component.labelKey] ?? "");
1274
+ return {
1275
+ color: resolveChartColor(component.colors?.[label], index),
1276
+ id: label,
1277
+ label,
1278
+ value: formatNumber(Number(datum[component.valueKey] ?? 0), component.format)
1279
+ };
1280
+ }),
1281
+ onToggle: (label) => setHidden(() => {
1282
+ const next = new Set(activeHidden);
1283
+ if (next.has(label)) next.delete(label);
1284
+ else if (next.size < component.data.length - 1) next.add(label);
1285
+ return next;
1286
+ })
1287
+ }
1288
+ );
1289
+ return /* @__PURE__ */ jsxs2(
1290
+ Card,
1291
+ {
1292
+ className,
1293
+ description: component.description,
1294
+ title: component.title,
1295
+ actions: exportFormats?.length || viewAction ? /* @__PURE__ */ jsx2(
1296
+ ComponentExportActions,
1297
+ {
1298
+ component,
1299
+ formats: exportFormats,
1300
+ viewAction,
1301
+ onAction
1302
+ }
1303
+ ) : null,
1304
+ children: [
1305
+ /* @__PURE__ */ jsx2(
1306
+ "div",
1307
+ {
1308
+ "aria-label": `${component.title} ${variant} chart`,
1309
+ className: "aui-chart aui-chart--pie",
1310
+ "data-slot": "agent-ui-chart",
1311
+ role: "img",
1312
+ children: /* @__PURE__ */ jsx2(ResponsiveContainer, { height: 220, width: "100%", children: /* @__PURE__ */ jsxs2(RechartsPieChart, { accessibilityLayer: true, children: [
1313
+ /* @__PURE__ */ jsxs2(
1314
+ Pie,
1315
+ {
1316
+ cx: "50%",
1317
+ cy: "50%",
1318
+ data,
1319
+ dataKey: "value",
1320
+ innerRadius: variant === "donut" ? 58 : 0,
1321
+ isAnimationActive: false,
1322
+ nameKey: "name",
1323
+ outerRadius: 88,
1324
+ paddingAngle: 0,
1325
+ strokeWidth: 0,
1326
+ onClick: (_, index) => {
1327
+ const datum = data[index]?.original;
1328
+ if (datum) onSelect?.(createComponentSelection(component, datum));
1329
+ },
1330
+ children: [
1331
+ data.map((entry) => /* @__PURE__ */ jsx2(Cell, { fill: entry.color }, entry.name)),
1332
+ variant === "donut" ? /* @__PURE__ */ jsx2(
1333
+ Label,
1334
+ {
1335
+ className: "aui-donut-total",
1336
+ position: "center",
1337
+ value: formatNumber(total, component.format)
1338
+ }
1339
+ ) : null
1340
+ ]
1341
+ }
1342
+ ),
1343
+ /* @__PURE__ */ jsx2(
1344
+ Tooltip,
1345
+ {
1346
+ content: /* @__PURE__ */ jsx2(ComponentTooltip, { series: [{ dataKey: "value", format: component.format }] }),
1347
+ isAnimationActive: false
1348
+ }
1349
+ )
1350
+ ] }) })
1351
+ }
1352
+ ),
1353
+ legend
1354
+ ]
1355
+ }
1356
+ );
1357
+ }
1358
+ function PieChartComponentContent(props) {
1359
+ return /* @__PURE__ */ jsx2(ProportionalChartComponentContent, { ...props, variant: "pie" });
1360
+ }
1361
+ function DonutChartComponentContent(props) {
1362
+ return /* @__PURE__ */ jsx2(ProportionalChartComponentContent, { ...props, variant: "donut" });
1363
+ }
1364
+ function RadarChartComponentContent({
1365
+ className,
1366
+ component,
1367
+ exportFormats,
1368
+ onAction,
1369
+ viewAction
1370
+ }) {
1371
+ const [hidden, setHidden] = useState2(() => /* @__PURE__ */ new Set());
1372
+ const seriesKeys = useMemo2(
1373
+ () => new Set(component.series.map((item) => item.dataKey)),
1374
+ [component.series]
1375
+ );
1376
+ const activeHidden = useMemo2(() => {
1377
+ const reconciled = new Set([...hidden].filter((dataKey) => seriesKeys.has(dataKey)));
1378
+ return reconciled.size < component.series.length ? reconciled : /* @__PURE__ */ new Set();
1379
+ }, [component.series.length, hidden, seriesKeys]);
1380
+ const activeSeriesKeys = new Set(
1381
+ component.series.filter((item) => !activeHidden.has(item.dataKey)).map((item) => item.dataKey)
1382
+ );
1383
+ const legend = /* @__PURE__ */ jsx2(
1384
+ ChartLegend,
1385
+ {
1386
+ activeKeys: activeSeriesKeys,
1387
+ ariaLabel: "Chart series",
1388
+ items: component.series.map((item, index) => ({
1389
+ color: resolveChartColor(item.color, index),
1390
+ id: item.dataKey,
1391
+ label: item.label
1392
+ })),
1393
+ onToggle: component.series.length > 1 ? (dataKey) => setHidden(() => {
1394
+ const next = new Set(activeHidden);
1395
+ const visible = component.series.length - next.size;
1396
+ if (next.has(dataKey)) next.delete(dataKey);
1397
+ else if (visible > 1) next.add(dataKey);
1398
+ return next;
1399
+ }) : void 0
1400
+ }
1401
+ );
1402
+ return /* @__PURE__ */ jsxs2(
1403
+ Card,
1404
+ {
1405
+ className,
1406
+ description: component.description,
1407
+ title: component.title,
1408
+ actions: exportFormats?.length || viewAction ? /* @__PURE__ */ jsx2(
1409
+ ComponentExportActions,
1410
+ {
1411
+ component,
1412
+ formats: exportFormats,
1413
+ viewAction,
1414
+ onAction
1415
+ }
1416
+ ) : null,
1417
+ children: [
1418
+ /* @__PURE__ */ jsx2(
1419
+ "div",
1420
+ {
1421
+ "aria-label": `${component.title} radar chart`,
1422
+ className: "aui-chart aui-chart--radar",
1423
+ "data-slot": "agent-ui-chart",
1424
+ role: "img",
1425
+ children: /* @__PURE__ */ jsx2(ResponsiveContainer, { height: 240, width: "100%", children: /* @__PURE__ */ jsxs2(
1426
+ RechartsRadarChart,
1427
+ {
1428
+ data: component.data,
1429
+ margin: { bottom: 8, left: 20, right: 20, top: 8 },
1430
+ children: [
1431
+ /* @__PURE__ */ jsx2(PolarGrid, {}),
1432
+ /* @__PURE__ */ jsx2(PolarAngleAxis, { dataKey: component.angleKey }),
1433
+ /* @__PURE__ */ jsx2(PolarRadiusAxis, { axisLine: false, tick: false }),
1434
+ component.series.map(
1435
+ (item, index) => activeHidden.has(item.dataKey) ? null : /* @__PURE__ */ jsx2(
1436
+ Radar,
1437
+ {
1438
+ dataKey: item.dataKey,
1439
+ fill: resolveChartColor(item.color, index),
1440
+ fillOpacity: 0.12,
1441
+ isAnimationActive: false,
1442
+ name: item.label,
1443
+ stroke: resolveChartColor(item.color, index),
1444
+ strokeWidth: 2
1445
+ },
1446
+ item.dataKey
1447
+ )
1448
+ ),
1449
+ /* @__PURE__ */ jsx2(
1450
+ Tooltip,
1451
+ {
1452
+ content: /* @__PURE__ */ jsx2(ComponentTooltip, { series: component.series }),
1453
+ isAnimationActive: false
1454
+ }
1455
+ )
1456
+ ]
1457
+ }
1458
+ ) })
1459
+ }
1460
+ ),
1461
+ legend
1462
+ ]
1463
+ }
1464
+ );
1465
+ }
1466
+ function RadialChartComponentContent({
1467
+ className,
1468
+ component,
1469
+ exportFormats,
1470
+ onAction,
1471
+ onSelect,
1472
+ viewAction
1473
+ }) {
1474
+ const data = component.data.map((datum, index) => ({
1475
+ ...datum,
1476
+ fill: resolveChartColor(component.colors?.[String(datum[component.labelKey] ?? "")], index)
1477
+ }));
1478
+ const legend = /* @__PURE__ */ jsx2(
1479
+ ChartLegend,
1480
+ {
1481
+ ariaLabel: "Chart categories",
1482
+ items: component.data.map((datum, index) => {
1483
+ const label = String(datum[component.labelKey] ?? "");
1484
+ return {
1485
+ color: resolveChartColor(component.colors?.[label], index),
1486
+ id: `${label}-${index}`,
1487
+ label,
1488
+ value: formatNumber(Number(datum[component.valueKey] ?? 0), component.format)
1489
+ };
1490
+ })
1491
+ }
1492
+ );
1493
+ return /* @__PURE__ */ jsxs2(
1494
+ Card,
1495
+ {
1496
+ className,
1497
+ description: component.description,
1498
+ title: component.title,
1499
+ actions: exportFormats?.length || viewAction ? /* @__PURE__ */ jsx2(
1500
+ ComponentExportActions,
1501
+ {
1502
+ component,
1503
+ formats: exportFormats,
1504
+ viewAction,
1505
+ onAction
1506
+ }
1507
+ ) : null,
1508
+ children: [
1509
+ /* @__PURE__ */ jsx2(
1510
+ "div",
1511
+ {
1512
+ "aria-label": `${component.title} radial chart`,
1513
+ className: "aui-chart aui-chart--radial",
1514
+ "data-slot": "agent-ui-chart",
1515
+ role: "img",
1516
+ children: /* @__PURE__ */ jsx2(ResponsiveContainer, { height: 230, width: "100%", children: /* @__PURE__ */ jsxs2(
1517
+ RechartsRadialBarChart,
1518
+ {
1519
+ cx: "50%",
1520
+ cy: "50%",
1521
+ data,
1522
+ endAngle: component.endAngle ?? -270,
1523
+ innerRadius: "24%",
1524
+ outerRadius: "92%",
1525
+ startAngle: component.startAngle ?? 90,
1526
+ children: [
1527
+ /* @__PURE__ */ jsx2(PolarAngleAxis, { domain: [0, component.maxValue ?? "auto"], tick: false, type: "number" }),
1528
+ /* @__PURE__ */ jsx2(
1529
+ RadialBar,
1530
+ {
1531
+ background: true,
1532
+ dataKey: component.valueKey,
1533
+ isAnimationActive: false,
1534
+ name: component.labelKey,
1535
+ onClick: (datum) => onSelect?.(createComponentSelection(component, datum))
1536
+ }
1537
+ ),
1538
+ /* @__PURE__ */ jsx2(
1539
+ Tooltip,
1540
+ {
1541
+ isAnimationActive: false,
1542
+ content: /* @__PURE__ */ jsx2(
1543
+ ComponentTooltip,
1544
+ {
1545
+ series: [{ dataKey: component.valueKey, format: component.format }]
1546
+ }
1547
+ )
1548
+ }
1549
+ )
1550
+ ]
1551
+ }
1552
+ ) })
1553
+ }
1554
+ ),
1555
+ legend
1556
+ ]
1557
+ }
1558
+ );
1559
+ }
1560
+ function ScatterChartComponentContent({
1561
+ className,
1562
+ component,
1563
+ exportFormats,
1564
+ onAction,
1565
+ onSelect,
1566
+ viewAction
1567
+ }) {
1568
+ const groups = useMemo2(() => {
1569
+ const grouped = /* @__PURE__ */ new Map();
1570
+ for (const datum of component.data) {
1571
+ const label = component.groupKey ? String(datum[component.groupKey] ?? "Other") : component.title;
1572
+ const entries = grouped.get(label) ?? [];
1573
+ entries.push(datum);
1574
+ grouped.set(label, entries);
1575
+ }
1576
+ return [...grouped.entries()];
1577
+ }, [component.data, component.groupKey, component.title]);
1578
+ const series = [
1579
+ { dataKey: component.xKey, format: component.format },
1580
+ { dataKey: component.yKey, format: component.format },
1581
+ ...component.sizeKey ? [{ dataKey: component.sizeKey, format: component.format }] : []
1582
+ ];
1583
+ const legend = /* @__PURE__ */ jsx2(
1584
+ ChartLegend,
1585
+ {
1586
+ ariaLabel: "Chart groups",
1587
+ items: groups.map(([label], index) => ({
1588
+ color: resolveChartColor(component.colors?.[label], index),
1589
+ id: label,
1590
+ label
1591
+ }))
1592
+ }
1593
+ );
1594
+ return /* @__PURE__ */ jsxs2(
1595
+ Card,
1596
+ {
1597
+ className,
1598
+ description: component.description,
1599
+ title: component.title,
1600
+ actions: exportFormats?.length || viewAction ? /* @__PURE__ */ jsx2(
1601
+ ComponentExportActions,
1602
+ {
1603
+ component,
1604
+ formats: exportFormats,
1605
+ viewAction,
1606
+ onAction
1607
+ }
1608
+ ) : null,
1609
+ children: [
1610
+ /* @__PURE__ */ jsx2(
1611
+ "div",
1612
+ {
1613
+ "aria-label": `${component.title} scatter chart`,
1614
+ className: "aui-chart aui-chart--scatter",
1615
+ "data-slot": "agent-ui-chart",
1616
+ role: "img",
1617
+ children: /* @__PURE__ */ jsx2(ResponsiveContainer, { height: 240, width: "100%", children: /* @__PURE__ */ jsxs2(RechartsScatterChart, { accessibilityLayer: true, margin: { bottom: 8, left: 0, right: 8, top: 8 }, children: [
1618
+ /* @__PURE__ */ jsx2(CartesianGrid, {}),
1619
+ /* @__PURE__ */ jsx2(
1620
+ XAxis,
1621
+ {
1622
+ dataKey: component.xKey,
1623
+ name: component.xKey,
1624
+ tickFormatter: (value) => formatAxisValue(value),
1625
+ type: "number"
1626
+ }
1627
+ ),
1628
+ /* @__PURE__ */ jsx2(
1629
+ YAxis,
1630
+ {
1631
+ dataKey: component.yKey,
1632
+ name: component.yKey,
1633
+ tickFormatter: (value) => formatAxisValue(value),
1634
+ type: "number",
1635
+ width: 42
1636
+ }
1637
+ ),
1638
+ component.sizeKey ? /* @__PURE__ */ jsx2(ZAxis, { dataKey: component.sizeKey, range: [48, 320], type: "number" }) : null,
1639
+ /* @__PURE__ */ jsx2(
1640
+ Tooltip,
1641
+ {
1642
+ content: /* @__PURE__ */ jsx2(ComponentTooltip, { series }),
1643
+ cursor: { strokeDasharray: "4 4" },
1644
+ isAnimationActive: false
1645
+ }
1646
+ ),
1647
+ groups.map(([label, data], index) => /* @__PURE__ */ jsx2(
1648
+ Scatter,
1649
+ {
1650
+ data,
1651
+ fill: resolveChartColor(component.colors?.[label], index),
1652
+ isAnimationActive: false,
1653
+ name: label,
1654
+ onClick: (point2) => {
1655
+ const datum = "payload" in point2 ? point2.payload : point2;
1656
+ onSelect?.(createComponentSelection(component, datum));
1657
+ }
1658
+ },
1659
+ label
1660
+ ))
1661
+ ] }) })
1662
+ }
1663
+ ),
1664
+ legend
1665
+ ]
1666
+ }
1667
+ );
1668
+ }
1669
+ function HeatmapComponentContent({
1670
+ className,
1671
+ component,
1672
+ exportFormats,
1673
+ onAction,
1674
+ onSelect,
1675
+ viewAction
1676
+ }) {
1677
+ const [focusedCell, setFocusedCell] = useState2(0);
1678
+ const xValues = [...new Set(component.data.map((datum) => String(datum[component.xKey] ?? "")))];
1679
+ const yValues = [...new Set(component.data.map((datum) => String(datum[component.yKey] ?? "")))];
1680
+ const values = component.data.map((datum) => Number(datum[component.valueKey] ?? 0));
1681
+ const minimum = Math.min(...values);
1682
+ const maximum = Math.max(...values);
1683
+ const range = maximum - minimum || 1;
1684
+ const width = 420;
1685
+ const left = 84;
1686
+ const top = 28;
1687
+ const right = 8;
1688
+ const bottom = 44;
1689
+ const cellWidth = (width - left - right) / Math.max(1, xValues.length);
1690
+ const cellHeight = Math.max(26, Math.min(44, 230 / Math.max(1, yValues.length)));
1691
+ const height = top + yValues.length * cellHeight + bottom;
1692
+ const dataByCoordinate = new Map(
1693
+ component.data.map((datum) => [
1694
+ `${String(datum[component.xKey] ?? "")}\0${String(datum[component.yKey] ?? "")}`,
1695
+ datum
1696
+ ])
1697
+ );
1698
+ const cellIndexByCoordinate = new Map(
1699
+ [...dataByCoordinate.keys()].map((coordinate, index) => [coordinate, index])
1700
+ );
1701
+ const rovingCell = Math.min(focusedCell, Math.max(0, dataByCoordinate.size - 1));
1702
+ const heatmapColor = resolveChartColor(component.color, 0);
1703
+ const legend = /* @__PURE__ */ jsxs2(
1704
+ "div",
1705
+ {
1706
+ "aria-label": "Heatmap intensity",
1707
+ className: "aui-legend aui-legend--scale",
1708
+ "data-slot": "agent-ui-chart-legend",
1709
+ role: "img",
1710
+ children: [
1711
+ /* @__PURE__ */ jsx2("span", { className: "aui-legend__value", children: formatNumber(minimum, component.format) }),
1712
+ /* @__PURE__ */ jsx2(
1713
+ "span",
1714
+ {
1715
+ className: "aui-legend__scale",
1716
+ style: {
1717
+ background: `linear-gradient(90deg, color-mix(in srgb, ${heatmapColor} 8%, transparent), ${heatmapColor})`
1718
+ }
1719
+ }
1720
+ ),
1721
+ /* @__PURE__ */ jsx2("span", { className: "aui-legend__value", children: formatNumber(maximum, component.format) })
1722
+ ]
1723
+ }
1724
+ );
1725
+ return /* @__PURE__ */ jsxs2(
1726
+ Card,
1727
+ {
1728
+ className,
1729
+ description: component.description,
1730
+ title: component.title,
1731
+ actions: exportFormats?.length || viewAction ? /* @__PURE__ */ jsx2(
1732
+ ComponentExportActions,
1733
+ {
1734
+ component,
1735
+ formats: exportFormats,
1736
+ viewAction,
1737
+ onAction
1738
+ }
1739
+ ) : null,
1740
+ children: [
1741
+ /* @__PURE__ */ jsx2(
1742
+ "div",
1743
+ {
1744
+ "aria-label": `${component.title} heatmap`,
1745
+ className: "aui-chart aui-chart--heatmap",
1746
+ "data-slot": "agent-ui-chart",
1747
+ role: onSelect ? "group" : "img",
1748
+ children: /* @__PURE__ */ jsxs2(
1749
+ "svg",
1750
+ {
1751
+ "aria-hidden": onSelect ? void 0 : true,
1752
+ preserveAspectRatio: "xMidYMid meet",
1753
+ viewBox: `0 0 ${width} ${height}`,
1754
+ children: [
1755
+ xValues.map((label, index) => /* @__PURE__ */ jsx2(
1756
+ "text",
1757
+ {
1758
+ className: "aui-heatmap__axis",
1759
+ textAnchor: "middle",
1760
+ x: left + index * cellWidth + cellWidth / 2,
1761
+ y: height - 14,
1762
+ children: label
1763
+ },
1764
+ label
1765
+ )),
1766
+ yValues.map((label, row) => /* @__PURE__ */ jsxs2("g", { children: [
1767
+ /* @__PURE__ */ jsx2(
1768
+ "text",
1769
+ {
1770
+ className: "aui-heatmap__axis",
1771
+ dominantBaseline: "middle",
1772
+ textAnchor: "end",
1773
+ x: left - 8,
1774
+ y: top + row * cellHeight + cellHeight / 2,
1775
+ children: label
1776
+ }
1777
+ ),
1778
+ xValues.map((xLabel, column) => {
1779
+ const coordinate = `${xLabel}\0${label}`;
1780
+ const datum = dataByCoordinate.get(coordinate);
1781
+ const markIndex = cellIndexByCoordinate.get(coordinate);
1782
+ const value = Number(datum?.[component.valueKey] ?? 0);
1783
+ const opacity = datum ? 0.14 + (value - minimum) / range * 0.76 : 0.04;
1784
+ return /* @__PURE__ */ jsxs2(
1785
+ "g",
1786
+ {
1787
+ className: "aui-heatmap__cell",
1788
+ "data-slot": datum ? "agent-ui-heatmap-cell" : void 0,
1789
+ role: datum && onSelect ? "button" : void 0,
1790
+ tabIndex: datum && onSelect && markIndex !== void 0 ? markIndex === rovingCell ? 0 : -1 : void 0,
1791
+ onClick: () => {
1792
+ if (datum) onSelect?.(createComponentSelection(component, datum));
1793
+ },
1794
+ onFocus: () => {
1795
+ if (markIndex !== void 0) setFocusedCell(markIndex);
1796
+ },
1797
+ onKeyDown: (event) => {
1798
+ if (!datum || !onSelect || markIndex === void 0) return;
1799
+ const nextIndex = nextRovingMarkIndex(
1800
+ event.key,
1801
+ markIndex,
1802
+ dataByCoordinate.size
1803
+ );
1804
+ if (nextIndex !== null) {
1805
+ event.preventDefault();
1806
+ setFocusedCell(nextIndex);
1807
+ focusSvgMark(event, "agent-ui-heatmap-cell", nextIndex);
1808
+ return;
1809
+ }
1810
+ if (event.key !== "Enter" && event.key !== " ") return;
1811
+ event.preventDefault();
1812
+ onSelect(createComponentSelection(component, datum));
1813
+ },
1814
+ children: [
1815
+ /* @__PURE__ */ jsx2(
1816
+ "rect",
1817
+ {
1818
+ fill: heatmapColor,
1819
+ fillOpacity: opacity,
1820
+ height: Math.max(1, cellHeight - 3),
1821
+ rx: 6,
1822
+ width: Math.max(1, cellWidth - 3),
1823
+ x: left + column * cellWidth + 1.5,
1824
+ y: top + row * cellHeight + 1.5
1825
+ }
1826
+ ),
1827
+ datum ? /* @__PURE__ */ jsx2("title", { children: `${label}, ${xLabel}: ${formatNumber(value, component.format)}` }) : null
1828
+ ]
1829
+ },
1830
+ xLabel
1831
+ );
1832
+ })
1833
+ ] }, label))
1834
+ ]
1835
+ }
1836
+ )
1837
+ }
1838
+ ),
1839
+ legend
1840
+ ]
1841
+ }
1842
+ );
1843
+ }
1844
+ function CandlestickChartComponentContent({
1845
+ className,
1846
+ component,
1847
+ exportFormats,
1848
+ onAction,
1849
+ onSelect,
1850
+ viewAction
1851
+ }) {
1852
+ const [focusedCandle, setFocusedCandle] = useState2(0);
1853
+ const [focusedTooltip, setFocusedTooltip] = useState2(null);
1854
+ const [hoveredTooltip, setHoveredTooltip] = useState2(null);
1855
+ const tooltip = hoveredTooltip ?? focusedTooltip;
1856
+ const width = 420;
1857
+ const height = 260;
1858
+ const points = component.data.map((datum) => ({
1859
+ close: Number(datum[component.closeKey]),
1860
+ high: Number(datum[component.highKey]),
1861
+ label: String(datum[component.xKey] ?? ""),
1862
+ low: Number(datum[component.lowKey]),
1863
+ open: Number(datum[component.openKey])
1864
+ }));
1865
+ const geometry = candlestickGeometry(points, {
1866
+ height,
1867
+ margins: { bottom: 34, left: 58, right: 8, top: 10 },
1868
+ width
1869
+ });
1870
+ const upColor = resolveChartColor(component.upColor ?? "success", 0);
1871
+ const downColor = resolveChartColor(component.downColor ?? "danger", 1);
1872
+ const flatColor = resolveChartColor("default", 2);
1873
+ const rovingCandle = Math.min(focusedCandle, component.data.length - 1);
1874
+ return /* @__PURE__ */ jsxs2(
1875
+ Card,
1876
+ {
1877
+ className,
1878
+ description: component.description,
1879
+ title: component.title,
1880
+ actions: exportFormats?.length || viewAction ? /* @__PURE__ */ jsx2(
1881
+ ComponentExportActions,
1882
+ {
1883
+ component,
1884
+ formats: exportFormats,
1885
+ viewAction,
1886
+ onAction
1887
+ }
1888
+ ) : null,
1889
+ children: [
1890
+ /* @__PURE__ */ jsxs2(
1891
+ "div",
1892
+ {
1893
+ "aria-label": `${component.title} candlestick chart`,
1894
+ className: "aui-chart aui-chart--candlestick",
1895
+ "data-slot": "agent-ui-chart",
1896
+ role: "group",
1897
+ children: [
1898
+ /* @__PURE__ */ jsxs2("svg", { preserveAspectRatio: "xMidYMid meet", viewBox: `0 0 ${width} ${height}`, children: [
1899
+ geometry?.yTicks.map((tick) => /* @__PURE__ */ jsxs2("g", { children: [
1900
+ /* @__PURE__ */ jsx2(
1901
+ "line",
1902
+ {
1903
+ className: "aui-chart-grid-line",
1904
+ x1: geometry.bounds.left,
1905
+ x2: geometry.bounds.right,
1906
+ y1: tick.y,
1907
+ y2: tick.y
1908
+ }
1909
+ ),
1910
+ /* @__PURE__ */ jsx2(
1911
+ "text",
1912
+ {
1913
+ className: "aui-chart-axis-label",
1914
+ dominantBaseline: "middle",
1915
+ textAnchor: "end",
1916
+ x: geometry.bounds.left - 9,
1917
+ y: tick.y,
1918
+ children: component.format ? formatNumber(tick.value, component.format) : formatAxisValue(tick.value)
1919
+ }
1920
+ )
1921
+ ] }, tick.value)),
1922
+ geometry?.candles.map((candle) => {
1923
+ const datum = component.data[candle.index];
1924
+ const point2 = points[candle.index];
1925
+ const color = candle.direction === "up" ? upColor : candle.direction === "down" ? downColor : flatColor;
1926
+ const tooltipContent = {
1927
+ items: [
1928
+ {
1929
+ color,
1930
+ id: "open",
1931
+ label: "Open",
1932
+ value: formatNumber(point2.open, component.format)
1933
+ },
1934
+ {
1935
+ color,
1936
+ id: "high",
1937
+ label: "High",
1938
+ value: formatNumber(point2.high, component.format)
1939
+ },
1940
+ { color, id: "low", label: "Low", value: formatNumber(point2.low, component.format) },
1941
+ {
1942
+ color,
1943
+ id: "close",
1944
+ label: "Close",
1945
+ value: formatNumber(point2.close, component.format)
1946
+ }
1947
+ ],
1948
+ label: candle.label
1949
+ };
1950
+ return /* @__PURE__ */ jsxs2(
1951
+ "g",
1952
+ {
1953
+ "aria-label": `${candle.label}: open ${formatNumber(point2.open, component.format)}, high ${formatNumber(point2.high, component.format)}, low ${formatNumber(point2.low, component.format)}, close ${formatNumber(point2.close, component.format)}`,
1954
+ className: "aui-chart-mark",
1955
+ "data-slot": "agent-ui-candlestick",
1956
+ role: datum && onSelect ? "button" : "img",
1957
+ tabIndex: candle.index === rovingCandle ? 0 : -1,
1958
+ onBlur: () => setFocusedTooltip(null),
1959
+ onPointerLeave: () => setHoveredTooltip(null),
1960
+ onClick: datum && onSelect ? () => onSelect(createComponentSelection(component, datum)) : void 0,
1961
+ onFocus: (event) => {
1962
+ setFocusedCandle(candle.index);
1963
+ setFocusedTooltip(
1964
+ positionSvgChartTooltip(
1965
+ event,
1966
+ { x: candle.x, y: Math.min(candle.wick.top, candle.body.y) },
1967
+ tooltipContent
1968
+ )
1969
+ );
1970
+ },
1971
+ onKeyDown: (event) => {
1972
+ const nextIndex = nextRovingMarkIndex(
1973
+ event.key,
1974
+ candle.index,
1975
+ geometry.candles.length
1976
+ );
1977
+ if (nextIndex !== null) {
1978
+ event.preventDefault();
1979
+ setFocusedCandle(nextIndex);
1980
+ focusSvgMark(event, "agent-ui-candlestick", nextIndex);
1981
+ return;
1982
+ }
1983
+ if (!datum || !onSelect) return;
1984
+ if (event.key !== "Enter" && event.key !== " ") return;
1985
+ event.preventDefault();
1986
+ onSelect(createComponentSelection(component, datum));
1987
+ },
1988
+ onPointerEnter: (event) => {
1989
+ setHoveredTooltip(
1990
+ positionSvgChartTooltip(
1991
+ event,
1992
+ { x: candle.x, y: Math.min(candle.wick.top, candle.body.y) },
1993
+ tooltipContent
1994
+ )
1995
+ );
1996
+ },
1997
+ children: [
1998
+ /* @__PURE__ */ jsx2(
1999
+ "line",
2000
+ {
2001
+ stroke: color,
2002
+ strokeWidth: 1.5,
2003
+ x1: candle.wick.x,
2004
+ x2: candle.wick.x,
2005
+ y1: candle.wick.top,
2006
+ y2: candle.wick.bottom
2007
+ }
2008
+ ),
2009
+ /* @__PURE__ */ jsx2(
2010
+ "rect",
2011
+ {
2012
+ fill: color,
2013
+ height: candle.body.height,
2014
+ rx: Math.min(2, candle.body.width / 2),
2015
+ width: candle.body.width,
2016
+ x: candle.body.x,
2017
+ y: candle.body.y
2018
+ }
2019
+ )
2020
+ ]
2021
+ },
2022
+ `${candle.label}-${candle.index}`
2023
+ );
2024
+ }),
2025
+ geometry?.xLabelIndices.map((index) => {
2026
+ const candle = geometry.candles[index];
2027
+ return candle ? /* @__PURE__ */ jsx2(
2028
+ "text",
2029
+ {
2030
+ className: "aui-chart-axis-label",
2031
+ textAnchor: "middle",
2032
+ x: candle.x,
2033
+ y: height - 10,
2034
+ children: candle.label
2035
+ },
2036
+ `${candle.label}-${index}`
2037
+ ) : null;
2038
+ })
2039
+ ] }),
2040
+ /* @__PURE__ */ jsx2(SvgChartTooltip, { state: tooltip })
2041
+ ]
2042
+ }
2043
+ ),
2044
+ /* @__PURE__ */ jsx2(
2045
+ ChartLegend,
2046
+ {
2047
+ ariaLabel: "Price direction",
2048
+ items: [
2049
+ { color: upColor, id: "up", label: "Close above open" },
2050
+ { color: downColor, id: "down", label: "Close below open" }
2051
+ ]
2052
+ }
2053
+ )
2054
+ ]
2055
+ }
2056
+ );
2057
+ }
2058
+ function FunnelChartComponentContent({
2059
+ className,
2060
+ component,
2061
+ exportFormats,
2062
+ onAction,
2063
+ onSelect,
2064
+ viewAction
2065
+ }) {
2066
+ const [focusedStage, setFocusedStage] = useState2(0);
2067
+ const [focusedTooltip, setFocusedTooltip] = useState2(null);
2068
+ const [hoveredTooltip, setHoveredTooltip] = useState2(null);
2069
+ const tooltip = hoveredTooltip ?? focusedTooltip;
2070
+ const width = 640;
2071
+ const height = 250;
2072
+ const plotTop = 12;
2073
+ const plotBottom = 238;
2074
+ const plotLeft = 22;
2075
+ const plotRight = 618;
2076
+ const vertical = (component.orientation ?? "vertical") === "vertical";
2077
+ const values = component.data.map((datum) => Math.max(0, Number(datum[component.valueKey] ?? 0)));
2078
+ const maximum = Math.max(...values, 1);
2079
+ const firstValue = values[0] ?? 0;
2080
+ const rovingStage = Math.min(focusedStage, component.data.length - 1);
2081
+ const stageSize = vertical ? (plotBottom - plotTop) / component.data.length : (plotRight - plotLeft) / component.data.length;
2082
+ const pointsForStage = (index) => {
2083
+ const currentRatio = (values[index] ?? 0) / maximum;
2084
+ const nextRatio = (values[index + 1] ?? values[index] ?? 0) / maximum;
2085
+ if (vertical) {
2086
+ const y1 = plotTop + stageSize * index;
2087
+ const y2 = plotTop + stageSize * (index + 1) - 3;
2088
+ const topWidth = Math.max(8, currentRatio * (plotRight - plotLeft));
2089
+ const bottomWidth = Math.max(8, nextRatio * (plotRight - plotLeft));
2090
+ const center2 = width / 2;
2091
+ return `${center2 - topWidth / 2},${y1} ${center2 + topWidth / 2},${y1} ${center2 + bottomWidth / 2},${y2} ${center2 - bottomWidth / 2},${y2}`;
2092
+ }
2093
+ const x1 = plotLeft + stageSize * index;
2094
+ const x2 = plotLeft + stageSize * (index + 1) - 3;
2095
+ const startHeight = Math.max(8, currentRatio * (plotBottom - plotTop));
2096
+ const endHeight = Math.max(8, nextRatio * (plotBottom - plotTop));
2097
+ const center = height / 2;
2098
+ return `${x1},${center - startHeight / 2} ${x2},${center - endHeight / 2} ${x2},${center + endHeight / 2} ${x1},${center + startHeight / 2}`;
2099
+ };
2100
+ const legend = component.data.map((datum, index) => {
2101
+ const label = String(datum[component.labelKey] ?? "");
2102
+ const value = values[index] ?? 0;
2103
+ const percentage = firstValue > 0 ? value / firstValue : 0;
2104
+ return {
2105
+ color: resolveChartColor(component.colors?.[label], index),
2106
+ id: `${label}-${index}`,
2107
+ label,
2108
+ value: component.showPercentages ? `${formatNumber(value, component.format)} \xB7 ${formatNumber(percentage, { maximumFractionDigits: 1, style: "percent" })}` : formatNumber(value, component.format)
2109
+ };
2110
+ });
2111
+ return /* @__PURE__ */ jsxs2(
2112
+ Card,
2113
+ {
2114
+ className,
2115
+ description: component.description,
2116
+ title: component.title,
2117
+ actions: exportFormats?.length || viewAction ? /* @__PURE__ */ jsx2(
2118
+ ComponentExportActions,
2119
+ {
2120
+ component,
2121
+ formats: exportFormats,
2122
+ viewAction,
2123
+ onAction
2124
+ }
2125
+ ) : null,
2126
+ children: [
2127
+ /* @__PURE__ */ jsxs2(
2128
+ "div",
2129
+ {
2130
+ "aria-label": `${component.title} funnel chart`,
2131
+ "data-slot": "agent-ui-chart",
2132
+ role: "group",
2133
+ className: mergeClassNames(
2134
+ "aui-chart aui-chart--funnel",
2135
+ vertical ? "aui-chart--funnel-vertical" : "aui-chart--funnel-horizontal"
2136
+ ),
2137
+ children: [
2138
+ /* @__PURE__ */ jsx2("svg", { preserveAspectRatio: "xMidYMid meet", viewBox: `0 0 ${width} ${height}`, children: component.data.map((datum, index) => {
2139
+ const label = String(datum[component.labelKey] ?? "");
2140
+ const color = resolveChartColor(component.colors?.[label], index);
2141
+ const value = values[index] ?? 0;
2142
+ const percentage = firstValue > 0 ? value / firstValue : 0;
2143
+ const tooltipContent = {
2144
+ items: [
2145
+ {
2146
+ color,
2147
+ id: "value",
2148
+ label: "Value",
2149
+ value: formatNumber(value, component.format)
2150
+ },
2151
+ ...component.showPercentages ? [
2152
+ {
2153
+ color,
2154
+ id: "conversion",
2155
+ label: "From first stage",
2156
+ value: formatNumber(percentage, {
2157
+ maximumFractionDigits: 1,
2158
+ style: "percent"
2159
+ })
2160
+ }
2161
+ ] : []
2162
+ ],
2163
+ label
2164
+ };
2165
+ const tooltipPoint = vertical ? { x: width / 2, y: plotTop + stageSize * index } : { x: plotLeft + stageSize * (index + 0.5), y: plotTop };
2166
+ return /* @__PURE__ */ jsx2(
2167
+ "g",
2168
+ {
2169
+ "aria-label": `${label}: ${formatNumber(values[index] ?? 0, component.format)}`,
2170
+ className: "aui-chart-mark",
2171
+ "data-slot": "agent-ui-funnel-stage",
2172
+ role: onSelect ? "button" : "img",
2173
+ tabIndex: index === rovingStage ? 0 : -1,
2174
+ onBlur: () => setFocusedTooltip(null),
2175
+ onPointerLeave: () => setHoveredTooltip(null),
2176
+ onClick: onSelect ? () => onSelect(createComponentSelection(component, datum)) : void 0,
2177
+ onFocus: (event) => {
2178
+ setFocusedStage(index);
2179
+ setFocusedTooltip(positionSvgChartTooltip(event, tooltipPoint, tooltipContent));
2180
+ },
2181
+ onKeyDown: (event) => {
2182
+ const nextIndex = nextRovingMarkIndex(event.key, index, component.data.length);
2183
+ if (nextIndex !== null) {
2184
+ event.preventDefault();
2185
+ setFocusedStage(nextIndex);
2186
+ focusSvgMark(event, "agent-ui-funnel-stage", nextIndex);
2187
+ return;
2188
+ }
2189
+ if (!onSelect) return;
2190
+ if (event.key !== "Enter" && event.key !== " ") return;
2191
+ event.preventDefault();
2192
+ onSelect(createComponentSelection(component, datum));
2193
+ },
2194
+ onPointerEnter: (event) => {
2195
+ setHoveredTooltip(positionSvgChartTooltip(event, tooltipPoint, tooltipContent));
2196
+ },
2197
+ children: /* @__PURE__ */ jsx2("polygon", { fill: color, points: pointsForStage(index) })
2198
+ },
2199
+ `${label}-${index}`
2200
+ );
2201
+ }) }),
2202
+ /* @__PURE__ */ jsx2(SvgChartTooltip, { state: tooltip })
2203
+ ]
2204
+ }
2205
+ ),
2206
+ /* @__PURE__ */ jsx2(ChartLegend, { ariaLabel: "Funnel stages", items: legend })
2207
+ ]
2208
+ }
2209
+ );
2210
+ }
2211
+ function GaugeChartComponentContent({
2212
+ className,
2213
+ component,
2214
+ exportFormats,
2215
+ onAction,
2216
+ onSelect,
2217
+ viewAction
2218
+ }) {
2219
+ const [focusedTooltip, setFocusedTooltip] = useState2(null);
2220
+ const [hoveredTooltip, setHoveredTooltip] = useState2(null);
2221
+ const tooltip = hoveredTooltip ?? focusedTooltip;
2222
+ const { maximum, minimum } = resolveGaugeBounds(component);
2223
+ const notches = component.notches ?? 30;
2224
+ const color = resolveChartColor(component.color, 0);
2225
+ const valueLabel = formatNumber(component.value, component.format);
2226
+ const selection = { label: component.label, max: maximum, min: minimum, value: component.value };
2227
+ const orientation = component.orientation ?? "arc";
2228
+ const tooltipContent = {
2229
+ items: [
2230
+ { color, id: "value", label: "Value", value: valueLabel },
2231
+ {
2232
+ color,
2233
+ id: "range",
2234
+ label: "Range",
2235
+ value: `${formatNumber(minimum, component.format)} \u2013 ${formatNumber(maximum, component.format)}`
2236
+ }
2237
+ ],
2238
+ label: component.label
2239
+ };
2240
+ const tooltipPoint = orientation === "arc" ? { x: 240, y: 4 } : { x: 280, y: 34 };
2241
+ const markProps = {
2242
+ "aria-label": `${component.label}: ${valueLabel}`,
2243
+ onBlur: () => setFocusedTooltip(null),
2244
+ onClick: onSelect ? () => onSelect(createComponentSelection(component, selection)) : void 0,
2245
+ onFocus: (event) => {
2246
+ setFocusedTooltip(positionSvgChartTooltip(event, tooltipPoint, tooltipContent));
2247
+ },
2248
+ onKeyDown: (event) => {
2249
+ if (!onSelect || event.key !== "Enter" && event.key !== " ") return;
2250
+ event.preventDefault();
2251
+ onSelect(createComponentSelection(component, selection));
2252
+ },
2253
+ onPointerEnter: (event) => {
2254
+ setHoveredTooltip(positionSvgChartTooltip(event, tooltipPoint, tooltipContent));
2255
+ },
2256
+ onPointerLeave: () => setHoveredTooltip(null),
2257
+ role: onSelect ? "button" : "img",
2258
+ tabIndex: 0
2259
+ };
2260
+ const arc = orientation === "arc" ? arcGaugeGeometry({
2261
+ centerX: 240,
2262
+ centerY: 126,
2263
+ count: notches,
2264
+ height: 240,
2265
+ max: maximum,
2266
+ min: minimum,
2267
+ padding: 12,
2268
+ radius: 104,
2269
+ value: component.value,
2270
+ width: 480
2271
+ }) : null;
2272
+ const linear = orientation === "linear" ? linearGaugeGeometry({
2273
+ count: notches,
2274
+ gap: 3,
2275
+ height: 24,
2276
+ max: maximum,
2277
+ min: minimum,
2278
+ value: component.value,
2279
+ width: 520
2280
+ }) : null;
2281
+ return /* @__PURE__ */ jsx2(
2282
+ Card,
2283
+ {
2284
+ className,
2285
+ description: component.description,
2286
+ title: component.title,
2287
+ actions: exportFormats?.length || viewAction ? /* @__PURE__ */ jsx2(
2288
+ ComponentExportActions,
2289
+ {
2290
+ component,
2291
+ formats: exportFormats,
2292
+ viewAction,
2293
+ onAction
2294
+ }
2295
+ ) : null,
2296
+ children: /* @__PURE__ */ jsxs2(
2297
+ "div",
2298
+ {
2299
+ "aria-label": `${component.title} gauge chart`,
2300
+ className: `aui-chart aui-chart--gauge aui-chart--gauge-${orientation}`,
2301
+ "data-slot": "agent-ui-chart",
2302
+ role: "group",
2303
+ children: [
2304
+ orientation === "arc" ? /* @__PURE__ */ jsx2("svg", { preserveAspectRatio: "xMidYMid meet", viewBox: "0 0 480 240", children: /* @__PURE__ */ jsxs2("g", { className: "aui-chart-mark", "data-slot": "agent-ui-gauge", ...markProps, children: [
2305
+ arc?.notches.map((notch) => /* @__PURE__ */ jsx2(
2306
+ "path",
2307
+ {
2308
+ className: "aui-gauge__notch",
2309
+ d: notch.path,
2310
+ "data-active": notch.active,
2311
+ fill: notch.active ? color : "var(--surface-secondary)"
2312
+ },
2313
+ notch.index
2314
+ )),
2315
+ /* @__PURE__ */ jsx2("text", { className: "aui-gauge__value", textAnchor: "middle", x: "240", y: "126", children: valueLabel }),
2316
+ /* @__PURE__ */ jsx2("text", { className: "aui-gauge__label", textAnchor: "middle", x: "240", y: "150", children: component.label }),
2317
+ /* @__PURE__ */ jsx2("text", { className: "aui-gauge__bound", textAnchor: "end", x: "154", y: "220", children: formatNumber(minimum, component.format) }),
2318
+ /* @__PURE__ */ jsx2("text", { className: "aui-gauge__bound", textAnchor: "start", x: "326", y: "220", children: formatNumber(maximum, component.format) })
2319
+ ] }) }) : /* @__PURE__ */ jsx2("svg", { preserveAspectRatio: "xMidYMid meet", viewBox: "0 0 560 130", children: /* @__PURE__ */ jsxs2("g", { className: "aui-chart-mark", "data-slot": "agent-ui-gauge", ...markProps, children: [
2320
+ /* @__PURE__ */ jsx2("text", { className: "aui-gauge__label", x: "20", y: "24", children: component.label }),
2321
+ /* @__PURE__ */ jsx2("text", { className: "aui-gauge__value", textAnchor: "end", x: "540", y: "24", children: valueLabel }),
2322
+ linear?.notches.map((notch) => /* @__PURE__ */ jsx2(
2323
+ "rect",
2324
+ {
2325
+ className: "aui-gauge__notch",
2326
+ "data-active": notch.active,
2327
+ fill: notch.active ? color : "var(--surface-secondary)",
2328
+ height: notch.height,
2329
+ rx: Math.min(3, notch.width / 2),
2330
+ width: notch.width,
2331
+ x: 20 + notch.x,
2332
+ y: 44 + notch.y
2333
+ },
2334
+ notch.index
2335
+ )),
2336
+ /* @__PURE__ */ jsx2("text", { className: "aui-gauge__bound", x: "20", y: "96", children: formatNumber(minimum, component.format) }),
2337
+ /* @__PURE__ */ jsx2("text", { className: "aui-gauge__bound", textAnchor: "end", x: "540", y: "96", children: formatNumber(maximum, component.format) })
2338
+ ] }) }),
2339
+ /* @__PURE__ */ jsx2(SvgChartTooltip, { state: tooltip })
2340
+ ]
2341
+ }
2342
+ )
2343
+ }
2344
+ );
2345
+ }
2346
+ function sunburstNodeValue(node) {
2347
+ return node.children?.length ? node.children.reduce((sum, child) => sum + sunburstNodeValue(child), 0) : node.value ?? 0;
2348
+ }
2349
+ function SunburstChartComponentContent({
2350
+ className,
2351
+ component,
2352
+ exportFormats,
2353
+ onAction,
2354
+ onSelect,
2355
+ viewAction
2356
+ }) {
2357
+ const [focusedArc, setFocusedArc] = useState2(0);
2358
+ const [focusedTooltip, setFocusedTooltip] = useState2(null);
2359
+ const [hoveredTooltip, setHoveredTooltip] = useState2(null);
2360
+ const tooltip = hoveredTooltip ?? focusedTooltip;
2361
+ const width = 360;
2362
+ const height = 250;
2363
+ const arcs = sunburstGeometry(component.data, {
2364
+ centerX: width / 2,
2365
+ centerY: height / 2,
2366
+ gapAngle: 1.1,
2367
+ innerRadius: 34,
2368
+ maxDepth: 4,
2369
+ outerRadius: 112
2370
+ });
2371
+ const nodeById = /* @__PURE__ */ new Map();
2372
+ const colorById = /* @__PURE__ */ new Map();
2373
+ let colorIndex = 0;
2374
+ const indexNodes = (node, isRoot = false) => {
2375
+ nodeById.set(node.id, node);
2376
+ if (!isRoot) {
2377
+ colorById.set(node.id, resolveChartColor(node.color, colorIndex));
2378
+ colorIndex += 1;
2379
+ }
2380
+ node.children?.forEach((child) => indexNodes(child));
2381
+ };
2382
+ indexNodes(component.data, true);
2383
+ const total = sunburstNodeValue(component.data);
2384
+ const rovingArc = Math.min(focusedArc, Math.max(0, arcs.length - 1));
2385
+ const topLevelItems = (component.data.children ?? []).map((node) => ({
2386
+ color: colorById.get(node.id) ?? resolveChartColor(node.color, 0),
2387
+ id: node.id,
2388
+ label: node.label,
2389
+ value: formatNumber(sunburstNodeValue(node), component.format)
2390
+ }));
2391
+ return /* @__PURE__ */ jsxs2(
2392
+ Card,
2393
+ {
2394
+ className,
2395
+ description: component.description,
2396
+ title: component.title,
2397
+ actions: exportFormats?.length || viewAction ? /* @__PURE__ */ jsx2(
2398
+ ComponentExportActions,
2399
+ {
2400
+ component,
2401
+ formats: exportFormats,
2402
+ viewAction,
2403
+ onAction
2404
+ }
2405
+ ) : null,
2406
+ children: [
2407
+ /* @__PURE__ */ jsxs2(
2408
+ "div",
2409
+ {
2410
+ "aria-label": `${component.title} sunburst chart`,
2411
+ className: "aui-chart aui-chart--sunburst",
2412
+ "data-slot": "agent-ui-chart",
2413
+ role: "group",
2414
+ children: [
2415
+ /* @__PURE__ */ jsxs2("svg", { preserveAspectRatio: "xMidYMid meet", viewBox: `0 0 ${width} ${height}`, children: [
2416
+ arcs.map((arc, index) => {
2417
+ const color = colorById.get(arc.id) ?? resolveChartColor(void 0, arc.depth);
2418
+ const pathLabels = arc.path.map((id) => nodeById.get(id)?.label ?? id);
2419
+ const middleAngle = (arc.startAngle + arc.endAngle) / 2 * (Math.PI / 180);
2420
+ const middleRadius = (arc.innerRadius + arc.outerRadius) / 2;
2421
+ const tooltipContent = {
2422
+ items: [
2423
+ {
2424
+ color,
2425
+ id: "value",
2426
+ label: "Value",
2427
+ value: formatNumber(arc.value, component.format)
2428
+ },
2429
+ {
2430
+ color,
2431
+ id: "share",
2432
+ label: "Share of total",
2433
+ value: formatNumber(total > 0 ? arc.value / total : 0, {
2434
+ maximumFractionDigits: 1,
2435
+ style: "percent"
2436
+ })
2437
+ }
2438
+ ],
2439
+ label: pathLabels.join(" / ")
2440
+ };
2441
+ const tooltipPoint = {
2442
+ x: width / 2 + Math.cos(middleAngle) * middleRadius,
2443
+ y: height / 2 + Math.sin(middleAngle) * middleRadius
2444
+ };
2445
+ const selectableDatum = {
2446
+ depth: arc.depth,
2447
+ id: arc.id,
2448
+ label: arc.label,
2449
+ path: pathLabels.join(" / "),
2450
+ value: arc.value
2451
+ };
2452
+ return /* @__PURE__ */ jsx2(
2453
+ "g",
2454
+ {
2455
+ "aria-label": `${pathLabels.join(", ")}: ${formatNumber(arc.value, component.format)}`,
2456
+ className: "aui-chart-mark",
2457
+ "data-slot": "agent-ui-sunburst-segment",
2458
+ role: onSelect ? "button" : "img",
2459
+ tabIndex: index === rovingArc ? 0 : -1,
2460
+ onBlur: () => setFocusedTooltip(null),
2461
+ onPointerLeave: () => setHoveredTooltip(null),
2462
+ onClick: onSelect ? () => onSelect(createComponentSelection(component, selectableDatum)) : void 0,
2463
+ onFocus: (event) => {
2464
+ setFocusedArc(index);
2465
+ setFocusedTooltip(positionSvgChartTooltip(event, tooltipPoint, tooltipContent));
2466
+ },
2467
+ onKeyDown: (event) => {
2468
+ const nextIndex = nextRovingMarkIndex(event.key, index, arcs.length);
2469
+ if (nextIndex !== null) {
2470
+ event.preventDefault();
2471
+ setFocusedArc(nextIndex);
2472
+ focusSvgMark(event, "agent-ui-sunburst-segment", nextIndex);
2473
+ return;
2474
+ }
2475
+ if (!onSelect) return;
2476
+ if (event.key !== "Enter" && event.key !== " ") return;
2477
+ event.preventDefault();
2478
+ onSelect(createComponentSelection(component, selectableDatum));
2479
+ },
2480
+ onPointerEnter: (event) => {
2481
+ setHoveredTooltip(positionSvgChartTooltip(event, tooltipPoint, tooltipContent));
2482
+ },
2483
+ children: /* @__PURE__ */ jsx2("path", { className: "aui-sunburst__arc", d: arc.d, fill: color })
2484
+ },
2485
+ arc.id
2486
+ );
2487
+ }),
2488
+ /* @__PURE__ */ jsx2(
2489
+ "text",
2490
+ {
2491
+ className: "aui-sunburst__total",
2492
+ textAnchor: "middle",
2493
+ x: width / 2,
2494
+ y: height / 2 - 2,
2495
+ children: formatNumber(total, component.format)
2496
+ }
2497
+ ),
2498
+ /* @__PURE__ */ jsx2(
2499
+ "text",
2500
+ {
2501
+ className: "aui-sunburst__root",
2502
+ textAnchor: "middle",
2503
+ x: width / 2,
2504
+ y: height / 2 + 16,
2505
+ children: component.data.label
2506
+ }
2507
+ )
2508
+ ] }),
2509
+ /* @__PURE__ */ jsx2(SvgChartTooltip, { state: tooltip })
2510
+ ]
2511
+ }
2512
+ ),
2513
+ topLevelItems.length ? /* @__PURE__ */ jsx2(ChartLegend, { ariaLabel: "Top-level categories", items: topLevelItems }) : null
2514
+ ]
2515
+ }
2516
+ );
2517
+ }
2518
+ function SankeyNode({ height, index, payload, width, x, y }) {
2519
+ return /* @__PURE__ */ jsxs2("g", { children: [
2520
+ /* @__PURE__ */ jsx2(
2521
+ "rect",
2522
+ {
2523
+ className: "aui-sankey__node",
2524
+ fill: paletteChartColor(index),
2525
+ height,
2526
+ rx: 4,
2527
+ width,
2528
+ x,
2529
+ y
2530
+ }
2531
+ ),
2532
+ /* @__PURE__ */ jsx2(
2533
+ "text",
2534
+ {
2535
+ className: "aui-sankey__label",
2536
+ dominantBaseline: "middle",
2537
+ x: x + width + 7,
2538
+ y: y + height / 2,
2539
+ children: payload.name
2540
+ }
2541
+ )
2542
+ ] });
2543
+ }
2544
+ function SankeyLink({
2545
+ chartId,
2546
+ index,
2547
+ linkWidth,
2548
+ payload,
2549
+ sourceControlX,
2550
+ sourceX,
2551
+ sourceY,
2552
+ targetControlX,
2553
+ targetX,
2554
+ targetY
2555
+ }) {
2556
+ const half = Math.max(1, linkWidth) / 2;
2557
+ const path = `M${sourceX},${sourceY - half} C${sourceControlX},${sourceY - half} ${targetControlX},${targetY - half} ${targetX},${targetY - half} L${targetX},${targetY + half} C${targetControlX},${targetY + half} ${sourceControlX},${sourceY + half} ${sourceX},${sourceY + half} Z`;
2558
+ return /* @__PURE__ */ jsxs2("g", { children: [
2559
+ /* @__PURE__ */ jsxs2("defs", { children: [
2560
+ /* @__PURE__ */ jsxs2("linearGradient", { id: `${chartId}-link-${index}`, x1: "0", x2: "1", children: [
2561
+ /* @__PURE__ */ jsx2("stop", { offset: "0%", stopColor: "var(--chart-3, var(--accent))", stopOpacity: 0.2 }),
2562
+ /* @__PURE__ */ jsx2(
2563
+ "stop",
2564
+ {
2565
+ offset: "50%",
2566
+ stopColor: "var(--chart-4, oklch(from var(--accent) calc(l + 0.12) c h))",
2567
+ stopOpacity: 0.55
2568
+ }
2569
+ ),
2570
+ /* @__PURE__ */ jsx2(
2571
+ "stop",
2572
+ {
2573
+ offset: "100%",
2574
+ stopColor: "var(--chart-1, oklch(from var(--accent) calc(l - 0.24) c h))",
2575
+ stopOpacity: 0.25
2576
+ }
2577
+ )
2578
+ ] }),
2579
+ /* @__PURE__ */ jsx2("filter", { height: "180%", id: `${chartId}-glow-${index}`, width: "180%", x: "-40%", y: "-40%", children: /* @__PURE__ */ jsx2("feGaussianBlur", { stdDeviation: "2.5" }) })
2580
+ ] }),
2581
+ /* @__PURE__ */ jsx2(
2582
+ "path",
2583
+ {
2584
+ d: path,
2585
+ fill: `url(#${chartId}-link-${index})`,
2586
+ filter: `url(#${chartId}-glow-${index})`,
2587
+ opacity: 0.35
2588
+ }
2589
+ ),
2590
+ /* @__PURE__ */ jsx2("path", { d: path, fill: `url(#${chartId}-link-${index})`, opacity: 0.8 }),
2591
+ /* @__PURE__ */ jsx2("title", { children: `${payload.source.name} \u2192 ${payload.target.name}: ${payload.value}` })
2592
+ ] });
2593
+ }
2594
+ function SankeyChartComponentContent({
2595
+ className,
2596
+ component,
2597
+ exportFormats,
2598
+ onAction,
2599
+ onSelect,
2600
+ viewAction
2601
+ }) {
2602
+ const chartId = useId().replaceAll(":", "");
2603
+ const nodeIndex = new Map(component.nodes.map((node, index) => [node.id, index]));
2604
+ const data = {
2605
+ links: component.links.flatMap((link) => {
2606
+ const source = nodeIndex.get(link.source);
2607
+ const target = nodeIndex.get(link.target);
2608
+ return source === void 0 || target === void 0 ? [] : [{ source, target, value: link.value }];
2609
+ }),
2610
+ nodes: component.nodes.map((node) => ({ name: node.label }))
2611
+ };
2612
+ return /* @__PURE__ */ jsxs2(
2613
+ Card,
2614
+ {
2615
+ className,
2616
+ description: component.description,
2617
+ title: component.title,
2618
+ actions: exportFormats?.length || viewAction ? /* @__PURE__ */ jsx2(
2619
+ ComponentExportActions,
2620
+ {
2621
+ component,
2622
+ formats: exportFormats,
2623
+ viewAction,
2624
+ onAction
2625
+ }
2626
+ ) : null,
2627
+ children: [
2628
+ /* @__PURE__ */ jsx2(
2629
+ "div",
2630
+ {
2631
+ "aria-label": `${component.title} sankey chart`,
2632
+ className: "aui-chart aui-chart--sankey aui-sankey",
2633
+ "data-slot": "agent-ui-chart",
2634
+ role: "img",
2635
+ children: /* @__PURE__ */ jsx2(ResponsiveContainer, { height: 260, width: "100%", children: /* @__PURE__ */ jsx2(
2636
+ Sankey,
2637
+ {
2638
+ data,
2639
+ link: (props) => /* @__PURE__ */ jsx2(SankeyLink, { ...props, chartId }),
2640
+ linkCurvature: 0.55,
2641
+ margin: { bottom: 12, left: 8, right: 92, top: 12 },
2642
+ node: (props) => /* @__PURE__ */ jsx2(SankeyNode, { ...props }),
2643
+ nodePadding: 18,
2644
+ nodeWidth: 12,
2645
+ onClick: (item, type) => onSelect?.(
2646
+ createComponentSelection(component, {
2647
+ element: type,
2648
+ index: item.index,
2649
+ value: "payload" in item ? item.payload.value : void 0
2650
+ })
2651
+ ),
2652
+ children: /* @__PURE__ */ jsx2(
2653
+ Tooltip,
2654
+ {
2655
+ content: /* @__PURE__ */ jsx2(ComponentTooltip, { series: [{ dataKey: "value", format: component.format }] }),
2656
+ isAnimationActive: false
2657
+ }
2658
+ )
2659
+ }
2660
+ ) })
2661
+ }
2662
+ ),
2663
+ /* @__PURE__ */ jsx2(
2664
+ "div",
2665
+ {
2666
+ "aria-label": "Chart encoding",
2667
+ className: "aui-legend",
2668
+ "data-slot": "agent-ui-chart-legend",
2669
+ role: "list",
2670
+ children: /* @__PURE__ */ jsxs2("span", { className: "aui-legend__item", "data-slot": "agent-ui-chart-legend-item", role: "listitem", children: [
2671
+ /* @__PURE__ */ jsx2("span", { className: "aui-legend__flow" }),
2672
+ /* @__PURE__ */ jsx2("span", { className: "aui-legend__label", children: "Flow volume" })
2673
+ ] })
2674
+ }
2675
+ )
2676
+ ]
2677
+ }
2678
+ );
2679
+ }
2680
+ export {
2681
+ AreaChartComponentContent,
2682
+ BarChartComponentContent,
2683
+ CandlestickChartComponentContent,
2684
+ ComposedChartComponentContent,
2685
+ DonutChartComponentContent,
2686
+ FunnelChartComponentContent,
2687
+ GaugeChartComponentContent,
2688
+ HeatmapComponentContent,
2689
+ LineChartComponentContent,
2690
+ PieChartComponentContent,
2691
+ RadarChartComponentContent,
2692
+ RadialChartComponentContent,
2693
+ SankeyChartComponentContent,
2694
+ ScatterChartComponentContent,
2695
+ SunburstChartComponentContent
2696
+ };