@tanstack/react-query-devtools 5.0.0-alpha.1 → 5.0.0-alpha.11

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 (47) hide show
  1. package/build/lib/Explorer.esm.js +2 -1
  2. package/build/lib/Explorer.esm.js.map +1 -1
  3. package/build/lib/Explorer.js +2 -1
  4. package/build/lib/Explorer.js.map +1 -1
  5. package/build/lib/Explorer.mjs +1 -0
  6. package/build/lib/Explorer.mjs.map +1 -1
  7. package/build/lib/devtools.d.ts +20 -2
  8. package/build/lib/devtools.esm.js +162 -34
  9. package/build/lib/devtools.esm.js.map +1 -1
  10. package/build/lib/devtools.js +161 -34
  11. package/build/lib/devtools.js.map +1 -1
  12. package/build/lib/devtools.mjs +106 -9
  13. package/build/lib/devtools.mjs.map +1 -1
  14. package/build/lib/index.esm.js +1 -0
  15. package/build/lib/index.esm.js.map +1 -1
  16. package/build/lib/index.js +1 -0
  17. package/build/lib/index.js.map +1 -1
  18. package/build/lib/index.mjs +1 -0
  19. package/build/lib/index.mjs.map +1 -1
  20. package/build/lib/index.prod.esm.js +165 -36
  21. package/build/lib/index.prod.esm.js.map +1 -1
  22. package/build/lib/index.prod.js +164 -36
  23. package/build/lib/index.prod.js.map +1 -1
  24. package/build/lib/index.prod.mjs +108 -10
  25. package/build/lib/index.prod.mjs.map +1 -1
  26. package/build/lib/styledComponents.d.ts +0 -1
  27. package/build/lib/styledComponents.esm.js +3 -1
  28. package/build/lib/styledComponents.esm.js.map +1 -1
  29. package/build/lib/styledComponents.js +3 -1
  30. package/build/lib/styledComponents.js.map +1 -1
  31. package/build/lib/styledComponents.mjs +3 -1
  32. package/build/lib/styledComponents.mjs.map +1 -1
  33. package/build/lib/theme.esm.js +1 -0
  34. package/build/lib/theme.esm.js.map +1 -1
  35. package/build/lib/theme.js +1 -0
  36. package/build/lib/theme.js.map +1 -1
  37. package/build/lib/theme.mjs +1 -0
  38. package/build/lib/theme.mjs.map +1 -1
  39. package/build/umd/index.development.js +107 -10
  40. package/build/umd/index.development.js.map +1 -1
  41. package/build/umd/index.production.js.map +1 -1
  42. package/package.json +4 -4
  43. package/src/__tests__/Explorer.test.tsx +3 -2
  44. package/src/__tests__/devtools.test.tsx +183 -9
  45. package/src/devtools.tsx +151 -3
  46. package/src/index.ts +2 -0
  47. package/src/styledComponents.ts +3 -1
@@ -1 +1 @@
1
- {"version":3,"file":"index.production.js","sources":["../../src/index.ts"],"sourcesContent":["import * as devtools from './devtools'\n\nexport const ReactQueryDevtools: (typeof devtools)['ReactQueryDevtools'] =\n process.env.NODE_ENV !== 'development'\n ? function () {\n return null\n }\n : devtools.ReactQueryDevtools\n\nexport const ReactQueryDevtoolsPanel: (typeof devtools)['ReactQueryDevtoolsPanel'] =\n process.env.NODE_ENV !== 'development'\n ? (function () {\n return null\n } as any)\n : devtools.ReactQueryDevtoolsPanel\n"],"names":[],"mappings":"+QAIM,WACE,OAAO,gCAMR,WACC,OAAO"}
1
+ {"version":3,"file":"index.production.js","sources":["../../src/index.ts"],"sourcesContent":["'use client'\n\nimport * as devtools from './devtools'\n\nexport const ReactQueryDevtools: (typeof devtools)['ReactQueryDevtools'] =\n process.env.NODE_ENV !== 'development'\n ? function () {\n return null\n }\n : devtools.ReactQueryDevtools\n\nexport const ReactQueryDevtoolsPanel: (typeof devtools)['ReactQueryDevtoolsPanel'] =\n process.env.NODE_ENV !== 'development'\n ? (function () {\n return null\n } as any)\n : devtools.ReactQueryDevtoolsPanel\n"],"names":[],"mappings":"+QAMM,WACE,OAAO,IACT,4BAKC,WACC,OAAO,IACT"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tanstack/react-query-devtools",
3
- "version": "5.0.0-alpha.1",
3
+ "version": "5.0.0-alpha.11",
4
4
  "description": "Developer tools to interact with and visualize the TanStack/react-query cache",
5
5
  "author": "tannerlinsley",
6
6
  "license": "MIT",
@@ -43,7 +43,7 @@
43
43
  "react": "^18.2.0",
44
44
  "react-dom": "^18.2.0",
45
45
  "react-error-boundary": "^3.1.4",
46
- "@tanstack/react-query": "5.0.0-alpha.1"
46
+ "@tanstack/react-query": "5.0.0-alpha.10"
47
47
  },
48
48
  "dependencies": {
49
49
  "@tanstack/match-sorter-utils": "^8.7.0",
@@ -52,13 +52,13 @@
52
52
  "peerDependencies": {
53
53
  "react": "^18.0.0",
54
54
  "react-dom": "^18.0.0",
55
- "@tanstack/react-query": "5.0.0-alpha.1"
55
+ "@tanstack/react-query": "5.0.0-alpha.10"
56
56
  },
57
57
  "scripts": {
58
58
  "clean": "rimraf ./build",
59
59
  "test:eslint": "eslint --ext .ts,.tsx ./src",
60
60
  "test:types": "tsc",
61
- "test:lib": "jest --config ./jest.config.ts",
61
+ "test:lib": "vitest run --coverage",
62
62
  "test:lib:dev": "pnpm run test:lib --watch",
63
63
  "build:types": "tsc --build && cp build/lib/index.d.ts build/lib/index.prod.d.ts"
64
64
  }
@@ -3,6 +3,7 @@ import * as React from 'react'
3
3
 
4
4
  import { chunkArray, CopyButton, DefaultRenderer } from '../Explorer'
5
5
  import { displayValue } from '../utils'
6
+ import { vi } from 'vitest'
6
7
 
7
8
  describe('Explorer', () => {
8
9
  describe('chunkArray', () => {
@@ -30,7 +31,7 @@ describe('Explorer', () => {
30
31
 
31
32
  describe('DefaultRenderer', () => {
32
33
  it('when the entry label is clicked, toggle expanded', async () => {
33
- const toggleExpanded = jest.fn()
34
+ const toggleExpanded = vi.fn()
34
35
 
35
36
  render(
36
37
  <DefaultRenderer
@@ -90,7 +91,7 @@ describe('Explorer', () => {
90
91
  })
91
92
 
92
93
  it('when the copy button is clicked but there is an error, show error state', async () => {
93
- const consoleMock = jest.spyOn(console, 'error')
94
+ const consoleMock = vi.spyOn(console, 'error')
94
95
  consoleMock.mockImplementation(() => undefined)
95
96
 
96
97
  // Mock clipboard with error state
@@ -1,7 +1,7 @@
1
1
  import * as React from 'react'
2
2
  import { fireEvent, screen, waitFor, act } from '@testing-library/react'
3
3
  import '@testing-library/jest-dom'
4
- import { useQuery } from '@tanstack/react-query'
4
+ import { useQuery, onlineManager } from '@tanstack/react-query'
5
5
  import { defaultPanelSize, sortFns } from '../utils'
6
6
  import {
7
7
  getByTextContent,
@@ -9,18 +9,27 @@ import {
9
9
  sleep,
10
10
  createQueryClient,
11
11
  } from './utils'
12
+ import { vi } from 'vitest'
13
+ import UserEvent from '@testing-library/user-event'
14
+
15
+ class CustomError extends Error {
16
+ constructor(message: string) {
17
+ super(message)
18
+ this.name = 'CustomError'
19
+ }
20
+ }
12
21
 
13
22
  Object.defineProperty(window, 'matchMedia', {
14
23
  writable: true,
15
- value: jest.fn().mockImplementation((query: string) => ({
24
+ value: vi.fn().mockImplementation((query: string) => ({
16
25
  matches: false,
17
26
  media: query,
18
27
  onchange: null,
19
- addListener: jest.fn(), // deprecated
20
- removeListener: jest.fn(), // deprecated
21
- addEventListener: jest.fn(),
22
- removeEventListener: jest.fn(),
23
- dispatchEvent: jest.fn(),
28
+ addListener: vi.fn(), // deprecated
29
+ removeListener: vi.fn(), // deprecated
30
+ addEventListener: vi.fn(),
31
+ removeEventListener: vi.fn(),
32
+ dispatchEvent: vi.fn(),
24
33
  })),
25
34
  })
26
35
 
@@ -31,8 +40,8 @@ describe('ReactQueryDevtools', () => {
31
40
  })
32
41
  it('should be able to open and close devtools', async () => {
33
42
  const { queryClient } = createQueryClient()
34
- const onCloseClick = jest.fn()
35
- const onToggleClick = jest.fn()
43
+ const onCloseClick = vi.fn()
44
+ const onToggleClick = vi.fn()
36
45
 
37
46
  function Page() {
38
47
  const { data = 'default' } = useQuery({
@@ -469,6 +478,31 @@ describe('ReactQueryDevtools', () => {
469
478
  expect(count).toBe(2)
470
479
  })
471
480
 
481
+ it('should inform onlineManager when offline mode is simulated', () => {
482
+ const { queryClient } = createQueryClient()
483
+ const online: Array<boolean> = []
484
+
485
+ const unsubscribe = onlineManager.subscribe(() => {
486
+ online.push(onlineManager.isOnline())
487
+ })
488
+
489
+ renderWithClient(queryClient, <div />, {
490
+ initialIsOpen: true,
491
+ })
492
+
493
+ fireEvent.click(
494
+ screen.getByRole('button', { name: /mock offline behavior/i }),
495
+ )
496
+
497
+ fireEvent.click(
498
+ screen.getByRole('button', { name: /restore offline mock/i }),
499
+ )
500
+
501
+ expect(online).toStrictEqual([false, true])
502
+
503
+ unsubscribe()
504
+ })
505
+
472
506
  it('should sort the queries according to the sorting filter', async () => {
473
507
  const { queryClient, queryCache } = createQueryClient()
474
508
 
@@ -861,4 +895,144 @@ describe('ReactQueryDevtools', () => {
861
895
  fireEvent.click(screen.getByRole('button', { name: /^close$/i }))
862
896
  expect(parentElement).toHaveStyle(parentPaddings)
863
897
  })
898
+
899
+ it('should simulate loading state', async () => {
900
+ const { queryClient } = createQueryClient()
901
+ let count = 0
902
+ function App() {
903
+ const { data, fetchStatus } = useQuery({
904
+ queryKey: ['key'],
905
+ queryFn: () => {
906
+ count++
907
+ return Promise.resolve('test')
908
+ },
909
+ })
910
+
911
+ return (
912
+ <div>
913
+ <h1>
914
+ {data ?? 'No data'}, {fetchStatus}
915
+ </h1>
916
+ </div>
917
+ )
918
+ }
919
+
920
+ renderWithClient(queryClient, <App />, {
921
+ initialIsOpen: true,
922
+ })
923
+
924
+ await screen.findByRole('heading', { name: /test/i })
925
+
926
+ const loadingButton = await screen.findByRole('button', {
927
+ name: 'Trigger loading',
928
+ })
929
+ fireEvent.click(loadingButton)
930
+
931
+ await waitFor(() => {
932
+ expect(screen.getByText('Restore loading')).toBeInTheDocument()
933
+ })
934
+
935
+ await waitFor(() => {
936
+ expect(screen.getByText('No data, fetching')).toBeInTheDocument()
937
+ })
938
+
939
+ fireEvent.click(screen.getByRole('button', { name: /restore loading/i }))
940
+
941
+ await waitFor(() => {
942
+ expect(screen.getByText('test, idle')).toBeInTheDocument()
943
+ })
944
+
945
+ expect(count).toBe(2)
946
+ })
947
+
948
+ it('should simulate error state', async () => {
949
+ const { queryClient } = createQueryClient()
950
+ function App() {
951
+ const { status, error } = useQuery({
952
+ queryKey: ['key'],
953
+ queryFn: () => {
954
+ return Promise.resolve('test')
955
+ },
956
+ })
957
+
958
+ return (
959
+ <div>
960
+ <h1>
961
+ {!!error ? 'Some error' : 'No error'}, {status}
962
+ </h1>
963
+ </div>
964
+ )
965
+ }
966
+
967
+ renderWithClient(queryClient, <App />, {
968
+ initialIsOpen: true,
969
+ })
970
+
971
+ const errorButton = await screen.findByRole('button', {
972
+ name: 'Trigger error',
973
+ })
974
+ fireEvent.click(errorButton)
975
+
976
+ await waitFor(() => {
977
+ expect(screen.getByText('Restore error')).toBeInTheDocument()
978
+ })
979
+
980
+ await waitFor(() => {
981
+ expect(screen.getByText('Some error, error')).toBeInTheDocument()
982
+ })
983
+
984
+ fireEvent.click(screen.getByRole('button', { name: /Restore error/i }))
985
+
986
+ await waitFor(() => {
987
+ expect(screen.getByText('No error, success')).toBeInTheDocument()
988
+ })
989
+ })
990
+
991
+ it('should can simulate a specific error', async () => {
992
+ const { queryClient } = createQueryClient()
993
+
994
+ function App() {
995
+ const { status, error } = useQuery({
996
+ queryKey: ['key'],
997
+ queryFn: () => {
998
+ return Promise.resolve('test')
999
+ },
1000
+ })
1001
+
1002
+ return (
1003
+ <div data-testid="test">
1004
+ <h1>
1005
+ {error instanceof CustomError
1006
+ ? error.message.toString()
1007
+ : 'No error'}
1008
+ , {status}
1009
+ </h1>
1010
+ </div>
1011
+ )
1012
+ }
1013
+
1014
+ renderWithClient(queryClient, <App />, {
1015
+ initialIsOpen: true,
1016
+ errorTypes: [
1017
+ {
1018
+ name: 'error1',
1019
+ initializer: () => new CustomError('error1'),
1020
+ },
1021
+ ],
1022
+ })
1023
+
1024
+ const errorOption = await screen.findByLabelText('Trigger error:')
1025
+
1026
+ UserEvent.selectOptions(errorOption, 'error1')
1027
+
1028
+ await waitFor(() => {
1029
+ expect(screen.getByText('error1, error')).toBeInTheDocument()
1030
+ })
1031
+
1032
+ fireEvent.click(screen.getByRole('button', { name: /Restore error/i }))
1033
+
1034
+ await waitFor(() => {
1035
+ expect(screen.getByText('No error, success')).toBeInTheDocument()
1036
+ })
1037
+ })
864
1038
  })
package/src/devtools.tsx CHANGED
@@ -4,6 +4,8 @@ import type {
4
4
  QueryCache,
5
5
  QueryClient,
6
6
  QueryKey as QueryKeyType,
7
+ Query,
8
+ DefaultError,
7
9
  } from '@tanstack/react-query'
8
10
  import {
9
11
  useQueryClient,
@@ -39,6 +41,18 @@ import { ThemeProvider, defaultTheme as theme } from './theme'
39
41
  import { getQueryStatusLabel, getQueryStatusColor } from './utils'
40
42
  import Explorer from './Explorer'
41
43
  import Logo from './Logo'
44
+ import { useMemo } from 'react'
45
+
46
+ export interface DevToolsErrorType {
47
+ /**
48
+ * The name of the error.
49
+ */
50
+ name: string
51
+ /**
52
+ * How the error is initialized.
53
+ */
54
+ initializer: (query: Query) => DefaultError
55
+ }
42
56
 
43
57
  export interface DevtoolsOptions {
44
58
  /**
@@ -81,6 +95,10 @@ export interface DevtoolsOptions {
81
95
  * Custom instance of QueryClient
82
96
  */
83
97
  queryClient?: QueryClient
98
+ /**
99
+ * Use this so you can define custom errors that can be shown in the devtools.
100
+ */
101
+ errorTypes?: DevToolsErrorType[]
84
102
  }
85
103
 
86
104
  interface DevtoolsPanelOptions {
@@ -129,6 +147,10 @@ interface DevtoolsPanelOptions {
129
147
  * Custom instance of QueryClient
130
148
  */
131
149
  queryClient?: QueryClient
150
+ /**
151
+ * Use this so you can define custom errors that can be shown in the devtools.
152
+ */
153
+ errorTypes?: DevToolsErrorType[]
132
154
  }
133
155
 
134
156
  export function ReactQueryDevtools({
@@ -141,6 +163,7 @@ export function ReactQueryDevtools({
141
163
  queryClient,
142
164
  styleNonce,
143
165
  panelPosition: initialPanelPosition = 'bottom',
166
+ errorTypes = [],
144
167
  }: DevtoolsOptions): React.ReactElement | null {
145
168
  const rootRef = React.useRef<HTMLDivElement>(null)
146
169
  const panelRef = React.useRef<HTMLDivElement>(null)
@@ -349,6 +372,7 @@ export function ReactQueryDevtools({
349
372
  isOpen={isResolvedOpen}
350
373
  setIsOpen={setIsOpen}
351
374
  onDragStart={(e) => handleDragStart(panelRef.current, e)}
375
+ errorTypes={errorTypes}
352
376
  />
353
377
  </ThemeProvider>
354
378
  {!isResolvedOpen ? (
@@ -439,6 +463,7 @@ export const ReactQueryDevtoolsPanel = React.forwardRef<
439
463
  showCloseButton,
440
464
  position,
441
465
  closeButtonProps = {},
466
+ errorTypes = [],
442
467
  ...panelProps
443
468
  } = props
444
469
 
@@ -611,6 +636,8 @@ export const ReactQueryDevtoolsPanel = React.forwardRef<
611
636
  style={{
612
637
  display: 'flex',
613
638
  alignItems: 'center',
639
+ flexWrap: 'wrap',
640
+ gap: '0.5em',
614
641
  }}
615
642
  >
616
643
  <Input
@@ -623,7 +650,6 @@ export const ReactQueryDevtoolsPanel = React.forwardRef<
623
650
  }}
624
651
  style={{
625
652
  flex: '1',
626
- marginRight: '.5em',
627
653
  width: '100%',
628
654
  }}
629
655
  />
@@ -663,6 +689,7 @@ export const ReactQueryDevtoolsPanel = React.forwardRef<
663
689
  } else {
664
690
  onlineManager.setOnline(false)
665
691
  setMockOffline(true)
692
+ window.dispatchEvent(new Event('offline'))
666
693
  }
667
694
  }}
668
695
  aria-label={
@@ -744,6 +771,7 @@ export const ReactQueryDevtoolsPanel = React.forwardRef<
744
771
  activeQueryHash={activeQueryHash}
745
772
  queryCache={queryCache}
746
773
  queryClient={client}
774
+ errorTypes={errorTypes}
747
775
  />
748
776
  ) : null}
749
777
 
@@ -779,10 +807,12 @@ const ActiveQuery = ({
779
807
  queryCache,
780
808
  activeQueryHash,
781
809
  queryClient,
810
+ errorTypes,
782
811
  }: {
783
812
  queryCache: QueryCache
784
813
  activeQueryHash: string
785
814
  queryClient: QueryClient
815
+ errorTypes: DevToolsErrorType[]
786
816
  }) => {
787
817
  const activeQuery = useSubscribeToQueryCache(queryCache, () =>
788
818
  queryCache.getAll().find((query) => query.queryHash === activeQueryHash),
@@ -816,10 +846,50 @@ const ActiveQuery = ({
816
846
  promise?.catch(noop)
817
847
  }
818
848
 
849
+ const currentErrorTypeName = useMemo(() => {
850
+ if (activeQuery && activeQueryState?.error) {
851
+ const errorType = errorTypes.find(
852
+ (type) =>
853
+ type.initializer(activeQuery).toString() ===
854
+ activeQueryState.error?.toString(),
855
+ )
856
+ return errorType?.name
857
+ }
858
+ return undefined
859
+ }, [activeQuery, activeQueryState?.error, errorTypes])
860
+
819
861
  if (!activeQuery || !activeQueryState) {
820
862
  return null
821
863
  }
822
864
 
865
+ const triggerError = (errorType?: DevToolsErrorType) => {
866
+ const error =
867
+ errorType?.initializer(activeQuery) ??
868
+ new Error('Unknown error from devtools')
869
+
870
+ const __previousQueryOptions = activeQuery.options
871
+
872
+ activeQuery.setState({
873
+ status: 'error',
874
+ error,
875
+ // eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion
876
+ fetchMeta: {
877
+ ...activeQuery.state.fetchMeta,
878
+ __previousQueryOptions,
879
+ } as any,
880
+ })
881
+ }
882
+
883
+ const restoreQueryAfterLoadingOrError = () => {
884
+ activeQuery.fetch(
885
+ (activeQuery.state.fetchMeta as any).__previousQueryOptions,
886
+ {
887
+ // Make sure this fetch will cancel the previous one
888
+ cancelRefetch: true,
889
+ },
890
+ )
891
+ }
892
+
823
893
  return (
824
894
  <ActiveQueryPanel>
825
895
  <div
@@ -842,7 +912,7 @@ const ActiveQuery = ({
842
912
  style={{
843
913
  marginBottom: '.5em',
844
914
  display: 'flex',
845
- alignItems: 'stretch',
915
+ alignItems: 'flex-start',
846
916
  justifyContent: 'space-between',
847
917
  }}
848
918
  >
@@ -916,6 +986,10 @@ const ActiveQuery = ({
916
986
  <div
917
987
  style={{
918
988
  padding: '0.5em',
989
+ display: 'flex',
990
+ flexWrap: 'wrap',
991
+ gap: '0.5em',
992
+ alignItems: 'flex-end',
919
993
  }}
920
994
  >
921
995
  <Button
@@ -955,7 +1029,81 @@ const ActiveQuery = ({
955
1029
  }}
956
1030
  >
957
1031
  Remove
958
- </Button>
1032
+ </Button>{' '}
1033
+ <Button
1034
+ type="button"
1035
+ onClick={() => {
1036
+ if (activeQuery.state.data === undefined) {
1037
+ restoreQueryAfterLoadingOrError()
1038
+ } else {
1039
+ const __previousQueryOptions = activeQuery.options
1040
+ // Trigger a fetch in order to trigger suspense as well.
1041
+ activeQuery.fetch({
1042
+ ...__previousQueryOptions,
1043
+ queryFn: () => {
1044
+ return new Promise(() => {
1045
+ // Never resolve
1046
+ })
1047
+ },
1048
+ gcTime: -1,
1049
+ })
1050
+ activeQuery.setState({
1051
+ data: undefined,
1052
+ status: 'pending',
1053
+ // eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion
1054
+ fetchMeta: {
1055
+ ...activeQuery.state.fetchMeta,
1056
+ __previousQueryOptions,
1057
+ } as any,
1058
+ })
1059
+ }
1060
+ }}
1061
+ style={{
1062
+ background: theme.paused,
1063
+ }}
1064
+ >
1065
+ {activeQuery.state.status === 'pending' ? 'Restore' : 'Trigger'}{' '}
1066
+ loading
1067
+ </Button>{' '}
1068
+ {errorTypes.length === 0 || activeQuery.state.status === 'error' ? (
1069
+ <Button
1070
+ type="button"
1071
+ onClick={() => {
1072
+ if (!activeQuery.state.error) {
1073
+ triggerError()
1074
+ } else {
1075
+ queryClient.resetQueries(activeQuery)
1076
+ }
1077
+ }}
1078
+ style={{
1079
+ background: theme.danger,
1080
+ }}
1081
+ >
1082
+ {activeQuery.state.status === 'error' ? 'Restore' : 'Trigger'} error
1083
+ </Button>
1084
+ ) : (
1085
+ <label>
1086
+ Trigger error:
1087
+ <Select
1088
+ value={currentErrorTypeName ?? ''}
1089
+ style={{ marginInlineStart: '.5em' }}
1090
+ onChange={(e) => {
1091
+ const errorType = errorTypes.find(
1092
+ (t) => t.name === e.target.value,
1093
+ )
1094
+
1095
+ triggerError(errorType)
1096
+ }}
1097
+ >
1098
+ <option key="" value="" />
1099
+ {errorTypes.map((errorType) => (
1100
+ <option key={errorType.name} value={errorType.name}>
1101
+ {errorType.name}
1102
+ </option>
1103
+ ))}
1104
+ </Select>
1105
+ </label>
1106
+ )}
959
1107
  </div>
960
1108
  <div
961
1109
  style={{
package/src/index.ts CHANGED
@@ -1,3 +1,5 @@
1
+ 'use client'
2
+
1
3
  import * as devtools from './devtools'
2
4
 
3
5
  export const ReactQueryDevtools: (typeof devtools)['ReactQueryDevtools'] =
@@ -50,7 +50,9 @@ export const Button = styled('button', (props, theme) => ({
50
50
  }))
51
51
 
52
52
  export const QueryKeys = styled('span', {
53
- display: 'inline-block',
53
+ display: 'flex',
54
+ flexWrap: 'wrap',
55
+ gap: '0.5em',
54
56
  fontSize: '0.9em',
55
57
  })
56
58