feat(console): scrollAutoscrollTargets walks ancestors; expose on window

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
mwiegand 2026-05-20 22:50:22 +02:00
parent 35dfb6dd1f
commit 02e44a04d3
No known key found for this signature in database

View file

@ -156,24 +156,39 @@ function bindAllConsoleForms(root) {
scope.forEach(bindConsoleForm);
}
function scrollConsolesToBottom(root) {
function scrollAutoscrollTargets(root) {
if (!root) return;
const scope = root.matches && root.matches("[data-autoscroll]") ? [root] : [];
if (root.querySelectorAll) {
root.querySelectorAll("[data-autoscroll]").forEach((el) => scope.push(el));
const targets = [];
// Case 1: root itself opts in.
if (root.matches && root.matches("[data-autoscroll]")) {
targets.push(root);
}
scope.forEach((el) => {
// Case 2: descendants opt in.
if (root.querySelectorAll) {
root.querySelectorAll("[data-autoscroll]").forEach((el) => targets.push(el));
}
// Case 3: neither — walk up. Handles htmx:load firing with the inserted
// child as the root after hx-swap="beforeend" on a console line.
if (targets.length === 0 && root.closest) {
const up = root.closest("[data-autoscroll]");
if (up) targets.push(up);
}
targets.forEach((el) => {
el.scrollTop = el.scrollHeight;
});
}
// Expose for tabs.js (and any future cross-module consumer). The script
// is `defer`red in base.html, so it runs before DOMContentLoaded and the
// global is defined by the time tabs.js's DCL-deferred initStrips runs.
window.scrollAutoscrollTargets = scrollAutoscrollTargets;
document.addEventListener("DOMContentLoaded", () => {
scrollConsolesToBottom(document);
scrollAutoscrollTargets(document);
bindAllConsoleForms(document);
});
// Support HTMX-injected content (mirrors sse.js pattern).
document.addEventListener("htmx:load", (event) => {
scrollConsolesToBottom(event.detail.elt);
scrollAutoscrollTargets(event.detail.elt);
bindAllConsoleForms(event.detail.elt);
});