reactbridge-sdk 0.2.3 → 0.2.4

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,qBA+vBzB"}
package/dist/index.esm.js CHANGED
@@ -2151,11 +2151,11 @@ 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
@@ -2191,20 +2191,20 @@ function AnalyticsDashboard({ onDirectiveAction, className = '', showRefresh = t
2191
2191
  // Refetch result to get updated directive statuses
2192
2192
  refetchResult();
2193
2193
  });
2194
- const filteredDirectives = (result === null || result === void 0 ? void 0 : result.directives.filter(d => {
2195
- if (directiveFilter === 'all')
2194
+ const filteredDirectives = (result === null || result === void 0 ? void 0 : result.directives.filter((d) => {
2195
+ if (directiveFilter === "all")
2196
2196
  return true;
2197
2197
  return d.status === directiveFilter;
2198
2198
  })) || [];
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;
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;
2203
2203
  const containerStyle = {
2204
- display: 'flex',
2204
+ display: "flex",
2205
2205
  gap: theme.spacing.lg,
2206
- width: '100%',
2207
- minHeight: '540px',
2206
+ width: "100%",
2207
+ minHeight: "540px",
2208
2208
  backgroundColor: theme.colors.background,
2209
2209
  color: theme.colors.text,
2210
2210
  border: `1px solid ${theme.colors.border}`,
@@ -2213,44 +2213,44 @@ function AnalyticsDashboard({ onDirectiveAction, className = '', showRefresh = t
2213
2213
  padding: theme.spacing.lg,
2214
2214
  };
2215
2215
  const sidebarStyle = {
2216
- width: '320px',
2216
+ width: "320px",
2217
2217
  borderRight: `1px solid ${theme.colors.border}`,
2218
2218
  paddingRight: theme.spacing.lg,
2219
- display: 'flex',
2220
- flexDirection: 'column',
2219
+ display: "flex",
2220
+ flexDirection: "column",
2221
2221
  gap: theme.spacing.sm,
2222
2222
  };
2223
2223
  const listItemStyle = (isActive, isDisabled) => ({
2224
- width: '100%',
2225
- textAlign: 'left',
2224
+ width: "100%",
2225
+ textAlign: "left",
2226
2226
  padding: theme.spacing.md,
2227
2227
  backgroundColor: isActive ? theme.colors.primary : theme.colors.surface,
2228
- color: isActive ? '#fff' : theme.colors.text,
2228
+ color: isActive ? "#fff" : theme.colors.text,
2229
2229
  border: `1px solid ${isActive ? theme.colors.primary : theme.colors.border}`,
2230
2230
  borderRadius: theme.borderRadius,
2231
- cursor: isDisabled ? 'not-allowed' : 'pointer',
2231
+ cursor: isDisabled ? "not-allowed" : "pointer",
2232
2232
  opacity: isDisabled ? 0.6 : 1,
2233
- transition: 'transform 0.15s ease, box-shadow 0.15s ease',
2234
- boxShadow: isActive ? theme.boxShadow : 'none',
2233
+ transition: "transform 0.15s ease, box-shadow 0.15s ease",
2234
+ boxShadow: isActive ? theme.boxShadow : "none",
2235
2235
  });
2236
2236
  const pillStyle = (bg) => ({
2237
2237
  fontSize: theme.fontSizes.xs,
2238
- padding: '2px 8px',
2239
- borderRadius: '999px',
2238
+ padding: "2px 8px",
2239
+ borderRadius: "999px",
2240
2240
  backgroundColor: bg,
2241
- color: '#fff',
2241
+ color: "#fff",
2242
2242
  fontWeight: 600,
2243
2243
  });
2244
2244
  const placeholderStyle = {
2245
2245
  flex: 1,
2246
- minHeight: '420px',
2247
- display: 'flex',
2248
- flexDirection: 'column',
2249
- alignItems: 'center',
2250
- justifyContent: 'center',
2246
+ minHeight: "420px",
2247
+ display: "flex",
2248
+ flexDirection: "column",
2249
+ alignItems: "center",
2250
+ justifyContent: "center",
2251
2251
  gap: theme.spacing.sm,
2252
2252
  color: theme.colors.textSecondary,
2253
- textAlign: 'center',
2253
+ textAlign: "center",
2254
2254
  };
2255
2255
  const cardStyle = {
2256
2256
  backgroundColor: theme.colors.surface,
@@ -2260,35 +2260,42 @@ function AnalyticsDashboard({ onDirectiveAction, className = '', showRefresh = t
2260
2260
  };
2261
2261
  const statusBadgeStyle = (status) => {
2262
2262
  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' },
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" },
2272
+ };
2273
+ const palette = colors[status] || {
2274
+ bg: theme.colors.surface,
2275
+ text: theme.colors.text,
2272
2276
  };
2273
- const palette = colors[status] || { bg: theme.colors.surface, text: theme.colors.text };
2274
2277
  return {
2275
2278
  fontSize: theme.fontSizes.xs,
2276
- padding: '2px 8px',
2277
- borderRadius: '999px',
2279
+ padding: "2px 8px",
2280
+ borderRadius: "999px",
2278
2281
  backgroundColor: palette.bg,
2279
2282
  color: palette.text,
2280
2283
  fontWeight: 700,
2281
- textTransform: 'capitalize',
2284
+ textTransform: "capitalize",
2282
2285
  };
2283
2286
  };
2284
- const directiveCardStyle = (status) => (Object.assign(Object.assign({}, cardStyle), { borderLeft: `4px solid ${status === 'executed'
2287
+ const directiveCardStyle = (status) => (Object.assign(Object.assign({}, cardStyle), { borderLeft: `4px solid ${status === "executed"
2285
2288
  ? theme.colors.success
2286
- : status === 'declined'
2289
+ : status === "declined"
2287
2290
  ? theme.colors.error
2288
- : theme.colors.primary}`, display: 'flex', flexDirection: 'column', gap: theme.spacing.sm }));
2291
+ : theme.colors.primary}`, display: "flex", flexDirection: "column", gap: theme.spacing.sm }));
2289
2292
  return (React.createElement("div", { className: className, style: containerStyle },
2290
2293
  React.createElement("div", { style: sidebarStyle },
2291
- React.createElement("div", { style: { display: 'flex', justifyContent: 'space-between', alignItems: 'center' } },
2294
+ React.createElement("div", { style: {
2295
+ display: "flex",
2296
+ justifyContent: "space-between",
2297
+ alignItems: "center",
2298
+ } },
2292
2299
  React.createElement("h3", { style: { margin: 0, fontSize: theme.fontSizes.lg } }, "Analytics"),
2293
2300
  showRefresh && (React.createElement("button", { type: "button", onClick: handleRefresh, disabled: configsLoading, style: {
2294
2301
  border: `1px solid ${theme.colors.border}`,
@@ -2296,43 +2303,58 @@ function AnalyticsDashboard({ onDirectiveAction, className = '', showRefresh = t
2296
2303
  color: theme.colors.text,
2297
2304
  padding: `${theme.spacing.xs} ${theme.spacing.sm}`,
2298
2305
  borderRadius: theme.borderRadius,
2299
- cursor: configsLoading ? 'not-allowed' : 'pointer',
2300
- } }, configsLoading ? 'Refreshing...' : 'Refresh'))),
2306
+ cursor: configsLoading ? "not-allowed" : "pointer",
2307
+ } }, configsLoading ? "Refreshing..." : "Refresh"))),
2301
2308
  configsLoading && (React.createElement("div", { style: placeholderStyle }, "Loading analytics...")),
2302
2309
  configsError && (React.createElement("div", { style: placeholderStyle },
2303
2310
  "Error loading analytics: ",
2304
2311
  configsError.message)),
2305
2312
  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) => {
2313
+ configs && configs.length > 0 && (React.createElement("div", { style: {
2314
+ display: "flex",
2315
+ flexDirection: "column",
2316
+ gap: theme.spacing.sm,
2317
+ } }, configs.map((config) => {
2307
2318
  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 },
2319
+ return (React.createElement("button", { key: config.configId, type: "button", onClick: () => config.isEnabled &&
2320
+ setSelectedAnalytics(config.analyticsType), style: listItemStyle(isActive, !config.isEnabled), disabled: !config.isEnabled },
2309
2321
  React.createElement("div", { style: {
2310
- display: 'flex',
2311
- justifyContent: 'space-between',
2312
- alignItems: 'center',
2322
+ display: "flex",
2323
+ justifyContent: "space-between",
2324
+ alignItems: "center",
2313
2325
  marginBottom: theme.spacing.xs,
2314
- width: '100%',
2326
+ width: "100%",
2315
2327
  } },
2316
2328
  React.createElement("span", { style: { fontSize: theme.fontSizes.md, fontWeight: 600 } }, config.analyticsType),
2317
- !config.isEnabled && React.createElement("span", { style: pillStyle(theme.colors.textSecondary) }, "Disabled")),
2329
+ !config.isEnabled && (React.createElement("span", { style: pillStyle(theme.colors.textSecondary) }, "Disabled"))),
2318
2330
  React.createElement("div", { style: {
2319
2331
  fontSize: theme.fontSizes.sm,
2320
- color: isActive ? 'rgba(255,255,255,0.9)' : theme.colors.textSecondary,
2332
+ color: isActive
2333
+ ? "rgba(255,255,255,0.9)"
2334
+ : theme.colors.textSecondary,
2321
2335
  marginBottom: theme.spacing.xs,
2322
2336
  } }, config.templateDescription),
2323
2337
  React.createElement("div", { style: {
2324
- display: 'flex',
2325
- justifyContent: 'space-between',
2326
- width: '100%',
2338
+ display: "flex",
2339
+ justifyContent: "space-between",
2340
+ width: "100%",
2327
2341
  fontSize: theme.fontSizes.xs,
2328
- color: isActive ? 'rgba(255,255,255,0.8)' : theme.colors.textSecondary,
2342
+ color: isActive
2343
+ ? "rgba(255,255,255,0.8)"
2344
+ : theme.colors.textSecondary,
2329
2345
  } },
2330
- React.createElement("span", { style: { textTransform: 'capitalize' } }, config.frequency),
2346
+ React.createElement("span", { style: { textTransform: "capitalize" } }, config.frequency),
2331
2347
  config.lastExecutedAt && (React.createElement("span", null,
2332
- "Last: ",
2348
+ "Last:",
2349
+ " ",
2333
2350
  new Date(config.lastExecutedAt).toLocaleDateString())))));
2334
2351
  })))),
2335
- React.createElement("div", { style: { flex: 1, display: 'flex', flexDirection: 'column', gap: theme.spacing.lg } },
2352
+ React.createElement("div", { style: {
2353
+ flex: 1,
2354
+ display: "flex",
2355
+ flexDirection: "column",
2356
+ gap: theme.spacing.lg,
2357
+ } },
2336
2358
  !selectedAnalytics && (React.createElement("div", { style: placeholderStyle },
2337
2359
  React.createElement("h3", { style: { margin: 0, color: theme.colors.text } }, "No analytics selected"),
2338
2360
  React.createElement("p", { style: { margin: 0 } }, "Select an analytics type from the left to view results."))),
@@ -2343,92 +2365,188 @@ function AnalyticsDashboard({ onDirectiveAction, className = '', showRefresh = t
2343
2365
  selectedAnalytics && !resultLoading && !result && (React.createElement("div", { style: placeholderStyle },
2344
2366
  React.createElement("h3", { style: { margin: 0, color: theme.colors.text } }, "No results yet"),
2345
2367
  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 } },
2368
+ selectedAnalytics && result && (React.createElement("div", { style: {
2369
+ display: "flex",
2370
+ flexDirection: "column",
2371
+ gap: theme.spacing.lg,
2372
+ } },
2373
+ React.createElement("div", { style: {
2374
+ display: "flex",
2375
+ flexDirection: "column",
2376
+ gap: theme.spacing.xs,
2377
+ } },
2378
+ React.createElement("h2", { style: {
2379
+ margin: 0,
2380
+ fontSize: theme.fontSizes.xl,
2381
+ color: theme.colors.text,
2382
+ } }, selectedConfig === null || selectedConfig === void 0 ? void 0 : selectedConfig.analyticsType),
2383
+ React.createElement("p", { style: {
2384
+ margin: 0,
2385
+ color: theme.colors.textSecondary,
2386
+ fontSize: theme.fontSizes.sm,
2387
+ } },
2350
2388
  "Generated: ",
2351
2389
  new Date(result.createdAt).toLocaleString())),
2352
- result.metrics && result.metrics.length > 0 && (React.createElement("div", { style: { display: 'flex', flexDirection: 'column', gap: theme.spacing.md } },
2390
+ result.metrics && result.metrics.length > 0 && (React.createElement("div", { style: {
2391
+ display: "flex",
2392
+ flexDirection: "column",
2393
+ gap: theme.spacing.md,
2394
+ } },
2353
2395
  React.createElement("h3", { style: { margin: 0, fontSize: theme.fontSizes.lg } }, "Metrics"),
2354
2396
  React.createElement("div", { style: {
2355
- display: 'grid',
2356
- gridTemplateColumns: 'repeat(auto-fill, minmax(220px, 1fr))',
2397
+ display: "grid",
2398
+ gridTemplateColumns: "repeat(auto-fill, minmax(220px, 1fr))",
2357
2399
  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'
2400
+ } }, result.metrics.map((metric, index) => (React.createElement("div", { key: index, style: Object.assign(Object.assign({}, cardStyle), { borderLeft: `4px solid ${metric.status === "ok"
2359
2401
  ? theme.colors.success
2360
- : metric.status === 'warning'
2361
- ? '#f59e0b'
2402
+ : metric.status === "warning"
2403
+ ? "#f59e0b"
2362
2404
  : theme.colors.error}` }) },
2363
2405
  React.createElement("div", { style: {
2364
- display: 'flex',
2365
- justifyContent: 'space-between',
2366
- alignItems: 'center',
2406
+ display: "flex",
2407
+ justifyContent: "space-between",
2408
+ alignItems: "center",
2367
2409
  marginBottom: theme.spacing.xs,
2368
2410
  } },
2369
- React.createElement("span", { style: { fontWeight: 600 } }, metric.name),
2411
+ React.createElement("span", { style: {
2412
+ fontWeight: 600,
2413
+ maxWidth: "100%",
2414
+ overflow: "hidden",
2415
+ textOverflow: "ellipsis",
2416
+ whiteSpace: "nowrap",
2417
+ display: "inline-block",
2418
+ }, title: metric.name }, metric.name),
2370
2419
  React.createElement("span", { style: statusBadgeStyle(metric.status) }, metric.status)),
2371
- React.createElement("div", { style: { fontSize: theme.fontSizes.xl, fontWeight: 700 } },
2420
+ React.createElement("div", { style: {
2421
+ fontSize: theme.fontSizes.xl,
2422
+ fontWeight: 700,
2423
+ } },
2372
2424
  metric.value,
2373
2425
  " ",
2374
2426
  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 } },
2427
+ React.createElement("div", { style: {
2428
+ color: theme.colors.textSecondary,
2429
+ fontSize: theme.fontSizes.sm,
2430
+ } }, metric.explanation))))))),
2431
+ result.observations && result.observations.length > 0 && (React.createElement("div", { style: {
2432
+ display: "flex",
2433
+ flexDirection: "column",
2434
+ gap: theme.spacing.md,
2435
+ } },
2377
2436
  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'
2437
+ React.createElement("div", { style: {
2438
+ display: "flex",
2439
+ flexDirection: "column",
2440
+ gap: theme.spacing.sm,
2441
+ } }, result.observations.map((observation, index) => (React.createElement("div", { key: index, style: Object.assign(Object.assign({}, cardStyle), { borderLeft: `4px solid ${observation.severity === "high"
2379
2442
  ? 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' } },
2443
+ : observation.severity === "medium"
2444
+ ? "#f59e0b"
2445
+ : theme.colors.primary}`, display: "flex", flexDirection: "column", gap: theme.spacing.xs }) },
2446
+ React.createElement("div", { style: {
2447
+ display: "flex",
2448
+ gap: theme.spacing.sm,
2449
+ alignItems: "center",
2450
+ } },
2384
2451
  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' } },
2452
+ React.createElement("span", { style: {
2453
+ color: theme.colors.textSecondary,
2454
+ fontSize: theme.fontSizes.sm,
2455
+ } }, observation.scope)),
2456
+ React.createElement("div", { style: {
2457
+ color: theme.colors.text,
2458
+ fontSize: theme.fontSizes.sm,
2459
+ } }, observation.text))))))),
2460
+ result.directives && result.directives.length > 0 && (React.createElement("div", { style: {
2461
+ display: "flex",
2462
+ flexDirection: "column",
2463
+ gap: theme.spacing.md,
2464
+ } },
2465
+ React.createElement("div", { style: {
2466
+ display: "flex",
2467
+ justifyContent: "space-between",
2468
+ alignItems: "center",
2469
+ } },
2389
2470
  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 }) },
2471
+ React.createElement("div", { style: { display: "flex", gap: theme.spacing.xs } },
2472
+ React.createElement("button", { type: "button", onClick: () => setDirectiveFilter("all"), style: Object.assign(Object.assign({}, pillStyle(directiveFilter === "all"
2473
+ ? theme.colors.primary
2474
+ : theme.colors.surface)), { border: `1px solid ${theme.colors.border}`, color: directiveFilter === "all"
2475
+ ? "#fff"
2476
+ : theme.colors.text }) },
2392
2477
  "All (",
2393
2478
  result.directives.length,
2394
2479
  ")"),
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 }) },
2480
+ React.createElement("button", { type: "button", onClick: () => setDirectiveFilter("proposed"), style: Object.assign(Object.assign({}, pillStyle(directiveFilter === "proposed"
2481
+ ? theme.colors.primary
2482
+ : theme.colors.surface)), { border: `1px solid ${theme.colors.border}`, color: directiveFilter === "proposed"
2483
+ ? "#fff"
2484
+ : theme.colors.text }) },
2396
2485
  "Proposed (",
2397
2486
  proposedCount,
2398
2487
  ")"),
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 }) },
2488
+ React.createElement("button", { type: "button", onClick: () => setDirectiveFilter("executed"), style: Object.assign(Object.assign({}, pillStyle(directiveFilter === "executed"
2489
+ ? theme.colors.primary
2490
+ : theme.colors.surface)), { border: `1px solid ${theme.colors.border}`, color: directiveFilter === "executed"
2491
+ ? "#fff"
2492
+ : theme.colors.text }) },
2400
2493
  "Executed (",
2401
2494
  executedCount,
2402
2495
  ")"),
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 }) },
2496
+ React.createElement("button", { type: "button", onClick: () => setDirectiveFilter("declined"), style: Object.assign(Object.assign({}, pillStyle(directiveFilter === "declined"
2497
+ ? theme.colors.primary
2498
+ : theme.colors.surface)), { border: `1px solid ${theme.colors.border}`, color: directiveFilter === "declined"
2499
+ ? "#fff"
2500
+ : theme.colors.text }) },
2404
2501
  "Declined (",
2405
2502
  declinedCount,
2406
2503
  ")"))),
2407
2504
  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) },
2505
+ React.createElement("div", { style: {
2506
+ display: "flex",
2507
+ flexDirection: "column",
2508
+ gap: theme.spacing.sm,
2509
+ } }, filteredDirectives.map((directive) => (React.createElement("div", { key: directive.directiveId, style: directiveCardStyle(directive.status) },
2409
2510
  React.createElement("div", { style: {
2410
- display: 'flex',
2411
- justifyContent: 'space-between',
2412
- alignItems: 'center',
2511
+ display: "flex",
2512
+ justifyContent: "space-between",
2513
+ alignItems: "center",
2413
2514
  gap: theme.spacing.sm,
2414
- flexWrap: 'wrap',
2515
+ flexWrap: "wrap",
2415
2516
  } },
2416
- React.createElement("div", { style: { display: 'flex', flexDirection: 'column', gap: theme.spacing.xs } },
2517
+ React.createElement("div", { style: {
2518
+ display: "flex",
2519
+ flexDirection: "column",
2520
+ gap: theme.spacing.xs,
2521
+ } },
2417
2522
  React.createElement("span", { style: { fontWeight: 700 } }, directive.action),
2418
- React.createElement("span", { style: { color: theme.colors.textSecondary, fontSize: theme.fontSizes.sm } },
2523
+ React.createElement("span", { style: {
2524
+ color: theme.colors.textSecondary,
2525
+ fontSize: theme.fontSizes.sm,
2526
+ } },
2419
2527
  "Priority: ",
2420
2528
  directive.priority)),
2421
2529
  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 } },
2530
+ React.createElement("div", { style: {
2531
+ color: theme.colors.text,
2532
+ fontSize: theme.fontSizes.sm,
2533
+ } }, directive.rationale),
2534
+ directive.parameters &&
2535
+ directive.parameters.length > 0 && (React.createElement("div", { style: {
2536
+ color: theme.colors.textSecondary,
2537
+ fontSize: theme.fontSizes.sm,
2538
+ } },
2424
2539
  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 } },
2540
+ React.createElement("ul", { style: {
2541
+ margin: `${theme.spacing.xs} 0 0 16px`,
2542
+ padding: 0,
2543
+ } }, directive.parameters.map((param, index) => (React.createElement("li", { key: index, style: { marginBottom: theme.spacing.xs } },
2426
2544
  React.createElement("code", null, param.name),
2427
2545
  ": ",
2428
2546
  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"))))))))))))));
2547
+ directive.status === "proposed" && (React.createElement("div", { style: { display: "flex", gap: theme.spacing.sm } },
2548
+ 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"),
2549
+ 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"))))))))))))));
2432
2550
  }
2433
2551
 
2434
2552
  export { AnalyticsAPI, AnalyticsDashboard, AnalyticsReport, AnalyticsWidget, DirectivesPanel, MetricsPanel, ObservationsPanel, ReactBridgeAPI, ReactBridgeChatbox, ReactBridgeProvider, ReactBridgeSearch, WebSpeechSTTProvider, WebSpeechTTSProvider, createCustomTheme, darkTheme, getTheme, lightTheme, useAnalyticsConfigs, useAnalyticsResult, useDirectiveAction, useReactBridge, useReactBridgeContext };