@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.
@@ -220,18 +220,108 @@ const sortFns = {
220
220
  'Query Hash': queryHashSort,
221
221
  'Last Updated': dateSort
222
222
  };
223
+ const minPanelSize = 70;
224
+ const defaultPanelSize = 500;
225
+ const sides = {
226
+ top: 'bottom',
227
+ bottom: 'top',
228
+ left: 'right',
229
+ right: 'left'
230
+ };
223
231
 
224
- function ScreenReader({
225
- text
232
+ /**
233
+ * Check if the given side is vertical (left/right)
234
+ */
235
+ function isVerticalSide(side) {
236
+ return ['left', 'right'].includes(side);
237
+ }
238
+ /**
239
+ * Get the opposite side, eg 'left' => 'right'. 'top' => 'bottom', etc
240
+ */
241
+
242
+ function getOppositeSide(side) {
243
+ return sides[side];
244
+ }
245
+ /**
246
+ * Given as css prop it will return a sided css prop based on a given side
247
+ * Example given `border` and `right` it return `borderRight`
248
+ */
249
+
250
+ function getSidedProp(prop, side) {
251
+ return "" + prop + (side.charAt(0).toUpperCase() + side.slice(1));
252
+ }
253
+ function getSidePanelStyle({
254
+ position = 'bottom',
255
+ height,
256
+ width,
257
+ devtoolsTheme,
258
+ isOpen,
259
+ isResizing,
260
+ panelStyle
226
261
  }) {
227
- return /*#__PURE__*/React__namespace.createElement("span", {
228
- style: {
229
- position: 'absolute',
230
- width: '0.1px',
231
- height: '0.1px',
232
- overflow: 'hidden'
233
- }
234
- }, text);
262
+ const oppositeSide = getOppositeSide(position);
263
+ const borderSide = getSidedProp('border', oppositeSide);
264
+ const isVertical = isVerticalSide(position);
265
+ return { ...panelStyle,
266
+ direction: 'ltr',
267
+ position: 'fixed',
268
+ [position]: 0,
269
+ [borderSide]: "1px solid " + devtoolsTheme.gray,
270
+ transformOrigin: oppositeSide,
271
+ boxShadow: '0 0 20px rgba(0,0,0,.3)',
272
+ zIndex: 99999,
273
+ // visibility will be toggled after transitions, but set initial state here
274
+ visibility: isOpen ? 'visible' : 'hidden',
275
+ ...(isResizing ? {
276
+ transition: "none"
277
+ } : {
278
+ transition: "all .2s ease"
279
+ }),
280
+ ...(isOpen ? {
281
+ opacity: 1,
282
+ pointerEvents: 'all',
283
+ transform: isVertical ? "translateX(0) scale(1)" : "translateY(0) scale(1)"
284
+ } : {
285
+ opacity: 0,
286
+ pointerEvents: 'none',
287
+ transform: isVertical ? "translateX(15px) scale(1.02)" : "translateY(15px) scale(1.02)"
288
+ }),
289
+ ...(isVertical ? {
290
+ top: 0,
291
+ height: '100vh',
292
+ maxWidth: '90%',
293
+ width: typeof width === 'number' && width >= minPanelSize ? width : defaultPanelSize
294
+ } : {
295
+ left: 0,
296
+ width: '100%',
297
+ maxHeight: '90%',
298
+ height: typeof height === 'number' && height >= minPanelSize ? height : defaultPanelSize
299
+ })
300
+ };
301
+ }
302
+ /**
303
+ * Get resize handle style based on a given side
304
+ */
305
+
306
+ function getResizeHandleStyle(position = 'bottom') {
307
+ const isVertical = isVerticalSide(position);
308
+ const oppositeSide = getOppositeSide(position);
309
+ const marginSide = getSidedProp('margin', oppositeSide);
310
+ return {
311
+ position: 'absolute',
312
+ cursor: isVertical ? 'col-resize' : 'row-resize',
313
+ zIndex: 100000,
314
+ [oppositeSide]: 0,
315
+ [marginSide]: "-4px",
316
+ ...(isVertical ? {
317
+ top: 0,
318
+ height: '100%',
319
+ width: '4px'
320
+ } : {
321
+ width: '100%',
322
+ height: '4px'
323
+ })
324
+ };
235
325
  }
236
326
 
237
327
  const Panel = styled('div', (_props, theme) => ({
@@ -322,6 +412,19 @@ const Select = styled('select', (_props, theme) => ({
322
412
  }
323
413
  });
324
414
 
415
+ function ScreenReader({
416
+ text
417
+ }) {
418
+ return /*#__PURE__*/React__namespace.createElement("span", {
419
+ style: {
420
+ position: 'absolute',
421
+ width: '0.1px',
422
+ height: '0.1px',
423
+ overflow: 'hidden'
424
+ }
425
+ }, text);
426
+ }
427
+
325
428
  const Entry = styled('div', {
326
429
  fontFamily: 'Menlo, monospace',
327
430
  fontSize: '1em',
@@ -515,33 +618,47 @@ function ReactQueryDevtools$1({
515
618
  position = 'bottom-left',
516
619
  containerElement: Container = 'aside',
517
620
  context,
518
- styleNonce
621
+ styleNonce,
622
+ panelPosition: initialPanelPosition = 'bottom'
519
623
  }) {
520
624
  const rootRef = React__namespace.useRef(null);
521
625
  const panelRef = React__namespace.useRef(null);
522
626
  const [isOpen, setIsOpen] = useLocalStorage('reactQueryDevtoolsOpen', initialIsOpen);
523
- const [devtoolsHeight, setDevtoolsHeight] = useLocalStorage('reactQueryDevtoolsHeight', null);
627
+ const [devtoolsHeight, setDevtoolsHeight] = useLocalStorage('reactQueryDevtoolsHeight', defaultPanelSize);
628
+ const [devtoolsWidth, setDevtoolsWidth] = useLocalStorage('reactQueryDevtoolsWidth', defaultPanelSize);
629
+ const [panelPosition = 'bottom', setPanelPosition] = useLocalStorage('reactQueryDevtoolsPanelPosition', initialPanelPosition);
524
630
  const [isResolvedOpen, setIsResolvedOpen] = React__namespace.useState(false);
525
631
  const [isResizing, setIsResizing] = React__namespace.useState(false);
526
632
  const isMounted = useIsMounted();
527
633
 
528
634
  const handleDragStart = (panelElement, startEvent) => {
529
- var _panelElement$getBoun;
530
-
635
+ if (!panelElement) return;
531
636
  if (startEvent.button !== 0) return; // Only allow left click for drag
532
637
 
638
+ const isVertical = isVerticalSide(panelPosition);
533
639
  setIsResizing(true);
534
- const dragInfo = {
535
- originalHeight: (_panelElement$getBoun = panelElement == null ? void 0 : panelElement.getBoundingClientRect().height) != null ? _panelElement$getBoun : 0,
536
- pageY: startEvent.pageY
537
- };
640
+ const {
641
+ height,
642
+ width
643
+ } = panelElement.getBoundingClientRect();
644
+ const startX = startEvent.clientX;
645
+ const startY = startEvent.clientY;
646
+ let newSize = 0;
538
647
 
539
648
  const run = moveEvent => {
540
- const delta = dragInfo.pageY - moveEvent.pageY;
541
- const newHeight = dragInfo.originalHeight + delta;
542
- setDevtoolsHeight(newHeight);
649
+ // prevent mouse selecting stuff with mouse drag
650
+ moveEvent.preventDefault(); // calculate the correct size based on mouse position and current panel position
651
+ // hint: it is different formula for the opposite sides
652
+
653
+ if (isVertical) {
654
+ newSize = width + (panelPosition === 'right' ? startX - moveEvent.clientX : moveEvent.clientX - startX);
655
+ setDevtoolsWidth(newSize);
656
+ } else {
657
+ newSize = height + (panelPosition === 'bottom' ? startY - moveEvent.clientY : moveEvent.clientY - startY);
658
+ setDevtoolsHeight(newSize);
659
+ }
543
660
 
544
- if (newHeight < 70) {
661
+ if (newSize < minPanelSize) {
545
662
  setIsOpen(false);
546
663
  } else {
547
664
  setIsOpen(true);
@@ -549,13 +666,16 @@ function ReactQueryDevtools$1({
549
666
  };
550
667
 
551
668
  const unsub = () => {
552
- setIsResizing(false);
553
- document.removeEventListener('mousemove', run);
554
- document.removeEventListener('mouseUp', unsub);
669
+ if (isResizing) {
670
+ setIsResizing(false);
671
+ }
672
+
673
+ document.removeEventListener('mousemove', run, false);
674
+ document.removeEventListener('mouseUp', unsub, false);
555
675
  };
556
676
 
557
- document.addEventListener('mousemove', run);
558
- document.addEventListener('mouseup', unsub);
677
+ document.addEventListener('mousemove', run, false);
678
+ document.addEventListener('mouseup', unsub, false);
559
679
  };
560
680
 
561
681
  React__namespace.useEffect(() => {
@@ -592,15 +712,20 @@ function ReactQueryDevtools$1({
592
712
  var _root$parentElement;
593
713
 
594
714
  const root = rootRef.current;
595
- const previousValue = root == null ? void 0 : (_root$parentElement = root.parentElement) == null ? void 0 : _root$parentElement.style.paddingBottom;
715
+ const styleProp = getSidedProp('padding', panelPosition);
716
+ const isVertical = isVerticalSide(panelPosition);
717
+ const previousValue = root == null ? void 0 : (_root$parentElement = root.parentElement) == null ? void 0 : _root$parentElement.style[styleProp];
596
718
 
597
719
  const run = () => {
598
- var _panelRef$current;
599
-
600
- const containerHeight = (_panelRef$current = panelRef.current) == null ? void 0 : _panelRef$current.getBoundingClientRect().height;
601
-
602
720
  if (root != null && root.parentElement) {
603
- root.parentElement.style.paddingBottom = containerHeight + "px";
721
+ // reset the padding
722
+ root.parentElement.style.padding = '0px';
723
+ root.parentElement.style.paddingTop = '0px';
724
+ root.parentElement.style.paddingBottom = '0px';
725
+ root.parentElement.style.paddingLeft = '0px';
726
+ root.parentElement.style.paddingRight = '0px'; // set the new padding based on the new panel position
727
+
728
+ root.parentElement.style[styleProp] = (isVertical ? devtoolsWidth : devtoolsHeight) + "px";
604
729
  }
605
730
  };
606
731
 
@@ -612,26 +737,31 @@ function ReactQueryDevtools$1({
612
737
  window.removeEventListener('resize', run);
613
738
 
614
739
  if (root != null && root.parentElement && typeof previousValue === 'string') {
615
- root.parentElement.style.paddingBottom = previousValue;
740
+ root.parentElement.style[styleProp] = previousValue;
616
741
  }
617
742
  };
618
743
  }
619
744
  }
620
- }, [isResolvedOpen]);
745
+ }, [isResolvedOpen, panelPosition, devtoolsHeight, devtoolsWidth]);
621
746
  const {
622
747
  style: panelStyle = {},
623
748
  ...otherPanelProps
624
749
  } = panelProps;
625
- const {
626
- style: closeButtonStyle = {},
627
- onClick: onCloseClick,
628
- ...otherCloseButtonProps
629
- } = closeButtonProps;
630
750
  const {
631
751
  style: toggleButtonStyle = {},
632
752
  onClick: onToggleClick,
633
753
  ...otherToggleButtonProps
634
- } = toggleButtonProps; // Do not render on the server
754
+ } = toggleButtonProps; // get computed style based on panel position
755
+
756
+ const style = getSidePanelStyle({
757
+ position: panelPosition,
758
+ devtoolsTheme: defaultTheme,
759
+ isOpen: isResolvedOpen,
760
+ height: devtoolsHeight,
761
+ width: devtoolsWidth,
762
+ isResizing,
763
+ panelStyle
764
+ }); // Do not render on the server
635
765
 
636
766
  if (!isMounted()) return null;
637
767
  return /*#__PURE__*/React__namespace.createElement(Container, {
@@ -643,67 +773,17 @@ function ReactQueryDevtools$1({
643
773
  }, /*#__PURE__*/React__namespace.createElement(ReactQueryDevtoolsPanel$1, _extends({
644
774
  ref: panelRef,
645
775
  context: context,
646
- styleNonce: styleNonce
776
+ styleNonce: styleNonce,
777
+ position: panelPosition,
778
+ onPositionChange: setPanelPosition,
779
+ showCloseButton: true,
780
+ closeButtonProps: closeButtonProps
647
781
  }, otherPanelProps, {
648
- style: {
649
- position: 'fixed',
650
- bottom: '0',
651
- right: '0',
652
- zIndex: 99999,
653
- width: '100%',
654
- height: devtoolsHeight != null ? devtoolsHeight : 500,
655
- maxHeight: '90%',
656
- boxShadow: '0 0 20px rgba(0,0,0,.3)',
657
- borderTop: "1px solid " + defaultTheme.gray,
658
- transformOrigin: 'top',
659
- // visibility will be toggled after transitions, but set initial state here
660
- visibility: isOpen ? 'visible' : 'hidden',
661
- ...panelStyle,
662
- ...(isResizing ? {
663
- transition: "none"
664
- } : {
665
- transition: "all .2s ease"
666
- }),
667
- ...(isResolvedOpen ? {
668
- opacity: 1,
669
- pointerEvents: 'all',
670
- transform: "translateY(0) scale(1)"
671
- } : {
672
- opacity: 0,
673
- pointerEvents: 'none',
674
- transform: "translateY(15px) scale(1.02)"
675
- })
676
- },
782
+ style: style,
677
783
  isOpen: isResolvedOpen,
678
784
  setIsOpen: setIsOpen,
679
- handleDragStart: e => handleDragStart(panelRef.current, e)
680
- })), isResolvedOpen ? /*#__PURE__*/React__namespace.createElement(Button, _extends({
681
- type: "button",
682
- "aria-controls": "ReactQueryDevtoolsPanel",
683
- "aria-haspopup": "true",
684
- "aria-expanded": "true"
685
- }, otherCloseButtonProps, {
686
- onClick: e => {
687
- setIsOpen(false);
688
- onCloseClick == null ? void 0 : onCloseClick(e);
689
- },
690
- style: {
691
- position: 'fixed',
692
- zIndex: 99999,
693
- margin: '.5em',
694
- bottom: 0,
695
- ...(position === 'top-right' ? {
696
- right: '0'
697
- } : position === 'top-left' ? {
698
- left: '0'
699
- } : position === 'bottom-right' ? {
700
- right: '0'
701
- } : {
702
- left: '0'
703
- }),
704
- ...closeButtonStyle
705
- }
706
- }), "Close") : null), !isResolvedOpen ? /*#__PURE__*/React__namespace.createElement("button", _extends({
785
+ onDragStart: e => handleDragStart(panelRef.current, e)
786
+ }))), !isResolvedOpen ? /*#__PURE__*/React__namespace.createElement("button", _extends({
707
787
  type: "button"
708
788
  }, otherToggleButtonProps, {
709
789
  "aria-label": "Open React Query Devtools",
@@ -761,10 +841,18 @@ const ReactQueryDevtoolsPanel$1 = /*#__PURE__*/React__namespace.forwardRef(funct
761
841
  isOpen = true,
762
842
  styleNonce,
763
843
  setIsOpen,
764
- handleDragStart,
765
844
  context,
845
+ onDragStart,
846
+ onPositionChange,
847
+ showCloseButton,
848
+ position,
849
+ closeButtonProps = {},
766
850
  ...panelProps
767
851
  } = props;
852
+ const {
853
+ onClick: onCloseClick,
854
+ ...otherCloseButtonProps
855
+ } = closeButtonProps;
768
856
  const queryClient = reactQuery.useQueryClient({
769
857
  context
770
858
  });
@@ -794,23 +882,20 @@ const ReactQueryDevtoolsPanel$1 = /*#__PURE__*/React__namespace.forwardRef(funct
794
882
  className: "ReactQueryDevtoolsPanel",
795
883
  "aria-label": "React Query Devtools Panel",
796
884
  id: "ReactQueryDevtoolsPanel"
797
- }, panelProps), /*#__PURE__*/React__namespace.createElement("style", {
885
+ }, panelProps, {
886
+ style: {
887
+ height: defaultPanelSize,
888
+ position: 'relative',
889
+ ...panelProps.style
890
+ }
891
+ }), /*#__PURE__*/React__namespace.createElement("style", {
798
892
  nonce: styleNonce,
799
893
  dangerouslySetInnerHTML: {
800
894
  __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 "
801
895
  }
802
896
  }), /*#__PURE__*/React__namespace.createElement("div", {
803
- style: {
804
- position: 'absolute',
805
- left: 0,
806
- top: 0,
807
- width: '100%',
808
- height: '4px',
809
- marginBottom: '-4px',
810
- cursor: 'row-resize',
811
- zIndex: 100000
812
- },
813
- onMouseDown: handleDragStart
897
+ style: getResizeHandleStyle(position),
898
+ onMouseDown: onDragStart
814
899
  }), isOpen && /*#__PURE__*/React__namespace.createElement("div", {
815
900
  style: {
816
901
  flex: '1 1 500px',
@@ -853,9 +938,31 @@ const ReactQueryDevtoolsPanel$1 = /*#__PURE__*/React__namespace.forwardRef(funct
853
938
  display: 'flex',
854
939
  flexDirection: 'column'
855
940
  }
941
+ }, /*#__PURE__*/React__namespace.createElement("div", {
942
+ style: {
943
+ display: 'flex',
944
+ justifyContent: 'space-between',
945
+ alignItems: 'center',
946
+ marginBottom: '.5em'
947
+ }
856
948
  }, /*#__PURE__*/React__namespace.createElement(QueryStatusCount, {
857
949
  queryCache: queryCache
858
- }), /*#__PURE__*/React__namespace.createElement("div", {
950
+ }), position && onPositionChange ? /*#__PURE__*/React__namespace.createElement(Select, {
951
+ "aria-label": "Panel position",
952
+ value: position,
953
+ style: {
954
+ marginInlineStart: '.5em'
955
+ },
956
+ onChange: e => onPositionChange(e.target.value)
957
+ }, /*#__PURE__*/React__namespace.createElement("option", {
958
+ value: "left"
959
+ }, "Left"), /*#__PURE__*/React__namespace.createElement("option", {
960
+ value: "right"
961
+ }, "Right"), /*#__PURE__*/React__namespace.createElement("option", {
962
+ value: "top"
963
+ }, "Top"), /*#__PURE__*/React__namespace.createElement("option", {
964
+ value: "bottom"
965
+ }, "Bottom")) : null), /*#__PURE__*/React__namespace.createElement("div", {
859
966
  style: {
860
967
  display: 'flex',
861
968
  alignItems: 'center'
@@ -971,7 +1078,25 @@ const ReactQueryDevtoolsPanel$1 = /*#__PURE__*/React__namespace.forwardRef(funct
971
1078
  activeQueryHash: activeQueryHash,
972
1079
  queryCache: queryCache,
973
1080
  queryClient: queryClient
974
- }) : null));
1081
+ }) : null, showCloseButton ? /*#__PURE__*/React__namespace.createElement(Button, _extends({
1082
+ type: "button",
1083
+ "aria-controls": "ReactQueryDevtoolsPanel",
1084
+ "aria-haspopup": "true",
1085
+ "aria-expanded": "true"
1086
+ }, otherCloseButtonProps, {
1087
+ style: {
1088
+ position: 'absolute',
1089
+ zIndex: 99999,
1090
+ margin: '.5em',
1091
+ bottom: 0,
1092
+ left: 0,
1093
+ ...otherCloseButtonProps.style
1094
+ },
1095
+ onClick: e => {
1096
+ setIsOpen(false);
1097
+ onCloseClick == null ? void 0 : onCloseClick(e);
1098
+ }
1099
+ }), "Close") : null));
975
1100
  });
976
1101
 
977
1102
  const ActiveQuery = ({
@@ -1146,11 +1271,7 @@ const QueryStatusCount = ({
1146
1271
  const hasPaused = useSubscribeToQueryCache(queryCache, () => queryCache.getAll().filter(q => getQueryStatusLabel(q) === 'paused').length);
1147
1272
  const hasStale = useSubscribeToQueryCache(queryCache, () => queryCache.getAll().filter(q => getQueryStatusLabel(q) === 'stale').length);
1148
1273
  const hasInactive = useSubscribeToQueryCache(queryCache, () => queryCache.getAll().filter(q => getQueryStatusLabel(q) === 'inactive').length);
1149
- return /*#__PURE__*/React__namespace.createElement(QueryKeys, {
1150
- style: {
1151
- marginBottom: '.5em'
1152
- }
1153
- }, /*#__PURE__*/React__namespace.createElement(QueryKey, {
1274
+ return /*#__PURE__*/React__namespace.createElement(QueryKeys, null, /*#__PURE__*/React__namespace.createElement(QueryKey, {
1154
1275
  style: {
1155
1276
  background: defaultTheme.success,
1156
1277
  opacity: hasFresh ? 1 : 0.3