diff --git a/src/client/App.tsx b/src/client/App.tsx index 27c3ee0..5396358 100644 --- a/src/client/App.tsx +++ b/src/client/App.tsx @@ -20,11 +20,13 @@ import { } from "@/client/components/Tooltip"; import { useTheme } from "@/client/contexts/theme"; import { defaultCode } from "@/client/snippets"; +import { examples } from "@/examples"; import type { ParameterWithSource, PreviewOutput, WorkspaceOwner, } from "@/gen/types"; +import { mockUsers } from "@/owner"; import { rpc } from "@/utils/rpc"; import { type WasmLoadState, @@ -36,7 +38,6 @@ import { MoonIcon, ShareIcon, SunIcon, SunMoonIcon } from "lucide-react"; import { type FC, useEffect, useMemo, useRef, useState } from "react"; import { type LoaderFunctionArgs, useLoaderData } from "react-router"; import { useDebouncedValue } from "./hooks/debounce"; -import { mockUsers } from "@/owner"; /** * Load the shared code if present. @@ -67,7 +68,9 @@ export const App = () => { return "loading"; }); const loadedCode = useLoaderData(); - const [code, setCode] = useState(loadedCode ?? defaultCode); + const [code, setCode] = useState( + loadedCode ?? window.EXAMPLE_CODE ?? defaultCode, + ); const [debouncedCode, isDebouncing] = useDebouncedValue(code, 1000); const [parameterValues, setParameterValues] = useState< Record @@ -203,14 +206,7 @@ export const App = () => { > Docs - - Support - + @@ -330,3 +326,31 @@ const ShareButton: FC = ({ code }) => { ); }; + +const ExampleSelector: FC = () => { + return ( + + + Examples + + + + + {examples.map(({ title, slug }) => { + const params = new URLSearchParams(); + params.append("example", slug); + + const href = `${window.location.origin}/parameters?${params.toString()}`; + return ( + + + {title} + + + ); + })} + + + + ); +}; diff --git a/src/examples.ts b/src/examples.ts new file mode 100644 index 0000000..308dae7 --- /dev/null +++ b/src/examples.ts @@ -0,0 +1,23 @@ +type Example = { + title: string; + slug: string; + code: string; +}; + +export const examples: Example[] = [ + { + title: "Example 1", + slug: "example-1", + code: "// Example 1", + }, + { + title: "Example 2", + slug: "example-2", + code: "// Example 2", + }, + { + title: "Example 3", + slug: "example-3", + code: "// Example 3", + }, +]; diff --git a/src/server/index.tsx b/src/server/index.tsx index 0ea6bd5..057fdd1 100644 --- a/src/server/index.tsx +++ b/src/server/index.tsx @@ -1,3 +1,4 @@ +import { examples } from "@/examples"; import { api } from "@/server/api"; import { Hono } from "hono"; import { renderToString } from "react-dom/server"; @@ -17,6 +18,15 @@ app.route("/api", api); // Serves the main web application. This must come after the API route. app.get("*", (c) => { + const getExampleCode = () => { + const { example } = c.req.query(); + if (!example) { + return; + } + + return examples.find((e) => e.slug === example)?.code; + }; + // Along with the vite React plugin this enables HMR within react while // running the dev server. const { url } = c.req; @@ -45,6 +55,9 @@ app.get("*", (c) => { : "/wasm_exec.js"; const iconPath = import.meta.env.PROD ? "/assets/logo.svg" : "/logo.svg"; + const exampleCode = getExampleCode(); + const loadExampleCodeScript = `window.EXAMPLE_CODE = "${exampleCode}"`; + return c.html( [ "", @@ -64,6 +77,9 @@ app.get("*", (c) => {
+ {exampleCode ? ( + + ) : null} , diff --git a/src/utils/wasm.ts b/src/utils/wasm.ts index 8166218..46397d0 100644 --- a/src/utils/wasm.ts +++ b/src/utils/wasm.ts @@ -20,7 +20,7 @@ declare global { // Loaded from wasm go_preview?: GoPreviewDef; Go: { new (): Go }; - CODE?: string; + EXAMPLE_CODE?: string; } }