reactbridge-sdk 0.1.20 → 0.2.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.
Files changed (30) hide show
  1. package/dist/components/ReactBridgeChatbox.d.ts.map +1 -1
  2. package/dist/components/analytics/AnalyticsDrawer.d.ts +13 -0
  3. package/dist/components/analytics/AnalyticsDrawer.d.ts.map +1 -0
  4. package/dist/components/analytics/AnalyticsReport.d.ts +13 -0
  5. package/dist/components/analytics/AnalyticsReport.d.ts.map +1 -0
  6. package/dist/components/analytics/AnalyticsWidget.d.ts +10 -0
  7. package/dist/components/analytics/AnalyticsWidget.d.ts.map +1 -0
  8. package/dist/components/analytics/DirectivesPanel.d.ts +11 -0
  9. package/dist/components/analytics/DirectivesPanel.d.ts.map +1 -0
  10. package/dist/components/analytics/MetricsPanel.d.ts +9 -0
  11. package/dist/components/analytics/MetricsPanel.d.ts.map +1 -0
  12. package/dist/components/analytics/ObservationsPanel.d.ts +9 -0
  13. package/dist/components/analytics/ObservationsPanel.d.ts.map +1 -0
  14. package/dist/hooks/analytics/useAnalyticsConfigs.d.ts +8 -0
  15. package/dist/hooks/analytics/useAnalyticsConfigs.d.ts.map +1 -0
  16. package/dist/hooks/analytics/useAnalyticsResult.d.ts +8 -0
  17. package/dist/hooks/analytics/useAnalyticsResult.d.ts.map +1 -0
  18. package/dist/hooks/analytics/useDirectiveAction.d.ts +7 -0
  19. package/dist/hooks/analytics/useDirectiveAction.d.ts.map +1 -0
  20. package/dist/index.d.ts +15 -0
  21. package/dist/index.d.ts.map +1 -1
  22. package/dist/index.esm.js +723 -7
  23. package/dist/index.esm.js.map +1 -1
  24. package/dist/index.js +731 -6
  25. package/dist/index.js.map +1 -1
  26. package/dist/types/analytics.d.ts +63 -0
  27. package/dist/types/analytics.d.ts.map +1 -0
  28. package/dist/utils/analytics-api.d.ts +23 -0
  29. package/dist/utils/analytics-api.d.ts.map +1 -0
  30. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -34,14 +34,14 @@ typeof SuppressedError === "function" ? SuppressedError : function (error, suppr
34
34
  return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
35
35
  };
36
36
 
37
- const DEFAULT_BASE_URL = 'https://react-bridge-api-14089992360.northamerica-northeast2.run.app'; // 'http://localhost:5093';
37
+ const DEFAULT_BASE_URL$1 = 'https://react-bridge-api-14089992360.northamerica-northeast2.run.app'; // 'http://localhost:5093';
38
38
  class ReactBridgeAPI {
39
39
  constructor(config) {
40
40
  this.config = config;
41
41
  }
42
42
  sendMessage(request) {
43
43
  return __awaiter(this, void 0, void 0, function* () {
44
- const baseURL = this.config.baseURL || DEFAULT_BASE_URL;
44
+ const baseURL = this.config.baseURL || DEFAULT_BASE_URL$1;
45
45
  const url = `${baseURL}/api/orchestrator/process`;
46
46
  try {
47
47
  // Configure abort signal for fetch with robust fallback.
@@ -792,7 +792,7 @@ toggleButtonClass = defaultToggleButtonClass, toggleButtonTitle = "Open chat ass
792
792
  display: "flex",
793
793
  alignItems: "center",
794
794
  justifyContent: "center",
795
- width: "40px",
795
+ width: "24px",
796
796
  height: "40px",
797
797
  } }, PLUS_ICON_SVG$1),
798
798
  isUploadMenuOpen && (React.createElement("div", { style: {
@@ -838,6 +838,7 @@ toggleButtonClass = defaultToggleButtonClass, toggleButtonTitle = "Open chat ass
838
838
  React.createElement("button", { type: "button", onClick: isListening ? stopVoiceInput : startVoiceInput, disabled: isLoading, title: isListening ? "Stop recording" : "Start voice input", style: {
839
839
  padding: theme.spacing.sm,
840
840
  paddingLeft: 0,
841
+ paddingRight: 0,
841
842
  color: isListening ? theme.colors.primary : theme.colors.border,
842
843
  border: "none",
843
844
  borderRadius: theme.borderRadius,
@@ -846,7 +847,7 @@ toggleButtonClass = defaultToggleButtonClass, toggleButtonTitle = "Open chat ass
846
847
  display: "flex",
847
848
  alignItems: "center",
848
849
  justifyContent: "center",
849
- width: "40px",
850
+ width: "24px",
850
851
  height: "40px",
851
852
  } }, MIC_ICON_SVG$1),
852
853
  React.createElement("button", { type: "submit", disabled: isLoading || (!inputValue.trim() && !selectedFile), style: {
@@ -990,7 +991,7 @@ toggleButtonClass = defaultToggleButtonClass, toggleButtonTitle = "Open chat ass
990
991
  display: "flex",
991
992
  alignItems: "center",
992
993
  justifyContent: "center",
993
- width: "40px",
994
+ width: "24px",
994
995
  height: "40px",
995
996
  } }, PLUS_ICON_SVG$1),
996
997
  isUploadMenuOpen && (React.createElement("div", { style: {
@@ -1042,6 +1043,7 @@ toggleButtonClass = defaultToggleButtonClass, toggleButtonTitle = "Open chat ass
1042
1043
  React.createElement("button", { type: "button", onClick: isListening ? stopVoiceInput : startVoiceInput, disabled: isLoading, title: isListening ? "Stop recording" : "Start voice input", style: {
1043
1044
  padding: theme.spacing.sm,
1044
1045
  paddingLeft: 0,
1046
+ paddingRight: 0,
1045
1047
  color: isListening ? theme.colors.primary : theme.colors.border,
1046
1048
  border: "none",
1047
1049
  borderRadius: theme.borderRadius,
@@ -1050,7 +1052,7 @@ toggleButtonClass = defaultToggleButtonClass, toggleButtonTitle = "Open chat ass
1050
1052
  display: "flex",
1051
1053
  alignItems: "center",
1052
1054
  justifyContent: "center",
1053
- width: "40px",
1055
+ width: "24px",
1054
1056
  height: "40px",
1055
1057
  } }, MIC_ICON_SVG$1),
1056
1058
  React.createElement("button", { type: "submit", disabled: isLoading || (!inputValue.trim() && !selectedFile), style: {
@@ -1437,6 +1439,726 @@ function createCustomTheme(baseTheme, overrides) {
1437
1439
  return Object.assign(Object.assign(Object.assign({}, baseTheme), overrides), { colors: Object.assign(Object.assign({}, baseTheme.colors), (overrides.colors || {})), spacing: Object.assign(Object.assign({}, baseTheme.spacing), (overrides.spacing || {})), fontSizes: Object.assign(Object.assign({}, baseTheme.fontSizes), (overrides.fontSizes || {})) });
1438
1440
  }
1439
1441
 
1442
+ const DEFAULT_BASE_URL = 'https://react-bridge-api-14089992360.northamerica-northeast2.run.app';
1443
+ class AnalyticsAPI {
1444
+ constructor(config) {
1445
+ this.config = config;
1446
+ }
1447
+ /**
1448
+ * Fetch all analytics configurations for the client
1449
+ */
1450
+ getConfigs() {
1451
+ return __awaiter(this, void 0, void 0, function* () {
1452
+ const baseURL = this.config.baseURL || DEFAULT_BASE_URL;
1453
+ const url = `${baseURL}/api/client/analytics/configs`;
1454
+ const response = yield fetch(url, {
1455
+ method: 'GET',
1456
+ headers: Object.assign({ 'X-API-Key': this.config.apiKey }, this.config.headers),
1457
+ });
1458
+ if (!response.ok) {
1459
+ throw new Error(`Failed to fetch analytics configs: ${response.statusText}`);
1460
+ }
1461
+ return response.json();
1462
+ });
1463
+ }
1464
+ /**
1465
+ * Fetch the latest analytics result for a specific type
1466
+ */
1467
+ getLatestResult(analyticsType) {
1468
+ return __awaiter(this, void 0, void 0, function* () {
1469
+ const baseURL = this.config.baseURL || DEFAULT_BASE_URL;
1470
+ const url = `${baseURL}/api/analytics/${analyticsType}/latest`;
1471
+ const response = yield fetch(url, {
1472
+ method: 'POST',
1473
+ headers: Object.assign({ 'X-API-Key': this.config.apiKey, 'Content-Type': 'application/json' }, this.config.headers),
1474
+ });
1475
+ if (!response.ok) {
1476
+ if (response.status === 404) {
1477
+ throw new Error(`No results found for analytics type: ${analyticsType}`);
1478
+ }
1479
+ throw new Error(`Failed to fetch analytics result: ${response.statusText}`);
1480
+ }
1481
+ return response.json();
1482
+ });
1483
+ }
1484
+ /**
1485
+ * Update directive status (executed, declined, failed)
1486
+ */
1487
+ updateDirectiveStatus(directiveId, status) {
1488
+ return __awaiter(this, void 0, void 0, function* () {
1489
+ const baseURL = this.config.baseURL || DEFAULT_BASE_URL;
1490
+ const url = `${baseURL}/api/analytics/directives/${directiveId}/status`;
1491
+ const response = yield fetch(url, {
1492
+ method: 'PATCH',
1493
+ headers: Object.assign({ 'X-API-Key': this.config.apiKey, 'Content-Type': 'application/json' }, this.config.headers),
1494
+ body: JSON.stringify({ status }),
1495
+ });
1496
+ if (!response.ok) {
1497
+ throw new Error(`Failed to update directive status: ${response.statusText}`);
1498
+ }
1499
+ return response.json();
1500
+ });
1501
+ }
1502
+ }
1503
+
1504
+ function useAnalyticsConfigs() {
1505
+ const { config } = useReactBridgeContext();
1506
+ const [configs, setConfigs] = React.useState([]);
1507
+ const [isLoading, setIsLoading] = React.useState(true);
1508
+ const [error, setError] = React.useState(null);
1509
+ const fetchConfigs = () => __awaiter(this, void 0, void 0, function* () {
1510
+ try {
1511
+ setIsLoading(true);
1512
+ setError(null);
1513
+ const api = new AnalyticsAPI(config);
1514
+ const data = yield api.getConfigs();
1515
+ setConfigs(data);
1516
+ }
1517
+ catch (err) {
1518
+ setError(err);
1519
+ }
1520
+ finally {
1521
+ setIsLoading(false);
1522
+ }
1523
+ });
1524
+ React.useEffect(() => {
1525
+ fetchConfigs();
1526
+ }, [config]);
1527
+ return {
1528
+ configs,
1529
+ isLoading,
1530
+ error,
1531
+ refetch: fetchConfigs,
1532
+ };
1533
+ }
1534
+
1535
+ function useAnalyticsResult(analyticsType) {
1536
+ const { config } = useReactBridgeContext();
1537
+ const [result, setResult] = React.useState(null);
1538
+ const [isLoading, setIsLoading] = React.useState(false);
1539
+ const [error, setError] = React.useState(null);
1540
+ const fetchResult = () => __awaiter(this, void 0, void 0, function* () {
1541
+ if (!analyticsType)
1542
+ return;
1543
+ try {
1544
+ setIsLoading(true);
1545
+ setError(null);
1546
+ const api = new AnalyticsAPI(config);
1547
+ const data = yield api.getLatestResult(analyticsType);
1548
+ setResult(data);
1549
+ }
1550
+ catch (err) {
1551
+ setError(err);
1552
+ setResult(null);
1553
+ }
1554
+ finally {
1555
+ setIsLoading(false);
1556
+ }
1557
+ });
1558
+ React.useEffect(() => {
1559
+ fetchResult();
1560
+ }, [analyticsType, config]);
1561
+ return {
1562
+ result,
1563
+ isLoading,
1564
+ error,
1565
+ refetch: fetchResult,
1566
+ };
1567
+ }
1568
+
1569
+ const MetricsPanel = ({ metrics, theme }) => {
1570
+ const getStatusColor = (status) => {
1571
+ switch (status) {
1572
+ case 'ok':
1573
+ return theme.colors.success;
1574
+ case 'warning':
1575
+ return '#FFA500'; // Orange
1576
+ case 'critical':
1577
+ return theme.colors.error;
1578
+ default:
1579
+ return theme.colors.textSecondary;
1580
+ }
1581
+ };
1582
+ return (React.createElement("div", null,
1583
+ React.createElement("h3", { style: {
1584
+ margin: 0,
1585
+ marginBottom: theme.spacing.md,
1586
+ fontSize: theme.fontSizes.lg,
1587
+ color: theme.colors.text,
1588
+ } }, "Metrics"),
1589
+ React.createElement("div", { style: {
1590
+ display: 'grid',
1591
+ gridTemplateColumns: 'repeat(auto-fit, minmax(200px, 1fr))',
1592
+ gap: theme.spacing.md,
1593
+ } }, metrics.map((metric, index) => (React.createElement("div", { key: index, style: {
1594
+ padding: theme.spacing.md,
1595
+ backgroundColor: theme.colors.surface,
1596
+ borderRadius: theme.borderRadius,
1597
+ border: `2px solid ${getStatusColor(metric.status)}`,
1598
+ } },
1599
+ React.createElement("div", { style: {
1600
+ display: 'flex',
1601
+ justifyContent: 'space-between',
1602
+ alignItems: 'center',
1603
+ marginBottom: theme.spacing.xs,
1604
+ } },
1605
+ React.createElement("span", { style: {
1606
+ fontSize: theme.fontSizes.sm,
1607
+ color: theme.colors.textSecondary,
1608
+ textTransform: 'uppercase',
1609
+ letterSpacing: '0.5px',
1610
+ } }, metric.name.replace(/_/g, ' ')),
1611
+ React.createElement("span", { style: {
1612
+ fontSize: theme.fontSizes.xs,
1613
+ padding: '2px 8px',
1614
+ borderRadius: '12px',
1615
+ backgroundColor: getStatusColor(metric.status),
1616
+ color: '#fff',
1617
+ textTransform: 'uppercase',
1618
+ } }, metric.status)),
1619
+ React.createElement("div", { style: {
1620
+ fontSize: theme.fontSizes.xl,
1621
+ fontWeight: 'bold',
1622
+ color: theme.colors.text,
1623
+ marginBottom: theme.spacing.xs,
1624
+ } },
1625
+ metric.value,
1626
+ " ",
1627
+ metric.unit),
1628
+ React.createElement("div", { style: {
1629
+ fontSize: theme.fontSizes.sm,
1630
+ color: theme.colors.textSecondary,
1631
+ } }, metric.explanation)))))));
1632
+ };
1633
+
1634
+ const ObservationsPanel = ({ observations, theme, }) => {
1635
+ const getSeverityColor = (severity) => {
1636
+ switch (severity) {
1637
+ case 'low':
1638
+ return theme.colors.success;
1639
+ case 'medium':
1640
+ return '#FFA500'; // Orange
1641
+ case 'high':
1642
+ return theme.colors.error;
1643
+ default:
1644
+ return theme.colors.textSecondary;
1645
+ }
1646
+ };
1647
+ return (React.createElement("div", null,
1648
+ React.createElement("h3", { style: {
1649
+ margin: 0,
1650
+ marginBottom: theme.spacing.md,
1651
+ fontSize: theme.fontSizes.lg,
1652
+ color: theme.colors.text,
1653
+ } }, "Observations"),
1654
+ React.createElement("div", { style: { display: 'flex', flexDirection: 'column', gap: theme.spacing.md } }, observations.map((observation, index) => (React.createElement("div", { key: index, style: {
1655
+ padding: theme.spacing.md,
1656
+ backgroundColor: theme.colors.surface,
1657
+ borderRadius: theme.borderRadius,
1658
+ border: `1px solid ${theme.colors.border}`,
1659
+ borderLeft: `4px solid ${getSeverityColor(observation.severity)}`,
1660
+ } },
1661
+ React.createElement("div", { style: {
1662
+ display: 'flex',
1663
+ justifyContent: 'space-between',
1664
+ alignItems: 'center',
1665
+ marginBottom: theme.spacing.xs,
1666
+ } },
1667
+ React.createElement("span", { style: {
1668
+ fontSize: theme.fontSizes.xs,
1669
+ padding: '2px 8px',
1670
+ borderRadius: '12px',
1671
+ backgroundColor: getSeverityColor(observation.severity),
1672
+ color: '#fff',
1673
+ textTransform: 'uppercase',
1674
+ } }, observation.severity),
1675
+ React.createElement("span", { style: {
1676
+ fontSize: theme.fontSizes.xs,
1677
+ color: theme.colors.textSecondary,
1678
+ } }, observation.scope)),
1679
+ React.createElement("div", { style: {
1680
+ fontSize: theme.fontSizes.md,
1681
+ color: theme.colors.text,
1682
+ lineHeight: '1.5',
1683
+ } }, observation.text)))))));
1684
+ };
1685
+
1686
+ function useDirectiveAction(onDirectiveAction) {
1687
+ const { config } = useReactBridgeContext();
1688
+ const [isProcessing, setIsProcessing] = React.useState(false);
1689
+ const [error, setError] = React.useState(null);
1690
+ const handleAction = (directive, action) => __awaiter(this, void 0, void 0, function* () {
1691
+ try {
1692
+ setIsProcessing(true);
1693
+ setError(null);
1694
+ const api = new AnalyticsAPI(config);
1695
+ // If onDirectiveAction callback is provided, execute it first
1696
+ if (onDirectiveAction) {
1697
+ const result = yield onDirectiveAction(directive, action);
1698
+ if (result.success) {
1699
+ // Update status to 'executed' if action succeeded
1700
+ yield api.updateDirectiveStatus(directive.directiveId, 'executed');
1701
+ }
1702
+ else {
1703
+ // Update status to 'failed' if action failed
1704
+ yield api.updateDirectiveStatus(directive.directiveId, 'failed');
1705
+ throw new Error(result.error || 'Directive execution failed');
1706
+ }
1707
+ return { success: true };
1708
+ }
1709
+ else {
1710
+ // No callback provided, just update status to 'declined'
1711
+ if (action === 'decline') {
1712
+ yield api.updateDirectiveStatus(directive.directiveId, 'declined');
1713
+ }
1714
+ return { success: true };
1715
+ }
1716
+ }
1717
+ catch (err) {
1718
+ setError(err);
1719
+ return { success: false, error: err.message };
1720
+ }
1721
+ finally {
1722
+ setIsProcessing(false);
1723
+ }
1724
+ });
1725
+ return {
1726
+ handleAction,
1727
+ isProcessing,
1728
+ error,
1729
+ };
1730
+ }
1731
+
1732
+ const DirectivesPanel = ({ directives, theme, onDirectiveAction, onUpdate, }) => {
1733
+ const { handleAction, isProcessing } = useDirectiveAction(onDirectiveAction);
1734
+ const [processingId, setProcessingId] = React.useState(null);
1735
+ const getPriorityColor = (priority) => {
1736
+ if (priority >= 3)
1737
+ return theme.colors.error; // High/Critical
1738
+ if (priority === 2)
1739
+ return '#FFA500'; // Medium
1740
+ return theme.colors.success; // Low
1741
+ };
1742
+ const getPriorityLabel = (priority) => {
1743
+ if (priority >= 3)
1744
+ return 'Critical';
1745
+ if (priority === 2)
1746
+ return 'High';
1747
+ if (priority === 1)
1748
+ return 'Medium';
1749
+ return 'Low';
1750
+ };
1751
+ const getStatusLabel = (status) => {
1752
+ switch (status) {
1753
+ case 'proposed':
1754
+ return 'Pending';
1755
+ case 'executed':
1756
+ return 'Executed ✓';
1757
+ case 'declined':
1758
+ return 'Declined';
1759
+ case 'failed':
1760
+ return 'Failed ✗';
1761
+ default:
1762
+ return status;
1763
+ }
1764
+ };
1765
+ const handleDirectiveAction = (directive, action) => __awaiter(void 0, void 0, void 0, function* () {
1766
+ setProcessingId(directive.directiveId);
1767
+ yield handleAction(directive, action);
1768
+ setProcessingId(null);
1769
+ if (onUpdate) {
1770
+ onUpdate();
1771
+ }
1772
+ });
1773
+ return (React.createElement("div", null,
1774
+ React.createElement("h3", { style: {
1775
+ margin: 0,
1776
+ marginBottom: theme.spacing.md,
1777
+ fontSize: theme.fontSizes.lg,
1778
+ color: theme.colors.text,
1779
+ } }, "Directives"),
1780
+ React.createElement("div", { style: { display: 'flex', flexDirection: 'column', gap: theme.spacing.md } }, directives.map((directive) => {
1781
+ const isDisabled = directive.status !== 'proposed' ||
1782
+ isProcessing ||
1783
+ processingId === directive.directiveId;
1784
+ return (React.createElement("div", { key: directive.directiveId, style: {
1785
+ padding: theme.spacing.md,
1786
+ backgroundColor: theme.colors.surface,
1787
+ borderRadius: theme.borderRadius,
1788
+ border: `1px solid ${theme.colors.border}`,
1789
+ } },
1790
+ React.createElement("div", { style: {
1791
+ display: 'flex',
1792
+ justifyContent: 'space-between',
1793
+ alignItems: 'center',
1794
+ marginBottom: theme.spacing.sm,
1795
+ } },
1796
+ React.createElement("span", { style: {
1797
+ fontSize: theme.fontSizes.xs,
1798
+ padding: '2px 8px',
1799
+ borderRadius: '12px',
1800
+ backgroundColor: getPriorityColor(directive.priority),
1801
+ color: '#fff',
1802
+ textTransform: 'uppercase',
1803
+ } }, getPriorityLabel(directive.priority)),
1804
+ React.createElement("span", { style: {
1805
+ fontSize: theme.fontSizes.xs,
1806
+ padding: '2px 8px',
1807
+ borderRadius: '12px',
1808
+ backgroundColor: theme.colors.textSecondary,
1809
+ color: '#fff',
1810
+ } }, getStatusLabel(directive.status))),
1811
+ React.createElement("div", { style: {
1812
+ fontSize: theme.fontSizes.lg,
1813
+ fontWeight: 'bold',
1814
+ color: theme.colors.text,
1815
+ marginBottom: theme.spacing.xs,
1816
+ } }, directive.action.replace(/_/g, ' ').toUpperCase()),
1817
+ directive.targets.length > 0 && (React.createElement("div", { style: {
1818
+ fontSize: theme.fontSizes.sm,
1819
+ color: theme.colors.textSecondary,
1820
+ marginBottom: theme.spacing.xs,
1821
+ } },
1822
+ React.createElement("strong", null, "Targets:"),
1823
+ " ",
1824
+ directive.targets.join(', '))),
1825
+ directive.parameters.length > 0 && (React.createElement("div", { style: {
1826
+ marginBottom: theme.spacing.sm,
1827
+ padding: theme.spacing.sm,
1828
+ backgroundColor: theme.colors.background,
1829
+ borderRadius: theme.borderRadius,
1830
+ } }, directive.parameters.map((param, index) => (React.createElement("div", { key: index, style: {
1831
+ fontSize: theme.fontSizes.sm,
1832
+ color: theme.colors.text,
1833
+ marginBottom: '4px',
1834
+ } },
1835
+ React.createElement("strong", null,
1836
+ param.name,
1837
+ ":"),
1838
+ " ",
1839
+ param.value,
1840
+ " (",
1841
+ param.valueType,
1842
+ ")"))))),
1843
+ React.createElement("div", { style: {
1844
+ fontSize: theme.fontSizes.sm,
1845
+ color: theme.colors.textSecondary,
1846
+ marginBottom: theme.spacing.md,
1847
+ lineHeight: '1.5',
1848
+ } }, directive.rationale),
1849
+ directive.status === 'proposed' && (React.createElement("div", { style: { display: 'flex', gap: theme.spacing.sm } },
1850
+ React.createElement("button", { onClick: () => handleDirectiveAction(directive, 'execute'), disabled: isDisabled, style: {
1851
+ flex: 1,
1852
+ padding: theme.spacing.sm,
1853
+ backgroundColor: isDisabled
1854
+ ? theme.colors.textSecondary
1855
+ : theme.colors.success,
1856
+ color: '#fff',
1857
+ border: 'none',
1858
+ borderRadius: theme.borderRadius,
1859
+ cursor: isDisabled ? 'not-allowed' : 'pointer',
1860
+ fontSize: theme.fontSizes.sm,
1861
+ fontWeight: 'bold',
1862
+ opacity: isDisabled ? 0.6 : 1,
1863
+ } }, processingId === directive.directiveId ? 'Processing...' : 'Execute'),
1864
+ React.createElement("button", { onClick: () => handleDirectiveAction(directive, 'decline'), disabled: isDisabled, style: {
1865
+ flex: 1,
1866
+ padding: theme.spacing.sm,
1867
+ backgroundColor: isDisabled
1868
+ ? theme.colors.textSecondary
1869
+ : theme.colors.error,
1870
+ color: '#fff',
1871
+ border: 'none',
1872
+ borderRadius: theme.borderRadius,
1873
+ cursor: isDisabled ? 'not-allowed' : 'pointer',
1874
+ fontSize: theme.fontSizes.sm,
1875
+ fontWeight: 'bold',
1876
+ opacity: isDisabled ? 0.6 : 1,
1877
+ } }, "Decline")))));
1878
+ }))));
1879
+ };
1880
+
1881
+ // Refresh Icon SVG
1882
+ const REFRESH_ICON_SVG = (React.createElement("svg", { xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 24 24", width: "1em", height: "1em", fill: "currentColor" },
1883
+ React.createElement("path", { d: "M17.65 6.35C16.2 4.9 14.21 4 12 4c-4.42 0-7.99 3.58-7.99 8s3.57 8 7.99 8c3.73 0 6.84-2.55 7.73-6h-2.08c-.82 2.33-3.04 4-5.65 4-3.31 0-6-2.69-6-6s2.69-6 6-6c1.66 0 3.14.69 4.22 1.78L13 11h7V4l-2.35 2.35z" })));
1884
+ // Back Arrow Icon SVG
1885
+ const BACK_ICON_SVG = (React.createElement("svg", { xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 24 24", width: "1em", height: "1em", fill: "currentColor" },
1886
+ React.createElement("path", { d: "M20 11H7.83l5.59-5.59L12 4l-8 8 8 8 1.41-1.41L7.83 13H20v-2z" })));
1887
+ // Close Icon SVG
1888
+ const CLOSE_ICON_SVG$1 = (React.createElement("svg", { xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 24 24", width: "1em", height: "1em", fill: "currentColor" },
1889
+ React.createElement("path", { d: "M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z" })));
1890
+ const AnalyticsReport = ({ analyticsType, theme: customTheme, onDirectiveAction, onRefresh, onBack, onClose, }) => {
1891
+ const { result, isLoading, error, refetch } = useAnalyticsResult(analyticsType);
1892
+ const handleRefresh = () => {
1893
+ refetch();
1894
+ if (onRefresh) {
1895
+ onRefresh();
1896
+ }
1897
+ };
1898
+ // Use a default theme if none provided
1899
+ const theme = customTheme || {
1900
+ colors: {
1901
+ background: '#ffffff',
1902
+ surface: '#f5f5f5',
1903
+ text: '#333333',
1904
+ textSecondary: '#666666',
1905
+ border: '#e0e0e0',
1906
+ primary: '#007bff',
1907
+ success: '#28a745',
1908
+ error: '#dc3545',
1909
+ secondary: '#6c757d',
1910
+ },
1911
+ spacing: {
1912
+ xs: '4px',
1913
+ sm: '8px',
1914
+ md: '16px',
1915
+ lg: '24px',
1916
+ xl: '32px',
1917
+ },
1918
+ fontSizes: {
1919
+ xs: '12px',
1920
+ sm: '14px',
1921
+ md: '16px',
1922
+ lg: '20px',
1923
+ xl: '24px',
1924
+ },
1925
+ borderRadius: '8px',
1926
+ boxShadow: '0 2px 8px rgba(0,0,0,0.1)',
1927
+ name: 'default',
1928
+ };
1929
+ return (React.createElement("div", { style: {
1930
+ height: '100%',
1931
+ display: 'flex',
1932
+ flexDirection: 'column',
1933
+ backgroundColor: theme.colors.background,
1934
+ } },
1935
+ React.createElement("div", { style: {
1936
+ padding: theme.spacing.lg,
1937
+ borderBottom: `1px solid ${theme.colors.border}`,
1938
+ display: 'flex',
1939
+ justifyContent: 'space-between',
1940
+ alignItems: 'center',
1941
+ } },
1942
+ React.createElement("div", { style: { display: 'flex', alignItems: 'center', gap: theme.spacing.sm } },
1943
+ onBack && (React.createElement("button", { onClick: onBack, style: {
1944
+ background: 'none',
1945
+ border: 'none',
1946
+ cursor: 'pointer',
1947
+ fontSize: '24px',
1948
+ color: theme.colors.text,
1949
+ padding: 0,
1950
+ } }, BACK_ICON_SVG)),
1951
+ React.createElement("div", null,
1952
+ React.createElement("h2", { style: {
1953
+ margin: 0,
1954
+ fontSize: theme.fontSizes.xl,
1955
+ color: theme.colors.text,
1956
+ } }, analyticsType),
1957
+ result && (React.createElement("div", { style: {
1958
+ fontSize: theme.fontSizes.xs,
1959
+ color: theme.colors.textSecondary,
1960
+ marginTop: '4px',
1961
+ } },
1962
+ "Last updated: ",
1963
+ new Date(result.createdAt).toLocaleString())))),
1964
+ React.createElement("div", { style: { display: 'flex', gap: theme.spacing.sm } },
1965
+ React.createElement("button", { onClick: handleRefresh, disabled: isLoading, style: {
1966
+ background: 'none',
1967
+ border: 'none',
1968
+ cursor: isLoading ? 'not-allowed' : 'pointer',
1969
+ fontSize: '24px',
1970
+ color: theme.colors.text,
1971
+ padding: 0,
1972
+ opacity: isLoading ? 0.5 : 1,
1973
+ } }, REFRESH_ICON_SVG),
1974
+ onClose && (React.createElement("button", { onClick: onClose, style: {
1975
+ background: 'none',
1976
+ border: 'none',
1977
+ cursor: 'pointer',
1978
+ fontSize: '24px',
1979
+ color: theme.colors.text,
1980
+ padding: 0,
1981
+ } }, CLOSE_ICON_SVG$1)))),
1982
+ React.createElement("div", { style: {
1983
+ flex: 1,
1984
+ overflowY: 'auto',
1985
+ padding: theme.spacing.lg,
1986
+ } }, isLoading ? (React.createElement("div", { style: { textAlign: 'center', color: theme.colors.textSecondary } }, "Loading analytics result...")) : error ? (React.createElement("div", { style: {
1987
+ padding: theme.spacing.md,
1988
+ backgroundColor: theme.colors.surface,
1989
+ borderRadius: theme.borderRadius,
1990
+ border: `1px solid ${theme.colors.error}`,
1991
+ color: theme.colors.error,
1992
+ } },
1993
+ "Error: ",
1994
+ error.message)) : result ? (React.createElement("div", { style: { display: 'flex', flexDirection: 'column', gap: theme.spacing.xl } },
1995
+ result.metrics.length > 0 && (React.createElement(MetricsPanel, { metrics: result.metrics, theme: theme })),
1996
+ result.observations.length > 0 && (React.createElement(ObservationsPanel, { observations: result.observations, theme: theme })),
1997
+ result.directives.length > 0 && (React.createElement(DirectivesPanel, { directives: result.directives, theme: theme, onDirectiveAction: onDirectiveAction, onUpdate: refetch })))) : (React.createElement("div", { style: { textAlign: 'center', color: theme.colors.textSecondary } }, "No results available")))));
1998
+ };
1999
+
2000
+ // Close Icon SVG
2001
+ const CLOSE_ICON_SVG = (React.createElement("svg", { xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 24 24", width: "1em", height: "1em", fill: "currentColor" },
2002
+ React.createElement("path", { d: "M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z" })));
2003
+ const AnalyticsDrawer = ({ isOpen, onClose, configs, isLoading, theme, onDirectiveAction, }) => {
2004
+ const [selectedAnalytics, setSelectedAnalytics] = React.useState(null);
2005
+ // Check if mobile
2006
+ const isMobile = typeof window !== 'undefined' && window.innerWidth < 768;
2007
+ const drawerStyles = {
2008
+ position: 'fixed',
2009
+ top: 0,
2010
+ right: 0,
2011
+ width: isMobile ? '100%' : '400px',
2012
+ height: '100%',
2013
+ backgroundColor: theme.colors.background,
2014
+ boxShadow: theme.boxShadow,
2015
+ zIndex: 1001,
2016
+ display: 'flex',
2017
+ flexDirection: 'column',
2018
+ transform: isOpen ? 'translateX(0)' : 'translateX(100%)',
2019
+ transition: 'transform 0.3s ease',
2020
+ };
2021
+ const overlayStyles = {
2022
+ position: 'fixed',
2023
+ top: 0,
2024
+ left: 0,
2025
+ width: '100%',
2026
+ height: '100%',
2027
+ backgroundColor: 'rgba(0, 0, 0, 0.5)',
2028
+ zIndex: 1000,
2029
+ opacity: isOpen ? 1 : 0,
2030
+ pointerEvents: isOpen ? 'auto' : 'none',
2031
+ transition: 'opacity 0.3s ease',
2032
+ };
2033
+ if (selectedAnalytics) {
2034
+ return (React.createElement(React.Fragment, null,
2035
+ React.createElement("div", { style: overlayStyles, onClick: onClose }),
2036
+ React.createElement("div", { style: drawerStyles },
2037
+ React.createElement(AnalyticsReport, { analyticsType: selectedAnalytics, theme: theme, onDirectiveAction: onDirectiveAction, onBack: () => setSelectedAnalytics(null), onClose: onClose }))));
2038
+ }
2039
+ return (React.createElement(React.Fragment, null,
2040
+ React.createElement("div", { style: overlayStyles, onClick: onClose }),
2041
+ React.createElement("div", { style: drawerStyles },
2042
+ React.createElement("div", { style: {
2043
+ padding: theme.spacing.lg,
2044
+ borderBottom: `1px solid ${theme.colors.border}`,
2045
+ display: 'flex',
2046
+ justifyContent: 'space-between',
2047
+ alignItems: 'center',
2048
+ } },
2049
+ React.createElement("h2", { style: {
2050
+ margin: 0,
2051
+ fontSize: theme.fontSizes.xl,
2052
+ color: theme.colors.text,
2053
+ } }, "Analytics"),
2054
+ React.createElement("button", { onClick: onClose, style: {
2055
+ background: 'none',
2056
+ border: 'none',
2057
+ cursor: 'pointer',
2058
+ fontSize: '24px',
2059
+ color: theme.colors.text,
2060
+ padding: 0,
2061
+ } }, CLOSE_ICON_SVG)),
2062
+ React.createElement("div", { style: {
2063
+ flex: 1,
2064
+ overflowY: 'auto',
2065
+ padding: theme.spacing.lg,
2066
+ } }, isLoading ? (React.createElement("div", { style: { textAlign: 'center', color: theme.colors.textSecondary } }, "Loading analytics...")) : configs.length === 0 ? (React.createElement("div", { style: { textAlign: 'center', color: theme.colors.textSecondary } }, "No analytics configured")) : (React.createElement("div", { style: { display: 'flex', flexDirection: 'column', gap: theme.spacing.md } }, configs.map((config) => (React.createElement("div", { key: config.configId, onClick: () => config.isEnabled && setSelectedAnalytics(config.analyticsType), style: {
2067
+ padding: theme.spacing.md,
2068
+ backgroundColor: theme.colors.surface,
2069
+ borderRadius: theme.borderRadius,
2070
+ border: `1px solid ${theme.colors.border}`,
2071
+ cursor: config.isEnabled ? 'pointer' : 'not-allowed',
2072
+ opacity: config.isEnabled ? 1 : 0.6,
2073
+ transition: 'transform 0.2s ease',
2074
+ }, onMouseEnter: (e) => {
2075
+ if (config.isEnabled) {
2076
+ e.currentTarget.style.transform = 'translateX(5px)';
2077
+ }
2078
+ }, onMouseLeave: (e) => {
2079
+ e.currentTarget.style.transform = 'translateX(0)';
2080
+ } },
2081
+ React.createElement("div", { style: {
2082
+ display: 'flex',
2083
+ justifyContent: 'space-between',
2084
+ alignItems: 'center',
2085
+ marginBottom: theme.spacing.xs,
2086
+ } },
2087
+ React.createElement("h3", { style: {
2088
+ margin: 0,
2089
+ fontSize: theme.fontSizes.md,
2090
+ color: theme.colors.text,
2091
+ } }, config.analyticsType),
2092
+ React.createElement("span", { style: {
2093
+ fontSize: theme.fontSizes.xs,
2094
+ padding: '2px 8px',
2095
+ borderRadius: '12px',
2096
+ backgroundColor: config.isEnabled
2097
+ ? theme.colors.success
2098
+ : theme.colors.textSecondary,
2099
+ color: '#fff',
2100
+ } }, config.isEnabled ? 'Enabled' : 'Disabled')),
2101
+ React.createElement("p", { style: {
2102
+ margin: 0,
2103
+ fontSize: theme.fontSizes.sm,
2104
+ color: theme.colors.textSecondary,
2105
+ marginBottom: theme.spacing.xs,
2106
+ } }, config.templateDescription),
2107
+ React.createElement("div", { style: {
2108
+ fontSize: theme.fontSizes.xs,
2109
+ color: theme.colors.textSecondary,
2110
+ } },
2111
+ React.createElement("div", null,
2112
+ "Frequency: ",
2113
+ config.frequency),
2114
+ config.lastExecutedAt && (React.createElement("div", null,
2115
+ "Last run: ",
2116
+ new Date(config.lastExecutedAt).toLocaleString()))))))))))));
2117
+ };
2118
+
2119
+ // Analytics Icon SVG
2120
+ const ANALYTICS_ICON_SVG = (React.createElement("svg", { xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 24 24", width: "1em", height: "1em", fill: "currentColor" },
2121
+ React.createElement("path", { d: "M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zM9 17H7v-7h2v7zm4 0h-2V7h2v10zm4 0h-2v-4h2v4z" })));
2122
+ const AnalyticsWidget = ({ position = 'bottom-right', theme: customTheme, onDirectiveAction, }) => {
2123
+ const { theme: contextTheme } = useReactBridgeContext();
2124
+ const theme = customTheme || contextTheme;
2125
+ const { configs, isLoading } = useAnalyticsConfigs();
2126
+ const [isOpen, setIsOpen] = React.useState(false);
2127
+ const enabledCount = configs.filter((c) => c.isEnabled).length;
2128
+ const positionStyles = position === 'bottom-right'
2129
+ ? { right: theme.spacing.lg, bottom: theme.spacing.lg }
2130
+ : { left: theme.spacing.lg, bottom: theme.spacing.lg };
2131
+ return (React.createElement(React.Fragment, null,
2132
+ React.createElement("button", { onClick: () => setIsOpen(!isOpen), style: Object.assign(Object.assign({ position: 'fixed' }, positionStyles), { width: '60px', height: '60px', borderRadius: '50%', backgroundColor: theme.colors.primary, color: '#fff', border: 'none', boxShadow: theme.boxShadow, cursor: 'pointer', display: 'flex', alignItems: 'center', justifyContent: 'center', fontSize: '24px', zIndex: 1000, transition: 'transform 0.2s ease' }), onMouseEnter: (e) => {
2133
+ e.currentTarget.style.transform = 'scale(1.1)';
2134
+ }, onMouseLeave: (e) => {
2135
+ e.currentTarget.style.transform = 'scale(1)';
2136
+ } },
2137
+ ANALYTICS_ICON_SVG,
2138
+ !isLoading && enabledCount > 0 && (React.createElement("span", { style: {
2139
+ position: 'absolute',
2140
+ top: '-5px',
2141
+ right: '-5px',
2142
+ backgroundColor: theme.colors.error,
2143
+ color: '#fff',
2144
+ borderRadius: '50%',
2145
+ width: '24px',
2146
+ height: '24px',
2147
+ display: 'flex',
2148
+ alignItems: 'center',
2149
+ justifyContent: 'center',
2150
+ fontSize: '12px',
2151
+ fontWeight: 'bold',
2152
+ } }, enabledCount))),
2153
+ isOpen && (React.createElement(AnalyticsDrawer, { isOpen: isOpen, onClose: () => setIsOpen(false), configs: configs, isLoading: isLoading, theme: theme, onDirectiveAction: onDirectiveAction }))));
2154
+ };
2155
+
2156
+ exports.AnalyticsAPI = AnalyticsAPI;
2157
+ exports.AnalyticsReport = AnalyticsReport;
2158
+ exports.AnalyticsWidget = AnalyticsWidget;
2159
+ exports.DirectivesPanel = DirectivesPanel;
2160
+ exports.MetricsPanel = MetricsPanel;
2161
+ exports.ObservationsPanel = ObservationsPanel;
1440
2162
  exports.ReactBridgeAPI = ReactBridgeAPI;
1441
2163
  exports.ReactBridgeChatbox = ReactBridgeChatbox;
1442
2164
  exports.ReactBridgeProvider = ReactBridgeProvider;
@@ -1447,6 +2169,9 @@ exports.createCustomTheme = createCustomTheme;
1447
2169
  exports.darkTheme = darkTheme;
1448
2170
  exports.getTheme = getTheme;
1449
2171
  exports.lightTheme = lightTheme;
2172
+ exports.useAnalyticsConfigs = useAnalyticsConfigs;
2173
+ exports.useAnalyticsResult = useAnalyticsResult;
2174
+ exports.useDirectiveAction = useDirectiveAction;
1450
2175
  exports.useReactBridge = useReactBridge;
1451
2176
  exports.useReactBridgeContext = useReactBridgeContext;
1452
2177
  //# sourceMappingURL=index.js.map