elseware-ui 2.32.0 → 2.33.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.mjs CHANGED
@@ -1,5 +1,5 @@
1
1
  import { twMerge } from 'tailwind-merge';
2
- import React4, { createContext, forwardRef, useState, useImperativeHandle, useEffect, useMemo, useContext, Fragment as Fragment$1, useRef, useCallback } from 'react';
2
+ import React3, { createContext, forwardRef, useState, useImperativeHandle, useEffect, useMemo, useContext, Fragment as Fragment$1, useCallback, useRef } from 'react';
3
3
  import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
4
4
  import { BsStarFill, BsStarHalf, BsStar, BsChevronDown, BsFillDiamondFill } from 'react-icons/bs';
5
5
  import { FaSun, FaMoon, FaGripVertical, FaTrash, FaPlus, FaTimes, FaBars, FaCircle, FaEyeSlash, FaEye } from 'react-icons/fa';
@@ -10,7 +10,7 @@ import classNames16 from 'classnames';
10
10
  import { FaCircleChevronDown } from 'react-icons/fa6';
11
11
  import ReactWorldFlags from 'react-world-flags';
12
12
  import emojiFlags from 'emoji-flags';
13
- import * as d3 from 'd3';
13
+ import { ResponsiveContainer, LineChart as LineChart$1, CartesianGrid, XAxis, YAxis, Tooltip as Tooltip$1, Line as Line$1, AreaChart, Area, BarChart as BarChart$1, Bar as Bar$1, PieChart as PieChart$1, Pie as Pie$1, Cell, ScatterChart, Scatter } from 'recharts';
14
14
  import { Image, CloudinaryContext as CloudinaryContext$1 } from 'cloudinary-react';
15
15
  import { useField, ErrorMessage, Formik, Form as Form$1, Field, useFormikContext, FieldArray } from 'formik';
16
16
  import { toast, ToastContainer } from 'react-toastify';
@@ -1320,257 +1320,2444 @@ var Flag = ({
1320
1320
  );
1321
1321
  };
1322
1322
 
1323
- // src/components/data-display/graphs/layouts/registry.ts
1324
- var registry = /* @__PURE__ */ new Map();
1325
- var registerLayout = (type, executor) => {
1326
- registry.set(type, executor);
1323
+ // src/components/data-display/graphs-v2/constants/graph.constants.ts
1324
+ var GRAPH_DEFAULT_HEIGHT = 320;
1325
+ var GRAPH_DEFAULT_MAX_REALTIME_POINTS = 100;
1326
+ var GRAPH_DEFAULT_POLLING_INTERVAL = 5e3;
1327
+ var GRAPH_DEFAULT_ANIMATION_DURATION = 350;
1328
+ var GRAPH_DEFAULT_MARGIN = {
1329
+ top: 16,
1330
+ right: 24,
1331
+ bottom: 16,
1332
+ left: 8
1327
1333
  };
1328
- var getLayout = (type) => {
1329
- const layout = registry.get(type);
1330
- if (!layout) {
1331
- throw new Error(`Layout "${type}" not registered`);
1332
- }
1333
- return layout;
1334
+ var GRAPH_DEFAULT_STROKE_WIDTH = 2;
1335
+ var GRAPH_DEFAULT_DOT_RADIUS = 3;
1336
+ var GRAPH_DEFAULT_ACTIVE_DOT_RADIUS = 5;
1337
+ var GRAPH_DEFAULT_BAR_RADIUS = [
1338
+ 6,
1339
+ 6,
1340
+ 0,
1341
+ 0
1342
+ ];
1343
+ var GRAPH_STATUSES = {
1344
+ IDLE: "idle",
1345
+ LOADING: "loading",
1346
+ SUCCESS: "success",
1347
+ ERROR: "error",
1348
+ STREAMING: "streaming"
1349
+ };
1350
+ var GRAPH_DATA_MODES = {
1351
+ STATIC: "static",
1352
+ POLLING: "polling",
1353
+ REALTIME: "realtime"
1354
+ };
1355
+ var GRAPH_VALUE_FORMATS = {
1356
+ RAW: "raw",
1357
+ NUMBER: "number",
1358
+ INTEGER: "integer",
1359
+ COMPACT: "compact",
1360
+ PERCENT: "percent",
1361
+ CURRENCY: "currency",
1362
+ BYTES: "bytes",
1363
+ DURATION: "duration"
1364
+ };
1365
+ var GRAPH_EMPTY_MESSAGE = "No graph data available";
1366
+ var GRAPH_ERROR_MESSAGE = "Unable to load graph data";
1367
+ var GRAPH_LOADING_MESSAGE = "Loading graph data...";
1368
+
1369
+ // src/components/data-display/graphs-v2/constants/graph-theme.constants.ts
1370
+ var GRAPH_COLOR_PALETTE = [
1371
+ "#7dd3fc",
1372
+ "#a78bfa",
1373
+ "#34d399",
1374
+ "#fbbf24",
1375
+ "#fb7185",
1376
+ "#60a5fa",
1377
+ "#f472b6",
1378
+ "#22d3ee",
1379
+ "#c084fc",
1380
+ "#a3e635"
1381
+ ];
1382
+ var GRAPH_STATUS_COLORS = {
1383
+ primary: "#7dd3fc",
1384
+ secondary: "#a78bfa",
1385
+ success: "#34d399",
1386
+ warning: "#fbbf24",
1387
+ danger: "#fb7185",
1388
+ info: "#60a5fa",
1389
+ muted: "#6b7280"
1390
+ };
1391
+ var GRAPH_DARK_THEME = {
1392
+ panel: {
1393
+ background: "bg-[#111217]",
1394
+ border: "border border-[#2a2d35]",
1395
+ radius: "rounded-xl",
1396
+ shadow: "shadow-sm"
1397
+ },
1398
+ text: {
1399
+ title: "text-gray-100",
1400
+ description: "text-gray-400",
1401
+ muted: "text-gray-500"
1402
+ },
1403
+ chart: {
1404
+ grid: "#2a2d35",
1405
+ axis: "#8b949e",
1406
+ cursor: "rgba(255, 255, 255, 0.06)"
1407
+ },
1408
+ tooltip: {
1409
+ background: "#181b21",
1410
+ border: "#2a2d35",
1411
+ text: "#f3f4f6",
1412
+ muted: "#9ca3af"
1413
+ },
1414
+ colors: GRAPH_COLOR_PALETTE
1415
+ };
1416
+ var GRAPH_LIGHT_THEME = {
1417
+ panel: {
1418
+ background: "bg-white",
1419
+ border: "border border-gray-200",
1420
+ radius: "rounded-xl",
1421
+ shadow: "shadow-sm"
1422
+ },
1423
+ text: {
1424
+ title: "text-gray-900",
1425
+ description: "text-gray-500",
1426
+ muted: "text-gray-400"
1427
+ },
1428
+ chart: {
1429
+ grid: "#e5e7eb",
1430
+ axis: "#6b7280",
1431
+ cursor: "rgba(0, 0, 0, 0.04)"
1432
+ },
1433
+ tooltip: {
1434
+ background: "#ffffff",
1435
+ border: "#e5e7eb",
1436
+ text: "#111827",
1437
+ muted: "#6b7280"
1438
+ },
1439
+ colors: GRAPH_COLOR_PALETTE
1440
+ };
1441
+ var DEFAULT_GRAPH_THEME = GRAPH_DARK_THEME;
1442
+
1443
+ // src/components/data-display/graphs-v2/utils/normalizeGraphData.ts
1444
+ var DEFAULT_NORMALIZE_OPTIONS = {
1445
+ serializeDates: true,
1446
+ parseNumericStrings: true,
1447
+ sanitizeInvalidNumbers: true,
1448
+ removeUndefined: true
1334
1449
  };
1335
- var createForceLayout = (nodes, edges, width, height) => {
1336
- const nodeMap = new Map(nodes.map((n) => [n.id, n]));
1337
- const d3Links = edges.filter((e) => {
1338
- const fromId = typeof e.from === "string" ? e.from : e.from.id;
1339
- const toId = typeof e.to === "string" ? e.to : e.to.id;
1340
- const valid = nodeMap.has(fromId) && nodeMap.has(toId);
1341
- if (!valid) {
1342
- console.warn("Invalid edge skipped:", e);
1450
+ function isNumericString(value) {
1451
+ if (!value.trim()) {
1452
+ return false;
1453
+ }
1454
+ return !Number.isNaN(Number(value));
1455
+ }
1456
+ function normalizeValue(value, options) {
1457
+ if (value instanceof Date) {
1458
+ return options.serializeDates ? value.toISOString() : value;
1459
+ }
1460
+ if (typeof value === "number") {
1461
+ if (options.sanitizeInvalidNumbers && (Number.isNaN(value) || !Number.isFinite(value))) {
1462
+ return null;
1343
1463
  }
1344
- return valid;
1345
- }).map((e) => ({
1346
- source: typeof e.from === "string" ? e.from : e.from.id,
1347
- target: typeof e.to === "string" ? e.to : e.to.id,
1348
- weight: e.weight
1349
- }));
1350
- return d3.forceSimulation(nodes).force(
1351
- "link",
1352
- d3.forceLink(d3Links).id((d) => d.id).distance(120).strength(0.7)
1353
- ).force("charge", d3.forceManyBody().strength(-280)).force("center", d3.forceCenter(width / 2, height / 2)).force("collision", d3.forceCollide().radius(35));
1464
+ return value;
1465
+ }
1466
+ if (typeof value === "string") {
1467
+ if (options.parseNumericStrings && isNumericString(value)) {
1468
+ return Number(value);
1469
+ }
1470
+ return value;
1471
+ }
1472
+ if (typeof value === "boolean" || value === null || value === void 0) {
1473
+ return value;
1474
+ }
1475
+ return String(value);
1476
+ }
1477
+ function normalizeGraphData(data, options = {}) {
1478
+ if (!Array.isArray(data)) {
1479
+ return [];
1480
+ }
1481
+ const resolvedOptions = {
1482
+ ...DEFAULT_NORMALIZE_OPTIONS,
1483
+ ...options
1484
+ };
1485
+ return data.map((item) => {
1486
+ const normalizedPoint = {};
1487
+ const keys = options.keys ?? Object.keys(item);
1488
+ keys.forEach((key) => {
1489
+ const value = normalizeValue(item[key], resolvedOptions);
1490
+ if (resolvedOptions.removeUndefined && value === void 0) {
1491
+ return;
1492
+ }
1493
+ normalizedPoint[key] = value;
1494
+ });
1495
+ return normalizedPoint;
1496
+ });
1497
+ }
1498
+ function normalizeGraphDataPoint(dataPoint, options = {}) {
1499
+ return normalizeGraphData([dataPoint], options)[0] ?? {};
1500
+ }
1501
+
1502
+ // src/components/data-display/graphs-v2/utils/formatGraphValue.ts
1503
+ var DEFAULT_FORMAT_OPTIONS = {
1504
+ format: "number",
1505
+ locale: "en-US",
1506
+ fallback: "-"
1354
1507
  };
1508
+ function isValidNumber(value) {
1509
+ return typeof value === "number" && Number.isFinite(value) && !Number.isNaN(value);
1510
+ }
1511
+ function formatBytes(value, locale) {
1512
+ if (value === 0) {
1513
+ return "0 B";
1514
+ }
1515
+ const units = ["B", "KB", "MB", "GB", "TB", "PB"];
1516
+ const unitIndex = Math.min(
1517
+ Math.floor(Math.log(Math.abs(value)) / Math.log(1024)),
1518
+ units.length - 1
1519
+ );
1520
+ const formattedValue = value / 1024 ** unitIndex;
1521
+ return `${new Intl.NumberFormat(locale, {
1522
+ maximumFractionDigits: formattedValue >= 10 ? 1 : 2
1523
+ }).format(formattedValue)} ${units[unitIndex]}`;
1524
+ }
1525
+ function formatDuration(value, locale) {
1526
+ if (value < 1e3) {
1527
+ return `${Math.round(value)} ms`;
1528
+ }
1529
+ const seconds = value / 1e3;
1530
+ if (seconds < 60) {
1531
+ return `${new Intl.NumberFormat(locale, {
1532
+ maximumFractionDigits: 2
1533
+ }).format(seconds)} s`;
1534
+ }
1535
+ const minutes = seconds / 60;
1536
+ if (minutes < 60) {
1537
+ return `${new Intl.NumberFormat(locale, {
1538
+ maximumFractionDigits: 2
1539
+ }).format(minutes)} min`;
1540
+ }
1541
+ const hours = minutes / 60;
1542
+ return `${new Intl.NumberFormat(locale, {
1543
+ maximumFractionDigits: 2
1544
+ }).format(hours)} h`;
1545
+ }
1546
+ function formatGraphValue(value, options = {}) {
1547
+ const {
1548
+ format,
1549
+ locale,
1550
+ fallback,
1551
+ prefix = "",
1552
+ suffix = "",
1553
+ currency = "USD",
1554
+ minimumFractionDigits,
1555
+ maximumFractionDigits
1556
+ } = {
1557
+ ...DEFAULT_FORMAT_OPTIONS,
1558
+ ...options
1559
+ };
1560
+ if (value === null || value === void 0 || value === "") {
1561
+ return fallback;
1562
+ }
1563
+ if (format === "raw") {
1564
+ return `${prefix}${String(value)}${suffix}`;
1565
+ }
1566
+ const numericValue = typeof value === "string" && value.trim() !== "" ? Number(value) : value;
1567
+ if (!isValidNumber(numericValue)) {
1568
+ return `${prefix}${String(value)}${suffix}`;
1569
+ }
1570
+ let formattedValue;
1571
+ switch (format) {
1572
+ case "integer":
1573
+ formattedValue = new Intl.NumberFormat(locale, {
1574
+ maximumFractionDigits: 0
1575
+ }).format(numericValue);
1576
+ break;
1577
+ case "compact":
1578
+ formattedValue = new Intl.NumberFormat(locale, {
1579
+ notation: "compact",
1580
+ maximumFractionDigits: maximumFractionDigits ?? 2
1581
+ }).format(numericValue);
1582
+ break;
1583
+ case "percent":
1584
+ formattedValue = new Intl.NumberFormat(locale, {
1585
+ style: "percent",
1586
+ minimumFractionDigits: minimumFractionDigits ?? 0,
1587
+ maximumFractionDigits: maximumFractionDigits ?? 2
1588
+ }).format(numericValue / 100);
1589
+ break;
1590
+ case "currency":
1591
+ formattedValue = new Intl.NumberFormat(locale, {
1592
+ style: "currency",
1593
+ currency,
1594
+ minimumFractionDigits,
1595
+ maximumFractionDigits
1596
+ }).format(numericValue);
1597
+ break;
1598
+ case "bytes":
1599
+ formattedValue = formatBytes(numericValue, locale);
1600
+ break;
1601
+ case "duration":
1602
+ formattedValue = formatDuration(numericValue, locale);
1603
+ break;
1604
+ case "number":
1605
+ default:
1606
+ formattedValue = new Intl.NumberFormat(locale, {
1607
+ minimumFractionDigits,
1608
+ maximumFractionDigits: maximumFractionDigits ?? 2
1609
+ }).format(numericValue);
1610
+ break;
1611
+ }
1612
+ return `${prefix}${formattedValue}${suffix}`;
1613
+ }
1355
1614
 
1356
- // src/components/data-display/graphs/layouts/gridLayout.ts
1357
- function createGridLayout(nodes, width, height) {
1358
- const cols = Math.ceil(Math.sqrt(nodes.length));
1359
- const spacingX = width / (cols + 1);
1360
- const spacingY = height / (cols + 1);
1361
- return nodes.map((node, i) => ({
1362
- ...node,
1363
- x: spacingX * (i % cols + 1),
1364
- y: spacingY * (Math.floor(i / cols) + 1)
1365
- }));
1615
+ // src/components/data-display/graphs-v2/utils/resolveGraphColor.ts
1616
+ var NAMED_COLORS = {
1617
+ primary: GRAPH_STATUS_COLORS.primary,
1618
+ secondary: GRAPH_STATUS_COLORS.secondary,
1619
+ success: GRAPH_STATUS_COLORS.success,
1620
+ warning: GRAPH_STATUS_COLORS.warning,
1621
+ danger: GRAPH_STATUS_COLORS.danger,
1622
+ info: GRAPH_STATUS_COLORS.info,
1623
+ muted: GRAPH_STATUS_COLORS.muted
1624
+ };
1625
+ function isCssColor(value) {
1626
+ return value.startsWith("#") || value.startsWith("rgb(") || value.startsWith("rgba(") || value.startsWith("hsl(") || value.startsWith("hsla(") || value.startsWith("var(");
1627
+ }
1628
+ function resolveGraphColor(color, options = {}) {
1629
+ const {
1630
+ index = 0,
1631
+ fallback = GRAPH_COLOR_PALETTE[0],
1632
+ palette = GRAPH_COLOR_PALETTE
1633
+ } = options;
1634
+ if (color) {
1635
+ if (isCssColor(color)) {
1636
+ return color;
1637
+ }
1638
+ if (color in NAMED_COLORS) {
1639
+ return NAMED_COLORS[color];
1640
+ }
1641
+ }
1642
+ if (palette.length > 0) {
1643
+ return palette[index % palette.length];
1644
+ }
1645
+ return fallback;
1646
+ }
1647
+ function resolveGraphColors(count, options = {}) {
1648
+ return Array.from(
1649
+ { length: count },
1650
+ (_, index) => resolveGraphColor(void 0, {
1651
+ ...options,
1652
+ index
1653
+ })
1654
+ );
1366
1655
  }
1367
1656
 
1368
- // src/components/data-display/graphs/layouts/treeLayout.ts
1369
- function createTreeLayout(nodes, edges, width, height) {
1370
- const levelMap = {};
1371
- const root = nodes[0];
1372
- if (!root) return nodes;
1373
- levelMap[root.id] = 0;
1374
- edges.forEach((edge) => {
1375
- const fromId = typeof edge.from === "string" ? edge.from : edge.from.id;
1376
- const toId = typeof edge.to === "string" ? edge.to : edge.to.id;
1377
- levelMap[toId] = (levelMap[fromId] ?? 0) + 1;
1657
+ // src/components/data-display/graphs-v2/utils/limitRealtimePoints.ts
1658
+ var DEFAULT_MAX_POINTS = 100;
1659
+ function limitRealtimePoints(currentData = [], nextData, options = {}) {
1660
+ const { maxPoints = DEFAULT_MAX_POINTS, appendDirection = "end" } = options;
1661
+ const incomingData = Array.isArray(nextData) ? nextData : [nextData];
1662
+ const mergedData = appendDirection === "start" ? [...incomingData, ...currentData] : [...currentData, ...incomingData];
1663
+ if (maxPoints <= 0) {
1664
+ return mergedData;
1665
+ }
1666
+ if (mergedData.length <= maxPoints) {
1667
+ return mergedData;
1668
+ }
1669
+ return appendDirection === "start" ? mergedData.slice(0, maxPoints) : mergedData.slice(-maxPoints);
1670
+ }
1671
+ function replaceRealtimePoints(nextData = [], options = {}) {
1672
+ const { maxPoints = DEFAULT_MAX_POINTS } = options;
1673
+ if (maxPoints <= 0) {
1674
+ return nextData;
1675
+ }
1676
+ return nextData.slice(-maxPoints);
1677
+ }
1678
+
1679
+ // src/components/data-display/graphs-v2/hooks/useGraphData.ts
1680
+ function useGraphData({
1681
+ data,
1682
+ dataSource,
1683
+ autoLoad = true,
1684
+ maxDataPoints = GRAPH_DEFAULT_MAX_REALTIME_POINTS,
1685
+ normalize: normalize2 = true,
1686
+ onDataChange,
1687
+ onError
1688
+ } = {}) {
1689
+ const [state, setState] = useState({
1690
+ data: data ?? [],
1691
+ loading: false,
1692
+ error: null,
1693
+ status: data?.length ? "success" : "idle",
1694
+ lastUpdatedAt: data?.length ? /* @__PURE__ */ new Date() : void 0
1378
1695
  });
1379
- const maxLevel = Math.max(...Object.values(levelMap));
1380
- const levelGroups = {};
1381
- nodes.forEach((node) => {
1382
- const level = levelMap[node.id] ?? 0;
1383
- if (!levelGroups[level]) levelGroups[level] = [];
1384
- levelGroups[level].push(node);
1696
+ const prepareData = useCallback(
1697
+ (nextData) => {
1698
+ if (!normalize2) {
1699
+ return nextData;
1700
+ }
1701
+ return normalizeGraphData(nextData);
1702
+ },
1703
+ [normalize2]
1704
+ );
1705
+ const replaceData = useCallback(
1706
+ (nextData) => {
1707
+ const normalizedData = prepareData(nextData);
1708
+ setState({
1709
+ data: normalizedData,
1710
+ loading: false,
1711
+ error: null,
1712
+ status: "success",
1713
+ lastUpdatedAt: /* @__PURE__ */ new Date()
1714
+ });
1715
+ onDataChange?.(normalizedData);
1716
+ },
1717
+ [onDataChange, prepareData]
1718
+ );
1719
+ const appendData = useCallback(
1720
+ (nextData) => {
1721
+ setState((currentState) => {
1722
+ const incomingData = Array.isArray(nextData) ? nextData : [nextData];
1723
+ const normalizedIncomingData = prepareData(incomingData);
1724
+ const limitedData = limitRealtimePoints(
1725
+ currentState.data,
1726
+ normalizedIncomingData,
1727
+ {
1728
+ maxPoints: maxDataPoints
1729
+ }
1730
+ );
1731
+ onDataChange?.(limitedData);
1732
+ return {
1733
+ data: limitedData,
1734
+ loading: false,
1735
+ error: null,
1736
+ status: "streaming",
1737
+ lastUpdatedAt: /* @__PURE__ */ new Date()
1738
+ };
1739
+ });
1740
+ },
1741
+ [maxDataPoints, onDataChange, prepareData]
1742
+ );
1743
+ const clearData = useCallback(() => {
1744
+ setState({
1745
+ data: [],
1746
+ loading: false,
1747
+ error: null,
1748
+ status: "idle",
1749
+ lastUpdatedAt: void 0
1750
+ });
1751
+ onDataChange?.([]);
1752
+ }, [onDataChange]);
1753
+ const handleError = useCallback(
1754
+ (error) => {
1755
+ setState((currentState) => ({
1756
+ ...currentState,
1757
+ loading: false,
1758
+ error,
1759
+ status: "error"
1760
+ }));
1761
+ onError?.(error);
1762
+ },
1763
+ [onError]
1764
+ );
1765
+ const refresh = useCallback(async () => {
1766
+ const resolvedDataSource = dataSource;
1767
+ if (!resolvedDataSource?.refresh && !resolvedDataSource?.getInitialData) {
1768
+ return;
1769
+ }
1770
+ try {
1771
+ setState((currentState) => ({
1772
+ ...currentState,
1773
+ loading: true,
1774
+ error: null,
1775
+ status: "loading"
1776
+ }));
1777
+ const loader = resolvedDataSource.refresh ?? resolvedDataSource.getInitialData;
1778
+ const result = await loader?.();
1779
+ replaceData(result ?? []);
1780
+ } catch (error) {
1781
+ handleError(error instanceof Error ? error : new Error(String(error)));
1782
+ }
1783
+ }, [dataSource, handleError, replaceData]);
1784
+ useEffect(() => {
1785
+ if (!data) {
1786
+ return;
1787
+ }
1788
+ replaceData(data);
1789
+ }, [data, replaceData]);
1790
+ useEffect(() => {
1791
+ if (!dataSource || !autoLoad) {
1792
+ return;
1793
+ }
1794
+ const resolvedDataSource = dataSource;
1795
+ let unsubscribe;
1796
+ let isMounted = true;
1797
+ async function loadInitialData() {
1798
+ if (!resolvedDataSource.getInitialData) {
1799
+ return;
1800
+ }
1801
+ try {
1802
+ setState((currentState) => ({
1803
+ ...currentState,
1804
+ loading: true,
1805
+ error: null,
1806
+ status: "loading"
1807
+ }));
1808
+ const result = await resolvedDataSource.getInitialData();
1809
+ if (isMounted) {
1810
+ replaceData(result ?? []);
1811
+ }
1812
+ } catch (error) {
1813
+ if (isMounted) {
1814
+ handleError(
1815
+ error instanceof Error ? error : new Error(String(error))
1816
+ );
1817
+ }
1818
+ }
1819
+ }
1820
+ void loadInitialData();
1821
+ if (resolvedDataSource.subscribe) {
1822
+ unsubscribe = resolvedDataSource.subscribe(appendData, handleError);
1823
+ }
1824
+ return () => {
1825
+ isMounted = false;
1826
+ unsubscribe?.();
1827
+ };
1828
+ }, [appendData, autoLoad, dataSource, handleError, replaceData]);
1829
+ return useMemo(
1830
+ () => ({
1831
+ ...state,
1832
+ refresh,
1833
+ replaceData,
1834
+ appendData,
1835
+ clearData
1836
+ }),
1837
+ [appendData, clearData, refresh, replaceData, state]
1838
+ );
1839
+ }
1840
+ function useGraphRealtime({
1841
+ enabled = true,
1842
+ maxDataPoints = GRAPH_DEFAULT_MAX_REALTIME_POINTS,
1843
+ normalize: normalize2 = true,
1844
+ connect,
1845
+ onData,
1846
+ onError
1847
+ }) {
1848
+ const [data, setData] = useState([]);
1849
+ const [error, setError] = useState(null);
1850
+ const [connected, setConnected] = useState(false);
1851
+ const [lastUpdatedAt, setLastUpdatedAt] = useState();
1852
+ useEffect(() => {
1853
+ if (!enabled) {
1854
+ setConnected(false);
1855
+ return;
1856
+ }
1857
+ const handleData = (incomingData) => {
1858
+ const incomingArray = Array.isArray(incomingData) ? incomingData : [incomingData];
1859
+ const normalizedIncomingData = normalize2 ? normalizeGraphData(incomingArray) : incomingArray;
1860
+ setData((currentData) => {
1861
+ const nextData = limitRealtimePoints(
1862
+ currentData,
1863
+ normalizedIncomingData,
1864
+ {
1865
+ maxPoints: maxDataPoints
1866
+ }
1867
+ );
1868
+ onData?.(nextData);
1869
+ return nextData;
1870
+ });
1871
+ setError(null);
1872
+ setConnected(true);
1873
+ setLastUpdatedAt(/* @__PURE__ */ new Date());
1874
+ };
1875
+ const handleError = (nextError) => {
1876
+ setError(nextError);
1877
+ onError?.(nextError);
1878
+ };
1879
+ const unsubscribe = connect(handleData, handleError);
1880
+ setConnected(true);
1881
+ return () => {
1882
+ unsubscribe?.();
1883
+ setConnected(false);
1884
+ };
1885
+ }, [connect, enabled, maxDataPoints, normalize2, onData, onError]);
1886
+ return useMemo(
1887
+ () => ({
1888
+ data,
1889
+ error,
1890
+ connected,
1891
+ loading: enabled && !connected && !error,
1892
+ status: error ? "error" : connected ? "streaming" : "idle",
1893
+ lastUpdatedAt,
1894
+ clearData: () => setData([])
1895
+ }),
1896
+ [connected, data, enabled, error, lastUpdatedAt]
1897
+ );
1898
+ }
1899
+ function useGraphPolling({
1900
+ enabled = true,
1901
+ interval = GRAPH_DEFAULT_POLLING_INTERVAL,
1902
+ immediate = true,
1903
+ normalize: normalize2 = true,
1904
+ fetcher,
1905
+ onData,
1906
+ onError
1907
+ }) {
1908
+ const isMountedRef = useRef(false);
1909
+ const isFetchingRef = useRef(false);
1910
+ const [data, setData] = useState([]);
1911
+ const [error, setError] = useState(null);
1912
+ const [loading, setLoading] = useState(immediate);
1913
+ const [lastUpdatedAt, setLastUpdatedAt] = useState();
1914
+ const refresh = useCallback(async () => {
1915
+ if (isFetchingRef.current) {
1916
+ return;
1917
+ }
1918
+ try {
1919
+ isFetchingRef.current = true;
1920
+ setLoading(true);
1921
+ setError(null);
1922
+ const result = await fetcher();
1923
+ const nextData = normalize2 ? normalizeGraphData(result ?? []) : result ?? [];
1924
+ if (!isMountedRef.current) {
1925
+ return;
1926
+ }
1927
+ setData(nextData);
1928
+ setLastUpdatedAt(/* @__PURE__ */ new Date());
1929
+ onData?.(nextData);
1930
+ } catch (error2) {
1931
+ const nextError = error2 instanceof Error ? error2 : new Error(String(error2));
1932
+ if (isMountedRef.current) {
1933
+ setError(nextError);
1934
+ onError?.(nextError);
1935
+ }
1936
+ } finally {
1937
+ if (isMountedRef.current) {
1938
+ setLoading(false);
1939
+ }
1940
+ isFetchingRef.current = false;
1941
+ }
1942
+ }, [fetcher, normalize2, onData, onError]);
1943
+ useEffect(() => {
1944
+ isMountedRef.current = true;
1945
+ return () => {
1946
+ isMountedRef.current = false;
1947
+ };
1948
+ }, []);
1949
+ useEffect(() => {
1950
+ if (!enabled) {
1951
+ setLoading(false);
1952
+ return;
1953
+ }
1954
+ if (immediate) {
1955
+ void refresh();
1956
+ }
1957
+ const timer = window.setInterval(() => {
1958
+ void refresh();
1959
+ }, interval);
1960
+ return () => {
1961
+ window.clearInterval(timer);
1962
+ };
1963
+ }, [enabled, immediate, interval, refresh]);
1964
+ return useMemo(
1965
+ () => ({
1966
+ data,
1967
+ error,
1968
+ loading,
1969
+ status: error ? "error" : loading ? "loading" : "success",
1970
+ lastUpdatedAt,
1971
+ refresh
1972
+ }),
1973
+ [data, error, lastUpdatedAt, loading, refresh]
1974
+ );
1975
+ }
1976
+ function createLabelFromKey(key) {
1977
+ return key.replace(/[_-]+/g, " ").replace(/([a-z])([A-Z])/g, "$1 $2").replace(/\b\w/g, (character) => character.toUpperCase());
1978
+ }
1979
+ function inferSeriesKeys(data, xKey, excludeKeys = []) {
1980
+ const firstPoint = data[0];
1981
+ if (!firstPoint) {
1982
+ return [];
1983
+ }
1984
+ return Object.keys(firstPoint).filter((key) => {
1985
+ if (key === xKey) {
1986
+ return false;
1987
+ }
1988
+ if (excludeKeys.includes(key)) {
1989
+ return false;
1990
+ }
1991
+ const value = firstPoint[key];
1992
+ return typeof value === "number";
1993
+ });
1994
+ }
1995
+ function useGraphSeries({
1996
+ data = [],
1997
+ series,
1998
+ xKey,
1999
+ excludeKeys = []
2000
+ }) {
2001
+ return useMemo(() => {
2002
+ const normalizedSeries = series && series.length > 0 ? series : inferSeriesKeys(data, xKey, excludeKeys).map((key) => ({
2003
+ key
2004
+ }));
2005
+ return normalizedSeries.map((item, index) => ({
2006
+ key: item.key,
2007
+ label: item.label ?? createLabelFromKey(item.key),
2008
+ type: item.type ?? "line",
2009
+ color: resolveGraphColor(item.color, { index }),
2010
+ unit: item.unit,
2011
+ visible: item.visible ?? true,
2012
+ strokeWidth: item.strokeWidth ?? GRAPH_DEFAULT_STROKE_WIDTH,
2013
+ radius: item.radius ?? GRAPH_DEFAULT_ACTIVE_DOT_RADIUS,
2014
+ format: item.format,
2015
+ prefix: item.prefix,
2016
+ suffix: item.suffix,
2017
+ yAxisId: item.yAxisId
2018
+ }));
2019
+ }, [data, excludeKeys, series, xKey]);
2020
+ }
2021
+ function mergeGraphTheme(baseTheme, customTheme) {
2022
+ if (!customTheme) {
2023
+ return baseTheme;
2024
+ }
2025
+ return {
2026
+ panel: {
2027
+ ...baseTheme.panel,
2028
+ ...customTheme.panel
2029
+ },
2030
+ text: {
2031
+ ...baseTheme.text,
2032
+ ...customTheme.text
2033
+ },
2034
+ chart: {
2035
+ ...baseTheme.chart,
2036
+ ...customTheme.chart
2037
+ },
2038
+ tooltip: {
2039
+ ...baseTheme.tooltip,
2040
+ ...customTheme.tooltip
2041
+ },
2042
+ colors: customTheme.colors ?? baseTheme.colors
2043
+ };
2044
+ }
2045
+ function useGraphTheme({
2046
+ mode = "dark",
2047
+ theme
2048
+ } = {}) {
2049
+ return useMemo(() => {
2050
+ const baseTheme = mode === "light" ? GRAPH_LIGHT_THEME : mode === "dark" ? GRAPH_DARK_THEME : DEFAULT_GRAPH_THEME;
2051
+ return mergeGraphTheme(baseTheme, theme);
2052
+ }, [mode, theme]);
2053
+ }
2054
+ var GraphContext = createContext({
2055
+ data: [],
2056
+ loading: false,
2057
+ error: null,
2058
+ status: "idle",
2059
+ maxDataPoints: GRAPH_DEFAULT_MAX_REALTIME_POINTS,
2060
+ refresh: async () => {
2061
+ },
2062
+ replaceData: () => {
2063
+ },
2064
+ appendData: () => {
2065
+ },
2066
+ clearData: () => {
2067
+ }
2068
+ });
2069
+ function GraphProvider({
2070
+ children,
2071
+ data,
2072
+ dataSource,
2073
+ maxDataPoints = GRAPH_DEFAULT_MAX_REALTIME_POINTS,
2074
+ autoLoad = true,
2075
+ onDataChange,
2076
+ onError
2077
+ }) {
2078
+ const graphData = useGraphData({
2079
+ data,
2080
+ dataSource,
2081
+ autoLoad,
2082
+ maxDataPoints,
2083
+ onDataChange,
2084
+ onError
1385
2085
  });
1386
- return nodes.map((node) => {
1387
- const level = levelMap[node.id] ?? 0;
1388
- const siblings = levelGroups[level];
1389
- const index = siblings.indexOf(node);
2086
+ const value = useMemo(
2087
+ () => ({
2088
+ ...graphData,
2089
+ mode: dataSource?.mode,
2090
+ maxDataPoints
2091
+ }),
2092
+ [dataSource?.mode, graphData, maxDataPoints]
2093
+ );
2094
+ return /* @__PURE__ */ jsx(
2095
+ GraphContext.Provider,
2096
+ {
2097
+ value,
2098
+ children
2099
+ }
2100
+ );
2101
+ }
2102
+ function useGraphContext() {
2103
+ return useContext(GraphContext);
2104
+ }
2105
+
2106
+ // src/components/data-display/graphs-v2/context/graphReducer.ts
2107
+ function createInitialGraphState(data = []) {
2108
+ return {
2109
+ data,
2110
+ loading: false,
2111
+ error: null,
2112
+ status: data.length > 0 ? "success" : "idle",
2113
+ lastUpdatedAt: data.length > 0 ? /* @__PURE__ */ new Date() : void 0
2114
+ };
2115
+ }
2116
+ function graphReducer(state, action) {
2117
+ switch (action.type) {
2118
+ case "SET_LOADING": {
2119
+ const loading = action.payload ?? true;
2120
+ return {
2121
+ ...state,
2122
+ loading,
2123
+ error: loading ? null : state.error,
2124
+ status: loading ? "loading" : state.status
2125
+ };
2126
+ }
2127
+ case "SET_ERROR": {
2128
+ return {
2129
+ ...state,
2130
+ loading: false,
2131
+ error: action.payload,
2132
+ status: action.payload ? "error" : state.data.length > 0 ? "success" : "idle"
2133
+ };
2134
+ }
2135
+ case "SET_DATA": {
2136
+ return {
2137
+ data: action.payload,
2138
+ loading: false,
2139
+ error: null,
2140
+ status: "success",
2141
+ lastUpdatedAt: /* @__PURE__ */ new Date()
2142
+ };
2143
+ }
2144
+ case "APPEND_DATA": {
2145
+ const nextData = limitRealtimePoints(state.data, action.payload.data, {
2146
+ maxPoints: action.payload.maxDataPoints ?? GRAPH_DEFAULT_MAX_REALTIME_POINTS
2147
+ });
2148
+ return {
2149
+ data: nextData,
2150
+ loading: false,
2151
+ error: null,
2152
+ status: "streaming",
2153
+ lastUpdatedAt: /* @__PURE__ */ new Date()
2154
+ };
2155
+ }
2156
+ case "CLEAR_DATA": {
2157
+ return {
2158
+ data: [],
2159
+ loading: false,
2160
+ error: null,
2161
+ status: "idle",
2162
+ lastUpdatedAt: void 0
2163
+ };
2164
+ }
2165
+ case "SET_STREAMING": {
2166
+ const streaming = action.payload ?? true;
2167
+ return {
2168
+ ...state,
2169
+ loading: false,
2170
+ error: null,
2171
+ status: streaming ? "streaming" : state.data.length > 0 ? "success" : "idle",
2172
+ lastUpdatedAt: streaming ? /* @__PURE__ */ new Date() : state.lastUpdatedAt
2173
+ };
2174
+ }
2175
+ default:
2176
+ return state;
2177
+ }
2178
+ }
2179
+ function GraphEmptyState({
2180
+ height = GRAPH_DEFAULT_HEIGHT,
2181
+ message = GRAPH_EMPTY_MESSAGE,
2182
+ description,
2183
+ className = ""
2184
+ }) {
2185
+ return /* @__PURE__ */ jsxs(
2186
+ "div",
2187
+ {
2188
+ className: `eui-graph flex flex-col items-center justify-center rounded-xl border border-dashed border-gray-700/80 bg-[#111217]/40 px-6 text-center ${className}`,
2189
+ style: { height },
2190
+ children: [
2191
+ /* @__PURE__ */ jsx("div", { className: "flex h-10 w-10 items-center justify-center rounded-full border border-gray-700 bg-white/5 text-gray-500", children: "\u2205" }),
2192
+ /* @__PURE__ */ jsx("div", { className: "mt-3 text-sm font-medium text-gray-300", children: message }),
2193
+ description && /* @__PURE__ */ jsx("div", { className: "mt-1 max-w-sm text-xs text-gray-500", children: description })
2194
+ ]
2195
+ }
2196
+ );
2197
+ }
2198
+ function GraphErrorState({
2199
+ error,
2200
+ height = GRAPH_DEFAULT_HEIGHT,
2201
+ title = GRAPH_ERROR_MESSAGE,
2202
+ message,
2203
+ className = "",
2204
+ onRetry,
2205
+ retryLabel = "Retry"
2206
+ }) {
2207
+ const resolvedMessage = message ?? error?.message;
2208
+ return /* @__PURE__ */ jsxs(
2209
+ "div",
2210
+ {
2211
+ className: `eui-graph flex flex-col items-center justify-center rounded-xl border border-red-500/30 bg-red-500/5 px-6 text-center ${className}`,
2212
+ style: { height },
2213
+ role: "alert",
2214
+ children: [
2215
+ /* @__PURE__ */ jsx("div", { className: "flex h-10 w-10 items-center justify-center rounded-full border border-red-500/30 bg-red-500/10 text-red-400", children: "!" }),
2216
+ /* @__PURE__ */ jsx("div", { className: "mt-3 text-sm font-medium text-red-300", children: title }),
2217
+ resolvedMessage && /* @__PURE__ */ jsx("div", { className: "mt-1 max-w-md text-xs text-red-200/70", children: resolvedMessage }),
2218
+ onRetry && /* @__PURE__ */ jsx(
2219
+ "button",
2220
+ {
2221
+ type: "button",
2222
+ onClick: () => void onRetry(),
2223
+ className: "mt-4 rounded-md border border-red-500/30 px-3 py-1.5 text-xs font-medium text-red-200 transition-colors hover:bg-red-500/10",
2224
+ children: retryLabel
2225
+ }
2226
+ )
2227
+ ]
2228
+ }
2229
+ );
2230
+ }
2231
+ function GraphHeader({
2232
+ title,
2233
+ description,
2234
+ actions,
2235
+ className = ""
2236
+ }) {
2237
+ if (!title && !description && !actions) {
2238
+ return null;
2239
+ }
2240
+ return /* @__PURE__ */ jsxs(
2241
+ "div",
2242
+ {
2243
+ className: `flex items-start justify-between gap-4 border-b border-[#2a2d35] px-4 py-3 ${className}`,
2244
+ children: [
2245
+ /* @__PURE__ */ jsxs("div", { className: "min-w-0", children: [
2246
+ title && /* @__PURE__ */ jsx("div", { className: "eui-graph-title truncate text-sm font-semibold text-gray-100", children: title }),
2247
+ description && /* @__PURE__ */ jsx("div", { className: "eui-graph-description mt-1 text-xs text-gray-400", children: description })
2248
+ ] }),
2249
+ actions && /* @__PURE__ */ jsx("div", { className: "shrink-0", children: actions })
2250
+ ]
2251
+ }
2252
+ );
2253
+ }
2254
+ function GraphLoadingState({
2255
+ height = GRAPH_DEFAULT_HEIGHT,
2256
+ message = GRAPH_LOADING_MESSAGE,
2257
+ className = "",
2258
+ showMessage = true
2259
+ }) {
2260
+ return /* @__PURE__ */ jsxs(
2261
+ "div",
2262
+ {
2263
+ className: `eui-graph eui-graph-loading flex flex-col items-center justify-center rounded-xl border border-[#2a2d35] bg-[#111217]/60 px-6 text-center ${className}`,
2264
+ style: { height },
2265
+ role: "status",
2266
+ "aria-live": "polite",
2267
+ "aria-busy": "true",
2268
+ children: [
2269
+ /* @__PURE__ */ jsx("div", { className: "h-7 w-7 animate-spin rounded-full border-2 border-gray-700 border-t-gray-200" }),
2270
+ showMessage && /* @__PURE__ */ jsx("span", { className: "mt-3 text-sm font-medium text-gray-300", children: message })
2271
+ ]
2272
+ }
2273
+ );
2274
+ }
2275
+ function formatLastUpdatedAt(value) {
2276
+ if (!value) {
2277
+ return "Never updated";
2278
+ }
2279
+ return `Updated ${value.toLocaleTimeString([], {
2280
+ hour: "2-digit",
2281
+ minute: "2-digit",
2282
+ second: "2-digit"
2283
+ })}`;
2284
+ }
2285
+ function GraphToolbar({
2286
+ children,
2287
+ className = "",
2288
+ showRefresh = true,
2289
+ showLastUpdated = true,
2290
+ refreshLabel = "Refresh",
2291
+ onRefresh
2292
+ }) {
2293
+ const graph = useGraphContext();
2294
+ async function handleRefresh() {
2295
+ if (onRefresh) {
2296
+ await onRefresh();
2297
+ return;
2298
+ }
2299
+ await graph.refresh();
2300
+ }
2301
+ if (!children && !showRefresh && !showLastUpdated) {
2302
+ return null;
2303
+ }
2304
+ return /* @__PURE__ */ jsxs(
2305
+ "div",
2306
+ {
2307
+ className: `flex flex-wrap items-center justify-between gap-3 border-b border-[#2a2d35] px-4 py-2 ${className}`,
2308
+ children: [
2309
+ /* @__PURE__ */ jsx("div", { className: "flex min-w-0 items-center gap-2", children }),
2310
+ /* @__PURE__ */ jsxs("div", { className: "ml-auto flex items-center gap-3", children: [
2311
+ showLastUpdated && /* @__PURE__ */ jsx("span", { className: "text-xs text-gray-500", children: formatLastUpdatedAt(graph.lastUpdatedAt) }),
2312
+ showRefresh && /* @__PURE__ */ jsx(
2313
+ "button",
2314
+ {
2315
+ type: "button",
2316
+ onClick: () => void handleRefresh(),
2317
+ disabled: graph.loading,
2318
+ className: "rounded-md border border-[#2a2d35] px-2.5 py-1.5 text-xs font-medium text-gray-300 transition-colors hover:bg-white/5 disabled:cursor-not-allowed disabled:opacity-60",
2319
+ children: graph.loading ? "Refreshing..." : refreshLabel
2320
+ }
2321
+ )
2322
+ ] })
2323
+ ]
2324
+ }
2325
+ );
2326
+ }
2327
+ function GraphPanel({
2328
+ title,
2329
+ description,
2330
+ actions,
2331
+ toolbar,
2332
+ children,
2333
+ className = "",
2334
+ contentClassName = "",
2335
+ height = GRAPH_DEFAULT_HEIGHT,
2336
+ loading,
2337
+ error,
2338
+ empty,
2339
+ emptyMessage,
2340
+ emptyDescription,
2341
+ showToolbar = false,
2342
+ showRefresh = true,
2343
+ showLastUpdated = true,
2344
+ onRetry
2345
+ }) {
2346
+ const graph = useGraphContext();
2347
+ const resolvedLoading = loading ?? graph.loading;
2348
+ const resolvedError = error ?? graph.error;
2349
+ const resolvedEmpty = empty ?? graph.data.length === 0;
2350
+ function renderContent() {
2351
+ if (resolvedLoading) {
2352
+ return /* @__PURE__ */ jsx(GraphLoadingState, { height });
2353
+ }
2354
+ if (resolvedError) {
2355
+ return /* @__PURE__ */ jsx(
2356
+ GraphErrorState,
2357
+ {
2358
+ height,
2359
+ error: resolvedError,
2360
+ onRetry: onRetry ?? graph.refresh
2361
+ }
2362
+ );
2363
+ }
2364
+ if (resolvedEmpty) {
2365
+ return /* @__PURE__ */ jsx(
2366
+ GraphEmptyState,
2367
+ {
2368
+ height,
2369
+ message: emptyMessage,
2370
+ description: emptyDescription
2371
+ }
2372
+ );
2373
+ }
2374
+ return children;
2375
+ }
2376
+ return /* @__PURE__ */ jsxs(
2377
+ "section",
2378
+ {
2379
+ className: `eui-graph eui-graph-panel overflow-hidden rounded-xl border border-[#2a2d35] bg-[#111217] ${className}`,
2380
+ children: [
2381
+ /* @__PURE__ */ jsx(GraphHeader, { title, description, actions }),
2382
+ showToolbar && /* @__PURE__ */ jsx(
2383
+ GraphToolbar,
2384
+ {
2385
+ showRefresh,
2386
+ showLastUpdated,
2387
+ children: toolbar
2388
+ }
2389
+ ),
2390
+ /* @__PURE__ */ jsx("div", { className: `p-4 ${contentClassName}`, children: renderContent() })
2391
+ ]
2392
+ }
2393
+ );
2394
+ }
2395
+ function createLabelFromKey2(key) {
2396
+ return key.replace(/[_-]+/g, " ").replace(/([a-z])([A-Z])/g, "$1 $2").replace(/\b\w/g, (character) => character.toUpperCase());
2397
+ }
2398
+ function GraphLegend({
2399
+ items,
2400
+ series,
2401
+ data = [],
2402
+ className = "",
2403
+ showValues = true,
2404
+ valueSource = "latest",
2405
+ onItemClick
2406
+ }) {
2407
+ const legendItems = useMemo(() => {
2408
+ if (items?.length) {
2409
+ return items;
2410
+ }
2411
+ if (!series?.length) {
2412
+ return [];
2413
+ }
2414
+ const latestPoint = data[data.length - 1];
2415
+ return series.map((item, index) => ({
2416
+ key: item.key,
2417
+ label: item.label ?? createLabelFromKey2(item.key),
2418
+ color: resolveGraphColor(item.color, { index }),
2419
+ value: valueSource === "latest" ? latestPoint?.[item.key] : void 0,
2420
+ unit: item.unit,
2421
+ format: item.format,
2422
+ prefix: item.prefix,
2423
+ suffix: item.suffix,
2424
+ active: item.visible ?? true
2425
+ }));
2426
+ }, [data, items, series, valueSource]);
2427
+ if (!legendItems.length) {
2428
+ return null;
2429
+ }
2430
+ return /* @__PURE__ */ jsx(
2431
+ "div",
2432
+ {
2433
+ className: `eui-graph flex flex-wrap items-center gap-x-4 gap-y-2 text-xs ${className}`,
2434
+ children: legendItems.map((item, index) => {
2435
+ const color = resolveGraphColor(item.color, { index });
2436
+ const active = item.active ?? true;
2437
+ return /* @__PURE__ */ jsxs(
2438
+ "button",
2439
+ {
2440
+ type: "button",
2441
+ onClick: () => onItemClick?.(item),
2442
+ disabled: !onItemClick,
2443
+ className: `inline-flex items-center gap-2 rounded-md transition-opacity ${active ? "opacity-100" : "opacity-40"} ${onItemClick ? "cursor-pointer hover:opacity-80" : "cursor-default"}`,
2444
+ children: [
2445
+ /* @__PURE__ */ jsx(
2446
+ "span",
2447
+ {
2448
+ className: "h-2.5 w-2.5 rounded-full",
2449
+ style: { backgroundColor: color }
2450
+ }
2451
+ ),
2452
+ /* @__PURE__ */ jsx("span", { className: "text-gray-400", children: item.label ?? createLabelFromKey2(item.key) }),
2453
+ showValues && item.value !== void 0 && /* @__PURE__ */ jsx("span", { className: "font-medium text-gray-200", children: formatGraphValue(item.value, {
2454
+ format: item.format ?? "number",
2455
+ prefix: item.prefix,
2456
+ suffix: item.suffix ?? item.unit
2457
+ }) })
2458
+ ]
2459
+ },
2460
+ item.key
2461
+ );
2462
+ })
2463
+ }
2464
+ );
2465
+ }
2466
+ function GraphTooltip({
2467
+ active,
2468
+ label,
2469
+ payload,
2470
+ className = "",
2471
+ labelFormatter,
2472
+ valueFormatter,
2473
+ seriesFormatters = {}
2474
+ }) {
2475
+ if (!active || !payload?.length) {
2476
+ return null;
2477
+ }
2478
+ return /* @__PURE__ */ jsxs(
2479
+ "div",
2480
+ {
2481
+ className: `eui-graph rounded-xl border border-[#2a2d35] bg-[#181b21] px-3 py-2 shadow-xl ${className}`,
2482
+ children: [
2483
+ label !== void 0 && /* @__PURE__ */ jsx("div", { className: "mb-2 text-xs font-semibold text-gray-100", children: labelFormatter ? labelFormatter(label) : label }),
2484
+ /* @__PURE__ */ jsx("div", { className: "flex flex-col gap-1.5", children: payload.map((item, index) => {
2485
+ const dataKey = item.dataKey ?? item.name ?? String(index);
2486
+ const formatterOptions = seriesFormatters[dataKey];
2487
+ const formattedValue = valueFormatter ? valueFormatter(item.value, item.name, item) : formatGraphValue(item.value, {
2488
+ format: formatterOptions?.format ?? "number",
2489
+ prefix: formatterOptions?.prefix,
2490
+ suffix: formatterOptions?.suffix ?? formatterOptions?.unit
2491
+ });
2492
+ return /* @__PURE__ */ jsxs(
2493
+ "div",
2494
+ {
2495
+ className: "flex min-w-[140px] items-center justify-between gap-4 text-xs",
2496
+ children: [
2497
+ /* @__PURE__ */ jsxs("div", { className: "flex min-w-0 items-center gap-2", children: [
2498
+ /* @__PURE__ */ jsx(
2499
+ "span",
2500
+ {
2501
+ className: "h-2 w-2 rounded-full",
2502
+ style: { backgroundColor: item.color }
2503
+ }
2504
+ ),
2505
+ /* @__PURE__ */ jsx("span", { className: "truncate text-gray-400", children: item.name ?? dataKey })
2506
+ ] }),
2507
+ /* @__PURE__ */ jsx("span", { className: "font-medium text-gray-100", children: formattedValue })
2508
+ ]
2509
+ },
2510
+ `${dataKey}-${index}`
2511
+ );
2512
+ }) })
2513
+ ]
2514
+ }
2515
+ );
2516
+ }
2517
+ function GraphContainer({
2518
+ children,
2519
+ height = GRAPH_DEFAULT_HEIGHT,
2520
+ className = "",
2521
+ contentClassName = ""
2522
+ }) {
2523
+ return /* @__PURE__ */ jsx(
2524
+ "div",
2525
+ {
2526
+ className: `eui-graph relative w-full min-w-0 overflow-hidden ${className}`,
2527
+ style: { height },
2528
+ children: /* @__PURE__ */ jsx("div", { className: `h-full w-full ${contentClassName}`, children })
2529
+ }
2530
+ );
2531
+ }
2532
+ function LineGraph({
2533
+ data,
2534
+ xKey = "time",
2535
+ series,
2536
+ height = GRAPH_DEFAULT_HEIGHT,
2537
+ loading,
2538
+ error,
2539
+ className = "",
2540
+ showGrid = true,
2541
+ showTooltip = true,
2542
+ showLegend = true,
2543
+ animated = true
2544
+ }) {
2545
+ const context = useGraphContext();
2546
+ const theme = useGraphTheme();
2547
+ const graphData = data ?? context.data;
2548
+ const graphLoading = loading ?? context.loading;
2549
+ const graphError = error ?? context.error;
2550
+ const resolvedSeries = useGraphSeries({
2551
+ data: graphData,
2552
+ series,
2553
+ xKey: String(xKey)
2554
+ }).filter((item) => item.visible);
2555
+ if (graphLoading) {
2556
+ return /* @__PURE__ */ jsx(GraphLoadingState, { height, className });
2557
+ }
2558
+ if (graphError) {
2559
+ return /* @__PURE__ */ jsx(
2560
+ GraphErrorState,
2561
+ {
2562
+ error: graphError,
2563
+ height,
2564
+ className
2565
+ }
2566
+ );
2567
+ }
2568
+ if (!graphData.length || !resolvedSeries.length) {
2569
+ return /* @__PURE__ */ jsx(GraphEmptyState, { height, className });
2570
+ }
2571
+ return /* @__PURE__ */ jsxs("div", { className: `eui-graph flex w-full flex-col gap-3 ${className}`, children: [
2572
+ /* @__PURE__ */ jsx(GraphContainer, { height, children: /* @__PURE__ */ jsx(ResponsiveContainer, { width: "100%", height: "100%", children: /* @__PURE__ */ jsxs(LineChart$1, { data: graphData, margin: GRAPH_DEFAULT_MARGIN, children: [
2573
+ showGrid && /* @__PURE__ */ jsx(
2574
+ CartesianGrid,
2575
+ {
2576
+ stroke: theme.chart.grid,
2577
+ strokeDasharray: "3 3",
2578
+ vertical: false
2579
+ }
2580
+ ),
2581
+ /* @__PURE__ */ jsx(
2582
+ XAxis,
2583
+ {
2584
+ dataKey: String(xKey),
2585
+ stroke: theme.chart.axis,
2586
+ tick: { fill: theme.chart.axis, fontSize: 12 },
2587
+ tickLine: false,
2588
+ axisLine: false
2589
+ }
2590
+ ),
2591
+ /* @__PURE__ */ jsx(
2592
+ YAxis,
2593
+ {
2594
+ stroke: theme.chart.axis,
2595
+ tick: { fill: theme.chart.axis, fontSize: 12 },
2596
+ tickLine: false,
2597
+ axisLine: false,
2598
+ tickFormatter: (value) => formatGraphValue(value, {
2599
+ format: "compact"
2600
+ })
2601
+ }
2602
+ ),
2603
+ showTooltip && /* @__PURE__ */ jsx(
2604
+ Tooltip$1,
2605
+ {
2606
+ content: /* @__PURE__ */ jsx(
2607
+ GraphTooltip,
2608
+ {
2609
+ seriesFormatters: Object.fromEntries(
2610
+ resolvedSeries.map((item) => [
2611
+ item.key,
2612
+ {
2613
+ format: item.format,
2614
+ prefix: item.prefix,
2615
+ suffix: item.suffix,
2616
+ unit: item.unit
2617
+ }
2618
+ ])
2619
+ )
2620
+ }
2621
+ ),
2622
+ cursor: { stroke: theme.chart.cursor }
2623
+ }
2624
+ ),
2625
+ resolvedSeries.map((item) => /* @__PURE__ */ jsx(
2626
+ Line$1,
2627
+ {
2628
+ type: "monotone",
2629
+ dataKey: item.key,
2630
+ name: item.label,
2631
+ stroke: item.color,
2632
+ strokeWidth: item.strokeWidth,
2633
+ dot: false,
2634
+ activeDot: { r: item.radius },
2635
+ isAnimationActive: animated,
2636
+ animationDuration: GRAPH_DEFAULT_ANIMATION_DURATION,
2637
+ yAxisId: item.yAxisId
2638
+ },
2639
+ item.key
2640
+ ))
2641
+ ] }) }) }),
2642
+ showLegend && /* @__PURE__ */ jsx(
2643
+ GraphLegend,
2644
+ {
2645
+ series: resolvedSeries,
2646
+ data: graphData,
2647
+ showValues: true,
2648
+ valueSource: "latest"
2649
+ }
2650
+ )
2651
+ ] });
2652
+ }
2653
+ function AreaGraph({
2654
+ data,
2655
+ xKey = "time",
2656
+ series,
2657
+ height = GRAPH_DEFAULT_HEIGHT,
2658
+ loading,
2659
+ error,
2660
+ className = "",
2661
+ showGrid = true,
2662
+ showTooltip = true,
2663
+ showLegend = true,
2664
+ animated = true
2665
+ }) {
2666
+ const context = useGraphContext();
2667
+ const theme = useGraphTheme();
2668
+ const graphData = data ?? context.data;
2669
+ const graphLoading = loading ?? context.loading;
2670
+ const graphError = error ?? context.error;
2671
+ const resolvedSeries = useGraphSeries({
2672
+ data: graphData,
2673
+ series,
2674
+ xKey: String(xKey)
2675
+ }).filter((item) => item.visible);
2676
+ if (graphLoading) {
2677
+ return /* @__PURE__ */ jsx(GraphLoadingState, { height, className });
2678
+ }
2679
+ if (graphError) {
2680
+ return /* @__PURE__ */ jsx(
2681
+ GraphErrorState,
2682
+ {
2683
+ error: graphError,
2684
+ height,
2685
+ className
2686
+ }
2687
+ );
2688
+ }
2689
+ if (!graphData.length || !resolvedSeries.length) {
2690
+ return /* @__PURE__ */ jsx(GraphEmptyState, { height, className });
2691
+ }
2692
+ return /* @__PURE__ */ jsxs("div", { className: `eui-graph flex w-full flex-col gap-3 ${className}`, children: [
2693
+ /* @__PURE__ */ jsx(GraphContainer, { height, children: /* @__PURE__ */ jsx(ResponsiveContainer, { width: "100%", height: "100%", children: /* @__PURE__ */ jsxs(AreaChart, { data: graphData, margin: GRAPH_DEFAULT_MARGIN, children: [
2694
+ /* @__PURE__ */ jsx("defs", { children: resolvedSeries.map((item) => /* @__PURE__ */ jsxs(
2695
+ "linearGradient",
2696
+ {
2697
+ id: `eui-area-gradient-${item.key}`,
2698
+ x1: "0",
2699
+ y1: "0",
2700
+ x2: "0",
2701
+ y2: "1",
2702
+ children: [
2703
+ /* @__PURE__ */ jsx("stop", { offset: "5%", stopColor: item.color, stopOpacity: 0.35 }),
2704
+ /* @__PURE__ */ jsx(
2705
+ "stop",
2706
+ {
2707
+ offset: "95%",
2708
+ stopColor: item.color,
2709
+ stopOpacity: 0.02
2710
+ }
2711
+ )
2712
+ ]
2713
+ },
2714
+ item.key
2715
+ )) }),
2716
+ showGrid && /* @__PURE__ */ jsx(
2717
+ CartesianGrid,
2718
+ {
2719
+ stroke: theme.chart.grid,
2720
+ strokeDasharray: "3 3",
2721
+ vertical: false
2722
+ }
2723
+ ),
2724
+ /* @__PURE__ */ jsx(
2725
+ XAxis,
2726
+ {
2727
+ dataKey: String(xKey),
2728
+ stroke: theme.chart.axis,
2729
+ tick: { fill: theme.chart.axis, fontSize: 12 },
2730
+ tickLine: false,
2731
+ axisLine: false
2732
+ }
2733
+ ),
2734
+ /* @__PURE__ */ jsx(
2735
+ YAxis,
2736
+ {
2737
+ stroke: theme.chart.axis,
2738
+ tick: { fill: theme.chart.axis, fontSize: 12 },
2739
+ tickLine: false,
2740
+ axisLine: false,
2741
+ tickFormatter: (value) => formatGraphValue(value, {
2742
+ format: "compact"
2743
+ })
2744
+ }
2745
+ ),
2746
+ showTooltip && /* @__PURE__ */ jsx(
2747
+ Tooltip$1,
2748
+ {
2749
+ content: /* @__PURE__ */ jsx(
2750
+ GraphTooltip,
2751
+ {
2752
+ seriesFormatters: Object.fromEntries(
2753
+ resolvedSeries.map((item) => [
2754
+ item.key,
2755
+ {
2756
+ format: item.format,
2757
+ prefix: item.prefix,
2758
+ suffix: item.suffix,
2759
+ unit: item.unit
2760
+ }
2761
+ ])
2762
+ )
2763
+ }
2764
+ ),
2765
+ cursor: { stroke: theme.chart.cursor }
2766
+ }
2767
+ ),
2768
+ resolvedSeries.map((item) => /* @__PURE__ */ jsx(
2769
+ Area,
2770
+ {
2771
+ type: "monotone",
2772
+ dataKey: item.key,
2773
+ name: item.label,
2774
+ stroke: item.color,
2775
+ strokeWidth: item.strokeWidth,
2776
+ fill: `url(#eui-area-gradient-${item.key})`,
2777
+ isAnimationActive: animated,
2778
+ animationDuration: GRAPH_DEFAULT_ANIMATION_DURATION,
2779
+ yAxisId: item.yAxisId
2780
+ },
2781
+ item.key
2782
+ ))
2783
+ ] }) }) }),
2784
+ showLegend && /* @__PURE__ */ jsx(
2785
+ GraphLegend,
2786
+ {
2787
+ series: resolvedSeries,
2788
+ data: graphData,
2789
+ showValues: true,
2790
+ valueSource: "latest"
2791
+ }
2792
+ )
2793
+ ] });
2794
+ }
2795
+ function BarGraph({
2796
+ data,
2797
+ xKey = "name",
2798
+ series,
2799
+ height = GRAPH_DEFAULT_HEIGHT,
2800
+ loading,
2801
+ error,
2802
+ className = "",
2803
+ showGrid = true,
2804
+ showTooltip = true,
2805
+ showLegend = true,
2806
+ animated = true,
2807
+ layout = "horizontal"
2808
+ }) {
2809
+ const context = useGraphContext();
2810
+ const theme = useGraphTheme();
2811
+ const graphData = data ?? context.data;
2812
+ const graphLoading = loading ?? context.loading;
2813
+ const graphError = error ?? context.error;
2814
+ const resolvedSeries = useGraphSeries({
2815
+ data: graphData,
2816
+ series,
2817
+ xKey: String(xKey)
2818
+ }).filter((item) => item.visible);
2819
+ if (graphLoading) {
2820
+ return /* @__PURE__ */ jsx(GraphLoadingState, { height, className });
2821
+ }
2822
+ if (graphError) {
2823
+ return /* @__PURE__ */ jsx(
2824
+ GraphErrorState,
2825
+ {
2826
+ error: graphError,
2827
+ height,
2828
+ className
2829
+ }
2830
+ );
2831
+ }
2832
+ if (!graphData.length || !resolvedSeries.length) {
2833
+ return /* @__PURE__ */ jsx(GraphEmptyState, { height, className });
2834
+ }
2835
+ const isVertical = layout === "vertical";
2836
+ return /* @__PURE__ */ jsxs("div", { className: `eui-graph flex w-full flex-col gap-3 ${className}`, children: [
2837
+ /* @__PURE__ */ jsx(GraphContainer, { height, children: /* @__PURE__ */ jsx(ResponsiveContainer, { width: "100%", height: "100%", children: /* @__PURE__ */ jsxs(
2838
+ BarChart$1,
2839
+ {
2840
+ data: graphData,
2841
+ margin: GRAPH_DEFAULT_MARGIN,
2842
+ layout: isVertical ? "vertical" : "horizontal",
2843
+ children: [
2844
+ showGrid && /* @__PURE__ */ jsx(
2845
+ CartesianGrid,
2846
+ {
2847
+ stroke: theme.chart.grid,
2848
+ strokeDasharray: "3 3",
2849
+ horizontal: !isVertical,
2850
+ vertical: isVertical
2851
+ }
2852
+ ),
2853
+ isVertical ? /* @__PURE__ */ jsxs(Fragment, { children: [
2854
+ /* @__PURE__ */ jsx(
2855
+ XAxis,
2856
+ {
2857
+ type: "number",
2858
+ stroke: theme.chart.axis,
2859
+ tick: { fill: theme.chart.axis, fontSize: 12 },
2860
+ tickLine: false,
2861
+ axisLine: false,
2862
+ tickFormatter: (value) => formatGraphValue(value, {
2863
+ format: "compact"
2864
+ })
2865
+ }
2866
+ ),
2867
+ /* @__PURE__ */ jsx(
2868
+ YAxis,
2869
+ {
2870
+ type: "category",
2871
+ dataKey: String(xKey),
2872
+ stroke: theme.chart.axis,
2873
+ tick: { fill: theme.chart.axis, fontSize: 12 },
2874
+ tickLine: false,
2875
+ axisLine: false,
2876
+ width: 110
2877
+ }
2878
+ )
2879
+ ] }) : /* @__PURE__ */ jsxs(Fragment, { children: [
2880
+ /* @__PURE__ */ jsx(
2881
+ XAxis,
2882
+ {
2883
+ dataKey: String(xKey),
2884
+ stroke: theme.chart.axis,
2885
+ tick: { fill: theme.chart.axis, fontSize: 12 },
2886
+ tickLine: false,
2887
+ axisLine: false
2888
+ }
2889
+ ),
2890
+ /* @__PURE__ */ jsx(
2891
+ YAxis,
2892
+ {
2893
+ stroke: theme.chart.axis,
2894
+ tick: { fill: theme.chart.axis, fontSize: 12 },
2895
+ tickLine: false,
2896
+ axisLine: false,
2897
+ tickFormatter: (value) => formatGraphValue(value, {
2898
+ format: "compact"
2899
+ })
2900
+ }
2901
+ )
2902
+ ] }),
2903
+ showTooltip && /* @__PURE__ */ jsx(
2904
+ Tooltip$1,
2905
+ {
2906
+ content: /* @__PURE__ */ jsx(
2907
+ GraphTooltip,
2908
+ {
2909
+ seriesFormatters: Object.fromEntries(
2910
+ resolvedSeries.map((item) => [
2911
+ item.key,
2912
+ {
2913
+ format: item.format,
2914
+ prefix: item.prefix,
2915
+ suffix: item.suffix,
2916
+ unit: item.unit
2917
+ }
2918
+ ])
2919
+ )
2920
+ }
2921
+ ),
2922
+ cursor: { fill: theme.chart.cursor }
2923
+ }
2924
+ ),
2925
+ resolvedSeries.map((item) => /* @__PURE__ */ jsx(
2926
+ Bar$1,
2927
+ {
2928
+ dataKey: item.key,
2929
+ name: item.label,
2930
+ fill: item.color,
2931
+ radius: GRAPH_DEFAULT_BAR_RADIUS,
2932
+ isAnimationActive: animated,
2933
+ animationDuration: GRAPH_DEFAULT_ANIMATION_DURATION,
2934
+ yAxisId: isVertical ? void 0 : item.yAxisId
2935
+ },
2936
+ item.key
2937
+ ))
2938
+ ]
2939
+ }
2940
+ ) }) }),
2941
+ showLegend && /* @__PURE__ */ jsx(
2942
+ GraphLegend,
2943
+ {
2944
+ series: resolvedSeries,
2945
+ data: graphData,
2946
+ showValues: true,
2947
+ valueSource: "latest"
2948
+ }
2949
+ )
2950
+ ] });
2951
+ }
2952
+ function PieGraph({
2953
+ data,
2954
+ nameKey = "name",
2955
+ valueKey = "value",
2956
+ height = GRAPH_DEFAULT_HEIGHT,
2957
+ loading,
2958
+ error,
2959
+ className = "",
2960
+ showTooltip = true,
2961
+ showLegend = true,
2962
+ animated = true,
2963
+ innerRadius = "45%",
2964
+ outerRadius = "75%",
2965
+ valueFormat = "number",
2966
+ unit
2967
+ }) {
2968
+ const context = useGraphContext();
2969
+ const theme = useGraphTheme();
2970
+ const graphData = data ?? context.data;
2971
+ const graphLoading = loading ?? context.loading;
2972
+ const graphError = error ?? context.error;
2973
+ if (graphLoading) {
2974
+ return /* @__PURE__ */ jsx(GraphLoadingState, { height, className });
2975
+ }
2976
+ if (graphError) {
2977
+ return /* @__PURE__ */ jsx(
2978
+ GraphErrorState,
2979
+ {
2980
+ error: graphError,
2981
+ height,
2982
+ className
2983
+ }
2984
+ );
2985
+ }
2986
+ if (!graphData.length) {
2987
+ return /* @__PURE__ */ jsx(GraphEmptyState, { height, className });
2988
+ }
2989
+ const legendItems = graphData.map((item, index) => {
2990
+ const key = String(item[String(nameKey)] ?? index);
1390
2991
  return {
1391
- ...node,
1392
- x: (index + 1) * width / (siblings.length + 1),
1393
- y: (level + 1) * height / (maxLevel + 2)
2992
+ key,
2993
+ label: key,
2994
+ value: item[String(valueKey)],
2995
+ color: resolveGraphColor(void 0, {
2996
+ index,
2997
+ palette: theme.colors
2998
+ }),
2999
+ format: valueFormat,
3000
+ unit,
3001
+ active: true
1394
3002
  };
1395
3003
  });
3004
+ return /* @__PURE__ */ jsxs("div", { className: `eui-graph flex w-full flex-col gap-3 ${className}`, children: [
3005
+ /* @__PURE__ */ jsx(GraphContainer, { height, children: /* @__PURE__ */ jsx(ResponsiveContainer, { width: "100%", height: "100%", children: /* @__PURE__ */ jsxs(PieChart$1, { children: [
3006
+ /* @__PURE__ */ jsx(
3007
+ Pie$1,
3008
+ {
3009
+ data: graphData,
3010
+ dataKey: String(valueKey),
3011
+ nameKey: String(nameKey),
3012
+ innerRadius,
3013
+ outerRadius,
3014
+ paddingAngle: 2,
3015
+ isAnimationActive: animated,
3016
+ animationDuration: GRAPH_DEFAULT_ANIMATION_DURATION,
3017
+ children: graphData.map((_item, index) => /* @__PURE__ */ jsx(
3018
+ Cell,
3019
+ {
3020
+ fill: resolveGraphColor(void 0, {
3021
+ index,
3022
+ palette: theme.colors
3023
+ })
3024
+ },
3025
+ `cell-${index}`
3026
+ ))
3027
+ }
3028
+ ),
3029
+ showTooltip && /* @__PURE__ */ jsx(
3030
+ Tooltip$1,
3031
+ {
3032
+ content: /* @__PURE__ */ jsx(
3033
+ GraphTooltip,
3034
+ {
3035
+ seriesFormatters: {
3036
+ [String(valueKey)]: {
3037
+ format: valueFormat,
3038
+ suffix: unit
3039
+ }
3040
+ }
3041
+ }
3042
+ )
3043
+ }
3044
+ )
3045
+ ] }) }) }),
3046
+ showLegend && /* @__PURE__ */ jsx(GraphLegend, { items: legendItems, showValues: true, valueSource: "latest" })
3047
+ ] });
1396
3048
  }
1397
- var NODE_SIZE = 48;
1398
- var GraphNode = ({ node, renderCustom }) => {
1399
- if (node.x === void 0 || node.y === void 0) return null;
1400
- const x = node.x;
1401
- const y = node.y;
1402
- if (renderCustom) {
3049
+ function ScatterGraph({
3050
+ data,
3051
+ xKey = "x",
3052
+ series,
3053
+ height = GRAPH_DEFAULT_HEIGHT,
3054
+ loading,
3055
+ error,
3056
+ className = "",
3057
+ showGrid = true,
3058
+ showTooltip = true,
3059
+ showLegend = true,
3060
+ animated = true
3061
+ }) {
3062
+ const context = useGraphContext();
3063
+ const theme = useGraphTheme();
3064
+ const graphData = data ?? context.data;
3065
+ const graphLoading = loading ?? context.loading;
3066
+ const graphError = error ?? context.error;
3067
+ const resolvedSeries = useGraphSeries({
3068
+ data: graphData,
3069
+ series,
3070
+ xKey: String(xKey)
3071
+ }).filter((item) => item.visible);
3072
+ if (graphLoading) {
3073
+ return /* @__PURE__ */ jsx(GraphLoadingState, { height, className });
3074
+ }
3075
+ if (graphError) {
1403
3076
  return /* @__PURE__ */ jsx(
1404
- "foreignObject",
3077
+ GraphErrorState,
1405
3078
  {
1406
- x: x - NODE_SIZE / 2,
1407
- y: y - NODE_SIZE / 2,
1408
- width: NODE_SIZE,
1409
- height: NODE_SIZE,
1410
- style: { overflow: "visible" },
1411
- children: /* @__PURE__ */ jsx(
1412
- "div",
1413
- {
1414
- style: {
1415
- width: NODE_SIZE,
1416
- height: NODE_SIZE,
1417
- display: "flex",
1418
- alignItems: "center",
1419
- justifyContent: "center"
1420
- },
1421
- children: renderCustom(node)
1422
- }
1423
- )
3079
+ error: graphError,
3080
+ height,
3081
+ className
1424
3082
  }
1425
3083
  );
1426
3084
  }
1427
- return /* @__PURE__ */ jsxs("g", { transform: `translate(${x}, ${y})`, children: [
1428
- /* @__PURE__ */ jsx("circle", { r: 16, fill: "#4f46e5" }),
1429
- node.label && /* @__PURE__ */ jsx(
1430
- "text",
3085
+ if (!graphData.length || !resolvedSeries.length) {
3086
+ return /* @__PURE__ */ jsx(GraphEmptyState, { height, className });
3087
+ }
3088
+ return /* @__PURE__ */ jsxs("div", { className: `eui-graph flex w-full flex-col gap-3 ${className}`, children: [
3089
+ /* @__PURE__ */ jsx(GraphContainer, { height, children: /* @__PURE__ */ jsx(ResponsiveContainer, { width: "100%", height: "100%", children: /* @__PURE__ */ jsxs(ScatterChart, { margin: GRAPH_DEFAULT_MARGIN, children: [
3090
+ showGrid && /* @__PURE__ */ jsx(CartesianGrid, { stroke: theme.chart.grid, strokeDasharray: "3 3" }),
3091
+ /* @__PURE__ */ jsx(
3092
+ XAxis,
3093
+ {
3094
+ type: "number",
3095
+ dataKey: String(xKey),
3096
+ name: String(xKey),
3097
+ stroke: theme.chart.axis,
3098
+ tick: { fill: theme.chart.axis, fontSize: 12 },
3099
+ tickLine: false,
3100
+ axisLine: false,
3101
+ tickFormatter: (value) => formatGraphValue(value, {
3102
+ format: "compact"
3103
+ })
3104
+ }
3105
+ ),
3106
+ /* @__PURE__ */ jsx(
3107
+ YAxis,
3108
+ {
3109
+ type: "number",
3110
+ stroke: theme.chart.axis,
3111
+ tick: { fill: theme.chart.axis, fontSize: 12 },
3112
+ tickLine: false,
3113
+ axisLine: false,
3114
+ tickFormatter: (value) => formatGraphValue(value, {
3115
+ format: "compact"
3116
+ })
3117
+ }
3118
+ ),
3119
+ showTooltip && /* @__PURE__ */ jsx(
3120
+ Tooltip$1,
3121
+ {
3122
+ content: /* @__PURE__ */ jsx(
3123
+ GraphTooltip,
3124
+ {
3125
+ seriesFormatters: Object.fromEntries(
3126
+ resolvedSeries.map((item) => [
3127
+ item.key,
3128
+ {
3129
+ format: item.format,
3130
+ prefix: item.prefix,
3131
+ suffix: item.suffix,
3132
+ unit: item.unit
3133
+ }
3134
+ ])
3135
+ )
3136
+ }
3137
+ ),
3138
+ cursor: { stroke: theme.chart.cursor, strokeDasharray: "3 3" }
3139
+ }
3140
+ ),
3141
+ resolvedSeries.map((item) => /* @__PURE__ */ jsx(
3142
+ Scatter,
3143
+ {
3144
+ data: graphData,
3145
+ dataKey: item.key,
3146
+ name: item.label,
3147
+ fill: item.color,
3148
+ isAnimationActive: animated,
3149
+ animationDuration: GRAPH_DEFAULT_ANIMATION_DURATION
3150
+ },
3151
+ item.key
3152
+ ))
3153
+ ] }) }) }),
3154
+ showLegend && /* @__PURE__ */ jsx(
3155
+ GraphLegend,
1431
3156
  {
1432
- y: 4,
1433
- textAnchor: "middle",
1434
- fontSize: "11",
1435
- fill: "white",
1436
- pointerEvents: "none",
1437
- children: node.label
3157
+ series: resolvedSeries,
3158
+ data: graphData,
3159
+ showValues: true,
3160
+ valueSource: "latest"
1438
3161
  }
1439
3162
  )
1440
3163
  ] });
1441
- };
1442
- function resolveNode(ref, map) {
1443
- return typeof ref === "string" ? map.get(ref) : ref;
1444
3164
  }
1445
- var GraphEdge = ({ edge, nodeMap }) => {
1446
- const source = resolveNode(edge.from, nodeMap);
1447
- const target = resolveNode(edge.to, nodeMap);
1448
- if (!source || !target) return null;
1449
- if (source.x == null || source.y == null) return null;
1450
- if (target.x == null || target.y == null) return null;
1451
- const labelX = (source.x + target.x) / 2;
1452
- const labelY = (source.y + target.y) / 2;
1453
- return /* @__PURE__ */ jsxs("g", { children: [
1454
- /* @__PURE__ */ jsx(
1455
- "line",
1456
- {
1457
- x1: source.x,
1458
- y1: source.y,
1459
- x2: target.x,
1460
- y2: target.y,
1461
- stroke: "#64748b",
1462
- strokeWidth: 1.5
1463
- }
1464
- ),
1465
- edge.weight && /* @__PURE__ */ jsx(
1466
- "text",
3165
+ function GaugeGraph({
3166
+ data,
3167
+ valueKey = "value",
3168
+ label,
3169
+ value,
3170
+ min = 0,
3171
+ max = 100,
3172
+ height = GRAPH_DEFAULT_HEIGHT,
3173
+ color,
3174
+ unit,
3175
+ format = "number",
3176
+ loading,
3177
+ error,
3178
+ className = ""
3179
+ }) {
3180
+ const context = useGraphContext();
3181
+ const theme = useGraphTheme();
3182
+ const graphData = data ?? context.data;
3183
+ const graphLoading = loading ?? context.loading;
3184
+ const graphError = error ?? context.error;
3185
+ const resolvedValue = useMemo(() => {
3186
+ if (typeof value === "number") {
3187
+ return value;
3188
+ }
3189
+ const latestPoint = graphData[graphData.length - 1];
3190
+ const latestValue = latestPoint?.[String(valueKey)];
3191
+ return typeof latestValue === "number" ? latestValue : void 0;
3192
+ }, [graphData, value, valueKey]);
3193
+ if (graphLoading) {
3194
+ return /* @__PURE__ */ jsx(GraphLoadingState, { height, className });
3195
+ }
3196
+ if (graphError) {
3197
+ return /* @__PURE__ */ jsx(
3198
+ GraphErrorState,
1467
3199
  {
1468
- x: labelX,
1469
- y: labelY - 4,
1470
- textAnchor: "middle",
1471
- fontSize: 10,
1472
- fill: "#e5e7eb",
1473
- children: edge.weight
3200
+ error: graphError,
3201
+ height,
3202
+ className
1474
3203
  }
1475
- )
1476
- ] });
1477
- };
1478
- var GraphRenderer = ({
1479
- data,
1480
- layout = "force",
1481
- nodeRenderer,
1482
- width = 1e3,
1483
- height = 700
1484
- }) => {
1485
- const [nodes, setNodes] = useState([]);
1486
- const edges = data.edges;
1487
- const simulationRef = useRef(null);
1488
- const [offset, setOffset] = useState({ x: 0, y: 0 });
1489
- const isDragging = useRef(false);
1490
- const lastPos = useRef({ x: 0, y: 0 });
1491
- const nodeMap = useMemo(() => {
1492
- return new Map(nodes.map((n) => [n.id, n]));
1493
- }, [nodes]);
1494
- useEffect(() => {
1495
- simulationRef.current?.stop?.();
1496
- const positionedNodes = data.nodes.map((n) => ({
1497
- ...n,
1498
- x: width / 2,
1499
- y: height / 2
1500
- }));
1501
- const executor = getLayout(layout);
1502
- const instance = executor({
1503
- nodes: positionedNodes,
1504
- edges,
1505
- width,
1506
- height,
1507
- onTick: setNodes
1508
- });
1509
- simulationRef.current = instance;
1510
- return () => instance.stop?.();
1511
- }, [data, layout, width, height]);
1512
- const onMouseDown = (e) => {
1513
- isDragging.current = true;
1514
- lastPos.current = { x: e.clientX, y: e.clientY };
1515
- };
1516
- const onMouseMove = (e) => {
1517
- if (!isDragging.current) return;
1518
- const dx = e.clientX - lastPos.current.x;
1519
- const dy = e.clientY - lastPos.current.y;
1520
- setOffset((prev) => ({
1521
- x: prev.x + dx,
1522
- y: prev.y + dy
1523
- }));
1524
- lastPos.current = { x: e.clientX, y: e.clientY };
1525
- };
1526
- const stopDrag = () => isDragging.current = false;
1527
- return /* @__PURE__ */ jsx("div", { className: "relative overflow-hidden border border-gray-800 rounded-lg", children: /* @__PURE__ */ jsx(
1528
- "svg",
3204
+ );
3205
+ }
3206
+ if (resolvedValue === void 0) {
3207
+ return /* @__PURE__ */ jsx(GraphEmptyState, { height, className });
3208
+ }
3209
+ const range = max - min;
3210
+ const percentage = range === 0 ? 0 : Math.min(100, Math.max(0, (resolvedValue - min) / range * 100));
3211
+ const radius = 72;
3212
+ const strokeWidth = 14;
3213
+ const circumference = Math.PI * radius;
3214
+ const offset = circumference - percentage / 100 * circumference;
3215
+ const resolvedColor = resolveGraphColor(color, {
3216
+ index: 0,
3217
+ palette: theme.colors
3218
+ });
3219
+ return /* @__PURE__ */ jsx(
3220
+ "div",
1529
3221
  {
1530
- width: "100%",
1531
- height,
1532
- viewBox: `0 0 ${width} ${height}`,
1533
- onMouseDown,
1534
- onMouseMove,
1535
- onMouseUp: stopDrag,
1536
- onMouseLeave: stopDrag,
1537
- style: {
1538
- cursor: isDragging.current ? "grabbing" : "grab"
1539
- },
1540
- children: /* @__PURE__ */ jsxs("g", { transform: `translate(${offset.x}, ${offset.y})`, children: [
1541
- edges.map((edge, i) => /* @__PURE__ */ jsx(GraphEdge, { edge, nodeMap }, edge.id || i)),
1542
- nodes.map((node) => /* @__PURE__ */ jsx(GraphNode, { node, renderCustom: nodeRenderer }, node.id))
3222
+ className: `eui-graph flex items-center justify-center ${className}`,
3223
+ style: { height },
3224
+ children: /* @__PURE__ */ jsxs("div", { className: "flex flex-col items-center gap-3", children: [
3225
+ /* @__PURE__ */ jsxs("svg", { width: "220", height: "130", viewBox: "0 0 220 130", children: [
3226
+ /* @__PURE__ */ jsx(
3227
+ "path",
3228
+ {
3229
+ d: "M 38 104 A 72 72 0 0 1 182 104",
3230
+ fill: "none",
3231
+ stroke: theme.chart.grid,
3232
+ strokeWidth,
3233
+ strokeLinecap: "round"
3234
+ }
3235
+ ),
3236
+ /* @__PURE__ */ jsx(
3237
+ "path",
3238
+ {
3239
+ d: "M 38 104 A 72 72 0 0 1 182 104",
3240
+ fill: "none",
3241
+ stroke: resolvedColor,
3242
+ strokeWidth,
3243
+ strokeLinecap: "round",
3244
+ strokeDasharray: circumference,
3245
+ strokeDashoffset: offset
3246
+ }
3247
+ ),
3248
+ /* @__PURE__ */ jsx(
3249
+ "text",
3250
+ {
3251
+ x: "110",
3252
+ y: "92",
3253
+ textAnchor: "middle",
3254
+ fill: theme.tooltip.text,
3255
+ fontSize: "28",
3256
+ fontWeight: "700",
3257
+ children: formatGraphValue(resolvedValue, {
3258
+ format,
3259
+ suffix: unit,
3260
+ maximumFractionDigits: 2
3261
+ })
3262
+ }
3263
+ ),
3264
+ label && /* @__PURE__ */ jsx(
3265
+ "text",
3266
+ {
3267
+ x: "110",
3268
+ y: "118",
3269
+ textAnchor: "middle",
3270
+ fill: theme.tooltip.muted,
3271
+ fontSize: "12",
3272
+ children: label
3273
+ }
3274
+ )
3275
+ ] }),
3276
+ /* @__PURE__ */ jsxs("div", { className: "flex w-full max-w-[180px] justify-between text-xs text-gray-500", children: [
3277
+ /* @__PURE__ */ jsx("span", { children: formatGraphValue(min, {
3278
+ format,
3279
+ suffix: unit
3280
+ }) }),
3281
+ /* @__PURE__ */ jsx("span", { children: formatGraphValue(max, {
3282
+ format,
3283
+ suffix: unit
3284
+ }) })
3285
+ ] })
1543
3286
  ] })
1544
3287
  }
1545
- ) });
1546
- };
1547
- var Graph = ({
3288
+ );
3289
+ }
3290
+ function StatGraph({
1548
3291
  data,
1549
- layout = "force",
1550
- nodeRenderer,
1551
- width = 800,
1552
- height = 500,
1553
- className,
1554
- ...rest
1555
- }) => {
1556
- return /* @__PURE__ */ jsx(
3292
+ valueKey = "value",
3293
+ label,
3294
+ value,
3295
+ previousValue,
3296
+ format = "number",
3297
+ prefix,
3298
+ suffix,
3299
+ unit,
3300
+ loading,
3301
+ error,
3302
+ className = "",
3303
+ showTrend = true
3304
+ }) {
3305
+ const context = useGraphContext();
3306
+ const graphData = data ?? context.data;
3307
+ const graphLoading = loading ?? context.loading;
3308
+ const graphError = error ?? context.error;
3309
+ const resolvedValue = useMemo(() => {
3310
+ if (value !== void 0) {
3311
+ return value;
3312
+ }
3313
+ const latestPoint = graphData[graphData.length - 1];
3314
+ return latestPoint?.[String(valueKey)] ?? null;
3315
+ }, [graphData, value, valueKey]);
3316
+ const resolvedPreviousValue = useMemo(() => {
3317
+ if (previousValue !== void 0) {
3318
+ return previousValue;
3319
+ }
3320
+ const previousPoint = graphData[graphData.length - 2];
3321
+ const previous = previousPoint?.[String(valueKey)];
3322
+ return typeof previous === "number" ? previous : void 0;
3323
+ }, [graphData, previousValue, valueKey]);
3324
+ const trend = useMemo(() => {
3325
+ if (typeof resolvedValue !== "number" || typeof resolvedPreviousValue !== "number") {
3326
+ return null;
3327
+ }
3328
+ const difference = resolvedValue - resolvedPreviousValue;
3329
+ const percentage = resolvedPreviousValue === 0 ? 0 : difference / Math.abs(resolvedPreviousValue) * 100;
3330
+ return {
3331
+ difference,
3332
+ percentage,
3333
+ direction: difference > 0 ? "up" : difference < 0 ? "down" : "neutral"
3334
+ };
3335
+ }, [resolvedPreviousValue, resolvedValue]);
3336
+ if (graphLoading) {
3337
+ return /* @__PURE__ */ jsx(GraphLoadingState, { height: 120, className });
3338
+ }
3339
+ if (graphError) {
3340
+ return /* @__PURE__ */ jsx(GraphErrorState, { error: graphError, height: 120, className });
3341
+ }
3342
+ if (resolvedValue === null || resolvedValue === void 0) {
3343
+ return /* @__PURE__ */ jsx(GraphEmptyState, { height: 120, className });
3344
+ }
3345
+ return /* @__PURE__ */ jsxs(
1557
3346
  "div",
1558
3347
  {
1559
- ...rest,
1560
- style: { width, height },
1561
- className: cn("relative bg-gray-900 rounded-lg", className),
1562
- children: /* @__PURE__ */ jsx(
1563
- GraphRenderer,
3348
+ className: `eui-graph rounded-xl border border-[#2a2d35] bg-[#111217] p-5 ${className}`,
3349
+ children: [
3350
+ label && /* @__PURE__ */ jsx("div", { className: "text-sm text-gray-400", children: label }),
3351
+ /* @__PURE__ */ jsx("div", { className: "mt-2 text-3xl font-semibold tracking-tight text-gray-100", children: formatGraphValue(resolvedValue, {
3352
+ format,
3353
+ prefix,
3354
+ suffix: suffix ?? unit
3355
+ }) }),
3356
+ showTrend && trend && /* @__PURE__ */ jsxs(
3357
+ "div",
3358
+ {
3359
+ className: `mt-3 text-sm ${trend.direction === "up" ? "text-emerald-400" : trend.direction === "down" ? "text-red-400" : "text-gray-500"}`,
3360
+ children: [
3361
+ trend.direction === "up" ? "\u2191" : trend.direction === "down" ? "\u2193" : "\u2192",
3362
+ " ",
3363
+ formatGraphValue(Math.abs(trend.percentage), {
3364
+ format: "number",
3365
+ suffix: "%",
3366
+ maximumFractionDigits: 2
3367
+ })
3368
+ ]
3369
+ }
3370
+ )
3371
+ ]
3372
+ }
3373
+ );
3374
+ }
3375
+ function renderGraphChart(props) {
3376
+ const {
3377
+ type = "line",
3378
+ data,
3379
+ xKey,
3380
+ series,
3381
+ height,
3382
+ loading,
3383
+ error,
3384
+ chartClassName = "",
3385
+ showGrid = true,
3386
+ showTooltip = true,
3387
+ showLegend = true,
3388
+ animated = true,
3389
+ layout,
3390
+ nameKey,
3391
+ valueKey,
3392
+ innerRadius,
3393
+ outerRadius,
3394
+ valueFormat,
3395
+ value,
3396
+ previousValue,
3397
+ label,
3398
+ min,
3399
+ max,
3400
+ color,
3401
+ unit,
3402
+ format,
3403
+ prefix,
3404
+ suffix,
3405
+ showTrend
3406
+ } = props;
3407
+ switch (type) {
3408
+ case "area":
3409
+ return /* @__PURE__ */ jsx(
3410
+ AreaGraph,
1564
3411
  {
1565
3412
  data,
1566
- layout,
1567
- nodeRenderer,
1568
- width,
1569
- height
3413
+ xKey,
3414
+ series,
3415
+ height,
3416
+ loading,
3417
+ error,
3418
+ className: chartClassName,
3419
+ showGrid,
3420
+ showTooltip,
3421
+ showLegend,
3422
+ animated
1570
3423
  }
1571
- )
3424
+ );
3425
+ case "bar":
3426
+ return /* @__PURE__ */ jsx(
3427
+ BarGraph,
3428
+ {
3429
+ data,
3430
+ xKey,
3431
+ series,
3432
+ height,
3433
+ loading,
3434
+ error,
3435
+ className: chartClassName,
3436
+ showGrid,
3437
+ showTooltip,
3438
+ showLegend,
3439
+ animated,
3440
+ layout
3441
+ }
3442
+ );
3443
+ case "pie":
3444
+ return /* @__PURE__ */ jsx(
3445
+ PieGraph,
3446
+ {
3447
+ data,
3448
+ nameKey,
3449
+ valueKey,
3450
+ height,
3451
+ loading,
3452
+ error,
3453
+ className: chartClassName,
3454
+ showTooltip,
3455
+ showLegend,
3456
+ animated,
3457
+ innerRadius,
3458
+ outerRadius,
3459
+ valueFormat,
3460
+ unit
3461
+ }
3462
+ );
3463
+ case "scatter":
3464
+ return /* @__PURE__ */ jsx(
3465
+ ScatterGraph,
3466
+ {
3467
+ data,
3468
+ xKey,
3469
+ series,
3470
+ height,
3471
+ loading,
3472
+ error,
3473
+ className: chartClassName,
3474
+ showGrid,
3475
+ showTooltip,
3476
+ showLegend,
3477
+ animated
3478
+ }
3479
+ );
3480
+ case "gauge":
3481
+ return /* @__PURE__ */ jsx(
3482
+ GaugeGraph,
3483
+ {
3484
+ data,
3485
+ valueKey,
3486
+ value: typeof value === "number" ? value : void 0,
3487
+ label,
3488
+ min,
3489
+ max,
3490
+ height,
3491
+ color,
3492
+ unit,
3493
+ format,
3494
+ loading,
3495
+ error,
3496
+ className: chartClassName
3497
+ }
3498
+ );
3499
+ case "stat":
3500
+ return /* @__PURE__ */ jsx(
3501
+ StatGraph,
3502
+ {
3503
+ data,
3504
+ valueKey,
3505
+ value,
3506
+ previousValue,
3507
+ label,
3508
+ format,
3509
+ prefix,
3510
+ suffix,
3511
+ unit,
3512
+ loading,
3513
+ error,
3514
+ className: chartClassName,
3515
+ showTrend
3516
+ }
3517
+ );
3518
+ case "line":
3519
+ default:
3520
+ return /* @__PURE__ */ jsx(
3521
+ LineGraph,
3522
+ {
3523
+ data,
3524
+ xKey,
3525
+ series,
3526
+ height,
3527
+ loading,
3528
+ error,
3529
+ className: chartClassName,
3530
+ showGrid,
3531
+ showTooltip,
3532
+ showLegend,
3533
+ animated
3534
+ }
3535
+ );
3536
+ }
3537
+ }
3538
+ function GraphContent(props) {
3539
+ const {
3540
+ children,
3541
+ withPanel = true,
3542
+ title,
3543
+ description,
3544
+ actions,
3545
+ toolbar,
3546
+ className = "",
3547
+ contentClassName = "",
3548
+ height,
3549
+ loading,
3550
+ error,
3551
+ showToolbar = false,
3552
+ showRefresh = true,
3553
+ showLastUpdated = true,
3554
+ emptyMessage,
3555
+ emptyDescription,
3556
+ onRetry
3557
+ } = props;
3558
+ const chart = children ?? renderGraphChart(props);
3559
+ if (!withPanel) {
3560
+ return /* @__PURE__ */ jsx(Fragment, { children: chart });
3561
+ }
3562
+ return /* @__PURE__ */ jsx(
3563
+ GraphPanel,
3564
+ {
3565
+ title,
3566
+ description,
3567
+ actions,
3568
+ toolbar,
3569
+ className,
3570
+ contentClassName,
3571
+ height,
3572
+ loading,
3573
+ error,
3574
+ empty: children ? false : void 0,
3575
+ showToolbar,
3576
+ showRefresh,
3577
+ showLastUpdated,
3578
+ emptyMessage,
3579
+ emptyDescription,
3580
+ onRetry,
3581
+ children: chart
3582
+ }
3583
+ );
3584
+ }
3585
+ function Graph(props) {
3586
+ const {
3587
+ data,
3588
+ dataSource,
3589
+ autoLoad = true,
3590
+ maxDataPoints,
3591
+ theme,
3592
+ onDataChange,
3593
+ onError
3594
+ } = props;
3595
+ const shouldUseProvider = Boolean(data || dataSource);
3596
+ const content = /* @__PURE__ */ jsx(GraphContent, { ...props });
3597
+ if (!shouldUseProvider) {
3598
+ return content;
3599
+ }
3600
+ return /* @__PURE__ */ jsx(
3601
+ GraphProvider,
3602
+ {
3603
+ data,
3604
+ dataSource,
3605
+ autoLoad,
3606
+ maxDataPoints,
3607
+ theme,
3608
+ onDataChange,
3609
+ onError,
3610
+ children: content
1572
3611
  }
1573
3612
  );
3613
+ }
3614
+
3615
+ // src/components/data-display/graphs-v2/datasource/GraphDataSource.ts
3616
+ var BaseGraphDataSource = class {
3617
+ normalizeError(error) {
3618
+ if (error instanceof Error) {
3619
+ return error;
3620
+ }
3621
+ return new Error(String(error));
3622
+ }
3623
+ ensureArray(data) {
3624
+ if (!data) {
3625
+ return [];
3626
+ }
3627
+ return Array.isArray(data) ? data : [data];
3628
+ }
3629
+ safeExecute(executor) {
3630
+ try {
3631
+ return Promise.resolve(executor());
3632
+ } catch (error) {
3633
+ return Promise.reject(this.normalizeError(error));
3634
+ }
3635
+ }
3636
+ };
3637
+
3638
+ // src/components/data-display/graphs-v2/datasource/StaticGraphDataSource.ts
3639
+ var StaticGraphDataSource = class extends BaseGraphDataSource {
3640
+ constructor(config = {}) {
3641
+ super();
3642
+ this.mode = GRAPH_DATA_MODES.STATIC;
3643
+ this.data = Array.isArray(config) ? config : config.data ?? [];
3644
+ }
3645
+ getInitialData() {
3646
+ return this.data;
3647
+ }
3648
+ refresh() {
3649
+ return this.data;
3650
+ }
3651
+ setData(data) {
3652
+ this.data = data;
3653
+ }
3654
+ appendData(data) {
3655
+ const nextData = this.ensureArray(data);
3656
+ this.data = [...this.data, ...nextData];
3657
+ }
3658
+ clearData() {
3659
+ this.data = [];
3660
+ }
3661
+ };
3662
+
3663
+ // src/components/data-display/graphs-v2/datasource/PollingGraphDataSource.ts
3664
+ var PollingGraphDataSource = class extends BaseGraphDataSource {
3665
+ constructor(config) {
3666
+ super();
3667
+ this.mode = GRAPH_DATA_MODES.POLLING;
3668
+ this.fetcher = config.fetcher;
3669
+ this.interval = config.interval ?? GRAPH_DEFAULT_POLLING_INTERVAL;
3670
+ this.immediate = config.immediate ?? true;
3671
+ }
3672
+ getInitialData() {
3673
+ return this.refresh();
3674
+ }
3675
+ refresh() {
3676
+ return this.safeExecute(async () => {
3677
+ const data = await this.fetcher();
3678
+ return this.ensureArray(data);
3679
+ });
3680
+ }
3681
+ subscribe(onData, onError) {
3682
+ let disposed = false;
3683
+ let fetching = false;
3684
+ let timer;
3685
+ const execute = async () => {
3686
+ if (disposed || fetching) {
3687
+ return;
3688
+ }
3689
+ try {
3690
+ fetching = true;
3691
+ const data = await this.refresh();
3692
+ if (!disposed) {
3693
+ onData(data);
3694
+ }
3695
+ } catch (error) {
3696
+ if (!disposed) {
3697
+ onError?.(this.normalizeError(error));
3698
+ }
3699
+ } finally {
3700
+ fetching = false;
3701
+ }
3702
+ };
3703
+ if (this.immediate) {
3704
+ void execute();
3705
+ }
3706
+ timer = globalThis.setInterval(() => {
3707
+ void execute();
3708
+ }, this.interval);
3709
+ return () => {
3710
+ disposed = true;
3711
+ if (timer) {
3712
+ globalThis.clearInterval(timer);
3713
+ }
3714
+ };
3715
+ }
3716
+ };
3717
+
3718
+ // src/components/data-display/graphs-v2/datasource/RealtimeGraphDataSource.ts
3719
+ var RealtimeGraphDataSource = class extends BaseGraphDataSource {
3720
+ constructor(config) {
3721
+ super();
3722
+ this.mode = GRAPH_DATA_MODES.REALTIME;
3723
+ this.connect = config.connect;
3724
+ this.initialDataLoader = config.getInitialData;
3725
+ this.refreshHandler = config.refresh;
3726
+ }
3727
+ getInitialData() {
3728
+ if (!this.initialDataLoader) {
3729
+ return [];
3730
+ }
3731
+ return this.safeExecute(async () => {
3732
+ const data = await this.initialDataLoader?.();
3733
+ return this.ensureArray(data);
3734
+ });
3735
+ }
3736
+ refresh() {
3737
+ if (!this.refreshHandler) {
3738
+ return this.getInitialData();
3739
+ }
3740
+ return this.safeExecute(async () => {
3741
+ const data = await this.refreshHandler?.();
3742
+ return this.ensureArray(data);
3743
+ });
3744
+ }
3745
+ subscribe(onData, onError) {
3746
+ try {
3747
+ return this.connect(
3748
+ (data) => {
3749
+ onData(this.ensureArray(data));
3750
+ },
3751
+ (error) => {
3752
+ onError?.(this.normalizeError(error));
3753
+ }
3754
+ );
3755
+ } catch (error) {
3756
+ onError?.(this.normalizeError(error));
3757
+ return () => {
3758
+ };
3759
+ }
3760
+ }
1574
3761
  };
1575
3762
  var CloudinaryContext = createContext(null);
1576
3763
  var CloudinaryProvider = ({
@@ -2033,7 +4220,7 @@ var ListItem = ({
2033
4220
  children: bullet
2034
4221
  }
2035
4222
  ),
2036
- /* @__PURE__ */ jsx("div", { className: "flex-1 min-w-0", children: TypographyComponent ? React4.cloneElement(
4223
+ /* @__PURE__ */ jsx("div", { className: "flex-1 min-w-0", children: TypographyComponent ? React3.cloneElement(
2037
4224
  TypographyComponent,
2038
4225
  {
2039
4226
  className: cn(
@@ -2067,7 +4254,7 @@ function normalizeItem(item, defaultBulletType) {
2067
4254
  bulletType: defaultBulletType
2068
4255
  };
2069
4256
  }
2070
- if (React4.isValidElement(item)) {
4257
+ if (React3.isValidElement(item)) {
2071
4258
  return {
2072
4259
  content: item,
2073
4260
  bulletType: defaultBulletType
@@ -2624,7 +4811,7 @@ function Tag({ text, className, ...rest }) {
2624
4811
  );
2625
4812
  }
2626
4813
  var Tag_default = Tag;
2627
- function Tooltip4({
4814
+ function Tooltip9({
2628
4815
  children,
2629
4816
  show,
2630
4817
  offsetX = 20,
@@ -3104,7 +5291,7 @@ var ShapeSwitch = () => {
3104
5291
  {
3105
5292
  value: currentShape,
3106
5293
  onChange: handleChange,
3107
- className: "\r\n px-3 py-2 rounded-md border border-gray-300\r\n bg-white dark:bg-gray-800\r\n text-sm shadow-sm\r\n focus:outline-none\r\n ",
5294
+ className: "\n px-3 py-2 rounded-md border border-gray-300\n bg-white dark:bg-gray-800\n text-sm shadow-sm\n focus:outline-none\n ",
3108
5295
  children: Object.keys(Shape).map((shape) => /* @__PURE__ */ jsx("option", { value: shape, children: shape }, shape))
3109
5296
  }
3110
5297
  ) });
@@ -14526,7 +16713,7 @@ function WorldMap({
14526
16713
  ]
14527
16714
  }
14528
16715
  ) }),
14529
- /* @__PURE__ */ jsx(Tooltip4, { show: showTooltip, children: tooltipContent })
16716
+ /* @__PURE__ */ jsx(Tooltip9, { show: showTooltip, children: tooltipContent })
14530
16717
  ] });
14531
16718
  }
14532
16719
  var sizes4 = {
@@ -16098,7 +18285,7 @@ function MarkdownTOC({ title = "Table of Contents" }) {
16098
18285
  /* @__PURE__ */ jsx("div", { children: /* @__PURE__ */ jsx(
16099
18286
  "h2",
16100
18287
  {
16101
- className: "\r\n text-sm\r\n font-semibold\r\n uppercase\r\n tracking-wide\r\n text-gray-900\r\n dark:text-gray-100\r\n ",
18288
+ className: "\n text-sm\n font-semibold\n uppercase\n tracking-wide\n text-gray-900\n dark:text-gray-100\n ",
16102
18289
  children: title
16103
18290
  }
16104
18291
  ) }),
@@ -16326,7 +18513,7 @@ var Breadcrumb = ({
16326
18513
  navigate(item.href);
16327
18514
  }
16328
18515
  };
16329
- return /* @__PURE__ */ jsxs(React4.Fragment, { children: [
18516
+ return /* @__PURE__ */ jsxs(React3.Fragment, { children: [
16330
18517
  /* @__PURE__ */ jsx(
16331
18518
  BreadcrumbItem_default,
16332
18519
  {
@@ -17428,7 +19615,7 @@ var GlowWrapper = ({
17428
19615
  /* @__PURE__ */ jsx(
17429
19616
  "span",
17430
19617
  {
17431
- className: "\r\n pointer-events-none absolute inset-0 opacity-0 \r\n group-hover:opacity-100 transition-opacity duration-300\r\n ",
19618
+ className: "\n pointer-events-none absolute inset-0 opacity-0 \n group-hover:opacity-100 transition-opacity duration-300\n ",
17432
19619
  style: { background: "var(--glow-bg)" }
17433
19620
  }
17434
19621
  ),
@@ -19100,6 +21287,6 @@ function ScrollToTop({
19100
21287
  }
19101
21288
  var ScrollToTop_default = ScrollToTop;
19102
21289
 
19103
- export { Accordion_default as Accordion, AsyncComponentWrapper_default as AsyncComponentWrapper, Avatar, Backdrop_default as Backdrop, Badge, BarChart_default as BarChart, Block_default as Block, BlockGroup_default as BlockGroup, BoxNav_default as BoxNav, BoxNavItem_default as BoxNavItem, Brand_default as Brand, Breadcrumb, BreadcrumbItem_default as BreadcrumbItem, Button_default as Button, Caption, Card_default as Card, CardContent_default as CardContent, CardFooter_default as CardFooter, CardHeader_default as CardHeader, Chapter, Checkbox_default as Checkbox, Chip, CloudinaryImage_default as CloudinaryImage, CloudinaryProvider, CloudinaryVideo_default as CloudinaryVideo, Code, CommentThread_default as CommentThread, Content, ContentArea_default as ContentArea, DataView, DataViewTable_default as DataViewTable, DateSelector_default as DateSelector, DefaultLayout_default as DefaultLayout, Display, DocumentationPanel_default as DocumentationPanel, Drawer, DrawerToggler_default as DrawerToggler, EUIDevLayout_default as EUIDevLayout, EUIProvider, Flag, Flex, FlexCol_default as FlexCol, FlexRow_default as FlexRow, Footer, FooterNav_default as FooterNav, FooterNavGroup_default as FooterNavGroup, FooterNavItem, FooterNavItemContext, FooterNavItemTitle, Form, FormResponse_default as FormResponse, GenericLayout_default as GenericLayout, GlowWrapper_default as GlowWrapper, Graph, GraphEdge, GraphNode, GraphRenderer, Grid_default as Grid, Header, HeaderNav_default as HeaderNav, HeaderNavGroup_default as HeaderNavGroup, HeaderNavItem, HeaderNavItemContext, HeaderNavItemTitle, HomeLayout_default as HomeLayout, Image2 as Image, ImageInput_default as ImageInput, InfiniteScrollTrigger_default as InfiniteScrollTrigger, Info_default as Info, Input, InputFile, InputLabel_default as InputLabel, InputList, InputListGroup, InputResponse_default as InputResponse, Label, Layout, Lead, LineChart_default as LineChart, Link, List_default as List, ListItem_default as ListItem, MarkdownEditor_default as MarkdownEditor, MarkdownProvider_default as MarkdownProvider, MarkdownTOC_default as MarkdownTOC, MarkdownViewer_default as MarkdownViewer, Menu, MenuGroup, MenuItem, MenuItemTitle, Modal_default as Modal, MotionSurface_default as MotionSurface, MultiImageInput_default as MultiImageInput, NumericRating_default as NumericRating, Overline, Paragraph, PieChart_default as PieChart, PriceTag, ProgressBar, ProgressBarRating_default as ProgressBarRating, Quote, Radio_default as Radio, RouteTab_default as RouteTab, RouteTabs_default as RouteTabs, ScrollToTop_default as ScrollToTop, Section, Select_default as Select, ShapeSwitch, ShowMore_default as ShowMore, Sidebar_default as Sidebar, SidebarLayout_default as SidebarLayout, SidemenuLayout_default as SidemenuLayout, Skeleton, Slider_default as Slider, StarRating_default as StarRating, StarRatingDistribution_default as StarRatingDistribution, StarRatingInput_default as StarRatingInput, Switch_default as Switch, TNDropdown, TNDropdownItem, TNDropdownTitle, TNGroup, Table_default as Table, Tag_default as Tag, Tags_default as Tags, TextArea_default as TextArea, ThemeContext, ThemeProvider, ThemeSwitch, TitleBanner, Toast, Tooltip4 as Tooltip, TopNav, Transition4 as Transition, TransitionDropdown_default as TransitionDropdown, TransitionFadeIn_default as TransitionFadeIn, Typography, UnderConstructionBanner, ValueBadge_default as ValueBadge, WorldMap, WorldMapCountryTable, YoutubeVideo_default as YoutubeVideoPlayer, addReplyToCache, applyReactionState, cn, createForceLayout, createGridLayout, createTreeLayout, decrementReplyCount, enumValues, formatCommentDate, getCurrencySymbol, getLayout, getOptimisticDislikeState, getOptimisticLikeState, incrementReplyCount, isMatch, isRenderFn, normalize, registerLayout, removeComment, removeCommentTreeFromCache, resolveAppearanceStyles, resolveWithGlobal, sendToast, updateComment, updateReplyCacheComment, useClickOutside, useCloudinaryConfig, useCurrentTheme_default as useCurrentTheme, useDrawer_default as useDrawer, useEUIConfig, useIsMobile_default as useIsMobile, useModal_default as useModal, useTheme_default as useTheme };
21290
+ export { Accordion_default as Accordion, AreaGraph, AsyncComponentWrapper_default as AsyncComponentWrapper, Avatar, Backdrop_default as Backdrop, Badge, BarChart_default as BarChart, BarGraph, BaseGraphDataSource, Block_default as Block, BlockGroup_default as BlockGroup, BoxNav_default as BoxNav, BoxNavItem_default as BoxNavItem, Brand_default as Brand, Breadcrumb, BreadcrumbItem_default as BreadcrumbItem, Button_default as Button, Caption, Card_default as Card, CardContent_default as CardContent, CardFooter_default as CardFooter, CardHeader_default as CardHeader, Chapter, Checkbox_default as Checkbox, Chip, CloudinaryImage_default as CloudinaryImage, CloudinaryProvider, CloudinaryVideo_default as CloudinaryVideo, Code, CommentThread_default as CommentThread, Content, ContentArea_default as ContentArea, DEFAULT_GRAPH_THEME, DataView, DataViewTable_default as DataViewTable, DateSelector_default as DateSelector, DefaultLayout_default as DefaultLayout, Display, DocumentationPanel_default as DocumentationPanel, Drawer, DrawerToggler_default as DrawerToggler, EUIDevLayout_default as EUIDevLayout, EUIProvider, Flag, Flex, FlexCol_default as FlexCol, FlexRow_default as FlexRow, Footer, FooterNav_default as FooterNav, FooterNavGroup_default as FooterNavGroup, FooterNavItem, FooterNavItemContext, FooterNavItemTitle, Form, FormResponse_default as FormResponse, GRAPH_COLOR_PALETTE, GRAPH_DARK_THEME, GRAPH_DATA_MODES, GRAPH_DEFAULT_ACTIVE_DOT_RADIUS, GRAPH_DEFAULT_ANIMATION_DURATION, GRAPH_DEFAULT_BAR_RADIUS, GRAPH_DEFAULT_DOT_RADIUS, GRAPH_DEFAULT_HEIGHT, GRAPH_DEFAULT_MARGIN, GRAPH_DEFAULT_MAX_REALTIME_POINTS, GRAPH_DEFAULT_POLLING_INTERVAL, GRAPH_DEFAULT_STROKE_WIDTH, GRAPH_EMPTY_MESSAGE, GRAPH_ERROR_MESSAGE, GRAPH_LIGHT_THEME, GRAPH_LOADING_MESSAGE, GRAPH_STATUSES, GRAPH_STATUS_COLORS, GRAPH_VALUE_FORMATS, GaugeGraph, GenericLayout_default as GenericLayout, GlowWrapper_default as GlowWrapper, Graph, GraphContainer, GraphContext, GraphEmptyState, GraphErrorState, GraphHeader, GraphLegend, GraphLoadingState, GraphPanel, GraphProvider, GraphToolbar, GraphTooltip, Grid_default as Grid, Header, HeaderNav_default as HeaderNav, HeaderNavGroup_default as HeaderNavGroup, HeaderNavItem, HeaderNavItemContext, HeaderNavItemTitle, HomeLayout_default as HomeLayout, Image2 as Image, ImageInput_default as ImageInput, InfiniteScrollTrigger_default as InfiniteScrollTrigger, Info_default as Info, Input, InputFile, InputLabel_default as InputLabel, InputList, InputListGroup, InputResponse_default as InputResponse, Label, Layout, Lead, LineChart_default as LineChart, LineGraph, Link, List_default as List, ListItem_default as ListItem, MarkdownEditor_default as MarkdownEditor, MarkdownProvider_default as MarkdownProvider, MarkdownTOC_default as MarkdownTOC, MarkdownViewer_default as MarkdownViewer, Menu, MenuGroup, MenuItem, MenuItemTitle, Modal_default as Modal, MotionSurface_default as MotionSurface, MultiImageInput_default as MultiImageInput, NumericRating_default as NumericRating, Overline, Paragraph, PieChart_default as PieChart, PieGraph, PollingGraphDataSource, PriceTag, ProgressBar, ProgressBarRating_default as ProgressBarRating, Quote, Radio_default as Radio, RealtimeGraphDataSource, RouteTab_default as RouteTab, RouteTabs_default as RouteTabs, ScatterGraph, ScrollToTop_default as ScrollToTop, Section, Select_default as Select, ShapeSwitch, ShowMore_default as ShowMore, Sidebar_default as Sidebar, SidebarLayout_default as SidebarLayout, SidemenuLayout_default as SidemenuLayout, Skeleton, Slider_default as Slider, StarRating_default as StarRating, StarRatingDistribution_default as StarRatingDistribution, StarRatingInput_default as StarRatingInput, StatGraph, StaticGraphDataSource, Switch_default as Switch, TNDropdown, TNDropdownItem, TNDropdownTitle, TNGroup, Table_default as Table, Tag_default as Tag, Tags_default as Tags, TextArea_default as TextArea, ThemeContext, ThemeProvider, ThemeSwitch, TitleBanner, Toast, Tooltip9 as Tooltip, TopNav, Transition4 as Transition, TransitionDropdown_default as TransitionDropdown, TransitionFadeIn_default as TransitionFadeIn, Typography, UnderConstructionBanner, ValueBadge_default as ValueBadge, WorldMap, WorldMapCountryTable, YoutubeVideo_default as YoutubeVideoPlayer, addReplyToCache, applyReactionState, cn, createInitialGraphState, decrementReplyCount, enumValues, formatCommentDate, formatGraphValue, getCurrencySymbol, getOptimisticDislikeState, getOptimisticLikeState, graphReducer, incrementReplyCount, isMatch, isRenderFn, limitRealtimePoints, normalize, normalizeGraphData, normalizeGraphDataPoint, removeComment, removeCommentTreeFromCache, replaceRealtimePoints, resolveAppearanceStyles, resolveGraphColor, resolveGraphColors, resolveWithGlobal, sendToast, updateComment, updateReplyCacheComment, useClickOutside, useCloudinaryConfig, useCurrentTheme_default as useCurrentTheme, useDrawer_default as useDrawer, useEUIConfig, useGraphContext, useGraphData, useGraphPolling, useGraphRealtime, useGraphSeries, useGraphTheme, useIsMobile_default as useIsMobile, useModal_default as useModal, useTheme_default as useTheme };
19104
21291
  //# sourceMappingURL=index.mjs.map
19105
21292
  //# sourceMappingURL=index.mjs.map