@buoy-gg/network 7.0.14 → 7.0.16

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 (107) hide show
  1. package/lib/commonjs/index.web.js +395 -0
  2. package/lib/commonjs/network/components/DataViewer.web.js +879 -0
  3. package/lib/commonjs/network/components/NetworkCopyScreen.web.js +48 -0
  4. package/lib/commonjs/network/components/NetworkCopySettingsView.web.js +1242 -0
  5. package/lib/commonjs/network/components/NetworkDetailScreen.web.js +101 -0
  6. package/lib/commonjs/network/components/NetworkDetailStepper.web.js +296 -0
  7. package/lib/commonjs/network/components/NetworkEventDetailView.web.js +1498 -0
  8. package/lib/commonjs/network/components/NetworkEventItemCompact.web.js +802 -0
  9. package/lib/commonjs/network/components/NetworkFilterScreen.web.js +55 -0
  10. package/lib/commonjs/network/components/NetworkFilterViewV3.web.js +1310 -0
  11. package/lib/commonjs/network/components/NetworkHeaderLive.web.js +604 -0
  12. package/lib/commonjs/network/components/NetworkListScreen.js +2 -1
  13. package/lib/commonjs/network/components/NetworkListScreen.web.js +607 -0
  14. package/lib/commonjs/network/components/NetworkModal.js +12 -3
  15. package/lib/commonjs/network/components/NetworkNumberPrompt.web.js +232 -0
  16. package/lib/commonjs/network/components/NetworkOverrideEditor.web.js +942 -0
  17. package/lib/commonjs/network/components/NetworkOverrideHeaderButton.web.js +133 -0
  18. package/lib/commonjs/network/components/NetworkOverridesButton.web.js +143 -0
  19. package/lib/commonjs/network/components/NetworkOverridesScreen.js +160 -126
  20. package/lib/commonjs/network/components/NetworkOverridesScreen.web.js +830 -0
  21. package/lib/commonjs/network/components/NetworkSavedScreen.web.js +459 -0
  22. package/lib/commonjs/network/components/response-editor/Explorer.web.js +1136 -0
  23. package/lib/commonjs/network/hooks/useNetworkEventList.js +12 -2
  24. package/lib/commonjs/network/overrides/applyToXhr.js +276 -15
  25. package/lib/commonjs/network/utils/generateNetworkCopyText.js +32 -5
  26. package/lib/commonjs/network/utils/networkEventStore.js +12 -4
  27. package/lib/commonjs/network/utils/networkListener.js +1 -16
  28. package/lib/module/index.web.js +81 -0
  29. package/lib/module/network/components/DataViewer.web.js +875 -0
  30. package/lib/module/network/components/NetworkCopyScreen.web.js +44 -0
  31. package/lib/module/network/components/NetworkCopySettingsView.web.js +1237 -0
  32. package/lib/module/network/components/NetworkDetailScreen.web.js +97 -0
  33. package/lib/module/network/components/NetworkDetailStepper.web.js +294 -0
  34. package/lib/module/network/components/NetworkEventDetailView.web.js +1496 -0
  35. package/lib/module/network/components/NetworkEventItemCompact.web.js +800 -0
  36. package/lib/module/network/components/NetworkFilterScreen.web.js +51 -0
  37. package/lib/module/network/components/NetworkFilterViewV3.web.js +1306 -0
  38. package/lib/module/network/components/NetworkHeaderLive.web.js +598 -0
  39. package/lib/module/network/components/NetworkListScreen.js +2 -1
  40. package/lib/module/network/components/NetworkListScreen.web.js +605 -0
  41. package/lib/module/network/components/NetworkModal.js +12 -3
  42. package/lib/module/network/components/NetworkNumberPrompt.web.js +230 -0
  43. package/lib/module/network/components/NetworkOverrideEditor.web.js +939 -0
  44. package/lib/module/network/components/NetworkOverrideHeaderButton.web.js +131 -0
  45. package/lib/module/network/components/NetworkOverridesButton.web.js +141 -0
  46. package/lib/module/network/components/NetworkOverridesScreen.js +161 -127
  47. package/lib/module/network/components/NetworkOverridesScreen.web.js +826 -0
  48. package/lib/module/network/components/NetworkSavedScreen.web.js +457 -0
  49. package/lib/module/network/components/response-editor/Explorer.web.js +1133 -0
  50. package/lib/module/network/hooks/useNetworkEventList.js +12 -2
  51. package/lib/module/network/overrides/applyToXhr.js +275 -15
  52. package/lib/module/network/utils/generateNetworkCopyText.js +28 -1
  53. package/lib/module/network/utils/networkEventStore.js +12 -4
  54. package/lib/module/network/utils/networkListener.js +1 -16
  55. package/lib/typescript/index.web.d.ts +56 -0
  56. package/lib/typescript/index.web.d.ts.map +1 -0
  57. package/lib/typescript/network/components/DataViewer.web.d.ts +78 -0
  58. package/lib/typescript/network/components/DataViewer.web.d.ts.map +1 -0
  59. package/lib/typescript/network/components/NetworkCopyScreen.web.d.ts +27 -0
  60. package/lib/typescript/network/components/NetworkCopyScreen.web.d.ts.map +1 -0
  61. package/lib/typescript/network/components/NetworkCopySettingsView.web.d.ts +68 -0
  62. package/lib/typescript/network/components/NetworkCopySettingsView.web.d.ts.map +1 -0
  63. package/lib/typescript/network/components/NetworkDetailScreen.web.d.ts +45 -0
  64. package/lib/typescript/network/components/NetworkDetailScreen.web.d.ts.map +1 -0
  65. package/lib/typescript/network/components/NetworkDetailStepper.web.d.ts +40 -0
  66. package/lib/typescript/network/components/NetworkDetailStepper.web.d.ts.map +1 -0
  67. package/lib/typescript/network/components/NetworkEventDetailView.web.d.ts +67 -0
  68. package/lib/typescript/network/components/NetworkEventDetailView.web.d.ts.map +1 -0
  69. package/lib/typescript/network/components/NetworkEventItemCompact.web.d.ts +58 -0
  70. package/lib/typescript/network/components/NetworkEventItemCompact.web.d.ts.map +1 -0
  71. package/lib/typescript/network/components/NetworkFilterScreen.web.d.ts +28 -0
  72. package/lib/typescript/network/components/NetworkFilterScreen.web.d.ts.map +1 -0
  73. package/lib/typescript/network/components/NetworkFilterViewV3.web.d.ts +74 -0
  74. package/lib/typescript/network/components/NetworkFilterViewV3.web.d.ts.map +1 -0
  75. package/lib/typescript/network/components/NetworkHeaderLive.web.d.ts +112 -0
  76. package/lib/typescript/network/components/NetworkHeaderLive.web.d.ts.map +1 -0
  77. package/lib/typescript/network/components/NetworkListScreen.d.ts.map +1 -1
  78. package/lib/typescript/network/components/NetworkListScreen.web.d.ts +63 -0
  79. package/lib/typescript/network/components/NetworkListScreen.web.d.ts.map +1 -0
  80. package/lib/typescript/network/components/NetworkModal.d.ts.map +1 -1
  81. package/lib/typescript/network/components/NetworkNumberPrompt.web.d.ts +38 -0
  82. package/lib/typescript/network/components/NetworkNumberPrompt.web.d.ts.map +1 -0
  83. package/lib/typescript/network/components/NetworkOverrideEditor.web.d.ts +43 -0
  84. package/lib/typescript/network/components/NetworkOverrideEditor.web.d.ts.map +1 -0
  85. package/lib/typescript/network/components/NetworkOverrideHeaderButton.web.d.ts +32 -0
  86. package/lib/typescript/network/components/NetworkOverrideHeaderButton.web.d.ts.map +1 -0
  87. package/lib/typescript/network/components/NetworkOverridesButton.web.d.ts +26 -0
  88. package/lib/typescript/network/components/NetworkOverridesButton.web.d.ts.map +1 -0
  89. package/lib/typescript/network/components/NetworkOverridesScreen.d.ts +9 -0
  90. package/lib/typescript/network/components/NetworkOverridesScreen.d.ts.map +1 -1
  91. package/lib/typescript/network/components/NetworkOverridesScreen.web.d.ts +69 -0
  92. package/lib/typescript/network/components/NetworkOverridesScreen.web.d.ts.map +1 -0
  93. package/lib/typescript/network/components/NetworkSavedScreen.web.d.ts +67 -0
  94. package/lib/typescript/network/components/NetworkSavedScreen.web.d.ts.map +1 -0
  95. package/lib/typescript/network/components/response-editor/Explorer.web.d.ts +56 -0
  96. package/lib/typescript/network/components/response-editor/Explorer.web.d.ts.map +1 -0
  97. package/lib/typescript/network/hooks/useNetworkEventList.d.ts +10 -0
  98. package/lib/typescript/network/hooks/useNetworkEventList.d.ts.map +1 -1
  99. package/lib/typescript/network/overrides/__tests__/applyToXhr.test.d.ts.map +1 -1
  100. package/lib/typescript/network/overrides/applyToXhr.d.ts +40 -14
  101. package/lib/typescript/network/overrides/applyToXhr.d.ts.map +1 -1
  102. package/lib/typescript/network/utils/generateNetworkCopyText.d.ts +34 -1
  103. package/lib/typescript/network/utils/generateNetworkCopyText.d.ts.map +1 -1
  104. package/lib/typescript/network/utils/networkEventStore.d.ts.map +1 -1
  105. package/lib/typescript/network/utils/networkListener.d.ts +0 -1
  106. package/lib/typescript/network/utils/networkListener.d.ts.map +1 -1
  107. package/package.json +2 -2
@@ -0,0 +1,1498 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.NetworkEventDetailView = void 0;
7
+ var _react = require("react");
8
+ var _formatGraphQLVariables = require("../utils/formatGraphQLVariables");
9
+ var _networkBodyResolver = require("../sync/networkBodyResolver");
10
+ var _DataViewer = require("./DataViewer.web");
11
+ var _jsxRuntime = require("react/jsx-runtime");
12
+ /**
13
+ * NetworkEventDetailView.web — DOM twin of NetworkEventDetailView.tsx.
14
+ *
15
+ * The request DETAIL inspector: method/status/duration header row, URL
16
+ * breakdown (with collapsible query parameters), error box, timing card
17
+ * (Started + Sent/Received + the two real timing-phase bars), collapsible
18
+ * Request/Response Headers, Request/Response Body (JSON trees, response
19
+ * expanded on arrival), and the Filter Options section — same section order,
20
+ * labels, defaults and styling as native. The data layer is REUSED, not
21
+ * forked: `useNetworkBodyResolver` (plain React context), `formatGraphQLDisplay`
22
+ * and the `NetworkEvent`/`NetworkTimings` types are the same modules native
23
+ * uses; `showBodies` carries the same settle-window contract (see the native
24
+ * file's prop doc) with the same fixed-height `BodyDeferred` stand-in.
25
+ *
26
+ * shared-ui RN chrome is replicated as DOM with provenance (web consumers
27
+ * resolve `@buoy-gg/shared-ui` to a minimal shim):
28
+ * - `macOSColors` — inlined verbatim subset from
29
+ * shared/src/ui/gameUI/constants/macOSDesignSystemColors.ts.
30
+ * - Icons — inline lucide SVGs (shared-ui's icons are lucide re-exports).
31
+ * - `formatBytes` / `formatDuration` — copied verbatim from
32
+ * shared/src/utils/formatting/dataFormatting.ts (not in the web shim).
33
+ * - `formatHttpStatus` — copied verbatim from
34
+ * shared/src/utils/formatting/httpFormatting.ts; its `gameUIColors` are the
35
+ * macOS theme, so the color table below carries the same resolved values.
36
+ * - `formatRelativeTime` — copied verbatim from
37
+ * shared/src/utils/time/formatRelativeTime.ts.
38
+ * - `DataViewer` / `InlineCopyButton` — DOM twins in ./DataViewer.web.
39
+ *
40
+ * Intentional deviations (all logged):
41
+ * - License gating isn't part of the web port: the view renders the Pro path
42
+ * (`isPro = true` everywhere native branches) — copy buttons are real
43
+ * clipboard copies, never upgrade prompts — and shared-ui's `UpgradeModal`
44
+ * is therefore not mounted (`useFeatureGate` lives behind @buoy-gg/license,
45
+ * outside the web port).
46
+ * - Copy affordances use `navigator.clipboard` via the CopyButton twin; the
47
+ * full-request copy keeps native's LAZY function value so no markdown is
48
+ * built per render.
49
+ * - Relative time ("12s ago") refreshes on re-render only — native mounts a
50
+ * `TickProvider` at the modal root; the web port's live-event subscription
51
+ * re-renders an open detail on every store update, which covers it in
52
+ * practice for in-flight requests.
53
+ *
54
+ * @platform React DOM Web
55
+ */
56
+
57
+ // =============================
58
+ // Native palettes (provenance)
59
+ // =============================
60
+
61
+ /** macOSColors subset — shared/src/ui/gameUI/constants/macOSDesignSystemColors.ts, verbatim. */const macOSColors = {
62
+ background: {
63
+ base: "#0A0A0C",
64
+ card: "#1A1A1C",
65
+ hover: "#1D1D1F",
66
+ input: "#26262A"
67
+ },
68
+ border: {
69
+ default: "#2D2D2F"
70
+ },
71
+ text: {
72
+ primary: "#F5F5F7",
73
+ secondary: "#A1A1A6",
74
+ muted: "#8E8E93"
75
+ },
76
+ semantic: {
77
+ success: "#34C759",
78
+ error: "#FF453A",
79
+ errorBackground: "rgba(255, 69, 58, 0.15)",
80
+ warning: "#FFEB3B",
81
+ warningBackground: "rgba(255, 235, 59, 0.15)",
82
+ info: "#00B8E6",
83
+ infoBackground: "rgba(0, 184, 230, 0.1)"
84
+ }
85
+ };
86
+
87
+ /**
88
+ * Colour for the icons that merely LABEL a section (Sent/Received, the JSON
89
+ * body glyphs) — same rationale as native.
90
+ */
91
+ const NEUTRAL_ICON = macOSColors.semantic.success;
92
+
93
+ // =============================
94
+ // Formatting utils (provenance: shared/src/utils — not in the web shim)
95
+ // =============================
96
+
97
+ /** shared/src/utils/formatting/dataFormatting.ts `formatBytes`, verbatim. */
98
+ function formatBytes(bytes) {
99
+ if (bytes === undefined || bytes === null) return "N/A";
100
+ if (bytes === 0) return "0 B";
101
+ const k = 1024;
102
+ const sizes = ["B", "KB", "MB", "GB", "TB"];
103
+ const i = Math.floor(Math.log(bytes) / Math.log(k));
104
+ return `${(bytes / Math.pow(k, i)).toFixed(1)} ${sizes[i]}`;
105
+ }
106
+
107
+ /** shared/src/utils/formatting/dataFormatting.ts `formatDuration`, verbatim. */
108
+ function formatDuration(ms) {
109
+ if (ms === undefined || ms === null) return "N/A";
110
+ if (ms < 1000) return `${ms}ms`;
111
+ if (ms < 60000) return `${(ms / 1000).toFixed(1)}s`;
112
+ if (ms < 3600000) {
113
+ const minutes = Math.floor(ms / 60000);
114
+ const seconds = Math.floor(ms % 60000 / 1000);
115
+ return seconds > 0 ? `${minutes}m ${seconds}s` : `${minutes}m`;
116
+ }
117
+ const hours = Math.floor(ms / 3600000);
118
+ const minutes = Math.floor(ms % 3600000 / 60000);
119
+ return minutes > 0 ? `${hours}h ${minutes}m` : `${hours}h`;
120
+ }
121
+
122
+ /** shared/src/utils/time/formatRelativeTime.ts, verbatim. */
123
+ function formatRelativeTime(timestamp, currentTime = Date.now()) {
124
+ const timestampMs = timestamp instanceof Date ? timestamp.getTime() : timestamp;
125
+ const seconds = Math.floor((currentTime - timestampMs) / 1000);
126
+ if (seconds < 0) return "just now";
127
+ if (seconds < 60) return seconds === 0 ? "just now" : `${seconds}s ago`;
128
+ const minutes = Math.floor(seconds / 60);
129
+ if (minutes < 60) return `${minutes}m ago`;
130
+ const hours = Math.floor(minutes / 60);
131
+ if (hours < 24) return `${hours}h ago`;
132
+ const days = Math.floor(hours / 24);
133
+ return `${days}d ago`;
134
+ }
135
+
136
+ /**
137
+ * shared/src/utils/formatting/httpFormatting.ts `formatHttpStatus`, verbatim —
138
+ * its `gameUIColors` resolve to the macOS theme's semantic values (the same
139
+ * `macOSColors.semantic` palette inlined above; muted = text.muted).
140
+ */
141
+ function formatHttpStatus(status) {
142
+ if (status >= 100 && status < 200) {
143
+ return {
144
+ text: String(status),
145
+ color: macOSColors.semantic.info,
146
+ meaning: "Informational"
147
+ };
148
+ }
149
+ if (status >= 200 && status < 300) {
150
+ const meanings = {
151
+ 200: "OK",
152
+ 201: "Created",
153
+ 202: "Accepted",
154
+ 204: "No Content",
155
+ 206: "Partial Content"
156
+ };
157
+ return {
158
+ text: String(status),
159
+ color: macOSColors.semantic.success,
160
+ meaning: meanings[status] || "Success"
161
+ };
162
+ }
163
+ if (status >= 300 && status < 400) {
164
+ const meanings = {
165
+ 301: "Moved Permanently",
166
+ 302: "Found",
167
+ 303: "See Other",
168
+ 304: "Not Modified",
169
+ 307: "Temporary Redirect",
170
+ 308: "Permanent Redirect"
171
+ };
172
+ return {
173
+ text: String(status),
174
+ color: macOSColors.semantic.warning,
175
+ meaning: meanings[status] || "Redirect"
176
+ };
177
+ }
178
+ if (status >= 400 && status < 500) {
179
+ const meanings = {
180
+ 400: "Bad Request",
181
+ 401: "Unauthorized",
182
+ 402: "Payment Required",
183
+ 403: "Forbidden",
184
+ 404: "Not Found",
185
+ 405: "Method Not Allowed",
186
+ 408: "Request Timeout",
187
+ 409: "Conflict",
188
+ 410: "Gone",
189
+ 422: "Unprocessable Entity",
190
+ 429: "Too Many Requests"
191
+ };
192
+ return {
193
+ text: String(status),
194
+ color: macOSColors.semantic.error,
195
+ meaning: meanings[status] || "Client Error"
196
+ };
197
+ }
198
+ if (status >= 500) {
199
+ const meanings = {
200
+ 500: "Internal Server Error",
201
+ 501: "Not Implemented",
202
+ 502: "Bad Gateway",
203
+ 503: "Service Unavailable",
204
+ 504: "Gateway Timeout",
205
+ 505: "HTTP Version Not Supported"
206
+ };
207
+ return {
208
+ text: String(status),
209
+ color: macOSColors.semantic.error,
210
+ meaning: meanings[status] || "Server Error"
211
+ };
212
+ }
213
+ return {
214
+ text: String(status),
215
+ color: macOSColors.text.muted,
216
+ meaning: "Unknown"
217
+ };
218
+ }
219
+
220
+ // =============================
221
+ // Inline lucide icons (shared-ui icons are lucide re-exports)
222
+ // =============================
223
+
224
+ function Svg({
225
+ size = 14,
226
+ color = "currentColor",
227
+ children
228
+ }) {
229
+ return /*#__PURE__*/(0, _jsxRuntime.jsx)("svg", {
230
+ width: size,
231
+ height: size,
232
+ viewBox: "0 0 24 24",
233
+ fill: "none",
234
+ stroke: color,
235
+ strokeWidth: 2,
236
+ strokeLinecap: "round",
237
+ strokeLinejoin: "round",
238
+ style: {
239
+ flexShrink: 0,
240
+ display: "block"
241
+ },
242
+ children: children
243
+ });
244
+ }
245
+ const Clock = p => /*#__PURE__*/(0, _jsxRuntime.jsxs)(Svg, {
246
+ ...p,
247
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsx)("circle", {
248
+ cx: "12",
249
+ cy: "12",
250
+ r: "10"
251
+ }), /*#__PURE__*/(0, _jsxRuntime.jsx)("polyline", {
252
+ points: "12 6 12 12 16 14"
253
+ })]
254
+ });
255
+ const Upload = p => /*#__PURE__*/(0, _jsxRuntime.jsxs)(Svg, {
256
+ ...p,
257
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsx)("path", {
258
+ d: "M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"
259
+ }), /*#__PURE__*/(0, _jsxRuntime.jsx)("polyline", {
260
+ points: "17 8 12 3 7 8"
261
+ }), /*#__PURE__*/(0, _jsxRuntime.jsx)("line", {
262
+ x1: "12",
263
+ x2: "12",
264
+ y1: "3",
265
+ y2: "15"
266
+ })]
267
+ });
268
+ const Download = p => /*#__PURE__*/(0, _jsxRuntime.jsxs)(Svg, {
269
+ ...p,
270
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsx)("path", {
271
+ d: "M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"
272
+ }), /*#__PURE__*/(0, _jsxRuntime.jsx)("polyline", {
273
+ points: "7 10 12 15 17 10"
274
+ }), /*#__PURE__*/(0, _jsxRuntime.jsx)("line", {
275
+ x1: "12",
276
+ x2: "12",
277
+ y1: "15",
278
+ y2: "3"
279
+ })]
280
+ });
281
+ const AlertCircle = p => /*#__PURE__*/(0, _jsxRuntime.jsxs)(Svg, {
282
+ ...p,
283
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsx)("circle", {
284
+ cx: "12",
285
+ cy: "12",
286
+ r: "10"
287
+ }), /*#__PURE__*/(0, _jsxRuntime.jsx)("line", {
288
+ x1: "12",
289
+ x2: "12",
290
+ y1: "8",
291
+ y2: "12"
292
+ }), /*#__PURE__*/(0, _jsxRuntime.jsx)("line", {
293
+ x1: "12",
294
+ x2: "12.01",
295
+ y1: "16",
296
+ y2: "16"
297
+ })]
298
+ });
299
+ const ChevronDown = p => /*#__PURE__*/(0, _jsxRuntime.jsx)(Svg, {
300
+ ...p,
301
+ children: /*#__PURE__*/(0, _jsxRuntime.jsx)("path", {
302
+ d: "m6 9 6 6 6-6"
303
+ })
304
+ });
305
+ const ChevronUp = p => /*#__PURE__*/(0, _jsxRuntime.jsx)(Svg, {
306
+ ...p,
307
+ children: /*#__PURE__*/(0, _jsxRuntime.jsx)("path", {
308
+ d: "m18 15-6-6-6 6"
309
+ })
310
+ });
311
+ const Lock = p => /*#__PURE__*/(0, _jsxRuntime.jsxs)(Svg, {
312
+ ...p,
313
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsx)("rect", {
314
+ width: "18",
315
+ height: "11",
316
+ x: "3",
317
+ y: "11",
318
+ rx: "2",
319
+ ry: "2"
320
+ }), /*#__PURE__*/(0, _jsxRuntime.jsx)("path", {
321
+ d: "M7 11V7a5 5 0 0 1 10 0v4"
322
+ })]
323
+ });
324
+ const Unlock = p => /*#__PURE__*/(0, _jsxRuntime.jsxs)(Svg, {
325
+ ...p,
326
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsx)("rect", {
327
+ width: "18",
328
+ height: "11",
329
+ x: "3",
330
+ y: "11",
331
+ rx: "2",
332
+ ry: "2"
333
+ }), /*#__PURE__*/(0, _jsxRuntime.jsx)("path", {
334
+ d: "M7 11V7a5 5 0 0 1 9.9-1"
335
+ })]
336
+ });
337
+ const FileJson = p => /*#__PURE__*/(0, _jsxRuntime.jsxs)(Svg, {
338
+ ...p,
339
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsx)("path", {
340
+ d: "M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z"
341
+ }), /*#__PURE__*/(0, _jsxRuntime.jsx)("path", {
342
+ d: "M14 2v4a2 2 0 0 0 2 2h4"
343
+ }), /*#__PURE__*/(0, _jsxRuntime.jsx)("path", {
344
+ d: "M10 12a1 1 0 0 0-1 1v1a1 1 0 0 1-1 1 1 1 0 0 1 1 1v1a1 1 0 0 0 1 1"
345
+ }), /*#__PURE__*/(0, _jsxRuntime.jsx)("path", {
346
+ d: "M14 18a1 1 0 0 0 1-1v-1a1 1 0 0 1 1-1 1 1 0 0 1-1-1v-1a1 1 0 0 0-1-1"
347
+ })]
348
+ });
349
+ const Filter = p => /*#__PURE__*/(0, _jsxRuntime.jsx)(Svg, {
350
+ ...p,
351
+ children: /*#__PURE__*/(0, _jsxRuntime.jsx)("polygon", {
352
+ points: "22 3 2 3 10 12.46 10 19 14 21 14 12.46 22 3"
353
+ })
354
+ });
355
+ const Globe = p => /*#__PURE__*/(0, _jsxRuntime.jsxs)(Svg, {
356
+ ...p,
357
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsx)("circle", {
358
+ cx: "12",
359
+ cy: "12",
360
+ r: "10"
361
+ }), /*#__PURE__*/(0, _jsxRuntime.jsx)("path", {
362
+ d: "M12 2a14.5 14.5 0 0 0 0 20 14.5 14.5 0 0 0 0-20"
363
+ }), /*#__PURE__*/(0, _jsxRuntime.jsx)("path", {
364
+ d: "M2 12h20"
365
+ })]
366
+ });
367
+ const Link = p => /*#__PURE__*/(0, _jsxRuntime.jsxs)(Svg, {
368
+ ...p,
369
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsx)("path", {
370
+ d: "M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"
371
+ }), /*#__PURE__*/(0, _jsxRuntime.jsx)("path", {
372
+ d: "M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"
373
+ })]
374
+ });
375
+ const FlaskConical = p => /*#__PURE__*/(0, _jsxRuntime.jsxs)(Svg, {
376
+ ...p,
377
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsx)("path", {
378
+ d: "M10 2v7.527a2 2 0 0 1-.211.896L4.72 20.55a1 1 0 0 0 .9 1.45h12.76a1 1 0 0 0 .9-1.45l-5.069-10.127A2 2 0 0 1 14 9.527V2"
379
+ }), /*#__PURE__*/(0, _jsxRuntime.jsx)("path", {
380
+ d: "M8.5 2h7"
381
+ }), /*#__PURE__*/(0, _jsxRuntime.jsx)("path", {
382
+ d: "M7 16h10"
383
+ })]
384
+ });
385
+
386
+ // =============================
387
+ // View (structure mirrors the native file 1:1)
388
+ // =============================
389
+
390
+ /** Hoisted so the defaults don't mint a new Set/function per render (native). */
391
+ const EMPTY_PATTERNS = new Set();
392
+ const noop = () => {};
393
+ /**
394
+ * The measurable slice of a request's lifetime, as proportional bars.
395
+ * Renders NOTHING when the interceptor couldn't measure it — same "absent,
396
+ * not zeroed" rule as native. Only two phases, on purpose (see native).
397
+ */
398
+ const TimingPhases = ({
399
+ timings,
400
+ total
401
+ }) => {
402
+ // Guard the divisor: a sub-millisecond request would otherwise divide by 0.
403
+ const span = Math.max(1, total);
404
+ const phases = [{
405
+ label: "Waiting (TTFB)",
406
+ hint: "incl. queue, DNS, TLS",
407
+ value: timings.ttfb,
408
+ color: macOSColors.semantic.warning
409
+ }, {
410
+ label: "Content download",
411
+ hint: undefined,
412
+ value: timings.download,
413
+ color: macOSColors.semantic.success
414
+ }];
415
+ return /*#__PURE__*/(0, _jsxRuntime.jsx)("div", {
416
+ style: styles.phaseList,
417
+ children: phases.map(phase => /*#__PURE__*/(0, _jsxRuntime.jsxs)("div", {
418
+ style: styles.phaseRow,
419
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsxs)("div", {
420
+ style: styles.phaseLabelGroup,
421
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsx)("div", {
422
+ style: styles.phaseLabel,
423
+ children: phase.label
424
+ }), phase.hint ? /*#__PURE__*/(0, _jsxRuntime.jsx)("div", {
425
+ style: styles.phaseHint,
426
+ children: phase.hint
427
+ }) : null]
428
+ }), /*#__PURE__*/(0, _jsxRuntime.jsx)("div", {
429
+ style: styles.phaseTrack,
430
+ children: /*#__PURE__*/(0, _jsxRuntime.jsx)("div", {
431
+ style: {
432
+ ...styles.phaseBar,
433
+ backgroundColor: phase.color,
434
+ // Floor so a 1ms phase is a visible tick; ceiling because ttfb
435
+ // can exceed event.duration (measured at different points).
436
+ width: `${Math.min(100, Math.max(1, phase.value / span * 100))}%`
437
+ }
438
+ })
439
+ }), /*#__PURE__*/(0, _jsxRuntime.jsx)("span", {
440
+ style: styles.phaseValue,
441
+ children: formatDuration(phase.value)
442
+ })]
443
+ }, phase.label))
444
+ });
445
+ };
446
+
447
+ /**
448
+ * Stand-in for a body tree while the prev/next cursor is still moving.
449
+ * Fixed-height nothing — must cost ~0 and must not resize the scroll view as
450
+ * the real tree swaps in (native rationale).
451
+ */
452
+ const BodyDeferred = () => /*#__PURE__*/(0, _jsxRuntime.jsx)("div", {
453
+ style: styles.bodyDeferred
454
+ });
455
+
456
+ // Component for collapsible sections matching Sentry style
457
+ const CollapsibleSection = ({
458
+ title,
459
+ icon,
460
+ children,
461
+ defaultOpen = false,
462
+ count
463
+ }) => {
464
+ const [isOpen, setIsOpen] = (0, _react.useState)(defaultOpen);
465
+ return /*#__PURE__*/(0, _jsxRuntime.jsxs)("div", {
466
+ style: styles.collapsibleSection,
467
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsxs)("button", {
468
+ type: "button",
469
+ style: styles.collapsibleHeader,
470
+ onClick: () => setIsOpen(!isOpen),
471
+ "aria-expanded": isOpen,
472
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsxs)("span", {
473
+ style: styles.collapsibleTitle,
474
+ children: [icon, /*#__PURE__*/(0, _jsxRuntime.jsx)("span", {
475
+ style: styles.collapsibleTitleText,
476
+ children: title
477
+ }), count !== undefined ? /*#__PURE__*/(0, _jsxRuntime.jsx)("span", {
478
+ style: styles.collapsibleCount,
479
+ children: count
480
+ }) : null]
481
+ }), isOpen ? /*#__PURE__*/(0, _jsxRuntime.jsx)(ChevronUp, {
482
+ size: 16,
483
+ color: macOSColors.text.secondary
484
+ }) : /*#__PURE__*/(0, _jsxRuntime.jsx)(ChevronDown, {
485
+ size: 16,
486
+ color: macOSColors.text.secondary
487
+ })]
488
+ }), isOpen ? /*#__PURE__*/(0, _jsxRuntime.jsx)("div", {
489
+ style: styles.collapsibleContent,
490
+ children: children
491
+ }) : null]
492
+ });
493
+ };
494
+
495
+ // URL breakdown component matching Sentry style
496
+ const UrlBreakdown = ({
497
+ url,
498
+ operationName,
499
+ graphqlVariables,
500
+ requestClient
501
+ }) => {
502
+ const parseUrl = urlString => {
503
+ try {
504
+ const urlObj = new URL(urlString);
505
+ const protocol = String(urlObj.protocol || "");
506
+ const host = String(urlObj.host || "");
507
+ const isSecure = protocol === "https:";
508
+ let pathname = String(urlObj.pathname || "");
509
+
510
+ // GraphQL requests format with arrow notation, matching React Query's
511
+ // key display: "GetPokemon › Sandshrew" (same pure util as native).
512
+ if (requestClient === "graphql" && operationName) {
513
+ const graphqlDisplay = (0, _formatGraphQLVariables.formatGraphQLDisplay)(operationName, graphqlVariables);
514
+ pathname = `${pathname} (${graphqlDisplay})`;
515
+ } else if (operationName) {
516
+ // Non-GraphQL requests with operation names (e.g., gRPC)
517
+ pathname = `${pathname} (${operationName})`;
518
+ }
519
+ const params = {};
520
+ const searchParams = urlObj.searchParams;
521
+ if (searchParams && typeof searchParams.forEach === "function") {
522
+ searchParams.forEach((value, key) => {
523
+ params[key] = value;
524
+ });
525
+ }
526
+ return {
527
+ protocol: protocol.replace(":", ""),
528
+ host,
529
+ pathname,
530
+ params: Object.keys(params).length > 0 ? params : null,
531
+ isSecure
532
+ };
533
+ } catch {
534
+ return {
535
+ protocol: "",
536
+ host: url,
537
+ pathname: "",
538
+ params: null,
539
+ isSecure: false
540
+ };
541
+ }
542
+ };
543
+
544
+ /**
545
+ * MUST be memoized — `params` is handed to DataViewer as its `data` prop,
546
+ * which the tree keys on by IDENTITY (same trap the native file documents).
547
+ */
548
+ const urlParts = (0, _react.useMemo)(() => parseUrl(url),
549
+ // parseUrl closes over the graphql/operation props, which are what change
550
+ // the derived pathname.
551
+ // eslint-disable-next-line react-hooks/exhaustive-deps
552
+ [url, requestClient, operationName, graphqlVariables]);
553
+ const [showParams, setShowParams] = (0, _react.useState)(false);
554
+ return /*#__PURE__*/(0, _jsxRuntime.jsxs)("div", {
555
+ style: styles.urlBreakdown,
556
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsxs)("div", {
557
+ style: styles.urlRow,
558
+ children: [urlParts.isSecure ? /*#__PURE__*/(0, _jsxRuntime.jsx)(Lock, {
559
+ size: 12,
560
+ color: macOSColors.semantic.success
561
+ }) : /*#__PURE__*/(0, _jsxRuntime.jsx)(Unlock, {
562
+ size: 12,
563
+ color: macOSColors.semantic.warning
564
+ }), /*#__PURE__*/(0, _jsxRuntime.jsx)("span", {
565
+ style: styles.urlDomain,
566
+ children: urlParts.host
567
+ }), /*#__PURE__*/(0, _jsxRuntime.jsxs)("span", {
568
+ style: styles.urlProtocol,
569
+ children: ["(", urlParts.protocol.toUpperCase(), ")"]
570
+ }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_DataViewer.InlineCopyButton, {
571
+ value: url,
572
+ buttonStyle: styles.copyButton
573
+ })]
574
+ }), /*#__PURE__*/(0, _jsxRuntime.jsx)("div", {
575
+ style: styles.urlPathRow,
576
+ children: /*#__PURE__*/(0, _jsxRuntime.jsxs)("span", {
577
+ style: styles.urlPath,
578
+ children: [urlParts.pathname, urlParts.params ? /*#__PURE__*/(0, _jsxRuntime.jsxs)("span", {
579
+ style: styles.urlQueryString,
580
+ children: ["?", new URLSearchParams(urlParts.params).toString()]
581
+ }) : null]
582
+ })
583
+ }), urlParts.params ? /*#__PURE__*/(0, _jsxRuntime.jsxs)("div", {
584
+ style: styles.queryParamsCollapsible,
585
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsxs)("button", {
586
+ type: "button",
587
+ style: styles.queryParamsToggle,
588
+ onClick: () => setShowParams(!showParams),
589
+ "aria-expanded": showParams,
590
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsx)("span", {
591
+ style: styles.queryParamsToggleText,
592
+ children: "Query Parameters"
593
+ }), /*#__PURE__*/(0, _jsxRuntime.jsx)("span", {
594
+ style: {
595
+ ...styles.collapsibleCount,
596
+ flex: 1,
597
+ textAlign: "left"
598
+ },
599
+ children: Object.keys(urlParts.params).length
600
+ }), showParams ? /*#__PURE__*/(0, _jsxRuntime.jsx)(ChevronUp, {
601
+ size: 14,
602
+ color: macOSColors.text.secondary
603
+ }) : /*#__PURE__*/(0, _jsxRuntime.jsx)(ChevronDown, {
604
+ size: 14,
605
+ color: macOSColors.text.secondary
606
+ })]
607
+ }), showParams ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_DataViewer.DataViewer, {
608
+ title: "",
609
+ data: urlParts.params,
610
+ showTypeFilter: true,
611
+ rawMode: true,
612
+ initialExpanded: true
613
+ }) : null]
614
+ }) : null]
615
+ });
616
+ };
617
+
618
+ /**
619
+ * Detailed inspector for a single network event — Sentry-style layout with
620
+ * collapsible sections and quick copy affordances.
621
+ *
622
+ * MEMOIZED for the same two render paths as native: `useLiveNetworkEvent`
623
+ * replays the same event object on re-subscribe, and host-root state changes
624
+ * re-render the shell with the detail body unchanged.
625
+ */
626
+ const NetworkEventDetailView = exports.NetworkEventDetailView = /*#__PURE__*/(0, _react.memo)(function NetworkEventDetailView({
627
+ event,
628
+ ignoredPatterns = EMPTY_PATTERNS,
629
+ onTogglePattern = noop,
630
+ showBodies = true
631
+ }) {
632
+ const status = event.status ? formatHttpStatus(event.status) : null;
633
+ const isPending = !event.status && !event.error;
634
+
635
+ // Large bodies are omitted from synced snapshots and fetched on demand
636
+ // through the resolver (plain React context — reused, not forked). In a
637
+ // webview port there is normally no resolver and bodies are always inline,
638
+ // so this is a no-op there — exactly like on the device.
639
+ const resolveBody = (0, _networkBodyResolver.useNetworkBodyResolver)();
640
+ const requestBodyOmitted = event.requestData === undefined && (event.requestSize ?? 0) > 0;
641
+ const responseBodyOmitted = event.responseData === undefined && (event.responseSize ?? 0) > 0;
642
+ const [resolvedBody, setResolvedBody] = (0, _react.useState)(null);
643
+ const [isLoadingBody, setIsLoadingBody] = (0, _react.useState)(false);
644
+ (0, _react.useEffect)(() => {
645
+ setResolvedBody(null);
646
+ if (!resolveBody || !requestBodyOmitted && !responseBodyOmitted) {
647
+ setIsLoadingBody(false);
648
+ return;
649
+ }
650
+ let cancelled = false;
651
+ setIsLoadingBody(true);
652
+ resolveBody(event.id).then(body => {
653
+ if (!cancelled) setResolvedBody(body);
654
+ }).catch(() => {}).finally(() => {
655
+ if (!cancelled) setIsLoadingBody(false);
656
+ });
657
+ return () => {
658
+ cancelled = true;
659
+ };
660
+ }, [event.id, resolveBody, requestBodyOmitted, responseBodyOmitted]);
661
+
662
+ // Effective bodies: inline data when present, otherwise the lazily resolved
663
+ // body. `null`/`undefined` both collapse to undefined ("no body").
664
+ const requestData = event.requestData ?? resolvedBody?.requestData ?? undefined;
665
+ const responseData = event.responseData ?? resolvedBody?.responseData ?? undefined;
666
+
667
+ // Generate full request details for copying (resolved LAZILY at press time —
668
+ // see the copy button below).
669
+ const getFullRequestDetails = () => {
670
+ const requestDetails = {
671
+ method: event.method,
672
+ url: event.url,
673
+ status: event.status,
674
+ statusText: event.statusText,
675
+ timestamp: new Date(event.timestamp).toISOString(),
676
+ duration: event.duration ? `${event.duration}ms` : "N/A",
677
+ requestHeaders: event.requestHeaders,
678
+ requestData,
679
+ responseHeaders: event.responseHeaders,
680
+ responseData,
681
+ requestSize: event.requestSize ? formatBytes(event.requestSize) : "N/A",
682
+ responseSize: event.responseSize ? formatBytes(event.responseSize) : "N/A",
683
+ error: event.error,
684
+ client: event.requestClient
685
+ };
686
+ return `# Network Request Details
687
+
688
+ ## Request
689
+ - **Method:** ${requestDetails.method}
690
+ - **URL:** ${requestDetails.url}
691
+ - **Client:** ${requestDetails.client || "N/A"}
692
+ - **Timestamp:** ${requestDetails.timestamp}
693
+
694
+ ## Response
695
+ - **Status:** ${requestDetails.status || "Pending"}${requestDetails.statusText ? ` (${requestDetails.statusText})` : ""}
696
+ - **Duration:** ${requestDetails.duration}
697
+ - **Request Size:** ${requestDetails.requestSize}
698
+ - **Response Size:** ${requestDetails.responseSize}
699
+ ${requestDetails.error ? `- **Error:** ${requestDetails.error}` : ""}
700
+
701
+ ## Request Headers
702
+ \`\`\`json
703
+ ${JSON.stringify(requestDetails.requestHeaders, null, 2)}
704
+ \`\`\`
705
+
706
+ ## Request Data
707
+ \`\`\`json
708
+ ${JSON.stringify(requestDetails.requestData, null, 2)}
709
+ \`\`\`
710
+
711
+ ## Response Headers
712
+ \`\`\`json
713
+ ${JSON.stringify(requestDetails.responseHeaders, null, 2)}
714
+ \`\`\`
715
+
716
+ ## Response Data
717
+ \`\`\`json
718
+ ${JSON.stringify(requestDetails.responseData, null, 2)}
719
+ \`\`\`
720
+ `;
721
+ };
722
+ return /*#__PURE__*/(0, _jsxRuntime.jsxs)("div", {
723
+ style: styles.container,
724
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsxs)("div", {
725
+ style: styles.requestDetailsSection,
726
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsxs)("div", {
727
+ style: styles.httpHeader,
728
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsx)("span", {
729
+ style: styles.httpMethodBadge,
730
+ children: /*#__PURE__*/(0, _jsxRuntime.jsx)("span", {
731
+ style: styles.httpMethod,
732
+ children: event.method
733
+ })
734
+ }), event.status ? /*#__PURE__*/(0, _jsxRuntime.jsx)("span", {
735
+ style: {
736
+ ...styles.httpStatusBadge,
737
+ backgroundColor: `${status?.color}20`
738
+ },
739
+ children: /*#__PURE__*/(0, _jsxRuntime.jsxs)("span", {
740
+ style: {
741
+ ...styles.httpStatusText,
742
+ color: status?.color
743
+ },
744
+ children: [status?.text, " ", status?.meaning]
745
+ })
746
+ }) : isPending ? /*#__PURE__*/(0, _jsxRuntime.jsxs)("span", {
747
+ style: styles.pendingBadge,
748
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(Clock, {
749
+ size: 10,
750
+ color: macOSColors.semantic.warning
751
+ }), /*#__PURE__*/(0, _jsxRuntime.jsx)("span", {
752
+ style: styles.pendingBadgeText,
753
+ children: "Pending"
754
+ })]
755
+ }) : null, event.duration ? /*#__PURE__*/(0, _jsxRuntime.jsxs)("span", {
756
+ style: styles.httpDuration,
757
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(Clock, {
758
+ size: 10,
759
+ color: macOSColors.text.muted
760
+ }), /*#__PURE__*/(0, _jsxRuntime.jsx)("span", {
761
+ style: styles.httpDurationText,
762
+ children: formatDuration(event.duration)
763
+ })]
764
+ }) : null, event.override ? /*#__PURE__*/(0, _jsxRuntime.jsxs)("span", {
765
+ style: styles.overrideBadge,
766
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(FlaskConical, {
767
+ size: 10,
768
+ color: macOSColors.semantic.warning
769
+ }), /*#__PURE__*/(0, _jsxRuntime.jsx)("span", {
770
+ style: styles.overrideBadgeText,
771
+ children: event.override.ruleName || "Overridden"
772
+ })]
773
+ }) : null, /*#__PURE__*/(0, _jsxRuntime.jsx)(_DataViewer.InlineCopyButton, {
774
+ value: getFullRequestDetails,
775
+ buttonStyle: styles.copyFullButton
776
+ })]
777
+ }), /*#__PURE__*/(0, _jsxRuntime.jsx)(UrlBreakdown, {
778
+ url: event.url,
779
+ requestData: requestData,
780
+ operationName: event.operationName,
781
+ graphqlVariables: event.graphqlVariables,
782
+ requestClient: event.requestClient
783
+ }), event.error ? /*#__PURE__*/(0, _jsxRuntime.jsxs)("div", {
784
+ style: styles.errorBox,
785
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(AlertCircle, {
786
+ size: 12,
787
+ color: macOSColors.semantic.error
788
+ }), /*#__PURE__*/(0, _jsxRuntime.jsx)("span", {
789
+ style: styles.errorText,
790
+ children: event.error
791
+ })]
792
+ }) : null]
793
+ }), /*#__PURE__*/(0, _jsxRuntime.jsxs)("div", {
794
+ style: styles.timingSection,
795
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsxs)("div", {
796
+ style: styles.timingRow,
797
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(Clock, {
798
+ size: 12,
799
+ color: macOSColors.text.secondary
800
+ }), /*#__PURE__*/(0, _jsxRuntime.jsx)("span", {
801
+ style: styles.timingLabel,
802
+ children: "Started:"
803
+ }), /*#__PURE__*/(0, _jsxRuntime.jsx)("span", {
804
+ style: styles.timingValue,
805
+ children: formatRelativeTime(event.timestamp)
806
+ }), /*#__PURE__*/(0, _jsxRuntime.jsxs)("span", {
807
+ style: styles.timingExact,
808
+ children: ["(", new Date(event.timestamp).toLocaleTimeString(), ")"]
809
+ }), event.requestSize || event.responseSize ? /*#__PURE__*/(0, _jsxRuntime.jsxs)("span", {
810
+ style: styles.sizeRow,
811
+ children: [event.requestSize !== undefined ? /*#__PURE__*/(0, _jsxRuntime.jsxs)("span", {
812
+ style: styles.sizeItem,
813
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(Upload, {
814
+ size: 10,
815
+ color: macOSColors.semantic.info
816
+ }), /*#__PURE__*/(0, _jsxRuntime.jsx)("span", {
817
+ style: styles.sizeLabel,
818
+ children: "Sent:"
819
+ }), /*#__PURE__*/(0, _jsxRuntime.jsx)("span", {
820
+ style: styles.sizeValue,
821
+ children: formatBytes(event.requestSize)
822
+ })]
823
+ }) : null, event.responseSize !== undefined ? /*#__PURE__*/(0, _jsxRuntime.jsxs)("span", {
824
+ style: styles.sizeItem,
825
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(Download, {
826
+ size: 10,
827
+ color: NEUTRAL_ICON
828
+ }), /*#__PURE__*/(0, _jsxRuntime.jsx)("span", {
829
+ style: styles.sizeLabel,
830
+ children: "Received:"
831
+ }), /*#__PURE__*/(0, _jsxRuntime.jsx)("span", {
832
+ style: styles.sizeValue,
833
+ children: formatBytes(event.responseSize)
834
+ })]
835
+ }) : null]
836
+ }) : null]
837
+ }), event.timings ? /*#__PURE__*/(0, _jsxRuntime.jsxs)(_jsxRuntime.Fragment, {
838
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsx)("div", {
839
+ style: styles.phaseDivider
840
+ }), /*#__PURE__*/(0, _jsxRuntime.jsx)(TimingPhases, {
841
+ timings: event.timings,
842
+ total: event.duration ?? event.timings.ttfb + event.timings.download
843
+ })]
844
+ }) : null]
845
+ }), /*#__PURE__*/(0, _jsxRuntime.jsx)(CollapsibleSection, {
846
+ title: "Request Headers",
847
+ icon: /*#__PURE__*/(0, _jsxRuntime.jsx)(Upload, {
848
+ size: 14,
849
+ color: macOSColors.semantic.info
850
+ }),
851
+ defaultOpen: false,
852
+ count: Object.keys(event.requestHeaders).length,
853
+ children: Object.keys(event.requestHeaders).length > 0 ? /*#__PURE__*/(0, _jsxRuntime.jsx)("div", {
854
+ style: styles.dataViewerContainer,
855
+ children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_DataViewer.DataViewer, {
856
+ title: "",
857
+ data: event.requestHeaders,
858
+ showTypeFilter: true,
859
+ rawMode: true,
860
+ initialExpanded: true
861
+ })
862
+ }) : /*#__PURE__*/(0, _jsxRuntime.jsx)("div", {
863
+ style: styles.emptyText,
864
+ children: "No request headers"
865
+ })
866
+ }), /*#__PURE__*/(0, _jsxRuntime.jsx)(CollapsibleSection, {
867
+ title: "Response Headers",
868
+ icon: /*#__PURE__*/(0, _jsxRuntime.jsx)(Download, {
869
+ size: 14,
870
+ color: NEUTRAL_ICON
871
+ }),
872
+ defaultOpen: false,
873
+ count: Object.keys(event.responseHeaders).length,
874
+ children: Object.keys(event.responseHeaders).length > 0 ? /*#__PURE__*/(0, _jsxRuntime.jsx)("div", {
875
+ style: styles.dataViewerContainer,
876
+ children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_DataViewer.DataViewer, {
877
+ title: "",
878
+ data: event.responseHeaders,
879
+ showTypeFilter: true,
880
+ rawMode: true,
881
+ initialExpanded: true
882
+ })
883
+ }) : /*#__PURE__*/(0, _jsxRuntime.jsx)("div", {
884
+ style: styles.emptyText,
885
+ children: "No response headers yet"
886
+ })
887
+ }), requestData !== undefined ? /*#__PURE__*/(0, _jsxRuntime.jsx)(CollapsibleSection, {
888
+ title: "Request Body",
889
+ icon: /*#__PURE__*/(0, _jsxRuntime.jsx)(FileJson, {
890
+ size: 14,
891
+ color: macOSColors.semantic.info
892
+ }),
893
+ defaultOpen: false,
894
+ children: /*#__PURE__*/(0, _jsxRuntime.jsx)("div", {
895
+ style: styles.dataViewerContainer,
896
+ children: showBodies ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_DataViewer.DataViewer, {
897
+ title: "",
898
+ data: requestData,
899
+ showTypeFilter: true,
900
+ rawMode: true,
901
+ initialExpanded: true
902
+ }) : /*#__PURE__*/(0, _jsxRuntime.jsx)(BodyDeferred, {})
903
+ })
904
+ }) : requestBodyOmitted ? /*#__PURE__*/(0, _jsxRuntime.jsx)(CollapsibleSection, {
905
+ title: "Request Body",
906
+ icon: /*#__PURE__*/(0, _jsxRuntime.jsx)(FileJson, {
907
+ size: 14,
908
+ color: macOSColors.semantic.info
909
+ }),
910
+ defaultOpen: true,
911
+ children: /*#__PURE__*/(0, _jsxRuntime.jsx)("div", {
912
+ style: styles.emptyText,
913
+ children: isLoadingBody ? `Loading request body (${formatBytes(event.requestSize ?? 0)})…` : "Request body unavailable"
914
+ })
915
+ }) : null, responseData !== undefined ? /*#__PURE__*/(0, _jsxRuntime.jsx)(CollapsibleSection, {
916
+ title: "Response Body",
917
+ icon: /*#__PURE__*/(0, _jsxRuntime.jsx)(FileJson, {
918
+ size: 14,
919
+ color: NEUTRAL_ICON
920
+ })
921
+ // The body is what you opened the row FOR — expanded on arrival,
922
+ // everything else closed (native).
923
+ ,
924
+ defaultOpen: true,
925
+ children: /*#__PURE__*/(0, _jsxRuntime.jsx)("div", {
926
+ style: styles.dataViewerContainer,
927
+ children: showBodies ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_DataViewer.DataViewer, {
928
+ title: "",
929
+ data: responseData,
930
+ showTypeFilter: true,
931
+ rawMode: true,
932
+ initialExpanded: true
933
+ }) : /*#__PURE__*/(0, _jsxRuntime.jsx)(BodyDeferred, {})
934
+ })
935
+ }) : responseBodyOmitted ? /*#__PURE__*/(0, _jsxRuntime.jsx)(CollapsibleSection, {
936
+ title: "Response Body",
937
+ icon: /*#__PURE__*/(0, _jsxRuntime.jsx)(FileJson, {
938
+ size: 14,
939
+ color: NEUTRAL_ICON
940
+ }),
941
+ defaultOpen: true,
942
+ children: /*#__PURE__*/(0, _jsxRuntime.jsx)("div", {
943
+ style: styles.emptyText,
944
+ children: isLoadingBody ? `Loading response body (${formatBytes(event.responseSize ?? 0)})…` : "Response body unavailable"
945
+ })
946
+ }) : null, /*#__PURE__*/(0, _jsxRuntime.jsx)(CollapsibleSection, {
947
+ title: "Filter Options",
948
+ icon: /*#__PURE__*/(0, _jsxRuntime.jsx)(Filter, {
949
+ size: 14,
950
+ color: macOSColors.semantic.warning
951
+ }),
952
+ defaultOpen: false,
953
+ children: /*#__PURE__*/(0, _jsxRuntime.jsx)("div", {
954
+ style: styles.filterOptionsContainer,
955
+ children: (() => {
956
+ let domain = "";
957
+ let urlPath = "";
958
+ try {
959
+ const url = new URL(event.url);
960
+ domain = url.hostname;
961
+ urlPath = url.pathname;
962
+ } catch {
963
+ urlPath = event.url;
964
+ }
965
+ const isDomainIgnored = ignoredPatterns.has(domain);
966
+ const isUrlIgnored = ignoredPatterns.has(urlPath);
967
+ return /*#__PURE__*/(0, _jsxRuntime.jsxs)(_jsxRuntime.Fragment, {
968
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsxs)("button", {
969
+ type: "button",
970
+ style: {
971
+ ...styles.filterOption,
972
+ ...(isDomainIgnored ? styles.filterOptionActive : null)
973
+ },
974
+ onClick: () => domain && onTogglePattern(domain),
975
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsxs)("span", {
976
+ style: styles.filterOptionLeft,
977
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(Globe, {
978
+ size: 16,
979
+ color: isDomainIgnored ? macOSColors.semantic.warning : macOSColors.text.muted
980
+ }), /*#__PURE__*/(0, _jsxRuntime.jsxs)("span", {
981
+ style: styles.filterOptionContent,
982
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsx)("span", {
983
+ style: styles.filterOptionLabel,
984
+ children: "Ignore Domain"
985
+ }), /*#__PURE__*/(0, _jsxRuntime.jsx)("span", {
986
+ style: styles.filterOptionValue,
987
+ children: domain || "N/A"
988
+ })]
989
+ })]
990
+ }), /*#__PURE__*/(0, _jsxRuntime.jsx)("span", {
991
+ style: {
992
+ ...styles.filterToggle,
993
+ ...(isDomainIgnored ? styles.filterToggleActive : null)
994
+ },
995
+ children: /*#__PURE__*/(0, _jsxRuntime.jsx)("span", {
996
+ style: {
997
+ ...styles.filterToggleText,
998
+ ...(isDomainIgnored ? styles.filterToggleTextActive : null)
999
+ },
1000
+ children: isDomainIgnored ? "IGNORED" : "IGNORE"
1001
+ })
1002
+ })]
1003
+ }), /*#__PURE__*/(0, _jsxRuntime.jsxs)("button", {
1004
+ type: "button",
1005
+ style: {
1006
+ ...styles.filterOption,
1007
+ ...(isUrlIgnored ? styles.filterOptionActive : null)
1008
+ },
1009
+ onClick: () => urlPath && onTogglePattern(urlPath),
1010
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsxs)("span", {
1011
+ style: styles.filterOptionLeft,
1012
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(Link, {
1013
+ size: 16,
1014
+ color: isUrlIgnored ? macOSColors.semantic.warning : macOSColors.text.muted
1015
+ }), /*#__PURE__*/(0, _jsxRuntime.jsxs)("span", {
1016
+ style: styles.filterOptionContent,
1017
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsx)("span", {
1018
+ style: styles.filterOptionLabel,
1019
+ children: "Ignore URL Pattern"
1020
+ }), /*#__PURE__*/(0, _jsxRuntime.jsx)("span", {
1021
+ style: {
1022
+ ...styles.filterOptionValue,
1023
+ ...styles.singleLine
1024
+ },
1025
+ children: urlPath || "N/A"
1026
+ })]
1027
+ })]
1028
+ }), /*#__PURE__*/(0, _jsxRuntime.jsx)("span", {
1029
+ style: {
1030
+ ...styles.filterToggle,
1031
+ ...(isUrlIgnored ? styles.filterToggleActive : null)
1032
+ },
1033
+ children: /*#__PURE__*/(0, _jsxRuntime.jsx)("span", {
1034
+ style: {
1035
+ ...styles.filterToggleText,
1036
+ ...(isUrlIgnored ? styles.filterToggleTextActive : null)
1037
+ },
1038
+ children: isUrlIgnored ? "IGNORED" : "IGNORE"
1039
+ })
1040
+ })]
1041
+ }), /*#__PURE__*/(0, _jsxRuntime.jsx)("div", {
1042
+ style: styles.filterInfoBox,
1043
+ children: /*#__PURE__*/(0, _jsxRuntime.jsx)("span", {
1044
+ style: styles.filterInfoText,
1045
+ children: "Ignored requests will be hidden from the network list. You can manage filters in the Filters tab."
1046
+ })
1047
+ })]
1048
+ });
1049
+ })()
1050
+ })
1051
+ })]
1052
+ });
1053
+ });
1054
+
1055
+ // Values mirror the native StyleSheet block 1:1.
1056
+ const styles = {
1057
+ // Native: ScrollView flex 1 on background.base — the detail body OWNS its
1058
+ // scrolling so the stepper footer stays pinned under it.
1059
+ container: {
1060
+ flex: 1,
1061
+ minHeight: 0,
1062
+ overflowY: "auto",
1063
+ backgroundColor: macOSColors.background.base
1064
+ },
1065
+ requestDetailsSection: {
1066
+ margin: "12px 12px 0",
1067
+ backgroundColor: macOSColors.background.card,
1068
+ borderRadius: 8,
1069
+ border: `1px solid ${macOSColors.border.default}`,
1070
+ padding: 12
1071
+ },
1072
+ httpHeader: {
1073
+ display: "flex",
1074
+ flexDirection: "row",
1075
+ alignItems: "center",
1076
+ gap: 8,
1077
+ marginBottom: 12,
1078
+ flexWrap: "nowrap"
1079
+ },
1080
+ httpMethodBadge: {
1081
+ display: "inline-flex",
1082
+ backgroundColor: macOSColors.semantic.infoBackground,
1083
+ padding: "4px 8px",
1084
+ borderRadius: 4
1085
+ },
1086
+ httpMethod: {
1087
+ color: macOSColors.semantic.info,
1088
+ fontSize: 11,
1089
+ fontWeight: 700,
1090
+ letterSpacing: 0.5
1091
+ },
1092
+ httpStatusBadge: {
1093
+ display: "inline-flex",
1094
+ padding: "4px 8px",
1095
+ borderRadius: 4,
1096
+ whiteSpace: "nowrap"
1097
+ },
1098
+ httpStatusText: {
1099
+ fontSize: 11,
1100
+ fontWeight: 600
1101
+ },
1102
+ pendingBadge: {
1103
+ display: "inline-flex",
1104
+ flexDirection: "row",
1105
+ alignItems: "center",
1106
+ gap: 4,
1107
+ backgroundColor: macOSColors.semantic.warningBackground,
1108
+ padding: "4px 8px",
1109
+ borderRadius: 4
1110
+ },
1111
+ pendingBadgeText: {
1112
+ color: macOSColors.semantic.warning,
1113
+ fontSize: 11,
1114
+ fontWeight: 600
1115
+ },
1116
+ httpDuration: {
1117
+ display: "inline-flex",
1118
+ flexDirection: "row",
1119
+ alignItems: "center",
1120
+ gap: 4
1121
+ },
1122
+ httpDurationText: {
1123
+ color: macOSColors.text.secondary,
1124
+ fontSize: 11
1125
+ },
1126
+ overrideBadge: {
1127
+ display: "inline-flex",
1128
+ flexDirection: "row",
1129
+ alignItems: "center",
1130
+ gap: 4,
1131
+ padding: "3px 6px",
1132
+ borderRadius: 4,
1133
+ backgroundColor: macOSColors.semantic.warningBackground
1134
+ },
1135
+ overrideBadgeText: {
1136
+ color: macOSColors.semantic.warning,
1137
+ fontSize: 10,
1138
+ fontWeight: 700
1139
+ },
1140
+ copyFullButton: {
1141
+ marginLeft: "auto",
1142
+ flexShrink: 0,
1143
+ padding: 4
1144
+ },
1145
+ // URL breakdown styles
1146
+ urlBreakdown: {
1147
+ backgroundColor: macOSColors.background.input,
1148
+ borderRadius: 4,
1149
+ padding: 8
1150
+ },
1151
+ urlRow: {
1152
+ display: "flex",
1153
+ flexDirection: "row",
1154
+ alignItems: "center",
1155
+ gap: 6,
1156
+ marginBottom: 4
1157
+ },
1158
+ urlDomain: {
1159
+ color: macOSColors.text.primary,
1160
+ fontSize: 12,
1161
+ fontWeight: 600,
1162
+ flex: 1,
1163
+ minWidth: 0,
1164
+ overflowWrap: "anywhere"
1165
+ },
1166
+ urlProtocol: {
1167
+ color: macOSColors.text.muted,
1168
+ fontSize: 10
1169
+ },
1170
+ copyButton: {
1171
+ padding: 4
1172
+ },
1173
+ urlPathRow: {
1174
+ paddingLeft: 18
1175
+ },
1176
+ urlPath: {
1177
+ color: macOSColors.text.secondary,
1178
+ fontSize: 11,
1179
+ fontFamily: "ui-monospace, Menlo, monospace",
1180
+ // Native numberOfLines={2}
1181
+ display: "-webkit-box",
1182
+ WebkitLineClamp: 2,
1183
+ WebkitBoxOrient: "vertical",
1184
+ overflow: "hidden",
1185
+ overflowWrap: "anywhere"
1186
+ },
1187
+ urlQueryString: {
1188
+ color: macOSColors.semantic.info,
1189
+ fontSize: 11,
1190
+ fontFamily: "ui-monospace, Menlo, monospace"
1191
+ },
1192
+ // Query Parameters - Collapsible section
1193
+ queryParamsCollapsible: {
1194
+ marginTop: 8
1195
+ },
1196
+ queryParamsToggle: {
1197
+ display: "flex",
1198
+ width: "100%",
1199
+ boxSizing: "border-box",
1200
+ flexDirection: "row",
1201
+ alignItems: "center",
1202
+ justifyContent: "space-between",
1203
+ gap: 8,
1204
+ padding: "10px 12px",
1205
+ backgroundColor: macOSColors.background.hover,
1206
+ borderRadius: 8,
1207
+ border: `1px solid ${macOSColors.border.default}`,
1208
+ marginBottom: 8,
1209
+ cursor: "pointer",
1210
+ margin: "0 0 8px",
1211
+ font: "inherit"
1212
+ },
1213
+ queryParamsToggleText: {
1214
+ flexGrow: 0,
1215
+ color: macOSColors.text.primary,
1216
+ fontSize: 12,
1217
+ fontWeight: 600,
1218
+ letterSpacing: 0.3,
1219
+ whiteSpace: "nowrap"
1220
+ },
1221
+ // Timing section - always visible
1222
+ timingSection: {
1223
+ margin: "8px 12px 0",
1224
+ backgroundColor: macOSColors.background.card,
1225
+ borderRadius: 8,
1226
+ border: `1px solid ${macOSColors.border.default}`,
1227
+ padding: 12
1228
+ },
1229
+ timingRow: {
1230
+ display: "flex",
1231
+ flexDirection: "row",
1232
+ alignItems: "center",
1233
+ gap: 6,
1234
+ // Wraps rather than squashing when the card is narrow — the sizes drop to
1235
+ // their own line there (native).
1236
+ flexWrap: "wrap"
1237
+ },
1238
+ timingLabel: {
1239
+ color: macOSColors.text.secondary,
1240
+ fontSize: 11
1241
+ },
1242
+ timingValue: {
1243
+ color: macOSColors.text.primary,
1244
+ fontSize: 11,
1245
+ fontWeight: 600
1246
+ },
1247
+ timingExact: {
1248
+ color: macOSColors.text.muted,
1249
+ fontSize: 10,
1250
+ marginLeft: 4
1251
+ },
1252
+ sizeRow: {
1253
+ display: "inline-flex",
1254
+ flexDirection: "row",
1255
+ alignItems: "center",
1256
+ gap: 16,
1257
+ // Pushed to the far end of the Started row (native).
1258
+ marginLeft: "auto"
1259
+ },
1260
+ sizeItem: {
1261
+ display: "inline-flex",
1262
+ flexDirection: "row",
1263
+ alignItems: "center",
1264
+ gap: 4
1265
+ },
1266
+ sizeLabel: {
1267
+ color: macOSColors.text.muted,
1268
+ fontSize: 10
1269
+ },
1270
+ sizeValue: {
1271
+ color: macOSColors.semantic.info,
1272
+ fontSize: 10,
1273
+ fontFamily: "ui-monospace, Menlo, monospace",
1274
+ fontWeight: 600
1275
+ },
1276
+ /* ---- Timing phases ---- */
1277
+ phaseDivider: {
1278
+ height: 1,
1279
+ backgroundColor: macOSColors.border.default,
1280
+ marginTop: 12,
1281
+ marginBottom: 12
1282
+ },
1283
+ phaseList: {
1284
+ display: "flex",
1285
+ flexDirection: "column",
1286
+ gap: 8
1287
+ },
1288
+ phaseRow: {
1289
+ display: "flex",
1290
+ flexDirection: "row",
1291
+ alignItems: "center",
1292
+ gap: 14
1293
+ },
1294
+ phaseLabelGroup: {
1295
+ width: 150,
1296
+ flexShrink: 0
1297
+ },
1298
+ phaseLabel: {
1299
+ fontSize: 12,
1300
+ color: macOSColors.text.secondary
1301
+ },
1302
+ phaseHint: {
1303
+ fontSize: 10,
1304
+ color: macOSColors.text.muted
1305
+ },
1306
+ phaseTrack: {
1307
+ flex: 1,
1308
+ minWidth: 0,
1309
+ height: 7,
1310
+ borderRadius: 4,
1311
+ backgroundColor: macOSColors.background.hover,
1312
+ display: "flex",
1313
+ justifyContent: "center",
1314
+ flexDirection: "column",
1315
+ overflow: "hidden"
1316
+ },
1317
+ phaseBar: {
1318
+ height: 7,
1319
+ borderRadius: 4
1320
+ },
1321
+ phaseValue: {
1322
+ width: 72,
1323
+ flexShrink: 0,
1324
+ textAlign: "right",
1325
+ fontSize: 12,
1326
+ fontFamily: "ui-monospace, Menlo, monospace",
1327
+ color: macOSColors.text.primary
1328
+ },
1329
+ // Collapsible section styles
1330
+ collapsibleSection: {
1331
+ margin: "8px 12px 0",
1332
+ backgroundColor: macOSColors.background.card,
1333
+ borderRadius: 8,
1334
+ border: `1px solid ${macOSColors.border.default}`,
1335
+ overflow: "hidden"
1336
+ },
1337
+ collapsibleHeader: {
1338
+ display: "flex",
1339
+ width: "100%",
1340
+ boxSizing: "border-box",
1341
+ flexDirection: "row",
1342
+ alignItems: "center",
1343
+ justifyContent: "space-between",
1344
+ padding: 12,
1345
+ // Near-white strip, not the selection grey (native rationale).
1346
+ backgroundColor: macOSColors.background.hover,
1347
+ border: "none",
1348
+ cursor: "pointer",
1349
+ margin: 0,
1350
+ font: "inherit",
1351
+ textAlign: "left"
1352
+ },
1353
+ collapsibleTitle: {
1354
+ display: "inline-flex",
1355
+ flexDirection: "row",
1356
+ alignItems: "center",
1357
+ gap: 8
1358
+ },
1359
+ collapsibleTitleText: {
1360
+ color: macOSColors.text.primary,
1361
+ fontSize: 13,
1362
+ fontWeight: 600
1363
+ },
1364
+ /** The "how much is in here" number beside a section title. */
1365
+ collapsibleCount: {
1366
+ color: macOSColors.text.muted,
1367
+ fontSize: 11.5,
1368
+ fontFamily: "ui-monospace, Menlo, monospace"
1369
+ },
1370
+ collapsibleContent: {
1371
+ padding: 12
1372
+ },
1373
+ // Data viewer container — pulls the tree flush against the section edges.
1374
+ dataViewerContainer: {
1375
+ margin: -12
1376
+ },
1377
+ /** Placeholder for a not-yet-mounted body tree. See BodyDeferred. */
1378
+ bodyDeferred: {
1379
+ height: 120
1380
+ },
1381
+ // Error box
1382
+ errorBox: {
1383
+ display: "flex",
1384
+ flexDirection: "row",
1385
+ alignItems: "center",
1386
+ gap: 6,
1387
+ backgroundColor: macOSColors.semantic.errorBackground,
1388
+ padding: 8,
1389
+ borderRadius: 4,
1390
+ marginTop: 8
1391
+ },
1392
+ errorText: {
1393
+ color: macOSColors.semantic.error,
1394
+ fontSize: 11,
1395
+ flex: 1,
1396
+ minWidth: 0,
1397
+ overflowWrap: "anywhere"
1398
+ },
1399
+ // Empty state
1400
+ emptyText: {
1401
+ color: macOSColors.text.muted,
1402
+ fontSize: 12,
1403
+ fontStyle: "italic",
1404
+ textAlign: "center"
1405
+ },
1406
+ // Filter options styles
1407
+ filterOptionsContainer: {
1408
+ display: "flex",
1409
+ flexDirection: "column",
1410
+ gap: 12
1411
+ },
1412
+ filterOption: {
1413
+ display: "flex",
1414
+ width: "100%",
1415
+ boxSizing: "border-box",
1416
+ flexDirection: "row",
1417
+ alignItems: "center",
1418
+ justifyContent: "space-between",
1419
+ backgroundColor: macOSColors.background.hover,
1420
+ borderRadius: 8,
1421
+ padding: 12,
1422
+ border: `1px solid ${macOSColors.border.default}`,
1423
+ cursor: "pointer",
1424
+ margin: 0,
1425
+ font: "inherit",
1426
+ textAlign: "left"
1427
+ },
1428
+ filterOptionActive: {
1429
+ backgroundColor: macOSColors.semantic.warningBackground,
1430
+ border: `1px solid ${macOSColors.semantic.warning}33`
1431
+ },
1432
+ filterOptionLeft: {
1433
+ display: "inline-flex",
1434
+ flexDirection: "row",
1435
+ alignItems: "center",
1436
+ gap: 12,
1437
+ flex: 1,
1438
+ minWidth: 0
1439
+ },
1440
+ filterOptionContent: {
1441
+ display: "inline-flex",
1442
+ flexDirection: "column",
1443
+ flex: 1,
1444
+ minWidth: 0
1445
+ },
1446
+ filterOptionLabel: {
1447
+ color: macOSColors.text.secondary,
1448
+ fontSize: 11,
1449
+ marginBottom: 2,
1450
+ textTransform: "uppercase",
1451
+ letterSpacing: 0.5
1452
+ },
1453
+ filterOptionValue: {
1454
+ color: macOSColors.text.primary,
1455
+ fontSize: 13,
1456
+ fontFamily: "ui-monospace, Menlo, monospace",
1457
+ overflowWrap: "anywhere"
1458
+ },
1459
+ /** Native numberOfLines={1}. */
1460
+ singleLine: {
1461
+ whiteSpace: "nowrap",
1462
+ overflow: "hidden",
1463
+ textOverflow: "ellipsis",
1464
+ display: "block"
1465
+ },
1466
+ filterToggle: {
1467
+ display: "inline-flex",
1468
+ padding: "6px 10px",
1469
+ borderRadius: 4,
1470
+ backgroundColor: macOSColors.background.input,
1471
+ border: `1px solid ${macOSColors.border.default}`,
1472
+ flexShrink: 0
1473
+ },
1474
+ filterToggleActive: {
1475
+ backgroundColor: `${macOSColors.semantic.warning}26`,
1476
+ border: `1px solid ${macOSColors.semantic.warning}4D`
1477
+ },
1478
+ filterToggleText: {
1479
+ fontSize: 10,
1480
+ fontWeight: 600,
1481
+ color: macOSColors.text.muted,
1482
+ letterSpacing: 0.5
1483
+ },
1484
+ filterToggleTextActive: {
1485
+ color: macOSColors.semantic.warning
1486
+ },
1487
+ filterInfoBox: {
1488
+ backgroundColor: macOSColors.semantic.infoBackground,
1489
+ borderRadius: 6,
1490
+ padding: 10,
1491
+ border: `1px solid ${macOSColors.semantic.info}33`
1492
+ },
1493
+ filterInfoText: {
1494
+ color: macOSColors.text.secondary,
1495
+ fontSize: 11,
1496
+ lineHeight: "16px"
1497
+ }
1498
+ };