@emblemvault/hustle-react 1.2.0 → 1.4.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.
- package/README.md +56 -0
- package/dist/browser/hustle-react.js +450 -5
- package/dist/browser/hustle-react.js.map +1 -1
- package/dist/components/index.cjs +450 -4
- package/dist/components/index.cjs.map +1 -1
- package/dist/components/index.d.cts +148 -2
- package/dist/components/index.d.ts +148 -2
- package/dist/components/index.js +450 -5
- package/dist/components/index.js.map +1 -1
- package/dist/index.cjs +450 -4
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +2 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.js +450 -5
- package/dist/index.js.map +1 -1
- package/dist/plugins/index.cjs +1 -1
- package/dist/plugins/index.cjs.map +1 -1
- package/dist/plugins/index.js +1 -1
- package/dist/plugins/index.js.map +1 -1
- package/package.json +2 -2
|
@@ -1609,7 +1609,7 @@ var screenshotExecutor = async (args2) => {
|
|
|
1609
1609
|
if (!window.html2canvas) {
|
|
1610
1610
|
await new Promise((resolve, reject) => {
|
|
1611
1611
|
const script = document.createElement("script");
|
|
1612
|
-
script.src = "https://
|
|
1612
|
+
script.src = "https://cdn.jsdelivr.net/npm/html2canvas-pro@1.5.0/dist/html2canvas-pro.min.js";
|
|
1613
1613
|
script.onload = () => resolve();
|
|
1614
1614
|
script.onerror = () => reject(new Error("Failed to load html2canvas"));
|
|
1615
1615
|
document.head.appendChild(script);
|
|
@@ -2664,6 +2664,14 @@ var animations = `
|
|
|
2664
2664
|
text-shadow: 0 0 8px ${defaults.colors.accentPrimary};
|
|
2665
2665
|
}
|
|
2666
2666
|
}
|
|
2667
|
+
/* Hide scrollbar while maintaining scroll functionality */
|
|
2668
|
+
.hustle-hide-scrollbar {
|
|
2669
|
+
-ms-overflow-style: none; /* IE and Edge */
|
|
2670
|
+
scrollbar-width: none; /* Firefox */
|
|
2671
|
+
}
|
|
2672
|
+
.hustle-hide-scrollbar::-webkit-scrollbar {
|
|
2673
|
+
display: none; /* Chrome, Safari, Opera */
|
|
2674
|
+
}
|
|
2667
2675
|
`;
|
|
2668
2676
|
hljs__default.default.registerLanguage("javascript", javascript__default.default);
|
|
2669
2677
|
hljs__default.default.registerLanguage("js", javascript__default.default);
|
|
@@ -3307,7 +3315,11 @@ var styles = {
|
|
|
3307
3315
|
border: "none",
|
|
3308
3316
|
borderRadius: 0,
|
|
3309
3317
|
color: tokens.colors.textTertiary,
|
|
3310
|
-
flexShrink: 0
|
|
3318
|
+
flexShrink: 0,
|
|
3319
|
+
display: "flex",
|
|
3320
|
+
alignItems: "center",
|
|
3321
|
+
justifyContent: "center",
|
|
3322
|
+
cursor: "pointer"
|
|
3311
3323
|
},
|
|
3312
3324
|
inputWrapper: {
|
|
3313
3325
|
flex: 1
|
|
@@ -3516,6 +3528,7 @@ function HustleChat({
|
|
|
3516
3528
|
placeholder = "Type a message...",
|
|
3517
3529
|
showSettings = false,
|
|
3518
3530
|
showDebug = false,
|
|
3531
|
+
hideHeader = false,
|
|
3519
3532
|
initialSystemPrompt = "",
|
|
3520
3533
|
onMessage,
|
|
3521
3534
|
onToolCall,
|
|
@@ -3528,6 +3541,7 @@ function HustleChat({
|
|
|
3528
3541
|
isLoading,
|
|
3529
3542
|
error: error2,
|
|
3530
3543
|
models,
|
|
3544
|
+
client,
|
|
3531
3545
|
chatStream,
|
|
3532
3546
|
uploadFile,
|
|
3533
3547
|
selectedModel,
|
|
@@ -3554,6 +3568,7 @@ function HustleChat({
|
|
|
3554
3568
|
const [showSettingsPanel, setShowSettingsPanel] = react.useState(false);
|
|
3555
3569
|
const messagesEndRef = react.useRef(null);
|
|
3556
3570
|
const fileInputRef = react.useRef(null);
|
|
3571
|
+
const messagesRef = react.useRef(messages);
|
|
3557
3572
|
react.useEffect(() => {
|
|
3558
3573
|
if (initialSystemPrompt && !systemPrompt) {
|
|
3559
3574
|
setSystemPrompt(initialSystemPrompt);
|
|
@@ -3562,6 +3577,9 @@ function HustleChat({
|
|
|
3562
3577
|
react.useEffect(() => {
|
|
3563
3578
|
messagesEndRef.current?.scrollIntoView({ behavior: "smooth" });
|
|
3564
3579
|
}, [messages]);
|
|
3580
|
+
react.useEffect(() => {
|
|
3581
|
+
messagesRef.current = messages;
|
|
3582
|
+
}, [messages]);
|
|
3565
3583
|
const handleFileSelect = react.useCallback(
|
|
3566
3584
|
async (e) => {
|
|
3567
3585
|
const files = e.target.files;
|
|
@@ -3583,6 +3601,96 @@ function HustleChat({
|
|
|
3583
3601
|
const removeAttachment = react.useCallback((index) => {
|
|
3584
3602
|
setAttachments((prev) => prev.filter((_, i) => i !== index));
|
|
3585
3603
|
}, []);
|
|
3604
|
+
const sendContinue = react.useCallback(async () => {
|
|
3605
|
+
if (isStreaming || !isReady) return;
|
|
3606
|
+
console.log("[AUTO_CONTINUE] Sending continue message...");
|
|
3607
|
+
const userMessage = {
|
|
3608
|
+
id: generateId(),
|
|
3609
|
+
role: "user",
|
|
3610
|
+
content: "continue"
|
|
3611
|
+
};
|
|
3612
|
+
setMessages((prev) => [...prev, userMessage]);
|
|
3613
|
+
onMessage?.(userMessage);
|
|
3614
|
+
const assistantMessage = {
|
|
3615
|
+
id: generateId(),
|
|
3616
|
+
role: "assistant",
|
|
3617
|
+
content: "",
|
|
3618
|
+
isStreaming: true,
|
|
3619
|
+
toolCalls: []
|
|
3620
|
+
};
|
|
3621
|
+
setMessages((prev) => [...prev, assistantMessage]);
|
|
3622
|
+
setIsStreaming(true);
|
|
3623
|
+
setCurrentToolCalls([]);
|
|
3624
|
+
try {
|
|
3625
|
+
const chatMessages = messagesRef.current.filter((m) => !m.isStreaming).map((m) => ({ role: m.role, content: m.content }));
|
|
3626
|
+
chatMessages.push({ role: "user", content: "continue" });
|
|
3627
|
+
const stream = chatStream({
|
|
3628
|
+
messages: chatMessages,
|
|
3629
|
+
processChunks: true
|
|
3630
|
+
});
|
|
3631
|
+
let fullContent = "";
|
|
3632
|
+
const toolCallsAccumulated = [];
|
|
3633
|
+
for await (const chunk of stream) {
|
|
3634
|
+
if (chunk.type === "text") {
|
|
3635
|
+
fullContent += chunk.value;
|
|
3636
|
+
setMessages(
|
|
3637
|
+
(prev) => prev.map(
|
|
3638
|
+
(m) => m.id === assistantMessage.id ? { ...m, content: fullContent } : m
|
|
3639
|
+
)
|
|
3640
|
+
);
|
|
3641
|
+
} else if (chunk.type === "tool_call") {
|
|
3642
|
+
const toolCall = chunk.value;
|
|
3643
|
+
toolCallsAccumulated.push(toolCall);
|
|
3644
|
+
setCurrentToolCalls([...toolCallsAccumulated]);
|
|
3645
|
+
setMessages(
|
|
3646
|
+
(prev) => prev.map(
|
|
3647
|
+
(m) => m.id === assistantMessage.id ? { ...m, toolCalls: [...toolCallsAccumulated] } : m
|
|
3648
|
+
)
|
|
3649
|
+
);
|
|
3650
|
+
onToolCall?.(toolCall);
|
|
3651
|
+
} else if (chunk.type === "error") {
|
|
3652
|
+
console.error("Stream error:", chunk.value);
|
|
3653
|
+
}
|
|
3654
|
+
}
|
|
3655
|
+
const processedResponse = await stream.response;
|
|
3656
|
+
const finalContent = processedResponse?.content || fullContent || "(No response)";
|
|
3657
|
+
setMessages(
|
|
3658
|
+
(prev) => prev.map(
|
|
3659
|
+
(m) => m.id === assistantMessage.id ? { ...m, isStreaming: false, content: finalContent } : m
|
|
3660
|
+
)
|
|
3661
|
+
);
|
|
3662
|
+
onResponse?.(finalContent);
|
|
3663
|
+
} catch (err) {
|
|
3664
|
+
console.error("Continue error:", err);
|
|
3665
|
+
setMessages(
|
|
3666
|
+
(prev) => prev.map(
|
|
3667
|
+
(m) => m.id === assistantMessage.id ? { ...m, isStreaming: false, content: `Error: ${err instanceof Error ? err.message : "Unknown error"}` } : m
|
|
3668
|
+
)
|
|
3669
|
+
);
|
|
3670
|
+
} finally {
|
|
3671
|
+
setIsStreaming(false);
|
|
3672
|
+
setCurrentToolCalls([]);
|
|
3673
|
+
}
|
|
3674
|
+
}, [isStreaming, isReady, chatStream, onMessage, onToolCall, onResponse]);
|
|
3675
|
+
react.useEffect(() => {
|
|
3676
|
+
if (!client) return;
|
|
3677
|
+
const unsubMaxTools = client.on("max_tools_reached", (event) => {
|
|
3678
|
+
console.log(`[AUTO_CONTINUE] Max tools reached (${event.toolsExecuted}/${event.maxSteps}), auto-continuing...`);
|
|
3679
|
+
setTimeout(() => {
|
|
3680
|
+
sendContinue();
|
|
3681
|
+
}, 100);
|
|
3682
|
+
});
|
|
3683
|
+
const unsubTimeout = client.on("timeout", (event) => {
|
|
3684
|
+
console.log(`[AUTO_CONTINUE] Timeout: ${event.message}, auto-continuing...`);
|
|
3685
|
+
setTimeout(() => {
|
|
3686
|
+
sendContinue();
|
|
3687
|
+
}, 100);
|
|
3688
|
+
});
|
|
3689
|
+
return () => {
|
|
3690
|
+
unsubMaxTools();
|
|
3691
|
+
unsubTimeout();
|
|
3692
|
+
};
|
|
3693
|
+
}, [client, sendContinue]);
|
|
3586
3694
|
const sendMessage = react.useCallback(async () => {
|
|
3587
3695
|
const content = inputValue.trim();
|
|
3588
3696
|
if (!content || isStreaming || !isReady) return;
|
|
@@ -3679,7 +3787,7 @@ function HustleChat({
|
|
|
3679
3787
|
return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
3680
3788
|
/* @__PURE__ */ jsxRuntime.jsx("style", { children: animations }),
|
|
3681
3789
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className, style: styles.container, children: [
|
|
3682
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { style: styles.header, children: [
|
|
3790
|
+
!hideHeader && /* @__PURE__ */ jsxRuntime.jsxs("div", { style: styles.header, children: [
|
|
3683
3791
|
/* @__PURE__ */ jsxRuntime.jsx("h2", { style: styles.headerTitle, children: "Chat" }),
|
|
3684
3792
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { style: styles.headerActions, children: [
|
|
3685
3793
|
selectedModel && /* @__PURE__ */ jsxRuntime.jsx("span", { style: { fontSize: tokens.typography.fontSizeSm, color: tokens.colors.textSecondary }, children: selectedModel.split("/").pop() }),
|
|
@@ -3854,7 +3962,7 @@ function HustleChat({
|
|
|
3854
3962
|
] })
|
|
3855
3963
|
] })
|
|
3856
3964
|
] }) }),
|
|
3857
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { style: styles.messagesArea, children: [
|
|
3965
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "hustle-hide-scrollbar", style: styles.messagesArea, children: [
|
|
3858
3966
|
messages.length === 0 && /* @__PURE__ */ jsxRuntime.jsx("div", { style: styles.messagesEmpty, children: /* @__PURE__ */ jsxRuntime.jsx("p", { children: getPlaceholderMessage() }) }),
|
|
3859
3967
|
/* @__PURE__ */ jsxRuntime.jsx("div", { style: styles.messagesContainer, children: messages.map((message) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
3860
3968
|
MessageBubble,
|
|
@@ -3981,8 +4089,346 @@ function SettingsIcon() {
|
|
|
3981
4089
|
function AttachIcon() {
|
|
3982
4090
|
return /* @__PURE__ */ jsxRuntime.jsx("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M21.44 11.05l-9.19 9.19a6 6 0 0 1-8.49-8.49l9.19-9.19a4 4 0 0 1 5.66 5.66l-9.2 9.19a2 2 0 0 1-2.83-2.83l8.49-8.48" }) });
|
|
3983
4091
|
}
|
|
4092
|
+
var sizeConfigs = {
|
|
4093
|
+
sm: { width: "320px", height: "400px" },
|
|
4094
|
+
md: { width: "380px", height: "520px" },
|
|
4095
|
+
lg: { width: "420px", height: "600px" },
|
|
4096
|
+
xl: { width: "480px", height: "700px" },
|
|
4097
|
+
full: { width: "100vw", height: "100vh" }
|
|
4098
|
+
};
|
|
4099
|
+
var widgetStyles = {
|
|
4100
|
+
// Container for absolute positioning
|
|
4101
|
+
container: {
|
|
4102
|
+
position: "fixed",
|
|
4103
|
+
zIndex: 9999,
|
|
4104
|
+
fontFamily: tokens.typography.fontFamily
|
|
4105
|
+
},
|
|
4106
|
+
// Launcher button
|
|
4107
|
+
launcher: {
|
|
4108
|
+
width: "56px",
|
|
4109
|
+
height: "56px",
|
|
4110
|
+
borderRadius: tokens.radius.full,
|
|
4111
|
+
background: `linear-gradient(135deg, ${tokens.colors.accentPrimary} 0%, #2d7dd2 100%)`,
|
|
4112
|
+
border: "none",
|
|
4113
|
+
cursor: "pointer",
|
|
4114
|
+
display: "flex",
|
|
4115
|
+
alignItems: "center",
|
|
4116
|
+
justifyContent: "center",
|
|
4117
|
+
boxShadow: `0 4px 20px rgba(76, 154, 255, 0.4), 0 2px 8px rgba(0, 0, 0, 0.3)`,
|
|
4118
|
+
transition: `all ${tokens.transitions.normal}`,
|
|
4119
|
+
color: tokens.colors.textInverse
|
|
4120
|
+
},
|
|
4121
|
+
launcherHover: {
|
|
4122
|
+
transform: "scale(1.05)",
|
|
4123
|
+
boxShadow: `0 6px 24px rgba(76, 154, 255, 0.5), 0 4px 12px rgba(0, 0, 0, 0.4)`
|
|
4124
|
+
},
|
|
4125
|
+
// Badge
|
|
4126
|
+
badge: {
|
|
4127
|
+
position: "absolute",
|
|
4128
|
+
top: "-4px",
|
|
4129
|
+
right: "-4px",
|
|
4130
|
+
minWidth: "20px",
|
|
4131
|
+
height: "20px",
|
|
4132
|
+
borderRadius: tokens.radius.pill,
|
|
4133
|
+
background: tokens.colors.accentError,
|
|
4134
|
+
color: tokens.colors.textInverse,
|
|
4135
|
+
fontSize: tokens.typography.fontSizeXs,
|
|
4136
|
+
fontWeight: tokens.typography.fontWeightSemibold,
|
|
4137
|
+
display: "flex",
|
|
4138
|
+
alignItems: "center",
|
|
4139
|
+
justifyContent: "center",
|
|
4140
|
+
padding: "0 6px",
|
|
4141
|
+
border: `2px solid ${tokens.colors.bgPrimary}`
|
|
4142
|
+
},
|
|
4143
|
+
// Chat panel
|
|
4144
|
+
panel: {
|
|
4145
|
+
position: "absolute",
|
|
4146
|
+
borderRadius: tokens.radius.xl,
|
|
4147
|
+
background: tokens.colors.bgSecondary,
|
|
4148
|
+
border: `1px solid ${tokens.colors.borderPrimary}`,
|
|
4149
|
+
boxShadow: `0 16px 48px rgba(0, 0, 0, 0.5)`,
|
|
4150
|
+
overflow: "hidden",
|
|
4151
|
+
display: "flex",
|
|
4152
|
+
flexDirection: "column",
|
|
4153
|
+
transition: `all ${tokens.transitions.slow}`
|
|
4154
|
+
},
|
|
4155
|
+
panelHidden: {
|
|
4156
|
+
opacity: 0,
|
|
4157
|
+
transform: "scale(0.95) translateY(10px)",
|
|
4158
|
+
pointerEvents: "none"
|
|
4159
|
+
},
|
|
4160
|
+
panelVisible: {
|
|
4161
|
+
opacity: 1,
|
|
4162
|
+
transform: "scale(1) translateY(0)"
|
|
4163
|
+
},
|
|
4164
|
+
// Full screen mode overrides
|
|
4165
|
+
panelFull: {
|
|
4166
|
+
position: "fixed",
|
|
4167
|
+
top: 0,
|
|
4168
|
+
left: 0,
|
|
4169
|
+
right: 0,
|
|
4170
|
+
bottom: 0,
|
|
4171
|
+
borderRadius: 0,
|
|
4172
|
+
width: "100vw",
|
|
4173
|
+
height: "100vh"
|
|
4174
|
+
},
|
|
4175
|
+
// Close button in panel header
|
|
4176
|
+
closeBtn: {
|
|
4177
|
+
width: "32px",
|
|
4178
|
+
height: "32px",
|
|
4179
|
+
borderRadius: tokens.radius.md,
|
|
4180
|
+
background: "transparent",
|
|
4181
|
+
border: "none",
|
|
4182
|
+
color: tokens.colors.textTertiary,
|
|
4183
|
+
cursor: "pointer",
|
|
4184
|
+
display: "flex",
|
|
4185
|
+
alignItems: "center",
|
|
4186
|
+
justifyContent: "center",
|
|
4187
|
+
transition: `all ${tokens.transitions.fast}`
|
|
4188
|
+
},
|
|
4189
|
+
closeBtnHover: {
|
|
4190
|
+
background: tokens.colors.bgTertiary,
|
|
4191
|
+
color: tokens.colors.textPrimary
|
|
4192
|
+
}
|
|
4193
|
+
};
|
|
4194
|
+
function ChatIcon() {
|
|
4195
|
+
return /* @__PURE__ */ jsxRuntime.jsx("svg", { width: "24", height: "24", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z" }) });
|
|
4196
|
+
}
|
|
4197
|
+
function CloseIcon() {
|
|
4198
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("svg", { width: "18", height: "18", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
|
|
4199
|
+
/* @__PURE__ */ jsxRuntime.jsx("line", { x1: "18", y1: "6", x2: "6", y2: "18" }),
|
|
4200
|
+
/* @__PURE__ */ jsxRuntime.jsx("line", { x1: "6", y1: "6", x2: "18", y2: "18" })
|
|
4201
|
+
] });
|
|
4202
|
+
}
|
|
4203
|
+
function MinimizeIcon() {
|
|
4204
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("svg", { width: "18", height: "18", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
|
|
4205
|
+
/* @__PURE__ */ jsxRuntime.jsx("polyline", { points: "4 14 10 14 10 20" }),
|
|
4206
|
+
/* @__PURE__ */ jsxRuntime.jsx("polyline", { points: "20 10 14 10 14 4" }),
|
|
4207
|
+
/* @__PURE__ */ jsxRuntime.jsx("line", { x1: "14", y1: "10", x2: "21", y2: "3" }),
|
|
4208
|
+
/* @__PURE__ */ jsxRuntime.jsx("line", { x1: "3", y1: "21", x2: "10", y2: "14" })
|
|
4209
|
+
] });
|
|
4210
|
+
}
|
|
4211
|
+
function HustleChatWidget({
|
|
4212
|
+
config = {},
|
|
4213
|
+
...chatProps
|
|
4214
|
+
}) {
|
|
4215
|
+
const {
|
|
4216
|
+
position = "bottom-right",
|
|
4217
|
+
size = "md",
|
|
4218
|
+
title = "Chat",
|
|
4219
|
+
defaultOpen = false,
|
|
4220
|
+
launcherIcon,
|
|
4221
|
+
offset = { x: 24, y: 24 },
|
|
4222
|
+
zIndex = 9999,
|
|
4223
|
+
showBadge = false,
|
|
4224
|
+
badgeContent,
|
|
4225
|
+
launcherStyle,
|
|
4226
|
+
panelStyle,
|
|
4227
|
+
onOpen,
|
|
4228
|
+
onClose,
|
|
4229
|
+
storageKey = "hustle-widget-open"
|
|
4230
|
+
} = config;
|
|
4231
|
+
const [isOpen, setIsOpen] = react.useState(false);
|
|
4232
|
+
const [isHovered, setIsHovered] = react.useState(false);
|
|
4233
|
+
const [closeHovered, setCloseHovered] = react.useState(false);
|
|
4234
|
+
const [mounted, setMounted] = react.useState(false);
|
|
4235
|
+
react.useEffect(() => {
|
|
4236
|
+
setMounted(true);
|
|
4237
|
+
if (storageKey && typeof window !== "undefined") {
|
|
4238
|
+
const stored = localStorage.getItem(storageKey);
|
|
4239
|
+
if (stored !== null) {
|
|
4240
|
+
setIsOpen(stored === "true");
|
|
4241
|
+
} else {
|
|
4242
|
+
setIsOpen(defaultOpen);
|
|
4243
|
+
}
|
|
4244
|
+
} else {
|
|
4245
|
+
setIsOpen(defaultOpen);
|
|
4246
|
+
}
|
|
4247
|
+
}, [defaultOpen, storageKey]);
|
|
4248
|
+
react.useEffect(() => {
|
|
4249
|
+
if (!mounted) return;
|
|
4250
|
+
if (storageKey && typeof window !== "undefined") {
|
|
4251
|
+
localStorage.setItem(storageKey, String(isOpen));
|
|
4252
|
+
}
|
|
4253
|
+
}, [isOpen, storageKey, mounted]);
|
|
4254
|
+
const toggle = react.useCallback(() => {
|
|
4255
|
+
setIsOpen((prev) => {
|
|
4256
|
+
const next = !prev;
|
|
4257
|
+
if (next) {
|
|
4258
|
+
onOpen?.();
|
|
4259
|
+
} else {
|
|
4260
|
+
onClose?.();
|
|
4261
|
+
}
|
|
4262
|
+
return next;
|
|
4263
|
+
});
|
|
4264
|
+
}, [onOpen, onClose]);
|
|
4265
|
+
const positionStyles = getPositionStyles(position, offset);
|
|
4266
|
+
const sizeConfig = sizeConfigs[size];
|
|
4267
|
+
if (!mounted) {
|
|
4268
|
+
return null;
|
|
4269
|
+
}
|
|
4270
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
4271
|
+
/* @__PURE__ */ jsxRuntime.jsx("style", { children: animations }),
|
|
4272
|
+
/* @__PURE__ */ jsxRuntime.jsx("style", { children: `
|
|
4273
|
+
@keyframes hustle-widget-bounce {
|
|
4274
|
+
0%, 100% { transform: translateY(0); }
|
|
4275
|
+
50% { transform: translateY(-4px); }
|
|
4276
|
+
}
|
|
4277
|
+
` }),
|
|
4278
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
4279
|
+
"div",
|
|
4280
|
+
{
|
|
4281
|
+
style: {
|
|
4282
|
+
...widgetStyles.container,
|
|
4283
|
+
...positionStyles.container,
|
|
4284
|
+
zIndex
|
|
4285
|
+
},
|
|
4286
|
+
children: [
|
|
4287
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
4288
|
+
"div",
|
|
4289
|
+
{
|
|
4290
|
+
style: {
|
|
4291
|
+
...widgetStyles.panel,
|
|
4292
|
+
...positionStyles.panel,
|
|
4293
|
+
...size === "full" ? widgetStyles.panelFull : {
|
|
4294
|
+
width: sizeConfig.width,
|
|
4295
|
+
height: sizeConfig.height
|
|
4296
|
+
},
|
|
4297
|
+
...isOpen ? widgetStyles.panelVisible : widgetStyles.panelHidden,
|
|
4298
|
+
...panelStyle
|
|
4299
|
+
},
|
|
4300
|
+
children: [
|
|
4301
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
4302
|
+
"div",
|
|
4303
|
+
{
|
|
4304
|
+
style: {
|
|
4305
|
+
display: "flex",
|
|
4306
|
+
alignItems: "center",
|
|
4307
|
+
justifyContent: "space-between",
|
|
4308
|
+
padding: `${tokens.spacing.md} ${tokens.spacing.lg}`,
|
|
4309
|
+
background: tokens.colors.bgPrimary,
|
|
4310
|
+
borderBottom: `1px solid ${tokens.colors.borderPrimary}`,
|
|
4311
|
+
borderRadius: `${tokens.radius.xl} ${tokens.radius.xl} 0 0`,
|
|
4312
|
+
flexShrink: 0
|
|
4313
|
+
},
|
|
4314
|
+
children: [
|
|
4315
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
4316
|
+
"span",
|
|
4317
|
+
{
|
|
4318
|
+
style: {
|
|
4319
|
+
fontWeight: tokens.typography.fontWeightSemibold,
|
|
4320
|
+
color: tokens.colors.textPrimary,
|
|
4321
|
+
fontSize: tokens.typography.fontSizeMd
|
|
4322
|
+
},
|
|
4323
|
+
children: title
|
|
4324
|
+
}
|
|
4325
|
+
),
|
|
4326
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
4327
|
+
"button",
|
|
4328
|
+
{
|
|
4329
|
+
onClick: toggle,
|
|
4330
|
+
onMouseEnter: () => setCloseHovered(true),
|
|
4331
|
+
onMouseLeave: () => setCloseHovered(false),
|
|
4332
|
+
style: {
|
|
4333
|
+
...widgetStyles.closeBtn,
|
|
4334
|
+
...closeHovered ? widgetStyles.closeBtnHover : {}
|
|
4335
|
+
},
|
|
4336
|
+
title: "Close chat",
|
|
4337
|
+
children: size === "full" ? /* @__PURE__ */ jsxRuntime.jsx(MinimizeIcon, {}) : /* @__PURE__ */ jsxRuntime.jsx(CloseIcon, {})
|
|
4338
|
+
}
|
|
4339
|
+
)
|
|
4340
|
+
]
|
|
4341
|
+
}
|
|
4342
|
+
),
|
|
4343
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { style: { flex: 1, display: "flex", flexDirection: "column", overflow: "hidden" }, children: /* @__PURE__ */ jsxRuntime.jsx(HustleChatInner, { ...chatProps }) })
|
|
4344
|
+
]
|
|
4345
|
+
}
|
|
4346
|
+
),
|
|
4347
|
+
(size !== "full" || !isOpen) && /* @__PURE__ */ jsxRuntime.jsxs(
|
|
4348
|
+
"button",
|
|
4349
|
+
{
|
|
4350
|
+
onClick: toggle,
|
|
4351
|
+
onMouseEnter: () => setIsHovered(true),
|
|
4352
|
+
onMouseLeave: () => setIsHovered(false),
|
|
4353
|
+
style: {
|
|
4354
|
+
...widgetStyles.launcher,
|
|
4355
|
+
...isHovered ? widgetStyles.launcherHover : {},
|
|
4356
|
+
...positionStyles.launcher,
|
|
4357
|
+
...launcherStyle,
|
|
4358
|
+
...isOpen ? { opacity: 0, pointerEvents: "none" } : {}
|
|
4359
|
+
},
|
|
4360
|
+
title: isOpen ? "Close chat" : "Open chat",
|
|
4361
|
+
"aria-label": isOpen ? "Close chat" : "Open chat",
|
|
4362
|
+
children: [
|
|
4363
|
+
launcherIcon || /* @__PURE__ */ jsxRuntime.jsx(ChatIcon, {}),
|
|
4364
|
+
showBadge && badgeContent && !isOpen && /* @__PURE__ */ jsxRuntime.jsx("span", { style: widgetStyles.badge, children: badgeContent })
|
|
4365
|
+
]
|
|
4366
|
+
}
|
|
4367
|
+
)
|
|
4368
|
+
]
|
|
4369
|
+
}
|
|
4370
|
+
)
|
|
4371
|
+
] });
|
|
4372
|
+
}
|
|
4373
|
+
function HustleChatInner(props) {
|
|
4374
|
+
return /* @__PURE__ */ jsxRuntime.jsx(HustleChat, { ...props, hideHeader: true });
|
|
4375
|
+
}
|
|
4376
|
+
function getPositionStyles(position, offset, isOpen, size) {
|
|
4377
|
+
const panelGap = 16;
|
|
4378
|
+
switch (position) {
|
|
4379
|
+
case "bottom-right":
|
|
4380
|
+
return {
|
|
4381
|
+
container: {
|
|
4382
|
+
bottom: `${offset.y}px`,
|
|
4383
|
+
right: `${offset.x}px`
|
|
4384
|
+
},
|
|
4385
|
+
launcher: {},
|
|
4386
|
+
panel: {
|
|
4387
|
+
bottom: `${56 + panelGap}px`,
|
|
4388
|
+
right: 0
|
|
4389
|
+
}
|
|
4390
|
+
};
|
|
4391
|
+
case "bottom-left":
|
|
4392
|
+
return {
|
|
4393
|
+
container: {
|
|
4394
|
+
bottom: `${offset.y}px`,
|
|
4395
|
+
left: `${offset.x}px`
|
|
4396
|
+
},
|
|
4397
|
+
launcher: {},
|
|
4398
|
+
panel: {
|
|
4399
|
+
bottom: `${56 + panelGap}px`,
|
|
4400
|
+
left: 0
|
|
4401
|
+
}
|
|
4402
|
+
};
|
|
4403
|
+
case "top-right":
|
|
4404
|
+
return {
|
|
4405
|
+
container: {
|
|
4406
|
+
top: `${offset.y}px`,
|
|
4407
|
+
right: `${offset.x}px`
|
|
4408
|
+
},
|
|
4409
|
+
launcher: {},
|
|
4410
|
+
panel: {
|
|
4411
|
+
top: `${56 + panelGap}px`,
|
|
4412
|
+
right: 0
|
|
4413
|
+
}
|
|
4414
|
+
};
|
|
4415
|
+
case "top-left":
|
|
4416
|
+
return {
|
|
4417
|
+
container: {
|
|
4418
|
+
top: `${offset.y}px`,
|
|
4419
|
+
left: `${offset.x}px`
|
|
4420
|
+
},
|
|
4421
|
+
launcher: {},
|
|
4422
|
+
panel: {
|
|
4423
|
+
top: `${56 + panelGap}px`,
|
|
4424
|
+
left: 0
|
|
4425
|
+
}
|
|
4426
|
+
};
|
|
4427
|
+
}
|
|
4428
|
+
}
|
|
3984
4429
|
|
|
3985
4430
|
exports.HustleChat = HustleChat;
|
|
4431
|
+
exports.HustleChatWidget = HustleChatWidget;
|
|
3986
4432
|
exports.MarkdownContent = MarkdownContent;
|
|
3987
4433
|
//# sourceMappingURL=index.cjs.map
|
|
3988
4434
|
//# sourceMappingURL=index.cjs.map
|