reactbridge-sdk 0.2.6 → 0.2.8

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 (89) hide show
  1. package/README.md +85 -1
  2. package/dist/components/ReactBridgeChatbox.d.ts.map +1 -1
  3. package/dist/components/ReactBridgeSearch.d.ts +2 -2
  4. package/dist/components/ReactBridgeSearch.d.ts.map +1 -1
  5. package/dist/components/ReportsDashboard.d.ts +13 -0
  6. package/dist/components/ReportsDashboard.d.ts.map +1 -0
  7. package/dist/components/analytics/AnalyticsDashboard.d.ts.map +1 -1
  8. package/dist/components/analytics/AnalyticsDrawer.d.ts +3 -3
  9. package/dist/components/analytics/AnalyticsDrawer.d.ts.map +1 -1
  10. package/dist/components/analytics/AnalyticsReport.d.ts +3 -3
  11. package/dist/components/analytics/AnalyticsReport.d.ts.map +1 -1
  12. package/dist/components/analytics/AnalyticsWidget.d.ts +4 -4
  13. package/dist/components/analytics/DirectivesPanel.d.ts +3 -3
  14. package/dist/components/analytics/DirectivesPanel.d.ts.map +1 -1
  15. package/dist/components/analytics/MetricsPanel.d.ts +3 -3
  16. package/dist/components/analytics/MetricsPanel.d.ts.map +1 -1
  17. package/dist/components/analytics/ObservationsPanel.d.ts +3 -3
  18. package/dist/components/analytics/ObservationsPanel.d.ts.map +1 -1
  19. package/dist/components/reports/DataQualityAutomation.d.ts +12 -0
  20. package/dist/components/reports/DataQualityAutomation.d.ts.map +1 -0
  21. package/dist/components/reports/DataTable.d.ts +24 -0
  22. package/dist/components/reports/DataTable.d.ts.map +1 -0
  23. package/dist/components/reports/DateRangeSelector.d.ts +14 -0
  24. package/dist/components/reports/DateRangeSelector.d.ts.map +1 -0
  25. package/dist/components/reports/ExecutionAuditTrail.d.ts +12 -0
  26. package/dist/components/reports/ExecutionAuditTrail.d.ts.map +1 -0
  27. package/dist/components/reports/ExecutiveDashboard.d.ts +12 -0
  28. package/dist/components/reports/ExecutiveDashboard.d.ts.map +1 -0
  29. package/dist/components/reports/HealthGauge.d.ts +14 -0
  30. package/dist/components/reports/HealthGauge.d.ts.map +1 -0
  31. package/dist/components/reports/LoadingState.d.ts +12 -0
  32. package/dist/components/reports/LoadingState.d.ts.map +1 -0
  33. package/dist/components/reports/MetricCard.d.ts +18 -0
  34. package/dist/components/reports/MetricCard.d.ts.map +1 -0
  35. package/dist/components/reports/PortfolioHealth.d.ts +12 -0
  36. package/dist/components/reports/PortfolioHealth.d.ts.map +1 -0
  37. package/dist/components/reports/ProgressBar.d.ts +15 -0
  38. package/dist/components/reports/ProgressBar.d.ts.map +1 -0
  39. package/dist/components/reports/ReportLayout.d.ts +19 -0
  40. package/dist/components/reports/ReportLayout.d.ts.map +1 -0
  41. package/dist/components/reports/RiskMatrix.d.ts +21 -0
  42. package/dist/components/reports/RiskMatrix.d.ts.map +1 -0
  43. package/dist/components/reports/StatusBadge.d.ts +14 -0
  44. package/dist/components/reports/StatusBadge.d.ts.map +1 -0
  45. package/dist/components/reports/SupplyChainRisk.d.ts +12 -0
  46. package/dist/components/reports/SupplyChainRisk.d.ts.map +1 -0
  47. package/dist/components/reports/TrendChart.d.ts +19 -0
  48. package/dist/components/reports/TrendChart.d.ts.map +1 -0
  49. package/dist/hooks/analytics/useAnalyticsConfigs.d.ts +1 -1
  50. package/dist/hooks/analytics/useAnalyticsResult.d.ts +1 -1
  51. package/dist/hooks/analytics/useDateRange.d.ts +18 -0
  52. package/dist/hooks/analytics/useDateRange.d.ts.map +1 -0
  53. package/dist/hooks/analytics/useDirectiveAction.d.ts +2 -2
  54. package/dist/hooks/analytics/useDirectiveAction.d.ts.map +1 -1
  55. package/dist/hooks/analytics/useReportData.d.ts +24 -0
  56. package/dist/hooks/analytics/useReportData.d.ts.map +1 -0
  57. package/dist/hooks/useReactBridge.d.ts +1 -1
  58. package/dist/hooks/useReactBridge.d.ts.map +1 -1
  59. package/dist/index.d.ts +67 -28
  60. package/dist/index.d.ts.map +1 -1
  61. package/dist/index.esm.js +2338 -389
  62. package/dist/index.esm.js.map +1 -1
  63. package/dist/index.js +2355 -387
  64. package/dist/index.js.map +1 -1
  65. package/dist/provider/ReactBridgeProvider.d.ts +3 -3
  66. package/dist/provider/ReactBridgeProvider.d.ts.map +1 -1
  67. package/dist/themes/dark.d.ts +1 -1
  68. package/dist/themes/index.d.ts +3 -3
  69. package/dist/themes/index.d.ts.map +1 -1
  70. package/dist/themes/light.d.ts +1 -1
  71. package/dist/types/analytics.d.ts +5 -5
  72. package/dist/types/index.d.ts +5 -4
  73. package/dist/types/index.d.ts.map +1 -1
  74. package/dist/types/reports.d.ts +158 -0
  75. package/dist/types/reports.d.ts.map +1 -0
  76. package/dist/utils/analytics-api.d.ts +3 -3
  77. package/dist/utils/analytics-api.d.ts.map +1 -1
  78. package/dist/utils/api.d.ts +12 -1
  79. package/dist/utils/api.d.ts.map +1 -1
  80. package/dist/utils/contextDiff.d.ts +1 -1
  81. package/dist/utils/contextDiff.d.ts.map +1 -1
  82. package/dist/utils/date-range.d.ts +32 -0
  83. package/dist/utils/date-range.d.ts.map +1 -0
  84. package/dist/utils/reports-api.d.ts +19 -0
  85. package/dist/utils/reports-api.d.ts.map +1 -0
  86. package/dist/utils/request-cache.d.ts +32 -0
  87. package/dist/utils/request-cache.d.ts.map +1 -0
  88. package/dist/utils/voice.d.ts.map +1 -1
  89. package/package.json +3 -3
package/dist/index.esm.js CHANGED
@@ -1,4 +1,4 @@
1
- import React, { createContext, useState, useContext, useRef, useEffect, useCallback } from 'react';
1
+ import React, { createContext, useState, useContext, useRef, useEffect, useCallback, useMemo } from 'react';
2
2
 
3
3
  /******************************************************************************
4
4
  Copyright (c) Microsoft Corporation.
@@ -32,7 +32,7 @@ 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$1 = '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;
@@ -45,13 +45,15 @@ class ReactBridgeAPI {
45
45
  // Configure abort signal for fetch with robust fallback.
46
46
  // `ReactBridgeConfig.timeout` is milliseconds. If it's undefined, no timeout is applied.
47
47
  // If it's 0 or a non-positive number, timeout is disabled.
48
- const timeoutMs = typeof this.config.timeout === 'number' ? this.config.timeout : undefined;
48
+ const timeoutMs = typeof this.config.timeout === "number"
49
+ ? this.config.timeout
50
+ : undefined;
49
51
  let controller = null;
50
52
  let timeoutId = null;
51
53
  let signal;
52
- if (typeof timeoutMs === 'number' && timeoutMs > 0) {
54
+ if (typeof timeoutMs === "number" && timeoutMs > 0) {
53
55
  // Prefer built-in AbortSignal.timeout when available
54
- if (typeof AbortSignal.timeout === 'function') {
56
+ if (typeof AbortSignal.timeout === "function") {
55
57
  signal = AbortSignal.timeout(timeoutMs);
56
58
  }
57
59
  else {
@@ -62,43 +64,43 @@ class ReactBridgeAPI {
62
64
  }
63
65
  // Check if this is a multimodal request (has image or document)
64
66
  const hasFile = request.image || request.document;
65
- let headers = Object.assign({ 'X-API-Key': this.config.apiKey }, this.config.headers);
67
+ let headers = Object.assign({ "X-API-Key": this.config.apiKey }, this.config.headers);
66
68
  let body;
67
69
  if (hasFile) {
68
70
  // Use FormData for file uploads
69
71
  const formData = new FormData();
70
72
  // Add text fields
71
- formData.append('userId', request.userId);
72
- formData.append('query', request.query);
73
+ formData.append("userId", request.userId);
74
+ formData.append("query", request.query);
73
75
  if (request.userName)
74
- formData.append('userName', request.userName);
76
+ formData.append("userName", request.userName);
75
77
  if (request.userPreferences)
76
- formData.append('userPreferences', request.userPreferences);
78
+ formData.append("userPreferences", request.userPreferences);
77
79
  if (request.userRecentActivity)
78
- formData.append('userRecentActivity', request.userRecentActivity);
80
+ formData.append("userRecentActivity", request.userRecentActivity);
79
81
  if (request.interfaceState)
80
82
  formData.append("InterfaceStateJson", JSON.stringify(request.interfaceState));
81
83
  if (request.sessionId)
82
- formData.append('sessionId', request.sessionId);
84
+ formData.append("sessionId", request.sessionId);
83
85
  if (request.modalityHint)
84
- formData.append('modalityHint', request.modalityHint);
86
+ formData.append("modalityHint", request.modalityHint);
85
87
  // Add files
86
88
  if (request.image)
87
- formData.append('image', request.image);
89
+ formData.append("image", request.image);
88
90
  if (request.document)
89
- formData.append('document', request.document);
91
+ formData.append("document", request.document);
90
92
  body = formData;
91
93
  // Don't set Content-Type for FormData - let browser set it with boundary
92
- delete headers['Content-Type'];
94
+ delete headers["Content-Type"];
93
95
  }
94
96
  else {
95
97
  // Use JSON for text-only requests
96
- headers['Content-Type'] = 'application/json';
98
+ headers["Content-Type"] = "application/json";
97
99
  body = JSON.stringify(request);
98
100
  }
99
101
  // console.log('Sending request to ReactBridge API:', { url, headers, body, timeoutMs });
100
102
  const response = yield fetch(url, {
101
- method: 'POST',
103
+ method: "POST",
102
104
  headers,
103
105
  body,
104
106
  signal,
@@ -118,7 +120,7 @@ class ReactBridgeAPI {
118
120
  if (error instanceof Error) {
119
121
  throw new Error(`ReactBridge API Error: ${error.message}`);
120
122
  }
121
- throw new Error('ReactBridge API Error: Unknown error occurred');
123
+ throw new Error("ReactBridge API Error: Unknown error occurred");
122
124
  }
123
125
  });
124
126
  }
@@ -138,65 +140,164 @@ class ReactBridgeAPI {
138
140
  });
139
141
  }
140
142
  sendImageRequest(userId_1, imageFile_1) {
141
- return __awaiter(this, arguments, void 0, function* (userId, imageFile, query = '', context) {
143
+ return __awaiter(this, arguments, void 0, function* (userId, imageFile, query = "", context) {
142
144
  const request = Object.assign({ userId,
143
- query, image: imageFile, modalityHint: 'image' }, context);
145
+ query, image: imageFile, modalityHint: "image" }, context);
144
146
  return this.sendMessage(request);
145
147
  });
146
148
  }
147
149
  sendDocumentRequest(userId_1, documentFile_1) {
148
- return __awaiter(this, arguments, void 0, function* (userId, documentFile, query = '', context) {
150
+ return __awaiter(this, arguments, void 0, function* (userId, documentFile, query = "", context) {
149
151
  const request = Object.assign({ userId,
150
- query, document: documentFile, modalityHint: 'document' }, context);
152
+ query, document: documentFile, modalityHint: "document" }, context);
151
153
  return this.sendMessage(request);
152
154
  });
153
155
  }
156
+ /**
157
+ * Report API Methods - Call analytics endpoints directly
158
+ */
159
+ fetchReport(endpoint, params) {
160
+ return __awaiter(this, void 0, void 0, function* () {
161
+ const baseURL = this.config.baseURL || DEFAULT_BASE_URL$1;
162
+ const url = new URL(`${baseURL}/api/reports/${endpoint}`);
163
+ // Add query parameters if provided
164
+ if (params) {
165
+ for (const key in params) {
166
+ if (params.hasOwnProperty(key)) {
167
+ url.searchParams.append(key, params[key]);
168
+ }
169
+ }
170
+ }
171
+ try {
172
+ const response = yield fetch(url.toString(), {
173
+ method: "GET",
174
+ headers: Object.assign({ "X-API-Key": this.config.apiKey, "Content-Type": "application/json" }, this.config.headers),
175
+ });
176
+ if (!response.ok) {
177
+ const errorMessage = this.getErrorMessage(response.status);
178
+ throw new Error(errorMessage);
179
+ }
180
+ return (yield response.json());
181
+ }
182
+ catch (error) {
183
+ if (error instanceof Error) {
184
+ throw error;
185
+ }
186
+ throw new Error("Failed to fetch report data");
187
+ }
188
+ });
189
+ }
190
+ getErrorMessage(status) {
191
+ switch (status) {
192
+ case 401:
193
+ return "Unauthorized: Invalid API key";
194
+ case 404:
195
+ return "Report endpoint not found";
196
+ case 500:
197
+ return "Server error: Unable to fetch report data";
198
+ default:
199
+ return `API Error: ${status}`;
200
+ }
201
+ }
202
+ getExecutiveDashboard(params) {
203
+ return __awaiter(this, void 0, void 0, function* () {
204
+ const queryParams = {};
205
+ if (params === null || params === void 0 ? void 0 : params.startDate)
206
+ queryParams.startDate = params.startDate;
207
+ if (params === null || params === void 0 ? void 0 : params.endDate)
208
+ queryParams.endDate = params.endDate;
209
+ return this.fetchReport("executive-dashboard", queryParams);
210
+ });
211
+ }
212
+ getSupplyChainRisk(params) {
213
+ return __awaiter(this, void 0, void 0, function* () {
214
+ const queryParams = {};
215
+ if (params === null || params === void 0 ? void 0 : params.startDate)
216
+ queryParams.startDate = params.startDate;
217
+ if (params === null || params === void 0 ? void 0 : params.endDate)
218
+ queryParams.endDate = params.endDate;
219
+ return this.fetchReport("supply-chain-risk", queryParams);
220
+ });
221
+ }
222
+ getExecutionAuditTrail(params) {
223
+ return __awaiter(this, void 0, void 0, function* () {
224
+ const queryParams = {};
225
+ if (params === null || params === void 0 ? void 0 : params.startDate)
226
+ queryParams.startDate = params.startDate;
227
+ if (params === null || params === void 0 ? void 0 : params.endDate)
228
+ queryParams.endDate = params.endDate;
229
+ if (params === null || params === void 0 ? void 0 : params.directiveType)
230
+ queryParams.directiveType = params.directiveType;
231
+ return this.fetchReport("execution-audit-trail", queryParams);
232
+ });
233
+ }
234
+ getPortfolioHealth(params) {
235
+ return __awaiter(this, void 0, void 0, function* () {
236
+ const queryParams = {};
237
+ if (params === null || params === void 0 ? void 0 : params.startDate)
238
+ queryParams.startDate = params.startDate;
239
+ if (params === null || params === void 0 ? void 0 : params.endDate)
240
+ queryParams.endDate = params.endDate;
241
+ return this.fetchReport("portfolio-health", queryParams);
242
+ });
243
+ }
244
+ getDataQualityAutomation(params) {
245
+ return __awaiter(this, void 0, void 0, function* () {
246
+ const queryParams = {};
247
+ if (params === null || params === void 0 ? void 0 : params.startDate)
248
+ queryParams.startDate = params.startDate;
249
+ if (params === null || params === void 0 ? void 0 : params.endDate)
250
+ queryParams.endDate = params.endDate;
251
+ return this.fetchReport("data-quality-automation", queryParams);
252
+ });
253
+ }
154
254
  }
155
255
 
156
256
  const lightTheme = {
157
- name: 'light',
257
+ name: "light",
158
258
  colors: {
159
- primary: '#1976d2',
160
- secondary: '#dc004e',
161
- background: '#ffffff',
162
- surface: '#f5f5f5',
163
- text: '#000000',
164
- textSecondary: '#666666',
165
- border: '#e0e0e0',
166
- error: '#f44336',
167
- success: '#4caf50',
259
+ primary: "#1976d2",
260
+ secondary: "#dc004e",
261
+ background: "#ffffff",
262
+ surface: "#f5f5f5",
263
+ text: "#000000",
264
+ textSecondary: "#666666",
265
+ border: "#e0e0e0",
266
+ error: "#f44336",
267
+ success: "#4caf50",
168
268
  },
169
269
  spacing: {
170
- xs: '4px',
171
- sm: '8px',
172
- md: '16px',
173
- lg: '24px',
174
- xl: '32px',
270
+ xs: "4px",
271
+ sm: "8px",
272
+ md: "16px",
273
+ lg: "24px",
274
+ xl: "32px",
175
275
  },
176
276
  fontSizes: {
177
- xs: '12px',
178
- sm: '14px',
179
- md: '16px',
180
- lg: '18px',
181
- xl: '24px',
277
+ xs: "12px",
278
+ sm: "14px",
279
+ md: "16px",
280
+ lg: "18px",
281
+ xl: "24px",
182
282
  },
183
- borderRadius: '8px',
184
- boxShadow: '0 2px 8px rgba(0, 0, 0, 0.1)',
283
+ borderRadius: "8px",
284
+ boxShadow: "0 2px 8px rgba(0, 0, 0, 0.1)",
185
285
  };
186
286
 
187
287
  // Default STT Provider using Web Speech API
188
288
  class WebSpeechSTTProvider {
189
289
  constructor() {
190
- if (typeof window !== 'undefined') {
191
- const SpeechRecognitionCtor = window.SpeechRecognition || window.webkitSpeechRecognition;
290
+ if (typeof window !== "undefined") {
291
+ const SpeechRecognitionCtor = window.SpeechRecognition ||
292
+ window.webkitSpeechRecognition;
192
293
  if (SpeechRecognitionCtor) {
193
294
  this.recognition = new SpeechRecognitionCtor();
194
295
  if (!this.recognition) {
195
- throw new Error('Failed to initialize SpeechRecognition');
296
+ throw new Error("Failed to initialize SpeechRecognition");
196
297
  }
197
298
  this.recognition.continuous = false;
198
299
  this.recognition.interimResults = false;
199
- this.recognition.lang = 'en-US';
300
+ this.recognition.lang = "en-US";
200
301
  this.recognition.onresult = (event) => {
201
302
  var _a;
202
303
  const transcript = event.results[0][0].transcript;
@@ -208,7 +309,7 @@ class WebSpeechSTTProvider {
208
309
  };
209
310
  }
210
311
  else {
211
- console.warn('SpeechRecognition API not supported in this browser.');
312
+ console.warn("SpeechRecognition API not supported in this browser.");
212
313
  }
213
314
  }
214
315
  }
@@ -217,7 +318,7 @@ class WebSpeechSTTProvider {
217
318
  this.recognition.start();
218
319
  }
219
320
  else {
220
- throw new Error('Speech recognition not supported');
321
+ throw new Error("Speech recognition not supported");
221
322
  }
222
323
  }
223
324
  stopRecognition() {
@@ -234,16 +335,16 @@ class WebSpeechSTTProvider {
234
335
  // Default TTS Provider using Web Speech API
235
336
  class WebSpeechTTSProvider {
236
337
  speak(text) {
237
- if (typeof window !== 'undefined' && 'speechSynthesis' in window) {
338
+ if (typeof window !== "undefined" && "speechSynthesis" in window) {
238
339
  const utterance = new SpeechSynthesisUtterance(text);
239
340
  window.speechSynthesis.speak(utterance);
240
341
  }
241
342
  else {
242
- console.warn('Text-to-speech not supported');
343
+ console.warn("Text-to-speech not supported");
243
344
  }
244
345
  }
245
346
  stop() {
246
- if (typeof window !== 'undefined' && 'speechSynthesis' in window) {
347
+ if (typeof window !== "undefined" && "speechSynthesis" in window) {
247
348
  window.speechSynthesis.cancel();
248
349
  }
249
350
  }
@@ -255,14 +356,10 @@ function ReactBridgeProvider({ apiKey, config = {}, theme = lightTheme, sttProvi
255
356
  apiKey,
256
357
  baseURL: config.baseURL,
257
358
  // Preserve explicit 0 (to disable timeouts). If not provided, default to 30s
258
- timeout: typeof config.timeout === 'number' ? config.timeout : 30000,
359
+ timeout: typeof config.timeout === "number" ? config.timeout : 30000,
259
360
  headers: config.headers,
260
361
  };
261
- const api = React.useMemo(() => new ReactBridgeAPI(fullConfig), [
262
- fullConfig.apiKey,
263
- fullConfig.baseURL,
264
- fullConfig.timeout,
265
- ]);
362
+ const api = React.useMemo(() => new ReactBridgeAPI(fullConfig), [fullConfig.apiKey, fullConfig.baseURL, fullConfig.timeout]);
266
363
  const [sttProvider, setSTTProvider] = useState(initialSTTProvider || new WebSpeechSTTProvider());
267
364
  const [ttsProvider, setTTSProvider] = useState(initialTTSProvider || new WebSpeechTTSProvider());
268
365
  const value = {
@@ -279,7 +376,7 @@ function ReactBridgeProvider({ apiKey, config = {}, theme = lightTheme, sttProvi
279
376
  function useReactBridgeContext() {
280
377
  const context = useContext(ReactBridgeContext);
281
378
  if (!context) {
282
- throw new Error('useReactBridgeContext must be used within a ReactBridgeProvider');
379
+ throw new Error("useReactBridgeContext must be used within a ReactBridgeProvider");
283
380
  }
284
381
  return context;
285
382
  }
@@ -288,7 +385,8 @@ function hasContextChanged(previous, current) {
288
385
  if (!previous)
289
386
  return true;
290
387
  // Check if page changed
291
- if (previous.interfaceState.currentPageName !== current.interfaceState.currentPageName) {
388
+ if (previous.interfaceState.currentPageName !==
389
+ current.interfaceState.currentPageName) {
292
390
  return true;
293
391
  }
294
392
  // Check if viewing items changed
@@ -298,8 +396,8 @@ function hasContextChanged(previous, current) {
298
396
  return true;
299
397
  }
300
398
  // Check if item IDs changed
301
- const prevIds = prevItems.map(item => item.id).sort();
302
- const currIds = currItems.map(item => item.id).sort();
399
+ const prevIds = prevItems.map((item) => item.id).sort();
400
+ const currIds = currItems.map((item) => item.id).sort();
303
401
  return JSON.stringify(prevIds) !== JSON.stringify(currIds);
304
402
  }
305
403
  function getContextSummary(context) {
@@ -308,14 +406,14 @@ function getContextSummary(context) {
308
406
  parts.push(`Page: ${interfaceState.currentPageName}`);
309
407
  if (interfaceState.viewingItems && interfaceState.viewingItems.length > 0) {
310
408
  parts.push(`Viewing ${interfaceState.viewingItems.length} items:`);
311
- interfaceState.viewingItems.slice(0, 3).forEach(item => {
409
+ interfaceState.viewingItems.slice(0, 3).forEach((item) => {
312
410
  parts.push(` - ${item.name} ($${item.price})`);
313
411
  });
314
412
  if (interfaceState.viewingItems.length > 3) {
315
413
  parts.push(` ... and ${interfaceState.viewingItems.length - 3} more`);
316
414
  }
317
415
  }
318
- return parts.join('\n');
416
+ return parts.join("\n");
319
417
  }
320
418
 
321
419
  function useReactBridge({ onIntentDetected, currentContext, onError, onSpeechStart, onSpeechEnd, onTranscript, onAgentResponse, }) {
@@ -333,17 +431,17 @@ function useReactBridge({ onIntentDetected, currentContext, onError, onSpeechSta
333
431
  const contextSummary = getContextSummary(currentContext);
334
432
  const contextMessage = {
335
433
  id: `context-${Date.now()}`,
336
- role: 'system',
434
+ role: "system",
337
435
  content: `[Context Update]\n${contextSummary}`,
338
436
  timestamp: new Date(),
339
437
  };
340
- setMessages(prev => [...prev, contextMessage]);
438
+ setMessages((prev) => [...prev, contextMessage]);
341
439
  previousContextRef.current = currentContext;
342
440
  }
343
441
  }, [currentContext]);
344
442
  const sendChatQuery = useCallback((queryOrOptions_1, ...args_1) => __awaiter(this, [queryOrOptions_1, ...args_1], void 0, function* (queryOrOptions, fromVoiceInput = false) {
345
- const isMultimodal = typeof queryOrOptions === 'object';
346
- const query = isMultimodal ? (queryOrOptions.query || '') : queryOrOptions;
443
+ const isMultimodal = typeof queryOrOptions === "object";
444
+ const query = isMultimodal ? queryOrOptions.query || "" : queryOrOptions;
347
445
  const image = isMultimodal ? queryOrOptions.image : undefined;
348
446
  const document = isMultimodal ? queryOrOptions.document : undefined;
349
447
  if (!query.trim() && !image && !document)
@@ -353,18 +451,22 @@ function useReactBridge({ onIntentDetected, currentContext, onError, onSpeechSta
353
451
  // Add user message with file info if present
354
452
  let messageContent = query;
355
453
  if (image) {
356
- messageContent = messageContent ? `${messageContent} [Image: ${image.name}]` : `[Image: ${image.name}]`;
454
+ messageContent = messageContent
455
+ ? `${messageContent} [Image: ${image.name}]`
456
+ : `[Image: ${image.name}]`;
357
457
  }
358
458
  else if (document) {
359
- messageContent = messageContent ? `${messageContent} [Document: ${document.name}]` : `[Document: ${document.name}]`;
459
+ messageContent = messageContent
460
+ ? `${messageContent} [Document: ${document.name}]`
461
+ : `[Document: ${document.name}]`;
360
462
  }
361
463
  const userMessage = {
362
464
  id: `user-${Date.now()}`,
363
- role: 'user',
465
+ role: "user",
364
466
  content: messageContent,
365
467
  timestamp: new Date(),
366
468
  };
367
- setMessages(prev => [...prev, userMessage]);
469
+ setMessages((prev) => [...prev, userMessage]);
368
470
  try {
369
471
  // Step 1: Send initial request to orchestrator
370
472
  const request = {
@@ -379,12 +481,12 @@ function useReactBridge({ onIntentDetected, currentContext, onError, onSpeechSta
379
481
  // Add multimodal fields
380
482
  image,
381
483
  document,
382
- modalityHint: image ? 'image' : document ? 'document' : undefined,
484
+ modalityHint: image ? "image" : document ? "document" : undefined,
383
485
  };
384
486
  lastRequestRef.current = request;
385
487
  const response = yield api.sendMessage(request);
386
488
  if (!response.success) {
387
- throw new Error(response.error || 'Request failed');
489
+ throw new Error(response.error || "Request failed");
388
490
  }
389
491
  // Update session ID
390
492
  if (response.sessionId) {
@@ -393,12 +495,12 @@ function useReactBridge({ onIntentDetected, currentContext, onError, onSpeechSta
393
495
  // Add assistant message
394
496
  const assistantMessage = {
395
497
  id: `assistant-${Date.now()}`,
396
- role: 'assistant',
498
+ role: "assistant",
397
499
  content: response.message,
398
500
  timestamp: new Date(),
399
501
  toolCall: response.toolCall,
400
502
  };
401
- setMessages(prev => [...prev, assistantMessage]);
503
+ setMessages((prev) => [...prev, assistantMessage]);
402
504
  // Trigger TTS and callback only if input came from voice
403
505
  if (fromVoiceInput) {
404
506
  ttsProvider.speak(response.message);
@@ -416,11 +518,11 @@ function useReactBridge({ onIntentDetected, currentContext, onError, onSpeechSta
416
518
  // Add final assistant message with tool result context
417
519
  const finalMessage = {
418
520
  id: `assistant-final-${Date.now()}`,
419
- role: 'assistant',
521
+ role: "assistant",
420
522
  content: resultResponse.message,
421
523
  timestamp: new Date(),
422
524
  };
423
- setMessages(prev => [...prev, finalMessage]);
525
+ setMessages((prev) => [...prev, finalMessage]);
424
526
  // Trigger TTS for final response only if input came from voice
425
527
  if (fromVoiceInput) {
426
528
  ttsProvider.speak(resultResponse.message);
@@ -433,30 +535,32 @@ function useReactBridge({ onIntentDetected, currentContext, onError, onSpeechSta
433
535
  catch (toolError) {
434
536
  const errorMessage = toolError instanceof Error
435
537
  ? toolError.message
436
- : 'Tool execution failed';
538
+ : "Tool execution failed";
437
539
  const errorMsg = {
438
540
  id: `error-${Date.now()}`,
439
- role: 'assistant',
541
+ role: "assistant",
440
542
  content: `I encountered an error: ${errorMessage}`,
441
543
  timestamp: new Date(),
442
544
  };
443
- setMessages(prev => [...prev, errorMsg]);
545
+ setMessages((prev) => [...prev, errorMsg]);
444
546
  if (onError) {
445
- onError(toolError instanceof Error ? toolError : new Error(errorMessage));
547
+ onError(toolError instanceof Error
548
+ ? toolError
549
+ : new Error(errorMessage));
446
550
  }
447
551
  }
448
552
  }
449
553
  }
450
554
  catch (err) {
451
- const error = err instanceof Error ? err : new Error('Unknown error');
555
+ const error = err instanceof Error ? err : new Error("Unknown error");
452
556
  setError(error);
453
557
  const errorMessage = {
454
558
  id: `error-${Date.now()}`,
455
- role: 'assistant',
559
+ role: "assistant",
456
560
  content: `Sorry, I encountered an error: ${error.message}`,
457
561
  timestamp: new Date(),
458
562
  };
459
- setMessages(prev => [...prev, errorMessage]);
563
+ setMessages((prev) => [...prev, errorMessage]);
460
564
  if (onError) {
461
565
  onError(error);
462
566
  }
@@ -497,7 +601,14 @@ function useReactBridge({ onIntentDetected, currentContext, onError, onSpeechSta
497
601
  });
498
602
  }
499
603
  sttProvider.startRecognition();
500
- }, [sttProvider, sendChatQuery, onSpeechStart, onSpeechEnd, onTranscript, onError]);
604
+ }, [
605
+ sttProvider,
606
+ sendChatQuery,
607
+ onSpeechStart,
608
+ onSpeechEnd,
609
+ onTranscript,
610
+ onError,
611
+ ]);
501
612
  const stopVoiceInput = useCallback(() => {
502
613
  setIsListening(false);
503
614
  sttProvider.stopRecognition();
@@ -955,7 +1066,9 @@ toggleButtonClass = defaultToggleButtonClass, toggleButtonTitle = "Open chat ass
955
1066
  padding: theme.spacing.md,
956
1067
  backgroundColor: theme.colors.background,
957
1068
  } },
958
- messages.map((message) => renderMessage ? renderMessage(message) : defaultRenderMessage(message)),
1069
+ messages.map((message) => renderMessage
1070
+ ? renderMessage(message)
1071
+ : defaultRenderMessage(message)),
959
1072
  isLoading && React.createElement(TypingIndicator, { theme: theme }),
960
1073
  React.createElement("div", { ref: messagesEndRef })),
961
1074
  React.createElement("form", { onSubmit: handleSubmit, style: {
@@ -1110,10 +1223,10 @@ const MIC_ICON_SVG = (React.createElement("svg", { xmlns: "http://www.w3.org/200
1110
1223
  // Plus Icon SVG
1111
1224
  const PLUS_ICON_SVG = (React.createElement("svg", { xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 24 24", width: "1em", height: "1em", fill: "currentColor" },
1112
1225
  React.createElement("path", { d: "M19 13h-6v6h-2v-6H5v-2h6V5h2v6h6v2z" })));
1113
- function ReactBridgeSearch({ onIntentDetected, currentContext, placeholder = 'Search...', width = '100%', maxResults = 5, theme: themeOverride, onError, onSpeechStart, onSpeechEnd, onTranscript, onAgentResponse, }) {
1226
+ function ReactBridgeSearch({ onIntentDetected, currentContext, placeholder = "Search...", width = "100%", maxResults = 5, theme: themeOverride, onError, onSpeechStart, onSpeechEnd, onTranscript, onAgentResponse, }) {
1114
1227
  const { theme: contextTheme } = useReactBridgeContext();
1115
1228
  const theme = Object.assign(Object.assign({}, contextTheme), themeOverride);
1116
- const { messages, isLoading, sendChatQuery, isListening, startVoiceInput, stopVoiceInput } = useReactBridge({
1229
+ const { messages, isLoading, sendChatQuery, isListening, startVoiceInput, stopVoiceInput, } = useReactBridge({
1117
1230
  onIntentDetected,
1118
1231
  currentContext,
1119
1232
  onError,
@@ -1122,7 +1235,7 @@ function ReactBridgeSearch({ onIntentDetected, currentContext, placeholder = 'Se
1122
1235
  onTranscript,
1123
1236
  onAgentResponse,
1124
1237
  });
1125
- const [inputValue, setInputValue] = useState('');
1238
+ const [inputValue, setInputValue] = useState("");
1126
1239
  const [isOpen, setIsOpen] = useState(false);
1127
1240
  const [isUploadMenuOpen, setIsUploadMenuOpen] = useState(false);
1128
1241
  const [selectedFile, setSelectedFile] = useState(null);
@@ -1132,13 +1245,14 @@ function ReactBridgeSearch({ onIntentDetected, currentContext, placeholder = 'Se
1132
1245
  // Close dropdown and upload menu when clicking outside
1133
1246
  useEffect(() => {
1134
1247
  const handleClickOutside = (event) => {
1135
- if (containerRef.current && !containerRef.current.contains(event.target)) {
1248
+ if (containerRef.current &&
1249
+ !containerRef.current.contains(event.target)) {
1136
1250
  setIsOpen(false);
1137
1251
  setIsUploadMenuOpen(false);
1138
1252
  }
1139
1253
  };
1140
- document.addEventListener('mousedown', handleClickOutside);
1141
- return () => document.removeEventListener('mousedown', handleClickOutside);
1254
+ document.addEventListener("mousedown", handleClickOutside);
1255
+ return () => document.removeEventListener("mousedown", handleClickOutside);
1142
1256
  }, []);
1143
1257
  // Open dropdown when there are messages
1144
1258
  useEffect(() => {
@@ -1148,9 +1262,10 @@ function ReactBridgeSearch({ onIntentDetected, currentContext, placeholder = 'Se
1148
1262
  }, [messages]);
1149
1263
  const handleFileSelect = (type) => {
1150
1264
  if (fileInputRef.current) {
1151
- fileInputRef.current.accept = type === 'image'
1152
- ? 'image/png,image/jpeg,image/jpg,image/webp'
1153
- : 'application/pdf,application/msword,application/vnd.openxmlformats-officedocument.wordprocessingml.document,text/plain';
1265
+ fileInputRef.current.accept =
1266
+ type === "image"
1267
+ ? "image/png,image/jpeg,image/jpg,image/webp"
1268
+ : "application/pdf,application/msword,application/vnd.openxmlformats-officedocument.wordprocessingml.document,text/plain";
1154
1269
  fileInputRef.current.click();
1155
1270
  }
1156
1271
  setIsUploadMenuOpen(false);
@@ -1161,12 +1276,19 @@ function ReactBridgeSearch({ onIntentDetected, currentContext, placeholder = 'Se
1161
1276
  if (!file)
1162
1277
  return;
1163
1278
  // Validate file type
1164
- const imageTypes = ['image/png', 'image/jpeg', 'image/jpg', 'image/webp'];
1165
- const documentTypes = ['application/pdf', 'application/msword', 'application/vnd.openxmlformats-officedocument.wordprocessingml.document', 'text/plain'];
1166
- const allowedTypes = file.type.startsWith('image/') ? imageTypes : documentTypes;
1279
+ const imageTypes = ["image/png", "image/jpeg", "image/jpg", "image/webp"];
1280
+ const documentTypes = [
1281
+ "application/pdf",
1282
+ "application/msword",
1283
+ "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
1284
+ "text/plain",
1285
+ ];
1286
+ const allowedTypes = file.type.startsWith("image/")
1287
+ ? imageTypes
1288
+ : documentTypes;
1167
1289
  if (!allowedTypes.includes(file.type)) {
1168
1290
  if (onError) {
1169
- onError(new Error(`Invalid file type. Please select a valid ${file.type.startsWith('image/') ? 'image' : 'document'} file.`));
1291
+ onError(new Error(`Invalid file type. Please select a valid ${file.type.startsWith("image/") ? "image" : "document"} file.`));
1170
1292
  }
1171
1293
  return;
1172
1294
  }
@@ -1174,13 +1296,13 @@ function ReactBridgeSearch({ onIntentDetected, currentContext, placeholder = 'Se
1174
1296
  const maxSize = 10 * 1024 * 1024; // 10MB
1175
1297
  if (file.size > maxSize) {
1176
1298
  if (onError) {
1177
- onError(new Error('File size too large. Please select a file smaller than 10MB.'));
1299
+ onError(new Error("File size too large. Please select a file smaller than 10MB."));
1178
1300
  }
1179
1301
  return;
1180
1302
  }
1181
1303
  setSelectedFile(file);
1182
1304
  // Create preview for images
1183
- if (file.type.startsWith('image/')) {
1305
+ if (file.type.startsWith("image/")) {
1184
1306
  const reader = new FileReader();
1185
1307
  reader.onload = (e) => {
1186
1308
  var _a;
@@ -1197,7 +1319,7 @@ function ReactBridgeSearch({ onIntentDetected, currentContext, placeholder = 'Se
1197
1319
  setSelectedFile(null);
1198
1320
  setFilePreview(null);
1199
1321
  if (fileInputRef.current) {
1200
- fileInputRef.current.value = '';
1322
+ fileInputRef.current.value = "";
1201
1323
  }
1202
1324
  };
1203
1325
  const handleSubmit = (e) => __awaiter(this, void 0, void 0, function* () {
@@ -1205,13 +1327,17 @@ function ReactBridgeSearch({ onIntentDetected, currentContext, placeholder = 'Se
1205
1327
  if ((!inputValue.trim() && !selectedFile) || isLoading)
1206
1328
  return;
1207
1329
  const query = inputValue.trim();
1208
- setInputValue('');
1330
+ setInputValue("");
1209
1331
  // Handle multimodal request
1210
1332
  if (selectedFile && filePreview) {
1211
1333
  yield sendChatQuery({
1212
1334
  query,
1213
- image: selectedFile.type.startsWith('image/') ? selectedFile : undefined,
1214
- document: selectedFile.type.startsWith('image/') ? undefined : selectedFile,
1335
+ image: selectedFile.type.startsWith("image/")
1336
+ ? selectedFile
1337
+ : undefined,
1338
+ document: selectedFile.type.startsWith("image/")
1339
+ ? undefined
1340
+ : selectedFile,
1215
1341
  });
1216
1342
  removeFile();
1217
1343
  }
@@ -1221,33 +1347,33 @@ function ReactBridgeSearch({ onIntentDetected, currentContext, placeholder = 'Se
1221
1347
  });
1222
1348
  // Get only assistant messages (not system messages)
1223
1349
  const displayMessages = messages
1224
- .filter((msg) => msg.role === 'assistant')
1350
+ .filter((msg) => msg.role === "assistant")
1225
1351
  .slice(-maxResults);
1226
1352
  return (React.createElement("div", { ref: containerRef, style: {
1227
- position: 'relative',
1353
+ position: "relative",
1228
1354
  width,
1229
- fontFamily: 'system-ui, -apple-system, sans-serif',
1355
+ fontFamily: "system-ui, -apple-system, sans-serif",
1230
1356
  } },
1231
1357
  React.createElement("form", { onSubmit: handleSubmit },
1232
- React.createElement("div", { style: { position: 'relative' } },
1233
- React.createElement("input", { ref: fileInputRef, type: "file", onChange: handleFileChange, style: { display: 'none' } }),
1358
+ React.createElement("div", { style: { position: "relative" } },
1359
+ React.createElement("input", { ref: fileInputRef, type: "file", onChange: handleFileChange, style: { display: "none" } }),
1234
1360
  React.createElement("input", { type: "text", value: inputValue, onChange: (e) => setInputValue(e.target.value), onFocus: () => displayMessages.length > 0 && setIsOpen(true), placeholder: selectedFile ? `Search with ${selectedFile.name}...` : placeholder, disabled: isLoading, style: {
1235
- width: '100%',
1361
+ width: "100%",
1236
1362
  padding: theme.spacing.md,
1237
- paddingRight: '180px', // Increased to make room for plus, mic, and search buttons
1363
+ paddingRight: "180px", // Increased to make room for plus, mic, and search buttons
1238
1364
  fontSize: theme.fontSizes.md,
1239
1365
  border: `1px solid ${theme.colors.border}`,
1240
1366
  borderRadius: theme.borderRadius,
1241
1367
  backgroundColor: theme.colors.background,
1242
1368
  color: theme.colors.text,
1243
- outline: 'none',
1244
- boxSizing: 'border-box',
1369
+ outline: "none",
1370
+ boxSizing: "border-box",
1245
1371
  } }),
1246
1372
  React.createElement("button", { type: "button", onClick: () => setIsUploadMenuOpen(!isUploadMenuOpen), disabled: isLoading, title: "Upload file", style: {
1247
- position: 'absolute',
1248
- right: '105px', // Position before the mic button
1249
- top: '50%',
1250
- transform: 'translateY(-50%)',
1373
+ position: "absolute",
1374
+ right: "105px", // Position before the mic button
1375
+ top: "50%",
1376
+ transform: "translateY(-50%)",
1251
1377
  padding: theme.spacing.sm,
1252
1378
  marginRight: theme.spacing.xs,
1253
1379
  color: theme.colors.border,
@@ -1262,42 +1388,42 @@ function ReactBridgeSearch({ onIntentDetected, currentContext, placeholder = 'Se
1262
1388
  height: "32px",
1263
1389
  } }, PLUS_ICON_SVG),
1264
1390
  isUploadMenuOpen && (React.createElement("div", { style: {
1265
- position: 'absolute',
1266
- right: '105px',
1267
- top: '100%',
1391
+ position: "absolute",
1392
+ right: "105px",
1393
+ top: "100%",
1268
1394
  marginTop: theme.spacing.xs,
1269
1395
  backgroundColor: theme.colors.background,
1270
1396
  border: `1px solid ${theme.colors.border}`,
1271
1397
  borderRadius: theme.borderRadius,
1272
1398
  boxShadow: theme.boxShadow,
1273
1399
  zIndex: 1000,
1274
- minWidth: '120px',
1400
+ minWidth: "120px",
1275
1401
  } },
1276
- React.createElement("button", { type: "button", onClick: () => handleFileSelect('image'), style: {
1277
- width: '100%',
1402
+ React.createElement("button", { type: "button", onClick: () => handleFileSelect("image"), style: {
1403
+ width: "100%",
1278
1404
  padding: theme.spacing.sm,
1279
- backgroundColor: 'transparent',
1280
- border: 'none',
1405
+ backgroundColor: "transparent",
1406
+ border: "none",
1281
1407
  color: theme.colors.text,
1282
- cursor: 'pointer',
1283
- textAlign: 'left',
1408
+ cursor: "pointer",
1409
+ textAlign: "left",
1284
1410
  fontSize: theme.fontSizes.sm,
1285
1411
  } }, "\uD83D\uDCF7 Image"),
1286
- React.createElement("button", { type: "button", onClick: () => handleFileSelect('document'), style: {
1287
- width: '100%',
1412
+ React.createElement("button", { type: "button", onClick: () => handleFileSelect("document"), style: {
1413
+ width: "100%",
1288
1414
  padding: theme.spacing.sm,
1289
- backgroundColor: 'transparent',
1290
- border: 'none',
1415
+ backgroundColor: "transparent",
1416
+ border: "none",
1291
1417
  color: theme.colors.text,
1292
- cursor: 'pointer',
1293
- textAlign: 'left',
1418
+ cursor: "pointer",
1419
+ textAlign: "left",
1294
1420
  fontSize: theme.fontSizes.sm,
1295
1421
  } }, "\uD83D\uDCC4 Document"))),
1296
1422
  React.createElement("button", { type: "button", onClick: isListening ? stopVoiceInput : startVoiceInput, disabled: isLoading, title: isListening ? "Stop recording" : "Start voice input", style: {
1297
- position: 'absolute',
1298
- right: '70px', // Position before the search button
1299
- top: '50%',
1300
- transform: 'translateY(-50%)',
1423
+ position: "absolute",
1424
+ right: "70px", // Position before the search button
1425
+ top: "50%",
1426
+ transform: "translateY(-50%)",
1301
1427
  padding: theme.spacing.sm,
1302
1428
  marginRight: theme.spacing.xs,
1303
1429
  color: isListening ? theme.colors.primary : theme.colors.border,
@@ -1312,67 +1438,73 @@ function ReactBridgeSearch({ onIntentDetected, currentContext, placeholder = 'Se
1312
1438
  height: "32px",
1313
1439
  } }, MIC_ICON_SVG),
1314
1440
  React.createElement("button", { type: "submit", disabled: isLoading || (!inputValue.trim() && !selectedFile), style: {
1315
- position: 'absolute',
1441
+ position: "absolute",
1316
1442
  right: theme.spacing.sm,
1317
- top: '50%',
1318
- transform: 'translateY(-50%)',
1443
+ top: "50%",
1444
+ transform: "translateY(-50%)",
1319
1445
  padding: `${theme.spacing.xs} ${theme.spacing.md}`,
1320
1446
  fontSize: theme.fontSizes.sm,
1321
1447
  backgroundColor: theme.colors.primary,
1322
1448
  color: theme.colors.background,
1323
- border: 'none',
1449
+ border: "none",
1324
1450
  borderRadius: theme.borderRadius,
1325
- cursor: isLoading || (!inputValue.trim() && !selectedFile) ? 'not-allowed' : 'pointer',
1451
+ cursor: isLoading || (!inputValue.trim() && !selectedFile)
1452
+ ? "not-allowed"
1453
+ : "pointer",
1326
1454
  opacity: isLoading || (!inputValue.trim() && !selectedFile) ? 0.5 : 1,
1327
- } }, isLoading ? 'Searching...' : 'Search')),
1455
+ } }, isLoading ? "Searching..." : "Search")),
1328
1456
  selectedFile && filePreview && (React.createElement("div", { style: {
1329
1457
  marginTop: theme.spacing.sm,
1330
1458
  padding: theme.spacing.sm,
1331
1459
  backgroundColor: theme.colors.surface,
1332
1460
  border: `1px solid ${theme.colors.border}`,
1333
1461
  borderRadius: theme.borderRadius,
1334
- display: 'flex',
1335
- alignItems: 'center',
1462
+ display: "flex",
1463
+ alignItems: "center",
1336
1464
  gap: theme.spacing.sm,
1337
1465
  } },
1338
- selectedFile.type.startsWith('image/') ? (React.createElement("img", { src: filePreview, alt: "Preview", style: {
1339
- width: '40px',
1340
- height: '40px',
1341
- objectFit: 'cover',
1466
+ selectedFile.type.startsWith("image/") ? (React.createElement("img", { src: filePreview, alt: "Preview", style: {
1467
+ width: "40px",
1468
+ height: "40px",
1469
+ objectFit: "cover",
1342
1470
  borderRadius: theme.borderRadius,
1343
1471
  } })) : (React.createElement("div", { style: {
1344
- width: '40px',
1345
- height: '40px',
1472
+ width: "40px",
1473
+ height: "40px",
1346
1474
  backgroundColor: theme.colors.primary,
1347
1475
  borderRadius: theme.borderRadius,
1348
- display: 'flex',
1349
- alignItems: 'center',
1350
- justifyContent: 'center',
1476
+ display: "flex",
1477
+ alignItems: "center",
1478
+ justifyContent: "center",
1351
1479
  color: theme.colors.background,
1352
1480
  fontSize: theme.fontSizes.lg,
1353
1481
  } }, "\uD83D\uDCC4")),
1354
- React.createElement("div", { style: { flex: 1, fontSize: theme.fontSizes.sm, color: theme.colors.text } },
1355
- React.createElement("div", { style: { fontWeight: 'bold' } }, selectedFile.name),
1482
+ React.createElement("div", { style: {
1483
+ flex: 1,
1484
+ fontSize: theme.fontSizes.sm,
1485
+ color: theme.colors.text,
1486
+ } },
1487
+ React.createElement("div", { style: { fontWeight: "bold" } }, selectedFile.name),
1356
1488
  React.createElement("div", { style: { color: theme.colors.textSecondary } },
1357
1489
  (selectedFile.size / 1024 / 1024).toFixed(2),
1358
1490
  " MB")),
1359
1491
  React.createElement("button", { type: "button", onClick: removeFile, style: {
1360
1492
  padding: theme.spacing.xs,
1361
- backgroundColor: 'transparent',
1362
- border: 'none',
1493
+ backgroundColor: "transparent",
1494
+ border: "none",
1363
1495
  color: theme.colors.textSecondary,
1364
- cursor: 'pointer',
1496
+ cursor: "pointer",
1365
1497
  borderRadius: theme.borderRadius,
1366
- width: '24px',
1367
- height: '24px',
1368
- display: 'flex',
1369
- alignItems: 'center',
1370
- justifyContent: 'center',
1371
- fontSize: '18px',
1498
+ width: "24px",
1499
+ height: "24px",
1500
+ display: "flex",
1501
+ alignItems: "center",
1502
+ justifyContent: "center",
1503
+ fontSize: "18px",
1372
1504
  }, title: "Remove file" }, "\u00D7")))),
1373
1505
  isOpen && displayMessages.length > 0 && (React.createElement("div", { style: {
1374
- position: 'absolute',
1375
- top: '100%',
1506
+ position: "absolute",
1507
+ top: "100%",
1376
1508
  left: 0,
1377
1509
  right: 0,
1378
1510
  marginTop: theme.spacing.xs,
@@ -1380,15 +1512,15 @@ function ReactBridgeSearch({ onIntentDetected, currentContext, placeholder = 'Se
1380
1512
  border: `1px solid ${theme.colors.border}`,
1381
1513
  borderRadius: theme.borderRadius,
1382
1514
  boxShadow: theme.boxShadow,
1383
- maxHeight: '300px',
1384
- overflowY: 'auto',
1515
+ maxHeight: "300px",
1516
+ overflowY: "auto",
1385
1517
  zIndex: 1000,
1386
1518
  } }, displayMessages.map((message) => (React.createElement("div", { key: message.id, style: {
1387
1519
  padding: theme.spacing.md,
1388
1520
  borderBottom: `1px solid ${theme.colors.border}`,
1389
1521
  fontSize: theme.fontSizes.sm,
1390
1522
  color: theme.colors.text,
1391
- cursor: 'pointer',
1523
+ cursor: "pointer",
1392
1524
  }, onMouseEnter: (e) => {
1393
1525
  e.currentTarget.style.backgroundColor = theme.colors.surface;
1394
1526
  }, onMouseLeave: (e) => {
@@ -1397,47 +1529,47 @@ function ReactBridgeSearch({ onIntentDetected, currentContext, placeholder = 'Se
1397
1529
  }
1398
1530
 
1399
1531
  const darkTheme = {
1400
- name: 'dark',
1532
+ name: "dark",
1401
1533
  colors: {
1402
- primary: '#90caf9',
1403
- secondary: '#f48fb1',
1404
- background: '#121212',
1405
- surface: '#1e1e1e',
1406
- text: '#ffffff',
1407
- textSecondary: '#b0b0b0',
1408
- border: '#333333',
1409
- error: '#f44336',
1410
- success: '#4caf50',
1534
+ primary: "#90caf9",
1535
+ secondary: "#f48fb1",
1536
+ background: "#121212",
1537
+ surface: "#1e1e1e",
1538
+ text: "#ffffff",
1539
+ textSecondary: "#b0b0b0",
1540
+ border: "#333333",
1541
+ error: "#f44336",
1542
+ success: "#4caf50",
1411
1543
  },
1412
1544
  spacing: {
1413
- xs: '4px',
1414
- sm: '8px',
1415
- md: '16px',
1416
- lg: '24px',
1417
- xl: '32px',
1545
+ xs: "4px",
1546
+ sm: "8px",
1547
+ md: "16px",
1548
+ lg: "24px",
1549
+ xl: "32px",
1418
1550
  },
1419
1551
  fontSizes: {
1420
- xs: '12px',
1421
- sm: '14px',
1422
- md: '16px',
1423
- lg: '18px',
1424
- xl: '24px',
1552
+ xs: "12px",
1553
+ sm: "14px",
1554
+ md: "16px",
1555
+ lg: "18px",
1556
+ xl: "24px",
1425
1557
  },
1426
- borderRadius: '8px',
1427
- boxShadow: '0 2px 8px rgba(0, 0, 0, 0.5)',
1558
+ borderRadius: "8px",
1559
+ boxShadow: "0 2px 8px rgba(0, 0, 0, 0.5)",
1428
1560
  };
1429
1561
 
1430
1562
  function getTheme(mode, customTheme) {
1431
- if (mode === 'custom' && customTheme) {
1563
+ if (mode === "custom" && customTheme) {
1432
1564
  return customTheme;
1433
1565
  }
1434
- return mode === 'dark' ? darkTheme : lightTheme;
1566
+ return mode === "dark" ? darkTheme : lightTheme;
1435
1567
  }
1436
1568
  function createCustomTheme(baseTheme, overrides) {
1437
1569
  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
1570
  }
1439
1571
 
1440
- const DEFAULT_BASE_URL = 'https://react-bridge-api-14089992360.northamerica-northeast2.run.app';
1572
+ const DEFAULT_BASE_URL = "https://react-bridge-api-14089992360.northamerica-northeast2.run.app";
1441
1573
  class AnalyticsAPI {
1442
1574
  constructor(config) {
1443
1575
  this.config = config;
@@ -1450,8 +1582,8 @@ class AnalyticsAPI {
1450
1582
  const baseURL = this.config.baseURL || DEFAULT_BASE_URL;
1451
1583
  const url = `${baseURL}/api/analytics/configs`;
1452
1584
  const response = yield fetch(url, {
1453
- method: 'GET',
1454
- headers: Object.assign({ 'X-API-Key': this.config.apiKey }, this.config.headers),
1585
+ method: "GET",
1586
+ headers: Object.assign({ "X-API-Key": this.config.apiKey }, this.config.headers),
1455
1587
  });
1456
1588
  if (!response.ok) {
1457
1589
  throw new Error(`Failed to fetch analytics configs: ${response.statusText}`);
@@ -1467,8 +1599,8 @@ class AnalyticsAPI {
1467
1599
  const baseURL = this.config.baseURL || DEFAULT_BASE_URL;
1468
1600
  const url = `${baseURL}/api/analytics/${analyticsType}/latest`;
1469
1601
  const response = yield fetch(url, {
1470
- method: 'GET',
1471
- headers: Object.assign({ 'X-API-Key': this.config.apiKey, 'Content-Type': 'application/json' }, this.config.headers),
1602
+ method: "GET",
1603
+ headers: Object.assign({ "X-API-Key": this.config.apiKey, "Content-Type": "application/json" }, this.config.headers),
1472
1604
  });
1473
1605
  if (!response.ok) {
1474
1606
  if (response.status === 404) {
@@ -1487,8 +1619,8 @@ class AnalyticsAPI {
1487
1619
  const baseURL = this.config.baseURL || DEFAULT_BASE_URL;
1488
1620
  const url = `${baseURL}/api/analytics/directives/${directiveId}/status`;
1489
1621
  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),
1622
+ method: "PATCH",
1623
+ headers: Object.assign({ "X-API-Key": this.config.apiKey, "Content-Type": "application/json" }, this.config.headers),
1492
1624
  body: JSON.stringify({ status }),
1493
1625
  });
1494
1626
  if (!response.ok) {
@@ -1564,14 +1696,14 @@ function useAnalyticsResult(analyticsType) {
1564
1696
  };
1565
1697
  }
1566
1698
 
1567
- const MetricsPanel = ({ metrics, theme }) => {
1699
+ const MetricsPanel = ({ metrics, theme, }) => {
1568
1700
  const getStatusColor = (status) => {
1569
1701
  switch (status) {
1570
- case 'ok':
1702
+ case "ok":
1571
1703
  return theme.colors.success;
1572
- case 'warning':
1573
- return '#FFA500'; // Orange
1574
- case 'critical':
1704
+ case "warning":
1705
+ return "#FFA500"; // Orange
1706
+ case "critical":
1575
1707
  return theme.colors.error;
1576
1708
  default:
1577
1709
  return theme.colors.textSecondary;
@@ -1585,8 +1717,8 @@ const MetricsPanel = ({ metrics, theme }) => {
1585
1717
  color: theme.colors.text,
1586
1718
  } }, "Metrics"),
1587
1719
  React.createElement("div", { style: {
1588
- display: 'grid',
1589
- gridTemplateColumns: 'repeat(auto-fit, minmax(200px, 1fr))',
1720
+ display: "grid",
1721
+ gridTemplateColumns: "repeat(auto-fit, minmax(200px, 1fr))",
1590
1722
  gap: theme.spacing.md,
1591
1723
  } }, metrics.map((metric, index) => (React.createElement("div", { key: index, style: {
1592
1724
  padding: theme.spacing.md,
@@ -1595,28 +1727,28 @@ const MetricsPanel = ({ metrics, theme }) => {
1595
1727
  border: `2px solid ${getStatusColor(metric.status)}`,
1596
1728
  } },
1597
1729
  React.createElement("div", { style: {
1598
- display: 'flex',
1599
- justifyContent: 'space-between',
1600
- alignItems: 'center',
1730
+ display: "flex",
1731
+ justifyContent: "space-between",
1732
+ alignItems: "center",
1601
1733
  marginBottom: theme.spacing.xs,
1602
1734
  } },
1603
1735
  React.createElement("span", { style: {
1604
1736
  fontSize: theme.fontSizes.sm,
1605
1737
  color: theme.colors.textSecondary,
1606
- textTransform: 'uppercase',
1607
- letterSpacing: '0.5px',
1608
- } }, metric.name.replace(/_/g, ' ')),
1738
+ textTransform: "uppercase",
1739
+ letterSpacing: "0.5px",
1740
+ } }, metric.name.replace(/_/g, " ")),
1609
1741
  React.createElement("span", { style: {
1610
1742
  fontSize: theme.fontSizes.xs,
1611
- padding: '2px 8px',
1612
- borderRadius: '12px',
1743
+ padding: "2px 8px",
1744
+ borderRadius: "12px",
1613
1745
  backgroundColor: getStatusColor(metric.status),
1614
- color: '#fff',
1615
- textTransform: 'uppercase',
1746
+ color: "#fff",
1747
+ textTransform: "uppercase",
1616
1748
  } }, metric.status)),
1617
1749
  React.createElement("div", { style: {
1618
1750
  fontSize: theme.fontSizes.xl,
1619
- fontWeight: 'bold',
1751
+ fontWeight: "bold",
1620
1752
  color: theme.colors.text,
1621
1753
  marginBottom: theme.spacing.xs,
1622
1754
  } },
@@ -1632,11 +1764,11 @@ const MetricsPanel = ({ metrics, theme }) => {
1632
1764
  const ObservationsPanel = ({ observations, theme, }) => {
1633
1765
  const getSeverityColor = (severity) => {
1634
1766
  switch (severity) {
1635
- case 'low':
1767
+ case "low":
1636
1768
  return theme.colors.success;
1637
- case 'medium':
1638
- return '#FFA500'; // Orange
1639
- case 'high':
1769
+ case "medium":
1770
+ return "#FFA500"; // Orange
1771
+ case "high":
1640
1772
  return theme.colors.error;
1641
1773
  default:
1642
1774
  return theme.colors.textSecondary;
@@ -1649,7 +1781,11 @@ const ObservationsPanel = ({ observations, theme, }) => {
1649
1781
  fontSize: theme.fontSizes.lg,
1650
1782
  color: theme.colors.text,
1651
1783
  } }, "Observations"),
1652
- React.createElement("div", { style: { display: 'flex', flexDirection: 'column', gap: theme.spacing.md } }, observations.map((observation, index) => (React.createElement("div", { key: index, style: {
1784
+ React.createElement("div", { style: {
1785
+ display: "flex",
1786
+ flexDirection: "column",
1787
+ gap: theme.spacing.md,
1788
+ } }, observations.map((observation, index) => (React.createElement("div", { key: index, style: {
1653
1789
  padding: theme.spacing.md,
1654
1790
  backgroundColor: theme.colors.surface,
1655
1791
  borderRadius: theme.borderRadius,
@@ -1657,18 +1793,18 @@ const ObservationsPanel = ({ observations, theme, }) => {
1657
1793
  borderLeft: `4px solid ${getSeverityColor(observation.severity)}`,
1658
1794
  } },
1659
1795
  React.createElement("div", { style: {
1660
- display: 'flex',
1661
- justifyContent: 'space-between',
1662
- alignItems: 'center',
1796
+ display: "flex",
1797
+ justifyContent: "space-between",
1798
+ alignItems: "center",
1663
1799
  marginBottom: theme.spacing.xs,
1664
1800
  } },
1665
1801
  React.createElement("span", { style: {
1666
1802
  fontSize: theme.fontSizes.xs,
1667
- padding: '2px 8px',
1668
- borderRadius: '12px',
1803
+ padding: "2px 8px",
1804
+ borderRadius: "12px",
1669
1805
  backgroundColor: getSeverityColor(observation.severity),
1670
- color: '#fff',
1671
- textTransform: 'uppercase',
1806
+ color: "#fff",
1807
+ textTransform: "uppercase",
1672
1808
  } }, observation.severity),
1673
1809
  React.createElement("span", { style: {
1674
1810
  fontSize: theme.fontSizes.xs,
@@ -1677,7 +1813,7 @@ const ObservationsPanel = ({ observations, theme, }) => {
1677
1813
  React.createElement("div", { style: {
1678
1814
  fontSize: theme.fontSizes.md,
1679
1815
  color: theme.colors.text,
1680
- lineHeight: '1.5',
1816
+ lineHeight: "1.5",
1681
1817
  } }, observation.text)))))));
1682
1818
  };
1683
1819
 
@@ -1695,19 +1831,19 @@ function useDirectiveAction(onDirectiveAction) {
1695
1831
  const result = yield onDirectiveAction(directive, action);
1696
1832
  if (result.success) {
1697
1833
  // Update status to 'executed' if action succeeded
1698
- yield api.updateDirectiveStatus(directive.directiveId, 'executed');
1834
+ yield api.updateDirectiveStatus(directive.directiveId, "executed");
1699
1835
  }
1700
1836
  else {
1701
1837
  // Update status to 'failed' if action failed
1702
- yield api.updateDirectiveStatus(directive.directiveId, 'failed');
1703
- throw new Error(result.error || 'Directive execution failed');
1838
+ yield api.updateDirectiveStatus(directive.directiveId, "failed");
1839
+ throw new Error(result.error || "Directive execution failed");
1704
1840
  }
1705
1841
  return { success: true };
1706
1842
  }
1707
1843
  else {
1708
1844
  // No callback provided, just update status to 'declined'
1709
- if (action === 'decline') {
1710
- yield api.updateDirectiveStatus(directive.directiveId, 'declined');
1845
+ if (action === "decline") {
1846
+ yield api.updateDirectiveStatus(directive.directiveId, "declined");
1711
1847
  }
1712
1848
  return { success: true };
1713
1849
  }
@@ -1734,28 +1870,28 @@ const DirectivesPanel = ({ directives, theme, onDirectiveAction, onUpdate, }) =>
1734
1870
  if (priority >= 3)
1735
1871
  return theme.colors.error; // High/Critical
1736
1872
  if (priority === 2)
1737
- return '#FFA500'; // Medium
1873
+ return "#FFA500"; // Medium
1738
1874
  return theme.colors.success; // Low
1739
1875
  };
1740
1876
  const getPriorityLabel = (priority) => {
1741
1877
  if (priority >= 3)
1742
- return 'Critical';
1878
+ return "Critical";
1743
1879
  if (priority === 2)
1744
- return 'High';
1880
+ return "High";
1745
1881
  if (priority === 1)
1746
- return 'Medium';
1747
- return 'Low';
1882
+ return "Medium";
1883
+ return "Low";
1748
1884
  };
1749
1885
  const getStatusLabel = (status) => {
1750
1886
  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 ✗';
1887
+ case "proposed":
1888
+ return "Pending";
1889
+ case "executed":
1890
+ return "Executed ✓";
1891
+ case "declined":
1892
+ return "Declined";
1893
+ case "failed":
1894
+ return "Failed ✗";
1759
1895
  default:
1760
1896
  return status;
1761
1897
  }
@@ -1775,8 +1911,12 @@ const DirectivesPanel = ({ directives, theme, onDirectiveAction, onUpdate, }) =>
1775
1911
  fontSize: theme.fontSizes.lg,
1776
1912
  color: theme.colors.text,
1777
1913
  } }, "Directives"),
1778
- React.createElement("div", { style: { display: 'flex', flexDirection: 'column', gap: theme.spacing.md } }, directives.map((directive) => {
1779
- const isDisabled = directive.status !== 'proposed' ||
1914
+ React.createElement("div", { style: {
1915
+ display: "flex",
1916
+ flexDirection: "column",
1917
+ gap: theme.spacing.md,
1918
+ } }, directives.map((directive) => {
1919
+ const isDisabled = directive.status !== "proposed" ||
1780
1920
  isProcessing ||
1781
1921
  processingId === directive.directiveId;
1782
1922
  return (React.createElement("div", { key: directive.directiveId, style: {
@@ -1786,32 +1926,32 @@ const DirectivesPanel = ({ directives, theme, onDirectiveAction, onUpdate, }) =>
1786
1926
  border: `1px solid ${theme.colors.border}`,
1787
1927
  } },
1788
1928
  React.createElement("div", { style: {
1789
- display: 'flex',
1790
- justifyContent: 'space-between',
1791
- alignItems: 'center',
1929
+ display: "flex",
1930
+ justifyContent: "space-between",
1931
+ alignItems: "center",
1792
1932
  marginBottom: theme.spacing.sm,
1793
1933
  } },
1794
1934
  React.createElement("span", { style: {
1795
1935
  fontSize: theme.fontSizes.xs,
1796
- padding: '2px 8px',
1797
- borderRadius: '12px',
1936
+ padding: "2px 8px",
1937
+ borderRadius: "12px",
1798
1938
  backgroundColor: getPriorityColor(directive.priority),
1799
- color: '#fff',
1800
- textTransform: 'uppercase',
1939
+ color: "#fff",
1940
+ textTransform: "uppercase",
1801
1941
  } }, getPriorityLabel(directive.priority)),
1802
1942
  React.createElement("span", { style: {
1803
1943
  fontSize: theme.fontSizes.xs,
1804
- padding: '2px 8px',
1805
- borderRadius: '12px',
1944
+ padding: "2px 8px",
1945
+ borderRadius: "12px",
1806
1946
  backgroundColor: theme.colors.textSecondary,
1807
- color: '#fff',
1947
+ color: "#fff",
1808
1948
  } }, getStatusLabel(directive.status))),
1809
1949
  React.createElement("div", { style: {
1810
1950
  fontSize: theme.fontSizes.lg,
1811
- fontWeight: 'bold',
1951
+ fontWeight: "bold",
1812
1952
  color: theme.colors.text,
1813
1953
  marginBottom: theme.spacing.xs,
1814
- } }, directive.action.replace(/_/g, ' ').toUpperCase()),
1954
+ } }, directive.action.replace(/_/g, " ").toUpperCase()),
1815
1955
  directive.targets.length > 0 && (React.createElement("div", { style: {
1816
1956
  fontSize: theme.fontSizes.sm,
1817
1957
  color: theme.colors.textSecondary,
@@ -1819,7 +1959,7 @@ const DirectivesPanel = ({ directives, theme, onDirectiveAction, onUpdate, }) =>
1819
1959
  } },
1820
1960
  React.createElement("strong", null, "Targets:"),
1821
1961
  " ",
1822
- directive.targets.join(', '))),
1962
+ directive.targets.join(", "))),
1823
1963
  directive.parameters.length > 0 && (React.createElement("div", { style: {
1824
1964
  marginBottom: theme.spacing.sm,
1825
1965
  padding: theme.spacing.sm,
@@ -1828,7 +1968,7 @@ const DirectivesPanel = ({ directives, theme, onDirectiveAction, onUpdate, }) =>
1828
1968
  } }, directive.parameters.map((param, index) => (React.createElement("div", { key: index, style: {
1829
1969
  fontSize: theme.fontSizes.sm,
1830
1970
  color: theme.colors.text,
1831
- marginBottom: '4px',
1971
+ marginBottom: "4px",
1832
1972
  } },
1833
1973
  React.createElement("strong", null,
1834
1974
  param.name,
@@ -1842,35 +1982,37 @@ const DirectivesPanel = ({ directives, theme, onDirectiveAction, onUpdate, }) =>
1842
1982
  fontSize: theme.fontSizes.sm,
1843
1983
  color: theme.colors.textSecondary,
1844
1984
  marginBottom: theme.spacing.md,
1845
- lineHeight: '1.5',
1985
+ lineHeight: "1.5",
1846
1986
  } }, 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: {
1987
+ directive.status === "proposed" && (React.createElement("div", { style: { display: "flex", gap: theme.spacing.sm } },
1988
+ React.createElement("button", { onClick: () => handleDirectiveAction(directive, "execute"), disabled: isDisabled, style: {
1849
1989
  flex: 1,
1850
1990
  padding: theme.spacing.sm,
1851
1991
  backgroundColor: isDisabled
1852
1992
  ? theme.colors.textSecondary
1853
1993
  : theme.colors.success,
1854
- color: '#fff',
1855
- border: 'none',
1994
+ color: "#fff",
1995
+ border: "none",
1856
1996
  borderRadius: theme.borderRadius,
1857
- cursor: isDisabled ? 'not-allowed' : 'pointer',
1997
+ cursor: isDisabled ? "not-allowed" : "pointer",
1858
1998
  fontSize: theme.fontSizes.sm,
1859
- fontWeight: 'bold',
1999
+ fontWeight: "bold",
1860
2000
  opacity: isDisabled ? 0.6 : 1,
1861
- } }, processingId === directive.directiveId ? 'Processing...' : 'Execute'),
1862
- React.createElement("button", { onClick: () => handleDirectiveAction(directive, 'decline'), disabled: isDisabled, style: {
2001
+ } }, processingId === directive.directiveId
2002
+ ? "Processing..."
2003
+ : "Execute"),
2004
+ React.createElement("button", { onClick: () => handleDirectiveAction(directive, "decline"), disabled: isDisabled, style: {
1863
2005
  flex: 1,
1864
2006
  padding: theme.spacing.sm,
1865
2007
  backgroundColor: isDisabled
1866
2008
  ? theme.colors.textSecondary
1867
2009
  : theme.colors.error,
1868
- color: '#fff',
1869
- border: 'none',
2010
+ color: "#fff",
2011
+ border: "none",
1870
2012
  borderRadius: theme.borderRadius,
1871
- cursor: isDisabled ? 'not-allowed' : 'pointer',
2013
+ cursor: isDisabled ? "not-allowed" : "pointer",
1872
2014
  fontSize: theme.fontSizes.sm,
1873
- fontWeight: 'bold',
2015
+ fontWeight: "bold",
1874
2016
  opacity: isDisabled ? 0.6 : 1,
1875
2017
  } }, "Decline")))));
1876
2018
  }))));
@@ -1896,53 +2038,57 @@ const AnalyticsReport = ({ analyticsType, theme: customTheme, onDirectiveAction,
1896
2038
  // Use a default theme if none provided
1897
2039
  const theme = customTheme || {
1898
2040
  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',
2041
+ background: "#ffffff",
2042
+ surface: "#f5f5f5",
2043
+ text: "#333333",
2044
+ textSecondary: "#666666",
2045
+ border: "#e0e0e0",
2046
+ primary: "#007bff",
2047
+ success: "#28a745",
2048
+ error: "#dc3545",
2049
+ secondary: "#6c757d",
1908
2050
  },
1909
2051
  spacing: {
1910
- xs: '4px',
1911
- sm: '8px',
1912
- md: '16px',
1913
- lg: '24px',
1914
- xl: '32px',
2052
+ xs: "4px",
2053
+ sm: "8px",
2054
+ md: "16px",
2055
+ lg: "24px",
2056
+ xl: "32px",
1915
2057
  },
1916
2058
  fontSizes: {
1917
- xs: '12px',
1918
- sm: '14px',
1919
- md: '16px',
1920
- lg: '20px',
1921
- xl: '24px',
2059
+ xs: "12px",
2060
+ sm: "14px",
2061
+ md: "16px",
2062
+ lg: "20px",
2063
+ xl: "24px",
1922
2064
  },
1923
- borderRadius: '8px',
1924
- boxShadow: '0 2px 8px rgba(0,0,0,0.1)',
1925
- name: 'default',
2065
+ borderRadius: "8px",
2066
+ boxShadow: "0 2px 8px rgba(0,0,0,0.1)",
2067
+ name: "default",
1926
2068
  };
1927
2069
  return (React.createElement("div", { style: {
1928
- height: '100%',
1929
- display: 'flex',
1930
- flexDirection: 'column',
2070
+ height: "100%",
2071
+ display: "flex",
2072
+ flexDirection: "column",
1931
2073
  backgroundColor: theme.colors.background,
1932
2074
  } },
1933
2075
  React.createElement("div", { style: {
1934
2076
  padding: theme.spacing.lg,
1935
2077
  borderBottom: `1px solid ${theme.colors.border}`,
1936
- display: 'flex',
1937
- justifyContent: 'space-between',
1938
- alignItems: 'center',
2078
+ display: "flex",
2079
+ justifyContent: "space-between",
2080
+ alignItems: "center",
1939
2081
  } },
1940
- React.createElement("div", { style: { display: 'flex', alignItems: 'center', gap: theme.spacing.sm } },
2082
+ React.createElement("div", { style: {
2083
+ display: "flex",
2084
+ alignItems: "center",
2085
+ gap: theme.spacing.sm,
2086
+ } },
1941
2087
  onBack && (React.createElement("button", { onClick: onBack, style: {
1942
- background: 'none',
1943
- border: 'none',
1944
- cursor: 'pointer',
1945
- fontSize: '24px',
2088
+ background: "none",
2089
+ border: "none",
2090
+ cursor: "pointer",
2091
+ fontSize: "24px",
1946
2092
  color: theme.colors.text,
1947
2093
  padding: 0,
1948
2094
  } }, BACK_ICON_SVG)),
@@ -1955,33 +2101,33 @@ const AnalyticsReport = ({ analyticsType, theme: customTheme, onDirectiveAction,
1955
2101
  result && (React.createElement("div", { style: {
1956
2102
  fontSize: theme.fontSizes.xs,
1957
2103
  color: theme.colors.textSecondary,
1958
- marginTop: '4px',
2104
+ marginTop: "4px",
1959
2105
  } },
1960
2106
  "Last updated: ",
1961
2107
  new Date(result.createdAt).toLocaleString())))),
1962
- React.createElement("div", { style: { display: 'flex', gap: theme.spacing.sm } },
2108
+ React.createElement("div", { style: { display: "flex", gap: theme.spacing.sm } },
1963
2109
  React.createElement("button", { onClick: handleRefresh, disabled: isLoading, style: {
1964
- background: 'none',
1965
- border: 'none',
1966
- cursor: isLoading ? 'not-allowed' : 'pointer',
1967
- fontSize: '24px',
2110
+ background: "none",
2111
+ border: "none",
2112
+ cursor: isLoading ? "not-allowed" : "pointer",
2113
+ fontSize: "24px",
1968
2114
  color: theme.colors.text,
1969
2115
  padding: 0,
1970
2116
  opacity: isLoading ? 0.5 : 1,
1971
2117
  } }, REFRESH_ICON_SVG),
1972
2118
  onClose && (React.createElement("button", { onClick: onClose, style: {
1973
- background: 'none',
1974
- border: 'none',
1975
- cursor: 'pointer',
1976
- fontSize: '24px',
2119
+ background: "none",
2120
+ border: "none",
2121
+ cursor: "pointer",
2122
+ fontSize: "24px",
1977
2123
  color: theme.colors.text,
1978
2124
  padding: 0,
1979
2125
  } }, CLOSE_ICON_SVG$1)))),
1980
2126
  React.createElement("div", { style: {
1981
2127
  flex: 1,
1982
- overflowY: 'auto',
2128
+ overflowY: "auto",
1983
2129
  padding: theme.spacing.lg,
1984
- } }, isLoading ? (React.createElement("div", { style: { textAlign: 'center', color: theme.colors.textSecondary } }, "Loading analytics result...")) : error ? (React.createElement("div", { style: {
2130
+ } }, isLoading ? (React.createElement("div", { style: { textAlign: "center", color: theme.colors.textSecondary } }, "Loading analytics result...")) : error ? (React.createElement("div", { style: {
1985
2131
  padding: theme.spacing.md,
1986
2132
  backgroundColor: theme.colors.surface,
1987
2133
  borderRadius: theme.borderRadius,
@@ -1989,10 +2135,14 @@ const AnalyticsReport = ({ analyticsType, theme: customTheme, onDirectiveAction,
1989
2135
  color: theme.colors.error,
1990
2136
  } },
1991
2137
  "Error: ",
1992
- error.message)) : result ? (React.createElement("div", { style: { display: 'flex', flexDirection: 'column', gap: theme.spacing.xl } },
2138
+ error.message)) : result ? (React.createElement("div", { style: {
2139
+ display: "flex",
2140
+ flexDirection: "column",
2141
+ gap: theme.spacing.xl,
2142
+ } },
1993
2143
  result.metrics.length > 0 && (React.createElement(MetricsPanel, { metrics: result.metrics, theme: theme })),
1994
2144
  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")))));
2145
+ 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
2146
  };
1997
2147
 
1998
2148
  // Close Icon SVG
@@ -2001,32 +2151,32 @@ const CLOSE_ICON_SVG = (React.createElement("svg", { xmlns: "http://www.w3.org/2
2001
2151
  const AnalyticsDrawer = ({ isOpen, onClose, configs, isLoading, theme, onDirectiveAction, }) => {
2002
2152
  const [selectedAnalytics, setSelectedAnalytics] = useState(null);
2003
2153
  // Check if mobile
2004
- const isMobile = typeof window !== 'undefined' && window.innerWidth < 768;
2154
+ const isMobile = typeof window !== "undefined" && window.innerWidth < 768;
2005
2155
  const drawerStyles = {
2006
- position: 'fixed',
2156
+ position: "fixed",
2007
2157
  top: 0,
2008
2158
  right: 0,
2009
- width: isMobile ? '100%' : '400px',
2010
- height: '100%',
2159
+ width: isMobile ? "100%" : "400px",
2160
+ height: "100%",
2011
2161
  backgroundColor: theme.colors.background,
2012
2162
  boxShadow: theme.boxShadow,
2013
2163
  zIndex: 1001,
2014
- display: 'flex',
2015
- flexDirection: 'column',
2016
- transform: isOpen ? 'translateX(0)' : 'translateX(100%)',
2017
- transition: 'transform 0.3s ease',
2164
+ display: "flex",
2165
+ flexDirection: "column",
2166
+ transform: isOpen ? "translateX(0)" : "translateX(100%)",
2167
+ transition: "transform 0.3s ease",
2018
2168
  };
2019
2169
  const overlayStyles = {
2020
- position: 'fixed',
2170
+ position: "fixed",
2021
2171
  top: 0,
2022
2172
  left: 0,
2023
- width: '100%',
2024
- height: '100%',
2025
- backgroundColor: 'rgba(0, 0, 0, 0.5)',
2173
+ width: "100%",
2174
+ height: "100%",
2175
+ backgroundColor: "rgba(0, 0, 0, 0.5)",
2026
2176
  zIndex: 1000,
2027
2177
  opacity: isOpen ? 1 : 0,
2028
- pointerEvents: isOpen ? 'auto' : 'none',
2029
- transition: 'opacity 0.3s ease',
2178
+ pointerEvents: isOpen ? "auto" : "none",
2179
+ transition: "opacity 0.3s ease",
2030
2180
  };
2031
2181
  if (selectedAnalytics) {
2032
2182
  return (React.createElement(React.Fragment, null,
@@ -2040,9 +2190,9 @@ const AnalyticsDrawer = ({ isOpen, onClose, configs, isLoading, theme, onDirecti
2040
2190
  React.createElement("div", { style: {
2041
2191
  padding: theme.spacing.lg,
2042
2192
  borderBottom: `1px solid ${theme.colors.border}`,
2043
- display: 'flex',
2044
- justifyContent: 'space-between',
2045
- alignItems: 'center',
2193
+ display: "flex",
2194
+ justifyContent: "space-between",
2195
+ alignItems: "center",
2046
2196
  } },
2047
2197
  React.createElement("h2", { style: {
2048
2198
  margin: 0,
@@ -2050,36 +2200,41 @@ const AnalyticsDrawer = ({ isOpen, onClose, configs, isLoading, theme, onDirecti
2050
2200
  color: theme.colors.text,
2051
2201
  } }, "Analytics"),
2052
2202
  React.createElement("button", { onClick: onClose, style: {
2053
- background: 'none',
2054
- border: 'none',
2055
- cursor: 'pointer',
2056
- fontSize: '24px',
2203
+ background: "none",
2204
+ border: "none",
2205
+ cursor: "pointer",
2206
+ fontSize: "24px",
2057
2207
  color: theme.colors.text,
2058
2208
  padding: 0,
2059
2209
  } }, CLOSE_ICON_SVG)),
2060
2210
  React.createElement("div", { style: {
2061
2211
  flex: 1,
2062
- overflowY: 'auto',
2212
+ overflowY: "auto",
2063
2213
  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: {
2214
+ } }, 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: {
2215
+ display: "flex",
2216
+ flexDirection: "column",
2217
+ gap: theme.spacing.md,
2218
+ } }, configs.map((config) => (React.createElement("div", { key: config.configId, onClick: () => config.isEnabled &&
2219
+ setSelectedAnalytics(config.analyticsType), style: {
2065
2220
  padding: theme.spacing.md,
2066
2221
  backgroundColor: theme.colors.surface,
2067
2222
  borderRadius: theme.borderRadius,
2068
2223
  border: `1px solid ${theme.colors.border}`,
2069
- cursor: config.isEnabled ? 'pointer' : 'not-allowed',
2224
+ cursor: config.isEnabled ? "pointer" : "not-allowed",
2070
2225
  opacity: config.isEnabled ? 1 : 0.6,
2071
- transition: 'transform 0.2s ease',
2226
+ transition: "transform 0.2s ease",
2072
2227
  }, onMouseEnter: (e) => {
2073
2228
  if (config.isEnabled) {
2074
- e.currentTarget.style.transform = 'translateX(5px)';
2229
+ e.currentTarget.style.transform = "translateX(5px)";
2075
2230
  }
2076
2231
  }, onMouseLeave: (e) => {
2077
- e.currentTarget.style.transform = 'translateX(0)';
2232
+ e.currentTarget.style.transform = "translateX(0)";
2078
2233
  } },
2079
2234
  React.createElement("div", { style: {
2080
- display: 'flex',
2081
- justifyContent: 'space-between',
2082
- alignItems: 'center',
2235
+ display: "flex",
2236
+ justifyContent: "space-between",
2237
+ alignItems: "center",
2083
2238
  marginBottom: theme.spacing.xs,
2084
2239
  } },
2085
2240
  React.createElement("h3", { style: {
@@ -2089,13 +2244,13 @@ const AnalyticsDrawer = ({ isOpen, onClose, configs, isLoading, theme, onDirecti
2089
2244
  } }, config.analyticsType),
2090
2245
  React.createElement("span", { style: {
2091
2246
  fontSize: theme.fontSizes.xs,
2092
- padding: '2px 8px',
2093
- borderRadius: '12px',
2247
+ padding: "2px 8px",
2248
+ borderRadius: "12px",
2094
2249
  backgroundColor: config.isEnabled
2095
2250
  ? theme.colors.success
2096
2251
  : theme.colors.textSecondary,
2097
- color: '#fff',
2098
- } }, config.isEnabled ? 'Enabled' : 'Disabled')),
2252
+ color: "#fff",
2253
+ } }, config.isEnabled ? "Enabled" : "Disabled")),
2099
2254
  React.createElement("p", { style: {
2100
2255
  margin: 0,
2101
2256
  fontSize: theme.fontSizes.sm,
@@ -2110,43 +2265,44 @@ const AnalyticsDrawer = ({ isOpen, onClose, configs, isLoading, theme, onDirecti
2110
2265
  "Frequency: ",
2111
2266
  config.frequency),
2112
2267
  config.lastExecutedAt && (React.createElement("div", null,
2113
- "Last run: ",
2268
+ "Last run:",
2269
+ " ",
2114
2270
  new Date(config.lastExecutedAt).toLocaleString()))))))))))));
2115
2271
  };
2116
2272
 
2117
2273
  // Analytics Icon SVG
2118
2274
  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
2275
  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, }) => {
2276
+ const AnalyticsWidget = ({ position = "bottom-right", theme: customTheme, onDirectiveAction, }) => {
2121
2277
  const { theme: contextTheme } = useReactBridgeContext();
2122
2278
  const theme = customTheme || contextTheme;
2123
2279
  const { configs, isLoading } = useAnalyticsConfigs();
2124
2280
  const [isOpen, setIsOpen] = useState(false);
2125
2281
  const enabledCount = configs.filter((c) => c.isEnabled).length;
2126
- const positionStyles = position === 'bottom-right'
2282
+ const positionStyles = position === "bottom-right"
2127
2283
  ? { right: theme.spacing.lg, bottom: theme.spacing.lg }
2128
2284
  : { left: theme.spacing.lg, bottom: theme.spacing.lg };
2129
2285
  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)';
2286
+ 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) => {
2287
+ e.currentTarget.style.transform = "scale(1.1)";
2132
2288
  }, onMouseLeave: (e) => {
2133
- e.currentTarget.style.transform = 'scale(1)';
2289
+ e.currentTarget.style.transform = "scale(1)";
2134
2290
  } },
2135
2291
  ANALYTICS_ICON_SVG,
2136
2292
  !isLoading && enabledCount > 0 && (React.createElement("span", { style: {
2137
- position: 'absolute',
2138
- top: '-5px',
2139
- right: '-5px',
2293
+ position: "absolute",
2294
+ top: "-5px",
2295
+ right: "-5px",
2140
2296
  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',
2297
+ color: "#fff",
2298
+ borderRadius: "50%",
2299
+ width: "24px",
2300
+ height: "24px",
2301
+ display: "flex",
2302
+ alignItems: "center",
2303
+ justifyContent: "center",
2304
+ fontSize: "12px",
2305
+ fontWeight: "bold",
2150
2306
  } }, enabledCount))),
2151
2307
  isOpen && (React.createElement(AnalyticsDrawer, { isOpen: isOpen, onClose: () => setIsOpen(false), configs: configs, isLoading: isLoading, theme: theme, onDirectiveAction: onDirectiveAction }))));
2152
2308
  };
@@ -2516,7 +2672,7 @@ function AnalyticsDashboard({ onDirectiveAction, className = "", showRefresh = t
2516
2672
  "Declined (",
2517
2673
  declinedCount,
2518
2674
  ")")),
2519
- directiveTypes.length > 1 && (React.createElement("select", { value: directiveType, onChange: e => setDirectiveType(e.target.value), style: {
2675
+ directiveTypes.length > 1 && (React.createElement("select", { value: directiveType, onChange: (e) => setDirectiveType(e.target.value), style: {
2520
2676
  padding: `${theme.spacing.xs} ${theme.spacing.sm}`,
2521
2677
  borderRadius: theme.borderRadius,
2522
2678
  border: `1px solid ${theme.colors.border}`,
@@ -2530,7 +2686,7 @@ function AnalyticsDashboard({ onDirectiveAction, className = "", showRefresh = t
2530
2686
  cursor: "pointer",
2531
2687
  } },
2532
2688
  React.createElement("option", { value: "all" }, "All types"),
2533
- directiveTypes.map(type => (React.createElement("option", { key: type, value: type }, type)))))),
2689
+ directiveTypes.map((type) => (React.createElement("option", { key: type, value: type }, type)))))),
2534
2690
  filteredDirectives.length === 0 && (React.createElement("div", { style: placeholderStyle }, "No directives match the selected filter.")),
2535
2691
  React.createElement("div", { style: {
2536
2692
  display: "flex",
@@ -2575,17 +2731,1810 @@ function AnalyticsDashboard({ onDirectiveAction, className = "", showRefresh = t
2575
2731
  ": ",
2576
2732
  param.value)))))),
2577
2733
  directive.status === "proposed" && (React.createElement("div", { style: { display: "flex", gap: theme.spacing.sm } },
2578
- React.createElement("button", { type: "button", onClick: () => handleDirectiveAction(directive, "execute"), disabled: isProcessing && processingId === directive.directiveId, style: Object.assign(Object.assign({}, pillStyle(theme.colors.success)), { border: "none", cursor: isProcessing && processingId === directive.directiveId
2734
+ React.createElement("button", { type: "button", onClick: () => handleDirectiveAction(directive, "execute"), disabled: isProcessing &&
2735
+ processingId === directive.directiveId, style: Object.assign(Object.assign({}, pillStyle(theme.colors.success)), { border: "none", cursor: isProcessing &&
2736
+ processingId === directive.directiveId
2579
2737
  ? "not-allowed"
2580
- : "pointer" }) }, isProcessing && processingId === directive.directiveId
2738
+ : "pointer" }) }, isProcessing &&
2739
+ processingId === directive.directiveId
2581
2740
  ? "Processing..."
2582
2741
  : "Execute"),
2583
- React.createElement("button", { type: "button", onClick: () => handleDirectiveAction(directive, "decline"), disabled: isProcessing && processingId === directive.directiveId, style: Object.assign(Object.assign({}, pillStyle(theme.colors.error)), { border: "none", cursor: isProcessing && processingId === directive.directiveId
2742
+ React.createElement("button", { type: "button", onClick: () => handleDirectiveAction(directive, "decline"), disabled: isProcessing &&
2743
+ processingId === directive.directiveId, style: Object.assign(Object.assign({}, pillStyle(theme.colors.error)), { border: "none", cursor: isProcessing &&
2744
+ processingId === directive.directiveId
2584
2745
  ? "not-allowed"
2585
- : "pointer" }) }, isProcessing && processingId === directive.directiveId
2746
+ : "pointer" }) }, isProcessing &&
2747
+ processingId === directive.directiveId
2586
2748
  ? "Processing..."
2587
2749
  : "Decline"))))))))))))));
2588
2750
  }
2589
2751
 
2590
- export { AnalyticsAPI, AnalyticsDashboard, AnalyticsReport, AnalyticsWidget, DirectivesPanel, MetricsPanel, ObservationsPanel, ReactBridgeAPI, ReactBridgeChatbox, ReactBridgeProvider, ReactBridgeSearch, WebSpeechSTTProvider, WebSpeechTTSProvider, createCustomTheme, darkTheme, getTheme, lightTheme, useAnalyticsConfigs, useAnalyticsResult, useDirectiveAction, useReactBridge, useReactBridgeContext };
2752
+ /**
2753
+ * Request Cache Manager
2754
+ * Implements a simple caching mechanism similar to react-query
2755
+ * Prevents duplicate concurrent requests and caches results
2756
+ */
2757
+ const DEFAULT_TTL = 5 * 60 * 1000; // 5 minutes
2758
+ class RequestCache {
2759
+ constructor() {
2760
+ this.cache = new Map();
2761
+ this.pendingRequests = new Map();
2762
+ }
2763
+ /**
2764
+ * Generate a cache key from function and parameters
2765
+ */
2766
+ getCacheKey(fetchFn, params) {
2767
+ const fnString = fetchFn.toString();
2768
+ const paramString = params ? JSON.stringify(params) : '';
2769
+ return `${fnString}::${paramString}`;
2770
+ }
2771
+ /**
2772
+ * Check if cache entry is still valid
2773
+ */
2774
+ isCacheValid(entry) {
2775
+ return Date.now() - entry.timestamp < entry.ttl;
2776
+ }
2777
+ /**
2778
+ * Fetch or return cached data
2779
+ */
2780
+ get(fetchFn_1, params_1) {
2781
+ return __awaiter(this, arguments, void 0, function* (fetchFn, params, ttl = DEFAULT_TTL) {
2782
+ const key = this.getCacheKey(fetchFn, params);
2783
+ // Return valid cached data
2784
+ const cached = this.cache.get(key);
2785
+ if (cached && this.isCacheValid(cached)) {
2786
+ return cached.data;
2787
+ }
2788
+ // Return pending request if already in flight
2789
+ const pending = this.pendingRequests.get(key);
2790
+ if (pending) {
2791
+ return pending.promise;
2792
+ }
2793
+ // Create new request
2794
+ const promise = fetchFn().then((data) => {
2795
+ this.cache.set(key, {
2796
+ data,
2797
+ timestamp: Date.now(),
2798
+ ttl,
2799
+ });
2800
+ this.pendingRequests.delete(key);
2801
+ return data;
2802
+ }).catch((error) => {
2803
+ this.pendingRequests.delete(key);
2804
+ throw error;
2805
+ });
2806
+ this.pendingRequests.set(key, { promise });
2807
+ return promise;
2808
+ });
2809
+ }
2810
+ /**
2811
+ * Invalidate cache entry
2812
+ */
2813
+ invalidate(fetchFn, params) {
2814
+ const key = this.getCacheKey(fetchFn, params);
2815
+ this.cache.delete(key);
2816
+ }
2817
+ /**
2818
+ * Clear all cache
2819
+ */
2820
+ clear() {
2821
+ this.cache.clear();
2822
+ this.pendingRequests.clear();
2823
+ }
2824
+ }
2825
+ // Singleton instance
2826
+ const requestCache = new RequestCache();
2827
+
2828
+ /**
2829
+ * useReportData Hook
2830
+ * Fetches and manages report data with error handling
2831
+ * Implements caching to prevent duplicate requests
2832
+ */
2833
+ /**
2834
+ * Generic hook for fetching report data
2835
+ * Implements caching and deduplication to prevent infinite requests
2836
+ * @param fetchFn - Async function to fetch report data
2837
+ * @param dependencies - Dependencies that trigger refetch when changed
2838
+ * @param options - Hook options (enabled flag, cache TTL)
2839
+ */
2840
+ function useReportData(fetchFn, dependencies = [], options = {}) {
2841
+ const [data, setData] = useState(null);
2842
+ const [loading, setLoading] = useState(true);
2843
+ const [error, setError] = useState(null);
2844
+ const isMountedRef = useRef(true);
2845
+ const { enabled = true, ttl = 5 * 60 * 1000 } = options;
2846
+ // Create a stable string representation of dependencies for comparison
2847
+ const depsString = JSON.stringify(dependencies);
2848
+ useEffect(() => {
2849
+ isMountedRef.current = true;
2850
+ if (!enabled) {
2851
+ setLoading(false);
2852
+ return;
2853
+ }
2854
+ let cancelled = false;
2855
+ const fetchData = () => __awaiter(this, void 0, void 0, function* () {
2856
+ try {
2857
+ setLoading(true);
2858
+ setError(null);
2859
+ // Use cache to avoid duplicate requests
2860
+ const result = yield requestCache.get(fetchFn, depsString, ttl);
2861
+ if (!cancelled && isMountedRef.current) {
2862
+ setData(result);
2863
+ }
2864
+ }
2865
+ catch (err) {
2866
+ if (!cancelled && isMountedRef.current) {
2867
+ const error = err instanceof Error ? err : new Error("Unknown error occurred");
2868
+ setError(error);
2869
+ setData(null);
2870
+ }
2871
+ }
2872
+ finally {
2873
+ if (!cancelled && isMountedRef.current) {
2874
+ setLoading(false);
2875
+ }
2876
+ }
2877
+ });
2878
+ fetchData();
2879
+ return () => {
2880
+ cancelled = true;
2881
+ };
2882
+ }, [depsString, enabled, ttl, fetchFn]);
2883
+ useEffect(() => {
2884
+ return () => {
2885
+ isMountedRef.current = false;
2886
+ };
2887
+ }, []);
2888
+ const refetch = () => __awaiter(this, void 0, void 0, function* () {
2889
+ // Invalidate cache and refetch
2890
+ requestCache.invalidate(fetchFn, depsString);
2891
+ try {
2892
+ setLoading(true);
2893
+ setError(null);
2894
+ const result = yield requestCache.get(fetchFn, depsString, ttl);
2895
+ if (isMountedRef.current) {
2896
+ setData(result);
2897
+ }
2898
+ }
2899
+ catch (err) {
2900
+ if (isMountedRef.current) {
2901
+ const error = err instanceof Error ? err : new Error("Unknown error occurred");
2902
+ setError(error);
2903
+ setData(null);
2904
+ }
2905
+ }
2906
+ finally {
2907
+ if (isMountedRef.current) {
2908
+ setLoading(false);
2909
+ }
2910
+ }
2911
+ });
2912
+ return { data, loading, error, refetch };
2913
+ }
2914
+
2915
+ /**
2916
+ * Date Range Service
2917
+ * Handles date range calculations and options
2918
+ */
2919
+ class DateRangeService {
2920
+ /**
2921
+ * Calculate date range based on predefined options
2922
+ */
2923
+ static getDateRange(option) {
2924
+ const today = new Date();
2925
+ const endDate = today.toISOString().split("T")[0]; // YYYY-MM-DD format
2926
+ let startDate;
2927
+ switch (option) {
2928
+ case "past-week":
2929
+ startDate = new Date(today);
2930
+ startDate.setDate(today.getDate() - 7);
2931
+ break;
2932
+ case "past-month":
2933
+ startDate = new Date(today);
2934
+ startDate.setMonth(today.getMonth() - 1);
2935
+ break;
2936
+ case "past-3-months":
2937
+ startDate = new Date(today);
2938
+ startDate.setMonth(today.getMonth() - 3);
2939
+ break;
2940
+ case "past-6-months":
2941
+ startDate = new Date(today);
2942
+ startDate.setMonth(today.getMonth() - 6);
2943
+ break;
2944
+ case "past-year":
2945
+ startDate = new Date(today);
2946
+ startDate.setFullYear(today.getFullYear() - 1);
2947
+ break;
2948
+ default:
2949
+ startDate = new Date(today);
2950
+ startDate.setMonth(today.getMonth() - 1);
2951
+ }
2952
+ return {
2953
+ label: this.getLabel(option),
2954
+ startDate: startDate.toISOString().split("T")[0],
2955
+ endDate,
2956
+ };
2957
+ }
2958
+ /**
2959
+ * Get human-readable label for date range option
2960
+ */
2961
+ static getLabel(option) {
2962
+ const labels = {
2963
+ "past-week": "Past Week",
2964
+ "past-month": "Past Month",
2965
+ "past-3-months": "Past 3 Months",
2966
+ "past-6-months": "Past 6 Months",
2967
+ "past-year": "Past Year",
2968
+ };
2969
+ return labels[option];
2970
+ }
2971
+ /**
2972
+ * Get all available date range options
2973
+ */
2974
+ static getAllOptions() {
2975
+ return [
2976
+ { value: "past-week", label: "Past Week" },
2977
+ { value: "past-month", label: "Past Month" },
2978
+ { value: "past-3-months", label: "Past 3 Months" },
2979
+ { value: "past-6-months", label: "Past 6 Months" },
2980
+ { value: "past-year", label: "Past Year" },
2981
+ ];
2982
+ }
2983
+ /**
2984
+ * Format date for display (e.g., "Jan 6 - Feb 5")
2985
+ */
2986
+ static formatDateRangeForDisplay(startDate, endDate) {
2987
+ try {
2988
+ const start = new Date(startDate);
2989
+ const end = new Date(endDate);
2990
+ const formatPart = (date) => {
2991
+ const month = date.toLocaleString("default", { month: "short" });
2992
+ const day = date.getDate();
2993
+ return `${month} ${day}`;
2994
+ };
2995
+ return `${formatPart(start)} - ${formatPart(end)}`;
2996
+ }
2997
+ catch (_a) {
2998
+ return `${startDate} - ${endDate}`;
2999
+ }
3000
+ }
3001
+ }
3002
+
3003
+ /**
3004
+ * useDateRange Hook
3005
+ * Manages date range state with predefined options
3006
+ */
3007
+ /**
3008
+ * Hook to manage date range selection for reports
3009
+ * @param defaultOption - Default date range option (default: 'past-month')
3010
+ */
3011
+ function useDateRange(defaultOption = "past-month") {
3012
+ const [selectedOption, setSelectedOption] = useState(defaultOption);
3013
+ const dateRange = DateRangeService.getDateRange(selectedOption);
3014
+ return {
3015
+ selectedOption,
3016
+ setSelectedOption,
3017
+ startDate: dateRange.startDate,
3018
+ endDate: dateRange.endDate,
3019
+ label: dateRange.label,
3020
+ };
3021
+ }
3022
+
3023
+ /**
3024
+ * DateRangeSelector Component
3025
+ * Select dropdown for date range selection
3026
+ */
3027
+ const DateRangeSelector = ({ selectedOption, onSelect, theme, }) => {
3028
+ const options = DateRangeService.getAllOptions();
3029
+ return (React.createElement("select", { value: selectedOption, onChange: (e) => onSelect(e.target.value), style: {
3030
+ padding: `${(theme === null || theme === void 0 ? void 0 : theme.spacing.xs) || "6px"} ${(theme === null || theme === void 0 ? void 0 : theme.spacing.sm) || "10px"}`,
3031
+ fontSize: (theme === null || theme === void 0 ? void 0 : theme.fontSizes.sm) || "13px",
3032
+ fontWeight: "500",
3033
+ borderRadius: (theme === null || theme === void 0 ? void 0 : theme.borderRadius) || "6px",
3034
+ border: `1px solid ${(theme === null || theme === void 0 ? void 0 : theme.colors.border) || "#d0d0d0"}`,
3035
+ backgroundColor: (theme === null || theme === void 0 ? void 0 : theme.colors.surface) || "#f9f9f9",
3036
+ color: (theme === null || theme === void 0 ? void 0 : theme.colors.text) || "#000",
3037
+ cursor: "pointer",
3038
+ transition: "border-color 0.2s ease, box-shadow 0.2s ease",
3039
+ }, onFocus: (e) => {
3040
+ e.currentTarget.style.borderColor =
3041
+ (theme === null || theme === void 0 ? void 0 : theme.colors.primary) || "#1976d2";
3042
+ e.currentTarget.style.boxShadow = `0 0 0 2px ${((theme === null || theme === void 0 ? void 0 : theme.colors.primary) || "#1976d2") + "20"}`;
3043
+ }, onBlur: (e) => {
3044
+ e.currentTarget.style.borderColor =
3045
+ (theme === null || theme === void 0 ? void 0 : theme.colors.border) || "#d0d0d0";
3046
+ e.currentTarget.style.boxShadow = "none";
3047
+ } }, options.map((option) => (React.createElement("option", { key: option.value, value: option.value }, option.label)))));
3048
+ };
3049
+
3050
+ /**
3051
+ * LoadingState Component
3052
+ * Skeleton loader for reports
3053
+ */
3054
+ const Skeleton = ({ theme }) => (React.createElement("div", { style: {
3055
+ backgroundColor: (theme === null || theme === void 0 ? void 0 : theme.colors.border) || "#e0e0e0",
3056
+ borderRadius: (theme === null || theme === void 0 ? void 0 : theme.borderRadius) || "8px",
3057
+ height: "16px",
3058
+ marginBottom: (theme === null || theme === void 0 ? void 0 : theme.spacing.xs) || "4px",
3059
+ animation: "pulse 2s cubic-bezier(0.4, 0, 0.6, 1) infinite",
3060
+ } }));
3061
+ const LoadingState = ({ theme, variant = "minimal", }) => {
3062
+ if (variant === "minimal") {
3063
+ return (React.createElement("div", { style: {
3064
+ padding: (theme === null || theme === void 0 ? void 0 : theme.spacing.lg) || "24px",
3065
+ textAlign: "center",
3066
+ color: (theme === null || theme === void 0 ? void 0 : theme.colors.textSecondary) || "#666",
3067
+ } },
3068
+ React.createElement("div", { style: {
3069
+ display: "inline-block",
3070
+ width: "40px",
3071
+ height: "40px",
3072
+ border: `3px solid ${(theme === null || theme === void 0 ? void 0 : theme.colors.border) || "#e0e0e0"}`,
3073
+ borderTop: `3px solid ${(theme === null || theme === void 0 ? void 0 : theme.colors.primary) || "#1976d2"}`,
3074
+ borderRadius: "50%",
3075
+ animation: "spin 0.6s linear infinite",
3076
+ } }),
3077
+ React.createElement("p", { style: { marginTop: (theme === null || theme === void 0 ? void 0 : theme.spacing.sm) || "8px" } }, "Loading report...")));
3078
+ }
3079
+ if (variant === "cards") {
3080
+ return (React.createElement("div", { style: {
3081
+ display: "grid",
3082
+ gridTemplateColumns: "repeat(auto-fit, minmax(200px, 1fr))",
3083
+ gap: (theme === null || theme === void 0 ? void 0 : theme.spacing.md) || "16px",
3084
+ padding: (theme === null || theme === void 0 ? void 0 : theme.spacing.md) || "16px",
3085
+ } }, [1, 2, 3, 4].map((i) => (React.createElement("div", { key: i, style: {
3086
+ padding: (theme === null || theme === void 0 ? void 0 : theme.spacing.md) || "16px",
3087
+ border: `1px solid ${(theme === null || theme === void 0 ? void 0 : theme.colors.border) || "#e0e0e0"}`,
3088
+ borderRadius: (theme === null || theme === void 0 ? void 0 : theme.borderRadius) || "8px",
3089
+ backgroundColor: (theme === null || theme === void 0 ? void 0 : theme.colors.surface) || "#f5f5f5",
3090
+ } },
3091
+ React.createElement(Skeleton, { theme: theme }),
3092
+ React.createElement(Skeleton, { theme: theme }),
3093
+ React.createElement(Skeleton, { theme: theme }))))));
3094
+ }
3095
+ return (React.createElement("div", { style: {
3096
+ padding: (theme === null || theme === void 0 ? void 0 : theme.spacing.md) || "16px",
3097
+ border: `1px solid ${(theme === null || theme === void 0 ? void 0 : theme.colors.border) || "#e0e0e0"}`,
3098
+ borderRadius: (theme === null || theme === void 0 ? void 0 : theme.borderRadius) || "8px",
3099
+ backgroundColor: (theme === null || theme === void 0 ? void 0 : theme.colors.surface) || "#f5f5f5",
3100
+ } }, [1, 2, 3, 4, 5].map((i) => (React.createElement("div", { key: i, style: { marginBottom: (theme === null || theme === void 0 ? void 0 : theme.spacing.md) || "16px" } },
3101
+ React.createElement(Skeleton, { theme: theme }),
3102
+ React.createElement(Skeleton, { theme: theme }))))));
3103
+ };
3104
+
3105
+ /**
3106
+ * ReportLayout Component
3107
+ * Wrapper for report pages with header and date range selector
3108
+ */
3109
+ const ReportLayout = ({ title, description, selectedDateRange, onDateRangeChange, loading, error, children, theme: themeProp, }) => {
3110
+ const { theme: contextTheme } = useReactBridgeContext();
3111
+ const theme = themeProp || contextTheme;
3112
+ return (React.createElement("div", { style: {
3113
+ display: "flex",
3114
+ flexDirection: "column",
3115
+ gap: (theme === null || theme === void 0 ? void 0 : theme.spacing.md) || "12px",
3116
+ } },
3117
+ React.createElement("div", { style: {
3118
+ display: "flex",
3119
+ alignItems: "flex-start",
3120
+ justifyContent: "space-between",
3121
+ gap: (theme === null || theme === void 0 ? void 0 : theme.spacing.sm) || "12px",
3122
+ flexWrap: "wrap",
3123
+ } },
3124
+ React.createElement("div", { style: { flex: 1, minWidth: "200px" } },
3125
+ React.createElement("h1", { style: {
3126
+ margin: 0,
3127
+ fontSize: (theme === null || theme === void 0 ? void 0 : theme.fontSizes.lg) || "20px",
3128
+ fontWeight: "700",
3129
+ color: (theme === null || theme === void 0 ? void 0 : theme.colors.text) || "#000",
3130
+ } }, title),
3131
+ description && (React.createElement("p", { style: {
3132
+ margin: `${(theme === null || theme === void 0 ? void 0 : theme.spacing.xs) || "4px"} 0 0 0`,
3133
+ fontSize: (theme === null || theme === void 0 ? void 0 : theme.fontSizes.sm) || "12px",
3134
+ color: (theme === null || theme === void 0 ? void 0 : theme.colors.textSecondary) || "#666",
3135
+ } }, description))),
3136
+ React.createElement(DateRangeSelector, { selectedOption: selectedDateRange, onSelect: onDateRangeChange, theme: theme })),
3137
+ loading ? (React.createElement(LoadingState, { theme: theme })) : error ? (React.createElement("div", { style: {
3138
+ padding: (theme === null || theme === void 0 ? void 0 : theme.spacing.sm) || "12px",
3139
+ borderRadius: (theme === null || theme === void 0 ? void 0 : theme.borderRadius) || "6px",
3140
+ backgroundColor: (theme === null || theme === void 0 ? void 0 : theme.colors.error)
3141
+ ? `${theme.colors.error}15`
3142
+ : "#FEE2E2",
3143
+ border: `1px solid ${(theme === null || theme === void 0 ? void 0 : theme.colors.error) || "#f44336"}`,
3144
+ } },
3145
+ React.createElement("p", { style: {
3146
+ margin: 0,
3147
+ fontSize: (theme === null || theme === void 0 ? void 0 : theme.fontSizes.sm) || "12px",
3148
+ color: (theme === null || theme === void 0 ? void 0 : theme.colors.error) || "#f44336",
3149
+ fontWeight: "500",
3150
+ } },
3151
+ "Error loading report: ",
3152
+ error.message))) : (children)));
3153
+ };
3154
+
3155
+ /**
3156
+ * MetricCard Component
3157
+ * Displays a single KPI metric with optional trend indicator
3158
+ */
3159
+ const MetricCard = ({ label, value, unit, trend, trendValue, icon, onClick, theme, }) => {
3160
+ const getTrendColor = () => {
3161
+ if (!theme)
3162
+ return "inherit";
3163
+ if (trend === "up")
3164
+ return theme.colors.success;
3165
+ if (trend === "down")
3166
+ return theme.colors.error;
3167
+ return theme.colors.textSecondary;
3168
+ };
3169
+ const getTrendIcon = () => {
3170
+ if (trend === "up")
3171
+ return "↑";
3172
+ if (trend === "down")
3173
+ return "↓";
3174
+ return "→";
3175
+ };
3176
+ const containerStyles = {
3177
+ padding: (theme === null || theme === void 0 ? void 0 : theme.spacing.sm) || "10px",
3178
+ borderRadius: (theme === null || theme === void 0 ? void 0 : theme.borderRadius) || "6px",
3179
+ border: `1px solid ${(theme === null || theme === void 0 ? void 0 : theme.colors.border) || "#e0e0e0"}`,
3180
+ backgroundColor: (theme === null || theme === void 0 ? void 0 : theme.colors.surface) || "#f5f5f5",
3181
+ cursor: onClick ? "pointer" : "default",
3182
+ transition: "all 0.2s ease",
3183
+ };
3184
+ return (React.createElement("div", { style: containerStyles, onClick: onClick, onMouseEnter: (e) => {
3185
+ if (onClick) {
3186
+ e.currentTarget.style.boxShadow =
3187
+ (theme === null || theme === void 0 ? void 0 : theme.boxShadow) || "0 2px 8px rgba(0, 0, 0, 0.1)";
3188
+ }
3189
+ }, onMouseLeave: (e) => {
3190
+ if (onClick) {
3191
+ e.currentTarget.style.boxShadow = "none";
3192
+ }
3193
+ } },
3194
+ React.createElement("div", { style: {
3195
+ display: "flex",
3196
+ alignItems: "flex-start",
3197
+ justifyContent: "space-between",
3198
+ } },
3199
+ React.createElement("div", { style: { flex: 1 } },
3200
+ React.createElement("p", { style: {
3201
+ fontSize: (theme === null || theme === void 0 ? void 0 : theme.fontSizes.xs) || "11px",
3202
+ color: (theme === null || theme === void 0 ? void 0 : theme.colors.textSecondary) || "#666",
3203
+ margin: "0 0 6px 0",
3204
+ } }, label),
3205
+ React.createElement("div", { style: {
3206
+ display: "flex",
3207
+ alignItems: "baseline",
3208
+ gap: (theme === null || theme === void 0 ? void 0 : theme.spacing.xs) || "4px",
3209
+ } },
3210
+ React.createElement("p", { style: {
3211
+ fontSize: "18px",
3212
+ fontWeight: "bold",
3213
+ color: (theme === null || theme === void 0 ? void 0 : theme.colors.text) || "#000",
3214
+ margin: 0,
3215
+ } }, value),
3216
+ unit && (React.createElement("p", { style: {
3217
+ fontSize: (theme === null || theme === void 0 ? void 0 : theme.fontSizes.xs) || "11px",
3218
+ color: (theme === null || theme === void 0 ? void 0 : theme.colors.textSecondary) || "#666",
3219
+ margin: 0,
3220
+ } }, unit))),
3221
+ trend && trendValue !== undefined && (React.createElement("div", { style: {
3222
+ fontSize: "10px",
3223
+ color: getTrendColor(),
3224
+ marginTop: "4px",
3225
+ } },
3226
+ getTrendIcon(),
3227
+ " ",
3228
+ trendValue,
3229
+ "%"))),
3230
+ icon && (React.createElement("div", { style: {
3231
+ color: (theme === null || theme === void 0 ? void 0 : theme.colors.textSecondary) || "#999",
3232
+ fontSize: "18px",
3233
+ } }, icon)))));
3234
+ };
3235
+
3236
+ /**
3237
+ * TrendChart Component
3238
+ * Renders a simple line/area chart for trend data
3239
+ */
3240
+ const TrendChart = ({ data, title, height = 200, theme, showArea = true, }) => {
3241
+ if (!data || data.length === 0) {
3242
+ return (React.createElement("div", { style: {
3243
+ padding: (theme === null || theme === void 0 ? void 0 : theme.spacing.lg) || "24px",
3244
+ textAlign: "center",
3245
+ color: (theme === null || theme === void 0 ? void 0 : theme.colors.textSecondary) || "#666",
3246
+ } }, "No data available"));
3247
+ }
3248
+ const padding = 40;
3249
+ const width = 600;
3250
+ const innerHeight = height - padding * 2;
3251
+ const innerWidth = width - padding * 2;
3252
+ const maxValue = Math.max(...data.map((d) => d.value));
3253
+ const minValue = Math.min(...data.map((d) => d.value));
3254
+ const range = maxValue - minValue || 1;
3255
+ const points = data.map((d, i) => {
3256
+ const x = padding + (i / (data.length - 1 || 1)) * innerWidth;
3257
+ const y = padding + innerHeight - ((d.value - minValue) / range) * innerHeight;
3258
+ return Object.assign({ x, y }, d);
3259
+ });
3260
+ const pathD = points
3261
+ .map((p, i) => `${i === 0 ? "M" : "L"} ${p.x} ${p.y}`)
3262
+ .join(" ");
3263
+ const areaPathD = `${pathD} L ${points[points.length - 1].x} ${padding + innerHeight} L ${points[0].x} ${padding + innerHeight} Z`;
3264
+ const lineColor = (theme === null || theme === void 0 ? void 0 : theme.colors.primary) || "#1976d2";
3265
+ const areaColor = (theme === null || theme === void 0 ? void 0 : theme.colors.primary) || "#1976d2";
3266
+ return (React.createElement("div", null,
3267
+ title && (React.createElement("h3", { style: {
3268
+ margin: `0 0 ${(theme === null || theme === void 0 ? void 0 : theme.spacing.md) || "16px"} 0`,
3269
+ fontSize: (theme === null || theme === void 0 ? void 0 : theme.fontSizes.md) || "16px",
3270
+ fontWeight: "600",
3271
+ color: (theme === null || theme === void 0 ? void 0 : theme.colors.text) || "#000",
3272
+ } }, title)),
3273
+ React.createElement("svg", { width: "100%", height: height, viewBox: `0 0 ${width} ${height}`, preserveAspectRatio: "xMidYMid meet", style: { overflow: "visible" } },
3274
+ [0, 0.25, 0.5, 0.75, 1].map((factor) => {
3275
+ const y = padding + innerHeight - factor * innerHeight;
3276
+ return (React.createElement("line", { key: `grid-${factor}`, x1: padding, y1: y, x2: width - padding, y2: y, stroke: (theme === null || theme === void 0 ? void 0 : theme.colors.border) || "#e0e0e0", strokeWidth: "1", strokeDasharray: "4", opacity: "0.5" }));
3277
+ }),
3278
+ showArea && React.createElement("path", { d: areaPathD, fill: areaColor, fillOpacity: "0.1" }),
3279
+ React.createElement("path", { d: pathD, fill: "none", stroke: lineColor, strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" }),
3280
+ points.map((p, i) => (React.createElement("circle", { key: `point-${i}`, cx: p.x, cy: p.y, r: "3", fill: lineColor, opacity: "0.8" }))),
3281
+ points.map((p, i) => {
3282
+ if (data.length <= 6 || i % Math.ceil(data.length / 6) === 0) {
3283
+ return (React.createElement("text", { key: `label-${i}`, x: p.x, y: height - padding + 20, textAnchor: "middle", fontSize: "12", fill: (theme === null || theme === void 0 ? void 0 : theme.colors.textSecondary) || "#666" }, p.label));
3284
+ }
3285
+ }))));
3286
+ };
3287
+
3288
+ /**
3289
+ * Executive Dashboard Report
3290
+ * High-level directive execution metrics, trends, and cost impact
3291
+ */
3292
+ const ExecutiveDashboard = ({ theme: themeProp, defaultDateRange = "past-month", }) => {
3293
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m;
3294
+ const { api, theme: contextTheme } = useReactBridgeContext();
3295
+ const theme = themeProp || contextTheme;
3296
+ const dateRange = useDateRange(defaultDateRange);
3297
+ const { data, loading, error } = useReportData(() => api.getExecutiveDashboard({
3298
+ startDate: dateRange.startDate,
3299
+ endDate: dateRange.endDate,
3300
+ }), [dateRange.startDate, dateRange.endDate]);
3301
+ const trendData = ((_a = data === null || data === void 0 ? void 0 : data.monthlyTrends) === null || _a === void 0 ? void 0 : _a.map((m) => ({
3302
+ label: m.month,
3303
+ value: m.successPercentage,
3304
+ }))) || [];
3305
+ return (React.createElement(ReportLayout, { title: "Executive Dashboard", description: "High-level directive execution metrics and trends", selectedDateRange: dateRange.selectedOption, onDateRangeChange: dateRange.setSelectedOption, loading: loading, error: error, theme: theme },
3306
+ React.createElement("div", { style: {
3307
+ display: "grid",
3308
+ gridTemplateColumns: "repeat(auto-fit, minmax(180px, 1fr))",
3309
+ gap: (theme === null || theme === void 0 ? void 0 : theme.spacing.sm) || "10px",
3310
+ } },
3311
+ React.createElement(MetricCard, { label: "Total Directives", value: (_b = data === null || data === void 0 ? void 0 : data.totalDirectives) !== null && _b !== void 0 ? _b : 0, theme: theme }),
3312
+ React.createElement(MetricCard, { label: "Success Rate", value: (_d = (_c = data === null || data === void 0 ? void 0 : data.successRate) === null || _c === void 0 ? void 0 : _c.toFixed(2)) !== null && _d !== void 0 ? _d : 0, unit: "%", trend: ((_e = data === null || data === void 0 ? void 0 : data.successRate) !== null && _e !== void 0 ? _e : 0 > 80) ? "up" : "neutral", theme: theme }),
3313
+ React.createElement(MetricCard, { label: "Auto-Executed", value: (_f = data === null || data === void 0 ? void 0 : data.autoExecutedDirectives) !== null && _f !== void 0 ? _f : 0, theme: theme }),
3314
+ React.createElement(MetricCard, { label: "Cost Impact", value: (_h = (_g = data === null || data === void 0 ? void 0 : data.totalCostImpact) === null || _g === void 0 ? void 0 : _g.toFixed(2)) !== null && _h !== void 0 ? _h : 0, unit: "$", theme: theme })),
3315
+ trendData.length > 0 && (React.createElement("div", { style: {
3316
+ padding: (theme === null || theme === void 0 ? void 0 : theme.spacing.sm) || "10px",
3317
+ border: `1px solid ${(theme === null || theme === void 0 ? void 0 : theme.colors.border) || "#e0e0e0"}`,
3318
+ borderRadius: (theme === null || theme === void 0 ? void 0 : theme.borderRadius) || "6px",
3319
+ backgroundColor: (theme === null || theme === void 0 ? void 0 : theme.colors.surface) || "#f5f5f5",
3320
+ } },
3321
+ React.createElement(TrendChart, { data: trendData, title: "Success Rate Trend", theme: theme, showArea: true }))),
3322
+ React.createElement("div", { style: {
3323
+ display: "grid",
3324
+ gridTemplateColumns: "repeat(auto-fit, minmax(220px, 1fr))",
3325
+ gap: (theme === null || theme === void 0 ? void 0 : theme.spacing.sm) || "10px",
3326
+ } },
3327
+ React.createElement("div", { style: {
3328
+ padding: (theme === null || theme === void 0 ? void 0 : theme.spacing.sm) || "10px",
3329
+ border: `1px solid ${(theme === null || theme === void 0 ? void 0 : theme.colors.border) || "#e0e0e0"}`,
3330
+ borderRadius: (theme === null || theme === void 0 ? void 0 : theme.borderRadius) || "6px",
3331
+ backgroundColor: (theme === null || theme === void 0 ? void 0 : theme.colors.surface) || "#f5f5f5",
3332
+ } },
3333
+ React.createElement("h3", { style: {
3334
+ margin: `0 0 ${(theme === null || theme === void 0 ? void 0 : theme.spacing.sm) || "8px"} 0`,
3335
+ fontSize: (theme === null || theme === void 0 ? void 0 : theme.fontSizes.sm) || "13px",
3336
+ fontWeight: "600",
3337
+ color: (theme === null || theme === void 0 ? void 0 : theme.colors.text) || "#000",
3338
+ } }, "Execution Summary"),
3339
+ React.createElement("div", { style: {
3340
+ display: "flex",
3341
+ flexDirection: "column",
3342
+ gap: (theme === null || theme === void 0 ? void 0 : theme.spacing.xs) || "4px",
3343
+ } },
3344
+ React.createElement("div", { style: {
3345
+ display: "flex",
3346
+ justifyContent: "space-between",
3347
+ padding: `${(theme === null || theme === void 0 ? void 0 : theme.spacing.xs) || "3px"} 0`,
3348
+ fontSize: (theme === null || theme === void 0 ? void 0 : theme.fontSizes.xs) || "11px",
3349
+ } },
3350
+ React.createElement("span", { style: { color: (theme === null || theme === void 0 ? void 0 : theme.colors.textSecondary) || "#666" } }, "Successful:"),
3351
+ React.createElement("span", { style: {
3352
+ fontWeight: "600",
3353
+ color: (theme === null || theme === void 0 ? void 0 : theme.colors.success) || "#4caf50",
3354
+ } }, (_j = data === null || data === void 0 ? void 0 : data.successfulExecutions) !== null && _j !== void 0 ? _j : 0)),
3355
+ React.createElement("div", { style: {
3356
+ display: "flex",
3357
+ justifyContent: "space-between",
3358
+ padding: `${(theme === null || theme === void 0 ? void 0 : theme.spacing.xs) || "3px"} 0`,
3359
+ fontSize: (theme === null || theme === void 0 ? void 0 : theme.fontSizes.xs) || "11px",
3360
+ } },
3361
+ React.createElement("span", { style: { color: (theme === null || theme === void 0 ? void 0 : theme.colors.textSecondary) || "#666" } }, "Failed:"),
3362
+ React.createElement("span", { style: {
3363
+ fontWeight: "600",
3364
+ color: (theme === null || theme === void 0 ? void 0 : theme.colors.error) || "#f44336",
3365
+ } }, (_k = data === null || data === void 0 ? void 0 : data.failedExecutions) !== null && _k !== void 0 ? _k : 0)),
3366
+ React.createElement("div", { style: {
3367
+ display: "flex",
3368
+ justifyContent: "space-between",
3369
+ padding: `${(theme === null || theme === void 0 ? void 0 : theme.spacing.xs) || "3px"} 0`,
3370
+ fontSize: (theme === null || theme === void 0 ? void 0 : theme.fontSizes.xs) || "11px",
3371
+ } },
3372
+ React.createElement("span", { style: { color: (theme === null || theme === void 0 ? void 0 : theme.colors.textSecondary) || "#666" } }, "Avg Cost:"),
3373
+ React.createElement("span", { style: {
3374
+ fontWeight: "600",
3375
+ color: (theme === null || theme === void 0 ? void 0 : theme.colors.text) || "#000",
3376
+ } },
3377
+ "$", (_m = (_l = data === null || data === void 0 ? void 0 : data.averageCostPerDirective) === null || _l === void 0 ? void 0 : _l.toFixed(2)) !== null && _m !== void 0 ? _m : 0)))))));
3378
+ };
3379
+
3380
+ /**
3381
+ * ProgressBar Component
3382
+ * Displays percentage with visual bar
3383
+ */
3384
+ const ProgressBar = ({ percentage, label, showPercentage = true, height = "medium", theme, }) => {
3385
+ const normalizedPercentage = Math.min(Math.max(percentage, 0), 100);
3386
+ const getBarColor = () => {
3387
+ if (!theme) {
3388
+ if (normalizedPercentage >= 80)
3389
+ return "#10B981";
3390
+ if (normalizedPercentage >= 60)
3391
+ return "#F59E0B";
3392
+ return "#EF4444";
3393
+ }
3394
+ if (normalizedPercentage >= 80)
3395
+ return theme.colors.success;
3396
+ if (normalizedPercentage >= 60)
3397
+ return "#F59E0B"; // warning
3398
+ return theme.colors.error;
3399
+ };
3400
+ const heightConfig = {
3401
+ small: "4px",
3402
+ medium: "8px",
3403
+ large: "12px",
3404
+ };
3405
+ return (React.createElement("div", null,
3406
+ (label || showPercentage) && (React.createElement("div", { style: {
3407
+ display: "flex",
3408
+ justifyContent: "space-between",
3409
+ alignItems: "center",
3410
+ marginBottom: (theme === null || theme === void 0 ? void 0 : theme.spacing.xs) || "4px",
3411
+ } },
3412
+ label && (React.createElement("span", { style: {
3413
+ fontSize: (theme === null || theme === void 0 ? void 0 : theme.fontSizes.sm) || "14px",
3414
+ color: (theme === null || theme === void 0 ? void 0 : theme.colors.text) || "#000",
3415
+ fontWeight: "500",
3416
+ } }, label)),
3417
+ showPercentage && (React.createElement("span", { style: {
3418
+ fontSize: (theme === null || theme === void 0 ? void 0 : theme.fontSizes.xs) || "12px",
3419
+ color: (theme === null || theme === void 0 ? void 0 : theme.colors.textSecondary) || "#666",
3420
+ } },
3421
+ normalizedPercentage.toFixed(1),
3422
+ "%")))),
3423
+ React.createElement("div", { style: {
3424
+ width: "100%",
3425
+ height: heightConfig[height],
3426
+ backgroundColor: (theme === null || theme === void 0 ? void 0 : theme.colors.border) || "#e0e0e0",
3427
+ borderRadius: "4px",
3428
+ overflow: "hidden",
3429
+ } },
3430
+ React.createElement("div", { style: {
3431
+ height: "100%",
3432
+ width: `${normalizedPercentage}%`,
3433
+ backgroundColor: getBarColor(),
3434
+ transition: "width 0.3s ease",
3435
+ } }))));
3436
+ };
3437
+
3438
+ /**
3439
+ * DataTable Component
3440
+ * Generic sortable/paginated table for report data
3441
+ */
3442
+ const DataTable = React.forwardRef(({ columns, data, title, pageSize = 10, theme }, ref) => {
3443
+ const [sortKey, setSortKey] = useState(null);
3444
+ const [sortOrder, setSortOrder] = useState("asc");
3445
+ const [currentPage, setCurrentPage] = useState(0);
3446
+ const sortedData = useMemo(() => {
3447
+ if (!sortKey)
3448
+ return data;
3449
+ const sorted = [...data].sort((a, b) => {
3450
+ const aVal = a[sortKey];
3451
+ const bVal = b[sortKey];
3452
+ if (aVal < bVal)
3453
+ return sortOrder === "asc" ? -1 : 1;
3454
+ if (aVal > bVal)
3455
+ return sortOrder === "asc" ? 1 : -1;
3456
+ return 0;
3457
+ });
3458
+ return sorted;
3459
+ }, [data, sortKey, sortOrder]);
3460
+ const paginatedData = useMemo(() => {
3461
+ const start = currentPage * pageSize;
3462
+ return sortedData.slice(start, start + pageSize);
3463
+ }, [sortedData, currentPage, pageSize]);
3464
+ const totalPages = Math.ceil(sortedData.length / pageSize);
3465
+ const handleSort = (key) => {
3466
+ if (sortKey === key) {
3467
+ setSortOrder(sortOrder === "asc" ? "desc" : "asc");
3468
+ }
3469
+ else {
3470
+ setSortKey(key);
3471
+ setSortOrder("asc");
3472
+ }
3473
+ setCurrentPage(0);
3474
+ };
3475
+ return (React.createElement("div", { ref: ref },
3476
+ title && (React.createElement("h3", { style: {
3477
+ margin: `0 0 ${(theme === null || theme === void 0 ? void 0 : theme.spacing.md) || "16px"} 0`,
3478
+ fontSize: (theme === null || theme === void 0 ? void 0 : theme.fontSizes.md) || "16px",
3479
+ fontWeight: "600",
3480
+ color: (theme === null || theme === void 0 ? void 0 : theme.colors.text) || "#000",
3481
+ } }, title)),
3482
+ data.length === 0 ? (React.createElement("div", { style: {
3483
+ padding: (theme === null || theme === void 0 ? void 0 : theme.spacing.lg) || "24px",
3484
+ textAlign: "center",
3485
+ color: (theme === null || theme === void 0 ? void 0 : theme.colors.textSecondary) || "#666",
3486
+ border: `1px solid ${(theme === null || theme === void 0 ? void 0 : theme.colors.border) || "#e0e0e0"}`,
3487
+ borderRadius: (theme === null || theme === void 0 ? void 0 : theme.borderRadius) || "8px",
3488
+ } }, "No data available")) : (React.createElement(React.Fragment, null,
3489
+ React.createElement("div", { style: {
3490
+ overflowX: "auto",
3491
+ border: `1px solid ${(theme === null || theme === void 0 ? void 0 : theme.colors.border) || "#e0e0e0"}`,
3492
+ borderRadius: (theme === null || theme === void 0 ? void 0 : theme.borderRadius) || "8px",
3493
+ } },
3494
+ React.createElement("table", { style: {
3495
+ width: "100%",
3496
+ borderCollapse: "collapse",
3497
+ fontSize: (theme === null || theme === void 0 ? void 0 : theme.fontSizes.sm) || "14px",
3498
+ } },
3499
+ React.createElement("thead", null,
3500
+ React.createElement("tr", { style: {
3501
+ backgroundColor: (theme === null || theme === void 0 ? void 0 : theme.colors.surface) || "#f5f5f5",
3502
+ borderBottom: `1px solid ${(theme === null || theme === void 0 ? void 0 : theme.colors.border) || "#e0e0e0"}`,
3503
+ } }, columns.map((col) => (React.createElement("th", { key: String(col.key), onClick: () => col.sortable && handleSort(String(col.key)), style: {
3504
+ padding: (theme === null || theme === void 0 ? void 0 : theme.spacing.sm) || "8px",
3505
+ textAlign: "left",
3506
+ fontWeight: "600",
3507
+ color: (theme === null || theme === void 0 ? void 0 : theme.colors.text) || "#000",
3508
+ cursor: col.sortable ? "pointer" : "default",
3509
+ userSelect: "none",
3510
+ width: col.width,
3511
+ whiteSpace: "nowrap",
3512
+ }, onMouseEnter: (e) => {
3513
+ if (col.sortable) {
3514
+ e.currentTarget.style.backgroundColor =
3515
+ (theme === null || theme === void 0 ? void 0 : theme.colors.border) || "#e0e0e0";
3516
+ }
3517
+ }, onMouseLeave: (e) => {
3518
+ e.currentTarget.style.backgroundColor =
3519
+ (theme === null || theme === void 0 ? void 0 : theme.colors.surface) || "#f5f5f5";
3520
+ } },
3521
+ React.createElement("div", { style: {
3522
+ display: "flex",
3523
+ alignItems: "center",
3524
+ gap: "4px",
3525
+ } },
3526
+ col.label,
3527
+ col.sortable && sortKey === String(col.key) && (React.createElement("span", null, sortOrder === "asc" ? "↑" : "↓")))))))),
3528
+ React.createElement("tbody", null, paginatedData.map((row, idx) => (React.createElement("tr", { key: row.id || idx, style: {
3529
+ borderBottom: `1px solid ${(theme === null || theme === void 0 ? void 0 : theme.colors.border) || "#e0e0e0"}`,
3530
+ backgroundColor: idx % 2 === 0
3531
+ ? "transparent"
3532
+ : (theme === null || theme === void 0 ? void 0 : theme.colors.surface) || "#f5f5f5",
3533
+ }, onMouseEnter: (e) => {
3534
+ e.currentTarget.style.backgroundColor =
3535
+ (theme === null || theme === void 0 ? void 0 : theme.colors.border) || "#e0e0e0";
3536
+ }, onMouseLeave: (e) => {
3537
+ e.currentTarget.style.backgroundColor =
3538
+ idx % 2 === 0
3539
+ ? "transparent"
3540
+ : (theme === null || theme === void 0 ? void 0 : theme.colors.surface) || "#f5f5f5";
3541
+ } }, columns.map((col) => (React.createElement("td", { key: String(col.key), style: {
3542
+ padding: (theme === null || theme === void 0 ? void 0 : theme.spacing.sm) || "8px",
3543
+ color: (theme === null || theme === void 0 ? void 0 : theme.colors.text) || "#000",
3544
+ } }, col.render
3545
+ ? col.render(row[col.key], row)
3546
+ : String(row[col.key])))))))))),
3547
+ totalPages > 1 && (React.createElement("div", { style: {
3548
+ marginTop: (theme === null || theme === void 0 ? void 0 : theme.spacing.md) || "16px",
3549
+ display: "flex",
3550
+ justifyContent: "space-between",
3551
+ alignItems: "center",
3552
+ } },
3553
+ React.createElement("span", { style: {
3554
+ fontSize: (theme === null || theme === void 0 ? void 0 : theme.fontSizes.sm) || "14px",
3555
+ color: (theme === null || theme === void 0 ? void 0 : theme.colors.textSecondary) || "#666",
3556
+ } },
3557
+ "Page ",
3558
+ currentPage + 1,
3559
+ " of ",
3560
+ totalPages),
3561
+ React.createElement("div", { style: { display: "flex", gap: (theme === null || theme === void 0 ? void 0 : theme.spacing.xs) || "4px" } },
3562
+ React.createElement("button", { onClick: () => setCurrentPage(0), disabled: currentPage === 0, style: {
3563
+ padding: `${(theme === null || theme === void 0 ? void 0 : theme.spacing.xs) || "4px"} ${(theme === null || theme === void 0 ? void 0 : theme.spacing.sm) || "8px"}`,
3564
+ fontSize: (theme === null || theme === void 0 ? void 0 : theme.fontSizes.sm) || "14px",
3565
+ borderRadius: "4px",
3566
+ border: `1px solid ${(theme === null || theme === void 0 ? void 0 : theme.colors.border) || "#e0e0e0"}`,
3567
+ backgroundColor: (theme === null || theme === void 0 ? void 0 : theme.colors.surface) || "#f5f5f5",
3568
+ cursor: currentPage === 0 ? "not-allowed" : "pointer",
3569
+ opacity: currentPage === 0 ? 0.5 : 1,
3570
+ } }, "First"),
3571
+ React.createElement("button", { onClick: () => setCurrentPage(Math.max(0, currentPage - 1)), disabled: currentPage === 0, style: {
3572
+ padding: `${(theme === null || theme === void 0 ? void 0 : theme.spacing.xs) || "4px"} ${(theme === null || theme === void 0 ? void 0 : theme.spacing.sm) || "8px"}`,
3573
+ fontSize: (theme === null || theme === void 0 ? void 0 : theme.fontSizes.sm) || "14px",
3574
+ borderRadius: "4px",
3575
+ border: `1px solid ${(theme === null || theme === void 0 ? void 0 : theme.colors.border) || "#e0e0e0"}`,
3576
+ backgroundColor: (theme === null || theme === void 0 ? void 0 : theme.colors.surface) || "#f5f5f5",
3577
+ cursor: currentPage === 0 ? "not-allowed" : "pointer",
3578
+ opacity: currentPage === 0 ? 0.5 : 1,
3579
+ } }, "Previous"),
3580
+ React.createElement("button", { onClick: () => setCurrentPage(Math.min(totalPages - 1, currentPage + 1)), disabled: currentPage === totalPages - 1, style: {
3581
+ padding: `${(theme === null || theme === void 0 ? void 0 : theme.spacing.xs) || "4px"} ${(theme === null || theme === void 0 ? void 0 : theme.spacing.sm) || "8px"}`,
3582
+ fontSize: (theme === null || theme === void 0 ? void 0 : theme.fontSizes.sm) || "14px",
3583
+ borderRadius: "4px",
3584
+ border: `1px solid ${(theme === null || theme === void 0 ? void 0 : theme.colors.border) || "#e0e0e0"}`,
3585
+ backgroundColor: (theme === null || theme === void 0 ? void 0 : theme.colors.surface) || "#f5f5f5",
3586
+ cursor: currentPage === totalPages - 1
3587
+ ? "not-allowed"
3588
+ : "pointer",
3589
+ opacity: currentPage === totalPages - 1 ? 0.5 : 1,
3590
+ } }, "Next"),
3591
+ React.createElement("button", { onClick: () => setCurrentPage(totalPages - 1), disabled: currentPage === totalPages - 1, style: {
3592
+ padding: `${(theme === null || theme === void 0 ? void 0 : theme.spacing.xs) || "4px"} ${(theme === null || theme === void 0 ? void 0 : theme.spacing.sm) || "8px"}`,
3593
+ fontSize: (theme === null || theme === void 0 ? void 0 : theme.fontSizes.sm) || "14px",
3594
+ borderRadius: "4px",
3595
+ border: `1px solid ${(theme === null || theme === void 0 ? void 0 : theme.colors.border) || "#e0e0e0"}`,
3596
+ backgroundColor: (theme === null || theme === void 0 ? void 0 : theme.colors.surface) || "#f5f5f5",
3597
+ cursor: currentPage === totalPages - 1
3598
+ ? "not-allowed"
3599
+ : "pointer",
3600
+ opacity: currentPage === totalPages - 1 ? 0.5 : 1,
3601
+ } }, "Last"))))))));
3602
+ });
3603
+ DataTable.displayName = "DataTable";
3604
+
3605
+ /**
3606
+ * Supply Chain Risk Report
3607
+ * Supply chain risks including inventory, supplier, and cost analysis
3608
+ */
3609
+ const SupplyChainRisk = ({ theme: themeProp, defaultDateRange = "past-month", }) => {
3610
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x, _y, _z, _0, _1, _2, _3;
3611
+ const { api, theme: contextTheme } = useReactBridgeContext();
3612
+ const theme = themeProp || contextTheme;
3613
+ const dateRange = useDateRange(defaultDateRange);
3614
+ const { data, loading, error } = useReportData(() => api.getSupplyChainRisk({
3615
+ startDate: dateRange.startDate,
3616
+ endDate: dateRange.endDate,
3617
+ }), [dateRange.startDate, dateRange.endDate]);
3618
+ const riskPercentage = (_a = data === null || data === void 0 ? void 0 : data.overallRiskScore) !== null && _a !== void 0 ? _a : 0;
3619
+ ((_b = data === null || data === void 0 ? void 0 : data.highRiskCount) !== null && _b !== void 0 ? _b : 0) +
3620
+ ((_c = data === null || data === void 0 ? void 0 : data.mediumRiskCount) !== null && _c !== void 0 ? _c : 0) +
3621
+ ((_d = data === null || data === void 0 ? void 0 : data.lowRiskCount) !== null && _d !== void 0 ? _d : 0);
3622
+ const tableColumns = [
3623
+ {
3624
+ key: "issueType",
3625
+ label: "Issue Type",
3626
+ sortable: true,
3627
+ },
3628
+ {
3629
+ key: "description",
3630
+ label: "Description",
3631
+ sortable: true,
3632
+ },
3633
+ {
3634
+ key: "affectedRecords",
3635
+ label: "Affected Records",
3636
+ sortable: true,
3637
+ },
3638
+ {
3639
+ key: "severity",
3640
+ label: "Severity",
3641
+ sortable: true,
3642
+ render: (value) => {
3643
+ const color = value === "high"
3644
+ ? theme === null || theme === void 0 ? void 0 : theme.colors.error
3645
+ : value === "medium"
3646
+ ? "#F59E0B"
3647
+ : theme === null || theme === void 0 ? void 0 : theme.colors.success;
3648
+ return (React.createElement("span", { style: { color, fontWeight: "600" } }, value.toUpperCase()));
3649
+ },
3650
+ },
3651
+ ];
3652
+ return (React.createElement(ReportLayout, { title: "Supply Chain Risk", description: "Inventory, supplier, and cost risk analysis", selectedDateRange: dateRange.selectedOption, onDateRangeChange: dateRange.setSelectedOption, loading: loading, error: error, theme: theme },
3653
+ React.createElement("div", { style: {
3654
+ padding: (theme === null || theme === void 0 ? void 0 : theme.spacing.md) || "16px",
3655
+ border: `1px solid ${(theme === null || theme === void 0 ? void 0 : theme.colors.border) || "#e0e0e0"}`,
3656
+ borderRadius: (theme === null || theme === void 0 ? void 0 : theme.borderRadius) || "8px",
3657
+ backgroundColor: (theme === null || theme === void 0 ? void 0 : theme.colors.surface) || "#f5f5f5",
3658
+ } },
3659
+ React.createElement("h3", { style: {
3660
+ margin: `0 0 ${(theme === null || theme === void 0 ? void 0 : theme.spacing.md) || "16px"} 0`,
3661
+ fontSize: (theme === null || theme === void 0 ? void 0 : theme.fontSizes.lg) || "18px",
3662
+ fontWeight: "600",
3663
+ color: (theme === null || theme === void 0 ? void 0 : theme.colors.text) || "#000",
3664
+ } }, "Overall Risk Assessment"),
3665
+ React.createElement(ProgressBar, { percentage: riskPercentage, label: "Risk Score", theme: theme, height: "large" })),
3666
+ React.createElement("div", { style: {
3667
+ display: "grid",
3668
+ gridTemplateColumns: "repeat(auto-fit, minmax(200px, 1fr))",
3669
+ gap: (theme === null || theme === void 0 ? void 0 : theme.spacing.md) || "16px",
3670
+ } },
3671
+ React.createElement(MetricCard, { label: "High Risk Items", value: (_e = data === null || data === void 0 ? void 0 : data.highRiskCount) !== null && _e !== void 0 ? _e : 0, theme: theme }),
3672
+ React.createElement(MetricCard, { label: "Medium Risk Items", value: (_f = data === null || data === void 0 ? void 0 : data.mediumRiskCount) !== null && _f !== void 0 ? _f : 0, theme: theme }),
3673
+ React.createElement(MetricCard, { label: "Low Risk Items", value: (_g = data === null || data === void 0 ? void 0 : data.lowRiskCount) !== null && _g !== void 0 ? _g : 0, theme: theme })),
3674
+ React.createElement("div", { style: {
3675
+ display: "grid",
3676
+ gridTemplateColumns: "repeat(auto-fit, minmax(250px, 1fr))",
3677
+ gap: (theme === null || theme === void 0 ? void 0 : theme.spacing.md) || "16px",
3678
+ } },
3679
+ React.createElement("div", { style: {
3680
+ padding: (theme === null || theme === void 0 ? void 0 : theme.spacing.md) || "16px",
3681
+ border: `1px solid ${(theme === null || theme === void 0 ? void 0 : theme.colors.border) || "#e0e0e0"}`,
3682
+ borderRadius: (theme === null || theme === void 0 ? void 0 : theme.borderRadius) || "8px",
3683
+ backgroundColor: (theme === null || theme === void 0 ? void 0 : theme.colors.surface) || "#f5f5f5",
3684
+ } },
3685
+ React.createElement("h4", { style: {
3686
+ margin: `0 0 ${(theme === null || theme === void 0 ? void 0 : theme.spacing.md) || "16px"} 0`,
3687
+ fontSize: (theme === null || theme === void 0 ? void 0 : theme.fontSizes.md) || "16px",
3688
+ fontWeight: "600",
3689
+ color: (theme === null || theme === void 0 ? void 0 : theme.colors.text) || "#000",
3690
+ } }, "Inventory Risk"),
3691
+ React.createElement("div", { style: {
3692
+ display: "flex",
3693
+ flexDirection: "column",
3694
+ gap: (theme === null || theme === void 0 ? void 0 : theme.spacing.sm) || "8px",
3695
+ } },
3696
+ React.createElement("div", { style: {
3697
+ display: "flex",
3698
+ justifyContent: "space-between",
3699
+ padding: `${(theme === null || theme === void 0 ? void 0 : theme.spacing.xs) || "4px"} 0`,
3700
+ } },
3701
+ React.createElement("span", { style: { color: (theme === null || theme === void 0 ? void 0 : theme.colors.textSecondary) || "#666" } }, "Low Stock Items:"),
3702
+ React.createElement("span", { style: { fontWeight: "600" } }, (_j = (_h = data === null || data === void 0 ? void 0 : data.inventoryRisk) === null || _h === void 0 ? void 0 : _h.lowStockItems) !== null && _j !== void 0 ? _j : 0)),
3703
+ React.createElement("div", { style: {
3704
+ display: "flex",
3705
+ justifyContent: "space-between",
3706
+ padding: `${(theme === null || theme === void 0 ? void 0 : theme.spacing.xs) || "4px"} 0`,
3707
+ } },
3708
+ React.createElement("span", { style: { color: (theme === null || theme === void 0 ? void 0 : theme.colors.textSecondary) || "#666" } }, "Overstocked Items:"),
3709
+ React.createElement("span", { style: { fontWeight: "600" } }, (_l = (_k = data === null || data === void 0 ? void 0 : data.inventoryRisk) === null || _k === void 0 ? void 0 : _k.overstockedItems) !== null && _l !== void 0 ? _l : 0)),
3710
+ React.createElement(ProgressBar, { percentage: (_o = (_m = data === null || data === void 0 ? void 0 : data.inventoryRisk) === null || _m === void 0 ? void 0 : _m.averageStockHealth) !== null && _o !== void 0 ? _o : 0, label: "Stock Health", theme: theme }))),
3711
+ React.createElement("div", { style: {
3712
+ padding: (theme === null || theme === void 0 ? void 0 : theme.spacing.md) || "16px",
3713
+ border: `1px solid ${(theme === null || theme === void 0 ? void 0 : theme.colors.border) || "#e0e0e0"}`,
3714
+ borderRadius: (theme === null || theme === void 0 ? void 0 : theme.borderRadius) || "8px",
3715
+ backgroundColor: (theme === null || theme === void 0 ? void 0 : theme.colors.surface) || "#f5f5f5",
3716
+ } },
3717
+ React.createElement("h4", { style: {
3718
+ margin: `0 0 ${(theme === null || theme === void 0 ? void 0 : theme.spacing.md) || "16px"} 0`,
3719
+ fontSize: (theme === null || theme === void 0 ? void 0 : theme.fontSizes.md) || "16px",
3720
+ fontWeight: "600",
3721
+ color: (theme === null || theme === void 0 ? void 0 : theme.colors.text) || "#000",
3722
+ } }, "Supplier Risk"),
3723
+ React.createElement("div", { style: {
3724
+ display: "flex",
3725
+ flexDirection: "column",
3726
+ gap: (theme === null || theme === void 0 ? void 0 : theme.spacing.sm) || "8px",
3727
+ } },
3728
+ React.createElement("div", { style: {
3729
+ display: "flex",
3730
+ justifyContent: "space-between",
3731
+ padding: `${(theme === null || theme === void 0 ? void 0 : theme.spacing.xs) || "4px"} 0`,
3732
+ } },
3733
+ React.createElement("span", { style: { color: (theme === null || theme === void 0 ? void 0 : theme.colors.textSecondary) || "#666" } }, "Unreliable Suppliers:"),
3734
+ React.createElement("span", { style: { fontWeight: "600" } }, (_q = (_p = data === null || data === void 0 ? void 0 : data.supplierRisk) === null || _p === void 0 ? void 0 : _p.unreliableSuppliers) !== null && _q !== void 0 ? _q : 0)),
3735
+ React.createElement("div", { style: {
3736
+ display: "flex",
3737
+ justifyContent: "space-between",
3738
+ padding: `${(theme === null || theme === void 0 ? void 0 : theme.spacing.xs) || "4px"} 0`,
3739
+ } },
3740
+ React.createElement("span", { style: { color: (theme === null || theme === void 0 ? void 0 : theme.colors.textSecondary) || "#666" } }, "High Defect Rate:"),
3741
+ React.createElement("span", { style: { fontWeight: "600" } }, (_s = (_r = data === null || data === void 0 ? void 0 : data.supplierRisk) === null || _r === void 0 ? void 0 : _r.highDefectRateSuppliers) !== null && _s !== void 0 ? _s : 0)),
3742
+ React.createElement(ProgressBar, { percentage: (_u = (_t = data === null || data === void 0 ? void 0 : data.supplierRisk) === null || _t === void 0 ? void 0 : _t.averageSupplierScore) !== null && _u !== void 0 ? _u : 0, label: "Supplier Score", theme: theme }))),
3743
+ React.createElement("div", { style: {
3744
+ padding: (theme === null || theme === void 0 ? void 0 : theme.spacing.md) || "16px",
3745
+ border: `1px solid ${(theme === null || theme === void 0 ? void 0 : theme.colors.border) || "#e0e0e0"}`,
3746
+ borderRadius: (theme === null || theme === void 0 ? void 0 : theme.borderRadius) || "8px",
3747
+ backgroundColor: (theme === null || theme === void 0 ? void 0 : theme.colors.surface) || "#f5f5f5",
3748
+ } },
3749
+ React.createElement("h4", { style: {
3750
+ margin: `0 0 ${(theme === null || theme === void 0 ? void 0 : theme.spacing.md) || "16px"} 0`,
3751
+ fontSize: (theme === null || theme === void 0 ? void 0 : theme.fontSizes.md) || "16px",
3752
+ fontWeight: "600",
3753
+ color: (theme === null || theme === void 0 ? void 0 : theme.colors.text) || "#000",
3754
+ } }, "Cost Risk"),
3755
+ React.createElement("div", { style: {
3756
+ display: "flex",
3757
+ flexDirection: "column",
3758
+ gap: (theme === null || theme === void 0 ? void 0 : theme.spacing.sm) || "8px",
3759
+ } },
3760
+ React.createElement("div", { style: {
3761
+ display: "flex",
3762
+ justifyContent: "space-between",
3763
+ padding: `${(theme === null || theme === void 0 ? void 0 : theme.spacing.xs) || "4px"} 0`,
3764
+ } },
3765
+ React.createElement("span", { style: { color: (theme === null || theme === void 0 ? void 0 : theme.colors.textSecondary) || "#666" } }, "Cost Variance:"),
3766
+ React.createElement("span", { style: {
3767
+ fontWeight: "600",
3768
+ color: (theme === null || theme === void 0 ? void 0 : theme.colors.error) || "#f44336",
3769
+ } },
3770
+ "$", (_x = (_w = (_v = data === null || data === void 0 ? void 0 : data.costRisk) === null || _v === void 0 ? void 0 : _v.unexpectedCostVariance) === null || _w === void 0 ? void 0 : _w.toFixed(2)) !== null && _x !== void 0 ? _x : 0)),
3771
+ React.createElement("div", { style: {
3772
+ display: "flex",
3773
+ justifyContent: "space-between",
3774
+ padding: `${(theme === null || theme === void 0 ? void 0 : theme.spacing.xs) || "4px"} 0`,
3775
+ } },
3776
+ React.createElement("span", { style: { color: (theme === null || theme === void 0 ? void 0 : theme.colors.textSecondary) || "#666" } }, "Potential Savings:"),
3777
+ React.createElement("span", { style: {
3778
+ fontWeight: "600",
3779
+ color: (theme === null || theme === void 0 ? void 0 : theme.colors.success) || "#4caf50",
3780
+ } },
3781
+ "$", (_0 = (_z = (_y = data === null || data === void 0 ? void 0 : data.costRisk) === null || _y === void 0 ? void 0 : _y.potentialSavings) === null || _z === void 0 ? void 0 : _z.toFixed(2)) !== null && _0 !== void 0 ? _0 : 0)),
3782
+ React.createElement("div", { style: {
3783
+ display: "flex",
3784
+ justifyContent: "space-between",
3785
+ padding: `${(theme === null || theme === void 0 ? void 0 : theme.spacing.xs) || "4px"} 0`,
3786
+ } },
3787
+ React.createElement("span", { style: { color: (theme === null || theme === void 0 ? void 0 : theme.colors.textSecondary) || "#666" } }, "Volatility Index:"),
3788
+ React.createElement("span", { style: { fontWeight: "600" } }, (_3 = (_2 = (_1 = data === null || data === void 0 ? void 0 : data.costRisk) === null || _1 === void 0 ? void 0 : _1.costVolatilityIndex) === null || _2 === void 0 ? void 0 : _2.toFixed(2)) !== null && _3 !== void 0 ? _3 : 0,
3789
+ "%"))))),
3790
+ (data === null || data === void 0 ? void 0 : data.dataQualityIssues) && data.dataQualityIssues.length > 0 && (React.createElement("div", null,
3791
+ React.createElement(DataTable, { title: "Data Quality Issues", columns: tableColumns, data: data.dataQualityIssues.map((issue, idx) => (Object.assign({ id: idx }, issue))), pageSize: 5, theme: theme })))));
3792
+ };
3793
+
3794
+ /**
3795
+ * StatusBadge Component
3796
+ * Displays status with color-coded background
3797
+ */
3798
+ const getStatusConfig = (status, theme) => {
3799
+ const baseConfig = {
3800
+ ok: { label: "OK" },
3801
+ warning: { label: "Warning" },
3802
+ critical: { label: "Critical" },
3803
+ proposed: { label: "Proposed" },
3804
+ executed: { label: "Executed" },
3805
+ declined: { label: "Declined" },
3806
+ failed: { label: "Failed" },
3807
+ "auto-executed": { label: "Auto Executed" },
3808
+ };
3809
+ const config = baseConfig[status];
3810
+ if (theme) {
3811
+ const statusColors = {
3812
+ ok: { bg: "rgba(16, 185, 129, 0.15)", text: theme.colors.success },
3813
+ warning: { bg: "rgba(245, 158, 11, 0.15)", text: "#F59E0B" },
3814
+ critical: { bg: "rgba(239, 68, 68, 0.15)", text: theme.colors.error },
3815
+ proposed: { bg: "rgba(59, 130, 246, 0.15)", text: theme.colors.primary },
3816
+ executed: { bg: "rgba(16, 185, 129, 0.15)", text: theme.colors.success },
3817
+ declined: {
3818
+ bg: "rgba(156, 163, 175, 0.15)",
3819
+ text: theme.colors.textSecondary,
3820
+ },
3821
+ failed: { bg: "rgba(239, 68, 68, 0.15)", text: theme.colors.error },
3822
+ "auto-executed": {
3823
+ bg: "rgba(16, 185, 129, 0.15)",
3824
+ text: theme.colors.success,
3825
+ },
3826
+ };
3827
+ return {
3828
+ bg: statusColors[status].bg,
3829
+ text: statusColors[status].text,
3830
+ label: config.label,
3831
+ };
3832
+ }
3833
+ const defaultColors = {
3834
+ ok: { bg: "#D1FAE5", text: "#059669" },
3835
+ warning: { bg: "#FEF3C7", text: "#D97706" },
3836
+ critical: { bg: "#FEE2E2", text: "#DC2626" },
3837
+ proposed: { bg: "#DBEAFE", text: "#1D4ED8" },
3838
+ executed: { bg: "#D1FAE5", text: "#059669" },
3839
+ declined: { bg: "#E5E7EB", text: "#4B5563" },
3840
+ failed: { bg: "#FEE2E2", text: "#DC2626" },
3841
+ "auto-executed": { bg: "#D1FAE5", text: "#059669" },
3842
+ };
3843
+ return {
3844
+ bg: defaultColors[status].bg,
3845
+ text: defaultColors[status].text,
3846
+ label: config.label,
3847
+ };
3848
+ };
3849
+ const StatusBadge = ({ status, label, theme, }) => {
3850
+ const config = getStatusConfig(status, theme);
3851
+ return (React.createElement("span", { style: {
3852
+ display: "inline-flex",
3853
+ alignItems: "center",
3854
+ paddingLeft: "10px",
3855
+ paddingRight: "10px",
3856
+ paddingTop: "4px",
3857
+ paddingBottom: "4px",
3858
+ borderRadius: "4px",
3859
+ fontSize: "12px",
3860
+ fontWeight: "500",
3861
+ backgroundColor: config.bg,
3862
+ color: config.text,
3863
+ whiteSpace: "nowrap",
3864
+ } }, label || config.label));
3865
+ };
3866
+
3867
+ /**
3868
+ * Execution Audit Trail Report
3869
+ * Complete execution history and audit information
3870
+ */
3871
+ const ExecutionAuditTrail = ({ theme: themeProp, defaultDateRange = "past-month", }) => {
3872
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q;
3873
+ const { api, theme: contextTheme } = useReactBridgeContext();
3874
+ const theme = themeProp || contextTheme;
3875
+ const dateRange = useDateRange(defaultDateRange);
3876
+ const [directiveTypeFilter, setDirectiveTypeFilter] = useState("");
3877
+ const { data, loading, error } = useReportData(() => api.getExecutionAuditTrail({
3878
+ startDate: dateRange.startDate,
3879
+ endDate: dateRange.endDate,
3880
+ directiveType: directiveTypeFilter || undefined,
3881
+ }), [dateRange.startDate, dateRange.endDate, directiveTypeFilter]);
3882
+ const tableColumns = [
3883
+ {
3884
+ key: "directiveAction",
3885
+ label: "Directive Action",
3886
+ sortable: true,
3887
+ width: "200px",
3888
+ },
3889
+ {
3890
+ key: "status",
3891
+ label: "Status",
3892
+ sortable: true,
3893
+ render: (value) => React.createElement(StatusBadge, { status: value, theme: theme }),
3894
+ },
3895
+ {
3896
+ key: "executedAt",
3897
+ label: "Executed At",
3898
+ sortable: true,
3899
+ render: (value) => {
3900
+ try {
3901
+ return new Date(value).toLocaleString();
3902
+ }
3903
+ catch (_a) {
3904
+ return value;
3905
+ }
3906
+ },
3907
+ },
3908
+ {
3909
+ key: "executionDurationMinutes",
3910
+ label: "Duration (min)",
3911
+ sortable: true,
3912
+ },
3913
+ {
3914
+ key: "executedBy",
3915
+ label: "Executed By",
3916
+ sortable: true,
3917
+ },
3918
+ {
3919
+ key: "outcome",
3920
+ label: "Outcome",
3921
+ sortable: false,
3922
+ },
3923
+ ];
3924
+ return (React.createElement(ReportLayout, { title: "Execution Audit Trail", description: "Directive execution history and audit information", selectedDateRange: dateRange.selectedOption, onDateRangeChange: dateRange.setSelectedOption, loading: loading, error: error, theme: theme },
3925
+ React.createElement("div", { style: {
3926
+ display: "grid",
3927
+ gridTemplateColumns: "repeat(auto-fit, minmax(200px, 1fr))",
3928
+ gap: (theme === null || theme === void 0 ? void 0 : theme.spacing.md) || "16px",
3929
+ } },
3930
+ React.createElement(MetricCard, { label: "Total Directives", value: (_a = data === null || data === void 0 ? void 0 : data.totalDirectives) !== null && _a !== void 0 ? _a : 0, theme: theme }),
3931
+ React.createElement(MetricCard, { label: "Executed", value: (_b = data === null || data === void 0 ? void 0 : data.executedCount) !== null && _b !== void 0 ? _b : 0, theme: theme }),
3932
+ React.createElement(MetricCard, { label: "Declined", value: (_c = data === null || data === void 0 ? void 0 : data.declinedCount) !== null && _c !== void 0 ? _c : 0, theme: theme }),
3933
+ React.createElement(MetricCard, { label: "Failed", value: (_d = data === null || data === void 0 ? void 0 : data.failedCount) !== null && _d !== void 0 ? _d : 0, theme: theme }),
3934
+ React.createElement(MetricCard, { label: "Auto-Executed", value: (_e = data === null || data === void 0 ? void 0 : data.autoExecutedCount) !== null && _e !== void 0 ? _e : 0, theme: theme })),
3935
+ React.createElement("div", { style: {
3936
+ display: "grid",
3937
+ gridTemplateColumns: "repeat(auto-fit, minmax(200px, 1fr))",
3938
+ gap: (theme === null || theme === void 0 ? void 0 : theme.spacing.md) || "16px",
3939
+ } },
3940
+ React.createElement("div", { style: {
3941
+ padding: (theme === null || theme === void 0 ? void 0 : theme.spacing.md) || "16px",
3942
+ border: `1px solid ${(theme === null || theme === void 0 ? void 0 : theme.colors.border) || "#e0e0e0"}`,
3943
+ borderRadius: (theme === null || theme === void 0 ? void 0 : theme.borderRadius) || "8px",
3944
+ backgroundColor: (theme === null || theme === void 0 ? void 0 : theme.colors.surface) || "#f5f5f5",
3945
+ } },
3946
+ React.createElement("h4", { style: {
3947
+ margin: `0 0 ${(theme === null || theme === void 0 ? void 0 : theme.spacing.md) || "16px"} 0`,
3948
+ fontSize: (theme === null || theme === void 0 ? void 0 : theme.fontSizes.md) || "16px",
3949
+ fontWeight: "600",
3950
+ color: (theme === null || theme === void 0 ? void 0 : theme.colors.text) || "#000",
3951
+ } }, "Execution Statistics"),
3952
+ React.createElement("div", { style: {
3953
+ display: "flex",
3954
+ flexDirection: "column",
3955
+ gap: (theme === null || theme === void 0 ? void 0 : theme.spacing.sm) || "8px",
3956
+ } },
3957
+ React.createElement("div", { style: {
3958
+ display: "flex",
3959
+ justifyContent: "space-between",
3960
+ padding: `${(theme === null || theme === void 0 ? void 0 : theme.spacing.xs) || "4px"} 0`,
3961
+ } },
3962
+ React.createElement("span", { style: { color: (theme === null || theme === void 0 ? void 0 : theme.colors.textSecondary) || "#666" } }, "Avg. Duration:"),
3963
+ React.createElement("span", { style: { fontWeight: "600" } }, (_h = (_g = (_f = data === null || data === void 0 ? void 0 : data.stats) === null || _f === void 0 ? void 0 : _f.averageExecutionTimeMinutes) === null || _g === void 0 ? void 0 : _g.toFixed(1)) !== null && _h !== void 0 ? _h : 0,
3964
+ " min")),
3965
+ React.createElement("div", { style: {
3966
+ display: "flex",
3967
+ justifyContent: "space-between",
3968
+ padding: `${(theme === null || theme === void 0 ? void 0 : theme.spacing.xs) || "4px"} 0`,
3969
+ } },
3970
+ React.createElement("span", { style: { color: (theme === null || theme === void 0 ? void 0 : theme.colors.textSecondary) || "#666" } }, "Success Rate:"),
3971
+ React.createElement("span", { style: {
3972
+ fontWeight: "600",
3973
+ color: (theme === null || theme === void 0 ? void 0 : theme.colors.success) || "#4caf50",
3974
+ } }, (_l = (_k = (_j = data === null || data === void 0 ? void 0 : data.stats) === null || _j === void 0 ? void 0 : _j.successRate) === null || _k === void 0 ? void 0 : _k.toFixed(2)) !== null && _l !== void 0 ? _l : 0,
3975
+ "%")),
3976
+ React.createElement("div", { style: {
3977
+ display: "flex",
3978
+ justifyContent: "space-between",
3979
+ padding: `${(theme === null || theme === void 0 ? void 0 : theme.spacing.xs) || "4px"} 0`,
3980
+ } },
3981
+ React.createElement("span", { style: { color: (theme === null || theme === void 0 ? void 0 : theme.colors.textSecondary) || "#666" } }, "Fastest Execution:"),
3982
+ React.createElement("span", { style: { fontWeight: "600" } }, (_o = (_m = data === null || data === void 0 ? void 0 : data.stats) === null || _m === void 0 ? void 0 : _m.fastestExecutionMinutes) !== null && _o !== void 0 ? _o : 0,
3983
+ " min")),
3984
+ React.createElement("div", { style: {
3985
+ display: "flex",
3986
+ justifyContent: "space-between",
3987
+ padding: `${(theme === null || theme === void 0 ? void 0 : theme.spacing.xs) || "4px"} 0`,
3988
+ } },
3989
+ React.createElement("span", { style: { color: (theme === null || theme === void 0 ? void 0 : theme.colors.textSecondary) || "#666" } }, "Slowest Execution:"),
3990
+ React.createElement("span", { style: { fontWeight: "600" } }, (_q = (_p = data === null || data === void 0 ? void 0 : data.stats) === null || _p === void 0 ? void 0 : _p.slowestExecutionMinutes) !== null && _q !== void 0 ? _q : 0,
3991
+ " min"))))),
3992
+ (data === null || data === void 0 ? void 0 : data.executionHistory) && data.executionHistory.length > 0 && (React.createElement("div", null,
3993
+ React.createElement(DataTable, { title: "Execution History", columns: tableColumns, data: data.executionHistory.map((record, idx) => (Object.assign({ id: idx }, record))), pageSize: 10, theme: theme })))));
3994
+ };
3995
+
3996
+ /**
3997
+ * HealthGauge Component
3998
+ * Displays health/score on a 0-10 scale with color-coded circle
3999
+ */
4000
+ const HealthGauge = ({ score, label, size = "medium", theme, }) => {
4001
+ const getColor = () => {
4002
+ if (!theme) {
4003
+ if (score >= 8)
4004
+ return "#10B981";
4005
+ if (score >= 6)
4006
+ return "#F59E0B";
4007
+ return "#EF4444";
4008
+ }
4009
+ if (score >= 8)
4010
+ return theme.colors.success;
4011
+ if (score >= 6)
4012
+ return "#F59E0B"; // warning
4013
+ return theme.colors.error;
4014
+ };
4015
+ const getBackgroundColor = () => {
4016
+ if (!theme) {
4017
+ if (score >= 8)
4018
+ return "rgba(16, 185, 129, 0.1)";
4019
+ if (score >= 6)
4020
+ return "rgba(245, 158, 11, 0.1)";
4021
+ return "rgba(239, 68, 68, 0.1)";
4022
+ }
4023
+ if (score >= 8)
4024
+ return "rgba(16, 185, 129, 0.15)";
4025
+ if (score >= 6)
4026
+ return "rgba(245, 158, 11, 0.15)";
4027
+ return "rgba(239, 68, 68, 0.15)";
4028
+ };
4029
+ const sizeConfig = {
4030
+ small: { width: 64, height: 64, fontSize: "14px", labelSize: "11px" },
4031
+ medium: { width: 96, height: 96, fontSize: "24px", labelSize: "12px" },
4032
+ large: { width: 128, height: 128, fontSize: "32px", labelSize: "13px" },
4033
+ };
4034
+ const config = sizeConfig[size];
4035
+ return (React.createElement("div", { style: {
4036
+ display: "flex",
4037
+ flexDirection: "column",
4038
+ alignItems: "center",
4039
+ gap: (theme === null || theme === void 0 ? void 0 : theme.spacing.sm) || "8px",
4040
+ } },
4041
+ React.createElement("div", { style: {
4042
+ width: `${config.width}px`,
4043
+ height: `${config.height}px`,
4044
+ borderRadius: "50%",
4045
+ backgroundColor: getBackgroundColor(),
4046
+ display: "flex",
4047
+ alignItems: "center",
4048
+ justifyContent: "center",
4049
+ flex: "none",
4050
+ } },
4051
+ React.createElement("span", { style: {
4052
+ fontSize: config.fontSize,
4053
+ fontWeight: "bold",
4054
+ color: getColor(),
4055
+ } }, score.toFixed(1))),
4056
+ React.createElement("p", { style: {
4057
+ fontSize: config.labelSize,
4058
+ color: (theme === null || theme === void 0 ? void 0 : theme.colors.textSecondary) || "#666",
4059
+ textAlign: "center",
4060
+ margin: 0,
4061
+ maxWidth: `${config.width + 20}px`,
4062
+ } }, label)));
4063
+ };
4064
+
4065
+ /**
4066
+ * Portfolio Health Report
4067
+ * Aggregated metric health across the entire portfolio
4068
+ */
4069
+ const PortfolioHealth = ({ theme: themeProp, defaultDateRange = "past-month", }) => {
4070
+ var _a, _b, _c, _d;
4071
+ const { api, theme: contextTheme } = useReactBridgeContext();
4072
+ const theme = themeProp || contextTheme;
4073
+ const dateRange = useDateRange(defaultDateRange);
4074
+ const { data, loading, error } = useReportData(() => api.getPortfolioHealth({
4075
+ startDate: dateRange.startDate,
4076
+ endDate: dateRange.endDate,
4077
+ }), [dateRange.startDate, dateRange.endDate]);
4078
+ const metricTableColumns = [
4079
+ {
4080
+ key: "metricName",
4081
+ label: "Metric Name",
4082
+ sortable: true,
4083
+ },
4084
+ {
4085
+ key: "score",
4086
+ label: "Score (0-10)",
4087
+ sortable: true,
4088
+ render: (value) => value.toFixed(2),
4089
+ },
4090
+ {
4091
+ key: "status",
4092
+ label: "Status",
4093
+ sortable: true,
4094
+ render: (value) => {
4095
+ const color = value === "ok"
4096
+ ? theme === null || theme === void 0 ? void 0 : theme.colors.success
4097
+ : value === "warning"
4098
+ ? "#F59E0B"
4099
+ : theme === null || theme === void 0 ? void 0 : theme.colors.error;
4100
+ return (React.createElement("span", { style: { color, fontWeight: "600" } }, value.toUpperCase()));
4101
+ },
4102
+ },
4103
+ {
4104
+ key: "currentValue",
4105
+ label: "Current Value",
4106
+ sortable: true,
4107
+ render: (value) => value.toFixed(2),
4108
+ },
4109
+ {
4110
+ key: "targetValue",
4111
+ label: "Target Value",
4112
+ sortable: true,
4113
+ render: (value) => value.toFixed(2),
4114
+ },
4115
+ {
4116
+ key: "variance",
4117
+ label: "Variance",
4118
+ sortable: true,
4119
+ render: (value) => {
4120
+ const color = value > 0 ? theme === null || theme === void 0 ? void 0 : theme.colors.success : theme === null || theme === void 0 ? void 0 : theme.colors.error;
4121
+ return (React.createElement("span", { style: { color, fontWeight: "600" } }, value.toFixed(2)));
4122
+ },
4123
+ },
4124
+ ];
4125
+ const criticalTableColumns = [
4126
+ {
4127
+ key: "metricName",
4128
+ label: "Metric Name",
4129
+ sortable: true,
4130
+ },
4131
+ {
4132
+ key: "description",
4133
+ label: "Description",
4134
+ sortable: true,
4135
+ },
4136
+ {
4137
+ key: "recommendedAction",
4138
+ label: "Recommended Action",
4139
+ sortable: false,
4140
+ },
4141
+ ];
4142
+ return (React.createElement(ReportLayout, { title: "Portfolio Health", description: "Aggregated metric health and critical alerts", selectedDateRange: dateRange.selectedOption, onDateRangeChange: dateRange.setSelectedOption, loading: loading, error: error, theme: theme },
4143
+ React.createElement("div", { style: {
4144
+ display: "flex",
4145
+ justifyContent: "center",
4146
+ padding: (theme === null || theme === void 0 ? void 0 : theme.spacing.lg) || "24px",
4147
+ border: `1px solid ${(theme === null || theme === void 0 ? void 0 : theme.colors.border) || "#e0e0e0"}`,
4148
+ borderRadius: (theme === null || theme === void 0 ? void 0 : theme.borderRadius) || "8px",
4149
+ backgroundColor: (theme === null || theme === void 0 ? void 0 : theme.colors.surface) || "#f5f5f5",
4150
+ } },
4151
+ React.createElement(HealthGauge, { score: (_a = data === null || data === void 0 ? void 0 : data.overallHealthScore) !== null && _a !== void 0 ? _a : 0, label: "Overall Portfolio Health", size: "large", theme: theme })),
4152
+ React.createElement("div", { style: {
4153
+ display: "grid",
4154
+ gridTemplateColumns: "repeat(auto-fit, minmax(150px, 1fr))",
4155
+ gap: (theme === null || theme === void 0 ? void 0 : theme.spacing.md) || "16px",
4156
+ } },
4157
+ React.createElement("div", { style: {
4158
+ padding: (theme === null || theme === void 0 ? void 0 : theme.spacing.md) || "16px",
4159
+ border: `1px solid ${(theme === null || theme === void 0 ? void 0 : theme.colors.border) || "#e0e0e0"}`,
4160
+ borderRadius: (theme === null || theme === void 0 ? void 0 : theme.borderRadius) || "8px",
4161
+ backgroundColor: (theme === null || theme === void 0 ? void 0 : theme.colors.surface) || "#f5f5f5",
4162
+ textAlign: "center",
4163
+ } },
4164
+ React.createElement("p", { style: {
4165
+ margin: 0,
4166
+ fontSize: (theme === null || theme === void 0 ? void 0 : theme.fontSizes.sm) || "14px",
4167
+ color: (theme === null || theme === void 0 ? void 0 : theme.colors.textSecondary) || "#666",
4168
+ marginBottom: (theme === null || theme === void 0 ? void 0 : theme.spacing.xs) || "4px",
4169
+ } }, "Healthy Metrics"),
4170
+ React.createElement("p", { style: {
4171
+ margin: 0,
4172
+ fontSize: "24px",
4173
+ fontWeight: "bold",
4174
+ color: (theme === null || theme === void 0 ? void 0 : theme.colors.success) || "#4caf50",
4175
+ } }, (_b = data === null || data === void 0 ? void 0 : data.healthyMetricsCount) !== null && _b !== void 0 ? _b : 0)),
4176
+ React.createElement("div", { style: {
4177
+ padding: (theme === null || theme === void 0 ? void 0 : theme.spacing.md) || "16px",
4178
+ border: `1px solid ${(theme === null || theme === void 0 ? void 0 : theme.colors.border) || "#e0e0e0"}`,
4179
+ borderRadius: (theme === null || theme === void 0 ? void 0 : theme.borderRadius) || "8px",
4180
+ backgroundColor: (theme === null || theme === void 0 ? void 0 : theme.colors.surface) || "#f5f5f5",
4181
+ textAlign: "center",
4182
+ } },
4183
+ React.createElement("p", { style: {
4184
+ margin: 0,
4185
+ fontSize: (theme === null || theme === void 0 ? void 0 : theme.fontSizes.sm) || "14px",
4186
+ color: (theme === null || theme === void 0 ? void 0 : theme.colors.textSecondary) || "#666",
4187
+ marginBottom: (theme === null || theme === void 0 ? void 0 : theme.spacing.xs) || "4px",
4188
+ } }, "Warning Metrics"),
4189
+ React.createElement("p", { style: {
4190
+ margin: 0,
4191
+ fontSize: "24px",
4192
+ fontWeight: "bold",
4193
+ color: "#F59E0B",
4194
+ } }, (_c = data === null || data === void 0 ? void 0 : data.warningMetricsCount) !== null && _c !== void 0 ? _c : 0)),
4195
+ React.createElement("div", { style: {
4196
+ padding: (theme === null || theme === void 0 ? void 0 : theme.spacing.md) || "16px",
4197
+ border: `1px solid ${(theme === null || theme === void 0 ? void 0 : theme.colors.border) || "#e0e0e0"}`,
4198
+ borderRadius: (theme === null || theme === void 0 ? void 0 : theme.borderRadius) || "8px",
4199
+ backgroundColor: (theme === null || theme === void 0 ? void 0 : theme.colors.surface) || "#f5f5f5",
4200
+ textAlign: "center",
4201
+ } },
4202
+ React.createElement("p", { style: {
4203
+ margin: 0,
4204
+ fontSize: (theme === null || theme === void 0 ? void 0 : theme.fontSizes.sm) || "14px",
4205
+ color: (theme === null || theme === void 0 ? void 0 : theme.colors.textSecondary) || "#666",
4206
+ marginBottom: (theme === null || theme === void 0 ? void 0 : theme.spacing.xs) || "4px",
4207
+ } }, "Critical Metrics"),
4208
+ React.createElement("p", { style: {
4209
+ margin: 0,
4210
+ fontSize: "24px",
4211
+ fontWeight: "bold",
4212
+ color: (theme === null || theme === void 0 ? void 0 : theme.colors.error) || "#f44336",
4213
+ } }, (_d = data === null || data === void 0 ? void 0 : data.criticalMetricsCount) !== null && _d !== void 0 ? _d : 0))),
4214
+ (data === null || data === void 0 ? void 0 : data.metricHealthScores) && data.metricHealthScores.length > 0 && (React.createElement("div", null,
4215
+ React.createElement(DataTable, { title: "Metric Health Scores", columns: metricTableColumns, data: data.metricHealthScores.map((metric, idx) => (Object.assign({ id: idx }, metric))), pageSize: 10, theme: theme }))),
4216
+ (data === null || data === void 0 ? void 0 : data.criticalMetrics) && data.criticalMetrics.length > 0 && (React.createElement("div", null,
4217
+ React.createElement(DataTable, { title: "Critical Metrics Requiring Attention", columns: criticalTableColumns, data: data.criticalMetrics.map((metric, idx) => (Object.assign({ id: idx }, metric))), pageSize: 5, theme: theme })))));
4218
+ };
4219
+
4220
+ /**
4221
+ * Data Quality & Automation Report
4222
+ * Data gaps, automation opportunities, and actionable recommendations
4223
+ */
4224
+ const DataQualityAutomation = ({ theme: themeProp, defaultDateRange = "past-month", }) => {
4225
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p;
4226
+ const { api, theme: contextTheme } = useReactBridgeContext();
4227
+ const theme = themeProp || contextTheme;
4228
+ const dateRange = useDateRange(defaultDateRange);
4229
+ const { data, loading, error } = useReportData(() => api.getDataQualityAutomation({
4230
+ startDate: dateRange.startDate,
4231
+ endDate: dateRange.endDate,
4232
+ }), [dateRange.startDate, dateRange.endDate]);
4233
+ const dataGapColumns = [
4234
+ {
4235
+ key: "fieldName",
4236
+ label: "Field Name",
4237
+ sortable: true,
4238
+ },
4239
+ {
4240
+ key: "missingRecords",
4241
+ label: "Missing Records",
4242
+ sortable: true,
4243
+ },
4244
+ {
4245
+ key: "missingPercentage",
4246
+ label: "Missing %",
4247
+ sortable: true,
4248
+ render: (value) => `${value.toFixed(2)}%`,
4249
+ },
4250
+ {
4251
+ key: "impact",
4252
+ label: "Impact",
4253
+ sortable: false,
4254
+ },
4255
+ ];
4256
+ const recommendationColumns = [
4257
+ {
4258
+ key: "category",
4259
+ label: "Category",
4260
+ sortable: true,
4261
+ },
4262
+ {
4263
+ key: "recommendation",
4264
+ label: "Recommendation",
4265
+ sortable: true,
4266
+ },
4267
+ {
4268
+ key: "priority",
4269
+ label: "Priority",
4270
+ sortable: true,
4271
+ render: (value) => {
4272
+ const color = value === "High"
4273
+ ? theme === null || theme === void 0 ? void 0 : theme.colors.error
4274
+ : value === "Medium"
4275
+ ? "#F59E0B"
4276
+ : theme === null || theme === void 0 ? void 0 : theme.colors.success;
4277
+ return React.createElement("span", { style: { color, fontWeight: "600" } }, value);
4278
+ },
4279
+ },
4280
+ {
4281
+ key: "expectedBenefit",
4282
+ label: "Expected Benefit",
4283
+ sortable: false,
4284
+ },
4285
+ ];
4286
+ return (React.createElement(ReportLayout, { title: "Data Quality & Automation", description: "Data quality assessment and automation opportunities", selectedDateRange: dateRange.selectedOption, onDateRangeChange: dateRange.setSelectedOption, loading: loading, error: error, theme: theme },
4287
+ React.createElement("div", { style: {
4288
+ padding: (theme === null || theme === void 0 ? void 0 : theme.spacing.md) || "16px",
4289
+ border: `1px solid ${(theme === null || theme === void 0 ? void 0 : theme.colors.border) || "#e0e0e0"}`,
4290
+ borderRadius: (theme === null || theme === void 0 ? void 0 : theme.borderRadius) || "8px",
4291
+ backgroundColor: (theme === null || theme === void 0 ? void 0 : theme.colors.surface) || "#f5f5f5",
4292
+ } },
4293
+ React.createElement("h3", { style: {
4294
+ margin: `0 0 ${(theme === null || theme === void 0 ? void 0 : theme.spacing.md) || "16px"} 0`,
4295
+ fontSize: (theme === null || theme === void 0 ? void 0 : theme.fontSizes.lg) || "18px",
4296
+ fontWeight: "600",
4297
+ color: (theme === null || theme === void 0 ? void 0 : theme.colors.text) || "#000",
4298
+ } }, "Data Quality Assessment"),
4299
+ React.createElement("div", { style: {
4300
+ display: "flex",
4301
+ flexDirection: "column",
4302
+ gap: (theme === null || theme === void 0 ? void 0 : theme.spacing.md) || "16px",
4303
+ } },
4304
+ React.createElement(ProgressBar, { percentage: (_a = data === null || data === void 0 ? void 0 : data.overallDataQualityScore) !== null && _a !== void 0 ? _a : 0, label: "Overall Quality Score", theme: theme, height: "large" }),
4305
+ React.createElement(ProgressBar, { percentage: (_b = data === null || data === void 0 ? void 0 : data.completenessScore) !== null && _b !== void 0 ? _b : 0, label: "Completeness", theme: theme }),
4306
+ React.createElement(ProgressBar, { percentage: (_c = data === null || data === void 0 ? void 0 : data.accuracyScore) !== null && _c !== void 0 ? _c : 0, label: "Accuracy", theme: theme }),
4307
+ React.createElement(ProgressBar, { percentage: (_d = data === null || data === void 0 ? void 0 : data.consistencyScore) !== null && _d !== void 0 ? _d : 0, label: "Consistency", theme: theme })),
4308
+ React.createElement("div", { style: {
4309
+ display: "grid",
4310
+ gridTemplateColumns: "repeat(auto-fit, minmax(150px, 1fr))",
4311
+ gap: (theme === null || theme === void 0 ? void 0 : theme.spacing.md) || "16px",
4312
+ marginTop: (theme === null || theme === void 0 ? void 0 : theme.spacing.lg) || "24px",
4313
+ } },
4314
+ React.createElement("div", { style: {
4315
+ textAlign: "center",
4316
+ padding: (theme === null || theme === void 0 ? void 0 : theme.spacing.sm) || "8px",
4317
+ } },
4318
+ React.createElement("p", { style: {
4319
+ margin: 0,
4320
+ fontSize: (theme === null || theme === void 0 ? void 0 : theme.fontSizes.sm) || "14px",
4321
+ color: (theme === null || theme === void 0 ? void 0 : theme.colors.textSecondary) || "#666",
4322
+ } }, "Total Records Analyzed"),
4323
+ React.createElement("p", { style: {
4324
+ margin: `${(theme === null || theme === void 0 ? void 0 : theme.spacing.xs) || "4px"} 0 0 0`,
4325
+ fontSize: "20px",
4326
+ fontWeight: "600",
4327
+ color: (theme === null || theme === void 0 ? void 0 : theme.colors.text) || "#000",
4328
+ } }, (_e = data === null || data === void 0 ? void 0 : data.totalRecordsAnalyzed) !== null && _e !== void 0 ? _e : 0)),
4329
+ React.createElement("div", { style: {
4330
+ textAlign: "center",
4331
+ padding: (theme === null || theme === void 0 ? void 0 : theme.spacing.sm) || "8px",
4332
+ } },
4333
+ React.createElement("p", { style: {
4334
+ margin: 0,
4335
+ fontSize: (theme === null || theme === void 0 ? void 0 : theme.fontSizes.sm) || "14px",
4336
+ color: (theme === null || theme === void 0 ? void 0 : theme.colors.textSecondary) || "#666",
4337
+ } }, "Records with Issues"),
4338
+ React.createElement("p", { style: {
4339
+ margin: `${(theme === null || theme === void 0 ? void 0 : theme.spacing.xs) || "4px"} 0 0 0`,
4340
+ fontSize: "20px",
4341
+ fontWeight: "600",
4342
+ color: (theme === null || theme === void 0 ? void 0 : theme.colors.error) || "#f44336",
4343
+ } }, (_f = data === null || data === void 0 ? void 0 : data.recordsWithIssues) !== null && _f !== void 0 ? _f : 0)))),
4344
+ React.createElement("div", { style: {
4345
+ display: "grid",
4346
+ gridTemplateColumns: "repeat(auto-fit, minmax(200px, 1fr))",
4347
+ gap: (theme === null || theme === void 0 ? void 0 : theme.spacing.md) || "16px",
4348
+ } },
4349
+ React.createElement("div", { style: {
4350
+ padding: (theme === null || theme === void 0 ? void 0 : theme.spacing.md) || "16px",
4351
+ border: `1px solid ${(theme === null || theme === void 0 ? void 0 : theme.colors.border) || "#e0e0e0"}`,
4352
+ borderRadius: (theme === null || theme === void 0 ? void 0 : theme.borderRadius) || "8px",
4353
+ backgroundColor: (theme === null || theme === void 0 ? void 0 : theme.colors.surface) || "#f5f5f5",
4354
+ } },
4355
+ React.createElement("h4", { style: {
4356
+ margin: `0 0 ${(theme === null || theme === void 0 ? void 0 : theme.spacing.md) || "16px"} 0`,
4357
+ fontSize: (theme === null || theme === void 0 ? void 0 : theme.fontSizes.md) || "16px",
4358
+ fontWeight: "600",
4359
+ color: (theme === null || theme === void 0 ? void 0 : theme.colors.text) || "#000",
4360
+ } }, "Automation Readiness"),
4361
+ React.createElement("div", { style: {
4362
+ marginBottom: (theme === null || theme === void 0 ? void 0 : theme.spacing.md) || "16px",
4363
+ } },
4364
+ React.createElement(ProgressBar, { percentage: (_h = (_g = data === null || data === void 0 ? void 0 : data.automationOpportunities) === null || _g === void 0 ? void 0 : _g.automationReadinessScore) !== null && _h !== void 0 ? _h : 0, label: "Readiness Score", theme: theme, height: "large" })),
4365
+ React.createElement("div", { style: {
4366
+ display: "flex",
4367
+ flexDirection: "column",
4368
+ gap: (theme === null || theme === void 0 ? void 0 : theme.spacing.sm) || "8px",
4369
+ } },
4370
+ React.createElement("div", { style: {
4371
+ display: "flex",
4372
+ justifyContent: "space-between",
4373
+ padding: `${(theme === null || theme === void 0 ? void 0 : theme.spacing.xs) || "4px"} 0`,
4374
+ } },
4375
+ React.createElement("span", { style: { color: (theme === null || theme === void 0 ? void 0 : theme.colors.textSecondary) || "#666" } }, "Fully Automatable:"),
4376
+ React.createElement("span", { style: { fontWeight: "600" } }, (_k = (_j = data === null || data === void 0 ? void 0 : data.automationOpportunities) === null || _j === void 0 ? void 0 : _j.fullyAutomatable) !== null && _k !== void 0 ? _k : 0)),
4377
+ React.createElement("div", { style: {
4378
+ display: "flex",
4379
+ justifyContent: "space-between",
4380
+ padding: `${(theme === null || theme === void 0 ? void 0 : theme.spacing.xs) || "4px"} 0`,
4381
+ } },
4382
+ React.createElement("span", { style: { color: (theme === null || theme === void 0 ? void 0 : theme.colors.textSecondary) || "#666" } }, "Partially Automatable:"),
4383
+ React.createElement("span", { style: { fontWeight: "600" } }, (_m = (_l = data === null || data === void 0 ? void 0 : data.automationOpportunities) === null || _l === void 0 ? void 0 : _l.partiallyAutomatable) !== null && _m !== void 0 ? _m : 0)),
4384
+ React.createElement("div", { style: {
4385
+ display: "flex",
4386
+ justifyContent: "space-between",
4387
+ padding: `${(theme === null || theme === void 0 ? void 0 : theme.spacing.xs) || "4px"} 0`,
4388
+ } },
4389
+ React.createElement("span", { style: { color: (theme === null || theme === void 0 ? void 0 : theme.colors.textSecondary) || "#666" } }, "Manual Only:"),
4390
+ React.createElement("span", { style: { fontWeight: "600" } }, (_p = (_o = data === null || data === void 0 ? void 0 : data.automationOpportunities) === null || _o === void 0 ? void 0 : _o.manualOnly) !== null && _p !== void 0 ? _p : 0))))),
4391
+ (data === null || data === void 0 ? void 0 : data.identifiedDataGaps) && data.identifiedDataGaps.length > 0 && (React.createElement("div", null,
4392
+ React.createElement(DataTable, { title: "Identified Data Gaps", columns: dataGapColumns, data: data.identifiedDataGaps.map((gap, idx) => (Object.assign({ id: idx }, gap))), pageSize: 10, theme: theme }))),
4393
+ (data === null || data === void 0 ? void 0 : data.recommendations) && data.recommendations.length > 0 && (React.createElement("div", null,
4394
+ React.createElement(DataTable, { title: "Recommendations", columns: recommendationColumns, data: data.recommendations.map((rec, idx) => (Object.assign({ id: idx }, rec))), pageSize: 10, theme: theme })))));
4395
+ };
4396
+
4397
+ /**
4398
+ * Reports Dashboard
4399
+ * Main container that displays all 5 reports with navigation
4400
+ */
4401
+ const REPORTS = [
4402
+ {
4403
+ id: "executive",
4404
+ label: "Executive Dashboard",
4405
+ icon: "📊",
4406
+ description: "High-level directive execution metrics",
4407
+ },
4408
+ {
4409
+ id: "risk",
4410
+ label: "Supply Chain Risk",
4411
+ icon: "⚠️",
4412
+ description: "Risk analysis and supply chain health",
4413
+ },
4414
+ {
4415
+ id: "audit",
4416
+ label: "Execution Audit",
4417
+ icon: "✓",
4418
+ description: "Directive execution history and audit trail",
4419
+ },
4420
+ {
4421
+ id: "health",
4422
+ label: "Portfolio Health",
4423
+ icon: "❤️",
4424
+ description: "Portfolio metric health and critical alerts",
4425
+ },
4426
+ {
4427
+ id: "quality",
4428
+ label: "Data Quality",
4429
+ icon: "📈",
4430
+ description: "Data quality and automation assessment",
4431
+ },
4432
+ ];
4433
+ const ReportsDashboard = ({ theme, initialReport = "executive", }) => {
4434
+ const [activeReport, setActiveReport] = useState(initialReport);
4435
+ const containerStyle = {
4436
+ minHeight: "100vh",
4437
+ backgroundColor: (theme === null || theme === void 0 ? void 0 : theme.colors.background) || "#fff",
4438
+ color: (theme === null || theme === void 0 ? void 0 : theme.colors.text) || "#000",
4439
+ };
4440
+ const navContainerStyle = {
4441
+ borderBottom: `1px solid ${(theme === null || theme === void 0 ? void 0 : theme.colors.border) || "#e0e0e0"}`,
4442
+ backgroundColor: (theme === null || theme === void 0 ? void 0 : theme.colors.surface) || "#f5f5f5",
4443
+ };
4444
+ const navWrapperStyle = {
4445
+ maxWidth: "1400px",
4446
+ margin: "0 auto",
4447
+ padding: `${(theme === null || theme === void 0 ? void 0 : theme.spacing.md) || "16px"} ${(theme === null || theme === void 0 ? void 0 : theme.spacing.lg) || "24px"}`,
4448
+ display: "flex",
4449
+ gap: (theme === null || theme === void 0 ? void 0 : theme.spacing.md) || "16px",
4450
+ overflowX: "auto",
4451
+ scrollBehavior: "smooth",
4452
+ };
4453
+ const navButtonStyle = (isActive) => ({
4454
+ padding: `${(theme === null || theme === void 0 ? void 0 : theme.spacing.sm) || "8px"} ${(theme === null || theme === void 0 ? void 0 : theme.spacing.md) || "16px"}`,
4455
+ fontSize: (theme === null || theme === void 0 ? void 0 : theme.fontSizes.sm) || "14px",
4456
+ fontWeight: "500",
4457
+ borderRadius: (theme === null || theme === void 0 ? void 0 : theme.borderRadius) || "8px",
4458
+ border: "none",
4459
+ cursor: "pointer",
4460
+ transition: "all 0.2s ease",
4461
+ backgroundColor: isActive
4462
+ ? (theme === null || theme === void 0 ? void 0 : theme.colors.primary) || "#1976d2"
4463
+ : (theme === null || theme === void 0 ? void 0 : theme.colors.background) || "#fff",
4464
+ color: isActive ? "#fff" : (theme === null || theme === void 0 ? void 0 : theme.colors.text) || "#000",
4465
+ whiteSpace: "nowrap",
4466
+ display: "flex",
4467
+ alignItems: "center",
4468
+ gap: (theme === null || theme === void 0 ? void 0 : theme.spacing.xs) || "4px",
4469
+ });
4470
+ const contentStyle = {
4471
+ maxWidth: "1400px",
4472
+ margin: "0 auto",
4473
+ padding: (theme === null || theme === void 0 ? void 0 : theme.spacing.lg) || "24px",
4474
+ };
4475
+ return (React.createElement("div", { style: containerStyle },
4476
+ React.createElement("div", { style: navContainerStyle },
4477
+ React.createElement("div", { style: navWrapperStyle }, REPORTS.map((report) => (React.createElement("button", { key: report.id, onClick: () => setActiveReport(report.id), style: navButtonStyle(activeReport === report.id), title: report.description },
4478
+ React.createElement("span", null, report.icon),
4479
+ React.createElement("span", null, report.label)))))),
4480
+ React.createElement("div", { style: contentStyle },
4481
+ activeReport === "executive" && React.createElement(ExecutiveDashboard, { theme: theme }),
4482
+ activeReport === "risk" && React.createElement(SupplyChainRisk, { theme: theme }),
4483
+ activeReport === "audit" && React.createElement(ExecutionAuditTrail, { theme: theme }),
4484
+ activeReport === "health" && React.createElement(PortfolioHealth, { theme: theme }),
4485
+ activeReport === "quality" && React.createElement(DataQualityAutomation, { theme: theme }))));
4486
+ };
4487
+
4488
+ /**
4489
+ * RiskMatrix Component
4490
+ * 2D visualization of risk items (probability vs impact)
4491
+ */
4492
+ const RiskMatrix = ({ items, title, height = 300, theme, }) => {
4493
+ if (!items || items.length === 0) {
4494
+ return (React.createElement("div", { style: {
4495
+ padding: (theme === null || theme === void 0 ? void 0 : theme.spacing.lg) || "24px",
4496
+ textAlign: "center",
4497
+ color: (theme === null || theme === void 0 ? void 0 : theme.colors.textSecondary) || "#666",
4498
+ } }, "No risk data available"));
4499
+ }
4500
+ const padding = 50;
4501
+ const width = 500;
4502
+ const innerWidth = width - padding * 2;
4503
+ const innerHeight = height - padding * 2;
4504
+ const getRiskColor = (severity) => {
4505
+ if (severity === "high")
4506
+ return (theme === null || theme === void 0 ? void 0 : theme.colors.error) || "#ef4444";
4507
+ if (severity === "medium")
4508
+ return "#F59E0B";
4509
+ return (theme === null || theme === void 0 ? void 0 : theme.colors.success) || "#10B981";
4510
+ };
4511
+ return (React.createElement("div", null,
4512
+ title && (React.createElement("h3", { style: {
4513
+ margin: `0 0 ${(theme === null || theme === void 0 ? void 0 : theme.spacing.md) || "16px"} 0`,
4514
+ fontSize: (theme === null || theme === void 0 ? void 0 : theme.fontSizes.md) || "16px",
4515
+ fontWeight: "600",
4516
+ color: (theme === null || theme === void 0 ? void 0 : theme.colors.text) || "#000",
4517
+ } }, title)),
4518
+ React.createElement("svg", { width: "100%", height: height, viewBox: `0 0 ${width} ${height}`, preserveAspectRatio: "xMidYMid meet", style: {
4519
+ border: `1px solid ${(theme === null || theme === void 0 ? void 0 : theme.colors.border) || "#e0e0e0"}`,
4520
+ borderRadius: "8px",
4521
+ } },
4522
+ React.createElement("rect", { x: padding + innerWidth / 2, y: padding, width: innerWidth / 2, height: innerHeight / 2, fill: "#ef4444", opacity: "0.05" }),
4523
+ React.createElement("rect", { x: padding, y: padding, width: innerWidth / 2, height: innerHeight / 2, fill: "#F59E0B", opacity: "0.05" }),
4524
+ React.createElement("rect", { x: padding + innerWidth / 2, y: padding + innerHeight / 2, width: innerWidth / 2, height: innerHeight / 2, fill: "#F59E0B", opacity: "0.05" }),
4525
+ React.createElement("rect", { x: padding, y: padding + innerHeight / 2, width: innerWidth / 2, height: innerHeight / 2, fill: "#10B981", opacity: "0.05" }),
4526
+ React.createElement("line", { x1: padding, y1: padding + innerHeight / 2, x2: width - padding, y2: padding + innerHeight / 2, stroke: (theme === null || theme === void 0 ? void 0 : theme.colors.border) || "#e0e0e0", strokeWidth: "2" }),
4527
+ React.createElement("line", { x1: padding + innerWidth / 2, y1: padding, x2: padding + innerWidth / 2, y2: height - padding, stroke: (theme === null || theme === void 0 ? void 0 : theme.colors.border) || "#e0e0e0", strokeWidth: "2" }),
4528
+ React.createElement("text", { x: width / 2, y: height - 5, textAnchor: "middle", fontSize: "12", fill: (theme === null || theme === void 0 ? void 0 : theme.colors.textSecondary) || "#666", fontWeight: "500" }, "Probability"),
4529
+ React.createElement("text", { x: 15, y: height / 2, textAnchor: "middle", fontSize: "12", fill: (theme === null || theme === void 0 ? void 0 : theme.colors.textSecondary) || "#666", fontWeight: "500", transform: `rotate(-90 15 ${height / 2})` }, "Impact"),
4530
+ items.map((item) => {
4531
+ const x = padding + (item.probability / 100) * innerWidth;
4532
+ const y = padding + innerHeight - (item.impact / 100) * innerHeight;
4533
+ return (React.createElement("g", { key: item.id },
4534
+ React.createElement("circle", { cx: x, cy: y, r: "6", fill: getRiskColor(item.severity), opacity: "0.7", style: { cursor: "pointer" } }),
4535
+ React.createElement("circle", { cx: x, cy: y, r: "6", fill: "none", stroke: getRiskColor(item.severity), strokeWidth: "2", opacity: "0.4" })));
4536
+ }))));
4537
+ };
4538
+
4539
+ export { AnalyticsAPI, AnalyticsDashboard, AnalyticsReport, AnalyticsWidget, DataQualityAutomation, DataTable, DateRangeSelector, DateRangeService, DirectivesPanel, ExecutionAuditTrail, ExecutiveDashboard, HealthGauge, LoadingState, MetricCard, MetricsPanel, ObservationsPanel, PortfolioHealth, ProgressBar, ReactBridgeAPI, ReactBridgeChatbox, ReactBridgeProvider, ReactBridgeSearch, ReportLayout, ReportsDashboard, RiskMatrix, StatusBadge, SupplyChainRisk, TrendChart, WebSpeechSTTProvider, WebSpeechTTSProvider, createCustomTheme, darkTheme, getTheme, lightTheme, useAnalyticsConfigs, useAnalyticsResult, useDateRange, useDirectiveAction, useReactBridge, useReactBridgeContext, useReportData };
2591
4540
  //# sourceMappingURL=index.esm.js.map