From 4121baf6bac82e943474b906b0c4fa7fe07f53ec Mon Sep 17 00:00:00 2001 From: Alem Tuzlak Date: Tue, 12 Aug 2025 11:58:15 +0200 Subject: [PATCH 1/4] feat: add json tree --- .changeset/thin-cougars-fly.md | 7 ++ packages/devtools-ui/src/components/tree.tsx | 75 +++++++++++++++++++ packages/devtools-ui/src/index.ts | 1 + packages/devtools-ui/src/styles/use-styles.ts | 25 +++++++ packages/react-devtools/src/devtools.tsx | 2 +- packages/solid-devtools/src/devtools.tsx | 2 +- 6 files changed, 110 insertions(+), 2 deletions(-) create mode 100644 .changeset/thin-cougars-fly.md create mode 100644 packages/devtools-ui/src/components/tree.tsx diff --git a/.changeset/thin-cougars-fly.md b/.changeset/thin-cougars-fly.md new file mode 100644 index 000000000..c29619646 --- /dev/null +++ b/.changeset/thin-cougars-fly.md @@ -0,0 +1,7 @@ +--- +'@tanstack/react-devtools': minor +'@tanstack/solid-devtools': minor +'@tanstack/devtools-ui': minor +--- + +Added json tree to devtools-ui and adjusted the width for the plugin renderers diff --git a/packages/devtools-ui/src/components/tree.tsx b/packages/devtools-ui/src/components/tree.tsx new file mode 100644 index 000000000..8567d5a94 --- /dev/null +++ b/packages/devtools-ui/src/components/tree.tsx @@ -0,0 +1,75 @@ +import { For } from "solid-js"; +import { useStyles } from "../styles/use-styles"; + +export function JsonTree(props: { value: any }){ + return +} + +export function JsonValue(props: { value: any; keyName?: string, isRoot?: boolean }) { + const { value, keyName, isRoot = false } = props; + const styles = useStyles(); + + if (typeof value === 'string') { + return + {keyName && "{keyName}": } + "{value}" + , + ; + } + if (typeof value === 'number') { + return + {keyName && "{keyName}": } + {value} + , + ; + } + if (typeof value === 'boolean') { + return + + {keyName && "{keyName}": } + {String(value)} + + , + ; + } + if (value === null) { + return + {keyName && "{keyName}": } + null + , + ; + } + if (value === undefined) { + return + {keyName && "{keyName}": } + undefined + , + ; + } + if (Array.isArray(value)) { + return + {keyName && "{keyName}": } + [ + {(item) => <> + + } + + ] + , + ; + } + if (typeof value === 'object') { + const keys = Object.keys(value); + return + {keyName && "{keyName}": } + {'{'} + {(k,) => <> + + } + + {'}'} + + ; + } + return ; +} \ No newline at end of file diff --git a/packages/devtools-ui/src/index.ts b/packages/devtools-ui/src/index.ts index dfaa26667..8ed1f72a0 100644 --- a/packages/devtools-ui/src/index.ts +++ b/packages/devtools-ui/src/index.ts @@ -2,3 +2,4 @@ export { Checkbox } from './components/checkbox' export { Input } from './components/input' export { Select } from './components/select' export { TanStackLogo } from './components/logo' +export { JsonTree } from './components/tree' \ No newline at end of file diff --git a/packages/devtools-ui/src/styles/use-styles.ts b/packages/devtools-ui/src/styles/use-styles.ts index 269260778..e87fb79a1 100644 --- a/packages/devtools-ui/src/styles/use-styles.ts +++ b/packages/devtools-ui/src/styles/use-styles.ts @@ -186,6 +186,31 @@ const stylesFactory = () => { font-size: 0.8rem; line-height: 1.3; `, + tree: { + valueString: css` + color: ${colors.green[400]}; + `, + valueNumber: css` + color: ${colors.yellow[400]}; + `, + valueBoolean: css` + color: ${colors.pink[400]}; + `, + valueNull: css` + color: ${colors.gray[400]}; + font-style: italic; + `, + valueKey: css` + color: ${colors.blue[300]}; + `, + valueBraces: css` + color: ${colors.gray[500]}; + `, + valueContainer: (isRoot: boolean) => css` + display: block; + margin-left: ${isRoot ? '0' : '1rem'}; + ` + } } } diff --git a/packages/react-devtools/src/devtools.tsx b/packages/react-devtools/src/devtools.tsx index c988c289b..28f393ff7 100644 --- a/packages/react-devtools/src/devtools.tsx +++ b/packages/react-devtools/src/devtools.tsx @@ -153,7 +153,7 @@ export const TanstackDevtools = ({ return ( <> -
+
{pluginContainer && PluginComponent ? createPortal(<>{PluginComponent}, pluginContainer) : null} diff --git a/packages/solid-devtools/src/devtools.tsx b/packages/solid-devtools/src/devtools.tsx index 795a6943a..dca5c12a3 100644 --- a/packages/solid-devtools/src/devtools.tsx +++ b/packages/solid-devtools/src/devtools.tsx @@ -126,5 +126,5 @@ export const TanstackDevtools = ({ }) } }) - return
+ return
} From a747ef4808490866bd8ee26d47debd55301bafbc Mon Sep 17 00:00:00 2001 From: Alem Tuzlak Date: Tue, 12 Aug 2025 12:11:22 +0200 Subject: [PATCH 2/4] chore: fix commas and improve code --- packages/devtools-ui/src/components/tree.tsx | 135 ++++++++++--------- 1 file changed, 70 insertions(+), 65 deletions(-) diff --git a/packages/devtools-ui/src/components/tree.tsx b/packages/devtools-ui/src/components/tree.tsx index 8567d5a94..78462613c 100644 --- a/packages/devtools-ui/src/components/tree.tsx +++ b/packages/devtools-ui/src/components/tree.tsx @@ -1,75 +1,80 @@ import { For } from "solid-js"; import { useStyles } from "../styles/use-styles"; -export function JsonTree(props: { value: any }){ +export function JsonTree(props: { value: any }) { return } -export function JsonValue(props: { value: any; keyName?: string, isRoot?: boolean }) { - const { value, keyName, isRoot = false } = props; +export function JsonValue(props: { value: any; keyName?: string, isRoot?: boolean, isLastKey?: boolean }) { + const { value, keyName, isRoot = false, isLastKey } = props; const styles = useStyles(); - if (typeof value === 'string') { - return - {keyName && "{keyName}": } - "{value}" - , - ; - } - if (typeof value === 'number') { - return - {keyName && "{keyName}": } - {value} - , - ; - } - if (typeof value === 'boolean') { - return - - {keyName && "{keyName}": } - {String(value)} - - , - ; - } - if (value === null) { - return - {keyName && "{keyName}": } - null - , - ; - } - if (value === undefined) { - return - {keyName && "{keyName}": } - undefined - , - ; - } - if (Array.isArray(value)) { - return - {keyName && "{keyName}": } - [ - {(item) => <> - - } - - ] - , - ; - } - if (typeof value === 'object') { - const keys = Object.keys(value); - return - {keyName && "{keyName}": } - {'{'} - {(k,) => <> - - } - - {'}'} + return + {(() => { + if (typeof value === 'string') { + return + {keyName && "{keyName}": } + "{value}" + + + } + if (typeof value === 'number') { + return {keyName && "{keyName}": } + {value} + + + } + if (typeof value === 'boolean') { + return + {keyName && "{keyName}": } + {String(value)} + + + } + if (value === null) { + return + {keyName && "{keyName}": } + null + + + } + if (value === undefined) { + return + {keyName && "{keyName}": } + undefined + ; + } + if (Array.isArray(value)) { + + return {keyName && "{keyName}": } + [ + {(item, i) => { + const isLastKey = i() === value.length - 1; + return <> + + + }} + + ] + + } + if (typeof value === 'object') { + const keys = Object.keys(value); + const lastKeyName = keys[keys.length - 1]; + return + {keyName && "{keyName}": } + {'{'} + {(k,) => <> + + } + + {'}'} + + + } + return ; + })()} + {isLastKey || isRoot ? '' : ,} + - ; - } - return ; } \ No newline at end of file From f8b5345c46cbe816fe35b3f13e30f20a2a840905 Mon Sep 17 00:00:00 2001 From: "autofix-ci[bot]" <114827586+autofix-ci[bot]@users.noreply.github.com> Date: Tue, 12 Aug 2025 10:12:23 +0000 Subject: [PATCH 3/4] ci: apply automated fixes --- packages/devtools-ui/src/components/tree.tsx | 202 +++++++++++------- packages/devtools-ui/src/index.ts | 2 +- packages/devtools-ui/src/styles/use-styles.ts | 34 +-- packages/react-devtools/src/devtools.tsx | 2 +- packages/solid-devtools/src/devtools.tsx | 2 +- 5 files changed, 148 insertions(+), 94 deletions(-) diff --git a/packages/devtools-ui/src/components/tree.tsx b/packages/devtools-ui/src/components/tree.tsx index 78462613c..ee0ccae8f 100644 --- a/packages/devtools-ui/src/components/tree.tsx +++ b/packages/devtools-ui/src/components/tree.tsx @@ -1,80 +1,134 @@ -import { For } from "solid-js"; -import { useStyles } from "../styles/use-styles"; +import { For } from 'solid-js' +import { useStyles } from '../styles/use-styles' export function JsonTree(props: { value: any }) { return } -export function JsonValue(props: { value: any; keyName?: string, isRoot?: boolean, isLastKey?: boolean }) { - const { value, keyName, isRoot = false, isLastKey } = props; - const styles = useStyles(); +export function JsonValue(props: { + value: any + keyName?: string + isRoot?: boolean + isLastKey?: boolean +}) { + const { value, keyName, isRoot = false, isLastKey } = props + const styles = useStyles() - return - {(() => { - if (typeof value === 'string') { - return - {keyName && "{keyName}": } - "{value}" - - - } - if (typeof value === 'number') { - return {keyName && "{keyName}": } - {value} - - - } - if (typeof value === 'boolean') { - return - {keyName && "{keyName}": } - {String(value)} - - - } - if (value === null) { - return - {keyName && "{keyName}": } - null - - - } - if (value === undefined) { - return - {keyName && "{keyName}": } - undefined - ; - } - if (Array.isArray(value)) { - - return {keyName && "{keyName}": } - [ - {(item, i) => { - const isLastKey = i() === value.length - 1; - return <> - - - }} - - ] - - } - if (typeof value === 'object') { - const keys = Object.keys(value); - const lastKeyName = keys[keys.length - 1]; - return - {keyName && "{keyName}": } - {'{'} - {(k,) => <> - - } - - {'}'} - - - } - return ; - })()} - {isLastKey || isRoot ? '' : ,} - - -} \ No newline at end of file + return ( + + {(() => { + if (typeof value === 'string') { + return ( + + {keyName && ( + + "{keyName}":{' '} + + )} + "{value}" + + ) + } + if (typeof value === 'number') { + return ( + + {keyName && ( + + "{keyName}":{' '} + + )} + {value} + + ) + } + if (typeof value === 'boolean') { + return ( + + {keyName && ( + + "{keyName}":{' '} + + )} + {String(value)} + + ) + } + if (value === null) { + return ( + + {keyName && ( + + "{keyName}":{' '} + + )} + null + + ) + } + if (value === undefined) { + return ( + + {keyName && ( + + "{keyName}":{' '} + + )} + undefined + + ) + } + if (Array.isArray(value)) { + return ( + + {keyName && ( + + "{keyName}":{' '} + + )} + [ + + {(item, i) => { + const isLastKey = i() === value.length - 1 + return ( + <> + + + ) + }} + + ] + + ) + } + if (typeof value === 'object') { + const keys = Object.keys(value) + const lastKeyName = keys[keys.length - 1] + return ( + + {keyName && ( + + "{keyName}":{' '} + + )} + {'{'} + + {(k) => ( + <> + + + )} + + {'}'} + + ) + } + return + })()} + {isLastKey || isRoot ? '' : ,} + + ) +} diff --git a/packages/devtools-ui/src/index.ts b/packages/devtools-ui/src/index.ts index 8ed1f72a0..ccbd745c7 100644 --- a/packages/devtools-ui/src/index.ts +++ b/packages/devtools-ui/src/index.ts @@ -2,4 +2,4 @@ export { Checkbox } from './components/checkbox' export { Input } from './components/input' export { Select } from './components/select' export { TanStackLogo } from './components/logo' -export { JsonTree } from './components/tree' \ No newline at end of file +export { JsonTree } from './components/tree' diff --git a/packages/devtools-ui/src/styles/use-styles.ts b/packages/devtools-ui/src/styles/use-styles.ts index e87fb79a1..919ccf483 100644 --- a/packages/devtools-ui/src/styles/use-styles.ts +++ b/packages/devtools-ui/src/styles/use-styles.ts @@ -188,29 +188,29 @@ const stylesFactory = () => { `, tree: { valueString: css` - color: ${colors.green[400]}; - `, + color: ${colors.green[400]}; + `, valueNumber: css` - color: ${colors.yellow[400]}; - `, + color: ${colors.yellow[400]}; + `, valueBoolean: css` - color: ${colors.pink[400]}; - `, + color: ${colors.pink[400]}; + `, valueNull: css` - color: ${colors.gray[400]}; - font-style: italic; - `, + color: ${colors.gray[400]}; + font-style: italic; + `, valueKey: css` - color: ${colors.blue[300]}; - `, + color: ${colors.blue[300]}; + `, valueBraces: css` - color: ${colors.gray[500]}; - `, + color: ${colors.gray[500]}; + `, valueContainer: (isRoot: boolean) => css` - display: block; - margin-left: ${isRoot ? '0' : '1rem'}; - ` - } + display: block; + margin-left: ${isRoot ? '0' : '1rem'}; + `, + }, } } diff --git a/packages/react-devtools/src/devtools.tsx b/packages/react-devtools/src/devtools.tsx index 28f393ff7..60f4d3d7c 100644 --- a/packages/react-devtools/src/devtools.tsx +++ b/packages/react-devtools/src/devtools.tsx @@ -153,7 +153,7 @@ export const TanstackDevtools = ({ return ( <> -
+
{pluginContainer && PluginComponent ? createPortal(<>{PluginComponent}, pluginContainer) : null} diff --git a/packages/solid-devtools/src/devtools.tsx b/packages/solid-devtools/src/devtools.tsx index dca5c12a3..739aa6e27 100644 --- a/packages/solid-devtools/src/devtools.tsx +++ b/packages/solid-devtools/src/devtools.tsx @@ -126,5 +126,5 @@ export const TanstackDevtools = ({ }) } }) - return
+ return
} From 25ab73e05bf61bb5d955c41405e7e868e7df8e9a Mon Sep 17 00:00:00 2001 From: Alem Tuzlak Date: Tue, 12 Aug 2025 12:14:51 +0200 Subject: [PATCH 4/4] chore: fix tests --- packages/devtools-ui/src/components/tree.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/devtools-ui/src/components/tree.tsx b/packages/devtools-ui/src/components/tree.tsx index ee0ccae8f..ba048d36b 100644 --- a/packages/devtools-ui/src/components/tree.tsx +++ b/packages/devtools-ui/src/components/tree.tsx @@ -5,7 +5,7 @@ export function JsonTree(props: { value: any }) { return } -export function JsonValue(props: { +function JsonValue(props: { value: any keyName?: string isRoot?: boolean