use ratatui::buffer::Buffer;
use ratatui::layout::Rect;
use ratatui::style::Style;
use ratatui::text::{Line, Span};
use ratatui::widgets::Widget;
use super::super::theme::Palette;
const DEFAULT_FRAMES: &[char] = &['◐', '◓', '◑', '◒'];
pub struct Spinner<'a> {
frames: &'a [char],
tick: u64,
label: Option<&'a str>,
palette: &'a Palette,
}
impl<'a> Spinner<'a> {
pub fn new(palette: &'a Palette) -> Self {
Self {
frames: DEFAULT_FRAMES,
tick: 0,
label: None,
palette,
}
}
pub fn frames(mut self, frames: &'a [char]) -> Self {
if !frames.is_empty() {
self.frames = frames;
}
self
}
pub fn tick(mut self, tick: u64) -> Self {
self.tick = tick;
self
}
pub fn label(mut self, label: &'a str) -> Self {
self.label = Some(label);
self
}
}
impl Widget for Spinner<'_> {
fn render(self, area: Rect, buf: &mut Buffer) {
if area.height == 0 || area.width == 0 {
return;
}
let frame = self.frames[(self.tick as usize) % self.frames.len()];
let mut spans = vec![Span::styled(
frame.to_string(),
Style::default().fg(self.palette.accent),
)];
if let Some(label) = self.label {
spans.push(Span::styled(
format!(" {label}"),
Style::default().fg(self.palette.primary),
));
}
Line::from(spans).render(area, buf);
}
}