# `MingaEditor.State.ModalOverlay.Completion`
[🔗](https://github.com/jsmestad/minga/blob/main/lib/minga_editor/state/modal_overlay/completion.ex#L1)

Modal-overlay payload for the completion menu.

The completion menu is logically per-tab: it tracks the cursor position of
the buffer that triggered it. The `owner` field carries the tab identifier
so the tab-switch hook (`ModalOverlay.dismiss_if_stale/1`) can auto-dismiss
completion that no longer belongs to the active tab.

## Trigger lifecycle

The completion trigger (debounce/pending-ref machinery) is part of the
modal's lifecycle: it only matters while completion is being driven, and
resets when completion dismisses. Carrying the trigger on the payload —
rather than as an independent field on workspace state — keeps the
modal's lifecycle self-contained and removes a per-tab field that other
callers had to know about.

# `completion_or_nil`

```elixir
@type completion_or_nil() :: Minga.Editing.Completion.t() | nil
```

The user-visible completion menu, or `nil` while a request is pending.

`nil` represents the brief window between the trigger firing an LSP
request and the response arriving. The render layer paints nothing
while completion is `nil`; the modal exists so the trigger's debounce/
pending-ref state has a home.

# `owner`

```elixir
@type owner() :: term()
```

Identifier of the tab that triggered completion.

Tab IDs are the keys of `MingaEditor.State.TabBar`'s tab map. We accept
any term so callers do not need to depend on TabBar's id type directly.

# `t`

```elixir
@type t() :: %MingaEditor.State.ModalOverlay.Completion{
  completion: completion_or_nil(),
  opened_at: integer(),
  owner: owner(),
  trigger: MingaEditor.CompletionTrigger.t()
}
```

# `new`

```elixir
@spec new(
  owner(),
  keyword()
) :: t()
```

Builds a completion payload bound to `owner` (typically a tab id).

Pass `:completion` to seed an already-resolved completion menu, or
omit to open a payload that just tracks the trigger lifecycle while
an LSP request is in flight.

# `put_completion`

```elixir
@spec put_completion(t(), completion_or_nil()) :: t()
```

Replaces the inner `Completion.t()` on the payload, preserving owner,
trigger, and opened_at. The only sanctioned way to update completion
state from outside this module (Rule 2: state ownership).

# `put_trigger`

```elixir
@spec put_trigger(t(), MingaEditor.CompletionTrigger.t()) :: t()
```

Replaces the inner trigger on the payload. The only sanctioned way to
update the trigger from outside this module.

---

*Consult [api-reference.md](api-reference.md) for complete listing*
