diff --git a/client/package.json b/client/package.json index aef5f4697a..27224493ce 100644 --- a/client/package.json +++ b/client/package.json @@ -39,10 +39,10 @@ "@marsidev/react-turnstile": "^1.1.0", "@mcp-ui/client": "^5.7.0", "@radix-ui/react-accordion": "^1.1.2", - "@radix-ui/react-alert-dialog": "^1.0.2", + "@radix-ui/react-alert-dialog": "^1.1.15", "@radix-ui/react-checkbox": "^1.0.3", "@radix-ui/react-collapsible": "^1.0.3", - "@radix-ui/react-dialog": "^1.0.2", + "@radix-ui/react-dialog": "^1.1.15", "@radix-ui/react-dropdown-menu": "^2.1.1", "@radix-ui/react-hover-card": "^1.0.5", "@radix-ui/react-icons": "^1.3.0", diff --git a/client/src/components/Chat/Menus/Endpoints/components/EndpointModelItem.tsx b/client/src/components/Chat/Menus/Endpoints/components/EndpointModelItem.tsx index 32a480e726..aab5b5889f 100644 --- a/client/src/components/Chat/Menus/Endpoints/components/EndpointModelItem.tsx +++ b/client/src/components/Chat/Menus/Endpoints/components/EndpointModelItem.tsx @@ -1,4 +1,4 @@ -import React from 'react'; +import React, { useRef, useState, useEffect } from 'react'; import { EarthIcon, Pin, PinOff } from 'lucide-react'; import { isAgentsEndpoint, isAssistantsEndpoint } from 'librechat-data-provider'; import { useModelSelectorContext } from '../ModelSelectorContext'; @@ -18,6 +18,26 @@ export function EndpointModelItem({ modelId, endpoint, isSelected }: EndpointMod const { handleSelectModel } = useModelSelectorContext(); const { isFavoriteModel, toggleFavoriteModel, isFavoriteAgent, toggleFavoriteAgent } = useFavorites(); + + const itemRef = useRef(null); + const [isActive, setIsActive] = useState(false); + + useEffect(() => { + const element = itemRef.current; + if (!element) { + return; + } + + const observer = new MutationObserver(() => { + setIsActive(element.hasAttribute('data-active-item')); + }); + + observer.observe(element, { attributes: true, attributeFilter: ['data-active-item'] }); + setIsActive(element.hasAttribute('data-active-item')); + + return () => observer.disconnect(); + }, []); + let isGlobal = false; let modelName = modelId; const avatarUrl = endpoint?.modelIcons?.[modelId ?? ''] || null; @@ -42,8 +62,7 @@ export function EndpointModelItem({ modelId, endpoint, isSelected }: EndpointMod ? isFavoriteAgent(modelId ?? '') : isFavoriteModel(modelId ?? '', endpoint.value); - const handleFavoriteClick = (e: React.MouseEvent) => { - e.stopPropagation(); + const handleFavoriteToggle = () => { if (!modelId) { return; } @@ -55,6 +74,11 @@ export function EndpointModelItem({ modelId, endpoint, isSelected }: EndpointMod } }; + const handleFavoriteClick = (e: React.MouseEvent) => { + e.stopPropagation(); + handleFavoriteToggle(); + }; + const renderAvatar = () => { const isAgentOrAssistant = isAgentsEndpoint(endpoint.value) || isAssistantsEndpoint(endpoint.value); @@ -84,6 +108,7 @@ export function EndpointModelItem({ modelId, endpoint, isSelected }: EndpointMod return ( handleSelectModel(endpoint, modelId ?? '')} className="group flex w-full cursor-pointer items-center justify-between rounded-lg px-2 text-sm" @@ -94,20 +119,18 @@ export function EndpointModelItem({ modelId, endpoint, isSelected }: EndpointMod {isGlobal && } {isSelected && ( diff --git a/client/src/components/Conversations/Convo.tsx b/client/src/components/Conversations/Convo.tsx index 382eace7a8..c10aad33e3 100644 --- a/client/src/components/Conversations/Convo.tsx +++ b/client/src/components/Conversations/Convo.tsx @@ -155,6 +155,9 @@ export default function Conversation({ conversation, retainView, toggleNav }: Co if (renaming) { return; } + if (e.target !== e.currentTarget) { + return; + } if (e.key === 'Enter' || e.key === ' ') { e.preventDefault(); handleNavigation(false); diff --git a/client/src/components/Conversations/ConvoOptions/ConvoOptions.tsx b/client/src/components/Conversations/ConvoOptions/ConvoOptions.tsx index aa82b3eb1d..b090027645 100644 --- a/client/src/components/Conversations/ConvoOptions/ConvoOptions.tsx +++ b/client/src/components/Conversations/ConvoOptions/ConvoOptions.tsx @@ -1,5 +1,5 @@ import { useState, useId, useRef, memo, useCallback, useMemo } from 'react'; -import * as Menu from '@ariakit/react/menu'; +import * as Ariakit from '@ariakit/react'; import { useParams, useNavigate } from 'react-router-dom'; import { QueryKeys } from 'librechat-data-provider'; import { useQueryClient } from '@tanstack/react-query'; @@ -49,6 +49,7 @@ function ConvoOptions({ const { conversationId: currentConvoId } = useParams(); const { newConversation } = useNewConvo(); + const menuId = useId(); const shareButtonRef = useRef(null); const deleteButtonRef = useRef(null); const [showShareDialog, setShowShareDialog] = useState(false); @@ -106,11 +107,11 @@ function ConvoOptions({ const isArchiveLoading = archiveConvoMutation.isLoading; const isDeleteLoading = deleteMutation.isLoading; - const handleShareClick = useCallback(() => { + const shareHandler = useCallback(() => { setShowShareDialog(true); }, []); - const handleDeleteClick = useCallback(() => { + const deleteHandler = useCallback(() => { setShowDeleteDialog(true); }, []); @@ -189,13 +190,15 @@ function ConvoOptions({ () => [ { label: localize('com_ui_share'), - onClick: handleShareClick, + onClick: shareHandler, icon: