@epilot/spark-ui 1.0.0-alpha.4 → 1.0.0-alpha.5

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 (183) hide show
  1. package/dist/accent-colors-Ch2J0EEY.js +13 -0
  2. package/dist/accent-colors-Ch2J0EEY.js.map +1 -0
  3. package/dist/accent-colors-CjHCf8fH.cjs +18 -0
  4. package/dist/accent-colors-CjHCf8fH.cjs.map +1 -0
  5. package/dist/components/accordion.cjs +1 -1
  6. package/dist/components/accordion.d.ts +1 -1
  7. package/dist/components/accordion.js +1 -1
  8. package/dist/components/attachment.d.cts +2 -2
  9. package/dist/components/attachment.d.ts +2 -2
  10. package/dist/components/badge.cjs +12 -7
  11. package/dist/components/badge.cjs.map +1 -1
  12. package/dist/components/badge.d.cts +5 -1
  13. package/dist/components/badge.d.ts +5 -1
  14. package/dist/components/badge.js +12 -7
  15. package/dist/components/badge.js.map +1 -1
  16. package/dist/components/bar-chart.cjs +12 -9
  17. package/dist/components/bar-chart.cjs.map +1 -1
  18. package/dist/components/bar-chart.js +12 -9
  19. package/dist/components/bar-chart.js.map +1 -1
  20. package/dist/components/battery-progress-row.cjs +10 -16
  21. package/dist/components/battery-progress-row.cjs.map +1 -1
  22. package/dist/components/battery-progress-row.d.cts +1 -1
  23. package/dist/components/battery-progress-row.d.ts +2 -2
  24. package/dist/components/battery-progress-row.js +10 -16
  25. package/dist/components/battery-progress-row.js.map +1 -1
  26. package/dist/components/bubble.d.cts +1 -1
  27. package/dist/components/bubble.d.ts +1 -1
  28. package/dist/components/button.cjs +5 -2
  29. package/dist/components/button.cjs.map +1 -1
  30. package/dist/components/button.d.cts +8 -7
  31. package/dist/components/button.d.ts +8 -7
  32. package/dist/components/button.js +5 -2
  33. package/dist/components/button.js.map +1 -1
  34. package/dist/components/card.d.cts +1 -1
  35. package/dist/components/card.d.ts +1 -1
  36. package/dist/components/chart.cjs +1 -1
  37. package/dist/components/chart.cjs.map +1 -1
  38. package/dist/components/chart.js +1 -1
  39. package/dist/components/chart.js.map +1 -1
  40. package/dist/components/checkbox.cjs +30 -23
  41. package/dist/components/checkbox.cjs.map +1 -1
  42. package/dist/components/checkbox.d.cts +5 -1
  43. package/dist/components/checkbox.d.ts +5 -1
  44. package/dist/components/checkbox.js +30 -23
  45. package/dist/components/checkbox.js.map +1 -1
  46. package/dist/components/circular-gauge.d.ts +1 -1
  47. package/dist/components/day-of-week-picker.cjs +2 -2
  48. package/dist/components/day-of-week-picker.cjs.map +1 -1
  49. package/dist/components/day-of-week-picker.js +2 -2
  50. package/dist/components/day-of-week-picker.js.map +1 -1
  51. package/dist/components/device-card.d.ts +1 -1
  52. package/dist/components/donut-chart.cjs +3 -3
  53. package/dist/components/donut-chart.cjs.map +1 -1
  54. package/dist/components/donut-chart.js +3 -3
  55. package/dist/components/donut-chart.js.map +1 -1
  56. package/dist/components/energy-bar-chart.d.ts +1 -1
  57. package/dist/components/energy-breakdown.cjs +1 -1
  58. package/dist/components/energy-breakdown.cjs.map +1 -1
  59. package/dist/components/energy-breakdown.js +1 -1
  60. package/dist/components/energy-breakdown.js.map +1 -1
  61. package/dist/components/feed-in-hero.d.ts +1 -1
  62. package/dist/components/field.cjs +1 -1
  63. package/dist/components/field.d.cts +1 -1
  64. package/dist/components/field.d.ts +1 -1
  65. package/dist/components/field.js +1 -1
  66. package/dist/components/info-block.d.cts +1 -1
  67. package/dist/components/info-block.d.ts +1 -1
  68. package/dist/components/input-group.cjs +1 -1
  69. package/dist/components/input-group.js +1 -1
  70. package/dist/components/input-otp.cjs +1 -1
  71. package/dist/components/input-otp.js +1 -1
  72. package/dist/components/input.cjs +1 -1
  73. package/dist/components/input.d.cts +1 -1
  74. package/dist/components/input.d.ts +1 -1
  75. package/dist/components/input.js +1 -1
  76. package/dist/components/line-chart.cjs +11 -9
  77. package/dist/components/line-chart.cjs.map +1 -1
  78. package/dist/components/line-chart.js +11 -9
  79. package/dist/components/line-chart.js.map +1 -1
  80. package/dist/components/metering-row.d.ts +1 -1
  81. package/dist/components/money-saved-block.cjs +1 -1
  82. package/dist/components/money-saved-block.cjs.map +1 -1
  83. package/dist/components/money-saved-block.js +1 -1
  84. package/dist/components/money-saved-block.js.map +1 -1
  85. package/dist/components/number-flow.d.ts +1 -1
  86. package/dist/components/power-history-chart.cjs +9 -7
  87. package/dist/components/power-history-chart.cjs.map +1 -1
  88. package/dist/components/power-history-chart.js +9 -7
  89. package/dist/components/power-history-chart.js.map +1 -1
  90. package/dist/components/power-history.cjs +1 -1
  91. package/dist/components/power-history.cjs.map +1 -1
  92. package/dist/components/power-history.js +1 -1
  93. package/dist/components/power-history.js.map +1 -1
  94. package/dist/components/power-network.cjs +36 -11
  95. package/dist/components/power-network.cjs.map +1 -1
  96. package/dist/components/power-network.js +36 -11
  97. package/dist/components/power-network.js.map +1 -1
  98. package/dist/components/progress.cjs +1 -1
  99. package/dist/components/progress.cjs.map +1 -1
  100. package/dist/components/progress.js +1 -1
  101. package/dist/components/progress.js.map +1 -1
  102. package/dist/components/radio-card-group.cjs +26 -1
  103. package/dist/components/radio-card-group.cjs.map +1 -1
  104. package/dist/components/radio-card-group.js +26 -1
  105. package/dist/components/radio-card-group.js.map +1 -1
  106. package/dist/components/radio.cjs +11 -4
  107. package/dist/components/radio.cjs.map +1 -1
  108. package/dist/components/radio.d.cts +15 -3
  109. package/dist/components/radio.d.ts +15 -3
  110. package/dist/components/radio.js +11 -4
  111. package/dist/components/radio.js.map +1 -1
  112. package/dist/components/sankey-chart.cjs +4 -4
  113. package/dist/components/sankey-chart.cjs.map +1 -1
  114. package/dist/components/sankey-chart.d.ts +1 -1
  115. package/dist/components/sankey-chart.js +4 -4
  116. package/dist/components/sankey-chart.js.map +1 -1
  117. package/dist/components/schedule-list.cjs +3 -3
  118. package/dist/components/schedule-list.cjs.map +1 -1
  119. package/dist/components/schedule-list.js +3 -3
  120. package/dist/components/schedule-list.js.map +1 -1
  121. package/dist/components/segmented-control.cjs +1 -1
  122. package/dist/components/segmented-control.cjs.map +1 -1
  123. package/dist/components/segmented-control.d.cts +1 -1
  124. package/dist/components/segmented-control.d.ts +1 -1
  125. package/dist/components/segmented-control.js +1 -1
  126. package/dist/components/segmented-control.js.map +1 -1
  127. package/dist/components/select.cjs +1 -1
  128. package/dist/components/select.d.cts +1 -1
  129. package/dist/components/select.d.ts +1 -1
  130. package/dist/components/select.js +1 -1
  131. package/dist/components/series-legend.cjs +1 -1
  132. package/dist/components/series-legend.cjs.map +1 -1
  133. package/dist/components/series-legend.js +1 -1
  134. package/dist/components/series-legend.js.map +1 -1
  135. package/dist/components/slider.cjs +6 -19
  136. package/dist/components/slider.cjs.map +1 -1
  137. package/dist/components/slider.d.cts +0 -13
  138. package/dist/components/slider.d.ts +0 -13
  139. package/dist/components/slider.js +6 -19
  140. package/dist/components/slider.js.map +1 -1
  141. package/dist/components/stepper.cjs +2 -2
  142. package/dist/components/stepper.cjs.map +1 -1
  143. package/dist/components/stepper.js +2 -2
  144. package/dist/components/stepper.js.map +1 -1
  145. package/dist/components/switch.cjs +8 -3
  146. package/dist/components/switch.cjs.map +1 -1
  147. package/dist/components/switch.d.cts +9 -4
  148. package/dist/components/switch.d.ts +9 -4
  149. package/dist/components/switch.js +8 -3
  150. package/dist/components/switch.js.map +1 -1
  151. package/dist/components/tabs.cjs +4 -4
  152. package/dist/components/tabs.cjs.map +1 -1
  153. package/dist/components/tabs.js +4 -4
  154. package/dist/components/tabs.js.map +1 -1
  155. package/dist/components/theme.cjs +1 -1
  156. package/dist/components/theme.d.cts +1 -1
  157. package/dist/components/theme.d.ts +1 -1
  158. package/dist/components/theme.js +1 -1
  159. package/dist/components/time-picker.cjs +1 -1
  160. package/dist/components/time-picker.cjs.map +1 -1
  161. package/dist/components/time-picker.js +1 -1
  162. package/dist/components/time-picker.js.map +1 -1
  163. package/dist/hooks/use-reduced-motion.cjs +22 -0
  164. package/dist/hooks/use-reduced-motion.cjs.map +1 -0
  165. package/dist/hooks/use-reduced-motion.d.cts +7 -0
  166. package/dist/hooks/use-reduced-motion.d.ts +7 -0
  167. package/dist/hooks/use-reduced-motion.js +20 -0
  168. package/dist/hooks/use-reduced-motion.js.map +1 -0
  169. package/dist/{input-box-variants-Dr1K7uYE.js → input-box-variants-DcajYXvo.js} +1 -1
  170. package/dist/{input-box-variants-Dr1K7uYE.js.map → input-box-variants-DcajYXvo.js.map} +1 -1
  171. package/dist/{input-box-variants-BMDdwvqg.cjs → input-box-variants-ZCtgs-1S.cjs} +1 -1
  172. package/dist/{input-box-variants-BMDdwvqg.cjs.map → input-box-variants-ZCtgs-1S.cjs.map} +1 -1
  173. package/dist/{number-flow-DSbucQ_K.d.ts → number-flow-D9zsxH0-.d.ts} +1 -1
  174. package/dist/styles/index.css +4 -2
  175. package/dist/styles/spark-default.css +78 -0
  176. package/dist/{theme-C19BbKfO.js → theme-8PDO9E0S.js} +1 -1
  177. package/dist/{theme-C19BbKfO.js.map → theme-8PDO9E0S.js.map} +1 -1
  178. package/dist/{theme-CfFWrMEF.cjs → theme-ClRJhexF.cjs} +1 -1
  179. package/dist/{theme-CfFWrMEF.cjs.map → theme-ClRJhexF.cjs.map} +1 -1
  180. package/dist/{theme-types-DoROIXpi.d.ts → theme-types-BDdoRxXa.d.ts} +2 -3
  181. package/dist/{theme-types-r20EJfEC.d.cts → theme-types-BwSJKdsB.d.cts} +2 -3
  182. package/dist/{tones-DyCkL71h.d.ts → tones-PXJGlSpe.d.ts} +1 -1
  183. package/package.json +1 -1
@@ -1,4 +1,5 @@
1
1
  "use client";
2
+ import { useReducedMotion } from "../hooks/use-reduced-motion.js";
2
3
  import { cn } from "../utils/cn.js";
3
4
  import { localeNumberFormat } from "../utils/format.js";
4
5
  import { buildYAxisScale, formatYAxisTick } from "../utils/chart-scale.js";
@@ -159,6 +160,7 @@ const LineChart = ({ series, width, height, margin = DEFAULT_MARGIN, curve: defa
159
160
  value: formatValue(d.value)
160
161
  }];
161
162
  }) : [];
163
+ const reducedMotion = useReducedMotion();
162
164
  const [tooltipRef, tooltipSize] = useMeasuredSize();
163
165
  const tooltipPos = clampTooltipPosition({
164
166
  anchorX: tooltipLeft ?? 0,
@@ -182,7 +184,7 @@ const LineChart = ({ series, width, height, margin = DEFAULT_MARGIN, curve: defa
182
184
  top: margin.top,
183
185
  children: [
184
186
  showGrid && yTicks.map((tick) => /* @__PURE__ */ jsx("line", {
185
- className: "stroke-slate-a4",
187
+ className: "stroke-gray-a4",
186
188
  strokeDasharray: "4,4",
187
189
  x1: 0,
188
190
  x2: innerWidth,
@@ -190,7 +192,7 @@ const LineChart = ({ series, width, height, margin = DEFAULT_MARGIN, curve: defa
190
192
  y2: yScale(tick)
191
193
  }, `grid-y-${tick}`)),
192
194
  /* @__PURE__ */ jsx("line", {
193
- className: "stroke-slate-a6",
195
+ className: "stroke-gray-a6",
194
196
  x1: 0,
195
197
  x2: innerWidth,
196
198
  y1: innerHeight,
@@ -221,7 +223,7 @@ const LineChart = ({ series, width, height, margin = DEFAULT_MARGIN, curve: defa
221
223
  }),
222
224
  xTicks.map((tick) => /* @__PURE__ */ jsx("text", {
223
225
  dy: "1em",
224
- fill: "var(--gray-a11)",
226
+ fill: "var(--neutral-a11)",
225
227
  fontSize: 10,
226
228
  textAnchor: "middle",
227
229
  x: xScale(tick),
@@ -229,7 +231,7 @@ const LineChart = ({ series, width, height, margin = DEFAULT_MARGIN, curve: defa
229
231
  children: formatDate(tick)
230
232
  }, `x-${tick.valueOf()}`)),
231
233
  yAxisUnit !== void 0 && /* @__PURE__ */ jsx("line", {
232
- stroke: "var(--gray-a6)",
234
+ stroke: "var(--neutral-a6)",
233
235
  strokeWidth: 1,
234
236
  x1: 0,
235
237
  x2: 0,
@@ -239,7 +241,7 @@ const LineChart = ({ series, width, height, margin = DEFAULT_MARGIN, curve: defa
239
241
  yTicks.map((tick) => {
240
242
  const y = yScale(tick);
241
243
  return /* @__PURE__ */ jsxs("g", { children: [yAxisUnit !== void 0 && /* @__PURE__ */ jsx("line", {
242
- stroke: "var(--gray-a8)",
244
+ stroke: "var(--neutral-a8)",
243
245
  strokeWidth: 1,
244
246
  x1: -4,
245
247
  x2: 0,
@@ -247,7 +249,7 @@ const LineChart = ({ series, width, height, margin = DEFAULT_MARGIN, curve: defa
247
249
  y2: y
248
250
  }), /* @__PURE__ */ jsx("text", {
249
251
  dy: "0.32em",
250
- fill: "var(--gray-a11)",
252
+ fill: "var(--neutral-a11)",
251
253
  fontSize: 10,
252
254
  textAnchor: "end",
253
255
  x: yAxisUnit !== void 0 ? -7 : -4,
@@ -256,7 +258,7 @@ const LineChart = ({ series, width, height, margin = DEFAULT_MARGIN, curve: defa
256
258
  })] }, `y-${tick}`);
257
259
  }),
258
260
  yAxisUnit !== void 0 && /* @__PURE__ */ jsx("text", {
259
- fill: "var(--gray-a11)",
261
+ fill: "var(--neutral-a11)",
260
262
  fontSize: 10,
261
263
  fontWeight: 600,
262
264
  textAnchor: "start",
@@ -286,7 +288,7 @@ const LineChart = ({ series, width, height, margin = DEFAULT_MARGIN, curve: defa
286
288
  y: 0
287
289
  }),
288
290
  tooltipOpen && tooltipData && /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx("line", {
289
- className: "stroke-slate-a6",
291
+ className: "stroke-gray-a6",
290
292
  pointerEvents: "none",
291
293
  strokeDasharray: "4,4",
292
294
  x1: xScale(tooltipData.date),
@@ -331,7 +333,7 @@ const LineChart = ({ series, width, height, margin = DEFAULT_MARGIN, curve: defa
331
333
  left: tooltipPos.left,
332
334
  top: tooltipPos.top,
333
335
  opacity: tooltipOpen && tooltipData ? 1 : 0,
334
- transition: "left 140ms ease-out, top 140ms ease-out, opacity 140ms ease-out"
336
+ transition: reducedMotion ? "opacity 140ms ease-out" : "left 140ms ease-out, top 140ms ease-out, opacity 140ms ease-out"
335
337
  },
336
338
  children: tooltipData && /* @__PURE__ */ jsx(ChartTooltipCard, {
337
339
  label: (formatTooltipDate ?? formatDate)(tooltipData.date),
@@ -1 +1 @@
1
- {"version":3,"file":"line-chart.js","names":[],"sources":["../../src/components/line-chart.tsx"],"sourcesContent":["import {\n curveLinear,\n curveMonotoneX,\n curveStep,\n curveStepAfter,\n curveStepBefore,\n} from '@visx/curve'\nimport { localPoint } from '@visx/event'\nimport { Group } from '@visx/group'\nimport { scaleLinear, scaleTime } from '@visx/scale'\nimport { LinePath } from '@visx/shape'\nimport { useTooltip } from '@visx/tooltip'\nimport { bisector, extent } from '@visx/vendor/d3-array'\nimport * as React from 'react'\nimport { useCallback, useMemo } from 'react'\nimport { buildYAxisScale, formatYAxisTick } 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'\n\nexport interface LineChartDatum {\n date: Date\n value: number\n}\n\nexport type LineChartCurve =\n | 'monotone'\n | 'step'\n | 'step-after'\n | 'step-before'\n | 'linear'\n\nexport interface LineChartSeries {\n id: string\n data: LineChartDatum[]\n /** Label shown in the hover tooltip. Defaults to `id`. */\n label?: React.ReactNode\n className?: string\n /** Curve interpolation type. Default: inherits from LineChartProps.curve */\n curve?: LineChartCurve\n /** Render as a dashed line */\n dashed?: boolean\n /** Custom dash pattern (e.g. \"8,4\" or \"4,2,1,2\"). Only applies when dashed is true. */\n dashPattern?: string\n}\n\nexport interface LineChartProps {\n series: LineChartSeries[]\n width: number\n height: number\n margin?: { top: number; right: number; bottom: number; left: number }\n /** Default curve for all series. Default: 'monotone' */\n curve?: LineChartCurve\n showGrid?: boolean\n showTooltip?: boolean\n className?: string\n xTickCount?: number\n yTickCount?: number\n /** Fixes the y-axis to an explicit `[min, max]`. Defaults to the data extent. */\n yDomain?: [number, number]\n /** Formats the x-axis tick labels. */\n formatDate?: (date: Date) => string\n /** Formats the tooltip title. Defaults to `formatDate`. */\n formatTooltipDate?: (date: Date) => string\n formatValue?: (value: number) => string\n /**\n * Unit shown once at the top of the y-axis (e.g. \"kW\"). When set, y-axis tick\n * labels render as plain numbers (matching BarChart / PowerHistoryChart)\n * instead of repeating `formatValue` on every tick. `formatValue` still feeds\n * the tooltip. Omit to keep the per-tick `formatValue` labels.\n */\n yAxisUnit?: string\n /**\n * Vertical reference markers positioned on the time axis (e.g. sunrise /\n * sunset). Each renders a dashed line across the plot with an optional label.\n */\n referenceLines?: Array<{ key: string; date: Date; label?: React.ReactNode }>\n /**\n * HTML content pinned to the top of the plot at a given time (e.g. an hourly\n * weather icon). Positioned by the same time scale as the series, so it lines\n * up with the curve below it.\n */\n topContent?: Array<{ key: string; date: Date; content: React.ReactNode }>\n}\n\nconst DEFAULT_MARGIN = { top: 16, right: 16, bottom: 40, left: 48 }\n\nconst CURVE_MAP = {\n monotone: curveMonotoneX,\n step: curveStep,\n 'step-after': curveStepAfter,\n 'step-before': curveStepBefore,\n linear: curveLinear,\n} as const\n\nconst resolveCurve = (type: LineChartCurve) => CURVE_MAP[type]\n\nconst dateBisector = bisector<LineChartDatum, Date>((d) => d.date)\nconst bisectDate = (data: LineChartDatum[], x: Date, lo?: number) =>\n dateBisector.left(data, x, lo)\n\n/** Whether `date` falls within a series' own x-range (data is sorted ascending). */\nfunction withinDomain(data: LineChartDatum[], date: Date): boolean {\n const first = data[0]\n const last = data[data.length - 1]\n if (!first || !last) return false\n const t = date.valueOf()\n return t >= first.date.valueOf() && t <= last.date.valueOf()\n}\n\n/**\n * y-domain padded 10% beyond the data extent. The baseline is pinned to 0 so\n * all-positive series render from the axis up; a series that dips below 0\n * (signed grid / battery power) extends the domain downward to keep the zero\n * crossing visible.\n */\nfunction computeYDomain(data: LineChartDatum[]): [number, number] {\n let min = 0\n let max = 0\n for (const d of data) {\n if (d.value < min) min = d.value\n if (d.value > max) max = d.value\n }\n if (min === max) return [min, min + 1]\n return [min * 1.1, max * 1.1]\n}\n\nfunction nearestDatum(\n data: LineChartDatum[],\n date: Date,\n): LineChartDatum | undefined {\n if (data.length === 0) return undefined\n const index = bisectDate(data, date, 1)\n const d0 = data[index - 1]\n const d1 = data[index]\n if (!d0) return d1\n if (!d1) return d0\n return date.valueOf() - d0.date.valueOf() > d1.date.valueOf() - date.valueOf()\n ? d1\n : d0\n}\n\nconst defaultFormatDate = (date: Date) =>\n date.toLocaleDateString(undefined, { month: 'short', day: 'numeric' })\n\nconst defaultValueFormat = localeNumberFormat()\nconst defaultFormatValue = (value: number) => defaultValueFormat.format(value)\n\nconst LINE_COLORS = [\n 'stroke-spark-9',\n 'stroke-green-9',\n 'stroke-blue-9',\n 'stroke-orange-9',\n 'stroke-red-9',\n]\n\nconst DOT_COLORS = [\n 'fill-spark-9',\n 'fill-green-9',\n 'fill-blue-9',\n 'fill-orange-9',\n 'fill-red-9',\n]\n\n// CSS-var colours matching LINE_COLORS, used for the tooltip legend dots.\nconst LEGEND_COLORS = [\n 'var(--spark-9)',\n 'var(--green-9)',\n 'var(--blue-9)',\n 'var(--orange-9)',\n 'var(--red-9)',\n]\n\nconst LineChart: React.FC<LineChartProps> = ({\n series,\n width,\n height,\n margin = DEFAULT_MARGIN,\n curve: defaultCurve = 'monotone',\n showGrid = true,\n showTooltip: enableTooltip = true,\n className,\n xTickCount = 5,\n yTickCount = 4,\n formatDate = defaultFormatDate,\n formatTooltipDate,\n formatValue = defaultFormatValue,\n yAxisUnit,\n yDomain,\n referenceLines,\n topContent,\n}) => {\n const {\n showTooltip,\n hideTooltip,\n tooltipData,\n tooltipLeft,\n tooltipTop,\n tooltipOpen,\n } = useTooltip<{ date: Date }>()\n\n const innerWidth = Math.max(0, width - margin.left - margin.right)\n const innerHeight = Math.max(0, height - margin.top - margin.bottom)\n\n const allData = useMemo(() => series.flatMap((s) => s.data), [series])\n\n const xScale = useMemo(\n () =>\n scaleTime({\n range: [0, innerWidth],\n domain: extent(allData, (d) => d.date) as [Date, Date],\n }),\n [allData, innerWidth],\n )\n\n // With a unit, the y-axis is generated by the shared scale util (nice ticks\n // + rounded bounds) so it matches BarChart / PowerHistoryChart exactly.\n const yAxisScale = useMemo(() => {\n if (yAxisUnit === undefined) return null\n let min = 0\n let max = 0\n for (const d of allData) {\n if (d.value < min) min = d.value\n if (d.value > max) max = d.value\n }\n return buildYAxisScale(min, max)\n }, [allData, yAxisUnit])\n\n const yScale = useMemo(\n () =>\n scaleLinear({\n range: [innerHeight, 0],\n domain:\n yDomain ??\n (yAxisScale\n ? [yAxisScale.min, yAxisScale.max]\n : computeYDomain(allData)),\n nice: !yDomain && !yAxisScale,\n }),\n [allData, innerHeight, yDomain, yAxisScale],\n )\n\n const xTicks = xScale.ticks(xTickCount)\n const yTicks = yAxisScale ? yAxisScale.ticks : yScale.ticks(yTickCount)\n\n const handleTooltip = useCallback(\n (\n event:\n | React.TouchEvent<SVGRectElement>\n | React.MouseEvent<SVGRectElement>,\n ) => {\n if (!enableTooltip) return\n\n const point = localPoint(event)\n if (!point) return\n\n const x0 = xScale.invert(point.x - margin.left)\n\n // Snap to the data point closest to the cursor across all series, so the\n // cursor line + tooltip line up with real values.\n let anchorDate: Date | null = null\n let bestDistance = Infinity\n for (const s of series) {\n const d = nearestDatum(s.data, x0)\n if (!d) continue\n const distance = Math.abs(d.date.valueOf() - x0.valueOf())\n if (distance < bestDistance) {\n bestDistance = distance\n anchorDate = d.date\n }\n }\n\n if (!anchorDate) return\n\n showTooltip({\n tooltipData: { date: anchorDate },\n tooltipLeft: xScale(anchorDate) + margin.left,\n tooltipTop: margin.top,\n })\n },\n [enableTooltip, margin, series, showTooltip, xScale],\n )\n\n const tooltipRows: ChartTooltipRow[] = tooltipData\n ? series.flatMap((s, i) => {\n const d = nearestDatum(s.data, tooltipData.date)\n if (!d || !withinDomain(s.data, tooltipData.date)) return []\n return [\n {\n key: s.id,\n label: s.label ?? s.id,\n color: LEGEND_COLORS[i % LEGEND_COLORS.length] as string,\n value: formatValue(d.value),\n },\n ]\n })\n : []\n\n const [tooltipRef, tooltipSize] = useMeasuredSize<HTMLDivElement>()\n const tooltipPos = clampTooltipPosition({\n anchorX: tooltipLeft ?? 0,\n anchorY: tooltipTop ?? margin.top,\n width,\n height,\n tipWidth: tooltipSize.width,\n tipHeight: tooltipSize.height,\n placement: 'beside',\n })\n\n if (width < 10 || height < 10) return null\n\n return (\n <div className={cn('relative', className)}>\n <svg className=\"block\" height={height} width={width}>\n <Group left={margin.left} top={margin.top}>\n {/* Grid lines */}\n {showGrid &&\n yTicks.map((tick) => (\n <line\n className=\"stroke-slate-a4\"\n key={`grid-y-${tick}`}\n strokeDasharray=\"4,4\"\n x1={0}\n x2={innerWidth}\n y1={yScale(tick)}\n y2={yScale(tick)}\n />\n ))}\n\n {/* X axis */}\n <line\n className=\"stroke-slate-a6\"\n x1={0}\n x2={innerWidth}\n y1={innerHeight}\n y2={innerHeight}\n />\n\n {/* Reference markers (e.g. sunrise / sunset) */}\n {referenceLines?.map((ref) => {\n const x = xScale(ref.date)\n if (!Number.isFinite(x)) return null\n // Sit the label beside the line, on whichever side keeps it in\n // frame: right of a left-half marker, left of a right-half one.\n const anchorEnd = x > innerWidth / 2\n return (\n <g key={ref.key} pointerEvents=\"none\">\n <line\n className=\"stroke-orange-8\"\n strokeDasharray=\"3,3\"\n x1={x}\n x2={x}\n y1={0}\n y2={innerHeight}\n />\n {ref.label != null && (\n <text\n className=\"fill-orange-11 text-[10px]\"\n dy=\"0.9em\"\n textAnchor={anchorEnd ? 'end' : 'start'}\n x={x + (anchorEnd ? -4 : 4)}\n y={0}\n >\n {ref.label}\n </text>\n )}\n </g>\n )\n })}\n\n {/* X axis labels */}\n {xTicks.map((tick) => (\n <text\n dy=\"1em\"\n fill=\"var(--gray-a11)\"\n fontSize={10}\n key={`x-${tick.valueOf()}`}\n textAnchor=\"middle\"\n x={xScale(tick)}\n y={innerHeight + 8}\n >\n {formatDate(tick)}\n </text>\n ))}\n\n {/* Y axis. With `yAxisUnit`, matches BarChart: a vertical axis line,\n short tick marks, plain numeric ticks, and the unit as a bold\n top-left header (top tick hidden). Without it, ticks repeat\n `formatValue` and no axis line/marks are drawn. */}\n {yAxisUnit !== undefined && (\n <line\n stroke=\"var(--gray-a6)\"\n strokeWidth={1}\n x1={0}\n x2={0}\n y1={0}\n y2={innerHeight}\n />\n )}\n {yTicks.map((tick) => {\n const y = yScale(tick)\n return (\n <g key={`y-${tick}`}>\n {yAxisUnit !== undefined && (\n <line\n stroke=\"var(--gray-a8)\"\n strokeWidth={1}\n x1={-4}\n x2={0}\n y1={y}\n y2={y}\n />\n )}\n <text\n dy=\"0.32em\"\n fill=\"var(--gray-a11)\"\n fontSize={10}\n textAnchor=\"end\"\n x={yAxisUnit !== undefined ? -7 : -4}\n y={y}\n >\n {yAxisUnit !== undefined\n ? formatYAxisTick(tick)\n : formatValue(tick)}\n </text>\n </g>\n )\n })}\n {yAxisUnit !== undefined && (\n <text\n fill=\"var(--gray-a11)\"\n fontSize={10}\n fontWeight={600}\n textAnchor=\"start\"\n x={-margin.left}\n y={-6}\n >\n {yAxisUnit}\n </text>\n )}\n\n {/* Lines */}\n {series.map((s, i) => (\n <LinePath\n className={cn(LINE_COLORS[i % LINE_COLORS.length], s.className)}\n curve={resolveCurve(s.curve ?? defaultCurve)}\n data={s.data}\n fill=\"none\"\n key={s.id}\n strokeDasharray={s.dashed ? (s.dashPattern ?? '6,4') : undefined}\n strokeWidth={2}\n x={(d) => xScale(d.date)}\n y={(d) => yScale(d.value)}\n />\n ))}\n\n {/* Tooltip hover target */}\n {enableTooltip && (\n <rect\n fill=\"transparent\"\n height={innerHeight}\n onMouseLeave={hideTooltip}\n onMouseMove={handleTooltip}\n onTouchEnd={hideTooltip}\n onTouchMove={handleTooltip}\n width={innerWidth}\n x={0}\n y={0}\n />\n )}\n\n {/* Cursor line + a dot per series */}\n {tooltipOpen && tooltipData && (\n <>\n <line\n className=\"stroke-slate-a6\"\n pointerEvents=\"none\"\n strokeDasharray=\"4,4\"\n x1={xScale(tooltipData.date)}\n x2={xScale(tooltipData.date)}\n y1={0}\n y2={innerHeight}\n />\n {series.map((s, i) => {\n const d = nearestDatum(s.data, tooltipData.date)\n if (!d || !withinDomain(s.data, tooltipData.date)) return null\n return (\n <circle\n key={s.id}\n className={cn(DOT_COLORS[i % DOT_COLORS.length])}\n cx={xScale(d.date)}\n cy={yScale(d.value)}\n pointerEvents=\"none\"\n r={4}\n stroke=\"white\"\n strokeWidth={2}\n />\n )\n })}\n </>\n )}\n </Group>\n </svg>\n\n {topContent && topContent.length > 0 && (\n <div className=\"pointer-events-none absolute inset-0\">\n {topContent.map((item) => {\n const x = xScale(item.date)\n if (!Number.isFinite(x)) return null\n return (\n <div\n key={item.key}\n className=\"absolute -translate-x-1/2\"\n style={{ left: margin.left + x, top: 0 }}\n >\n {item.content}\n </div>\n )\n })}\n </div>\n )}\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: tooltipOpen && tooltipData ? 1 : 0,\n transition:\n 'left 140ms ease-out, top 140ms ease-out, opacity 140ms ease-out',\n }}\n >\n {tooltipData && (\n <ChartTooltipCard\n label={(formatTooltipDate ?? formatDate)(tooltipData.date)}\n rows={tooltipRows}\n />\n )}\n </div>\n </div>\n )\n}\n\nexport { LineChart }\n"],"mappings":"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"}
1
+ {"version":3,"file":"line-chart.js","names":[],"sources":["../../src/components/line-chart.tsx"],"sourcesContent":["import {\n curveLinear,\n curveMonotoneX,\n curveStep,\n curveStepAfter,\n curveStepBefore,\n} from '@visx/curve'\nimport { localPoint } from '@visx/event'\nimport { Group } from '@visx/group'\nimport { scaleLinear, scaleTime } from '@visx/scale'\nimport { LinePath } from '@visx/shape'\nimport { useTooltip } from '@visx/tooltip'\nimport { bisector, extent } from '@visx/vendor/d3-array'\nimport * as React from 'react'\nimport { useCallback, useMemo } from 'react'\nimport { useReducedMotion } from '../hooks/use-reduced-motion'\nimport { buildYAxisScale, formatYAxisTick } 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'\n\nexport interface LineChartDatum {\n date: Date\n value: number\n}\n\nexport type LineChartCurve =\n | 'monotone'\n | 'step'\n | 'step-after'\n | 'step-before'\n | 'linear'\n\nexport interface LineChartSeries {\n id: string\n data: LineChartDatum[]\n /** Label shown in the hover tooltip. Defaults to `id`. */\n label?: React.ReactNode\n className?: string\n /** Curve interpolation type. Default: inherits from LineChartProps.curve */\n curve?: LineChartCurve\n /** Render as a dashed line */\n dashed?: boolean\n /** Custom dash pattern (e.g. \"8,4\" or \"4,2,1,2\"). Only applies when dashed is true. */\n dashPattern?: string\n}\n\nexport interface LineChartProps {\n series: LineChartSeries[]\n width: number\n height: number\n margin?: { top: number; right: number; bottom: number; left: number }\n /** Default curve for all series. Default: 'monotone' */\n curve?: LineChartCurve\n showGrid?: boolean\n showTooltip?: boolean\n className?: string\n xTickCount?: number\n yTickCount?: number\n /** Fixes the y-axis to an explicit `[min, max]`. Defaults to the data extent. */\n yDomain?: [number, number]\n /** Formats the x-axis tick labels. */\n formatDate?: (date: Date) => string\n /** Formats the tooltip title. Defaults to `formatDate`. */\n formatTooltipDate?: (date: Date) => string\n formatValue?: (value: number) => string\n /**\n * Unit shown once at the top of the y-axis (e.g. \"kW\"). When set, y-axis tick\n * labels render as plain numbers (matching BarChart / PowerHistoryChart)\n * instead of repeating `formatValue` on every tick. `formatValue` still feeds\n * the tooltip. Omit to keep the per-tick `formatValue` labels.\n */\n yAxisUnit?: string\n /**\n * Vertical reference markers positioned on the time axis (e.g. sunrise /\n * sunset). Each renders a dashed line across the plot with an optional label.\n */\n referenceLines?: Array<{ key: string; date: Date; label?: React.ReactNode }>\n /**\n * HTML content pinned to the top of the plot at a given time (e.g. an hourly\n * weather icon). Positioned by the same time scale as the series, so it lines\n * up with the curve below it.\n */\n topContent?: Array<{ key: string; date: Date; content: React.ReactNode }>\n}\n\nconst DEFAULT_MARGIN = { top: 16, right: 16, bottom: 40, left: 48 }\n\nconst CURVE_MAP = {\n monotone: curveMonotoneX,\n step: curveStep,\n 'step-after': curveStepAfter,\n 'step-before': curveStepBefore,\n linear: curveLinear,\n} as const\n\nconst resolveCurve = (type: LineChartCurve) => CURVE_MAP[type]\n\nconst dateBisector = bisector<LineChartDatum, Date>((d) => d.date)\nconst bisectDate = (data: LineChartDatum[], x: Date, lo?: number) =>\n dateBisector.left(data, x, lo)\n\n/** Whether `date` falls within a series' own x-range (data is sorted ascending). */\nfunction withinDomain(data: LineChartDatum[], date: Date): boolean {\n const first = data[0]\n const last = data[data.length - 1]\n if (!first || !last) return false\n const t = date.valueOf()\n return t >= first.date.valueOf() && t <= last.date.valueOf()\n}\n\n/**\n * y-domain padded 10% beyond the data extent. The baseline is pinned to 0 so\n * all-positive series render from the axis up; a series that dips below 0\n * (signed grid / battery power) extends the domain downward to keep the zero\n * crossing visible.\n */\nfunction computeYDomain(data: LineChartDatum[]): [number, number] {\n let min = 0\n let max = 0\n for (const d of data) {\n if (d.value < min) min = d.value\n if (d.value > max) max = d.value\n }\n if (min === max) return [min, min + 1]\n return [min * 1.1, max * 1.1]\n}\n\nfunction nearestDatum(\n data: LineChartDatum[],\n date: Date,\n): LineChartDatum | undefined {\n if (data.length === 0) return undefined\n const index = bisectDate(data, date, 1)\n const d0 = data[index - 1]\n const d1 = data[index]\n if (!d0) return d1\n if (!d1) return d0\n return date.valueOf() - d0.date.valueOf() > d1.date.valueOf() - date.valueOf()\n ? d1\n : d0\n}\n\nconst defaultFormatDate = (date: Date) =>\n date.toLocaleDateString(undefined, { month: 'short', day: 'numeric' })\n\nconst defaultValueFormat = localeNumberFormat()\nconst defaultFormatValue = (value: number) => defaultValueFormat.format(value)\n\nconst LINE_COLORS = [\n 'stroke-spark-9',\n 'stroke-green-9',\n 'stroke-blue-9',\n 'stroke-orange-9',\n 'stroke-red-9',\n]\n\nconst DOT_COLORS = [\n 'fill-spark-9',\n 'fill-green-9',\n 'fill-blue-9',\n 'fill-orange-9',\n 'fill-red-9',\n]\n\n// CSS-var colours matching LINE_COLORS, used for the tooltip legend dots.\nconst LEGEND_COLORS = [\n 'var(--spark-9)',\n 'var(--green-9)',\n 'var(--blue-9)',\n 'var(--orange-9)',\n 'var(--red-9)',\n]\n\nconst LineChart: React.FC<LineChartProps> = ({\n series,\n width,\n height,\n margin = DEFAULT_MARGIN,\n curve: defaultCurve = 'monotone',\n showGrid = true,\n showTooltip: enableTooltip = true,\n className,\n xTickCount = 5,\n yTickCount = 4,\n formatDate = defaultFormatDate,\n formatTooltipDate,\n formatValue = defaultFormatValue,\n yAxisUnit,\n yDomain,\n referenceLines,\n topContent,\n}) => {\n const {\n showTooltip,\n hideTooltip,\n tooltipData,\n tooltipLeft,\n tooltipTop,\n tooltipOpen,\n } = useTooltip<{ date: Date }>()\n\n const innerWidth = Math.max(0, width - margin.left - margin.right)\n const innerHeight = Math.max(0, height - margin.top - margin.bottom)\n\n const allData = useMemo(() => series.flatMap((s) => s.data), [series])\n\n const xScale = useMemo(\n () =>\n scaleTime({\n range: [0, innerWidth],\n domain: extent(allData, (d) => d.date) as [Date, Date],\n }),\n [allData, innerWidth],\n )\n\n // With a unit, the y-axis is generated by the shared scale util (nice ticks\n // + rounded bounds) so it matches BarChart / PowerHistoryChart exactly.\n const yAxisScale = useMemo(() => {\n if (yAxisUnit === undefined) return null\n let min = 0\n let max = 0\n for (const d of allData) {\n if (d.value < min) min = d.value\n if (d.value > max) max = d.value\n }\n return buildYAxisScale(min, max)\n }, [allData, yAxisUnit])\n\n const yScale = useMemo(\n () =>\n scaleLinear({\n range: [innerHeight, 0],\n domain:\n yDomain ??\n (yAxisScale\n ? [yAxisScale.min, yAxisScale.max]\n : computeYDomain(allData)),\n nice: !yDomain && !yAxisScale,\n }),\n [allData, innerHeight, yDomain, yAxisScale],\n )\n\n const xTicks = xScale.ticks(xTickCount)\n const yTicks = yAxisScale ? yAxisScale.ticks : yScale.ticks(yTickCount)\n\n const handleTooltip = useCallback(\n (\n event:\n | React.TouchEvent<SVGRectElement>\n | React.MouseEvent<SVGRectElement>,\n ) => {\n if (!enableTooltip) return\n\n const point = localPoint(event)\n if (!point) return\n\n const x0 = xScale.invert(point.x - margin.left)\n\n // Snap to the data point closest to the cursor across all series, so the\n // cursor line + tooltip line up with real values.\n let anchorDate: Date | null = null\n let bestDistance = Infinity\n for (const s of series) {\n const d = nearestDatum(s.data, x0)\n if (!d) continue\n const distance = Math.abs(d.date.valueOf() - x0.valueOf())\n if (distance < bestDistance) {\n bestDistance = distance\n anchorDate = d.date\n }\n }\n\n if (!anchorDate) return\n\n showTooltip({\n tooltipData: { date: anchorDate },\n tooltipLeft: xScale(anchorDate) + margin.left,\n tooltipTop: margin.top,\n })\n },\n [enableTooltip, margin, series, showTooltip, xScale],\n )\n\n const tooltipRows: ChartTooltipRow[] = tooltipData\n ? series.flatMap((s, i) => {\n const d = nearestDatum(s.data, tooltipData.date)\n if (!d || !withinDomain(s.data, tooltipData.date)) return []\n return [\n {\n key: s.id,\n label: s.label ?? s.id,\n color: LEGEND_COLORS[i % LEGEND_COLORS.length] as string,\n value: formatValue(d.value),\n },\n ]\n })\n : []\n\n const reducedMotion = useReducedMotion()\n const [tooltipRef, tooltipSize] = useMeasuredSize<HTMLDivElement>()\n const tooltipPos = clampTooltipPosition({\n anchorX: tooltipLeft ?? 0,\n anchorY: tooltipTop ?? margin.top,\n width,\n height,\n tipWidth: tooltipSize.width,\n tipHeight: tooltipSize.height,\n placement: 'beside',\n })\n\n if (width < 10 || height < 10) return null\n\n return (\n <div className={cn('relative', className)}>\n <svg className=\"block\" height={height} width={width}>\n <Group left={margin.left} top={margin.top}>\n {/* Grid lines */}\n {showGrid &&\n yTicks.map((tick) => (\n <line\n className=\"stroke-gray-a4\"\n key={`grid-y-${tick}`}\n strokeDasharray=\"4,4\"\n x1={0}\n x2={innerWidth}\n y1={yScale(tick)}\n y2={yScale(tick)}\n />\n ))}\n\n {/* X axis */}\n <line\n className=\"stroke-gray-a6\"\n x1={0}\n x2={innerWidth}\n y1={innerHeight}\n y2={innerHeight}\n />\n\n {/* Reference markers (e.g. sunrise / sunset) */}\n {referenceLines?.map((ref) => {\n const x = xScale(ref.date)\n if (!Number.isFinite(x)) return null\n // Sit the label beside the line, on whichever side keeps it in\n // frame: right of a left-half marker, left of a right-half one.\n const anchorEnd = x > innerWidth / 2\n return (\n <g key={ref.key} pointerEvents=\"none\">\n <line\n className=\"stroke-orange-8\"\n strokeDasharray=\"3,3\"\n x1={x}\n x2={x}\n y1={0}\n y2={innerHeight}\n />\n {ref.label != null && (\n <text\n className=\"fill-orange-11 text-[10px]\"\n dy=\"0.9em\"\n textAnchor={anchorEnd ? 'end' : 'start'}\n x={x + (anchorEnd ? -4 : 4)}\n y={0}\n >\n {ref.label}\n </text>\n )}\n </g>\n )\n })}\n\n {/* X axis labels */}\n {xTicks.map((tick) => (\n <text\n dy=\"1em\"\n fill=\"var(--neutral-a11)\"\n fontSize={10}\n key={`x-${tick.valueOf()}`}\n textAnchor=\"middle\"\n x={xScale(tick)}\n y={innerHeight + 8}\n >\n {formatDate(tick)}\n </text>\n ))}\n\n {/* Y axis. With `yAxisUnit`, matches BarChart: a vertical axis line,\n short tick marks, plain numeric ticks, and the unit as a bold\n top-left header (top tick hidden). Without it, ticks repeat\n `formatValue` and no axis line/marks are drawn. */}\n {yAxisUnit !== undefined && (\n <line\n stroke=\"var(--neutral-a6)\"\n strokeWidth={1}\n x1={0}\n x2={0}\n y1={0}\n y2={innerHeight}\n />\n )}\n {yTicks.map((tick) => {\n const y = yScale(tick)\n return (\n <g key={`y-${tick}`}>\n {yAxisUnit !== undefined && (\n <line\n stroke=\"var(--neutral-a8)\"\n strokeWidth={1}\n x1={-4}\n x2={0}\n y1={y}\n y2={y}\n />\n )}\n <text\n dy=\"0.32em\"\n fill=\"var(--neutral-a11)\"\n fontSize={10}\n textAnchor=\"end\"\n x={yAxisUnit !== undefined ? -7 : -4}\n y={y}\n >\n {yAxisUnit !== undefined\n ? formatYAxisTick(tick)\n : formatValue(tick)}\n </text>\n </g>\n )\n })}\n {yAxisUnit !== undefined && (\n <text\n fill=\"var(--neutral-a11)\"\n fontSize={10}\n fontWeight={600}\n textAnchor=\"start\"\n x={-margin.left}\n y={-6}\n >\n {yAxisUnit}\n </text>\n )}\n\n {/* Lines */}\n {series.map((s, i) => (\n <LinePath\n className={cn(LINE_COLORS[i % LINE_COLORS.length], s.className)}\n curve={resolveCurve(s.curve ?? defaultCurve)}\n data={s.data}\n fill=\"none\"\n key={s.id}\n strokeDasharray={s.dashed ? (s.dashPattern ?? '6,4') : undefined}\n strokeWidth={2}\n x={(d) => xScale(d.date)}\n y={(d) => yScale(d.value)}\n />\n ))}\n\n {/* Tooltip hover target */}\n {enableTooltip && (\n <rect\n fill=\"transparent\"\n height={innerHeight}\n onMouseLeave={hideTooltip}\n onMouseMove={handleTooltip}\n onTouchEnd={hideTooltip}\n onTouchMove={handleTooltip}\n width={innerWidth}\n x={0}\n y={0}\n />\n )}\n\n {/* Cursor line + a dot per series */}\n {tooltipOpen && tooltipData && (\n <>\n <line\n className=\"stroke-gray-a6\"\n pointerEvents=\"none\"\n strokeDasharray=\"4,4\"\n x1={xScale(tooltipData.date)}\n x2={xScale(tooltipData.date)}\n y1={0}\n y2={innerHeight}\n />\n {series.map((s, i) => {\n const d = nearestDatum(s.data, tooltipData.date)\n if (!d || !withinDomain(s.data, tooltipData.date)) return null\n return (\n <circle\n key={s.id}\n className={cn(DOT_COLORS[i % DOT_COLORS.length])}\n cx={xScale(d.date)}\n cy={yScale(d.value)}\n pointerEvents=\"none\"\n r={4}\n stroke=\"white\"\n strokeWidth={2}\n />\n )\n })}\n </>\n )}\n </Group>\n </svg>\n\n {topContent && topContent.length > 0 && (\n <div className=\"pointer-events-none absolute inset-0\">\n {topContent.map((item) => {\n const x = xScale(item.date)\n if (!Number.isFinite(x)) return null\n return (\n <div\n key={item.key}\n className=\"absolute -translate-x-1/2\"\n style={{ left: margin.left + x, top: 0 }}\n >\n {item.content}\n </div>\n )\n })}\n </div>\n )}\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: tooltipOpen && tooltipData ? 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 {tooltipData && (\n <ChartTooltipCard\n label={(formatTooltipDate ?? formatDate)(tooltipData.date)}\n rows={tooltipRows}\n />\n )}\n </div>\n </div>\n )\n}\n\nexport { LineChart }\n"],"mappings":"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"}
@@ -1,7 +1,7 @@
1
1
  "use client";
2
2
 
3
3
  import { MaterialSymbolIconName } from "../icons/material-symbol.js";
4
- import { t as Tone } from "../tones-DyCkL71h.js";
4
+ import { t as Tone } from "../tones-PXJGlSpe.js";
5
5
  import * as _$react_jsx_runtime0 from "react/jsx-runtime";
6
6
 
7
7
  //#region src/components/metering-row.d.ts
@@ -51,7 +51,7 @@ const MoneySavedGaugeContent = ({ autarkyProgress, autarkyLabel, autarkyCaption
51
51
  children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("path", {
52
52
  d: gaugeArcPath,
53
53
  fill: "none",
54
- stroke: "var(--gray-a5)",
54
+ stroke: "var(--neutral-a5)",
55
55
  strokeWidth: gaugeStrokeWidth,
56
56
  strokeLinecap: "round",
57
57
  pathLength: 1
@@ -1 +1 @@
1
- {"version":3,"file":"money-saved-block.cjs","names":["SectionTitle","StateValue","MaterialSymbol"],"sources":["../../src/components/money-saved-block.tsx"],"sourcesContent":["import { MaterialSymbol } from '../icons/material-symbol'\nimport { SectionTitle, StateValue } from './typography'\n\nconst MoneySavedContainer = ({\n children,\n ariaLabel = 'Money saved today',\n}: {\n children: React.ReactNode\n /** Override the accessible label for the container. Defaults to `\"Money saved today\"`. */\n ariaLabel?: string\n}) => {\n return (\n <div\n aria-label={ariaLabel}\n className=\"flex items-center justify-between gap-4\"\n >\n {children}\n </div>\n )\n}\n\nconst MoneySavedContent = ({ children }: { children: React.ReactNode }) => {\n return <div className=\"flex flex-col gap-1\">{children}</div>\n}\n\nconst MoneySavedTitle = ({ children }: { children: React.ReactNode }) => {\n return <SectionTitle>{children}</SectionTitle>\n}\n\nconst MoneySavedValue = ({ children }: { children: React.ReactNode }) => {\n return <StateValue>{children}</StateValue>\n}\n\nconst MoneySavedDelta = ({ children }: { children: React.ReactNode }) => {\n return (\n <span className=\"flex items-end gap-1 text-sm text-base-success-solid\">\n <MaterialSymbol className=\"rotate-180 text-[14px]\" name=\"swap_vert\" />\n <span className=\"tabular-nums\">{children}</span>\n </span>\n )\n}\n\nconst MoneySavedGaugeContainer = ({\n children,\n}: {\n children: React.ReactNode\n}) => {\n return (\n <div className=\"relative top-2 flex flex-col items-end gap-1\">\n {children}\n </div>\n )\n}\n\nconst MoneySavedGaugeContent = ({\n autarkyProgress,\n autarkyLabel,\n autarkyCaption = 'Autarky',\n gaugeWidth,\n gaugeHeight,\n gaugeArcPath,\n gaugeStrokeWidth,\n}: {\n autarkyProgress: number\n autarkyLabel: string\n /** Override the caption shown beneath the gauge. Defaults to `\"Autarky\"`. */\n autarkyCaption?: React.ReactNode\n gaugeWidth: number\n gaugeHeight: number\n gaugeArcPath: string\n gaugeStrokeWidth: number\n}) => {\n return (\n <>\n <svg\n className=\"h-[44px] w-[76px]\"\n viewBox={`0 0 ${gaugeWidth} ${gaugeHeight}`}\n aria-hidden=\"true\"\n >\n <path\n d={gaugeArcPath}\n fill=\"none\"\n stroke=\"var(--gray-a5)\"\n strokeWidth={gaugeStrokeWidth}\n strokeLinecap=\"round\"\n pathLength={1}\n />\n <path\n d={gaugeArcPath}\n fill=\"none\"\n stroke=\"var(--green-a9)\"\n strokeWidth={gaugeStrokeWidth}\n strokeLinecap=\"round\"\n pathLength={1}\n strokeDasharray={`${autarkyProgress} 1`}\n />\n </svg>\n <span className=\"absolute inset-0 flex items-center justify-center text-sm font-semibold text-gray\">\n {autarkyLabel}\n </span>\n <span className=\"mx-auto text-xs text-gray-light\">{autarkyCaption}</span>\n </>\n )\n}\n\nexport {\n MoneySavedContainer,\n MoneySavedContent,\n MoneySavedTitle,\n MoneySavedValue,\n MoneySavedDelta,\n MoneySavedGaugeContainer,\n MoneySavedGaugeContent,\n}\n"],"mappings":";;;;;;;AAGA,MAAM,uBAAuB,EAC3B,UACA,YAAY,0BAKR;AACJ,QACE,iBAAA,GAAA,kBAAA,KAAC,OAAD;EACE,cAAY;EACZ,WAAU;EAET;EACG,CAAA;;AAIV,MAAM,qBAAqB,EAAE,eAA8C;AACzE,QAAO,iBAAA,GAAA,kBAAA,KAAC,OAAD;EAAK,WAAU;EAAuB;EAAe,CAAA;;AAG9D,MAAM,mBAAmB,EAAE,eAA8C;AACvE,QAAO,iBAAA,GAAA,kBAAA,KAACA,8BAAAA,cAAD,EAAe,UAAwB,CAAA;;AAGhD,MAAM,mBAAmB,EAAE,eAA8C;AACvE,QAAO,iBAAA,GAAA,kBAAA,KAACC,8BAAAA,YAAD,EAAa,UAAsB,CAAA;;AAG5C,MAAM,mBAAmB,EAAE,eAA8C;AACvE,QACE,iBAAA,GAAA,kBAAA,MAAC,QAAD;EAAM,WAAU;YAAhB,CACE,iBAAA,GAAA,kBAAA,KAACC,8BAAAA,gBAAD;GAAgB,WAAU;GAAyB,MAAK;GAAc,CAAA,EACtE,iBAAA,GAAA,kBAAA,KAAC,QAAD;GAAM,WAAU;GAAgB;GAAgB,CAAA,CAC3C;;;AAIX,MAAM,4BAA4B,EAChC,eAGI;AACJ,QACE,iBAAA,GAAA,kBAAA,KAAC,OAAD;EAAK,WAAU;EACZ;EACG,CAAA;;AAIV,MAAM,0BAA0B,EAC9B,iBACA,cACA,iBAAiB,WACjB,YACA,aACA,cACA,uBAUI;AACJ,QACE,iBAAA,GAAA,kBAAA,MAAA,kBAAA,UAAA,EAAA,UAAA;EACE,iBAAA,GAAA,kBAAA,MAAC,OAAD;GACE,WAAU;GACV,SAAS,OAAO,WAAW,GAAG;GAC9B,eAAY;aAHd,CAKE,iBAAA,GAAA,kBAAA,KAAC,QAAD;IACE,GAAG;IACH,MAAK;IACL,QAAO;IACP,aAAa;IACb,eAAc;IACd,YAAY;IACZ,CAAA,EACF,iBAAA,GAAA,kBAAA,KAAC,QAAD;IACE,GAAG;IACH,MAAK;IACL,QAAO;IACP,aAAa;IACb,eAAc;IACd,YAAY;IACZ,iBAAiB,GAAG,gBAAgB;IACpC,CAAA,CACE;;EACN,iBAAA,GAAA,kBAAA,KAAC,QAAD;GAAM,WAAU;aACb;GACI,CAAA;EACP,iBAAA,GAAA,kBAAA,KAAC,QAAD;GAAM,WAAU;aAAmC;GAAsB,CAAA;EACxE,EAAA,CAAA"}
1
+ {"version":3,"file":"money-saved-block.cjs","names":["SectionTitle","StateValue","MaterialSymbol"],"sources":["../../src/components/money-saved-block.tsx"],"sourcesContent":["import { MaterialSymbol } from '../icons/material-symbol'\nimport { SectionTitle, StateValue } from './typography'\n\nconst MoneySavedContainer = ({\n children,\n ariaLabel = 'Money saved today',\n}: {\n children: React.ReactNode\n /** Override the accessible label for the container. Defaults to `\"Money saved today\"`. */\n ariaLabel?: string\n}) => {\n return (\n <div\n aria-label={ariaLabel}\n className=\"flex items-center justify-between gap-4\"\n >\n {children}\n </div>\n )\n}\n\nconst MoneySavedContent = ({ children }: { children: React.ReactNode }) => {\n return <div className=\"flex flex-col gap-1\">{children}</div>\n}\n\nconst MoneySavedTitle = ({ children }: { children: React.ReactNode }) => {\n return <SectionTitle>{children}</SectionTitle>\n}\n\nconst MoneySavedValue = ({ children }: { children: React.ReactNode }) => {\n return <StateValue>{children}</StateValue>\n}\n\nconst MoneySavedDelta = ({ children }: { children: React.ReactNode }) => {\n return (\n <span className=\"flex items-end gap-1 text-sm text-base-success-solid\">\n <MaterialSymbol className=\"rotate-180 text-[14px]\" name=\"swap_vert\" />\n <span className=\"tabular-nums\">{children}</span>\n </span>\n )\n}\n\nconst MoneySavedGaugeContainer = ({\n children,\n}: {\n children: React.ReactNode\n}) => {\n return (\n <div className=\"relative top-2 flex flex-col items-end gap-1\">\n {children}\n </div>\n )\n}\n\nconst MoneySavedGaugeContent = ({\n autarkyProgress,\n autarkyLabel,\n autarkyCaption = 'Autarky',\n gaugeWidth,\n gaugeHeight,\n gaugeArcPath,\n gaugeStrokeWidth,\n}: {\n autarkyProgress: number\n autarkyLabel: string\n /** Override the caption shown beneath the gauge. Defaults to `\"Autarky\"`. */\n autarkyCaption?: React.ReactNode\n gaugeWidth: number\n gaugeHeight: number\n gaugeArcPath: string\n gaugeStrokeWidth: number\n}) => {\n return (\n <>\n <svg\n className=\"h-[44px] w-[76px]\"\n viewBox={`0 0 ${gaugeWidth} ${gaugeHeight}`}\n aria-hidden=\"true\"\n >\n <path\n d={gaugeArcPath}\n fill=\"none\"\n stroke=\"var(--neutral-a5)\"\n strokeWidth={gaugeStrokeWidth}\n strokeLinecap=\"round\"\n pathLength={1}\n />\n <path\n d={gaugeArcPath}\n fill=\"none\"\n stroke=\"var(--green-a9)\"\n strokeWidth={gaugeStrokeWidth}\n strokeLinecap=\"round\"\n pathLength={1}\n strokeDasharray={`${autarkyProgress} 1`}\n />\n </svg>\n <span className=\"absolute inset-0 flex items-center justify-center text-sm font-semibold text-gray\">\n {autarkyLabel}\n </span>\n <span className=\"mx-auto text-xs text-gray-light\">{autarkyCaption}</span>\n </>\n )\n}\n\nexport {\n MoneySavedContainer,\n MoneySavedContent,\n MoneySavedTitle,\n MoneySavedValue,\n MoneySavedDelta,\n MoneySavedGaugeContainer,\n MoneySavedGaugeContent,\n}\n"],"mappings":";;;;;;;AAGA,MAAM,uBAAuB,EAC3B,UACA,YAAY,0BAKR;AACJ,QACE,iBAAA,GAAA,kBAAA,KAAC,OAAD;EACE,cAAY;EACZ,WAAU;EAET;EACG,CAAA;;AAIV,MAAM,qBAAqB,EAAE,eAA8C;AACzE,QAAO,iBAAA,GAAA,kBAAA,KAAC,OAAD;EAAK,WAAU;EAAuB;EAAe,CAAA;;AAG9D,MAAM,mBAAmB,EAAE,eAA8C;AACvE,QAAO,iBAAA,GAAA,kBAAA,KAACA,8BAAAA,cAAD,EAAe,UAAwB,CAAA;;AAGhD,MAAM,mBAAmB,EAAE,eAA8C;AACvE,QAAO,iBAAA,GAAA,kBAAA,KAACC,8BAAAA,YAAD,EAAa,UAAsB,CAAA;;AAG5C,MAAM,mBAAmB,EAAE,eAA8C;AACvE,QACE,iBAAA,GAAA,kBAAA,MAAC,QAAD;EAAM,WAAU;YAAhB,CACE,iBAAA,GAAA,kBAAA,KAACC,8BAAAA,gBAAD;GAAgB,WAAU;GAAyB,MAAK;GAAc,CAAA,EACtE,iBAAA,GAAA,kBAAA,KAAC,QAAD;GAAM,WAAU;GAAgB;GAAgB,CAAA,CAC3C;;;AAIX,MAAM,4BAA4B,EAChC,eAGI;AACJ,QACE,iBAAA,GAAA,kBAAA,KAAC,OAAD;EAAK,WAAU;EACZ;EACG,CAAA;;AAIV,MAAM,0BAA0B,EAC9B,iBACA,cACA,iBAAiB,WACjB,YACA,aACA,cACA,uBAUI;AACJ,QACE,iBAAA,GAAA,kBAAA,MAAA,kBAAA,UAAA,EAAA,UAAA;EACE,iBAAA,GAAA,kBAAA,MAAC,OAAD;GACE,WAAU;GACV,SAAS,OAAO,WAAW,GAAG;GAC9B,eAAY;aAHd,CAKE,iBAAA,GAAA,kBAAA,KAAC,QAAD;IACE,GAAG;IACH,MAAK;IACL,QAAO;IACP,aAAa;IACb,eAAc;IACd,YAAY;IACZ,CAAA,EACF,iBAAA,GAAA,kBAAA,KAAC,QAAD;IACE,GAAG;IACH,MAAK;IACL,QAAO;IACP,aAAa;IACb,eAAc;IACd,YAAY;IACZ,iBAAiB,GAAG,gBAAgB;IACpC,CAAA,CACE;;EACN,iBAAA,GAAA,kBAAA,KAAC,QAAD;GAAM,WAAU;aACb;GACI,CAAA;EACP,iBAAA,GAAA,kBAAA,KAAC,QAAD;GAAM,WAAU;aAAmC;GAAsB,CAAA;EACxE,EAAA,CAAA"}
@@ -49,7 +49,7 @@ const MoneySavedGaugeContent = ({ autarkyProgress, autarkyLabel, autarkyCaption
49
49
  children: [/* @__PURE__ */ jsx("path", {
50
50
  d: gaugeArcPath,
51
51
  fill: "none",
52
- stroke: "var(--gray-a5)",
52
+ stroke: "var(--neutral-a5)",
53
53
  strokeWidth: gaugeStrokeWidth,
54
54
  strokeLinecap: "round",
55
55
  pathLength: 1
@@ -1 +1 @@
1
- {"version":3,"file":"money-saved-block.js","names":[],"sources":["../../src/components/money-saved-block.tsx"],"sourcesContent":["import { MaterialSymbol } from '../icons/material-symbol'\nimport { SectionTitle, StateValue } from './typography'\n\nconst MoneySavedContainer = ({\n children,\n ariaLabel = 'Money saved today',\n}: {\n children: React.ReactNode\n /** Override the accessible label for the container. Defaults to `\"Money saved today\"`. */\n ariaLabel?: string\n}) => {\n return (\n <div\n aria-label={ariaLabel}\n className=\"flex items-center justify-between gap-4\"\n >\n {children}\n </div>\n )\n}\n\nconst MoneySavedContent = ({ children }: { children: React.ReactNode }) => {\n return <div className=\"flex flex-col gap-1\">{children}</div>\n}\n\nconst MoneySavedTitle = ({ children }: { children: React.ReactNode }) => {\n return <SectionTitle>{children}</SectionTitle>\n}\n\nconst MoneySavedValue = ({ children }: { children: React.ReactNode }) => {\n return <StateValue>{children}</StateValue>\n}\n\nconst MoneySavedDelta = ({ children }: { children: React.ReactNode }) => {\n return (\n <span className=\"flex items-end gap-1 text-sm text-base-success-solid\">\n <MaterialSymbol className=\"rotate-180 text-[14px]\" name=\"swap_vert\" />\n <span className=\"tabular-nums\">{children}</span>\n </span>\n )\n}\n\nconst MoneySavedGaugeContainer = ({\n children,\n}: {\n children: React.ReactNode\n}) => {\n return (\n <div className=\"relative top-2 flex flex-col items-end gap-1\">\n {children}\n </div>\n )\n}\n\nconst MoneySavedGaugeContent = ({\n autarkyProgress,\n autarkyLabel,\n autarkyCaption = 'Autarky',\n gaugeWidth,\n gaugeHeight,\n gaugeArcPath,\n gaugeStrokeWidth,\n}: {\n autarkyProgress: number\n autarkyLabel: string\n /** Override the caption shown beneath the gauge. Defaults to `\"Autarky\"`. */\n autarkyCaption?: React.ReactNode\n gaugeWidth: number\n gaugeHeight: number\n gaugeArcPath: string\n gaugeStrokeWidth: number\n}) => {\n return (\n <>\n <svg\n className=\"h-[44px] w-[76px]\"\n viewBox={`0 0 ${gaugeWidth} ${gaugeHeight}`}\n aria-hidden=\"true\"\n >\n <path\n d={gaugeArcPath}\n fill=\"none\"\n stroke=\"var(--gray-a5)\"\n strokeWidth={gaugeStrokeWidth}\n strokeLinecap=\"round\"\n pathLength={1}\n />\n <path\n d={gaugeArcPath}\n fill=\"none\"\n stroke=\"var(--green-a9)\"\n strokeWidth={gaugeStrokeWidth}\n strokeLinecap=\"round\"\n pathLength={1}\n strokeDasharray={`${autarkyProgress} 1`}\n />\n </svg>\n <span className=\"absolute inset-0 flex items-center justify-center text-sm font-semibold text-gray\">\n {autarkyLabel}\n </span>\n <span className=\"mx-auto text-xs text-gray-light\">{autarkyCaption}</span>\n </>\n )\n}\n\nexport {\n MoneySavedContainer,\n MoneySavedContent,\n MoneySavedTitle,\n MoneySavedValue,\n MoneySavedDelta,\n MoneySavedGaugeContainer,\n MoneySavedGaugeContent,\n}\n"],"mappings":";;;;;AAGA,MAAM,uBAAuB,EAC3B,UACA,YAAY,0BAKR;AACJ,QACE,oBAAC,OAAD;EACE,cAAY;EACZ,WAAU;EAET;EACG,CAAA;;AAIV,MAAM,qBAAqB,EAAE,eAA8C;AACzE,QAAO,oBAAC,OAAD;EAAK,WAAU;EAAuB;EAAe,CAAA;;AAG9D,MAAM,mBAAmB,EAAE,eAA8C;AACvE,QAAO,oBAAC,cAAD,EAAe,UAAwB,CAAA;;AAGhD,MAAM,mBAAmB,EAAE,eAA8C;AACvE,QAAO,oBAAC,YAAD,EAAa,UAAsB,CAAA;;AAG5C,MAAM,mBAAmB,EAAE,eAA8C;AACvE,QACE,qBAAC,QAAD;EAAM,WAAU;YAAhB,CACE,oBAAC,gBAAD;GAAgB,WAAU;GAAyB,MAAK;GAAc,CAAA,EACtE,oBAAC,QAAD;GAAM,WAAU;GAAgB;GAAgB,CAAA,CAC3C;;;AAIX,MAAM,4BAA4B,EAChC,eAGI;AACJ,QACE,oBAAC,OAAD;EAAK,WAAU;EACZ;EACG,CAAA;;AAIV,MAAM,0BAA0B,EAC9B,iBACA,cACA,iBAAiB,WACjB,YACA,aACA,cACA,uBAUI;AACJ,QACE,qBAAA,UAAA,EAAA,UAAA;EACE,qBAAC,OAAD;GACE,WAAU;GACV,SAAS,OAAO,WAAW,GAAG;GAC9B,eAAY;aAHd,CAKE,oBAAC,QAAD;IACE,GAAG;IACH,MAAK;IACL,QAAO;IACP,aAAa;IACb,eAAc;IACd,YAAY;IACZ,CAAA,EACF,oBAAC,QAAD;IACE,GAAG;IACH,MAAK;IACL,QAAO;IACP,aAAa;IACb,eAAc;IACd,YAAY;IACZ,iBAAiB,GAAG,gBAAgB;IACpC,CAAA,CACE;;EACN,oBAAC,QAAD;GAAM,WAAU;aACb;GACI,CAAA;EACP,oBAAC,QAAD;GAAM,WAAU;aAAmC;GAAsB,CAAA;EACxE,EAAA,CAAA"}
1
+ {"version":3,"file":"money-saved-block.js","names":[],"sources":["../../src/components/money-saved-block.tsx"],"sourcesContent":["import { MaterialSymbol } from '../icons/material-symbol'\nimport { SectionTitle, StateValue } from './typography'\n\nconst MoneySavedContainer = ({\n children,\n ariaLabel = 'Money saved today',\n}: {\n children: React.ReactNode\n /** Override the accessible label for the container. Defaults to `\"Money saved today\"`. */\n ariaLabel?: string\n}) => {\n return (\n <div\n aria-label={ariaLabel}\n className=\"flex items-center justify-between gap-4\"\n >\n {children}\n </div>\n )\n}\n\nconst MoneySavedContent = ({ children }: { children: React.ReactNode }) => {\n return <div className=\"flex flex-col gap-1\">{children}</div>\n}\n\nconst MoneySavedTitle = ({ children }: { children: React.ReactNode }) => {\n return <SectionTitle>{children}</SectionTitle>\n}\n\nconst MoneySavedValue = ({ children }: { children: React.ReactNode }) => {\n return <StateValue>{children}</StateValue>\n}\n\nconst MoneySavedDelta = ({ children }: { children: React.ReactNode }) => {\n return (\n <span className=\"flex items-end gap-1 text-sm text-base-success-solid\">\n <MaterialSymbol className=\"rotate-180 text-[14px]\" name=\"swap_vert\" />\n <span className=\"tabular-nums\">{children}</span>\n </span>\n )\n}\n\nconst MoneySavedGaugeContainer = ({\n children,\n}: {\n children: React.ReactNode\n}) => {\n return (\n <div className=\"relative top-2 flex flex-col items-end gap-1\">\n {children}\n </div>\n )\n}\n\nconst MoneySavedGaugeContent = ({\n autarkyProgress,\n autarkyLabel,\n autarkyCaption = 'Autarky',\n gaugeWidth,\n gaugeHeight,\n gaugeArcPath,\n gaugeStrokeWidth,\n}: {\n autarkyProgress: number\n autarkyLabel: string\n /** Override the caption shown beneath the gauge. Defaults to `\"Autarky\"`. */\n autarkyCaption?: React.ReactNode\n gaugeWidth: number\n gaugeHeight: number\n gaugeArcPath: string\n gaugeStrokeWidth: number\n}) => {\n return (\n <>\n <svg\n className=\"h-[44px] w-[76px]\"\n viewBox={`0 0 ${gaugeWidth} ${gaugeHeight}`}\n aria-hidden=\"true\"\n >\n <path\n d={gaugeArcPath}\n fill=\"none\"\n stroke=\"var(--neutral-a5)\"\n strokeWidth={gaugeStrokeWidth}\n strokeLinecap=\"round\"\n pathLength={1}\n />\n <path\n d={gaugeArcPath}\n fill=\"none\"\n stroke=\"var(--green-a9)\"\n strokeWidth={gaugeStrokeWidth}\n strokeLinecap=\"round\"\n pathLength={1}\n strokeDasharray={`${autarkyProgress} 1`}\n />\n </svg>\n <span className=\"absolute inset-0 flex items-center justify-center text-sm font-semibold text-gray\">\n {autarkyLabel}\n </span>\n <span className=\"mx-auto text-xs text-gray-light\">{autarkyCaption}</span>\n </>\n )\n}\n\nexport {\n MoneySavedContainer,\n MoneySavedContent,\n MoneySavedTitle,\n MoneySavedValue,\n MoneySavedDelta,\n MoneySavedGaugeContainer,\n MoneySavedGaugeContent,\n}\n"],"mappings":";;;;;AAGA,MAAM,uBAAuB,EAC3B,UACA,YAAY,0BAKR;AACJ,QACE,oBAAC,OAAD;EACE,cAAY;EACZ,WAAU;EAET;EACG,CAAA;;AAIV,MAAM,qBAAqB,EAAE,eAA8C;AACzE,QAAO,oBAAC,OAAD;EAAK,WAAU;EAAuB;EAAe,CAAA;;AAG9D,MAAM,mBAAmB,EAAE,eAA8C;AACvE,QAAO,oBAAC,cAAD,EAAe,UAAwB,CAAA;;AAGhD,MAAM,mBAAmB,EAAE,eAA8C;AACvE,QAAO,oBAAC,YAAD,EAAa,UAAsB,CAAA;;AAG5C,MAAM,mBAAmB,EAAE,eAA8C;AACvE,QACE,qBAAC,QAAD;EAAM,WAAU;YAAhB,CACE,oBAAC,gBAAD;GAAgB,WAAU;GAAyB,MAAK;GAAc,CAAA,EACtE,oBAAC,QAAD;GAAM,WAAU;GAAgB;GAAgB,CAAA,CAC3C;;;AAIX,MAAM,4BAA4B,EAChC,eAGI;AACJ,QACE,oBAAC,OAAD;EAAK,WAAU;EACZ;EACG,CAAA;;AAIV,MAAM,0BAA0B,EAC9B,iBACA,cACA,iBAAiB,WACjB,YACA,aACA,cACA,uBAUI;AACJ,QACE,qBAAA,UAAA,EAAA,UAAA;EACE,qBAAC,OAAD;GACE,WAAU;GACV,SAAS,OAAO,WAAW,GAAG;GAC9B,eAAY;aAHd,CAKE,oBAAC,QAAD;IACE,GAAG;IACH,MAAK;IACL,QAAO;IACP,aAAa;IACb,eAAc;IACd,YAAY;IACZ,CAAA,EACF,oBAAC,QAAD;IACE,GAAG;IACH,MAAK;IACL,QAAO;IACP,aAAa;IACb,eAAc;IACd,YAAY;IACZ,iBAAiB,GAAG,gBAAgB;IACpC,CAAA,CACE;;EACN,oBAAC,QAAD;GAAM,WAAU;aACb;GACI,CAAA;EACP,oBAAC,QAAD;GAAM,WAAU;aAAmC;GAAsB,CAAA;EACxE,EAAA,CAAA"}
@@ -1,4 +1,4 @@
1
1
  "use client";
2
2
 
3
- import { n as NumberFlow, r as NumberFlowProps, t as Format } from "../number-flow-DSbucQ_K.js";
3
+ import { n as NumberFlow, r as NumberFlowProps, t as Format } from "../number-flow-D9zsxH0-.js";
4
4
  export { Format, NumberFlowProps, NumberFlow as default };
@@ -1,6 +1,7 @@
1
1
  "use client";
2
2
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
3
  const require_chunk = require("../chunk-aJGBMT86.cjs");
4
+ const require_hooks_use_reduced_motion = require("../hooks/use-reduced-motion.cjs");
4
5
  require("../utils/chars.cjs");
5
6
  const require_utils_format = require("../utils/format.cjs");
6
7
  const require_utils_chart_scale = require("../utils/chart-scale.cjs");
@@ -33,7 +34,7 @@ const SERIES_COLORS = {
33
34
  solar: "var(--orange-a9)",
34
35
  grid: "var(--blue-9)",
35
36
  battery: "var(--green-a9)",
36
- consumption: "var(--gray-12)"
37
+ consumption: "var(--neutral-12)"
37
38
  };
38
39
  const PADDING_TOP = 20;
39
40
  const PADDING_BOTTOM = 28;
@@ -52,6 +53,7 @@ const tBisector = (0, _visx_vendor_d3_array.bisector)((d) => d.t);
52
53
  function PowerHistoryChart({ data, unit, formatX, formatTooltipX, formatValue, labels, omitSeries, highlightAt, title, className, height = DEFAULT_HEIGHT }) {
53
54
  const fmtTooltipX = formatTooltipX ?? formatX;
54
55
  const containerRef = (0, react.useRef)(null);
56
+ const reducedMotion = require_hooks_use_reduced_motion.useReducedMotion();
55
57
  const [width, setWidth] = (0, react.useState)(0);
56
58
  const [hiddenSeries, setHiddenSeries] = (0, react.useState)(() => /* @__PURE__ */ new Set());
57
59
  const omitted = (0, react.useMemo)(() => new Set(omitSeries), [omitSeries]);
@@ -206,13 +208,13 @@ function PowerHistoryChart({ data, unit, formatX, formatTooltipX, formatValue, l
206
208
  x2: plotRight,
207
209
  y1: y,
208
210
  y2: y,
209
- stroke: "var(--gray-a4)",
211
+ stroke: "var(--neutral-a4)",
210
212
  strokeWidth: 1
211
213
  }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("text", {
212
214
  x: Y_AXIS_GUTTER - 7,
213
215
  y: y + 3,
214
216
  textAnchor: "end",
215
- fill: "var(--gray-a11)",
217
+ fill: "var(--neutral-a11)",
216
218
  fontSize: 10,
217
219
  children: require_utils_chart_scale.formatYAxisTick(tick)
218
220
  })] }, `y-tick-${tick}`);
@@ -249,7 +251,7 @@ function PowerHistoryChart({ data, unit, formatX, formatTooltipX, formatValue, l
249
251
  x2: plotRight,
250
252
  y1: yScale(0),
251
253
  y2: yScale(0),
252
- stroke: "var(--slate-a6)",
254
+ stroke: "var(--neutral-a6)",
253
255
  strokeWidth: 1
254
256
  }),
255
257
  showHighlight && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("line", {
@@ -266,7 +268,7 @@ function PowerHistoryChart({ data, unit, formatX, formatTooltipX, formatValue, l
266
268
  x: xScale(tick),
267
269
  y: height - PADDING_BOTTOM + 16,
268
270
  textAnchor: "middle",
269
- fill: "var(--gray-a11)",
271
+ fill: "var(--neutral-a11)",
270
272
  fontSize: 10,
271
273
  children: formatX(tick)
272
274
  }, `x-tick-${tick}`)),
@@ -276,7 +278,7 @@ function PowerHistoryChart({ data, unit, formatX, formatTooltipX, formatValue, l
276
278
  x2: xScale(tooltipData.t),
277
279
  y1: PADDING_TOP,
278
280
  y2: height - PADDING_BOTTOM,
279
- stroke: "var(--slate-a6)",
281
+ stroke: "var(--neutral-a6)",
280
282
  strokeDasharray: "4 4",
281
283
  pointerEvents: "none"
282
284
  }),
@@ -318,7 +320,7 @@ function PowerHistoryChart({ data, unit, formatX, formatTooltipX, formatValue, l
318
320
  left: tooltipPos.left,
319
321
  top: tooltipPos.top,
320
322
  opacity: tooltipOpen && tooltipData ? 1 : 0,
321
- transition: "left 140ms ease-out, top 140ms ease-out, opacity 140ms ease-out"
323
+ transition: reducedMotion ? "opacity 140ms ease-out" : "left 140ms ease-out, top 140ms ease-out, opacity 140ms ease-out"
322
324
  },
323
325
  children: tooltipData && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_components_chart.ChartTooltipCard, {
324
326
  label: fmtTooltipX(tooltipData.t),
@@ -1 +1 @@
1
- {"version":3,"file":"power-history-chart.cjs","names":["valueFormat","buildYAxisScale","useMeasuredSize","clampTooltipPosition","SectionTitle","SeriesLegend","formatYAxisTick","Area","curveMonotoneX","LinePath","ChartTooltipCard"],"sources":["../../src/components/power-history-chart.tsx"],"sourcesContent":["import { curveMonotoneX } from '@visx/curve'\nimport { localPoint } from '@visx/event'\nimport { scaleLinear } from '@visx/scale'\nimport { Area, LinePath } from '@visx/shape'\nimport { useTooltip } from '@visx/tooltip'\nimport { bisector } from '@visx/vendor/d3-array'\nimport * as React from 'react'\nimport { useCallback, useEffect, useMemo, useRef, useState } from 'react'\nimport { NARROW_NBSP } from '../utils/chars'\nimport { buildYAxisScale, formatYAxisTick } from '../utils/chart-scale'\nimport { cn } from '../utils/cn'\nimport { twoDecimalFormat as valueFormat } from '../utils/format'\nimport {\n ChartTooltipCard,\n type ChartTooltipRow,\n clampTooltipPosition,\n useMeasuredSize,\n} from './chart'\nimport { SeriesLegend, type SeriesLegendItem } from './series-legend'\nimport { SectionTitle } from './typography'\n\nexport interface PowerHistoryPoint {\n /** Epoch milliseconds. */\n t: number\n solar: number\n /** Signed: positive = import, negative = feed-in. */\n grid: number\n /** Signed: positive = discharge, negative = charge. */\n battery: number\n consumption: number\n}\n\nexport interface PowerHistoryChartProps {\n data: PowerHistoryPoint[]\n /** Axis/tooltip unit, e.g. \"kW\". */\n unit: string\n formatX: (t: number) => string\n /** Tooltip time formatter. Defaults to `formatX`; use to keep the tooltip's\n * full clock time when the axis ticks are compact (hour-only). */\n formatTooltipX?: (t: number) => string\n formatValue?: (value: number) => string\n labels: {\n solar: string\n grid: string\n battery: string\n consumption: string\n }\n /** Series to drop entirely (no legend entry, area, or tooltip row). */\n omitSeries?: readonly PowerHistorySeriesKey[]\n /** Epoch ms to mark with the current-time dashed line (omit to hide). */\n highlightAt?: number\n title?: string\n className?: string\n height?: number\n}\n\nconst AREA_KEYS = ['solar', 'grid', 'battery'] as const\n\n// All toggleable series, in legend order. The areas (solar/grid/battery) plus\n// the consumption overlay line.\nconst SERIES_KEYS = ['solar', 'grid', 'battery', 'consumption'] as const\nexport type PowerHistorySeriesKey = (typeof SERIES_KEYS)[number]\ntype SeriesKey = PowerHistorySeriesKey\n\nconst SERIES_COLORS = {\n solar: 'var(--orange-a9)',\n grid: 'var(--blue-9)',\n battery: 'var(--green-a9)',\n consumption: 'var(--gray-12)',\n} as const\n\nconst PADDING_TOP = 20\nconst PADDING_BOTTOM = 28\nconst PADDING_RIGHT = 8\nconst Y_AXIS_GUTTER = 34\nconst X_TICK_COUNT = 6\nconst DEFAULT_HEIGHT = 260\n\nconst tBisector = bisector<PowerHistoryPoint, number>((d) => d.t)\n\n/**\n * Diverging \"power sources\" area chart over a continuous time axis: solar\n * (orange), grid (blue) and battery (green) areas around a zero baseline, with\n * consumption overlaid as a line. Negative values (grid feed-in, battery\n * charging) dip below zero. For instantaneous power (day view). A legend at the\n * top toggles each series on/off; the y-axis rescales to the visible ones. visx.\n */\nexport function PowerHistoryChart({\n data,\n unit,\n formatX,\n formatTooltipX,\n formatValue,\n labels,\n omitSeries,\n highlightAt,\n title,\n className,\n height = DEFAULT_HEIGHT,\n}: PowerHistoryChartProps) {\n const fmtTooltipX = formatTooltipX ?? formatX\n const containerRef = useRef<HTMLDivElement>(null)\n const [width, setWidth] = useState(0)\n const [hiddenSeries, setHiddenSeries] = useState<ReadonlySet<string>>(\n () => new Set(),\n )\n const omitted = useMemo(() => new Set<SeriesKey>(omitSeries), [omitSeries])\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 const isHidden = useCallback(\n (key: SeriesKey) => omitted.has(key) || hiddenSeries.has(key),\n [hiddenSeries, omitted],\n )\n\n const {\n showTooltip,\n hideTooltip,\n tooltipData,\n tooltipLeft,\n tooltipTop,\n tooltipOpen,\n } = useTooltip<PowerHistoryPoint>()\n\n useEffect(() => {\n const element = containerRef.current\n if (!element) return\n\n const resizeObserver = new ResizeObserver((entries) => {\n const entry = entries[0]\n if (!entry) return\n setWidth(entry.contentRect.width)\n })\n\n resizeObserver.observe(element)\n return () => resizeObserver.disconnect()\n }, [])\n\n const fmtValue = (value: number) =>\n formatValue\n ? formatValue(value)\n : `${valueFormat.format(value)}${NARROW_NBSP}${unit}`\n\n const tMin = data.length ? (data[0]?.t ?? 0) : 0\n const tMax = data.length ? (data[data.length - 1]?.t ?? 0) : 0\n\n const { yMin, yMax } = useMemo(() => {\n let min = 0\n let max = 0\n for (const d of data) {\n if (!isHidden('solar')) max = Math.max(max, d.solar)\n if (!isHidden('consumption')) max = Math.max(max, d.consumption)\n if (!isHidden('grid')) {\n max = Math.max(max, d.grid)\n min = Math.min(min, d.grid)\n }\n if (!isHidden('battery')) {\n max = Math.max(max, d.battery)\n min = Math.min(min, d.battery)\n }\n }\n return { yMin: min, yMax: max }\n }, [data, isHidden])\n\n const {\n ticks: yTicks,\n min: lo,\n max: hi,\n } = useMemo(() => buildYAxisScale(yMin, yMax), [yMin, yMax])\n\n const plotRight = Math.max(Y_AXIS_GUTTER, width - PADDING_RIGHT)\n\n const xScale = useMemo(\n () =>\n scaleLinear<number>({\n domain: [tMin, tMax === tMin ? tMin + 1 : tMax],\n range: [Y_AXIS_GUTTER, plotRight],\n }),\n [tMin, tMax, plotRight],\n )\n\n const yScale = useMemo(\n () =>\n scaleLinear<number>({\n domain: [lo, hi === lo ? lo + 1 : hi],\n range: [height - PADDING_BOTTOM, PADDING_TOP],\n }),\n [lo, hi, height],\n )\n\n const xTicks = useMemo(() => {\n if (tMax <= tMin) return [tMin]\n return Array.from(\n { length: X_TICK_COUNT },\n (_, i) => tMin + (i / (X_TICK_COUNT - 1)) * (tMax - tMin),\n )\n }, [tMin, tMax])\n\n const handleTooltip = useCallback(\n (\n event:\n | React.TouchEvent<SVGRectElement>\n | React.MouseEvent<SVGRectElement>,\n ) => {\n const point = localPoint(event)\n if (!point || data.length === 0) return\n\n const xMs = xScale.invert(point.x)\n const index = tBisector.left(data, xMs, 1)\n const d0 = data[index - 1]\n const d1 = data[index]\n if (!d0) return\n\n const d = d1 && xMs - d0.t > d1.t - xMs ? d1 : d0\n showTooltip({\n tooltipData: d,\n tooltipLeft: xScale(d.t),\n tooltipTop: PADDING_TOP,\n })\n },\n [data, showTooltip, xScale],\n )\n\n const legendItems: SeriesLegendItem[] = SERIES_KEYS.filter(\n (key) => !omitted.has(key),\n ).map((key) => ({\n id: key,\n label: labels[key],\n color: SERIES_COLORS[key],\n }))\n\n const tooltipRows: ChartTooltipRow[] = tooltipData\n ? SERIES_KEYS.filter((key) => !isHidden(key)).map((key) => ({\n key,\n label: labels[key],\n color: SERIES_COLORS[key],\n value: fmtValue(tooltipData[key]),\n }))\n : []\n\n const showHighlight =\n highlightAt !== undefined && highlightAt >= tMin && highlightAt <= tMax\n\n const [tooltipRef, tooltipSize] = useMeasuredSize<HTMLDivElement>()\n const tooltipPos = clampTooltipPosition({\n anchorX: tooltipLeft ?? 0,\n anchorY: tooltipTop ?? PADDING_TOP,\n width,\n height,\n tipWidth: tooltipSize.width,\n tipHeight: tooltipSize.height,\n placement: 'beside',\n })\n\n return (\n <div className={cn('flex w-full flex-col gap-2', className)}>\n {title && <SectionTitle>{title}</SectionTitle>}\n <SeriesLegend\n items={legendItems}\n hiddenIds={hiddenSeries}\n onToggle={toggleSeries}\n />\n <span className=\"px-1 text-xs text-gray-light\">{unit}</span>\n <div ref={containerRef} className=\"relative w-full\" style={{ height }}>\n {width > 0 && (\n <svg width={width} height={height}>\n <defs>\n {AREA_KEYS.map((key) => (\n <linearGradient\n key={key}\n id={`power-history-fill-${key}`}\n x1=\"0\"\n y1=\"0\"\n x2=\"0\"\n y2=\"1\"\n >\n <stop\n offset=\"0%\"\n stopColor={SERIES_COLORS[key]}\n stopOpacity={0.35}\n />\n <stop\n offset=\"100%\"\n stopColor={SERIES_COLORS[key]}\n stopOpacity={0.04}\n />\n </linearGradient>\n ))}\n </defs>\n\n {yTicks.map((tick) => {\n const y = yScale(tick)\n return (\n <g key={`y-tick-${tick}`}>\n <line\n x1={Y_AXIS_GUTTER}\n x2={plotRight}\n y1={y}\n y2={y}\n stroke=\"var(--gray-a4)\"\n strokeWidth={1}\n />\n <text\n x={Y_AXIS_GUTTER - 7}\n y={y + 3}\n textAnchor=\"end\"\n fill=\"var(--gray-a11)\"\n fontSize={10}\n >\n {formatYAxisTick(tick)}\n </text>\n </g>\n )\n })}\n\n {AREA_KEYS.filter((key) => !isHidden(key)).map((key) => (\n <Area<PowerHistoryPoint>\n key={`area-${key}`}\n data={data}\n x={(d) => xScale(d.t)}\n y0={yScale(0)}\n y1={(d) => yScale(d[key])}\n curve={curveMonotoneX}\n fill={`url(#power-history-fill-${key})`}\n stroke=\"transparent\"\n />\n ))}\n\n {AREA_KEYS.filter((key) => !isHidden(key)).map((key) => (\n <LinePath<PowerHistoryPoint>\n key={`line-${key}`}\n data={data}\n x={(d) => xScale(d.t)}\n y={(d) => yScale(d[key])}\n curve={curveMonotoneX}\n stroke={SERIES_COLORS[key]}\n strokeWidth={1.5}\n fill=\"none\"\n />\n ))}\n\n {!isHidden('consumption') && (\n <LinePath<PowerHistoryPoint>\n data={data}\n x={(d) => xScale(d.t)}\n y={(d) => yScale(d.consumption)}\n curve={curveMonotoneX}\n stroke={SERIES_COLORS.consumption}\n strokeWidth={1.5}\n fill=\"none\"\n />\n )}\n\n <line\n x1={Y_AXIS_GUTTER}\n x2={plotRight}\n y1={yScale(0)}\n y2={yScale(0)}\n stroke=\"var(--slate-a6)\"\n strokeWidth={1}\n />\n\n {showHighlight && (\n <line\n x1={xScale(highlightAt)}\n x2={xScale(highlightAt)}\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 {xTicks.map((tick) => (\n <text\n key={`x-tick-${tick}`}\n x={xScale(tick)}\n y={height - PADDING_BOTTOM + 16}\n textAnchor=\"middle\"\n fill=\"var(--gray-a11)\"\n fontSize={10}\n >\n {formatX(tick)}\n </text>\n ))}\n\n {tooltipOpen && tooltipData && (\n <>\n <line\n x1={xScale(tooltipData.t)}\n x2={xScale(tooltipData.t)}\n y1={PADDING_TOP}\n y2={height - PADDING_BOTTOM}\n stroke=\"var(--slate-a6)\"\n strokeDasharray=\"4 4\"\n pointerEvents=\"none\"\n />\n {AREA_KEYS.filter((key) => !isHidden(key)).map((key) => (\n <circle\n key={`dot-${key}`}\n cx={xScale(tooltipData.t)}\n cy={yScale(tooltipData[key])}\n r={3.5}\n fill={SERIES_COLORS[key]}\n stroke=\"white\"\n strokeWidth={1.5}\n pointerEvents=\"none\"\n />\n ))}\n {!isHidden('consumption') && (\n <circle\n cx={xScale(tooltipData.t)}\n cy={yScale(tooltipData.consumption)}\n r={3.5}\n fill={SERIES_COLORS.consumption}\n stroke=\"white\"\n strokeWidth={1.5}\n pointerEvents=\"none\"\n />\n )}\n </>\n )}\n\n <rect\n x={Y_AXIS_GUTTER}\n y={PADDING_TOP}\n width={Math.max(0, plotRight - Y_AXIS_GUTTER)}\n height={Math.max(0, height - PADDING_BOTTOM - PADDING_TOP)}\n fill=\"transparent\"\n onMouseMove={handleTooltip}\n onMouseLeave={hideTooltip}\n onTouchMove={handleTooltip}\n onTouchEnd={hideTooltip}\n />\n </svg>\n )}\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: tooltipOpen && tooltipData ? 1 : 0,\n transition:\n 'left 140ms ease-out, top 140ms ease-out, opacity 140ms ease-out',\n }}\n >\n {tooltipData && (\n <ChartTooltipCard\n label={fmtTooltipX(tooltipData.t)}\n rows={tooltipRows}\n />\n )}\n </div>\n </div>\n </div>\n )\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"power-history-chart.cjs","names":["useReducedMotion","valueFormat","buildYAxisScale","useMeasuredSize","clampTooltipPosition","SectionTitle","SeriesLegend","formatYAxisTick","Area","curveMonotoneX","LinePath","ChartTooltipCard"],"sources":["../../src/components/power-history-chart.tsx"],"sourcesContent":["import { curveMonotoneX } from '@visx/curve'\nimport { localPoint } from '@visx/event'\nimport { scaleLinear } from '@visx/scale'\nimport { Area, LinePath } from '@visx/shape'\nimport { useTooltip } from '@visx/tooltip'\nimport { bisector } from '@visx/vendor/d3-array'\nimport * as React from 'react'\nimport { useCallback, useEffect, useMemo, useRef, useState } from 'react'\nimport { useReducedMotion } from '../hooks/use-reduced-motion'\nimport { NARROW_NBSP } from '../utils/chars'\nimport { buildYAxisScale, formatYAxisTick } from '../utils/chart-scale'\nimport { cn } from '../utils/cn'\nimport { twoDecimalFormat as valueFormat } from '../utils/format'\nimport {\n ChartTooltipCard,\n type ChartTooltipRow,\n clampTooltipPosition,\n useMeasuredSize,\n} from './chart'\nimport { SeriesLegend, type SeriesLegendItem } from './series-legend'\nimport { SectionTitle } from './typography'\n\nexport interface PowerHistoryPoint {\n /** Epoch milliseconds. */\n t: number\n solar: number\n /** Signed: positive = import, negative = feed-in. */\n grid: number\n /** Signed: positive = discharge, negative = charge. */\n battery: number\n consumption: number\n}\n\nexport interface PowerHistoryChartProps {\n data: PowerHistoryPoint[]\n /** Axis/tooltip unit, e.g. \"kW\". */\n unit: string\n formatX: (t: number) => string\n /** Tooltip time formatter. Defaults to `formatX`; use to keep the tooltip's\n * full clock time when the axis ticks are compact (hour-only). */\n formatTooltipX?: (t: number) => string\n formatValue?: (value: number) => string\n labels: {\n solar: string\n grid: string\n battery: string\n consumption: string\n }\n /** Series to drop entirely (no legend entry, area, or tooltip row). */\n omitSeries?: readonly PowerHistorySeriesKey[]\n /** Epoch ms to mark with the current-time dashed line (omit to hide). */\n highlightAt?: number\n title?: string\n className?: string\n height?: number\n}\n\nconst AREA_KEYS = ['solar', 'grid', 'battery'] as const\n\n// All toggleable series, in legend order. The areas (solar/grid/battery) plus\n// the consumption overlay line.\nconst SERIES_KEYS = ['solar', 'grid', 'battery', 'consumption'] as const\nexport type PowerHistorySeriesKey = (typeof SERIES_KEYS)[number]\ntype SeriesKey = PowerHistorySeriesKey\n\nconst SERIES_COLORS = {\n solar: 'var(--orange-a9)',\n grid: 'var(--blue-9)',\n battery: 'var(--green-a9)',\n consumption: 'var(--neutral-12)',\n} as const\n\nconst PADDING_TOP = 20\nconst PADDING_BOTTOM = 28\nconst PADDING_RIGHT = 8\nconst Y_AXIS_GUTTER = 34\nconst X_TICK_COUNT = 6\nconst DEFAULT_HEIGHT = 260\n\nconst tBisector = bisector<PowerHistoryPoint, number>((d) => d.t)\n\n/**\n * Diverging \"power sources\" area chart over a continuous time axis: solar\n * (orange), grid (blue) and battery (green) areas around a zero baseline, with\n * consumption overlaid as a line. Negative values (grid feed-in, battery\n * charging) dip below zero. For instantaneous power (day view). A legend at the\n * top toggles each series on/off; the y-axis rescales to the visible ones. visx.\n */\nexport function PowerHistoryChart({\n data,\n unit,\n formatX,\n formatTooltipX,\n formatValue,\n labels,\n omitSeries,\n highlightAt,\n title,\n className,\n height = DEFAULT_HEIGHT,\n}: PowerHistoryChartProps) {\n const fmtTooltipX = formatTooltipX ?? formatX\n const containerRef = useRef<HTMLDivElement>(null)\n const reducedMotion = useReducedMotion()\n const [width, setWidth] = useState(0)\n const [hiddenSeries, setHiddenSeries] = useState<ReadonlySet<string>>(\n () => new Set(),\n )\n const omitted = useMemo(() => new Set<SeriesKey>(omitSeries), [omitSeries])\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 const isHidden = useCallback(\n (key: SeriesKey) => omitted.has(key) || hiddenSeries.has(key),\n [hiddenSeries, omitted],\n )\n\n const {\n showTooltip,\n hideTooltip,\n tooltipData,\n tooltipLeft,\n tooltipTop,\n tooltipOpen,\n } = useTooltip<PowerHistoryPoint>()\n\n useEffect(() => {\n const element = containerRef.current\n if (!element) return\n\n const resizeObserver = new ResizeObserver((entries) => {\n const entry = entries[0]\n if (!entry) return\n setWidth(entry.contentRect.width)\n })\n\n resizeObserver.observe(element)\n return () => resizeObserver.disconnect()\n }, [])\n\n const fmtValue = (value: number) =>\n formatValue\n ? formatValue(value)\n : `${valueFormat.format(value)}${NARROW_NBSP}${unit}`\n\n const tMin = data.length ? (data[0]?.t ?? 0) : 0\n const tMax = data.length ? (data[data.length - 1]?.t ?? 0) : 0\n\n const { yMin, yMax } = useMemo(() => {\n let min = 0\n let max = 0\n for (const d of data) {\n if (!isHidden('solar')) max = Math.max(max, d.solar)\n if (!isHidden('consumption')) max = Math.max(max, d.consumption)\n if (!isHidden('grid')) {\n max = Math.max(max, d.grid)\n min = Math.min(min, d.grid)\n }\n if (!isHidden('battery')) {\n max = Math.max(max, d.battery)\n min = Math.min(min, d.battery)\n }\n }\n return { yMin: min, yMax: max }\n }, [data, isHidden])\n\n const {\n ticks: yTicks,\n min: lo,\n max: hi,\n } = useMemo(() => buildYAxisScale(yMin, yMax), [yMin, yMax])\n\n const plotRight = Math.max(Y_AXIS_GUTTER, width - PADDING_RIGHT)\n\n const xScale = useMemo(\n () =>\n scaleLinear<number>({\n domain: [tMin, tMax === tMin ? tMin + 1 : tMax],\n range: [Y_AXIS_GUTTER, plotRight],\n }),\n [tMin, tMax, plotRight],\n )\n\n const yScale = useMemo(\n () =>\n scaleLinear<number>({\n domain: [lo, hi === lo ? lo + 1 : hi],\n range: [height - PADDING_BOTTOM, PADDING_TOP],\n }),\n [lo, hi, height],\n )\n\n const xTicks = useMemo(() => {\n if (tMax <= tMin) return [tMin]\n return Array.from(\n { length: X_TICK_COUNT },\n (_, i) => tMin + (i / (X_TICK_COUNT - 1)) * (tMax - tMin),\n )\n }, [tMin, tMax])\n\n const handleTooltip = useCallback(\n (\n event:\n | React.TouchEvent<SVGRectElement>\n | React.MouseEvent<SVGRectElement>,\n ) => {\n const point = localPoint(event)\n if (!point || data.length === 0) return\n\n const xMs = xScale.invert(point.x)\n const index = tBisector.left(data, xMs, 1)\n const d0 = data[index - 1]\n const d1 = data[index]\n if (!d0) return\n\n const d = d1 && xMs - d0.t > d1.t - xMs ? d1 : d0\n showTooltip({\n tooltipData: d,\n tooltipLeft: xScale(d.t),\n tooltipTop: PADDING_TOP,\n })\n },\n [data, showTooltip, xScale],\n )\n\n const legendItems: SeriesLegendItem[] = SERIES_KEYS.filter(\n (key) => !omitted.has(key),\n ).map((key) => ({\n id: key,\n label: labels[key],\n color: SERIES_COLORS[key],\n }))\n\n const tooltipRows: ChartTooltipRow[] = tooltipData\n ? SERIES_KEYS.filter((key) => !isHidden(key)).map((key) => ({\n key,\n label: labels[key],\n color: SERIES_COLORS[key],\n value: fmtValue(tooltipData[key]),\n }))\n : []\n\n const showHighlight =\n highlightAt !== undefined && highlightAt >= tMin && highlightAt <= tMax\n\n const [tooltipRef, tooltipSize] = useMeasuredSize<HTMLDivElement>()\n const tooltipPos = clampTooltipPosition({\n anchorX: tooltipLeft ?? 0,\n anchorY: tooltipTop ?? PADDING_TOP,\n width,\n height,\n tipWidth: tooltipSize.width,\n tipHeight: tooltipSize.height,\n placement: 'beside',\n })\n\n return (\n <div className={cn('flex w-full flex-col gap-2', className)}>\n {title && <SectionTitle>{title}</SectionTitle>}\n <SeriesLegend\n items={legendItems}\n hiddenIds={hiddenSeries}\n onToggle={toggleSeries}\n />\n <span className=\"px-1 text-xs text-gray-light\">{unit}</span>\n <div ref={containerRef} className=\"relative w-full\" style={{ height }}>\n {width > 0 && (\n <svg width={width} height={height}>\n <defs>\n {AREA_KEYS.map((key) => (\n <linearGradient\n key={key}\n id={`power-history-fill-${key}`}\n x1=\"0\"\n y1=\"0\"\n x2=\"0\"\n y2=\"1\"\n >\n <stop\n offset=\"0%\"\n stopColor={SERIES_COLORS[key]}\n stopOpacity={0.35}\n />\n <stop\n offset=\"100%\"\n stopColor={SERIES_COLORS[key]}\n stopOpacity={0.04}\n />\n </linearGradient>\n ))}\n </defs>\n\n {yTicks.map((tick) => {\n const y = yScale(tick)\n return (\n <g key={`y-tick-${tick}`}>\n <line\n x1={Y_AXIS_GUTTER}\n x2={plotRight}\n y1={y}\n y2={y}\n stroke=\"var(--neutral-a4)\"\n strokeWidth={1}\n />\n <text\n x={Y_AXIS_GUTTER - 7}\n y={y + 3}\n textAnchor=\"end\"\n fill=\"var(--neutral-a11)\"\n fontSize={10}\n >\n {formatYAxisTick(tick)}\n </text>\n </g>\n )\n })}\n\n {AREA_KEYS.filter((key) => !isHidden(key)).map((key) => (\n <Area<PowerHistoryPoint>\n key={`area-${key}`}\n data={data}\n x={(d) => xScale(d.t)}\n y0={yScale(0)}\n y1={(d) => yScale(d[key])}\n curve={curveMonotoneX}\n fill={`url(#power-history-fill-${key})`}\n stroke=\"transparent\"\n />\n ))}\n\n {AREA_KEYS.filter((key) => !isHidden(key)).map((key) => (\n <LinePath<PowerHistoryPoint>\n key={`line-${key}`}\n data={data}\n x={(d) => xScale(d.t)}\n y={(d) => yScale(d[key])}\n curve={curveMonotoneX}\n stroke={SERIES_COLORS[key]}\n strokeWidth={1.5}\n fill=\"none\"\n />\n ))}\n\n {!isHidden('consumption') && (\n <LinePath<PowerHistoryPoint>\n data={data}\n x={(d) => xScale(d.t)}\n y={(d) => yScale(d.consumption)}\n curve={curveMonotoneX}\n stroke={SERIES_COLORS.consumption}\n strokeWidth={1.5}\n fill=\"none\"\n />\n )}\n\n <line\n x1={Y_AXIS_GUTTER}\n x2={plotRight}\n y1={yScale(0)}\n y2={yScale(0)}\n stroke=\"var(--neutral-a6)\"\n strokeWidth={1}\n />\n\n {showHighlight && (\n <line\n x1={xScale(highlightAt)}\n x2={xScale(highlightAt)}\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 {xTicks.map((tick) => (\n <text\n key={`x-tick-${tick}`}\n x={xScale(tick)}\n y={height - PADDING_BOTTOM + 16}\n textAnchor=\"middle\"\n fill=\"var(--neutral-a11)\"\n fontSize={10}\n >\n {formatX(tick)}\n </text>\n ))}\n\n {tooltipOpen && tooltipData && (\n <>\n <line\n x1={xScale(tooltipData.t)}\n x2={xScale(tooltipData.t)}\n y1={PADDING_TOP}\n y2={height - PADDING_BOTTOM}\n stroke=\"var(--neutral-a6)\"\n strokeDasharray=\"4 4\"\n pointerEvents=\"none\"\n />\n {AREA_KEYS.filter((key) => !isHidden(key)).map((key) => (\n <circle\n key={`dot-${key}`}\n cx={xScale(tooltipData.t)}\n cy={yScale(tooltipData[key])}\n r={3.5}\n fill={SERIES_COLORS[key]}\n stroke=\"white\"\n strokeWidth={1.5}\n pointerEvents=\"none\"\n />\n ))}\n {!isHidden('consumption') && (\n <circle\n cx={xScale(tooltipData.t)}\n cy={yScale(tooltipData.consumption)}\n r={3.5}\n fill={SERIES_COLORS.consumption}\n stroke=\"white\"\n strokeWidth={1.5}\n pointerEvents=\"none\"\n />\n )}\n </>\n )}\n\n <rect\n x={Y_AXIS_GUTTER}\n y={PADDING_TOP}\n width={Math.max(0, plotRight - Y_AXIS_GUTTER)}\n height={Math.max(0, height - PADDING_BOTTOM - PADDING_TOP)}\n fill=\"transparent\"\n onMouseMove={handleTooltip}\n onMouseLeave={hideTooltip}\n onTouchMove={handleTooltip}\n onTouchEnd={hideTooltip}\n />\n </svg>\n )}\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: tooltipOpen && tooltipData ? 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 {tooltipData && (\n <ChartTooltipCard\n label={fmtTooltipX(tooltipData.t)}\n rows={tooltipRows}\n />\n )}\n </div>\n </div>\n </div>\n )\n}\n"],"mappings":"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"}
@@ -1,4 +1,5 @@
1
1
  "use client";
2
+ import { useReducedMotion } from "../hooks/use-reduced-motion.js";
2
3
  import { cn } from "../utils/cn.js";
3
4
  import "../utils/chars.js";
4
5
  import { twoDecimalFormat } from "../utils/format.js";
@@ -30,7 +31,7 @@ const SERIES_COLORS = {
30
31
  solar: "var(--orange-a9)",
31
32
  grid: "var(--blue-9)",
32
33
  battery: "var(--green-a9)",
33
- consumption: "var(--gray-12)"
34
+ consumption: "var(--neutral-12)"
34
35
  };
35
36
  const PADDING_TOP = 20;
36
37
  const PADDING_BOTTOM = 28;
@@ -49,6 +50,7 @@ const tBisector = bisector((d) => d.t);
49
50
  function PowerHistoryChart({ data, unit, formatX, formatTooltipX, formatValue, labels, omitSeries, highlightAt, title, className, height = DEFAULT_HEIGHT }) {
50
51
  const fmtTooltipX = formatTooltipX ?? formatX;
51
52
  const containerRef = useRef(null);
53
+ const reducedMotion = useReducedMotion();
52
54
  const [width, setWidth] = useState(0);
53
55
  const [hiddenSeries, setHiddenSeries] = useState(() => /* @__PURE__ */ new Set());
54
56
  const omitted = useMemo(() => new Set(omitSeries), [omitSeries]);
@@ -203,13 +205,13 @@ function PowerHistoryChart({ data, unit, formatX, formatTooltipX, formatValue, l
203
205
  x2: plotRight,
204
206
  y1: y,
205
207
  y2: y,
206
- stroke: "var(--gray-a4)",
208
+ stroke: "var(--neutral-a4)",
207
209
  strokeWidth: 1
208
210
  }), /* @__PURE__ */ jsx("text", {
209
211
  x: Y_AXIS_GUTTER - 7,
210
212
  y: y + 3,
211
213
  textAnchor: "end",
212
- fill: "var(--gray-a11)",
214
+ fill: "var(--neutral-a11)",
213
215
  fontSize: 10,
214
216
  children: formatYAxisTick(tick)
215
217
  })] }, `y-tick-${tick}`);
@@ -246,7 +248,7 @@ function PowerHistoryChart({ data, unit, formatX, formatTooltipX, formatValue, l
246
248
  x2: plotRight,
247
249
  y1: yScale(0),
248
250
  y2: yScale(0),
249
- stroke: "var(--slate-a6)",
251
+ stroke: "var(--neutral-a6)",
250
252
  strokeWidth: 1
251
253
  }),
252
254
  showHighlight && /* @__PURE__ */ jsx("line", {
@@ -263,7 +265,7 @@ function PowerHistoryChart({ data, unit, formatX, formatTooltipX, formatValue, l
263
265
  x: xScale(tick),
264
266
  y: height - PADDING_BOTTOM + 16,
265
267
  textAnchor: "middle",
266
- fill: "var(--gray-a11)",
268
+ fill: "var(--neutral-a11)",
267
269
  fontSize: 10,
268
270
  children: formatX(tick)
269
271
  }, `x-tick-${tick}`)),
@@ -273,7 +275,7 @@ function PowerHistoryChart({ data, unit, formatX, formatTooltipX, formatValue, l
273
275
  x2: xScale(tooltipData.t),
274
276
  y1: PADDING_TOP,
275
277
  y2: height - PADDING_BOTTOM,
276
- stroke: "var(--slate-a6)",
278
+ stroke: "var(--neutral-a6)",
277
279
  strokeDasharray: "4 4",
278
280
  pointerEvents: "none"
279
281
  }),
@@ -315,7 +317,7 @@ function PowerHistoryChart({ data, unit, formatX, formatTooltipX, formatValue, l
315
317
  left: tooltipPos.left,
316
318
  top: tooltipPos.top,
317
319
  opacity: tooltipOpen && tooltipData ? 1 : 0,
318
- transition: "left 140ms ease-out, top 140ms ease-out, opacity 140ms ease-out"
320
+ transition: reducedMotion ? "opacity 140ms ease-out" : "left 140ms ease-out, top 140ms ease-out, opacity 140ms ease-out"
319
321
  },
320
322
  children: tooltipData && /* @__PURE__ */ jsx(ChartTooltipCard, {
321
323
  label: fmtTooltipX(tooltipData.t),