1+ document . addEventListener ( 'DOMContentLoaded' , function ( ) {
2+ // Load Mermaid from CDN
3+ const script = document . createElement ( 'script' ) ;
4+ script . src = 'https://cdn.jsdelivr.net/npm/[email protected] /dist/mermaid.min.js' ; 5+ script . onload = function ( ) {
6+ // Initialize Mermaid when the script loads
7+ mermaid . initialize ( {
8+ startOnLoad : true ,
9+ theme : 'default' ,
10+ securityLevel : 'loose' ,
11+ flowchart : {
12+ useMaxWidth : false ,
13+ htmlLabels : true
14+ } ,
15+ sequence : {
16+ useMaxWidth : false
17+ } ,
18+ gantt : {
19+ useMaxWidth : false
20+ }
21+ } ) ;
22+
23+ // Add zoom functionality to Mermaid diagrams
24+ mermaid . init ( ) . then ( ( ) => {
25+ document . querySelectorAll ( '.mermaid' ) . forEach ( function ( diagram ) {
26+ // Make diagrams clickable for zoom
27+ diagram . style . cursor = 'zoom-in' ;
28+ diagram . style . maxWidth = '100%' ;
29+ diagram . style . height = 'auto' ;
30+
31+ // Add click handler for zoom
32+ diagram . addEventListener ( 'click' , function ( ) {
33+ // Create zoom overlay
34+ const overlay = document . createElement ( 'div' ) ;
35+ overlay . className = 'mermaid-zoom-overlay' ;
36+ overlay . style . cssText = `
37+ position: fixed;
38+ top: 0;
39+ left: 0;
40+ width: 100%;
41+ height: 100%;
42+ background: rgba(0, 0, 0, 0.8);
43+ display: flex;
44+ justify-content: center;
45+ align-items: center;
46+ z-index: 9999;
47+ cursor: grab;
48+ overflow: hidden;
49+ ` ;
50+
51+ // Create container for panning
52+ const container = document . createElement ( 'div' ) ;
53+ container . style . cssText = `
54+ position: relative;
55+ cursor: grab;
56+ user-select: none;
57+ transform-origin: center center;
58+ ` ;
59+
60+ // Clone the diagram for the overlay
61+ const clonedDiagram = diagram . cloneNode ( true ) ;
62+ clonedDiagram . style . cssText = `
63+ max-width: none;
64+ max-height: none;
65+ background: white;
66+ padding: 20px;
67+ border-radius: 8px;
68+ box-shadow: 0 4px 20px rgba(0, 0, 0, 0.3);
69+ cursor: grab;
70+ user-select: none;
71+ transform-origin: center center;
72+ ` ;
73+
74+ container . appendChild ( clonedDiagram ) ;
75+ overlay . appendChild ( container ) ;
76+ document . body . appendChild ( overlay ) ;
77+
78+ // Zoom and pan functionality
79+ let scale = 1 ;
80+ let translateX = 0 ;
81+ let translateY = 0 ;
82+ let isDragging = false ;
83+ let lastX = 0 ;
84+ let lastY = 0 ;
85+
86+ function updateTransform ( ) {
87+ container . style . transform = `translate(${ translateX } px, ${ translateY } px) scale(${ scale } )` ;
88+ }
89+
90+ // Wheel zoom
91+ overlay . addEventListener ( 'wheel' , function ( e ) {
92+ e . preventDefault ( ) ;
93+ const delta = e . deltaY > 0 ? 0.9 : 1.1 ;
94+ const newScale = Math . max ( 0.5 , Math . min ( 5 , scale * delta ) ) ;
95+
96+ if ( newScale !== scale ) {
97+ const rect = overlay . getBoundingClientRect ( ) ;
98+ const centerX = rect . width / 2 ;
99+ const centerY = rect . height / 2 ;
100+ const mouseX = e . clientX - rect . left ;
101+ const mouseY = e . clientY - rect . top ;
102+
103+ const offsetX = mouseX - centerX ;
104+ const offsetY = mouseY - centerY ;
105+
106+ translateX = translateX - offsetX * ( newScale / scale - 1 ) ;
107+ translateY = translateY - offsetY * ( newScale / scale - 1 ) ;
108+ scale = newScale ;
109+
110+ updateTransform ( ) ;
111+ }
112+ } ) ;
113+
114+ // Mouse drag
115+ container . addEventListener ( 'mousedown' , function ( e ) {
116+ if ( e . button === 0 ) { // Left mouse button
117+ isDragging = true ;
118+ lastX = e . clientX ;
119+ lastY = e . clientY ;
120+ container . style . cursor = 'grabbing' ;
121+ overlay . style . cursor = 'grabbing' ;
122+ e . preventDefault ( ) ;
123+ }
124+ } ) ;
125+
126+ overlay . addEventListener ( 'mousemove' , function ( e ) {
127+ if ( isDragging ) {
128+ const deltaX = e . clientX - lastX ;
129+ const deltaY = e . clientY - lastY ;
130+ translateX += deltaX ;
131+ translateY += deltaY ;
132+ lastX = e . clientX ;
133+ lastY = e . clientY ;
134+ updateTransform ( ) ;
135+ }
136+ } ) ;
137+
138+ overlay . addEventListener ( 'mouseup' , function ( ) {
139+ isDragging = false ;
140+ container . style . cursor = 'grab' ;
141+ overlay . style . cursor = 'grab' ;
142+ } ) ;
143+
144+ // Double-click to reset zoom
145+ container . addEventListener ( 'dblclick' , function ( e ) {
146+ e . stopPropagation ( ) ;
147+ scale = 1 ;
148+ translateX = 0 ;
149+ translateY = 0 ;
150+ updateTransform ( ) ;
151+ } ) ;
152+
153+ // Close on background click (but not on diagram)
154+ overlay . addEventListener ( 'click' , function ( e ) {
155+ if ( e . target === overlay ) {
156+ document . body . removeChild ( overlay ) ;
157+ }
158+ } ) ;
159+
160+ // Close on escape key
161+ const escapeHandler = function ( e ) {
162+ if ( e . key === 'Escape' ) {
163+ document . body . removeChild ( overlay ) ;
164+ document . removeEventListener ( 'keydown' , escapeHandler ) ;
165+ }
166+ } ;
167+ document . addEventListener ( 'keydown' , escapeHandler ) ;
168+
169+ // Add instructions
170+ const instructions = document . createElement ( 'div' ) ;
171+ instructions . style . cssText = `
172+ position: absolute;
173+ top: 20px;
174+ left: 20px;
175+ background: rgba(0, 0, 0, 0.7);
176+ color: white;
177+ padding: 10px 15px;
178+ border-radius: 5px;
179+ font-size: 14px;
180+ font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
181+ z-index: 10000;
182+ pointer-events: none;
183+ ` ;
184+ instructions . innerHTML = `
185+ <div>🔍 Scroll to zoom</div>
186+ <div>🖱️ Drag to pan</div>
187+ <div>📱 Double-click to reset</div>
188+ <div>⌨️ ESC to close</div>
189+ ` ;
190+ overlay . appendChild ( instructions ) ;
191+ } ) ;
192+ } ) ;
193+ } ) ;
194+ } ;
195+ document . head . appendChild ( script ) ;
196+ } ) ;
0 commit comments