rdesign/frontend/node_modules/@copilotkitnext/react/dist/components/chat/CopilotChatView.cjs

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