@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.
@@ -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,68 +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
- direction: 'ltr',
650
- position: 'fixed',
651
- bottom: '0',
652
- right: '0',
653
- zIndex: 99999,
654
- width: '100%',
655
- height: devtoolsHeight != null ? devtoolsHeight : 500,
656
- maxHeight: '90%',
657
- boxShadow: '0 0 20px rgba(0,0,0,.3)',
658
- borderTop: "1px solid " + defaultTheme.gray,
659
- transformOrigin: 'top',
660
- // visibility will be toggled after transitions, but set initial state here
661
- visibility: isOpen ? 'visible' : 'hidden',
662
- ...panelStyle,
663
- ...(isResizing ? {
664
- transition: "none"
665
- } : {
666
- transition: "all .2s ease"
667
- }),
668
- ...(isResolvedOpen ? {
669
- opacity: 1,
670
- pointerEvents: 'all',
671
- transform: "translateY(0) scale(1)"
672
- } : {
673
- opacity: 0,
674
- pointerEvents: 'none',
675
- transform: "translateY(15px) scale(1.02)"
676
- })
677
- },
782
+ style: style,
678
783
  isOpen: isResolvedOpen,
679
784
  setIsOpen: setIsOpen,
680
- handleDragStart: e => handleDragStart(panelRef.current, e)
681
- })), isResolvedOpen ? /*#__PURE__*/React__namespace.createElement(Button, _extends({
682
- type: "button",
683
- "aria-controls": "ReactQueryDevtoolsPanel",
684
- "aria-haspopup": "true",
685
- "aria-expanded": "true"
686
- }, otherCloseButtonProps, {
687
- onClick: e => {
688
- setIsOpen(false);
689
- onCloseClick == null ? void 0 : onCloseClick(e);
690
- },
691
- style: {
692
- position: 'fixed',
693
- zIndex: 99999,
694
- margin: '.5em',
695
- bottom: 0,
696
- ...(position === 'top-right' ? {
697
- right: '0'
698
- } : position === 'top-left' ? {
699
- left: '0'
700
- } : position === 'bottom-right' ? {
701
- right: '0'
702
- } : {
703
- left: '0'
704
- }),
705
- ...closeButtonStyle
706
- }
707
- }), "Close") : null), !isResolvedOpen ? /*#__PURE__*/React__namespace.createElement("button", _extends({
785
+ onDragStart: e => handleDragStart(panelRef.current, e)
786
+ }))), !isResolvedOpen ? /*#__PURE__*/React__namespace.createElement("button", _extends({
708
787
  type: "button"
709
788
  }, otherToggleButtonProps, {
710
789
  "aria-label": "Open React Query Devtools",
@@ -762,10 +841,18 @@ const ReactQueryDevtoolsPanel$1 = /*#__PURE__*/React__namespace.forwardRef(funct
762
841
  isOpen = true,
763
842
  styleNonce,
764
843
  setIsOpen,
765
- handleDragStart,
766
844
  context,
845
+ onDragStart,
846
+ onPositionChange,
847
+ showCloseButton,
848
+ position,
849
+ closeButtonProps = {},
767
850
  ...panelProps
768
851
  } = props;
852
+ const {
853
+ onClick: onCloseClick,
854
+ ...otherCloseButtonProps
855
+ } = closeButtonProps;
769
856
  const queryClient = reactQuery.useQueryClient({
770
857
  context
771
858
  });
@@ -795,23 +882,20 @@ const ReactQueryDevtoolsPanel$1 = /*#__PURE__*/React__namespace.forwardRef(funct
795
882
  className: "ReactQueryDevtoolsPanel",
796
883
  "aria-label": "React Query Devtools Panel",
797
884
  id: "ReactQueryDevtoolsPanel"
798
- }, 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", {
799
892
  nonce: styleNonce,
800
893
  dangerouslySetInnerHTML: {
801
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 "
802
895
  }
803
896
  }), /*#__PURE__*/React__namespace.createElement("div", {
804
- style: {
805
- position: 'absolute',
806
- left: 0,
807
- top: 0,
808
- width: '100%',
809
- height: '4px',
810
- marginBottom: '-4px',
811
- cursor: 'row-resize',
812
- zIndex: 100000
813
- },
814
- onMouseDown: handleDragStart
897
+ style: getResizeHandleStyle(position),
898
+ onMouseDown: onDragStart
815
899
  }), isOpen && /*#__PURE__*/React__namespace.createElement("div", {
816
900
  style: {
817
901
  flex: '1 1 500px',
@@ -854,9 +938,31 @@ const ReactQueryDevtoolsPanel$1 = /*#__PURE__*/React__namespace.forwardRef(funct
854
938
  display: 'flex',
855
939
  flexDirection: 'column'
856
940
  }
941
+ }, /*#__PURE__*/React__namespace.createElement("div", {
942
+ style: {
943
+ display: 'flex',
944
+ justifyContent: 'space-between',
945
+ alignItems: 'center',
946
+ marginBottom: '.5em'
947
+ }
857
948
  }, /*#__PURE__*/React__namespace.createElement(QueryStatusCount, {
858
949
  queryCache: queryCache
859
- }), /*#__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", {
860
966
  style: {
861
967
  display: 'flex',
862
968
  alignItems: 'center'
@@ -972,7 +1078,25 @@ const ReactQueryDevtoolsPanel$1 = /*#__PURE__*/React__namespace.forwardRef(funct
972
1078
  activeQueryHash: activeQueryHash,
973
1079
  queryCache: queryCache,
974
1080
  queryClient: queryClient
975
- }) : 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));
976
1100
  });
977
1101
 
978
1102
  const ActiveQuery = ({
@@ -1147,11 +1271,7 @@ const QueryStatusCount = ({
1147
1271
  const hasPaused = useSubscribeToQueryCache(queryCache, () => queryCache.getAll().filter(q => getQueryStatusLabel(q) === 'paused').length);
1148
1272
  const hasStale = useSubscribeToQueryCache(queryCache, () => queryCache.getAll().filter(q => getQueryStatusLabel(q) === 'stale').length);
1149
1273
  const hasInactive = useSubscribeToQueryCache(queryCache, () => queryCache.getAll().filter(q => getQueryStatusLabel(q) === 'inactive').length);
1150
- return /*#__PURE__*/React__namespace.createElement(QueryKeys, {
1151
- style: {
1152
- marginBottom: '.5em'
1153
- }
1154
- }, /*#__PURE__*/React__namespace.createElement(QueryKey, {
1274
+ return /*#__PURE__*/React__namespace.createElement(QueryKeys, null, /*#__PURE__*/React__namespace.createElement(QueryKey, {
1155
1275
  style: {
1156
1276
  background: defaultTheme.success,
1157
1277
  opacity: hasFresh ? 1 : 0.3