Skip to main content

streaming-mindmap-rendering

Implement real-time streaming mindmap rendering using Mind Elixir in web applications. Supports streaming text parsing and incremental updates.

소스 정보

저장소
SSShooter/mind-elixir-core
최근 소스 활동
2026년 2월 16일 09:59
감지된 SKILL.md 언어
영어
스타
3,177
포크
417

설치 방법

기본적으로 소스를 먼저 확인하는 Prompt가 선택됩니다. 직접 명령으로 전환하거나 로컬 사본을 다운로드할 수도 있습니다.

소스 파일 검토

설치 여부를 결정하기 전에 SKILL.md와 SkillsMP에 표시된 보조 파일을 읽어 보세요.

SKILL.md 표시 중

SKILL.md
소스 지침 · 읽기 전용 미리보기
name
Streaming Mindmap Rendering
description
Implement real-time streaming mindmap rendering using Mind Elixir in web applications. Supports streaming text parsing and incremental updates.
# Streaming Mindmap Rendering This skill guides you through implementing a streaming mindmap renderer using `mind-elixir`. This technique allows you to display a mindmap that grows in real-time as data is generated by an AI model or fetched from a stream. ## Prerequisites - React (or any frontend framework, examples use React) - `mind-elixir` library ## 1. Install Dependencies First, ensure you have `mind-elixir` installed. ```bash npm install mind-elixir ``` ## 2. Component Structure Create a wrapper component for `mind-elixir` to handle the lifecycle and updates. ```tsx import MindElixir, { type MindElixirData, type MindElixirInstance } from 'mind-elixir' import { useEffect, useRef } from 'react' export function MindmapRenderer({ data }: { data: MindElixirData | null }) { const elRef = useRef<HTMLDivElement>(null) const meRef = useRef<MindElixirInstance | null>(null) useEffect(() => { if (!elRef.current) return meRef.current = new MindElixir({ el: elRef.current, direction: MindElixir.RIGHT, }) // Initial empty state or loading state meRef.current.init(data || { nodeData: { topic: 'Loading...', id: 'root' } }) return () => { // Cleanup if necessary } }, []) // Update effect useEffect(() => { if (meRef.current && data) { // Refresh the graph with new data meRef.current.refresh(data) } }, [data]) return <div ref={elRef} style={{ height: '500px', width: '100%' }} /> } ``` ## 3. Streaming & Parsing Logic The core of this skill is efficiently handling the stream and parsing potentially incomplete data. ### Data Formats Mind Elixir supports two main formats: 1. **JSON (Native)**: Hierarchical tree structure. Hard to stream because JSON is invalid until complete. 2. **Plain Text (Recommended for Streaming)**: Indentation-based or markdown-list-based text. Easier to parse partially. #### Plain Text Format Example ```text - Root Node - Child Node 1 - Child Node 1-1 - Child Node 1-2 - Child Node 1-3 - }:2 Summary of first two nodes - Child Node 2 - Child Node 2-1 [^id1] - Child Node 2-2 [^id2] - Child Node 2-3 {color: "#e87a90"} - > [^id1] <-Bidirectional Link-> [^id2] - Child Node 3 - Child Node 3-1 [^id3] - Child Node 3-2 [^id4] - Child Node 3-3 [^id5] - > [^id3] >-Unidirectional Link-> [^id4] - > [^id3] <-Unidirectional Link-< [^id5] - Child Node 4 - Child Node 4-1 [^id6] - Child Node 4-2 [^id7] - Child Node 4-3 [^id8] - } Summary of all previous nodes - Child Node 4-4 - > [^id1] <-Link position is not restricted, as long as the id can be found during rendering-> [^id8] ``` ### Parsing Implementation Use `mind-elixir/plaintextConverter` (or a custom parser) to convert text to the Mind Elixir JSON format. ````typescript import { plaintextToMindElixir } from 'mind-elixir/plaintextConverter' // Helper to clean Markdown code blocks if your stream includes them function cleanStreamContent(content: string): string { return content .replace(/^```[\w]*\n?/gm, '') .replace(/```$/gm, '') .trim() } // State hooks in your parent component const [mindmapData, setMindmapData] = useState<MindElixirData | null>(null) const accumulatedText = useRef('') const lastRenderTime = useRef(0) // Streaming function (Generic Example) async function startStreaming(url: string) { const response = await fetch(url) const reader = response.body?.getReader() const decoder = new TextDecoder() if (!reader) return while (true) { const { done, value } = await reader.read() if (done) break const chunk = decoder.decode(value) accumulatedText.current += chunk // Throttle updates to avoid freezing the UI const now = Date.now() if (now - lastRenderTime.current > 500) { // 500ms throttle updateMindmap() lastRenderTime.current = now } } // Final update updateMindmap() } function updateMindmap() { try { const cleanText = cleanStreamContent(accumulatedText.current) const data = plaintextToMindElixir(cleanText) setMindmapData(data) // This triggers the useEffect in MindmapRenderer } catch (e) { // Ignore parse errors from incomplete chunks console.warn('Partial parse error ignored') } } ```` ## 4. Optimization Tips - **Throttling**: Do not re-parse and re-render on every single byte. Use a throttle (e.g., 200-500ms). - **Stable Root**: Ensure the parsing logic maintains a stable root ID if possible, to prevent the whole graph from flashing. - **Scroll to Last**: To follow the generation, you can programmatically scroll to the last added node. ```typescript // Scroll to last node (inside MindmapRenderer update effect) const lastNode = findLastNode(data.nodeData) // Implement traversal to find last node if (lastNode?.id) { const nodeEle = meRef.current.findEle(lastNode.id) if (nodeEle) meRef.current.scrollIntoView(nodeEle) } ``` ## 5. Integrating with AI Prompts When generating mindmaps with LLMs, instruct the model to use the plaintext format.
GitHub에서 보기