@handled-ai/design-system 0.8.0 → 0.9.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 (336) hide show
  1. package/README.md +14 -4
  2. package/dist/charts/bar-chart-component.d.ts +24 -0
  3. package/dist/charts/bar-chart-component.js +123 -0
  4. package/dist/charts/bar-chart-component.js.map +1 -0
  5. package/dist/charts/chart-tooltip.d.ts +26 -0
  6. package/dist/charts/chart-tooltip.js +69 -0
  7. package/dist/charts/chart-tooltip.js.map +1 -0
  8. package/dist/charts/chart.d.ts +64 -0
  9. package/dist/charts/chart.js +285 -0
  10. package/dist/charts/chart.js.map +1 -0
  11. package/dist/charts/donut-chart.d.ts +21 -0
  12. package/dist/charts/donut-chart.js +96 -0
  13. package/dist/charts/donut-chart.js.map +1 -0
  14. package/dist/charts/index.d.ts +11 -0
  15. package/dist/charts/index.js +10 -0
  16. package/dist/charts/index.js.map +1 -0
  17. package/dist/charts/pipeline-overview.d.ts +76 -0
  18. package/dist/charts/pipeline-overview.js +372 -0
  19. package/dist/charts/pipeline-overview.js.map +1 -0
  20. package/dist/charts/sankey-chart.d.ts +52 -0
  21. package/dist/charts/sankey-chart.js +219 -0
  22. package/dist/charts/sankey-chart.js.map +1 -0
  23. package/dist/charts/top-line-metrics.d.ts +26 -0
  24. package/dist/charts/top-line-metrics.js +224 -0
  25. package/dist/charts/top-line-metrics.js.map +1 -0
  26. package/dist/charts/trend-area-chart.d.ts +21 -0
  27. package/dist/charts/trend-area-chart.js +150 -0
  28. package/dist/charts/trend-area-chart.js.map +1 -0
  29. package/dist/charts/volume-analysis-chart.d.ts +19 -0
  30. package/dist/charts/volume-analysis-chart.js +121 -0
  31. package/dist/charts/volume-analysis-chart.js.map +1 -0
  32. package/dist/components/activity-detail.d.ts +38 -0
  33. package/dist/components/activity-detail.js +163 -0
  34. package/dist/components/activity-detail.js.map +1 -0
  35. package/dist/components/activity-log.d.ts +21 -0
  36. package/dist/components/activity-log.js +61 -0
  37. package/dist/components/activity-log.js.map +1 -0
  38. package/dist/components/agent-popover.d.ts +71 -0
  39. package/dist/components/agent-popover.js +282 -0
  40. package/dist/components/agent-popover.js.map +1 -0
  41. package/dist/components/agent-widget.d.ts +24 -0
  42. package/dist/components/agent-widget.js +117 -0
  43. package/dist/components/agent-widget.js.map +1 -0
  44. package/dist/components/avatar.d.ts +13 -0
  45. package/dist/components/avatar.js +140 -0
  46. package/dist/components/avatar.js.map +1 -0
  47. package/dist/components/badge.d.ts +12 -0
  48. package/dist/components/badge.js +75 -0
  49. package/dist/components/badge.js.map +1 -0
  50. package/dist/components/button.d.ts +13 -0
  51. package/dist/components/button.js +83 -0
  52. package/dist/components/button.js.map +1 -0
  53. package/dist/components/card.d.ts +11 -0
  54. package/dist/components/card.js +119 -0
  55. package/dist/components/card.js.map +1 -0
  56. package/dist/components/contact-list.d.ts +34 -0
  57. package/dist/components/contact-list.js +84 -0
  58. package/dist/components/contact-list.js.map +1 -0
  59. package/dist/components/dashboard-cards.d.ts +10 -0
  60. package/dist/components/dashboard-cards.js +164 -0
  61. package/dist/components/dashboard-cards.js.map +1 -0
  62. package/dist/components/data-table-display.d.ts +19 -0
  63. package/dist/components/data-table-display.js +109 -0
  64. package/dist/components/data-table-display.js.map +1 -0
  65. package/dist/components/data-table-filter.d.ts +18 -0
  66. package/dist/components/data-table-filter.js +107 -0
  67. package/dist/components/data-table-filter.js.map +1 -0
  68. package/dist/components/data-table-quick-views.d.ts +13 -0
  69. package/dist/components/data-table-quick-views.js +90 -0
  70. package/dist/components/data-table-quick-views.js.map +1 -0
  71. package/dist/components/data-table-toolbar.d.ts +18 -0
  72. package/dist/components/data-table-toolbar.js +45 -0
  73. package/dist/components/data-table-toolbar.js.map +1 -0
  74. package/dist/components/data-table.d.ts +39 -0
  75. package/dist/components/data-table.js +821 -0
  76. package/dist/components/data-table.js.map +1 -0
  77. package/dist/components/detail-view.d.ts +44 -0
  78. package/dist/components/detail-view.js +165 -0
  79. package/dist/components/detail-view.js.map +1 -0
  80. package/dist/components/dialog.d.ts +19 -0
  81. package/dist/components/dialog.js +188 -0
  82. package/dist/components/dialog.js.map +1 -0
  83. package/dist/components/dropdown-menu.d.ts +27 -0
  84. package/dist/components/dropdown-menu.js +279 -0
  85. package/dist/components/dropdown-menu.js.map +1 -0
  86. package/dist/components/entity-panel.d.ts +69 -0
  87. package/dist/components/entity-panel.js +584 -0
  88. package/dist/components/entity-panel.js.map +1 -0
  89. package/dist/components/inbox-row.d.ts +27 -0
  90. package/dist/components/inbox-row.js +139 -0
  91. package/dist/components/inbox-row.js.map +1 -0
  92. package/dist/components/inbox-toolbar.d.ts +21 -0
  93. package/dist/components/inbox-toolbar.js +203 -0
  94. package/dist/components/inbox-toolbar.js.map +1 -0
  95. package/dist/components/input.d.ts +5 -0
  96. package/dist/components/input.js +50 -0
  97. package/dist/components/input.js.map +1 -0
  98. package/dist/components/insights-filter-bar.d.ts +21 -0
  99. package/dist/components/insights-filter-bar.js +99 -0
  100. package/dist/components/insights-filter-bar.js.map +1 -0
  101. package/dist/components/item-list-display.d.ts +22 -0
  102. package/dist/components/item-list-display.js +240 -0
  103. package/dist/components/item-list-display.js.map +1 -0
  104. package/dist/components/item-list-filter.d.ts +16 -0
  105. package/dist/components/item-list-filter.js +87 -0
  106. package/dist/components/item-list-filter.js.map +1 -0
  107. package/dist/components/item-list-toolbar.d.ts +25 -0
  108. package/dist/components/item-list-toolbar.js +79 -0
  109. package/dist/components/item-list-toolbar.js.map +1 -0
  110. package/dist/components/item-list.d.ts +20 -0
  111. package/dist/components/item-list.js +702 -0
  112. package/dist/components/item-list.js.map +1 -0
  113. package/dist/components/label.d.ts +6 -0
  114. package/dist/components/label.js +55 -0
  115. package/dist/components/label.js.map +1 -0
  116. package/dist/components/message.d.ts +23 -0
  117. package/dist/components/message.js +117 -0
  118. package/dist/components/message.js.map +1 -0
  119. package/dist/components/metric-card.d.ts +25 -0
  120. package/dist/components/metric-card.js +107 -0
  121. package/dist/components/metric-card.js.map +1 -0
  122. package/dist/components/performance-metrics-table.d.ts +38 -0
  123. package/dist/components/performance-metrics-table.js +342 -0
  124. package/dist/components/performance-metrics-table.js.map +1 -0
  125. package/dist/components/preview-list.d.ts +14 -0
  126. package/dist/components/preview-list.js +83 -0
  127. package/dist/components/preview-list.js.map +1 -0
  128. package/dist/components/progress.d.ts +6 -0
  129. package/dist/components/progress.js +69 -0
  130. package/dist/components/progress.js.map +1 -0
  131. package/dist/components/quick-action-chat-area.d.ts +24 -0
  132. package/dist/components/quick-action-chat-area.js +178 -0
  133. package/dist/components/quick-action-chat-area.js.map +1 -0
  134. package/dist/components/quick-action-modal.d.ts +30 -0
  135. package/dist/components/quick-action-modal.js +288 -0
  136. package/dist/components/quick-action-modal.js.map +1 -0
  137. package/dist/components/quick-action-sidebar-nav.d.ts +51 -0
  138. package/dist/components/quick-action-sidebar-nav.js +528 -0
  139. package/dist/components/quick-action-sidebar-nav.js.map +1 -0
  140. package/dist/components/recommended-actions-section.d.ts +23 -0
  141. package/dist/components/recommended-actions-section.js +215 -0
  142. package/dist/components/recommended-actions-section.js.map +1 -0
  143. package/dist/components/report-card.d.ts +26 -0
  144. package/dist/components/report-card.js +69 -0
  145. package/dist/components/report-card.js.map +1 -0
  146. package/dist/components/score-analysis-modal.d.ts +26 -0
  147. package/dist/components/score-analysis-modal.js +141 -0
  148. package/dist/components/score-analysis-modal.js.map +1 -0
  149. package/dist/components/score-breakdown.d.ts +17 -0
  150. package/dist/components/score-breakdown.js +162 -0
  151. package/dist/components/score-breakdown.js.map +1 -0
  152. package/dist/components/score-feedback.d.ts +40 -0
  153. package/dist/components/score-feedback.js +209 -0
  154. package/dist/components/score-feedback.js.map +1 -0
  155. package/dist/components/score-ring.d.ts +14 -0
  156. package/dist/components/score-ring.js +79 -0
  157. package/dist/components/score-ring.js.map +1 -0
  158. package/dist/components/scroll-area.d.ts +7 -0
  159. package/dist/components/scroll-area.js +101 -0
  160. package/dist/components/scroll-area.js.map +1 -0
  161. package/dist/components/select.d.ts +17 -0
  162. package/dist/components/select.js +228 -0
  163. package/dist/components/select.js.map +1 -0
  164. package/dist/components/separator.d.ts +6 -0
  165. package/dist/components/separator.js +61 -0
  166. package/dist/components/separator.js.map +1 -0
  167. package/dist/components/sheet.d.ts +16 -0
  168. package/dist/components/sheet.js +168 -0
  169. package/dist/components/sheet.js.map +1 -0
  170. package/dist/components/sidebar.d.ts +73 -0
  171. package/dist/components/sidebar.js +723 -0
  172. package/dist/components/sidebar.js.map +1 -0
  173. package/dist/components/signal-feedback-inline.d.ts +51 -0
  174. package/dist/components/signal-feedback-inline.js +548 -0
  175. package/dist/components/signal-feedback-inline.js.map +1 -0
  176. package/dist/components/simple-data-table.d.ts +15 -0
  177. package/dist/components/simple-data-table.js +91 -0
  178. package/dist/components/simple-data-table.js.map +1 -0
  179. package/dist/components/skeleton.d.ts +5 -0
  180. package/dist/components/skeleton.js +44 -0
  181. package/dist/components/skeleton.js.map +1 -0
  182. package/dist/components/status-badge.d.ts +10 -0
  183. package/dist/components/status-badge.js +82 -0
  184. package/dist/components/status-badge.js.map +1 -0
  185. package/dist/components/styled-bar-list.d.ts +20 -0
  186. package/dist/components/styled-bar-list.js +59 -0
  187. package/dist/components/styled-bar-list.js.map +1 -0
  188. package/dist/components/suggested-actions.d.ts +110 -0
  189. package/dist/components/suggested-actions.js +1538 -0
  190. package/dist/components/suggested-actions.js.map +1 -0
  191. package/dist/components/table.d.ts +12 -0
  192. package/dist/components/table.js +147 -0
  193. package/dist/components/table.js.map +1 -0
  194. package/dist/components/tabs.d.ts +14 -0
  195. package/dist/components/tabs.js +129 -0
  196. package/dist/components/tabs.js.map +1 -0
  197. package/dist/components/textarea.d.ts +5 -0
  198. package/dist/components/textarea.js +47 -0
  199. package/dist/components/textarea.js.map +1 -0
  200. package/dist/components/timeline-activity.d.ts +34 -0
  201. package/dist/components/timeline-activity.js +181 -0
  202. package/dist/components/timeline-activity.js.map +1 -0
  203. package/dist/components/tooltip.d.ts +9 -0
  204. package/dist/components/tooltip.js +93 -0
  205. package/dist/components/tooltip.js.map +1 -0
  206. package/dist/components/view-mode-toggle.d.ts +16 -0
  207. package/dist/components/view-mode-toggle.js +24 -0
  208. package/dist/components/view-mode-toggle.js.map +1 -0
  209. package/dist/hooks/use-mobile.d.ts +3 -0
  210. package/dist/hooks/use-mobile.js +21 -0
  211. package/dist/hooks/use-mobile.js.map +1 -0
  212. package/dist/index.d.ts +68 -1878
  213. package/dist/index.js +69 -10918
  214. package/dist/index.js.map +1 -1
  215. package/dist/lib/icons.d.ts +18 -0
  216. package/dist/lib/icons.js +21 -0
  217. package/dist/lib/icons.js.map +1 -0
  218. package/dist/lib/utils.d.ts +5 -0
  219. package/dist/lib/utils.js +9 -0
  220. package/dist/lib/utils.js.map +1 -0
  221. package/dist/prototype/index.d.ts +20 -0
  222. package/dist/prototype/index.js +8 -0
  223. package/dist/prototype/index.js.map +1 -0
  224. package/dist/prototype/prototype-accounts-view.d.ts +22 -0
  225. package/dist/prototype/prototype-accounts-view.js +70 -0
  226. package/dist/prototype/prototype-accounts-view.js.map +1 -0
  227. package/dist/prototype/prototype-admin-view.d.ts +21 -0
  228. package/dist/prototype/prototype-admin-view.js +53 -0
  229. package/dist/prototype/prototype-admin-view.js.map +1 -0
  230. package/dist/prototype/prototype-config.d.ts +226 -0
  231. package/dist/prototype/prototype-config.js +1 -0
  232. package/dist/prototype/prototype-config.js.map +1 -0
  233. package/dist/prototype/prototype-inbox-view.d.ts +48 -0
  234. package/dist/prototype/prototype-inbox-view.js +701 -0
  235. package/dist/prototype/prototype-inbox-view.js.map +1 -0
  236. package/dist/prototype/prototype-insights-view.d.ts +23 -0
  237. package/dist/prototype/prototype-insights-view.js +335 -0
  238. package/dist/prototype/prototype-insights-view.js.map +1 -0
  239. package/dist/prototype/prototype-shell.d.ts +40 -0
  240. package/dist/prototype/prototype-shell.js +190 -0
  241. package/dist/prototype/prototype-shell.js.map +1 -0
  242. package/dist/prototype/prototype-work-queue-view.d.ts +8 -0
  243. package/dist/prototype/prototype-work-queue-view.js +17 -0
  244. package/dist/prototype/prototype-work-queue-view.js.map +1 -0
  245. package/dist/three/agent-orb.d.ts +39 -0
  246. package/dist/three/agent-orb.js +500 -0
  247. package/dist/three/agent-orb.js.map +1 -0
  248. package/dist/three/index.d.ts +2 -0
  249. package/dist/three/index.js +2 -0
  250. package/dist/three/index.js.map +1 -0
  251. package/package.json +98 -17
  252. package/src/charts/bar-chart-component.tsx +150 -0
  253. package/src/charts/chart-tooltip.tsx +86 -0
  254. package/src/charts/chart.tsx +371 -0
  255. package/src/charts/donut-chart.tsx +112 -0
  256. package/src/charts/index.ts +13 -0
  257. package/src/charts/pipeline-overview.tsx +476 -0
  258. package/src/charts/sankey-chart.tsx +290 -0
  259. package/src/charts/top-line-metrics.tsx +261 -0
  260. package/src/charts/trend-area-chart.tsx +150 -0
  261. package/src/charts/volume-analysis-chart.tsx +124 -0
  262. package/src/components/activity-detail.tsx +233 -0
  263. package/src/components/activity-log.tsx +89 -0
  264. package/src/components/agent-popover.tsx +373 -0
  265. package/src/components/agent-widget.tsx +163 -0
  266. package/src/components/avatar.tsx +109 -0
  267. package/src/components/badge.tsx +48 -0
  268. package/src/components/button.tsx +59 -0
  269. package/src/components/card.tsx +92 -0
  270. package/src/components/contact-list.tsx +121 -0
  271. package/src/components/dashboard-cards.tsx +170 -0
  272. package/src/components/data-table-display.tsx +139 -0
  273. package/src/components/data-table-filter.tsx +138 -0
  274. package/src/components/data-table-quick-views.tsx +103 -0
  275. package/src/components/data-table-toolbar.tsx +56 -0
  276. package/src/components/data-table.tsx +915 -0
  277. package/src/components/detail-view.tsx +237 -0
  278. package/src/components/dialog.tsx +158 -0
  279. package/src/components/dropdown-menu.tsx +257 -0
  280. package/src/components/entity-panel.tsx +767 -0
  281. package/src/components/inbox-row.tsx +132 -0
  282. package/src/components/inbox-toolbar.tsx +213 -0
  283. package/src/components/input.tsx +21 -0
  284. package/src/components/insights-filter-bar.tsx +132 -0
  285. package/src/components/item-list-display.tsx +278 -0
  286. package/src/components/item-list-filter.tsx +118 -0
  287. package/src/components/item-list-toolbar.tsx +97 -0
  288. package/src/components/item-list.tsx +843 -0
  289. package/src/components/label.tsx +24 -0
  290. package/src/components/message.tsx +83 -0
  291. package/src/components/metric-card.tsx +178 -0
  292. package/src/components/performance-metrics-table.tsx +442 -0
  293. package/src/components/preview-list.tsx +62 -0
  294. package/src/components/progress.tsx +31 -0
  295. package/src/components/quick-action-chat-area.tsx +156 -0
  296. package/src/components/quick-action-modal.tsx +331 -0
  297. package/src/components/quick-action-sidebar-nav.tsx +592 -0
  298. package/src/components/recommended-actions-section.tsx +258 -0
  299. package/src/components/report-card.tsx +106 -0
  300. package/src/components/score-analysis-modal.tsx +172 -0
  301. package/src/components/score-breakdown.tsx +179 -0
  302. package/src/components/score-feedback.tsx +288 -0
  303. package/src/components/score-ring.tsx +87 -0
  304. package/src/components/scroll-area.tsx +58 -0
  305. package/src/components/select.tsx +190 -0
  306. package/src/components/separator.tsx +28 -0
  307. package/src/components/sheet.tsx +143 -0
  308. package/src/components/sidebar.tsx +726 -0
  309. package/src/components/signal-feedback-inline.tsx +591 -0
  310. package/src/components/simple-data-table.tsx +124 -0
  311. package/src/components/skeleton.tsx +15 -0
  312. package/src/components/status-badge.tsx +63 -0
  313. package/src/components/styled-bar-list.tsx +70 -0
  314. package/src/components/suggested-actions.tsx +1985 -0
  315. package/src/components/table.tsx +116 -0
  316. package/src/components/tabs.tsx +91 -0
  317. package/src/components/textarea.tsx +18 -0
  318. package/src/components/timeline-activity.tsx +234 -0
  319. package/src/components/tooltip.tsx +57 -0
  320. package/src/components/view-mode-toggle.tsx +39 -0
  321. package/src/hooks/use-mobile.ts +21 -0
  322. package/src/index.ts +77 -0
  323. package/src/lib/icons.ts +18 -0
  324. package/src/lib/utils.ts +6 -0
  325. package/src/prototype/index.ts +11 -0
  326. package/src/prototype/prototype-accounts-view.tsx +112 -0
  327. package/src/prototype/prototype-admin-view.tsx +67 -0
  328. package/src/prototype/prototype-config.ts +243 -0
  329. package/src/prototype/prototype-inbox-view.tsx +810 -0
  330. package/src/prototype/prototype-insights-view.tsx +379 -0
  331. package/src/prototype/prototype-shell.tsx +219 -0
  332. package/src/prototype/prototype-work-queue-view.tsx +30 -0
  333. package/src/styles/globals.css +299 -0
  334. package/src/three/agent-orb.tsx +557 -0
  335. package/src/three/index.ts +5 -0
  336. package/src/types/r3f.d.ts +8 -0
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/charts/chart.tsx"],"sourcesContent":["\"use client\";\n\nimport * as React from \"react\";\nimport * as RechartsPrimitive from \"recharts\";\n\nimport { cn } from \"../lib/utils\";\n\n// Format: { THEME_NAME: CSS_SELECTOR }\nconst THEMES = { light: \"\", dark: \".dark\" } as const;\n\nexport type ChartConfig = {\n [k in string]: {\n label?: React.ReactNode;\n icon?: React.ComponentType;\n } & (\n | { color?: string; theme?: never }\n | { color?: never; theme: Record<keyof typeof THEMES, string> }\n );\n};\n\ntype ChartContextProps = {\n config: ChartConfig;\n};\n\nconst ChartContext = React.createContext<ChartContextProps | null>(null);\n\nfunction useChart() {\n const context = React.useContext(ChartContext);\n\n if (!context) {\n throw new Error(\"useChart must be used within a <ChartContainer />\");\n }\n\n return context;\n}\n\nfunction ChartContainer({\n id,\n className,\n children,\n config,\n ...props\n}: React.ComponentProps<\"div\"> & {\n config: ChartConfig;\n children: React.ComponentProps<\n typeof RechartsPrimitive.ResponsiveContainer\n >[\"children\"];\n}) {\n const uniqueId = React.useId();\n const chartId = `chart-${id || uniqueId.replace(/:/g, \"\")}`;\n\n return (\n <ChartContext.Provider value={{ config }}>\n <div\n data-slot=\"chart\"\n data-chart={chartId}\n className={cn(\n \"[&_.recharts-cartesian-axis-tick_text]:fill-muted-foreground [&_.recharts-cartesian-grid_line[stroke='#ccc']]:stroke-border/50 [&_.recharts-curve.recharts-tooltip-cursor]:stroke-border [&_.recharts-polar-grid_[stroke='#ccc']]:stroke-border [&_.recharts-radial-bar-background-sector]:fill-muted [&_.recharts-rectangle.recharts-tooltip-cursor]:fill-muted [&_.recharts-reference-line_[stroke='#ccc']]:stroke-border flex aspect-video justify-center text-xs [&_.recharts-dot[stroke='#fff']]:stroke-transparent [&_.recharts-layer]:outline-hidden [&_.recharts-sector]:outline-hidden [&_.recharts-sector[stroke='#fff']]:stroke-transparent [&_.recharts-surface]:outline-hidden\",\n className,\n )}\n {...props}\n >\n <ChartStyle id={chartId} config={config} />\n <RechartsPrimitive.ResponsiveContainer>\n {children}\n </RechartsPrimitive.ResponsiveContainer>\n </div>\n </ChartContext.Provider>\n );\n}\n\nconst ChartStyle = ({ id, config }: { id: string; config: ChartConfig }) => {\n const colorConfig = Object.entries(config).filter(\n ([, config]) => config.theme || config.color,\n );\n\n if (!colorConfig.length) {\n return null;\n }\n\n return (\n <style\n dangerouslySetInnerHTML={{\n __html: Object.entries(THEMES)\n .map(\n ([theme, prefix]) => `\n${prefix} [data-chart=${id}] {\n${colorConfig\n .map(([key, itemConfig]) => {\n const color =\n itemConfig.theme?.[theme as keyof typeof itemConfig.theme] ||\n itemConfig.color;\n return color ? ` --color-${key}: ${color};` : null;\n })\n .join(\"\\n\")}\n}\n`,\n )\n .join(\"\\n\"),\n }}\n />\n );\n};\n\nconst ChartTooltip = RechartsPrimitive.Tooltip;\n\ntype TooltipPayloadItem = {\n name?: string;\n value?: number | string;\n dataKey?: string;\n payload?: Record<string, unknown>;\n color?: string;\n fill?: string;\n};\n\nfunction ChartTooltipContent({\n active,\n payload,\n className,\n indicator = \"dot\",\n hideLabel = false,\n hideIndicator = false,\n label,\n labelFormatter,\n labelClassName,\n formatter,\n color,\n nameKey,\n labelKey,\n}: React.ComponentProps<\"div\"> & {\n active?: boolean;\n payload?: TooltipPayloadItem[];\n label?: string;\n labelFormatter?: (value: unknown, payload: TooltipPayloadItem[]) => React.ReactNode;\n formatter?: (value: unknown, name: string, item: TooltipPayloadItem, index: number, payload: Record<string, unknown>) => React.ReactNode;\n hideLabel?: boolean;\n hideIndicator?: boolean;\n indicator?: \"line\" | \"dot\" | \"dashed\";\n nameKey?: string;\n labelKey?: string;\n labelClassName?: string;\n color?: string;\n}) {\n const { config } = useChart();\n\n const tooltipLabel = React.useMemo(() => {\n if (hideLabel || !payload?.length) {\n return null;\n }\n\n const [item] = payload;\n const key = `${labelKey || item?.dataKey || item?.name || \"value\"}`;\n const itemConfig = getPayloadConfigFromPayload(config, item, key);\n const value =\n !labelKey && typeof label === \"string\"\n ? config[label as keyof typeof config]?.label || label\n : itemConfig?.label;\n\n if (labelFormatter) {\n return (\n <div className={cn(\"font-medium\", labelClassName)}>\n {labelFormatter(value, payload)}\n </div>\n );\n }\n\n if (!value) {\n return null;\n }\n\n return <div className={cn(\"font-medium\", labelClassName)}>{value}</div>;\n }, [\n label,\n labelFormatter,\n payload,\n hideLabel,\n labelClassName,\n config,\n labelKey,\n ]);\n\n if (!active || !payload?.length) {\n return null;\n }\n\n const nestLabel = payload.length === 1 && indicator !== \"dot\";\n\n return (\n <div\n className={cn(\n \"border-border/50 bg-background grid min-w-[8rem] items-start gap-1.5 rounded-lg border px-2.5 py-1.5 text-xs shadow-xl\",\n className,\n )}\n >\n {!nestLabel ? tooltipLabel : null}\n <div className=\"grid gap-1.5\">\n {payload.map((item: TooltipPayloadItem, index: number) => {\n const key = `${nameKey || item.name || item.dataKey || \"value\"}`;\n const itemConfig = getPayloadConfigFromPayload(config, item, key);\n const indicatorColor = color || item.payload?.fill || item.color;\n\n return (\n <div\n key={item.dataKey}\n className={cn(\n \"[&>svg]:text-muted-foreground flex w-full flex-wrap items-stretch gap-2 [&>svg]:h-2.5 [&>svg]:w-2.5\",\n indicator === \"dot\" && \"items-center\",\n )}\n >\n {formatter && item?.value !== undefined && item.name ? (\n formatter(item.value, item.name, item, index, item.payload ?? {})\n ) : (\n <>\n {itemConfig?.icon ? (\n <itemConfig.icon />\n ) : (\n !hideIndicator && (\n <div\n className={cn(\n \"shrink-0 rounded-[2px] border-(--color-border) bg-(--color-bg)\",\n {\n \"h-2.5 w-2.5\": indicator === \"dot\",\n \"w-1\": indicator === \"line\",\n \"w-0 border-[1.5px] border-dashed bg-transparent\":\n indicator === \"dashed\",\n \"my-0.5\": nestLabel && indicator === \"dashed\",\n },\n )}\n style={\n {\n \"--color-bg\": indicatorColor,\n \"--color-border\": indicatorColor,\n } as React.CSSProperties\n }\n />\n )\n )}\n <div\n className={cn(\n \"flex flex-1 justify-between leading-none\",\n nestLabel ? \"items-end\" : \"items-center\",\n )}\n >\n <div className=\"grid gap-1.5\">\n {nestLabel ? tooltipLabel : null}\n <span className=\"text-muted-foreground\">\n {itemConfig?.label || item.name}\n </span>\n </div>\n {item.value && (\n <span className=\"text-foreground font-mono font-medium tabular-nums\">\n {item.value.toLocaleString()}\n </span>\n )}\n </div>\n </>\n )}\n </div>\n );\n })}\n </div>\n </div>\n );\n}\n\nconst ChartLegend = RechartsPrimitive.Legend;\n\ntype LegendPayloadItem = { value?: string; dataKey?: string; [key: string]: unknown };\n\nfunction ChartLegendContent({\n className,\n hideIcon = false,\n payload,\n verticalAlign = \"bottom\",\n nameKey,\n}: React.ComponentProps<\"div\"> & {\n payload?: LegendPayloadItem[];\n verticalAlign?: \"top\" | \"bottom\";\n hideIcon?: boolean;\n nameKey?: string;\n}) {\n const { config } = useChart();\n\n if (!payload?.length) {\n return null;\n }\n\n return (\n <div\n className={cn(\n \"flex items-center justify-center gap-4\",\n verticalAlign === \"top\" ? \"pb-3\" : \"pt-3\",\n className,\n )}\n >\n {payload.map((item: LegendPayloadItem) => {\n const key = `${nameKey || item.dataKey || \"value\"}`;\n const itemConfig = getPayloadConfigFromPayload(config, item, key);\n\n return (\n <div\n key={item.value}\n className={cn(\n \"[&>svg]:text-muted-foreground flex items-center gap-1.5 [&>svg]:h-3 [&>svg]:w-3\",\n )}\n >\n {itemConfig?.icon && !hideIcon ? (\n <itemConfig.icon />\n ) : (\n <div\n className=\"h-2 w-2 shrink-0 rounded-[2px]\"\n style={{\n backgroundColor: item.color as string | undefined,\n }}\n />\n )}\n {itemConfig?.label}\n </div>\n );\n })}\n </div>\n );\n}\n\n// Helper to extract item config from a payload.\nfunction getPayloadConfigFromPayload(\n config: ChartConfig,\n payload: unknown,\n key: string,\n) {\n if (typeof payload !== \"object\" || payload === null) {\n return undefined;\n }\n\n const payloadPayload =\n \"payload\" in payload &&\n typeof payload.payload === \"object\" &&\n payload.payload !== null\n ? payload.payload\n : undefined;\n\n let configLabelKey: string = key;\n\n if (\n key in payload &&\n typeof payload[key as keyof typeof payload] === \"string\"\n ) {\n configLabelKey = payload[key as keyof typeof payload] as string;\n } else if (\n payloadPayload &&\n key in payloadPayload &&\n typeof payloadPayload[key as keyof typeof payloadPayload] === \"string\"\n ) {\n configLabelKey = payloadPayload[\n key as keyof typeof payloadPayload\n ] as string;\n }\n\n return configLabelKey in config\n ? config[configLabelKey]\n : config[key as keyof typeof config];\n}\n\nexport {\n ChartContainer,\n ChartTooltip,\n ChartTooltipContent,\n ChartLegend,\n ChartLegendContent,\n ChartStyle,\n};\n"],"mappings":"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","names":["config"]}
@@ -0,0 +1,21 @@
1
+ import * as React from 'react';
2
+
3
+ interface DonutSegment {
4
+ name: string;
5
+ value: number;
6
+ color: string;
7
+ }
8
+ interface DonutChartProps {
9
+ data: DonutSegment[];
10
+ centerLabel?: string | number;
11
+ size?: number;
12
+ innerRadius?: number;
13
+ outerRadius?: number;
14
+ paddingAngle?: number;
15
+ showTooltip?: boolean;
16
+ showLegend?: boolean;
17
+ className?: string;
18
+ }
19
+ declare function DonutChart({ data, centerLabel, size, innerRadius, outerRadius, paddingAngle, showTooltip, showLegend, className, }: DonutChartProps): React.JSX.Element;
20
+
21
+ export { DonutChart, type DonutChartProps, type DonutSegment };
@@ -0,0 +1,96 @@
1
+ "use client"
2
+
3
+ "use client";
4
+ import { jsx, jsxs } from "react/jsx-runtime";
5
+ import {
6
+ PieChart,
7
+ Pie,
8
+ Cell,
9
+ Label,
10
+ Tooltip,
11
+ ResponsiveContainer
12
+ } from "recharts";
13
+ import { cn } from "../lib/utils.js";
14
+ import { CHART_TOOLTIP_STYLE } from "./chart-tooltip.js";
15
+ function DonutChart({
16
+ data,
17
+ centerLabel,
18
+ size = 80,
19
+ innerRadius,
20
+ outerRadius,
21
+ paddingAngle = 2,
22
+ showTooltip = true,
23
+ showLegend = false,
24
+ className
25
+ }) {
26
+ const computedInner = innerRadius != null ? innerRadius : Math.round(size * 0.325);
27
+ const computedOuter = outerRadius != null ? outerRadius : Math.round(size * 0.45);
28
+ return /* @__PURE__ */ jsxs("div", { className: cn("flex items-center gap-3", className), children: [
29
+ /* @__PURE__ */ jsx("div", { className: "shrink-0", style: { height: size, width: size }, children: /* @__PURE__ */ jsx(ResponsiveContainer, { width: "100%", height: "100%", children: /* @__PURE__ */ jsxs(PieChart, { children: [
30
+ showTooltip ? /* @__PURE__ */ jsx(
31
+ Tooltip,
32
+ {
33
+ contentStyle: CHART_TOOLTIP_STYLE,
34
+ itemStyle: { color: "#0f172a", fontWeight: 600 },
35
+ formatter: (value, name) => [
36
+ `${value}`,
37
+ String(name)
38
+ ]
39
+ }
40
+ ) : null,
41
+ /* @__PURE__ */ jsxs(
42
+ Pie,
43
+ {
44
+ data,
45
+ innerRadius: computedInner,
46
+ outerRadius: computedOuter,
47
+ paddingAngle,
48
+ dataKey: "value",
49
+ stroke: "none",
50
+ children: [
51
+ data.map((entry, index) => /* @__PURE__ */ jsx(Cell, { fill: entry.color }, `cell-${index}`)),
52
+ centerLabel != null ? /* @__PURE__ */ jsx(
53
+ Label,
54
+ {
55
+ value: String(centerLabel),
56
+ position: "center",
57
+ className: "fill-foreground text-lg font-bold"
58
+ }
59
+ ) : null
60
+ ]
61
+ }
62
+ )
63
+ ] }) }) }),
64
+ showLegend ? /* @__PURE__ */ jsx("div", { className: "flex min-w-0 flex-1 flex-col gap-1.5 pl-1", children: data.map((d) => /* @__PURE__ */ jsxs(
65
+ "div",
66
+ {
67
+ className: "flex items-center justify-between text-[10px]",
68
+ children: [
69
+ /* @__PURE__ */ jsxs("div", { className: "flex min-w-0 items-center gap-1.5", children: [
70
+ /* @__PURE__ */ jsx(
71
+ "div",
72
+ {
73
+ className: "h-1.5 w-1.5 shrink-0 rounded-full",
74
+ style: { backgroundColor: d.color }
75
+ }
76
+ ),
77
+ /* @__PURE__ */ jsx(
78
+ "span",
79
+ {
80
+ className: "whitespace-nowrap font-medium text-muted-foreground",
81
+ title: d.name,
82
+ children: d.name
83
+ }
84
+ )
85
+ ] }),
86
+ /* @__PURE__ */ jsx("span", { className: "ml-1.5 font-bold text-foreground", children: d.value })
87
+ ]
88
+ },
89
+ d.name
90
+ )) }) : null
91
+ ] });
92
+ }
93
+ export {
94
+ DonutChart
95
+ };
96
+ //# sourceMappingURL=donut-chart.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/charts/donut-chart.tsx"],"sourcesContent":["\"use client\"\n\nimport * as React from \"react\"\nimport {\n PieChart,\n Pie,\n Cell,\n Label,\n Tooltip,\n ResponsiveContainer,\n} from \"recharts\"\n\nimport { cn } from \"../lib/utils\"\nimport { CHART_TOOLTIP_STYLE } from \"./chart-tooltip\"\n\nexport interface DonutSegment {\n name: string\n value: number\n color: string\n}\n\nexport interface DonutChartProps {\n data: DonutSegment[]\n centerLabel?: string | number\n size?: number\n innerRadius?: number\n outerRadius?: number\n paddingAngle?: number\n showTooltip?: boolean\n showLegend?: boolean\n className?: string\n}\n\nexport function DonutChart({\n data,\n centerLabel,\n size = 80,\n innerRadius,\n outerRadius,\n paddingAngle = 2,\n showTooltip = true,\n showLegend = false,\n className,\n}: DonutChartProps) {\n const computedInner = innerRadius ?? Math.round(size * 0.325)\n const computedOuter = outerRadius ?? Math.round(size * 0.45)\n\n return (\n <div className={cn(\"flex items-center gap-3\", className)}>\n <div className=\"shrink-0\" style={{ height: size, width: size }}>\n <ResponsiveContainer width=\"100%\" height=\"100%\">\n <PieChart>\n {showTooltip ? (\n <Tooltip\n contentStyle={CHART_TOOLTIP_STYLE}\n itemStyle={{ color: \"#0f172a\", fontWeight: 600 }}\n formatter={(value: unknown, name: unknown) => [\n `${value}`,\n String(name),\n ]}\n />\n ) : null}\n <Pie\n data={data}\n innerRadius={computedInner}\n outerRadius={computedOuter}\n paddingAngle={paddingAngle}\n dataKey=\"value\"\n stroke=\"none\"\n >\n {data.map((entry, index) => (\n <Cell key={`cell-${index}`} fill={entry.color} />\n ))}\n {centerLabel != null ? (\n <Label\n value={String(centerLabel)}\n position=\"center\"\n className=\"fill-foreground text-lg font-bold\"\n />\n ) : null}\n </Pie>\n </PieChart>\n </ResponsiveContainer>\n </div>\n\n {showLegend ? (\n <div className=\"flex min-w-0 flex-1 flex-col gap-1.5 pl-1\">\n {data.map((d) => (\n <div\n key={d.name}\n className=\"flex items-center justify-between text-[10px]\"\n >\n <div className=\"flex min-w-0 items-center gap-1.5\">\n <div\n className=\"h-1.5 w-1.5 shrink-0 rounded-full\"\n style={{ backgroundColor: d.color }}\n />\n <span\n className=\"whitespace-nowrap font-medium text-muted-foreground\"\n title={d.name}\n >\n {d.name}\n </span>\n </div>\n <span className=\"ml-1.5 font-bold text-foreground\">{d.value}</span>\n </div>\n ))}\n </div>\n ) : null}\n </div>\n )\n}\n"],"mappings":";AAqDc,cASF,YATE;AAlDd;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AAEP,SAAS,UAAU;AACnB,SAAS,2BAA2B;AAoB7B,SAAS,WAAW;AAAA,EACzB;AAAA,EACA;AAAA,EACA,OAAO;AAAA,EACP;AAAA,EACA;AAAA,EACA,eAAe;AAAA,EACf,cAAc;AAAA,EACd,aAAa;AAAA,EACb;AACF,GAAoB;AAClB,QAAM,gBAAgB,oCAAe,KAAK,MAAM,OAAO,KAAK;AAC5D,QAAM,gBAAgB,oCAAe,KAAK,MAAM,OAAO,IAAI;AAE3D,SACE,qBAAC,SAAI,WAAW,GAAG,2BAA2B,SAAS,GACrD;AAAA,wBAAC,SAAI,WAAU,YAAW,OAAO,EAAE,QAAQ,MAAM,OAAO,KAAK,GAC3D,8BAAC,uBAAoB,OAAM,QAAO,QAAO,QACvC,+BAAC,YACE;AAAA,oBACC;AAAA,QAAC;AAAA;AAAA,UACC,cAAc;AAAA,UACd,WAAW,EAAE,OAAO,WAAW,YAAY,IAAI;AAAA,UAC/C,WAAW,CAAC,OAAgB,SAAkB;AAAA,YAC5C,GAAG,KAAK;AAAA,YACR,OAAO,IAAI;AAAA,UACb;AAAA;AAAA,MACF,IACE;AAAA,MACJ;AAAA,QAAC;AAAA;AAAA,UACC;AAAA,UACA,aAAa;AAAA,UACb,aAAa;AAAA,UACb;AAAA,UACA,SAAQ;AAAA,UACR,QAAO;AAAA,UAEN;AAAA,iBAAK,IAAI,CAAC,OAAO,UAChB,oBAAC,QAA2B,MAAM,MAAM,SAA7B,QAAQ,KAAK,EAAuB,CAChD;AAAA,YACA,eAAe,OACd;AAAA,cAAC;AAAA;AAAA,gBACC,OAAO,OAAO,WAAW;AAAA,gBACzB,UAAS;AAAA,gBACT,WAAU;AAAA;AAAA,YACZ,IACE;AAAA;AAAA;AAAA,MACN;AAAA,OACF,GACF,GACF;AAAA,IAEC,aACC,oBAAC,SAAI,WAAU,6CACZ,eAAK,IAAI,CAAC,MACT;AAAA,MAAC;AAAA;AAAA,QAEC,WAAU;AAAA,QAEV;AAAA,+BAAC,SAAI,WAAU,qCACb;AAAA;AAAA,cAAC;AAAA;AAAA,gBACC,WAAU;AAAA,gBACV,OAAO,EAAE,iBAAiB,EAAE,MAAM;AAAA;AAAA,YACpC;AAAA,YACA;AAAA,cAAC;AAAA;AAAA,gBACC,WAAU;AAAA,gBACV,OAAO,EAAE;AAAA,gBAER,YAAE;AAAA;AAAA,YACL;AAAA,aACF;AAAA,UACA,oBAAC,UAAK,WAAU,oCAAoC,YAAE,OAAM;AAAA;AAAA;AAAA,MAfvD,EAAE;AAAA,IAgBT,CACD,GACH,IACE;AAAA,KACN;AAEJ;","names":[]}
@@ -0,0 +1,11 @@
1
+ export { ChartConfig, ChartContainer, ChartLegend, ChartLegendContent, ChartStyle, ChartTooltip, ChartTooltipContent } from './chart.js';
2
+ export { CHART_CURSOR_STYLE, CHART_TOOLTIP_STYLE, ChartTooltipEntry, SimpleChartTooltip, SimpleChartTooltipProps } from './chart-tooltip.js';
3
+ export { BarChartComponent, BarChartComponentProps, BarSeries } from './bar-chart-component.js';
4
+ export { DonutChart, DonutChartProps, DonutSegment } from './donut-chart.js';
5
+ export { TrendAreaChart, TrendAreaChartProps, TrendSeries } from './trend-area-chart.js';
6
+ export { VolumeAnalysisChart, VolumeAnalysisChartProps, VolumeDataKey } from './volume-analysis-chart.js';
7
+ export { MetricCardData, TopLineMetrics, TopLineMetricsProps } from './top-line-metrics.js';
8
+ export { PipelineFilterBreakdown, PipelineOverview, PipelineOverviewProps, PipelineStage, PipelineStageMetrics, PipelineStageTiming } from './pipeline-overview.js';
9
+ export { SankeyChart, SankeyData, SankeyDropOff, SankeyHoverCardData, SankeyLink, SankeyNode, SankeyStageMetrics } from './sankey-chart.js';
10
+ import 'react';
11
+ import 'recharts';
@@ -0,0 +1,10 @@
1
+ export * from "./chart.js";
2
+ export * from "./chart-tooltip.js";
3
+ export * from "./bar-chart-component.js";
4
+ export * from "./donut-chart.js";
5
+ export * from "./trend-area-chart.js";
6
+ export * from "./volume-analysis-chart.js";
7
+ export * from "./top-line-metrics.js";
8
+ export * from "./pipeline-overview.js";
9
+ export * from "./sankey-chart.js";
10
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/charts/index.ts"],"sourcesContent":["/**\n * @handled-ai/design-system/charts\n * Chart components requiring recharts and @nivo/sankey\n */\nexport * from \"./chart\"\nexport * from \"./chart-tooltip\"\nexport * from \"./bar-chart-component\"\nexport * from \"./donut-chart\"\nexport * from \"./trend-area-chart\"\nexport * from \"./volume-analysis-chart\"\nexport * from \"./top-line-metrics\"\nexport * from \"./pipeline-overview\"\nexport * from \"./sankey-chart\"\n"],"mappings":"AAIA,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;","names":[]}
@@ -0,0 +1,76 @@
1
+ import * as React from 'react';
2
+
3
+ interface PipelineStage {
4
+ id: string;
5
+ label: string;
6
+ count: number;
7
+ trend: string;
8
+ nextConversion: string | null;
9
+ }
10
+ interface PipelineStageMetrics {
11
+ medianTime: string;
12
+ avgTime: string;
13
+ dropOffs: {
14
+ reason: string;
15
+ count: number;
16
+ pct: string;
17
+ }[];
18
+ }
19
+ interface PipelineStageTiming {
20
+ median: string;
21
+ avg: string;
22
+ }
23
+ interface PipelineFilterBreakdown {
24
+ [stageId: string]: Record<string, number>;
25
+ }
26
+ interface PipelineOverviewProps {
27
+ title?: string;
28
+ stages: PipelineStage[];
29
+ stageMetrics: Record<string, PipelineStageMetrics>;
30
+ stageTimings: (PipelineStageTiming | null)[];
31
+ filterOptions?: string[];
32
+ onFilterChange?: (filterOption: string) => void;
33
+ filterBreakdowns?: Record<string, PipelineFilterBreakdown>;
34
+ countingModes?: string[];
35
+ countingModeTooltip?: string;
36
+ /** Main pipeline flow nodes (after the first stage) */
37
+ flowNodes?: {
38
+ id: string;
39
+ nodeColor: string;
40
+ }[];
41
+ /** Drop-off distribution from initial stage: { "Lost/Other": 56, "Coverage": 40, ... } */
42
+ dropOffDistribution?: Record<string, number>;
43
+ /** Flow links after the first stage (middle of pipeline onward) */
44
+ flowLinks?: {
45
+ source: string;
46
+ target: string;
47
+ value: number;
48
+ }[];
49
+ totalReceived?: number;
50
+ /** Dollar amounts to display on terminal node labels: { "Retained": "$18.2M" } */
51
+ nodeAmounts?: Record<string, string>;
52
+ /** Unit noun for standard node/link tooltips (e.g. "signals", "accounts"). */
53
+ unitLabel?: string;
54
+ /** Unit noun for terminal/drop-off node tooltips (e.g. "opportunities"). Defaults to unitLabel. */
55
+ terminalUnitLabel?: string;
56
+ /** Node IDs that should use terminalUnitLabel. Defaults to keys of dropOffDistribution. */
57
+ terminalNodeIds?: string[];
58
+ /** Sankey chart margins, merged with defaults { top: 20, right: 120, bottom: 20, left: 140 }. */
59
+ sankeyMargin?: {
60
+ top?: number;
61
+ right?: number;
62
+ bottom?: number;
63
+ left?: number;
64
+ };
65
+ /** Gap between Sankey node bar and its outside label. */
66
+ sankeyLabelPadding?: number;
67
+ /** When true, conversion badges use `flex`; when false, `hidden xl:flex`. */
68
+ alwaysShowConversionBadges?: boolean;
69
+ /** Color for dynamically generated drop-off nodes. */
70
+ dropOffNodeColor?: string;
71
+ onViewInWorkQueue?: (stageId: string) => void;
72
+ className?: string;
73
+ }
74
+ declare function PipelineOverview({ title, stages, stageMetrics, stageTimings, filterOptions, onFilterChange, filterBreakdowns, countingModes, countingModeTooltip, flowNodes, dropOffDistribution, flowLinks, totalReceived, nodeAmounts, unitLabel, terminalUnitLabel, terminalNodeIds, sankeyMargin, sankeyLabelPadding, alwaysShowConversionBadges, dropOffNodeColor, onViewInWorkQueue: _onViewInWorkQueue, className, }: PipelineOverviewProps): React.JSX.Element;
75
+
76
+ export { type PipelineFilterBreakdown, PipelineOverview, type PipelineOverviewProps, type PipelineStage, type PipelineStageMetrics, type PipelineStageTiming };
@@ -0,0 +1,372 @@
1
+ "use client"
2
+
3
+ "use client";
4
+ var __defProp = Object.defineProperty;
5
+ var __getOwnPropSymbols = Object.getOwnPropertySymbols;
6
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
7
+ var __propIsEnum = Object.prototype.propertyIsEnumerable;
8
+ var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
9
+ var __spreadValues = (a, b) => {
10
+ for (var prop in b || (b = {}))
11
+ if (__hasOwnProp.call(b, prop))
12
+ __defNormalProp(a, prop, b[prop]);
13
+ if (__getOwnPropSymbols)
14
+ for (var prop of __getOwnPropSymbols(b)) {
15
+ if (__propIsEnum.call(b, prop))
16
+ __defNormalProp(a, prop, b[prop]);
17
+ }
18
+ return a;
19
+ };
20
+ import { jsx, jsxs } from "react/jsx-runtime";
21
+ import * as React from "react";
22
+ import { TrendingUp, Info, ArrowRight } from "lucide-react";
23
+ import { ResponsiveSankey } from "@nivo/sankey";
24
+ import { cn } from "../lib/utils.js";
25
+ import {
26
+ Tooltip,
27
+ TooltipContent,
28
+ TooltipProvider,
29
+ TooltipTrigger
30
+ } from "../components/tooltip.js";
31
+ const SEGMENT_PALETTE = [
32
+ "#0F4C3A",
33
+ "#15803d",
34
+ "#0ea5e9",
35
+ "#8b5cf6",
36
+ "#f59e0b",
37
+ "#ef4444"
38
+ ];
39
+ const DROP_OFF_NODES = [
40
+ { id: "Lost/Other", nodeColor: "#CBD5E1" },
41
+ { id: "Coverage", nodeColor: "#F59E0B" },
42
+ { id: "Unqualified", nodeColor: "#F59E0B" },
43
+ { id: "No Contact", nodeColor: "#F59E0B" },
44
+ { id: "Intake Drop", nodeColor: "#F59E0B" },
45
+ { id: "No Show/Cancel", nodeColor: "#F59E0B" }
46
+ ];
47
+ function StageHoverCard({
48
+ title,
49
+ count,
50
+ metrics
51
+ }) {
52
+ return /* @__PURE__ */ jsxs("div", { className: "w-[260px] overflow-hidden rounded-lg border border-border bg-card font-sans text-left shadow-xl", children: [
53
+ /* @__PURE__ */ jsxs("div", { className: "border-b border-border p-3", children: [
54
+ /* @__PURE__ */ jsx("div", { className: "mb-0.5 text-xs font-medium text-muted-foreground", children: title }),
55
+ /* @__PURE__ */ jsx("div", { className: "text-2xl font-bold text-foreground", children: count })
56
+ ] }),
57
+ metrics && /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-2 gap-2 border-b border-border bg-muted/30 px-3 py-2", children: [
58
+ /* @__PURE__ */ jsxs("div", { children: [
59
+ /* @__PURE__ */ jsx("div", { className: "text-[9px] font-semibold uppercase tracking-wider text-muted-foreground/70", children: "Median" }),
60
+ /* @__PURE__ */ jsx("div", { className: "text-xs font-bold text-foreground", children: metrics.medianTime })
61
+ ] }),
62
+ /* @__PURE__ */ jsxs("div", { className: "border-l border-border pl-2", children: [
63
+ /* @__PURE__ */ jsx("div", { className: "text-[9px] font-semibold uppercase tracking-wider text-muted-foreground/70", children: "Average" }),
64
+ /* @__PURE__ */ jsx("div", { className: "text-xs font-bold text-foreground", children: metrics.avgTime })
65
+ ] })
66
+ ] }),
67
+ (metrics == null ? void 0 : metrics.dropOffs) && metrics.dropOffs.length > 0 && /* @__PURE__ */ jsxs("div", { className: "p-2", children: [
68
+ /* @__PURE__ */ jsx("div", { className: "mb-1.5 px-1 text-[10px] font-semibold uppercase tracking-wide text-muted-foreground", children: "Drop-off Reasons" }),
69
+ /* @__PURE__ */ jsx("div", { className: "space-y-0.5", children: metrics.dropOffs.map((drop, i) => /* @__PURE__ */ jsxs(
70
+ "div",
71
+ {
72
+ className: "group flex cursor-pointer items-center justify-between rounded p-1.5 text-xs transition-colors hover:bg-muted",
73
+ children: [
74
+ /* @__PURE__ */ jsx("span", { className: "truncate pr-2 text-muted-foreground group-hover:text-foreground", children: drop.reason }),
75
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1.5", children: [
76
+ /* @__PURE__ */ jsx("span", { className: "text-[10px] text-muted-foreground/70", children: drop.pct }),
77
+ /* @__PURE__ */ jsx("span", { className: "inline-flex h-4 min-w-[20px] items-center justify-center rounded border border-border bg-muted px-1 text-[9px] font-semibold text-muted-foreground group-hover:bg-muted group-hover:text-foreground", children: drop.count })
78
+ ] })
79
+ ]
80
+ },
81
+ i
82
+ )) })
83
+ ] }),
84
+ /* @__PURE__ */ jsxs("div", { className: "flex cursor-pointer items-center justify-between border-t border-border bg-muted px-3 py-2 text-xs font-medium text-blue-600 transition-colors hover:bg-muted hover:text-blue-700", children: [
85
+ "View in Work Queue ",
86
+ /* @__PURE__ */ jsx(ArrowRight, { className: "h-3 w-3" })
87
+ ] })
88
+ ] });
89
+ }
90
+ function PipelineOverview({
91
+ title = "Pipeline Overview",
92
+ stages,
93
+ stageMetrics,
94
+ stageTimings,
95
+ filterOptions = ["Facility", "Source", "Lead Source", "Payer", "Channel"],
96
+ onFilterChange,
97
+ filterBreakdowns,
98
+ countingModes = ["Unique Patients", "All Referrals"],
99
+ countingModeTooltip = "Patients may be referred through multiple channels. 'All Referrals' shows total volume; 'Unique Patients' deduplicates to show distinct patient counts.",
100
+ flowNodes = [
101
+ { id: "Contacted", nodeColor: "#2A8F7A" },
102
+ { id: "Intake Sent", nodeColor: "#3DB4A0" },
103
+ { id: "Intake Done", nodeColor: "#4CC9B0" },
104
+ { id: "Scheduled", nodeColor: "#5FCFBC" },
105
+ { id: "Completed", nodeColor: "#79E2C9" }
106
+ ],
107
+ dropOffDistribution = {
108
+ "Lost/Other": 56,
109
+ Coverage: 40,
110
+ Unqualified: 30
111
+ },
112
+ flowLinks = [
113
+ { source: "Contacted", target: "Intake Sent", value: 660 },
114
+ { source: "Contacted", target: "No Contact", value: 60 },
115
+ { source: "Intake Sent", target: "Intake Done", value: 612 },
116
+ { source: "Intake Sent", target: "Intake Drop", value: 48 },
117
+ { source: "Intake Done", target: "Scheduled", value: 612 },
118
+ { source: "Scheduled", target: "Completed", value: 520 },
119
+ { source: "Scheduled", target: "No Show/Cancel", value: 92 }
120
+ ],
121
+ totalReceived = 847,
122
+ nodeAmounts,
123
+ unitLabel,
124
+ terminalUnitLabel,
125
+ terminalNodeIds,
126
+ sankeyMargin,
127
+ sankeyLabelPadding,
128
+ alwaysShowConversionBadges = false,
129
+ dropOffNodeColor,
130
+ onViewInWorkQueue: _onViewInWorkQueue,
131
+ className
132
+ }) {
133
+ const [selectedFilter, setSelectedFilter] = React.useState(filterOptions[0]);
134
+ const [countingMode, setCountingMode] = React.useState(countingModes[0]);
135
+ const effectiveUnitLabel = unitLabel != null ? unitLabel : "items";
136
+ const effectiveTerminalUnitLabel = terminalUnitLabel != null ? terminalUnitLabel : effectiveUnitLabel;
137
+ const effectiveTerminalNodeIds = React.useMemo(
138
+ () => new Set(terminalNodeIds != null ? terminalNodeIds : Object.keys(dropOffDistribution)),
139
+ [terminalNodeIds, dropOffDistribution]
140
+ );
141
+ const effectiveMargin = React.useMemo(
142
+ () => __spreadValues({ top: 20, right: 120, bottom: 20, left: 140 }, sankeyMargin),
143
+ [sankeyMargin]
144
+ );
145
+ const effectiveLabelPadding = sankeyLabelPadding != null ? sankeyLabelPadding : 16;
146
+ const sankeyData = React.useMemo(() => {
147
+ var _a, _b, _c, _d, _e, _f;
148
+ const breakdown = (_d = (_a = filterBreakdowns == null ? void 0 : filterBreakdowns[selectedFilter]) == null ? void 0 : _a.received) != null ? _d : { [(_c = (_b = stages[0]) == null ? void 0 : _b.label) != null ? _c : "Received"]: totalReceived };
149
+ const segments = Object.entries(breakdown).map(([name, value], index) => ({
150
+ id: name,
151
+ nodeColor: SEGMENT_PALETTE[index % SEGMENT_PALETTE.length],
152
+ value
153
+ }));
154
+ const dropOffKeys = Object.keys(dropOffDistribution);
155
+ const dropOffNodes = dropOffKeys.length > 0 ? dropOffKeys.map((reason) => ({
156
+ id: reason,
157
+ nodeColor: dropOffNodeColor != null ? dropOffNodeColor : "#F59E0B"
158
+ })) : DROP_OFF_NODES;
159
+ const nodes = [
160
+ ...segments,
161
+ ...flowNodes,
162
+ ...dropOffNodes
163
+ ];
164
+ const nodeIds = new Set(nodes.map((n) => n.id));
165
+ for (const link of flowLinks) {
166
+ for (const endpoint of [link.source, link.target]) {
167
+ if (!nodeIds.has(endpoint)) {
168
+ nodes.push({ id: endpoint, nodeColor: dropOffNodeColor != null ? dropOffNodeColor : "#F59E0B" });
169
+ nodeIds.add(endpoint);
170
+ }
171
+ }
172
+ }
173
+ const links = [];
174
+ const firstFlowNode = (_f = (_e = flowNodes[0]) == null ? void 0 : _e.id) != null ? _f : "Contacted";
175
+ segments.forEach((segment) => {
176
+ if (segment.value > 0) {
177
+ links.push({
178
+ source: segment.id,
179
+ target: firstFlowNode,
180
+ value: segment.value
181
+ });
182
+ }
183
+ });
184
+ for (const [reason, count] of Object.entries(dropOffDistribution)) {
185
+ if (count > 0) {
186
+ links.push({ source: firstFlowNode, target: reason, value: count });
187
+ }
188
+ }
189
+ flowLinks.forEach((link) => links.push(__spreadValues({}, link)));
190
+ return { nodes, links };
191
+ }, [
192
+ selectedFilter,
193
+ filterBreakdowns,
194
+ stages,
195
+ totalReceived,
196
+ flowNodes,
197
+ dropOffDistribution,
198
+ dropOffNodeColor,
199
+ flowLinks
200
+ ]);
201
+ return /* @__PURE__ */ jsxs(
202
+ "div",
203
+ {
204
+ className: cn(
205
+ "rounded-xl border border-border bg-card p-5 shadow-sm",
206
+ className
207
+ ),
208
+ children: [
209
+ /* @__PURE__ */ jsx("div", { className: "mb-6 flex flex-col gap-4", children: /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-4 md:flex-row md:items-center md:justify-between", children: [
210
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-4", children: [
211
+ /* @__PURE__ */ jsx("h3", { className: "text-lg font-semibold text-foreground", children: title }),
212
+ countingModes.length > 1 && /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 rounded-lg border border-border bg-muted p-1", children: [
213
+ countingModes.map((mode) => /* @__PURE__ */ jsx(
214
+ "button",
215
+ {
216
+ onClick: () => setCountingMode(mode),
217
+ className: cn(
218
+ "rounded-md px-3 py-1 text-xs font-medium transition-all",
219
+ countingMode === mode ? "border border-border bg-background text-foreground shadow-sm" : "text-muted-foreground hover:text-foreground"
220
+ ),
221
+ children: mode
222
+ },
223
+ mode
224
+ )),
225
+ /* @__PURE__ */ jsx(TooltipProvider, { children: /* @__PURE__ */ jsxs(Tooltip, { children: [
226
+ /* @__PURE__ */ jsx(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx(Info, { className: "ml-1 h-3.5 w-3.5 cursor-help text-muted-foreground/70" }) }),
227
+ /* @__PURE__ */ jsx(TooltipContent, { className: "max-w-[250px] text-xs", children: countingModeTooltip })
228
+ ] }) })
229
+ ] })
230
+ ] }),
231
+ filterOptions.length > 1 && /* @__PURE__ */ jsx("div", { className: "flex items-center gap-1 self-start rounded-lg bg-muted p-1 md:self-auto", children: filterOptions.map((option) => /* @__PURE__ */ jsx(
232
+ "button",
233
+ {
234
+ onClick: () => {
235
+ setSelectedFilter(option);
236
+ onFilterChange == null ? void 0 : onFilterChange(option);
237
+ },
238
+ className: cn(
239
+ "h-7 rounded-md border-none bg-transparent px-3 text-xs font-medium shadow-none transition-all hover:bg-background",
240
+ selectedFilter === option && "bg-background text-foreground shadow-sm"
241
+ ),
242
+ children: option
243
+ },
244
+ option
245
+ )) })
246
+ ] }) }),
247
+ /* @__PURE__ */ jsx("div", { className: "mb-2 grid gap-4", style: { gridTemplateColumns: `repeat(${stages.length}, minmax(0, 1fr))` }, children: stages.map((stage, index) => {
248
+ var _a;
249
+ const details = stageMetrics[stage.id];
250
+ const timing = (_a = stageTimings[index]) != null ? _a : null;
251
+ return /* @__PURE__ */ jsx(TooltipProvider, { delayDuration: 100, children: /* @__PURE__ */ jsxs(Tooltip, { children: [
252
+ /* @__PURE__ */ jsx(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsxs("div", { className: "group relative flex cursor-pointer flex-col items-center rounded-lg p-2 text-center transition-colors hover:bg-muted", children: [
253
+ /* @__PURE__ */ jsx(
254
+ "div",
255
+ {
256
+ className: "mb-1 w-full truncate text-xs font-medium text-muted-foreground",
257
+ title: stage.label,
258
+ children: stage.label
259
+ }
260
+ ),
261
+ /* @__PURE__ */ jsx("div", { className: "mb-1 text-2xl font-bold text-foreground", children: stage.count.toLocaleString() }),
262
+ /* @__PURE__ */ jsxs("div", { className: "mb-1 flex items-center justify-center gap-1 text-xs font-medium text-emerald-600", children: [
263
+ stage.trend,
264
+ " ",
265
+ /* @__PURE__ */ jsx(TrendingUp, { className: "h-3 w-3" })
266
+ ] }),
267
+ index < stages.length - 1 && stage.nextConversion && /* @__PURE__ */ jsxs("div", { className: cn(
268
+ alwaysShowConversionBadges ? "flex" : "hidden xl:flex",
269
+ "absolute -right-2 top-1/2 z-10 -translate-y-1/2 translate-x-1/2 flex-col items-center"
270
+ ), children: [
271
+ /* @__PURE__ */ jsx("span", { className: "z-10 whitespace-nowrap rounded-full border border-border bg-muted px-1.5 py-0.5 text-[10px] font-medium text-muted-foreground shadow-sm", children: stage.nextConversion }),
272
+ timing && /* @__PURE__ */ jsxs("div", { className: "mt-1 flex flex-col items-center", children: [
273
+ /* @__PURE__ */ jsx("div", { className: "h-2 w-px bg-border" }),
274
+ /* @__PURE__ */ jsxs("div", { className: "whitespace-nowrap rounded bg-background/80 px-1 py-0.5 text-[9px] font-medium leading-3 text-muted-foreground/70 backdrop-blur-[2px]", children: [
275
+ /* @__PURE__ */ jsxs("span", { className: "mr-1 font-semibold text-muted-foreground", children: [
276
+ "Med: ",
277
+ timing.median
278
+ ] }),
279
+ /* @__PURE__ */ jsxs("span", { className: "text-muted-foreground/70", children: [
280
+ "Avg: ",
281
+ timing.avg
282
+ ] })
283
+ ] })
284
+ ] })
285
+ ] }),
286
+ /* @__PURE__ */ jsx("div", { className: "mx-auto mb-1 mt-2 h-4 w-px bg-border" })
287
+ ] }) }),
288
+ /* @__PURE__ */ jsx(
289
+ TooltipContent,
290
+ {
291
+ className: "border-none bg-transparent p-0 shadow-none",
292
+ sideOffset: 8,
293
+ children: /* @__PURE__ */ jsx(
294
+ StageHoverCard,
295
+ {
296
+ title: stage.label,
297
+ count: stage.count,
298
+ metrics: details
299
+ }
300
+ )
301
+ }
302
+ )
303
+ ] }) }, stage.id);
304
+ }) }),
305
+ /* @__PURE__ */ jsx(
306
+ "div",
307
+ {
308
+ className: "relative mt-4 w-full",
309
+ style: { height: 400, minWidth: 0 },
310
+ children: /* @__PURE__ */ jsx(
311
+ ResponsiveSankey,
312
+ {
313
+ data: sankeyData,
314
+ margin: effectiveMargin,
315
+ align: "justify",
316
+ colors: (node) => node.nodeColor || "#94a3b8",
317
+ nodeOpacity: 1,
318
+ nodeHoverOthersOpacity: 0.35,
319
+ nodeThickness: 18,
320
+ nodeSpacing: 16,
321
+ nodeBorderWidth: 0,
322
+ nodeBorderRadius: 3,
323
+ linkOpacity: 0.5,
324
+ linkHoverOthersOpacity: 0.1,
325
+ linkContract: 3,
326
+ enableLinkGradient: true,
327
+ labelPosition: "outside",
328
+ labelOrientation: "horizontal",
329
+ labelPadding: effectiveLabelPadding,
330
+ label: (node) => (nodeAmounts == null ? void 0 : nodeAmounts[node.id]) ? `${node.id} (${nodeAmounts[node.id]})` : node.id,
331
+ labelTextColor: { from: "color", modifiers: [["darker", 1]] },
332
+ nodeTooltip: ({ node }) => {
333
+ const unit = effectiveTerminalNodeIds.has(node.id) ? effectiveTerminalUnitLabel : effectiveUnitLabel;
334
+ return /* @__PURE__ */ jsxs("div", { className: "rounded-md border border-border bg-card p-2 text-xs shadow-lg", children: [
335
+ /* @__PURE__ */ jsxs("span", { className: "mb-1 block font-bold", children: [
336
+ node.id,
337
+ (nodeAmounts == null ? void 0 : nodeAmounts[node.id]) ? ` \u2014 ${nodeAmounts[node.id]}` : ""
338
+ ] }),
339
+ /* @__PURE__ */ jsxs("span", { children: [
340
+ node.value,
341
+ " ",
342
+ unit
343
+ ] })
344
+ ] });
345
+ },
346
+ linkTooltip: ({ link }) => {
347
+ const unit = effectiveTerminalNodeIds.has(link.target.id) ? effectiveTerminalUnitLabel : effectiveUnitLabel;
348
+ return /* @__PURE__ */ jsxs("div", { className: "rounded-md border border-border bg-card p-2 text-xs shadow-lg", children: [
349
+ /* @__PURE__ */ jsxs("span", { className: "mb-1 block font-bold", children: [
350
+ link.source.id,
351
+ " \u2192 ",
352
+ link.target.id
353
+ ] }),
354
+ /* @__PURE__ */ jsxs("span", { children: [
355
+ link.value,
356
+ " ",
357
+ unit
358
+ ] })
359
+ ] });
360
+ }
361
+ }
362
+ )
363
+ }
364
+ )
365
+ ]
366
+ }
367
+ );
368
+ }
369
+ export {
370
+ PipelineOverview
371
+ };
372
+ //# sourceMappingURL=pipeline-overview.js.map