diff --git a/src/apps/chat/components/composer/actile/ActilePopup.tsx b/src/apps/chat/components/composer/actile/ActilePopup.tsx index 18b664e76..81d940c97 100644 --- a/src/apps/chat/components/composer/actile/ActilePopup.tsx +++ b/src/apps/chat/components/composer/actile/ActilePopup.tsx @@ -2,7 +2,7 @@ import * as React from 'react'; import { Box, ListItem, ListItemButton, ListItemDecorator, Sheet, Typography } from '@mui/joy'; -import { CloseableMenu } from '~/common/components/CloseableMenu'; +import { CloseablePopup } from '~/common/components/CloseablePopup'; import type { ActileItem, ActileProvider } from './ActileProvider'; @@ -33,12 +33,12 @@ export function ActilePopup(props: { }, [props.itemsByProvider, props.activeItemIndex]); return ( - {!props.itemsByProvider.length && ( @@ -108,6 +108,6 @@ export function ActilePopup(props: { ))} - + ); } diff --git a/src/apps/chat/components/composer/llmattachments/LLMAttachmentMenu.tsx b/src/apps/chat/components/composer/llmattachments/LLMAttachmentMenu.tsx index 53689e4ba..80a549eb0 100644 --- a/src/apps/chat/components/composer/llmattachments/LLMAttachmentMenu.tsx +++ b/src/apps/chat/components/composer/llmattachments/LLMAttachmentMenu.tsx @@ -15,7 +15,7 @@ import ReadMoreIcon from '@mui/icons-material/ReadMore'; import VerticalAlignBottomIcon from '@mui/icons-material/VerticalAlignBottom'; import VisibilityIcon from '@mui/icons-material/Visibility'; -import { CloseableMenu } from '~/common/components/CloseableMenu'; +import { CloseablePopup } from '~/common/components/CloseablePopup'; import { DMessageAttachmentFragment, DMessageDocPart, DMessageImageRefPart, isDocPart, isImageRefPart } from '~/common/stores/chat/chat.fragments'; import { LiveFileIcon } from '~/common/livefile/liveFile.icons'; import { copyToClipboard } from '~/common/util/clipboardUtils'; @@ -151,11 +151,13 @@ export function LLMAttachmentMenu(props: { const showInputs = uiComplexityMode !== 'minimal'; return ( - {/* Move Arrows */} @@ -388,6 +390,6 @@ export function LLMAttachmentMenu(props: { Remove - + ); } diff --git a/src/apps/chat/components/composer/llmattachments/LLMAttachmentsList.tsx b/src/apps/chat/components/composer/llmattachments/LLMAttachmentsList.tsx index 8eed140ea..2c3edac90 100644 --- a/src/apps/chat/components/composer/llmattachments/LLMAttachmentsList.tsx +++ b/src/apps/chat/components/composer/llmattachments/LLMAttachmentsList.tsx @@ -9,7 +9,7 @@ import VerticalAlignBottomIcon from '@mui/icons-material/VerticalAlignBottom'; import type { AgiAttachmentPromptsData } from '~/modules/aifn/agiattachmentprompts/useAgiAttachmentPrompts'; -import { CloseableMenu } from '~/common/components/CloseableMenu'; +import { CloseablePopup } from '~/common/components/CloseablePopup'; import { ConfirmationModal } from '~/common/components/modals/ConfirmationModal'; import { useOverlayComponents } from '~/common/layout/overlays/useOverlayComponents'; @@ -205,11 +205,11 @@ export function LLMAttachmentsList(props: { {/* All Drafts Menu */} {!!overallMenuAnchor && ( - {/* uses the agiAttachmentPrompts to imagine what the user will ask aboud those */} @@ -234,7 +234,7 @@ export function LLMAttachmentsList(props: { Remove All{llmAttachmentDrafts.length > 5 ? {llmAttachmentDrafts.length} attachments : null} - + )} ; diff --git a/src/apps/chat/components/layout-drawer/ChatDrawer.tsx b/src/apps/chat/components/layout-drawer/ChatDrawer.tsx index 43f162b2c..3fb8d6c1e 100644 --- a/src/apps/chat/components/layout-drawer/ChatDrawer.tsx +++ b/src/apps/chat/components/layout-drawer/ChatDrawer.tsx @@ -15,7 +15,7 @@ import MoreVertIcon from '@mui/icons-material/MoreVert'; import StarOutlineRoundedIcon from '@mui/icons-material/StarOutlineRounded'; import type { DConversationId } from '~/common/stores/chat/chat.conversation'; -import { CloseableMenu } from '~/common/components/CloseableMenu'; +import { CloseablePopup } from '~/common/components/CloseablePopup'; import { DFolder, useFolderStore } from '~/common/stores/folders/store-chat-folders'; import { DebouncedInputMemo } from '~/common/components/DebouncedInput'; import { FoldersToggleOff } from '~/common/components/icons/FoldersToggleOff'; @@ -410,12 +410,12 @@ function ChatDrawer(props: { {/* [Menu] Chat Item Folder Change */} {!!folderChangeRequest?.anchorEl && ( - {/* Folder Assignment Buttons */} @@ -449,7 +449,7 @@ function ChatDrawer(props: { )} - + )} ; diff --git a/src/apps/chat/components/layout-drawer/folders/FolderListItem.tsx b/src/apps/chat/components/layout-drawer/folders/FolderListItem.tsx index 36618f64a..86b769276 100644 --- a/src/apps/chat/components/layout-drawer/folders/FolderListItem.tsx +++ b/src/apps/chat/components/layout-drawer/folders/FolderListItem.tsx @@ -9,7 +9,7 @@ import EditRoundedIcon from '@mui/icons-material/EditRounded'; import FolderIcon from '@mui/icons-material/Folder'; import MoreVertIcon from '@mui/icons-material/MoreVert'; -import { CloseableMenu } from '~/common/components/CloseableMenu'; +import { CloseablePopup } from '~/common/components/CloseablePopup'; import { DFolder, FOLDERS_COLOR_PALETTE, useFolderStore } from '~/common/stores/folders/store-chat-folders'; import { InlineTextarea } from '~/common/components/InlineTextarea'; import { themeZIndexOverMobileDrawer } from '~/common/app.theme'; @@ -203,11 +203,12 @@ export function FolderListItem(props: { {!!menuAnchorEl && ( - - + )} diff --git a/src/apps/chat/components/message/ChatMessage.tsx b/src/apps/chat/components/message/ChatMessage.tsx index a72113998..4852acb54 100644 --- a/src/apps/chat/components/message/ChatMessage.tsx +++ b/src/apps/chat/components/message/ChatMessage.tsx @@ -35,7 +35,7 @@ import { ModelVendorAnthropic } from '~/modules/llms/vendors/anthropic/anthropic import { AnthropicIcon } from '~/common/components/icons/vendors/AnthropicIcon'; import { ChatBeamIcon } from '~/common/components/icons/ChatBeamIcon'; -import { CloseableMenu } from '~/common/components/CloseableMenu'; +import { CloseablePopup } from '~/common/components/CloseablePopup'; import { DMessage, DMessageId, DMessageUserFlag, DMetaReferenceItem, MESSAGE_FLAG_AIX_SKIP, MESSAGE_FLAG_NOTIFY_COMPLETE, MESSAGE_FLAG_STARRED, MESSAGE_FLAG_VND_ANT_CACHE_AUTO, MESSAGE_FLAG_VND_ANT_CACHE_USER, messageFragmentsReduceText, messageHasUserFlag } from '~/common/stores/chat/chat.message'; import { KeyStroke } from '~/common/components/KeyStroke'; import { MarkHighlightIcon } from '~/common/components/icons/MarkHighlightIcon'; @@ -796,10 +796,11 @@ export function ChatMessage(props: { {/* Message Operations Menu (3 dots) */} {!!opsMenuAnchor && ( - {fromSystem && ( @@ -946,7 +947,7 @@ export function ChatMessage(props: { : Beam Edit} )} - + )} @@ -1049,10 +1050,11 @@ export function ChatMessage(props: { {/* Context (Right-click) Menu */} {!!contextMenuAnchor && ( - @@ -1071,7 +1073,7 @@ export function ChatMessage(props: { {props.isSpeaking ? : } Speak } - + )} diff --git a/src/apps/chat/execute-mode/ExecuteModeMenu.tsx b/src/apps/chat/execute-mode/ExecuteModeMenu.tsx index 808b8e7a2..827be100a 100644 --- a/src/apps/chat/execute-mode/ExecuteModeMenu.tsx +++ b/src/apps/chat/execute-mode/ExecuteModeMenu.tsx @@ -2,7 +2,7 @@ import * as React from 'react'; import { Box, MenuItem, Radio, Typography } from '@mui/joy'; -import { CloseableMenu } from '~/common/components/CloseableMenu'; +import { CloseablePopup } from '~/common/components/CloseablePopup'; import { KeyStroke, platformAwareKeystrokes } from '~/common/components/KeyStroke'; import { useUIPreferencesStore } from '~/common/state/store-ui'; @@ -23,10 +23,10 @@ export function ExecuteModeMenu(props: { const enterIsNewline = useUIPreferencesStore(state => state.enterIsNewline); return ( - {/**/} @@ -60,7 +60,7 @@ export function ExecuteModeMenu(props: { , )} - + ); } diff --git a/src/common/components/CloseableMenu.tsx b/src/common/components/CloseableMenu.tsx deleted file mode 100644 index 6cbb3f228..000000000 --- a/src/common/components/CloseableMenu.tsx +++ /dev/null @@ -1,100 +0,0 @@ -import * as React from 'react'; - -import { ClickAwayListener, Popper, PopperPlacementType } from '@mui/base'; -import { MenuList, styled } from '@mui/joy'; -import { SxProps } from '@mui/joy/styles/types'; - - -// adds the 'sx' prop to the Popper, and defaults zIndex to 1000 -const Popup = styled(Popper)({ - zIndex: 1000, -}); - - -/** - * Workaround to the Menu in Joy 5-beta.0. - * - * This component addresses major changes in the Menu component in Joy 5-beta.0: - * - missing callback for onClose - * - clickaway listener not working - * - dynamic menus unsupported - * - ... - */ -export function CloseableMenu(props: { - open: boolean, anchorEl: HTMLElement | null, onClose: () => void, - dense?: boolean, - bigIcons?: boolean, - // variant?: VariantProp, - // color?: ColorPaletteProp, - // size?: 'sm' | 'md' | 'lg', - placement?: PopperPlacementType, - placementOffset?: number[], - maxHeightGapPx?: number, - noTopPadding?: boolean, - noBottomPadding?: boolean, - sx?: SxProps, - zIndex?: number, - listRef?: React.Ref, - children?: React.ReactNode, -}) { - - const handleClose = (event: MouseEvent | TouchEvent | React.KeyboardEvent) => { - event.stopPropagation(); - props.onClose(); - }; - - const handleListKeyDown = (event: React.KeyboardEvent) => { - if (event.key === 'Tab') { - handleClose(event); - } else if (event.key === 'Escape') { - if (props.anchorEl) - props.anchorEl?.focus(); - handleClose(event); - } - }; - - return ( - - - - {props.children} - - - - ); -} \ No newline at end of file diff --git a/src/common/components/CloseablePopup.tsx b/src/common/components/CloseablePopup.tsx new file mode 100644 index 000000000..fd6fc920d --- /dev/null +++ b/src/common/components/CloseablePopup.tsx @@ -0,0 +1,120 @@ +import * as React from 'react'; + +import type { SxProps } from '@mui/joy/styles/types'; +import { Box, MenuList, styled } from '@mui/joy'; +import { ClickAwayListener, Popper, PopperPlacementType } from '@mui/base'; + + +// adds the 'sx' prop to the Popper, and defaults zIndex to 1000 +const Popup = styled(Popper)({ + zIndex: 1000, +}); + + +/** + * Workaround to the Menu in Joy 5-beta.0. + * + * This component addresses major changes in the Menu component in Joy 5-beta.0: + * - missing callback for onClose + * - clickaway listener not working + * - dynamic menus unsupported + * - ... + */ +export function CloseablePopup(props: { + menu?: boolean, // whether to render as a MenuList (or as a Box otherwise) + anchorEl: HTMLElement | null, + onClose: () => void, + + // looks + dense?: boolean, + bigIcons?: boolean, + + placement?: PopperPlacementType, + maxHeightGapPx?: number, + noTopPadding?: boolean, + noBottomPadding?: boolean, + minWidth?: number, + maxWidth?: number, + zIndex?: number, + sx?: SxProps, + + // unused + placementOffset?: number[], + + children?: React.ReactNode, +}) { + + const handleClose = (event: MouseEvent | TouchEvent | React.KeyboardEvent) => { + event.stopPropagation(); + props.onClose(); + }; + + const handleKeyDown = (event: React.KeyboardEvent) => { + if (event.key === 'Tab') { + handleClose(event); + } else if (event.key === 'Escape') { + if (props.anchorEl) + props.anchorEl?.focus(); + handleClose(event); + } + }; + + + // memos + const modifiersMemo = React.useMemo(() => [{ + name: 'offset', + options: { + offset: props.placementOffset || [0, 4], + }, + }], [props.placementOffset]); + + const styleMemoSx: SxProps = React.useMemo(() => ({ + + // style + backgroundColor: 'background.popup', + boxShadow: 'md', + ...(props.maxHeightGapPx !== undefined ? { maxHeight: `calc(100dvh - ${props.maxHeightGapPx}px)`, overflowY: 'auto' } : {}), + ...(props.maxWidth !== undefined && { maxWidth: props.maxWidth }), + ...(props.minWidth !== undefined && { minWidth: props.minWidth }), + + // MenuList customizations + '--ListItem-minHeight': props.dense + ? '2.25rem' /* 2.25 is the default */ + : '2.5rem', /* we enlarge the default */ + ...(props.bigIcons && { + '--Icon-fontSize': 'var(--joy-fontSize-xl2)', + // '--ListItemDecorator-size': '2.75rem', + }), + ...(props.noBottomPadding && { pb: 0 }), + ...(props.noTopPadding && { pt: 0 }), + + // inject + ...(props.sx || {}), + + }), [props.dense, props.bigIcons, props.maxHeightGapPx, props.maxWidth, props.minWidth, props.noBottomPadding, props.noTopPadding, props.sx]); + + + return ( + + + {props.menu ? ( + + {props.children} + + ) : ( + + {props.children} + + )} + + + ); +} \ No newline at end of file diff --git a/src/common/layout/optima/bar/OptimaBar.tsx b/src/common/layout/optima/bar/OptimaBar.tsx index 3ba2b3226..87e016aa7 100644 --- a/src/common/layout/optima/bar/OptimaBar.tsx +++ b/src/common/layout/optima/bar/OptimaBar.tsx @@ -9,7 +9,7 @@ import NavigateNextIcon from '@mui/icons-material/NavigateNext'; import { AgiSquircleIcon } from '~/common/components/icons/AgiSquircleIcon'; import { Brand } from '~/common/app.config'; -import { CloseableMenu } from '~/common/components/CloseableMenu'; +import { CloseablePopup } from '~/common/components/CloseablePopup'; import { LayoutSidebarRight } from '~/common/components/icons/LayoutSidebarRight'; import { Link } from '~/common/components/Link'; import { ROUTE_INDEX } from '~/common/app.routes'; @@ -124,18 +124,18 @@ function RenderAsPopupDesktopOnly(props: { return null; return ( - {/* contents rendered in a desktop popup menu */} {props.menuContent} - + ); } diff --git a/src/common/stores/workspace/WorkspaceLiveFilePicker.tsx b/src/common/stores/workspace/WorkspaceLiveFilePicker.tsx index 9554dfb8d..463a8a166 100644 --- a/src/common/stores/workspace/WorkspaceLiveFilePicker.tsx +++ b/src/common/stores/workspace/WorkspaceLiveFilePicker.tsx @@ -5,7 +5,7 @@ import ClearIcon from '@mui/icons-material/Clear'; import CodeIcon from '@mui/icons-material/Code'; import type { LiveFileId, LiveFileMetadata } from '~/common/livefile/liveFile.types'; -import { CloseableMenu } from '~/common/components/CloseableMenu'; +import { CloseablePopup } from '~/common/components/CloseablePopup'; import { LiveFileChooseIcon, LiveFileIcon } from '~/common/livefile/liveFile.icons'; import { TooltipOutlined } from '~/common/components/TooltipOutlined'; import { getFirstFileSystemFileHandle } from '~/common/util/fileSystemUtils'; @@ -146,14 +146,10 @@ export function WorkspaceLiveFilePicker(props: { {/* Select/Upload file menu */} {!!menuAnchor && ( - {/* Workspace Files (if any) */} @@ -198,7 +194,7 @@ export function WorkspaceLiveFilePicker(props: { )} - + )} ; diff --git a/src/modules/blocks/enhanced-code/EnhancedRenderCodeMenu.tsx b/src/modules/blocks/enhanced-code/EnhancedRenderCodeMenu.tsx index 3b62a31a2..fe789c2b4 100644 --- a/src/modules/blocks/enhanced-code/EnhancedRenderCodeMenu.tsx +++ b/src/modules/blocks/enhanced-code/EnhancedRenderCodeMenu.tsx @@ -9,7 +9,7 @@ import UnfoldLessIcon from '@mui/icons-material/UnfoldLess'; import UnfoldMoreIcon from '@mui/icons-material/UnfoldMore'; import SaveAsOutlinedIcon from '@mui/icons-material/SaveAsOutlined'; -import { CloseableMenu } from '~/common/components/CloseableMenu'; +import { CloseablePopup } from '~/common/components/CloseablePopup'; import { copyToClipboard } from '~/common/util/clipboardUtils'; import { isLiveFileSupported } from '~/common/livefile/store-live-file'; import { reverseLookupMdTitle, reverseLookupMimeType } from '~/common/attachment-drafts/attachment.mimetypes'; @@ -110,11 +110,11 @@ export function EnhancedRenderCodeMenu(props: { return ( - @@ -155,6 +155,6 @@ export function EnhancedRenderCodeMenu(props: { {/* */} {/*)}*/} - + ); } \ No newline at end of file diff --git a/src/modules/llms/models-modal/ModelsServiceSelector.tsx b/src/modules/llms/models-modal/ModelsServiceSelector.tsx index 6fad87c4a..1b5472c6b 100644 --- a/src/modules/llms/models-modal/ModelsServiceSelector.tsx +++ b/src/modules/llms/models-modal/ModelsServiceSelector.tsx @@ -5,7 +5,7 @@ import AddIcon from '@mui/icons-material/Add'; import DeleteOutlineIcon from '@mui/icons-material/DeleteOutline'; import type { DModelsService, DModelsServiceId } from '~/common/stores/llms/modelsservice.types'; -import { CloseableMenu } from '~/common/components/CloseableMenu'; +import { CloseablePopup } from '~/common/components/CloseablePopup'; import { ConfirmationModal } from '~/common/components/modals/ConfirmationModal'; import { llmsStoreActions, llmsStoreState } from '~/common/stores/llms/store-llms'; import { themeZIndexOverMobileDrawer } from '~/common/app.theme'; @@ -218,13 +218,14 @@ export function ModelsServiceSelector(props: { {/* vendors popup, for adding */} - {vendorComponents} - + );