@buoy-gg/network 7.0.12 → 7.0.14

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 (136) hide show
  1. package/lib/commonjs/index.js +52 -0
  2. package/lib/commonjs/network/components/NetworkDetailStepper.js +26 -14
  3. package/lib/commonjs/network/components/NetworkEventDetailView.js +86 -14
  4. package/lib/commonjs/network/components/NetworkEventItemCompact.js +4 -0
  5. package/lib/commonjs/network/components/NetworkHeaderLive.js +32 -7
  6. package/lib/commonjs/network/components/NetworkHeaderMenu.js +183 -0
  7. package/lib/commonjs/network/components/NetworkListScreen.js +134 -8
  8. package/lib/commonjs/network/components/NetworkModal.js +198 -51
  9. package/lib/commonjs/network/components/NetworkNumberPrompt.js +178 -0
  10. package/lib/commonjs/network/components/NetworkOverrideEditor.js +797 -0
  11. package/lib/commonjs/network/components/NetworkOverrideHeaderButton.js +102 -0
  12. package/lib/commonjs/network/components/NetworkOverridesButton.js +88 -0
  13. package/lib/commonjs/network/components/NetworkOverridesScreen.js +489 -0
  14. package/lib/commonjs/network/components/response-editor/Explorer.js +973 -0
  15. package/lib/commonjs/network/components/response-editor/deleteNestedDataByPath.js +56 -0
  16. package/lib/commonjs/network/components/response-editor/editorContext.js +33 -0
  17. package/lib/commonjs/network/components/response-editor/updateNestedDataByPath.js +61 -0
  18. package/lib/commonjs/network/hooks/useNetworkSelection.js +53 -0
  19. package/lib/commonjs/network/hooks/useOverrideRules.js +36 -0
  20. package/lib/commonjs/network/overrides/applyToFetch.js +80 -0
  21. package/lib/commonjs/network/overrides/applyToXhr.js +190 -0
  22. package/lib/commonjs/network/overrides/engine.js +70 -0
  23. package/lib/commonjs/network/overrides/matchRule.js +81 -0
  24. package/lib/commonjs/network/overrides/overrideRulesStore.js +550 -0
  25. package/lib/commonjs/network/overrides/presets.js +70 -0
  26. package/lib/commonjs/network/overrides/resolveOverride.js +158 -0
  27. package/lib/commonjs/network/overrides/types.js +85 -0
  28. package/lib/commonjs/network/sync/networkSyncAdapter.js +230 -1
  29. package/lib/commonjs/network/types/index.js +5 -1
  30. package/lib/commonjs/network/utils/networkEventStore.js +52 -6
  31. package/lib/commonjs/network/utils/networkListener.js +90 -10
  32. package/lib/commonjs/network/utils/networkSelectionStore.js +193 -0
  33. package/lib/commonjs/preset.js +11 -0
  34. package/lib/module/index.js +19 -0
  35. package/lib/module/network/components/NetworkDetailStepper.js +27 -15
  36. package/lib/module/network/components/NetworkEventDetailView.js +87 -15
  37. package/lib/module/network/components/NetworkEventItemCompact.js +5 -1
  38. package/lib/module/network/components/NetworkHeaderLive.js +32 -7
  39. package/lib/module/network/components/NetworkHeaderMenu.js +177 -0
  40. package/lib/module/network/components/NetworkListScreen.js +135 -9
  41. package/lib/module/network/components/NetworkModal.js +200 -53
  42. package/lib/module/network/components/NetworkNumberPrompt.js +174 -0
  43. package/lib/module/network/components/NetworkOverrideEditor.js +794 -0
  44. package/lib/module/network/components/NetworkOverrideHeaderButton.js +99 -0
  45. package/lib/module/network/components/NetworkOverridesButton.js +85 -0
  46. package/lib/module/network/components/NetworkOverridesScreen.js +485 -0
  47. package/lib/module/network/components/response-editor/Explorer.js +972 -0
  48. package/lib/module/network/components/response-editor/deleteNestedDataByPath.js +51 -0
  49. package/lib/module/network/components/response-editor/editorContext.js +29 -0
  50. package/lib/module/network/components/response-editor/updateNestedDataByPath.js +56 -0
  51. package/lib/module/network/hooks/useNetworkSelection.js +46 -0
  52. package/lib/module/network/hooks/useOverrideRules.js +32 -0
  53. package/lib/module/network/overrides/applyToFetch.js +72 -0
  54. package/lib/module/network/overrides/applyToXhr.js +185 -0
  55. package/lib/module/network/overrides/engine.js +64 -0
  56. package/lib/module/network/overrides/matchRule.js +75 -0
  57. package/lib/module/network/overrides/overrideRulesStore.js +547 -0
  58. package/lib/module/network/overrides/presets.js +65 -0
  59. package/lib/module/network/overrides/resolveOverride.js +152 -0
  60. package/lib/module/network/overrides/types.js +80 -0
  61. package/lib/module/network/sync/networkSyncAdapter.js +230 -1
  62. package/lib/module/network/types/index.js +3 -1
  63. package/lib/module/network/utils/networkEventStore.js +52 -6
  64. package/lib/module/network/utils/networkListener.js +91 -10
  65. package/lib/module/network/utils/networkSelectionStore.js +188 -0
  66. package/lib/module/preset.js +13 -1
  67. package/lib/typescript/index.d.ts +9 -0
  68. package/lib/typescript/index.d.ts.map +1 -1
  69. package/lib/typescript/network/components/NetworkDetailStepper.d.ts +8 -5
  70. package/lib/typescript/network/components/NetworkDetailStepper.d.ts.map +1 -1
  71. package/lib/typescript/network/components/NetworkEventDetailView.d.ts +36 -1
  72. package/lib/typescript/network/components/NetworkEventDetailView.d.ts.map +1 -1
  73. package/lib/typescript/network/components/NetworkEventItemCompact.d.ts +6 -0
  74. package/lib/typescript/network/components/NetworkEventItemCompact.d.ts.map +1 -1
  75. package/lib/typescript/network/components/NetworkHeaderLive.d.ts +13 -3
  76. package/lib/typescript/network/components/NetworkHeaderLive.d.ts.map +1 -1
  77. package/lib/typescript/network/components/NetworkHeaderMenu.d.ts +46 -0
  78. package/lib/typescript/network/components/NetworkHeaderMenu.d.ts.map +1 -0
  79. package/lib/typescript/network/components/NetworkListScreen.d.ts.map +1 -1
  80. package/lib/typescript/network/components/NetworkModal.d.ts.map +1 -1
  81. package/lib/typescript/network/components/NetworkNumberPrompt.d.ts +33 -0
  82. package/lib/typescript/network/components/NetworkNumberPrompt.d.ts.map +1 -0
  83. package/lib/typescript/network/components/NetworkOverrideEditor.d.ts +17 -0
  84. package/lib/typescript/network/components/NetworkOverrideEditor.d.ts.map +1 -0
  85. package/lib/typescript/network/components/NetworkOverrideHeaderButton.d.ts +27 -0
  86. package/lib/typescript/network/components/NetworkOverrideHeaderButton.d.ts.map +1 -0
  87. package/lib/typescript/network/components/NetworkOverridesButton.d.ts +17 -0
  88. package/lib/typescript/network/components/NetworkOverridesButton.d.ts.map +1 -0
  89. package/lib/typescript/network/components/NetworkOverridesScreen.d.ts +29 -0
  90. package/lib/typescript/network/components/NetworkOverridesScreen.d.ts.map +1 -0
  91. package/lib/typescript/network/components/response-editor/Explorer.d.ts +17 -0
  92. package/lib/typescript/network/components/response-editor/Explorer.d.ts.map +1 -0
  93. package/lib/typescript/network/components/response-editor/deleteNestedDataByPath.d.ts +9 -0
  94. package/lib/typescript/network/components/response-editor/deleteNestedDataByPath.d.ts.map +1 -0
  95. package/lib/typescript/network/components/response-editor/editorContext.d.ts +29 -0
  96. package/lib/typescript/network/components/response-editor/editorContext.d.ts.map +1 -0
  97. package/lib/typescript/network/components/response-editor/updateNestedDataByPath.d.ts +10 -0
  98. package/lib/typescript/network/components/response-editor/updateNestedDataByPath.d.ts.map +1 -0
  99. package/lib/typescript/network/hooks/useNetworkSelection.d.ts +26 -0
  100. package/lib/typescript/network/hooks/useNetworkSelection.d.ts.map +1 -0
  101. package/lib/typescript/network/hooks/useOverrideRules.d.ts +29 -0
  102. package/lib/typescript/network/hooks/useOverrideRules.d.ts.map +1 -0
  103. package/lib/typescript/network/overrides/__tests__/applyToFetch.test.d.ts +16 -0
  104. package/lib/typescript/network/overrides/__tests__/applyToFetch.test.d.ts.map +1 -0
  105. package/lib/typescript/network/overrides/__tests__/applyToXhr.test.d.ts +19 -0
  106. package/lib/typescript/network/overrides/__tests__/applyToXhr.test.d.ts.map +1 -0
  107. package/lib/typescript/network/overrides/__tests__/resolveOverride.test.d.ts +22 -0
  108. package/lib/typescript/network/overrides/__tests__/resolveOverride.test.d.ts.map +1 -0
  109. package/lib/typescript/network/overrides/applyToFetch.d.ts +50 -0
  110. package/lib/typescript/network/overrides/applyToFetch.d.ts.map +1 -0
  111. package/lib/typescript/network/overrides/applyToXhr.d.ts +43 -0
  112. package/lib/typescript/network/overrides/applyToXhr.d.ts.map +1 -0
  113. package/lib/typescript/network/overrides/engine.d.ts +47 -0
  114. package/lib/typescript/network/overrides/engine.d.ts.map +1 -0
  115. package/lib/typescript/network/overrides/matchRule.d.ts +22 -0
  116. package/lib/typescript/network/overrides/matchRule.d.ts.map +1 -0
  117. package/lib/typescript/network/overrides/overrideRulesStore.d.ts +205 -0
  118. package/lib/typescript/network/overrides/overrideRulesStore.d.ts.map +1 -0
  119. package/lib/typescript/network/overrides/presets.d.ts +38 -0
  120. package/lib/typescript/network/overrides/presets.d.ts.map +1 -0
  121. package/lib/typescript/network/overrides/resolveOverride.d.ts +46 -0
  122. package/lib/typescript/network/overrides/resolveOverride.d.ts.map +1 -0
  123. package/lib/typescript/network/overrides/types.d.ts +169 -0
  124. package/lib/typescript/network/overrides/types.d.ts.map +1 -0
  125. package/lib/typescript/network/sync/networkSyncAdapter.d.ts +73 -0
  126. package/lib/typescript/network/sync/networkSyncAdapter.d.ts.map +1 -1
  127. package/lib/typescript/network/types/index.d.ts +10 -0
  128. package/lib/typescript/network/types/index.d.ts.map +1 -1
  129. package/lib/typescript/network/utils/networkEventStore.d.ts +14 -0
  130. package/lib/typescript/network/utils/networkEventStore.d.ts.map +1 -1
  131. package/lib/typescript/network/utils/networkListener.d.ts +3 -0
  132. package/lib/typescript/network/utils/networkListener.d.ts.map +1 -1
  133. package/lib/typescript/network/utils/networkSelectionStore.d.ts +117 -0
  134. package/lib/typescript/network/utils/networkSelectionStore.d.ts.map +1 -0
  135. package/lib/typescript/preset.d.ts.map +1 -1
  136. package/package.json +2 -2
@@ -0,0 +1,972 @@
1
+ "use strict";
2
+
3
+ import { useState, useMemo, useCallback, useRef, useEffect, memo } from "react";
4
+ import { Text, TouchableOpacity, View, StyleSheet } from "react-native";
5
+ import { displayValue, buoyColors } from "@buoy-gg/shared-ui";
6
+ import { CopyButton as SharedCopyButton } from "@buoy-gg/shared-ui";
7
+ import { ChevronRight, ChevronDown, Trash } from "@buoy-gg/shared-ui";
8
+ import { CyberpunkInput } from "@buoy-gg/shared-ui/dataViewer";
9
+ import { updateNestedDataByPath } from "./updateNestedDataByPath";
10
+ import { deleteNestedDataByPath } from "./deleteNestedDataByPath";
11
+ import { useResponseEditor } from "./editorContext";
12
+
13
+ /**
14
+ * The response-body tree: preview and editor as ONE surface.
15
+ *
16
+ * A 1:1 port of the React Query tool's `Explorer` — deliberately, because that
17
+ * is the interaction that already works: there is no read mode and no edit
18
+ * mode, no button that swaps one for the other. A string renders AS its input,
19
+ * a boolean AS its toggle, and typing into what you are reading is the edit.
20
+ *
21
+ * The only thing changed from the original is where an edit LANDS. There it was
22
+ * `queryClient.setQueryData(activeQuery.queryKey, …)`; here it's the `onChange`
23
+ * from `ResponseEditorContext`, which turns the rebuilt body into an override
24
+ * rule. Everything else — the chunked pages, the focus handling, the
25
+ * local-input-state race note below — is carried over unchanged so the two
26
+ * trees behave identically.
27
+ */
28
+
29
+ // Stable constants to prevent re-renders [[memory:4875251]]
30
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
31
+ const CHUNK_SIZE = 100;
32
+ const HIT_SLOP_OPTIMIZED = {
33
+ top: 8,
34
+ bottom: 8,
35
+ left: 8,
36
+ right: 8
37
+ };
38
+ const EXPANDER_SIZE = 12;
39
+
40
+ // Optimized chunking function moved to module scope [[memory:4875251]]
41
+ const chunkArray = (array, size = CHUNK_SIZE) => {
42
+ if (size < 1 || array.length === 0) return [];
43
+ const result = [];
44
+ for (let i = 0; i < array.length; i += size) {
45
+ result.push(array.slice(i, i + size));
46
+ }
47
+ return result;
48
+ };
49
+ // Memoized Expander component for performance [[memory:4875251]]
50
+ const Expander = /*#__PURE__*/memo(({
51
+ expanded,
52
+ isFocused = false,
53
+ isMain = false
54
+ }) => {
55
+ return /*#__PURE__*/_jsx(View, {
56
+ style: [styles.expanderIcon, isMain && styles.expanderIconMain, expanded ? styles.expanded : styles.collapsed],
57
+ children: expanded ? /*#__PURE__*/_jsx(ChevronDown, {
58
+ size: isMain ? 14 : EXPANDER_SIZE,
59
+ color: isFocused ? buoyColors.primary : isMain ? buoyColors.text : buoyColors.textSecondary,
60
+ strokeWidth: 2.5
61
+ }) : /*#__PURE__*/_jsx(ChevronRight, {
62
+ size: isMain ? 14 : EXPANDER_SIZE,
63
+ color: isFocused ? buoyColors.primary : isMain ? buoyColors.text : buoyColors.textSecondary,
64
+ strokeWidth: 2.5
65
+ })
66
+ });
67
+ });
68
+ Expander.displayName = "Expander";
69
+ // Local wrapper for the shared CopyButton to maintain backward compatibility
70
+ const CopyButton = /*#__PURE__*/memo(({
71
+ value,
72
+ isFocused = false
73
+ }) => {
74
+ return /*#__PURE__*/_jsx(SharedCopyButton, {
75
+ value: value,
76
+ isFocused: isFocused,
77
+ buttonStyle: isFocused ? {
78
+ ...styles.buttonStyle,
79
+ ...styles.buttonStyleFocused
80
+ } : styles.buttonStyle
81
+ });
82
+ });
83
+ CopyButton.displayName = "CopyButton";
84
+
85
+ // Memoized DeleteItemButton component [[memory:4875251]]
86
+ const DeleteItemButton = /*#__PURE__*/memo(({
87
+ dataPath,
88
+ isFocused = false
89
+ }) => {
90
+ const editor = useResponseEditor();
91
+ const handleDelete = useCallback(() => {
92
+ if (!editor) return;
93
+ editor.onChange(deleteNestedDataByPath(editor.root, dataPath));
94
+ }, [editor, dataPath]);
95
+ if (!editor) return null;
96
+ return /*#__PURE__*/_jsx(TouchableOpacity, {
97
+ "sentry-label": "ignore devtools explorer delete button",
98
+ onPress: handleDelete,
99
+ style: [styles.deleteButton, isFocused && styles.deleteButtonFocused],
100
+ accessibilityLabel: "Delete item",
101
+ hitSlop: HIT_SLOP_OPTIMIZED,
102
+ activeOpacity: 0.7,
103
+ children: /*#__PURE__*/_jsx(Trash, {
104
+ size: 14,
105
+ strokeWidth: 2,
106
+ color: isFocused ? buoyColors.error : buoyColors.error + "CC"
107
+ })
108
+ });
109
+ });
110
+ DeleteItemButton.displayName = "DeleteItemButton";
111
+ // Memoized ClearArrayButton component [[memory:4875251]]
112
+ const ClearArrayButton = /*#__PURE__*/memo(({
113
+ dataPath,
114
+ isFocused = false
115
+ }) => {
116
+ const editor = useResponseEditor();
117
+ const handleClear = useCallback(() => {
118
+ if (!editor) return;
119
+ editor.onChange(updateNestedDataByPath(editor.root, dataPath, []));
120
+ }, [editor, dataPath]);
121
+ if (!editor) return null;
122
+ return /*#__PURE__*/_jsx(TouchableOpacity, {
123
+ "sentry-label": "ignore devtools explorer clear button",
124
+ style: [styles.clearButton, isFocused && styles.clearButtonFocused],
125
+ "aria-label": "Remove all items",
126
+ onPress: handleClear,
127
+ hitSlop: HIT_SLOP_OPTIMIZED,
128
+ activeOpacity: 0.7,
129
+ children: /*#__PURE__*/_jsx(Text, {
130
+ style: [styles.clearButtonText, {
131
+ color: isFocused ? buoyColors.warning : buoyColors.warning + "CC"
132
+ }],
133
+ children: "[]"
134
+ })
135
+ });
136
+ });
137
+ ClearArrayButton.displayName = "ClearArrayButton";
138
+ // ToggleValueButton - not memoized because parent Explorer passes new dataPath array each render
139
+ // which defeats memo anyway, and we need reliable re-renders when value changes
140
+ function ToggleValueButton({
141
+ dataPath,
142
+ value,
143
+ itemsDeletable
144
+ }) {
145
+ const editor = useResponseEditor();
146
+ const handleClick = useCallback(() => {
147
+ if (!editor) return;
148
+ const currentValue = typeof value === "boolean" ? value : false;
149
+ editor.onChange(updateNestedDataByPath(editor.root, dataPath, !currentValue));
150
+ }, [editor, dataPath, value]);
151
+ const handleDelete = useCallback(() => {
152
+ if (!editor) return;
153
+ editor.onChange(deleteNestedDataByPath(editor.root, dataPath));
154
+ }, [editor, dataPath]);
155
+ if (!editor) return null;
156
+
157
+ // Pre-compute styles based on value state
158
+ const badgeStyle = value ? styles.toggleBadgeTrue : styles.toggleBadgeFalse;
159
+ const textStyle = value ? styles.toggleTextTrue : styles.toggleTextFalse;
160
+ return /*#__PURE__*/_jsxs(TouchableOpacity, {
161
+ "sentry-label": "ignore devtools explorer toggle button",
162
+ style: styles.modernToggleButton,
163
+ onPress: handleClick,
164
+ hitSlop: HIT_SLOP_OPTIMIZED,
165
+ activeOpacity: 0.8,
166
+ children: [/*#__PURE__*/_jsx(View, {
167
+ style: [styles.toggleBadge, badgeStyle],
168
+ children: /*#__PURE__*/_jsx(Text, {
169
+ style: [styles.toggleBadgeText, textStyle],
170
+ children: value ? "TRUE" : "FALSE"
171
+ })
172
+ }), itemsDeletable && /*#__PURE__*/_jsx(TouchableOpacity, {
173
+ "sentry-label": "ignore devtools explorer delete button in toggle",
174
+ onPress: handleDelete,
175
+ style: styles.deleteButtonInToggle,
176
+ accessibilityLabel: "Delete item",
177
+ hitSlop: HIT_SLOP_OPTIMIZED,
178
+ activeOpacity: 0.7,
179
+ children: /*#__PURE__*/_jsx(Trash, {
180
+ size: 14,
181
+ strokeWidth: 2,
182
+ color: buoyColors.error + "CC"
183
+ })
184
+ })]
185
+ });
186
+ }
187
+ // Optimized Explorer component following rule2 guidelines [[memory:4875251]]
188
+ /**
189
+ * Recursive data explorer component used for both editable and read-only JSON trees inside the
190
+ * React Query dev tools.
191
+ */
192
+ export default function Explorer({
193
+ editable,
194
+ label,
195
+ value,
196
+ defaultExpanded,
197
+ dataPath,
198
+ itemsDeletable,
199
+ dataVersion = 0
200
+ }) {
201
+ const editor = useResponseEditor();
202
+ const [isRowFocused, setIsRowFocused] = useState(false);
203
+
204
+ // Local state for input value to handle typing properly
205
+ const [localInputValue, setLocalInputValue] = useState("");
206
+
207
+ // Sync local state with prop value
208
+ // ⚠️ CRITICAL: Do NOT add localInputValue to the dependency array!
209
+ // Adding localInputValue causes a race condition where user edits get reverted:
210
+ // 1. User types "5101" → setLocalInputValue("5101")
211
+ // 2. Cache updates
212
+ // 3. useEffect fires because localInputValue changed
213
+ // 4. At this moment, value prop is still old (5100)
214
+ // 5. Syncs back to 5100, reverting user's change ❌
215
+ // Only sync when EXTERNAL changes happen (value, label, dataVersion)
216
+ useEffect(() => {
217
+ if (value !== null && value !== undefined && (typeof value === "string" || typeof value === "number")) {
218
+ const newValue = value.toString();
219
+ setLocalInputValue(newValue);
220
+ }
221
+ }, [value, label, dataVersion]); // ⚠️ DO NOT add localInputValue here!
222
+
223
+ // Determine if this is a main section
224
+ const isMainSection = useMemo(() => {
225
+ const upperLabel = label.toUpperCase();
226
+ return ["DATA", "QUERY", "QUERYKEY", "TYPES", "STATS", "OPTIONS", "OBSERVERS"].includes(upperLabel);
227
+ }, [label]);
228
+
229
+ // Explorer's section is expanded or collapsed
230
+ const [isExpanded, setIsExpanded] = useState((defaultExpanded || []).includes(label));
231
+ // Remove unnecessary useCallback - simple state setter [[memory:4875251]]
232
+ const toggleExpanded = () => setIsExpanded(old => !old);
233
+ const [expandedPages, setExpandedPages] = useState([]);
234
+
235
+ // Optimized subEntries computation with early returns and limited processing [[memory:4875251]]
236
+ const subEntries = useMemo(() => {
237
+ // Early return for primitive values to avoid unnecessary computation
238
+ if (value === null || value === undefined || typeof value !== "object") {
239
+ return [];
240
+ }
241
+ if (Array.isArray(value)) {
242
+ // Limit array processing for performance [[memory:4875251]]
243
+ const limitedValue = value.length > 1000 ? value.slice(0, 1000) : value;
244
+ return limitedValue.map((d, i) => ({
245
+ label: i.toString(),
246
+ value: d
247
+ }));
248
+ }
249
+ if (value instanceof Map) {
250
+ // Limit Map entries for performance
251
+ const entries = Array.from(value.entries()).slice(0, 1000);
252
+ return entries.map(([key, val]) => ({
253
+ label: key.toString(),
254
+ value: val
255
+ }));
256
+ }
257
+ if (value instanceof Set) {
258
+ // Limit Set entries for performance
259
+ const entries = Array.from(value).slice(0, 1000);
260
+ return entries.map((val, i) => ({
261
+ label: i.toString(),
262
+ value: val
263
+ }));
264
+ }
265
+
266
+ // Handle regular objects with key limiting
267
+ const entries = Object.entries(value).slice(0, 1000);
268
+ return entries.map(([key, val]) => ({
269
+ label: key,
270
+ value: val
271
+ }));
272
+ }, [value]);
273
+
274
+ // Optimized valueType computation with early returns [[memory:4875251]]
275
+ const valueType = useMemo(() => {
276
+ if (Array.isArray(value)) return "array";
277
+ if (value === null || typeof value !== "object") return typeof value;
278
+ if (value instanceof Map || value instanceof Set) return "Iterable";
279
+ return "object";
280
+ }, [value]);
281
+
282
+ // Optimized chunking with stable chunk size [[memory:4875251]]
283
+ const subEntryPages = useMemo(() => {
284
+ return chunkArray(subEntries, CHUNK_SIZE);
285
+ }, [subEntries]);
286
+ const currentDataPath = dataPath ?? [];
287
+
288
+ // Optimize handleChange using refs to avoid dependency arrays [[memory:4875251]]
289
+ const editorRef = useRef(editor);
290
+ const dataPathRef = useRef(currentDataPath);
291
+ const valueTypeRef = useRef(valueType);
292
+ editorRef.current = editor;
293
+ dataPathRef.current = currentDataPath;
294
+ valueTypeRef.current = valueType;
295
+ const handleChange = useCallback((isNumber, newValue) => {
296
+ // Update local state immediately for responsive typing
297
+ setLocalInputValue(newValue);
298
+ const current = editorRef.current;
299
+ if (!current) return;
300
+ if (isNumber && isNaN(Number(newValue))) return;
301
+ const updatedValue = valueTypeRef.current === "number" ? Number(newValue) : newValue;
302
+ current.onChange(updateNestedDataByPath(current.root, dataPathRef.current, updatedValue));
303
+ }, [setLocalInputValue]);
304
+ return /*#__PURE__*/_jsx(View, {
305
+ style: styles.minWidthWrapper,
306
+ children: /*#__PURE__*/_jsxs(View, {
307
+ style: styles.fullWidthMarginRight,
308
+ children: [subEntryPages.length > 0 && /*#__PURE__*/_jsxs(_Fragment, {
309
+ children: [/*#__PURE__*/_jsxs(View, {
310
+ style: [styles.flexRowItemsCenterGap, isMainSection && styles.flexRowItemsCenterGapMain],
311
+ children: [/*#__PURE__*/_jsxs(TouchableOpacity, {
312
+ "sentry-label": "ignore devtools explorer expander button",
313
+ style: styles.expanderButton,
314
+ onPress: toggleExpanded,
315
+ hitSlop: HIT_SLOP_OPTIMIZED,
316
+ activeOpacity: 0.6,
317
+ children: [/*#__PURE__*/_jsx(Expander, {
318
+ expanded: isExpanded,
319
+ isFocused: isRowFocused,
320
+ isMain: isMainSection
321
+ }), /*#__PURE__*/_jsx(Text, {
322
+ style: [styles.labelText, isRowFocused && styles.labelTextFocused, isMainSection && styles.labelTextMain],
323
+ children: label
324
+ }), /*#__PURE__*/_jsx(Text, {
325
+ style: styles.textGray500,
326
+ children: `${String(valueType).toLowerCase() === "iterable" ? "(Iterable) " : ""}${subEntries.length} ${subEntries.length > 1 ? `items` : `item`}`
327
+ })]
328
+ }), editable && /*#__PURE__*/_jsxs(View, {
329
+ style: styles.flexRowGapItemsCenter,
330
+ children: [/*#__PURE__*/_jsx(CopyButton, {
331
+ value: value,
332
+ isFocused: isRowFocused
333
+ }), itemsDeletable && editor !== null && /*#__PURE__*/_jsx(DeleteItemButton, {
334
+ dataPath: currentDataPath,
335
+ isFocused: isRowFocused
336
+ }), valueType === "array" && editor !== null && /*#__PURE__*/_jsx(ClearArrayButton, {
337
+ dataPath: currentDataPath,
338
+ isFocused: isRowFocused
339
+ })]
340
+ })]
341
+ }), isExpanded && /*#__PURE__*/_jsxs(_Fragment, {
342
+ children: [subEntryPages.length === 1 && /*#__PURE__*/_jsx(View, {
343
+ style: [styles.singleEntryContainer, isMainSection && styles.singleEntryContainerMain],
344
+ children: subEntries.map((entry, index) => /*#__PURE__*/_jsx(Explorer, {
345
+ defaultExpanded: defaultExpanded,
346
+ label: entry.label,
347
+ value: entry.value,
348
+ editable: editable,
349
+ dataPath: [...currentDataPath, entry.label],
350
+ itemsDeletable: valueType === "array" || valueType === "Iterable" || valueType === "object",
351
+ dataVersion: dataVersion
352
+ }, entry.label + index))
353
+ }), subEntryPages.length > 1 && /*#__PURE__*/_jsx(View, {
354
+ style: styles.multiEntryContainer,
355
+ children: subEntryPages.map((entries, index) => /*#__PURE__*/_jsx(View, {
356
+ children: /*#__PURE__*/_jsxs(View, {
357
+ style: styles.relativeOutlineNone,
358
+ children: [/*#__PURE__*/_jsxs(TouchableOpacity, {
359
+ "sentry-label": "ignore devtools explorer page toggle",
360
+ onPress: () => setExpandedPages(old => old.includes(index) ? old.filter(d => d !== index) : [...old, index]),
361
+ style: styles.pageExpanderButton,
362
+ hitSlop: HIT_SLOP_OPTIMIZED,
363
+ children: [/*#__PURE__*/_jsx(Expander, {
364
+ expanded: expandedPages.includes(index)
365
+ }), /*#__PURE__*/_jsxs(Text, {
366
+ style: styles.pageRangeText,
367
+ children: ["[", index * CHUNK_SIZE, "...", index * CHUNK_SIZE + CHUNK_SIZE - 1, "]"]
368
+ })]
369
+ }), expandedPages.includes(index) && /*#__PURE__*/_jsx(View, {
370
+ style: styles.entriesContainer,
371
+ children: entries.map(entry => /*#__PURE__*/_jsx(Explorer, {
372
+ defaultExpanded: defaultExpanded,
373
+ label: entry.label,
374
+ value: entry.value,
375
+ editable: editable,
376
+ dataPath: [...currentDataPath, entry.label],
377
+ dataVersion: dataVersion
378
+ }, entry.label))
379
+ })]
380
+ })
381
+ }, index))
382
+ })]
383
+ })]
384
+ }), subEntryPages.length === 0 && /*#__PURE__*/_jsxs(View, {
385
+ style: styles.flexRowGapFullWidth,
386
+ children: [editable && editor !== null && (valueType === "string" || valueType === "number" || valueType === "boolean") ? /*#__PURE__*/_jsxs(_Fragment, {
387
+ children: [editable && editor && (valueType === "string" || valueType === "number") && /*#__PURE__*/_jsx(View, {
388
+ style: styles.nebulaInputWrapper,
389
+ children: /*#__PURE__*/_jsx(CyberpunkInput, {
390
+ label: label,
391
+ accessibilityLabel: "Data input field for editing values",
392
+ style: [valueType === "number" ? styles.textNumber : styles.textString],
393
+ keyboardType: valueType === "number" ? "numeric" : "default",
394
+ value: localInputValue,
395
+ onChangeText: newValue => handleChange(valueType === "number", newValue),
396
+ onFocus: () => setIsRowFocused(true),
397
+ onBlur: () => setIsRowFocused(false),
398
+ showNumberControls: valueType === "number",
399
+ onIncrement: () => {
400
+ const currentNum = Number(localInputValue) || 0;
401
+ handleChange(true, String(currentNum + 1));
402
+ },
403
+ onDecrement: () => {
404
+ const currentNum = Number(localInputValue) || 0;
405
+ handleChange(true, String(currentNum - 1));
406
+ },
407
+ showDeleteButton: itemsDeletable,
408
+ onDelete: () => {
409
+ editor.onChange(deleteNestedDataByPath(editor.root, currentDataPath));
410
+ }
411
+ })
412
+ }), valueType === "boolean" && /*#__PURE__*/_jsxs(View, {
413
+ style: styles.booleanRowContainer,
414
+ children: [/*#__PURE__*/_jsx(Text, {
415
+ style: styles.booleanLabel,
416
+ children: label
417
+ }), /*#__PURE__*/_jsx(View, {
418
+ style: styles.booleanToggleWrapper,
419
+ children: /*#__PURE__*/_jsx(ToggleValueButton, {
420
+ dataPath: currentDataPath,
421
+ value: value,
422
+ itemsDeletable: itemsDeletable
423
+ })
424
+ })]
425
+ })]
426
+ }) : /*#__PURE__*/_jsxs(_Fragment, {
427
+ children: [/*#__PURE__*/_jsx(Text, {
428
+ style: styles.text344054,
429
+ children: label
430
+ }), /*#__PURE__*/_jsx(Text, {
431
+ style: styles.displayValueText,
432
+ children: displayValue(value)
433
+ })]
434
+ }), editable && itemsDeletable && editor !== null && valueType !== "string" && valueType !== "number" && valueType !== "boolean" && /*#__PURE__*/_jsx(DeleteItemButton, {
435
+ dataPath: currentDataPath,
436
+ isFocused: isRowFocused
437
+ })]
438
+ })]
439
+ })
440
+ });
441
+ }
442
+ const styles = StyleSheet.create({
443
+ buttonStyle: {
444
+ backgroundColor: buoyColors.card + "E6",
445
+ borderWidth: 1,
446
+ borderColor: buoyColors.textSecondary + "33",
447
+ borderRadius: 6,
448
+ flexDirection: "row",
449
+ alignItems: "center",
450
+ justifyContent: "center",
451
+ width: 28,
452
+ height: 28,
453
+ position: "relative",
454
+ shadowColor: "#000",
455
+ shadowOffset: {
456
+ width: 0,
457
+ height: 1
458
+ },
459
+ shadowOpacity: 0.2,
460
+ shadowRadius: 2
461
+ },
462
+ buttonStyleFocused: {
463
+ borderColor: buoyColors.primary + "CC",
464
+ backgroundColor: buoyColors.primary + "26",
465
+ shadowColor: buoyColors.primary,
466
+ shadowOpacity: 0.3,
467
+ shadowRadius: 4
468
+ },
469
+ deleteButton: {
470
+ backgroundColor: buoyColors.error + "1A",
471
+ borderColor: buoyColors.error + "4D",
472
+ borderWidth: 1,
473
+ borderRadius: 6,
474
+ padding: 0,
475
+ alignItems: "center",
476
+ justifyContent: "center",
477
+ width: 28,
478
+ height: 28,
479
+ position: "relative",
480
+ shadowColor: buoyColors.error,
481
+ shadowOffset: {
482
+ width: 0,
483
+ height: 0
484
+ },
485
+ shadowOpacity: 0.15,
486
+ shadowRadius: 3
487
+ },
488
+ deleteButtonFocused: {
489
+ borderColor: buoyColors.error + "CC",
490
+ backgroundColor: buoyColors.error + "33",
491
+ shadowOpacity: 0.3,
492
+ shadowRadius: 5
493
+ },
494
+ deleteButtonInToggle: {
495
+ backgroundColor: buoyColors.error + "1A",
496
+ borderColor: buoyColors.error + "4D",
497
+ borderWidth: 1,
498
+ borderRadius: 6,
499
+ padding: 0,
500
+ alignItems: "center",
501
+ justifyContent: "center",
502
+ width: 28,
503
+ height: 28,
504
+ shadowColor: buoyColors.error,
505
+ shadowOffset: {
506
+ width: 0,
507
+ height: 0
508
+ },
509
+ shadowOpacity: 0.15,
510
+ shadowRadius: 3
511
+ },
512
+ clearButton: {
513
+ backgroundColor: buoyColors.warning + "1A",
514
+ borderWidth: 1,
515
+ borderColor: buoyColors.warning + "4D",
516
+ borderRadius: 6,
517
+ flexDirection: "row",
518
+ padding: 0,
519
+ alignItems: "center",
520
+ justifyContent: "center",
521
+ width: 28,
522
+ height: 28,
523
+ position: "relative",
524
+ zIndex: 10,
525
+ shadowColor: buoyColors.warning,
526
+ shadowOffset: {
527
+ width: 0,
528
+ height: 0
529
+ },
530
+ shadowOpacity: 0.15,
531
+ shadowRadius: 3
532
+ },
533
+ clearButtonFocused: {
534
+ borderColor: buoyColors.warning + "CC",
535
+ backgroundColor: buoyColors.warning + "33",
536
+ shadowOpacity: 0.3,
537
+ shadowRadius: 5
538
+ },
539
+ clearButtonText: {
540
+ fontSize: 12,
541
+ fontWeight: "700",
542
+ fontFamily: "monospace"
543
+ },
544
+ expanderIcon: {
545
+ width: 18,
546
+ height: 18,
547
+ alignItems: "center",
548
+ justifyContent: "center",
549
+ marginRight: 1,
550
+ backgroundColor: buoyColors.textSecondary + "14",
551
+ borderRadius: 3
552
+ },
553
+ expanderIconMain: {
554
+ backgroundColor: buoyColors.textSecondary + "1A",
555
+ width: 20,
556
+ height: 20,
557
+ borderRadius: 4,
558
+ borderWidth: 0.5,
559
+ borderColor: buoyColors.textSecondary + "33"
560
+ },
561
+ expanded: {
562
+ transform: [{
563
+ rotate: "0deg"
564
+ }]
565
+ },
566
+ collapsed: {
567
+ transform: [{
568
+ rotate: "0deg"
569
+ }]
570
+ },
571
+ minWidthWrapper: {
572
+ minWidth: 180,
573
+ fontSize: 11,
574
+ flexDirection: "row",
575
+ flexWrap: "wrap",
576
+ width: "100%",
577
+ marginVertical: 0.5
578
+ },
579
+ fullWidthMarginRight: {
580
+ position: "relative",
581
+ width: "100%",
582
+ marginRight: 1
583
+ },
584
+ flexRowItemsCenterGap: {
585
+ flexDirection: "row",
586
+ alignItems: "center",
587
+ justifyContent: "space-between",
588
+ paddingVertical: 3,
589
+ paddingHorizontal: 6,
590
+ marginVertical: 1,
591
+ borderRadius: 4,
592
+ backgroundColor: buoyColors.card + "66",
593
+ borderWidth: 0.5,
594
+ borderColor: buoyColors.textSecondary + "1A"
595
+ },
596
+ flexRowItemsCenterGapMain: {
597
+ backgroundColor: buoyColors.card + "E6",
598
+ borderLeftWidth: 2.5,
599
+ borderLeftColor: buoyColors.textSecondary + "80",
600
+ borderColor: buoyColors.textSecondary + "26",
601
+ paddingVertical: 5,
602
+ paddingHorizontal: 8,
603
+ marginBottom: 3,
604
+ borderWidth: 1,
605
+ shadowColor: "#000",
606
+ shadowOffset: {
607
+ width: 0,
608
+ height: 0
609
+ },
610
+ shadowOpacity: 0.08,
611
+ shadowRadius: 3
612
+ },
613
+ expanderButton: {
614
+ flexDirection: "row",
615
+ alignItems: "center",
616
+ backgroundColor: "transparent",
617
+ paddingVertical: 1,
618
+ paddingHorizontal: 2,
619
+ gap: 6,
620
+ borderWidth: 0,
621
+ minHeight: 24,
622
+ flex: 1
623
+ },
624
+ labelText: {
625
+ color: buoyColors.textSecondary,
626
+ fontSize: 10,
627
+ fontWeight: "600",
628
+ marginRight: 4,
629
+ fontFamily: "monospace",
630
+ letterSpacing: 0.4
631
+ },
632
+ labelTextFocused: {
633
+ color: buoyColors.text
634
+ },
635
+ labelTextMain: {
636
+ color: buoyColors.text,
637
+ fontSize: 11,
638
+ fontWeight: "700",
639
+ letterSpacing: 0.6
640
+ },
641
+ textGray500: {
642
+ color: buoyColors.textMuted,
643
+ fontSize: 10,
644
+ fontWeight: "400",
645
+ fontFamily: "monospace",
646
+ opacity: 0.7
647
+ },
648
+ pageRangeText: {
649
+ color: buoyColors.textSecondary,
650
+ fontSize: 10,
651
+ fontWeight: "600",
652
+ fontFamily: "monospace"
653
+ },
654
+ flexRowGapItemsCenter: {
655
+ flexDirection: "row",
656
+ alignItems: "center",
657
+ gap: 4,
658
+ paddingLeft: 2
659
+ },
660
+ singleEntryContainer: {
661
+ marginLeft: 2,
662
+ marginTop: 2,
663
+ paddingLeft: 8,
664
+ borderLeftWidth: 1.5,
665
+ borderLeftColor: buoyColors.textSecondary + "40"
666
+ },
667
+ singleEntryContainerMain: {
668
+ borderLeftColor: buoyColors.textSecondary + "4D",
669
+ marginLeft: 4,
670
+ paddingLeft: 10
671
+ },
672
+ multiEntryContainer: {
673
+ marginLeft: 2,
674
+ marginTop: 2,
675
+ paddingLeft: 8,
676
+ borderLeftWidth: 1.5,
677
+ borderLeftColor: buoyColors.textSecondary + "40"
678
+ },
679
+ multiEntryContainerMain: {
680
+ borderLeftColor: buoyColors.textSecondary + "4D",
681
+ marginLeft: 4,
682
+ paddingLeft: 10
683
+ },
684
+ relativeOutlineNone: {
685
+ position: "relative"
686
+ },
687
+ pageExpanderButton: {
688
+ flexDirection: "row",
689
+ alignItems: "center",
690
+ backgroundColor: buoyColors.card + "66",
691
+ paddingVertical: 3,
692
+ paddingHorizontal: 6,
693
+ gap: 6,
694
+ borderRadius: 4,
695
+ borderWidth: 0.5,
696
+ borderColor: buoyColors.textSecondary + "1A",
697
+ marginBottom: 2,
698
+ minHeight: 24
699
+ },
700
+ entriesContainer: {
701
+ marginLeft: 2,
702
+ paddingLeft: 8,
703
+ marginTop: 2,
704
+ borderLeftWidth: 1.5,
705
+ borderLeftColor: buoyColors.textSecondary + "40"
706
+ },
707
+ textNumber: {
708
+ color: buoyColors.text,
709
+ fontWeight: "600",
710
+ fontFamily: "monospace"
711
+ },
712
+ textString: {
713
+ color: buoyColors.text,
714
+ fontFamily: "monospace"
715
+ },
716
+ flexRowGapFullWidth: {
717
+ flexDirection: "row",
718
+ width: "100%",
719
+ alignItems: "center",
720
+ marginVertical: 1,
721
+ gap: 6,
722
+ paddingHorizontal: 4,
723
+ paddingVertical: 2,
724
+ borderRadius: 3
725
+ },
726
+ text344054: {
727
+ color: buoyColors.textSecondary,
728
+ fontWeight: "600",
729
+ fontSize: 9,
730
+ minWidth: 50,
731
+ fontFamily: "monospace",
732
+ letterSpacing: 0.4,
733
+ opacity: 0.8
734
+ },
735
+ numberInputButtons: {
736
+ position: "absolute",
737
+ right: 8,
738
+ top: "50%",
739
+ transform: [{
740
+ translateY: -18
741
+ }],
742
+ flexDirection: "row",
743
+ gap: 4,
744
+ zIndex: 10
745
+ },
746
+ touchableButton: {
747
+ width: 32,
748
+ height: 32,
749
+ borderRadius: 6,
750
+ backgroundColor: buoyColors.card + "E6",
751
+ borderWidth: 1,
752
+ borderColor: buoyColors.textSecondary + "33",
753
+ alignItems: "center",
754
+ justifyContent: "center",
755
+ marginLeft: 2,
756
+ shadowColor: "#000",
757
+ shadowOffset: {
758
+ width: 0,
759
+ height: 1
760
+ },
761
+ shadowOpacity: 0.2,
762
+ shadowRadius: 2
763
+ },
764
+ touchableButtonFocused: {
765
+ borderColor: buoyColors.primary + "CC",
766
+ backgroundColor: buoyColors.primary + "26",
767
+ shadowColor: buoyColors.primary,
768
+ shadowOffset: {
769
+ width: 0,
770
+ height: 0
771
+ },
772
+ shadowOpacity: 0.3,
773
+ shadowRadius: 4,
774
+ elevation: 3
775
+ },
776
+ nebulaInputWrapper: {
777
+ flex: 1,
778
+ width: "100%",
779
+ position: "relative"
780
+ },
781
+ displayValueText: {
782
+ flex: 1,
783
+ color: buoyColors.text,
784
+ fontWeight: "400",
785
+ fontFamily: "monospace",
786
+ fontSize: 12,
787
+ paddingVertical: 6,
788
+ paddingHorizontal: 10,
789
+ borderRadius: 6,
790
+ borderWidth: 1,
791
+ borderColor: buoyColors.textMuted + "66",
792
+ minHeight: 34
793
+ },
794
+ // New redesigned styles (kept for future use)
795
+ dataRow: {
796
+ flexDirection: "row",
797
+ alignItems: "center",
798
+ paddingVertical: 4,
799
+ paddingHorizontal: 8,
800
+ minHeight: 44,
801
+ gap: 12
802
+ },
803
+ dataLabel: {
804
+ color: buoyColors.textSecondary,
805
+ fontSize: 13,
806
+ fontWeight: "500",
807
+ minWidth: 80,
808
+ flexShrink: 0
809
+ },
810
+ dataValueContainer: {
811
+ flex: 1,
812
+ flexDirection: "row",
813
+ alignItems: "center"
814
+ },
815
+ inputWithActions: {
816
+ flex: 1,
817
+ position: "relative"
818
+ },
819
+ numberControls: {
820
+ position: "absolute",
821
+ right: 8,
822
+ top: "50%",
823
+ transform: [{
824
+ translateY: -16
825
+ }],
826
+ flexDirection: "column",
827
+ gap: 2
828
+ },
829
+ numberButton: {
830
+ width: 32,
831
+ height: 16,
832
+ borderRadius: 4,
833
+ alignItems: "center",
834
+ justifyContent: "center",
835
+ borderWidth: 1,
836
+ borderColor: buoyColors.primary + "0F"
837
+ },
838
+ readOnlyValue: {
839
+ color: buoyColors.text,
840
+ fontSize: 13,
841
+ fontFamily: "monospace",
842
+ paddingVertical: 8,
843
+ paddingHorizontal: 12,
844
+ borderRadius: 6,
845
+ borderWidth: 1,
846
+ borderColor: buoyColors.textMuted + "33",
847
+ flex: 1
848
+ },
849
+ actionButtons: {
850
+ flexDirection: "row",
851
+ gap: 6,
852
+ paddingLeft: 8
853
+ },
854
+ booleanContainer: {
855
+ flexDirection: "row",
856
+ alignItems: "center",
857
+ padding: 8,
858
+ borderRadius: 6,
859
+ borderWidth: 1,
860
+ borderColor: buoyColors.textMuted + "4D",
861
+ flex: 1
862
+ },
863
+ booleanText: {
864
+ marginLeft: 8,
865
+ color: buoyColors.warning,
866
+ fontWeight: "500",
867
+ fontFamily: "monospace"
868
+ },
869
+ modernToggleButton: {
870
+ flexDirection: "row",
871
+ alignItems: "center",
872
+ justifyContent: "space-between",
873
+ borderRadius: 6,
874
+ borderWidth: 1,
875
+ borderColor: buoyColors.textMuted + "99",
876
+ paddingHorizontal: 8,
877
+ paddingVertical: 6,
878
+ marginVertical: 2,
879
+ minHeight: 34,
880
+ gap: 8
881
+ },
882
+ toggleIconContainer: {
883
+ marginRight: 6
884
+ },
885
+ toggleIcon: {
886
+ padding: 8,
887
+ borderRadius: 8,
888
+ alignItems: "center",
889
+ justifyContent: "center",
890
+ width: 32,
891
+ height: 32
892
+ },
893
+ toggleIconSmall: {
894
+ width: 8,
895
+ height: 8,
896
+ borderRadius: 4
897
+ },
898
+ toggleContent: {
899
+ flex: 1,
900
+ minWidth: 0
901
+ },
902
+ toggleLabel: {
903
+ color: "#E5E7EB",
904
+ fontSize: 11,
905
+ fontWeight: "600",
906
+ fontFamily: "monospace",
907
+ letterSpacing: 0.3
908
+ },
909
+ toggleStatus: {
910
+ color: "#9CA3AF",
911
+ fontSize: 11
912
+ },
913
+ toggleBadge: {
914
+ marginLeft: 6,
915
+ paddingHorizontal: 6,
916
+ paddingVertical: 3,
917
+ borderRadius: 4,
918
+ borderWidth: 1
919
+ },
920
+ toggleBadgeText: {
921
+ fontSize: 9,
922
+ fontWeight: "700",
923
+ textTransform: "uppercase",
924
+ letterSpacing: 0.8,
925
+ fontFamily: "monospace"
926
+ },
927
+ // Pre-computed toggle icon styles to avoid inline objects [[memory:4875251]]
928
+ toggleIconTrue: {
929
+ backgroundColor: buoyColors.primary
930
+ },
931
+ toggleIconFalse: {
932
+ backgroundColor: buoyColors.textMuted
933
+ },
934
+ // Pre-computed toggle badge styles [[memory:4875251]]
935
+ toggleBadgeTrue: {
936
+ backgroundColor: buoyColors.primary + "1A",
937
+ borderColor: buoyColors.primary + "4D"
938
+ },
939
+ toggleBadgeFalse: {
940
+ backgroundColor: buoyColors.textMuted + "1A",
941
+ borderColor: buoyColors.textMuted + "4D"
942
+ },
943
+ // Pre-computed toggle text styles [[memory:4875251]]
944
+ toggleTextTrue: {
945
+ color: buoyColors.primary,
946
+ fontWeight: "600"
947
+ },
948
+ toggleTextFalse: {
949
+ color: buoyColors.textSecondary,
950
+ fontWeight: "500"
951
+ },
952
+ // Boolean row container styles
953
+ booleanRowContainer: {
954
+ flexDirection: "row",
955
+ alignItems: "center",
956
+ width: "100%",
957
+ gap: 8,
958
+ paddingVertical: 2
959
+ },
960
+ booleanLabel: {
961
+ color: buoyColors.textSecondary,
962
+ fontSize: 10,
963
+ fontWeight: "600",
964
+ fontFamily: "monospace",
965
+ letterSpacing: 0.4,
966
+ minWidth: 60,
967
+ flexShrink: 0
968
+ },
969
+ booleanToggleWrapper: {
970
+ flex: 1
971
+ }
972
+ });