MCPcopy
hub / github.com/lightningpixel/modly / ExtensionsPanel

Function ExtensionsPanel

src/areas/workflows/WorkflowsPage.tsx:186–383  ·  view source on GitHub ↗
({ allExtensions, open }: { allExtensions: WorkflowExtension[]; open: boolean })

Source from the content-addressed store, hash-verified

184}
185
186function ExtensionsPanel({ allExtensions, open }: { allExtensions: WorkflowExtension[]; open: boolean }) {
187 const [search, setSearch] = useState('')
188 const [collapsed, setCollapsed] = useState<Record<string, boolean>>({})
189 const [width, setWidth] = useState(288)
190 const dragging = useRef(false)
191 const startX = useRef(0)
192 const startW = useRef(0)
193
194 useEffect(() => {
195 const onMove = (e: MouseEvent) => {
196 if (!dragging.current) return
197 const delta = startX.current - e.clientX
198 setWidth((w) => Math.min(PANEL_MAX, Math.max(PANEL_MIN, startW.current + delta)))
199 }
200 const onUp = () => { dragging.current = false; document.body.style.cursor = '' }
201 document.addEventListener('mousemove', onMove)
202 document.addEventListener('mouseup', onUp)
203 return () => {
204 document.removeEventListener('mousemove', onMove)
205 document.removeEventListener('mouseup', onUp)
206 }
207 }, [])
208
209 const cols = width >= 580 ? 3 : width >= 370 ? 2 : 1
210 const gridClass = cols === 3 ? 'grid-cols-3' : cols === 2 ? 'grid-cols-2' : 'grid-cols-1'
211 const query = search.trim().toLowerCase()
212
213 const toggleGroup = (id: string) => setCollapsed((c) => ({ ...c, [id]: !c[id] }))
214 const isExpanded = (id: string, hasMatches: boolean) => (query && hasMatches) || !collapsed[id]
215
216 // Base group
217 const filteredBuiltinNodes = PANEL_BUILTIN_NODES.filter((n) => !query || n.label.toLowerCase().includes(query))
218 const filteredBuiltinExts = allExtensions.filter((e) => e.builtin && (!query || e.name.toLowerCase().includes(query)))
219 const baseCount = filteredBuiltinNodes.length + filteredBuiltinExts.length
220 const baseVisible = !query || baseCount > 0
221
222 // Non-builtin groups: grouped by extensionId
223 const nonBuiltinMap = useMemo(() => {
224 const map = new Map<string, { extensionName: string; nodes: WorkflowExtension[] }>()
225 for (const ext of allExtensions) {
226 if (ext.builtin) continue
227 if (!map.has(ext.extensionId)) map.set(ext.extensionId, { extensionName: ext.extensionName, nodes: [] })
228 map.get(ext.extensionId)!.nodes.push(ext)
229 }
230 return map
231 }, [allExtensions])
232
233 return (
234 <div
235 style={{ width: open ? width : 0 }}
236 className="flex overflow-hidden border-l border-zinc-800 transition-[width] duration-300 ease-in-out shrink-0"
237 >
238 <div className="flex shrink-0" style={{ width }}>
239
240 {/* Resize handle */}
241 <div
242 onMouseDown={(e) => {
243 dragging.current = true; startX.current = e.clientX; startW.current = width

Callers

nothing calls this directly

Calls 3

isExpandedFunction · 0.85
toggleGroupFunction · 0.85
filterMethod · 0.80

Tested by

no test coverage detected