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