{"version":3,"file":"Sparkline.cjs","names":[],"sources":["../../../src/components/Sparkline/Sparkline.tsx"],"sourcesContent":["/**\n * @tempest-limits props-count — an inline chart with no chart library: data plus its\n * scale (min, max), its box (width, height), its look (variant, color, showEnd) and\n * its accessibility (valueFormatter, label). The formatter and label matter because\n * a sparkline has no axes to read.\n */\nimport type { HTMLAttributes } from \"react\";\n\nimport { cn } from \"@/utils/cn\";\n\nimport { areaPath, barRects, describeSeries, linePath, sparkPoints } from \"./sparkline-geometry\";\nimport styles from \"./Sparkline.module.css\";\n\nexport type SparklineVariant = \"line\" | \"area\" | \"bar\";\n\nexport interface SparklineProps extends Omit<HTMLAttributes<HTMLSpanElement>, \"children\"> {\n    /** The series, in order. Non-finite entries are skipped. */\n    data: readonly number[];\n    /** Drawing width in px. Default `88`. */\n    width?: number;\n    /** Drawing height in px. Default `24`. */\n    height?: number;\n    /** Which mark to draw. Default `\"line\"`. */\n    variant?: SparklineVariant;\n    /** Any CSS colour. Defaults to the first chart series token. */\n    color?: string;\n    /** Draw a dot on the last point. Default `true` for line and area. */\n    showEnd?: boolean;\n    /** Force the low end of the value axis — use it to compare several sparklines. */\n    min?: number;\n    /** Force the high end. */\n    max?: number;\n    /** Render a value; used in the accessible description. */\n    valueFormatter?: (value: number) => string;\n    /**\n     * Accessible name. Defaults to a sentence describing the series.\n     *\n     * Pass one when the surrounding text already says what is plotted — the default\n     * still appends the shape, so a caller never ends up with an unlabelled image.\n     */\n    label?: string;\n}\n\n/**\n * A tiny inline chart: shape only, no axes, no legend.\n *\n * Sized to sit in a table cell or beside a number, which is why it is plain SVG on\n * the root entry rather than a recharts wrapper — a sparkline in a data table should\n * not oblige an app to install a charting library.\n *\n * It carries `role=\"img\"` and a spoken description of the series (direction, ends,\n * extremes). Without that it is an unlabelled image: a sparkline has no axis or\n * legend to fall back on, so a screen reader would reach it and read nothing. Pair it\n * with the number it annotates — the shape is context, never the only way to read the\n * value.\n *\n * @example\n * <Sparkline data={last30Days} />\n * <Sparkline data={revenue} variant=\"area\" width={120} height={32} />\n *\n * // Same axis across a column, so the rows are comparable\n * <Sparkline data={row.series} min={0} max={columnMax} />\n */\nexport function Sparkline({\n    data,\n    width = 88,\n    height = 24,\n    variant = \"line\",\n    color = \"var(--tempest-chart-1)\",\n    showEnd,\n    min,\n    max,\n    valueFormatter,\n    label,\n    className,\n    ...rest\n}: SparklineProps) {\n    const points = sparkPoints({ values: data, width, height, min, max });\n    const description = label ?? describeSeries(data, valueFormatter);\n    const withEnd = showEnd ?? variant !== \"bar\";\n    const last = points[points.length - 1];\n\n    /*\n     * Bars grow from the bottom of the box; line and area close against it. Both use\n     * the same edge so a sparkline swapped between variants keeps its footprint.\n     */\n    const baselineY = height - 2;\n\n    return (\n        <span className={cn(styles.wrapper, className)} {...rest}>\n            <svg\n                className={styles.svg}\n                width={width}\n                height={height}\n                viewBox={`0 0 ${width} ${height}`}\n                role=\"img\"\n                aria-label={description}\n            >\n                {points.length > 0 && variant === \"area\" && (\n                    <path d={areaPath(points, baselineY)} fill={color} className={styles.area} />\n                )}\n\n                {points.length > 0 && variant !== \"bar\" && (\n                    <path\n                        d={linePath(points)}\n                        fill=\"none\"\n                        stroke={color}\n                        strokeWidth={2}\n                        strokeLinecap=\"round\"\n                        strokeLinejoin=\"round\"\n                    />\n                )}\n\n                {variant === \"bar\" &&\n                    barRects(points, { width, baselineY }).map((rect) => (\n                        <rect\n                            key={rect.point.index}\n                            x={rect.x}\n                            y={rect.y}\n                            width={rect.width}\n                            height={rect.height}\n                            rx={1}\n                            fill={color}\n                        />\n                    ))}\n\n                {withEnd && last && (\n                    /*\n                     * The ring is drawn in the surface colour rather than as a stroke on\n                     * the dot: it keeps the marker legible where it sits on top of the\n                     * line without adding ink that is not data.\n                     */\n                    <circle\n                        cx={last.x}\n                        cy={last.y}\n                        r={3}\n                        fill={color}\n                        stroke=\"var(--tempest-bg)\"\n                        strokeWidth={2}\n                    />\n                )}\n            </svg>\n        </span>\n    );\n}\n"],"mappings":"mJA+DA,SAAgB,EAAU,CACtB,OACA,QAAQ,GACR,SAAS,GACT,UAAU,OACV,QAAQ,yBACR,UACA,MACA,MACA,iBACA,QACA,YACA,GAAG,GACY,CACf,IAAM,EAAS,EAAA,YAAY,CAAE,OAAQ,EAAM,QAAO,SAAQ,MAAK,KAAI,CAAC,EAC9D,EAAc,GAAS,EAAA,eAAe,EAAM,CAAc,EAC1D,EAAU,GAAW,IAAY,MACjC,EAAO,EAAO,EAAO,OAAS,GAM9B,EAAY,EAAS,EAE3B,OACI,EAAA,EAAA,IAAA,CAAC,OAAD,CAAM,UAAW,EAAA,GAAG,EAAA,QAAO,QAAS,CAAS,EAAG,GAAI,EAChD,UAAA,EAAA,EAAA,KAAA,CAAC,MAAD,CACI,UAAW,EAAA,QAAO,IACX,QACC,SACR,QAAS,OAAO,EAAM,GAAG,IACzB,KAAK,MACL,aAAY,EANhB,SAAA,CAQK,EAAO,OAAS,GAAK,IAAY,SAC9B,EAAA,EAAA,IAAA,CAAC,OAAD,CAAM,EAAG,EAAA,SAAS,EAAQ,CAAS,EAAG,KAAM,EAAO,UAAW,EAAA,QAAO,IAAO,CAAA,EAG/E,EAAO,OAAS,GAAK,IAAY,QAC9B,EAAA,EAAA,IAAA,CAAC,OAAD,CACI,EAAG,EAAA,SAAS,CAAM,EAClB,KAAK,OACL,OAAQ,EACR,YAAa,EACb,cAAc,QACd,eAAe,OAClB,CAAA,EAGJ,IAAY,OACT,EAAA,SAAS,EAAQ,CAAE,QAAO,WAAU,CAAC,CAAC,CAAC,IAAK,IACxC,EAAA,EAAA,IAAA,CAAC,OAAD,CAEI,EAAG,EAAK,EACR,EAAG,EAAK,EACR,MAAO,EAAK,MACZ,OAAQ,EAAK,OACb,GAAI,EACJ,KAAM,CACT,EAPQ,EAAK,MAAM,KAOnB,CACJ,EAEJ,GAAW,IAMR,EAAA,EAAA,IAAA,CAAC,SAAD,CACI,GAAI,EAAK,EACT,GAAI,EAAK,EACT,EAAG,EACH,KAAM,EACN,OAAO,oBACP,YAAa,CAChB,CAAA,CAEJ,GACH,CAAA,CAEd"}