22
33import { memo , useCallback , useEffect , useMemo , useRef , useState } from 'react'
44import { createLogger } from '@sim/logger'
5- import { Folder , MoreHorizontal } from 'lucide-react'
5+ import { MoreHorizontal } from 'lucide-react'
66import Link from 'next/link'
77import { useParams , usePathname , useRouter } from 'next/navigation'
88import {
@@ -12,9 +12,6 @@ import {
1212 DropdownMenu ,
1313 DropdownMenuContent ,
1414 DropdownMenuItem ,
15- DropdownMenuSub ,
16- DropdownMenuSubContent ,
17- DropdownMenuSubTrigger ,
1815 DropdownMenuTrigger ,
1916 FolderPlus ,
2017 Home ,
@@ -41,6 +38,8 @@ import { useRegisterGlobalCommands } from '@/app/workspace/[workspaceId]/provide
4138import { useUserPermissionsContext } from '@/app/workspace/[workspaceId]/providers/workspace-permissions-provider'
4239import { createCommands } from '@/app/workspace/[workspaceId]/utils/commands-utils'
4340import {
41+ CollapsedFolderItems ,
42+ CollapsedSidebarMenu ,
4443 HelpModal ,
4544 NavItemContextMenu ,
4645 SearchModal ,
@@ -73,103 +72,11 @@ import { useSettingsNavigation } from '@/hooks/use-settings-navigation'
7372import { useTaskEvents } from '@/hooks/use-task-events'
7473import { SIDEBAR_WIDTH } from '@/stores/constants'
7574import { useFolderStore } from '@/stores/folders/store'
76- import type { FolderTreeNode } from '@/stores/folders/types'
7775import { useSearchModalStore } from '@/stores/modals/search/store'
7876import { useSidebarStore } from '@/stores/sidebar/store'
79- import type { WorkflowMetadata } from '@/stores/workflows/registry/types'
8077
8178const logger = createLogger ( 'Sidebar' )
8279
83- interface CollapsedSidebarMenuProps {
84- icon : React . ReactNode
85- hover : ReturnType < typeof useHoverMenu >
86- onClick ?: ( ) => void
87- children : React . ReactNode
88- className ?: string
89- }
90-
91- function CollapsedSidebarMenu ( {
92- icon,
93- hover,
94- onClick,
95- children,
96- className,
97- } : CollapsedSidebarMenuProps ) {
98- return (
99- < div className = { cn ( 'flex flex-col px-[8px]' , className ) } >
100- < DropdownMenu
101- open = { hover . isOpen }
102- onOpenChange = { ( open ) => {
103- if ( ! open ) hover . close ( )
104- } }
105- modal = { false }
106- >
107- < div { ...hover . triggerProps } >
108- < DropdownMenuTrigger asChild >
109- < button
110- type = 'button'
111- className = 'mx-[2px] flex h-[30px] items-center rounded-[8px] px-[8px] hover:bg-[var(--surface-active)]'
112- onClick = { onClick }
113- >
114- { icon }
115- </ button >
116- </ DropdownMenuTrigger >
117- </ div >
118- < DropdownMenuContent side = 'right' align = 'start' sideOffset = { 8 } { ...hover . contentProps } >
119- { children }
120- </ DropdownMenuContent >
121- </ DropdownMenu >
122- </ div >
123- )
124- }
125-
126- function renderCollapsedFolderItems (
127- nodes : FolderTreeNode [ ] ,
128- grouped : Record < string , WorkflowMetadata [ ] > ,
129- wsId : string
130- ) : React . ReactNode [ ] {
131- return nodes . map ( ( folder ) => {
132- const folderWorkflows = grouped [ folder . id ] || [ ]
133- const hasChildren = folder . children . length > 0 || folderWorkflows . length > 0
134-
135- if ( ! hasChildren ) {
136- return (
137- < DropdownMenuItem key = { folder . id } disabled >
138- < Folder className = 'h-[14px] w-[14px]' />
139- < span className = 'truncate' > { folder . name } </ span >
140- </ DropdownMenuItem >
141- )
142- }
143-
144- return (
145- < DropdownMenuSub key = { folder . id } >
146- < DropdownMenuSubTrigger >
147- < Folder className = 'h-[14px] w-[14px]' />
148- < span className = 'truncate' > { folder . name } </ span >
149- </ DropdownMenuSubTrigger >
150- < DropdownMenuSubContent >
151- { renderCollapsedFolderItems ( folder . children , grouped , wsId ) }
152- { folderWorkflows . map ( ( workflow ) => (
153- < DropdownMenuItem key = { workflow . id } asChild >
154- < Link href = { `/workspace/${ wsId } /w/${ workflow . id } ` } >
155- < div
156- className = 'h-[14px] w-[14px] flex-shrink-0 rounded-[3px] border-[2px]'
157- style = { {
158- backgroundColor : workflow . color ,
159- borderColor : `${ workflow . color } 60` ,
160- backgroundClip : 'padding-box' ,
161- } }
162- />
163- < span className = 'truncate' > { workflow . name } </ span >
164- </ Link >
165- </ DropdownMenuItem >
166- ) ) }
167- </ DropdownMenuSubContent >
168- </ DropdownMenuSub >
169- )
170- } )
171- }
172-
17380function SidebarItemSkeleton ( ) {
17481 return (
17582 < div className = 'sidebar-collapse-hide mx-[2px] flex h-[30px] items-center px-[8px]' >
@@ -457,11 +364,11 @@ export const Sidebar = memo(function Sidebar() {
457364
458365 useFolders ( workspaceId )
459366 const folders = useFolderStore ( ( s ) => s . folders )
367+ const getFolderTree = useFolderStore ( ( s ) => s . getFolderTree )
460368
461369 const folderTree = useMemo (
462- ( ) => ( isCollapsed && workspaceId ? useFolderStore . getState ( ) . getFolderTree ( workspaceId ) : [ ] ) ,
463- // eslint-disable-next-line react-hooks/exhaustive-deps
464- [ isCollapsed , workspaceId , folders ]
370+ ( ) => ( isCollapsed && workspaceId ? getFolderTree ( workspaceId ) : [ ] ) ,
371+ [ isCollapsed , workspaceId , folders , getFolderTree ]
465372 )
466373
467374 const workflowsByFolder = useMemo (
@@ -1305,7 +1212,11 @@ export const Sidebar = memo(function Sidebar() {
13051212 < DropdownMenuItem disabled > No workflows yet</ DropdownMenuItem >
13061213 ) : (
13071214 < >
1308- { renderCollapsedFolderItems ( folderTree , workflowsByFolder , workspaceId ) }
1215+ < CollapsedFolderItems
1216+ nodes = { folderTree }
1217+ workflowsByFolder = { workflowsByFolder }
1218+ workspaceId = { workspaceId }
1219+ />
13091220 { ( workflowsByFolder . root || [ ] ) . map ( ( workflow ) => (
13101221 < DropdownMenuItem key = { workflow . id } asChild >
13111222 < Link href = { `/workspace/${ workspaceId } /w/${ workflow . id } ` } >
0 commit comments