@signalflare-ai/ui 1.2.0 → 1.3.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 (317) hide show
  1. package/CHANGELOG.md +77 -1
  2. package/ai/component-registry.json +208 -550
  3. package/ai/component-registry.md +3042 -3115
  4. package/ai/schemas.ts +504 -96
  5. package/dist/.build-complete +1 -1
  6. package/dist/ai/schemas.d.ts.map +1 -1
  7. package/dist/{ai-actions-BdUZI3Gk.js → ai-actions-CBfz5XEf.js} +4 -4
  8. package/dist/{ai-actions-BdUZI3Gk.js.map → ai-actions-CBfz5XEf.js.map} +1 -1
  9. package/dist/{ai-agent-card-BR2NIYhi.js → ai-agent-card-CByAUe0q.js} +3 -3
  10. package/dist/ai-agent-card-CByAUe0q.js.map +1 -0
  11. package/dist/{ai-approval-Ba7mrKba.js → ai-approval-Ci8N70a7.js} +4 -3
  12. package/dist/{ai-approval-Ba7mrKba.js.map → ai-approval-Ci8N70a7.js.map} +1 -1
  13. package/dist/{ai-code-block-CZtoL73R.js → ai-code-block-P9TJHvaC.js} +37 -39
  14. package/dist/ai-code-block-P9TJHvaC.js.map +1 -0
  15. package/dist/{ai-conversation-Cc7WlaBg.js → ai-conversation-Qslfdi1t.js} +28 -42
  16. package/dist/ai-conversation-Qslfdi1t.js.map +1 -0
  17. package/dist/{ai-info-banner-C7EWPBj7.js → ai-info-banner-B_9vtGK3.js} +3 -3
  18. package/dist/{ai-info-banner-C7EWPBj7.js.map → ai-info-banner-B_9vtGK3.js.map} +1 -1
  19. package/dist/{ai-message-Bp7L68U_.js → ai-message-Ci3gwM7G.js} +6 -6
  20. package/dist/{ai-message-Bp7L68U_.js.map → ai-message-Ci3gwM7G.js.map} +1 -1
  21. package/dist/{ai-mission-header-TiCJfTNt.js → ai-mission-header-CaBc19-t.js} +2 -2
  22. package/dist/{ai-mission-header-TiCJfTNt.js.map → ai-mission-header-CaBc19-t.js.map} +1 -1
  23. package/dist/{ai-part-group-DNb9I446.js → ai-part-group-Dx1Mr92B.js} +5 -4
  24. package/dist/ai-part-group-Dx1Mr92B.js.map +1 -0
  25. package/dist/{ai-prompt-input-BVvov_KF.js → ai-prompt-input-Bm4XoSj2.js} +19 -17
  26. package/dist/ai-prompt-input-Bm4XoSj2.js.map +1 -0
  27. package/dist/{ai-question-GPPMk7YM.js → ai-question-OyJovxGe.js} +4 -3
  28. package/dist/{ai-question-GPPMk7YM.js.map → ai-question-OyJovxGe.js.map} +1 -1
  29. package/dist/{ai-reasoning-_feFjk56.js → ai-reasoning-BLfBXx3F.js} +9 -5
  30. package/dist/ai-reasoning-BLfBXx3F.js.map +1 -0
  31. package/dist/{ai-response-CvjV3WhV.js → ai-response-hbVCZJmo.js} +2 -2
  32. package/dist/{ai-response-CvjV3WhV.js.map → ai-response-hbVCZJmo.js.map} +1 -1
  33. package/dist/{ai-shimmer-j6lKIrjj.js → ai-shimmer-BamNMNK3.js} +2 -2
  34. package/dist/{ai-shimmer-j6lKIrjj.js.map → ai-shimmer-BamNMNK3.js.map} +1 -1
  35. package/dist/{ai-status-badge-CSU_QOdz.js → ai-status-badge-BZLczdkI.js} +2 -2
  36. package/dist/{ai-status-badge-CSU_QOdz.js.map → ai-status-badge-BZLczdkI.js.map} +1 -1
  37. package/dist/{ai-streaming-text-IWW1BhvZ.js → ai-streaming-text-DgYu64UH.js} +1 -1
  38. package/dist/{ai-streaming-text-IWW1BhvZ.js.map → ai-streaming-text-DgYu64UH.js.map} +1 -1
  39. package/dist/{ai-subagent-JA4iIMW3.js → ai-subagent-p97AI1h9.js} +3 -3
  40. package/dist/{ai-subagent-JA4iIMW3.js.map → ai-subagent-p97AI1h9.js.map} +1 -1
  41. package/dist/{ai-suggestion-BdO6MBuH.js → ai-suggestion-Bj6vF7CT.js} +3 -3
  42. package/dist/{ai-suggestion-BdO6MBuH.js.map → ai-suggestion-Bj6vF7CT.js.map} +1 -1
  43. package/dist/{ai-task-list-DYw4R1FA.js → ai-task-list-C_UQYpk9.js} +6 -4
  44. package/dist/{ai-task-list-DYw4R1FA.js.map → ai-task-list-C_UQYpk9.js.map} +1 -1
  45. package/dist/{ai-timeline-C42tOUT8.js → ai-timeline-CePL1LOU.js} +3 -3
  46. package/dist/ai-timeline-CePL1LOU.js.map +1 -0
  47. package/dist/{ai-tool-03jOTwUI.js → ai-tool-CfRcwmHT.js} +17 -11
  48. package/dist/ai-tool-CfRcwmHT.js.map +1 -0
  49. package/dist/{ai-usage-bar-BRf5LC_b.js → ai-usage-bar-45pVRCGA.js} +2 -2
  50. package/dist/{ai-usage-bar-BRf5LC_b.js.map → ai-usage-bar-45pVRCGA.js.map} +1 -1
  51. package/dist/{badge-BheXjMc8.js → badge-Beb-6uut.js} +5 -5
  52. package/dist/{badge-BheXjMc8.js.map → badge-Beb-6uut.js.map} +1 -1
  53. package/dist/{banner-CcsjunJg.js → banner-CCEksxPg.js} +3 -3
  54. package/dist/{banner-CcsjunJg.js.map → banner-CCEksxPg.js.map} +1 -1
  55. package/dist/{breadcrumbs-CouSyy3H.js → breadcrumbs-HiTmgaZ4.js} +5 -5
  56. package/dist/{breadcrumbs-CouSyy3H.js.map → breadcrumbs-HiTmgaZ4.js.map} +1 -1
  57. package/dist/{button-CO6-qPax.js → button-BHOgXJRU.js} +4 -4
  58. package/dist/{button-CO6-qPax.js.map → button-BHOgXJRU.js.map} +1 -1
  59. package/dist/catalog.js +1 -1
  60. package/dist/catalog.js.map +1 -1
  61. package/dist/{chart-Dg0qUeSc.js → chart-B9FfZdKs.js} +7 -7
  62. package/dist/chart-B9FfZdKs.js.map +1 -0
  63. package/dist/{checkbox-D7p4QKsC.js → checkbox-Cy_OCyay.js} +3 -3
  64. package/dist/{checkbox-D7p4QKsC.js.map → checkbox-Cy_OCyay.js.map} +1 -1
  65. package/dist/{clipboard-text-kLaMogs3.js → clipboard-text-CKSvNp9L.js} +6 -5
  66. package/dist/clipboard-text-CKSvNp9L.js.map +1 -0
  67. package/dist/{cn-YROP2_ox.js → cn-CmAOpn49.js} +2 -2
  68. package/dist/{cn-YROP2_ox.js.map → cn-CmAOpn49.js.map} +1 -1
  69. package/dist/{code-BN8InC0G.js → code-JsQz-0G_.js} +4 -4
  70. package/dist/{code-BN8InC0G.js.map → code-JsQz-0G_.js.map} +1 -1
  71. package/dist/{collapsible-D_ueZ0jz.js → collapsible-1kOZ-89L.js} +2 -2
  72. package/dist/{collapsible-D_ueZ0jz.js.map → collapsible-1kOZ-89L.js.map} +1 -1
  73. package/dist/{combobox-B7TOK0U2.js → combobox-CQwDmqgA.js} +4 -4
  74. package/dist/{combobox-B7TOK0U2.js.map → combobox-CQwDmqgA.js.map} +1 -1
  75. package/dist/command-line/cli.js +3 -3
  76. package/dist/{command-palette-CuNUyJca.js → command-palette-Bkuv3e6o.js} +20 -5
  77. package/dist/command-palette-Bkuv3e6o.js.map +1 -0
  78. package/dist/components/ai-actions.js +1 -1
  79. package/dist/components/ai-agent-card.js +1 -1
  80. package/dist/components/ai-approval.js +1 -1
  81. package/dist/components/ai-code-block.js +1 -1
  82. package/dist/components/ai-conversation.js +1 -1
  83. package/dist/components/ai-info-banner.js +1 -1
  84. package/dist/components/ai-message.js +1 -1
  85. package/dist/components/ai-mission-header.js +1 -1
  86. package/dist/components/ai-part-group.js +1 -1
  87. package/dist/components/ai-prompt-input.js +1 -1
  88. package/dist/components/ai-question.js +1 -1
  89. package/dist/components/ai-reasoning.js +1 -1
  90. package/dist/components/ai-response.js +1 -1
  91. package/dist/components/ai-shimmer.js +1 -1
  92. package/dist/components/ai-status-badge.js +1 -1
  93. package/dist/components/ai-streaming-text.js +1 -1
  94. package/dist/components/ai-subagent.js +1 -1
  95. package/dist/components/ai-suggestion.js +1 -1
  96. package/dist/components/ai-task-list.js +1 -1
  97. package/dist/components/ai-timeline.js +1 -1
  98. package/dist/components/ai-tool.js +1 -1
  99. package/dist/components/ai-usage-bar.js +1 -1
  100. package/dist/components/badge.js +1 -1
  101. package/dist/components/banner.js +1 -1
  102. package/dist/components/breadcrumbs.js +1 -1
  103. package/dist/components/button.js +1 -1
  104. package/dist/components/chart.js +2 -2
  105. package/dist/components/checkbox.js +1 -1
  106. package/dist/components/clipboard-text.js +1 -1
  107. package/dist/components/code.js +1 -1
  108. package/dist/components/collapsible.js +1 -1
  109. package/dist/components/combobox.js +1 -1
  110. package/dist/components/command-palette.js +1 -1
  111. package/dist/components/data-grid.js +1 -1
  112. package/dist/components/date-picker.js +1 -1
  113. package/dist/components/date-range-picker.js +1 -1
  114. package/dist/components/dialog.js +1 -1
  115. package/dist/components/dropdown.js +1 -1
  116. package/dist/components/empty.js +1 -1
  117. package/dist/components/field.js +1 -1
  118. package/dist/components/filters.js +1 -1
  119. package/dist/components/flow.js +1 -1
  120. package/dist/components/grid.js +1 -1
  121. package/dist/components/input.js +2 -2
  122. package/dist/components/label.js +1 -1
  123. package/dist/components/layer-card.js +1 -1
  124. package/dist/components/link.js +3 -3
  125. package/dist/components/link.js.map +1 -1
  126. package/dist/components/loader.js +2 -2
  127. package/dist/components/menubar.js +1 -1
  128. package/dist/components/meter.js +1 -1
  129. package/dist/components/pagination.js +1 -1
  130. package/dist/components/popover.js +1 -1
  131. package/dist/components/radio.js +1 -1
  132. package/dist/components/select.js +1 -1
  133. package/dist/components/sensitive-input.js +1 -1
  134. package/dist/components/sidebar.js +1 -1
  135. package/dist/components/signalflare-ai-logo.js +1 -1
  136. package/dist/components/sparkline.js +1 -1
  137. package/dist/components/stat-card.js +1 -1
  138. package/dist/components/surface.js +1 -1
  139. package/dist/components/switch.js +1 -1
  140. package/dist/components/table.js +1 -1
  141. package/dist/components/tabs.js +1 -1
  142. package/dist/components/text-roll.js +1 -1
  143. package/dist/components/text.js +1 -1
  144. package/dist/components/theme-toggle.js +1 -1
  145. package/dist/components/toast.js +1 -1
  146. package/dist/components/tooltip.js +1 -1
  147. package/dist/components/use-agent-harness.js +1 -1
  148. package/dist/{data-grid-DGHmU0w3.js → data-grid-DDSFMHud.js} +136 -53
  149. package/dist/data-grid-DDSFMHud.js.map +1 -0
  150. package/dist/{date-picker--ox89RBy.js → date-picker-O34AqG3f.js} +2 -2
  151. package/dist/{date-picker--ox89RBy.js.map → date-picker-O34AqG3f.js.map} +1 -1
  152. package/dist/{date-range-picker-DVa7QBqE.js → date-range-picker-YKYvum_r.js} +29 -39
  153. package/dist/{date-range-picker-DVa7QBqE.js.map → date-range-picker-YKYvum_r.js.map} +1 -1
  154. package/dist/{dialog-Bv1oSFOd.js → dialog-DYqu4aDO.js} +3 -3
  155. package/dist/{dialog-Bv1oSFOd.js.map → dialog-DYqu4aDO.js.map} +1 -1
  156. package/dist/{dist-B6iWiWwp.js → dist-6AtBsaJE.js} +153 -47
  157. package/dist/dist-6AtBsaJE.js.map +1 -0
  158. package/dist/{dropdown-B_nrGXjV.js → dropdown-XzbnRLYR.js} +15 -5
  159. package/dist/dropdown-XzbnRLYR.js.map +1 -0
  160. package/dist/{echart-CdOUaT-r.js → echart-DGBIVAv1.js} +23 -57
  161. package/dist/{echart-CdOUaT-r.js.map → echart-DGBIVAv1.js.map} +1 -1
  162. package/dist/{empty-DZnN0zKX.js → empty-C1tAkawe.js} +6 -6
  163. package/dist/{empty-DZnN0zKX.js.map → empty-C1tAkawe.js.map} +1 -1
  164. package/dist/{field-B_yVof52.js → field-DBpFzzBS.js} +3 -3
  165. package/dist/{field-B_yVof52.js.map → field-DBpFzzBS.js.map} +1 -1
  166. package/dist/{filters-cpJCY21R.js → filters-SmEl93za.js} +10 -10
  167. package/dist/filters-SmEl93za.js.map +1 -0
  168. package/dist/{flow-B4v198ot.js → flow-BLzgbq1T.js} +6 -6
  169. package/dist/flow-BLzgbq1T.js.map +1 -0
  170. package/dist/genui.js +2 -2
  171. package/dist/genui.js.map +1 -1
  172. package/dist/{grid-CEd64Lnh.js → grid-CifjQL-5.js} +2 -2
  173. package/dist/{grid-CEd64Lnh.js.map → grid-CifjQL-5.js.map} +1 -1
  174. package/dist/{highlight-to-react-D0Yav4jk.js → highlight-to-react-DN9dUCS2.js} +9 -15
  175. package/dist/highlight-to-react-DN9dUCS2.js.map +1 -0
  176. package/dist/index.js +71 -71
  177. package/dist/index.js.map +1 -1
  178. package/dist/{input-ClB_E4Lb.js → input-COmx2M_R.js} +5 -5
  179. package/dist/{input-ClB_E4Lb.js.map → input-COmx2M_R.js.map} +1 -1
  180. package/dist/{input-B2bbijRh.js → input-GkfMQZC_.js} +3 -3
  181. package/dist/{input-B2bbijRh.js.map → input-GkfMQZC_.js.map} +1 -1
  182. package/dist/{label-DUv_urO1.js → label-CiGZ464N.js} +3 -3
  183. package/dist/{label-DUv_urO1.js.map → label-CiGZ464N.js.map} +1 -1
  184. package/dist/{layer-card-BK7eYfwn.js → layer-card-8l8GuLQr.js} +2 -2
  185. package/dist/{layer-card-BK7eYfwn.js.map → layer-card-8l8GuLQr.js.map} +1 -1
  186. package/dist/{layout-DJHMMap2.js → layout-CWBE0qwx.js} +258 -154
  187. package/dist/layout-CWBE0qwx.js.map +1 -0
  188. package/dist/{link-provider-BUZKXaNE.js → link-provider-BSn8YJon.js} +2 -2
  189. package/dist/link-provider-BSn8YJon.js.map +1 -0
  190. package/dist/{loader-DAcc-Uag.js → loader-BEMz8pJO.js} +1 -1
  191. package/dist/{loader-DAcc-Uag.js.map → loader-BEMz8pJO.js.map} +1 -1
  192. package/dist/{measured-text-BI3dTJmH.js → measured-text-CXkdw9Yr.js} +45 -30
  193. package/dist/measured-text-CXkdw9Yr.js.map +1 -0
  194. package/dist/{menubar-Cxf3xeAt.js → menubar-CoOr4ocj.js} +3 -3
  195. package/dist/{menubar-Cxf3xeAt.js.map → menubar-CoOr4ocj.js.map} +1 -1
  196. package/dist/{meter-BFFe9l5b.js → meter-Pf_VOl59.js} +2 -2
  197. package/dist/{meter-BFFe9l5b.js.map → meter-Pf_VOl59.js.map} +1 -1
  198. package/dist/{pagination-yS372Tr4.js → pagination-DSY279Ta.js} +2 -2
  199. package/dist/{pagination-yS372Tr4.js.map → pagination-DSY279Ta.js.map} +1 -1
  200. package/dist/{popover-SRoJaCZr.js → popover-BY-e9co1.js} +2 -2
  201. package/dist/{popover-SRoJaCZr.js.map → popover-BY-e9co1.js.map} +1 -1
  202. package/dist/{radio-BcwhwYNB.js → radio-DZwL13j0.js} +2 -2
  203. package/dist/{radio-BcwhwYNB.js.map → radio-DZwL13j0.js.map} +1 -1
  204. package/dist/{select-DMhdoHMa.js → select-BFifYqHA.js} +6 -6
  205. package/dist/{select-DMhdoHMa.js.map → select-BFifYqHA.js.map} +1 -1
  206. package/dist/{sensitive-input-CJUpIRal.js → sensitive-input-DHLZcM73.js} +4 -4
  207. package/dist/{sensitive-input-CJUpIRal.js.map → sensitive-input-DHLZcM73.js.map} +1 -1
  208. package/dist/{sidebar-D4zrlYpn.js → sidebar-odGsdvG4.js} +6 -7
  209. package/dist/sidebar-odGsdvG4.js.map +1 -0
  210. package/dist/{signalflare-ai-logo-Bipogceq.js → signalflare-ai-logo-CNaDT_w8.js} +2 -2
  211. package/dist/{signalflare-ai-logo-Bipogceq.js.map → signalflare-ai-logo-CNaDT_w8.js.map} +1 -1
  212. package/dist/{skeleton-line-CH1-h6e2.js → skeleton-line-CxxYVTO2.js} +2 -2
  213. package/dist/{skeleton-line-CH1-h6e2.js.map → skeleton-line-CxxYVTO2.js.map} +1 -1
  214. package/dist/{sparkline-DHmgj1d0.js → sparkline-BQ-4j2W2.js} +2 -2
  215. package/dist/{sparkline-DHmgj1d0.js.map → sparkline-BQ-4j2W2.js.map} +1 -1
  216. package/dist/src/blocks/agent-harness/agent-harness.tsx +11 -11
  217. package/dist/src/blocks/commander/commander.tsx +15 -15
  218. package/dist/src/blocks/map-block/map-block.d.ts.map +1 -1
  219. package/dist/src/blocks/map-block/map-block.tsx +11 -7
  220. package/dist/src/components/ai-approval/ai-approval.d.ts.map +1 -1
  221. package/dist/src/components/ai-code-block/ai-code-block.d.ts +14 -13
  222. package/dist/src/components/ai-code-block/ai-code-block.d.ts.map +1 -1
  223. package/dist/src/components/ai-conversation/ai-conversation.d.ts.map +1 -1
  224. package/dist/src/components/ai-part-group/ai-part-group.d.ts.map +1 -1
  225. package/dist/src/components/ai-prompt-input/ai-prompt-input.d.ts.map +1 -1
  226. package/dist/src/components/ai-prompt-input/controller.d.ts.map +1 -1
  227. package/dist/src/components/ai-prompt-input/types.d.ts.map +1 -1
  228. package/dist/src/components/ai-question/ai-question.d.ts.map +1 -1
  229. package/dist/src/components/ai-reasoning/ai-reasoning.d.ts.map +1 -1
  230. package/dist/src/components/ai-response/ai-response.d.ts.map +1 -1
  231. package/dist/src/components/ai-subagent/ai-subagent.d.ts.map +1 -1
  232. package/dist/src/components/ai-tool/ai-tool.d.ts.map +1 -1
  233. package/dist/src/components/chart/echart.d.ts.map +1 -1
  234. package/dist/src/components/clipboard-text/clipboard-text.d.ts.map +1 -1
  235. package/dist/src/components/data-grid/data-grid.d.ts +2 -1
  236. package/dist/src/components/data-grid/data-grid.d.ts.map +1 -1
  237. package/dist/src/components/data-grid/features.d.ts +20 -0
  238. package/dist/src/components/data-grid/features.d.ts.map +1 -0
  239. package/dist/src/components/data-grid/types.d.ts +38 -7
  240. package/dist/src/components/data-grid/types.d.ts.map +1 -1
  241. package/dist/src/components/filters/filters.d.ts.map +1 -1
  242. package/dist/src/components/flow/use-children.d.ts +1 -1
  243. package/dist/src/components/link/link.d.ts.map +1 -1
  244. package/dist/src/components/sidebar/sidebar.d.ts +1 -1
  245. package/dist/src/components/signalflare-ai-logo/signalflare-ai-logo.d.ts.map +1 -1
  246. package/dist/src/components/text/text.d.ts +2 -1
  247. package/dist/src/components/text/text.d.ts.map +1 -1
  248. package/dist/src/components/text-roll/text-roll.d.ts.map +1 -1
  249. package/dist/src/components/theme-toggle/theme-toggle.d.ts.map +1 -1
  250. package/dist/src/components/toast/toast.d.ts.map +1 -1
  251. package/dist/src/utils/highlight-to-react.d.ts.map +1 -1
  252. package/dist/src/utils/measured-text.d.ts.map +1 -1
  253. package/dist/src/utils/use-measured-text.d.ts.map +1 -1
  254. package/dist/{stat-card-Ew-ofzEm.js → stat-card-Bspk4XFr.js} +4 -4
  255. package/dist/stat-card-Bspk4XFr.js.map +1 -0
  256. package/dist/styles/sf-standalone.css +1 -1
  257. package/dist/styles/theme-fedramp.css +3 -12
  258. package/dist/styles/theme-minimal.css +26 -104
  259. package/dist/styles/theme-sf.css +37 -142
  260. package/dist/{surface-DGwRlC0o.js → surface-CWdSFVUx.js} +3 -3
  261. package/dist/{surface-DGwRlC0o.js.map → surface-CWdSFVUx.js.map} +1 -1
  262. package/dist/{switch-BxAMfHdt.js → switch-TA4cByCJ.js} +5 -5
  263. package/dist/switch-TA4cByCJ.js.map +1 -0
  264. package/dist/{table-BBeAtYVZ.js → table-BM8JBGBs.js} +3 -3
  265. package/dist/{table-BBeAtYVZ.js.map → table-BM8JBGBs.js.map} +1 -1
  266. package/dist/{tabs-CeHu7Scn.js → tabs-bnH2vGLv.js} +2 -2
  267. package/dist/{tabs-CeHu7Scn.js.map → tabs-bnH2vGLv.js.map} +1 -1
  268. package/dist/{text-Cqryz7rk.js → text-iQ0YUFNg.js} +4 -5
  269. package/dist/{text-Cqryz7rk.js.map → text-iQ0YUFNg.js.map} +1 -1
  270. package/dist/{text-roll-Ch52hcQj.js → text-roll-C3U2jd2u.js} +5 -2
  271. package/dist/text-roll-C3U2jd2u.js.map +1 -0
  272. package/dist/{theme-toggle-LDfIKEqx.js → theme-toggle-BTVxD-fD.js} +10 -9
  273. package/dist/theme-toggle-BTVxD-fD.js.map +1 -0
  274. package/dist/{toast-CaFQNYng.js → toast-CgZVaAkw.js} +3 -3
  275. package/dist/{toast-CaFQNYng.js.map → toast-CgZVaAkw.js.map} +1 -1
  276. package/dist/{tooltip-g9lFsvcT.js → tooltip-uobk6Oh-.js} +3 -3
  277. package/dist/{tooltip-g9lFsvcT.js.map → tooltip-uobk6Oh-.js.map} +1 -1
  278. package/dist/{use-agent-harness-BTcNJdw4.js → use-agent-harness-Dl8w6X5O.js} +3 -3
  279. package/dist/{use-agent-harness-BTcNJdw4.js.map → use-agent-harness-Dl8w6X5O.js.map} +1 -1
  280. package/dist/utils.js +3 -3
  281. package/package.json +27 -25
  282. package/scripts/component-registry/discovery.ts +11 -10
  283. package/scripts/component-registry/example-cleanup.ts +8 -8
  284. package/scripts/component-registry/index.ts +6 -6
  285. package/scripts/component-registry/schema-generator.ts +1 -1
  286. package/scripts/component-registry/sub-components.ts +35 -23
  287. package/scripts/component-registry/utils.ts +11 -11
  288. package/scripts/component-registry/variant-parser.ts +17 -15
  289. package/scripts/convert-demos-to-stories.ts +5 -5
  290. package/scripts/theme-generator/config.ts +1 -5
  291. package/scripts/theme-generator/generate-css.ts +1 -1
  292. package/scripts/theme-generator/migrate.ts +3 -3
  293. package/dist/ai-agent-card-BR2NIYhi.js.map +0 -1
  294. package/dist/ai-code-block-CZtoL73R.js.map +0 -1
  295. package/dist/ai-conversation-Cc7WlaBg.js.map +0 -1
  296. package/dist/ai-part-group-DNb9I446.js.map +0 -1
  297. package/dist/ai-prompt-input-BVvov_KF.js.map +0 -1
  298. package/dist/ai-reasoning-_feFjk56.js.map +0 -1
  299. package/dist/ai-timeline-C42tOUT8.js.map +0 -1
  300. package/dist/ai-tool-03jOTwUI.js.map +0 -1
  301. package/dist/chart-Dg0qUeSc.js.map +0 -1
  302. package/dist/clipboard-text-kLaMogs3.js.map +0 -1
  303. package/dist/command-palette-CuNUyJca.js.map +0 -1
  304. package/dist/data-grid-DGHmU0w3.js.map +0 -1
  305. package/dist/dist-B6iWiWwp.js.map +0 -1
  306. package/dist/dropdown-B_nrGXjV.js.map +0 -1
  307. package/dist/filters-cpJCY21R.js.map +0 -1
  308. package/dist/flow-B4v198ot.js.map +0 -1
  309. package/dist/highlight-to-react-D0Yav4jk.js.map +0 -1
  310. package/dist/layout-DJHMMap2.js.map +0 -1
  311. package/dist/link-provider-BUZKXaNE.js.map +0 -1
  312. package/dist/measured-text-BI3dTJmH.js.map +0 -1
  313. package/dist/sidebar-D4zrlYpn.js.map +0 -1
  314. package/dist/stat-card-Ew-ofzEm.js.map +0 -1
  315. package/dist/switch-BxAMfHdt.js.map +0 -1
  316. package/dist/text-roll-Ch52hcQj.js.map +0 -1
  317. package/dist/theme-toggle-LDfIKEqx.js.map +0 -1
@@ -1,6 +1,6 @@
1
1
  "use client";
2
- import { t as cn } from "./cn-YROP2_ox.js";
3
- import { i as ChartPalette, n as CHART_DARK_COLORS, r as CHART_LIGHT_COLORS, t as Chart } from "./echart-CdOUaT-r.js";
2
+ import { t as cn } from "./cn-CmAOpn49.js";
3
+ import { i as ChartPalette, n as CHART_DARK_COLORS, r as CHART_LIGHT_COLORS, t as Chart } from "./echart-DGBIVAv1.js";
4
4
  import { useEffect, useMemo, useRef } from "react";
5
5
  import { jsx, jsxs } from "react/jsx-runtime";
6
6
  //#region src/components/chart/timeseries-chart.tsx
@@ -113,7 +113,7 @@ function TimeseriesChart({ echarts, type = "line", data, xAxisName, xAxisTickCou
113
113
  });
114
114
  const first = filteredParams[0];
115
115
  const ts = first?.value?.[0] ?? first?.axisValue;
116
- return `${ts != null ? `<div style="font-weight:600;margin-bottom:4px;">${formatTimestamp(ts)}</div>` : ""}${filteredParams.map((param) => {
116
+ return `${ts == null ? "" : `<div style="font-weight:600;margin-bottom:4px;">${formatTimestamp(ts)}</div>`}${filteredParams.map((param) => {
117
117
  const value = param?.value?.[1];
118
118
  const formatFn = tooltipValueFormat ?? yAxisTickLabelFormat;
119
119
  return `${param.marker} ${param.seriesName}: <strong>${formatFn ? formatFn(value) : value}</strong>`;
@@ -249,7 +249,7 @@ function ChartWaveLoader({ height, isDarkMode }) {
249
249
  const steps = 120;
250
250
  const points = [];
251
251
  for (let i = 0; i <= steps; i++) {
252
- const x = -period + i / steps * period * 3;
252
+ const x = -400 + i / steps * period * 3;
253
253
  const y = mid + Math.sin(i / steps * 2 * Math.PI * 3) * amp;
254
254
  points.push(`${i === 0 ? "M" : "L"}${x.toFixed(2)},${y.toFixed(2)}`);
255
255
  }
@@ -291,9 +291,9 @@ function ChartWaveLoader({ height, isDarkMode }) {
291
291
  */
292
292
  function colorWithOpacity(color, alpha) {
293
293
  const a = Math.max(0, Math.min(1, alpha));
294
- const rgbMatch = /rgba?\(\s*([\d.]+)\s*,\s*([\d.]+)\s*,\s*([\d.]+)/i.exec(color);
294
+ const rgbMatch = /rgba?\(\s*([\d.]+)\s*,\s*([\d.]+)\s*,\s*([\d.]+)/iu.exec(color);
295
295
  if (rgbMatch) return `rgba(${rgbMatch[1]}, ${rgbMatch[2]}, ${rgbMatch[3]}, ${a})`;
296
- let hex = color.replace(/^#/, "");
296
+ let hex = color.replace(/^#/u, "");
297
297
  if (hex.length === 3) hex = hex[0] + hex[0] + hex[1] + hex[1] + hex[2] + hex[2];
298
298
  if (hex.length === 8) hex = hex.slice(0, 6);
299
299
  return `rgba(${Number.parseInt(hex.slice(0, 2), 16)}, ${Number.parseInt(hex.slice(2, 4), 16)}, ${Number.parseInt(hex.slice(4, 6), 16)}, ${a})`;
@@ -809,4 +809,4 @@ function ScatterChart({ echarts, series, height = 320, xAxisName, yAxisName, xAx
809
809
  //#endregion
810
810
  export { BarChart as a, StackedBarChart as i, AreaChart as n, ChartLegend as o, PieChart as r, TimeseriesChart as s, ScatterChart as t };
811
811
 
812
- //# sourceMappingURL=chart-Dg0qUeSc.js.map
812
+ //# sourceMappingURL=chart-B9FfZdKs.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"chart-B9FfZdKs.js","names":[],"sources":["../src/components/chart/timeseries-chart.tsx","../src/components/chart/legend.tsx","../src/components/chart/bar-chart.tsx","../src/components/chart/stacked-bar-chart.tsx","../src/components/chart/pie-chart.tsx","../src/components/chart/area-chart.tsx","../src/components/chart/scatter-chart.tsx"],"sourcesContent":["import type { EChartsOption } from \"echarts\";\nimport type { LineSeriesOption, BarSeriesOption } from \"echarts/charts\";\nimport type * as echarts from \"echarts/core\";\nimport { useEffect, useMemo, useRef } from \"react\";\n\nimport { ChartPalette } from \"./color\";\nimport { Chart, ChartEvents } from \"./echart\";\n\n/** A single data series rendered on a `TimeseriesChart` */\nexport interface TimeseriesData {\n /** Display name shown in tooltips and legends */\n name: string;\n /** Array of `[timestamp_ms, value]` tuples ordered by time */\n data: [number, number][];\n /** Hex color string used for this series' line, bars, and legend dot */\n color: string;\n}\n\n/** Props for `TimeseriesChart` */\nexport interface TimeseriesChartProps {\n /**\n * The ECharts core instance imported by the consumer.\n * Passed in rather than imported directly so the consumer controls which\n * ECharts modules are bundled (tree-shaking).\n */\n echarts: typeof echarts;\n /** Visual style of each series. Defaults to `\"line\"`. */\n type?: \"line\" | \"bar\";\n /** Array of time series data to display on the chart */\n data: TimeseriesData[];\n /** Label for the x-axis (time axis) */\n xAxisName?: string;\n /** Number of ticks to display on the x-axis */\n xAxisTickCount?: number;\n /**\n * Custom formatter for x-axis tick labels.\n * Receives the raw timestamp in milliseconds and returns a display string,\n * overriding ECharts' built-in time formatting.\n */\n xAxisTickFormat?: (value: number) => string;\n /**\n * Custom formatter for y-axis tick labels.\n * Receives the raw value and returns a display string.\n * When omitted, ECharts' built-in formatter is used.\n */\n yAxisTickFormat?: (value: number) => string;\n /**\n * @deprecated Use `tooltipValueFormat` instead. This prop formats tooltip\n * values, not y-axis tick labels. It will be removed in a future major version.\n */\n yAxisTickLabelFormat?: (value: number) => string;\n /** Label for the y-axis (value axis) */\n yAxisName?: string;\n /** Number of ticks to display on the y-axis */\n yAxisTickCount?: number;\n /**\n * Custom formatter for tooltip values.\n * Receives the raw y-value and returns a display string.\n * When omitted, the raw value is shown. Takes precedence over the\n * deprecated `yAxisTickLabelFormat` prop.\n */\n tooltipValueFormat?: (value: number) => string;\n /** Indicates incomplete data periods with optional before/after timestamps in ms */\n incomplete?: { before?: number; after?: number };\n /** Height of the chart in pixels. Defaults to `350`. */\n height?: number;\n /** Callback fired when user selects a time range via brush selection */\n onTimeRangeChange?: (from: number, to: number) => void;\n /** When `true`, switches the chart to ECharts' built-in dark theme */\n isDarkMode?: boolean;\n /**\n * When `true`, renders a vertical gradient fill beneath each line series.\n * The gradient fades from the series' color at the top to transparent at the bottom.\n * Has no effect when `type` is `\"bar\"`.\n */\n gradient?: boolean;\n /**\n * When `true`, hides the chart and displays an animated sine-wave skeleton\n * that oscillates back and forth to indicate that data is being fetched.\n */\n loading?: boolean;\n /**\n * Accessible description for screen readers. When provided, it is passed to\n * ECharts' `aria.label.description` and announced when the chart receives\n * focus. Consumers are responsible for writing a meaningful description —\n * see the W3C guidance on complex images for recommendations.\n *\n * @see https://www.w3.org/WAI/tutorials/images/complex/\n * @see https://echarts.apache.org/handbook/en/best-practices/aria/\n */\n ariaDescription?: string;\n}\n\n/**\n * TimeseriesChart — a time-series line or bar chart.\n *\n * Built on `Chart` (Apache ECharts) with opinionated defaults for time-series data:\n * a time-typed x-axis, dashed lines for incomplete data periods, brush-based\n * time range selection, and automatic tooltip deduplication.\n *\n * @example\n * ```tsx\n * import * as echarts from \"echarts/core\";\n * import { LineChart } from \"echarts/charts\";\n * import { GridComponent, TooltipComponent, BrushComponent, ToolboxComponent } from \"echarts/components\";\n * import { CanvasRenderer } from \"echarts/renderers\";\n *\n * echarts.use([LineChart, GridComponent, TooltipComponent, BrushComponent, ToolboxComponent, CanvasRenderer]);\n *\n * const [range, setRange] = useState<[number, number]>();\n *\n * <TimeseriesChart\n * echarts={echarts}\n * data={[{ name: \"Requests\", data: [[Date.now(), 42]], color: \"#086FFF\" }]}\n * xAxisName=\"Time\"\n * xAxisTickFormat={(ts) => new Date(ts).toLocaleTimeString()}\n * yAxisName=\"Count\"\n * yAxisTickFormat={(value) => `${value / 1000}k`}\n * tooltipValueFormat={(value) => `${value.toFixed(2)} req/s`}\n * onTimeRangeChange={(from, to) => setRange([from, to])}\n * />\n * ```\n */\nexport function TimeseriesChart({\n echarts,\n type = \"line\",\n data,\n xAxisName,\n xAxisTickCount,\n xAxisTickFormat,\n yAxisTickFormat,\n yAxisTickLabelFormat,\n yAxisName,\n yAxisTickCount,\n tooltipValueFormat,\n onTimeRangeChange,\n height = 350,\n incomplete,\n isDarkMode,\n gradient,\n loading,\n ariaDescription,\n}: TimeseriesChartProps) {\n const chartRef = useRef<echarts.ECharts | null>(null);\n const incompleteBefore = incomplete?.before;\n const incompleteAfter = incomplete?.after;\n\n const options = useMemo(() => {\n const transformSeries: Array<LineSeriesOption | BarSeriesOption> = [];\n\n const seriesType =\n type === \"bar\"\n ? ({ type: \"bar\", stack: \"total\" } as const)\n : ({ type: \"line\", showSymbol: false } as const);\n\n for (const s of data) {\n const incompleteBeforePoints =\n incompleteBefore && type === \"line\"\n ? s.data.filter((point) => point[0] <= incompleteBefore)\n : [];\n\n const incompleteAfterPoints =\n incompleteAfter && type === \"line\"\n ? s.data.filter((point) => point[0] >= incompleteAfter)\n : [];\n\n const completePoints =\n incompleteBeforePoints.length > 0 || incompleteAfterPoints.length > 0\n ? s.data.slice(\n Math.max(0, incompleteBeforePoints.length - 1),\n Math.max(0, s.data.length - incompleteAfterPoints.length + 1)\n )\n : s.data;\n\n // Main complete data series\n const areaStyle =\n gradient && type === \"line\"\n ? {\n color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [\n { offset: 0, color: colorWithOpacity(s.color, 0.4) },\n { offset: 1, color: colorWithOpacity(s.color, 0) },\n ]),\n }\n : undefined;\n\n transformSeries.push({\n data: completePoints,\n color: s.color,\n name: s.name,\n emphasis: { focus: \"series\" },\n ...(areaStyle ? { areaStyle } : {}),\n ...seriesType,\n });\n\n // Incomplete data series with dashed lines\n const incompleteSeriesConfig = {\n color: s.color,\n name: s.name,\n type: \"line\" as const,\n lineStyle: { type: \"dashed\" as const },\n showSymbol: false,\n emphasis: { focus: \"series\" as const },\n };\n\n if (incompleteBeforePoints.length > 0) {\n transformSeries.push({\n ...incompleteSeriesConfig,\n data: incompleteBeforePoints,\n });\n }\n\n if (incompleteAfterPoints.length > 0) {\n transformSeries.push({\n ...incompleteSeriesConfig,\n data: incompleteAfterPoints,\n });\n }\n }\n\n return {\n aria: {\n enabled: true,\n ...(ariaDescription && { label: { description: ariaDescription } }),\n },\n brush: {\n snapToData: true,\n xAxisIndex: \"all\" as const,\n brushType: \"lineX\" as const,\n brushMode: \"single\" as const,\n outOfBrush: {\n colorAlpha: 0.3,\n },\n brushStyle: {\n borderWidth: 1,\n color: \"rgba(120,140,180,0.3)\",\n borderColor: \"rgba(120,140,180,0.8)\",\n },\n },\n tooltip: {\n trigger: \"axis\" as const,\n axisPointer: { type: \"shadow\" as const },\n formatter: (params: any) => {\n const items = Array.isArray(params) ? params : [params];\n\n // Track seen series names to avoid duplicates in tooltip\n // This is needed because incomplete data series (dashed lines) and complete data series\n // can overlap at the same timestamp, causing duplicate entries in the tooltip\n const seenNames = new Set<string>();\n const filteredParams = items.filter((param: any) => {\n if (seenNames.has(param.seriesName)) return false;\n seenNames.add(param.seriesName);\n return true;\n });\n\n const first = filteredParams[0];\n const ts = first?.value?.[0] ?? first?.axisValue;\n const header =\n ts == null\n ? \"\"\n : `<div style=\"font-weight:600;margin-bottom:4px;\">${formatTimestamp(ts)}</div>`;\n\n const rows = filteredParams\n .map((param: any) => {\n const value = param?.value?.[1];\n const formatFn = tooltipValueFormat ?? yAxisTickLabelFormat;\n return `${param.marker} ${param.seriesName}: <strong>${formatFn ? formatFn(value) : value}</strong>`;\n })\n .join(\"<br/>\");\n\n return `${header}${rows}`;\n },\n },\n backgroundColor: \"transparent\",\n toolbox: { show: false },\n xAxis: {\n name: xAxisName,\n nameLocation: \"middle\" as const,\n nameGap: 30,\n type: \"time\" as const,\n splitLine: {\n show: true,\n lineStyle: {\n color: ChartPalette.axisLine(isDarkMode),\n type: \"dashed\" as const,\n width: 1,\n },\n },\n axisLine: { show: false },\n splitNumber: xAxisTickCount ?? 5,\n ...(xAxisTickFormat && {\n axisLabel: {\n formatter: (value: number) => xAxisTickFormat(value),\n },\n }),\n },\n yAxis: {\n name: yAxisName,\n nameLocation: \"middle\" as const,\n nameGap: 40,\n type: \"value\" as const,\n axisLine: { show: false },\n axisTick: { show: false },\n axisLabel: {\n margin: 15,\n ...(yAxisTickFormat && {\n formatter: (value: number) => yAxisTickFormat(value),\n }),\n },\n splitLine: {\n show: true,\n lineStyle: {\n color: ChartPalette.axisLine(isDarkMode),\n type: \"dashed\" as const,\n width: 1,\n },\n },\n splitNumber: yAxisTickCount,\n },\n grid: {\n left: yAxisName ? 30 : 24,\n right: 24,\n top: 24,\n bottom: xAxisName ? 30 : 24,\n },\n series: transformSeries,\n };\n }, [\n data,\n xAxisName,\n xAxisTickCount,\n xAxisTickFormat,\n yAxisTickFormat,\n yAxisTickLabelFormat,\n yAxisName,\n yAxisTickCount,\n tooltipValueFormat,\n incompleteBefore,\n incompleteAfter,\n type,\n gradient,\n echarts,\n ariaDescription,\n ]);\n\n const events = useMemo<Partial<ChartEvents>>(() => {\n if (!onTimeRangeChange) return {};\n\n return {\n brushend: (params) => {\n const range = params.areas[0].coordRange;\n onTimeRangeChange(range[0], range[1]);\n chartRef.current?.dispatchAction({ type: \"brush\", areas: [] });\n },\n };\n }, [onTimeRangeChange]);\n\n // Activate the lineX brush cursor when a time-range callback is provided,\n // and deactivate it on cleanup so the cursor resets when the prop is removed.\n const hasTimeRangeCallback = !!onTimeRangeChange;\n useEffect(() => {\n const chart = chartRef.current;\n if (chart && hasTimeRangeCallback) {\n chart.dispatchAction({\n type: \"takeGlobalCursor\",\n key: \"brush\",\n brushOption: {\n brushType: \"lineX\" as const,\n brushMode: \"single\" as const,\n },\n });\n\n return () => {\n chart.dispatchAction({\n type: \"takeGlobalCursor\",\n key: \"brush\",\n brushOption: {\n brushType: false,\n },\n });\n };\n }\n // `loading` controls whether <Chart> is mounted. When it flips to false,\n // chartRef.current becomes available and the brush cursor must be activated.\n // Without this dep, the effect won't re-run after Chart mounts.\n }, [chartRef, hasTimeRangeCallback, loading]);\n\n return (\n <div className=\"relative w-full\" style={{ height }}>\n {loading && <ChartWaveLoader height={height} isDarkMode={isDarkMode} />}\n {!loading && (\n <Chart\n echarts={echarts}\n ref={chartRef}\n options={options as EChartsOption}\n height={height}\n isDarkMode={isDarkMode}\n onEvents={events}\n />\n )}\n </div>\n );\n}\n\n/**\n * Animated sine-wave skeleton shown while `TimeseriesChart` is in `loading` state.\n * Renders multiple staggered wave paths that sweep continuously left-to-right,\n * mimicking the motion of live time-series data being drawn.\n */\nfunction ChartWaveLoader({\n height,\n isDarkMode,\n}: {\n height: number;\n isDarkMode?: boolean;\n}) {\n const mid = height / 2;\n const amp = Math.min(height * 0.12, 28);\n const period = 400;\n const steps = 120;\n\n const points: string[] = [];\n for (let i = 0; i <= steps; i++) {\n const x = -period + (i / steps) * period * 3;\n const y = mid + Math.sin((i / steps) * 2 * Math.PI * 3) * amp;\n points.push(`${i === 0 ? \"M\" : \"L\"}${x.toFixed(2)},${y.toFixed(2)}`);\n }\n const d = points.join(\" \");\n\n const strokeColor = isDarkMode ? \"rgba(255,255,255,0.5)\" : \"rgba(0,0,0,0.2)\";\n\n return (\n <div\n aria-hidden=\"true\"\n className=\"absolute inset-0 overflow-hidden\"\n style={{ height }}\n >\n <style>{`@keyframes sf-chart-wave{from{transform:translateX(0)}to{transform:translateX(${period}px)}}`}</style>\n <svg\n width=\"100%\"\n height={height}\n viewBox={`0 0 ${period} ${height}`}\n preserveAspectRatio=\"none\"\n className=\"w-full animate-pulse\"\n >\n <path\n d={d}\n fill=\"none\"\n stroke={strokeColor}\n strokeWidth=\"2\"\n style={{\n animation: `sf-chart-wave 2.4s linear infinite`,\n transformOrigin: \"0 0\",\n }}\n />\n </svg>\n </div>\n );\n}\n\n/**\n * Returns an `rgba(r, g, b, alpha)` string for any hex or rgb(a) color input,\n * replacing whatever opacity was already present with the given `alpha` (0–1).\n *\n * Handles:\n * - 6-digit hex: `#RRGGBB`\n * - 8-digit hex: `#RRGGBBAA` ← strips existing alpha\n * - 3-digit hex: `#RGB`\n * - `rgb(r, g, b)`\n * - `rgba(r, g, b, a)` ← replaces existing alpha\n */\nfunction colorWithOpacity(color: string, alpha: number): string {\n const a = Math.max(0, Math.min(1, alpha));\n\n // rgb / rgba\n const rgbMatch = /rgba?\\(\\s*([\\d.]+)\\s*,\\s*([\\d.]+)\\s*,\\s*([\\d.]+)/iu.exec(\n color\n );\n if (rgbMatch) {\n return `rgba(${rgbMatch[1]}, ${rgbMatch[2]}, ${rgbMatch[3]}, ${a})`;\n }\n\n // hex — strip leading #\n let hex = color.replace(/^#/u, \"\");\n\n // expand 3-digit → 6-digit\n if (hex.length === 3) {\n hex = hex[0] + hex[0] + hex[1] + hex[1] + hex[2] + hex[2];\n }\n\n // strip 8-digit alpha → keep only 6\n if (hex.length === 8) {\n hex = hex.slice(0, 6);\n }\n\n const r = Number.parseInt(hex.slice(0, 2), 16);\n const g = Number.parseInt(hex.slice(2, 4), 16);\n const b = Number.parseInt(hex.slice(4, 6), 16);\n\n return `rgba(${r}, ${g}, ${b}, ${a})`;\n}\n\n/** Zero-pads a number to two digits (e.g. `5` → `\"05\"`) */\nfunction pad(n: number) {\n return n.toString().padStart(2, \"0\");\n}\n\n/**\n * Formats a timestamp as `\"YYYY-MM-DD HH:mm:ss\"` for use in chart tooltips.\n * Accepts a Unix timestamp in milliseconds, an ISO date string, or a `Date` object.\n */\nfunction formatTimestamp(ts: number | string | Date): string {\n const d = new Date(ts);\n return `${d.getFullYear()}-${pad(d.getMonth() + 1)}-${pad(d.getDate())} ${pad(d.getHours())}:${pad(d.getMinutes())}:${pad(d.getSeconds())}`;\n}\n","import { cn } from \"../../utils\";\n\n/** Shared props for both legend item variants */\ninterface LegendItemProps {\n /** Series name shown as a label */\n name: string;\n /** Hex color string for the series indicator dot */\n color: string;\n /** Formatted value string to display */\n value: string;\n /** Optional unit label shown after the value (e.g. `\"ms\"`, `\"%\"`) */\n unit?: string;\n /** When `true`, renders the item at 50% opacity to indicate a deselected state */\n inactive?: boolean;\n}\n\n/**\n * Large legend item — stacked layout with a colored dot + series name on top\n * and a large value with an optional small unit below. Use for prominent\n * single-metric displays such as dashboard cards.\n */\nfunction LargeItem({ color, value, name, unit, inactive }: LegendItemProps) {\n return (\n <div className=\"inline-flex flex-col gap-2 min-w-42 py-2\">\n <div className=\"flex items-center gap-2\">\n <span\n className={cn(\"size-2 rounded-full inline-block\", {\n \"opacity-50\": inactive,\n })}\n style={{ backgroundColor: color }}\n />\n <span className={cn(\"text-xs\", { \"opacity-50\": inactive })}>\n {name}\n </span>\n </div>\n <div className=\"flex items-baseline gap-0.5\">\n <span\n className={cn(\"text-lg font-medium leading-none\", {\n \"opacity-50\": inactive,\n })}\n >\n {value}\n </span>\n {unit && (\n <span\n className={cn(\"text-xs text-sf-subtle leading-none\", {\n \"opacity-50\": inactive,\n })}\n >\n {unit}\n </span>\n )}\n </div>\n </div>\n );\n}\n\n/**\n * Small legend item — inline layout with a colored dot, series name, and value\n * on a single row. Use for compact legends below or beside a chart.\n */\nfunction SmallItem({ color, value, name, inactive }: LegendItemProps) {\n return (\n <div className=\"inline-flex items-center gap-2\">\n <span\n className={cn(\"size-2 rounded-full inline-block\", {\n \"opacity-50\": inactive,\n })}\n style={{ backgroundColor: color }}\n />\n <span className={cn(\"text-xs\", { \"opacity-50\": inactive })}>{name}</span>\n <span className={cn(\"text-xs font-medium\", { \"opacity-50\": inactive })}>\n {value}\n </span>\n </div>\n );\n}\n\n/**\n * ChartLegend — pre-built legend item components for use alongside a chart.\n *\n * - `ChartLegend.SmallItem` — compact inline layout; suited for multi-series legends\n * - `ChartLegend.LargeItem` — stacked layout with a large value; suited for single-metric cards\n *\n * @example\n * ```tsx\n * <ChartLegend.SmallItem name=\"Requests\" color=\"#086FFF\" value=\"1,234\" />\n * <ChartLegend.LargeItem name=\"Latency\" color=\"#CF7EE9\" value=\"42\" unit=\"ms\" inactive />\n * ```\n */\nexport const ChartLegend = {\n SmallItem,\n LargeItem,\n};\n","import type { EChartsOption } from \"echarts\";\nimport type * as echarts from \"echarts/core\";\nimport { useMemo } from \"react\";\n\nimport { ChartPalette, CHART_DARK_COLORS, CHART_LIGHT_COLORS } from \"./color\";\nimport { Chart } from \"./echart\";\n\n/** A single bar value on a `BarChart` */\nexport interface BarChartDatum {\n /** Category name shown on the axis and in tooltips */\n name: string;\n /** Numeric value represented by the bar */\n value: number;\n /** Optional override color for this bar; defaults to the categorical palette */\n color?: string;\n}\n\n/** Props for `BarChart` */\nexport interface BarChartProps {\n /**\n * The ECharts core instance imported by the consumer.\n * Passed in rather than imported directly so the consumer controls which\n * ECharts modules are bundled (tree-shaking).\n */\n echarts: typeof echarts;\n /** Array of bars to display */\n data: BarChartDatum[];\n /** Axis orientation. `\"vertical\"` draws bars upward from the x-axis. */\n orientation?: \"vertical\" | \"horizontal\";\n /** Height of the chart in pixels. Defaults to `320`. */\n height?: number;\n /** Custom formatter for value-axis tick labels */\n yAxisTickFormat?: (value: number) => string;\n /** Custom formatter for tooltip values */\n tooltipValueFormat?: (value: number) => string;\n /** When `true`, switches ECharts to its built-in dark theme */\n isDarkMode?: boolean;\n /**\n * When `true`, hides the chart and displays a neutral skeleton placeholder\n * to indicate data is being fetched.\n */\n loading?: boolean;\n /** Callback fired when a bar is clicked (receives the bar's `name`) */\n onBarClick?: (name: string) => void;\n /** Additional CSS classes applied to the chart container */\n className?: string;\n}\n\n/**\n * BarChart — categorical bar chart for comparing discrete values.\n *\n * Consumer must register `BarChart`, `GridComponent`, `TooltipComponent`, and a\n * renderer (e.g. `CanvasRenderer`) on the passed-in `echarts` instance.\n *\n * @example\n * ```tsx\n * <BarChart\n * echarts={echarts}\n * data={[\n * { name: \"Mon\", value: 120 },\n * { name: \"Tue\", value: 200 },\n * { name: \"Wed\", value: 150 },\n * ]}\n * />\n * ```\n */\nexport function BarChart({\n echarts,\n data,\n orientation = \"vertical\",\n height = 320,\n yAxisTickFormat,\n tooltipValueFormat,\n isDarkMode,\n loading,\n onBarClick,\n className,\n}: BarChartProps) {\n const options = useMemo<EChartsOption>(() => {\n const palette = isDarkMode ? CHART_DARK_COLORS : CHART_LIGHT_COLORS;\n const axis = ChartPalette.axisDefaults(isDarkMode);\n const categoryAxis = {\n ...axis,\n type: \"category\" as const,\n data: data.map((d) => d.name),\n };\n const valueAxis = {\n ...axis,\n type: \"value\" as const,\n axisLabel: yAxisTickFormat\n ? { formatter: (v: number) => yAxisTickFormat(v) }\n : undefined,\n };\n\n return {\n grid: { left: 40, right: 16, top: 24, bottom: 32, containLabel: true },\n tooltip: {\n trigger: \"axis\",\n axisPointer: { type: \"shadow\" },\n valueFormatter: tooltipValueFormat\n ? (value: unknown) =>\n typeof value === \"number\"\n ? tooltipValueFormat(value)\n : String(value)\n : undefined,\n },\n xAxis: orientation === \"vertical\" ? categoryAxis : valueAxis,\n yAxis: orientation === \"vertical\" ? valueAxis : categoryAxis,\n series: [\n {\n type: \"bar\",\n data: data.map((d, i) => ({\n value: d.value,\n itemStyle: { color: d.color ?? palette[i % palette.length] },\n })),\n },\n ],\n };\n }, [data, orientation, yAxisTickFormat, tooltipValueFormat, isDarkMode]);\n\n const onEvents = useMemo(\n () =>\n onBarClick\n ? {\n click: (params: { name?: string }) => {\n if (params.name) onBarClick(params.name);\n },\n }\n : undefined,\n [onBarClick]\n );\n\n if (loading) {\n return (\n <div\n aria-busy=\"true\"\n className={className}\n style={{ height }}\n data-sf-skeleton=\"\"\n >\n <div className=\"h-full w-full animate-pulse rounded-md bg-sf-fill\" />\n </div>\n );\n }\n\n return (\n <Chart\n echarts={echarts}\n options={options}\n height={height}\n isDarkMode={isDarkMode}\n className={className}\n onEvents={onEvents}\n />\n );\n}\n","import type { EChartsOption } from \"echarts\";\nimport type * as echarts from \"echarts/core\";\nimport { useMemo } from \"react\";\n\nimport { ChartPalette, CHART_DARK_COLORS, CHART_LIGHT_COLORS } from \"./color\";\nimport { Chart } from \"./echart\";\n\n/** A single series on a `StackedBarChart`. */\nexport interface StackedBarSeries {\n /** Series name displayed in tooltips and legends */\n name: string;\n /** Values aligned 1:1 with the parent `categories` array */\n data: number[];\n /** Optional override color; defaults to the categorical palette */\n color?: string;\n}\n\n/** Props for `StackedBarChart` */\nexport interface StackedBarChartProps {\n /**\n * The ECharts core instance imported by the consumer.\n * Passed in rather than imported directly so the consumer controls which\n * ECharts modules are bundled (tree-shaking).\n */\n echarts: typeof echarts;\n /** Category labels rendered on the non-value axis */\n categories: string[];\n /** Array of stacked series */\n series: StackedBarSeries[];\n /** Axis orientation. `\"vertical\"` draws bars upward from the x-axis. */\n orientation?: \"vertical\" | \"horizontal\";\n /**\n * When `true`, renders as a 100%-stacked chart where each category sums to 100.\n * @default false\n */\n percent?: boolean;\n /** Height of the chart in pixels. Defaults to `320`. */\n height?: number;\n /** Custom formatter for value-axis tick labels */\n yAxisTickFormat?: (value: number) => string;\n /** Custom formatter for tooltip values */\n tooltipValueFormat?: (value: number) => string;\n /** When `true`, switches ECharts to its built-in dark theme */\n isDarkMode?: boolean;\n /** When `true`, hides the chart and displays a neutral skeleton placeholder */\n loading?: boolean;\n /** Additional CSS classes applied to the chart container */\n className?: string;\n}\n\n/**\n * StackedBarChart — stacked categorical bar chart for part-to-whole comparisons.\n *\n * @example\n * ```tsx\n * <StackedBarChart\n * echarts={echarts}\n * categories={[\"Mon\", \"Tue\", \"Wed\"]}\n * series={[\n * { name: \"Desktop\", data: [100, 120, 90] },\n * { name: \"Mobile\", data: [60, 80, 110] },\n * ]}\n * />\n * ```\n */\nexport function StackedBarChart({\n echarts,\n categories,\n series,\n orientation = \"vertical\",\n percent = false,\n height = 320,\n yAxisTickFormat,\n tooltipValueFormat,\n isDarkMode,\n loading,\n className,\n}: StackedBarChartProps) {\n const options = useMemo<EChartsOption>(() => {\n const palette = isDarkMode ? CHART_DARK_COLORS : CHART_LIGHT_COLORS;\n\n // For percent mode, normalize each position across all series to sum to 100.\n const resolvedSeries = percent\n ? series.map((s) => ({\n ...s,\n data: s.data.map((v, i) => {\n const total = series.reduce(\n (acc, other) => acc + (other.data[i] ?? 0),\n 0\n );\n return total === 0 ? 0 : (v / total) * 100;\n }),\n }))\n : series;\n\n const axis = ChartPalette.axisDefaults(isDarkMode);\n const categoryAxis = {\n ...axis,\n type: \"category\" as const,\n data: categories,\n };\n const valueAxis = {\n ...axis,\n type: \"value\" as const,\n max: percent ? 100 : undefined,\n axisLabel: yAxisTickFormat\n ? { formatter: (v: number) => yAxisTickFormat(v) }\n : percent\n ? { formatter: \"{value}%\" }\n : undefined,\n };\n\n return {\n legend: { bottom: 0 },\n grid: { left: 40, right: 16, top: 24, bottom: 48, containLabel: true },\n tooltip: {\n trigger: \"axis\",\n axisPointer: { type: \"shadow\" },\n valueFormatter: tooltipValueFormat\n ? (value: unknown) =>\n typeof value === \"number\"\n ? tooltipValueFormat(value)\n : String(value)\n : undefined,\n },\n xAxis: orientation === \"vertical\" ? categoryAxis : valueAxis,\n yAxis: orientation === \"vertical\" ? valueAxis : categoryAxis,\n series: resolvedSeries.map((s, i) => ({\n name: s.name,\n type: \"bar\" as const,\n stack: \"total\",\n data: s.data,\n itemStyle: { color: s.color ?? palette[i % palette.length] },\n })),\n };\n }, [\n categories,\n series,\n orientation,\n percent,\n yAxisTickFormat,\n tooltipValueFormat,\n isDarkMode,\n ]);\n\n if (loading) {\n return (\n <div aria-busy=\"true\" className={className} style={{ height }}>\n <div className=\"h-full w-full animate-pulse rounded-md bg-sf-fill\" />\n </div>\n );\n }\n\n return (\n <Chart\n echarts={echarts}\n options={options}\n height={height}\n isDarkMode={isDarkMode}\n className={className}\n />\n );\n}\n","import type { EChartsOption } from \"echarts\";\nimport type * as echarts from \"echarts/core\";\nimport type { ReactNode } from \"react\";\nimport { useMemo } from \"react\";\n\nimport { cn } from \"../../utils/cn\";\nimport { CHART_DARK_COLORS, CHART_LIGHT_COLORS } from \"./color\";\nimport { Chart } from \"./echart\";\n\n/** A single slice of a `PieChart` */\nexport interface PieChartDatum {\n /** Display name shown in tooltips and legends */\n name: string;\n /** Numeric value determining the slice's arc size */\n value: number;\n /** Optional override color; defaults to the categorical palette */\n color?: string;\n}\n\n/** Props for `PieChart` */\nexport interface PieChartProps {\n /**\n * The ECharts core instance imported by the consumer.\n * Passed in rather than imported directly so the consumer controls which\n * ECharts modules are bundled (tree-shaking).\n */\n echarts: typeof echarts;\n /** Array of slice data */\n data: PieChartDatum[];\n /**\n * Visual variant. `\"donut\"` renders with a hollow center suitable for\n * overlaying a centered label via `centerSlot`.\n * @default \"pie\"\n */\n variant?: \"pie\" | \"donut\";\n /** Height of the chart in pixels. Defaults to `320`. */\n height?: number;\n /** When `true`, shows a legend below the chart. */\n showLegend?: boolean;\n /** Custom formatter for tooltip values */\n tooltipValueFormat?: (value: number) => string;\n /** When `true`, switches ECharts to its built-in dark theme */\n isDarkMode?: boolean;\n /** When `true`, hides the chart and displays a neutral skeleton placeholder */\n loading?: boolean;\n /**\n * Optional content rendered absolutely centered over the chart. Intended for\n * donut variants — displays a KPI (e.g. total value) in the hole.\n */\n centerSlot?: ReactNode;\n /** Additional CSS classes applied to the chart container */\n className?: string;\n}\n\n/**\n * PieChart — single-series pie or donut chart for part-to-whole relationships.\n *\n * @example\n * ```tsx\n * <PieChart\n * echarts={echarts}\n * variant=\"donut\"\n * data={[\n * { name: \"Prod\", value: 60 },\n * { name: \"Staging\", value: 30 },\n * { name: \"Dev\", value: 10 },\n * ]}\n * centerSlot={<span className=\"text-sf-strong\">100</span>}\n * />\n * ```\n */\nexport function PieChart({\n echarts,\n data,\n variant = \"pie\",\n height = 320,\n showLegend,\n tooltipValueFormat,\n isDarkMode,\n loading,\n centerSlot,\n className,\n}: PieChartProps) {\n const options = useMemo<EChartsOption>(() => {\n const palette = isDarkMode ? CHART_DARK_COLORS : CHART_LIGHT_COLORS;\n return {\n legend: showLegend ? { bottom: 0 } : undefined,\n tooltip: {\n trigger: \"item\",\n valueFormatter: tooltipValueFormat\n ? (value: unknown) =>\n typeof value === \"number\"\n ? tooltipValueFormat(value)\n : String(value)\n : undefined,\n },\n series: [\n {\n type: \"pie\",\n radius: variant === \"donut\" ? [\"55%\", \"80%\"] : \"75%\",\n avoidLabelOverlap: true,\n label: {\n show: variant !== \"donut\",\n color: isDarkMode ? \"#e5e5e5\" : \"#1a1a1a\",\n textBorderWidth: 0,\n textBorderColor: \"transparent\",\n },\n labelLine: {\n show: variant !== \"donut\",\n lineStyle: { color: isDarkMode ? \"#e5e5e5\" : \"#1a1a1a\" },\n },\n data: data.map((d, i) => ({\n name: d.name,\n value: d.value,\n itemStyle: { color: d.color ?? palette[i % palette.length] },\n })),\n },\n ],\n };\n }, [data, variant, showLegend, tooltipValueFormat, isDarkMode]);\n\n if (loading) {\n return (\n <div aria-busy=\"true\" className={className} style={{ height }}>\n <div className=\"h-full w-full animate-pulse rounded-full bg-sf-fill\" />\n </div>\n );\n }\n\n return (\n <div className={cn(\"relative\", className)} style={{ height }}>\n <Chart\n echarts={echarts}\n options={options}\n height={height}\n isDarkMode={isDarkMode}\n />\n {centerSlot !== undefined && variant === \"donut\" ? (\n <div className=\"pointer-events-none absolute inset-0 flex items-center justify-center\">\n {centerSlot}\n </div>\n ) : null}\n </div>\n );\n}\n","import type { EChartsOption } from \"echarts\";\nimport type * as echarts from \"echarts/core\";\nimport { useMemo } from \"react\";\n\nimport { ChartPalette, CHART_DARK_COLORS, CHART_LIGHT_COLORS } from \"./color\";\nimport { Chart } from \"./echart\";\n\n/** A single data series rendered on an `AreaChart` */\nexport interface AreaChartSeries {\n /** Display name shown in tooltips and legends */\n name: string;\n /**\n * Series data. For `\"time\"` x-axis: `[timestampMs, value][]`.\n * For `\"category\"` x-axis: a numeric array aligned with the parent `categories`.\n */\n data: [number, number][] | number[];\n /** Optional override color; defaults to the categorical palette */\n color?: string;\n}\n\n/** Props for `AreaChart` */\nexport interface AreaChartProps {\n /**\n * The ECharts core instance imported by the consumer.\n * Passed in rather than imported directly so the consumer controls which\n * ECharts modules are bundled (tree-shaking).\n */\n echarts: typeof echarts;\n /** Array of series to display */\n series: AreaChartSeries[];\n /**\n * X-axis type. `\"time\"` plots `[ts, value]` tuples; `\"category\"` plots\n * numeric arrays indexed against `categories`.\n * @default \"time\"\n */\n xAxisType?: \"time\" | \"category\";\n /** Required when `xAxisType === \"category\"` — labels rendered on the x-axis */\n categories?: string[];\n /** Height of the chart in pixels. Defaults to `320`. */\n height?: number;\n /** Label for the x-axis */\n xAxisName?: string;\n /** Label for the y-axis */\n yAxisName?: string;\n /** Custom formatter for y-axis tick labels */\n yAxisTickFormat?: (value: number) => string;\n /** Custom formatter for tooltip values */\n tooltipValueFormat?: (value: number) => string;\n /** When `true`, switches ECharts to its built-in dark theme */\n isDarkMode?: boolean;\n /** When `true`, stacks all series on top of one another */\n stacked?: boolean;\n /** When `true`, hides the chart and displays a neutral skeleton placeholder */\n loading?: boolean;\n /** Additional CSS classes applied to the chart container */\n className?: string;\n}\n\n/**\n * AreaChart — filled line chart with gradient fill, suitable for trend\n * visualisations on either a time or category x-axis.\n *\n * Unlike `TimeseriesChart`, this component also accepts a category x-axis,\n * making it useful for cohort or bucketed trend displays.\n *\n * @example\n * ```tsx\n * <AreaChart\n * echarts={echarts}\n * xAxisType=\"category\"\n * categories={[\"W1\", \"W2\", \"W3\", \"W4\"]}\n * series={[{ name: \"Signups\", data: [120, 180, 240, 200] }]}\n * />\n * ```\n */\nexport function AreaChart({\n echarts,\n series,\n xAxisType = \"time\",\n categories,\n height = 320,\n xAxisName,\n yAxisName,\n yAxisTickFormat,\n tooltipValueFormat,\n isDarkMode,\n stacked,\n loading,\n className,\n}: AreaChartProps) {\n const options = useMemo<EChartsOption>(() => {\n const palette = isDarkMode ? CHART_DARK_COLORS : CHART_LIGHT_COLORS;\n\n return {\n grid: { left: 40, right: 16, top: 24, bottom: 32, containLabel: true },\n legend: series.length > 1 ? { bottom: 0 } : undefined,\n tooltip: {\n trigger: \"axis\",\n valueFormatter: tooltipValueFormat\n ? (value: unknown) =>\n typeof value === \"number\"\n ? tooltipValueFormat(value)\n : String(value)\n : undefined,\n },\n xAxis:\n xAxisType === \"category\"\n ? {\n ...ChartPalette.axisDefaults(isDarkMode),\n type: \"category\" as const,\n name: xAxisName,\n data: categories,\n boundaryGap: false,\n }\n : {\n ...ChartPalette.axisDefaults(isDarkMode),\n type: \"time\" as const,\n name: xAxisName,\n },\n yAxis: {\n ...ChartPalette.axisDefaults(isDarkMode),\n type: \"value\",\n name: yAxisName,\n axisLabel: yAxisTickFormat\n ? { formatter: (v: number) => yAxisTickFormat(v) }\n : undefined,\n },\n series: series.map((s, i) => {\n const color = s.color ?? palette[i % palette.length];\n return {\n name: s.name,\n type: \"line\" as const,\n smooth: true,\n showSymbol: false,\n stack: stacked ? \"total\" : undefined,\n data: s.data,\n itemStyle: { color },\n lineStyle: { color },\n areaStyle: {\n color: {\n type: \"linear\" as const,\n x: 0,\n y: 0,\n x2: 0,\n y2: 1,\n colorStops: [\n { offset: 0, color },\n { offset: 1, color: \"rgba(0,0,0,0)\" },\n ],\n },\n opacity: 0.4,\n },\n };\n }),\n };\n }, [\n series,\n xAxisType,\n categories,\n xAxisName,\n yAxisName,\n yAxisTickFormat,\n tooltipValueFormat,\n stacked,\n isDarkMode,\n ]);\n\n if (loading) {\n return (\n <div aria-busy=\"true\" className={className} style={{ height }}>\n <div className=\"h-full w-full animate-pulse rounded-md bg-sf-fill\" />\n </div>\n );\n }\n\n return (\n <Chart\n echarts={echarts}\n options={options}\n height={height}\n isDarkMode={isDarkMode}\n className={className}\n />\n );\n}\n","import type { EChartsOption } from \"echarts\";\nimport type * as echarts from \"echarts/core\";\nimport { useMemo } from \"react\";\n\nimport { ChartPalette, CHART_DARK_COLORS, CHART_LIGHT_COLORS } from \"./color\";\nimport { Chart } from \"./echart\";\n\n/** A single scatter series (point cloud) */\nexport interface ScatterSeries {\n /** Display name shown in tooltips and legends */\n name: string;\n /** Array of `[x, y]` point tuples */\n data: [number, number][];\n /** Optional override color; defaults to the categorical palette */\n color?: string;\n /** Optional marker size in pixels (default 8) */\n symbolSize?: number;\n}\n\n/** Props for `ScatterChart` */\nexport interface ScatterChartProps {\n /**\n * The ECharts core instance imported by the consumer.\n * Passed in rather than imported directly so the consumer controls which\n * ECharts modules are bundled (tree-shaking).\n */\n echarts: typeof echarts;\n /** Array of scatter series */\n series: ScatterSeries[];\n /** Height of the chart in pixels. Defaults to `320`. */\n height?: number;\n /** Label for the x-axis */\n xAxisName?: string;\n /** Label for the y-axis */\n yAxisName?: string;\n /** Custom formatter for x-axis tick labels */\n xAxisTickFormat?: (value: number) => string;\n /** Custom formatter for y-axis tick labels */\n yAxisTickFormat?: (value: number) => string;\n /** When `true`, switches ECharts to its built-in dark theme */\n isDarkMode?: boolean;\n /** When `true`, hides the chart and displays a neutral skeleton placeholder */\n loading?: boolean;\n /** Additional CSS classes applied to the chart container */\n className?: string;\n}\n\n/**\n * ScatterChart — multi-series scatter/point cloud for correlation visualisations.\n *\n * @example\n * ```tsx\n * <ScatterChart\n * echarts={echarts}\n * series={[\n * { name: \"Group A\", data: [[1, 2], [2, 3], [3, 4]] },\n * { name: \"Group B\", data: [[1.5, 4], [2.5, 5]] },\n * ]}\n * xAxisName=\"Cost\"\n * yAxisName=\"Value\"\n * />\n * ```\n */\nexport function ScatterChart({\n echarts,\n series,\n height = 320,\n xAxisName,\n yAxisName,\n xAxisTickFormat,\n yAxisTickFormat,\n isDarkMode,\n loading,\n className,\n}: ScatterChartProps) {\n const options = useMemo<EChartsOption>(() => {\n const palette = isDarkMode ? CHART_DARK_COLORS : CHART_LIGHT_COLORS;\n\n return {\n grid: { left: 40, right: 16, top: 24, bottom: 40, containLabel: true },\n legend: series.length > 1 ? { bottom: 0 } : undefined,\n tooltip: { trigger: \"item\" },\n xAxis: {\n ...ChartPalette.axisDefaults(isDarkMode),\n type: \"value\",\n name: xAxisName,\n axisLabel: xAxisTickFormat\n ? { formatter: (v: number) => xAxisTickFormat(v) }\n : undefined,\n },\n yAxis: {\n ...ChartPalette.axisDefaults(isDarkMode),\n type: \"value\",\n name: yAxisName,\n axisLabel: yAxisTickFormat\n ? { formatter: (v: number) => yAxisTickFormat(v) }\n : undefined,\n },\n series: series.map((s, i) => ({\n name: s.name,\n type: \"scatter\" as const,\n data: s.data,\n symbolSize: s.symbolSize ?? 8,\n itemStyle: { color: s.color ?? palette[i % palette.length] },\n })),\n };\n }, [\n series,\n xAxisName,\n yAxisName,\n xAxisTickFormat,\n yAxisTickFormat,\n isDarkMode,\n ]);\n\n if (loading) {\n return (\n <div aria-busy=\"true\" className={className} style={{ height }}>\n <div className=\"h-full w-full animate-pulse rounded-md bg-sf-fill\" />\n </div>\n );\n }\n\n return (\n <Chart\n echarts={echarts}\n options={options}\n height={height}\n isDarkMode={isDarkMode}\n className={className}\n />\n );\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA2HA,SAAgB,gBAAgB,EAC9B,SACA,OAAO,QACP,MACA,WACA,gBACA,iBACA,iBACA,sBACA,WACA,gBACA,oBACA,mBACA,SAAS,KACT,YACA,YACA,UACA,SACA,mBACuB;CACvB,MAAM,WAAW,OAA+B,IAAI;CACpD,MAAM,mBAAmB,YAAY;CACrC,MAAM,kBAAkB,YAAY;CAEpC,MAAM,UAAU,cAAc;EAC5B,MAAM,kBAA6D,CAAC;EAEpE,MAAM,aACJ,SAAS,QACJ;GAAE,MAAM;GAAO,OAAO;EAAQ,IAC9B;GAAE,MAAM;GAAQ,YAAY;EAAM;EAEzC,KAAK,MAAM,KAAK,MAAM;GACpB,MAAM,yBACJ,oBAAoB,SAAS,SACzB,EAAE,KAAK,QAAQ,UAAU,MAAM,MAAM,gBAAgB,IACrD,CAAC;GAEP,MAAM,wBACJ,mBAAmB,SAAS,SACxB,EAAE,KAAK,QAAQ,UAAU,MAAM,MAAM,eAAe,IACpD,CAAC;GAEP,MAAM,iBACJ,uBAAuB,SAAS,KAAK,sBAAsB,SAAS,IAChE,EAAE,KAAK,MACL,KAAK,IAAI,GAAG,uBAAuB,SAAS,CAAC,GAC7C,KAAK,IAAI,GAAG,EAAE,KAAK,SAAS,sBAAsB,SAAS,CAAC,CAC9D,IACA,EAAE;GAGR,MAAM,YACJ,YAAY,SAAS,SACjB,EACE,OAAO,IAAI,QAAQ,QAAQ,eAAe,GAAG,GAAG,GAAG,GAAG,CACpD;IAAE,QAAQ;IAAG,OAAO,iBAAiB,EAAE,OAAO,EAAG;GAAE,GACnD;IAAE,QAAQ;IAAG,OAAO,iBAAiB,EAAE,OAAO,CAAC;GAAE,CACnD,CAAC,EACH,IACA,KAAA;GAEN,gBAAgB,KAAK;IACnB,MAAM;IACN,OAAO,EAAE;IACT,MAAM,EAAE;IACR,UAAU,EAAE,OAAO,SAAS;IAC5B,GAAI,YAAY,EAAE,UAAU,IAAI,CAAC;IACjC,GAAG;GACL,CAAC;GAGD,MAAM,yBAAyB;IAC7B,OAAO,EAAE;IACT,MAAM,EAAE;IACR,MAAM;IACN,WAAW,EAAE,MAAM,SAAkB;IACrC,YAAY;IACZ,UAAU,EAAE,OAAO,SAAkB;GACvC;GAEA,IAAI,uBAAuB,SAAS,GAClC,gBAAgB,KAAK;IACnB,GAAG;IACH,MAAM;GACR,CAAC;GAGH,IAAI,sBAAsB,SAAS,GACjC,gBAAgB,KAAK;IACnB,GAAG;IACH,MAAM;GACR,CAAC;EAEL;EAEA,OAAO;GACL,MAAM;IACJ,SAAS;IACT,GAAI,mBAAmB,EAAE,OAAO,EAAE,aAAa,gBAAgB,EAAE;GACnE;GACA,OAAO;IACL,YAAY;IACZ,YAAY;IACZ,WAAW;IACX,WAAW;IACX,YAAY,EACV,YAAY,GACd;IACA,YAAY;KACV,aAAa;KACb,OAAO;KACP,aAAa;IACf;GACF;GACA,SAAS;IACP,SAAS;IACT,aAAa,EAAE,MAAM,SAAkB;IACvC,YAAY,WAAgB;KAC1B,MAAM,QAAQ,MAAM,QAAQ,MAAM,IAAI,SAAS,CAAC,MAAM;KAKtD,MAAM,4BAAY,IAAI,IAAY;KAClC,MAAM,iBAAiB,MAAM,QAAQ,UAAe;MAClD,IAAI,UAAU,IAAI,MAAM,UAAU,GAAG,OAAO;MAC5C,UAAU,IAAI,MAAM,UAAU;MAC9B,OAAO;KACT,CAAC;KAED,MAAM,QAAQ,eAAe;KAC7B,MAAM,KAAK,OAAO,QAAQ,MAAM,OAAO;KAcvC,OAAO,GAZL,MAAM,OACF,KACA,mDAAmD,gBAAgB,EAAE,EAAE,UAEhE,eACV,KAAK,UAAe;MACnB,MAAM,QAAQ,OAAO,QAAQ;MAC7B,MAAM,WAAW,sBAAsB;MACvC,OAAO,GAAG,MAAM,OAAO,GAAG,MAAM,WAAW,YAAY,WAAW,SAAS,KAAK,IAAI,MAAM;KAC5F,CAAC,EACA,KAAK,OAEW;IACrB;GACF;GACA,iBAAiB;GACjB,SAAS,EAAE,MAAM,MAAM;GACvB,OAAO;IACL,MAAM;IACN,cAAc;IACd,SAAS;IACT,MAAM;IACN,WAAW;KACT,MAAM;KACN,WAAW;MACT,OAAO,aAAa,SAAS,UAAU;MACvC,MAAM;MACN,OAAO;KACT;IACF;IACA,UAAU,EAAE,MAAM,MAAM;IACxB,aAAa,kBAAkB;IAC/B,GAAI,mBAAmB,EACrB,WAAW,EACT,YAAY,UAAkB,gBAAgB,KAAK,EACrD,EACF;GACF;GACA,OAAO;IACL,MAAM;IACN,cAAc;IACd,SAAS;IACT,MAAM;IACN,UAAU,EAAE,MAAM,MAAM;IACxB,UAAU,EAAE,MAAM,MAAM;IACxB,WAAW;KACT,QAAQ;KACR,GAAI,mBAAmB,EACrB,YAAY,UAAkB,gBAAgB,KAAK,EACrD;IACF;IACA,WAAW;KACT,MAAM;KACN,WAAW;MACT,OAAO,aAAa,SAAS,UAAU;MACvC,MAAM;MACN,OAAO;KACT;IACF;IACA,aAAa;GACf;GACA,MAAM;IACJ,MAAM,YAAY,KAAK;IACvB,OAAO;IACP,KAAK;IACL,QAAQ,YAAY,KAAK;GAC3B;GACA,QAAQ;EACV;CACF,GAAG;EACD;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;CACF,CAAC;CAED,MAAM,SAAS,cAAoC;EACjD,IAAI,CAAC,mBAAmB,OAAO,CAAC;EAEhC,OAAO,EACL,WAAW,WAAW;GACpB,MAAM,QAAQ,OAAO,MAAM,GAAG;GAC9B,kBAAkB,MAAM,IAAI,MAAM,EAAE;GACpC,SAAS,SAAS,eAAe;IAAE,MAAM;IAAS,OAAO,CAAC;GAAE,CAAC;EAC/D,EACF;CACF,GAAG,CAAC,iBAAiB,CAAC;CAItB,MAAM,uBAAuB,CAAC,CAAC;CAC/B,gBAAgB;EACd,MAAM,QAAQ,SAAS;EACvB,IAAI,SAAS,sBAAsB;GACjC,MAAM,eAAe;IACnB,MAAM;IACN,KAAK;IACL,aAAa;KACX,WAAW;KACX,WAAW;IACb;GACF,CAAC;GAED,aAAa;IACX,MAAM,eAAe;KACnB,MAAM;KACN,KAAK;KACL,aAAa,EACX,WAAW,MACb;IACF,CAAC;GACH;EACF;CAIF,GAAG;EAAC;EAAU;EAAsB;CAAO,CAAC;CAE5C,OACE,qBAAC,OAAD;EAAK,WAAU;EAAkB,OAAO,EAAE,OAAO;YAAjD,CACG,WAAW,oBAAC,iBAAD;GAAyB;GAAoB;EAAa,CAAA,GACrE,CAAC,WACA,oBAAC,OAAD;GACW;GACT,KAAK;GACI;GACD;GACI;GACZ,UAAU;EACX,CAAA,CAEA;;AAET;;;;;;AAOA,SAAS,gBAAgB,EACvB,QACA,cAIC;CACD,MAAM,MAAM,SAAS;CACrB,MAAM,MAAM,KAAK,IAAI,SAAS,KAAM,EAAE;CACtC,MAAM,SAAS;CACf,MAAM,QAAQ;CAEd,MAAM,SAAmB,CAAC;CAC1B,KAAK,IAAI,IAAI,GAAG,KAAK,OAAO,KAAK;EAC/B,MAAM,IAAI,OAAW,IAAI,QAAS,SAAS;EAC3C,MAAM,IAAI,MAAM,KAAK,IAAK,IAAI,QAAS,IAAI,KAAK,KAAK,CAAC,IAAI;EAC1D,OAAO,KAAK,GAAG,MAAM,IAAI,MAAM,MAAM,EAAE,QAAQ,CAAC,EAAE,GAAG,EAAE,QAAQ,CAAC,GAAG;CACrE;CACA,MAAM,IAAI,OAAO,KAAK,GAAG;CAEzB,MAAM,cAAc,aAAa,0BAA0B;CAE3D,OACE,qBAAC,OAAD;EACE,eAAY;EACZ,WAAU;EACV,OAAO,EAAE,OAAO;YAHlB,CAKE,oBAAC,SAAD,EAAA,UAAQ,iFAAiF,OAAO,OAAc,CAAA,GAC9G,oBAAC,OAAD;GACE,OAAM;GACE;GACR,SAAS,OAAO,OAAO,GAAG;GAC1B,qBAAoB;GACpB,WAAU;aAEV,oBAAC,QAAD;IACK;IACH,MAAK;IACL,QAAQ;IACR,aAAY;IACZ,OAAO;KACL,WAAW;KACX,iBAAiB;IACnB;GACD,CAAA;EACE,CAAA,CACF;;AAET;;;;;;;;;;;;AAaA,SAAS,iBAAiB,OAAe,OAAuB;CAC9D,MAAM,IAAI,KAAK,IAAI,GAAG,KAAK,IAAI,GAAG,KAAK,CAAC;CAGxC,MAAM,WAAW,qDAAqD,KACpE,KACF;CACA,IAAI,UACF,OAAO,QAAQ,SAAS,GAAG,IAAI,SAAS,GAAG,IAAI,SAAS,GAAG,IAAI,EAAE;CAInE,IAAI,MAAM,MAAM,QAAQ,OAAO,EAAE;CAGjC,IAAI,IAAI,WAAW,GACjB,MAAM,IAAI,KAAK,IAAI,KAAK,IAAI,KAAK,IAAI,KAAK,IAAI,KAAK,IAAI;CAIzD,IAAI,IAAI,WAAW,GACjB,MAAM,IAAI,MAAM,GAAG,CAAC;CAOtB,OAAO,QAJG,OAAO,SAAS,IAAI,MAAM,GAAG,CAAC,GAAG,EAI5B,EAAE,IAHP,OAAO,SAAS,IAAI,MAAM,GAAG,CAAC,GAAG,EAGtB,EAAE,IAFb,OAAO,SAAS,IAAI,MAAM,GAAG,CAAC,GAAG,EAEhB,EAAE,IAAI,EAAE;AACrC;;AAGA,SAAS,IAAI,GAAW;CACtB,OAAO,EAAE,SAAS,EAAE,SAAS,GAAG,GAAG;AACrC;;;;;AAMA,SAAS,gBAAgB,IAAoC;CAC3D,MAAM,IAAI,IAAI,KAAK,EAAE;CACrB,OAAO,GAAG,EAAE,YAAY,EAAE,GAAG,IAAI,EAAE,SAAS,IAAI,CAAC,EAAE,GAAG,IAAI,EAAE,QAAQ,CAAC,EAAE,GAAG,IAAI,EAAE,SAAS,CAAC,EAAE,GAAG,IAAI,EAAE,WAAW,CAAC,EAAE,GAAG,IAAI,EAAE,WAAW,CAAC;AAC1I;;;;;;;;AC5eA,SAAS,UAAU,EAAE,OAAO,OAAO,MAAM,MAAM,YAA6B;CAC1E,OACE,qBAAC,OAAD;EAAK,WAAU;YAAf,CACE,qBAAC,OAAD;GAAK,WAAU;aAAf,CACE,oBAAC,QAAD;IACE,WAAW,GAAG,oCAAoC,EAChD,cAAc,SAChB,CAAC;IACD,OAAO,EAAE,iBAAiB,MAAM;GACjC,CAAA,GACD,oBAAC,QAAD;IAAM,WAAW,GAAG,WAAW,EAAE,cAAc,SAAS,CAAC;cACtD;GACG,CAAA,CACH;MACL,qBAAC,OAAD;GAAK,WAAU;aAAf,CACE,oBAAC,QAAD;IACE,WAAW,GAAG,oCAAoC,EAChD,cAAc,SAChB,CAAC;cAEA;GACG,CAAA,GACL,QACC,oBAAC,QAAD;IACE,WAAW,GAAG,uCAAuC,EACnD,cAAc,SAChB,CAAC;cAEA;GACG,CAAA,CAEL;IACF;;AAET;;;;;AAMA,SAAS,UAAU,EAAE,OAAO,OAAO,MAAM,YAA6B;CACpE,OACE,qBAAC,OAAD;EAAK,WAAU;YAAf;GACE,oBAAC,QAAD;IACE,WAAW,GAAG,oCAAoC,EAChD,cAAc,SAChB,CAAC;IACD,OAAO,EAAE,iBAAiB,MAAM;GACjC,CAAA;GACD,oBAAC,QAAD;IAAM,WAAW,GAAG,WAAW,EAAE,cAAc,SAAS,CAAC;cAAI;GAAW,CAAA;GACxE,oBAAC,QAAD;IAAM,WAAW,GAAG,uBAAuB,EAAE,cAAc,SAAS,CAAC;cAClE;GACG,CAAA;EACH;;AAET;;;;;;;;;;;;;AAcA,IAAa,cAAc;CACzB;CACA;AACF;;;;;;;;;;;;;;;;;;;;;AC3BA,SAAgB,SAAS,EACvB,SACA,MACA,cAAc,YACd,SAAS,KACT,iBACA,oBACA,YACA,SACA,YACA,aACgB;CAChB,MAAM,UAAU,cAA6B;EAC3C,MAAM,UAAU,aAAa,oBAAoB;EACjD,MAAM,OAAO,aAAa,aAAa,UAAU;EACjD,MAAM,eAAe;GACnB,GAAG;GACH,MAAM;GACN,MAAM,KAAK,KAAK,MAAM,EAAE,IAAI;EAC9B;EACA,MAAM,YAAY;GAChB,GAAG;GACH,MAAM;GACN,WAAW,kBACP,EAAE,YAAY,MAAc,gBAAgB,CAAC,EAAE,IAC/C,KAAA;EACN;EAEA,OAAO;GACL,MAAM;IAAE,MAAM;IAAI,OAAO;IAAI,KAAK;IAAI,QAAQ;IAAI,cAAc;GAAK;GACrE,SAAS;IACP,SAAS;IACT,aAAa,EAAE,MAAM,SAAS;IAC9B,gBAAgB,sBACX,UACC,OAAO,UAAU,WACb,mBAAmB,KAAK,IACxB,OAAO,KAAK,IAClB,KAAA;GACN;GACA,OAAO,gBAAgB,aAAa,eAAe;GACnD,OAAO,gBAAgB,aAAa,YAAY;GAChD,QAAQ,CACN;IACE,MAAM;IACN,MAAM,KAAK,KAAK,GAAG,OAAO;KACxB,OAAO,EAAE;KACT,WAAW,EAAE,OAAO,EAAE,SAAS,QAAQ,IAAI,QAAQ,QAAQ;IAC7D,EAAE;GACJ,CACF;EACF;CACF,GAAG;EAAC;EAAM;EAAa;EAAiB;EAAoB;CAAU,CAAC;CAEvE,MAAM,WAAW,cAEb,aACI,EACE,QAAQ,WAA8B;EACpC,IAAI,OAAO,MAAM,WAAW,OAAO,IAAI;CACzC,EACF,IACA,KAAA,GACN,CAAC,UAAU,CACb;CAEA,IAAI,SACF,OACE,oBAAC,OAAD;EACE,aAAU;EACC;EACX,OAAO,EAAE,OAAO;EAChB,oBAAiB;YAEjB,oBAAC,OAAD,EAAK,WAAU,oDAAqD,CAAA;CACjE,CAAA;CAIT,OACE,oBAAC,OAAD;EACW;EACA;EACD;EACI;EACD;EACD;CACX,CAAA;AAEL;;;;;;;;;;;;;;;;;;AC1FA,SAAgB,gBAAgB,EAC9B,SACA,YACA,QACA,cAAc,YACd,UAAU,OACV,SAAS,KACT,iBACA,oBACA,YACA,SACA,aACuB;CACvB,MAAM,UAAU,cAA6B;EAC3C,MAAM,UAAU,aAAa,oBAAoB;EAGjD,MAAM,iBAAiB,UACnB,OAAO,KAAK,OAAO;GACjB,GAAG;GACH,MAAM,EAAE,KAAK,KAAK,GAAG,MAAM;IACzB,MAAM,QAAQ,OAAO,QAClB,KAAK,UAAU,OAAO,MAAM,KAAK,MAAM,IACxC,CACF;IACA,OAAO,UAAU,IAAI,IAAK,IAAI,QAAS;GACzC,CAAC;EACH,EAAE,IACF;EAEJ,MAAM,OAAO,aAAa,aAAa,UAAU;EACjD,MAAM,eAAe;GACnB,GAAG;GACH,MAAM;GACN,MAAM;EACR;EACA,MAAM,YAAY;GAChB,GAAG;GACH,MAAM;GACN,KAAK,UAAU,MAAM,KAAA;GACrB,WAAW,kBACP,EAAE,YAAY,MAAc,gBAAgB,CAAC,EAAE,IAC/C,UACE,EAAE,WAAW,WAAW,IACxB,KAAA;EACR;EAEA,OAAO;GACL,QAAQ,EAAE,QAAQ,EAAE;GACpB,MAAM;IAAE,MAAM;IAAI,OAAO;IAAI,KAAK;IAAI,QAAQ;IAAI,cAAc;GAAK;GACrE,SAAS;IACP,SAAS;IACT,aAAa,EAAE,MAAM,SAAS;IAC9B,gBAAgB,sBACX,UACC,OAAO,UAAU,WACb,mBAAmB,KAAK,IACxB,OAAO,KAAK,IAClB,KAAA;GACN;GACA,OAAO,gBAAgB,aAAa,eAAe;GACnD,OAAO,gBAAgB,aAAa,YAAY;GAChD,QAAQ,eAAe,KAAK,GAAG,OAAO;IACpC,MAAM,EAAE;IACR,MAAM;IACN,OAAO;IACP,MAAM,EAAE;IACR,WAAW,EAAE,OAAO,EAAE,SAAS,QAAQ,IAAI,QAAQ,QAAQ;GAC7D,EAAE;EACJ;CACF,GAAG;EACD;EACA;EACA;EACA;EACA;EACA;EACA;CACF,CAAC;CAED,IAAI,SACF,OACE,oBAAC,OAAD;EAAK,aAAU;EAAkB;EAAW,OAAO,EAAE,OAAO;YAC1D,oBAAC,OAAD,EAAK,WAAU,oDAAqD,CAAA;CACjE,CAAA;CAIT,OACE,oBAAC,OAAD;EACW;EACA;EACD;EACI;EACD;CACZ,CAAA;AAEL;;;;;;;;;;;;;;;;;;;;AC3FA,SAAgB,SAAS,EACvB,SACA,MACA,UAAU,OACV,SAAS,KACT,YACA,oBACA,YACA,SACA,YACA,aACgB;CAChB,MAAM,UAAU,cAA6B;EAC3C,MAAM,UAAU,aAAa,oBAAoB;EACjD,OAAO;GACL,QAAQ,aAAa,EAAE,QAAQ,EAAE,IAAI,KAAA;GACrC,SAAS;IACP,SAAS;IACT,gBAAgB,sBACX,UACC,OAAO,UAAU,WACb,mBAAmB,KAAK,IACxB,OAAO,KAAK,IAClB,KAAA;GACN;GACA,QAAQ,CACN;IACE,MAAM;IACN,QAAQ,YAAY,UAAU,CAAC,OAAO,KAAK,IAAI;IAC/C,mBAAmB;IACnB,OAAO;KACL,MAAM,YAAY;KAClB,OAAO,aAAa,YAAY;KAChC,iBAAiB;KACjB,iBAAiB;IACnB;IACA,WAAW;KACT,MAAM,YAAY;KAClB,WAAW,EAAE,OAAO,aAAa,YAAY,UAAU;IACzD;IACA,MAAM,KAAK,KAAK,GAAG,OAAO;KACxB,MAAM,EAAE;KACR,OAAO,EAAE;KACT,WAAW,EAAE,OAAO,EAAE,SAAS,QAAQ,IAAI,QAAQ,QAAQ;IAC7D,EAAE;GACJ,CACF;EACF;CACF,GAAG;EAAC;EAAM;EAAS;EAAY;EAAoB;CAAU,CAAC;CAE9D,IAAI,SACF,OACE,oBAAC,OAAD;EAAK,aAAU;EAAkB;EAAW,OAAO,EAAE,OAAO;YAC1D,oBAAC,OAAD,EAAK,WAAU,sDAAuD,CAAA;CACnE,CAAA;CAIT,OACE,qBAAC,OAAD;EAAK,WAAW,GAAG,YAAY,SAAS;EAAG,OAAO,EAAE,OAAO;YAA3D,CACE,oBAAC,OAAD;GACW;GACA;GACD;GACI;EACb,CAAA,GACA,eAAe,KAAA,KAAa,YAAY,UACvC,oBAAC,OAAD;GAAK,WAAU;aACZ;EACE,CAAA,IACH,IACD;;AAET;;;;;;;;;;;;;;;;;;;;ACrEA,SAAgB,UAAU,EACxB,SACA,QACA,YAAY,QACZ,YACA,SAAS,KACT,WACA,WACA,iBACA,oBACA,YACA,SACA,SACA,aACiB;CACjB,MAAM,UAAU,cAA6B;EAC3C,MAAM,UAAU,aAAa,oBAAoB;EAEjD,OAAO;GACL,MAAM;IAAE,MAAM;IAAI,OAAO;IAAI,KAAK;IAAI,QAAQ;IAAI,cAAc;GAAK;GACrE,QAAQ,OAAO,SAAS,IAAI,EAAE,QAAQ,EAAE,IAAI,KAAA;GAC5C,SAAS;IACP,SAAS;IACT,gBAAgB,sBACX,UACC,OAAO,UAAU,WACb,mBAAmB,KAAK,IACxB,OAAO,KAAK,IAClB,KAAA;GACN;GACA,OACE,cAAc,aACV;IACE,GAAG,aAAa,aAAa,UAAU;IACvC,MAAM;IACN,MAAM;IACN,MAAM;IACN,aAAa;GACf,IACA;IACE,GAAG,aAAa,aAAa,UAAU;IACvC,MAAM;IACN,MAAM;GACR;GACN,OAAO;IACL,GAAG,aAAa,aAAa,UAAU;IACvC,MAAM;IACN,MAAM;IACN,WAAW,kBACP,EAAE,YAAY,MAAc,gBAAgB,CAAC,EAAE,IAC/C,KAAA;GACN;GACA,QAAQ,OAAO,KAAK,GAAG,MAAM;IAC3B,MAAM,QAAQ,EAAE,SAAS,QAAQ,IAAI,QAAQ;IAC7C,OAAO;KACL,MAAM,EAAE;KACR,MAAM;KACN,QAAQ;KACR,YAAY;KACZ,OAAO,UAAU,UAAU,KAAA;KAC3B,MAAM,EAAE;KACR,WAAW,EAAE,MAAM;KACnB,WAAW,EAAE,MAAM;KACnB,WAAW;MACT,OAAO;OACL,MAAM;OACN,GAAG;OACH,GAAG;OACH,IAAI;OACJ,IAAI;OACJ,YAAY,CACV;QAAE,QAAQ;QAAG;OAAM,GACnB;QAAE,QAAQ;QAAG,OAAO;OAAgB,CACtC;MACF;MACA,SAAS;KACX;IACF;GACF,CAAC;EACH;CACF,GAAG;EACD;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;CACF,CAAC;CAED,IAAI,SACF,OACE,oBAAC,OAAD;EAAK,aAAU;EAAkB;EAAW,OAAO,EAAE,OAAO;YAC1D,oBAAC,OAAD,EAAK,WAAU,oDAAqD,CAAA;CACjE,CAAA;CAIT,OACE,oBAAC,OAAD;EACW;EACA;EACD;EACI;EACD;CACZ,CAAA;AAEL;;;;;;;;;;;;;;;;;;;ACzHA,SAAgB,aAAa,EAC3B,SACA,QACA,SAAS,KACT,WACA,WACA,iBACA,iBACA,YACA,SACA,aACoB;CACpB,MAAM,UAAU,cAA6B;EAC3C,MAAM,UAAU,aAAa,oBAAoB;EAEjD,OAAO;GACL,MAAM;IAAE,MAAM;IAAI,OAAO;IAAI,KAAK;IAAI,QAAQ;IAAI,cAAc;GAAK;GACrE,QAAQ,OAAO,SAAS,IAAI,EAAE,QAAQ,EAAE,IAAI,KAAA;GAC5C,SAAS,EAAE,SAAS,OAAO;GAC3B,OAAO;IACL,GAAG,aAAa,aAAa,UAAU;IACvC,MAAM;IACN,MAAM;IACN,WAAW,kBACP,EAAE,YAAY,MAAc,gBAAgB,CAAC,EAAE,IAC/C,KAAA;GACN;GACA,OAAO;IACL,GAAG,aAAa,aAAa,UAAU;IACvC,MAAM;IACN,MAAM;IACN,WAAW,kBACP,EAAE,YAAY,MAAc,gBAAgB,CAAC,EAAE,IAC/C,KAAA;GACN;GACA,QAAQ,OAAO,KAAK,GAAG,OAAO;IAC5B,MAAM,EAAE;IACR,MAAM;IACN,MAAM,EAAE;IACR,YAAY,EAAE,cAAc;IAC5B,WAAW,EAAE,OAAO,EAAE,SAAS,QAAQ,IAAI,QAAQ,QAAQ;GAC7D,EAAE;EACJ;CACF,GAAG;EACD;EACA;EACA;EACA;EACA;EACA;CACF,CAAC;CAED,IAAI,SACF,OACE,oBAAC,OAAD;EAAK,aAAU;EAAkB;EAAW,OAAO,EAAE,OAAO;YAC1D,oBAAC,OAAD,EAAK,WAAU,oDAAqD,CAAA;CACjE,CAAA;CAIT,OACE,oBAAC,OAAD;EACW;EACA;EACD;EACI;EACD;CACZ,CAAA;AAEL"}
@@ -1,6 +1,6 @@
1
1
  "use client";
2
- import { t as cn } from "./cn-YROP2_ox.js";
3
- import { t as Label } from "./label-DUv_urO1.js";
2
+ import { t as cn } from "./cn-CmAOpn49.js";
3
+ import { t as Label } from "./label-CiGZ464N.js";
4
4
  import { createContext, forwardRef, useContext } from "react";
5
5
  import { jsx, jsxs } from "react/jsx-runtime";
6
6
  import { CheckIcon, MinusIcon } from "@phosphor-icons/react";
@@ -150,4 +150,4 @@ Checkbox$1.displayName = "Checkbox";
150
150
  //#endregion
151
151
  export { SF_CHECKBOX_DEFAULT_VARIANTS as n, SF_CHECKBOX_VARIANTS as r, Checkbox$1 as t };
152
152
 
153
- //# sourceMappingURL=checkbox-D7p4QKsC.js.map
153
+ //# sourceMappingURL=checkbox-Cy_OCyay.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"checkbox-D7p4QKsC.js","names":[],"sources":["../src/components/checkbox/checkbox.tsx"],"sourcesContent":["import {\n Checkbox as BaseCheckbox,\n type CheckboxRootChangeEventDetails,\n} from \"@base-ui/react/checkbox\";\nimport { CheckboxGroup as BaseCheckboxGroup } from \"@base-ui/react/checkbox-group\";\nimport { Field as FieldBase } from \"@base-ui/react/field\";\nimport { Fieldset } from \"@base-ui/react/fieldset\";\nimport { CheckIcon, MinusIcon } from \"@phosphor-icons/react\";\nimport { forwardRef, createContext, useContext, type ReactNode } from \"react\";\n\nimport { cn } from \"../../utils/cn\";\nimport { Label } from \"../label\";\n\n/** Checkbox variant definitions mapping variant names to their Tailwind classes. */\nexport const SF_CHECKBOX_VARIANTS = {\n variant: {\n default: {\n classes: \"[&:focus-within>span]:ring-sf-ring [&:hover>span]:ring-sf-ring\",\n description: \"Default checkbox appearance\",\n },\n error: {\n classes: \"[&>span]:ring-sf-danger\",\n description: \"Error state for validation failures\",\n },\n },\n} as const;\n\nexport const SF_CHECKBOX_DEFAULT_VARIANTS = {\n variant: \"default\",\n} as const;\n\n// Derived types from SF_CHECKBOX_VARIANTS\nexport type SFCheckboxVariant = keyof typeof SF_CHECKBOX_VARIANTS.variant;\n\nexport interface SFCheckboxVariantsProps {\n /**\n * Visual variant.\n * - `\"default\"` — Standard checkbox appearance\n * - `\"error\"` — Error state for validation failures\n * @default \"default\"\n */\n variant?: SFCheckboxVariant;\n}\n\nexport function checkboxVariants({\n variant = SF_CHECKBOX_DEFAULT_VARIANTS.variant,\n}: SFCheckboxVariantsProps = {}) {\n return cn(SF_CHECKBOX_VARIANTS.variant[variant].classes);\n}\n\n// Legacy type alias for backwards compatibility\nexport type CheckboxVariant = SFCheckboxVariant;\n\n// Context for passing controlFirst from Group to Items\nconst CheckboxGroupContext = createContext<{ controlFirst: boolean }>({\n controlFirst: true,\n});\n\n/**\n * Single checkbox component props with accessibility guidance.\n *\n * **Accessible Name Required:** Checkbox should have one of:\n * 1. `label` prop (recommended) - built-in Field wrapper with horizontal layout\n * 2. `aria-label` - for checkboxes without visible label\n * 3. `aria-labelledby` - for custom label association\n *\n * **Note:** When used inside Checkbox.Group or Dropdown, label is optional (parent provides context).\n *\n * Missing accessible names will trigger console warnings in development (unless inside a group).\n *\n * @example\n * // Recommended: Built-in Field wrapper with label\n * <Checkbox label=\"Accept terms and conditions\" />\n *\n * @example\n * // Control-first layout (checkbox before label)\n * <Checkbox label=\"Remember me\" controlFirst={true} />\n *\n * @example\n * // Label-first layout (label before checkbox)\n * <Checkbox label=\"Enable notifications\" controlFirst={false} />\n *\n * @example\n * // Error variant (visual only, no error text for single checkboxes)\n * <Checkbox label=\"Required field\" variant=\"error\" />\n *\n * @example\n * // Without visible label (aria-label required)\n * <Checkbox aria-label=\"Select all items\" />\n *\n * @example\n * // Custom label association\n * <label id=\"terms-label\">I accept the terms</label>\n * <Checkbox aria-labelledby=\"terms-label\" />\n *\n * @example\n * // Inside Checkbox.Group (label optional)\n * <Checkbox.Group legend=\"Preferences\">\n * <Checkbox.Item value=\"email\" label=\"Email notifications\" />\n * <Checkbox.Item value=\"sms\" label=\"SMS notifications\" />\n * </Checkbox.Group>\n */\nexport type CheckboxProps = {\n /** Visual variant: \"default\" or \"error\" for validation failures (visual only, no error text) */\n variant?: CheckboxVariant;\n /** Label content for the checkbox (enables built-in Field wrapper) - can be a string or any React node */\n label?: ReactNode;\n /** Tooltip content to display next to the label via an info icon */\n labelTooltip?: ReactNode;\n /** When true (default), checkbox appears before label. When false, label appears before checkbox. */\n controlFirst?: boolean;\n /** Whether the checkbox is checked (controlled) */\n checked?: boolean;\n /** Whether the checkbox is in indeterminate state */\n indeterminate?: boolean;\n /** Whether the checkbox is disabled */\n disabled?: boolean;\n /** Callback when the checked state changes */\n onCheckedChange?: (checked: boolean) => void;\n /** @deprecated Use onCheckedChange instead */\n onValueChange?: (checked: boolean) => void;\n /** @deprecated Use onCheckedChange instead */\n onChange?: (event: React.ChangeEvent<HTMLInputElement>) => void;\n /** Click handler */\n onClick?: (event: React.MouseEvent) => void;\n /** Name for form submission */\n name?: string;\n /** Whether the field is required */\n required?: boolean;\n /** Additional class name */\n className?: string;\n /** Accessible label when no visible label is provided */\n \"aria-label\"?: string;\n /** ID of element that labels this checkbox */\n \"aria-labelledby\"?: string;\n};\n\n/**\n * Checkbox group component props (with built-in Fieldset and CheckboxGroup)\n *\n * Usage:\n * ```tsx\n * <Checkbox.Group\n * legend=\"Choose preferences\"\n * defaultValue={['email']}\n * error=\"You must select at least one option\"\n * >\n * <Checkbox.Item label=\"Email notifications\" value=\"email\" />\n * <Checkbox.Item label=\"SMS notifications\" value=\"sms\" />\n * </Checkbox.Group>\n * ```\n */\nexport interface CheckboxGroupProps {\n /** Legend text for the group */\n legend: string;\n /** Child Checkbox.Item components */\n children: ReactNode;\n /** Error message for the group (only appears in groups, not single checkboxes) */\n error?: string;\n /** Helper text for the group */\n description?: ReactNode;\n /** Values of checkboxes that should be initially checked (uncontrolled) */\n defaultValue?: string[];\n /** Values of checkboxes that should be checked (controlled) */\n value?: string[];\n /** Event handler called when checkbox values change */\n onValueChange?: (value: string[]) => void;\n /** All possible checkbox values (required for parent checkbox pattern) */\n allValues?: string[];\n /** Whether all checkboxes in the group are disabled */\n disabled?: boolean;\n /** When true (default), checkbox appears before label. When false, label appears before checkbox. */\n controlFirst?: boolean;\n /** Additional CSS classes */\n className?: string;\n}\n\n/**\n * Individual checkbox item within a group\n */\nexport type CheckboxItemProps = {\n /** Visual variant: \"default\" or \"error\" for validation failures */\n variant?: CheckboxVariant;\n /** Label text displayed next to checkbox */\n label: string;\n /** Value of the checkbox (required when used in Checkbox.Group) */\n value?: string;\n /** Additional CSS classes for the label wrapper */\n className?: string;\n checked?: boolean;\n indeterminate?: boolean;\n disabled?: boolean;\n /** Callback when the checked state changes */\n onCheckedChange?: (checked: boolean) => void;\n /** @deprecated Use onCheckedChange instead */\n onValueChange?: (checked: boolean) => void;\n name?: string;\n};\n\n// Single checkbox with built-in Field\nconst CheckboxBase = forwardRef<HTMLButtonElement, CheckboxProps>(\n (\n {\n className,\n checked,\n indeterminate,\n disabled,\n variant = \"default\",\n label,\n labelTooltip,\n controlFirst = true,\n onCheckedChange,\n onValueChange,\n onChange,\n required,\n name,\n ...props\n },\n ref\n ) => {\n // A11y enforcement: warn in dev if no accessible name provided\n if (process.env.NODE_ENV !== \"production\") {\n const hasLabel = Boolean(label);\n const hasAriaLabel = Boolean(props[\"aria-label\"]);\n const hasAriaLabelledBy = Boolean(props[\"aria-labelledby\"]);\n\n if (!hasLabel && !hasAriaLabel && !hasAriaLabelledBy) {\n console.warn(\n \"[SignalFlare Checkbox]: Checkbox must have an accessible name. Provide either:\\n\" +\n \" - label prop: <Checkbox label='Accept terms' />\\n\" +\n \" - aria-label: <Checkbox aria-label='Select item' />\\n\" +\n \" - aria-labelledby for custom label association\\n\" +\n \" Note: When used inside Checkbox.Group, label is optional\"\n );\n }\n }\n\n // Handle onCheckedChange (preferred) and deprecated onValueChange/onChange\n const handleCheckedChange = (\n newChecked: boolean,\n eventDetails: CheckboxRootChangeEventDetails\n ) => {\n onCheckedChange?.(newChecked);\n onValueChange?.(newChecked);\n if (onChange) {\n // Backwards compatibility: extend native event with target.checked\n // so existing code using `e.target.checked` continues to work\n const event = Object.assign(eventDetails.event, {\n target: { checked: newChecked },\n });\n onChange(event as never);\n }\n };\n\n const checkboxControl = (\n <BaseCheckbox.Root\n ref={ref}\n name={name}\n checked={checked}\n indeterminate={indeterminate}\n disabled={disabled}\n onCheckedChange={handleCheckedChange}\n className={cn(\n \"flex h-3.5 w-3.5 items-center justify-center rounded-sm border-0 bg-sf-base ring\",\n variant === \"error\" ? \"ring-sf-danger\" : \"ring-sf-interact\",\n !disabled && \"hover:ring-sf-ring focus-visible:ring-sf-ring\",\n \"data-[checked]:bg-sf-contrast data-[checked]:ring-sf-contrast data-[indeterminate]:bg-sf-contrast data-[indeterminate]:ring-sf-contrast\",\n disabled && \"cursor-not-allowed opacity-50\",\n className\n )}\n {...props}\n >\n <BaseCheckbox.Indicator\n className=\"flex items-center justify-center text-sf-inverse\"\n render={(renderProps, state) => {\n const Icon = state.indeterminate ? MinusIcon : CheckIcon;\n return (\n <span {...renderProps}>\n {(state.checked || state.indeterminate) && (\n <Icon weight=\"bold\" size={10} />\n )}\n </span>\n );\n }}\n />\n </BaseCheckbox.Root>\n );\n\n // If no label provided, return bare checkbox (for use in other components like Dropdown)\n if (!label) {\n return checkboxControl;\n }\n\n // Use Field.Root + Field.Label enclosing pattern for proper a11y association\n // See: https://base-ui.com/react/components/field\n return (\n <FieldBase.Root className=\"inline-flex\">\n <FieldBase.Label\n className={cn(\n \"inline-flex items-center gap-2\",\n controlFirst ? \"flex-row\" : \"flex-row-reverse justify-end\",\n disabled ? \"cursor-not-allowed\" : \"cursor-pointer\"\n )}\n >\n {checkboxControl}\n <Label\n showOptional={required === false}\n tooltip={labelTooltip}\n asContent\n >\n {label}\n </Label>\n </FieldBase.Label>\n </FieldBase.Root>\n );\n }\n);\n\nCheckboxBase.displayName = \"Checkbox\";\n\n// Checkbox.Item for use within Checkbox.Group\nconst CheckboxItem = forwardRef<HTMLButtonElement, CheckboxItemProps>(\n (\n {\n className,\n checked,\n indeterminate,\n disabled,\n variant = \"default\",\n label,\n value,\n onCheckedChange,\n onValueChange,\n name,\n },\n ref\n ) => {\n const { controlFirst } = useContext(CheckboxGroupContext);\n\n // Handle onCheckedChange (preferred) and deprecated onValueChange\n const handleCheckedChange = (newChecked: boolean) => {\n onCheckedChange?.(newChecked);\n onValueChange?.(newChecked);\n };\n\n return (\n <label\n className={cn(\n \"relative inline-flex items-center gap-2\",\n // Control first (default): checkbox before label\n // Label first: label before checkbox using flex-row-reverse\n !controlFirst && \"flex-row-reverse justify-end\",\n disabled ? \"cursor-not-allowed opacity-50\" : \"cursor-pointer\",\n className\n )}\n >\n <BaseCheckbox.Root\n ref={ref}\n value={value}\n name={name}\n checked={checked}\n indeterminate={indeterminate}\n disabled={disabled}\n onCheckedChange={handleCheckedChange}\n className={cn(\n \"peer flex h-3.5 w-3.5 items-center justify-center rounded-sm border-0 bg-sf-base ring\",\n variant === \"error\" ? \"ring-sf-danger\" : \"ring-sf-interact\",\n !disabled &&\n \"group-hover:ring-sf-ring hover:ring-sf-ring focus-visible:ring-sf-ring\",\n \"data-[checked]:bg-sf-contrast data-[checked]:ring-sf-contrast data-[indeterminate]:bg-sf-contrast data-[indeterminate]:ring-sf-contrast\"\n )}\n >\n <BaseCheckbox.Indicator\n className=\"flex items-center justify-center text-sf-inverse\"\n render={(props, state) => {\n const Icon = state.indeterminate ? MinusIcon : CheckIcon;\n return (\n <span {...props}>\n {(state.checked || state.indeterminate) && (\n <Icon weight=\"bold\" size={10} />\n )}\n </span>\n );\n }}\n />\n </BaseCheckbox.Root>\n <span className=\"text-base font-medium text-sf-default\">{label}</span>\n </label>\n );\n }\n);\n\nCheckboxItem.displayName = \"Checkbox.Item\";\n\n// Checkbox.Group with built-in Fieldset and CheckboxGroup\nfunction CheckboxGroup({\n legend,\n children,\n error,\n description,\n defaultValue,\n value,\n onValueChange,\n allValues,\n disabled,\n controlFirst = true,\n className,\n}: CheckboxGroupProps) {\n return (\n <CheckboxGroupContext.Provider value={{ controlFirst }}>\n <BaseCheckboxGroup\n defaultValue={defaultValue}\n value={value}\n onValueChange={onValueChange}\n allValues={allValues}\n disabled={disabled}\n >\n <Fieldset.Root\n className={cn(\n \"flex flex-col gap-4 rounded-lg border border-sf-line p-4\",\n className\n )}\n >\n <Fieldset.Legend className=\"text-lg font-medium text-sf-default\">\n {legend}\n </Fieldset.Legend>\n <div className=\"flex flex-col gap-2\">{children}</div>\n {error && <p className=\"text-sm text-sf-danger\">{error}</p>}\n {description && (\n <p className=\"text-sm text-sf-subtle\">{description}</p>\n )}\n </Fieldset.Root>\n </BaseCheckboxGroup>\n </CheckboxGroupContext.Provider>\n );\n}\n\n// Compound component\nexport const Checkbox = Object.assign(CheckboxBase, {\n Item: CheckboxItem,\n Group: CheckboxGroup,\n});\n\nCheckbox.displayName = \"Checkbox\";\n"],"mappings":";;;;;;;;;;;;AAcA,IAAa,uBAAuB,EAClC,SAAS;CACP,SAAS;EACP,SAAS;EACT,aAAa;EACd;CACD,OAAO;EACL,SAAS;EACT,aAAa;EACd;CACF,EACF;AAED,IAAa,+BAA+B,EAC1C,SAAS,WACV;AAyBD,IAAM,uBAAuB,cAAyC,EACpE,cAAc,MACf,CAAC;AAgJF,IAAM,eAAe,YAEjB,EACE,WACA,SACA,eACA,UACA,UAAU,WACV,OACA,cACA,eAAe,MACf,iBACA,eACA,UACA,UACA,MACA,GAAG,SAEL,QACG;AAEH,KAAA,QAAA,IAAA,aAA6B,cAAc;EACzC,MAAM,WAAW,QAAQ,MAAM;EAC/B,MAAM,eAAe,QAAQ,MAAM,cAAc;EACjD,MAAM,oBAAoB,QAAQ,MAAM,mBAAmB;AAE3D,MAAI,CAAC,YAAY,CAAC,gBAAgB,CAAC,kBACjC,SAAQ,KACN,ySAKD;;CAKL,MAAM,uBACJ,YACA,iBACG;AACH,oBAAkB,WAAW;AAC7B,kBAAgB,WAAW;AAC3B,MAAI,SAMF,UAHc,OAAO,OAAO,aAAa,OAAO,EAC9C,QAAQ,EAAE,SAAS,YAAY,EAChC,CAAC,CACsB;;CAI5B,MAAM,kBACJ,oBAAC,SAAa,MAAd;EACO;EACC;EACG;EACM;EACL;EACV,iBAAiB;EACjB,WAAW,GACT,oFACA,YAAY,UAAU,mBAAmB,oBACzC,CAAC,YAAY,iDACb,2IACA,YAAY,iCACZ,UACD;EACD,GAAI;YAEJ,oBAAC,SAAa,WAAd;GACE,WAAU;GACV,SAAS,aAAa,UAAU;IAC9B,MAAM,OAAO,MAAM,gBAAgB,YAAY;AAC/C,WACE,oBAAC,QAAD;KAAM,GAAI;gBACN,MAAM,WAAW,MAAM,kBACvB,oBAAC,MAAD;MAAM,QAAO;MAAO,MAAM;MAAM,CAAA;KAE7B,CAAA;;GAGX,CAAA;EACgB,CAAA;AAItB,KAAI,CAAC,MACH,QAAO;AAKT,QACE,oBAAC,MAAU,MAAX;EAAgB,WAAU;YACxB,qBAAC,MAAU,OAAX;GACE,WAAW,GACT,kCACA,eAAe,aAAa,gCAC5B,WAAW,uBAAuB,iBACnC;aALH,CAOG,iBACD,oBAAC,OAAD;IACE,cAAc,aAAa;IAC3B,SAAS;IACT,WAAA;cAEC;IACK,CAAA,CACQ;;EACH,CAAA;EAGtB;AAED,aAAa,cAAc;AAG3B,IAAM,eAAe,YAEjB,EACE,WACA,SACA,eACA,UACA,UAAU,WACV,OACA,OACA,iBACA,eACA,QAEF,QACG;CACH,MAAM,EAAE,iBAAiB,WAAW,qBAAqB;CAGzD,MAAM,uBAAuB,eAAwB;AACnD,oBAAkB,WAAW;AAC7B,kBAAgB,WAAW;;AAG7B,QACE,qBAAC,SAAD;EACE,WAAW,GACT,2CAGA,CAAC,gBAAgB,gCACjB,WAAW,kCAAkC,kBAC7C,UACD;YARH,CAUE,oBAAC,SAAa,MAAd;GACO;GACE;GACD;GACG;GACM;GACL;GACV,iBAAiB;GACjB,WAAW,GACT,yFACA,YAAY,UAAU,mBAAmB,oBACzC,CAAC,YACC,0EACF,0IACD;aAED,oBAAC,SAAa,WAAd;IACE,WAAU;IACV,SAAS,OAAO,UAAU;KACxB,MAAM,OAAO,MAAM,gBAAgB,YAAY;AAC/C,YACE,oBAAC,QAAD;MAAM,GAAI;iBACN,MAAM,WAAW,MAAM,kBACvB,oBAAC,MAAD;OAAM,QAAO;OAAO,MAAM;OAAM,CAAA;MAE7B,CAAA;;IAGX,CAAA;GACgB,CAAA,EACpB,oBAAC,QAAD;GAAM,WAAU;aAAyC;GAAa,CAAA,CAChE;;EAGb;AAED,aAAa,cAAc;AAG3B,SAAS,gBAAc,EACrB,QACA,UACA,OACA,aACA,cACA,OACA,eACA,WACA,UACA,eAAe,MACf,aACqB;AACrB,QACE,oBAAC,qBAAqB,UAAtB;EAA+B,OAAO,EAAE,cAAc;YACpD,oBAAC,eAAD;GACgB;GACP;GACQ;GACJ;GACD;aAEV,qBAAC,SAAS,MAAV;IACE,WAAW,GACT,4DACA,UACD;cAJH;KAME,oBAAC,SAAS,QAAV;MAAiB,WAAU;gBACxB;MACe,CAAA;KAClB,oBAAC,OAAD;MAAK,WAAU;MAAuB;MAAe,CAAA;KACpD,SAAS,oBAAC,KAAD;MAAG,WAAU;gBAA0B;MAAU,CAAA;KAC1D,eACC,oBAAC,KAAD;MAAG,WAAU;gBAA0B;MAAgB,CAAA;KAE3C;;GACE,CAAA;EACU,CAAA;;AAKpC,IAAa,aAAW,OAAO,OAAO,cAAc;CAClD,MAAM;CACN,OAAO;CACR,CAAC;AAEF,WAAS,cAAc"}
1
+ {"version":3,"file":"checkbox-Cy_OCyay.js","names":[],"sources":["../src/components/checkbox/checkbox.tsx"],"sourcesContent":["import {\n Checkbox as BaseCheckbox,\n type CheckboxRootChangeEventDetails,\n} from \"@base-ui/react/checkbox\";\nimport { CheckboxGroup as BaseCheckboxGroup } from \"@base-ui/react/checkbox-group\";\nimport { Field as FieldBase } from \"@base-ui/react/field\";\nimport { Fieldset } from \"@base-ui/react/fieldset\";\nimport { CheckIcon, MinusIcon } from \"@phosphor-icons/react\";\nimport { forwardRef, createContext, useContext, type ReactNode } from \"react\";\n\nimport { cn } from \"../../utils/cn\";\nimport { Label } from \"../label\";\n\n/** Checkbox variant definitions mapping variant names to their Tailwind classes. */\nexport const SF_CHECKBOX_VARIANTS = {\n variant: {\n default: {\n classes: \"[&:focus-within>span]:ring-sf-ring [&:hover>span]:ring-sf-ring\",\n description: \"Default checkbox appearance\",\n },\n error: {\n classes: \"[&>span]:ring-sf-danger\",\n description: \"Error state for validation failures\",\n },\n },\n} as const;\n\nexport const SF_CHECKBOX_DEFAULT_VARIANTS = {\n variant: \"default\",\n} as const;\n\n// Derived types from SF_CHECKBOX_VARIANTS\nexport type SFCheckboxVariant = keyof typeof SF_CHECKBOX_VARIANTS.variant;\n\nexport interface SFCheckboxVariantsProps {\n /**\n * Visual variant.\n * - `\"default\"` — Standard checkbox appearance\n * - `\"error\"` — Error state for validation failures\n * @default \"default\"\n */\n variant?: SFCheckboxVariant;\n}\n\nexport function checkboxVariants({\n variant = SF_CHECKBOX_DEFAULT_VARIANTS.variant,\n}: SFCheckboxVariantsProps = {}) {\n return cn(SF_CHECKBOX_VARIANTS.variant[variant].classes);\n}\n\n// Legacy type alias for backwards compatibility\nexport type CheckboxVariant = SFCheckboxVariant;\n\n// Context for passing controlFirst from Group to Items\nconst CheckboxGroupContext = createContext<{ controlFirst: boolean }>({\n controlFirst: true,\n});\n\n/**\n * Single checkbox component props with accessibility guidance.\n *\n * **Accessible Name Required:** Checkbox should have one of:\n * 1. `label` prop (recommended) - built-in Field wrapper with horizontal layout\n * 2. `aria-label` - for checkboxes without visible label\n * 3. `aria-labelledby` - for custom label association\n *\n * **Note:** When used inside Checkbox.Group or Dropdown, label is optional (parent provides context).\n *\n * Missing accessible names will trigger console warnings in development (unless inside a group).\n *\n * @example\n * // Recommended: Built-in Field wrapper with label\n * <Checkbox label=\"Accept terms and conditions\" />\n *\n * @example\n * // Control-first layout (checkbox before label)\n * <Checkbox label=\"Remember me\" controlFirst={true} />\n *\n * @example\n * // Label-first layout (label before checkbox)\n * <Checkbox label=\"Enable notifications\" controlFirst={false} />\n *\n * @example\n * // Error variant (visual only, no error text for single checkboxes)\n * <Checkbox label=\"Required field\" variant=\"error\" />\n *\n * @example\n * // Without visible label (aria-label required)\n * <Checkbox aria-label=\"Select all items\" />\n *\n * @example\n * // Custom label association\n * <label id=\"terms-label\">I accept the terms</label>\n * <Checkbox aria-labelledby=\"terms-label\" />\n *\n * @example\n * // Inside Checkbox.Group (label optional)\n * <Checkbox.Group legend=\"Preferences\">\n * <Checkbox.Item value=\"email\" label=\"Email notifications\" />\n * <Checkbox.Item value=\"sms\" label=\"SMS notifications\" />\n * </Checkbox.Group>\n */\nexport type CheckboxProps = {\n /** Visual variant: \"default\" or \"error\" for validation failures (visual only, no error text) */\n variant?: CheckboxVariant;\n /** Label content for the checkbox (enables built-in Field wrapper) - can be a string or any React node */\n label?: ReactNode;\n /** Tooltip content to display next to the label via an info icon */\n labelTooltip?: ReactNode;\n /** When true (default), checkbox appears before label. When false, label appears before checkbox. */\n controlFirst?: boolean;\n /** Whether the checkbox is checked (controlled) */\n checked?: boolean;\n /** Whether the checkbox is in indeterminate state */\n indeterminate?: boolean;\n /** Whether the checkbox is disabled */\n disabled?: boolean;\n /** Callback when the checked state changes */\n onCheckedChange?: (checked: boolean) => void;\n /** @deprecated Use onCheckedChange instead */\n onValueChange?: (checked: boolean) => void;\n /** @deprecated Use onCheckedChange instead */\n onChange?: (event: React.ChangeEvent<HTMLInputElement>) => void;\n /** Click handler */\n onClick?: (event: React.MouseEvent) => void;\n /** Name for form submission */\n name?: string;\n /** Whether the field is required */\n required?: boolean;\n /** Additional class name */\n className?: string;\n /** Accessible label when no visible label is provided */\n \"aria-label\"?: string;\n /** ID of element that labels this checkbox */\n \"aria-labelledby\"?: string;\n};\n\n/**\n * Checkbox group component props (with built-in Fieldset and CheckboxGroup)\n *\n * Usage:\n * ```tsx\n * <Checkbox.Group\n * legend=\"Choose preferences\"\n * defaultValue={['email']}\n * error=\"You must select at least one option\"\n * >\n * <Checkbox.Item label=\"Email notifications\" value=\"email\" />\n * <Checkbox.Item label=\"SMS notifications\" value=\"sms\" />\n * </Checkbox.Group>\n * ```\n */\nexport interface CheckboxGroupProps {\n /** Legend text for the group */\n legend: string;\n /** Child Checkbox.Item components */\n children: ReactNode;\n /** Error message for the group (only appears in groups, not single checkboxes) */\n error?: string;\n /** Helper text for the group */\n description?: ReactNode;\n /** Values of checkboxes that should be initially checked (uncontrolled) */\n defaultValue?: string[];\n /** Values of checkboxes that should be checked (controlled) */\n value?: string[];\n /** Event handler called when checkbox values change */\n onValueChange?: (value: string[]) => void;\n /** All possible checkbox values (required for parent checkbox pattern) */\n allValues?: string[];\n /** Whether all checkboxes in the group are disabled */\n disabled?: boolean;\n /** When true (default), checkbox appears before label. When false, label appears before checkbox. */\n controlFirst?: boolean;\n /** Additional CSS classes */\n className?: string;\n}\n\n/**\n * Individual checkbox item within a group\n */\nexport type CheckboxItemProps = {\n /** Visual variant: \"default\" or \"error\" for validation failures */\n variant?: CheckboxVariant;\n /** Label text displayed next to checkbox */\n label: string;\n /** Value of the checkbox (required when used in Checkbox.Group) */\n value?: string;\n /** Additional CSS classes for the label wrapper */\n className?: string;\n checked?: boolean;\n indeterminate?: boolean;\n disabled?: boolean;\n /** Callback when the checked state changes */\n onCheckedChange?: (checked: boolean) => void;\n /** @deprecated Use onCheckedChange instead */\n onValueChange?: (checked: boolean) => void;\n name?: string;\n};\n\n// Single checkbox with built-in Field\nconst CheckboxBase = forwardRef<HTMLButtonElement, CheckboxProps>(\n (\n {\n className,\n checked,\n indeterminate,\n disabled,\n variant = \"default\",\n label,\n labelTooltip,\n controlFirst = true,\n onCheckedChange,\n onValueChange,\n onChange,\n required,\n name,\n ...props\n },\n ref\n ) => {\n // A11y enforcement: warn in dev if no accessible name provided\n if (process.env.NODE_ENV !== \"production\") {\n const hasLabel = Boolean(label);\n const hasAriaLabel = Boolean(props[\"aria-label\"]);\n const hasAriaLabelledBy = Boolean(props[\"aria-labelledby\"]);\n\n if (!hasLabel && !hasAriaLabel && !hasAriaLabelledBy) {\n console.warn(\n \"[SignalFlare Checkbox]: Checkbox must have an accessible name. Provide either:\\n\" +\n \" - label prop: <Checkbox label='Accept terms' />\\n\" +\n \" - aria-label: <Checkbox aria-label='Select item' />\\n\" +\n \" - aria-labelledby for custom label association\\n\" +\n \" Note: When used inside Checkbox.Group, label is optional\"\n );\n }\n }\n\n // Handle onCheckedChange (preferred) and deprecated onValueChange/onChange\n const handleCheckedChange = (\n newChecked: boolean,\n eventDetails: CheckboxRootChangeEventDetails\n ) => {\n onCheckedChange?.(newChecked);\n onValueChange?.(newChecked);\n if (onChange) {\n // Backwards compatibility: extend native event with target.checked\n // so existing code using `e.target.checked` continues to work\n const event = Object.assign(eventDetails.event, {\n target: { checked: newChecked },\n });\n onChange(event as never);\n }\n };\n\n const checkboxControl = (\n <BaseCheckbox.Root\n ref={ref}\n name={name}\n checked={checked}\n indeterminate={indeterminate}\n disabled={disabled}\n onCheckedChange={handleCheckedChange}\n className={cn(\n \"flex h-3.5 w-3.5 items-center justify-center rounded-sm border-0 bg-sf-base ring\",\n variant === \"error\" ? \"ring-sf-danger\" : \"ring-sf-interact\",\n !disabled && \"hover:ring-sf-ring focus-visible:ring-sf-ring\",\n \"data-[checked]:bg-sf-contrast data-[checked]:ring-sf-contrast data-[indeterminate]:bg-sf-contrast data-[indeterminate]:ring-sf-contrast\",\n disabled && \"cursor-not-allowed opacity-50\",\n className\n )}\n {...props}\n >\n <BaseCheckbox.Indicator\n className=\"flex items-center justify-center text-sf-inverse\"\n render={(renderProps, state) => {\n const Icon = state.indeterminate ? MinusIcon : CheckIcon;\n return (\n <span {...renderProps}>\n {(state.checked || state.indeterminate) && (\n <Icon weight=\"bold\" size={10} />\n )}\n </span>\n );\n }}\n />\n </BaseCheckbox.Root>\n );\n\n // If no label provided, return bare checkbox (for use in other components like Dropdown)\n if (!label) {\n return checkboxControl;\n }\n\n // Use Field.Root + Field.Label enclosing pattern for proper a11y association\n // See: https://base-ui.com/react/components/field\n return (\n <FieldBase.Root className=\"inline-flex\">\n <FieldBase.Label\n className={cn(\n \"inline-flex items-center gap-2\",\n controlFirst ? \"flex-row\" : \"flex-row-reverse justify-end\",\n disabled ? \"cursor-not-allowed\" : \"cursor-pointer\"\n )}\n >\n {checkboxControl}\n <Label\n showOptional={required === false}\n tooltip={labelTooltip}\n asContent\n >\n {label}\n </Label>\n </FieldBase.Label>\n </FieldBase.Root>\n );\n }\n);\n\nCheckboxBase.displayName = \"Checkbox\";\n\n// Checkbox.Item for use within Checkbox.Group\nconst CheckboxItem = forwardRef<HTMLButtonElement, CheckboxItemProps>(\n (\n {\n className,\n checked,\n indeterminate,\n disabled,\n variant = \"default\",\n label,\n value,\n onCheckedChange,\n onValueChange,\n name,\n },\n ref\n ) => {\n const { controlFirst } = useContext(CheckboxGroupContext);\n\n // Handle onCheckedChange (preferred) and deprecated onValueChange\n const handleCheckedChange = (newChecked: boolean) => {\n onCheckedChange?.(newChecked);\n onValueChange?.(newChecked);\n };\n\n return (\n <label\n className={cn(\n \"relative inline-flex items-center gap-2\",\n // Control first (default): checkbox before label\n // Label first: label before checkbox using flex-row-reverse\n !controlFirst && \"flex-row-reverse justify-end\",\n disabled ? \"cursor-not-allowed opacity-50\" : \"cursor-pointer\",\n className\n )}\n >\n <BaseCheckbox.Root\n ref={ref}\n value={value}\n name={name}\n checked={checked}\n indeterminate={indeterminate}\n disabled={disabled}\n onCheckedChange={handleCheckedChange}\n className={cn(\n \"peer flex h-3.5 w-3.5 items-center justify-center rounded-sm border-0 bg-sf-base ring\",\n variant === \"error\" ? \"ring-sf-danger\" : \"ring-sf-interact\",\n !disabled &&\n \"group-hover:ring-sf-ring hover:ring-sf-ring focus-visible:ring-sf-ring\",\n \"data-[checked]:bg-sf-contrast data-[checked]:ring-sf-contrast data-[indeterminate]:bg-sf-contrast data-[indeterminate]:ring-sf-contrast\"\n )}\n >\n <BaseCheckbox.Indicator\n className=\"flex items-center justify-center text-sf-inverse\"\n render={(props, state) => {\n const Icon = state.indeterminate ? MinusIcon : CheckIcon;\n return (\n <span {...props}>\n {(state.checked || state.indeterminate) && (\n <Icon weight=\"bold\" size={10} />\n )}\n </span>\n );\n }}\n />\n </BaseCheckbox.Root>\n <span className=\"text-base font-medium text-sf-default\">{label}</span>\n </label>\n );\n }\n);\n\nCheckboxItem.displayName = \"Checkbox.Item\";\n\n// Checkbox.Group with built-in Fieldset and CheckboxGroup\nfunction CheckboxGroup({\n legend,\n children,\n error,\n description,\n defaultValue,\n value,\n onValueChange,\n allValues,\n disabled,\n controlFirst = true,\n className,\n}: CheckboxGroupProps) {\n return (\n <CheckboxGroupContext.Provider value={{ controlFirst }}>\n <BaseCheckboxGroup\n defaultValue={defaultValue}\n value={value}\n onValueChange={onValueChange}\n allValues={allValues}\n disabled={disabled}\n >\n <Fieldset.Root\n className={cn(\n \"flex flex-col gap-4 rounded-lg border border-sf-line p-4\",\n className\n )}\n >\n <Fieldset.Legend className=\"text-lg font-medium text-sf-default\">\n {legend}\n </Fieldset.Legend>\n <div className=\"flex flex-col gap-2\">{children}</div>\n {error && <p className=\"text-sm text-sf-danger\">{error}</p>}\n {description && (\n <p className=\"text-sm text-sf-subtle\">{description}</p>\n )}\n </Fieldset.Root>\n </BaseCheckboxGroup>\n </CheckboxGroupContext.Provider>\n );\n}\n\n// Compound component\nexport const Checkbox = Object.assign(CheckboxBase, {\n Item: CheckboxItem,\n Group: CheckboxGroup,\n});\n\nCheckbox.displayName = \"Checkbox\";\n"],"mappings":"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"}
@@ -1,7 +1,7 @@
1
1
  "use client";
2
- import { t as cn } from "./cn-YROP2_ox.js";
3
- import { t as Button } from "./button-CO6-qPax.js";
4
- import { r as inputVariants } from "./input-B2bbijRh.js";
2
+ import { t as cn } from "./cn-CmAOpn49.js";
3
+ import { t as Button } from "./button-BHOgXJRU.js";
4
+ import { r as inputVariants } from "./input-GkfMQZC_.js";
5
5
  import { forwardRef, useCallback, useRef, useState } from "react";
6
6
  import { jsx, jsxs } from "react/jsx-runtime";
7
7
  import { Tooltip } from "@base-ui/react/tooltip";
@@ -9,6 +9,7 @@ import { CheckIcon, CopyIcon } from "@phosphor-icons/react";
9
9
  import { Toast } from "@base-ui/react/toast";
10
10
  //#region src/components/clipboard-text/clipboard-text.tsx
11
11
  var clipboardToastManager = Toast.createToastManager();
12
+ var EMPTY_CLIPBOARD_LABELS = {};
12
13
  /** ClipboardText size variant definitions mapping sizes to their Tailwind classes. */
13
14
  var SF_CLIPBOARD_TEXT_VARIANTS = { size: {
14
15
  sm: {
@@ -71,7 +72,7 @@ function TooltipWrapper({ children }) {
71
72
  * <ClipboardText text="0c239dd2" />
72
73
  * ```
73
74
  */
74
- var ClipboardText = forwardRef(({ text, className, size = SF_CLIPBOARD_TEXT_DEFAULT_VARIANTS.size, onCopy, tooltip, labels: { copyAction = "Copy to clipboard" } = {} }, ref) => {
75
+ var ClipboardText = forwardRef(({ text, className, size = SF_CLIPBOARD_TEXT_DEFAULT_VARIANTS.size, onCopy, tooltip, labels: { copyAction = "Copy to clipboard" } = EMPTY_CLIPBOARD_LABELS }, ref) => {
75
76
  const [copied, setCopied] = useState(false);
76
77
  const buttonRef = useRef(null);
77
78
  const sizeConfig = SF_CLIPBOARD_TEXT_VARIANTS.size[size];
@@ -173,4 +174,4 @@ ClipboardText.displayName = "ClipboardText";
173
174
  //#endregion
174
175
  export { ClipboardText as t };
175
176
 
176
- //# sourceMappingURL=clipboard-text-kLaMogs3.js.map
177
+ //# sourceMappingURL=clipboard-text-CKSvNp9L.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"clipboard-text-CKSvNp9L.js","names":[],"sources":["../src/components/clipboard-text/clipboard-text.tsx"],"sourcesContent":["import { Toast } from \"@base-ui/react/toast\";\nimport { Tooltip } from \"@base-ui/react/tooltip\";\nimport { CheckIcon, CopyIcon } from \"@phosphor-icons/react\";\nimport { forwardRef, useCallback, useRef, useState } from \"react\";\n\nimport { cn } from \"../../utils/cn\";\nimport { Button } from \"../button\";\nimport { inputVariants } from \"../input\";\n\n// Create a toast manager for anchored \"Copied\" toasts\nconst clipboardToastManager = Toast.createToastManager();\nconst EMPTY_CLIPBOARD_LABELS: { copyAction?: string } = {};\n\n/** ClipboardText size variant definitions mapping sizes to their Tailwind classes. */\nexport const SF_CLIPBOARD_TEXT_VARIANTS = {\n size: {\n sm: {\n classes: \"text-xs\",\n buttonSize: \"sm\" as const,\n description: \"Small clipboard text for compact UIs\",\n },\n base: {\n classes: \"text-sm\",\n buttonSize: \"base\" as const,\n description: \"Default clipboard text size\",\n },\n lg: {\n classes: \"text-sm\",\n buttonSize: \"lg\" as const,\n description: \"Large clipboard text for prominent display\",\n },\n },\n} as const;\n\nexport const SF_CLIPBOARD_TEXT_DEFAULT_VARIANTS = {\n size: \"lg\",\n} as const;\n\nconst clipboardTextAnimations = {\n slide: {\n initial:\n \"pointer-events-none absolute inset-0 flex items-center justify-center opacity-0 translate-y-full\",\n animate: \"translate-y-0 opacity-100\",\n end: \"pointer-events-none absolute inset-0 flex items-center justify-center opacity-0 -translate-y-full\",\n },\n} as const;\n\n// Derived types from SF_CLIPBOARD_TEXT_VARIANTS\nexport type SFClipboardTextSize = keyof typeof SF_CLIPBOARD_TEXT_VARIANTS.size;\n\nexport interface SFClipboardTextVariantsProps {\n /**\n * Size of the clipboard text field.\n * - `\"sm\"` — Small clipboard text for compact UIs\n * - `\"base\"` — Default clipboard text size\n * - `\"lg\"` — Large clipboard text for prominent display\n * @default \"lg\"\n */\n size?: SFClipboardTextSize;\n}\n\nexport function clipboardTextVariants({\n size = SF_CLIPBOARD_TEXT_DEFAULT_VARIANTS.size,\n}: SFClipboardTextVariantsProps = {}) {\n return cn(\n // Base styles\n \"flex items-center overflow-hidden bg-sf-base px-0 font-mono\",\n // Apply size styles from SF_CLIPBOARD_TEXT_VARIANTS\n SF_CLIPBOARD_TEXT_VARIANTS.size[size].classes\n );\n}\n\n// Legacy type alias for backwards compatibility\nexport type ClipboardTextSize = SFClipboardTextSize;\n\n/**\n * ClipboardText component props.\n *\n * @example\n * ```tsx\n * <ClipboardText text=\"sk_live_abc123\" />\n * <ClipboardText text=\"npm install @signalflare-ai/ui\" size=\"sm\" />\n * ```\n */\nexport interface ClipboardTextProps extends SFClipboardTextVariantsProps {\n /** The text to display and copy to clipboard. */\n text: string;\n /** Additional CSS classes merged via `cn()`. */\n className?: string;\n /** Callback fired after text is copied to clipboard. */\n onCopy?: () => void;\n /**\n * Tooltip config. Shows tooltip on hover, anchored toast on click.\n * @example\n * ```tsx\n * <ClipboardText\n * text=\"abc123\"\n * tooltip={{ text: \"Copy\", copiedText: \"Copied!\", side: \"top\" }}\n * />\n * ```\n */\n tooltip?: {\n /** Text shown in tooltip on hover. @default \"Copy\" */\n text?: string;\n /** Text shown in toast after copying. @default \"Copied\" */\n copiedText?: string;\n /** Tooltip/toast placement. @default \"top\" */\n side?: \"top\" | \"bottom\" | \"left\" | \"right\";\n };\n /** Accessible labels for i18n. */\n labels?: {\n /** @default \"Copy to clipboard\" */\n copyAction?: string;\n };\n}\n\n/**\n * Anchored toasts viewport - renders \"Copied\" toasts anchored to buttons\n */\nfunction AnchoredToasts() {\n const { toasts } = Toast.useToastManager();\n return (\n <Toast.Viewport className=\"pointer-events-none fixed inset-0 z-50\">\n {toasts.map((toast) => (\n <Toast.Positioner key={toast.id} toast={toast} className=\"absolute\">\n <Toast.Root\n toast={toast}\n className={cn(\n \"flex origin-[var(--transform-origin)] flex-col rounded-md bg-sf-base px-3 py-1.5 text-xs text-sf-default font-sans\",\n \"shadow-lg shadow-sf-tip-shadow outline outline-sf-fill\"\n )}\n >\n <Toast.Description />\n </Toast.Root>\n </Toast.Positioner>\n ))}\n </Toast.Viewport>\n );\n}\n\n/**\n * Internal wrapper that provides Toast context when tooltip is enabled.\n */\nfunction TooltipWrapper({ children }: { children: React.ReactNode }) {\n return (\n <Tooltip.Provider>\n <Toast.Provider toastManager={clipboardToastManager}>\n <AnchoredToasts />\n {children}\n </Toast.Provider>\n </Tooltip.Provider>\n );\n}\n\n/**\n * Read-only text field with a one-click copy-to-clipboard button.\n *\n * @example\n * ```tsx\n * <ClipboardText text=\"0c239dd2\" />\n * ```\n */\nexport const ClipboardText = forwardRef<HTMLDivElement, ClipboardTextProps>(\n (\n {\n text,\n className,\n size = SF_CLIPBOARD_TEXT_DEFAULT_VARIANTS.size,\n onCopy,\n tooltip,\n labels: { copyAction = \"Copy to clipboard\" } = EMPTY_CLIPBOARD_LABELS,\n },\n ref\n ) => {\n const [copied, setCopied] = useState(false);\n const buttonRef = useRef<HTMLButtonElement | null>(null);\n const sizeConfig = SF_CLIPBOARD_TEXT_VARIANTS.size[size];\n\n // Destructure tooltip config with defaults\n const {\n text: tooltipText = \"Copy\",\n copiedText = \"Copied\",\n side: tooltipSide = \"top\",\n } = tooltip ?? {};\n\n const copyToClipboard = useCallback(async () => {\n try {\n if (\n typeof navigator !== \"undefined\" &&\n navigator.clipboard &&\n typeof navigator.clipboard.writeText === \"function\"\n ) {\n await navigator.clipboard.writeText(text);\n } else if (typeof document !== \"undefined\") {\n // Fallback for older browsers\n const textarea = document.createElement(\"textarea\");\n textarea.value = text;\n textarea.setAttribute(\"readonly\", \"\");\n textarea.style.position = \"absolute\";\n textarea.style.left = \"-9999px\";\n document.body.appendChild(textarea);\n const selection = document.getSelection();\n const previousRange = selection?.rangeCount\n ? selection.getRangeAt(0)\n : null;\n textarea.select();\n try {\n document.execCommand(\"copy\");\n } finally {\n document.body.removeChild(textarea);\n if (previousRange) {\n selection?.removeAllRanges();\n selection?.addRange(previousRange);\n }\n }\n }\n\n setCopied(true);\n\n // Show anchored toast if tooltip mode is enabled\n if (tooltip) {\n clipboardToastManager.add({\n description: copiedText,\n positionerProps: {\n anchor: buttonRef.current,\n side: tooltipSide,\n sideOffset: 8,\n },\n timeout: 1500,\n onClose() {\n setCopied(false);\n },\n });\n } else {\n // Reset copied state after delay when no tooltip\n setTimeout(() => setCopied(false), 1500);\n }\n\n onCopy?.();\n } catch (error) {\n console.warn(\"Clipboard copy failed\", error);\n }\n }, [text, onCopy, tooltip, copiedText, tooltipSide]);\n\n const copyButton = (\n <Button\n ref={buttonRef}\n size={sizeConfig.buttonSize}\n variant=\"ghost\"\n className=\"rounded-none border-l! border-sf-line! px-3 relative overflow-hidden transition-all duration-200\"\n onClick={copyToClipboard}\n aria-label={copyAction}\n >\n <span\n className={cn(\n \"flex items-center gap-1 transition-all duration-200\",\n copied\n ? clipboardTextAnimations.slide.animate\n : clipboardTextAnimations.slide.initial\n )}\n >\n <CheckIcon />\n </span>\n <span\n className={cn(\n \"flex items-center justify-center transition-all duration-200\",\n copied\n ? clipboardTextAnimations.slide.end\n : clipboardTextAnimations.slide.animate\n )}\n >\n <CopyIcon />\n </span>\n </Button>\n );\n\n return (\n <div\n ref={ref}\n className={cn(\n inputVariants({ size: sizeConfig.buttonSize }),\n clipboardTextVariants({ size }),\n className\n )}\n >\n <span className=\"grow truncate ps-4 pe-2\">{text}</span>\n {tooltip ? (\n <TooltipWrapper>\n <Tooltip.Root\n disabled={copied}\n onOpenChange={(open, eventDetails) => {\n // Prevent tooltip from closing when button is clicked\n if (eventDetails.reason === \"trigger-press\") {\n eventDetails.cancel();\n }\n }}\n >\n <Tooltip.Trigger render={copyButton} />\n <Tooltip.Portal>\n <Tooltip.Positioner side={tooltipSide} sideOffset={8}>\n <Tooltip.Popup\n className={cn(\n \"flex origin-[var(--transform-origin)] flex-col rounded-md bg-sf-base px-3 py-1.5 text-xs text-sf-default\",\n \"shadow-lg shadow-sf-tip-shadow outline outline-sf-fill\"\n )}\n >\n {tooltipText}\n </Tooltip.Popup>\n </Tooltip.Positioner>\n </Tooltip.Portal>\n </Tooltip.Root>\n </TooltipWrapper>\n ) : (\n copyButton\n )}\n <span className=\"sr-only\" aria-live=\"polite\">\n {copied ? copiedText : \"\"}\n </span>\n </div>\n );\n }\n);\n\nClipboardText.displayName = \"ClipboardText\";\n"],"mappings":"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"}
@@ -7,7 +7,7 @@ function cn(...inputs) {
7
7
  }
8
8
  var toHex = (n) => n.toString(16).padStart(2, "0");
9
9
  function safeRandomId() {
10
- const c = (typeof globalThis !== "undefined" ? globalThis : {}).crypto;
10
+ const c = (typeof globalThis === "undefined" ? {} : globalThis).crypto;
11
11
  if (c && typeof c.randomUUID === "function") return c.randomUUID();
12
12
  if (c && typeof c.getRandomValues === "function") {
13
13
  const bytes = new Uint8Array(16);
@@ -22,4 +22,4 @@ function safeRandomId() {
22
22
  //#endregion
23
23
  export { safeRandomId as n, cn as t };
24
24
 
25
- //# sourceMappingURL=cn-YROP2_ox.js.map
25
+ //# sourceMappingURL=cn-CmAOpn49.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"cn-YROP2_ox.js","names":[],"sources":["../src/utils/cn.ts"],"sourcesContent":["import { clsx, type ClassValue } from \"clsx\";\nimport { twMerge } from \"tailwind-merge\";\n\nexport function cn(...inputs: ClassValue[]) {\n return twMerge(clsx(inputs));\n}\n\nconst toHex = (n: number) => n.toString(16).padStart(2, \"0\");\n\nexport function safeRandomId(): string {\n const g: any = typeof globalThis !== \"undefined\" ? (globalThis as any) : {};\n const c = g.crypto;\n if (c && typeof c.randomUUID === \"function\") {\n return c.randomUUID();\n }\n // RFC4122 v4 using getRandomValues if available\n if (c && typeof c.getRandomValues === \"function\") {\n const bytes = new Uint8Array(16);\n c.getRandomValues(bytes);\n bytes[6] = (bytes[6] & 0x0f) | 0x40; // version 4\n bytes[8] = (bytes[8] & 0x3f) | 0x80; // variant 10\n const hex = Array.from(bytes, toHex).join(\"\");\n return `${hex.slice(0, 8)}-${hex.slice(8, 12)}-${hex.slice(\n 12,\n 16\n )}-${hex.slice(16, 20)}-${hex.slice(20)}`;\n }\n // Last-resort fallback\n return `r${Math.random().toString(36).slice(2)}${Date.now().toString(36)}`;\n}\n"],"mappings":";;;;AAGA,SAAgB,GAAG,GAAG,QAAsB;AAC1C,QAAO,QAAQ,KAAK,OAAO,CAAC;;AAG9B,IAAM,SAAS,MAAc,EAAE,SAAS,GAAG,CAAC,SAAS,GAAG,IAAI;AAE5D,SAAgB,eAAuB;CAErC,MAAM,KADS,OAAO,eAAe,cAAe,aAAqB,EAAE,EAC/D;AACZ,KAAI,KAAK,OAAO,EAAE,eAAe,WAC/B,QAAO,EAAE,YAAY;AAGvB,KAAI,KAAK,OAAO,EAAE,oBAAoB,YAAY;EAChD,MAAM,QAAQ,IAAI,WAAW,GAAG;AAChC,IAAE,gBAAgB,MAAM;AACxB,QAAM,KAAM,MAAM,KAAK,KAAQ;AAC/B,QAAM,KAAM,MAAM,KAAK,KAAQ;EAC/B,MAAM,MAAM,MAAM,KAAK,OAAO,MAAM,CAAC,KAAK,GAAG;AAC7C,SAAO,GAAG,IAAI,MAAM,GAAG,EAAE,CAAC,GAAG,IAAI,MAAM,GAAG,GAAG,CAAC,GAAG,IAAI,MACnD,IACA,GACD,CAAC,GAAG,IAAI,MAAM,IAAI,GAAG,CAAC,GAAG,IAAI,MAAM,GAAG;;AAGzC,QAAO,IAAI,KAAK,QAAQ,CAAC,SAAS,GAAG,CAAC,MAAM,EAAE,GAAG,KAAK,KAAK,CAAC,SAAS,GAAG"}
1
+ {"version":3,"file":"cn-CmAOpn49.js","names":[],"sources":["../src/utils/cn.ts"],"sourcesContent":["import { clsx, type ClassValue } from \"clsx\";\nimport { twMerge } from \"tailwind-merge\";\n\nexport function cn(...inputs: ClassValue[]) {\n return twMerge(clsx(inputs));\n}\n\nconst toHex = (n: number) => n.toString(16).padStart(2, \"0\");\n\nexport function safeRandomId(): string {\n const g: any = typeof globalThis === \"undefined\" ? {} : (globalThis as any);\n const c = g.crypto;\n if (c && typeof c.randomUUID === \"function\") {\n return c.randomUUID();\n }\n // RFC4122 v4 using getRandomValues if available\n if (c && typeof c.getRandomValues === \"function\") {\n const bytes = new Uint8Array(16);\n c.getRandomValues(bytes);\n bytes[6] = (bytes[6] & 0x0f) | 0x40; // version 4\n bytes[8] = (bytes[8] & 0x3f) | 0x80; // variant 10\n const hex = Array.from(bytes, toHex).join(\"\");\n return `${hex.slice(0, 8)}-${hex.slice(8, 12)}-${hex.slice(\n 12,\n 16\n )}-${hex.slice(16, 20)}-${hex.slice(20)}`;\n }\n // Last-resort fallback\n return `r${Math.random().toString(36).slice(2)}${Date.now().toString(36)}`;\n}\n"],"mappings":";;;;AAGA,SAAgB,GAAG,GAAG,QAAsB;CAC1C,OAAO,QAAQ,KAAK,MAAM,CAAC;AAC7B;AAEA,IAAM,SAAS,MAAc,EAAE,SAAS,EAAE,EAAE,SAAS,GAAG,GAAG;AAE3D,SAAgB,eAAuB;CAErC,MAAM,KADS,OAAO,eAAe,cAAc,CAAC,IAAK,YAC7C;CACZ,IAAI,KAAK,OAAO,EAAE,eAAe,YAC/B,OAAO,EAAE,WAAW;CAGtB,IAAI,KAAK,OAAO,EAAE,oBAAoB,YAAY;EAChD,MAAM,QAAQ,IAAI,WAAW,EAAE;EAC/B,EAAE,gBAAgB,KAAK;EACvB,MAAM,KAAM,MAAM,KAAK,KAAQ;EAC/B,MAAM,KAAM,MAAM,KAAK,KAAQ;EAC/B,MAAM,MAAM,MAAM,KAAK,OAAO,KAAK,EAAE,KAAK,EAAE;EAC5C,OAAO,GAAG,IAAI,MAAM,GAAG,CAAC,EAAE,GAAG,IAAI,MAAM,GAAG,EAAE,EAAE,GAAG,IAAI,MACnD,IACA,EACF,EAAE,GAAG,IAAI,MAAM,IAAI,EAAE,EAAE,GAAG,IAAI,MAAM,EAAE;CACxC;CAEA,OAAO,IAAI,KAAK,OAAO,EAAE,SAAS,EAAE,EAAE,MAAM,CAAC,IAAI,KAAK,IAAI,EAAE,SAAS,EAAE;AACzE"}
@@ -1,6 +1,6 @@
1
1
  "use client";
2
- import { t as cn } from "./cn-YROP2_ox.js";
3
- import { n as highlightToTokens } from "./highlight-to-react-D0Yav4jk.js";
2
+ import { t as cn } from "./cn-CmAOpn49.js";
3
+ import { n as highlightToTokens } from "./highlight-to-react-DN9dUCS2.js";
4
4
  import { jsx } from "react/jsx-runtime";
5
5
  import { highlight } from "sugar-high";
6
6
  //#region src/components/code/code.tsx
@@ -42,7 +42,7 @@ function applyValues(code, values) {
42
42
  highlights
43
43
  };
44
44
  return {
45
- code: code.replace(/\{\{(\w+)\}\}/g, (_, key) => {
45
+ code: code.replace(/\{\{(\w+)\}\}/gu, (_, key) => {
46
46
  const entry = values[key];
47
47
  if (!entry) return `{{${key}}}`;
48
48
  if (entry.highlight) highlights.set(entry.value, entry.value);
@@ -94,4 +94,4 @@ var CodeBlock = CodeBlockComponent;
94
94
  //#endregion
95
95
  export { CodeBlock as n, Code as t };
96
96
 
97
- //# sourceMappingURL=code-BN8InC0G.js.map
97
+ //# sourceMappingURL=code-JsQz-0G_.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"code-BN8InC0G.js","names":[],"sources":["../src/components/code/code.tsx"],"sourcesContent":["\"use client\";\n\nimport { type CSSProperties } from \"react\";\nimport { highlight } from \"sugar-high\";\n\nimport { cn } from \"../../utils/cn\";\nimport { highlightToTokens } from \"../../utils/highlight-to-react\";\n\n/** Code language variant definitions. */\nexport const SF_CODE_VARIANTS = {\n lang: {\n ts: {\n classes: \"\",\n description: \"TypeScript code\",\n },\n tsx: {\n classes: \"\",\n description: \"TypeScript JSX code\",\n },\n jsonc: {\n classes: \"\",\n description: \"JSON with comments\",\n },\n bash: {\n classes: \"\",\n description: \"Shell/Bash commands\",\n },\n css: {\n classes: \"\",\n description: \"CSS styles\",\n },\n },\n} as const;\n\nexport const SF_CODE_DEFAULT_VARIANTS = {\n lang: \"ts\",\n} as const;\n\n/**\n * Styling metadata for Code component (for AI/Figma plugin consumption)\n */\nexport const SF_CODE_STYLING = {\n /** Base semantic tokens used */\n baseTokens: [\"text-sf-default\"],\n /** Typography and layout */\n typography: {\n fontFamily: \"font-mono\",\n fontSize: \"text-sm\",\n lineHeight: \"leading-[20px]\",\n },\n /** Container dimensions */\n dimensions: {\n margin: \"m-0\",\n padding: \"p-0\",\n width: \"w-auto\",\n },\n /** Border and background */\n appearance: {\n borderRadius: \"rounded-none\",\n border: \"border-none\",\n background: \"bg-transparent\",\n },\n} as const;\n\n/**\n * Styling metadata for CodeBlock component (for AI/Figma plugin consumption)\n */\nexport const SF_CODEBLOCK_STYLING = {\n /** Base semantic tokens used */\n baseTokens: [\"bg-sf-recessed\", \"border-sf-line\"],\n /** Container styling */\n container: {\n minWidth: \"min-w-0\",\n borderRadius: \"rounded-md\",\n border: \"border border-sf-line\",\n background: \"bg-sf-recessed\",\n },\n /** Inner code element padding */\n innerPadding: \"[&>pre]:p-4\",\n /** Parsed dimensions */\n dimensions: {\n borderRadius: 6,\n padding: 16,\n },\n} as const;\n\n// Derived types from SF_CODE_VARIANTS\nexport type SFCodeLang = keyof typeof SF_CODE_VARIANTS.lang;\n\nexport interface SFCodeVariantsProps {\n /**\n * Language hint for the code content.\n * - `\"ts\"` — TypeScript code\n * - `\"tsx\"` — TypeScript JSX code\n * - `\"jsonc\"` — JSON with comments\n * - `\"bash\"` — Shell/Bash commands\n * - `\"css\"` — CSS styles\n * @default \"ts\"\n */\n lang?: SFCodeLang;\n}\n\nexport function codeVariants({\n lang = SF_CODE_DEFAULT_VARIANTS.lang,\n}: SFCodeVariantsProps = {}) {\n return cn(\n \"m-0 w-auto rounded-none border-none bg-transparent p-0 font-mono text-sm leading-[20px] text-sf-default\",\n SF_CODE_VARIANTS.lang[lang].classes\n );\n}\n\n// Legacy type alias for backwards compatibility\nexport type CodeLang = SFCodeLang;\n\n/** @deprecated Use CodeLang instead */\nexport type BundledLanguage = CodeLang;\n\n/**\n * Code component props.\n *\n * @example\n * ```tsx\n * <Code code=\"const x = 1;\" lang=\"ts\" />\n * <Code code=\"export API_KEY={{apiKey}}\" lang=\"bash\"\n * values={{ apiKey: { value: \"sk_live_123\", highlight: true } }}\n * />\n * ```\n */\nexport interface CodeProps extends SFCodeVariantsProps {\n /** The code string to display. */\n code: string;\n /** Template values for `{{key}}` interpolation. Values with `highlight: true` are visually emphasized. */\n values?: Record<\n string,\n {\n value: string;\n highlight?: boolean;\n }\n >;\n /** Additional CSS classes merged via `cn()`. */\n className?: string;\n /** Inline styles. */\n style?: CSSProperties;\n}\n\n/**\n * Substitutes `{{key}}` placeholders in the raw code string before highlighting.\n * Returns the substituted code and a set of highlighted values to wrap post-highlight.\n */\nfunction applyValues(\n code: string,\n values?: CodeProps[\"values\"]\n): { code: string; highlights: Map<string, string> } {\n const highlights = new Map<string, string>();\n if (!values) return { code, highlights };\n const substituted = code.replace(/\\{\\{(\\w+)\\}\\}/g, (_, key) => {\n const entry = values[key as string];\n if (!entry) return `{{${key}}}`;\n if (entry.highlight) highlights.set(entry.value, entry.value);\n return entry.value;\n });\n return { code: substituted, highlights };\n}\n\n/**\n * Syntax-highlighted code component powered by sugar-high.\n *\n * Renders code in a monospace font with token-level syntax highlighting.\n * For a bordered container version, use `Code.Block` or `CodeBlock`.\n *\n * **Styling:**\n * - Typography: `font-mono text-sm leading-[20px]`\n * - Colors: semantic `--sh-*` CSS variables (defined in SignalFlare theme)\n * - No borders or padding (use CodeBlock for styled container)\n */\nfunction CodeComponent({\n code,\n lang = SF_CODE_DEFAULT_VARIANTS.lang,\n values,\n className,\n style,\n}: CodeProps) {\n const { code: substituted } = applyValues(code, values);\n const html = highlight(substituted);\n const tokens = highlightToTokens(html);\n\n return (\n <pre className={cn(codeVariants({ lang }), className)} style={style}>\n <code>{tokens}</code>\n </pre>\n );\n}\n\nCodeComponent.displayName = \"Code\";\n\n/**\n * CodeBlock component props — code inside a bordered container.\n *\n * @example\n * ```tsx\n * <CodeBlock lang=\"tsx\" code={`const greeting = \"Hello!\";`} />\n * ```\n */\nexport interface CodeBlockProps {\n /** The code string to display. */\n code: string;\n /**\n * Language hint for the code content.\n * @default \"ts\"\n */\n lang?: CodeLang;\n}\n\n/**\n * Syntax-highlighted code block with border and background container.\n *\n * **Styling:**\n * - Container: `min-w-0 rounded-md border border-sf-line bg-sf-recessed`\n * - Inner padding: `p-4` (16px)\n */\nfunction CodeBlockComponent({ code, lang }: CodeBlockProps) {\n return (\n <div className=\"min-w-0 overflow-x-auto rounded-md border border-sf-line bg-sf-recessed [&>pre]:p-4\">\n <CodeComponent lang={lang} code={code} />\n </div>\n );\n}\n\nCodeBlockComponent.displayName = \"CodeBlock\";\n\n// Export Code with Block sub-component (for registry detection)\nexport const Code = Object.assign(CodeComponent, {\n Block: CodeBlockComponent,\n});\n\n// Backward-compatible standalone export\nexport const CodeBlock = CodeBlockComponent;\n"],"mappings":";;;;;;;AASA,IAAa,mBAAmB,EAC9B,MAAM;CACJ,IAAI;EACF,SAAS;EACT,aAAa;EACd;CACD,KAAK;EACH,SAAS;EACT,aAAa;EACd;CACD,OAAO;EACL,SAAS;EACT,aAAa;EACd;CACD,MAAM;EACJ,SAAS;EACT,aAAa;EACd;CACD,KAAK;EACH,SAAS;EACT,aAAa;EACd;CACF,EACF;AAED,IAAa,2BAA2B,EACtC,MAAM,MACP;AAkED,SAAgB,aAAa,EAC3B,OAAO,yBAAyB,SACT,EAAE,EAAE;AAC3B,QAAO,GACL,2GACA,iBAAiB,KAAK,MAAM,QAC7B;;;;;;AAyCH,SAAS,YACP,MACA,QACmD;CACnD,MAAM,6BAAa,IAAI,KAAqB;AAC5C,KAAI,CAAC,OAAQ,QAAO;EAAE;EAAM;EAAY;AAOxC,QAAO;EAAE,MANW,KAAK,QAAQ,mBAAmB,GAAG,QAAQ;GAC7D,MAAM,QAAQ,OAAO;AACrB,OAAI,CAAC,MAAO,QAAO,KAAK,IAAI;AAC5B,OAAI,MAAM,UAAW,YAAW,IAAI,MAAM,OAAO,MAAM,MAAM;AAC7D,UAAO,MAAM;IACb;EAC0B;EAAY;;;;;;;;;;;;;AAc1C,SAAS,cAAc,EACrB,MACA,OAAO,yBAAyB,MAChC,QACA,WACA,SACY;CACZ,MAAM,EAAE,MAAM,gBAAgB,YAAY,MAAM,OAAO;CAEvD,MAAM,SAAS,kBADF,UAAU,YAAY,CACG;AAEtC,QACE,oBAAC,OAAD;EAAK,WAAW,GAAG,aAAa,EAAE,MAAM,CAAC,EAAE,UAAU;EAAS;YAC5D,oBAAC,QAAD,EAAA,UAAO,QAAc,CAAA;EACjB,CAAA;;AAIV,cAAc,cAAc;;;;;;;;AA2B5B,SAAS,mBAAmB,EAAE,MAAM,QAAwB;AAC1D,QACE,oBAAC,OAAD;EAAK,WAAU;YACb,oBAAC,eAAD;GAAqB;GAAY;GAAQ,CAAA;EACrC,CAAA;;AAIV,mBAAmB,cAAc;AAGjC,IAAa,OAAO,OAAO,OAAO,eAAe,EAC/C,OAAO,oBACR,CAAC;AAGF,IAAa,YAAY"}
1
+ {"version":3,"file":"code-JsQz-0G_.js","names":[],"sources":["../src/components/code/code.tsx"],"sourcesContent":["\"use client\";\n\nimport { type CSSProperties } from \"react\";\nimport { highlight } from \"sugar-high\";\n\nimport { cn } from \"../../utils/cn\";\nimport { highlightToTokens } from \"../../utils/highlight-to-react\";\n\n/** Code language variant definitions. */\nexport const SF_CODE_VARIANTS = {\n lang: {\n ts: {\n classes: \"\",\n description: \"TypeScript code\",\n },\n tsx: {\n classes: \"\",\n description: \"TypeScript JSX code\",\n },\n jsonc: {\n classes: \"\",\n description: \"JSON with comments\",\n },\n bash: {\n classes: \"\",\n description: \"Shell/Bash commands\",\n },\n css: {\n classes: \"\",\n description: \"CSS styles\",\n },\n },\n} as const;\n\nexport const SF_CODE_DEFAULT_VARIANTS = {\n lang: \"ts\",\n} as const;\n\n/**\n * Styling metadata for Code component (for AI/Figma plugin consumption)\n */\nexport const SF_CODE_STYLING = {\n /** Base semantic tokens used */\n baseTokens: [\"text-sf-default\"],\n /** Typography and layout */\n typography: {\n fontFamily: \"font-mono\",\n fontSize: \"text-sm\",\n lineHeight: \"leading-[20px]\",\n },\n /** Container dimensions */\n dimensions: {\n margin: \"m-0\",\n padding: \"p-0\",\n width: \"w-auto\",\n },\n /** Border and background */\n appearance: {\n borderRadius: \"rounded-none\",\n border: \"border-none\",\n background: \"bg-transparent\",\n },\n} as const;\n\n/**\n * Styling metadata for CodeBlock component (for AI/Figma plugin consumption)\n */\nexport const SF_CODEBLOCK_STYLING = {\n /** Base semantic tokens used */\n baseTokens: [\"bg-sf-recessed\", \"border-sf-line\"],\n /** Container styling */\n container: {\n minWidth: \"min-w-0\",\n borderRadius: \"rounded-md\",\n border: \"border border-sf-line\",\n background: \"bg-sf-recessed\",\n },\n /** Inner code element padding */\n innerPadding: \"[&>pre]:p-4\",\n /** Parsed dimensions */\n dimensions: {\n borderRadius: 6,\n padding: 16,\n },\n} as const;\n\n// Derived types from SF_CODE_VARIANTS\nexport type SFCodeLang = keyof typeof SF_CODE_VARIANTS.lang;\n\nexport interface SFCodeVariantsProps {\n /**\n * Language hint for the code content.\n * - `\"ts\"` — TypeScript code\n * - `\"tsx\"` — TypeScript JSX code\n * - `\"jsonc\"` — JSON with comments\n * - `\"bash\"` — Shell/Bash commands\n * - `\"css\"` — CSS styles\n * @default \"ts\"\n */\n lang?: SFCodeLang;\n}\n\nexport function codeVariants({\n lang = SF_CODE_DEFAULT_VARIANTS.lang,\n}: SFCodeVariantsProps = {}) {\n return cn(\n \"m-0 w-auto rounded-none border-none bg-transparent p-0 font-mono text-sm leading-[20px] text-sf-default\",\n SF_CODE_VARIANTS.lang[lang].classes\n );\n}\n\n// Legacy type alias for backwards compatibility\nexport type CodeLang = SFCodeLang;\n\n/** @deprecated Use CodeLang instead */\nexport type BundledLanguage = CodeLang;\n\n/**\n * Code component props.\n *\n * @example\n * ```tsx\n * <Code code=\"const x = 1;\" lang=\"ts\" />\n * <Code code=\"export API_KEY={{apiKey}}\" lang=\"bash\"\n * values={{ apiKey: { value: \"sk_live_123\", highlight: true } }}\n * />\n * ```\n */\nexport interface CodeProps extends SFCodeVariantsProps {\n /** The code string to display. */\n code: string;\n /** Template values for `{{key}}` interpolation. Values with `highlight: true` are visually emphasized. */\n values?: Record<\n string,\n {\n value: string;\n highlight?: boolean;\n }\n >;\n /** Additional CSS classes merged via `cn()`. */\n className?: string;\n /** Inline styles. */\n style?: CSSProperties;\n}\n\n/**\n * Substitutes `{{key}}` placeholders in the raw code string before highlighting.\n * Returns the substituted code and a set of highlighted values to wrap post-highlight.\n */\nfunction applyValues(\n code: string,\n values?: CodeProps[\"values\"]\n): { code: string; highlights: Map<string, string> } {\n const highlights = new Map<string, string>();\n if (!values) return { code, highlights };\n const substituted = code.replace(/\\{\\{(\\w+)\\}\\}/gu, (_, key) => {\n const entry = values[key as string];\n if (!entry) return `{{${key}}}`;\n if (entry.highlight) highlights.set(entry.value, entry.value);\n return entry.value;\n });\n return { code: substituted, highlights };\n}\n\n/**\n * Syntax-highlighted code component powered by sugar-high.\n *\n * Renders code in a monospace font with token-level syntax highlighting.\n * For a bordered container version, use `Code.Block` or `CodeBlock`.\n *\n * **Styling:**\n * - Typography: `font-mono text-sm leading-[20px]`\n * - Colors: semantic `--sh-*` CSS variables (defined in SignalFlare theme)\n * - No borders or padding (use CodeBlock for styled container)\n */\nfunction CodeComponent({\n code,\n lang = SF_CODE_DEFAULT_VARIANTS.lang,\n values,\n className,\n style,\n}: CodeProps) {\n const { code: substituted } = applyValues(code, values);\n const html = highlight(substituted);\n const tokens = highlightToTokens(html);\n\n return (\n <pre className={cn(codeVariants({ lang }), className)} style={style}>\n <code>{tokens}</code>\n </pre>\n );\n}\n\nCodeComponent.displayName = \"Code\";\n\n/**\n * CodeBlock component props — code inside a bordered container.\n *\n * @example\n * ```tsx\n * <CodeBlock lang=\"tsx\" code={`const greeting = \"Hello!\";`} />\n * ```\n */\nexport interface CodeBlockProps {\n /** The code string to display. */\n code: string;\n /**\n * Language hint for the code content.\n * @default \"ts\"\n */\n lang?: CodeLang;\n}\n\n/**\n * Syntax-highlighted code block with border and background container.\n *\n * **Styling:**\n * - Container: `min-w-0 rounded-md border border-sf-line bg-sf-recessed`\n * - Inner padding: `p-4` (16px)\n */\nfunction CodeBlockComponent({ code, lang }: CodeBlockProps) {\n return (\n <div className=\"min-w-0 overflow-x-auto rounded-md border border-sf-line bg-sf-recessed [&>pre]:p-4\">\n <CodeComponent lang={lang} code={code} />\n </div>\n );\n}\n\nCodeBlockComponent.displayName = \"CodeBlock\";\n\n// Export Code with Block sub-component (for registry detection)\nexport const Code = Object.assign(CodeComponent, {\n Block: CodeBlockComponent,\n});\n\n// Backward-compatible standalone export\nexport const CodeBlock = CodeBlockComponent;\n"],"mappings":";;;;;;;AASA,IAAa,mBAAmB,EAC9B,MAAM;CACJ,IAAI;EACF,SAAS;EACT,aAAa;CACf;CACA,KAAK;EACH,SAAS;EACT,aAAa;CACf;CACA,OAAO;EACL,SAAS;EACT,aAAa;CACf;CACA,MAAM;EACJ,SAAS;EACT,aAAa;CACf;CACA,KAAK;EACH,SAAS;EACT,aAAa;CACf;AACF,EACF;AAEA,IAAa,2BAA2B,EACtC,MAAM,KACR;AAkEA,SAAgB,aAAa,EAC3B,OAAO,yBAAyB,SACT,CAAC,GAAG;CAC3B,OAAO,GACL,2GACA,iBAAiB,KAAK,MAAM,OAC9B;AACF;;;;;AAwCA,SAAS,YACP,MACA,QACmD;CACnD,MAAM,6BAAa,IAAI,IAAoB;CAC3C,IAAI,CAAC,QAAQ,OAAO;EAAE;EAAM;CAAW;CAOvC,OAAO;EAAE,MANW,KAAK,QAAQ,oBAAoB,GAAG,QAAQ;GAC9D,MAAM,QAAQ,OAAO;GACrB,IAAI,CAAC,OAAO,OAAO,KAAK,IAAI;GAC5B,IAAI,MAAM,WAAW,WAAW,IAAI,MAAM,OAAO,MAAM,KAAK;GAC5D,OAAO,MAAM;EACf,CACe;EAAa;CAAW;AACzC;;;;;;;;;;;;AAaA,SAAS,cAAc,EACrB,MACA,OAAO,yBAAyB,MAChC,QACA,WACA,SACY;CACZ,MAAM,EAAE,MAAM,gBAAgB,YAAY,MAAM,MAAM;CAEtD,MAAM,SAAS,kBADF,UAAU,WACU,CAAI;CAErC,OACE,oBAAC,OAAD;EAAK,WAAW,GAAG,aAAa,EAAE,KAAK,CAAC,GAAG,SAAS;EAAU;YAC5D,oBAAC,QAAD,EAAA,UAAO,OAAa,CAAA;CACjB,CAAA;AAET;AAEA,cAAc,cAAc;;;;;;;;AA2B5B,SAAS,mBAAmB,EAAE,MAAM,QAAwB;CAC1D,OACE,oBAAC,OAAD;EAAK,WAAU;YACb,oBAAC,eAAD;GAAqB;GAAY;EAAO,CAAA;CACrC,CAAA;AAET;AAEA,mBAAmB,cAAc;AAGjC,IAAa,OAAO,OAAO,OAAO,eAAe,EAC/C,OAAO,mBACT,CAAC;AAGD,IAAa,YAAY"}
@@ -1,5 +1,5 @@
1
1
  "use client";
2
- import { t as cn } from "./cn-YROP2_ox.js";
2
+ import { t as cn } from "./cn-CmAOpn49.js";
3
3
  import { forwardRef, useCallback, useId } from "react";
4
4
  import { jsx, jsxs } from "react/jsx-runtime";
5
5
  import { CaretDownIcon } from "@phosphor-icons/react";
@@ -69,4 +69,4 @@ Collapsible.displayName = "Collapsible";
69
69
  //#endregion
70
70
  export { Collapsible as t };
71
71
 
72
- //# sourceMappingURL=collapsible-D_ueZ0jz.js.map
72
+ //# sourceMappingURL=collapsible-1kOZ-89L.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"collapsible-D_ueZ0jz.js","names":[],"sources":["../src/components/collapsible/collapsible.tsx"],"sourcesContent":["import { CaretDownIcon } from \"@phosphor-icons/react\";\nimport { type PropsWithChildren, forwardRef, useCallback, useId } from \"react\";\n\nimport { cn } from \"../../utils/cn\";\n\nexport const SF_COLLAPSIBLE_VARIANTS = {} as const;\n\nexport const SF_COLLAPSIBLE_DEFAULT_VARIANTS = {} as const;\n\nexport interface SFCollapsibleVariantsProps {}\n\nexport function collapsibleVariants(_props: SFCollapsibleVariantsProps = {}) {\n return cn(\n // Base styles for the trigger\n \"flex cursor-pointer items-center gap-1 text-sm text-sf-link select-none\"\n );\n}\n\n/**\n * Collapsible component props.\n *\n * @example\n * ```tsx\n * <Collapsible label=\"Show details\" open={open} onOpenChange={setOpen}>\n * <Text>Hidden content revealed when expanded.</Text>\n * </Collapsible>\n * ```\n */\nexport type CollapsibleProps = PropsWithChildren<\n SFCollapsibleVariantsProps & {\n /** Text label displayed in the trigger button */\n label: string;\n /** Whether the collapsible content is visible */\n open?: boolean;\n /** Callback fired when the open state changes */\n onOpenChange?: (open: boolean) => void;\n /** Additional CSS classes for the content panel */\n className?: string;\n }\n>;\n\n/**\n * Collapsible component for showing/hiding content.\n *\n * Features:\n * - Animated chevron indicator (rotates 180° when open)\n * - Accessible with aria-expanded and aria-controls\n * - Content panel with left border accent\n *\n * @example\n * ```tsx\n * const [open, setOpen] = useState(false);\n *\n * <Collapsible label=\"Show details\" open={open} onOpenChange={setOpen}>\n * <Text>Hidden content revealed when expanded.</Text>\n * </Collapsible>\n * ```\n *\n * @example Controlled accordion pattern\n * ```tsx\n * const [activeIndex, setActiveIndex] = useState<number | null>(null);\n *\n * {items.map((item, i) => (\n * <Collapsible\n * key={i}\n * label={item.title}\n * open={activeIndex === i}\n * onOpenChange={(open) => setActiveIndex(open ? i : null)}\n * >\n * {item.content}\n * </Collapsible>\n * ))}\n * ```\n */\nexport const Collapsible = forwardRef<HTMLDivElement, CollapsibleProps>(\n ({ label, open, onOpenChange, children, className }, ref) => {\n const contentId = useId();\n\n const handleOpen = useCallback(() => {\n onOpenChange?.(!open);\n }, [open, onOpenChange]);\n\n return (\n <div ref={ref}>\n <button\n type=\"button\"\n aria-expanded={open}\n aria-controls={contentId}\n className={collapsibleVariants()}\n onClick={handleOpen}\n >\n {label}{\" \"}\n <CaretDownIcon\n className={cn(\"h-4 w-4 transition-transform\", open && \"rotate-180\")}\n />\n </button>\n {open && (\n <div\n id={contentId}\n className={cn(\n \"my-2 space-y-4 border-l-2 border-sf-fill pl-4\",\n className\n )}\n >\n {children}\n </div>\n )}\n </div>\n );\n }\n);\n\nCollapsible.displayName = \"Collapsible\";\n"],"mappings":";;;;;;AAWA,SAAgB,oBAAoB,SAAqC,EAAE,EAAE;AAC3E,QAAO,GAEL,0EACD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA2DH,IAAa,cAAc,YACxB,EAAE,OAAO,MAAM,cAAc,UAAU,aAAa,QAAQ;CAC3D,MAAM,YAAY,OAAO;CAEzB,MAAM,aAAa,kBAAkB;AACnC,iBAAe,CAAC,KAAK;IACpB,CAAC,MAAM,aAAa,CAAC;AAExB,QACE,qBAAC,OAAD;EAAU;YAAV,CACE,qBAAC,UAAD;GACE,MAAK;GACL,iBAAe;GACf,iBAAe;GACf,WAAW,qBAAqB;GAChC,SAAS;aALX;IAOG;IAAO;IACR,oBAAC,eAAD,EACE,WAAW,GAAG,gCAAgC,QAAQ,aAAa,EACnE,CAAA;IACK;MACR,QACC,oBAAC,OAAD;GACE,IAAI;GACJ,WAAW,GACT,iDACA,UACD;GAEA;GACG,CAAA,CAEJ;;EAGX;AAED,YAAY,cAAc"}
1
+ {"version":3,"file":"collapsible-1kOZ-89L.js","names":[],"sources":["../src/components/collapsible/collapsible.tsx"],"sourcesContent":["import { CaretDownIcon } from \"@phosphor-icons/react\";\nimport { type PropsWithChildren, forwardRef, useCallback, useId } from \"react\";\n\nimport { cn } from \"../../utils/cn\";\n\nexport const SF_COLLAPSIBLE_VARIANTS = {} as const;\n\nexport const SF_COLLAPSIBLE_DEFAULT_VARIANTS = {} as const;\n\nexport interface SFCollapsibleVariantsProps {}\n\nexport function collapsibleVariants(_props: SFCollapsibleVariantsProps = {}) {\n return cn(\n // Base styles for the trigger\n \"flex cursor-pointer items-center gap-1 text-sm text-sf-link select-none\"\n );\n}\n\n/**\n * Collapsible component props.\n *\n * @example\n * ```tsx\n * <Collapsible label=\"Show details\" open={open} onOpenChange={setOpen}>\n * <Text>Hidden content revealed when expanded.</Text>\n * </Collapsible>\n * ```\n */\nexport type CollapsibleProps = PropsWithChildren<\n SFCollapsibleVariantsProps & {\n /** Text label displayed in the trigger button */\n label: string;\n /** Whether the collapsible content is visible */\n open?: boolean;\n /** Callback fired when the open state changes */\n onOpenChange?: (open: boolean) => void;\n /** Additional CSS classes for the content panel */\n className?: string;\n }\n>;\n\n/**\n * Collapsible component for showing/hiding content.\n *\n * Features:\n * - Animated chevron indicator (rotates 180° when open)\n * - Accessible with aria-expanded and aria-controls\n * - Content panel with left border accent\n *\n * @example\n * ```tsx\n * const [open, setOpen] = useState(false);\n *\n * <Collapsible label=\"Show details\" open={open} onOpenChange={setOpen}>\n * <Text>Hidden content revealed when expanded.</Text>\n * </Collapsible>\n * ```\n *\n * @example Controlled accordion pattern\n * ```tsx\n * const [activeIndex, setActiveIndex] = useState<number | null>(null);\n *\n * {items.map((item, i) => (\n * <Collapsible\n * key={i}\n * label={item.title}\n * open={activeIndex === i}\n * onOpenChange={(open) => setActiveIndex(open ? i : null)}\n * >\n * {item.content}\n * </Collapsible>\n * ))}\n * ```\n */\nexport const Collapsible = forwardRef<HTMLDivElement, CollapsibleProps>(\n ({ label, open, onOpenChange, children, className }, ref) => {\n const contentId = useId();\n\n const handleOpen = useCallback(() => {\n onOpenChange?.(!open);\n }, [open, onOpenChange]);\n\n return (\n <div ref={ref}>\n <button\n type=\"button\"\n aria-expanded={open}\n aria-controls={contentId}\n className={collapsibleVariants()}\n onClick={handleOpen}\n >\n {label}{\" \"}\n <CaretDownIcon\n className={cn(\"h-4 w-4 transition-transform\", open && \"rotate-180\")}\n />\n </button>\n {open && (\n <div\n id={contentId}\n className={cn(\n \"my-2 space-y-4 border-l-2 border-sf-fill pl-4\",\n className\n )}\n >\n {children}\n </div>\n )}\n </div>\n );\n }\n);\n\nCollapsible.displayName = \"Collapsible\";\n"],"mappings":";;;;;;AAWA,SAAgB,oBAAoB,SAAqC,CAAC,GAAG;CAC3E,OAAO,GAEL,yEACF;AACF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA0DA,IAAa,cAAc,YACxB,EAAE,OAAO,MAAM,cAAc,UAAU,aAAa,QAAQ;CAC3D,MAAM,YAAY,MAAM;CAExB,MAAM,aAAa,kBAAkB;EACnC,eAAe,CAAC,IAAI;CACtB,GAAG,CAAC,MAAM,YAAY,CAAC;CAEvB,OACE,qBAAC,OAAD;EAAU;YAAV,CACE,qBAAC,UAAD;GACE,MAAK;GACL,iBAAe;GACf,iBAAe;GACf,WAAW,oBAAoB;GAC/B,SAAS;aALX;IAOG;IAAO;IACR,oBAAC,eAAD,EACE,WAAW,GAAG,gCAAgC,QAAQ,YAAY,EACnE,CAAA;GACK;MACP,QACC,oBAAC,OAAD;GACE,IAAI;GACJ,WAAW,GACT,iDACA,SACF;GAEC;EACE,CAAA,CAEJ;;AAET,CACF;AAEA,YAAY,cAAc"}
@@ -1,7 +1,7 @@
1
1
  "use client";
2
- import { t as cn } from "./cn-YROP2_ox.js";
3
- import { t as Field } from "./field-B_yVof52.js";
4
- import { r as inputVariants } from "./input-B2bbijRh.js";
2
+ import { t as cn } from "./cn-CmAOpn49.js";
3
+ import { t as Field } from "./field-DBpFzzBS.js";
4
+ import { r as inputVariants } from "./input-GkfMQZC_.js";
5
5
  import { Fragment } from "react";
6
6
  import { jsx, jsxs } from "react/jsx-runtime";
7
7
  import { CaretDownIcon, CheckIcon, XIcon } from "@phosphor-icons/react";
@@ -194,4 +194,4 @@ var Combobox$1 = Object.assign(Root, {
194
194
  //#endregion
195
195
  export { Combobox$1 as t };
196
196
 
197
- //# sourceMappingURL=combobox-B7TOK0U2.js.map
197
+ //# sourceMappingURL=combobox-CQwDmqgA.js.map