Skip to content

packages/core/src/features/viz/lib/chart-lines.tsx

Read as Markdown

This is the source snapshot used to build these API details. View this revision on GitHub.

Back to reference

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 built with @pibbl/core 0.0.2, revision 2dccb19. ALPHA — NOT FOR PRODUCTION USE.