@buoy-gg/react-query 5.0.0 → 6.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,389 +1,63 @@
1
- # @buoy/react-query
1
+ # @buoy-gg/react-query
2
2
 
3
- [![npm](https://img.shields.io/npm/v/@buoy%2Freact-query)](https://www.npmjs.com/package/@buoy/react-query)
3
+ [![npm version](https://img.shields.io/npm/v/@buoy-gg/react-query?style=flat-square&labelColor=1c1c1c&color=10B981)](https://www.npmjs.com/package/@buoy-gg/react-query) [![npm downloads](https://img.shields.io/npm/dm/@buoy-gg/react-query?style=flat-square&labelColor=1c1c1c&color=10B981)](https://www.npmjs.com/package/@buoy-gg/react-query)
4
4
 
5
- React Query (TanStack Query) devtools modal for React Native development.
5
+ **Full TanStack Query devtools on the device — inspect the cache, simulate loading and error states, and flip your app offline with one tap.**
6
6
 
7
- ## Features
7
+ Part of [Buoy](https://github.com/Buoy-gg/buoy) — devtools that live inside your React Native app. Install it and it auto-appears in the floating menu from [`@buoy-gg/core`](https://www.npmjs.com/package/@buoy-gg/core).
8
8
 
9
- - **Query Inspector**: Browse and inspect all queries in your app
10
- - **Mutation Tracking**: Monitor mutations and their states
11
- - **Cache Inspection**: View and manipulate the React Query cache
12
- - **Query Invalidation**: Invalidate queries directly from the UI
13
- - **Refetch Control**: Manually trigger query refetches
14
- - **Filter & Search**: Filter queries by status, search by key
15
- - **WiFi Toggle**: Simulate offline mode to test query behavior
16
- - **Performance Monitoring**: Track query timings and performance
17
- - **Beautiful UI**: Modern, game-themed interface matching other React Buoy tools
9
+ ![React Query DevTools demo](https://github.com/user-attachments/assets/258e892d-3eaf-41f8-9fae-d7d2dcd6c39d)
18
10
 
19
- ## Installation
20
-
21
- This package is part of the React Buoy monorepo and is automatically available to other packages and the example app.
22
-
23
- For external projects:
11
+ ## Install
24
12
 
25
13
  ```bash
26
- npm install @buoy/react-query @tanstack/react-query
27
- # or
28
- pnpm add @buoy/react-query @tanstack/react-query
29
- # or
30
- yarn add @buoy/react-query @tanstack/react-query
14
+ npm install @buoy-gg/core @buoy-gg/react-query
31
15
  ```
32
16
 
33
- ## Quick Start
17
+ Requires `@tanstack/react-query` as a peer — you already have it if you use React Query.
34
18
 
35
- ### Simplest Setup - Just 1 Line!
19
+ ## Quick start
36
20
 
37
- **Import the preset and add it to your tools array. Done!**
21
+ Render `FloatingDevTools` inside your `QueryClientProvider`. The tool picks up your `QueryClient` from context and connects automatically — no extra call needed.
38
22
 
39
- ```typescript
40
- import { reactQueryToolPreset } from '@buoy/react-query';
41
- import { FloatingDevTools } from '@buoy/core';
23
+ ```tsx
42
24
  import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
25
+ import { FloatingDevTools } from '@buoy-gg/core';
43
26
 
44
27
  const queryClient = new QueryClient();
45
28
 
46
- const installedApps = [
47
- reactQueryToolPreset, // That's it! One line.
48
- // ...your other tools
49
- ];
50
-
51
- function App() {
29
+ export default function App() {
52
30
  return (
53
31
  <QueryClientProvider client={queryClient}>
54
- <FloatingDevTools
55
- apps={installedApps}
56
- environment="local"
57
- userRole="admin"
58
- />
59
- <YourAppContent />
32
+ <YourApp />
33
+ <FloatingDevTools />
60
34
  </QueryClientProvider>
61
35
  );
62
36
  }
63
37
  ```
64
38
 
65
- **Done!** The preset automatically:
66
- - ✅ Inspects all queries and mutations
67
- - ✅ Provides cache manipulation tools
68
- - ✅ Includes WiFi toggle for offline testing
69
- - ✅ No configuration required
70
-
71
- ### Custom Configuration
72
-
73
- If you want to customize the appearance:
74
-
75
- ```typescript
76
- import { createReactQueryTool } from '@buoy/react-query';
77
-
78
- const myQueryTool = createReactQueryTool({
79
- name: "TANSTACK",
80
- colorPreset: "purple",
81
- enableSharedModalDimensions: true,
82
- });
83
-
84
- const installedApps = [
85
- myQueryTool,
86
- // ...other tools
87
- ];
88
- ```
89
-
90
- ### Alternative: Manual Setup
91
-
92
- If you're not using FloatingDevTools or want more control:
93
-
94
- ```typescript
95
- import { ReactQueryDevToolsModal } from '@buoy/react-query';
96
- import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
97
-
98
- const queryClient = new QueryClient();
99
-
100
- function App() {
101
- const [showQuery, setShowQuery] = useState(false);
102
-
103
- return (
104
- <QueryClientProvider client={queryClient}>
105
- <Button onPress={() => setShowQuery(true)}>
106
- Open Query Inspector
107
- </Button>
108
-
109
- <ReactQueryDevToolsModal
110
- visible={showQuery}
111
- onClose={() => setShowQuery(false)}
112
- />
113
-
114
- <YourAppContent />
115
- </QueryClientProvider>
116
- );
117
- }
118
- ```
119
-
120
- ## API Reference
121
-
122
- ### Presets
123
-
124
- #### `reactQueryToolPreset`
125
-
126
- Pre-configured React Query devtools ready to use with FloatingDevTools.
127
-
128
- **Example:**
129
- ```typescript
130
- import { reactQueryToolPreset } from '@buoy/react-query';
131
-
132
- const installedApps = [reactQueryToolPreset];
133
- ```
134
-
135
- #### `createReactQueryTool(options?)`
136
-
137
- Create a custom React Query devtools configuration.
138
-
139
- **Options:**
140
- ```typescript
141
- {
142
- /** Tool name (default: "QUERY") */
143
- name?: string;
144
- /** Tool description */
145
- description?: string;
146
- /** Icon color preset (default: "red") */
147
- colorPreset?: "orange" | "cyan" | "purple" | "pink" | "yellow" | "green" | "red";
148
- /** Custom tool ID (default: "query") */
149
- id?: string;
150
- /** Enable shared modal dimensions (default: true) */
151
- enableSharedModalDimensions?: boolean;
152
- }
153
- ```
154
-
155
- **Example:**
156
- ```typescript
157
- import { createReactQueryTool } from '@buoy/react-query';
158
-
159
- const myQueryTool = createReactQueryTool({
160
- name: "RQ DEVTOOLS",
161
- colorPreset: "cyan",
162
- enableSharedModalDimensions: true,
163
- });
164
- ```
165
-
166
- ### Components
167
-
168
- #### `ReactQueryDevToolsModal`
169
-
170
- Main modal component for React Query devtools.
171
-
172
- **Props:**
173
- ```typescript
174
- interface ReactQueryDevToolsModalProps {
175
- /** Whether the modal is visible */
176
- visible: boolean;
177
- /** Callback when modal is closed */
178
- onClose: () => void;
179
- /** Whether to use shared modal dimensions (default: true) */
180
- enableSharedModalDimensions?: boolean;
181
- }
182
- ```
183
-
184
- **Example:**
185
- ```typescript
186
- <ReactQueryDevToolsModal
187
- visible={isVisible}
188
- onClose={handleClose}
189
- enableSharedModalDimensions={true}
190
- />
191
- ```
192
-
193
- #### `WifiToggle`
194
-
195
- Small WiFi toggle component for simulating offline mode.
196
-
197
- **Props:**
198
- ```typescript
199
- interface WifiToggleProps {
200
- /** Icon size (default: 16) */
201
- size?: number;
202
- }
203
- ```
204
-
205
- **Example:**
206
- ```typescript
207
- import { WifiToggle } from '@buoy/react-query';
208
-
209
- <WifiToggle size={20} />
210
- ```
211
-
212
- ### Hooks
213
-
214
- #### `useWifiState()`
215
-
216
- Hook to manage and access WiFi/online state.
217
-
218
- **Returns:**
219
- ```typescript
220
- {
221
- /** Whether the app is online */
222
- isOnline: boolean;
223
- /** Toggle WiFi state */
224
- handleWifiToggle: () => void;
225
- /** Set online state directly */
226
- setIsOnline: (online: boolean) => void;
227
- }
228
- ```
229
-
230
- **Example:**
231
- ```typescript
232
- import { useWifiState } from '@buoy/react-query';
233
-
234
- function MyComponent() {
235
- const { isOnline, handleWifiToggle } = useWifiState();
236
-
237
- return (
238
- <View>
239
- <Text>Status: {isOnline ? 'Online' : 'Offline'}</Text>
240
- <Button onPress={handleWifiToggle}>
241
- Toggle WiFi
242
- </Button>
243
- </View>
244
- );
245
- }
246
- ```
247
-
248
- ## Use Cases
39
+ That's it. The React Query tool (and a WiFi toggle) appear in the floating menu.
249
40
 
250
- ### Query Debugging
41
+ ## What you get
251
42
 
252
- Inspect and debug queries in real-time:
43
+ - **Cache inspection** — browse every query, drill into cached data with an interactive JSON tree, and edit values in place
44
+ - **Refetch & invalidate** — trigger refetches or invalidate queries straight from the UI
45
+ - **Simulate loading & error states** — test spinners and error boundaries without waiting on real network conditions
46
+ - **One-tap offline toggle** — the WiFi switch drives React Query's `onlineManager` to pause all queries, perfect for offline-first testing
47
+ - **Live mutation tracking** — status, variables, response or error, and timing for every mutation as it runs
48
+ - **Query states at a glance** — fresh, stale, fetching, paused, and inactive across your whole cache
49
+ - **Filter & search** — narrow by status or search by query key
253
50
 
254
- ```typescript
255
- import { reactQueryToolPreset } from '@buoy/react-query';
256
-
257
- // Add to your dev tools
258
- const installedApps = [reactQueryToolPreset];
259
-
260
- // Now you can:
261
- // - See all active queries
262
- // - View query data and status
263
- // - Inspect stale/fresh/loading states
264
- // - Manually refetch queries
265
- // - Invalidate queries to trigger refetch
266
- ```
267
-
268
- ### Offline Testing
269
-
270
- Test your app's behavior in offline mode:
271
-
272
- ```typescript
273
- import { WifiToggle } from '@buoy/react-query';
274
-
275
- // Add WiFi toggle to your header
276
- <WifiToggle size={18} />
277
-
278
- // Or use the hook directly
279
- const { isOnline, handleWifiToggle } = useWifiState();
280
- ```
281
-
282
- ### Cache Manipulation
283
-
284
- Inspect and manipulate the query cache:
285
-
286
- ```typescript
287
- // In the React Query devtools modal:
288
- // - View all cached queries
289
- // - See cache sizes and data
290
- // - Manually invalidate cache entries
291
- // - Trigger refetches
292
- // - Remove queries from cache
293
- ```
294
-
295
- ### Mutation Monitoring
296
-
297
- Track mutations and their states:
298
-
299
- ```typescript
300
- // In the React Query devtools modal:
301
- // - View all active mutations
302
- // - See mutation status (idle, loading, success, error)
303
- // - Inspect mutation data and variables
304
- // - Track mutation timing
305
- ```
306
-
307
- ## Features in Detail
308
-
309
- ### Query Browser
310
-
311
- - **View All Queries**: See all queries registered with React Query
312
- - **Filter by Status**: Filter by fresh, fetching, stale, or inactive
313
- - **Search**: Search queries by key
314
- - **Query Details**: View full query data, status, and metadata
315
- - **Refetch**: Manually trigger query refetches
316
- - **Invalidate**: Invalidate queries to trigger automatic refetch
317
- - **Remove**: Remove queries from cache
318
-
319
- ### Mutation Tracking
320
-
321
- - **View Mutations**: See all registered mutations
322
- - **Mutation Status**: Track mutation states (idle, loading, success, error)
323
- - **Variables**: Inspect mutation variables
324
- - **Results**: View mutation results and errors
325
- - **Reset**: Reset mutation states
326
-
327
- ### WiFi Toggle
328
-
329
- - **Offline Mode**: Simulate offline state
330
- - **Query Behavior**: Test how queries behave without network
331
- - **Retry Logic**: Verify retry and error handling
332
- - **Cache Fallbacks**: Test cache-first strategies
333
-
334
- ### Performance Monitoring
335
-
336
- - **Query Timing**: See how long queries take
337
- - **Cache Hits**: Track cache hit rates
338
- - **Stale Time**: Monitor query freshness
339
- - **Background Updates**: See when queries update in background
340
-
341
- ## React Query Integration
342
-
343
- This package integrates with React Query's online manager to provide WiFi toggle functionality. When you toggle WiFi off:
344
-
345
- - React Query treats the app as offline
346
- - Queries won't refetch automatically
347
- - New queries will be paused
348
- - Mutations will be paused until online
349
- - Background refetches are disabled
350
-
351
- This is perfect for testing offline scenarios without actually disconnecting your device.
352
-
353
- ## Dependencies
354
-
355
- - `@buoy/shared-ui` - Common UI components and utilities
356
- - `@tanstack/react-query` - React Query library (peer dependency)
357
- - React and React Native (peer dependencies)
358
-
359
- ## Development
360
-
361
- ### Building
362
-
363
- ```bash
364
- pnpm build
365
- ```
366
-
367
- ### Type Checking
368
-
369
- ```bash
370
- pnpm typecheck
371
- ```
372
-
373
- ### Clean Build
374
-
375
- ```bash
376
- pnpm clean
377
- ```
51
+ ## Desktop & AI
378
52
 
379
- ## License
53
+ The same live session streams to [Buoy Desktop](https://github.com/Buoy-gg/Buoy-Desktop) (free, macOS/Windows/Linux) and to Claude Code or Cursor via the [Buoy MCP server](https://buoy.gg/buoy/latest/docs/mcp).
380
54
 
381
- MIT
55
+ ## Free vs Pro
382
56
 
383
- ## Contributing
57
+ Every tool is free. [Pro](https://buoy.gg/pricing) unlocks production builds, the MCP server, and unlimited capture. Every weekend, Pro features unlock free for everyone.
384
58
 
385
- See the main repository [CONTRIBUTING.md](../../CONTRIBUTING.md) for contribution guidelines.
59
+ ---
386
60
 
387
- ## Support
61
+ 📚 [Full docs](https://buoy.gg/buoy/latest/docs/tools/react-query) · [All Buoy tools](https://github.com/Buoy-gg/buoy)
388
62
 
389
- For issues and feature requests, please visit the [GitHub repository](https://github.com/LovesWorking/react-native-buoy/issues).
63
+ Proprietary software. © Buoy LLC. [Terms](https://buoy.gg/terms)
@@ -199,7 +199,11 @@ function QueryBrowserModal({
199
199
  onModeChange: handleModeChange,
200
200
  enablePersistence: true,
201
201
  initialMode: "bottomSheet",
202
- enableGlitchEffects: true,
202
+ enableGlitchEffects: true
203
+ // The query list virtualizes itself (see QueryBrowser) — it must own
204
+ // scrolling. The filter view keeps the wrapper.
205
+ ,
206
+ disableScrollWrapper: !showFilterView,
203
207
  styles: {},
204
208
  footer: !showFilterView ? footerNode : undefined,
205
209
  footerHeight: !showFilterView ? 56 : undefined,
@@ -106,16 +106,51 @@ function QueryBrowser({
106
106
  })
107
107
  });
108
108
  }
109
- return /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.ScrollView, {
110
- style: styles.listWrapper,
111
- contentContainerStyle: contentContainerStyle || styles.listContent,
112
- showsVerticalScrollIndicator: true,
113
- children: filteredQueries.map(query => /*#__PURE__*/(0, _jsxRuntime.jsx)(_QueryRow.default, {
114
- query: query,
115
- isSelected: selectedQuery?.queryHash === query.queryHash,
116
- onSelect: handleQuerySelect
117
- }, `${query.queryHash}-${query.state.dataUpdatedAt}-${query.state.fetchStatus}`))
118
- });
109
+ return (
110
+ /*#__PURE__*/
111
+ // Virtualized list with STABLE keys (queryHash). The previous
112
+ // ScrollView + map mounted every row, and its key included
113
+ // dataUpdatedAt/fetchStatus so rows REMOUNTED on each update — at 300
114
+ // seeded queries that measured 168% CPU with 546 row renders during a
115
+ // 5s idle dwell (tool-bench 2026-07-06). TanStack Query objects are
116
+ // mutable with stable identity, so `stateSig` carries the changing
117
+ // fields for the row's memo comparison.
118
+ (0, _jsxRuntime.jsx)(_reactNative.FlatList, {
119
+ style: styles.listWrapper,
120
+ contentContainerStyle: contentContainerStyle || styles.listContent,
121
+ data: filteredQueries,
122
+ keyExtractor: queryKeyExtractor,
123
+ renderItem: ({
124
+ item: query
125
+ }) => /*#__PURE__*/(0, _jsxRuntime.jsx)(_QueryRow.default, {
126
+ query: query,
127
+ stateSig: computeQueryStateSig(query),
128
+ isSelected: selectedQuery?.queryHash === query.queryHash,
129
+ onSelect: handleQuerySelect
130
+ }),
131
+ showsVerticalScrollIndicator: true,
132
+ removeClippedSubviews: true,
133
+ initialNumToRender: 12,
134
+ maxToRenderPerBatch: 8,
135
+ windowSize: 5,
136
+ updateCellsBatchingPeriod: 50
137
+ })
138
+ );
139
+ }
140
+ const queryKeyExtractor = q => q.queryHash;
141
+
142
+ /** The row-visible slice of a query's mutable state, as a comparable
143
+ * string — drives QueryRow's memo (see comment above). */
144
+ function computeQueryStateSig(q) {
145
+ let observers = 0;
146
+ let stale = false;
147
+ try {
148
+ observers = q.getObserversCount();
149
+ stale = q.isStale();
150
+ } catch {
151
+ // defensive: state reads on a disposed query must not break the list
152
+ }
153
+ return `${q.state.dataUpdatedAt}|${q.state.fetchStatus}|${q.state.status}|${observers}|${stale}`;
119
154
  }
120
155
  const styles = _reactNative.StyleSheet.create({
121
156
  listWrapper: {
@@ -4,6 +4,7 @@ Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
6
  exports.default = void 0;
7
+ var _react = require("react");
7
8
  var _getQueryStatusLabel = require("../../utils/getQueryStatusLabel");
8
9
  var _sharedUi = require("@buoy-gg/shared-ui");
9
10
  var _jsxRuntime = require("react/jsx-runtime");
@@ -15,11 +16,15 @@ const getQueryText = query => {
15
16
  /**
16
17
  * Single row representation of a query for the list view, showing status and observer count.
17
18
  */
18
- const QueryRow = ({
19
+ // Memo justified by profiling (tool-bench 2026-07-06): 546 row renders in
20
+ // a 5s idle dwell at 300 queries. `stateSig` exists ONLY for this memo —
21
+ // Query objects are mutable with stable identity, so shallow-comparing
22
+ // `query` alone would never re-render (see QueryBrowser).
23
+ const QueryRow = /*#__PURE__*/(0, _react.memo)(function QueryRow({
19
24
  query,
20
25
  isSelected,
21
26
  onSelect
22
- }) => {
27
+ }) {
23
28
  // Buoy theme status color mapping
24
29
  const getStatusHexColor = status => {
25
30
  switch (status) {
@@ -76,5 +81,5 @@ const QueryRow = ({
76
81
  isSelected: isSelected,
77
82
  onPress: () => onSelect(query)
78
83
  });
79
- };
84
+ });
80
85
  var _default = exports.default = QueryRow;
@@ -195,7 +195,11 @@ export function QueryBrowserModal({
195
195
  onModeChange: handleModeChange,
196
196
  enablePersistence: true,
197
197
  initialMode: "bottomSheet",
198
- enableGlitchEffects: true,
198
+ enableGlitchEffects: true
199
+ // The query list virtualizes itself (see QueryBrowser) — it must own
200
+ // scrolling. The filter view keeps the wrapper.
201
+ ,
202
+ disableScrollWrapper: !showFilterView,
199
203
  styles: {},
200
204
  footer: !showFilterView ? footerNode : undefined,
201
205
  footerHeight: !showFilterView ? 56 : undefined,
@@ -1,7 +1,7 @@
1
1
  "use strict";
2
2
 
3
3
  import { useMemo, useCallback } from "react";
4
- import { View, StyleSheet, Text, ScrollView } from "react-native";
4
+ import { View, StyleSheet, Text, FlatList } from "react-native";
5
5
  import QueryRow from "./QueryRow";
6
6
  import useAllQueries from "../../hooks/useAllQueries";
7
7
  import { getQueryStatusLabel } from "../../utils/getQueryStatusLabel";
@@ -101,16 +101,51 @@ export default function QueryBrowser({
101
101
  })
102
102
  });
103
103
  }
104
- return /*#__PURE__*/_jsx(ScrollView, {
105
- style: styles.listWrapper,
106
- contentContainerStyle: contentContainerStyle || styles.listContent,
107
- showsVerticalScrollIndicator: true,
108
- children: filteredQueries.map(query => /*#__PURE__*/_jsx(QueryRow, {
109
- query: query,
110
- isSelected: selectedQuery?.queryHash === query.queryHash,
111
- onSelect: handleQuerySelect
112
- }, `${query.queryHash}-${query.state.dataUpdatedAt}-${query.state.fetchStatus}`))
113
- });
104
+ return (
105
+ /*#__PURE__*/
106
+ // Virtualized list with STABLE keys (queryHash). The previous
107
+ // ScrollView + map mounted every row, and its key included
108
+ // dataUpdatedAt/fetchStatus so rows REMOUNTED on each update — at 300
109
+ // seeded queries that measured 168% CPU with 546 row renders during a
110
+ // 5s idle dwell (tool-bench 2026-07-06). TanStack Query objects are
111
+ // mutable with stable identity, so `stateSig` carries the changing
112
+ // fields for the row's memo comparison.
113
+ _jsx(FlatList, {
114
+ style: styles.listWrapper,
115
+ contentContainerStyle: contentContainerStyle || styles.listContent,
116
+ data: filteredQueries,
117
+ keyExtractor: queryKeyExtractor,
118
+ renderItem: ({
119
+ item: query
120
+ }) => /*#__PURE__*/_jsx(QueryRow, {
121
+ query: query,
122
+ stateSig: computeQueryStateSig(query),
123
+ isSelected: selectedQuery?.queryHash === query.queryHash,
124
+ onSelect: handleQuerySelect
125
+ }),
126
+ showsVerticalScrollIndicator: true,
127
+ removeClippedSubviews: true,
128
+ initialNumToRender: 12,
129
+ maxToRenderPerBatch: 8,
130
+ windowSize: 5,
131
+ updateCellsBatchingPeriod: 50
132
+ })
133
+ );
134
+ }
135
+ const queryKeyExtractor = q => q.queryHash;
136
+
137
+ /** The row-visible slice of a query's mutable state, as a comparable
138
+ * string — drives QueryRow's memo (see comment above). */
139
+ function computeQueryStateSig(q) {
140
+ let observers = 0;
141
+ let stale = false;
142
+ try {
143
+ observers = q.getObserversCount();
144
+ stale = q.isStale();
145
+ } catch {
146
+ // defensive: state reads on a disposed query must not break the list
147
+ }
148
+ return `${q.state.dataUpdatedAt}|${q.state.fetchStatus}|${q.state.status}|${observers}|${stale}`;
114
149
  }
115
150
  const styles = StyleSheet.create({
116
151
  listWrapper: {
@@ -1,5 +1,6 @@
1
1
  "use strict";
2
2
 
3
+ import { memo } from "react";
3
4
  import { getQueryStatusLabel } from "../../utils/getQueryStatusLabel";
4
5
  import { CompactRow, buoyColors, useRelativeTime } from "@buoy-gg/shared-ui";
5
6
  import { jsx as _jsx } from "react/jsx-runtime";
@@ -11,11 +12,15 @@ const getQueryText = query => {
11
12
  /**
12
13
  * Single row representation of a query for the list view, showing status and observer count.
13
14
  */
14
- const QueryRow = ({
15
+ // Memo justified by profiling (tool-bench 2026-07-06): 546 row renders in
16
+ // a 5s idle dwell at 300 queries. `stateSig` exists ONLY for this memo —
17
+ // Query objects are mutable with stable identity, so shallow-comparing
18
+ // `query` alone would never re-render (see QueryBrowser).
19
+ const QueryRow = /*#__PURE__*/memo(function QueryRow({
15
20
  query,
16
21
  isSelected,
17
22
  onSelect
18
- }) => {
23
+ }) {
19
24
  // Buoy theme status color mapping
20
25
  const getStatusHexColor = status => {
21
26
  switch (status) {
@@ -72,5 +77,5 @@ const QueryRow = ({
72
77
  isSelected: isSelected,
73
78
  onPress: () => onSelect(query)
74
79
  });
75
- };
80
+ });
76
81
  export default QueryRow;
@@ -1 +1 @@
1
- {"version":3,"file":"QueryBrowserModal.d.ts","sourceRoot":"","sources":["../../../../../src/react-query/components/modals/QueryBrowserModal.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAkB,MAAM,uBAAuB,CAAC;AAiBxE,UAAU,sBAAsB;IAC9B,OAAO,EAAE,OAAO,CAAC;IACjB,gBAAgB,CAAC,EAAE,QAAQ,CAAC;IAC5B,aAAa,EAAE,CAAC,KAAK,EAAE,KAAK,GAAG,SAAS,KAAK,IAAI,CAAC;IAClD,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB,UAAU,CAAC,EAAE,CAAC,UAAU,EAAE,GAAG,KAAK,IAAI,CAAC;IACvC,YAAY,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,cAAc,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,KAAK,IAAI,CAAC;IACjD,2BAA2B,CAAC,EAAE,OAAO,CAAC;IACtC,WAAW,EAAE,CAAC,GAAG,EAAE,SAAS,GAAG,WAAW,KAAK,IAAI,CAAC;IACpD,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,cAAc,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;CACzC;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,EAChC,OAAO,EACP,gBAAgB,EAChB,aAAa,EACb,OAAO,EACP,UAAU,EACV,YAAY,EAAE,oBAAoB,EAClC,cAAc,EAAE,sBAAsB,EACtC,2BAAmC,EACnC,WAAW,EACX,UAAe,EACf,cAAc,GACf,EAAE,sBAAsB,sCA4NxB"}
1
+ {"version":3,"file":"QueryBrowserModal.d.ts","sourceRoot":"","sources":["../../../../../src/react-query/components/modals/QueryBrowserModal.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAkB,MAAM,uBAAuB,CAAC;AAiBxE,UAAU,sBAAsB;IAC9B,OAAO,EAAE,OAAO,CAAC;IACjB,gBAAgB,CAAC,EAAE,QAAQ,CAAC;IAC5B,aAAa,EAAE,CAAC,KAAK,EAAE,KAAK,GAAG,SAAS,KAAK,IAAI,CAAC;IAClD,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB,UAAU,CAAC,EAAE,CAAC,UAAU,EAAE,GAAG,KAAK,IAAI,CAAC;IACvC,YAAY,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,cAAc,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,KAAK,IAAI,CAAC;IACjD,2BAA2B,CAAC,EAAE,OAAO,CAAC;IACtC,WAAW,EAAE,CAAC,GAAG,EAAE,SAAS,GAAG,WAAW,KAAK,IAAI,CAAC;IACpD,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,cAAc,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;CACzC;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,EAChC,OAAO,EACP,gBAAgB,EAChB,aAAa,EACb,OAAO,EACP,UAAU,EACV,YAAY,EAAE,oBAAoB,EAClC,cAAc,EAAE,sBAAsB,EACtC,2BAAmC,EACnC,WAAW,EACX,UAAe,EACf,cAAc,GACf,EAAE,sBAAsB,sCA+NxB"}
@@ -1 +1 @@
1
- {"version":3,"file":"QueryBrowser.d.ts","sourceRoot":"","sources":["../../../../../src/react-query/components/query-browser/QueryBrowser.tsx"],"names":[],"mappings":"AACA,OAAO,EAAsC,SAAS,EAAE,MAAM,cAAc,CAAC;AAC7E,OAAO,EAAE,KAAK,EAAE,MAAM,uBAAuB,CAAC;AAM9C,UAAU,KAAK;IACb,aAAa,EAAE,KAAK,GAAG,SAAS,CAAC;IACjC,aAAa,EAAE,CAAC,KAAK,EAAE,KAAK,GAAG,SAAS,KAAK,IAAI,CAAC;IAClD,YAAY,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,qBAAqB,CAAC,EAAE,SAAS,CAAC;IAClC,OAAO,CAAC,EAAE,KAAK,EAAE,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,eAAe,CAAC,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IAC9B,gBAAgB,CAAC,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;CAChC;AAED;;GAEG;AACH,MAAM,CAAC,OAAO,UAAU,YAAY,CAAC,EACnC,aAAa,EACb,aAAa,EACb,YAAY,EACZ,iBAAiB,EACjB,qBAAqB,EACrB,OAAO,EAAE,eAAe,EACxB,UAAe,EACf,eAA2B,EAC3B,gBAA4B,GAC7B,EAAE,KAAK,+BAiIP"}
1
+ {"version":3,"file":"QueryBrowser.d.ts","sourceRoot":"","sources":["../../../../../src/react-query/components/query-browser/QueryBrowser.tsx"],"names":[],"mappings":"AACA,OAAO,EAAoC,SAAS,EAAE,MAAM,cAAc,CAAC;AAC3E,OAAO,EAAE,KAAK,EAAE,MAAM,uBAAuB,CAAC;AAM9C,UAAU,KAAK;IACb,aAAa,EAAE,KAAK,GAAG,SAAS,CAAC;IACjC,aAAa,EAAE,CAAC,KAAK,EAAE,KAAK,GAAG,SAAS,KAAK,IAAI,CAAC;IAClD,YAAY,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,qBAAqB,CAAC,EAAE,SAAS,CAAC;IAClC,OAAO,CAAC,EAAE,KAAK,EAAE,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,eAAe,CAAC,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IAC9B,gBAAgB,CAAC,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;CAChC;AAED;;GAEG;AACH,MAAM,CAAC,OAAO,UAAU,YAAY,CAAC,EACnC,aAAa,EACb,aAAa,EACb,YAAY,EACZ,iBAAiB,EACjB,qBAAqB,EACrB,OAAO,EAAE,eAAe,EACxB,UAAe,EACf,eAA2B,EAC3B,gBAA4B,GAC7B,EAAE,KAAK,+BA8IP"}
@@ -1,12 +1,14 @@
1
1
  import { Query } from "@tanstack/react-query";
2
2
  interface QueryRowProps {
3
3
  query: Query;
4
+ /** Changing state slice for the memo comparison — not read directly. */
5
+ stateSig: string;
4
6
  isSelected: boolean;
5
7
  onSelect: (query: Query) => void;
6
8
  }
7
9
  /**
8
10
  * Single row representation of a query for the list view, showing status and observer count.
9
11
  */
10
- declare const QueryRow: React.FC<QueryRowProps>;
12
+ declare const QueryRow: import("react").NamedExoticComponent<QueryRowProps>;
11
13
  export default QueryRow;
12
14
  //# sourceMappingURL=QueryRow.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"QueryRow.d.ts","sourceRoot":"","sources":["../../../../../src/react-query/components/query-browser/QueryRow.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,uBAAuB,CAAC;AAiB9C,UAAU,aAAa;IACrB,KAAK,EAAE,KAAK,CAAC;IACb,UAAU,EAAE,OAAO,CAAC;IACpB,QAAQ,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;CAClC;AAED;;GAEG;AACH,QAAA,MAAM,QAAQ,EAAE,KAAK,CAAC,EAAE,CAAC,aAAa,CA6DrC,CAAC;AAEF,eAAe,QAAQ,CAAC"}
1
+ {"version":3,"file":"QueryRow.d.ts","sourceRoot":"","sources":["../../../../../src/react-query/components/query-browser/QueryRow.tsx"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,EAAE,MAAM,uBAAuB,CAAC;AAiB9C,UAAU,aAAa;IACrB,KAAK,EAAE,KAAK,CAAC;IACb,wEAAwE;IACxE,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,OAAO,CAAC;IACpB,QAAQ,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;CAClC;AAED;;GAEG;AAKH,QAAA,MAAM,QAAQ,qDA6DZ,CAAC;AAEH,eAAe,QAAQ,CAAC"}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@buoy-gg/react-query",
3
- "version": "5.0.0",
4
- "description": "react-query package",
3
+ "version": "6.0.1",
4
+ "description": "TanStack Query devtools inside your React Native app — cache inspection, refetch & invalidate, offline toggle. Part of Buoy devtools.",
5
5
  "main": "lib/commonjs/index.js",
6
6
  "module": "lib/module/index.js",
7
7
  "types": "lib/typescript/index.d.ts",
@@ -26,8 +26,8 @@
26
26
  ],
27
27
  "sideEffects": false,
28
28
  "dependencies": {
29
- "@buoy-gg/shared-ui": "5.0.0",
30
- "@buoy-gg/floating-tools-core": "5.0.0"
29
+ "@buoy-gg/shared-ui": "6.0.1",
30
+ "@buoy-gg/floating-tools-core": "6.0.1"
31
31
  },
32
32
  "peerDependencies": {
33
33
  "@tanstack/react-query": ">=5.0.0",