UNPKG

@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
"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