@sentropic/design-system-svelte 0.34.28 → 0.34.33
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/Badge.svelte +66 -2
- package/dist/Badge.svelte.d.ts +21 -0
- package/dist/Badge.svelte.d.ts.map +1 -1
- 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/Collapsible.svelte +55 -1
- package/dist/Collapsible.svelte.d.ts +15 -0
- package/dist/Collapsible.svelte.d.ts.map +1 -1
- package/dist/Collapsible.test.d.ts +2 -0
- package/dist/Collapsible.test.d.ts.map +1 -0
- package/dist/Collapsible.test.js +68 -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/SelectableList.svelte +36 -17
- package/dist/SelectableList.svelte.d.ts.map +1 -1
- package/dist/SelectableRow.svelte +53 -1
- package/dist/SelectableRow.svelte.d.ts +10 -0
- package/dist/SelectableRow.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 +3 -3
package/dist/ScatterPlot.svelte
CHANGED
|
@@ -26,6 +26,15 @@
|
|
|
26
26
|
|
|
27
27
|
<script lang="ts">
|
|
28
28
|
import ChartDataList from "./ChartDataList.svelte";
|
|
29
|
+
import {
|
|
30
|
+
annotationDataListItems,
|
|
31
|
+
polygonPoints,
|
|
32
|
+
resolveAnnotations,
|
|
33
|
+
type ChartAnnotation,
|
|
34
|
+
} from "./chartAnnotations.js";
|
|
35
|
+
import { formatDataLabel, normalizeDataLabels, type DataLabelsProp } from "./chartDataLabels.js";
|
|
36
|
+
import { resolveActiveIndex } from "./chartCrosshair.js";
|
|
37
|
+
import { datapointAriaLabel, datapointNavAction, rovingTabIndex } from "./chartKeyboardNav.js";
|
|
29
38
|
|
|
30
39
|
type ScatterPlotProps = {
|
|
31
40
|
data: ScatterPlotDatum[];
|
|
@@ -39,6 +48,29 @@
|
|
|
39
48
|
* coordinates are folded into the axis domain. Non-finite x/y are skipped.
|
|
40
49
|
*/
|
|
41
50
|
centroids?: ScatterPlotCentroid[];
|
|
51
|
+
/**
|
|
52
|
+
* Annotation overlay in DATA space (points, labels, axis lines, regions,
|
|
53
|
+
* polygons). Both axes are continuous (linear). Additive: absent ⇒ unchanged.
|
|
54
|
+
*/
|
|
55
|
+
annotations?: ChartAnnotation[];
|
|
56
|
+
/**
|
|
57
|
+
* Per-point value labels. `false`/absent → none. `true` → each point's value
|
|
58
|
+
* (the datum `label` wins when present). Object → `format`/`position`.
|
|
59
|
+
* Default position `top`. Labels are `aria-hidden`.
|
|
60
|
+
*/
|
|
61
|
+
dataLabels?: DataLabelsProp;
|
|
62
|
+
/**
|
|
63
|
+
* CONTROLLED synchronised hover key (FR-3). A point's key is its `label` when
|
|
64
|
+
* present, otherwise `"x,y"`. Absent (`undefined`) keeps the uncontrolled
|
|
65
|
+
* behaviour.
|
|
66
|
+
*/
|
|
67
|
+
hoverKey?: string | null;
|
|
68
|
+
/** Emitted on hover (the key) / leave (`null`); fired even while controlled. */
|
|
69
|
+
onHoverKeyChange?: (key: string | null) => void;
|
|
70
|
+
/** FR-5 — roving-tabindex keyboard navigation of the data points. */
|
|
71
|
+
keyboardNav?: boolean;
|
|
72
|
+
/** Emitted on Enter/Space select (the key) / Escape (`null`); enables nav. */
|
|
73
|
+
onSelectKey?: (key: string | null) => void;
|
|
42
74
|
label: string;
|
|
43
75
|
class?: string;
|
|
44
76
|
};
|
|
@@ -51,6 +83,12 @@
|
|
|
51
83
|
yLabel,
|
|
52
84
|
radius = 5,
|
|
53
85
|
centroids,
|
|
86
|
+
annotations,
|
|
87
|
+
dataLabels,
|
|
88
|
+
hoverKey,
|
|
89
|
+
onHoverKeyChange,
|
|
90
|
+
keyboardNav,
|
|
91
|
+
onSelectKey,
|
|
54
92
|
label,
|
|
55
93
|
class: className
|
|
56
94
|
}: ScatterPlotProps = $props();
|
|
@@ -88,6 +126,9 @@
|
|
|
88
126
|
}
|
|
89
127
|
|
|
90
128
|
let hoveredIndex: number | null = $state(null);
|
|
129
|
+
// FR-5 — roving keyboard focus over the data points (separate from hover).
|
|
130
|
+
let focusedIndex: number = $state(-1);
|
|
131
|
+
let datapointRefs: Array<SVGRectElement | null> = [];
|
|
91
132
|
|
|
92
133
|
const TONES = ["category1","category2","category3","category4","category5","category6","category7","category8"] as const;
|
|
93
134
|
|
|
@@ -95,6 +136,11 @@
|
|
|
95
136
|
// the plot); non-finite/negative values fall back to the global radius.
|
|
96
137
|
const MAX_POINT_RADIUS = 32;
|
|
97
138
|
|
|
139
|
+
/** Stable hover/selection key of a point: its label, else `"x,y"`. */
|
|
140
|
+
function keyForPoint(d: ScatterPlotDatum): string {
|
|
141
|
+
return d.label ?? `${d.x},${d.y}`;
|
|
142
|
+
}
|
|
143
|
+
|
|
98
144
|
// Centroids guarded once: non-finite coordinates are skipped entirely.
|
|
99
145
|
const validCentroids = $derived(
|
|
100
146
|
(centroids ?? []).filter((c) => Number.isFinite(c.x) && Number.isFinite(c.y))
|
|
@@ -124,6 +170,7 @@
|
|
|
124
170
|
cy: MARGIN.top + scaleLinear(d.y, yMin, yMax, plotH, 0),
|
|
125
171
|
r: typeof d.r === "number" && Number.isFinite(d.r) && d.r >= 0 ? Math.min(d.r, MAX_POINT_RADIUS) : radius,
|
|
126
172
|
datum: d,
|
|
173
|
+
index: i,
|
|
127
174
|
tone: d.tone ?? TONES[i % TONES.length]
|
|
128
175
|
}));
|
|
129
176
|
});
|
|
@@ -138,21 +185,110 @@
|
|
|
138
185
|
}));
|
|
139
186
|
});
|
|
140
187
|
|
|
188
|
+
// --- Annotation overlay ----------------------------------------------------
|
|
189
|
+
// Both axes continuous: linear `xScale`/`yScale`, out-of-domain ⇒ null.
|
|
190
|
+
const annotationXScale = $derived((v: number | string): number | null => {
|
|
191
|
+
const { xMin, xMax, plotW } = scales;
|
|
192
|
+
if (typeof v !== "number" || !Number.isFinite(v)) return null;
|
|
193
|
+
if (v < xMin || v > xMax) return null;
|
|
194
|
+
return scaleLinear(v, xMin, xMax, 0, plotW);
|
|
195
|
+
});
|
|
196
|
+
const annotationYScale = $derived((v: number): number | null => {
|
|
197
|
+
const { yMin, yMax, plotH } = scales;
|
|
198
|
+
if (!Number.isFinite(v)) return null;
|
|
199
|
+
if (v < yMin || v > yMax) return null;
|
|
200
|
+
return scaleLinear(v, yMin, yMax, plotH, 0);
|
|
201
|
+
});
|
|
202
|
+
const resolvedAnnotations = $derived(
|
|
203
|
+
resolveAnnotations(annotations, {
|
|
204
|
+
xScale: annotationXScale,
|
|
205
|
+
yScale: annotationYScale,
|
|
206
|
+
plotLeft: MARGIN.left,
|
|
207
|
+
plotTop: MARGIN.top,
|
|
208
|
+
plotWidth: scales.plotW,
|
|
209
|
+
plotHeight: scales.plotH
|
|
210
|
+
})
|
|
211
|
+
);
|
|
212
|
+
const annotationRegions = $derived(resolvedAnnotations.filter((a) => a.kind === "region"));
|
|
213
|
+
const annotationAbove = $derived(resolvedAnnotations.filter((a) => a.kind !== "region"));
|
|
214
|
+
|
|
215
|
+
// --- Data labels -----------------------------------------------------------
|
|
216
|
+
// One label per point. Default `top`. The datum `label` wins; else the y.
|
|
217
|
+
const dataLabelOpts = $derived(normalizeDataLabels(dataLabels));
|
|
218
|
+
const dataLabelItems = $derived(
|
|
219
|
+
dataLabelOpts.enabled
|
|
220
|
+
? points.map((p) => {
|
|
221
|
+
const text = p.datum.label ?? formatDataLabel(p.datum.y, dataLabelOpts, fmt);
|
|
222
|
+
const center = dataLabelOpts.position === "center" || dataLabelOpts.position === "inside";
|
|
223
|
+
return {
|
|
224
|
+
key: p.index,
|
|
225
|
+
x: p.cx,
|
|
226
|
+
y: center ? p.cy : p.cy - (p.r + 5),
|
|
227
|
+
text,
|
|
228
|
+
baseline: (center ? "middle" : "auto") as "middle" | "auto"
|
|
229
|
+
};
|
|
230
|
+
})
|
|
231
|
+
: []
|
|
232
|
+
);
|
|
233
|
+
|
|
141
234
|
const dataValueItems = $derived([
|
|
142
235
|
...data.map((d) => (d.label ? `${d.label}: x ${d.x}, y ${d.y}` : `x ${d.x}, y ${d.y}`)),
|
|
143
236
|
...validCentroids.map((c) =>
|
|
144
237
|
c.label ? `Centroïde ${c.label}: (${c.x}, ${c.y})` : `Centroïde: (${c.x}, ${c.y})`
|
|
145
|
-
)
|
|
238
|
+
),
|
|
239
|
+
...annotationDataListItems(annotations)
|
|
146
240
|
]);
|
|
147
241
|
|
|
242
|
+
// Stable key per point (FR-3): `label` else `"x,y"`.
|
|
243
|
+
const hoverKeys = $derived(data.map((d) => keyForPoint(d)));
|
|
244
|
+
function emitHoverKey(index: number | null) {
|
|
245
|
+
onHoverKeyChange?.(index == null ? null : hoverKeys[index] ?? null);
|
|
246
|
+
}
|
|
247
|
+
function handleLeave() {
|
|
248
|
+
hoveredIndex = null;
|
|
249
|
+
emitHoverKey(null);
|
|
250
|
+
}
|
|
148
251
|
function handleVisualPointerMove(event: PointerEvent) {
|
|
149
252
|
const target = event.target;
|
|
150
253
|
if (!(target instanceof Element)) {
|
|
151
254
|
hoveredIndex = null;
|
|
255
|
+
emitHoverKey(null);
|
|
152
256
|
return;
|
|
153
257
|
}
|
|
154
|
-
const
|
|
155
|
-
|
|
258
|
+
const raw = Number(target.getAttribute("data-chart-index"));
|
|
259
|
+
const index = Number.isInteger(raw) ? raw : null;
|
|
260
|
+
hoveredIndex = index;
|
|
261
|
+
emitHoverKey(index);
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
// Index whose crosshair/tooltip is DISPLAYED: the controlled `hoverKey` when
|
|
265
|
+
// provided (resolved against `hoverKeys`), else the internal pointer index.
|
|
266
|
+
const activeIndex = $derived(resolveActiveIndex(hoverKey, hoveredIndex, hoverKeys));
|
|
267
|
+
|
|
268
|
+
// --- Keyboard navigation (FR-5) --------------------------------------------
|
|
269
|
+
// Active when wired explicitly (`keyboardNav`) or implicitly (`onSelectKey`).
|
|
270
|
+
const navEnabled = $derived((keyboardNav === true || onSelectKey !== undefined) && points.length > 0);
|
|
271
|
+
// Comfortable square hit area centred on each dot.
|
|
272
|
+
const NAV_HIT = 18;
|
|
273
|
+
function focusDatum(index: number) {
|
|
274
|
+
focusedIndex = index;
|
|
275
|
+
datapointRefs[index]?.focus();
|
|
276
|
+
emitHoverKey(index);
|
|
277
|
+
}
|
|
278
|
+
function handleDatapointKeyDown(event: KeyboardEvent, index: number) {
|
|
279
|
+
const action = datapointNavAction(event.key, index, points.length);
|
|
280
|
+
if (!action) return;
|
|
281
|
+
event.preventDefault();
|
|
282
|
+
if (action.kind === "move") {
|
|
283
|
+
focusDatum(action.index);
|
|
284
|
+
} else if (action.kind === "select") {
|
|
285
|
+
onSelectKey?.(hoverKeys[index] ?? null);
|
|
286
|
+
} else {
|
|
287
|
+
focusedIndex = -1;
|
|
288
|
+
emitHoverKey(null);
|
|
289
|
+
onSelectKey?.(null);
|
|
290
|
+
(event.currentTarget as SVGElement).blur();
|
|
291
|
+
}
|
|
156
292
|
}
|
|
157
293
|
|
|
158
294
|
const classes = () => ["st-scatterPlot", className].filter(Boolean).join(" ");
|
|
@@ -164,7 +300,7 @@
|
|
|
164
300
|
role="img"
|
|
165
301
|
aria-label={label}
|
|
166
302
|
onpointermove={handleVisualPointerMove}
|
|
167
|
-
onpointerleave={
|
|
303
|
+
onpointerleave={handleLeave}
|
|
168
304
|
>
|
|
169
305
|
<svg viewBox="0 0 {width} {height}" preserveAspectRatio="xMidYMid meet" width="100%" height="100%" focusable="false" aria-hidden="true">
|
|
170
306
|
<!-- gridlines + ticks Y -->
|
|
@@ -190,6 +326,20 @@
|
|
|
190
326
|
<text class="st-scatterPlot__axisLabel" x={12} y={MARGIN.top + scales.plotH / 2} text-anchor="middle" transform="rotate(-90 12 {MARGIN.top + scales.plotH / 2})">{yLabel}</text>
|
|
191
327
|
{/if}
|
|
192
328
|
|
|
329
|
+
<!-- Annotation regions sit BEHIND the points (filled bands). -->
|
|
330
|
+
{#if annotationRegions.length > 0}
|
|
331
|
+
<g class="st-scatterPlot__annotations st-scatterPlot__annotations--behind">
|
|
332
|
+
{#each annotationRegions as a (a.key)}
|
|
333
|
+
{#if a.kind === "region"}
|
|
334
|
+
<rect class="st-scatterPlot__annotationRegion" x={a.x} y={a.y} width={a.width} height={a.height} />
|
|
335
|
+
{#if a.label}
|
|
336
|
+
<text class="st-scatterPlot__annotationLabel" x={a.x + 4} y={a.y + 11}>{a.label}</text>
|
|
337
|
+
{/if}
|
|
338
|
+
{/if}
|
|
339
|
+
{/each}
|
|
340
|
+
</g>
|
|
341
|
+
{/if}
|
|
342
|
+
|
|
193
343
|
<!-- points -->
|
|
194
344
|
{#each points as p, i (i)}
|
|
195
345
|
<circle
|
|
@@ -209,13 +359,100 @@
|
|
|
209
359
|
<line class="st-scatterPlot__centroidCross" x1={c.cx} x2={c.cx} y1={c.cy - 3.5} y2={c.cy + 3.5} />
|
|
210
360
|
</g>
|
|
211
361
|
{/each}
|
|
362
|
+
|
|
363
|
+
<!-- Annotations ABOVE the points: lines, shapes, points, labels. -->
|
|
364
|
+
{#if annotationAbove.length > 0}
|
|
365
|
+
<g class="st-scatterPlot__annotations st-scatterPlot__annotations--above">
|
|
366
|
+
{#each annotationAbove as a (a.key)}
|
|
367
|
+
{#if a.kind === "line"}
|
|
368
|
+
<line class="st-scatterPlot__annotationLine" x1={a.x1} y1={a.y1} x2={a.x2} y2={a.y2} />
|
|
369
|
+
{#if a.label}
|
|
370
|
+
<text
|
|
371
|
+
class="st-scatterPlot__annotationLabel"
|
|
372
|
+
x={a.axis === "x" ? a.x1 + 4 : MARGIN.left + scales.plotW - 4}
|
|
373
|
+
y={a.axis === "x" ? MARGIN.top + 11 : a.y1 - 4}
|
|
374
|
+
text-anchor={a.axis === "x" ? "start" : "end"}
|
|
375
|
+
>{a.label}</text>
|
|
376
|
+
{/if}
|
|
377
|
+
{:else if a.kind === "shape"}
|
|
378
|
+
<polygon class="st-scatterPlot__annotationShape" points={polygonPoints(a.points)} />
|
|
379
|
+
{#if a.label}
|
|
380
|
+
<text class="st-scatterPlot__annotationLabel" x={a.labelX} y={a.labelY} text-anchor="middle">{a.label}</text>
|
|
381
|
+
{/if}
|
|
382
|
+
{:else if a.kind === "point"}
|
|
383
|
+
<circle class="st-scatterPlot__annotationPoint" cx={a.x} cy={a.y} r="4.5" />
|
|
384
|
+
{#if a.label}
|
|
385
|
+
<text class="st-scatterPlot__annotationLabel" x={a.x} y={a.y - 8} text-anchor="middle">{a.label}</text>
|
|
386
|
+
{/if}
|
|
387
|
+
{:else if a.kind === "label"}
|
|
388
|
+
<text class="st-scatterPlot__annotationText" x={a.x} y={a.y} text-anchor={a.anchor}>{a.text}</text>
|
|
389
|
+
{/if}
|
|
390
|
+
{/each}
|
|
391
|
+
</g>
|
|
392
|
+
{/if}
|
|
393
|
+
|
|
394
|
+
<!-- Data labels — one value/label per point, drawn on top. aria-hidden. -->
|
|
395
|
+
{#if dataLabelItems.length > 0}
|
|
396
|
+
<g class="st-scatterPlot__dataLabels" aria-hidden="true">
|
|
397
|
+
{#each dataLabelItems as d (d.key)}
|
|
398
|
+
<text class="st-scatterPlot__dataLabel" x={d.x} y={d.y} text-anchor="middle" dominant-baseline={d.baseline}>{d.text}</text>
|
|
399
|
+
{/each}
|
|
400
|
+
</g>
|
|
401
|
+
{/if}
|
|
402
|
+
|
|
403
|
+
<!-- Crosshair (FR-3) — a tokenised CROSSED pair (vertical + horizontal) at
|
|
404
|
+
the active key, plus a marker on the point. Decorative (aria-hidden). -->
|
|
405
|
+
{#if activeIndex >= 0 && points[activeIndex]}
|
|
406
|
+
{@const cp = points[activeIndex]}
|
|
407
|
+
<g class="st-scatterPlot__crosshair" aria-hidden="true">
|
|
408
|
+
<line class="st-scatterPlot__crosshairLine" x1={cp.cx} x2={cp.cx} y1={MARGIN.top} y2={MARGIN.top + scales.plotH} />
|
|
409
|
+
<line class="st-scatterPlot__crosshairLine" x1={MARGIN.left} x2={MARGIN.left + scales.plotW} y1={cp.cy} y2={cp.cy} />
|
|
410
|
+
<circle class="st-scatterPlot__crosshairMarker" cx={cp.cx} cy={cp.cy} r="5" />
|
|
411
|
+
</g>
|
|
412
|
+
{/if}
|
|
212
413
|
</svg>
|
|
414
|
+
|
|
415
|
+
<!-- Keyboard navigation overlay (FR-5) — a focusable, transparent hit layer
|
|
416
|
+
over the points. NOT aria-hidden: it is the accessible roving cursor.
|
|
417
|
+
Each rect announces its key + value; the focus ring is tokenised via
|
|
418
|
+
CSS. Absent unless keyboard nav is enabled. -->
|
|
419
|
+
{#if navEnabled}
|
|
420
|
+
<svg
|
|
421
|
+
class="st-scatterPlot__navLayer"
|
|
422
|
+
viewBox="0 0 {width} {height}"
|
|
423
|
+
preserveAspectRatio="xMidYMid meet"
|
|
424
|
+
width="100%"
|
|
425
|
+
height="100%"
|
|
426
|
+
role="group"
|
|
427
|
+
aria-label={`${label} — points de données`}
|
|
428
|
+
>
|
|
429
|
+
{#each points as p, i (p.index)}
|
|
430
|
+
<rect
|
|
431
|
+
bind:this={datapointRefs[i]}
|
|
432
|
+
class="st-scatterPlot__navDatum"
|
|
433
|
+
x={p.cx - NAV_HIT / 2}
|
|
434
|
+
y={p.cy - NAV_HIT / 2}
|
|
435
|
+
width={NAV_HIT}
|
|
436
|
+
height={NAV_HIT}
|
|
437
|
+
rx="3"
|
|
438
|
+
role="img"
|
|
439
|
+
tabindex={rovingTabIndex(i, focusedIndex, points.length)}
|
|
440
|
+
aria-label={datapointAriaLabel(p.datum.label ?? `${p.datum.x}, ${p.datum.y}`, p.datum.y)}
|
|
441
|
+
onkeydown={(event) => handleDatapointKeyDown(event, i)}
|
|
442
|
+
onfocus={() => {
|
|
443
|
+
focusedIndex = i;
|
|
444
|
+
emitHoverKey(i);
|
|
445
|
+
}}
|
|
446
|
+
/>
|
|
447
|
+
{/each}
|
|
448
|
+
</svg>
|
|
449
|
+
{/if}
|
|
213
450
|
</div>
|
|
214
451
|
|
|
215
452
|
<ChartDataList {label} items={dataValueItems} />
|
|
216
453
|
|
|
217
|
-
{#if
|
|
218
|
-
{@const p = points[
|
|
454
|
+
{#if activeIndex >= 0 && points[activeIndex]}
|
|
455
|
+
{@const p = points[activeIndex]}
|
|
219
456
|
<div class="st-scatterPlot__tooltip" role="presentation" style="left: {(p.cx / width) * 100}%; top: {(p.cy / height) * 100}%">
|
|
220
457
|
{#if p.datum.label}<span class="st-scatterPlot__tooltipLabel">{p.datum.label}</span>{/if}
|
|
221
458
|
<span class="st-scatterPlot__tooltipValue">x {p.datum.x} · y {p.datum.y}</span>
|
|
@@ -252,6 +489,23 @@
|
|
|
252
489
|
.st-scatterPlot__centroid--category6 { color: var(--st-semantic-data-category6); }
|
|
253
490
|
.st-scatterPlot__centroid--category7 { color: var(--st-semantic-data-category7); }
|
|
254
491
|
.st-scatterPlot__centroid--category8 { color: var(--st-semantic-data-category8); }
|
|
492
|
+
/* --- Annotation layer ----------------------------------------------------
|
|
493
|
+
Regions render BEHIND the points (color-mix tint, never raw opacity so the
|
|
494
|
+
data keeps contrast); lines/shapes/points/labels render ABOVE. */
|
|
495
|
+
.st-scatterPlot__annotationRegion { fill: color-mix(in srgb, var(--st-semantic-feedback-info) 12%, transparent); stroke: none; }
|
|
496
|
+
.st-scatterPlot__annotationLine { stroke: var(--st-semantic-feedback-info); stroke-width: 1.5; stroke-dasharray: 4 3; }
|
|
497
|
+
.st-scatterPlot__annotationShape { fill: color-mix(in srgb, var(--st-semantic-feedback-info) 14%, transparent); stroke: var(--st-semantic-feedback-info); stroke-width: 1.5; }
|
|
498
|
+
.st-scatterPlot__annotationPoint { fill: var(--st-semantic-feedback-info); stroke: var(--st-semantic-surface-default); stroke-width: 1.5; }
|
|
499
|
+
.st-scatterPlot__annotationLabel, .st-scatterPlot__annotationText { fill: var(--st-semantic-text-primary); font-size: 0.625rem; font-weight: 600; }
|
|
500
|
+
/* Data labels — per-point value/label, drawn on top. Token-only colour. */
|
|
501
|
+
.st-scatterPlot__dataLabel { fill: var(--st-semantic-text-primary); font-size: 0.6875rem; font-weight: 600; }
|
|
502
|
+
/* --- Crosshair layer (FR-3) — tokenised CROSSED pair + marker. -------------- */
|
|
503
|
+
.st-scatterPlot__crosshairLine { stroke: var(--st-semantic-border-strong); stroke-width: 1; stroke-dasharray: 3 3; opacity: 0.7; }
|
|
504
|
+
.st-scatterPlot__crosshairMarker { fill: currentColor; stroke: var(--st-semantic-surface-default); stroke-width: 2; }
|
|
505
|
+
/* --- Keyboard navigation layer (FR-5) — focusable transparent hit-rects. ---- */
|
|
506
|
+
.st-scatterPlot__navLayer { inset: 0; position: absolute; }
|
|
507
|
+
.st-scatterPlot__navDatum { fill: transparent; outline: none; }
|
|
508
|
+
.st-scatterPlot__navDatum:focus-visible { fill: color-mix(in srgb, var(--st-semantic-border-interactive) 12%, transparent); outline: 2px solid var(--st-semantic-border-interactive); outline-offset: 1px; }
|
|
255
509
|
@media (prefers-reduced-motion: reduce) {
|
|
256
510
|
.st-scatterPlot__point { transition: none; }
|
|
257
511
|
}
|
|
@@ -17,6 +17,8 @@ export type ScatterPlotCentroid = {
|
|
|
17
17
|
tone?: ScatterPlotTone;
|
|
18
18
|
label?: string;
|
|
19
19
|
};
|
|
20
|
+
import { type ChartAnnotation } from "./chartAnnotations.js";
|
|
21
|
+
import { type DataLabelsProp } from "./chartDataLabels.js";
|
|
20
22
|
type ScatterPlotProps = {
|
|
21
23
|
data: ScatterPlotDatum[];
|
|
22
24
|
width?: number;
|
|
@@ -29,6 +31,29 @@ type ScatterPlotProps = {
|
|
|
29
31
|
* coordinates are folded into the axis domain. Non-finite x/y are skipped.
|
|
30
32
|
*/
|
|
31
33
|
centroids?: ScatterPlotCentroid[];
|
|
34
|
+
/**
|
|
35
|
+
* Annotation overlay in DATA space (points, labels, axis lines, regions,
|
|
36
|
+
* polygons). Both axes are continuous (linear). Additive: absent ⇒ unchanged.
|
|
37
|
+
*/
|
|
38
|
+
annotations?: ChartAnnotation[];
|
|
39
|
+
/**
|
|
40
|
+
* Per-point value labels. `false`/absent → none. `true` → each point's value
|
|
41
|
+
* (the datum `label` wins when present). Object → `format`/`position`.
|
|
42
|
+
* Default position `top`. Labels are `aria-hidden`.
|
|
43
|
+
*/
|
|
44
|
+
dataLabels?: DataLabelsProp;
|
|
45
|
+
/**
|
|
46
|
+
* CONTROLLED synchronised hover key (FR-3). A point's key is its `label` when
|
|
47
|
+
* present, otherwise `"x,y"`. Absent (`undefined`) keeps the uncontrolled
|
|
48
|
+
* behaviour.
|
|
49
|
+
*/
|
|
50
|
+
hoverKey?: string | null;
|
|
51
|
+
/** Emitted on hover (the key) / leave (`null`); fired even while controlled. */
|
|
52
|
+
onHoverKeyChange?: (key: string | null) => void;
|
|
53
|
+
/** FR-5 — roving-tabindex keyboard navigation of the data points. */
|
|
54
|
+
keyboardNav?: boolean;
|
|
55
|
+
/** Emitted on Enter/Space select (the key) / Escape (`null`); enables nav. */
|
|
56
|
+
onSelectKey?: (key: string | null) => void;
|
|
32
57
|
label: string;
|
|
33
58
|
class?: string;
|
|
34
59
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ScatterPlot.svelte.d.ts","sourceRoot":"","sources":["../src/lib/ScatterPlot.svelte.ts"],"names":[],"mappings":"AAGE,MAAM,MAAM,eAAe,GACvB,WAAW,GAAG,WAAW,GAAG,WAAW,GAAG,WAAW,GACrD,WAAW,GAAG,WAAW,GAAG,WAAW,GAAG,WAAW,CAAC;AAE1D,MAAM,MAAM,gBAAgB,GAAG;IAC7B,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;IACV,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,eAAe,CAAC;IACvB;;;OAGG;IACH,CAAC,CAAC,EAAE,MAAM,CAAC;CACZ,CAAC;AAEF,2EAA2E;AAC3E,MAAM,MAAM,mBAAmB,GAAG;IAChC,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;IACV,IAAI,CAAC,EAAE,eAAe,CAAC;IACvB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,CAAC;
|
|
1
|
+
{"version":3,"file":"ScatterPlot.svelte.d.ts","sourceRoot":"","sources":["../src/lib/ScatterPlot.svelte.ts"],"names":[],"mappings":"AAGE,MAAM,MAAM,eAAe,GACvB,WAAW,GAAG,WAAW,GAAG,WAAW,GAAG,WAAW,GACrD,WAAW,GAAG,WAAW,GAAG,WAAW,GAAG,WAAW,CAAC;AAE1D,MAAM,MAAM,gBAAgB,GAAG;IAC7B,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;IACV,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,eAAe,CAAC;IACvB;;;OAGG;IACH,CAAC,CAAC,EAAE,MAAM,CAAC;CACZ,CAAC;AAEF,2EAA2E;AAC3E,MAAM,MAAM,mBAAmB,GAAG;IAChC,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;IACV,IAAI,CAAC,EAAE,eAAe,CAAC;IACvB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,CAAC;AAIJ,OAAO,EAIH,KAAK,eAAe,EACrB,MAAM,uBAAuB,CAAC;AACjC,OAAO,EAAwC,KAAK,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAK/F,KAAK,gBAAgB,GAAG;IACtB,IAAI,EAAE,gBAAgB,EAAE,CAAC;IACzB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB;;;OAGG;IACH,SAAS,CAAC,EAAE,mBAAmB,EAAE,CAAC;IAClC;;;OAGG;IACH,WAAW,CAAC,EAAE,eAAe,EAAE,CAAC;IAChC;;;;OAIG;IACH,UAAU,CAAC,EAAE,cAAc,CAAC;IAC5B;;;;OAIG;IACH,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,gFAAgF;IAChF,gBAAgB,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,KAAK,IAAI,CAAC;IAChD,qEAAqE;IACrE,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,8EAA8E;IAC9E,WAAW,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,KAAK,IAAI,CAAC;IAC3C,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,CAAC;AAsWJ,QAAA,MAAM,WAAW,sDAAwC,CAAC;AAC1D,KAAK,WAAW,GAAG,UAAU,CAAC,OAAO,WAAW,CAAC,CAAC;AAClD,eAAe,WAAW,CAAC"}
|
|
@@ -58,8 +58,11 @@
|
|
|
58
58
|
let internal = $state<Set<string>>(new Set());
|
|
59
59
|
const selectedValues = $derived(controlled ? toSet(value) : internal);
|
|
60
60
|
|
|
61
|
-
// --- Row registry
|
|
62
|
-
//
|
|
61
|
+
// --- Row registry. Rows are stored in INSERTION order (registration is O(1));
|
|
62
|
+
// the DOM-ordered view is computed LAZILY (see `orderedEntries`) and only
|
|
63
|
+
// when a consumer actually needs visual order (arrow nav / roving tab stop).
|
|
64
|
+
// Sorting eagerly on every register() was O(n) per mount → O(n²) for the
|
|
65
|
+
// whole list (issue #26); deferring it makes a large list mount in O(n).
|
|
63
66
|
type Entry = { el: HTMLElement; value: string | undefined; disabled?: boolean };
|
|
64
67
|
let entries = $state<Entry[]>([]);
|
|
65
68
|
|
|
@@ -76,17 +79,28 @@
|
|
|
76
79
|
});
|
|
77
80
|
}
|
|
78
81
|
|
|
82
|
+
// DOM-ordered view of the registry. Memoised by `$derived.by` so the O(n log n)
|
|
83
|
+
// `compareDocumentPosition` sort runs at most ONCE per registry change (a batch
|
|
84
|
+
// of mounts in the same tick collapses into a single recompute), not once per
|
|
85
|
+
// register() call. ORDER-dependent readers (`navigate`, `effectiveTabStop`'s
|
|
86
|
+
// "first enabled row") read THIS so visual order is correct regardless of
|
|
87
|
+
// registration timing; order-INDEPENDENT lookups (`valueOf`/`isSelected`,
|
|
88
|
+
// disabled-membership) read the raw `entries`. register() itself stays O(1).
|
|
89
|
+
const orderedEntries = $derived.by(() => sortByDom(entries));
|
|
90
|
+
|
|
79
91
|
// register/unregister are called from each row's $effect. They read AND write
|
|
80
92
|
// `entries`, so the read must be untracked — otherwise the calling effect would
|
|
81
93
|
// subscribe to `entries`, and writing it would re-run the effect forever.
|
|
82
|
-
//
|
|
83
|
-
//
|
|
94
|
+
// register() APPENDS in insertion order (O(1)); the DOM sort is deferred to the
|
|
95
|
+
// lazy `orderedEntries`. Disabled rows are registered with disabled:true so
|
|
96
|
+
// navigate() can skip them explicitly, making the skip correct even when the
|
|
97
|
+
// disabled state changes mid-session.
|
|
84
98
|
function register(el: HTMLElement, rowValue: string | undefined, rowDisabled = false): () => void {
|
|
85
99
|
untrack(() => {
|
|
86
|
-
entries =
|
|
100
|
+
entries = [
|
|
87
101
|
...entries.filter((e) => e.el !== el),
|
|
88
102
|
{ el, value: rowValue, disabled: rowDisabled }
|
|
89
|
-
]
|
|
103
|
+
];
|
|
90
104
|
});
|
|
91
105
|
return () => {
|
|
92
106
|
untrack(() => {
|
|
@@ -103,7 +117,8 @@
|
|
|
103
117
|
const entry = entries.find((e) => e.el === tabStopEl);
|
|
104
118
|
if (entry && !entry.disabled) return tabStopEl;
|
|
105
119
|
}
|
|
106
|
-
|
|
120
|
+
// "First enabled row" must be in DOM order, so read the ordered view.
|
|
121
|
+
return orderedEntries.find((e) => !e.disabled)?.el ?? null;
|
|
107
122
|
});
|
|
108
123
|
|
|
109
124
|
// Si la row qui détient le focus DOM devient disabled (in-place, sans unmount),
|
|
@@ -161,38 +176,42 @@
|
|
|
161
176
|
}
|
|
162
177
|
|
|
163
178
|
function navigate(el: HTMLElement, key: string) {
|
|
164
|
-
|
|
165
|
-
|
|
179
|
+
// Keyboard navigation walks rows in VISUAL (DOM) order, so read the lazily
|
|
180
|
+
// sorted view here. This is the first point the deferred sort is forced — the
|
|
181
|
+
// O(n²) register-time sort storm is gone, the sort runs once on demand.
|
|
182
|
+
const ordered = orderedEntries;
|
|
183
|
+
if (ordered.length === 0) return;
|
|
184
|
+
const idx = ordered.findIndex((e) => e.el === el);
|
|
166
185
|
if (idx === -1) return;
|
|
167
186
|
|
|
168
187
|
let targetIdx: number | null = null;
|
|
169
188
|
|
|
170
189
|
if (key === "ArrowDown" || key === "ArrowRight") {
|
|
171
190
|
// Walk forward from current position, find the next non-disabled entry.
|
|
172
|
-
for (let i = idx + 1; i <
|
|
173
|
-
if (!
|
|
191
|
+
for (let i = idx + 1; i < ordered.length; i++) {
|
|
192
|
+
if (!ordered[i].disabled) { targetIdx = i; break; }
|
|
174
193
|
}
|
|
175
194
|
} else if (key === "ArrowUp" || key === "ArrowLeft") {
|
|
176
195
|
// Walk backward from current position, find the previous non-disabled entry.
|
|
177
196
|
for (let i = idx - 1; i >= 0; i--) {
|
|
178
|
-
if (!
|
|
197
|
+
if (!ordered[i].disabled) { targetIdx = i; break; }
|
|
179
198
|
}
|
|
180
199
|
} else if (key === "Home") {
|
|
181
200
|
// First non-disabled entry.
|
|
182
|
-
for (let i = 0; i <
|
|
183
|
-
if (!
|
|
201
|
+
for (let i = 0; i < ordered.length; i++) {
|
|
202
|
+
if (!ordered[i].disabled) { targetIdx = i; break; }
|
|
184
203
|
}
|
|
185
204
|
} else if (key === "End") {
|
|
186
205
|
// Last non-disabled entry.
|
|
187
|
-
for (let i =
|
|
188
|
-
if (!
|
|
206
|
+
for (let i = ordered.length - 1; i >= 0; i--) {
|
|
207
|
+
if (!ordered[i].disabled) { targetIdx = i; break; }
|
|
189
208
|
}
|
|
190
209
|
}
|
|
191
210
|
|
|
192
211
|
// If no target found (all remaining are disabled, or already at boundary), stay put.
|
|
193
212
|
if (targetIdx === null) return;
|
|
194
213
|
|
|
195
|
-
const target =
|
|
214
|
+
const target = ordered[targetIdx]?.el;
|
|
196
215
|
if (target) {
|
|
197
216
|
tabStopEl = target;
|
|
198
217
|
target.focus();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SelectableList.svelte.d.ts","sourceRoot":"","sources":["../src/lib/SelectableList.svelte.ts"],"names":[],"mappings":"AAGE,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,QAAQ,CAAC;AAEtC,MAAM,MAAM,mBAAmB,GAAG;IAChC,+DAA+D;IAC/D,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,+EAA+E;IAC/E,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB;;;OAGG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB;;;;OAIG;IACH,KAAK,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,GAAG,IAAI,CAAC;IACjC;;;;OAIG;IACH,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,GAAG,IAAI,KAAK,IAAI,CAAC;IACrD,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB,CAAC;
|
|
1
|
+
{"version":3,"file":"SelectableList.svelte.d.ts","sourceRoot":"","sources":["../src/lib/SelectableList.svelte.ts"],"names":[],"mappings":"AAGE,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,QAAQ,CAAC;AAEtC,MAAM,MAAM,mBAAmB,GAAG;IAChC,+DAA+D;IAC/D,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,+EAA+E;IAC/E,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB;;;OAGG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB;;;;OAIG;IACH,KAAK,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,GAAG,IAAI,CAAC;IACjC;;;;OAIG;IACH,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,GAAG,IAAI,KAAK,IAAI,CAAC;IACrD,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB,CAAC;AA6NJ,QAAA,MAAM,cAAc,yDAAwC,CAAC;AAC7D,KAAK,cAAc,GAAG,UAAU,CAAC,OAAO,cAAc,CAAC,CAAC;AACxD,eAAe,cAAc,CAAC"}
|
|
@@ -60,6 +60,16 @@
|
|
|
60
60
|
trailing?: Snippet;
|
|
61
61
|
/** Main content. */
|
|
62
62
|
children?: Snippet;
|
|
63
|
+
/**
|
|
64
|
+
* Optional secondary line (the "legend") rendered MUTED and smaller UNDER
|
|
65
|
+
* `children`. When present the content column stacks vertically (a
|
|
66
|
+
* `--hasCaption` modifier); when absent the row stays single-line and
|
|
67
|
+
* byte-identical. The caption joins the row's accessible name by default (the
|
|
68
|
+
* SR reads "label, caption"); wrap it `aria-hidden` if it is purely
|
|
69
|
+
* decorative. MUST NOT contain interactive controls — a row is a single tab
|
|
70
|
+
* stop.
|
|
71
|
+
*/
|
|
72
|
+
caption?: Snippet;
|
|
63
73
|
class?: string;
|
|
64
74
|
};
|
|
65
75
|
</script>
|
|
@@ -77,6 +87,7 @@
|
|
|
77
87
|
leading,
|
|
78
88
|
trailing,
|
|
79
89
|
children,
|
|
90
|
+
caption,
|
|
80
91
|
class: className
|
|
81
92
|
}: SelectableRowProps = $props();
|
|
82
93
|
|
|
@@ -125,6 +136,7 @@
|
|
|
125
136
|
isSelected ? "st-selectableRow--selected" : null,
|
|
126
137
|
disabled ? "st-selectableRow--disabled" : null,
|
|
127
138
|
accentBar ? "st-selectableRow--accentBar" : null,
|
|
139
|
+
caption ? "st-selectableRow--hasCaption" : null,
|
|
128
140
|
className
|
|
129
141
|
]
|
|
130
142
|
.filter(Boolean)
|
|
@@ -190,7 +202,17 @@
|
|
|
190
202
|
{#if leading}
|
|
191
203
|
<span class="st-selectableRow__leading">{@render leading()}</span>
|
|
192
204
|
{/if}
|
|
193
|
-
|
|
205
|
+
{#if caption}
|
|
206
|
+
<!-- Caption present: the content column stacks the primary label over a muted
|
|
207
|
+
second line. Both lines truncate independently (each min-width:0 + ellipsis)
|
|
208
|
+
so a long caption never pushes the row width. -->
|
|
209
|
+
<span class="st-selectableRow__content st-selectableRow__content--stacked">
|
|
210
|
+
<span class="st-selectableRow__label">{@render children?.()}</span>
|
|
211
|
+
<span class="st-selectableRow__caption">{@render caption()}</span>
|
|
212
|
+
</span>
|
|
213
|
+
{:else}
|
|
214
|
+
<span class="st-selectableRow__content">{@render children?.()}</span>
|
|
215
|
+
{/if}
|
|
194
216
|
{#if trailing}
|
|
195
217
|
<span class="st-selectableRow__trailing">{@render trailing()}</span>
|
|
196
218
|
{/if}
|
|
@@ -300,6 +322,36 @@
|
|
|
300
322
|
white-space: nowrap;
|
|
301
323
|
}
|
|
302
324
|
|
|
325
|
+
/* Caption variant (additive). Rows WITHOUT a caption keep the single-line
|
|
326
|
+
`.st-selectableRow__content` above byte-identically (no `--stacked` rule
|
|
327
|
+
applies). `--stacked` overlays a vertical column: the primary `__label` keeps
|
|
328
|
+
its own single-line ellipsis, and the muted `__caption` truncates
|
|
329
|
+
independently so a long legend never pushes the row width. Every leaf falls
|
|
330
|
+
back to a base literal so a theme that emits no
|
|
331
|
+
`--st-component-selectableRow-caption*` renders the caption identically. */
|
|
332
|
+
.st-selectableRow__content--stacked {
|
|
333
|
+
display: flex;
|
|
334
|
+
flex-direction: column;
|
|
335
|
+
/* The column stack drops the inline ellipsis/nowrap (each line truncates on
|
|
336
|
+
its own child); keep min-width:0 so the column can shrink and ellipsize. */
|
|
337
|
+
overflow: visible;
|
|
338
|
+
white-space: normal;
|
|
339
|
+
gap: var(--st-component-selectableRow-captionGap, 0.125rem);
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
.st-selectableRow__label,
|
|
343
|
+
.st-selectableRow__caption {
|
|
344
|
+
min-width: 0;
|
|
345
|
+
overflow: hidden;
|
|
346
|
+
text-overflow: ellipsis;
|
|
347
|
+
white-space: nowrap;
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
.st-selectableRow__caption {
|
|
351
|
+
color: var(--st-component-selectableRow-captionColor, var(--st-semantic-text-muted));
|
|
352
|
+
font-size: var(--st-component-selectableRow-captionFontSize, 0.75rem);
|
|
353
|
+
}
|
|
354
|
+
|
|
303
355
|
@media (prefers-reduced-motion: reduce) {
|
|
304
356
|
.st-selectableRow { transition: none; }
|
|
305
357
|
}
|
|
@@ -56,6 +56,16 @@ export type SelectableRowProps = {
|
|
|
56
56
|
trailing?: Snippet;
|
|
57
57
|
/** Main content. */
|
|
58
58
|
children?: Snippet;
|
|
59
|
+
/**
|
|
60
|
+
* Optional secondary line (the "legend") rendered MUTED and smaller UNDER
|
|
61
|
+
* `children`. When present the content column stacks vertically (a
|
|
62
|
+
* `--hasCaption` modifier); when absent the row stays single-line and
|
|
63
|
+
* byte-identical. The caption joins the row's accessible name by default (the
|
|
64
|
+
* SR reads "label, caption"); wrap it `aria-hidden` if it is purely
|
|
65
|
+
* decorative. MUST NOT contain interactive controls — a row is a single tab
|
|
66
|
+
* stop.
|
|
67
|
+
*/
|
|
68
|
+
caption?: Snippet;
|
|
59
69
|
class?: string;
|
|
60
70
|
};
|
|
61
71
|
declare const SelectableRow: import("svelte").Component<SelectableRowProps, {}, "selected">;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SelectableRow.svelte.d.ts","sourceRoot":"","sources":["../src/lib/SelectableRow.svelte.ts"],"names":[],"mappings":"AAGE,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,QAAQ,CAAC;AAEtC;;;;;;;GAOG;AACH,eAAO,MAAM,mBAAmB,eAA+B,CAAC;AAEhE,MAAM,MAAM,qBAAqB,GAAG;IAClC,gEAAgE;IAChE,QAAQ,CAAC,OAAO,EAAE,IAAI,CAAC;IACvB,wDAAwD;IACxD,QAAQ,CAAC,QAAQ,EAAE,QAAQ,CAAC;IAC5B,wIAAwI;IACxI,QAAQ,EAAE,CAAC,EAAE,EAAE,WAAW,EAAE,KAAK,EAAE,MAAM,GAAG,SAAS,EAAE,QAAQ,CAAC,EAAE,OAAO,KAAK,MAAM,IAAI,CAAC;IACzF,uDAAuD;IACvD,UAAU,EAAE,CAAC,EAAE,EAAE,WAAW,KAAK,OAAO,CAAC;IACzC,iFAAiF;IACjF,SAAS,EAAE,CAAC,EAAE,EAAE,WAAW,KAAK,OAAO,CAAC;IACxC,6EAA6E;IAC7E,QAAQ,EAAE,CAAC,EAAE,EAAE,WAAW,KAAK,IAAI,CAAC;IACpC,wDAAwD;IACxD,QAAQ,EAAE,CAAC,EAAE,EAAE,WAAW,KAAK,IAAI,CAAC;IACpC,gDAAgD;IAChD,QAAQ,EAAE,CAAC,EAAE,EAAE,WAAW,EAAE,GAAG,EAAE,MAAM,KAAK,IAAI,CAAC;CAClD,CAAC;AAEF,MAAM,MAAM,kBAAkB,GAAG;IAC/B;;;;OAIG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,8EAA8E;IAC9E,QAAQ,CAAC,EAAE,CAAC,QAAQ,EAAE,OAAO,KAAK,IAAI,CAAC;IACvC,iCAAiC;IACjC,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,+EAA+E;IAC/E,KAAK,CAAC,EAAE,MAAM,CAAC;IACf;;;;OAIG;IACH,IAAI,CAAC,EAAE,MAAM,CAAC;IACd;;;OAGG;IACH,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,oCAAoC;IACpC,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,mCAAmC;IACnC,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,oBAAoB;IACpB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,CAAC;
|
|
1
|
+
{"version":3,"file":"SelectableRow.svelte.d.ts","sourceRoot":"","sources":["../src/lib/SelectableRow.svelte.ts"],"names":[],"mappings":"AAGE,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,QAAQ,CAAC;AAEtC;;;;;;;GAOG;AACH,eAAO,MAAM,mBAAmB,eAA+B,CAAC;AAEhE,MAAM,MAAM,qBAAqB,GAAG;IAClC,gEAAgE;IAChE,QAAQ,CAAC,OAAO,EAAE,IAAI,CAAC;IACvB,wDAAwD;IACxD,QAAQ,CAAC,QAAQ,EAAE,QAAQ,CAAC;IAC5B,wIAAwI;IACxI,QAAQ,EAAE,CAAC,EAAE,EAAE,WAAW,EAAE,KAAK,EAAE,MAAM,GAAG,SAAS,EAAE,QAAQ,CAAC,EAAE,OAAO,KAAK,MAAM,IAAI,CAAC;IACzF,uDAAuD;IACvD,UAAU,EAAE,CAAC,EAAE,EAAE,WAAW,KAAK,OAAO,CAAC;IACzC,iFAAiF;IACjF,SAAS,EAAE,CAAC,EAAE,EAAE,WAAW,KAAK,OAAO,CAAC;IACxC,6EAA6E;IAC7E,QAAQ,EAAE,CAAC,EAAE,EAAE,WAAW,KAAK,IAAI,CAAC;IACpC,wDAAwD;IACxD,QAAQ,EAAE,CAAC,EAAE,EAAE,WAAW,KAAK,IAAI,CAAC;IACpC,gDAAgD;IAChD,QAAQ,EAAE,CAAC,EAAE,EAAE,WAAW,EAAE,GAAG,EAAE,MAAM,KAAK,IAAI,CAAC;CAClD,CAAC;AAEF,MAAM,MAAM,kBAAkB,GAAG;IAC/B;;;;OAIG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,8EAA8E;IAC9E,QAAQ,CAAC,EAAE,CAAC,QAAQ,EAAE,OAAO,KAAK,IAAI,CAAC;IACvC,iCAAiC;IACjC,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,+EAA+E;IAC/E,KAAK,CAAC,EAAE,MAAM,CAAC;IACf;;;;OAIG;IACH,IAAI,CAAC,EAAE,MAAM,CAAC;IACd;;;OAGG;IACH,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,oCAAoC;IACpC,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,mCAAmC;IACnC,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,oBAAoB;IACpB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB;;;;;;;;OAQG;IACH,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,CAAC;AA2IJ,QAAA,MAAM,aAAa,gEAAwC,CAAC;AAC5D,KAAK,aAAa,GAAG,UAAU,CAAC,OAAO,aAAa,CAAC,CAAC;AACtD,eAAe,aAAa,CAAC"}
|