diff --git a/lib/components/ChartLabel/ChartLabelText.tsx b/lib/components/ChartLabel/ChartLabelText.tsx new file mode 100644 index 0000000..2c81c7d --- /dev/null +++ b/lib/components/ChartLabel/ChartLabelText.tsx @@ -0,0 +1,45 @@ +import { ViewBox } from "recharts/types/util/types"; +import React from "react"; +import { cx } from "../common/utils.ts"; + +export type ChartLabelTextProps = { + children: React.ReactNode; + dy?: number; + dx?: number; + viewBox?: ViewBox; + className?: string; +}; + +export function ChartLabelText({ + children, + dy = -5, + dx = 0, + viewBox, + className, +}: ChartLabelTextProps) { + if (!viewBox) { + console.warn("ChartLabelText requires a viewBox prop"); + return null; + } + + const isCartesianViewBox = "x" in viewBox && "y" in viewBox; + + if (!isCartesianViewBox) { + console.warn("ChartLabelText currently only accepts CartesianViewBox"); + return null; + } + + return ( + + {children} + + ); +} diff --git a/lib/components/ChartLabel/index.ts b/lib/components/ChartLabel/index.ts new file mode 100644 index 0000000..a2f459b --- /dev/null +++ b/lib/components/ChartLabel/index.ts @@ -0,0 +1,4 @@ +export { + Label as ChartLabel, + type LabelProps as ChartLabelProps, +} from "recharts"; diff --git a/lib/main.ts b/lib/main.ts index 32a6381..eb5457f 100644 --- a/lib/main.ts +++ b/lib/main.ts @@ -46,3 +46,8 @@ export { Dot } from "./components/Dot"; export { defaultDotProps } from "./components/Dot/constants"; export { Legend, type LegendProps } from "./components/Legend"; +export { ChartLabel, type ChartLabelProps } from "./components/ChartLabel"; +export { + ChartLabelText, + type ChartLabelTextProps, +} from "./components/ChartLabel/ChartLabelText.tsx"; diff --git a/src/stories/AreaChart.stories.tsx b/src/stories/AreaChart.stories.tsx index 59ae499..d581c5e 100644 --- a/src/stories/AreaChart.stories.tsx +++ b/src/stories/AreaChart.stories.tsx @@ -16,6 +16,8 @@ import { ReferenceLine, XAxis, YAxis, + ChartLabel, + ChartLabelText, } from "../../lib/main.ts"; type Story = StoryObj; @@ -24,10 +26,10 @@ const data = [ { x: "Mon", y: 0 }, { x: "Tue", y: 30 }, { x: "Wed", y: 20 }, - { x: "Thu", y: 35 }, + { x: "Thu", y: 60 }, { x: "Fri", y: 27 }, { x: "Sat", y: 40 }, - { x: "Sun", y: 60 }, + { x: "Sun", y: 30 }, ]; const meta: Meta = { @@ -45,31 +47,48 @@ export default meta; export const Default: Story = { args: { data, + margin: { top: 20, left: 10, right: 10, bottom: 10 }, }, render: (args) => ( -
- - - - - - `${p.y} count`} />} - /> - {}} cursor={"pointer"} /> - } - dataKey="y" /> - ( -
-
x – day
-
y – users
-
+ + + + + ( + `${p.y} count`} + /> + )} + /> + b.y - a.y)[0].y} + > + ( + All time high )} - /> - -
+ > + + {}} cursor={"pointer"} /> + } + dataKey="y" + /> + ( +
+
x – day
+
y – users
+
+ )} + /> + ), }; diff --git a/src/tests/components/ChartLabelText.test.tsx b/src/tests/components/ChartLabelText.test.tsx new file mode 100644 index 0000000..21be339 --- /dev/null +++ b/src/tests/components/ChartLabelText.test.tsx @@ -0,0 +1,57 @@ +import { render, screen } from "../test-utils.ts"; +import { ChartLabelText } from "../../../lib/main.ts"; + +describe("Component ChartLabelText", () => { + it("should render when correct viewBox is provided", async () => { + render( + + test-label, + , + ); + expect(await screen.findByText("test-label")).toBeInTheDocument(); + }); + + it("should not render when no viewBox", () => { + render( + + test-label + , + ); + expect(screen.queryByText("test-label")).not.toBeInTheDocument(); + }); + + it("should not render when viewBox is PolarViewBox", () => { + render( + + test-label + , + ); + expect(screen.queryByText("test-label")).not.toBeInTheDocument(); + }); + + it("should render with custom classNames", async () => { + render( + + + test-label + + , + ); + expect(await screen.findByText("test-label")).toHaveClass("fill-red-500"); + }); + + it("should override default dy and dx", async () => { + render( + + + test-label + + , + ); + + const element = await screen.findByText("test-label"); + + expect(element).toHaveAttribute("dy", "12"); + expect(element).toHaveAttribute("dx", "34"); + }); +});