1#![deny(unsafe_code)]
2#![warn(missing_docs)]
3#![cfg_attr(target_arch = "wasm32", allow(dead_code, unused_imports))]
4
5#[cfg(all(target_arch = "wasm32", any(feature = "image", feature = "terminal")))]
11compile_error!(
12 "tui-lipan: wasm32 builds cannot enable image or terminal features; use --no-default-features"
13);
14
15pub mod prelude;
16
17#[macro_use]
18mod widget_manifest;
19
20pub mod core;
21
22pub mod animation;
23pub mod capture;
24pub mod debug;
25#[cfg(feature = "devtools")]
26pub(crate) mod devtools;
27pub mod input;
28#[cfg(not(target_arch = "wasm32"))]
29pub mod process;
30pub mod ui_snapshot;
31
32mod clipboard;
33
34mod app;
35mod backend;
36mod callback;
37pub mod callbacks;
38mod layout;
39mod mockup;
40mod overlay;
41mod runtime;
42mod ui;
43
44pub mod style;
45
46mod test_backend;
47mod text;
48pub mod text_motion;
49pub mod utils;
50pub mod validation;
51mod widgets;
52
53#[cfg(all(feature = "terminal-images", not(target_arch = "wasm32")))]
64pub fn host_cell_size() -> crate::widgets::TerminalCellSize {
65 crate::backend::ratatui_backend::image_support::host_cell_size()
66}
67
68#[cfg(not(target_arch = "wasm32"))]
74pub mod terminal_handoff {
75 pub use crate::backend::ratatui_backend::terminal_handoff::{
76 resume_after_external_process, suspend_for_external_process,
77 };
78}
79
80#[cfg(not(target_arch = "wasm32"))]
81pub use crate::app::AppRunner;
82#[cfg(feature = "devtools")]
83pub use crate::app::DevToolsConfig;
84pub use crate::app::input::command_registry::{
85 CommandBuilder, CommandEntry, CommandId, CommandRegistry,
86};
87pub use crate::app::input::key_dispatch::{
88 ChordMismatchPolicy, CommandConflictPolicy, KeyDispatchPolicy, TerminalKeyPolicy,
89};
90pub use crate::app::input::keymap::{FrameworkAction, FrameworkKeymap, UserKeymapPolicy};
91#[cfg(all(target_arch = "wasm32", feature = "web"))]
92pub use crate::app::web_runner::{WebTerminal, mount_web};
93pub use crate::app::{
94 App, ContrastPolicy, DevToolsMetric, FocusChanged, FocusEntry, FocusPolicy, InlineHeight,
95 InlineStartupPolicy, ScreenBackground, SurfaceMode, TextAreaNewlineBinding,
96};
97pub use crate::mockup::Mockup;
98
99pub use crate::animation::{ExitAnimation, ExitQueue, ExitTransfer};
100pub use crate::callback::{Callback, CancellationToken, CommandLink, KeyHandler, Link};
101pub use crate::capture::{CapturedCell, CapturedFrame, CastRecording, CellModifiers, CursorState};
102#[cfg(feature = "ui-snapshot-png")]
103pub use crate::capture::{PngOptions, PngTextRenderer};
104pub use crate::clipboard::{
105 ClipboardConfig, ClipboardError, ClipboardHandle, ClipboardPasteContent, ClipboardProvider,
106 ImageContent, ImageFormat, PasteShiftInsertBehavior,
107};
108pub use crate::core::component::{
109 Breakpoint, Command, Component, Context, KeyUpdate, ScrollbarVisibility, TaskPolicy, Update,
110 UpdateLevel,
111};
112pub use crate::core::context_value::ContextValue;
113pub use crate::core::element::{Element, IntoElement, Key};
114pub use crate::core::event::{
115 KeyCode, KeyEvent, KeyMods, MouseDragEvent, MouseEvent, MouseMoveEvent,
116};
117pub use crate::core::mask::CellMask;
118pub use crate::core::memo::Memo;
119pub use crate::core::nested::any_props::ThemableProps;
120pub use crate::core::node::NodeId;
121pub use crate::input::{
122 ChordMatcher, ChordResult, KeyBinding, KeyBindingParseError, KeyBindings,
123 KeyEventExpansionError, format_binding, format_binding_compact, format_binding_lowercase,
124 format_bindings, format_bindings_compact, format_bindings_lowercase,
125};
126pub use crate::layout::tag::Tag;
127pub use crate::overlay::{OverlayId, OverlayScope, ToastHandle, ToastPlacement};
128#[cfg(not(target_arch = "wasm32"))]
129pub use crate::process::{
130 ProcessEvent, ProcessExitStatus, ProcessSpec, process_command, process_command_keyed,
131 stream_process, stream_process_until,
132};
133pub use crate::style::Theme;
134pub use crate::style::{
135 Align, BorderEdges, BorderStyle, CaretPalette, CaretShape, CellEffect, Color, ColorTransform,
136 DiffPalette, DocumentPalette, DocumentViewPalette, Edge, EffectAxis, EffectCell, EffectContext,
137 EffectPalette, EffectPrepareContext, FileIconPalette, FloatRect, GitStatusPalette,
138 HexAreaPalette, HostTerminalColors, InputPalette, Justify, LayoutConstraints, Length, Padding,
139 Paint, PreparedCellEffect, Rect, RetroPreset, RichText, RippleRadius, ScrollbarConfig,
140 ScrollbarPalette, ScrollbarVariant, ShrinkPriority, Size, Span, StatusPalette, Style,
141 SurfacePalette, SyntaxPalette, TerminalColor, TerminalPalette, TextAreaPalette, ThemeExtension,
142 ThemePalette, VisualEffect, query_host_colors,
143};
144#[cfg(feature = "theme-reload")]
145pub use crate::style::{ThemeWatcher, load_theme_from_toml};
146pub use crate::test_backend::TestBackend;
147pub use crate::text::edit::{TextEditEvent, TextEditKind};
148pub use crate::text::editor::TextEditor;
149pub use crate::text::line_index::{LineIndex, TextEncoding, TextPosition, TextRange};
150pub use crate::ui_snapshot::{
151 Action, FocusStep, Recording, ScrollDirection, Sketch, Target, UiSnapshot,
152 UiSnapshotFileFormat, UiSnapshotFormatOptions, UiSnapshotOptions, UiSnapshotSlot, UiWidgetDesc,
153 UiWidgetKind,
154};
155#[cfg(feature = "ui-snapshot-png")]
156pub use crate::ui_snapshot::{BaselineComparison, BaselineOutcome, SnapshotBaseline};
157pub use crate::validation::{StringValidator, ValidationError, Validator};
158pub use crate::widgets::{Badge, BadgePosition, CapSides, CapStyle};
159pub use crate::widgets::{
160 BorderLabels, Canvas, CanvasItem, ClassDiagram, ClassDiagramTheme, ClassMember, ClassRelation,
161 ClassRelationKind, ClassSpec, ClassVisibility, ContextProvider, DEFAULT_PREVIEW_MAX_HEIGHT,
162 DEFAULT_PREVIEW_MAX_WIDTH, DiagramClassMemberSpec, DiagramClassNodeSpec,
163 DiagramClassRelationSpec, DiagramClassSpec, DiagramClassVisibilitySpec, DiagramDirection,
164 DiagramErAttributeSpec, DiagramErEntitySpec, DiagramErRelationSpec, DiagramErSpec,
165 DiagramFlowEdgeSpec, DiagramFlowNodeShape, DiagramFlowNodeSpec, DiagramFlowchartSpec,
166 DiagramGanttDate, DiagramGanttDuration, DiagramGanttSection, DiagramGanttSpec,
167 DiagramGanttTask, DiagramGanttTaskStart, DiagramGanttTaskStatus, DiagramPieSliceSpec,
168 DiagramPieSpec, DiagramSequenceMessageSpec, DiagramSequenceParticipantSpec,
169 DiagramSequenceSpec, DiagramStateKindSpec, DiagramStateNodeSpec, DiagramStateSpec,
170 DiagramStateTransitionSpec, DraggableTabBarOverflow, ErAttribute, ErCardinality, ErDiagram,
171 ErDiagramTheme, ErEntity, ErRelation, FileKind, FileTree, FileTreeChange, FileTreeChangeSource,
172 FileTreeChangeStatus, FileTreeChangeView, FileTreeDirectoryListing, FileTreeEntry,
173 FileTreeEntryRequest, FileTreeEntrySource, FileTreeEvent, FileTreeExplorerFocusOrigin,
174 FileTreeGitView, FileTreeItemStyle, FileTreeSuffixPriority, FileTreeToggleEvent, FocusScope,
175 FormattedDiagramBlock, Frame, FrameLabel, GanttDate, GanttDiagram, GanttDiagramTheme,
176 GanttDuration, GanttSection, GanttSpec, GanttTask, GanttTaskStart, GanttTaskStatus, Heatmap,
177 HeatmapCellMode, HeatmapLegendWidth, HexArea, HexAreaChangeEvent, HexAreaCursorEvent,
178 HexAreaEditEvent, HexAreaEditKind, IMAGE_SENTINEL_BASE, PanEvent, PanKeymap, PanMetrics,
179 PanView, ParsedDiagram, SENTINEL_BASE, ScrollAxis, ScrollBehavior, ScrollChildExitDirection,
180 ScrollChildVisibility, ScrollDistanceConfig, ScrollEvent, ScrollExitedChild, ScrollMetrics,
181 ScrollTarget, ScrollViewportEvent, ScrollVisibleChild, ScrollWheelBehavior, ScrollWheelConfig,
182 SentinelEvent, SentinelId, StateDiagram, StateDiagramTheme, StateKind, StateSpec,
183 StateTransition, TextArea, TextAreaColorInput, TextAreaColorLines, TextAreaColorStrategy,
184 TextAreaCursorMetrics, TextAreaDecoration, TextAreaDecorationKind, TextAreaEvent,
185 TextAreaGutter, TextAreaGutterColumn, TextAreaGutterSign, TextAreaImageMode,
186 TextAreaLineNumberMode, TextAreaMetrics, TextAreaPasteEvent, TextAreaSentinel,
187 TextAreaSentinelClickEvent, TextAreaSentinelClickKind, TextAreaSnapshot,
188 TextAreaStateChangeEvent, TextAreaStateChangeReason, TextAreaVimConfig,
189 TextAreaVimCurrentLineHighlight, TextAreaVimKeyBinding, TextAreaVimKeymap, TextAreaVimMode,
190 TextAreaVirtualText, Toast, ToastCopyAffordance, TripleClickSelectionMode,
191 VirtualTextPlacement, insert_sentinel, rank_search_palette_indices,
192 rank_search_palette_indices_with_mode, rank_search_palette_indices_with_score,
193};
194#[cfg(feature = "qr-code")]
195pub use crate::widgets::{QrCode, QrEcc, QrRender};
196
197#[cfg(all(feature = "terminal", unix))]
198pub use crate::widgets::TerminalPtyHandoff;
199#[cfg(feature = "terminal")]
200pub use crate::widgets::{
201 CopyModeAction, CopyModeGrid, KittyKeyboardFlags, MouseEncoding, MouseMode, MouseModeState,
202 TerminalCellSize, TerminalColorPalette, TerminalCopyMode, TerminalDecoration, TerminalKeyModes,
203 TerminalPasteShortcutBehavior, TerminalRenderSnapshot, terminal_selection_text,
204};
205#[cfg(feature = "terminal-images")]
206pub use crate::widgets::{TerminalImage, TerminalImageCrop, TerminalImagePlacement};
207
208#[cfg(feature = "diff-view")]
209pub use crate::widgets::{
210 DiffContextExpansion, DiffContextRange, DiffContextSeparatorDirection,
211 DiffContextSeparatorEvent, DiffData, DiffDataConfig, DiffHunkAnchor,
212};
213
214#[cfg(feature = "syntax-syntect")]
215pub use crate::widgets::{
216 SyntectDocumentFormatter, SyntectStrategy, apply_syntect_strategy_app_theme, language_from_path,
217};
218pub use tui_lipan_macro::rsx;
220pub use tui_lipan_macro::ui;
225
226#[cfg(not(target_arch = "wasm32"))]
276#[macro_export]
277macro_rules! mockup {
278 ($title:expr, $body:expr) => {
279 $crate::App::new()
280 .title($title)
281 .mount($crate::Mockup::new(move || { $body }.into()))
282 .run()
283 };
284}
285
286pub fn child<C, F>(factory: F, props: C::Properties) -> Element
290where
291 C: Component,
292 F: Fn() -> C + 'static,
293{
294 Element::new(crate::core::element::ElementKind::Component(
295 crate::core::nested::ComponentElement::new::<C, F>(factory, props),
296 ))
297}
298
299pub type Result<T> = std::result::Result<T, Error>;
301
302#[derive(thiserror::Error, Debug)]
304pub enum Error {
305 #[error(transparent)]
307 Io(#[from] std::io::Error),
308
309 #[error("failed to load syntax theme `{name}`: {message}")]
311 SyntaxThemeLoad {
312 name: String,
314 message: String,
316 #[source]
318 error: Option<Box<dyn std::error::Error + Send + Sync>>,
319 },
320
321 #[error(
323 "message type mismatch for component `{component}` (expected `{expected}`, got `{actual}`)"
324 )]
325 MessageTypeMismatch {
326 component: &'static str,
328 expected: &'static str,
330 actual: &'static str,
332 },
333
334 #[error(
336 "props type mismatch for component `{component}` (expected `{expected}`, got `{actual}`)"
337 )]
338 PropsTypeMismatch {
339 component: &'static str,
341 expected: &'static str,
343 actual: &'static str,
345 },
346
347 #[error("component expansion failed: {reason}")]
349 ComponentExpansion {
350 reason: String,
352 },
353
354 #[error("theme reload error: {message}")]
356 ThemeReload {
357 message: String,
359 },
360}
361
362#[cfg(test)]
363#[test]
364fn inline_transcript_append_rejects_component_nodes() {
365 crate::runtime::assert_inline_transcript_append_rejects_component_nodes();
366}
367
368#[cfg(test)]
369#[test]
370fn inline_surface_commit_render_path_is_unified() {
371 crate::runtime::assert_inline_surface_commit_render_path_is_unified();
372}
373
374#[cfg(all(test, not(target_arch = "wasm32")))]
375#[test]
376fn inline_surface_internal_wrap_policy_is_opaque() {
377 crate::backend::ratatui_backend::assert_inline_surface_internal_wrap_policy_is_opaque();
378}