@sentropic/design-system-svelte 0.34.34 → 0.34.36
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/dist/AnomalySwimLaneChart.svelte +388 -0
- package/dist/AnomalySwimLaneChart.svelte.d.ts +42 -0
- package/dist/AnomalySwimLaneChart.svelte.d.ts.map +1 -0
- package/dist/RibbonChart.svelte +439 -0
- package/dist/RibbonChart.svelte.d.ts +43 -0
- package/dist/RibbonChart.svelte.d.ts.map +1 -0
- package/dist/StatusHistoryChart.svelte +416 -0
- package/dist/StatusHistoryChart.svelte.d.ts +46 -0
- package/dist/StatusHistoryChart.svelte.d.ts.map +1 -0
- package/dist/WaffleChart.svelte +258 -0
- package/dist/WaffleChart.svelte.d.ts +37 -0
- package/dist/WaffleChart.svelte.d.ts.map +1 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -0
- package/package.json +1 -1
|
@@ -0,0 +1,416 @@
|
|
|
1
|
+
<script lang="ts" module>
|
|
2
|
+
/**
|
|
3
|
+
* StatusHistoryChart - grille TEMPS × ENTITÉ dont chaque cellule encode un
|
|
4
|
+
* STATUT DISCRET (façon Grafana « status history »). Une ligne (series) =
|
|
5
|
+
* une séquence de buckets temporels ; chaque bucket est une cellule colorée
|
|
6
|
+
* par son statut. Distinct de HeatmapChart (dégradé continu Low→High) : la
|
|
7
|
+
* coloration suit un statut discret, comme StateTimelineChart encode l'état,
|
|
8
|
+
* mais en GRILLE de buckets au lieu de segments contigus.
|
|
9
|
+
* API canonique (référence Svelte, React/Vue doivent s'aligner).
|
|
10
|
+
*
|
|
11
|
+
* Modèle : lignes = series, colonnes = buckets temporels (ordre d'apparition
|
|
12
|
+
* des `at`). La couleur suit `tone` si fourni, sinon dérive une teinte stable
|
|
13
|
+
* par `value` (cycle sur category1..8). Étiquette de series à gauche
|
|
14
|
+
* (ellipsis). Légende des statuts sous le graphe via ChartDataList.
|
|
15
|
+
*
|
|
16
|
+
* Props obligatoires :
|
|
17
|
+
* data StatusHistorySeries[] - tableau {series, buckets[]}
|
|
18
|
+
*
|
|
19
|
+
* Props optionnelles :
|
|
20
|
+
* label string
|
|
21
|
+
* width number (défaut 640)
|
|
22
|
+
* height number (défaut 320)
|
|
23
|
+
* size number (alias de width)
|
|
24
|
+
* class string
|
|
25
|
+
*/
|
|
26
|
+
export type StatusHistoryTone =
|
|
27
|
+
| "neutral" | "info" | "success" | "warning" | "error"
|
|
28
|
+
| "category1" | "category2" | "category3" | "category4"
|
|
29
|
+
| "category5" | "category6" | "category7" | "category8";
|
|
30
|
+
|
|
31
|
+
export type StatusHistoryBucket = {
|
|
32
|
+
at: number;
|
|
33
|
+
value: string | number;
|
|
34
|
+
tone?: StatusHistoryTone;
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
export type StatusHistorySeries = {
|
|
38
|
+
series: string;
|
|
39
|
+
buckets: StatusHistoryBucket[];
|
|
40
|
+
};
|
|
41
|
+
</script>
|
|
42
|
+
|
|
43
|
+
<script lang="ts">
|
|
44
|
+
import ChartDataList from "./ChartDataList.svelte";
|
|
45
|
+
|
|
46
|
+
type StatusHistoryChartProps = {
|
|
47
|
+
data: StatusHistorySeries[];
|
|
48
|
+
label?: string;
|
|
49
|
+
width?: number;
|
|
50
|
+
height?: number;
|
|
51
|
+
size?: number;
|
|
52
|
+
class?: string;
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
let {
|
|
56
|
+
data = [],
|
|
57
|
+
label,
|
|
58
|
+
width,
|
|
59
|
+
height = 320,
|
|
60
|
+
size,
|
|
61
|
+
class: className
|
|
62
|
+
}: StatusHistoryChartProps = $props();
|
|
63
|
+
|
|
64
|
+
const resolvedWidth = $derived(width ?? size ?? 640);
|
|
65
|
+
|
|
66
|
+
const MARGIN = { top: 16, right: 16, bottom: 32, left: 132 };
|
|
67
|
+
|
|
68
|
+
// Tronque une étiquette à la largeur de la marge gauche (approx. par char).
|
|
69
|
+
function ellipsize(text: string, maxChars: number): string {
|
|
70
|
+
if (text.length <= maxChars) return text;
|
|
71
|
+
if (maxChars <= 1) return "…";
|
|
72
|
+
return `${text.slice(0, maxChars - 1)}…`;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
function formatTick(v: number): string {
|
|
76
|
+
if (Math.abs(v) >= 1000) return `${(v / 1000).toFixed(v % 1000 === 0 ? 0 : 1)}k`;
|
|
77
|
+
if (Number.isInteger(v)) return String(v);
|
|
78
|
+
return v.toFixed(1);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
let hoveredKey: string | null = $state(null);
|
|
82
|
+
|
|
83
|
+
const plotWidth = $derived(Math.max(resolvedWidth - MARGIN.left - MARGIN.right, 1));
|
|
84
|
+
const plotHeight = $derived(Math.max(height - MARGIN.top - MARGIN.bottom, 1));
|
|
85
|
+
|
|
86
|
+
// Normalise : filtre les series sans libellé et les buckets non finis.
|
|
87
|
+
const validData = $derived(
|
|
88
|
+
data
|
|
89
|
+
.filter((d) => typeof d.series === "string" && d.series.length > 0)
|
|
90
|
+
.map((d) => ({
|
|
91
|
+
series: d.series,
|
|
92
|
+
buckets: (d.buckets ?? [])
|
|
93
|
+
.filter((b) => Number.isFinite(b.at))
|
|
94
|
+
.map((b) => ({ at: b.at, value: b.value, tone: b.tone }))
|
|
95
|
+
}))
|
|
96
|
+
);
|
|
97
|
+
|
|
98
|
+
// Colonnes temporelles distinctes (par `at`, croissant).
|
|
99
|
+
const columnOrder = $derived.by(() => {
|
|
100
|
+
const seen: number[] = [];
|
|
101
|
+
for (const d of validData) {
|
|
102
|
+
for (const b of d.buckets) {
|
|
103
|
+
if (!seen.includes(b.at)) seen.push(b.at);
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
return seen.sort((a, b) => a - b);
|
|
107
|
+
});
|
|
108
|
+
|
|
109
|
+
// Statuts distincts (ordre d'apparition) → index categoryN (1..8, cyclé) si
|
|
110
|
+
// aucun `tone` explicite. Un `tone` sur un bucket l'emporte sur la dérivation.
|
|
111
|
+
const statusOrder = $derived.by(() => {
|
|
112
|
+
const seen: string[] = [];
|
|
113
|
+
for (const d of validData) {
|
|
114
|
+
for (const b of d.buckets) {
|
|
115
|
+
const key = String(b.value);
|
|
116
|
+
if (!seen.includes(key)) seen.push(key);
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
return seen;
|
|
120
|
+
});
|
|
121
|
+
const explicitToneByStatus = $derived.by(() => {
|
|
122
|
+
const map = new Map<string, StatusHistoryTone>();
|
|
123
|
+
for (const d of validData) {
|
|
124
|
+
for (const b of d.buckets) {
|
|
125
|
+
if (b.tone) map.set(String(b.value), b.tone);
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
return map;
|
|
129
|
+
});
|
|
130
|
+
const toneOf = (bucket: { value: string | number; tone?: StatusHistoryTone }): StatusHistoryTone => {
|
|
131
|
+
if (bucket.tone) return bucket.tone;
|
|
132
|
+
const key = String(bucket.value);
|
|
133
|
+
const explicit = explicitToneByStatus.get(key);
|
|
134
|
+
if (explicit) return explicit;
|
|
135
|
+
const idx = statusOrder.indexOf(key);
|
|
136
|
+
return `category${((idx < 0 ? 0 : idx) % 8) + 1}` as StatusHistoryTone;
|
|
137
|
+
};
|
|
138
|
+
const legendItems = $derived(
|
|
139
|
+
statusOrder.map((value) => ({ value, tone: toneOf({ value }) }))
|
|
140
|
+
);
|
|
141
|
+
const hasLegend = $derived(statusOrder.length > 0);
|
|
142
|
+
|
|
143
|
+
const rows = $derived.by(() => {
|
|
144
|
+
if (validData.length === 0 || columnOrder.length === 0) return [];
|
|
145
|
+
const band = plotHeight / validData.length;
|
|
146
|
+
const rowHeight = Math.min(band * 0.62, 28);
|
|
147
|
+
const colWidth = plotWidth / columnOrder.length;
|
|
148
|
+
return validData.map((d, i) => {
|
|
149
|
+
const y = MARGIN.top + band * i + (band - rowHeight) / 2;
|
|
150
|
+
const cells = d.buckets.map((b, j) => {
|
|
151
|
+
const colIndex = Math.max(0, columnOrder.indexOf(b.at));
|
|
152
|
+
const x = MARGIN.left + colIndex * colWidth;
|
|
153
|
+
const w = Math.max(colWidth - 2, 1);
|
|
154
|
+
return {
|
|
155
|
+
key: `${i}-${j}`,
|
|
156
|
+
datum: b,
|
|
157
|
+
x,
|
|
158
|
+
width: w,
|
|
159
|
+
cx: x + w / 2,
|
|
160
|
+
tone: toneOf(b)
|
|
161
|
+
};
|
|
162
|
+
});
|
|
163
|
+
return {
|
|
164
|
+
datum: d,
|
|
165
|
+
index: i,
|
|
166
|
+
y,
|
|
167
|
+
height: rowHeight,
|
|
168
|
+
rowCenterY: MARGIN.top + band * (i + 0.5),
|
|
169
|
+
cells
|
|
170
|
+
};
|
|
171
|
+
});
|
|
172
|
+
});
|
|
173
|
+
|
|
174
|
+
const columns = $derived.by(() => {
|
|
175
|
+
if (columnOrder.length === 0) return [];
|
|
176
|
+
const colWidth = plotWidth / columnOrder.length;
|
|
177
|
+
return columnOrder.map((at, index) => ({
|
|
178
|
+
at,
|
|
179
|
+
cx: MARGIN.left + (index + 0.5) * colWidth
|
|
180
|
+
}));
|
|
181
|
+
});
|
|
182
|
+
|
|
183
|
+
const dataValueItems = $derived(
|
|
184
|
+
validData.map(
|
|
185
|
+
(d) => `${d.series}: ${d.buckets.map((b) => `${b.at} = ${b.value}`).join(", ")}`
|
|
186
|
+
)
|
|
187
|
+
);
|
|
188
|
+
|
|
189
|
+
function handlePointerMove(event: PointerEvent) {
|
|
190
|
+
const target = event.target;
|
|
191
|
+
if (!(target instanceof Element)) {
|
|
192
|
+
hoveredKey = null;
|
|
193
|
+
return;
|
|
194
|
+
}
|
|
195
|
+
const key = target.getAttribute("data-chart-key");
|
|
196
|
+
hoveredKey = key ?? null;
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
const hoveredCell = $derived.by(() => {
|
|
200
|
+
if (hoveredKey === null) return null;
|
|
201
|
+
for (const row of rows) {
|
|
202
|
+
for (const cell of row.cells) {
|
|
203
|
+
if (cell.key === hoveredKey) return { row, cell };
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
return null;
|
|
207
|
+
});
|
|
208
|
+
|
|
209
|
+
const classes = () => ["st-statusHistoryChart", className].filter(Boolean).join(" ");
|
|
210
|
+
</script>
|
|
211
|
+
|
|
212
|
+
<div class={classes()}>
|
|
213
|
+
<div
|
|
214
|
+
class="st-statusHistoryChart__visual"
|
|
215
|
+
role="img"
|
|
216
|
+
aria-label={label}
|
|
217
|
+
onpointermove={handlePointerMove}
|
|
218
|
+
onpointerleave={() => (hoveredKey = null)}
|
|
219
|
+
>
|
|
220
|
+
<svg
|
|
221
|
+
viewBox="0 0 {resolvedWidth} {height}"
|
|
222
|
+
preserveAspectRatio="xMidYMid meet"
|
|
223
|
+
width="100%"
|
|
224
|
+
height="100%"
|
|
225
|
+
focusable="false"
|
|
226
|
+
aria-hidden="true"
|
|
227
|
+
>
|
|
228
|
+
<!-- tick labels (axe X temporel) -->
|
|
229
|
+
{#each columns as column (column.at)}
|
|
230
|
+
<text class="st-statusHistoryChart__tickLabel" x={column.cx} y={height - MARGIN.bottom + 16} text-anchor="middle">
|
|
231
|
+
{formatTick(column.at)}
|
|
232
|
+
</text>
|
|
233
|
+
{/each}
|
|
234
|
+
|
|
235
|
+
<!-- axes -->
|
|
236
|
+
<line class="st-statusHistoryChart__axis" x1={MARGIN.left} x2={MARGIN.left} y1={MARGIN.top} y2={height - MARGIN.bottom} />
|
|
237
|
+
<line class="st-statusHistoryChart__axis" x1={MARGIN.left} x2={resolvedWidth - MARGIN.right} y1={height - MARGIN.bottom} y2={height - MARGIN.bottom} />
|
|
238
|
+
|
|
239
|
+
<!-- une ligne par series : étiquette à gauche + cellules de statut par bucket -->
|
|
240
|
+
{#each rows as row (`${row.index}-${row.datum.series}`)}
|
|
241
|
+
<text
|
|
242
|
+
class="st-statusHistoryChart__seriesLabel"
|
|
243
|
+
x={MARGIN.left - 8}
|
|
244
|
+
y={row.rowCenterY}
|
|
245
|
+
text-anchor="end"
|
|
246
|
+
dominant-baseline="middle"
|
|
247
|
+
>
|
|
248
|
+
{ellipsize(row.datum.series, 18)}
|
|
249
|
+
</text>
|
|
250
|
+
{#each row.cells as cell (cell.key)}
|
|
251
|
+
<rect
|
|
252
|
+
class="st-statusHistoryChart__cell st-statusHistoryChart__cell--{cell.tone}"
|
|
253
|
+
class:st-statusHistoryChart__cell--dim={hoveredKey !== null && hoveredKey !== cell.key}
|
|
254
|
+
x={cell.x}
|
|
255
|
+
y={row.y}
|
|
256
|
+
width={cell.width}
|
|
257
|
+
height={row.height}
|
|
258
|
+
rx="2"
|
|
259
|
+
data-chart-key={cell.key}
|
|
260
|
+
/>
|
|
261
|
+
{/each}
|
|
262
|
+
{/each}
|
|
263
|
+
</svg>
|
|
264
|
+
</div>
|
|
265
|
+
|
|
266
|
+
{#if hasLegend}
|
|
267
|
+
<ul class="st-statusHistoryChart__legend" aria-label={`Statuts de ${label ?? "status history"}`}>
|
|
268
|
+
{#each legendItems as item (item.value)}
|
|
269
|
+
<li class="st-statusHistoryChart__legendItem">
|
|
270
|
+
<span class="st-statusHistoryChart__legendSwatch st-statusHistoryChart__legendSwatch--{item.tone}" aria-hidden="true"></span>
|
|
271
|
+
{item.value}
|
|
272
|
+
</li>
|
|
273
|
+
{/each}
|
|
274
|
+
</ul>
|
|
275
|
+
{/if}
|
|
276
|
+
|
|
277
|
+
<ChartDataList label={label ?? "status history"} items={dataValueItems} />
|
|
278
|
+
|
|
279
|
+
{#if hoveredCell}
|
|
280
|
+
{@const cell = hoveredCell.cell}
|
|
281
|
+
{@const row = hoveredCell.row}
|
|
282
|
+
<div
|
|
283
|
+
class="st-statusHistoryChart__tooltip"
|
|
284
|
+
role="presentation"
|
|
285
|
+
style="left: {(cell.cx / resolvedWidth) * 100}%; top: {(row.rowCenterY / height) * 100}%"
|
|
286
|
+
>
|
|
287
|
+
<span class="st-statusHistoryChart__tooltipLabel">{row.datum.series} · {cell.datum.at}</span>
|
|
288
|
+
<span class="st-statusHistoryChart__tooltipValue">{cell.datum.value}</span>
|
|
289
|
+
</div>
|
|
290
|
+
{/if}
|
|
291
|
+
</div>
|
|
292
|
+
|
|
293
|
+
<style>
|
|
294
|
+
.st-statusHistoryChart {
|
|
295
|
+
color: var(--st-semantic-text-secondary);
|
|
296
|
+
display: block;
|
|
297
|
+
font-family: inherit;
|
|
298
|
+
position: relative;
|
|
299
|
+
width: 100%;
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
.st-statusHistoryChart svg {
|
|
303
|
+
display: block;
|
|
304
|
+
overflow: visible;
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
.st-statusHistoryChart__visual {
|
|
308
|
+
display: block;
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
.st-statusHistoryChart__axis {
|
|
312
|
+
stroke: var(--st-semantic-border-subtle);
|
|
313
|
+
stroke-width: 1;
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
.st-statusHistoryChart__tickLabel,
|
|
317
|
+
.st-statusHistoryChart__seriesLabel {
|
|
318
|
+
fill: var(--st-semantic-text-secondary);
|
|
319
|
+
font-size: 0.6875rem;
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
.st-statusHistoryChart__cell {
|
|
323
|
+
cursor: pointer;
|
|
324
|
+
stroke: var(--st-semantic-surface-default, Canvas);
|
|
325
|
+
stroke-width: 1;
|
|
326
|
+
transition: opacity 120ms ease;
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
.st-statusHistoryChart__cell--dim {
|
|
330
|
+
opacity: 0.4;
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
.st-statusHistoryChart__cell--neutral { fill: var(--st-semantic-border-strong, var(--st-semantic-surface-subtle)); }
|
|
334
|
+
.st-statusHistoryChart__cell--info { fill: var(--st-semantic-feedback-info, var(--st-semantic-action-primary)); }
|
|
335
|
+
.st-statusHistoryChart__cell--success { fill: var(--st-semantic-feedback-success); }
|
|
336
|
+
.st-statusHistoryChart__cell--warning { fill: var(--st-semantic-feedback-warning); }
|
|
337
|
+
.st-statusHistoryChart__cell--error { fill: var(--st-semantic-feedback-error); }
|
|
338
|
+
|
|
339
|
+
.st-statusHistoryChart__cell--category1 { fill: var(--st-semantic-data-category1); }
|
|
340
|
+
.st-statusHistoryChart__cell--category2 { fill: var(--st-semantic-data-category2); }
|
|
341
|
+
.st-statusHistoryChart__cell--category3 { fill: var(--st-semantic-data-category3); }
|
|
342
|
+
.st-statusHistoryChart__cell--category4 { fill: var(--st-semantic-data-category4); }
|
|
343
|
+
.st-statusHistoryChart__cell--category5 { fill: var(--st-semantic-data-category5); }
|
|
344
|
+
.st-statusHistoryChart__cell--category6 { fill: var(--st-semantic-data-category6); }
|
|
345
|
+
.st-statusHistoryChart__cell--category7 { fill: var(--st-semantic-data-category7); }
|
|
346
|
+
.st-statusHistoryChart__cell--category8 { fill: var(--st-semantic-data-category8); }
|
|
347
|
+
|
|
348
|
+
.st-statusHistoryChart__legend {
|
|
349
|
+
display: flex;
|
|
350
|
+
flex-wrap: wrap;
|
|
351
|
+
gap: var(--st-spacing-3, 0.75rem);
|
|
352
|
+
list-style: none;
|
|
353
|
+
margin: var(--st-spacing-2, 0.5rem) 0 0 0;
|
|
354
|
+
padding: 0;
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
.st-statusHistoryChart__legendItem {
|
|
358
|
+
align-items: center;
|
|
359
|
+
color: var(--st-semantic-text-secondary);
|
|
360
|
+
display: inline-flex;
|
|
361
|
+
font-size: 0.75rem;
|
|
362
|
+
gap: var(--st-spacing-1, 0.25rem);
|
|
363
|
+
line-height: 1;
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
.st-statusHistoryChart__legendSwatch {
|
|
367
|
+
border-radius: var(--st-radius-sm, 0.25rem);
|
|
368
|
+
display: inline-block;
|
|
369
|
+
height: 0.625rem;
|
|
370
|
+
width: 0.625rem;
|
|
371
|
+
}
|
|
372
|
+
.st-statusHistoryChart__legendSwatch--neutral { background: var(--st-semantic-border-strong, var(--st-semantic-surface-subtle)); }
|
|
373
|
+
.st-statusHistoryChart__legendSwatch--info { background: var(--st-semantic-feedback-info, var(--st-semantic-action-primary)); }
|
|
374
|
+
.st-statusHistoryChart__legendSwatch--success { background: var(--st-semantic-feedback-success); }
|
|
375
|
+
.st-statusHistoryChart__legendSwatch--warning { background: var(--st-semantic-feedback-warning); }
|
|
376
|
+
.st-statusHistoryChart__legendSwatch--error { background: var(--st-semantic-feedback-error); }
|
|
377
|
+
.st-statusHistoryChart__legendSwatch--category1 { background: var(--st-semantic-data-category1); }
|
|
378
|
+
.st-statusHistoryChart__legendSwatch--category2 { background: var(--st-semantic-data-category2); }
|
|
379
|
+
.st-statusHistoryChart__legendSwatch--category3 { background: var(--st-semantic-data-category3); }
|
|
380
|
+
.st-statusHistoryChart__legendSwatch--category4 { background: var(--st-semantic-data-category4); }
|
|
381
|
+
.st-statusHistoryChart__legendSwatch--category5 { background: var(--st-semantic-data-category5); }
|
|
382
|
+
.st-statusHistoryChart__legendSwatch--category6 { background: var(--st-semantic-data-category6); }
|
|
383
|
+
.st-statusHistoryChart__legendSwatch--category7 { background: var(--st-semantic-data-category7); }
|
|
384
|
+
.st-statusHistoryChart__legendSwatch--category8 { background: var(--st-semantic-data-category8); }
|
|
385
|
+
|
|
386
|
+
.st-statusHistoryChart__tooltip {
|
|
387
|
+
background: var(--st-semantic-surface-inverse);
|
|
388
|
+
border-radius: var(--st-radius-sm, 0.25rem);
|
|
389
|
+
color: var(--st-semantic-text-inverse);
|
|
390
|
+
display: inline-flex;
|
|
391
|
+
flex-direction: column;
|
|
392
|
+
font-size: 0.75rem;
|
|
393
|
+
gap: 0.125rem;
|
|
394
|
+
line-height: 1.2;
|
|
395
|
+
padding: 0.375rem 0.5rem;
|
|
396
|
+
pointer-events: none;
|
|
397
|
+
position: absolute;
|
|
398
|
+
transform: translate(-50%, calc(-100% - 8px));
|
|
399
|
+
white-space: nowrap;
|
|
400
|
+
z-index: 1;
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
.st-statusHistoryChart__tooltipLabel {
|
|
404
|
+
font-weight: 600;
|
|
405
|
+
}
|
|
406
|
+
|
|
407
|
+
.st-statusHistoryChart__tooltipValue {
|
|
408
|
+
opacity: 0.85;
|
|
409
|
+
}
|
|
410
|
+
|
|
411
|
+
@media (prefers-reduced-motion: reduce) {
|
|
412
|
+
.st-statusHistoryChart__cell {
|
|
413
|
+
transition: none;
|
|
414
|
+
}
|
|
415
|
+
}
|
|
416
|
+
</style>
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* StatusHistoryChart - grille TEMPS × ENTITÉ dont chaque cellule encode un
|
|
3
|
+
* STATUT DISCRET (façon Grafana « status history »). Une ligne (series) =
|
|
4
|
+
* une séquence de buckets temporels ; chaque bucket est une cellule colorée
|
|
5
|
+
* par son statut. Distinct de HeatmapChart (dégradé continu Low→High) : la
|
|
6
|
+
* coloration suit un statut discret, comme StateTimelineChart encode l'état,
|
|
7
|
+
* mais en GRILLE de buckets au lieu de segments contigus.
|
|
8
|
+
* API canonique (référence Svelte, React/Vue doivent s'aligner).
|
|
9
|
+
*
|
|
10
|
+
* Modèle : lignes = series, colonnes = buckets temporels (ordre d'apparition
|
|
11
|
+
* des `at`). La couleur suit `tone` si fourni, sinon dérive une teinte stable
|
|
12
|
+
* par `value` (cycle sur category1..8). Étiquette de series à gauche
|
|
13
|
+
* (ellipsis). Légende des statuts sous le graphe via ChartDataList.
|
|
14
|
+
*
|
|
15
|
+
* Props obligatoires :
|
|
16
|
+
* data StatusHistorySeries[] - tableau {series, buckets[]}
|
|
17
|
+
*
|
|
18
|
+
* Props optionnelles :
|
|
19
|
+
* label string
|
|
20
|
+
* width number (défaut 640)
|
|
21
|
+
* height number (défaut 320)
|
|
22
|
+
* size number (alias de width)
|
|
23
|
+
* class string
|
|
24
|
+
*/
|
|
25
|
+
export type StatusHistoryTone = "neutral" | "info" | "success" | "warning" | "error" | "category1" | "category2" | "category3" | "category4" | "category5" | "category6" | "category7" | "category8";
|
|
26
|
+
export type StatusHistoryBucket = {
|
|
27
|
+
at: number;
|
|
28
|
+
value: string | number;
|
|
29
|
+
tone?: StatusHistoryTone;
|
|
30
|
+
};
|
|
31
|
+
export type StatusHistorySeries = {
|
|
32
|
+
series: string;
|
|
33
|
+
buckets: StatusHistoryBucket[];
|
|
34
|
+
};
|
|
35
|
+
type StatusHistoryChartProps = {
|
|
36
|
+
data: StatusHistorySeries[];
|
|
37
|
+
label?: string;
|
|
38
|
+
width?: number;
|
|
39
|
+
height?: number;
|
|
40
|
+
size?: number;
|
|
41
|
+
class?: string;
|
|
42
|
+
};
|
|
43
|
+
declare const StatusHistoryChart: import("svelte").Component<StatusHistoryChartProps, {}, "">;
|
|
44
|
+
type StatusHistoryChart = ReturnType<typeof StatusHistoryChart>;
|
|
45
|
+
export default StatusHistoryChart;
|
|
46
|
+
//# sourceMappingURL=StatusHistoryChart.svelte.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"StatusHistoryChart.svelte.d.ts","sourceRoot":"","sources":["../src/lib/StatusHistoryChart.svelte.ts"],"names":[],"mappings":"AAGE;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,MAAM,MAAM,iBAAiB,GACzB,SAAS,GAAG,MAAM,GAAG,SAAS,GAAG,SAAS,GAAG,OAAO,GACpD,WAAW,GAAG,WAAW,GAAG,WAAW,GAAG,WAAW,GACrD,WAAW,GAAG,WAAW,GAAG,WAAW,GAAG,WAAW,CAAC;AAE1D,MAAM,MAAM,mBAAmB,GAAG;IAChC,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,GAAG,MAAM,CAAC;IACvB,IAAI,CAAC,EAAE,iBAAiB,CAAC;CAC1B,CAAC;AAEF,MAAM,MAAM,mBAAmB,GAAG;IAChC,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,mBAAmB,EAAE,CAAC;CAChC,CAAC;AAMF,KAAK,uBAAuB,GAAG;IAC7B,IAAI,EAAE,mBAAmB,EAAE,CAAC;IAC5B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,CAAC;AAyNJ,QAAA,MAAM,kBAAkB,6DAAwC,CAAC;AACjE,KAAK,kBAAkB,GAAG,UAAU,CAAC,OAAO,kBAAkB,CAAC,CAAC;AAChE,eAAe,kBAAkB,CAAC"}
|