@copilotkitnext/react 1.52.2-next.2 → 1.52.2-next.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/components/chat/CopilotChat.cjs +13 -6
- package/dist/components/chat/CopilotChat.cjs.map +1 -1
- package/dist/components/chat/CopilotChat.d.cts.map +1 -1
- package/dist/components/chat/CopilotChat.d.mts.map +1 -1
- package/dist/components/chat/CopilotChat.mjs +14 -7
- package/dist/components/chat/CopilotChat.mjs.map +1 -1
- package/dist/components/chat/CopilotChatAssistantMessage.cjs +1 -1
- package/dist/components/chat/CopilotChatAssistantMessage.cjs.map +1 -1
- package/dist/components/chat/CopilotChatAssistantMessage.d.cts.map +1 -1
- package/dist/components/chat/CopilotChatAssistantMessage.d.mts.map +1 -1
- package/dist/components/chat/CopilotChatAssistantMessage.mjs +1 -1
- package/dist/components/chat/CopilotChatAssistantMessage.mjs.map +1 -1
- package/dist/components/chat/CopilotChatInput.cjs +1 -1
- package/dist/components/chat/CopilotChatInput.cjs.map +1 -1
- package/dist/components/chat/CopilotChatInput.d.cts.map +1 -1
- package/dist/components/chat/CopilotChatInput.d.mts.map +1 -1
- package/dist/components/chat/CopilotChatInput.mjs +1 -1
- package/dist/components/chat/CopilotChatInput.mjs.map +1 -1
- package/dist/components/chat/CopilotChatMessageView.cjs +1 -1
- package/dist/components/chat/CopilotChatMessageView.cjs.map +1 -1
- package/dist/components/chat/CopilotChatMessageView.mjs +1 -1
- package/dist/components/chat/CopilotChatMessageView.mjs.map +1 -1
- package/dist/components/chat/CopilotChatToggleButton.cjs +1 -1
- package/dist/components/chat/CopilotChatToggleButton.cjs.map +1 -1
- package/dist/components/chat/CopilotChatToggleButton.d.cts.map +1 -1
- package/dist/components/chat/CopilotChatToggleButton.d.mts.map +1 -1
- package/dist/components/chat/CopilotChatToggleButton.mjs +1 -1
- package/dist/components/chat/CopilotChatToggleButton.mjs.map +1 -1
- package/dist/components/chat/CopilotChatUserMessage.cjs +1 -1
- package/dist/components/chat/CopilotChatUserMessage.cjs.map +1 -1
- package/dist/components/chat/CopilotChatUserMessage.mjs +1 -1
- package/dist/components/chat/CopilotChatUserMessage.mjs.map +1 -1
- package/dist/components/chat/CopilotChatView.cjs +2 -2
- package/dist/components/chat/CopilotChatView.cjs.map +1 -1
- package/dist/components/chat/CopilotChatView.mjs +2 -2
- package/dist/components/chat/CopilotChatView.mjs.map +1 -1
- package/dist/components/chat/CopilotModalHeader.cjs +1 -1
- package/dist/components/chat/CopilotModalHeader.cjs.map +1 -1
- package/dist/components/chat/CopilotModalHeader.d.cts.map +1 -1
- package/dist/components/chat/CopilotModalHeader.d.mts.map +1 -1
- package/dist/components/chat/CopilotModalHeader.mjs +1 -1
- package/dist/components/chat/CopilotModalHeader.mjs.map +1 -1
- package/dist/components/chat/CopilotPopupView.cjs +1 -1
- package/dist/components/chat/CopilotPopupView.cjs.map +1 -1
- package/dist/components/chat/CopilotPopupView.d.cts.map +1 -1
- package/dist/components/chat/CopilotPopupView.d.mts.map +1 -1
- package/dist/components/chat/CopilotPopupView.mjs +1 -1
- package/dist/components/chat/CopilotPopupView.mjs.map +1 -1
- package/dist/components/chat/CopilotSidebarView.cjs +1 -1
- package/dist/components/chat/CopilotSidebarView.cjs.map +1 -1
- package/dist/components/chat/CopilotSidebarView.d.cts.map +1 -1
- package/dist/components/chat/CopilotSidebarView.d.mts.map +1 -1
- package/dist/components/chat/CopilotSidebarView.mjs +1 -1
- package/dist/components/chat/CopilotSidebarView.mjs.map +1 -1
- package/dist/hooks/use-agent.cjs +12 -3
- package/dist/hooks/use-agent.cjs.map +1 -1
- package/dist/hooks/use-agent.mjs +13 -4
- package/dist/hooks/use-agent.mjs.map +1 -1
- package/dist/index.umd.js +81 -43
- package/dist/index.umd.js.map +1 -1
- package/dist/lib/react-core.cjs +6 -0
- package/dist/lib/react-core.cjs.map +1 -1
- package/dist/lib/react-core.d.cts +2 -0
- package/dist/lib/react-core.d.cts.map +1 -1
- package/dist/lib/react-core.d.mts +2 -0
- package/dist/lib/react-core.d.mts.map +1 -1
- package/dist/lib/react-core.mjs +6 -0
- package/dist/lib/react-core.mjs.map +1 -1
- package/dist/providers/CopilotKitProvider.cjs +40 -24
- package/dist/providers/CopilotKitProvider.cjs.map +1 -1
- package/dist/providers/CopilotKitProvider.d.cts.map +1 -1
- package/dist/providers/CopilotKitProvider.d.mts.map +1 -1
- package/dist/providers/CopilotKitProvider.mjs +40 -24
- package/dist/providers/CopilotKitProvider.mjs.map +1 -1
- package/package.json +8 -8
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CopilotChatView.cjs","names":["useKeyboardHeight","renderSlot","CopilotChatMessageView","CopilotChatInput","CopilotChatSuggestionView","StickToBottom","cn","Button","ChevronDown","useCopilotChatConfiguration","CopilotChatDefaultLabels"],"sources":["../../../src/components/chat/CopilotChatView.tsx"],"sourcesContent":["import React, { useRef, useState, useEffect } from \"react\";\nimport { WithSlots, SlotValue, renderSlot } from \"@/lib/slots\";\nimport CopilotChatMessageView from \"./CopilotChatMessageView\";\nimport CopilotChatInput, {\n CopilotChatInputProps,\n CopilotChatInputMode,\n} from \"./CopilotChatInput\";\nimport CopilotChatSuggestionView, {\n CopilotChatSuggestionViewProps,\n} from \"./CopilotChatSuggestionView\";\nimport { Suggestion } from \"@copilotkitnext/core\";\nimport { Message } from \"@ag-ui/core\";\nimport { twMerge } from \"tailwind-merge\";\nimport {\n StickToBottom,\n useStickToBottom,\n useStickToBottomContext,\n} from \"use-stick-to-bottom\";\nimport { ChevronDown } from \"lucide-react\";\nimport { Button } from \"@/components/ui/button\";\nimport { cn } from \"@/lib/utils\";\nimport {\n useCopilotChatConfiguration,\n CopilotChatDefaultLabels,\n} from \"@/providers/CopilotChatConfigurationProvider\";\nimport { useKeyboardHeight } from \"@/hooks/use-keyboard-height\";\n\n// Height of the feather gradient overlay (h-24 = 6rem = 96px)\nconst FEATHER_HEIGHT = 96;\n\n// Forward declaration for WelcomeScreen component type\nexport type WelcomeScreenProps = WithSlots<\n {\n welcomeMessage: React.FC<React.HTMLAttributes<HTMLDivElement>>;\n },\n {\n input: React.ReactElement;\n suggestionView: React.ReactElement;\n } & React.HTMLAttributes<HTMLDivElement>\n>;\n\nexport type CopilotChatViewProps = WithSlots<\n {\n messageView: typeof CopilotChatMessageView;\n scrollView: typeof CopilotChatView.ScrollView;\n input: typeof CopilotChatInput;\n suggestionView: typeof CopilotChatSuggestionView;\n },\n {\n messages?: Message[];\n autoScroll?: boolean;\n isRunning?: boolean;\n suggestions?: Suggestion[];\n suggestionLoadingIndexes?: ReadonlyArray<number>;\n onSelectSuggestion?: (suggestion: Suggestion, index: number) => void;\n welcomeScreen?: SlotValue<React.FC<WelcomeScreenProps>> | boolean;\n // Input behavior props\n onSubmitMessage?: (value: string) => void;\n onStop?: () => void;\n inputMode?: CopilotChatInputMode;\n inputValue?: string;\n onInputChange?: (value: string) => void;\n onStartTranscribe?: () => void;\n onCancelTranscribe?: () => void;\n onFinishTranscribe?: () => void;\n onFinishTranscribeWithAudio?: (audioBlob: Blob) => Promise<void>;\n /**\n * @deprecated Use the `input` slot's `disclaimer` prop instead:\n * ```tsx\n * <CopilotChat input={{ disclaimer: MyDisclaimer }} />\n * ```\n */\n disclaimer?: SlotValue<React.FC<React.HTMLAttributes<HTMLDivElement>>>;\n } & React.HTMLAttributes<HTMLDivElement>\n>;\n\nexport function CopilotChatView({\n messageView,\n input,\n scrollView,\n suggestionView,\n welcomeScreen,\n messages = [],\n autoScroll = true,\n isRunning = false,\n suggestions,\n suggestionLoadingIndexes,\n onSelectSuggestion,\n // Input behavior props\n onSubmitMessage,\n onStop,\n inputMode,\n inputValue,\n onInputChange,\n onStartTranscribe,\n onCancelTranscribe,\n onFinishTranscribe,\n onFinishTranscribeWithAudio,\n // Deprecated — forwarded to input slot\n disclaimer,\n children,\n className,\n ...props\n}: CopilotChatViewProps) {\n const inputContainerRef = useRef<HTMLDivElement>(null);\n const [inputContainerHeight, setInputContainerHeight] = useState(0);\n const [isResizing, setIsResizing] = useState(false);\n const resizeTimeoutRef = useRef<NodeJS.Timeout | null>(null);\n\n // Track keyboard state for mobile\n const { isKeyboardOpen, keyboardHeight, availableHeight } =\n useKeyboardHeight();\n\n // Track input container height changes\n useEffect(() => {\n const element = inputContainerRef.current;\n if (!element) return;\n\n const resizeObserver = new ResizeObserver((entries) => {\n for (const entry of entries) {\n const newHeight = entry.contentRect.height;\n\n // Update height and set resizing state\n setInputContainerHeight((prevHeight) => {\n if (newHeight !== prevHeight) {\n setIsResizing(true);\n\n // Clear existing timeout\n if (resizeTimeoutRef.current) {\n clearTimeout(resizeTimeoutRef.current);\n }\n\n // Set isResizing to false after a short delay\n resizeTimeoutRef.current = setTimeout(() => {\n setIsResizing(false);\n }, 250);\n\n return newHeight;\n }\n return prevHeight;\n });\n }\n });\n\n resizeObserver.observe(element);\n\n // Set initial height\n setInputContainerHeight(element.offsetHeight);\n\n return () => {\n resizeObserver.disconnect();\n if (resizeTimeoutRef.current) {\n clearTimeout(resizeTimeoutRef.current);\n }\n };\n }, []);\n\n const BoundMessageView = renderSlot(messageView, CopilotChatMessageView, {\n messages,\n isRunning,\n });\n\n const BoundInput = renderSlot(input, CopilotChatInput, {\n onSubmitMessage,\n onStop,\n mode: inputMode,\n value: inputValue,\n onChange: onInputChange,\n isRunning,\n onStartTranscribe,\n onCancelTranscribe,\n onFinishTranscribe,\n onFinishTranscribeWithAudio,\n positioning: \"absolute\",\n keyboardHeight: isKeyboardOpen ? keyboardHeight : 0,\n containerRef: inputContainerRef,\n showDisclaimer: true,\n ...(disclaimer !== undefined ? { disclaimer } : {}),\n } as CopilotChatInputProps);\n\n const hasSuggestions = Array.isArray(suggestions) && suggestions.length > 0;\n const BoundSuggestionView = hasSuggestions\n ? renderSlot(suggestionView, CopilotChatSuggestionView, {\n suggestions,\n loadingIndexes: suggestionLoadingIndexes,\n onSelectSuggestion,\n className: \"cpk:mb-3 cpk:lg:ml-4 cpk:lg:mr-4 cpk:ml-0 cpk:mr-0\",\n })\n : null;\n\n const BoundScrollView = renderSlot(scrollView, CopilotChatView.ScrollView, {\n autoScroll,\n inputContainerHeight,\n isResizing,\n children: (\n <div\n style={{\n paddingBottom: `${inputContainerHeight + FEATHER_HEIGHT + (hasSuggestions ? 4 : 32)}px`,\n }}\n >\n <div className=\"cpk:max-w-3xl cpk:mx-auto\">\n {BoundMessageView}\n {hasSuggestions ? (\n <div className=\"cpk:pl-0 cpk:pr-4 cpk:sm:px-0 cpk:mt-4\">\n {BoundSuggestionView}\n </div>\n ) : null}\n </div>\n </div>\n ),\n });\n\n // Welcome screen logic\n const isEmpty = messages.length === 0;\n // Type assertion needed because TypeScript doesn't fully propagate `| boolean` through WithSlots\n const welcomeScreenDisabled = (welcomeScreen as unknown) === false;\n const shouldShowWelcomeScreen = isEmpty && !welcomeScreenDisabled;\n\n if (shouldShowWelcomeScreen) {\n // Create a separate input for welcome screen with static positioning and disclaimer visible\n const BoundInputForWelcome = renderSlot(input, CopilotChatInput, {\n onSubmitMessage,\n onStop,\n mode: inputMode,\n value: inputValue,\n onChange: onInputChange,\n isRunning,\n onStartTranscribe,\n onCancelTranscribe,\n onFinishTranscribe,\n onFinishTranscribeWithAudio,\n positioning: \"static\",\n showDisclaimer: true,\n ...(disclaimer !== undefined ? { disclaimer } : {}),\n } as CopilotChatInputProps);\n\n // Convert boolean `true` to undefined (use default), and exclude `false` since we've checked for it\n const welcomeScreenSlot = (\n welcomeScreen === true ? undefined : welcomeScreen\n ) as SlotValue<React.FC<WelcomeScreenProps>> | undefined;\n const BoundWelcomeScreen = renderSlot(\n welcomeScreenSlot,\n CopilotChatView.WelcomeScreen,\n {\n input: BoundInputForWelcome,\n suggestionView: BoundSuggestionView ?? <></>,\n },\n );\n\n return (\n <div\n data-copilotkit\n data-testid=\"copilot-chat\"\n data-copilot-running={isRunning ? \"true\" : \"false\"}\n className={twMerge(\n \"cpk:relative cpk:h-full cpk:flex cpk:flex-col\",\n className,\n )}\n {...props}\n >\n {BoundWelcomeScreen}\n </div>\n );\n }\n\n if (children) {\n return (\n <div data-copilotkit style={{ display: \"contents\" }}>\n {children({\n messageView: BoundMessageView,\n input: BoundInput,\n scrollView: BoundScrollView,\n suggestionView: BoundSuggestionView ?? <></>,\n })}\n </div>\n );\n }\n\n return (\n <div\n data-copilotkit\n data-testid=\"copilot-chat\"\n data-copilot-running={isRunning ? \"true\" : \"false\"}\n className={twMerge(\"cpk:relative cpk:h-full\", className)}\n {...props}\n >\n {BoundScrollView}\n\n {BoundInput}\n </div>\n );\n}\n\nexport namespace CopilotChatView {\n // Inner component that has access to StickToBottom context\n const ScrollContent: React.FC<{\n children: React.ReactNode;\n scrollToBottomButton?: SlotValue<\n React.FC<React.ButtonHTMLAttributes<HTMLButtonElement>>\n >;\n feather?: SlotValue<React.FC<React.HTMLAttributes<HTMLDivElement>>>;\n inputContainerHeight: number;\n isResizing: boolean;\n }> = ({\n children,\n scrollToBottomButton,\n feather,\n inputContainerHeight,\n isResizing,\n }) => {\n const { isAtBottom, scrollToBottom } = useStickToBottomContext();\n\n const BoundFeather = renderSlot(feather, CopilotChatView.Feather, {});\n\n return (\n <>\n <StickToBottom.Content\n className=\"cpk:overflow-y-scroll cpk:overflow-x-hidden\"\n style={{ flex: \"1 1 0%\", minHeight: 0 }}\n >\n <div className=\"cpk:px-4 cpk:sm:px-0 cpk:[div[data-sidebar-chat]_&]:px-8 cpk:[div[data-popup-chat]_&]:px-6\">\n {children}\n </div>\n </StickToBottom.Content>\n\n {/* Feather gradient overlay */}\n {BoundFeather}\n\n {/* Scroll to bottom button - hidden during resize */}\n {!isAtBottom && !isResizing && (\n <div\n className=\"cpk:absolute cpk:inset-x-0 cpk:flex cpk:justify-center cpk:z-30 cpk:pointer-events-none\"\n style={{\n bottom: `${inputContainerHeight + FEATHER_HEIGHT + 16}px`,\n }}\n >\n {renderSlot(\n scrollToBottomButton,\n CopilotChatView.ScrollToBottomButton,\n {\n onClick: () => scrollToBottom(),\n },\n )}\n </div>\n )}\n </>\n );\n };\n\n export const ScrollView: React.FC<\n React.HTMLAttributes<HTMLDivElement> & {\n autoScroll?: boolean;\n scrollToBottomButton?: SlotValue<\n React.FC<React.ButtonHTMLAttributes<HTMLButtonElement>>\n >;\n feather?: SlotValue<React.FC<React.HTMLAttributes<HTMLDivElement>>>;\n inputContainerHeight?: number;\n isResizing?: boolean;\n }\n > = ({\n children,\n autoScroll = true,\n scrollToBottomButton,\n feather,\n inputContainerHeight = 0,\n isResizing = false,\n className,\n ...props\n }) => {\n const [hasMounted, setHasMounted] = useState(false);\n const { scrollRef, contentRef, scrollToBottom } = useStickToBottom();\n const [showScrollButton, setShowScrollButton] = useState(false);\n\n useEffect(() => {\n setHasMounted(true);\n }, []);\n\n // Monitor scroll position for non-autoscroll mode\n useEffect(() => {\n if (autoScroll) return; // Skip for autoscroll mode\n\n const scrollElement = scrollRef.current;\n if (!scrollElement) return;\n\n const checkScroll = () => {\n const atBottom =\n scrollElement.scrollHeight -\n scrollElement.scrollTop -\n scrollElement.clientHeight <\n 10;\n setShowScrollButton(!atBottom);\n };\n\n checkScroll();\n scrollElement.addEventListener(\"scroll\", checkScroll);\n\n // Also check on resize\n const resizeObserver = new ResizeObserver(checkScroll);\n resizeObserver.observe(scrollElement);\n\n return () => {\n scrollElement.removeEventListener(\"scroll\", checkScroll);\n resizeObserver.disconnect();\n };\n }, [scrollRef, autoScroll]);\n\n if (!hasMounted) {\n return (\n <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\">\n <div className=\"cpk:px-4 cpk:sm:px-0 cpk:[div[data-sidebar-chat]_&]:px-8 cpk:[div[data-popup-chat]_&]:px-6\">\n {children}\n </div>\n </div>\n );\n }\n\n // When autoScroll is false, we don't use StickToBottom\n if (!autoScroll) {\n const BoundFeather = renderSlot(feather, CopilotChatView.Feather, {});\n\n return (\n <div\n ref={scrollRef}\n className={cn(\n \"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\",\n className,\n )}\n {...props}\n >\n <div\n ref={contentRef}\n className=\"cpk:px-4 cpk:sm:px-0 cpk:[div[data-sidebar-chat]_&]:px-8 cpk:[div[data-popup-chat]_&]:px-6\"\n >\n {children}\n </div>\n\n {/* Feather gradient overlay */}\n {BoundFeather}\n\n {/* Scroll to bottom button for manual mode */}\n {showScrollButton && !isResizing && (\n <div\n className=\"cpk:absolute cpk:inset-x-0 cpk:flex cpk:justify-center cpk:z-30 cpk:pointer-events-none\"\n style={{\n bottom: `${inputContainerHeight + FEATHER_HEIGHT + 16}px`,\n }}\n >\n {renderSlot(\n scrollToBottomButton,\n CopilotChatView.ScrollToBottomButton,\n {\n onClick: () => scrollToBottom(),\n },\n )}\n </div>\n )}\n </div>\n );\n }\n\n return (\n <StickToBottom\n className={cn(\n \"cpk:h-full cpk:max-h-full cpk:flex cpk:flex-col cpk:min-h-0 cpk:relative\",\n className,\n )}\n resize=\"smooth\"\n initial=\"smooth\"\n {...props}\n >\n <ScrollContent\n scrollToBottomButton={scrollToBottomButton}\n feather={feather}\n inputContainerHeight={inputContainerHeight}\n isResizing={isResizing}\n >\n {children}\n </ScrollContent>\n </StickToBottom>\n );\n };\n\n export const ScrollToBottomButton: React.FC<\n React.ButtonHTMLAttributes<HTMLButtonElement>\n > = ({ className, ...props }) => (\n <Button\n data-testid=\"copilot-scroll-to-bottom\"\n variant=\"outline\"\n size=\"sm\"\n className={twMerge(\n \"cpk:rounded-full cpk:w-10 cpk:h-10 cpk:p-0 cpk:pointer-events-auto\",\n \"cpk:bg-white cpk:dark:bg-gray-900\",\n \"cpk:shadow-lg cpk:border cpk:border-gray-200 cpk:dark:border-gray-700\",\n \"cpk:hover:bg-gray-50 cpk:dark:hover:bg-gray-800\",\n \"cpk:flex cpk:items-center cpk:justify-center cpk:cursor-pointer\",\n className,\n )}\n {...props}\n >\n <ChevronDown className=\"cpk:w-4 cpk:h-4 cpk:text-gray-600 cpk:dark:text-white\" />\n </Button>\n );\n\n export const Feather: React.FC<React.HTMLAttributes<HTMLDivElement>> = ({\n className,\n style,\n ...props\n }) => (\n <div\n className={cn(\n \"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\",\n \"cpk:from-white cpk:via-white cpk:to-transparent\",\n \"cpk:dark:from-[rgb(33,33,33)] cpk:dark:via-[rgb(33,33,33)]\",\n className,\n )}\n style={style}\n {...props}\n />\n );\n\n export const WelcomeMessage: React.FC<\n React.HTMLAttributes<HTMLDivElement>\n > = ({ className, ...props }) => {\n const config = useCopilotChatConfiguration();\n const labels = config?.labels ?? CopilotChatDefaultLabels;\n\n return (\n <h1\n className={cn(\n \"cpk:text-xl cpk:sm:text-2xl cpk:font-medium cpk:text-foreground cpk:text-center\",\n className,\n )}\n {...props}\n >\n {labels.welcomeMessageText}\n </h1>\n );\n };\n\n export const WelcomeScreen: React.FC<WelcomeScreenProps> = ({\n welcomeMessage,\n input,\n suggestionView,\n className,\n children,\n ...props\n }) => {\n // Render the welcomeMessage slot internally\n const BoundWelcomeMessage = renderSlot(\n welcomeMessage,\n CopilotChatView.WelcomeMessage,\n {},\n );\n\n if (children) {\n return (\n <div data-copilotkit style={{ display: \"contents\" }}>\n {children({\n welcomeMessage: BoundWelcomeMessage,\n input,\n suggestionView,\n className,\n ...props,\n })}\n </div>\n );\n }\n\n return (\n <div\n data-testid=\"copilot-welcome-screen\"\n className={cn(\n \"cpk:flex-1 cpk:flex cpk:flex-col cpk:items-center cpk:justify-center cpk:px-4\",\n className,\n )}\n {...props}\n >\n <div className=\"cpk:w-full cpk:max-w-3xl cpk:flex cpk:flex-col cpk:items-center\">\n {/* Welcome message */}\n <div className=\"cpk:mb-6\">{BoundWelcomeMessage}</div>\n\n {/* Input */}\n <div className=\"cpk:w-full\">{input}</div>\n\n {/* Suggestions */}\n <div className=\"cpk:mt-4 cpk:flex cpk:justify-center\">\n {suggestionView}\n </div>\n </div>\n </div>\n );\n };\n}\n\nexport default CopilotChatView;\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"CopilotChatView.cjs","names":["useKeyboardHeight","renderSlot","CopilotChatMessageView","CopilotChatInput","CopilotChatSuggestionView","StickToBottom","cn","Button","ChevronDown","useCopilotChatConfiguration","CopilotChatDefaultLabels"],"sources":["../../../src/components/chat/CopilotChatView.tsx"],"sourcesContent":["import React, { useRef, useState, useEffect } from \"react\";\nimport { WithSlots, SlotValue, renderSlot } from \"@/lib/slots\";\nimport CopilotChatMessageView from \"./CopilotChatMessageView\";\nimport CopilotChatInput, {\n CopilotChatInputProps,\n CopilotChatInputMode,\n} from \"./CopilotChatInput\";\nimport CopilotChatSuggestionView, {\n CopilotChatSuggestionViewProps,\n} from \"./CopilotChatSuggestionView\";\nimport { Suggestion } from \"@copilotkitnext/core\";\nimport { Message } from \"@ag-ui/core\";\nimport { twMerge } from \"tailwind-merge\";\nimport {\n StickToBottom,\n useStickToBottom,\n useStickToBottomContext,\n} from \"use-stick-to-bottom\";\nimport { ChevronDown } from \"lucide-react\";\nimport { Button } from \"@/components/ui/button\";\nimport { cn } from \"@/lib/utils\";\nimport {\n useCopilotChatConfiguration,\n CopilotChatDefaultLabels,\n} from \"@/providers/CopilotChatConfigurationProvider\";\nimport { useKeyboardHeight } from \"@/hooks/use-keyboard-height\";\n\n// Height of the feather gradient overlay (h-24 = 6rem = 96px)\nconst FEATHER_HEIGHT = 96;\n\n// Forward declaration for WelcomeScreen component type\nexport type WelcomeScreenProps = WithSlots<\n {\n welcomeMessage: React.FC<React.HTMLAttributes<HTMLDivElement>>;\n },\n {\n input: React.ReactElement;\n suggestionView: React.ReactElement;\n } & React.HTMLAttributes<HTMLDivElement>\n>;\n\nexport type CopilotChatViewProps = WithSlots<\n {\n messageView: typeof CopilotChatMessageView;\n scrollView: typeof CopilotChatView.ScrollView;\n input: typeof CopilotChatInput;\n suggestionView: typeof CopilotChatSuggestionView;\n },\n {\n messages?: Message[];\n autoScroll?: boolean;\n isRunning?: boolean;\n suggestions?: Suggestion[];\n suggestionLoadingIndexes?: ReadonlyArray<number>;\n onSelectSuggestion?: (suggestion: Suggestion, index: number) => void;\n welcomeScreen?: SlotValue<React.FC<WelcomeScreenProps>> | boolean;\n // Input behavior props\n onSubmitMessage?: (value: string) => void;\n onStop?: () => void;\n inputMode?: CopilotChatInputMode;\n inputValue?: string;\n onInputChange?: (value: string) => void;\n onStartTranscribe?: () => void;\n onCancelTranscribe?: () => void;\n onFinishTranscribe?: () => void;\n onFinishTranscribeWithAudio?: (audioBlob: Blob) => Promise<void>;\n /**\n * @deprecated Use the `input` slot's `disclaimer` prop instead:\n * ```tsx\n * <CopilotChat input={{ disclaimer: MyDisclaimer }} />\n * ```\n */\n disclaimer?: SlotValue<React.FC<React.HTMLAttributes<HTMLDivElement>>>;\n } & React.HTMLAttributes<HTMLDivElement>\n>;\n\nexport function CopilotChatView({\n messageView,\n input,\n scrollView,\n suggestionView,\n welcomeScreen,\n messages = [],\n autoScroll = true,\n isRunning = false,\n suggestions,\n suggestionLoadingIndexes,\n onSelectSuggestion,\n // Input behavior props\n onSubmitMessage,\n onStop,\n inputMode,\n inputValue,\n onInputChange,\n onStartTranscribe,\n onCancelTranscribe,\n onFinishTranscribe,\n onFinishTranscribeWithAudio,\n // Deprecated — forwarded to input slot\n disclaimer,\n children,\n className,\n ...props\n}: CopilotChatViewProps) {\n const inputContainerRef = useRef<HTMLDivElement>(null);\n const [inputContainerHeight, setInputContainerHeight] = useState(0);\n const [isResizing, setIsResizing] = useState(false);\n const resizeTimeoutRef = useRef<NodeJS.Timeout | null>(null);\n\n // Track keyboard state for mobile\n const { isKeyboardOpen, keyboardHeight, availableHeight } =\n useKeyboardHeight();\n\n // Track input container height changes\n useEffect(() => {\n const element = inputContainerRef.current;\n if (!element) return;\n\n const resizeObserver = new ResizeObserver((entries) => {\n for (const entry of entries) {\n const newHeight = entry.contentRect.height;\n\n // Update height and set resizing state\n setInputContainerHeight((prevHeight) => {\n if (newHeight !== prevHeight) {\n setIsResizing(true);\n\n // Clear existing timeout\n if (resizeTimeoutRef.current) {\n clearTimeout(resizeTimeoutRef.current);\n }\n\n // Set isResizing to false after a short delay\n resizeTimeoutRef.current = setTimeout(() => {\n setIsResizing(false);\n }, 250);\n\n return newHeight;\n }\n return prevHeight;\n });\n }\n });\n\n resizeObserver.observe(element);\n\n // Set initial height\n setInputContainerHeight(element.offsetHeight);\n\n return () => {\n resizeObserver.disconnect();\n if (resizeTimeoutRef.current) {\n clearTimeout(resizeTimeoutRef.current);\n }\n };\n }, []);\n\n const BoundMessageView = renderSlot(messageView, CopilotChatMessageView, {\n messages,\n isRunning,\n });\n\n const BoundInput = renderSlot(input, CopilotChatInput, {\n onSubmitMessage,\n onStop,\n mode: inputMode,\n value: inputValue,\n onChange: onInputChange,\n isRunning,\n onStartTranscribe,\n onCancelTranscribe,\n onFinishTranscribe,\n onFinishTranscribeWithAudio,\n positioning: \"absolute\",\n keyboardHeight: isKeyboardOpen ? keyboardHeight : 0,\n containerRef: inputContainerRef,\n showDisclaimer: true,\n ...(disclaimer !== undefined ? { disclaimer } : {}),\n } as CopilotChatInputProps);\n\n const hasSuggestions = Array.isArray(suggestions) && suggestions.length > 0;\n const BoundSuggestionView = hasSuggestions\n ? renderSlot(suggestionView, CopilotChatSuggestionView, {\n suggestions,\n loadingIndexes: suggestionLoadingIndexes,\n onSelectSuggestion,\n className: \"cpk:mb-3 cpk:lg:ml-4 cpk:lg:mr-4 cpk:ml-0 cpk:mr-0\",\n })\n : null;\n\n const BoundScrollView = renderSlot(scrollView, CopilotChatView.ScrollView, {\n autoScroll,\n inputContainerHeight,\n isResizing,\n children: (\n <div\n style={{\n paddingBottom: `${inputContainerHeight + FEATHER_HEIGHT + (hasSuggestions ? 4 : 32)}px`,\n }}\n >\n <div className=\"cpk:max-w-3xl cpk:mx-auto\">\n {BoundMessageView}\n {hasSuggestions ? (\n <div className=\"cpk:pl-0 cpk:pr-4 cpk:sm:px-0 cpk:mt-4\">\n {BoundSuggestionView}\n </div>\n ) : null}\n </div>\n </div>\n ),\n });\n\n // Welcome screen logic\n const isEmpty = messages.length === 0;\n // Type assertion needed because TypeScript doesn't fully propagate `| boolean` through WithSlots\n const welcomeScreenDisabled = (welcomeScreen as unknown) === false;\n const shouldShowWelcomeScreen = isEmpty && !welcomeScreenDisabled;\n\n if (shouldShowWelcomeScreen) {\n // Create a separate input for welcome screen with static positioning and disclaimer visible\n const BoundInputForWelcome = renderSlot(input, CopilotChatInput, {\n onSubmitMessage,\n onStop,\n mode: inputMode,\n value: inputValue,\n onChange: onInputChange,\n isRunning,\n onStartTranscribe,\n onCancelTranscribe,\n onFinishTranscribe,\n onFinishTranscribeWithAudio,\n positioning: \"static\",\n showDisclaimer: true,\n ...(disclaimer !== undefined ? { disclaimer } : {}),\n } as CopilotChatInputProps);\n\n // Convert boolean `true` to undefined (use default), and exclude `false` since we've checked for it\n const welcomeScreenSlot = (\n welcomeScreen === true ? undefined : welcomeScreen\n ) as SlotValue<React.FC<WelcomeScreenProps>> | undefined;\n const BoundWelcomeScreen = renderSlot(\n welcomeScreenSlot,\n CopilotChatView.WelcomeScreen,\n {\n input: BoundInputForWelcome,\n suggestionView: BoundSuggestionView ?? <></>,\n },\n );\n\n return (\n <div\n data-copilotkit\n data-testid=\"copilot-chat\"\n data-copilot-running={isRunning ? \"true\" : \"false\"}\n className={twMerge(\n \"copilotKitChat cpk:relative cpk:h-full cpk:flex cpk:flex-col\",\n className,\n )}\n {...props}\n >\n {BoundWelcomeScreen}\n </div>\n );\n }\n\n if (children) {\n return (\n <div data-copilotkit style={{ display: \"contents\" }}>\n {children({\n messageView: BoundMessageView,\n input: BoundInput,\n scrollView: BoundScrollView,\n suggestionView: BoundSuggestionView ?? <></>,\n })}\n </div>\n );\n }\n\n return (\n <div\n data-copilotkit\n data-testid=\"copilot-chat\"\n data-copilot-running={isRunning ? \"true\" : \"false\"}\n className={twMerge(\"copilotKitChat cpk:relative cpk:h-full\", className)}\n {...props}\n >\n {BoundScrollView}\n\n {BoundInput}\n </div>\n );\n}\n\nexport namespace CopilotChatView {\n // Inner component that has access to StickToBottom context\n const ScrollContent: React.FC<{\n children: React.ReactNode;\n scrollToBottomButton?: SlotValue<\n React.FC<React.ButtonHTMLAttributes<HTMLButtonElement>>\n >;\n feather?: SlotValue<React.FC<React.HTMLAttributes<HTMLDivElement>>>;\n inputContainerHeight: number;\n isResizing: boolean;\n }> = ({\n children,\n scrollToBottomButton,\n feather,\n inputContainerHeight,\n isResizing,\n }) => {\n const { isAtBottom, scrollToBottom } = useStickToBottomContext();\n\n const BoundFeather = renderSlot(feather, CopilotChatView.Feather, {});\n\n return (\n <>\n <StickToBottom.Content\n className=\"cpk:overflow-y-scroll cpk:overflow-x-hidden\"\n style={{ flex: \"1 1 0%\", minHeight: 0 }}\n >\n <div className=\"cpk:px-4 cpk:sm:px-0 cpk:[div[data-sidebar-chat]_&]:px-8 cpk:[div[data-popup-chat]_&]:px-6\">\n {children}\n </div>\n </StickToBottom.Content>\n\n {/* Feather gradient overlay */}\n {BoundFeather}\n\n {/* Scroll to bottom button - hidden during resize */}\n {!isAtBottom && !isResizing && (\n <div\n className=\"cpk:absolute cpk:inset-x-0 cpk:flex cpk:justify-center cpk:z-30 cpk:pointer-events-none\"\n style={{\n bottom: `${inputContainerHeight + FEATHER_HEIGHT + 16}px`,\n }}\n >\n {renderSlot(\n scrollToBottomButton,\n CopilotChatView.ScrollToBottomButton,\n {\n onClick: () => scrollToBottom(),\n },\n )}\n </div>\n )}\n </>\n );\n };\n\n export const ScrollView: React.FC<\n React.HTMLAttributes<HTMLDivElement> & {\n autoScroll?: boolean;\n scrollToBottomButton?: SlotValue<\n React.FC<React.ButtonHTMLAttributes<HTMLButtonElement>>\n >;\n feather?: SlotValue<React.FC<React.HTMLAttributes<HTMLDivElement>>>;\n inputContainerHeight?: number;\n isResizing?: boolean;\n }\n > = ({\n children,\n autoScroll = true,\n scrollToBottomButton,\n feather,\n inputContainerHeight = 0,\n isResizing = false,\n className,\n ...props\n }) => {\n const [hasMounted, setHasMounted] = useState(false);\n const { scrollRef, contentRef, scrollToBottom } = useStickToBottom();\n const [showScrollButton, setShowScrollButton] = useState(false);\n\n useEffect(() => {\n setHasMounted(true);\n }, []);\n\n // Monitor scroll position for non-autoscroll mode\n useEffect(() => {\n if (autoScroll) return; // Skip for autoscroll mode\n\n const scrollElement = scrollRef.current;\n if (!scrollElement) return;\n\n const checkScroll = () => {\n const atBottom =\n scrollElement.scrollHeight -\n scrollElement.scrollTop -\n scrollElement.clientHeight <\n 10;\n setShowScrollButton(!atBottom);\n };\n\n checkScroll();\n scrollElement.addEventListener(\"scroll\", checkScroll);\n\n // Also check on resize\n const resizeObserver = new ResizeObserver(checkScroll);\n resizeObserver.observe(scrollElement);\n\n return () => {\n scrollElement.removeEventListener(\"scroll\", checkScroll);\n resizeObserver.disconnect();\n };\n }, [scrollRef, autoScroll]);\n\n if (!hasMounted) {\n return (\n <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\">\n <div className=\"cpk:px-4 cpk:sm:px-0 cpk:[div[data-sidebar-chat]_&]:px-8 cpk:[div[data-popup-chat]_&]:px-6\">\n {children}\n </div>\n </div>\n );\n }\n\n // When autoScroll is false, we don't use StickToBottom\n if (!autoScroll) {\n const BoundFeather = renderSlot(feather, CopilotChatView.Feather, {});\n\n return (\n <div\n ref={scrollRef}\n className={cn(\n \"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\",\n className,\n )}\n {...props}\n >\n <div\n ref={contentRef}\n className=\"cpk:px-4 cpk:sm:px-0 cpk:[div[data-sidebar-chat]_&]:px-8 cpk:[div[data-popup-chat]_&]:px-6\"\n >\n {children}\n </div>\n\n {/* Feather gradient overlay */}\n {BoundFeather}\n\n {/* Scroll to bottom button for manual mode */}\n {showScrollButton && !isResizing && (\n <div\n className=\"cpk:absolute cpk:inset-x-0 cpk:flex cpk:justify-center cpk:z-30 cpk:pointer-events-none\"\n style={{\n bottom: `${inputContainerHeight + FEATHER_HEIGHT + 16}px`,\n }}\n >\n {renderSlot(\n scrollToBottomButton,\n CopilotChatView.ScrollToBottomButton,\n {\n onClick: () => scrollToBottom(),\n },\n )}\n </div>\n )}\n </div>\n );\n }\n\n return (\n <StickToBottom\n className={cn(\n \"cpk:h-full cpk:max-h-full cpk:flex cpk:flex-col cpk:min-h-0 cpk:relative\",\n className,\n )}\n resize=\"smooth\"\n initial=\"smooth\"\n {...props}\n >\n <ScrollContent\n scrollToBottomButton={scrollToBottomButton}\n feather={feather}\n inputContainerHeight={inputContainerHeight}\n isResizing={isResizing}\n >\n {children}\n </ScrollContent>\n </StickToBottom>\n );\n };\n\n export const ScrollToBottomButton: React.FC<\n React.ButtonHTMLAttributes<HTMLButtonElement>\n > = ({ className, ...props }) => (\n <Button\n data-testid=\"copilot-scroll-to-bottom\"\n variant=\"outline\"\n size=\"sm\"\n className={twMerge(\n \"cpk:rounded-full cpk:w-10 cpk:h-10 cpk:p-0 cpk:pointer-events-auto\",\n \"cpk:bg-white cpk:dark:bg-gray-900\",\n \"cpk:shadow-lg cpk:border cpk:border-gray-200 cpk:dark:border-gray-700\",\n \"cpk:hover:bg-gray-50 cpk:dark:hover:bg-gray-800\",\n \"cpk:flex cpk:items-center cpk:justify-center cpk:cursor-pointer\",\n className,\n )}\n {...props}\n >\n <ChevronDown className=\"cpk:w-4 cpk:h-4 cpk:text-gray-600 cpk:dark:text-white\" />\n </Button>\n );\n\n export const Feather: React.FC<React.HTMLAttributes<HTMLDivElement>> = ({\n className,\n style,\n ...props\n }) => (\n <div\n className={cn(\n \"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\",\n \"cpk:from-white cpk:via-white cpk:to-transparent\",\n \"cpk:dark:from-[rgb(33,33,33)] cpk:dark:via-[rgb(33,33,33)]\",\n className,\n )}\n style={style}\n {...props}\n />\n );\n\n export const WelcomeMessage: React.FC<\n React.HTMLAttributes<HTMLDivElement>\n > = ({ className, ...props }) => {\n const config = useCopilotChatConfiguration();\n const labels = config?.labels ?? CopilotChatDefaultLabels;\n\n return (\n <h1\n className={cn(\n \"cpk:text-xl cpk:sm:text-2xl cpk:font-medium cpk:text-foreground cpk:text-center\",\n className,\n )}\n {...props}\n >\n {labels.welcomeMessageText}\n </h1>\n );\n };\n\n export const WelcomeScreen: React.FC<WelcomeScreenProps> = ({\n welcomeMessage,\n input,\n suggestionView,\n className,\n children,\n ...props\n }) => {\n // Render the welcomeMessage slot internally\n const BoundWelcomeMessage = renderSlot(\n welcomeMessage,\n CopilotChatView.WelcomeMessage,\n {},\n );\n\n if (children) {\n return (\n <div data-copilotkit style={{ display: \"contents\" }}>\n {children({\n welcomeMessage: BoundWelcomeMessage,\n input,\n suggestionView,\n className,\n ...props,\n })}\n </div>\n );\n }\n\n return (\n <div\n data-testid=\"copilot-welcome-screen\"\n className={cn(\n \"cpk:flex-1 cpk:flex cpk:flex-col cpk:items-center cpk:justify-center cpk:px-4\",\n className,\n )}\n {...props}\n >\n <div className=\"cpk:w-full cpk:max-w-3xl cpk:flex cpk:flex-col cpk:items-center\">\n {/* Welcome message */}\n <div className=\"cpk:mb-6\">{BoundWelcomeMessage}</div>\n\n {/* Input */}\n <div className=\"cpk:w-full\">{input}</div>\n\n {/* Suggestions */}\n <div className=\"cpk:mt-4 cpk:flex cpk:justify-center\">\n {suggestionView}\n </div>\n </div>\n </div>\n );\n };\n}\n\nexport default CopilotChatView;\n"],"mappings":"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"}
|
|
@@ -113,7 +113,7 @@ function CopilotChatView({ messageView, input, scrollView, suggestionView, welco
|
|
|
113
113
|
"data-copilotkit": true,
|
|
114
114
|
"data-testid": "copilot-chat",
|
|
115
115
|
"data-copilot-running": isRunning ? "true" : "false",
|
|
116
|
-
className: twMerge("cpk:relative cpk:h-full cpk:flex cpk:flex-col", className),
|
|
116
|
+
className: twMerge("copilotKitChat cpk:relative cpk:h-full cpk:flex cpk:flex-col", className),
|
|
117
117
|
...props,
|
|
118
118
|
children: BoundWelcomeScreen
|
|
119
119
|
});
|
|
@@ -132,7 +132,7 @@ function CopilotChatView({ messageView, input, scrollView, suggestionView, welco
|
|
|
132
132
|
"data-copilotkit": true,
|
|
133
133
|
"data-testid": "copilot-chat",
|
|
134
134
|
"data-copilot-running": isRunning ? "true" : "false",
|
|
135
|
-
className: twMerge("cpk:relative cpk:h-full", className),
|
|
135
|
+
className: twMerge("copilotKitChat cpk:relative cpk:h-full", className),
|
|
136
136
|
...props,
|
|
137
137
|
children: [BoundScrollView, BoundInput]
|
|
138
138
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CopilotChatView.mjs","names":["CopilotChatInput"],"sources":["../../../src/components/chat/CopilotChatView.tsx"],"sourcesContent":["import React, { useRef, useState, useEffect } from \"react\";\nimport { WithSlots, SlotValue, renderSlot } from \"@/lib/slots\";\nimport CopilotChatMessageView from \"./CopilotChatMessageView\";\nimport CopilotChatInput, {\n CopilotChatInputProps,\n CopilotChatInputMode,\n} from \"./CopilotChatInput\";\nimport CopilotChatSuggestionView, {\n CopilotChatSuggestionViewProps,\n} from \"./CopilotChatSuggestionView\";\nimport { Suggestion } from \"@copilotkitnext/core\";\nimport { Message } from \"@ag-ui/core\";\nimport { twMerge } from \"tailwind-merge\";\nimport {\n StickToBottom,\n useStickToBottom,\n useStickToBottomContext,\n} from \"use-stick-to-bottom\";\nimport { ChevronDown } from \"lucide-react\";\nimport { Button } from \"@/components/ui/button\";\nimport { cn } from \"@/lib/utils\";\nimport {\n useCopilotChatConfiguration,\n CopilotChatDefaultLabels,\n} from \"@/providers/CopilotChatConfigurationProvider\";\nimport { useKeyboardHeight } from \"@/hooks/use-keyboard-height\";\n\n// Height of the feather gradient overlay (h-24 = 6rem = 96px)\nconst FEATHER_HEIGHT = 96;\n\n// Forward declaration for WelcomeScreen component type\nexport type WelcomeScreenProps = WithSlots<\n {\n welcomeMessage: React.FC<React.HTMLAttributes<HTMLDivElement>>;\n },\n {\n input: React.ReactElement;\n suggestionView: React.ReactElement;\n } & React.HTMLAttributes<HTMLDivElement>\n>;\n\nexport type CopilotChatViewProps = WithSlots<\n {\n messageView: typeof CopilotChatMessageView;\n scrollView: typeof CopilotChatView.ScrollView;\n input: typeof CopilotChatInput;\n suggestionView: typeof CopilotChatSuggestionView;\n },\n {\n messages?: Message[];\n autoScroll?: boolean;\n isRunning?: boolean;\n suggestions?: Suggestion[];\n suggestionLoadingIndexes?: ReadonlyArray<number>;\n onSelectSuggestion?: (suggestion: Suggestion, index: number) => void;\n welcomeScreen?: SlotValue<React.FC<WelcomeScreenProps>> | boolean;\n // Input behavior props\n onSubmitMessage?: (value: string) => void;\n onStop?: () => void;\n inputMode?: CopilotChatInputMode;\n inputValue?: string;\n onInputChange?: (value: string) => void;\n onStartTranscribe?: () => void;\n onCancelTranscribe?: () => void;\n onFinishTranscribe?: () => void;\n onFinishTranscribeWithAudio?: (audioBlob: Blob) => Promise<void>;\n /**\n * @deprecated Use the `input` slot's `disclaimer` prop instead:\n * ```tsx\n * <CopilotChat input={{ disclaimer: MyDisclaimer }} />\n * ```\n */\n disclaimer?: SlotValue<React.FC<React.HTMLAttributes<HTMLDivElement>>>;\n } & React.HTMLAttributes<HTMLDivElement>\n>;\n\nexport function CopilotChatView({\n messageView,\n input,\n scrollView,\n suggestionView,\n welcomeScreen,\n messages = [],\n autoScroll = true,\n isRunning = false,\n suggestions,\n suggestionLoadingIndexes,\n onSelectSuggestion,\n // Input behavior props\n onSubmitMessage,\n onStop,\n inputMode,\n inputValue,\n onInputChange,\n onStartTranscribe,\n onCancelTranscribe,\n onFinishTranscribe,\n onFinishTranscribeWithAudio,\n // Deprecated — forwarded to input slot\n disclaimer,\n children,\n className,\n ...props\n}: CopilotChatViewProps) {\n const inputContainerRef = useRef<HTMLDivElement>(null);\n const [inputContainerHeight, setInputContainerHeight] = useState(0);\n const [isResizing, setIsResizing] = useState(false);\n const resizeTimeoutRef = useRef<NodeJS.Timeout | null>(null);\n\n // Track keyboard state for mobile\n const { isKeyboardOpen, keyboardHeight, availableHeight } =\n useKeyboardHeight();\n\n // Track input container height changes\n useEffect(() => {\n const element = inputContainerRef.current;\n if (!element) return;\n\n const resizeObserver = new ResizeObserver((entries) => {\n for (const entry of entries) {\n const newHeight = entry.contentRect.height;\n\n // Update height and set resizing state\n setInputContainerHeight((prevHeight) => {\n if (newHeight !== prevHeight) {\n setIsResizing(true);\n\n // Clear existing timeout\n if (resizeTimeoutRef.current) {\n clearTimeout(resizeTimeoutRef.current);\n }\n\n // Set isResizing to false after a short delay\n resizeTimeoutRef.current = setTimeout(() => {\n setIsResizing(false);\n }, 250);\n\n return newHeight;\n }\n return prevHeight;\n });\n }\n });\n\n resizeObserver.observe(element);\n\n // Set initial height\n setInputContainerHeight(element.offsetHeight);\n\n return () => {\n resizeObserver.disconnect();\n if (resizeTimeoutRef.current) {\n clearTimeout(resizeTimeoutRef.current);\n }\n };\n }, []);\n\n const BoundMessageView = renderSlot(messageView, CopilotChatMessageView, {\n messages,\n isRunning,\n });\n\n const BoundInput = renderSlot(input, CopilotChatInput, {\n onSubmitMessage,\n onStop,\n mode: inputMode,\n value: inputValue,\n onChange: onInputChange,\n isRunning,\n onStartTranscribe,\n onCancelTranscribe,\n onFinishTranscribe,\n onFinishTranscribeWithAudio,\n positioning: \"absolute\",\n keyboardHeight: isKeyboardOpen ? keyboardHeight : 0,\n containerRef: inputContainerRef,\n showDisclaimer: true,\n ...(disclaimer !== undefined ? { disclaimer } : {}),\n } as CopilotChatInputProps);\n\n const hasSuggestions = Array.isArray(suggestions) && suggestions.length > 0;\n const BoundSuggestionView = hasSuggestions\n ? renderSlot(suggestionView, CopilotChatSuggestionView, {\n suggestions,\n loadingIndexes: suggestionLoadingIndexes,\n onSelectSuggestion,\n className: \"cpk:mb-3 cpk:lg:ml-4 cpk:lg:mr-4 cpk:ml-0 cpk:mr-0\",\n })\n : null;\n\n const BoundScrollView = renderSlot(scrollView, CopilotChatView.ScrollView, {\n autoScroll,\n inputContainerHeight,\n isResizing,\n children: (\n <div\n style={{\n paddingBottom: `${inputContainerHeight + FEATHER_HEIGHT + (hasSuggestions ? 4 : 32)}px`,\n }}\n >\n <div className=\"cpk:max-w-3xl cpk:mx-auto\">\n {BoundMessageView}\n {hasSuggestions ? (\n <div className=\"cpk:pl-0 cpk:pr-4 cpk:sm:px-0 cpk:mt-4\">\n {BoundSuggestionView}\n </div>\n ) : null}\n </div>\n </div>\n ),\n });\n\n // Welcome screen logic\n const isEmpty = messages.length === 0;\n // Type assertion needed because TypeScript doesn't fully propagate `| boolean` through WithSlots\n const welcomeScreenDisabled = (welcomeScreen as unknown) === false;\n const shouldShowWelcomeScreen = isEmpty && !welcomeScreenDisabled;\n\n if (shouldShowWelcomeScreen) {\n // Create a separate input for welcome screen with static positioning and disclaimer visible\n const BoundInputForWelcome = renderSlot(input, CopilotChatInput, {\n onSubmitMessage,\n onStop,\n mode: inputMode,\n value: inputValue,\n onChange: onInputChange,\n isRunning,\n onStartTranscribe,\n onCancelTranscribe,\n onFinishTranscribe,\n onFinishTranscribeWithAudio,\n positioning: \"static\",\n showDisclaimer: true,\n ...(disclaimer !== undefined ? { disclaimer } : {}),\n } as CopilotChatInputProps);\n\n // Convert boolean `true` to undefined (use default), and exclude `false` since we've checked for it\n const welcomeScreenSlot = (\n welcomeScreen === true ? undefined : welcomeScreen\n ) as SlotValue<React.FC<WelcomeScreenProps>> | undefined;\n const BoundWelcomeScreen = renderSlot(\n welcomeScreenSlot,\n CopilotChatView.WelcomeScreen,\n {\n input: BoundInputForWelcome,\n suggestionView: BoundSuggestionView ?? <></>,\n },\n );\n\n return (\n <div\n data-copilotkit\n data-testid=\"copilot-chat\"\n data-copilot-running={isRunning ? \"true\" : \"false\"}\n className={twMerge(\n \"cpk:relative cpk:h-full cpk:flex cpk:flex-col\",\n className,\n )}\n {...props}\n >\n {BoundWelcomeScreen}\n </div>\n );\n }\n\n if (children) {\n return (\n <div data-copilotkit style={{ display: \"contents\" }}>\n {children({\n messageView: BoundMessageView,\n input: BoundInput,\n scrollView: BoundScrollView,\n suggestionView: BoundSuggestionView ?? <></>,\n })}\n </div>\n );\n }\n\n return (\n <div\n data-copilotkit\n data-testid=\"copilot-chat\"\n data-copilot-running={isRunning ? \"true\" : \"false\"}\n className={twMerge(\"cpk:relative cpk:h-full\", className)}\n {...props}\n >\n {BoundScrollView}\n\n {BoundInput}\n </div>\n );\n}\n\nexport namespace CopilotChatView {\n // Inner component that has access to StickToBottom context\n const ScrollContent: React.FC<{\n children: React.ReactNode;\n scrollToBottomButton?: SlotValue<\n React.FC<React.ButtonHTMLAttributes<HTMLButtonElement>>\n >;\n feather?: SlotValue<React.FC<React.HTMLAttributes<HTMLDivElement>>>;\n inputContainerHeight: number;\n isResizing: boolean;\n }> = ({\n children,\n scrollToBottomButton,\n feather,\n inputContainerHeight,\n isResizing,\n }) => {\n const { isAtBottom, scrollToBottom } = useStickToBottomContext();\n\n const BoundFeather = renderSlot(feather, CopilotChatView.Feather, {});\n\n return (\n <>\n <StickToBottom.Content\n className=\"cpk:overflow-y-scroll cpk:overflow-x-hidden\"\n style={{ flex: \"1 1 0%\", minHeight: 0 }}\n >\n <div className=\"cpk:px-4 cpk:sm:px-0 cpk:[div[data-sidebar-chat]_&]:px-8 cpk:[div[data-popup-chat]_&]:px-6\">\n {children}\n </div>\n </StickToBottom.Content>\n\n {/* Feather gradient overlay */}\n {BoundFeather}\n\n {/* Scroll to bottom button - hidden during resize */}\n {!isAtBottom && !isResizing && (\n <div\n className=\"cpk:absolute cpk:inset-x-0 cpk:flex cpk:justify-center cpk:z-30 cpk:pointer-events-none\"\n style={{\n bottom: `${inputContainerHeight + FEATHER_HEIGHT + 16}px`,\n }}\n >\n {renderSlot(\n scrollToBottomButton,\n CopilotChatView.ScrollToBottomButton,\n {\n onClick: () => scrollToBottom(),\n },\n )}\n </div>\n )}\n </>\n );\n };\n\n export const ScrollView: React.FC<\n React.HTMLAttributes<HTMLDivElement> & {\n autoScroll?: boolean;\n scrollToBottomButton?: SlotValue<\n React.FC<React.ButtonHTMLAttributes<HTMLButtonElement>>\n >;\n feather?: SlotValue<React.FC<React.HTMLAttributes<HTMLDivElement>>>;\n inputContainerHeight?: number;\n isResizing?: boolean;\n }\n > = ({\n children,\n autoScroll = true,\n scrollToBottomButton,\n feather,\n inputContainerHeight = 0,\n isResizing = false,\n className,\n ...props\n }) => {\n const [hasMounted, setHasMounted] = useState(false);\n const { scrollRef, contentRef, scrollToBottom } = useStickToBottom();\n const [showScrollButton, setShowScrollButton] = useState(false);\n\n useEffect(() => {\n setHasMounted(true);\n }, []);\n\n // Monitor scroll position for non-autoscroll mode\n useEffect(() => {\n if (autoScroll) return; // Skip for autoscroll mode\n\n const scrollElement = scrollRef.current;\n if (!scrollElement) return;\n\n const checkScroll = () => {\n const atBottom =\n scrollElement.scrollHeight -\n scrollElement.scrollTop -\n scrollElement.clientHeight <\n 10;\n setShowScrollButton(!atBottom);\n };\n\n checkScroll();\n scrollElement.addEventListener(\"scroll\", checkScroll);\n\n // Also check on resize\n const resizeObserver = new ResizeObserver(checkScroll);\n resizeObserver.observe(scrollElement);\n\n return () => {\n scrollElement.removeEventListener(\"scroll\", checkScroll);\n resizeObserver.disconnect();\n };\n }, [scrollRef, autoScroll]);\n\n if (!hasMounted) {\n return (\n <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\">\n <div className=\"cpk:px-4 cpk:sm:px-0 cpk:[div[data-sidebar-chat]_&]:px-8 cpk:[div[data-popup-chat]_&]:px-6\">\n {children}\n </div>\n </div>\n );\n }\n\n // When autoScroll is false, we don't use StickToBottom\n if (!autoScroll) {\n const BoundFeather = renderSlot(feather, CopilotChatView.Feather, {});\n\n return (\n <div\n ref={scrollRef}\n className={cn(\n \"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\",\n className,\n )}\n {...props}\n >\n <div\n ref={contentRef}\n className=\"cpk:px-4 cpk:sm:px-0 cpk:[div[data-sidebar-chat]_&]:px-8 cpk:[div[data-popup-chat]_&]:px-6\"\n >\n {children}\n </div>\n\n {/* Feather gradient overlay */}\n {BoundFeather}\n\n {/* Scroll to bottom button for manual mode */}\n {showScrollButton && !isResizing && (\n <div\n className=\"cpk:absolute cpk:inset-x-0 cpk:flex cpk:justify-center cpk:z-30 cpk:pointer-events-none\"\n style={{\n bottom: `${inputContainerHeight + FEATHER_HEIGHT + 16}px`,\n }}\n >\n {renderSlot(\n scrollToBottomButton,\n CopilotChatView.ScrollToBottomButton,\n {\n onClick: () => scrollToBottom(),\n },\n )}\n </div>\n )}\n </div>\n );\n }\n\n return (\n <StickToBottom\n className={cn(\n \"cpk:h-full cpk:max-h-full cpk:flex cpk:flex-col cpk:min-h-0 cpk:relative\",\n className,\n )}\n resize=\"smooth\"\n initial=\"smooth\"\n {...props}\n >\n <ScrollContent\n scrollToBottomButton={scrollToBottomButton}\n feather={feather}\n inputContainerHeight={inputContainerHeight}\n isResizing={isResizing}\n >\n {children}\n </ScrollContent>\n </StickToBottom>\n );\n };\n\n export const ScrollToBottomButton: React.FC<\n React.ButtonHTMLAttributes<HTMLButtonElement>\n > = ({ className, ...props }) => (\n <Button\n data-testid=\"copilot-scroll-to-bottom\"\n variant=\"outline\"\n size=\"sm\"\n className={twMerge(\n \"cpk:rounded-full cpk:w-10 cpk:h-10 cpk:p-0 cpk:pointer-events-auto\",\n \"cpk:bg-white cpk:dark:bg-gray-900\",\n \"cpk:shadow-lg cpk:border cpk:border-gray-200 cpk:dark:border-gray-700\",\n \"cpk:hover:bg-gray-50 cpk:dark:hover:bg-gray-800\",\n \"cpk:flex cpk:items-center cpk:justify-center cpk:cursor-pointer\",\n className,\n )}\n {...props}\n >\n <ChevronDown className=\"cpk:w-4 cpk:h-4 cpk:text-gray-600 cpk:dark:text-white\" />\n </Button>\n );\n\n export const Feather: React.FC<React.HTMLAttributes<HTMLDivElement>> = ({\n className,\n style,\n ...props\n }) => (\n <div\n className={cn(\n \"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\",\n \"cpk:from-white cpk:via-white cpk:to-transparent\",\n \"cpk:dark:from-[rgb(33,33,33)] cpk:dark:via-[rgb(33,33,33)]\",\n className,\n )}\n style={style}\n {...props}\n />\n );\n\n export const WelcomeMessage: React.FC<\n React.HTMLAttributes<HTMLDivElement>\n > = ({ className, ...props }) => {\n const config = useCopilotChatConfiguration();\n const labels = config?.labels ?? CopilotChatDefaultLabels;\n\n return (\n <h1\n className={cn(\n \"cpk:text-xl cpk:sm:text-2xl cpk:font-medium cpk:text-foreground cpk:text-center\",\n className,\n )}\n {...props}\n >\n {labels.welcomeMessageText}\n </h1>\n );\n };\n\n export const WelcomeScreen: React.FC<WelcomeScreenProps> = ({\n welcomeMessage,\n input,\n suggestionView,\n className,\n children,\n ...props\n }) => {\n // Render the welcomeMessage slot internally\n const BoundWelcomeMessage = renderSlot(\n welcomeMessage,\n CopilotChatView.WelcomeMessage,\n {},\n );\n\n if (children) {\n return (\n <div data-copilotkit style={{ display: \"contents\" }}>\n {children({\n welcomeMessage: BoundWelcomeMessage,\n input,\n suggestionView,\n className,\n ...props,\n })}\n </div>\n );\n }\n\n return (\n <div\n data-testid=\"copilot-welcome-screen\"\n className={cn(\n \"cpk:flex-1 cpk:flex cpk:flex-col cpk:items-center cpk:justify-center cpk:px-4\",\n className,\n )}\n {...props}\n >\n <div className=\"cpk:w-full cpk:max-w-3xl cpk:flex cpk:flex-col cpk:items-center\">\n {/* Welcome message */}\n <div className=\"cpk:mb-6\">{BoundWelcomeMessage}</div>\n\n {/* Input */}\n <div className=\"cpk:w-full\">{input}</div>\n\n {/* Suggestions */}\n <div className=\"cpk:mt-4 cpk:flex cpk:justify-center\">\n {suggestionView}\n </div>\n </div>\n </div>\n );\n };\n}\n\nexport default CopilotChatView;\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"CopilotChatView.mjs","names":["CopilotChatInput"],"sources":["../../../src/components/chat/CopilotChatView.tsx"],"sourcesContent":["import React, { useRef, useState, useEffect } from \"react\";\nimport { WithSlots, SlotValue, renderSlot } from \"@/lib/slots\";\nimport CopilotChatMessageView from \"./CopilotChatMessageView\";\nimport CopilotChatInput, {\n CopilotChatInputProps,\n CopilotChatInputMode,\n} from \"./CopilotChatInput\";\nimport CopilotChatSuggestionView, {\n CopilotChatSuggestionViewProps,\n} from \"./CopilotChatSuggestionView\";\nimport { Suggestion } from \"@copilotkitnext/core\";\nimport { Message } from \"@ag-ui/core\";\nimport { twMerge } from \"tailwind-merge\";\nimport {\n StickToBottom,\n useStickToBottom,\n useStickToBottomContext,\n} from \"use-stick-to-bottom\";\nimport { ChevronDown } from \"lucide-react\";\nimport { Button } from \"@/components/ui/button\";\nimport { cn } from \"@/lib/utils\";\nimport {\n useCopilotChatConfiguration,\n CopilotChatDefaultLabels,\n} from \"@/providers/CopilotChatConfigurationProvider\";\nimport { useKeyboardHeight } from \"@/hooks/use-keyboard-height\";\n\n// Height of the feather gradient overlay (h-24 = 6rem = 96px)\nconst FEATHER_HEIGHT = 96;\n\n// Forward declaration for WelcomeScreen component type\nexport type WelcomeScreenProps = WithSlots<\n {\n welcomeMessage: React.FC<React.HTMLAttributes<HTMLDivElement>>;\n },\n {\n input: React.ReactElement;\n suggestionView: React.ReactElement;\n } & React.HTMLAttributes<HTMLDivElement>\n>;\n\nexport type CopilotChatViewProps = WithSlots<\n {\n messageView: typeof CopilotChatMessageView;\n scrollView: typeof CopilotChatView.ScrollView;\n input: typeof CopilotChatInput;\n suggestionView: typeof CopilotChatSuggestionView;\n },\n {\n messages?: Message[];\n autoScroll?: boolean;\n isRunning?: boolean;\n suggestions?: Suggestion[];\n suggestionLoadingIndexes?: ReadonlyArray<number>;\n onSelectSuggestion?: (suggestion: Suggestion, index: number) => void;\n welcomeScreen?: SlotValue<React.FC<WelcomeScreenProps>> | boolean;\n // Input behavior props\n onSubmitMessage?: (value: string) => void;\n onStop?: () => void;\n inputMode?: CopilotChatInputMode;\n inputValue?: string;\n onInputChange?: (value: string) => void;\n onStartTranscribe?: () => void;\n onCancelTranscribe?: () => void;\n onFinishTranscribe?: () => void;\n onFinishTranscribeWithAudio?: (audioBlob: Blob) => Promise<void>;\n /**\n * @deprecated Use the `input` slot's `disclaimer` prop instead:\n * ```tsx\n * <CopilotChat input={{ disclaimer: MyDisclaimer }} />\n * ```\n */\n disclaimer?: SlotValue<React.FC<React.HTMLAttributes<HTMLDivElement>>>;\n } & React.HTMLAttributes<HTMLDivElement>\n>;\n\nexport function CopilotChatView({\n messageView,\n input,\n scrollView,\n suggestionView,\n welcomeScreen,\n messages = [],\n autoScroll = true,\n isRunning = false,\n suggestions,\n suggestionLoadingIndexes,\n onSelectSuggestion,\n // Input behavior props\n onSubmitMessage,\n onStop,\n inputMode,\n inputValue,\n onInputChange,\n onStartTranscribe,\n onCancelTranscribe,\n onFinishTranscribe,\n onFinishTranscribeWithAudio,\n // Deprecated — forwarded to input slot\n disclaimer,\n children,\n className,\n ...props\n}: CopilotChatViewProps) {\n const inputContainerRef = useRef<HTMLDivElement>(null);\n const [inputContainerHeight, setInputContainerHeight] = useState(0);\n const [isResizing, setIsResizing] = useState(false);\n const resizeTimeoutRef = useRef<NodeJS.Timeout | null>(null);\n\n // Track keyboard state for mobile\n const { isKeyboardOpen, keyboardHeight, availableHeight } =\n useKeyboardHeight();\n\n // Track input container height changes\n useEffect(() => {\n const element = inputContainerRef.current;\n if (!element) return;\n\n const resizeObserver = new ResizeObserver((entries) => {\n for (const entry of entries) {\n const newHeight = entry.contentRect.height;\n\n // Update height and set resizing state\n setInputContainerHeight((prevHeight) => {\n if (newHeight !== prevHeight) {\n setIsResizing(true);\n\n // Clear existing timeout\n if (resizeTimeoutRef.current) {\n clearTimeout(resizeTimeoutRef.current);\n }\n\n // Set isResizing to false after a short delay\n resizeTimeoutRef.current = setTimeout(() => {\n setIsResizing(false);\n }, 250);\n\n return newHeight;\n }\n return prevHeight;\n });\n }\n });\n\n resizeObserver.observe(element);\n\n // Set initial height\n setInputContainerHeight(element.offsetHeight);\n\n return () => {\n resizeObserver.disconnect();\n if (resizeTimeoutRef.current) {\n clearTimeout(resizeTimeoutRef.current);\n }\n };\n }, []);\n\n const BoundMessageView = renderSlot(messageView, CopilotChatMessageView, {\n messages,\n isRunning,\n });\n\n const BoundInput = renderSlot(input, CopilotChatInput, {\n onSubmitMessage,\n onStop,\n mode: inputMode,\n value: inputValue,\n onChange: onInputChange,\n isRunning,\n onStartTranscribe,\n onCancelTranscribe,\n onFinishTranscribe,\n onFinishTranscribeWithAudio,\n positioning: \"absolute\",\n keyboardHeight: isKeyboardOpen ? keyboardHeight : 0,\n containerRef: inputContainerRef,\n showDisclaimer: true,\n ...(disclaimer !== undefined ? { disclaimer } : {}),\n } as CopilotChatInputProps);\n\n const hasSuggestions = Array.isArray(suggestions) && suggestions.length > 0;\n const BoundSuggestionView = hasSuggestions\n ? renderSlot(suggestionView, CopilotChatSuggestionView, {\n suggestions,\n loadingIndexes: suggestionLoadingIndexes,\n onSelectSuggestion,\n className: \"cpk:mb-3 cpk:lg:ml-4 cpk:lg:mr-4 cpk:ml-0 cpk:mr-0\",\n })\n : null;\n\n const BoundScrollView = renderSlot(scrollView, CopilotChatView.ScrollView, {\n autoScroll,\n inputContainerHeight,\n isResizing,\n children: (\n <div\n style={{\n paddingBottom: `${inputContainerHeight + FEATHER_HEIGHT + (hasSuggestions ? 4 : 32)}px`,\n }}\n >\n <div className=\"cpk:max-w-3xl cpk:mx-auto\">\n {BoundMessageView}\n {hasSuggestions ? (\n <div className=\"cpk:pl-0 cpk:pr-4 cpk:sm:px-0 cpk:mt-4\">\n {BoundSuggestionView}\n </div>\n ) : null}\n </div>\n </div>\n ),\n });\n\n // Welcome screen logic\n const isEmpty = messages.length === 0;\n // Type assertion needed because TypeScript doesn't fully propagate `| boolean` through WithSlots\n const welcomeScreenDisabled = (welcomeScreen as unknown) === false;\n const shouldShowWelcomeScreen = isEmpty && !welcomeScreenDisabled;\n\n if (shouldShowWelcomeScreen) {\n // Create a separate input for welcome screen with static positioning and disclaimer visible\n const BoundInputForWelcome = renderSlot(input, CopilotChatInput, {\n onSubmitMessage,\n onStop,\n mode: inputMode,\n value: inputValue,\n onChange: onInputChange,\n isRunning,\n onStartTranscribe,\n onCancelTranscribe,\n onFinishTranscribe,\n onFinishTranscribeWithAudio,\n positioning: \"static\",\n showDisclaimer: true,\n ...(disclaimer !== undefined ? { disclaimer } : {}),\n } as CopilotChatInputProps);\n\n // Convert boolean `true` to undefined (use default), and exclude `false` since we've checked for it\n const welcomeScreenSlot = (\n welcomeScreen === true ? undefined : welcomeScreen\n ) as SlotValue<React.FC<WelcomeScreenProps>> | undefined;\n const BoundWelcomeScreen = renderSlot(\n welcomeScreenSlot,\n CopilotChatView.WelcomeScreen,\n {\n input: BoundInputForWelcome,\n suggestionView: BoundSuggestionView ?? <></>,\n },\n );\n\n return (\n <div\n data-copilotkit\n data-testid=\"copilot-chat\"\n data-copilot-running={isRunning ? \"true\" : \"false\"}\n className={twMerge(\n \"copilotKitChat cpk:relative cpk:h-full cpk:flex cpk:flex-col\",\n className,\n )}\n {...props}\n >\n {BoundWelcomeScreen}\n </div>\n );\n }\n\n if (children) {\n return (\n <div data-copilotkit style={{ display: \"contents\" }}>\n {children({\n messageView: BoundMessageView,\n input: BoundInput,\n scrollView: BoundScrollView,\n suggestionView: BoundSuggestionView ?? <></>,\n })}\n </div>\n );\n }\n\n return (\n <div\n data-copilotkit\n data-testid=\"copilot-chat\"\n data-copilot-running={isRunning ? \"true\" : \"false\"}\n className={twMerge(\"copilotKitChat cpk:relative cpk:h-full\", className)}\n {...props}\n >\n {BoundScrollView}\n\n {BoundInput}\n </div>\n );\n}\n\nexport namespace CopilotChatView {\n // Inner component that has access to StickToBottom context\n const ScrollContent: React.FC<{\n children: React.ReactNode;\n scrollToBottomButton?: SlotValue<\n React.FC<React.ButtonHTMLAttributes<HTMLButtonElement>>\n >;\n feather?: SlotValue<React.FC<React.HTMLAttributes<HTMLDivElement>>>;\n inputContainerHeight: number;\n isResizing: boolean;\n }> = ({\n children,\n scrollToBottomButton,\n feather,\n inputContainerHeight,\n isResizing,\n }) => {\n const { isAtBottom, scrollToBottom } = useStickToBottomContext();\n\n const BoundFeather = renderSlot(feather, CopilotChatView.Feather, {});\n\n return (\n <>\n <StickToBottom.Content\n className=\"cpk:overflow-y-scroll cpk:overflow-x-hidden\"\n style={{ flex: \"1 1 0%\", minHeight: 0 }}\n >\n <div className=\"cpk:px-4 cpk:sm:px-0 cpk:[div[data-sidebar-chat]_&]:px-8 cpk:[div[data-popup-chat]_&]:px-6\">\n {children}\n </div>\n </StickToBottom.Content>\n\n {/* Feather gradient overlay */}\n {BoundFeather}\n\n {/* Scroll to bottom button - hidden during resize */}\n {!isAtBottom && !isResizing && (\n <div\n className=\"cpk:absolute cpk:inset-x-0 cpk:flex cpk:justify-center cpk:z-30 cpk:pointer-events-none\"\n style={{\n bottom: `${inputContainerHeight + FEATHER_HEIGHT + 16}px`,\n }}\n >\n {renderSlot(\n scrollToBottomButton,\n CopilotChatView.ScrollToBottomButton,\n {\n onClick: () => scrollToBottom(),\n },\n )}\n </div>\n )}\n </>\n );\n };\n\n export const ScrollView: React.FC<\n React.HTMLAttributes<HTMLDivElement> & {\n autoScroll?: boolean;\n scrollToBottomButton?: SlotValue<\n React.FC<React.ButtonHTMLAttributes<HTMLButtonElement>>\n >;\n feather?: SlotValue<React.FC<React.HTMLAttributes<HTMLDivElement>>>;\n inputContainerHeight?: number;\n isResizing?: boolean;\n }\n > = ({\n children,\n autoScroll = true,\n scrollToBottomButton,\n feather,\n inputContainerHeight = 0,\n isResizing = false,\n className,\n ...props\n }) => {\n const [hasMounted, setHasMounted] = useState(false);\n const { scrollRef, contentRef, scrollToBottom } = useStickToBottom();\n const [showScrollButton, setShowScrollButton] = useState(false);\n\n useEffect(() => {\n setHasMounted(true);\n }, []);\n\n // Monitor scroll position for non-autoscroll mode\n useEffect(() => {\n if (autoScroll) return; // Skip for autoscroll mode\n\n const scrollElement = scrollRef.current;\n if (!scrollElement) return;\n\n const checkScroll = () => {\n const atBottom =\n scrollElement.scrollHeight -\n scrollElement.scrollTop -\n scrollElement.clientHeight <\n 10;\n setShowScrollButton(!atBottom);\n };\n\n checkScroll();\n scrollElement.addEventListener(\"scroll\", checkScroll);\n\n // Also check on resize\n const resizeObserver = new ResizeObserver(checkScroll);\n resizeObserver.observe(scrollElement);\n\n return () => {\n scrollElement.removeEventListener(\"scroll\", checkScroll);\n resizeObserver.disconnect();\n };\n }, [scrollRef, autoScroll]);\n\n if (!hasMounted) {\n return (\n <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\">\n <div className=\"cpk:px-4 cpk:sm:px-0 cpk:[div[data-sidebar-chat]_&]:px-8 cpk:[div[data-popup-chat]_&]:px-6\">\n {children}\n </div>\n </div>\n );\n }\n\n // When autoScroll is false, we don't use StickToBottom\n if (!autoScroll) {\n const BoundFeather = renderSlot(feather, CopilotChatView.Feather, {});\n\n return (\n <div\n ref={scrollRef}\n className={cn(\n \"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\",\n className,\n )}\n {...props}\n >\n <div\n ref={contentRef}\n className=\"cpk:px-4 cpk:sm:px-0 cpk:[div[data-sidebar-chat]_&]:px-8 cpk:[div[data-popup-chat]_&]:px-6\"\n >\n {children}\n </div>\n\n {/* Feather gradient overlay */}\n {BoundFeather}\n\n {/* Scroll to bottom button for manual mode */}\n {showScrollButton && !isResizing && (\n <div\n className=\"cpk:absolute cpk:inset-x-0 cpk:flex cpk:justify-center cpk:z-30 cpk:pointer-events-none\"\n style={{\n bottom: `${inputContainerHeight + FEATHER_HEIGHT + 16}px`,\n }}\n >\n {renderSlot(\n scrollToBottomButton,\n CopilotChatView.ScrollToBottomButton,\n {\n onClick: () => scrollToBottom(),\n },\n )}\n </div>\n )}\n </div>\n );\n }\n\n return (\n <StickToBottom\n className={cn(\n \"cpk:h-full cpk:max-h-full cpk:flex cpk:flex-col cpk:min-h-0 cpk:relative\",\n className,\n )}\n resize=\"smooth\"\n initial=\"smooth\"\n {...props}\n >\n <ScrollContent\n scrollToBottomButton={scrollToBottomButton}\n feather={feather}\n inputContainerHeight={inputContainerHeight}\n isResizing={isResizing}\n >\n {children}\n </ScrollContent>\n </StickToBottom>\n );\n };\n\n export const ScrollToBottomButton: React.FC<\n React.ButtonHTMLAttributes<HTMLButtonElement>\n > = ({ className, ...props }) => (\n <Button\n data-testid=\"copilot-scroll-to-bottom\"\n variant=\"outline\"\n size=\"sm\"\n className={twMerge(\n \"cpk:rounded-full cpk:w-10 cpk:h-10 cpk:p-0 cpk:pointer-events-auto\",\n \"cpk:bg-white cpk:dark:bg-gray-900\",\n \"cpk:shadow-lg cpk:border cpk:border-gray-200 cpk:dark:border-gray-700\",\n \"cpk:hover:bg-gray-50 cpk:dark:hover:bg-gray-800\",\n \"cpk:flex cpk:items-center cpk:justify-center cpk:cursor-pointer\",\n className,\n )}\n {...props}\n >\n <ChevronDown className=\"cpk:w-4 cpk:h-4 cpk:text-gray-600 cpk:dark:text-white\" />\n </Button>\n );\n\n export const Feather: React.FC<React.HTMLAttributes<HTMLDivElement>> = ({\n className,\n style,\n ...props\n }) => (\n <div\n className={cn(\n \"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\",\n \"cpk:from-white cpk:via-white cpk:to-transparent\",\n \"cpk:dark:from-[rgb(33,33,33)] cpk:dark:via-[rgb(33,33,33)]\",\n className,\n )}\n style={style}\n {...props}\n />\n );\n\n export const WelcomeMessage: React.FC<\n React.HTMLAttributes<HTMLDivElement>\n > = ({ className, ...props }) => {\n const config = useCopilotChatConfiguration();\n const labels = config?.labels ?? CopilotChatDefaultLabels;\n\n return (\n <h1\n className={cn(\n \"cpk:text-xl cpk:sm:text-2xl cpk:font-medium cpk:text-foreground cpk:text-center\",\n className,\n )}\n {...props}\n >\n {labels.welcomeMessageText}\n </h1>\n );\n };\n\n export const WelcomeScreen: React.FC<WelcomeScreenProps> = ({\n welcomeMessage,\n input,\n suggestionView,\n className,\n children,\n ...props\n }) => {\n // Render the welcomeMessage slot internally\n const BoundWelcomeMessage = renderSlot(\n welcomeMessage,\n CopilotChatView.WelcomeMessage,\n {},\n );\n\n if (children) {\n return (\n <div data-copilotkit style={{ display: \"contents\" }}>\n {children({\n welcomeMessage: BoundWelcomeMessage,\n input,\n suggestionView,\n className,\n ...props,\n })}\n </div>\n );\n }\n\n return (\n <div\n data-testid=\"copilot-welcome-screen\"\n className={cn(\n \"cpk:flex-1 cpk:flex cpk:flex-col cpk:items-center cpk:justify-center cpk:px-4\",\n className,\n )}\n {...props}\n >\n <div className=\"cpk:w-full cpk:max-w-3xl cpk:flex cpk:flex-col cpk:items-center\">\n {/* Welcome message */}\n <div className=\"cpk:mb-6\">{BoundWelcomeMessage}</div>\n\n {/* Input */}\n <div className=\"cpk:w-full\">{input}</div>\n\n {/* Suggestions */}\n <div className=\"cpk:mt-4 cpk:flex cpk:justify-center\">\n {suggestionView}\n </div>\n </div>\n </div>\n );\n };\n}\n\nexport default CopilotChatView;\n"],"mappings":"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"}
|
|
@@ -26,7 +26,7 @@ function CopilotModalHeader({ title, titleContent, closeButton, children, classN
|
|
|
26
26
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("header", {
|
|
27
27
|
"data-testid": "copilot-modal-header",
|
|
28
28
|
"data-slot": "copilot-modal-header",
|
|
29
|
-
className: require_utils.cn("cpk:flex cpk:items-center cpk:justify-between cpk:border-b cpk:border-border cpk:px-4 cpk:py-4", "cpk:bg-background/95 cpk:backdrop-blur cpk:supports-[backdrop-filter]:bg-background/80", className),
|
|
29
|
+
className: require_utils.cn("copilotKitHeader", "cpk:flex cpk:items-center cpk:justify-between cpk:border-b cpk:border-border cpk:px-4 cpk:py-4", "cpk:bg-background/95 cpk:backdrop-blur cpk:supports-[backdrop-filter]:bg-background/80", className),
|
|
30
30
|
...rest,
|
|
31
31
|
children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
32
32
|
className: "cpk:flex cpk:w-full cpk:items-center cpk:gap-2",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CopilotModalHeader.cjs","names":["useCopilotChatConfiguration","CopilotChatDefaultLabels","renderSlot","cn","X"],"sources":["../../../src/components/chat/CopilotModalHeader.tsx"],"sourcesContent":["import React, { useCallback } from \"react\";\n\nimport { cn } from \"@/lib/utils\";\nimport {\n useCopilotChatConfiguration,\n CopilotChatDefaultLabels,\n} from \"@/providers/CopilotChatConfigurationProvider\";\nimport { renderSlot, WithSlots } from \"@/lib/slots\";\nimport { X } from \"lucide-react\";\n\ntype HeaderSlots = {\n titleContent: typeof CopilotModalHeader.Title;\n closeButton: typeof CopilotModalHeader.CloseButton;\n};\n\ntype HeaderRestProps = {\n title?: string;\n} & Omit<React.HTMLAttributes<HTMLDivElement>, \"children\">;\n\nexport type CopilotModalHeaderProps = WithSlots<HeaderSlots, HeaderRestProps>;\n\nexport function CopilotModalHeader({\n title,\n titleContent,\n closeButton,\n children,\n className,\n ...rest\n}: CopilotModalHeaderProps) {\n const configuration = useCopilotChatConfiguration();\n\n const fallbackTitle =\n configuration?.labels.modalHeaderTitle ??\n CopilotChatDefaultLabels.modalHeaderTitle;\n const resolvedTitle = title ?? fallbackTitle;\n\n const handleClose = useCallback(() => {\n configuration?.setModalOpen?.(false);\n }, [configuration]);\n\n const BoundTitle = renderSlot(titleContent, CopilotModalHeader.Title, {\n children: resolvedTitle,\n });\n\n const BoundCloseButton = renderSlot(\n closeButton,\n CopilotModalHeader.CloseButton,\n {\n onClick: handleClose,\n },\n );\n\n if (children) {\n return children({\n titleContent: BoundTitle,\n closeButton: BoundCloseButton,\n title: resolvedTitle,\n ...rest,\n });\n }\n\n return (\n <header\n data-testid=\"copilot-modal-header\"\n data-slot=\"copilot-modal-header\"\n className={cn(\n \"cpk:flex cpk:items-center cpk:justify-between cpk:border-b cpk:border-border cpk:px-4 cpk:py-4\",\n \"cpk:bg-background/95 cpk:backdrop-blur cpk:supports-[backdrop-filter]:bg-background/80\",\n className,\n )}\n {...rest}\n >\n <div className=\"cpk:flex cpk:w-full cpk:items-center cpk:gap-2\">\n <div className=\"cpk:flex-1\" aria-hidden=\"true\" />\n <div className=\"cpk:flex cpk:flex-1 cpk:justify-center cpk:text-center\">\n {BoundTitle}\n </div>\n <div className=\"cpk:flex cpk:flex-1 cpk:justify-end\">\n {BoundCloseButton}\n </div>\n </div>\n </header>\n );\n}\n\nCopilotModalHeader.displayName = \"CopilotModalHeader\";\n\nexport namespace CopilotModalHeader {\n export const Title: React.FC<React.HTMLAttributes<HTMLDivElement>> = ({\n children,\n className,\n ...props\n }) => (\n <div\n data-testid=\"copilot-header-title\"\n className={cn(\n \"cpk:w-full cpk:text-base cpk:font-medium cpk:leading-none cpk:tracking-tight cpk:text-foreground\",\n className,\n )}\n {...props}\n >\n {children}\n </div>\n );\n\n export const CloseButton: React.FC<\n React.ButtonHTMLAttributes<HTMLButtonElement>\n > = ({ className, ...props }) => (\n <button\n type=\"button\"\n data-testid=\"copilot-close-button\"\n className={cn(\n \"cpk:inline-flex cpk:size-8 cpk:items-center cpk:justify-center cpk:rounded-full cpk:text-muted-foreground cpk:transition cpk:cursor-pointer\",\n \"cpk:hover:bg-muted cpk:hover:text-foreground cpk:focus-visible:outline-none cpk:focus-visible:ring-2 cpk:focus-visible:ring-ring\",\n className,\n )}\n aria-label=\"Close\"\n {...props}\n >\n <X className=\"cpk:h-4 cpk:w-4\" aria-hidden=\"true\" />\n </button>\n );\n}\n\nCopilotModalHeader.Title.displayName = \"CopilotModalHeader.Title\";\nCopilotModalHeader.CloseButton.displayName = \"CopilotModalHeader.CloseButton\";\n\nexport default CopilotModalHeader;\n"],"mappings":";;;;;;;;;;AAqBA,SAAgB,mBAAmB,EACjC,OACA,cACA,aACA,UACA,WACA,GAAG,QACuB;CAC1B,MAAM,gBAAgBA,sEAA6B;CAEnD,MAAM,gBACJ,eAAe,OAAO,oBACtBC,kEAAyB;CAC3B,MAAM,gBAAgB,SAAS;CAE/B,MAAM,2CAAgC;AACpC,iBAAe,eAAe,MAAM;IACnC,CAAC,cAAc,CAAC;CAEnB,MAAM,aAAaC,yBAAW,cAAc,mBAAmB,OAAO,EACpE,UAAU,eACX,CAAC;CAEF,MAAM,mBAAmBA,yBACvB,aACA,mBAAmB,aACnB,EACE,SAAS,aACV,CACF;AAED,KAAI,SACF,QAAO,SAAS;EACd,cAAc;EACd,aAAa;EACb,OAAO;EACP,GAAG;EACJ,CAAC;AAGJ,QACE,2CAAC;EACC,eAAY;EACZ,aAAU;EACV,WAAWC,iBACT,kGACA,0FACA,UACD;EACD,GAAI;YAEJ,4CAAC;GAAI,WAAU;;IACb,2CAAC;KAAI,WAAU;KAAa,eAAY;MAAS;IACjD,2CAAC;KAAI,WAAU;eACZ;MACG;IACN,2CAAC;KAAI,WAAU;eACZ;MACG;;IACF;GACC;;AAIb,mBAAmB,cAAc;;8BAGuC,EACpE,UACA,WACA,GAAG,YAEH,2CAAC;EACC,eAAY;EACZ,WAAWA,iBACT,oGACA,UACD;EACD,GAAI;EAEH;GACG;oCAKH,EAAE,WAAW,GAAG,YACnB,2CAAC;EACC,MAAK;EACL,eAAY;EACZ,WAAWA,iBACT,+IACA,oIACA,UACD;EACD,cAAW;EACX,GAAI;YAEJ,2CAACC;GAAE,WAAU;GAAkB,eAAY;IAAS;GAC7C;;AAIb,mBAAmB,MAAM,cAAc;AACvC,mBAAmB,YAAY,cAAc"}
|
|
1
|
+
{"version":3,"file":"CopilotModalHeader.cjs","names":["useCopilotChatConfiguration","CopilotChatDefaultLabels","renderSlot","cn","X"],"sources":["../../../src/components/chat/CopilotModalHeader.tsx"],"sourcesContent":["import React, { useCallback } from \"react\";\n\nimport { cn } from \"@/lib/utils\";\nimport {\n useCopilotChatConfiguration,\n CopilotChatDefaultLabels,\n} from \"@/providers/CopilotChatConfigurationProvider\";\nimport { renderSlot, WithSlots } from \"@/lib/slots\";\nimport { X } from \"lucide-react\";\n\ntype HeaderSlots = {\n titleContent: typeof CopilotModalHeader.Title;\n closeButton: typeof CopilotModalHeader.CloseButton;\n};\n\ntype HeaderRestProps = {\n title?: string;\n} & Omit<React.HTMLAttributes<HTMLDivElement>, \"children\">;\n\nexport type CopilotModalHeaderProps = WithSlots<HeaderSlots, HeaderRestProps>;\n\nexport function CopilotModalHeader({\n title,\n titleContent,\n closeButton,\n children,\n className,\n ...rest\n}: CopilotModalHeaderProps) {\n const configuration = useCopilotChatConfiguration();\n\n const fallbackTitle =\n configuration?.labels.modalHeaderTitle ??\n CopilotChatDefaultLabels.modalHeaderTitle;\n const resolvedTitle = title ?? fallbackTitle;\n\n const handleClose = useCallback(() => {\n configuration?.setModalOpen?.(false);\n }, [configuration]);\n\n const BoundTitle = renderSlot(titleContent, CopilotModalHeader.Title, {\n children: resolvedTitle,\n });\n\n const BoundCloseButton = renderSlot(\n closeButton,\n CopilotModalHeader.CloseButton,\n {\n onClick: handleClose,\n },\n );\n\n if (children) {\n return children({\n titleContent: BoundTitle,\n closeButton: BoundCloseButton,\n title: resolvedTitle,\n ...rest,\n });\n }\n\n return (\n <header\n data-testid=\"copilot-modal-header\"\n data-slot=\"copilot-modal-header\"\n className={cn(\n \"copilotKitHeader\",\n \"cpk:flex cpk:items-center cpk:justify-between cpk:border-b cpk:border-border cpk:px-4 cpk:py-4\",\n \"cpk:bg-background/95 cpk:backdrop-blur cpk:supports-[backdrop-filter]:bg-background/80\",\n className,\n )}\n {...rest}\n >\n <div className=\"cpk:flex cpk:w-full cpk:items-center cpk:gap-2\">\n <div className=\"cpk:flex-1\" aria-hidden=\"true\" />\n <div className=\"cpk:flex cpk:flex-1 cpk:justify-center cpk:text-center\">\n {BoundTitle}\n </div>\n <div className=\"cpk:flex cpk:flex-1 cpk:justify-end\">\n {BoundCloseButton}\n </div>\n </div>\n </header>\n );\n}\n\nCopilotModalHeader.displayName = \"CopilotModalHeader\";\n\nexport namespace CopilotModalHeader {\n export const Title: React.FC<React.HTMLAttributes<HTMLDivElement>> = ({\n children,\n className,\n ...props\n }) => (\n <div\n data-testid=\"copilot-header-title\"\n className={cn(\n \"cpk:w-full cpk:text-base cpk:font-medium cpk:leading-none cpk:tracking-tight cpk:text-foreground\",\n className,\n )}\n {...props}\n >\n {children}\n </div>\n );\n\n export const CloseButton: React.FC<\n React.ButtonHTMLAttributes<HTMLButtonElement>\n > = ({ className, ...props }) => (\n <button\n type=\"button\"\n data-testid=\"copilot-close-button\"\n className={cn(\n \"cpk:inline-flex cpk:size-8 cpk:items-center cpk:justify-center cpk:rounded-full cpk:text-muted-foreground cpk:transition cpk:cursor-pointer\",\n \"cpk:hover:bg-muted cpk:hover:text-foreground cpk:focus-visible:outline-none cpk:focus-visible:ring-2 cpk:focus-visible:ring-ring\",\n className,\n )}\n aria-label=\"Close\"\n {...props}\n >\n <X className=\"cpk:h-4 cpk:w-4\" aria-hidden=\"true\" />\n </button>\n );\n}\n\nCopilotModalHeader.Title.displayName = \"CopilotModalHeader.Title\";\nCopilotModalHeader.CloseButton.displayName = \"CopilotModalHeader.CloseButton\";\n\nexport default CopilotModalHeader;\n"],"mappings":";;;;;;;;;;AAqBA,SAAgB,mBAAmB,EACjC,OACA,cACA,aACA,UACA,WACA,GAAG,QACuB;CAC1B,MAAM,gBAAgBA,sEAA6B;CAEnD,MAAM,gBACJ,eAAe,OAAO,oBACtBC,kEAAyB;CAC3B,MAAM,gBAAgB,SAAS;CAE/B,MAAM,2CAAgC;AACpC,iBAAe,eAAe,MAAM;IACnC,CAAC,cAAc,CAAC;CAEnB,MAAM,aAAaC,yBAAW,cAAc,mBAAmB,OAAO,EACpE,UAAU,eACX,CAAC;CAEF,MAAM,mBAAmBA,yBACvB,aACA,mBAAmB,aACnB,EACE,SAAS,aACV,CACF;AAED,KAAI,SACF,QAAO,SAAS;EACd,cAAc;EACd,aAAa;EACb,OAAO;EACP,GAAG;EACJ,CAAC;AAGJ,QACE,2CAAC;EACC,eAAY;EACZ,aAAU;EACV,WAAWC,iBACT,oBACA,kGACA,0FACA,UACD;EACD,GAAI;YAEJ,4CAAC;GAAI,WAAU;;IACb,2CAAC;KAAI,WAAU;KAAa,eAAY;MAAS;IACjD,2CAAC;KAAI,WAAU;eACZ;MACG;IACN,2CAAC;KAAI,WAAU;eACZ;MACG;;IACF;GACC;;AAIb,mBAAmB,cAAc;;8BAGuC,EACpE,UACA,WACA,GAAG,YAEH,2CAAC;EACC,eAAY;EACZ,WAAWA,iBACT,oGACA,UACD;EACD,GAAI;EAEH;GACG;oCAKH,EAAE,WAAW,GAAG,YACnB,2CAAC;EACC,MAAK;EACL,eAAY;EACZ,WAAWA,iBACT,+IACA,oIACA,UACD;EACD,cAAW;EACX,GAAI;YAEJ,2CAACC;GAAE,WAAU;GAAkB,eAAY;IAAS;GAC7C;;AAIb,mBAAmB,MAAM,cAAc;AACvC,mBAAmB,YAAY,cAAc"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CopilotModalHeader.d.cts","names":[],"sources":["../../../src/components/chat/CopilotModalHeader.tsx"],"mappings":";;;;;KAUK,WAAA;EACH,YAAA,SAAqB,kBAAA,CAAmB,KAAA;EACxC,WAAA,SAAoB,kBAAA,CAAmB,WAAA;AAAA;AAAA,KAGpC,eAAA;EACH,KAAA;AAAA,IACE,IAAA,CAAK,KAAA,CAAM,cAAA,CAAe,cAAA;AAAA,KAElB,uBAAA,GAA0B,SAAA,CAAU,WAAA,EAAa,eAAA;AAAA,iBAE7C,kBAAA,CAAA;EACd,KAAA;EACA,YAAA;EACA,WAAA;EACA,QAAA;EACA,SAAA;EAAA,GACG;AAAA,GACF,uBAAA,wCAAuB,kBAAA,CAAA,GAAA,CAAA,OAAA,GAAA,QAAA,CAAA,KAAA,CAAA,SAAA,IAAA,OAAA,sCAAA,KAAA,CAAA,WAAA,GAAA,KAAA,CAAA,YAAA,mBAAA,KAAA,CAAA,qBAAA,SAAA,QAAA,CAAA,KAAA,CAAA,SAAA;AAAA,kBAPV,kBAAA;EAAA,IAAkB,WAAA;AAAA;AAAA,
|
|
1
|
+
{"version":3,"file":"CopilotModalHeader.d.cts","names":[],"sources":["../../../src/components/chat/CopilotModalHeader.tsx"],"mappings":";;;;;KAUK,WAAA;EACH,YAAA,SAAqB,kBAAA,CAAmB,KAAA;EACxC,WAAA,SAAoB,kBAAA,CAAmB,WAAA;AAAA;AAAA,KAGpC,eAAA;EACH,KAAA;AAAA,IACE,IAAA,CAAK,KAAA,CAAM,cAAA,CAAe,cAAA;AAAA,KAElB,uBAAA,GAA0B,SAAA,CAAU,WAAA,EAAa,eAAA;AAAA,iBAE7C,kBAAA,CAAA;EACd,KAAA;EACA,YAAA;EACA,WAAA;EACA,QAAA;EACA,SAAA;EAAA,GACG;AAAA,GACF,uBAAA,wCAAuB,kBAAA,CAAA,GAAA,CAAA,OAAA,GAAA,QAAA,CAAA,KAAA,CAAA,SAAA,IAAA,OAAA,sCAAA,KAAA,CAAA,WAAA,GAAA,KAAA,CAAA,YAAA,mBAAA,KAAA,CAAA,qBAAA,SAAA,QAAA,CAAA,KAAA,CAAA,SAAA;AAAA,kBAPV,kBAAA;EAAA,IAAkB,WAAA;AAAA;AAAA,kBAmEjB,kBAAA;EAAA,MACF,KAAA,EAAO,KAAA,CAAM,EAAA,CAAG,KAAA,CAAM,cAAA,CAAe,cAAA;EAAA,MAiBrC,WAAA,EAAa,KAAA,CAAM,EAAA,CAC9B,KAAA,CAAM,oBAAA,CAAqB,iBAAA;AAAA"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CopilotModalHeader.d.mts","names":[],"sources":["../../../src/components/chat/CopilotModalHeader.tsx"],"mappings":";;;;;KAUK,WAAA;EACH,YAAA,SAAqB,kBAAA,CAAmB,KAAA;EACxC,WAAA,SAAoB,kBAAA,CAAmB,WAAA;AAAA;AAAA,KAGpC,eAAA;EACH,KAAA;AAAA,IACE,IAAA,CAAK,KAAA,CAAM,cAAA,CAAe,cAAA;AAAA,KAElB,uBAAA,GAA0B,SAAA,CAAU,WAAA,EAAa,eAAA;AAAA,iBAE7C,kBAAA,CAAA;EACd,KAAA;EACA,YAAA;EACA,WAAA;EACA,QAAA;EACA,SAAA;EAAA,GACG;AAAA,GACF,uBAAA,wCAAuB,kBAAA,CAAA,GAAA,CAAA,OAAA,GAAA,QAAA,CAAA,KAAA,CAAA,SAAA,IAAA,OAAA,sCAAA,KAAA,CAAA,WAAA,GAAA,KAAA,CAAA,YAAA,mBAAA,KAAA,CAAA,qBAAA,SAAA,QAAA,CAAA,KAAA,CAAA,SAAA;AAAA,kBAPV,kBAAA;EAAA,IAAkB,WAAA;AAAA;AAAA,
|
|
1
|
+
{"version":3,"file":"CopilotModalHeader.d.mts","names":[],"sources":["../../../src/components/chat/CopilotModalHeader.tsx"],"mappings":";;;;;KAUK,WAAA;EACH,YAAA,SAAqB,kBAAA,CAAmB,KAAA;EACxC,WAAA,SAAoB,kBAAA,CAAmB,WAAA;AAAA;AAAA,KAGpC,eAAA;EACH,KAAA;AAAA,IACE,IAAA,CAAK,KAAA,CAAM,cAAA,CAAe,cAAA;AAAA,KAElB,uBAAA,GAA0B,SAAA,CAAU,WAAA,EAAa,eAAA;AAAA,iBAE7C,kBAAA,CAAA;EACd,KAAA;EACA,YAAA;EACA,WAAA;EACA,QAAA;EACA,SAAA;EAAA,GACG;AAAA,GACF,uBAAA,wCAAuB,kBAAA,CAAA,GAAA,CAAA,OAAA,GAAA,QAAA,CAAA,KAAA,CAAA,SAAA,IAAA,OAAA,sCAAA,KAAA,CAAA,WAAA,GAAA,KAAA,CAAA,YAAA,mBAAA,KAAA,CAAA,qBAAA,SAAA,QAAA,CAAA,KAAA,CAAA,SAAA;AAAA,kBAPV,kBAAA;EAAA,IAAkB,WAAA;AAAA;AAAA,kBAmEjB,kBAAA;EAAA,MACF,KAAA,EAAO,KAAA,CAAM,EAAA,CAAG,KAAA,CAAM,cAAA,CAAe,cAAA;EAAA,MAiBrC,WAAA,EAAa,KAAA,CAAM,EAAA,CAC9B,KAAA,CAAM,oBAAA,CAAqB,iBAAA;AAAA"}
|
|
@@ -24,7 +24,7 @@ function CopilotModalHeader({ title, titleContent, closeButton, children, classN
|
|
|
24
24
|
return /* @__PURE__ */ jsx("header", {
|
|
25
25
|
"data-testid": "copilot-modal-header",
|
|
26
26
|
"data-slot": "copilot-modal-header",
|
|
27
|
-
className: cn("cpk:flex cpk:items-center cpk:justify-between cpk:border-b cpk:border-border cpk:px-4 cpk:py-4", "cpk:bg-background/95 cpk:backdrop-blur cpk:supports-[backdrop-filter]:bg-background/80", className),
|
|
27
|
+
className: cn("copilotKitHeader", "cpk:flex cpk:items-center cpk:justify-between cpk:border-b cpk:border-border cpk:px-4 cpk:py-4", "cpk:bg-background/95 cpk:backdrop-blur cpk:supports-[backdrop-filter]:bg-background/80", className),
|
|
28
28
|
...rest,
|
|
29
29
|
children: /* @__PURE__ */ jsxs("div", {
|
|
30
30
|
className: "cpk:flex cpk:w-full cpk:items-center cpk:gap-2",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CopilotModalHeader.mjs","names":[],"sources":["../../../src/components/chat/CopilotModalHeader.tsx"],"sourcesContent":["import React, { useCallback } from \"react\";\n\nimport { cn } from \"@/lib/utils\";\nimport {\n useCopilotChatConfiguration,\n CopilotChatDefaultLabels,\n} from \"@/providers/CopilotChatConfigurationProvider\";\nimport { renderSlot, WithSlots } from \"@/lib/slots\";\nimport { X } from \"lucide-react\";\n\ntype HeaderSlots = {\n titleContent: typeof CopilotModalHeader.Title;\n closeButton: typeof CopilotModalHeader.CloseButton;\n};\n\ntype HeaderRestProps = {\n title?: string;\n} & Omit<React.HTMLAttributes<HTMLDivElement>, \"children\">;\n\nexport type CopilotModalHeaderProps = WithSlots<HeaderSlots, HeaderRestProps>;\n\nexport function CopilotModalHeader({\n title,\n titleContent,\n closeButton,\n children,\n className,\n ...rest\n}: CopilotModalHeaderProps) {\n const configuration = useCopilotChatConfiguration();\n\n const fallbackTitle =\n configuration?.labels.modalHeaderTitle ??\n CopilotChatDefaultLabels.modalHeaderTitle;\n const resolvedTitle = title ?? fallbackTitle;\n\n const handleClose = useCallback(() => {\n configuration?.setModalOpen?.(false);\n }, [configuration]);\n\n const BoundTitle = renderSlot(titleContent, CopilotModalHeader.Title, {\n children: resolvedTitle,\n });\n\n const BoundCloseButton = renderSlot(\n closeButton,\n CopilotModalHeader.CloseButton,\n {\n onClick: handleClose,\n },\n );\n\n if (children) {\n return children({\n titleContent: BoundTitle,\n closeButton: BoundCloseButton,\n title: resolvedTitle,\n ...rest,\n });\n }\n\n return (\n <header\n data-testid=\"copilot-modal-header\"\n data-slot=\"copilot-modal-header\"\n className={cn(\n \"cpk:flex cpk:items-center cpk:justify-between cpk:border-b cpk:border-border cpk:px-4 cpk:py-4\",\n \"cpk:bg-background/95 cpk:backdrop-blur cpk:supports-[backdrop-filter]:bg-background/80\",\n className,\n )}\n {...rest}\n >\n <div className=\"cpk:flex cpk:w-full cpk:items-center cpk:gap-2\">\n <div className=\"cpk:flex-1\" aria-hidden=\"true\" />\n <div className=\"cpk:flex cpk:flex-1 cpk:justify-center cpk:text-center\">\n {BoundTitle}\n </div>\n <div className=\"cpk:flex cpk:flex-1 cpk:justify-end\">\n {BoundCloseButton}\n </div>\n </div>\n </header>\n );\n}\n\nCopilotModalHeader.displayName = \"CopilotModalHeader\";\n\nexport namespace CopilotModalHeader {\n export const Title: React.FC<React.HTMLAttributes<HTMLDivElement>> = ({\n children,\n className,\n ...props\n }) => (\n <div\n data-testid=\"copilot-header-title\"\n className={cn(\n \"cpk:w-full cpk:text-base cpk:font-medium cpk:leading-none cpk:tracking-tight cpk:text-foreground\",\n className,\n )}\n {...props}\n >\n {children}\n </div>\n );\n\n export const CloseButton: React.FC<\n React.ButtonHTMLAttributes<HTMLButtonElement>\n > = ({ className, ...props }) => (\n <button\n type=\"button\"\n data-testid=\"copilot-close-button\"\n className={cn(\n \"cpk:inline-flex cpk:size-8 cpk:items-center cpk:justify-center cpk:rounded-full cpk:text-muted-foreground cpk:transition cpk:cursor-pointer\",\n \"cpk:hover:bg-muted cpk:hover:text-foreground cpk:focus-visible:outline-none cpk:focus-visible:ring-2 cpk:focus-visible:ring-ring\",\n className,\n )}\n aria-label=\"Close\"\n {...props}\n >\n <X className=\"cpk:h-4 cpk:w-4\" aria-hidden=\"true\" />\n </button>\n );\n}\n\nCopilotModalHeader.Title.displayName = \"CopilotModalHeader.Title\";\nCopilotModalHeader.CloseButton.displayName = \"CopilotModalHeader.CloseButton\";\n\nexport default CopilotModalHeader;\n"],"mappings":";;;;;;;;AAqBA,SAAgB,mBAAmB,EACjC,OACA,cACA,aACA,UACA,WACA,GAAG,QACuB;CAC1B,MAAM,gBAAgB,6BAA6B;CAEnD,MAAM,gBACJ,eAAe,OAAO,oBACtB,yBAAyB;CAC3B,MAAM,gBAAgB,SAAS;CAE/B,MAAM,cAAc,kBAAkB;AACpC,iBAAe,eAAe,MAAM;IACnC,CAAC,cAAc,CAAC;CAEnB,MAAM,aAAa,WAAW,cAAc,mBAAmB,OAAO,EACpE,UAAU,eACX,CAAC;CAEF,MAAM,mBAAmB,WACvB,aACA,mBAAmB,aACnB,EACE,SAAS,aACV,CACF;AAED,KAAI,SACF,QAAO,SAAS;EACd,cAAc;EACd,aAAa;EACb,OAAO;EACP,GAAG;EACJ,CAAC;AAGJ,QACE,oBAAC;EACC,eAAY;EACZ,aAAU;EACV,WAAW,GACT,kGACA,0FACA,UACD;EACD,GAAI;YAEJ,qBAAC;GAAI,WAAU;;IACb,oBAAC;KAAI,WAAU;KAAa,eAAY;MAAS;IACjD,oBAAC;KAAI,WAAU;eACZ;MACG;IACN,oBAAC;KAAI,WAAU;eACZ;MACG;;IACF;GACC;;AAIb,mBAAmB,cAAc;;8BAGuC,EACpE,UACA,WACA,GAAG,YAEH,oBAAC;EACC,eAAY;EACZ,WAAW,GACT,oGACA,UACD;EACD,GAAI;EAEH;GACG;oCAKH,EAAE,WAAW,GAAG,YACnB,oBAAC;EACC,MAAK;EACL,eAAY;EACZ,WAAW,GACT,+IACA,oIACA,UACD;EACD,cAAW;EACX,GAAI;YAEJ,oBAAC;GAAE,WAAU;GAAkB,eAAY;IAAS;GAC7C;;AAIb,mBAAmB,MAAM,cAAc;AACvC,mBAAmB,YAAY,cAAc"}
|
|
1
|
+
{"version":3,"file":"CopilotModalHeader.mjs","names":[],"sources":["../../../src/components/chat/CopilotModalHeader.tsx"],"sourcesContent":["import React, { useCallback } from \"react\";\n\nimport { cn } from \"@/lib/utils\";\nimport {\n useCopilotChatConfiguration,\n CopilotChatDefaultLabels,\n} from \"@/providers/CopilotChatConfigurationProvider\";\nimport { renderSlot, WithSlots } from \"@/lib/slots\";\nimport { X } from \"lucide-react\";\n\ntype HeaderSlots = {\n titleContent: typeof CopilotModalHeader.Title;\n closeButton: typeof CopilotModalHeader.CloseButton;\n};\n\ntype HeaderRestProps = {\n title?: string;\n} & Omit<React.HTMLAttributes<HTMLDivElement>, \"children\">;\n\nexport type CopilotModalHeaderProps = WithSlots<HeaderSlots, HeaderRestProps>;\n\nexport function CopilotModalHeader({\n title,\n titleContent,\n closeButton,\n children,\n className,\n ...rest\n}: CopilotModalHeaderProps) {\n const configuration = useCopilotChatConfiguration();\n\n const fallbackTitle =\n configuration?.labels.modalHeaderTitle ??\n CopilotChatDefaultLabels.modalHeaderTitle;\n const resolvedTitle = title ?? fallbackTitle;\n\n const handleClose = useCallback(() => {\n configuration?.setModalOpen?.(false);\n }, [configuration]);\n\n const BoundTitle = renderSlot(titleContent, CopilotModalHeader.Title, {\n children: resolvedTitle,\n });\n\n const BoundCloseButton = renderSlot(\n closeButton,\n CopilotModalHeader.CloseButton,\n {\n onClick: handleClose,\n },\n );\n\n if (children) {\n return children({\n titleContent: BoundTitle,\n closeButton: BoundCloseButton,\n title: resolvedTitle,\n ...rest,\n });\n }\n\n return (\n <header\n data-testid=\"copilot-modal-header\"\n data-slot=\"copilot-modal-header\"\n className={cn(\n \"copilotKitHeader\",\n \"cpk:flex cpk:items-center cpk:justify-between cpk:border-b cpk:border-border cpk:px-4 cpk:py-4\",\n \"cpk:bg-background/95 cpk:backdrop-blur cpk:supports-[backdrop-filter]:bg-background/80\",\n className,\n )}\n {...rest}\n >\n <div className=\"cpk:flex cpk:w-full cpk:items-center cpk:gap-2\">\n <div className=\"cpk:flex-1\" aria-hidden=\"true\" />\n <div className=\"cpk:flex cpk:flex-1 cpk:justify-center cpk:text-center\">\n {BoundTitle}\n </div>\n <div className=\"cpk:flex cpk:flex-1 cpk:justify-end\">\n {BoundCloseButton}\n </div>\n </div>\n </header>\n );\n}\n\nCopilotModalHeader.displayName = \"CopilotModalHeader\";\n\nexport namespace CopilotModalHeader {\n export const Title: React.FC<React.HTMLAttributes<HTMLDivElement>> = ({\n children,\n className,\n ...props\n }) => (\n <div\n data-testid=\"copilot-header-title\"\n className={cn(\n \"cpk:w-full cpk:text-base cpk:font-medium cpk:leading-none cpk:tracking-tight cpk:text-foreground\",\n className,\n )}\n {...props}\n >\n {children}\n </div>\n );\n\n export const CloseButton: React.FC<\n React.ButtonHTMLAttributes<HTMLButtonElement>\n > = ({ className, ...props }) => (\n <button\n type=\"button\"\n data-testid=\"copilot-close-button\"\n className={cn(\n \"cpk:inline-flex cpk:size-8 cpk:items-center cpk:justify-center cpk:rounded-full cpk:text-muted-foreground cpk:transition cpk:cursor-pointer\",\n \"cpk:hover:bg-muted cpk:hover:text-foreground cpk:focus-visible:outline-none cpk:focus-visible:ring-2 cpk:focus-visible:ring-ring\",\n className,\n )}\n aria-label=\"Close\"\n {...props}\n >\n <X className=\"cpk:h-4 cpk:w-4\" aria-hidden=\"true\" />\n </button>\n );\n}\n\nCopilotModalHeader.Title.displayName = \"CopilotModalHeader.Title\";\nCopilotModalHeader.CloseButton.displayName = \"CopilotModalHeader.CloseButton\";\n\nexport default CopilotModalHeader;\n"],"mappings":";;;;;;;;AAqBA,SAAgB,mBAAmB,EACjC,OACA,cACA,aACA,UACA,WACA,GAAG,QACuB;CAC1B,MAAM,gBAAgB,6BAA6B;CAEnD,MAAM,gBACJ,eAAe,OAAO,oBACtB,yBAAyB;CAC3B,MAAM,gBAAgB,SAAS;CAE/B,MAAM,cAAc,kBAAkB;AACpC,iBAAe,eAAe,MAAM;IACnC,CAAC,cAAc,CAAC;CAEnB,MAAM,aAAa,WAAW,cAAc,mBAAmB,OAAO,EACpE,UAAU,eACX,CAAC;CAEF,MAAM,mBAAmB,WACvB,aACA,mBAAmB,aACnB,EACE,SAAS,aACV,CACF;AAED,KAAI,SACF,QAAO,SAAS;EACd,cAAc;EACd,aAAa;EACb,OAAO;EACP,GAAG;EACJ,CAAC;AAGJ,QACE,oBAAC;EACC,eAAY;EACZ,aAAU;EACV,WAAW,GACT,oBACA,kGACA,0FACA,UACD;EACD,GAAI;YAEJ,qBAAC;GAAI,WAAU;;IACb,oBAAC;KAAI,WAAU;KAAa,eAAY;MAAS;IACjD,oBAAC;KAAI,WAAU;eACZ;MACG;IACN,oBAAC;KAAI,WAAU;eACZ;MACG;;IACF;GACC;;AAIb,mBAAmB,cAAc;;8BAGuC,EACpE,UACA,WACA,GAAG,YAEH,oBAAC;EACC,eAAY;EACZ,WAAW,GACT,oGACA,UACD;EACD,GAAI;EAEH;GACG;oCAKH,EAAE,WAAW,GAAG,YACnB,oBAAC;EACC,MAAK;EACL,eAAY;EACZ,WAAW,GACT,+IACA,oIACA,UACD;EACD,cAAW;EACX,GAAI;YAEJ,oBAAC;GAAE,WAAU;GAAkB,eAAY;IAAS;GAC7C;;AAIb,mBAAmB,MAAM,cAAc;AACvC,mBAAmB,YAAY,cAAc"}
|
|
@@ -116,7 +116,7 @@ function CopilotPopupViewInternal({ header, toggleButton, width, height, clickOu
|
|
|
116
116
|
"aria-label": labels.modalHeaderTitle,
|
|
117
117
|
"data-testid": "copilot-popup",
|
|
118
118
|
"data-copilot-popup": true,
|
|
119
|
-
className: require_utils.cn("cpk:relative cpk:flex cpk:h-full cpk:w-full cpk:flex-col cpk:overflow-hidden cpk:bg-background cpk:text-foreground", "cpk:origin-bottom cpk:focus:outline-none cpk:transform-gpu cpk:transition-transform cpk:transition-opacity cpk:duration-200 cpk:ease-out", "cpk:md:transition-transform cpk:md:transition-opacity", "cpk:rounded-none cpk:border cpk:border-border/0 cpk:shadow-none cpk:ring-0", "cpk:md:h-[var(--copilot-popup-height)] cpk:md:w-[var(--copilot-popup-width)]", "cpk:md:max-h-[var(--copilot-popup-max-height)] cpk:md:max-w-[var(--copilot-popup-max-width)]", "cpk:md:origin-bottom-right cpk:md:rounded-2xl cpk:md:border-border cpk:md:shadow-xl cpk:md:ring-1 cpk:md:ring-border/40", popupAnimationClass),
|
|
119
|
+
className: require_utils.cn("copilotKitPopup copilotKitWindow", "cpk:relative cpk:flex cpk:h-full cpk:w-full cpk:flex-col cpk:overflow-hidden cpk:bg-background cpk:text-foreground", "cpk:origin-bottom cpk:focus:outline-none cpk:transform-gpu cpk:transition-transform cpk:transition-opacity cpk:duration-200 cpk:ease-out", "cpk:md:transition-transform cpk:md:transition-opacity", "cpk:rounded-none cpk:border cpk:border-border/0 cpk:shadow-none cpk:ring-0", "cpk:md:h-[var(--copilot-popup-height)] cpk:md:w-[var(--copilot-popup-width)]", "cpk:md:max-h-[var(--copilot-popup-max-height)] cpk:md:max-w-[var(--copilot-popup-max-width)]", "cpk:md:origin-bottom-right cpk:md:rounded-2xl cpk:md:border-border cpk:md:shadow-xl cpk:md:ring-1 cpk:md:ring-border/40", popupAnimationClass),
|
|
120
120
|
style: popupStyle,
|
|
121
121
|
children: [headerElement, /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
122
122
|
className: "cpk:flex-1 cpk:overflow-hidden",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CopilotPopupView.cjs","names":["CopilotChatConfigurationProvider","useCopilotChatConfiguration","CopilotChatDefaultLabels","renderSlot","CopilotModalHeader","CopilotChatToggleButton","cn","CopilotChatView"],"sources":["../../../src/components/chat/CopilotPopupView.tsx"],"sourcesContent":["import React, { useEffect, useMemo, useRef, useState } from \"react\";\nimport CopilotChatView, {\n CopilotChatViewProps,\n WelcomeScreenProps,\n} from \"./CopilotChatView\";\nimport CopilotChatToggleButton from \"./CopilotChatToggleButton\";\nimport { CopilotModalHeader } from \"./CopilotModalHeader\";\nimport { cn } from \"@/lib/utils\";\nimport { renderSlot, SlotValue } from \"@/lib/slots\";\nimport {\n CopilotChatConfigurationProvider,\n CopilotChatDefaultLabels,\n useCopilotChatConfiguration,\n} from \"@/providers/CopilotChatConfigurationProvider\";\n\nconst DEFAULT_POPUP_WIDTH = 420;\nconst DEFAULT_POPUP_HEIGHT = 560;\n\nexport type CopilotPopupViewProps = CopilotChatViewProps & {\n header?: SlotValue<typeof CopilotModalHeader>;\n toggleButton?: SlotValue<typeof CopilotChatToggleButton>;\n width?: number | string;\n height?: number | string;\n clickOutsideToClose?: boolean;\n defaultOpen?: boolean;\n};\n\nconst dimensionToCss = (\n value: number | string | undefined,\n fallback: number,\n): string => {\n if (typeof value === \"number\" && Number.isFinite(value)) {\n return `${value}px`;\n }\n\n if (typeof value === \"string\" && value.trim().length > 0) {\n return value;\n }\n\n return `${fallback}px`;\n};\n\nexport function CopilotPopupView({\n header,\n toggleButton,\n width,\n height,\n clickOutsideToClose,\n defaultOpen = true,\n className,\n ...restProps\n}: CopilotPopupViewProps) {\n return (\n <CopilotChatConfigurationProvider isModalDefaultOpen={defaultOpen}>\n <CopilotPopupViewInternal\n header={header}\n toggleButton={toggleButton}\n width={width}\n height={height}\n clickOutsideToClose={clickOutsideToClose}\n className={className}\n {...restProps}\n />\n </CopilotChatConfigurationProvider>\n );\n}\n\nfunction CopilotPopupViewInternal({\n header,\n toggleButton,\n width,\n height,\n clickOutsideToClose,\n className,\n ...restProps\n}: Omit<CopilotPopupViewProps, \"defaultOpen\">) {\n const configuration = useCopilotChatConfiguration();\n const isPopupOpen = configuration?.isModalOpen ?? false;\n const setModalOpen = configuration?.setModalOpen;\n const labels = configuration?.labels ?? CopilotChatDefaultLabels;\n\n const containerRef = useRef<HTMLDivElement>(null);\n const [isRendered, setIsRendered] = useState(isPopupOpen);\n const [isAnimatingOut, setIsAnimatingOut] = useState(false);\n\n useEffect(() => {\n if (isPopupOpen) {\n setIsRendered(true);\n setIsAnimatingOut(false);\n return;\n }\n\n if (!isRendered) {\n return;\n }\n\n setIsAnimatingOut(true);\n const timeout = setTimeout(() => {\n setIsRendered(false);\n setIsAnimatingOut(false);\n }, 200);\n\n return () => clearTimeout(timeout);\n }, [isPopupOpen, isRendered]);\n\n useEffect(() => {\n if (!isPopupOpen) {\n return;\n }\n\n if (typeof window === \"undefined\") {\n return;\n }\n\n const handleKeyDown = (event: KeyboardEvent) => {\n if (event.key === \"Escape\") {\n event.preventDefault();\n setModalOpen?.(false);\n }\n };\n\n window.addEventListener(\"keydown\", handleKeyDown);\n return () => window.removeEventListener(\"keydown\", handleKeyDown);\n }, [isPopupOpen, setModalOpen]);\n\n useEffect(() => {\n if (!isPopupOpen) {\n return;\n }\n\n const focusTimer = setTimeout(() => {\n const container = containerRef.current;\n // Don't steal focus if something inside the popup (like the input) is already focused\n if (container && !container.contains(document.activeElement)) {\n container.focus({ preventScroll: true });\n }\n }, 200);\n\n return () => clearTimeout(focusTimer);\n }, [isPopupOpen]);\n\n useEffect(() => {\n if (!isPopupOpen || !clickOutsideToClose) {\n return;\n }\n\n if (typeof document === \"undefined\") {\n return;\n }\n\n const handlePointerDown = (event: PointerEvent) => {\n const target = event.target as Node | null;\n if (!target) {\n return;\n }\n\n const container = containerRef.current;\n if (container?.contains(target)) {\n return;\n }\n\n const toggleButton = document.querySelector(\n \"[data-slot='chat-toggle-button']\",\n );\n if (toggleButton && toggleButton.contains(target)) {\n return;\n }\n\n setModalOpen?.(false);\n };\n\n document.addEventListener(\"pointerdown\", handlePointerDown);\n return () => document.removeEventListener(\"pointerdown\", handlePointerDown);\n }, [isPopupOpen, clickOutsideToClose, setModalOpen]);\n\n const headerElement = useMemo(\n () => renderSlot(header, CopilotModalHeader, {}),\n [header],\n );\n const toggleButtonElement = useMemo(\n () => renderSlot(toggleButton, CopilotChatToggleButton, {}),\n [toggleButton],\n );\n\n const resolvedWidth = dimensionToCss(width, DEFAULT_POPUP_WIDTH);\n const resolvedHeight = dimensionToCss(height, DEFAULT_POPUP_HEIGHT);\n\n const popupStyle = useMemo(\n () =>\n ({\n \"--copilot-popup-width\": resolvedWidth,\n \"--copilot-popup-height\": resolvedHeight,\n \"--copilot-popup-max-width\": \"calc(100vw - 3rem)\",\n \"--copilot-popup-max-height\": \"calc(100dvh - 7.5rem)\",\n paddingTop: \"env(safe-area-inset-top)\",\n paddingBottom: \"env(safe-area-inset-bottom)\",\n paddingLeft: \"env(safe-area-inset-left)\",\n paddingRight: \"env(safe-area-inset-right)\",\n }) as React.CSSProperties,\n [resolvedHeight, resolvedWidth],\n );\n\n const popupAnimationClass =\n isPopupOpen && !isAnimatingOut\n ? \"cpk:pointer-events-auto cpk:translate-y-0 cpk:opacity-100 cpk:md:scale-100\"\n : \"cpk:pointer-events-none cpk:translate-y-4 cpk:opacity-0 cpk:md:translate-y-5 cpk:md:scale-[0.95]\";\n\n const popupContent = isRendered ? (\n <div\n data-copilotkit\n className={cn(\n \"cpk:fixed cpk:inset-0 cpk:z-[1200] cpk:flex cpk:max-w-full cpk:flex-col cpk:items-stretch\",\n \"cpk:md:inset-auto cpk:md:bottom-24 cpk:md:right-6 cpk:md:items-end cpk:md:gap-4\",\n )}\n >\n <div\n ref={containerRef}\n tabIndex={-1}\n role=\"dialog\"\n aria-label={labels.modalHeaderTitle}\n data-testid=\"copilot-popup\"\n data-copilot-popup\n className={cn(\n \"cpk:relative cpk:flex cpk:h-full cpk:w-full cpk:flex-col cpk:overflow-hidden cpk:bg-background cpk:text-foreground\",\n \"cpk:origin-bottom cpk:focus:outline-none cpk:transform-gpu cpk:transition-transform cpk:transition-opacity cpk:duration-200 cpk:ease-out\",\n \"cpk:md:transition-transform cpk:md:transition-opacity\",\n \"cpk:rounded-none cpk:border cpk:border-border/0 cpk:shadow-none cpk:ring-0\",\n \"cpk:md:h-[var(--copilot-popup-height)] cpk:md:w-[var(--copilot-popup-width)]\",\n \"cpk:md:max-h-[var(--copilot-popup-max-height)] cpk:md:max-w-[var(--copilot-popup-max-width)]\",\n \"cpk:md:origin-bottom-right cpk:md:rounded-2xl cpk:md:border-border cpk:md:shadow-xl cpk:md:ring-1 cpk:md:ring-border/40\",\n popupAnimationClass,\n )}\n style={popupStyle}\n >\n {headerElement}\n <div className=\"cpk:flex-1 cpk:overflow-hidden\" data-popup-chat>\n <CopilotChatView\n {...restProps}\n className={cn(\"cpk:h-full cpk:min-h-0\", className)}\n />\n </div>\n </div>\n </div>\n ) : null;\n\n return (\n <>\n {toggleButtonElement}\n {popupContent}\n </>\n );\n}\n\nCopilotPopupView.displayName = \"CopilotPopupView\";\n\n// eslint-disable-next-line @typescript-eslint/no-namespace\nexport namespace CopilotPopupView {\n /**\n * Popup-specific welcome screen layout:\n * - Welcome message centered vertically\n * - Suggestions just above input\n * - Input fixed at the bottom\n */\n export const WelcomeScreen: React.FC<WelcomeScreenProps> = ({\n welcomeMessage,\n input,\n suggestionView,\n className,\n children,\n ...props\n }) => {\n // Render the welcomeMessage slot internally\n const BoundWelcomeMessage = renderSlot(\n welcomeMessage,\n CopilotChatView.WelcomeMessage,\n {},\n );\n\n if (children) {\n return (\n <div data-copilotkit style={{ display: \"contents\" }}>\n {children({\n welcomeMessage: BoundWelcomeMessage,\n input,\n suggestionView,\n className,\n ...props,\n })}\n </div>\n );\n }\n\n return (\n <div\n className={cn(\"cpk:h-full cpk:flex cpk:flex-col\", className)}\n {...props}\n >\n {/* Welcome message - centered vertically */}\n <div className=\"cpk:flex-1 cpk:flex cpk:flex-col cpk:items-center cpk:justify-center cpk:px-4\">\n {BoundWelcomeMessage}\n </div>\n\n {/* Suggestions and input at bottom */}\n <div>\n {/* Suggestions above input */}\n <div className=\"cpk:mb-4 cpk:flex cpk:justify-center cpk:px-4\">\n {suggestionView}\n </div>\n {input}\n </div>\n </div>\n );\n };\n}\n\nexport default CopilotPopupView;\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"CopilotPopupView.cjs","names":["CopilotChatConfigurationProvider","useCopilotChatConfiguration","CopilotChatDefaultLabels","renderSlot","CopilotModalHeader","CopilotChatToggleButton","cn","CopilotChatView"],"sources":["../../../src/components/chat/CopilotPopupView.tsx"],"sourcesContent":["import React, { useEffect, useMemo, useRef, useState } from \"react\";\nimport CopilotChatView, {\n CopilotChatViewProps,\n WelcomeScreenProps,\n} from \"./CopilotChatView\";\nimport CopilotChatToggleButton from \"./CopilotChatToggleButton\";\nimport { CopilotModalHeader } from \"./CopilotModalHeader\";\nimport { cn } from \"@/lib/utils\";\nimport { renderSlot, SlotValue } from \"@/lib/slots\";\nimport {\n CopilotChatConfigurationProvider,\n CopilotChatDefaultLabels,\n useCopilotChatConfiguration,\n} from \"@/providers/CopilotChatConfigurationProvider\";\n\nconst DEFAULT_POPUP_WIDTH = 420;\nconst DEFAULT_POPUP_HEIGHT = 560;\n\nexport type CopilotPopupViewProps = CopilotChatViewProps & {\n header?: SlotValue<typeof CopilotModalHeader>;\n toggleButton?: SlotValue<typeof CopilotChatToggleButton>;\n width?: number | string;\n height?: number | string;\n clickOutsideToClose?: boolean;\n defaultOpen?: boolean;\n};\n\nconst dimensionToCss = (\n value: number | string | undefined,\n fallback: number,\n): string => {\n if (typeof value === \"number\" && Number.isFinite(value)) {\n return `${value}px`;\n }\n\n if (typeof value === \"string\" && value.trim().length > 0) {\n return value;\n }\n\n return `${fallback}px`;\n};\n\nexport function CopilotPopupView({\n header,\n toggleButton,\n width,\n height,\n clickOutsideToClose,\n defaultOpen = true,\n className,\n ...restProps\n}: CopilotPopupViewProps) {\n return (\n <CopilotChatConfigurationProvider isModalDefaultOpen={defaultOpen}>\n <CopilotPopupViewInternal\n header={header}\n toggleButton={toggleButton}\n width={width}\n height={height}\n clickOutsideToClose={clickOutsideToClose}\n className={className}\n {...restProps}\n />\n </CopilotChatConfigurationProvider>\n );\n}\n\nfunction CopilotPopupViewInternal({\n header,\n toggleButton,\n width,\n height,\n clickOutsideToClose,\n className,\n ...restProps\n}: Omit<CopilotPopupViewProps, \"defaultOpen\">) {\n const configuration = useCopilotChatConfiguration();\n const isPopupOpen = configuration?.isModalOpen ?? false;\n const setModalOpen = configuration?.setModalOpen;\n const labels = configuration?.labels ?? CopilotChatDefaultLabels;\n\n const containerRef = useRef<HTMLDivElement>(null);\n const [isRendered, setIsRendered] = useState(isPopupOpen);\n const [isAnimatingOut, setIsAnimatingOut] = useState(false);\n\n useEffect(() => {\n if (isPopupOpen) {\n setIsRendered(true);\n setIsAnimatingOut(false);\n return;\n }\n\n if (!isRendered) {\n return;\n }\n\n setIsAnimatingOut(true);\n const timeout = setTimeout(() => {\n setIsRendered(false);\n setIsAnimatingOut(false);\n }, 200);\n\n return () => clearTimeout(timeout);\n }, [isPopupOpen, isRendered]);\n\n useEffect(() => {\n if (!isPopupOpen) {\n return;\n }\n\n if (typeof window === \"undefined\") {\n return;\n }\n\n const handleKeyDown = (event: KeyboardEvent) => {\n if (event.key === \"Escape\") {\n event.preventDefault();\n setModalOpen?.(false);\n }\n };\n\n window.addEventListener(\"keydown\", handleKeyDown);\n return () => window.removeEventListener(\"keydown\", handleKeyDown);\n }, [isPopupOpen, setModalOpen]);\n\n useEffect(() => {\n if (!isPopupOpen) {\n return;\n }\n\n const focusTimer = setTimeout(() => {\n const container = containerRef.current;\n // Don't steal focus if something inside the popup (like the input) is already focused\n if (container && !container.contains(document.activeElement)) {\n container.focus({ preventScroll: true });\n }\n }, 200);\n\n return () => clearTimeout(focusTimer);\n }, [isPopupOpen]);\n\n useEffect(() => {\n if (!isPopupOpen || !clickOutsideToClose) {\n return;\n }\n\n if (typeof document === \"undefined\") {\n return;\n }\n\n const handlePointerDown = (event: PointerEvent) => {\n const target = event.target as Node | null;\n if (!target) {\n return;\n }\n\n const container = containerRef.current;\n if (container?.contains(target)) {\n return;\n }\n\n const toggleButton = document.querySelector(\n \"[data-slot='chat-toggle-button']\",\n );\n if (toggleButton && toggleButton.contains(target)) {\n return;\n }\n\n setModalOpen?.(false);\n };\n\n document.addEventListener(\"pointerdown\", handlePointerDown);\n return () => document.removeEventListener(\"pointerdown\", handlePointerDown);\n }, [isPopupOpen, clickOutsideToClose, setModalOpen]);\n\n const headerElement = useMemo(\n () => renderSlot(header, CopilotModalHeader, {}),\n [header],\n );\n const toggleButtonElement = useMemo(\n () => renderSlot(toggleButton, CopilotChatToggleButton, {}),\n [toggleButton],\n );\n\n const resolvedWidth = dimensionToCss(width, DEFAULT_POPUP_WIDTH);\n const resolvedHeight = dimensionToCss(height, DEFAULT_POPUP_HEIGHT);\n\n const popupStyle = useMemo(\n () =>\n ({\n \"--copilot-popup-width\": resolvedWidth,\n \"--copilot-popup-height\": resolvedHeight,\n \"--copilot-popup-max-width\": \"calc(100vw - 3rem)\",\n \"--copilot-popup-max-height\": \"calc(100dvh - 7.5rem)\",\n paddingTop: \"env(safe-area-inset-top)\",\n paddingBottom: \"env(safe-area-inset-bottom)\",\n paddingLeft: \"env(safe-area-inset-left)\",\n paddingRight: \"env(safe-area-inset-right)\",\n }) as React.CSSProperties,\n [resolvedHeight, resolvedWidth],\n );\n\n const popupAnimationClass =\n isPopupOpen && !isAnimatingOut\n ? \"cpk:pointer-events-auto cpk:translate-y-0 cpk:opacity-100 cpk:md:scale-100\"\n : \"cpk:pointer-events-none cpk:translate-y-4 cpk:opacity-0 cpk:md:translate-y-5 cpk:md:scale-[0.95]\";\n\n const popupContent = isRendered ? (\n <div\n data-copilotkit\n className={cn(\n \"cpk:fixed cpk:inset-0 cpk:z-[1200] cpk:flex cpk:max-w-full cpk:flex-col cpk:items-stretch\",\n \"cpk:md:inset-auto cpk:md:bottom-24 cpk:md:right-6 cpk:md:items-end cpk:md:gap-4\",\n )}\n >\n <div\n ref={containerRef}\n tabIndex={-1}\n role=\"dialog\"\n aria-label={labels.modalHeaderTitle}\n data-testid=\"copilot-popup\"\n data-copilot-popup\n className={cn(\n \"copilotKitPopup copilotKitWindow\",\n \"cpk:relative cpk:flex cpk:h-full cpk:w-full cpk:flex-col cpk:overflow-hidden cpk:bg-background cpk:text-foreground\",\n \"cpk:origin-bottom cpk:focus:outline-none cpk:transform-gpu cpk:transition-transform cpk:transition-opacity cpk:duration-200 cpk:ease-out\",\n \"cpk:md:transition-transform cpk:md:transition-opacity\",\n \"cpk:rounded-none cpk:border cpk:border-border/0 cpk:shadow-none cpk:ring-0\",\n \"cpk:md:h-[var(--copilot-popup-height)] cpk:md:w-[var(--copilot-popup-width)]\",\n \"cpk:md:max-h-[var(--copilot-popup-max-height)] cpk:md:max-w-[var(--copilot-popup-max-width)]\",\n \"cpk:md:origin-bottom-right cpk:md:rounded-2xl cpk:md:border-border cpk:md:shadow-xl cpk:md:ring-1 cpk:md:ring-border/40\",\n popupAnimationClass,\n )}\n style={popupStyle}\n >\n {headerElement}\n <div className=\"cpk:flex-1 cpk:overflow-hidden\" data-popup-chat>\n <CopilotChatView\n {...restProps}\n className={cn(\"cpk:h-full cpk:min-h-0\", className)}\n />\n </div>\n </div>\n </div>\n ) : null;\n\n return (\n <>\n {toggleButtonElement}\n {popupContent}\n </>\n );\n}\n\nCopilotPopupView.displayName = \"CopilotPopupView\";\n\n// eslint-disable-next-line @typescript-eslint/no-namespace\nexport namespace CopilotPopupView {\n /**\n * Popup-specific welcome screen layout:\n * - Welcome message centered vertically\n * - Suggestions just above input\n * - Input fixed at the bottom\n */\n export const WelcomeScreen: React.FC<WelcomeScreenProps> = ({\n welcomeMessage,\n input,\n suggestionView,\n className,\n children,\n ...props\n }) => {\n // Render the welcomeMessage slot internally\n const BoundWelcomeMessage = renderSlot(\n welcomeMessage,\n CopilotChatView.WelcomeMessage,\n {},\n );\n\n if (children) {\n return (\n <div data-copilotkit style={{ display: \"contents\" }}>\n {children({\n welcomeMessage: BoundWelcomeMessage,\n input,\n suggestionView,\n className,\n ...props,\n })}\n </div>\n );\n }\n\n return (\n <div\n className={cn(\"cpk:h-full cpk:flex cpk:flex-col\", className)}\n {...props}\n >\n {/* Welcome message - centered vertically */}\n <div className=\"cpk:flex-1 cpk:flex cpk:flex-col cpk:items-center cpk:justify-center cpk:px-4\">\n {BoundWelcomeMessage}\n </div>\n\n {/* Suggestions and input at bottom */}\n <div>\n {/* Suggestions above input */}\n <div className=\"cpk:mb-4 cpk:flex cpk:justify-center cpk:px-4\">\n {suggestionView}\n </div>\n {input}\n </div>\n </div>\n );\n };\n}\n\nexport default CopilotPopupView;\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CopilotPopupView.d.cts","names":[],"sources":["../../../src/components/chat/CopilotPopupView.tsx"],"mappings":";;;;;;;;KAkBY,qBAAA,GAAwB,oBAAA;EAClC,MAAA,GAAS,SAAA,QAAiB,kBAAA;EAC1B,YAAA,GAAe,SAAA,QAAiB,uBAAA;EAChC,KAAA;EACA,MAAA;EACA,mBAAA;EACA,WAAA;AAAA;AAAA,iBAkBc,gBAAA,CAAA;EACd,MAAA;EACA,YAAA;EACA,KAAA;EACA,MAAA;EACA,mBAAA;EACA,WAAA;EACA,SAAA;EAAA,GACG;AAAA,GACF,qBAAA,GAAqB,kBAAA,CAAA,GAAA,CAAA,OAAA;AAAA,kBATR,gBAAA;EAAA,IAAgB,WAAA;AAAA;AAAA,
|
|
1
|
+
{"version":3,"file":"CopilotPopupView.d.cts","names":[],"sources":["../../../src/components/chat/CopilotPopupView.tsx"],"mappings":";;;;;;;;KAkBY,qBAAA,GAAwB,oBAAA;EAClC,MAAA,GAAS,SAAA,QAAiB,kBAAA;EAC1B,YAAA,GAAe,SAAA,QAAiB,uBAAA;EAChC,KAAA;EACA,MAAA;EACA,mBAAA;EACA,WAAA;AAAA;AAAA,iBAkBc,gBAAA,CAAA;EACd,MAAA;EACA,YAAA;EACA,KAAA;EACA,MAAA;EACA,mBAAA;EACA,WAAA;EACA,SAAA;EAAA,GACG;AAAA,GACF,qBAAA,GAAqB,kBAAA,CAAA,GAAA,CAAA,OAAA;AAAA,kBATR,gBAAA;EAAA,IAAgB,WAAA;AAAA;AAAA,kBAuNf,gBAAA;EA/OmB;;;;;;EAAA,MAsPrB,aAAA,EAAe,KAAA,CAAM,EAAA,CAAG,kBAAA;AAAA"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CopilotPopupView.d.mts","names":[],"sources":["../../../src/components/chat/CopilotPopupView.tsx"],"mappings":";;;;;;;;KAkBY,qBAAA,GAAwB,oBAAA;EAClC,MAAA,GAAS,SAAA,QAAiB,kBAAA;EAC1B,YAAA,GAAe,SAAA,QAAiB,uBAAA;EAChC,KAAA;EACA,MAAA;EACA,mBAAA;EACA,WAAA;AAAA;AAAA,iBAkBc,gBAAA,CAAA;EACd,MAAA;EACA,YAAA;EACA,KAAA;EACA,MAAA;EACA,mBAAA;EACA,WAAA;EACA,SAAA;EAAA,GACG;AAAA,GACF,qBAAA,GAAqB,kBAAA,CAAA,GAAA,CAAA,OAAA;AAAA,kBATR,gBAAA;EAAA,IAAgB,WAAA;AAAA;AAAA,
|
|
1
|
+
{"version":3,"file":"CopilotPopupView.d.mts","names":[],"sources":["../../../src/components/chat/CopilotPopupView.tsx"],"mappings":";;;;;;;;KAkBY,qBAAA,GAAwB,oBAAA;EAClC,MAAA,GAAS,SAAA,QAAiB,kBAAA;EAC1B,YAAA,GAAe,SAAA,QAAiB,uBAAA;EAChC,KAAA;EACA,MAAA;EACA,mBAAA;EACA,WAAA;AAAA;AAAA,iBAkBc,gBAAA,CAAA;EACd,MAAA;EACA,YAAA;EACA,KAAA;EACA,MAAA;EACA,mBAAA;EACA,WAAA;EACA,SAAA;EAAA,GACG;AAAA,GACF,qBAAA,GAAqB,kBAAA,CAAA,GAAA,CAAA,OAAA;AAAA,kBATR,gBAAA;EAAA,IAAgB,WAAA;AAAA;AAAA,kBAuNf,gBAAA;EA/OmB;;;;;;EAAA,MAsPrB,aAAA,EAAe,KAAA,CAAM,EAAA,CAAG,kBAAA;AAAA"}
|
|
@@ -114,7 +114,7 @@ function CopilotPopupViewInternal({ header, toggleButton, width, height, clickOu
|
|
|
114
114
|
"aria-label": labels.modalHeaderTitle,
|
|
115
115
|
"data-testid": "copilot-popup",
|
|
116
116
|
"data-copilot-popup": true,
|
|
117
|
-
className: cn("cpk:relative cpk:flex cpk:h-full cpk:w-full cpk:flex-col cpk:overflow-hidden cpk:bg-background cpk:text-foreground", "cpk:origin-bottom cpk:focus:outline-none cpk:transform-gpu cpk:transition-transform cpk:transition-opacity cpk:duration-200 cpk:ease-out", "cpk:md:transition-transform cpk:md:transition-opacity", "cpk:rounded-none cpk:border cpk:border-border/0 cpk:shadow-none cpk:ring-0", "cpk:md:h-[var(--copilot-popup-height)] cpk:md:w-[var(--copilot-popup-width)]", "cpk:md:max-h-[var(--copilot-popup-max-height)] cpk:md:max-w-[var(--copilot-popup-max-width)]", "cpk:md:origin-bottom-right cpk:md:rounded-2xl cpk:md:border-border cpk:md:shadow-xl cpk:md:ring-1 cpk:md:ring-border/40", popupAnimationClass),
|
|
117
|
+
className: cn("copilotKitPopup copilotKitWindow", "cpk:relative cpk:flex cpk:h-full cpk:w-full cpk:flex-col cpk:overflow-hidden cpk:bg-background cpk:text-foreground", "cpk:origin-bottom cpk:focus:outline-none cpk:transform-gpu cpk:transition-transform cpk:transition-opacity cpk:duration-200 cpk:ease-out", "cpk:md:transition-transform cpk:md:transition-opacity", "cpk:rounded-none cpk:border cpk:border-border/0 cpk:shadow-none cpk:ring-0", "cpk:md:h-[var(--copilot-popup-height)] cpk:md:w-[var(--copilot-popup-width)]", "cpk:md:max-h-[var(--copilot-popup-max-height)] cpk:md:max-w-[var(--copilot-popup-max-width)]", "cpk:md:origin-bottom-right cpk:md:rounded-2xl cpk:md:border-border cpk:md:shadow-xl cpk:md:ring-1 cpk:md:ring-border/40", popupAnimationClass),
|
|
118
118
|
style: popupStyle,
|
|
119
119
|
children: [headerElement, /* @__PURE__ */ jsx("div", {
|
|
120
120
|
className: "cpk:flex-1 cpk:overflow-hidden",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CopilotPopupView.mjs","names":["CopilotChatView"],"sources":["../../../src/components/chat/CopilotPopupView.tsx"],"sourcesContent":["import React, { useEffect, useMemo, useRef, useState } from \"react\";\nimport CopilotChatView, {\n CopilotChatViewProps,\n WelcomeScreenProps,\n} from \"./CopilotChatView\";\nimport CopilotChatToggleButton from \"./CopilotChatToggleButton\";\nimport { CopilotModalHeader } from \"./CopilotModalHeader\";\nimport { cn } from \"@/lib/utils\";\nimport { renderSlot, SlotValue } from \"@/lib/slots\";\nimport {\n CopilotChatConfigurationProvider,\n CopilotChatDefaultLabels,\n useCopilotChatConfiguration,\n} from \"@/providers/CopilotChatConfigurationProvider\";\n\nconst DEFAULT_POPUP_WIDTH = 420;\nconst DEFAULT_POPUP_HEIGHT = 560;\n\nexport type CopilotPopupViewProps = CopilotChatViewProps & {\n header?: SlotValue<typeof CopilotModalHeader>;\n toggleButton?: SlotValue<typeof CopilotChatToggleButton>;\n width?: number | string;\n height?: number | string;\n clickOutsideToClose?: boolean;\n defaultOpen?: boolean;\n};\n\nconst dimensionToCss = (\n value: number | string | undefined,\n fallback: number,\n): string => {\n if (typeof value === \"number\" && Number.isFinite(value)) {\n return `${value}px`;\n }\n\n if (typeof value === \"string\" && value.trim().length > 0) {\n return value;\n }\n\n return `${fallback}px`;\n};\n\nexport function CopilotPopupView({\n header,\n toggleButton,\n width,\n height,\n clickOutsideToClose,\n defaultOpen = true,\n className,\n ...restProps\n}: CopilotPopupViewProps) {\n return (\n <CopilotChatConfigurationProvider isModalDefaultOpen={defaultOpen}>\n <CopilotPopupViewInternal\n header={header}\n toggleButton={toggleButton}\n width={width}\n height={height}\n clickOutsideToClose={clickOutsideToClose}\n className={className}\n {...restProps}\n />\n </CopilotChatConfigurationProvider>\n );\n}\n\nfunction CopilotPopupViewInternal({\n header,\n toggleButton,\n width,\n height,\n clickOutsideToClose,\n className,\n ...restProps\n}: Omit<CopilotPopupViewProps, \"defaultOpen\">) {\n const configuration = useCopilotChatConfiguration();\n const isPopupOpen = configuration?.isModalOpen ?? false;\n const setModalOpen = configuration?.setModalOpen;\n const labels = configuration?.labels ?? CopilotChatDefaultLabels;\n\n const containerRef = useRef<HTMLDivElement>(null);\n const [isRendered, setIsRendered] = useState(isPopupOpen);\n const [isAnimatingOut, setIsAnimatingOut] = useState(false);\n\n useEffect(() => {\n if (isPopupOpen) {\n setIsRendered(true);\n setIsAnimatingOut(false);\n return;\n }\n\n if (!isRendered) {\n return;\n }\n\n setIsAnimatingOut(true);\n const timeout = setTimeout(() => {\n setIsRendered(false);\n setIsAnimatingOut(false);\n }, 200);\n\n return () => clearTimeout(timeout);\n }, [isPopupOpen, isRendered]);\n\n useEffect(() => {\n if (!isPopupOpen) {\n return;\n }\n\n if (typeof window === \"undefined\") {\n return;\n }\n\n const handleKeyDown = (event: KeyboardEvent) => {\n if (event.key === \"Escape\") {\n event.preventDefault();\n setModalOpen?.(false);\n }\n };\n\n window.addEventListener(\"keydown\", handleKeyDown);\n return () => window.removeEventListener(\"keydown\", handleKeyDown);\n }, [isPopupOpen, setModalOpen]);\n\n useEffect(() => {\n if (!isPopupOpen) {\n return;\n }\n\n const focusTimer = setTimeout(() => {\n const container = containerRef.current;\n // Don't steal focus if something inside the popup (like the input) is already focused\n if (container && !container.contains(document.activeElement)) {\n container.focus({ preventScroll: true });\n }\n }, 200);\n\n return () => clearTimeout(focusTimer);\n }, [isPopupOpen]);\n\n useEffect(() => {\n if (!isPopupOpen || !clickOutsideToClose) {\n return;\n }\n\n if (typeof document === \"undefined\") {\n return;\n }\n\n const handlePointerDown = (event: PointerEvent) => {\n const target = event.target as Node | null;\n if (!target) {\n return;\n }\n\n const container = containerRef.current;\n if (container?.contains(target)) {\n return;\n }\n\n const toggleButton = document.querySelector(\n \"[data-slot='chat-toggle-button']\",\n );\n if (toggleButton && toggleButton.contains(target)) {\n return;\n }\n\n setModalOpen?.(false);\n };\n\n document.addEventListener(\"pointerdown\", handlePointerDown);\n return () => document.removeEventListener(\"pointerdown\", handlePointerDown);\n }, [isPopupOpen, clickOutsideToClose, setModalOpen]);\n\n const headerElement = useMemo(\n () => renderSlot(header, CopilotModalHeader, {}),\n [header],\n );\n const toggleButtonElement = useMemo(\n () => renderSlot(toggleButton, CopilotChatToggleButton, {}),\n [toggleButton],\n );\n\n const resolvedWidth = dimensionToCss(width, DEFAULT_POPUP_WIDTH);\n const resolvedHeight = dimensionToCss(height, DEFAULT_POPUP_HEIGHT);\n\n const popupStyle = useMemo(\n () =>\n ({\n \"--copilot-popup-width\": resolvedWidth,\n \"--copilot-popup-height\": resolvedHeight,\n \"--copilot-popup-max-width\": \"calc(100vw - 3rem)\",\n \"--copilot-popup-max-height\": \"calc(100dvh - 7.5rem)\",\n paddingTop: \"env(safe-area-inset-top)\",\n paddingBottom: \"env(safe-area-inset-bottom)\",\n paddingLeft: \"env(safe-area-inset-left)\",\n paddingRight: \"env(safe-area-inset-right)\",\n }) as React.CSSProperties,\n [resolvedHeight, resolvedWidth],\n );\n\n const popupAnimationClass =\n isPopupOpen && !isAnimatingOut\n ? \"cpk:pointer-events-auto cpk:translate-y-0 cpk:opacity-100 cpk:md:scale-100\"\n : \"cpk:pointer-events-none cpk:translate-y-4 cpk:opacity-0 cpk:md:translate-y-5 cpk:md:scale-[0.95]\";\n\n const popupContent = isRendered ? (\n <div\n data-copilotkit\n className={cn(\n \"cpk:fixed cpk:inset-0 cpk:z-[1200] cpk:flex cpk:max-w-full cpk:flex-col cpk:items-stretch\",\n \"cpk:md:inset-auto cpk:md:bottom-24 cpk:md:right-6 cpk:md:items-end cpk:md:gap-4\",\n )}\n >\n <div\n ref={containerRef}\n tabIndex={-1}\n role=\"dialog\"\n aria-label={labels.modalHeaderTitle}\n data-testid=\"copilot-popup\"\n data-copilot-popup\n className={cn(\n \"cpk:relative cpk:flex cpk:h-full cpk:w-full cpk:flex-col cpk:overflow-hidden cpk:bg-background cpk:text-foreground\",\n \"cpk:origin-bottom cpk:focus:outline-none cpk:transform-gpu cpk:transition-transform cpk:transition-opacity cpk:duration-200 cpk:ease-out\",\n \"cpk:md:transition-transform cpk:md:transition-opacity\",\n \"cpk:rounded-none cpk:border cpk:border-border/0 cpk:shadow-none cpk:ring-0\",\n \"cpk:md:h-[var(--copilot-popup-height)] cpk:md:w-[var(--copilot-popup-width)]\",\n \"cpk:md:max-h-[var(--copilot-popup-max-height)] cpk:md:max-w-[var(--copilot-popup-max-width)]\",\n \"cpk:md:origin-bottom-right cpk:md:rounded-2xl cpk:md:border-border cpk:md:shadow-xl cpk:md:ring-1 cpk:md:ring-border/40\",\n popupAnimationClass,\n )}\n style={popupStyle}\n >\n {headerElement}\n <div className=\"cpk:flex-1 cpk:overflow-hidden\" data-popup-chat>\n <CopilotChatView\n {...restProps}\n className={cn(\"cpk:h-full cpk:min-h-0\", className)}\n />\n </div>\n </div>\n </div>\n ) : null;\n\n return (\n <>\n {toggleButtonElement}\n {popupContent}\n </>\n );\n}\n\nCopilotPopupView.displayName = \"CopilotPopupView\";\n\n// eslint-disable-next-line @typescript-eslint/no-namespace\nexport namespace CopilotPopupView {\n /**\n * Popup-specific welcome screen layout:\n * - Welcome message centered vertically\n * - Suggestions just above input\n * - Input fixed at the bottom\n */\n export const WelcomeScreen: React.FC<WelcomeScreenProps> = ({\n welcomeMessage,\n input,\n suggestionView,\n className,\n children,\n ...props\n }) => {\n // Render the welcomeMessage slot internally\n const BoundWelcomeMessage = renderSlot(\n welcomeMessage,\n CopilotChatView.WelcomeMessage,\n {},\n );\n\n if (children) {\n return (\n <div data-copilotkit style={{ display: \"contents\" }}>\n {children({\n welcomeMessage: BoundWelcomeMessage,\n input,\n suggestionView,\n className,\n ...props,\n })}\n </div>\n );\n }\n\n return (\n <div\n className={cn(\"cpk:h-full cpk:flex cpk:flex-col\", className)}\n {...props}\n >\n {/* Welcome message - centered vertically */}\n <div className=\"cpk:flex-1 cpk:flex cpk:flex-col cpk:items-center cpk:justify-center cpk:px-4\">\n {BoundWelcomeMessage}\n </div>\n\n {/* Suggestions and input at bottom */}\n <div>\n {/* Suggestions above input */}\n <div className=\"cpk:mb-4 cpk:flex cpk:justify-center cpk:px-4\">\n {suggestionView}\n </div>\n {input}\n </div>\n </div>\n );\n };\n}\n\nexport default CopilotPopupView;\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"CopilotPopupView.mjs","names":["CopilotChatView"],"sources":["../../../src/components/chat/CopilotPopupView.tsx"],"sourcesContent":["import React, { useEffect, useMemo, useRef, useState } from \"react\";\nimport CopilotChatView, {\n CopilotChatViewProps,\n WelcomeScreenProps,\n} from \"./CopilotChatView\";\nimport CopilotChatToggleButton from \"./CopilotChatToggleButton\";\nimport { CopilotModalHeader } from \"./CopilotModalHeader\";\nimport { cn } from \"@/lib/utils\";\nimport { renderSlot, SlotValue } from \"@/lib/slots\";\nimport {\n CopilotChatConfigurationProvider,\n CopilotChatDefaultLabels,\n useCopilotChatConfiguration,\n} from \"@/providers/CopilotChatConfigurationProvider\";\n\nconst DEFAULT_POPUP_WIDTH = 420;\nconst DEFAULT_POPUP_HEIGHT = 560;\n\nexport type CopilotPopupViewProps = CopilotChatViewProps & {\n header?: SlotValue<typeof CopilotModalHeader>;\n toggleButton?: SlotValue<typeof CopilotChatToggleButton>;\n width?: number | string;\n height?: number | string;\n clickOutsideToClose?: boolean;\n defaultOpen?: boolean;\n};\n\nconst dimensionToCss = (\n value: number | string | undefined,\n fallback: number,\n): string => {\n if (typeof value === \"number\" && Number.isFinite(value)) {\n return `${value}px`;\n }\n\n if (typeof value === \"string\" && value.trim().length > 0) {\n return value;\n }\n\n return `${fallback}px`;\n};\n\nexport function CopilotPopupView({\n header,\n toggleButton,\n width,\n height,\n clickOutsideToClose,\n defaultOpen = true,\n className,\n ...restProps\n}: CopilotPopupViewProps) {\n return (\n <CopilotChatConfigurationProvider isModalDefaultOpen={defaultOpen}>\n <CopilotPopupViewInternal\n header={header}\n toggleButton={toggleButton}\n width={width}\n height={height}\n clickOutsideToClose={clickOutsideToClose}\n className={className}\n {...restProps}\n />\n </CopilotChatConfigurationProvider>\n );\n}\n\nfunction CopilotPopupViewInternal({\n header,\n toggleButton,\n width,\n height,\n clickOutsideToClose,\n className,\n ...restProps\n}: Omit<CopilotPopupViewProps, \"defaultOpen\">) {\n const configuration = useCopilotChatConfiguration();\n const isPopupOpen = configuration?.isModalOpen ?? false;\n const setModalOpen = configuration?.setModalOpen;\n const labels = configuration?.labels ?? CopilotChatDefaultLabels;\n\n const containerRef = useRef<HTMLDivElement>(null);\n const [isRendered, setIsRendered] = useState(isPopupOpen);\n const [isAnimatingOut, setIsAnimatingOut] = useState(false);\n\n useEffect(() => {\n if (isPopupOpen) {\n setIsRendered(true);\n setIsAnimatingOut(false);\n return;\n }\n\n if (!isRendered) {\n return;\n }\n\n setIsAnimatingOut(true);\n const timeout = setTimeout(() => {\n setIsRendered(false);\n setIsAnimatingOut(false);\n }, 200);\n\n return () => clearTimeout(timeout);\n }, [isPopupOpen, isRendered]);\n\n useEffect(() => {\n if (!isPopupOpen) {\n return;\n }\n\n if (typeof window === \"undefined\") {\n return;\n }\n\n const handleKeyDown = (event: KeyboardEvent) => {\n if (event.key === \"Escape\") {\n event.preventDefault();\n setModalOpen?.(false);\n }\n };\n\n window.addEventListener(\"keydown\", handleKeyDown);\n return () => window.removeEventListener(\"keydown\", handleKeyDown);\n }, [isPopupOpen, setModalOpen]);\n\n useEffect(() => {\n if (!isPopupOpen) {\n return;\n }\n\n const focusTimer = setTimeout(() => {\n const container = containerRef.current;\n // Don't steal focus if something inside the popup (like the input) is already focused\n if (container && !container.contains(document.activeElement)) {\n container.focus({ preventScroll: true });\n }\n }, 200);\n\n return () => clearTimeout(focusTimer);\n }, [isPopupOpen]);\n\n useEffect(() => {\n if (!isPopupOpen || !clickOutsideToClose) {\n return;\n }\n\n if (typeof document === \"undefined\") {\n return;\n }\n\n const handlePointerDown = (event: PointerEvent) => {\n const target = event.target as Node | null;\n if (!target) {\n return;\n }\n\n const container = containerRef.current;\n if (container?.contains(target)) {\n return;\n }\n\n const toggleButton = document.querySelector(\n \"[data-slot='chat-toggle-button']\",\n );\n if (toggleButton && toggleButton.contains(target)) {\n return;\n }\n\n setModalOpen?.(false);\n };\n\n document.addEventListener(\"pointerdown\", handlePointerDown);\n return () => document.removeEventListener(\"pointerdown\", handlePointerDown);\n }, [isPopupOpen, clickOutsideToClose, setModalOpen]);\n\n const headerElement = useMemo(\n () => renderSlot(header, CopilotModalHeader, {}),\n [header],\n );\n const toggleButtonElement = useMemo(\n () => renderSlot(toggleButton, CopilotChatToggleButton, {}),\n [toggleButton],\n );\n\n const resolvedWidth = dimensionToCss(width, DEFAULT_POPUP_WIDTH);\n const resolvedHeight = dimensionToCss(height, DEFAULT_POPUP_HEIGHT);\n\n const popupStyle = useMemo(\n () =>\n ({\n \"--copilot-popup-width\": resolvedWidth,\n \"--copilot-popup-height\": resolvedHeight,\n \"--copilot-popup-max-width\": \"calc(100vw - 3rem)\",\n \"--copilot-popup-max-height\": \"calc(100dvh - 7.5rem)\",\n paddingTop: \"env(safe-area-inset-top)\",\n paddingBottom: \"env(safe-area-inset-bottom)\",\n paddingLeft: \"env(safe-area-inset-left)\",\n paddingRight: \"env(safe-area-inset-right)\",\n }) as React.CSSProperties,\n [resolvedHeight, resolvedWidth],\n );\n\n const popupAnimationClass =\n isPopupOpen && !isAnimatingOut\n ? \"cpk:pointer-events-auto cpk:translate-y-0 cpk:opacity-100 cpk:md:scale-100\"\n : \"cpk:pointer-events-none cpk:translate-y-4 cpk:opacity-0 cpk:md:translate-y-5 cpk:md:scale-[0.95]\";\n\n const popupContent = isRendered ? (\n <div\n data-copilotkit\n className={cn(\n \"cpk:fixed cpk:inset-0 cpk:z-[1200] cpk:flex cpk:max-w-full cpk:flex-col cpk:items-stretch\",\n \"cpk:md:inset-auto cpk:md:bottom-24 cpk:md:right-6 cpk:md:items-end cpk:md:gap-4\",\n )}\n >\n <div\n ref={containerRef}\n tabIndex={-1}\n role=\"dialog\"\n aria-label={labels.modalHeaderTitle}\n data-testid=\"copilot-popup\"\n data-copilot-popup\n className={cn(\n \"copilotKitPopup copilotKitWindow\",\n \"cpk:relative cpk:flex cpk:h-full cpk:w-full cpk:flex-col cpk:overflow-hidden cpk:bg-background cpk:text-foreground\",\n \"cpk:origin-bottom cpk:focus:outline-none cpk:transform-gpu cpk:transition-transform cpk:transition-opacity cpk:duration-200 cpk:ease-out\",\n \"cpk:md:transition-transform cpk:md:transition-opacity\",\n \"cpk:rounded-none cpk:border cpk:border-border/0 cpk:shadow-none cpk:ring-0\",\n \"cpk:md:h-[var(--copilot-popup-height)] cpk:md:w-[var(--copilot-popup-width)]\",\n \"cpk:md:max-h-[var(--copilot-popup-max-height)] cpk:md:max-w-[var(--copilot-popup-max-width)]\",\n \"cpk:md:origin-bottom-right cpk:md:rounded-2xl cpk:md:border-border cpk:md:shadow-xl cpk:md:ring-1 cpk:md:ring-border/40\",\n popupAnimationClass,\n )}\n style={popupStyle}\n >\n {headerElement}\n <div className=\"cpk:flex-1 cpk:overflow-hidden\" data-popup-chat>\n <CopilotChatView\n {...restProps}\n className={cn(\"cpk:h-full cpk:min-h-0\", className)}\n />\n </div>\n </div>\n </div>\n ) : null;\n\n return (\n <>\n {toggleButtonElement}\n {popupContent}\n </>\n );\n}\n\nCopilotPopupView.displayName = \"CopilotPopupView\";\n\n// eslint-disable-next-line @typescript-eslint/no-namespace\nexport namespace CopilotPopupView {\n /**\n * Popup-specific welcome screen layout:\n * - Welcome message centered vertically\n * - Suggestions just above input\n * - Input fixed at the bottom\n */\n export const WelcomeScreen: React.FC<WelcomeScreenProps> = ({\n welcomeMessage,\n input,\n suggestionView,\n className,\n children,\n ...props\n }) => {\n // Render the welcomeMessage slot internally\n const BoundWelcomeMessage = renderSlot(\n welcomeMessage,\n CopilotChatView.WelcomeMessage,\n {},\n );\n\n if (children) {\n return (\n <div data-copilotkit style={{ display: \"contents\" }}>\n {children({\n welcomeMessage: BoundWelcomeMessage,\n input,\n suggestionView,\n className,\n ...props,\n })}\n </div>\n );\n }\n\n return (\n <div\n className={cn(\"cpk:h-full cpk:flex cpk:flex-col\", className)}\n {...props}\n >\n {/* Welcome message - centered vertically */}\n <div className=\"cpk:flex-1 cpk:flex cpk:flex-col cpk:items-center cpk:justify-center cpk:px-4\">\n {BoundWelcomeMessage}\n </div>\n\n {/* Suggestions and input at bottom */}\n <div>\n {/* Suggestions above input */}\n <div className=\"cpk:mb-4 cpk:flex cpk:justify-center cpk:px-4\">\n {suggestionView}\n </div>\n {input}\n </div>\n </div>\n );\n };\n}\n\nexport default CopilotPopupView;\n"],"mappings":"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"}
|
|
@@ -75,7 +75,7 @@ function CopilotSidebarViewInternal({ header, toggleButton, width, ...props }) {
|
|
|
75
75
|
"data-copilotkit": true,
|
|
76
76
|
"data-testid": "copilot-sidebar",
|
|
77
77
|
"data-copilot-sidebar": true,
|
|
78
|
-
className: require_utils.cn("cpk:fixed cpk:right-0 cpk:top-0 cpk:z-[1200] cpk:flex", "cpk:h-[100vh] cpk:h-[100dvh] cpk:max-h-screen", "cpk:w-full", "cpk:border-l cpk:border-border cpk:bg-background cpk:text-foreground cpk:shadow-xl", "cpk:transition-transform cpk:duration-300 cpk:ease-out", isSidebarOpen ? "cpk:translate-x-0" : "cpk:translate-x-full cpk:pointer-events-none"),
|
|
78
|
+
className: require_utils.cn("copilotKitSidebar copilotKitWindow", "cpk:fixed cpk:right-0 cpk:top-0 cpk:z-[1200] cpk:flex", "cpk:h-[100vh] cpk:h-[100dvh] cpk:max-h-screen", "cpk:w-full", "cpk:border-l cpk:border-border cpk:bg-background cpk:text-foreground cpk:shadow-xl", "cpk:transition-transform cpk:duration-300 cpk:ease-out", isSidebarOpen ? "cpk:translate-x-0" : "cpk:translate-x-full cpk:pointer-events-none"),
|
|
79
79
|
style: {
|
|
80
80
|
["--sidebar-width"]: widthToCss(sidebarWidth),
|
|
81
81
|
paddingTop: "env(safe-area-inset-top)",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CopilotSidebarView.cjs","names":["CopilotChatConfigurationProvider","useCopilotChatConfiguration","renderSlot","CopilotModalHeader","CopilotChatToggleButton","cn","CopilotChatView"],"sources":["../../../src/components/chat/CopilotSidebarView.tsx"],"sourcesContent":["import React, { useEffect, useLayoutEffect, useRef, useState } from \"react\";\n\nimport CopilotChatView, {\n CopilotChatViewProps,\n WelcomeScreenProps,\n} from \"./CopilotChatView\";\nimport {\n CopilotChatConfigurationProvider,\n useCopilotChatConfiguration,\n} from \"@/providers/CopilotChatConfigurationProvider\";\nimport CopilotChatToggleButton from \"./CopilotChatToggleButton\";\nimport { cn } from \"@/lib/utils\";\nimport { CopilotModalHeader } from \"./CopilotModalHeader\";\nimport { renderSlot, SlotValue } from \"@/lib/slots\";\n\nconst DEFAULT_SIDEBAR_WIDTH = 480;\nconst SIDEBAR_TRANSITION_MS = 260;\n\nexport type CopilotSidebarViewProps = CopilotChatViewProps & {\n header?: SlotValue<typeof CopilotModalHeader>;\n toggleButton?: SlotValue<typeof CopilotChatToggleButton>;\n width?: number | string;\n defaultOpen?: boolean;\n};\n\nexport function CopilotSidebarView({\n header,\n toggleButton,\n width,\n defaultOpen = true,\n ...props\n}: CopilotSidebarViewProps) {\n return (\n <CopilotChatConfigurationProvider isModalDefaultOpen={defaultOpen}>\n <CopilotSidebarViewInternal\n header={header}\n toggleButton={toggleButton}\n width={width}\n {...props}\n />\n </CopilotChatConfigurationProvider>\n );\n}\n\nfunction CopilotSidebarViewInternal({\n header,\n toggleButton,\n width,\n ...props\n}: Omit<CopilotSidebarViewProps, \"defaultOpen\">) {\n const configuration = useCopilotChatConfiguration();\n\n const isSidebarOpen = configuration?.isModalOpen ?? false;\n\n const sidebarRef = useRef<HTMLDivElement | null>(null);\n const [sidebarWidth, setSidebarWidth] = useState<number | string>(\n width ?? DEFAULT_SIDEBAR_WIDTH,\n );\n\n // Helper to convert width to CSS value\n const widthToCss = (w: number | string): string => {\n return typeof w === \"number\" ? `${w}px` : w;\n };\n\n // Helper to extract numeric value for body margin (only works with px values)\n const widthToMargin = (w: number | string): string => {\n if (typeof w === \"number\") {\n return `${w}px`;\n }\n // For string values, use as-is (assumes valid CSS unit)\n return w;\n };\n\n useEffect(() => {\n // If width is explicitly provided, don't measure\n if (width !== undefined) {\n return;\n }\n\n if (typeof window === \"undefined\") {\n return;\n }\n\n const element = sidebarRef.current;\n if (!element) {\n return;\n }\n\n const updateWidth = () => {\n const rect = element.getBoundingClientRect();\n if (rect.width > 0) {\n setSidebarWidth(rect.width);\n }\n };\n\n updateWidth();\n\n if (typeof ResizeObserver !== \"undefined\") {\n const observer = new ResizeObserver(() => updateWidth());\n observer.observe(element);\n return () => observer.disconnect();\n }\n\n window.addEventListener(\"resize\", updateWidth);\n return () => window.removeEventListener(\"resize\", updateWidth);\n }, [width]);\n\n // Manage body margin for sidebar docking (desktop only).\n // useLayoutEffect runs before paint, so defaultOpen={true} never causes a\n // visible layout shift — the margin is already applied on the first frame.\n const hasMounted = useRef(false);\n\n useLayoutEffect(() => {\n if (\n typeof window === \"undefined\" ||\n typeof window.matchMedia !== \"function\"\n )\n return;\n if (!window.matchMedia(\"(min-width: 768px)\").matches) return;\n\n if (isSidebarOpen) {\n if (hasMounted.current) {\n document.body.style.transition = `margin-inline-end ${SIDEBAR_TRANSITION_MS}ms ease`;\n }\n document.body.style.marginInlineEnd = widthToMargin(sidebarWidth);\n } else if (hasMounted.current) {\n document.body.style.transition = `margin-inline-end ${SIDEBAR_TRANSITION_MS}ms ease`;\n document.body.style.marginInlineEnd = \"\";\n }\n\n hasMounted.current = true;\n\n return () => {\n document.body.style.marginInlineEnd = \"\";\n document.body.style.transition = \"\";\n };\n }, [isSidebarOpen, sidebarWidth]);\n\n const headerElement = renderSlot(header, CopilotModalHeader, {});\n const toggleButtonElement = renderSlot(\n toggleButton,\n CopilotChatToggleButton,\n {},\n );\n\n return (\n <>\n {toggleButtonElement}\n <aside\n ref={sidebarRef}\n data-copilotkit\n data-testid=\"copilot-sidebar\"\n data-copilot-sidebar\n className={cn(\n \"cpk:fixed cpk:right-0 cpk:top-0 cpk:z-[1200] cpk:flex\",\n // Height with dvh fallback and safe area support\n \"cpk:h-[100vh] cpk:h-[100dvh] cpk:max-h-screen\",\n // Responsive width: full on mobile, custom on desktop\n \"cpk:w-full\",\n \"cpk:border-l cpk:border-border cpk:bg-background cpk:text-foreground cpk:shadow-xl\",\n \"cpk:transition-transform cpk:duration-300 cpk:ease-out\",\n isSidebarOpen\n ? \"cpk:translate-x-0\"\n : \"cpk:translate-x-full cpk:pointer-events-none\",\n )}\n style={\n {\n // Use CSS custom property for responsive width\n [\"--sidebar-width\" as string]: widthToCss(sidebarWidth),\n // Safe area insets for iOS\n paddingTop: \"env(safe-area-inset-top)\",\n paddingBottom: \"env(safe-area-inset-bottom)\",\n } as React.CSSProperties\n }\n aria-hidden={!isSidebarOpen}\n aria-label=\"Copilot chat sidebar\"\n role=\"complementary\"\n >\n <div className=\"cpk:flex cpk:h-full cpk:w-full cpk:flex-col cpk:overflow-hidden\">\n {headerElement}\n <div className=\"cpk:flex-1 cpk:overflow-hidden\" data-sidebar-chat>\n <CopilotChatView {...props} />\n </div>\n </div>\n </aside>\n </>\n );\n}\n\nCopilotSidebarView.displayName = \"CopilotSidebarView\";\n\n// eslint-disable-next-line @typescript-eslint/no-namespace\nexport namespace CopilotSidebarView {\n /**\n * Sidebar-specific welcome screen layout:\n * - Suggestions at the top\n * - Welcome message in the middle\n * - Input fixed at the bottom (like normal chat)\n */\n export const WelcomeScreen: React.FC<WelcomeScreenProps> = ({\n welcomeMessage,\n input,\n suggestionView,\n className,\n children,\n ...props\n }) => {\n // Render the welcomeMessage slot internally\n const BoundWelcomeMessage = renderSlot(\n welcomeMessage,\n CopilotChatView.WelcomeMessage,\n {},\n );\n\n if (children) {\n return (\n <div data-copilotkit style={{ display: \"contents\" }}>\n {children({\n welcomeMessage: BoundWelcomeMessage,\n input,\n suggestionView,\n className,\n ...props,\n })}\n </div>\n );\n }\n\n return (\n <div\n className={cn(\"cpk:h-full cpk:flex cpk:flex-col\", className)}\n {...props}\n >\n {/* Welcome message - centered vertically */}\n <div className=\"cpk:flex-1 cpk:flex cpk:flex-col cpk:items-center cpk:justify-center cpk:px-4\">\n {BoundWelcomeMessage}\n </div>\n\n {/* Suggestions and input at bottom */}\n <div className=\"cpk:px-8 cpk:pb-4\">\n <div className=\"cpk:max-w-3xl cpk:mx-auto\">\n {/* Suggestions above input */}\n <div className=\"cpk:mb-4 cpk:flex cpk:justify-center\">\n {suggestionView}\n </div>\n {input}\n </div>\n </div>\n </div>\n );\n };\n}\n\nexport default CopilotSidebarView;\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"CopilotSidebarView.cjs","names":["CopilotChatConfigurationProvider","useCopilotChatConfiguration","renderSlot","CopilotModalHeader","CopilotChatToggleButton","cn","CopilotChatView"],"sources":["../../../src/components/chat/CopilotSidebarView.tsx"],"sourcesContent":["import React, { useEffect, useLayoutEffect, useRef, useState } from \"react\";\n\nimport CopilotChatView, {\n CopilotChatViewProps,\n WelcomeScreenProps,\n} from \"./CopilotChatView\";\nimport {\n CopilotChatConfigurationProvider,\n useCopilotChatConfiguration,\n} from \"@/providers/CopilotChatConfigurationProvider\";\nimport CopilotChatToggleButton from \"./CopilotChatToggleButton\";\nimport { cn } from \"@/lib/utils\";\nimport { CopilotModalHeader } from \"./CopilotModalHeader\";\nimport { renderSlot, SlotValue } from \"@/lib/slots\";\n\nconst DEFAULT_SIDEBAR_WIDTH = 480;\nconst SIDEBAR_TRANSITION_MS = 260;\n\nexport type CopilotSidebarViewProps = CopilotChatViewProps & {\n header?: SlotValue<typeof CopilotModalHeader>;\n toggleButton?: SlotValue<typeof CopilotChatToggleButton>;\n width?: number | string;\n defaultOpen?: boolean;\n};\n\nexport function CopilotSidebarView({\n header,\n toggleButton,\n width,\n defaultOpen = true,\n ...props\n}: CopilotSidebarViewProps) {\n return (\n <CopilotChatConfigurationProvider isModalDefaultOpen={defaultOpen}>\n <CopilotSidebarViewInternal\n header={header}\n toggleButton={toggleButton}\n width={width}\n {...props}\n />\n </CopilotChatConfigurationProvider>\n );\n}\n\nfunction CopilotSidebarViewInternal({\n header,\n toggleButton,\n width,\n ...props\n}: Omit<CopilotSidebarViewProps, \"defaultOpen\">) {\n const configuration = useCopilotChatConfiguration();\n\n const isSidebarOpen = configuration?.isModalOpen ?? false;\n\n const sidebarRef = useRef<HTMLDivElement | null>(null);\n const [sidebarWidth, setSidebarWidth] = useState<number | string>(\n width ?? DEFAULT_SIDEBAR_WIDTH,\n );\n\n // Helper to convert width to CSS value\n const widthToCss = (w: number | string): string => {\n return typeof w === \"number\" ? `${w}px` : w;\n };\n\n // Helper to extract numeric value for body margin (only works with px values)\n const widthToMargin = (w: number | string): string => {\n if (typeof w === \"number\") {\n return `${w}px`;\n }\n // For string values, use as-is (assumes valid CSS unit)\n return w;\n };\n\n useEffect(() => {\n // If width is explicitly provided, don't measure\n if (width !== undefined) {\n return;\n }\n\n if (typeof window === \"undefined\") {\n return;\n }\n\n const element = sidebarRef.current;\n if (!element) {\n return;\n }\n\n const updateWidth = () => {\n const rect = element.getBoundingClientRect();\n if (rect.width > 0) {\n setSidebarWidth(rect.width);\n }\n };\n\n updateWidth();\n\n if (typeof ResizeObserver !== \"undefined\") {\n const observer = new ResizeObserver(() => updateWidth());\n observer.observe(element);\n return () => observer.disconnect();\n }\n\n window.addEventListener(\"resize\", updateWidth);\n return () => window.removeEventListener(\"resize\", updateWidth);\n }, [width]);\n\n // Manage body margin for sidebar docking (desktop only).\n // useLayoutEffect runs before paint, so defaultOpen={true} never causes a\n // visible layout shift — the margin is already applied on the first frame.\n const hasMounted = useRef(false);\n\n useLayoutEffect(() => {\n if (\n typeof window === \"undefined\" ||\n typeof window.matchMedia !== \"function\"\n )\n return;\n if (!window.matchMedia(\"(min-width: 768px)\").matches) return;\n\n if (isSidebarOpen) {\n if (hasMounted.current) {\n document.body.style.transition = `margin-inline-end ${SIDEBAR_TRANSITION_MS}ms ease`;\n }\n document.body.style.marginInlineEnd = widthToMargin(sidebarWidth);\n } else if (hasMounted.current) {\n document.body.style.transition = `margin-inline-end ${SIDEBAR_TRANSITION_MS}ms ease`;\n document.body.style.marginInlineEnd = \"\";\n }\n\n hasMounted.current = true;\n\n return () => {\n document.body.style.marginInlineEnd = \"\";\n document.body.style.transition = \"\";\n };\n }, [isSidebarOpen, sidebarWidth]);\n\n const headerElement = renderSlot(header, CopilotModalHeader, {});\n const toggleButtonElement = renderSlot(\n toggleButton,\n CopilotChatToggleButton,\n {},\n );\n\n return (\n <>\n {toggleButtonElement}\n <aside\n ref={sidebarRef}\n data-copilotkit\n data-testid=\"copilot-sidebar\"\n data-copilot-sidebar\n className={cn(\n \"copilotKitSidebar copilotKitWindow\",\n \"cpk:fixed cpk:right-0 cpk:top-0 cpk:z-[1200] cpk:flex\",\n // Height with dvh fallback and safe area support\n \"cpk:h-[100vh] cpk:h-[100dvh] cpk:max-h-screen\",\n // Responsive width: full on mobile, custom on desktop\n \"cpk:w-full\",\n \"cpk:border-l cpk:border-border cpk:bg-background cpk:text-foreground cpk:shadow-xl\",\n \"cpk:transition-transform cpk:duration-300 cpk:ease-out\",\n isSidebarOpen\n ? \"cpk:translate-x-0\"\n : \"cpk:translate-x-full cpk:pointer-events-none\",\n )}\n style={\n {\n // Use CSS custom property for responsive width\n [\"--sidebar-width\" as string]: widthToCss(sidebarWidth),\n // Safe area insets for iOS\n paddingTop: \"env(safe-area-inset-top)\",\n paddingBottom: \"env(safe-area-inset-bottom)\",\n } as React.CSSProperties\n }\n aria-hidden={!isSidebarOpen}\n aria-label=\"Copilot chat sidebar\"\n role=\"complementary\"\n >\n <div className=\"cpk:flex cpk:h-full cpk:w-full cpk:flex-col cpk:overflow-hidden\">\n {headerElement}\n <div className=\"cpk:flex-1 cpk:overflow-hidden\" data-sidebar-chat>\n <CopilotChatView {...props} />\n </div>\n </div>\n </aside>\n </>\n );\n}\n\nCopilotSidebarView.displayName = \"CopilotSidebarView\";\n\n// eslint-disable-next-line @typescript-eslint/no-namespace\nexport namespace CopilotSidebarView {\n /**\n * Sidebar-specific welcome screen layout:\n * - Suggestions at the top\n * - Welcome message in the middle\n * - Input fixed at the bottom (like normal chat)\n */\n export const WelcomeScreen: React.FC<WelcomeScreenProps> = ({\n welcomeMessage,\n input,\n suggestionView,\n className,\n children,\n ...props\n }) => {\n // Render the welcomeMessage slot internally\n const BoundWelcomeMessage = renderSlot(\n welcomeMessage,\n CopilotChatView.WelcomeMessage,\n {},\n );\n\n if (children) {\n return (\n <div data-copilotkit style={{ display: \"contents\" }}>\n {children({\n welcomeMessage: BoundWelcomeMessage,\n input,\n suggestionView,\n className,\n ...props,\n })}\n </div>\n );\n }\n\n return (\n <div\n className={cn(\"cpk:h-full cpk:flex cpk:flex-col\", className)}\n {...props}\n >\n {/* Welcome message - centered vertically */}\n <div className=\"cpk:flex-1 cpk:flex cpk:flex-col cpk:items-center cpk:justify-center cpk:px-4\">\n {BoundWelcomeMessage}\n </div>\n\n {/* Suggestions and input at bottom */}\n <div className=\"cpk:px-8 cpk:pb-4\">\n <div className=\"cpk:max-w-3xl cpk:mx-auto\">\n {/* Suggestions above input */}\n <div className=\"cpk:mb-4 cpk:flex cpk:justify-center\">\n {suggestionView}\n </div>\n {input}\n </div>\n </div>\n </div>\n );\n };\n}\n\nexport default CopilotSidebarView;\n"],"mappings":"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"}
|