@robosystems/report-components 0.2.9 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -1,8 +1,109 @@
1
- import { formatDate, BLOCK_TITLES, numericKindOf, humanizeDuration, formatValue, formatPeriod, isExternalFactUrl, BLOCK_ORDER, humanize, qname, currencySymbolFor } from './chunk-DV6XPUSY.js';
2
- export { BLOCK_ORDER, BLOCK_TITLES, NS, currencySymbolFor, cypherAdapter, fetchSecReportShell, fetchSecSection, formatDate, formatMoney, formatPeriod, formatValue, humanize, humanizeDuration, isExternalFactUrl, jsonldFileAdapter, mergeSecSections, numericKindOf, parseJsonld, parseStore, parseStructureDefinition, parseStructureName, qname, stripRoleSuffix } from './chunk-DV6XPUSY.js';
3
- import { useState, useEffect, useMemo, useRef } from 'react';
1
+ import { formatMoney, formatDate, BLOCK_TITLES, numericKindOf, humanizeDuration, formatValue, formatPeriod, isExternalFactUrl, BLOCK_ORDER, humanize, qname, currencySymbolFor } from './chunk-ZTYXTMAT.js';
2
+ export { BLOCK_ORDER, BLOCK_TITLES, NS, currencySymbolFor, cypherAdapter, fetchSecReportShell, fetchSecSection, formatDate, formatMoney, formatPeriod, formatValue, humanize, humanizeDuration, isExternalFactUrl, jsonldFileAdapter, mergeSecSections, numericKindOf, parseJsonld, parseStore, parseStructureDefinition, parseStructureName, qname, stripRoleSuffix } from './chunk-ZTYXTMAT.js';
3
+ import { marked } from 'marked';
4
+ import { useState, useEffect, useMemo, useRef, useId } from 'react';
4
5
  import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
5
6
 
7
+ // src/chart/format.ts
8
+ var DASH = "\u2014";
9
+ function formatMetricValue(itemType, value) {
10
+ if (value === null || value === void 0 || Number.isNaN(value)) return DASH;
11
+ switch (itemType) {
12
+ case "monetary":
13
+ return formatMoney(value);
14
+ case "percent":
15
+ return `${(value * 100).toLocaleString("en-US", { maximumFractionDigits: 2 })}%`;
16
+ case "multiple":
17
+ return `${value.toLocaleString("en-US", { minimumFractionDigits: 2, maximumFractionDigits: 2 })}\xD7`;
18
+ case "days":
19
+ return value.toLocaleString("en-US", { maximumFractionDigits: 0 });
20
+ case "ratio":
21
+ return value.toLocaleString("en-US", {
22
+ minimumFractionDigits: 2,
23
+ maximumFractionDigits: 2
24
+ });
25
+ default:
26
+ return value.toLocaleString("en-US", { maximumFractionDigits: 4 });
27
+ }
28
+ }
29
+ function formatMetricCompact(itemType, value) {
30
+ if (value === null || value === void 0 || Number.isNaN(value)) return "";
31
+ if (itemType === "monetary") {
32
+ const abs = Math.abs(value);
33
+ const sign = value < 0 ? "-" : "";
34
+ if (abs >= 1e9) return `${sign}$${(abs / 1e9).toFixed(abs >= 1e10 ? 0 : 1)}B`;
35
+ if (abs >= 1e6) return `${sign}$${(abs / 1e6).toFixed(abs >= 1e7 ? 0 : 1)}M`;
36
+ if (abs >= 1e3) return `${sign}$${(abs / 1e3).toFixed(abs >= 1e4 ? 0 : 1)}K`;
37
+ return `${sign}$${abs.toFixed(0)}`;
38
+ }
39
+ if (itemType === "percent") {
40
+ return `${(value * 100).toLocaleString("en-US", { maximumFractionDigits: 1 })}%`;
41
+ }
42
+ if (itemType === "multiple") {
43
+ return `${value.toLocaleString("en-US", { maximumFractionDigits: 1 })}\xD7`;
44
+ }
45
+ if (itemType === "days") {
46
+ return value.toLocaleString("en-US", { maximumFractionDigits: 0 });
47
+ }
48
+ return value.toLocaleString("en-US", { maximumFractionDigits: 2 });
49
+ }
50
+
51
+ // src/chart/join.ts
52
+ function joinChartSeries(panel, rendering) {
53
+ const rowByElement = new Map(rendering.rows.map((r) => [r.elementId, r]));
54
+ const periods = rendering.periods;
55
+ const out = [];
56
+ for (const series of panel.series) {
57
+ const row = rowByElement.get(series.elementId);
58
+ if (!row) continue;
59
+ const points = periods.map((p, i) => ({
60
+ x: p.end,
61
+ y: i < row.values.length ? row.values[i] : null
62
+ }));
63
+ out.push({
64
+ key: series.key,
65
+ label: series.label,
66
+ itemType: panel.itemType,
67
+ points
68
+ });
69
+ }
70
+ return out;
71
+ }
72
+
73
+ // src/chart/palette.ts
74
+ var SERIES_COLORS_LIGHT = [
75
+ "#2a78d6",
76
+ // 1 blue
77
+ "#eb6834",
78
+ // 2 orange
79
+ "#1baf7a",
80
+ // 3 aqua
81
+ "#eda100",
82
+ // 4 yellow
83
+ "#e87ba4",
84
+ // 5 magenta
85
+ "#008300",
86
+ // 6 green
87
+ "#4a3aa7",
88
+ // 7 violet
89
+ "#e34948"
90
+ // 8 red
91
+ ];
92
+ var SERIES_COLORS_DARK = [
93
+ "#3987e5",
94
+ "#d95926",
95
+ "#199e70",
96
+ "#c98500",
97
+ "#d55181",
98
+ "#008300",
99
+ "#9085e9",
100
+ "#e66767"
101
+ ];
102
+ function seriesColor(index) {
103
+ const slot = Math.min(index, SERIES_COLORS_LIGHT.length - 1);
104
+ return `var(--rs-chart-series-${slot + 1}, ${SERIES_COLORS_LIGHT[slot]})`;
105
+ }
106
+
6
107
  // src/project.ts
7
108
  function fallbackElement(id) {
8
109
  return {
@@ -591,7 +692,23 @@ var styles = {
591
692
  margin: 0
592
693
  }
593
694
  };
594
- function wrapHtml(body) {
695
+ var MARKDOWN_CSS = `
696
+ h1, h2, h3, h4 { line-height: 1.25; margin: 1.1em 0 0.45em; font-weight: 600; }
697
+ h1 { font-size: 1.35em; margin-top: 0.2em; }
698
+ h2 { font-size: 1.15em; }
699
+ h3 { font-size: 1.05em; }
700
+ p { margin: 0.55em 0; }
701
+ ul, ol { margin: 0.55em 0; padding-left: 1.6em; }
702
+ li { margin: 0.25em 0; }
703
+ table { border-collapse: collapse; margin: 0.7em 0; }
704
+ th, td { border: 1px solid #d1d5db; padding: 0.35em 0.6em; text-align: left; }
705
+ th { background: #f3f4f6; font-weight: 600; }
706
+ code { font-family: ui-monospace, monospace; font-size: 0.92em;
707
+ background: #f3f4f6; padding: 0.1em 0.3em; border-radius: 3px; }
708
+ blockquote { margin: 0.7em 0; padding: 0.1em 1em; border-left: 3px solid #d1d5db;
709
+ color: #4b5563; }
710
+ hr { border: none; border-top: 1px solid #e5e7eb; margin: 1em 0; }`;
711
+ function wrapHtml(body, extraCss = "") {
595
712
  return `<!doctype html><html><head><meta charset="utf-8"><base target="_blank"><style>
596
713
  :root { color-scheme: light; }
597
714
  body { margin: 0; color: #111827;
@@ -599,13 +716,21 @@ function wrapHtml(body) {
599
716
  font-size: 13px; line-height: 1.45; }
600
717
  img, svg { max-width: 100%; height: auto; }
601
718
  table { max-width: 100%; border-collapse: collapse; }
602
- a { color: #1d4ed8; }
719
+ a { color: #1d4ed8; }${extraCss}
603
720
  </style></head><body>${body}</body></html>`;
604
721
  }
605
- function InlineTextBlock({ html }) {
606
- return /* @__PURE__ */ jsx(SandboxedHtml, { html });
722
+ function InlineTextBlock({
723
+ html,
724
+ contentType
725
+ }) {
726
+ const md = isMarkdown(contentType);
727
+ const body = md ? marked.parse(html, { async: false }) : html;
728
+ return /* @__PURE__ */ jsx(SandboxedHtml, { html: body, extraCss: md ? MARKDOWN_CSS : "" });
729
+ }
730
+ function isMarkdown(contentType) {
731
+ return (contentType ?? "").split(";")[0].trim().toLowerCase() === "text/markdown";
607
732
  }
608
- function SandboxedHtml({ html }) {
733
+ function SandboxedHtml({ html, extraCss = "" }) {
609
734
  const ref = useRef(null);
610
735
  const fit = () => {
611
736
  const frame = ref.current;
@@ -622,7 +747,7 @@ function SandboxedHtml({ html }) {
622
747
  ref,
623
748
  title: "Disclosure",
624
749
  sandbox: "allow-same-origin",
625
- srcDoc: wrapHtml(html),
750
+ srcDoc: wrapHtml(html, extraCss),
626
751
  style: styles.frame,
627
752
  onLoad: () => {
628
753
  fit();
@@ -1023,7 +1148,13 @@ function StatementTable({
1023
1148
  if (inline?.textValue) {
1024
1149
  return /* @__PURE__ */ jsx("tr", { children: /* @__PURE__ */ jsxs("td", { colSpan: totalCols + 1, style: styles3.textBlockCell, children: [
1025
1150
  /* @__PURE__ */ jsx("div", { style: styles3.textBlockLabel, title: row.element.qname, children: rowLabel(row) }),
1026
- /* @__PURE__ */ jsx(InlineTextBlock, { html: inline.textValue })
1151
+ /* @__PURE__ */ jsx(
1152
+ InlineTextBlock,
1153
+ {
1154
+ html: inline.textValue,
1155
+ contentType: inline.fact?.contentType
1156
+ }
1157
+ )
1027
1158
  ] }) }, row.key);
1028
1159
  }
1029
1160
  }
@@ -1159,7 +1290,394 @@ function ReportView({ report, inspect = true, dimensionAxis = "rows" }) {
1159
1290
  )
1160
1291
  ] });
1161
1292
  }
1293
+ var MARGIN = { top: 16, right: 104, bottom: 30, left: 60 };
1294
+ var MONTHS = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"];
1295
+ function shortMonth(iso) {
1296
+ const m = /^(\d{4})-(\d{2})/.exec(iso);
1297
+ if (!m) return iso;
1298
+ return `${MONTHS[Number(m[2]) - 1] ?? m[2]} '${m[1].slice(2)}`;
1299
+ }
1300
+ function niceTicks(min, max, count = 4) {
1301
+ if (!(max > min)) return [min];
1302
+ const span = max - min;
1303
+ const step0 = span / count;
1304
+ const mag = Math.pow(10, Math.floor(Math.log10(step0)));
1305
+ const norm = step0 / mag;
1306
+ const step = (norm >= 5 ? 10 : norm >= 2 ? 5 : norm >= 1 ? 2 : 1) * mag;
1307
+ const start = Math.ceil(min / step) * step;
1308
+ const ticks = [];
1309
+ for (let v = start; v <= max + step * 1e-6; v += step) ticks.push(Number(v.toFixed(10)));
1310
+ return ticks;
1311
+ }
1312
+ var styles5 = {
1313
+ wrap: {
1314
+ fontFamily: "var(--rs-font-sans, ui-sans-serif, system-ui, sans-serif)",
1315
+ color: "var(--rs-text, #111827)"
1316
+ },
1317
+ title: {
1318
+ fontFamily: "var(--rs-font-heading, var(--rs-font-sans, sans-serif))",
1319
+ fontSize: "0.9rem",
1320
+ fontWeight: 600,
1321
+ margin: "0 0 0.5rem"
1322
+ },
1323
+ legend: {
1324
+ display: "flex",
1325
+ flexWrap: "wrap",
1326
+ gap: "0.25rem 1rem",
1327
+ marginBottom: "0.5rem",
1328
+ fontSize: "0.78rem",
1329
+ color: "var(--rs-muted, #6b7280)"
1330
+ },
1331
+ legendItem: { display: "inline-flex", alignItems: "center", gap: "0.4rem" },
1332
+ legendKey: { display: "inline-block", width: 16, height: 2, borderRadius: 1 },
1333
+ empty: {
1334
+ padding: "2rem",
1335
+ textAlign: "center",
1336
+ color: "var(--rs-muted, #6b7280)",
1337
+ fontSize: "0.85rem"
1338
+ }
1339
+ };
1340
+ function TimeSeriesChart({
1341
+ series,
1342
+ itemType,
1343
+ title,
1344
+ width = 720,
1345
+ height = 280
1346
+ }) {
1347
+ const svgRef = useRef(null);
1348
+ const [active, setActive] = useState(null);
1349
+ const clipId = useId();
1350
+ const family = itemType ?? series[0]?.itemType ?? null;
1351
+ const periodCount = series[0]?.points.length ?? 0;
1352
+ const model = useMemo(() => {
1353
+ const values = [];
1354
+ for (const s of series)
1355
+ for (const p of s.points) if (p.y !== null && !Number.isNaN(p.y)) values.push(p.y);
1356
+ if (!values.length) return null;
1357
+ let min2 = Math.min(...values);
1358
+ let max2 = Math.max(...values);
1359
+ if (min2 === max2) {
1360
+ const pad = Math.abs(min2) * 0.1 || 1;
1361
+ min2 -= pad;
1362
+ max2 += pad;
1363
+ } else {
1364
+ const pad = (max2 - min2) * 0.08;
1365
+ min2 -= pad;
1366
+ max2 += pad;
1367
+ }
1368
+ return { min: min2, max: max2 };
1369
+ }, [series]);
1370
+ if (!model || periodCount === 0) {
1371
+ return /* @__PURE__ */ jsxs("div", { style: styles5.wrap, children: [
1372
+ title && /* @__PURE__ */ jsx("p", { style: styles5.title, children: title }),
1373
+ /* @__PURE__ */ jsx("p", { style: styles5.empty, children: "No data to plot for this period range." })
1374
+ ] });
1375
+ }
1376
+ const innerW = width - MARGIN.left - MARGIN.right;
1377
+ const innerH = height - MARGIN.top - MARGIN.bottom;
1378
+ const { min, max } = model;
1379
+ const xAt = (i) => periodCount === 1 ? MARGIN.left + innerW / 2 : MARGIN.left + i / (periodCount - 1) * innerW;
1380
+ const yAt = (v) => MARGIN.top + innerH - (v - min) / (max - min) * innerH;
1381
+ const yTicks = niceTicks(min, max, 4);
1382
+ const xEvery = Math.max(1, Math.ceil(periodCount / 6));
1383
+ const periods = series[0].points;
1384
+ const showEndLabels = series.length <= 4;
1385
+ const placedLabelY = [];
1386
+ const showLegend = series.length >= 2;
1387
+ const ariaLabel = `${title ? `${title} \u2014 ` : ""}line chart of ${series.length} metric${series.length === 1 ? "" : "s"} over ${periodCount} periods`;
1388
+ function handleMove(e) {
1389
+ const svg = svgRef.current;
1390
+ const ctm = svg?.getScreenCTM?.();
1391
+ if (!svg || !ctm) return;
1392
+ const pt = new DOMPoint(e.clientX, e.clientY).matrixTransform(ctm.inverse());
1393
+ if (periodCount === 1) {
1394
+ setActive(0);
1395
+ return;
1396
+ }
1397
+ const frac = (pt.x - MARGIN.left) / innerW;
1398
+ const idx = Math.round(frac * (periodCount - 1));
1399
+ setActive(Math.max(0, Math.min(periodCount - 1, idx)));
1400
+ }
1401
+ function handleKey(e) {
1402
+ if (e.key === "ArrowRight") {
1403
+ e.preventDefault();
1404
+ setActive((a) => Math.min(periodCount - 1, (a ?? -1) + 1));
1405
+ } else if (e.key === "ArrowLeft") {
1406
+ e.preventDefault();
1407
+ setActive((a) => Math.max(0, (a ?? periodCount) - 1));
1408
+ } else if (e.key === "Escape") {
1409
+ setActive(null);
1410
+ }
1411
+ }
1412
+ return /* @__PURE__ */ jsxs("div", { style: styles5.wrap, children: [
1413
+ title && /* @__PURE__ */ jsx("p", { style: styles5.title, children: title }),
1414
+ showLegend && /* @__PURE__ */ jsx("div", { style: styles5.legend, children: series.map((s, i) => /* @__PURE__ */ jsxs("span", { style: styles5.legendItem, children: [
1415
+ /* @__PURE__ */ jsx("span", { style: { ...styles5.legendKey, background: seriesColor(i) } }),
1416
+ s.label
1417
+ ] }, s.key)) }),
1418
+ /* @__PURE__ */ jsxs(
1419
+ "svg",
1420
+ {
1421
+ ref: svgRef,
1422
+ viewBox: `0 0 ${width} ${height}`,
1423
+ width: "100%",
1424
+ role: "img",
1425
+ "aria-label": ariaLabel,
1426
+ tabIndex: 0,
1427
+ style: { display: "block", outline: "none", touchAction: "none" },
1428
+ onPointerMove: handleMove,
1429
+ onPointerLeave: () => setActive(null),
1430
+ onKeyDown: handleKey,
1431
+ children: [
1432
+ /* @__PURE__ */ jsx("defs", { children: /* @__PURE__ */ jsx("clipPath", { id: clipId, children: /* @__PURE__ */ jsx("rect", { x: MARGIN.left, y: MARGIN.top, width: innerW, height: innerH }) }) }),
1433
+ yTicks.map((t) => /* @__PURE__ */ jsxs("g", { children: [
1434
+ /* @__PURE__ */ jsx(
1435
+ "line",
1436
+ {
1437
+ x1: MARGIN.left,
1438
+ x2: MARGIN.left + innerW,
1439
+ y1: yAt(t),
1440
+ y2: yAt(t),
1441
+ stroke: "var(--rs-border, #e5e7eb)",
1442
+ strokeWidth: 1
1443
+ }
1444
+ ),
1445
+ /* @__PURE__ */ jsx(
1446
+ "text",
1447
+ {
1448
+ x: MARGIN.left - 8,
1449
+ y: yAt(t),
1450
+ textAnchor: "end",
1451
+ dominantBaseline: "middle",
1452
+ fontSize: 11,
1453
+ fill: "var(--rs-muted, #6b7280)",
1454
+ style: { fontVariantNumeric: "tabular-nums" },
1455
+ children: formatMetricCompact(family, t)
1456
+ }
1457
+ )
1458
+ ] }, `y${t}`)),
1459
+ periods.map(
1460
+ (p, i) => i % xEvery === 0 || i === periodCount - 1 ? /* @__PURE__ */ jsx(
1461
+ "text",
1462
+ {
1463
+ x: xAt(i),
1464
+ y: height - MARGIN.bottom + 18,
1465
+ textAnchor: "middle",
1466
+ fontSize: 11,
1467
+ fill: "var(--rs-muted, #6b7280)",
1468
+ children: shortMonth(p.x)
1469
+ },
1470
+ `x${p.x}`
1471
+ ) : null
1472
+ ),
1473
+ /* @__PURE__ */ jsx(
1474
+ "line",
1475
+ {
1476
+ x1: MARGIN.left,
1477
+ x2: MARGIN.left + innerW,
1478
+ y1: MARGIN.top + innerH,
1479
+ y2: MARGIN.top + innerH,
1480
+ stroke: "var(--rs-border-strong, #9ca3af)",
1481
+ strokeWidth: 1
1482
+ }
1483
+ ),
1484
+ active !== null && /* @__PURE__ */ jsx(
1485
+ "line",
1486
+ {
1487
+ x1: xAt(active),
1488
+ x2: xAt(active),
1489
+ y1: MARGIN.top,
1490
+ y2: MARGIN.top + innerH,
1491
+ stroke: "var(--rs-border-strong, #9ca3af)",
1492
+ strokeWidth: 1
1493
+ }
1494
+ ),
1495
+ /* @__PURE__ */ jsx("g", { clipPath: `url(#${clipId})`, children: series.map((s, si) => {
1496
+ const color = seriesColor(si);
1497
+ const segs = [];
1498
+ let pen = false;
1499
+ s.points.forEach((pt, i) => {
1500
+ if (pt.y === null || Number.isNaN(pt.y)) {
1501
+ pen = false;
1502
+ return;
1503
+ }
1504
+ segs.push(`${pen ? "L" : "M"}${xAt(i)},${yAt(pt.y)}`);
1505
+ pen = true;
1506
+ });
1507
+ return /* @__PURE__ */ jsx(
1508
+ "path",
1509
+ {
1510
+ d: segs.join(" "),
1511
+ fill: "none",
1512
+ stroke: color,
1513
+ strokeWidth: 2,
1514
+ strokeLinejoin: "round",
1515
+ strokeLinecap: "round"
1516
+ },
1517
+ s.key
1518
+ );
1519
+ }) }),
1520
+ series.map((s, si) => {
1521
+ const color = seriesColor(si);
1522
+ let endIdx = -1;
1523
+ for (let i = s.points.length - 1; i >= 0; i--) {
1524
+ const y = s.points[i].y;
1525
+ if (y !== null && !Number.isNaN(y)) {
1526
+ endIdx = i;
1527
+ break;
1528
+ }
1529
+ }
1530
+ if (endIdx < 0) return null;
1531
+ const ey = yAt(s.points[endIdx].y);
1532
+ const ex = xAt(endIdx);
1533
+ let label = null;
1534
+ if (showEndLabels && endIdx === periodCount - 1) {
1535
+ const collides = placedLabelY.some((py) => Math.abs(py - ey) < 13);
1536
+ if (!collides) {
1537
+ placedLabelY.push(ey);
1538
+ label = formatMetricValue(family, s.points[endIdx].y);
1539
+ }
1540
+ }
1541
+ return /* @__PURE__ */ jsxs("g", { children: [
1542
+ /* @__PURE__ */ jsx(
1543
+ "circle",
1544
+ {
1545
+ cx: ex,
1546
+ cy: ey,
1547
+ r: 4,
1548
+ fill: color,
1549
+ stroke: "var(--rs-surface, #ffffff)",
1550
+ strokeWidth: 2
1551
+ }
1552
+ ),
1553
+ label && /* @__PURE__ */ jsx(
1554
+ "text",
1555
+ {
1556
+ x: ex + 8,
1557
+ y: ey,
1558
+ dominantBaseline: "middle",
1559
+ fontSize: 11,
1560
+ fill: "var(--rs-text, #111827)",
1561
+ style: { fontVariantNumeric: "tabular-nums" },
1562
+ children: label
1563
+ }
1564
+ )
1565
+ ] }, `end${s.key}`);
1566
+ }),
1567
+ active !== null && /* @__PURE__ */ jsx(
1568
+ ActiveReadout,
1569
+ {
1570
+ active,
1571
+ series,
1572
+ family,
1573
+ xAt,
1574
+ yAt,
1575
+ width,
1576
+ periodLabel: periods[active] ? shortMonth(periods[active].x) : "",
1577
+ plotTop: MARGIN.top
1578
+ }
1579
+ )
1580
+ ]
1581
+ }
1582
+ )
1583
+ ] });
1584
+ }
1585
+ function ActiveReadout({
1586
+ active,
1587
+ series,
1588
+ family,
1589
+ xAt,
1590
+ yAt,
1591
+ width,
1592
+ periodLabel,
1593
+ plotTop
1594
+ }) {
1595
+ const rows = series.map((s, i) => ({
1596
+ label: s.label,
1597
+ color: seriesColor(i),
1598
+ value: s.points[active]?.y ?? null,
1599
+ y: s.points[active]?.y
1600
+ }));
1601
+ const rowH = 16;
1602
+ const boxW = 176;
1603
+ const boxH = 22 + rows.length * rowH;
1604
+ const cx = xAt(active);
1605
+ const bx = cx + 12 + boxW > width ? cx - 12 - boxW : cx + 12;
1606
+ const by = plotTop + 4;
1607
+ return /* @__PURE__ */ jsxs("g", { pointerEvents: "none", children: [
1608
+ rows.map(
1609
+ (r) => r.y !== null && r.y !== void 0 && !Number.isNaN(r.y) ? /* @__PURE__ */ jsx(
1610
+ "circle",
1611
+ {
1612
+ cx,
1613
+ cy: yAt(r.y),
1614
+ r: 4,
1615
+ fill: r.color,
1616
+ stroke: "var(--rs-surface, #ffffff)",
1617
+ strokeWidth: 2
1618
+ },
1619
+ `ap${r.label}`
1620
+ ) : null
1621
+ ),
1622
+ /* @__PURE__ */ jsx(
1623
+ "rect",
1624
+ {
1625
+ x: bx,
1626
+ y: by,
1627
+ width: boxW,
1628
+ height: boxH,
1629
+ rx: 6,
1630
+ fill: "var(--rs-surface, #ffffff)",
1631
+ stroke: "var(--rs-border, #e5e7eb)",
1632
+ strokeWidth: 1
1633
+ }
1634
+ ),
1635
+ /* @__PURE__ */ jsx("text", { x: bx + 10, y: by + 15, fontSize: 11, fontWeight: 600, fill: "var(--rs-muted, #6b7280)", children: periodLabel }),
1636
+ rows.map((r, i) => {
1637
+ const ry = by + 22 + i * rowH + 11;
1638
+ return /* @__PURE__ */ jsxs("g", { children: [
1639
+ /* @__PURE__ */ jsx(
1640
+ "line",
1641
+ {
1642
+ x1: bx + 10,
1643
+ x2: bx + 24,
1644
+ y1: ry,
1645
+ y2: ry,
1646
+ stroke: r.color,
1647
+ strokeWidth: 2,
1648
+ strokeLinecap: "round"
1649
+ }
1650
+ ),
1651
+ /* @__PURE__ */ jsx(
1652
+ "text",
1653
+ {
1654
+ x: bx + 30,
1655
+ y: ry,
1656
+ dominantBaseline: "middle",
1657
+ fontSize: 11,
1658
+ fill: "var(--rs-muted, #6b7280)",
1659
+ children: r.label
1660
+ }
1661
+ ),
1662
+ /* @__PURE__ */ jsx(
1663
+ "text",
1664
+ {
1665
+ x: bx + boxW - 10,
1666
+ y: ry,
1667
+ dominantBaseline: "middle",
1668
+ textAnchor: "end",
1669
+ fontSize: 11,
1670
+ fontWeight: 600,
1671
+ fill: "var(--rs-text, #111827)",
1672
+ style: { fontVariantNumeric: "tabular-nums" },
1673
+ children: formatMetricValue(family, r.value)
1674
+ }
1675
+ )
1676
+ ] }, `tr${r.label}`);
1677
+ })
1678
+ ] });
1679
+ }
1162
1680
 
1163
- export { ExternalTextBlock, FactInspector, ReportView, StatementTable, buildPivot, buildPivots, calcSubtotals, defaultPivotConfig, footCheck, pivotDimensionsOn, presentationOrder, reportSections, sliceReportSection };
1681
+ export { ExternalTextBlock, FactInspector, ReportView, SERIES_COLORS_DARK, SERIES_COLORS_LIGHT, StatementTable, TimeSeriesChart, buildPivot, buildPivots, calcSubtotals, defaultPivotConfig, footCheck, formatMetricCompact, formatMetricValue, joinChartSeries, pivotDimensionsOn, presentationOrder, reportSections, seriesColor, sliceReportSection };
1164
1682
  //# sourceMappingURL=index.js.map
1165
1683
  //# sourceMappingURL=index.js.map