@usecrow/ui 0.1.44 → 0.1.46
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 +351 -41
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +14 -2
- package/dist/index.d.ts +14 -2
- package/dist/index.js +351 -41
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.d.cts
CHANGED
|
@@ -1075,13 +1075,24 @@ declare function WidgetHeader({ isVerifiedUser, showConversationList, onNewChat,
|
|
|
1075
1075
|
|
|
1076
1076
|
/**
|
|
1077
1077
|
* CopilotToggleButton - Edge toggle button for floating copilot
|
|
1078
|
+
*
|
|
1079
|
+
* Supports dual interaction:
|
|
1080
|
+
* - Click: toggle sidebar open/close
|
|
1081
|
+
* - Drag: resize sidebar width (when open)
|
|
1082
|
+
*
|
|
1083
|
+
* Forwards ref to the <button> so CopilotContainer can directly
|
|
1084
|
+
* manipulate its style.transition during drag for zero-lag resizing.
|
|
1078
1085
|
*/
|
|
1079
1086
|
interface CopilotToggleButtonProps {
|
|
1080
1087
|
isOpen: boolean;
|
|
1081
1088
|
position: "left" | "right";
|
|
1082
1089
|
onClick: () => void;
|
|
1090
|
+
/** Called on mousedown to initiate potential drag-to-resize */
|
|
1091
|
+
onMouseDown?: (e: React.MouseEvent) => void;
|
|
1092
|
+
/** Whether the user is actively dragging to resize */
|
|
1093
|
+
isDragging?: boolean;
|
|
1083
1094
|
}
|
|
1084
|
-
declare
|
|
1095
|
+
declare const CopilotToggleButton: react.ForwardRefExoticComponent<CopilotToggleButtonProps & react.RefAttributes<HTMLButtonElement>>;
|
|
1085
1096
|
|
|
1086
1097
|
interface CopilotContainerProps {
|
|
1087
1098
|
position: "left" | "right";
|
|
@@ -1089,8 +1100,9 @@ interface CopilotContainerProps {
|
|
|
1089
1100
|
defaultOpen: boolean;
|
|
1090
1101
|
children: (controls: {
|
|
1091
1102
|
close: () => void;
|
|
1103
|
+
currentWidth: number;
|
|
1092
1104
|
}) => ReactNode;
|
|
1093
1105
|
}
|
|
1094
|
-
declare function CopilotContainer({ position, width, defaultOpen, children, }: CopilotContainerProps): react_jsx_runtime.JSX.Element;
|
|
1106
|
+
declare function CopilotContainer({ position, width: initialWidth, defaultOpen, children, }: CopilotContainerProps): react_jsx_runtime.JSX.Element;
|
|
1095
1107
|
|
|
1096
1108
|
export { AVAILABLE_MODELS, type ActiveWorkflow, type AnimationsConfig, CSS_VAR_NAMES, ChatBubble, type Citation, type ClientToolHandler, type ColorsConfig, type Conversation, ConversationList, type CopilotBrandingConfig, CopilotContainer, type CopilotDimensionsConfig, type CopilotPositionConfig, type CopilotStyleConfig, CopilotStyleProvider, CopilotToggleButton, CrowCopilot, type CrowCopilotProps, CrowProvider, CrowWidget, type CrowWidgetProps, DEFAULT_COPILOT_STYLES, DEFAULT_MODEL, DEFAULT_WELCOME_MESSAGE, DEFAULT_WIDGET_STYLES, type IdentifyData, type IdentifyFunction, type JourneyEvent, LoadingHistory, MESSAGES_CONTAINER_ID, type Message, MessageBubble, MessageList, MessagesContainer, type Model, ModelSelector, PoweredByBadge, PromptInputBox, ReasoningTrace, type ResolvedCopilotStyles, type ResolvedWidgetStyles, ShadowContainer, StreamingText, ThinkingIndicator, type ToolCall, type ToolHandler, type ToolRenderers, type ToolsMap, type TypographyConfig, WIDGET_CSS, type WidgetBrandingConfig, type WidgetBubbleConfig, type WidgetConfigResponse, type WidgetDimensionsConfig, WidgetHeader, type WidgetPositionConfig, type WidgetProps, type WidgetShadowsConfig, WidgetShell, type WidgetStyleConfig, WidgetStyleProvider, WorkflowPanel, type WorkflowTodo, clearStyleCache, getCssVar, injectStyles, mergeCopilotStyles, mergeWidgetStyles, stylesToCSSVariables, stylesToCssVars, useChat, useConversations, useCopilotStyleContext, useCopilotStyles$1 as useCopilotStyles, useCopilotStyles as useCopilotStylesContext, useCrowAPI, usePreviewCopilotStyles, usePreviewWidgetStyles, useWidgetStyleContext, useWidgetStyles$1 as useWidgetStyles, useWidgetStyles as useWidgetStylesContext, useWorkflow };
|
package/dist/index.d.ts
CHANGED
|
@@ -1075,13 +1075,24 @@ declare function WidgetHeader({ isVerifiedUser, showConversationList, onNewChat,
|
|
|
1075
1075
|
|
|
1076
1076
|
/**
|
|
1077
1077
|
* CopilotToggleButton - Edge toggle button for floating copilot
|
|
1078
|
+
*
|
|
1079
|
+
* Supports dual interaction:
|
|
1080
|
+
* - Click: toggle sidebar open/close
|
|
1081
|
+
* - Drag: resize sidebar width (when open)
|
|
1082
|
+
*
|
|
1083
|
+
* Forwards ref to the <button> so CopilotContainer can directly
|
|
1084
|
+
* manipulate its style.transition during drag for zero-lag resizing.
|
|
1078
1085
|
*/
|
|
1079
1086
|
interface CopilotToggleButtonProps {
|
|
1080
1087
|
isOpen: boolean;
|
|
1081
1088
|
position: "left" | "right";
|
|
1082
1089
|
onClick: () => void;
|
|
1090
|
+
/** Called on mousedown to initiate potential drag-to-resize */
|
|
1091
|
+
onMouseDown?: (e: React.MouseEvent) => void;
|
|
1092
|
+
/** Whether the user is actively dragging to resize */
|
|
1093
|
+
isDragging?: boolean;
|
|
1083
1094
|
}
|
|
1084
|
-
declare
|
|
1095
|
+
declare const CopilotToggleButton: react.ForwardRefExoticComponent<CopilotToggleButtonProps & react.RefAttributes<HTMLButtonElement>>;
|
|
1085
1096
|
|
|
1086
1097
|
interface CopilotContainerProps {
|
|
1087
1098
|
position: "left" | "right";
|
|
@@ -1089,8 +1100,9 @@ interface CopilotContainerProps {
|
|
|
1089
1100
|
defaultOpen: boolean;
|
|
1090
1101
|
children: (controls: {
|
|
1091
1102
|
close: () => void;
|
|
1103
|
+
currentWidth: number;
|
|
1092
1104
|
}) => ReactNode;
|
|
1093
1105
|
}
|
|
1094
|
-
declare function CopilotContainer({ position, width, defaultOpen, children, }: CopilotContainerProps): react_jsx_runtime.JSX.Element;
|
|
1106
|
+
declare function CopilotContainer({ position, width: initialWidth, defaultOpen, children, }: CopilotContainerProps): react_jsx_runtime.JSX.Element;
|
|
1095
1107
|
|
|
1096
1108
|
export { AVAILABLE_MODELS, type ActiveWorkflow, type AnimationsConfig, CSS_VAR_NAMES, ChatBubble, type Citation, type ClientToolHandler, type ColorsConfig, type Conversation, ConversationList, type CopilotBrandingConfig, CopilotContainer, type CopilotDimensionsConfig, type CopilotPositionConfig, type CopilotStyleConfig, CopilotStyleProvider, CopilotToggleButton, CrowCopilot, type CrowCopilotProps, CrowProvider, CrowWidget, type CrowWidgetProps, DEFAULT_COPILOT_STYLES, DEFAULT_MODEL, DEFAULT_WELCOME_MESSAGE, DEFAULT_WIDGET_STYLES, type IdentifyData, type IdentifyFunction, type JourneyEvent, LoadingHistory, MESSAGES_CONTAINER_ID, type Message, MessageBubble, MessageList, MessagesContainer, type Model, ModelSelector, PoweredByBadge, PromptInputBox, ReasoningTrace, type ResolvedCopilotStyles, type ResolvedWidgetStyles, ShadowContainer, StreamingText, ThinkingIndicator, type ToolCall, type ToolHandler, type ToolRenderers, type ToolsMap, type TypographyConfig, WIDGET_CSS, type WidgetBrandingConfig, type WidgetBubbleConfig, type WidgetConfigResponse, type WidgetDimensionsConfig, WidgetHeader, type WidgetPositionConfig, type WidgetProps, type WidgetShadowsConfig, WidgetShell, type WidgetStyleConfig, WidgetStyleProvider, WorkflowPanel, type WorkflowTodo, clearStyleCache, getCssVar, injectStyles, mergeCopilotStyles, mergeWidgetStyles, stylesToCSSVariables, stylesToCssVars, useChat, useConversations, useCopilotStyleContext, useCopilotStyles$1 as useCopilotStyles, useCopilotStyles as useCopilotStylesContext, useCrowAPI, usePreviewCopilotStyles, usePreviewWidgetStyles, useWidgetStyleContext, useWidgetStyles$1 as useWidgetStyles, useWidgetStyles as useWidgetStylesContext, useWorkflow };
|
package/dist/index.js
CHANGED
|
@@ -123,7 +123,7 @@ function useChat({
|
|
|
123
123
|
identity_token: identityToken,
|
|
124
124
|
model: selectedModel,
|
|
125
125
|
user_timezone: Intl.DateTimeFormat().resolvedOptions().timeZone,
|
|
126
|
-
user_local_time: (/* @__PURE__ */ new Date()).toLocaleString(),
|
|
126
|
+
user_local_time: (/* @__PURE__ */ new Date()).toLocaleString("en-US", { year: "numeric", month: "long", day: "numeric", hour: "numeric", minute: "numeric", hour12: true }),
|
|
127
127
|
page_path: typeof window !== "undefined" ? window.location.pathname : void 0,
|
|
128
128
|
context: typeof window !== "undefined" ? window.__crow_page_context : void 0
|
|
129
129
|
}),
|
|
@@ -482,7 +482,7 @@ function useChat({
|
|
|
482
482
|
identity_token: identityToken,
|
|
483
483
|
model: selectedModel,
|
|
484
484
|
user_timezone: Intl.DateTimeFormat().resolvedOptions().timeZone,
|
|
485
|
-
user_local_time: (/* @__PURE__ */ new Date()).toLocaleString()
|
|
485
|
+
user_local_time: (/* @__PURE__ */ new Date()).toLocaleString("en-US", { year: "numeric", month: "long", day: "numeric", hour: "numeric", minute: "numeric", hour12: true })
|
|
486
486
|
})
|
|
487
487
|
});
|
|
488
488
|
if (!response.ok) {
|
|
@@ -3457,40 +3457,88 @@ function MessageIcon() {
|
|
|
3457
3457
|
}
|
|
3458
3458
|
);
|
|
3459
3459
|
}
|
|
3460
|
-
|
|
3461
|
-
isOpen,
|
|
3462
|
-
|
|
3463
|
-
|
|
3464
|
-
|
|
3465
|
-
|
|
3466
|
-
|
|
3467
|
-
|
|
3468
|
-
|
|
3469
|
-
|
|
3470
|
-
|
|
3471
|
-
|
|
3472
|
-
|
|
3473
|
-
|
|
3474
|
-
|
|
3475
|
-
|
|
3476
|
-
|
|
3477
|
-
|
|
3478
|
-
|
|
3479
|
-
|
|
3480
|
-
}
|
|
3460
|
+
var CopilotToggleButton = forwardRef(
|
|
3461
|
+
function CopilotToggleButton2({ isOpen, position, onClick, onMouseDown, isDragging }, ref) {
|
|
3462
|
+
const renderIcon = () => {
|
|
3463
|
+
if (!isOpen) return /* @__PURE__ */ jsx(MessageIcon, {});
|
|
3464
|
+
if (position === "right") return /* @__PURE__ */ jsx(ChevronRight2, {});
|
|
3465
|
+
return /* @__PURE__ */ jsx(ChevronLeft, {});
|
|
3466
|
+
};
|
|
3467
|
+
return /* @__PURE__ */ jsx(
|
|
3468
|
+
"button",
|
|
3469
|
+
{
|
|
3470
|
+
ref,
|
|
3471
|
+
onClick,
|
|
3472
|
+
onMouseDown,
|
|
3473
|
+
className: `crow-copilot-toggle crow-copilot-toggle-${position} ${isOpen ? "open" : ""} ${isDragging ? "dragging" : ""}`,
|
|
3474
|
+
style: {
|
|
3475
|
+
cursor: isOpen ? "col-resize" : void 0
|
|
3476
|
+
},
|
|
3477
|
+
"aria-label": isOpen ? "Close Copilot" : "Open Copilot",
|
|
3478
|
+
title: isOpen ? "Close Copilot" : "Open Copilot",
|
|
3479
|
+
children: renderIcon()
|
|
3480
|
+
}
|
|
3481
|
+
);
|
|
3482
|
+
}
|
|
3483
|
+
);
|
|
3484
|
+
var DRAG_THRESHOLD = 5;
|
|
3485
|
+
var MIN_WIDTH = 280;
|
|
3486
|
+
var MAX_WIDTH = 800;
|
|
3481
3487
|
function CopilotContainer({
|
|
3482
3488
|
position,
|
|
3483
|
-
width,
|
|
3489
|
+
width: initialWidth,
|
|
3484
3490
|
defaultOpen,
|
|
3485
3491
|
children
|
|
3486
3492
|
}) {
|
|
3487
|
-
const [isOpen, setIsOpen] = useState(
|
|
3493
|
+
const [isOpen, setIsOpen] = useState(() => {
|
|
3494
|
+
try {
|
|
3495
|
+
const stored = sessionStorage.getItem("crow_copilot_open");
|
|
3496
|
+
if (stored !== null) return stored === "true";
|
|
3497
|
+
} catch {
|
|
3498
|
+
}
|
|
3499
|
+
return defaultOpen;
|
|
3500
|
+
});
|
|
3501
|
+
const [currentWidth, setCurrentWidth] = useState(() => {
|
|
3502
|
+
try {
|
|
3503
|
+
const stored = sessionStorage.getItem("crow_copilot_width");
|
|
3504
|
+
if (stored) {
|
|
3505
|
+
const parsed = parseInt(stored, 10);
|
|
3506
|
+
if (parsed >= MIN_WIDTH && parsed <= MAX_WIDTH) return parsed;
|
|
3507
|
+
}
|
|
3508
|
+
} catch {
|
|
3509
|
+
}
|
|
3510
|
+
return initialWidth;
|
|
3511
|
+
});
|
|
3512
|
+
const [isDragging, setIsDragging] = useState(false);
|
|
3513
|
+
useEffect(() => {
|
|
3514
|
+
try {
|
|
3515
|
+
sessionStorage.setItem("crow_copilot_open", String(isOpen));
|
|
3516
|
+
} catch {
|
|
3517
|
+
}
|
|
3518
|
+
}, [isOpen]);
|
|
3519
|
+
useEffect(() => {
|
|
3520
|
+
try {
|
|
3521
|
+
sessionStorage.setItem("crow_copilot_width", String(currentWidth));
|
|
3522
|
+
} catch {
|
|
3523
|
+
}
|
|
3524
|
+
}, [currentWidth]);
|
|
3525
|
+
const sidebarRef = useRef(null);
|
|
3526
|
+
const toggleRef = useRef(null);
|
|
3527
|
+
const dragStartXRef = useRef(0);
|
|
3528
|
+
const dragStartWidthRef = useRef(0);
|
|
3529
|
+
const hasDraggedRef = useRef(false);
|
|
3530
|
+
const liveWidthRef = useRef(initialWidth);
|
|
3531
|
+
const positionRef = useRef(position);
|
|
3532
|
+
positionRef.current = position;
|
|
3533
|
+
useEffect(() => {
|
|
3534
|
+
liveWidthRef.current = currentWidth;
|
|
3535
|
+
}, [currentWidth]);
|
|
3488
3536
|
useEffect(() => {
|
|
3489
3537
|
document.documentElement.style.setProperty(
|
|
3490
3538
|
"--crow-copilot-width",
|
|
3491
|
-
`${
|
|
3539
|
+
`${currentWidth}px`
|
|
3492
3540
|
);
|
|
3493
|
-
}, [
|
|
3541
|
+
}, [currentWidth]);
|
|
3494
3542
|
useEffect(() => {
|
|
3495
3543
|
const className = `crow-copilot-open-${position}`;
|
|
3496
3544
|
if (isOpen) {
|
|
@@ -3512,21 +3560,97 @@ function CopilotContainer({
|
|
|
3512
3560
|
delete window.crowCopilot;
|
|
3513
3561
|
};
|
|
3514
3562
|
}, []);
|
|
3563
|
+
const handleMouseMove = useCallback(
|
|
3564
|
+
(e) => {
|
|
3565
|
+
const deltaX = e.clientX - dragStartXRef.current;
|
|
3566
|
+
if (!hasDraggedRef.current && Math.abs(deltaX) >= DRAG_THRESHOLD) {
|
|
3567
|
+
hasDraggedRef.current = true;
|
|
3568
|
+
document.body.style.transition = "none";
|
|
3569
|
+
document.body.style.cursor = "col-resize";
|
|
3570
|
+
document.body.style.userSelect = "none";
|
|
3571
|
+
document.body.classList.add("crow-copilot-resizing");
|
|
3572
|
+
if (sidebarRef.current) {
|
|
3573
|
+
sidebarRef.current.style.transition = "none";
|
|
3574
|
+
}
|
|
3575
|
+
if (toggleRef.current) {
|
|
3576
|
+
toggleRef.current.style.transition = "none";
|
|
3577
|
+
}
|
|
3578
|
+
setIsDragging(true);
|
|
3579
|
+
}
|
|
3580
|
+
if (!hasDraggedRef.current) return;
|
|
3581
|
+
const widthDelta = positionRef.current === "right" ? -deltaX : deltaX;
|
|
3582
|
+
const newWidth = Math.min(
|
|
3583
|
+
MAX_WIDTH,
|
|
3584
|
+
Math.max(MIN_WIDTH, dragStartWidthRef.current + widthDelta)
|
|
3585
|
+
);
|
|
3586
|
+
liveWidthRef.current = newWidth;
|
|
3587
|
+
const px = `${newWidth}px`;
|
|
3588
|
+
document.documentElement.style.setProperty("--crow-copilot-width", px);
|
|
3589
|
+
if (sidebarRef.current) {
|
|
3590
|
+
sidebarRef.current.style.width = px;
|
|
3591
|
+
}
|
|
3592
|
+
},
|
|
3593
|
+
[]
|
|
3594
|
+
// no deps — we use refs for everything to avoid stale closures
|
|
3595
|
+
);
|
|
3596
|
+
const handleMouseUp = useCallback(() => {
|
|
3597
|
+
document.removeEventListener("mousemove", handleMouseMove);
|
|
3598
|
+
document.removeEventListener("mouseup", handleMouseUp);
|
|
3599
|
+
document.body.style.transition = "";
|
|
3600
|
+
document.body.style.cursor = "";
|
|
3601
|
+
document.body.style.userSelect = "";
|
|
3602
|
+
document.body.classList.remove("crow-copilot-resizing");
|
|
3603
|
+
if (sidebarRef.current) {
|
|
3604
|
+
sidebarRef.current.style.transition = "";
|
|
3605
|
+
}
|
|
3606
|
+
if (toggleRef.current) {
|
|
3607
|
+
toggleRef.current.style.transition = "";
|
|
3608
|
+
}
|
|
3609
|
+
if (hasDraggedRef.current) {
|
|
3610
|
+
setCurrentWidth(liveWidthRef.current);
|
|
3611
|
+
setIsDragging(false);
|
|
3612
|
+
} else {
|
|
3613
|
+
setIsDragging(false);
|
|
3614
|
+
setIsOpen((prev) => !prev);
|
|
3615
|
+
}
|
|
3616
|
+
}, [handleMouseMove]);
|
|
3617
|
+
const handleToggleMouseDown = useCallback(
|
|
3618
|
+
(e) => {
|
|
3619
|
+
if (e.button !== 0 || !isOpen) return;
|
|
3620
|
+
e.preventDefault();
|
|
3621
|
+
e.stopPropagation();
|
|
3622
|
+
dragStartXRef.current = e.clientX;
|
|
3623
|
+
dragStartWidthRef.current = liveWidthRef.current;
|
|
3624
|
+
hasDraggedRef.current = false;
|
|
3625
|
+
document.addEventListener("mousemove", handleMouseMove);
|
|
3626
|
+
document.addEventListener("mouseup", handleMouseUp);
|
|
3627
|
+
},
|
|
3628
|
+
[isOpen, handleMouseMove, handleMouseUp]
|
|
3629
|
+
);
|
|
3630
|
+
const handleToggleClick = useCallback(() => {
|
|
3631
|
+
if (!isOpen) {
|
|
3632
|
+
setIsOpen(true);
|
|
3633
|
+
}
|
|
3634
|
+
}, [isOpen]);
|
|
3515
3635
|
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
3516
3636
|
/* @__PURE__ */ jsx(
|
|
3517
3637
|
CopilotToggleButton,
|
|
3518
3638
|
{
|
|
3639
|
+
ref: toggleRef,
|
|
3519
3640
|
isOpen,
|
|
3520
3641
|
position,
|
|
3521
|
-
onClick:
|
|
3642
|
+
onClick: handleToggleClick,
|
|
3643
|
+
onMouseDown: handleToggleMouseDown,
|
|
3644
|
+
isDragging
|
|
3522
3645
|
}
|
|
3523
3646
|
),
|
|
3524
3647
|
/* @__PURE__ */ jsx(
|
|
3525
3648
|
"div",
|
|
3526
3649
|
{
|
|
3650
|
+
ref: sidebarRef,
|
|
3527
3651
|
className: `crow-copilot-sidebar crow-copilot-sidebar-${position} ${isOpen ? "" : "closed"}`,
|
|
3528
|
-
style: { width: `${
|
|
3529
|
-
children: children({ close: () => setIsOpen(false) })
|
|
3652
|
+
style: { width: `${currentWidth}px` },
|
|
3653
|
+
children: children({ close: () => setIsOpen(false), currentWidth })
|
|
3530
3654
|
}
|
|
3531
3655
|
)
|
|
3532
3656
|
] });
|
|
@@ -3609,6 +3733,93 @@ function CrowCopilot({
|
|
|
3609
3733
|
window.crow?.("registerTools", autoTools);
|
|
3610
3734
|
}
|
|
3611
3735
|
}, [autoTools]);
|
|
3736
|
+
const embeddedInitialWidth = typeof width === "number" ? width : parseInt(String(width), 10) || 400;
|
|
3737
|
+
const [embeddedWidth, setEmbeddedWidth] = useState(() => {
|
|
3738
|
+
try {
|
|
3739
|
+
const stored = sessionStorage.getItem("crow_embedded_width");
|
|
3740
|
+
if (stored) {
|
|
3741
|
+
const parsed = parseInt(stored, 10);
|
|
3742
|
+
if (parsed >= 280 && parsed <= 800) return parsed;
|
|
3743
|
+
}
|
|
3744
|
+
} catch {
|
|
3745
|
+
}
|
|
3746
|
+
return embeddedInitialWidth;
|
|
3747
|
+
});
|
|
3748
|
+
const [isCollapsed, setIsCollapsed] = useState(() => {
|
|
3749
|
+
try {
|
|
3750
|
+
return sessionStorage.getItem("crow_embedded_collapsed") === "true";
|
|
3751
|
+
} catch {
|
|
3752
|
+
return false;
|
|
3753
|
+
}
|
|
3754
|
+
});
|
|
3755
|
+
useEffect(() => {
|
|
3756
|
+
try {
|
|
3757
|
+
sessionStorage.setItem("crow_embedded_width", String(embeddedWidth));
|
|
3758
|
+
} catch {
|
|
3759
|
+
}
|
|
3760
|
+
}, [embeddedWidth]);
|
|
3761
|
+
useEffect(() => {
|
|
3762
|
+
try {
|
|
3763
|
+
sessionStorage.setItem("crow_embedded_collapsed", String(isCollapsed));
|
|
3764
|
+
} catch {
|
|
3765
|
+
}
|
|
3766
|
+
}, [isCollapsed]);
|
|
3767
|
+
const embeddedContentRef = useRef(null);
|
|
3768
|
+
const embeddedToggleRef = useRef(null);
|
|
3769
|
+
const embeddedDragStartX = useRef(0);
|
|
3770
|
+
const embeddedDragStartW = useRef(0);
|
|
3771
|
+
const embeddedHasDragged = useRef(false);
|
|
3772
|
+
const embeddedLiveWidth = useRef(embeddedInitialWidth);
|
|
3773
|
+
const positionRef = useRef(position);
|
|
3774
|
+
positionRef.current = position;
|
|
3775
|
+
useEffect(() => {
|
|
3776
|
+
embeddedLiveWidth.current = embeddedWidth;
|
|
3777
|
+
}, [embeddedWidth]);
|
|
3778
|
+
const embeddedMouseMove = useCallback((e) => {
|
|
3779
|
+
const dx = e.clientX - embeddedDragStartX.current;
|
|
3780
|
+
if (!embeddedHasDragged.current && Math.abs(dx) >= 5) {
|
|
3781
|
+
embeddedHasDragged.current = true;
|
|
3782
|
+
document.body.style.cursor = "col-resize";
|
|
3783
|
+
document.body.style.userSelect = "none";
|
|
3784
|
+
}
|
|
3785
|
+
if (!embeddedHasDragged.current) return;
|
|
3786
|
+
const delta = positionRef.current === "right" ? -dx : dx;
|
|
3787
|
+
const newW = Math.min(800, Math.max(280, embeddedDragStartW.current + delta));
|
|
3788
|
+
embeddedLiveWidth.current = newW;
|
|
3789
|
+
if (embeddedContentRef.current) {
|
|
3790
|
+
embeddedContentRef.current.style.width = `${newW}px`;
|
|
3791
|
+
}
|
|
3792
|
+
}, []);
|
|
3793
|
+
const embeddedMouseUp = useCallback(() => {
|
|
3794
|
+
document.removeEventListener("mousemove", embeddedMouseMove);
|
|
3795
|
+
document.removeEventListener("mouseup", embeddedMouseUp);
|
|
3796
|
+
document.body.style.cursor = "";
|
|
3797
|
+
document.body.style.userSelect = "";
|
|
3798
|
+
if (embeddedHasDragged.current) {
|
|
3799
|
+
setEmbeddedWidth(embeddedLiveWidth.current);
|
|
3800
|
+
} else {
|
|
3801
|
+
setIsCollapsed((prev) => !prev);
|
|
3802
|
+
}
|
|
3803
|
+
}, [embeddedMouseMove]);
|
|
3804
|
+
const embeddedHandleMouseDown = useCallback(
|
|
3805
|
+
(e) => {
|
|
3806
|
+
if (e.button !== 0) return;
|
|
3807
|
+
if (isCollapsed) return;
|
|
3808
|
+
e.preventDefault();
|
|
3809
|
+
e.stopPropagation();
|
|
3810
|
+
embeddedDragStartX.current = e.clientX;
|
|
3811
|
+
embeddedDragStartW.current = embeddedLiveWidth.current;
|
|
3812
|
+
embeddedHasDragged.current = false;
|
|
3813
|
+
document.addEventListener("mousemove", embeddedMouseMove);
|
|
3814
|
+
document.addEventListener("mouseup", embeddedMouseUp);
|
|
3815
|
+
},
|
|
3816
|
+
[isCollapsed, embeddedMouseMove, embeddedMouseUp]
|
|
3817
|
+
);
|
|
3818
|
+
const embeddedHandleClick = useCallback(() => {
|
|
3819
|
+
if (isCollapsed) {
|
|
3820
|
+
setIsCollapsed(false);
|
|
3821
|
+
}
|
|
3822
|
+
}, [isCollapsed]);
|
|
3612
3823
|
const messagesContainerRef = useRef(null);
|
|
3613
3824
|
const tabsScrollRef = useRef(null);
|
|
3614
3825
|
const executeClientToolRef = useRef(null);
|
|
@@ -3628,6 +3839,16 @@ function CrowCopilot({
|
|
|
3628
3839
|
const conversations = useConversations({ productId, apiUrl });
|
|
3629
3840
|
const [shouldRestoreHistory, setShouldRestoreHistory] = useState(false);
|
|
3630
3841
|
const hasRestoredHistoryRef = useRef(false);
|
|
3842
|
+
const activeConvStorageKey = `crow_active_conv_${productId}`;
|
|
3843
|
+
const pendingRestoreConvId = useRef(null);
|
|
3844
|
+
const hasRestoredActiveConvRef = useRef(false);
|
|
3845
|
+
if (pendingRestoreConvId.current === null) {
|
|
3846
|
+
try {
|
|
3847
|
+
pendingRestoreConvId.current = localStorage.getItem(activeConvStorageKey) || "";
|
|
3848
|
+
} catch {
|
|
3849
|
+
pendingRestoreConvId.current = "";
|
|
3850
|
+
}
|
|
3851
|
+
}
|
|
3631
3852
|
const chat = useChat({
|
|
3632
3853
|
productId,
|
|
3633
3854
|
apiUrl,
|
|
@@ -3714,6 +3935,32 @@ function CrowCopilot({
|
|
|
3714
3935
|
});
|
|
3715
3936
|
}
|
|
3716
3937
|
}, [shouldRestoreHistory, chat.conversationId, conversations, chat]);
|
|
3938
|
+
useEffect(() => {
|
|
3939
|
+
if (isLoadingStyles || hasRestoredActiveConvRef.current) return;
|
|
3940
|
+
const timer = setTimeout(() => {
|
|
3941
|
+
if (hasRestoredActiveConvRef.current || isVerifiedUser) return;
|
|
3942
|
+
const savedId = pendingRestoreConvId.current;
|
|
3943
|
+
if (!savedId) return;
|
|
3944
|
+
hasRestoredActiveConvRef.current = true;
|
|
3945
|
+
pendingRestoreConvId.current = "";
|
|
3946
|
+
conversations.loadAnonymousConversationHistory(savedId).then((historyMessages) => {
|
|
3947
|
+
if (historyMessages.length > 0) {
|
|
3948
|
+
chat.loadMessages(historyMessages);
|
|
3949
|
+
chat.setConversationId(savedId);
|
|
3950
|
+
}
|
|
3951
|
+
}).catch(() => {
|
|
3952
|
+
});
|
|
3953
|
+
}, 500);
|
|
3954
|
+
return () => clearTimeout(timer);
|
|
3955
|
+
}, [isLoadingStyles]);
|
|
3956
|
+
useEffect(() => {
|
|
3957
|
+
try {
|
|
3958
|
+
if (chat.conversationId) {
|
|
3959
|
+
localStorage.setItem(activeConvStorageKey, chat.conversationId);
|
|
3960
|
+
}
|
|
3961
|
+
} catch {
|
|
3962
|
+
}
|
|
3963
|
+
}, [chat.conversationId, activeConvStorageKey]);
|
|
3717
3964
|
useEffect(() => {
|
|
3718
3965
|
if (variant === "floating") {
|
|
3719
3966
|
injectCopilotBodyStyles();
|
|
@@ -3747,6 +3994,19 @@ function CrowCopilot({
|
|
|
3747
3994
|
onIdentified: async () => {
|
|
3748
3995
|
setIsVerifiedUser(true);
|
|
3749
3996
|
await conversations.loadConversations();
|
|
3997
|
+
const savedId = pendingRestoreConvId.current;
|
|
3998
|
+
if (savedId && !hasRestoredActiveConvRef.current) {
|
|
3999
|
+
hasRestoredActiveConvRef.current = true;
|
|
4000
|
+
pendingRestoreConvId.current = "";
|
|
4001
|
+
try {
|
|
4002
|
+
const historyMessages = await conversations.loadConversationHistory(savedId);
|
|
4003
|
+
if (historyMessages.length > 0) {
|
|
4004
|
+
chat.loadMessages(historyMessages);
|
|
4005
|
+
chat.setConversationId(savedId);
|
|
4006
|
+
}
|
|
4007
|
+
} catch {
|
|
4008
|
+
}
|
|
4009
|
+
}
|
|
3750
4010
|
},
|
|
3751
4011
|
onReset: () => {
|
|
3752
4012
|
setIsVerifiedUser(false);
|
|
@@ -3998,7 +4258,7 @@ function CrowCopilot({
|
|
|
3998
4258
|
checkTabsOverflow();
|
|
3999
4259
|
}, [tabs.length, checkTabsOverflow]);
|
|
4000
4260
|
const widthStyle = typeof width === "number" ? `${width}px` : width;
|
|
4001
|
-
const renderCopilotContent = (overrideOnClose, forceShowClose) => /* @__PURE__ */ jsx(
|
|
4261
|
+
const renderCopilotContent = (overrideOnClose, forceShowClose, overrideWidth) => /* @__PURE__ */ jsx(
|
|
4002
4262
|
CopilotStyleProvider,
|
|
4003
4263
|
{
|
|
4004
4264
|
styles,
|
|
@@ -4009,7 +4269,7 @@ function CrowCopilot({
|
|
|
4009
4269
|
{
|
|
4010
4270
|
className: `crow-flex crow-flex-col crow-h-full ${position === "left" ? "crow-border-r" : "crow-border-l"} ${className || ""}`,
|
|
4011
4271
|
style: {
|
|
4012
|
-
width: widthStyle,
|
|
4272
|
+
width: overrideWidth ? typeof overrideWidth === "number" ? `${overrideWidth}px` : overrideWidth : widthStyle,
|
|
4013
4273
|
fontFamily: styles.typography.fontFamily,
|
|
4014
4274
|
fontSize: styles.typography.fontSize,
|
|
4015
4275
|
fontWeight: styles.typography.fontWeight,
|
|
@@ -4241,15 +4501,65 @@ function CrowCopilot({
|
|
|
4241
4501
|
}
|
|
4242
4502
|
);
|
|
4243
4503
|
const floatingWidth = typeof width === "number" ? width : parseInt(String(width), 10) || 400;
|
|
4244
|
-
|
|
4245
|
-
|
|
4246
|
-
|
|
4247
|
-
|
|
4248
|
-
|
|
4249
|
-
|
|
4250
|
-
|
|
4251
|
-
|
|
4252
|
-
|
|
4504
|
+
if (variant === "floating") {
|
|
4505
|
+
return /* @__PURE__ */ jsx(ShadowContainer, { styles: WIDGET_CSS, children: /* @__PURE__ */ jsx(
|
|
4506
|
+
CopilotContainer,
|
|
4507
|
+
{
|
|
4508
|
+
position,
|
|
4509
|
+
width: floatingWidth,
|
|
4510
|
+
defaultOpen,
|
|
4511
|
+
children: ({ close, currentWidth: resizedWidth }) => renderCopilotContent(close, true, resizedWidth)
|
|
4512
|
+
}
|
|
4513
|
+
) });
|
|
4514
|
+
}
|
|
4515
|
+
const isRight = position === "right";
|
|
4516
|
+
const edgeSide = isRight ? "left" : "right";
|
|
4517
|
+
const toggleIcon = isCollapsed ? /* @__PURE__ */ jsx("svg", { xmlns: "http://www.w3.org/2000/svg", width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "#6b7280", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ jsx("path", { d: "M7.9 20A9 9 0 1 0 4 16.1L2 22Z" }) }) : /* @__PURE__ */ jsx("svg", { xmlns: "http://www.w3.org/2000/svg", width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "#6b7280", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: isRight ? /* @__PURE__ */ jsx("path", { d: "m9 18 6-6-6-6" }) : /* @__PURE__ */ jsx("path", { d: "m15 18-6-6 6-6" }) });
|
|
4518
|
+
return /* @__PURE__ */ jsxs("div", { style: { position: "relative", flexShrink: 0, height: "100%" }, children: [
|
|
4519
|
+
/* @__PURE__ */ jsx(
|
|
4520
|
+
"button",
|
|
4521
|
+
{
|
|
4522
|
+
ref: embeddedToggleRef,
|
|
4523
|
+
onMouseDown: embeddedHandleMouseDown,
|
|
4524
|
+
onClick: embeddedHandleClick,
|
|
4525
|
+
style: {
|
|
4526
|
+
position: "absolute",
|
|
4527
|
+
[edgeSide]: "-12px",
|
|
4528
|
+
top: "50%",
|
|
4529
|
+
transform: "translateY(-50%)",
|
|
4530
|
+
zIndex: 10,
|
|
4531
|
+
width: "24px",
|
|
4532
|
+
height: "64px",
|
|
4533
|
+
display: "flex",
|
|
4534
|
+
alignItems: "center",
|
|
4535
|
+
justifyContent: "center",
|
|
4536
|
+
background: "#fff",
|
|
4537
|
+
border: "1px solid #e5e7eb",
|
|
4538
|
+
[isRight ? "borderRight" : "borderLeft"]: "none",
|
|
4539
|
+
borderRadius: isRight ? "8px 0 0 8px" : "0 8px 8px 0",
|
|
4540
|
+
cursor: isCollapsed ? "pointer" : "col-resize",
|
|
4541
|
+
boxShadow: "0 2px 8px rgba(0,0,0,0.1)",
|
|
4542
|
+
padding: 0,
|
|
4543
|
+
outline: "none"
|
|
4544
|
+
},
|
|
4545
|
+
"aria-label": isCollapsed ? "Open Copilot" : "Resize or close Copilot",
|
|
4546
|
+
children: toggleIcon
|
|
4547
|
+
}
|
|
4548
|
+
),
|
|
4549
|
+
/* @__PURE__ */ jsx(
|
|
4550
|
+
"div",
|
|
4551
|
+
{
|
|
4552
|
+
ref: embeddedContentRef,
|
|
4553
|
+
style: {
|
|
4554
|
+
width: `${embeddedWidth}px`,
|
|
4555
|
+
height: "100%",
|
|
4556
|
+
display: isCollapsed ? "none" : "block",
|
|
4557
|
+
overflow: "hidden"
|
|
4558
|
+
},
|
|
4559
|
+
children: /* @__PURE__ */ jsx(ShadowContainer, { styles: WIDGET_CSS, children: renderCopilotContent(void 0, false, "100%") })
|
|
4560
|
+
}
|
|
4561
|
+
)
|
|
4562
|
+
] });
|
|
4253
4563
|
}
|
|
4254
4564
|
function PlusIcon({ className }) {
|
|
4255
4565
|
return /* @__PURE__ */ jsxs(
|