@arolariu/components
Version:
🎨 70+ beautiful, accessible React components built on Radix UI. TypeScript-first, tree-shakeable, SSR-ready. Perfect for modern web apps, design systems & rapid prototyping. Zero config, maximum flexibility! ⚡
176 lines (175 loc) • 9.47 kB
JavaScript
"use client";
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
import { cn } from "../../lib/utilities.js";
import { createContext, useContext, useId, useMemo } from "react";
import { Legend, ResponsiveContainer, Tooltip } from "recharts";
const THEMES = {
light: "",
dark: ".dark"
};
const ChartContext = /*#__PURE__*/ createContext(null);
function useChart() {
const context = useContext(ChartContext);
if (!context) throw new Error("useChart must be used within a <ChartContainer />");
return context;
}
function ChartContainer({ id, config, initialDimension = {
width: 320,
height: 200
}, className, children, ...props }) {
const uniqueId = useId();
const chartId = `chart-${id ?? uniqueId.replace(/:/g, "")}`;
return /*#__PURE__*/ jsx(ChartContext.Provider, {
value: {
config
},
children: /*#__PURE__*/ jsxs("div", {
"data-slot": "chart",
"data-chart": chartId,
className: cn("[&_.recharts-cartesian-axis-tick_text]:fill-muted-foreground [&_.recharts-cartesian-grid_line[stroke='#ccc']]:stroke-border/50 [&_.recharts-curve.recharts-tooltip-cursor]:stroke-border [&_.recharts-polar-grid_[stroke='#ccc']]:stroke-border [&_.recharts-radial-bar-background-sector]:fill-muted [&_.recharts-rectangle.recharts-tooltip-cursor]:fill-muted [&_.recharts-reference-line_[stroke='#ccc']]:stroke-border flex aspect-video justify-center text-xs [&_.recharts-dot[stroke='#fff']]:stroke-transparent [&_.recharts-layer]:outline-hidden [&_.recharts-sector]:outline-hidden [&_.recharts-sector[stroke='#fff']]:stroke-transparent [&_.recharts-surface]:outline-hidden", className),
...props,
children: [
/*#__PURE__*/ jsx(ChartStyle, {
id: chartId,
config: config
}),
/*#__PURE__*/ jsx(ResponsiveContainer, {
initialDimension: initialDimension,
children: children
})
]
})
});
}
const ChartStyle = ({ id, config })=>{
const colorConfig = Object.entries(config).filter(([, config])=>config.theme ?? config.color);
if (!colorConfig.length) return null;
return /*#__PURE__*/ jsx("style", {
dangerouslySetInnerHTML: {
__html: Object.entries(THEMES).map(([theme, prefix])=>`
${prefix} [data-chart=${id}] {
${colorConfig.map(([key, itemConfig])=>{
const color = itemConfig.theme?.[theme] ?? itemConfig.color;
return color ? ` --color-${key}: ${color};` : null;
}).join("\n")}
}
`).join("\n")
}
});
};
const ChartTooltip = Tooltip;
function ChartTooltipContent({ active, payload, className, indicator = "dot", hideLabel = false, hideIndicator = false, label, labelFormatter, labelClassName, formatter, color, nameKey, labelKey }) {
const { config } = useChart();
const tooltipLabel = useMemo(()=>{
if (hideLabel || !payload?.length) return null;
const [item] = payload;
const key = `${labelKey ?? item?.dataKey ?? item?.name ?? "value"}`;
const itemConfig = getPayloadConfigFromPayload(config, item, key);
const value = labelKey || "string" != typeof label ? itemConfig?.label : config[label]?.label ?? label;
if (labelFormatter) return /*#__PURE__*/ jsx("div", {
className: cn("font-medium", labelClassName),
children: labelFormatter(value, payload)
});
if (!value) return null;
return /*#__PURE__*/ jsx("div", {
className: cn("font-medium", labelClassName),
children: value
});
}, [
label,
labelFormatter,
payload,
hideLabel,
labelClassName,
config,
labelKey
]);
if (!active || !payload?.length) return null;
const nestLabel = 1 === payload.length && "dot" !== indicator;
return /*#__PURE__*/ jsxs("div", {
className: cn("border-border/50 bg-background grid min-w-[8rem] items-start gap-1.5 rounded-lg border px-2.5 py-1.5 text-xs shadow-xl", className),
children: [
nestLabel ? null : tooltipLabel,
/*#__PURE__*/ jsx("div", {
className: "grid gap-1.5",
children: payload.filter((item)=>"none" !== item.type).map((item, index)=>{
const key = `${nameKey ?? item.name ?? item.dataKey ?? "value"}`;
const itemConfig = getPayloadConfigFromPayload(config, item, key);
const indicatorColor = color ?? item.payload?.fill ?? item.color;
return /*#__PURE__*/ jsx("div", {
className: cn("[&>svg]:text-muted-foreground flex w-full flex-wrap items-stretch gap-2 [&>svg]:h-2.5 [&>svg]:w-2.5", "dot" === indicator && "items-center"),
children: formatter && item?.value !== void 0 && item.name ? formatter(item.value, item.name, item, index, item.payload) : /*#__PURE__*/ jsxs(Fragment, {
children: [
itemConfig?.icon ? /*#__PURE__*/ jsx(itemConfig.icon, {}) : !hideIndicator && /*#__PURE__*/ jsx("div", {
className: cn("shrink-0 rounded-[2px] border-(--color-border) bg-(--color-bg)", {
"h-2.5 w-2.5": "dot" === indicator,
"w-1": "line" === indicator,
"w-0 border-[1.5px] border-dashed bg-transparent": "dashed" === indicator,
"my-0.5": nestLabel && "dashed" === indicator
}),
style: {
"--color-bg": indicatorColor,
"--color-border": indicatorColor
}
}),
/*#__PURE__*/ jsxs("div", {
className: cn("flex flex-1 justify-between leading-none", nestLabel ? "items-end" : "items-center"),
children: [
/*#__PURE__*/ jsxs("div", {
className: "grid gap-1.5",
children: [
nestLabel ? tooltipLabel : null,
/*#__PURE__*/ jsx("span", {
className: "text-muted-foreground",
children: itemConfig?.label ?? item.name
})
]
}),
null != item.value && /*#__PURE__*/ jsx("span", {
className: "text-foreground font-mono font-medium tabular-nums",
children: "number" == typeof item.value ? item.value.toLocaleString() : String(item.value)
})
]
})
]
})
}, index);
})
})
]
});
}
const ChartLegend = Legend;
function ChartLegendContent({ className, hideIcon = false, nameKey, payload, verticalAlign }) {
const { config } = useChart();
if (!payload?.length) return null;
return /*#__PURE__*/ jsx("div", {
className: cn("flex items-center justify-center gap-4", "top" === verticalAlign ? "pb-3" : "pt-3", className),
children: payload.filter((item)=>"none" !== item.type).map((item)=>{
const key = `${nameKey ?? item.dataKey ?? "value"}`;
const itemConfig = getPayloadConfigFromPayload(config, item, key);
return /*#__PURE__*/ jsxs("div", {
className: cn("[&>svg]:text-muted-foreground flex items-center gap-1.5 [&>svg]:h-3 [&>svg]:w-3"),
children: [
itemConfig?.icon && !hideIcon ? /*#__PURE__*/ jsx(itemConfig.icon, {}) : /*#__PURE__*/ jsx("div", {
className: "h-2 w-2 shrink-0 rounded-[2px]",
style: {
backgroundColor: item.color
}
}),
itemConfig?.label
]
}, item.value);
})
});
}
function getPayloadConfigFromPayload(config, payload, key) {
if ("object" != typeof payload || null === payload) return;
const payloadPayload = "payload" in payload && "object" == typeof payload.payload && null !== payload.payload ? payload.payload : void 0;
let configLabelKey = key;
if (key in payload && "string" == typeof payload[key]) configLabelKey = payload[key];
else if (payloadPayload && key in payloadPayload && "string" == typeof payloadPayload[key]) configLabelKey = payloadPayload[key];
return configLabelKey in config ? config[configLabelKey] : config[key];
}
export { ChartContainer, ChartLegend, ChartLegendContent, ChartStyle, ChartTooltip, ChartTooltipContent };
//# sourceMappingURL=chart.js.map