diff options
Diffstat (limited to 'modules/ext/mindmap.js')
| -rw-r--r-- | modules/ext/mindmap.js | 65 |
1 files changed, 64 insertions, 1 deletions
diff --git a/modules/ext/mindmap.js b/modules/ext/mindmap.js index a5e7286..acce9aa 100644 --- a/modules/ext/mindmap.js +++ b/modules/ext/mindmap.js @@ -1075,6 +1075,61 @@ class MindmapModule { } } } + _svgFullscreen(args) { + const cur = this._ensureMindmap(); + if (!cur) return this.terminal.print('No mindmap. Create one with mindmap new first.', 'warning'); + const name = args[0] || this.current || 'mindmap'; + const layout = this._layoutTree(cur.root); + const colorMap = { + red: '#fb7185', green: '#34d399', yellow: '#fbbf24', blue: '#818cf8', + cyan: '#22d3ee', magenta: '#e879f9', white: '#e0e0e0' + }; + const xShift = layout.minX === Infinity ? 0 : -layout.minX; + const svgWidth = layout.width; + const svgHeight = layout.height; + let svg = '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 ' + svgWidth + ' ' + svgHeight + '" style="background:#0a0a14;font-family:monospace;">'; + for (const e of layout.edges) { + const sx = e.x1 + xShift + 30, sy = e.y1; + const ex = e.x2 + xShift + 30, ey = e.y2; + const mx = (sx + ex) / 2; + svg += '<path d="M' + sx + ',' + sy + ' C' + mx + ',' + (sy + 20) + ' ' + mx + ',' + (ey - 20) + ' ' + ex + ',' + ey + '" fill="none" stroke="#2a2a4a" stroke-width="1.5"/>'; + } + for (const n of layout.nodes) { + const nx = n.x + xShift + 30; + const color = colorMap[n.color] || '#818cf8'; + const fontSize = n.w < 120 ? '9' : '10'; + const text = n.text.length > 18 ? n.text.substring(0, 16) + '..' : n.text; + svg += '<rect x="' + nx + '" y="' + n.y + '" width="' + n.w + '" height="' + n.h + '" rx="6" fill="' + color + '18" stroke="' + color + '" stroke-width="1.5"/>'; + svg += '<text x="' + (nx + n.w / 2) + '" y="' + (n.y + n.h / 2 + 4) + '" text-anchor="middle" fill="#e0e0e0" font-size="' + fontSize + '" font-family="monospace">' + this._escapeHtml(text) + '</text>'; + } + svg += '</svg>'; + + // Create fullscreen overlay + const overlay = document.createElement('div'); + overlay.id = 'mindmap-svg-overlay'; + overlay.style.cssText = 'position:fixed;inset:0;z-index:9999;background:#0a0a14;display:flex;align-items:center;justify-content:center;overflow:auto'; + overlay.innerHTML = svg; + document.body.appendChild(overlay); + + // Close button + const closeBtn = document.createElement('button'); + closeBtn.textContent = '✕'; + closeBtn.style.cssText = 'position:fixed;top:12px;right:12px;z-index:10000;background:rgba(0,0,0,0.6);color:#e0e0e0;border:1px solid #444;border-radius:6px;padding:6px 14px;font-size:16px;cursor:pointer;font-family:monospace'; + closeBtn.addEventListener('click', () => { overlay.remove(); closeBtn.remove(); }); + document.body.appendChild(closeBtn); + + // Escape key + const escHandler = (e) => { + if (e.key === 'Escape') { + overlay.remove(); + closeBtn.remove(); + document.removeEventListener('keydown', escHandler); + } + }; + document.addEventListener('keydown', escHandler); + + this.terminal.print(`🖼️ SVG fullscreen: ${layout.nodes.length} nodes, ${svgWidth}x${svgHeight}`, 'success'); + } // ── Main dispatcher ── registerCommands() { this.commands['mindmap'] = (args) => { @@ -1116,7 +1171,15 @@ class MindmapModule { case 'clone': return this._clone(rest); case 'archive': return this._archive(rest); case 'refresh-html': return this._refreshHtml(rest); - case 'svg': return this._svg(rest); + case 'svg': { + const fsIdx = rest.indexOf('--fullscreen'); + if (fsIdx >= 0) { + const clean = rest.filter(a => a !== '--fullscreen'); + return this._svgFullscreen(clean); + } + return this._svg(rest); + } + case 'svg-fullscreen': return this._svgFullscreen(rest); default: this.terminal.print('Unknown subcommand: ' + sub + '. Try: mindmap help', 'warning'); } }; |