2019-12-03 22:00:21 +00:00
|
|
|
|
import {useState, useEffect} from 'react';
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Hook permettant d’obtenir des résultats asynchrones.
|
|
|
|
|
*
|
|
|
|
|
* @param initial Valeur initiale lorsque la promesse n’a pas répondu.
|
|
|
|
|
* @param func Fonction renvoyant une promesse.
|
|
|
|
|
* @param ...args Arguments à passer à `func` qui sont susceptibles de changer.
|
|
|
|
|
* @return Résultats de la promesse.
|
|
|
|
|
*/
|
|
|
|
|
export const useAsync = (initial, func, ...args) =>
|
|
|
|
|
{
|
|
|
|
|
const [results, setResults] = useState(initial);
|
|
|
|
|
|
|
|
|
|
useEffect(() =>
|
|
|
|
|
{
|
|
|
|
|
const fetcher = async () =>
|
|
|
|
|
{
|
|
|
|
|
setResults(await func(...args));
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
fetcher();
|
|
|
|
|
}, args);
|
|
|
|
|
|
|
|
|
|
return results;
|
|
|
|
|
};
|
2019-12-04 22:59:52 +00:00
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Crée un état composé d’une liste et d’un élément ayant le focus dans cette
|
|
|
|
|
* liste. À la modification de la liste ou de l’indice de l’élément ayant le
|
2019-12-04 23:54:44 +00:00
|
|
|
|
* focus, la contrainte suivante est imposée :
|
2019-12-04 23:16:27 +00:00
|
|
|
|
*
|
|
|
|
|
* — si la liste n’est pas vide, focus ∈ [0, taille de la liste].
|
|
|
|
|
* — sinon, focus = 0.
|
2019-12-04 22:59:52 +00:00
|
|
|
|
*/
|
|
|
|
|
export const useFocusableList = () =>
|
|
|
|
|
{
|
|
|
|
|
const [list, setList] = useState([]);
|
|
|
|
|
const [focus, setFocus] = useState(0);
|
|
|
|
|
|
|
|
|
|
return {
|
2019-12-05 02:46:57 +00:00
|
|
|
|
/**
|
|
|
|
|
* Contenu courant de la liste.
|
|
|
|
|
*/
|
2019-12-04 22:59:52 +00:00
|
|
|
|
list,
|
2019-12-05 02:46:57 +00:00
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Indice de l’élément ayant présentement le focus.
|
|
|
|
|
*/
|
2019-12-04 22:59:52 +00:00
|
|
|
|
focus,
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Modifie la liste et s’assure que l’élément ayant le focus est
|
|
|
|
|
* toujours dans sa plage de valeurs possibles.
|
|
|
|
|
*
|
|
|
|
|
* @param nextList Nouvelle liste.
|
|
|
|
|
*/
|
|
|
|
|
setList(nextList)
|
|
|
|
|
{
|
|
|
|
|
setList(nextList);
|
2019-12-04 23:16:27 +00:00
|
|
|
|
setFocus(
|
|
|
|
|
nextList.length === 0
|
|
|
|
|
? 0
|
|
|
|
|
: Math.min(nextList.length - 1, focus)
|
|
|
|
|
);
|
2019-12-04 22:59:52 +00:00
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Modifie l’élément ayant le focus en imposant les contraintes
|
|
|
|
|
* d’intégrité.
|
|
|
|
|
*
|
|
|
|
|
* @param nextFocus Indice du nouvel élément ayant le focus.
|
|
|
|
|
*/
|
|
|
|
|
setFocus(nextFocus)
|
|
|
|
|
{
|
2019-12-04 23:46:29 +00:00
|
|
|
|
const itemCount = list.length;
|
|
|
|
|
|
|
|
|
|
if (itemCount === 0)
|
|
|
|
|
{
|
|
|
|
|
// Sur la liste vide, on ne peut pas changer le focus
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Ramène une valeur négative dans les positifs
|
|
|
|
|
while (nextFocus < 0) { nextFocus += itemCount; }
|
|
|
|
|
|
|
|
|
|
// Ramène une valeur trop grande à l’intérieur de la liste
|
|
|
|
|
nextFocus = nextFocus % itemCount;
|
|
|
|
|
|
|
|
|
|
setFocus(nextFocus);
|
2019-12-04 22:59:52 +00:00
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
};
|
2019-12-05 02:46:57 +00:00
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Crée une liste de termes de recherche.
|
|
|
|
|
*/
|
|
|
|
|
export const useQuery = () =>
|
|
|
|
|
{
|
|
|
|
|
const [query, setQuery] = useState([]);
|
|
|
|
|
|
|
|
|
|
return {
|
|
|
|
|
/**
|
|
|
|
|
* Liste des termes de la requête.
|
|
|
|
|
*/
|
|
|
|
|
query,
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Ajoute un terme à la requête.
|
|
|
|
|
*
|
|
|
|
|
* @param term Terme à ajouter.
|
|
|
|
|
*/
|
|
|
|
|
addTerm(term)
|
|
|
|
|
{
|
|
|
|
|
if (query.some(({id}) => id === term.id))
|
|
|
|
|
{
|
|
|
|
|
// N’ajoute pas les termes déjà sélectionnés
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
setQuery(query.concat([term]));
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Supprime un terme de la requête.
|
|
|
|
|
*
|
|
|
|
|
* @param index Indice du terme à supprimer dans la liste.
|
|
|
|
|
*/
|
|
|
|
|
removeTerm(index)
|
|
|
|
|
{
|
|
|
|
|
setQuery([
|
|
|
|
|
...query.slice(0, index),
|
|
|
|
|
...query.slice(index + 1)
|
|
|
|
|
]);
|
|
|
|
|
},
|
|
|
|
|
};
|
|
|
|
|
};
|