@synertech/ui 0.43.0 → 0.44.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude/skills/use-synertech-ui/SKILL.md +103 -1
- package/dist/index.cjs +10 -9
- package/dist/index.d.cts +760 -101
- package/dist/index.d.ts +760 -101
- package/dist/index.js +10 -9
- package/dist/styles.css +14 -0
- package/package.json +1 -1
|
@@ -168,6 +168,9 @@ import { cn } from "@synertech/ui";
|
|
|
168
168
|
- `BoxPlot` - Médiane, quartiles, moustaches et valeurs aberrantes
|
|
169
169
|
- `CandlestickChart` - Ouverture, haut, bas, clôture (couleurs de statut)
|
|
170
170
|
- `GanttChart` - Des tâches dans le temps, avec dépendances et jalons
|
|
171
|
+
- `ChartSyncProvider` - Plusieurs panneaux qui se lisent comme un seul objet :
|
|
172
|
+
survol partagé et fenêtre brossée en commun
|
|
173
|
+
- `ChartExportButton` - Le tableau du graphique en CSV ou JSON
|
|
171
174
|
|
|
172
175
|
### Feedback & Overlays
|
|
173
176
|
|
|
@@ -552,7 +555,10 @@ Tous les graphiques partagent la même forme de données : un tableau de lignes
|
|
|
552
555
|
et des séries qui pointent un champ, exactement comme `DataGrid`.
|
|
553
556
|
|
|
554
557
|
```tsx
|
|
555
|
-
import {
|
|
558
|
+
import {
|
|
559
|
+
LineChart, AreaChart, BarChart, PieChart, ScatterChart,
|
|
560
|
+
ChartSyncProvider, ChartExportButton, brushToPeriod,
|
|
561
|
+
} from "@synertech/ui";
|
|
556
562
|
|
|
557
563
|
const data = [
|
|
558
564
|
{ month: "Jan", revenue: 18400, cost: 12200 },
|
|
@@ -758,6 +764,75 @@ const data = [
|
|
|
758
764
|
<Select size="sm" options={regions} value={region} onValueChange={setRegion} />
|
|
759
765
|
</ChartFilterBar>
|
|
760
766
|
|
|
767
|
+
// L'état d'erreur — distinct de l'état vide, sur TOUS les graphiques du kit
|
|
768
|
+
// (« il n'y a rien » et « on n'a pas réussi à charger » sont deux affirmations
|
|
769
|
+
// différentes ; seule la seconde appelle une reprise)
|
|
770
|
+
<LineChart
|
|
771
|
+
data={rows}
|
|
772
|
+
series={series}
|
|
773
|
+
x={{ key: "month" }}
|
|
774
|
+
loading={query.isFetching}
|
|
775
|
+
error={query.isError}
|
|
776
|
+
onRetry={() => query.refetch()}
|
|
777
|
+
/>
|
|
778
|
+
|
|
779
|
+
// L'export — le tableau exact du graphique, dans la fente `actions`
|
|
780
|
+
<LineChart
|
|
781
|
+
data={rows}
|
|
782
|
+
series={series}
|
|
783
|
+
x={{ key: "month", label: "Mois" }}
|
|
784
|
+
actions={
|
|
785
|
+
<ChartExportButton
|
|
786
|
+
data={rows}
|
|
787
|
+
series={series}
|
|
788
|
+
xKey="month"
|
|
789
|
+
xLabel="Mois"
|
|
790
|
+
filename="revenus"
|
|
791
|
+
size="sm"
|
|
792
|
+
/>
|
|
793
|
+
}
|
|
794
|
+
/>
|
|
795
|
+
|
|
796
|
+
// La trappe d'évasion — dessiner DANS le tracé, avec les échelles du graphique
|
|
797
|
+
// (Line, Area, Bar, Scatter. Une fonction dessine par-dessus les marques ;
|
|
798
|
+
// `{ under, over }` atteint aussi le dessous. Coordonnées relatives à la zone
|
|
799
|
+
// de dessin, et sans clip : la marge est à la charge de l'appelant)
|
|
800
|
+
<LineChart
|
|
801
|
+
data={rows}
|
|
802
|
+
series={series}
|
|
803
|
+
x={{ key: "month" }}
|
|
804
|
+
y={{ domain: [100, 230] }} // ← réserver la place de l'annotation
|
|
805
|
+
overlay={({ xAt, yAt, dimensions }) => (
|
|
806
|
+
<rect
|
|
807
|
+
x={0}
|
|
808
|
+
y={yAt(200)}
|
|
809
|
+
width={dimensions.innerWidth}
|
|
810
|
+
height={Math.abs(yAt(160) - yAt(200))}
|
|
811
|
+
className="fill-green-500"
|
|
812
|
+
opacity={0.1}
|
|
813
|
+
/>
|
|
814
|
+
)}
|
|
815
|
+
/>
|
|
816
|
+
|
|
817
|
+
// La volumétrie — allège le TRACÉ, jamais les données
|
|
818
|
+
// (LTTB sur Line/Area, échantillon régulier sur Scatter. Le tableau, l'infobulle
|
|
819
|
+
// et la droite de tendance continuent de lire chaque ligne)
|
|
820
|
+
<LineChart data={fiftyThousandRows} series={series} x={{ key: "t", scale: "linear" }} maxPoints={400} />
|
|
821
|
+
|
|
822
|
+
// Le tableau de bord synchronisé — un pointeur, une infobulle ; une plage, toutes
|
|
823
|
+
// les cartes. `brushToPeriod` rend la fenêtre au `ChartPeriodPicker`
|
|
824
|
+
<ChartSyncProvider brush={null} onBrushChange={(range) => {
|
|
825
|
+
const next = range && brushToPeriod(range);
|
|
826
|
+
if (next) setPeriod(next);
|
|
827
|
+
}}>
|
|
828
|
+
<ChartFilterBar>
|
|
829
|
+
<ChartPeriodPicker size="sm" value={period} onChange={setPeriod} />
|
|
830
|
+
</ChartFilterBar>
|
|
831
|
+
|
|
832
|
+
<LineChart data={rows} series={series} x={xAxis} brush />
|
|
833
|
+
<BarChart data={rows} series={series} x={{ key: "day" }} />
|
|
834
|
+
</ChartSyncProvider>
|
|
835
|
+
|
|
761
836
|
// Petits multiples — le domaine est calculé sur l'ensemble et imposé à chaque panneau
|
|
762
837
|
<ChartFacets data={rows} by="region" values={["revenue"]} columns={3}>
|
|
763
838
|
{({ data, domain, label }) => (
|
|
@@ -822,6 +897,33 @@ const data = [
|
|
|
822
897
|
- **Les annotations se lisent sur l'axe des catégories.** Un `BarChart`
|
|
823
898
|
horizontal les ignore, avec un avertissement : un moment placé sur une liste
|
|
824
899
|
de noms n'en est plus un.
|
|
900
|
+
- **`error` n'est jamais `empty`.** Un panneau qui affiche « Aucune donnée »
|
|
901
|
+
après une requête échouée affirme quelque chose de faux, et ne propose aucune
|
|
902
|
+
sortie. `loading` l'emporte sur les deux : une reprise remplace le message par
|
|
903
|
+
le voyant.
|
|
904
|
+
- **Rien n'est décimé tout seul.** Un graphique qui dessinerait en douce une
|
|
905
|
+
autre forme que celle qu'on lui a remise serait pire qu'un graphique lent :
|
|
906
|
+
au-delà de 2 000 points il avertit, et `maxPoints` est à vous. Il n'allège
|
|
907
|
+
que le tracé — le tableau garde chaque ligne.
|
|
908
|
+
- **`BarChart` n'a pas de `maxPoints`.** Décimer des barres, c'est supprimer des
|
|
909
|
+
catégories : `bins` est la réponse là-bas.
|
|
910
|
+
- **`ScatterChart` échantillonne régulièrement, pas en LTTB.** Un nuage se lit à
|
|
911
|
+
sa densité ; garder les plus grands triangles en découperait l'enveloppe et
|
|
912
|
+
jetterait précisément ce qu'on regarde.
|
|
913
|
+
- **`overlay` n'est pas `children`.** Les graphiques restent des objets fermés ;
|
|
914
|
+
la trappe remet la géométrie résolue et rien d'autre. C'est elle qui rend
|
|
915
|
+
défendable chaque refus de cette liste — « prenez un `BarChart` groupé » ne
|
|
916
|
+
tient que si l'application peut dessiner ce qu'elle n'obtiendra jamais du kit.
|
|
917
|
+
- **Un `ScatterChart` ne se brosse pas.** Ses deux axes sont des mesures, et une
|
|
918
|
+
fenêtre sur l'une d'elles n'est pas le geste qu'un nuage appelle.
|
|
919
|
+
- **Une plage se pose aussi au clavier.** Maj + flèches l'étend, Échap la retire :
|
|
920
|
+
un filtre qui ne s'atteint qu'à la souris est inaccessible à la moitié des
|
|
921
|
+
lecteurs.
|
|
922
|
+
- **Une fenêtre qui a déjà recadré le tableau de bord n'a plus à être teintée.**
|
|
923
|
+
Les panneaux SONT la fenêtre ; la bande lave alors chaque tracé de bord à bord
|
|
924
|
+
et n'énonce rien. Repassez `brush={null}` après l'avoir appliquée.
|
|
925
|
+
- **L'export écrit les mesures brutes.** Ce qui ouvre le fichier va calculer
|
|
926
|
+
dessus, et `1 234,5 $` est une chaîne. Seule la catégorie est formatée.
|
|
825
927
|
|
|
826
928
|
### Cartes KPI
|
|
827
929
|
|