{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "Chart",
  "dependencies": [
    "cn",
    "recharts",
    "rescript-base-ui"
  ],
  "files": [
    {
      "path": "registry/base/ui/Chart.res",
      "content": "@@jsxConfig({version: 4, mode: \"automatic\", module_: \"BaseUi.BaseUiJsxDOM\"})\n\n@@directive(\"'use client'\")\n\n@module(\"cn\")\nexternal cn: (string, option<string>) => string = \"cn\"\n\ntype colorTheme = {\n  light?: string,\n  dark?: string,\n}\n\ntype chartConfigItem = {\n  label?: React.element,\n  icon?: unit => React.element,\n  color?: string,\n  theme?: colorTheme,\n}\n\ntype chartConfig = dict<chartConfigItem>\n\ntype chartContext = {config: chartConfig}\n\ntype payloadItem<'value> = {\n  @as(\"type\") type_?: string,\n  dataKey?: string,\n  name?: string,\n  color?: string,\n  value?: 'value,\n  payload: dict<string>,\n}\n\nlet chartContext: React.Context.t<option<chartContext>> = React.createContext(None)\n\n@throws(JsExn)\nlet use = () =>\n  switch React.useContext(chartContext) {\n  | Some(context) => context\n  | None => JsError.throwWithMessage(\"useChart must be used within a <ChartContainer />\")\n  }\n\nlet themeColor = (~itemConfig: chartConfigItem, ~themeName: string) =>\n  switch itemConfig.theme {\n  | Some(theme) =>\n    switch themeName {\n    | \"light\" => theme.light->Option.orElse(itemConfig.color)\n    | \"dark\" => theme.dark->Option.orElse(itemConfig.color)\n    | _ => itemConfig.color\n    }\n  | None => itemConfig.color\n  }\n\nlet getPayloadConfigFromPayload = (\n  ~config: chartConfig,\n  ~payload: payloadItem<'value>,\n  ~key: string,\n) => {\n  let configLabelKey = switch key {\n  | \"name\" => payload.name->Option.orElse(payload.payload->Dict.get(\"name\"))\n  | \"dataKey\" => payload.dataKey->Option.orElse(payload.payload->Dict.get(\"dataKey\"))\n  | _ => payload.payload->Dict.get(key)\n  }->Option.getOr(key)\n  switch config->Dict.get(configLabelKey) {\n  | Some(foundConfig) => Some(foundConfig)\n  | None => config->Dict.get(key)\n  }\n}\n\nmodule Recharts = {\n  module Dimensions = {\n    type t = {width: float, height: float}\n  }\n  module ResponsiveContainer = {\n    @module(\"recharts\") @react.component\n    external make: (\n      /**\n   * width / height. If specified, the height will be calculated by width / aspect.\n   */\n      ~aspect: float=?,\n      /**\n   * The width of chart container.\n   * Can be a number or a percent string like \"100%\".\n   * @default '100%'\n   */\n      ~width: float=?,\n      /**\n   * The height of chart container.\n   * Can be a number or a percent string like \"100%\".\n   * @default '100%'\n   */\n      ~height: float=?,\n      /**\n   * The minimum width of the container.\n   * @default 0\n   */\n      ~minWidth: float=?,\n      /**\n   * The minimum height of the container.\n   */\n      ~minHeight: float=?,\n      /**\n   * The initial width and height of the container.\n   * @default {\"width\":-1,\"height\":-1}\n   */\n      ~initialDimension: Dimensions.t=?,\n      /**\n   * The maximum height of the container. It can be a number.\n   */\n      ~maxHeight: float=?,\n      /**\n   * The content of the container.\n   * It can contain multiple charts, and then they will all share the same dimensions.\n   */\n      ~children: React.element,\n      /**\n   * If specified a positive number, debounced function will be used to handle the resize event.\n   * @default 0\n   */\n      ~debounce: float=?,\n      /**\n   * Unique identifier of this component.\n   * Used as an HTML attribute `id`.\n   */\n      ~id: string=?,\n      /**\n   * The HTML element's class name\n   */\n      ~className: string=?,\n      /**\n   * The style of the container.\n   */\n      ~style: ReactDOM.Style.t=?,\n      /**\n   * If specified provides a callback providing the updated chart width and height values.\n   */\n      ~onResize: (float, float) => unit=?,\n    ) => React.element = \"ResponsiveContainer\"\n  }\n\n  module AllowInDimension = {\n    type t = {x?: bool, y?: bool}\n  }\n  module AnimationTiming = {\n    @unboxed\n    type t =\n      | @as(\"ease\") Ease\n      | @as(\"linear\") Linear\n      | @as(\"ease-in\") EaseIn\n      | @as(\"ease-out\") EaseOut\n      | @as(\"ease-in-out\") EaseInOut\n  }\n\n  module Index = {\n    @unboxed\n    type t =\n      | Int(int)\n      | String(string)\n  }\n\n  module CursorDefinition = {\n    @unboxed\n    type t =\n      | @as(false) NoCursor\n      | Custom(React.element)\n  }\n\n  module AnimationActive = {\n    @unboxed\n    type t =\n      | @as(true) True\n      | @as(false) False\n      | @as(\"auto\") Auto\n  }\n\n  module TooltipItemSorter = {\n    @unboxed\n    type t<'payloadItem> =\n      | @as(\"name\") Name\n      | @as(\"value\") Value\n      | @as(\"dataKey\") Id\n      | Function((~item: 'payloadItem) => int)\n  }\n\n  module Coordinate = {\n    type t = {x: float, y: float}\n    module Partial = {\n      type t = {x?: float, y?: float}\n    }\n  }\n\n  module Offset = {\n    @unboxed\n    type t =\n      | Int(int)\n      | Coordinate(Coordinate.t)\n  }\n\n  module UniqueOption = {\n    @unboxed\n    type t<'entry> =\n      | @as(true) True\n      | @as(false) False\n      | Function('entry => string)\n  }\n\n  module TooltipTrigger = {\n    @unboxed\n    type t =\n      | @as(\"hover\") Hover\n      | @as(\"click\") Click\n  }\n\n  type mouseEvent<'element>\n\n  module Tooltip = {\n    @module(\"recharts\") @react.component\n    external make: (\n      ~wrapperClassName: string=?,\n      ~labelClassName: string=?,\n      /**\n   * If true, then Tooltip is always displayed, once an activeIndex is set by mouse over, or programmatically.\n   * If false, then Tooltip is never displayed.\n   * If undefined, Recharts will control when the Tooltip displays. This includes mouse and keyboard controls.\n   */\n      ~active: bool=?,\n      /**\n   * This option allows the tooltip to extend beyond the viewBox of the chart itself.\n   * @defaultValue {\"x\":false,\"y\":false}\n   */\n      ~allowEscapeViewBox: AllowInDimension.t=?,\n      /**\n   * Specifies the duration of animation, the unit of this option is ms.\n   * @defaultValue 400\n   */\n      ~animationDuration: float=?,\n      /**\n   * The type of easing function.\n   * @defaultValue ease\n   */\n      ~animationEasing: AnimationTiming.t=?,\n      /**\n   * Tooltip always attaches itself to the \"Tooltip\" axis. Which axis is it? Depends on the layout:\n   * - horizontal layout -> X axis\n   * - vertical layout -> Y axis\n   * - radial layout -> radial axis\n   * - centric layout -> angle axis\n   *\n   * Tooltip will use the default axis for the layout, unless you specify an axisId.\n   *\n   * @defaultValue 0\n   */\n      ~axisId: Index.t=?,\n      /**\n   * Renders the content of the tooltip.\n   *\n   * This should return HTML elements, not SVG elements.\n   *\n   * - If not set, the {@link DefaultTooltipContent} component is used.\n   * - If set to a React element, this element will be cloned and extra props will be passed in.\n   * - If set to a function, the function will be called and should return HTML elements.\n   *\n   * @see {@link https://recharts.github.io/en-US/examples/CustomContentOfTooltip/ Example with custom content}\n   */\n      ~content: React.element=?,\n      /**\n   * The style of tooltip content which is a dom element.\n   * @defaultValue {}\n   */\n      ~contentStyle: ReactDOM.Style.t=?,\n      /**\n   * If set false, no cursor will be drawn when tooltip is active.\n   * If set a object, the option is the configuration of cursor.\n   * If set a React element, the option is the custom react element of drawing cursor.\n   * @defaultValue true\n   */\n      ~cursor: CursorDefinition.t=?,\n      ~defaultIndex: Index.t=?,\n      /**\n   * When an item of the payload has value null or undefined, this item won't be displayed.\n   * @defaultValue true\n   */\n      ~filterNull: bool=?,\n      /**\n   * Function to customize the value in the tooltip.\n   * If you return an array, the first entry will be the formatted \"value\", and the second entry will be the formatted \"name\"\n   */\n      ~formatter: (\n        ~name: string,\n        ~value: string,\n        ~item: 'payloadItem,\n        ~index: int,\n        ~payload: array<'payloadEntry>,\n      ) => (React.element, React.element)=?,\n      /**\n   * If true, the tooltip will display information about hidden series.\n   * Defaults to false.\n   * Interacting with the hide property of Area, Bar, Line, Scatter.\n   *\n   * @defaultValue false\n   */\n      ~includeHidden: bool=?,\n      /**\n   * If set false, animation of tooltip will be disabled.\n   * If set \"auto\", the animation will be disabled in SSR and will respect the user's prefers-reduced-motion system preference for accessibility.\n   * @defaultValue auto\n   */\n      ~isAnimationActive: AnimationActive.t=?,\n      /**\n   * Sorts tooltip items.\n   * Defaults to 'name' which means it sorts alphabetically by graphical item `name` property.\n   * @defaultValue name\n   */\n      ~itemSorter: TooltipItemSorter.t<'payloadItem>=?,\n      /**\n   * The style of default tooltip content item which is a li element.\n   * @defaultValue {}\n   */\n      ~itemStyle: ReactDOM.Style.t=?,\n      /**\n   * The formatter function of label in tooltip.\n   */\n      ~labelFormatter: (~label: 'label, ~payload: 'tooltipPayload) => React.element=?,\n      /**\n   * The style of default tooltip label which is a p element.\n   * @defaultValue {}\n   */\n      ~labelStyle: ReactDOM.Style.t=?,\n      /**\n   * The offset size between the position of tooltip and the mouse cursor position.\n   * When a number is provided, the same offset is applied to both x and y axes.\n   *\n   * When a Coordinate object is provided, you can specify different offsets for each axis (x and y as numbers)\n   * @defaultValue 10\n   */\n      ~offset: Offset.t=?,\n      ~payloadUniqBy: UniqueOption.t<'payloadEntry>=?,\n      /**\n   * If portal is defined, then Tooltip will use this element as a target\n   * for rendering using React Portal: https://react.dev/reference/react-dom/createPortal\n   *\n   * If this is undefined then Tooltip renders inside the recharts-wrapper element.\n   */\n      ~portal: Dom.htmlElement=?,\n      /**\n   * If this field is set, the tooltip will be displayed at the specified position\n   * regardless of the mouse position.\n   *\n   * You can set a single field (x or y) and let the other field be calculated automatically based\n   * on the mouse position.\n   */\n      ~position: Coordinate.Partial.t=?,\n      /**\n   * @defaultValue {\"x\":false,\"y\":false}\n   */\n      ~reverseDirection: AllowInDimension.t=?,\n      /**\n   * The separator between name and value.\n   * @defaultValue ' : '\n   */\n      ~separator: string=?,\n      /**\n   * Defines whether the tooltip is reacting to the current data point,\n   * or to all data points at the current axis coordinate.\n   */\n      ~shared: bool=?,\n      /**\n   * If `hover` then the Tooltip shows on mouse enter and hides on mouse leave.\n   *\n   * If `click` then the Tooltip shows after clicking and stays active.\n   *\n   * @defaultValue hover\n   */\n      ~trigger: TooltipTrigger.t=?,\n      /**\n   * @defaultValue false\n   */\n      ~useTranslate3d: bool=?,\n      /**\n   * CSS styles to be applied to the wrapper `div` element.\n   */\n      ~wrapperStyle: ReactDOM.Style.t=?,\n    ) => React.element = \"Tooltip\"\n  }\n\n  module LegendType = {\n    @unboxed\n    type t =\n      | @as(\"circle\") Circle\n      | @as(\"cross\") Cross\n      | @as(\"diamond\") Diamond\n      | @as(\"line\") Line\n      | @as(\"plainline\") Plainline\n      | @as(\"rect\") Rect\n      | @as(\"square\") Square\n      | @as(\"star\") Star\n      | @as(\"triangle\") Triangle\n      | @as(\"wye\") Wye\n      | @as(\"none\") None\n  }\n\n  module CartesianLayout = {\n    @unboxed\n    type t =\n      | @as(\"horizontal\") Horizontal\n      | @as(\"vertical\") Vertical\n  }\n\n  module HorizontalAlignmentType = {\n    @unboxed\n    type t =\n      | @as(\"left\") Left\n      | @as(\"right\") Right\n      | @as(\"center\") Center\n  }\n\n  module VerticalAlignmentType = {\n    @unboxed\n    type t =\n      | @as(\"bottom\") Bottom\n      | @as(\"top\") Top\n      | @as(\"middle\") Middle\n  }\n\n  module Dimension = {\n    @unboxed\n    type t =\n      | Int(int)\n      | String(string)\n  }\n\n  module LegendItemSorter = {\n    @unboxed\n    type t<'legendPayload> =\n      | @as(\"value\") Value\n      | @as(\"dataKey\") DataKey\n      | Function((~item: 'legendPayload) => string)\n  }\n  module Legend = {\n    @module(\"recharts\") @react.component\n    external make: (\n      /**\n   * The size of icon in each legend item.\n   * @defaultValue 14\n   */\n      ~iconSize: float=?,\n      /**\n   * The type of icon in each legend item.\n   */\n      ~iconType: LegendType.t=?,\n      /**\n   * The layout of legend items inside the legend container.\n   * @defaultValue horizontal\n   */\n      ~layout: CartesianLayout.t=?,\n      /**\n   * Horizontal alignment of the whole Legend container:\n   *\n   * - `left`: shows the Legend to the left of the chart, and chart width reduces automatically to make space for it.\n   * - `right` shows the Legend to the right of the chart, and chart width reduces automatically.\n   * - `center` shows the Legend in the middle of chart, and chart width remains unchanged.\n   *\n   * The exact behavior changes depending on 'verticalAlign' prop.\n   *\n   * @defaultValue center\n   */\n      ~align: HorizontalAlignmentType.t=?,\n      /**\n   * The color of the icon when the item is inactive.\n   * @defaultValue #ccc\n   */\n      ~inactiveColor: string=?,\n      /**\n   * Function to customize how content is serialized before rendering.\n   *\n   * This should return HTML elements, or strings.\n   *\n   * @example (value, entry, index) => <span style={{ color: 'red' }}>{value}</span>\n   * @example https://codesandbox.io/s/legend-formatter-rmzp9\n   */\n      ~formatter: (~value: 'value, ~entry: 'entry, ~index: int) => React.element=?,\n      /**\n   * The customized event handler of mouseenter on the items in this group\n   * @example https://recharts.github.io/examples/LegendEffectOpacity\n   */\n      ~onMouseEnter: (\n        ~data: 'legendPayload,\n        ~index: int,\n        ~event: mouseEvent<Dom.htmlElement>,\n      ) => unit=?,\n      /**\n   * The customized event handler of mouseleave on the items in this group\n   * @example https://recharts.github.io/examples/LegendEffectOpacity\n   */\n      ~onMouseLeave: (\n        ~data: 'legendPayload,\n        ~index: int,\n        ~event: mouseEvent<Dom.htmlElement>,\n      ) => unit=?,\n      /**\n   * The customized event handler of click on the items in this group\n   */\n      ~onClick: (~data: 'legendPayload, ~index: int, ~event: mouseEvent<Dom.htmlElement>) => unit=?,\n      /**\n   * The style of each text label which is a span element.\n   * @defaultValue {}\n   */\n      ~labelStyle: ReactDOM.Style.t=?,\n      /**\n   * Renders the content of the legend.\n   *\n   * This should return HTML elements, not SVG elements.\n   *\n   * - If not set, the {@link DefaultLegendContent} component is used.\n   * - If set to a React element, this element will be cloned and extra props will be passed in.\n   * - If set to a function, the function will be called and should return HTML elements.\n   *\n   * @example <Legend content={CustomizedLegend} />\n   * @example <Legend content={renderLegend} />\n   */\n      ~content: React.element=?,\n      /**\n   * CSS styles to be applied to the wrapper `div` element.\n   */\n      ~wrapperStyle: ReactDOM.Style.t=?,\n      /**\n   * Width of the legend.\n   * Accept CSS style string values like `100%` or `fit-content`, or number values like `400`.\n   */\n      ~width: Dimension.t=?,\n      /**\n   * Height of the legend.\n   * Accept CSS style string values like `100%` or `fit-content`, or number values like `400`.\n   */\n      ~height: Dimension.t=?,\n      /**\n   * If portal is defined, then Legend will use this element as a target\n   * for rendering using React Portal.\n   *\n   * If this is undefined then Legend renders inside the recharts-wrapper element.\n   *\n   * @see {@link https://react.dev/reference/react-dom/createPortal}\n   */\n      ~portal: Dom.htmlElement=?,\n      /**\n   * Sorts Legend items. Defaults to `value` which means it will sort alphabetically\n   * by the label.\n   *\n   * If `null` is provided then the payload is not sorted. Be aware that without sort,\n   * the order of items may change between renders!\n   *\n   * @defaultValue value\n   */\n      ~itemSorter: LegendItemSorter.t<'payloadItem>=?,\n      /**\n   * The alignment of the whole Legend container:\n   *\n   * - `bottom`: shows the Legend below chart, and chart height reduces automatically to make space for it.\n   * - `top`: shows the Legend above chart, and chart height reduces automatically.\n   * - `middle`:  shows the Legend in the middle of chart, covering other content, and chart height remains unchanged.\n   * The exact behavior changes depending on `align` prop.\n   *\n   * @defaultValue bottom\n   */\n      ~verticalAlign: VerticalAlignmentType.t=?,\n    ) => React.element = \"Legend\"\n  }\n\n  module Bar = {\n    @module(\"recharts\") @react.component\n    external make: (~dataKey: string, ~radius: float=?) => React.element = \"Bar\"\n  }\n\n  module BarChart = {\n    @module(\"recharts\") @react.component\n    external make: (\n      ~data: array<'data>,\n      ~accessibilityLayer: bool=?,\n      ~children: React.element,\n    ) => React.element = \"BarChart\"\n  }\n\n  module GridLineType = {\n    @unboxed\n    type t =\n      | @as(false) NoLine\n      | Custom(React.element)\n  }\n\n  module CartesianGrid = {\n    @module(\"recharts\") @react.component\n    external make: (~vertical: GridLineType.t=?, ~horizontal: GridLineType.t=?) => React.element =\n      \"CartesianGrid\"\n  }\n\n  module XAxis = {\n    @module(\"recharts\") @react.component\n    external make: (\n      ~dataKey: string=?,\n      ~tickLine: bool=?,\n      ~axisLine: bool=?,\n      ~tickMargin: int=?,\n      ~tickFormatter: string => string=?,\n    ) => React.element = \"XAxis\"\n  }\n}\n\nmodule Style = {\n  @react.component\n  let make = (~id: string, ~config: chartConfig) => {\n    let colorConfig =\n      config\n      ->Dict.toArray\n      ->Array.filter(((_, itemConfig)) =>\n        switch itemConfig {\n        | {theme: _} | {color: _} => true\n        | _ => false\n        }\n      )\n    switch colorConfig {\n    | [] => React.null\n    | _ =>\n      let css =\n        [(\"light\", \"\"), (\"dark\", \".dark\")]\n        ->Array.map(((themeName, prefix)) => {\n          let declarations =\n            colorConfig\n            ->Array.filterMap(((key, itemConfig)) =>\n              switch themeColor(~itemConfig, ~themeName) {\n              | Some(color) => Some(`  --color-${key}: ${color};`)\n              | None => None\n              }\n            )\n            ->Array.join(\"\\n\")\n\n          `${prefix} [data-chart=${id}] {\\n${declarations}\\n}`\n        })\n        ->Array.join(\"\\n\\n\")\n      <style\n        dangerouslySetInnerHTML={(\n          {\n            \"__html\": css,\n          }: {\"__html\": string}\n        )}\n      />\n    }\n  }\n}\n\ntype props = {\n  ...BaseUi.Types.DomProps.t,\n  config: chartConfig,\n  initialDimension?: Recharts.Dimensions.t,\n}\n\nlet toBaseUiProps: props => BaseUi.Types.DomProps.t = %raw(`({config, initialDimension, id, ...props}) => props`)\n\n@react.componentWithProps(props)\nlet make = (props: props) => {\n  let config = props.config\n  let initialDimension = props.initialDimension->Option.getOr({width: 320., height: 200.})\n  let children = props.children->Option.getOr(React.null)\n  let id = props.id\n  let uniqueId = React.useId()->String.replaceAll(\":\", \"\")\n  let chartId = switch id {\n  | Some(id) => `chart-${id}`\n  | None => `chart-${uniqueId}`\n  }\n  module Provider = {\n    let make = React.Context.provider(chartContext)\n  }\n  <Provider value={Some({config: config})}>\n    <div\n      {...props->toBaseUiProps}\n      dataSlot={props.dataSlot->Option.getOr(\"chart\")}\n      dataChart={chartId}\n      className={cn(\n        \"flex aspect-video justify-center text-xs [&_.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-dot[stroke='#fff']]:stroke-transparent [&_.recharts-layer]:outline-hidden [&_.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-sector]:outline-hidden [&_.recharts-sector[stroke='#fff']]:stroke-transparent [&_.recharts-surface]:outline-hidden\",\n        props.className,\n      )}\n    >\n      <Style id={chartId} config={config} />\n      <Recharts.ResponsiveContainer initialDimension children />\n    </div>\n  </Provider>\n}\n\nmodule Tooltip = Recharts.Tooltip\n\nmodule Indicator = {\n  @unboxed\n  type t =\n    | @as(\"line\") Line\n    | @as(\"dot\") Dot\n    | @as(\"dashed\") Dashed\n}\n\nmodule TooltipContent = {\n  type props<'value> = {\n    ...BaseUi.Types.DomProps.t,\n    active?: bool,\n    payload?: array<payloadItem<'value>>,\n    indicator?: Indicator.t,\n    hideLabel?: bool,\n    hideIndicator?: bool,\n    labelFormatter?: (option<React.element>, array<payloadItem<'value>>) => React.element,\n    labelClassName?: string,\n    formatter?: ('value, string, payloadItem<'value>, int, dict<string>) => React.element,\n    color?: string,\n    nameKey?: string,\n    labelKey?: string,\n  }\n\n  // Recharts clones custom content with its own options; only DOM props belong on the container.\n  let toBaseUiProps: props<'value> => BaseUi.Types.DomProps.t = %raw(`({\n    active, payload, indicator, hideLabel, hideIndicator, label, labelFormatter,\n    labelClassName, formatter, color, nameKey, labelKey,\n    content, contentStyle, itemStyle, labelStyle, wrapperStyle, wrapperClassName,\n    separator, itemSorter, accessibilityLayer, activeIndex, coordinate, viewBox,\n    allowEscapeViewBox, animationDuration, animationEasing, axisId, cursor,\n    defaultIndex, filterNull, includeHidden, isAnimationActive, offset, payloadUniqBy,\n    portal, position, reverseDirection, shared, trigger, useTranslate3d,\n    ...props\n  }) => props`)\n\n  @react.componentWithProps(props)\n  let make = (props: props<'value>) => {\n    let active = props.active->Option.getOr(false)\n    let payload = props.payload->Option.getOr([])\n    let indicator = props.indicator->Option.getOr(Indicator.Dot)\n    let hideLabel = props.hideLabel->Option.getOr(false)\n    let hideIndicator = props.hideIndicator->Option.getOr(false)\n    let label = props.label\n    let labelFormatter = props.labelFormatter\n    let labelClassName = props.labelClassName\n    let formatter = props.formatter\n    let color = props.color\n    let nameKey = props.nameKey\n    let labelKey = props.labelKey\n    let {config} = use()\n    let tooltipLabel = if hideLabel || payload->Array.length == 0 {\n      None\n    } else {\n      switch payload->Array.get(0) {\n      | None => None\n      | Some(item) =>\n        let key =\n          labelKey->Option.orElse(item.dataKey)->Option.orElse(item.name)->Option.getOr(\"value\")\n        let itemConfig = getPayloadConfigFromPayload(~config, ~payload=item, ~key)\n        let value = switch (labelKey, label) {\n        | (None, Some(label)) =>\n          switch config->Dict.get(label) {\n          | Some(configItem) => Some(configItem.label->Option.getOr(label->React.string))\n          | None => Some(label->React.string)\n          }\n        | _ => itemConfig->Option.flatMap(itemConfig => itemConfig.label)\n        }\n        switch labelFormatter {\n        | Some(formatLabel) =>\n          Some(\n            <div className={cn(\"font-medium\", labelClassName)}>\n              {formatLabel(value, payload)}\n            </div>,\n          )\n        | None =>\n          switch value {\n          | Some(value) => Some(<div className={cn(\"font-medium\", labelClassName)}> {value} </div>)\n          | None => None\n          }\n        }\n      }\n    }\n    switch (active, payload) {\n    | (false, _) | (_, []) => React.null\n    | _ =>\n      let nestLabel = payload->Array.length == 1 && indicator != Indicator.Dot\n      let visiblePayloadItems = payload->Array.filter(item =>\n        switch item.type_ {\n        | Some(\"none\") => false\n        | _ => true\n        }\n      )\n      <div\n        {...props->toBaseUiProps}\n        className={cn(\n          \"border-border/50 bg-background gap-1.5 rounded-lg border px-2.5 py-1.5 text-xs shadow-xl grid min-w-32 items-start\",\n          props.className,\n        )}\n      >\n        {switch (nestLabel, tooltipLabel) {\n        | (false, Some(labelElement)) => labelElement\n        | _ => React.null\n        }}\n        <div className=\"grid gap-1.5\">\n          {visiblePayloadItems\n          ->Array.mapWithIndex((item, index) => {\n            let key =\n              nameKey->Option.orElse(item.name)->Option.orElse(item.dataKey)->Option.getOr(\"value\")\n            let itemConfig = getPayloadConfigFromPayload(~config, ~payload=item, ~key)\n            let indicatorColor =\n              color->Option.orElse(item.payload->Dict.get(\"fill\"))->Option.orElse(item.color)\n            let customContent = switch (formatter, item.value, item.name) {\n            | (Some(customFormatter), Some(value), Some(name)) =>\n              Some(customFormatter(value, name, item, index, item.payload))\n            | _ => None\n            }\n            let rawItemValue = item.value\n            let itemValue = rawItemValue->Option.map(Float.toLocaleString)\n            let shouldShowValue = rawItemValue->Option.isSome\n            let itemLabel =\n              itemConfig\n              ->Option.flatMap(configItem => configItem.label)\n              ->Option.orElse(item.name->Option.map(React.string))\n            let itemKey =\n              item.dataKey\n              ->Option.orElse(item.name)\n              ->Option.getOr(Int.toString(index))\n            <div\n              key={itemKey}\n              className={`[&>svg]:text-muted-foreground flex w-full flex-wrap items-stretch gap-2 [&>svg]:h-2.5 [&>svg]:w-2.5 ${indicator ==\n                  Indicator.Dot\n                  ? \"items-center\"\n                  : \"\"}`}\n            >\n              {switch customContent {\n              | Some(content) => content\n              | None =>\n                <>\n                  {switch itemConfig->Option.flatMap(itemConfig => itemConfig.icon) {\n                  | Some(icon) => icon()\n                  | None =>\n                    hideIndicator\n                      ? React.null\n                      : {\n                          let indicatorClass = switch indicator {\n                          | Indicator.Dot => \"h-2.5 w-2.5\"\n                          | Indicator.Line => \"w-1\"\n                          | Indicator.Dashed =>\n                            `w-0 border-[1.5px] border-dashed bg-transparent ${nestLabel\n                                ? \"my-0.5\"\n                                : \"\"}`\n                          }\n                          let indicatorStyle = indicatorColor->Option.map(color =>\n                            ReactDOM.Style._dictToStyle(\n                              dict{\n                                \"--color-bg\": color,\n                                \"--color-border\": color,\n                              },\n                            )\n                          )\n                          <div\n                            style=?indicatorStyle\n                            className={cn(\n                              \"shrink-0 rounded-[2px] border-(--color-border) bg-(--color-bg)\",\n                              indicatorClass->Some,\n                            )}\n                          />\n                        }\n                  }}\n                  <div\n                    className={`flex flex-1 justify-between leading-none ${nestLabel\n                        ? \"items-end\"\n                        : \"items-center\"}`}\n                  >\n                    <div className=\"grid gap-1.5\">\n                      {switch (nestLabel, tooltipLabel) {\n                      | (true, Some(labelElement)) => labelElement\n                      | _ => React.null\n                      }}\n                      {switch itemLabel {\n                      | Some(itemLabel) =>\n                        <span className=\"text-muted-foreground\"> {itemLabel} </span>\n                      | None => React.null\n                      }}\n                    </div>\n                    {switch (shouldShowValue, itemValue) {\n                    | (true, Some(itemValue)) =>\n                      <span className=\"text-foreground font-mono font-medium tabular-nums\">\n                        {itemValue->React.string}\n                      </span>\n                    | _ => React.null\n                    }}\n                  </div>\n                </>\n              }}\n            </div>\n          })\n          ->React.array}\n        </div>\n      </div>\n    }\n  }\n}\n\nmodule Legend = Recharts.Legend\n\nmodule LegendContent = {\n  type props<'value> = {\n    ...BaseUi.Types.DomProps.t,\n    hideIcon?: bool,\n    payload?: array<payloadItem<'value>>,\n    verticalAlign?: string,\n    nameKey?: string,\n  }\n\n  // Recharts clones custom content with its own options; only DOM props belong on the container.\n  let toBaseUiProps: props<'value> => BaseUi.Types.DomProps.t = %raw(`({\n    hideIcon, payload, verticalAlign, nameKey,\n    content, iconSize, iconType, layout, align, inactiveColor, formatter, labelStyle,\n    wrapperStyle, width, height, payloadUniqBy, onBBoxUpdate, portal, itemSorter,\n    position, offset, margin, chartWidth, chartHeight,\n    ...props\n  }) => props`)\n\n  @react.componentWithProps(props)\n  let make = (props: props<'value>) => {\n    let hideIcon = props.hideIcon->Option.getOr(false)\n    let payload = props.payload->Option.getOr([])\n    let verticalAlign = props.verticalAlign->Option.getOr(\"bottom\")\n    let nameKey = props.nameKey->Option.getOr(\"\")\n    let {config} = use()\n    switch payload {\n    | [] => React.null\n    | _ =>\n      <div\n        {...props->toBaseUiProps}\n        className={cn(\n          `flex items-center justify-center gap-4 ${verticalAlign == \"top\" ? \"pb-3\" : \"pt-3\"}`,\n          props.className,\n        )}\n      >\n        {payload\n        ->Array.filter(item =>\n          switch item.type_ {\n          | Some(\"none\") => false\n          | _ => true\n          }\n        )\n        ->Array.mapWithIndex((item, index) => {\n          let key = if nameKey != \"\" {\n            nameKey\n          } else {\n            item.dataKey->Option.getOr(\"value\")\n          }\n          let itemConfig = getPayloadConfigFromPayload(~config, ~payload=item, ~key)\n          let itemKey = item.dataKey->Option.orElse(item.name)->Option.getOr(Int.toString(index))\n          let colorStyle =\n            item.color->Option.map(color =>\n              ReactDOM.Style._dictToStyle(dict{\"backgroundColor\": color})\n            )\n          <div\n            key={itemKey}\n            className=\"[&>svg]:text-muted-foreground flex items-center gap-1.5 [&>svg]:h-3 [&>svg]:w-3\"\n          >\n            {switch itemConfig->Option.flatMap(itemConfig => itemConfig.icon) {\n            | Some(icon) =>\n              hideIcon\n                ? <div className=\"h-2 w-2 shrink-0 rounded-[2px]\" style=?colorStyle />\n                : icon()\n            | None => <div className=\"h-2 w-2 shrink-0 rounded-[2px]\" style=?colorStyle />\n            }}\n            {itemConfig->Option.flatMap(itemConfig => itemConfig.label)->Option.getOr(React.null)}\n          </div>\n        })\n        ->React.array}\n      </div>\n    }\n  }\n}\n",
      "type": "registry:file",
      "target": "@ui/Chart.res"
    }
  ],
  "type": "registry:ui"
}