@epilot/spark-ui 0.11.0 → 0.12.0

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.
Files changed (162) hide show
  1. package/dist/components/attachment.d.cts +1 -1
  2. package/dist/components/attachment.d.ts +1 -1
  3. package/dist/components/avatar.d.cts +1 -1
  4. package/dist/components/avatar.d.ts +1 -1
  5. package/dist/components/badge.d.cts +1 -1
  6. package/dist/components/badge.d.ts +1 -1
  7. package/dist/components/bar-chart.cjs +2 -1
  8. package/dist/components/bar-chart.cjs.map +1 -1
  9. package/dist/components/bar-chart.js +2 -1
  10. package/dist/components/bar-chart.js.map +1 -1
  11. package/dist/components/box.cjs +3 -2
  12. package/dist/components/box.cjs.map +1 -1
  13. package/dist/components/box.d.cts +8 -1
  14. package/dist/components/box.d.ts +8 -1
  15. package/dist/components/box.js +3 -2
  16. package/dist/components/box.js.map +1 -1
  17. package/dist/components/bubble.d.cts +1 -1
  18. package/dist/components/bubble.d.ts +1 -1
  19. package/dist/components/button-group.d.cts +1 -1
  20. package/dist/components/button-group.d.ts +1 -1
  21. package/dist/components/button.d.cts +3 -3
  22. package/dist/components/button.d.ts +3 -3
  23. package/dist/components/calendar.cjs +2 -2
  24. package/dist/components/calendar.cjs.map +1 -1
  25. package/dist/components/calendar.js +2 -2
  26. package/dist/components/calendar.js.map +1 -1
  27. package/dist/components/callout.cjs +1 -1
  28. package/dist/components/callout.cjs.map +1 -1
  29. package/dist/components/callout.d.cts +3 -3
  30. package/dist/components/callout.d.ts +3 -3
  31. package/dist/components/callout.js +1 -1
  32. package/dist/components/callout.js.map +1 -1
  33. package/dist/components/card.cjs +3 -2
  34. package/dist/components/card.cjs.map +1 -1
  35. package/dist/components/card.d.cts +7 -1
  36. package/dist/components/card.d.ts +7 -1
  37. package/dist/components/card.js +3 -2
  38. package/dist/components/card.js.map +1 -1
  39. package/dist/components/checkbox.d.cts +1 -1
  40. package/dist/components/checkbox.d.ts +1 -1
  41. package/dist/components/field.d.cts +1 -1
  42. package/dist/components/field.d.ts +1 -1
  43. package/dist/components/icon.cjs +1 -1
  44. package/dist/components/icon.cjs.map +1 -1
  45. package/dist/components/icon.js +1 -1
  46. package/dist/components/icon.js.map +1 -1
  47. package/dist/components/info-block.d.cts +1 -1
  48. package/dist/components/info-block.d.ts +1 -1
  49. package/dist/components/input-group.cjs +1 -1
  50. package/dist/components/input-group.cjs.map +1 -1
  51. package/dist/components/input-group.js +1 -1
  52. package/dist/components/input-group.js.map +1 -1
  53. package/dist/components/input.d.cts +1 -1
  54. package/dist/components/input.d.ts +1 -1
  55. package/dist/components/layout.cjs +6 -2
  56. package/dist/components/layout.cjs.map +1 -1
  57. package/dist/components/layout.d.cts +9 -2
  58. package/dist/components/layout.d.ts +8 -2
  59. package/dist/components/layout.js +6 -2
  60. package/dist/components/layout.js.map +1 -1
  61. package/dist/components/list.cjs +46 -14
  62. package/dist/components/list.cjs.map +1 -1
  63. package/dist/components/list.d.cts +27 -3
  64. package/dist/components/list.d.ts +27 -3
  65. package/dist/components/list.js +46 -14
  66. package/dist/components/list.js.map +1 -1
  67. package/dist/components/page-header.d.cts +1 -1
  68. package/dist/components/page-header.d.ts +1 -1
  69. package/dist/components/pill.cjs +19 -12
  70. package/dist/components/pill.cjs.map +1 -1
  71. package/dist/components/pill.d.cts +1 -1
  72. package/dist/components/pill.d.ts +1 -1
  73. package/dist/components/pill.js +19 -12
  74. package/dist/components/pill.js.map +1 -1
  75. package/dist/components/popover.cjs +16 -13
  76. package/dist/components/popover.cjs.map +1 -1
  77. package/dist/components/popover.d.cts +2 -1
  78. package/dist/components/popover.d.ts +2 -1
  79. package/dist/components/popover.js +16 -13
  80. package/dist/components/popover.js.map +1 -1
  81. package/dist/components/progress.cjs +1 -1
  82. package/dist/components/progress.cjs.map +1 -1
  83. package/dist/components/progress.js +1 -1
  84. package/dist/components/progress.js.map +1 -1
  85. package/dist/components/radio-card-group.cjs +6 -2
  86. package/dist/components/radio-card-group.cjs.map +1 -1
  87. package/dist/components/radio-card-group.d.cts +2 -0
  88. package/dist/components/radio-card-group.d.ts +2 -0
  89. package/dist/components/radio-card-group.js +6 -2
  90. package/dist/components/radio-card-group.js.map +1 -1
  91. package/dist/components/radio.cjs +6 -2
  92. package/dist/components/radio.cjs.map +1 -1
  93. package/dist/components/radio.d.cts +7 -3
  94. package/dist/components/radio.d.ts +7 -3
  95. package/dist/components/radio.js +6 -2
  96. package/dist/components/radio.js.map +1 -1
  97. package/dist/components/schedule-list.cjs +10 -7
  98. package/dist/components/schedule-list.cjs.map +1 -1
  99. package/dist/components/schedule-list.js +10 -7
  100. package/dist/components/schedule-list.js.map +1 -1
  101. package/dist/components/segmented-control.d.cts +1 -1
  102. package/dist/components/segmented-control.d.ts +1 -1
  103. package/dist/components/select.cjs +21 -18
  104. package/dist/components/select.cjs.map +1 -1
  105. package/dist/components/select.d.cts +3 -2
  106. package/dist/components/select.d.ts +3 -2
  107. package/dist/components/select.js +21 -18
  108. package/dist/components/select.js.map +1 -1
  109. package/dist/components/switch.d.cts +1 -1
  110. package/dist/components/switch.d.ts +1 -1
  111. package/dist/components/tabs.cjs +4 -3
  112. package/dist/components/tabs.cjs.map +1 -1
  113. package/dist/components/tabs.d.cts +9 -0
  114. package/dist/components/tabs.d.ts +9 -0
  115. package/dist/components/tabs.js +4 -3
  116. package/dist/components/tabs.js.map +1 -1
  117. package/dist/components/textarea.d.cts +1 -1
  118. package/dist/components/textarea.d.ts +1 -1
  119. package/dist/components/theme.cjs +18 -6
  120. package/dist/components/theme.cjs.map +1 -1
  121. package/dist/components/theme.d.cts +16 -2
  122. package/dist/components/theme.d.ts +16 -2
  123. package/dist/components/theme.js +19 -7
  124. package/dist/components/theme.js.map +1 -1
  125. package/dist/{generate-radix-colors-Bw-RYaV4.d.ts → generate-radix-colors-BY4Wjsm7.d.cts} +4 -2
  126. package/dist/{generate-radix-colors-Bw-RYaV4.d.cts → generate-radix-colors-BY4Wjsm7.d.ts} +4 -2
  127. package/dist/icons/material-symbol.cjs +1 -1
  128. package/dist/icons/material-symbol.cjs.map +1 -1
  129. package/dist/icons/material-symbol.js +1 -1
  130. package/dist/icons/material-symbol.js.map +1 -1
  131. package/dist/lib/accent-theme.cjs +367 -16
  132. package/dist/lib/accent-theme.cjs.map +1 -1
  133. package/dist/lib/accent-theme.d.cts +75 -6
  134. package/dist/lib/accent-theme.d.ts +75 -6
  135. package/dist/lib/accent-theme.js +365 -18
  136. package/dist/lib/accent-theme.js.map +1 -1
  137. package/dist/lib/container-chrome.cjs +9 -7
  138. package/dist/lib/container-chrome.cjs.map +1 -1
  139. package/dist/lib/container-chrome.d.cts +4 -3
  140. package/dist/lib/container-chrome.d.ts +4 -3
  141. package/dist/lib/container-chrome.js +9 -8
  142. package/dist/lib/container-chrome.js.map +1 -1
  143. package/dist/lib/generate-radix-colors.cjs +7 -0
  144. package/dist/lib/generate-radix-colors.cjs.map +1 -1
  145. package/dist/lib/generate-radix-colors.d.cts +2 -2
  146. package/dist/lib/generate-radix-colors.d.ts +2 -2
  147. package/dist/lib/generate-radix-colors.js +6 -1
  148. package/dist/lib/generate-radix-colors.js.map +1 -1
  149. package/dist/lib/input-box-variants.d.cts +1 -1
  150. package/dist/lib/input-box-variants.d.ts +1 -1
  151. package/dist/lib/theme-types.cjs +19 -0
  152. package/dist/lib/theme-types.cjs.map +1 -0
  153. package/dist/lib/theme-types.d.cts +2 -2
  154. package/dist/lib/theme-types.d.ts +2 -2
  155. package/dist/lib/theme-types.js +17 -1
  156. package/dist/lib/theme-types.js.map +1 -0
  157. package/dist/styles/material-symbol.css +3 -0
  158. package/dist/styles/spark-default.css +148 -0
  159. package/dist/styles/utilities.css +9 -8
  160. package/dist/{theme-types-1yB0d8mp.d.ts → theme-types-Bn5E15-P.d.cts} +12 -3
  161. package/dist/{theme-types-1yB0d8mp.d.cts → theme-types-Bn5E15-P.d.ts} +12 -3
  162. package/package.json +113 -55
@@ -7,7 +7,7 @@ import { useRender } from "@base-ui/react/use-render";
7
7
 
8
8
  //#region src/components/attachment.d.ts
9
9
  declare const attachmentVariants: (props?: ({
10
- size?: "sm" | "default" | "xs" | null | undefined;
10
+ size?: "default" | "sm" | "xs" | null | undefined;
11
11
  orientation?: "horizontal" | "vertical" | null | undefined;
12
12
  } & import("class-variance-authority/types").ClassProp) | undefined) => string;
13
13
  declare function Attachment({
@@ -7,7 +7,7 @@ import { useRender } from "@base-ui/react/use-render";
7
7
 
8
8
  //#region src/components/attachment.d.ts
9
9
  declare const attachmentVariants: (props?: ({
10
- size?: "sm" | "default" | "xs" | null | undefined;
10
+ size?: "default" | "sm" | "xs" | null | undefined;
11
11
  orientation?: "horizontal" | "vertical" | null | undefined;
12
12
  } & import("class-variance-authority/types").ClassProp) | undefined) => string;
13
13
  declare function Attachment({
@@ -1,6 +1,6 @@
1
1
  "use client";
2
2
 
3
- import { u as SparkStyle } from "../theme-types-1yB0d8mp.cjs";
3
+ import { f as SparkStyle } from "../theme-types-Bn5E15-P.cjs";
4
4
  import { SparkAccentColor } from "../lib/accent-colors.cjs";
5
5
  import * as React$1 from "react";
6
6
  import { Avatar as Avatar$1 } from "@base-ui/react/avatar";
@@ -1,6 +1,6 @@
1
1
  "use client";
2
2
 
3
- import { u as SparkStyle } from "../theme-types-1yB0d8mp.js";
3
+ import { f as SparkStyle } from "../theme-types-Bn5E15-P.js";
4
4
  import { SparkAccentColor } from "../lib/accent-colors.js";
5
5
  import * as React$1 from "react";
6
6
  import { Avatar as Avatar$1 } from "@base-ui/react/avatar";
@@ -1,6 +1,6 @@
1
1
  "use client";
2
2
 
3
- import { u as SparkStyle } from "../theme-types-1yB0d8mp.cjs";
3
+ import { f as SparkStyle } from "../theme-types-Bn5E15-P.cjs";
4
4
  import * as React$1 from "react";
5
5
 
6
6
  //#region src/components/badge.d.ts
@@ -1,6 +1,6 @@
1
1
  "use client";
2
2
 
3
- import { u as SparkStyle } from "../theme-types-1yB0d8mp.js";
3
+ import { f as SparkStyle } from "../theme-types-Bn5E15-P.js";
4
4
  import * as React$1 from "react";
5
5
 
6
6
  //#region src/components/badge.d.ts
@@ -21,6 +21,7 @@ const HOVER_FADE_MS = 200;
21
21
  const FOCUS_TRANSITION_MS = 180;
22
22
  const DEFAULT_HEIGHT = 220;
23
23
  const BAR_RADIUS = 2;
24
+ const NO_TICKS = [];
24
25
  function buildBarPath(x, y, width, height, radius, roundTop, roundBottom) {
25
26
  const r = Math.max(0, Math.min(radius, width / 2, height / 2));
26
27
  if (r === 0 || !roundTop && !roundBottom) return `M ${x} ${y} H ${x + width} V ${y + height} H ${x} Z`;
@@ -223,7 +224,7 @@ function BarChart({ data, series, lines, getCategory, categories, categoryTicks,
223
224
  ]);
224
225
  const rightAxisDomain = (0, react.useMemo)(() => (lines ?? []).filter((line) => line.domain !== void 0 && !hiddenSeries.has(line.key)), [lines, hiddenSeries])[0]?.domain;
225
226
  const rightAxisScale = (0, react.useMemo)(() => rightAxisDomain === void 0 ? null : require_utils_chart_scale.buildYAxisScale(rightAxisDomain[0], rightAxisDomain[1]), [rightAxisDomain]);
226
- const rightTicks = rightAxisScale?.ticks ?? [];
227
+ const rightTicks = rightAxisScale?.ticks ?? NO_TICKS;
227
228
  const rightGutter = (0, react.useMemo)(() => rightAxisScale === null ? 0 : yAxisRightWidth ?? require_utils_chart_scale.measureYAxisGutter(rightTicks, formatYTickRight, 0), [
228
229
  rightAxisScale,
229
230
  rightTicks,
@@ -1 +1 @@
1
- {"version":3,"file":"bar-chart.cjs","names":["localeNumberFormat","BarStack","useReducedMotion","formatYAxisTick","buildYAxisScale","measureYAxisGutter","useMeasuredSize","clampTooltipPosition","SectionTitle","SeriesLegend","ChartTooltipCard","Group"],"sources":["../../src/components/bar-chart.tsx"],"sourcesContent":["import { localPoint } from '@visx/event'\nimport { Group } from '@visx/group'\nimport { scaleBand, scaleLinear, scaleOrdinal } from '@visx/scale'\nimport { BarStack } from '@visx/shape'\nimport { useCallback, useEffect, useMemo, useRef, useState } from 'react'\nimport { useReducedMotion } from '../hooks/use-reduced-motion'\nimport {\n buildYAxisScale,\n formatYAxisTick,\n measureYAxisGutter,\n} from '../utils/chart-scale'\nimport { cn } from '../utils/cn'\nimport { localeNumberFormat } from '../utils/format'\nimport {\n ChartTooltipCard,\n type ChartTooltipRow,\n clampTooltipPosition,\n useMeasuredSize,\n} from './chart'\nimport { SeriesLegend } from './series-legend'\nimport { SectionTitle } from './typography'\n\nconst defaultTotalFormat = localeNumberFormat()\n\nexport type BarChartCategory = string | number\n\nexport interface BarChartSeries<TDatum> {\n key: string\n label: string\n color: string\n hoverFill?: string\n getValue: (datum: TDatum) => number\n}\n\nexport interface BarChartLineSeries<TDatum> {\n key: string\n label: string\n color: string\n /** `null` gaps break the line (e.g. hours without a reading). */\n getValue: (datum: TDatum) => number | null\n /** Own y-domain for this line (e.g. `[0, 100]` for a percentage). Defaults to the bar scale. */\n domain?: [number, number]\n /** Start hidden; the user can enable the line from the legend. */\n hiddenByDefault?: boolean\n /** Formats this line's value in the hover tooltip. Defaults to `formatValue`. */\n formatValue?: (value: number) => string\n strokeDasharray?: string\n}\n\nexport interface BarChartProps<TDatum> {\n data: TDatum[]\n series: BarChartSeries<TDatum>[]\n /** Line overlays drawn on top of the bars, toggleable from the legend. */\n lines?: BarChartLineSeries<TDatum>[]\n getCategory: (datum: TDatum) => BarChartCategory\n /** Full ordered set of categories on the x-axis. Defaults to `data.map(getCategory)`. */\n categories?: BarChartCategory[]\n /** Subset of categories that should render an x-axis label. Defaults to every category. */\n categoryTicks?: BarChartCategory[]\n formatCategory?: (category: BarChartCategory) => string\n /** Formats the hovered category in the tooltip header. Defaults to `formatCategory`. */\n formatTooltipCategory?: (category: BarChartCategory) => string\n highlightedCategory?: BarChartCategory\n showHighlightLine?: boolean\n /**\n * Horizontal reference line drawn across the plot at a given y-value.\n * Useful for thresholds (e.g. price ceiling).\n */\n referenceLine?: { value: number; label?: string; color?: string }\n title?: string\n yAxisUnit?: string\n /** Overrides the y-axis tick formatter. Defaults to the shared compact formatter. */\n formatYTick?: (value: number) => string\n /** Fixes the y-axis gutter width (px). Defaults to auto-measuring the widest tick label. */\n yAxisWidth?: number\n yAxisRightUnit?: string\n /** Overrides the right y-axis tick formatter. Defaults to the shared compact formatter. */\n formatYTickRight?: (value: number) => string\n /** Fixes the right y-axis gutter width (px). Defaults to auto-measuring the widest tick label. */\n yAxisRightWidth?: number\n height?: number\n /**\n * Override how the total value (sum of focused or all categories) is\n * rendered. `animated` is false while a bar is focused (hover), so an\n * animated total can snap between hovered buckets instead of re-firing a\n * tween on every bar the pointer crosses.\n */\n renderTotal?: (value: number, animated: boolean) => React.ReactNode\n /** Format function used when `renderTotal` is not provided. */\n formatTotal?: (value: number) => string\n /** Formats per-series values in the hover tooltip. Defaults to `formatTotal`. */\n formatValue?: (value: number) => string\n className?: string\n}\n\ninterface StackDatum {\n __category: BarChartCategory\n __values: Record<string, number>\n}\n\ninterface BarStackLayerProps<TDatum> {\n stackData: StackDatum[]\n series: BarChartSeries<TDatum>[]\n seriesByKey: Map<string, BarChartSeries<TDatum>>\n xScale: ReturnType<typeof scaleBand<BarChartCategory>>\n yScale: ReturnType<typeof scaleLinear<number>>\n colorScale: ReturnType<typeof scaleOrdinal<string, string>>\n}\n\ninterface CategoryTicksProps {\n ticks: BarChartCategory[]\n xScale: ReturnType<typeof scaleBand<BarChartCategory>>\n height: number\n formatCategory: (category: BarChartCategory) => string\n}\n\nconst PADDING_TOP = 20\nconst PADDING_BOTTOM = 28\nconst HOVER_FADE_MS = 200\nconst FOCUS_TRANSITION_MS = 180\nconst DEFAULT_HEIGHT = 220\nconst BAR_RADIUS = 2\n\nfunction buildBarPath(\n x: number,\n y: number,\n width: number,\n height: number,\n radius: number,\n roundTop: boolean,\n roundBottom: boolean,\n) {\n const r = Math.max(0, Math.min(radius, width / 2, height / 2))\n\n if (r === 0 || (!roundTop && !roundBottom)) {\n return `M ${x} ${y} H ${x + width} V ${y + height} H ${x} Z`\n }\n\n const tl = roundTop ? r : 0\n const tr = roundTop ? r : 0\n const br = roundBottom ? r : 0\n const bl = roundBottom ? r : 0\n\n return [\n `M ${x + tl} ${y}`,\n `H ${x + width - tr}`,\n tr > 0\n ? `Q ${x + width} ${y} ${x + width} ${y + tr}`\n : `L ${x + width} ${y}`,\n `V ${y + height - br}`,\n br > 0\n ? `Q ${x + width} ${y + height} ${x + width - br} ${y + height}`\n : `L ${x + width} ${y + height}`,\n `H ${x + bl}`,\n bl > 0\n ? `Q ${x} ${y + height} ${x} ${y + height - bl}`\n : `L ${x} ${y + height}`,\n `V ${y + tl}`,\n tl > 0 ? `Q ${x} ${y} ${x + tl} ${y}` : `L ${x} ${y}`,\n 'Z',\n ].join(' ')\n}\n\nfunction BarStackLayer<TDatum>({\n stackData,\n series,\n seriesByKey,\n xScale,\n yScale,\n colorScale,\n}: BarStackLayerProps<TDatum>) {\n return (\n <BarStack<StackDatum, string>\n data={stackData}\n keys={series.map((entry) => entry.key)}\n x={(record) => record.__category}\n value={(record, key) => record.__values[key] ?? 0}\n xScale={xScale}\n yScale={yScale}\n color={colorScale}\n offset=\"diverging\"\n >\n {(barStacks) =>\n barStacks.map((barStack) =>\n barStack.bars.map((bar) => {\n const values = bar.bar.data.__values\n const segmentValue = values[barStack.key] ?? 0\n\n if (segmentValue === 0) {\n return null\n }\n\n const seriesEntry = seriesByKey.get(barStack.key)\n const strokeColor = seriesEntry?.color ?? bar.color\n const fillColor = strokeColor\n\n // Positive segments stack up from the baseline, negatives down.\n // Round only the outermost corner of each side of the axis.\n const positiveKeys = series\n .map((entry) => entry.key)\n .filter((key) => (values[key] ?? 0) > 0)\n const negativeKeys = series\n .map((entry) => entry.key)\n .filter((key) => (values[key] ?? 0) < 0)\n const roundTop =\n segmentValue > 0 &&\n positiveKeys[positiveKeys.length - 1] === barStack.key\n const roundBottom =\n segmentValue > 0\n ? positiveKeys[0] === barStack.key\n : negativeKeys[negativeKeys.length - 1] === barStack.key\n\n // visx returns a signed height for below-baseline bars; normalize\n // to a top-left origin with a positive height for the path.\n const top = bar.height < 0 ? bar.y + bar.height : bar.y\n const barHeight = Math.abs(bar.height)\n\n return (\n <path\n key={`bar-${barStack.index}-${bar.index}`}\n d={buildBarPath(\n bar.x,\n top,\n bar.width,\n Math.max(0, barHeight),\n BAR_RADIUS,\n roundTop,\n roundBottom,\n )}\n fill={fillColor}\n stroke={strokeColor}\n strokeWidth={1}\n style={{ transition: 'fill 180ms ease' }}\n />\n )\n }),\n )\n }\n </BarStack>\n )\n}\n\ninterface FocusBorderProps<TDatum> {\n category: BarChartCategory\n visible: boolean\n stackData: StackDatum[]\n series: BarChartSeries<TDatum>[]\n xScale: ReturnType<typeof scaleBand<BarChartCategory>>\n yScale: ReturnType<typeof scaleLinear<number>>\n}\n\nfunction FocusBorder<TDatum>({\n category,\n visible,\n stackData,\n series,\n xScale,\n yScale,\n}: FocusBorderProps<TDatum>) {\n const reducedMotion = useReducedMotion()\n const x = xScale(category)\n const datum = stackData.find((entry) => entry.__category === category)\n\n if (x === undefined || !datum) {\n return null\n }\n\n const hasAnyValue = series.some(\n (entry) => (datum.__values[entry.key] ?? 0) !== 0,\n )\n\n if (!hasAnyValue) {\n return null\n }\n\n const topY = PADDING_TOP\n // Extend past the baseline to cover any below-axis (feed-in) segment.\n const negativeSum = series.reduce(\n (sum, entry) => sum + Math.min(0, datum.__values[entry.key] ?? 0),\n 0,\n )\n const bottomY = yScale(negativeSum)\n const borderPaddingX = 4\n const borderPaddingY = 3\n const borderXRaw = x - borderPaddingX\n const borderY = topY - borderPaddingY\n const borderWidthRaw = xScale.bandwidth() + borderPaddingX * 2\n const [rangeStart, rangeEnd] = xScale.range()\n const minX = Math.min(rangeStart, rangeEnd)\n const maxX = Math.max(rangeStart, rangeEnd)\n const borderX = Math.max(minX, borderXRaw)\n const borderRight = Math.min(maxX, borderXRaw + borderWidthRaw)\n const borderWidth = Math.max(0, borderRight - borderX)\n const borderHeight = Math.max(1, bottomY - topY + borderPaddingY * 2)\n\n if (borderWidth <= 0) {\n return null\n }\n\n return (\n <rect\n x={borderX}\n y={borderY}\n width={borderWidth}\n height={borderHeight}\n rx={6}\n fill=\"var(--spark-a2)\"\n stroke=\"var(--spark-a9)\"\n strokeWidth={2}\n pointerEvents=\"none\"\n style={{\n opacity: visible ? 1 : 0,\n transition: reducedMotion\n ? `opacity ${FOCUS_TRANSITION_MS}ms ease`\n : `x ${FOCUS_TRANSITION_MS}ms ease, y ${FOCUS_TRANSITION_MS}ms ease, width ${FOCUS_TRANSITION_MS}ms ease, height ${FOCUS_TRANSITION_MS}ms ease, opacity ${FOCUS_TRANSITION_MS}ms ease`,\n }}\n />\n )\n}\n\ninterface InteractionLayerProps {\n xDomain: BarChartCategory[]\n activeCategories: Set<BarChartCategory>\n xScale: ReturnType<typeof scaleBand<BarChartCategory>>\n height: number\n onHoverChange: (category: BarChartCategory | null) => void\n}\n\nfunction InteractionLayer({\n xDomain,\n activeCategories,\n xScale,\n height,\n onHoverChange,\n}: InteractionLayerProps) {\n const bandwidth = xScale.bandwidth()\n const [rangeStart, rangeEnd] = xScale.range()\n const minX = Math.min(rangeStart, rangeEnd)\n const maxX = Math.max(rangeStart, rangeEnd)\n\n // A single overlay that maps the pointer to the nearest category with data,\n // so there are no dead zones between/around bars to break the hover.\n const handleMove = (\n event: React.MouseEvent<SVGRectElement> | React.TouchEvent<SVGRectElement>,\n ) => {\n const point = localPoint(event)\n if (!point) return\n\n let nearest: BarChartCategory | null = null\n let best = Infinity\n for (const category of xDomain) {\n if (!activeCategories.has(category)) continue\n const x = xScale(category)\n if (x === undefined) continue\n const distance = Math.abs(x + bandwidth / 2 - point.x)\n if (distance < best) {\n best = distance\n nearest = category\n }\n }\n\n if (nearest !== null) onHoverChange(nearest)\n }\n\n return (\n <rect\n x={minX}\n y={PADDING_TOP}\n width={Math.max(0, maxX - minX)}\n height={height - PADDING_TOP - PADDING_BOTTOM}\n fill=\"transparent\"\n onMouseMove={handleMove}\n onMouseLeave={() => onHoverChange(null)}\n onTouchMove={handleMove}\n onTouchEnd={() => onHoverChange(null)}\n />\n )\n}\n\nfunction CategoryTicks({\n ticks,\n xScale,\n height,\n formatCategory,\n}: CategoryTicksProps) {\n return (\n <>\n {ticks.map((category) => {\n const x = xScale(category)\n\n if (x === undefined) {\n return null\n }\n\n return (\n <text\n key={`tick-${String(category)}`}\n x={x + xScale.bandwidth() / 2}\n y={height - PADDING_BOTTOM + 16}\n textAnchor=\"middle\"\n fill=\"var(--neutral-a11)\"\n fontSize={10}\n >\n {formatCategory(category)}\n </text>\n )\n })}\n </>\n )\n}\n\nfunction defaultFormatTotal(value: number) {\n return defaultTotalFormat.format(value)\n}\n\nexport function BarChart<TDatum>({\n data,\n series,\n lines,\n getCategory,\n categories,\n categoryTicks,\n formatCategory = (category) => String(category),\n formatTooltipCategory = formatCategory,\n highlightedCategory,\n showHighlightLine = false,\n referenceLine,\n title,\n yAxisUnit,\n formatYTick = formatYAxisTick,\n yAxisWidth,\n yAxisRightUnit,\n formatYTickRight = formatYAxisTick,\n yAxisRightWidth,\n height = DEFAULT_HEIGHT,\n renderTotal,\n formatTotal = defaultFormatTotal,\n formatValue,\n className,\n}: BarChartProps<TDatum>): React.ReactElement {\n const containerRef = useRef<HTMLDivElement>(null)\n const reducedMotion = useReducedMotion()\n const [width, setWidth] = useState(0)\n const [hoveredCategory, setHoveredCategory] =\n useState<BarChartCategory | null>(null)\n const [trailingHoverLabel, setTrailingHoverLabel] = useState<string | null>(\n null,\n )\n const [hiddenSeries, setHiddenSeries] = useState<ReadonlySet<string>>(\n () =>\n new Set(\n (lines ?? [])\n .filter((line) => line.hiddenByDefault)\n .map((line) => line.key),\n ),\n )\n\n const toggleSeries = useCallback((id: string) => {\n setHiddenSeries((prev) => {\n const next = new Set(prev)\n if (next.has(id)) {\n next.delete(id)\n } else {\n next.add(id)\n }\n return next\n })\n }, [])\n\n useEffect(() => {\n const element = containerRef.current\n\n if (!element) {\n return\n }\n\n const resizeObserver = new ResizeObserver((entries) => {\n const entry = entries[0]\n\n if (!entry) {\n return\n }\n\n setWidth(entry.contentRect.width)\n })\n\n resizeObserver.observe(element)\n\n return () => {\n resizeObserver.disconnect()\n }\n }, [])\n\n const seriesByKey = useMemo(() => {\n const map = new Map<string, BarChartSeries<TDatum>>()\n\n for (const entry of series) {\n map.set(entry.key, entry)\n }\n\n return map\n }, [series])\n\n const stackData = useMemo<StackDatum[]>(\n () =>\n data.map((datum) => {\n const values: Record<string, number> = {}\n\n for (const entry of series) {\n values[entry.key] = hiddenSeries.has(entry.key)\n ? 0\n : entry.getValue(datum)\n }\n\n return { __category: getCategory(datum), __values: values }\n }),\n [data, getCategory, series, hiddenSeries],\n )\n\n const yMax = useMemo(\n () =>\n Math.max(\n 1,\n referenceLine?.value ?? 0,\n ...stackData.map((record) =>\n series.reduce(\n (sum, entry) => sum + Math.max(0, record.__values[entry.key] ?? 0),\n 0,\n ),\n ),\n ),\n [referenceLine, series, stackData],\n )\n\n // Most negative stack sum across buckets (0 when nothing dips below the axis).\n const yMin = useMemo(\n () =>\n Math.min(\n 0,\n ...stackData.map((record) =>\n series.reduce(\n (sum, entry) => sum + Math.min(0, record.__values[entry.key] ?? 0),\n 0,\n ),\n ),\n ),\n [series, stackData],\n )\n\n const xDomain = useMemo(\n () => categories ?? stackData.map((record) => record.__category),\n [categories, stackData],\n )\n\n const yAxisScale = useMemo(() => buildYAxisScale(yMin, yMax), [yMin, yMax])\n const yTicks = yAxisScale.ticks\n const gutter = useMemo(\n () => yAxisWidth ?? measureYAxisGutter(yTicks, formatYTick),\n [yTicks, formatYTick, yAxisWidth],\n )\n\n const visibleDomainLines = useMemo(\n () =>\n (lines ?? []).filter(\n (line) => line.domain !== undefined && !hiddenSeries.has(line.key),\n ),\n [lines, hiddenSeries],\n )\n\n const rightAxisDomain = visibleDomainLines[0]?.domain\n const rightAxisScale = useMemo(\n () =>\n rightAxisDomain === undefined\n ? null\n : buildYAxisScale(rightAxisDomain[0], rightAxisDomain[1]),\n [rightAxisDomain],\n )\n const rightTicks = rightAxisScale?.ticks ?? []\n const rightGutter = useMemo(\n () =>\n rightAxisScale === null\n ? 0\n : (yAxisRightWidth ??\n measureYAxisGutter(rightTicks, formatYTickRight, 0)),\n [rightAxisScale, rightTicks, formatYTickRight, yAxisRightWidth],\n )\n const plotRight = Math.max(gutter, width - rightGutter)\n\n const xScale = useMemo(\n () =>\n scaleBand<BarChartCategory>({\n domain: xDomain,\n range: [gutter, plotRight],\n padding: 0.32,\n }),\n [xDomain, gutter, plotRight],\n )\n\n // Domain must be the tick scale's rounded bounds, not the raw data extent:\n // otherwise the outermost tick (e.g. -2 for a -1.5 kWh feed-in) maps below\n // the plot floor, onto the x-axis labels and off the bottom of the svg.\n const yScale = useMemo(\n () =>\n scaleLinear<number>({\n domain: [yAxisScale.min, yAxisScale.max],\n range: [height - PADDING_BOTTOM, PADDING_TOP],\n }),\n [height, yAxisScale],\n )\n\n const rightYScale = useMemo(\n () =>\n rightAxisDomain === undefined\n ? null\n : scaleLinear<number>({\n domain: rightAxisDomain,\n range: [height - PADDING_BOTTOM, PADDING_TOP],\n }),\n [height, rightAxisDomain],\n )\n\n const colorScale = useMemo(\n () =>\n scaleOrdinal<string, string>({\n domain: series.map((entry) => entry.key),\n range: series.map((entry) => entry.color),\n }),\n [series],\n )\n\n const linePaths = useMemo(() => {\n if (!lines || width === 0) {\n return []\n }\n\n return lines\n .filter((line) => !hiddenSeries.has(line.key))\n .map((line) => {\n const lineScale = line.domain\n ? scaleLinear<number>({\n domain: line.domain,\n range: [height - PADDING_BOTTOM, PADDING_TOP],\n })\n : yScale\n const segments: string[] = []\n let previous: { x: number; y: number } | null = null\n\n for (const datum of data) {\n const x = xScale(getCategory(datum))\n const value = line.getValue(datum)\n\n if (x === undefined || value === null || !Number.isFinite(value)) {\n previous = null\n continue\n }\n\n const point = {\n x: x + xScale.bandwidth() / 2,\n y: lineScale(value),\n }\n segments.push(\n previous === null\n ? `M ${point.x} ${point.y}`\n : `L ${point.x} ${point.y}`,\n )\n previous = point\n }\n\n return {\n key: line.key,\n d: segments.join(' '),\n color: line.color,\n strokeDasharray: line.strokeDasharray ?? '5 4',\n }\n })\n .filter((path) => path.d !== '')\n }, [lines, hiddenSeries, data, getCategory, xScale, yScale, height, width])\n\n const stackCategorySet = useMemo(\n () => new Set(stackData.map((record) => record.__category)),\n [stackData],\n )\n\n const lastFocusCategoryRef = useRef<BarChartCategory | null>(null)\n if (hoveredCategory !== null) {\n lastFocusCategoryRef.current = hoveredCategory\n }\n const focusCategory = lastFocusCategoryRef.current\n\n const focused = useMemo(\n () =>\n hoveredCategory === null\n ? null\n : (stackData.find((record) => record.__category === hoveredCategory) ??\n null),\n [hoveredCategory, stackData],\n )\n\n // Below-baseline segments (feed-in) are context, not part of the headline\n // sum, so the total counts only the positive stack (energy consumed).\n const totalValue = useMemo(() => {\n if (focused) {\n return series.reduce(\n (sum, entry) => sum + Math.max(0, focused.__values[entry.key] ?? 0),\n 0,\n )\n }\n\n return stackData.reduce(\n (sum, record) =>\n sum +\n series.reduce(\n (s, entry) => s + Math.max(0, record.__values[entry.key] ?? 0),\n 0,\n ),\n 0,\n )\n }, [focused, series, stackData])\n\n const hoverLabel = focused ? formatTooltipCategory(focused.__category) : null\n\n useEffect(() => {\n if (hoverLabel) {\n setTrailingHoverLabel(hoverLabel)\n return\n }\n\n const timeoutId = window.setTimeout(() => {\n setTrailingHoverLabel(null)\n }, HOVER_FADE_MS)\n\n return () => {\n window.clearTimeout(timeoutId)\n }\n }, [hoverLabel])\n\n const ticks = categoryTicks ?? xDomain\n const highlightX = useMemo(() => {\n if (!showHighlightLine || highlightedCategory === undefined) {\n return null\n }\n\n const x = xScale(highlightedCategory)\n\n if (x === undefined) {\n return null\n }\n\n return x + xScale.bandwidth() / 2\n }, [highlightedCategory, showHighlightLine, xScale])\n\n const focusedDatum = useMemo(\n () =>\n hoveredCategory === null\n ? null\n : (data.find((datum) => getCategory(datum) === hoveredCategory) ??\n null),\n [hoveredCategory, data, getCategory],\n )\n\n // The bars don't depend on hover state, so memoize the layer: hovering\n // across bars must not re-render (and re-stack) every bar path each move.\n const barStackLayer = useMemo(\n () => (\n <BarStackLayer\n stackData={stackData}\n series={series}\n seriesByKey={seriesByKey}\n xScale={xScale}\n yScale={yScale}\n colorScale={colorScale}\n />\n ),\n [stackData, series, seriesByKey, xScale, yScale, colorScale],\n )\n\n const fmtTooltipValue = formatValue ?? formatTotal\n const tooltipRows: ChartTooltipRow[] = focused\n ? [\n ...series\n .filter((entry) => (focused.__values[entry.key] ?? 0) !== 0)\n .map((entry) => ({\n key: entry.key,\n label: entry.label,\n color: entry.color,\n value: fmtTooltipValue(Math.abs(focused.__values[entry.key] ?? 0)),\n })),\n ...(lines ?? [])\n .filter((line) => !hiddenSeries.has(line.key))\n .flatMap((line) => {\n const value =\n focusedDatum === null ? null : line.getValue(focusedDatum)\n\n if (value === null || !Number.isFinite(value)) {\n return []\n }\n\n return [\n {\n key: line.key,\n label: line.label,\n color: line.color,\n value: (line.formatValue ?? fmtTooltipValue)(value),\n marker: 'dashed-line' as const,\n },\n ]\n }),\n ]\n : []\n const tooltipActive = tooltipRows.length > 0\n const anchorX =\n focusCategory !== null\n ? (xScale(focusCategory) ?? 0) + xScale.bandwidth() / 2\n : 0\n const anchorY = yScale(totalValue)\n const [tooltipRef, tooltipSize] = useMeasuredSize<HTMLDivElement>()\n const tooltipPos = clampTooltipPosition({\n anchorX,\n anchorY,\n width,\n height,\n tipWidth: tooltipSize.width,\n tipHeight: tooltipSize.height,\n })\n\n return (\n <div\n data-slot=\"bar-chart\"\n className={cn('flex w-full flex-col', className)}\n >\n <div className=\"flex items-baseline justify-between\">\n {title && <SectionTitle>{title}</SectionTitle>}\n <span className=\"tabular-nums\">\n {renderTotal ? (\n renderTotal(totalValue, focused === null)\n ) : (\n <span className=\"text-base font-bold text-gray tabular-nums\">\n {formatTotal(totalValue)}\n </span>\n )}\n </span>\n </div>\n\n <div className=\"flex min-h-5 items-baseline justify-between gap-4\">\n <SeriesLegend\n items={[\n ...series.map((entry) => ({\n id: entry.key,\n label: entry.label,\n color: entry.color,\n })),\n ...(lines ?? []).map((line) => ({\n id: line.key,\n label: line.label,\n color: line.color,\n marker: 'dashed-line' as const,\n })),\n ]}\n hiddenIds={hiddenSeries}\n onToggle={toggleSeries}\n className=\"gap-y-1\"\n />\n <span\n className={cn(\n 'text-xs text-gray-light transition-opacity duration-200',\n hoverLabel ? 'opacity-100' : 'opacity-0',\n )}\n >\n {trailingHoverLabel ?? ' '}\n </span>\n </div>\n\n <div\n ref={containerRef}\n className=\"relative mt-2 w-full\"\n style={{ height }}\n >\n <div\n ref={tooltipRef}\n className=\"pointer-events-none absolute z-10\"\n style={{\n left: tooltipPos.left,\n top: tooltipPos.top,\n opacity: tooltipActive ? 1 : 0,\n transition: reducedMotion\n ? 'opacity 140ms ease-out'\n : 'left 140ms ease-out, top 140ms ease-out, opacity 140ms ease-out',\n }}\n >\n {focusCategory !== null && (\n <ChartTooltipCard\n label={formatTooltipCategory(focusCategory)}\n rows={tooltipRows}\n />\n )}\n </div>\n {width > 0 && (\n <svg width={width} height={height}>\n <line\n x1={gutter}\n x2={gutter}\n y1={PADDING_TOP}\n y2={height - PADDING_BOTTOM}\n stroke=\"var(--neutral-a6)\"\n strokeWidth={1}\n />\n\n {yTicks.map((tick, index) => {\n const y = yScale(tick)\n const hideTickLabel =\n yAxisUnit !== undefined && index === yTicks.length - 1\n\n return (\n <g key={`y-tick-${tick}`}>\n {!hideTickLabel && (\n <line\n x1={gutter - 4}\n x2={gutter}\n y1={y}\n y2={y}\n stroke=\"var(--neutral-a8)\"\n strokeWidth={1}\n />\n )}\n {!hideTickLabel && (\n <text\n x={gutter - 7}\n y={y + 3}\n textAnchor=\"end\"\n fill=\"var(--neutral-a11)\"\n fontSize={10}\n >\n {formatYTick(tick)}\n </text>\n )}\n </g>\n )\n })}\n\n {yAxisUnit && (\n <text\n x={0}\n y={PADDING_TOP - 6}\n textAnchor=\"start\"\n fill=\"var(--neutral-a11)\"\n fontSize={10}\n fontWeight={600}\n >\n {yAxisUnit}\n </text>\n )}\n\n {highlightX !== null && (\n <line\n x1={highlightX}\n x2={highlightX}\n y1={PADDING_TOP}\n y2={height - PADDING_BOTTOM}\n stroke=\"var(--spark-a9)\"\n strokeWidth={1.5}\n strokeDasharray=\"5 4\"\n pointerEvents=\"none\"\n />\n )}\n\n <line\n x1={gutter}\n x2={plotRight}\n y1={yScale(0)}\n y2={yScale(0)}\n stroke=\"var(--neutral-a5)\"\n strokeWidth={1}\n />\n\n {rightYScale !== null && (\n <>\n <line\n x1={plotRight}\n x2={plotRight}\n y1={PADDING_TOP}\n y2={height - PADDING_BOTTOM}\n stroke=\"var(--neutral-a6)\"\n strokeWidth={1}\n />\n\n {rightTicks.map((tick, index) => {\n const y = rightYScale(tick)\n const hideTickLabel =\n yAxisRightUnit !== undefined &&\n index === rightTicks.length - 1\n\n return (\n <g key={`y-tick-right-${tick}`}>\n {!hideTickLabel && (\n <line\n x1={plotRight}\n x2={plotRight + 4}\n y1={y}\n y2={y}\n stroke=\"var(--neutral-a8)\"\n strokeWidth={1}\n />\n )}\n {!hideTickLabel && (\n <text\n x={plotRight + 7}\n y={y + 3}\n textAnchor=\"start\"\n fill=\"var(--neutral-a11)\"\n fontSize={10}\n >\n {formatYTickRight(tick)}\n </text>\n )}\n </g>\n )\n })}\n\n {yAxisRightUnit && (\n <text\n x={width}\n y={PADDING_TOP - 6}\n textAnchor=\"end\"\n fill=\"var(--neutral-a11)\"\n fontSize={10}\n fontWeight={600}\n >\n {yAxisRightUnit}\n </text>\n )}\n </>\n )}\n\n <Group>\n {focusCategory !== null && (\n <FocusBorder\n category={focusCategory}\n visible={hoveredCategory !== null}\n stackData={stackData}\n series={series}\n xScale={xScale}\n yScale={yScale}\n />\n )}\n {barStackLayer}\n\n {referenceLine && (\n <line\n x1={gutter}\n x2={width}\n y1={yScale(referenceLine.value)}\n y2={yScale(referenceLine.value)}\n stroke={referenceLine.color ?? 'var(--neutral-a11)'}\n strokeWidth={1.5}\n pointerEvents=\"none\"\n />\n )}\n\n {linePaths.map((path) => (\n <path\n key={`line-${path.key}`}\n d={path.d}\n fill=\"none\"\n stroke={path.color}\n strokeWidth={1.5}\n strokeDasharray={path.strokeDasharray}\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n pointerEvents=\"none\"\n />\n ))}\n </Group>\n\n <InteractionLayer\n xDomain={xDomain}\n activeCategories={stackCategorySet}\n xScale={xScale}\n height={height}\n onHoverChange={setHoveredCategory}\n />\n\n <CategoryTicks\n ticks={ticks}\n xScale={xScale}\n height={height}\n formatCategory={formatCategory}\n />\n </svg>\n )}\n </div>\n </div>\n )\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"bar-chart.cjs","names":["localeNumberFormat","BarStack","useReducedMotion","formatYAxisTick","buildYAxisScale","measureYAxisGutter","useMeasuredSize","clampTooltipPosition","SectionTitle","SeriesLegend","ChartTooltipCard","Group"],"sources":["../../src/components/bar-chart.tsx"],"sourcesContent":["import { localPoint } from '@visx/event'\nimport { Group } from '@visx/group'\nimport { scaleBand, scaleLinear, scaleOrdinal } from '@visx/scale'\nimport { BarStack } from '@visx/shape'\nimport { useCallback, useEffect, useMemo, useRef, useState } from 'react'\nimport { useReducedMotion } from '../hooks/use-reduced-motion'\nimport {\n buildYAxisScale,\n formatYAxisTick,\n measureYAxisGutter,\n} from '../utils/chart-scale'\nimport { cn } from '../utils/cn'\nimport { localeNumberFormat } from '../utils/format'\nimport {\n ChartTooltipCard,\n type ChartTooltipRow,\n clampTooltipPosition,\n useMeasuredSize,\n} from './chart'\nimport { SeriesLegend } from './series-legend'\nimport { SectionTitle } from './typography'\n\nconst defaultTotalFormat = localeNumberFormat()\n\nexport type BarChartCategory = string | number\n\nexport interface BarChartSeries<TDatum> {\n key: string\n label: string\n color: string\n hoverFill?: string\n getValue: (datum: TDatum) => number\n}\n\nexport interface BarChartLineSeries<TDatum> {\n key: string\n label: string\n color: string\n /** `null` gaps break the line (e.g. hours without a reading). */\n getValue: (datum: TDatum) => number | null\n /** Own y-domain for this line (e.g. `[0, 100]` for a percentage). Defaults to the bar scale. */\n domain?: [number, number]\n /** Start hidden; the user can enable the line from the legend. */\n hiddenByDefault?: boolean\n /** Formats this line's value in the hover tooltip. Defaults to `formatValue`. */\n formatValue?: (value: number) => string\n strokeDasharray?: string\n}\n\nexport interface BarChartProps<TDatum> {\n data: TDatum[]\n series: BarChartSeries<TDatum>[]\n /** Line overlays drawn on top of the bars, toggleable from the legend. */\n lines?: BarChartLineSeries<TDatum>[]\n getCategory: (datum: TDatum) => BarChartCategory\n /** Full ordered set of categories on the x-axis. Defaults to `data.map(getCategory)`. */\n categories?: BarChartCategory[]\n /** Subset of categories that should render an x-axis label. Defaults to every category. */\n categoryTicks?: BarChartCategory[]\n formatCategory?: (category: BarChartCategory) => string\n /** Formats the hovered category in the tooltip header. Defaults to `formatCategory`. */\n formatTooltipCategory?: (category: BarChartCategory) => string\n highlightedCategory?: BarChartCategory\n showHighlightLine?: boolean\n /**\n * Horizontal reference line drawn across the plot at a given y-value.\n * Useful for thresholds (e.g. price ceiling).\n */\n referenceLine?: { value: number; label?: string; color?: string }\n title?: string\n yAxisUnit?: string\n /** Overrides the y-axis tick formatter. Defaults to the shared compact formatter. */\n formatYTick?: (value: number) => string\n /** Fixes the y-axis gutter width (px). Defaults to auto-measuring the widest tick label. */\n yAxisWidth?: number\n yAxisRightUnit?: string\n /** Overrides the right y-axis tick formatter. Defaults to the shared compact formatter. */\n formatYTickRight?: (value: number) => string\n /** Fixes the right y-axis gutter width (px). Defaults to auto-measuring the widest tick label. */\n yAxisRightWidth?: number\n height?: number\n /**\n * Override how the total value (sum of focused or all categories) is\n * rendered. `animated` is false while a bar is focused (hover), so an\n * animated total can snap between hovered buckets instead of re-firing a\n * tween on every bar the pointer crosses.\n */\n renderTotal?: (value: number, animated: boolean) => React.ReactNode\n /** Format function used when `renderTotal` is not provided. */\n formatTotal?: (value: number) => string\n /** Formats per-series values in the hover tooltip. Defaults to `formatTotal`. */\n formatValue?: (value: number) => string\n className?: string\n}\n\ninterface StackDatum {\n __category: BarChartCategory\n __values: Record<string, number>\n}\n\ninterface BarStackLayerProps<TDatum> {\n stackData: StackDatum[]\n series: BarChartSeries<TDatum>[]\n seriesByKey: Map<string, BarChartSeries<TDatum>>\n xScale: ReturnType<typeof scaleBand<BarChartCategory>>\n yScale: ReturnType<typeof scaleLinear<number>>\n colorScale: ReturnType<typeof scaleOrdinal<string, string>>\n}\n\ninterface CategoryTicksProps {\n ticks: BarChartCategory[]\n xScale: ReturnType<typeof scaleBand<BarChartCategory>>\n height: number\n formatCategory: (category: BarChartCategory) => string\n}\n\nconst PADDING_TOP = 20\nconst PADDING_BOTTOM = 28\nconst HOVER_FADE_MS = 200\nconst FOCUS_TRANSITION_MS = 180\nconst DEFAULT_HEIGHT = 220\nconst BAR_RADIUS = 2\n// Shared so the no-right-axis case keeps a stable identity: a `?? []` literal is a new\n// array each render, which churns any dep array it lands in.\nconst NO_TICKS: number[] = []\n\nfunction buildBarPath(\n x: number,\n y: number,\n width: number,\n height: number,\n radius: number,\n roundTop: boolean,\n roundBottom: boolean,\n) {\n const r = Math.max(0, Math.min(radius, width / 2, height / 2))\n\n if (r === 0 || (!roundTop && !roundBottom)) {\n return `M ${x} ${y} H ${x + width} V ${y + height} H ${x} Z`\n }\n\n const tl = roundTop ? r : 0\n const tr = roundTop ? r : 0\n const br = roundBottom ? r : 0\n const bl = roundBottom ? r : 0\n\n return [\n `M ${x + tl} ${y}`,\n `H ${x + width - tr}`,\n tr > 0\n ? `Q ${x + width} ${y} ${x + width} ${y + tr}`\n : `L ${x + width} ${y}`,\n `V ${y + height - br}`,\n br > 0\n ? `Q ${x + width} ${y + height} ${x + width - br} ${y + height}`\n : `L ${x + width} ${y + height}`,\n `H ${x + bl}`,\n bl > 0\n ? `Q ${x} ${y + height} ${x} ${y + height - bl}`\n : `L ${x} ${y + height}`,\n `V ${y + tl}`,\n tl > 0 ? `Q ${x} ${y} ${x + tl} ${y}` : `L ${x} ${y}`,\n 'Z',\n ].join(' ')\n}\n\nfunction BarStackLayer<TDatum>({\n stackData,\n series,\n seriesByKey,\n xScale,\n yScale,\n colorScale,\n}: BarStackLayerProps<TDatum>) {\n return (\n <BarStack<StackDatum, string>\n data={stackData}\n keys={series.map((entry) => entry.key)}\n x={(record) => record.__category}\n value={(record, key) => record.__values[key] ?? 0}\n xScale={xScale}\n yScale={yScale}\n color={colorScale}\n offset=\"diverging\"\n >\n {(barStacks) =>\n barStacks.map((barStack) =>\n barStack.bars.map((bar) => {\n const values = bar.bar.data.__values\n const segmentValue = values[barStack.key] ?? 0\n\n if (segmentValue === 0) {\n return null\n }\n\n const seriesEntry = seriesByKey.get(barStack.key)\n const strokeColor = seriesEntry?.color ?? bar.color\n const fillColor = strokeColor\n\n // Positive segments stack up from the baseline, negatives down.\n // Round only the outermost corner of each side of the axis.\n const positiveKeys = series\n .map((entry) => entry.key)\n .filter((key) => (values[key] ?? 0) > 0)\n const negativeKeys = series\n .map((entry) => entry.key)\n .filter((key) => (values[key] ?? 0) < 0)\n const roundTop =\n segmentValue > 0 &&\n positiveKeys[positiveKeys.length - 1] === barStack.key\n const roundBottom =\n segmentValue > 0\n ? positiveKeys[0] === barStack.key\n : negativeKeys[negativeKeys.length - 1] === barStack.key\n\n // visx returns a signed height for below-baseline bars; normalize\n // to a top-left origin with a positive height for the path.\n const top = bar.height < 0 ? bar.y + bar.height : bar.y\n const barHeight = Math.abs(bar.height)\n\n return (\n <path\n key={`bar-${barStack.index}-${bar.index}`}\n d={buildBarPath(\n bar.x,\n top,\n bar.width,\n Math.max(0, barHeight),\n BAR_RADIUS,\n roundTop,\n roundBottom,\n )}\n fill={fillColor}\n stroke={strokeColor}\n strokeWidth={1}\n style={{ transition: 'fill 180ms ease' }}\n />\n )\n }),\n )\n }\n </BarStack>\n )\n}\n\ninterface FocusBorderProps<TDatum> {\n category: BarChartCategory\n visible: boolean\n stackData: StackDatum[]\n series: BarChartSeries<TDatum>[]\n xScale: ReturnType<typeof scaleBand<BarChartCategory>>\n yScale: ReturnType<typeof scaleLinear<number>>\n}\n\nfunction FocusBorder<TDatum>({\n category,\n visible,\n stackData,\n series,\n xScale,\n yScale,\n}: FocusBorderProps<TDatum>) {\n const reducedMotion = useReducedMotion()\n const x = xScale(category)\n const datum = stackData.find((entry) => entry.__category === category)\n\n if (x === undefined || !datum) {\n return null\n }\n\n const hasAnyValue = series.some(\n (entry) => (datum.__values[entry.key] ?? 0) !== 0,\n )\n\n if (!hasAnyValue) {\n return null\n }\n\n const topY = PADDING_TOP\n // Extend past the baseline to cover any below-axis (feed-in) segment.\n const negativeSum = series.reduce(\n (sum, entry) => sum + Math.min(0, datum.__values[entry.key] ?? 0),\n 0,\n )\n const bottomY = yScale(negativeSum)\n const borderPaddingX = 4\n const borderPaddingY = 3\n const borderXRaw = x - borderPaddingX\n const borderY = topY - borderPaddingY\n const borderWidthRaw = xScale.bandwidth() + borderPaddingX * 2\n const [rangeStart, rangeEnd] = xScale.range()\n const minX = Math.min(rangeStart, rangeEnd)\n const maxX = Math.max(rangeStart, rangeEnd)\n const borderX = Math.max(minX, borderXRaw)\n const borderRight = Math.min(maxX, borderXRaw + borderWidthRaw)\n const borderWidth = Math.max(0, borderRight - borderX)\n const borderHeight = Math.max(1, bottomY - topY + borderPaddingY * 2)\n\n if (borderWidth <= 0) {\n return null\n }\n\n return (\n <rect\n x={borderX}\n y={borderY}\n width={borderWidth}\n height={borderHeight}\n rx={6}\n fill=\"var(--spark-a2)\"\n stroke=\"var(--spark-a9)\"\n strokeWidth={2}\n pointerEvents=\"none\"\n style={{\n opacity: visible ? 1 : 0,\n transition: reducedMotion\n ? `opacity ${FOCUS_TRANSITION_MS}ms ease`\n : `x ${FOCUS_TRANSITION_MS}ms ease, y ${FOCUS_TRANSITION_MS}ms ease, width ${FOCUS_TRANSITION_MS}ms ease, height ${FOCUS_TRANSITION_MS}ms ease, opacity ${FOCUS_TRANSITION_MS}ms ease`,\n }}\n />\n )\n}\n\ninterface InteractionLayerProps {\n xDomain: BarChartCategory[]\n activeCategories: Set<BarChartCategory>\n xScale: ReturnType<typeof scaleBand<BarChartCategory>>\n height: number\n onHoverChange: (category: BarChartCategory | null) => void\n}\n\nfunction InteractionLayer({\n xDomain,\n activeCategories,\n xScale,\n height,\n onHoverChange,\n}: InteractionLayerProps) {\n const bandwidth = xScale.bandwidth()\n const [rangeStart, rangeEnd] = xScale.range()\n const minX = Math.min(rangeStart, rangeEnd)\n const maxX = Math.max(rangeStart, rangeEnd)\n\n // A single overlay that maps the pointer to the nearest category with data,\n // so there are no dead zones between/around bars to break the hover.\n const handleMove = (\n event: React.MouseEvent<SVGRectElement> | React.TouchEvent<SVGRectElement>,\n ) => {\n const point = localPoint(event)\n if (!point) return\n\n let nearest: BarChartCategory | null = null\n let best = Infinity\n for (const category of xDomain) {\n if (!activeCategories.has(category)) continue\n const x = xScale(category)\n if (x === undefined) continue\n const distance = Math.abs(x + bandwidth / 2 - point.x)\n if (distance < best) {\n best = distance\n nearest = category\n }\n }\n\n if (nearest !== null) onHoverChange(nearest)\n }\n\n return (\n <rect\n x={minX}\n y={PADDING_TOP}\n width={Math.max(0, maxX - minX)}\n height={height - PADDING_TOP - PADDING_BOTTOM}\n fill=\"transparent\"\n onMouseMove={handleMove}\n onMouseLeave={() => onHoverChange(null)}\n onTouchMove={handleMove}\n onTouchEnd={() => onHoverChange(null)}\n />\n )\n}\n\nfunction CategoryTicks({\n ticks,\n xScale,\n height,\n formatCategory,\n}: CategoryTicksProps) {\n return (\n <>\n {ticks.map((category) => {\n const x = xScale(category)\n\n if (x === undefined) {\n return null\n }\n\n return (\n <text\n key={`tick-${String(category)}`}\n x={x + xScale.bandwidth() / 2}\n y={height - PADDING_BOTTOM + 16}\n textAnchor=\"middle\"\n fill=\"var(--neutral-a11)\"\n fontSize={10}\n >\n {formatCategory(category)}\n </text>\n )\n })}\n </>\n )\n}\n\nfunction defaultFormatTotal(value: number) {\n return defaultTotalFormat.format(value)\n}\n\nexport function BarChart<TDatum>({\n data,\n series,\n lines,\n getCategory,\n categories,\n categoryTicks,\n formatCategory = (category) => String(category),\n formatTooltipCategory = formatCategory,\n highlightedCategory,\n showHighlightLine = false,\n referenceLine,\n title,\n yAxisUnit,\n formatYTick = formatYAxisTick,\n yAxisWidth,\n yAxisRightUnit,\n formatYTickRight = formatYAxisTick,\n yAxisRightWidth,\n height = DEFAULT_HEIGHT,\n renderTotal,\n formatTotal = defaultFormatTotal,\n formatValue,\n className,\n}: BarChartProps<TDatum>): React.ReactElement {\n const containerRef = useRef<HTMLDivElement>(null)\n const reducedMotion = useReducedMotion()\n const [width, setWidth] = useState(0)\n const [hoveredCategory, setHoveredCategory] =\n useState<BarChartCategory | null>(null)\n const [trailingHoverLabel, setTrailingHoverLabel] = useState<string | null>(\n null,\n )\n const [hiddenSeries, setHiddenSeries] = useState<ReadonlySet<string>>(\n () =>\n new Set(\n (lines ?? [])\n .filter((line) => line.hiddenByDefault)\n .map((line) => line.key),\n ),\n )\n\n const toggleSeries = useCallback((id: string) => {\n setHiddenSeries((prev) => {\n const next = new Set(prev)\n if (next.has(id)) {\n next.delete(id)\n } else {\n next.add(id)\n }\n return next\n })\n }, [])\n\n useEffect(() => {\n const element = containerRef.current\n\n if (!element) {\n return\n }\n\n const resizeObserver = new ResizeObserver((entries) => {\n const entry = entries[0]\n\n if (!entry) {\n return\n }\n\n setWidth(entry.contentRect.width)\n })\n\n resizeObserver.observe(element)\n\n return () => {\n resizeObserver.disconnect()\n }\n }, [])\n\n const seriesByKey = useMemo(() => {\n const map = new Map<string, BarChartSeries<TDatum>>()\n\n for (const entry of series) {\n map.set(entry.key, entry)\n }\n\n return map\n }, [series])\n\n const stackData = useMemo<StackDatum[]>(\n () =>\n data.map((datum) => {\n const values: Record<string, number> = {}\n\n for (const entry of series) {\n values[entry.key] = hiddenSeries.has(entry.key)\n ? 0\n : entry.getValue(datum)\n }\n\n return { __category: getCategory(datum), __values: values }\n }),\n [data, getCategory, series, hiddenSeries],\n )\n\n const yMax = useMemo(\n () =>\n Math.max(\n 1,\n referenceLine?.value ?? 0,\n ...stackData.map((record) =>\n series.reduce(\n (sum, entry) => sum + Math.max(0, record.__values[entry.key] ?? 0),\n 0,\n ),\n ),\n ),\n [referenceLine, series, stackData],\n )\n\n // Most negative stack sum across buckets (0 when nothing dips below the axis).\n const yMin = useMemo(\n () =>\n Math.min(\n 0,\n ...stackData.map((record) =>\n series.reduce(\n (sum, entry) => sum + Math.min(0, record.__values[entry.key] ?? 0),\n 0,\n ),\n ),\n ),\n [series, stackData],\n )\n\n const xDomain = useMemo(\n () => categories ?? stackData.map((record) => record.__category),\n [categories, stackData],\n )\n\n const yAxisScale = useMemo(() => buildYAxisScale(yMin, yMax), [yMin, yMax])\n const yTicks = yAxisScale.ticks\n const gutter = useMemo(\n () => yAxisWidth ?? measureYAxisGutter(yTicks, formatYTick),\n [yTicks, formatYTick, yAxisWidth],\n )\n\n const visibleDomainLines = useMemo(\n () =>\n (lines ?? []).filter(\n (line) => line.domain !== undefined && !hiddenSeries.has(line.key),\n ),\n [lines, hiddenSeries],\n )\n\n const rightAxisDomain = visibleDomainLines[0]?.domain\n const rightAxisScale = useMemo(\n () =>\n rightAxisDomain === undefined\n ? null\n : buildYAxisScale(rightAxisDomain[0], rightAxisDomain[1]),\n [rightAxisDomain],\n )\n const rightTicks = rightAxisScale?.ticks ?? NO_TICKS\n const rightGutter = useMemo(\n () =>\n rightAxisScale === null\n ? 0\n : (yAxisRightWidth ??\n measureYAxisGutter(rightTicks, formatYTickRight, 0)),\n [rightAxisScale, rightTicks, formatYTickRight, yAxisRightWidth],\n )\n const plotRight = Math.max(gutter, width - rightGutter)\n\n const xScale = useMemo(\n () =>\n scaleBand<BarChartCategory>({\n domain: xDomain,\n range: [gutter, plotRight],\n padding: 0.32,\n }),\n [xDomain, gutter, plotRight],\n )\n\n // Domain must be the tick scale's rounded bounds, not the raw data extent:\n // otherwise the outermost tick (e.g. -2 for a -1.5 kWh feed-in) maps below\n // the plot floor, onto the x-axis labels and off the bottom of the svg.\n const yScale = useMemo(\n () =>\n scaleLinear<number>({\n domain: [yAxisScale.min, yAxisScale.max],\n range: [height - PADDING_BOTTOM, PADDING_TOP],\n }),\n [height, yAxisScale],\n )\n\n const rightYScale = useMemo(\n () =>\n rightAxisDomain === undefined\n ? null\n : scaleLinear<number>({\n domain: rightAxisDomain,\n range: [height - PADDING_BOTTOM, PADDING_TOP],\n }),\n [height, rightAxisDomain],\n )\n\n const colorScale = useMemo(\n () =>\n scaleOrdinal<string, string>({\n domain: series.map((entry) => entry.key),\n range: series.map((entry) => entry.color),\n }),\n [series],\n )\n\n const linePaths = useMemo(() => {\n if (!lines || width === 0) {\n return []\n }\n\n return lines\n .filter((line) => !hiddenSeries.has(line.key))\n .map((line) => {\n const lineScale = line.domain\n ? scaleLinear<number>({\n domain: line.domain,\n range: [height - PADDING_BOTTOM, PADDING_TOP],\n })\n : yScale\n const segments: string[] = []\n let previous: { x: number; y: number } | null = null\n\n for (const datum of data) {\n const x = xScale(getCategory(datum))\n const value = line.getValue(datum)\n\n if (x === undefined || value === null || !Number.isFinite(value)) {\n previous = null\n continue\n }\n\n const point = {\n x: x + xScale.bandwidth() / 2,\n y: lineScale(value),\n }\n segments.push(\n previous === null\n ? `M ${point.x} ${point.y}`\n : `L ${point.x} ${point.y}`,\n )\n previous = point\n }\n\n return {\n key: line.key,\n d: segments.join(' '),\n color: line.color,\n strokeDasharray: line.strokeDasharray ?? '5 4',\n }\n })\n .filter((path) => path.d !== '')\n }, [lines, hiddenSeries, data, getCategory, xScale, yScale, height, width])\n\n const stackCategorySet = useMemo(\n () => new Set(stackData.map((record) => record.__category)),\n [stackData],\n )\n\n const lastFocusCategoryRef = useRef<BarChartCategory | null>(null)\n if (hoveredCategory !== null) {\n lastFocusCategoryRef.current = hoveredCategory\n }\n const focusCategory = lastFocusCategoryRef.current\n\n const focused = useMemo(\n () =>\n hoveredCategory === null\n ? null\n : (stackData.find((record) => record.__category === hoveredCategory) ??\n null),\n [hoveredCategory, stackData],\n )\n\n // Below-baseline segments (feed-in) are context, not part of the headline\n // sum, so the total counts only the positive stack (energy consumed).\n const totalValue = useMemo(() => {\n if (focused) {\n return series.reduce(\n (sum, entry) => sum + Math.max(0, focused.__values[entry.key] ?? 0),\n 0,\n )\n }\n\n return stackData.reduce(\n (sum, record) =>\n sum +\n series.reduce(\n (s, entry) => s + Math.max(0, record.__values[entry.key] ?? 0),\n 0,\n ),\n 0,\n )\n }, [focused, series, stackData])\n\n const hoverLabel = focused ? formatTooltipCategory(focused.__category) : null\n\n useEffect(() => {\n if (hoverLabel) {\n setTrailingHoverLabel(hoverLabel)\n return\n }\n\n const timeoutId = window.setTimeout(() => {\n setTrailingHoverLabel(null)\n }, HOVER_FADE_MS)\n\n return () => {\n window.clearTimeout(timeoutId)\n }\n }, [hoverLabel])\n\n const ticks = categoryTicks ?? xDomain\n const highlightX = useMemo(() => {\n if (!showHighlightLine || highlightedCategory === undefined) {\n return null\n }\n\n const x = xScale(highlightedCategory)\n\n if (x === undefined) {\n return null\n }\n\n return x + xScale.bandwidth() / 2\n }, [highlightedCategory, showHighlightLine, xScale])\n\n const focusedDatum = useMemo(\n () =>\n hoveredCategory === null\n ? null\n : (data.find((datum) => getCategory(datum) === hoveredCategory) ??\n null),\n [hoveredCategory, data, getCategory],\n )\n\n // The bars don't depend on hover state, so memoize the layer: hovering\n // across bars must not re-render (and re-stack) every bar path each move.\n const barStackLayer = useMemo(\n () => (\n <BarStackLayer\n stackData={stackData}\n series={series}\n seriesByKey={seriesByKey}\n xScale={xScale}\n yScale={yScale}\n colorScale={colorScale}\n />\n ),\n [stackData, series, seriesByKey, xScale, yScale, colorScale],\n )\n\n const fmtTooltipValue = formatValue ?? formatTotal\n const tooltipRows: ChartTooltipRow[] = focused\n ? [\n ...series\n .filter((entry) => (focused.__values[entry.key] ?? 0) !== 0)\n .map((entry) => ({\n key: entry.key,\n label: entry.label,\n color: entry.color,\n value: fmtTooltipValue(Math.abs(focused.__values[entry.key] ?? 0)),\n })),\n ...(lines ?? [])\n .filter((line) => !hiddenSeries.has(line.key))\n .flatMap((line) => {\n const value =\n focusedDatum === null ? null : line.getValue(focusedDatum)\n\n if (value === null || !Number.isFinite(value)) {\n return []\n }\n\n return [\n {\n key: line.key,\n label: line.label,\n color: line.color,\n value: (line.formatValue ?? fmtTooltipValue)(value),\n marker: 'dashed-line' as const,\n },\n ]\n }),\n ]\n : []\n const tooltipActive = tooltipRows.length > 0\n const anchorX =\n focusCategory !== null\n ? (xScale(focusCategory) ?? 0) + xScale.bandwidth() / 2\n : 0\n const anchorY = yScale(totalValue)\n const [tooltipRef, tooltipSize] = useMeasuredSize<HTMLDivElement>()\n const tooltipPos = clampTooltipPosition({\n anchorX,\n anchorY,\n width,\n height,\n tipWidth: tooltipSize.width,\n tipHeight: tooltipSize.height,\n })\n\n return (\n <div\n data-slot=\"bar-chart\"\n className={cn('flex w-full flex-col', className)}\n >\n <div className=\"flex items-baseline justify-between\">\n {title && <SectionTitle>{title}</SectionTitle>}\n <span className=\"tabular-nums\">\n {renderTotal ? (\n renderTotal(totalValue, focused === null)\n ) : (\n <span className=\"text-base font-bold text-gray tabular-nums\">\n {formatTotal(totalValue)}\n </span>\n )}\n </span>\n </div>\n\n <div className=\"flex min-h-5 items-baseline justify-between gap-4\">\n <SeriesLegend\n items={[\n ...series.map((entry) => ({\n id: entry.key,\n label: entry.label,\n color: entry.color,\n })),\n ...(lines ?? []).map((line) => ({\n id: line.key,\n label: line.label,\n color: line.color,\n marker: 'dashed-line' as const,\n })),\n ]}\n hiddenIds={hiddenSeries}\n onToggle={toggleSeries}\n className=\"gap-y-1\"\n />\n <span\n className={cn(\n 'text-xs text-gray-light transition-opacity duration-200',\n hoverLabel ? 'opacity-100' : 'opacity-0',\n )}\n >\n {trailingHoverLabel ?? ' '}\n </span>\n </div>\n\n <div\n ref={containerRef}\n className=\"relative mt-2 w-full\"\n style={{ height }}\n >\n <div\n ref={tooltipRef}\n className=\"pointer-events-none absolute z-10\"\n style={{\n left: tooltipPos.left,\n top: tooltipPos.top,\n opacity: tooltipActive ? 1 : 0,\n transition: reducedMotion\n ? 'opacity 140ms ease-out'\n : 'left 140ms ease-out, top 140ms ease-out, opacity 140ms ease-out',\n }}\n >\n {focusCategory !== null && (\n <ChartTooltipCard\n label={formatTooltipCategory(focusCategory)}\n rows={tooltipRows}\n />\n )}\n </div>\n {width > 0 && (\n <svg width={width} height={height}>\n <line\n x1={gutter}\n x2={gutter}\n y1={PADDING_TOP}\n y2={height - PADDING_BOTTOM}\n stroke=\"var(--neutral-a6)\"\n strokeWidth={1}\n />\n\n {yTicks.map((tick, index) => {\n const y = yScale(tick)\n const hideTickLabel =\n yAxisUnit !== undefined && index === yTicks.length - 1\n\n return (\n <g key={`y-tick-${tick}`}>\n {!hideTickLabel && (\n <line\n x1={gutter - 4}\n x2={gutter}\n y1={y}\n y2={y}\n stroke=\"var(--neutral-a8)\"\n strokeWidth={1}\n />\n )}\n {!hideTickLabel && (\n <text\n x={gutter - 7}\n y={y + 3}\n textAnchor=\"end\"\n fill=\"var(--neutral-a11)\"\n fontSize={10}\n >\n {formatYTick(tick)}\n </text>\n )}\n </g>\n )\n })}\n\n {yAxisUnit && (\n <text\n x={0}\n y={PADDING_TOP - 6}\n textAnchor=\"start\"\n fill=\"var(--neutral-a11)\"\n fontSize={10}\n fontWeight={600}\n >\n {yAxisUnit}\n </text>\n )}\n\n {highlightX !== null && (\n <line\n x1={highlightX}\n x2={highlightX}\n y1={PADDING_TOP}\n y2={height - PADDING_BOTTOM}\n stroke=\"var(--spark-a9)\"\n strokeWidth={1.5}\n strokeDasharray=\"5 4\"\n pointerEvents=\"none\"\n />\n )}\n\n <line\n x1={gutter}\n x2={plotRight}\n y1={yScale(0)}\n y2={yScale(0)}\n stroke=\"var(--neutral-a5)\"\n strokeWidth={1}\n />\n\n {rightYScale !== null && (\n <>\n <line\n x1={plotRight}\n x2={plotRight}\n y1={PADDING_TOP}\n y2={height - PADDING_BOTTOM}\n stroke=\"var(--neutral-a6)\"\n strokeWidth={1}\n />\n\n {rightTicks.map((tick, index) => {\n const y = rightYScale(tick)\n const hideTickLabel =\n yAxisRightUnit !== undefined &&\n index === rightTicks.length - 1\n\n return (\n <g key={`y-tick-right-${tick}`}>\n {!hideTickLabel && (\n <line\n x1={plotRight}\n x2={plotRight + 4}\n y1={y}\n y2={y}\n stroke=\"var(--neutral-a8)\"\n strokeWidth={1}\n />\n )}\n {!hideTickLabel && (\n <text\n x={plotRight + 7}\n y={y + 3}\n textAnchor=\"start\"\n fill=\"var(--neutral-a11)\"\n fontSize={10}\n >\n {formatYTickRight(tick)}\n </text>\n )}\n </g>\n )\n })}\n\n {yAxisRightUnit && (\n <text\n x={width}\n y={PADDING_TOP - 6}\n textAnchor=\"end\"\n fill=\"var(--neutral-a11)\"\n fontSize={10}\n fontWeight={600}\n >\n {yAxisRightUnit}\n </text>\n )}\n </>\n )}\n\n <Group>\n {focusCategory !== null && (\n <FocusBorder\n category={focusCategory}\n visible={hoveredCategory !== null}\n stackData={stackData}\n series={series}\n xScale={xScale}\n yScale={yScale}\n />\n )}\n {barStackLayer}\n\n {referenceLine && (\n <line\n x1={gutter}\n x2={width}\n y1={yScale(referenceLine.value)}\n y2={yScale(referenceLine.value)}\n stroke={referenceLine.color ?? 'var(--neutral-a11)'}\n strokeWidth={1.5}\n pointerEvents=\"none\"\n />\n )}\n\n {linePaths.map((path) => (\n <path\n key={`line-${path.key}`}\n d={path.d}\n fill=\"none\"\n stroke={path.color}\n strokeWidth={1.5}\n strokeDasharray={path.strokeDasharray}\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n pointerEvents=\"none\"\n />\n ))}\n </Group>\n\n <InteractionLayer\n xDomain={xDomain}\n activeCategories={stackCategorySet}\n xScale={xScale}\n height={height}\n onHoverChange={setHoveredCategory}\n />\n\n <CategoryTicks\n ticks={ticks}\n xScale={xScale}\n height={height}\n formatCategory={formatCategory}\n />\n </svg>\n )}\n </div>\n </div>\n )\n}\n"],"mappings":"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"}
@@ -20,6 +20,7 @@ const HOVER_FADE_MS = 200;
20
20
  const FOCUS_TRANSITION_MS = 180;
21
21
  const DEFAULT_HEIGHT = 220;
22
22
  const BAR_RADIUS = 2;
23
+ const NO_TICKS = [];
23
24
  function buildBarPath(x, y, width, height, radius, roundTop, roundBottom) {
24
25
  const r = Math.max(0, Math.min(radius, width / 2, height / 2));
25
26
  if (r === 0 || !roundTop && !roundBottom) return `M ${x} ${y} H ${x + width} V ${y + height} H ${x} Z`;
@@ -222,7 +223,7 @@ function BarChart({ data, series, lines, getCategory, categories, categoryTicks,
222
223
  ]);
223
224
  const rightAxisDomain = useMemo(() => (lines ?? []).filter((line) => line.domain !== void 0 && !hiddenSeries.has(line.key)), [lines, hiddenSeries])[0]?.domain;
224
225
  const rightAxisScale = useMemo(() => rightAxisDomain === void 0 ? null : buildYAxisScale(rightAxisDomain[0], rightAxisDomain[1]), [rightAxisDomain]);
225
- const rightTicks = rightAxisScale?.ticks ?? [];
226
+ const rightTicks = rightAxisScale?.ticks ?? NO_TICKS;
226
227
  const rightGutter = useMemo(() => rightAxisScale === null ? 0 : yAxisRightWidth ?? measureYAxisGutter(rightTicks, formatYTickRight, 0), [
227
228
  rightAxisScale,
228
229
  rightTicks,
@@ -1 +1 @@
1
- {"version":3,"file":"bar-chart.js","names":[],"sources":["../../src/components/bar-chart.tsx"],"sourcesContent":["import { localPoint } from '@visx/event'\nimport { Group } from '@visx/group'\nimport { scaleBand, scaleLinear, scaleOrdinal } from '@visx/scale'\nimport { BarStack } from '@visx/shape'\nimport { useCallback, useEffect, useMemo, useRef, useState } from 'react'\nimport { useReducedMotion } from '../hooks/use-reduced-motion'\nimport {\n buildYAxisScale,\n formatYAxisTick,\n measureYAxisGutter,\n} from '../utils/chart-scale'\nimport { cn } from '../utils/cn'\nimport { localeNumberFormat } from '../utils/format'\nimport {\n ChartTooltipCard,\n type ChartTooltipRow,\n clampTooltipPosition,\n useMeasuredSize,\n} from './chart'\nimport { SeriesLegend } from './series-legend'\nimport { SectionTitle } from './typography'\n\nconst defaultTotalFormat = localeNumberFormat()\n\nexport type BarChartCategory = string | number\n\nexport interface BarChartSeries<TDatum> {\n key: string\n label: string\n color: string\n hoverFill?: string\n getValue: (datum: TDatum) => number\n}\n\nexport interface BarChartLineSeries<TDatum> {\n key: string\n label: string\n color: string\n /** `null` gaps break the line (e.g. hours without a reading). */\n getValue: (datum: TDatum) => number | null\n /** Own y-domain for this line (e.g. `[0, 100]` for a percentage). Defaults to the bar scale. */\n domain?: [number, number]\n /** Start hidden; the user can enable the line from the legend. */\n hiddenByDefault?: boolean\n /** Formats this line's value in the hover tooltip. Defaults to `formatValue`. */\n formatValue?: (value: number) => string\n strokeDasharray?: string\n}\n\nexport interface BarChartProps<TDatum> {\n data: TDatum[]\n series: BarChartSeries<TDatum>[]\n /** Line overlays drawn on top of the bars, toggleable from the legend. */\n lines?: BarChartLineSeries<TDatum>[]\n getCategory: (datum: TDatum) => BarChartCategory\n /** Full ordered set of categories on the x-axis. Defaults to `data.map(getCategory)`. */\n categories?: BarChartCategory[]\n /** Subset of categories that should render an x-axis label. Defaults to every category. */\n categoryTicks?: BarChartCategory[]\n formatCategory?: (category: BarChartCategory) => string\n /** Formats the hovered category in the tooltip header. Defaults to `formatCategory`. */\n formatTooltipCategory?: (category: BarChartCategory) => string\n highlightedCategory?: BarChartCategory\n showHighlightLine?: boolean\n /**\n * Horizontal reference line drawn across the plot at a given y-value.\n * Useful for thresholds (e.g. price ceiling).\n */\n referenceLine?: { value: number; label?: string; color?: string }\n title?: string\n yAxisUnit?: string\n /** Overrides the y-axis tick formatter. Defaults to the shared compact formatter. */\n formatYTick?: (value: number) => string\n /** Fixes the y-axis gutter width (px). Defaults to auto-measuring the widest tick label. */\n yAxisWidth?: number\n yAxisRightUnit?: string\n /** Overrides the right y-axis tick formatter. Defaults to the shared compact formatter. */\n formatYTickRight?: (value: number) => string\n /** Fixes the right y-axis gutter width (px). Defaults to auto-measuring the widest tick label. */\n yAxisRightWidth?: number\n height?: number\n /**\n * Override how the total value (sum of focused or all categories) is\n * rendered. `animated` is false while a bar is focused (hover), so an\n * animated total can snap between hovered buckets instead of re-firing a\n * tween on every bar the pointer crosses.\n */\n renderTotal?: (value: number, animated: boolean) => React.ReactNode\n /** Format function used when `renderTotal` is not provided. */\n formatTotal?: (value: number) => string\n /** Formats per-series values in the hover tooltip. Defaults to `formatTotal`. */\n formatValue?: (value: number) => string\n className?: string\n}\n\ninterface StackDatum {\n __category: BarChartCategory\n __values: Record<string, number>\n}\n\ninterface BarStackLayerProps<TDatum> {\n stackData: StackDatum[]\n series: BarChartSeries<TDatum>[]\n seriesByKey: Map<string, BarChartSeries<TDatum>>\n xScale: ReturnType<typeof scaleBand<BarChartCategory>>\n yScale: ReturnType<typeof scaleLinear<number>>\n colorScale: ReturnType<typeof scaleOrdinal<string, string>>\n}\n\ninterface CategoryTicksProps {\n ticks: BarChartCategory[]\n xScale: ReturnType<typeof scaleBand<BarChartCategory>>\n height: number\n formatCategory: (category: BarChartCategory) => string\n}\n\nconst PADDING_TOP = 20\nconst PADDING_BOTTOM = 28\nconst HOVER_FADE_MS = 200\nconst FOCUS_TRANSITION_MS = 180\nconst DEFAULT_HEIGHT = 220\nconst BAR_RADIUS = 2\n\nfunction buildBarPath(\n x: number,\n y: number,\n width: number,\n height: number,\n radius: number,\n roundTop: boolean,\n roundBottom: boolean,\n) {\n const r = Math.max(0, Math.min(radius, width / 2, height / 2))\n\n if (r === 0 || (!roundTop && !roundBottom)) {\n return `M ${x} ${y} H ${x + width} V ${y + height} H ${x} Z`\n }\n\n const tl = roundTop ? r : 0\n const tr = roundTop ? r : 0\n const br = roundBottom ? r : 0\n const bl = roundBottom ? r : 0\n\n return [\n `M ${x + tl} ${y}`,\n `H ${x + width - tr}`,\n tr > 0\n ? `Q ${x + width} ${y} ${x + width} ${y + tr}`\n : `L ${x + width} ${y}`,\n `V ${y + height - br}`,\n br > 0\n ? `Q ${x + width} ${y + height} ${x + width - br} ${y + height}`\n : `L ${x + width} ${y + height}`,\n `H ${x + bl}`,\n bl > 0\n ? `Q ${x} ${y + height} ${x} ${y + height - bl}`\n : `L ${x} ${y + height}`,\n `V ${y + tl}`,\n tl > 0 ? `Q ${x} ${y} ${x + tl} ${y}` : `L ${x} ${y}`,\n 'Z',\n ].join(' ')\n}\n\nfunction BarStackLayer<TDatum>({\n stackData,\n series,\n seriesByKey,\n xScale,\n yScale,\n colorScale,\n}: BarStackLayerProps<TDatum>) {\n return (\n <BarStack<StackDatum, string>\n data={stackData}\n keys={series.map((entry) => entry.key)}\n x={(record) => record.__category}\n value={(record, key) => record.__values[key] ?? 0}\n xScale={xScale}\n yScale={yScale}\n color={colorScale}\n offset=\"diverging\"\n >\n {(barStacks) =>\n barStacks.map((barStack) =>\n barStack.bars.map((bar) => {\n const values = bar.bar.data.__values\n const segmentValue = values[barStack.key] ?? 0\n\n if (segmentValue === 0) {\n return null\n }\n\n const seriesEntry = seriesByKey.get(barStack.key)\n const strokeColor = seriesEntry?.color ?? bar.color\n const fillColor = strokeColor\n\n // Positive segments stack up from the baseline, negatives down.\n // Round only the outermost corner of each side of the axis.\n const positiveKeys = series\n .map((entry) => entry.key)\n .filter((key) => (values[key] ?? 0) > 0)\n const negativeKeys = series\n .map((entry) => entry.key)\n .filter((key) => (values[key] ?? 0) < 0)\n const roundTop =\n segmentValue > 0 &&\n positiveKeys[positiveKeys.length - 1] === barStack.key\n const roundBottom =\n segmentValue > 0\n ? positiveKeys[0] === barStack.key\n : negativeKeys[negativeKeys.length - 1] === barStack.key\n\n // visx returns a signed height for below-baseline bars; normalize\n // to a top-left origin with a positive height for the path.\n const top = bar.height < 0 ? bar.y + bar.height : bar.y\n const barHeight = Math.abs(bar.height)\n\n return (\n <path\n key={`bar-${barStack.index}-${bar.index}`}\n d={buildBarPath(\n bar.x,\n top,\n bar.width,\n Math.max(0, barHeight),\n BAR_RADIUS,\n roundTop,\n roundBottom,\n )}\n fill={fillColor}\n stroke={strokeColor}\n strokeWidth={1}\n style={{ transition: 'fill 180ms ease' }}\n />\n )\n }),\n )\n }\n </BarStack>\n )\n}\n\ninterface FocusBorderProps<TDatum> {\n category: BarChartCategory\n visible: boolean\n stackData: StackDatum[]\n series: BarChartSeries<TDatum>[]\n xScale: ReturnType<typeof scaleBand<BarChartCategory>>\n yScale: ReturnType<typeof scaleLinear<number>>\n}\n\nfunction FocusBorder<TDatum>({\n category,\n visible,\n stackData,\n series,\n xScale,\n yScale,\n}: FocusBorderProps<TDatum>) {\n const reducedMotion = useReducedMotion()\n const x = xScale(category)\n const datum = stackData.find((entry) => entry.__category === category)\n\n if (x === undefined || !datum) {\n return null\n }\n\n const hasAnyValue = series.some(\n (entry) => (datum.__values[entry.key] ?? 0) !== 0,\n )\n\n if (!hasAnyValue) {\n return null\n }\n\n const topY = PADDING_TOP\n // Extend past the baseline to cover any below-axis (feed-in) segment.\n const negativeSum = series.reduce(\n (sum, entry) => sum + Math.min(0, datum.__values[entry.key] ?? 0),\n 0,\n )\n const bottomY = yScale(negativeSum)\n const borderPaddingX = 4\n const borderPaddingY = 3\n const borderXRaw = x - borderPaddingX\n const borderY = topY - borderPaddingY\n const borderWidthRaw = xScale.bandwidth() + borderPaddingX * 2\n const [rangeStart, rangeEnd] = xScale.range()\n const minX = Math.min(rangeStart, rangeEnd)\n const maxX = Math.max(rangeStart, rangeEnd)\n const borderX = Math.max(minX, borderXRaw)\n const borderRight = Math.min(maxX, borderXRaw + borderWidthRaw)\n const borderWidth = Math.max(0, borderRight - borderX)\n const borderHeight = Math.max(1, bottomY - topY + borderPaddingY * 2)\n\n if (borderWidth <= 0) {\n return null\n }\n\n return (\n <rect\n x={borderX}\n y={borderY}\n width={borderWidth}\n height={borderHeight}\n rx={6}\n fill=\"var(--spark-a2)\"\n stroke=\"var(--spark-a9)\"\n strokeWidth={2}\n pointerEvents=\"none\"\n style={{\n opacity: visible ? 1 : 0,\n transition: reducedMotion\n ? `opacity ${FOCUS_TRANSITION_MS}ms ease`\n : `x ${FOCUS_TRANSITION_MS}ms ease, y ${FOCUS_TRANSITION_MS}ms ease, width ${FOCUS_TRANSITION_MS}ms ease, height ${FOCUS_TRANSITION_MS}ms ease, opacity ${FOCUS_TRANSITION_MS}ms ease`,\n }}\n />\n )\n}\n\ninterface InteractionLayerProps {\n xDomain: BarChartCategory[]\n activeCategories: Set<BarChartCategory>\n xScale: ReturnType<typeof scaleBand<BarChartCategory>>\n height: number\n onHoverChange: (category: BarChartCategory | null) => void\n}\n\nfunction InteractionLayer({\n xDomain,\n activeCategories,\n xScale,\n height,\n onHoverChange,\n}: InteractionLayerProps) {\n const bandwidth = xScale.bandwidth()\n const [rangeStart, rangeEnd] = xScale.range()\n const minX = Math.min(rangeStart, rangeEnd)\n const maxX = Math.max(rangeStart, rangeEnd)\n\n // A single overlay that maps the pointer to the nearest category with data,\n // so there are no dead zones between/around bars to break the hover.\n const handleMove = (\n event: React.MouseEvent<SVGRectElement> | React.TouchEvent<SVGRectElement>,\n ) => {\n const point = localPoint(event)\n if (!point) return\n\n let nearest: BarChartCategory | null = null\n let best = Infinity\n for (const category of xDomain) {\n if (!activeCategories.has(category)) continue\n const x = xScale(category)\n if (x === undefined) continue\n const distance = Math.abs(x + bandwidth / 2 - point.x)\n if (distance < best) {\n best = distance\n nearest = category\n }\n }\n\n if (nearest !== null) onHoverChange(nearest)\n }\n\n return (\n <rect\n x={minX}\n y={PADDING_TOP}\n width={Math.max(0, maxX - minX)}\n height={height - PADDING_TOP - PADDING_BOTTOM}\n fill=\"transparent\"\n onMouseMove={handleMove}\n onMouseLeave={() => onHoverChange(null)}\n onTouchMove={handleMove}\n onTouchEnd={() => onHoverChange(null)}\n />\n )\n}\n\nfunction CategoryTicks({\n ticks,\n xScale,\n height,\n formatCategory,\n}: CategoryTicksProps) {\n return (\n <>\n {ticks.map((category) => {\n const x = xScale(category)\n\n if (x === undefined) {\n return null\n }\n\n return (\n <text\n key={`tick-${String(category)}`}\n x={x + xScale.bandwidth() / 2}\n y={height - PADDING_BOTTOM + 16}\n textAnchor=\"middle\"\n fill=\"var(--neutral-a11)\"\n fontSize={10}\n >\n {formatCategory(category)}\n </text>\n )\n })}\n </>\n )\n}\n\nfunction defaultFormatTotal(value: number) {\n return defaultTotalFormat.format(value)\n}\n\nexport function BarChart<TDatum>({\n data,\n series,\n lines,\n getCategory,\n categories,\n categoryTicks,\n formatCategory = (category) => String(category),\n formatTooltipCategory = formatCategory,\n highlightedCategory,\n showHighlightLine = false,\n referenceLine,\n title,\n yAxisUnit,\n formatYTick = formatYAxisTick,\n yAxisWidth,\n yAxisRightUnit,\n formatYTickRight = formatYAxisTick,\n yAxisRightWidth,\n height = DEFAULT_HEIGHT,\n renderTotal,\n formatTotal = defaultFormatTotal,\n formatValue,\n className,\n}: BarChartProps<TDatum>): React.ReactElement {\n const containerRef = useRef<HTMLDivElement>(null)\n const reducedMotion = useReducedMotion()\n const [width, setWidth] = useState(0)\n const [hoveredCategory, setHoveredCategory] =\n useState<BarChartCategory | null>(null)\n const [trailingHoverLabel, setTrailingHoverLabel] = useState<string | null>(\n null,\n )\n const [hiddenSeries, setHiddenSeries] = useState<ReadonlySet<string>>(\n () =>\n new Set(\n (lines ?? [])\n .filter((line) => line.hiddenByDefault)\n .map((line) => line.key),\n ),\n )\n\n const toggleSeries = useCallback((id: string) => {\n setHiddenSeries((prev) => {\n const next = new Set(prev)\n if (next.has(id)) {\n next.delete(id)\n } else {\n next.add(id)\n }\n return next\n })\n }, [])\n\n useEffect(() => {\n const element = containerRef.current\n\n if (!element) {\n return\n }\n\n const resizeObserver = new ResizeObserver((entries) => {\n const entry = entries[0]\n\n if (!entry) {\n return\n }\n\n setWidth(entry.contentRect.width)\n })\n\n resizeObserver.observe(element)\n\n return () => {\n resizeObserver.disconnect()\n }\n }, [])\n\n const seriesByKey = useMemo(() => {\n const map = new Map<string, BarChartSeries<TDatum>>()\n\n for (const entry of series) {\n map.set(entry.key, entry)\n }\n\n return map\n }, [series])\n\n const stackData = useMemo<StackDatum[]>(\n () =>\n data.map((datum) => {\n const values: Record<string, number> = {}\n\n for (const entry of series) {\n values[entry.key] = hiddenSeries.has(entry.key)\n ? 0\n : entry.getValue(datum)\n }\n\n return { __category: getCategory(datum), __values: values }\n }),\n [data, getCategory, series, hiddenSeries],\n )\n\n const yMax = useMemo(\n () =>\n Math.max(\n 1,\n referenceLine?.value ?? 0,\n ...stackData.map((record) =>\n series.reduce(\n (sum, entry) => sum + Math.max(0, record.__values[entry.key] ?? 0),\n 0,\n ),\n ),\n ),\n [referenceLine, series, stackData],\n )\n\n // Most negative stack sum across buckets (0 when nothing dips below the axis).\n const yMin = useMemo(\n () =>\n Math.min(\n 0,\n ...stackData.map((record) =>\n series.reduce(\n (sum, entry) => sum + Math.min(0, record.__values[entry.key] ?? 0),\n 0,\n ),\n ),\n ),\n [series, stackData],\n )\n\n const xDomain = useMemo(\n () => categories ?? stackData.map((record) => record.__category),\n [categories, stackData],\n )\n\n const yAxisScale = useMemo(() => buildYAxisScale(yMin, yMax), [yMin, yMax])\n const yTicks = yAxisScale.ticks\n const gutter = useMemo(\n () => yAxisWidth ?? measureYAxisGutter(yTicks, formatYTick),\n [yTicks, formatYTick, yAxisWidth],\n )\n\n const visibleDomainLines = useMemo(\n () =>\n (lines ?? []).filter(\n (line) => line.domain !== undefined && !hiddenSeries.has(line.key),\n ),\n [lines, hiddenSeries],\n )\n\n const rightAxisDomain = visibleDomainLines[0]?.domain\n const rightAxisScale = useMemo(\n () =>\n rightAxisDomain === undefined\n ? null\n : buildYAxisScale(rightAxisDomain[0], rightAxisDomain[1]),\n [rightAxisDomain],\n )\n const rightTicks = rightAxisScale?.ticks ?? []\n const rightGutter = useMemo(\n () =>\n rightAxisScale === null\n ? 0\n : (yAxisRightWidth ??\n measureYAxisGutter(rightTicks, formatYTickRight, 0)),\n [rightAxisScale, rightTicks, formatYTickRight, yAxisRightWidth],\n )\n const plotRight = Math.max(gutter, width - rightGutter)\n\n const xScale = useMemo(\n () =>\n scaleBand<BarChartCategory>({\n domain: xDomain,\n range: [gutter, plotRight],\n padding: 0.32,\n }),\n [xDomain, gutter, plotRight],\n )\n\n // Domain must be the tick scale's rounded bounds, not the raw data extent:\n // otherwise the outermost tick (e.g. -2 for a -1.5 kWh feed-in) maps below\n // the plot floor, onto the x-axis labels and off the bottom of the svg.\n const yScale = useMemo(\n () =>\n scaleLinear<number>({\n domain: [yAxisScale.min, yAxisScale.max],\n range: [height - PADDING_BOTTOM, PADDING_TOP],\n }),\n [height, yAxisScale],\n )\n\n const rightYScale = useMemo(\n () =>\n rightAxisDomain === undefined\n ? null\n : scaleLinear<number>({\n domain: rightAxisDomain,\n range: [height - PADDING_BOTTOM, PADDING_TOP],\n }),\n [height, rightAxisDomain],\n )\n\n const colorScale = useMemo(\n () =>\n scaleOrdinal<string, string>({\n domain: series.map((entry) => entry.key),\n range: series.map((entry) => entry.color),\n }),\n [series],\n )\n\n const linePaths = useMemo(() => {\n if (!lines || width === 0) {\n return []\n }\n\n return lines\n .filter((line) => !hiddenSeries.has(line.key))\n .map((line) => {\n const lineScale = line.domain\n ? scaleLinear<number>({\n domain: line.domain,\n range: [height - PADDING_BOTTOM, PADDING_TOP],\n })\n : yScale\n const segments: string[] = []\n let previous: { x: number; y: number } | null = null\n\n for (const datum of data) {\n const x = xScale(getCategory(datum))\n const value = line.getValue(datum)\n\n if (x === undefined || value === null || !Number.isFinite(value)) {\n previous = null\n continue\n }\n\n const point = {\n x: x + xScale.bandwidth() / 2,\n y: lineScale(value),\n }\n segments.push(\n previous === null\n ? `M ${point.x} ${point.y}`\n : `L ${point.x} ${point.y}`,\n )\n previous = point\n }\n\n return {\n key: line.key,\n d: segments.join(' '),\n color: line.color,\n strokeDasharray: line.strokeDasharray ?? '5 4',\n }\n })\n .filter((path) => path.d !== '')\n }, [lines, hiddenSeries, data, getCategory, xScale, yScale, height, width])\n\n const stackCategorySet = useMemo(\n () => new Set(stackData.map((record) => record.__category)),\n [stackData],\n )\n\n const lastFocusCategoryRef = useRef<BarChartCategory | null>(null)\n if (hoveredCategory !== null) {\n lastFocusCategoryRef.current = hoveredCategory\n }\n const focusCategory = lastFocusCategoryRef.current\n\n const focused = useMemo(\n () =>\n hoveredCategory === null\n ? null\n : (stackData.find((record) => record.__category === hoveredCategory) ??\n null),\n [hoveredCategory, stackData],\n )\n\n // Below-baseline segments (feed-in) are context, not part of the headline\n // sum, so the total counts only the positive stack (energy consumed).\n const totalValue = useMemo(() => {\n if (focused) {\n return series.reduce(\n (sum, entry) => sum + Math.max(0, focused.__values[entry.key] ?? 0),\n 0,\n )\n }\n\n return stackData.reduce(\n (sum, record) =>\n sum +\n series.reduce(\n (s, entry) => s + Math.max(0, record.__values[entry.key] ?? 0),\n 0,\n ),\n 0,\n )\n }, [focused, series, stackData])\n\n const hoverLabel = focused ? formatTooltipCategory(focused.__category) : null\n\n useEffect(() => {\n if (hoverLabel) {\n setTrailingHoverLabel(hoverLabel)\n return\n }\n\n const timeoutId = window.setTimeout(() => {\n setTrailingHoverLabel(null)\n }, HOVER_FADE_MS)\n\n return () => {\n window.clearTimeout(timeoutId)\n }\n }, [hoverLabel])\n\n const ticks = categoryTicks ?? xDomain\n const highlightX = useMemo(() => {\n if (!showHighlightLine || highlightedCategory === undefined) {\n return null\n }\n\n const x = xScale(highlightedCategory)\n\n if (x === undefined) {\n return null\n }\n\n return x + xScale.bandwidth() / 2\n }, [highlightedCategory, showHighlightLine, xScale])\n\n const focusedDatum = useMemo(\n () =>\n hoveredCategory === null\n ? null\n : (data.find((datum) => getCategory(datum) === hoveredCategory) ??\n null),\n [hoveredCategory, data, getCategory],\n )\n\n // The bars don't depend on hover state, so memoize the layer: hovering\n // across bars must not re-render (and re-stack) every bar path each move.\n const barStackLayer = useMemo(\n () => (\n <BarStackLayer\n stackData={stackData}\n series={series}\n seriesByKey={seriesByKey}\n xScale={xScale}\n yScale={yScale}\n colorScale={colorScale}\n />\n ),\n [stackData, series, seriesByKey, xScale, yScale, colorScale],\n )\n\n const fmtTooltipValue = formatValue ?? formatTotal\n const tooltipRows: ChartTooltipRow[] = focused\n ? [\n ...series\n .filter((entry) => (focused.__values[entry.key] ?? 0) !== 0)\n .map((entry) => ({\n key: entry.key,\n label: entry.label,\n color: entry.color,\n value: fmtTooltipValue(Math.abs(focused.__values[entry.key] ?? 0)),\n })),\n ...(lines ?? [])\n .filter((line) => !hiddenSeries.has(line.key))\n .flatMap((line) => {\n const value =\n focusedDatum === null ? null : line.getValue(focusedDatum)\n\n if (value === null || !Number.isFinite(value)) {\n return []\n }\n\n return [\n {\n key: line.key,\n label: line.label,\n color: line.color,\n value: (line.formatValue ?? fmtTooltipValue)(value),\n marker: 'dashed-line' as const,\n },\n ]\n }),\n ]\n : []\n const tooltipActive = tooltipRows.length > 0\n const anchorX =\n focusCategory !== null\n ? (xScale(focusCategory) ?? 0) + xScale.bandwidth() / 2\n : 0\n const anchorY = yScale(totalValue)\n const [tooltipRef, tooltipSize] = useMeasuredSize<HTMLDivElement>()\n const tooltipPos = clampTooltipPosition({\n anchorX,\n anchorY,\n width,\n height,\n tipWidth: tooltipSize.width,\n tipHeight: tooltipSize.height,\n })\n\n return (\n <div\n data-slot=\"bar-chart\"\n className={cn('flex w-full flex-col', className)}\n >\n <div className=\"flex items-baseline justify-between\">\n {title && <SectionTitle>{title}</SectionTitle>}\n <span className=\"tabular-nums\">\n {renderTotal ? (\n renderTotal(totalValue, focused === null)\n ) : (\n <span className=\"text-base font-bold text-gray tabular-nums\">\n {formatTotal(totalValue)}\n </span>\n )}\n </span>\n </div>\n\n <div className=\"flex min-h-5 items-baseline justify-between gap-4\">\n <SeriesLegend\n items={[\n ...series.map((entry) => ({\n id: entry.key,\n label: entry.label,\n color: entry.color,\n })),\n ...(lines ?? []).map((line) => ({\n id: line.key,\n label: line.label,\n color: line.color,\n marker: 'dashed-line' as const,\n })),\n ]}\n hiddenIds={hiddenSeries}\n onToggle={toggleSeries}\n className=\"gap-y-1\"\n />\n <span\n className={cn(\n 'text-xs text-gray-light transition-opacity duration-200',\n hoverLabel ? 'opacity-100' : 'opacity-0',\n )}\n >\n {trailingHoverLabel ?? ' '}\n </span>\n </div>\n\n <div\n ref={containerRef}\n className=\"relative mt-2 w-full\"\n style={{ height }}\n >\n <div\n ref={tooltipRef}\n className=\"pointer-events-none absolute z-10\"\n style={{\n left: tooltipPos.left,\n top: tooltipPos.top,\n opacity: tooltipActive ? 1 : 0,\n transition: reducedMotion\n ? 'opacity 140ms ease-out'\n : 'left 140ms ease-out, top 140ms ease-out, opacity 140ms ease-out',\n }}\n >\n {focusCategory !== null && (\n <ChartTooltipCard\n label={formatTooltipCategory(focusCategory)}\n rows={tooltipRows}\n />\n )}\n </div>\n {width > 0 && (\n <svg width={width} height={height}>\n <line\n x1={gutter}\n x2={gutter}\n y1={PADDING_TOP}\n y2={height - PADDING_BOTTOM}\n stroke=\"var(--neutral-a6)\"\n strokeWidth={1}\n />\n\n {yTicks.map((tick, index) => {\n const y = yScale(tick)\n const hideTickLabel =\n yAxisUnit !== undefined && index === yTicks.length - 1\n\n return (\n <g key={`y-tick-${tick}`}>\n {!hideTickLabel && (\n <line\n x1={gutter - 4}\n x2={gutter}\n y1={y}\n y2={y}\n stroke=\"var(--neutral-a8)\"\n strokeWidth={1}\n />\n )}\n {!hideTickLabel && (\n <text\n x={gutter - 7}\n y={y + 3}\n textAnchor=\"end\"\n fill=\"var(--neutral-a11)\"\n fontSize={10}\n >\n {formatYTick(tick)}\n </text>\n )}\n </g>\n )\n })}\n\n {yAxisUnit && (\n <text\n x={0}\n y={PADDING_TOP - 6}\n textAnchor=\"start\"\n fill=\"var(--neutral-a11)\"\n fontSize={10}\n fontWeight={600}\n >\n {yAxisUnit}\n </text>\n )}\n\n {highlightX !== null && (\n <line\n x1={highlightX}\n x2={highlightX}\n y1={PADDING_TOP}\n y2={height - PADDING_BOTTOM}\n stroke=\"var(--spark-a9)\"\n strokeWidth={1.5}\n strokeDasharray=\"5 4\"\n pointerEvents=\"none\"\n />\n )}\n\n <line\n x1={gutter}\n x2={plotRight}\n y1={yScale(0)}\n y2={yScale(0)}\n stroke=\"var(--neutral-a5)\"\n strokeWidth={1}\n />\n\n {rightYScale !== null && (\n <>\n <line\n x1={plotRight}\n x2={plotRight}\n y1={PADDING_TOP}\n y2={height - PADDING_BOTTOM}\n stroke=\"var(--neutral-a6)\"\n strokeWidth={1}\n />\n\n {rightTicks.map((tick, index) => {\n const y = rightYScale(tick)\n const hideTickLabel =\n yAxisRightUnit !== undefined &&\n index === rightTicks.length - 1\n\n return (\n <g key={`y-tick-right-${tick}`}>\n {!hideTickLabel && (\n <line\n x1={plotRight}\n x2={plotRight + 4}\n y1={y}\n y2={y}\n stroke=\"var(--neutral-a8)\"\n strokeWidth={1}\n />\n )}\n {!hideTickLabel && (\n <text\n x={plotRight + 7}\n y={y + 3}\n textAnchor=\"start\"\n fill=\"var(--neutral-a11)\"\n fontSize={10}\n >\n {formatYTickRight(tick)}\n </text>\n )}\n </g>\n )\n })}\n\n {yAxisRightUnit && (\n <text\n x={width}\n y={PADDING_TOP - 6}\n textAnchor=\"end\"\n fill=\"var(--neutral-a11)\"\n fontSize={10}\n fontWeight={600}\n >\n {yAxisRightUnit}\n </text>\n )}\n </>\n )}\n\n <Group>\n {focusCategory !== null && (\n <FocusBorder\n category={focusCategory}\n visible={hoveredCategory !== null}\n stackData={stackData}\n series={series}\n xScale={xScale}\n yScale={yScale}\n />\n )}\n {barStackLayer}\n\n {referenceLine && (\n <line\n x1={gutter}\n x2={width}\n y1={yScale(referenceLine.value)}\n y2={yScale(referenceLine.value)}\n stroke={referenceLine.color ?? 'var(--neutral-a11)'}\n strokeWidth={1.5}\n pointerEvents=\"none\"\n />\n )}\n\n {linePaths.map((path) => (\n <path\n key={`line-${path.key}`}\n d={path.d}\n fill=\"none\"\n stroke={path.color}\n strokeWidth={1.5}\n strokeDasharray={path.strokeDasharray}\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n pointerEvents=\"none\"\n />\n ))}\n </Group>\n\n <InteractionLayer\n xDomain={xDomain}\n activeCategories={stackCategorySet}\n xScale={xScale}\n height={height}\n onHoverChange={setHoveredCategory}\n />\n\n <CategoryTicks\n ticks={ticks}\n xScale={xScale}\n height={height}\n formatCategory={formatCategory}\n />\n </svg>\n )}\n </div>\n </div>\n )\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"bar-chart.js","names":[],"sources":["../../src/components/bar-chart.tsx"],"sourcesContent":["import { localPoint } from '@visx/event'\nimport { Group } from '@visx/group'\nimport { scaleBand, scaleLinear, scaleOrdinal } from '@visx/scale'\nimport { BarStack } from '@visx/shape'\nimport { useCallback, useEffect, useMemo, useRef, useState } from 'react'\nimport { useReducedMotion } from '../hooks/use-reduced-motion'\nimport {\n buildYAxisScale,\n formatYAxisTick,\n measureYAxisGutter,\n} from '../utils/chart-scale'\nimport { cn } from '../utils/cn'\nimport { localeNumberFormat } from '../utils/format'\nimport {\n ChartTooltipCard,\n type ChartTooltipRow,\n clampTooltipPosition,\n useMeasuredSize,\n} from './chart'\nimport { SeriesLegend } from './series-legend'\nimport { SectionTitle } from './typography'\n\nconst defaultTotalFormat = localeNumberFormat()\n\nexport type BarChartCategory = string | number\n\nexport interface BarChartSeries<TDatum> {\n key: string\n label: string\n color: string\n hoverFill?: string\n getValue: (datum: TDatum) => number\n}\n\nexport interface BarChartLineSeries<TDatum> {\n key: string\n label: string\n color: string\n /** `null` gaps break the line (e.g. hours without a reading). */\n getValue: (datum: TDatum) => number | null\n /** Own y-domain for this line (e.g. `[0, 100]` for a percentage). Defaults to the bar scale. */\n domain?: [number, number]\n /** Start hidden; the user can enable the line from the legend. */\n hiddenByDefault?: boolean\n /** Formats this line's value in the hover tooltip. Defaults to `formatValue`. */\n formatValue?: (value: number) => string\n strokeDasharray?: string\n}\n\nexport interface BarChartProps<TDatum> {\n data: TDatum[]\n series: BarChartSeries<TDatum>[]\n /** Line overlays drawn on top of the bars, toggleable from the legend. */\n lines?: BarChartLineSeries<TDatum>[]\n getCategory: (datum: TDatum) => BarChartCategory\n /** Full ordered set of categories on the x-axis. Defaults to `data.map(getCategory)`. */\n categories?: BarChartCategory[]\n /** Subset of categories that should render an x-axis label. Defaults to every category. */\n categoryTicks?: BarChartCategory[]\n formatCategory?: (category: BarChartCategory) => string\n /** Formats the hovered category in the tooltip header. Defaults to `formatCategory`. */\n formatTooltipCategory?: (category: BarChartCategory) => string\n highlightedCategory?: BarChartCategory\n showHighlightLine?: boolean\n /**\n * Horizontal reference line drawn across the plot at a given y-value.\n * Useful for thresholds (e.g. price ceiling).\n */\n referenceLine?: { value: number; label?: string; color?: string }\n title?: string\n yAxisUnit?: string\n /** Overrides the y-axis tick formatter. Defaults to the shared compact formatter. */\n formatYTick?: (value: number) => string\n /** Fixes the y-axis gutter width (px). Defaults to auto-measuring the widest tick label. */\n yAxisWidth?: number\n yAxisRightUnit?: string\n /** Overrides the right y-axis tick formatter. Defaults to the shared compact formatter. */\n formatYTickRight?: (value: number) => string\n /** Fixes the right y-axis gutter width (px). Defaults to auto-measuring the widest tick label. */\n yAxisRightWidth?: number\n height?: number\n /**\n * Override how the total value (sum of focused or all categories) is\n * rendered. `animated` is false while a bar is focused (hover), so an\n * animated total can snap between hovered buckets instead of re-firing a\n * tween on every bar the pointer crosses.\n */\n renderTotal?: (value: number, animated: boolean) => React.ReactNode\n /** Format function used when `renderTotal` is not provided. */\n formatTotal?: (value: number) => string\n /** Formats per-series values in the hover tooltip. Defaults to `formatTotal`. */\n formatValue?: (value: number) => string\n className?: string\n}\n\ninterface StackDatum {\n __category: BarChartCategory\n __values: Record<string, number>\n}\n\ninterface BarStackLayerProps<TDatum> {\n stackData: StackDatum[]\n series: BarChartSeries<TDatum>[]\n seriesByKey: Map<string, BarChartSeries<TDatum>>\n xScale: ReturnType<typeof scaleBand<BarChartCategory>>\n yScale: ReturnType<typeof scaleLinear<number>>\n colorScale: ReturnType<typeof scaleOrdinal<string, string>>\n}\n\ninterface CategoryTicksProps {\n ticks: BarChartCategory[]\n xScale: ReturnType<typeof scaleBand<BarChartCategory>>\n height: number\n formatCategory: (category: BarChartCategory) => string\n}\n\nconst PADDING_TOP = 20\nconst PADDING_BOTTOM = 28\nconst HOVER_FADE_MS = 200\nconst FOCUS_TRANSITION_MS = 180\nconst DEFAULT_HEIGHT = 220\nconst BAR_RADIUS = 2\n// Shared so the no-right-axis case keeps a stable identity: a `?? []` literal is a new\n// array each render, which churns any dep array it lands in.\nconst NO_TICKS: number[] = []\n\nfunction buildBarPath(\n x: number,\n y: number,\n width: number,\n height: number,\n radius: number,\n roundTop: boolean,\n roundBottom: boolean,\n) {\n const r = Math.max(0, Math.min(radius, width / 2, height / 2))\n\n if (r === 0 || (!roundTop && !roundBottom)) {\n return `M ${x} ${y} H ${x + width} V ${y + height} H ${x} Z`\n }\n\n const tl = roundTop ? r : 0\n const tr = roundTop ? r : 0\n const br = roundBottom ? r : 0\n const bl = roundBottom ? r : 0\n\n return [\n `M ${x + tl} ${y}`,\n `H ${x + width - tr}`,\n tr > 0\n ? `Q ${x + width} ${y} ${x + width} ${y + tr}`\n : `L ${x + width} ${y}`,\n `V ${y + height - br}`,\n br > 0\n ? `Q ${x + width} ${y + height} ${x + width - br} ${y + height}`\n : `L ${x + width} ${y + height}`,\n `H ${x + bl}`,\n bl > 0\n ? `Q ${x} ${y + height} ${x} ${y + height - bl}`\n : `L ${x} ${y + height}`,\n `V ${y + tl}`,\n tl > 0 ? `Q ${x} ${y} ${x + tl} ${y}` : `L ${x} ${y}`,\n 'Z',\n ].join(' ')\n}\n\nfunction BarStackLayer<TDatum>({\n stackData,\n series,\n seriesByKey,\n xScale,\n yScale,\n colorScale,\n}: BarStackLayerProps<TDatum>) {\n return (\n <BarStack<StackDatum, string>\n data={stackData}\n keys={series.map((entry) => entry.key)}\n x={(record) => record.__category}\n value={(record, key) => record.__values[key] ?? 0}\n xScale={xScale}\n yScale={yScale}\n color={colorScale}\n offset=\"diverging\"\n >\n {(barStacks) =>\n barStacks.map((barStack) =>\n barStack.bars.map((bar) => {\n const values = bar.bar.data.__values\n const segmentValue = values[barStack.key] ?? 0\n\n if (segmentValue === 0) {\n return null\n }\n\n const seriesEntry = seriesByKey.get(barStack.key)\n const strokeColor = seriesEntry?.color ?? bar.color\n const fillColor = strokeColor\n\n // Positive segments stack up from the baseline, negatives down.\n // Round only the outermost corner of each side of the axis.\n const positiveKeys = series\n .map((entry) => entry.key)\n .filter((key) => (values[key] ?? 0) > 0)\n const negativeKeys = series\n .map((entry) => entry.key)\n .filter((key) => (values[key] ?? 0) < 0)\n const roundTop =\n segmentValue > 0 &&\n positiveKeys[positiveKeys.length - 1] === barStack.key\n const roundBottom =\n segmentValue > 0\n ? positiveKeys[0] === barStack.key\n : negativeKeys[negativeKeys.length - 1] === barStack.key\n\n // visx returns a signed height for below-baseline bars; normalize\n // to a top-left origin with a positive height for the path.\n const top = bar.height < 0 ? bar.y + bar.height : bar.y\n const barHeight = Math.abs(bar.height)\n\n return (\n <path\n key={`bar-${barStack.index}-${bar.index}`}\n d={buildBarPath(\n bar.x,\n top,\n bar.width,\n Math.max(0, barHeight),\n BAR_RADIUS,\n roundTop,\n roundBottom,\n )}\n fill={fillColor}\n stroke={strokeColor}\n strokeWidth={1}\n style={{ transition: 'fill 180ms ease' }}\n />\n )\n }),\n )\n }\n </BarStack>\n )\n}\n\ninterface FocusBorderProps<TDatum> {\n category: BarChartCategory\n visible: boolean\n stackData: StackDatum[]\n series: BarChartSeries<TDatum>[]\n xScale: ReturnType<typeof scaleBand<BarChartCategory>>\n yScale: ReturnType<typeof scaleLinear<number>>\n}\n\nfunction FocusBorder<TDatum>({\n category,\n visible,\n stackData,\n series,\n xScale,\n yScale,\n}: FocusBorderProps<TDatum>) {\n const reducedMotion = useReducedMotion()\n const x = xScale(category)\n const datum = stackData.find((entry) => entry.__category === category)\n\n if (x === undefined || !datum) {\n return null\n }\n\n const hasAnyValue = series.some(\n (entry) => (datum.__values[entry.key] ?? 0) !== 0,\n )\n\n if (!hasAnyValue) {\n return null\n }\n\n const topY = PADDING_TOP\n // Extend past the baseline to cover any below-axis (feed-in) segment.\n const negativeSum = series.reduce(\n (sum, entry) => sum + Math.min(0, datum.__values[entry.key] ?? 0),\n 0,\n )\n const bottomY = yScale(negativeSum)\n const borderPaddingX = 4\n const borderPaddingY = 3\n const borderXRaw = x - borderPaddingX\n const borderY = topY - borderPaddingY\n const borderWidthRaw = xScale.bandwidth() + borderPaddingX * 2\n const [rangeStart, rangeEnd] = xScale.range()\n const minX = Math.min(rangeStart, rangeEnd)\n const maxX = Math.max(rangeStart, rangeEnd)\n const borderX = Math.max(minX, borderXRaw)\n const borderRight = Math.min(maxX, borderXRaw + borderWidthRaw)\n const borderWidth = Math.max(0, borderRight - borderX)\n const borderHeight = Math.max(1, bottomY - topY + borderPaddingY * 2)\n\n if (borderWidth <= 0) {\n return null\n }\n\n return (\n <rect\n x={borderX}\n y={borderY}\n width={borderWidth}\n height={borderHeight}\n rx={6}\n fill=\"var(--spark-a2)\"\n stroke=\"var(--spark-a9)\"\n strokeWidth={2}\n pointerEvents=\"none\"\n style={{\n opacity: visible ? 1 : 0,\n transition: reducedMotion\n ? `opacity ${FOCUS_TRANSITION_MS}ms ease`\n : `x ${FOCUS_TRANSITION_MS}ms ease, y ${FOCUS_TRANSITION_MS}ms ease, width ${FOCUS_TRANSITION_MS}ms ease, height ${FOCUS_TRANSITION_MS}ms ease, opacity ${FOCUS_TRANSITION_MS}ms ease`,\n }}\n />\n )\n}\n\ninterface InteractionLayerProps {\n xDomain: BarChartCategory[]\n activeCategories: Set<BarChartCategory>\n xScale: ReturnType<typeof scaleBand<BarChartCategory>>\n height: number\n onHoverChange: (category: BarChartCategory | null) => void\n}\n\nfunction InteractionLayer({\n xDomain,\n activeCategories,\n xScale,\n height,\n onHoverChange,\n}: InteractionLayerProps) {\n const bandwidth = xScale.bandwidth()\n const [rangeStart, rangeEnd] = xScale.range()\n const minX = Math.min(rangeStart, rangeEnd)\n const maxX = Math.max(rangeStart, rangeEnd)\n\n // A single overlay that maps the pointer to the nearest category with data,\n // so there are no dead zones between/around bars to break the hover.\n const handleMove = (\n event: React.MouseEvent<SVGRectElement> | React.TouchEvent<SVGRectElement>,\n ) => {\n const point = localPoint(event)\n if (!point) return\n\n let nearest: BarChartCategory | null = null\n let best = Infinity\n for (const category of xDomain) {\n if (!activeCategories.has(category)) continue\n const x = xScale(category)\n if (x === undefined) continue\n const distance = Math.abs(x + bandwidth / 2 - point.x)\n if (distance < best) {\n best = distance\n nearest = category\n }\n }\n\n if (nearest !== null) onHoverChange(nearest)\n }\n\n return (\n <rect\n x={minX}\n y={PADDING_TOP}\n width={Math.max(0, maxX - minX)}\n height={height - PADDING_TOP - PADDING_BOTTOM}\n fill=\"transparent\"\n onMouseMove={handleMove}\n onMouseLeave={() => onHoverChange(null)}\n onTouchMove={handleMove}\n onTouchEnd={() => onHoverChange(null)}\n />\n )\n}\n\nfunction CategoryTicks({\n ticks,\n xScale,\n height,\n formatCategory,\n}: CategoryTicksProps) {\n return (\n <>\n {ticks.map((category) => {\n const x = xScale(category)\n\n if (x === undefined) {\n return null\n }\n\n return (\n <text\n key={`tick-${String(category)}`}\n x={x + xScale.bandwidth() / 2}\n y={height - PADDING_BOTTOM + 16}\n textAnchor=\"middle\"\n fill=\"var(--neutral-a11)\"\n fontSize={10}\n >\n {formatCategory(category)}\n </text>\n )\n })}\n </>\n )\n}\n\nfunction defaultFormatTotal(value: number) {\n return defaultTotalFormat.format(value)\n}\n\nexport function BarChart<TDatum>({\n data,\n series,\n lines,\n getCategory,\n categories,\n categoryTicks,\n formatCategory = (category) => String(category),\n formatTooltipCategory = formatCategory,\n highlightedCategory,\n showHighlightLine = false,\n referenceLine,\n title,\n yAxisUnit,\n formatYTick = formatYAxisTick,\n yAxisWidth,\n yAxisRightUnit,\n formatYTickRight = formatYAxisTick,\n yAxisRightWidth,\n height = DEFAULT_HEIGHT,\n renderTotal,\n formatTotal = defaultFormatTotal,\n formatValue,\n className,\n}: BarChartProps<TDatum>): React.ReactElement {\n const containerRef = useRef<HTMLDivElement>(null)\n const reducedMotion = useReducedMotion()\n const [width, setWidth] = useState(0)\n const [hoveredCategory, setHoveredCategory] =\n useState<BarChartCategory | null>(null)\n const [trailingHoverLabel, setTrailingHoverLabel] = useState<string | null>(\n null,\n )\n const [hiddenSeries, setHiddenSeries] = useState<ReadonlySet<string>>(\n () =>\n new Set(\n (lines ?? [])\n .filter((line) => line.hiddenByDefault)\n .map((line) => line.key),\n ),\n )\n\n const toggleSeries = useCallback((id: string) => {\n setHiddenSeries((prev) => {\n const next = new Set(prev)\n if (next.has(id)) {\n next.delete(id)\n } else {\n next.add(id)\n }\n return next\n })\n }, [])\n\n useEffect(() => {\n const element = containerRef.current\n\n if (!element) {\n return\n }\n\n const resizeObserver = new ResizeObserver((entries) => {\n const entry = entries[0]\n\n if (!entry) {\n return\n }\n\n setWidth(entry.contentRect.width)\n })\n\n resizeObserver.observe(element)\n\n return () => {\n resizeObserver.disconnect()\n }\n }, [])\n\n const seriesByKey = useMemo(() => {\n const map = new Map<string, BarChartSeries<TDatum>>()\n\n for (const entry of series) {\n map.set(entry.key, entry)\n }\n\n return map\n }, [series])\n\n const stackData = useMemo<StackDatum[]>(\n () =>\n data.map((datum) => {\n const values: Record<string, number> = {}\n\n for (const entry of series) {\n values[entry.key] = hiddenSeries.has(entry.key)\n ? 0\n : entry.getValue(datum)\n }\n\n return { __category: getCategory(datum), __values: values }\n }),\n [data, getCategory, series, hiddenSeries],\n )\n\n const yMax = useMemo(\n () =>\n Math.max(\n 1,\n referenceLine?.value ?? 0,\n ...stackData.map((record) =>\n series.reduce(\n (sum, entry) => sum + Math.max(0, record.__values[entry.key] ?? 0),\n 0,\n ),\n ),\n ),\n [referenceLine, series, stackData],\n )\n\n // Most negative stack sum across buckets (0 when nothing dips below the axis).\n const yMin = useMemo(\n () =>\n Math.min(\n 0,\n ...stackData.map((record) =>\n series.reduce(\n (sum, entry) => sum + Math.min(0, record.__values[entry.key] ?? 0),\n 0,\n ),\n ),\n ),\n [series, stackData],\n )\n\n const xDomain = useMemo(\n () => categories ?? stackData.map((record) => record.__category),\n [categories, stackData],\n )\n\n const yAxisScale = useMemo(() => buildYAxisScale(yMin, yMax), [yMin, yMax])\n const yTicks = yAxisScale.ticks\n const gutter = useMemo(\n () => yAxisWidth ?? measureYAxisGutter(yTicks, formatYTick),\n [yTicks, formatYTick, yAxisWidth],\n )\n\n const visibleDomainLines = useMemo(\n () =>\n (lines ?? []).filter(\n (line) => line.domain !== undefined && !hiddenSeries.has(line.key),\n ),\n [lines, hiddenSeries],\n )\n\n const rightAxisDomain = visibleDomainLines[0]?.domain\n const rightAxisScale = useMemo(\n () =>\n rightAxisDomain === undefined\n ? null\n : buildYAxisScale(rightAxisDomain[0], rightAxisDomain[1]),\n [rightAxisDomain],\n )\n const rightTicks = rightAxisScale?.ticks ?? NO_TICKS\n const rightGutter = useMemo(\n () =>\n rightAxisScale === null\n ? 0\n : (yAxisRightWidth ??\n measureYAxisGutter(rightTicks, formatYTickRight, 0)),\n [rightAxisScale, rightTicks, formatYTickRight, yAxisRightWidth],\n )\n const plotRight = Math.max(gutter, width - rightGutter)\n\n const xScale = useMemo(\n () =>\n scaleBand<BarChartCategory>({\n domain: xDomain,\n range: [gutter, plotRight],\n padding: 0.32,\n }),\n [xDomain, gutter, plotRight],\n )\n\n // Domain must be the tick scale's rounded bounds, not the raw data extent:\n // otherwise the outermost tick (e.g. -2 for a -1.5 kWh feed-in) maps below\n // the plot floor, onto the x-axis labels and off the bottom of the svg.\n const yScale = useMemo(\n () =>\n scaleLinear<number>({\n domain: [yAxisScale.min, yAxisScale.max],\n range: [height - PADDING_BOTTOM, PADDING_TOP],\n }),\n [height, yAxisScale],\n )\n\n const rightYScale = useMemo(\n () =>\n rightAxisDomain === undefined\n ? null\n : scaleLinear<number>({\n domain: rightAxisDomain,\n range: [height - PADDING_BOTTOM, PADDING_TOP],\n }),\n [height, rightAxisDomain],\n )\n\n const colorScale = useMemo(\n () =>\n scaleOrdinal<string, string>({\n domain: series.map((entry) => entry.key),\n range: series.map((entry) => entry.color),\n }),\n [series],\n )\n\n const linePaths = useMemo(() => {\n if (!lines || width === 0) {\n return []\n }\n\n return lines\n .filter((line) => !hiddenSeries.has(line.key))\n .map((line) => {\n const lineScale = line.domain\n ? scaleLinear<number>({\n domain: line.domain,\n range: [height - PADDING_BOTTOM, PADDING_TOP],\n })\n : yScale\n const segments: string[] = []\n let previous: { x: number; y: number } | null = null\n\n for (const datum of data) {\n const x = xScale(getCategory(datum))\n const value = line.getValue(datum)\n\n if (x === undefined || value === null || !Number.isFinite(value)) {\n previous = null\n continue\n }\n\n const point = {\n x: x + xScale.bandwidth() / 2,\n y: lineScale(value),\n }\n segments.push(\n previous === null\n ? `M ${point.x} ${point.y}`\n : `L ${point.x} ${point.y}`,\n )\n previous = point\n }\n\n return {\n key: line.key,\n d: segments.join(' '),\n color: line.color,\n strokeDasharray: line.strokeDasharray ?? '5 4',\n }\n })\n .filter((path) => path.d !== '')\n }, [lines, hiddenSeries, data, getCategory, xScale, yScale, height, width])\n\n const stackCategorySet = useMemo(\n () => new Set(stackData.map((record) => record.__category)),\n [stackData],\n )\n\n const lastFocusCategoryRef = useRef<BarChartCategory | null>(null)\n if (hoveredCategory !== null) {\n lastFocusCategoryRef.current = hoveredCategory\n }\n const focusCategory = lastFocusCategoryRef.current\n\n const focused = useMemo(\n () =>\n hoveredCategory === null\n ? null\n : (stackData.find((record) => record.__category === hoveredCategory) ??\n null),\n [hoveredCategory, stackData],\n )\n\n // Below-baseline segments (feed-in) are context, not part of the headline\n // sum, so the total counts only the positive stack (energy consumed).\n const totalValue = useMemo(() => {\n if (focused) {\n return series.reduce(\n (sum, entry) => sum + Math.max(0, focused.__values[entry.key] ?? 0),\n 0,\n )\n }\n\n return stackData.reduce(\n (sum, record) =>\n sum +\n series.reduce(\n (s, entry) => s + Math.max(0, record.__values[entry.key] ?? 0),\n 0,\n ),\n 0,\n )\n }, [focused, series, stackData])\n\n const hoverLabel = focused ? formatTooltipCategory(focused.__category) : null\n\n useEffect(() => {\n if (hoverLabel) {\n setTrailingHoverLabel(hoverLabel)\n return\n }\n\n const timeoutId = window.setTimeout(() => {\n setTrailingHoverLabel(null)\n }, HOVER_FADE_MS)\n\n return () => {\n window.clearTimeout(timeoutId)\n }\n }, [hoverLabel])\n\n const ticks = categoryTicks ?? xDomain\n const highlightX = useMemo(() => {\n if (!showHighlightLine || highlightedCategory === undefined) {\n return null\n }\n\n const x = xScale(highlightedCategory)\n\n if (x === undefined) {\n return null\n }\n\n return x + xScale.bandwidth() / 2\n }, [highlightedCategory, showHighlightLine, xScale])\n\n const focusedDatum = useMemo(\n () =>\n hoveredCategory === null\n ? null\n : (data.find((datum) => getCategory(datum) === hoveredCategory) ??\n null),\n [hoveredCategory, data, getCategory],\n )\n\n // The bars don't depend on hover state, so memoize the layer: hovering\n // across bars must not re-render (and re-stack) every bar path each move.\n const barStackLayer = useMemo(\n () => (\n <BarStackLayer\n stackData={stackData}\n series={series}\n seriesByKey={seriesByKey}\n xScale={xScale}\n yScale={yScale}\n colorScale={colorScale}\n />\n ),\n [stackData, series, seriesByKey, xScale, yScale, colorScale],\n )\n\n const fmtTooltipValue = formatValue ?? formatTotal\n const tooltipRows: ChartTooltipRow[] = focused\n ? [\n ...series\n .filter((entry) => (focused.__values[entry.key] ?? 0) !== 0)\n .map((entry) => ({\n key: entry.key,\n label: entry.label,\n color: entry.color,\n value: fmtTooltipValue(Math.abs(focused.__values[entry.key] ?? 0)),\n })),\n ...(lines ?? [])\n .filter((line) => !hiddenSeries.has(line.key))\n .flatMap((line) => {\n const value =\n focusedDatum === null ? null : line.getValue(focusedDatum)\n\n if (value === null || !Number.isFinite(value)) {\n return []\n }\n\n return [\n {\n key: line.key,\n label: line.label,\n color: line.color,\n value: (line.formatValue ?? fmtTooltipValue)(value),\n marker: 'dashed-line' as const,\n },\n ]\n }),\n ]\n : []\n const tooltipActive = tooltipRows.length > 0\n const anchorX =\n focusCategory !== null\n ? (xScale(focusCategory) ?? 0) + xScale.bandwidth() / 2\n : 0\n const anchorY = yScale(totalValue)\n const [tooltipRef, tooltipSize] = useMeasuredSize<HTMLDivElement>()\n const tooltipPos = clampTooltipPosition({\n anchorX,\n anchorY,\n width,\n height,\n tipWidth: tooltipSize.width,\n tipHeight: tooltipSize.height,\n })\n\n return (\n <div\n data-slot=\"bar-chart\"\n className={cn('flex w-full flex-col', className)}\n >\n <div className=\"flex items-baseline justify-between\">\n {title && <SectionTitle>{title}</SectionTitle>}\n <span className=\"tabular-nums\">\n {renderTotal ? (\n renderTotal(totalValue, focused === null)\n ) : (\n <span className=\"text-base font-bold text-gray tabular-nums\">\n {formatTotal(totalValue)}\n </span>\n )}\n </span>\n </div>\n\n <div className=\"flex min-h-5 items-baseline justify-between gap-4\">\n <SeriesLegend\n items={[\n ...series.map((entry) => ({\n id: entry.key,\n label: entry.label,\n color: entry.color,\n })),\n ...(lines ?? []).map((line) => ({\n id: line.key,\n label: line.label,\n color: line.color,\n marker: 'dashed-line' as const,\n })),\n ]}\n hiddenIds={hiddenSeries}\n onToggle={toggleSeries}\n className=\"gap-y-1\"\n />\n <span\n className={cn(\n 'text-xs text-gray-light transition-opacity duration-200',\n hoverLabel ? 'opacity-100' : 'opacity-0',\n )}\n >\n {trailingHoverLabel ?? ' '}\n </span>\n </div>\n\n <div\n ref={containerRef}\n className=\"relative mt-2 w-full\"\n style={{ height }}\n >\n <div\n ref={tooltipRef}\n className=\"pointer-events-none absolute z-10\"\n style={{\n left: tooltipPos.left,\n top: tooltipPos.top,\n opacity: tooltipActive ? 1 : 0,\n transition: reducedMotion\n ? 'opacity 140ms ease-out'\n : 'left 140ms ease-out, top 140ms ease-out, opacity 140ms ease-out',\n }}\n >\n {focusCategory !== null && (\n <ChartTooltipCard\n label={formatTooltipCategory(focusCategory)}\n rows={tooltipRows}\n />\n )}\n </div>\n {width > 0 && (\n <svg width={width} height={height}>\n <line\n x1={gutter}\n x2={gutter}\n y1={PADDING_TOP}\n y2={height - PADDING_BOTTOM}\n stroke=\"var(--neutral-a6)\"\n strokeWidth={1}\n />\n\n {yTicks.map((tick, index) => {\n const y = yScale(tick)\n const hideTickLabel =\n yAxisUnit !== undefined && index === yTicks.length - 1\n\n return (\n <g key={`y-tick-${tick}`}>\n {!hideTickLabel && (\n <line\n x1={gutter - 4}\n x2={gutter}\n y1={y}\n y2={y}\n stroke=\"var(--neutral-a8)\"\n strokeWidth={1}\n />\n )}\n {!hideTickLabel && (\n <text\n x={gutter - 7}\n y={y + 3}\n textAnchor=\"end\"\n fill=\"var(--neutral-a11)\"\n fontSize={10}\n >\n {formatYTick(tick)}\n </text>\n )}\n </g>\n )\n })}\n\n {yAxisUnit && (\n <text\n x={0}\n y={PADDING_TOP - 6}\n textAnchor=\"start\"\n fill=\"var(--neutral-a11)\"\n fontSize={10}\n fontWeight={600}\n >\n {yAxisUnit}\n </text>\n )}\n\n {highlightX !== null && (\n <line\n x1={highlightX}\n x2={highlightX}\n y1={PADDING_TOP}\n y2={height - PADDING_BOTTOM}\n stroke=\"var(--spark-a9)\"\n strokeWidth={1.5}\n strokeDasharray=\"5 4\"\n pointerEvents=\"none\"\n />\n )}\n\n <line\n x1={gutter}\n x2={plotRight}\n y1={yScale(0)}\n y2={yScale(0)}\n stroke=\"var(--neutral-a5)\"\n strokeWidth={1}\n />\n\n {rightYScale !== null && (\n <>\n <line\n x1={plotRight}\n x2={plotRight}\n y1={PADDING_TOP}\n y2={height - PADDING_BOTTOM}\n stroke=\"var(--neutral-a6)\"\n strokeWidth={1}\n />\n\n {rightTicks.map((tick, index) => {\n const y = rightYScale(tick)\n const hideTickLabel =\n yAxisRightUnit !== undefined &&\n index === rightTicks.length - 1\n\n return (\n <g key={`y-tick-right-${tick}`}>\n {!hideTickLabel && (\n <line\n x1={plotRight}\n x2={plotRight + 4}\n y1={y}\n y2={y}\n stroke=\"var(--neutral-a8)\"\n strokeWidth={1}\n />\n )}\n {!hideTickLabel && (\n <text\n x={plotRight + 7}\n y={y + 3}\n textAnchor=\"start\"\n fill=\"var(--neutral-a11)\"\n fontSize={10}\n >\n {formatYTickRight(tick)}\n </text>\n )}\n </g>\n )\n })}\n\n {yAxisRightUnit && (\n <text\n x={width}\n y={PADDING_TOP - 6}\n textAnchor=\"end\"\n fill=\"var(--neutral-a11)\"\n fontSize={10}\n fontWeight={600}\n >\n {yAxisRightUnit}\n </text>\n )}\n </>\n )}\n\n <Group>\n {focusCategory !== null && (\n <FocusBorder\n category={focusCategory}\n visible={hoveredCategory !== null}\n stackData={stackData}\n series={series}\n xScale={xScale}\n yScale={yScale}\n />\n )}\n {barStackLayer}\n\n {referenceLine && (\n <line\n x1={gutter}\n x2={width}\n y1={yScale(referenceLine.value)}\n y2={yScale(referenceLine.value)}\n stroke={referenceLine.color ?? 'var(--neutral-a11)'}\n strokeWidth={1.5}\n pointerEvents=\"none\"\n />\n )}\n\n {linePaths.map((path) => (\n <path\n key={`line-${path.key}`}\n d={path.d}\n fill=\"none\"\n stroke={path.color}\n strokeWidth={1.5}\n strokeDasharray={path.strokeDasharray}\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n pointerEvents=\"none\"\n />\n ))}\n </Group>\n\n <InteractionLayer\n xDomain={xDomain}\n activeCategories={stackCategorySet}\n xScale={xScale}\n height={height}\n onHoverChange={setHoveredCategory}\n />\n\n <CategoryTicks\n ticks={ticks}\n xScale={xScale}\n height={height}\n formatCategory={formatCategory}\n />\n </svg>\n )}\n </div>\n </div>\n )\n}\n"],"mappings":"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"}
@@ -22,7 +22,7 @@ const fixedPaddingClasses = {
22
22
  sm: "p-3",
23
23
  lg: "p-6"
24
24
  };
25
- function Box({ className, variant, color, radius = "2xl", padding = "md", render, ...props }) {
25
+ function Box({ className, variant, color, radius = "2xl", padding = "md", elevated, render, ...props }) {
26
26
  const interactive = render != null;
27
27
  const resolved = variant ?? "ambient";
28
28
  return (0, _base_ui_react_use_render.useRender)({
@@ -32,7 +32,8 @@ function Box({ className, variant, color, radius = "2xl", padding = "md", render
32
32
  "data-slot": "box",
33
33
  "data-variant": variant,
34
34
  "data-card-color": color === "accent" ? "accent" : void 0,
35
- className: (0, cnfast.cn)(boxVariants({ variant }), padding === "md" ? require_lib_container_chrome.containerPaddingAll[resolved] : fixedPaddingClasses[padding], require_lib_container_chrome.radiusClasses[radius], interactive && require_lib_container_chrome.containerInteractiveClasses(resolved), className)
35
+ "data-elevated": elevated ? "" : void 0,
36
+ className: (0, cnfast.cn)(boxVariants({ variant }), padding === "md" ? require_lib_container_chrome.containerPaddingAll[resolved] : fixedPaddingClasses[padding], require_lib_container_chrome.radiusClasses[radius], elevated && "bg-(--spark-elevated) [background-image:linear-gradient(var(--spark-card-bg,transparent),var(--spark-card-bg,transparent))] shadow-(--spark-card-shadow,var(--spark-shadow-1))", interactive && require_lib_container_chrome.containerInteractiveClasses(resolved, elevated), className)
36
37
  }, props)
37
38
  });
38
39
  }
@@ -1 +1 @@
1
- {"version":3,"file":"box.cjs","names":["containerChrome","containerPaddingAll","radiusClasses","containerInteractiveClasses"],"sources":["../../src/components/box.tsx"],"sourcesContent":["import { mergeProps } from '@base-ui/react/merge-props'\nimport { useRender } from '@base-ui/react/use-render'\nimport { cva } from 'class-variance-authority'\nimport type * as React from 'react'\nimport {\n containerChrome,\n containerInteractiveClasses,\n containerPaddingAll,\n radiusClasses,\n type ContainerRadius,\n} from '../lib/container-chrome'\nimport type { SparkCardColor, SparkCardVariant } from '../lib/theme-types'\nimport { cn } from '../utils/cn'\n\nconst boxVariants = cva('relative flex w-full flex-col', {\n variants: {\n variant: {\n ambient: containerChrome.ambient,\n soft: containerChrome.soft,\n surface: containerChrome.surface,\n outline: containerChrome.outline,\n ghost: containerChrome.ghost,\n solid: containerChrome.solid,\n },\n },\n defaultVariants: {\n variant: 'ambient',\n },\n})\n\ntype BoxPadding = 'none' | 'sm' | 'md' | 'lg'\n\nconst fixedPaddingClasses: Record<Exclude<BoxPadding, 'md'>, string> = {\n none: '',\n sm: 'p-3',\n lg: 'p-6',\n}\n\ninterface BoxProps extends useRender.ComponentProps<'div'> {\n /**\n * Same chrome recipe as `Card`, with none of its header/title/description/\n * footer slots — for wrapping arbitrary content instead. Unset → follows\n * the app-level `[data-card-variant]` knob (default soft-neutral).\n */\n variant?: SparkCardVariant\n /** Chrome palette. `neutral` (default) tracks the app neutral; `accent` tints with the brand accent. */\n color?: SparkCardColor\n /** Corner radius, as a named step. Unset → `2xl`. */\n radius?: ContainerRadius\n /** Padding on all sides. `md` (default) follows the variant's own inset (chromed variants pad, `ghost` sits flush); `none` strips it entirely for a clipped frame. */\n padding?: BoxPadding\n}\n\nfunction Box({\n className,\n variant,\n color,\n radius = '2xl',\n padding = 'md',\n render,\n ...props\n}: BoxProps) {\n const interactive = render != null\n const resolved = variant ?? 'ambient'\n return useRender({\n defaultTagName: 'div',\n render,\n props: mergeProps<'div'>(\n {\n 'data-slot': 'box',\n 'data-variant': variant,\n 'data-card-color': color === 'accent' ? 'accent' : undefined,\n className: cn(\n boxVariants({ variant }),\n padding === 'md'\n ? containerPaddingAll[resolved]\n : fixedPaddingClasses[padding],\n radiusClasses[radius],\n interactive && containerInteractiveClasses(resolved),\n className,\n ),\n } as React.ComponentProps<'div'>,\n props,\n ),\n })\n}\n\nexport { Box }\nexport type { BoxProps, BoxPadding }\n"],"mappings":";;;;;;;;AAcA,MAAM,eAAA,GAAA,yBAAA,KAAkB,iCAAiC;CACvD,UAAU,EACR,SAAS;EACP,SAASA,6BAAAA,gBAAgB;EACzB,MAAMA,6BAAAA,gBAAgB;EACtB,SAASA,6BAAAA,gBAAgB;EACzB,SAASA,6BAAAA,gBAAgB;EACzB,OAAOA,6BAAAA,gBAAgB;EACvB,OAAOA,6BAAAA,gBAAgB;CACzB,EACF;CACA,iBAAiB,EACf,SAAS,UACX;AACF,CAAC;AAID,MAAM,sBAAiE;CACrE,MAAM;CACN,IAAI;CACJ,IAAI;AACN;AAiBA,SAAS,IAAI,EACX,WACA,SACA,OACA,SAAS,OACT,UAAU,MACV,QACA,GAAG,SACQ;CACX,MAAM,cAAc,UAAU;CAC9B,MAAM,WAAW,WAAW;CAC5B,QAAA,GAAA,0BAAA,WAAiB;EACf,gBAAgB;EAChB;EACA,QAAA,GAAA,2BAAA,YACE;GACE,aAAa;GACb,gBAAgB;GAChB,mBAAmB,UAAU,WAAW,WAAW,KAAA;GACnD,YAAA,GAAA,OAAA,IACE,YAAY,EAAE,QAAQ,CAAC,GACvB,YAAY,OACRC,6BAAAA,oBAAoB,YACpB,oBAAoB,UACxBC,6BAAAA,cAAc,SACd,eAAeC,6BAAAA,4BAA4B,QAAQ,GACnD,SACF;EACF,GACA,KACF;CACF,CAAC;AACH"}
1
+ {"version":3,"file":"box.cjs","names":["containerChrome","containerPaddingAll","radiusClasses","containerInteractiveClasses"],"sources":["../../src/components/box.tsx"],"sourcesContent":["import { mergeProps } from '@base-ui/react/merge-props'\nimport { useRender } from '@base-ui/react/use-render'\nimport { cva } from 'class-variance-authority'\nimport type * as React from 'react'\nimport {\n containerChrome,\n containerElevated,\n containerInteractiveClasses,\n containerPaddingAll,\n radiusClasses,\n type ContainerRadius,\n} from '../lib/container-chrome'\nimport type { SparkCardColor, SparkCardVariant } from '../lib/theme-types'\nimport { cn } from '../utils/cn'\n\nconst boxVariants = cva('relative flex w-full flex-col', {\n variants: {\n variant: {\n ambient: containerChrome.ambient,\n soft: containerChrome.soft,\n surface: containerChrome.surface,\n outline: containerChrome.outline,\n ghost: containerChrome.ghost,\n solid: containerChrome.solid,\n },\n },\n defaultVariants: {\n variant: 'ambient',\n },\n})\n\ntype BoxPadding = 'none' | 'sm' | 'md' | 'lg'\n\nconst fixedPaddingClasses: Record<Exclude<BoxPadding, 'md'>, string> = {\n none: '',\n sm: 'p-3',\n lg: 'p-6',\n}\n\ninterface BoxProps extends useRender.ComponentProps<'div'> {\n /**\n * Same chrome recipe as `Card`, with none of its header/title/description/\n * footer slots — for wrapping arbitrary content instead. Unset → follows\n * the app-level `[data-card-variant]` knob (default soft-neutral).\n */\n variant?: SparkCardVariant\n /** Chrome palette. `neutral` (default) tracks the app neutral; `accent` tints with the brand accent. */\n color?: SparkCardColor\n /** Corner radius, as a named step. Unset → `2xl`. */\n radius?: ContainerRadius\n /** Padding on all sides. `md` (default) follows the variant's own inset (chromed variants pad, `ghost` sits flush); `none` strips it entirely for a clipped frame. */\n padding?: BoxPadding\n /**\n * Lift the box off an arbitrary backdrop (a photo, not the flat app canvas):\n * an opaque `--spark-elevated` fill plus a shadow, so no `variant`/`color`\n * combination — including a translucent one like `soft` — can bleed it through.\n */\n elevated?: boolean\n}\n\nfunction Box({\n className,\n variant,\n color,\n radius = '2xl',\n padding = 'md',\n elevated,\n render,\n ...props\n}: BoxProps) {\n const interactive = render != null\n const resolved = variant ?? 'ambient'\n return useRender({\n defaultTagName: 'div',\n render,\n props: mergeProps<'div'>(\n {\n 'data-slot': 'box',\n 'data-variant': variant,\n 'data-card-color': color === 'accent' ? 'accent' : undefined,\n 'data-elevated': elevated ? '' : undefined,\n className: cn(\n boxVariants({ variant }),\n padding === 'md'\n ? containerPaddingAll[resolved]\n : fixedPaddingClasses[padding],\n radiusClasses[radius],\n elevated && containerElevated,\n interactive && containerInteractiveClasses(resolved, elevated),\n className,\n ),\n } as React.ComponentProps<'div'>,\n props,\n ),\n })\n}\n\nexport { Box }\nexport type { BoxProps, BoxPadding }\n"],"mappings":";;;;;;;;AAeA,MAAM,eAAA,GAAA,yBAAA,KAAkB,iCAAiC;CACvD,UAAU,EACR,SAAS;EACP,SAASA,6BAAAA,gBAAgB;EACzB,MAAMA,6BAAAA,gBAAgB;EACtB,SAASA,6BAAAA,gBAAgB;EACzB,SAASA,6BAAAA,gBAAgB;EACzB,OAAOA,6BAAAA,gBAAgB;EACvB,OAAOA,6BAAAA,gBAAgB;CACzB,EACF;CACA,iBAAiB,EACf,SAAS,UACX;AACF,CAAC;AAID,MAAM,sBAAiE;CACrE,MAAM;CACN,IAAI;CACJ,IAAI;AACN;AAuBA,SAAS,IAAI,EACX,WACA,SACA,OACA,SAAS,OACT,UAAU,MACV,UACA,QACA,GAAG,SACQ;CACX,MAAM,cAAc,UAAU;CAC9B,MAAM,WAAW,WAAW;CAC5B,QAAA,GAAA,0BAAA,WAAiB;EACf,gBAAgB;EAChB;EACA,QAAA,GAAA,2BAAA,YACE;GACE,aAAa;GACb,gBAAgB;GAChB,mBAAmB,UAAU,WAAW,WAAW,KAAA;GACnD,iBAAiB,WAAW,KAAK,KAAA;GACjC,YAAA,GAAA,OAAA,IACE,YAAY,EAAE,QAAQ,CAAC,GACvB,YAAY,OACRC,6BAAAA,oBAAoB,YACpB,oBAAoB,UACxBC,6BAAAA,cAAc,SACd,YAAA,kLACA,eAAeC,6BAAAA,4BAA4B,UAAU,QAAQ,GAC7D,SACF;EACF,GACA,KACF;CACF,CAAC;AACH"}