@edugouvfr/ngx-dsfr-ext
Version:
NgxDsfrExt est une extension au package @edugouvfr/ngx-dsfr (portage Angular des éléments DSFR)
78 lines • 11.9 kB
JavaScript
/**
* Classe utilitaire permettant de récupérer les éléments <li> concernés
* dans le cadre de la gestion du focus à la navigation clavier du composant multiselect
* selon la structure des options avec groupes éventuels
*/
export class SelectFocusUtils {
static { this.CONTAINER_LIST_CLASS = 'dsfrx-multiselect__list'; }
constructor() { }
/**
* Détermine l'élément suivant à focus (li role=option), en tenant compte des groupes et des éléments enfants.
*/
static findNextListItem(elementToFocus, currentElement) {
if (elementToFocus) {
return this.isGroupElement(elementToFocus)
? elementToFocus.children[1] // Premier élément du groupe
: elementToFocus; // Élément direct suivant
}
// prochain element de la liste ou sous-liste
if (currentElement) {
// focus sur le prochain groupe
const nextGroup = currentElement.parentElement?.nextElementSibling;
if (nextGroup && this.isGroupElement(nextGroup)) {
return nextGroup.children[1]; // Premier élément du groupe suivant
}
// Retour au début si fin de liste
return this.findNextListItem(this.getFirstListItem(currentElement));
}
return null;
}
/**
* Détermine l'élément précédent à focus (li role=option), en tenant compte des groupes et des éléments enfants.
*/
static findPreviousListItem(elementToFocus, currentElement) {
// focus sur le nom du groupe,
if (this.isPresentationElement(elementToFocus)) {
const prevGroup = elementToFocus?.parentElement?.previousElementSibling;
if (prevGroup && this.isGroupElement(prevGroup)) {
return prevGroup.lastElementChild; // Dernier élément du groupe précédent
}
if (currentElement) {
// premier groupe ou element de la liste, renvoyer au dernier élément
return this.findPreviousListItem(this.getLastListItem(currentElement));
}
}
if (elementToFocus && this.isGroupElement(elementToFocus)) {
return elementToFocus.lastElementChild; // dernier element du groupe
}
if (!elementToFocus && currentElement) {
return this.findPreviousListItem(this.getLastListItem(currentElement));
}
return elementToFocus; // Élément direct précédent
}
static setFocusElementOnFirst(event) {
let firstItem = this.getFirstListItem(event.target);
firstItem = this.findPreviousListItem(firstItem);
return firstItem;
}
static setFocusElementOnLast(event) {
let lastItem = this.getLastListItem(event.target);
lastItem = this.findPreviousListItem(lastItem);
return lastItem;
}
static getFirstListItem(element) {
return element?.closest(`.${this.CONTAINER_LIST_CLASS}`)?.firstElementChild;
}
static getLastListItem(element) {
return element?.closest(`.${this.CONTAINER_LIST_CLASS}`)?.lastElementChild;
}
/** L'élément est le container du groupe */
static isGroupElement(el) {
return !!(el && el.getAttribute('role') === 'group');
}
/** L'élément est un élément de présentation correspondant au nom du groupe */
static isPresentationElement(el) {
return !!(el && el.getAttribute('role') === 'presentation');
}
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2VsZWN0LWZvY3VzLnV0aWxzLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vcHJvamVjdHMvbmd4LWRzZnItZXh0L3NyYy9saWIvbXVsdGlzZWxlY3Qvc2VsZWN0LWZvY3VzLnV0aWxzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOzs7O0dBSUc7QUFDSCxNQUFNLE9BQU8sZ0JBQWdCO2FBQ1gseUJBQW9CLEdBQUcseUJBQXlCLENBQUM7SUFFakUsZ0JBQXVCLENBQUM7SUFFeEI7O09BRUc7SUFDSCxNQUFNLENBQUMsZ0JBQWdCLENBQUMsY0FBa0MsRUFBRSxjQUE0QjtRQUN0RixJQUFJLGNBQWMsRUFBRSxDQUFDO1lBQ25CLE9BQU8sSUFBSSxDQUFDLGNBQWMsQ0FBQyxjQUFjLENBQUM7Z0JBQ3hDLENBQUMsQ0FBRSxjQUFjLENBQUMsUUFBUSxDQUFDLENBQUMsQ0FBaUIsQ0FBQyw0QkFBNEI7Z0JBQzFFLENBQUMsQ0FBQyxjQUFjLENBQUMsQ0FBQyx5QkFBeUI7UUFDL0MsQ0FBQztRQUVELDhDQUE4QztRQUM5QyxJQUFJLGNBQWMsRUFBRSxDQUFDO1lBQ25CLCtCQUErQjtZQUMvQixNQUFNLFNBQVMsR0FBRyxjQUFjLENBQUMsYUFBYSxFQUFFLGtCQUFrQixDQUFDO1lBQ25FLElBQUksU0FBUyxJQUFJLElBQUksQ0FBQyxjQUFjLENBQUMsU0FBUyxDQUFDLEVBQUUsQ0FBQztnQkFDaEQsT0FBTyxTQUFTLENBQUMsUUFBUSxDQUFDLENBQUMsQ0FBZ0IsQ0FBQyxDQUFDLG9DQUFvQztZQUNuRixDQUFDO1lBRUQsa0NBQWtDO1lBQ2xDLE9BQU8sSUFBSSxDQUFDLGdCQUFnQixDQUFDLElBQUksQ0FBQyxnQkFBZ0IsQ0FBQyxjQUFjLENBQUMsQ0FBQyxDQUFDO1FBQ3RFLENBQUM7UUFFRCxPQUFPLElBQUksQ0FBQztJQUNkLENBQUM7SUFFRDs7T0FFRztJQUNILE1BQU0sQ0FBQyxvQkFBb0IsQ0FBQyxjQUFrQyxFQUFFLGNBQTRCO1FBQzFGLDhCQUE4QjtRQUM5QixJQUFJLElBQUksQ0FBQyxxQkFBcUIsQ0FBQyxjQUFjLENBQUMsRUFBRSxDQUFDO1lBQy9DLE1BQU0sU0FBUyxHQUFHLGNBQWMsRUFBRSxhQUFhLEVBQUUsc0JBQXNCLENBQUM7WUFDeEUsSUFBSSxTQUFTLElBQUksSUFBSSxDQUFDLGNBQWMsQ0FBQyxTQUFTLENBQUMsRUFBRSxDQUFDO2dCQUNoRCxPQUFPLFNBQVMsQ0FBQyxnQkFBK0IsQ0FBQyxDQUFDLHNDQUFzQztZQUMxRixDQUFDO1lBQ0QsSUFBSSxjQUFjLEVBQUUsQ0FBQztnQkFDbkIscUVBQXFFO2dCQUNyRSxPQUFPLElBQUksQ0FBQyxvQkFBb0IsQ0FBQyxJQUFJLENBQUMsZUFBZSxDQUFDLGNBQWMsQ0FBQyxDQUFDLENBQUM7WUFDekUsQ0FBQztRQUNILENBQUM7UUFFRCxJQUFJLGNBQWMsSUFBSSxJQUFJLENBQUMsY0FBYyxDQUFDLGNBQWMsQ0FBQyxFQUFFLENBQUM7WUFDMUQsT0FBTyxjQUFjLENBQUMsZ0JBQStCLENBQUMsQ0FBQyw0QkFBNEI7UUFDckYsQ0FBQztRQUNELElBQUksQ0FBQyxjQUFjLElBQUksY0FBYyxFQUFFLENBQUM7WUFDdEMsT0FBTyxJQUFJLENBQUMsb0JBQW9CLENBQUMsSUFBSSxDQUFDLGVBQWUsQ0FBQyxjQUFjLENBQUMsQ0FBQyxDQUFDO1FBQ3pFLENBQUM7UUFFRCxPQUFPLGNBQWMsQ0FBQyxDQUFDLDJCQUEyQjtJQUNwRCxDQUFDO0lBRUQsTUFBTSxDQUFDLHNCQUFzQixDQUFDLEtBQW9CO1FBQ2hELElBQUksU0FBUyxHQUFHLElBQUksQ0FBQyxnQkFBZ0IsQ0FBQyxLQUFLLENBQUMsTUFBcUIsQ0FBQyxDQUFDO1FBRW5FLFNBQVMsR0FBRyxJQUFJLENBQUMsb0JBQW9CLENBQUMsU0FBUyxDQUFnQixDQUFDO1FBRWhFLE9BQU8sU0FBUyxDQUFDO0lBQ25CLENBQUM7SUFFRCxNQUFNLENBQUMscUJBQXFCLENBQUMsS0FBb0I7UUFDL0MsSUFBSSxRQUFRLEdBQUcsSUFBSSxDQUFDLGVBQWUsQ0FBQyxLQUFLLENBQUMsTUFBcUIsQ0FBQyxDQUFDO1FBQ2pFLFFBQVEsR0FBRyxJQUFJLENBQUMsb0JBQW9CLENBQUMsUUFBUSxDQUFnQixDQUFDO1FBRTlELE9BQU8sUUFBUSxDQUFDO0lBQ2xCLENBQUM7SUFFRCxNQUFNLENBQUMsZ0JBQWdCLENBQUMsT0FBMkI7UUFDakQsT0FBTyxPQUFPLEVBQUUsT0FBTyxDQUFDLElBQUksSUFBSSxDQUFDLG9CQUFvQixFQUFFLENBQUMsRUFBRSxpQkFBZ0MsQ0FBQztJQUM3RixDQUFDO0lBRUQsTUFBTSxDQUFDLGVBQWUsQ0FBQyxPQUEyQjtRQUNoRCxPQUFPLE9BQU8sRUFBRSxPQUFPLENBQUMsSUFBSSxJQUFJLENBQUMsb0JBQW9CLEVBQUUsQ0FBQyxFQUFFLGdCQUErQixDQUFDO0lBQzVGLENBQUM7SUFFRCwyQ0FBMkM7SUFDM0MsTUFBTSxDQUFDLGNBQWMsQ0FBQyxFQUE4QjtRQUNsRCxPQUFPLENBQUMsQ0FBQyxDQUFDLEVBQUUsSUFBSSxFQUFFLENBQUMsWUFBWSxDQUFDLE1BQU0sQ0FBQyxLQUFLLE9BQU8sQ0FBQyxDQUFDO0lBQ3ZELENBQUM7SUFFRCw4RUFBOEU7SUFDOUUsTUFBTSxDQUFDLHFCQUFxQixDQUFDLEVBQThCO1FBQ3pELE9BQU8sQ0FBQyxDQUFDLENBQUMsRUFBRSxJQUFJLEVBQUUsQ0FBQyxZQUFZLENBQUMsTUFBTSxDQUFDLEtBQUssY0FBYyxDQUFDLENBQUM7SUFDOUQsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogQ2xhc3NlIHV0aWxpdGFpcmUgcGVybWV0dGFudCBkZSByw6ljdXDDqXJlciBsZXMgw6lsw6ltZW50cyA8bGk+IGNvbmNlcm7DqXNcbiAqIGRhbnMgbGUgY2FkcmUgZGUgbGEgZ2VzdGlvbiBkdSBmb2N1cyDDoCBsYSBuYXZpZ2F0aW9uIGNsYXZpZXIgZHUgY29tcG9zYW50IG11bHRpc2VsZWN0XG4gKiBzZWxvbiBsYSBzdHJ1Y3R1cmUgZGVzIG9wdGlvbnMgYXZlYyBncm91cGVzIMOpdmVudHVlbHNcbiAqL1xuZXhwb3J0IGNsYXNzIFNlbGVjdEZvY3VzVXRpbHMge1xuICBzdGF0aWMgcmVhZG9ubHkgQ09OVEFJTkVSX0xJU1RfQ0xBU1MgPSAnZHNmcngtbXVsdGlzZWxlY3RfX2xpc3QnO1xuXG4gIHByaXZhdGUgY29uc3RydWN0b3IoKSB7fVxuXG4gIC8qKlxuICAgKiBEw6l0ZXJtaW5lIGwnw6lsw6ltZW50IHN1aXZhbnQgw6AgZm9jdXMgKGxpIHJvbGU9b3B0aW9uKSwgZW4gdGVuYW50IGNvbXB0ZSBkZXMgZ3JvdXBlcyBldCBkZXMgw6lsw6ltZW50cyBlbmZhbnRzLlxuICAgKi9cbiAgc3RhdGljIGZpbmROZXh0TGlzdEl0ZW0oZWxlbWVudFRvRm9jdXM6IEhUTUxFbGVtZW50IHwgbnVsbCwgY3VycmVudEVsZW1lbnQ/OiBIVE1MRWxlbWVudCk6IEhUTUxFbGVtZW50IHwgbnVsbCB7XG4gICAgaWYgKGVsZW1lbnRUb0ZvY3VzKSB7XG4gICAgICByZXR1cm4gdGhpcy5pc0dyb3VwRWxlbWVudChlbGVtZW50VG9Gb2N1cylcbiAgICAgICAgPyAoZWxlbWVudFRvRm9jdXMuY2hpbGRyZW5bMV0gYXMgSFRNTEVsZW1lbnQpIC8vIFByZW1pZXIgw6lsw6ltZW50IGR1IGdyb3VwZVxuICAgICAgICA6IGVsZW1lbnRUb0ZvY3VzOyAvLyDDiWzDqW1lbnQgZGlyZWN0IHN1aXZhbnRcbiAgICB9XG5cbiAgICAvLyAgcHJvY2hhaW4gZWxlbWVudCBkZSBsYSBsaXN0ZSBvdSBzb3VzLWxpc3RlXG4gICAgaWYgKGN1cnJlbnRFbGVtZW50KSB7XG4gICAgICAvLyBmb2N1cyBzdXIgbGUgcHJvY2hhaW4gZ3JvdXBlXG4gICAgICBjb25zdCBuZXh0R3JvdXAgPSBjdXJyZW50RWxlbWVudC5wYXJlbnRFbGVtZW50Py5uZXh0RWxlbWVudFNpYmxpbmc7XG4gICAgICBpZiAobmV4dEdyb3VwICYmIHRoaXMuaXNHcm91cEVsZW1lbnQobmV4dEdyb3VwKSkge1xuICAgICAgICByZXR1cm4gbmV4dEdyb3VwLmNoaWxkcmVuWzFdIGFzIEhUTUxFbGVtZW50OyAvLyBQcmVtaWVyIMOpbMOpbWVudCBkdSBncm91cGUgc3VpdmFudFxuICAgICAgfVxuXG4gICAgICAvLyBSZXRvdXIgYXUgZMOpYnV0IHNpIGZpbiBkZSBsaXN0ZVxuICAgICAgcmV0dXJuIHRoaXMuZmluZE5leHRMaXN0SXRlbSh0aGlzLmdldEZpcnN0TGlzdEl0ZW0oY3VycmVudEVsZW1lbnQpKTtcbiAgICB9XG5cbiAgICByZXR1cm4gbnVsbDtcbiAgfVxuXG4gIC8qKlxuICAgKiBEw6l0ZXJtaW5lIGwnw6lsw6ltZW50IHByw6ljw6lkZW50IMOgIGZvY3VzIChsaSByb2xlPW9wdGlvbiksIGVuIHRlbmFudCBjb21wdGUgZGVzIGdyb3VwZXMgZXQgZGVzIMOpbMOpbWVudHMgZW5mYW50cy5cbiAgICovXG4gIHN0YXRpYyBmaW5kUHJldmlvdXNMaXN0SXRlbShlbGVtZW50VG9Gb2N1czogSFRNTEVsZW1lbnQgfCBudWxsLCBjdXJyZW50RWxlbWVudD86IEhUTUxFbGVtZW50KTogSFRNTEVsZW1lbnQgfCBudWxsIHtcbiAgICAvLyBmb2N1cyBzdXIgbGUgbm9tIGR1IGdyb3VwZSxcbiAgICBpZiAodGhpcy5pc1ByZXNlbnRhdGlvbkVsZW1lbnQoZWxlbWVudFRvRm9jdXMpKSB7XG4gICAgICBjb25zdCBwcmV2R3JvdXAgPSBlbGVtZW50VG9Gb2N1cz8ucGFyZW50RWxlbWVudD8ucHJldmlvdXNFbGVtZW50U2libGluZztcbiAgICAgIGlmIChwcmV2R3JvdXAgJiYgdGhpcy5pc0dyb3VwRWxlbWVudChwcmV2R3JvdXApKSB7XG4gICAgICAgIHJldHVybiBwcmV2R3JvdXAubGFzdEVsZW1lbnRDaGlsZCBhcyBIVE1MRWxlbWVudDsgLy8gRGVybmllciDDqWzDqW1lbnQgZHUgZ3JvdXBlIHByw6ljw6lkZW50XG4gICAgICB9XG4gICAgICBpZiAoY3VycmVudEVsZW1lbnQpIHtcbiAgICAgICAgLy8gcHJlbWllciBncm91cGUgb3UgZWxlbWVudCBkZSBsYSBsaXN0ZSwgcmVudm95ZXIgYXUgZGVybmllciDDqWzDqW1lbnRcbiAgICAgICAgcmV0dXJuIHRoaXMuZmluZFByZXZpb3VzTGlzdEl0ZW0odGhpcy5nZXRMYXN0TGlzdEl0ZW0oY3VycmVudEVsZW1lbnQpKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICBpZiAoZWxlbWVudFRvRm9jdXMgJiYgdGhpcy5pc0dyb3VwRWxlbWVudChlbGVtZW50VG9Gb2N1cykpIHtcbiAgICAgIHJldHVybiBlbGVtZW50VG9Gb2N1cy5sYXN0RWxlbWVudENoaWxkIGFzIEhUTUxFbGVtZW50OyAvLyBkZXJuaWVyIGVsZW1lbnQgZHUgZ3JvdXBlXG4gICAgfVxuICAgIGlmICghZWxlbWVudFRvRm9jdXMgJiYgY3VycmVudEVsZW1lbnQpIHtcbiAgICAgIHJldHVybiB0aGlzLmZpbmRQcmV2aW91c0xpc3RJdGVtKHRoaXMuZ2V0TGFzdExpc3RJdGVtKGN1cnJlbnRFbGVtZW50KSk7XG4gICAgfVxuXG4gICAgcmV0dXJuIGVsZW1lbnRUb0ZvY3VzOyAvLyDDiWzDqW1lbnQgZGlyZWN0IHByw6ljw6lkZW50XG4gIH1cblxuICBzdGF0aWMgc2V0Rm9jdXNFbGVtZW50T25GaXJzdChldmVudDogS2V5Ym9hcmRFdmVudCk6IEhUTUxFbGVtZW50IHtcbiAgICBsZXQgZmlyc3RJdGVtID0gdGhpcy5nZXRGaXJzdExpc3RJdGVtKGV2ZW50LnRhcmdldCBhcyBIVE1MRWxlbWVudCk7XG5cbiAgICBmaXJzdEl0ZW0gPSB0aGlzLmZpbmRQcmV2aW91c0xpc3RJdGVtKGZpcnN0SXRlbSkgYXMgSFRNTEVsZW1lbnQ7XG5cbiAgICByZXR1cm4gZmlyc3RJdGVtO1xuICB9XG5cbiAgc3RhdGljIHNldEZvY3VzRWxlbWVudE9uTGFzdChldmVudDogS2V5Ym9hcmRFdmVudCk6IEhUTUxFbGVtZW50IHtcbiAgICBsZXQgbGFzdEl0ZW0gPSB0aGlzLmdldExhc3RMaXN0SXRlbShldmVudC50YXJnZXQgYXMgSFRNTEVsZW1lbnQpO1xuICAgIGxhc3RJdGVtID0gdGhpcy5maW5kUHJldmlvdXNMaXN0SXRlbShsYXN0SXRlbSkgYXMgSFRNTEVsZW1lbnQ7XG5cbiAgICByZXR1cm4gbGFzdEl0ZW07XG4gIH1cblxuICBzdGF0aWMgZ2V0Rmlyc3RMaXN0SXRlbShlbGVtZW50OiBIVE1MRWxlbWVudCB8IG51bGwpOiBIVE1MRWxlbWVudCB8IG51bGwge1xuICAgIHJldHVybiBlbGVtZW50Py5jbG9zZXN0KGAuJHt0aGlzLkNPTlRBSU5FUl9MSVNUX0NMQVNTfWApPy5maXJzdEVsZW1lbnRDaGlsZCBhcyBIVE1MRWxlbWVudDtcbiAgfVxuXG4gIHN0YXRpYyBnZXRMYXN0TGlzdEl0ZW0oZWxlbWVudDogSFRNTEVsZW1lbnQgfCBudWxsKTogSFRNTEVsZW1lbnQgfCBudWxsIHtcbiAgICByZXR1cm4gZWxlbWVudD8uY2xvc2VzdChgLiR7dGhpcy5DT05UQUlORVJfTElTVF9DTEFTU31gKT8ubGFzdEVsZW1lbnRDaGlsZCBhcyBIVE1MRWxlbWVudDtcbiAgfVxuXG4gIC8qKiBMJ8OpbMOpbWVudCBlc3QgbGUgY29udGFpbmVyIGR1IGdyb3VwZSAqL1xuICBzdGF0aWMgaXNHcm91cEVsZW1lbnQoZWw6IEVsZW1lbnQgfCBudWxsIHwgdW5kZWZpbmVkKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuICEhKGVsICYmIGVsLmdldEF0dHJpYnV0ZSgncm9sZScpID09PSAnZ3JvdXAnKTtcbiAgfVxuXG4gIC8qKiBMJ8OpbMOpbWVudCBlc3QgdW4gw6lsw6ltZW50IGRlIHByw6lzZW50YXRpb24gY29ycmVzcG9uZGFudCBhdSBub20gZHUgZ3JvdXBlICovXG4gIHN0YXRpYyBpc1ByZXNlbnRhdGlvbkVsZW1lbnQoZWw6IEVsZW1lbnQgfCBudWxsIHwgdW5kZWZpbmVkKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuICEhKGVsICYmIGVsLmdldEF0dHJpYnV0ZSgncm9sZScpID09PSAncHJlc2VudGF0aW9uJyk7XG4gIH1cbn1cbiJdfQ==