use crate::diag::bail;
use crate::foundations::{
Array, Content, NativeElement, Packed, Smart, Styles, cast, elem, scope,
};
use crate::introspection::{Locatable, Tagged};
use crate::layout::{Em, HElem, Length};
use crate::model::{ListItemLike, ListLike};
#[elem(scope, title = "Term List", Locatable, Tagged)]
pub struct TermsElem {
#[default(true)]
pub tight: bool,
#[default(HElem::new(Em::new(0.6).into()).with_weak(true).pack())]
pub separator: Content,
pub indent: Length,
#[default(Em::new(2.0).into())]
pub hanging_indent: Length,
pub spacing: Smart<Length>,
#[variadic]
pub children: Vec<Packed<TermItem>>,
#[internal]
#[ghost]
pub within: bool,
}
#[scope]
impl TermsElem {
#[elem]
type TermItem;
}
#[elem(name = "item", title = "Term List Item", Tagged)]
pub struct TermItem {
#[required]
pub term: Content,
#[required]
pub description: Content,
}
cast! {
TermItem,
array: Array => {
let mut iter = array.into_iter();
let (term, description) = match (iter.next(), iter.next(), iter.next()) {
(Some(a), Some(b), None) => (a.cast()?, b.cast()?),
_ => bail!("array must contain exactly two entries"),
};
Self::new(term, description)
},
v: Content => v.unpack::<Self>().map_err(|_| "expected term item or array")?,
}
impl ListLike for TermsElem {
type Item = TermItem;
fn create(children: Vec<Packed<Self::Item>>, tight: bool) -> Self {
Self::new(children).with_tight(tight)
}
}
impl ListItemLike for TermItem {
fn styled(mut item: Packed<Self>, styles: Styles) -> Packed<Self> {
item.term.style_in_place(styles.clone());
item.description.style_in_place(styles);
item
}
}