scrin-widgets 0.2.4

Scrin-native widgets and Aisling terminal effects for immersive TUIs.
Documentation
use std::{io, time::Duration};

use scrin::{
    Color, Terminal,
    layout::{Constraint, Direction, Layout},
    widgets::{
        Paragraph, Widget,
        block::{Block, BorderStyle},
    },
};
use scrin_widgets::{AislingExt, AislingPalette, GlyphRain, NebulaGauge, SignalPanel};

fn main() -> io::Result<()> {
    let mut terminal = Terminal::init()?;
    let result = run(&mut terminal);
    terminal.restore()?;
    result
}

fn run(terminal: &mut Terminal) -> io::Result<()> {
    let tick = 37;

    terminal.draw(|frame| {
        let rows = Layout::default()
            .direction(Direction::Vertical)
            .constraints([
                Constraint::Min(8),
                Constraint::Length(7),
                Constraint::Length(5),
            ])
            .split(frame.area());
        let buffer = frame.buffer();

        GlyphRain::new(tick)
            .density(30)
            .block(bordered_block("glyph rain", AislingPalette::cypherpunk().low))
            .render(buffer, rows[0]);

        let columns = Layout::default()
            .direction(Direction::Horizontal)
            .constraints([Constraint::Percentage(50), Constraint::Percentage(50)])
            .split(rows[1]);

        NebulaGauge::new(0.72)
            .tick(tick)
            .label("link 72%")
            .block(bordered_block("gauge", AislingPalette::cypherpunk().mid))
            .render(buffer, columns[0]);

        SignalPanel::new("relay")
            .line("status: luminous")
            .line("route: scrin://aisling")
            .tick(tick)
            .render(buffer, columns[1]);

        let block = bordered_block("plug and play", AislingPalette::cypherpunk().high);
        let inner = block.inner(rows[2]);
        block.render(buffer, rows[2]);
        Paragraph::new(
            "Wrap any existing Scrin widget with `.aisling()` for shimmer, scanlines, and edge glow.",
        )
        .with_word_wrap(true)
        .aisling()
        .tick(tick)
        .palette(AislingPalette::cypherpunk())
        .intensity(7)
        .render(buffer, inner);
    })?;

    std::thread::sleep(Duration::from_secs(3));
    Ok(())
}

fn bordered_block(title: &str, color: Color) -> Block<'_> {
    Block::new(title)
        .with_borders(BorderStyle::Plain)
        .with_border_color(color)
        .with_inner_margin(scrin::Rect::ZERO)
}