Skip to main content

oino_ui/
lib.rs

1//! `oino-ui` — wire types and the ratatui-mirroring builder for the Oino
2//! extension UI protocol v2 (docs/dev/v2/specs/ui-protocol.md).
3//!
4//! This crate is the single serde-only definition of the protocol: node trees
5//! (§4), the entry registry envelopes (§6.1, §9.2), patch ops (§4.7), validation
6//! limits and the OUS v1 gate (§4.8), the plain-text fallback (§10) and — behind
7//! the `schema` feature — the normative JSON Schema (Appendix A). It builds for
8//! `wasm32-wasip2` (deps: `serde`, `serde_json` only, §11).
9//!
10//! ```
11//! use oino_ui::prelude::*;
12//!
13//! let list = List::new(["first", "second"])
14//!     .highlight_symbol("› ")
15//!     .on_activate("open");
16//! let node: Node = Layout::vertical([Constraint::Length(1), Constraint::Fill(1)])
17//!     .children([Paragraph::new("Tasks").into(), list.into()])
18//!     .into();
19//! let json = serde_json::to_value(&node).unwrap_or_default();
20//! assert_eq!(json["t"], "Layout");
21//! ```
22
23pub mod extras;
24pub mod layout;
25pub mod limits;
26pub mod node;
27pub mod patch;
28pub mod plain;
29pub mod settings;
30pub mod slot;
31pub mod style;
32pub mod text;
33pub mod widgets;
34
35#[cfg(feature = "schema")]
36pub mod schema;
37
38/// Everything an extension author usually wants (§11): node kinds, the prelude
39/// types and the [`Stylize`] helpers.
40pub mod prelude {
41    pub use crate::extras::button::{Button, ButtonVariant};
42    pub use crate::extras::code::Code;
43    pub use crate::extras::diff::{Diff, DiffMode};
44    pub use crate::extras::empty::Empty;
45    pub use crate::extras::icon::Icon;
46    pub use crate::extras::image::{Fit, Image, ImageSource};
47    pub use crate::extras::input::Input;
48    pub use crate::extras::key_hints::{Hint, KeyHints};
49    pub use crate::extras::log::Log;
50    pub use crate::extras::markdown::Markdown;
51    pub use crate::extras::select::{Select, SelectOption};
52    pub use crate::extras::spinner::Spinner;
53    pub use crate::extras::toggle::Toggle;
54    pub use crate::extras::tree::{Tree, TreeNode, TreeState};
55    pub use crate::layout::{Constraint, Direction, Flex, Layout, Margin};
56    pub use crate::node::{ActionId, Common, IntoNode, Key, Node, Unknown, WithCommon};
57    pub use crate::patch::{NodeOp, NodePath, PatchField, PatchItem};
58    pub use crate::style::{Color, Modifier, Modifiers, Style, Stylize};
59    pub use crate::text::{Alignment, Line, Span, Text};
60    pub use crate::widgets::barchart::{Bar, BarChart, BarGroup};
61    pub use crate::widgets::block::{
62        Block, BlockProps, BlockTitle, BorderSide, BorderType, Borders, Padding, Title,
63        TitlePosition, borders,
64    };
65    pub use crate::widgets::chart::{Axis, Chart, Dataset, GraphType, LegendPosition, Marker};
66    pub use crate::widgets::gauge::{Gauge, LineGauge, LineSet};
67    pub use crate::widgets::list::{
68        HighlightSpacing, List, ListDirection, ListItem, ListState, Selection,
69    };
70    pub use crate::widgets::paragraph::{Paragraph, Wrap};
71    pub use crate::widgets::scrollbar::{Scrollbar, ScrollbarOrientation, ScrollbarState};
72    pub use crate::widgets::sparkline::{BarSet, SparkDirection, Sparkline};
73    pub use crate::widgets::table::{Cell, Row, Sticky, Table};
74    pub use crate::widgets::tabs::{TabTitle, Tabs};
75}
76
77pub use layout::{Constraint, Direction, Flex, Layout, Margin};
78pub use node::{ActionId, Common, IntoNode, Key, Node, Unknown, WithCommon};
79pub use style::{Color, Modifier, Modifiers, Style, Stylize};
80pub use text::{Alignment, Line, Span, Text};
81
82#[cfg(test)]
83mod tests {
84    #![allow(
85        clippy::unwrap_used,
86        clippy::expect_used,
87        clippy::panic,
88        reason = "tests assert by unwrapping"
89    )]
90    #[test]
91    fn prelude_example_round_trips() {
92        use crate::prelude::*;
93        let list = List::new(["first", "second"]).on_activate("open");
94        let node: Node = Layout::vertical([Constraint::Fill(1)])
95            .children([list.into()])
96            .into();
97        let json = serde_json::to_value(&node).unwrap_or_default();
98        let back: Node = serde_json::from_value(json).unwrap_or(Node::Unknown(Unknown {
99            t: "boom".into(),
100            ..Unknown::default()
101        }));
102        assert_eq!(node, back);
103    }
104}