@sentropic/design-system-svelte 0.34.0 → 0.34.21

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.
Files changed (112) hide show
  1. package/dist/AppChrome.svelte +660 -0
  2. package/dist/AppChrome.svelte.d.ts +74 -0
  3. package/dist/AppChrome.svelte.d.ts.map +1 -0
  4. package/dist/AppChrome.test.d.ts +2 -0
  5. package/dist/AppChrome.test.d.ts.map +1 -0
  6. package/dist/AppChrome.test.js +122 -0
  7. package/dist/AppHeader.svelte +159 -1
  8. package/dist/AppHeader.svelte.d.ts +18 -1
  9. package/dist/AppHeader.svelte.d.ts.map +1 -1
  10. package/dist/ArcDiagramChart.svelte +380 -0
  11. package/dist/ArcDiagramChart.svelte.d.ts +43 -0
  12. package/dist/ArcDiagramChart.svelte.d.ts.map +1 -0
  13. package/dist/AreaRangeChart.svelte +487 -0
  14. package/dist/AreaRangeChart.svelte.d.ts +38 -0
  15. package/dist/AreaRangeChart.svelte.d.ts.map +1 -0
  16. package/dist/AreaSplineRangeChart.svelte +478 -0
  17. package/dist/AreaSplineRangeChart.svelte.d.ts +37 -0
  18. package/dist/AreaSplineRangeChart.svelte.d.ts.map +1 -0
  19. package/dist/BellCurveChart.svelte +487 -0
  20. package/dist/BellCurveChart.svelte.d.ts +40 -0
  21. package/dist/BellCurveChart.svelte.d.ts.map +1 -0
  22. package/dist/Calendar.svelte +11 -0
  23. package/dist/ChatThread.svelte +32 -1
  24. package/dist/ChatThread.svelte.d.ts +14 -0
  25. package/dist/ChatThread.svelte.d.ts.map +1 -1
  26. package/dist/ColumnPyramidChart.svelte +332 -0
  27. package/dist/ColumnPyramidChart.svelte.d.ts +35 -0
  28. package/dist/ColumnPyramidChart.svelte.d.ts.map +1 -0
  29. package/dist/ColumnRangeChart.svelte +432 -0
  30. package/dist/ColumnRangeChart.svelte.d.ts +42 -0
  31. package/dist/ColumnRangeChart.svelte.d.ts.map +1 -0
  32. package/dist/Combobox.svelte +3 -0
  33. package/dist/ConfigItemCard.svelte +303 -0
  34. package/dist/ConfigItemCard.svelte.d.ts +37 -0
  35. package/dist/ConfigItemCard.svelte.d.ts.map +1 -0
  36. package/dist/ContentSwitcher.svelte +1 -1
  37. package/dist/DatePicker.svelte +3 -0
  38. package/dist/DependencyWheelChart.svelte +413 -0
  39. package/dist/DependencyWheelChart.svelte.d.ts +42 -0
  40. package/dist/DependencyWheelChart.svelte.d.ts.map +1 -0
  41. package/dist/DumbbellChart.svelte +403 -0
  42. package/dist/DumbbellChart.svelte.d.ts +44 -0
  43. package/dist/DumbbellChart.svelte.d.ts.map +1 -0
  44. package/dist/ErrorBarChart.svelte +428 -0
  45. package/dist/ErrorBarChart.svelte.d.ts +40 -0
  46. package/dist/ErrorBarChart.svelte.d.ts.map +1 -0
  47. package/dist/FieldCard.svelte +220 -0
  48. package/dist/FieldCard.svelte.d.ts +28 -0
  49. package/dist/FieldCard.svelte.d.ts.map +1 -0
  50. package/dist/GanttChart.svelte +410 -0
  51. package/dist/GanttChart.svelte.d.ts +39 -0
  52. package/dist/GanttChart.svelte.d.ts.map +1 -0
  53. package/dist/HLCChart.svelte +330 -0
  54. package/dist/HLCChart.svelte.d.ts +32 -0
  55. package/dist/HLCChart.svelte.d.ts.map +1 -0
  56. package/dist/HeikinAshiChart.svelte +365 -0
  57. package/dist/HeikinAshiChart.svelte.d.ts +37 -0
  58. package/dist/HeikinAshiChart.svelte.d.ts.map +1 -0
  59. package/dist/HollowCandlestickChart.svelte +357 -0
  60. package/dist/HollowCandlestickChart.svelte.d.ts +34 -0
  61. package/dist/HollowCandlestickChart.svelte.d.ts.map +1 -0
  62. package/dist/Input.svelte +3 -0
  63. package/dist/ItemChart.svelte +389 -0
  64. package/dist/ItemChart.svelte.d.ts +67 -0
  65. package/dist/ItemChart.svelte.d.ts.map +1 -0
  66. package/dist/LollipopChart.svelte +1 -1
  67. package/dist/MultiSelect.svelte +3 -0
  68. package/dist/NumberInput.svelte +3 -0
  69. package/dist/OHLCChart.svelte +343 -0
  70. package/dist/OHLCChart.svelte.d.ts +33 -0
  71. package/dist/OHLCChart.svelte.d.ts.map +1 -0
  72. package/dist/OrganizationChart.svelte +284 -0
  73. package/dist/OrganizationChart.svelte.d.ts +19 -0
  74. package/dist/OrganizationChart.svelte.d.ts.map +1 -0
  75. package/dist/PasswordInput.svelte +3 -0
  76. package/dist/PolygonChart.svelte +189 -0
  77. package/dist/PolygonChart.svelte.d.ts +17 -0
  78. package/dist/PolygonChart.svelte.d.ts.map +1 -0
  79. package/dist/ScoreCard.svelte +172 -0
  80. package/dist/ScoreCard.svelte.d.ts +27 -0
  81. package/dist/ScoreCard.svelte.d.ts.map +1 -0
  82. package/dist/Search.svelte +7 -5
  83. package/dist/Select.svelte +3 -0
  84. package/dist/StreamgraphChart.svelte +283 -0
  85. package/dist/StreamgraphChart.svelte.d.ts +23 -0
  86. package/dist/StreamgraphChart.svelte.d.ts.map +1 -0
  87. package/dist/StreamingMessage.svelte +44 -2
  88. package/dist/StreamingMessage.svelte.d.ts +18 -1
  89. package/dist/StreamingMessage.svelte.d.ts.map +1 -1
  90. package/dist/TileMapChart.svelte +314 -0
  91. package/dist/TileMapChart.svelte.d.ts +45 -0
  92. package/dist/TileMapChart.svelte.d.ts.map +1 -0
  93. package/dist/TimePicker.svelte +3 -0
  94. package/dist/TimelineChart.svelte +362 -0
  95. package/dist/TimelineChart.svelte.d.ts +22 -0
  96. package/dist/TimelineChart.svelte.d.ts.map +1 -0
  97. package/dist/TreegraphChart.svelte +281 -0
  98. package/dist/TreegraphChart.svelte.d.ts +19 -0
  99. package/dist/TreegraphChart.svelte.d.ts.map +1 -0
  100. package/dist/VariablePieChart.svelte +313 -0
  101. package/dist/VariablePieChart.svelte.d.ts +52 -0
  102. package/dist/VariablePieChart.svelte.d.ts.map +1 -0
  103. package/dist/VennChart.svelte +348 -0
  104. package/dist/VennChart.svelte.d.ts +72 -0
  105. package/dist/VennChart.svelte.d.ts.map +1 -0
  106. package/dist/WordCloudChart.svelte +279 -0
  107. package/dist/WordCloudChart.svelte.d.ts +18 -0
  108. package/dist/WordCloudChart.svelte.d.ts.map +1 -0
  109. package/dist/index.d.ts +56 -0
  110. package/dist/index.d.ts.map +1 -1
  111. package/dist/index.js +28 -0
  112. package/package.json +5 -3
@@ -0,0 +1,428 @@
1
+ <script lang="ts" module>
2
+ /**
3
+ * ErrorBarChart — pour chaque catégorie, un marqueur central au point `value`
4
+ * (la moyenne ou la mesure) et une moustache horizontale allant de `low` à
5
+ * `high` (les bornes d'incertitude), terminée à chaque extrémité par un court
6
+ * capuchon perpendiculaire (les « error bars »). Idéal pour visualiser une
7
+ * estimation et son intervalle de confiance par catégorie.
8
+ * API canonique (référence Svelte ; React/Vue s'alignent).
9
+ *
10
+ * Props obligatoires :
11
+ * data ErrorBarChartDatum[] - tableau {category, value, low, high}
12
+ * label string - aria-label du graphique
13
+ *
14
+ * Props optionnelles :
15
+ * tone "category1".."category8" (défaut "category1") - moustache + marqueur
16
+ * width number (défaut 480)
17
+ * height number (défaut 240)
18
+ * class string
19
+ *
20
+ * Les catégories sont distribuées sur l'axe vertical (une ligne par
21
+ * catégorie) ; l'axe horizontal porte l'échelle de valeurs graduée.
22
+ */
23
+ export type ErrorBarChartTone =
24
+ | "category1"
25
+ | "category2"
26
+ | "category3"
27
+ | "category4"
28
+ | "category5"
29
+ | "category6"
30
+ | "category7"
31
+ | "category8";
32
+
33
+ export type ErrorBarChartDatum = {
34
+ category: string;
35
+ value: number;
36
+ low: number;
37
+ high: number;
38
+ };
39
+ </script>
40
+
41
+ <script lang="ts">
42
+ import ChartDataList from "./ChartDataList.svelte";
43
+ import GraphLegend from "./GraphLegend.svelte";
44
+
45
+ type ErrorBarChartProps = {
46
+ data: ErrorBarChartDatum[];
47
+ width?: number;
48
+ height?: number;
49
+ tone?: ErrorBarChartTone;
50
+ label: string;
51
+ class?: string;
52
+ };
53
+
54
+ let {
55
+ data = [],
56
+ width = 480,
57
+ height = 240,
58
+ tone = "category1",
59
+ label,
60
+ class: className
61
+ }: ErrorBarChartProps = $props();
62
+
63
+ const MARGIN = { top: 16, right: 20, bottom: 32, left: 96 };
64
+ const MARKER_RADIUS = 4;
65
+ const CAP_HALF = 5; // demi-hauteur du capuchon perpendiculaire
66
+
67
+ function niceTicks(min: number, max: number, target = 5): number[] {
68
+ if (!Number.isFinite(min) || !Number.isFinite(max) || min === max) {
69
+ const base = Number.isFinite(max) ? max : 0;
70
+ return [base];
71
+ }
72
+ const range = max - min;
73
+ const rough = range / Math.max(target - 1, 1);
74
+ const pow = Math.pow(10, Math.floor(Math.log10(rough)));
75
+ const norm = rough / pow;
76
+ let step: number;
77
+ if (norm < 1.5) step = 1 * pow;
78
+ else if (norm < 3) step = 2 * pow;
79
+ else if (norm < 7) step = 5 * pow;
80
+ else step = 10 * pow;
81
+ const start = Math.floor(min / step) * step;
82
+ const end = Math.ceil(max / step) * step;
83
+ const ticks: number[] = [];
84
+ for (let v = start; v <= end + step / 2; v += step) {
85
+ ticks.push(Number(v.toFixed(10)));
86
+ }
87
+ return ticks;
88
+ }
89
+
90
+ function scaleLinear(v: number, d0: number, d1: number, r0: number, r1: number) {
91
+ if (d1 === d0) return r0;
92
+ return r0 + ((v - d0) * (r1 - r0)) / (d1 - d0);
93
+ }
94
+
95
+ function formatTick(v: number): string {
96
+ if (Math.abs(v) >= 1000) return `${(v / 1000).toFixed(v % 1000 === 0 ? 0 : 1)}k`;
97
+ if (Number.isInteger(v)) return String(v);
98
+ return v.toFixed(1);
99
+ }
100
+
101
+ // Normalise un point : value/low/high finis, ordonnés (lo <= value <= hi).
102
+ function normalize(d: ErrorBarChartDatum): { lo: number; mid: number; hi: number } | null {
103
+ if (!Number.isFinite(d.value) || !Number.isFinite(d.low) || !Number.isFinite(d.high)) return null;
104
+ const lo = Math.min(d.low, d.high);
105
+ const hi = Math.max(d.low, d.high);
106
+ const mid = Math.min(hi, Math.max(lo, d.value));
107
+ return { lo, mid, hi };
108
+ }
109
+
110
+ // Données valides : value + low + high finis.
111
+ const validData = $derived(data.filter((d) => normalize(d) !== null));
112
+
113
+ const dataValueItems = $derived(
114
+ validData.map((d) => {
115
+ const r = normalize(d)!;
116
+ return `${d.category}: ${r.mid} (${r.lo} – ${r.hi})`;
117
+ })
118
+ );
119
+
120
+ // Réduit la police des étiquettes de catégorie quand l'espace réservé (marge
121
+ // gauche) est plus petit que le défaut de référence, pour éviter le rognage
122
+ // (cf. fix lollipop : adapter la taille au conteneur).
123
+ const categoryFontSize = $derived.by(() => {
124
+ const ratio = Math.min(1, MARGIN.left / 96);
125
+ return Math.max(0.5, 0.6875 * ratio);
126
+ });
127
+
128
+ let hoveredIndex: number | null = $state(null);
129
+
130
+ const plotWidth = $derived(Math.max(width - MARGIN.left - MARGIN.right, 1));
131
+ const plotHeight = $derived(Math.max(height - MARGIN.top - MARGIN.bottom, 1));
132
+
133
+ const xTicks = $derived.by(() => {
134
+ if (validData.length === 0) return [0];
135
+ const lows = validData.map((d) => normalize(d)!.lo);
136
+ const highs = validData.map((d) => normalize(d)!.hi);
137
+ const minRaw = Math.min(...lows);
138
+ const maxRaw = Math.max(...highs);
139
+ const padded = (maxRaw - minRaw) * 0.08 || Math.max(Math.abs(maxRaw), 1) * 0.1;
140
+ return niceTicks(minRaw - padded, maxRaw + padded, 5);
141
+ });
142
+
143
+ const xDomain = $derived.by(() => {
144
+ if (xTicks.length === 0) return { min: 0, max: 1 };
145
+ return { min: xTicks[0], max: xTicks[xTicks.length - 1] };
146
+ });
147
+
148
+ const rows = $derived.by(() => {
149
+ if (validData.length === 0) return [];
150
+ const band = plotHeight / validData.length;
151
+ return validData.map((d, i) => {
152
+ const r = normalize(d)!;
153
+ const cy = MARGIN.top + band * (i + 0.5);
154
+ const xLow = MARGIN.left + scaleLinear(r.lo, xDomain.min, xDomain.max, 0, plotWidth);
155
+ const xMid = MARGIN.left + scaleLinear(r.mid, xDomain.min, xDomain.max, 0, plotWidth);
156
+ const xHigh = MARGIN.left + scaleLinear(r.hi, xDomain.min, xDomain.max, 0, plotWidth);
157
+ return {
158
+ datum: d,
159
+ range: r,
160
+ cy,
161
+ xLow,
162
+ xMid,
163
+ xHigh,
164
+ index: i
165
+ };
166
+ });
167
+ });
168
+
169
+ const gridLines = $derived(
170
+ xTicks.map((tick) => ({
171
+ value: tick,
172
+ x: MARGIN.left + scaleLinear(tick, xDomain.min, xDomain.max, 0, plotWidth)
173
+ }))
174
+ );
175
+
176
+ const legendEntries = $derived([{ label, shape: "circle" as const, tone }]);
177
+
178
+ function handleLeave() {
179
+ hoveredIndex = null;
180
+ }
181
+ function handleVisualPointerMove(event: PointerEvent) {
182
+ const target = event.target;
183
+ if (!(target instanceof Element)) {
184
+ hoveredIndex = null;
185
+ return;
186
+ }
187
+ const index = Number(target.getAttribute("data-chart-index"));
188
+ hoveredIndex = Number.isInteger(index) ? index : null;
189
+ }
190
+
191
+ const classes = () => ["st-errorBarChart", className].filter(Boolean).join(" ");
192
+ </script>
193
+
194
+ <div class={classes()}>
195
+ <div
196
+ class="st-errorBarChart__visual"
197
+ role="img"
198
+ aria-label={label}
199
+ onpointermove={handleVisualPointerMove}
200
+ onpointerleave={handleLeave}
201
+ >
202
+ <svg
203
+ viewBox="0 0 {width} {height}"
204
+ preserveAspectRatio="xMidYMid meet"
205
+ width="100%"
206
+ height="100%"
207
+ focusable="false"
208
+ aria-hidden="true"
209
+ >
210
+ <!-- gridlines + X axis ticks -->
211
+ {#each gridLines as g (g.value)}
212
+ <line
213
+ class="st-errorBarChart__grid"
214
+ x1={g.x}
215
+ x2={g.x}
216
+ y1={MARGIN.top}
217
+ y2={height - MARGIN.bottom}
218
+ />
219
+ <text
220
+ class="st-errorBarChart__tickLabel"
221
+ x={g.x}
222
+ y={height - MARGIN.bottom + 16}
223
+ text-anchor="middle"
224
+ >
225
+ {formatTick(g.value)}
226
+ </text>
227
+ {/each}
228
+
229
+ <!-- axes -->
230
+ <line
231
+ class="st-errorBarChart__axis"
232
+ x1={MARGIN.left}
233
+ x2={MARGIN.left}
234
+ y1={MARGIN.top}
235
+ y2={height - MARGIN.bottom}
236
+ />
237
+ <line
238
+ class="st-errorBarChart__axis"
239
+ x1={MARGIN.left}
240
+ x2={width - MARGIN.right}
241
+ y1={height - MARGIN.bottom}
242
+ y2={height - MARGIN.bottom}
243
+ />
244
+
245
+ <!-- category labels + error bars -->
246
+ {#each rows as row (row.index)}
247
+ <text
248
+ class="st-errorBarChart__categoryLabel"
249
+ x={MARGIN.left - 8}
250
+ y={row.cy}
251
+ text-anchor="end"
252
+ dominant-baseline="middle"
253
+ style="font-size: {categoryFontSize}rem"
254
+ >
255
+ {row.datum.category}
256
+ </text>
257
+ <line
258
+ class="st-errorBarChart__whisker st-errorBarChart__whisker--{tone}"
259
+ x1={row.xLow}
260
+ x2={row.xHigh}
261
+ y1={row.cy}
262
+ y2={row.cy}
263
+ />
264
+ <line
265
+ class="st-errorBarChart__cap st-errorBarChart__cap--low st-errorBarChart__cap--{tone}"
266
+ x1={row.xLow}
267
+ x2={row.xLow}
268
+ y1={row.cy - CAP_HALF}
269
+ y2={row.cy + CAP_HALF}
270
+ />
271
+ <line
272
+ class="st-errorBarChart__cap st-errorBarChart__cap--high st-errorBarChart__cap--{tone}"
273
+ x1={row.xHigh}
274
+ x2={row.xHigh}
275
+ y1={row.cy - CAP_HALF}
276
+ y2={row.cy + CAP_HALF}
277
+ />
278
+ <circle
279
+ class="st-errorBarChart__marker st-errorBarChart__marker--{tone}"
280
+ cx={row.xMid}
281
+ cy={row.cy}
282
+ r={MARKER_RADIUS}
283
+ data-chart-index={row.index}
284
+ />
285
+ {/each}
286
+ </svg>
287
+ <GraphLegend class="st-errorBarChart__legend" entries={legendEntries} />
288
+ </div>
289
+
290
+ <ChartDataList {label} items={dataValueItems} />
291
+
292
+ {#if hoveredIndex !== null && rows[hoveredIndex]}
293
+ {@const row = rows[hoveredIndex]}
294
+ <div
295
+ class="st-errorBarChart__tooltip"
296
+ role="presentation"
297
+ style="left: {(row.xMid / width) * 100}%; top: {(row.cy / height) * 100}%"
298
+ >
299
+ <span class="st-errorBarChart__tooltipLabel">{row.datum.category}</span>
300
+ <span class="st-errorBarChart__tooltipValue">{row.range.mid} ({row.range.lo} – {row.range.hi})</span>
301
+ </div>
302
+ {/if}
303
+ </div>
304
+
305
+ <style>
306
+ .st-errorBarChart {
307
+ color: var(--st-semantic-data-category1);
308
+ display: block;
309
+ font-family: inherit;
310
+ position: relative;
311
+ width: 100%;
312
+ }
313
+
314
+ .st-errorBarChart svg {
315
+ display: block;
316
+ overflow: visible;
317
+ }
318
+
319
+ .st-errorBarChart__visual {
320
+ display: block;
321
+ position: relative;
322
+ }
323
+
324
+ .st-errorBarChart__legend {
325
+ position: absolute;
326
+ right: 0.25rem;
327
+ top: 0.25rem;
328
+ }
329
+
330
+ .st-errorBarChart__grid {
331
+ stroke: var(--st-component-errorBarChart-gridStroke, var(--st-semantic-border-subtle));
332
+ stroke-dasharray: 2 3;
333
+ stroke-width: 1;
334
+ opacity: 0.7;
335
+ }
336
+
337
+ .st-errorBarChart__axis {
338
+ stroke: var(--st-component-errorBarChart-axisStroke, var(--st-semantic-border-subtle));
339
+ stroke-width: 1;
340
+ }
341
+
342
+ .st-errorBarChart__tickLabel,
343
+ .st-errorBarChart__categoryLabel {
344
+ fill: var(--st-component-errorBarChart-labelColor, var(--st-semantic-text-secondary));
345
+ font-size: 0.6875rem;
346
+ }
347
+
348
+ .st-errorBarChart__whisker {
349
+ stroke: currentColor;
350
+ stroke-width: 2;
351
+ stroke-linecap: round;
352
+ }
353
+
354
+ .st-errorBarChart__cap {
355
+ stroke: currentColor;
356
+ stroke-width: 2;
357
+ stroke-linecap: round;
358
+ }
359
+
360
+ .st-errorBarChart__whisker--category1,
361
+ .st-errorBarChart__cap--category1 { stroke: var(--st-semantic-data-category1); }
362
+ .st-errorBarChart__whisker--category2,
363
+ .st-errorBarChart__cap--category2 { stroke: var(--st-semantic-data-category2); }
364
+ .st-errorBarChart__whisker--category3,
365
+ .st-errorBarChart__cap--category3 { stroke: var(--st-semantic-data-category3); }
366
+ .st-errorBarChart__whisker--category4,
367
+ .st-errorBarChart__cap--category4 { stroke: var(--st-semantic-data-category4); }
368
+ .st-errorBarChart__whisker--category5,
369
+ .st-errorBarChart__cap--category5 { stroke: var(--st-semantic-data-category5); }
370
+ .st-errorBarChart__whisker--category6,
371
+ .st-errorBarChart__cap--category6 { stroke: var(--st-semantic-data-category6); }
372
+ .st-errorBarChart__whisker--category7,
373
+ .st-errorBarChart__cap--category7 { stroke: var(--st-semantic-data-category7); }
374
+ .st-errorBarChart__whisker--category8,
375
+ .st-errorBarChart__cap--category8 { stroke: var(--st-semantic-data-category8); }
376
+
377
+ .st-errorBarChart__marker {
378
+ fill: currentColor;
379
+ stroke: var(--st-semantic-surface-default);
380
+ stroke-width: 1.5;
381
+ cursor: pointer;
382
+ transition: r 120ms ease;
383
+ }
384
+
385
+ .st-errorBarChart__marker:hover {
386
+ r: 6;
387
+ }
388
+
389
+ .st-errorBarChart__marker--category1 { fill: var(--st-semantic-data-category1); }
390
+ .st-errorBarChart__marker--category2 { fill: var(--st-semantic-data-category2); }
391
+ .st-errorBarChart__marker--category3 { fill: var(--st-semantic-data-category3); }
392
+ .st-errorBarChart__marker--category4 { fill: var(--st-semantic-data-category4); }
393
+ .st-errorBarChart__marker--category5 { fill: var(--st-semantic-data-category5); }
394
+ .st-errorBarChart__marker--category6 { fill: var(--st-semantic-data-category6); }
395
+ .st-errorBarChart__marker--category7 { fill: var(--st-semantic-data-category7); }
396
+ .st-errorBarChart__marker--category8 { fill: var(--st-semantic-data-category8); }
397
+
398
+ @media (prefers-reduced-motion: reduce) {
399
+ .st-errorBarChart__marker {
400
+ transition: none;
401
+ }
402
+ }
403
+
404
+ .st-errorBarChart__tooltip {
405
+ background: var(--st-component-errorBarChart-tooltipBackground, var(--st-semantic-surface-inverse));
406
+ border-radius: var(--st-radius-sm, 0.25rem);
407
+ color: var(--st-component-errorBarChart-tooltipText, var(--st-semantic-text-inverse));
408
+ display: inline-flex;
409
+ flex-direction: column;
410
+ font-size: 0.75rem;
411
+ gap: 0.125rem;
412
+ line-height: 1.2;
413
+ padding: 0.375rem 0.5rem;
414
+ pointer-events: none;
415
+ position: absolute;
416
+ transform: translate(-50%, calc(-100% - 8px));
417
+ white-space: nowrap;
418
+ z-index: 1;
419
+ }
420
+
421
+ .st-errorBarChart__tooltipLabel {
422
+ font-weight: 600;
423
+ }
424
+
425
+ .st-errorBarChart__tooltipValue {
426
+ opacity: 0.85;
427
+ }
428
+ </style>
@@ -0,0 +1,40 @@
1
+ /**
2
+ * ErrorBarChart — pour chaque catégorie, un marqueur central au point `value`
3
+ * (la moyenne ou la mesure) et une moustache horizontale allant de `low` à
4
+ * `high` (les bornes d'incertitude), terminée à chaque extrémité par un court
5
+ * capuchon perpendiculaire (les « error bars »). Idéal pour visualiser une
6
+ * estimation et son intervalle de confiance par catégorie.
7
+ * API canonique (référence Svelte ; React/Vue s'alignent).
8
+ *
9
+ * Props obligatoires :
10
+ * data ErrorBarChartDatum[] - tableau {category, value, low, high}
11
+ * label string - aria-label du graphique
12
+ *
13
+ * Props optionnelles :
14
+ * tone "category1".."category8" (défaut "category1") - moustache + marqueur
15
+ * width number (défaut 480)
16
+ * height number (défaut 240)
17
+ * class string
18
+ *
19
+ * Les catégories sont distribuées sur l'axe vertical (une ligne par
20
+ * catégorie) ; l'axe horizontal porte l'échelle de valeurs graduée.
21
+ */
22
+ export type ErrorBarChartTone = "category1" | "category2" | "category3" | "category4" | "category5" | "category6" | "category7" | "category8";
23
+ export type ErrorBarChartDatum = {
24
+ category: string;
25
+ value: number;
26
+ low: number;
27
+ high: number;
28
+ };
29
+ type ErrorBarChartProps = {
30
+ data: ErrorBarChartDatum[];
31
+ width?: number;
32
+ height?: number;
33
+ tone?: ErrorBarChartTone;
34
+ label: string;
35
+ class?: string;
36
+ };
37
+ declare const ErrorBarChart: import("svelte").Component<ErrorBarChartProps, {}, "">;
38
+ type ErrorBarChart = ReturnType<typeof ErrorBarChart>;
39
+ export default ErrorBarChart;
40
+ //# sourceMappingURL=ErrorBarChart.svelte.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ErrorBarChart.svelte.d.ts","sourceRoot":"","sources":["../src/lib/ErrorBarChart.svelte.ts"],"names":[],"mappings":"AAGE;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,MAAM,MAAM,iBAAiB,GACzB,WAAW,GACX,WAAW,GACX,WAAW,GACX,WAAW,GACX,WAAW,GACX,WAAW,GACX,WAAW,GACX,WAAW,CAAC;AAEhB,MAAM,MAAM,kBAAkB,GAAG;IAC/B,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;CACd,CAAC;AAOF,KAAK,kBAAkB,GAAG;IACxB,IAAI,EAAE,kBAAkB,EAAE,CAAC;IAC3B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,iBAAiB,CAAC;IACzB,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,CAAC;AAgMJ,QAAA,MAAM,aAAa,wDAAwC,CAAC;AAC5D,KAAK,aAAa,GAAG,UAAU,CAAC,OAAO,aAAa,CAAC,CAAC;AACtD,eAAe,aAAa,CAAC"}
@@ -0,0 +1,220 @@
1
+ <script lang="ts" module>
2
+ import type { HTMLAttributes } from "svelte/elements";
3
+ import type { Snippet } from "svelte";
4
+
5
+ export type FieldCardVariant = "plain" | "bordered" | "accent";
6
+ export type FieldCardTone =
7
+ | "category1"
8
+ | "category2"
9
+ | "category3"
10
+ | "category4"
11
+ | "category5"
12
+ | "category6"
13
+ | "category7"
14
+ | "category8";
15
+
16
+ export type FieldCardProps = Omit<HTMLAttributes<HTMLElement>, "class"> & {
17
+ /** Titre de la carte / du groupe de champs. */
18
+ label: string;
19
+ /**
20
+ * Variante visuelle :
21
+ * - `plain` : cadre simple, titre discret.
22
+ * - `bordered` (défaut) : titre séparé par un filet sous l'en-tête.
23
+ * - `accent` : liseré catégoriel à gauche (conteneur à angles nets, jamais arrondi).
24
+ */
25
+ variant?: FieldCardVariant;
26
+ /** Couleur catégorielle pour la variante `accent`. */
27
+ tone?: FieldCardTone;
28
+ /** Nombre de commentaires ; affiche une pastille à côté du titre si > 0 ou si `onOpenComments`. */
29
+ commentCount?: number;
30
+ /** Ouvre le fil de commentaires ; rend la pastille interactive. */
31
+ onOpenComments?: () => void;
32
+ class?: string;
33
+ /** Corps de la carte. */
34
+ children?: Snippet;
35
+ };
36
+ </script>
37
+
38
+ <script lang="ts">
39
+ let {
40
+ label,
41
+ variant = "bordered",
42
+ tone,
43
+ commentCount = 0,
44
+ onOpenComments,
45
+ class: className,
46
+ children,
47
+ ...rest
48
+ }: FieldCardProps = $props();
49
+
50
+ const classes = $derived(
51
+ [
52
+ "st-fieldCard",
53
+ `st-fieldCard--${variant}`,
54
+ variant === "accent" && tone && `st-fieldCard--${tone}`,
55
+ className
56
+ ]
57
+ .filter(Boolean)
58
+ .join(" ")
59
+ );
60
+
61
+ const showBadge = $derived(commentCount > 0 || !!onOpenComments);
62
+ </script>
63
+
64
+ <section {...rest} class={classes}>
65
+ <header class="st-fieldCard__header">
66
+ <h3 class="st-fieldCard__label">{label}</h3>
67
+ {#if showBadge}
68
+ {#if onOpenComments}
69
+ <button
70
+ type="button"
71
+ class="st-fieldCard__comments"
72
+ aria-label={`Commentaires (${commentCount})`}
73
+ onclick={() => onOpenComments?.()}
74
+ >
75
+ <svg width="14" height="14" viewBox="0 0 16 16" aria-hidden="true" focusable="false">
76
+ <path
77
+ d="M2.5 4.25A1.25 1.25 0 0 1 3.75 3h8.5A1.25 1.25 0 0 1 13.5 4.25v5A1.25 1.25 0 0 1 12.25 10.5H6.5L3.5 13v-2.5h-.75A.25.25 0 0 1 2.5 10.25v-6Z"
78
+ fill="none"
79
+ stroke="currentColor"
80
+ stroke-width="1.25"
81
+ stroke-linecap="round"
82
+ stroke-linejoin="round"
83
+ />
84
+ </svg>
85
+ {#if commentCount > 0}
86
+ <span class="st-fieldCard__commentCount">{commentCount}</span>
87
+ {/if}
88
+ </button>
89
+ {:else}
90
+ <span class="st-fieldCard__comments st-fieldCard__comments--static">
91
+ <svg width="14" height="14" viewBox="0 0 16 16" aria-hidden="true" focusable="false">
92
+ <path
93
+ d="M2.5 4.25A1.25 1.25 0 0 1 3.75 3h8.5A1.25 1.25 0 0 1 13.5 4.25v5A1.25 1.25 0 0 1 12.25 10.5H6.5L3.5 13v-2.5h-.75A.25.25 0 0 1 2.5 10.25v-6Z"
94
+ fill="none"
95
+ stroke="currentColor"
96
+ stroke-width="1.25"
97
+ stroke-linecap="round"
98
+ stroke-linejoin="round"
99
+ />
100
+ </svg>
101
+ <span class="st-fieldCard__commentCount">{commentCount}</span>
102
+ </span>
103
+ {/if}
104
+ {/if}
105
+ </header>
106
+ <div class="st-fieldCard__body">
107
+ {@render children?.()}
108
+ </div>
109
+ </section>
110
+
111
+ <style>
112
+ .st-fieldCard {
113
+ background: var(--st-component-card-background, var(--st-semantic-surface-raised));
114
+ border-width: var(--st-component-card-anatomy-shape-borderWidth, 1px);
115
+ border-style: var(--st-component-card-anatomy-shape-borderStyle, solid);
116
+ border-color: var(--st-component-card-border, var(--st-semantic-border-subtle));
117
+ border-radius: var(--st-component-card-anatomy-shape-radius, 0.5rem);
118
+ color: var(--st-semantic-text-primary);
119
+ display: flex;
120
+ flex-direction: column;
121
+ height: 100%;
122
+ padding: var(--st-spacing-4, 1rem);
123
+ }
124
+
125
+ /* Variante accent : exergue par liseré de bord → conteneur à angles NETS
126
+ (anti-pattern proscrit : carte arrondie avec exergue par trait de bord). */
127
+ .st-fieldCard--accent {
128
+ border-inline-start-width: var(--st-spacing-1, 0.25rem);
129
+ border-radius: 0;
130
+ }
131
+
132
+ .st-fieldCard__header {
133
+ align-items: center;
134
+ display: flex;
135
+ gap: var(--st-spacing-2, 0.5rem);
136
+ justify-content: space-between;
137
+ }
138
+
139
+ .st-fieldCard--bordered .st-fieldCard__header {
140
+ border-bottom: 1px solid var(--st-semantic-border-subtle);
141
+ margin-bottom: var(--st-spacing-3, 0.75rem);
142
+ padding-bottom: var(--st-spacing-3, 0.75rem);
143
+ }
144
+
145
+ .st-fieldCard__label {
146
+ color: var(--st-semantic-text-primary);
147
+ font-size: 0.875rem;
148
+ font-weight: 600;
149
+ line-height: 1.3;
150
+ margin: 0;
151
+ }
152
+
153
+ .st-fieldCard--bordered .st-fieldCard__label {
154
+ font-size: 1rem;
155
+ }
156
+
157
+ .st-fieldCard__comments {
158
+ align-items: center;
159
+ background: transparent;
160
+ border: none;
161
+ border-radius: var(--st-radius-sm, 0.25rem);
162
+ color: var(--st-semantic-text-muted);
163
+ cursor: var(--st-cursor-interactive, pointer);
164
+ display: inline-flex;
165
+ flex: 0 0 auto;
166
+ font-size: 0.75rem;
167
+ gap: 0.1875rem;
168
+ line-height: 1;
169
+ padding: 0.125rem var(--st-spacing-1, 0.25rem);
170
+ }
171
+
172
+ .st-fieldCard__comments--static {
173
+ cursor: default;
174
+ }
175
+
176
+ .st-fieldCard__comments:hover:not(.st-fieldCard__comments--static) {
177
+ color: var(--st-semantic-text-primary);
178
+ }
179
+
180
+ .st-fieldCard__comments:focus-visible {
181
+ outline: 2px solid var(--st-semantic-border-interactive);
182
+ outline-offset: 2px;
183
+ }
184
+
185
+ .st-fieldCard__body {
186
+ color: var(--st-semantic-text-primary);
187
+ flex: 1 1 auto;
188
+ }
189
+
190
+ .st-fieldCard--plain .st-fieldCard__body,
191
+ .st-fieldCard--accent .st-fieldCard__body {
192
+ margin-top: var(--st-spacing-2, 0.5rem);
193
+ }
194
+
195
+ /* Liserés catégoriels — alignés sur la palette data des autres composants. */
196
+ .st-fieldCard--category1 {
197
+ border-inline-start-color: var(--st-semantic-data-category1);
198
+ }
199
+ .st-fieldCard--category2 {
200
+ border-inline-start-color: var(--st-semantic-data-category2);
201
+ }
202
+ .st-fieldCard--category3 {
203
+ border-inline-start-color: var(--st-semantic-data-category3);
204
+ }
205
+ .st-fieldCard--category4 {
206
+ border-inline-start-color: var(--st-semantic-data-category4);
207
+ }
208
+ .st-fieldCard--category5 {
209
+ border-inline-start-color: var(--st-semantic-data-category5);
210
+ }
211
+ .st-fieldCard--category6 {
212
+ border-inline-start-color: var(--st-semantic-data-category6);
213
+ }
214
+ .st-fieldCard--category7 {
215
+ border-inline-start-color: var(--st-semantic-data-category7);
216
+ }
217
+ .st-fieldCard--category8 {
218
+ border-inline-start-color: var(--st-semantic-data-category8);
219
+ }
220
+ </style>