Docs / Sandbox and code /
CodeEditorPane
Read-only code pane with syntax highlighting, line numbers, and optional line range focus.
Preview
src/lib/auth.tstypescript
1import { SignJWT, jwtVerify } from 'jose'2import { db } from './db'3 4const SECRET = new TextEncoder().encode(process.env.JWT_SECRET!)5 6export class AuthError extends Error {}7 8export async function signToken(userId: string): Promise<string> {9 return new SignJWT({ sub: userId })Agent added sub claim for user identity10 .setProtectedHeader({ alg: 'HS256' })11 .setExpirationTime('7d')12 .sign(SECRET)13}14 15export async function verifyJWT(token: string) {16 const { payload } = await jwtVerify(token, SECRET)17 if (!payload.sub) throw new AuthError('Invalid token')Consider checking token expiry explicitly18 return payload19}Variants
TypeScript
src/lib/auth.tstypescript
1import { SignJWT, jwtVerify } from 'jose'2import { db } from './db'3 4const SECRET = new TextEncoder().encode(process.env.JWT_SECRET!)5 6export class AuthError extends Error {}7 8export async function signToken(userId: string): Promise<string> {9 return new SignJWT({ sub: userId })Agent added sub claim for user identity10 .setProtectedHeader({ alg: 'HS256' })11 .setExpirationTime('7d')12 .sign(SECRET)13}14 15export async function verifyJWT(token: string) {16 const { payload } = await jwtVerify(token, SECRET)17 if (!payload.sub) throw new AuthError('Invalid token')Consider checking token expiry explicitly18 return payload19}JSON
tsconfig.jsonjson
1{2 "compilerOptions": {3 "target": "ES2022",4 "lib": ["dom", "dom.iterable", "esnext"],5 "allowJs": true,6 "skipLibCheck": true,7 "strict": true,8 "noEmit": true,9 "esModuleInterop": true,10 "module": "esnext",11 "moduleResolution": "bundler",12 "resolveJsonModule": true,13 "isolatedModules": true,14 "jsx": "preserve",15 "incremental": true,16 "paths": {17 "@/*": ["./src/*"]18 }19 },20 "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx"],21 "exclude": ["node_modules"]22}Props
| Prop | Type | Description |
|---|---|---|
| tabs* | SandboxTab[] | Open file tabs. Each tab carries an id, label, optional path, dirty flag, and badge. |
| activeTab* | string | The id of the currently active tab. |
| onSelectTab* | (id: string) => void | Called when a tab is clicked. |
| onCloseTab | (id: string) => void | When provided, shows a close button on each tab. |
| onNewTab | () => void | When provided, shows a + button to open a new tab. |
| lines* | EditorLine[] | Source lines for the active file. Supports agentEdit, failing, matched highlights, and inline annotations. |
| language | string | Language label shown in the breadcrumb. Defaults to 'typescript'. |
| path | string | File path shown in the breadcrumb bar. |
| cursor | { line: number; col: number } | Cursor position shown in the status bar. |
| status | { ok: boolean; message: string } | Diagnostic status shown in the status bar. |
| className | string | Additional class names for the root element. |
* required.
Usage
import { CodeEditorPane } from "@/components/sandbox/code-editor-pane";
<CodeEditorPane
tabs={[{ id: "auth", label: "auth.ts", path: "src/lib/auth.ts", dirty: true }]}
activeTab="auth"
onSelectTab={setActiveTab}
lines={[
{ text: "export async function signToken(userId: string) {" },
{ text: " // ...", agentEdit: true },
{ text: "}" },
]}
path="src/lib/auth.ts"
language="typescript"
cursor={{ line: 2, col: 8 }}
status={{ ok: true, message: "No errors" }}
/>