diff --git a/src-tauri/icons/icon.icns b/src-tauri/icons/icon.icns index 841d28ab..c3721c3f 100644 Binary files a/src-tauri/icons/icon.icns and b/src-tauri/icons/icon.icns differ diff --git a/src-web/components/HeaderEditor.tsx b/src-web/components/HeaderEditor.tsx index d64643ae..ebee50ac 100644 --- a/src-web/components/HeaderEditor.tsx +++ b/src-web/components/HeaderEditor.tsx @@ -81,13 +81,11 @@ function FormRow({ pair, onChange, onDelete, - onFocus, isLast, }: { pair: PairWithId; onChange: (pair: PairWithId) => void; onDelete?: (pair: PairWithId) => void; - onFocus?: (pair: PairWithId) => void; isLast?: boolean; }) { return ( @@ -99,7 +97,6 @@ function FormRow({ label="Name" name="name" onChange={(name) => onChange({ id: pair.id, header: { name } })} - onFocus={() => onFocus?.(pair)} placeholder="name" useEditor={{ useTemplating: true }} /> @@ -110,7 +107,6 @@ function FormRow({ label="Value" name="value" onChange={(value) => onChange({ id: pair.id, header: { value } })} - onFocus={() => onFocus?.(pair)} placeholder="value" useEditor={{ useTemplating: true }} /> @@ -118,7 +114,8 @@ function FormRow({ onDelete(pair)} - className="invisible group-hover:visible" + tabIndex={-1} + className={classnames('opacity-0 group-hover:opacity-100')} /> )} diff --git a/src-web/components/RequestPane.tsx b/src-web/components/RequestPane.tsx index 692efcd3..a8c33575 100644 --- a/src-web/components/RequestPane.tsx +++ b/src-web/components/RequestPane.tsx @@ -1,10 +1,12 @@ 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'; import { Editor } from './core/Editor'; -import { HeaderEditor } from './HeaderEditor'; import { TabContent, Tabs } from './core/Tabs/Tabs'; +import { GraphQLEditor } from './editors/GraphQLEditor'; +import { HeaderEditor } from './HeaderEditor'; import { UrlBar } from './UrlBar'; interface Props { @@ -63,21 +65,20 @@ export function RequestPane({ fullHeight, className }: Props) { {activeRequest.bodyType === 'json' ? ( updateRequest.mutate({ body })} /> ) : activeRequest.bodyType === 'graphql' ? ( - updateRequest.mutate({ body })} /> ) : ( diff --git a/src-web/components/RouteError.tsx b/src-web/components/RouteError.tsx index 855a8f41..5370823a 100644 --- a/src-web/components/RouteError.tsx +++ b/src-web/components/RouteError.tsx @@ -6,6 +6,7 @@ import { VStack } from './core/Stacks'; export default function RouteError() { const error = useRouteError(); const stringified = JSON.stringify(error); + // eslint-disable-next-line @typescript-eslint/no-explicit-any const message = (error as any).message ?? stringified; return (
diff --git a/src-web/components/Workspace.tsx b/src-web/components/Workspace.tsx index 0eb275b8..f191034c 100644 --- a/src-web/components/Workspace.tsx +++ b/src-web/components/Workspace.tsx @@ -31,7 +31,7 @@ export default function Workspace() { : 'grid-cols-1 grid-rows-[minmax(0,auto)_minmax(0,100%)]', )} > - +
diff --git a/src-web/components/core/Editor/extensions.ts b/src-web/components/core/Editor/extensions.ts index 48f10424..766d0d4d 100644 --- a/src-web/components/core/Editor/extensions.ts +++ b/src-web/components/core/Editor/extensions.ts @@ -33,7 +33,6 @@ import { } from '@codemirror/view'; import { tags as t } from '@lezer/highlight'; import { graphqlLanguageSupport } from 'cm6-graphql'; -import { debouncedAutocompletionDisplay } from './autocomplete'; import { twig } from './twig/extension'; import { url } from './url/extension'; @@ -78,7 +77,7 @@ export const myHighlightStyle = HighlightStyle.define([ // ]); const syntaxExtensions: Record = { - 'application/graphql+json': graphqlLanguageSupport(), + 'application/graphql': graphqlLanguageSupport(), 'application/json': json(), 'application/javascript': javascript(), 'text/html': html(), diff --git a/src-web/components/core/Tabs/Tabs.tsx b/src-web/components/core/Tabs/Tabs.tsx index 573e81f3..6e1df938 100644 --- a/src-web/components/core/Tabs/Tabs.tsx +++ b/src-web/components/core/Tabs/Tabs.tsx @@ -1,6 +1,6 @@ import * as T from '@radix-ui/react-tabs'; import classnames from 'classnames'; -import type { ReactElement, ReactNode } from 'react'; +import type { ReactNode } from 'react'; import { useState } from 'react'; import { Button } from '../Button'; import type { DropdownMenuRadioItem, DropdownMenuRadioProps } from '../Dropdown'; @@ -81,7 +81,7 @@ export function Tabs({ defaultValue, label, children, tabs, className, tabListCl )} > {t.options.items.find((i) => i.value === t.options?.value)?.label ?? ''} - + ); diff --git a/src-web/components/editors/GraphQLEditor.tsx b/src-web/components/editors/GraphQLEditor.tsx new file mode 100644 index 00000000..e6955c3c --- /dev/null +++ b/src-web/components/editors/GraphQLEditor.tsx @@ -0,0 +1,32 @@ +import { useMemo } from 'react'; +import type { EditorProps } from '../core/Editor'; +import { Editor } from '../core/Editor'; + +type Props = Pick< + EditorProps, + 'heightMode' | 'onChange' | 'defaultValue' | 'className' | 'useTemplating' +>; + +export function GraphQLEditor({ defaultValue, onChange, ...props }: Props) { + const { query } = useMemo(() => { + try { + const { query } = JSON.parse(defaultValue ?? '{}'); + return { query }; + } catch (err) { + return { query: 'failed to parse' }; + } + }, [defaultValue]); + + const handleChange = (query: string) => { + onChange?.(JSON.stringify({ query }, null, 2)); + }; + + return ( + + ); +} diff --git a/src-web/lib/theme/window.ts b/src-web/lib/theme/window.ts index 8d5e22c1..8d95c86d 100644 --- a/src-web/lib/theme/window.ts +++ b/src-web/lib/theme/window.ts @@ -11,11 +11,11 @@ const darkTheme: AppTheme = { blackPoint: 0.2, colors: { gray: '#6b5b98', - red: '#ee3b3b', + red: '#ff417b', orange: '#ff9411', - yellow: '#dcc73b', - green: '#44cb44', - blue: '#2e91ff', + yellow: '#e8d13f', + green: '#43e76f', + blue: '#219dff', pink: '#f670f6', violet: '#b176ff', },