mirror of
https://github.com/simstudioai/sim.git
synced 2026-01-19 20:08:04 -05:00
cleanup
This commit is contained in:
@@ -38,7 +38,6 @@ const SCOPE_DESCRIPTIONS: Record<string, string> = {
|
||||
'https://www.googleapis.com/auth/gmail.modify': 'View and manage email messages',
|
||||
'https://www.googleapis.com/auth/drive.file': 'View and manage Google Drive files',
|
||||
'https://www.googleapis.com/auth/drive': 'Access all Google Drive files',
|
||||
'https://www.googleapis.com/auth/drive.readonly': 'View Google Drive files',
|
||||
'https://www.googleapis.com/auth/calendar': 'View and manage calendar',
|
||||
'https://www.googleapis.com/auth/userinfo.email': 'View email address',
|
||||
'https://www.googleapis.com/auth/userinfo.profile': 'View basic profile info',
|
||||
|
||||
@@ -29,7 +29,6 @@ const findFolderInNested = (
|
||||
if (folderId === targetFolderId) {
|
||||
return nestedTag
|
||||
}
|
||||
// Recursively search in nested children
|
||||
if (nestedTag.nestedChildren) {
|
||||
const found = findFolderInNested(nestedTag.nestedChildren, blockId, targetFolderId)
|
||||
if (found) return found
|
||||
@@ -67,7 +66,6 @@ const findFolderInfoForTag = (
|
||||
nestedTag,
|
||||
}
|
||||
}
|
||||
// Recursively search in nested children
|
||||
if (nestedTag.nestedChildren) {
|
||||
const found = findFolderInfoForTag(nestedTag.nestedChildren, targetTag, group)
|
||||
if (found) return found
|
||||
@@ -82,7 +80,6 @@ const findFolderInfoForTag = (
|
||||
*/
|
||||
const isChildOfAnyFolder = (nestedTags: NestedTag[], tag: string): boolean => {
|
||||
for (const nestedTag of nestedTags) {
|
||||
// Check in leaf children
|
||||
if (nestedTag.children) {
|
||||
for (const child of nestedTag.children) {
|
||||
if (child.fullTag === tag) {
|
||||
@@ -90,14 +87,12 @@ const isChildOfAnyFolder = (nestedTags: NestedTag[], tag: string): boolean => {
|
||||
}
|
||||
}
|
||||
}
|
||||
// Check if this is a nested folder's parent tag (should be hidden at root)
|
||||
if (nestedTag.nestedChildren) {
|
||||
for (const nestedChild of nestedTag.nestedChildren) {
|
||||
if (nestedChild.parentTag === tag) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
// Recursively check deeper nested children
|
||||
if (isChildOfAnyFolder(nestedTag.nestedChildren, tag)) {
|
||||
return true
|
||||
}
|
||||
@@ -122,14 +117,11 @@ export const KeyboardNavigationHandler: React.FC<KeyboardNavigationHandlerProps>
|
||||
const nestedPath = nestedNav?.nestedPath ?? []
|
||||
|
||||
if (isInFolder && currentFolder) {
|
||||
// Determine the current folder to show based on nested navigation
|
||||
let currentNestedTag: NestedTag | null = null
|
||||
|
||||
if (nestedPath.length > 0) {
|
||||
// We're in nested navigation - use the deepest nested tag
|
||||
currentNestedTag = nestedPath[nestedPath.length - 1]
|
||||
} else {
|
||||
// At base folder level - find the folder from currentFolder ID
|
||||
for (const group of nestedBlockTagGroups) {
|
||||
const folder = findFolderInNested(group.nestedTags, group.blockId, currentFolder)
|
||||
if (folder) {
|
||||
@@ -140,7 +132,6 @@ export const KeyboardNavigationHandler: React.FC<KeyboardNavigationHandlerProps>
|
||||
}
|
||||
|
||||
if (currentNestedTag) {
|
||||
// First, add the parent tag itself (so it's navigable as the first item)
|
||||
if (currentNestedTag.parentTag) {
|
||||
const parentIdx = flatTagList.findIndex(
|
||||
(item) => item.tag === currentNestedTag!.parentTag
|
||||
@@ -149,7 +140,6 @@ export const KeyboardNavigationHandler: React.FC<KeyboardNavigationHandlerProps>
|
||||
indices.push(parentIdx)
|
||||
}
|
||||
}
|
||||
// Add all leaf children
|
||||
if (currentNestedTag.children) {
|
||||
for (const child of currentNestedTag.children) {
|
||||
const idx = flatTagList.findIndex((item) => item.tag === child.fullTag)
|
||||
@@ -158,7 +148,6 @@ export const KeyboardNavigationHandler: React.FC<KeyboardNavigationHandlerProps>
|
||||
}
|
||||
}
|
||||
}
|
||||
// Add nested children parent tags (for subfolder navigation)
|
||||
if (currentNestedTag.nestedChildren) {
|
||||
for (const nestedChild of currentNestedTag.nestedChildren) {
|
||||
if (nestedChild.parentTag) {
|
||||
@@ -171,12 +160,9 @@ export const KeyboardNavigationHandler: React.FC<KeyboardNavigationHandlerProps>
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// We're at root level, show all non-child items
|
||||
// (variables and parent tags, but not their children)
|
||||
for (let i = 0; i < flatTagList.length; i++) {
|
||||
const tag = flatTagList[i].tag
|
||||
|
||||
// Check if this is a child of a parent folder
|
||||
let isChild = false
|
||||
for (const group of nestedBlockTagGroups) {
|
||||
if (isChildOfAnyFolder(group.nestedTags, tag)) {
|
||||
@@ -194,15 +180,11 @@ export const KeyboardNavigationHandler: React.FC<KeyboardNavigationHandlerProps>
|
||||
return indices
|
||||
}, [isInFolder, currentFolder, flatTagList, nestedBlockTagGroups, nestedNav])
|
||||
|
||||
// Track nested path length for dependency
|
||||
const nestedPathLength = nestedNav?.nestedPath.length ?? 0
|
||||
|
||||
// Auto-select first visible item when entering/exiting folders or navigating nested
|
||||
// This effect only runs when folder navigation state changes, not on every render
|
||||
useEffect(() => {
|
||||
if (!visible || visibleIndices.length === 0) return
|
||||
|
||||
// Select first visible item when entering a folder or navigating nested
|
||||
setSelectedIndex(visibleIndices[0])
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [visible, isInFolder, currentFolder, nestedPathLength])
|
||||
@@ -237,7 +219,6 @@ export const KeyboardNavigationHandler: React.FC<KeyboardNavigationHandlerProps>
|
||||
} | null = null
|
||||
|
||||
if (selected) {
|
||||
// Find if selected tag can be expanded (is a folder)
|
||||
for (const group of nestedBlockTagGroups) {
|
||||
const folderInfo = findFolderInfoForTag(group.nestedTags, selected.tag, group)
|
||||
if (folderInfo) {
|
||||
@@ -278,8 +259,6 @@ export const KeyboardNavigationHandler: React.FC<KeyboardNavigationHandlerProps>
|
||||
e.preventDefault()
|
||||
e.stopPropagation()
|
||||
if (selected && selectedIndex >= 0 && selectedIndex < flatTagList.length) {
|
||||
// Always select the tag, even for folders
|
||||
// Use Arrow Right to navigate into folders
|
||||
handleTagSelect(selected.tag, selected.group)
|
||||
}
|
||||
break
|
||||
@@ -288,10 +267,8 @@ export const KeyboardNavigationHandler: React.FC<KeyboardNavigationHandlerProps>
|
||||
e.preventDefault()
|
||||
e.stopPropagation()
|
||||
if (isInFolder && nestedNav) {
|
||||
// Already in a folder - use nested navigation to go deeper
|
||||
nestedNav.navigateIn(currentFolderInfo.nestedTag, currentFolderInfo.group)
|
||||
} else {
|
||||
// At root level - open the folder normally
|
||||
openFolderWithSelection(
|
||||
currentFolderInfo.id,
|
||||
currentFolderInfo.title,
|
||||
@@ -305,13 +282,9 @@ export const KeyboardNavigationHandler: React.FC<KeyboardNavigationHandlerProps>
|
||||
if (isInFolder) {
|
||||
e.preventDefault()
|
||||
e.stopPropagation()
|
||||
// Try to navigate back in nested path first
|
||||
if (nestedNav?.navigateBack()) {
|
||||
// Successfully navigated back one level in nested navigation
|
||||
// Selection will be handled by the auto-select effect
|
||||
return
|
||||
}
|
||||
// At root folder level, close the folder entirely
|
||||
closeFolder()
|
||||
let firstRootIndex = 0
|
||||
for (let i = 0; i < flatTagList.length; i++) {
|
||||
|
||||
@@ -340,12 +340,10 @@ interface TagTreeNode {
|
||||
const buildNestedTagTree = (tags: string[], blockName: string): NestedTag[] => {
|
||||
const root: TagTreeNode = { key: 'root', children: new Map() }
|
||||
|
||||
// Build tree from tags
|
||||
for (const tag of tags) {
|
||||
const parts = tag.split('.')
|
||||
if (parts.length < 2) continue // Skip root-only tags
|
||||
if (parts.length < 2) continue
|
||||
|
||||
// Skip the blockname part, start from the first property
|
||||
const pathParts = parts.slice(1)
|
||||
let current = root
|
||||
|
||||
@@ -359,7 +357,6 @@ const buildNestedTagTree = (tags: string[], blockName: string): NestedTag[] => {
|
||||
}
|
||||
const node = current.children.get(part)!
|
||||
|
||||
// If this is the last part, store the full tag
|
||||
if (i === pathParts.length - 1) {
|
||||
node.fullTag = tag
|
||||
}
|
||||
@@ -367,7 +364,6 @@ const buildNestedTagTree = (tags: string[], blockName: string): NestedTag[] => {
|
||||
}
|
||||
}
|
||||
|
||||
// Convert tree to NestedTag array
|
||||
const convertToNestedTags = (
|
||||
node: TagTreeNode,
|
||||
parentPath: string,
|
||||
@@ -380,17 +376,14 @@ const buildNestedTagTree = (tags: string[], blockName: string): NestedTag[] => {
|
||||
const parentTag = `${blockPrefix}.${currentPath}`
|
||||
|
||||
if (child.children.size === 0) {
|
||||
// Leaf node
|
||||
result.push({
|
||||
key: currentPath,
|
||||
display: key,
|
||||
fullTag: child.fullTag || parentTag,
|
||||
})
|
||||
} else {
|
||||
// Folder node - may have both leaf value and children
|
||||
const nestedChildren = convertToNestedTags(child, currentPath, blockPrefix)
|
||||
|
||||
// Separate leaf children from nested folders
|
||||
const leafChildren: NestedTagChild[] = []
|
||||
const folders: NestedTag[] = []
|
||||
|
||||
@@ -483,10 +476,8 @@ const FolderContentsInner: React.FC<FolderContentsProps> = ({
|
||||
nestedTag,
|
||||
onNavigateIn,
|
||||
}) => {
|
||||
// Get the current folder based on nested path
|
||||
const currentNestedTag = nestedPath.length > 0 ? nestedPath[nestedPath.length - 1] : nestedTag
|
||||
|
||||
// Find parent tag index for highlighting
|
||||
const parentTagIndex = currentNestedTag.parentTag
|
||||
? flatTagList.findIndex((item) => item.tag === currentNestedTag.parentTag)
|
||||
: -1
|
||||
@@ -609,7 +600,6 @@ const FolderContents: React.FC<NestedTagRendererProps> = (props) => {
|
||||
|
||||
const nestedPath = nestedNav?.nestedPath ?? []
|
||||
|
||||
// Register this folder when it becomes active
|
||||
useEffect(() => {
|
||||
if (nestedNav && currentFolder) {
|
||||
const folderId = `${props.group.blockId}-${props.nestedTag.key}`
|
||||
@@ -647,7 +637,6 @@ const NestedTagRenderer: React.FC<NestedTagRendererProps> = ({
|
||||
const hasChildren = nestedTag.children && nestedTag.children.length > 0
|
||||
const hasNestedChildren = nestedTag.nestedChildren && nestedTag.nestedChildren.length > 0
|
||||
|
||||
// If this tag has children (leaf or nested), render as a folder
|
||||
if (hasChildren || hasNestedChildren) {
|
||||
const folderId = `${group.blockId}-${nestedTag.key}`
|
||||
|
||||
@@ -863,7 +852,6 @@ export const TagDropdown: React.FC<TagDropdownProps> = ({
|
||||
const [selectedIndex, setSelectedIndex] = useState(0)
|
||||
const itemRefs = useRef<Map<number, HTMLElement>>(new Map())
|
||||
|
||||
// Nested navigation state - supports unlimited nesting depth
|
||||
const [nestedPath, setNestedPath] = useState<NestedTag[]>([])
|
||||
const baseFolderRef = useRef<{
|
||||
id: string
|
||||
@@ -1578,31 +1566,25 @@ export const TagDropdown: React.FC<TagDropdownProps> = ({
|
||||
list.push({ tag })
|
||||
})
|
||||
|
||||
// Recursively flatten nested tags
|
||||
const flattenNestedTag = (nestedTag: NestedTag, group: BlockTagGroup, rootTag: string) => {
|
||||
// Skip if this is the root tag (already added)
|
||||
if (nestedTag.fullTag === rootTag) {
|
||||
return
|
||||
}
|
||||
|
||||
// Add parent tag for folders
|
||||
if (nestedTag.parentTag) {
|
||||
list.push({ tag: nestedTag.parentTag, group })
|
||||
}
|
||||
|
||||
// Add the tag itself if it's a leaf
|
||||
if (nestedTag.fullTag && !nestedTag.children && !nestedTag.nestedChildren) {
|
||||
list.push({ tag: nestedTag.fullTag, group })
|
||||
}
|
||||
|
||||
// Add leaf children
|
||||
if (nestedTag.children) {
|
||||
nestedTag.children.forEach((child) => {
|
||||
list.push({ tag: child.fullTag, group })
|
||||
})
|
||||
}
|
||||
|
||||
// Recursively process nested children
|
||||
if (nestedTag.nestedChildren) {
|
||||
nestedTag.nestedChildren.forEach((nestedChild) => {
|
||||
flattenNestedTag(nestedChild, group, rootTag)
|
||||
@@ -1727,15 +1709,12 @@ export const TagDropdown: React.FC<TagDropdownProps> = ({
|
||||
[inputValue, cursorPosition, workflowVariables, onSelect, onClose, getMergedSubBlocks]
|
||||
)
|
||||
|
||||
// Keep ref updated for nested navigation
|
||||
handleTagSelectRef.current = handleTagSelect
|
||||
|
||||
// Get popover context for nested navigation (will be available inside Popover)
|
||||
const popoverContextRef = useRef<{
|
||||
openFolder: (id: string, title: string, onLoad?: () => void, onSelect?: () => void) => void
|
||||
} | null>(null)
|
||||
|
||||
// Create nested navigation context value
|
||||
const nestedNavigationValue = useMemo<NestedNavigationContextValue>(
|
||||
() => ({
|
||||
nestedPath,
|
||||
@@ -1745,12 +1724,10 @@ export const TagDropdown: React.FC<TagDropdownProps> = ({
|
||||
|
||||
setNestedPath((prev) => [...prev, tag])
|
||||
|
||||
// Reset scroll to top when navigating into a folder
|
||||
if (scrollAreaRef.current) {
|
||||
scrollAreaRef.current.scrollTop = 0
|
||||
}
|
||||
|
||||
// Update popover's folder title to show current nested folder
|
||||
const selectionCallback = () => {
|
||||
if (tag.parentTag && handleTagSelectRef.current) {
|
||||
handleTagSelectRef.current(tag.parentTag, group)
|
||||
@@ -1772,7 +1749,6 @@ export const TagDropdown: React.FC<TagDropdownProps> = ({
|
||||
setNestedPath(newPath)
|
||||
|
||||
if (newPath.length === 0) {
|
||||
// Going back to root folder level
|
||||
const selectionCallback = () => {
|
||||
if (baseFolder.baseTag.parentTag && handleTagSelectRef.current) {
|
||||
handleTagSelectRef.current(baseFolder.baseTag.parentTag, baseFolder.group)
|
||||
@@ -1785,7 +1761,6 @@ export const TagDropdown: React.FC<TagDropdownProps> = ({
|
||||
selectionCallback
|
||||
)
|
||||
} else {
|
||||
// Going back to a nested folder
|
||||
const parentTag = newPath[newPath.length - 1]
|
||||
const selectionCallback = () => {
|
||||
if (parentTag.parentTag && handleTagSelectRef.current) {
|
||||
@@ -1803,7 +1778,6 @@ export const TagDropdown: React.FC<TagDropdownProps> = ({
|
||||
},
|
||||
registerFolder: (folderId, folderTitle, baseTag, group) => {
|
||||
baseFolderRef.current = { id: folderId, title: folderTitle, baseTag, group }
|
||||
// Reset scroll to top when entering a folder
|
||||
if (scrollAreaRef.current) {
|
||||
scrollAreaRef.current.scrollTop = 0
|
||||
}
|
||||
@@ -1812,7 +1786,6 @@ export const TagDropdown: React.FC<TagDropdownProps> = ({
|
||||
[nestedPath]
|
||||
)
|
||||
|
||||
// Reset nested path when popover closes
|
||||
useEffect(() => {
|
||||
if (!visible) {
|
||||
setNestedPath([])
|
||||
|
||||
@@ -34,16 +34,13 @@ function ColorGrid({
|
||||
const gridRef = useRef<HTMLDivElement>(null)
|
||||
const buttonRefs = useRef<(HTMLButtonElement | null)[]>([])
|
||||
|
||||
// Focus the grid when entering the folder
|
||||
useEffect(() => {
|
||||
if (isInFolder && gridRef.current) {
|
||||
// Find the currently selected color or default to first
|
||||
const selectedIndex = WORKFLOW_COLORS.findIndex(
|
||||
({ color }) => color.toLowerCase() === hexInput.toLowerCase()
|
||||
)
|
||||
const initialIndex = selectedIndex >= 0 ? selectedIndex : 0
|
||||
setFocusedIndex(initialIndex)
|
||||
// Small delay to let the folder animation complete
|
||||
setTimeout(() => {
|
||||
buttonRefs.current[initialIndex]?.focus()
|
||||
}, 50)
|
||||
|
||||
@@ -433,17 +433,14 @@ const PopoverContent = React.forwardRef<
|
||||
|
||||
const effectiveSideOffset = sideOffset ?? (side === 'top' ? 20 : 14)
|
||||
|
||||
// Switch to mouse mode when mouse moves
|
||||
const handleMouseMove = React.useCallback(() => {
|
||||
if (context?.isKeyboardNav) {
|
||||
context.setKeyboardNav(false)
|
||||
}
|
||||
}, [context])
|
||||
|
||||
// Track menu items for keyboard navigation
|
||||
const contentRef = React.useRef<HTMLDivElement>(null)
|
||||
|
||||
// Merge refs
|
||||
const mergedRef = React.useCallback(
|
||||
(node: HTMLDivElement | null) => {
|
||||
contentRef.current = node
|
||||
@@ -456,12 +453,10 @@ const PopoverContent = React.forwardRef<
|
||||
[ref]
|
||||
)
|
||||
|
||||
// Keyboard navigation handler - use window listener to ensure events are captured
|
||||
React.useEffect(() => {
|
||||
if (!context) return
|
||||
|
||||
const handleKeyDown = (e: KeyboardEvent) => {
|
||||
// Get content element inside handler to ensure it's current
|
||||
const content = contentRef.current
|
||||
if (!content) return
|
||||
|
||||
@@ -477,7 +472,6 @@ const PopoverContent = React.forwardRef<
|
||||
e.preventDefault()
|
||||
e.stopPropagation()
|
||||
context.setKeyboardNav(true)
|
||||
// If no selection, start at first item; otherwise move down
|
||||
if (currentIndex < 0) {
|
||||
context.setSelectedIndex(0)
|
||||
} else {
|
||||
@@ -488,7 +482,6 @@ const PopoverContent = React.forwardRef<
|
||||
e.preventDefault()
|
||||
e.stopPropagation()
|
||||
context.setKeyboardNav(true)
|
||||
// If no selection, start at last item; otherwise move up
|
||||
if (currentIndex < 0) {
|
||||
context.setSelectedIndex(items.length - 1)
|
||||
} else {
|
||||
@@ -509,12 +502,10 @@ const PopoverContent = React.forwardRef<
|
||||
}
|
||||
}
|
||||
|
||||
// Use capture phase to ensure we get the event
|
||||
window.addEventListener('keydown', handleKeyDown, true)
|
||||
return () => window.removeEventListener('keydown', handleKeyDown, true)
|
||||
}, [context])
|
||||
|
||||
// Scroll selected item into view
|
||||
React.useEffect(() => {
|
||||
const content = contentRef.current
|
||||
if (!content || !context?.isKeyboardNav || context.selectedIndex < 0) return
|
||||
@@ -684,7 +675,6 @@ const PopoverItem = React.forwardRef<HTMLDivElement, PopoverItemProps>(
|
||||
const itemRef = React.useRef<HTMLDivElement>(null)
|
||||
const [itemIndex, setItemIndex] = React.useState(-1)
|
||||
|
||||
// Merge refs
|
||||
const mergedRef = React.useCallback(
|
||||
(node: HTMLDivElement | null) => {
|
||||
itemRef.current = node
|
||||
@@ -697,7 +687,6 @@ const PopoverItem = React.forwardRef<HTMLDivElement, PopoverItemProps>(
|
||||
[ref]
|
||||
)
|
||||
|
||||
// Calculate item index on mount and when siblings change
|
||||
React.useEffect(() => {
|
||||
if (!itemRef.current) return
|
||||
const content = itemRef.current.closest('[data-radix-popper-content-wrapper]')
|
||||
@@ -718,9 +707,7 @@ const PopoverItem = React.forwardRef<HTMLDivElement, PopoverItemProps>(
|
||||
}
|
||||
|
||||
const handleMouseEnter = (e: React.MouseEvent<HTMLDivElement>) => {
|
||||
// Clear last hovered item to close any open hover submenus
|
||||
context?.setLastHoveredItem(null)
|
||||
// Update selected index to this item's position
|
||||
if (itemIndex >= 0 && context) {
|
||||
context.setSelectedIndex(itemIndex)
|
||||
}
|
||||
@@ -863,10 +850,8 @@ const PopoverFolder = React.forwardRef<HTMLDivElement, PopoverFolderProps>(
|
||||
const triggerRef = React.useRef<HTMLDivElement>(null)
|
||||
const [itemIndex, setItemIndex] = React.useState(-1)
|
||||
|
||||
// Submenu is open when this folder is the last hovered item (for expandOnHover mode)
|
||||
const isHoverOpen = expandOnHover && lastHoveredItem === id
|
||||
|
||||
// Merge refs
|
||||
const mergedRef = React.useCallback(
|
||||
(node: HTMLDivElement | null) => {
|
||||
triggerRef.current = node
|
||||
@@ -879,7 +864,6 @@ const PopoverFolder = React.forwardRef<HTMLDivElement, PopoverFolderProps>(
|
||||
[ref]
|
||||
)
|
||||
|
||||
// Calculate item index on mount
|
||||
React.useEffect(() => {
|
||||
if (!triggerRef.current) return
|
||||
const content = triggerRef.current.closest('[data-radix-popper-content-wrapper]')
|
||||
@@ -889,9 +873,7 @@ const PopoverFolder = React.forwardRef<HTMLDivElement, PopoverFolderProps>(
|
||||
setItemIndex(index)
|
||||
}, [])
|
||||
|
||||
// If we're in a folder and this isn't the current one, hide
|
||||
if (isInFolder && currentFolder !== id) return null
|
||||
// If this folder is open via click (inline mode), render children directly
|
||||
if (currentFolder === id) return <>{children}</>
|
||||
|
||||
const handleClickOpen = () => {
|
||||
@@ -901,27 +883,23 @@ const PopoverFolder = React.forwardRef<HTMLDivElement, PopoverFolderProps>(
|
||||
const handleClick = (e: React.MouseEvent) => {
|
||||
e.stopPropagation()
|
||||
if (expandOnHover) {
|
||||
// In hover mode, clicking opens inline and clears hover state
|
||||
setLastHoveredItem(null)
|
||||
}
|
||||
handleClickOpen()
|
||||
}
|
||||
|
||||
const handleMouseEnter = () => {
|
||||
// Update selected index for keyboard navigation
|
||||
if (itemIndex >= 0) {
|
||||
setSelectedIndex(itemIndex)
|
||||
}
|
||||
|
||||
if (!expandOnHover) return
|
||||
|
||||
// Calculate position for submenu
|
||||
if (triggerRef.current) {
|
||||
const rect = triggerRef.current.getBoundingClientRect()
|
||||
const parentPopover = triggerRef.current.closest('[data-radix-popper-content-wrapper]')
|
||||
const parentRect = parentPopover?.getBoundingClientRect()
|
||||
|
||||
// Position to the right of the parent popover with a small gap
|
||||
setSubmenuPosition({
|
||||
top: rect.top,
|
||||
left: parentRect ? parentRect.right + 4 : rect.right + 4,
|
||||
@@ -932,7 +910,6 @@ const PopoverFolder = React.forwardRef<HTMLDivElement, PopoverFolderProps>(
|
||||
onOpen?.()
|
||||
}
|
||||
|
||||
// Determine if this folder is active (for keyboard navigation highlight)
|
||||
const isActive = active !== undefined ? active : itemIndex >= 0 && selectedIndex === itemIndex
|
||||
|
||||
// Suppress hover when in keyboard mode to prevent dual highlights
|
||||
|
||||
Reference in New Issue
Block a user