const require_runtime = require('../../_virtual/_rolldown/runtime.cjs'); const require_CopilotChatConfigurationProvider = require('../../providers/CopilotChatConfigurationProvider.cjs'); const require_utils = require('../../lib/utils.cjs'); const require_button = require('../ui/button.cjs'); const require_tooltip = require('../ui/tooltip.cjs'); const require_dropdown_menu = require('../ui/dropdown-menu.cjs'); const require_CopilotChatAudioRecorder = require('./CopilotChatAudioRecorder.cjs'); const require_slots = require('../../lib/slots.cjs'); let react = require("react"); react = require_runtime.__toESM(react); let tailwind_merge = require("tailwind-merge"); let lucide_react = require("lucide-react"); let react_jsx_runtime = require("react/jsx-runtime"); //#region src/components/chat/CopilotChatInput.tsx const SLASH_MENU_MAX_VISIBLE_ITEMS = 5; const SLASH_MENU_ITEM_HEIGHT_PX = 40; function CopilotChatInput({ mode = "input", onSubmitMessage, onStop, isRunning = false, onStartTranscribe, onCancelTranscribe, onFinishTranscribe, onFinishTranscribeWithAudio, onAddFile, onChange, value, toolsMenu, autoFocus = true, positioning = "static", keyboardHeight = 0, containerRef, showDisclaimer, textArea, sendButton, startTranscribeButton, cancelTranscribeButton, finishTranscribeButton, addMenuButton, audioRecorder, disclaimer, children, className, ...props }) { const isControlled = value !== void 0; const [internalValue, setInternalValue] = (0, react.useState)(() => value ?? ""); (0, react.useEffect)(() => { if (!isControlled && value !== void 0) setInternalValue(value); }, [isControlled, value]); const resolvedValue = isControlled ? value ?? "" : internalValue; const [layout, setLayout] = (0, react.useState)("compact"); const ignoreResizeRef = (0, react.useRef)(false); const resizeEvaluationRafRef = (0, react.useRef)(null); const isExpanded = mode === "input" && layout === "expanded"; const [commandQuery, setCommandQuery] = (0, react.useState)(null); const [slashHighlightIndex, setSlashHighlightIndex] = (0, react.useState)(0); const inputRef = (0, react.useRef)(null); const gridRef = (0, react.useRef)(null); const addButtonContainerRef = (0, react.useRef)(null); const actionsContainerRef = (0, react.useRef)(null); const audioRecorderRef = (0, react.useRef)(null); const slashMenuRef = (0, react.useRef)(null); const config = require_CopilotChatConfigurationProvider.useCopilotChatConfiguration(); const labels = config?.labels ?? require_CopilotChatConfigurationProvider.CopilotChatDefaultLabels; const previousModalStateRef = (0, react.useRef)(void 0); const measurementCanvasRef = (0, react.useRef)(null); const measurementsRef = (0, react.useRef)({ singleLineHeight: 0, maxHeight: 0, paddingLeft: 0, paddingRight: 0 }); const commandItems = (0, react.useMemo)(() => { const entries = []; const seen = /* @__PURE__ */ new Set(); const pushItem = (item) => { if (item === "-") return; if (item.items && item.items.length > 0) { for (const nested of item.items) pushItem(nested); return; } if (!seen.has(item.label)) { seen.add(item.label); entries.push(item); } }; if (onAddFile) pushItem({ label: labels.chatInputToolbarAddButtonLabel, action: onAddFile }); if (toolsMenu && toolsMenu.length > 0) for (const item of toolsMenu) pushItem(item); return entries; }, [ labels.chatInputToolbarAddButtonLabel, onAddFile, toolsMenu ]); const filteredCommands = (0, react.useMemo)(() => { if (commandQuery === null) return []; if (commandItems.length === 0) return []; const query = commandQuery.trim().toLowerCase(); if (query.length === 0) return commandItems; const startsWith = []; const contains = []; for (const item of commandItems) { const label = item.label.toLowerCase(); if (label.startsWith(query)) startsWith.push(item); else if (label.includes(query)) contains.push(item); } return [...startsWith, ...contains]; }, [commandItems, commandQuery]); (0, react.useEffect)(() => { if (!autoFocus) { previousModalStateRef.current = config?.isModalOpen; return; } if (config?.isModalOpen && !previousModalStateRef.current) inputRef.current?.focus(); previousModalStateRef.current = config?.isModalOpen; }, [config?.isModalOpen, autoFocus]); (0, react.useEffect)(() => { if (commandItems.length === 0 && commandQuery !== null) setCommandQuery(null); }, [commandItems.length, commandQuery]); const previousCommandQueryRef = (0, react.useRef)(null); (0, react.useEffect)(() => { if (commandQuery !== null && commandQuery !== previousCommandQueryRef.current && filteredCommands.length > 0) setSlashHighlightIndex(0); previousCommandQueryRef.current = commandQuery; }, [commandQuery, filteredCommands.length]); (0, react.useEffect)(() => { if (commandQuery === null) { setSlashHighlightIndex(0); return; } if (filteredCommands.length === 0) setSlashHighlightIndex(-1); else if (slashHighlightIndex < 0 || slashHighlightIndex >= filteredCommands.length) setSlashHighlightIndex(0); }, [ commandQuery, filteredCommands, slashHighlightIndex ]); (0, react.useEffect)(() => { const recorder = audioRecorderRef.current; if (!recorder) return; if (mode === "transcribe") recorder.start().catch(console.error); else if (recorder.state === "recording") recorder.stop().catch(console.error); }, [mode]); (0, react.useEffect)(() => { if (mode !== "input") { setLayout("compact"); setCommandQuery(null); } }, [mode]); const updateSlashState = (0, react.useCallback)((value) => { if (commandItems.length === 0) { setCommandQuery((prev) => prev === null ? prev : null); return; } if (value.startsWith("/")) { const query = (value.split(/\r?\n/, 1)[0] ?? "").slice(1); setCommandQuery((prev) => prev === query ? prev : query); } else setCommandQuery((prev) => prev === null ? prev : null); }, [commandItems.length]); (0, react.useEffect)(() => { updateSlashState(resolvedValue); }, [resolvedValue, updateSlashState]); const handleChange = (e) => { const nextValue = e.target.value; if (!isControlled) setInternalValue(nextValue); onChange?.(nextValue); updateSlashState(nextValue); }; const clearInputValue = (0, react.useCallback)(() => { if (!isControlled) setInternalValue(""); if (onChange) onChange(""); }, [isControlled, onChange]); const runCommand = (0, react.useCallback)((item) => { clearInputValue(); item.action?.(); setCommandQuery(null); setSlashHighlightIndex(0); requestAnimationFrame(() => { inputRef.current?.focus(); }); }, [clearInputValue]); const handleKeyDown = (e) => { if (commandQuery !== null && mode === "input") { if (e.key === "ArrowDown") { if (filteredCommands.length > 0) { e.preventDefault(); setSlashHighlightIndex((prev) => { if (filteredCommands.length === 0) return prev; return prev === -1 ? 0 : (prev + 1) % filteredCommands.length; }); } return; } if (e.key === "ArrowUp") { if (filteredCommands.length > 0) { e.preventDefault(); setSlashHighlightIndex((prev) => { if (filteredCommands.length === 0) return prev; if (prev === -1) return filteredCommands.length - 1; return prev <= 0 ? filteredCommands.length - 1 : prev - 1; }); } return; } if (e.key === "Enter") { const selected = slashHighlightIndex >= 0 ? filteredCommands[slashHighlightIndex] : void 0; if (selected) { e.preventDefault(); runCommand(selected); return; } } if (e.key === "Escape") { e.preventDefault(); setCommandQuery(null); return; } } if (e.key === "Enter" && !e.shiftKey) { e.preventDefault(); if (isProcessing) onStop?.(); else send(); } }; const send = () => { if (!onSubmitMessage) return; const trimmed = resolvedValue.trim(); if (!trimmed) return; onSubmitMessage(trimmed); if (!isControlled) { setInternalValue(""); onChange?.(""); } if (inputRef.current) inputRef.current.focus(); }; const BoundTextArea = require_slots.renderSlot(textArea, CopilotChatInput.TextArea, { ref: inputRef, value: resolvedValue, onChange: handleChange, onKeyDown: handleKeyDown, autoFocus, className: (0, tailwind_merge.twMerge)("cpk:w-full cpk:py-3", isExpanded ? "cpk:px-5" : "cpk:pr-5") }); const isProcessing = mode !== "transcribe" && isRunning; const canSend = resolvedValue.trim().length > 0 && !!onSubmitMessage; const canStop = !!onStop; const handleSendButtonClick = () => { if (isProcessing) { onStop?.(); return; } send(); }; const BoundAudioRecorder = require_slots.renderSlot(audioRecorder, require_CopilotChatAudioRecorder.CopilotChatAudioRecorder, { ref: audioRecorderRef }); const BoundSendButton = require_slots.renderSlot(sendButton, CopilotChatInput.SendButton, { onClick: handleSendButtonClick, disabled: isProcessing ? !canStop : !canSend, children: isProcessing && canStop ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(lucide_react.Square, { className: "cpk:size-[18px] cpk:fill-current" }) : void 0 }); const BoundStartTranscribeButton = require_slots.renderSlot(startTranscribeButton, CopilotChatInput.StartTranscribeButton, { onClick: onStartTranscribe }); const BoundCancelTranscribeButton = require_slots.renderSlot(cancelTranscribeButton, CopilotChatInput.CancelTranscribeButton, { onClick: onCancelTranscribe }); const handleFinishTranscribe = (0, react.useCallback)(async () => { const recorder = audioRecorderRef.current; if (recorder && recorder.state === "recording") try { const audioBlob = await recorder.stop(); if (onFinishTranscribeWithAudio) await onFinishTranscribeWithAudio(audioBlob); } catch (error) { console.error("Failed to stop recording:", error); } onFinishTranscribe?.(); }, [onFinishTranscribe, onFinishTranscribeWithAudio]); const BoundFinishTranscribeButton = require_slots.renderSlot(finishTranscribeButton, CopilotChatInput.FinishTranscribeButton, { onClick: handleFinishTranscribe }); const BoundAddMenuButton = require_slots.renderSlot(addMenuButton, CopilotChatInput.AddMenuButton, { disabled: mode === "transcribe", onAddFile, toolsMenu }); const BoundDisclaimer = require_slots.renderSlot(disclaimer, CopilotChatInput.Disclaimer, {}); const shouldShowDisclaimer = showDisclaimer ?? positioning === "absolute"; if (children) { const childProps = { textArea: BoundTextArea, audioRecorder: BoundAudioRecorder, sendButton: BoundSendButton, startTranscribeButton: BoundStartTranscribeButton, cancelTranscribeButton: BoundCancelTranscribeButton, finishTranscribeButton: BoundFinishTranscribeButton, addMenuButton: BoundAddMenuButton, disclaimer: BoundDisclaimer, onSubmitMessage, onStop, isRunning, onStartTranscribe, onCancelTranscribe, onFinishTranscribe, onAddFile, mode, toolsMenu, autoFocus, positioning, keyboardHeight, showDisclaimer: shouldShowDisclaimer }; return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", { "data-copilotkit": true, style: { display: "contents" }, children: children(childProps) }); } const handleContainerClick = (e) => { const target = e.target; if (target.tagName !== "BUTTON" && !target.closest("button") && inputRef.current && mode === "input") inputRef.current.focus(); }; const ensureMeasurements = (0, react.useCallback)(() => { const textarea = inputRef.current; if (!textarea) return; const previousValue = textarea.value; const previousHeight = textarea.style.height; textarea.style.height = "auto"; const computedStyle = window.getComputedStyle(textarea); const paddingLeft = parseFloat(computedStyle.paddingLeft) || 0; const paddingRight = parseFloat(computedStyle.paddingRight) || 0; const paddingTop = parseFloat(computedStyle.paddingTop) || 0; const paddingBottom = parseFloat(computedStyle.paddingBottom) || 0; textarea.value = ""; const singleLineHeight = textarea.scrollHeight; textarea.value = previousValue; const maxHeight = (singleLineHeight - paddingTop - paddingBottom) * 5 + paddingTop + paddingBottom; measurementsRef.current = { singleLineHeight, maxHeight, paddingLeft, paddingRight }; textarea.style.height = previousHeight; textarea.style.maxHeight = `${maxHeight}px`; }, []); const adjustTextareaHeight = (0, react.useCallback)(() => { const textarea = inputRef.current; if (!textarea) return 0; if (measurementsRef.current.singleLineHeight === 0) ensureMeasurements(); const { maxHeight } = measurementsRef.current; if (maxHeight) textarea.style.maxHeight = `${maxHeight}px`; textarea.style.height = "auto"; const scrollHeight = textarea.scrollHeight; if (maxHeight) textarea.style.height = `${Math.min(scrollHeight, maxHeight)}px`; else textarea.style.height = `${scrollHeight}px`; return scrollHeight; }, [ensureMeasurements]); const updateLayout = (0, react.useCallback)((nextLayout) => { setLayout((prev) => { if (prev === nextLayout) return prev; ignoreResizeRef.current = true; return nextLayout; }); }, []); const evaluateLayout = (0, react.useCallback)(() => { if (mode !== "input") { updateLayout("compact"); return; } if (typeof window !== "undefined" && typeof window.matchMedia === "function") { if (window.matchMedia("(max-width: 767px)").matches) { ensureMeasurements(); adjustTextareaHeight(); updateLayout("expanded"); return; } } const textarea = inputRef.current; const grid = gridRef.current; const addContainer = addButtonContainerRef.current; const actionsContainer = actionsContainerRef.current; if (!textarea || !grid || !addContainer || !actionsContainer) return; if (measurementsRef.current.singleLineHeight === 0) ensureMeasurements(); const scrollHeight = adjustTextareaHeight(); const baseline = measurementsRef.current.singleLineHeight; const hasExplicitBreak = resolvedValue.includes("\n"); const renderedMultiline = baseline > 0 ? scrollHeight > baseline + 1 : false; let shouldExpand = hasExplicitBreak || renderedMultiline; if (!shouldExpand) { const gridStyles = window.getComputedStyle(grid); const paddingLeft = parseFloat(gridStyles.paddingLeft) || 0; const paddingRight = parseFloat(gridStyles.paddingRight) || 0; const columnGap = parseFloat(gridStyles.columnGap) || 0; const gridAvailableWidth = grid.clientWidth - paddingLeft - paddingRight; if (gridAvailableWidth > 0) { const addWidth = addContainer.getBoundingClientRect().width; const actionsWidth = actionsContainer.getBoundingClientRect().width; const compactWidth = Math.max(gridAvailableWidth - addWidth - actionsWidth - columnGap * 2, 0); const canvas = measurementCanvasRef.current ?? document.createElement("canvas"); if (!measurementCanvasRef.current) measurementCanvasRef.current = canvas; const context = canvas.getContext("2d"); if (context) { const textareaStyles = window.getComputedStyle(textarea); context.font = textareaStyles.font || `${textareaStyles.fontStyle} ${textareaStyles.fontVariant} ${textareaStyles.fontWeight} ${textareaStyles.fontSize}/${textareaStyles.lineHeight} ${textareaStyles.fontFamily}`; const compactInnerWidth = Math.max(compactWidth - (measurementsRef.current.paddingLeft || 0) - (measurementsRef.current.paddingRight || 0), 0); if (compactInnerWidth > 0) { const lines = resolvedValue.length > 0 ? resolvedValue.split("\n") : [""]; let longestWidth = 0; for (const line of lines) { const metrics = context.measureText(line || " "); if (metrics.width > longestWidth) longestWidth = metrics.width; } if (longestWidth > compactInnerWidth) shouldExpand = true; } } } } updateLayout(shouldExpand ? "expanded" : "compact"); }, [ adjustTextareaHeight, ensureMeasurements, mode, resolvedValue, updateLayout ]); (0, react.useLayoutEffect)(() => { evaluateLayout(); }, [evaluateLayout]); (0, react.useEffect)(() => { if (typeof ResizeObserver === "undefined") return; const textarea = inputRef.current; const grid = gridRef.current; const addContainer = addButtonContainerRef.current; const actionsContainer = actionsContainerRef.current; if (!textarea || !grid || !addContainer || !actionsContainer) return; const scheduleEvaluation = () => { if (ignoreResizeRef.current) { ignoreResizeRef.current = false; return; } if (typeof window === "undefined") { evaluateLayout(); return; } if (resizeEvaluationRafRef.current !== null) cancelAnimationFrame(resizeEvaluationRafRef.current); resizeEvaluationRafRef.current = window.requestAnimationFrame(() => { resizeEvaluationRafRef.current = null; evaluateLayout(); }); }; const observer = new ResizeObserver(() => { scheduleEvaluation(); }); observer.observe(grid); observer.observe(addContainer); observer.observe(actionsContainer); observer.observe(textarea); return () => { observer.disconnect(); if (typeof window !== "undefined" && resizeEvaluationRafRef.current !== null) { cancelAnimationFrame(resizeEvaluationRafRef.current); resizeEvaluationRafRef.current = null; } }; }, [evaluateLayout]); const slashMenuVisible = commandQuery !== null && commandItems.length > 0; (0, react.useEffect)(() => { if (!slashMenuVisible || slashHighlightIndex < 0) return; (slashMenuRef.current?.querySelector(`[data-slash-index="${slashHighlightIndex}"]`))?.scrollIntoView({ block: "nearest" }); }, [slashMenuVisible, slashHighlightIndex]); const slashMenu = slashMenuVisible ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", { "data-testid": "copilot-slash-menu", role: "listbox", "aria-label": "Slash commands", ref: slashMenuRef, className: "cpk:absolute cpk:bottom-full cpk:left-0 cpk:right-0 cpk:z-30 cpk:mb-2 cpk:max-h-64 cpk:overflow-y-auto cpk:rounded-lg cpk:border cpk:border-border cpk:bg-white cpk:shadow-lg cpk:dark:border-[#3a3a3a] cpk:dark:bg-[#1f1f1f]", style: { maxHeight: `${SLASH_MENU_MAX_VISIBLE_ITEMS * SLASH_MENU_ITEM_HEIGHT_PX}px` }, children: filteredCommands.length === 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", { className: "cpk:px-3 cpk:py-2 cpk:text-sm cpk:text-muted-foreground", children: "No commands found" }) : filteredCommands.map((item, index) => { const isActive = index === slashHighlightIndex; return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", { type: "button", role: "option", "aria-selected": isActive, "data-active": isActive ? "true" : void 0, "data-slash-index": index, className: (0, tailwind_merge.twMerge)("cpk:w-full cpk:px-3 cpk:py-2 cpk:text-left cpk:text-sm cpk:transition-colors", "cpk:hover:bg-muted cpk:dark:hover:bg-[#2f2f2f]", isActive ? "cpk:bg-muted cpk:dark:bg-[#2f2f2f]" : "cpk:bg-transparent"), onMouseEnter: () => setSlashHighlightIndex(index), onMouseDown: (event) => { event.preventDefault(); runCommand(item); }, children: item.label }, `${item.label}-${index}`); }) }) : null; const inputPill = /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", { "data-testid": "copilot-chat-input", className: (0, tailwind_merge.twMerge)("copilotKitInput", "cpk:flex cpk:w-full cpk:flex-col cpk:items-center cpk:justify-center", "cpk:cursor-text", "cpk:overflow-visible cpk:bg-clip-padding cpk:contain-inline-size", "cpk:bg-white cpk:dark:bg-[#303030]", "cpk:shadow-[0_4px_4px_0_#0000000a,0_0_1px_0_#0000009e] cpk:rounded-[28px]"), onClick: handleContainerClick, "data-layout": isExpanded ? "expanded" : "compact", children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", { ref: gridRef, className: (0, tailwind_merge.twMerge)("cpk:grid cpk:w-full cpk:gap-x-3 cpk:gap-y-3 cpk:px-3 cpk:py-2", isExpanded ? "cpk:grid-cols-[auto_minmax(0,1fr)_auto] cpk:grid-rows-[auto_auto]" : "cpk:grid-cols-[auto_minmax(0,1fr)_auto] cpk:items-center"), "data-layout": isExpanded ? "expanded" : "compact", children: [ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", { ref: addButtonContainerRef, className: (0, tailwind_merge.twMerge)("cpk:flex cpk:items-center", isExpanded ? "cpk:row-start-2" : "cpk:row-start-1", "cpk:col-start-1"), children: BoundAddMenuButton }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", { className: (0, tailwind_merge.twMerge)("cpk:relative cpk:flex cpk:min-w-0 cpk:flex-col cpk:min-h-[50px] cpk:justify-center", isExpanded ? "cpk:col-span-3 cpk:row-start-1" : "cpk:col-start-2 cpk:row-start-1"), children: mode === "transcribe" ? BoundAudioRecorder : mode === "processing" ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", { className: "cpk:flex cpk:w-full cpk:items-center cpk:justify-center cpk:py-3 cpk:px-5", children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(lucide_react.Loader2, { className: "cpk:size-[26px] cpk:animate-spin cpk:text-muted-foreground" }) }) : /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [BoundTextArea, slashMenu] }) }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", { ref: actionsContainerRef, className: (0, tailwind_merge.twMerge)("cpk:flex cpk:items-center cpk:justify-end cpk:gap-2", isExpanded ? "cpk:col-start-3 cpk:row-start-2" : "cpk:col-start-3 cpk:row-start-1"), children: mode === "transcribe" ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [onCancelTranscribe && BoundCancelTranscribeButton, onFinishTranscribe && BoundFinishTranscribeButton] }) : /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [onStartTranscribe && BoundStartTranscribeButton, BoundSendButton] }) }) ] }) }); return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", { "data-copilotkit": true, ref: containerRef, className: require_utils.cn(positioning === "absolute" && "cpk:absolute cpk:bottom-0 cpk:left-0 cpk:right-0 cpk:z-20 cpk:pointer-events-none", className), style: { transform: keyboardHeight > 0 ? `translateY(-${keyboardHeight}px)` : void 0, transition: "transform 0.2s ease-out" }, ...props, children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", { className: "cpk:max-w-3xl cpk:mx-auto cpk:py-0 cpk:px-4 cpk:sm:px-0 cpk:[div[data-sidebar-chat]_&]:px-8 cpk:[div[data-popup-chat]_&]:px-4 cpk:pointer-events-auto", children: inputPill }), shouldShowDisclaimer && BoundDisclaimer] }); } (function(_CopilotChatInput) { _CopilotChatInput.SendButton = ({ className, children, ...props }) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", { className: "cpk:mr-[10px]", children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_button.Button, { type: "button", "data-testid": "copilot-send-button", variant: "chatInputToolbarPrimary", size: "chatInputToolbarIcon", className, ...props, children: children ?? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(lucide_react.ArrowUp, { className: "cpk:size-[18px]" }) }) }); const ToolbarButton = _CopilotChatInput.ToolbarButton = ({ icon, labelKey, defaultClassName, className, ...props }) => { const labels = require_CopilotChatConfigurationProvider.useCopilotChatConfiguration()?.labels ?? require_CopilotChatConfigurationProvider.CopilotChatDefaultLabels; return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(require_tooltip.Tooltip, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_tooltip.TooltipTrigger, { asChild: true, children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_button.Button, { type: "button", variant: "chatInputToolbarSecondary", size: "chatInputToolbarIcon", className: (0, tailwind_merge.twMerge)(defaultClassName, className), ...props, children: icon }) }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_tooltip.TooltipContent, { side: "bottom", children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", { children: labels[labelKey] }) })] }); }; _CopilotChatInput.StartTranscribeButton = (props) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ToolbarButton, { "data-testid": "copilot-start-transcribe-button", icon: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(lucide_react.Mic, { className: "cpk:size-[18px]" }), labelKey: "chatInputToolbarStartTranscribeButtonLabel", defaultClassName: "cpk:mr-2", ...props }); _CopilotChatInput.CancelTranscribeButton = (props) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ToolbarButton, { "data-testid": "copilot-cancel-transcribe-button", icon: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(lucide_react.X, { className: "cpk:size-[18px]" }), labelKey: "chatInputToolbarCancelTranscribeButtonLabel", defaultClassName: "cpk:mr-2", ...props }); _CopilotChatInput.FinishTranscribeButton = (props) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ToolbarButton, { "data-testid": "copilot-finish-transcribe-button", icon: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(lucide_react.Check, { className: "cpk:size-[18px]" }), labelKey: "chatInputToolbarFinishTranscribeButtonLabel", defaultClassName: "cpk:mr-[10px]", ...props }); _CopilotChatInput.AddMenuButton = ({ className, toolsMenu, onAddFile, disabled, ...props }) => { const labels = require_CopilotChatConfigurationProvider.useCopilotChatConfiguration()?.labels ?? require_CopilotChatConfigurationProvider.CopilotChatDefaultLabels; const menuItems = (0, react.useMemo)(() => { const items = []; if (onAddFile) items.push({ label: labels.chatInputToolbarAddButtonLabel, action: onAddFile }); if (toolsMenu && toolsMenu.length > 0) { if (items.length > 0) items.push("-"); for (const item of toolsMenu) if (item === "-") { if (items.length === 0 || items[items.length - 1] === "-") continue; items.push(item); } else items.push(item); while (items.length > 0 && items[items.length - 1] === "-") items.pop(); } return items; }, [ onAddFile, toolsMenu, labels.chatInputToolbarAddButtonLabel ]); const renderMenuItems = (0, react.useCallback)((items) => items.map((item, index) => { if (item === "-") return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_dropdown_menu.DropdownMenuSeparator, {}, `separator-${index}`); if (item.items && item.items.length > 0) return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(require_dropdown_menu.DropdownMenuSub, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_dropdown_menu.DropdownMenuSubTrigger, { children: item.label }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_dropdown_menu.DropdownMenuSubContent, { children: renderMenuItems(item.items) })] }, `group-${index}`); return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_dropdown_menu.DropdownMenuItem, { onClick: item.action, children: item.label }, `item-${index}`); }), []); const hasMenuItems = menuItems.length > 0; const isDisabled = disabled || !hasMenuItems; return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(require_dropdown_menu.DropdownMenu, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)(require_tooltip.Tooltip, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_tooltip.TooltipTrigger, { asChild: true, children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_dropdown_menu.DropdownMenuTrigger, { asChild: true, children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_button.Button, { type: "button", "data-testid": "copilot-add-menu-button", variant: "chatInputToolbarSecondary", size: "chatInputToolbarIcon", className: (0, tailwind_merge.twMerge)("cpk:ml-1", className), disabled: isDisabled, ...props, children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(lucide_react.Plus, { className: "cpk:size-[20px]" }) }) }) }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_tooltip.TooltipContent, { side: "bottom", children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("p", { className: "cpk:flex cpk:items-center cpk:gap-1 cpk:text-xs cpk:font-medium", children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: "Add files and more" }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("code", { className: "cpk:rounded cpk:bg-[#4a4a4a] cpk:px-1 cpk:py-[1px] cpk:font-mono cpk:text-[11px] cpk:text-white cpk:dark:bg-[#e0e0e0] cpk:dark:text-black", children: "/" })] }) })] }), hasMenuItems && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_dropdown_menu.DropdownMenuContent, { side: "top", align: "start", children: renderMenuItems(menuItems) })] }); }; _CopilotChatInput.TextArea = (0, react.forwardRef)(function TextArea({ style, className, autoFocus, placeholder, ...props }, ref) { const internalTextareaRef = (0, react.useRef)(null); const labels = require_CopilotChatConfigurationProvider.useCopilotChatConfiguration()?.labels ?? require_CopilotChatConfigurationProvider.CopilotChatDefaultLabels; (0, react.useImperativeHandle)(ref, () => internalTextareaRef.current); (0, react.useEffect)(() => { const textarea = internalTextareaRef.current; if (!textarea) return; const handleFocus = () => { setTimeout(() => { textarea.scrollIntoView({ behavior: "smooth", block: "nearest" }); }, 300); }; textarea.addEventListener("focus", handleFocus); return () => textarea.removeEventListener("focus", handleFocus); }, []); (0, react.useEffect)(() => { if (autoFocus) internalTextareaRef.current?.focus(); }, [autoFocus]); return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("textarea", { ref: internalTextareaRef, "data-testid": "copilot-chat-textarea", placeholder: placeholder ?? labels.chatInputPlaceholder, className: (0, tailwind_merge.twMerge)("cpk:bg-transparent cpk:outline-none cpk:antialiased cpk:font-regular cpk:leading-relaxed cpk:text-[16px] cpk:placeholder:text-[#00000077] cpk:dark:placeholder:text-[#fffc]", className), style: { overflow: "auto", resize: "none", ...style }, rows: 1, ...props }); }); _CopilotChatInput.AudioRecorder = require_CopilotChatAudioRecorder.CopilotChatAudioRecorder; _CopilotChatInput.Disclaimer = ({ className, ...props }) => { const labels = require_CopilotChatConfigurationProvider.useCopilotChatConfiguration()?.labels ?? require_CopilotChatConfigurationProvider.CopilotChatDefaultLabels; return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", { className: require_utils.cn("cpk:text-center cpk:text-xs cpk:text-muted-foreground cpk:py-3 cpk:px-4 cpk:max-w-3xl cpk:mx-auto", className), ...props, children: labels.chatDisclaimerText }); }; })(CopilotChatInput || (CopilotChatInput = {})); CopilotChatInput.TextArea.displayName = "CopilotChatInput.TextArea"; CopilotChatInput.SendButton.displayName = "CopilotChatInput.SendButton"; CopilotChatInput.ToolbarButton.displayName = "CopilotChatInput.ToolbarButton"; CopilotChatInput.StartTranscribeButton.displayName = "CopilotChatInput.StartTranscribeButton"; CopilotChatInput.CancelTranscribeButton.displayName = "CopilotChatInput.CancelTranscribeButton"; CopilotChatInput.FinishTranscribeButton.displayName = "CopilotChatInput.FinishTranscribeButton"; CopilotChatInput.AddMenuButton.displayName = "CopilotChatInput.AddMenuButton"; CopilotChatInput.Disclaimer.displayName = "CopilotChatInput.Disclaimer"; var CopilotChatInput_default = CopilotChatInput; //#endregion exports.default = CopilotChatInput_default; //# sourceMappingURL=CopilotChatInput.cjs.map