import { ScreenDefinition, ConnectionDef, FlowType } from './types' /** * Find all connected nodes recursively from a start node. */ export function findConnectedNodes( startNodeId: string, connections: ConnectionDef[], direction: 'children' | 'parents' | 'both' = 'children' ): Set { const connected = new Set() connected.add(startNodeId) const queue = [startNodeId] while (queue.length > 0) { const current = queue.shift()! connections.forEach(conn => { if ((direction === 'children' || direction === 'both') && conn.source === current) { if (!connected.has(conn.target)) { connected.add(conn.target) queue.push(conn.target) } } if ((direction === 'parents' || direction === 'both') && conn.target === current) { if (!connected.has(conn.source)) { connected.add(conn.source) queue.push(conn.source) } } }) } return connected } /** * Construct an embeddable URL from a base URL and screen URL. */ export function constructEmbedUrl(baseUrl: string, url: string | undefined): string | null { if (!url) return null const hashIndex = url.indexOf('#') if (hashIndex !== -1) { const basePart = url.substring(0, hashIndex) const hashPart = url.substring(hashIndex) const separator = basePart.includes('?') ? '&' : '?' return `${baseUrl}${basePart}${separator}embed=true${hashPart}` } else { const separator = url.includes('?') ? '&' : '?' return `${baseUrl}${url}${separator}embed=true` } } /** * Calculate node position based on category and index within that category. */ export function getNodePosition( id: string, category: string, screens: ScreenDefinition[], flowType: FlowType ) { const studioPositions: Record = { navigation: { x: 400, y: 50 }, content: { x: 50, y: 250 }, communication: { x: 750, y: 250 }, school: { x: 50, y: 500 }, admin: { x: 750, y: 500 }, ai: { x: 400, y: 380 }, } const adminPositions: Record = { overview: { x: 400, y: 30 }, infrastructure: { x: 50, y: 150 }, compliance: { x: 700, y: 150 }, ai: { x: 50, y: 350 }, communication: { x: 400, y: 350 }, security: { x: 700, y: 350 }, content: { x: 50, y: 550 }, game: { x: 400, y: 550 }, misc: { x: 700, y: 550 }, } const positions = flowType === 'studio' ? studioPositions : adminPositions const base = positions[category] || { x: 400, y: 300 } const categoryScreens = screens.filter(s => s.category === category) const categoryIndex = categoryScreens.findIndex(s => s.id === id) const cols = Math.ceil(Math.sqrt(categoryScreens.length + 1)) const row = Math.floor(categoryIndex / cols) const col = categoryIndex % cols return { x: base.x + col * 160, y: base.y + row * 90, } }