diff --git a/src/components/playground/Playground.tsx b/src/components/playground/Playground.tsx deleted file mode 100644 index d077327b4..000000000 --- a/src/components/playground/Playground.tsx +++ /dev/null @@ -1,108 +0,0 @@ -import React, {useEffect, useMemo, useState} from "react" -import {GraphiQL} from "graphiql" -import {analyticsHandler, isValidURL, sendConversionEvent} from "@site/src/utils" -import {CookiePreferenceCategory, playgroundAdsConversionId} from "@site/src/constants" -import "graphiql/graphiql.css" -import "../../css/graphiql.css" -import {type FetcherParams, FetcherOpts} from "@graphiql/toolkit" -import {useCookieConsent} from "@site/src/utils/hooks/useCookieConsent" -import {createGraphiQLFetcher} from "@graphiql/create-fetcher" - -const useDebouncedValue = (inputValue: string, delay: number) => { - const [debouncedValue, setDebouncedValue] = useState(inputValue) - - useEffect(() => { - const handler = setTimeout(() => { - setDebouncedValue(inputValue) - }, delay) - - return () => { - clearTimeout(handler) - } - }, [inputValue, delay]) - - return debouncedValue -} - -const Playground = () => { - const apiEndpointParam = typeof window !== "undefined" && new URLSearchParams(window.location.search).get("u") - const initialApiEndpoint = - (typeof apiEndpointParam === "string" && isValidURL(apiEndpointParam) && new URL(apiEndpointParam)) || "" - const [apiEndpoint, setApiEndpoint] = useState( - initialApiEndpoint !== "" ? new URL(initialApiEndpoint) : "", - ) - const [inputValue, setInputValue] = useState(initialApiEndpoint.toString()) - - const {getCookieConsent} = useCookieConsent() - const cookieConsent = getCookieConsent() - - const debouncedApiEndpoint = useDebouncedValue(inputValue, 500) - const apiEndpointInputClasses = `border border-solid border-tailCall-border-light-500 rounded-lg font-space-grotesk h-11 w-[100%] - p-SPACE_04 text-content-small outline-none focus:border-x-tailCall-light-700` - - useEffect(() => { - if (isValidURL(debouncedApiEndpoint)) { - setApiEndpoint(new URL(debouncedApiEndpoint)) - } - }, [debouncedApiEndpoint]) - - const graphQLFetcher = async (graphQLParams: FetcherParams, opts?: FetcherOpts) => { - if (apiEndpoint.toString().trim() === "") { - return Promise.resolve({}) - } - analyticsHandler("GraphQL", "tc_fetch_query", apiEndpoint.toString()) - sendConversionEvent(playgroundAdsConversionId) - - const fetcher = createGraphiQLFetcher({url: apiEndpoint.toString()}) - return fetcher(graphQLParams, opts) - } - - const emptyGraphiqlStorageObject = { - getItem: (): null => null, - setItem: (): void => undefined, - removeItem: (): void => undefined, - clear: (): void => undefined, - length: 0, - } - - const graphiqlStorage = useMemo(() => { - if ( - cookieConsent?.accepted && - (!cookieConsent?.preferences || cookieConsent?.preferences?.includes(CookiePreferenceCategory.PREFERENCE)) - ) { - // Defaults to local storage - return undefined - } - - // Block storing graphiql data in local storage if user denies cookie consent - return emptyGraphiqlStorageObject - }, [cookieConsent]) - - return ( -
- {typeof window !== "undefined" && ( -
-
- setInputValue(e.target.value)} - className={apiEndpointInputClasses} - placeholder="API Endpoint" - /> -
-
- - - <> - - -
-
- )} -
- ) -} - -export default Playground diff --git a/src/components/playground/index.tsx b/src/components/playground/index.tsx deleted file mode 100644 index 846c15cf5..000000000 --- a/src/components/playground/index.tsx +++ /dev/null @@ -1,13 +0,0 @@ -import React from "react" -import Playground from "./Playground" -import Announcement from "@site/src/components/shared/Announcement" - -const PlaygroundPage = (): JSX.Element => { - return ( - <> - - - ) -} - -export default PlaygroundPage diff --git a/src/css/graphiql.css b/src/css/graphiql.css deleted file mode 100644 index 68c7a0a92..000000000 --- a/src/css/graphiql.css +++ /dev/null @@ -1,41 +0,0 @@ -.graphiql-main { - height: 80vh; -} - -.graphiql-main * { - font-family: "Space Grotesk", sans-serif; -} - -.graphiql-query-editor *, -.graphiql-response * { - font-family: "Space Mono", sans-serif; -} - -.graphiql-dialog, -.graphiql-dialog-overlay { - z-index: var(--ifm-z-index-overlay) !important; -} - -@media (max-width: 600px) { - .graphiql-main { - flex-direction: column; - overflow: scroll; - } - - .graphiql-session { - flex-direction: column; - } - - .graphiql-response { - margin-top: 16px; - height: 30vh; - } - - .graphiql-editor-tool { - height: 10vh; - } - - button[data-value="short-keys"] { - display: none !important; - } -} diff --git a/src/pages/playground.tsx b/src/pages/playground.tsx deleted file mode 100644 index e38dbc11c..000000000 --- a/src/pages/playground.tsx +++ /dev/null @@ -1,22 +0,0 @@ -import React, {useEffect} from "react" -import ReactGA from "react-ga4" -import Layout from "@theme/Layout" -import PlaygroundPage from "../components/playground" -import {useLocation} from "@docusaurus/router" -import {PageDescription, PageTitle} from "../constants/titles" - -const Playground = () => { - const location = useLocation() - - useEffect(() => { - ReactGA.send({hitType: "pageview", page: location.pathname, title: "Playground Page"}) - }, []) - - return ( - - - - ) -} - -export default Playground diff --git a/static/playground/index.html b/static/playground/index.html new file mode 100644 index 000000000..198995db9 --- /dev/null +++ b/static/playground/index.html @@ -0,0 +1,266 @@ + + + + + + Tailcall GraphQL Playground + + + + + +
+ +
+

GraphQL Playground

+

Enter a GraphQL API endpoint to load the interactive editor only when you need it.

+
+
+
+ + + +
+
+ The editor is deferred until an endpoint is provided, keeping this page fast on first load. +
+ +
+
+ + +