///|
fn drawer_cross_axis(side : Side, point : @minimoon.TouchPoint) -> Double {
match side {
Left | Right => point.client_y
Top | Bottom => point.client_x
}
}
///|
fn drawer_signed_distance(side : Side, drag : DrawerDrag) -> Double {
(drag.position - drag.start) *
(if side == Left || side == Top { -1.0 } else { 1.0 })
}
///|
/// Only mounted beside an open panel. The edge faces into the viewport and
/// shares the panel transform; there is no closed-screen gesture listener.
fn drawer_swipe_edge(
id : String,
side : Side,
area : Int32,
emit : @minimoon.Emit[DrawerMsg],
) -> @minimoon.Node {
let size = area.to_string() + "px;"
let placement = match side {
Bottom => "bottom:100%;left:0;right:0;height:"
Top => "top:100%;left:0;right:0;height:"
Left => "left:100%;top:0;bottom:0;width:"
Right => "right:100%;top:0;bottom:0;width:"
}
@minimoon.touch_view(
id=id + "-swipe-edge",
class="mmui-drawer-swipe-edge",
style="position:absolute;" + placement + size,
catch_move=true,
on_touch_start=emit.map(value => StartEdge(value)),
on_touch_move=emit.map(value => Move(value)),
on_touch_end=emit.map(value => End(value)),
on_touch_cancel=emit.map(value => CancelTouch(value)),
event_key=id + "/edge",
semantics=@minimoon.semantics(label="Swipe toward panel to close"),
@minimoon.nothing(),
)
}
///|
fn drawer_body(
id : String,
title : String,
content : @minimoon.Node,
emit : @minimoon.Emit[DrawerMsg],
on_change : @minimoon.Emit[Bool],
side : Side,
swipe_area : Int32,
) -> Array[@minimoon.Node] {
let body = [
@minimoon.touch_view(
id=id + "-handle",
class="mmui-drawer-handle",
style="min-width:44px;min-height:44px;",
catch_move=true,
on_touch_start=emit.map(value => DrawerMsg::Start(value)),
on_touch_move=emit.map(value => Move(value)),
on_touch_end=emit.map(value => DrawerMsg::End(value)),
on_touch_cancel=emit.map(value => CancelTouch(value)),
event_key=id + "/drag",
semantics=@minimoon.semantics(label="Drag to close"),
@minimoon.text("—"),
),
@minimoon.h1(id=id + "-title", class="mmui-surface-title", title),
content,
@minimoon.button(on_tap=on_change(false), event_key=id + "/close", "Close"),
]
if swipe_area == 0 {
return body
}
let limit = if side == Left || side == Right { "100vh" } else { "85vh" }
[
drawer_swipe_edge(id, side, swipe_area, emit),
@minimoon.div(
style="display:flex;flex-direction:column;gap:8px;max-height:calc(" +
limit +
" - 34px);overflow:auto;",
body,
),
]
}