Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
92 changes: 91 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ TypeScript-first React component package scaffold with:

- `npm run typecheck`: Validate TypeScript.
- `npm run build`: Build ESM, CJS, and declaration outputs.
- `npm run test:visual`: Build package and start visual harness server.
- `npm run test:visual`: Start the visual harness server.

## Sandbox terminal usage

Expand Down Expand Up @@ -243,6 +243,96 @@ Terminal primitives support:

You can also create a reusable spreadable config with `createTerminalTheme(...)`.

## Filesystem workspace usage

The public filesystem path is built from two layers:

- `HyperbrowserFileWorkspace`: ready-to-use Hyperbrowser-backed filesystem browser
- `FileWorkspace`: lower-level browser shell when you want to bring your own adapter

Import the packaged stylesheet once in your app entrypoint:

```tsx
import "@hyperbrowser/ui/styles.css";
```

### Basic `HyperbrowserFileWorkspace` example

```tsx
import { useCallback } from "react";
import {
createFileWorkspaceTheme,
HyperbrowserFileWorkspace,
type HyperbrowserFilesystemBrowserAuthParams,
} from "@hyperbrowser/ui";
import "@hyperbrowser/ui/styles.css";

export function SandboxFiles({
sandboxId,
}: {
sandboxId: string;
}) {
const getRuntimeBrowserAuth = useCallback(
async ({
browserAuthEndpoint,
sandboxId: resolvedSandboxId,
signal,
}: HyperbrowserFilesystemBrowserAuthParams) => {
if (!browserAuthEndpoint) {
throw new Error("Sandbox filesystem auth endpoint is unavailable.");
}

const response = await fetch(browserAuthEndpoint, {
method: "POST",
signal,
});

if (!response.ok) {
throw new Error(
`Failed to get filesystem auth for sandbox ${resolvedSandboxId ?? sandboxId}.`,
);
}

return response.json();
},
[sandboxId],
);

const filesystemTheme = createFileWorkspaceTheme("basic", {
appearance: "dark",
});

return (
<HyperbrowserFileWorkspace
{...filesystemTheme}
getRuntimeBrowserAuth={getRuntimeBrowserAuth}
sandboxId={sandboxId}
style={{ minHeight: 720 }}
title="Sandbox Files"
workspacePath="/workspace"
/>
);
}
```

Notes:

- `getRuntimeBrowserAuth(...)` receives `{ signal, sandboxId, browserAuthEndpoint }`.
- `sandboxId` is the standard customer path.
- `runtimeBaseUrl + bootstrapUrl` is also supported for already-bootstrapped runtime sessions.
- `apiBaseUrl` is only needed when you want the library to call the control-plane endpoint directly or when you need a non-default control-plane base.

### Filesystem theming

Filesystem theming supports:

- `preset`: one of `basic`, `atlas`, `ledger`
- `appearance`: `"dark"` or `"light"`
- `chromeTheme`: partial chrome overrides
- `editorTheme`: partial editor typography overrides

You can create a reusable spreadable config with `createFileWorkspaceTheme(...)`.

## VNC component usage

`HyperbrowserVncViewer` renders a noVNC viewer using a Hyperbrowser session token and
Expand Down
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
"default": "./dist/esm/index.js"
},
"./styles.css": "./dist/styles/styles.css",
"./filesystem.css": "./dist/styles/filesystem.css",
"./terminal-core.css": "./dist/styles/terminal-core.css",
"./terminal.css": "./dist/styles/terminal.css",
"./package.json": "./package.json"
Expand All @@ -34,7 +35,7 @@
"build": "npm run clean && npm run build:esm && npm run build:cjs && npm run build:types && node ./scripts/write-dist-package-jsons.mjs && node ./scripts/copy-static-assets.mjs",
"prepublishOnly": "npm run build",
"typecheck": "tsc -p ./tsconfig.base.json --noEmit",
"test:visual": "npm run build && vite --config ./tests/visual/vite.config.mjs"
"test:visual": "vite --config ./tests/visual/vite.config.mjs"
},
"peerDependencies": {
"react": ">=18 <20",
Expand All @@ -44,7 +45,6 @@
"@xterm/addon-fit": "^0.11.0",
"@xterm/xterm": "^6.0.0",
"hls.js": "^1.6.13",
"monaco-editor": "^0.52.2",
"react-vnc": "^3.2.0"
},
"devDependencies": {
Expand Down
36 changes: 30 additions & 6 deletions scripts/copy-static-assets.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,12 @@ const sourceTerminalCoreStylesPath = path.join(
"terminal-core.css"
);
const sourceTerminalStylesPath = path.join(rootDir, "src", "styles", "terminal.css");
const sourceFilesystemStylesPath = path.join(
rootDir,
"src",
"styles",
"filesystem.css"
);
const xtermStylesPath = path.join(
rootDir,
"node_modules",
Expand All @@ -23,14 +29,22 @@ const terminalCoreBundle = (xtermStyles, terminalCoreStyles) =>
`${xtermStyles.trim()}\n\n${terminalCoreStyles.trim()}\n`;
const terminalBundle = (xtermStyles, terminalCoreStyles, terminalStyles) =>
`${terminalCoreBundle(xtermStyles, terminalCoreStyles).trim()}\n\n${terminalStyles.trim()}\n`;
const fullStylesBundle = (
xtermStyles,
terminalCoreStyles,
terminalStyles,
filesystemStyles
) => `${terminalBundle(xtermStyles, terminalCoreStyles, terminalStyles).trim()}\n\n${filesystemStyles.trim()}\n`;

await mkdir(distStylesDir, { recursive: true });

const [xtermStyles, terminalCoreStyles, terminalStyles] = await Promise.all([
readFile(xtermStylesPath, "utf8"),
readFile(sourceTerminalCoreStylesPath, "utf8"),
readFile(sourceTerminalStylesPath, "utf8"),
]);
const [xtermStyles, terminalCoreStyles, terminalStyles, filesystemStyles] =
await Promise.all([
readFile(xtermStylesPath, "utf8"),
readFile(sourceTerminalCoreStylesPath, "utf8"),
readFile(sourceTerminalStylesPath, "utf8"),
readFile(sourceFilesystemStylesPath, "utf8"),
]);

await Promise.all([
writeFile(
Expand All @@ -43,9 +57,19 @@ await Promise.all([
terminalBundle(xtermStyles, terminalCoreStyles, terminalStyles),
"utf8"
),
writeFile(
path.join(distStylesDir, "filesystem.css"),
`${filesystemStyles.trim()}\n`,
"utf8"
),
writeFile(
path.join(distStylesDir, "styles.css"),
terminalBundle(xtermStyles, terminalCoreStyles, terminalStyles),
fullStylesBundle(
xtermStyles,
terminalCoreStyles,
terminalStyles,
filesystemStyles
),
"utf8"
),
]);
Loading