Skip to content

Commit

Permalink
commit @graphiql/react
Browse files Browse the repository at this point in the history
commit graphiql

remove unused and add editor theme

add monaco-editor-webpack-plugin

remove
  • Loading branch information
dimaMachina committed Jun 16, 2023
1 parent 67bf93a commit 2e06209
Show file tree
Hide file tree
Showing 35 changed files with 1,042 additions and 187 deletions.
4 changes: 3 additions & 1 deletion packages/graphiql-react/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@
"types"
],
"scripts": {
"dev": "concurrently 'tsc --emitDeclarationOnly --watch' 'vite build --watch'",
"dev": "vite build --watch",
"build": "tsc --emitDeclarationOnly && vite build"
},
"peerDependencies": {
Expand All @@ -47,6 +47,8 @@
"react-dom": "^16.8.0 || ^17 || ^18"
},
"dependencies": {
"monaco-editor": "^0.39.0",
"monaco-graphql": "^1.2.3",
"@headlessui/react": "^1.7.15",
"@radix-ui/react-dialog": "^1.0.4",
"@radix-ui/react-visually-hidden": "^1.0.3",
Expand Down
449 changes: 449 additions & 0 deletions packages/graphiql-react/src/constants.ts

Large diffs are not rendered by default.

57 changes: 57 additions & 0 deletions packages/graphiql-react/src/create-editor.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
import { editor as MONACO_EDITOR } from 'monaco-editor';
import {
OPERATIONS_MODEL,
VARIABLES_MODEL,
HEADERS_MODEL,
RESULTS_MODEL,
editorThemeDark,
editorThemeLight,
} from './constants';

// this should be called somewhere else, but fine here for now
MONACO_EDITOR.defineTheme('graphiql-DARK', editorThemeDark);
MONACO_EDITOR.defineTheme('graphiql-LIGHT', editorThemeLight);

export function createEditor(
type: 'operations' | 'variables' | 'headers' | 'results',
domElement: HTMLDivElement,
) {
return MONACO_EDITOR.create(domElement, {
language: type === 'operations' ? 'graphql' : 'json',
// the default theme
theme: 'graphiql-DARK',
automaticLayout: true,
// folding: false, // disable folding
fontFamily: "'Fira Code', monospace", // TODO: set the font (this is problematic because the font has to be installed locally)
fontSize: 13, // default is 12
// lineDecorationsWidth: 100,
lineNumbersMinChars: 2,
minimap: {
enabled: false, // disable the minimap
},
overviewRulerLanes: 0, // remove unnecessary cruft on right side of editors
scrollbar: {
// hide the scrollbars
horizontal: 'hidden',
// vertical: 'hidden',
verticalScrollbarSize: 4,
},
// scrollPredominantAxis: false,
scrollBeyondLastLine: false, // cleans up unnecessary "padding" on the bottom of each editor
tabSize: 2,
wordWrap: 'on',
// wrappingIndent: 'none',
wrappingStrategy: 'advanced',
fixedOverflowWidgets: true,
...(type === 'results' && {
readOnly: true,
lineNumbers: 'off',
}),
model: {
operations: OPERATIONS_MODEL,
variables: VARIABLES_MODEL,
headers: HEADERS_MODEL,
results: RESULTS_MODEL,
}[type],
});
}
10 changes: 4 additions & 6 deletions packages/graphiql-react/src/editor/completion.ts
Original file line number Diff line number Diff line change
Expand Up @@ -164,12 +164,10 @@ export function onHasCompletion(
if (event.target === hintsUl) {
hintsUl.removeEventListener('scroll', handleScroll);
hintsUl.removeEventListener('DOMNodeRemoved', onRemoveFn);
if (information) {
information.removeEventListener(
'click',
onClickHintInformation,
);
}
information?.removeEventListener(
'click',
onClickHintInformation,
);
information = null;
fieldName = null;
typeNamePill = null;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
// @ts-nocheck -- codemirror editor complain about type errors
import { useEffect } from 'react';
import { clsx } from 'clsx';

Expand Down
48 changes: 48 additions & 0 deletions packages/graphiql-react/src/editor/components/headers-editor.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import { useEffect, useRef } from 'react';
import { clsx } from 'clsx';
import { useEditorContext } from '../context';
import { UseHeaderEditorArgs } from '../header-editor';
import '../style/editor.css';
import { createEditor } from '@/create-editor';
import { HEADERS_MODEL } from '@/constants';
import debounce from '@/utility/debounce';
import { useStorageContext } from '@/storage';

type HeaderEditorProps = UseHeaderEditorArgs & {
/**
* Visually hide the header editor.
* @default false
*/
isHidden?: boolean;
};

export function HeadersEditor({ isHidden, ...hookArgs }: HeaderEditorProps) {
const { setHeaderEditor, updateActiveTabValues, shouldPersistHeaders } =
useEditorContext({
nonNull: true,
caller: HeadersEditor,
});
const ref = useRef<HTMLDivElement>(null);
const storage = useStorageContext();

useEffect(() => {
setHeaderEditor(createEditor('headers', ref.current!));
if (!shouldPersistHeaders) {
return;
}
HEADERS_MODEL.onDidChangeContent(
debounce(500, () => {
const value = HEADERS_MODEL.getValue();
storage?.set(STORAGE_KEY, value);
updateActiveTabValues({ headers: value });
}),
);
// eslint-disable-next-line react-hooks/exhaustive-deps -- only on mount
}, []);

return (
<div className={clsx('graphiql-editor', isHidden && 'hidden')} ref={ref} />
);
}

export const STORAGE_KEY = 'headers';
4 changes: 4 additions & 0 deletions packages/graphiql-react/src/editor/components/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,7 @@ export { ImagePreview } from './image-preview';
export { QueryEditor } from './query-editor';
export { ResponseEditor } from './response-editor';
export { VariableEditor } from './variable-editor';
export { OperationsEditor } from './operations-editor';
export { VariablesEditor } from './variables-editor';
export { HeadersEditor } from './headers-editor';
export { ResultsEditor } from './results-editor';
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import React from 'react';
import { useQueryEditor, UseQueryEditorArgs } from '../operations-editor';

export function OperationsEditor(props: UseQueryEditorArgs) {
const ref = useQueryEditor(props, OperationsEditor);

return <div className="graphiql-editor" ref={ref} />;
}
29 changes: 29 additions & 0 deletions packages/graphiql-react/src/editor/components/results-editor.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import { UseResponseEditorArgs } from '../response-editor';
import { useEffect, useRef } from 'react';
import { createEditor } from '@/create-editor';
import { useEditorContext } from '@/editor';
import '../style/editor.css';

export function ResultsEditor(props: UseResponseEditorArgs) {
const ref = useRef<HTMLDivElement>(null);

const { setResponseEditor } = useEditorContext({
nonNull: true,
caller: ResultsEditor,
});

useEffect(() => {
setResponseEditor(createEditor('results', ref.current!));
// eslint-disable-next-line react-hooks/exhaustive-deps -- only on mount
}, []);

return (
<section
className="result-window"
aria-label="Result Window"
aria-live="polite"
aria-atomic="true"
ref={ref}
/>
);
}
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
// @ts-nocheck -- codemirror editor complain about type errors
import { useEffect } from 'react';
import { clsx } from 'clsx';

Expand Down Expand Up @@ -26,8 +27,8 @@ export function VariableEditor({ isHidden, ...hookArgs }: VariableEditorProps) {
const ref = useVariableEditor(hookArgs, VariableEditor);

useEffect(() => {
if (variableEditor && !isHidden) {
variableEditor.refresh();
if (!isHidden) {
variableEditor?.refresh();
}
}, [variableEditor, isHidden]);

Expand Down
47 changes: 47 additions & 0 deletions packages/graphiql-react/src/editor/components/variables-editor.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import { useEffect, useRef } from 'react';
import { clsx } from 'clsx';
import { UseVariableEditorArgs } from '../variable-editor';
import { createEditor } from '@/create-editor';
import { VARIABLES_MODEL } from '@/constants';
import { useStorageContext } from '@/storage';
import { useEditorContext } from '@/editor';
import debounce from '@/utility/debounce';

type VariableEditorProps = UseVariableEditorArgs & {
/**
* Visually hide the header editor.
* @default false
*/
isHidden?: boolean;
};

export function VariablesEditor({
isHidden,
...hookArgs
}: VariableEditorProps) {
const ref = useRef<HTMLDivElement>(null);
const storage = useStorageContext();

const { updateActiveTabValues, setVariableEditor } = useEditorContext({
nonNull: true,
caller: VariablesEditor,
});

useEffect(() => {
setVariableEditor(createEditor('variables', ref.current!));
VARIABLES_MODEL.onDidChangeContent(
debounce(500, () => {
const value = VARIABLES_MODEL.getValue();
storage?.set(STORAGE_KEY, value);
updateActiveTabValues({ variables: value });
}),
);
// eslint-disable-next-line react-hooks/exhaustive-deps -- only on mount
}, []);

return (
<div className={clsx('graphiql-editor', isHidden && 'hidden')} ref={ref} />
);
}

const STORAGE_KEY = 'variables';
40 changes: 21 additions & 19 deletions packages/graphiql-react/src/editor/context.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ import {
} from './tabs';
import { CodeMirrorEditor } from './types';
import { STORAGE_KEY as STORAGE_KEY_VARIABLES } from './variable-editor';
import { editor } from 'monaco-editor';

export type CodeMirrorEditorWithOperationFacts = CodeMirrorEditor & {
documentAST: DocumentNode | null;
Expand Down Expand Up @@ -79,39 +80,39 @@ export type EditorContextType = TabsState & {
): void;

/**
* The CodeMirror editor instance for the headers editor.
* The CodeMirror editor instance for the headers' editor.
*/
headerEditor: CodeMirrorEditor | null;
headerEditor: editor.IStandaloneCodeEditor | null;
/**
* The CodeMirror editor instance for the query editor. This editor also
* stores the operation facts that are derived from the current editor
* contents.
*/
queryEditor: CodeMirrorEditorWithOperationFacts | null;
queryEditor: editor.IStandaloneCodeEditor | null;
/**
* The CodeMirror editor instance for the response editor.
*/
responseEditor: CodeMirrorEditor | null;
responseEditor: editor.IStandaloneCodeEditor | null;
/**
* The CodeMirror editor instance for the variables editor.
* The CodeMirror editor instance for the variables' editor.
*/
variableEditor: CodeMirrorEditor | null;
variableEditor: editor.IStandaloneCodeEditor | null;
/**
* Set the CodeMirror editor instance for the headers editor.
* Set the CodeMirror editor instance for the headers' editor.
*/
setHeaderEditor(newEditor: CodeMirrorEditor): void;
setHeaderEditor(newEditor: editor.IStandaloneCodeEditor): void;
/**
* Set the CodeMirror editor instance for the query editor.
*/
setQueryEditor(newEditor: CodeMirrorEditorWithOperationFacts): void;
setQueryEditor(newEditor: editor.IStandaloneCodeEditor): void;
/**
* Set the CodeMirror editor instance for the response editor.
*/
setResponseEditor(newEditor: CodeMirrorEditor): void;
setResponseEditor(newEditor: editor.IStandaloneCodeEditor): void;
/**
* Set the CodeMirror editor instance for the variables editor.
* Set the CodeMirror editor instance for the variables' editor.
*/
setVariableEditor(newEditor: CodeMirrorEditor): void;
setVariableEditor(newEditor: editor.IStandaloneCodeEditor): void;

/**
* Changes the operation name and invokes the `onEditOperationName` callback.
Expand Down Expand Up @@ -207,7 +208,7 @@ export type EditorContextProviderProps = {
/**
* Invoked when the operation name changes. Possible triggers are:
* - Editing the contents of the query editor
* - Selecting a operation for execution in a document that contains multiple
* - Selecting an operation for execution in a document that contains multiple
* operation definitions
* @param operationName The operation name after it has been changed.
*/
Expand Down Expand Up @@ -248,7 +249,7 @@ export type EditorContextProviderProps = {
*/
validationRules?: ValidationRule[];
/**
* This prop can be used to set the contents of the variables editor. Every
* This prop can be used to set the contents of the variables' editor. Every
* time this prop changes, the contents of the variables editor are replaced.
* Note that the editor contents can be changed in between these updates by
* typing in the editor.
Expand All @@ -263,15 +264,15 @@ export type EditorContextProviderProps = {

export function EditorContextProvider(props: EditorContextProviderProps) {
const storage = useStorageContext();
const [headerEditor, setHeaderEditor] = useState<CodeMirrorEditor | null>(
const [headerEditor, setHeaderEditor] = useState<editor.IStandaloneCodeEditor | null>(
null,
);
const [queryEditor, setQueryEditor] =
useState<CodeMirrorEditorWithOperationFacts | null>(null);
const [responseEditor, setResponseEditor] = useState<CodeMirrorEditor | null>(
useState<editor.IStandaloneCodeEditor | null>(null);
const [responseEditor, setResponseEditor] = useState<editor.IStandaloneCodeEditor | null>(
null,
);
const [variableEditor, setVariableEditor] = useState<CodeMirrorEditor | null>(
const [variableEditor, setVariableEditor] = useState<editor.IStandaloneCodeEditor | null>(
null,
);

Expand Down Expand Up @@ -458,6 +459,7 @@ export function EditorContextProvider(props: EditorContextProviderProps) {
return;
}

// @ts-expect-error FIXME: MONACO
queryEditor.operationName = operationName;
updateActiveTabValues({ operationName });
onEditOperationName?.(operationName);
Expand Down Expand Up @@ -555,7 +557,7 @@ export const useEditorContext = createContextHook(EditorContext);

const PERSIST_HEADERS_STORAGE_KEY = 'shouldPersistHeaders';

const DEFAULT_QUERY = `# Welcome to GraphiQL
export const DEFAULT_QUERY = `# Welcome to GraphiQL
#
# GraphiQL is an in-browser tool for writing, validating, and
# testing GraphQL queries.
Expand Down
1 change: 1 addition & 0 deletions packages/graphiql-react/src/editor/header-editor.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
// @ts-nocheck -- codemirror editor complain about type errors
import { useEffect, useRef } from 'react';

import { useExecutionContext } from '../execution';
Expand Down
Loading

0 comments on commit 2e06209

Please sign in to comment.