@rozenite/network-activity-plugin 1.0.0-alpha.5 → 1.0.0-alpha.6

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.
Files changed (75) hide show
  1. package/dist/{panel.html → App.html} +3 -3
  2. package/dist/assets/App-CIflVb88.js +24164 -0
  3. package/dist/assets/App-Czu6Vt2P.css +1233 -0
  4. package/dist/react-native.cjs +1 -1
  5. package/dist/react-native.d.ts +1 -90
  6. package/dist/rozenite.config.d.ts +7 -0
  7. package/dist/rozenite.json +1 -1
  8. package/dist/src/react-native/network-inspector.d.ts +8 -0
  9. package/dist/src/react-native/network-requests-registry.d.ts +6 -0
  10. package/dist/src/react-native/useNetworkActivityDevTools.d.ts +2 -0
  11. package/dist/src/react-native/xhr-interceptor.d.ts +38 -0
  12. package/dist/src/shared/client.d.ts +64 -0
  13. package/dist/src/ui/App.d.ts +1 -0
  14. package/dist/src/ui/components/Badge.d.ts +9 -0
  15. package/dist/src/ui/components/Button.d.ts +11 -0
  16. package/dist/src/ui/components/Input.d.ts +3 -0
  17. package/dist/src/ui/components/JsonTree.d.ts +5 -0
  18. package/dist/src/ui/components/RequestList.d.ts +45 -0
  19. package/dist/src/ui/components/ScrollArea.d.ts +4 -0
  20. package/dist/src/ui/components/Separator.d.ts +3 -0
  21. package/dist/src/ui/tabs/CookiesTab.d.ts +8 -0
  22. package/dist/src/ui/tabs/HeadersTab.d.ts +17 -0
  23. package/dist/src/ui/tabs/RequestTab.d.ts +10 -0
  24. package/dist/src/ui/tabs/ResponseTab.d.ts +12 -0
  25. package/dist/src/ui/tabs/TimingTab.d.ts +7 -0
  26. package/dist/src/ui/types.d.ts +23 -0
  27. package/dist/src/ui/utils.d.ts +2 -0
  28. package/dist/src/ui/views/InspectorView.d.ts +5 -0
  29. package/dist/src/ui/views/LoadingView.d.ts +1 -0
  30. package/dist/useNetworkActivityDevTools.cjs +360 -0
  31. package/dist/useNetworkActivityDevTools.js +108 -236
  32. package/package.json +23 -16
  33. package/postcss.config.js +6 -0
  34. package/rozenite.config.ts +1 -1
  35. package/src/react-native/network-inspector.ts +113 -260
  36. package/src/react-native/network-requests-registry.ts +7 -77
  37. package/src/react-native/useNetworkActivityDevTools.ts +1 -1
  38. package/src/react-native/xhr-interceptor.ts +2 -2
  39. package/src/react-native/xml-request.d.ts +11 -1
  40. package/src/shared/client.ts +80 -0
  41. package/src/ui/App.tsx +19 -0
  42. package/src/ui/components/Badge.tsx +36 -0
  43. package/src/ui/components/Button.tsx +56 -0
  44. package/src/ui/components/Input.tsx +22 -0
  45. package/src/ui/components/JsonTree.tsx +37 -0
  46. package/src/ui/components/RequestList.tsx +376 -0
  47. package/src/ui/components/ScrollArea.tsx +48 -0
  48. package/src/ui/components/Separator.tsx +31 -0
  49. package/src/ui/components/Tabs.tsx +55 -0
  50. package/src/ui/globals.css +90 -0
  51. package/src/ui/tabs/CookiesTab.tsx +290 -0
  52. package/src/ui/tabs/HeadersTab.tsx +117 -0
  53. package/src/ui/tabs/RequestTab.tsx +72 -0
  54. package/src/ui/tabs/ResponseTab.tsx +140 -0
  55. package/src/ui/tabs/TimingTab.tsx +71 -0
  56. package/src/ui/types.ts +30 -0
  57. package/src/ui/utils.ts +5 -97
  58. package/src/ui/views/InspectorView.tsx +349 -0
  59. package/src/ui/views/LoadingView.tsx +19 -0
  60. package/tailwind.config.ts +93 -0
  61. package/dist/assets/panel-BNxB_KsS.js +0 -16663
  62. package/dist/assets/panel-DXGMsavf.css +0 -555
  63. package/src/types/client.ts +0 -111
  64. package/src/types/network.ts +0 -32
  65. package/src/ui/components.module.css +0 -158
  66. package/src/ui/components.tsx +0 -241
  67. package/src/ui/network-details.module.css +0 -197
  68. package/src/ui/network-details.tsx +0 -345
  69. package/src/ui/network-list.module.css +0 -128
  70. package/src/ui/network-list.tsx +0 -240
  71. package/src/ui/network-toolbar.module.css +0 -9
  72. package/src/ui/network-toolbar.tsx +0 -34
  73. package/src/ui/panel.module.css +0 -67
  74. package/src/ui/panel.tsx +0 -318
  75. package/src/ui/tanstack-query.tsx +0 -204
@@ -1,345 +0,0 @@
1
- import React, { useState } from 'react';
2
- import { NetworkEntry } from '../types/network';
3
- import { formatFileSize, formatDuration, formatLongUrl } from './utils';
4
- import { Card, EmptyState, Tooltip } from './components';
5
- import styles from './network-details.module.css';
6
-
7
- // Enhanced network entry type to match the panel
8
- type EnhancedNetworkEntry = NetworkEntry & {
9
- type?: string;
10
- initiator?: {
11
- type: string;
12
- url?: string;
13
- lineNumber?: number;
14
- columnNumber?: number;
15
- };
16
- request?: {
17
- url: string;
18
- method: string;
19
- headers: Record<string, string>;
20
- postData?: string;
21
- hasPostData?: boolean;
22
- };
23
- response?: {
24
- url: string;
25
- status: number;
26
- statusText: string;
27
- headers: Record<string, string>;
28
- mimeType: string;
29
- encodedDataLength: number;
30
- responseTime: number;
31
- };
32
- responseBody?: {
33
- body: string;
34
- base64Encoded: boolean;
35
- };
36
- dataLength?: number;
37
- };
38
-
39
- // Symbolication response types
40
- interface SymbolicatedStackFrame {
41
- column: number;
42
- file: string;
43
- lineNumber: number;
44
- methodName: string;
45
- collapse: boolean;
46
- }
47
-
48
- interface CodeFrame {
49
- content: string;
50
- location: {
51
- row: number;
52
- column: number;
53
- };
54
- fileName: string;
55
- }
56
-
57
- interface SymbolicationResponse {
58
- codeFrame: CodeFrame;
59
- stack: SymbolicatedStackFrame[];
60
- }
61
-
62
- interface NetworkDetailsProps {
63
- entry: EnhancedNetworkEntry | null;
64
- onRequestResponseBody?: (requestId: string) => void;
65
- }
66
-
67
- export const NetworkDetails: React.FC<NetworkDetailsProps> = ({
68
- entry,
69
- onRequestResponseBody,
70
- }) => {
71
- const [isSymbolicating, setIsSymbolicating] = useState(false);
72
- const [, forceUpdate] = useState({});
73
-
74
- const symbolicateCaller = async () => {
75
- if (!entry?.initiator) return;
76
-
77
- setIsSymbolicating(true);
78
- try {
79
- const stackData = {
80
- stack: [
81
- {
82
- column: entry.initiator.columnNumber || 0,
83
- file: entry.initiator.url || '',
84
- lineNumber: entry.initiator.lineNumber || 0,
85
- },
86
- ],
87
- };
88
-
89
- const response = await fetch(`${window.location.origin}/symbolicate`, {
90
- method: 'POST',
91
- headers: {
92
- 'Content-Type': 'application/json',
93
- },
94
- body: JSON.stringify(stackData),
95
- });
96
-
97
- if (response.ok) {
98
- const data: SymbolicationResponse = await response.json();
99
-
100
- // Update the entry.initiator with symbolicated data
101
- if (data.stack && data.stack.length > 0) {
102
- const symbolicatedFrame = data.stack[0];
103
- if (entry.initiator) {
104
- entry.initiator.url = symbolicatedFrame.file;
105
- entry.initiator.lineNumber = symbolicatedFrame.lineNumber;
106
- entry.initiator.columnNumber = symbolicatedFrame.column;
107
- // Add method name to initiator
108
- (entry.initiator as any).methodName = symbolicatedFrame.methodName;
109
- }
110
- }
111
- forceUpdate({});
112
- } else {
113
- console.error('Symbolication failed:', response.statusText);
114
- }
115
- } catch (error) {
116
- console.error('Symbolication error:', error);
117
- } finally {
118
- setIsSymbolicating(false);
119
- }
120
- };
121
-
122
- if (!entry) {
123
- return <EmptyState message="Select a request to view details" />;
124
- }
125
-
126
- return (
127
- <div className={styles.container}>
128
- {/* General Information */}
129
- <Card className={styles.card}>
130
- <h3 className={styles.cardTitle}>General</h3>
131
- <div className={styles.infoText}>
132
- <div className={styles.infoRowUrl}>
133
- <strong>Request URL:</strong>
134
- <Tooltip content={entry.url} showOnlyWhenTruncated>
135
- <span className={styles.urlText}>
136
- {formatLongUrl(entry.url, 100)}
137
- </span>
138
- </Tooltip>
139
- </div>
140
- <div className={styles.infoRow}>
141
- <strong>Request Method:</strong> {entry.method}
142
- </div>
143
- <div className={styles.infoRow}>
144
- <strong>Status Code:</strong> {entry.response?.status || 'Pending'}
145
- </div>
146
- <div className={styles.infoRow}>
147
- <strong>Status:</strong> {entry.status}
148
- </div>
149
- {entry.type && (
150
- <div className={styles.infoRow}>
151
- <strong>Resource Type:</strong> {entry.type}
152
- </div>
153
- )}
154
- {entry.initiator && (
155
- <div className={styles.infoRow}>
156
- <strong>Initiator:</strong> {entry.initiator.type}
157
- {(entry.initiator as any).methodName && (
158
- <div className={styles.infoRowSub}>
159
- <strong>Method:</strong> {(entry.initiator as any).methodName}
160
- </div>
161
- )}
162
- {entry.initiator.url && (
163
- <div className={styles.infoRowSub}>
164
- <strong>URL:</strong> {entry.initiator.url}
165
- </div>
166
- )}
167
- {entry.initiator.lineNumber && (
168
- <div className={styles.infoRowSub}>
169
- <strong>Line:</strong> {entry.initiator.lineNumber}:
170
- {entry.initiator.columnNumber || 0}
171
- </div>
172
- )}
173
- <div className={styles.infoRowSub}>
174
- <button
175
- className={styles.symbolicateButton}
176
- onClick={symbolicateCaller}
177
- disabled={isSymbolicating}
178
- >
179
- {isSymbolicating
180
- ? 'Symbolicating...'
181
- : 'Symbolicate initiator'}
182
- </button>
183
- </div>
184
- </div>
185
- )}
186
- </div>
187
- </Card>
188
-
189
- {/* Response Headers */}
190
- {entry.response && (
191
- <Card className={styles.card}>
192
- <h3 className={styles.cardTitle}>Response Headers</h3>
193
- <div className={styles.headersContainer}>
194
- {Object.entries(entry.response.headers).map(([key, value]) => (
195
- <div key={key} className={styles.headerRow}>
196
- <strong>{key}:</strong>
197
- <Tooltip content={value} showOnlyWhenTruncated>
198
- <span className={styles.headerValue}>{value}</span>
199
- </Tooltip>
200
- </div>
201
- ))}
202
- </div>
203
- </Card>
204
- )}
205
-
206
- {/* Request Headers */}
207
- <Card className={styles.card}>
208
- <h3 className={styles.cardTitle}>Request Headers</h3>
209
- <div className={styles.headersContainer}>
210
- {Object.entries(entry.headers).map(([key, value]) => (
211
- <div key={key} className={styles.headerRow}>
212
- <strong>{key}:</strong>
213
- <Tooltip content={value} showOnlyWhenTruncated>
214
- <span className={styles.headerValue}>{value}</span>
215
- </Tooltip>
216
- </div>
217
- ))}
218
- </div>
219
- </Card>
220
-
221
- {/* Size Information */}
222
- {(entry.encodedDataLength || entry.dataLength) && (
223
- <Card className={styles.card}>
224
- <h3 className={styles.cardTitle}>Size Information</h3>
225
- <div className={styles.infoText}>
226
- {entry.dataLength && (
227
- <div className={styles.infoRow}>
228
- <strong>Data Length:</strong> {formatFileSize(entry.dataLength)}
229
- </div>
230
- )}
231
- {entry.encodedDataLength && (
232
- <div className={styles.infoRow}>
233
- <strong>Encoded Data Length:</strong>{' '}
234
- {formatFileSize(entry.encodedDataLength)}
235
- </div>
236
- )}
237
- {entry.response?.mimeType && (
238
- <div className={styles.infoRow}>
239
- <strong>MIME Type:</strong> {entry.response.mimeType}
240
- </div>
241
- )}
242
- </div>
243
- </Card>
244
- )}
245
-
246
- {/* Timing Information */}
247
- {entry.duration && (
248
- <Card className={styles.card}>
249
- <h3 className={styles.cardTitle}>Timing</h3>
250
- <div className={styles.infoText}>
251
- <div className={styles.infoRow}>
252
- <strong>Duration:</strong> {formatDuration(entry.duration)}
253
- </div>
254
- <div className={styles.infoRow}>
255
- <strong>Start Time:</strong>{' '}
256
- {new Date(entry.startTime).toLocaleTimeString()}
257
- </div>
258
- {entry.endTime && (
259
- <div className={styles.infoRow}>
260
- <strong>End Time:</strong>{' '}
261
- {new Date(entry.endTime).toLocaleTimeString()}
262
- </div>
263
- )}
264
- {entry.response?.responseTime && (
265
- <div className={styles.infoRow}>
266
- <strong>Response Time:</strong>{' '}
267
- {new Date(entry.response.responseTime).toLocaleTimeString()}
268
- </div>
269
- )}
270
- </div>
271
- </Card>
272
- )}
273
-
274
- {/* Error Information */}
275
- {entry.status === 'failed' && (
276
- <Card className={styles.card}>
277
- <h3 className={styles.cardTitle}>Error Information</h3>
278
- <div className={styles.infoText}>
279
- <div className={styles.infoRow}>
280
- <strong>Error:</strong> {entry.errorText || 'Unknown error'}
281
- </div>
282
- <div className={styles.infoRow}>
283
- <strong>Canceled:</strong> {entry.canceled ? 'Yes' : 'No'}
284
- </div>
285
- </div>
286
- </Card>
287
- )}
288
-
289
- {/* Post Data */}
290
- {entry.postData && (
291
- <Card className={styles.card}>
292
- <h3 className={styles.cardTitle}>Post Data</h3>
293
- <div className={styles.postDataContainer}>
294
- <pre className={styles.postDataText}>{entry.postData}</pre>
295
- </div>
296
- </Card>
297
- )}
298
-
299
- {/* Response Body */}
300
- {entry.response && (
301
- <Card className={styles.card}>
302
- <h3 className={styles.cardTitle}>Response Body</h3>
303
- {entry.responseBody ? (
304
- <div className={styles.responseBodyContainer}>
305
- <pre className={styles.responseBodyText}>
306
- {entry.responseBody.base64Encoded
307
- ? atob(entry.responseBody.body)
308
- : entry.responseBody.body}
309
- </pre>
310
- </div>
311
- ) : (
312
- <div className={styles.responseBodyContainer}>
313
- <button
314
- className={styles.loadResponseBodyButton}
315
- onClick={() => onRequestResponseBody?.(entry.requestId)}
316
- disabled={!onRequestResponseBody}
317
- >
318
- Load Response Body
319
- </button>
320
- </div>
321
- )}
322
- </Card>
323
- )}
324
-
325
- {/* Request Details */}
326
- {entry.request && (
327
- <Card className={styles.card}>
328
- <h3 className={styles.cardTitle}>Request Details</h3>
329
- <div className={styles.infoText}>
330
- <div className={styles.infoRow}>
331
- <strong>Has Post Data:</strong>{' '}
332
- {entry.request.hasPostData ? 'Yes' : 'No'}
333
- </div>
334
- {entry.request.postData && (
335
- <div className={styles.infoRow}>
336
- <strong>Post Data Length:</strong>{' '}
337
- {entry.request.postData.length} characters
338
- </div>
339
- )}
340
- </div>
341
- </Card>
342
- )}
343
- </div>
344
- );
345
- };
@@ -1,128 +0,0 @@
1
- .container {
2
- height: 100%;
3
- overflow: auto;
4
- }
5
-
6
- .virtualContainer {
7
- height: 100%;
8
- width: 100%;
9
- position: relative;
10
- }
11
-
12
- .virtualItem {
13
- position: absolute;
14
- top: 0;
15
- left: 0;
16
- width: 100%;
17
- height: 60px;
18
- }
19
-
20
- .listItem {
21
- display: flex;
22
- align-items: center;
23
- padding: 8px 12px;
24
- border-bottom: 1px solid #e0e0e0;
25
- background-color: white;
26
- cursor: pointer;
27
- font-size: 12px;
28
- font-family: monospace;
29
- height: 60px;
30
- box-sizing: border-box;
31
- min-width: 0;
32
- }
33
-
34
- .listItemSelected {
35
- display: flex;
36
- align-items: center;
37
- padding: 8px 12px;
38
- border-bottom: 1px solid #e0e0e0;
39
- background-color: #f5f5f5;
40
- cursor: pointer;
41
- font-size: 12px;
42
- font-family: monospace;
43
- height: 60px;
44
- box-sizing: border-box;
45
- min-width: 0;
46
- }
47
-
48
- .statusColumn {
49
- width: 60px;
50
- text-align: center;
51
- flex-shrink: 0;
52
- }
53
-
54
- .methodColumn {
55
- width: 80px;
56
- text-align: center;
57
- flex-shrink: 0;
58
- }
59
-
60
- .urlColumn {
61
- flex: 1;
62
- overflow: hidden;
63
- min-width: 0;
64
- }
65
-
66
- .typeColumn {
67
- width: 100px;
68
- text-align: center;
69
- flex-shrink: 0;
70
- }
71
-
72
- .domainText {
73
- font-weight: bold;
74
- color: #333;
75
- margin-bottom: 2px;
76
- white-space: nowrap;
77
- overflow: hidden;
78
- text-overflow: ellipsis;
79
- }
80
-
81
- .pathText {
82
- color: #666;
83
- font-size: 11px;
84
- white-space: nowrap;
85
- overflow: hidden;
86
- text-overflow: ellipsis;
87
- }
88
-
89
- .fullUrlText {
90
- color: #999;
91
- font-size: 10px;
92
- white-space: nowrap;
93
- overflow: hidden;
94
- text-overflow: ellipsis;
95
- margin-top: 1px;
96
- }
97
-
98
- .durationColumn {
99
- width: 80px;
100
- text-align: right;
101
- margin-right: 8px;
102
- flex-shrink: 0;
103
- }
104
-
105
- .sizeColumn {
106
- width: 80px;
107
- text-align: right;
108
- flex-shrink: 0;
109
- }
110
-
111
- .columnText {
112
- white-space: nowrap;
113
- overflow: hidden;
114
- text-overflow: ellipsis;
115
- display: block;
116
- }
117
-
118
- .emptyContainer {
119
- height: 100%;
120
- display: flex;
121
- align-items: center;
122
- justify-content: center;
123
- }
124
-
125
- .emptyText {
126
- color: #666;
127
- font-size: 14px;
128
- }
@@ -1,240 +0,0 @@
1
- import React from 'react';
2
- import { useVirtualizer } from '@tanstack/react-virtual';
3
- import { NetworkEntry } from '../types/network';
4
- import {
5
- getStatusColor,
6
- getMethodColor,
7
- formatDuration,
8
- formatFileSize,
9
- parseUrl,
10
- } from './utils';
11
- import { Badge, Tooltip } from './components';
12
- import styles from './network-list.module.css';
13
-
14
- // Enhanced network entry type to match the panel
15
- type EnhancedNetworkEntry = NetworkEntry & {
16
- type?: string;
17
- initiator?: {
18
- type: string;
19
- url?: string;
20
- lineNumber?: number;
21
- columnNumber?: number;
22
- };
23
- request?: {
24
- url: string;
25
- method: string;
26
- headers: Record<string, string>;
27
- postData?: string;
28
- hasPostData?: boolean;
29
- };
30
- response?: {
31
- url: string;
32
- status: number;
33
- statusText: string;
34
- headers: Record<string, string>;
35
- mimeType: string;
36
- encodedDataLength: number;
37
- responseTime: number;
38
- };
39
- dataLength?: number;
40
- };
41
-
42
- interface NetworkListProps {
43
- entries: EnhancedNetworkEntry[];
44
- selectedRequestId: string | null;
45
- onSelect: (requestId: string) => void;
46
- height: number;
47
- }
48
-
49
- const ITEM_HEIGHT = 60; // Height of each network list item
50
-
51
- const getResourceTypeColor = (type: string): string => {
52
- switch (type) {
53
- case 'Document':
54
- return '#4285f4';
55
- case 'Stylesheet':
56
- return '#34a853';
57
- case 'Script':
58
- return '#fbbc04';
59
- case 'Image':
60
- return '#ea4335';
61
- case 'Font':
62
- return '#9c27b0';
63
- case 'XHR':
64
- return '#ff9800';
65
- case 'Fetch':
66
- return '#2196f3';
67
- case 'WebSocket':
68
- return '#00bcd4';
69
- case 'Media':
70
- return '#e91e63';
71
- default:
72
- return '#757575';
73
- }
74
- };
75
-
76
- const getStatusDisplay = (
77
- entry: EnhancedNetworkEntry
78
- ): { text: string; color: string } => {
79
- if (entry.status === 'failed') {
80
- return { text: 'Failed', color: '#d32f2f' };
81
- }
82
- if (entry.status === 'pending') {
83
- return { text: 'Pending', color: '#ff9800' };
84
- }
85
- if (entry.status === 'loading') {
86
- return { text: 'Loading', color: '#2196f3' };
87
- }
88
- if (entry.status === 'finished') {
89
- const status = entry.response?.status || 0;
90
- if (status >= 400) {
91
- return { text: status.toString(), color: '#d32f2f' };
92
- }
93
- if (status >= 300) {
94
- return { text: status.toString(), color: '#ff9800' };
95
- }
96
- return { text: status.toString(), color: '#4caf50' };
97
- }
98
- return { text: '...', color: '#757575' };
99
- };
100
-
101
- export const NetworkList: React.FC<NetworkListProps> = ({
102
- entries,
103
- selectedRequestId,
104
- onSelect,
105
- height,
106
- }) => {
107
- const parentRef = React.useRef<HTMLDivElement>(null);
108
-
109
- const virtualizer = useVirtualizer({
110
- count: entries.length,
111
- getScrollElement: () => parentRef.current,
112
- estimateSize: () => ITEM_HEIGHT,
113
- overscan: 5,
114
- });
115
-
116
- const NetworkListItem: React.FC<{
117
- entry: EnhancedNetworkEntry;
118
- index: number;
119
- }> = ({ entry, index }) => {
120
- const method = entry.method;
121
- const url = entry.url;
122
- const { domain, path } = parseUrl(url);
123
- const resourceType = entry.type || 'Other';
124
-
125
- // Get size information - prefer dataLength over encodedDataLength for display
126
- const displaySize = entry.dataLength || entry.encodedDataLength || 0;
127
- const statusDisplay = getStatusDisplay(entry);
128
-
129
- const isSelected = selectedRequestId === entry.requestId;
130
-
131
- return (
132
- <div
133
- className={isSelected ? styles.listItemSelected : styles.listItem}
134
- onClick={() => onSelect(entry.requestId)}
135
- >
136
- <div className={styles.statusColumn}>
137
- <Tooltip
138
- content={`Status: ${statusDisplay.text}`}
139
- showOnlyWhenTruncated
140
- variant={
141
- statusDisplay.color === '#d32f2f'
142
- ? 'error'
143
- : statusDisplay.color === '#ff9800'
144
- ? 'warning'
145
- : 'info'
146
- }
147
- >
148
- <Badge color={statusDisplay.color}>{statusDisplay.text}</Badge>
149
- </Tooltip>
150
- </div>
151
- <div className={styles.methodColumn}>
152
- <Tooltip
153
- content={`Method: ${method}`}
154
- showOnlyWhenTruncated
155
- variant="info"
156
- >
157
- <Badge color={getMethodColor(method)}>{method}</Badge>
158
- </Tooltip>
159
- </div>
160
- <div className={styles.urlColumn}>
161
- <Tooltip content={domain} showOnlyWhenTruncated>
162
- <div className={styles.domainText}>{domain}</div>
163
- </Tooltip>
164
- <Tooltip content={path} showOnlyWhenTruncated>
165
- <div className={styles.pathText}>{path}</div>
166
- </Tooltip>
167
- <Tooltip content={url} showOnlyWhenTruncated>
168
- <div className={styles.fullUrlText}>{url}</div>
169
- </Tooltip>
170
- </div>
171
- <div className={styles.typeColumn}>
172
- <Tooltip
173
- content={`Resource Type: ${resourceType}`}
174
- showOnlyWhenTruncated
175
- variant="info"
176
- >
177
- <Badge color={getResourceTypeColor(resourceType)}>
178
- {resourceType}
179
- </Badge>
180
- </Tooltip>
181
- </div>
182
- <div className={styles.durationColumn}>
183
- <Tooltip
184
- content={`Duration: ${
185
- entry.duration ? formatDuration(entry.duration) : 'Pending'
186
- }`}
187
- showOnlyWhenTruncated
188
- >
189
- <span className={styles.columnText}>
190
- {entry.duration ? formatDuration(entry.duration) : '...'}
191
- </span>
192
- </Tooltip>
193
- </div>
194
- <div className={styles.sizeColumn}>
195
- <Tooltip
196
- content={`Size: ${
197
- displaySize > 0 ? formatFileSize(displaySize) : 'Unknown'
198
- }`}
199
- showOnlyWhenTruncated
200
- >
201
- <span className={styles.columnText}>
202
- {displaySize > 0 ? formatFileSize(displaySize) : '...'}
203
- </span>
204
- </Tooltip>
205
- </div>
206
- </div>
207
- );
208
- };
209
-
210
- return (
211
- <div ref={parentRef} className={styles.networkList} style={{ height }}>
212
- <div
213
- style={{
214
- height: `${virtualizer.getTotalSize()}px`,
215
- width: '100%',
216
- position: 'relative',
217
- }}
218
- >
219
- {virtualizer.getVirtualItems().map((virtualItem) => (
220
- <div
221
- key={virtualItem.key}
222
- style={{
223
- position: 'absolute',
224
- top: 0,
225
- left: 0,
226
- width: '100%',
227
- height: `${virtualItem.size}px`,
228
- transform: `translateY(${virtualItem.start}px)`,
229
- }}
230
- >
231
- <NetworkListItem
232
- entry={entries[virtualItem.index]}
233
- index={virtualItem.index}
234
- />
235
- </div>
236
- ))}
237
- </div>
238
- </div>
239
- );
240
- };