2024-10-14 23:09:27 +02:00
|
|
|
import { Controller } from "@hotwired/stimulus";
|
2024-02-08 10:46:05 -06:00
|
|
|
|
|
|
|
// Connects to data-controller="list-keyboard-navigation"
|
|
|
|
export default class extends Controller {
|
|
|
|
focusPrevious() {
|
2024-10-14 23:09:27 +02:00
|
|
|
this.focusLinkTargetInDirection(-1);
|
2024-02-08 10:46:05 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
focusNext() {
|
2024-10-14 23:09:27 +02:00
|
|
|
this.focusLinkTargetInDirection(1);
|
2024-02-08 10:46:05 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
focusLinkTargetInDirection(direction) {
|
2024-10-14 23:09:27 +02:00
|
|
|
const element = this.getLinkTargetInDirection(direction);
|
|
|
|
element?.focus();
|
2024-02-08 10:46:05 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
getLinkTargetInDirection(direction) {
|
2024-10-14 23:09:27 +02:00
|
|
|
const indexOfLastFocus = this.indexOfLastFocus();
|
|
|
|
let nextIndex = (indexOfLastFocus + direction) % this.focusableLinks.length;
|
|
|
|
if (nextIndex < 0) nextIndex = this.focusableLinks.length - 1;
|
|
|
|
|
|
|
|
return this.focusableLinks[nextIndex];
|
2024-02-08 10:46:05 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
indexOfLastFocus(targets = this.focusableLinks) {
|
2024-10-14 23:09:27 +02:00
|
|
|
const indexOfActiveElement = targets.indexOf(document.activeElement);
|
2024-02-08 10:46:05 -06:00
|
|
|
|
|
|
|
if (indexOfActiveElement !== -1) {
|
2024-10-14 23:09:27 +02:00
|
|
|
return indexOfActiveElement;
|
2024-02-08 10:46:05 -06:00
|
|
|
}
|
2024-10-14 23:09:27 +02:00
|
|
|
return targets.findIndex(
|
|
|
|
(target) => target.getAttribute("tabindex") === "0",
|
|
|
|
);
|
2024-02-08 10:46:05 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
get focusableLinks() {
|
2024-10-14 23:09:27 +02:00
|
|
|
return Array.from(this.element.querySelectorAll("a[href]"));
|
2024-02-08 10:46:05 -06:00
|
|
|
}
|
|
|
|
}
|