@ramme-io/ui 4.0.1 → 4.1.1

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 (83) hide show
  1. package/README.md +159 -7
  2. package/dist/blocks/ai/Actions.js +2 -2
  3. package/dist/blocks/ai/PromptInput.js +6 -6
  4. package/dist/component-registry.js +389 -359
  5. package/dist/components/ai/AIChatThread/AIChatThread.js +81 -73
  6. package/dist/components/ai/ArchitectureReferenceCard/ArchitectureReferenceCard.d.ts +28 -0
  7. package/dist/components/ai/ArchitectureReferenceCard/ArchitectureReferenceCard.js +70 -0
  8. package/dist/components/ai/ArchitectureReferenceCard/index.d.ts +2 -0
  9. package/dist/components/ai/CounterpartyGraphCard/CounterpartyGraphCard.d.ts +30 -0
  10. package/dist/components/ai/CounterpartyGraphCard/CounterpartyGraphCard.js +82 -0
  11. package/dist/components/ai/CounterpartyGraphCard/index.d.ts +2 -0
  12. package/dist/components/ai/DivergenceMetricsCard/DivergenceMetricsCard.d.ts +29 -0
  13. package/dist/components/ai/DivergenceMetricsCard/DivergenceMetricsCard.js +69 -0
  14. package/dist/components/ai/DivergenceMetricsCard/index.d.ts +2 -0
  15. package/dist/components/ai/KeyInjectionOverlay.d.ts +10 -0
  16. package/dist/components/ai/KeyInjectionOverlay.js +11 -11
  17. package/dist/components/ai/NewsSummaryCard/NewsSummaryCard.js +17 -17
  18. package/dist/components/ai/StockChart/StockChart.js +4 -4
  19. package/dist/components/auth/AuthLayout.js +4 -4
  20. package/dist/components/auth/LoginPage.d.ts +22 -0
  21. package/dist/components/auth/LoginPage.js +50 -42
  22. package/dist/components/data-display/CodeBlock.d.ts +33 -7
  23. package/dist/components/data-display/CodeBlock.js +134 -41
  24. package/dist/components/data-display/Table.js +8 -8
  25. package/dist/components/feedback/EmptyState.js +9 -9
  26. package/dist/components/feedback/ToastProvider.js +4 -4
  27. package/dist/components/forms/Checkbox.js +5 -5
  28. package/dist/components/forms/ComboBox.js +2 -2
  29. package/dist/components/forms/DatePicker.js +37 -32
  30. package/dist/components/forms/FileUpload.js +39 -37
  31. package/dist/components/forms/Input.js +19 -18
  32. package/dist/components/forms/MultiSelect.js +9 -8
  33. package/dist/components/forms/Radio.js +6 -6
  34. package/dist/components/forms/SegmentedControl.d.ts +1 -1
  35. package/dist/components/forms/SegmentedControl.js +28 -11
  36. package/dist/components/forms/Select.js +9 -8
  37. package/dist/components/forms/Textarea.d.ts +13 -11
  38. package/dist/components/forms/Textarea.js +36 -16
  39. package/dist/components/forms/ToggleSwitch.js +9 -9
  40. package/dist/components/layout/AboutRamme.d.ts +8 -0
  41. package/dist/components/layout/Accordion.js +25 -32
  42. package/dist/components/layout/AppShell.js +7 -7
  43. package/dist/components/layout/Card.js +38 -21
  44. package/dist/components/layout/DetailDrawer.js +37 -38
  45. package/dist/components/layout/Drawer.js +50 -51
  46. package/dist/components/layout/List.js +9 -9
  47. package/dist/components/layout/Modal.js +5 -5
  48. package/dist/components/layout/PageHeader.js +7 -7
  49. package/dist/components/layout/SectionHeader.js +4 -4
  50. package/dist/components/layout/SettingsContainer.d.ts +12 -0
  51. package/dist/components/layout/SettingsContainer.js +30 -18
  52. package/dist/components/layout/Sheet.d.ts +58 -0
  53. package/dist/components/layout/Sheet.js +144 -0
  54. package/dist/components/layout/Sidebar.js +1 -1
  55. package/dist/components/layout/UserNav.d.ts +13 -0
  56. package/dist/components/layout/UserNav.js +17 -17
  57. package/dist/components/molecular/ConnectorOverlay.d.ts +12 -0
  58. package/dist/components/navigation/Breadcrumbs.js +8 -8
  59. package/dist/components/navigation/Menu.js +6 -6
  60. package/dist/components/navigation/MobileNav.d.ts +44 -1
  61. package/dist/components/navigation/MobileNav.js +97 -71
  62. package/dist/components/navigation/Pagination.js +46 -41
  63. package/dist/components/navigation/Stepper.js +17 -17
  64. package/dist/components/navigation/Tabs.js +18 -11
  65. package/dist/components/theme/ThemeLab.d.ts +7 -1
  66. package/dist/components/theme/ThemeLab.js +175 -154
  67. package/dist/components/ui/icon-loader.d.ts +1 -1
  68. package/dist/contexts/ThemeContext.js +111 -82
  69. package/dist/data/mockData.d.ts +0 -3
  70. package/dist/index.css +1 -1
  71. package/dist/index.d.ts +10 -0
  72. package/dist/index.js +222 -197
  73. package/dist/lib/hooks/useBodyScrollLock.d.ts +27 -0
  74. package/dist/lib/hooks/useBodyScrollLock.js +18 -0
  75. package/dist/lib/hooks/useSheetGesture.d.ts +81 -0
  76. package/dist/lib/hooks/useSheetGesture.js +70 -0
  77. package/dist/lib/theme/themeUtils.d.ts +21 -0
  78. package/dist/lib/theme/themeUtils.js +31 -17
  79. package/dist/setupTests.d.ts +1 -0
  80. package/dist/wizardManifest.js +364 -19
  81. package/package.json +10 -4
  82. package/src/wizardManifest.ts +364 -19
  83. package/tailwind.preset.js +98 -10
@@ -1,49 +1,53 @@
1
1
  import { jsxs as c, jsx as t, Fragment as w } from "react/jsx-runtime";
2
- import { useState as B, useRef as R, useEffect as $, useCallback as C } from "react";
3
- import { CodeBlock as z } from "../../data-display/CodeBlock.js";
4
- import { Icon as y } from "../../ui/Icon.js";
5
- import { PromptInput as D } from "../../../blocks/ai/PromptInput.js";
6
- import { Actions as E, Suggestion as F } from "../../../blocks/ai/Actions.js";
7
- import { cn as m } from "../../../utils/cn.js";
8
- import { TelemetryGraph as G } from "../TelemetryGraph/TelemetryGraph.js";
2
+ import { useState as B, useRef as R, useEffect as D, useCallback as N } from "react";
3
+ import { CodeBlock as G } from "../../data-display/CodeBlock.js";
4
+ import { Icon as C } from "../../ui/Icon.js";
5
+ import { PromptInput as $ } from "../../../blocks/ai/PromptInput.js";
6
+ import { Actions as z, Suggestion as E } from "../../../blocks/ai/Actions.js";
7
+ import { cn as p } from "../../../utils/cn.js";
8
+ import { TelemetryGraph as F } from "../TelemetryGraph/TelemetryGraph.js";
9
9
  import { StockChart as S } from "../StockChart/StockChart.js";
10
10
  import { LiveQuoteCard as V } from "../LiveQuoteCard/LiveQuoteCard.js";
11
- import { NewsSummaryCard as O } from "../NewsSummaryCard/NewsSummaryCard.js";
12
- function U(e) {
11
+ import { NewsSummaryCard as M } from "../NewsSummaryCard/NewsSummaryCard.js";
12
+ import { CompanyProfileCard as O } from "../CompanyProfileCard/CompanyProfileCard.js";
13
+ import { CounterpartyGraphCard as U } from "../CounterpartyGraphCard/CounterpartyGraphCard.js";
14
+ import { DivergenceMetricsCard as q } from "../DivergenceMetricsCard/DivergenceMetricsCard.js";
15
+ import { ArchitectureReferenceCard as L } from "../ArchitectureReferenceCard/ArchitectureReferenceCard.js";
16
+ function Q(e) {
13
17
  if (!e) return null;
14
18
  const l = e.split(/(```[\w]*\n[\s\S]*?```)/g);
15
- return /* @__PURE__ */ t(w, { children: l.map((a, o) => {
16
- const n = a.match(/^```([\w]*)\n([\s\S]*?)```$/);
19
+ return /* @__PURE__ */ t(w, { children: l.map((o, a) => {
20
+ const n = o.match(/^```([\w]*)\n([\s\S]*?)```$/);
17
21
  if (n) {
18
- const s = n[1] || "text", i = n[2].replace(/\n$/, "");
19
- return /* @__PURE__ */ t("div", { className: "my-3", children: /* @__PURE__ */ t(z, { language: s, code: i }) }, o);
22
+ const i = n[1] || "text", d = n[2].replace(/\n$/, "");
23
+ return /* @__PURE__ */ t("div", { className: "my-3", children: /* @__PURE__ */ t(G, { language: i, code: d }) }, a);
20
24
  }
21
- return a ? /* @__PURE__ */ t("p", { className: "whitespace-pre-wrap text-sm leading-relaxed", children: a }, o) : null;
25
+ return o ? /* @__PURE__ */ t("p", { className: "whitespace-pre-wrap text-sm leading-relaxed", children: o }, a) : null;
22
26
  }) });
23
27
  }
24
- const q = () => /* @__PURE__ */ t("div", { className: "flex items-center gap-1 px-1 py-0.5", "aria-label": "Assistant is typing", children: [0, 1, 2].map((e) => /* @__PURE__ */ t(
28
+ const W = () => /* @__PURE__ */ t("div", { className: "flex items-center gap-1 px-1 py-0.5", "aria-label": "Assistant is typing", children: [0, 1, 2].map((e) => /* @__PURE__ */ t(
25
29
  "span",
26
30
  {
27
31
  className: "w-1.5 h-1.5 rounded-full bg-muted-foreground/60 animate-bounce",
28
32
  style: { animationDelay: `${e * 0.15}s`, animationDuration: "0.9s" }
29
33
  },
30
34
  e
31
- )) }), L = ({ message: e, isLastAssistant: l, isStreaming: a, renderContent: o }) => {
32
- var u;
33
- const n = e.role === "user", s = !e.content && !e.toolCall && l && a, i = !n && e.toolCall, p = ((u = e.content) == null ? void 0 : u.trim()) && e.content.trim().length > 0, h = !i && (p || s);
34
- return /* @__PURE__ */ c("div", { className: m("flex flex-col gap-2 mb-4", n ? "items-end" : "items-start"), children: [
35
- h && /* @__PURE__ */ c("div", { className: m("flex items-end gap-2", n ? "justify-end" : "justify-start"), children: [
36
- !n && /* @__PURE__ */ t("div", { className: "shrink-0 w-7 h-7 rounded-full bg-primary/10 border border-primary/20 flex items-center justify-center mb-0.5", children: /* @__PURE__ */ t(y, { name: "sparkles", size: 13, className: "text-primary" }) }),
35
+ )) }), H = ({ message: e, isLastAssistant: l, isStreaming: o, renderContent: a }) => {
36
+ var h, s;
37
+ const n = e.role === "user", i = !e.content && !e.toolCall && l && o, d = !n && e.toolCall, u = ((h = e.content) == null ? void 0 : h.trim()) && e.content.trim().length > 0, f = !d && (u || i);
38
+ return /* @__PURE__ */ c("div", { className: p("flex flex-col gap-2 mb-4", n ? "items-end" : "items-start"), children: [
39
+ f && /* @__PURE__ */ c("div", { className: p("flex items-end gap-2", n ? "justify-end" : "justify-start"), children: [
40
+ !n && /* @__PURE__ */ t("div", { className: "shrink-0 w-7 h-7 rounded-full bg-primary/10 border border-primary/20 flex items-center justify-center mb-0.5", children: /* @__PURE__ */ t(C, { name: "sparkles", size: 13, className: "text-primary" }) }),
37
41
  /* @__PURE__ */ t(
38
42
  "div",
39
43
  {
40
- className: m(
44
+ className: p(
41
45
  "relative max-w-[85%] rounded-2xl px-4 py-2.5 text-sm",
42
46
  n ? "rounded-br-sm bg-primary text-primary-foreground" : "rounded-bl-sm bg-muted/60 border border-border/40 text-foreground"
43
47
  ),
44
- children: n ? /* @__PURE__ */ t("p", { className: "whitespace-pre-wrap leading-relaxed", children: e.content }) : s ? /* @__PURE__ */ t(q, {}) : /* @__PURE__ */ c(w, { children: [
45
- o ? o(e.content) : U(e.content),
46
- l && a && e.content && !e.toolCall && /* @__PURE__ */ t(
48
+ children: n ? /* @__PURE__ */ t("p", { className: "whitespace-pre-wrap leading-relaxed", children: e.content }) : i ? /* @__PURE__ */ t(W, {}) : /* @__PURE__ */ c(w, { children: [
49
+ a ? a(e.content) : Q(e.content),
50
+ l && o && e.content && !e.toolCall && /* @__PURE__ */ t(
47
51
  "span",
48
52
  {
49
53
  className: "inline-block w-[2px] h-[1em] bg-current ml-0.5 align-middle animate-pulse",
@@ -54,114 +58,118 @@ const q = () => /* @__PURE__ */ t("div", { className: "flex items-center gap-1 p
54
58
  }
55
59
  )
56
60
  ] }),
57
- i && e.toolCall && /* @__PURE__ */ c("div", { className: "ml-9 w-full max-w-[85%]", children: [
58
- e.toolCall.name === "get_telemetry_graph" && /* @__PURE__ */ t(G, { params: e.toolCall.arguments }),
61
+ d && e.toolCall && /* @__PURE__ */ c("div", { className: "ml-9 w-full max-w-[85%]", children: [
62
+ e.toolCall.name === "get_telemetry_graph" && /* @__PURE__ */ t(F, { params: e.toolCall.arguments }),
59
63
  e.toolCall.name === "get_stock_chart" && /* @__PURE__ */ t(S, { params: e.toolCall.arguments }),
60
64
  e.toolCall.name === "get_live_quote" && /* @__PURE__ */ t(V, { params: e.toolCall.arguments }),
61
- e.toolCall.name === "get_company_news" && /* @__PURE__ */ t(O, { params: e.toolCall.arguments })
65
+ e.toolCall.name === "get_company_news" && /* @__PURE__ */ t(M, { params: e.toolCall.arguments }),
66
+ e.toolCall.name === "get_company_profile" && /* @__PURE__ */ t(O, { ticker: (s = e.toolCall.arguments) == null ? void 0 : s.ticker }),
67
+ e.toolCall.name === "get_counterparty_graph" && /* @__PURE__ */ t(U, { params: e.toolCall.arguments }),
68
+ e.toolCall.name === "get_divergence_metrics" && /* @__PURE__ */ t(q, { params: e.toolCall.arguments }),
69
+ e.toolCall.name === "get_architecture_reference" && /* @__PURE__ */ t(L, {})
62
70
  ] })
63
71
  ] });
64
- }, M = {
72
+ }, J = {
65
73
  idle: { dot: "bg-emerald-500", label: "Ready" },
66
74
  streaming: { dot: "bg-amber-500 animate-pulse", label: "Generating…" },
67
75
  error: { dot: "bg-red-500", label: "Error" }
68
- }, Q = ({ status: e, provider: l, model: a }) => {
69
- const { dot: o, label: n } = M[e];
76
+ }, K = ({ status: e, provider: l, model: o }) => {
77
+ const { dot: a, label: n } = J[e];
70
78
  return /* @__PURE__ */ c("div", { className: "shrink-0 flex items-center justify-between px-3 py-1.5 border-b border-border/50 bg-muted/20", children: [
71
79
  /* @__PURE__ */ c("div", { className: "flex items-center gap-2", children: [
72
- /* @__PURE__ */ t("span", { className: `w-2 h-2 rounded-full ${o}` }),
80
+ /* @__PURE__ */ t("span", { className: `w-2 h-2 rounded-full ${a}` }),
73
81
  /* @__PURE__ */ t("span", { className: "text-[10px] font-semibold uppercase tracking-widest opacity-60", children: n })
74
82
  ] }),
75
- (l || a) && /* @__PURE__ */ t("span", { className: "text-[10px] font-mono opacity-50 truncate max-w-[200px]", children: [l, a].filter(Boolean).join(" · ") })
83
+ (l || o) && /* @__PURE__ */ t("span", { className: "text-[10px] font-mono opacity-50 truncate max-w-[200px]", children: [l, o].filter(Boolean).join(" · ") })
76
84
  ] });
77
- }, le = ({
85
+ }, me = ({
78
86
  messages: e,
79
87
  isStreaming: l,
80
- onSubmit: a,
81
- error: o = null,
88
+ onSubmit: o,
89
+ error: a = null,
82
90
  activeProvider: n,
83
- activeModel: s,
84
- connectionStatus: i,
85
- renderMessage: p,
86
- placeholder: h = "Ask Ramme AI...",
87
- className: u,
88
- suggestions: f,
91
+ activeModel: i,
92
+ connectionStatus: d,
93
+ renderMessage: u,
94
+ placeholder: f = "Ask AI…",
95
+ className: h,
96
+ suggestions: s,
89
97
  onSuggestionClick: k
90
98
  }) => {
91
- const I = i ?? (o ? "error" : l ? "streaming" : "idle"), [b, v] = B(""), N = R(null);
92
- $(() => {
99
+ const _ = d ?? (a ? "error" : l ? "streaming" : "idle"), [b, y] = B(""), v = R(null);
100
+ D(() => {
93
101
  var r;
94
- (r = N.current) == null || r.scrollIntoView({ behavior: "smooth", block: "end" });
102
+ (r = v.current) == null || r.scrollIntoView({ behavior: "smooth", block: "end" });
95
103
  }, [e.length, l]);
96
- const _ = C(
97
- (r) => v(r.target.value),
104
+ const I = N(
105
+ (r) => y(r.target.value),
98
106
  []
99
- ), A = C(
107
+ ), A = N(
100
108
  (r) => {
101
109
  r.preventDefault();
102
- const d = b.trim();
103
- !d || l || (a(d), v(""));
110
+ const m = b.trim();
111
+ !m || l || (o(m), y(""));
104
112
  },
105
- [b, l, a]
113
+ [b, l, o]
106
114
  ), j = e.reduce(
107
- (r, d, x) => d.role === "assistant" ? x : r,
115
+ (r, m, x) => m.role === "assistant" ? x : r,
108
116
  -1
109
117
  ), g = e.filter((r) => r.role !== "system");
110
118
  return /* @__PURE__ */ c(
111
119
  "div",
112
120
  {
113
- className: m(
121
+ className: p(
114
122
  "flex flex-col h-full bg-background text-foreground overflow-hidden",
115
- u
123
+ h
116
124
  ),
117
125
  children: [
118
- (n || s || l || o) && /* @__PURE__ */ t(
119
- Q,
126
+ (n || i || l || a) && /* @__PURE__ */ t(
127
+ K,
120
128
  {
121
- status: I,
129
+ status: _,
122
130
  provider: n,
123
- model: s
131
+ model: i
124
132
  }
125
133
  ),
126
134
  /* @__PURE__ */ c("div", { className: "flex-1 overflow-y-auto px-4 py-4 scroll-smooth [scrollbar-width:thin] [scrollbar-color:hsl(var(--border))_transparent]", children: [
127
135
  g.length === 0 && /* @__PURE__ */ c("div", { className: "flex flex-col items-center justify-center h-full gap-2 text-muted-foreground/50 select-none", children: [
128
- /* @__PURE__ */ t(y, { name: "sparkles", size: 28 }),
136
+ /* @__PURE__ */ t(C, { name: "sparkles", size: 28 }),
129
137
  /* @__PURE__ */ t("p", { className: "text-sm", children: "Start a conversation" }),
130
- f && f.length > 0 && /* @__PURE__ */ t("div", { className: "mt-2 select-auto", children: /* @__PURE__ */ t(E, { children: f.map((r) => /* @__PURE__ */ t(F, { onClick: () => (k ?? a)(r), children: r }, r)) }) })
138
+ s && s.length > 0 && /* @__PURE__ */ t("div", { className: "mt-2 select-auto", children: /* @__PURE__ */ t(z, { children: s.map((r) => /* @__PURE__ */ t(E, { onClick: () => (k ?? o)(r), children: r }, r)) }) })
131
139
  ] }),
132
- g.map((r, d) => {
140
+ g.map((r, m) => {
133
141
  const x = e.indexOf(r);
134
142
  return /* @__PURE__ */ t(
135
- L,
143
+ H,
136
144
  {
137
145
  message: r,
138
146
  isLastAssistant: x === j,
139
147
  isStreaming: l,
140
- renderContent: p ? (T) => p(T, r.role) : void 0
148
+ renderContent: u ? (T) => u(T, r.role) : void 0
141
149
  },
142
- d
150
+ m
143
151
  );
144
152
  }),
145
- /* @__PURE__ */ t("div", { ref: N })
153
+ /* @__PURE__ */ t("div", { ref: v })
146
154
  ] }),
147
- o && /* @__PURE__ */ c("div", { className: "shrink-0 mx-3 mb-2 flex items-start gap-2 rounded-lg border border-destructive/40 bg-destructive/10 px-3 py-2 text-xs text-destructive", children: [
148
- /* @__PURE__ */ t(y, { name: "alert-circle", size: 14, className: "mt-px shrink-0" }),
149
- /* @__PURE__ */ t("span", { className: "leading-snug", children: o })
155
+ a && /* @__PURE__ */ c("div", { className: "shrink-0 mx-3 mb-2 flex items-start gap-2 rounded-lg border border-destructive/40 bg-destructive/10 px-3 py-2 text-xs text-destructive", children: [
156
+ /* @__PURE__ */ t(C, { name: "alert-circle", size: 14, className: "mt-px shrink-0" }),
157
+ /* @__PURE__ */ t("span", { className: "leading-snug", children: a })
150
158
  ] }),
151
159
  /* @__PURE__ */ t(
152
160
  "div",
153
161
  {
154
- className: m(
162
+ className: p(
155
163
  "shrink-0 border-t border-border/60 bg-background/80 backdrop-blur-sm transition-opacity",
156
164
  l && "opacity-70"
157
165
  ),
158
166
  children: /* @__PURE__ */ t(
159
- D,
167
+ $,
160
168
  {
161
169
  value: b,
162
- onChange: _,
170
+ onChange: I,
163
171
  onSubmit: A,
164
- placeholder: l ? "Waiting for response…" : h
172
+ placeholder: l ? "Waiting for response…" : f
165
173
  }
166
174
  )
167
175
  }
@@ -171,5 +179,5 @@ const q = () => /* @__PURE__ */ t("div", { className: "flex items-center gap-1 p
171
179
  );
172
180
  };
173
181
  export {
174
- le as AIChatThread
182
+ me as AIChatThread
175
183
  };
@@ -0,0 +1,28 @@
1
+ /**
2
+ * @file ArchitectureReferenceCard.tsx
3
+ * @package @ramme-io/ui
4
+ * @description AI-generated platform architecture summary card
5
+ *
6
+ * ARCHITECTURAL ROLE:
7
+ * Renders a condensed summary of this platform's own data architecture
8
+ * (stack, table count, AI pipelines, sentinel fleet, live scale facts)
9
+ * inside AI chat bubbles. Fetches from the Ramme Data Factory API's
10
+ * /architecture/reference endpoint. Follows the same self-fetching
11
+ * pattern as LiveQuoteCard — takes no ticker, since it describes the
12
+ * system itself rather than a company. Full detail lives on the Ops
13
+ * console's Architecture Reference page; this card is a chat-sized digest.
14
+ */
15
+ import React from 'react';
16
+ export interface ArchitectureReferenceCardProps {
17
+ /** Present for signature symmetry with other tool cards; the tool takes no arguments. */
18
+ params?: Record<string, never>;
19
+ }
20
+ /**
21
+ * @wizard
22
+ * @name ArchitectureReferenceCard
23
+ * @description AI-generated card summarizing this platform's own data architecture — stack, data model, AI pipelines, and sentinel fleet
24
+ * @tags ai, architecture, reference, generative-ui
25
+ * @category ai
26
+ * @id architecture-reference-card
27
+ */
28
+ export declare const ArchitectureReferenceCard: React.FC<ArchitectureReferenceCardProps>;
@@ -0,0 +1,70 @@
1
+ import { jsxs as r, jsx as e } from "react/jsx-runtime";
2
+ import { useState as c, useEffect as x } from "react";
3
+ import { Card as h, CardHeader as b, CardTitle as g, CardContent as N } from "../../layout/Card.js";
4
+ import { Icon as n } from "../../ui/Icon.js";
5
+ const o = { BASE_URL: "/", DEV: !1, MODE: "production", PROD: !0, SSR: !1 }, E = () => {
6
+ const [t, u] = c(null), [l, i] = c(!0), [d, m] = c(null);
7
+ x(() => {
8
+ (async () => {
9
+ try {
10
+ i(!0), m(null);
11
+ const s = (o == null ? void 0 : o.VITE_API_URL) ?? "http://localhost:8000", p = await fetch(`${s}/architecture/reference`);
12
+ if (!p.ok)
13
+ throw new Error("Could not load the architecture reference");
14
+ u(await p.json());
15
+ } catch (s) {
16
+ m(s instanceof Error ? s.message : "Failed to fetch architecture reference");
17
+ } finally {
18
+ i(!1);
19
+ }
20
+ })();
21
+ }, []);
22
+ const f = (t == null ? void 0 : t.data_model.groups.reduce((a, s) => a + s.tables.length, 0)) ?? 0;
23
+ return /* @__PURE__ */ r(h, { className: "w-full min-w-[280px] max-w-md shadow-lg border-primary/20", children: [
24
+ /* @__PURE__ */ e(b, { className: "pb-3", children: /* @__PURE__ */ r(g, { className: "text-sm font-medium text-muted-foreground flex items-center gap-2", children: [
25
+ /* @__PURE__ */ e(n, { name: "book-open", size: 14 }),
26
+ "Platform Architecture"
27
+ ] }) }),
28
+ /* @__PURE__ */ r(N, { className: "pt-0", children: [
29
+ l && /* @__PURE__ */ e("div", { className: "flex items-center justify-center py-8", children: /* @__PURE__ */ e(n, { name: "loader", size: 24, className: "animate-spin text-muted-foreground" }) }),
30
+ d && /* @__PURE__ */ r("div", { className: "flex items-start gap-2 rounded-lg border border-destructive/40 bg-destructive/10 px-3 py-2 text-xs text-destructive", children: [
31
+ /* @__PURE__ */ e(n, { name: "alert-circle", size: 14, className: "mt-px shrink-0" }),
32
+ /* @__PURE__ */ e("span", { children: d })
33
+ ] }),
34
+ t && !l && !d && /* @__PURE__ */ r("div", { className: "space-y-3", children: [
35
+ /* @__PURE__ */ r("div", { className: "grid grid-cols-3 gap-2", children: [
36
+ /* @__PURE__ */ r("div", { className: "rounded-md border border-border/60 bg-muted/20 p-2 text-center", children: [
37
+ /* @__PURE__ */ e("p", { className: "font-mono text-sm font-semibold tabular-nums", children: f }),
38
+ /* @__PURE__ */ e("p", { className: "text-[10px] text-muted-foreground", children: "tables" })
39
+ ] }),
40
+ /* @__PURE__ */ r("div", { className: "rounded-md border border-border/60 bg-muted/20 p-2 text-center", children: [
41
+ /* @__PURE__ */ e("p", { className: "font-mono text-sm font-semibold tabular-nums", children: t.ai_pipelines.length }),
42
+ /* @__PURE__ */ e("p", { className: "text-[10px] text-muted-foreground", children: "AI pipelines" })
43
+ ] }),
44
+ /* @__PURE__ */ r("div", { className: "rounded-md border border-border/60 bg-muted/20 p-2 text-center", children: [
45
+ /* @__PURE__ */ e("p", { className: "font-mono text-sm font-semibold tabular-nums", children: t.pm2_processes.length }),
46
+ /* @__PURE__ */ e("p", { className: "text-[10px] text-muted-foreground", children: "workers" })
47
+ ] })
48
+ ] }),
49
+ /* @__PURE__ */ r("div", { className: "space-y-1", children: [
50
+ /* @__PURE__ */ e("p", { className: "text-[10px] font-semibold uppercase tracking-wide text-muted-foreground", children: "Stack" }),
51
+ /* @__PURE__ */ r("p", { className: "text-xs text-foreground/90 leading-relaxed", children: [
52
+ t.stack.backend[0],
53
+ t.stack.frontend[0] ? ` · ${t.stack.frontend[0]}` : ""
54
+ ] })
55
+ ] }),
56
+ /* @__PURE__ */ r("div", { className: "space-y-1", children: [
57
+ /* @__PURE__ */ e("p", { className: "text-[10px] font-semibold uppercase tracking-wide text-muted-foreground", children: "AI / LLM providers" }),
58
+ /* @__PURE__ */ e("div", { className: "flex flex-wrap gap-1", children: t.stack.ai_llm_providers.map((a) => /* @__PURE__ */ e("span", { className: "rounded border border-border/60 bg-muted/20 px-1.5 py-0.5 font-mono text-[10px]", children: a }, a)) })
59
+ ] }),
60
+ t.scale_facts.db_size_gb !== null && /* @__PURE__ */ r("p", { className: "text-[10px] text-muted-foreground pt-1 border-t border-border/60", children: [
61
+ t.scale_facts.db_size_gb,
62
+ " GB database · see Ops → Architecture Reference for full detail"
63
+ ] })
64
+ ] })
65
+ ] })
66
+ ] });
67
+ };
68
+ export {
69
+ E as ArchitectureReferenceCard
70
+ };
@@ -0,0 +1,2 @@
1
+ export { ArchitectureReferenceCard } from './ArchitectureReferenceCard';
2
+ export type { ArchitectureReferenceCardProps } from './ArchitectureReferenceCard';
@@ -0,0 +1,30 @@
1
+ /**
2
+ * @file CounterpartyGraphCard.tsx
3
+ * @package @ramme-io/ui
4
+ * @description AI-generated counterparty relationship card
5
+ *
6
+ * ARCHITECTURAL ROLE:
7
+ * Renders Fleet-Brain-Deep's inferred counterparty graph inside AI chat
8
+ * bubbles. Fetches from the Ramme Data Factory API's
9
+ * /fleet/counterparties/{ticker} endpoint. Follows the same self-fetching
10
+ * pattern as LiveQuoteCard — no product-layer data plumbing required.
11
+ */
12
+ import React from 'react';
13
+ interface CounterpartyGraphParams {
14
+ ticker: string;
15
+ hops?: number;
16
+ }
17
+ export interface CounterpartyGraphCardProps {
18
+ /** Parameters from the LLM tool call */
19
+ params: CounterpartyGraphParams;
20
+ }
21
+ /**
22
+ * @wizard
23
+ * @name CounterpartyGraphCard
24
+ * @description AI-generated counterparty relationship card showing suppliers, customers, partners, and competitors inferred from alternative signals
25
+ * @tags ai, counterparty, graph, relationships, generative-ui
26
+ * @category ai
27
+ * @id counterparty-graph-card
28
+ */
29
+ export declare const CounterpartyGraphCard: React.FC<CounterpartyGraphCardProps>;
30
+ export {};
@@ -0,0 +1,82 @@
1
+ import { jsxs as r, jsx as s } from "react/jsx-runtime";
2
+ import { useState as i, useEffect as w } from "react";
3
+ import { Card as N, CardHeader as b, CardTitle as C, CardContent as E } from "../../layout/Card.js";
4
+ import { Icon as l } from "../../ui/Icon.js";
5
+ const p = { BASE_URL: "/", DEV: !1, MODE: "production", PROD: !0, SSR: !1 }, k = {
6
+ supplies_to: "Supplies to",
7
+ purchases_from: "Purchases from",
8
+ partners_with: "Partners with",
9
+ competes_with: "Competes with",
10
+ regulated_by: "Regulated by",
11
+ invests_in: "Invests in",
12
+ acquires: "Acquires",
13
+ same_as: "Also known as"
14
+ }, L = ({ params: x }) => {
15
+ const { ticker: n, hops: d } = x, [a, g] = i(null), [m, u] = i(!0), [o, h] = i(null);
16
+ w(() => {
17
+ (async () => {
18
+ try {
19
+ u(!0), h(null);
20
+ const e = (p == null ? void 0 : p.VITE_API_URL) ?? "http://localhost:8000", f = await fetch(
21
+ `${e}/fleet/counterparties/${n.toUpperCase()}?hops=${d ?? 1}`
22
+ );
23
+ if (!f.ok)
24
+ throw new Error(`No counterparty data available for ${n.toUpperCase()}`);
25
+ g(await f.json());
26
+ } catch (e) {
27
+ h(e instanceof Error ? e.message : "Failed to fetch counterparty graph");
28
+ } finally {
29
+ u(!1);
30
+ }
31
+ })();
32
+ }, [n, d]);
33
+ const y = new Map(((a == null ? void 0 : a.nodes) ?? []).map((t) => [t.id, t])), c = (a == null ? void 0 : a.edges) ?? [];
34
+ return /* @__PURE__ */ r(N, { className: "w-full min-w-[280px] max-w-md shadow-lg border-primary/20", children: [
35
+ /* @__PURE__ */ s(b, { className: "pb-3", children: /* @__PURE__ */ r(C, { className: "text-sm font-medium text-muted-foreground flex items-center gap-2", children: [
36
+ /* @__PURE__ */ s(l, { name: "share-2", size: 14 }),
37
+ "Counterparty Network — ",
38
+ n.toUpperCase()
39
+ ] }) }),
40
+ /* @__PURE__ */ r(E, { className: "pt-0", children: [
41
+ m && /* @__PURE__ */ s("div", { className: "flex items-center justify-center py-8", children: /* @__PURE__ */ s(l, { name: "loader", size: 24, className: "animate-spin text-muted-foreground" }) }),
42
+ o && /* @__PURE__ */ r("div", { className: "flex items-start gap-2 rounded-lg border border-destructive/40 bg-destructive/10 px-3 py-2 text-xs text-destructive", children: [
43
+ /* @__PURE__ */ s(l, { name: "alert-circle", size: 14, className: "mt-px shrink-0" }),
44
+ /* @__PURE__ */ s("span", { children: o })
45
+ ] }),
46
+ !m && !o && c.length === 0 && /* @__PURE__ */ r("p", { className: "text-xs text-muted-foreground py-2", children: [
47
+ "No counterparty relationships inferred yet for ",
48
+ n.toUpperCase(),
49
+ "."
50
+ ] }),
51
+ c.length > 0 && /* @__PURE__ */ s("div", { className: "space-y-1.5 max-h-72 overflow-y-auto", children: c.map((t) => {
52
+ const e = y.get(t.target_id);
53
+ return e ? /* @__PURE__ */ r(
54
+ "div",
55
+ {
56
+ className: "flex items-center justify-between gap-2 rounded-md border border-border/60 bg-muted/20 px-2.5 py-1.5",
57
+ children: [
58
+ /* @__PURE__ */ r("div", { className: "min-w-0", children: [
59
+ /* @__PURE__ */ r("span", { className: "text-xs font-semibold text-foreground truncate block", children: [
60
+ e.public_name ?? e.name,
61
+ e.ticker && e.resolution === "public" && /* @__PURE__ */ s("span", { className: "ml-1.5 font-mono text-primary", children: e.ticker.toUpperCase() })
62
+ ] }),
63
+ /* @__PURE__ */ r("span", { className: "text-[10px] font-mono text-muted-foreground uppercase tracking-wide", children: [
64
+ k[t.edge_type] ?? t.edge_type,
65
+ t.hop === 2 && /* @__PURE__ */ s("span", { className: "ml-1.5 opacity-70", children: "· 2nd degree" })
66
+ ] })
67
+ ] }),
68
+ /* @__PURE__ */ r("span", { className: "text-[10px] font-mono text-muted-foreground shrink-0", children: [
69
+ Math.round(t.weight * 100),
70
+ "%"
71
+ ] })
72
+ ]
73
+ },
74
+ t.id
75
+ ) : null;
76
+ }) })
77
+ ] })
78
+ ] });
79
+ };
80
+ export {
81
+ L as CounterpartyGraphCard
82
+ };
@@ -0,0 +1,2 @@
1
+ export { CounterpartyGraphCard } from './CounterpartyGraphCard';
2
+ export type { CounterpartyGraphCardProps } from './CounterpartyGraphCard';
@@ -0,0 +1,29 @@
1
+ /**
2
+ * @file DivergenceMetricsCard.tsx
3
+ * @package @ramme-io/ui
4
+ * @description AI-generated operational/customer divergence card
5
+ *
6
+ * ARCHITECTURAL ROLE:
7
+ * Renders Fleet-Brain-Deep's divergence scoring (signed delta between
8
+ * expected/baseline and observed performance) inside AI chat bubbles.
9
+ * Fetches from the Ramme Data Factory API's /fleet/divergence/{ticker}
10
+ * endpoint. Follows the same self-fetching pattern as LiveQuoteCard.
11
+ */
12
+ import React from 'react';
13
+ interface DivergenceMetricsParams {
14
+ ticker: string;
15
+ }
16
+ export interface DivergenceMetricsCardProps {
17
+ /** Parameters from the LLM tool call */
18
+ params: DivergenceMetricsParams;
19
+ }
20
+ /**
21
+ * @wizard
22
+ * @name DivergenceMetricsCard
23
+ * @description AI-generated card showing operational and customer divergence scores — a signed delta between expected and observed performance
24
+ * @tags ai, divergence, metrics, generative-ui
25
+ * @category ai
26
+ * @id divergence-metrics-card
27
+ */
28
+ export declare const DivergenceMetricsCard: React.FC<DivergenceMetricsCardProps>;
29
+ export {};
@@ -0,0 +1,69 @@
1
+ import { jsxs as s, jsx as t } from "react/jsx-runtime";
2
+ import { useState as c, useEffect as v } from "react";
3
+ import { Card as N, CardHeader as b, CardTitle as y, CardContent as C } from "../../layout/Card.js";
4
+ import { Icon as d } from "../../ui/Icon.js";
5
+ const l = { BASE_URL: "/", DEV: !1, MODE: "production", PROD: !0, SSR: !1 }, E = {
6
+ operations: "Operations",
7
+ customer: "Customer",
8
+ operational: "Operations",
9
+ ux: "Customer"
10
+ }, R = ({ params: x }) => {
11
+ const { ticker: a } = x, [g, h] = c(null), [m, p] = c(!0), [i, u] = c(null);
12
+ v(() => {
13
+ (async () => {
14
+ try {
15
+ p(!0), u(null);
16
+ const r = (l == null ? void 0 : l.VITE_API_URL) ?? "http://localhost:8000", o = await fetch(`${r}/fleet/divergence/${a.toUpperCase()}`);
17
+ if (!o.ok)
18
+ throw new Error(`No divergence data available for ${a.toUpperCase()}`);
19
+ h(await o.json());
20
+ } catch (r) {
21
+ u(r instanceof Error ? r.message : "Failed to fetch divergence metrics");
22
+ } finally {
23
+ p(!1);
24
+ }
25
+ })();
26
+ }, [a]);
27
+ const n = /* @__PURE__ */ new Map();
28
+ return (g ?? []).forEach((e) => {
29
+ n.has(e.metric) || n.set(e.metric, e);
30
+ }), /* @__PURE__ */ s(N, { className: "w-full min-w-[280px] max-w-md shadow-lg border-primary/20", children: [
31
+ /* @__PURE__ */ t(b, { className: "pb-3", children: /* @__PURE__ */ s(y, { className: "text-sm font-medium text-muted-foreground flex items-center gap-2", children: [
32
+ /* @__PURE__ */ t(d, { name: "activity", size: 14 }),
33
+ "Signal Impact — ",
34
+ a.toUpperCase()
35
+ ] }) }),
36
+ /* @__PURE__ */ s(C, { className: "pt-0", children: [
37
+ m && /* @__PURE__ */ t("div", { className: "flex items-center justify-center py-8", children: /* @__PURE__ */ t(d, { name: "loader", size: 24, className: "animate-spin text-muted-foreground" }) }),
38
+ i && /* @__PURE__ */ s("div", { className: "flex items-start gap-2 rounded-lg border border-destructive/40 bg-destructive/10 px-3 py-2 text-xs text-destructive", children: [
39
+ /* @__PURE__ */ t(d, { name: "alert-circle", size: 14, className: "mt-px shrink-0" }),
40
+ /* @__PURE__ */ t("span", { children: i })
41
+ ] }),
42
+ !m && !i && n.size === 0 && /* @__PURE__ */ s("p", { className: "text-xs text-muted-foreground py-2", children: [
43
+ "No divergence readings yet for ",
44
+ a.toUpperCase(),
45
+ "."
46
+ ] }),
47
+ n.size > 0 && /* @__PURE__ */ t("div", { className: "space-y-2", children: Array.from(n.values()).map((e) => {
48
+ var f;
49
+ const r = e.score > 0, o = e.score === 0;
50
+ return /* @__PURE__ */ s("div", { className: "rounded-md border border-border/60 bg-muted/20 p-2.5 space-y-1", children: [
51
+ /* @__PURE__ */ s("div", { className: "flex items-center justify-between", children: [
52
+ /* @__PURE__ */ t("span", { className: "text-xs font-semibold uppercase tracking-wide text-foreground", children: E[e.metric] }),
53
+ /* @__PURE__ */ t(
54
+ "span",
55
+ {
56
+ className: `text-xs font-mono font-semibold ${o ? "text-muted-foreground" : r ? "text-green-500" : "text-red-500"}`,
57
+ children: o ? "—" : `${r ? "+" : ""}${e.score.toFixed(0)}`
58
+ }
59
+ )
60
+ ] }),
61
+ ((f = e.contributing_signals[0]) == null ? void 0 : f.reason) && /* @__PURE__ */ t("p", { className: "text-[10px] text-muted-foreground leading-relaxed", children: e.contributing_signals[0].reason })
62
+ ] }, e.metric);
63
+ }) })
64
+ ] })
65
+ ] });
66
+ };
67
+ export {
68
+ R as DivergenceMetricsCard
69
+ };
@@ -0,0 +1,2 @@
1
+ export { DivergenceMetricsCard } from './DivergenceMetricsCard';
2
+ export type { DivergenceMetricsCardProps } from './DivergenceMetricsCard';
@@ -1,3 +1,13 @@
1
+ /**
2
+ * @wizard
3
+ * @name KeyInjectionOverlay
4
+ * @description Blocks the app and collects an AI provider key when the gateway reports one is missing or expired. Strategic purpose: the BYOK prompt, in one place, so a key request looks the same everywhere and never becomes an inline form somebody rebuilds per feature. Renders nothing unless status is 'BYOK_REQUIRED' or 'KEY_EXPIRED', so it can stay mounted at the shell level.
5
+ * @tags ai, byok, overlay, auth, gateway, key
6
+ * @category ai
7
+ * @id key-injection-overlay
8
+ * @param {string} status - Gateway status. The overlay shows only for 'BYOK_REQUIRED' or 'KEY_EXPIRED'.
9
+ * @param {function} setSessionKey - Receives the entered key when the form is submitted.
10
+ */
1
11
  export interface KeyInjectionOverlayProps {
2
12
  status: string;
3
13
  setSessionKey: (key: string) => void;