/** * Copyright (c) 2026-present, Goldman Sachs * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ import { useRef, useLayoutEffect, useEffect, useState, useMemo } from 'react'; import { SendIcon, LoadingIcon, SquareIcon, SparkleStarsIcon, CheckIcon, clsx, } from '@finos/legend-art'; import type { LegendAIChatState, LegendAIScopeItem } from '../LegendAITypes.js'; import { LegendAIScopeSelector } from './LegendAIScopeSelector.js'; const MAX_TEXTAREA_HEIGHT = 160; export const LegendAIChatInput = (props: { state: LegendAIChatState; scopes: LegendAIScopeItem[]; }): React.ReactNode => { const { state, scopes } = props; const textareaRef = useRef(null); const modelDropdownRef = useRef(null); const [isModelDropdownOpen, setIsModelDropdownOpen] = useState(false); const modelLabel = useMemo(() => { const modelName = state.selectedModelName ?? 'Auto'; return modelName.length > 18 ? `${modelName.slice(0, 17)}...` : modelName; }, [state.selectedModelName]); const effectiveModelName = state.selectedModelName ?? state.availableModelNames[0]; useEffect(() => { if (!isModelDropdownOpen) { return undefined; } const handleClickOutside = (event: MouseEvent): void => { if ( modelDropdownRef.current && !modelDropdownRef.current.contains(event.target as Node) ) { setIsModelDropdownOpen(false); } }; const handleEscape = (event: KeyboardEvent): void => { if (event.key === 'Escape') { setIsModelDropdownOpen(false); } }; document.addEventListener('mousedown', handleClickOutside); document.addEventListener('keydown', handleEscape); return (): void => { document.removeEventListener('mousedown', handleClickOutside); document.removeEventListener('keydown', handleEscape); }; }, [isModelDropdownOpen]); useLayoutEffect(() => { const el = textareaRef.current; if (el) { el.style.height = 'auto'; const nextHeight = Math.min(el.scrollHeight, MAX_TEXTAREA_HEIGHT); el.style.height = `${nextHeight}px`; } }, [state.questionText]); return (
{state.selectedScopes.length > 0 && ( )}