@darqlabs/curator-sdk-react 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (76) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +205 -0
  3. package/dist/cjs/CuratorAdapter.d.ts +28 -0
  4. package/dist/cjs/CuratorAdapter.d.ts.map +1 -0
  5. package/dist/cjs/CuratorAdapter.js +100 -0
  6. package/dist/cjs/CuratorAdapter.js.map +1 -0
  7. package/dist/cjs/CuratorChat.d.ts +70 -0
  8. package/dist/cjs/CuratorChat.d.ts.map +1 -0
  9. package/dist/cjs/CuratorChat.js +454 -0
  10. package/dist/cjs/CuratorChat.js.map +1 -0
  11. package/dist/cjs/CuratorChatLauncher.d.ts +57 -0
  12. package/dist/cjs/CuratorChatLauncher.d.ts.map +1 -0
  13. package/dist/cjs/CuratorChatLauncher.js +134 -0
  14. package/dist/cjs/CuratorChatLauncher.js.map +1 -0
  15. package/dist/cjs/CuratorProvider.d.ts +37 -0
  16. package/dist/cjs/CuratorProvider.d.ts.map +1 -0
  17. package/dist/cjs/CuratorProvider.js +49 -0
  18. package/dist/cjs/CuratorProvider.js.map +1 -0
  19. package/dist/cjs/Markdown.d.ts +16 -0
  20. package/dist/cjs/Markdown.d.ts.map +1 -0
  21. package/dist/cjs/Markdown.js +18 -0
  22. package/dist/cjs/Markdown.js.map +1 -0
  23. package/dist/cjs/brand.d.ts +26 -0
  24. package/dist/cjs/brand.d.ts.map +1 -0
  25. package/dist/cjs/brand.js +47 -0
  26. package/dist/cjs/brand.js.map +1 -0
  27. package/dist/cjs/index.d.ts +10 -0
  28. package/dist/cjs/index.d.ts.map +1 -0
  29. package/dist/cjs/index.js +17 -0
  30. package/dist/cjs/index.js.map +1 -0
  31. package/dist/cjs/normalizeMarkdown.d.ts +24 -0
  32. package/dist/cjs/normalizeMarkdown.d.ts.map +1 -0
  33. package/dist/cjs/normalizeMarkdown.js +111 -0
  34. package/dist/cjs/normalizeMarkdown.js.map +1 -0
  35. package/dist/cjs/useCuratorChat.d.ts +79 -0
  36. package/dist/cjs/useCuratorChat.d.ts.map +1 -0
  37. package/dist/cjs/useCuratorChat.js +135 -0
  38. package/dist/cjs/useCuratorChat.js.map +1 -0
  39. package/dist/esm/CuratorAdapter.d.ts +28 -0
  40. package/dist/esm/CuratorAdapter.d.ts.map +1 -0
  41. package/dist/esm/CuratorAdapter.js +97 -0
  42. package/dist/esm/CuratorAdapter.js.map +1 -0
  43. package/dist/esm/CuratorChat.d.ts +70 -0
  44. package/dist/esm/CuratorChat.d.ts.map +1 -0
  45. package/dist/esm/CuratorChat.js +451 -0
  46. package/dist/esm/CuratorChat.js.map +1 -0
  47. package/dist/esm/CuratorChatLauncher.d.ts +57 -0
  48. package/dist/esm/CuratorChatLauncher.d.ts.map +1 -0
  49. package/dist/esm/CuratorChatLauncher.js +131 -0
  50. package/dist/esm/CuratorChatLauncher.js.map +1 -0
  51. package/dist/esm/CuratorProvider.d.ts +37 -0
  52. package/dist/esm/CuratorProvider.d.ts.map +1 -0
  53. package/dist/esm/CuratorProvider.js +44 -0
  54. package/dist/esm/CuratorProvider.js.map +1 -0
  55. package/dist/esm/Markdown.d.ts +16 -0
  56. package/dist/esm/Markdown.d.ts.map +1 -0
  57. package/dist/esm/Markdown.js +12 -0
  58. package/dist/esm/Markdown.js.map +1 -0
  59. package/dist/esm/brand.d.ts +26 -0
  60. package/dist/esm/brand.d.ts.map +1 -0
  61. package/dist/esm/brand.js +43 -0
  62. package/dist/esm/brand.js.map +1 -0
  63. package/dist/esm/index.d.ts +10 -0
  64. package/dist/esm/index.d.ts.map +1 -0
  65. package/dist/esm/index.js +6 -0
  66. package/dist/esm/index.js.map +1 -0
  67. package/dist/esm/normalizeMarkdown.d.ts +24 -0
  68. package/dist/esm/normalizeMarkdown.d.ts.map +1 -0
  69. package/dist/esm/normalizeMarkdown.js +108 -0
  70. package/dist/esm/normalizeMarkdown.js.map +1 -0
  71. package/dist/esm/package.json +3 -0
  72. package/dist/esm/useCuratorChat.d.ts +79 -0
  73. package/dist/esm/useCuratorChat.d.ts.map +1 -0
  74. package/dist/esm/useCuratorChat.js +132 -0
  75. package/dist/esm/useCuratorChat.js.map +1 -0
  76. package/package.json +66 -0
@@ -0,0 +1,454 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.CuratorChat = CuratorChat;
4
+ const jsx_runtime_1 = require("react/jsx-runtime");
5
+ /**
6
+ * <CuratorChat /> — drop-in chat widget backed by a Curator SDK client.
7
+ *
8
+ * <CuratorChat curator={curator} agent="support-bot" />
9
+ *
10
+ * Internals are powered by `@assistant-ui/react` — `useLocalRuntime`
11
+ * wraps our `CuratorAdapter`, which delegates each user turn to
12
+ * `chat.stream(...)` for token-by-token rendering. The outer chrome
13
+ * (header, brand footer, theme tokens, close button) and the bubble
14
+ * layout stay ours so the widget keeps its identity across themes.
15
+ */
16
+ const react_1 = require("react");
17
+ const react_2 = require("@assistant-ui/react");
18
+ const CuratorProvider_js_1 = require("./CuratorProvider.js");
19
+ const CuratorAdapter_js_1 = require("./CuratorAdapter.js");
20
+ const brand_js_1 = require("./brand.js");
21
+ const Markdown_js_1 = require("./Markdown.js");
22
+ function CuratorChat(props) {
23
+ const { curator, agent, project, environment, system, conversationId, title = "Chat", placeholder = "Type a message…", welcomeMessage, theme = "light", className, style, onClose, loadingIndicator, onMessage, onError, enableRetry = false, enableCopy = false, } = props;
24
+ const contextClient = (0, CuratorProvider_js_1.useCuratorOrNull)();
25
+ const client = curator ?? contextClient;
26
+ if (!client) {
27
+ throw new Error("CuratorChat requires a Curator client. Either pass `curator` explicitly " +
28
+ "or wrap your app in <CuratorProvider client={curator}>.");
29
+ }
30
+ // Build a stable Chat handle per addressing input. Recreating on any
31
+ // change wipes the runtime so two agents can't share message history.
32
+ const chat = (0, react_1.useMemo)(() => {
33
+ const a = client.agent(agent, { project, environment, system });
34
+ return conversationId ? a.conversation(conversationId) : a.chat();
35
+ }, [client, agent, project, environment, system, conversationId]);
36
+ const adapter = (0, react_1.useMemo)(() => (0, CuratorAdapter_js_1.createCuratorAdapter)(chat, { onMessage, onError }), [chat, onMessage, onError]);
37
+ const runtime = (0, react_2.useLocalRuntime)(adapter);
38
+ // Branding is a server-resolved entitlement (org subscription tier), not a
39
+ // client prop — the widget runs on the customer's own page, so a local
40
+ // boolean would be trivially flippable. We fetch the deployment config on
41
+ // mount and hold the footer until it resolves: showing it and then hiding
42
+ // it would flash "Powered by Curator" on every load for white-label
43
+ // customers. `null` = not yet known → render nothing; on fetch failure we
44
+ // fall open to showing the footer (protects our branding for the common
45
+ // non-white-label case, where the fetch failing shouldn't strip it).
46
+ const [hidePoweredBy, setHidePoweredBy] = (0, react_1.useState)(null);
47
+ (0, react_1.useEffect)(() => {
48
+ let cancelled = false;
49
+ client
50
+ .agent(agent, { project, environment, system })
51
+ .config()
52
+ .then((cfg) => {
53
+ if (!cancelled)
54
+ setHidePoweredBy(cfg.branding.hidePoweredBy);
55
+ })
56
+ .catch(() => {
57
+ if (!cancelled)
58
+ setHidePoweredBy(false);
59
+ });
60
+ return () => {
61
+ cancelled = true;
62
+ };
63
+ }, [client, agent, project, environment, system]);
64
+ const palette = theme === "dark" ? DARK_VARS : LIGHT_VARS;
65
+ const wrapperStyle = { ...palette, ...containerStyle, ...style };
66
+ return ((0, jsx_runtime_1.jsxs)("div", { className: className, style: wrapperStyle, "data-curator-chat": true, "data-theme": theme, children: [(0, jsx_runtime_1.jsx)(Header, { title: title, onClose: onClose }), (0, jsx_runtime_1.jsx)(LoadingIndicatorContext.Provider, { value: loadingIndicator ?? (0, jsx_runtime_1.jsx)(TypingDots, {}), children: (0, jsx_runtime_1.jsx)(RetryEnabledContext.Provider, { value: enableRetry, children: (0, jsx_runtime_1.jsx)(CopyEnabledContext.Provider, { value: enableCopy, children: (0, jsx_runtime_1.jsx)(react_2.AssistantRuntimeProvider, { runtime: runtime, children: (0, jsx_runtime_1.jsxs)(react_2.ThreadPrimitive.Root, { style: threadRootStyle, children: [(0, jsx_runtime_1.jsxs)(react_2.ThreadPrimitive.Viewport, { autoScroll: true, style: viewportStyle, children: [(0, jsx_runtime_1.jsx)(react_2.ThreadPrimitive.Empty, { children: welcomeMessage ? (0, jsx_runtime_1.jsx)(Welcome, { text: welcomeMessage }) : null }), (0, jsx_runtime_1.jsx)(react_2.ThreadPrimitive.Messages, { components: {
67
+ UserMessage,
68
+ AssistantMessage,
69
+ } })] }), (0, jsx_runtime_1.jsx)(Composer, { placeholder: placeholder })] }) }) }) }) }), hidePoweredBy === false && (0, jsx_runtime_1.jsx)(brand_js_1.PoweredByCurator, {})] }));
70
+ }
71
+ // Context for threading the loading indicator into the message-component
72
+ // callbacks without remounting them on every render. Default is rendered
73
+ // when no consumer-supplied node is provided.
74
+ const LoadingIndicatorContext = (0, react_1.createContext)(null);
75
+ // Threads the `enableRetry` prop into AssistantMessage, which assistant-ui
76
+ // instantiates itself (no direct prop passing). Default off.
77
+ const RetryEnabledContext = (0, react_1.createContext)(false);
78
+ // Same threading trick for the `enableCopy` prop. Default off.
79
+ const CopyEnabledContext = (0, react_1.createContext)(false);
80
+ // ── header ──────────────────────────────────────────────────────
81
+ function Header({ title, onClose }) {
82
+ return ((0, jsx_runtime_1.jsxs)("header", { style: headerStyle, children: [(0, jsx_runtime_1.jsx)("h2", { style: titleStyle, children: title }), onClose && ((0, jsx_runtime_1.jsx)("button", { type: "button", onClick: onClose, "aria-label": "Close chat", style: headerActionStyle, children: (0, jsx_runtime_1.jsx)(HeaderCloseGlyph, {}) }))] }));
83
+ }
84
+ // ── message primitives (custom UI on top of assistant-ui state) ─
85
+ function Welcome({ text }) {
86
+ return (0, jsx_runtime_1.jsx)("div", { style: welcomeStyle, children: text });
87
+ }
88
+ function UserMessage() {
89
+ return ((0, jsx_runtime_1.jsx)(react_2.MessagePrimitive.Root, { style: rowEndStyle, children: (0, jsx_runtime_1.jsx)("div", { style: { ...bubbleBaseStyle, ...userBubbleStyle }, children: (0, jsx_runtime_1.jsx)(react_2.MessagePrimitive.Parts, { components: { Text: UserTextPart } }) }) }));
90
+ }
91
+ const UserTextPart = ({ text }) => (0, jsx_runtime_1.jsx)(jsx_runtime_1.Fragment, { children: text });
92
+ function AssistantMessage() {
93
+ const indicator = (0, react_1.useContext)(LoadingIndicatorContext);
94
+ const retryEnabled = (0, react_1.useContext)(RetryEnabledContext);
95
+ const copyEnabled = (0, react_1.useContext)(CopyEnabledContext);
96
+ return ((0, jsx_runtime_1.jsxs)(react_2.MessagePrimitive.Root, { style: rowStartStyle, children: [(0, jsx_runtime_1.jsxs)("div", { style: { ...bubbleBaseStyle, ...assistantBubbleStyle }, children: [(0, jsx_runtime_1.jsx)(react_2.MessagePrimitive.If, { hasContent: false, children: indicator }), (0, jsx_runtime_1.jsx)(react_2.MessagePrimitive.Parts, { components: { Text: AssistantTextPart } })] }), (retryEnabled || copyEnabled) && (
97
+ // `autohide="not-last"` shows the bar only on the trailing assistant
98
+ // message; `hideWhenRunning` keeps it away while a reply streams.
99
+ (0, jsx_runtime_1.jsxs)(react_2.ActionBarPrimitive.Root, { autohide: "not-last", hideWhenRunning: true, style: actionBarStyle, children: [copyEnabled && ((0, jsx_runtime_1.jsxs)(react_2.ActionBarPrimitive.Copy, { "aria-label": "Copy", style: actionButtonStyle, children: [(0, jsx_runtime_1.jsx)(react_2.MessagePrimitive.If, { copied: true, children: (0, jsx_runtime_1.jsx)(CheckGlyph, {}) }), (0, jsx_runtime_1.jsx)(react_2.MessagePrimitive.If, { copied: false, children: (0, jsx_runtime_1.jsx)(CopyGlyph, {}) })] })), retryEnabled && ((0, jsx_runtime_1.jsx)(react_2.ActionBarPrimitive.Reload, { "aria-label": "Retry", style: actionButtonStyle, children: (0, jsx_runtime_1.jsx)(RetryGlyph, {}) }))] }))] }));
100
+ }
101
+ function TypingDots() {
102
+ return ((0, jsx_runtime_1.jsxs)("span", { style: typingDotsStyle, "aria-label": "Assistant is thinking", children: [(0, jsx_runtime_1.jsx)(Dot, { delay: 0 }), (0, jsx_runtime_1.jsx)(Dot, { delay: 150 }), (0, jsx_runtime_1.jsx)(Dot, { delay: 300 })] }));
103
+ }
104
+ function Dot({ delay }) {
105
+ return ((0, jsx_runtime_1.jsx)("span", { style: {
106
+ display: "inline-block",
107
+ width: 6,
108
+ height: 6,
109
+ margin: "0 2px",
110
+ borderRadius: "50%",
111
+ background: "currentColor",
112
+ animation: `curator-pulse 1s ${delay}ms infinite ease-in-out`,
113
+ opacity: 0.6,
114
+ } }));
115
+ }
116
+ const AssistantTextPart = ({ text }) => ((0, jsx_runtime_1.jsx)(Markdown_js_1.Markdown, { content: text }));
117
+ // ── composer ────────────────────────────────────────────────────
118
+ function Composer({ placeholder }) {
119
+ return ((0, jsx_runtime_1.jsxs)(react_2.ComposerPrimitive.Root, { style: composerRootStyle, children: [(0, jsx_runtime_1.jsx)(react_2.ComposerPrimitive.Input, { placeholder: placeholder, submitOnEnter: true, rows: 1, maxRows: 6,
120
+ // ComposerPrimitive.Input is backed by react-textarea-autosize,
121
+ // whose `Style` type forbids non-numeric `height` (which we
122
+ // never set). Erase the type through `unknown` since the
123
+ // narrower expectation is satisfied at runtime.
124
+ style: textareaStyle, "aria-label": "Message" }), (0, jsx_runtime_1.jsx)(react_2.ComposerPrimitive.Send, { "aria-label": "Send", style: sendButtonStyle, children: (0, jsx_runtime_1.jsx)(SendGlyph, {}) })] }));
125
+ }
126
+ // ── glyphs ──────────────────────────────────────────────────────
127
+ function HeaderCloseGlyph() {
128
+ return ((0, jsx_runtime_1.jsx)("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", "aria-hidden": "true", children: (0, jsx_runtime_1.jsx)("path", { d: "M6 6 18 18 M18 6 6 18", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round" }) }));
129
+ }
130
+ function SendGlyph() {
131
+ return ((0, jsx_runtime_1.jsx)("svg", { width: "18", height: "18", viewBox: "0 0 24 24", fill: "none", "aria-hidden": "true", children: (0, jsx_runtime_1.jsx)("path", { d: "m4 12 16-8-6 16-2.5-6.5L4 12Z", stroke: "currentColor", strokeWidth: "1.75", strokeLinejoin: "round", fill: "none" }) }));
132
+ }
133
+ function RetryGlyph() {
134
+ return ((0, jsx_runtime_1.jsx)("svg", { width: "13", height: "13", viewBox: "0 0 24 24", fill: "none", "aria-hidden": "true", children: (0, jsx_runtime_1.jsx)("path", { d: "M20 11a8 8 0 1 0-.6 3M20 5v6h-6", stroke: "currentColor", strokeWidth: "1.75", strokeLinecap: "round", strokeLinejoin: "round", fill: "none" }) }));
135
+ }
136
+ function CopyGlyph() {
137
+ return ((0, jsx_runtime_1.jsxs)("svg", { width: "13", height: "13", viewBox: "0 0 24 24", fill: "none", "aria-hidden": "true", children: [(0, jsx_runtime_1.jsx)("rect", { x: "9", y: "9", width: "11", height: "11", rx: "2", stroke: "currentColor", strokeWidth: "1.75" }), (0, jsx_runtime_1.jsx)("path", { d: "M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1", stroke: "currentColor", strokeWidth: "1.75", strokeLinecap: "round", strokeLinejoin: "round" })] }));
138
+ }
139
+ function CheckGlyph() {
140
+ return ((0, jsx_runtime_1.jsx)("svg", { width: "13", height: "13", viewBox: "0 0 24 24", fill: "none", "aria-hidden": "true", children: (0, jsx_runtime_1.jsx)("path", { d: "m5 13 4 4L19 7", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" }) }));
141
+ }
142
+ // ── design tokens ───────────────────────────────────────────────
143
+ const SPACE_2 = 8;
144
+ const SPACE_3 = 12;
145
+ const SPACE_4 = 16;
146
+ const FONT_BASE = 14;
147
+ const RADIUS_LG = 14;
148
+ const RADIUS_MD = 10;
149
+ const RADIUS_SM = 8;
150
+ const LIGHT_VARS = {
151
+ ["--curator-bg"]: "#ffffff",
152
+ ["--curator-surface"]: "#f8fafc",
153
+ ["--curator-text"]: "#0f172a",
154
+ ["--curator-muted"]: "#64748b",
155
+ ["--curator-border"]: "rgba(15, 23, 42, 0.08)",
156
+ ["--curator-accent"]: "#0f172a",
157
+ ["--curator-accent-text"]: "#ffffff",
158
+ ["--curator-user-bubble"]: "#f1f5f9",
159
+ ["--curator-error"]: "#b91c1c",
160
+ ["--curator-radius"]: `${RADIUS_LG}px`,
161
+ };
162
+ const DARK_VARS = {
163
+ ["--curator-bg"]: "#0b1220",
164
+ ["--curator-surface"]: "#111a2c",
165
+ ["--curator-text"]: "#e2e8f0",
166
+ ["--curator-muted"]: "#94a3b8",
167
+ ["--curator-border"]: "rgba(226, 232, 240, 0.1)",
168
+ ["--curator-accent"]: "#e2e8f0",
169
+ ["--curator-accent-text"]: "#0b1220",
170
+ ["--curator-user-bubble"]: "#1f2937",
171
+ ["--curator-error"]: "#fca5a5",
172
+ ["--curator-radius"]: `${RADIUS_LG}px`,
173
+ };
174
+ const containerStyle = {
175
+ display: "flex",
176
+ flexDirection: "column",
177
+ width: "100%",
178
+ height: "100%",
179
+ minHeight: 360,
180
+ background: "var(--curator-bg)",
181
+ color: "var(--curator-text)",
182
+ border: "1px solid var(--curator-border)",
183
+ borderRadius: "var(--curator-radius)",
184
+ overflow: "hidden",
185
+ fontFamily: "ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif",
186
+ fontSize: FONT_BASE,
187
+ lineHeight: 1.5,
188
+ boxSizing: "border-box",
189
+ };
190
+ const headerStyle = {
191
+ paddingLeft: SPACE_4,
192
+ paddingRight: SPACE_2,
193
+ paddingTop: SPACE_2,
194
+ paddingBottom: SPACE_2,
195
+ borderBottom: "1px solid var(--curator-border)",
196
+ display: "flex",
197
+ alignItems: "center",
198
+ justifyContent: "space-between",
199
+ gap: SPACE_3,
200
+ height: 52,
201
+ flexShrink: 0,
202
+ boxSizing: "border-box",
203
+ };
204
+ const titleStyle = {
205
+ margin: 0,
206
+ fontWeight: 600,
207
+ fontSize: FONT_BASE,
208
+ lineHeight: 1.2,
209
+ };
210
+ const headerActionStyle = {
211
+ width: 32,
212
+ height: 32,
213
+ display: "inline-flex",
214
+ alignItems: "center",
215
+ justifyContent: "center",
216
+ border: "none",
217
+ borderRadius: 8,
218
+ background: "transparent",
219
+ color: "var(--curator-muted)",
220
+ cursor: "pointer",
221
+ flexShrink: 0,
222
+ transition: "background-color 120ms ease, color 120ms ease",
223
+ fontFamily: "inherit",
224
+ padding: 0,
225
+ };
226
+ const threadRootStyle = {
227
+ flex: 1,
228
+ display: "flex",
229
+ flexDirection: "column",
230
+ minHeight: 0,
231
+ };
232
+ const viewportStyle = {
233
+ flex: 1,
234
+ overflowY: "auto",
235
+ padding: `${SPACE_4}px ${SPACE_4}px ${SPACE_3}px`,
236
+ display: "flex",
237
+ flexDirection: "column",
238
+ gap: SPACE_2,
239
+ };
240
+ const welcomeStyle = {
241
+ color: "var(--curator-muted)",
242
+ fontSize: 13,
243
+ padding: `${SPACE_2}px 0`,
244
+ };
245
+ const rowStartStyle = {
246
+ // Column so the retry action bar can stack beneath the bubble, both
247
+ // left-aligned. Assistant-only; the user row stays a plain flex row.
248
+ display: "flex",
249
+ flexDirection: "column",
250
+ alignItems: "flex-start",
251
+ width: "100%",
252
+ };
253
+ const rowEndStyle = {
254
+ display: "flex",
255
+ width: "100%",
256
+ justifyContent: "flex-end",
257
+ };
258
+ const actionBarStyle = {
259
+ display: "flex",
260
+ alignItems: "center",
261
+ gap: 4,
262
+ marginTop: 4,
263
+ paddingLeft: 2,
264
+ };
265
+ const actionButtonStyle = {
266
+ display: "inline-flex",
267
+ alignItems: "center",
268
+ justifyContent: "center",
269
+ width: 26,
270
+ height: 26,
271
+ padding: 0,
272
+ border: "none",
273
+ borderRadius: RADIUS_SM,
274
+ background: "transparent",
275
+ color: "var(--curator-muted)",
276
+ cursor: "pointer",
277
+ transition: "color 120ms ease, background 120ms ease",
278
+ };
279
+ const bubbleBaseStyle = {
280
+ maxWidth: "85%",
281
+ padding: `${SPACE_2 + 2}px ${SPACE_3}px`,
282
+ borderRadius: RADIUS_MD,
283
+ whiteSpace: "pre-wrap",
284
+ wordBreak: "break-word",
285
+ fontSize: FONT_BASE,
286
+ lineHeight: 1.5,
287
+ };
288
+ const userBubbleStyle = {
289
+ background: "var(--curator-user-bubble)",
290
+ color: "var(--curator-text)",
291
+ borderBottomRightRadius: 4,
292
+ };
293
+ const assistantBubbleStyle = {
294
+ background: "var(--curator-accent)",
295
+ color: "var(--curator-accent-text)",
296
+ borderBottomLeftRadius: 4,
297
+ };
298
+ const typingDotsStyle = {
299
+ display: "inline-flex",
300
+ alignItems: "center",
301
+ paddingTop: 2,
302
+ paddingBottom: 2,
303
+ lineHeight: 1,
304
+ };
305
+ const composerRootStyle = {
306
+ borderTop: "1px solid var(--curator-border)",
307
+ background: "var(--curator-surface)",
308
+ display: "flex",
309
+ gap: SPACE_2,
310
+ alignItems: "flex-end",
311
+ padding: `${SPACE_3}px ${SPACE_3}px ${SPACE_2}px`,
312
+ flexShrink: 0,
313
+ };
314
+ const textareaStyle = {
315
+ flex: 1,
316
+ resize: "none",
317
+ border: "1px solid var(--curator-border)",
318
+ borderRadius: RADIUS_SM,
319
+ padding: `${SPACE_2}px ${SPACE_3}px`,
320
+ background: "var(--curator-bg)",
321
+ color: "var(--curator-text)",
322
+ fontFamily: "inherit",
323
+ fontSize: FONT_BASE,
324
+ lineHeight: 1.45,
325
+ outline: "none",
326
+ // Vertical bounds belong on the textarea-autosize component itself
327
+ // (via `rows` / `maxRows`), not in style — it explicitly throws when
328
+ // `style.maxHeight` is set. See ComposerPrimitive.Input above.
329
+ boxSizing: "border-box",
330
+ };
331
+ const sendButtonStyle = {
332
+ border: "none",
333
+ borderRadius: RADIUS_SM,
334
+ width: 38,
335
+ height: 38,
336
+ background: "var(--curator-accent)",
337
+ color: "var(--curator-accent-text)",
338
+ display: "inline-flex",
339
+ alignItems: "center",
340
+ justifyContent: "center",
341
+ fontFamily: "inherit",
342
+ transition: "opacity 120ms ease",
343
+ flexShrink: 0,
344
+ cursor: "pointer",
345
+ };
346
+ // One-shot stylesheet injection — scoped markdown + focus rules.
347
+ // Idempotent. Skipped in SSR. STYLE_ID is bumped when the rules change
348
+ // so existing pages re-inject the new sheet on next mount instead of
349
+ // reusing the stale element.
350
+ if (typeof document !== "undefined") {
351
+ const STYLE_ID = "curator-chat-styles-v4";
352
+ if (!document.getElementById(STYLE_ID)) {
353
+ const el = document.createElement("style");
354
+ el.id = STYLE_ID;
355
+ el.textContent = `
356
+ @keyframes curator-pulse { 0%, 80%, 100% { transform: scale(0.6); opacity: 0.3; } 40% { transform: scale(1); opacity: 0.9; } }
357
+ [data-curator-chat] textarea {
358
+ transition: border-color 120ms ease, box-shadow 120ms ease;
359
+ }
360
+ [data-curator-chat] textarea:focus {
361
+ /* Keep the resting border; signal focus with a faint outer halo only. */
362
+ box-shadow: 0 0 0 3px rgba(15, 23, 42, 0.04) !important;
363
+ }
364
+ [data-curator-chat][data-theme="dark"] textarea:focus {
365
+ box-shadow: 0 0 0 3px rgba(226, 232, 240, 0.05) !important;
366
+ }
367
+ [data-curator-chat] header button:hover { background-color: var(--curator-user-bubble) !important; color: var(--curator-text) !important; }
368
+ [data-curator-chat] button:disabled { opacity: 0.4; cursor: not-allowed; }
369
+
370
+ /* ── Markdown bubble ──────────────────────────────────────────────
371
+ Goal: render LLM-emitted markdown tightly regardless of structural
372
+ quirks (loose-list autopromotion, intermediate <div> wrappers from
373
+ react-markdown / assistant-ui, inherited bubble line-height bleeding
374
+ into list items, etc.).
375
+
376
+ We can't rely on a consumer's CSS reset (Tailwind preflight or
377
+ similar), so this block is self-contained and uses !important on the
378
+ spacing properties that fight default browser styling. Specificity
379
+ alone isn't enough because some wrapping elements come from
380
+ third-party libraries we don't control. */
381
+
382
+ /* Container: pin line-height so list items don't inherit the bubble's
383
+ 1.5 line-height and stretch out vertically. Also reset white-space —
384
+ the bubble sets white-space: pre-wrap so it can preserve newlines in
385
+ user-typed messages (those don't go through markdown), but that
386
+ inheritance turns every newline between rendered HTML siblings
387
+ (</p> + <ul>, </li> + <li>, etc.) into a visible blank line in the
388
+ markdown output. Normal whitespace handling collapses those. */
389
+ [data-curator-md] {
390
+ line-height: 1.4 !important;
391
+ white-space: normal !important;
392
+ }
393
+
394
+ /* Container edges flush with the bubble — no leading or trailing gap. */
395
+ [data-curator-md] > :first-child { margin-top: 0 !important; }
396
+ [data-curator-md] > :last-child { margin-bottom: 0 !important; }
397
+
398
+ /* Paragraphs (top-level or wrapping). */
399
+ [data-curator-md] p { margin: 0 0 4px !important; line-height: 1.4 !important; }
400
+ [data-curator-md] p + p { margin-top: 0 !important; }
401
+
402
+ /* Lists: tight outer spacing, zero margin on the lists themselves
403
+ (margin lives on the items below). */
404
+ [data-curator-md] ul, [data-curator-md] ol {
405
+ margin: 4px 0 !important;
406
+ padding: 0 0 0 20px !important;
407
+ line-height: 1.4 !important;
408
+ }
409
+ /* Nested lists: zero own margin so the outer list item's margin is the
410
+ only vertical contribution. */
411
+ [data-curator-md] ul ul, [data-curator-md] ul ol,
412
+ [data-curator-md] ol ul, [data-curator-md] ol ol {
413
+ margin: 0 !important;
414
+ padding-left: 18px !important;
415
+ }
416
+
417
+ /* List items: tight margin + pinned line-height so they don't inherit
418
+ the bubble. */
419
+ [data-curator-md] li {
420
+ margin: 2px 0 !important;
421
+ padding: 0 !important;
422
+ line-height: 1.4 !important;
423
+ }
424
+
425
+ /* Any <p> at any depth inside a list item — react-markdown wraps
426
+ loose-list item content (and items with mixed inline+block children)
427
+ in <p>; the browser default ~16px margin makes the chat look like a
428
+ stack of paragraphs. Descendant selector covers nested cases. */
429
+ [data-curator-md] li p { margin: 0 !important; }
430
+
431
+ /* Intermediate <div> wrappers (assistant-ui / react-markdown internals
432
+ sometimes inject these). Default browser styling doesn't add margin
433
+ to <div>, but inherited block-flow rules can; force flat. */
434
+ [data-curator-md] div { margin: 0 !important; }
435
+
436
+ [data-curator-md] h1, [data-curator-md] h2, [data-curator-md] h3, [data-curator-md] h4, [data-curator-md] h5, [data-curator-md] h6 { margin: 8px 0 2px; font-weight: 600; line-height: 1.3; }
437
+ [data-curator-md] h1:first-child, [data-curator-md] h2:first-child, [data-curator-md] h3:first-child, [data-curator-md] h4:first-child, [data-curator-md] h5:first-child, [data-curator-md] h6:first-child { margin-top: 0; }
438
+ [data-curator-md] h1 { font-size: 1.15em; }
439
+ [data-curator-md] h2 { font-size: 1.08em; }
440
+ [data-curator-md] h3, [data-curator-md] h4, [data-curator-md] h5, [data-curator-md] h6 { font-size: 1em; }
441
+ [data-curator-md] a { color: inherit; text-decoration: underline; text-underline-offset: 2px; }
442
+ [data-curator-md] code { font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; font-size: 0.92em; background: rgba(255, 255, 255, 0.12); padding: 1px 5px; border-radius: 4px; }
443
+ [data-curator-md] pre { margin: 6px 0; padding: 10px 12px; background: rgba(0, 0, 0, 0.18); border-radius: 8px; overflow-x: auto; }
444
+ [data-curator-md] pre code { background: transparent; padding: 0; border-radius: 0; font-size: 0.88em; line-height: 1.5; display: block; }
445
+ [data-curator-md] blockquote { margin: 4px 0; padding: 0 10px; border-left: 2px solid currentColor; opacity: 0.85; }
446
+ [data-curator-md] hr { border: none; border-top: 1px solid currentColor; opacity: 0.2; margin: 8px 0; }
447
+ [data-curator-md] table { border-collapse: collapse; margin: 4px 0; font-size: 0.95em; }
448
+ [data-curator-md] th, [data-curator-md] td { border: 1px solid currentColor; padding: 4px 8px; }
449
+ [data-curator-md] th { font-weight: 600; }
450
+ `;
451
+ document.head.appendChild(el);
452
+ }
453
+ }
454
+ //# sourceMappingURL=CuratorChat.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"CuratorChat.js","sourceRoot":"","sources":["../../src/CuratorChat.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,57 @@
1
+ /**
2
+ * <CuratorChatLauncher /> — floating chat bubble that opens an
3
+ * anchored panel containing `<CuratorChat />`. The drop-in shape
4
+ * customers reach for when they want an Intercom-style widget on
5
+ * their site without rolling their own positioning.
6
+ *
7
+ * <CuratorChatLauncher agent="support-bot" placement="bottom-right" />
8
+ *
9
+ * Rendered via a portal to `document.body` so stacking contexts in
10
+ * the consuming app don't trap it. The panel reuses `<CuratorChat />`
11
+ * verbatim — same theming, same hook, same provider context.
12
+ *
13
+ * ESC closes the panel; clicking outside does NOT (intentional — losing
14
+ * chat state on a stray click is the most annoying widget UX there is).
15
+ */
16
+ import { type ReactNode } from "react";
17
+ import type { Curator, Environment, AssistantMessage, CuratorError } from "@darqlabs/curator-sdk";
18
+ export type LauncherPlacement = "bottom-right" | "bottom-left" | "top-right" | "top-left";
19
+ export interface CuratorChatLauncherProps {
20
+ /** SDK instance. Optional when a `<CuratorProvider>` is in scope. */
21
+ curator?: Curator;
22
+ /** Deployment slug to chat with. */
23
+ agent: string;
24
+ /** Corner of the viewport to dock the launcher to. Default `bottom-right`. */
25
+ placement?: LauncherPlacement;
26
+ /** Distance (px) from the docked corner. Default 24. */
27
+ offset?: number;
28
+ /** Open the panel on first mount. Default false. */
29
+ defaultOpen?: boolean;
30
+ /** Width (px) of the open panel. Default 440. */
31
+ panelWidth?: number;
32
+ /** Height (px) of the open panel. Default 620. */
33
+ panelHeight?: number;
34
+ /** Custom bubble content. Default: chat-bubble SVG. */
35
+ icon?: ReactNode;
36
+ /** Accessible label for the bubble. Default "Open chat". */
37
+ ariaLabel?: string;
38
+ /** Open/close events. */
39
+ onOpen?: () => void;
40
+ onClose?: () => void;
41
+ project?: string;
42
+ environment?: Environment;
43
+ system?: boolean;
44
+ conversationId?: string;
45
+ title?: string;
46
+ placeholder?: string;
47
+ welcomeMessage?: string;
48
+ theme?: "light" | "dark";
49
+ /** Show the retry (↻) button under the latest assistant message. Default false. */
50
+ enableRetry?: boolean;
51
+ /** Show a copy button on assistant messages. Default false. */
52
+ enableCopy?: boolean;
53
+ onMessage?: (message: AssistantMessage) => void;
54
+ onError?: (error: CuratorError | Error) => void;
55
+ }
56
+ export declare function CuratorChatLauncher(props: CuratorChatLauncherProps): import("react").ReactPortal | null;
57
+ //# sourceMappingURL=CuratorChatLauncher.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"CuratorChatLauncher.d.ts","sourceRoot":"","sources":["../../src/CuratorChatLauncher.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,EAKL,KAAK,SAAS,EACf,MAAM,OAAO,CAAA;AAEd,OAAO,KAAK,EAAE,OAAO,EAAE,WAAW,EAAE,gBAAgB,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAA;AAGjG,MAAM,MAAM,iBAAiB,GACzB,cAAc,GACd,aAAa,GACb,WAAW,GACX,UAAU,CAAA;AAEd,MAAM,WAAW,wBAAwB;IACvC,qEAAqE;IACrE,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB,oCAAoC;IACpC,KAAK,EAAE,MAAM,CAAA;IAEb,8EAA8E;IAC9E,SAAS,CAAC,EAAE,iBAAiB,CAAA;IAC7B,wDAAwD;IACxD,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,oDAAoD;IACpD,WAAW,CAAC,EAAE,OAAO,CAAA;IAErB,iDAAiD;IACjD,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,kDAAkD;IAClD,WAAW,CAAC,EAAE,MAAM,CAAA;IAEpB,uDAAuD;IACvD,IAAI,CAAC,EAAE,SAAS,CAAA;IAChB,4DAA4D;IAC5D,SAAS,CAAC,EAAE,MAAM,CAAA;IAElB,yBAAyB;IACzB,MAAM,CAAC,EAAE,MAAM,IAAI,CAAA;IACnB,OAAO,CAAC,EAAE,MAAM,IAAI,CAAA;IAGpB,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,WAAW,CAAC,EAAE,WAAW,CAAA;IACzB,MAAM,CAAC,EAAE,OAAO,CAAA;IAChB,cAAc,CAAC,EAAE,MAAM,CAAA;IACvB,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,cAAc,CAAC,EAAE,MAAM,CAAA;IACvB,KAAK,CAAC,EAAE,OAAO,GAAG,MAAM,CAAA;IACxB,mFAAmF;IACnF,WAAW,CAAC,EAAE,OAAO,CAAA;IACrB,+DAA+D;IAC/D,UAAU,CAAC,EAAE,OAAO,CAAA;IACpB,SAAS,CAAC,EAAE,CAAC,OAAO,EAAE,gBAAgB,KAAK,IAAI,CAAA;IAC/C,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,YAAY,GAAG,KAAK,KAAK,IAAI,CAAA;CAChD;AAED,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,wBAAwB,sCAwFlE"}