# Dépannage

> Résolvez les problèmes d’intégration courants : styles absents, hôte sans hauteur, refs nulles, vues vides, imports erronés, React dupliqué, CSP et Tailwind.

Source: https://superscheduler.org/fr/docs/troubleshooting/
Reviewed: 2026-10-07

La plupart des problèmes viennent de quelques causes : la feuille de style n’est pas importée, l’hôte n’a pas de hauteur pour `height="100%"`, le contrôle est lu avant le montage, ou la vue montre une seule journée, aujourd’hui, alors que les données se trouvent ailleurs (`days` vaut 1 par défaut et `startDate` vaut aujourd’hui). Vérifiez aussi que les chaînes de date comportent les secondes, que les valeurs `resource` des événements correspondent exactement aux id des ressources, et qu’une seule copie de React est installée. Chaque section ci-dessous donne le symptôme, la cause et la solution.

Trouvez le symptôme, vérifiez la cause, appliquez la solution. Les sections concernent Pro et Lite, sauf si elles nomment une édition. Si votre problème n’est pas ici, la [référence de l’API](https://superscheduler.org/fr/docs/api-reference/) liste chaque option implémentée avec sa valeur par défaut, et sa section [API réservées](https://superscheduler.org/fr/docs/api-reference/#reserved) liste ce qui est typé mais pas implémenté.

## Le planificateur s’affiche sans styles
**Symptôme.** Les lignes et les événements apparaissent, mais sans lignes de grille, sans couleurs ni en-têtes alignés.

**Cause.** La feuille de style n’est pas chargée, ou c’est celle de l’autre édition qui l’est.

**Solution.** Importez-la une seule fois, dans votre point d’entrée ou votre layout racine : `import 'super-scheduler/styles.css'` pour Pro, `import 'super-scheduler-lite/styles.css'` pour Lite. La feuille de style Pro vit dans `@layer super-scheduler` avec des sélecteurs de spécificité nulle : n’importe laquelle de vos règles hors couche l’emporte, et une réinitialisation large comme `* { border: 0 }` supprime donc aussi les bordures de la bibliothèque (voir [Tailwind](#tailwind)). `unstyled` désactive volontairement les règles visuelles de la bibliothèque.

## Le planificateur fait 0 px de haut ou n’a pas la hauteur définie
**Symptôme.** Rien n’est visible, ou la grille est plus petite ou plus grande que prévu.

**Causes et solutions (Pro).**

- `heightSpec` vaut `'Max'` par défaut : `height` (600 par défaut) est un plafond, et la grille est aussi haute que ses lignes, jusqu’à cette valeur. Deux lignes avec `height={320}` s’affichent sur environ 130 px de haut. Utilisez `heightSpec="Fixed"` pour une boîte de taille constante.
- `height="100%"` remplit l’élément hôte du composant, un `<div>` sans style que `SuperSchedulerComponent` rend à l’intérieur de votre conteneur. Si ce `<div>` n’a pas de hauteur, le planificateur s’effondre à 0 px. Donnez au conteneur une hauteur définie et à l’hôte 100 % :

```tsx
// src/FillParent.tsx
import { SuperSchedulerComponent } from 'super-scheduler'
import type { SuperScheduler } from 'super-scheduler'

interface Props {
  readonly rooms: SuperScheduler.ResourceData[]
  readonly events: SuperScheduler.EventData[]
}

// height="100%" fills the component's own host <div>: .fill sizes it (see the CSS below).
export function FillParent({ rooms, events }: Props) {
  return (
    <div className="fill">
      <SuperSchedulerComponent
        height="100%"
        startDate="2026-10-01"
        days={31}
        scale="Day"
        resources={rooms}
        events={events}
      />
    </div>
  )
}
```
```css
.fill {
  height: 70vh; /* or a flex item with min-height: 0 */
}
.fill > div {
  height: 100%;
}
```

- `heightSpec="Auto"` dimensionne le contrôle selon son contenu, sans barre de défilement verticale : c’est alors la page qui défile.
- `SchedulerPanes` prend sa propre `height` numérique pour l’ensemble des volets.

Dans Lite, `height` est toujours un nombre fixe de pixels (400 par défaut). Dans les deux éditions, quand le conteneur est un élément flex, donnez-lui `min-width: 0` dans une ligne (ou `min-height: 0` dans une colonne) ; sinon, la taille minimale automatique de l’élément flex peut laisser la grille élargir ou allonger la mise en page au lieu de défiler.

## `ref.current` ou `control` vaut null
**Cause.** Le contrôle est créé dans `componentDidMount`. Pendant le premier rendu, côté serveur et après le démontage, il n’existe aucun contrôle actif : `ref.current` vaut `null` avant le montage, et les objets ref passés dans `controlRef` sont remis à `null` au démontage.

**Solution.** Lisez le contrôle dans des effets et des gestionnaires d’événements, jamais pendant le rendu. `useSchedulerControl()` renvoie le contrôle sous forme d’état, si bien qu’un effet peut en dépendre :

```tsx
// src/Planning.tsx
import { useEffect } from 'react'
import { SuperScheduler, SuperSchedulerComponent, useSchedulerControl } from 'super-scheduler'

const START = SuperScheduler.Date.today().addDays(-30)

export function Planning({ rooms }: { rooms: SuperScheduler.ResourceData[] }) {
  // `control` is null during the first render and the live control after mount.
  const { controlRef, control } = useSchedulerControl()

  useEffect(() => {
    if (control === null || control.disposed()) return
    control.scrollTo(SuperScheduler.Date.today(), false, 'middle')
  }, [control])

  return (
    <SuperSchedulerComponent
      controlRef={controlRef}
      startDate={START}
      days={90}
      scale="Day"
      resources={rooms}
    />
  )
}
```
Dans Pro, une fonction `controlRef` est appelée avec le contrôle au montage et n’est pas appelée avec `null` au démontage. Une référence au contrôle conservée d’avant un démontage pointe vers un contrôle libéré : vérifiez `control.disposed()` dans le code asynchrone. Avec l’API impérative, appelez `init()` avant toute autre chose ; `update()` avant `init()` lève `SuperScheduler.Exception`.

## Rien ne s’affiche dans la grille
Vérifiez ces points dans l’ordre :

1. **Plage.** `days` vaut `1` par défaut et `startDate` vaut aujourd’hui. Dans Pro, `scale` correspond aussi par défaut à des cellules d’une heure (`'CellDuration'` avec 60 minutes). Réglez `startDate`, `days` et `scale="Day"` sur la période que couvrent vos données. Les jeux de données de `super-scheduler/datasets` commencent par défaut le 2026-01-01.
2. **Chaînes de date.** `'2026-10-01T10:00'` lève `SchedulerDate: "2026-10-01T10:00" is not an ISO 8601 date`. Utilisez `'2026-10-01'` ou `'2026-10-01T10:00:00'`. Les objets `Date` natifs ne passent pas la vérification de types ; convertissez-les (voir [dates civiles](https://superscheduler.org/fr/docs/locales-dates-timezones/#civil-dates)).
3. **Id des ressources.** La `resource` d’un événement doit être exactement égale à l’`id` d’une ressource : `1` et `'1'` sont différents. Les événements de ressources inconnues ne sont pas dessinés.
4. **Arborescences (Pro).** Les `children` ne s’affichent qu’avec `treeEnabled`, et un parent ne montre ses enfants que s’il a `expanded: true`.
5. **Filtres et indicateurs.** Un `control.events.filter()` ou un `control.rows.filter()` actif, ou `hidden: true` sur l’événement, le masque.
6. **État vide.** Sans ligne visible, Pro affiche `emptyState` si vous l’avez défini ; Lite affiche « No resources » par défaut.

## Les modifications n’apparaissent pas
- **Modification sur place.** Le composant React ne transmet une prop que si son identité change. Ajouter des éléments au même tableau `events` ou `resources` puis refaire un rendu n’envoie rien. Passez un nouveau tableau, ou appelez `control.update()` après une modification sur place.
- **Le tableau change tout seul (Pro).** Le contrôle adopte le tableau `events` que vous passez et le modifie avec splice quand des événements sont ajoutés, retirés ou validés. Passez une copie (`useMemo(() => events.slice(), [events])`) si ce tableau est un état partagé. Un tableau gelé, comme en produisent certaines bibliothèques d’état en développement, fait lever une `TypeError` à `control.events.add`, `update` et `remove`.
- **Mise à jour d’un id inconnu.** `control.events.update(data)` ne fait rien quand l’id n’est pas chargé ; utilisez `add` pour les nouveaux événements. `add` lève une exception en cas d’id en double.
- **`defaultEvents` a changé.** Il n’est lu qu’une fois, lors de `init()` ; les valeurs ultérieures sont ignorées avec un avertissement en développement. Utilisez des `events` contrôlés pour des données qui changent.
- **Hooks de cellule (Pro).** Les résultats de `onBeforeCellRender` sont mis en cache par cellule. Si une cellule dépend des événements, définissez `cellsAutoUpdated: true` sur sa ressource ou appelez `control.update()`.
- **Une prop retirée.** Une prop qui disparaît entre deux rendus revient à sa valeur par défaut.

## Erreurs d’import et sous-chemins erronés
Seuls ces points d’entrée existent ; tout autre, comme `super-scheduler/dist/...`, échoue avec une erreur « not exported » de votre bundler ou de Node :

- Pro : `super-scheduler`, `/styles.css`, `/react-render`, `/history`, `/minimap`, `/panes`, `/zoom-ui`, `/views`, `/ranges`, `/hooks`, `/tailwind`, `/datasets` et `/core`.
- Lite : `super-scheduler-lite` et `super-scheduler-lite/styles.css` uniquement. Les modules Pro ne font pas partie de Lite.

TypeScript les résout via les `exports` du paquet avec `moduleResolution` réglé sur `bundler`, `node16` ou `nodenext` ; l’ancien réglage `node` fonctionne grâce aux `typesVersions` du paquet. Avec `noUncheckedSideEffectImports` (TypeScript 5.6 et ultérieur), l’import d’une feuille de style nécessite une déclaration `declare module '*.css'`, que fournissent déjà les types client des bundlers comme `vite/client`. `super-scheduler/tailwind` est un preset de style CommonJS : chargez-le avec `require('super-scheduler/tailwind')`, ou avec un import par défaut si votre configuration prend en charge l’interopérabilité CommonJS.

## Messages de la console
| Message | Signification |
|---|---|
| `[super-scheduler] renderEvent needs the component from "super-scheduler/react-render"` | Une prop de rendu React (`renderEvent`, `renderCell`, `eventHover`, un handler `onBefore*DomAdd`...) a été donnée au composant racine. Importez `SuperSchedulerComponent` depuis `super-scheduler/react-render`. |
| `super-scheduler: <feature> is not supported yet` | Une API réservée : typée, acceptée, inerte. Voir [API réservées](https://superscheduler.org/fr/docs/api-reference/#reserved). |
| `[super-scheduler] events wins over defaultEvents` | Les deux props ont été données ; c’est `events` qui est utilisée. |
| `[super-scheduler] defaultEvents is read only during init()` | Une nouvelle valeur de `defaultEvents` après le montage est ignorée. |
| `SuperScheduler Lite: unsupported option "..."` | Lite lève une erreur pour toute option qu’il n’implémente pas, y compris en production. `scale` doit valoir `'Day'`, et les `children`, `frozen`, `split` et `columns` des ressources nécessitent Pro. |

Pro n’affiche ces avertissements que lorsque `NODE_ENV` ne vaut pas `production`, et les avertissements des API réservées une seule fois par fonction. Les erreurs de Lite sont levées dans tous les builds.

## « Invalid hook call » ou deux copies de React
**Symptôme.** « Invalid hook call » depuis `useSchedulerControl` ou `useScheduler`, du contenu React dans les slots de rendu qui ne voit pas vos context providers, ou des erreurs de portail.

**Cause.** La bibliothèque résout une autre copie de React que votre application. Les deux éditions déclarent React comme dépendance peer et ne l’embarquent jamais : cela arrive donc quand l’installation ou un lien apporte une seconde copie, par exemple un paquet lié ou compilé localement, un monorepo avec plusieurs versions de React, ou des plages peer non satisfaites (18.2 ou ultérieur, ou 19).

**Solution.** `npm ls react react-dom` doit afficher une seule version. Installez l’archive tarball Pro au lieu de lier une copie locale. Dans Vite, ajoutez `resolve: { dedupe: ['react', 'react-dom'] }` ; dans webpack, faites pointer des alias `react` et `react-dom` vers les copies de votre application.

## Erreurs de Content Security Policy
La bibliothèque n’a besoin ni de scripts inline ni de styles `'unsafe-inline'` : elle se charge sous forme de modules et écrit la géométrie via `element.style`. Si la console signale des violations, vérifiez trois choses : les chunks chargés à la demande doivent être autorisés par `script-src` ; les petites images SVG `data:` de la feuille de style Pro nécessitent `img-src data:` ; et les attributs `style` inline dans les chaînes HTML que vous passez (`html`, `bubbleHtml`) sont bloqués, utilisez donc des classes. Les détails et un exemple de politique se trouvent dans [Rendu serveur](https://superscheduler.org/fr/docs/ssr-prerender/#csp).

## Tailwind supprime les bordures ou écrase le planificateur
Le preflight de Tailwind v3 est hors couche et réinitialise les bordures de tous les éléments, ce qui l’emporte sur les règles en couche de la bibliothèque. Placez le preflight dans une couche inférieure à SuperScheduler :

```css
@layer tw-base, super-scheduler;

@import 'super-scheduler/styles.css';

@layer tw-base {
  @tailwind base;
}
@tailwind components;
@tailwind utilities;
```

Avec Tailwind v4, déclarez l’ordre des couches avant les imports pour que la bibliothèque se place entre `base` et vos utilitaires :

```css
@layer theme, base, super-scheduler, components, utilities;

@import 'tailwindcss';
@import 'super-scheduler/styles.css';
```

Voir [Thèmes](https://superscheduler.org/fr/docs/theming/) pour le preset Tailwind et la correspondance des tokens.

## Autres surprises
- **Les événements s’alignent sur des journées entières (Pro).** `useEventBoxes` vaut `'Always'` par défaut, ce qui dessine les événements sur des cellules entières. Utilisez `'Never'` pour dessiner les horaires exacts, et ajoutez `eventMoveByCell` si le glissement doit rester ancré aux cellules.
- **Un clic laisse une sélection derrière lui (Pro).** Un clic sur une cellule vide est une sélection d’une cellule signalée à `onTimeRangeSelected` avec `origin: 'click'`, et son ombre reste jusqu’à la sélection suivante ou un clic ailleurs. Appelez `args.control.clearSelection()` dans le handler.
- **Les touches ne font rien (Pro).** `keyboardEnabled` vaut `false` par défaut. `keyboardMode="Full"` en a aussi besoin. Avec plusieurs planificateurs sur une page, définissez `keyboardTarget="component"`.
- **Les dates sont devenues des objets (Pro).** Après un glissement ou un redimensionnement, le `start` et le `end` de l’événement sont des objets `SuperScheduler.Date`. `String(date)` et `JSON.stringify` donnent la valeur ISO civile ; `date.toString('d MMM', locale)` la formate.
- **Mauvais jour de la semaine.** `SuperScheduler.Date#getDay()` renvoie le jour du mois. Utilisez `getDayOfWeek()` (0 correspond à dimanche) ou `dayOfWeekISO()` (1 correspond à lundi).

Guides associés : [Intégration React](https://superscheduler.org/fr/docs/react-integration/), [État contrôlé](https://superscheduler.org/fr/docs/controlled-state/), [Rendu serveur](https://superscheduler.org/fr/docs/ssr-prerender/) et [Virtualisation et performances](https://superscheduler.org/fr/docs/performance-virtualization/).
