green-screen-react 0.4.0 → 1.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +33 -259
- package/dist/index.d.mts +40 -91
- package/dist/index.d.ts +40 -91
- package/dist/index.js +208 -64
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +207 -64
- package/dist/index.mjs.map +1 -1
- package/dist/styles.css +28 -1
- package/package.json +5 -3
- package/LICENSE +0 -21
package/README.md
CHANGED
|
@@ -1,76 +1,31 @@
|
|
|
1
|
-
#
|
|
1
|
+
# green-screen-react
|
|
2
2
|
|
|
3
|
-
Multi-protocol legacy terminal
|
|
3
|
+
Multi-protocol legacy terminal React component. Connects to **TN5250** (IBM i / AS/400), **TN3270** (z/OS mainframe), **VT220** (OpenVMS, Unix), and **HP 6530** (NonStop) hosts.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
[**Live Preview**](https://visionbridge-solutions.github.io/green-screen-react/)
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
- **Real-time WebSocket** — instant screen updates
|
|
9
|
-
- Protocol-specific color conventions and screen dimensions
|
|
10
|
-
- Keyboard input: text, function keys (F1-F24), tab, arrow keys
|
|
11
|
-
- Field-aware rendering with input field underlines
|
|
12
|
-
- Typing animation with correction detection
|
|
13
|
-
- Auto-reconnect with exponential backoff
|
|
14
|
-
- Fully themeable via CSS custom properties
|
|
15
|
-
- Zero runtime dependencies (peer deps: React 18+)
|
|
16
|
-
- Togglable inline sign-in form (host, credentials, protocol picker)
|
|
17
|
-
- Pluggable adapter interface for any backend
|
|
18
|
-
- Mock mode for instant evaluation without a real host
|
|
7
|
+
## Install
|
|
19
8
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
Browsers cannot open raw TCP sockets to telnet hosts. You need a backend that bridges WebSocket to TCP. Choose one:
|
|
23
|
-
|
|
24
|
-
**Option A — Run locally (development):**
|
|
25
|
-
```
|
|
26
|
-
Your React App green-screen-proxy Legacy Host
|
|
27
|
-
┌──────────────┐ ┌──────────────────┐ ┌──────────────┐
|
|
28
|
-
│ <GreenScreen│ WS │ Node.js proxy │ TCP │ IBM i │
|
|
29
|
-
│ Terminal/> │◄──────►│ localhost:3001 │◄──────►│ Mainframe │
|
|
30
|
-
│ │ │ │ │ VMS / etc. │
|
|
31
|
-
└──────────────┘ └──────────────────┘ └──────────────┘
|
|
32
|
-
npm install npx green-screen-proxy
|
|
33
|
-
green-screen-react
|
|
34
|
-
```
|
|
35
|
-
|
|
36
|
-
**Option B — Deploy to Cloudflare (production):**
|
|
37
|
-
```
|
|
38
|
-
Your React App Cloudflare Worker Legacy Host
|
|
39
|
-
┌──────────────┐ ┌──────────────────┐ ┌──────────────┐
|
|
40
|
-
│ <GreenScreen│ WS │ Durable Object │ TCP │ IBM i │
|
|
41
|
-
│ Terminal/> │◄──────►│ holds TCP conn │◄──────►│ Mainframe │
|
|
42
|
-
│ │ │ │ │ VMS / etc. │
|
|
43
|
-
└──────────────┘ └──────────────────┘ └──────────────┘
|
|
44
|
-
npm install npx green-screen-proxy deploy
|
|
45
|
-
green-screen-react
|
|
9
|
+
```bash
|
|
10
|
+
npm install green-screen-react green-screen-proxy
|
|
46
11
|
```
|
|
47
12
|
|
|
48
|
-
| | Node.js Proxy | Cloudflare Worker |
|
|
49
|
-
|---|---|---|
|
|
50
|
-
| Run with | `npx green-screen-proxy` | `npx green-screen-proxy deploy` |
|
|
51
|
-
| Transport | WebSocket (real-time) | WebSocket (real-time) |
|
|
52
|
-
| Best for | Local dev, self-hosted infra | Production, static sites |
|
|
53
|
-
| Cost | Free (your server) | Free (Cloudflare free tier) |
|
|
54
|
-
|
|
55
|
-
Both use the same WebSocket protocol, so `WebSocketAdapter` works with either.
|
|
56
|
-
|
|
57
13
|
## Quick Start
|
|
58
14
|
|
|
59
|
-
|
|
15
|
+
Start the proxy (separate terminal):
|
|
60
16
|
|
|
61
17
|
```bash
|
|
62
|
-
|
|
18
|
+
npx green-screen-proxy
|
|
63
19
|
```
|
|
64
20
|
|
|
65
|
-
|
|
21
|
+
Or start it programmatically from your app:
|
|
66
22
|
|
|
67
|
-
```
|
|
68
|
-
|
|
23
|
+
```typescript
|
|
24
|
+
import { createProxy } from 'green-screen-proxy';
|
|
25
|
+
await createProxy({ port: 3001 });
|
|
69
26
|
```
|
|
70
27
|
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
**Step 3 — Render the terminal:**
|
|
28
|
+
Render the component:
|
|
74
29
|
|
|
75
30
|
```tsx
|
|
76
31
|
import { GreenScreenTerminal } from 'green-screen-react';
|
|
@@ -81,77 +36,7 @@ function App() {
|
|
|
81
36
|
}
|
|
82
37
|
```
|
|
83
38
|
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
## Production Deployment (Cloudflare Worker)
|
|
87
|
-
|
|
88
|
-
Deploy a serverless backend with one command — no server to manage:
|
|
89
|
-
|
|
90
|
-
```bash
|
|
91
|
-
npx green-screen-proxy deploy
|
|
92
|
-
```
|
|
93
|
-
|
|
94
|
-
This will:
|
|
95
|
-
1. Install Wrangler (Cloudflare CLI) if not present
|
|
96
|
-
2. Log you in to Cloudflare if needed
|
|
97
|
-
3. Deploy the worker and print the URL
|
|
98
|
-
4. Save the URL to `.env.local` (auto-detects Vite, Next.js, CRA)
|
|
99
|
-
|
|
100
|
-
Then use it in your app:
|
|
101
|
-
|
|
102
|
-
```tsx
|
|
103
|
-
import { GreenScreenTerminal, WebSocketAdapter } from 'green-screen-react';
|
|
104
|
-
import 'green-screen-react/styles.css';
|
|
105
|
-
|
|
106
|
-
// Reads from VITE_GREEN_SCREEN_URL / NEXT_PUBLIC_GREEN_SCREEN_URL / REACT_APP_GREEN_SCREEN_URL
|
|
107
|
-
const adapter = new WebSocketAdapter({
|
|
108
|
-
workerUrl: import.meta.env.VITE_GREEN_SCREEN_URL
|
|
109
|
-
});
|
|
110
|
-
|
|
111
|
-
<GreenScreenTerminal adapter={adapter} />
|
|
112
|
-
```
|
|
113
|
-
|
|
114
|
-
If no `workerUrl` is provided, the adapter defaults to `http://localhost:3001` (the local proxy).
|
|
115
|
-
|
|
116
|
-
### Deploy options
|
|
117
|
-
|
|
118
|
-
```bash
|
|
119
|
-
npx green-screen-proxy deploy # Default settings
|
|
120
|
-
npx green-screen-proxy deploy --name my-terminal # Custom worker name
|
|
121
|
-
npx green-screen-proxy deploy --origins https://myapp.com # Lock CORS to your domain
|
|
122
|
-
```
|
|
123
|
-
|
|
124
|
-
User-deployed workers have no restrictions. The shared demo worker (GitHub Pages) has rate limiting and SSRF protection.
|
|
125
|
-
|
|
126
|
-
## Proxy Server
|
|
127
|
-
|
|
128
|
-
The Node.js proxy is ideal for local development and self-hosted environments.
|
|
129
|
-
|
|
130
|
-
```bash
|
|
131
|
-
npx green-screen-proxy # Start on port 3001
|
|
132
|
-
npx green-screen-proxy --mock # Mock mode (no real host needed)
|
|
133
|
-
npx green-screen-proxy --port 8080 # Custom port
|
|
134
|
-
PORT=8080 npx green-screen-proxy # Port via environment variable
|
|
135
|
-
```
|
|
136
|
-
|
|
137
|
-
If you prefer to install it:
|
|
138
|
-
|
|
139
|
-
```bash
|
|
140
|
-
npm install -g green-screen-proxy
|
|
141
|
-
green-screen-proxy
|
|
142
|
-
```
|
|
143
|
-
|
|
144
|
-
### Connecting to a real host
|
|
145
|
-
|
|
146
|
-
Without `--mock`, the proxy opens real TCP connections. The sign-in form in the terminal collects host, port, protocol, and credentials — the proxy handles the rest.
|
|
147
|
-
|
|
148
|
-
Example: connecting to the public IBM i system at `pub400.com`:
|
|
149
|
-
|
|
150
|
-
```tsx
|
|
151
|
-
<GreenScreenTerminal defaultProtocol="tn5250" />
|
|
152
|
-
```
|
|
153
|
-
|
|
154
|
-
Enter `pub400.com` as the host in the sign-in form. The component connects to the local proxy automatically.
|
|
39
|
+
Connects to `localhost:3001` automatically. Use the sign-in form to connect to a real host.
|
|
155
40
|
|
|
156
41
|
## Adapters
|
|
157
42
|
|
|
@@ -162,18 +47,18 @@ Real-time bidirectional WebSocket. Works with both the Node.js proxy and the Clo
|
|
|
162
47
|
```tsx
|
|
163
48
|
import { WebSocketAdapter } from 'green-screen-react';
|
|
164
49
|
|
|
165
|
-
// Local proxy
|
|
50
|
+
// Local proxy (default)
|
|
166
51
|
const adapter = new WebSocketAdapter({ workerUrl: 'http://localhost:3001' });
|
|
167
52
|
|
|
168
53
|
// Cloudflare Worker
|
|
169
54
|
const adapter = new WebSocketAdapter({
|
|
170
55
|
workerUrl: 'https://green-screen-worker.your-subdomain.workers.dev'
|
|
171
56
|
});
|
|
172
|
-
```
|
|
173
57
|
|
|
174
|
-
|
|
58
|
+
<GreenScreenTerminal adapter={adapter} />
|
|
59
|
+
```
|
|
175
60
|
|
|
176
|
-
### RestAdapter
|
|
61
|
+
### RestAdapter
|
|
177
62
|
|
|
178
63
|
For backends that expose a REST API:
|
|
179
64
|
|
|
@@ -186,133 +71,46 @@ const adapter = new RestAdapter({
|
|
|
186
71
|
});
|
|
187
72
|
```
|
|
188
73
|
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
| Method | Path | Request Body |
|
|
192
|
-
|--------|------|-------------|
|
|
193
|
-
| GET | `/screen` | - |
|
|
194
|
-
| GET | `/status` | - |
|
|
195
|
-
| POST | `/connect` | `{ host, port, protocol }` |
|
|
196
|
-
| POST | `/send-text` | `{ text }` |
|
|
197
|
-
| POST | `/send-key` | `{ key }` |
|
|
198
|
-
| POST | `/disconnect` | - |
|
|
199
|
-
| POST | `/reconnect` | - |
|
|
200
|
-
|
|
201
|
-
### Custom Adapters
|
|
74
|
+
### Custom Adapter
|
|
202
75
|
|
|
203
76
|
Implement `TerminalAdapter` to connect to any backend:
|
|
204
77
|
|
|
205
78
|
```typescript
|
|
206
|
-
import type { TerminalAdapter
|
|
79
|
+
import type { TerminalAdapter } from 'green-screen-react';
|
|
207
80
|
|
|
208
81
|
class MyAdapter implements TerminalAdapter {
|
|
209
|
-
async getScreen()
|
|
210
|
-
async getStatus()
|
|
211
|
-
async sendText(text: string)
|
|
212
|
-
async sendKey(key: string)
|
|
213
|
-
async connect(config
|
|
214
|
-
async disconnect()
|
|
215
|
-
async reconnect()
|
|
82
|
+
async getScreen() { /* ... */ }
|
|
83
|
+
async getStatus() { /* ... */ }
|
|
84
|
+
async sendText(text: string) { /* ... */ }
|
|
85
|
+
async sendKey(key: string) { /* ... */ }
|
|
86
|
+
async connect(config?) { /* ... */ }
|
|
87
|
+
async disconnect() { /* ... */ }
|
|
88
|
+
async reconnect() { /* ... */ }
|
|
216
89
|
}
|
|
217
90
|
```
|
|
218
91
|
|
|
219
|
-
## Component Usage
|
|
220
|
-
|
|
221
|
-
### Minimal (inline sign-in)
|
|
222
|
-
|
|
223
|
-
```tsx
|
|
224
|
-
import { GreenScreenTerminal } from 'green-screen-react';
|
|
225
|
-
import 'green-screen-react/styles.css';
|
|
226
|
-
|
|
227
|
-
// Connects to localhost:3001 by default. Sign-in form collects host and credentials.
|
|
228
|
-
<GreenScreenTerminal />
|
|
229
|
-
```
|
|
230
|
-
|
|
231
|
-
### Switching protocols
|
|
232
|
-
|
|
233
|
-
```tsx
|
|
234
|
-
<GreenScreenTerminal adapter={adapter} protocol="tn3270" />
|
|
235
|
-
<GreenScreenTerminal adapter={adapter} protocol="vt" />
|
|
236
|
-
<GreenScreenTerminal adapter={adapter} protocol="hp6530" />
|
|
237
|
-
```
|
|
238
|
-
|
|
239
|
-
### Inline Sign-In
|
|
240
|
-
|
|
241
|
-
The sign-in form appears by default when disconnected. It collects host, port, protocol, and credentials.
|
|
242
|
-
|
|
243
|
-
```tsx
|
|
244
|
-
// Disable the form (use when you manage connections yourself)
|
|
245
|
-
<GreenScreenTerminal adapter={adapter} inlineSignIn={false} />
|
|
246
|
-
|
|
247
|
-
// Pre-select a protocol
|
|
248
|
-
<GreenScreenTerminal
|
|
249
|
-
adapter={adapter}
|
|
250
|
-
defaultProtocol="tn3270"
|
|
251
|
-
onSignIn={(config) => console.log('Connecting to', config.host)}
|
|
252
|
-
/>
|
|
253
|
-
```
|
|
254
|
-
|
|
255
92
|
## Props
|
|
256
93
|
|
|
257
94
|
| Prop | Type | Default | Description |
|
|
258
95
|
|------|------|---------|-------------|
|
|
259
|
-
| `adapter` | `TerminalAdapter` |
|
|
260
|
-
| `baseUrl` | `string` | - | Shorthand — auto-creates a RestAdapter |
|
|
96
|
+
| `adapter` | `TerminalAdapter` | auto | Backend adapter |
|
|
261
97
|
| `protocol` | `'tn5250' \| 'tn3270' \| 'vt' \| 'hp6530'` | `'tn5250'` | Terminal protocol |
|
|
262
|
-
| `protocolProfile` | `ProtocolProfile` | - | Custom protocol profile (overrides `protocol`) |
|
|
263
|
-
| `screenData` | `ScreenData` | - | Direct screen data injection (bypasses polling) |
|
|
264
|
-
| `connectionStatus` | `ConnectionStatus` | - | Direct status injection |
|
|
265
98
|
| `inlineSignIn` | `boolean` | `true` | Show sign-in form when disconnected |
|
|
266
|
-
| `defaultProtocol` | `TerminalProtocol` | `'tn5250'` | Pre-selected protocol in sign-in
|
|
267
|
-
| `onSignIn` | `(config) => void` | - | Sign-in submit callback |
|
|
99
|
+
| `defaultProtocol` | `TerminalProtocol` | `'tn5250'` | Pre-selected protocol in sign-in |
|
|
268
100
|
| `readOnly` | `boolean` | `false` | Disable keyboard input |
|
|
269
|
-
| `pollInterval` | `number` | `2000` | Screen polling interval
|
|
101
|
+
| `pollInterval` | `number` | `2000` | Screen polling interval (ms) |
|
|
270
102
|
| `autoReconnect` | `boolean` | `true` | Auto-reconnect on disconnect |
|
|
271
|
-
| `maxReconnectAttempts` | `number` | `5` | Max reconnect attempts |
|
|
272
103
|
| `embedded` | `boolean` | `false` | Compact embedded mode |
|
|
273
104
|
| `showHeader` | `boolean` | `true` | Show header bar |
|
|
274
105
|
| `typingAnimation` | `boolean` | `true` | Enable typing animation |
|
|
275
|
-
| `bootLoader` | `ReactNode \| false` | default | Custom boot loader
|
|
276
|
-
| `
|
|
277
|
-
| `overlay` | `ReactNode` | - | Custom overlay content |
|
|
278
|
-
| `onNotification` | `(msg, type) => void` | - | Notification callback |
|
|
106
|
+
| `bootLoader` | `ReactNode \| false` | default | Custom boot loader |
|
|
107
|
+
| `onSignIn` | `(config) => void` | - | Sign-in callback |
|
|
279
108
|
| `onScreenChange` | `(screen) => void` | - | Screen change callback |
|
|
280
|
-
| `className` | `string` | - |
|
|
109
|
+
| `className` | `string` | - | CSS class |
|
|
281
110
|
| `style` | `CSSProperties` | - | Inline styles |
|
|
282
111
|
|
|
283
|
-
## Key Types
|
|
284
|
-
|
|
285
|
-
```typescript
|
|
286
|
-
interface ScreenData {
|
|
287
|
-
content: string; // Newline-separated text (24 lines of 80 chars)
|
|
288
|
-
cursor_row: number; // 0-based cursor row
|
|
289
|
-
cursor_col: number; // 0-based cursor column
|
|
290
|
-
rows?: number; // Terminal rows (default 24)
|
|
291
|
-
cols?: number; // Terminal columns (default 80)
|
|
292
|
-
fields?: Field[]; // Input/protected field definitions
|
|
293
|
-
}
|
|
294
|
-
|
|
295
|
-
interface ConnectionStatus {
|
|
296
|
-
connected: boolean;
|
|
297
|
-
status: 'disconnected' | 'connecting' | 'connected' | 'authenticated' | 'error';
|
|
298
|
-
protocol?: TerminalProtocol;
|
|
299
|
-
host?: string;
|
|
300
|
-
error?: string;
|
|
301
|
-
}
|
|
302
|
-
|
|
303
|
-
interface Field {
|
|
304
|
-
row: number; // 0-based row
|
|
305
|
-
col: number; // 0-based column
|
|
306
|
-
length: number; // Field length in characters
|
|
307
|
-
is_input: boolean; // Accepts user input
|
|
308
|
-
is_protected: boolean; // Read-only
|
|
309
|
-
}
|
|
310
|
-
```
|
|
311
|
-
|
|
312
112
|
## Theming
|
|
313
113
|
|
|
314
|
-
Override CSS custom properties to customize the look:
|
|
315
|
-
|
|
316
114
|
```css
|
|
317
115
|
:root {
|
|
318
116
|
--terminal-green: #10b981;
|
|
@@ -326,30 +124,6 @@ Override CSS custom properties to customize the look:
|
|
|
326
124
|
}
|
|
327
125
|
```
|
|
328
126
|
|
|
329
|
-
## Exports
|
|
330
|
-
|
|
331
|
-
### Adapters
|
|
332
|
-
|
|
333
|
-
- `WebSocketAdapter` — Real-time WebSocket (works with proxy and worker)
|
|
334
|
-
- `RestAdapter` — HTTP polling
|
|
335
|
-
|
|
336
|
-
### Hooks
|
|
337
|
-
|
|
338
|
-
- `useTerminalConnection(adapter)` — Connection lifecycle
|
|
339
|
-
- `useTerminalScreen(adapter, interval, enabled)` — Screen polling
|
|
340
|
-
- `useTerminalInput(adapter)` — Send text/key operations
|
|
341
|
-
- `useTypingAnimation(content, enabled, budgetMs)` — Typing animation
|
|
342
|
-
|
|
343
|
-
### Protocol Profiles
|
|
344
|
-
|
|
345
|
-
- `getProtocolProfile(protocol)` — Get built-in profile by name
|
|
346
|
-
- `tn5250Profile`, `tn3270Profile`, `vtProfile`, `hp6530Profile`
|
|
347
|
-
|
|
348
|
-
### Utilities
|
|
349
|
-
|
|
350
|
-
- `positionToRowCol(content, position)` — Convert linear position to row/col
|
|
351
|
-
- `isFieldEntry(prev, next)` — Detect field entry vs screen transition
|
|
352
|
-
|
|
353
127
|
## License
|
|
354
128
|
|
|
355
129
|
MIT
|
package/dist/index.d.mts
CHANGED
|
@@ -1,10 +1,8 @@
|
|
|
1
1
|
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
2
|
import React from 'react';
|
|
3
|
+
import { ScreenData, ConnectionStatus, ConnectConfig, ProtocolType } from 'green-screen-types';
|
|
4
|
+
export { ConnectConfig, ConnectionStatus, Field, ScreenData, ProtocolType as TerminalProtocol } from 'green-screen-types';
|
|
3
5
|
|
|
4
|
-
/**
|
|
5
|
-
* Supported terminal protocol types.
|
|
6
|
-
*/
|
|
7
|
-
type TerminalProtocol = 'tn5250' | 'tn3270' | 'vt' | 'hp6530';
|
|
8
6
|
/**
|
|
9
7
|
* Protocol-specific color/rendering conventions.
|
|
10
8
|
*/
|
|
@@ -22,7 +20,7 @@ interface ProtocolColorProfile {
|
|
|
22
20
|
*/
|
|
23
21
|
interface ProtocolProfile {
|
|
24
22
|
/** Protocol identifier */
|
|
25
|
-
protocol:
|
|
23
|
+
protocol: string;
|
|
26
24
|
/** Human-readable name */
|
|
27
25
|
displayName: string;
|
|
28
26
|
/** Default terminal dimensions */
|
|
@@ -35,65 +33,6 @@ interface ProtocolProfile {
|
|
|
35
33
|
/** Boot loader default text */
|
|
36
34
|
bootText: string;
|
|
37
35
|
}
|
|
38
|
-
/**
|
|
39
|
-
* Field definition from the terminal data stream.
|
|
40
|
-
* Describes an input or protected field on the terminal screen.
|
|
41
|
-
*/
|
|
42
|
-
interface Field {
|
|
43
|
-
/** 0-based row index */
|
|
44
|
-
row: number;
|
|
45
|
-
/** 0-based column index */
|
|
46
|
-
col: number;
|
|
47
|
-
/** Field length in characters */
|
|
48
|
-
length: number;
|
|
49
|
-
/** Whether the field accepts user input */
|
|
50
|
-
is_input: boolean;
|
|
51
|
-
/** Whether the field is protected (read-only) */
|
|
52
|
-
is_protected: boolean;
|
|
53
|
-
/** Whether the field is displayed with high intensity (bright/white) */
|
|
54
|
-
is_highlighted?: boolean;
|
|
55
|
-
/** Whether the field is displayed in reverse video */
|
|
56
|
-
is_reverse?: boolean;
|
|
57
|
-
}
|
|
58
|
-
/**
|
|
59
|
-
* Screen data returned by the adapter.
|
|
60
|
-
* Represents the current state of the terminal screen.
|
|
61
|
-
*/
|
|
62
|
-
interface ScreenData {
|
|
63
|
-
/** Screen content as newline-separated text (e.g. 24 lines of 80 chars) */
|
|
64
|
-
content: string;
|
|
65
|
-
/** 0-based cursor row */
|
|
66
|
-
cursor_row: number;
|
|
67
|
-
/** 0-based cursor column */
|
|
68
|
-
cursor_col: number;
|
|
69
|
-
/** Number of rows (default 24) */
|
|
70
|
-
rows?: number;
|
|
71
|
-
/** Number of columns (default 80) */
|
|
72
|
-
cols?: number;
|
|
73
|
-
/** Field definitions on the current screen */
|
|
74
|
-
fields?: Field[];
|
|
75
|
-
/** Unique identifier for the current screen state */
|
|
76
|
-
screen_signature?: string;
|
|
77
|
-
/** ISO timestamp of when this screen was captured */
|
|
78
|
-
timestamp?: string;
|
|
79
|
-
}
|
|
80
|
-
/**
|
|
81
|
-
* Connection status information.
|
|
82
|
-
*/
|
|
83
|
-
interface ConnectionStatus {
|
|
84
|
-
/** Whether a TCP connection is established */
|
|
85
|
-
connected: boolean;
|
|
86
|
-
/** Current connection state */
|
|
87
|
-
status: 'disconnected' | 'connecting' | 'connected' | 'authenticated' | 'error';
|
|
88
|
-
/** Terminal protocol in use */
|
|
89
|
-
protocol?: TerminalProtocol;
|
|
90
|
-
/** Host address */
|
|
91
|
-
host?: string;
|
|
92
|
-
/** Authenticated username */
|
|
93
|
-
username?: string;
|
|
94
|
-
/** Error message if status is 'error' */
|
|
95
|
-
error?: string;
|
|
96
|
-
}
|
|
97
36
|
/**
|
|
98
37
|
* Result from a send operation (text or key).
|
|
99
38
|
*/
|
|
@@ -133,29 +72,16 @@ interface TerminalAdapter {
|
|
|
133
72
|
/** Reconnect to the host */
|
|
134
73
|
reconnect(): Promise<SendResult>;
|
|
135
74
|
}
|
|
136
|
-
/**
|
|
137
|
-
* Configuration passed from the inline sign-in form to adapter.connect().
|
|
138
|
-
*/
|
|
139
|
-
interface ConnectConfig {
|
|
140
|
-
/** Target host address */
|
|
141
|
-
host: string;
|
|
142
|
-
/** Target port (optional, adapter/server can default per protocol) */
|
|
143
|
-
port?: number;
|
|
144
|
-
/** Terminal protocol */
|
|
145
|
-
protocol: TerminalProtocol;
|
|
146
|
-
/** Username for authentication */
|
|
147
|
-
username: string;
|
|
148
|
-
/** Password for authentication */
|
|
149
|
-
password: string;
|
|
150
|
-
}
|
|
151
75
|
|
|
152
76
|
interface GreenScreenTerminalProps {
|
|
153
77
|
/** Adapter for communicating with the terminal backend (optional — auto-created from sign-in form or baseUrl) */
|
|
154
78
|
adapter?: TerminalAdapter;
|
|
155
79
|
/** Base URL for the terminal API — convenience shorthand that auto-creates a RestAdapter */
|
|
156
80
|
baseUrl?: string;
|
|
81
|
+
/** Worker/proxy WebSocket URL — convenience shorthand that auto-creates a WebSocketAdapter */
|
|
82
|
+
workerUrl?: string;
|
|
157
83
|
/** Terminal protocol (determines color conventions, header label, etc.) */
|
|
158
|
-
protocol?:
|
|
84
|
+
protocol?: ProtocolType;
|
|
159
85
|
/** Custom protocol profile (overrides protocol param) */
|
|
160
86
|
protocolProfile?: ProtocolProfile;
|
|
161
87
|
/** Direct screen data injection (bypasses polling) */
|
|
@@ -181,9 +107,13 @@ interface GreenScreenTerminalProps {
|
|
|
181
107
|
/** Show inline sign-in form when disconnected (default true) */
|
|
182
108
|
inlineSignIn?: boolean;
|
|
183
109
|
/** Default protocol for the sign-in form dropdown (default 'tn5250') */
|
|
184
|
-
defaultProtocol?:
|
|
110
|
+
defaultProtocol?: ProtocolType;
|
|
185
111
|
/** Callback when sign-in form is submitted */
|
|
186
112
|
onSignIn?: (config: ConnectConfig) => void;
|
|
113
|
+
/** Show "press Enter to continue" hint after auto sign-in (for external adapter flows) */
|
|
114
|
+
autoSignedIn?: boolean;
|
|
115
|
+
/** Disable auto-focus on the terminal after connecting (default false) */
|
|
116
|
+
autoFocusDisabled?: boolean;
|
|
187
117
|
/** Custom boot loader element, or false to disable */
|
|
188
118
|
bootLoader?: React.ReactNode | false;
|
|
189
119
|
/** Content for the right side of the header */
|
|
@@ -214,7 +144,7 @@ interface GreenScreenTerminalProps {
|
|
|
214
144
|
*
|
|
215
145
|
* Supports: TN5250 (IBM i), TN3270 (z/OS), VT (OpenVMS/Pick), HP 6530 (NonStop)
|
|
216
146
|
*/
|
|
217
|
-
declare function GreenScreenTerminal({ adapter: externalAdapter, baseUrl, protocol, protocolProfile: customProfile, screenData: externalScreenData, connectionStatus: externalStatus, readOnly, pollInterval, autoReconnect: autoReconnectEnabled, maxReconnectAttempts: maxAttempts, embedded, showHeader, typingAnimation, typingBudgetMs, inlineSignIn, defaultProtocol: signInDefaultProtocol, onSignIn, bootLoader, headerRight, overlay, onNotification, onScreenChange, onMinimize, className, style, }: GreenScreenTerminalProps): react_jsx_runtime.JSX.Element;
|
|
147
|
+
declare function GreenScreenTerminal({ adapter: externalAdapter, baseUrl, workerUrl, protocol, protocolProfile: customProfile, screenData: externalScreenData, connectionStatus: externalStatus, readOnly, pollInterval, autoReconnect: autoReconnectEnabled, maxReconnectAttempts: maxAttempts, embedded, showHeader, typingAnimation, typingBudgetMs, inlineSignIn, defaultProtocol: signInDefaultProtocol, onSignIn, autoSignedIn, autoFocusDisabled, bootLoader, headerRight, overlay, onNotification, onScreenChange, onMinimize, className, style, }: GreenScreenTerminalProps): react_jsx_runtime.JSX.Element;
|
|
218
148
|
|
|
219
149
|
interface TerminalBootLoaderProps {
|
|
220
150
|
/** Text to display during boot animation */
|
|
@@ -233,12 +163,12 @@ interface TerminalBootLoaderProps {
|
|
|
233
163
|
declare function TerminalBootLoader({ brandText, charSpeed, logo, height, }: TerminalBootLoaderProps): react_jsx_runtime.JSX.Element;
|
|
234
164
|
|
|
235
165
|
interface InlineSignInProps {
|
|
236
|
-
defaultProtocol:
|
|
166
|
+
defaultProtocol: ProtocolType;
|
|
237
167
|
loading: boolean;
|
|
238
168
|
error: string | null;
|
|
239
169
|
onConnect: (config: ConnectConfig) => void;
|
|
240
170
|
}
|
|
241
|
-
declare function InlineSignIn({ defaultProtocol, loading, error, onConnect }: InlineSignInProps): react_jsx_runtime.JSX.Element;
|
|
171
|
+
declare function InlineSignIn({ defaultProtocol, loading: externalLoading, error, onConnect }: InlineSignInProps): react_jsx_runtime.JSX.Element;
|
|
242
172
|
|
|
243
173
|
declare const TerminalIcon: ({ size }: {
|
|
244
174
|
size?: number;
|
|
@@ -303,25 +233,38 @@ declare class RestAdapter implements TerminalAdapter {
|
|
|
303
233
|
}
|
|
304
234
|
|
|
305
235
|
interface WebSocketAdapterOptions {
|
|
306
|
-
/** URL of the green-screen proxy or worker.
|
|
236
|
+
/** URL of the green-screen proxy or worker. Auto-detected from env vars, defaults to http://localhost:3001 */
|
|
307
237
|
workerUrl?: string;
|
|
308
238
|
}
|
|
309
239
|
/**
|
|
310
|
-
* WebSocket adapter that connects to a Cloudflare Worker
|
|
311
|
-
* The
|
|
240
|
+
* WebSocket adapter that connects to a green-screen proxy or Cloudflare Worker.
|
|
241
|
+
* The backend holds the TCP connection to the legacy host and relays protocol data.
|
|
312
242
|
*
|
|
313
243
|
* Unlike RestAdapter (which polls over HTTP), this adapter receives real-time
|
|
314
244
|
* screen updates via WebSocket push.
|
|
245
|
+
*
|
|
246
|
+
* workerUrl resolution order:
|
|
247
|
+
* 1. Explicit `workerUrl` option
|
|
248
|
+
* 2. VITE_GREEN_SCREEN_URL / VITE_WORKER_URL (Vite)
|
|
249
|
+
* 3. NEXT_PUBLIC_GREEN_SCREEN_URL (Next.js)
|
|
250
|
+
* 4. REACT_APP_GREEN_SCREEN_URL (CRA)
|
|
251
|
+
* 5. http://localhost:3001
|
|
315
252
|
*/
|
|
316
253
|
declare class WebSocketAdapter implements TerminalAdapter {
|
|
317
254
|
private workerUrl;
|
|
318
255
|
private ws;
|
|
319
256
|
private screen;
|
|
320
257
|
private status;
|
|
321
|
-
private
|
|
258
|
+
private pendingScreenResolver;
|
|
259
|
+
private pendingConnectResolver;
|
|
260
|
+
private connectingPromise;
|
|
322
261
|
private screenListeners;
|
|
323
262
|
private statusListeners;
|
|
263
|
+
private _sessionId;
|
|
324
264
|
constructor(options?: WebSocketAdapterOptions);
|
|
265
|
+
private static detectEnvUrl;
|
|
266
|
+
/** The proxy-side session ID (available after connect or reattach) */
|
|
267
|
+
get sessionId(): string | null;
|
|
325
268
|
/** Subscribe to real-time screen updates */
|
|
326
269
|
onScreen(listener: (screen: ScreenData) => void): () => void;
|
|
327
270
|
/** Subscribe to status changes */
|
|
@@ -331,9 +274,15 @@ declare class WebSocketAdapter implements TerminalAdapter {
|
|
|
331
274
|
sendText(text: string): Promise<SendResult>;
|
|
332
275
|
sendKey(key: string): Promise<SendResult>;
|
|
333
276
|
connect(config?: ConnectConfig): Promise<SendResult>;
|
|
277
|
+
/**
|
|
278
|
+
* Reattach to an existing proxy session (e.g. after page reload).
|
|
279
|
+
* The proxy keeps the TCP connection alive; this just reconnects the
|
|
280
|
+
* WebSocket and receives the current screen.
|
|
281
|
+
*/
|
|
282
|
+
reattach(sessionId: string): Promise<SendResult>;
|
|
334
283
|
disconnect(): Promise<SendResult>;
|
|
335
284
|
reconnect(): Promise<SendResult>;
|
|
336
|
-
/** Close the WebSocket without sending disconnect */
|
|
285
|
+
/** Close the WebSocket without sending disconnect (session stays alive on proxy) */
|
|
337
286
|
dispose(): void;
|
|
338
287
|
private ensureWebSocket;
|
|
339
288
|
private handleMessage;
|
|
@@ -416,7 +365,7 @@ declare function useTerminalInput(adapter: TerminalAdapter): {
|
|
|
416
365
|
/**
|
|
417
366
|
* Get a protocol profile by type. Defaults to TN5250 for backward compatibility.
|
|
418
367
|
*/
|
|
419
|
-
declare function getProtocolProfile(protocol?:
|
|
368
|
+
declare function getProtocolProfile(protocol?: ProtocolType): ProtocolProfile;
|
|
420
369
|
|
|
421
370
|
declare const tn5250Profile: ProtocolProfile;
|
|
422
371
|
|
|
@@ -461,4 +410,4 @@ declare function parseHeaderRow(line: string): {
|
|
|
461
410
|
colorClass: string;
|
|
462
411
|
}[] | null;
|
|
463
412
|
|
|
464
|
-
export { AlertTriangleIcon,
|
|
413
|
+
export { AlertTriangleIcon, GreenScreenTerminal, type GreenScreenTerminalProps, InlineSignIn, type InlineSignInProps, KeyIcon, MinimizeIcon, type ProtocolColorProfile, type ProtocolProfile, RefreshIcon, RestAdapter, type RestAdapterOptions, type SendResult, type TerminalAdapter, TerminalBootLoader, type TerminalBootLoaderProps, TerminalIcon, WebSocketAdapter, type WebSocketAdapterOptions, WifiIcon, WifiOffIcon, getProtocolProfile, getRowColorClass, hp6530Profile, isFieldEntry, parseHeaderRow, positionToRowCol, tn3270Profile, tn5250Profile, useTerminalConnection, useTerminalInput, useTerminalScreen, useTypingAnimation, vtProfile };
|