///|
const PopoverPanelStyle : String = "position:absolute;z-index:50;display:flex;flex-direction:column;min-width:200px;padding:12px;border:1px solid var(--sumi-stroke-secondary,rgba(255,255,255,0.04));border-radius:var(--sumi-radius-lg,12px);background:var(--sumi-menu,#262626);box-shadow:var(--sumi-shadow-menu,0px 8px 56px 0px rgba(0,0,0,0.24))"

///|
/// A generic anchored floating panel with a caller-supplied trigger — the
/// base for composite pickers that are not plain option lists (sliders,
/// forms, previews). Same overlay/motion model as `dropdown_menu`: fully
/// controlled (`open` + `on_open_change`), closes on outside click, enters
/// with the scale animation whose origin follows `side` and `align`.
///
/// ```moonbit nocheck
/// popover(
///   trigger=button(variant=Ghost, [text("16:9 · 2K"), menu_chevron()]),
///   open=panel_open,
///   on_open_change=set_panel_open.map(v => _ => v),
///   [my_panel_content],
/// )
/// ```
pub fn[C : @html.IsChildren] popover(
  trigger~ : @html.Html,
  open~ : Bool,
  on_open_change? : @internal.Emit[Bool],
  align? : MenuAlign = Start,
  side? : MenuSide = Bottom,
  id? : String,
  class? : String,
  attrs? : @html.Attrs,
  style? : Array[String] = [],
  panel_style? : Array[String] = [],
  children : C,
) -> @html.Html {
  let close : @cmd.Cmd? = on_open_change.map(emit => emit(false))
  let toggle : @cmd.Cmd? = on_open_change.map(emit => emit(!open))
  let overlay : @html.Html = match close {
    Some(cmd) =>
      @html.div(
        style=[MenuOverlayStyle],
        hidden=!open,
        on_click=cmd,
        attrs=@html.Attrs::build()
          .data_set("slot", "menu-overlay")
          .aria_hidden("true"),
        "",
      )
    None => @html.nothing
  }
  let element_attrs = @internal.sumi_attrs(attrs)
    .data_set("slot", "popover")
    .data_set("state", if open { "open" } else { "closed" })
  let trigger_attrs = @html.Attrs::build().data_set("slot", "popover-trigger")
  if toggle is Some(cmd) {
    ignore(trigger_attrs.on_click(_ => cmd))
  }
  @html.div(
    style=@internal.sumi_styles(
      [@internal.SumiBoxSizing, "position:relative;display:inline-flex"],
      style,
    ),
    id?,
    class?,
    attrs=element_attrs,
    [
      @html.div(style=["display:inline-flex"], attrs=trigger_attrs, [trigger]),
      @html.fragment([
        overlay,
        @html.div(
          style=@internal.sumi_styles(
            [
              @internal.SumiBoxSizing,
              @internal.SumiFontSans,
              @internal.SumiTextRendering,
              PopoverPanelStyle,
              menu_align_style(align),
              menu_side_style(side),
            ],
            panel_style,
          ),
          hidden=!open,
          attrs=@html.Attrs::build()
            .data_set("slot", "popover-panel")
            .data_set("side", menu_side_value(side))
            .data_set("align", menu_align_value(align)),
          [@internal.sumi_slot(children)],
        ),
      ]),
    ],
  )
}