@customafk/lunas-ui 0.2.62 → 0.2.63
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/dist/features/charts/index.cjs +2 -0
- package/dist/features/charts/index.cjs.map +1 -0
- package/dist/features/charts/index.d.cts +349 -0
- package/dist/features/charts/index.d.mts +349 -0
- package/dist/features/charts/index.mjs +2 -0
- package/dist/features/charts/index.mjs.map +1 -0
- package/dist/index.cjs +1 -1
- package/dist/index.d.cts +4 -2
- package/dist/index.d.mts +4 -2
- package/dist/index.mjs +1 -1
- package/dist/{resizable-CNIYTd7k.d.cts → resizable-BLfxHCf4.d.cts} +2 -2
- package/dist/{resizable-CNIYTd7k.d.mts → resizable-BLfxHCf4.d.mts} +2 -2
- package/dist/ui/chart.cjs +4 -0
- package/dist/ui/chart.cjs.map +1 -0
- package/dist/ui/chart.d.cts +80 -0
- package/dist/ui/chart.d.mts +80 -0
- package/dist/ui/chart.mjs +4 -0
- package/dist/ui/chart.mjs.map +1 -0
- package/dist/ui/resizable.d.cts +1 -1
- package/dist/ui/resizable.d.mts +1 -1
- package/package.json +11 -1
- package/styles/theme.css +8 -5
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require("../../ui/chart.cjs");let t=require("react"),n=require("@customafk/react-toolkit/utils"),r=require("react/jsx-runtime"),i=require("recharts");const a=e=>`var(--chart-${(e%8+8)%8+1})`,o=(e,t=`en-US`)=>new Intl.NumberFormat(t,{notation:`compact`,maximumFractionDigits:1}).format(e),s=(e,t=`USD`,n=`en-US`)=>new Intl.NumberFormat(n,{style:`currency`,currency:t,notation:Math.abs(e)>=1e4?`compact`:`standard`,maximumFractionDigits:+(Math.abs(e)>=1e4)}).format(e),c=(e,t=`en-US`)=>new Intl.NumberFormat(t,{style:`percent`,maximumFractionDigits:1}).format(e),l=(e,t=`en-US`)=>{let n=e instanceof Date?e:new Date(e);return Number.isNaN(n.getTime())?String(e):n.toLocaleDateString(t,{month:`short`,day:`numeric`})},u=({data:s,showConversionRates:l=!0,valueFormatter:u=o,className:d,animate:f=!0,height:p})=>{let{chartData:m,config:h}=(0,t.useMemo)(()=>{let e=s[0]?.value??0,t=s.map((t,n)=>{let r=e===0?0:t.value/e,i=l?`${u(t.value)} (${c(r)})`:u(t.value);return{...t,key:t.key||t.name.toLowerCase().replace(/[^a-z0-9]+/g,`-`),fill:t.color||a(n),valueLabel:i}});return{chartData:t,config:Object.fromEntries(t.map(e=>[e.key,{label:e.name,color:e.fill}]))}},[s,l,u]);return(0,r.jsx)(e.ChartContainer,{"data-slot":`conversion-funnel-chart`,config:h,className:(0,n.cn)(`w-full`,d),style:p===void 0?void 0:{height:p,aspectRatio:`auto`},children:(0,r.jsxs)(i.FunnelChart,{margin:{top:8,right:120,bottom:8,left:120},children:[(0,r.jsx)(e.ChartTooltip,{content:(0,r.jsx)(e.ChartTooltipContent,{nameKey:`key`,hideLabel:!0})}),(0,r.jsxs)(i.Funnel,{dataKey:`value`,data:m,isAnimationActive:f,children:[(0,r.jsx)(i.LabelList,{dataKey:`name`,position:`left`,offset:12,className:`fill-muted-strong`,fontSize:12}),(0,r.jsx)(i.LabelList,{dataKey:`valueLabel`,position:`right`,offset:12,className:`fill-text-positive-strong font-number`,fontSize:12})]})]})})},d=e=>e.key||e.name.toLowerCase().replace(/[^a-z0-9]+/g,`-`),f=({data:s,centerLabel:c,centerValueFormatter:l=o,totalValue:u,showLegend:f=!0,showCenterTotal:p=!0,className:m,animate:h=!0,height:g})=>{let{chartData:_,config:v,total:y}=(0,t.useMemo)(()=>{let e=s.map((e,t)=>({...e,key:d(e),fill:e.color||a(t)}));return{chartData:e,config:Object.fromEntries(e.map(e=>[e.key,{label:e.name,color:e.fill}])),total:u??s.reduce((e,t)=>e+t.value,0)}},[s,u]);return(0,r.jsx)(e.ChartContainer,{"data-slot":`donut-chart`,config:v,className:(0,n.cn)(`mx-auto`,g===void 0&&`aspect-square`,m),style:g===void 0?void 0:{height:g,aspectRatio:`auto`},children:(0,r.jsxs)(i.PieChart,{children:[(0,r.jsx)(e.ChartTooltip,{cursor:!1,content:(0,r.jsx)(e.ChartTooltipContent,{nameKey:`key`,hideLabel:!0})}),(0,r.jsx)(i.Pie,{data:_,dataKey:`value`,nameKey:`key`,innerRadius:`60%`,strokeWidth:5,isAnimationActive:h,children:p&&(0,r.jsx)(i.Label,{content:({viewBox:e})=>!e||!(`cx`in e)||!(`cy`in e)?null:(0,r.jsxs)(`text`,{x:e.cx,y:e.cy,textAnchor:`middle`,dominantBaseline:`middle`,children:[(0,r.jsx)(`tspan`,{x:e.cx,y:e.cy,className:`fill-text-positive-strong font-number text-2xl font-bold`,children:l(y)}),c&&(0,r.jsx)(`tspan`,{x:e.cx,y:(e.cy||0)+22,className:`fill-muted text-xs`,children:c})]})})}),f&&(0,r.jsx)(e.ChartLegend,{content:(0,r.jsx)(e.ChartLegendContent,{nameKey:`key`})})]})})},p=({data:o,dataKey:s=`orders`,label:c=`Orders`,statuses:u,color:d=`var(--chart-1)`,valueFormatter:f=e=>e.toLocaleString(`en-US`),dateFormatter:p=l,showLegend:m=!!u,showGrid:h=!0,className:g,animate:_=!0,height:v})=>(0,r.jsx)(e.ChartContainer,{"data-slot":`orders-bar-chart`,config:(0,t.useMemo)(()=>u?Object.fromEntries(u.map((e,t)=>[e.key,{label:e.label,color:e.color||a(t)}])):{[s]:{label:c,color:d}},[u,s,c,d]),className:(0,n.cn)(`w-full`,g),style:v===void 0?void 0:{height:v,aspectRatio:`auto`},children:(0,r.jsxs)(i.BarChart,{data:o,margin:{top:8,right:12,bottom:0,left:12},children:[h&&(0,r.jsx)(i.CartesianGrid,{vertical:!1}),(0,r.jsx)(i.XAxis,{dataKey:`date`,tickLine:!1,axisLine:!1,tickMargin:8,tickFormatter:p}),(0,r.jsx)(i.YAxis,{tickLine:!1,axisLine:!1,tickMargin:8,width:48,allowDecimals:!1,tickFormatter:f}),(0,r.jsx)(e.ChartTooltip,{content:(0,r.jsx)(e.ChartTooltipContent,{labelFormatter:(e,t)=>{let n=t?.[0]?.payload?.date;return n?p(n):null}})}),u?u.map((e,t)=>(0,r.jsx)(i.Bar,{dataKey:e.key,stackId:`orders`,fill:e.color||a(t),radius:t===u.length-1?[4,4,0,0]:[0,0,0,0],isAnimationActive:_},e.key)):(0,r.jsx)(i.Bar,{dataKey:s,fill:d,radius:[4,4,0,0],isAnimationActive:_}),m&&(0,r.jsx)(e.ChartLegend,{content:(0,r.jsx)(e.ChartLegendContent,{})})]})}),m=({data:a,label:o=`Revenue`,comparisonLabel:c=`Previous period`,showComparison:u=!1,color:d=`var(--chart-1)`,comparisonColor:f=`var(--chart-8)`,valueFormatter:p=e=>s(e),dateFormatter:m=l,showLegend:h=u,showGrid:g=!0,className:_,animate:v=!0,height:y})=>{let b=(0,t.useId)(),x=(0,t.useMemo)(()=>({value:{label:o,color:d},...u?{previousValue:{label:c,color:f}}:{}}),[o,d,u,c,f]);return(0,r.jsx)(e.ChartContainer,{"data-slot":`revenue-area-chart`,config:x,className:(0,n.cn)(`w-full`,_),style:y===void 0?void 0:{height:y,aspectRatio:`auto`},children:(0,r.jsxs)(i.AreaChart,{data:a,margin:{top:8,right:12,bottom:0,left:12},children:[(0,r.jsxs)(`defs`,{children:[(0,r.jsxs)(`linearGradient`,{id:`${b}-value`,x1:`0`,y1:`0`,x2:`0`,y2:`1`,children:[(0,r.jsx)(`stop`,{offset:`5%`,stopColor:d,stopOpacity:.6}),(0,r.jsx)(`stop`,{offset:`95%`,stopColor:d,stopOpacity:.05})]}),(0,r.jsxs)(`linearGradient`,{id:`${b}-previous`,x1:`0`,y1:`0`,x2:`0`,y2:`1`,children:[(0,r.jsx)(`stop`,{offset:`5%`,stopColor:f,stopOpacity:.3}),(0,r.jsx)(`stop`,{offset:`95%`,stopColor:f,stopOpacity:.02})]})]}),g&&(0,r.jsx)(i.CartesianGrid,{vertical:!1}),(0,r.jsx)(i.XAxis,{dataKey:`date`,tickLine:!1,axisLine:!1,tickMargin:8,tickFormatter:m}),(0,r.jsx)(i.YAxis,{tickLine:!1,axisLine:!1,tickMargin:8,width:64,tickFormatter:p}),(0,r.jsx)(e.ChartTooltip,{cursor:!1,content:(0,r.jsx)(e.ChartTooltipContent,{labelFormatter:(e,t)=>{let n=t?.[0]?.payload?.date;return n?m(n):null},formatter:(e,t,n)=>(0,r.jsxs)(r.Fragment,{children:[(0,r.jsx)(`div`,{className:`size-2.5 shrink-0 rounded-[2px]`,style:{backgroundColor:n.color}}),(0,r.jsx)(`span`,{className:`text-muted`,children:x[String(t)]?.label||t}),(0,r.jsx)(`span`,{className:`text-text-positive-strong font-number ml-auto font-medium tabular-nums`,children:p(Number(e))})]})})}),u&&(0,r.jsx)(i.Area,{type:`natural`,dataKey:`previousValue`,stroke:f,strokeWidth:2,strokeDasharray:`4 4`,fill:`url(#${b}-previous)`,isAnimationActive:v}),(0,r.jsx)(i.Area,{type:`natural`,dataKey:`value`,stroke:d,strokeWidth:2,fill:`url(#${b}-value)`,isAnimationActive:v}),h&&(0,r.jsx)(e.ChartLegend,{content:(0,r.jsx)(e.ChartLegendContent,{})})]})})},h=({data:a,revenueLabel:o=`Revenue`,ordersLabel:c=`Orders`,revenueColor:u=`var(--chart-1)`,ordersColor:d=`var(--chart-4)`,revenueFormatter:f=e=>s(e),ordersFormatter:p=e=>e.toLocaleString(`en-US`),dateFormatter:m=l,showLegend:h=!0,showGrid:g=!0,className:_,animate:v=!0,height:y})=>{let b=(0,t.useMemo)(()=>({revenue:{label:o,color:u},orders:{label:c,color:d}}),[o,u,c,d]);return(0,r.jsx)(e.ChartContainer,{"data-slot":`revenue-orders-composed-chart`,config:b,className:(0,n.cn)(`w-full`,_),style:y===void 0?void 0:{height:y,aspectRatio:`auto`},children:(0,r.jsxs)(i.ComposedChart,{data:a,margin:{top:8,right:12,bottom:0,left:12},children:[g&&(0,r.jsx)(i.CartesianGrid,{vertical:!1}),(0,r.jsx)(i.XAxis,{dataKey:`date`,tickLine:!1,axisLine:!1,tickMargin:8,tickFormatter:m}),(0,r.jsx)(i.YAxis,{yAxisId:`revenue`,tickLine:!1,axisLine:!1,tickMargin:8,width:64,tickFormatter:f}),(0,r.jsx)(i.YAxis,{yAxisId:`orders`,orientation:`right`,tickLine:!1,axisLine:!1,tickMargin:8,width:48,allowDecimals:!1,tickFormatter:p}),(0,r.jsx)(e.ChartTooltip,{content:(0,r.jsx)(e.ChartTooltipContent,{labelFormatter:(e,t)=>{let n=t?.[0]?.payload?.date;return n?m(n):null},formatter:(e,t,n)=>(0,r.jsxs)(r.Fragment,{children:[(0,r.jsx)(`div`,{className:`size-2.5 shrink-0 rounded-[2px]`,style:{backgroundColor:n.color}}),(0,r.jsx)(`span`,{className:`text-muted`,children:b[String(t)]?.label||t}),(0,r.jsx)(`span`,{className:`text-text-positive-strong font-number ml-auto font-medium tabular-nums`,children:t===`revenue`?f(Number(e)):p(Number(e))})]})})}),(0,r.jsx)(i.Bar,{dataKey:`revenue`,yAxisId:`revenue`,fill:u,radius:[4,4,0,0],isAnimationActive:v}),(0,r.jsx)(i.Line,{type:`natural`,dataKey:`orders`,yAxisId:`orders`,stroke:d,strokeWidth:2,dot:!1,isAnimationActive:v}),h&&(0,r.jsx)(e.ChartLegend,{content:(0,r.jsx)(e.ChartLegendContent,{})})]})})},g=({value:a,target:o,label:s=`Target`,valueFormatter:l=(e,t)=>c(t===0?0:e/t),color:u=`var(--chart-1)`,className:d,animate:f=!0,height:p})=>{let m=(0,t.useMemo)(()=>[{name:`progress`,value:Math.min(Math.max(a,0),o),fill:u}],[a,o,u]);return(0,r.jsx)(e.ChartContainer,{"data-slot":`sales-target-radial-chart`,config:(0,t.useMemo)(()=>({progress:{label:s,color:u}}),[s,u]),className:(0,n.cn)(`mx-auto`,p===void 0&&`aspect-square`,d),style:p===void 0?void 0:{height:p,aspectRatio:`auto`},children:(0,r.jsxs)(i.RadialBarChart,{data:m,startAngle:90,endAngle:-270,innerRadius:`75%`,outerRadius:`100%`,children:[(0,r.jsx)(i.PolarAngleAxis,{type:`number`,domain:[0,o],angleAxisId:0,tick:!1}),(0,r.jsx)(i.RadialBar,{dataKey:`value`,angleAxisId:0,background:!0,cornerRadius:10,isAnimationActive:f}),(0,r.jsx)(i.PolarRadiusAxis,{tick:!1,tickLine:!1,axisLine:!1,children:(0,r.jsx)(i.Label,{content:({viewBox:e})=>!e||!(`cx`in e)||!(`cy`in e)?null:(0,r.jsxs)(`text`,{x:e.cx,y:e.cy,textAnchor:`middle`,dominantBaseline:`middle`,children:[(0,r.jsx)(`tspan`,{x:e.cx,y:e.cy,className:`fill-text-positive-strong font-number text-3xl font-bold`,children:l(a,o)}),(0,r.jsx)(`tspan`,{x:e.cx,y:(e.cy||0)+24,className:`fill-muted text-xs`,children:s})]})})})]})})},_={up:`var(--success)`,down:`var(--danger)`,neutral:`var(--chart-1)`},v=({data:e,type:a=`area`,trend:o=`neutral`,color:s,height:c=40,animate:l=!0,className:u})=>{let d=(0,t.useId)(),f=s||_[o],p=(0,t.useMemo)(()=>e.map(e=>typeof e==`number`?{value:e}:e),[e]),m={top:2,right:0,bottom:2,left:0};return(0,r.jsx)(`div`,{"data-slot":`sparkline-chart`,className:(0,n.cn)(`w-full`,u),style:{height:c},children:(0,r.jsx)(i.ResponsiveContainer,{children:a===`line`?(0,r.jsx)(i.LineChart,{data:p,margin:m,children:(0,r.jsx)(i.Line,{type:`natural`,dataKey:`value`,stroke:f,strokeWidth:2,dot:!1,isAnimationActive:l})}):(0,r.jsxs)(i.AreaChart,{data:p,margin:m,children:[(0,r.jsx)(`defs`,{children:(0,r.jsxs)(`linearGradient`,{id:d,x1:`0`,y1:`0`,x2:`0`,y2:`1`,children:[(0,r.jsx)(`stop`,{offset:`5%`,stopColor:f,stopOpacity:.4}),(0,r.jsx)(`stop`,{offset:`95%`,stopColor:f,stopOpacity:.05})]})}),(0,r.jsx)(i.Area,{type:`natural`,dataKey:`value`,stroke:f,strokeWidth:2,fill:`url(#${d})`,isAnimationActive:l})]})})})},y=({data:a,label:s=`Sales`,maxItems:c=8,color:l=`var(--chart-1)`,valueFormatter:u=o,showValueLabels:d=!0,className:f,animate:p=!0,height:m})=>{let h=(0,t.useMemo)(()=>[...a].sort((e,t)=>t.value-e.value).slice(0,c),[a,c]);return(0,r.jsx)(e.ChartContainer,{"data-slot":`top-products-bar-chart`,config:(0,t.useMemo)(()=>({value:{label:s,color:l}}),[s,l]),className:(0,n.cn)(`w-full`,f),style:m===void 0?void 0:{height:m,aspectRatio:`auto`},children:(0,r.jsxs)(i.BarChart,{data:h,layout:`vertical`,margin:{top:0,right:d?48:12,bottom:0,left:12},children:[(0,r.jsx)(i.XAxis,{type:`number`,dataKey:`value`,hide:!0}),(0,r.jsx)(i.YAxis,{type:`category`,dataKey:`name`,tickLine:!1,axisLine:!1,tickMargin:8,width:120}),(0,r.jsx)(e.ChartTooltip,{cursor:!1,content:(0,r.jsx)(e.ChartTooltipContent,{hideLabel:!0})}),(0,r.jsx)(i.Bar,{dataKey:`value`,fill:l,radius:4,isAnimationActive:p,children:d&&(0,r.jsx)(i.LabelList,{dataKey:`value`,position:`right`,offset:8,className:`fill-muted-strong`,fontSize:12,formatter:e=>u(Number(e))})})]})})};exports.ConversionFunnelChart=u,exports.DonutChart=f,exports.OrdersBarChart=p,exports.RevenueAreaChart=m,exports.RevenueOrdersComposedChart=h,exports.SalesTargetRadialChart=g,exports.SparklineChart=v,exports.TopProductsBarChart=y,exports.formatCompactNumber=o,exports.formatCurrency=s,exports.formatPercent=c,exports.getChartColor=a,exports.toDateLabel=l;
|
|
2
|
+
//# sourceMappingURL=index.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.cjs","names":["ChartContainer","FunnelChart","ChartTooltip","ChartTooltipContent","Funnel","LabelList","ChartContainer","PieChart","ChartTooltip","ChartTooltipContent","Pie","Label","ChartLegend","ChartLegendContent","ChartContainer","BarChart","CartesianGrid","XAxis","YAxis","ChartTooltip","ChartTooltipContent","Bar","ChartLegend","ChartLegendContent","ChartContainer","AreaChart","CartesianGrid","XAxis","YAxis","ChartTooltip","ChartTooltipContent","Area","ChartLegend","ChartLegendContent","ChartContainer","ComposedChart","CartesianGrid","XAxis","YAxis","ChartTooltip","ChartTooltipContent","Bar","Line","ChartLegend","ChartLegendContent","ChartContainer","RadialBarChart","PolarAngleAxis","RadialBar","PolarRadiusAxis","Label","ResponsiveContainer","LineChart","Line","AreaChart","Area","ChartContainer","BarChart","XAxis","YAxis","ChartTooltip","ChartTooltipContent","Bar","LabelList"],"sources":["../../../packages/components/features/charts/utils.ts","../../../packages/components/features/charts/components/conversion-funnel-chart.tsx","../../../packages/components/features/charts/components/donut-chart.tsx","../../../packages/components/features/charts/components/orders-bar-chart.tsx","../../../packages/components/features/charts/components/revenue-area-chart.tsx","../../../packages/components/features/charts/components/revenue-orders-composed-chart.tsx","../../../packages/components/features/charts/components/sales-target-radial-chart.tsx","../../../packages/components/features/charts/components/sparkline-chart.tsx","../../../packages/components/features/charts/components/top-products-bar-chart.tsx"],"sourcesContent":["const CHART_COLOR_COUNT = 8;\n\n/** Cycles through the eight `--chart-N` theme palette variables. */\nexport const getChartColor = (index: number): string => `var(--chart-${(((index % CHART_COLOR_COUNT) + CHART_COLOR_COUNT) % CHART_COLOR_COUNT) + 1})`;\n\nexport const formatCompactNumber = (value: number, locale = 'en-US'): string =>\n new Intl.NumberFormat(locale, { notation: 'compact', maximumFractionDigits: 1 }).format(value);\n\nexport const formatCurrency = (value: number, currency = 'USD', locale = 'en-US'): string =>\n new Intl.NumberFormat(locale, {\n style: 'currency',\n currency,\n notation: Math.abs(value) >= 10_000 ? 'compact' : 'standard',\n maximumFractionDigits: Math.abs(value) >= 10_000 ? 1 : 0,\n }).format(value);\n\nexport const formatPercent = (value: number, locale = 'en-US'): string =>\n new Intl.NumberFormat(locale, { style: 'percent', maximumFractionDigits: 1 }).format(value);\n\nexport const toDateLabel = (date: string | Date, locale = 'en-US'): string => {\n const parsed = date instanceof Date ? date : new Date(date);\n if (Number.isNaN(parsed.getTime())) return String(date);\n return parsed.toLocaleDateString(locale, { month: 'short', day: 'numeric' });\n};\n","'use client';\n\nimport { useMemo } from 'react';\n\nimport { cn } from '@customafk/react-toolkit/utils';\n\nimport { type ChartConfig, ChartContainer, ChartTooltip, ChartTooltipContent } from '@/components/ui/chart';\n\nimport { Funnel, FunnelChart, LabelList } from 'recharts';\nimport type { BaseChartProps, NamedValue } from '../types';\nimport { formatCompactNumber, formatPercent, getChartColor } from '../utils';\n\nexport type FunnelStage = NamedValue & {\n /** Config key; derived from `name` when omitted. */\n key?: string;\n color?: string;\n};\n\nexport type ConversionFunnelChartProps = BaseChartProps & {\n /** Funnel stages ordered top (widest) to bottom. */\n data: FunnelStage[];\n /** Appends each stage's percentage of the first stage. Defaults to `true`. */\n showConversionRates?: boolean;\n valueFormatter?: (value: number) => string;\n};\n\n/**\n * A conversion funnel for the ecommerce purchase journey — sessions, product views, carts,\n * checkouts, purchases — with per-stage conversion rates against the first stage.\n *\n * @example\n * ```tsx\n * import { ConversionFunnelChart } from '@customafk/lunas-ui/features/charts';\n *\n * <ConversionFunnelChart\n * data={[\n * { name: 'Sessions', value: 50000 },\n * { name: 'Product views', value: 32000 },\n * { name: 'Added to cart', value: 8400 },\n * { name: 'Purchased', value: 2900 },\n * ]}\n * />\n * ```\n */\nexport const ConversionFunnelChart = ({\n data,\n showConversionRates = true,\n valueFormatter = formatCompactNumber,\n className,\n animate = true,\n height,\n}: ConversionFunnelChartProps) => {\n const { chartData, config } = useMemo(() => {\n const first = data[0]?.value ?? 0;\n const entries = data.map((stage, index) => {\n const rate = first === 0 ? 0 : stage.value / first;\n const valueLabel = showConversionRates ? `${valueFormatter(stage.value)} (${formatPercent(rate)})` : valueFormatter(stage.value);\n return {\n ...stage,\n key: stage.key || stage.name.toLowerCase().replace(/[^a-z0-9]+/g, '-'),\n fill: stage.color || getChartColor(index),\n valueLabel,\n };\n });\n const chartConfig: ChartConfig = Object.fromEntries(entries.map(entry => [entry.key, { label: entry.name, color: entry.fill }]));\n return { chartData: entries, config: chartConfig };\n }, [data, showConversionRates, valueFormatter]);\n\n return (\n <ChartContainer\n data-slot=\"conversion-funnel-chart\"\n config={config}\n className={cn('w-full', className)}\n style={height !== undefined ? { height, aspectRatio: 'auto' } : undefined}\n >\n <FunnelChart margin={{ top: 8, right: 120, bottom: 8, left: 120 }}>\n <ChartTooltip content={<ChartTooltipContent nameKey=\"key\" hideLabel />} />\n <Funnel dataKey=\"value\" data={chartData} isAnimationActive={animate}>\n <LabelList dataKey=\"name\" position=\"left\" offset={12} className=\"fill-muted-strong\" fontSize={12} />\n <LabelList dataKey=\"valueLabel\" position=\"right\" offset={12} className=\"fill-text-positive-strong font-number\" fontSize={12} />\n </Funnel>\n </FunnelChart>\n </ChartContainer>\n );\n};\n","'use client';\n\nimport { useMemo } from 'react';\n\nimport { cn } from '@customafk/react-toolkit/utils';\n\nimport { type ChartConfig, ChartContainer, ChartLegend, ChartLegendContent, ChartTooltip, ChartTooltipContent } from '@/components/ui/chart';\n\nimport { Label, Pie, PieChart } from 'recharts';\nimport type { BaseChartProps, NamedValue } from '../types';\nimport { formatCompactNumber, getChartColor } from '../utils';\n\nexport type DonutChartSegment = NamedValue & {\n /** Config key; derived from `name` when omitted. */\n key?: string;\n color?: string;\n};\n\nexport type DonutChartProps = BaseChartProps & {\n data: DonutChartSegment[];\n /** Text under the center total, e.g. `'Total sales'`. */\n centerLabel?: string;\n /** Formats the center total. Defaults to compact notation. */\n centerValueFormatter?: (total: number) => string;\n /** Overrides the computed segment sum shown in the center. */\n totalValue?: number;\n showLegend?: boolean;\n showCenterTotal?: boolean;\n};\n\nconst toKey = (segment: DonutChartSegment): string => segment.key || segment.name.toLowerCase().replace(/[^a-z0-9]+/g, '-');\n\n/**\n * A donut breakdown chart with a center total — category sales, traffic sources, payment methods.\n *\n * @example\n * ```tsx\n * import { DonutChart } from '@customafk/lunas-ui/features/charts';\n *\n * <DonutChart\n * data={[\n * { name: 'Fashion', value: 12400 },\n * { name: 'Electronics', value: 8200 },\n * ]}\n * centerLabel=\"Total sales\"\n * />\n * ```\n */\nexport const DonutChart = ({\n data,\n centerLabel,\n centerValueFormatter = formatCompactNumber,\n totalValue,\n showLegend = true,\n showCenterTotal = true,\n className,\n animate = true,\n height,\n}: DonutChartProps) => {\n const { chartData, config, total } = useMemo(() => {\n const entries = data.map((segment, index) => ({\n ...segment,\n key: toKey(segment),\n fill: segment.color || getChartColor(index),\n }));\n const chartConfig: ChartConfig = Object.fromEntries(entries.map(entry => [entry.key, { label: entry.name, color: entry.fill }]));\n return {\n chartData: entries,\n config: chartConfig,\n total: totalValue ?? data.reduce((sum, segment) => sum + segment.value, 0),\n };\n }, [data, totalValue]);\n\n return (\n <ChartContainer\n data-slot=\"donut-chart\"\n config={config}\n className={cn('mx-auto', height === undefined && 'aspect-square', className)}\n style={height !== undefined ? { height, aspectRatio: 'auto' } : undefined}\n >\n <PieChart>\n <ChartTooltip cursor={false} content={<ChartTooltipContent nameKey=\"key\" hideLabel />} />\n <Pie data={chartData} dataKey=\"value\" nameKey=\"key\" innerRadius=\"60%\" strokeWidth={5} isAnimationActive={animate}>\n {showCenterTotal && (\n <Label\n content={({ viewBox }) => {\n if (!viewBox || !('cx' in viewBox) || !('cy' in viewBox)) return null;\n return (\n <text x={viewBox.cx} y={viewBox.cy} textAnchor=\"middle\" dominantBaseline=\"middle\">\n <tspan x={viewBox.cx} y={viewBox.cy} className=\"fill-text-positive-strong font-number text-2xl font-bold\">\n {centerValueFormatter(total)}\n </tspan>\n {centerLabel && (\n <tspan x={viewBox.cx} y={(viewBox.cy || 0) + 22} className=\"fill-muted text-xs\">\n {centerLabel}\n </tspan>\n )}\n </text>\n );\n }}\n />\n )}\n </Pie>\n {showLegend && <ChartLegend content={<ChartLegendContent nameKey=\"key\" />} />}\n </PieChart>\n </ChartContainer>\n );\n};\n","'use client';\n\nimport { useMemo } from 'react';\n\nimport { cn } from '@customafk/react-toolkit/utils';\n\nimport { type ChartConfig, ChartContainer, ChartLegend, ChartLegendContent, ChartTooltip, ChartTooltipContent } from '@/components/ui/chart';\n\nimport { Bar, BarChart, CartesianGrid, XAxis, YAxis } from 'recharts';\nimport type { BaseChartProps, ChartSeries } from '../types';\nimport { getChartColor, toDateLabel } from '../utils';\n\nexport type OrdersBarChartProps = BaseChartProps & {\n data: Array<{ date: string | Date } & Record<string, unknown>>;\n /** Simple mode: the key holding each period's count. Defaults to `'orders'`. */\n dataKey?: string;\n /** Series label in simple mode. Defaults to `'Orders'`. */\n label?: string;\n /** Stacked mode: one series per order status; each `key` indexes into the data rows. */\n statuses?: ChartSeries[];\n color?: string;\n valueFormatter?: (value: number) => string;\n dateFormatter?: (date: string | Date) => string;\n /** Defaults to `true` when `statuses` is provided. */\n showLegend?: boolean;\n showGrid?: boolean;\n};\n\n/**\n * A bar chart for order volume per period — a single series by default, or stacked by order\n * status when `statuses` is provided.\n *\n * @example\n * ```tsx\n * import { OrdersBarChart } from '@customafk/lunas-ui/features/charts';\n *\n * <OrdersBarChart\n * data={[{ date: '2026-06-01', completed: 32, pending: 6, cancelled: 2 }]}\n * statuses={[\n * { key: 'completed', label: 'Completed' },\n * { key: 'pending', label: 'Pending' },\n * { key: 'cancelled', label: 'Cancelled' },\n * ]}\n * />\n * ```\n */\nexport const OrdersBarChart = ({\n data,\n dataKey = 'orders',\n label = 'Orders',\n statuses,\n color = 'var(--chart-1)',\n valueFormatter = value => value.toLocaleString('en-US'),\n dateFormatter = toDateLabel,\n showLegend = !!statuses,\n showGrid = true,\n className,\n animate = true,\n height,\n}: OrdersBarChartProps) => {\n const config = useMemo<ChartConfig>(() => {\n if (!statuses) return { [dataKey]: { label, color } };\n return Object.fromEntries(statuses.map((status, index) => [status.key, { label: status.label, color: status.color || getChartColor(index) }]));\n }, [statuses, dataKey, label, color]);\n\n return (\n <ChartContainer\n data-slot=\"orders-bar-chart\"\n config={config}\n className={cn('w-full', className)}\n style={height !== undefined ? { height, aspectRatio: 'auto' } : undefined}\n >\n <BarChart data={data} margin={{ top: 8, right: 12, bottom: 0, left: 12 }}>\n {showGrid && <CartesianGrid vertical={false} />}\n <XAxis dataKey=\"date\" tickLine={false} axisLine={false} tickMargin={8} tickFormatter={dateFormatter} />\n <YAxis tickLine={false} axisLine={false} tickMargin={8} width={48} allowDecimals={false} tickFormatter={valueFormatter} />\n <ChartTooltip\n content={\n <ChartTooltipContent\n labelFormatter={(_, payload) => {\n const date = payload?.[0]?.payload?.date;\n return date ? dateFormatter(date) : null;\n }}\n />\n }\n />\n {statuses ? (\n statuses.map((status, index) => (\n <Bar\n key={status.key}\n dataKey={status.key}\n stackId=\"orders\"\n fill={status.color || getChartColor(index)}\n radius={index === statuses.length - 1 ? [4, 4, 0, 0] : [0, 0, 0, 0]}\n isAnimationActive={animate}\n />\n ))\n ) : (\n <Bar dataKey={dataKey} fill={color} radius={[4, 4, 0, 0]} isAnimationActive={animate} />\n )}\n {showLegend && <ChartLegend content={<ChartLegendContent />} />}\n </BarChart>\n </ChartContainer>\n );\n};\n","'use client';\n\nimport { useId, useMemo } from 'react';\n\nimport { cn } from '@customafk/react-toolkit/utils';\n\nimport { type ChartConfig, ChartContainer, ChartLegend, ChartLegendContent, ChartTooltip, ChartTooltipContent } from '@/components/ui/chart';\n\nimport { Area, AreaChart, CartesianGrid, XAxis, YAxis } from 'recharts';\nimport type { BaseChartProps, TimeSeriesPoint } from '../types';\nimport { formatCurrency, toDateLabel } from '../utils';\n\nexport type RevenueAreaChartProps = BaseChartProps & {\n data: TimeSeriesPoint[];\n /** Series label. Defaults to `'Revenue'`. */\n label?: string;\n /** Comparison series label. Defaults to `'Previous period'`. */\n comparisonLabel?: string;\n /** Renders `previousValue` as a second, muted area series. */\n showComparison?: boolean;\n color?: string;\n comparisonColor?: string;\n /** Formats tooltip and Y-axis values. Defaults to compact currency. */\n valueFormatter?: (value: number) => string;\n dateFormatter?: (date: string | Date) => string;\n /** Defaults to `showComparison`. */\n showLegend?: boolean;\n showGrid?: boolean;\n};\n\n/**\n * A gradient area chart for revenue (or any currency metric) over time, with an optional\n * previous-period comparison series.\n *\n * @example\n * ```tsx\n * import { RevenueAreaChart } from '@customafk/lunas-ui/features/charts';\n *\n * <RevenueAreaChart\n * data={[\n * { date: '2026-06-01', value: 4200, previousValue: 3800 },\n * { date: '2026-06-02', value: 5100, previousValue: 4300 },\n * ]}\n * showComparison\n * />\n * ```\n */\nexport const RevenueAreaChart = ({\n data,\n label = 'Revenue',\n comparisonLabel = 'Previous period',\n showComparison = false,\n color = 'var(--chart-1)',\n comparisonColor = 'var(--chart-8)',\n valueFormatter = value => formatCurrency(value),\n dateFormatter = toDateLabel,\n showLegend = showComparison,\n showGrid = true,\n className,\n animate = true,\n height,\n}: RevenueAreaChartProps) => {\n const gradientId = useId();\n\n const config = useMemo<ChartConfig>(\n () => ({\n value: { label, color },\n ...(showComparison ? { previousValue: { label: comparisonLabel, color: comparisonColor } } : {}),\n }),\n [label, color, showComparison, comparisonLabel, comparisonColor]\n );\n\n return (\n <ChartContainer\n data-slot=\"revenue-area-chart\"\n config={config}\n className={cn('w-full', className)}\n style={height !== undefined ? { height, aspectRatio: 'auto' } : undefined}\n >\n <AreaChart data={data} margin={{ top: 8, right: 12, bottom: 0, left: 12 }}>\n <defs>\n <linearGradient id={`${gradientId}-value`} x1=\"0\" y1=\"0\" x2=\"0\" y2=\"1\">\n <stop offset=\"5%\" stopColor={color} stopOpacity={0.6} />\n <stop offset=\"95%\" stopColor={color} stopOpacity={0.05} />\n </linearGradient>\n <linearGradient id={`${gradientId}-previous`} x1=\"0\" y1=\"0\" x2=\"0\" y2=\"1\">\n <stop offset=\"5%\" stopColor={comparisonColor} stopOpacity={0.3} />\n <stop offset=\"95%\" stopColor={comparisonColor} stopOpacity={0.02} />\n </linearGradient>\n </defs>\n {showGrid && <CartesianGrid vertical={false} />}\n <XAxis dataKey=\"date\" tickLine={false} axisLine={false} tickMargin={8} tickFormatter={dateFormatter} />\n <YAxis tickLine={false} axisLine={false} tickMargin={8} width={64} tickFormatter={valueFormatter} />\n <ChartTooltip\n cursor={false}\n content={\n <ChartTooltipContent\n labelFormatter={(_, payload) => {\n const date = payload?.[0]?.payload?.date;\n return date ? dateFormatter(date) : null;\n }}\n formatter={(value, name, item) => (\n <>\n <div className=\"size-2.5 shrink-0 rounded-[2px]\" style={{ backgroundColor: item.color }} />\n <span className=\"text-muted\">{config[String(name)]?.label || name}</span>\n <span className=\"text-text-positive-strong font-number ml-auto font-medium tabular-nums\">{valueFormatter(Number(value))}</span>\n </>\n )}\n />\n }\n />\n {showComparison && (\n <Area\n type=\"natural\"\n dataKey=\"previousValue\"\n stroke={comparisonColor}\n strokeWidth={2}\n strokeDasharray=\"4 4\"\n fill={`url(#${gradientId}-previous)`}\n isAnimationActive={animate}\n />\n )}\n <Area type=\"natural\" dataKey=\"value\" stroke={color} strokeWidth={2} fill={`url(#${gradientId}-value)`} isAnimationActive={animate} />\n {showLegend && <ChartLegend content={<ChartLegendContent />} />}\n </AreaChart>\n </ChartContainer>\n );\n};\n","'use client';\n\nimport { useMemo } from 'react';\n\nimport { cn } from '@customafk/react-toolkit/utils';\n\nimport { type ChartConfig, ChartContainer, ChartLegend, ChartLegendContent, ChartTooltip, ChartTooltipContent } from '@/components/ui/chart';\n\nimport { Bar, CartesianGrid, ComposedChart, Line, XAxis, YAxis } from 'recharts';\nimport type { BaseChartProps } from '../types';\nimport { formatCurrency, toDateLabel } from '../utils';\n\nexport type RevenueOrdersPoint = {\n date: string | Date;\n revenue: number;\n orders: number;\n};\n\nexport type RevenueOrdersComposedChartProps = BaseChartProps & {\n data: RevenueOrdersPoint[];\n revenueLabel?: string;\n ordersLabel?: string;\n revenueColor?: string;\n ordersColor?: string;\n /** Formats the left (revenue) axis and tooltip values. Defaults to compact currency. */\n revenueFormatter?: (value: number) => string;\n /** Formats the right (orders) axis and tooltip values. */\n ordersFormatter?: (value: number) => string;\n dateFormatter?: (date: string | Date) => string;\n showLegend?: boolean;\n showGrid?: boolean;\n};\n\n/**\n * A dual-axis chart combining revenue bars (left axis, currency) with an orders line\n * (right axis, count) to correlate the two metrics per period.\n *\n * @example\n * ```tsx\n * import { RevenueOrdersComposedChart } from '@customafk/lunas-ui/features/charts';\n *\n * <RevenueOrdersComposedChart\n * data={[{ date: '2026-06-01', revenue: 12400, orders: 87 }]}\n * />\n * ```\n */\nexport const RevenueOrdersComposedChart = ({\n data,\n revenueLabel = 'Revenue',\n ordersLabel = 'Orders',\n revenueColor = 'var(--chart-1)',\n ordersColor = 'var(--chart-4)',\n revenueFormatter = value => formatCurrency(value),\n ordersFormatter = value => value.toLocaleString('en-US'),\n dateFormatter = toDateLabel,\n showLegend = true,\n showGrid = true,\n className,\n animate = true,\n height,\n}: RevenueOrdersComposedChartProps) => {\n const config = useMemo<ChartConfig>(\n () => ({\n revenue: { label: revenueLabel, color: revenueColor },\n orders: { label: ordersLabel, color: ordersColor },\n }),\n [revenueLabel, revenueColor, ordersLabel, ordersColor]\n );\n\n return (\n <ChartContainer\n data-slot=\"revenue-orders-composed-chart\"\n config={config}\n className={cn('w-full', className)}\n style={height !== undefined ? { height, aspectRatio: 'auto' } : undefined}\n >\n <ComposedChart data={data} margin={{ top: 8, right: 12, bottom: 0, left: 12 }}>\n {showGrid && <CartesianGrid vertical={false} />}\n <XAxis dataKey=\"date\" tickLine={false} axisLine={false} tickMargin={8} tickFormatter={dateFormatter} />\n <YAxis yAxisId=\"revenue\" tickLine={false} axisLine={false} tickMargin={8} width={64} tickFormatter={revenueFormatter} />\n <YAxis\n yAxisId=\"orders\"\n orientation=\"right\"\n tickLine={false}\n axisLine={false}\n tickMargin={8}\n width={48}\n allowDecimals={false}\n tickFormatter={ordersFormatter}\n />\n <ChartTooltip\n content={\n <ChartTooltipContent\n labelFormatter={(_, payload) => {\n const date = payload?.[0]?.payload?.date;\n return date ? dateFormatter(date) : null;\n }}\n formatter={(value, name, item) => (\n <>\n <div className=\"size-2.5 shrink-0 rounded-[2px]\" style={{ backgroundColor: item.color }} />\n <span className=\"text-muted\">{config[String(name)]?.label || name}</span>\n <span className=\"text-text-positive-strong font-number ml-auto font-medium tabular-nums\">\n {name === 'revenue' ? revenueFormatter(Number(value)) : ordersFormatter(Number(value))}\n </span>\n </>\n )}\n />\n }\n />\n <Bar dataKey=\"revenue\" yAxisId=\"revenue\" fill={revenueColor} radius={[4, 4, 0, 0]} isAnimationActive={animate} />\n <Line type=\"natural\" dataKey=\"orders\" yAxisId=\"orders\" stroke={ordersColor} strokeWidth={2} dot={false} isAnimationActive={animate} />\n {showLegend && <ChartLegend content={<ChartLegendContent />} />}\n </ComposedChart>\n </ChartContainer>\n );\n};\n","'use client';\n\nimport { useMemo } from 'react';\n\nimport { cn } from '@customafk/react-toolkit/utils';\n\nimport { type ChartConfig, ChartContainer } from '@/components/ui/chart';\n\nimport { Label, PolarAngleAxis, PolarRadiusAxis, RadialBar, RadialBarChart } from 'recharts';\nimport type { BaseChartProps } from '../types';\nimport { formatPercent } from '../utils';\n\nexport type SalesTargetRadialChartProps = BaseChartProps & {\n /** Current progress value, e.g. revenue to date. */\n value: number;\n /** The goal the value is measured against. */\n target: number;\n /** Text under the center figure. Defaults to `'Target'`. */\n label?: string;\n /** Formats the center figure. Defaults to percent-of-target. */\n valueFormatter?: (value: number, target: number) => string;\n color?: string;\n};\n\n/**\n * A radial gauge showing progress toward a sales target with the completion figure in the center.\n *\n * @example\n * ```tsx\n * import { SalesTargetRadialChart } from '@customafk/lunas-ui/features/charts';\n *\n * <SalesTargetRadialChart value={65_000} target={100_000} label=\"Monthly target\" />\n * ```\n */\nexport const SalesTargetRadialChart = ({\n value,\n target,\n label = 'Target',\n valueFormatter = (current, goal) => formatPercent(goal === 0 ? 0 : current / goal),\n color = 'var(--chart-1)',\n className,\n animate = true,\n height,\n}: SalesTargetRadialChartProps) => {\n const chartData = useMemo(() => [{ name: 'progress', value: Math.min(Math.max(value, 0), target), fill: color }], [value, target, color]);\n\n const config = useMemo<ChartConfig>(() => ({ progress: { label, color } }), [label, color]);\n\n return (\n <ChartContainer\n data-slot=\"sales-target-radial-chart\"\n config={config}\n className={cn('mx-auto', height === undefined && 'aspect-square', className)}\n style={height !== undefined ? { height, aspectRatio: 'auto' } : undefined}\n >\n <RadialBarChart data={chartData} startAngle={90} endAngle={-270} innerRadius=\"75%\" outerRadius=\"100%\">\n <PolarAngleAxis type=\"number\" domain={[0, target]} angleAxisId={0} tick={false} />\n <RadialBar dataKey=\"value\" angleAxisId={0} background cornerRadius={10} isAnimationActive={animate} />\n <PolarRadiusAxis tick={false} tickLine={false} axisLine={false}>\n <Label\n content={({ viewBox }) => {\n if (!viewBox || !('cx' in viewBox) || !('cy' in viewBox)) return null;\n return (\n <text x={viewBox.cx} y={viewBox.cy} textAnchor=\"middle\" dominantBaseline=\"middle\">\n <tspan x={viewBox.cx} y={viewBox.cy} className=\"fill-text-positive-strong font-number text-3xl font-bold\">\n {valueFormatter(value, target)}\n </tspan>\n <tspan x={viewBox.cx} y={(viewBox.cy || 0) + 24} className=\"fill-muted text-xs\">\n {label}\n </tspan>\n </text>\n );\n }}\n />\n </PolarRadiusAxis>\n </RadialBarChart>\n </ChartContainer>\n );\n};\n","'use client';\n\nimport { useId, useMemo } from 'react';\n\nimport { cn } from '@customafk/react-toolkit/utils';\n\nimport { Area, AreaChart, Line, LineChart, ResponsiveContainer } from 'recharts';\nimport type { ChartTrend } from '../types';\n\nconst TREND_COLORS: Record<ChartTrend, string> = {\n up: 'var(--success)',\n down: 'var(--danger)',\n neutral: 'var(--chart-1)',\n};\n\nexport type SparklineChartProps = {\n data: number[] | Array<{ value: number }>;\n /** Render style. Defaults to `'area'`. */\n type?: 'line' | 'area';\n /** Colors the series like the `Statistic` trend prop. Defaults to `'neutral'`. */\n trend?: ChartTrend;\n /** Explicit series color; overrides `trend`. */\n color?: string;\n /** Fixed height in px. Defaults to `40`. */\n height?: number;\n animate?: boolean;\n className?: string;\n};\n\n/**\n * A tiny, axis-less trend chart for KPI cards; pairs with the `Statistic` display component.\n *\n * @example\n * ```tsx\n * import { SparklineChart } from '@customafk/lunas-ui/features/charts';\n *\n * <SparklineChart data={[12, 18, 14, 26, 22, 31]} trend=\"up\" />\n * ```\n */\nexport const SparklineChart = ({ data, type = 'area', trend = 'neutral', color, height = 40, animate = true, className }: SparklineChartProps) => {\n const gradientId = useId();\n const seriesColor = color || TREND_COLORS[trend];\n\n const chartData = useMemo(() => data.map(point => (typeof point === 'number' ? { value: point } : point)), [data]);\n\n const margin = { top: 2, right: 0, bottom: 2, left: 0 };\n\n return (\n <div data-slot=\"sparkline-chart\" className={cn('w-full', className)} style={{ height }}>\n <ResponsiveContainer>\n {type === 'line' ? (\n <LineChart data={chartData} margin={margin}>\n <Line type=\"natural\" dataKey=\"value\" stroke={seriesColor} strokeWidth={2} dot={false} isAnimationActive={animate} />\n </LineChart>\n ) : (\n <AreaChart data={chartData} margin={margin}>\n <defs>\n <linearGradient id={gradientId} x1=\"0\" y1=\"0\" x2=\"0\" y2=\"1\">\n <stop offset=\"5%\" stopColor={seriesColor} stopOpacity={0.4} />\n <stop offset=\"95%\" stopColor={seriesColor} stopOpacity={0.05} />\n </linearGradient>\n </defs>\n <Area type=\"natural\" dataKey=\"value\" stroke={seriesColor} strokeWidth={2} fill={`url(#${gradientId})`} isAnimationActive={animate} />\n </AreaChart>\n )}\n </ResponsiveContainer>\n </div>\n );\n};\n","'use client';\n\nimport { useMemo } from 'react';\n\nimport { cn } from '@customafk/react-toolkit/utils';\n\nimport { type ChartConfig, ChartContainer, ChartTooltip, ChartTooltipContent } from '@/components/ui/chart';\n\nimport { Bar, BarChart, LabelList, XAxis, YAxis } from 'recharts';\nimport type { BaseChartProps, NamedValue } from '../types';\nimport { formatCompactNumber } from '../utils';\n\nexport type TopProductsBarChartProps = BaseChartProps & {\n data: NamedValue[];\n /** Series label. Defaults to `'Sales'`. */\n label?: string;\n /** Number of items shown after sorting descending. Defaults to `8`. */\n maxItems?: number;\n color?: string;\n valueFormatter?: (value: number) => string;\n /** Value labels at the end of each bar. Defaults to `true`. */\n showValueLabels?: boolean;\n};\n\n/**\n * A horizontal bar ranking chart — top products, best categories, top customers.\n *\n * @example\n * ```tsx\n * import { TopProductsBarChart } from '@customafk/lunas-ui/features/charts';\n *\n * <TopProductsBarChart\n * data={[\n * { name: 'Wireless Earbuds', value: 1245 },\n * { name: 'Smart Watch', value: 986 },\n * ]}\n * />\n * ```\n */\nexport const TopProductsBarChart = ({\n data,\n label = 'Sales',\n maxItems = 8,\n color = 'var(--chart-1)',\n valueFormatter = formatCompactNumber,\n showValueLabels = true,\n className,\n animate = true,\n height,\n}: TopProductsBarChartProps) => {\n const chartData = useMemo(() => [...data].sort((a, b) => b.value - a.value).slice(0, maxItems), [data, maxItems]);\n\n const config = useMemo<ChartConfig>(() => ({ value: { label, color } }), [label, color]);\n\n return (\n <ChartContainer\n data-slot=\"top-products-bar-chart\"\n config={config}\n className={cn('w-full', className)}\n style={height !== undefined ? { height, aspectRatio: 'auto' } : undefined}\n >\n <BarChart data={chartData} layout=\"vertical\" margin={{ top: 0, right: showValueLabels ? 48 : 12, bottom: 0, left: 12 }}>\n <XAxis type=\"number\" dataKey=\"value\" hide />\n <YAxis type=\"category\" dataKey=\"name\" tickLine={false} axisLine={false} tickMargin={8} width={120} />\n <ChartTooltip cursor={false} content={<ChartTooltipContent hideLabel />} />\n <Bar dataKey=\"value\" fill={color} radius={4} isAnimationActive={animate}>\n {showValueLabels && (\n <LabelList\n dataKey=\"value\"\n position=\"right\"\n offset={8}\n className=\"fill-muted-strong\"\n fontSize={12}\n formatter={(value: React.ReactNode) => valueFormatter(Number(value))}\n />\n )}\n </Bar>\n </BarChart>\n </ChartContainer>\n );\n};\n"],"mappings":"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"}
|
|
@@ -0,0 +1,349 @@
|
|
|
1
|
+
//#region packages/components/features/charts/types.d.ts
|
|
2
|
+
/** Trend direction shared with the `Statistic` display component. */
|
|
3
|
+
type ChartTrend = 'up' | 'down' | 'neutral';
|
|
4
|
+
type TimeSeriesPoint = {
|
|
5
|
+
date: string | Date;
|
|
6
|
+
value: number; /** Same-bucket value from the comparison period (enables the comparison series). */
|
|
7
|
+
previousValue?: number;
|
|
8
|
+
};
|
|
9
|
+
type ChartSeries = {
|
|
10
|
+
key: string;
|
|
11
|
+
label: string;
|
|
12
|
+
color?: string;
|
|
13
|
+
};
|
|
14
|
+
type NamedValue = {
|
|
15
|
+
name: string;
|
|
16
|
+
value: number;
|
|
17
|
+
};
|
|
18
|
+
/** Props shared by every prebuilt chart. */
|
|
19
|
+
type BaseChartProps = {
|
|
20
|
+
className?: string; /** Enable the recharts enter animation. Disable for deterministic tests. Defaults to `true`. */
|
|
21
|
+
animate?: boolean; /** Fixed height in px; otherwise the container's aspect-video ratio applies. */
|
|
22
|
+
height?: number;
|
|
23
|
+
};
|
|
24
|
+
//#endregion
|
|
25
|
+
//#region packages/components/features/charts/components/conversion-funnel-chart.d.ts
|
|
26
|
+
type FunnelStage = NamedValue & {
|
|
27
|
+
/** Config key; derived from `name` when omitted. */key?: string;
|
|
28
|
+
color?: string;
|
|
29
|
+
};
|
|
30
|
+
type ConversionFunnelChartProps = BaseChartProps & {
|
|
31
|
+
/** Funnel stages ordered top (widest) to bottom. */data: FunnelStage[]; /** Appends each stage's percentage of the first stage. Defaults to `true`. */
|
|
32
|
+
showConversionRates?: boolean;
|
|
33
|
+
valueFormatter?: (value: number) => string;
|
|
34
|
+
};
|
|
35
|
+
/**
|
|
36
|
+
* A conversion funnel for the ecommerce purchase journey — sessions, product views, carts,
|
|
37
|
+
* checkouts, purchases — with per-stage conversion rates against the first stage.
|
|
38
|
+
*
|
|
39
|
+
* @example
|
|
40
|
+
* ```tsx
|
|
41
|
+
* import { ConversionFunnelChart } from '@customafk/lunas-ui/features/charts';
|
|
42
|
+
*
|
|
43
|
+
* <ConversionFunnelChart
|
|
44
|
+
* data={[
|
|
45
|
+
* { name: 'Sessions', value: 50000 },
|
|
46
|
+
* { name: 'Product views', value: 32000 },
|
|
47
|
+
* { name: 'Added to cart', value: 8400 },
|
|
48
|
+
* { name: 'Purchased', value: 2900 },
|
|
49
|
+
* ]}
|
|
50
|
+
* />
|
|
51
|
+
* ```
|
|
52
|
+
*/
|
|
53
|
+
declare const ConversionFunnelChart: ({
|
|
54
|
+
data,
|
|
55
|
+
showConversionRates,
|
|
56
|
+
valueFormatter,
|
|
57
|
+
className,
|
|
58
|
+
animate,
|
|
59
|
+
height
|
|
60
|
+
}: ConversionFunnelChartProps) => import("react").JSX.Element;
|
|
61
|
+
//#endregion
|
|
62
|
+
//#region packages/components/features/charts/components/donut-chart.d.ts
|
|
63
|
+
type DonutChartSegment = NamedValue & {
|
|
64
|
+
/** Config key; derived from `name` when omitted. */key?: string;
|
|
65
|
+
color?: string;
|
|
66
|
+
};
|
|
67
|
+
type DonutChartProps = BaseChartProps & {
|
|
68
|
+
data: DonutChartSegment[]; /** Text under the center total, e.g. `'Total sales'`. */
|
|
69
|
+
centerLabel?: string; /** Formats the center total. Defaults to compact notation. */
|
|
70
|
+
centerValueFormatter?: (total: number) => string; /** Overrides the computed segment sum shown in the center. */
|
|
71
|
+
totalValue?: number;
|
|
72
|
+
showLegend?: boolean;
|
|
73
|
+
showCenterTotal?: boolean;
|
|
74
|
+
};
|
|
75
|
+
/**
|
|
76
|
+
* A donut breakdown chart with a center total — category sales, traffic sources, payment methods.
|
|
77
|
+
*
|
|
78
|
+
* @example
|
|
79
|
+
* ```tsx
|
|
80
|
+
* import { DonutChart } from '@customafk/lunas-ui/features/charts';
|
|
81
|
+
*
|
|
82
|
+
* <DonutChart
|
|
83
|
+
* data={[
|
|
84
|
+
* { name: 'Fashion', value: 12400 },
|
|
85
|
+
* { name: 'Electronics', value: 8200 },
|
|
86
|
+
* ]}
|
|
87
|
+
* centerLabel="Total sales"
|
|
88
|
+
* />
|
|
89
|
+
* ```
|
|
90
|
+
*/
|
|
91
|
+
declare const DonutChart: ({
|
|
92
|
+
data,
|
|
93
|
+
centerLabel,
|
|
94
|
+
centerValueFormatter,
|
|
95
|
+
totalValue,
|
|
96
|
+
showLegend,
|
|
97
|
+
showCenterTotal,
|
|
98
|
+
className,
|
|
99
|
+
animate,
|
|
100
|
+
height
|
|
101
|
+
}: DonutChartProps) => import("react").JSX.Element;
|
|
102
|
+
//#endregion
|
|
103
|
+
//#region packages/components/features/charts/components/orders-bar-chart.d.ts
|
|
104
|
+
type OrdersBarChartProps = BaseChartProps & {
|
|
105
|
+
data: Array<{
|
|
106
|
+
date: string | Date;
|
|
107
|
+
} & Record<string, unknown>>; /** Simple mode: the key holding each period's count. Defaults to `'orders'`. */
|
|
108
|
+
dataKey?: string; /** Series label in simple mode. Defaults to `'Orders'`. */
|
|
109
|
+
label?: string; /** Stacked mode: one series per order status; each `key` indexes into the data rows. */
|
|
110
|
+
statuses?: ChartSeries[];
|
|
111
|
+
color?: string;
|
|
112
|
+
valueFormatter?: (value: number) => string;
|
|
113
|
+
dateFormatter?: (date: string | Date) => string; /** Defaults to `true` when `statuses` is provided. */
|
|
114
|
+
showLegend?: boolean;
|
|
115
|
+
showGrid?: boolean;
|
|
116
|
+
};
|
|
117
|
+
/**
|
|
118
|
+
* A bar chart for order volume per period — a single series by default, or stacked by order
|
|
119
|
+
* status when `statuses` is provided.
|
|
120
|
+
*
|
|
121
|
+
* @example
|
|
122
|
+
* ```tsx
|
|
123
|
+
* import { OrdersBarChart } from '@customafk/lunas-ui/features/charts';
|
|
124
|
+
*
|
|
125
|
+
* <OrdersBarChart
|
|
126
|
+
* data={[{ date: '2026-06-01', completed: 32, pending: 6, cancelled: 2 }]}
|
|
127
|
+
* statuses={[
|
|
128
|
+
* { key: 'completed', label: 'Completed' },
|
|
129
|
+
* { key: 'pending', label: 'Pending' },
|
|
130
|
+
* { key: 'cancelled', label: 'Cancelled' },
|
|
131
|
+
* ]}
|
|
132
|
+
* />
|
|
133
|
+
* ```
|
|
134
|
+
*/
|
|
135
|
+
declare const OrdersBarChart: ({
|
|
136
|
+
data,
|
|
137
|
+
dataKey,
|
|
138
|
+
label,
|
|
139
|
+
statuses,
|
|
140
|
+
color,
|
|
141
|
+
valueFormatter,
|
|
142
|
+
dateFormatter,
|
|
143
|
+
showLegend,
|
|
144
|
+
showGrid,
|
|
145
|
+
className,
|
|
146
|
+
animate,
|
|
147
|
+
height
|
|
148
|
+
}: OrdersBarChartProps) => import("react").JSX.Element;
|
|
149
|
+
//#endregion
|
|
150
|
+
//#region packages/components/features/charts/components/revenue-area-chart.d.ts
|
|
151
|
+
type RevenueAreaChartProps = BaseChartProps & {
|
|
152
|
+
data: TimeSeriesPoint[]; /** Series label. Defaults to `'Revenue'`. */
|
|
153
|
+
label?: string; /** Comparison series label. Defaults to `'Previous period'`. */
|
|
154
|
+
comparisonLabel?: string; /** Renders `previousValue` as a second, muted area series. */
|
|
155
|
+
showComparison?: boolean;
|
|
156
|
+
color?: string;
|
|
157
|
+
comparisonColor?: string; /** Formats tooltip and Y-axis values. Defaults to compact currency. */
|
|
158
|
+
valueFormatter?: (value: number) => string;
|
|
159
|
+
dateFormatter?: (date: string | Date) => string; /** Defaults to `showComparison`. */
|
|
160
|
+
showLegend?: boolean;
|
|
161
|
+
showGrid?: boolean;
|
|
162
|
+
};
|
|
163
|
+
/**
|
|
164
|
+
* A gradient area chart for revenue (or any currency metric) over time, with an optional
|
|
165
|
+
* previous-period comparison series.
|
|
166
|
+
*
|
|
167
|
+
* @example
|
|
168
|
+
* ```tsx
|
|
169
|
+
* import { RevenueAreaChart } from '@customafk/lunas-ui/features/charts';
|
|
170
|
+
*
|
|
171
|
+
* <RevenueAreaChart
|
|
172
|
+
* data={[
|
|
173
|
+
* { date: '2026-06-01', value: 4200, previousValue: 3800 },
|
|
174
|
+
* { date: '2026-06-02', value: 5100, previousValue: 4300 },
|
|
175
|
+
* ]}
|
|
176
|
+
* showComparison
|
|
177
|
+
* />
|
|
178
|
+
* ```
|
|
179
|
+
*/
|
|
180
|
+
declare const RevenueAreaChart: ({
|
|
181
|
+
data,
|
|
182
|
+
label,
|
|
183
|
+
comparisonLabel,
|
|
184
|
+
showComparison,
|
|
185
|
+
color,
|
|
186
|
+
comparisonColor,
|
|
187
|
+
valueFormatter,
|
|
188
|
+
dateFormatter,
|
|
189
|
+
showLegend,
|
|
190
|
+
showGrid,
|
|
191
|
+
className,
|
|
192
|
+
animate,
|
|
193
|
+
height
|
|
194
|
+
}: RevenueAreaChartProps) => import("react").JSX.Element;
|
|
195
|
+
//#endregion
|
|
196
|
+
//#region packages/components/features/charts/components/revenue-orders-composed-chart.d.ts
|
|
197
|
+
type RevenueOrdersPoint = {
|
|
198
|
+
date: string | Date;
|
|
199
|
+
revenue: number;
|
|
200
|
+
orders: number;
|
|
201
|
+
};
|
|
202
|
+
type RevenueOrdersComposedChartProps = BaseChartProps & {
|
|
203
|
+
data: RevenueOrdersPoint[];
|
|
204
|
+
revenueLabel?: string;
|
|
205
|
+
ordersLabel?: string;
|
|
206
|
+
revenueColor?: string;
|
|
207
|
+
ordersColor?: string; /** Formats the left (revenue) axis and tooltip values. Defaults to compact currency. */
|
|
208
|
+
revenueFormatter?: (value: number) => string; /** Formats the right (orders) axis and tooltip values. */
|
|
209
|
+
ordersFormatter?: (value: number) => string;
|
|
210
|
+
dateFormatter?: (date: string | Date) => string;
|
|
211
|
+
showLegend?: boolean;
|
|
212
|
+
showGrid?: boolean;
|
|
213
|
+
};
|
|
214
|
+
/**
|
|
215
|
+
* A dual-axis chart combining revenue bars (left axis, currency) with an orders line
|
|
216
|
+
* (right axis, count) to correlate the two metrics per period.
|
|
217
|
+
*
|
|
218
|
+
* @example
|
|
219
|
+
* ```tsx
|
|
220
|
+
* import { RevenueOrdersComposedChart } from '@customafk/lunas-ui/features/charts';
|
|
221
|
+
*
|
|
222
|
+
* <RevenueOrdersComposedChart
|
|
223
|
+
* data={[{ date: '2026-06-01', revenue: 12400, orders: 87 }]}
|
|
224
|
+
* />
|
|
225
|
+
* ```
|
|
226
|
+
*/
|
|
227
|
+
declare const RevenueOrdersComposedChart: ({
|
|
228
|
+
data,
|
|
229
|
+
revenueLabel,
|
|
230
|
+
ordersLabel,
|
|
231
|
+
revenueColor,
|
|
232
|
+
ordersColor,
|
|
233
|
+
revenueFormatter,
|
|
234
|
+
ordersFormatter,
|
|
235
|
+
dateFormatter,
|
|
236
|
+
showLegend,
|
|
237
|
+
showGrid,
|
|
238
|
+
className,
|
|
239
|
+
animate,
|
|
240
|
+
height
|
|
241
|
+
}: RevenueOrdersComposedChartProps) => import("react").JSX.Element;
|
|
242
|
+
//#endregion
|
|
243
|
+
//#region packages/components/features/charts/components/sales-target-radial-chart.d.ts
|
|
244
|
+
type SalesTargetRadialChartProps = BaseChartProps & {
|
|
245
|
+
/** Current progress value, e.g. revenue to date. */value: number; /** The goal the value is measured against. */
|
|
246
|
+
target: number; /** Text under the center figure. Defaults to `'Target'`. */
|
|
247
|
+
label?: string; /** Formats the center figure. Defaults to percent-of-target. */
|
|
248
|
+
valueFormatter?: (value: number, target: number) => string;
|
|
249
|
+
color?: string;
|
|
250
|
+
};
|
|
251
|
+
/**
|
|
252
|
+
* A radial gauge showing progress toward a sales target with the completion figure in the center.
|
|
253
|
+
*
|
|
254
|
+
* @example
|
|
255
|
+
* ```tsx
|
|
256
|
+
* import { SalesTargetRadialChart } from '@customafk/lunas-ui/features/charts';
|
|
257
|
+
*
|
|
258
|
+
* <SalesTargetRadialChart value={65_000} target={100_000} label="Monthly target" />
|
|
259
|
+
* ```
|
|
260
|
+
*/
|
|
261
|
+
declare const SalesTargetRadialChart: ({
|
|
262
|
+
value,
|
|
263
|
+
target,
|
|
264
|
+
label,
|
|
265
|
+
valueFormatter,
|
|
266
|
+
color,
|
|
267
|
+
className,
|
|
268
|
+
animate,
|
|
269
|
+
height
|
|
270
|
+
}: SalesTargetRadialChartProps) => import("react").JSX.Element;
|
|
271
|
+
//#endregion
|
|
272
|
+
//#region packages/components/features/charts/components/sparkline-chart.d.ts
|
|
273
|
+
type SparklineChartProps = {
|
|
274
|
+
data: number[] | Array<{
|
|
275
|
+
value: number;
|
|
276
|
+
}>; /** Render style. Defaults to `'area'`. */
|
|
277
|
+
type?: 'line' | 'area'; /** Colors the series like the `Statistic` trend prop. Defaults to `'neutral'`. */
|
|
278
|
+
trend?: ChartTrend; /** Explicit series color; overrides `trend`. */
|
|
279
|
+
color?: string; /** Fixed height in px. Defaults to `40`. */
|
|
280
|
+
height?: number;
|
|
281
|
+
animate?: boolean;
|
|
282
|
+
className?: string;
|
|
283
|
+
};
|
|
284
|
+
/**
|
|
285
|
+
* A tiny, axis-less trend chart for KPI cards; pairs with the `Statistic` display component.
|
|
286
|
+
*
|
|
287
|
+
* @example
|
|
288
|
+
* ```tsx
|
|
289
|
+
* import { SparklineChart } from '@customafk/lunas-ui/features/charts';
|
|
290
|
+
*
|
|
291
|
+
* <SparklineChart data={[12, 18, 14, 26, 22, 31]} trend="up" />
|
|
292
|
+
* ```
|
|
293
|
+
*/
|
|
294
|
+
declare const SparklineChart: ({
|
|
295
|
+
data,
|
|
296
|
+
type,
|
|
297
|
+
trend,
|
|
298
|
+
color,
|
|
299
|
+
height,
|
|
300
|
+
animate,
|
|
301
|
+
className
|
|
302
|
+
}: SparklineChartProps) => import("react").JSX.Element;
|
|
303
|
+
//#endregion
|
|
304
|
+
//#region packages/components/features/charts/components/top-products-bar-chart.d.ts
|
|
305
|
+
type TopProductsBarChartProps = BaseChartProps & {
|
|
306
|
+
data: NamedValue[]; /** Series label. Defaults to `'Sales'`. */
|
|
307
|
+
label?: string; /** Number of items shown after sorting descending. Defaults to `8`. */
|
|
308
|
+
maxItems?: number;
|
|
309
|
+
color?: string;
|
|
310
|
+
valueFormatter?: (value: number) => string; /** Value labels at the end of each bar. Defaults to `true`. */
|
|
311
|
+
showValueLabels?: boolean;
|
|
312
|
+
};
|
|
313
|
+
/**
|
|
314
|
+
* A horizontal bar ranking chart — top products, best categories, top customers.
|
|
315
|
+
*
|
|
316
|
+
* @example
|
|
317
|
+
* ```tsx
|
|
318
|
+
* import { TopProductsBarChart } from '@customafk/lunas-ui/features/charts';
|
|
319
|
+
*
|
|
320
|
+
* <TopProductsBarChart
|
|
321
|
+
* data={[
|
|
322
|
+
* { name: 'Wireless Earbuds', value: 1245 },
|
|
323
|
+
* { name: 'Smart Watch', value: 986 },
|
|
324
|
+
* ]}
|
|
325
|
+
* />
|
|
326
|
+
* ```
|
|
327
|
+
*/
|
|
328
|
+
declare const TopProductsBarChart: ({
|
|
329
|
+
data,
|
|
330
|
+
label,
|
|
331
|
+
maxItems,
|
|
332
|
+
color,
|
|
333
|
+
valueFormatter,
|
|
334
|
+
showValueLabels,
|
|
335
|
+
className,
|
|
336
|
+
animate,
|
|
337
|
+
height
|
|
338
|
+
}: TopProductsBarChartProps) => import("react").JSX.Element;
|
|
339
|
+
//#endregion
|
|
340
|
+
//#region packages/components/features/charts/utils.d.ts
|
|
341
|
+
/** Cycles through the eight `--chart-N` theme palette variables. */
|
|
342
|
+
declare const getChartColor: (index: number) => string;
|
|
343
|
+
declare const formatCompactNumber: (value: number, locale?: string) => string;
|
|
344
|
+
declare const formatCurrency: (value: number, currency?: string, locale?: string) => string;
|
|
345
|
+
declare const formatPercent: (value: number, locale?: string) => string;
|
|
346
|
+
declare const toDateLabel: (date: string | Date, locale?: string) => string;
|
|
347
|
+
//#endregion
|
|
348
|
+
export { BaseChartProps, ChartSeries, ChartTrend, ConversionFunnelChart, ConversionFunnelChartProps, DonutChart, DonutChartProps, DonutChartSegment, FunnelStage, NamedValue, OrdersBarChart, OrdersBarChartProps, RevenueAreaChart, RevenueAreaChartProps, RevenueOrdersComposedChart, RevenueOrdersComposedChartProps, RevenueOrdersPoint, SalesTargetRadialChart, SalesTargetRadialChartProps, SparklineChart, SparklineChartProps, TimeSeriesPoint, TopProductsBarChart, TopProductsBarChartProps, formatCompactNumber, formatCurrency, formatPercent, getChartColor, toDateLabel };
|
|
349
|
+
//# sourceMappingURL=index.d.cts.map
|