@pond-ts/charts 0.36.0 → 0.38.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +80 -3
- package/dist/ChartRow.js +28 -3
- package/dist/Layers.js +23 -3
- package/dist/XAxis.d.ts +14 -1
- package/dist/XAxis.js +71 -11
- package/dist/YAxis.d.ts +25 -1
- package/dist/YAxis.js +38 -13
- package/dist/annotations.d.ts +25 -3
- package/dist/annotations.js +28 -10
- package/dist/chip.d.ts +36 -0
- package/dist/chip.js +85 -1
- package/dist/context.d.ts +16 -1
- package/dist/domain.d.ts +6 -1
- package/dist/domain.js +15 -1
- package/dist/index.d.ts +2 -0
- package/dist/index.js +3 -0
- package/dist/indicators.d.ts +105 -0
- package/dist/indicators.js +114 -0
- package/dist/theme.d.ts +11 -0
- package/dist/tracker.d.ts +1 -1
- package/dist/tracker.js +4 -0
- package/package.json +3 -3
package/CHANGELOG.md
CHANGED
|
@@ -8,7 +8,9 @@ The `@pond-ts` packages — `pond-ts`, `@pond-ts/react`, `@pond-ts/charts`, and
|
|
|
8
8
|
them all. Pre-1.0: minor bumps may include new features and type-level changes;
|
|
9
9
|
patch bumps are strictly additive.
|
|
10
10
|
|
|
11
|
-
[Unreleased]: https://github.com/pjm17971/pond-ts/compare/v0.
|
|
11
|
+
[Unreleased]: https://github.com/pjm17971/pond-ts/compare/v0.38.0...HEAD
|
|
12
|
+
[0.38.0]: https://github.com/pjm17971/pond-ts/compare/v0.37.0...v0.38.0
|
|
13
|
+
[0.37.0]: https://github.com/pjm17971/pond-ts/compare/v0.36.0...v0.37.0
|
|
12
14
|
[0.36.0]: https://github.com/pjm17971/pond-ts/compare/v0.35.0...v0.36.0
|
|
13
15
|
[0.35.0]: https://github.com/pjm17971/pond-ts/compare/v0.34.1...v0.35.0
|
|
14
16
|
[0.34.1]: https://github.com/pjm17971/pond-ts/compare/v0.34.0...v0.34.1
|
|
@@ -32,6 +34,81 @@ patch bumps are strictly additive.
|
|
|
32
34
|
[0.19.0]: https://github.com/pjm17971/pond-ts/compare/v0.18.0...v0.19.0
|
|
33
35
|
[0.18.0]: https://github.com/pjm17971/pond-ts/compare/v0.17.1...v0.18.0
|
|
34
36
|
|
|
37
|
+
## [0.38.0] — 2026-07-03
|
|
38
|
+
|
|
39
|
+
A `@pond-ts/charts` release: **axis-edge value indicators + the crosshair
|
|
40
|
+
cursor** — the ChartIQ / Yahoo-Finance price-tag family, driven by the Tidal
|
|
41
|
+
terminal. `pond-ts`, `@pond-ts/react`, and `@pond-ts/fit` carry no code changes —
|
|
42
|
+
republished in lock-step (peer ranges widen to `^0.38.0`).
|
|
43
|
+
|
|
44
|
+
### Added
|
|
45
|
+
|
|
46
|
+
- `@pond-ts/charts`: **`<YAxisIndicator>` + `createLiveValue`** — a value pill
|
|
47
|
+
pinned to a y-axis edge, decoupled from the series' last point. A `LiveValue`
|
|
48
|
+
`source` updates it at high frequency **without re-rendering the chart** (only
|
|
49
|
+
the subscribed pill repaints). Props: `value` / `source`, `axis`, `side`,
|
|
50
|
+
`color`, `format`, `line` (dashed guide), `pointer` (callout triangle).
|
|
51
|
+
- `@pond-ts/charts`: **`cursor="crosshair"`** `CursorMode` — a synced vertical
|
|
52
|
+
line + per-series dots, each series' value pinned to its y-axis and the hovered
|
|
53
|
+
time pinned to the x-axis.
|
|
54
|
+
- `@pond-ts/charts`: **`indicator`** opt-in on `<Baseline>` (a y-axis value pill)
|
|
55
|
+
and `<Marker>` (an x-axis time pill, with a connector down to the mark).
|
|
56
|
+
- `@pond-ts/charts`: `<Baseline labelSide>` (`left` / `right`) + `labelPosition`
|
|
57
|
+
(`center` on the line / `above` it) for the near-line label chip.
|
|
58
|
+
- `@pond-ts/charts`: `<Region edges>` (default `true`; `false` = shaded fill with
|
|
59
|
+
no side outlines).
|
|
60
|
+
- `@pond-ts/charts`: `axisPillStyle`, `contrastText`, `pointerStyle` chip helpers
|
|
61
|
+
are exported.
|
|
62
|
+
|
|
63
|
+
### Changed
|
|
64
|
+
|
|
65
|
+
- `@pond-ts/charts`: axis indicator pills are **solid** (colour fill +
|
|
66
|
+
auto-contrast text), aligned to the tick-label row, and **always show the axis
|
|
67
|
+
coordinate** — never a custom label (a label stays the in-plot chip).
|
|
68
|
+
- `@pond-ts/charts`: cursor flag / inline chips now have **square corners**; the
|
|
69
|
+
cursor **time** atop a flag stack renders as plain text (no chip background).
|
|
70
|
+
- `@pond-ts/charts`: Storybook reorganized into a feature-axis reference tree with
|
|
71
|
+
systematic per-prop coverage (dev-only; stories are excluded from the package).
|
|
72
|
+
|
|
73
|
+
### Fixed
|
|
74
|
+
|
|
75
|
+
- `@pond-ts/charts`: the crosshair x-axis pill used the container's time formatter
|
|
76
|
+
(showing a raw number on a value axis) — it now uses the axis's own resolved
|
|
77
|
+
formatter, matching the ticks. The crosshair also no longer double-renders the
|
|
78
|
+
time (a stray per-row chip alongside the x-axis pill).
|
|
79
|
+
|
|
80
|
+
## [0.37.0] — 2026-07-02
|
|
81
|
+
|
|
82
|
+
A `@pond-ts/charts` release: the axis wave — label, tick, and domain controls
|
|
83
|
+
driven by the Tidal terminal's friction. `pond-ts`, `@pond-ts/react`, and
|
|
84
|
+
`@pond-ts/fit` carry no code changes — republished in lock-step (peer ranges
|
|
85
|
+
widen to `^0.37.0`).
|
|
86
|
+
|
|
87
|
+
### Added
|
|
88
|
+
|
|
89
|
+
- **Charts — axis title typography (`theme.axis.title`).** The rotated y-axis
|
|
90
|
+
title now renders a touch larger than the ticks by default and is fully
|
|
91
|
+
themeable (`{ color, size, opacity }`, shared with the x-axis label). (#318)
|
|
92
|
+
- **Charts — `YAxis labelPlacement`.** `'rotated'` (default) or `'top'` — a
|
|
93
|
+
horizontal title above the axis, aligned to the axis line, in a reserved
|
|
94
|
+
header band that clears the top tick. (#318, #320)
|
|
95
|
+
- **Charts — `XAxis align`.** `'center'` (**new default**), `'auto'` (previous
|
|
96
|
+
behaviour: centred but first/last end-anchored), or `'right'` (label beside an
|
|
97
|
+
extended tick). (#318)
|
|
98
|
+
- **Charts — `YAxis pad`.** Fractional headroom added to each side of the
|
|
99
|
+
resolved domain (`0` default) — lifts a tight domain off the plot edges
|
|
100
|
+
without hand-computing bounds. (#319)
|
|
101
|
+
- **Charts — `YAxis boundaryLabels`.** `false` drops the top & bottom tick
|
|
102
|
+
numbers (gridlines stay) for stacked layouts where the edge labels crowd. (#319)
|
|
103
|
+
- **Charts — new `Charts/Axes` Storybook gallery** covering the above. (#318)
|
|
104
|
+
|
|
105
|
+
### Changed
|
|
106
|
+
|
|
107
|
+
- **Charts — domain-extreme y-tick labels now clamp inside the row** instead of
|
|
108
|
+
half-overflowing the top/bottom edge (resolves Tidal friction F-charts-6). (#319)
|
|
109
|
+
- **Charts — `XAxis` tick-label default is now `'center'`** (was the
|
|
110
|
+
end-anchored `'auto'`). Pass `align="auto"` for the old behaviour. (#318)
|
|
111
|
+
|
|
35
112
|
## [0.36.0] — 2026-07-02
|
|
36
113
|
|
|
37
114
|
A `@pond-ts/charts` release: a CSS-custom-property → theme bridge so a canvas
|
|
@@ -77,7 +154,7 @@ lock-step (their `pond-ts` / `@pond-ts/react` peer ranges widen to `^0.35.0`).
|
|
|
77
154
|
(`[6, 4]` dashed, `[2, 3]` ≈ dotted; omit or `[]` = solid) applied to the
|
|
78
155
|
series stroke. Lets a theme set a **modeled / forecast** line (e.g. GARCH
|
|
79
156
|
vol) apart from an observed one at a glance. Distinct from a `GapMode`'s
|
|
80
|
-
inferred gap-bridge dashing (which marks
|
|
157
|
+
inferred gap-bridge dashing (which marks _missing data_, not the whole
|
|
81
158
|
line). Additive: existing themes are unaffected; a solid line never touches
|
|
82
159
|
`setLineDash`. New `Charts/LineChart → LineStyles` story. (#313)
|
|
83
160
|
|
|
@@ -116,7 +193,7 @@ Tidal wire-format spike. `@pond-ts/react`, `@pond-ts/charts`, and
|
|
|
116
193
|
- **`TimeSeries.fromColumns`** — the columnar (struct-of-arrays) ingress,
|
|
117
194
|
the counterpart to `fromJSON`'s row-tuple shape. Accepts either a plain
|
|
118
195
|
`number[]` or a `Float64Array` per column — one polymorphic door, so a
|
|
119
|
-
wire format only changes the
|
|
196
|
+
wire format only changes the _decoder_, not the ingest. `Float64Array`
|
|
120
197
|
columns are adopted directly (zero-copy); `number[]` columns are copied.
|
|
121
198
|
A `null`/`undefined` cell or a non-finite value (`NaN`/`Infinity`) is a
|
|
122
199
|
gap, identically across both input shapes. Enforces the same
|
package/dist/ChartRow.js
CHANGED
|
@@ -12,6 +12,10 @@ const IMPLICIT_AXIS_ID = '__default__';
|
|
|
12
12
|
/** Axis tick count for the per-axis formatter — matches `<YAxis>`'s tick count
|
|
13
13
|
* so the readout formatter is calibrated exactly as the labels are. */
|
|
14
14
|
const AXIS_TICK_COUNT = 5;
|
|
15
|
+
/** Vertical band (px) reserved above the plot for a `labelPlacement="top"` axis
|
|
16
|
+
* title, so it clears the top tick + plotted data. Sized for the default title
|
|
17
|
+
* (~`font.size + 1`); a much larger themed title may want more room. */
|
|
18
|
+
const TOP_LABEL_HEADER = 16;
|
|
15
19
|
/**
|
|
16
20
|
* A horizontal band sharing the container's time axis. `ChartRow` owns the
|
|
17
21
|
* **horizontal layout** (axes left/right around a `<Layers>` plot area) and
|
|
@@ -91,6 +95,8 @@ export function ChartRow({ height, cursor, children }) {
|
|
|
91
95
|
width: 0,
|
|
92
96
|
min: undefined,
|
|
93
97
|
max: undefined,
|
|
98
|
+
pad: 0,
|
|
99
|
+
labelPlacement: 'rotated',
|
|
94
100
|
format: undefined,
|
|
95
101
|
tickValues: undefined,
|
|
96
102
|
index: 0,
|
|
@@ -126,6 +132,11 @@ export function ChartRow({ height, cursor, children }) {
|
|
|
126
132
|
const containerLeftSlots = container.leftSlots;
|
|
127
133
|
const containerRightSlots = container.rightSlots;
|
|
128
134
|
const { axisSlots, leftPad, rightPad } = useMemo(() => placeAxisSlots(leftAxes, rightAxes, containerLeftSlots, containerRightSlots), [leftAxes, rightAxes, containerLeftSlots, containerRightSlots]);
|
|
135
|
+
// Header band reserved at the top of the plot when any axis draws a `'top'`
|
|
136
|
+
// title — the scale range then starts below it (see below).
|
|
137
|
+
const topHeader = effectiveAxes.some((ax) => ax.labelPlacement === 'top')
|
|
138
|
+
? TOP_LABEL_HEADER
|
|
139
|
+
: 0;
|
|
129
140
|
// One y-scale per axis. A layer counts toward an axis when its (late-resolved)
|
|
130
141
|
// axis id matches; `resolveYDomain` handles the auto-fit + empty/flat/inverted
|
|
131
142
|
// edges. yExtent() is O(points), so only walk the layers when a bound auto-fits.
|
|
@@ -137,11 +148,15 @@ export function ChartRow({ height, cursor, children }) {
|
|
|
137
148
|
.filter((entry) => (entry.axisId ?? defaultAxisId) === ax.id)
|
|
138
149
|
.map((entry) => entry.layer.yExtent())
|
|
139
150
|
: [];
|
|
140
|
-
const [lo, hi] = resolveYDomain(ax.min, ax.max, extents);
|
|
141
|
-
|
|
151
|
+
const [lo, hi] = resolveYDomain(ax.min, ax.max, extents, ax.pad);
|
|
152
|
+
// Reserve a header band at the top when any axis draws a `'top'` title,
|
|
153
|
+
// so the title clears the top tick + plot (the whole row shifts down
|
|
154
|
+
// uniformly, keeping stacked axes aligned). No top titles ⇒ range top 0,
|
|
155
|
+
// so nothing changes for existing charts.
|
|
156
|
+
map.set(ax.id, scaleLinear().domain([lo, hi]).range([height, topHeader]));
|
|
142
157
|
}
|
|
143
158
|
return map;
|
|
144
|
-
}, [effectiveAxes, layerList, height, defaultAxisId]);
|
|
159
|
+
}, [effectiveAxes, layerList, height, defaultAxisId, topHeader]);
|
|
145
160
|
// A value formatter per axis (its `format` resolved against its scale) — shared
|
|
146
161
|
// by the axis tick labels and the cursor readout so a value reads the same.
|
|
147
162
|
const formats = useMemo(() => {
|
|
@@ -164,6 +179,14 @@ export function ChartRow({ height, cursor, children }) {
|
|
|
164
179
|
}
|
|
165
180
|
return map;
|
|
166
181
|
}, [effectiveAxes]);
|
|
182
|
+
// Which side each axis sits on — so an axis-edge overlay (the crosshair's
|
|
183
|
+
// value pills) hugs the correct gutter without re-deriving from the specs.
|
|
184
|
+
const axisSides = useMemo(() => {
|
|
185
|
+
const map = new Map();
|
|
186
|
+
for (const ax of effectiveAxes)
|
|
187
|
+
map.set(ax.id, ax.side);
|
|
188
|
+
return map;
|
|
189
|
+
}, [effectiveAxes]);
|
|
167
190
|
const frame = useMemo(() => ({
|
|
168
191
|
height,
|
|
169
192
|
cursor,
|
|
@@ -172,6 +195,7 @@ export function ChartRow({ height, cursor, children }) {
|
|
|
172
195
|
yScales,
|
|
173
196
|
formats,
|
|
174
197
|
tickValues,
|
|
198
|
+
axisSides,
|
|
175
199
|
defaultAxisId,
|
|
176
200
|
axisSlots,
|
|
177
201
|
registerAxis,
|
|
@@ -187,6 +211,7 @@ export function ChartRow({ height, cursor, children }) {
|
|
|
187
211
|
yScales,
|
|
188
212
|
formats,
|
|
189
213
|
tickValues,
|
|
214
|
+
axisSides,
|
|
190
215
|
defaultAxisId,
|
|
191
216
|
axisSlots,
|
|
192
217
|
registerAxis,
|
package/dist/Layers.js
CHANGED
|
@@ -5,7 +5,7 @@ import { drawGrid } from './grid.js';
|
|
|
5
5
|
import { cursorParts } from './tracker.js';
|
|
6
6
|
import { resolveSelection } from './select.js';
|
|
7
7
|
import { panRange, zoomRange } from './viewport.js';
|
|
8
|
-
import { flagChipStyle, flagChipX } from './chip.js';
|
|
8
|
+
import { flagChipStyle, flagChipX, axisPillX, axisPillStyle } from './chip.js';
|
|
9
9
|
import { ContainerContext, LayersContext, RowContext, } from './context.js';
|
|
10
10
|
/** Gridline tick count — matches the axes (`YAxis`/`TimeAxis`) so they align. */
|
|
11
11
|
const GRID_TICKS = 5;
|
|
@@ -49,7 +49,7 @@ export function Layers({ children }) {
|
|
|
49
49
|
}), [row.registerLayer, row.unregisterLayer]);
|
|
50
50
|
const background = container.theme.background;
|
|
51
51
|
const { grid: gridColor, gridDash } = container.theme.axis;
|
|
52
|
-
const { layers, yScales, formats, defaultAxisId, tickValues } = row;
|
|
52
|
+
const { layers, yScales, formats, defaultAxisId, tickValues, axisSides } = row;
|
|
53
53
|
// x geometry is shared and lives on the container (uniform across rows).
|
|
54
54
|
const { xScale, plotWidth } = container;
|
|
55
55
|
const draw = useCallback((ctx, w, h) => {
|
|
@@ -132,6 +132,8 @@ export function Layers({ children }) {
|
|
|
132
132
|
// The chip uses this layer's axis formatter, so a readout value reads
|
|
133
133
|
// exactly as the axis labels it.
|
|
134
134
|
const fmt = formats.get(axisId) ?? String;
|
|
135
|
+
// Which gutter the crosshair value pill hugs (the axis's own side).
|
|
136
|
+
const side = axisSides.get(axisId) ?? 'left';
|
|
135
137
|
for (const s of entry.layer.sampleAt(cursorTime)) {
|
|
136
138
|
out.push({
|
|
137
139
|
px: xScale(s.x),
|
|
@@ -139,6 +141,7 @@ export function Layers({ children }) {
|
|
|
139
141
|
value: s.value,
|
|
140
142
|
color: s.color,
|
|
141
143
|
format: fmt,
|
|
144
|
+
side,
|
|
142
145
|
});
|
|
143
146
|
}
|
|
144
147
|
}
|
|
@@ -148,6 +151,7 @@ export function Layers({ children }) {
|
|
|
148
151
|
layers,
|
|
149
152
|
yScales,
|
|
150
153
|
formats,
|
|
154
|
+
axisSides,
|
|
151
155
|
xScale,
|
|
152
156
|
defaultAxisId,
|
|
153
157
|
parts.dots,
|
|
@@ -403,9 +407,13 @@ export function Layers({ children }) {
|
|
|
403
407
|
// The time is shared across rows (one cursor, one time), so it shows **once**,
|
|
404
408
|
// atop the first row — not repeated per row. (Gating it here also drops the
|
|
405
409
|
// top-of-stack space reservation on the other rows, see `flagBase`.)
|
|
410
|
+
// Crosshair (`chip: 'axis'`) is excluded: it pins the time to the shared x-axis
|
|
411
|
+
// pill (`<XAxis>`), so a per-row chip here would double it (and land wrong on a
|
|
412
|
+
// stacked row).
|
|
406
413
|
const showTime = showCursorTime &&
|
|
407
414
|
cursorTime !== null &&
|
|
408
415
|
(parts.line || parts.dots) &&
|
|
416
|
+
parts.chip !== 'axis' &&
|
|
409
417
|
row.isFirstRow;
|
|
410
418
|
// Flag geometry: each value flies as a flag from the top of its own staff — the
|
|
411
419
|
// chip's top sits at `flagBase` (just below the time chip when shown) and the
|
|
@@ -491,9 +499,12 @@ export function Layers({ children }) {
|
|
|
491
499
|
cursorX >= 0 &&
|
|
492
500
|
cursorX <= plotWidth && (_jsx("line", { x1: Math.round(cursorX), y1: 0, x2: Math.round(cursorX), y2: row.height, stroke: cursorColor, strokeWidth: 1, shapeRendering: "crispEdges" })), parts.chip === 'flag' &&
|
|
493
501
|
trackerSamples.map((s, i) => s.py > flagBase ? (_jsx("line", { x1: s.px, y1: flagBase, x2: s.px, y2: s.py, stroke: cursorColor, strokeWidth: 1, opacity: 0.5 }, `staff-${i}`)) : null), parts.chip === 'flag' &&
|
|
494
|
-
trackerFlags.map((f, i) => f.topPy > flagBase ? (_jsx("line", { x1: f.px, y1: flagBase, x2: f.px, y2: f.topPy, stroke: cursorColor, strokeWidth: 1, opacity: 0.5 }, `boxstaff-${i}`)) : null), parts.
|
|
502
|
+
trackerFlags.map((f, i) => f.topPy > flagBase ? (_jsx("line", { x1: f.px, y1: flagBase, x2: f.px, y2: f.topPy, stroke: cursorColor, strokeWidth: 1, opacity: 0.5 }, `boxstaff-${i}`)) : null), parts.chip === 'axis' &&
|
|
503
|
+
trackerSamples.map((s, i) => (_jsx("line", { x1: s.side === 'right' ? Math.round(s.px) : 0, y1: Math.round(s.py), x2: s.side === 'right' ? plotWidth : Math.round(s.px), y2: Math.round(s.py), stroke: s.color, strokeWidth: 1, opacity: 0.4, strokeDasharray: "3 3", shapeRendering: "crispEdges" }, `hconn-${i}`))), parts.dots &&
|
|
495
504
|
trackerSamples.map((s, i) => (_jsx("circle", { cx: s.px, cy: s.py, r: 3, fill: s.color, stroke: background, strokeWidth: background ? 1 : 0 }, `dot-${i}`)))] }), showTime && timeX !== null && cursorTime !== null && (_jsx("div", { style: {
|
|
496
505
|
...chipStyle,
|
|
506
|
+
background: 'transparent',
|
|
507
|
+
padding: 0,
|
|
497
508
|
top: `${flagTop}px`,
|
|
498
509
|
left: timeX > plotWidth * LABEL_FLIP_FRACTION
|
|
499
510
|
? undefined
|
|
@@ -518,6 +529,15 @@ export function Layers({ children }) {
|
|
|
518
529
|
right: flip ? `${plotWidth - s.px + 8}px` : undefined,
|
|
519
530
|
color: s.color,
|
|
520
531
|
}, children: s.format(s.value) }, i));
|
|
532
|
+
}), parts.chip === 'axis' &&
|
|
533
|
+
trackerSamples.map((s, i) => {
|
|
534
|
+
const top = Math.max(flagLineHeight / 2, Math.min(row.height - flagLineHeight / 2, s.py));
|
|
535
|
+
return (_jsx("div", { style: {
|
|
536
|
+
...axisPillStyle(container.theme, s.color),
|
|
537
|
+
top: `${top}px`,
|
|
538
|
+
transform: 'translateY(-50%)',
|
|
539
|
+
...axisPillX(s.side, plotWidth),
|
|
540
|
+
}, children: s.format(s.value) }, `ytag-${i}`));
|
|
521
541
|
}), parts.chip === 'flag' &&
|
|
522
542
|
cursorX !== null &&
|
|
523
543
|
trackerSamples.map((s, i) => (
|
package/dist/XAxis.d.ts
CHANGED
|
@@ -24,6 +24,19 @@ export interface XAxisProps {
|
|
|
24
24
|
readonly at: number;
|
|
25
25
|
readonly label: string;
|
|
26
26
|
}>;
|
|
27
|
+
/**
|
|
28
|
+
* Horizontal placement of each tick label relative to its tick.
|
|
29
|
+
* - **`'center'` (default)** — every label centred on its tick. Note the
|
|
30
|
+
* first/last labels can then extend past the plot edges (the strip doesn't
|
|
31
|
+
* clip), so a wide first label may reach into the left y-axis gutter; use
|
|
32
|
+
* `'auto'` if that crowds.
|
|
33
|
+
* - `'auto'` — centred, but the first label left-anchors and the last
|
|
34
|
+
* right-anchors so the edge labels stay inside the plot (the old default).
|
|
35
|
+
* - `'right'` — the label sits to the **right** of an extended tick that
|
|
36
|
+
* drops from the axis line (label beside the tick, not under it) — useful
|
|
37
|
+
* for dense or wide labels that would collide when centred.
|
|
38
|
+
*/
|
|
39
|
+
align?: 'auto' | 'center' | 'right';
|
|
27
40
|
}
|
|
28
41
|
/**
|
|
29
42
|
* The shared **x axis**, a sibling of {@link YAxis} for the horizontal axis. A
|
|
@@ -35,5 +48,5 @@ export interface XAxisProps {
|
|
|
35
48
|
*
|
|
36
49
|
* `<TimeAxis>` is the time-flavoured preset (`<XAxis />`).
|
|
37
50
|
*/
|
|
38
|
-
export declare function XAxis({ format, label, side, height, ticks: customTicks, }?: XAxisProps): import("react/jsx-runtime").JSX.Element;
|
|
51
|
+
export declare function XAxis({ format, label, side, height, ticks: customTicks, align, }?: XAxisProps): import("react/jsx-runtime").JSX.Element;
|
|
39
52
|
//# sourceMappingURL=XAxis.d.ts.map
|
package/dist/XAxis.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { Fragment, useContext } from 'react';
|
|
3
3
|
import { ContainerContext } from './context.js';
|
|
4
|
+
import { axisPillStyle } from './chip.js';
|
|
4
5
|
import { resolveAxisFormat, resolveTimeFormat, } from './format.js';
|
|
5
6
|
/** Tick strip height (mark + value label) in CSS px. */
|
|
6
7
|
const TICK_STRIP = 22;
|
|
@@ -17,12 +18,23 @@ const TICK_COUNT = 5;
|
|
|
17
18
|
*
|
|
18
19
|
* `<TimeAxis>` is the time-flavoured preset (`<XAxis />`).
|
|
19
20
|
*/
|
|
20
|
-
export function XAxis({ format, label, side = 'bottom', height, ticks: customTicks, } = {}) {
|
|
21
|
+
export function XAxis({ format, label, side = 'bottom', height, ticks: customTicks, align = 'center', } = {}) {
|
|
21
22
|
const container = useContext(ContainerContext);
|
|
22
23
|
if (container === null) {
|
|
23
24
|
throw new Error('<XAxis> must be rendered inside a <ChartContainer>');
|
|
24
25
|
}
|
|
25
26
|
const { xScale, plotWidth, leftGutter, theme, formatTime, xKind } = container;
|
|
27
|
+
// The crosshair's x-time pill: when the container cursor is `'crosshair'` and a
|
|
28
|
+
// cursor is live in-bounds, pin the hovered time to this axis (covering the
|
|
29
|
+
// tick behind it), matching the on-axis y value pills the rows draw. Gated on
|
|
30
|
+
// the container default, so a per-row `cursor` override doesn't reach here.
|
|
31
|
+
const cursorX = container.cursorX;
|
|
32
|
+
const showCursorTag = container.cursor === 'crosshair' &&
|
|
33
|
+
cursorX !== null &&
|
|
34
|
+
cursorX >= 0 &&
|
|
35
|
+
cursorX <= plotWidth;
|
|
36
|
+
const cursorColor = theme.cursor ?? theme.axis.label;
|
|
37
|
+
const annotationColor = theme.annotation?.color ?? '#0d9488';
|
|
26
38
|
// Tick formatter: an explicit `format` is resolved against the axis kind
|
|
27
39
|
// (a time specifier through the time scale, a number specifier through the
|
|
28
40
|
// value scale); otherwise the container's shared formatter — the one the
|
|
@@ -32,6 +44,18 @@ export function XAxis({ format, label, side = 'bottom', height, ticks: customTic
|
|
|
32
44
|
: xKind === 'time'
|
|
33
45
|
? resolveTimeFormat(xScale, TICK_COUNT, format)
|
|
34
46
|
: resolveAxisFormat(xScale, TICK_COUNT, format);
|
|
47
|
+
// Marker annotations that opted into an axis indicator (`<Marker indicator>`)
|
|
48
|
+
// pin their **time** to this shared x-axis — a pill at `at`, in the annotation
|
|
49
|
+
// colour, reading like a tick. An indicator always shows the axis coordinate
|
|
50
|
+
// (the formatted `at`), never the marker's custom label (that stays the in-plot
|
|
51
|
+
// chip). Skipped when off-plot.
|
|
52
|
+
const markerTags = container.annotations
|
|
53
|
+
.filter((a) => a.indicator && a.kind === 'marker' && a.xs[0] !== undefined)
|
|
54
|
+
.map((a) => {
|
|
55
|
+
const at = a.xs[0];
|
|
56
|
+
return { id: a.id ?? `marker-at-${at}`, x: xScale(at), text: fmt(at) };
|
|
57
|
+
})
|
|
58
|
+
.filter((t) => t.x >= 0 && t.x <= plotWidth);
|
|
35
59
|
const placed = customTicks
|
|
36
60
|
? customTicks.map((t) => ({ x: xScale(t.at), label: t.label }))
|
|
37
61
|
: xScale.ticks(TICK_COUNT).map((d) => ({
|
|
@@ -40,6 +64,9 @@ export function XAxis({ format, label, side = 'bottom', height, ticks: customTic
|
|
|
40
64
|
}));
|
|
41
65
|
const stripHeight = height ?? TICK_STRIP + (label ? LABEL_STRIP : 0);
|
|
42
66
|
const onTop = side === 'top';
|
|
67
|
+
// Axis pills (marker / crosshair) sit at the same offset as the tick labels so
|
|
68
|
+
// they line up with their tick-label neighbours (matches `labelOffset` below).
|
|
69
|
+
const pillOffset = align === 'right' ? 2 : 6;
|
|
43
70
|
return (_jsxs("div", { style: {
|
|
44
71
|
position: 'relative',
|
|
45
72
|
marginLeft: `${leftGutter}px`,
|
|
@@ -51,23 +78,33 @@ export function XAxis({ format, label, side = 'bottom', height, ticks: customTic
|
|
|
51
78
|
fontSize: `${theme.font.size}px`,
|
|
52
79
|
color: theme.axis.label,
|
|
53
80
|
}, children: [placed.map((t, i) => {
|
|
54
|
-
|
|
55
|
-
const
|
|
81
|
+
const isFirst = i === 0;
|
|
82
|
+
const isLast = i === placed.length - 1;
|
|
83
|
+
// `center`: every label centred on its tick. `auto`: centred, but the
|
|
84
|
+
// edge labels end-align so they stay within [0, plotWidth]. `right`:
|
|
85
|
+
// label left-anchored just past an extended tick (beside, not under).
|
|
86
|
+
const labelTransform = align === 'right'
|
|
56
87
|
? 'none'
|
|
57
|
-
:
|
|
58
|
-
? '
|
|
59
|
-
: '
|
|
88
|
+
: align === 'auto' && isFirst
|
|
89
|
+
? 'none'
|
|
90
|
+
: align === 'auto' && isLast
|
|
91
|
+
? 'translateX(-100%)'
|
|
92
|
+
: 'translateX(-50%)';
|
|
93
|
+
// `right` drops a longer tick alongside the label; others keep the 4px stub.
|
|
94
|
+
const tickHeight = align === 'right' ? theme.font.size + 4 : 4;
|
|
95
|
+
const labelLeft = align === 'right' ? t.x + 4 : t.x;
|
|
96
|
+
const labelOffset = align === 'right' ? 2 : 6;
|
|
60
97
|
return (_jsxs(Fragment, { children: [_jsx("div", { style: {
|
|
61
98
|
position: 'absolute',
|
|
62
99
|
left: `${t.x}px`,
|
|
63
100
|
[onTop ? 'bottom' : 'top']: 0,
|
|
64
101
|
width: '1px',
|
|
65
|
-
height:
|
|
102
|
+
height: `${tickHeight}px`,
|
|
66
103
|
background: theme.axis.grid,
|
|
67
104
|
} }), _jsx("div", { style: {
|
|
68
105
|
position: 'absolute',
|
|
69
|
-
left: `${
|
|
70
|
-
[onTop ? 'bottom' : 'top']:
|
|
106
|
+
left: `${labelLeft}px`,
|
|
107
|
+
[onTop ? 'bottom' : 'top']: `${labelOffset}px`,
|
|
71
108
|
transform: labelTransform,
|
|
72
109
|
whiteSpace: 'nowrap',
|
|
73
110
|
}, children: t.label })] }, `${t.x}-${i}`));
|
|
@@ -77,8 +114,31 @@ export function XAxis({ format, label, side = 'bottom', height, ticks: customTic
|
|
|
77
114
|
width: '100%',
|
|
78
115
|
textAlign: 'center',
|
|
79
116
|
[onTop ? 'top' : 'bottom']: 0,
|
|
80
|
-
|
|
117
|
+
// Themeable axis-title text (shared with the rotated y-axis title).
|
|
118
|
+
fontSize: `${theme.axis.title?.size ?? theme.font.size + 1}px`,
|
|
119
|
+
color: theme.axis.title?.color ?? theme.axis.label,
|
|
120
|
+
opacity: theme.axis.title?.opacity ?? 0.85,
|
|
81
121
|
whiteSpace: 'nowrap',
|
|
82
|
-
}, children: label }))
|
|
122
|
+
}, children: label })), markerTags.map((t) => (_jsxs(Fragment, { children: [_jsx("div", { style: {
|
|
123
|
+
position: 'absolute',
|
|
124
|
+
left: `${t.x}px`,
|
|
125
|
+
[onTop ? 'bottom' : 'top']: 0,
|
|
126
|
+
width: '1px',
|
|
127
|
+
height: `${pillOffset}px`,
|
|
128
|
+
background: annotationColor,
|
|
129
|
+
zIndex: 2,
|
|
130
|
+
} }), _jsx("div", { style: {
|
|
131
|
+
...axisPillStyle(theme, annotationColor),
|
|
132
|
+
left: `${t.x}px`,
|
|
133
|
+
transform: 'translateX(-50%)',
|
|
134
|
+
[onTop ? 'bottom' : 'top']: `${pillOffset}px`,
|
|
135
|
+
zIndex: 2,
|
|
136
|
+
}, children: t.text })] }, t.id))), showCursorTag && (_jsx("div", { style: {
|
|
137
|
+
...axisPillStyle(theme, cursorColor),
|
|
138
|
+
left: `${cursorX}px`,
|
|
139
|
+
transform: 'translateX(-50%)',
|
|
140
|
+
[onTop ? 'bottom' : 'top']: `${pillOffset}px`,
|
|
141
|
+
zIndex: 3,
|
|
142
|
+
}, children: fmt(+xScale.invert(cursorX)) }))] }));
|
|
83
143
|
}
|
|
84
144
|
//# sourceMappingURL=XAxis.js.map
|
package/dist/YAxis.d.ts
CHANGED
|
@@ -11,9 +11,25 @@ export interface YAxisProps {
|
|
|
11
11
|
side?: 'left' | 'right';
|
|
12
12
|
/** Display label / unit (e.g. `bpm`); defaults to `id`. */
|
|
13
13
|
label?: string;
|
|
14
|
+
/**
|
|
15
|
+
* How the axis title (`label`) is drawn:
|
|
16
|
+
* - **`'rotated'` (default)** — a thin vertical strip down the outer edge
|
|
17
|
+
* (the standard y-axis convention; fits long labels in a narrow gutter).
|
|
18
|
+
* - `'top'` — horizontal, at the top of the axis, aligned to its side. Reads
|
|
19
|
+
* better for short unit labels; keep it terse and pair it with a domain
|
|
20
|
+
* that has headroom (auto-fit / padded) so it doesn't crowd the top tick.
|
|
21
|
+
*/
|
|
22
|
+
labelPlacement?: 'rotated' | 'top';
|
|
14
23
|
/** Explicit domain bounds; omit to auto-fit the charts linked to this axis. */
|
|
15
24
|
min?: number;
|
|
16
25
|
max?: number;
|
|
26
|
+
/**
|
|
27
|
+
* Fractional headroom added to each side of the resolved domain — `0` (the
|
|
28
|
+
* default) means none. Lifts a tight domain off the plot edges without
|
|
29
|
+
* hand-computing bounds (e.g. `pad={0.05}` adds 5% of the span top & bottom).
|
|
30
|
+
* Applies to an explicit `[min, max]` or an auto-fit domain.
|
|
31
|
+
*/
|
|
32
|
+
pad?: number;
|
|
17
33
|
/**
|
|
18
34
|
* Value formatting for the tick labels (and the cursor readout, which matches):
|
|
19
35
|
* a d3 format specifier string (e.g. `'.0%'`, `',.2f'`) or a `(value) => string`
|
|
@@ -37,6 +53,14 @@ export interface YAxisProps {
|
|
|
37
53
|
readonly at: number;
|
|
38
54
|
readonly label: string;
|
|
39
55
|
}>;
|
|
56
|
+
/**
|
|
57
|
+
* Render the tick labels at the domain extremes (the top & bottom ticks)?
|
|
58
|
+
* **Default `true`.** `false` drops just those two numbers — the gridlines
|
|
59
|
+
* stay — for when the min/max labels crowd a stacked row's edges and you'd
|
|
60
|
+
* rather omit them than keep them. (Extreme labels are otherwise clamped to
|
|
61
|
+
* stay inside the row, never overflowing the edge.)
|
|
62
|
+
*/
|
|
63
|
+
boundaryLabels?: boolean;
|
|
40
64
|
/** Gutter width in CSS pixels (default 50). */
|
|
41
65
|
width?: number;
|
|
42
66
|
/**
|
|
@@ -53,5 +77,5 @@ export interface YAxisProps {
|
|
|
53
77
|
* tick marks + labels from that scale. Charts attach via `<LineChart axis="id">`
|
|
54
78
|
* (default: the first axis).
|
|
55
79
|
*/
|
|
56
|
-
export declare function YAxis({ id, side, label, min, max, format, ticks, width, index, }: YAxisProps): import("react/jsx-runtime").JSX.Element;
|
|
80
|
+
export declare function YAxis({ id, side, label, min, max, format, ticks, pad, boundaryLabels, width, labelPlacement, index, }: YAxisProps): import("react/jsx-runtime").JSX.Element;
|
|
57
81
|
//# sourceMappingURL=YAxis.d.ts.map
|
package/dist/YAxis.js
CHANGED
|
@@ -13,7 +13,7 @@ const TICK_COUNT = 5;
|
|
|
13
13
|
* tick marks + labels from that scale. Charts attach via `<LineChart axis="id">`
|
|
14
14
|
* (default: the first axis).
|
|
15
15
|
*/
|
|
16
|
-
export function YAxis({ id, side = 'left', label, min, max, format, ticks, width = DEFAULT_WIDTH, index = 0, }) {
|
|
16
|
+
export function YAxis({ id, side = 'left', label, min, max, format, ticks, pad = 0, boundaryLabels = true, width = DEFAULT_WIDTH, labelPlacement = 'rotated', index = 0, }) {
|
|
17
17
|
const container = useContext(ContainerContext);
|
|
18
18
|
if (container === null) {
|
|
19
19
|
throw new Error('<YAxis> must be rendered inside a <ChartContainer>');
|
|
@@ -28,10 +28,12 @@ export function YAxis({ id, side = 'left', label, min, max, format, ticks, width
|
|
|
28
28
|
width,
|
|
29
29
|
min,
|
|
30
30
|
max,
|
|
31
|
+
pad,
|
|
32
|
+
labelPlacement,
|
|
31
33
|
format,
|
|
32
34
|
tickValues: ticks?.map((t) => t.at),
|
|
33
35
|
index,
|
|
34
|
-
}), [id, side, width, min, max, format, ticks, index]);
|
|
36
|
+
}), [id, side, width, min, max, pad, labelPlacement, format, ticks, index]);
|
|
35
37
|
// A stable per-instance slot (see useSlotKey) keeps this axis in a fixed
|
|
36
38
|
// registry position, so a min/max/side change updates in place rather than
|
|
37
39
|
// re-appending (which would move the first axis behind a later one and
|
|
@@ -76,27 +78,50 @@ export function YAxis({ id, side = 'left', label, min, max, format, ticks, width
|
|
|
76
78
|
fontSize: `${theme.font.size}px`,
|
|
77
79
|
color: theme.axis.label,
|
|
78
80
|
}, children: [yScale &&
|
|
79
|
-
tickList.map(({ value, label }) =>
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
81
|
+
tickList.map(({ value, label }, i) => {
|
|
82
|
+
// Drop just the top & bottom labels when boundary labels are off
|
|
83
|
+
// (gridlines are drawn separately, so they stay).
|
|
84
|
+
if (!boundaryLabels && (i === 0 || i === tickList.length - 1))
|
|
85
|
+
return null;
|
|
86
|
+
// Clamp the label's centre so a domain-extreme label stays inside
|
|
87
|
+
// the row instead of half-overflowing the top/bottom edge (and
|
|
88
|
+
// colliding across a splitter in a stacked layout) — F-charts-6.
|
|
89
|
+
const half = theme.font.size / 2 + 1;
|
|
90
|
+
const top = Math.max(half, Math.min(row.height - half, yScale(value)));
|
|
91
|
+
return (_jsx("div", { style: {
|
|
92
|
+
position: 'absolute',
|
|
93
|
+
top: `${top}px`,
|
|
94
|
+
[side === 'left' ? 'right' : 'left']: '4px',
|
|
95
|
+
transform: 'translateY(-50%)',
|
|
96
|
+
whiteSpace: 'nowrap',
|
|
97
|
+
}, children: label }, value));
|
|
98
|
+
}), labelPlacement === 'top' ? (_jsx("div", { style: {
|
|
99
|
+
position: 'absolute',
|
|
100
|
+
top: 0,
|
|
101
|
+
// Align to the axis line (the plot-facing edge), matching the tick
|
|
102
|
+
// labels' alignment, rather than floating at the outer gutter edge.
|
|
103
|
+
[side === 'left' ? 'right' : 'left']: '4px',
|
|
104
|
+
fontSize: `${theme.axis.title?.size ?? theme.font.size + 1}px`,
|
|
105
|
+
color: theme.axis.title?.color ?? theme.axis.label,
|
|
106
|
+
opacity: theme.axis.title?.opacity ?? 0.85,
|
|
107
|
+
whiteSpace: 'nowrap',
|
|
108
|
+
pointerEvents: 'none',
|
|
109
|
+
}, children: label ?? id })) : (_jsx("div", { style: {
|
|
86
110
|
position: 'absolute',
|
|
87
111
|
[side === 'left' ? 'left' : 'right']: '1px',
|
|
88
112
|
top: 0,
|
|
89
113
|
bottom: 0,
|
|
90
|
-
width: `${theme.font.size +
|
|
114
|
+
width: `${(theme.axis.title?.size ?? theme.font.size + 1) + 3}px`,
|
|
91
115
|
display: 'flex',
|
|
92
116
|
alignItems: 'center',
|
|
93
117
|
justifyContent: 'center',
|
|
94
|
-
fontSize: `${theme.font.size
|
|
95
|
-
|
|
118
|
+
fontSize: `${theme.axis.title?.size ?? theme.font.size + 1}px`,
|
|
119
|
+
color: theme.axis.title?.color ?? theme.axis.label,
|
|
120
|
+
opacity: theme.axis.title?.opacity ?? 0.85,
|
|
96
121
|
pointerEvents: 'none',
|
|
97
122
|
}, children: _jsx("span", { style: {
|
|
98
123
|
whiteSpace: 'nowrap',
|
|
99
124
|
transform: `rotate(${side === 'left' ? -90 : 90}deg)`,
|
|
100
|
-
}, children: label ?? id }) })] }) }));
|
|
125
|
+
}, children: label ?? id }) }))] }) }));
|
|
101
126
|
}
|
|
102
127
|
//# sourceMappingURL=YAxis.js.map
|
package/dist/annotations.d.ts
CHANGED
|
@@ -51,9 +51,16 @@ export interface MarkerProps {
|
|
|
51
51
|
/** Make the marker **editable** (in edit mode): dragging its line reports the
|
|
52
52
|
* new `at` (controlled — wire it back to `at`). The whole line moves. */
|
|
53
53
|
onChange?: (at: number) => void;
|
|
54
|
+
/** Also pin this marker's **time** to the **x-axis** as an on-axis pill (drawn
|
|
55
|
+
* by `<XAxis>` at `at`, in the annotation colour) — the axis-edge counterpart
|
|
56
|
+
* of the near-line chip. Default `false`. The pill always shows the formatted
|
|
57
|
+
* `at` (the axis coordinate), never the custom `label` (which stays the
|
|
58
|
+
* near-line chip) — an indicator reads like a tick. A connector links the
|
|
59
|
+
* marker line to its pill. */
|
|
60
|
+
indicator?: boolean;
|
|
54
61
|
}
|
|
55
62
|
/** A vertical line at an x position (a time, a distance, a lap boundary). */
|
|
56
|
-
export declare function Marker({ at, label, id, selected, selectable, hovered, editing, onChange, }: MarkerProps): import("react/jsx-runtime").JSX.Element;
|
|
63
|
+
export declare function Marker({ at, label, id, selected, selectable, hovered, editing, onChange, indicator, }: MarkerProps): import("react/jsx-runtime").JSX.Element;
|
|
57
64
|
export interface BaselineProps {
|
|
58
65
|
/** y value in the linked axis's units. */
|
|
59
66
|
value: number;
|
|
@@ -62,6 +69,11 @@ export interface BaselineProps {
|
|
|
62
69
|
/** Chip label. Omit to format `value` with that axis's formatter; pass `false`
|
|
63
70
|
* (or `''`) to render **no label chip**. */
|
|
64
71
|
label?: string | false;
|
|
72
|
+
/** Which side of the chart the near-line label chip sits. **Default `left`.** */
|
|
73
|
+
labelSide?: 'left' | 'right';
|
|
74
|
+
/** Where the label chip sits relative to the line: **`center`** (default) rides
|
|
75
|
+
* on the line, vertically centred; `above` sits just on top of it. */
|
|
76
|
+
labelPosition?: 'center' | 'above';
|
|
65
77
|
/** Stable consumer id — a click reports it via `onSelectAnnotation`. */
|
|
66
78
|
id?: string;
|
|
67
79
|
/** Controlled selection — brightens to the front (level 1). Handles are an
|
|
@@ -82,10 +94,16 @@ export interface BaselineProps {
|
|
|
82
94
|
/** Make the baseline **editable** (in edit mode): dragging it vertically reports
|
|
83
95
|
* the new `value` (controlled — wire it back to `value`). */
|
|
84
96
|
onChange?: (value: number) => void;
|
|
97
|
+
/** Also pin this baseline's **value** to its **y-axis** as an on-axis pill (in
|
|
98
|
+
* the annotation colour) — the axis-edge counterpart of the near-line chip.
|
|
99
|
+
* Default `false`. The pill always shows the formatted `value` (the axis
|
|
100
|
+
* coordinate), never the custom `label` (which stays the near-line chip) — an
|
|
101
|
+
* indicator reads like a tick. */
|
|
102
|
+
indicator?: boolean;
|
|
85
103
|
}
|
|
86
104
|
/** A horizontal line at a y value, scaled against one row axis (RTC's `Baseline`).
|
|
87
105
|
* Its label anchors at the left, at the line's height. */
|
|
88
|
-
export declare function Baseline({ value, axis, label, id, selected, selectable, hovered, editing, onChange, }: BaselineProps): import("react/jsx-runtime").JSX.Element | null;
|
|
106
|
+
export declare function Baseline({ value, axis, label, labelSide, labelPosition, id, selected, selectable, hovered, editing, onChange, indicator, }: BaselineProps): import("react/jsx-runtime").JSX.Element | null;
|
|
89
107
|
export interface RegionProps {
|
|
90
108
|
/** Start x in axis units (time or value). */
|
|
91
109
|
from: number;
|
|
@@ -122,8 +140,12 @@ export interface RegionProps {
|
|
|
122
140
|
from: number;
|
|
123
141
|
to: number;
|
|
124
142
|
}) => void;
|
|
143
|
+
/** Draw the vertical **side outlines** at `from`/`to`. **Default `true`.**
|
|
144
|
+
* `false` shades the span with no edge lines (fill only) — a soft highlight
|
|
145
|
+
* band. Edit-mode resizing still works (the grab areas are invisible). */
|
|
146
|
+
edges?: boolean;
|
|
125
147
|
}
|
|
126
148
|
/** A shaded span over an x range — a lap, a zone, a selected interval. Its label
|
|
127
149
|
* flies as a flag off the left edge. */
|
|
128
|
-
export declare function Region({ from, to, label, id, selected, selectable, hovered, editing, onChange, }: RegionProps): import("react/jsx-runtime").JSX.Element;
|
|
150
|
+
export declare function Region({ from, to, label, id, selected, selectable, hovered, editing, onChange, edges, }: RegionProps): import("react/jsx-runtime").JSX.Element;
|
|
129
151
|
//# sourceMappingURL=annotations.d.ts.map
|