@tanstack/react-query-devtools 4.0.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.
Files changed (59) hide show
  1. package/build/cjs/Explorer.js +215 -0
  2. package/build/cjs/Explorer.js.map +1 -0
  3. package/build/cjs/Logo.js +66 -0
  4. package/build/cjs/Logo.js.map +1 -0
  5. package/build/cjs/_virtual/_rollupPluginBabelHelpers.js +33 -0
  6. package/build/cjs/_virtual/_rollupPluginBabelHelpers.js.map +1 -0
  7. package/build/cjs/devtools.js +822 -0
  8. package/build/cjs/devtools.js.map +1 -0
  9. package/build/cjs/index.js +21 -0
  10. package/build/cjs/index.js.map +1 -0
  11. package/build/cjs/packages/react-query-devtools/src/Explorer.js +215 -0
  12. package/build/cjs/packages/react-query-devtools/src/Explorer.js.map +1 -0
  13. package/build/cjs/packages/react-query-devtools/src/Logo.js +66 -0
  14. package/build/cjs/packages/react-query-devtools/src/Logo.js.map +1 -0
  15. package/build/cjs/packages/react-query-devtools/src/devtools.js +818 -0
  16. package/build/cjs/packages/react-query-devtools/src/devtools.js.map +1 -0
  17. package/build/cjs/packages/react-query-devtools/src/index.js +22 -0
  18. package/build/cjs/packages/react-query-devtools/src/index.js.map +1 -0
  19. package/build/cjs/packages/react-query-devtools/src/styledComponents.js +113 -0
  20. package/build/cjs/packages/react-query-devtools/src/styledComponents.js.map +1 -0
  21. package/build/cjs/packages/react-query-devtools/src/theme.js +68 -0
  22. package/build/cjs/packages/react-query-devtools/src/theme.js.map +1 -0
  23. package/build/cjs/packages/react-query-devtools/src/useLocalStorage.js +81 -0
  24. package/build/cjs/packages/react-query-devtools/src/useLocalStorage.js.map +1 -0
  25. package/build/cjs/packages/react-query-devtools/src/useMediaQuery.js +66 -0
  26. package/build/cjs/packages/react-query-devtools/src/useMediaQuery.js.map +1 -0
  27. package/build/cjs/packages/react-query-devtools/src/utils.js +100 -0
  28. package/build/cjs/packages/react-query-devtools/src/utils.js.map +1 -0
  29. package/build/cjs/styledComponents.js +113 -0
  30. package/build/cjs/styledComponents.js.map +1 -0
  31. package/build/cjs/theme.js +68 -0
  32. package/build/cjs/theme.js.map +1 -0
  33. package/build/cjs/useLocalStorage.js +81 -0
  34. package/build/cjs/useLocalStorage.js.map +1 -0
  35. package/build/cjs/useMediaQuery.js +66 -0
  36. package/build/cjs/useMediaQuery.js.map +1 -0
  37. package/build/cjs/utils.js +100 -0
  38. package/build/cjs/utils.js.map +1 -0
  39. package/build/esm/index.js +1973 -0
  40. package/build/esm/index.js.map +1 -0
  41. package/build/stats-html.html +2689 -0
  42. package/build/umd/index.development.js +2001 -0
  43. package/build/umd/index.development.js.map +1 -0
  44. package/build/umd/index.production.js +29 -0
  45. package/build/umd/index.production.js.map +1 -0
  46. package/package.json +30 -0
  47. package/src/Explorer.tsx +261 -0
  48. package/src/Logo.tsx +32 -0
  49. package/src/__tests__/Explorer.test.tsx +68 -0
  50. package/src/__tests__/devtools.test.tsx +766 -0
  51. package/src/__tests__/utils.tsx +81 -0
  52. package/src/devtools.tsx +1128 -0
  53. package/src/index.ts +1 -0
  54. package/src/noop.ts +7 -0
  55. package/src/styledComponents.ts +108 -0
  56. package/src/theme.tsx +32 -0
  57. package/src/useLocalStorage.ts +52 -0
  58. package/src/useMediaQuery.ts +32 -0
  59. package/src/utils.ts +126 -0
package/src/index.ts ADDED
@@ -0,0 +1 @@
1
+ export * from './devtools'
package/src/noop.ts ADDED
@@ -0,0 +1,7 @@
1
+ export function ReactQueryDevtools() {
2
+ return null
3
+ }
4
+
5
+ export function ReactQueryDevtoolsPanel() {
6
+ return null
7
+ }
@@ -0,0 +1,108 @@
1
+ import { styled } from './utils'
2
+
3
+ export const Panel = styled(
4
+ 'div',
5
+ (_props, theme) => ({
6
+ fontSize: 'clamp(12px, 1.5vw, 14px)',
7
+ fontFamily: `sans-serif`,
8
+ display: 'flex',
9
+ backgroundColor: theme.background,
10
+ color: theme.foreground,
11
+ }),
12
+ {
13
+ '(max-width: 700px)': {
14
+ flexDirection: 'column',
15
+ },
16
+ '(max-width: 600px)': {
17
+ fontSize: '.9em',
18
+ // flexDirection: 'column',
19
+ },
20
+ },
21
+ )
22
+
23
+ export const ActiveQueryPanel = styled(
24
+ 'div',
25
+ () => ({
26
+ flex: '1 1 500px',
27
+ display: 'flex',
28
+ flexDirection: 'column',
29
+ overflow: 'auto',
30
+ height: '100%',
31
+ }),
32
+ {
33
+ '(max-width: 700px)': (_props, theme) => ({
34
+ borderTop: `2px solid ${theme.gray}`,
35
+ }),
36
+ },
37
+ )
38
+
39
+ export const Button = styled('button', (props, theme) => ({
40
+ appearance: 'none',
41
+ fontSize: '.9em',
42
+ fontWeight: 'bold',
43
+ background: theme.gray,
44
+ border: '0',
45
+ borderRadius: '.3em',
46
+ color: 'white',
47
+ padding: '.5em',
48
+ opacity: props.disabled ? '.5' : undefined,
49
+ cursor: 'pointer',
50
+ }))
51
+
52
+ export const QueryKeys = styled('span', {
53
+ display: 'inline-block',
54
+ fontSize: '0.9em',
55
+ })
56
+
57
+ export const QueryKey = styled('span', {
58
+ display: 'inline-flex',
59
+ alignItems: 'center',
60
+ padding: '.2em .4em',
61
+ fontWeight: 'bold',
62
+ textShadow: '0 0 10px black',
63
+ borderRadius: '.2em',
64
+ })
65
+
66
+ export const Code = styled('code', {
67
+ fontSize: '.9em',
68
+ color: 'inherit',
69
+ background: 'inherit',
70
+ })
71
+
72
+ export const Input = styled('input', (_props, theme) => ({
73
+ backgroundColor: theme.inputBackgroundColor,
74
+ border: 0,
75
+ borderRadius: '.2em',
76
+ color: theme.inputTextColor,
77
+ fontSize: '.9em',
78
+ lineHeight: `1.3`,
79
+ padding: '.3em .4em',
80
+ }))
81
+
82
+ export const Select = styled(
83
+ 'select',
84
+ (_props, theme) => ({
85
+ display: `inline-block`,
86
+ fontSize: `.9em`,
87
+ fontFamily: `sans-serif`,
88
+ fontWeight: 'normal',
89
+ lineHeight: `1.3`,
90
+ padding: `.3em 1.5em .3em .5em`,
91
+ height: 'auto',
92
+ border: 0,
93
+ borderRadius: `.2em`,
94
+ appearance: `none`,
95
+ WebkitAppearance: 'none',
96
+ backgroundColor: theme.inputBackgroundColor,
97
+ backgroundImage: `url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='100' height='100' fill='%23444444'><polygon points='0,25 100,25 50,75'/></svg>")`,
98
+ backgroundRepeat: `no-repeat`,
99
+ backgroundPosition: `right .55em center`,
100
+ backgroundSize: `.65em auto, 100%`,
101
+ color: theme.inputTextColor,
102
+ }),
103
+ {
104
+ '(max-width: 500px)': {
105
+ display: 'none',
106
+ },
107
+ },
108
+ )
package/src/theme.tsx ADDED
@@ -0,0 +1,32 @@
1
+ import * as React from 'react'
2
+
3
+ export const defaultTheme = {
4
+ background: '#0b1521',
5
+ backgroundAlt: '#132337',
6
+ foreground: 'white',
7
+ gray: '#3f4e60',
8
+ grayAlt: '#222e3e',
9
+ inputBackgroundColor: '#fff',
10
+ inputTextColor: '#000',
11
+ success: '#00ab52',
12
+ danger: '#ff0085',
13
+ active: '#006bff',
14
+ paused: '#8c49eb',
15
+ warning: '#ffb200',
16
+ } as const
17
+
18
+ export type Theme = typeof defaultTheme
19
+ interface ProviderProps {
20
+ theme: Theme
21
+ children?: React.ReactNode
22
+ }
23
+
24
+ const ThemeContext = React.createContext(defaultTheme)
25
+
26
+ export function ThemeProvider({ theme, ...rest }: ProviderProps) {
27
+ return <ThemeContext.Provider value={theme} {...rest} />
28
+ }
29
+
30
+ export function useTheme() {
31
+ return React.useContext(ThemeContext)
32
+ }
@@ -0,0 +1,52 @@
1
+ import * as React from 'react'
2
+
3
+ const getItem = (key: string): unknown => {
4
+ try {
5
+ const itemValue = localStorage.getItem(key)
6
+ if (typeof itemValue === 'string') {
7
+ return JSON.parse(itemValue)
8
+ }
9
+ return undefined
10
+ } catch {
11
+ return undefined
12
+ }
13
+ }
14
+
15
+ export default function useLocalStorage<T>(
16
+ key: string,
17
+ defaultValue: T | undefined,
18
+ ): [T | undefined, (newVal: T | ((prevVal: T) => T)) => void] {
19
+ const [value, setValue] = React.useState<T>()
20
+
21
+ React.useEffect(() => {
22
+ const initialValue = getItem(key) as T | undefined
23
+
24
+ if (typeof initialValue === 'undefined' || initialValue === null) {
25
+ setValue(
26
+ typeof defaultValue === 'function' ? defaultValue() : defaultValue,
27
+ )
28
+ } else {
29
+ setValue(initialValue)
30
+ }
31
+ }, [defaultValue, key])
32
+
33
+ const setter = React.useCallback(
34
+ (updater: any) => {
35
+ setValue((old) => {
36
+ let newVal = updater
37
+
38
+ if (typeof updater == 'function') {
39
+ newVal = updater(old)
40
+ }
41
+ try {
42
+ localStorage.setItem(key, JSON.stringify(newVal))
43
+ } catch {}
44
+
45
+ return newVal
46
+ })
47
+ },
48
+ [key],
49
+ )
50
+
51
+ return [value, setter]
52
+ }
@@ -0,0 +1,32 @@
1
+ import * as React from 'react'
2
+
3
+ export default function useMediaQuery(query: string): boolean | undefined {
4
+ // Keep track of the preference in state, start with the current match
5
+ const [isMatch, setIsMatch] = React.useState(() => {
6
+ if (typeof window !== 'undefined') {
7
+ return window.matchMedia(query).matches
8
+ }
9
+ })
10
+
11
+ // Watch for changes
12
+ React.useEffect(() => {
13
+ if (typeof window !== 'undefined') {
14
+ // Create a matcher
15
+ const matcher = window.matchMedia(query)
16
+
17
+ // Create our handler
18
+ const onChange = ({ matches }: { matches: boolean }) =>
19
+ setIsMatch(matches)
20
+
21
+ // Listen for changes
22
+ matcher.addListener(onChange)
23
+
24
+ return () => {
25
+ // Stop listening for changes
26
+ matcher.removeListener(onChange)
27
+ }
28
+ }
29
+ }, [isMatch, query, setIsMatch])
30
+
31
+ return isMatch
32
+ }
package/src/utils.ts ADDED
@@ -0,0 +1,126 @@
1
+ import * as React from 'react'
2
+ import type { Query } from '@tanstack/react-query'
3
+
4
+ import { Theme, useTheme } from './theme'
5
+ import useMediaQuery from './useMediaQuery'
6
+
7
+ export const isServer = typeof window === 'undefined'
8
+
9
+ type StyledComponent<T> = T extends 'button'
10
+ ? React.DetailedHTMLProps<
11
+ React.ButtonHTMLAttributes<HTMLButtonElement>,
12
+ HTMLButtonElement
13
+ >
14
+ : T extends 'input'
15
+ ? React.DetailedHTMLProps<
16
+ React.InputHTMLAttributes<HTMLInputElement>,
17
+ HTMLInputElement
18
+ >
19
+ : T extends 'select'
20
+ ? React.DetailedHTMLProps<
21
+ React.SelectHTMLAttributes<HTMLSelectElement>,
22
+ HTMLSelectElement
23
+ >
24
+ : T extends keyof HTMLElementTagNameMap
25
+ ? React.HTMLAttributes<HTMLElementTagNameMap[T]>
26
+ : never
27
+
28
+ export function getQueryStatusColor({
29
+ queryState,
30
+ observerCount,
31
+ isStale,
32
+ theme,
33
+ }: {
34
+ queryState: Query['state']
35
+ observerCount: number
36
+ isStale: boolean
37
+ theme: Theme
38
+ }) {
39
+ return queryState.fetchStatus === 'fetching'
40
+ ? theme.active
41
+ : !observerCount
42
+ ? theme.gray
43
+ : queryState.fetchStatus === 'paused'
44
+ ? theme.paused
45
+ : isStale
46
+ ? theme.warning
47
+ : theme.success
48
+ }
49
+
50
+ export function getQueryStatusLabel(query: Query) {
51
+ return query.state.fetchStatus === 'fetching'
52
+ ? 'fetching'
53
+ : !query.getObserversCount()
54
+ ? 'inactive'
55
+ : query.state.fetchStatus === 'paused'
56
+ ? 'paused'
57
+ : query.isStale()
58
+ ? 'stale'
59
+ : 'fresh'
60
+ }
61
+
62
+ type Styles =
63
+ | React.CSSProperties
64
+ | ((props: Record<string, any>, theme: Theme) => React.CSSProperties)
65
+
66
+ export function styled<T extends keyof HTMLElementTagNameMap>(
67
+ type: T,
68
+ newStyles: Styles,
69
+ queries: Record<string, Styles> = {},
70
+ ) {
71
+ return React.forwardRef<HTMLElementTagNameMap[T], StyledComponent<T>>(
72
+ ({ style, ...rest }, ref) => {
73
+ const theme = useTheme()
74
+
75
+ const mediaStyles = Object.entries(queries).reduce(
76
+ (current, [key, value]) => {
77
+ // eslint-disable-next-line react-hooks/rules-of-hooks
78
+ return useMediaQuery(key)
79
+ ? {
80
+ ...current,
81
+ ...(typeof value === 'function' ? value(rest, theme) : value),
82
+ }
83
+ : current
84
+ },
85
+ {},
86
+ )
87
+
88
+ return React.createElement(type, {
89
+ ...rest,
90
+ style: {
91
+ ...(typeof newStyles === 'function'
92
+ ? newStyles(rest, theme)
93
+ : newStyles),
94
+ ...style,
95
+ ...mediaStyles,
96
+ },
97
+ ref,
98
+ })
99
+ },
100
+ )
101
+ }
102
+
103
+ export function useIsMounted() {
104
+ const mountedRef = React.useRef(false)
105
+ const isMounted = React.useCallback(() => mountedRef.current, [])
106
+
107
+ React[isServer ? 'useEffect' : 'useLayoutEffect'](() => {
108
+ mountedRef.current = true
109
+ return () => {
110
+ mountedRef.current = false
111
+ }
112
+ }, [])
113
+
114
+ return isMounted
115
+ }
116
+
117
+ /**
118
+ * Displays a string regardless the type of the data
119
+ * @param {unknown} value Value to be stringified
120
+ */
121
+ export const displayValue = (value: unknown) => {
122
+ const name = Object.getOwnPropertyNames(Object(value))
123
+ const newValue = typeof value === 'bigint' ? `${value.toString()}n` : value
124
+
125
+ return JSON.stringify(newValue, name)
126
+ }