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