@sentropic/design-system-svelte 0.34.28 → 0.34.32
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/CandlestickChart.svelte +286 -11
- package/dist/CandlestickChart.svelte.d.ts +17 -3
- package/dist/CandlestickChart.svelte.d.ts.map +1 -1
- package/dist/CellDecorationIcon.svelte +39 -0
- package/dist/CellDecorationIcon.svelte.d.ts +7 -0
- package/dist/CellDecorationIcon.svelte.d.ts.map +1 -0
- package/dist/ComboChart.svelte +333 -2
- package/dist/ComboChart.svelte.d.ts +34 -0
- package/dist/ComboChart.svelte.d.ts.map +1 -1
- package/dist/DataTable.svelte +91 -2
- package/dist/DataTable.svelte.d.ts +12 -0
- package/dist/DataTable.svelte.d.ts.map +1 -1
- package/dist/KpiCard.svelte +66 -1
- package/dist/KpiCard.svelte.d.ts +7 -0
- package/dist/KpiCard.svelte.d.ts.map +1 -1
- package/dist/OHLCChart.svelte +286 -11
- package/dist/OHLCChart.svelte.d.ts +17 -3
- package/dist/OHLCChart.svelte.d.ts.map +1 -1
- package/dist/ScatterPlot.svelte +260 -6
- package/dist/ScatterPlot.svelte.d.ts +25 -0
- package/dist/ScatterPlot.svelte.d.ts.map +1 -1
- package/dist/cellDecoration.d.ts +36 -0
- package/dist/cellDecoration.d.ts.map +1 -0
- package/dist/cellDecoration.js +71 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/package.json +1 -1
|
@@ -8,9 +8,15 @@
|
|
|
8
8
|
* label string
|
|
9
9
|
*
|
|
10
10
|
* Props optionnelles :
|
|
11
|
-
* width
|
|
12
|
-
* height
|
|
13
|
-
*
|
|
11
|
+
* width number (défaut 480)
|
|
12
|
+
* height number (défaut 240)
|
|
13
|
+
* annotations ChartAnnotation[] - overlay support/résistance/zones/events
|
|
14
|
+
* dataLabels boolean | { format?, position? } - étiquette close par bougie
|
|
15
|
+
* hoverKey string | null - crosshair contrôlé (clé = date/catégorie)
|
|
16
|
+
* onHoverKeyChange (key) => void - émet la date survolée (ou null)
|
|
17
|
+
* keyboardNav boolean - navigation clavier (roving tabindex)
|
|
18
|
+
* onSelectKey (key) => void - sélection clavier (Enter/Space) ; null = Escape
|
|
19
|
+
* class string
|
|
14
20
|
*/
|
|
15
21
|
export type CandlestickChartDatum = {
|
|
16
22
|
label: string;
|
|
@@ -23,12 +29,27 @@
|
|
|
23
29
|
|
|
24
30
|
<script lang="ts">
|
|
25
31
|
import ChartDataList from "./ChartDataList.svelte";
|
|
32
|
+
import {
|
|
33
|
+
resolveAnnotations,
|
|
34
|
+
annotationDataListItems,
|
|
35
|
+
polygonPoints,
|
|
36
|
+
type ChartAnnotation
|
|
37
|
+
} from "./chartAnnotations.js";
|
|
38
|
+
import { formatDataLabel, normalizeDataLabels, type DataLabelsProp } from "./chartDataLabels.js";
|
|
39
|
+
import { resolveActiveIndex } from "./chartCrosshair.js";
|
|
40
|
+
import { datapointAriaLabel, datapointNavAction, rovingTabIndex } from "./chartKeyboardNav.js";
|
|
26
41
|
|
|
27
42
|
type CandlestickChartProps = {
|
|
28
43
|
data: CandlestickChartDatum[];
|
|
29
44
|
label: string;
|
|
30
45
|
width?: number;
|
|
31
46
|
height?: number;
|
|
47
|
+
annotations?: ChartAnnotation[];
|
|
48
|
+
dataLabels?: DataLabelsProp;
|
|
49
|
+
hoverKey?: string | null;
|
|
50
|
+
onHoverKeyChange?: (key: string | null) => void;
|
|
51
|
+
keyboardNav?: boolean;
|
|
52
|
+
onSelectKey?: (key: string | null) => void;
|
|
32
53
|
class?: string;
|
|
33
54
|
};
|
|
34
55
|
|
|
@@ -37,6 +58,12 @@
|
|
|
37
58
|
label,
|
|
38
59
|
width = 480,
|
|
39
60
|
height = 240,
|
|
61
|
+
annotations,
|
|
62
|
+
dataLabels,
|
|
63
|
+
hoverKey,
|
|
64
|
+
onHoverKeyChange,
|
|
65
|
+
keyboardNav,
|
|
66
|
+
onSelectKey,
|
|
40
67
|
class: className
|
|
41
68
|
}: CandlestickChartProps = $props();
|
|
42
69
|
|
|
@@ -77,6 +104,9 @@
|
|
|
77
104
|
}
|
|
78
105
|
|
|
79
106
|
let hoveredIndex: number | null = $state(null);
|
|
107
|
+
// FR-5 — roving keyboard focus over the data points (separate from hover).
|
|
108
|
+
let focusedIndex: number = $state(-1);
|
|
109
|
+
let datapointRefs: Array<SVGRectElement | null> = [];
|
|
80
110
|
|
|
81
111
|
const plotWidth = $derived(Math.max(width - MARGIN.left - MARGIN.right, 1));
|
|
82
112
|
const plotHeight = $derived(Math.max(height - MARGIN.top - MARGIN.bottom, 1));
|
|
@@ -131,6 +161,7 @@
|
|
|
131
161
|
index: i,
|
|
132
162
|
bullish,
|
|
133
163
|
centerX,
|
|
164
|
+
band,
|
|
134
165
|
bodyX: centerX - bodyW / 2,
|
|
135
166
|
bodyY: bodyTop,
|
|
136
167
|
bodyW,
|
|
@@ -142,15 +173,103 @@
|
|
|
142
173
|
});
|
|
143
174
|
});
|
|
144
175
|
|
|
145
|
-
|
|
146
|
-
|
|
176
|
+
// --- Annotation overlay ---------------------------------------------------
|
|
177
|
+
// The x coordinate is CATEGORICAL (a candle `label` → centre of band); the y
|
|
178
|
+
// coordinate is a price-axis number. Regions render behind the candles, every
|
|
179
|
+
// other kind above. The resolver maps each x via `xScale` (category → pixel)
|
|
180
|
+
// and each y via `yScale` (price → pixel), relative to the plot origin.
|
|
181
|
+
const priceY = $derived((v: number): number | null => {
|
|
182
|
+
if (!Number.isFinite(v)) return null;
|
|
183
|
+
return scaleLinear(v, domainMin, domainMax, plotHeight, 0);
|
|
184
|
+
});
|
|
185
|
+
const categoryPixel = $derived((v: number | string): number | null => {
|
|
186
|
+
const candle = candles.find((c) => c.datum.label === String(v));
|
|
187
|
+
if (!candle) return null;
|
|
188
|
+
return candle.centerX - MARGIN.left;
|
|
189
|
+
});
|
|
190
|
+
const resolvedAnnotations = $derived(
|
|
191
|
+
resolveAnnotations(annotations, {
|
|
192
|
+
xScale: categoryPixel,
|
|
193
|
+
yScale: priceY,
|
|
194
|
+
plotLeft: MARGIN.left,
|
|
195
|
+
plotTop: MARGIN.top,
|
|
196
|
+
plotWidth,
|
|
197
|
+
plotHeight
|
|
198
|
+
})
|
|
147
199
|
);
|
|
200
|
+
const annotationRegions = $derived(resolvedAnnotations.filter((a) => a.kind === "region"));
|
|
201
|
+
const annotationAbove = $derived(resolvedAnnotations.filter((a) => a.kind !== "region"));
|
|
202
|
+
|
|
203
|
+
// --- Data labels ----------------------------------------------------------
|
|
204
|
+
// One `close` value label per candle, placed just above it. aria-hidden.
|
|
205
|
+
const dataLabelOpts = $derived(normalizeDataLabels(dataLabels));
|
|
206
|
+
const dataLabelItems = $derived.by(() => {
|
|
207
|
+
if (!dataLabelOpts.enabled) return [] as { key: string; x: number; y: number; text: string }[];
|
|
208
|
+
return candles.map((candle) => ({
|
|
209
|
+
key: candle.datum.label,
|
|
210
|
+
x: candle.centerX,
|
|
211
|
+
y: candle.wickHighY - 6,
|
|
212
|
+
text: formatDataLabel(candle.datum.close, dataLabelOpts, formatTick)
|
|
213
|
+
}));
|
|
214
|
+
});
|
|
148
215
|
|
|
216
|
+
const dataValueItems = $derived([
|
|
217
|
+
...validData.map((d) => `${d.label}: O ${d.open} H ${d.high} L ${d.low} C ${d.close}`),
|
|
218
|
+
...annotationDataListItems(annotations)
|
|
219
|
+
]);
|
|
220
|
+
|
|
221
|
+
// Stable key per candle (FR-3): its `label`. Resolves a controlled `hoverKey`
|
|
222
|
+
// to an index and feeds `onHoverKeyChange` from pointer events.
|
|
223
|
+
const hoverKeys = $derived(candles.map((c) => c.datum.label));
|
|
224
|
+
function emitHoverKey(index: number | null) {
|
|
225
|
+
onHoverKeyChange?.(index == null ? null : hoverKeys[index] ?? null);
|
|
226
|
+
}
|
|
227
|
+
function handleLeave() {
|
|
228
|
+
hoveredIndex = null;
|
|
229
|
+
emitHoverKey(null);
|
|
230
|
+
}
|
|
149
231
|
function handlePointerMove(event: PointerEvent) {
|
|
150
232
|
const target = event.target;
|
|
151
|
-
if (!(target instanceof Element)) {
|
|
152
|
-
|
|
153
|
-
|
|
233
|
+
if (!(target instanceof Element)) {
|
|
234
|
+
hoveredIndex = null;
|
|
235
|
+
emitHoverKey(null);
|
|
236
|
+
return;
|
|
237
|
+
}
|
|
238
|
+
const raw = Number(target.getAttribute("data-chart-index"));
|
|
239
|
+
const index = Number.isInteger(raw) ? raw : null;
|
|
240
|
+
hoveredIndex = index;
|
|
241
|
+
emitHoverKey(index);
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
// Index whose crosshair/tooltip is DISPLAYED: the controlled `hoverKey` when
|
|
245
|
+
// provided (resolved against `hoverKeys`), else the internal pointer index.
|
|
246
|
+
const activeIndex = $derived(resolveActiveIndex(hoverKey, hoveredIndex, hoverKeys));
|
|
247
|
+
|
|
248
|
+
// --- Keyboard navigation (FR-5) ------------------------------------------
|
|
249
|
+
// Active when wired explicitly (`keyboardNav`) or implicitly (`onSelectKey`).
|
|
250
|
+
const navEnabled = $derived((keyboardNav === true || onSelectKey !== undefined) && candles.length > 0);
|
|
251
|
+
function focusDatum(index: number) {
|
|
252
|
+
focusedIndex = index;
|
|
253
|
+
datapointRefs[index]?.focus();
|
|
254
|
+
emitHoverKey(index);
|
|
255
|
+
}
|
|
256
|
+
function handleDatapointKeyDown(event: KeyboardEvent, index: number) {
|
|
257
|
+
const action = datapointNavAction(event.key, index, candles.length);
|
|
258
|
+
if (!action) return;
|
|
259
|
+
event.preventDefault();
|
|
260
|
+
if (action.kind === "move") {
|
|
261
|
+
focusDatum(action.index);
|
|
262
|
+
} else if (action.kind === "select") {
|
|
263
|
+
onSelectKey?.(candles[index].datum.label);
|
|
264
|
+
} else {
|
|
265
|
+
focusedIndex = -1;
|
|
266
|
+
emitHoverKey(null);
|
|
267
|
+
onSelectKey?.(null);
|
|
268
|
+
(event.currentTarget as SVGElement).blur();
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
function ohlcAriaLabel(d: CandlestickChartDatum): string {
|
|
272
|
+
return datapointAriaLabel(d.label, `O ${d.open} H ${d.high} L ${d.low} C ${d.close}`);
|
|
154
273
|
}
|
|
155
274
|
|
|
156
275
|
const classes = () => ["st-candlestickChart", className].filter(Boolean).join(" ");
|
|
@@ -162,7 +281,7 @@
|
|
|
162
281
|
role="img"
|
|
163
282
|
aria-label={label}
|
|
164
283
|
onpointermove={handlePointerMove}
|
|
165
|
-
onpointerleave={
|
|
284
|
+
onpointerleave={handleLeave}
|
|
166
285
|
>
|
|
167
286
|
<svg
|
|
168
287
|
viewBox="0 0 {width} {height}"
|
|
@@ -185,6 +304,20 @@
|
|
|
185
304
|
<line class="st-candlestickChart__axis" x1={MARGIN.left} x2={MARGIN.left} y1={MARGIN.top} y2={height - MARGIN.bottom} />
|
|
186
305
|
<line class="st-candlestickChart__axis" x1={MARGIN.left} x2={width - MARGIN.right} y1={height - MARGIN.bottom} y2={height - MARGIN.bottom} />
|
|
187
306
|
|
|
307
|
+
<!-- Annotation regions sit BEHIND the candles (filled bands). -->
|
|
308
|
+
{#if annotationRegions.length > 0}
|
|
309
|
+
<g class="st-candlestickChart__annotations st-candlestickChart__annotations--behind">
|
|
310
|
+
{#each annotationRegions as a (a.key)}
|
|
311
|
+
{#if a.kind === "region"}
|
|
312
|
+
<rect class="st-candlestickChart__annotationRegion" x={a.x} y={a.y} width={a.width} height={a.height} />
|
|
313
|
+
{#if a.label}
|
|
314
|
+
<text class="st-candlestickChart__annotationLabel" x={a.x + 4} y={a.y + 11}>{a.label}</text>
|
|
315
|
+
{/if}
|
|
316
|
+
{/if}
|
|
317
|
+
{/each}
|
|
318
|
+
</g>
|
|
319
|
+
{/if}
|
|
320
|
+
|
|
188
321
|
<!-- FIX #7 : clé composite pour éviter les doublons -->
|
|
189
322
|
{#each candles as c, i (`${i}-${c.datum.label}`)}
|
|
190
323
|
<!-- wick -->
|
|
@@ -217,13 +350,95 @@
|
|
|
217
350
|
{c.datum.label}
|
|
218
351
|
</text>
|
|
219
352
|
{/each}
|
|
353
|
+
|
|
354
|
+
<!-- Annotations ABOVE the candles: lines, shapes, points, labels. -->
|
|
355
|
+
{#if annotationAbove.length > 0}
|
|
356
|
+
<g class="st-candlestickChart__annotations st-candlestickChart__annotations--above">
|
|
357
|
+
{#each annotationAbove as a (a.key)}
|
|
358
|
+
{#if a.kind === "line"}
|
|
359
|
+
<line class="st-candlestickChart__annotationLine" x1={a.x1} y1={a.y1} x2={a.x2} y2={a.y2} />
|
|
360
|
+
{#if a.label}
|
|
361
|
+
<text
|
|
362
|
+
class="st-candlestickChart__annotationLabel"
|
|
363
|
+
x={a.axis === "x" ? a.x1 + 4 : MARGIN.left + plotWidth - 4}
|
|
364
|
+
y={a.axis === "x" ? MARGIN.top + 11 : a.y1 - 4}
|
|
365
|
+
text-anchor={a.axis === "x" ? "start" : "end"}
|
|
366
|
+
>{a.label}</text>
|
|
367
|
+
{/if}
|
|
368
|
+
{:else if a.kind === "shape"}
|
|
369
|
+
<polygon class="st-candlestickChart__annotationShape" points={polygonPoints(a.points)} />
|
|
370
|
+
{#if a.label}
|
|
371
|
+
<text class="st-candlestickChart__annotationLabel" x={a.labelX} y={a.labelY} text-anchor="middle">{a.label}</text>
|
|
372
|
+
{/if}
|
|
373
|
+
{:else if a.kind === "point"}
|
|
374
|
+
<circle class="st-candlestickChart__annotationPoint" cx={a.x} cy={a.y} r="4.5" />
|
|
375
|
+
{#if a.label}
|
|
376
|
+
<text class="st-candlestickChart__annotationLabel" x={a.x} y={a.y - 8} text-anchor="middle">{a.label}</text>
|
|
377
|
+
{/if}
|
|
378
|
+
{:else}
|
|
379
|
+
<text class="st-candlestickChart__annotationText" x={a.x} y={a.y} text-anchor={a.anchor}>{a.text}</text>
|
|
380
|
+
{/if}
|
|
381
|
+
{/each}
|
|
382
|
+
</g>
|
|
383
|
+
{/if}
|
|
384
|
+
|
|
385
|
+
<!-- Data labels — one close value per candle, drawn on top. aria-hidden. -->
|
|
386
|
+
{#if dataLabelItems.length > 0}
|
|
387
|
+
<g class="st-candlestickChart__dataLabels" aria-hidden="true">
|
|
388
|
+
{#each dataLabelItems as d (d.key)}
|
|
389
|
+
<text class="st-candlestickChart__dataLabel" x={d.x} y={d.y} text-anchor="middle" dominant-baseline="auto">{d.text}</text>
|
|
390
|
+
{/each}
|
|
391
|
+
</g>
|
|
392
|
+
{/if}
|
|
393
|
+
|
|
394
|
+
<!-- Crosshair (FR-3) — a tokenised dashed vertical line at the active candle.
|
|
395
|
+
Decorative (aria-hidden); the value is in the tooltip + ChartDataList. -->
|
|
396
|
+
{#if activeIndex >= 0 && candles[activeIndex]}
|
|
397
|
+
{@const cc = candles[activeIndex]}
|
|
398
|
+
<g class="st-candlestickChart__crosshair" aria-hidden="true">
|
|
399
|
+
<line class="st-candlestickChart__crosshairLine" x1={cc.centerX} x2={cc.centerX} y1={MARGIN.top} y2={MARGIN.top + plotHeight} />
|
|
400
|
+
</g>
|
|
401
|
+
{/if}
|
|
220
402
|
</svg>
|
|
403
|
+
|
|
404
|
+
<!-- Keyboard navigation overlay (FR-5) — a focusable, transparent hit layer
|
|
405
|
+
over the candles. NOT aria-hidden: it is the accessible roving cursor. -->
|
|
406
|
+
{#if navEnabled}
|
|
407
|
+
<svg
|
|
408
|
+
class="st-candlestickChart__navLayer"
|
|
409
|
+
viewBox="0 0 {width} {height}"
|
|
410
|
+
preserveAspectRatio="xMidYMid meet"
|
|
411
|
+
width="100%"
|
|
412
|
+
height="100%"
|
|
413
|
+
role="group"
|
|
414
|
+
aria-label={`${label} — points de données`}
|
|
415
|
+
>
|
|
416
|
+
{#each candles as candle, i (`${i}-${candle.datum.label}`)}
|
|
417
|
+
<rect
|
|
418
|
+
bind:this={datapointRefs[i]}
|
|
419
|
+
class="st-candlestickChart__navDatum"
|
|
420
|
+
x={candle.centerX - candle.band / 2}
|
|
421
|
+
y={MARGIN.top}
|
|
422
|
+
width={candle.band}
|
|
423
|
+
height={plotHeight}
|
|
424
|
+
role="img"
|
|
425
|
+
tabindex={rovingTabIndex(i, focusedIndex, candles.length)}
|
|
426
|
+
aria-label={ohlcAriaLabel(candle.datum)}
|
|
427
|
+
onkeydown={(event) => handleDatapointKeyDown(event, i)}
|
|
428
|
+
onfocus={() => {
|
|
429
|
+
focusedIndex = i;
|
|
430
|
+
emitHoverKey(i);
|
|
431
|
+
}}
|
|
432
|
+
/>
|
|
433
|
+
{/each}
|
|
434
|
+
</svg>
|
|
435
|
+
{/if}
|
|
221
436
|
</div>
|
|
222
437
|
|
|
223
438
|
<ChartDataList {label} items={dataValueItems} />
|
|
224
439
|
|
|
225
|
-
{#if
|
|
226
|
-
{@const c = candles[
|
|
440
|
+
{#if activeIndex >= 0 && candles[activeIndex]}
|
|
441
|
+
{@const c = candles[activeIndex]}
|
|
227
442
|
<div
|
|
228
443
|
class="st-candlestickChart__tooltip"
|
|
229
444
|
role="presentation"
|
|
@@ -251,6 +466,7 @@
|
|
|
251
466
|
|
|
252
467
|
.st-candlestickChart__visual {
|
|
253
468
|
display: block;
|
|
469
|
+
position: relative;
|
|
254
470
|
}
|
|
255
471
|
|
|
256
472
|
.st-candlestickChart__axis {
|
|
@@ -294,6 +510,65 @@
|
|
|
294
510
|
fill: var(--st-semantic-feedback-error);
|
|
295
511
|
}
|
|
296
512
|
|
|
513
|
+
/* --- Annotation layer ----------------------------------------------------
|
|
514
|
+
Regions render BEHIND the candles; lines/shapes/points/labels render ABOVE. */
|
|
515
|
+
.st-candlestickChart__annotationRegion {
|
|
516
|
+
fill: color-mix(in srgb, var(--st-semantic-feedback-info) 12%, transparent);
|
|
517
|
+
stroke: none;
|
|
518
|
+
}
|
|
519
|
+
.st-candlestickChart__annotationLine {
|
|
520
|
+
stroke: var(--st-semantic-feedback-info);
|
|
521
|
+
stroke-width: 1.5;
|
|
522
|
+
stroke-dasharray: 4 3;
|
|
523
|
+
}
|
|
524
|
+
.st-candlestickChart__annotationShape {
|
|
525
|
+
fill: color-mix(in srgb, var(--st-semantic-feedback-info) 14%, transparent);
|
|
526
|
+
stroke: var(--st-semantic-feedback-info);
|
|
527
|
+
stroke-width: 1.5;
|
|
528
|
+
}
|
|
529
|
+
.st-candlestickChart__annotationPoint {
|
|
530
|
+
fill: var(--st-semantic-feedback-info);
|
|
531
|
+
stroke: var(--st-semantic-surface-default);
|
|
532
|
+
stroke-width: 1.5;
|
|
533
|
+
}
|
|
534
|
+
.st-candlestickChart__annotationLabel,
|
|
535
|
+
.st-candlestickChart__annotationText {
|
|
536
|
+
fill: var(--st-semantic-text-primary);
|
|
537
|
+
font-size: 0.625rem;
|
|
538
|
+
font-weight: 600;
|
|
539
|
+
}
|
|
540
|
+
|
|
541
|
+
/* Data labels — per-candle close value, drawn on top. Token-only colour. */
|
|
542
|
+
.st-candlestickChart__dataLabel {
|
|
543
|
+
fill: var(--st-semantic-text-primary);
|
|
544
|
+
font-size: 0.6875rem;
|
|
545
|
+
font-weight: 600;
|
|
546
|
+
}
|
|
547
|
+
|
|
548
|
+
/* Crosshair (FR-3) — a tokenised dashed vertical line at the active candle. */
|
|
549
|
+
.st-candlestickChart__crosshairLine {
|
|
550
|
+
stroke: var(--st-semantic-border-strong);
|
|
551
|
+
stroke-width: 1;
|
|
552
|
+
stroke-dasharray: 3 3;
|
|
553
|
+
opacity: 0.7;
|
|
554
|
+
}
|
|
555
|
+
|
|
556
|
+
/* Keyboard navigation layer (FR-5) — a focusable, transparent overlay of one
|
|
557
|
+
hit-rect per candle. Carries the roving tab stop; the focus ring is tokenised. */
|
|
558
|
+
.st-candlestickChart__navLayer {
|
|
559
|
+
inset: 0;
|
|
560
|
+
position: absolute;
|
|
561
|
+
}
|
|
562
|
+
.st-candlestickChart__navDatum {
|
|
563
|
+
fill: transparent;
|
|
564
|
+
outline: none;
|
|
565
|
+
}
|
|
566
|
+
.st-candlestickChart__navDatum:focus-visible {
|
|
567
|
+
fill: color-mix(in srgb, var(--st-semantic-border-interactive) 12%, transparent);
|
|
568
|
+
outline: 2px solid var(--st-semantic-border-interactive);
|
|
569
|
+
outline-offset: 1px;
|
|
570
|
+
}
|
|
571
|
+
|
|
297
572
|
@media (prefers-reduced-motion: reduce) {
|
|
298
573
|
.st-candlestickChart__body {
|
|
299
574
|
transition: none;
|
|
@@ -7,9 +7,15 @@
|
|
|
7
7
|
* label string
|
|
8
8
|
*
|
|
9
9
|
* Props optionnelles :
|
|
10
|
-
* width
|
|
11
|
-
* height
|
|
12
|
-
*
|
|
10
|
+
* width number (défaut 480)
|
|
11
|
+
* height number (défaut 240)
|
|
12
|
+
* annotations ChartAnnotation[] - overlay support/résistance/zones/events
|
|
13
|
+
* dataLabels boolean | { format?, position? } - étiquette close par bougie
|
|
14
|
+
* hoverKey string | null - crosshair contrôlé (clé = date/catégorie)
|
|
15
|
+
* onHoverKeyChange (key) => void - émet la date survolée (ou null)
|
|
16
|
+
* keyboardNav boolean - navigation clavier (roving tabindex)
|
|
17
|
+
* onSelectKey (key) => void - sélection clavier (Enter/Space) ; null = Escape
|
|
18
|
+
* class string
|
|
13
19
|
*/
|
|
14
20
|
export type CandlestickChartDatum = {
|
|
15
21
|
label: string;
|
|
@@ -18,11 +24,19 @@ export type CandlestickChartDatum = {
|
|
|
18
24
|
low: number;
|
|
19
25
|
close: number;
|
|
20
26
|
};
|
|
27
|
+
import { type ChartAnnotation } from "./chartAnnotations.js";
|
|
28
|
+
import { type DataLabelsProp } from "./chartDataLabels.js";
|
|
21
29
|
type CandlestickChartProps = {
|
|
22
30
|
data: CandlestickChartDatum[];
|
|
23
31
|
label: string;
|
|
24
32
|
width?: number;
|
|
25
33
|
height?: number;
|
|
34
|
+
annotations?: ChartAnnotation[];
|
|
35
|
+
dataLabels?: DataLabelsProp;
|
|
36
|
+
hoverKey?: string | null;
|
|
37
|
+
onHoverKeyChange?: (key: string | null) => void;
|
|
38
|
+
keyboardNav?: boolean;
|
|
39
|
+
onSelectKey?: (key: string | null) => void;
|
|
26
40
|
class?: string;
|
|
27
41
|
};
|
|
28
42
|
declare const CandlestickChart: import("svelte").Component<CandlestickChartProps, {}, "">;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CandlestickChart.svelte.d.ts","sourceRoot":"","sources":["../src/lib/CandlestickChart.svelte.ts"],"names":[],"mappings":"AAGE
|
|
1
|
+
{"version":3,"file":"CandlestickChart.svelte.d.ts","sourceRoot":"","sources":["../src/lib/CandlestickChart.svelte.ts"],"names":[],"mappings":"AAGE;;;;;;;;;;;;;;;;;;GAkBG;AACH,MAAM,MAAM,qBAAqB,GAAG;IAClC,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;CACf,CAAC;AAIJ,OAAO,EAIH,KAAK,eAAe,EACrB,MAAM,uBAAuB,CAAC;AACjC,OAAO,EAAwC,KAAK,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAK/F,KAAK,qBAAqB,GAAG;IAC3B,IAAI,EAAE,qBAAqB,EAAE,CAAC;IAC9B,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,WAAW,CAAC,EAAE,eAAe,EAAE,CAAC;IAChC,UAAU,CAAC,EAAE,cAAc,CAAC;IAC5B,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,gBAAgB,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,KAAK,IAAI,CAAC;IAChD,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,WAAW,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,KAAK,IAAI,CAAC;IAC3C,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,CAAC;AA2VJ,QAAA,MAAM,gBAAgB,2DAAwC,CAAC;AAC/D,KAAK,gBAAgB,GAAG,UAAU,CAAC,OAAO,gBAAgB,CAAC,CAAC;AAC5D,eAAe,gBAAgB,CAAC"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { cellDecorationIcon } from "./cellDecoration.js";
|
|
3
|
+
|
|
4
|
+
let { icon }: { icon?: string } = $props();
|
|
5
|
+
|
|
6
|
+
const nodes = $derived(cellDecorationIcon(icon));
|
|
7
|
+
</script>
|
|
8
|
+
|
|
9
|
+
{#if nodes}
|
|
10
|
+
<svg
|
|
11
|
+
class="st-cell__icon"
|
|
12
|
+
width="14"
|
|
13
|
+
height="14"
|
|
14
|
+
viewBox="0 0 24 24"
|
|
15
|
+
fill="none"
|
|
16
|
+
stroke="currentColor"
|
|
17
|
+
stroke-width="2"
|
|
18
|
+
stroke-linecap="round"
|
|
19
|
+
stroke-linejoin="round"
|
|
20
|
+
aria-hidden="true"
|
|
21
|
+
focusable="false"
|
|
22
|
+
>
|
|
23
|
+
{#each nodes as [tag, attrs]}
|
|
24
|
+
{#if tag === "path"}
|
|
25
|
+
<path {...attrs} />
|
|
26
|
+
{:else if tag === "circle"}
|
|
27
|
+
<circle {...attrs} />
|
|
28
|
+
{:else if tag === "line"}
|
|
29
|
+
<line {...attrs} />
|
|
30
|
+
{/if}
|
|
31
|
+
{/each}
|
|
32
|
+
</svg>
|
|
33
|
+
{/if}
|
|
34
|
+
|
|
35
|
+
<style>
|
|
36
|
+
.st-cell__icon {
|
|
37
|
+
flex: 0 0 auto;
|
|
38
|
+
}
|
|
39
|
+
</style>
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
type $$ComponentProps = {
|
|
2
|
+
icon?: string;
|
|
3
|
+
};
|
|
4
|
+
declare const CellDecorationIcon: import("svelte").Component<$$ComponentProps, {}, "">;
|
|
5
|
+
type CellDecorationIcon = ReturnType<typeof CellDecorationIcon>;
|
|
6
|
+
export default CellDecorationIcon;
|
|
7
|
+
//# sourceMappingURL=CellDecorationIcon.svelte.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"CellDecorationIcon.svelte.d.ts","sourceRoot":"","sources":["../src/lib/CellDecorationIcon.svelte.ts"],"names":[],"mappings":"AAKC,KAAK,gBAAgB,GAAI;IAAE,IAAI,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC;AA2B5C,QAAA,MAAM,kBAAkB,sDAAwC,CAAC;AACjE,KAAK,kBAAkB,GAAG,UAAU,CAAC,OAAO,kBAAkB,CAAC,CAAC;AAChE,eAAe,kBAAkB,CAAC"}
|