diff --git a/packages/query-devtools/src/Devtools.tsx b/packages/query-devtools/src/Devtools.tsx index df2a6edf6a..4db77d7737 100644 --- a/packages/query-devtools/src/Devtools.tsx +++ b/packages/query-devtools/src/Devtools.tsx @@ -1700,6 +1700,8 @@ const QueryDetails = () => { const queryClient = useQueryDevtoolsContext().client const [restoringLoading, setRestoringLoading] = createSignal(false) + const [dataMode, setDataMode] = createSignal<'view' | 'edit'>('view') + const [dataEditError, setDataEditError] = createSignal(false) const errorTypes = createMemo(() => { return useQueryDevtoolsContext().errorTypes || [] @@ -2047,22 +2049,85 @@ const QueryDetails = () => {
- Data Explorer -
-
- + Data {dataMode() === 'view' ? 'Explorer' : 'Editor'}
+ +
+ setDataMode('edit')} + activeQuery={activeQuery()} + /> +
+
+ +
{ + e.preventDefault() + const formData = new FormData(e.currentTarget) + const data = formData.get('data') as string + try { + const parsedData = JSON.parse(data) + activeQuery()!.setState({ + ...activeQuery()!.state, + data: parsedData, + }) + setDataMode('view') + } catch (error) { + setDataEditError(true) + } + }} + > + +
+ + {dataEditError() ? 'Invalid Value' : ''} + +
+ + +
+
+
+
Query Explorer
@@ -3318,6 +3383,74 @@ const stylesFactory = ( } } `, + devtoolsEditForm: css` + padding: ${size[2]}; + & > [data-error='true'] { + outline: 2px solid ${t(colors.red[200], colors.red[800])}; + outline-offset: 2px; + border-radius: ${border.radius.xs}; + } + `, + devtoolsEditTextarea: css` + width: 100%; + max-height: 500px; + font-family: 'Fira Code', monospace; + font-size: ${font.size.xs}; + border-radius: ${border.radius.sm}; + field-sizing: content; + padding: ${size[2]}; + background-color: ${t(colors.gray[100], colors.darkGray[800])}; + color: ${t(colors.gray[900], colors.gray[100])}; + border: 1px solid ${t(colors.gray[200], colors.gray[700])}; + resize: none; + &:focus { + outline-offset: 2px; + border-radius: ${border.radius.xs}; + outline: 2px solid ${t(colors.blue[200], colors.blue[800])}; + } + `, + devtoolsEditFormActions: css` + display: flex; + justify-content: space-between; + gap: ${size[2]}; + align-items: center; + padding-top: ${size[1]}; + font-size: ${font.size.xs}; + `, + devtoolsEditFormError: css` + color: ${t(colors.red[700], colors.red[500])}; + `, + devtoolsEditFormActionContainer: css` + display: flex; + gap: ${size[2]}; + `, + devtoolsEditFormAction: css` + font-family: ui-sans-serif, Inter, system-ui, sans-serif, sans-serif; + font-size: ${font.size.xs}; + padding: ${size[1]} ${tokens.size[2]}; + display: flex; + border-radius: ${border.radius.sm}; + background-color: ${t(colors.gray[100], colors.darkGray[600])}; + border: 1px solid ${t(colors.gray[300], colors.darkGray[400])}; + align-items: center; + gap: ${size[2]}; + font-weight: ${font.weight.medium}; + line-height: ${font.lineHeight.xs}; + cursor: pointer; + &:focus-visible { + outline-offset: 2px; + border-radius: ${border.radius.xs}; + outline: 2px solid ${colors.blue[800]}; + } + &:hover { + background-color: ${t(colors.gray[200], colors.darkGray[500])}; + } + + &:disabled { + opacity: 0.6; + cursor: not-allowed; + } + `, } } diff --git a/packages/query-devtools/src/Explorer.tsx b/packages/query-devtools/src/Explorer.tsx index 923eb016b3..e1bce213fb 100644 --- a/packages/query-devtools/src/Explorer.tsx +++ b/packages/query-devtools/src/Explorer.tsx @@ -1,4 +1,4 @@ -import { stringify } from 'superjson' +import { serialize, stringify } from 'superjson' import { clsx as cx } from 'clsx' import { Index, Match, Show, Switch, createMemo, createSignal } from 'solid-js' import { Key } from '@solid-primitives/keyed' @@ -9,7 +9,15 @@ import { displayValue, updateNestedDataByPath, } from './utils' -import { Check, CopiedCopier, Copier, ErrorCopier, List, Trash } from './icons' +import { + Check, + CopiedCopier, + Copier, + ErrorCopier, + List, + Pencil, + Trash, +} from './icons' import { useQueryDevtoolsContext, useTheme } from './contexts' import type { Query } from '@tanstack/query-core' @@ -243,6 +251,7 @@ type ExplorerProps = { dataPath?: Array activeQuery?: Query itemsDeletable?: boolean + onEdit?: () => void } function isIterable(x: any): x is Iterable { @@ -351,6 +360,19 @@ export default function Explorer(props: ExplorerProps) { dataPath={currentDataPath} /> + + + + diff --git a/packages/query-devtools/src/icons/index.tsx b/packages/query-devtools/src/icons/index.tsx index c8e0722c2c..7075634de8 100644 --- a/packages/query-devtools/src/icons/index.tsx +++ b/packages/query-devtools/src/icons/index.tsx @@ -309,6 +309,26 @@ export function Copier() { ) } +export function Pencil() { + return ( + + + + ) +} + export function CopiedCopier(props: { theme: 'light' | 'dark' }) { return (