Shared {{path}} (and, on opted-in fields, legacy $var) token-detection,
filtering, keyboard navigation, and insertion engine behind VarInput's autocomplete popover.
Extracted out of VarInput.tsx (behavior-preserving refactor — see
task-1-brief.md) so a second consumer (the template-editor modal, Task 2)
can share the exact same token logic instead of duplicating it. This
module owns only the state machine: open/filter/active-suggestion state,
the pendingCaret/justInserted refs, and the caret-restore effect.
Popover rendering, availability messaging, and the footer stay in
VarInput (and, from Task 2, whatever else renders a popover against this
hook) — see that component's module doc comment for the popover's
user-facing behavior contract.
Shared
{{path}}(and, on opted-in fields, legacy$var) token-detection, filtering, keyboard navigation, and insertion engine behind VarInput's autocomplete popover.Extracted out of
VarInput.tsx(behavior-preserving refactor — see task-1-brief.md) so a second consumer (the template-editor modal, Task 2) can share the exact same token logic instead of duplicating it. This module owns only the state machine: open/filter/active-suggestion state, thependingCaret/justInsertedrefs, and the caret-restore effect. Popover rendering, availability messaging, and the footer stay inVarInput(and, from Task 2, whatever else renders a popover against this hook) — see that component's module doc comment for the popover's user-facing behavior contract.