299 lines
13 KiB
JavaScript
299 lines
13 KiB
JavaScript
const require_runtime = require('../../_virtual/_rolldown/runtime.cjs');
|
|
const require_CopilotChatConfigurationProvider = require('../../providers/CopilotChatConfigurationProvider.cjs');
|
|
const require_utils = require('../../lib/utils.cjs');
|
|
const require_button = require('../ui/button.cjs');
|
|
const require_slots = require('../../lib/slots.cjs');
|
|
const require_CopilotChatInput = require('./CopilotChatInput.cjs');
|
|
const require_CopilotChatSuggestionView = require('./CopilotChatSuggestionView.cjs');
|
|
const require_CopilotChatMessageView = require('./CopilotChatMessageView.cjs');
|
|
const require_use_keyboard_height = require('../../hooks/use-keyboard-height.cjs');
|
|
let react = require("react");
|
|
react = require_runtime.__toESM(react);
|
|
let tailwind_merge = require("tailwind-merge");
|
|
let lucide_react = require("lucide-react");
|
|
let react_jsx_runtime = require("react/jsx-runtime");
|
|
let use_stick_to_bottom = require("use-stick-to-bottom");
|
|
|
|
//#region src/components/chat/CopilotChatView.tsx
|
|
const FEATHER_HEIGHT = 96;
|
|
function CopilotChatView({ messageView, input, scrollView, suggestionView, welcomeScreen, messages = [], autoScroll = true, isRunning = false, suggestions, suggestionLoadingIndexes, onSelectSuggestion, onSubmitMessage, onStop, inputMode, inputValue, onInputChange, onStartTranscribe, onCancelTranscribe, onFinishTranscribe, onFinishTranscribeWithAudio, disclaimer, children, className, ...props }) {
|
|
const inputContainerRef = (0, react.useRef)(null);
|
|
const [inputContainerHeight, setInputContainerHeight] = (0, react.useState)(0);
|
|
const [isResizing, setIsResizing] = (0, react.useState)(false);
|
|
const resizeTimeoutRef = (0, react.useRef)(null);
|
|
const { isKeyboardOpen, keyboardHeight, availableHeight } = require_use_keyboard_height.useKeyboardHeight();
|
|
(0, react.useEffect)(() => {
|
|
const element = inputContainerRef.current;
|
|
if (!element) return;
|
|
const resizeObserver = new ResizeObserver((entries) => {
|
|
for (const entry of entries) {
|
|
const newHeight = entry.contentRect.height;
|
|
setInputContainerHeight((prevHeight) => {
|
|
if (newHeight !== prevHeight) {
|
|
setIsResizing(true);
|
|
if (resizeTimeoutRef.current) clearTimeout(resizeTimeoutRef.current);
|
|
resizeTimeoutRef.current = setTimeout(() => {
|
|
setIsResizing(false);
|
|
}, 250);
|
|
return newHeight;
|
|
}
|
|
return prevHeight;
|
|
});
|
|
}
|
|
});
|
|
resizeObserver.observe(element);
|
|
setInputContainerHeight(element.offsetHeight);
|
|
return () => {
|
|
resizeObserver.disconnect();
|
|
if (resizeTimeoutRef.current) clearTimeout(resizeTimeoutRef.current);
|
|
};
|
|
}, []);
|
|
const BoundMessageView = require_slots.renderSlot(messageView, require_CopilotChatMessageView.default, {
|
|
messages,
|
|
isRunning
|
|
});
|
|
const BoundInput = require_slots.renderSlot(input, require_CopilotChatInput.default, {
|
|
onSubmitMessage,
|
|
onStop,
|
|
mode: inputMode,
|
|
value: inputValue,
|
|
onChange: onInputChange,
|
|
isRunning,
|
|
onStartTranscribe,
|
|
onCancelTranscribe,
|
|
onFinishTranscribe,
|
|
onFinishTranscribeWithAudio,
|
|
positioning: "absolute",
|
|
keyboardHeight: isKeyboardOpen ? keyboardHeight : 0,
|
|
containerRef: inputContainerRef,
|
|
showDisclaimer: true,
|
|
...disclaimer !== void 0 ? { disclaimer } : {}
|
|
});
|
|
const hasSuggestions = Array.isArray(suggestions) && suggestions.length > 0;
|
|
const BoundSuggestionView = hasSuggestions ? require_slots.renderSlot(suggestionView, require_CopilotChatSuggestionView.default, {
|
|
suggestions,
|
|
loadingIndexes: suggestionLoadingIndexes,
|
|
onSelectSuggestion,
|
|
className: "cpk:mb-3 cpk:lg:ml-4 cpk:lg:mr-4 cpk:ml-0 cpk:mr-0"
|
|
}) : null;
|
|
const BoundScrollView = require_slots.renderSlot(scrollView, CopilotChatView.ScrollView, {
|
|
autoScroll,
|
|
inputContainerHeight,
|
|
isResizing,
|
|
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
style: { paddingBottom: `${inputContainerHeight + FEATHER_HEIGHT + (hasSuggestions ? 4 : 32)}px` },
|
|
children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
className: "cpk:max-w-3xl cpk:mx-auto",
|
|
children: [BoundMessageView, hasSuggestions ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
className: "cpk:pl-0 cpk:pr-4 cpk:sm:px-0 cpk:mt-4",
|
|
children: BoundSuggestionView
|
|
}) : null]
|
|
})
|
|
})
|
|
});
|
|
if (messages.length === 0 && !(welcomeScreen === false)) {
|
|
const BoundInputForWelcome = require_slots.renderSlot(input, require_CopilotChatInput.default, {
|
|
onSubmitMessage,
|
|
onStop,
|
|
mode: inputMode,
|
|
value: inputValue,
|
|
onChange: onInputChange,
|
|
isRunning,
|
|
onStartTranscribe,
|
|
onCancelTranscribe,
|
|
onFinishTranscribe,
|
|
onFinishTranscribeWithAudio,
|
|
positioning: "static",
|
|
showDisclaimer: true,
|
|
...disclaimer !== void 0 ? { disclaimer } : {}
|
|
});
|
|
const BoundWelcomeScreen = require_slots.renderSlot(welcomeScreen === true ? void 0 : welcomeScreen, CopilotChatView.WelcomeScreen, {
|
|
input: BoundInputForWelcome,
|
|
suggestionView: BoundSuggestionView ?? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_jsx_runtime.Fragment, {})
|
|
});
|
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
"data-copilotkit": true,
|
|
"data-testid": "copilot-chat",
|
|
"data-copilot-running": isRunning ? "true" : "false",
|
|
className: (0, tailwind_merge.twMerge)("copilotKitChat cpk:relative cpk:h-full cpk:flex cpk:flex-col", className),
|
|
...props,
|
|
children: BoundWelcomeScreen
|
|
});
|
|
}
|
|
if (children) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
"data-copilotkit": true,
|
|
style: { display: "contents" },
|
|
children: children({
|
|
messageView: BoundMessageView,
|
|
input: BoundInput,
|
|
scrollView: BoundScrollView,
|
|
suggestionView: BoundSuggestionView ?? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_jsx_runtime.Fragment, {})
|
|
})
|
|
});
|
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
"data-copilotkit": true,
|
|
"data-testid": "copilot-chat",
|
|
"data-copilot-running": isRunning ? "true" : "false",
|
|
className: (0, tailwind_merge.twMerge)("copilotKitChat cpk:relative cpk:h-full", className),
|
|
...props,
|
|
children: [BoundScrollView, BoundInput]
|
|
});
|
|
}
|
|
(function(_CopilotChatView) {
|
|
const ScrollContent = ({ children, scrollToBottomButton, feather, inputContainerHeight, isResizing }) => {
|
|
const { isAtBottom, scrollToBottom } = (0, use_stick_to_bottom.useStickToBottomContext)();
|
|
const BoundFeather = require_slots.renderSlot(feather, CopilotChatView.Feather, {});
|
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [
|
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(use_stick_to_bottom.StickToBottom.Content, {
|
|
className: "cpk:overflow-y-scroll cpk:overflow-x-hidden",
|
|
style: {
|
|
flex: "1 1 0%",
|
|
minHeight: 0
|
|
},
|
|
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
className: "cpk:px-4 cpk:sm:px-0 cpk:[div[data-sidebar-chat]_&]:px-8 cpk:[div[data-popup-chat]_&]:px-6",
|
|
children
|
|
})
|
|
}),
|
|
BoundFeather,
|
|
!isAtBottom && !isResizing && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
className: "cpk:absolute cpk:inset-x-0 cpk:flex cpk:justify-center cpk:z-30 cpk:pointer-events-none",
|
|
style: { bottom: `${inputContainerHeight + FEATHER_HEIGHT + 16}px` },
|
|
children: require_slots.renderSlot(scrollToBottomButton, CopilotChatView.ScrollToBottomButton, { onClick: () => scrollToBottom() })
|
|
})
|
|
] });
|
|
};
|
|
_CopilotChatView.ScrollView = ({ children, autoScroll = true, scrollToBottomButton, feather, inputContainerHeight = 0, isResizing = false, className, ...props }) => {
|
|
const [hasMounted, setHasMounted] = (0, react.useState)(false);
|
|
const { scrollRef, contentRef, scrollToBottom } = (0, use_stick_to_bottom.useStickToBottom)();
|
|
const [showScrollButton, setShowScrollButton] = (0, react.useState)(false);
|
|
(0, react.useEffect)(() => {
|
|
setHasMounted(true);
|
|
}, []);
|
|
(0, react.useEffect)(() => {
|
|
if (autoScroll) return;
|
|
const scrollElement = scrollRef.current;
|
|
if (!scrollElement) return;
|
|
const checkScroll = () => {
|
|
setShowScrollButton(!(scrollElement.scrollHeight - scrollElement.scrollTop - scrollElement.clientHeight < 10));
|
|
};
|
|
checkScroll();
|
|
scrollElement.addEventListener("scroll", checkScroll);
|
|
const resizeObserver = new ResizeObserver(checkScroll);
|
|
resizeObserver.observe(scrollElement);
|
|
return () => {
|
|
scrollElement.removeEventListener("scroll", checkScroll);
|
|
resizeObserver.disconnect();
|
|
};
|
|
}, [scrollRef, autoScroll]);
|
|
if (!hasMounted) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
className: "cpk:h-full cpk:max-h-full cpk:flex cpk:flex-col cpk:min-h-0 cpk:overflow-y-scroll cpk:overflow-x-hidden",
|
|
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
className: "cpk:px-4 cpk:sm:px-0 cpk:[div[data-sidebar-chat]_&]:px-8 cpk:[div[data-popup-chat]_&]:px-6",
|
|
children
|
|
})
|
|
});
|
|
if (!autoScroll) {
|
|
const BoundFeather = require_slots.renderSlot(feather, CopilotChatView.Feather, {});
|
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
ref: scrollRef,
|
|
className: require_utils.cn("cpk:h-full cpk:max-h-full cpk:flex cpk:flex-col cpk:min-h-0 cpk:overflow-y-scroll cpk:overflow-x-hidden cpk:relative", className),
|
|
...props,
|
|
children: [
|
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
ref: contentRef,
|
|
className: "cpk:px-4 cpk:sm:px-0 cpk:[div[data-sidebar-chat]_&]:px-8 cpk:[div[data-popup-chat]_&]:px-6",
|
|
children
|
|
}),
|
|
BoundFeather,
|
|
showScrollButton && !isResizing && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
className: "cpk:absolute cpk:inset-x-0 cpk:flex cpk:justify-center cpk:z-30 cpk:pointer-events-none",
|
|
style: { bottom: `${inputContainerHeight + FEATHER_HEIGHT + 16}px` },
|
|
children: require_slots.renderSlot(scrollToBottomButton, CopilotChatView.ScrollToBottomButton, { onClick: () => scrollToBottom() })
|
|
})
|
|
]
|
|
});
|
|
}
|
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(use_stick_to_bottom.StickToBottom, {
|
|
className: require_utils.cn("cpk:h-full cpk:max-h-full cpk:flex cpk:flex-col cpk:min-h-0 cpk:relative", className),
|
|
resize: "smooth",
|
|
initial: "smooth",
|
|
...props,
|
|
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ScrollContent, {
|
|
scrollToBottomButton,
|
|
feather,
|
|
inputContainerHeight,
|
|
isResizing,
|
|
children
|
|
})
|
|
});
|
|
};
|
|
_CopilotChatView.ScrollToBottomButton = ({ className, ...props }) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_button.Button, {
|
|
"data-testid": "copilot-scroll-to-bottom",
|
|
variant: "outline",
|
|
size: "sm",
|
|
className: (0, tailwind_merge.twMerge)("cpk:rounded-full cpk:w-10 cpk:h-10 cpk:p-0 cpk:pointer-events-auto", "cpk:bg-white cpk:dark:bg-gray-900", "cpk:shadow-lg cpk:border cpk:border-gray-200 cpk:dark:border-gray-700", "cpk:hover:bg-gray-50 cpk:dark:hover:bg-gray-800", "cpk:flex cpk:items-center cpk:justify-center cpk:cursor-pointer", className),
|
|
...props,
|
|
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(lucide_react.ChevronDown, { className: "cpk:w-4 cpk:h-4 cpk:text-gray-600 cpk:dark:text-white" })
|
|
});
|
|
_CopilotChatView.Feather = ({ className, style, ...props }) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
className: require_utils.cn("cpk:absolute cpk:bottom-0 cpk:left-0 cpk:right-4 cpk:h-24 cpk:pointer-events-none cpk:z-10 cpk:bg-gradient-to-t", "cpk:from-white cpk:via-white cpk:to-transparent", "cpk:dark:from-[rgb(33,33,33)] cpk:dark:via-[rgb(33,33,33)]", className),
|
|
style,
|
|
...props
|
|
});
|
|
_CopilotChatView.WelcomeMessage = ({ className, ...props }) => {
|
|
const labels = require_CopilotChatConfigurationProvider.useCopilotChatConfiguration()?.labels ?? require_CopilotChatConfigurationProvider.CopilotChatDefaultLabels;
|
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("h1", {
|
|
className: require_utils.cn("cpk:text-xl cpk:sm:text-2xl cpk:font-medium cpk:text-foreground cpk:text-center", className),
|
|
...props,
|
|
children: labels.welcomeMessageText
|
|
});
|
|
};
|
|
_CopilotChatView.WelcomeScreen = ({ welcomeMessage, input, suggestionView, className, children, ...props }) => {
|
|
const BoundWelcomeMessage = require_slots.renderSlot(welcomeMessage, CopilotChatView.WelcomeMessage, {});
|
|
if (children) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
"data-copilotkit": true,
|
|
style: { display: "contents" },
|
|
children: children({
|
|
welcomeMessage: BoundWelcomeMessage,
|
|
input,
|
|
suggestionView,
|
|
className,
|
|
...props
|
|
})
|
|
});
|
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
"data-testid": "copilot-welcome-screen",
|
|
className: require_utils.cn("cpk:flex-1 cpk:flex cpk:flex-col cpk:items-center cpk:justify-center cpk:px-4", className),
|
|
...props,
|
|
children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
className: "cpk:w-full cpk:max-w-3xl cpk:flex cpk:flex-col cpk:items-center",
|
|
children: [
|
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
className: "cpk:mb-6",
|
|
children: BoundWelcomeMessage
|
|
}),
|
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
className: "cpk:w-full",
|
|
children: input
|
|
}),
|
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
className: "cpk:mt-4 cpk:flex cpk:justify-center",
|
|
children: suggestionView
|
|
})
|
|
]
|
|
})
|
|
});
|
|
};
|
|
})(CopilotChatView || (CopilotChatView = {}));
|
|
var CopilotChatView_default = CopilotChatView;
|
|
|
|
//#endregion
|
|
Object.defineProperty(exports, 'CopilotChatView', {
|
|
enumerable: true,
|
|
get: function () {
|
|
return CopilotChatView;
|
|
}
|
|
});
|
|
exports.default = CopilotChatView_default;
|
|
//# sourceMappingURL=CopilotChatView.cjs.map
|