@tanstack/query-devtools 5.0.0-alpha.27

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 (45) hide show
  1. package/LICENSE +21 -0
  2. package/build/.tsbuildinfo +1 -0
  3. package/build/cjs/index.js +7966 -0
  4. package/build/cjs/index.js.map +1 -0
  5. package/build/esm/index.js +7964 -0
  6. package/build/esm/index.js.map +1 -0
  7. package/build/source/Context.js +10 -0
  8. package/build/source/Devtools.jsx +1485 -0
  9. package/build/source/Explorer.jsx +266 -0
  10. package/build/source/__tests__/devtools.test.jsx +6 -0
  11. package/build/source/fonts.js +7 -0
  12. package/build/source/icons/index.jsx +344 -0
  13. package/build/source/index.jsx +64 -0
  14. package/build/source/theme.js +304 -0
  15. package/build/source/utils.jsx +74 -0
  16. package/build/types/Context.d.ts +29 -0
  17. package/build/types/Context.d.ts.map +1 -0
  18. package/build/types/Devtools.d.ts +23 -0
  19. package/build/types/Devtools.d.ts.map +1 -0
  20. package/build/types/Explorer.d.ts +22 -0
  21. package/build/types/Explorer.d.ts.map +1 -0
  22. package/build/types/__tests__/devtools.test.d.ts +1 -0
  23. package/build/types/__tests__/devtools.test.d.ts.map +1 -0
  24. package/build/types/fonts.d.ts +2 -0
  25. package/build/types/fonts.d.ts.map +1 -0
  26. package/build/types/icons/index.d.ts +12 -0
  27. package/build/types/icons/index.d.ts.map +1 -0
  28. package/build/types/index.d.ts +27 -0
  29. package/build/types/index.d.ts.map +1 -0
  30. package/build/types/theme.d.ts +297 -0
  31. package/build/types/theme.d.ts.map +1 -0
  32. package/build/types/utils.d.ts +22 -0
  33. package/build/types/utils.d.ts.map +1 -0
  34. package/build/umd/index.js +872 -0
  35. package/build/umd/index.js.map +1 -0
  36. package/package.json +53 -0
  37. package/src/Context.ts +41 -0
  38. package/src/Devtools.tsx +1890 -0
  39. package/src/Explorer.tsx +348 -0
  40. package/src/__tests__/devtools.test.tsx +5 -0
  41. package/src/fonts.ts +7 -0
  42. package/src/icons/index.tsx +1065 -0
  43. package/src/index.tsx +113 -0
  44. package/src/theme.ts +321 -0
  45. package/src/utils.tsx +103 -0
package/src/index.tsx ADDED
@@ -0,0 +1,113 @@
1
+ import type {
2
+ QueryClient,
3
+ onlineManager as TonlineManager,
4
+ } from '@tanstack/query-core'
5
+ import { DevtoolsComponent } from './Devtools'
6
+ import { render } from 'solid-js/web'
7
+ import type {
8
+ DevtoolsButtonPosition,
9
+ DevtoolsPosition,
10
+ QueryDevtoolsProps,
11
+ DevToolsErrorType,
12
+ } from './Context'
13
+ import type { Signal } from 'solid-js'
14
+ import { createSignal } from 'solid-js'
15
+
16
+ export type { DevtoolsButtonPosition, DevtoolsPosition, DevToolsErrorType }
17
+ export interface TanstackQueryDevtoolsConfig extends QueryDevtoolsProps {}
18
+
19
+ class TanstackQueryDevtools {
20
+ client: QueryClient
21
+ onlineManager: typeof TonlineManager
22
+ queryFlavor: string
23
+ version: string
24
+ isMounted = false
25
+ buttonPosition: Signal<DevtoolsButtonPosition | undefined>
26
+ position: Signal<DevtoolsPosition | undefined>
27
+ initialIsOpen: Signal<boolean | undefined>
28
+ errorTypes: Signal<DevToolsErrorType[] | undefined>
29
+ dispose?: () => void
30
+
31
+ constructor(config: TanstackQueryDevtoolsConfig) {
32
+ const {
33
+ client,
34
+ queryFlavor,
35
+ version,
36
+ onlineManager,
37
+ buttonPosition,
38
+ position,
39
+ initialIsOpen,
40
+ errorTypes,
41
+ } = config
42
+ this.client = client
43
+ this.queryFlavor = queryFlavor
44
+ this.version = version
45
+ this.onlineManager = onlineManager
46
+ this.buttonPosition = createSignal(buttonPosition)
47
+ this.position = createSignal(position)
48
+ this.initialIsOpen = createSignal(initialIsOpen)
49
+ this.errorTypes = createSignal(errorTypes)
50
+ }
51
+
52
+ setButtonPosition(position: DevtoolsButtonPosition) {
53
+ this.buttonPosition[1](position)
54
+ }
55
+
56
+ setPosition(position: DevtoolsPosition) {
57
+ this.position[1](position)
58
+ }
59
+
60
+ setInitialIsOpen(isOpen: boolean) {
61
+ this.initialIsOpen[1](isOpen)
62
+ }
63
+
64
+ setErrorTypes(errorTypes: DevToolsErrorType[]) {
65
+ this.errorTypes[1](errorTypes)
66
+ }
67
+
68
+ mount<T extends HTMLElement>(el: T) {
69
+ if (this.isMounted) {
70
+ throw new Error('Devtools is already mounted')
71
+ }
72
+ const dispose = render(() => {
73
+ const [btnPosition] = this.buttonPosition
74
+ const [pos] = this.position
75
+ const [isOpen] = this.initialIsOpen
76
+ const [errors] = this.errorTypes
77
+ return (
78
+ <DevtoolsComponent
79
+ client={this.client}
80
+ queryFlavor={this.queryFlavor}
81
+ version={this.version}
82
+ onlineManager={this.onlineManager}
83
+ {...{
84
+ get buttonPosition() {
85
+ return btnPosition()
86
+ },
87
+ get position() {
88
+ return pos()
89
+ },
90
+ get initialIsOpen() {
91
+ return isOpen()
92
+ },
93
+ get errorTypes() {
94
+ return errors()
95
+ },
96
+ }}
97
+ />
98
+ )
99
+ }, el)
100
+ this.isMounted = true
101
+ this.dispose = dispose
102
+ }
103
+
104
+ unmount() {
105
+ if (!this.isMounted) {
106
+ throw new Error('Devtools is not mounted')
107
+ }
108
+ this.dispose?.()
109
+ this.isMounted = false
110
+ }
111
+ }
112
+
113
+ export { TanstackQueryDevtools }
package/src/theme.ts ADDED
@@ -0,0 +1,321 @@
1
+ const ShadowVariants = {
2
+ xs: '0 1px 2px 0 rgb(0 0 0 / 0.05)',
3
+ sm: '0 1px 3px 0 color, 0 1px 2px -1px color',
4
+ md: '0 4px 6px -1px color, 0 2px 4px -2px color',
5
+ lg: '0 10px 15px -3px color, 0 4px 6px -4px color',
6
+ xl: '0 20px 25px -5px color, 0 8px 10px -6px color',
7
+ '2xl': '0 25px 50px -12px color',
8
+ inner: 'inset 0 2px 4px 0 color',
9
+ none: 'none',
10
+ }
11
+
12
+ type ShadowVariantType = keyof typeof ShadowVariants
13
+
14
+ const getShadow = (variant: ShadowVariantType, color: string = ''): string => {
15
+ return ShadowVariants[variant].replace(/color/g, color)
16
+ }
17
+
18
+ const Shadow = {
19
+ xs: (color: string = 'rgb(0 0 0 / 0.1)') => getShadow('xs', color),
20
+ sm: (color: string = 'rgb(0 0 0 / 0.1)') => getShadow('sm', color),
21
+ md: (color: string = 'rgb(0 0 0 / 0.1)') => getShadow('md', color),
22
+ lg: (color: string = 'rgb(0 0 0 / 0.1)') => getShadow('lg', color),
23
+ xl: (color: string = 'rgb(0 0 0 / 0.1)') => getShadow('xl', color),
24
+ '2xl': (color: string = 'rgb(0 0 0 / 0.25)') => getShadow('2xl', color),
25
+ inner: (color: string = 'rgb(0 0 0 / 0.05)') => getShadow('inner', color),
26
+ none: () => getShadow('none'),
27
+ }
28
+
29
+ export const tokens = {
30
+ colors: {
31
+ inherit: 'inherit',
32
+ current: 'currentColor',
33
+ transparent: 'transparent',
34
+ black: '#000000',
35
+ white: '#ffffff',
36
+ neutral: {
37
+ 50: '#f9fafb',
38
+ 100: '#f2f4f7',
39
+ 200: '#eaecf0',
40
+ 300: '#d0d5dd',
41
+ 400: '#98a2b3',
42
+ 500: '#667085',
43
+ 600: '#475467',
44
+ 700: '#344054',
45
+ 800: '#1d2939',
46
+ 900: '#101828',
47
+ },
48
+ darkGray: {
49
+ 50: '#525c7a',
50
+ 100: '#49536e',
51
+ 200: '#414962',
52
+ 300: '#394056',
53
+ 400: '#313749',
54
+ 500: '#292e3d',
55
+ 600: '#212530',
56
+ 700: '#191c24',
57
+ 800: '#111318',
58
+ 900: '#0b0d10',
59
+ },
60
+ gray: {
61
+ 50: '#f9fafb',
62
+ 100: '#f2f4f7',
63
+ 200: '#eaecf0',
64
+ 300: '#d0d5dd',
65
+ 400: '#98a2b3',
66
+ 500: '#667085',
67
+ 600: '#475467',
68
+ 700: '#344054',
69
+ 800: '#1d2939',
70
+ 900: '#101828',
71
+ },
72
+ blue: {
73
+ 25: '#F5FAFF',
74
+ 50: '#EFF8FF',
75
+ 100: '#D1E9FF',
76
+ 200: '#B2DDFF',
77
+ 300: '#84CAFF',
78
+ 400: '#53B1FD',
79
+ 500: '#2E90FA',
80
+ 600: '#1570EF',
81
+ 700: '#175CD3',
82
+ 800: '#1849A9',
83
+ 900: '#194185',
84
+ },
85
+ green: {
86
+ 25: '#F6FEF9',
87
+ 50: '#ECFDF3',
88
+ 100: '#D1FADF',
89
+ 200: '#A6F4C5',
90
+ 300: '#6CE9A6',
91
+ 400: '#32D583',
92
+ 500: '#12B76A',
93
+ 600: '#039855',
94
+ 700: '#027A48',
95
+ 800: '#05603A',
96
+ 900: '#054F31',
97
+ },
98
+ red: {
99
+ 25: '#FFFBFA',
100
+ 50: '#FEF3F2',
101
+ 100: '#FEE4E2',
102
+ 200: '#FECDCA',
103
+ 300: '#FDA29B',
104
+ 400: '#F97066',
105
+ 500: '#F04438',
106
+ 600: '#D92D20',
107
+ 700: '#B42318',
108
+ 800: '#912018',
109
+ 900: '#7A271A',
110
+ },
111
+ yellow: {
112
+ 25: '#FFFCF5',
113
+ 50: '#FFFAEB',
114
+ 100: '#FEF0C7',
115
+ 200: '#FEDF89',
116
+ 300: '#FEC84B',
117
+ 400: '#FDB022',
118
+ 500: '#F79009',
119
+ 600: '#DC6803',
120
+ 700: '#B54708',
121
+ 800: '#93370D',
122
+ 900: '#7A2E0E',
123
+ },
124
+ purple: {
125
+ 25: '#FAFAFF',
126
+ 50: '#F4F3FF',
127
+ 100: '#EBE9FE',
128
+ 200: '#D9D6FE',
129
+ 300: '#BDB4FE',
130
+ 400: '#9B8AFB',
131
+ 500: '#7A5AF8',
132
+ 600: '#6938EF',
133
+ 700: '#5925DC',
134
+ 800: '#4A1FB8',
135
+ 900: '#3E1C96',
136
+ },
137
+ teal: {
138
+ 25: '#F6FEFC',
139
+ 50: '#F0FDF9',
140
+ 100: '#CCFBEF',
141
+ 200: '#99F6E0',
142
+ 300: '#5FE9D0',
143
+ 400: '#2ED3B7',
144
+ 500: '#15B79E',
145
+ 600: '#0E9384',
146
+ 700: '#107569',
147
+ 800: '#125D56',
148
+ 900: '#134E48',
149
+ },
150
+ pink: {
151
+ 25: '#fdf2f8',
152
+ 50: '#fce7f3',
153
+ 100: '#fbcfe8',
154
+ 200: '#f9a8d4',
155
+ 300: '#f472b6',
156
+ 400: '#ec4899',
157
+ 500: '#db2777',
158
+ 600: '#be185d',
159
+ 700: '#9d174d',
160
+ 800: '#831843',
161
+ 900: '#500724',
162
+ },
163
+ cyan: {
164
+ 25: '#ecfeff',
165
+ 50: '#cffafe',
166
+ 100: '#a5f3fc',
167
+ 200: '#67e8f9',
168
+ 300: '#22d3ee',
169
+ 400: '#06b6d4',
170
+ 500: '#0891b2',
171
+ 600: '#0e7490',
172
+ 700: '#155e75',
173
+ 800: '#164e63',
174
+ 900: '#083344',
175
+ },
176
+ },
177
+ alpha: {
178
+ 100: 'ff',
179
+ 90: 'e5',
180
+ 80: 'cc',
181
+ 70: 'b3',
182
+ 60: '99',
183
+ 50: '80',
184
+ 40: '66',
185
+ 30: '4d',
186
+ 20: '33',
187
+ 10: '1a',
188
+ 0: '00',
189
+ },
190
+ font: {
191
+ size: {
192
+ '2xs': '0.625rem',
193
+ xs: '0.75rem',
194
+ sm: '0.875rem',
195
+ md: '1rem',
196
+ lg: '1.125rem',
197
+ xl: '1.25rem',
198
+ '2xl': '1.5rem',
199
+ '3xl': '1.875rem',
200
+ '4xl': '2.25rem',
201
+ '5xl': '3rem',
202
+ '6xl': '3.75rem',
203
+ '7xl': '4.5rem',
204
+ '8xl': '6rem',
205
+ '9xl': '8rem',
206
+ },
207
+ lineHeight: {
208
+ xs: '1rem',
209
+ sm: '1.25rem',
210
+ md: '1.5rem',
211
+ lg: '1.75rem',
212
+ xl: '1.75rem',
213
+ '2xl': '2rem',
214
+ '3xl': '2.25rem',
215
+ '4xl': '2.5rem',
216
+ '5xl': '1',
217
+ '6xl': '1',
218
+ '7xl': '1',
219
+ '8xl': '1',
220
+ '9xl': '1',
221
+ },
222
+ weight: {
223
+ thin: '100',
224
+ extralight: '200',
225
+ light: '300',
226
+ normal: '400',
227
+ medium: '500',
228
+ semibold: '600',
229
+ bold: '700',
230
+ extrabold: '800',
231
+ black: '900',
232
+ },
233
+ },
234
+ breakpoints: {
235
+ xs: '320px',
236
+ sm: '640px',
237
+ md: '768px',
238
+ lg: '1024px',
239
+ xl: '1280px',
240
+ '2xl': '1536px',
241
+ },
242
+ border: {
243
+ radius: {
244
+ none: '0px',
245
+ xs: '0.125rem',
246
+ sm: '0.25rem',
247
+ md: '0.375rem',
248
+ lg: '0.5rem',
249
+ xl: '0.75rem',
250
+ '2xl': '1rem',
251
+ '3xl': '1.5rem',
252
+ full: '9999px',
253
+ },
254
+ },
255
+ size: {
256
+ 0: '0px',
257
+ 0.25: '0.0625rem',
258
+ 0.5: '0.125rem',
259
+ 1: '0.25rem',
260
+ 1.5: '0.375rem',
261
+ 2: '0.5rem',
262
+ 2.5: '0.625rem',
263
+ 3: '0.75rem',
264
+ 3.5: '0.875rem',
265
+ 4: '1rem',
266
+ 4.5: '1.125rem',
267
+ 5: '1.25rem',
268
+ 6: '1.5rem',
269
+ 7: '1.75rem',
270
+ 8: '2rem',
271
+ 9: '2.25rem',
272
+ 10: '2.5rem',
273
+ 11: '2.75rem',
274
+ 12: '3rem',
275
+ 14: '3.5rem',
276
+ 16: '4rem',
277
+ 20: '5rem',
278
+ 24: '6rem',
279
+ 28: '7rem',
280
+ 32: '8rem',
281
+ 36: '9rem',
282
+ 40: '10rem',
283
+ 44: '11rem',
284
+ 48: '12rem',
285
+ 52: '13rem',
286
+ 56: '14rem',
287
+ 60: '15rem',
288
+ 64: '16rem',
289
+ 72: '18rem',
290
+ 80: '20rem',
291
+ 96: '24rem',
292
+ },
293
+ shadow: Shadow,
294
+ zIndices: {
295
+ hide: -1,
296
+ auto: 'auto',
297
+ base: 0,
298
+ docked: 10,
299
+ dropdown: 1000,
300
+ sticky: 1100,
301
+ banner: 1200,
302
+ overlay: 1300,
303
+ modal: 1400,
304
+ popover: 1500,
305
+ skipLink: 1600,
306
+ toast: 1700,
307
+ tooltip: 1800,
308
+ },
309
+ }
310
+
311
+ export type ThemeConfigType = typeof tokens
312
+ export type ThemeColorsAll = {
313
+ [key in keyof ThemeConfigType['colors']]: key
314
+ }[keyof ThemeConfigType['colors']]
315
+ export type AtomicThemeColors =
316
+ | 'white'
317
+ | 'black'
318
+ | 'transparent'
319
+ | 'current'
320
+ | 'inherit'
321
+ export type ThemeColors = Exclude<ThemeColorsAll, AtomicThemeColors>
package/src/utils.tsx ADDED
@@ -0,0 +1,103 @@
1
+ import type { Query } from '@tanstack/query-core'
2
+ import SuperJSON from 'superjson'
3
+
4
+ export function getQueryStatusLabel(query: Query) {
5
+ return query.state.fetchStatus === 'fetching'
6
+ ? 'fetching'
7
+ : !query.getObserversCount()
8
+ ? 'inactive'
9
+ : query.state.fetchStatus === 'paused'
10
+ ? 'paused'
11
+ : query.isStale()
12
+ ? 'stale'
13
+ : 'fresh'
14
+ }
15
+
16
+ export const queryStatusLabels = [
17
+ 'fresh',
18
+ 'stale',
19
+ 'paused',
20
+ 'inactive',
21
+ 'fetching',
22
+ ] as const
23
+ export type IQueryStatusLabel = (typeof queryStatusLabels)[number]
24
+
25
+ export function getQueryStatusColor({
26
+ queryState,
27
+ observerCount,
28
+ isStale,
29
+ }: {
30
+ queryState: Query['state']
31
+ observerCount: number
32
+ isStale: boolean
33
+ }) {
34
+ return queryState.fetchStatus === 'fetching'
35
+ ? 'blue'
36
+ : !observerCount
37
+ ? 'gray'
38
+ : queryState.fetchStatus === 'paused'
39
+ ? 'purple'
40
+ : isStale
41
+ ? 'yellow'
42
+ : 'green'
43
+ }
44
+
45
+ export function getQueryStatusColorByLabel(label: IQueryStatusLabel) {
46
+ return label === 'fresh'
47
+ ? 'green'
48
+ : label === 'stale'
49
+ ? 'yellow'
50
+ : label === 'paused'
51
+ ? 'purple'
52
+ : label === 'inactive'
53
+ ? 'gray'
54
+ : 'blue'
55
+ }
56
+
57
+ /**
58
+ * Displays a string regardless the type of the data
59
+ * @param {unknown} value Value to be stringified
60
+ * @param {boolean} beautify Formats json to multiline
61
+ */
62
+ export const displayValue = (value: unknown, beautify: boolean = false) => {
63
+ const { json } = SuperJSON.serialize(value)
64
+
65
+ return JSON.stringify(json, null, beautify ? 2 : undefined)
66
+ }
67
+
68
+ // Sorting functions
69
+ type SortFn = (a: Query, b: Query) => number
70
+
71
+ const getStatusRank = (q: Query) =>
72
+ q.state.fetchStatus !== 'idle'
73
+ ? 0
74
+ : !q.getObserversCount()
75
+ ? 3
76
+ : q.isStale()
77
+ ? 2
78
+ : 1
79
+
80
+ const queryHashSort: SortFn = (a, b) => a.queryHash.localeCompare(b.queryHash)
81
+
82
+ const dateSort: SortFn = (a, b) =>
83
+ a.state.dataUpdatedAt < b.state.dataUpdatedAt ? 1 : -1
84
+
85
+ const statusAndDateSort: SortFn = (a, b) => {
86
+ if (getStatusRank(a) === getStatusRank(b)) {
87
+ return dateSort(a, b)
88
+ }
89
+
90
+ return getStatusRank(a) > getStatusRank(b) ? 1 : -1
91
+ }
92
+
93
+ export const sortFns: Record<string, SortFn> = {
94
+ status: statusAndDateSort,
95
+ 'query hash': queryHashSort,
96
+ 'last updated': dateSort,
97
+ }
98
+
99
+ export const convertRemToPixels = (rem: number) => {
100
+ return rem * parseFloat(getComputedStyle(document.documentElement).fontSize)
101
+ }
102
+
103
+ export const convertPixelsToRem = (px: number) => px / convertRemToPixels(1)