use ratatui::layout::Rect;
pub const MODAL_FRACTION_W: u32 = 3; pub const MODAL_FRACTION_H: u32 = 3; pub const MODAL_DIVISOR: u32 = 4;
pub const MIN_MODAL_W: u16 = 24;
pub const MIN_MODAL_H: u16 = 9;
pub fn modal_rect(area: Rect) -> Rect {
if area.width == 0 || area.height == 0 {
return area;
}
if area.width < MIN_MODAL_W || area.height < MIN_MODAL_H {
return area;
}
let mut w = (area.width as u32 * MODAL_FRACTION_W / MODAL_DIVISOR) as u16;
let mut h = (area.height as u32 * MODAL_FRACTION_H / MODAL_DIVISOR) as u16;
w = w.clamp(MIN_MODAL_W, area.width);
h = h.clamp(MIN_MODAL_H, area.height);
let x = area.x + (area.width.saturating_sub(w)) / 2;
let y = area.y + (area.height.saturating_sub(h)) / 2;
Rect::new(x, y, w, h)
}
#[cfg(test)]
mod tests {
use super::*;
fn modal_at(w: u16, h: u16) -> (u16, u16, u16, u16) {
let r = modal_rect(Rect::new(0, 0, w, h));
(r.x, r.y, r.width, r.height)
}
#[test]
fn modal_120x40_is_centered_and_75_percent() {
let (x, y, w, h) = modal_at(120, 40);
assert_eq!((w, h), (90, 30));
assert_eq!((x, y), (15, 5));
}
#[test]
fn modal_80x24_is_centered_and_75_percent() {
let (x, y, w, h) = modal_at(80, 24);
assert_eq!((w, h), (60, 18));
assert_eq!((x, y), (10, 3));
}
#[test]
fn modal_tiny_20x5_does_not_overflow() {
let (x, y, w, h) = modal_at(20, 5);
assert!(w <= 20 && h <= 5, "tiny modal must not overflow: {w}x{h}");
assert!(x + w <= 20 && y + h <= 5);
}
}