@acronis-platform/ui-react 2.0.0 → 4.0.0

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.
Files changed (243) hide show
  1. package/dist/components/ui/accordion-container/accordion-container.js +144 -0
  2. package/dist/components/ui/accordion-container/accordion-container.js.map +1 -0
  3. package/dist/components/ui/app-shell-chat/app-shell-chat.js.map +1 -1
  4. package/dist/components/ui/area-chart/area-chart.js +141 -139
  5. package/dist/components/ui/area-chart/area-chart.js.map +1 -1
  6. package/dist/components/ui/avatar/avatar.js +33 -22
  7. package/dist/components/ui/avatar/avatar.js.map +1 -1
  8. package/dist/components/ui/bar-chart/bar-chart.js +295 -293
  9. package/dist/components/ui/bar-chart/bar-chart.js.map +1 -1
  10. package/dist/components/ui/card/card.js +150 -74
  11. package/dist/components/ui/card/card.js.map +1 -1
  12. package/dist/components/ui/card-section/card-section.js +111 -0
  13. package/dist/components/ui/card-section/card-section.js.map +1 -0
  14. package/dist/components/ui/category-bar/category-bar.js +109 -93
  15. package/dist/components/ui/category-bar/category-bar.js.map +1 -1
  16. package/dist/components/ui/chart/chart-palette.js +113 -0
  17. package/dist/components/ui/chart/chart-palette.js.map +1 -0
  18. package/dist/components/ui/chart/chart.js +176 -129
  19. package/dist/components/ui/chart/chart.js.map +1 -1
  20. package/dist/components/ui/chart-state/chart-state-illustrations.js +310 -0
  21. package/dist/components/ui/chart-state/chart-state-illustrations.js.map +1 -0
  22. package/dist/components/ui/chart-state/chart-state.js +48 -34
  23. package/dist/components/ui/chart-state/chart-state.js.map +1 -1
  24. package/dist/components/ui/chart-widget/chart-widget.js +87 -0
  25. package/dist/components/ui/chart-widget/chart-widget.js.map +1 -0
  26. package/dist/components/ui/composed-chart/composed-chart.js +117 -115
  27. package/dist/components/ui/composed-chart/composed-chart.js.map +1 -1
  28. package/dist/components/ui/confidence-cone/confidence-cone.js +166 -158
  29. package/dist/components/ui/confidence-cone/confidence-cone.js.map +1 -1
  30. package/dist/components/ui/data-table/data-table.js +4 -2
  31. package/dist/components/ui/data-table/data-table.js.map +1 -1
  32. package/dist/components/ui/empty-overlay/empty-overlay.js +49 -0
  33. package/dist/components/ui/empty-overlay/empty-overlay.js.map +1 -0
  34. package/dist/components/ui/funnel-chart/funnel-chart.js +162 -161
  35. package/dist/components/ui/funnel-chart/funnel-chart.js.map +1 -1
  36. package/dist/components/ui/histogram/histogram.js +94 -92
  37. package/dist/components/ui/histogram/histogram.js.map +1 -1
  38. package/dist/components/ui/input/input.js.map +1 -1
  39. package/dist/components/ui/label/label.js +2 -9
  40. package/dist/components/ui/label/label.js.map +1 -1
  41. package/dist/components/ui/line-chart/line-chart.js +143 -141
  42. package/dist/components/ui/line-chart/line-chart.js.map +1 -1
  43. package/dist/components/ui/metric/metric.js +74 -185
  44. package/dist/components/ui/metric/metric.js.map +1 -1
  45. package/dist/components/ui/page-content/page-content.js.map +1 -1
  46. package/dist/components/ui/pie-chart/pie-chart.js +201 -195
  47. package/dist/components/ui/pie-chart/pie-chart.js.map +1 -1
  48. package/dist/components/ui/radar-chart/radar-chart.js +133 -131
  49. package/dist/components/ui/radar-chart/radar-chart.js.map +1 -1
  50. package/dist/components/ui/radial-bar-chart/radial-bar-chart.js +297 -265
  51. package/dist/components/ui/radial-bar-chart/radial-bar-chart.js.map +1 -1
  52. package/dist/components/ui/sankey-chart/sankey-chart.js +123 -101
  53. package/dist/components/ui/sankey-chart/sankey-chart.js.map +1 -1
  54. package/dist/components/ui/scatter-chart/scatter-chart.js +76 -74
  55. package/dist/components/ui/scatter-chart/scatter-chart.js.map +1 -1
  56. package/dist/components/ui/section/section.js +157 -31
  57. package/dist/components/ui/section/section.js.map +1 -1
  58. package/dist/components/ui/stepper/stepper.js +24 -24
  59. package/dist/components/ui/stepper/stepper.js.map +1 -1
  60. package/dist/components/ui/stepper-item/stepper-item.js +43 -24
  61. package/dist/components/ui/stepper-item/stepper-item.js.map +1 -1
  62. package/dist/components/ui/table/table.js +27 -27
  63. package/dist/components/ui/table/table.js.map +1 -1
  64. package/dist/components/ui/treemap/treemap.js +133 -124
  65. package/dist/components/ui/treemap/treemap.js.map +1 -1
  66. package/dist/components/ui/trend-indicator/trend-indicator.js +34 -69
  67. package/dist/components/ui/trend-indicator/trend-indicator.js.map +1 -1
  68. package/dist/components/ui/wizard/wizard.js +59 -0
  69. package/dist/components/ui/wizard/wizard.js.map +1 -0
  70. package/dist/hooks/use-wizard.js +75 -0
  71. package/dist/hooks/use-wizard.js.map +1 -0
  72. package/dist/index.js +540 -525
  73. package/dist/index.js.map +1 -1
  74. package/dist/llms/accordion-container.md +181 -0
  75. package/dist/llms/accordion.md +124 -0
  76. package/dist/llms/alert.md +225 -0
  77. package/dist/llms/app-shell-chat.md +415 -0
  78. package/dist/llms/area-chart.md +355 -0
  79. package/dist/llms/avatar.md +208 -0
  80. package/dist/llms/bar-chart.md +406 -0
  81. package/dist/llms/breadcrumb.md +326 -0
  82. package/dist/llms/button-group.md +298 -0
  83. package/dist/llms/button-icon-input.md +142 -0
  84. package/dist/llms/button-icon-menu.md +209 -0
  85. package/dist/llms/button-icon.md +128 -0
  86. package/dist/llms/button-menu.md +172 -0
  87. package/dist/llms/button.md +185 -0
  88. package/dist/llms/calendar-panel.md +733 -0
  89. package/dist/llms/calendar.md +188 -0
  90. package/dist/llms/card-filter.md +214 -0
  91. package/dist/llms/card-section.md +293 -0
  92. package/dist/llms/card.md +447 -0
  93. package/dist/llms/carousel-dialog.md +156 -0
  94. package/dist/llms/category-bar.md +193 -0
  95. package/dist/llms/chart-state.md +190 -0
  96. package/dist/llms/chart-widget.md +209 -0
  97. package/dist/llms/chart.md +182 -0
  98. package/dist/llms/checkbox.md +257 -0
  99. package/dist/llms/chip.md +195 -0
  100. package/dist/llms/combobox.md +164 -0
  101. package/dist/llms/composed-chart.md +508 -0
  102. package/dist/llms/confidence-cone.md +277 -0
  103. package/dist/llms/data-table.md +474 -0
  104. package/dist/llms/date-range-picker.md +272 -0
  105. package/dist/llms/description-list.md +131 -0
  106. package/dist/llms/dialog-footer-carousel.md +147 -0
  107. package/dist/llms/dialog-footer-default.md +142 -0
  108. package/dist/llms/dialog-root.md +246 -0
  109. package/dist/llms/dialog-welcome.md +223 -0
  110. package/dist/llms/dialog.md +403 -0
  111. package/dist/llms/dropdown-menu.md +193 -0
  112. package/dist/llms/empty-overlay.md +146 -0
  113. package/dist/llms/empty.md +156 -0
  114. package/dist/llms/field.md +185 -0
  115. package/dist/llms/filter-cards.md +157 -0
  116. package/dist/llms/filter-chips.md +323 -0
  117. package/dist/llms/filter-search.md +512 -0
  118. package/dist/llms/form.md +154 -0
  119. package/dist/llms/funnel-chart.md +333 -0
  120. package/dist/llms/grid.md +80 -0
  121. package/dist/llms/histogram.md +190 -0
  122. package/dist/llms/input-date-picker.md +203 -0
  123. package/dist/llms/input-otp.md +173 -0
  124. package/dist/llms/input-password.md +197 -0
  125. package/dist/llms/input-search.md +170 -0
  126. package/dist/llms/input-select.md +278 -0
  127. package/dist/llms/input-text-area.md +271 -0
  128. package/dist/llms/input-text.md +192 -0
  129. package/dist/llms/line-chart.md +369 -0
  130. package/dist/llms/link.md +209 -0
  131. package/dist/llms/loading.md +130 -0
  132. package/dist/llms/meter.md +177 -0
  133. package/dist/llms/metric.md +204 -0
  134. package/dist/llms/number-field.md +122 -0
  135. package/dist/llms/page-content.md +69 -0
  136. package/dist/llms/page-header.md +182 -0
  137. package/dist/llms/pagination.md +133 -0
  138. package/dist/llms/pie-chart.md +307 -0
  139. package/dist/llms/popover.md +252 -0
  140. package/dist/llms/progress-circle.md +126 -0
  141. package/dist/llms/progress.md +111 -0
  142. package/dist/llms/radar-chart.md +316 -0
  143. package/dist/llms/radial-bar-chart.md +319 -0
  144. package/dist/llms/radio.md +255 -0
  145. package/dist/llms/resizable.md +195 -0
  146. package/dist/llms/sankey-chart.md +208 -0
  147. package/dist/llms/scatter-chart.md +239 -0
  148. package/dist/llms/scroll-area.md +183 -0
  149. package/dist/llms/section.md +401 -0
  150. package/dist/llms/select.md +210 -0
  151. package/dist/llms/separator.md +87 -0
  152. package/dist/llms/sheet.md +202 -0
  153. package/dist/llms/sidebar-primary.md +360 -0
  154. package/dist/llms/sidebar-secondary.md +417 -0
  155. package/dist/llms/skeleton.md +81 -0
  156. package/dist/llms/slider.md +97 -0
  157. package/dist/llms/spinner.md +100 -0
  158. package/dist/llms/stack.md +80 -0
  159. package/dist/llms/stepper-item.md +309 -0
  160. package/dist/llms/stepper.md +251 -0
  161. package/dist/llms/switch.md +140 -0
  162. package/dist/llms/table.md +436 -0
  163. package/dist/llms/tabs.md +197 -0
  164. package/dist/llms/tag.md +139 -0
  165. package/dist/llms/timeline.md +361 -0
  166. package/dist/llms/timer.md +259 -0
  167. package/dist/llms/toast.md +241 -0
  168. package/dist/llms/toggle-group.md +121 -0
  169. package/dist/llms/toolbar.md +453 -0
  170. package/dist/llms/tooltip.md +164 -0
  171. package/dist/llms/treemap.md +254 -0
  172. package/dist/llms/trend-indicator.md +132 -0
  173. package/dist/llms/widget-placeholder.md +169 -0
  174. package/dist/llms/wizard.md +412 -0
  175. package/dist/llms.txt +142 -0
  176. package/dist/react.js +540 -525
  177. package/dist/react.js.map +1 -1
  178. package/dist/src/components/ui/accordion-container/accordion-container.d.ts +44 -0
  179. package/dist/src/components/ui/accordion-container/index.d.ts +1 -0
  180. package/dist/src/components/ui/area-chart/area-chart.d.ts +9 -4
  181. package/dist/src/components/ui/avatar/avatar.d.ts +27 -8
  182. package/dist/src/components/ui/bar-chart/bar-chart.d.ts +9 -4
  183. package/dist/src/components/ui/button/button.d.ts +1 -1
  184. package/dist/src/components/ui/card/card.d.ts +69 -8
  185. package/dist/src/components/ui/card/index.d.ts +1 -1
  186. package/dist/src/components/ui/card-section/card-section.d.ts +50 -0
  187. package/dist/src/components/ui/card-section/index.d.ts +1 -0
  188. package/dist/src/components/ui/category-bar/category-bar.d.ts +10 -4
  189. package/dist/src/components/ui/chart/__stories__/palette-control.d.ts +48 -0
  190. package/dist/src/components/ui/chart/__tests__/chart-palette.test.d.ts +1 -0
  191. package/dist/src/components/ui/chart/chart-palette.d.ts +128 -0
  192. package/dist/src/components/ui/chart/chart.d.ts +66 -15
  193. package/dist/src/components/ui/chart/index.d.ts +4 -2
  194. package/dist/src/components/ui/chart-state/chart-state-illustrations.d.ts +6 -0
  195. package/dist/src/components/ui/chart-state/chart-state.d.ts +13 -2
  196. package/dist/src/components/ui/chart-state/index.d.ts +1 -0
  197. package/dist/src/components/ui/chart-widget/chart-widget.d.ts +64 -0
  198. package/dist/src/components/ui/chart-widget/index.d.ts +1 -0
  199. package/dist/src/components/ui/composed-chart/composed-chart.d.ts +12 -7
  200. package/dist/src/components/ui/confidence-cone/confidence-cone.d.ts +10 -5
  201. package/dist/src/components/ui/dialog/dialog.d.ts +1 -1
  202. package/dist/src/components/ui/empty-overlay/empty-overlay.d.ts +20 -0
  203. package/dist/src/components/ui/empty-overlay/index.d.ts +2 -0
  204. package/dist/src/components/ui/funnel-chart/funnel-chart.d.ts +11 -5
  205. package/dist/src/components/ui/grid/grid.d.ts +1 -1
  206. package/dist/src/components/ui/histogram/histogram.d.ts +10 -4
  207. package/dist/src/components/ui/label/index.d.ts +1 -1
  208. package/dist/src/components/ui/label/label.d.ts +1 -5
  209. package/dist/src/components/ui/line-chart/line-chart.d.ts +9 -4
  210. package/dist/src/components/ui/metric/metric.d.ts +13 -14
  211. package/dist/src/components/ui/pie-chart/pie-chart.d.ts +17 -8
  212. package/dist/src/components/ui/radar-chart/radar-chart.d.ts +10 -5
  213. package/dist/src/components/ui/radial-bar-chart/radial-bar-chart.d.ts +17 -6
  214. package/dist/src/components/ui/sankey-chart/sankey-chart.d.ts +10 -5
  215. package/dist/src/components/ui/scatter-chart/scatter-chart.d.ts +10 -5
  216. package/dist/src/components/ui/section/index.d.ts +1 -1
  217. package/dist/src/components/ui/section/section.d.ts +75 -6
  218. package/dist/src/components/ui/sheet/sheet.d.ts +1 -1
  219. package/dist/src/components/ui/stack/stack.d.ts +1 -1
  220. package/dist/src/components/ui/stepper-item/stepper-item.d.ts +6 -5
  221. package/dist/src/components/ui/tag/tag.d.ts +1 -1
  222. package/dist/src/components/ui/treemap/treemap.d.ts +11 -5
  223. package/dist/src/components/ui/trend-indicator/trend-indicator.d.ts +3 -7
  224. package/dist/src/components/ui/wizard/index.d.ts +1 -0
  225. package/dist/src/components/ui/wizard/wizard.d.ts +6 -0
  226. package/dist/src/hooks/index.d.ts +1 -0
  227. package/dist/src/hooks/use-wizard.d.ts +80 -0
  228. package/dist/src/index.d.ts +5 -3
  229. package/dist/ui-react.css +1 -1
  230. package/package.json +12 -6
  231. package/dist/components/ui/app-shell/app-shell.js +0 -75
  232. package/dist/components/ui/app-shell/app-shell.js.map +0 -1
  233. package/dist/components/ui/auth-layout/auth-layout.js +0 -56
  234. package/dist/components/ui/auth-layout/auth-layout.js.map +0 -1
  235. package/dist/components/ui/collapsible/collapsible.js +0 -22
  236. package/dist/components/ui/collapsible/collapsible.js.map +0 -1
  237. package/dist/src/components/ui/app-shell/app-shell.d.ts +0 -8
  238. package/dist/src/components/ui/app-shell/index.d.ts +0 -1
  239. package/dist/src/components/ui/auth-layout/auth-layout.d.ts +0 -6
  240. package/dist/src/components/ui/auth-layout/index.d.ts +0 -1
  241. package/dist/src/components/ui/collapsible/collapsible.d.ts +0 -5
  242. package/dist/src/components/ui/collapsible/index.d.ts +0 -1
  243. package/dist/src/components/ui/label/label.docs.d.ts +0 -10
@@ -1 +1 @@
1
- {"version":3,"file":"sankey-chart.js","sources":["../../../../src/components/ui/sankey-chart/sankey-chart.tsx"],"sourcesContent":["'use client';\n\nimport * as React from 'react';\nimport { Sankey as RechartsSankey, Rectangle } from 'recharts';\n\nimport { cn } from '@/lib/utils';\nimport {\n ChartContainer,\n ChartStyle,\n ChartTooltip,\n type ChartConfig,\n} from '../chart';\n\n// A typed recharts composition over the shared `Chart` primitives — a flow\n// diagram where link width is proportional to the value flowing between nodes.\n// Like Treemap/Funnel it's a single recharts element (`<Sankey>`) themed through\n// custom `node` / `link` renderers (recharts' defaults paint one flat grey and\n// carry no token hooks). No CVA variant: a Sankey's expressiveness is the\n// nodes/links graph + geometry (plain props), not a visual \"mode\".\n//\n// Node `name`s are the color keys: each must match a `config` entry, so they\n// must be CSS-safe (they become part of a `--color-<name>` custom property).\n// The human-readable text comes from `config[name].label`.\n\n/** A node in the flow — `name` is its color/config key (CSS-safe, unique). */\nexport interface SankeyChartNode {\n name: string;\n}\n\n/** A directed flow between two nodes, referenced by their index in `nodes`. */\nexport interface SankeyChartLink {\n /** Index of the source node in `data.nodes`. */\n source: number;\n /** Index of the target node in `data.nodes`. */\n target: number;\n /** Flow magnitude — drives the link's width. */\n value: number;\n /**\n * Ribbon color (any CSS color, e.g. a `var(--ui-*)` token), rendered at **full\n * opacity** so it matches its node bar. Omit to use the target node's color at\n * 35% (the default tinted ribbon).\n */\n color?: string;\n}\n\nexport interface SankeyChartProps\n extends Omit<React.ComponentProps<'div'>, 'children'> {\n /** The graph: `nodes` (color keys) + `links` (source/target indices + value). */\n data: {\n nodes: ReadonlyArray<SankeyChartNode>;\n links: ReadonlyArray<SankeyChartLink>;\n };\n /**\n * Per-node map of `label` / `color`, keyed by the node's `name` (imported from\n * the shared `Chart` primitives). Turned into `--color-<name>` custom\n * properties. Colors are caller-supplied — reference an existing semantic\n * `--ui-*` token; there is no chart palette tier yet.\n */\n config: ChartConfig;\n /** Vertical gap between nodes in the same column. */\n nodePadding?: number;\n /** Thickness of each node bar. */\n nodeWidth?: number;\n /** Curviness of the links (0 = straight, 1 = fully curved). */\n linkCurvature?: number;\n /**\n * Sort nodes vertically to minimize link crossings (recharts' relaxation).\n * Defaults to `false` — nodes render in the order given by `data.nodes` within\n * each column, which keeps curated flows tidy; set `true` to auto-order.\n */\n sort?: boolean;\n /** Render each node's label (from `config[name].label`) beside its bar. */\n showLabels?: boolean;\n /** Render a legend (color dot + label + value + % per node) below the chart. */\n showLegend?: boolean;\n /** Show a hover tooltip on nodes and links (dot + `source → target` + value). */\n showTooltip?: boolean;\n /**\n * Replace the default tooltip. Pass a configured `ChartTooltipContent`\n * (imported from this library) — e.g. with a `formatter` / `labelFormatter` —\n * to customize formatting without composing recharts yourself. Ignored when\n * `showTooltip` is false.\n */\n tooltipContent?: React.ComponentProps<typeof ChartTooltip>['content'];\n}\n\n// recharts injects these into the `node` / `link` render functions but doesn't\n// export their prop types from the package root, so we type the fields we use\n// (structurally compatible with recharts' internal NodeProps / LinkProps).\ninterface SankeyNodeShapeProps {\n x: number;\n y: number;\n width: number;\n height: number;\n index: number;\n payload: { name: string; value: number };\n}\n\ninterface SankeyLinkShapeProps {\n sourceX: number;\n targetX: number;\n sourceY: number;\n targetY: number;\n sourceControlX: number;\n targetControlX: number;\n linkWidth: number;\n // recharts spreads the original link onto `payload` (then overrides\n // source/target with node objects), so a custom `color` survives here.\n payload: {\n source: { name: string };\n target: { name: string };\n value: number;\n color?: string;\n };\n}\n\n// Node bar: a rect filled from `--color-<name>`, with the config label placed on\n// whichever side keeps it inside the plot — to the right for nodes that have\n// outgoing links (sources), to the left for terminal nodes (sinks).\nfunction makeNodeRenderer(\n config: ChartConfig,\n sourceIndices: ReadonlySet<number>,\n showLabels: boolean\n) {\n return function SankeyNodeShape({\n x,\n y,\n width,\n height,\n index,\n payload,\n }: SankeyNodeShapeProps) {\n const name = String(payload.name);\n const label = config[name]?.label ?? name;\n const isSource = sourceIndices.has(index);\n return (\n <g>\n <Rectangle\n x={x}\n y={y}\n width={width}\n height={height}\n fill={`var(--color-${name})`}\n radius={2}\n />\n {showLabels && (\n <text\n x={isSource ? x + width + 6 : x - 6}\n y={y + height / 2}\n textAnchor={isSource ? 'start' : 'end'}\n dominantBaseline=\"middle\"\n className=\"fill-foreground text-xs\"\n >\n {label}\n </text>\n )}\n </g>\n );\n };\n}\n\n// Link ribbon: a bezier stroked at 35% opacity in the link's own `color` if\n// given (recharts preserves custom link fields on the render `payload`), else\n// the **target** node's color (so a flow reads as \"where it goes\"). Drawn as a\n// stroke, not a fill, so the ribbon width comes from `linkWidth`.\nfunction SankeyLinkShape({\n sourceX,\n targetX,\n sourceY,\n targetY,\n sourceControlX,\n targetControlX,\n linkWidth,\n payload,\n}: SankeyLinkShapeProps) {\n const targetName = String(payload.target.name);\n const stroke = payload.color ?? `var(--color-${targetName})`;\n return (\n <path\n d={`M${sourceX},${sourceY}C${sourceControlX},${sourceY} ${targetControlX},${targetY} ${targetX},${targetY}`}\n fill=\"none\"\n stroke={stroke}\n strokeWidth={Math.max(1, linkWidth)}\n // An explicit per-link color is the caller's exact choice — render it at\n // full opacity (so it matches its node bar); the default target-tint is\n // dimmed to 35% so ribbons don't overwhelm the nodes.\n strokeOpacity={payload.color ? 1 : 0.35}\n />\n );\n}\n\n// Default tooltip: recharts' Sankey payload carries no config color, and labels\n// a hovered link \"source - target\" using the node keys (a node is a single key).\n// Parse that name to a color dot (the target node's color) + the mapped config\n// labels joined with an arrow + the value — driven by `config`, so it's reliable\n// where the shared ChartTooltipContent can't resolve the Sankey payload.\n//\n// Exported (module-only, not from the package barrel) so its branches can be\n// unit-tested directly: recharts can't lay out a Sankey in happy-dom, and its\n// hover tooltip has no statically-open form the component exposes, so rendering\n// `<SankeyChart>` never reaches this code.\nexport function makeSankeyTooltip(\n config: ChartConfig,\n links: ReadonlyArray<SankeyChartLink>,\n nodes: ReadonlyArray<SankeyChartNode>\n) {\n const labelFor = (key: string): React.ReactNode => config[key]?.label ?? key;\n // Resolve each link's dot color by its \"source - target\" name (which is the\n // tooltip item's name): the link's own color if set, else the target's, via\n // the `--color-<name>` bridge so a per-theme config resolves too.\n const styleByName = new Map<string, { color: string; opacity: number }>();\n for (const link of links) {\n const source = nodes[link.source]?.name ?? '';\n const target = nodes[link.target]?.name ?? '';\n // Mirror the ribbon: an explicit color renders full-opacity; the default\n // target tint renders at 35%.\n styleByName.set(source + ' - ' + target, {\n color: link.color ?? `var(--color-${target})`,\n opacity: link.color ? 1 : 0.35,\n });\n }\n\n return function SankeyTooltipContent({\n active,\n payload,\n }: {\n active?: boolean;\n payload?: ReadonlyArray<{\n name?: string | number;\n value?: number | string | ReadonlyArray<number | string>;\n }>;\n }) {\n if (!active || !payload?.length) return null;\n const item = payload[0];\n const parts = String(item?.name ?? '').split(' - ');\n const targetKey = parts[parts.length - 1];\n const linkStyle = styleByName.get(String(item?.name ?? ''));\n const dotColor = linkStyle?.color ?? `var(--color-${targetKey})`;\n const dotOpacity = linkStyle?.opacity ?? 1;\n const value = item?.value;\n return (\n <div className=\"flex items-center gap-2 rounded-[var(--ui-tooltip-container-border-radius)] border border-border bg-background px-[var(--ui-tooltip-container-padding-x)] py-[var(--ui-tooltip-container-padding-y)] text-xs text-foreground shadow-md\">\n <span\n className=\"h-2.5 w-2.5 shrink-0 rounded-[2px]\"\n style={{ backgroundColor: dotColor, opacity: dotOpacity }}\n />\n <span className=\"text-muted-foreground\">\n {/* A config label can be any ReactNode, so the arrow-joined label is\n built as nodes rather than stringified. */}\n {parts.map((key, index) => (\n <React.Fragment key={`${key}-${index}`}>\n {index > 0 && ' → '}\n {labelFor(key)}\n </React.Fragment>\n ))}\n </span>\n {value != null && (\n <span className=\"ms-2 font-medium tabular-nums\">\n {formatTooltipValue(value)}\n </span>\n )}\n </div>\n );\n };\n}\n\n// recharts types a tooltip item's value as a scalar *or* a range tuple; a plain\n// `String()` would print \"1,2\" for the tuple, so format each part and join.\nfunction formatTooltipValue(\n value: number | string | ReadonlyArray<number | string>\n): string {\n if (Array.isArray(value)) {\n return value.map((part) => formatTooltipValue(part)).join(' – ');\n }\n return typeof value === 'number'\n ? value.toLocaleString()\n : String(value as string);\n}\n\nconst SankeyChart = React.forwardRef<HTMLDivElement, SankeyChartProps>(\n (\n {\n className,\n config,\n data,\n nodePadding = 24,\n nodeWidth = 12,\n linkCurvature = 0.5,\n sort = false,\n showLabels = true,\n showLegend = false,\n showTooltip = true,\n tooltipContent,\n ...props\n },\n ref\n ) => {\n const uniqueId = React.useId();\n const chartId = `chart-${uniqueId.replace(/:/g, '')}`;\n\n // Node indices that appear as a link `source` have outgoing flow — used by\n // the node renderer to place the label on the readable side.\n const sourceIndices = React.useMemo(\n () => new Set(data.links.map((link) => link.source)),\n [data.links]\n );\n\n const nodeRenderer = React.useMemo(\n () => makeNodeRenderer(config, sourceIndices, showLabels),\n [config, sourceIndices, showLabels]\n );\n\n const defaultTooltip = React.useMemo(\n () => makeSankeyTooltip(config, data.links, data.nodes),\n [config, data.links, data.nodes]\n );\n\n // Per-node value (incoming flow, or outgoing for a source with no incoming)\n // and its share of the largest node — drives the legend's count + %.\n const nodeStats = React.useMemo(() => {\n const incoming = new Map<number, number>();\n const outgoing = new Map<number, number>();\n for (const link of data.links) {\n outgoing.set(link.source, (outgoing.get(link.source) ?? 0) + link.value);\n incoming.set(link.target, (incoming.get(link.target) ?? 0) + link.value);\n }\n const values = data.nodes.map(\n (_, i) => incoming.get(i) ?? outgoing.get(i) ?? 0\n );\n const total = values.length ? Math.max(...values) : 0;\n return data.nodes.map((node, i) => ({\n name: node.name,\n value: values[i],\n pct: total > 0 ? Math.round((values[i] / total) * 100) : 0,\n }));\n }, [data]);\n\n return (\n <div\n ref={ref}\n // The legend sits outside `ChartContainer`, so the root carries its own\n // `--color-<name>` scope for it (the plot and the recharts-portaled\n // tooltip resolve theirs from ChartContainer's).\n data-chart={chartId}\n className={cn('flex flex-col', className)}\n {...props}\n >\n <ChartStyle id={chartId} config={config} />\n <ChartContainer config={config} className=\"min-h-0 flex-1\">\n <RechartsSankey\n data={data as { nodes: SankeyChartNode[]; links: SankeyChartLink[] }}\n node={nodeRenderer}\n link={SankeyLinkShape}\n nodePadding={nodePadding}\n nodeWidth={nodeWidth}\n linkCurvature={linkCurvature}\n sort={sort}\n // recharts defaults to `justify`, which right-aligns sink nodes to\n // the last column — so a terminal node like \"No certification\" would\n // jump to the far right instead of staying at its real depth. `left`\n // positions every node by its distance from the source, keeping the\n // flow's columns intact.\n align=\"left\"\n // Node labels never extend past the plot's right edge: a node in the\n // last column has no outgoing links, so its label is drawn to the\n // LEFT of its bar (see the node renderer). Only a small gutter is\n // needed here — a wide reserve would just shrink the diagram.\n margin={{ top: 8, right: 24, bottom: 8, left: 24 }}\n >\n {showTooltip && (\n <ChartTooltip content={tooltipContent ?? defaultTooltip} />\n )}\n </RechartsSankey>\n </ChartContainer>\n {showLegend && (\n <div\n data-slot=\"sankey-chart-legend\"\n className=\"mt-3 grid grid-cols-2 gap-x-6 gap-y-1.5 text-xs\"\n >\n {nodeStats.map(({ name, value, pct }) => (\n <div key={name} className=\"flex items-center gap-2\">\n <span\n className=\"size-2.5 shrink-0 rounded-sm\"\n style={{ backgroundColor: `var(--color-${name})` }}\n />\n <span className=\"truncate text-muted-foreground\">\n {config[name]?.label ?? name}\n </span>\n <span className=\"ms-auto font-semibold tabular-nums\">\n {value.toLocaleString()}\n </span>\n <span className=\"w-9 shrink-0 text-end tabular-nums text-muted-foreground\">\n {pct}%\n </span>\n </div>\n ))}\n </div>\n )}\n </div>\n );\n }\n);\nSankeyChart.displayName = 'SankeyChart';\n\nexport { SankeyChart };\n"],"names":["makeNodeRenderer","config","sourceIndices","showLabels","x","y","width","height","index","payload","name","label","_a","isSource","jsx","Rectangle","SankeyLinkShape","sourceX","targetX","sourceY","targetY","sourceControlX","targetControlX","linkWidth","targetName","stroke","makeSankeyTooltip","links","nodes","labelFor","key","styleByName","link","source","target","_b","active","item","parts","targetKey","linkStyle","dotColor","dotOpacity","value","jsxs","React","formatTooltipValue","part","SankeyChart","className","data","nodePadding","nodeWidth","linkCurvature","sort","showLegend","showTooltip","tooltipContent","props","ref","chartId","nodeRenderer","defaultTooltip","nodeStats","incoming","outgoing","values","_","i","total","node","cn","ChartStyle","ChartContainer","RechartsSankey","ChartTooltip","pct"],"mappings":"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"}
1
+ {"version":3,"file":"sankey-chart.js","sources":["../../../../src/components/ui/sankey-chart/sankey-chart.tsx"],"sourcesContent":["'use client';\n\nimport * as React from 'react';\nimport { Sankey as RechartsSankey, Rectangle } from 'recharts';\n\nimport { cn } from '@/lib/utils';\nimport {\n ChartContainer,\n ChartStyle,\n resolveChartColors,\n CHART_DEFAULT_PALETTE,\n ChartTooltip,\n type ChartConfig,\n type ChartPalette,\n} from '../chart';\n\n// A typed recharts composition over the shared `Chart` primitives — a flow\n// diagram where link width is proportional to the value flowing between nodes.\n// Like Treemap/Funnel it's a single recharts element (`<Sankey>`) themed through\n// custom `node` / `link` renderers (recharts' defaults paint one flat grey and\n// carry no token hooks). No CVA variant: a Sankey's expressiveness is the\n// nodes/links graph + geometry (plain props), not a visual \"mode\".\n//\n// Node `name`s are the color keys: each must match a `config` entry, so they\n// must be CSS-safe (they become part of a `--color-<name>` custom property).\n// The human-readable text comes from `config[name].label`.\n\n/** A node in the flow — `name` is its color/config key (CSS-safe, unique). */\nexport interface SankeyChartNode {\n name: string;\n}\n\n/** A directed flow between two nodes, referenced by their index in `nodes`. */\nexport interface SankeyChartLink {\n /** Index of the source node in `data.nodes`. */\n source: number;\n /** Index of the target node in `data.nodes`. */\n target: number;\n /** Flow magnitude — drives the link's width. */\n value: number;\n /**\n * Ribbon color (any CSS color, e.g. a `var(--ui-*)` token), rendered at **full\n * opacity** so it matches its node bar. Omit to use the target node's color at\n * 35% (the default tinted ribbon).\n */\n color?: string;\n}\n\nexport interface SankeyChartProps extends Omit<\n React.ComponentProps<'div'>,\n 'children'\n> {\n /**\n * The dataviz palette this chart's series are painted from. Series that\n * state no `color` of their own take a stop of it. See `ChartPalette`.\n */\n palette?: ChartPalette;\n /** The graph: `nodes` (color keys) + `links` (source/target indices + value). */\n data: {\n nodes: ReadonlyArray<SankeyChartNode>;\n links: ReadonlyArray<SankeyChartLink>;\n };\n /**\n * Per-node map of `label` / `icon` / `tone`, keyed by the node's `name`\n * (imported from the shared `Chart` primitives). Turned into `--color-<name>`\n * custom properties. Series take their colour from the container's `palette`;\n * each entry maps a key to a `label` and an optional `tone`.\n */\n config: ChartConfig;\n /** Vertical gap between nodes in the same column. */\n nodePadding?: number;\n /** Thickness of each node bar. */\n nodeWidth?: number;\n /** Curviness of the links (0 = straight, 1 = fully curved). */\n linkCurvature?: number;\n /**\n * Sort nodes vertically to minimize link crossings (recharts' relaxation).\n * Defaults to `false` — nodes render in the order given by `data.nodes` within\n * each column, which keeps curated flows tidy; set `true` to auto-order.\n */\n sort?: boolean;\n /** Render each node's label (from `config[name].label`) beside its bar. */\n showLabels?: boolean;\n /** Render a legend (color dot + label + value + % per node) below the chart. */\n showLegend?: boolean;\n /** Show a hover tooltip on nodes and links (dot + `source → target` + value). */\n showTooltip?: boolean;\n /**\n * Replace the default tooltip. Pass a configured `ChartTooltipContent`\n * (imported from this library) — e.g. with a `formatter` / `labelFormatter` —\n * to customize formatting without composing recharts yourself. Ignored when\n * `showTooltip` is false.\n */\n tooltipContent?: React.ComponentProps<typeof ChartTooltip>['content'];\n}\n\n// recharts injects these into the `node` / `link` render functions but doesn't\n// export their prop types from the package root, so we type the fields we use\n// (structurally compatible with recharts' internal NodeProps / LinkProps).\ninterface SankeyNodeShapeProps {\n x: number;\n y: number;\n width: number;\n height: number;\n index: number;\n payload: { name: string; value: number };\n}\n\ninterface SankeyLinkShapeProps {\n sourceX: number;\n targetX: number;\n sourceY: number;\n targetY: number;\n sourceControlX: number;\n targetControlX: number;\n linkWidth: number;\n // recharts spreads the original link onto `payload` (then overrides\n // source/target with node objects), so a custom `color` survives here.\n payload: {\n source: { name: string };\n target: { name: string };\n value: number;\n color?: string;\n };\n}\n\n// Node bar: a rect filled from `--color-<name>`, with the config label placed on\n// whichever side keeps it inside the plot — to the right for nodes that have\n// outgoing links (sources), to the left for terminal nodes (sinks).\nfunction makeNodeRenderer(\n config: ChartConfig,\n sourceIndices: ReadonlySet<number>,\n showLabels: boolean\n) {\n return function SankeyNodeShape({\n x,\n y,\n width,\n height,\n index,\n payload,\n }: SankeyNodeShapeProps) {\n const name = String(payload.name);\n const label = config[name]?.label ?? name;\n const isSource = sourceIndices.has(index);\n return (\n <g>\n <Rectangle\n x={x}\n y={y}\n width={width}\n height={height}\n fill={`var(--color-${name})`}\n radius={2}\n />\n {showLabels && (\n <text\n x={isSource ? x + width + 6 : x - 6}\n y={y + height / 2}\n textAnchor={isSource ? 'start' : 'end'}\n dominantBaseline=\"middle\"\n className=\"fill-foreground text-xs\"\n >\n {label}\n </text>\n )}\n </g>\n );\n };\n}\n\n// Link ribbon: a bezier stroked at 35% opacity in the link's own `color` if\n// given (recharts preserves custom link fields on the render `payload`), else\n// the **target** node's color (so a flow reads as \"where it goes\"). Drawn as a\n// stroke, not a fill, so the ribbon width comes from `linkWidth`.\nfunction SankeyLinkShape({\n sourceX,\n targetX,\n sourceY,\n targetY,\n sourceControlX,\n targetControlX,\n linkWidth,\n payload,\n}: SankeyLinkShapeProps) {\n const targetName = String(payload.target.name);\n const stroke = payload.color ?? `var(--color-${targetName})`;\n return (\n <path\n d={`M${sourceX},${sourceY}C${sourceControlX},${sourceY} ${targetControlX},${targetY} ${targetX},${targetY}`}\n fill=\"none\"\n stroke={stroke}\n strokeWidth={Math.max(1, linkWidth)}\n // An explicit per-link color is the caller's exact choice — render it at\n // full opacity (so it matches its node bar); the default target-tint is\n // dimmed to 35% so ribbons don't overwhelm the nodes.\n strokeOpacity={payload.color ? 1 : 0.35}\n />\n );\n}\n\n// Default tooltip: recharts' Sankey payload carries no config color, and labels\n// a hovered link \"source - target\" using the node keys (a node is a single key).\n// Parse that name to a color dot (the target node's color) + the mapped config\n// labels joined with an arrow + the value — driven by `config`, so it's reliable\n// where the shared ChartTooltipContent can't resolve the Sankey payload.\n//\n// Exported (module-only, not from the package barrel) so its branches can be\n// unit-tested directly: recharts can't lay out a Sankey in happy-dom, and its\n// hover tooltip has no statically-open form the component exposes, so rendering\n// `<SankeyChart>` never reaches this code.\nexport function makeSankeyTooltip(\n config: ChartConfig,\n links: ReadonlyArray<SankeyChartLink>,\n nodes: ReadonlyArray<SankeyChartNode>\n) {\n const labelFor = (key: string): React.ReactNode => config[key]?.label ?? key;\n // Resolve each link's dot color by its \"source - target\" name (which is the\n // tooltip item's name): the link's own color if set, else the target's, via\n // the `--color-<name>` bridge.\n const styleByName = new Map<string, { color: string; opacity: number }>();\n for (const link of links) {\n const source = nodes[link.source]?.name ?? '';\n const target = nodes[link.target]?.name ?? '';\n // Mirror the ribbon: an explicit color renders full-opacity; the default\n // target tint renders at 35%.\n styleByName.set(source + ' - ' + target, {\n color: link.color ?? `var(--color-${target})`,\n opacity: link.color ? 1 : 0.35,\n });\n }\n\n return function SankeyTooltipContent({\n active,\n payload,\n }: {\n active?: boolean;\n payload?: ReadonlyArray<{\n name?: string | number;\n value?: number | string | ReadonlyArray<number | string>;\n }>;\n }) {\n if (!active || !payload?.length) return null;\n const item = payload[0];\n const parts = String(item?.name ?? '').split(' - ');\n const targetKey = parts[parts.length - 1];\n const linkStyle = styleByName.get(String(item?.name ?? ''));\n const dotColor = linkStyle?.color ?? `var(--color-${targetKey})`;\n const dotOpacity = linkStyle?.opacity ?? 1;\n const value = item?.value;\n return (\n <div className=\"flex items-center gap-2 rounded-[var(--ui-tooltip-container-border-radius)] border border-border bg-background px-[var(--ui-tooltip-container-padding-x)] py-[var(--ui-tooltip-container-padding-y)] text-xs text-foreground shadow-md\">\n <span\n className=\"h-2.5 w-2.5 shrink-0 rounded-[2px]\"\n style={{ backgroundColor: dotColor, opacity: dotOpacity }}\n />\n <span className=\"text-muted-foreground\">\n {/* A config label can be any ReactNode, so the arrow-joined label is\n built as nodes rather than stringified. */}\n {parts.map((key, index) => (\n <React.Fragment key={`${key}-${index}`}>\n {index > 0 && ' → '}\n {labelFor(key)}\n </React.Fragment>\n ))}\n </span>\n {value != null && (\n <span className=\"ms-2 font-medium tabular-nums\">\n {formatTooltipValue(value)}\n </span>\n )}\n </div>\n );\n };\n}\n\n// recharts types a tooltip item's value as a scalar *or* a range tuple; a plain\n// `String()` would print \"1,2\" for the tuple, so format each part and join.\nfunction formatTooltipValue(\n value: number | string | ReadonlyArray<number | string>\n): string {\n if (Array.isArray(value)) {\n return value.map((part) => formatTooltipValue(part)).join(' – ');\n }\n return typeof value === 'number'\n ? value.toLocaleString()\n : String(value as string);\n}\n\nconst SankeyChart = React.forwardRef<HTMLDivElement, SankeyChartProps>(\n (\n {\n className,\n config,\n palette,\n data,\n nodePadding = 24,\n nodeWidth = 12,\n linkCurvature = 0.5,\n sort = false,\n showLabels = true,\n showLegend = false,\n showTooltip = true,\n tooltipContent,\n ...props\n },\n ref\n ) => {\n const uniqueId = React.useId();\n const chartId = `chart-${uniqueId.replace(/:/g, '')}`;\n\n // Node indices that appear as a link `source` have outgoing flow — used by\n // the node renderer to place the label on the readable side.\n const sourceIndices = React.useMemo(\n () => new Set(data.links.map((link) => link.source)),\n [data.links]\n );\n\n const nodeRenderer = React.useMemo(\n () => makeNodeRenderer(config, sourceIndices, showLabels),\n [config, sourceIndices, showLabels]\n );\n\n const defaultTooltip = React.useMemo(\n () => makeSankeyTooltip(config, data.links, data.nodes),\n [config, data.links, data.nodes]\n );\n\n // Per-node value (incoming flow, or outgoing for a source with no incoming)\n // and its share of the largest node — drives the legend's count + %.\n const nodeStats = React.useMemo(() => {\n const incoming = new Map<number, number>();\n const outgoing = new Map<number, number>();\n for (const link of data.links) {\n outgoing.set(\n link.source,\n (outgoing.get(link.source) ?? 0) + link.value\n );\n incoming.set(\n link.target,\n (incoming.get(link.target) ?? 0) + link.value\n );\n }\n const values = data.nodes.map(\n (_, i) => incoming.get(i) ?? outgoing.get(i) ?? 0\n );\n const total = values.length ? Math.max(...values) : 0;\n return data.nodes.map((node, i) => ({\n name: node.name,\n value: values[i],\n pct: total > 0 ? Math.round((values[i] / total) * 100) : 0,\n }));\n }, [data]);\n\n return (\n <div\n ref={ref}\n // The legend sits outside `ChartContainer`, so the root carries its own\n // `--color-<name>` scope for it (the plot and the recharts-portaled\n // tooltip resolve theirs from ChartContainer's).\n data-chart={chartId}\n className={cn('flex flex-col', className)}\n {...props}\n >\n <ChartStyle\n id={chartId}\n config={resolveChartColors(config, palette ?? CHART_DEFAULT_PALETTE)}\n />\n <ChartContainer\n config={config}\n palette={palette}\n className=\"min-h-0 flex-1\"\n >\n <RechartsSankey\n data={\n data as { nodes: SankeyChartNode[]; links: SankeyChartLink[] }\n }\n node={nodeRenderer}\n link={SankeyLinkShape}\n nodePadding={nodePadding}\n nodeWidth={nodeWidth}\n linkCurvature={linkCurvature}\n sort={sort}\n // recharts defaults to `justify`, which right-aligns sink nodes to\n // the last column — so a terminal node like \"No certification\" would\n // jump to the far right instead of staying at its real depth. `left`\n // positions every node by its distance from the source, keeping the\n // flow's columns intact.\n align=\"left\"\n // Node labels never extend past the plot's right edge: a node in the\n // last column has no outgoing links, so its label is drawn to the\n // LEFT of its bar (see the node renderer). Only a small gutter is\n // needed here — a wide reserve would just shrink the diagram.\n margin={{ top: 8, right: 24, bottom: 8, left: 24 }}\n >\n {showTooltip && (\n <ChartTooltip content={tooltipContent ?? defaultTooltip} />\n )}\n </RechartsSankey>\n </ChartContainer>\n {showLegend && (\n <div\n data-slot=\"sankey-chart-legend\"\n className=\"mt-3 grid grid-cols-2 gap-x-6 gap-y-1.5 text-xs\"\n >\n {nodeStats.map(({ name, value, pct }) => (\n <div key={name} className=\"flex items-center gap-2\">\n <span\n className=\"size-2.5 shrink-0 rounded-sm\"\n style={{ backgroundColor: `var(--color-${name})` }}\n />\n <span className=\"truncate text-muted-foreground\">\n {config[name]?.label ?? name}\n </span>\n <span className=\"ms-auto font-semibold tabular-nums\">\n {value.toLocaleString()}\n </span>\n <span className=\"w-9 shrink-0 text-end tabular-nums text-muted-foreground\">\n {pct}%\n </span>\n </div>\n ))}\n </div>\n )}\n </div>\n );\n }\n);\nSankeyChart.displayName = 'SankeyChart';\n\nexport { SankeyChart };\n"],"names":["makeNodeRenderer","config","sourceIndices","showLabels","x","y","width","height","index","payload","name","label","_a","isSource","jsx","Rectangle","SankeyLinkShape","sourceX","targetX","sourceY","targetY","sourceControlX","targetControlX","linkWidth","targetName","stroke","makeSankeyTooltip","links","nodes","labelFor","key","styleByName","link","source","target","_b","active","item","parts","targetKey","linkStyle","dotColor","dotOpacity","value","jsxs","React","formatTooltipValue","part","SankeyChart","className","palette","data","nodePadding","nodeWidth","linkCurvature","sort","showLegend","showTooltip","tooltipContent","props","ref","chartId","nodeRenderer","defaultTooltip","nodeStats","incoming","outgoing","values","_","i","total","node","cn","ChartStyle","resolveChartColors","CHART_DEFAULT_PALETTE","ChartContainer","RechartsSankey","ChartTooltip","pct"],"mappings":";;;;;;AAiIA,SAASA,EACPC,GACAC,GACAC,GACA;AACA,SAAO,SAAyB;AAAA,IAC9B,GAAAC;AAAA,IACA,GAAAC;AAAA,IACA,OAAAC;AAAA,IACA,QAAAC;AAAA,IACA,OAAAC;AAAA,IACA,SAAAC;AAAA,EAAA,GACuB;;AACvB,UAAMC,IAAO,OAAOD,EAAQ,IAAI,GAC1BE,MAAQC,IAAAX,EAAOS,CAAI,MAAX,gBAAAE,EAAc,UAASF,GAC/BG,IAAWX,EAAc,IAAIM,CAAK;AACxC,6BACG,KAAA,EACC,UAAA;AAAA,MAAA,gBAAAM;AAAA,QAACC;AAAA,QAAA;AAAA,UACC,GAAAX;AAAA,UACA,GAAAC;AAAA,UACA,OAAAC;AAAA,UACA,QAAAC;AAAA,UACA,MAAM,eAAeG,CAAI;AAAA,UACzB,QAAQ;AAAA,QAAA;AAAA,MAAA;AAAA,MAETP,KACC,gBAAAW;AAAA,QAAC;AAAA,QAAA;AAAA,UACC,GAAGD,IAAWT,IAAIE,IAAQ,IAAIF,IAAI;AAAA,UAClC,GAAGC,IAAIE,IAAS;AAAA,UAChB,YAAYM,IAAW,UAAU;AAAA,UACjC,kBAAiB;AAAA,UACjB,WAAU;AAAA,UAET,UAAAF;AAAA,QAAA;AAAA,MAAA;AAAA,IACH,GAEJ;AAAA,EAEJ;AACF;AAMA,SAASK,EAAgB;AAAA,EACvB,SAAAC;AAAA,EACA,SAAAC;AAAA,EACA,SAAAC;AAAA,EACA,SAAAC;AAAA,EACA,gBAAAC;AAAA,EACA,gBAAAC;AAAA,EACA,WAAAC;AAAA,EACA,SAAAd;AACF,GAAyB;AACvB,QAAMe,IAAa,OAAOf,EAAQ,OAAO,IAAI,GACvCgB,IAAShB,EAAQ,SAAS,eAAee,CAAU;AACzD,SACE,gBAAAV;AAAA,IAAC;AAAA,IAAA;AAAA,MACC,GAAG,IAAIG,CAAO,IAAIE,CAAO,IAAIE,CAAc,IAAIF,CAAO,IAAIG,CAAc,IAAIF,CAAO,IAAIF,CAAO,IAAIE,CAAO;AAAA,MACzG,MAAK;AAAA,MACL,QAAAK;AAAA,MACA,aAAa,KAAK,IAAI,GAAGF,CAAS;AAAA,MAIlC,eAAed,EAAQ,QAAQ,IAAI;AAAA,IAAA;AAAA,EAAA;AAGzC;AAYO,SAASiB,EACdzB,GACA0B,GACAC,GACA;;AACA,QAAMC,IAAW,CAACC,MAAA;;AAAiC,aAAAlB,IAAAX,EAAO6B,CAAG,MAAV,gBAAAlB,EAAa,UAASkB;AAAA,KAInEC,wBAAkB,IAAA;AACxB,aAAWC,KAAQL,GAAO;AACxB,UAAMM,MAASrB,IAAAgB,EAAMI,EAAK,MAAM,MAAjB,gBAAApB,EAAoB,SAAQ,IACrCsB,MAASC,IAAAP,EAAMI,EAAK,MAAM,MAAjB,gBAAAG,EAAoB,SAAQ;AAG3C,IAAAJ,EAAY,IAAIE,IAAS,QAAQC,GAAQ;AAAA,MACvC,OAAOF,EAAK,SAAS,eAAeE,CAAM;AAAA,MAC1C,SAASF,EAAK,QAAQ,IAAI;AAAA,IAAA,CAC3B;AAAA,EACH;AAEA,SAAO,SAA8B;AAAA,IACnC,QAAAI;AAAA,IACA,SAAA3B;AAAA,EAAA,GAOC;AACD,QAAI,CAAC2B,KAAU,EAAC3B,KAAA,QAAAA,EAAS,QAAQ,QAAO;AACxC,UAAM4B,IAAO5B,EAAQ,CAAC,GAChB6B,IAAQ,QAAOD,KAAA,gBAAAA,EAAM,SAAQ,EAAE,EAAE,MAAM,KAAK,GAC5CE,IAAYD,EAAMA,EAAM,SAAS,CAAC,GAClCE,IAAYT,EAAY,IAAI,QAAOM,KAAA,gBAAAA,EAAM,SAAQ,EAAE,CAAC,GACpDI,KAAWD,KAAA,gBAAAA,EAAW,UAAS,eAAeD,CAAS,KACvDG,KAAaF,KAAA,gBAAAA,EAAW,YAAW,GACnCG,IAAQN,KAAA,gBAAAA,EAAM;AACpB,WACE,gBAAAO,EAAC,OAAA,EAAI,WAAU,0OACb,UAAA;AAAA,MAAA,gBAAA9B;AAAA,QAAC;AAAA,QAAA;AAAA,UACC,WAAU;AAAA,UACV,OAAO,EAAE,iBAAiB2B,GAAU,SAASC,EAAA;AAAA,QAAW;AAAA,MAAA;AAAA,MAE1D,gBAAA5B,EAAC,QAAA,EAAK,WAAU,yBAGb,UAAAwB,EAAM,IAAI,CAACR,GAAKtB,MACf,gBAAAoC,EAACC,EAAM,UAAN,EACE,UAAA;AAAA,QAAArC,IAAQ,KAAK;AAAA,QACbqB,EAASC,CAAG;AAAA,MAAA,EAAA,GAFM,GAAGA,CAAG,IAAItB,CAAK,EAGpC,CACD,GACH;AAAA,MACCmC,KAAS,QACR,gBAAA7B,EAAC,QAAA,EAAK,WAAU,iCACb,UAAAgC,EAAmBH,CAAK,EAAA,CAC3B;AAAA,IAAA,GAEJ;AAAA,EAEJ;AACF;AAIA,SAASG,EACPH,GACQ;AACR,SAAI,MAAM,QAAQA,CAAK,IACdA,EAAM,IAAI,CAACI,MAASD,EAAmBC,CAAI,CAAC,EAAE,KAAK,KAAK,IAE1D,OAAOJ,KAAU,WACpBA,EAAM,eAAA,IACN,OAAOA,CAAe;AAC5B;AAEA,MAAMK,IAAcH,EAAM;AAAA,EACxB,CACE;AAAA,IACE,WAAAI;AAAA,IACA,QAAAhD;AAAA,IACA,SAAAiD;AAAA,IACA,MAAAC;AAAA,IACA,aAAAC,IAAc;AAAA,IACd,WAAAC,IAAY;AAAA,IACZ,eAAAC,IAAgB;AAAA,IAChB,MAAAC,IAAO;AAAA,IACP,YAAApD,IAAa;AAAA,IACb,YAAAqD,IAAa;AAAA,IACb,aAAAC,IAAc;AAAA,IACd,gBAAAC;AAAA,IACA,GAAGC;AAAA,EAAA,GAELC,MACG;AAEH,UAAMC,IAAU,SADChB,EAAM,MAAA,EACW,QAAQ,MAAM,EAAE,CAAC,IAI7C3C,IAAgB2C,EAAM;AAAA,MAC1B,MAAM,IAAI,IAAIM,EAAK,MAAM,IAAI,CAACnB,MAASA,EAAK,MAAM,CAAC;AAAA,MACnD,CAACmB,EAAK,KAAK;AAAA,IAAA,GAGPW,IAAejB,EAAM;AAAA,MACzB,MAAM7C,EAAiBC,GAAQC,GAAeC,CAAU;AAAA,MACxD,CAACF,GAAQC,GAAeC,CAAU;AAAA,IAAA,GAG9B4D,IAAiBlB,EAAM;AAAA,MAC3B,MAAMnB,EAAkBzB,GAAQkD,EAAK,OAAOA,EAAK,KAAK;AAAA,MACtD,CAAClD,GAAQkD,EAAK,OAAOA,EAAK,KAAK;AAAA,IAAA,GAK3Ba,IAAYnB,EAAM,QAAQ,MAAM;AACpC,YAAMoB,wBAAe,IAAA,GACfC,wBAAe,IAAA;AACrB,iBAAWlC,KAAQmB,EAAK;AACtB,QAAAe,EAAS;AAAA,UACPlC,EAAK;AAAA,WACJkC,EAAS,IAAIlC,EAAK,MAAM,KAAK,KAAKA,EAAK;AAAA,QAAA,GAE1CiC,EAAS;AAAA,UACPjC,EAAK;AAAA,WACJiC,EAAS,IAAIjC,EAAK,MAAM,KAAK,KAAKA,EAAK;AAAA,QAAA;AAG5C,YAAMmC,IAAShB,EAAK,MAAM;AAAA,QACxB,CAACiB,GAAGC,MAAMJ,EAAS,IAAII,CAAC,KAAKH,EAAS,IAAIG,CAAC,KAAK;AAAA,MAAA,GAE5CC,IAAQH,EAAO,SAAS,KAAK,IAAI,GAAGA,CAAM,IAAI;AACpD,aAAOhB,EAAK,MAAM,IAAI,CAACoB,GAAMF,OAAO;AAAA,QAClC,MAAME,EAAK;AAAA,QACX,OAAOJ,EAAOE,CAAC;AAAA,QACf,KAAKC,IAAQ,IAAI,KAAK,MAAOH,EAAOE,CAAC,IAAIC,IAAS,GAAG,IAAI;AAAA,MAAA,EACzD;AAAA,IACJ,GAAG,CAACnB,CAAI,CAAC;AAET,WACE,gBAAAP;AAAA,MAAC;AAAA,MAAA;AAAA,QACC,KAAAgB;AAAA,QAIA,cAAYC;AAAA,QACZ,WAAWW,EAAG,iBAAiBvB,CAAS;AAAA,QACvC,GAAGU;AAAA,QAEJ,UAAA;AAAA,UAAA,gBAAA7C;AAAA,YAAC2D;AAAA,YAAA;AAAA,cACC,IAAIZ;AAAA,cACJ,QAAQa,EAAmBzE,GAAQiD,KAAWyB,CAAqB;AAAA,YAAA;AAAA,UAAA;AAAA,UAErE,gBAAA7D;AAAA,YAAC8D;AAAA,YAAA;AAAA,cACC,QAAA3E;AAAA,cACA,SAAAiD;AAAA,cACA,WAAU;AAAA,cAEV,UAAA,gBAAApC;AAAA,gBAAC+D;AAAAA,gBAAA;AAAA,kBACC,MAAA1B;AAAA,kBAGA,MAAMW;AAAA,kBACN,MAAM9C;AAAA,kBACN,aAAAoC;AAAA,kBACA,WAAAC;AAAA,kBACA,eAAAC;AAAA,kBACA,MAAAC;AAAA,kBAMA,OAAM;AAAA,kBAKN,QAAQ,EAAE,KAAK,GAAG,OAAO,IAAI,QAAQ,GAAG,MAAM,GAAA;AAAA,kBAE7C,UAAAE,KACC,gBAAA3C,EAACgE,GAAA,EAAa,SAASpB,KAAkBK,EAAA,CAAgB;AAAA,gBAAA;AAAA,cAAA;AAAA,YAE7D;AAAA,UAAA;AAAA,UAEDP,KACC,gBAAA1C;AAAA,YAAC;AAAA,YAAA;AAAA,cACC,aAAU;AAAA,cACV,WAAU;AAAA,cAET,UAAAkD,EAAU,IAAI,CAAC,EAAE,MAAAtD,GAAM,OAAAiC,GAAO,KAAAoC,EAAA,MAAI;;AACjC,uCAAAnC,EAAC,OAAA,EAAe,WAAU,2BACxB,UAAA;AAAA,kBAAA,gBAAA9B;AAAA,oBAAC;AAAA,oBAAA;AAAA,sBACC,WAAU;AAAA,sBACV,OAAO,EAAE,iBAAiB,eAAeJ,CAAI,IAAA;AAAA,oBAAI;AAAA,kBAAA;AAAA,kBAEnD,gBAAAI,EAAC,UAAK,WAAU,kCACb,kBAAOJ,CAAI,wBAAG,UAASA,GAC1B;AAAA,oCACC,QAAA,EAAK,WAAU,sCACb,UAAAiC,EAAM,kBACT;AAAA,kBACA,gBAAAC,EAAC,QAAA,EAAK,WAAU,4DACb,UAAA;AAAA,oBAAAmC;AAAA,oBAAI;AAAA,kBAAA,EAAA,CACP;AAAA,gBAAA,EAAA,GAbQrE,CAcV;AAAA,eACD;AAAA,YAAA;AAAA,UAAA;AAAA,QACH;AAAA,MAAA;AAAA,IAAA;AAAA,EAIR;AACF;AACAsC,EAAY,cAAc;"}
@@ -1,126 +1,128 @@
1
- import { jsx as t, jsxs as Z } from "react/jsx-runtime";
2
- import * as _ from "react";
3
- import { ScatterChart as q, CartesianGrid as z, XAxis as E, YAxis as I, ZAxis as J, Scatter as O } from "recharts";
4
- import { cn as P } from "../../../lib/utils.js";
5
- import { resolveAnimation as Q, resolveRotatedTickAnchor as U, resolveXAxisTitle as V, resolveXAxisHeight as W, resolveYAxisTitle as K, resolveAxisDomain as tt } from "../chart/chart-format.js";
6
- import { ChartContainer as et, ChartTooltip as rt, ChartTooltipContent as at, ChartLegend as it, ChartLegendContent as ot } from "../chart/chart.js";
7
- const nt = _.forwardRef(
1
+ import { jsx as t, jsxs as _ } from "react/jsx-runtime";
2
+ import * as q from "react";
3
+ import { ScatterChart as z, CartesianGrid as E, XAxis as I, YAxis as J, ZAxis as O, Scatter as P } from "recharts";
4
+ import { cn as Q } from "../../../lib/utils.js";
5
+ import { resolveAnimation as U, resolveRotatedTickAnchor as V, resolveXAxisTitle as W, resolveXAxisHeight as K, resolveYAxisTitle as tt, resolveAxisDomain as et } from "../chart/chart-format.js";
6
+ import { ChartContainer as rt, ChartTooltip as at, ChartTooltipContent as it, ChartLegend as ot, ChartLegendContent as nt } from "../chart/chart.js";
7
+ const st = q.forwardRef(
8
8
  ({
9
9
  className: l,
10
10
  config: c,
11
- series: m,
11
+ palette: m,
12
+ series: h,
12
13
  xKey: i,
13
14
  yKey: o,
14
15
  zKey: r,
15
- zRange: h = [60, 400],
16
- shape: d = "circle",
16
+ zRange: d = [60, 400],
17
+ shape: f = "circle",
17
18
  xAxisLabel: n,
18
19
  yAxisLabel: s,
19
- xUnit: f,
20
- yUnit: u,
21
- showGrid: p = !0,
22
- showTooltip: C = !0,
23
- showLegend: k = !0,
24
- showXAxis: v = !0,
25
- showYAxis: g = !0,
26
- xTickFormatter: x,
27
- yTickFormatter: y,
20
+ xUnit: u,
21
+ yUnit: p,
22
+ showGrid: C = !0,
23
+ showTooltip: k = !0,
24
+ showLegend: v = !0,
25
+ showXAxis: g = !0,
26
+ showYAxis: x = !0,
27
+ xTickFormatter: y,
28
+ yTickFormatter: A,
28
29
  xAxisAngle: a,
29
- xAxisInterval: A,
30
- yAxisTickCount: T,
31
- yAxisDomain: b,
32
- gridDashed: S,
33
- gridHorizontal: D,
34
- gridVertical: L,
35
- tooltipContent: N,
36
- animate: R,
37
- animationDuration: X,
38
- animationBegin: j,
39
- animationEasing: w,
40
- ...F
41
- }, H) => {
42
- const M = Q({
43
- animate: R,
44
- animationDuration: X,
45
- animationBegin: j,
46
- animationEasing: w
47
- }), Y = V(
30
+ xAxisInterval: T,
31
+ yAxisTickCount: b,
32
+ yAxisDomain: S,
33
+ gridDashed: D,
34
+ gridHorizontal: L,
35
+ gridVertical: N,
36
+ tooltipContent: R,
37
+ animate: X,
38
+ animationDuration: j,
39
+ animationBegin: w,
40
+ animationEasing: F,
41
+ ...H
42
+ }, M) => {
43
+ const Y = U({
44
+ animate: X,
45
+ animationDuration: j,
46
+ animationBegin: w,
47
+ animationEasing: F
48
+ }), $ = W(
48
49
  n,
49
50
  "insideBottom",
50
51
  -8
51
- ), $ = K(s), B = tt(b), G = W(n, a);
52
- return /* @__PURE__ */ t("div", { ref: H, className: P(l), ...F, children: /* @__PURE__ */ t(
53
- et,
52
+ ), B = tt(s), G = et(S), Z = K(n, a);
53
+ return /* @__PURE__ */ t("div", { ref: M, className: Q(l), ...H, children: /* @__PURE__ */ t(
54
+ rt,
54
55
  {
55
56
  config: c,
57
+ palette: m,
56
58
  className: "size-full [&_.recharts-label]:fill-foreground",
57
- children: /* @__PURE__ */ Z(
58
- q,
59
+ children: /* @__PURE__ */ _(
60
+ z,
59
61
  {
60
62
  margin: { top: 16, right: 16, bottom: 16, left: 16 },
61
63
  children: [
62
- p && /* @__PURE__ */ t(
63
- z,
64
+ C && /* @__PURE__ */ t(
65
+ E,
64
66
  {
65
- horizontal: D ?? !0,
66
- vertical: L ?? !0,
67
- strokeDasharray: S ? "3 3" : void 0
67
+ horizontal: L ?? !0,
68
+ vertical: N ?? !0,
69
+ strokeDasharray: D ? "3 3" : void 0
68
70
  }
69
71
  ),
70
72
  /* @__PURE__ */ t(
71
- E,
73
+ I,
72
74
  {
73
75
  type: "number",
74
76
  dataKey: i,
75
77
  name: i,
76
- unit: f,
77
- hide: !v,
78
+ unit: u,
79
+ hide: !g,
78
80
  tickLine: !1,
79
81
  axisLine: !1,
80
82
  tickMargin: 8,
81
- tickFormatter: x,
83
+ tickFormatter: y,
82
84
  angle: a,
83
- interval: A,
84
- textAnchor: U(a),
85
- height: G,
86
- label: Y
85
+ interval: T,
86
+ textAnchor: V(a),
87
+ height: Z,
88
+ label: $
87
89
  }
88
90
  ),
89
91
  /* @__PURE__ */ t(
90
- I,
92
+ J,
91
93
  {
92
94
  type: "number",
93
95
  dataKey: o,
94
96
  name: o,
95
- unit: u,
96
- hide: !g,
97
+ unit: p,
98
+ hide: !x,
97
99
  tickLine: !1,
98
100
  axisLine: !1,
99
101
  tickMargin: 8,
100
- tickFormatter: y,
101
- tickCount: T,
102
- domain: B,
102
+ tickFormatter: A,
103
+ tickCount: b,
104
+ domain: G,
103
105
  width: s ? 72 : void 0,
104
- label: $
106
+ label: B
105
107
  }
106
108
  ),
107
- r && /* @__PURE__ */ t(J, { type: "number", dataKey: r, range: h, name: r }),
108
- C && /* @__PURE__ */ t(
109
- rt,
109
+ r && /* @__PURE__ */ t(O, { type: "number", dataKey: r, range: d, name: r }),
110
+ k && /* @__PURE__ */ t(
111
+ at,
110
112
  {
111
113
  cursor: { strokeDasharray: "3 3" },
112
- content: N ?? /* @__PURE__ */ t(at, {})
114
+ content: R ?? /* @__PURE__ */ t(it, {})
113
115
  }
114
116
  ),
115
- k && /* @__PURE__ */ t(it, { content: /* @__PURE__ */ t(ot, {}) }),
116
- m.map((e) => /* @__PURE__ */ t(
117
- O,
117
+ v && /* @__PURE__ */ t(ot, { content: /* @__PURE__ */ t(nt, {}) }),
118
+ h.map((e) => /* @__PURE__ */ t(
119
+ P,
118
120
  {
119
121
  name: e.key,
120
122
  data: e.data,
121
123
  fill: `var(--color-${e.key})`,
122
- shape: d,
123
- ...M
124
+ shape: f,
125
+ ...Y
124
126
  },
125
127
  e.key
126
128
  ))
@@ -131,8 +133,8 @@ const nt = _.forwardRef(
131
133
  ) });
132
134
  }
133
135
  );
134
- nt.displayName = "ScatterChart";
136
+ st.displayName = "ScatterChart";
135
137
  export {
136
- nt as ScatterChart
138
+ st as ScatterChart
137
139
  };
138
140
  //# sourceMappingURL=scatter-chart.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"scatter-chart.js","sources":["../../../../src/components/ui/scatter-chart/scatter-chart.tsx"],"sourcesContent":["'use client';\n\nimport * as React from 'react';\nimport {\n CartesianGrid,\n Scatter,\n ScatterChart as RechartsScatterChart,\n XAxis,\n YAxis,\n ZAxis,\n} from 'recharts';\n\nimport { cn } from '@/lib/utils';\nimport {\n ChartContainer,\n ChartLegend,\n ChartLegendContent,\n ChartTooltip,\n ChartTooltipContent,\n resolveAnimation,\n resolveAxisDomain,\n resolveRotatedTickAnchor,\n resolveXAxisHeight,\n resolveXAxisTitle,\n resolveYAxisTitle,\n type ChartConfig,\n type CartesianChartProps,\n type ChartAnimationProps,\n} from '../chart';\n\n// A typed recharts composition over the shared `Chart` primitives. Unlike the\n// other chart types, a scatter has no visual \"mode\" to model as a CVA variant —\n// its shape is fixed (x/y points, optionally sized by z) and its expressiveness\n// comes from the data mapping. So there is no `cva` axis here (matches the\n// skill's \"usually none\"); marker `shape` and bubble sizing are plain props.\n// Each series carries its own point array (points aren't columns of a shared\n// row the way bar/line/area series are), so the API takes a `series` list rather\n// than `dataKeys` over one `data` array.\nexport type ScatterMarkerShape =\n | 'circle'\n | 'cross'\n | 'diamond'\n | 'square'\n | 'star'\n | 'triangle'\n | 'wye';\n\nexport interface ScatterSeries {\n /** Series key — must match a `config` entry; drives its `--color-<key>` fill and legend label. */\n key: string;\n /** This series' points — each row holds at least `xKey` and `yKey` (and `zKey` when used). */\n data: ReadonlyArray<Record<string, number>>;\n}\n\nexport interface ScatterChartProps\n extends Omit<React.ComponentProps<'div'>, 'children'>,\n CartesianChartProps,\n ChartAnimationProps {\n /** One `<Scatter>` per entry — each with its own point array. Use a single entry for an ungrouped scatter. */\n series: ScatterSeries[];\n /**\n * Per-series map of `label` / `color`, keyed by `series[].key` (imported from\n * the shared `Chart` primitives). Turned into `--color-<key>` custom\n * properties. Colors are caller-supplied — reference an existing semantic\n * `--ui-*` token; there is no chart palette tier yet.\n */\n config: ChartConfig;\n /** Numeric field for the horizontal axis. */\n xKey: string;\n /** Numeric field for the vertical axis. */\n yKey: string;\n /** Unit suffix appended to X-axis tick values (recharts `unit`). */\n xUnit?: string;\n /** Optional numeric field mapped to point size (a bubble chart), via recharts `ZAxis`. */\n zKey?: string;\n /** Point-size range `[min, max]` the `zKey` maps into. Ignored when `zKey` is unset (points use recharts' default size). */\n zRange?: [number, number];\n /** Marker shape for every point. */\n shape?: ScatterMarkerShape;\n showLegend?: boolean;\n}\n\nconst ScatterChart = React.forwardRef<HTMLDivElement, ScatterChartProps>(\n (\n {\n className,\n config,\n series,\n xKey,\n yKey,\n zKey,\n zRange = [60, 400],\n shape = 'circle',\n xAxisLabel,\n yAxisLabel,\n xUnit,\n yUnit,\n showGrid = true,\n showTooltip = true,\n showLegend = true,\n showXAxis = true,\n showYAxis = true,\n xTickFormatter,\n yTickFormatter,\n xAxisAngle,\n xAxisInterval,\n yAxisTickCount,\n yAxisDomain,\n gridDashed,\n gridHorizontal,\n gridVertical,\n tooltipContent,\n animate,\n animationDuration,\n animationBegin,\n animationEasing,\n ...props\n },\n ref\n ) => {\n const animation = resolveAnimation({\n animate,\n animationDuration,\n animationBegin,\n animationEasing,\n });\n // Axis titles: the X title sits below the ticks; the Y title is rotated in\n // the left gutter. Passed to recharts' native `label` (themed via the\n // `.recharts-label` fill selector on the container).\n const xAxisTitle = resolveXAxisTitle(\n xAxisLabel,\n 'insideBottom',\n -8\n );\n const yAxisTitle = resolveYAxisTitle(yAxisLabel);\n\n const yDomain = resolveAxisDomain(yAxisDomain);\n\n const xAxisHeight = resolveXAxisHeight(xAxisLabel, xAxisAngle);\n\n return (\n <div ref={ref} className={cn(className)} {...props}>\n <ChartContainer\n config={config}\n className=\"size-full [&_.recharts-label]:fill-foreground\"\n >\n <RechartsScatterChart\n margin={{ top: 16, right: 16, bottom: 16, left: 16 }}\n >\n {showGrid && (\n <CartesianGrid\n horizontal={gridHorizontal ?? true}\n vertical={gridVertical ?? true}\n strokeDasharray={gridDashed ? '3 3' : undefined}\n />\n )}\n <XAxis\n type=\"number\"\n dataKey={xKey}\n name={xKey}\n unit={xUnit}\n hide={!showXAxis}\n tickLine={false}\n axisLine={false}\n tickMargin={8}\n tickFormatter={xTickFormatter}\n angle={xAxisAngle}\n interval={xAxisInterval}\n textAnchor={resolveRotatedTickAnchor(xAxisAngle)}\n height={xAxisHeight}\n label={xAxisTitle}\n />\n <YAxis\n type=\"number\"\n dataKey={yKey}\n name={yKey}\n unit={yUnit}\n hide={!showYAxis}\n tickLine={false}\n axisLine={false}\n tickMargin={8}\n tickFormatter={yTickFormatter}\n tickCount={yAxisTickCount}\n domain={yDomain}\n width={yAxisLabel ? 72 : undefined}\n label={yAxisTitle}\n />\n {zKey && (\n <ZAxis type=\"number\" dataKey={zKey} range={zRange} name={zKey} />\n )}\n {showTooltip && (\n <ChartTooltip\n cursor={{ strokeDasharray: '3 3' }}\n content={tooltipContent ?? <ChartTooltipContent />}\n />\n )}\n {showLegend && <ChartLegend content={<ChartLegendContent />} />}\n {series.map((s) => (\n <Scatter\n key={s.key}\n name={s.key}\n data={s.data as Record<string, number>[]}\n fill={`var(--color-${s.key})`}\n shape={shape}\n {...animation}\n />\n ))}\n </RechartsScatterChart>\n </ChartContainer>\n </div>\n );\n }\n);\nScatterChart.displayName = 'ScatterChart';\n\nexport { ScatterChart };\n"],"names":["ScatterChart","React","className","config","series","xKey","yKey","zKey","zRange","shape","xAxisLabel","yAxisLabel","xUnit","yUnit","showGrid","showTooltip","showLegend","showXAxis","showYAxis","xTickFormatter","yTickFormatter","xAxisAngle","xAxisInterval","yAxisTickCount","yAxisDomain","gridDashed","gridHorizontal","gridVertical","tooltipContent","animate","animationDuration","animationBegin","animationEasing","props","ref","animation","resolveAnimation","xAxisTitle","resolveXAxisTitle","yAxisTitle","resolveYAxisTitle","yDomain","resolveAxisDomain","xAxisHeight","resolveXAxisHeight","jsx","cn","ChartContainer","jsxs","RechartsScatterChart","CartesianGrid","XAxis","resolveRotatedTickAnchor","YAxis","ZAxis","ChartTooltip","ChartTooltipContent","ChartLegend","ChartLegendContent","s","Scatter"],"mappings":"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"}
1
+ {"version":3,"file":"scatter-chart.js","sources":["../../../../src/components/ui/scatter-chart/scatter-chart.tsx"],"sourcesContent":["'use client';\n\nimport * as React from 'react';\nimport {\n CartesianGrid,\n Scatter,\n ScatterChart as RechartsScatterChart,\n XAxis,\n YAxis,\n ZAxis,\n} from 'recharts';\n\nimport { cn } from '@/lib/utils';\nimport {\n ChartContainer,\n ChartLegend,\n ChartLegendContent,\n ChartTooltip,\n ChartTooltipContent,\n resolveAnimation,\n resolveAxisDomain,\n resolveRotatedTickAnchor,\n resolveXAxisHeight,\n resolveXAxisTitle,\n resolveYAxisTitle,\n type ChartConfig,\n type ChartPalette,\n type CartesianChartProps,\n type ChartAnimationProps,\n} from '../chart';\n\n// A typed recharts composition over the shared `Chart` primitives. Unlike the\n// other chart types, a scatter has no visual \"mode\" to model as a CVA variant —\n// its shape is fixed (x/y points, optionally sized by z) and its expressiveness\n// comes from the data mapping. So there is no `cva` axis here (matches the\n// skill's \"usually none\"); marker `shape` and bubble sizing are plain props.\n// Each series carries its own point array (points aren't columns of a shared\n// row the way bar/line/area series are), so the API takes a `series` list rather\n// than `dataKeys` over one `data` array.\nexport type ScatterMarkerShape =\n | 'circle'\n | 'cross'\n | 'diamond'\n | 'square'\n | 'star'\n | 'triangle'\n | 'wye';\n\nexport interface ScatterSeries {\n /** Series key — must match a `config` entry; drives its `--color-<key>` fill and legend label. */\n key: string;\n /** This series' points — each row holds at least `xKey` and `yKey` (and `zKey` when used). */\n data: ReadonlyArray<Record<string, number>>;\n}\n\nexport interface ScatterChartProps\n extends Omit<React.ComponentProps<'div'>, 'children'>,\n CartesianChartProps,\n ChartAnimationProps {\n /**\n * The dataviz palette this chart's series are painted from. Series that\n * state no `color` of their own take a stop of it. See `ChartPalette`.\n */\n palette?: ChartPalette;\n /** One `<Scatter>` per entry — each with its own point array. Use a single entry for an ungrouped scatter. */\n series: ScatterSeries[];\n /**\n * Per-series map of `label` / `icon` / `tone`, keyed by `series[].key`\n * (imported from the shared `Chart` primitives). Turned into `--color-<key>`\n * custom properties. Series take their colour from the container's `palette`;\n * each entry maps a key to a `label` and an optional `tone`.\n */\n config: ChartConfig;\n /** Numeric field for the horizontal axis. */\n xKey: string;\n /** Numeric field for the vertical axis. */\n yKey: string;\n /** Unit suffix appended to X-axis tick values (recharts `unit`). */\n xUnit?: string;\n /** Optional numeric field mapped to point size (a bubble chart), via recharts `ZAxis`. */\n zKey?: string;\n /** Point-size range `[min, max]` the `zKey` maps into. Ignored when `zKey` is unset (points use recharts' default size). */\n zRange?: [number, number];\n /** Marker shape for every point. */\n shape?: ScatterMarkerShape;\n showLegend?: boolean;\n}\n\nconst ScatterChart = React.forwardRef<HTMLDivElement, ScatterChartProps>(\n (\n {\n className,\n config,\n palette,\n series,\n xKey,\n yKey,\n zKey,\n zRange = [60, 400],\n shape = 'circle',\n xAxisLabel,\n yAxisLabel,\n xUnit,\n yUnit,\n showGrid = true,\n showTooltip = true,\n showLegend = true,\n showXAxis = true,\n showYAxis = true,\n xTickFormatter,\n yTickFormatter,\n xAxisAngle,\n xAxisInterval,\n yAxisTickCount,\n yAxisDomain,\n gridDashed,\n gridHorizontal,\n gridVertical,\n tooltipContent,\n animate,\n animationDuration,\n animationBegin,\n animationEasing,\n ...props\n },\n ref\n ) => {\n const animation = resolveAnimation({\n animate,\n animationDuration,\n animationBegin,\n animationEasing,\n });\n // Axis titles: the X title sits below the ticks; the Y title is rotated in\n // the left gutter. Passed to recharts' native `label` (themed via the\n // `.recharts-label` fill selector on the container).\n const xAxisTitle = resolveXAxisTitle(\n xAxisLabel,\n 'insideBottom',\n -8\n );\n const yAxisTitle = resolveYAxisTitle(yAxisLabel);\n\n const yDomain = resolveAxisDomain(yAxisDomain);\n\n const xAxisHeight = resolveXAxisHeight(xAxisLabel, xAxisAngle);\n\n return (\n <div ref={ref} className={cn(className)} {...props}>\n <ChartContainer\n config={config}\n palette={palette}\n className=\"size-full [&_.recharts-label]:fill-foreground\"\n >\n <RechartsScatterChart\n margin={{ top: 16, right: 16, bottom: 16, left: 16 }}\n >\n {showGrid && (\n <CartesianGrid\n horizontal={gridHorizontal ?? true}\n vertical={gridVertical ?? true}\n strokeDasharray={gridDashed ? '3 3' : undefined}\n />\n )}\n <XAxis\n type=\"number\"\n dataKey={xKey}\n name={xKey}\n unit={xUnit}\n hide={!showXAxis}\n tickLine={false}\n axisLine={false}\n tickMargin={8}\n tickFormatter={xTickFormatter}\n angle={xAxisAngle}\n interval={xAxisInterval}\n textAnchor={resolveRotatedTickAnchor(xAxisAngle)}\n height={xAxisHeight}\n label={xAxisTitle}\n />\n <YAxis\n type=\"number\"\n dataKey={yKey}\n name={yKey}\n unit={yUnit}\n hide={!showYAxis}\n tickLine={false}\n axisLine={false}\n tickMargin={8}\n tickFormatter={yTickFormatter}\n tickCount={yAxisTickCount}\n domain={yDomain}\n width={yAxisLabel ? 72 : undefined}\n label={yAxisTitle}\n />\n {zKey && (\n <ZAxis type=\"number\" dataKey={zKey} range={zRange} name={zKey} />\n )}\n {showTooltip && (\n <ChartTooltip\n cursor={{ strokeDasharray: '3 3' }}\n content={tooltipContent ?? <ChartTooltipContent />}\n />\n )}\n {showLegend && <ChartLegend content={<ChartLegendContent />} />}\n {series.map((s) => (\n <Scatter\n key={s.key}\n name={s.key}\n data={s.data as Record<string, number>[]}\n fill={`var(--color-${s.key})`}\n shape={shape}\n {...animation}\n />\n ))}\n </RechartsScatterChart>\n </ChartContainer>\n </div>\n );\n }\n);\nScatterChart.displayName = 'ScatterChart';\n\nexport { ScatterChart };\n"],"names":["ScatterChart","React","className","config","palette","series","xKey","yKey","zKey","zRange","shape","xAxisLabel","yAxisLabel","xUnit","yUnit","showGrid","showTooltip","showLegend","showXAxis","showYAxis","xTickFormatter","yTickFormatter","xAxisAngle","xAxisInterval","yAxisTickCount","yAxisDomain","gridDashed","gridHorizontal","gridVertical","tooltipContent","animate","animationDuration","animationBegin","animationEasing","props","ref","animation","resolveAnimation","xAxisTitle","resolveXAxisTitle","yAxisTitle","resolveYAxisTitle","yDomain","resolveAxisDomain","xAxisHeight","resolveXAxisHeight","jsx","cn","ChartContainer","jsxs","RechartsScatterChart","CartesianGrid","XAxis","resolveRotatedTickAnchor","YAxis","ZAxis","ChartTooltip","ChartTooltipContent","ChartLegend","ChartLegendContent","s","Scatter"],"mappings":"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"}
@@ -1,37 +1,163 @@
1
- import { jsx as a } from "react/jsx-runtime";
2
- import * as i from "react";
3
- import { cn as n } from "../../../lib/utils.js";
4
- const s = i.forwardRef(
5
- ({ className: e, ...t }, o) => /* @__PURE__ */ a("section", { ref: o, className: n("space-y-4", e), ...t })
1
+ import { jsx as t, jsxs as m, Fragment as x } from "react/jsx-runtime";
2
+ import * as n from "react";
3
+ import { mergeProps as d } from "@base-ui/react/merge-props";
4
+ import { useRender as u } from "@base-ui/react/use-render";
5
+ import { cva as y } from "../../../node_modules/.pnpm/class-variance-authority@0.7.1/node_modules/class-variance-authority/dist/index.js";
6
+ import { cn as f } from "../../../lib/utils.js";
7
+ import { Switch as V } from "../switch/switch.js";
8
+ import { AccordionContainer as j } from "../accordion-container/accordion-container.js";
9
+ import { buttonIconVariants as A } from "../button-icon/button-icon.js";
10
+ const H = y("flex w-full flex-col gap-3", {
11
+ variants: {
12
+ variant: {
13
+ column1: "px-4 pt-4",
14
+ "column2-70-30": "px-4 pt-4",
15
+ grid3: "px-4 pt-4",
16
+ // Flush: the table's own rows run edge-to-edge.
17
+ table: ""
18
+ },
19
+ hasBottomBorder: {
20
+ false: "",
21
+ true: "border-b border-[var(--ui-border-on-surface-divider)]"
22
+ }
23
+ },
24
+ compoundVariants: [
25
+ { variant: "column1", hasBottomBorder: !0, class: "pb-4" },
26
+ { variant: "column2-70-30", hasBottomBorder: !0, class: "pb-4" },
27
+ { variant: "grid3", hasBottomBorder: !0, class: "pb-4" }
28
+ ],
29
+ defaultVariants: {
30
+ variant: "column1",
31
+ hasBottomBorder: !1
32
+ }
33
+ }), g = n.createContext({
34
+ variant: "column1"
35
+ }), v = () => n.useContext(g), P = n.forwardRef(
36
+ ({ className: s, variant: e = "column1", hasBottomBorder: i = !1, render: a, ...c }, l) => {
37
+ const r = n.useMemo(
38
+ () => ({ variant: e ?? "column1" }),
39
+ [e]
40
+ ), o = u({
41
+ render: a,
42
+ ref: l,
43
+ defaultTagName: "section",
44
+ props: d(
45
+ {
46
+ className: f(
47
+ H({ variant: e, hasBottomBorder: i }),
48
+ s
49
+ )
50
+ },
51
+ c
52
+ )
53
+ });
54
+ return /* @__PURE__ */ t(g.Provider, { value: r, children: o });
55
+ }
6
56
  );
7
- s.displayName = "Section";
8
- const c = i.forwardRef(({ className: e, ...t }, o) => /* @__PURE__ */ a("div", { ref: o, className: n("space-y-1", e), ...t }));
9
- c.displayName = "SectionHeader";
10
- const r = i.forwardRef(({ className: e, ...t }, o) => /* @__PURE__ */ a(
11
- "h2",
12
- {
13
- ref: o,
14
- className: n("text-lg font-semibold leading-none tracking-tight", e),
15
- ...t
57
+ P.displayName = "Section";
58
+ const F = n.forwardRef(
59
+ ({
60
+ className: s,
61
+ title: e,
62
+ description: i,
63
+ hasDescription: a = !1,
64
+ isSwitchable: c = !1,
65
+ switchChecked: l,
66
+ defaultSwitchChecked: r,
67
+ onSwitchCheckedChange: o,
68
+ switchDisabled: h,
69
+ switchLabel: N = "Toggle section",
70
+ extras: p,
71
+ actions: b,
72
+ isCollapsible: w = !1,
73
+ collapseLabel: C = "Collapse section",
74
+ render: B,
75
+ children: S,
76
+ ...R
77
+ }, T) => {
78
+ const { variant: k } = v();
79
+ return u({
80
+ render: B,
81
+ ref: T,
82
+ defaultTagName: "div",
83
+ props: d(
84
+ {
85
+ className: f(
86
+ "flex w-full shrink-0 items-center gap-2",
87
+ // The `table` root drops its inset so the rows below can bleed to
88
+ // the page edges; the header re-applies it so the title still lines
89
+ // up with the first column.
90
+ k === "table" && "px-4 pt-4",
91
+ s
92
+ ),
93
+ children: /* @__PURE__ */ m(x, { children: [
94
+ c && /* @__PURE__ */ t(
95
+ V,
96
+ {
97
+ checked: l,
98
+ defaultChecked: r,
99
+ onCheckedChange: o,
100
+ disabled: h,
101
+ "aria-label": N,
102
+ className: "shrink-0"
103
+ }
104
+ ),
105
+ (e || p || a) && /* @__PURE__ */ m("div", { className: "flex min-w-0 flex-1 flex-col items-start justify-center gap-0.5", children: [
106
+ /* @__PURE__ */ m("div", { className: "flex min-w-0 items-center gap-2", children: [
107
+ e && /* @__PURE__ */ t("p", { className: "truncate text-xl leading-6 font-medium text-[var(--ui-text-on-surface-primary)]", children: e }),
108
+ p
109
+ ] }),
110
+ a && /* @__PURE__ */ t("p", { className: "w-full truncate text-sm leading-6 text-[var(--ui-text-on-surface-secondary)]", children: i })
111
+ ] }),
112
+ S,
113
+ b,
114
+ w && /* @__PURE__ */ t(
115
+ j.Trigger,
116
+ {
117
+ "aria-label": C,
118
+ className: A({ variant: "ghost" })
119
+ }
120
+ )
121
+ ] })
122
+ },
123
+ R
124
+ )
125
+ });
16
126
  }
17
- ));
18
- r.displayName = "SectionTitle";
19
- const m = i.forwardRef(({ className: e, ...t }, o) => /* @__PURE__ */ a(
20
- "p",
21
- {
22
- ref: o,
23
- className: n("text-sm text-muted-foreground", e),
24
- ...t
127
+ );
128
+ F.displayName = "SectionHeader";
129
+ const I = n.forwardRef(
130
+ ({ className: s, secondaryContent: e, render: i, children: a, ...c }, l) => {
131
+ const { variant: r } = v(), o = r === "column2-70-30";
132
+ return u({
133
+ render: i,
134
+ ref: l,
135
+ defaultTagName: "div",
136
+ props: d(
137
+ {
138
+ className: f(
139
+ "w-full",
140
+ // Both grid layouts share the same 3-column track; the 70/30 split
141
+ // is a 2:1 span of it, and `grid3` simply lets children flow.
142
+ (o || r === "grid3") && "grid grid-cols-3 items-start gap-4",
143
+ s
144
+ ),
145
+ children: o ? /* @__PURE__ */ m(x, { children: [
146
+ /* @__PURE__ */ t("div", { className: "col-span-2 min-w-0", children: a }),
147
+ e != null && /* @__PURE__ */ t("div", { className: "col-span-1 min-w-0", children: e })
148
+ ] }) : a
149
+ },
150
+ c
151
+ )
152
+ });
25
153
  }
26
- ));
27
- m.displayName = "SectionDescription";
28
- const d = i.forwardRef(({ className: e, ...t }, o) => /* @__PURE__ */ a("div", { ref: o, className: n("pt-2", e), ...t }));
29
- d.displayName = "SectionContent";
154
+ );
155
+ I.displayName = "SectionContent";
30
156
  export {
31
- s as Section,
32
- d as SectionContent,
33
- m as SectionDescription,
34
- c as SectionHeader,
35
- r as SectionTitle
157
+ P as Section,
158
+ I as SectionContent,
159
+ F as SectionHeader,
160
+ H as sectionVariants,
161
+ v as useSectionContext
36
162
  };
37
163
  //# sourceMappingURL=section.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"section.js","sources":["../../../../src/components/ui/section/section.tsx"],"sourcesContent":["import * as React from 'react';\n\nimport { cn } from '@/lib/utils';\n\n// Ported 1:1 from `@acronis-platform`'s `section`. A titled content block —\n// semantic markup parts; the only color is the muted description\n// (`text-muted-foreground` → --ui-text-on-surface-secondary).\nconst Section = React.forwardRef<HTMLElement, React.HTMLAttributes<HTMLElement>>(\n ({ className, ...props }, ref) => (\n <section ref={ref} className={cn('space-y-4', className)} {...props} />\n )\n);\nSection.displayName = 'Section';\n\nconst SectionHeader = React.forwardRef<\n HTMLDivElement,\n React.HTMLAttributes<HTMLDivElement>\n>(({ className, ...props }, ref) => (\n <div ref={ref} className={cn('space-y-1', className)} {...props} />\n));\nSectionHeader.displayName = 'SectionHeader';\n\nconst SectionTitle = React.forwardRef<\n HTMLHeadingElement,\n React.HTMLAttributes<HTMLHeadingElement>\n>(({ className, ...props }, ref) => (\n <h2\n ref={ref}\n className={cn('text-lg font-semibold leading-none tracking-tight', className)}\n {...props}\n />\n));\nSectionTitle.displayName = 'SectionTitle';\n\nconst SectionDescription = React.forwardRef<\n HTMLParagraphElement,\n React.HTMLAttributes<HTMLParagraphElement>\n>(({ className, ...props }, ref) => (\n <p\n ref={ref}\n className={cn('text-sm text-muted-foreground', className)}\n {...props}\n />\n));\nSectionDescription.displayName = 'SectionDescription';\n\nconst SectionContent = React.forwardRef<\n HTMLDivElement,\n React.HTMLAttributes<HTMLDivElement>\n>(({ className, ...props }, ref) => (\n <div ref={ref} className={cn('pt-2', className)} {...props} />\n));\nSectionContent.displayName = 'SectionContent';\n\nexport {\n Section,\n SectionHeader,\n SectionTitle,\n SectionDescription,\n SectionContent,\n};\n"],"names":["Section","React","className","props","ref","jsx","cn","SectionHeader","SectionTitle","SectionDescription","SectionContent"],"mappings":";;;AAOA,MAAMA,IAAUC,EAAM;AAAA,EACpB,CAAC,EAAE,WAAAC,GAAW,GAAGC,EAAA,GAASC,MACxB,gBAAAC,EAAC,WAAA,EAAQ,KAAAD,GAAU,WAAWE,EAAG,aAAaJ,CAAS,GAAI,GAAGC,EAAA,CAAO;AAEzE;AACAH,EAAQ,cAAc;AAEtB,MAAMO,IAAgBN,EAAM,WAG1B,CAAC,EAAE,WAAAC,GAAW,GAAGC,KAASC,wBACzB,OAAA,EAAI,KAAAA,GAAU,WAAWE,EAAG,aAAaJ,CAAS,GAAI,GAAGC,GAAO,CAClE;AACDI,EAAc,cAAc;AAE5B,MAAMC,IAAeP,EAAM,WAGzB,CAAC,EAAE,WAAAC,GAAW,GAAGC,EAAA,GAASC,MAC1B,gBAAAC;AAAA,EAAC;AAAA,EAAA;AAAA,IACC,KAAAD;AAAA,IACA,WAAWE,EAAG,qDAAqDJ,CAAS;AAAA,IAC3E,GAAGC;AAAA,EAAA;AACN,CACD;AACDK,EAAa,cAAc;AAE3B,MAAMC,IAAqBR,EAAM,WAG/B,CAAC,EAAE,WAAAC,GAAW,GAAGC,EAAA,GAASC,MAC1B,gBAAAC;AAAA,EAAC;AAAA,EAAA;AAAA,IACC,KAAAD;AAAA,IACA,WAAWE,EAAG,iCAAiCJ,CAAS;AAAA,IACvD,GAAGC;AAAA,EAAA;AACN,CACD;AACDM,EAAmB,cAAc;AAEjC,MAAMC,IAAiBT,EAAM,WAG3B,CAAC,EAAE,WAAAC,GAAW,GAAGC,KAASC,wBACzB,OAAA,EAAI,KAAAA,GAAU,WAAWE,EAAG,QAAQJ,CAAS,GAAI,GAAGC,GAAO,CAC7D;AACDO,EAAe,cAAc;"}
1
+ {"version":3,"file":"section.js","sources":["../../../../src/components/ui/section/section.tsx"],"sourcesContent":["'use client';\n\nimport * as React from 'react';\nimport { mergeProps } from '@base-ui/react/merge-props';\nimport { useRender } from '@base-ui/react/use-render';\nimport { cva, type VariantProps } from 'class-variance-authority';\n\nimport { cn } from '@/lib/utils';\nimport { Switch } from '@/components/ui/switch';\nimport { buttonIconVariants } from '@/components/ui/button-icon';\nimport { AccordionContainer } from '@/components/ui/accordion-container';\n\n// Figma node 8262:6179 (\"Section\"). A titled band that groups cards — or a\n// table — on a page. Where `Card` owns a single surface and `CardSection`\n// divides a card's body, `Section` is the page-level grouping above both.\n//\n// Padding is variant-dependent, straight from the design. The three card\n// layouts (`column1`, `column2-70-30`, `grid3`) inset their content\n// (`px-4 pt-4`) and deliberately reserve no bottom padding: stacked unbordered\n// sections would otherwise double up their vertical spacing, since the next\n// section already opens with its own `pt-4`. `hasBottomBorder` adds the divider\n// plus the matching `pb-4` that closes the band off. The `table` variant sits\n// completely flush — no root padding at all — so its rows can bleed to the page\n// edges; only the divider still applies, and `SectionHeader` re-applies the\n// inset it drops. This is the same reasoning as `card-section.tsx`'s\n// `table-actions` variant, one level up.\n//\n// `hasHeader` from Figma isn't reproduced as a boolean: this is a compound\n// component (`Section` + `SectionHeader` + `SectionContent`), so a part is\n// simply omitted by the consumer instead of hidden behind a flag — same pattern\n// as `Card`. `SectionHeader`'s own toggles (`hasDescription`, `isSwitchable`,\n// `isCollapsible`) stay booleans because each gates a real sub-part with its\n// own payload.\n//\n// The design's `isCollapsable` variant (`false` / `true-expanded` /\n// `true-collapsed`) is implemented by composing `Section` with\n// `AccordionContainer` — the shared disclosure primitive — exactly like `Card`:\n// wrap header + content, set `SectionHeader`'s `isCollapsible` to render the\n// trigger, and restyle that trigger with `buttonIconVariants({ variant:\n// 'ghost' })` because Figma's `ButtonCollapse` is a real ghost `ButtonIcon`.\n//\n// No dedicated `--ui-section-*` token tier exists in tokens-pd (same as\n// `Card` / `CardSection`), so the chrome rides on the shared semantic tier.\n\nconst sectionVariants = cva('flex w-full flex-col gap-3', {\n variants: {\n variant: {\n column1: 'px-4 pt-4',\n 'column2-70-30': 'px-4 pt-4',\n grid3: 'px-4 pt-4',\n // Flush: the table's own rows run edge-to-edge.\n table: '',\n },\n hasBottomBorder: {\n false: '',\n true: 'border-b border-[var(--ui-border-on-surface-divider)]',\n },\n },\n compoundVariants: [\n { variant: 'column1', hasBottomBorder: true, class: 'pb-4' },\n { variant: 'column2-70-30', hasBottomBorder: true, class: 'pb-4' },\n { variant: 'grid3', hasBottomBorder: true, class: 'pb-4' },\n ],\n defaultVariants: {\n variant: 'column1',\n hasBottomBorder: false,\n },\n});\n\ntype SectionVariant = NonNullable<\n VariantProps<typeof sectionVariants>['variant']\n>;\n\ninterface SectionContextValue {\n variant: SectionVariant;\n}\n\n// `SectionContent` and `SectionHeader` need the root's content layout without\n// the consumer repeating `variant` on every part, so the root publishes it.\nconst SectionContext = React.createContext<SectionContextValue>({\n variant: 'column1',\n});\n\n/**\n * Reads the content layout of the nearest `Section` ancestor. Falls back to\n * `column1` for a part rendered outside a `Section`.\n */\nconst useSectionContext = () => React.useContext(SectionContext);\n\nexport interface SectionProps\n extends\n React.HTMLAttributes<HTMLElement>,\n VariantProps<typeof sectionVariants> {\n /**\n * Replace the rendered `<section>` with another element or component (Base UI\n * composition).\n */\n render?: useRender.RenderProp;\n}\n\nconst Section = React.forwardRef<HTMLElement, SectionProps>(\n (\n { className, variant = 'column1', hasBottomBorder = false, render, ...props },\n ref\n ) => {\n const contextValue = React.useMemo<SectionContextValue>(\n () => ({ variant: variant ?? 'column1' }),\n [variant]\n );\n\n const rendered = useRender({\n render,\n ref,\n defaultTagName: 'section',\n props: mergeProps<'section'>(\n {\n className: cn(\n sectionVariants({ variant, hasBottomBorder }),\n className\n ),\n },\n props\n ),\n });\n\n return (\n <SectionContext.Provider value={contextValue}>\n {rendered}\n </SectionContext.Provider>\n );\n }\n);\nSection.displayName = 'Section';\n\nexport interface SectionHeaderProps extends Omit<\n React.HTMLAttributes<HTMLDivElement>,\n 'title'\n> {\n /** The section's title. Renders nothing when omitted. */\n title?: string;\n /** Helper text shown under the title; only rendered when `hasDescription`. */\n description?: string;\n /** Shows `description` below the title. */\n hasDescription?: boolean;\n /** Shows a toggle switch at the start of the header. */\n isSwitchable?: boolean;\n /** Controlled checked state of the header switch. */\n switchChecked?: boolean;\n /** Uncontrolled initial checked state of the header switch. */\n defaultSwitchChecked?: boolean;\n /** Fires when the header switch is toggled. */\n onSwitchCheckedChange?: (checked: boolean) => void;\n /** Disables the header switch. */\n switchDisabled?: boolean;\n /** Accessible label for the header switch. */\n switchLabel?: string;\n /** Extra content rendered inline next to the title (e.g. a tag or badge). */\n extras?: React.ReactNode;\n /** Actions rendered at the end of the header (e.g. a button). */\n actions?: React.ReactNode;\n /**\n * Shows a disclosure trigger at the end of the header. Only has an effect\n * when this header renders inside a collapsible `AccordionContainer` —\n * see the collapsible composition example.\n */\n isCollapsible?: boolean;\n /** Accessible label for the collapse trigger. */\n collapseLabel?: string;\n /**\n * Replace the rendered `<div>` with another element or component (Base UI\n * composition).\n */\n render?: useRender.RenderProp;\n}\n\nconst SectionHeader = React.forwardRef<HTMLDivElement, SectionHeaderProps>(\n (\n {\n className,\n title,\n description,\n hasDescription = false,\n isSwitchable = false,\n switchChecked,\n defaultSwitchChecked,\n onSwitchCheckedChange,\n switchDisabled,\n switchLabel = 'Toggle section',\n extras,\n actions,\n isCollapsible = false,\n collapseLabel = 'Collapse section',\n render,\n children,\n ...props\n },\n ref\n ) => {\n const { variant } = useSectionContext();\n\n return useRender({\n render,\n ref,\n defaultTagName: 'div',\n props: mergeProps<'div'>(\n {\n className: cn(\n 'flex w-full shrink-0 items-center gap-2',\n // The `table` root drops its inset so the rows below can bleed to\n // the page edges; the header re-applies it so the title still lines\n // up with the first column.\n variant === 'table' && 'px-4 pt-4',\n className\n ),\n children: (\n <>\n {isSwitchable && (\n <Switch\n checked={switchChecked}\n defaultChecked={defaultSwitchChecked}\n onCheckedChange={onSwitchCheckedChange}\n disabled={switchDisabled}\n aria-label={switchLabel}\n className=\"shrink-0\"\n />\n )}\n {/* Gated as a whole: an empty wrapper would still claim the\n header row's free space through `flex-1` and push a\n consumer-supplied heading (`children`) to the end. */}\n {(title || extras || hasDescription) && (\n <div className=\"flex min-w-0 flex-1 flex-col items-start justify-center gap-0.5\">\n <div className=\"flex min-w-0 items-center gap-2\">\n {title && (\n <p className=\"truncate text-xl leading-6 font-medium text-[var(--ui-text-on-surface-primary)]\">\n {title}\n </p>\n )}\n {extras}\n </div>\n {hasDescription && (\n <p className=\"w-full truncate text-sm leading-6 text-[var(--ui-text-on-surface-secondary)]\">\n {description}\n </p>\n )}\n </div>\n )}\n {children}\n {actions}\n {isCollapsible && (\n <AccordionContainer.Trigger\n aria-label={collapseLabel}\n className={buttonIconVariants({ variant: 'ghost' })}\n />\n )}\n </>\n ),\n },\n props\n ),\n });\n }\n);\nSectionHeader.displayName = 'SectionHeader';\n\nexport interface SectionContentProps\n extends React.HTMLAttributes<HTMLDivElement> {\n /**\n * The narrow (~30%) second column of the `column2-70-30` layout. Ignored by\n * every other variant, which has only one content area.\n */\n secondaryContent?: React.ReactNode;\n /**\n * Replace the rendered `<div>` with another element or component (Base UI\n * composition).\n */\n render?: useRender.RenderProp;\n}\n\nconst SectionContent = React.forwardRef<HTMLDivElement, SectionContentProps>(\n ({ className, secondaryContent, render, children, ...props }, ref) => {\n const { variant } = useSectionContext();\n const isTwoColumn = variant === 'column2-70-30';\n\n return useRender({\n render,\n ref,\n defaultTagName: 'div',\n props: mergeProps<'div'>(\n {\n className: cn(\n 'w-full',\n // Both grid layouts share the same 3-column track; the 70/30 split\n // is a 2:1 span of it, and `grid3` simply lets children flow.\n (isTwoColumn || variant === 'grid3') &&\n 'grid grid-cols-3 items-start gap-4',\n className\n ),\n children: isTwoColumn ? (\n <>\n <div className=\"col-span-2 min-w-0\">{children}</div>\n {secondaryContent != null && (\n <div className=\"col-span-1 min-w-0\">{secondaryContent}</div>\n )}\n </>\n ) : (\n children\n ),\n },\n props\n ),\n });\n }\n);\nSectionContent.displayName = 'SectionContent';\n\nexport {\n Section,\n SectionHeader,\n SectionContent,\n sectionVariants,\n useSectionContext,\n type SectionVariant,\n};\n"],"names":["sectionVariants","cva","SectionContext","React","useSectionContext","Section","className","variant","hasBottomBorder","render","props","ref","contextValue","rendered","useRender","mergeProps","cn","SectionHeader","title","description","hasDescription","isSwitchable","switchChecked","defaultSwitchChecked","onSwitchCheckedChange","switchDisabled","switchLabel","extras","actions","isCollapsible","collapseLabel","children","jsxs","Fragment","jsx","Switch","AccordionContainer","buttonIconVariants","SectionContent","secondaryContent","isTwoColumn"],"mappings":"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"}