@tanstack/react-query-devtools 4.10.4 → 4.12.0

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.
@@ -3,10 +3,10 @@ import * as React from 'react';
3
3
  import { useQueryClient, onlineManager, notifyManager } from '@tanstack/react-query';
4
4
  import { rankItem } from '@tanstack/match-sorter-utils';
5
5
  import useLocalStorage from './useLocalStorage.mjs';
6
- import { useIsMounted, sortFns, getQueryStatusColor, getQueryStatusLabel } from './utils.mjs';
6
+ import { defaultPanelSize, useIsMounted, getSidedProp, getSidePanelStyle, sortFns, getResizeHandleStyle, getQueryStatusColor, getQueryStatusLabel, isVerticalSide, minPanelSize } from './utils.mjs';
7
+ import { Panel, Select, Input, Button, ActiveQueryPanel, Code, QueryKeys, QueryKey } from './styledComponents.mjs';
7
8
  import ScreenReader from './screenreader.mjs';
8
- import { Button, Panel, Input, Select, ActiveQueryPanel, Code, QueryKeys, QueryKey } from './styledComponents.mjs';
9
- import { ThemeProvider, defaultTheme } from './theme.mjs';
9
+ import { defaultTheme, ThemeProvider } from './theme.mjs';
10
10
  import Explorer from './Explorer.mjs';
11
11
  import Logo from './Logo.mjs';
12
12
  import { useSyncExternalStore } from 'use-sync-external-store/shim/index.js';
@@ -19,33 +19,47 @@ function ReactQueryDevtools({
19
19
  position = 'bottom-left',
20
20
  containerElement: Container = 'aside',
21
21
  context,
22
- styleNonce
22
+ styleNonce,
23
+ panelPosition: initialPanelPosition = 'bottom'
23
24
  }) {
24
25
  const rootRef = React.useRef(null);
25
26
  const panelRef = React.useRef(null);
26
27
  const [isOpen, setIsOpen] = useLocalStorage('reactQueryDevtoolsOpen', initialIsOpen);
27
- const [devtoolsHeight, setDevtoolsHeight] = useLocalStorage('reactQueryDevtoolsHeight', null);
28
+ const [devtoolsHeight, setDevtoolsHeight] = useLocalStorage('reactQueryDevtoolsHeight', defaultPanelSize);
29
+ const [devtoolsWidth, setDevtoolsWidth] = useLocalStorage('reactQueryDevtoolsWidth', defaultPanelSize);
30
+ const [panelPosition = 'bottom', setPanelPosition] = useLocalStorage('reactQueryDevtoolsPanelPosition', initialPanelPosition);
28
31
  const [isResolvedOpen, setIsResolvedOpen] = React.useState(false);
29
32
  const [isResizing, setIsResizing] = React.useState(false);
30
33
  const isMounted = useIsMounted();
31
34
 
32
35
  const handleDragStart = (panelElement, startEvent) => {
33
- var _panelElement$getBoun;
34
-
36
+ if (!panelElement) return;
35
37
  if (startEvent.button !== 0) return; // Only allow left click for drag
36
38
 
39
+ const isVertical = isVerticalSide(panelPosition);
37
40
  setIsResizing(true);
38
- const dragInfo = {
39
- originalHeight: (_panelElement$getBoun = panelElement == null ? void 0 : panelElement.getBoundingClientRect().height) != null ? _panelElement$getBoun : 0,
40
- pageY: startEvent.pageY
41
- };
41
+ const {
42
+ height,
43
+ width
44
+ } = panelElement.getBoundingClientRect();
45
+ const startX = startEvent.clientX;
46
+ const startY = startEvent.clientY;
47
+ let newSize = 0;
42
48
 
43
49
  const run = moveEvent => {
44
- const delta = dragInfo.pageY - moveEvent.pageY;
45
- const newHeight = dragInfo.originalHeight + delta;
46
- setDevtoolsHeight(newHeight);
50
+ // prevent mouse selecting stuff with mouse drag
51
+ moveEvent.preventDefault(); // calculate the correct size based on mouse position and current panel position
52
+ // hint: it is different formula for the opposite sides
53
+
54
+ if (isVertical) {
55
+ newSize = width + (panelPosition === 'right' ? startX - moveEvent.clientX : moveEvent.clientX - startX);
56
+ setDevtoolsWidth(newSize);
57
+ } else {
58
+ newSize = height + (panelPosition === 'bottom' ? startY - moveEvent.clientY : moveEvent.clientY - startY);
59
+ setDevtoolsHeight(newSize);
60
+ }
47
61
 
48
- if (newHeight < 70) {
62
+ if (newSize < minPanelSize) {
49
63
  setIsOpen(false);
50
64
  } else {
51
65
  setIsOpen(true);
@@ -53,13 +67,16 @@ function ReactQueryDevtools({
53
67
  };
54
68
 
55
69
  const unsub = () => {
56
- setIsResizing(false);
57
- document.removeEventListener('mousemove', run);
58
- document.removeEventListener('mouseUp', unsub);
70
+ if (isResizing) {
71
+ setIsResizing(false);
72
+ }
73
+
74
+ document.removeEventListener('mousemove', run, false);
75
+ document.removeEventListener('mouseUp', unsub, false);
59
76
  };
60
77
 
61
- document.addEventListener('mousemove', run);
62
- document.addEventListener('mouseup', unsub);
78
+ document.addEventListener('mousemove', run, false);
79
+ document.addEventListener('mouseup', unsub, false);
63
80
  };
64
81
 
65
82
  React.useEffect(() => {
@@ -96,15 +113,20 @@ function ReactQueryDevtools({
96
113
  var _root$parentElement;
97
114
 
98
115
  const root = rootRef.current;
99
- const previousValue = root == null ? void 0 : (_root$parentElement = root.parentElement) == null ? void 0 : _root$parentElement.style.paddingBottom;
116
+ const styleProp = getSidedProp('padding', panelPosition);
117
+ const isVertical = isVerticalSide(panelPosition);
118
+ const previousValue = root == null ? void 0 : (_root$parentElement = root.parentElement) == null ? void 0 : _root$parentElement.style[styleProp];
100
119
 
101
120
  const run = () => {
102
- var _panelRef$current;
103
-
104
- const containerHeight = (_panelRef$current = panelRef.current) == null ? void 0 : _panelRef$current.getBoundingClientRect().height;
105
-
106
121
  if (root != null && root.parentElement) {
107
- root.parentElement.style.paddingBottom = containerHeight + "px";
122
+ // reset the padding
123
+ root.parentElement.style.padding = '0px';
124
+ root.parentElement.style.paddingTop = '0px';
125
+ root.parentElement.style.paddingBottom = '0px';
126
+ root.parentElement.style.paddingLeft = '0px';
127
+ root.parentElement.style.paddingRight = '0px'; // set the new padding based on the new panel position
128
+
129
+ root.parentElement.style[styleProp] = (isVertical ? devtoolsWidth : devtoolsHeight) + "px";
108
130
  }
109
131
  };
110
132
 
@@ -116,26 +138,31 @@ function ReactQueryDevtools({
116
138
  window.removeEventListener('resize', run);
117
139
 
118
140
  if (root != null && root.parentElement && typeof previousValue === 'string') {
119
- root.parentElement.style.paddingBottom = previousValue;
141
+ root.parentElement.style[styleProp] = previousValue;
120
142
  }
121
143
  };
122
144
  }
123
145
  }
124
- }, [isResolvedOpen]);
146
+ }, [isResolvedOpen, panelPosition, devtoolsHeight, devtoolsWidth]);
125
147
  const {
126
148
  style: panelStyle = {},
127
149
  ...otherPanelProps
128
150
  } = panelProps;
129
- const {
130
- style: closeButtonStyle = {},
131
- onClick: onCloseClick,
132
- ...otherCloseButtonProps
133
- } = closeButtonProps;
134
151
  const {
135
152
  style: toggleButtonStyle = {},
136
153
  onClick: onToggleClick,
137
154
  ...otherToggleButtonProps
138
- } = toggleButtonProps; // Do not render on the server
155
+ } = toggleButtonProps; // get computed style based on panel position
156
+
157
+ const style = getSidePanelStyle({
158
+ position: panelPosition,
159
+ devtoolsTheme: defaultTheme,
160
+ isOpen: isResolvedOpen,
161
+ height: devtoolsHeight,
162
+ width: devtoolsWidth,
163
+ isResizing,
164
+ panelStyle
165
+ }); // Do not render on the server
139
166
 
140
167
  if (!isMounted()) return null;
141
168
  return /*#__PURE__*/React.createElement(Container, {
@@ -147,68 +174,17 @@ function ReactQueryDevtools({
147
174
  }, /*#__PURE__*/React.createElement(ReactQueryDevtoolsPanel, _extends({
148
175
  ref: panelRef,
149
176
  context: context,
150
- styleNonce: styleNonce
177
+ styleNonce: styleNonce,
178
+ position: panelPosition,
179
+ onPositionChange: setPanelPosition,
180
+ showCloseButton: true,
181
+ closeButtonProps: closeButtonProps
151
182
  }, otherPanelProps, {
152
- style: {
153
- direction: 'ltr',
154
- position: 'fixed',
155
- bottom: '0',
156
- right: '0',
157
- zIndex: 99999,
158
- width: '100%',
159
- height: devtoolsHeight != null ? devtoolsHeight : 500,
160
- maxHeight: '90%',
161
- boxShadow: '0 0 20px rgba(0,0,0,.3)',
162
- borderTop: "1px solid " + defaultTheme.gray,
163
- transformOrigin: 'top',
164
- // visibility will be toggled after transitions, but set initial state here
165
- visibility: isOpen ? 'visible' : 'hidden',
166
- ...panelStyle,
167
- ...(isResizing ? {
168
- transition: "none"
169
- } : {
170
- transition: "all .2s ease"
171
- }),
172
- ...(isResolvedOpen ? {
173
- opacity: 1,
174
- pointerEvents: 'all',
175
- transform: "translateY(0) scale(1)"
176
- } : {
177
- opacity: 0,
178
- pointerEvents: 'none',
179
- transform: "translateY(15px) scale(1.02)"
180
- })
181
- },
183
+ style: style,
182
184
  isOpen: isResolvedOpen,
183
185
  setIsOpen: setIsOpen,
184
- handleDragStart: e => handleDragStart(panelRef.current, e)
185
- })), isResolvedOpen ? /*#__PURE__*/React.createElement(Button, _extends({
186
- type: "button",
187
- "aria-controls": "ReactQueryDevtoolsPanel",
188
- "aria-haspopup": "true",
189
- "aria-expanded": "true"
190
- }, otherCloseButtonProps, {
191
- onClick: e => {
192
- setIsOpen(false);
193
- onCloseClick == null ? void 0 : onCloseClick(e);
194
- },
195
- style: {
196
- position: 'fixed',
197
- zIndex: 99999,
198
- margin: '.5em',
199
- bottom: 0,
200
- ...(position === 'top-right' ? {
201
- right: '0'
202
- } : position === 'top-left' ? {
203
- left: '0'
204
- } : position === 'bottom-right' ? {
205
- right: '0'
206
- } : {
207
- left: '0'
208
- }),
209
- ...closeButtonStyle
210
- }
211
- }), "Close") : null), !isResolvedOpen ? /*#__PURE__*/React.createElement("button", _extends({
186
+ onDragStart: e => handleDragStart(panelRef.current, e)
187
+ }))), !isResolvedOpen ? /*#__PURE__*/React.createElement("button", _extends({
212
188
  type: "button"
213
189
  }, otherToggleButtonProps, {
214
190
  "aria-label": "Open React Query Devtools",
@@ -266,10 +242,18 @@ const ReactQueryDevtoolsPanel = /*#__PURE__*/React.forwardRef(function ReactQuer
266
242
  isOpen = true,
267
243
  styleNonce,
268
244
  setIsOpen,
269
- handleDragStart,
270
245
  context,
246
+ onDragStart,
247
+ onPositionChange,
248
+ showCloseButton,
249
+ position,
250
+ closeButtonProps = {},
271
251
  ...panelProps
272
252
  } = props;
253
+ const {
254
+ onClick: onCloseClick,
255
+ ...otherCloseButtonProps
256
+ } = closeButtonProps;
273
257
  const queryClient = useQueryClient({
274
258
  context
275
259
  });
@@ -299,23 +283,20 @@ const ReactQueryDevtoolsPanel = /*#__PURE__*/React.forwardRef(function ReactQuer
299
283
  className: "ReactQueryDevtoolsPanel",
300
284
  "aria-label": "React Query Devtools Panel",
301
285
  id: "ReactQueryDevtoolsPanel"
302
- }, panelProps), /*#__PURE__*/React.createElement("style", {
286
+ }, panelProps, {
287
+ style: {
288
+ height: defaultPanelSize,
289
+ position: 'relative',
290
+ ...panelProps.style
291
+ }
292
+ }), /*#__PURE__*/React.createElement("style", {
303
293
  nonce: styleNonce,
304
294
  dangerouslySetInnerHTML: {
305
295
  __html: "\n .ReactQueryDevtoolsPanel * {\n scrollbar-color: " + defaultTheme.backgroundAlt + " " + defaultTheme.gray + ";\n }\n\n .ReactQueryDevtoolsPanel *::-webkit-scrollbar, .ReactQueryDevtoolsPanel scrollbar {\n width: 1em;\n height: 1em;\n }\n\n .ReactQueryDevtoolsPanel *::-webkit-scrollbar-track, .ReactQueryDevtoolsPanel scrollbar-track {\n background: " + defaultTheme.backgroundAlt + ";\n }\n\n .ReactQueryDevtoolsPanel *::-webkit-scrollbar-thumb, .ReactQueryDevtoolsPanel scrollbar-thumb {\n background: " + defaultTheme.gray + ";\n border-radius: .5em;\n border: 3px solid " + defaultTheme.backgroundAlt + ";\n }\n "
306
296
  }
307
297
  }), /*#__PURE__*/React.createElement("div", {
308
- style: {
309
- position: 'absolute',
310
- left: 0,
311
- top: 0,
312
- width: '100%',
313
- height: '4px',
314
- marginBottom: '-4px',
315
- cursor: 'row-resize',
316
- zIndex: 100000
317
- },
318
- onMouseDown: handleDragStart
298
+ style: getResizeHandleStyle(position),
299
+ onMouseDown: onDragStart
319
300
  }), isOpen && /*#__PURE__*/React.createElement("div", {
320
301
  style: {
321
302
  flex: '1 1 500px',
@@ -358,9 +339,31 @@ const ReactQueryDevtoolsPanel = /*#__PURE__*/React.forwardRef(function ReactQuer
358
339
  display: 'flex',
359
340
  flexDirection: 'column'
360
341
  }
342
+ }, /*#__PURE__*/React.createElement("div", {
343
+ style: {
344
+ display: 'flex',
345
+ justifyContent: 'space-between',
346
+ alignItems: 'center',
347
+ marginBottom: '.5em'
348
+ }
361
349
  }, /*#__PURE__*/React.createElement(QueryStatusCount, {
362
350
  queryCache: queryCache
363
- }), /*#__PURE__*/React.createElement("div", {
351
+ }), position && onPositionChange ? /*#__PURE__*/React.createElement(Select, {
352
+ "aria-label": "Panel position",
353
+ value: position,
354
+ style: {
355
+ marginInlineStart: '.5em'
356
+ },
357
+ onChange: e => onPositionChange(e.target.value)
358
+ }, /*#__PURE__*/React.createElement("option", {
359
+ value: "left"
360
+ }, "Left"), /*#__PURE__*/React.createElement("option", {
361
+ value: "right"
362
+ }, "Right"), /*#__PURE__*/React.createElement("option", {
363
+ value: "top"
364
+ }, "Top"), /*#__PURE__*/React.createElement("option", {
365
+ value: "bottom"
366
+ }, "Bottom")) : null), /*#__PURE__*/React.createElement("div", {
364
367
  style: {
365
368
  display: 'flex',
366
369
  alignItems: 'center'
@@ -476,7 +479,25 @@ const ReactQueryDevtoolsPanel = /*#__PURE__*/React.forwardRef(function ReactQuer
476
479
  activeQueryHash: activeQueryHash,
477
480
  queryCache: queryCache,
478
481
  queryClient: queryClient
479
- }) : null));
482
+ }) : null, showCloseButton ? /*#__PURE__*/React.createElement(Button, _extends({
483
+ type: "button",
484
+ "aria-controls": "ReactQueryDevtoolsPanel",
485
+ "aria-haspopup": "true",
486
+ "aria-expanded": "true"
487
+ }, otherCloseButtonProps, {
488
+ style: {
489
+ position: 'absolute',
490
+ zIndex: 99999,
491
+ margin: '.5em',
492
+ bottom: 0,
493
+ left: 0,
494
+ ...otherCloseButtonProps.style
495
+ },
496
+ onClick: e => {
497
+ setIsOpen(false);
498
+ onCloseClick == null ? void 0 : onCloseClick(e);
499
+ }
500
+ }), "Close") : null));
480
501
  });
481
502
 
482
503
  const ActiveQuery = ({
@@ -651,11 +672,7 @@ const QueryStatusCount = ({
651
672
  const hasPaused = useSubscribeToQueryCache(queryCache, () => queryCache.getAll().filter(q => getQueryStatusLabel(q) === 'paused').length);
652
673
  const hasStale = useSubscribeToQueryCache(queryCache, () => queryCache.getAll().filter(q => getQueryStatusLabel(q) === 'stale').length);
653
674
  const hasInactive = useSubscribeToQueryCache(queryCache, () => queryCache.getAll().filter(q => getQueryStatusLabel(q) === 'inactive').length);
654
- return /*#__PURE__*/React.createElement(QueryKeys, {
655
- style: {
656
- marginBottom: '.5em'
657
- }
658
- }, /*#__PURE__*/React.createElement(QueryKey, {
675
+ return /*#__PURE__*/React.createElement(QueryKeys, null, /*#__PURE__*/React.createElement(QueryKey, {
659
676
  style: {
660
677
  background: defaultTheme.success,
661
678
  opacity: hasFresh ? 1 : 0.3