use deckmint::layout::{self, GridLayoutBuilder, GridTrack};
use deckmint::objects::shape::ShapeOptionsBuilder;
use deckmint::objects::text::TextOptionsBuilder;
use deckmint::{AlignH, AlignV, Presentation, ShapeType};
fn main() {
let mut pres = Presentation::new();
{
let slide = pres.add_slide();
slide.set_background_color("#F5F6FA");
let outer = GridLayoutBuilder::sidebar_left(2.5, 0.15)
.padding(0.2)
.build();
let sidebar = outer.cell(0, 0);
let main_area = outer.cell(1, 0);
slide.add_shape(ShapeType::RoundRect, ShapeOptionsBuilder::new()
.rect(sidebar)
.fill_color("#2C3E50")
.rect_radius(0.08)
.build());
let menu_items = ["Dashboard", "Analytics", "Reports", "Settings"];
let menu_grid = GridLayoutBuilder::within(sidebar)
.rows(vec![
GridTrack::Inches(0.8), GridTrack::Fr(1.0), ])
.padding(0.15)
.build();
slide.add_text("DASH", TextOptionsBuilder::new()
.rect(menu_grid.cell(0, 0))
.font_size(22.0).bold()
.color("#3498DB")
.align(AlignH::Center).valign(AlignV::Middle)
.build());
let items_area = menu_grid.cell(0, 1);
let rows = layout::split_v(&items_area, menu_items.len(), 0.08);
for (i, item) in menu_items.iter().enumerate() {
let is_active = i == 0;
let bg = if is_active { "#3498DB" } else { "#34495E" };
slide.add_shape(ShapeType::RoundRect, ShapeOptionsBuilder::new()
.rect(rows[i])
.fill_color(bg)
.rect_radius(0.04)
.build());
slide.add_text(*item, TextOptionsBuilder::new()
.rect(rows[i].inset_xy(0.15, 0.0))
.font_size(12.0)
.color("#FFFFFF")
.valign(AlignV::Middle)
.build());
}
let main_grid = GridLayoutBuilder::within(main_area)
.rows(vec![GridTrack::Inches(0.7), GridTrack::Fr(1.0)])
.row_gap(0.12)
.build();
slide.add_text("Dashboard Overview", TextOptionsBuilder::new()
.rect(main_grid.cell(0, 0))
.font_size(22.0).bold()
.color("#2C3E50")
.valign(AlignV::Bottom)
.build());
let cards = main_grid.sub_grid(0, 1)
.cols(vec![GridTrack::Fr(1.0); 2])
.rows(vec![GridTrack::Fr(1.0); 2])
.gap(0.12)
.build();
let card_data = [
("Users", "12,847", "+12%", "#3498DB"),
("Revenue", "$84.2K", "+8%", "#2ECC71"),
("Orders", "1,423", "+23%", "#E67E22"),
("Uptime", "99.97%", "+0.1%","#9B59B6"),
];
for (i, (label, value, delta, color)) in card_data.iter().enumerate() {
let cell = cards.cell(i % 2, i / 2);
slide.add_shape(ShapeType::RoundRect, ShapeOptionsBuilder::new()
.rect(cell)
.fill_color("#FFFFFF")
.rect_radius(0.06)
.build());
let accent = deckmint::layout::CellRect {
x: cell.x, y: cell.y, w: cell.w, h: 0.05,
};
slide.add_shape(ShapeType::Rect, ShapeOptionsBuilder::new()
.rect(accent)
.fill_color(*color)
.build());
let inner = cell.inset(0.15);
let (top, bot) = inner.halves_v(0.0);
slide.add_text(*value, TextOptionsBuilder::new()
.rect(top)
.font_size(28.0).bold()
.color("#2C3E50")
.valign(AlignV::Bottom)
.build());
slide.add_text(&format!("{} {}", label, delta), TextOptionsBuilder::new()
.rect(bot)
.font_size(11.0)
.color("#95A5A6")
.valign(AlignV::Top)
.build());
}
}
{
let slide = pres.add_slide();
slide.set_background_color("#FFFFFF");
let grid = GridLayoutBuilder::new()
.cols(vec![GridTrack::Fr(2.0), GridTrack::Fr(1.0), GridTrack::Fr(1.0)])
.rows(vec![
GridTrack::Inches(0.8), GridTrack::Fr(1.0), GridTrack::Inches(1.2), ])
.gap(0.12)
.padding(0.3)
.build();
let title_bar = grid.span(0, 0, 3, 1);
slide.add_shape(ShapeType::Rect, ShapeOptionsBuilder::new()
.rect(title_bar)
.fill_color("#1A1A2E")
.build());
slide.add_text("Project Status Report", TextOptionsBuilder::new()
.rect(title_bar.inset_xy(0.2, 0.0))
.font_size(24.0).bold()
.color("#FFFFFF")
.valign(AlignV::Middle)
.build());
let feature = grid.span(0, 1, 1, 2);
slide.add_shape(ShapeType::RoundRect, ShapeOptionsBuilder::new()
.rect(feature)
.fill_color("#16213E")
.rect_radius(0.08)
.build());
let (ft, fb) = feature.inset(0.25).halves_v(0.1);
slide.add_text("Sprint 24", TextOptionsBuilder::new()
.rect(ft)
.font_size(30.0).bold()
.color("#E94560")
.valign(AlignV::Bottom)
.build());
slide.add_text("14 stories completed\n3 in review\n1 blocked", TextOptionsBuilder::new()
.rect(fb)
.font_size(14.0)
.color("#A0A0C0")
.valign(AlignV::Top)
.build());
let card1 = grid.cell(1, 1);
let card2 = grid.cell(2, 1);
for (cell, label, value, color) in [
(card1, "Velocity", "42 pts", "#0F3460"),
(card2, "Burndown", "78%", "#533483"),
] {
slide.add_shape(ShapeType::RoundRect, ShapeOptionsBuilder::new()
.rect(cell)
.fill_color(color)
.rect_radius(0.06)
.build());
let (t, b) = cell.inset(0.12).halves_v(0.0);
slide.add_text(label, TextOptionsBuilder::new()
.rect(t)
.font_size(11.0)
.color("#8899AA")
.valign(AlignV::Bottom).align(AlignH::Center)
.build());
slide.add_text(value, TextOptionsBuilder::new()
.rect(b)
.font_size(24.0).bold()
.color("#FFFFFF")
.valign(AlignV::Top).align(AlignH::Center)
.build());
}
let timeline = grid.span(1, 2, 2, 1);
slide.add_shape(ShapeType::RoundRect, ShapeOptionsBuilder::new()
.rect(timeline)
.fill_color("#1A1A2E")
.rect_radius(0.06)
.build());
slide.add_text("Timeline: On Track for July Release", TextOptionsBuilder::new()
.rect(timeline)
.font_size(14.0).bold()
.color("#5BC0BE")
.align(AlignH::Center).valign(AlignV::Middle)
.build());
}
{
let slide = pres.add_slide();
slide.set_background_color("#0B0C10");
let grid = GridLayoutBuilder::new()
.cols(vec![
GridTrack::MinMax { min: 2.0, max_fr: 1.0 },
GridTrack::MinMax { min: 2.0, max_fr: 1.0 },
GridTrack::MinMax { min: 2.0, max_fr: 1.0 },
])
.rows(vec![GridTrack::Inches(0.7), GridTrack::Fr(1.0)])
.gap(0.15)
.padding(0.4)
.build();
let header = grid.span(0, 0, 3, 1);
slide.add_text("Feature Comparison", TextOptionsBuilder::new()
.rect(header)
.font_size(24.0).bold()
.color("#66FCF1")
.valign(AlignV::Bottom)
.build());
let tiers = [
("Starter", "$9/mo", ["5 users", "10GB storage", "Email support"], "#1F2833"),
("Pro", "$29/mo", ["25 users", "100GB storage", "Priority support"], "#45A29E"),
("Enterprise", "$99/mo", ["Unlimited", "1TB storage", "24/7 phone"], "#66FCF1"),
];
for (col, (name, price, features, accent)) in tiers.iter().enumerate() {
let cell = grid.cell(col, 1);
let is_highlight = col == 1;
let bg = if is_highlight { "#1F2833" } else { "#0B0C10" };
slide.add_shape(ShapeType::RoundRect, ShapeOptionsBuilder::new()
.rect(cell)
.fill_color(bg)
.line_color(*accent).line_width(if is_highlight { 2.0 } else { 1.0 })
.rect_radius(0.08)
.build());
let inner = cell.inset(0.2);
let sections = layout::split_v(&inner, 5, 0.08);
slide.add_text(*name, TextOptionsBuilder::new()
.rect(sections[0])
.font_size(20.0).bold()
.color(*accent)
.align(AlignH::Center).valign(AlignV::Middle)
.build());
slide.add_text(*price, TextOptionsBuilder::new()
.rect(sections[1])
.font_size(16.0)
.color("#C5C6C7")
.align(AlignH::Center).valign(AlignV::Middle)
.build());
for (i, feat) in features.iter().enumerate() {
slide.add_text(*feat, TextOptionsBuilder::new()
.rect(sections[2 + i])
.font_size(11.0)
.color("#C5C6C7")
.align(AlignH::Center).valign(AlignV::Middle)
.build());
}
}
}
pres.write_to_file("14_grid_advanced.pptx").unwrap();
println!("Wrote 14_grid_advanced.pptx");
}