@buoy-gg/react-query 7.0.30 → 7.0.32

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