@principal-ade/industry-themed-terminal
v0.1.14
Published
Industry-themed terminal wrapper with integrated theming for xterm.js
Downloads
1,841
Maintainers
Readme
@principal-ade/industry-themed-terminal
Industry-themed terminal wrapper with integrated theming support for xterm.js.
Features
- Seamless integration with
@a24z/industry-theme - Automatic theme synchronization with xterm.js
- Built on pure UI component architecture (no backend dependencies)
- TypeScript support with full type definitions
- Custom CSS theming via CSS custom properties
- Customizable header, badges, and overlays
- Support for all xterm.js addons (FitAddon, SearchAddon, WebLinksAddon, etc.)
- Programmatic control via imperative ref API
- Scroll preservation and user intent tracking
- Optional WebGL rendering support
Installation
npm install @principal-ade/industry-themed-terminal @xterm/xterm @a24z/industry-themeor with bun:
bun add @principal-ade/industry-themed-terminal @xterm/xterm @a24z/industry-themeOptional addons:
npm install @xterm/addon-fit @xterm/addon-search @xterm/addon-web-linksUsage
Basic Usage with Theme Provider
import { ThemedTerminalWithProvider } from '@principal-ade/industry-themed-terminal';
import '@xterm/xterm/css/xterm.css';
import '@principal-ade/industry-themed-terminal/styles.css';
function App() {
const handleData = (data: string) => {
// Send data to your backend (WebSocket, HTTP, etc.)
console.log('User input:', data);
};
return (
<ThemedTerminalWithProvider
onData={handleData}
headerTitle="Terminal"
headerSubtitle="/home/user/project"
/>
);
}Usage with Explicit Theme
import { ThemedTerminal } from '@principal-ade/industry-themed-terminal';
import { useTheme } from '@a24z/industry-theme';
import '@xterm/xterm/css/xterm.css';
import '@principal-ade/industry-themed-terminal/styles.css';
function Terminal() {
const { theme } = useTheme();
const handleData = (data: string) => {
// Send to backend
websocket.send(data);
};
return (
<ThemedTerminal
theme={theme}
onData={handleData}
headerTitle="Terminal"
/>
);
}With Programmatic Control
import { ThemedTerminal, ThemedTerminalRef } from '@principal-ade/industry-themed-terminal';
import { useRef, useEffect } from 'react';
function Terminal() {
const terminalRef = useRef<ThemedTerminalRef>(null);
useEffect(() => {
// Connect to backend
const ws = new WebSocket('wss://terminal-server.example.com');
ws.onmessage = (event) => {
// Write data from backend to terminal
terminalRef.current?.write(event.data);
};
return () => ws.close();
}, []);
const handleData = (data: string) => {
ws.send(data);
};
const handleClear = () => {
terminalRef.current?.clear();
};
return (
<>
<button onClick={handleClear}>Clear Terminal</button>
<ThemedTerminal
ref={terminalRef}
onData={handleData}
headerTitle="Terminal"
/>
</>
);
}With Custom Header and Actions
import { ThemedTerminal } from '@principal-ade/industry-themed-terminal';
function Terminal() {
return (
<ThemedTerminal
onData={handleData}
headerTitle="Terminal"
headerSubtitle="/home/user/project"
headerBadge={{ label: 'Running', color: '#50fa7b' }}
onClose={() => console.log('Hide terminal')}
onPopOut={() => console.log('Pop out terminal')}
onDestroy={() => console.log('Destroy terminal')}
/>
);
}With Overlay State
import { ThemedTerminal } from '@principal-ade/industry-themed-terminal';
import { Monitor } from 'lucide-react';
function Terminal() {
const overlayState = {
message: 'Terminal is owned by another window',
subtitle: 'This terminal is currently active in a different window.',
opacity: 1.0, // Full opacity (default) - completely hides terminal content
actions: [
{
label: 'Claim Ownership',
primary: true,
onClick: () => console.log('Claim ownership'),
},
],
};
return (
<ThemedTerminal
onData={handleData}
overlayState={overlayState}
/>
);
}The opacity property controls the overlay background opacity (0-1):
1.0(default): Full opacity - completely hides terminal content0.85: Semi-transparent - terminal content slightly visible0.5: Very transparent - terminal content clearly visible- Omitted: Defaults to
1.0for full opacity
API
ThemedTerminal Props
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| theme | Theme | Required | Industry theme object |
| onData | (data: string) => void | - | Callback when user types |
| onBinary | (data: string) => void | - | Callback for binary data |
| onResize | (cols: number, rows: number) => void | - | Callback when terminal resizes |
| onLinkClick | (url: string, isLocalhost: boolean) => void | - | Callback when link is clicked |
| headerTitle | string | 'Terminal' | Header title text |
| headerSubtitle | string | - | Header subtitle text |
| headerBadge | { label: string; color?: string } | - | Header badge |
| hideHeader | boolean | false | Hide the header |
| autoFocus | boolean | true | Auto-focus on mount |
| isVisible | boolean | true | Visibility state |
| scrollbarStyle | 'overlay' \| 'hidden' \| 'thin' \| 'auto-hide' | 'overlay' | Scrollbar style |
| onClose | () => void | - | Hide button callback |
| onDestroy | () => void | - | Destroy button callback |
| onPopOut | () => void | - | Pop-out button callback |
| overlayState | OverlayState | - | Overlay message state |
| className | string | - | Additional CSS classes |
ThemedTerminalWithProvider Props
Same as ThemedTerminal but without the theme prop (uses theme from context).
ThemedTerminalRef Methods
interface ThemedTerminalRef {
write: (data: string | Uint8Array) => void;
writeln: (data: string) => void;
clear: () => void;
scrollToBottom: () => void;
focus: () => void;
getTerminal: () => Terminal | null;
findNext: (term: string, options?: ISearchOptions) => boolean;
findPrevious: (term: string, options?: ISearchOptions) => boolean;
clearSearch: () => void;
fit: () => void;
}useThemedTerminal Hook
const { theme, getTerminalOptions } = useThemedTerminal();Returns:
theme- Processed theme object with terminal-specific valuesgetTerminalOptions()- Function that returns xterm.js terminal options
Backend Integration
This package provides only the UI component. You need to provide your own backend for terminal functionality:
WebSocket Example
import { ThemedTerminal, ThemedTerminalRef } from '@principal-ade/industry-themed-terminal';
import { useRef, useEffect } from 'react';
function Terminal() {
const terminalRef = useRef<ThemedTerminalRef>(null);
const ws = useRef<WebSocket>();
useEffect(() => {
ws.current = new WebSocket('wss://your-terminal-backend.com');
ws.current.onmessage = (event) => {
terminalRef.current?.write(event.data);
};
ws.current.onclose = () => {
terminalRef.current?.write('\r\nConnection closed\r\n');
};
return () => ws.current?.close();
}, []);
const handleData = (data: string) => {
ws.current?.send(data);
};
const handleResize = (cols: number, rows: number) => {
ws.current?.send(JSON.stringify({ type: 'resize', cols, rows }));
};
return (
<ThemedTerminal
ref={terminalRef}
onData={handleData}
onResize={handleResize}
/>
);
}CSS Custom Properties
The package uses CSS custom properties for theming:
--terminal-bg- Background color--terminal-fg- Foreground (text) color--terminal-border- Border color--terminal-header-bg- Header background--terminal-font-family- Font family--terminal-font-size- Font size
License
MIT © Principal ADE Team
