Variables
Const ArgumentIcon
ArgumentIcon: FC<SVGProps<SVGSVGElement>> = generateIcon(_ArgumentIcon)
Const Button
Button: ForwardRefExoticComponent<Omit<ButtonProps & ClassAttributes<HTMLButtonElement> & ButtonHTMLAttributes<HTMLButtonElement>, "ref"> & RefAttributes<HTMLButtonElement>> = forwardRef<HTMLButtonElement,ButtonProps & JSX.IntrinsicElements['button']>((props, ref) => (<button{...props}ref={ref}className={clsx('graphiql-button',{success: 'graphiql-button-success',error: 'graphiql-button-error',}[props.state!],props.className,)}/>))
Const ButtonGroup
ButtonGroup: ForwardRefExoticComponent<Omit<DetailedHTMLProps<HTMLAttributes<HTMLDivElement>, HTMLDivElement>, "ref"> & RefAttributes<HTMLDivElement>> = forwardRef<HTMLDivElement,JSX.IntrinsicElements['div']>((props, ref) => (<div{...props}ref={ref}className={clsx('graphiql-button-group', props.className)}/>))
Const ChevronDownIcon
ChevronDownIcon: FC<SVGProps<SVGSVGElement>> = generateIcon(_ChevronDownIcon)
Const ChevronLeftIcon
ChevronLeftIcon: FC<SVGProps<SVGSVGElement>> = generateIcon(_ChevronLeftIcon)
Const ChevronUpIcon
ChevronUpIcon: FC<SVGProps<SVGSVGElement>> = generateIcon(_ChevronUpIcon)
Const CloseIcon
CloseIcon: FC<SVGProps<SVGSVGElement>> = generateIcon(_CloseIcon)
Const CopyIcon
CopyIcon: FC<SVGProps<SVGSVGElement>> = generateIcon(_CopyIcon)
Const DEFAULT_EDITOR_THEME
DEFAULT_EDITOR_THEME: "graphiql" = "graphiql"
Const DEFAULT_KEY_MAP
DEFAULT_
KEY_MAP: KeyMap = "sublime"
Const DEFAULT_QUERY
DEFAULT_QUERY: "# Welcome to GraphiQL## GraphiQL is an in-browser tool for writing, validating, and# testing GraphQL queries.## Type queries into this side of the screen, and you will see intelligent# typeaheads aware of the current GraphQL type schema and live syntax and# validation errors highlighted within the text.## GraphQL queries typically start with a "{" character. Lines that start# with a # are ignored.## An example GraphQL query might look like:## {# field(arg: "value") {# subField# }# }## Keyboard shortcuts:## Prettify query: Shift-Ctrl-P (or press the prettify button)## Merge fragments: Shift-Ctrl-M (or press the merge button)## Run Query: Ctrl-Enter (or press the play button)## Auto Complete: Ctrl-Space (or just start typing)#" = `# Welcome to GraphiQL## GraphiQL is an in-browser tool for writing, validating, and# testing GraphQL queries.## Type queries into this side of the screen, and you will see intelligent# typeaheads aware of the current GraphQL type schema and live syntax and# validation errors highlighted within the text.## GraphQL queries typically start with a "{" character. Lines that start# with a # are ignored.## An example GraphQL query might look like:## {# field(arg: "value") {# subField# }# }## Keyboard shortcuts:## Prettify query: Shift-Ctrl-P (or press the prettify button)## Merge fragments: Shift-Ctrl-M (or press the merge button)## Run Query: Ctrl-Enter (or press the play button)## Auto Complete: Ctrl-Space (or just start typing)#`
Const DeprecatedArgumentIcon
DeprecatedArgumentIcon: FC<SVGProps<SVGSVGElement>> = generateIcon(_DeprecatedArgumentIcon)
Const DeprecatedEnumValueIcon
DeprecatedEnumValueIcon: FC<SVGProps<SVGSVGElement>> = generateIcon(_DeprecatedEnumValueIcon)
Const DeprecatedFieldIcon
DeprecatedFieldIcon: FC<SVGProps<SVGSVGElement>> = generateIcon(_DeprecatedFieldIcon)
Const Dialog
Dialog: FC<DialogProps> & { Close: ForwardRefExoticComponent<Omit<DetailedHTMLProps<ButtonHTMLAttributes<HTMLButtonElement>, HTMLButtonElement>, "ref"> & RefAttributes<HTMLButtonElement>>; Description: ForwardRefExoticComponent<DialogDescriptionProps & RefAttributes<HTMLParagraphElement>>; Title: ForwardRefExoticComponent<DialogTitleProps & RefAttributes<HTMLHeadingElement>>; Trigger: ForwardRefExoticComponent<DialogTriggerProps & RefAttributes<HTMLButtonElement>> } = Object.assign(DialogRoot, {Close: DialogClose,Title: D.Title,Trigger: D.Trigger,Description: D.Description,})
Const DirectiveIcon
DirectiveIcon: FC<SVGProps<SVGSVGElement>> = generateIcon(_DirectiveIcon)
Const DocsFilledIcon
DocsFilledIcon: FC<SVGProps<SVGSVGElement>> = generateIcon(_DocsFilledIcon)
Const DocsIcon
DocsIcon: FC<SVGProps<SVGSVGElement>> = generateIcon(_DocsIcon)
Const DropdownMenu
DropdownMenu: FC<DropdownMenuProps> & { Button: ForwardRefExoticComponent<Omit<DetailedHTMLProps<ButtonHTMLAttributes<HTMLButtonElement>, HTMLButtonElement>, "ref"> & RefAttributes<HTMLButtonElement>>; Content: FC<DropdownMenuContentProps>; Item: FC<DropdownMenuItemProps> } = Object.assign(Root, {Button,Item,Content,})
Const EnumValueIcon
EnumValueIcon: FC<SVGProps<SVGSVGElement>> = generateIcon(_EnumValueIcon)
Const FieldIcon
FieldIcon: FC<SVGProps<SVGSVGElement>> = generateIcon(_FieldIcon)
Const HistoryIcon
HistoryIcon: FC<SVGProps<SVGSVGElement>> = generateIcon(_HistoryIcon)
Const ImagePreview
ImagePreview: FC<ImagePreviewProps> & { shouldRender: any } = Object.assign(ImagePreview_, {shouldRender(token: Token) {const url = tokenToURL(token);return url ? isImageURL(url) : false;},})
Const ImplementsIcon
ImplementsIcon: FC<SVGProps<SVGSVGElement>> = generateIcon(_ImplementsIcon)
Const KeyboardShortcutIcon
KeyboardShortcutIcon: FC<SVGProps<SVGSVGElement>> = generateIcon(_KeyboardShortcutIcon)
Const MagnifyingGlassIcon
MagnifyingGlassIcon: FC<SVGProps<SVGSVGElement>> = generateIcon(_MagnifyingGlassIcon)
Const MarkdownContent
MarkdownContent: ForwardRefExoticComponent<Omit<MarkdownContentProps & Omit<DetailedHTMLProps<HTMLAttributes<HTMLDivElement>, HTMLDivElement>, "children">, "ref"> & RefAttributes<HTMLDivElement>> = forwardRef<HTMLDivElement,MarkdownContentProps & Omit<JSX.IntrinsicElements['div'], 'children'>>(({ children, onlyShowFirstChild, type, ...props }, ref) => (<div{...props}ref={ref}className={clsx(`graphiql-markdown-${type}`,onlyShowFirstChild && 'graphiql-markdown-preview',props.className,)}dangerouslySetInnerHTML={{ __html: markdown.render(children) }}/>))
Const MergeIcon
MergeIcon: FC<SVGProps<SVGSVGElement>> = generateIcon(_MergeIcon)
Const PenIcon
PenIcon: FC<SVGProps<SVGSVGElement>> = generateIcon(_PenIcon)
Const PlayIcon
PlayIcon: FC<SVGProps<SVGSVGElement>> = generateIcon(_PlayIcon)
Const PlusIcon
PlusIcon: FC<SVGProps<SVGSVGElement>> = generateIcon(_PlusIcon)
Const PrettifyIcon
PrettifyIcon: FC<SVGProps<SVGSVGElement>> = generateIcon(_PrettifyIcon)
Const ReloadIcon
ReloadIcon: FC<SVGProps<SVGSVGElement>> = generateIcon(_ReloadIcon)
Const RootTypeIcon
RootTypeIcon: FC<SVGProps<SVGSVGElement>> = generateIcon(_RootTypeIcon)
Const STORAGE_KEY
STORAGE_KEY: "variables" = "variables"
Const STORAGE_KEY
STORAGE_KEY: "tabState" = "tabState"
Const STORAGE_KEY
STORAGE_KEY: "headers" = "headers"
Const STORAGE_KEY_QUERY
STORAGE_KEY_QUERY: "query" = "query"
Const SettingsIcon
SettingsIcon: FC<SVGProps<SVGSVGElement>> = generateIcon(_SettingsIcon)
Const Spinner
Spinner: ForwardRefExoticComponent<Omit<DetailedHTMLProps<HTMLAttributes<HTMLDivElement>, HTMLDivElement>, "ref"> & RefAttributes<HTMLDivElement>> = forwardRef<HTMLDivElement, JSX.IntrinsicElements['div']>((props, ref) => (<div{...props}ref={ref}className={clsx('graphiql-spinner', props.className)}/>),)
Const StarFilledIcon
StarFilledIcon: FC<SVGProps<SVGSVGElement>> = generateIcon(_StarFilledIcon)
Const StarIcon
StarIcon: FC<SVGProps<SVGSVGElement>> = generateIcon(_StarIcon)
Const StopIcon
StopIcon: FC<SVGProps<SVGSVGElement>> = generateIcon(_StopIcon)
Const Tab
Tab: ForwardRefExoticComponent<TabProps & RefAttributes<HTMLLIElement>> & { Button: ForwardRefExoticComponent<Omit<DetailedHTMLProps<ButtonHTMLAttributes<HTMLButtonElement>, HTMLButtonElement>, "ref"> & RefAttributes<HTMLButtonElement>>; Close: ForwardRefExoticComponent<Omit<DetailedHTMLProps<ButtonHTMLAttributes<HTMLButtonElement>, HTMLButtonElement>, "ref"> & RefAttributes<HTMLButtonElement>> } = Object.assign(TabRoot, {Button: TabButton,Close: TabClose,})
Const Tabs
Tabs: ForwardRefExoticComponent<TabsProps & RefAttributes<HTMLUListElement>> = forwardRef<HTMLUListElement, TabsProps>(({ values, onReorder, children, className, ...props }, ref) => (<Reorder.Group{...props}ref={ref}values={values}onReorder={onReorder}axis="x"role="tablist"className={clsx('graphiql-tabs', className)}>{children}</Reorder.Group>),)
Const ToolbarButton
ToolbarButton: ForwardRefExoticComponent<Omit<ToolbarButtonProps & ClassAttributes<HTMLButtonElement> & ButtonHTMLAttributes<HTMLButtonElement>, "ref"> & RefAttributes<HTMLButtonElement>> = forwardRef<HTMLButtonElement,ToolbarButtonProps & JSX.IntrinsicElements['button']>(({ label, onClick, ...props }, ref) => {const [error, setError] = useState<Error | null>(null);const handleClick: MouseEventHandler<HTMLButtonElement> = event => {try {// Optional chaining inside try-catch isn't supported yet by react-compilerif (onClick) {onClick(event);}setError(null);} catch (err) {setError(err instanceof Error? err: new Error(`Toolbar button click failed: ${err}`),);}};return (<Tooltip label={label}><UnStyledButton{...props}ref={ref}type="button"className={clsx('graphiql-toolbar-button',error && 'error',props.className,)}onClick={handleClick}aria-label={error ? error.message : label}aria-invalid={error ? 'true' : props['aria-invalid']}/></Tooltip>);})
Const ToolbarMenu
ToolbarMenu: ToolbarMenuRoot & { Item: FC<DropdownMenuItemProps> } = Object.assign(ToolbarMenuRoot, {Item: DropdownMenu.Item,})
Const Tooltip
Tooltip: FC<TooltipContentProps & { label: ReactNode }> & { Provider: FC<TooltipProviderProps> } = Object.assign(TooltipRoot, {Provider: T.Provider,})
Const TrashIcon
TrashIcon: FC<SVGProps<SVGSVGElement>> = generateIcon(_TrashIcon)
Const TypeIcon
TypeIcon: FC<SVGProps<SVGSVGElement>> = generateIcon(_TypeIcon)
Const UnStyledButton
UnStyledButton: ForwardRefExoticComponent<Omit<DetailedHTMLProps<ButtonHTMLAttributes<HTMLButtonElement>, HTMLButtonElement>, "ref"> & RefAttributes<HTMLButtonElement>> = forwardRef<HTMLButtonElement,JSX.IntrinsicElements['button']>((props, ref) => (<button{...props}ref={ref}className={clsx('graphiql-un-styled', props.className)}/>))
Const createBoundedUseStore
createBoundedUseStore: <S>(store: S) => { (): ExtractState<S>; <T>(selector: (state: ExtractState<S>) => T): T } = (store => selector =>useStore(store, selector)) as <S extends StoreApi<unknown>>(store: S,) => {(): ExtractState<S>;<T>(selector: (state: ExtractState<S>) => T): T;}
Type declaration
-
- <S>(store: S): { (): ExtractState<S>; <T>(selector: (state: ExtractState<S>) => T): T }
-
Type parameters
Parameters
Returns { (): ExtractState<S>; <T>(selector: (state: ExtractState<S>) => T): T }
-
- (): ExtractState<S>
- <T>(selector: (state: ExtractState<S>) => T): T
-
Returns ExtractState<S>
-
Type parameters
Parameters
-
selector: (state: ExtractState<S>) => T
-
- (state: ExtractState<S>): T
Returns T
Const editorStore
editorStore: StoreApi<EditorStore> = createStore<EditorStore>((set, get) => ({tabs: null!,activeTabIndex: null!,addTab() {set(current => {const { defaultQuery, defaultHeaders, onTabChange } = get();// Make sure the current tab stores the latest valuesconst updatedValues = synchronizeActiveTabValues(current);const updated = {tabs: [...updatedValues.tabs,createTab({headers: defaultHeaders,query: defaultQuery,}),],activeTabIndex: updatedValues.tabs.length,};storeTabs(updated);setEditorValues(updated.tabs[updated.activeTabIndex]);onTabChange?.(updated);return updated;});},changeTab(index) {set(current => {const { onTabChange } = get();const updated = {...current,activeTabIndex: index,};storeTabs(updated);setEditorValues(updated.tabs[updated.activeTabIndex]);onTabChange?.(updated);return updated;});},moveTab(newOrder) {set(current => {const { onTabChange } = get();const activeTab = current.tabs[current.activeTabIndex];const updated = {tabs: newOrder,activeTabIndex: newOrder.indexOf(activeTab),};storeTabs(updated);setEditorValues(updated.tabs[updated.activeTabIndex]);onTabChange?.(updated);return updated;});},closeTab(index) {set(current => {const { onTabChange } = get();const updated = {tabs: current.tabs.filter((_tab, i) => index !== i),activeTabIndex: Math.max(current.activeTabIndex - 1, 0),};storeTabs(updated);setEditorValues(updated.tabs[updated.activeTabIndex]);onTabChange?.(updated);return updated;});},updateActiveTabValues(partialTab) {set(current => {if (!current.tabs) {// Vitest fails with TypeError: Cannot read properties of null (reading 'map')// in `setPropertiesInActiveTab` when `tabs` is `null`return current;}const { onTabChange } = get();const updated = setPropertiesInActiveTab(current, partialTab);storeTabs(updated);onTabChange?.(updated);return updated;});},headerEditor: null!,queryEditor: null!,responseEditor: null!,variableEditor: null!,setHeaderEditor(headerEditor) {set({ headerEditor });},setQueryEditor(queryEditor) {set({ queryEditor });},setResponseEditor(responseEditor) {set({ responseEditor });},setVariableEditor(variableEditor) {set({ variableEditor });},setOperationName(operationName) {const { queryEditor, onEditOperationName, updateActiveTabValues } = get();if (!queryEditor) {return;}queryEditor.operationName = operationName;updateActiveTabValues({ operationName });onEditOperationName?.(operationName);},shouldPersistHeaders: false,setShouldPersistHeaders(persist) {const { headerEditor, tabs, activeTabIndex } = get();const { storage } = storageStore.getState();if (persist) {storage.set(STORAGE_KEY_HEADERS, headerEditor?.getValue() ?? '');const serializedTabs = serializeTabState({ tabs, activeTabIndex }, true);storage.set(STORAGE_KEY_TABS, serializedTabs);} else {storage.set(STORAGE_KEY_HEADERS, '');clearHeadersFromTabs();}set({ shouldPersistHeaders: persist });storage.set(PERSIST_HEADERS_STORAGE_KEY, persist.toString());},onEditOperationName: undefined,externalFragments: null!,onTabChange: undefined,defaultQuery: undefined,defaultHeaders: undefined,validationRules: null!,initialHeaders: null!,initialQuery: null!,initialResponse: null!,initialVariables: null!,}))
Const executionStore
execution
Store: StoreApi<ExecutionContextType & Pick<ExecutionContextProviderProps, "getDefaultFieldNames">> = createStore<ExecutionContextType &Pick<ExecutionContextProviderProps, 'getDefaultFieldNames'>>((set, get) => ({isFetching: false,subscription: null,operationName: null,getDefaultFieldNames: undefined,queryId: 0,stop() {const { subscription } = get();subscription?.unsubscribe();set({ isFetching: false, subscription: null });},async run() {const {externalFragments,headerEditor,queryEditor,responseEditor,variableEditor,updateActiveTabValues,} = editorStore.getState();if (!queryEditor || !responseEditor) {return;}const { subscription, operationName, queryId } = get();// If there's an active subscription, unsubscribe it and returnif (subscription) {stop();return;}const setResponse = (value: string) => {responseEditor.setValue(value);updateActiveTabValues({ response: value });};const newQueryId = queryId + 1;set({ queryId: newQueryId });// Use the edited query after autoCompleteLeafs() runs or,// in case autoCompletion fails (the function returns undefined),// the current query from the editor.let query = getAutoCompleteLeafs() || queryEditor.getValue();const variablesString = variableEditor?.getValue();let variables: Record<string, unknown> | undefined;try {variables = tryParseJsonObject({json: variablesString,errorMessageParse: 'Variables are invalid JSON',errorMessageType: 'Variables are not a JSON object.',});} catch (error) {setResponse(error instanceof Error ? error.message : `${error}`);return;}const headersString = headerEditor?.getValue();let headers: Record<string, unknown> | undefined;try {headers = tryParseJsonObject({json: headersString,errorMessageParse: 'Headers are invalid JSON',errorMessageType: 'Headers are not a JSON object.',});} catch (error) {setResponse(error instanceof Error ? error.message : `${error}`);return;}if (externalFragments) {const fragmentDependencies = queryEditor.documentAST? getFragmentDependenciesForAST(queryEditor.documentAST,externalFragments,): [];if (fragmentDependencies.length > 0) {query +='\n' +fragmentDependencies.map((node: FragmentDefinitionNode) => print(node)).join('\n');}}setResponse('');set({ isFetching: true });try {const fullResponse: ExecutionResult = {};const handleResponse = (result: ExecutionResult) => {// A different query was dispatched in the meantime, so don't// show the results of this one.if (newQueryId !== get().queryId) {return;}let maybeMultipart = Array.isArray(result) ? result : false;if (!maybeMultipart &&typeof result === 'object' &&result !== null &&'hasNext' in result) {maybeMultipart = [result];}if (maybeMultipart) {for (const part of maybeMultipart) {mergeIncrementalResult(fullResponse, part);}set({ isFetching: false });setResponse(formatResult(fullResponse));} else {set({ isFetching: false });setResponse(formatResult(result));}};const { fetcher } = schemaStore.getState();const fetch = fetcher({query,variables,operationName:operationName ?? queryEditor.operationName ?? undefined,},{headers: headers ?? undefined,documentAST: queryEditor.documentAST ?? undefined,},);const value = await fetch;if (isObservable(value)) {// If the fetcher returned an Observable, then subscribe to it, calling// the callback on each next value and handling both errors and the// completion of the Observable.const newSubscription = value.subscribe({next(result) {handleResponse(result);},error(error: Error) {set({ isFetching: false });if (error) {setResponse(formatError(error));}set({ subscription: null });},complete() {set({ isFetching: false, subscription: null });},});set({ subscription: newSubscription });} else if (isAsyncIterable(value)) {const newSubscription = {unsubscribe: () => value[Symbol.asyncIterator]().return?.(),};set({ subscription: newSubscription });for await (const result of value) {handleResponse(result);}set({ isFetching: false, subscription: null });} else {handleResponse(value);}} catch (error) {set({ isFetching: false });setResponse(formatError(error));set({ subscription: null });}},}))
Const invalidCharacters
invalidCharacters: string[] = Array.from({ length: 11 }, (_, i) => {// \u2000 -> \u200areturn String.fromCharCode(0x2000 + i);}).concat(['\u2028', '\u2029', '\u202f', '\u00a0'])
Const isMacOs
isMacOs: boolean = typeof navigator !== 'undefined' && navigator.userAgent.includes('Mac')
Const markdown
markdown: MarkdownIt = new MarkdownIt({// we don't want to convert \n to <br> because in markdown a single newline is not a line break// https://github.com/graphql/graphiql/issues/3155breaks: false,linkify: true,})
Const pluginStore
plugin
Store: StoreApi<PluginContextType> = createStore<PluginContextType>((set, get) => ({plugins: [],visiblePlugin: null,referencePlugin: undefined,setVisiblePlugin(plugin) {const { plugins, onTogglePluginVisibility } = get();const byTitle = typeof plugin === 'string';const newVisiblePlugin: PluginContextType['visiblePlugin'] =(plugin && plugins.find(p => (byTitle ? p.title : p) === plugin)) || null;set(({ visiblePlugin }) => {if (newVisiblePlugin === visiblePlugin) {return { visiblePlugin };}onTogglePluginVisibility?.(newVisiblePlugin);return { visiblePlugin: newVisiblePlugin };});},}))
Const schemaStore
schemaStore: StoreApi<SchemaStore> = createStore<SchemaStore>((set, get) => ({inputValueDeprecation: null!,introspectionQueryName: null!,schemaDescription: null!,fetcher: null!, // Explicitly set to null, as it's safe since we have TypeError thrownonSchemaChange: undefined,fetchError: null,isFetching: false,schema: null,/*** Derive validation errors from the schema*/validationErrors: [],schemaReference: null,setSchemaReference(schemaReference) {set({ schemaReference });},requestCounter: 0,shouldIntrospect: true,/*** Fetch the schema*/async introspect() {const {requestCounter,fetcher,onSchemaChange,shouldIntrospect,...rest} = get();/*** Only introspect if there is no schema provided via props. If the* prop is passed an introspection result, we do continue but skip the* introspection request.*/if (!shouldIntrospect) {return;}const counter = requestCounter + 1;set({ requestCounter: counter });try {const { headerEditor } = editorStore.getState();const currentHeaders = headerEditor?.getValue();const parsedHeaders = parseHeaderString(currentHeaders);if (!parsedHeaders.isValidJSON) {set({ fetchError: 'Introspection failed as headers are invalid.' });return;}const fetcherOpts: FetcherOpts = parsedHeaders.headers? { headers: parsedHeaders.headers }: {};/*** Get an introspection query for settings given via props*/const {introspectionQuery,introspectionQueryName,introspectionQuerySansSubscriptions,} = generateIntrospectionQuery(rest);const fetch = fetcherReturnToPromise(fetcher({query: introspectionQuery,operationName: introspectionQueryName,},fetcherOpts,),);if (!isPromise(fetch)) {set({fetchError: 'Fetcher did not return a Promise for introspection.',});return;}set({ isFetching: true, fetchError: null });let result = await fetch;if (typeof result !== 'object' ||result === null ||!('data' in result)) {// Try the stock introspection query first, falling back on the// sans-subscriptions query for services which do not yet support it.const fetch2 = fetcherReturnToPromise(fetcher({query: introspectionQuerySansSubscriptions,operationName: introspectionQueryName,},fetcherOpts,),);if (!isPromise(fetch2)) {throw new Error('Fetcher did not return a Promise for introspection.',);}result = await fetch2;}set({ isFetching: false });let introspectionData: IntrospectionQuery | undefined;if (result?.data && '__schema' in result.data) {introspectionData = result.data as IntrospectionQuery;} else {// handle as if it were an error if the fetcher response is not a string or response.data is not presentconst responseString =typeof result === 'string' ? result : formatResult(result);set({ fetchError: responseString });}/*** Don't continue if another introspection request has been started in* the meantime or if there is no introspection data.*/if (counter !== get().requestCounter || !introspectionData) {return;}const newSchema = buildClientSchema(introspectionData);set({ schema: newSchema });onSchemaChange?.(newSchema);} catch (error) {/*** Don't continue if another introspection request has been started in* the meantime.*/if (counter !== get().requestCounter) {return;}set({fetchError: formatError(error),isFetching: false,});}},}))
Const storageStore
storageStore: StoreApi<StorageContextType> = createStore<StorageContextType>(() => ({storage: null!,}))
Const useEditorStore
useEditorStore: { (): ExtractState<S>; <T>(selector: (state: ExtractState<S>) => T): T } = createBoundedUseStore(editorStore)
Type declaration
-
- (): ExtractState<S>
- <T>(selector: (state: ExtractState<S>) => T): T
-
Returns ExtractState<S>
-
Type parameters
Parameters
-
selector: (state: ExtractState<S>) => T
-
- (state: ExtractState<S>): T
Returns T
Const useExecutionStore
useExecutionStore: { (): ExtractState<S>; <T>(selector: (state: ExtractState<S>) => T): T } = createBoundedUseStore(executionStore)
Type declaration
-
- (): ExtractState<S>
- <T>(selector: (state: ExtractState<S>) => T): T
-
Returns ExtractState<S>
-
Type parameters
Parameters
-
selector: (state: ExtractState<S>) => T
-
- (state: ExtractState<S>): T
Returns T
Const usePluginStore
usePluginStore: { (): ExtractState<S>; <T>(selector: (state: ExtractState<S>) => T): T } = createBoundedUseStore(pluginStore)
Type declaration
-
- (): ExtractState<S>
- <T>(selector: (state: ExtractState<S>) => T): T
-
Returns ExtractState<S>
-
Type parameters
Parameters
-
selector: (state: ExtractState<S>) => T
-
- (state: ExtractState<S>): T
Returns T
Const useSchemaStore
useSchemaStore: { (): ExtractState<S>; <T>(selector: (state: ExtractState<S>) => T): T } = createBoundedUseStore(schemaStore)
Type declaration
-
- (): ExtractState<S>
- <T>(selector: (state: ExtractState<S>) => T): T
-
Returns ExtractState<S>
-
Type parameters
Parameters
-
selector: (state: ExtractState<S>) => T
-
- (state: ExtractState<S>): T
Returns T
Changelog | API Docs | NPM
@graphiql/react
A React SDK for building integrated GraphQL developer experiences for the web.
Purpose
This package contains a set of building blocks that allow its users to build GraphQL IDEs with ease. It's the set of components that make up GraphiQL, the first and official GraphQL IDE, owned and maintained by the GraphQL Foundation.
There are two kinds of building blocks that this package provides: Stateful context providers for state management and simple UI components.
Getting started
All the state for your GraphQL IDE lives in multiple contexts. The easiest way to get started is by using the
GraphiQLProvider
component that renders all the individual providers.There is one required prop called
fetcher
. This is a function that performs GraphQL request against a given endpoint. You can easily create a fetcher using the methodcreateGraphiQLFetcher
from the@graphiql/toolkit
package.import { GraphiQLProvider } from '@graphiql/react'; import { createGraphiQLFetcher } from '@graphiql/toolkit'; const fetcher = createGraphiQLFetcher({ url: 'https://my.graphql.api/graphql', }); function MyGraphQLIDE() { return ( <GraphiQLProvider fetcher={fetcher}> <div className="graphiql-container">Hello GraphQL</div> </GraphiQLProvider> ); }
Inside the provider you can now use any UI component provided by
@graphiql/react
. For example, you can render a query editor like this:import { QueryEditor } from '@graphiql/react'; function MyGraphQLIDE() { return ( <GraphiQLProvider fetcher={fetcher}> <div className="graphiql-container"> <QueryEditor /> </div> </GraphiQLProvider> ); }
The package also ships the necessary CSS that all its UI components need. You can import them from
@graphiql/react/style.css
.By default, the UI components will try to use the Roboto font for regular text and the Fira Code font for mono-space text. If you want to use the default fonts you can load them using these files:
@graphiql/react/font/roboto.css
@graphiql/react/font/fira-code.css
.You can of course use any other method to load these fonts (for example loading them from Google Fonts).
Further details on how to use
@graphiql/react
can be found in the reference implementation of a GraphQL IDE - GraphiQL - in thegraphiql
package.Available contexts
There are multiple contexts that own different parts of the state that make up a complete GraphQL IDE. For each context there is a provider component (
<name>ContextProvider
) that makes sure the context is initialized and managed properly. These components contains all the logic related to state management. In addition, for each context there is also a hook (use<name>Context
) that allows you to consume its current value.Here is a list of all contexts that come with
@graphiql/react
StorageContext
: Provides a storage API that can be used to persist state in the browser (by default usinglocalStorage
)EditorContext
: Manages all the editors and tabsSchemaContext
: Fetches, validates and stores the GraphQL schemaExecutionContext
: Executes GraphQL requestsHistoryContext
: Persists executed requests in storageExplorerContext
: Handles the state for the docs explorerAll context properties are documented using JSDoc comments. If you're using an IDE like VSCode for development these descriptions will show up in auto-complete tooltips. All these descriptions can also be found in the API Docs.
Theming
All the components from
@graphiql/react
have been designed with customization in mind. We achieve this using CSS variables.All variables that are available for customization can be found in the
root.css
file.Colors
Colors are defined using the HSL format. All CSS variables for colors are defined as a list of the three values that make up HSL (hue, saturation and lightness).
This approach allows
@graphiql/react
to use transparent colors by passing the value of the CSS variable in thehsla
function. This enables us to provide truly reusable UI elements where good contrasts are preserved regardless of the elements background.Development
If you want to develop with
@graphiql/react
locally - in particular when working on thegraphiql
package - all you need to do is runyarn dev
in the package folder in a separate terminal. This will build the package using Vite. When using it in combination withyarn dev:graphiql
(running in the repo root) this will give you auto-reloading when working ongraphiql
and@graphiql/react
simultaneously.