@epilot/spark-ui 0.10.1 → 0.11.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.
- package/README.md +9 -1
- package/dist/components/accordion.cjs +1 -1
- package/dist/components/accordion.d.ts +1 -1
- package/dist/components/accordion.js +1 -1
- package/dist/components/attachment.d.cts +1 -1
- package/dist/components/attachment.d.ts +1 -1
- package/dist/components/avatar.d.cts +1 -1
- package/dist/components/avatar.d.ts +1 -1
- package/dist/components/badge.cjs +1 -1
- package/dist/components/badge.cjs.map +1 -1
- package/dist/components/badge.d.cts +1 -1
- package/dist/components/badge.d.ts +1 -1
- package/dist/components/badge.js +1 -1
- package/dist/components/badge.js.map +1 -1
- package/dist/components/bar-chart.cjs +4 -7
- package/dist/components/bar-chart.cjs.map +1 -1
- package/dist/components/bar-chart.js +5 -8
- package/dist/components/bar-chart.js.map +1 -1
- package/dist/components/battery-progress-row.cjs +6 -7
- package/dist/components/battery-progress-row.cjs.map +1 -1
- package/dist/components/battery-progress-row.js +6 -7
- package/dist/components/battery-progress-row.js.map +1 -1
- package/dist/components/box.cjs +42 -0
- package/dist/components/box.cjs.map +1 -0
- package/dist/components/box.d.cts +35 -0
- package/dist/components/box.d.ts +35 -0
- package/dist/components/box.js +41 -0
- package/dist/components/box.js.map +1 -0
- package/dist/components/bubble.d.cts +1 -1
- package/dist/components/bubble.d.ts +1 -1
- package/dist/components/button-group.d.cts +1 -1
- package/dist/components/button-group.d.ts +1 -1
- package/dist/components/button.cjs +1 -1
- package/dist/components/button.cjs.map +1 -1
- package/dist/components/button.d.cts +3 -3
- package/dist/components/button.d.ts +3 -3
- package/dist/components/button.js +1 -1
- package/dist/components/button.js.map +1 -1
- package/dist/components/callout.d.cts +1 -1
- package/dist/components/callout.d.ts +1 -1
- package/dist/components/card.cjs +10 -14
- package/dist/components/card.cjs.map +1 -1
- package/dist/components/card.d.cts +6 -3
- package/dist/components/card.d.ts +6 -3
- package/dist/components/card.js +10 -14
- package/dist/components/card.js.map +1 -1
- package/dist/components/checkbox.d.cts +1 -1
- package/dist/components/checkbox.d.ts +1 -1
- package/dist/components/empty-state.cjs +4 -7
- package/dist/components/empty-state.cjs.map +1 -1
- package/dist/components/empty-state.js +4 -7
- package/dist/components/empty-state.js.map +1 -1
- package/dist/components/field.cjs +43 -10
- package/dist/components/field.cjs.map +1 -1
- package/dist/components/field.d.cts +19 -2
- package/dist/components/field.d.ts +19 -2
- package/dist/components/field.js +43 -11
- package/dist/components/field.js.map +1 -1
- package/dist/components/icon.cjs +12 -9
- package/dist/components/icon.cjs.map +1 -1
- package/dist/components/icon.d.cts +6 -2
- package/dist/components/icon.d.ts +6 -2
- package/dist/components/icon.js +12 -9
- package/dist/components/icon.js.map +1 -1
- package/dist/components/info-block.d.cts +1 -1
- package/dist/components/info-block.d.ts +1 -1
- package/dist/components/input.d.cts +1 -1
- package/dist/components/input.d.ts +1 -1
- package/dist/components/line-chart.cjs +1 -1
- package/dist/components/line-chart.js +2 -2
- package/dist/components/marker.d.cts +1 -1
- package/dist/components/marker.d.ts +1 -1
- package/dist/components/metering-row.cjs +28 -11
- package/dist/components/metering-row.cjs.map +1 -1
- package/dist/components/metering-row.js +28 -11
- package/dist/components/metering-row.js.map +1 -1
- package/dist/components/page-header.d.cts +1 -1
- package/dist/components/page-header.d.ts +1 -1
- package/dist/components/pill.cjs +1 -1
- package/dist/components/pill.cjs.map +1 -1
- package/dist/components/pill.d.cts +1 -1
- package/dist/components/pill.d.ts +1 -1
- package/dist/components/pill.js +1 -1
- package/dist/components/pill.js.map +1 -1
- package/dist/components/power-history-chart.cjs +1 -1
- package/dist/components/power-history-chart.js +2 -2
- package/dist/components/power-history.cjs +1 -1
- package/dist/components/power-history.js +1 -1
- package/dist/components/power-network.cjs +1 -1
- package/dist/components/power-network.js +1 -1
- package/dist/components/radio.d.cts +1 -1
- package/dist/components/radio.d.ts +1 -1
- package/dist/components/segmented-control.d.cts +1 -1
- package/dist/components/segmented-control.d.ts +1 -1
- package/dist/components/select.d.cts +1 -1
- package/dist/components/select.d.ts +1 -1
- package/dist/components/switch.d.cts +1 -1
- package/dist/components/switch.d.ts +1 -1
- package/dist/components/textarea.d.cts +1 -1
- package/dist/components/textarea.d.ts +1 -1
- package/dist/components/theme.cjs +35 -9
- package/dist/components/theme.cjs.map +1 -1
- package/dist/components/theme.d.cts +12 -1
- package/dist/components/theme.d.ts +12 -1
- package/dist/components/theme.js +36 -10
- package/dist/components/theme.js.map +1 -1
- package/dist/icons/material-symbol.cjs +1 -0
- package/dist/icons/material-symbol.cjs.map +1 -1
- package/dist/icons/material-symbol.js +1 -0
- package/dist/icons/material-symbol.js.map +1 -1
- package/dist/lib/accent-theme.cjs +102 -14
- package/dist/lib/accent-theme.cjs.map +1 -1
- package/dist/lib/accent-theme.d.cts +29 -4
- package/dist/lib/accent-theme.d.ts +29 -4
- package/dist/lib/accent-theme.js +100 -15
- package/dist/lib/accent-theme.js.map +1 -1
- package/dist/lib/container-chrome.cjs +53 -0
- package/dist/lib/container-chrome.cjs.map +1 -0
- package/dist/lib/container-chrome.d.cts +15 -0
- package/dist/lib/container-chrome.d.ts +15 -0
- package/dist/lib/container-chrome.js +48 -0
- package/dist/lib/container-chrome.js.map +1 -0
- package/dist/lib/input-box-variants.d.cts +1 -1
- package/dist/lib/input-box-variants.d.ts +1 -1
- package/dist/lib/theme-types.d.cts +1 -1
- package/dist/lib/theme-types.d.ts +1 -1
- package/dist/styles/spark-default.css +34 -8
- package/dist/{theme-types-8wjgiNA_.d.ts → theme-types-1yB0d8mp.d.cts} +6 -6
- package/dist/{theme-types-8wjgiNA_.d.cts → theme-types-1yB0d8mp.d.ts} +6 -6
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -22,7 +22,6 @@ Import the UI package styles once (e.g. in your app entry). This ships:
|
|
|
22
22
|
|
|
23
23
|
- Radix color tokens as CSS variables (e.g. `--slate-1`, `--mauve-a8`, …)
|
|
24
24
|
- Default Spark brand tokens as CSS variables (e.g. `--spark-9`, `--spark-a3`, …)
|
|
25
|
-
- Precompiled Tailwind utilities used by the components (e.g. `bg-spark-10`)
|
|
26
25
|
|
|
27
26
|
Theme selectors follow the same convention as the portal:
|
|
28
27
|
`:root, .light, .light-theme` and `.dark, .dark-theme`.
|
|
@@ -30,3 +29,12 @@ Theme selectors follow the same convention as the portal:
|
|
|
30
29
|
```ts
|
|
31
30
|
import '@epilot/spark-ui/styles'
|
|
32
31
|
```
|
|
32
|
+
|
|
33
|
+
Tailwind v4 skips `node_modules` during content detection, so without an explicit
|
|
34
|
+
`@source` the components' own utility classes (e.g. `bg-spark-10`) never get
|
|
35
|
+
generated — they render **completely unstyled, with no error or warning**. Point
|
|
36
|
+
your Tailwind entry stylesheet at the package's `dist`:
|
|
37
|
+
|
|
38
|
+
```css
|
|
39
|
+
@source '../node_modules/@epilot/spark-ui/dist';
|
|
40
|
+
```
|
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
3
3
|
const require_chunk = require("../chunk-DY84GLCh.cjs");
|
|
4
4
|
const require_icons_material_symbol = require("../icons/material-symbol.cjs");
|
|
5
|
-
let _base_ui_react_accordion = require("@base-ui/react/accordion");
|
|
6
5
|
let react = require("react");
|
|
7
6
|
react = require_chunk.__toESM(react);
|
|
7
|
+
let _base_ui_react_accordion = require("@base-ui/react/accordion");
|
|
8
8
|
let react_jsx_runtime = require("react/jsx-runtime");
|
|
9
9
|
let cnfast = require("cnfast");
|
|
10
10
|
//#region src/components/accordion.tsx
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
|
|
3
|
-
import { Accordion as Accordion$1 } from "@base-ui/react/accordion";
|
|
4
3
|
import * as React$1 from "react";
|
|
4
|
+
import { Accordion as Accordion$1 } from "@base-ui/react/accordion";
|
|
5
5
|
|
|
6
6
|
//#region src/components/accordion.d.ts
|
|
7
7
|
type AccordionVariant = 'ghost' | 'soft' | 'surface' | 'outline';
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { cn } from "../utils/cn.js";
|
|
3
3
|
import { MaterialSymbol } from "../icons/material-symbol.js";
|
|
4
|
-
import { Accordion as Accordion$1 } from "@base-ui/react/accordion";
|
|
5
4
|
import "react";
|
|
5
|
+
import { Accordion as Accordion$1 } from "@base-ui/react/accordion";
|
|
6
6
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
7
7
|
//#region src/components/accordion.tsx
|
|
8
8
|
function Accordion({ className, variant = "soft", ...props }) {
|
|
@@ -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?: "
|
|
10
|
+
size?: "sm" | "default" | "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?: "
|
|
10
|
+
size?: "sm" | "default" | "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-
|
|
3
|
+
import { u as SparkStyle } from "../theme-types-1yB0d8mp.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-
|
|
3
|
+
import { u as SparkStyle } from "../theme-types-1yB0d8mp.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";
|
|
@@ -12,7 +12,7 @@ const Badge = react.forwardRef(({ className, children, styleVariant, color, ...p
|
|
|
12
12
|
"data-slot": "badge",
|
|
13
13
|
"data-style": styleVariant !== void 0 || color !== void 0 ? styleVariant ?? "soft" : void 0,
|
|
14
14
|
"data-accent-color": color ? require_lib_accent_colors.accentByColor[color] : void 0,
|
|
15
|
-
className: (0, cnfast.cn)("inline-flex h-5 min-w-5 items-center justify-center rounded-sm px-1.5 text-center text-xs font-normal tabular-nums", "border-(length:--spark-style-border-width,1px) border-(--spark-style-border,transparent)", "bg-(--spark-style-bg,var(--
|
|
15
|
+
className: (0, cnfast.cn)("inline-flex h-5 min-w-5 items-center justify-center rounded-sm px-1.5 text-center text-xs font-normal tabular-nums", "border-(length:--spark-style-border-width,1px) border-(--spark-style-border,transparent)", "bg-(--spark-style-bg,var(--neutral-a3)) text-(--spark-style-fg,var(--spark-badge-fg,var(--neutral-a11)))", className),
|
|
16
16
|
ref,
|
|
17
17
|
...props,
|
|
18
18
|
children
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"badge.cjs","names":["React","accentByColor"],"sources":["../../src/components/badge.tsx"],"sourcesContent":["import * as React from 'react'\nimport { accentByColor } from '../lib/accent-colors'\nimport type { SparkStyle } from '../lib/theme-types'\nimport { cn } from '../utils/cn'\n\nexport type SparkBadgeColor =\n | 'accent'\n | 'neutral'\n | 'success'\n | 'warning'\n | 'danger'\n\ninterface BadgeProps extends React.HTMLAttributes<HTMLSpanElement> {\n styleVariant?: SparkStyle\n color?: SparkBadgeColor\n children?: React.ReactNode\n}\n\nconst Badge = React.forwardRef<HTMLSpanElement, BadgeProps>(\n ({ className, children, styleVariant, color, ...props }, ref) => {\n const hasLook = styleVariant !== undefined || color !== undefined\n return (\n <span\n data-slot=\"badge\"\n data-style={hasLook ? (styleVariant ?? 'soft') : undefined}\n data-accent-color={color ? accentByColor[color] : undefined}\n className={cn(\n 'inline-flex h-5 min-w-5 items-center justify-center rounded-sm px-1.5 text-center text-xs font-normal tabular-nums',\n 'border-(length:--spark-style-border-width,1px) border-(--spark-style-border,transparent)',\n 'bg-(--spark-style-bg,var(--
|
|
1
|
+
{"version":3,"file":"badge.cjs","names":["React","accentByColor"],"sources":["../../src/components/badge.tsx"],"sourcesContent":["import * as React from 'react'\nimport { accentByColor } from '../lib/accent-colors'\nimport type { SparkStyle } from '../lib/theme-types'\nimport { cn } from '../utils/cn'\n\nexport type SparkBadgeColor =\n | 'accent'\n | 'neutral'\n | 'success'\n | 'warning'\n | 'danger'\n\ninterface BadgeProps extends React.HTMLAttributes<HTMLSpanElement> {\n styleVariant?: SparkStyle\n color?: SparkBadgeColor\n children?: React.ReactNode\n}\n\nconst Badge = React.forwardRef<HTMLSpanElement, BadgeProps>(\n ({ className, children, styleVariant, color, ...props }, ref) => {\n const hasLook = styleVariant !== undefined || color !== undefined\n return (\n <span\n data-slot=\"badge\"\n data-style={hasLook ? (styleVariant ?? 'soft') : undefined}\n data-accent-color={color ? accentByColor[color] : undefined}\n className={cn(\n 'inline-flex h-5 min-w-5 items-center justify-center rounded-sm px-1.5 text-center text-xs font-normal tabular-nums',\n 'border-(length:--spark-style-border-width,1px) border-(--spark-style-border,transparent)',\n 'bg-(--spark-style-bg,var(--neutral-a3)) text-(--spark-style-fg,var(--spark-badge-fg,var(--neutral-a11)))',\n className,\n )}\n ref={ref}\n {...props}\n >\n {children}\n </span>\n )\n },\n)\n\nBadge.displayName = 'Badge'\n\nexport { Badge }\nexport type { BadgeProps }\n"],"mappings":";;;;;;;;;AAkBA,MAAM,QAAQA,MAAM,YACjB,EAAE,WAAW,UAAU,cAAc,OAAO,GAAG,SAAS,QAAQ;CAE/D,OACE,iBAAA,GAAA,kBAAA,KAAC,QAAD;EACE,aAAU;EACV,cAJY,iBAAiB,KAAA,KAAa,UAAU,KAAA,IAI7B,gBAAgB,SAAU,KAAA;EACjD,qBAAmB,QAAQC,0BAAAA,cAAc,SAAS,KAAA;EAClD,YAAA,GAAA,OAAA,IACE,sHACA,4FACA,4GACA,SACF;EACK;EACL,GAAI;EAEH;CACG,CAAA;AAEV,CACF;AAEA,MAAM,cAAc"}
|
package/dist/components/badge.js
CHANGED
|
@@ -9,7 +9,7 @@ const Badge = React$1.forwardRef(({ className, children, styleVariant, color, ..
|
|
|
9
9
|
"data-slot": "badge",
|
|
10
10
|
"data-style": styleVariant !== void 0 || color !== void 0 ? styleVariant ?? "soft" : void 0,
|
|
11
11
|
"data-accent-color": color ? accentByColor[color] : void 0,
|
|
12
|
-
className: cn("inline-flex h-5 min-w-5 items-center justify-center rounded-sm px-1.5 text-center text-xs font-normal tabular-nums", "border-(length:--spark-style-border-width,1px) border-(--spark-style-border,transparent)", "bg-(--spark-style-bg,var(--
|
|
12
|
+
className: cn("inline-flex h-5 min-w-5 items-center justify-center rounded-sm px-1.5 text-center text-xs font-normal tabular-nums", "border-(length:--spark-style-border-width,1px) border-(--spark-style-border,transparent)", "bg-(--spark-style-bg,var(--neutral-a3)) text-(--spark-style-fg,var(--spark-badge-fg,var(--neutral-a11)))", className),
|
|
13
13
|
ref,
|
|
14
14
|
...props,
|
|
15
15
|
children
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"badge.js","names":["React"],"sources":["../../src/components/badge.tsx"],"sourcesContent":["import * as React from 'react'\nimport { accentByColor } from '../lib/accent-colors'\nimport type { SparkStyle } from '../lib/theme-types'\nimport { cn } from '../utils/cn'\n\nexport type SparkBadgeColor =\n | 'accent'\n | 'neutral'\n | 'success'\n | 'warning'\n | 'danger'\n\ninterface BadgeProps extends React.HTMLAttributes<HTMLSpanElement> {\n styleVariant?: SparkStyle\n color?: SparkBadgeColor\n children?: React.ReactNode\n}\n\nconst Badge = React.forwardRef<HTMLSpanElement, BadgeProps>(\n ({ className, children, styleVariant, color, ...props }, ref) => {\n const hasLook = styleVariant !== undefined || color !== undefined\n return (\n <span\n data-slot=\"badge\"\n data-style={hasLook ? (styleVariant ?? 'soft') : undefined}\n data-accent-color={color ? accentByColor[color] : undefined}\n className={cn(\n 'inline-flex h-5 min-w-5 items-center justify-center rounded-sm px-1.5 text-center text-xs font-normal tabular-nums',\n 'border-(length:--spark-style-border-width,1px) border-(--spark-style-border,transparent)',\n 'bg-(--spark-style-bg,var(--
|
|
1
|
+
{"version":3,"file":"badge.js","names":["React"],"sources":["../../src/components/badge.tsx"],"sourcesContent":["import * as React from 'react'\nimport { accentByColor } from '../lib/accent-colors'\nimport type { SparkStyle } from '../lib/theme-types'\nimport { cn } from '../utils/cn'\n\nexport type SparkBadgeColor =\n | 'accent'\n | 'neutral'\n | 'success'\n | 'warning'\n | 'danger'\n\ninterface BadgeProps extends React.HTMLAttributes<HTMLSpanElement> {\n styleVariant?: SparkStyle\n color?: SparkBadgeColor\n children?: React.ReactNode\n}\n\nconst Badge = React.forwardRef<HTMLSpanElement, BadgeProps>(\n ({ className, children, styleVariant, color, ...props }, ref) => {\n const hasLook = styleVariant !== undefined || color !== undefined\n return (\n <span\n data-slot=\"badge\"\n data-style={hasLook ? (styleVariant ?? 'soft') : undefined}\n data-accent-color={color ? accentByColor[color] : undefined}\n className={cn(\n 'inline-flex h-5 min-w-5 items-center justify-center rounded-sm px-1.5 text-center text-xs font-normal tabular-nums',\n 'border-(length:--spark-style-border-width,1px) border-(--spark-style-border,transparent)',\n 'bg-(--spark-style-bg,var(--neutral-a3)) text-(--spark-style-fg,var(--spark-badge-fg,var(--neutral-a11)))',\n className,\n )}\n ref={ref}\n {...props}\n >\n {children}\n </span>\n )\n },\n)\n\nBadge.displayName = 'Badge'\n\nexport { Badge }\nexport type { BadgeProps }\n"],"mappings":";;;;;;AAkBA,MAAM,QAAQA,QAAM,YACjB,EAAE,WAAW,UAAU,cAAc,OAAO,GAAG,SAAS,QAAQ;CAE/D,OACE,oBAAC,QAAD;EACE,aAAU;EACV,cAJY,iBAAiB,KAAA,KAAa,UAAU,KAAA,IAI7B,gBAAgB,SAAU,KAAA;EACjD,qBAAmB,QAAQ,cAAc,SAAS,KAAA;EAClD,WAAW,GACT,sHACA,4FACA,4GACA,SACF;EACK;EACL,GAAI;EAEH;CACG,CAAA;AAEV,CACF;AAEA,MAAM,cAAc"}
|
|
@@ -214,7 +214,8 @@ function BarChart({ data, series, lines, getCategory, categories, categoryTicks,
|
|
|
214
214
|
]);
|
|
215
215
|
const yMin = (0, react.useMemo)(() => Math.min(0, ...stackData.map((record) => series.reduce((sum, entry) => sum + Math.min(0, record.__values[entry.key] ?? 0), 0))), [series, stackData]);
|
|
216
216
|
const xDomain = (0, react.useMemo)(() => categories ?? stackData.map((record) => record.__category), [categories, stackData]);
|
|
217
|
-
const
|
|
217
|
+
const yAxisScale = (0, react.useMemo)(() => require_utils_chart_scale.buildYAxisScale(yMin, yMax), [yMin, yMax]);
|
|
218
|
+
const yTicks = yAxisScale.ticks;
|
|
218
219
|
const gutter = (0, react.useMemo)(() => yAxisWidth ?? require_utils_chart_scale.measureYAxisGutter(yTicks, formatYTick), [
|
|
219
220
|
yTicks,
|
|
220
221
|
formatYTick,
|
|
@@ -240,13 +241,9 @@ function BarChart({ data, series, lines, getCategory, categories, categoryTicks,
|
|
|
240
241
|
plotRight
|
|
241
242
|
]);
|
|
242
243
|
const yScale = (0, react.useMemo)(() => (0, _visx_scale.scaleLinear)({
|
|
243
|
-
domain: [
|
|
244
|
+
domain: [yAxisScale.min, yAxisScale.max],
|
|
244
245
|
range: [height - PADDING_BOTTOM, PADDING_TOP]
|
|
245
|
-
}), [
|
|
246
|
-
height,
|
|
247
|
-
yMax,
|
|
248
|
-
yMin
|
|
249
|
-
]);
|
|
246
|
+
}), [height, yAxisScale]);
|
|
250
247
|
const rightYScale = (0, react.useMemo)(() => rightAxisDomain === void 0 ? null : (0, _visx_scale.scaleLinear)({
|
|
251
248
|
domain: rightAxisDomain,
|
|
252
249
|
range: [height - PADDING_BOTTOM, PADDING_TOP]
|
|
@@ -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 yTicks = useMemo(() => buildYAxisScale(yMin, yMax).ticks, [yMin, yMax])\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 const yScale = useMemo(\n () =>\n scaleLinear<number>({\n domain: [yMin, yMax],\n range: [height - PADDING_BOTTOM, PADDING_TOP],\n }),\n [height, yMax, yMin],\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\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,6 +1,6 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
import { cn } from "../utils/cn.js";
|
|
3
2
|
import { useReducedMotion } from "../hooks/use-reduced-motion.js";
|
|
3
|
+
import { cn } from "../utils/cn.js";
|
|
4
4
|
import { localeNumberFormat } from "../utils/format.js";
|
|
5
5
|
import { buildYAxisScale, formatYAxisTick, measureYAxisGutter } from "../utils/chart-scale.js";
|
|
6
6
|
import { ChartTooltipCard, clampTooltipPosition, useMeasuredSize } from "./chart.js";
|
|
@@ -213,7 +213,8 @@ function BarChart({ data, series, lines, getCategory, categories, categoryTicks,
|
|
|
213
213
|
]);
|
|
214
214
|
const yMin = useMemo(() => Math.min(0, ...stackData.map((record) => series.reduce((sum, entry) => sum + Math.min(0, record.__values[entry.key] ?? 0), 0))), [series, stackData]);
|
|
215
215
|
const xDomain = useMemo(() => categories ?? stackData.map((record) => record.__category), [categories, stackData]);
|
|
216
|
-
const
|
|
216
|
+
const yAxisScale = useMemo(() => buildYAxisScale(yMin, yMax), [yMin, yMax]);
|
|
217
|
+
const yTicks = yAxisScale.ticks;
|
|
217
218
|
const gutter = useMemo(() => yAxisWidth ?? measureYAxisGutter(yTicks, formatYTick), [
|
|
218
219
|
yTicks,
|
|
219
220
|
formatYTick,
|
|
@@ -239,13 +240,9 @@ function BarChart({ data, series, lines, getCategory, categories, categoryTicks,
|
|
|
239
240
|
plotRight
|
|
240
241
|
]);
|
|
241
242
|
const yScale = useMemo(() => scaleLinear({
|
|
242
|
-
domain: [
|
|
243
|
+
domain: [yAxisScale.min, yAxisScale.max],
|
|
243
244
|
range: [height - PADDING_BOTTOM, PADDING_TOP]
|
|
244
|
-
}), [
|
|
245
|
-
height,
|
|
246
|
-
yMax,
|
|
247
|
-
yMin
|
|
248
|
-
]);
|
|
245
|
+
}), [height, yAxisScale]);
|
|
249
246
|
const rightYScale = useMemo(() => rightAxisDomain === void 0 ? null : scaleLinear({
|
|
250
247
|
domain: rightAxisDomain,
|
|
251
248
|
range: [height - PADDING_BOTTOM, PADDING_TOP]
|