From 46793306058ab6d1dc11c32f7162c8c0ca966483 Mon Sep 17 00:00:00 2001 From: Alem Tuzlak Date: Wed, 17 Sep 2025 17:32:26 +0200 Subject: [PATCH 1/3] feat: add expansion depth to json tree --- .changeset/silent-beds-create.md | 5 + packages/devtools-ui/src/components/tree.tsx | 232 ++++++++++-------- packages/devtools-ui/src/styles/use-styles.ts | 13 +- 3 files changed, 146 insertions(+), 104 deletions(-) create mode 100644 .changeset/silent-beds-create.md diff --git a/.changeset/silent-beds-create.md b/.changeset/silent-beds-create.md new file mode 100644 index 00000000..b583e2b7 --- /dev/null +++ b/.changeset/silent-beds-create.md @@ -0,0 +1,5 @@ +--- +'@tanstack/devtools-ui': patch +--- + +Improvements to the json tree component, now supports expansion length config diff --git a/packages/devtools-ui/src/components/tree.tsx b/packages/devtools-ui/src/components/tree.tsx index b8a4e0d6..3e31113e 100644 --- a/packages/devtools-ui/src/components/tree.tsx +++ b/packages/devtools-ui/src/components/tree.tsx @@ -3,99 +3,10 @@ import clsx from 'clsx' import { css, useStyles } from '../styles/use-styles' import { CopiedCopier, Copier, ErrorCopier } from './icons' -export function JsonTree(props: { value: any; copyable?: boolean }) { - return +export function JsonTree(props: { value: any; copyable?: boolean, defaultExpansionDepth?: number }) { + return } -type CopyState = 'NoCopy' | 'SuccessCopy' | 'ErrorCopy' - -const CopyButton = (props: { value: unknown }) => { - const styles = useStyles() - const [copyState, setCopyState] = createSignal('NoCopy') - return ( - - ) -} - -const Expander = (props: { expanded: boolean }) => { - const styles = useStyles() - return ( - - - - - - ) -} function JsonValue(props: { value: any @@ -103,8 +14,10 @@ function JsonValue(props: { isRoot?: boolean isLastKey?: boolean copyable?: boolean + defaultExpansionDepth: number + depth: number }) { - const { value, keyName, isRoot = false, isLastKey, copyable } = props + const { value, keyName, isRoot = false, isLastKey, copyable, defaultExpansionDepth, depth } = props const styles = useStyles() return ( @@ -137,12 +50,12 @@ function JsonValue(props: { } if (Array.isArray(value)) { return ( - + ) } if (typeof value === 'object') { return ( - + ) } return @@ -161,16 +74,32 @@ const ArrayValue = ({ value, keyName, copyable, + defaultExpansionDepth, + depth }: { value: Array copyable?: boolean keyName?: string + defaultExpansionDepth: number + depth: number }) => { const styles = useStyles() - const [expanded, setExpanded] = createSignal(true) + const [expanded, setExpanded] = createSignal(depth <= defaultExpansionDepth) + + if (value.length === 0) { + return ( + {keyName && + "{keyName}":{' '} + } + [] + ) + } return ( - + setExpanded(!expanded())} expanded={expanded()} /> {keyName && ( { @@ -195,6 +124,8 @@ const ArrayValue = ({ copyable={copyable} value={item} isLastKey={isLastKey} + defaultExpansionDepth={defaultExpansionDepth} + depth={depth + 1} /> ) }} @@ -222,19 +153,31 @@ const ObjectValue = ({ value, keyName, copyable, + defaultExpansionDepth, + depth }: { value: Record keyName?: string copyable?: boolean + defaultExpansionDepth: number + depth: number }) => { const styles = useStyles() - const [expanded, setExpanded] = createSignal(true) + const [expanded, setExpanded] = createSignal(depth <= defaultExpansionDepth) const keys = Object.keys(value) const lastKeyName = keys[keys.length - 1] + if (keys.length === 0) { + return ( + {keyName && + "{keyName}":{' '} + } + {"{}"} + ) + } return ( - {keyName && } + {keyName && setExpanded(!expanded())} expanded={expanded()} />} {keyName && ( { @@ -259,6 +202,8 @@ const ObjectValue = ({ keyName={k} isLastKey={lastKeyName === k} copyable={copyable} + defaultExpansionDepth={defaultExpansionDepth} + depth={depth + 1} /> )} @@ -281,3 +226,94 @@ const ObjectValue = ({ ) } + +type CopyState = 'NoCopy' | 'SuccessCopy' | 'ErrorCopy' + +const CopyButton = (props: { value: unknown }) => { + const styles = useStyles() + const [copyState, setCopyState] = createSignal('NoCopy') + + return ( + + ) +} + +const Expander = (props: { expanded: boolean, onClick: () => void }) => { + const styles = useStyles() + return ( + + + + + + ) +} \ 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 9155a379..48435118 100644 --- a/packages/devtools-ui/src/styles/use-styles.ts +++ b/packages/devtools-ui/src/styles/use-styles.ts @@ -317,9 +317,9 @@ const stylesFactory = (theme: Theme = 'dark') => { height: ${tokens.size[1.5]}; border-radius: ${tokens.border.radius.full}; background-color: ${t( - tokens.colors[color][500], - tokens.colors[color][500], - )}; + tokens.colors[color][500], + tokens.colors[color][500], + )}; `, base: css` display: flex; @@ -393,6 +393,7 @@ const stylesFactory = (theme: Theme = 'dark') => { `, expander: css` position: absolute; + cursor: pointer; left: -16px; top: 3px; & path { @@ -538,9 +539,9 @@ const stylesFactory = (theme: Theme = 'dark') => { border: 1px solid ${t(colors.gray[300], colors.gray[700])}; border-radius: 0.75rem; box-shadow: ${t( - '0 1px 3px rgba(0,0,0,0.06)', - '0 1px 3px rgba(0,0,0,0.18)', - )}; + '0 1px 3px rgba(0,0,0,0.06)', + '0 1px 3px rgba(0,0,0,0.18)', + )}; `, title: css` font-size: 1.125rem; From 67d5ff1a1777bde4ddfdc65d77f5c67690f71ac8 Mon Sep 17 00:00:00 2001 From: "autofix-ci[bot]" <114827586+autofix-ci[bot]@users.noreply.github.com> Date: Wed, 17 Sep 2025 15:34:34 +0000 Subject: [PATCH 2/3] ci: apply automated fixes --- packages/devtools-ui/src/components/tree.tsx | 149 ++++++++++++------ packages/devtools-ui/src/styles/use-styles.ts | 12 +- 2 files changed, 103 insertions(+), 58 deletions(-) diff --git a/packages/devtools-ui/src/components/tree.tsx b/packages/devtools-ui/src/components/tree.tsx index 3e31113e..546d8842 100644 --- a/packages/devtools-ui/src/components/tree.tsx +++ b/packages/devtools-ui/src/components/tree.tsx @@ -3,11 +3,22 @@ import clsx from 'clsx' import { css, useStyles } from '../styles/use-styles' import { CopiedCopier, Copier, ErrorCopier } from './icons' -export function JsonTree(props: { value: any; copyable?: boolean, defaultExpansionDepth?: number }) { - return +export function JsonTree(props: { + value: any + copyable?: boolean + defaultExpansionDepth?: number +}) { + return ( + + ) } - function JsonValue(props: { value: any keyName?: string @@ -17,7 +28,15 @@ function JsonValue(props: { defaultExpansionDepth: number depth: number }) { - const { value, keyName, isRoot = false, isLastKey, copyable, defaultExpansionDepth, depth } = props + const { + value, + keyName, + isRoot = false, + isLastKey, + copyable, + defaultExpansionDepth, + depth, + } = props const styles = useStyles() return ( @@ -50,12 +69,24 @@ function JsonValue(props: { } if (Array.isArray(value)) { return ( - + ) } if (typeof value === 'object') { return ( - + ) } return @@ -75,7 +106,7 @@ const ArrayValue = ({ keyName, copyable, defaultExpansionDepth, - depth + depth, }: { value: Array copyable?: boolean @@ -87,19 +118,23 @@ const ArrayValue = ({ const [expanded, setExpanded] = createSignal(depth <= defaultExpansionDepth) if (value.length === 0) { - return ( - {keyName && - "{keyName}":{' '} - } - [] - ) + return ( + + {keyName && ( + + "{keyName}":{' '} + + )} + [] + + ) } return ( - setExpanded(!expanded())} expanded={expanded()} /> + setExpanded(!expanded())} + expanded={expanded()} + /> {keyName && ( { @@ -154,7 +189,7 @@ const ObjectValue = ({ keyName, copyable, defaultExpansionDepth, - depth + depth, }: { value: Record keyName?: string @@ -168,16 +203,25 @@ const ObjectValue = ({ const lastKeyName = keys[keys.length - 1] if (keys.length === 0) { - return ( - {keyName && - "{keyName}":{' '} - } - {"{}"} - ) + return ( + + {keyName && ( + + "{keyName}":{' '} + + )} + {'{}'} + + ) } return ( - {keyName && setExpanded(!expanded())} expanded={expanded()} />} + {keyName && ( + setExpanded(!expanded())} + expanded={expanded()} + /> + )} {keyName && ( { @@ -237,33 +281,34 @@ const CopyButton = (props: { value: unknown }) => {