@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.
@@ -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,68 +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
- direction: 'ltr',
623
- position: 'fixed',
624
- bottom: '0',
625
- right: '0',
626
- zIndex: 99999,
627
- width: '100%',
628
- height: devtoolsHeight != null ? devtoolsHeight : 500,
629
- maxHeight: '90%',
630
- boxShadow: '0 0 20px rgba(0,0,0,.3)',
631
- borderTop: "1px solid " + defaultTheme.gray,
632
- transformOrigin: 'top',
633
- // visibility will be toggled after transitions, but set initial state here
634
- visibility: isOpen ? 'visible' : 'hidden',
635
- ...panelStyle,
636
- ...(isResizing ? {
637
- transition: "none"
638
- } : {
639
- transition: "all .2s ease"
640
- }),
641
- ...(isResolvedOpen ? {
642
- opacity: 1,
643
- pointerEvents: 'all',
644
- transform: "translateY(0) scale(1)"
645
- } : {
646
- opacity: 0,
647
- pointerEvents: 'none',
648
- transform: "translateY(15px) scale(1.02)"
649
- })
650
- },
755
+ style: style,
651
756
  isOpen: isResolvedOpen,
652
757
  setIsOpen: setIsOpen,
653
- handleDragStart: e => handleDragStart(panelRef.current, e)
654
- })), isResolvedOpen ? /*#__PURE__*/React.createElement(Button, _extends({
655
- type: "button",
656
- "aria-controls": "ReactQueryDevtoolsPanel",
657
- "aria-haspopup": "true",
658
- "aria-expanded": "true"
659
- }, otherCloseButtonProps, {
660
- onClick: e => {
661
- setIsOpen(false);
662
- onCloseClick == null ? void 0 : onCloseClick(e);
663
- },
664
- style: {
665
- position: 'fixed',
666
- zIndex: 99999,
667
- margin: '.5em',
668
- bottom: 0,
669
- ...(position === 'top-right' ? {
670
- right: '0'
671
- } : position === 'top-left' ? {
672
- left: '0'
673
- } : position === 'bottom-right' ? {
674
- right: '0'
675
- } : {
676
- left: '0'
677
- }),
678
- ...closeButtonStyle
679
- }
680
- }), "Close") : null), !isResolvedOpen ? /*#__PURE__*/React.createElement("button", _extends({
758
+ onDragStart: e => handleDragStart(panelRef.current, e)
759
+ }))), !isResolvedOpen ? /*#__PURE__*/React.createElement("button", _extends({
681
760
  type: "button"
682
761
  }, otherToggleButtonProps, {
683
762
  "aria-label": "Open React Query Devtools",
@@ -735,10 +814,18 @@ const ReactQueryDevtoolsPanel$1 = /*#__PURE__*/React.forwardRef(function ReactQu
735
814
  isOpen = true,
736
815
  styleNonce,
737
816
  setIsOpen,
738
- handleDragStart,
739
817
  context,
818
+ onDragStart,
819
+ onPositionChange,
820
+ showCloseButton,
821
+ position,
822
+ closeButtonProps = {},
740
823
  ...panelProps
741
824
  } = props;
825
+ const {
826
+ onClick: onCloseClick,
827
+ ...otherCloseButtonProps
828
+ } = closeButtonProps;
742
829
  const queryClient = useQueryClient({
743
830
  context
744
831
  });
@@ -768,23 +855,20 @@ const ReactQueryDevtoolsPanel$1 = /*#__PURE__*/React.forwardRef(function ReactQu
768
855
  className: "ReactQueryDevtoolsPanel",
769
856
  "aria-label": "React Query Devtools Panel",
770
857
  id: "ReactQueryDevtoolsPanel"
771
- }, panelProps), /*#__PURE__*/React.createElement("style", {
858
+ }, panelProps, {
859
+ style: {
860
+ height: defaultPanelSize,
861
+ position: 'relative',
862
+ ...panelProps.style
863
+ }
864
+ }), /*#__PURE__*/React.createElement("style", {
772
865
  nonce: styleNonce,
773
866
  dangerouslySetInnerHTML: {
774
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 "
775
868
  }
776
869
  }), /*#__PURE__*/React.createElement("div", {
777
- style: {
778
- position: 'absolute',
779
- left: 0,
780
- top: 0,
781
- width: '100%',
782
- height: '4px',
783
- marginBottom: '-4px',
784
- cursor: 'row-resize',
785
- zIndex: 100000
786
- },
787
- onMouseDown: handleDragStart
870
+ style: getResizeHandleStyle(position),
871
+ onMouseDown: onDragStart
788
872
  }), isOpen && /*#__PURE__*/React.createElement("div", {
789
873
  style: {
790
874
  flex: '1 1 500px',
@@ -827,9 +911,31 @@ const ReactQueryDevtoolsPanel$1 = /*#__PURE__*/React.forwardRef(function ReactQu
827
911
  display: 'flex',
828
912
  flexDirection: 'column'
829
913
  }
914
+ }, /*#__PURE__*/React.createElement("div", {
915
+ style: {
916
+ display: 'flex',
917
+ justifyContent: 'space-between',
918
+ alignItems: 'center',
919
+ marginBottom: '.5em'
920
+ }
830
921
  }, /*#__PURE__*/React.createElement(QueryStatusCount, {
831
922
  queryCache: queryCache
832
- }), /*#__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", {
833
939
  style: {
834
940
  display: 'flex',
835
941
  alignItems: 'center'
@@ -945,7 +1051,25 @@ const ReactQueryDevtoolsPanel$1 = /*#__PURE__*/React.forwardRef(function ReactQu
945
1051
  activeQueryHash: activeQueryHash,
946
1052
  queryCache: queryCache,
947
1053
  queryClient: queryClient
948
- }) : 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));
949
1073
  });
950
1074
 
951
1075
  const ActiveQuery = ({
@@ -1120,11 +1244,7 @@ const QueryStatusCount = ({
1120
1244
  const hasPaused = useSubscribeToQueryCache(queryCache, () => queryCache.getAll().filter(q => getQueryStatusLabel(q) === 'paused').length);
1121
1245
  const hasStale = useSubscribeToQueryCache(queryCache, () => queryCache.getAll().filter(q => getQueryStatusLabel(q) === 'stale').length);
1122
1246
  const hasInactive = useSubscribeToQueryCache(queryCache, () => queryCache.getAll().filter(q => getQueryStatusLabel(q) === 'inactive').length);
1123
- return /*#__PURE__*/React.createElement(QueryKeys, {
1124
- style: {
1125
- marginBottom: '.5em'
1126
- }
1127
- }, /*#__PURE__*/React.createElement(QueryKey, {
1247
+ return /*#__PURE__*/React.createElement(QueryKeys, null, /*#__PURE__*/React.createElement(QueryKey, {
1128
1248
  style: {
1129
1249
  background: defaultTheme.success,
1130
1250
  opacity: hasFresh ? 1 : 0.3