@tanstack/react-query-devtools 4.10.3 → 4.11.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,67 +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
- position: 'fixed',
154
- bottom: '0',
155
- right: '0',
156
- zIndex: 99999,
157
- width: '100%',
158
- height: devtoolsHeight != null ? devtoolsHeight : 500,
159
- maxHeight: '90%',
160
- boxShadow: '0 0 20px rgba(0,0,0,.3)',
161
- borderTop: "1px solid " + defaultTheme.gray,
162
- transformOrigin: 'top',
163
- // visibility will be toggled after transitions, but set initial state here
164
- visibility: isOpen ? 'visible' : 'hidden',
165
- ...panelStyle,
166
- ...(isResizing ? {
167
- transition: "none"
168
- } : {
169
- transition: "all .2s ease"
170
- }),
171
- ...(isResolvedOpen ? {
172
- opacity: 1,
173
- pointerEvents: 'all',
174
- transform: "translateY(0) scale(1)"
175
- } : {
176
- opacity: 0,
177
- pointerEvents: 'none',
178
- transform: "translateY(15px) scale(1.02)"
179
- })
180
- },
183
+ style: style,
181
184
  isOpen: isResolvedOpen,
182
185
  setIsOpen: setIsOpen,
183
- handleDragStart: e => handleDragStart(panelRef.current, e)
184
- })), isResolvedOpen ? /*#__PURE__*/React.createElement(Button, _extends({
185
- type: "button",
186
- "aria-controls": "ReactQueryDevtoolsPanel",
187
- "aria-haspopup": "true",
188
- "aria-expanded": "true"
189
- }, otherCloseButtonProps, {
190
- onClick: e => {
191
- setIsOpen(false);
192
- onCloseClick == null ? void 0 : onCloseClick(e);
193
- },
194
- style: {
195
- position: 'fixed',
196
- zIndex: 99999,
197
- margin: '.5em',
198
- bottom: 0,
199
- ...(position === 'top-right' ? {
200
- right: '0'
201
- } : position === 'top-left' ? {
202
- left: '0'
203
- } : position === 'bottom-right' ? {
204
- right: '0'
205
- } : {
206
- left: '0'
207
- }),
208
- ...closeButtonStyle
209
- }
210
- }), "Close") : null), !isResolvedOpen ? /*#__PURE__*/React.createElement("button", _extends({
186
+ onDragStart: e => handleDragStart(panelRef.current, e)
187
+ }))), !isResolvedOpen ? /*#__PURE__*/React.createElement("button", _extends({
211
188
  type: "button"
212
189
  }, otherToggleButtonProps, {
213
190
  "aria-label": "Open React Query Devtools",
@@ -265,10 +242,18 @@ const ReactQueryDevtoolsPanel = /*#__PURE__*/React.forwardRef(function ReactQuer
265
242
  isOpen = true,
266
243
  styleNonce,
267
244
  setIsOpen,
268
- handleDragStart,
269
245
  context,
246
+ onDragStart,
247
+ onPositionChange,
248
+ showCloseButton,
249
+ position,
250
+ closeButtonProps = {},
270
251
  ...panelProps
271
252
  } = props;
253
+ const {
254
+ onClick: onCloseClick,
255
+ ...otherCloseButtonProps
256
+ } = closeButtonProps;
272
257
  const queryClient = useQueryClient({
273
258
  context
274
259
  });
@@ -298,23 +283,20 @@ const ReactQueryDevtoolsPanel = /*#__PURE__*/React.forwardRef(function ReactQuer
298
283
  className: "ReactQueryDevtoolsPanel",
299
284
  "aria-label": "React Query Devtools Panel",
300
285
  id: "ReactQueryDevtoolsPanel"
301
- }, panelProps), /*#__PURE__*/React.createElement("style", {
286
+ }, panelProps, {
287
+ style: {
288
+ height: defaultPanelSize,
289
+ position: 'relative',
290
+ ...panelProps.style
291
+ }
292
+ }), /*#__PURE__*/React.createElement("style", {
302
293
  nonce: styleNonce,
303
294
  dangerouslySetInnerHTML: {
304
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 "
305
296
  }
306
297
  }), /*#__PURE__*/React.createElement("div", {
307
- style: {
308
- position: 'absolute',
309
- left: 0,
310
- top: 0,
311
- width: '100%',
312
- height: '4px',
313
- marginBottom: '-4px',
314
- cursor: 'row-resize',
315
- zIndex: 100000
316
- },
317
- onMouseDown: handleDragStart
298
+ style: getResizeHandleStyle(position),
299
+ onMouseDown: onDragStart
318
300
  }), isOpen && /*#__PURE__*/React.createElement("div", {
319
301
  style: {
320
302
  flex: '1 1 500px',
@@ -357,9 +339,31 @@ const ReactQueryDevtoolsPanel = /*#__PURE__*/React.forwardRef(function ReactQuer
357
339
  display: 'flex',
358
340
  flexDirection: 'column'
359
341
  }
342
+ }, /*#__PURE__*/React.createElement("div", {
343
+ style: {
344
+ display: 'flex',
345
+ justifyContent: 'space-between',
346
+ alignItems: 'center',
347
+ marginBottom: '.5em'
348
+ }
360
349
  }, /*#__PURE__*/React.createElement(QueryStatusCount, {
361
350
  queryCache: queryCache
362
- }), /*#__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", {
363
367
  style: {
364
368
  display: 'flex',
365
369
  alignItems: 'center'
@@ -475,7 +479,25 @@ const ReactQueryDevtoolsPanel = /*#__PURE__*/React.forwardRef(function ReactQuer
475
479
  activeQueryHash: activeQueryHash,
476
480
  queryCache: queryCache,
477
481
  queryClient: queryClient
478
- }) : 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));
479
501
  });
480
502
 
481
503
  const ActiveQuery = ({
@@ -650,11 +672,7 @@ const QueryStatusCount = ({
650
672
  const hasPaused = useSubscribeToQueryCache(queryCache, () => queryCache.getAll().filter(q => getQueryStatusLabel(q) === 'paused').length);
651
673
  const hasStale = useSubscribeToQueryCache(queryCache, () => queryCache.getAll().filter(q => getQueryStatusLabel(q) === 'stale').length);
652
674
  const hasInactive = useSubscribeToQueryCache(queryCache, () => queryCache.getAll().filter(q => getQueryStatusLabel(q) === 'inactive').length);
653
- return /*#__PURE__*/React.createElement(QueryKeys, {
654
- style: {
655
- marginBottom: '.5em'
656
- }
657
- }, /*#__PURE__*/React.createElement(QueryKey, {
675
+ return /*#__PURE__*/React.createElement(QueryKeys, null, /*#__PURE__*/React.createElement(QueryKey, {
658
676
  style: {
659
677
  background: defaultTheme.success,
660
678
  opacity: hasFresh ? 1 : 0.3