packages/core/src/features/viz/lib/chart-lines.tsx
This is the source snapshot used to build these API details. View this revision on GitHub.
1 import { Line, resolveSignalValue, type SignalValue } from "@pibbl/core";
2 import type { AxisProps, AxisStyle, BandCategory, ScaleId } from "./types.js";
3 import type { SignalStyle } from "@pibbl/core/internal";
4 import { lookupScale } from "./scale-context.js";
5 import { ticks, position } from "./scale-ticks.js";
6 import { width, opacity } from "./paint.js";
7 /** Shared geometry and paint for decorative chart lines; no layout is allocated. See {@link GridLines}. */
8 export interface ChartLineProps {
9 /** Ancestor scale providing the line's mapped coordinate. */
10 readonly scale: ScaleId;
11 /** Direction the painted line extends. */
12 readonly direction: "horizontal" | "vertical";
13 /** Explicit perpendicular pixel endpoints, in the caller's local coordinate space. */
14 readonly span: SignalValue<readonly [number, number]>;
15 /** Stroke defaults to #dce5e8, width to 1, opacity to 1. */
16 readonly style?: SignalValue<SignalStyle<Pick<AxisStyle, "stroke" | "strokeWidth" | "opacity">>>;
17 }
18 /** Grid positions use Axis tick rules, independent of Axis label visibility. See {@link GridLines}. */
19 export type GridLinesProps = ChartLineProps & (
20 {
21 /** Explicit domain ticks; same validation as Axis. */
22 readonly tickValues: AxisProps["tickValues"];
23 /** Mutually exclusive with explicit values. */
24 readonly tickCount?: never;
25 } |
26 {
27 /** Mutually exclusive with generated ticks. */
28 readonly tickValues?: never;
29 /** Requested tick count; defaults to five. */
30 readonly tickCount?: AxisProps["tickCount"];
31 }
32 );
33 /** A reference value must belong to the selected scale's domain. See {@link ReferenceLine}. */
34 export interface ReferenceLineProps extends ChartLineProps {
35 /** Numeric domain value or categorical identity; signals update the line. */
36 readonly value: SignalValue<BandCategory>;
37 }
38 function lines(props: ChartLineProps, selection: Pick<AxisProps, "tickCount" | "tickValues">) {
39 if (props.direction !== "horizontal" && props.direction !== "vertical") throw new TypeError("Chart line direction must be horizontal or vertical.");
40 const source = lookupScale(props.scale, "Chart line");
41 if (!source) throw new TypeError("Chart lines require a scale ID.");
42 const scale = source.get(), span = resolveSignalValue(props.span);
43 if (!Array.isArray(span) || span.length !== 2 || !span.every(v => typeof v === "number" && Number.isFinite(v))) throw new RangeError("Chart line span must have two finite pixel endpoints.");
44 const style = resolveSignalValue(props.style) ?? {};
45 const stroke = resolveSignalValue(style.stroke) ?? "#dce5e8";
46 const strokeWidth = width(resolveSignalValue(style.strokeWidth) ?? 1, "Chart line");
47 const alpha = opacity(resolveSignalValue(style.opacity) ?? 1, "Chart line");
48 return ticks(scale, selection).map((value, index) => {
49 const p = position(scale, value);
50 const coords: [number, number][] = props.direction === "horizontal" ? [[span[0], p], [span[1], p]] : [[p, span[0]], [p, span[1]]];
51 return <Line key={index} pointerEvents="none" style={{ coords, stroke, strokeWidth, opacity: alpha }} />;
52 });
53 }
54 /** Paint grid lines at scale ticks, without labels or allocation.
55 * @param props - Scale geometry and presentation. See {@link GridLinesProps}.
56 * @returns Decorative chart content in the caller's coordinate space.
57 */
58 export function GridLines(props: GridLinesProps) { return lines(props, props); }
59 /** Paint one decorative line at a domain value, without labels or allocation.
60 * @param props - Scale geometry and presentation. See {@link ReferenceLineProps}.
61 * @returns Decorative chart content in the caller's coordinate space.
62 */
63 export function ReferenceLine(props: ReferenceLineProps) { return lines(props, { tickValues: [resolveSignalValue(props.value)] }); }
64
Documentation version
Section titled “Documentation version”Documentation built with @pibbl/core 0.0.2, revision 2dccb19. ALPHA — NOT FOR PRODUCTION USE.