@hookraft/use-claude-support 0.1.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs ADDED
@@ -0,0 +1,483 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/index.ts
21
+ var index_exports = {};
22
+ __export(index_exports, {
23
+ useClaudeSupport: () => useClaudeSupport
24
+ });
25
+ module.exports = __toCommonJS(index_exports);
26
+
27
+ // src/SupportWidget.tsx
28
+ var import_react = require("react");
29
+ var import_jsx_runtime = require("react/jsx-runtime");
30
+ var CLAUDE_LOGO = "data:image/svg+xml;base64," + btoa(
31
+ `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 48 48" fill="none">
32
+ <rect width="48" height="48" rx="12" fill="#D97757"/>
33
+ <path d="M32.16 13H28.7l-7.4 21.82h3.22l1.68-5.18h7.56l1.68 5.18h3.32L32.16 13zm-5.06 13.94 2.96-9.12 2.96 9.12h-5.92zM18.3 13h-3.46L11 22.06 7.16 13H3.7l5.96 13.44L3.7 39h3.46l4.62-10.5L16.4 39h3.46l-6-12.56L18.3 13z" fill="white"/>
34
+ </svg>`
35
+ );
36
+ function ChatIcon({ size = 24 }) {
37
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("svg", { width: size, height: size, viewBox: "0 0 24 24", fill: "currentColor", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M12 2C6.477 2 2 6.477 2 12c0 1.89.525 3.66 1.438 5.168L2.546 21.16a.5.5 0 00.628.628l3.992-.892A9.96 9.96 0 0012 22c5.523 0 10-4.477 10-10S17.523 2 12 2z" }) });
38
+ }
39
+ function CloseIcon({ size = 18 }) {
40
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
41
+ "svg",
42
+ {
43
+ width: size,
44
+ height: size,
45
+ viewBox: "0 0 24 24",
46
+ fill: "none",
47
+ stroke: "currentColor",
48
+ strokeWidth: 2,
49
+ strokeLinecap: "round",
50
+ children: [
51
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("line", { x1: "18", y1: "6", x2: "6", y2: "18" }),
52
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("line", { x1: "6", y1: "6", x2: "18", y2: "18" })
53
+ ]
54
+ }
55
+ );
56
+ }
57
+ function SendIcon({ size = 18 }) {
58
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
59
+ "svg",
60
+ {
61
+ width: size,
62
+ height: size,
63
+ viewBox: "0 0 24 24",
64
+ fill: "none",
65
+ stroke: "currentColor",
66
+ strokeWidth: 2,
67
+ strokeLinecap: "round",
68
+ strokeLinejoin: "round",
69
+ children: [
70
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("line", { x1: "22", y1: "2", x2: "11", y2: "13" }),
71
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("polygon", { points: "22 2 15 22 11 13 2 9 22 2" })
72
+ ]
73
+ }
74
+ );
75
+ }
76
+ function TypingIndicator({ bg }) {
77
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
78
+ "div",
79
+ {
80
+ style: {
81
+ display: "flex",
82
+ gap: 4,
83
+ padding: "10px 14px",
84
+ background: bg,
85
+ borderRadius: "18px 18px 18px 4px",
86
+ width: "fit-content",
87
+ alignItems: "center"
88
+ },
89
+ children: [0, 1, 2].map((i) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
90
+ "span",
91
+ {
92
+ style: {
93
+ width: 7,
94
+ height: 7,
95
+ borderRadius: "50%",
96
+ background: "#9ca3af",
97
+ display: "inline-block",
98
+ animation: "bounce 1.2s infinite",
99
+ animationDelay: `${i * 0.2}s`
100
+ }
101
+ },
102
+ i
103
+ ))
104
+ }
105
+ );
106
+ }
107
+ function useResolvedTheme(theme) {
108
+ const [resolved, setResolved] = (0, import_react.useState)("light");
109
+ (0, import_react.useEffect)(() => {
110
+ if (theme === "light" || theme === "dark") {
111
+ setResolved(theme);
112
+ return;
113
+ }
114
+ const checkTheme = () => {
115
+ const html = document.documentElement;
116
+ const dataTheme = html.getAttribute("data-theme");
117
+ const classList = html.classList;
118
+ if (dataTheme === "dark" || classList.contains("dark")) {
119
+ setResolved("dark");
120
+ return;
121
+ }
122
+ if (dataTheme === "light" || classList.contains("light")) {
123
+ setResolved("light");
124
+ return;
125
+ }
126
+ const prefersDark = window.matchMedia("(prefers-color-scheme: dark)").matches;
127
+ setResolved(prefersDark ? "dark" : "light");
128
+ };
129
+ checkTheme();
130
+ const observer = new MutationObserver(checkTheme);
131
+ observer.observe(document.documentElement, {
132
+ attributes: true,
133
+ attributeFilter: ["class", "data-theme", "style"]
134
+ });
135
+ const mq = window.matchMedia("(prefers-color-scheme: dark)");
136
+ mq.addEventListener("change", checkTheme);
137
+ return () => {
138
+ observer.disconnect();
139
+ mq.removeEventListener("change", checkTheme);
140
+ };
141
+ }, [theme]);
142
+ return resolved;
143
+ }
144
+ function SupportWidgetComponent({
145
+ endpoint,
146
+ knowledge,
147
+ branding
148
+ }) {
149
+ const {
150
+ theme = "system",
151
+ primaryColor = "#D97757",
152
+ logo = CLAUDE_LOGO,
153
+ title = "Claude Support"
154
+ } = branding;
155
+ const resolvedTheme = useResolvedTheme(theme);
156
+ const isDark = resolvedTheme === "dark";
157
+ const colors = {
158
+ bg: isDark ? "#1a1a1a" : "#ffffff",
159
+ border: isDark ? "#333333" : "#e5e7eb",
160
+ text: isDark ? "#f1f1f1" : "#111111",
161
+ textMuted: isDark ? "#9ca3af" : "#6b7280",
162
+ inputBg: isDark ? "#2a2a2a" : "#ffffff",
163
+ assistantBubble: isDark ? "#2a2a2a" : "#f3f4f6",
164
+ assistantText: isDark ? "#f1f1f1" : "#111111"
165
+ };
166
+ const [open, setOpen] = (0, import_react.useState)(false);
167
+ const [messages, setMessages] = (0, import_react.useState)([]);
168
+ const [input, setInput] = (0, import_react.useState)("");
169
+ const [isTyping, setIsTyping] = (0, import_react.useState)(false);
170
+ const [error, setError] = (0, import_react.useState)(null);
171
+ const messagesEndRef = (0, import_react.useRef)(null);
172
+ const inputRef = (0, import_react.useRef)(null);
173
+ (0, import_react.useEffect)(() => {
174
+ messagesEndRef.current?.scrollIntoView({ behavior: "smooth" });
175
+ }, [messages, isTyping]);
176
+ (0, import_react.useEffect)(() => {
177
+ if (open) setTimeout(() => inputRef.current?.focus(), 100);
178
+ }, [open]);
179
+ (0, import_react.useEffect)(() => {
180
+ const handler = (e) => {
181
+ if (e.key === "Escape") setOpen(false);
182
+ };
183
+ document.addEventListener("keydown", handler);
184
+ return () => document.removeEventListener("keydown", handler);
185
+ }, []);
186
+ const sendMessage = (0, import_react.useCallback)(async () => {
187
+ if (!input.trim() || isTyping) return;
188
+ setError(null);
189
+ const userMessage = {
190
+ id: crypto.randomUUID(),
191
+ role: "user",
192
+ content: input.trim(),
193
+ timestamp: Date.now()
194
+ };
195
+ const history = messages.map((m) => ({ role: m.role, content: m.content }));
196
+ setMessages((prev) => [...prev, userMessage]);
197
+ setInput("");
198
+ setIsTyping(true);
199
+ try {
200
+ const res = await fetch(endpoint, {
201
+ method: "POST",
202
+ headers: { "Content-Type": "application/json" },
203
+ body: JSON.stringify({ message: userMessage.content, history, knowledge })
204
+ });
205
+ if (!res.ok) throw new Error(`Request failed: ${res.status}`);
206
+ const data = await res.json();
207
+ const assistantMessage = {
208
+ id: crypto.randomUUID(),
209
+ role: "assistant",
210
+ content: data.reply,
211
+ timestamp: Date.now()
212
+ };
213
+ setMessages((prev) => [...prev, assistantMessage]);
214
+ } catch {
215
+ setError("Something went wrong. Please try again.");
216
+ } finally {
217
+ setIsTyping(false);
218
+ }
219
+ }, [input, isTyping, messages, endpoint, knowledge]);
220
+ const handleKeyDown = (e) => {
221
+ if (e.key === "Enter" && !e.shiftKey) {
222
+ e.preventDefault();
223
+ sendMessage();
224
+ }
225
+ };
226
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
227
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("style", { children: `
228
+ @keyframes bounce {
229
+ 0%, 60%, 100% { transform: translateY(0); }
230
+ 30% { transform: translateY(-6px); }
231
+ }
232
+ @keyframes fadeIn {
233
+ from { opacity: 0; transform: translateY(8px); }
234
+ to { opacity: 1; transform: translateY(0); }
235
+ }
236
+ ` }),
237
+ open && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
238
+ "div",
239
+ {
240
+ style: {
241
+ position: "fixed",
242
+ bottom: 90,
243
+ right: 24,
244
+ width: 360,
245
+ maxWidth: "calc(100vw - 32px)",
246
+ height: 520,
247
+ maxHeight: "calc(100vh - 120px)",
248
+ background: colors.bg,
249
+ border: `1px solid ${colors.border}`,
250
+ borderRadius: 16,
251
+ boxShadow: "0 8px 40px rgba(0,0,0,0.18)",
252
+ display: "flex",
253
+ flexDirection: "column",
254
+ zIndex: 9998,
255
+ animation: "fadeIn 0.2s ease",
256
+ overflow: "hidden"
257
+ },
258
+ children: [
259
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
260
+ "div",
261
+ {
262
+ style: {
263
+ display: "flex",
264
+ alignItems: "center",
265
+ gap: 10,
266
+ padding: "14px 16px",
267
+ borderBottom: `1px solid ${colors.border}`,
268
+ background: colors.bg
269
+ },
270
+ children: [
271
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
272
+ "img",
273
+ {
274
+ src: logo,
275
+ alt: "logo",
276
+ style: { width: 28, height: 28, borderRadius: 6, objectFit: "cover" }
277
+ }
278
+ ),
279
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style: { fontWeight: 600, fontSize: 15, color: colors.text, flex: 1 }, children: title }),
280
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
281
+ "button",
282
+ {
283
+ onClick: () => setOpen(false),
284
+ style: {
285
+ background: "none",
286
+ border: "none",
287
+ cursor: "pointer",
288
+ color: colors.textMuted,
289
+ padding: 4,
290
+ display: "flex",
291
+ alignItems: "center"
292
+ },
293
+ children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(CloseIcon, {})
294
+ }
295
+ )
296
+ ]
297
+ }
298
+ ),
299
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
300
+ "div",
301
+ {
302
+ style: {
303
+ flex: 1,
304
+ overflowY: "auto",
305
+ padding: 16,
306
+ display: "flex",
307
+ flexDirection: "column",
308
+ gap: 12
309
+ },
310
+ children: [
311
+ messages.length === 0 && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
312
+ "div",
313
+ {
314
+ style: {
315
+ background: colors.assistantBubble,
316
+ color: colors.assistantText,
317
+ padding: "10px 14px",
318
+ borderRadius: "18px 18px 18px 4px",
319
+ fontSize: 14,
320
+ lineHeight: 1.5,
321
+ maxWidth: "85%"
322
+ },
323
+ children: "\u{1F44B} Hi! How can I help you today?"
324
+ }
325
+ ),
326
+ messages.map((msg) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
327
+ "div",
328
+ {
329
+ style: {
330
+ display: "flex",
331
+ justifyContent: msg.role === "user" ? "flex-end" : "flex-start"
332
+ },
333
+ children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
334
+ "div",
335
+ {
336
+ style: {
337
+ maxWidth: "85%",
338
+ padding: "10px 14px",
339
+ borderRadius: msg.role === "user" ? "18px 18px 4px 18px" : "18px 18px 18px 4px",
340
+ background: msg.role === "user" ? primaryColor : colors.assistantBubble,
341
+ color: msg.role === "user" ? "#ffffff" : colors.assistantText,
342
+ fontSize: 14,
343
+ lineHeight: 1.6,
344
+ wordBreak: "break-word",
345
+ whiteSpace: "pre-wrap"
346
+ },
347
+ children: msg.content
348
+ }
349
+ )
350
+ },
351
+ msg.id
352
+ )),
353
+ isTyping && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(TypingIndicator, { bg: colors.assistantBubble }),
354
+ error && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { style: { fontSize: 12, color: "#ef4444", textAlign: "center", margin: 0 }, children: error }),
355
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { ref: messagesEndRef })
356
+ ]
357
+ }
358
+ ),
359
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
360
+ "div",
361
+ {
362
+ style: {
363
+ padding: "10px 12px",
364
+ borderTop: `1px solid ${colors.border}`,
365
+ display: "flex",
366
+ gap: 8,
367
+ alignItems: "flex-end",
368
+ background: colors.bg
369
+ },
370
+ children: [
371
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
372
+ "textarea",
373
+ {
374
+ ref: inputRef,
375
+ value: input,
376
+ onChange: (e) => setInput(e.target.value),
377
+ onKeyDown: handleKeyDown,
378
+ placeholder: "Ask a question...",
379
+ rows: 1,
380
+ disabled: isTyping,
381
+ style: {
382
+ flex: 1,
383
+ resize: "none",
384
+ border: `1px solid ${colors.border}`,
385
+ borderRadius: 10,
386
+ padding: "8px 12px",
387
+ fontSize: 14,
388
+ lineHeight: 1.5,
389
+ background: colors.inputBg,
390
+ color: colors.text,
391
+ outline: "none",
392
+ fontFamily: "inherit",
393
+ maxHeight: 100,
394
+ overflowY: "auto"
395
+ }
396
+ }
397
+ ),
398
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
399
+ "button",
400
+ {
401
+ onClick: sendMessage,
402
+ disabled: !input.trim() || isTyping,
403
+ style: {
404
+ width: 38,
405
+ height: 38,
406
+ borderRadius: 10,
407
+ background: primaryColor,
408
+ border: "none",
409
+ cursor: "pointer",
410
+ display: "flex",
411
+ alignItems: "center",
412
+ justifyContent: "center",
413
+ color: "#ffffff",
414
+ opacity: !input.trim() || isTyping ? 0.4 : 1,
415
+ flexShrink: 0,
416
+ transition: "opacity 0.15s"
417
+ },
418
+ children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(SendIcon, {})
419
+ }
420
+ )
421
+ ]
422
+ }
423
+ )
424
+ ]
425
+ }
426
+ ),
427
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
428
+ "button",
429
+ {
430
+ onClick: () => setOpen((prev) => !prev),
431
+ style: {
432
+ position: "fixed",
433
+ bottom: 24,
434
+ right: 24,
435
+ width: 56,
436
+ height: 56,
437
+ borderRadius: "50%",
438
+ background: primaryColor,
439
+ border: "none",
440
+ cursor: "pointer",
441
+ display: "flex",
442
+ alignItems: "center",
443
+ justifyContent: "center",
444
+ color: "#ffffff",
445
+ boxShadow: "0 4px 20px rgba(0,0,0,0.2)",
446
+ zIndex: 9999,
447
+ transition: "transform 0.15s, box-shadow 0.15s"
448
+ },
449
+ onMouseEnter: (e) => {
450
+ e.currentTarget.style.transform = "scale(1.08)";
451
+ e.currentTarget.style.boxShadow = "0 6px 24px rgba(0,0,0,0.28)";
452
+ },
453
+ onMouseLeave: (e) => {
454
+ e.currentTarget.style.transform = "scale(1)";
455
+ e.currentTarget.style.boxShadow = "0 4px 20px rgba(0,0,0,0.2)";
456
+ },
457
+ "aria-label": open ? "Close support chat" : "Open support chat",
458
+ children: open ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(CloseIcon, { size: 22 }) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ChatIcon, { size: 24 })
459
+ }
460
+ )
461
+ ] });
462
+ }
463
+
464
+ // src/useClaudeSupport.tsx
465
+ var import_jsx_runtime2 = require("react/jsx-runtime");
466
+ function useClaudeSupport(options) {
467
+ const { endpoint, knowledge, branding = {} } = options;
468
+ const SupportWidget = () => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
469
+ SupportWidgetComponent,
470
+ {
471
+ endpoint,
472
+ knowledge,
473
+ branding
474
+ }
475
+ );
476
+ SupportWidget.displayName = "ClaudeSupport.Widget";
477
+ return { SupportWidget };
478
+ }
479
+ // Annotate the CommonJS export names for ESM import in node:
480
+ 0 && (module.exports = {
481
+ useClaudeSupport
482
+ });
483
+ //# sourceMappingURL=index.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/index.ts","../src/SupportWidget.tsx","../src/useClaudeSupport.tsx"],"sourcesContent":["export { useClaudeSupport } from \"./useClaudeSupport\"\nexport type { ClaudeSupport } from \"./useClaudeSupport\"","\"use client\"\n\nimport React, { useState, useRef, useEffect, useCallback } from \"react\"\nimport type { ClaudeSupport } from \"./useClaudeSupport\"\n\n// ─── Claude logo ──────────────────────────────────────────────────────────────\n\nconst CLAUDE_LOGO =\n \"data:image/svg+xml;base64,\" +\n btoa(\n `<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 48 48\" fill=\"none\">\n <rect width=\"48\" height=\"48\" rx=\"12\" fill=\"#D97757\"/>\n <path d=\"M32.16 13H28.7l-7.4 21.82h3.22l1.68-5.18h7.56l1.68 5.18h3.32L32.16 13zm-5.06 13.94 2.96-9.12 2.96 9.12h-5.92zM18.3 13h-3.46L11 22.06 7.16 13H3.7l5.96 13.44L3.7 39h3.46l4.62-10.5L16.4 39h3.46l-6-12.56L18.3 13z\" fill=\"white\"/>\n</svg>`\n )\n\n// ─── Icons ────────────────────────────────────────────────────────────────────\n\nfunction ChatIcon({ size = 24 }: { size?: number }) {\n return (\n <svg width={size} height={size} viewBox=\"0 0 24 24\" fill=\"currentColor\">\n <path d=\"M12 2C6.477 2 2 6.477 2 12c0 1.89.525 3.66 1.438 5.168L2.546 21.16a.5.5 0 00.628.628l3.992-.892A9.96 9.96 0 0012 22c5.523 0 10-4.477 10-10S17.523 2 12 2z\" />\n </svg>\n )\n}\n\nfunction CloseIcon({ size = 18 }: { size?: number }) {\n return (\n <svg\n width={size}\n height={size}\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth={2}\n strokeLinecap=\"round\"\n >\n <line x1=\"18\" y1=\"6\" x2=\"6\" y2=\"18\" />\n <line x1=\"6\" y1=\"6\" x2=\"18\" y2=\"18\" />\n </svg>\n )\n}\n\nfunction SendIcon({ size = 18 }: { size?: number }) {\n return (\n <svg\n width={size}\n height={size}\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth={2}\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n >\n <line x1=\"22\" y1=\"2\" x2=\"11\" y2=\"13\" />\n <polygon points=\"22 2 15 22 11 13 2 9 22 2\" />\n </svg>\n )\n}\n\n// ─── Typing indicator ─────────────────────────────────────────────────────────\n\nfunction TypingIndicator({ bg }: { bg: string }) {\n return (\n <div\n style={{\n display: \"flex\",\n gap: 4,\n padding: \"10px 14px\",\n background: bg,\n borderRadius: \"18px 18px 18px 4px\",\n width: \"fit-content\",\n alignItems: \"center\",\n }}\n >\n {[0, 1, 2].map((i) => (\n <span\n key={i}\n style={{\n width: 7,\n height: 7,\n borderRadius: \"50%\",\n background: \"#9ca3af\",\n display: \"inline-block\",\n animation: \"bounce 1.2s infinite\",\n animationDelay: `${i * 0.2}s`,\n }}\n />\n ))}\n </div>\n )\n}\n\n// ─── Theme resolver ───────────────────────────────────────────────────────────\n\nfunction useResolvedTheme(theme: ClaudeSupport.Theme): \"light\" | \"dark\" {\n const [resolved, setResolved] = useState<\"light\" | \"dark\">(\"light\")\n\n useEffect(() => {\n if (theme === \"light\" || theme === \"dark\") {\n setResolved(theme)\n return\n }\n\n const checkTheme = () => {\n const html = document.documentElement\n const dataTheme = html.getAttribute(\"data-theme\")\n const classList = html.classList\n\n if (dataTheme === \"dark\" || classList.contains(\"dark\")) {\n setResolved(\"dark\")\n return\n }\n if (dataTheme === \"light\" || classList.contains(\"light\")) {\n setResolved(\"light\")\n return\n }\n\n const prefersDark = window.matchMedia(\"(prefers-color-scheme: dark)\").matches\n setResolved(prefersDark ? \"dark\" : \"light\")\n }\n\n checkTheme()\n\n const observer = new MutationObserver(checkTheme)\n observer.observe(document.documentElement, {\n attributes: true,\n attributeFilter: [\"class\", \"data-theme\", \"style\"],\n })\n\n const mq = window.matchMedia(\"(prefers-color-scheme: dark)\")\n mq.addEventListener(\"change\", checkTheme)\n\n return () => {\n observer.disconnect()\n mq.removeEventListener(\"change\", checkTheme)\n }\n }, [theme])\n\n return resolved\n}\n\n// ─── Widget ───────────────────────────────────────────────────────────────────\n\ninterface SupportWidgetProps {\n endpoint: string\n knowledge: string\n branding: ClaudeSupport.Branding\n}\n\nexport function SupportWidgetComponent({\n endpoint,\n knowledge,\n branding,\n}: SupportWidgetProps) {\n const {\n theme = \"system\",\n primaryColor = \"#D97757\",\n logo = CLAUDE_LOGO,\n title = \"Claude Support\",\n } = branding\n\n const resolvedTheme = useResolvedTheme(theme)\n const isDark = resolvedTheme === \"dark\"\n\n const colors = {\n bg: isDark ? \"#1a1a1a\" : \"#ffffff\",\n border: isDark ? \"#333333\" : \"#e5e7eb\",\n text: isDark ? \"#f1f1f1\" : \"#111111\",\n textMuted: isDark ? \"#9ca3af\" : \"#6b7280\",\n inputBg: isDark ? \"#2a2a2a\" : \"#ffffff\",\n assistantBubble: isDark ? \"#2a2a2a\" : \"#f3f4f6\",\n assistantText: isDark ? \"#f1f1f1\" : \"#111111\",\n }\n\n const [open, setOpen] = useState(false)\n const [messages, setMessages] = useState<ClaudeSupport.Message[]>([])\n const [input, setInput] = useState(\"\")\n const [isTyping, setIsTyping] = useState(false)\n const [error, setError] = useState<string | null>(null)\n const messagesEndRef = useRef<HTMLDivElement>(null)\n const inputRef = useRef<HTMLTextAreaElement>(null)\n\n useEffect(() => {\n messagesEndRef.current?.scrollIntoView({ behavior: \"smooth\" })\n }, [messages, isTyping])\n\n useEffect(() => {\n if (open) setTimeout(() => inputRef.current?.focus(), 100)\n }, [open])\n\n useEffect(() => {\n const handler = (e: KeyboardEvent) => {\n if (e.key === \"Escape\") setOpen(false)\n }\n document.addEventListener(\"keydown\", handler)\n return () => document.removeEventListener(\"keydown\", handler)\n }, [])\n\n const sendMessage = useCallback(async () => {\n if (!input.trim() || isTyping) return\n setError(null)\n\n const userMessage: ClaudeSupport.Message = {\n id: crypto.randomUUID(),\n role: \"user\",\n content: input.trim(),\n timestamp: Date.now(),\n }\n\n const history = messages.map((m) => ({ role: m.role, content: m.content }))\n setMessages((prev) => [...prev, userMessage])\n setInput(\"\")\n setIsTyping(true)\n\n try {\n const res = await fetch(endpoint, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({ message: userMessage.content, history, knowledge }),\n })\n\n if (!res.ok) throw new Error(`Request failed: ${res.status}`)\n const data = await res.json()\n\n const assistantMessage: ClaudeSupport.Message = {\n id: crypto.randomUUID(),\n role: \"assistant\",\n content: data.reply,\n timestamp: Date.now(),\n }\n\n setMessages((prev) => [...prev, assistantMessage])\n } catch {\n setError(\"Something went wrong. Please try again.\")\n } finally {\n setIsTyping(false)\n }\n }, [input, isTyping, messages, endpoint, knowledge])\n\n const handleKeyDown = (e: React.KeyboardEvent<HTMLTextAreaElement>) => {\n if (e.key === \"Enter\" && !e.shiftKey) {\n e.preventDefault()\n sendMessage()\n }\n }\n\n return (\n <>\n <style>{`\n @keyframes bounce {\n 0%, 60%, 100% { transform: translateY(0); }\n 30% { transform: translateY(-6px); }\n }\n @keyframes fadeIn {\n from { opacity: 0; transform: translateY(8px); }\n to { opacity: 1; transform: translateY(0); }\n }\n `}</style>\n\n {open && (\n <div\n style={{\n position: \"fixed\",\n bottom: 90,\n right: 24,\n width: 360,\n maxWidth: \"calc(100vw - 32px)\",\n height: 520,\n maxHeight: \"calc(100vh - 120px)\",\n background: colors.bg,\n border: `1px solid ${colors.border}`,\n borderRadius: 16,\n boxShadow: \"0 8px 40px rgba(0,0,0,0.18)\",\n display: \"flex\",\n flexDirection: \"column\",\n zIndex: 9998,\n animation: \"fadeIn 0.2s ease\",\n overflow: \"hidden\",\n }}\n >\n {/* Header */}\n <div\n style={{\n display: \"flex\",\n alignItems: \"center\",\n gap: 10,\n padding: \"14px 16px\",\n borderBottom: `1px solid ${colors.border}`,\n background: colors.bg,\n }}\n >\n <img\n src={logo}\n alt=\"logo\"\n style={{ width: 28, height: 28, borderRadius: 6, objectFit: \"cover\" }}\n />\n <span style={{ fontWeight: 600, fontSize: 15, color: colors.text, flex: 1 }}>\n {title}\n </span>\n <button\n onClick={() => setOpen(false)}\n style={{\n background: \"none\",\n border: \"none\",\n cursor: \"pointer\",\n color: colors.textMuted,\n padding: 4,\n display: \"flex\",\n alignItems: \"center\",\n }}\n >\n <CloseIcon />\n </button>\n </div>\n\n {/* Messages */}\n <div\n style={{\n flex: 1,\n overflowY: \"auto\",\n padding: 16,\n display: \"flex\",\n flexDirection: \"column\",\n gap: 12,\n }}\n >\n {messages.length === 0 && (\n <div\n style={{\n background: colors.assistantBubble,\n color: colors.assistantText,\n padding: \"10px 14px\",\n borderRadius: \"18px 18px 18px 4px\",\n fontSize: 14,\n lineHeight: 1.5,\n maxWidth: \"85%\",\n }}\n >\n 👋 Hi! How can I help you today?\n </div>\n )}\n\n {messages.map((msg) => (\n <div\n key={msg.id}\n style={{\n display: \"flex\",\n justifyContent: msg.role === \"user\" ? \"flex-end\" : \"flex-start\",\n }}\n >\n <div\n style={{\n maxWidth: \"85%\",\n padding: \"10px 14px\",\n borderRadius:\n msg.role === \"user\"\n ? \"18px 18px 4px 18px\"\n : \"18px 18px 18px 4px\",\n background:\n msg.role === \"user\" ? primaryColor : colors.assistantBubble,\n color: msg.role === \"user\" ? \"#ffffff\" : colors.assistantText,\n fontSize: 14,\n lineHeight: 1.6,\n wordBreak: \"break-word\",\n whiteSpace: \"pre-wrap\",\n }}\n >\n {msg.content}\n </div>\n </div>\n ))}\n\n {isTyping && <TypingIndicator bg={colors.assistantBubble} />}\n\n {error && (\n <p style={{ fontSize: 12, color: \"#ef4444\", textAlign: \"center\", margin: 0 }}>\n {error}\n </p>\n )}\n\n <div ref={messagesEndRef} />\n </div>\n\n {/* Input */}\n <div\n style={{\n padding: \"10px 12px\",\n borderTop: `1px solid ${colors.border}`,\n display: \"flex\",\n gap: 8,\n alignItems: \"flex-end\",\n background: colors.bg,\n }}\n >\n <textarea\n ref={inputRef}\n value={input}\n onChange={(e) => setInput(e.target.value)}\n onKeyDown={handleKeyDown}\n placeholder=\"Ask a question...\"\n rows={1}\n disabled={isTyping}\n style={{\n flex: 1,\n resize: \"none\",\n border: `1px solid ${colors.border}`,\n borderRadius: 10,\n padding: \"8px 12px\",\n fontSize: 14,\n lineHeight: 1.5,\n background: colors.inputBg,\n color: colors.text,\n outline: \"none\",\n fontFamily: \"inherit\",\n maxHeight: 100,\n overflowY: \"auto\",\n }}\n />\n <button\n onClick={sendMessage}\n disabled={!input.trim() || isTyping}\n style={{\n width: 38,\n height: 38,\n borderRadius: 10,\n background: primaryColor,\n border: \"none\",\n cursor: \"pointer\",\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n color: \"#ffffff\",\n opacity: !input.trim() || isTyping ? 0.4 : 1,\n flexShrink: 0,\n transition: \"opacity 0.15s\",\n }}\n >\n <SendIcon />\n </button>\n </div>\n </div>\n )}\n\n {/* Trigger button */}\n <button\n onClick={() => setOpen((prev) => !prev)}\n style={{\n position: \"fixed\",\n bottom: 24,\n right: 24,\n width: 56,\n height: 56,\n borderRadius: \"50%\",\n background: primaryColor,\n border: \"none\",\n cursor: \"pointer\",\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n color: \"#ffffff\",\n boxShadow: \"0 4px 20px rgba(0,0,0,0.2)\",\n zIndex: 9999,\n transition: \"transform 0.15s, box-shadow 0.15s\",\n }}\n onMouseEnter={(e) => {\n e.currentTarget.style.transform = \"scale(1.08)\"\n e.currentTarget.style.boxShadow = \"0 6px 24px rgba(0,0,0,0.28)\"\n }}\n onMouseLeave={(e) => {\n e.currentTarget.style.transform = \"scale(1)\"\n e.currentTarget.style.boxShadow = \"0 4px 20px rgba(0,0,0,0.2)\"\n }}\n aria-label={open ? \"Close support chat\" : \"Open support chat\"}\n >\n {open ? <CloseIcon size={22} /> : <ChatIcon size={24} />}\n </button>\n </>\n )\n}","\"use client\"\n\nimport React from \"react\"\nimport { SupportWidgetComponent } from \"./SupportWidget\"\n\n// ─── Namespace ────────────────────────────────────────────────────────────────\n\nexport namespace ClaudeSupport {\n export type Theme = \"light\" | \"dark\" | \"system\"\n\n export interface Branding {\n theme?: Theme\n primaryColor?: string\n logo?: string\n title?: string\n }\n\n export interface Message {\n id: string\n role: \"user\" | \"assistant\"\n content: string\n timestamp: number\n }\n\n export interface Options {\n endpoint: string\n knowledge: string\n branding?: Branding\n }\n\n export interface Return {\n SupportWidget: React.FC\n }\n}\n\n// ─── Hook ─────────────────────────────────────────────────────────────────────\n\nexport function useClaudeSupport(options: ClaudeSupport.Options): ClaudeSupport.Return {\n const { endpoint, knowledge, branding = {} } = options\n\n const SupportWidget: React.FC = () => (\n <SupportWidgetComponent\n endpoint={endpoint}\n knowledge={knowledge}\n branding={branding}\n />\n )\n\n SupportWidget.displayName = \"ClaudeSupport.Widget\"\n\n return { SupportWidget }\n}"],"mappings":"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","names":["import_jsx_runtime"]}
@@ -0,0 +1,28 @@
1
+ import React from 'react';
2
+
3
+ declare namespace ClaudeSupport {
4
+ type Theme = "light" | "dark" | "system";
5
+ interface Branding {
6
+ theme?: Theme;
7
+ primaryColor?: string;
8
+ logo?: string;
9
+ title?: string;
10
+ }
11
+ interface Message {
12
+ id: string;
13
+ role: "user" | "assistant";
14
+ content: string;
15
+ timestamp: number;
16
+ }
17
+ interface Options {
18
+ endpoint: string;
19
+ knowledge: string;
20
+ branding?: Branding;
21
+ }
22
+ interface Return {
23
+ SupportWidget: React.FC;
24
+ }
25
+ }
26
+ declare function useClaudeSupport(options: ClaudeSupport.Options): ClaudeSupport.Return;
27
+
28
+ export { ClaudeSupport, useClaudeSupport };
@@ -0,0 +1,28 @@
1
+ import React from 'react';
2
+
3
+ declare namespace ClaudeSupport {
4
+ type Theme = "light" | "dark" | "system";
5
+ interface Branding {
6
+ theme?: Theme;
7
+ primaryColor?: string;
8
+ logo?: string;
9
+ title?: string;
10
+ }
11
+ interface Message {
12
+ id: string;
13
+ role: "user" | "assistant";
14
+ content: string;
15
+ timestamp: number;
16
+ }
17
+ interface Options {
18
+ endpoint: string;
19
+ knowledge: string;
20
+ branding?: Branding;
21
+ }
22
+ interface Return {
23
+ SupportWidget: React.FC;
24
+ }
25
+ }
26
+ declare function useClaudeSupport(options: ClaudeSupport.Options): ClaudeSupport.Return;
27
+
28
+ export { ClaudeSupport, useClaudeSupport };
package/dist/index.js ADDED
@@ -0,0 +1,456 @@
1
+ // src/SupportWidget.tsx
2
+ import { useState, useRef, useEffect, useCallback } from "react";
3
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
4
+ var CLAUDE_LOGO = "data:image/svg+xml;base64," + btoa(
5
+ `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 48 48" fill="none">
6
+ <rect width="48" height="48" rx="12" fill="#D97757"/>
7
+ <path d="M32.16 13H28.7l-7.4 21.82h3.22l1.68-5.18h7.56l1.68 5.18h3.32L32.16 13zm-5.06 13.94 2.96-9.12 2.96 9.12h-5.92zM18.3 13h-3.46L11 22.06 7.16 13H3.7l5.96 13.44L3.7 39h3.46l4.62-10.5L16.4 39h3.46l-6-12.56L18.3 13z" fill="white"/>
8
+ </svg>`
9
+ );
10
+ function ChatIcon({ size = 24 }) {
11
+ return /* @__PURE__ */ jsx("svg", { width: size, height: size, viewBox: "0 0 24 24", fill: "currentColor", children: /* @__PURE__ */ jsx("path", { d: "M12 2C6.477 2 2 6.477 2 12c0 1.89.525 3.66 1.438 5.168L2.546 21.16a.5.5 0 00.628.628l3.992-.892A9.96 9.96 0 0012 22c5.523 0 10-4.477 10-10S17.523 2 12 2z" }) });
12
+ }
13
+ function CloseIcon({ size = 18 }) {
14
+ return /* @__PURE__ */ jsxs(
15
+ "svg",
16
+ {
17
+ width: size,
18
+ height: size,
19
+ viewBox: "0 0 24 24",
20
+ fill: "none",
21
+ stroke: "currentColor",
22
+ strokeWidth: 2,
23
+ strokeLinecap: "round",
24
+ children: [
25
+ /* @__PURE__ */ jsx("line", { x1: "18", y1: "6", x2: "6", y2: "18" }),
26
+ /* @__PURE__ */ jsx("line", { x1: "6", y1: "6", x2: "18", y2: "18" })
27
+ ]
28
+ }
29
+ );
30
+ }
31
+ function SendIcon({ size = 18 }) {
32
+ return /* @__PURE__ */ jsxs(
33
+ "svg",
34
+ {
35
+ width: size,
36
+ height: size,
37
+ viewBox: "0 0 24 24",
38
+ fill: "none",
39
+ stroke: "currentColor",
40
+ strokeWidth: 2,
41
+ strokeLinecap: "round",
42
+ strokeLinejoin: "round",
43
+ children: [
44
+ /* @__PURE__ */ jsx("line", { x1: "22", y1: "2", x2: "11", y2: "13" }),
45
+ /* @__PURE__ */ jsx("polygon", { points: "22 2 15 22 11 13 2 9 22 2" })
46
+ ]
47
+ }
48
+ );
49
+ }
50
+ function TypingIndicator({ bg }) {
51
+ return /* @__PURE__ */ jsx(
52
+ "div",
53
+ {
54
+ style: {
55
+ display: "flex",
56
+ gap: 4,
57
+ padding: "10px 14px",
58
+ background: bg,
59
+ borderRadius: "18px 18px 18px 4px",
60
+ width: "fit-content",
61
+ alignItems: "center"
62
+ },
63
+ children: [0, 1, 2].map((i) => /* @__PURE__ */ jsx(
64
+ "span",
65
+ {
66
+ style: {
67
+ width: 7,
68
+ height: 7,
69
+ borderRadius: "50%",
70
+ background: "#9ca3af",
71
+ display: "inline-block",
72
+ animation: "bounce 1.2s infinite",
73
+ animationDelay: `${i * 0.2}s`
74
+ }
75
+ },
76
+ i
77
+ ))
78
+ }
79
+ );
80
+ }
81
+ function useResolvedTheme(theme) {
82
+ const [resolved, setResolved] = useState("light");
83
+ useEffect(() => {
84
+ if (theme === "light" || theme === "dark") {
85
+ setResolved(theme);
86
+ return;
87
+ }
88
+ const checkTheme = () => {
89
+ const html = document.documentElement;
90
+ const dataTheme = html.getAttribute("data-theme");
91
+ const classList = html.classList;
92
+ if (dataTheme === "dark" || classList.contains("dark")) {
93
+ setResolved("dark");
94
+ return;
95
+ }
96
+ if (dataTheme === "light" || classList.contains("light")) {
97
+ setResolved("light");
98
+ return;
99
+ }
100
+ const prefersDark = window.matchMedia("(prefers-color-scheme: dark)").matches;
101
+ setResolved(prefersDark ? "dark" : "light");
102
+ };
103
+ checkTheme();
104
+ const observer = new MutationObserver(checkTheme);
105
+ observer.observe(document.documentElement, {
106
+ attributes: true,
107
+ attributeFilter: ["class", "data-theme", "style"]
108
+ });
109
+ const mq = window.matchMedia("(prefers-color-scheme: dark)");
110
+ mq.addEventListener("change", checkTheme);
111
+ return () => {
112
+ observer.disconnect();
113
+ mq.removeEventListener("change", checkTheme);
114
+ };
115
+ }, [theme]);
116
+ return resolved;
117
+ }
118
+ function SupportWidgetComponent({
119
+ endpoint,
120
+ knowledge,
121
+ branding
122
+ }) {
123
+ const {
124
+ theme = "system",
125
+ primaryColor = "#D97757",
126
+ logo = CLAUDE_LOGO,
127
+ title = "Claude Support"
128
+ } = branding;
129
+ const resolvedTheme = useResolvedTheme(theme);
130
+ const isDark = resolvedTheme === "dark";
131
+ const colors = {
132
+ bg: isDark ? "#1a1a1a" : "#ffffff",
133
+ border: isDark ? "#333333" : "#e5e7eb",
134
+ text: isDark ? "#f1f1f1" : "#111111",
135
+ textMuted: isDark ? "#9ca3af" : "#6b7280",
136
+ inputBg: isDark ? "#2a2a2a" : "#ffffff",
137
+ assistantBubble: isDark ? "#2a2a2a" : "#f3f4f6",
138
+ assistantText: isDark ? "#f1f1f1" : "#111111"
139
+ };
140
+ const [open, setOpen] = useState(false);
141
+ const [messages, setMessages] = useState([]);
142
+ const [input, setInput] = useState("");
143
+ const [isTyping, setIsTyping] = useState(false);
144
+ const [error, setError] = useState(null);
145
+ const messagesEndRef = useRef(null);
146
+ const inputRef = useRef(null);
147
+ useEffect(() => {
148
+ messagesEndRef.current?.scrollIntoView({ behavior: "smooth" });
149
+ }, [messages, isTyping]);
150
+ useEffect(() => {
151
+ if (open) setTimeout(() => inputRef.current?.focus(), 100);
152
+ }, [open]);
153
+ useEffect(() => {
154
+ const handler = (e) => {
155
+ if (e.key === "Escape") setOpen(false);
156
+ };
157
+ document.addEventListener("keydown", handler);
158
+ return () => document.removeEventListener("keydown", handler);
159
+ }, []);
160
+ const sendMessage = useCallback(async () => {
161
+ if (!input.trim() || isTyping) return;
162
+ setError(null);
163
+ const userMessage = {
164
+ id: crypto.randomUUID(),
165
+ role: "user",
166
+ content: input.trim(),
167
+ timestamp: Date.now()
168
+ };
169
+ const history = messages.map((m) => ({ role: m.role, content: m.content }));
170
+ setMessages((prev) => [...prev, userMessage]);
171
+ setInput("");
172
+ setIsTyping(true);
173
+ try {
174
+ const res = await fetch(endpoint, {
175
+ method: "POST",
176
+ headers: { "Content-Type": "application/json" },
177
+ body: JSON.stringify({ message: userMessage.content, history, knowledge })
178
+ });
179
+ if (!res.ok) throw new Error(`Request failed: ${res.status}`);
180
+ const data = await res.json();
181
+ const assistantMessage = {
182
+ id: crypto.randomUUID(),
183
+ role: "assistant",
184
+ content: data.reply,
185
+ timestamp: Date.now()
186
+ };
187
+ setMessages((prev) => [...prev, assistantMessage]);
188
+ } catch {
189
+ setError("Something went wrong. Please try again.");
190
+ } finally {
191
+ setIsTyping(false);
192
+ }
193
+ }, [input, isTyping, messages, endpoint, knowledge]);
194
+ const handleKeyDown = (e) => {
195
+ if (e.key === "Enter" && !e.shiftKey) {
196
+ e.preventDefault();
197
+ sendMessage();
198
+ }
199
+ };
200
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
201
+ /* @__PURE__ */ jsx("style", { children: `
202
+ @keyframes bounce {
203
+ 0%, 60%, 100% { transform: translateY(0); }
204
+ 30% { transform: translateY(-6px); }
205
+ }
206
+ @keyframes fadeIn {
207
+ from { opacity: 0; transform: translateY(8px); }
208
+ to { opacity: 1; transform: translateY(0); }
209
+ }
210
+ ` }),
211
+ open && /* @__PURE__ */ jsxs(
212
+ "div",
213
+ {
214
+ style: {
215
+ position: "fixed",
216
+ bottom: 90,
217
+ right: 24,
218
+ width: 360,
219
+ maxWidth: "calc(100vw - 32px)",
220
+ height: 520,
221
+ maxHeight: "calc(100vh - 120px)",
222
+ background: colors.bg,
223
+ border: `1px solid ${colors.border}`,
224
+ borderRadius: 16,
225
+ boxShadow: "0 8px 40px rgba(0,0,0,0.18)",
226
+ display: "flex",
227
+ flexDirection: "column",
228
+ zIndex: 9998,
229
+ animation: "fadeIn 0.2s ease",
230
+ overflow: "hidden"
231
+ },
232
+ children: [
233
+ /* @__PURE__ */ jsxs(
234
+ "div",
235
+ {
236
+ style: {
237
+ display: "flex",
238
+ alignItems: "center",
239
+ gap: 10,
240
+ padding: "14px 16px",
241
+ borderBottom: `1px solid ${colors.border}`,
242
+ background: colors.bg
243
+ },
244
+ children: [
245
+ /* @__PURE__ */ jsx(
246
+ "img",
247
+ {
248
+ src: logo,
249
+ alt: "logo",
250
+ style: { width: 28, height: 28, borderRadius: 6, objectFit: "cover" }
251
+ }
252
+ ),
253
+ /* @__PURE__ */ jsx("span", { style: { fontWeight: 600, fontSize: 15, color: colors.text, flex: 1 }, children: title }),
254
+ /* @__PURE__ */ jsx(
255
+ "button",
256
+ {
257
+ onClick: () => setOpen(false),
258
+ style: {
259
+ background: "none",
260
+ border: "none",
261
+ cursor: "pointer",
262
+ color: colors.textMuted,
263
+ padding: 4,
264
+ display: "flex",
265
+ alignItems: "center"
266
+ },
267
+ children: /* @__PURE__ */ jsx(CloseIcon, {})
268
+ }
269
+ )
270
+ ]
271
+ }
272
+ ),
273
+ /* @__PURE__ */ jsxs(
274
+ "div",
275
+ {
276
+ style: {
277
+ flex: 1,
278
+ overflowY: "auto",
279
+ padding: 16,
280
+ display: "flex",
281
+ flexDirection: "column",
282
+ gap: 12
283
+ },
284
+ children: [
285
+ messages.length === 0 && /* @__PURE__ */ jsx(
286
+ "div",
287
+ {
288
+ style: {
289
+ background: colors.assistantBubble,
290
+ color: colors.assistantText,
291
+ padding: "10px 14px",
292
+ borderRadius: "18px 18px 18px 4px",
293
+ fontSize: 14,
294
+ lineHeight: 1.5,
295
+ maxWidth: "85%"
296
+ },
297
+ children: "\u{1F44B} Hi! How can I help you today?"
298
+ }
299
+ ),
300
+ messages.map((msg) => /* @__PURE__ */ jsx(
301
+ "div",
302
+ {
303
+ style: {
304
+ display: "flex",
305
+ justifyContent: msg.role === "user" ? "flex-end" : "flex-start"
306
+ },
307
+ children: /* @__PURE__ */ jsx(
308
+ "div",
309
+ {
310
+ style: {
311
+ maxWidth: "85%",
312
+ padding: "10px 14px",
313
+ borderRadius: msg.role === "user" ? "18px 18px 4px 18px" : "18px 18px 18px 4px",
314
+ background: msg.role === "user" ? primaryColor : colors.assistantBubble,
315
+ color: msg.role === "user" ? "#ffffff" : colors.assistantText,
316
+ fontSize: 14,
317
+ lineHeight: 1.6,
318
+ wordBreak: "break-word",
319
+ whiteSpace: "pre-wrap"
320
+ },
321
+ children: msg.content
322
+ }
323
+ )
324
+ },
325
+ msg.id
326
+ )),
327
+ isTyping && /* @__PURE__ */ jsx(TypingIndicator, { bg: colors.assistantBubble }),
328
+ error && /* @__PURE__ */ jsx("p", { style: { fontSize: 12, color: "#ef4444", textAlign: "center", margin: 0 }, children: error }),
329
+ /* @__PURE__ */ jsx("div", { ref: messagesEndRef })
330
+ ]
331
+ }
332
+ ),
333
+ /* @__PURE__ */ jsxs(
334
+ "div",
335
+ {
336
+ style: {
337
+ padding: "10px 12px",
338
+ borderTop: `1px solid ${colors.border}`,
339
+ display: "flex",
340
+ gap: 8,
341
+ alignItems: "flex-end",
342
+ background: colors.bg
343
+ },
344
+ children: [
345
+ /* @__PURE__ */ jsx(
346
+ "textarea",
347
+ {
348
+ ref: inputRef,
349
+ value: input,
350
+ onChange: (e) => setInput(e.target.value),
351
+ onKeyDown: handleKeyDown,
352
+ placeholder: "Ask a question...",
353
+ rows: 1,
354
+ disabled: isTyping,
355
+ style: {
356
+ flex: 1,
357
+ resize: "none",
358
+ border: `1px solid ${colors.border}`,
359
+ borderRadius: 10,
360
+ padding: "8px 12px",
361
+ fontSize: 14,
362
+ lineHeight: 1.5,
363
+ background: colors.inputBg,
364
+ color: colors.text,
365
+ outline: "none",
366
+ fontFamily: "inherit",
367
+ maxHeight: 100,
368
+ overflowY: "auto"
369
+ }
370
+ }
371
+ ),
372
+ /* @__PURE__ */ jsx(
373
+ "button",
374
+ {
375
+ onClick: sendMessage,
376
+ disabled: !input.trim() || isTyping,
377
+ style: {
378
+ width: 38,
379
+ height: 38,
380
+ borderRadius: 10,
381
+ background: primaryColor,
382
+ border: "none",
383
+ cursor: "pointer",
384
+ display: "flex",
385
+ alignItems: "center",
386
+ justifyContent: "center",
387
+ color: "#ffffff",
388
+ opacity: !input.trim() || isTyping ? 0.4 : 1,
389
+ flexShrink: 0,
390
+ transition: "opacity 0.15s"
391
+ },
392
+ children: /* @__PURE__ */ jsx(SendIcon, {})
393
+ }
394
+ )
395
+ ]
396
+ }
397
+ )
398
+ ]
399
+ }
400
+ ),
401
+ /* @__PURE__ */ jsx(
402
+ "button",
403
+ {
404
+ onClick: () => setOpen((prev) => !prev),
405
+ style: {
406
+ position: "fixed",
407
+ bottom: 24,
408
+ right: 24,
409
+ width: 56,
410
+ height: 56,
411
+ borderRadius: "50%",
412
+ background: primaryColor,
413
+ border: "none",
414
+ cursor: "pointer",
415
+ display: "flex",
416
+ alignItems: "center",
417
+ justifyContent: "center",
418
+ color: "#ffffff",
419
+ boxShadow: "0 4px 20px rgba(0,0,0,0.2)",
420
+ zIndex: 9999,
421
+ transition: "transform 0.15s, box-shadow 0.15s"
422
+ },
423
+ onMouseEnter: (e) => {
424
+ e.currentTarget.style.transform = "scale(1.08)";
425
+ e.currentTarget.style.boxShadow = "0 6px 24px rgba(0,0,0,0.28)";
426
+ },
427
+ onMouseLeave: (e) => {
428
+ e.currentTarget.style.transform = "scale(1)";
429
+ e.currentTarget.style.boxShadow = "0 4px 20px rgba(0,0,0,0.2)";
430
+ },
431
+ "aria-label": open ? "Close support chat" : "Open support chat",
432
+ children: open ? /* @__PURE__ */ jsx(CloseIcon, { size: 22 }) : /* @__PURE__ */ jsx(ChatIcon, { size: 24 })
433
+ }
434
+ )
435
+ ] });
436
+ }
437
+
438
+ // src/useClaudeSupport.tsx
439
+ import { jsx as jsx2 } from "react/jsx-runtime";
440
+ function useClaudeSupport(options) {
441
+ const { endpoint, knowledge, branding = {} } = options;
442
+ const SupportWidget = () => /* @__PURE__ */ jsx2(
443
+ SupportWidgetComponent,
444
+ {
445
+ endpoint,
446
+ knowledge,
447
+ branding
448
+ }
449
+ );
450
+ SupportWidget.displayName = "ClaudeSupport.Widget";
451
+ return { SupportWidget };
452
+ }
453
+ export {
454
+ useClaudeSupport
455
+ };
456
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/SupportWidget.tsx","../src/useClaudeSupport.tsx"],"sourcesContent":["\"use client\"\n\nimport React, { useState, useRef, useEffect, useCallback } from \"react\"\nimport type { ClaudeSupport } from \"./useClaudeSupport\"\n\n// ─── Claude logo ──────────────────────────────────────────────────────────────\n\nconst CLAUDE_LOGO =\n \"data:image/svg+xml;base64,\" +\n btoa(\n `<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 48 48\" fill=\"none\">\n <rect width=\"48\" height=\"48\" rx=\"12\" fill=\"#D97757\"/>\n <path d=\"M32.16 13H28.7l-7.4 21.82h3.22l1.68-5.18h7.56l1.68 5.18h3.32L32.16 13zm-5.06 13.94 2.96-9.12 2.96 9.12h-5.92zM18.3 13h-3.46L11 22.06 7.16 13H3.7l5.96 13.44L3.7 39h3.46l4.62-10.5L16.4 39h3.46l-6-12.56L18.3 13z\" fill=\"white\"/>\n</svg>`\n )\n\n// ─── Icons ────────────────────────────────────────────────────────────────────\n\nfunction ChatIcon({ size = 24 }: { size?: number }) {\n return (\n <svg width={size} height={size} viewBox=\"0 0 24 24\" fill=\"currentColor\">\n <path d=\"M12 2C6.477 2 2 6.477 2 12c0 1.89.525 3.66 1.438 5.168L2.546 21.16a.5.5 0 00.628.628l3.992-.892A9.96 9.96 0 0012 22c5.523 0 10-4.477 10-10S17.523 2 12 2z\" />\n </svg>\n )\n}\n\nfunction CloseIcon({ size = 18 }: { size?: number }) {\n return (\n <svg\n width={size}\n height={size}\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth={2}\n strokeLinecap=\"round\"\n >\n <line x1=\"18\" y1=\"6\" x2=\"6\" y2=\"18\" />\n <line x1=\"6\" y1=\"6\" x2=\"18\" y2=\"18\" />\n </svg>\n )\n}\n\nfunction SendIcon({ size = 18 }: { size?: number }) {\n return (\n <svg\n width={size}\n height={size}\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth={2}\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n >\n <line x1=\"22\" y1=\"2\" x2=\"11\" y2=\"13\" />\n <polygon points=\"22 2 15 22 11 13 2 9 22 2\" />\n </svg>\n )\n}\n\n// ─── Typing indicator ─────────────────────────────────────────────────────────\n\nfunction TypingIndicator({ bg }: { bg: string }) {\n return (\n <div\n style={{\n display: \"flex\",\n gap: 4,\n padding: \"10px 14px\",\n background: bg,\n borderRadius: \"18px 18px 18px 4px\",\n width: \"fit-content\",\n alignItems: \"center\",\n }}\n >\n {[0, 1, 2].map((i) => (\n <span\n key={i}\n style={{\n width: 7,\n height: 7,\n borderRadius: \"50%\",\n background: \"#9ca3af\",\n display: \"inline-block\",\n animation: \"bounce 1.2s infinite\",\n animationDelay: `${i * 0.2}s`,\n }}\n />\n ))}\n </div>\n )\n}\n\n// ─── Theme resolver ───────────────────────────────────────────────────────────\n\nfunction useResolvedTheme(theme: ClaudeSupport.Theme): \"light\" | \"dark\" {\n const [resolved, setResolved] = useState<\"light\" | \"dark\">(\"light\")\n\n useEffect(() => {\n if (theme === \"light\" || theme === \"dark\") {\n setResolved(theme)\n return\n }\n\n const checkTheme = () => {\n const html = document.documentElement\n const dataTheme = html.getAttribute(\"data-theme\")\n const classList = html.classList\n\n if (dataTheme === \"dark\" || classList.contains(\"dark\")) {\n setResolved(\"dark\")\n return\n }\n if (dataTheme === \"light\" || classList.contains(\"light\")) {\n setResolved(\"light\")\n return\n }\n\n const prefersDark = window.matchMedia(\"(prefers-color-scheme: dark)\").matches\n setResolved(prefersDark ? \"dark\" : \"light\")\n }\n\n checkTheme()\n\n const observer = new MutationObserver(checkTheme)\n observer.observe(document.documentElement, {\n attributes: true,\n attributeFilter: [\"class\", \"data-theme\", \"style\"],\n })\n\n const mq = window.matchMedia(\"(prefers-color-scheme: dark)\")\n mq.addEventListener(\"change\", checkTheme)\n\n return () => {\n observer.disconnect()\n mq.removeEventListener(\"change\", checkTheme)\n }\n }, [theme])\n\n return resolved\n}\n\n// ─── Widget ───────────────────────────────────────────────────────────────────\n\ninterface SupportWidgetProps {\n endpoint: string\n knowledge: string\n branding: ClaudeSupport.Branding\n}\n\nexport function SupportWidgetComponent({\n endpoint,\n knowledge,\n branding,\n}: SupportWidgetProps) {\n const {\n theme = \"system\",\n primaryColor = \"#D97757\",\n logo = CLAUDE_LOGO,\n title = \"Claude Support\",\n } = branding\n\n const resolvedTheme = useResolvedTheme(theme)\n const isDark = resolvedTheme === \"dark\"\n\n const colors = {\n bg: isDark ? \"#1a1a1a\" : \"#ffffff\",\n border: isDark ? \"#333333\" : \"#e5e7eb\",\n text: isDark ? \"#f1f1f1\" : \"#111111\",\n textMuted: isDark ? \"#9ca3af\" : \"#6b7280\",\n inputBg: isDark ? \"#2a2a2a\" : \"#ffffff\",\n assistantBubble: isDark ? \"#2a2a2a\" : \"#f3f4f6\",\n assistantText: isDark ? \"#f1f1f1\" : \"#111111\",\n }\n\n const [open, setOpen] = useState(false)\n const [messages, setMessages] = useState<ClaudeSupport.Message[]>([])\n const [input, setInput] = useState(\"\")\n const [isTyping, setIsTyping] = useState(false)\n const [error, setError] = useState<string | null>(null)\n const messagesEndRef = useRef<HTMLDivElement>(null)\n const inputRef = useRef<HTMLTextAreaElement>(null)\n\n useEffect(() => {\n messagesEndRef.current?.scrollIntoView({ behavior: \"smooth\" })\n }, [messages, isTyping])\n\n useEffect(() => {\n if (open) setTimeout(() => inputRef.current?.focus(), 100)\n }, [open])\n\n useEffect(() => {\n const handler = (e: KeyboardEvent) => {\n if (e.key === \"Escape\") setOpen(false)\n }\n document.addEventListener(\"keydown\", handler)\n return () => document.removeEventListener(\"keydown\", handler)\n }, [])\n\n const sendMessage = useCallback(async () => {\n if (!input.trim() || isTyping) return\n setError(null)\n\n const userMessage: ClaudeSupport.Message = {\n id: crypto.randomUUID(),\n role: \"user\",\n content: input.trim(),\n timestamp: Date.now(),\n }\n\n const history = messages.map((m) => ({ role: m.role, content: m.content }))\n setMessages((prev) => [...prev, userMessage])\n setInput(\"\")\n setIsTyping(true)\n\n try {\n const res = await fetch(endpoint, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({ message: userMessage.content, history, knowledge }),\n })\n\n if (!res.ok) throw new Error(`Request failed: ${res.status}`)\n const data = await res.json()\n\n const assistantMessage: ClaudeSupport.Message = {\n id: crypto.randomUUID(),\n role: \"assistant\",\n content: data.reply,\n timestamp: Date.now(),\n }\n\n setMessages((prev) => [...prev, assistantMessage])\n } catch {\n setError(\"Something went wrong. Please try again.\")\n } finally {\n setIsTyping(false)\n }\n }, [input, isTyping, messages, endpoint, knowledge])\n\n const handleKeyDown = (e: React.KeyboardEvent<HTMLTextAreaElement>) => {\n if (e.key === \"Enter\" && !e.shiftKey) {\n e.preventDefault()\n sendMessage()\n }\n }\n\n return (\n <>\n <style>{`\n @keyframes bounce {\n 0%, 60%, 100% { transform: translateY(0); }\n 30% { transform: translateY(-6px); }\n }\n @keyframes fadeIn {\n from { opacity: 0; transform: translateY(8px); }\n to { opacity: 1; transform: translateY(0); }\n }\n `}</style>\n\n {open && (\n <div\n style={{\n position: \"fixed\",\n bottom: 90,\n right: 24,\n width: 360,\n maxWidth: \"calc(100vw - 32px)\",\n height: 520,\n maxHeight: \"calc(100vh - 120px)\",\n background: colors.bg,\n border: `1px solid ${colors.border}`,\n borderRadius: 16,\n boxShadow: \"0 8px 40px rgba(0,0,0,0.18)\",\n display: \"flex\",\n flexDirection: \"column\",\n zIndex: 9998,\n animation: \"fadeIn 0.2s ease\",\n overflow: \"hidden\",\n }}\n >\n {/* Header */}\n <div\n style={{\n display: \"flex\",\n alignItems: \"center\",\n gap: 10,\n padding: \"14px 16px\",\n borderBottom: `1px solid ${colors.border}`,\n background: colors.bg,\n }}\n >\n <img\n src={logo}\n alt=\"logo\"\n style={{ width: 28, height: 28, borderRadius: 6, objectFit: \"cover\" }}\n />\n <span style={{ fontWeight: 600, fontSize: 15, color: colors.text, flex: 1 }}>\n {title}\n </span>\n <button\n onClick={() => setOpen(false)}\n style={{\n background: \"none\",\n border: \"none\",\n cursor: \"pointer\",\n color: colors.textMuted,\n padding: 4,\n display: \"flex\",\n alignItems: \"center\",\n }}\n >\n <CloseIcon />\n </button>\n </div>\n\n {/* Messages */}\n <div\n style={{\n flex: 1,\n overflowY: \"auto\",\n padding: 16,\n display: \"flex\",\n flexDirection: \"column\",\n gap: 12,\n }}\n >\n {messages.length === 0 && (\n <div\n style={{\n background: colors.assistantBubble,\n color: colors.assistantText,\n padding: \"10px 14px\",\n borderRadius: \"18px 18px 18px 4px\",\n fontSize: 14,\n lineHeight: 1.5,\n maxWidth: \"85%\",\n }}\n >\n 👋 Hi! How can I help you today?\n </div>\n )}\n\n {messages.map((msg) => (\n <div\n key={msg.id}\n style={{\n display: \"flex\",\n justifyContent: msg.role === \"user\" ? \"flex-end\" : \"flex-start\",\n }}\n >\n <div\n style={{\n maxWidth: \"85%\",\n padding: \"10px 14px\",\n borderRadius:\n msg.role === \"user\"\n ? \"18px 18px 4px 18px\"\n : \"18px 18px 18px 4px\",\n background:\n msg.role === \"user\" ? primaryColor : colors.assistantBubble,\n color: msg.role === \"user\" ? \"#ffffff\" : colors.assistantText,\n fontSize: 14,\n lineHeight: 1.6,\n wordBreak: \"break-word\",\n whiteSpace: \"pre-wrap\",\n }}\n >\n {msg.content}\n </div>\n </div>\n ))}\n\n {isTyping && <TypingIndicator bg={colors.assistantBubble} />}\n\n {error && (\n <p style={{ fontSize: 12, color: \"#ef4444\", textAlign: \"center\", margin: 0 }}>\n {error}\n </p>\n )}\n\n <div ref={messagesEndRef} />\n </div>\n\n {/* Input */}\n <div\n style={{\n padding: \"10px 12px\",\n borderTop: `1px solid ${colors.border}`,\n display: \"flex\",\n gap: 8,\n alignItems: \"flex-end\",\n background: colors.bg,\n }}\n >\n <textarea\n ref={inputRef}\n value={input}\n onChange={(e) => setInput(e.target.value)}\n onKeyDown={handleKeyDown}\n placeholder=\"Ask a question...\"\n rows={1}\n disabled={isTyping}\n style={{\n flex: 1,\n resize: \"none\",\n border: `1px solid ${colors.border}`,\n borderRadius: 10,\n padding: \"8px 12px\",\n fontSize: 14,\n lineHeight: 1.5,\n background: colors.inputBg,\n color: colors.text,\n outline: \"none\",\n fontFamily: \"inherit\",\n maxHeight: 100,\n overflowY: \"auto\",\n }}\n />\n <button\n onClick={sendMessage}\n disabled={!input.trim() || isTyping}\n style={{\n width: 38,\n height: 38,\n borderRadius: 10,\n background: primaryColor,\n border: \"none\",\n cursor: \"pointer\",\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n color: \"#ffffff\",\n opacity: !input.trim() || isTyping ? 0.4 : 1,\n flexShrink: 0,\n transition: \"opacity 0.15s\",\n }}\n >\n <SendIcon />\n </button>\n </div>\n </div>\n )}\n\n {/* Trigger button */}\n <button\n onClick={() => setOpen((prev) => !prev)}\n style={{\n position: \"fixed\",\n bottom: 24,\n right: 24,\n width: 56,\n height: 56,\n borderRadius: \"50%\",\n background: primaryColor,\n border: \"none\",\n cursor: \"pointer\",\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n color: \"#ffffff\",\n boxShadow: \"0 4px 20px rgba(0,0,0,0.2)\",\n zIndex: 9999,\n transition: \"transform 0.15s, box-shadow 0.15s\",\n }}\n onMouseEnter={(e) => {\n e.currentTarget.style.transform = \"scale(1.08)\"\n e.currentTarget.style.boxShadow = \"0 6px 24px rgba(0,0,0,0.28)\"\n }}\n onMouseLeave={(e) => {\n e.currentTarget.style.transform = \"scale(1)\"\n e.currentTarget.style.boxShadow = \"0 4px 20px rgba(0,0,0,0.2)\"\n }}\n aria-label={open ? \"Close support chat\" : \"Open support chat\"}\n >\n {open ? <CloseIcon size={22} /> : <ChatIcon size={24} />}\n </button>\n </>\n )\n}","\"use client\"\n\nimport React from \"react\"\nimport { SupportWidgetComponent } from \"./SupportWidget\"\n\n// ─── Namespace ────────────────────────────────────────────────────────────────\n\nexport namespace ClaudeSupport {\n export type Theme = \"light\" | \"dark\" | \"system\"\n\n export interface Branding {\n theme?: Theme\n primaryColor?: string\n logo?: string\n title?: string\n }\n\n export interface Message {\n id: string\n role: \"user\" | \"assistant\"\n content: string\n timestamp: number\n }\n\n export interface Options {\n endpoint: string\n knowledge: string\n branding?: Branding\n }\n\n export interface Return {\n SupportWidget: React.FC\n }\n}\n\n// ─── Hook ─────────────────────────────────────────────────────────────────────\n\nexport function useClaudeSupport(options: ClaudeSupport.Options): ClaudeSupport.Return {\n const { endpoint, knowledge, branding = {} } = options\n\n const SupportWidget: React.FC = () => (\n <SupportWidgetComponent\n endpoint={endpoint}\n knowledge={knowledge}\n branding={branding}\n />\n )\n\n SupportWidget.displayName = \"ClaudeSupport.Widget\"\n\n return { SupportWidget }\n}"],"mappings":"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","names":["jsx"]}
package/package.json ADDED
@@ -0,0 +1,57 @@
1
+ {
2
+ "name": "@hookraft/use-claude-support",
3
+ "version": "0.1.3",
4
+ "description": "Add an AI-powered support chat to any React or Next.js app in minutes. Powered by Claude.",
5
+ "author": "virus",
6
+ "license": "MIT",
7
+ "type": "module",
8
+ "main": "./dist/index.js",
9
+ "module": "./dist/index.js",
10
+ "types": "./dist/index.d.ts",
11
+ "exports": {
12
+ ".": {
13
+ "types": "./dist/index.d.ts",
14
+ "import": "./dist/index.js",
15
+ "require": "./dist/index.cjs"
16
+ }
17
+ },
18
+ "files": [
19
+ "dist"
20
+ ],
21
+ "scripts": {
22
+ "build": "tsup",
23
+ "dev": "tsup --watch",
24
+ "typecheck": "tsc --noEmit",
25
+ "pub:release": "npm publish --access public"
26
+ },
27
+ "peerDependencies": {
28
+ "react": ">=18.0.0",
29
+ "react-dom": ">=18.0.0"
30
+ },
31
+ "devDependencies": {
32
+ "@types/react": "^19.2.14",
33
+ "@types/react-dom": "^19.2.3",
34
+ "react": "^19.2.4",
35
+ "react-dom": "^19.2.4",
36
+ "tsup": "^8.5.1",
37
+ "typescript": "^5.9.3"
38
+ },
39
+ "keywords": [
40
+ "react",
41
+ "hooks",
42
+ "claude",
43
+ "ai",
44
+ "support",
45
+ "chat",
46
+ "widget",
47
+ "anthropic",
48
+ "customer-support",
49
+ "nextjs",
50
+ "typescript"
51
+ ],
52
+ "repository": {
53
+ "type": "git",
54
+ "url": "https://github.com/purposewalks9/Hookraft"
55
+ },
56
+ "homepage": "https://hookraft.site"
57
+ }