@slate-terminal/react
v2.3.0
Published
Production-grade terminal UI runtime with native TSX and optional React integration.
Downloads
754
Readme
@slate-terminal/react
Production-grade declarative terminal UI for TypeScript and TSX. React is optional: the Slate runtime and window/element API remain available without React, while createSlateReactRenderer exposes the same tree and hooks through a real React runtime.
import { Button, Container, Input, Text, createSlateOutput, createTerminalController, render, signal } from "@slate-terminal/react";
import { createInputSource } from "@slate-terminal/core";
const value = signal("");
const app = render(
<Container id="app" direction="column" gap={1}>
<Text>Slate Mosaic</Text>
<Input id="value" value={value} onChange={next => value.set(next)} />
<Button id="save" onPress={() => value.set("saved")}>Save</Button>
</Container>,
{ viewport: { width: 80, height: 24 } }
);
const terminal = createTerminalController(app, createInputSource(), createSlateOutput(process.stdout));
terminal.start();
// Ctrl+C calls the same close path; use this for normal shutdown too.
// terminal.close();Use jsxImportSource: "@slate-terminal/react" com jsx: "react-jsx". Para integrar uma fonte nativa, passe { poll: pollEvent } a createInputRouter. O pacote core fornece os controles de raw mode e mouse capture.
Leia o guia de produção para o fluxo completo de
montagem, Ctrl+C, hit-test de mouse, disabled, onEvent, onHover,
wrapping por grapheme, LogView rico, testes Windows e migração de renderers.
Exports principais:
- runtime:
render,createApp,createSlateApp,SlateApplication,createTerminalController; - estado:
signal,computed,effect,batch,untracked; - layout:
createFlexLayoutEngine,createYogaLayoutEngine; - entrada:
createInputRouter,createNormalizedInput,normalizeEvent,sameEvent,useInput,useFocus,useFocusManager,useCursor,useWindowSize; - componentes:
Container,Block,Text,Button,Input,Select,Checkbox,Tabs,Table,Spinner,Progress,Modal,ScrollView,List,Form,Glow,ColorShift; - mídia:
Image,Video,Media,loadMediaFile,createMediaSource,renderMedia(Kitty/iTerm2 com fallback textual); - apresentação:
LogView,TextStyle,LogLine,LogRun,wrapText; - composição:
Panel,Card,Alert,Dialog,Menu,Gauge,KeyHint,StatusBar,Tree,flattenTree; - tema:
createTheme,setTheme,getTheme,withTheme,themeColor,themeSpacing; - capacidades:
detectTerminalCapabilities,capabilityMatrix,describeCapabilities,colorParameters; - console de baixo nível:
openConsole,openInteractiveConsole,ANSI; - cache:
createMemoryCache,openDiskCache,resolveCacheRoot,createSessionScratch,clearTextCaches; - pré-aquecimento:
prewarm,prewarmSync,recordPrewarmSamples; - extensões:
registerExtension,registerWidget,createWidget,runExtensionConformance; - infraestrutura:
resolveTree,reconcile,createSlateRoot,renderTreeToAnsi.
Desde a 2.3.0, renderAnsi/renderTreeToAnsi aceitam capabilities, colors
e unicode: a saída degrada para 256 cores, 8 cores ou nenhuma, e desenha
bordas ASCII quando o console não garante box drawing. detectTerminalCapabilities()
é uma função pura do ambiente, então esse comportamento é testável sem o
terminal real.
Callbacks use the ignored, consumed, render, or exit contract. IDs are unique per tree and stable during reconciliation. createSlateOutput suppresses duplicate frames; direct writes remain available for integrations that need them.
createTerminalController expõe stop, close, dispose e error. Ctrl+C é
reservado como saída de emergência e fecha o controller antes de chamar
onExit; closeTerminal() do core restaura os modos nativos.
React integration
React is an optional peer dependency. Pass the React namespace explicitly so Slate does not impose a React version or bundle it into non-React applications:
import React from "react";
import { Container, createSlateReactRenderer } from "@slate-terminal/react";
const slateReact = createSlateReactRenderer(React);
const element = slateReact.toReact(Container({ children: "Hello 👩💻" }));Slate's terminal renderer remains the source of truth for terminal output; the adapter is the native bridge for React components and hooks.
For a real React application, mount React itself into Slate with the custom
terminal reconciler. The Slate JSX components are not React components in this
mode; create host elements with React.createElement:
import React from "react";
import { createInputSource } from "@slate-terminal/core";
import { createReactTerminalRoot, createSlateOutput, createTerminalController } from "@slate-terminal/react";
const root = await createReactTerminalRoot({ viewport: { width: 80, height: 24 } });
const terminal = createTerminalController(root.app, createInputSource(), createSlateOutput(process.stdout));
root.render(React.createElement(
"container",
{ id: "app", direction: "column", padding: 1 },
React.createElement("text", { id: "title", text: "Hello from React 👩💻" })
));
terminal.start();
// terminal.close() also unmounts the Slate tree and removes its SIGINT hook.React owns component execution, hooks, and reconciliation. Slate owns terminal layout, focus, keyboard/mouse events, ANSI rendering, and output scheduling.
The reconciler peer is optional for React-free consumers. Pin a compatible pair when using real React elements:
| React | react-reconciler | peer range |
| --- | --- | --- |
| 18.x | 0.29.x | ^18.3.0 + ^0.29.2 |
| 19.x | 0.31.x | ^19.0.0 + ^0.31.0 |
The peer ranges exclude every other line, but npm cannot express that React 18
requires 0.29 and React 19 requires 0.31, so a crossed pair still installs.
createReactTerminalRoot compares the installed React major with the major the
reconciler was built for and refuses the pair with the line to install;
checkReactCompatibility(reactVersion, reconcilerReactRange, createContainerArity)
exposes the same decision without creating a root. A missing peer reports the
expected line as well. createReactAdapter(React) remains the simpler bridge when
React should only consume Slate nodes, including React 18 applications that do
not need a terminal reconciler.
onError recebe falhas da fonte, do renderer e do output. O controller fecha o
polling e a árvore antes de retornar ao processo; a função é protegida para
que um logger com defeito não impeça a limpeza. maxRenderPasses interrompe
feedback loops de composição com uma mensagem determinística.
Glow e ColorShift podem envolver texto ou ser usados como effect em qualquer nó. O controller anima efeitos e spinners em até 60 FPS por padrão; use animationFps: 0 para desativar a agenda automática.
Para mídia, prefira loadMediaFile("./cover.png") e passe o resultado a
Image. A camada de protocolo é opt-in ou pode usar mediaProtocol: "auto";
quando não há suporte, Slate mantém o alt no grid. Uma string base64 sem data
URI pode ser usada com mimeType no componente. Video reproduz frames
de imagem fornecidos pela aplicação e não promete decodificar containers de
vídeo.
Use createI18n for application and widget translations. It provides locale fallback to English and does not impose a translation framework.
