{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "recharts-chart",
  "description": "Deprecated: Recharts chart helpers. Use chart instead.",
  "dependencies": [
    "react-aria-components",
    "recharts",
    "cn@^0.2.4"
  ],
  "registryDependencies": [
    "https://ui-three-mu.vercel.app/r/primitive.json"
  ],
  "files": [
    {
      "path": "registry/preskok/ui/preskok-ui/recharts-chart.tsx",
      "content": "\"use client\"\n\n/**\n * @deprecated Recharts helpers for the deprecated `Recharts*Chart` components.\n * Use `@preskok/chart`, built on TanStack Charts.\n */\n\nimport {\n  createContext,\n  use,\n  useCallback,\n  useId,\n  useMemo,\n  useState,\n  type ReactElement,\n} from \"react\"\nimport { twJoin, twMerge } from \"cn\"\nimport {\n  ToggleButton,\n  ToggleButtonGroup,\n  type ToggleButtonGroupProps,\n} from \"react-aria-components/ToggleButtonGroup\"\nimport type {\n  CartesianGridProps as CartesianGridPrimitiveProps,\n  CartesianGridProps,\n  LegendPayload,\n  LegendProps,\n  TooltipProps as TooltipPrimitiveProps,\n  XAxisProps as XAxisPropsPrimitive,\n  YAxisProps as YAxisPrimitiveProps,\n} from \"recharts\"\nimport {\n  CartesianGrid as CartesianGridPrimitive,\n  Legend as LegendPrimitive,\n  ResponsiveContainer,\n  Tooltip as TooltipPrimitive,\n  XAxis as XAxisPrimitive,\n  YAxis as YAxisPrimitive,\n} from \"recharts\"\nimport type { ContentType as LegendContentType } from \"recharts/types/component/DefaultLegendContent\"\nimport type {\n  NameType,\n  Props as TooltipContentProps,\n  ValueType,\n} from \"recharts/types/component/DefaultTooltipContent\"\nimport type { ContentType as TooltipContentType } from \"recharts/types/component/Tooltip\"\n\nimport { cx } from \"@/lib/primitive\"\n\n// #region Chart Types\ntype ChartType = \"default\" | \"stacked\" | \"percent\"\ntype ChartLayout = \"horizontal\" | \"vertical\" | \"radial\"\ntype IntervalType = \"preserveStartEnd\" | \"equidistantPreserveStart\"\n\ntype ChartConfig = {\n  [k in string]: {\n    label?: React.ReactNode\n    icon?: React.ComponentType\n  } & (\n    | { color?: ChartColorKeys | (string & {}); theme?: never }\n    | { color?: never; theme: Record<keyof typeof THEMES, string> }\n  )\n}\n\ntype ChartDatum = Record<string, unknown>\n\nconst CHART_COLORS = {\n  \"chart-1\": \"var(--chart-1)\",\n  \"chart-2\": \"var(--chart-2)\",\n  \"chart-3\": \"var(--chart-3)\",\n  \"chart-4\": \"var(--chart-4)\",\n  \"chart-5\": \"var(--chart-5)\",\n} as const\n\ntype ChartColorKeys = keyof typeof CHART_COLORS | (string & {})\n\nconst DEFAULT_COLORS = [\n  \"chart-1\",\n  \"chart-2\",\n  \"chart-3\",\n  \"chart-4\",\n  \"chart-5\",\n] as const\n\n// #endregion\n\n// #region Chart Context\n\ntype ChartContextProps = {\n  config: ChartConfig\n  data?: ChartDatum[]\n  layout: ChartLayout\n  dataKey?: string\n  selectedLegend: string | null\n  onLegendSelect: (legendItem: string | null) => void\n}\n\nconst ChartContext = createContext<ChartContextProps | null>(null)\n\nexport function useChart() {\n  const context = use(ChartContext)\n\n  if (!context) {\n    throw new Error(\"useChart must be used within a <Chart />\")\n  }\n\n  return context\n}\n\n// #endregion\n\n// #region helpers\n\nexport function valueToPercent(value: number) {\n  return `${(value * 100).toFixed(0)}%`\n}\n\nconst constructCategoryColors = (\n  categories: string[],\n  colors: readonly ChartColorKeys[]\n): Map<string, ChartColorKeys> => {\n  const categoryColors = new Map<string, ChartColorKeys>()\n\n  categories.forEach((category, index) => {\n    const color = colors[index % colors.length]\n    if (color !== undefined) {\n      categoryColors.set(category, color)\n    }\n  })\n\n  return categoryColors\n}\n\nconst getColorValue = (color?: string): string => {\n  if (!color) {\n    return \"var(--chart-1)\"\n  }\n\n  return CHART_COLORS[color as \"chart-1\"] ?? color\n}\n\nfunction getPayloadConfigFromPayload(\n  config: ChartConfig,\n  payload: unknown,\n  key: string\n) {\n  if (typeof payload !== \"object\" || payload === null) {\n    return undefined\n  }\n\n  const payloadPayload =\n    \"payload\" in payload &&\n    typeof payload.payload === \"object\" &&\n    payload.payload !== null\n      ? payload.payload\n      : undefined\n\n  let configLabelKey: string = key\n\n  if (\n    key in payload &&\n    typeof payload[key as keyof typeof payload] === \"string\"\n  ) {\n    configLabelKey = payload[key as keyof typeof payload] as string\n  } else if (\n    payloadPayload &&\n    key in payloadPayload &&\n    typeof payloadPayload[key as keyof typeof payloadPayload] === \"string\"\n  ) {\n    configLabelKey = payloadPayload[\n      key as keyof typeof payloadPayload\n    ] as string\n  }\n\n  return configLabelKey in config\n    ? config[configLabelKey]\n    : config[key as keyof typeof config]\n}\n\n// #endregion\n\n// #region Base Chart Components\n\ninterface BaseChartProps<\n  TValue extends ValueType,\n  TName extends NameType,\n> extends React.HTMLAttributes<HTMLDivElement> {\n  config: ChartConfig\n  data: ChartDatum[]\n  dataKey: string\n  colors?: readonly (ChartColorKeys | (string & {}))[]\n  type?: ChartType\n  intervalType?: IntervalType\n  layout?: ChartLayout\n  valueFormatter?: (value: number) => string\n\n  tooltip?: TooltipContentType<ValueType, NameType> | boolean\n  tooltipProps?: Omit<ChartTooltipProps, \"content\"> & {\n    hideLabel?: boolean\n    labelSeparator?: boolean\n    hideIndicator?: boolean\n    indicator?: \"line\" | \"dot\" | \"dashed\"\n    nameKey?: string\n    labelKey?: string\n  }\n\n  cartesianGridProps?: CartesianGridProps\n\n  legend?: LegendContentType | boolean\n  legendProps?: Omit<\n    React.ComponentProps<typeof LegendPrimitive>,\n    \"content\" | \"ref\"\n  >\n\n  xAxisProps?: XAxisPropsPrimitive\n  yAxisProps?: YAxisPrimitiveProps\n\n  // XAxis\n  displayEdgeLabelsOnly?: boolean\n\n  hideGridLines?: boolean\n  hideXAxis?: boolean\n  hideYAxis?: boolean\n}\n\nconst Chart = ({\n  id,\n  className,\n  children,\n  config,\n  data,\n  dataKey,\n  ref,\n  layout = \"horizontal\",\n  ...props\n}: Omit<React.ComponentProps<\"div\">, \"children\"> &\n  Pick<ChartContextProps, \"data\" | \"dataKey\"> & {\n    config: ChartConfig\n    layout?: ChartLayout\n    children: ReactElement | ((props: ChartContextProps) => ReactElement)\n  }) => {\n  const uniqueId = useId()\n  const chartId = useMemo(\n    () => `chart-${id || uniqueId.replace(/:/g, \"\")}`,\n    [id, uniqueId]\n  )\n\n  const [selectedLegend, setSelectedLegend] = useState<string | null>(null)\n\n  const onLegendSelect = useCallback((legendItem: string | null) => {\n    setSelectedLegend(legendItem)\n  }, [])\n\n  const _data = data ?? []\n  const _dataKey = dataKey ?? \"value\"\n\n  const value = {\n    config,\n    selectedLegend,\n    onLegendSelect,\n    data: _data,\n    dataKey: _dataKey,\n    layout,\n  }\n\n  return (\n    <ChartContext value={value}>\n      <div\n        data-chart={chartId}\n        ref={ref}\n        className={twMerge(\n          \"z-20 flex w-full justify-center text-xs\",\n          \"[&_.recharts-cartesian-axis-tick_text]:fill-muted-foreground [&_.recharts-cartesian-grid_line[stroke='#ccc']]:stroke-border/80 [&_.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 [&_.recharts-layer]:outline-hidden [&_.recharts-sector]:outline-hidden [&_.recharts-sector[stroke='#fff']]:stroke-transparent [&_.recharts-surface]:outline-hidden\",\n          // dot\n          \"[&_.recharts-dot[fill='#fff']]:fill-(--line-color)\",\n          // when hover over the line chart, the active dot should not have a fill or stroke\n          \"[&_.recharts-active-dot>.recharts-dot]:stroke-foreground/10\",\n          className\n        )}\n        {...props}\n      >\n        <ChartStyle id={chartId} config={config} />\n        <ResponsiveContainer\n          width=\"100%\"\n          height=\"100%\"\n          minWidth={0}\n          initialDimension={{ width: 1, height: 1 }}\n        >\n          {typeof children === \"function\" ? children(value) : children}\n        </ResponsiveContainer>\n      </div>\n    </ChartContext>\n  )\n}\n\nconst THEMES = { light: \"\", dark: \".dark\" } as const\nconst ChartStyle = ({ id, config }: { id: string; config: ChartConfig }) => {\n  const colorConfig = Object.entries(config).filter(\n    ([_, config]) => config.theme || config.color\n  )\n\n  if (!colorConfig.length) {\n    return null\n  }\n\n  return (\n    <style\n      dangerouslySetInnerHTML={{\n        __html: Object.entries(THEMES)\n          .map(\n            ([theme, prefix]) => `\n${prefix} [data-chart=${id}] {\n${colorConfig\n  .map(([key, itemConfig]) => {\n    const color =\n      itemConfig.theme?.[theme as keyof typeof itemConfig.theme] ||\n      itemConfig.color\n    return color ? `  --color-${key}: ${color};` : null\n  })\n  .join(\"\\n\")}\n}\n`\n          )\n          .join(\"\\n\"),\n      }}\n    />\n  )\n}\n\ntype ChartTooltipProps = TooltipPrimitiveProps<ValueType, NameType>\n\nconst ChartTooltip = (props: ChartTooltipProps) => {\n  const { layout } = useChart()\n\n  return (\n    <TooltipPrimitive\n      wrapperStyle={{ outline: \"none\" }}\n      isAnimationActive={true}\n      animationDuration={500}\n      offset={10}\n      cursor={{\n        stroke: \"var(--muted)\",\n        strokeWidth: layout === \"radial\" ? 0.1 : 1,\n        fill: \"var(--muted)\",\n        fillOpacity: 0.5,\n      }}\n      {...props}\n    />\n  )\n}\n\ntype ChartLegendProps = Omit<\n  React.ComponentProps<typeof LegendPrimitive>,\n  \"ref\"\n>\n\nconst ChartLegend = (props: ChartLegendProps) => {\n  return <LegendPrimitive align=\"center\" verticalAlign=\"bottom\" {...props} />\n}\n\ninterface XAxisProps extends Omit<XAxisPropsPrimitive, \"ref\"> {\n  displayEdgeLabelsOnly?: boolean\n  intervalType?: IntervalType\n}\n\nconst XAxis = ({\n  displayEdgeLabelsOnly,\n  className,\n  intervalType = \"preserveStartEnd\",\n  minTickGap = 5,\n  domain = [\"auto\", \"auto\"],\n  ...props\n}: XAxisProps) => {\n  const { dataKey, data, layout } = useChart()\n\n  let ticks: Array<string | number> | undefined\n  if (displayEdgeLabelsOnly && data?.length && dataKey) {\n    const firstTick = data[0]?.[dataKey]\n    const lastTick = data[data.length - 1]?.[dataKey]\n    if (\n      (typeof firstTick === \"string\" || typeof firstTick === \"number\") &&\n      (typeof lastTick === \"string\" || typeof lastTick === \"number\")\n    ) {\n      ticks = [firstTick, lastTick]\n    }\n  }\n\n  const tick = {\n    transform: layout === \"horizontal\" ? \"translate(32, 6)\" : undefined,\n  }\n  return (\n    <XAxisPrimitive\n      className={twMerge(\n        \"text-muted-foreground **:[text]:fill-muted-foreground text-xs\",\n        className\n      )}\n      interval={displayEdgeLabelsOnly ? \"preserveStartEnd\" : intervalType}\n      tick={tick}\n      ticks={ticks}\n      tickLine={false}\n      axisLine={false}\n      minTickGap={minTickGap}\n      dataKey={layout === \"horizontal\" ? dataKey : undefined}\n      {...props}\n    />\n  )\n}\n\nconst YAxis = ({\n  className,\n  width,\n  domain = [\"auto\", \"auto\"],\n  type,\n  ...props\n}: Omit<YAxisPrimitiveProps, \"ref\">) => {\n  const { layout, dataKey } = useChart()\n\n  return (\n    <YAxisPrimitive\n      className={twMerge(\n        \"text-muted-foreground **:[text]:fill-muted-foreground text-xs\",\n        className\n      )}\n      width={(width ?? layout === \"horizontal\") ? 40 : 80}\n      domain={domain}\n      tick={{\n        transform:\n          layout === \"horizontal\" ? \"translate(-3, 0)\" : \"translate(0, 0)\",\n      }}\n      dataKey={layout === \"horizontal\" ? undefined : dataKey}\n      type={type || layout === \"horizontal\" ? \"number\" : \"category\"}\n      interval={\n        layout === \"horizontal\" ? undefined : \"equidistantPreserveStart\"\n      }\n      axisLine={false}\n      tickLine={false}\n      {...props}\n    />\n  )\n}\n\nconst CartesianGrid = ({\n  className,\n  ...props\n}: CartesianGridPrimitiveProps) => {\n  const { layout } = useChart()\n  return (\n    <CartesianGridPrimitive\n      className={twMerge(\"stroke-muted stroke-1\", className)}\n      horizontal={layout !== \"vertical\"}\n      vertical={layout === \"vertical\"}\n      {...props}\n    />\n  )\n}\n\nconst ChartTooltipContent = <TValue extends ValueType, TName extends NameType>({\n  payload,\n  className,\n  indicator = \"dot\",\n  hideLabel = false,\n  hideIndicator = false,\n  label,\n  labelSeparator = true,\n  labelFormatter,\n  labelClassName,\n  formatter,\n  color,\n  nameKey,\n  labelKey,\n  ref,\n}: TooltipContentProps<TValue, TName> &\n  React.ComponentProps<\"div\"> & {\n    hideLabel?: boolean\n    labelSeparator?: boolean\n    hideIndicator?: boolean\n    indicator?: \"line\" | \"dot\" | \"dashed\"\n    nameKey?: string\n    labelKey?: string\n  }) => {\n  const { config } = useChart()\n\n  const tooltipLabel = useMemo(() => {\n    if (hideLabel || !payload?.length) {\n      return null\n    }\n\n    const [item] = payload\n\n    if (!item) {\n      return null\n    }\n\n    const key = `${labelKey || item.dataKey || item.name || \"value\"}`\n    const itemConfig = getPayloadConfigFromPayload(config, item, key)\n    const value =\n      !labelKey && typeof label === \"string\"\n        ? config[label as keyof typeof config]?.label || label\n        : itemConfig?.label\n\n    if (labelFormatter) {\n      return (\n        <div className={labelClassName}>{labelFormatter(value, payload)}</div>\n      )\n    }\n\n    if (!value) {\n      return null\n    }\n\n    return <div className={labelClassName}>{value}</div>\n  }, [\n    label,\n    labelFormatter,\n    payload,\n    hideLabel,\n    labelClassName,\n    config,\n    labelKey,\n  ])\n\n  if (!payload?.length) {\n    return null\n  }\n\n  const nestLabel = payload.length === 1 && indicator !== \"dot\"\n\n  return (\n    <div\n      ref={ref}\n      className={twMerge(\n        \"bg-overlay/70 text-overlay-foreground grid min-w-[12rem] items-start rounded-lg p-3 py-2 text-xs ring ring-current/10 backdrop-blur-lg\",\n        className\n      )}\n    >\n      {!hideLabel && (\n        <>\n          {!nestLabel ? (\n            <span className=\"font-medium\">{tooltipLabel}</span>\n          ) : null}\n          {labelSeparator && (\n            <span\n              aria-hidden\n              className=\"mt-2 mb-3 block h-px w-full bg-background/10\"\n            />\n          )}\n        </>\n      )}\n      <div className=\"grid gap-3\">\n        {payload.map((item, index) => {\n          const key = `${nameKey || item.name || item.dataKey || \"value\"}`\n          const itemConfig = getPayloadConfigFromPayload(config, item, key)\n          const indicatorColor = color || item.payload.fill || item.color\n\n          return (\n            <div\n              key={key}\n              className={twMerge(\n                \"*:data-[slot=icon]:text-muted-foreground flex w-full flex-wrap items-stretch gap-2\",\n                indicator === \"dot\" &&\n                  \"items-center *:data-[slot=icon]:size-2.5\",\n                indicator === \"line\" &&\n                  \"*:data-[slot=icon]:h-full *:data-[slot=icon]:w-2.5\"\n              )}\n            >\n              {formatter && item?.value !== undefined && item.name ? (\n                formatter(item.value, item.name, item, index, item.payload)\n              ) : (\n                <>\n                  {itemConfig?.icon ? (\n                    <itemConfig.icon />\n                  ) : (\n                    !hideIndicator && (\n                      <div\n                        className={twMerge(\n                          \"shrink-0 rounded-full border-(--color-border) bg-(--color-background)\",\n                          indicator === \"dot\" && \"size-2.5\",\n                          indicator === \"line\" && \"w-1\",\n                          indicator === \"dashed\" &&\n                            \"w-0 border-[1.5px] border-dashed bg-transparent\",\n                          nestLabel && indicator === \"dashed\" && \"my-0.5\"\n                        )}\n                        style={\n                          {\n                            \"--color-background\": indicatorColor,\n                            \"--color-border\": indicatorColor,\n                          } as React.CSSProperties\n                        }\n                      />\n                    )\n                  )}\n                  <div\n                    className={twMerge(\n                      \"flex flex-1 justify-between leading-none\",\n                      nestLabel ? \"items-end\" : \"items-center\"\n                    )}\n                  >\n                    <div className=\"grid gap-1.5\">\n                      {nestLabel ? tooltipLabel : null}\n                      <span className=\"text-muted-foreground\">\n                        {itemConfig?.label || item.name}\n                      </span>\n                    </div>\n\n                    {item.value && (\n                      <span className=\"font-mono font-medium text-foreground tabular-nums\">\n                        {item.value.toString()}\n                      </span>\n                    )}\n                  </div>\n                </>\n              )}\n            </div>\n          )\n        })}\n      </div>\n    </div>\n  )\n}\n\ntype ChartLegendContentProps = ToggleButtonGroupProps &\n  Pick<LegendProps, \"align\" | \"verticalAlign\"> & {\n    payload?: ReadonlyArray<LegendPayload>\n    hideIcon?: boolean\n    nameKey?: string\n    ref?: React.Ref<HTMLDivElement>\n  }\n\nconst ChartLegendContent = ({\n  className,\n  hideIcon = false,\n  payload,\n  align = \"right\",\n  verticalAlign = \"bottom\",\n  nameKey,\n  ref,\n}: ChartLegendContentProps) => {\n  const { config, selectedLegend, onLegendSelect } = useChart()\n\n  if (!payload?.length) {\n    return null\n  }\n\n  return (\n    <ToggleButtonGroup\n      ref={ref}\n      className={cx(\n        twJoin(\n          \"flex flex-wrap items-center gap-x-1\",\n          verticalAlign === \"top\" ? \"pb-3\" : \"pt-3\",\n          align === \"right\"\n            ? \"justify-end\"\n            : align === \"left\"\n              ? \"justify-start\"\n              : \"justify-center\"\n        ),\n        className\n      )}\n      selectedKeys={selectedLegend ? [selectedLegend] : undefined}\n      onSelectionChange={(v) => {\n        const key = [...v][0]?.toString() ?? null\n        onLegendSelect(key)\n      }}\n      selectionMode=\"single\"\n    >\n      {payload.map((item: LegendPayload) => {\n        const key = `${nameKey || item.dataKey || \"value\"}`\n        const itemConfig = getPayloadConfigFromPayload(config, item, key)\n\n        return (\n          <ToggleButton\n            key={key}\n            id={key}\n            className={twMerge(\n              \"text-muted-foreground *:data-[slot=icon]:text-muted-foreground flex items-center gap-2 rounded-sm px-2 py-1 *:data-[slot=icon]:-mx-0.5 *:data-[slot=icon]:size-2.5 *:data-[slot=icon]:shrink-0\",\n              \"selected:bg-secondary/70 selected:text-secondary-foreground\",\n              \"hover:bg-secondary/70 hover:text-secondary-foreground\"\n            )}\n            aria-label={\"Legend Item\"}\n          >\n            {itemConfig?.icon && !hideIcon ? (\n              <itemConfig.icon data-slot=\"icon\" />\n            ) : (\n              <div\n                data-slot=\"icon\"\n                className=\"rounded-full\"\n                style={{\n                  backgroundColor: item.color,\n                }}\n              />\n            )}\n            {itemConfig?.label}\n          </ToggleButton>\n        )\n      })}\n    </ToggleButtonGroup>\n  )\n}\n\nexport type {\n  BaseChartProps,\n  ChartColorKeys,\n  ChartConfig,\n  ChartDatum,\n  ChartLayout,\n  ChartLegendContentProps,\n  ChartLegendProps,\n  ChartTooltipProps,\n  ChartType,\n  IntervalType,\n  XAxisProps,\n}\n\nexport {\n  CartesianGrid,\n  Chart,\n  CHART_COLORS,\n  ChartLegend,\n  ChartLegendContent,\n  ChartTooltip,\n  ChartTooltipContent,\n  constructCategoryColors,\n  DEFAULT_COLORS,\n  getColorValue,\n  XAxis,\n  YAxis,\n}\n",
      "type": "registry:ui"
    }
  ],
  "type": "registry:ui"
}