Utilitaires

Fichiers rangés avec les composants mais qui n’en sont pas : ils servent aux composants.

opensModal.ts

Exporte : opensModal

src/components/opensModal.ts
import type { MouseEvent } from 'react';

/**
 * Lien vers une page d'information (/methode, /sources, /pays) qui ouvre sa modale au clic simple : l'adresse reste
 * lisible des moteurs et s'ouvre dans un onglet au clic du milieu ou avec ⌘/Ctrl.
 */
export const opensModal = (open: () => void) => (e: MouseEvent) => {
  if (e.button !== 0 || e.metaKey || e.ctrlKey || e.shiftKey || e.altKey) return;
  e.preventDefault();
  open();
};

preloadable.tsx

Exporte : preloadable

src/components/preloadable.tsx
import { lazy, useState, type ComponentType } from 'react';

/**
 * Composant chargé à part, comme avec `lazy`, mais affiché tout de suite quand son fichier est déjà téléchargé :
 * `lazy` passe toujours par l'écran de chargement au premier affichage (au moins 300 ms avec React 19), même préchargé.
 * `preload()` télécharge le fichier à l'avance.
 */
export function preloadable<P extends object>(load: () => Promise<{ default: ComponentType<P> }>) {
  let loaded: ComponentType<P> | null = null;
  const preload = () =>
    load().then((m) => {
      loaded = m.default;
      return m;
    });
  const Lazy = lazy(preload) as unknown as ComponentType<P>;
  function Preloadable(props: P) {
    // choisi une fois pour toutes : passer de l'un à l'autre en cours de route recréerait le composant
    const [C] = useState(() => loaded ?? Lazy);
    return <C {...props} />;
  }
  return Object.assign(Preloadable, { preload });
}

techStyle.ts

Exporte : colStyle

src/components/techStyle.ts
import type { CSSProperties } from 'react';
import { mtbColor } from '../lib/colors';

/** Couleur d'une cotation S0–S5 pour les pastilles et colonnes ; S3 (noir) suit le thème pour rester visible sur fond sombre. */
export const colStyle = (g: number): CSSProperties =>
  g === 3 ? ({ '--c': 'var(--tech-black)', '--ink': 'var(--tech-black-ink)' } as CSSProperties) : ({ '--c': mtbColor(g) } as CSSProperties);