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