SPB Git forge

spb/fetcha

Public
11commits 1branches 0releases
1.5 MBsize
maindefault branch
16 days agolast push
TypeScript 97.5% SQL 1.4% Python 0.8%
4.1 KB · 82 lines tsx
Raw Blame History
1"use client";2import * as React from "react";3import Link from "next/link";4import type { FetchRequestInput } from "@fetcha/core/client";5import { KeyRound } from "lucide-react";6import { CodeBlock } from "@/components/ui/code-block";7import { CopyButton } from "@/components/ui/copy-button";8import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select";9import { CODEGEN_LANGS, codegenInfo, generateCode, type CodegenLang } from "@/lib/codegen";10import { cn } from "@/lib/utils";11import type { PlaygroundKey } from "./types";1213export function keyPlaceholder(k: PlaygroundKey | undefined): string {14  if (!k) return "YOUR_API_KEY";15  const prefix = k.keyPrefix.endsWith("_") ? k.keyPrefix : `${k.keyPrefix}_`;16  return `${prefix}••••${k.last4}`;17}1819/** Language tabs + API key selector + generated snippet for the current request. */20export function CodePanel({ request, keys, baseUrl, lang, onLangChange, keyId, onKeyChange, className }: { request: FetchRequestInput; keys: PlaygroundKey[]; baseUrl: string; lang: CodegenLang; onLangChange: (l: CodegenLang) => void; keyId: string; onKeyChange: (id: string) => void; className?: string }) {21  const key = keys.find((k) => k.id === keyId) ?? keys[0];22  const info = codegenInfo(lang);23  const code = React.useMemo(() => generateCode(lang, request, { apiKeyPlaceholder: keyPlaceholder(key), baseUrl }), [lang, request, key, baseUrl]);2425  return (26    <div className={cn("grid gap-3", className)}>27      <div className="flex flex-col gap-2 sm:flex-row sm:items-center sm:justify-between">28        <div role="tablist" aria-label="Language" className="flex items-center gap-1 overflow-x-auto no-scrollbar -mx-1 px-1">29          {CODEGEN_LANGS.map((l) => (30            <button31              key={l.id}32              type="button"33              role="tab"34              aria-selected={l.id === lang}35              onClick={() => onLangChange(l.id)}36              className={cn("h-7 shrink-0 rounded-[5px] px-2.5 text-[12.5px] font-medium transition-colors focus:outline-none focus-visible:ring-2 focus-visible:ring-accent/30", l.id === lang ? "bg-fg text-bg" : "text-fg-muted hover:bg-bg-muted hover:text-fg")}37            >38              {l.label}39            </button>40          ))}41        </div>42        <div className="flex items-center gap-2 sm:shrink-0">43          {keys.length ? (44            <Select value={key?.id ?? ""} onValueChange={onKeyChange}>45              <SelectTrigger className="h-8 w-full sm:w-[220px] text-[12.5px]" aria-label="API key used in the snippet">46                <KeyRound className="size-3.5 shrink-0 text-fg-subtle" aria-hidden />47                <SelectValue placeholder="API key" />48              </SelectTrigger>49              <SelectContent>50                {keys.map((k) => (51                  <SelectItem key={k.id} value={k.id}>52                    <span className="font-mono text-[12px]">{keyPlaceholder(k)}</span>53                    <span className="ml-2 text-fg-muted">{k.name}</span>54                  </SelectItem>55                ))}56              </SelectContent>57            </Select>58          ) : null}59          <CopyButton value={code} label="Copy" variant="outline" size="sm" className="h-8 text-fg" />60        </div>61      </div>62      <CodeBlock code={code} lang={info.codeLang} title={`fetch.${info.ext}`} maxHeight={480} copy={false} />63      <p className="text-xs text-fg-subtle leading-relaxed">64        {keys.length ? (65          <>66            <span className="font-mono">{keyPlaceholder(key)}</span> is a placeholder for <span className="font-medium text-fg-muted">{key?.name}</span>. Replace it with your key — keys are only shown once, at creation.{" "}67          </>68        ) : (69          <>70            This project has no API key yet.{" "}71            <Link href="/dashboard/api-keys" className="text-accent underline-offset-4 hover:underline">72              Create one73            </Link>{" "}74            and replace <span className="font-mono">YOUR_API_KEY</span>.{" "}75          </>76        )}77        {lang === "typescript" || lang === "python-sdk" ? "SDKs are not published yet: install from source (repo packages/sdk and sdk-python)." : null}78      </p>79    </div>80  );81}82