reactbridge-sdk 0.2.3 → 0.2.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -10,6 +10,7 @@ A flexible React SDK for building intelligent conversational interfaces with LLM
10
10
  🤖 **Intelligent Context** - Automatic context diffing and injection
11
11
  ⚡ **Two-Step Orchestration** - Seamless action execution and feedback loop
12
12
  📦 **TypeScript First** - Full type safety and IntelliSense support
13
+ 📈 **Analytics Admin UI** - Widgets, reports, and dashboards for AI-generated insights
13
14
 
14
15
  ## Installation
15
16
 
@@ -187,6 +188,83 @@ function CustomChat() {
187
188
  }
188
189
  ```
189
190
 
191
+ ## Analytics Suite
192
+
193
+ The SDK ships with DirectivSys analytics components for visualizing AI-generated metrics, observations, and directives and for executing recommended actions.
194
+
195
+ ### Components
196
+
197
+ - `AnalyticsWidget` — Floating entry point that opens a drawer of analytics configs; best for adding analytics everywhere in your admin UI.
198
+ - `AnalyticsReport` — Full report view for a single `analyticsType` (metrics, observations, directives) with optional back/close controls.
199
+ - `AnalyticsDashboard` — Full-width dashboard that lists all analytics configs on the left and shows the selected report on the right. Supports manual refresh, optional `autoRefreshInterval`, and directive status filtering.
200
+
201
+ ```tsx
202
+ import {
203
+ ReactBridgeProvider,
204
+ AnalyticsWidget,
205
+ AnalyticsReport,
206
+ AnalyticsDashboard,
207
+ } from 'reactbridge-sdk';
208
+
209
+ const handleDirectiveAction = async (directive, action) => {
210
+ if (action === 'decline') return { success: true };
211
+
212
+ // Execute the directive in your system
213
+ const result = await api.executeDirective(directive);
214
+ return { success: result.ok, error: result.error };
215
+ };
216
+
217
+ function Admin() {
218
+ return (
219
+ <ReactBridgeProvider apiKey="your-api-key">
220
+ <AnalyticsWidget onDirectiveAction={handleDirectiveAction} />
221
+
222
+ <AnalyticsReport
223
+ analyticsType="InventoryHealth"
224
+ onDirectiveAction={handleDirectiveAction}
225
+ />
226
+
227
+ <AnalyticsDashboard
228
+ onDirectiveAction={handleDirectiveAction}
229
+ autoRefreshInterval={300}
230
+ />
231
+ </ReactBridgeProvider>
232
+ );
233
+ }
234
+ ```
235
+
236
+ **Directive actions:** The callback receives the directive plus the requested action (`execute` or `decline`) and should return `{ success: boolean, error?: string }`. On success, directive status becomes `executed`; failures become `failed`; declines become `declined`. Directive statuses are `proposed`, `executed`, `declined`, and `failed`. Priorities are numeric (higher = more urgent).
237
+
238
+ ### Analytics Hooks
239
+
240
+ - `useAnalyticsConfigs()` — Fetches all analytics configs (`configs`, `isLoading`, `error`, `refetch`).
241
+ - `useAnalyticsResult(analyticsType)` — Fetches the latest result for a given analytics type (`result`, `isLoading`, `error`, `refetch`).
242
+ - `useDirectiveAction(onDirectiveAction?)` — Wraps your handler, updates directive status in the backend, and exposes `handleAction`, `isProcessing`, and `error`.
243
+
244
+ ```tsx
245
+ import { useAnalyticsConfigs, useAnalyticsResult, useDirectiveAction } from 'reactbridge-sdk';
246
+
247
+ const { configs } = useAnalyticsConfigs();
248
+ const { result, refetch } = useAnalyticsResult('InventoryHealth');
249
+ const { handleAction, isProcessing } = useDirectiveAction(handleDirectiveAction);
250
+ ```
251
+
252
+ ### Analytics API Client
253
+
254
+ ```tsx
255
+ import { AnalyticsAPI } from 'reactbridge-sdk';
256
+
257
+ const api = new AnalyticsAPI({ apiKey: 'your-api-key' });
258
+ const configs = await api.getConfigs();
259
+ const result = await api.getLatestResult('InventoryHealth');
260
+ await api.updateDirectiveStatus(directiveId, 'executed');
261
+ ```
262
+
263
+ ### More Docs
264
+
265
+ - Detailed components and hooks: [ANALYTICS_README.md](ANALYTICS_README.md)
266
+ - Full dashboard guide: [ANALYTICS_DASHBOARD_README.md](ANALYTICS_DASHBOARD_README.md)
267
+
190
268
  ## Voice Input/Output
191
269
 
192
270
  The SDK supports voice input (Speech-to-Text) and voice output (Text-to-Speech) for a fully conversational experience.
@@ -1,6 +1,6 @@
1
- import React from 'react';
2
- import type { DirectiveActionCallback } from '../../types/analytics';
3
- import type { Theme } from '../../types';
1
+ import React from "react";
2
+ import type { DirectiveActionCallback } from "../../types/analytics";
3
+ import type { Theme } from "../../types";
4
4
  export interface AnalyticsDashboardProps {
5
5
  onDirectiveAction: DirectiveActionCallback;
6
6
  className?: string;
@@ -1 +1 @@
1
- {"version":3,"file":"AnalyticsDashboard.d.ts","sourceRoot":"","sources":["../../../src/components/analytics/AnalyticsDashboard.tsx"],"names":[],"mappings":"AAAA,OAAO,KAA8B,MAAM,OAAO,CAAC;AAKnD,OAAO,KAAK,EAAsB,uBAAuB,EAAE,MAAM,uBAAuB,CAAC;AACzF,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,aAAa,CAAC;AAEzC,MAAM,WAAW,uBAAuB;IACtC,iBAAiB,EAAE,uBAAuB,CAAC;IAC3C,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,KAAK,CAAC,EAAE,KAAK,CAAC;CACf;AAED,wBAAgB,kBAAkB,CAAC,EACjC,iBAAiB,EACjB,SAAc,EACd,WAAkB,EAClB,mBAAuB,EACvB,KAAK,EAAE,WAAW,GACnB,EAAE,uBAAuB,qBAygBzB"}
1
+ {"version":3,"file":"AnalyticsDashboard.d.ts","sourceRoot":"","sources":["../../../src/components/analytics/AnalyticsDashboard.tsx"],"names":[],"mappings":"AAAA,OAAO,KAA8B,MAAM,OAAO,CAAC;AAKnD,OAAO,KAAK,EAEV,uBAAuB,EACxB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,aAAa,CAAC;AAEzC,MAAM,WAAW,uBAAuB;IACtC,iBAAiB,EAAE,uBAAuB,CAAC;IAC3C,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,KAAK,CAAC,EAAE,KAAK,CAAC;CACf;AAED,wBAAgB,kBAAkB,CAAC,EACjC,iBAAiB,EACjB,SAAc,EACd,WAAkB,EAClB,mBAAuB,EACvB,KAAK,EAAE,WAAW,GACnB,EAAE,uBAAuB,qBAwwBzB"}
package/dist/index.esm.js CHANGED
@@ -2151,17 +2151,18 @@ const AnalyticsWidget = ({ position = 'bottom-right', theme: customTheme, onDire
2151
2151
  isOpen && (React.createElement(AnalyticsDrawer, { isOpen: isOpen, onClose: () => setIsOpen(false), configs: configs, isLoading: isLoading, theme: theme, onDirectiveAction: onDirectiveAction }))));
2152
2152
  };
2153
2153
 
2154
- function AnalyticsDashboard({ onDirectiveAction, className = '', showRefresh = true, autoRefreshInterval = 0, theme: customTheme, }) {
2154
+ function AnalyticsDashboard({ onDirectiveAction, className = "", showRefresh = true, autoRefreshInterval = 0, theme: customTheme, }) {
2155
2155
  const { theme: contextTheme } = useReactBridgeContext();
2156
2156
  const theme = customTheme || contextTheme;
2157
2157
  const [selectedAnalytics, setSelectedAnalytics] = useState(null);
2158
- const [directiveFilter, setDirectiveFilter] = useState('all');
2158
+ const [directiveFilter, setDirectiveFilter] = useState("all");
2159
2159
  // Fetch analytics configurations
2160
2160
  const { configs, isLoading: configsLoading, error: configsError, refetch: refetchConfigs, } = useAnalyticsConfigs();
2161
2161
  // Fetch latest result for selected analytics
2162
2162
  const { result, isLoading: resultLoading, error: resultError, refetch: refetchResult, } = useAnalyticsResult(selectedAnalytics);
2163
2163
  // Handle directive actions
2164
2164
  const { handleAction, isProcessing } = useDirectiveAction(onDirectiveAction);
2165
+ const [processingId, setProcessingId] = useState(null);
2165
2166
  // Auto-select first analytics if none selected
2166
2167
  useEffect(() => {
2167
2168
  if (configs && configs.length > 0 && !selectedAnalytics) {
@@ -2187,24 +2188,26 @@ function AnalyticsDashboard({ onDirectiveAction, className = '', showRefresh = t
2187
2188
  }
2188
2189
  };
2189
2190
  const handleDirectiveAction = (directive, action) => __awaiter(this, void 0, void 0, function* () {
2191
+ setProcessingId(directive.directiveId);
2190
2192
  yield handleAction(directive, action);
2193
+ setProcessingId(null);
2191
2194
  // Refetch result to get updated directive statuses
2192
2195
  refetchResult();
2193
2196
  });
2194
- const filteredDirectives = (result === null || result === void 0 ? void 0 : result.directives.filter(d => {
2195
- if (directiveFilter === 'all')
2197
+ const filteredDirectives = (result === null || result === void 0 ? void 0 : result.directives.filter((d) => {
2198
+ if (directiveFilter === "all")
2196
2199
  return true;
2197
2200
  return d.status === directiveFilter;
2198
2201
  })) || [];
2199
- const selectedConfig = configs === null || configs === void 0 ? void 0 : configs.find(c => c.analyticsType === selectedAnalytics);
2200
- const proposedCount = (result === null || result === void 0 ? void 0 : result.directives.filter(d => d.status === 'proposed').length) || 0;
2201
- const executedCount = (result === null || result === void 0 ? void 0 : result.directives.filter(d => d.status === 'executed').length) || 0;
2202
- const declinedCount = (result === null || result === void 0 ? void 0 : result.directives.filter(d => d.status === 'declined').length) || 0;
2202
+ const selectedConfig = configs === null || configs === void 0 ? void 0 : configs.find((c) => c.analyticsType === selectedAnalytics);
2203
+ const proposedCount = (result === null || result === void 0 ? void 0 : result.directives.filter((d) => d.status === "proposed").length) || 0;
2204
+ const executedCount = (result === null || result === void 0 ? void 0 : result.directives.filter((d) => d.status === "executed").length) || 0;
2205
+ const declinedCount = (result === null || result === void 0 ? void 0 : result.directives.filter((d) => d.status === "declined").length) || 0;
2203
2206
  const containerStyle = {
2204
- display: 'flex',
2207
+ display: "flex",
2205
2208
  gap: theme.spacing.lg,
2206
- width: '100%',
2207
- minHeight: '540px',
2209
+ width: "100%",
2210
+ minHeight: "540px",
2208
2211
  backgroundColor: theme.colors.background,
2209
2212
  color: theme.colors.text,
2210
2213
  border: `1px solid ${theme.colors.border}`,
@@ -2213,44 +2216,44 @@ function AnalyticsDashboard({ onDirectiveAction, className = '', showRefresh = t
2213
2216
  padding: theme.spacing.lg,
2214
2217
  };
2215
2218
  const sidebarStyle = {
2216
- width: '320px',
2219
+ width: "320px",
2217
2220
  borderRight: `1px solid ${theme.colors.border}`,
2218
2221
  paddingRight: theme.spacing.lg,
2219
- display: 'flex',
2220
- flexDirection: 'column',
2222
+ display: "flex",
2223
+ flexDirection: "column",
2221
2224
  gap: theme.spacing.sm,
2222
2225
  };
2223
2226
  const listItemStyle = (isActive, isDisabled) => ({
2224
- width: '100%',
2225
- textAlign: 'left',
2227
+ width: "100%",
2228
+ textAlign: "left",
2226
2229
  padding: theme.spacing.md,
2227
2230
  backgroundColor: isActive ? theme.colors.primary : theme.colors.surface,
2228
- color: isActive ? '#fff' : theme.colors.text,
2231
+ color: isActive ? "#fff" : theme.colors.text,
2229
2232
  border: `1px solid ${isActive ? theme.colors.primary : theme.colors.border}`,
2230
2233
  borderRadius: theme.borderRadius,
2231
- cursor: isDisabled ? 'not-allowed' : 'pointer',
2234
+ cursor: isDisabled ? "not-allowed" : "pointer",
2232
2235
  opacity: isDisabled ? 0.6 : 1,
2233
- transition: 'transform 0.15s ease, box-shadow 0.15s ease',
2234
- boxShadow: isActive ? theme.boxShadow : 'none',
2236
+ transition: "transform 0.15s ease, box-shadow 0.15s ease",
2237
+ boxShadow: isActive ? theme.boxShadow : "none",
2235
2238
  });
2236
2239
  const pillStyle = (bg) => ({
2237
2240
  fontSize: theme.fontSizes.xs,
2238
- padding: '2px 8px',
2239
- borderRadius: '999px',
2241
+ padding: "2px 8px",
2242
+ borderRadius: "999px",
2240
2243
  backgroundColor: bg,
2241
- color: '#fff',
2244
+ color: "#fff",
2242
2245
  fontWeight: 600,
2243
2246
  });
2244
2247
  const placeholderStyle = {
2245
2248
  flex: 1,
2246
- minHeight: '420px',
2247
- display: 'flex',
2248
- flexDirection: 'column',
2249
- alignItems: 'center',
2250
- justifyContent: 'center',
2249
+ minHeight: "420px",
2250
+ display: "flex",
2251
+ flexDirection: "column",
2252
+ alignItems: "center",
2253
+ justifyContent: "center",
2251
2254
  gap: theme.spacing.sm,
2252
2255
  color: theme.colors.textSecondary,
2253
- textAlign: 'center',
2256
+ textAlign: "center",
2254
2257
  };
2255
2258
  const cardStyle = {
2256
2259
  backgroundColor: theme.colors.surface,
@@ -2260,35 +2263,42 @@ function AnalyticsDashboard({ onDirectiveAction, className = '', showRefresh = t
2260
2263
  };
2261
2264
  const statusBadgeStyle = (status) => {
2262
2265
  const colors = {
2263
- proposed: { bg: theme.colors.primary, text: '#fff' },
2264
- executed: { bg: theme.colors.success, text: '#fff' },
2265
- declined: { bg: theme.colors.error, text: '#fff' },
2266
- ok: { bg: '#d1fae5', text: '#065f46' },
2267
- warning: { bg: '#fef3c7', text: '#92400e' },
2268
- critical: { bg: '#fee2e2', text: '#991b1b' },
2269
- high: { bg: '#fee2e2', text: '#991b1b' },
2270
- medium: { bg: '#fef3c7', text: '#92400e' },
2271
- low: { bg: '#e0ecff', text: '#1e3a8a' },
2266
+ proposed: { bg: theme.colors.primary, text: "#fff" },
2267
+ executed: { bg: theme.colors.success, text: "#fff" },
2268
+ declined: { bg: theme.colors.error, text: "#fff" },
2269
+ ok: { bg: "#d1fae5", text: "#065f46" },
2270
+ warning: { bg: "#fef3c7", text: "#92400e" },
2271
+ critical: { bg: "#fee2e2", text: "#991b1b" },
2272
+ high: { bg: "#fee2e2", text: "#991b1b" },
2273
+ medium: { bg: "#fef3c7", text: "#92400e" },
2274
+ low: { bg: "#e0ecff", text: "#1e3a8a" },
2275
+ };
2276
+ const palette = colors[status] || {
2277
+ bg: theme.colors.surface,
2278
+ text: theme.colors.text,
2272
2279
  };
2273
- const palette = colors[status] || { bg: theme.colors.surface, text: theme.colors.text };
2274
2280
  return {
2275
2281
  fontSize: theme.fontSizes.xs,
2276
- padding: '2px 8px',
2277
- borderRadius: '999px',
2282
+ padding: "2px 8px",
2283
+ borderRadius: "999px",
2278
2284
  backgroundColor: palette.bg,
2279
2285
  color: palette.text,
2280
2286
  fontWeight: 700,
2281
- textTransform: 'capitalize',
2287
+ textTransform: "capitalize",
2282
2288
  };
2283
2289
  };
2284
- const directiveCardStyle = (status) => (Object.assign(Object.assign({}, cardStyle), { borderLeft: `4px solid ${status === 'executed'
2290
+ const directiveCardStyle = (status) => (Object.assign(Object.assign({}, cardStyle), { borderLeft: `4px solid ${status === "executed"
2285
2291
  ? theme.colors.success
2286
- : status === 'declined'
2292
+ : status === "declined"
2287
2293
  ? theme.colors.error
2288
- : theme.colors.primary}`, display: 'flex', flexDirection: 'column', gap: theme.spacing.sm }));
2294
+ : theme.colors.primary}`, display: "flex", flexDirection: "column", gap: theme.spacing.sm }));
2289
2295
  return (React.createElement("div", { className: className, style: containerStyle },
2290
2296
  React.createElement("div", { style: sidebarStyle },
2291
- React.createElement("div", { style: { display: 'flex', justifyContent: 'space-between', alignItems: 'center' } },
2297
+ React.createElement("div", { style: {
2298
+ display: "flex",
2299
+ justifyContent: "space-between",
2300
+ alignItems: "center",
2301
+ } },
2292
2302
  React.createElement("h3", { style: { margin: 0, fontSize: theme.fontSizes.lg } }, "Analytics"),
2293
2303
  showRefresh && (React.createElement("button", { type: "button", onClick: handleRefresh, disabled: configsLoading, style: {
2294
2304
  border: `1px solid ${theme.colors.border}`,
@@ -2296,43 +2306,58 @@ function AnalyticsDashboard({ onDirectiveAction, className = '', showRefresh = t
2296
2306
  color: theme.colors.text,
2297
2307
  padding: `${theme.spacing.xs} ${theme.spacing.sm}`,
2298
2308
  borderRadius: theme.borderRadius,
2299
- cursor: configsLoading ? 'not-allowed' : 'pointer',
2300
- } }, configsLoading ? 'Refreshing...' : 'Refresh'))),
2309
+ cursor: configsLoading ? "not-allowed" : "pointer",
2310
+ } }, configsLoading ? "Refreshing..." : "Refresh"))),
2301
2311
  configsLoading && (React.createElement("div", { style: placeholderStyle }, "Loading analytics...")),
2302
2312
  configsError && (React.createElement("div", { style: placeholderStyle },
2303
2313
  "Error loading analytics: ",
2304
2314
  configsError.message)),
2305
2315
  configs && configs.length === 0 && (React.createElement("div", { style: placeholderStyle }, "No analytics configured. Configure analytics in your DirectivSys dashboard.")),
2306
- configs && configs.length > 0 && (React.createElement("div", { style: { display: 'flex', flexDirection: 'column', gap: theme.spacing.sm } }, configs.map((config) => {
2316
+ configs && configs.length > 0 && (React.createElement("div", { style: {
2317
+ display: "flex",
2318
+ flexDirection: "column",
2319
+ gap: theme.spacing.sm,
2320
+ } }, configs.map((config) => {
2307
2321
  const isActive = selectedAnalytics === config.analyticsType;
2308
- return (React.createElement("button", { key: config.configId, type: "button", onClick: () => config.isEnabled && setSelectedAnalytics(config.analyticsType), style: listItemStyle(isActive, !config.isEnabled), disabled: !config.isEnabled },
2322
+ return (React.createElement("button", { key: config.configId, type: "button", onClick: () => config.isEnabled &&
2323
+ setSelectedAnalytics(config.analyticsType), style: listItemStyle(isActive, !config.isEnabled), disabled: !config.isEnabled },
2309
2324
  React.createElement("div", { style: {
2310
- display: 'flex',
2311
- justifyContent: 'space-between',
2312
- alignItems: 'center',
2325
+ display: "flex",
2326
+ justifyContent: "space-between",
2327
+ alignItems: "center",
2313
2328
  marginBottom: theme.spacing.xs,
2314
- width: '100%',
2329
+ width: "100%",
2315
2330
  } },
2316
2331
  React.createElement("span", { style: { fontSize: theme.fontSizes.md, fontWeight: 600 } }, config.analyticsType),
2317
- !config.isEnabled && React.createElement("span", { style: pillStyle(theme.colors.textSecondary) }, "Disabled")),
2332
+ !config.isEnabled && (React.createElement("span", { style: pillStyle(theme.colors.textSecondary) }, "Disabled"))),
2318
2333
  React.createElement("div", { style: {
2319
2334
  fontSize: theme.fontSizes.sm,
2320
- color: isActive ? 'rgba(255,255,255,0.9)' : theme.colors.textSecondary,
2335
+ color: isActive
2336
+ ? "rgba(255,255,255,0.9)"
2337
+ : theme.colors.textSecondary,
2321
2338
  marginBottom: theme.spacing.xs,
2322
2339
  } }, config.templateDescription),
2323
2340
  React.createElement("div", { style: {
2324
- display: 'flex',
2325
- justifyContent: 'space-between',
2326
- width: '100%',
2341
+ display: "flex",
2342
+ justifyContent: "space-between",
2343
+ width: "100%",
2327
2344
  fontSize: theme.fontSizes.xs,
2328
- color: isActive ? 'rgba(255,255,255,0.8)' : theme.colors.textSecondary,
2345
+ color: isActive
2346
+ ? "rgba(255,255,255,0.8)"
2347
+ : theme.colors.textSecondary,
2329
2348
  } },
2330
- React.createElement("span", { style: { textTransform: 'capitalize' } }, config.frequency),
2349
+ React.createElement("span", { style: { textTransform: "capitalize" } }, config.frequency),
2331
2350
  config.lastExecutedAt && (React.createElement("span", null,
2332
- "Last: ",
2351
+ "Last:",
2352
+ " ",
2333
2353
  new Date(config.lastExecutedAt).toLocaleDateString())))));
2334
2354
  })))),
2335
- React.createElement("div", { style: { flex: 1, display: 'flex', flexDirection: 'column', gap: theme.spacing.lg } },
2355
+ React.createElement("div", { style: {
2356
+ flex: 1,
2357
+ display: "flex",
2358
+ flexDirection: "column",
2359
+ gap: theme.spacing.lg,
2360
+ } },
2336
2361
  !selectedAnalytics && (React.createElement("div", { style: placeholderStyle },
2337
2362
  React.createElement("h3", { style: { margin: 0, color: theme.colors.text } }, "No analytics selected"),
2338
2363
  React.createElement("p", { style: { margin: 0 } }, "Select an analytics type from the left to view results."))),
@@ -2343,92 +2368,196 @@ function AnalyticsDashboard({ onDirectiveAction, className = '', showRefresh = t
2343
2368
  selectedAnalytics && !resultLoading && !result && (React.createElement("div", { style: placeholderStyle },
2344
2369
  React.createElement("h3", { style: { margin: 0, color: theme.colors.text } }, "No results yet"),
2345
2370
  React.createElement("p", { style: { margin: 0 } }, "This analytics has not run yet. Results will appear after the first run."))),
2346
- selectedAnalytics && result && (React.createElement("div", { style: { display: 'flex', flexDirection: 'column', gap: theme.spacing.lg } },
2347
- React.createElement("div", { style: { display: 'flex', flexDirection: 'column', gap: theme.spacing.xs } },
2348
- React.createElement("h2", { style: { margin: 0, fontSize: theme.fontSizes.xl, color: theme.colors.text } }, selectedConfig === null || selectedConfig === void 0 ? void 0 : selectedConfig.analyticsType),
2349
- React.createElement("p", { style: { margin: 0, color: theme.colors.textSecondary, fontSize: theme.fontSizes.sm } },
2371
+ selectedAnalytics && result && (React.createElement("div", { style: {
2372
+ display: "flex",
2373
+ flexDirection: "column",
2374
+ gap: theme.spacing.lg,
2375
+ } },
2376
+ React.createElement("div", { style: {
2377
+ display: "flex",
2378
+ flexDirection: "column",
2379
+ gap: theme.spacing.xs,
2380
+ } },
2381
+ React.createElement("h2", { style: {
2382
+ margin: 0,
2383
+ fontSize: theme.fontSizes.xl,
2384
+ color: theme.colors.text,
2385
+ } }, selectedConfig === null || selectedConfig === void 0 ? void 0 : selectedConfig.analyticsType),
2386
+ React.createElement("p", { style: {
2387
+ margin: 0,
2388
+ color: theme.colors.textSecondary,
2389
+ fontSize: theme.fontSizes.sm,
2390
+ } },
2350
2391
  "Generated: ",
2351
2392
  new Date(result.createdAt).toLocaleString())),
2352
- result.metrics && result.metrics.length > 0 && (React.createElement("div", { style: { display: 'flex', flexDirection: 'column', gap: theme.spacing.md } },
2393
+ result.metrics && result.metrics.length > 0 && (React.createElement("div", { style: {
2394
+ display: "flex",
2395
+ flexDirection: "column",
2396
+ gap: theme.spacing.md,
2397
+ } },
2353
2398
  React.createElement("h3", { style: { margin: 0, fontSize: theme.fontSizes.lg } }, "Metrics"),
2354
2399
  React.createElement("div", { style: {
2355
- display: 'grid',
2356
- gridTemplateColumns: 'repeat(auto-fill, minmax(220px, 1fr))',
2400
+ display: "grid",
2401
+ gridTemplateColumns: "repeat(auto-fill, minmax(220px, 1fr))",
2357
2402
  gap: theme.spacing.md,
2358
- } }, result.metrics.map((metric, index) => (React.createElement("div", { key: index, style: Object.assign(Object.assign({}, cardStyle), { borderLeft: `4px solid ${metric.status === 'ok'
2403
+ } }, result.metrics.map((metric, index) => (React.createElement("div", { key: index, style: Object.assign(Object.assign({}, cardStyle), { borderLeft: `4px solid ${metric.status === "ok"
2359
2404
  ? theme.colors.success
2360
- : metric.status === 'warning'
2361
- ? '#f59e0b'
2405
+ : metric.status === "warning"
2406
+ ? "#f59e0b"
2362
2407
  : theme.colors.error}` }) },
2363
2408
  React.createElement("div", { style: {
2364
- display: 'flex',
2365
- justifyContent: 'space-between',
2366
- alignItems: 'center',
2409
+ display: "flex",
2410
+ justifyContent: "space-between",
2411
+ alignItems: "center",
2367
2412
  marginBottom: theme.spacing.xs,
2368
2413
  } },
2369
- React.createElement("span", { style: { fontWeight: 600 } }, metric.name),
2414
+ React.createElement("span", { style: {
2415
+ fontWeight: 600,
2416
+ maxWidth: "100%",
2417
+ overflow: "hidden",
2418
+ textOverflow: "ellipsis",
2419
+ whiteSpace: "nowrap",
2420
+ display: "inline-block",
2421
+ }, title: metric.name }, metric.name),
2370
2422
  React.createElement("span", { style: statusBadgeStyle(metric.status) }, metric.status)),
2371
- React.createElement("div", { style: { fontSize: theme.fontSizes.xl, fontWeight: 700 } },
2423
+ React.createElement("div", { style: {
2424
+ fontSize: theme.fontSizes.xl,
2425
+ fontWeight: 700,
2426
+ } },
2372
2427
  metric.value,
2373
2428
  " ",
2374
2429
  metric.unit),
2375
- React.createElement("div", { style: { color: theme.colors.textSecondary, fontSize: theme.fontSizes.sm } }, metric.explanation))))))),
2376
- result.observations && result.observations.length > 0 && (React.createElement("div", { style: { display: 'flex', flexDirection: 'column', gap: theme.spacing.md } },
2430
+ React.createElement("div", { style: {
2431
+ color: theme.colors.textSecondary,
2432
+ fontSize: theme.fontSizes.sm,
2433
+ } }, metric.explanation))))))),
2434
+ result.observations && result.observations.length > 0 && (React.createElement("div", { style: {
2435
+ display: "flex",
2436
+ flexDirection: "column",
2437
+ gap: theme.spacing.md,
2438
+ } },
2377
2439
  React.createElement("h3", { style: { margin: 0, fontSize: theme.fontSizes.lg } }, "Observations"),
2378
- React.createElement("div", { style: { display: 'flex', flexDirection: 'column', gap: theme.spacing.sm } }, result.observations.map((observation, index) => (React.createElement("div", { key: index, style: Object.assign(Object.assign({}, cardStyle), { borderLeft: `4px solid ${observation.severity === 'high'
2440
+ React.createElement("div", { style: {
2441
+ display: "flex",
2442
+ flexDirection: "column",
2443
+ gap: theme.spacing.sm,
2444
+ } }, result.observations.map((observation, index) => (React.createElement("div", { key: index, style: Object.assign(Object.assign({}, cardStyle), { borderLeft: `4px solid ${observation.severity === "high"
2379
2445
  ? theme.colors.error
2380
- : observation.severity === 'medium'
2381
- ? '#f59e0b'
2382
- : theme.colors.primary}`, display: 'flex', flexDirection: 'column', gap: theme.spacing.xs }) },
2383
- React.createElement("div", { style: { display: 'flex', gap: theme.spacing.sm, alignItems: 'center' } },
2446
+ : observation.severity === "medium"
2447
+ ? "#f59e0b"
2448
+ : theme.colors.primary}`, display: "flex", flexDirection: "column", gap: theme.spacing.xs }) },
2449
+ React.createElement("div", { style: {
2450
+ display: "flex",
2451
+ gap: theme.spacing.sm,
2452
+ alignItems: "center",
2453
+ } },
2384
2454
  React.createElement("span", { style: statusBadgeStyle(observation.severity) }, observation.severity),
2385
- React.createElement("span", { style: { color: theme.colors.textSecondary, fontSize: theme.fontSizes.sm } }, observation.scope)),
2386
- React.createElement("div", { style: { color: theme.colors.text, fontSize: theme.fontSizes.sm } }, observation.text))))))),
2387
- result.directives && result.directives.length > 0 && (React.createElement("div", { style: { display: 'flex', flexDirection: 'column', gap: theme.spacing.md } },
2388
- React.createElement("div", { style: { display: 'flex', justifyContent: 'space-between', alignItems: 'center' } },
2455
+ React.createElement("span", { style: {
2456
+ color: theme.colors.textSecondary,
2457
+ fontSize: theme.fontSizes.sm,
2458
+ } }, observation.scope)),
2459
+ React.createElement("div", { style: {
2460
+ color: theme.colors.text,
2461
+ fontSize: theme.fontSizes.sm,
2462
+ } }, observation.text))))))),
2463
+ result.directives && result.directives.length > 0 && (React.createElement("div", { style: {
2464
+ display: "flex",
2465
+ flexDirection: "column",
2466
+ gap: theme.spacing.md,
2467
+ } },
2468
+ React.createElement("div", { style: {
2469
+ display: "flex",
2470
+ justifyContent: "space-between",
2471
+ alignItems: "center",
2472
+ } },
2389
2473
  React.createElement("h3", { style: { margin: 0, fontSize: theme.fontSizes.lg } }, "Recommended actions"),
2390
- React.createElement("div", { style: { display: 'flex', gap: theme.spacing.xs } },
2391
- React.createElement("button", { type: "button", onClick: () => setDirectiveFilter('all'), style: Object.assign(Object.assign({}, pillStyle(directiveFilter === 'all' ? theme.colors.primary : theme.colors.surface)), { border: `1px solid ${theme.colors.border}`, color: directiveFilter === 'all' ? '#fff' : theme.colors.text }) },
2474
+ React.createElement("div", { style: { display: "flex", gap: theme.spacing.xs } },
2475
+ React.createElement("button", { type: "button", onClick: () => setDirectiveFilter("all"), style: Object.assign(Object.assign({}, pillStyle(directiveFilter === "all"
2476
+ ? theme.colors.primary
2477
+ : theme.colors.surface)), { border: `1px solid ${theme.colors.border}`, color: directiveFilter === "all"
2478
+ ? "#fff"
2479
+ : theme.colors.text }) },
2392
2480
  "All (",
2393
2481
  result.directives.length,
2394
2482
  ")"),
2395
- React.createElement("button", { type: "button", onClick: () => setDirectiveFilter('proposed'), style: Object.assign(Object.assign({}, pillStyle(directiveFilter === 'proposed' ? theme.colors.primary : theme.colors.surface)), { border: `1px solid ${theme.colors.border}`, color: directiveFilter === 'proposed' ? '#fff' : theme.colors.text }) },
2483
+ React.createElement("button", { type: "button", onClick: () => setDirectiveFilter("proposed"), style: Object.assign(Object.assign({}, pillStyle(directiveFilter === "proposed"
2484
+ ? theme.colors.primary
2485
+ : theme.colors.surface)), { border: `1px solid ${theme.colors.border}`, color: directiveFilter === "proposed"
2486
+ ? "#fff"
2487
+ : theme.colors.text }) },
2396
2488
  "Proposed (",
2397
2489
  proposedCount,
2398
2490
  ")"),
2399
- React.createElement("button", { type: "button", onClick: () => setDirectiveFilter('executed'), style: Object.assign(Object.assign({}, pillStyle(directiveFilter === 'executed' ? theme.colors.primary : theme.colors.surface)), { border: `1px solid ${theme.colors.border}`, color: directiveFilter === 'executed' ? '#fff' : theme.colors.text }) },
2491
+ React.createElement("button", { type: "button", onClick: () => setDirectiveFilter("executed"), style: Object.assign(Object.assign({}, pillStyle(directiveFilter === "executed"
2492
+ ? theme.colors.primary
2493
+ : theme.colors.surface)), { border: `1px solid ${theme.colors.border}`, color: directiveFilter === "executed"
2494
+ ? "#fff"
2495
+ : theme.colors.text }) },
2400
2496
  "Executed (",
2401
2497
  executedCount,
2402
2498
  ")"),
2403
- React.createElement("button", { type: "button", onClick: () => setDirectiveFilter('declined'), style: Object.assign(Object.assign({}, pillStyle(directiveFilter === 'declined' ? theme.colors.primary : theme.colors.surface)), { border: `1px solid ${theme.colors.border}`, color: directiveFilter === 'declined' ? '#fff' : theme.colors.text }) },
2499
+ React.createElement("button", { type: "button", onClick: () => setDirectiveFilter("declined"), style: Object.assign(Object.assign({}, pillStyle(directiveFilter === "declined"
2500
+ ? theme.colors.primary
2501
+ : theme.colors.surface)), { border: `1px solid ${theme.colors.border}`, color: directiveFilter === "declined"
2502
+ ? "#fff"
2503
+ : theme.colors.text }) },
2404
2504
  "Declined (",
2405
2505
  declinedCount,
2406
2506
  ")"))),
2407
2507
  filteredDirectives.length === 0 && (React.createElement("div", { style: placeholderStyle }, "No directives match the selected filter.")),
2408
- React.createElement("div", { style: { display: 'flex', flexDirection: 'column', gap: theme.spacing.sm } }, filteredDirectives.map((directive) => (React.createElement("div", { key: directive.directiveId, style: directiveCardStyle(directive.status) },
2508
+ React.createElement("div", { style: {
2509
+ display: "flex",
2510
+ flexDirection: "column",
2511
+ gap: theme.spacing.sm,
2512
+ } }, filteredDirectives.map((directive) => (React.createElement("div", { key: directive.directiveId, style: directiveCardStyle(directive.status) },
2409
2513
  React.createElement("div", { style: {
2410
- display: 'flex',
2411
- justifyContent: 'space-between',
2412
- alignItems: 'center',
2514
+ display: "flex",
2515
+ justifyContent: "space-between",
2516
+ alignItems: "center",
2413
2517
  gap: theme.spacing.sm,
2414
- flexWrap: 'wrap',
2518
+ flexWrap: "wrap",
2415
2519
  } },
2416
- React.createElement("div", { style: { display: 'flex', flexDirection: 'column', gap: theme.spacing.xs } },
2520
+ React.createElement("div", { style: {
2521
+ display: "flex",
2522
+ flexDirection: "column",
2523
+ gap: theme.spacing.xs,
2524
+ } },
2417
2525
  React.createElement("span", { style: { fontWeight: 700 } }, directive.action),
2418
- React.createElement("span", { style: { color: theme.colors.textSecondary, fontSize: theme.fontSizes.sm } },
2526
+ React.createElement("span", { style: {
2527
+ color: theme.colors.textSecondary,
2528
+ fontSize: theme.fontSizes.sm,
2529
+ } },
2419
2530
  "Priority: ",
2420
2531
  directive.priority)),
2421
2532
  React.createElement("span", { style: statusBadgeStyle(directive.status) }, directive.status)),
2422
- React.createElement("div", { style: { color: theme.colors.text, fontSize: theme.fontSizes.sm } }, directive.rationale),
2423
- directive.parameters && directive.parameters.length > 0 && (React.createElement("div", { style: { color: theme.colors.textSecondary, fontSize: theme.fontSizes.sm } },
2533
+ React.createElement("div", { style: {
2534
+ color: theme.colors.text,
2535
+ fontSize: theme.fontSizes.sm,
2536
+ } }, directive.rationale),
2537
+ directive.parameters &&
2538
+ directive.parameters.length > 0 && (React.createElement("div", { style: {
2539
+ color: theme.colors.textSecondary,
2540
+ fontSize: theme.fontSizes.sm,
2541
+ } },
2424
2542
  React.createElement("strong", { style: { color: theme.colors.text } }, "Parameters:"),
2425
- React.createElement("ul", { style: { margin: `${theme.spacing.xs} 0 0 16px`, padding: 0 } }, directive.parameters.map((param, index) => (React.createElement("li", { key: index, style: { marginBottom: theme.spacing.xs } },
2543
+ React.createElement("ul", { style: {
2544
+ margin: `${theme.spacing.xs} 0 0 16px`,
2545
+ padding: 0,
2546
+ } }, directive.parameters.map((param, index) => (React.createElement("li", { key: index, style: { marginBottom: theme.spacing.xs } },
2426
2547
  React.createElement("code", null, param.name),
2427
2548
  ": ",
2428
2549
  param.value)))))),
2429
- directive.status === 'proposed' && (React.createElement("div", { style: { display: 'flex', gap: theme.spacing.sm } },
2430
- React.createElement("button", { type: "button", onClick: () => handleDirectiveAction(directive, 'execute'), disabled: isProcessing, style: Object.assign(Object.assign({}, pillStyle(theme.colors.success)), { border: 'none', cursor: isProcessing ? 'not-allowed' : 'pointer' }) }, isProcessing ? 'Processing...' : 'Execute'),
2431
- React.createElement("button", { type: "button", onClick: () => handleDirectiveAction(directive, 'decline'), disabled: isProcessing, style: Object.assign(Object.assign({}, pillStyle(theme.colors.error)), { border: 'none', cursor: isProcessing ? 'not-allowed' : 'pointer' }) }, "Decline"))))))))))))));
2550
+ directive.status === "proposed" && (React.createElement("div", { style: { display: "flex", gap: theme.spacing.sm } },
2551
+ 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
2552
+ ? "not-allowed"
2553
+ : "pointer" }) }, isProcessing && processingId === directive.directiveId
2554
+ ? "Processing..."
2555
+ : "Execute"),
2556
+ 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
2557
+ ? "not-allowed"
2558
+ : "pointer" }) }, isProcessing && processingId === directive.directiveId
2559
+ ? "Processing..."
2560
+ : "Decline"))))))))))))));
2432
2561
  }
2433
2562
 
2434
2563
  export { AnalyticsAPI, AnalyticsDashboard, AnalyticsReport, AnalyticsWidget, DirectivesPanel, MetricsPanel, ObservationsPanel, ReactBridgeAPI, ReactBridgeChatbox, ReactBridgeProvider, ReactBridgeSearch, WebSpeechSTTProvider, WebSpeechTTSProvider, createCustomTheme, darkTheme, getTheme, lightTheme, useAnalyticsConfigs, useAnalyticsResult, useDirectiveAction, useReactBridge, useReactBridgeContext };