The runtime JS hooks an element can be attached to, and the two attributes that attach it.
Why a picker and not a code box
MishkaCmsCore.Runtime.PageBuilder.Interactions covers what a page usually wants — toggle a class,
show something, hide something — with no code at any point. What it cannot do is anything else, and
the answer to "anything else" is a hook: real JavaScript, written on the JS hooks page, compiled
into the site's bundle and registered with LiveView.
Writing one stays there. This only selects from what is already in the bundle, which is the whole
reason it needs no gate of its own: it grants nothing the actor did not already have, it removes
the step where they hand-type phx-hook into Advanced and get the capitalisation wrong.
The two attributes
phx-hook names the hook, and LiveView requires a unique DOM id on any element carrying one —
a hook on an element with no id silently never mounts, which is a bad afternoon. So attaching one
mints an id when the element has none, and the picker says so rather than leaving it to be
discovered.
The name written is JavaScriptCompiler.browser_name/2's, not the row's: a global hook called
collapse registers as GlobalCollapse and a site's own as <Site>Collapse. Asking the compiler
is what keeps the two from drifting.
Summary
Functions
Every hook this site can attach, its own and the globals, as %{name:, hook:, description:}.
Whether name is a hook the picker is entitled to write.
Every hook the picker offers: this site's, the globals, and whatever a plugin contributes through
builder:js_hooks.
Functions
Every hook this site can attach, its own and the globals, as %{name:, hook:, description:}.
name is what goes in phx-hook; hook is the row's own name, which is what the JS hooks page
calls it and therefore what a reader is looking for.
Whether name is a hook the picker is entitled to write.
The picker writes the name into the document, so a stale option — a hook archived in another tab — must not be written as though it existed.
Every hook the picker offers: this site's, the globals, and whatever a plugin contributes through
builder:js_hooks.
ONE LIST FOR THE PICKER AND FOR known?/4, which is the whole point of naming it — the same
Interactions.registry/0 and Conditions.registry/0 are. The picker read the appended list and
known?/4 read available/3, so every hook an extension contributed was offered and then refused
on Apply.