@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.
@@ -193,18 +193,108 @@ const sortFns = {
193
193
  'Query Hash': queryHashSort,
194
194
  'Last Updated': dateSort
195
195
  };
196
+ const minPanelSize = 70;
197
+ const defaultPanelSize = 500;
198
+ const sides = {
199
+ top: 'bottom',
200
+ bottom: 'top',
201
+ left: 'right',
202
+ right: 'left'
203
+ };
196
204
 
197
- function ScreenReader({
198
- text
205
+ /**
206
+ * Check if the given side is vertical (left/right)
207
+ */
208
+ function isVerticalSide(side) {
209
+ return ['left', 'right'].includes(side);
210
+ }
211
+ /**
212
+ * Get the opposite side, eg 'left' => 'right'. 'top' => 'bottom', etc
213
+ */
214
+
215
+ function getOppositeSide(side) {
216
+ return sides[side];
217
+ }
218
+ /**
219
+ * Given as css prop it will return a sided css prop based on a given side
220
+ * Example given `border` and `right` it return `borderRight`
221
+ */
222
+
223
+ function getSidedProp(prop, side) {
224
+ return "" + prop + (side.charAt(0).toUpperCase() + side.slice(1));
225
+ }
226
+ function getSidePanelStyle({
227
+ position = 'bottom',
228
+ height,
229
+ width,
230
+ devtoolsTheme,
231
+ isOpen,
232
+ isResizing,
233
+ panelStyle
199
234
  }) {
200
- return /*#__PURE__*/React.createElement("span", {
201
- style: {
202
- position: 'absolute',
203
- width: '0.1px',
204
- height: '0.1px',
205
- overflow: 'hidden'
206
- }
207
- }, text);
235
+ const oppositeSide = getOppositeSide(position);
236
+ const borderSide = getSidedProp('border', oppositeSide);
237
+ const isVertical = isVerticalSide(position);
238
+ return { ...panelStyle,
239
+ direction: 'ltr',
240
+ position: 'fixed',
241
+ [position]: 0,
242
+ [borderSide]: "1px solid " + devtoolsTheme.gray,
243
+ transformOrigin: oppositeSide,
244
+ boxShadow: '0 0 20px rgba(0,0,0,.3)',
245
+ zIndex: 99999,
246
+ // visibility will be toggled after transitions, but set initial state here
247
+ visibility: isOpen ? 'visible' : 'hidden',
248
+ ...(isResizing ? {
249
+ transition: "none"
250
+ } : {
251
+ transition: "all .2s ease"
252
+ }),
253
+ ...(isOpen ? {
254
+ opacity: 1,
255
+ pointerEvents: 'all',
256
+ transform: isVertical ? "translateX(0) scale(1)" : "translateY(0) scale(1)"
257
+ } : {
258
+ opacity: 0,
259
+ pointerEvents: 'none',
260
+ transform: isVertical ? "translateX(15px) scale(1.02)" : "translateY(15px) scale(1.02)"
261
+ }),
262
+ ...(isVertical ? {
263
+ top: 0,
264
+ height: '100vh',
265
+ maxWidth: '90%',
266
+ width: typeof width === 'number' && width >= minPanelSize ? width : defaultPanelSize
267
+ } : {
268
+ left: 0,
269
+ width: '100%',
270
+ maxHeight: '90%',
271
+ height: typeof height === 'number' && height >= minPanelSize ? height : defaultPanelSize
272
+ })
273
+ };
274
+ }
275
+ /**
276
+ * Get resize handle style based on a given side
277
+ */
278
+
279
+ function getResizeHandleStyle(position = 'bottom') {
280
+ const isVertical = isVerticalSide(position);
281
+ const oppositeSide = getOppositeSide(position);
282
+ const marginSide = getSidedProp('margin', oppositeSide);
283
+ return {
284
+ position: 'absolute',
285
+ cursor: isVertical ? 'col-resize' : 'row-resize',
286
+ zIndex: 100000,
287
+ [oppositeSide]: 0,
288
+ [marginSide]: "-4px",
289
+ ...(isVertical ? {
290
+ top: 0,
291
+ height: '100%',
292
+ width: '4px'
293
+ } : {
294
+ width: '100%',
295
+ height: '4px'
296
+ })
297
+ };
208
298
  }
209
299
 
210
300
  const Panel = styled('div', (_props, theme) => ({
@@ -295,6 +385,19 @@ const Select = styled('select', (_props, theme) => ({
295
385
  }
296
386
  });
297
387
 
388
+ function ScreenReader({
389
+ text
390
+ }) {
391
+ return /*#__PURE__*/React.createElement("span", {
392
+ style: {
393
+ position: 'absolute',
394
+ width: '0.1px',
395
+ height: '0.1px',
396
+ overflow: 'hidden'
397
+ }
398
+ }, text);
399
+ }
400
+
298
401
  const Entry = styled('div', {
299
402
  fontFamily: 'Menlo, monospace',
300
403
  fontSize: '1em',
@@ -488,33 +591,47 @@ function ReactQueryDevtools$1({
488
591
  position = 'bottom-left',
489
592
  containerElement: Container = 'aside',
490
593
  context,
491
- styleNonce
594
+ styleNonce,
595
+ panelPosition: initialPanelPosition = 'bottom'
492
596
  }) {
493
597
  const rootRef = React.useRef(null);
494
598
  const panelRef = React.useRef(null);
495
599
  const [isOpen, setIsOpen] = useLocalStorage('reactQueryDevtoolsOpen', initialIsOpen);
496
- const [devtoolsHeight, setDevtoolsHeight] = useLocalStorage('reactQueryDevtoolsHeight', null);
600
+ const [devtoolsHeight, setDevtoolsHeight] = useLocalStorage('reactQueryDevtoolsHeight', defaultPanelSize);
601
+ const [devtoolsWidth, setDevtoolsWidth] = useLocalStorage('reactQueryDevtoolsWidth', defaultPanelSize);
602
+ const [panelPosition = 'bottom', setPanelPosition] = useLocalStorage('reactQueryDevtoolsPanelPosition', initialPanelPosition);
497
603
  const [isResolvedOpen, setIsResolvedOpen] = React.useState(false);
498
604
  const [isResizing, setIsResizing] = React.useState(false);
499
605
  const isMounted = useIsMounted();
500
606
 
501
607
  const handleDragStart = (panelElement, startEvent) => {
502
- var _panelElement$getBoun;
503
-
608
+ if (!panelElement) return;
504
609
  if (startEvent.button !== 0) return; // Only allow left click for drag
505
610
 
611
+ const isVertical = isVerticalSide(panelPosition);
506
612
  setIsResizing(true);
507
- const dragInfo = {
508
- originalHeight: (_panelElement$getBoun = panelElement == null ? void 0 : panelElement.getBoundingClientRect().height) != null ? _panelElement$getBoun : 0,
509
- pageY: startEvent.pageY
510
- };
613
+ const {
614
+ height,
615
+ width
616
+ } = panelElement.getBoundingClientRect();
617
+ const startX = startEvent.clientX;
618
+ const startY = startEvent.clientY;
619
+ let newSize = 0;
511
620
 
512
621
  const run = moveEvent => {
513
- const delta = dragInfo.pageY - moveEvent.pageY;
514
- const newHeight = dragInfo.originalHeight + delta;
515
- setDevtoolsHeight(newHeight);
622
+ // prevent mouse selecting stuff with mouse drag
623
+ moveEvent.preventDefault(); // calculate the correct size based on mouse position and current panel position
624
+ // hint: it is different formula for the opposite sides
625
+
626
+ if (isVertical) {
627
+ newSize = width + (panelPosition === 'right' ? startX - moveEvent.clientX : moveEvent.clientX - startX);
628
+ setDevtoolsWidth(newSize);
629
+ } else {
630
+ newSize = height + (panelPosition === 'bottom' ? startY - moveEvent.clientY : moveEvent.clientY - startY);
631
+ setDevtoolsHeight(newSize);
632
+ }
516
633
 
517
- if (newHeight < 70) {
634
+ if (newSize < minPanelSize) {
518
635
  setIsOpen(false);
519
636
  } else {
520
637
  setIsOpen(true);
@@ -522,13 +639,16 @@ function ReactQueryDevtools$1({
522
639
  };
523
640
 
524
641
  const unsub = () => {
525
- setIsResizing(false);
526
- document.removeEventListener('mousemove', run);
527
- document.removeEventListener('mouseUp', unsub);
642
+ if (isResizing) {
643
+ setIsResizing(false);
644
+ }
645
+
646
+ document.removeEventListener('mousemove', run, false);
647
+ document.removeEventListener('mouseUp', unsub, false);
528
648
  };
529
649
 
530
- document.addEventListener('mousemove', run);
531
- document.addEventListener('mouseup', unsub);
650
+ document.addEventListener('mousemove', run, false);
651
+ document.addEventListener('mouseup', unsub, false);
532
652
  };
533
653
 
534
654
  React.useEffect(() => {
@@ -565,15 +685,20 @@ function ReactQueryDevtools$1({
565
685
  var _root$parentElement;
566
686
 
567
687
  const root = rootRef.current;
568
- const previousValue = root == null ? void 0 : (_root$parentElement = root.parentElement) == null ? void 0 : _root$parentElement.style.paddingBottom;
688
+ const styleProp = getSidedProp('padding', panelPosition);
689
+ const isVertical = isVerticalSide(panelPosition);
690
+ const previousValue = root == null ? void 0 : (_root$parentElement = root.parentElement) == null ? void 0 : _root$parentElement.style[styleProp];
569
691
 
570
692
  const run = () => {
571
- var _panelRef$current;
572
-
573
- const containerHeight = (_panelRef$current = panelRef.current) == null ? void 0 : _panelRef$current.getBoundingClientRect().height;
574
-
575
693
  if (root != null && root.parentElement) {
576
- root.parentElement.style.paddingBottom = containerHeight + "px";
694
+ // reset the padding
695
+ root.parentElement.style.padding = '0px';
696
+ root.parentElement.style.paddingTop = '0px';
697
+ root.parentElement.style.paddingBottom = '0px';
698
+ root.parentElement.style.paddingLeft = '0px';
699
+ root.parentElement.style.paddingRight = '0px'; // set the new padding based on the new panel position
700
+
701
+ root.parentElement.style[styleProp] = (isVertical ? devtoolsWidth : devtoolsHeight) + "px";
577
702
  }
578
703
  };
579
704
 
@@ -585,26 +710,31 @@ function ReactQueryDevtools$1({
585
710
  window.removeEventListener('resize', run);
586
711
 
587
712
  if (root != null && root.parentElement && typeof previousValue === 'string') {
588
- root.parentElement.style.paddingBottom = previousValue;
713
+ root.parentElement.style[styleProp] = previousValue;
589
714
  }
590
715
  };
591
716
  }
592
717
  }
593
- }, [isResolvedOpen]);
718
+ }, [isResolvedOpen, panelPosition, devtoolsHeight, devtoolsWidth]);
594
719
  const {
595
720
  style: panelStyle = {},
596
721
  ...otherPanelProps
597
722
  } = panelProps;
598
- const {
599
- style: closeButtonStyle = {},
600
- onClick: onCloseClick,
601
- ...otherCloseButtonProps
602
- } = closeButtonProps;
603
723
  const {
604
724
  style: toggleButtonStyle = {},
605
725
  onClick: onToggleClick,
606
726
  ...otherToggleButtonProps
607
- } = toggleButtonProps; // Do not render on the server
727
+ } = toggleButtonProps; // get computed style based on panel position
728
+
729
+ const style = getSidePanelStyle({
730
+ position: panelPosition,
731
+ devtoolsTheme: defaultTheme,
732
+ isOpen: isResolvedOpen,
733
+ height: devtoolsHeight,
734
+ width: devtoolsWidth,
735
+ isResizing,
736
+ panelStyle
737
+ }); // Do not render on the server
608
738
 
609
739
  if (!isMounted()) return null;
610
740
  return /*#__PURE__*/React.createElement(Container, {
@@ -616,67 +746,17 @@ function ReactQueryDevtools$1({
616
746
  }, /*#__PURE__*/React.createElement(ReactQueryDevtoolsPanel$1, _extends({
617
747
  ref: panelRef,
618
748
  context: context,
619
- styleNonce: styleNonce
749
+ styleNonce: styleNonce,
750
+ position: panelPosition,
751
+ onPositionChange: setPanelPosition,
752
+ showCloseButton: true,
753
+ closeButtonProps: closeButtonProps
620
754
  }, otherPanelProps, {
621
- style: {
622
- position: 'fixed',
623
- bottom: '0',
624
- right: '0',
625
- zIndex: 99999,
626
- width: '100%',
627
- height: devtoolsHeight != null ? devtoolsHeight : 500,
628
- maxHeight: '90%',
629
- boxShadow: '0 0 20px rgba(0,0,0,.3)',
630
- borderTop: "1px solid " + defaultTheme.gray,
631
- transformOrigin: 'top',
632
- // visibility will be toggled after transitions, but set initial state here
633
- visibility: isOpen ? 'visible' : 'hidden',
634
- ...panelStyle,
635
- ...(isResizing ? {
636
- transition: "none"
637
- } : {
638
- transition: "all .2s ease"
639
- }),
640
- ...(isResolvedOpen ? {
641
- opacity: 1,
642
- pointerEvents: 'all',
643
- transform: "translateY(0) scale(1)"
644
- } : {
645
- opacity: 0,
646
- pointerEvents: 'none',
647
- transform: "translateY(15px) scale(1.02)"
648
- })
649
- },
755
+ style: style,
650
756
  isOpen: isResolvedOpen,
651
757
  setIsOpen: setIsOpen,
652
- handleDragStart: e => handleDragStart(panelRef.current, e)
653
- })), isResolvedOpen ? /*#__PURE__*/React.createElement(Button, _extends({
654
- type: "button",
655
- "aria-controls": "ReactQueryDevtoolsPanel",
656
- "aria-haspopup": "true",
657
- "aria-expanded": "true"
658
- }, otherCloseButtonProps, {
659
- onClick: e => {
660
- setIsOpen(false);
661
- onCloseClick == null ? void 0 : onCloseClick(e);
662
- },
663
- style: {
664
- position: 'fixed',
665
- zIndex: 99999,
666
- margin: '.5em',
667
- bottom: 0,
668
- ...(position === 'top-right' ? {
669
- right: '0'
670
- } : position === 'top-left' ? {
671
- left: '0'
672
- } : position === 'bottom-right' ? {
673
- right: '0'
674
- } : {
675
- left: '0'
676
- }),
677
- ...closeButtonStyle
678
- }
679
- }), "Close") : null), !isResolvedOpen ? /*#__PURE__*/React.createElement("button", _extends({
758
+ onDragStart: e => handleDragStart(panelRef.current, e)
759
+ }))), !isResolvedOpen ? /*#__PURE__*/React.createElement("button", _extends({
680
760
  type: "button"
681
761
  }, otherToggleButtonProps, {
682
762
  "aria-label": "Open React Query Devtools",
@@ -734,10 +814,18 @@ const ReactQueryDevtoolsPanel$1 = /*#__PURE__*/React.forwardRef(function ReactQu
734
814
  isOpen = true,
735
815
  styleNonce,
736
816
  setIsOpen,
737
- handleDragStart,
738
817
  context,
818
+ onDragStart,
819
+ onPositionChange,
820
+ showCloseButton,
821
+ position,
822
+ closeButtonProps = {},
739
823
  ...panelProps
740
824
  } = props;
825
+ const {
826
+ onClick: onCloseClick,
827
+ ...otherCloseButtonProps
828
+ } = closeButtonProps;
741
829
  const queryClient = useQueryClient({
742
830
  context
743
831
  });
@@ -767,23 +855,20 @@ const ReactQueryDevtoolsPanel$1 = /*#__PURE__*/React.forwardRef(function ReactQu
767
855
  className: "ReactQueryDevtoolsPanel",
768
856
  "aria-label": "React Query Devtools Panel",
769
857
  id: "ReactQueryDevtoolsPanel"
770
- }, panelProps), /*#__PURE__*/React.createElement("style", {
858
+ }, panelProps, {
859
+ style: {
860
+ height: defaultPanelSize,
861
+ position: 'relative',
862
+ ...panelProps.style
863
+ }
864
+ }), /*#__PURE__*/React.createElement("style", {
771
865
  nonce: styleNonce,
772
866
  dangerouslySetInnerHTML: {
773
867
  __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 "
774
868
  }
775
869
  }), /*#__PURE__*/React.createElement("div", {
776
- style: {
777
- position: 'absolute',
778
- left: 0,
779
- top: 0,
780
- width: '100%',
781
- height: '4px',
782
- marginBottom: '-4px',
783
- cursor: 'row-resize',
784
- zIndex: 100000
785
- },
786
- onMouseDown: handleDragStart
870
+ style: getResizeHandleStyle(position),
871
+ onMouseDown: onDragStart
787
872
  }), isOpen && /*#__PURE__*/React.createElement("div", {
788
873
  style: {
789
874
  flex: '1 1 500px',
@@ -826,9 +911,31 @@ const ReactQueryDevtoolsPanel$1 = /*#__PURE__*/React.forwardRef(function ReactQu
826
911
  display: 'flex',
827
912
  flexDirection: 'column'
828
913
  }
914
+ }, /*#__PURE__*/React.createElement("div", {
915
+ style: {
916
+ display: 'flex',
917
+ justifyContent: 'space-between',
918
+ alignItems: 'center',
919
+ marginBottom: '.5em'
920
+ }
829
921
  }, /*#__PURE__*/React.createElement(QueryStatusCount, {
830
922
  queryCache: queryCache
831
- }), /*#__PURE__*/React.createElement("div", {
923
+ }), position && onPositionChange ? /*#__PURE__*/React.createElement(Select, {
924
+ "aria-label": "Panel position",
925
+ value: position,
926
+ style: {
927
+ marginInlineStart: '.5em'
928
+ },
929
+ onChange: e => onPositionChange(e.target.value)
930
+ }, /*#__PURE__*/React.createElement("option", {
931
+ value: "left"
932
+ }, "Left"), /*#__PURE__*/React.createElement("option", {
933
+ value: "right"
934
+ }, "Right"), /*#__PURE__*/React.createElement("option", {
935
+ value: "top"
936
+ }, "Top"), /*#__PURE__*/React.createElement("option", {
937
+ value: "bottom"
938
+ }, "Bottom")) : null), /*#__PURE__*/React.createElement("div", {
832
939
  style: {
833
940
  display: 'flex',
834
941
  alignItems: 'center'
@@ -944,7 +1051,25 @@ const ReactQueryDevtoolsPanel$1 = /*#__PURE__*/React.forwardRef(function ReactQu
944
1051
  activeQueryHash: activeQueryHash,
945
1052
  queryCache: queryCache,
946
1053
  queryClient: queryClient
947
- }) : null));
1054
+ }) : null, showCloseButton ? /*#__PURE__*/React.createElement(Button, _extends({
1055
+ type: "button",
1056
+ "aria-controls": "ReactQueryDevtoolsPanel",
1057
+ "aria-haspopup": "true",
1058
+ "aria-expanded": "true"
1059
+ }, otherCloseButtonProps, {
1060
+ style: {
1061
+ position: 'absolute',
1062
+ zIndex: 99999,
1063
+ margin: '.5em',
1064
+ bottom: 0,
1065
+ left: 0,
1066
+ ...otherCloseButtonProps.style
1067
+ },
1068
+ onClick: e => {
1069
+ setIsOpen(false);
1070
+ onCloseClick == null ? void 0 : onCloseClick(e);
1071
+ }
1072
+ }), "Close") : null));
948
1073
  });
949
1074
 
950
1075
  const ActiveQuery = ({
@@ -1119,11 +1244,7 @@ const QueryStatusCount = ({
1119
1244
  const hasPaused = useSubscribeToQueryCache(queryCache, () => queryCache.getAll().filter(q => getQueryStatusLabel(q) === 'paused').length);
1120
1245
  const hasStale = useSubscribeToQueryCache(queryCache, () => queryCache.getAll().filter(q => getQueryStatusLabel(q) === 'stale').length);
1121
1246
  const hasInactive = useSubscribeToQueryCache(queryCache, () => queryCache.getAll().filter(q => getQueryStatusLabel(q) === 'inactive').length);
1122
- return /*#__PURE__*/React.createElement(QueryKeys, {
1123
- style: {
1124
- marginBottom: '.5em'
1125
- }
1126
- }, /*#__PURE__*/React.createElement(QueryKey, {
1247
+ return /*#__PURE__*/React.createElement(QueryKeys, null, /*#__PURE__*/React.createElement(QueryKey, {
1127
1248
  style: {
1128
1249
  background: defaultTheme.success,
1129
1250
  opacity: hasFresh ? 1 : 0.3