@pibbl/core 0.0.2 → 0.0.3-alpha.85.1
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/THIRD_PARTY_NOTICES.txt +81 -0
- package/dist/features/textures/index.d.ts +12 -2
- package/dist/features/textures/index.js +33 -1
- package/dist/features/textures/index.js.map +2 -2
- package/dist/features/textures/lib/chemical-field.d.ts +56 -0
- package/dist/features/textures/lib/chemical-field.js +154 -0
- package/dist/features/textures/lib/chemical-field.js.map +7 -0
- package/dist/features/textures/lib/chemical-recipes.d.ts +119 -0
- package/dist/features/textures/lib/chemical-recipes.js +275 -0
- package/dist/features/textures/lib/chemical-recipes.js.map +7 -0
- package/dist/features/textures/lib/definitions.d.ts +3 -18
- package/dist/features/textures/lib/definitions.js +15 -20
- package/dist/features/textures/lib/definitions.js.map +2 -2
- package/dist/features/textures/lib/geometric-patterns.d.ts +149 -0
- package/dist/features/textures/lib/geometric-patterns.js +305 -0
- package/dist/features/textures/lib/geometric-patterns.js.map +7 -0
- package/dist/features/textures/lib/gray-scott.d.ts +55 -0
- package/dist/features/textures/lib/gray-scott.js +39 -0
- package/dist/features/textures/lib/gray-scott.js.map +7 -0
- package/dist/features/textures/lib/patterns.d.ts +123 -0
- package/dist/features/textures/lib/patterns.js +344 -0
- package/dist/features/textures/lib/patterns.js.map +7 -0
- package/dist/features/textures/lib/reaction-diffusion.d.ts +3 -2
- package/dist/features/textures/lib/reaction-diffusion.js +9 -20
- package/dist/features/textures/lib/reaction-diffusion.js.map +2 -2
- package/dist/features/textures/lib/simulation.d.ts +10 -4
- package/dist/features/textures/lib/simulation.js +23 -13
- package/dist/features/textures/lib/simulation.js.map +2 -2
- package/dist/features/viz/index.d.ts +55 -6
- package/dist/features/viz/index.js +107 -2
- package/dist/features/viz/index.js.map +2 -2
- package/dist/features/viz/inspection/bar.d.ts +79 -0
- package/dist/features/viz/inspection/bar.js +49 -0
- package/dist/features/viz/inspection/bar.js.map +7 -0
- package/dist/features/viz/inspection/candle.d.ts +156 -0
- package/dist/features/viz/inspection/candle.js +120 -0
- package/dist/features/viz/inspection/candle.js.map +7 -0
- package/dist/features/viz/inspection/capture-types.d.ts +65 -0
- package/dist/features/viz/inspection/capture.d.ts +16 -0
- package/dist/features/viz/inspection/capture.js +49 -0
- package/dist/features/viz/inspection/capture.js.map +7 -0
- package/dist/features/viz/inspection/handler.d.ts +36 -0
- package/dist/features/viz/inspection/handler.js +91 -0
- package/dist/features/viz/inspection/handler.js.map +7 -0
- package/dist/features/viz/inspection/ohlc-bar.d.ts +132 -0
- package/dist/features/viz/inspection/ohlc-bar.js +118 -0
- package/dist/features/viz/inspection/ohlc-bar.js.map +7 -0
- package/dist/features/viz/inspection/owned-ref.d.ts +16 -0
- package/dist/features/viz/inspection/owned-ref.js +99 -0
- package/dist/features/viz/inspection/owned-ref.js.map +7 -0
- package/dist/features/viz/inspection/painted-point.d.ts +22 -0
- package/dist/features/viz/inspection/painted-point.js +29 -0
- package/dist/features/viz/inspection/painted-point.js.map +7 -0
- package/dist/features/viz/inspection/queries.d.ts +100 -0
- package/dist/features/viz/inspection/queries.js +192 -0
- package/dist/features/viz/inspection/queries.js.map +7 -0
- package/dist/features/viz/inspection/query-types.d.ts +177 -0
- package/dist/features/viz/inspection/volume.d.ts +104 -0
- package/dist/features/viz/inspection/volume.js +95 -0
- package/dist/features/viz/inspection/volume.js.map +7 -0
- package/dist/features/viz/inspection.d.ts +19 -0
- package/dist/features/viz/inspection.js +54 -0
- package/dist/features/viz/inspection.js.map +7 -0
- package/dist/features/viz/inspection.mjs +1 -0
- package/dist/features/viz/lib/area-series.d.ts +62 -0
- package/dist/features/viz/lib/area-series.js +120 -0
- package/dist/features/viz/lib/area-series.js.map +7 -0
- package/dist/features/viz/lib/axis.js +1 -1
- package/dist/features/viz/lib/axis.js.map +2 -2
- package/dist/features/viz/lib/bar-series.d.ts +3 -1
- package/dist/features/viz/lib/bar-series.js +16 -1
- package/dist/features/viz/lib/bar-series.js.map +2 -2
- package/dist/features/viz/lib/baseline-series.d.ts +55 -0
- package/dist/features/viz/lib/baseline-series.js +136 -0
- package/dist/features/viz/lib/baseline-series.js.map +7 -0
- package/dist/features/viz/lib/candlestick-series.d.ts +62 -0
- package/dist/features/viz/lib/candlestick-series.js +150 -0
- package/dist/features/viz/lib/candlestick-series.js.map +7 -0
- package/dist/features/viz/lib/censored-point-series.d.ts +71 -0
- package/dist/features/viz/lib/censored-point-series.js +129 -0
- package/dist/features/viz/lib/censored-point-series.js.map +7 -0
- package/dist/features/viz/lib/color-context.d.ts +4 -0
- package/dist/features/viz/lib/color-context.js +41 -0
- package/dist/features/viz/lib/color-context.js.map +7 -0
- package/dist/features/viz/lib/color-math.d.ts +4 -0
- package/dist/features/viz/lib/color-math.js +31 -0
- package/dist/features/viz/lib/color-math.js.map +7 -0
- package/dist/features/viz/lib/color-types.d.ts +53 -0
- package/dist/features/viz/lib/curve-definition.d.ts +49 -0
- package/dist/features/viz/lib/curve-definition.js +148 -0
- package/dist/features/viz/lib/curve-definition.js.map +7 -0
- package/dist/features/viz/lib/diverging-color-scale.d.ts +11 -0
- package/dist/features/viz/lib/diverging-color-scale.js +51 -0
- package/dist/features/viz/lib/diverging-color-scale.js.map +7 -0
- package/dist/features/viz/lib/domain-navigation.d.ts +40 -0
- package/dist/features/viz/lib/domain-navigation.js +77 -0
- package/dist/features/viz/lib/domain-navigation.js.map +7 -0
- package/dist/features/viz/lib/editable-chart-elements.d.ts +178 -0
- package/dist/features/viz/lib/editable-chart-elements.js +733 -0
- package/dist/features/viz/lib/editable-chart-elements.js.map +7 -0
- package/dist/features/viz/lib/financial-aggregation.d.ts +127 -0
- package/dist/features/viz/lib/financial-aggregation.js +116 -0
- package/dist/features/viz/lib/financial-aggregation.js.map +7 -0
- package/dist/features/viz/lib/financial-autoscale.d.ts +64 -0
- package/dist/features/viz/lib/financial-autoscale.js +61 -0
- package/dist/features/viz/lib/financial-autoscale.js.map +7 -0
- package/dist/features/viz/lib/financial-comparison.d.ts +62 -0
- package/dist/features/viz/lib/financial-comparison.js +98 -0
- package/dist/features/viz/lib/financial-comparison.js.map +7 -0
- package/dist/features/viz/lib/financial-geometry.d.ts +77 -0
- package/dist/features/viz/lib/financial-geometry.js +67 -0
- package/dist/features/viz/lib/financial-geometry.js.map +7 -0
- package/dist/features/viz/lib/financial-indicators.d.ts +114 -0
- package/dist/features/viz/lib/financial-indicators.js +135 -0
- package/dist/features/viz/lib/financial-indicators.js.map +7 -0
- package/dist/features/viz/lib/financial-oscillators.d.ts +171 -0
- package/dist/features/viz/lib/financial-oscillators.js +265 -0
- package/dist/features/viz/lib/financial-oscillators.js.map +7 -0
- package/dist/features/viz/lib/hover-data.d.ts +1 -1
- package/dist/features/viz/lib/hover-data.js +5 -2
- package/dist/features/viz/lib/hover-data.js.map +2 -2
- package/dist/features/viz/lib/interval-band-series.d.ts +49 -0
- package/dist/features/viz/lib/interval-band-series.js +136 -0
- package/dist/features/viz/lib/interval-band-series.js.map +7 -0
- package/dist/features/viz/lib/interval-diamond-series.d.ts +43 -0
- package/dist/features/viz/lib/interval-diamond-series.js +124 -0
- package/dist/features/viz/lib/interval-diamond-series.js.map +7 -0
- package/dist/features/viz/lib/interval-series.d.ts +79 -0
- package/dist/features/viz/lib/interval-series.js +158 -0
- package/dist/features/viz/lib/interval-series.js.map +7 -0
- package/dist/features/viz/lib/line-series.d.ts +1 -1
- package/dist/features/viz/lib/line-series.js +47 -28
- package/dist/features/viz/lib/line-series.js.map +2 -2
- package/dist/features/viz/lib/linear-scale.js +1 -1
- package/dist/features/viz/lib/linear-scale.js.map +2 -2
- package/dist/features/viz/lib/monotone-curve.d.ts +11 -0
- package/dist/features/viz/lib/monotone-curve.js +63 -0
- package/dist/features/viz/lib/monotone-curve.js.map +7 -0
- package/dist/features/viz/lib/numeric-range-interpolation.d.ts +15 -0
- package/dist/features/viz/lib/numeric-range-interpolation.js +36 -0
- package/dist/features/viz/lib/numeric-range-interpolation.js.map +7 -0
- package/dist/features/viz/lib/ohlc-bar-series.d.ts +55 -0
- package/dist/features/viz/lib/ohlc-bar-series.js +168 -0
- package/dist/features/viz/lib/ohlc-bar-series.js.map +7 -0
- package/dist/features/viz/lib/paired-series.d.ts +44 -0
- package/dist/features/viz/lib/paired-series.js +93 -0
- package/dist/features/viz/lib/paired-series.js.map +7 -0
- package/dist/features/viz/lib/plot-series.js +11 -6
- package/dist/features/viz/lib/plot-series.js.map +2 -2
- package/dist/features/viz/lib/plot-types.d.ts +4 -3
- package/dist/features/viz/lib/point-series.d.ts +1 -1
- package/dist/features/viz/lib/point-series.js +36 -9
- package/dist/features/viz/lib/point-series.js.map +2 -2
- package/dist/features/viz/lib/point-types.d.ts +5 -2
- package/dist/features/viz/lib/scale-context.d.ts +1 -1
- package/dist/features/viz/lib/scale-ticks.js +21 -6
- package/dist/features/viz/lib/scale-ticks.js.map +2 -2
- package/dist/features/viz/lib/sequential-color-scale.d.ts +11 -0
- package/dist/features/viz/lib/sequential-color-scale.js +49 -0
- package/dist/features/viz/lib/sequential-color-scale.js.map +7 -0
- package/dist/features/viz/lib/series-position.d.ts +12 -0
- package/dist/features/viz/lib/series-position.js +44 -0
- package/dist/features/viz/lib/series-position.js.map +7 -0
- package/dist/features/viz/lib/step-curves.d.ts +19 -0
- package/dist/features/viz/lib/step-curves.js +53 -0
- package/dist/features/viz/lib/step-curves.js.map +7 -0
- package/dist/features/viz/lib/threshold-color-scale.d.ts +43 -0
- package/dist/features/viz/lib/threshold-color-scale.js +59 -0
- package/dist/features/viz/lib/threshold-color-scale.js.map +7 -0
- package/dist/features/viz/lib/trading-time-mapping.d.ts +32 -0
- package/dist/features/viz/lib/trading-time-mapping.js +89 -0
- package/dist/features/viz/lib/trading-time-mapping.js.map +7 -0
- package/dist/features/viz/lib/trading-time-scale.d.ts +83 -0
- package/dist/features/viz/lib/trading-time-scale.js +96 -0
- package/dist/features/viz/lib/trading-time-scale.js.map +7 -0
- package/dist/features/viz/lib/trajectory-series.d.ts +71 -0
- package/dist/features/viz/lib/trajectory-series.js +111 -0
- package/dist/features/viz/lib/trajectory-series.js.map +7 -0
- package/dist/features/viz/lib/types.d.ts +20 -4
- package/dist/features/viz/lib/use-continuous-scale.js +6 -1
- package/dist/features/viz/lib/use-continuous-scale.js.map +2 -2
- package/dist/features/viz/lib/volume-series.d.ts +59 -0
- package/dist/features/viz/lib/volume-series.js +117 -0
- package/dist/features/viz/lib/volume-series.js.map +7 -0
- package/dist/features/viz/lib/weighted-point-series.d.ts +71 -0
- package/dist/features/viz/lib/weighted-point-series.js +169 -0
- package/dist/features/viz/lib/weighted-point-series.js.map +7 -0
- package/dist/filters/emboss-gpu.d.ts +4 -0
- package/dist/filters/emboss-gpu.js +39 -0
- package/dist/filters/emboss-gpu.js.map +7 -0
- package/dist/filters/emboss.d.ts +32 -0
- package/dist/filters/emboss.js +106 -0
- package/dist/filters/emboss.js.map +7 -0
- package/dist/filters/reflection-gpu.d.ts +3 -1
- package/dist/filters/reflection-gpu.js +5 -2
- package/dist/filters/reflection-gpu.js.map +2 -2
- package/dist/filters/render-emboss-boundary.d.ts +13 -0
- package/dist/filters/render-emboss-boundary.js +131 -0
- package/dist/filters/render-emboss-boundary.js.map +7 -0
- package/dist/filters.d.ts +2 -0
- package/dist/filters.js +2 -0
- package/dist/filters.js.map +2 -2
- package/dist/index.d.ts +2 -0
- package/dist/index.js +3 -0
- package/dist/index.js.map +2 -2
- package/dist/internal.d.ts +2 -0
- package/dist/internal.js +4 -0
- package/dist/internal.js.map +2 -2
- package/dist/lib/events/event-facade.d.ts +13 -0
- package/dist/lib/events/event-facade.js +23 -0
- package/dist/lib/events/event-facade.js.map +2 -2
- package/dist/lib/events/propagation.js +19 -14
- package/dist/lib/events/propagation.js.map +2 -2
- package/dist/lib/execute-render.js +13 -0
- package/dist/lib/execute-render.js.map +2 -2
- package/dist/lib/recording/recording.d.ts +43 -0
- package/dist/lib/recording/recording.js +555 -0
- package/dist/lib/recording/recording.js.map +7 -0
- package/dist/lib/recording/types.d.ts +118 -0
- package/dist/lib/recording/wasm-bytes.d.ts +1 -0
- package/dist/lib/recording/wasm-bytes.js +5 -0
- package/dist/lib/recording/wasm-bytes.js.map +7 -0
- package/dist/lib/recording/worker-source.d.ts +1 -0
- package/dist/lib/recording/worker-source.js +5 -0
- package/dist/lib/recording/worker-source.js.map +7 -0
- package/dist/lib/render-transaction.d.ts +5 -2
- package/dist/lib/render-transaction.js +23 -1
- package/dist/lib/render-transaction.js.map +2 -2
- package/dist/lib/series-inspection-frame.d.ts +18 -0
- package/dist/lib/series-inspection-frame.js +70 -0
- package/dist/lib/series-inspection-frame.js.map +7 -0
- package/dist/lib/types.d.ts +6 -0
- package/package.json +10 -2
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
import { jsx } from "@pibbl/core/jsx-runtime";
|
|
2
|
+
import { useNumericPosition } from "./series-position.js";
|
|
3
|
+
import { Path, resolveSignalValue } from "@pibbl/core";
|
|
4
|
+
import {
|
|
5
|
+
useInternalValueMemoSlot,
|
|
6
|
+
validateTexturePaint
|
|
7
|
+
} from "@pibbl/core/internal";
|
|
8
|
+
import { opacity } from "./paint.js";
|
|
9
|
+
import {
|
|
10
|
+
appendCurveForward,
|
|
11
|
+
appendCurveReverse,
|
|
12
|
+
curveGeometry,
|
|
13
|
+
resolveSeriesCurve,
|
|
14
|
+
validatePairedCurveGeometry
|
|
15
|
+
} from "./curve-definition.js";
|
|
16
|
+
import { useContinuousScale } from "./use-continuous-scale.js";
|
|
17
|
+
function accessor(input) {
|
|
18
|
+
return typeof input === "function" ? input : (datum) => datum[input];
|
|
19
|
+
}
|
|
20
|
+
function fill(value) {
|
|
21
|
+
if (typeof value === "string" || value instanceof CanvasGradient || value instanceof CanvasPattern)
|
|
22
|
+
return value;
|
|
23
|
+
try {
|
|
24
|
+
validateTexturePaint(value);
|
|
25
|
+
return value;
|
|
26
|
+
} catch {
|
|
27
|
+
throw new TypeError("IntervalBandSeries: invalid fill.");
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
function IntervalBandSeries({
|
|
31
|
+
data: dataInput,
|
|
32
|
+
x: xInput,
|
|
33
|
+
lower: lowerInput,
|
|
34
|
+
upper: upperInput,
|
|
35
|
+
xScale: xId,
|
|
36
|
+
yScale: yId,
|
|
37
|
+
defined,
|
|
38
|
+
curve,
|
|
39
|
+
style: styleInput,
|
|
40
|
+
...eventProps
|
|
41
|
+
}) {
|
|
42
|
+
const xScale = useNumericPosition(xId);
|
|
43
|
+
const yScale = useContinuousScale(yId).get();
|
|
44
|
+
const curveDefinition = resolveSeriesCurve(curve);
|
|
45
|
+
const x = useInternalValueMemoSlot(
|
|
46
|
+
"vizIntervalBandXAccessor",
|
|
47
|
+
() => accessor(xInput),
|
|
48
|
+
[xInput]
|
|
49
|
+
);
|
|
50
|
+
const lower = useInternalValueMemoSlot(
|
|
51
|
+
"vizIntervalBandLowerAccessor",
|
|
52
|
+
() => accessor(lowerInput),
|
|
53
|
+
[lowerInput]
|
|
54
|
+
);
|
|
55
|
+
const upper = useInternalValueMemoSlot(
|
|
56
|
+
"vizIntervalBandUpperAccessor",
|
|
57
|
+
() => accessor(upperInput),
|
|
58
|
+
[upperInput]
|
|
59
|
+
);
|
|
60
|
+
const data = resolveSignalValue(dataInput);
|
|
61
|
+
if (!Array.isArray(data))
|
|
62
|
+
throw new TypeError(
|
|
63
|
+
"IntervalBandSeries data must be an array or a signal containing an array."
|
|
64
|
+
);
|
|
65
|
+
const style = resolveSignalValue(styleInput) ?? {};
|
|
66
|
+
if (style === null || typeof style !== "object" || Array.isArray(style))
|
|
67
|
+
throw new TypeError("IntervalBandSeries: style must be an object.");
|
|
68
|
+
const bandFill = fill(resolveSignalValue(style.fill) ?? "#2563eb");
|
|
69
|
+
const alpha = opacity(
|
|
70
|
+
resolveSignalValue(style.opacity) ?? 0.2,
|
|
71
|
+
"IntervalBandSeries"
|
|
72
|
+
);
|
|
73
|
+
const cursor = resolveSignalValue(style.cursor);
|
|
74
|
+
if (cursor !== void 0 && typeof cursor !== "string")
|
|
75
|
+
throw new TypeError("IntervalBandSeries: cursor must be a string.");
|
|
76
|
+
const path = new Path2D();
|
|
77
|
+
let run = [];
|
|
78
|
+
const closeRun = () => {
|
|
79
|
+
if (run.length >= 2) {
|
|
80
|
+
const upper2 = curveGeometry(
|
|
81
|
+
curveDefinition,
|
|
82
|
+
run.map(([x2, _lower, value]) => [x2, value])
|
|
83
|
+
);
|
|
84
|
+
const lower2 = curveGeometry(
|
|
85
|
+
curveDefinition,
|
|
86
|
+
run.map(([x2, value]) => [x2, value])
|
|
87
|
+
);
|
|
88
|
+
validatePairedCurveGeometry(upper2, lower2);
|
|
89
|
+
path.moveTo(upper2.start[0], upper2.start[1]);
|
|
90
|
+
appendCurveForward(path, upper2);
|
|
91
|
+
appendCurveReverse(path, lower2);
|
|
92
|
+
path.closePath();
|
|
93
|
+
}
|
|
94
|
+
run = [];
|
|
95
|
+
};
|
|
96
|
+
for (let i = 0; i < data.length; i++) {
|
|
97
|
+
const datum = data[i];
|
|
98
|
+
if (defined && !defined(datum, i, data)) {
|
|
99
|
+
closeRun();
|
|
100
|
+
continue;
|
|
101
|
+
}
|
|
102
|
+
const xv = x(datum, i, data);
|
|
103
|
+
const lowerValue = lower(datum, i, data);
|
|
104
|
+
const upperValue = upper(datum, i, data);
|
|
105
|
+
if (typeof xv !== "number" || typeof lowerValue !== "number" || typeof upperValue !== "number" || !Number.isFinite(xv) || !Number.isFinite(lowerValue) || !Number.isFinite(upperValue)) {
|
|
106
|
+
closeRun();
|
|
107
|
+
continue;
|
|
108
|
+
}
|
|
109
|
+
if (lowerValue > upperValue)
|
|
110
|
+
throw new RangeError(
|
|
111
|
+
`IntervalBandSeries datum at index ${i} has lower bound above upper bound.`
|
|
112
|
+
);
|
|
113
|
+
const point = [
|
|
114
|
+
xScale.map(xv),
|
|
115
|
+
yScale.map(lowerValue),
|
|
116
|
+
yScale.map(upperValue)
|
|
117
|
+
];
|
|
118
|
+
if (!point.every(Number.isFinite)) {
|
|
119
|
+
closeRun();
|
|
120
|
+
continue;
|
|
121
|
+
}
|
|
122
|
+
run.push(point);
|
|
123
|
+
}
|
|
124
|
+
closeRun();
|
|
125
|
+
return /* @__PURE__ */ jsx(
|
|
126
|
+
Path,
|
|
127
|
+
{
|
|
128
|
+
...eventProps,
|
|
129
|
+
style: { d: path, fill: bandFill, opacity: alpha, cursor }
|
|
130
|
+
}
|
|
131
|
+
);
|
|
132
|
+
}
|
|
133
|
+
export {
|
|
134
|
+
IntervalBandSeries
|
|
135
|
+
};
|
|
136
|
+
//# sourceMappingURL=interval-band-series.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../../src/features/viz/lib/interval-band-series.tsx"],
|
|
4
|
+
"sourcesContent": ["import { useNumericPosition } from \"./series-position.js\";\nimport { Path, resolveSignalValue } from \"@pibbl/core\";\nimport type {\n FillStyle,\n PibblEventHandlers,\n PibblEventParticipationOptions,\n SignalValue,\n} from \"@pibbl/core\";\nimport {\n useInternalValueMemoSlot,\n validateTexturePaint,\n} from \"@pibbl/core/internal\";\nimport type { SignalStyle } from \"@pibbl/core/internal\";\nimport type { AreaSeriesStyle } from \"./area-series.js\";\nimport { opacity } from \"./paint.js\";\nimport type { LineAccessor, LineCoordinate, LineSeriesProps } from \"./types.js\";\nimport {\n appendCurveForward,\n appendCurveReverse,\n curveGeometry,\n resolveSeriesCurve,\n validatePairedCurveGeometry,\n} from \"./curve-definition.js\";\nimport { useContinuousScale } from \"./use-continuous-scale.js\";\n\n/**\n * Authored inputs for {@link IntervalBandSeries}.\n *\n * The data, horizontal coordinate, scales, and defined predicate use the same contract as\n * {@link LineSeriesProps}. Each contiguous run of at least two observations draws its upper\n * boundary forward and lower boundary backward.\n *\n * @see {@link AreaSeriesStyle}\n * @see {@link LineSeriesProps}\n */\nexport interface IntervalBandSeriesProps<D>\n extends PibblEventHandlers, PibblEventParticipationOptions {\n /** Application data supplied directly or through a signal. */\n readonly data: LineSeriesProps<D>[\"data\"];\n /** Property key or callback extracting the horizontal coordinate. */\n readonly x: LineAccessor<D>;\n /** Property key or callback extracting the lower bound. */\n readonly lower: LineAccessor<D>;\n /** Property key or callback extracting the upper bound. */\n readonly upper: LineAccessor<D>;\n /** Continuous scale used to map horizontal data coordinates. */\n readonly xScale: LineSeriesProps<D>[\"xScale\"];\n /** Continuous scale used to map both data bounds. */\n readonly yScale: LineSeriesProps<D>[\"yScale\"];\n /** Selects records that participate in a matching-bounds run. */\n readonly defined?: LineSeriesProps<D>[\"defined\"];\n /** Curve used to connect successive matching bounds. */\n readonly curve?: LineSeriesProps<D>[\"curve\"];\n /** Shared band presentation. Individual datum styling is not supported. */\n readonly style?: SignalValue<SignalStyle<AreaSeriesStyle>>;\n}\n\nfunction accessor<D>(\n input: LineAccessor<D>,\n): (datum: D, index: number, data: readonly D[]) => LineCoordinate {\n return typeof input === \"function\"\n ? input\n : (datum) => datum[input] as LineCoordinate;\n}\n\nfunction fill(value: unknown): FillStyle {\n if (\n typeof value === \"string\" ||\n value instanceof CanvasGradient ||\n value instanceof CanvasPattern\n )\n return value;\n try {\n validateTexturePaint(value as never);\n return value as FillStyle;\n } catch {\n throw new TypeError(\"IntervalBandSeries: invalid fill.\");\n }\n}\n\n/**\n * Draws a filled band between matching lower and upper observations.\n *\n * Missing, non-finite, and excluded coordinates split runs. A lower value above its upper\n * value rejects the datum; equal bounds produce zero-area geometry. The component owns one\n * ordinary {@link Path} target, so event participation follows standard Path defaults.\n *\n * @param props - Data, coordinate accessors, continuous scales, and presentation.\n * @returns A Pibbl path node containing all drawable interval-band runs.\n * @throws When data, presentation, or bounds are invalid.\n *\n * @see {@link IntervalBandSeriesProps}\n */\nexport function IntervalBandSeries<D>({\n data: dataInput,\n x: xInput,\n lower: lowerInput,\n upper: upperInput,\n xScale: xId,\n yScale: yId,\n defined,\n curve,\n style: styleInput,\n ...eventProps\n}: IntervalBandSeriesProps<D>) {\n const xScale = useNumericPosition(xId);\n const yScale = useContinuousScale(yId).get();\n const curveDefinition = resolveSeriesCurve(curve);\n const x = useInternalValueMemoSlot(\n \"vizIntervalBandXAccessor\",\n () => accessor(xInput),\n [xInput],\n );\n const lower = useInternalValueMemoSlot(\n \"vizIntervalBandLowerAccessor\",\n () => accessor(lowerInput),\n [lowerInput],\n );\n const upper = useInternalValueMemoSlot(\n \"vizIntervalBandUpperAccessor\",\n () => accessor(upperInput),\n [upperInput],\n );\n const data = resolveSignalValue(dataInput);\n if (!Array.isArray(data))\n throw new TypeError(\n \"IntervalBandSeries data must be an array or a signal containing an array.\",\n );\n const style = resolveSignalValue(styleInput) ?? {};\n if (style === null || typeof style !== \"object\" || Array.isArray(style))\n throw new TypeError(\"IntervalBandSeries: style must be an object.\");\n const bandFill = fill(resolveSignalValue(style.fill) ?? \"#2563eb\");\n const alpha = opacity(\n resolveSignalValue(style.opacity) ?? 0.2,\n \"IntervalBandSeries\",\n );\n const cursor = resolveSignalValue(style.cursor);\n if (cursor !== undefined && typeof cursor !== \"string\")\n throw new TypeError(\"IntervalBandSeries: cursor must be a string.\");\n\n const path = new Path2D();\n let run: (readonly [number, number, number])[] = [];\n const closeRun = () => {\n if (run.length >= 2) {\n const upper = curveGeometry(\n curveDefinition,\n run.map(([x, _lower, value]) => [x, value] as const),\n );\n const lower = curveGeometry(\n curveDefinition,\n run.map(([x, value]) => [x, value] as const),\n );\n validatePairedCurveGeometry(upper, lower);\n path.moveTo(upper.start[0], upper.start[1]);\n appendCurveForward(path, upper);\n appendCurveReverse(path, lower);\n path.closePath();\n }\n run = [];\n };\n for (let i = 0; i < data.length; i++) {\n const datum = data[i];\n if (defined && !defined(datum, i, data)) {\n closeRun();\n continue;\n }\n const xv = x(datum, i, data);\n const lowerValue = lower(datum, i, data);\n const upperValue = upper(datum, i, data);\n if (\n typeof xv !== \"number\" ||\n typeof lowerValue !== \"number\" ||\n typeof upperValue !== \"number\" ||\n !Number.isFinite(xv) ||\n !Number.isFinite(lowerValue) ||\n !Number.isFinite(upperValue)\n ) {\n closeRun();\n continue;\n }\n if (lowerValue > upperValue)\n throw new RangeError(\n `IntervalBandSeries datum at index ${i} has lower bound above upper bound.`,\n );\n const point = [\n xScale.map(xv),\n yScale.map(lowerValue),\n yScale.map(upperValue),\n ] as const;\n if (!point.every(Number.isFinite)) {\n closeRun();\n continue;\n }\n run.push(point);\n }\n closeRun();\n return (\n <Path\n {...eventProps}\n style={{ d: path, fill: bandFill, opacity: alpha, cursor }}\n />\n );\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": ["upper", "x", "lower"]
|
|
7
|
+
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { type FillStyle, type PibblNode, type SignalValue, type StrokeStyle } from "@pibbl/core";
|
|
2
|
+
import { type SignalStyle } from "@pibbl/core/internal";
|
|
3
|
+
import type { IntervalSeriesProps } from "./interval-series.js";
|
|
4
|
+
/** Local-pixel height and shared paint for supplied summary diamonds.
|
|
5
|
+
* @see {@link IntervalDiamondSeries}
|
|
6
|
+
*/
|
|
7
|
+
export interface IntervalDiamondSeriesStyle {
|
|
8
|
+
/** Full perpendicular height in local pixels; defaults to 12. Zero hides marks. */
|
|
9
|
+
readonly height?: number;
|
|
10
|
+
/** Diamond interior paint; defaults to #087f8c. */
|
|
11
|
+
readonly fill?: FillStyle;
|
|
12
|
+
/** Diamond outline paint; defaults to #087f8c. */
|
|
13
|
+
readonly stroke?: StrokeStyle;
|
|
14
|
+
/** Visible outline width in local pixels; defaults to 1.5. */
|
|
15
|
+
readonly strokeWidth?: number;
|
|
16
|
+
/** Outline targeting width in local pixels; defaults to strokeWidth. */
|
|
17
|
+
readonly lineInteractionWidth?: number;
|
|
18
|
+
/** Shared opacity from zero to one; defaults to 1. */
|
|
19
|
+
readonly opacity?: number;
|
|
20
|
+
/** Cursor shown over painted diamonds. */
|
|
21
|
+
readonly cursor?: string;
|
|
22
|
+
}
|
|
23
|
+
/** Supplied summary estimates and bounds placed horizontally at categorical centers.
|
|
24
|
+
* @see {@link IntervalSeriesProps}
|
|
25
|
+
* @see {@link IntervalDiamondSeriesStyle}
|
|
26
|
+
*/
|
|
27
|
+
export interface IntervalDiamondSeriesProps<D> extends Omit<IntervalSeriesProps<D>, "style"> {
|
|
28
|
+
/** Whole-object and shallow field signals are observed; per-datum styling is not supported. */
|
|
29
|
+
readonly style?: SignalValue<SignalStyle<IntervalDiamondSeriesStyle>>;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Draw supplied summary estimates as horizontal diamonds; no pooling or inference.
|
|
33
|
+
* Left/right tips map lower/upper, top/bottom map the estimate. Estimates must
|
|
34
|
+
* lie inside the supplied bounds. Missing/nonfinite rows and unknown categories
|
|
35
|
+
* are omitted; reversed bounds and invalid log values reject included rows.
|
|
36
|
+
* Diamonds share one ordinary Path target; handlers receive ordinary events.
|
|
37
|
+
* Mapping does not clamp or clip. Compose a Clip when required.
|
|
38
|
+
*
|
|
39
|
+
* @param props - Supplied rows, accessors, categorical/value scales, and shared paint.
|
|
40
|
+
* @returns One batched Pibbl Path containing the supplied diamonds in source order.
|
|
41
|
+
* @see {@link IntervalDiamondSeriesProps}
|
|
42
|
+
*/
|
|
43
|
+
export declare function IntervalDiamondSeries<D>(props: IntervalDiamondSeriesProps<D>): PibblNode;
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
import { jsx } from "@pibbl/core/jsx-runtime";
|
|
2
|
+
import {
|
|
3
|
+
Path,
|
|
4
|
+
resolveSignalValue
|
|
5
|
+
} from "@pibbl/core";
|
|
6
|
+
import { withHooksForbidden } from "@pibbl/core/internal";
|
|
7
|
+
import { lookupScale } from "./scale-context.js";
|
|
8
|
+
import { useContinuousScale } from "./use-continuous-scale.js";
|
|
9
|
+
import { finiteCoordinate, pointAccessor, pointData } from "./point-data.js";
|
|
10
|
+
import { opacity, width } from "./paint.js";
|
|
11
|
+
function IntervalDiamondSeries(props) {
|
|
12
|
+
const receiver = "IntervalDiamondSeries";
|
|
13
|
+
const {
|
|
14
|
+
data: input,
|
|
15
|
+
category: categoryInput,
|
|
16
|
+
estimate: estimateInput,
|
|
17
|
+
lower: lowerInput,
|
|
18
|
+
upper: upperInput,
|
|
19
|
+
categoryScale,
|
|
20
|
+
valueScale,
|
|
21
|
+
defined,
|
|
22
|
+
style: styleInput,
|
|
23
|
+
...events
|
|
24
|
+
} = props;
|
|
25
|
+
const categories = lookupScale(categoryScale, receiver)?.get();
|
|
26
|
+
const values = useContinuousScale(valueScale).get();
|
|
27
|
+
if (!categories || categories.type !== "point" && categories.type !== "band")
|
|
28
|
+
throw new TypeError(
|
|
29
|
+
`${receiver}: categoryScale requires PointScale or BarScale.`
|
|
30
|
+
);
|
|
31
|
+
const data = pointData(resolveSignalValue(input), receiver);
|
|
32
|
+
const category = typeof categoryInput === "function" ? categoryInput : (datum) => datum[categoryInput];
|
|
33
|
+
const estimate = pointAccessor(estimateInput), lower = pointAccessor(lowerInput), upper = pointAccessor(upperInput);
|
|
34
|
+
const specified = resolveSignalValue(styleInput) ?? {};
|
|
35
|
+
if (typeof specified !== "object" || Array.isArray(specified))
|
|
36
|
+
throw new TypeError(`${receiver}: style must be an object.`);
|
|
37
|
+
const resolved = {};
|
|
38
|
+
for (const key of Object.keys(specified)) {
|
|
39
|
+
if (![
|
|
40
|
+
"height",
|
|
41
|
+
"fill",
|
|
42
|
+
"stroke",
|
|
43
|
+
"strokeWidth",
|
|
44
|
+
"lineInteractionWidth",
|
|
45
|
+
"opacity",
|
|
46
|
+
"cursor"
|
|
47
|
+
].includes(key))
|
|
48
|
+
throw new TypeError(`${receiver}: unsupported style field ${key}.`);
|
|
49
|
+
resolved[key] = resolveSignalValue(
|
|
50
|
+
specified[key]
|
|
51
|
+
);
|
|
52
|
+
}
|
|
53
|
+
const style = resolved;
|
|
54
|
+
const halfHeight = width(style.height ?? 12, `${receiver} height`) / 2;
|
|
55
|
+
const strokeWidth = width(style.strokeWidth ?? 1.5, receiver);
|
|
56
|
+
const lineInteractionWidth = width(
|
|
57
|
+
style.lineInteractionWidth ?? strokeWidth,
|
|
58
|
+
receiver
|
|
59
|
+
);
|
|
60
|
+
const alpha = opacity(style.opacity ?? 1, receiver);
|
|
61
|
+
if (style.cursor !== void 0 && typeof style.cursor !== "string")
|
|
62
|
+
throw new TypeError(`${receiver}: cursor must be a string.`);
|
|
63
|
+
const path = new Path2D();
|
|
64
|
+
for (let i = 0; i < data.length; i++) {
|
|
65
|
+
const datum = data[i];
|
|
66
|
+
const row = withHooksForbidden(
|
|
67
|
+
`${receiver}: accessors cannot call hooks.`,
|
|
68
|
+
() => {
|
|
69
|
+
if (defined && !defined(datum, i, data)) return void 0;
|
|
70
|
+
return {
|
|
71
|
+
category: category(datum, i, data),
|
|
72
|
+
estimate: estimate(datum, i, data),
|
|
73
|
+
lower: lower(datum, i, data),
|
|
74
|
+
upper: upper(datum, i, data)
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
);
|
|
78
|
+
if (!row || row.category == null || !finiteCoordinate(row.estimate) || !finiteCoordinate(row.lower) || !finiteCoordinate(row.upper))
|
|
79
|
+
continue;
|
|
80
|
+
const start = categories.map(row.category);
|
|
81
|
+
if (start === void 0) continue;
|
|
82
|
+
if (row.lower > row.upper)
|
|
83
|
+
throw new RangeError(
|
|
84
|
+
`${receiver}: lower must not exceed upper (row ${i}).`
|
|
85
|
+
);
|
|
86
|
+
if (row.estimate < row.lower || row.estimate > row.upper)
|
|
87
|
+
throw new RangeError(
|
|
88
|
+
`${receiver}: estimate must lie inside supplied bounds (row ${i}).`
|
|
89
|
+
);
|
|
90
|
+
const center = start + (categories.type === "band" ? categories.bandwidth / 2 : 0);
|
|
91
|
+
const lo = values.map(row.lower), hi = values.map(row.upper), point = values.map(row.estimate);
|
|
92
|
+
if (![center - halfHeight, center + halfHeight, lo, hi, point].every(
|
|
93
|
+
Number.isFinite
|
|
94
|
+
))
|
|
95
|
+
throw new RangeError(
|
|
96
|
+
`${receiver}: mapped coordinates must be finite (row ${i}).`
|
|
97
|
+
);
|
|
98
|
+
if (halfHeight === 0) continue;
|
|
99
|
+
path.moveTo(lo, center);
|
|
100
|
+
path.lineTo(point, center - halfHeight);
|
|
101
|
+
path.lineTo(hi, center);
|
|
102
|
+
path.lineTo(point, center + halfHeight);
|
|
103
|
+
path.closePath();
|
|
104
|
+
}
|
|
105
|
+
return /* @__PURE__ */ jsx(
|
|
106
|
+
Path,
|
|
107
|
+
{
|
|
108
|
+
...events,
|
|
109
|
+
style: {
|
|
110
|
+
d: path,
|
|
111
|
+
fill: style.fill ?? "#087f8c",
|
|
112
|
+
stroke: style.stroke ?? "#087f8c",
|
|
113
|
+
strokeWidth,
|
|
114
|
+
lineInteractionWidth,
|
|
115
|
+
opacity: alpha,
|
|
116
|
+
cursor: style.cursor
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
);
|
|
120
|
+
}
|
|
121
|
+
export {
|
|
122
|
+
IntervalDiamondSeries
|
|
123
|
+
};
|
|
124
|
+
//# sourceMappingURL=interval-diamond-series.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../../src/features/viz/lib/interval-diamond-series.tsx"],
|
|
4
|
+
"sourcesContent": ["import {\n Path,\n resolveSignalValue,\n type FillStyle,\n type PibblNode,\n type SignalValue,\n type StrokeStyle,\n} from \"@pibbl/core\";\nimport { withHooksForbidden, type SignalStyle } from \"@pibbl/core/internal\";\nimport type { IntervalSeriesProps } from \"./interval-series.js\";\nimport type { BandCategory } from \"./types.js\";\nimport { lookupScale } from \"./scale-context.js\";\nimport { useContinuousScale } from \"./use-continuous-scale.js\";\nimport { finiteCoordinate, pointAccessor, pointData } from \"./point-data.js\";\nimport { opacity, width } from \"./paint.js\";\n\n/** Local-pixel height and shared paint for supplied summary diamonds.\n * @see {@link IntervalDiamondSeries}\n */\nexport interface IntervalDiamondSeriesStyle {\n /** Full perpendicular height in local pixels; defaults to 12. Zero hides marks. */\n readonly height?: number;\n /** Diamond interior paint; defaults to #087f8c. */\n readonly fill?: FillStyle;\n /** Diamond outline paint; defaults to #087f8c. */\n readonly stroke?: StrokeStyle;\n /** Visible outline width in local pixels; defaults to 1.5. */\n readonly strokeWidth?: number;\n /** Outline targeting width in local pixels; defaults to strokeWidth. */\n readonly lineInteractionWidth?: number;\n /** Shared opacity from zero to one; defaults to 1. */\n readonly opacity?: number;\n /** Cursor shown over painted diamonds. */\n readonly cursor?: string;\n}\n\n/** Supplied summary estimates and bounds placed horizontally at categorical centers.\n * @see {@link IntervalSeriesProps}\n * @see {@link IntervalDiamondSeriesStyle}\n */\nexport interface IntervalDiamondSeriesProps<D> extends Omit<\n IntervalSeriesProps<D>,\n \"style\"\n> {\n /** Whole-object and shallow field signals are observed; per-datum styling is not supported. */\n readonly style?: SignalValue<SignalStyle<IntervalDiamondSeriesStyle>>;\n}\n\n/**\n * Draw supplied summary estimates as horizontal diamonds; no pooling or inference.\n * Left/right tips map lower/upper, top/bottom map the estimate. Estimates must\n * lie inside the supplied bounds. Missing/nonfinite rows and unknown categories\n * are omitted; reversed bounds and invalid log values reject included rows.\n * Diamonds share one ordinary Path target; handlers receive ordinary events.\n * Mapping does not clamp or clip. Compose a Clip when required.\n *\n * @param props - Supplied rows, accessors, categorical/value scales, and shared paint.\n * @returns One batched Pibbl Path containing the supplied diamonds in source order.\n * @see {@link IntervalDiamondSeriesProps}\n */\nexport function IntervalDiamondSeries<D>(\n props: IntervalDiamondSeriesProps<D>,\n): PibblNode {\n const receiver = \"IntervalDiamondSeries\";\n const {\n data: input,\n category: categoryInput,\n estimate: estimateInput,\n lower: lowerInput,\n upper: upperInput,\n categoryScale,\n valueScale,\n defined,\n style: styleInput,\n ...events\n } = props;\n const categories = lookupScale(categoryScale, receiver)?.get();\n const values = useContinuousScale(valueScale).get();\n if (\n !categories ||\n (categories.type !== \"point\" && categories.type !== \"band\")\n )\n throw new TypeError(\n `${receiver}: categoryScale requires PointScale or BarScale.`,\n );\n const data = pointData(resolveSignalValue(input), receiver);\n const category =\n typeof categoryInput === \"function\"\n ? categoryInput\n : (datum: D) => datum[categoryInput] as BandCategory | null | undefined;\n const estimate = pointAccessor(estimateInput),\n lower = pointAccessor(lowerInput),\n upper = pointAccessor(upperInput);\n const specified = resolveSignalValue(styleInput) ?? {};\n if (typeof specified !== \"object\" || Array.isArray(specified))\n throw new TypeError(`${receiver}: style must be an object.`);\n const resolved: Record<string, unknown> = {};\n for (const key of Object.keys(specified)) {\n if (\n ![\n \"height\",\n \"fill\",\n \"stroke\",\n \"strokeWidth\",\n \"lineInteractionWidth\",\n \"opacity\",\n \"cursor\",\n ].includes(key)\n )\n throw new TypeError(`${receiver}: unsupported style field ${key}.`);\n resolved[key] = resolveSignalValue(\n specified[key as keyof typeof specified],\n );\n }\n const style = resolved as IntervalDiamondSeriesStyle;\n const halfHeight = width(style.height ?? 12, `${receiver} height`) / 2;\n const strokeWidth = width(style.strokeWidth ?? 1.5, receiver);\n const lineInteractionWidth = width(\n style.lineInteractionWidth ?? strokeWidth,\n receiver,\n );\n const alpha = opacity(style.opacity ?? 1, receiver);\n if (style.cursor !== undefined && typeof style.cursor !== \"string\")\n throw new TypeError(`${receiver}: cursor must be a string.`);\n const path = new Path2D();\n for (let i = 0; i < data.length; i++) {\n const datum = data[i];\n const row = withHooksForbidden(\n `${receiver}: accessors cannot call hooks.`,\n () => {\n if (defined && !defined(datum, i, data)) return undefined;\n return {\n category: category(datum, i, data),\n estimate: estimate(datum, i, data),\n lower: lower(datum, i, data),\n upper: upper(datum, i, data),\n };\n },\n );\n if (\n !row ||\n row.category == null ||\n !finiteCoordinate(row.estimate) ||\n !finiteCoordinate(row.lower) ||\n !finiteCoordinate(row.upper)\n )\n continue;\n const start = categories.map(row.category);\n if (start === undefined) continue;\n if (row.lower > row.upper)\n throw new RangeError(\n `${receiver}: lower must not exceed upper (row ${i}).`,\n );\n if (row.estimate < row.lower || row.estimate > row.upper)\n throw new RangeError(\n `${receiver}: estimate must lie inside supplied bounds (row ${i}).`,\n );\n const center =\n start + (categories.type === \"band\" ? categories.bandwidth / 2 : 0);\n const lo = values.map(row.lower),\n hi = values.map(row.upper),\n point = values.map(row.estimate);\n if (\n ![center - halfHeight, center + halfHeight, lo, hi, point].every(\n Number.isFinite,\n )\n )\n throw new RangeError(\n `${receiver}: mapped coordinates must be finite (row ${i}).`,\n );\n if (halfHeight === 0) continue;\n path.moveTo(lo, center);\n path.lineTo(point, center - halfHeight);\n path.lineTo(hi, center);\n path.lineTo(point, center + halfHeight);\n path.closePath();\n }\n return (\n <Path\n {...events}\n style={{\n d: path,\n fill: style.fill ?? \"#087f8c\",\n stroke: style.stroke ?? \"#087f8c\",\n strokeWidth,\n lineInteractionWidth,\n opacity: alpha,\n cursor: style.cursor,\n }}\n />\n );\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import type { FillStyle, PibblEventHandlers, PibblEventParticipationOptions, PibblNode, SignalValue, StrokeStyle } from "@pibbl/core";
|
|
2
|
+
import type { SignalStyle } from "@pibbl/core/internal";
|
|
3
|
+
import type { BarCategoryAccessor } from "./bar-series.js";
|
|
4
|
+
import type { LineAccessor, ScaleId } from "./types.js";
|
|
5
|
+
/** Shared local-pixel geometry and paint for estimate-and-interval marks.
|
|
6
|
+
* @see {@link IntervalSeriesProps}
|
|
7
|
+
*/
|
|
8
|
+
export interface IntervalSeriesStyle {
|
|
9
|
+
/** Estimate circle radius in local pixels; defaults to 4. */
|
|
10
|
+
readonly radius?: number;
|
|
11
|
+
/** Full perpendicular length of each endpoint cap; defaults to 8 pixels. */
|
|
12
|
+
readonly capSize?: number;
|
|
13
|
+
/** Estimate circle fill; defaults to #087f8c. */
|
|
14
|
+
readonly fill?: FillStyle;
|
|
15
|
+
/** Interval, cap, and circle outline paint; defaults to #087f8c. */
|
|
16
|
+
readonly stroke?: StrokeStyle;
|
|
17
|
+
/** Visible stroke width in local pixels; defaults to 1.5. */
|
|
18
|
+
readonly strokeWidth?: number;
|
|
19
|
+
/** Stroke targeting width, independent of visible width; defaults to strokeWidth. */
|
|
20
|
+
readonly lineInteractionWidth?: number;
|
|
21
|
+
/** Shared paint opacity from zero to one; defaults to 1. */
|
|
22
|
+
readonly opacity?: number;
|
|
23
|
+
/** Cursor for painted mark targets. */
|
|
24
|
+
readonly cursor?: string;
|
|
25
|
+
}
|
|
26
|
+
/** Explicit supplied estimates and numeric bounds placed at categorical centers.
|
|
27
|
+
* @see {@link HorizontalIntervalSeries}
|
|
28
|
+
* @see {@link VerticalIntervalSeries}
|
|
29
|
+
*/
|
|
30
|
+
export interface IntervalSeriesProps<D> extends PibblEventHandlers, PibblEventParticipationOptions {
|
|
31
|
+
/** Original records, or a signal of records; no estimation is performed. */
|
|
32
|
+
readonly data: SignalValue<readonly D[]>;
|
|
33
|
+
/** Property or callback supplying a category; missing/unknown categories omit rows. */
|
|
34
|
+
readonly category: BarCategoryAccessor<D>;
|
|
35
|
+
/** Property or callback supplying the numeric point estimate. */
|
|
36
|
+
readonly estimate: LineAccessor<D>;
|
|
37
|
+
/** Property or callback supplying the numeric lower bound. */
|
|
38
|
+
readonly lower: LineAccessor<D>;
|
|
39
|
+
/** Property or callback supplying the numeric upper bound. */
|
|
40
|
+
readonly upper: LineAccessor<D>;
|
|
41
|
+
/** Ancestor PointScale or BarScale; band categories use their centers. */
|
|
42
|
+
readonly categoryScale: ScaleId;
|
|
43
|
+
/** Ancestor continuous numeric scale mapping estimate and both bounds independently. */
|
|
44
|
+
readonly valueScale: ScaleId;
|
|
45
|
+
/** Optional synchronous predicate; excluded rows contribute no marks.
|
|
46
|
+
* @param datum - Original record being tested.
|
|
47
|
+
* @param index - Source index of the record.
|
|
48
|
+
* @param data - Complete supplied data array.
|
|
49
|
+
* @returns Whether to include this record's estimate and interval.
|
|
50
|
+
*/
|
|
51
|
+
readonly defined?: (datum: D, index: number, data: readonly D[]) => boolean;
|
|
52
|
+
/** Shared style; whole-object and shallow field signals are observed by the series. */
|
|
53
|
+
readonly style?: SignalValue<SignalStyle<IntervalSeriesStyle>>;
|
|
54
|
+
}
|
|
55
|
+
/** Horizontal estimate-and-interval authoring inputs. See {@link HorizontalIntervalSeries}. */
|
|
56
|
+
export type HorizontalIntervalSeriesProps<D> = IntervalSeriesProps<D>;
|
|
57
|
+
/** Vertical estimate-and-interval authoring inputs. See {@link VerticalIntervalSeries}. */
|
|
58
|
+
export type VerticalIntervalSeriesProps<D> = IntervalSeriesProps<D>;
|
|
59
|
+
/**
|
|
60
|
+
* Draw supplied numeric intervals horizontally with an estimate circle per category.
|
|
61
|
+
* Missing/non-finite coordinates omit the entire row; reversed bounds reject it.
|
|
62
|
+
* Mapping does not clamp or clip; compose a Clip when required. Marks use ordinary
|
|
63
|
+
* Line/Circle targets, with series handlers receiving their bubbled events.
|
|
64
|
+
*
|
|
65
|
+
* @param props - Supplied data, categorical/numeric scale IDs, and shared style.
|
|
66
|
+
* @returns Ordinary Pibbl content in source order, interval then circle for each row.
|
|
67
|
+
* @see {@link HorizontalIntervalSeriesProps}
|
|
68
|
+
*/
|
|
69
|
+
export declare function HorizontalIntervalSeries<D>(props: HorizontalIntervalSeriesProps<D>): PibblNode;
|
|
70
|
+
/**
|
|
71
|
+
* Draw supplied numeric intervals vertically with an estimate circle per category.
|
|
72
|
+
* Shares the missing-data, bounds, paint, targeting, and clipping contract of
|
|
73
|
+
* HorizontalIntervalSeries; orientation is explicit in the operation name.
|
|
74
|
+
*
|
|
75
|
+
* @param props - Supplied data, categorical/numeric scale IDs, and shared style.
|
|
76
|
+
* @returns Ordinary Pibbl content in source order, interval then circle for each row.
|
|
77
|
+
* @see {@link VerticalIntervalSeriesProps}
|
|
78
|
+
*/
|
|
79
|
+
export declare function VerticalIntervalSeries<D>(props: VerticalIntervalSeriesProps<D>): PibblNode;
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
import { Fragment, jsx, jsxs } from "@pibbl/core/jsx-runtime";
|
|
2
|
+
import { Circle, Group, Line, resolveSignalValue } from "@pibbl/core";
|
|
3
|
+
import { withHooksForbidden } from "@pibbl/core/internal";
|
|
4
|
+
import { lookupScale } from "./scale-context.js";
|
|
5
|
+
import { useContinuousScale } from "./use-continuous-scale.js";
|
|
6
|
+
import { finiteCoordinate, pointAccessor, pointData } from "./point-data.js";
|
|
7
|
+
import { opacity, width } from "./paint.js";
|
|
8
|
+
function intervalSeries(props, horizontal) {
|
|
9
|
+
const receiver = horizontal ? "HorizontalIntervalSeries" : "VerticalIntervalSeries";
|
|
10
|
+
const {
|
|
11
|
+
data: input,
|
|
12
|
+
category: categoryInput,
|
|
13
|
+
estimate: estimateInput,
|
|
14
|
+
lower: lowerInput,
|
|
15
|
+
upper: upperInput,
|
|
16
|
+
categoryScale,
|
|
17
|
+
valueScale,
|
|
18
|
+
defined,
|
|
19
|
+
style: styleInput,
|
|
20
|
+
pointerEvents,
|
|
21
|
+
...events
|
|
22
|
+
} = props;
|
|
23
|
+
const categories = lookupScale(categoryScale, receiver)?.get();
|
|
24
|
+
const values = useContinuousScale(valueScale).get();
|
|
25
|
+
if (!categories || categories.type !== "point" && categories.type !== "band")
|
|
26
|
+
throw new TypeError(
|
|
27
|
+
`${receiver}: categoryScale requires PointScale or BarScale.`
|
|
28
|
+
);
|
|
29
|
+
const data = pointData(resolveSignalValue(input), receiver);
|
|
30
|
+
const category = typeof categoryInput === "function" ? categoryInput : (datum) => datum[categoryInput];
|
|
31
|
+
const estimate = pointAccessor(estimateInput), lower = pointAccessor(lowerInput), upper = pointAccessor(upperInput);
|
|
32
|
+
const specified = resolveSignalValue(styleInput) ?? {};
|
|
33
|
+
if (typeof specified !== "object" || Array.isArray(specified))
|
|
34
|
+
throw new TypeError(`${receiver}: style must be an object.`);
|
|
35
|
+
const style = {};
|
|
36
|
+
for (const key of Object.keys(specified)) {
|
|
37
|
+
if (![
|
|
38
|
+
"radius",
|
|
39
|
+
"capSize",
|
|
40
|
+
"fill",
|
|
41
|
+
"stroke",
|
|
42
|
+
"strokeWidth",
|
|
43
|
+
"lineInteractionWidth",
|
|
44
|
+
"opacity",
|
|
45
|
+
"cursor"
|
|
46
|
+
].includes(key))
|
|
47
|
+
throw new TypeError(`${receiver}: unsupported style field ${key}.`);
|
|
48
|
+
style[key] = resolveSignalValue(specified[key]);
|
|
49
|
+
}
|
|
50
|
+
const resolved = style;
|
|
51
|
+
const radius = width(resolved.radius ?? 4, `${receiver} radius`);
|
|
52
|
+
const halfCap = width(resolved.capSize ?? 8, `${receiver} capSize`) / 2;
|
|
53
|
+
const strokeWidth = width(resolved.strokeWidth ?? 1.5, receiver);
|
|
54
|
+
const lineInteractionWidth = width(
|
|
55
|
+
resolved.lineInteractionWidth ?? strokeWidth,
|
|
56
|
+
receiver
|
|
57
|
+
);
|
|
58
|
+
const alpha = opacity(resolved.opacity ?? 1, receiver);
|
|
59
|
+
if (resolved.cursor !== void 0 && typeof resolved.cursor !== "string")
|
|
60
|
+
throw new TypeError(`${receiver}: cursor must be a string.`);
|
|
61
|
+
const stroke = resolved.stroke ?? "#087f8c";
|
|
62
|
+
const lineStyle = {
|
|
63
|
+
stroke,
|
|
64
|
+
strokeWidth,
|
|
65
|
+
lineInteractionWidth,
|
|
66
|
+
opacity: alpha,
|
|
67
|
+
cursor: resolved.cursor
|
|
68
|
+
};
|
|
69
|
+
const nodes = [];
|
|
70
|
+
for (let i = 0; i < data.length; i++) {
|
|
71
|
+
const datum = data[i];
|
|
72
|
+
const coordinates = withHooksForbidden(
|
|
73
|
+
`${receiver}: accessors cannot call hooks.`,
|
|
74
|
+
() => {
|
|
75
|
+
if (defined && !defined(datum, i, data)) return void 0;
|
|
76
|
+
return {
|
|
77
|
+
category: category(datum, i, data),
|
|
78
|
+
estimate: estimate(datum, i, data),
|
|
79
|
+
lower: lower(datum, i, data),
|
|
80
|
+
upper: upper(datum, i, data)
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
);
|
|
84
|
+
if (!coordinates || coordinates.category == null || !finiteCoordinate(coordinates.estimate) || !finiteCoordinate(coordinates.lower) || !finiteCoordinate(coordinates.upper))
|
|
85
|
+
continue;
|
|
86
|
+
const start = categories.map(coordinates.category);
|
|
87
|
+
if (start === void 0) continue;
|
|
88
|
+
if (coordinates.lower > coordinates.upper)
|
|
89
|
+
throw new RangeError(
|
|
90
|
+
`${receiver}: lower must not exceed upper (row ${i}).`
|
|
91
|
+
);
|
|
92
|
+
const center = start + (categories.type === "band" ? categories.bandwidth / 2 : 0);
|
|
93
|
+
const lo = values.map(coordinates.lower), hi = values.map(coordinates.upper), point = values.map(coordinates.estimate);
|
|
94
|
+
if (![center, lo, hi, point].every(Number.isFinite))
|
|
95
|
+
throw new RangeError(
|
|
96
|
+
`${receiver}: mapped coordinates must be finite (row ${i}).`
|
|
97
|
+
);
|
|
98
|
+
const position = (value, offset = 0) => horizontal ? [value, center + offset] : [center + offset, value];
|
|
99
|
+
nodes.push(
|
|
100
|
+
/* @__PURE__ */ jsxs(Group, { children: [
|
|
101
|
+
/* @__PURE__ */ jsx(
|
|
102
|
+
Line,
|
|
103
|
+
{
|
|
104
|
+
pointerEvents,
|
|
105
|
+
style: { ...lineStyle, coords: [position(lo), position(hi)] }
|
|
106
|
+
}
|
|
107
|
+
),
|
|
108
|
+
halfCap > 0 && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
109
|
+
/* @__PURE__ */ jsx(
|
|
110
|
+
Line,
|
|
111
|
+
{
|
|
112
|
+
pointerEvents,
|
|
113
|
+
style: {
|
|
114
|
+
...lineStyle,
|
|
115
|
+
coords: [position(lo, -halfCap), position(lo, halfCap)]
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
),
|
|
119
|
+
/* @__PURE__ */ jsx(
|
|
120
|
+
Line,
|
|
121
|
+
{
|
|
122
|
+
pointerEvents,
|
|
123
|
+
style: {
|
|
124
|
+
...lineStyle,
|
|
125
|
+
coords: [position(hi, -halfCap), position(hi, halfCap)]
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
)
|
|
129
|
+
] }),
|
|
130
|
+
radius > 0 && /* @__PURE__ */ jsx(
|
|
131
|
+
Circle,
|
|
132
|
+
{
|
|
133
|
+
pointerEvents,
|
|
134
|
+
style: {
|
|
135
|
+
...lineStyle,
|
|
136
|
+
cx: horizontal ? point : center,
|
|
137
|
+
cy: horizontal ? center : point,
|
|
138
|
+
radius,
|
|
139
|
+
fill: resolved.fill ?? "#087f8c"
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
)
|
|
143
|
+
] }, i)
|
|
144
|
+
);
|
|
145
|
+
}
|
|
146
|
+
return /* @__PURE__ */ jsx(Group, { ...events, children: nodes });
|
|
147
|
+
}
|
|
148
|
+
function HorizontalIntervalSeries(props) {
|
|
149
|
+
return intervalSeries(props, true);
|
|
150
|
+
}
|
|
151
|
+
function VerticalIntervalSeries(props) {
|
|
152
|
+
return intervalSeries(props, false);
|
|
153
|
+
}
|
|
154
|
+
export {
|
|
155
|
+
HorizontalIntervalSeries,
|
|
156
|
+
VerticalIntervalSeries
|
|
157
|
+
};
|
|
158
|
+
//# sourceMappingURL=interval-series.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../../src/features/viz/lib/interval-series.tsx"],
|
|
4
|
+
"sourcesContent": ["import { Circle, Group, Line, resolveSignalValue } from \"@pibbl/core\";\nimport type {\n FillStyle,\n PibblEventHandlers,\n PibblEventParticipationOptions,\n PibblNode,\n SignalValue,\n StrokeStyle,\n} from \"@pibbl/core\";\nimport type { SignalStyle } from \"@pibbl/core/internal\";\nimport { withHooksForbidden } from \"@pibbl/core/internal\";\nimport type { BarCategoryAccessor } from \"./bar-series.js\";\nimport type { BandCategory, LineAccessor, ScaleId } from \"./types.js\";\nimport { lookupScale } from \"./scale-context.js\";\nimport { useContinuousScale } from \"./use-continuous-scale.js\";\nimport { finiteCoordinate, pointAccessor, pointData } from \"./point-data.js\";\nimport { opacity, width } from \"./paint.js\";\n\n/** Shared local-pixel geometry and paint for estimate-and-interval marks.\n * @see {@link IntervalSeriesProps}\n */\nexport interface IntervalSeriesStyle {\n /** Estimate circle radius in local pixels; defaults to 4. */\n readonly radius?: number;\n /** Full perpendicular length of each endpoint cap; defaults to 8 pixels. */\n readonly capSize?: number;\n /** Estimate circle fill; defaults to #087f8c. */\n readonly fill?: FillStyle;\n /** Interval, cap, and circle outline paint; defaults to #087f8c. */\n readonly stroke?: StrokeStyle;\n /** Visible stroke width in local pixels; defaults to 1.5. */\n readonly strokeWidth?: number;\n /** Stroke targeting width, independent of visible width; defaults to strokeWidth. */\n readonly lineInteractionWidth?: number;\n /** Shared paint opacity from zero to one; defaults to 1. */\n readonly opacity?: number;\n /** Cursor for painted mark targets. */\n readonly cursor?: string;\n}\n\n/** Explicit supplied estimates and numeric bounds placed at categorical centers.\n * @see {@link HorizontalIntervalSeries}\n * @see {@link VerticalIntervalSeries}\n */\nexport interface IntervalSeriesProps<D>\n extends PibblEventHandlers, PibblEventParticipationOptions {\n /** Original records, or a signal of records; no estimation is performed. */\n readonly data: SignalValue<readonly D[]>;\n /** Property or callback supplying a category; missing/unknown categories omit rows. */\n readonly category: BarCategoryAccessor<D>;\n /** Property or callback supplying the numeric point estimate. */\n readonly estimate: LineAccessor<D>;\n /** Property or callback supplying the numeric lower bound. */\n readonly lower: LineAccessor<D>;\n /** Property or callback supplying the numeric upper bound. */\n readonly upper: LineAccessor<D>;\n /** Ancestor PointScale or BarScale; band categories use their centers. */\n readonly categoryScale: ScaleId;\n /** Ancestor continuous numeric scale mapping estimate and both bounds independently. */\n readonly valueScale: ScaleId;\n /** Optional synchronous predicate; excluded rows contribute no marks.\n * @param datum - Original record being tested.\n * @param index - Source index of the record.\n * @param data - Complete supplied data array.\n * @returns Whether to include this record's estimate and interval.\n */\n readonly defined?: (datum: D, index: number, data: readonly D[]) => boolean;\n /** Shared style; whole-object and shallow field signals are observed by the series. */\n readonly style?: SignalValue<SignalStyle<IntervalSeriesStyle>>;\n}\n\n/** Horizontal estimate-and-interval authoring inputs. See {@link HorizontalIntervalSeries}. */\nexport type HorizontalIntervalSeriesProps<D> = IntervalSeriesProps<D>;\n/** Vertical estimate-and-interval authoring inputs. See {@link VerticalIntervalSeries}. */\nexport type VerticalIntervalSeriesProps<D> = IntervalSeriesProps<D>;\n\nfunction intervalSeries<D>(\n props: IntervalSeriesProps<D>,\n horizontal: boolean,\n): PibblNode {\n const receiver = horizontal\n ? \"HorizontalIntervalSeries\"\n : \"VerticalIntervalSeries\";\n const {\n data: input,\n category: categoryInput,\n estimate: estimateInput,\n lower: lowerInput,\n upper: upperInput,\n categoryScale,\n valueScale,\n defined,\n style: styleInput,\n pointerEvents,\n ...events\n } = props;\n const categories = lookupScale(categoryScale, receiver)?.get();\n const values = useContinuousScale(valueScale).get();\n if (\n !categories ||\n (categories.type !== \"point\" && categories.type !== \"band\")\n )\n throw new TypeError(\n `${receiver}: categoryScale requires PointScale or BarScale.`,\n );\n const data = pointData(resolveSignalValue(input), receiver);\n const category =\n typeof categoryInput === \"function\"\n ? categoryInput\n : (datum: D) => datum[categoryInput] as BandCategory | null | undefined;\n const estimate = pointAccessor(estimateInput),\n lower = pointAccessor(lowerInput),\n upper = pointAccessor(upperInput);\n const specified = resolveSignalValue(styleInput) ?? {};\n if (typeof specified !== \"object\" || Array.isArray(specified))\n throw new TypeError(`${receiver}: style must be an object.`);\n const style: Record<string, unknown> = {};\n for (const key of Object.keys(specified)) {\n if (\n ![\n \"radius\",\n \"capSize\",\n \"fill\",\n \"stroke\",\n \"strokeWidth\",\n \"lineInteractionWidth\",\n \"opacity\",\n \"cursor\",\n ].includes(key)\n )\n throw new TypeError(`${receiver}: unsupported style field ${key}.`);\n style[key] = resolveSignalValue(specified[key as keyof typeof specified]);\n }\n const resolved = style as IntervalSeriesStyle;\n const radius = width(resolved.radius ?? 4, `${receiver} radius`);\n const halfCap = width(resolved.capSize ?? 8, `${receiver} capSize`) / 2;\n const strokeWidth = width(resolved.strokeWidth ?? 1.5, receiver);\n const lineInteractionWidth = width(\n resolved.lineInteractionWidth ?? strokeWidth,\n receiver,\n );\n const alpha = opacity(resolved.opacity ?? 1, receiver);\n if (resolved.cursor !== undefined && typeof resolved.cursor !== \"string\")\n throw new TypeError(`${receiver}: cursor must be a string.`);\n const stroke = resolved.stroke ?? \"#087f8c\";\n const lineStyle = {\n stroke,\n strokeWidth,\n lineInteractionWidth,\n opacity: alpha,\n cursor: resolved.cursor,\n };\n const nodes: PibblNode[] = [];\n for (let i = 0; i < data.length; i++) {\n const datum = data[i];\n const coordinates = withHooksForbidden(\n `${receiver}: accessors cannot call hooks.`,\n () => {\n if (defined && !defined(datum, i, data)) return undefined;\n return {\n category: category(datum, i, data),\n estimate: estimate(datum, i, data),\n lower: lower(datum, i, data),\n upper: upper(datum, i, data),\n };\n },\n );\n if (\n !coordinates ||\n coordinates.category == null ||\n !finiteCoordinate(coordinates.estimate) ||\n !finiteCoordinate(coordinates.lower) ||\n !finiteCoordinate(coordinates.upper)\n )\n continue;\n const start = categories.map(coordinates.category);\n if (start === undefined) continue;\n if (coordinates.lower > coordinates.upper)\n throw new RangeError(\n `${receiver}: lower must not exceed upper (row ${i}).`,\n );\n const center =\n start + (categories.type === \"band\" ? categories.bandwidth / 2 : 0);\n const lo = values.map(coordinates.lower),\n hi = values.map(coordinates.upper),\n point = values.map(coordinates.estimate);\n if (![center, lo, hi, point].every(Number.isFinite))\n throw new RangeError(\n `${receiver}: mapped coordinates must be finite (row ${i}).`,\n );\n const position = (value: number, offset = 0): [number, number] =>\n horizontal ? [value, center + offset] : [center + offset, value];\n nodes.push(\n <Group key={i}>\n <Line\n pointerEvents={pointerEvents}\n style={{ ...lineStyle, coords: [position(lo), position(hi)] }}\n />\n {halfCap > 0 && (\n <>\n <Line\n pointerEvents={pointerEvents}\n style={{\n ...lineStyle,\n coords: [position(lo, -halfCap), position(lo, halfCap)],\n }}\n />\n <Line\n pointerEvents={pointerEvents}\n style={{\n ...lineStyle,\n coords: [position(hi, -halfCap), position(hi, halfCap)],\n }}\n />\n </>\n )}\n {radius > 0 && (\n <Circle\n pointerEvents={pointerEvents}\n style={{\n ...lineStyle,\n cx: horizontal ? point : center,\n cy: horizontal ? center : point,\n radius,\n fill: resolved.fill ?? \"#087f8c\",\n }}\n />\n )}\n </Group>,\n );\n }\n return <Group {...events}>{nodes}</Group>;\n}\n\n/**\n * Draw supplied numeric intervals horizontally with an estimate circle per category.\n * Missing/non-finite coordinates omit the entire row; reversed bounds reject it.\n * Mapping does not clamp or clip; compose a Clip when required. Marks use ordinary\n * Line/Circle targets, with series handlers receiving their bubbled events.\n *\n * @param props - Supplied data, categorical/numeric scale IDs, and shared style.\n * @returns Ordinary Pibbl content in source order, interval then circle for each row.\n * @see {@link HorizontalIntervalSeriesProps}\n */\nexport function HorizontalIntervalSeries<D>(\n props: HorizontalIntervalSeriesProps<D>,\n): PibblNode {\n return intervalSeries(props, true);\n}\n\n/**\n * Draw supplied numeric intervals vertically with an estimate circle per category.\n * Shares the missing-data, bounds, paint, targeting, and clipping contract of\n * HorizontalIntervalSeries; orientation is explicit in the operation name.\n *\n * @param props - Supplied data, categorical/numeric scale IDs, and shared style.\n * @returns Ordinary Pibbl content in source order, interval then circle for each row.\n * @see {@link VerticalIntervalSeriesProps}\n */\nexport function VerticalIntervalSeries<D>(\n props: VerticalIntervalSeriesProps<D>,\n): PibblNode {\n return intervalSeries(props, false);\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -8,4 +8,4 @@ import type { LineSeriesProps } from "./types.js";
|
|
|
8
8
|
*
|
|
9
9
|
* @see {@link LineSeriesProps}
|
|
10
10
|
*/
|
|
11
|
-
export declare function LineSeries<D>({ data: dataInput, x: xInput, y: yInput, xScale: xId, yScale: yId, defined, curve, style: styleInput, ...eventProps }: LineSeriesProps<D>): import("../../../jsx-runtime.js").JSX.Element;
|
|
11
|
+
export declare function LineSeries<D>({ data: dataInput, x: xInput, y: yInput, xScale: xId, yScale: yId, defined, inspection, curve, style: styleInput, ...eventProps }: LineSeriesProps<D>): import("../../../jsx-runtime.js").JSX.Element;
|