///|
/// RUI disclosure compound primitives; callers own state through Val and Emit.
pub(all) enum TabsListVariant {
TabsDefault
TabsLine
} derive(Eq, Debug)
///|
fn validate_panels(items : Array[Panel]) -> Unit {
let seen : Map[String, Bool] = Map([])
for item in items {
guard item.key != "" && !seen.contains(item.key) else {
abort("panel keys must be unique and nonempty")
}
seen[item.key] = true
}
}
///|
fn normalize_panel_keys(
items : Array[Panel],
keys : Array[String],
multiple : Bool,
) -> Array[String] {
let normalized : Array[String] = []
for key in keys {
if !normalized.contains(key) && items.any(item => item.key == key) {
normalized.push(key)
if !multiple {
break
}
}
}
normalized
}
///|
fn valid_tab_selection(items : Array[Panel], selected : String?) -> String? {
if items.any(item => selected == Some(item.key) && !item.disabled) {
return selected
}
for item in items {
if !item.disabled {
return Some(item.key)
}
}
None
}
///|
fn panel_trigger(item : Panel) -> @minimoon.Node {
item.trigger.unwrap_or(
@minimoon.fragment([
item.icon.unwrap_or(@minimoon.nothing()),
@minimoon.text(item.title),
]),
)
}
///|
pub fn[C : @minimoon.IsChildren] accordion_root(
id? : String = "",
disabled? : Bool = false,
children : C,
) -> @minimoon.Node {
ui_container(
"accordion",
children.to_nodes(),
id~,
semantics=@minimoon.semantics(disabled~),
)
}
///|
pub fn[C : @minimoon.IsChildren] accordion_item(
id? : String = "",
open? : Bool = false,
disabled? : Bool = false,
children : C,
) -> @minimoon.Node {
ui_container(
"accordion-item",
children.to_nodes(),
id~,
semantics=@minimoon.semantics(expanded=open, disabled~),
)
}
///|
pub fn[C : @minimoon.IsChildren] accordion_trigger(
value~ : String,
on_change~ : @minimoon.Emit[String],
open? : Bool = false,
disabled? : Bool = false,
controls? : String = "",
id? : String = "",
show_indicator? : Bool = true,
children : C,
) -> @minimoon.Node {
@minimoon.button_children(
id~,
class="mmui-accordion-trigger",
disabled~,
on_tap=if disabled { @minimoon.none } else { on_change(value) },
semantics=@minimoon.semantics(
role=@minimoon.ButtonRole,
expanded=open,
controls~,
disabled~,
),
[
@minimoon.fragment(children.to_nodes()),
if show_indicator {
@minimoon.text(if open { "−" } else { "+" })
} else {
@minimoon.nothing()
},
],
)
}
///|
pub fn[C : @minimoon.IsChildren] accordion_content(
id? : String = "",
open? : Bool = false,
force_mount? : Bool = false,
labelled_by? : String = "",
children : C,
) -> @minimoon.Node {
if !open && !force_mount {
@minimoon.nothing()
} else {
ui_container(
"accordion-panel",
children.to_nodes(),
id~,
style=if open { "" } else { "display:none;" },
semantics=@minimoon.semantics(
role=@minimoon.RegionRole,
hidden=!open,
labelled_by~,
),
)
}
}
///|
pub fn[C : @minimoon.IsChildren] collapsible_root(
id? : String = "",
open? : Bool = false,
disabled? : Bool = false,
children : C,
) -> @minimoon.Node {
ui_container(
"collapsible",
children.to_nodes(),
id~,
semantics=@minimoon.semantics(expanded=open, disabled~),
)
}
///|
pub fn[C : @minimoon.IsChildren] collapsible_trigger(
on_change~ : @minimoon.Emit[Bool],
open? : Bool = false,
disabled? : Bool = false,
controls? : String = "",
id? : String = "",
show_indicator? : Bool = true,
children : C,
) -> @minimoon.Node {
@minimoon.button_children(
id~,
class="mmui-collapsible-trigger",
disabled~,
on_tap=if disabled { @minimoon.none } else { on_change(!open) },
semantics=@minimoon.semantics(
role=@minimoon.ButtonRole,
expanded=open,
controls~,
disabled~,
),
[
@minimoon.fragment(children.to_nodes()),
if show_indicator {
@minimoon.text(if open { "−" } else { "+" })
} else {
@minimoon.nothing()
},
],
)
}
///|
pub fn[C : @minimoon.IsChildren] collapsible_content(
id? : String = "",
open? : Bool = false,
force_mount? : Bool = false,
labelled_by? : String = "",
children : C,
) -> @minimoon.Node {
accordion_content(id~, open~, force_mount~, labelled_by~, children)
}
///|
pub fn[C : @minimoon.IsChildren] tabs_root(
id? : String = "",
vertical? : Bool = false,
children : C,
) -> @minimoon.Node {
ui_container(
"tabs",
children.to_nodes(),
id~,
class=if vertical { "mmui-vertical" } else { "mmui-horizontal" },
)
}
///|
pub fn[C : @minimoon.IsChildren] tabs_list(
id? : String = "",
vertical? : Bool = false,
variant? : TabsListVariant = TabsDefault,
children : C,
) -> @minimoon.Node {
ui_container(
"tab-list",
children.to_nodes(),
id~,
class=(if vertical { "mmui-vertical" } else { "mmui-horizontal" }) +
(if variant == TabsLine {
" mmui-tabs-line"
} else {
" mmui-tabs-default"
}),
semantics=@minimoon.semantics(
role=@minimoon.TabListRole,
orientation=if vertical { "vertical" } else { "horizontal" },
),
)
}
///|
pub fn[C : @minimoon.IsChildren] tabs_trigger(
value~ : String,
on_change~ : @minimoon.Emit[String],
selected? : Bool = false,
disabled? : Bool = false,
controls? : String = "",
id? : String = "",
children : C,
) -> @minimoon.Node {
@minimoon.button_children(
id~,
class="mmui-tab",
disabled~,
on_tap=if disabled { @minimoon.none } else { on_change(value) },
semantics=@minimoon.semantics(
role=@minimoon.TabRole,
selected~,
controls~,
disabled~,
),
children,
)
}
///|
pub fn[C : @minimoon.IsChildren] tabs_content(
id? : String = "",
selected? : Bool = false,
force_mount? : Bool = false,
labelled_by? : String = "",
children : C,
) -> @minimoon.Node {
if !selected && !force_mount {
@minimoon.nothing()
} else {
ui_container(
"tab-panel",
children.to_nodes(),
id~,
style=if selected { "" } else { "display:none;" },
semantics=@minimoon.semantics(
role=@minimoon.TabPanelRole,
hidden=!selected,
labelled_by~,
),
)
}
}