diff --git a/src-web/components/RequestPane.tsx b/src-web/components/RequestPane.tsx
index a8c33575..a942dd4a 100644
--- a/src-web/components/RequestPane.tsx
+++ b/src-web/components/RequestPane.tsx
@@ -1,5 +1,4 @@
import classnames from 'classnames';
-import { act } from 'react-dom/test-utils';
import { useActiveRequest } from '../hooks/useActiveRequest';
import { useSendRequest } from '../hooks/useSendRequest';
import { useUpdateRequest } from '../hooks/useUpdateRequest';
@@ -67,7 +66,6 @@ export function RequestPane({ fullHeight, className }: Props) {
key={activeRequest.id}
useTemplating
className="!bg-gray-50"
- heightMode={fullHeight ? 'full' : 'auto'}
defaultValue={activeRequest.body ?? ''}
contentType="application/json"
onChange={(body) => updateRequest.mutate({ body })}
@@ -78,7 +76,6 @@ export function RequestPane({ fullHeight, className }: Props) {
useTemplating
className="!bg-gray-50"
defaultValue={activeRequest?.body ?? ''}
- heightMode={fullHeight ? 'full' : 'auto'}
onChange={(body) => updateRequest.mutate({ body })}
/>
) : (
diff --git a/src-web/components/Sidebar.tsx b/src-web/components/Sidebar.tsx
index cb74577c..62da5092 100644
--- a/src-web/components/Sidebar.tsx
+++ b/src-web/components/Sidebar.tsx
@@ -26,7 +26,7 @@ export function Sidebar({ className }: Props) {
diff --git a/src-web/components/UrlBar.tsx b/src-web/components/UrlBar.tsx
index 099a45af..cbff485e 100644
--- a/src-web/components/UrlBar.tsx
+++ b/src-web/components/UrlBar.tsx
@@ -1,5 +1,5 @@
import { Button } from './core/Button';
-import { DropdownMenuRadio } from './core/Dropdown';
+import { DropdownMenuRadio, DropdownMenuTrigger } from './core/Dropdown';
import { IconButton } from './core/IconButton';
import { Input } from './core/Input';
@@ -45,9 +45,11 @@ export function UrlBar({ sendRequest, loading, onMethodChange, method, onUrlChan
{ label: 'HEAD', value: 'HEAD' },
]}
>
-
+
+
+
}
rightSlot={
diff --git a/src-web/components/Workspace.tsx b/src-web/components/Workspace.tsx
index f191034c..075f21d9 100644
--- a/src-web/components/Workspace.tsx
+++ b/src-web/components/Workspace.tsx
@@ -10,7 +10,7 @@ import { useActiveRequest } from '../hooks/useActiveRequest';
export default function Workspace() {
const activeRequest = useActiveRequest();
const { width } = useWindowSize();
- const isH = width > 900;
+ const isSideBySide = width > 900;
return (
@@ -26,12 +26,12 @@ export default function Workspace() {
-
+
diff --git a/src-web/components/core/Divider.tsx b/src-web/components/core/Divider.tsx
index 0e1a194e..522ca267 100644
--- a/src-web/components/core/Divider.tsx
+++ b/src-web/components/core/Divider.tsx
@@ -12,7 +12,7 @@ export function Divider({ className, orientation = 'horizontal', decorative }: P
(onChange);
+ useEffect(() => {
+ handleChange.current = onChange;
+ }, [onChange]);
+
+ // Use ref so we can update the onChange handler without re-initializing the editor
+ const handleFocus = useRef<_EditorProps['onFocus']>(onFocus);
+ useEffect(() => {
+ handleFocus.current = onFocus;
+ }, [onFocus]);
+
// Update language extension when contentType changes
useEffect(() => {
if (cm.current === null) return;
@@ -69,11 +80,11 @@ export function _Editor({
langHolder.of(langExt),
...getExtensions({
container: el,
+ onChange: handleChange,
+ onFocus: handleFocus,
readOnly,
placeholder,
singleLine,
- onChange,
- onFocus,
contentType,
useTemplating,
}),
@@ -91,6 +102,7 @@ export function _Editor({
return (
- {contentType?.includes('graphql') && (
- {
- const doc = cm.current?.view.state.doc ?? '';
- const insert = formatSdl(doc.toString());
- cm.current?.view.dispatch({ changes: { from: 0, to: doc.length, insert } });
- }}
- />
- )}
-
+ />
);
}
@@ -125,14 +125,12 @@ function getExtensions({
useTemplating,
}: Pick<
_EditorProps,
- | 'singleLine'
- | 'onChange'
- | 'contentType'
- | 'useTemplating'
- | 'placeholder'
- | 'readOnly'
- | 'onFocus'
-> & { container: HTMLDivElement | null }) {
+ 'singleLine' | 'contentType' | 'useTemplating' | 'placeholder' | 'readOnly'
+> & {
+ container: HTMLDivElement | null;
+ onChange: MutableRefObject<_EditorProps['onChange']>;
+ onFocus: MutableRefObject<_EditorProps['onFocus']>;
+}) {
const ext = getLanguageExtension({ contentType, useTemplating });
// TODO: Ensure tooltips render inside the dialog if we are in one.
@@ -172,14 +170,14 @@ function getExtensions({
// Handle onFocus
EditorView.domEventHandlers({
focus: () => {
- onFocus?.();
+ onFocus.current?.();
},
}),
// Handle onChange
EditorView.updateListener.of((update) => {
- if (typeof onChange === 'function' && update.docChanged) {
- onChange(update.state.doc.toString());
+ if (onChange && update.docChanged) {
+ onChange.current?.(update.state.doc.toString());
}
}),
];
diff --git a/src-web/components/editors/GraphQLEditor.tsx b/src-web/components/editors/GraphQLEditor.tsx
index e6955c3c..05d164c1 100644
--- a/src-web/components/editors/GraphQLEditor.tsx
+++ b/src-web/components/editors/GraphQLEditor.tsx
@@ -1,4 +1,5 @@
import { useMemo } from 'react';
+import { Divider } from '../core/Divider';
import type { EditorProps } from '../core/Editor';
import { Editor } from '../core/Editor';
@@ -7,26 +8,57 @@ type Props = Pick<
'heightMode' | 'onChange' | 'defaultValue' | 'className' | 'useTemplating'
>;
-export function GraphQLEditor({ defaultValue, onChange, ...props }: Props) {
- const { query } = useMemo(() => {
+interface GraphQLBody {
+ query: string;
+ variables?: Record;
+ operationName?: string;
+}
+
+export function GraphQLEditor({ defaultValue, onChange, ...extraEditorProps }: Props) {
+ const { query, variables } = useMemo(() => {
try {
- const { query } = JSON.parse(defaultValue ?? '{}');
- return { query };
+ const p = JSON.parse(defaultValue ?? '{}');
+ const query = p.query ?? '';
+ const variables = p.variables;
+ const operationName = p.operationName;
+ return { query, variables, operationName };
} catch (err) {
return { query: 'failed to parse' };
}
}, [defaultValue]);
- const handleChange = (query: string) => {
- onChange?.(JSON.stringify({ query }, null, 2));
+ const handleChange = (b: GraphQLBody) => {
+ onChange?.(JSON.stringify(b, null, 2));
+ };
+
+ const handleChangeQuery = (query: string) => {
+ handleChange({ query, variables });
+ };
+
+ const handleChangeVariables = (variables: string) => {
+ handleChange({ query, variables: JSON.parse(variables) });
};
return (
-
+
);
}