import { CopyIcon, GraphiQLProvider, GraphiQLProviderProps, PrettifyIcon, QueryEditor, ToolbarButton, Tooltip, UnStyledButton, useCopyQuery, useEditorContext, UseHeaderEditorArgs, usePluginContext, usePrettifyEditors, UseQueryEditorArgs, UseResponseEditorArgs, UseVariableEditorArgs, WriteableEditorProps, } from "@graphiql/react"; import clsx from "clsx"; import React, { ComponentType, PropsWithChildren, ReactNode } from "react"; import { useDashboardTheme, useEditorStyles, useGraphiQLThemeSwitcher, useStyles, } from "./styles"; export interface GraphiQLToolbarConfig { /** * This content will be rendered after the built-in buttons of the toolbar. * Note that this will not apply if you provide a completely custom toolbar * (by passing `GraphiQL.Toolbar` as child to the `GraphiQL` component). */ additionalContent?: React.ReactNode; } export type GraphiQLProps = Omit & GraphiQLInterfaceProps; export function GraphiQL({ dangerouslyAssumeSchemaIsValid, defaultQuery, defaultTabs, externalFragments, fetcher, getDefaultFieldNames, headers, initialTabs, inputValueDeprecation, introspectionQueryName, maxHistoryLength, onEditOperationName, onSchemaChange, onTabChange, onTogglePluginVisibility, operationName, plugins, query, response, schema, schemaDescription, shouldPersistHeaders, storage, validationRules, variables, visiblePlugin, defaultHeaders, ...props }: GraphiQLProps) { // Ensure props are correct if (typeof fetcher !== "function") { throw new TypeError( "The `GraphiQL` component requires a `fetcher` function to be passed as prop.", ); } return ( ); } // Export main windows/panes to be used separately if desired. GraphiQL.Toolbar = GraphiQLToolbar; type AddSuffix, Suffix extends string> = { [Key in keyof Obj as `${string & Key}${Suffix}`]: Obj[Key]; }; export type GraphiQLInterfaceProps = WriteableEditorProps & AddSuffix, "Query"> & Pick & AddSuffix, "Variables"> & AddSuffix, "Headers"> & Pick & { children?: ReactNode; defaultEditorToolsVisibility?: boolean | "variables" | "headers"; isHeadersEditorEnabled?: boolean; toolbar?: GraphiQLToolbarConfig; }; export function GraphiQLInterface(props: GraphiQLInterfaceProps) { const editorContext = useEditorContext({ nonNull: true }); const pluginContext = usePluginContext(); const classes = useStyles(); const { pluginResize, editorResize, editorToolsResize } = useEditorStyles(); const copy = useCopyQuery({ onCopyQuery: props.onCopyQuery }); const prettify = usePrettifyEditors(); const { rootStyle } = useDashboardTheme(); useGraphiQLThemeSwitcher(); const PluginContent = pluginContext?.visiblePlugin?.content; const children = React.Children.toArray(props.children); const toolbar = children.find(child => isChildComponentType(child, GraphiQL.Toolbar), ) || ( <> prettify()} label="Prettify query (Shift-Ctrl-P)" > copy()} label="Copy query (Shift-Ctrl-C)"> {props.toolbar?.additionalContent || null} ); const onClickReference = () => { if (pluginResize.hiddenElement === "first") { pluginResize.setHiddenElement(null); } }; return (
{pluginContext?.plugins.map(plugin => { const isVisible = plugin === pluginContext.visiblePlugin; const label = `${isVisible ? "Hide" : "Show"} ${plugin.title}`; const Icon = plugin.icon; return ( { if (isVisible) { pluginContext.setVisiblePlugin(null); pluginResize.setHiddenElement("first"); } else { pluginContext.setVisiblePlugin(plugin); pluginResize.setHiddenElement(null); } }} aria-label={label} > ); })}
{PluginContent ? : null}
{pluginContext?.visiblePlugin ? (
) : null}
{toolbar}
); } function GraphiQLToolbar(props: PropsWithChildren) { return <>{props.children}; } GraphiQLToolbar.displayName = "GraphiQLToolbar"; function isChildComponentType( child: any, component: T, ): child is T { if ( child?.type?.displayName && child.type.displayName === component.displayName ) { return true; } return child.type === component; } export default GraphiQL;