@flight-framework/devtools 1.0.2 → 3.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/panel.js CHANGED
@@ -91,11 +91,11 @@ export function injectDevToolsPanel() {
91
91
  if (panelState.isDragging || panelState.isResizing)
92
92
  return;
93
93
  const options = devTools.getOptions();
94
- container.innerHTML = `
95
- <div class="flight-devtools ${options.position} ${panelState.isOpen ? 'open' : ''}">
96
- ${panelState.isOpen ? '' : `<button class="flight-devtools-toggle" data-action="toggle">${getFlightLogo()}</button>`}
97
- ${panelState.isOpen ? renderPanel(state) : renderBadge(state)}
98
- </div>
94
+ container.innerHTML = `
95
+ <div class="flight-devtools ${options.position} ${panelState.isOpen ? 'open' : ''}">
96
+ ${panelState.isOpen ? '' : `<button class="flight-devtools-toggle" data-action="toggle">${getFlightLogo()}</button>`}
97
+ ${panelState.isOpen ? renderPanel(state) : renderBadge(state)}
98
+ </div>
99
99
  `;
100
100
  // Attach event listeners
101
101
  attachEventListeners(state);
@@ -121,33 +121,33 @@ export function injectDevToolsPanel() {
121
121
  const positionStyle = panelState.x !== null && panelState.y !== null
122
122
  ? `position:fixed;left:${panelState.x}px;top:${panelState.y}px;right:auto;bottom:auto;`
123
123
  : '';
124
- return `
125
- <div class="flight-devtools-panel" style="width:${panelState.width}px;height:${panelState.height}px;${positionStyle}">
126
- <div class="flight-devtools-resize-handle-top" data-resize="top"></div>
127
- <div class="flight-devtools-resize-handle-left" data-resize="left"></div>
128
- <div class="flight-devtools-resize-handle-corner" data-resize="corner"></div>
129
- <div class="flight-devtools-header">
130
- <div class="flight-devtools-header-title">
131
- <span class="flight-devtools-logo">Flight DevTools</span>
132
- <span class="flight-devtools-version">v1.0.1</span>
133
- </div>
134
- <button class="flight-devtools-close" data-action="toggle">x</button>
135
- </div>
136
- <div class="flight-devtools-tabs">
137
- ${tabs.map(tab => `
138
- <button
139
- class="${panelState.currentTab === tab.id ? 'active' : ''}"
140
- data-action="tab"
141
- data-tab="${tab.id}"
142
- >
143
- ${tab.label}${tab.count !== null ? ` <span class="count">${tab.count}</span>` : ''}
144
- </button>
145
- `).join('')}
146
- </div>
147
- <div class="flight-devtools-content">
148
- ${renderTabContent(state)}
149
- </div>
150
- </div>
124
+ return `
125
+ <div class="flight-devtools-panel" style="width:${panelState.width}px;height:${panelState.height}px;${positionStyle}">
126
+ <div class="flight-devtools-resize-handle-top" data-resize="top"></div>
127
+ <div class="flight-devtools-resize-handle-left" data-resize="left"></div>
128
+ <div class="flight-devtools-resize-handle-corner" data-resize="corner"></div>
129
+ <div class="flight-devtools-header">
130
+ <div class="flight-devtools-header-title">
131
+ <span class="flight-devtools-logo">Flight DevTools</span>
132
+ <span class="flight-devtools-version">v1.0.1</span>
133
+ </div>
134
+ <button class="flight-devtools-close" data-action="toggle">x</button>
135
+ </div>
136
+ <div class="flight-devtools-tabs">
137
+ ${tabs.map(tab => `
138
+ <button
139
+ class="${panelState.currentTab === tab.id ? 'active' : ''}"
140
+ data-action="tab"
141
+ data-tab="${tab.id}"
142
+ >
143
+ ${tab.label}${tab.count !== null ? ` <span class="count">${tab.count}</span>` : ''}
144
+ </button>
145
+ `).join('')}
146
+ </div>
147
+ <div class="flight-devtools-content">
148
+ ${renderTabContent(state)}
149
+ </div>
150
+ </div>
151
151
  `;
152
152
  }
153
153
  function renderTabContent(state) {
@@ -177,59 +177,59 @@ export function injectDevToolsPanel() {
177
177
  : routes;
178
178
  const pageRoutes = filtered.filter(r => r.type === 'page');
179
179
  const apiRoutes = filtered.filter(r => r.type === 'api');
180
- return `
181
- <div class="flight-devtools-toolbar">
182
- <input
183
- type="text"
184
- placeholder="Filter routes..."
185
- value="${panelState.routeFilter}"
186
- data-action="filter-routes"
187
- class="flight-devtools-search"
188
- />
189
- </div>
190
- <div class="flight-devtools-list">
191
- ${pageRoutes.length > 0 ? `
192
- <div class="flight-devtools-section">
193
- <div class="flight-devtools-section-title">Pages (${pageRoutes.length})</div>
194
- ${pageRoutes.map(route => renderRouteItem(route)).join('')}
195
- </div>
196
- ` : ''}
197
- ${apiRoutes.length > 0 ? `
198
- <div class="flight-devtools-section">
199
- <div class="flight-devtools-section-title">API Routes (${apiRoutes.length})</div>
200
- ${apiRoutes.map(route => renderRouteItem(route)).join('')}
201
- </div>
202
- ` : ''}
203
- </div>
180
+ return `
181
+ <div class="flight-devtools-toolbar">
182
+ <input
183
+ type="text"
184
+ placeholder="Filter routes..."
185
+ value="${panelState.routeFilter}"
186
+ data-action="filter-routes"
187
+ class="flight-devtools-search"
188
+ />
189
+ </div>
190
+ <div class="flight-devtools-list">
191
+ ${pageRoutes.length > 0 ? `
192
+ <div class="flight-devtools-section">
193
+ <div class="flight-devtools-section-title">Pages (${pageRoutes.length})</div>
194
+ ${pageRoutes.map(route => renderRouteItem(route)).join('')}
195
+ </div>
196
+ ` : ''}
197
+ ${apiRoutes.length > 0 ? `
198
+ <div class="flight-devtools-section">
199
+ <div class="flight-devtools-section-title">API Routes (${apiRoutes.length})</div>
200
+ ${apiRoutes.map(route => renderRouteItem(route)).join('')}
201
+ </div>
202
+ ` : ''}
203
+ </div>
204
204
  `;
205
205
  }
206
206
  function renderRouteItem(route) {
207
207
  const isExpanded = panelState.expandedItems.has(route.path);
208
208
  const hasParams = route.path.includes(':') || route.path.includes('[');
209
- return `
210
- <div class="flight-devtools-item ${isExpanded ? 'expanded' : ''}" data-action="toggle-item" data-id="${route.path}">
211
- <div class="flight-devtools-item-header">
212
- <span class="method ${route.method.toLowerCase()}">${route.method}</span>
213
- <span class="path">${route.path}</span>
214
- ${hasParams ? '<span class="badge dynamic">Dynamic</span>' : ''}
215
- ${route.slot ? `<span class="badge slot">@${route.slot}</span>` : ''}
216
- <span class="expand-icon">${isExpanded ? '▼' : '▶'}</span>
217
- </div>
218
- ${isExpanded ? `
219
- <div class="flight-devtools-item-details">
220
- <div class="detail-row">
221
- <span class="detail-label">File:</span>
222
- <span class="detail-value mono">${route.filePath}</span>
223
- </div>
224
- ${route.params ? `
225
- <div class="detail-row">
226
- <span class="detail-label">Params:</span>
227
- <span class="detail-value">${route.params.join(', ')}</span>
228
- </div>
229
- ` : ''}
230
- </div>
231
- ` : ''}
232
- </div>
209
+ return `
210
+ <div class="flight-devtools-item ${isExpanded ? 'expanded' : ''}" data-action="toggle-item" data-id="${route.path}">
211
+ <div class="flight-devtools-item-header">
212
+ <span class="method ${route.method.toLowerCase()}">${route.method}</span>
213
+ <span class="path">${route.path}</span>
214
+ ${hasParams ? '<span class="badge dynamic">Dynamic</span>' : ''}
215
+ ${route.slot ? `<span class="badge slot">@${route.slot}</span>` : ''}
216
+ <span class="expand-icon">${isExpanded ? '▼' : '▶'}</span>
217
+ </div>
218
+ ${isExpanded ? `
219
+ <div class="flight-devtools-item-details">
220
+ <div class="detail-row">
221
+ <span class="detail-label">File:</span>
222
+ <span class="detail-value mono">${route.filePath}</span>
223
+ </div>
224
+ ${route.params ? `
225
+ <div class="detail-row">
226
+ <span class="detail-label">Params:</span>
227
+ <span class="detail-value">${route.params.join(', ')}</span>
228
+ </div>
229
+ ` : ''}
230
+ </div>
231
+ ` : ''}
232
+ </div>
233
233
  `;
234
234
  }
235
235
  function renderRequests(requests) {
@@ -241,84 +241,84 @@ export function injectDevToolsPanel() {
241
241
  const filteredRequests = filter
242
242
  ? requests.filter(r => r.path.toLowerCase().includes(filter) || r.method.toLowerCase().includes(filter))
243
243
  : requests;
244
- return `
245
- <div class="flight-devtools-toolbar">
246
- <input
247
- type="text"
248
- class="flight-devtools-search"
249
- placeholder="Filter requests..."
250
- value="${panelState.requestFilter}"
251
- data-action="filter-requests"
252
- />
253
- </div>
254
- <div class="flight-devtools-toolbar">
255
- <span class="flight-devtools-info">${filteredRequests.length}/${requests.length} requests</span>
256
- <div class="flight-devtools-btn-group">
257
- <button data-action="export-requests" class="flight-devtools-btn-small">Export</button>
258
- <button data-action="clear-requests" class="flight-devtools-btn-small">Clear</button>
259
- </div>
260
- </div>
261
- <div class="flight-devtools-list">
262
- ${filteredRequests.slice(0, 50).map(req => renderRequestItem(req)).join('')}
263
- </div>
244
+ return `
245
+ <div class="flight-devtools-toolbar">
246
+ <input
247
+ type="text"
248
+ class="flight-devtools-search"
249
+ placeholder="Filter requests..."
250
+ value="${panelState.requestFilter}"
251
+ data-action="filter-requests"
252
+ />
253
+ </div>
254
+ <div class="flight-devtools-toolbar">
255
+ <span class="flight-devtools-info">${filteredRequests.length}/${requests.length} requests</span>
256
+ <div class="flight-devtools-btn-group">
257
+ <button data-action="export-requests" class="flight-devtools-btn-small">Export</button>
258
+ <button data-action="clear-requests" class="flight-devtools-btn-small">Clear</button>
259
+ </div>
260
+ </div>
261
+ <div class="flight-devtools-list">
262
+ ${filteredRequests.slice(0, 50).map(req => renderRequestItem(req)).join('')}
263
+ </div>
264
264
  `;
265
265
  }
266
266
  function renderRequestItem(req) {
267
267
  const isExpanded = panelState.expandedItems.has(req.id);
268
268
  const statusClass = `status-${Math.floor(req.status / 100)}xx`;
269
- return `
270
- <div class="flight-devtools-item ${isExpanded ? 'expanded' : ''}" data-action="toggle-item" data-id="${req.id}">
271
- <div class="flight-devtools-item-header">
272
- <span class="method ${req.method.toLowerCase()}">${req.method}</span>
273
- <span class="path">${req.path}</span>
274
- <span class="status ${statusClass}">${req.status}</span>
275
- <span class="duration">${formatDuration(req.duration)}</span>
276
- <span class="time">${formatRelativeTime(req.timestamp)}</span>
277
- </div>
278
- ${isExpanded ? `
279
- <div class="flight-devtools-item-details">
280
- <div class="detail-row">
281
- <span class="detail-label">Duration:</span>
282
- <span class="detail-value">${formatDuration(req.duration)}</span>
283
- </div>
284
- ${req.size !== undefined ? `
285
- <div class="detail-row">
286
- <span class="detail-label">Size:</span>
287
- <span class="detail-value">${formatBytes(req.size)}</span>
288
- </div>
289
- ` : ''}
290
- ${req.type ? `
291
- <div class="detail-row">
292
- <span class="detail-label">Type:</span>
293
- <span class="detail-value">${req.type}</span>
294
- </div>
295
- ` : ''}
296
- <div class="detail-row">
297
- <span class="detail-label">Time:</span>
298
- <span class="detail-value">${new Date(req.timestamp).toLocaleTimeString()}</span>
299
- </div>
300
- </div>
301
- ` : ''}
302
- </div>
269
+ return `
270
+ <div class="flight-devtools-item ${isExpanded ? 'expanded' : ''}" data-action="toggle-item" data-id="${req.id}">
271
+ <div class="flight-devtools-item-header">
272
+ <span class="method ${req.method.toLowerCase()}">${req.method}</span>
273
+ <span class="path">${req.path}</span>
274
+ <span class="status ${statusClass}">${req.status}</span>
275
+ <span class="duration">${formatDuration(req.duration)}</span>
276
+ <span class="time">${formatRelativeTime(req.timestamp)}</span>
277
+ </div>
278
+ ${isExpanded ? `
279
+ <div class="flight-devtools-item-details">
280
+ <div class="detail-row">
281
+ <span class="detail-label">Duration:</span>
282
+ <span class="detail-value">${formatDuration(req.duration)}</span>
283
+ </div>
284
+ ${req.size !== undefined ? `
285
+ <div class="detail-row">
286
+ <span class="detail-label">Size:</span>
287
+ <span class="detail-value">${formatBytes(req.size)}</span>
288
+ </div>
289
+ ` : ''}
290
+ ${req.type ? `
291
+ <div class="detail-row">
292
+ <span class="detail-label">Type:</span>
293
+ <span class="detail-value">${req.type}</span>
294
+ </div>
295
+ ` : ''}
296
+ <div class="detail-row">
297
+ <span class="detail-label">Time:</span>
298
+ <span class="detail-value">${new Date(req.timestamp).toLocaleTimeString()}</span>
299
+ </div>
300
+ </div>
301
+ ` : ''}
302
+ </div>
303
303
  `;
304
304
  }
305
305
  function renderAdapters(state) {
306
306
  if (state.adapters.length === 0) {
307
307
  return '<div class="flight-devtools-empty">No adapters registered</div>';
308
308
  }
309
- return `
310
- <div class="flight-devtools-list">
311
- ${state.adapters.map(adapter => `
312
- <div class="flight-devtools-item">
313
- <div class="flight-devtools-item-header">
314
- <span class="adapter-icon">${getAdapterIcon(adapter.type)}</span>
315
- <span class="adapter-name">${adapter.name}</span>
316
- <span class="adapter-type">${adapter.type}</span>
317
- <span class="adapter-status status-${adapter.status}">${adapter.status}</span>
318
- </div>
319
- </div>
320
- `).join('')}
321
- </div>
309
+ return `
310
+ <div class="flight-devtools-list">
311
+ ${state.adapters.map(adapter => `
312
+ <div class="flight-devtools-item">
313
+ <div class="flight-devtools-item-header">
314
+ <span class="adapter-icon">${getAdapterIcon(adapter.type)}</span>
315
+ <span class="adapter-name">${adapter.name}</span>
316
+ <span class="adapter-type">${adapter.type}</span>
317
+ <span class="adapter-status status-${adapter.status}">${adapter.status}</span>
318
+ </div>
319
+ </div>
320
+ `).join('')}
321
+ </div>
322
322
  `;
323
323
  }
324
324
  function getAdapterIcon(type) {
@@ -346,22 +346,22 @@ export function injectDevToolsPanel() {
346
346
  { label: 'FCP', value: perf.fcp, unit: 'ms', good: 1800, desc: 'First Contentful Paint' },
347
347
  { label: 'TTFB', value: perf.ttfb, unit: 'ms', good: 800, desc: 'Time to First Byte' },
348
348
  ].filter(m => m.value !== undefined);
349
- return `
350
- <div class="flight-devtools-list">
351
- <div class="flight-devtools-section-title">Core Web Vitals</div>
352
- <div class="flight-devtools-metrics">
349
+ return `
350
+ <div class="flight-devtools-list">
351
+ <div class="flight-devtools-section-title">Core Web Vitals</div>
352
+ <div class="flight-devtools-metrics">
353
353
  ${metrics.map(m => {
354
354
  const status = m.value <= m.good ? 'good' : m.value <= m.good * 2 ? 'needs-improvement' : 'poor';
355
- return `
356
- <div class="flight-devtools-metric ${status}">
357
- <div class="metric-label">${m.label}</div>
358
- <div class="metric-value">${m.unit ? formatDuration(m.value) : m.value.toFixed(3)}</div>
359
- <div class="metric-desc">${m.desc}</div>
360
- </div>
355
+ return `
356
+ <div class="flight-devtools-metric ${status}">
357
+ <div class="metric-label">${m.label}</div>
358
+ <div class="metric-value">${m.unit ? formatDuration(m.value) : m.value.toFixed(3)}</div>
359
+ <div class="metric-desc">${m.desc}</div>
360
+ </div>
361
361
  `;
362
- }).join('')}
363
- </div>
364
- </div>
362
+ }).join('')}
363
+ </div>
364
+ </div>
365
365
  `;
366
366
  }
367
367
  function renderConsole(state) {
@@ -372,30 +372,30 @@ export function injectDevToolsPanel() {
372
372
  const filtered = panelState.consoleFilter === 'all'
373
373
  ? entries
374
374
  : entries.filter(e => e.level === panelState.consoleFilter);
375
- return `
376
- <div class="flight-devtools-toolbar">
377
- <div class="flight-devtools-filter-group">
378
- ${['all', 'log', 'warn', 'error'].map(f => `
379
- <button
380
- class="flight-devtools-filter-btn ${panelState.consoleFilter === f ? 'active' : ''}"
381
- data-action="filter-console"
382
- data-filter="${f}"
383
- >${f}</button>
384
- `).join('')}
385
- </div>
386
- <button data-action="clear-console" class="flight-devtools-btn-small">Clear</button>
387
- </div>
388
- <div class="flight-devtools-list console-list">
375
+ return `
376
+ <div class="flight-devtools-toolbar">
377
+ <div class="flight-devtools-filter-group">
378
+ ${['all', 'log', 'warn', 'error'].map(f => `
379
+ <button
380
+ class="flight-devtools-filter-btn ${panelState.consoleFilter === f ? 'active' : ''}"
381
+ data-action="filter-console"
382
+ data-filter="${f}"
383
+ >${f}</button>
384
+ `).join('')}
385
+ </div>
386
+ <button data-action="clear-console" class="flight-devtools-btn-small">Clear</button>
387
+ </div>
388
+ <div class="flight-devtools-list console-list">
389
389
  ${filtered.length === 0
390
390
  ? '<div class="flight-devtools-empty">No console entries</div>'
391
- : filtered.slice(0, 100).map(entry => `
392
- <div class="flight-devtools-console-item level-${entry.level}">
393
- <span class="console-time">${formatRelativeTime(entry.timestamp)}</span>
394
- <span class="console-level">${entry.level}</span>
395
- <span class="console-message">${escapeHtml(entry.message)}</span>
396
- </div>
397
- `).join('')}
398
- </div>
391
+ : filtered.slice(0, 100).map(entry => `
392
+ <div class="flight-devtools-console-item level-${entry.level}">
393
+ <span class="console-time">${formatRelativeTime(entry.timestamp)}</span>
394
+ <span class="console-level">${entry.level}</span>
395
+ <span class="console-message">${escapeHtml(entry.message)}</span>
396
+ </div>
397
+ `).join('')}
398
+ </div>
399
399
  `;
400
400
  }
401
401
  function escapeHtml(text) {
@@ -584,555 +584,555 @@ export function injectDevToolsPanel() {
584
584
  function getFlightLogo() {
585
585
  // Flight logo SVG - exact copy from favicon.svg with optimized viewBox for button display
586
586
  // Following SVGO best practices: proper viewBox, inlined transforms, appropriate sizing
587
- return `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 800 800" width="40" height="40" fill="currentColor">
588
- <g transform="translate(0,800) scale(0.1,-0.1)">
589
- <path d="M 4056 6148 c31 -40 81 -114 110 -165 53 -89 119 -231 112 -239 -2 -2 -23 6 -45 17 -133 65 -342 65 -475 0 -26 -13 -38 -15 -38 -6 0 18 94 206 136 272 34 55 135 193 140 193 2 0 28 -33 60 -72z m90 -449 c34 -11 90 -39 125 -62 l64 -43 24 -99 c13 -55 25 -106 27 -112 3 -10 107 -13 480 -13 l476 0 -5 -22 c-3 -13 -18 -88 -32 -167 -14 -80 -28 -148 -31 -153 -3 -4 -182 -8 -399 -8 l-393 0 -27 -82 c-86 -263 -277 -536 -531 -758 -131 -114 -245 -201 -484 -370 -96 -67 -222 -159 -280 -204 -143 -110 -364 -332 -428 -429 -62 -94 -67 -84 -11 25 120 240 288 420 669 719 268 209 377 305 511 444 180 188 290 363 352 561 41 134 39 143 -11 44 -98 -195 -226 -366 -406 -545 -112 -111 -204 -191 -210 -184 -13 15 -39 379 -43 601 -6 283 3 419 37 588 33 162 33 160 102 207 134 91 274 111 424 62z m889 -1121 c-4 -24 -17 -101 -28 -173 l-22 -130 -305 -5 -305 -5 -18 -115 c-32 -215 -98 -615 -103 -632 -5 -17 -26 -18 -258 -18 l-253 0 -17 108 c-9 59 -16 116 -16 128 0 13 30 44 93 94 256 206 529 539 612 748 l17 42 305 0 304 0 -6 -42z m-1506 -283 l13 -134 -32 -27 c-78 -66 -261 -204 -270 -204 -10 0 -8 55 6 165 7 64 60 143 161 243 52 50 97 92 102 92 4 0 13 -61 20 -135z m105 -676 l7 -56 -113 -71 c-218 -136 -405 -290 -515 -423 -110 -133 -108 -132 -77 -69 69 142 178 280 330 414 118 106 346 278 355 268 4 -4 10 -32 13 -63z m558 -251 c12 -21 20 -40 17 -42 -6 -6 -413 -10 -419 -5 -3 3 4 24 14 47 l19 42 174 -2 174 -3 21 -37z m-330 -190 c-24 -46 -27 -64 -26 -140 0 -48 -3 -88 -7 -88 -19 0 -41 92 -37 151 4 56 8 65 41 95 52 48 60 42 29 -18z m188 22 c41 -44 48 -104 22 -183 -22 -66 -72 -180 -77 -175 -2 2 -21 46 -44 99 -58 135 -57 223 3 271 32 26 64 22 96 -12z m85 18 c38 -17 68 -73 69 -127 1 -44 -28 -141 -42 -141 -4 0 -7 40 -7 88 0 76 -4 95 -27 140 -15 29 -25 52 -23 52 2 0 16 -5 30 -12z m243 -267 c-10 -17 -12 -17 -27 -2 -15 14 -15 17 -1 28 22 17 43 -3 28 -26z m-248 -158 c20 -84 53 -177 97 -275 25 -57 27 -58 65 -58 42 0 98 -26 98 -46 0 -16 -51 -55 -170 -134 -242 -158 -507 -256 -730 -267 -124 -6 -167 4 -190 46 -26 50 0 131 65 205 44 50 44 43 0 -30 -47 -79 -50 -134 -9 -171 40 -36 60 -30 67 18 6 42 44 94 78 104 13 4 17 17 17 55 0 99 68 170 165 170 l44 0 31 73 c40 95 86 236 102 312 7 33 17 64 21 69 10 12 42 -59 84 -188 l33 -99 17 59 c22 77 87 246 92 240 2 -2 12 -39 23 -83z m456 27 c161 -71 188 -222 73 -416 -47 -81 -215 -247 -324 -321 -170 -115 -370 -202 -577 -253 -148 -36 -205 -38 -93 -4 384 120 667 287 867 513 160 181 181 361 51 438 -55 32 -138 52 -218 54 -45 0 -55 3 -40 10 36 17 207 3 261 -21z m-253 -111 c3 -11 15 -23 26 -26 12 -3 21 -9 21 -13 0 -4 -9 -10 -21 -13 -11 -3 -23 -15 -26 -26 -7 -27 -19 -27 -26 -1 -3 11 -15 24 -27 28 l-22 8 26 17 c14 10 26 24 26 32 0 22 17 18 23 -6z m231 -18 c3 -5 0 -14 -8 -20 -10 -8 -16 -8 -25 3 -9 11 -9 15 1 19 20 8 26 8 32 -2z m-876 -99 c-17 -20 -40 5 -26 28 11 17 13 17 24 2 9 -12 9 -21 2 -30z m-145 -102 c22 -8 22 -8 -4 -18 -15 -6 -29 -21 -33 -34 -5 -17 -9 -19 -13 -8 -3 8 -16 25 -30 36 -25 22 -25 22 -4 29 11 3 24 18 27 32 l7 26 14 -27 c8 -15 24 -31 36 -36z m953 -67 c-124 -160 -309 -303 -529 -408 -356 -171 -686 -202 -767 -73 -28 43 -22 132 10 181 12 17 19 23 15 12 -4 -11 -10 -43 -12 -71 -5 -46 -2 -54 27 -87 37 -43 79 -57 173 -57 295 0 769 215 1027 467 52 51 96 93 98 93 2 0 -17 -26 -42 -57z m-1162 -2 c3 -5 -1 -14 -8 -20 -16 -13 -32 2 -21 19 8 12 22 13 29 1z m1332 -182 c10 -17 -13 -36 -27 -22 -12 12 -4 33 11 33 5 0 12 -5 16 -11z m-298 -239 c7 -11 20 -20 30 -20 12 -1 9 -5 -10 -16 -16 -8 -28 -21 -28 -29 0 -22 -17 -18 -23 5 -3 11 -12 20 -21 20 -23 0 -20 17 4 23 11 3 20 12 20 21 0 22 13 20 28 -4z m-164 -108 c2 -4 1 -14 -4 -22 -7 -11 -12 -12 -21 -3 -6 6 -8 16 -5 22 8 13 23 14 30 3z"/>
590
- <path d="M3938 5509 c-57 -16 -114 -71 -133 -130 -29 -86 -4 -168 67 -222 136 -103 328 -10 328 160 0 132 -131 228 -262 192z"/>
591
- <path d="M3923 2465 c-10 -10 -9 -16 1 -24 10 -8 16 -8 25 3 16 19 -9 40 -26 21z"/>
592
- <path d="M4110 2440 l-25 -27 27 -27 c25 -24 27 -25 33 -7 3 10 16 22 28 25 l22 7 -23 9 c-12 5 -26 18 -30 29 -7 18 -9 17 -32 -9z"/>
593
- <path d="M3851 2307 c-9 -11 -8 -17 3 -26 11 -9 15 -8 20 5 9 23 -8 38 -23 21z"/>
594
- <path d="M3665 2266 c-5 -18 -18 -33 -39 -41 l-31 -13 28 -7 c18 -5 33 -18 41 -39 l13 -31 8 29 c5 18 18 33 39 41 l31 13 -28 7 c-18 5 -33 18 -41 39 l-13 31 -8 -29z"/>
595
- </g>
587
+ return `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 800 800" width="40" height="40" fill="currentColor">
588
+ <g transform="translate(0,800) scale(0.1,-0.1)">
589
+ <path d="M 4056 6148 c31 -40 81 -114 110 -165 53 -89 119 -231 112 -239 -2 -2 -23 6 -45 17 -133 65 -342 65 -475 0 -26 -13 -38 -15 -38 -6 0 18 94 206 136 272 34 55 135 193 140 193 2 0 28 -33 60 -72z m90 -449 c34 -11 90 -39 125 -62 l64 -43 24 -99 c13 -55 25 -106 27 -112 3 -10 107 -13 480 -13 l476 0 -5 -22 c-3 -13 -18 -88 -32 -167 -14 -80 -28 -148 -31 -153 -3 -4 -182 -8 -399 -8 l-393 0 -27 -82 c-86 -263 -277 -536 -531 -758 -131 -114 -245 -201 -484 -370 -96 -67 -222 -159 -280 -204 -143 -110 -364 -332 -428 -429 -62 -94 -67 -84 -11 25 120 240 288 420 669 719 268 209 377 305 511 444 180 188 290 363 352 561 41 134 39 143 -11 44 -98 -195 -226 -366 -406 -545 -112 -111 -204 -191 -210 -184 -13 15 -39 379 -43 601 -6 283 3 419 37 588 33 162 33 160 102 207 134 91 274 111 424 62z m889 -1121 c-4 -24 -17 -101 -28 -173 l-22 -130 -305 -5 -305 -5 -18 -115 c-32 -215 -98 -615 -103 -632 -5 -17 -26 -18 -258 -18 l-253 0 -17 108 c-9 59 -16 116 -16 128 0 13 30 44 93 94 256 206 529 539 612 748 l17 42 305 0 304 0 -6 -42z m-1506 -283 l13 -134 -32 -27 c-78 -66 -261 -204 -270 -204 -10 0 -8 55 6 165 7 64 60 143 161 243 52 50 97 92 102 92 4 0 13 -61 20 -135z m105 -676 l7 -56 -113 -71 c-218 -136 -405 -290 -515 -423 -110 -133 -108 -132 -77 -69 69 142 178 280 330 414 118 106 346 278 355 268 4 -4 10 -32 13 -63z m558 -251 c12 -21 20 -40 17 -42 -6 -6 -413 -10 -419 -5 -3 3 4 24 14 47 l19 42 174 -2 174 -3 21 -37z m-330 -190 c-24 -46 -27 -64 -26 -140 0 -48 -3 -88 -7 -88 -19 0 -41 92 -37 151 4 56 8 65 41 95 52 48 60 42 29 -18z m188 22 c41 -44 48 -104 22 -183 -22 -66 -72 -180 -77 -175 -2 2 -21 46 -44 99 -58 135 -57 223 3 271 32 26 64 22 96 -12z m85 18 c38 -17 68 -73 69 -127 1 -44 -28 -141 -42 -141 -4 0 -7 40 -7 88 0 76 -4 95 -27 140 -15 29 -25 52 -23 52 2 0 16 -5 30 -12z m243 -267 c-10 -17 -12 -17 -27 -2 -15 14 -15 17 -1 28 22 17 43 -3 28 -26z m-248 -158 c20 -84 53 -177 97 -275 25 -57 27 -58 65 -58 42 0 98 -26 98 -46 0 -16 -51 -55 -170 -134 -242 -158 -507 -256 -730 -267 -124 -6 -167 4 -190 46 -26 50 0 131 65 205 44 50 44 43 0 -30 -47 -79 -50 -134 -9 -171 40 -36 60 -30 67 18 6 42 44 94 78 104 13 4 17 17 17 55 0 99 68 170 165 170 l44 0 31 73 c40 95 86 236 102 312 7 33 17 64 21 69 10 12 42 -59 84 -188 l33 -99 17 59 c22 77 87 246 92 240 2 -2 12 -39 23 -83z m456 27 c161 -71 188 -222 73 -416 -47 -81 -215 -247 -324 -321 -170 -115 -370 -202 -577 -253 -148 -36 -205 -38 -93 -4 384 120 667 287 867 513 160 181 181 361 51 438 -55 32 -138 52 -218 54 -45 0 -55 3 -40 10 36 17 207 3 261 -21z m-253 -111 c3 -11 15 -23 26 -26 12 -3 21 -9 21 -13 0 -4 -9 -10 -21 -13 -11 -3 -23 -15 -26 -26 -7 -27 -19 -27 -26 -1 -3 11 -15 24 -27 28 l-22 8 26 17 c14 10 26 24 26 32 0 22 17 18 23 -6z m231 -18 c3 -5 0 -14 -8 -20 -10 -8 -16 -8 -25 3 -9 11 -9 15 1 19 20 8 26 8 32 -2z m-876 -99 c-17 -20 -40 5 -26 28 11 17 13 17 24 2 9 -12 9 -21 2 -30z m-145 -102 c22 -8 22 -8 -4 -18 -15 -6 -29 -21 -33 -34 -5 -17 -9 -19 -13 -8 -3 8 -16 25 -30 36 -25 22 -25 22 -4 29 11 3 24 18 27 32 l7 26 14 -27 c8 -15 24 -31 36 -36z m953 -67 c-124 -160 -309 -303 -529 -408 -356 -171 -686 -202 -767 -73 -28 43 -22 132 10 181 12 17 19 23 15 12 -4 -11 -10 -43 -12 -71 -5 -46 -2 -54 27 -87 37 -43 79 -57 173 -57 295 0 769 215 1027 467 52 51 96 93 98 93 2 0 -17 -26 -42 -57z m-1162 -2 c3 -5 -1 -14 -8 -20 -16 -13 -32 2 -21 19 8 12 22 13 29 1z m1332 -182 c10 -17 -13 -36 -27 -22 -12 12 -4 33 11 33 5 0 12 -5 16 -11z m-298 -239 c7 -11 20 -20 30 -20 12 -1 9 -5 -10 -16 -16 -8 -28 -21 -28 -29 0 -22 -17 -18 -23 5 -3 11 -12 20 -21 20 -23 0 -20 17 4 23 11 3 20 12 20 21 0 22 13 20 28 -4z m-164 -108 c2 -4 1 -14 -4 -22 -7 -11 -12 -12 -21 -3 -6 6 -8 16 -5 22 8 13 23 14 30 3z"/>
590
+ <path d="M3938 5509 c-57 -16 -114 -71 -133 -130 -29 -86 -4 -168 67 -222 136 -103 328 -10 328 160 0 132 -131 228 -262 192z"/>
591
+ <path d="M3923 2465 c-10 -10 -9 -16 1 -24 10 -8 16 -8 25 3 16 19 -9 40 -26 21z"/>
592
+ <path d="M4110 2440 l-25 -27 27 -27 c25 -24 27 -25 33 -7 3 10 16 22 28 25 l22 7 -23 9 c-12 5 -26 18 -30 29 -7 18 -9 17 -32 -9z"/>
593
+ <path d="M3851 2307 c-9 -11 -8 -17 3 -26 11 -9 15 -8 20 5 9 23 -8 38 -23 21z"/>
594
+ <path d="M3665 2266 c-5 -18 -18 -33 -39 -41 l-31 -13 28 -7 c18 -5 33 -18 41 -39 l13 -31 8 29 c5 18 18 33 39 41 l31 13 -28 7 c-18 5 -33 18 -41 39 l-13 31 -8 -29z"/>
595
+ </g>
596
596
  </svg>`;
597
597
  }
598
598
  function getFlightLogoSmall() {
599
599
  // Small Flight logo for the header (16x16)
600
- return `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 800 800" width="16" height="16" fill="currentColor" style="vertical-align:middle;margin-right:6px;">
601
- <g transform="translate(0,800) scale(0.1,-0.1)">
602
- <path d="M 4056 6148 c31 -40 81 -114 110 -165 53 -89 119 -231 112 -239 -2 -2 -23 6 -45 17 -133 65 -342 65 -475 0 -26 -13 -38 -15 -38 -6 0 18 94 206 136 272 34 55 135 193 140 193 2 0 28 -33 60 -72z m90 -449 c34 -11 90 -39 125 -62 l64 -43 24 -99 c13 -55 25 -106 27 -112 3 -10 107 -13 480 -13 l476 0 -5 -22 c-3 -13 -18 -88 -32 -167 -14 -80 -28 -148 -31 -153 -3 -4 -182 -8 -399 -8 l-393 0 -27 -82 c-86 -263 -277 -536 -531 -758 -131 -114 -245 -201 -484 -370 -96 -67 -222 -159 -280 -204 -143 -110 -364 -332 -428 -429 -62 -94 -67 -84 -11 25 120 240 288 420 669 719 268 209 377 305 511 444 180 188 290 363 352 561 41 134 39 143 -11 44 -98 -195 -226 -366 -406 -545 -112 -111 -204 -191 -210 -184 -13 15 -39 379 -43 601 -6 283 3 419 37 588 33 162 33 160 102 207 134 91 274 111 424 62z"/>
603
- <path d="M3938 5509 c-57 -16 -114 -71 -133 -130 -29 -86 -4 -168 67 -222 136 -103 328 -10 328 160 0 132 -131 228 -262 192z"/>
604
- </g>
600
+ return `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 800 800" width="16" height="16" fill="currentColor" style="vertical-align:middle;margin-right:6px;">
601
+ <g transform="translate(0,800) scale(0.1,-0.1)">
602
+ <path d="M 4056 6148 c31 -40 81 -114 110 -165 53 -89 119 -231 112 -239 -2 -2 -23 6 -45 17 -133 65 -342 65 -475 0 -26 -13 -38 -15 -38 -6 0 18 94 206 136 272 34 55 135 193 140 193 2 0 28 -33 60 -72z m90 -449 c34 -11 90 -39 125 -62 l64 -43 24 -99 c13 -55 25 -106 27 -112 3 -10 107 -13 480 -13 l476 0 -5 -22 c-3 -13 -18 -88 -32 -167 -14 -80 -28 -148 -31 -153 -3 -4 -182 -8 -399 -8 l-393 0 -27 -82 c-86 -263 -277 -536 -531 -758 -131 -114 -245 -201 -484 -370 -96 -67 -222 -159 -280 -204 -143 -110 -364 -332 -428 -429 -62 -94 -67 -84 -11 25 120 240 288 420 669 719 268 209 377 305 511 444 180 188 290 363 352 561 41 134 39 143 -11 44 -98 -195 -226 -366 -406 -545 -112 -111 -204 -191 -210 -184 -13 15 -39 379 -43 601 -6 283 3 419 37 588 33 162 33 160 102 207 134 91 274 111 424 62z"/>
603
+ <path d="M3938 5509 c-57 -16 -114 -71 -133 -130 -29 -86 -4 -168 67 -222 136 -103 328 -10 328 160 0 132 -131 228 -262 192z"/>
604
+ </g>
605
605
  </svg>`;
606
606
  }
607
607
  // ============================================================================
608
608
  // Styles
609
609
  // ============================================================================
610
610
  function getDevToolsStyles() {
611
- return `
612
- #flight-devtools {
613
- font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', sans-serif;
614
- font-size: 12px;
615
- line-height: 1.4;
616
- --green: #22c55e;
617
- --green-dark: #16a34a;
618
- --bg: #0f0f0f;
619
- --bg-2: #1a1a1a;
620
- --bg-3: #252525;
621
- --border: #333;
622
- --text: #e5e5e5;
623
- --text-muted: #888;
624
- }
625
-
626
- .flight-devtools {
627
- position: fixed;
628
- z-index: 999999;
629
- }
630
-
631
- .flight-devtools.bottom-right { bottom: 16px; right: 16px; }
632
- .flight-devtools.bottom-left { bottom: 16px; left: 16px; }
633
- .flight-devtools.top-right { top: 16px; right: 16px; }
634
- .flight-devtools.top-left { top: 16px; left: 16px; }
635
-
636
- .flight-devtools-toggle {
637
- width: 48px;
638
- height: 48px;
639
- border-radius: 50%;
640
- border: none;
641
- background: linear-gradient(135deg, var(--green) 0%, var(--green-dark) 100%);
642
- color: white;
643
- font-size: 20px;
644
- cursor: pointer;
645
- box-shadow: 0 4px 20px rgba(34, 197, 94, 0.4);
646
- transition: transform 0.2s, box-shadow 0.2s;
647
- display: flex;
648
- align-items: center;
649
- justify-content: center;
650
- padding: 0;
651
- }
652
-
653
- .flight-devtools-toggle:hover {
654
- transform: scale(1.05);
655
- box-shadow: 0 6px 24px rgba(34, 197, 94, 0.5);
656
- }
657
-
658
- .flight-devtools.open .flight-devtools-toggle {
659
- position: absolute;
660
- top: 8px;
661
- right: 8px;
662
- width: 28px;
663
- height: 28px;
664
- font-size: 14px;
665
- background: rgba(0,0,0,0.3);
666
- box-shadow: none;
667
- z-index: 10;
668
- }
669
-
670
- .flight-devtools-badge {
671
- position: absolute;
672
- top: -4px;
673
- right: -4px;
674
- width: 18px;
675
- height: 18px;
676
- border-radius: 50%;
677
- background: #ef4444;
678
- color: white;
679
- font-size: 10px;
680
- font-weight: 600;
681
- display: flex;
682
- align-items: center;
683
- justify-content: center;
684
- }
685
-
686
- .flight-devtools-panel {
687
- position: absolute;
688
- bottom: 0;
689
- right: 0;
690
- width: 480px;
691
- height: 500px;
692
- max-height: 80vh;
693
- background: var(--bg);
694
- border: 1px solid var(--border);
695
- border-radius: 12px;
696
- overflow: hidden;
697
- box-shadow: 0 8px 40px rgba(0,0,0,0.5);
698
- display: flex;
699
- flex-direction: column;
700
- }
701
-
702
- .flight-devtools-resize-handle-top {
703
- position: absolute;
704
- top: 0;
705
- left: 20px;
706
- right: 20px;
707
- height: 6px;
708
- cursor: ns-resize;
709
- z-index: 10;
710
- }
711
-
712
- .flight-devtools-resize-handle-left {
713
- position: absolute;
714
- left: 0;
715
- top: 20px;
716
- bottom: 20px;
717
- width: 6px;
718
- cursor: ew-resize;
719
- z-index: 10;
720
- }
721
-
722
- .flight-devtools-resize-handle-corner {
723
- position: absolute;
724
- top: 0;
725
- left: 0;
726
- width: 16px;
727
- height: 16px;
728
- cursor: nwse-resize;
729
- z-index: 11;
730
- }
731
-
732
- .flight-devtools-header {
733
- padding: 12px 16px;
734
- background: linear-gradient(135deg, var(--green) 0%, var(--green-dark) 100%);
735
- color: white;
736
- display: flex;
737
- align-items: center;
738
- justify-content: space-between;
739
- gap: 12px;
740
- cursor: move;
741
- user-select: none;
742
- }
743
-
744
- .flight-devtools-header-title {
745
- display: flex;
746
- align-items: center;
747
- gap: 8px;
748
- }
749
-
750
- .flight-devtools-logo {
751
- font-weight: 600;
752
- font-size: 14px;
753
- }
754
-
755
- .flight-devtools-version {
756
- font-size: 10px;
757
- opacity: 0.7;
758
- background: rgba(0,0,0,0.15);
759
- padding: 2px 6px;
760
- border-radius: 4px;
761
- }
762
-
763
- .flight-devtools-close {
764
- width: 28px;
765
- height: 28px;
766
- border: none;
767
- background: rgba(0,0,0,0.2);
768
- color: white;
769
- border-radius: 6px;
770
- cursor: pointer;
771
- font-size: 16px;
772
- line-height: 1;
773
- display: flex;
774
- align-items: center;
775
- justify-content: center;
776
- transition: background 0.2s;
777
- flex-shrink: 0;
778
- }
779
-
780
- .flight-devtools-close:hover {
781
- background: rgba(0,0,0,0.4);
782
- }
783
-
784
- .flight-devtools-tabs {
785
- display: flex;
786
- background: var(--bg-2);
787
- border-bottom: 1px solid var(--border);
788
- }
789
-
790
- .flight-devtools-tabs button {
791
- flex: 1;
792
- padding: 10px 8px;
793
- border: none;
794
- background: transparent;
795
- color: var(--text-muted);
796
- font-size: 11px;
797
- cursor: pointer;
798
- border-bottom: 2px solid transparent;
799
- transition: all 0.2s;
800
- }
801
-
802
- .flight-devtools-tabs button:hover {
803
- color: var(--text);
804
- background: var(--bg-3);
805
- }
806
-
807
- .flight-devtools-tabs button.active {
808
- color: var(--green);
809
- border-bottom-color: var(--green);
810
- }
811
-
812
- .flight-devtools-tabs .count {
813
- display: inline-block;
814
- min-width: 18px;
815
- padding: 1px 5px;
816
- margin-left: 4px;
817
- background: var(--bg-3);
818
- border-radius: 10px;
819
- font-size: 10px;
820
- }
821
-
822
- .flight-devtools-content {
823
- flex: 1;
824
- overflow-y: auto;
825
- min-height: 0;
826
- }
827
-
828
- .flight-devtools-toolbar {
829
- display: flex;
830
- align-items: center;
831
- justify-content: space-between;
832
- padding: 8px 12px;
833
- background: var(--bg-2);
834
- border-bottom: 1px solid var(--border);
835
- }
836
-
837
- .flight-devtools-search {
838
- flex: 1;
839
- padding: 6px 10px;
840
- background: var(--bg-3);
841
- border: 1px solid var(--border);
842
- border-radius: 6px;
843
- color: var(--text);
844
- font-size: 12px;
845
- }
846
-
847
- .flight-devtools-search:focus {
848
- outline: none;
849
- border-color: var(--green);
850
- }
851
-
852
- .flight-devtools-btn-small {
853
- padding: 4px 10px;
854
- background: var(--bg-3);
855
- border: 1px solid var(--border);
856
- border-radius: 4px;
857
- color: var(--text-muted);
858
- font-size: 11px;
859
- cursor: pointer;
860
- }
861
-
862
- .flight-devtools-btn-small:hover {
863
- background: var(--border);
864
- color: var(--text);
865
- }
866
-
867
- .flight-devtools-btn-group {
868
- display: flex;
869
- gap: 6px;
870
- }
871
-
872
- .flight-devtools-info {
873
- color: var(--text-muted);
874
- font-size: 11px;
875
- }
876
-
877
- .flight-devtools-list {
878
- padding: 8px;
879
- }
880
-
881
- .flight-devtools-section {
882
- margin-bottom: 16px;
883
- }
884
-
885
- .flight-devtools-section-title {
886
- padding: 8px 8px 4px;
887
- color: var(--text-muted);
888
- font-size: 10px;
889
- font-weight: 600;
890
- text-transform: uppercase;
891
- letter-spacing: 0.5px;
892
- }
893
-
894
- .flight-devtools-item {
895
- padding: 8px 10px;
896
- border-radius: 6px;
897
- cursor: pointer;
898
- transition: background 0.15s;
899
- }
900
-
901
- .flight-devtools-item:hover {
902
- background: var(--bg-2);
903
- }
904
-
905
- .flight-devtools-item.expanded {
906
- background: var(--bg-2);
907
- }
908
-
909
- .flight-devtools-item-header {
910
- display: flex;
911
- align-items: center;
912
- gap: 8px;
913
- }
914
-
915
- .flight-devtools-item-details {
916
- margin-top: 8px;
917
- padding: 8px;
918
- background: var(--bg-3);
919
- border-radius: 4px;
920
- }
921
-
922
- .detail-row {
923
- display: flex;
924
- padding: 3px 0;
925
- }
926
-
927
- .detail-label {
928
- width: 80px;
929
- color: var(--text-muted);
930
- }
931
-
932
- .detail-value {
933
- flex: 1;
934
- color: var(--text);
935
- }
936
-
937
- .detail-value.mono {
938
- font-family: 'SF Mono', Monaco, monospace;
939
- font-size: 11px;
940
- }
941
-
942
- .method {
943
- font-weight: 600;
944
- font-size: 10px;
945
- padding: 2px 6px;
946
- border-radius: 3px;
947
- background: var(--bg-3);
948
- }
949
-
950
- .method.get { color: #22c55e; }
951
- .method.post { color: #3b82f6; }
952
- .method.put { color: #f59e0b; }
953
- .method.patch { color: #f59e0b; }
954
- .method.delete { color: #ef4444; }
955
-
956
- .path {
957
- flex: 1;
958
- font-family: 'SF Mono', Monaco, monospace;
959
- font-size: 11px;
960
- color: var(--text);
961
- overflow: hidden;
962
- text-overflow: ellipsis;
963
- white-space: nowrap;
964
- }
965
-
966
- .badge {
967
- font-size: 9px;
968
- padding: 2px 5px;
969
- border-radius: 3px;
970
- background: var(--bg-3);
971
- color: var(--text-muted);
972
- }
973
-
974
- .badge.dynamic { color: #a78bfa; }
975
- .badge.slot { color: #60a5fa; }
976
-
977
- .expand-icon {
978
- color: var(--text-muted);
979
- font-size: 8px;
980
- }
981
-
982
- .status { font-weight: 600; }
983
- .status.status-2xx { color: #22c55e; }
984
- .status.status-3xx { color: #f59e0b; }
985
- .status.status-4xx { color: #ef4444; }
986
- .status.status-5xx { color: #a855f7; }
987
-
988
- .duration, .time {
989
- color: var(--text-muted);
990
- font-size: 11px;
991
- }
992
-
993
- .adapter-icon {
994
- font-size: 16px;
995
- }
996
-
997
- .adapter-name {
998
- flex: 1;
999
- font-weight: 500;
1000
- }
1001
-
1002
- .adapter-type {
1003
- color: var(--text-muted);
1004
- font-size: 10px;
1005
- }
1006
-
1007
- .adapter-status {
1008
- font-size: 10px;
1009
- padding: 2px 6px;
1010
- border-radius: 3px;
1011
- }
1012
-
1013
- .adapter-status.status-connected { background: rgba(34, 197, 94, 0.2); color: #22c55e; }
1014
- .adapter-status.status-disconnected { background: rgba(239, 68, 68, 0.2); color: #ef4444; }
1015
- .adapter-status.status-error { background: rgba(239, 68, 68, 0.2); color: #ef4444; }
1016
-
1017
- .flight-devtools-metrics {
1018
- display: grid;
1019
- grid-template-columns: repeat(3, 1fr);
1020
- gap: 8px;
1021
- padding: 8px;
1022
- }
1023
-
1024
- .flight-devtools-metric {
1025
- padding: 12px;
1026
- background: var(--bg-2);
1027
- border-radius: 8px;
1028
- text-align: center;
1029
- }
1030
-
1031
- .flight-devtools-metric.good { border-left: 3px solid #22c55e; }
1032
- .flight-devtools-metric.needs-improvement { border-left: 3px solid #f59e0b; }
1033
- .flight-devtools-metric.poor { border-left: 3px solid #ef4444; }
1034
-
1035
- .metric-label {
1036
- font-weight: 600;
1037
- font-size: 11px;
1038
- color: var(--text);
1039
- }
1040
-
1041
- .metric-value {
1042
- font-size: 18px;
1043
- font-weight: 600;
1044
- margin: 4px 0;
1045
- }
1046
-
1047
- .flight-devtools-metric.good .metric-value { color: #22c55e; }
1048
- .flight-devtools-metric.needs-improvement .metric-value { color: #f59e0b; }
1049
- .flight-devtools-metric.poor .metric-value { color: #ef4444; }
1050
-
1051
- .metric-desc {
1052
- font-size: 9px;
1053
- color: var(--text-muted);
1054
- }
1055
-
1056
- .flight-devtools-filter-group {
1057
- display: flex;
1058
- gap: 4px;
1059
- }
1060
-
1061
- .flight-devtools-filter-btn {
1062
- padding: 4px 8px;
1063
- background: transparent;
1064
- border: 1px solid var(--border);
1065
- border-radius: 4px;
1066
- color: var(--text-muted);
1067
- font-size: 10px;
1068
- cursor: pointer;
1069
- text-transform: capitalize;
1070
- }
1071
-
1072
- .flight-devtools-filter-btn.active {
1073
- background: var(--green);
1074
- border-color: var(--green);
1075
- color: white;
1076
- }
1077
-
1078
- .console-list {
1079
- font-family: 'SF Mono', Monaco, monospace;
1080
- font-size: 11px;
1081
- }
1082
-
1083
- .flight-devtools-console-item {
1084
- display: flex;
1085
- gap: 8px;
1086
- padding: 6px 8px;
1087
- border-bottom: 1px solid var(--border);
1088
- }
1089
-
1090
- .flight-devtools-console-item.level-error {
1091
- background: rgba(239, 68, 68, 0.1);
1092
- }
1093
-
1094
- .flight-devtools-console-item.level-warn {
1095
- background: rgba(245, 158, 11, 0.1);
1096
- }
1097
-
1098
- .console-time {
1099
- color: var(--text-muted);
1100
- flex-shrink: 0;
1101
- }
1102
-
1103
- .console-level {
1104
- flex-shrink: 0;
1105
- width: 40px;
1106
- font-weight: 600;
1107
- }
1108
-
1109
- .level-log .console-level { color: #888; }
1110
- .level-info .console-level { color: #3b82f6; }
1111
- .level-warn .console-level { color: #f59e0b; }
1112
- .level-error .console-level { color: #ef4444; }
1113
-
1114
- .console-message {
1115
- flex: 1;
1116
- word-break: break-word;
1117
- color: var(--text);
1118
- }
1119
-
1120
- .flight-devtools-empty {
1121
- padding: 40px 20px;
1122
- text-align: center;
1123
- color: var(--text-muted);
1124
- }
1125
-
1126
- .flight-devtools-empty small {
1127
- display: block;
1128
- margin-top: 8px;
1129
- font-size: 11px;
1130
- opacity: 0.7;
1131
- }
1132
-
1133
- ${hydrationPanelStyles}
1134
-
1135
- ${bundlePanelStyles}
611
+ return `
612
+ #flight-devtools {
613
+ font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', sans-serif;
614
+ font-size: 12px;
615
+ line-height: 1.4;
616
+ --green: #22c55e;
617
+ --green-dark: #16a34a;
618
+ --bg: #0f0f0f;
619
+ --bg-2: #1a1a1a;
620
+ --bg-3: #252525;
621
+ --border: #333;
622
+ --text: #e5e5e5;
623
+ --text-muted: #888;
624
+ }
625
+
626
+ .flight-devtools {
627
+ position: fixed;
628
+ z-index: 999999;
629
+ }
630
+
631
+ .flight-devtools.bottom-right { bottom: 16px; right: 16px; }
632
+ .flight-devtools.bottom-left { bottom: 16px; left: 16px; }
633
+ .flight-devtools.top-right { top: 16px; right: 16px; }
634
+ .flight-devtools.top-left { top: 16px; left: 16px; }
635
+
636
+ .flight-devtools-toggle {
637
+ width: 48px;
638
+ height: 48px;
639
+ border-radius: 50%;
640
+ border: none;
641
+ background: linear-gradient(135deg, var(--green) 0%, var(--green-dark) 100%);
642
+ color: white;
643
+ font-size: 20px;
644
+ cursor: pointer;
645
+ box-shadow: 0 4px 20px rgba(34, 197, 94, 0.4);
646
+ transition: transform 0.2s, box-shadow 0.2s;
647
+ display: flex;
648
+ align-items: center;
649
+ justify-content: center;
650
+ padding: 0;
651
+ }
652
+
653
+ .flight-devtools-toggle:hover {
654
+ transform: scale(1.05);
655
+ box-shadow: 0 6px 24px rgba(34, 197, 94, 0.5);
656
+ }
657
+
658
+ .flight-devtools.open .flight-devtools-toggle {
659
+ position: absolute;
660
+ top: 8px;
661
+ right: 8px;
662
+ width: 28px;
663
+ height: 28px;
664
+ font-size: 14px;
665
+ background: rgba(0,0,0,0.3);
666
+ box-shadow: none;
667
+ z-index: 10;
668
+ }
669
+
670
+ .flight-devtools-badge {
671
+ position: absolute;
672
+ top: -4px;
673
+ right: -4px;
674
+ width: 18px;
675
+ height: 18px;
676
+ border-radius: 50%;
677
+ background: #ef4444;
678
+ color: white;
679
+ font-size: 10px;
680
+ font-weight: 600;
681
+ display: flex;
682
+ align-items: center;
683
+ justify-content: center;
684
+ }
685
+
686
+ .flight-devtools-panel {
687
+ position: absolute;
688
+ bottom: 0;
689
+ right: 0;
690
+ width: 480px;
691
+ height: 500px;
692
+ max-height: 80vh;
693
+ background: var(--bg);
694
+ border: 1px solid var(--border);
695
+ border-radius: 12px;
696
+ overflow: hidden;
697
+ box-shadow: 0 8px 40px rgba(0,0,0,0.5);
698
+ display: flex;
699
+ flex-direction: column;
700
+ }
701
+
702
+ .flight-devtools-resize-handle-top {
703
+ position: absolute;
704
+ top: 0;
705
+ left: 20px;
706
+ right: 20px;
707
+ height: 6px;
708
+ cursor: ns-resize;
709
+ z-index: 10;
710
+ }
711
+
712
+ .flight-devtools-resize-handle-left {
713
+ position: absolute;
714
+ left: 0;
715
+ top: 20px;
716
+ bottom: 20px;
717
+ width: 6px;
718
+ cursor: ew-resize;
719
+ z-index: 10;
720
+ }
721
+
722
+ .flight-devtools-resize-handle-corner {
723
+ position: absolute;
724
+ top: 0;
725
+ left: 0;
726
+ width: 16px;
727
+ height: 16px;
728
+ cursor: nwse-resize;
729
+ z-index: 11;
730
+ }
731
+
732
+ .flight-devtools-header {
733
+ padding: 12px 16px;
734
+ background: linear-gradient(135deg, var(--green) 0%, var(--green-dark) 100%);
735
+ color: white;
736
+ display: flex;
737
+ align-items: center;
738
+ justify-content: space-between;
739
+ gap: 12px;
740
+ cursor: move;
741
+ user-select: none;
742
+ }
743
+
744
+ .flight-devtools-header-title {
745
+ display: flex;
746
+ align-items: center;
747
+ gap: 8px;
748
+ }
749
+
750
+ .flight-devtools-logo {
751
+ font-weight: 600;
752
+ font-size: 14px;
753
+ }
754
+
755
+ .flight-devtools-version {
756
+ font-size: 10px;
757
+ opacity: 0.7;
758
+ background: rgba(0,0,0,0.15);
759
+ padding: 2px 6px;
760
+ border-radius: 4px;
761
+ }
762
+
763
+ .flight-devtools-close {
764
+ width: 28px;
765
+ height: 28px;
766
+ border: none;
767
+ background: rgba(0,0,0,0.2);
768
+ color: white;
769
+ border-radius: 6px;
770
+ cursor: pointer;
771
+ font-size: 16px;
772
+ line-height: 1;
773
+ display: flex;
774
+ align-items: center;
775
+ justify-content: center;
776
+ transition: background 0.2s;
777
+ flex-shrink: 0;
778
+ }
779
+
780
+ .flight-devtools-close:hover {
781
+ background: rgba(0,0,0,0.4);
782
+ }
783
+
784
+ .flight-devtools-tabs {
785
+ display: flex;
786
+ background: var(--bg-2);
787
+ border-bottom: 1px solid var(--border);
788
+ }
789
+
790
+ .flight-devtools-tabs button {
791
+ flex: 1;
792
+ padding: 10px 8px;
793
+ border: none;
794
+ background: transparent;
795
+ color: var(--text-muted);
796
+ font-size: 11px;
797
+ cursor: pointer;
798
+ border-bottom: 2px solid transparent;
799
+ transition: all 0.2s;
800
+ }
801
+
802
+ .flight-devtools-tabs button:hover {
803
+ color: var(--text);
804
+ background: var(--bg-3);
805
+ }
806
+
807
+ .flight-devtools-tabs button.active {
808
+ color: var(--green);
809
+ border-bottom-color: var(--green);
810
+ }
811
+
812
+ .flight-devtools-tabs .count {
813
+ display: inline-block;
814
+ min-width: 18px;
815
+ padding: 1px 5px;
816
+ margin-left: 4px;
817
+ background: var(--bg-3);
818
+ border-radius: 10px;
819
+ font-size: 10px;
820
+ }
821
+
822
+ .flight-devtools-content {
823
+ flex: 1;
824
+ overflow-y: auto;
825
+ min-height: 0;
826
+ }
827
+
828
+ .flight-devtools-toolbar {
829
+ display: flex;
830
+ align-items: center;
831
+ justify-content: space-between;
832
+ padding: 8px 12px;
833
+ background: var(--bg-2);
834
+ border-bottom: 1px solid var(--border);
835
+ }
836
+
837
+ .flight-devtools-search {
838
+ flex: 1;
839
+ padding: 6px 10px;
840
+ background: var(--bg-3);
841
+ border: 1px solid var(--border);
842
+ border-radius: 6px;
843
+ color: var(--text);
844
+ font-size: 12px;
845
+ }
846
+
847
+ .flight-devtools-search:focus {
848
+ outline: none;
849
+ border-color: var(--green);
850
+ }
851
+
852
+ .flight-devtools-btn-small {
853
+ padding: 4px 10px;
854
+ background: var(--bg-3);
855
+ border: 1px solid var(--border);
856
+ border-radius: 4px;
857
+ color: var(--text-muted);
858
+ font-size: 11px;
859
+ cursor: pointer;
860
+ }
861
+
862
+ .flight-devtools-btn-small:hover {
863
+ background: var(--border);
864
+ color: var(--text);
865
+ }
866
+
867
+ .flight-devtools-btn-group {
868
+ display: flex;
869
+ gap: 6px;
870
+ }
871
+
872
+ .flight-devtools-info {
873
+ color: var(--text-muted);
874
+ font-size: 11px;
875
+ }
876
+
877
+ .flight-devtools-list {
878
+ padding: 8px;
879
+ }
880
+
881
+ .flight-devtools-section {
882
+ margin-bottom: 16px;
883
+ }
884
+
885
+ .flight-devtools-section-title {
886
+ padding: 8px 8px 4px;
887
+ color: var(--text-muted);
888
+ font-size: 10px;
889
+ font-weight: 600;
890
+ text-transform: uppercase;
891
+ letter-spacing: 0.5px;
892
+ }
893
+
894
+ .flight-devtools-item {
895
+ padding: 8px 10px;
896
+ border-radius: 6px;
897
+ cursor: pointer;
898
+ transition: background 0.15s;
899
+ }
900
+
901
+ .flight-devtools-item:hover {
902
+ background: var(--bg-2);
903
+ }
904
+
905
+ .flight-devtools-item.expanded {
906
+ background: var(--bg-2);
907
+ }
908
+
909
+ .flight-devtools-item-header {
910
+ display: flex;
911
+ align-items: center;
912
+ gap: 8px;
913
+ }
914
+
915
+ .flight-devtools-item-details {
916
+ margin-top: 8px;
917
+ padding: 8px;
918
+ background: var(--bg-3);
919
+ border-radius: 4px;
920
+ }
921
+
922
+ .detail-row {
923
+ display: flex;
924
+ padding: 3px 0;
925
+ }
926
+
927
+ .detail-label {
928
+ width: 80px;
929
+ color: var(--text-muted);
930
+ }
931
+
932
+ .detail-value {
933
+ flex: 1;
934
+ color: var(--text);
935
+ }
936
+
937
+ .detail-value.mono {
938
+ font-family: 'SF Mono', Monaco, monospace;
939
+ font-size: 11px;
940
+ }
941
+
942
+ .method {
943
+ font-weight: 600;
944
+ font-size: 10px;
945
+ padding: 2px 6px;
946
+ border-radius: 3px;
947
+ background: var(--bg-3);
948
+ }
949
+
950
+ .method.get { color: #22c55e; }
951
+ .method.post { color: #3b82f6; }
952
+ .method.put { color: #f59e0b; }
953
+ .method.patch { color: #f59e0b; }
954
+ .method.delete { color: #ef4444; }
955
+
956
+ .path {
957
+ flex: 1;
958
+ font-family: 'SF Mono', Monaco, monospace;
959
+ font-size: 11px;
960
+ color: var(--text);
961
+ overflow: hidden;
962
+ text-overflow: ellipsis;
963
+ white-space: nowrap;
964
+ }
965
+
966
+ .badge {
967
+ font-size: 9px;
968
+ padding: 2px 5px;
969
+ border-radius: 3px;
970
+ background: var(--bg-3);
971
+ color: var(--text-muted);
972
+ }
973
+
974
+ .badge.dynamic { color: #a78bfa; }
975
+ .badge.slot { color: #60a5fa; }
976
+
977
+ .expand-icon {
978
+ color: var(--text-muted);
979
+ font-size: 8px;
980
+ }
981
+
982
+ .status { font-weight: 600; }
983
+ .status.status-2xx { color: #22c55e; }
984
+ .status.status-3xx { color: #f59e0b; }
985
+ .status.status-4xx { color: #ef4444; }
986
+ .status.status-5xx { color: #a855f7; }
987
+
988
+ .duration, .time {
989
+ color: var(--text-muted);
990
+ font-size: 11px;
991
+ }
992
+
993
+ .adapter-icon {
994
+ font-size: 16px;
995
+ }
996
+
997
+ .adapter-name {
998
+ flex: 1;
999
+ font-weight: 500;
1000
+ }
1001
+
1002
+ .adapter-type {
1003
+ color: var(--text-muted);
1004
+ font-size: 10px;
1005
+ }
1006
+
1007
+ .adapter-status {
1008
+ font-size: 10px;
1009
+ padding: 2px 6px;
1010
+ border-radius: 3px;
1011
+ }
1012
+
1013
+ .adapter-status.status-connected { background: rgba(34, 197, 94, 0.2); color: #22c55e; }
1014
+ .adapter-status.status-disconnected { background: rgba(239, 68, 68, 0.2); color: #ef4444; }
1015
+ .adapter-status.status-error { background: rgba(239, 68, 68, 0.2); color: #ef4444; }
1016
+
1017
+ .flight-devtools-metrics {
1018
+ display: grid;
1019
+ grid-template-columns: repeat(3, 1fr);
1020
+ gap: 8px;
1021
+ padding: 8px;
1022
+ }
1023
+
1024
+ .flight-devtools-metric {
1025
+ padding: 12px;
1026
+ background: var(--bg-2);
1027
+ border-radius: 8px;
1028
+ text-align: center;
1029
+ }
1030
+
1031
+ .flight-devtools-metric.good { border-left: 3px solid #22c55e; }
1032
+ .flight-devtools-metric.needs-improvement { border-left: 3px solid #f59e0b; }
1033
+ .flight-devtools-metric.poor { border-left: 3px solid #ef4444; }
1034
+
1035
+ .metric-label {
1036
+ font-weight: 600;
1037
+ font-size: 11px;
1038
+ color: var(--text);
1039
+ }
1040
+
1041
+ .metric-value {
1042
+ font-size: 18px;
1043
+ font-weight: 600;
1044
+ margin: 4px 0;
1045
+ }
1046
+
1047
+ .flight-devtools-metric.good .metric-value { color: #22c55e; }
1048
+ .flight-devtools-metric.needs-improvement .metric-value { color: #f59e0b; }
1049
+ .flight-devtools-metric.poor .metric-value { color: #ef4444; }
1050
+
1051
+ .metric-desc {
1052
+ font-size: 9px;
1053
+ color: var(--text-muted);
1054
+ }
1055
+
1056
+ .flight-devtools-filter-group {
1057
+ display: flex;
1058
+ gap: 4px;
1059
+ }
1060
+
1061
+ .flight-devtools-filter-btn {
1062
+ padding: 4px 8px;
1063
+ background: transparent;
1064
+ border: 1px solid var(--border);
1065
+ border-radius: 4px;
1066
+ color: var(--text-muted);
1067
+ font-size: 10px;
1068
+ cursor: pointer;
1069
+ text-transform: capitalize;
1070
+ }
1071
+
1072
+ .flight-devtools-filter-btn.active {
1073
+ background: var(--green);
1074
+ border-color: var(--green);
1075
+ color: white;
1076
+ }
1077
+
1078
+ .console-list {
1079
+ font-family: 'SF Mono', Monaco, monospace;
1080
+ font-size: 11px;
1081
+ }
1082
+
1083
+ .flight-devtools-console-item {
1084
+ display: flex;
1085
+ gap: 8px;
1086
+ padding: 6px 8px;
1087
+ border-bottom: 1px solid var(--border);
1088
+ }
1089
+
1090
+ .flight-devtools-console-item.level-error {
1091
+ background: rgba(239, 68, 68, 0.1);
1092
+ }
1093
+
1094
+ .flight-devtools-console-item.level-warn {
1095
+ background: rgba(245, 158, 11, 0.1);
1096
+ }
1097
+
1098
+ .console-time {
1099
+ color: var(--text-muted);
1100
+ flex-shrink: 0;
1101
+ }
1102
+
1103
+ .console-level {
1104
+ flex-shrink: 0;
1105
+ width: 40px;
1106
+ font-weight: 600;
1107
+ }
1108
+
1109
+ .level-log .console-level { color: #888; }
1110
+ .level-info .console-level { color: #3b82f6; }
1111
+ .level-warn .console-level { color: #f59e0b; }
1112
+ .level-error .console-level { color: #ef4444; }
1113
+
1114
+ .console-message {
1115
+ flex: 1;
1116
+ word-break: break-word;
1117
+ color: var(--text);
1118
+ }
1119
+
1120
+ .flight-devtools-empty {
1121
+ padding: 40px 20px;
1122
+ text-align: center;
1123
+ color: var(--text-muted);
1124
+ }
1125
+
1126
+ .flight-devtools-empty small {
1127
+ display: block;
1128
+ margin-top: 8px;
1129
+ font-size: 11px;
1130
+ opacity: 0.7;
1131
+ }
1132
+
1133
+ ${hydrationPanelStyles}
1134
+
1135
+ ${bundlePanelStyles}
1136
1136
  `;
1137
1137
  }
1138
1138
  //# sourceMappingURL=panel.js.map