import { cn } from "@openstatus/ui/lib/utils"; import { type VariantProps, cva } from "class-variance-authority"; import type * as React from "react"; /* * Every part is positioned in CSS from `--max` (set once on `RangePlot`) and * its own `--value`, so rows on the same `max` share one axis without context. * Values past `max` clamp to the edge; flag them with `RangePlotOverflow`. */ const AT = "left-[calc(min(var(--value),var(--max))/var(--max)*100%)]"; function vars(values: Record) { return Object.fromEntries( Object.entries(values).map(([key, value]) => [`--${key}`, value]), ) as React.CSSProperties; } export function RangePlot({ max, className, style, ...props }: React.ComponentProps<"div"> & { max: number }) { return (
); } /** Vertical lines at 0, half and max; bleeds into the cell padding so stacked rows join. */ export function RangePlotGrid({ className, ...props }: React.ComponentProps<"div">) { return (
); } /** Axis labels for a header cell: 0, half and max with the unit. */ export function RangePlotAxis({ max, unit, className, ...props }: React.ComponentProps<"div"> & { max: number; unit?: string }) { return (
0 {max / 2} {max} {unit}
); } /** Vertical line at a value (e.g. a degraded threshold); bleeds into the cell padding like the grid so rows join. */ export function RangePlotThreshold({ value, className, style, ...props }: React.ComponentProps<"div"> & { value: number }) { return (
); } const rangeVariants = cva( "absolute top-1/2 right-[calc(100%_-_min(var(--to),var(--max))/var(--max)*100%)] left-[calc(min(var(--from),var(--max))/var(--max)*100%)] -translate-y-1/2", { variants: { variant: { whisker: "bg-muted-foreground/50 h-px", box: "border-muted-foreground/50 bg-muted h-2.5 rounded-xs border", }, }, defaultVariants: { variant: "whisker" }, }, ); export function RangePlotRange({ from, to, variant, className, style, ...props }: React.ComponentProps<"div"> & VariantProps & { from: number; to: number }) { return (
); } const markerVariants = cva( "bg-foreground absolute top-1/2 -translate-x-1/2 -translate-y-1/2 rounded-full", { variants: { variant: { dot: "bg-muted-foreground size-2", tick: "h-3 w-0.5", end: "bg-muted-foreground h-2 w-px", }, }, defaultVariants: { variant: "dot" }, }, ); export function RangePlotMarker({ value, variant, className, style, ...props }: React.ComponentProps<"div"> & VariantProps & { value: number }) { return (
); } /** Pinned to the right edge when a value runs past `max`. */ export function RangePlotOverflow({ className, ...props }: React.ComponentProps<"span">) { return ( ); } export function RangePlotEmpty({ className, ...props }: React.ComponentProps<"p">) { return (

); } export function RangePlotLegend({ className, ...props }: React.ComponentProps<"ul">) { return (

    ); } const swatchVariants = cva("bg-foreground shrink-0 rounded-full", { variants: { variant: { dot: "bg-muted-foreground size-2", tick: "h-3 w-0.5", end: "bg-muted-foreground h-2 w-px", box: "border-muted-foreground/50 bg-muted h-2.5 w-3 rounded-xs border", warning: "border-warning h-3 w-0 rounded-none border-l bg-transparent", }, }, defaultVariants: { variant: "dot" }, }); export function RangePlotLegendItem({ variant, className, children, ...props }: React.ComponentProps<"li"> & VariantProps) { return (
  • {children}
  • ); } /** px offsets inside the 26px icon: whisker ends, box edges and middle. */ const POSITIONS = { min: 2, start: 8, mid: 13, end: 18, max: 24 } as const; const positionDotVariants = cva( "absolute top-1/2 size-1.5 -translate-x-1/2 -translate-y-1/2 rounded-full", { variants: { variant: { default: "bg-foreground", warning: "bg-warning", }, }, defaultVariants: { variant: "default" }, }, ); /** A miniature of the plot (whisker + box) with one dot where a percentile sits. */ export function RangePlotPositionIcon({ at, variant, className, ...props }: React.ComponentProps<"span"> & VariantProps & { at: keyof typeof POSITIONS }) { return ( ); }