@signalflare-ai/ui 1.2.0 → 1.4.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 (318) hide show
  1. package/CHANGELOG.md +154 -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-DrguJq_H.js +395 -0
  149. package/dist/data-grid-DrguJq_H.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 +0 -305
  305. package/dist/data-grid-DGHmU0w3.js.map +0 -1
  306. package/dist/dist-B6iWiWwp.js.map +0 -1
  307. package/dist/dropdown-B_nrGXjV.js.map +0 -1
  308. package/dist/filters-cpJCY21R.js.map +0 -1
  309. package/dist/flow-B4v198ot.js.map +0 -1
  310. package/dist/highlight-to-react-D0Yav4jk.js.map +0 -1
  311. package/dist/layout-DJHMMap2.js.map +0 -1
  312. package/dist/link-provider-BUZKXaNE.js.map +0 -1
  313. package/dist/measured-text-BI3dTJmH.js.map +0 -1
  314. package/dist/sidebar-D4zrlYpn.js.map +0 -1
  315. package/dist/stat-card-Ew-ofzEm.js.map +0 -1
  316. package/dist/switch-BxAMfHdt.js.map +0 -1
  317. package/dist/text-roll-Ch52hcQj.js.map +0 -1
  318. package/dist/theme-toggle-LDfIKEqx.js.map +0 -1
@@ -1,7 +1,7 @@
1
1
  "use client";
2
- import { t as cn } from "./cn-YROP2_ox.js";
3
- import { n as useLinkComponent } from "./link-provider-BUZKXaNE.js";
4
- import { t as Checkbox } from "./checkbox-D7p4QKsC.js";
2
+ import { t as cn } from "./cn-CmAOpn49.js";
3
+ import { n as useLinkComponent } from "./link-provider-BSn8YJon.js";
4
+ import { t as Checkbox } from "./checkbox-Cy_OCyay.js";
5
5
  import * as React$1 from "react";
6
6
  import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
7
7
  import { CaretRightIcon, CheckIcon } from "@phosphor-icons/react";
@@ -59,13 +59,18 @@ var DropdownMenuItem = React$1.forwardRef(({ className, inset, icon: IconCompone
59
59
  })
60
60
  ] });
61
61
  if (!href) return innerContent;
62
- const isExternal = /^(https?:)?\/\//.test(href);
62
+ const isExternal = /^(https?:)?\/\//u.test(href);
63
63
  const styles = cn("flex items-center", variant === "danger" && "text-sf-danger data-highlighted:bg-sf-danger/5 data-highlighted:text-sf-danger");
64
64
  if (isExternal) return /* @__PURE__ */ jsx("a", {
65
65
  className: cn(styles, "w-full text-inherit! no-underline!"),
66
66
  href,
67
67
  target: "_blank",
68
68
  rel: "noreferrer",
69
+ /**
70
+ * For some reason we need this here to prevent the outer link
71
+ * from being clicked (thereby going to the worker details
72
+ * instead of visiting the link)
73
+ */
69
74
  onClick: (e) => e.stopPropagation(),
70
75
  children: innerContent
71
76
  });
@@ -73,6 +78,11 @@ var DropdownMenuItem = React$1.forwardRef(({ className, inset, icon: IconCompone
73
78
  className: cn(styles, "w-full text-inherit! no-underline!"),
74
79
  href,
75
80
  to: href,
81
+ /**
82
+ * For some reason we need this here to prevent the outer link
83
+ * from being clicked (thereby going to the worker details
84
+ * instead of visiting the link)
85
+ */
76
86
  onClick: (e) => e.stopPropagation(),
77
87
  children: innerContent
78
88
  });
@@ -199,4 +209,4 @@ var DropdownMenu = Object.assign(Menu.Root, {
199
209
  //#endregion
200
210
  export { DropdownMenu as t };
201
211
 
202
- //# sourceMappingURL=dropdown-B_nrGXjV.js.map
212
+ //# sourceMappingURL=dropdown-XzbnRLYR.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dropdown-XzbnRLYR.js","names":[],"sources":["../src/components/dropdown/dropdown.tsx"],"sourcesContent":["import { Menu as DropdownMenuPrimitive } from \"@base-ui/react/menu\";\nimport {\n CaretRightIcon as CaretRight,\n CheckIcon as Check,\n type Icon,\n} from \"@phosphor-icons/react\";\nimport * as React from \"react\";\n\nimport { cn } from \"../../utils/cn\";\nimport { useLinkComponent } from \"../../utils/link-provider\";\nimport { Checkbox } from \"../checkbox\";\n\n/** Dropdown item variant definitions (default and danger styles). */\nexport const SF_DROPDOWN_VARIANTS = {\n variant: {\n default: {\n classes: \"\",\n description: \"Default dropdown item appearance\",\n },\n danger: {\n classes:\n \"text-sf-danger data-highlighted:bg-sf-danger/5 data-highlighted:text-sf-danger\",\n description: \"Destructive action item\",\n },\n },\n} as const;\n\nexport const SF_DROPDOWN_DEFAULT_VARIANTS = {\n variant: \"default\",\n} as const;\n\n// Derived types from SF_DROPDOWN_VARIANTS\nexport type SFDropdownVariant = keyof typeof SF_DROPDOWN_VARIANTS.variant;\n\nexport interface SFDropdownVariantsProps {\n /**\n * Visual style of the dropdown item.\n * - `\"default\"` — Standard item appearance\n * - `\"danger\"` — Destructive action with red text\n * @default \"default\"\n */\n variant?: SFDropdownVariant;\n}\n\nexport function dropdownVariants({\n variant = SF_DROPDOWN_DEFAULT_VARIANTS.variant,\n}: SFDropdownVariantsProps = {}) {\n return cn(SF_DROPDOWN_VARIANTS.variant[variant].classes);\n}\n\nconst DropdownMenuSubTrigger = React.forwardRef<\n React.ElementRef<typeof DropdownMenuPrimitive.SubmenuTrigger>,\n React.ComponentPropsWithoutRef<\n typeof DropdownMenuPrimitive.SubmenuTrigger\n > & {\n inset?: boolean;\n icon?: Icon;\n }\n>(({ className, inset, children, icon: IconComponent, ...props }, ref) => (\n <DropdownMenuPrimitive.SubmenuTrigger\n ref={ref}\n className={cn(\n \"flex cursor-default items-center rounded-sm text-base outline-hidden select-none\", // base styles\n \"px-2 py-1.5\", // spacing\n \"focus:bg-sf-tint\", // focus state\n \"data-[state=open]:bg-sf-tint\", // open state\n inset && \"pl-8\", // conditional inset\n className\n )}\n {...props}\n >\n {IconComponent && <IconComponent className=\"mr-2 h-4 w-4\" />}\n {children}\n <CaretRight className=\"ml-auto h-4 w-4\" />\n </DropdownMenuPrimitive.SubmenuTrigger>\n));\n\nDropdownMenuSubTrigger.displayName =\n DropdownMenuPrimitive.SubmenuTrigger.displayName;\n\nconst DropdownMenuContent = React.forwardRef<\n React.ElementRef<typeof DropdownMenuPrimitive.Positioner>,\n React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Positioner>\n>(({ className, sideOffset = 8, children, ...props }, ref) => (\n <DropdownMenuPrimitive.Portal>\n <DropdownMenuPrimitive.Positioner\n ref={ref}\n sideOffset={sideOffset}\n {...props}\n >\n <DropdownMenuPrimitive.Popup\n className={cn(\n \"overflow-hidden bg-sf-control text-sf-default\", // background\n \"rounded-lg shadow-lg ring ring-sf-line\", // border part\n \"min-w-36 p-1.5\", // spacing\n \"data-[state=open]:animate-in data-[state=open]:fade-in-0 data-[state=open]:zoom-in-95\", // open animation\n \"data-[side=bottom]:slide-in-from-top-2\", // bottom side animation\n \"data-[side=left]:slide-in-from-right-2\", // left side animation\n \"data-[side=right]:slide-in-from-left-2\", // right side animation\n \"data-[side=top]:slide-in-from-bottom-2\", // top side animation\n \"data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95\", // close animation\n className\n )}\n >\n {children}\n </DropdownMenuPrimitive.Popup>\n </DropdownMenuPrimitive.Positioner>\n </DropdownMenuPrimitive.Portal>\n));\n\nconst renderIconNode = (IconComponent?: Icon | React.ReactNode) => {\n if (!IconComponent) return null;\n if (React.isValidElement(IconComponent)) return IconComponent;\n const Comp = IconComponent as React.ComponentType<Record<string, unknown>>;\n return <Comp className=\"mr-2 h-4 w-4\" />;\n};\n\nconst DropdownMenuItem = React.forwardRef<\n React.ElementRef<typeof DropdownMenuPrimitive.Item>,\n React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Item> & {\n inset?: boolean;\n icon?: Icon | React.ReactNode;\n selected?: boolean;\n href?: string;\n variant?: \"default\" | \"danger\";\n }\n>(\n (\n {\n className,\n inset,\n icon: IconComponent,\n children,\n selected,\n render,\n href,\n variant = \"default\",\n ...props\n },\n ref\n ) => {\n const LinkComponent = useLinkComponent();\n const content = React.useMemo(() => {\n const innerContent = (\n <>\n {IconComponent && renderIconNode(IconComponent)}\n {children}\n {selected && (\n <span className=\"inline-flex\">\n <Check />\n </span>\n )}\n </>\n );\n\n if (!href) return innerContent;\n\n // Matches http://, https://, or protocol-relative //\n const isExternal = /^(https?:)?\\/\\//u.test(href);\n const styles = cn(\n \"flex items-center\",\n variant === \"danger\" &&\n \"text-sf-danger data-highlighted:bg-sf-danger/5 data-highlighted:text-sf-danger\"\n );\n if (isExternal) {\n return (\n <a\n className={cn(styles, \"w-full text-inherit! no-underline!\")}\n href={href}\n target=\"_blank\"\n rel=\"noreferrer\"\n /**\n * For some reason we need this here to prevent the outer link\n * from being clicked (thereby going to the worker details\n * instead of visiting the link)\n */\n onClick={(e) => e.stopPropagation()}\n >\n {innerContent}\n </a>\n );\n }\n return (\n <LinkComponent\n className={cn(styles, \"w-full text-inherit! no-underline!\")}\n href={href}\n to={href}\n /**\n * For some reason we need this here to prevent the outer link\n * from being clicked (thereby going to the worker details\n * instead of visiting the link)\n */\n onClick={(e) => e.stopPropagation()}\n >\n {innerContent}\n </LinkComponent>\n );\n }, [href, IconComponent, children, selected, variant, LinkComponent]);\n\n // When href is provided, content already contains children via innerContent\n // When render prop is provided, caller controls children rendering\n // Only pass children directly when neither href nor render is used\n const useRenderProp = href || render;\n\n return (\n <DropdownMenuPrimitive.Item\n ref={ref}\n className={cn(\n \"relative flex cursor-default items-center rounded-md px-2 py-1.5 text-base outline-hidden select-none focus:text-sf-default data-disabled:pointer-events-none data-disabled:opacity-50 data-highlighted:bg-sf-overlay\",\n inset && \"pl-8\",\n dropdownVariants({ variant }),\n className\n )}\n render={href ? content : render}\n {...props}\n >\n {useRenderProp ? undefined : children}\n </DropdownMenuPrimitive.Item>\n );\n }\n);\n\nDropdownMenuItem.displayName = DropdownMenuPrimitive.Item.displayName;\n\nconst DropdownMenuCheckboxItem = React.forwardRef<\n React.ElementRef<typeof DropdownMenuPrimitive.CheckboxItem>,\n React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.CheckboxItem>\n>(({ className, children, checked, ...props }, ref) => (\n <DropdownMenuPrimitive.CheckboxItem\n ref={ref}\n className={cn(\n \"relative flex cursor-default items-center rounded-sm py-1.5 pr-2 pl-8 text-base outline-hidden transition-colors select-none focus:bg-sf-tint focus:text-sf-default data-disabled:pointer-events-none data-disabled:opacity-50\",\n className\n )}\n checked={checked}\n {...props}\n >\n <span className=\"absolute left-2 flex h-3.5 w-3.5 items-center justify-center text-inherit\">\n <Checkbox checked={checked} />\n </span>\n {children}\n </DropdownMenuPrimitive.CheckboxItem>\n));\nDropdownMenuCheckboxItem.displayName =\n DropdownMenuPrimitive.CheckboxItem.displayName;\n\nconst DropdownMenuLabel = React.forwardRef<\n React.ElementRef<typeof DropdownMenuPrimitive.GroupLabel>,\n React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.GroupLabel> & {\n inset?: boolean;\n }\n>(({ className, inset, ...props }, ref) => (\n <DropdownMenuPrimitive.GroupLabel\n ref={ref}\n className={cn(\n \"px-2 py-1.5 text-base font-semibold\",\n inset && \"pl-8\",\n className\n )}\n {...props}\n />\n));\nDropdownMenuLabel.displayName = DropdownMenuPrimitive.GroupLabel.displayName;\n\nconst DropdownMenuSeparator = React.forwardRef<\n React.ElementRef<typeof DropdownMenuPrimitive.Separator>,\n React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Separator>\n>(({ className, ...props }, ref) => (\n <DropdownMenuPrimitive.Separator\n ref={ref}\n className={cn(\"-mx-1 my-1 h-px bg-sf-line\", className)}\n {...props}\n />\n));\nDropdownMenuSeparator.displayName = DropdownMenuPrimitive.Separator.displayName;\n\nconst DropdownMenuShortcut = ({\n className,\n ...props\n}: React.HTMLAttributes<HTMLSpanElement>) => {\n return (\n <span\n className={cn(\"ml-auto text-xs tracking-widest opacity-60\", className)}\n {...props}\n />\n );\n};\nDropdownMenuShortcut.displayName = \"DropdownMenuShortcut\";\n\nconst DropdownMenuRadioItem = React.forwardRef<\n React.ElementRef<typeof DropdownMenuPrimitive.RadioItem>,\n React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.RadioItem> & {\n inset?: boolean;\n icon?: Icon | React.ReactNode;\n }\n>(({ className, children, inset, icon: IconComponent, ...props }, ref) => (\n <DropdownMenuPrimitive.RadioItem\n ref={ref}\n className={cn(\n \"relative flex cursor-default items-center rounded-md px-2 py-1.5 text-base outline-hidden select-none\",\n \"data-disabled:pointer-events-none data-disabled:opacity-50 data-highlighted:bg-sf-tint\",\n inset && \"pl-8\",\n className\n )}\n {...props}\n >\n {IconComponent && renderIconNode(IconComponent)}\n {children}\n </DropdownMenuPrimitive.RadioItem>\n));\nDropdownMenuRadioItem.displayName = \"DropdownMenuRadioItem\";\n\nconst DropdownMenuRadioItemIndicator = React.forwardRef<\n React.ElementRef<typeof DropdownMenuPrimitive.RadioItemIndicator>,\n React.ComponentPropsWithoutRef<\n typeof DropdownMenuPrimitive.RadioItemIndicator\n >\n>(({ className, children, ...props }, ref) => (\n <DropdownMenuPrimitive.RadioItemIndicator\n ref={ref}\n className={cn(\"ml-auto\", className)}\n {...props}\n >\n {children ?? <Check className=\"h-4 w-4\" />}\n </DropdownMenuPrimitive.RadioItemIndicator>\n));\nDropdownMenuRadioItemIndicator.displayName = \"DropdownMenuRadioItemIndicator\";\n\n/**\n * Custom Trigger that converts a single child element to the `render` prop\n * to avoid nested button issues with base-ui's Menu.Trigger.\n */\nconst DropdownMenuTrigger = React.forwardRef<\n HTMLButtonElement,\n React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Trigger>\n>(({ children, render, ...props }, ref) => {\n // If render prop is provided, use it directly\n // Otherwise, convert single child element to render prop\n const childElement = React.isValidElement(children) ? children : null;\n const effectiveRender = render ?? childElement;\n\n return (\n <DropdownMenuPrimitive.Trigger\n ref={ref}\n {...props}\n {...(effectiveRender && {\n render: effectiveRender as React.ReactElement<Record<string, unknown>>,\n })}\n >\n {/* Only pass children if not using as render prop */}\n {childElement ? undefined : children}\n </DropdownMenuPrimitive.Trigger>\n );\n});\nDropdownMenuTrigger.displayName = \"DropdownMenuTrigger\";\n\n/**\n * DropdownMenu — accessible dropdown menu anchored to a trigger.\n *\n * Compound component: `DropdownMenu` (Root), `.Trigger`, `.Content`, `.Item`,\n * `.CheckboxItem`, `.RadioGroup`, `.RadioItem`, `.RadioItemIndicator`,\n * `.Sub`, `.SubTrigger`, `.SubContent`, `.Label`, `.Separator`, `.Shortcut`, `.Group`.\n *\n * Built on `@base-ui/react/menu`.\n *\n * @example\n * ```tsx\n * <DropdownMenu>\n * <DropdownMenu.Trigger>\n * <Button>Actions</Button>\n * </DropdownMenu.Trigger>\n * <DropdownMenu.Content>\n * <DropdownMenu.Item>Edit</DropdownMenu.Item>\n * <DropdownMenu.Item icon={CopyIcon}>Duplicate</DropdownMenu.Item>\n * <DropdownMenu.Separator />\n * <DropdownMenu.Item variant=\"danger\">Delete</DropdownMenu.Item>\n * </DropdownMenu.Content>\n * </DropdownMenu>\n * ```\n *\n * @see https://base-ui.com/react/components/menu\n */\nexport const DropdownMenu = Object.assign(DropdownMenuPrimitive.Root, {\n Trigger: DropdownMenuTrigger,\n Portal: DropdownMenuPrimitive.Portal,\n Sub: DropdownMenuPrimitive.SubmenuRoot,\n SubTrigger: DropdownMenuSubTrigger,\n SubContent: DropdownMenuContent,\n Content: DropdownMenuContent,\n Item: DropdownMenuItem,\n CheckboxItem: DropdownMenuCheckboxItem,\n RadioGroup: DropdownMenuPrimitive.RadioGroup,\n RadioItem: DropdownMenuRadioItem,\n RadioItemIndicator: DropdownMenuRadioItemIndicator,\n Label: DropdownMenuLabel,\n Separator: DropdownMenuSeparator,\n Shortcut: DropdownMenuShortcut,\n Group: DropdownMenuPrimitive.Group,\n});\n"],"mappings":"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"}
@@ -1,43 +1,9 @@
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, useEffect, useRef } from "react";
4
4
  import { jsx } from "react/jsx-runtime";
5
5
  //#region src/components/chart/color.ts
6
6
  /**
7
- * Categorical colors for light mode — used when assigning colors to data series
8
- * by index (e.g. the first series gets Blue, the second gets Violet, etc.).
9
- */
10
- var ChartCategoricalLightColors = /* @__PURE__ */ function(ChartCategoricalLightColors) {
11
- ChartCategoricalLightColors["Blue"] = "#086FFF";
12
- ChartCategoricalLightColors["Violet"] = "#CF7EE9";
13
- ChartCategoricalLightColors["Cyan"] = "#73CEE6";
14
- ChartCategoricalLightColors["Indigo"] = "#5B5FEF";
15
- ChartCategoricalLightColors["LightBlue"] = "#82B6FF";
16
- ChartCategoricalLightColors["Pink"] = "#F5609F";
17
- ChartCategoricalLightColors["Indigo3"] = "#C2BDF3";
18
- ChartCategoricalLightColors["Violet2"] = "#8D1EB1";
19
- ChartCategoricalLightColors["Violet3"] = "#EBCAF6";
20
- ChartCategoricalLightColors["Indigo2"] = "#7366E4";
21
- return ChartCategoricalLightColors;
22
- }(ChartCategoricalLightColors || {});
23
- /**
24
- * Categorical colors for dark mode — same hues as the light palette but with
25
- * `E6` alpha (90% opacity) appended to soften contrast on dark backgrounds.
26
- */
27
- var ChartCategoricalDarkColors = /* @__PURE__ */ function(ChartCategoricalDarkColors) {
28
- ChartCategoricalDarkColors["Blue"] = "#086FFFE6";
29
- ChartCategoricalDarkColors["Violet"] = "#CF7EE9E6";
30
- ChartCategoricalDarkColors["Cyan"] = "#73CEE6E6";
31
- ChartCategoricalDarkColors["Indigo"] = "#5B5FEFE6";
32
- ChartCategoricalDarkColors["LightBlue"] = "#82B6FFE6";
33
- ChartCategoricalDarkColors["Pink"] = "#F5609FE6";
34
- ChartCategoricalDarkColors["Indigo3"] = "#C2BDF3E6";
35
- ChartCategoricalDarkColors["Violet2"] = "#8D1EB1E6";
36
- ChartCategoricalDarkColors["Violet3"] = "#EBCAF6E6";
37
- ChartCategoricalDarkColors["Indigo2"] = "#7366E4E6";
38
- return ChartCategoricalDarkColors;
39
- }(ChartCategoricalDarkColors || {});
40
- /**
41
7
  * Semantic colors for light mode — used to convey meaning (status, severity)
42
8
  * rather than just distinguishing series. Use via `ChartPalette.semantic()`.
43
9
  */
@@ -68,32 +34,32 @@ var ChartSemanticDarkColors = /* @__PURE__ */ function(ChartSemanticDarkColors)
68
34
  * Used as the default ECharts color palette when `isDarkMode` is `false`.
69
35
  */
70
36
  var CHART_LIGHT_COLORS = [
71
- ChartCategoricalLightColors.Blue,
72
- ChartCategoricalLightColors.Violet,
73
- ChartCategoricalLightColors.Cyan,
74
- ChartCategoricalLightColors.Indigo,
75
- ChartCategoricalLightColors.LightBlue,
76
- ChartCategoricalLightColors.Pink,
77
- ChartCategoricalLightColors.Indigo3,
78
- ChartCategoricalLightColors.Violet2,
79
- ChartCategoricalLightColors.Violet3,
80
- ChartCategoricalLightColors.Indigo2
37
+ "#086FFF",
38
+ "#CF7EE9",
39
+ "#73CEE6",
40
+ "#5B5FEF",
41
+ "#82B6FF",
42
+ "#F5609F",
43
+ "#C2BDF3",
44
+ "#8D1EB1",
45
+ "#EBCAF6",
46
+ "#7366E4"
81
47
  ];
82
48
  /**
83
49
  * Ordered list of categorical colors for dark mode, indexed by series position.
84
50
  * Used as the default ECharts color palette when `isDarkMode` is `true`.
85
51
  */
86
52
  var CHART_DARK_COLORS = [
87
- ChartCategoricalDarkColors.Blue,
88
- ChartCategoricalDarkColors.Violet,
89
- ChartCategoricalDarkColors.Cyan,
90
- ChartCategoricalDarkColors.Indigo,
91
- ChartCategoricalDarkColors.LightBlue,
92
- ChartCategoricalDarkColors.Pink,
93
- ChartCategoricalDarkColors.Indigo3,
94
- ChartCategoricalDarkColors.Violet2,
95
- ChartCategoricalDarkColors.Violet3,
96
- ChartCategoricalDarkColors.Indigo2
53
+ "#086FFFE6",
54
+ "#CF7EE9E6",
55
+ "#73CEE6E6",
56
+ "#5B5FEFE6",
57
+ "#82B6FFE6",
58
+ "#F5609FE6",
59
+ "#C2BDF3E6",
60
+ "#8D1EB1E6",
61
+ "#EBCAF6E6",
62
+ "#7366E4E6"
97
63
  ];
98
64
  /**
99
65
  * Returns the hex color for a named semantic value (status, severity, etc.).
@@ -215,7 +181,7 @@ var ChartPalette = {
215
181
  * />
216
182
  * ```
217
183
  */
218
- var Chart = forwardRef(function Chart({ echarts, options, optionUpdateBehavior, className, isDarkMode, height = 350, onEvents }, ref) {
184
+ var Chart = forwardRef(({ echarts, options, optionUpdateBehavior, className, isDarkMode, height = 350, onEvents }, ref) => {
219
185
  const elRef = useRef(null);
220
186
  const chartRef = useRef(null);
221
187
  const handlersRef = useRef({});
@@ -311,4 +277,4 @@ Chart.displayName = "Chart";
311
277
  //#endregion
312
278
  export { ChartPalette as i, CHART_DARK_COLORS as n, CHART_LIGHT_COLORS as r, Chart as t };
313
279
 
314
- //# sourceMappingURL=echart-CdOUaT-r.js.map
280
+ //# sourceMappingURL=echart-DGBIVAv1.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"echart-CdOUaT-r.js","names":[],"sources":["../src/components/chart/color.ts","../src/components/chart/echart.tsx"],"sourcesContent":["/**\n * Categorical colors for light mode — used when assigning colors to data series\n * by index (e.g. the first series gets Blue, the second gets Violet, etc.).\n */\nenum ChartCategoricalLightColors {\n Blue = \"#086FFF\",\n Violet = \"#CF7EE9\",\n Cyan = \"#73CEE6\",\n Indigo = \"#5B5FEF\",\n LightBlue = \"#82B6FF\",\n Pink = \"#F5609F\",\n Indigo3 = \"#C2BDF3\",\n Violet2 = \"#8D1EB1\",\n Violet3 = \"#EBCAF6\",\n Indigo2 = \"#7366E4\",\n}\n\n/**\n * Categorical colors for dark mode — same hues as the light palette but with\n * `E6` alpha (90% opacity) appended to soften contrast on dark backgrounds.\n */\nenum ChartCategoricalDarkColors {\n Blue = \"#086FFFE6\",\n Violet = \"#CF7EE9E6\",\n Cyan = \"#73CEE6E6\",\n Indigo = \"#5B5FEFE6\",\n LightBlue = \"#82B6FFE6\",\n Pink = \"#F5609FE6\",\n Indigo3 = \"#C2BDF3E6\",\n Violet2 = \"#8D1EB1E6\",\n Violet3 = \"#EBCAF6E6\",\n Indigo2 = \"#7366E4E6\",\n}\n\n/**\n * Semantic colors for light mode — used to convey meaning (status, severity)\n * rather than just distinguishing series. Use via `ChartPalette.semantic()`.\n */\nenum ChartSemanticLightColors {\n Attention = \"#FC574A\",\n Warning = \"#F8A054\",\n Neutral = \"#82B6FF\",\n NeutralLight = \"#B9D6FF\",\n Disabled = \"#B6B6B6\",\n DisabledLight = \"#D9D9D9\",\n}\n\n/**\n * Semantic colors for dark mode — same meanings as the light palette but with\n * `E6` alpha (90% opacity) for dark backgrounds.\n */\nenum ChartSemanticDarkColors {\n Attention = \"#FC574AE6\",\n Warning = \"#F8A054E6\",\n Neutral = \"#82B6FFE6\",\n NeutralLight = \"#B9D6FFE6\",\n Disabled = \"#B6B6B6E6\",\n DisabledLight = \"#D9D9D9E6\",\n}\n\n/**\n * Ordered list of categorical colors for light mode, indexed by series position.\n * Used as the default ECharts color palette when `isDarkMode` is `false`.\n */\nexport const CHART_LIGHT_COLORS = [\n ChartCategoricalLightColors.Blue,\n ChartCategoricalLightColors.Violet,\n ChartCategoricalLightColors.Cyan,\n ChartCategoricalLightColors.Indigo,\n ChartCategoricalLightColors.LightBlue,\n ChartCategoricalLightColors.Pink,\n ChartCategoricalLightColors.Indigo3,\n ChartCategoricalLightColors.Violet2,\n ChartCategoricalLightColors.Violet3,\n ChartCategoricalLightColors.Indigo2,\n];\n\n/**\n * Ordered list of categorical colors for dark mode, indexed by series position.\n * Used as the default ECharts color palette when `isDarkMode` is `true`.\n */\nexport const CHART_DARK_COLORS = [\n ChartCategoricalDarkColors.Blue,\n ChartCategoricalDarkColors.Violet,\n ChartCategoricalDarkColors.Cyan,\n ChartCategoricalDarkColors.Indigo,\n ChartCategoricalDarkColors.LightBlue,\n ChartCategoricalDarkColors.Pink,\n ChartCategoricalDarkColors.Indigo3,\n ChartCategoricalDarkColors.Violet2,\n ChartCategoricalDarkColors.Violet3,\n ChartCategoricalDarkColors.Indigo2,\n];\n\n/**\n * Returns the hex color for a named semantic value (status, severity, etc.).\n *\n * @example\n * ```ts\n * ChartPalette.semantic(\"Attention\") // \"#FC574A\" (light)\n * ChartPalette.semantic(\"Warning\", true) // \"#F8A054E6\" (dark)\n * ```\n */\nfunction semantic(\n name:\n | \"Attention\"\n | \"Warning\"\n | \"Neutral\"\n | \"NeutralLight\"\n | \"Disabled\"\n | \"DisabledLight\",\n isDarkMode = false\n) {\n return isDarkMode\n ? ChartSemanticDarkColors[name]\n : ChartSemanticLightColors[name];\n}\n\n/**\n * Returns the categorical color for a given series index.\n * Wraps around via modulo when `index` exceeds the palette length (10 colors).\n *\n * @example\n * ```ts\n * ChartPalette.color(0) // Blue (light)\n * ChartPalette.color(0, true) // Blue with E6 alpha (dark)\n * ChartPalette.color(10) // wraps back to Blue\n * ```\n */\nfunction color(index: number, isDarkMode = false) {\n return isDarkMode\n ? CHART_DARK_COLORS[index % CHART_DARK_COLORS.length]\n : CHART_LIGHT_COLORS[index % CHART_LIGHT_COLORS.length];\n}\n\n/**\n * Returns a stable list of categorical colors for a given set of series names.\n * Names are assigned colors by their position in the input array (not by hash),\n * so the same index always maps to the same palette slot.\n *\n * @example\n * ```ts\n * ChartPalette.forSeriesNames([\"prod\", \"staging\", \"dev\"])\n * // → [\"#086FFF\", \"#CF7EE9\", \"#73CEE6\"]\n * ```\n */\nfunction forSeriesNames(names: string[], isDarkMode = false): string[] {\n const palette = isDarkMode ? CHART_DARK_COLORS : CHART_LIGHT_COLORS;\n return names.map((_name, index) => palette[index % palette.length]);\n}\n\n/**\n * Dim axis line / split line color for charts. Matches the `sf-line` token\n * aesthetic (soft, ~0.5 alpha neutral) so axis rules don't compete with series.\n *\n * ECharts doesn't read CSS custom properties for stroke colors, so we emit\n * hex+alpha values here directly.\n *\n * @example\n * ```ts\n * ChartPalette.axisLine() // \"#000000\" at ~8% alpha (light)\n * ChartPalette.axisLine(true) // \"#ffffff\" at ~10% alpha (dark)\n * ```\n */\nfunction axisLine(isDarkMode = false) {\n return isDarkMode ? \"#ffffff33\" : \"#00000014\";\n}\n\n/**\n * Shared ECharts axis config block for dim grid lines and hidden axis\n * chrome. Spread into `xAxis` / `yAxis` to give every chart the same quiet,\n * flat look.\n *\n * @example\n * ```ts\n * xAxis: { ...axisDefaults(isDarkMode), type: \"category\", data: [...] }\n * yAxis: { ...axisDefaults(isDarkMode), type: \"value\" }\n * ```\n */\nfunction axisDefaults(isDarkMode = false) {\n return {\n axisLine: { show: false },\n axisTick: { show: false },\n splitLine: {\n show: true,\n lineStyle: {\n color: axisLine(isDarkMode),\n type: \"dashed\" as const,\n width: 1,\n },\n },\n };\n}\n\n/**\n * Utilities for resolving SignalFlare chart colors by semantic name or series index.\n * Both functions accept an `isDarkMode` flag and return the appropriate hex color.\n */\nexport const ChartPalette = {\n semantic,\n color,\n forSeriesNames,\n axisLine,\n axisDefaults,\n};\n","import type { EChartsOption, SetOptionOpts } from \"echarts\";\nimport type * as echarts from \"echarts/core\";\nimport { forwardRef, useEffect, useRef } from \"react\";\n\nimport { cn } from \"../../utils\";\nimport { CHART_DARK_COLORS, CHART_LIGHT_COLORS } from \"./color\";\n\n/** Parameters passed to mouse event handlers on chart elements */\ntype EChartsMouseEventParams = {\n /** The type of component that triggered the event (e.g. \"series\", \"markPoint\") */\n componentType: string;\n /** Series type (e.g. \"line\", \"bar\") — present when componentType is \"series\" */\n seriesType?: string;\n /** Zero-based index of the series in the option.series array */\n seriesIndex?: number;\n /** Name of the series */\n seriesName?: string;\n /** Name of the data item */\n name?: string;\n /** Zero-based index of the data item within its series */\n dataIndex?: number;\n /** Raw data item value */\n data?: any;\n /** Sub-type of data (e.g. \"node\", \"edge\" for graph series) */\n dataType?: string;\n /** Numeric or array value of the data item */\n value?: number | any[];\n /** Resolved color of the series or data item */\n color?: string;\n};\n\n/**\n * ECharts event handlers that can be attached to a `Chart`.\n * Pass a subset via the `onEvents` prop; handlers are registered lazily and\n * cleaned up automatically when removed or when the chart is unmounted.\n */\nexport interface ChartEvents {\n // Mouse events — fired on chart elements (series, marks, etc.)\n click: (params: EChartsMouseEventParams) => void;\n dblclick: (params: EChartsMouseEventParams) => void;\n mousedown: (params: EChartsMouseEventParams) => void;\n mousemove: (params: EChartsMouseEventParams) => void;\n mouseup: (params: EChartsMouseEventParams) => void;\n mouseover: (params: EChartsMouseEventParams) => void;\n mouseout: (params: EChartsMouseEventParams) => void;\n /** Fired when the pointer leaves the chart canvas entirely */\n globalout: (params: any) => void;\n contextmenu: (params: any) => void;\n\n // Legend events\n /** Fired when any legend item's selected state changes */\n legendselectchanged: (params: {\n name: string;\n /** Map of series name → selected state for all legend items */\n selected: Record<string, boolean>;\n }) => void;\n legendselected: (params: any) => void;\n legendunselected: (params: any) => void;\n legendscroll: (params: any) => void;\n\n // Data zoom / timeline events\n datazoom: (params: any) => void;\n datarangeselected: (params: any) => void;\n timelinechanged: (params: any) => void;\n timelineplaychanged: (params: any) => void;\n\n // Toolbox events\n restore: (params: any) => void;\n dataviewchanged: (params: any) => void;\n magictypechanged: (params: any) => void;\n\n // Pie chart selection events\n pieselectchanged: (params: any) => void;\n pieselected: (params: any) => void;\n pieunselected: (params: any) => void;\n\n // Map / geo selection events\n mapselectchanged: (params: any) => void;\n mapselected: (params: any) => void;\n mapunselected: (params: any) => void;\n geoselectchanged: (params: any) => void;\n geoselected: (params: any) => void;\n geounselected: (params: any) => void;\n\n axisareaselected: (params: any) => void;\n\n // Brush / selection events\n brush: (params: any) => void;\n brushselected: (params: any) => void;\n /** Fired when the user finishes drawing a brush selection */\n brushend: (params: {\n areas: Array<{\n /** Coordinate range covered by the brush — interpretation depends on axis type */\n coordRange: any;\n brushType?: string;\n panelId?: string;\n range?: any;\n }>;\n }) => void;\n}\n\n/** Props for the low-level `Chart` wrapper around Apache ECharts */\nexport interface ChartProps {\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 /** ECharts option object — passed through to `chart.setOption()` */\n options: EChartsOption;\n /**\n * Additional options passed as the second argument to `chart.setOption()`.\n * Defaults to `{ notMerge: false, lazyUpdate: true }`.\n */\n optionUpdateBehavior?: SetOptionOpts;\n /** Additional CSS classes applied to the chart container `<div>` */\n className?: string;\n /**\n * When `true`, initialises ECharts with its built-in dark theme.\n * Changing this value after mount destroys and re-creates the chart instance.\n */\n isDarkMode?: boolean;\n /** Height of the chart container in pixels. Defaults to `350`. */\n height?: number;\n /** Subset of ECharts events to listen for. Handlers are bound/unbound reactively. */\n onEvents?: Partial<ChartEvents>;\n}\n\n/**\n * Chart — a low-level wrapper around [Apache ECharts](https://echarts.apache.org).\n *\n * Manages the ECharts instance lifecycle (init, option updates, event binding,\n * resize observation, and disposal). Exposes the raw `echarts.ECharts` instance\n * via `ref` for imperative access when needed.\n *\n * Prefer `TimeseriesChart` for time-series data; use this component when you\n * need full control over the ECharts option object.\n *\n * @example\n * ```tsx\n * import * as echarts from \"echarts/core\";\n * import { BarChart } from \"echarts/charts\";\n * import { GridComponent } from \"echarts/components\";\n * import { CanvasRenderer } from \"echarts/renderers\";\n *\n * echarts.use([BarChart, GridComponent, CanvasRenderer]);\n *\n * <Chart\n * echarts={echarts}\n * options={{ xAxis: { data: [\"A\", \"B\"] }, yAxis: {}, series: [{ type: \"bar\", data: [1, 2] }] }}\n * />\n * ```\n */\nexport const Chart = forwardRef<echarts.ECharts, ChartProps>(function Chart(\n {\n echarts,\n options,\n optionUpdateBehavior,\n className,\n isDarkMode,\n height = 350,\n onEvents,\n }: ChartProps,\n ref\n) {\n // Ref to the container DOM node that ECharts renders into\n const elRef = useRef<HTMLDivElement | null>(null);\n // Ref to the active ECharts instance\n const chartRef = useRef<echarts.ECharts | null>(null);\n // Keeps the latest onEvents object without triggering re-binding on every render\n const handlersRef = useRef<Partial<ChartEvents>>({});\n // Stable wrapper functions per event name — avoids creating new closures on re-render\n const wrappersRef = useRef<Record<string, (params: any) => void>>({});\n // Tracks which event names are currently bound to the chart instance\n const boundEventsRef = useRef<Set<string>>(new Set());\n\n // Init and cleanup\n useEffect(() => {\n if (!elRef.current) return;\n\n const chart = echarts.init(elRef.current, undefined, {\n useDirtyRect: false,\n });\n const textColor = isDarkMode ? \"#e5e5e5\" : \"#1a1a1a\";\n chart.setOption({\n color: isDarkMode ? CHART_DARK_COLORS : CHART_LIGHT_COLORS,\n backgroundColor: \"transparent\",\n textStyle: { color: textColor },\n });\n chartRef.current = chart;\n\n if (typeof ref === \"function\") ref(chart);\n else if (ref) ref.current = chart;\n\n return () => {\n for (const event of boundEventsRef.current) {\n const wrapper = wrappersRef.current[event];\n if (wrapper) chart.off(event, wrapper);\n }\n boundEventsRef.current.clear();\n if (typeof ref === \"function\") ref(null);\n else if (ref) ref.current = null;\n chartRef.current = null;\n chart.dispose();\n };\n }, [elRef, isDarkMode]);\n\n // Update options\n useEffect(() => {\n const chart = chartRef.current;\n if (!chart) return;\n\n chart.setOption(options, {\n notMerge: false,\n lazyUpdate: true,\n ...optionUpdateBehavior,\n });\n }, [isDarkMode, optionUpdateBehavior, options]);\n\n // Keep handlersRef in sync so wrapper closures always call the latest handler\n // without needing to re-bind listeners on every render\n useEffect(() => {\n handlersRef.current = onEvents ?? {};\n }, [onEvents]);\n\n // Reactively bind and unbind event listeners when onEvents changes.\n // Uses stable wrapper functions (wrappersRef) so the same function reference\n // is passed to both chart.on() and chart.off(), which ECharts requires.\n useEffect(() => {\n const chart = chartRef.current;\n if (!chart) return;\n\n const nextBound = new Set<string>();\n\n for (const [event, handler] of Object.entries(onEvents ?? {})) {\n if (typeof handler !== \"function\") continue;\n nextBound.add(event);\n\n if (!wrappersRef.current[event]) {\n wrappersRef.current[event] = (params: any) => {\n const current = handlersRef.current as Record<\n string,\n ((p: any) => void) | undefined\n >;\n current[event]?.(params);\n };\n }\n\n if (!boundEventsRef.current.has(event)) {\n chart.on(event, wrappersRef.current[event]);\n }\n }\n\n for (const event of boundEventsRef.current) {\n if (nextBound.has(event)) continue;\n const wrapper = wrappersRef.current[event];\n if (wrapper) {\n chart.off(event, wrapper);\n }\n }\n\n boundEventsRef.current = nextBound;\n }, [echarts, isDarkMode, onEvents]);\n\n // Resize handling\n useEffect(() => {\n const chart = chartRef.current;\n const el = elRef.current;\n if (!chart || !el) return;\n\n // Flag to skip the very first trigger\n let isInitial = true;\n\n const ro = new ResizeObserver(() => {\n if (isInitial) {\n isInitial = false;\n return; // Skip the first resize to let the animation play\n }\n chart.resize();\n });\n\n ro.observe(el);\n\n return () => ro.disconnect();\n }, []);\n\n return (\n <div\n ref={elRef}\n className={cn(\"w-full\", className)}\n style={{ height }}\n tabIndex={options.aria?.enabled ? 0 : undefined}\n role={options.aria?.enabled ? \"img\" : undefined}\n />\n );\n});\n\nChart.displayName = \"Chart\";\n"],"mappings":"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"}
1
+ {"version":3,"file":"echart-DGBIVAv1.js","names":[],"sources":["../src/components/chart/color.ts","../src/components/chart/echart.tsx"],"sourcesContent":["/**\n * Categorical colors for light mode — used when assigning colors to data series\n * by index (e.g. the first series gets Blue, the second gets Violet, etc.).\n */\nenum ChartCategoricalLightColors {\n Blue = \"#086FFF\",\n Violet = \"#CF7EE9\",\n Cyan = \"#73CEE6\",\n Indigo = \"#5B5FEF\",\n LightBlue = \"#82B6FF\",\n Pink = \"#F5609F\",\n Indigo3 = \"#C2BDF3\",\n Violet2 = \"#8D1EB1\",\n Violet3 = \"#EBCAF6\",\n Indigo2 = \"#7366E4\",\n}\n\n/**\n * Categorical colors for dark mode — same hues as the light palette but with\n * `E6` alpha (90% opacity) appended to soften contrast on dark backgrounds.\n */\nenum ChartCategoricalDarkColors {\n Blue = \"#086FFFE6\",\n Violet = \"#CF7EE9E6\",\n Cyan = \"#73CEE6E6\",\n Indigo = \"#5B5FEFE6\",\n LightBlue = \"#82B6FFE6\",\n Pink = \"#F5609FE6\",\n Indigo3 = \"#C2BDF3E6\",\n Violet2 = \"#8D1EB1E6\",\n Violet3 = \"#EBCAF6E6\",\n Indigo2 = \"#7366E4E6\",\n}\n\n/**\n * Semantic colors for light mode — used to convey meaning (status, severity)\n * rather than just distinguishing series. Use via `ChartPalette.semantic()`.\n */\nenum ChartSemanticLightColors {\n Attention = \"#FC574A\",\n Warning = \"#F8A054\",\n Neutral = \"#82B6FF\",\n NeutralLight = \"#B9D6FF\",\n Disabled = \"#B6B6B6\",\n DisabledLight = \"#D9D9D9\",\n}\n\n/**\n * Semantic colors for dark mode — same meanings as the light palette but with\n * `E6` alpha (90% opacity) for dark backgrounds.\n */\nenum ChartSemanticDarkColors {\n Attention = \"#FC574AE6\",\n Warning = \"#F8A054E6\",\n Neutral = \"#82B6FFE6\",\n NeutralLight = \"#B9D6FFE6\",\n Disabled = \"#B6B6B6E6\",\n DisabledLight = \"#D9D9D9E6\",\n}\n\n/**\n * Ordered list of categorical colors for light mode, indexed by series position.\n * Used as the default ECharts color palette when `isDarkMode` is `false`.\n */\nexport const CHART_LIGHT_COLORS = [\n ChartCategoricalLightColors.Blue,\n ChartCategoricalLightColors.Violet,\n ChartCategoricalLightColors.Cyan,\n ChartCategoricalLightColors.Indigo,\n ChartCategoricalLightColors.LightBlue,\n ChartCategoricalLightColors.Pink,\n ChartCategoricalLightColors.Indigo3,\n ChartCategoricalLightColors.Violet2,\n ChartCategoricalLightColors.Violet3,\n ChartCategoricalLightColors.Indigo2,\n];\n\n/**\n * Ordered list of categorical colors for dark mode, indexed by series position.\n * Used as the default ECharts color palette when `isDarkMode` is `true`.\n */\nexport const CHART_DARK_COLORS = [\n ChartCategoricalDarkColors.Blue,\n ChartCategoricalDarkColors.Violet,\n ChartCategoricalDarkColors.Cyan,\n ChartCategoricalDarkColors.Indigo,\n ChartCategoricalDarkColors.LightBlue,\n ChartCategoricalDarkColors.Pink,\n ChartCategoricalDarkColors.Indigo3,\n ChartCategoricalDarkColors.Violet2,\n ChartCategoricalDarkColors.Violet3,\n ChartCategoricalDarkColors.Indigo2,\n];\n\n/**\n * Returns the hex color for a named semantic value (status, severity, etc.).\n *\n * @example\n * ```ts\n * ChartPalette.semantic(\"Attention\") // \"#FC574A\" (light)\n * ChartPalette.semantic(\"Warning\", true) // \"#F8A054E6\" (dark)\n * ```\n */\nfunction semantic(\n name:\n | \"Attention\"\n | \"Warning\"\n | \"Neutral\"\n | \"NeutralLight\"\n | \"Disabled\"\n | \"DisabledLight\",\n isDarkMode = false\n) {\n return isDarkMode\n ? ChartSemanticDarkColors[name]\n : ChartSemanticLightColors[name];\n}\n\n/**\n * Returns the categorical color for a given series index.\n * Wraps around via modulo when `index` exceeds the palette length (10 colors).\n *\n * @example\n * ```ts\n * ChartPalette.color(0) // Blue (light)\n * ChartPalette.color(0, true) // Blue with E6 alpha (dark)\n * ChartPalette.color(10) // wraps back to Blue\n * ```\n */\nfunction color(index: number, isDarkMode = false) {\n return isDarkMode\n ? CHART_DARK_COLORS[index % CHART_DARK_COLORS.length]\n : CHART_LIGHT_COLORS[index % CHART_LIGHT_COLORS.length];\n}\n\n/**\n * Returns a stable list of categorical colors for a given set of series names.\n * Names are assigned colors by their position in the input array (not by hash),\n * so the same index always maps to the same palette slot.\n *\n * @example\n * ```ts\n * ChartPalette.forSeriesNames([\"prod\", \"staging\", \"dev\"])\n * // → [\"#086FFF\", \"#CF7EE9\", \"#73CEE6\"]\n * ```\n */\nfunction forSeriesNames(names: string[], isDarkMode = false): string[] {\n const palette = isDarkMode ? CHART_DARK_COLORS : CHART_LIGHT_COLORS;\n return names.map((_name, index) => palette[index % palette.length]);\n}\n\n/**\n * Dim axis line / split line color for charts. Matches the `sf-line` token\n * aesthetic (soft, ~0.5 alpha neutral) so axis rules don't compete with series.\n *\n * ECharts doesn't read CSS custom properties for stroke colors, so we emit\n * hex+alpha values here directly.\n *\n * @example\n * ```ts\n * ChartPalette.axisLine() // \"#000000\" at ~8% alpha (light)\n * ChartPalette.axisLine(true) // \"#ffffff\" at ~10% alpha (dark)\n * ```\n */\nfunction axisLine(isDarkMode = false) {\n return isDarkMode ? \"#ffffff33\" : \"#00000014\";\n}\n\n/**\n * Shared ECharts axis config block for dim grid lines and hidden axis\n * chrome. Spread into `xAxis` / `yAxis` to give every chart the same quiet,\n * flat look.\n *\n * @example\n * ```ts\n * xAxis: { ...axisDefaults(isDarkMode), type: \"category\", data: [...] }\n * yAxis: { ...axisDefaults(isDarkMode), type: \"value\" }\n * ```\n */\nfunction axisDefaults(isDarkMode = false) {\n return {\n axisLine: { show: false },\n axisTick: { show: false },\n splitLine: {\n show: true,\n lineStyle: {\n color: axisLine(isDarkMode),\n type: \"dashed\" as const,\n width: 1,\n },\n },\n };\n}\n\n/**\n * Utilities for resolving SignalFlare chart colors by semantic name or series index.\n * Both functions accept an `isDarkMode` flag and return the appropriate hex color.\n */\nexport const ChartPalette = {\n semantic,\n color,\n forSeriesNames,\n axisLine,\n axisDefaults,\n};\n","import type { EChartsOption, SetOptionOpts } from \"echarts\";\nimport type * as echarts from \"echarts/core\";\nimport { forwardRef, useEffect, useRef } from \"react\";\n\nimport { cn } from \"../../utils\";\nimport { CHART_DARK_COLORS, CHART_LIGHT_COLORS } from \"./color\";\n\n/** Parameters passed to mouse event handlers on chart elements */\ntype EChartsMouseEventParams = {\n /** The type of component that triggered the event (e.g. \"series\", \"markPoint\") */\n componentType: string;\n /** Series type (e.g. \"line\", \"bar\") — present when componentType is \"series\" */\n seriesType?: string;\n /** Zero-based index of the series in the option.series array */\n seriesIndex?: number;\n /** Name of the series */\n seriesName?: string;\n /** Name of the data item */\n name?: string;\n /** Zero-based index of the data item within its series */\n dataIndex?: number;\n /** Raw data item value */\n data?: any;\n /** Sub-type of data (e.g. \"node\", \"edge\" for graph series) */\n dataType?: string;\n /** Numeric or array value of the data item */\n value?: number | any[];\n /** Resolved color of the series or data item */\n color?: string;\n};\n\n/**\n * ECharts event handlers that can be attached to a `Chart`.\n * Pass a subset via the `onEvents` prop; handlers are registered lazily and\n * cleaned up automatically when removed or when the chart is unmounted.\n */\nexport interface ChartEvents {\n // Mouse events — fired on chart elements (series, marks, etc.)\n click: (params: EChartsMouseEventParams) => void;\n dblclick: (params: EChartsMouseEventParams) => void;\n mousedown: (params: EChartsMouseEventParams) => void;\n mousemove: (params: EChartsMouseEventParams) => void;\n mouseup: (params: EChartsMouseEventParams) => void;\n mouseover: (params: EChartsMouseEventParams) => void;\n mouseout: (params: EChartsMouseEventParams) => void;\n /** Fired when the pointer leaves the chart canvas entirely */\n globalout: (params: any) => void;\n contextmenu: (params: any) => void;\n\n // Legend events\n /** Fired when any legend item's selected state changes */\n legendselectchanged: (params: {\n name: string;\n /** Map of series name → selected state for all legend items */\n selected: Record<string, boolean>;\n }) => void;\n legendselected: (params: any) => void;\n legendunselected: (params: any) => void;\n legendscroll: (params: any) => void;\n\n // Data zoom / timeline events\n datazoom: (params: any) => void;\n datarangeselected: (params: any) => void;\n timelinechanged: (params: any) => void;\n timelineplaychanged: (params: any) => void;\n\n // Toolbox events\n restore: (params: any) => void;\n dataviewchanged: (params: any) => void;\n magictypechanged: (params: any) => void;\n\n // Pie chart selection events\n pieselectchanged: (params: any) => void;\n pieselected: (params: any) => void;\n pieunselected: (params: any) => void;\n\n // Map / geo selection events\n mapselectchanged: (params: any) => void;\n mapselected: (params: any) => void;\n mapunselected: (params: any) => void;\n geoselectchanged: (params: any) => void;\n geoselected: (params: any) => void;\n geounselected: (params: any) => void;\n\n axisareaselected: (params: any) => void;\n\n // Brush / selection events\n brush: (params: any) => void;\n brushselected: (params: any) => void;\n /** Fired when the user finishes drawing a brush selection */\n brushend: (params: {\n areas: Array<{\n /** Coordinate range covered by the brush — interpretation depends on axis type */\n coordRange: any;\n brushType?: string;\n panelId?: string;\n range?: any;\n }>;\n }) => void;\n}\n\n/** Props for the low-level `Chart` wrapper around Apache ECharts */\nexport interface ChartProps {\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 /** ECharts option object — passed through to `chart.setOption()` */\n options: EChartsOption;\n /**\n * Additional options passed as the second argument to `chart.setOption()`.\n * Defaults to `{ notMerge: false, lazyUpdate: true }`.\n */\n optionUpdateBehavior?: SetOptionOpts;\n /** Additional CSS classes applied to the chart container `<div>` */\n className?: string;\n /**\n * When `true`, initialises ECharts with its built-in dark theme.\n * Changing this value after mount destroys and re-creates the chart instance.\n */\n isDarkMode?: boolean;\n /** Height of the chart container in pixels. Defaults to `350`. */\n height?: number;\n /** Subset of ECharts events to listen for. Handlers are bound/unbound reactively. */\n onEvents?: Partial<ChartEvents>;\n}\n\n/**\n * Chart — a low-level wrapper around [Apache ECharts](https://echarts.apache.org).\n *\n * Manages the ECharts instance lifecycle (init, option updates, event binding,\n * resize observation, and disposal). Exposes the raw `echarts.ECharts` instance\n * via `ref` for imperative access when needed.\n *\n * Prefer `TimeseriesChart` for time-series data; use this component when you\n * need full control over the ECharts option object.\n *\n * @example\n * ```tsx\n * import * as echarts from \"echarts/core\";\n * import { BarChart } from \"echarts/charts\";\n * import { GridComponent } from \"echarts/components\";\n * import { CanvasRenderer } from \"echarts/renderers\";\n *\n * echarts.use([BarChart, GridComponent, CanvasRenderer]);\n *\n * <Chart\n * echarts={echarts}\n * options={{ xAxis: { data: [\"A\", \"B\"] }, yAxis: {}, series: [{ type: \"bar\", data: [1, 2] }] }}\n * />\n * ```\n */\nexport const Chart = forwardRef<echarts.ECharts, ChartProps>(\n (\n {\n echarts,\n options,\n optionUpdateBehavior,\n className,\n isDarkMode,\n height = 350,\n onEvents,\n }: ChartProps,\n ref\n ) => {\n // Ref to the container DOM node that ECharts renders into\n const elRef = useRef<HTMLDivElement | null>(null);\n // Ref to the active ECharts instance\n const chartRef = useRef<echarts.ECharts | null>(null);\n // Keeps the latest onEvents object without triggering re-binding on every render\n const handlersRef = useRef<Partial<ChartEvents>>({});\n // Stable wrapper functions per event name — avoids creating new closures on re-render\n const wrappersRef = useRef<Record<string, (params: any) => void>>({});\n // Tracks which event names are currently bound to the chart instance\n const boundEventsRef = useRef<Set<string>>(new Set());\n\n // Init and cleanup\n useEffect(() => {\n if (!elRef.current) return;\n\n const chart = echarts.init(elRef.current, undefined, {\n useDirtyRect: false,\n });\n const textColor = isDarkMode ? \"#e5e5e5\" : \"#1a1a1a\";\n chart.setOption({\n color: isDarkMode ? CHART_DARK_COLORS : CHART_LIGHT_COLORS,\n backgroundColor: \"transparent\",\n textStyle: { color: textColor },\n });\n chartRef.current = chart;\n\n if (typeof ref === \"function\") ref(chart);\n else if (ref) ref.current = chart;\n\n return () => {\n for (const event of boundEventsRef.current) {\n const wrapper = wrappersRef.current[event];\n if (wrapper) chart.off(event, wrapper);\n }\n boundEventsRef.current.clear();\n if (typeof ref === \"function\") ref(null);\n else if (ref) ref.current = null;\n chartRef.current = null;\n chart.dispose();\n };\n }, [elRef, isDarkMode]);\n\n // Update options\n useEffect(() => {\n const chart = chartRef.current;\n if (!chart) return;\n\n chart.setOption(options, {\n notMerge: false,\n lazyUpdate: true,\n ...optionUpdateBehavior,\n });\n }, [isDarkMode, optionUpdateBehavior, options]);\n\n // Keep handlersRef in sync so wrapper closures always call the latest handler\n // without needing to re-bind listeners on every render\n useEffect(() => {\n handlersRef.current = onEvents ?? {};\n }, [onEvents]);\n\n // Reactively bind and unbind event listeners when onEvents changes.\n // Uses stable wrapper functions (wrappersRef) so the same function reference\n // is passed to both chart.on() and chart.off(), which ECharts requires.\n useEffect(() => {\n const chart = chartRef.current;\n if (!chart) return;\n\n const nextBound = new Set<string>();\n\n for (const [event, handler] of Object.entries(onEvents ?? {})) {\n if (typeof handler !== \"function\") continue;\n nextBound.add(event);\n\n if (!wrappersRef.current[event]) {\n wrappersRef.current[event] = (params: any) => {\n const current = handlersRef.current as Record<\n string,\n ((p: any) => void) | undefined\n >;\n current[event]?.(params);\n };\n }\n\n if (!boundEventsRef.current.has(event)) {\n chart.on(event, wrappersRef.current[event]);\n }\n }\n\n for (const event of boundEventsRef.current) {\n if (nextBound.has(event)) continue;\n const wrapper = wrappersRef.current[event];\n if (wrapper) {\n chart.off(event, wrapper);\n }\n }\n\n boundEventsRef.current = nextBound;\n }, [echarts, isDarkMode, onEvents]);\n\n // Resize handling\n useEffect(() => {\n const chart = chartRef.current;\n const el = elRef.current;\n if (!chart || !el) return;\n\n // Flag to skip the very first trigger\n let isInitial = true;\n\n const ro = new ResizeObserver(() => {\n if (isInitial) {\n isInitial = false;\n return; // Skip the first resize to let the animation play\n }\n chart.resize();\n });\n\n ro.observe(el);\n\n return () => ro.disconnect();\n }, []);\n\n return (\n <div\n ref={elRef}\n className={cn(\"w-full\", className)}\n style={{ height }}\n tabIndex={options.aria?.enabled ? 0 : undefined}\n role={options.aria?.enabled ? \"img\" : undefined}\n />\n );\n }\n);\n\nChart.displayName = \"Chart\";\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 Text } from "./text-Cqryz7rk.js";
4
- import { t as Button } from "./button-CO6-qPax.js";
2
+ import { t as cn } from "./cn-CmAOpn49.js";
3
+ import { t as Text } from "./text-iQ0YUFNg.js";
4
+ import { t as Button } from "./button-BHOgXJRU.js";
5
5
  import { useState } from "react";
6
6
  import { jsx, jsxs } from "react/jsx-runtime";
7
7
  import { CheckIcon, CopyIcon } from "@phosphor-icons/react";
@@ -41,12 +41,12 @@ function Empty({ icon, title, description, commandLine, contents, size = "base",
41
41
  icon,
42
42
  /* @__PURE__ */ jsx(Text, {
43
43
  variant: "heading2",
44
- wrap: "balance",
44
+ wrap: "natural",
45
45
  as: "h2",
46
46
  children: title
47
47
  }),
48
48
  description && /* @__PURE__ */ jsx(Text, {
49
- wrap: "balance",
49
+ wrap: "natural",
50
50
  as: "p",
51
51
  DANGEROUS_className: "max-w-140 text-center text-sf-strong",
52
52
  children: description
@@ -92,4 +92,4 @@ function Empty({ icon, title, description, commandLine, contents, size = "base",
92
92
  //#endregion
93
93
  export { emptyVariants as i, SF_EMPTY_DEFAULT_VARIANTS as n, SF_EMPTY_VARIANTS as r, Empty as t };
94
94
 
95
- //# sourceMappingURL=empty-DZnN0zKX.js.map
95
+ //# sourceMappingURL=empty-C1tAkawe.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"empty-DZnN0zKX.js","names":[],"sources":["../src/components/empty/empty.tsx"],"sourcesContent":["import { CheckIcon, CopyIcon } from \"@phosphor-icons/react\";\nimport { useState } from \"react\";\n\nimport { Button } from \"../../components/button\";\nimport { Text } from \"../../components/text\";\nimport { cn } from \"../../utils/cn\";\n\n/** Empty state size variant definitions mapping sizes to their Tailwind classes. */\nexport const SF_EMPTY_VARIANTS = {\n size: {\n sm: {\n classes: \"px-6 py-8 gap-4\",\n description: \"Compact empty state for smaller containers\",\n },\n base: {\n classes: \"px-10 py-16 gap-6\",\n description: \"Default empty state size\",\n },\n lg: {\n classes: \"px-12 py-20 gap-8\",\n description: \"Large empty state for prominent placement\",\n },\n },\n} as const;\n\nexport const SF_EMPTY_DEFAULT_VARIANTS = {\n size: \"base\",\n} as const;\n\nexport type SFEmptySize = keyof typeof SF_EMPTY_VARIANTS.size;\n\nexport interface SFEmptyVariantsProps {\n /**\n * Size of the empty state container.\n * - `\"sm\"` — Compact empty state for smaller containers\n * - `\"base\"` — Default empty state size\n * - `\"lg\"` — Large empty state for prominent placement\n * @default \"base\"\n */\n size?: SFEmptySize;\n}\n\nexport function emptyVariants({\n size = SF_EMPTY_DEFAULT_VARIANTS.size,\n}: SFEmptyVariantsProps = {}) {\n return cn(\n \"flex w-full flex-col items-center rounded-xl border border-sf-fill bg-sf-control text-sf-default\",\n SF_EMPTY_VARIANTS.size[size].classes\n );\n}\n\n/**\n * Empty state component props.\n *\n * @example\n * ```tsx\n * <Empty\n * icon={<PackageIcon size={48} />}\n * title=\"No packages found\"\n * description=\"Get started by installing your first package.\"\n * commandLine=\"npm install @signalflare-ai/ui\"\n * />\n * ```\n */\nexport interface EmptyProps extends SFEmptyVariantsProps {\n /** Decorative icon displayed above the title (e.g. from `@phosphor-icons/react`). */\n icon?: React.ReactNode;\n /** Primary heading text for the empty state. */\n title: string;\n /** Secondary description text displayed below the title. */\n description?: string;\n /** Shell command displayed in a copyable code block. */\n commandLine?: string;\n /** Additional content (buttons, links) rendered below the description. */\n contents?: React.ReactNode;\n /** Additional CSS classes merged via `cn()`. */\n className?: string;\n}\n\n/**\n * Placeholder shown when a list, table, or page has no content to display.\n *\n * @example\n * ```tsx\n * <Empty title=\"No results found\" description=\"Try adjusting your search.\" />\n * ```\n */\nexport function Empty({\n icon,\n title,\n description,\n commandLine,\n contents,\n size = \"base\",\n className,\n}: EmptyProps) {\n const [emptyStateCopied, setEmptyStateCopied] = useState<boolean>(false);\n\n return (\n <div className={cn(emptyVariants({ size }), className)}>\n {icon}\n <Text variant=\"heading2\" wrap=\"balance\" as=\"h2\">\n {title}\n </Text>\n\n {description && (\n <Text\n wrap=\"balance\"\n as=\"p\"\n DANGEROUS_className=\"max-w-140 text-center text-sf-strong\"\n >\n {description}\n </Text>\n )}\n\n {commandLine && (\n <div\n className={cn(\n \"group/cmd relative inline-flex h-10 max-w-8/10 transform-gpu items-center gap-2 rounded-lg font-mono shadow-sm\",\n \"bg-sf-overlay pr-2 pl-3\",\n \"transition-all duration-300 hover:border-sf-interact/80 hover:shadow-md\",\n \"border border-sf-fill/60\"\n )}\n >\n <span className=\"text-xs text-sf-inactive select-none\">$</span>\n <span className=\"no-scrollbar overflow-scroll text-[14px] whitespace-nowrap text-sf-brand\">\n {commandLine}\n </span>\n <Button\n className=\"group\"\n size=\"sm\"\n variant=\"ghost\"\n shape=\"square\"\n aria-label=\"Copy command\"\n onClick={async () => {\n setEmptyStateCopied(true);\n setTimeout(() => {\n setEmptyStateCopied(false);\n }, 1000);\n await navigator.clipboard.writeText(commandLine);\n }}\n >\n {emptyStateCopied ? (\n <CheckIcon\n size={16}\n className=\"animate-bounce-in text-sf-success\"\n />\n ) : (\n <CopyIcon\n size={16}\n className=\"text-sf-inactive group-hover:text-sf-brand\"\n />\n )}\n </Button>\n </div>\n )}\n\n {contents}\n </div>\n );\n}\n"],"mappings":";;;;;;;;;AAQA,IAAa,oBAAoB,EAC/B,MAAM;CACJ,IAAI;EACF,SAAS;EACT,aAAa;EACd;CACD,MAAM;EACJ,SAAS;EACT,aAAa;EACd;CACD,IAAI;EACF,SAAS;EACT,aAAa;EACd;CACF,EACF;AAED,IAAa,4BAA4B,EACvC,MAAM,QACP;AAeD,SAAgB,cAAc,EAC5B,OAAO,0BAA0B,SACT,EAAE,EAAE;AAC5B,QAAO,GACL,oGACA,kBAAkB,KAAK,MAAM,QAC9B;;;;;;;;;;AAuCH,SAAgB,MAAM,EACpB,MACA,OACA,aACA,aACA,UACA,OAAO,QACP,aACa;CACb,MAAM,CAAC,kBAAkB,uBAAuB,SAAkB,MAAM;AAExE,QACE,qBAAC,OAAD;EAAK,WAAW,GAAG,cAAc,EAAE,MAAM,CAAC,EAAE,UAAU;YAAtD;GACG;GACD,oBAAC,MAAD;IAAM,SAAQ;IAAW,MAAK;IAAU,IAAG;cACxC;IACI,CAAA;GAEN,eACC,oBAAC,MAAD;IACE,MAAK;IACL,IAAG;IACH,qBAAoB;cAEnB;IACI,CAAA;GAGR,eACC,qBAAC,OAAD;IACE,WAAW,GACT,kHACA,2BACA,2EACA,2BACD;cANH;KAQE,oBAAC,QAAD;MAAM,WAAU;gBAAuC;MAAQ,CAAA;KAC/D,oBAAC,QAAD;MAAM,WAAU;gBACb;MACI,CAAA;KACP,oBAAC,QAAD;MACE,WAAU;MACV,MAAK;MACL,SAAQ;MACR,OAAM;MACN,cAAW;MACX,SAAS,YAAY;AACnB,2BAAoB,KAAK;AACzB,wBAAiB;AACf,4BAAoB,MAAM;UACzB,IAAK;AACR,aAAM,UAAU,UAAU,UAAU,YAAY;;gBAGjD,mBACC,oBAAC,WAAD;OACE,MAAM;OACN,WAAU;OACV,CAAA,GAEF,oBAAC,UAAD;OACE,MAAM;OACN,WAAU;OACV,CAAA;MAEG,CAAA;KACL;;GAGP;GACG"}
1
+ {"version":3,"file":"empty-C1tAkawe.js","names":[],"sources":["../src/components/empty/empty.tsx"],"sourcesContent":["import { CheckIcon, CopyIcon } from \"@phosphor-icons/react\";\nimport { useState } from \"react\";\n\nimport { Button } from \"../../components/button\";\nimport { Text } from \"../../components/text\";\nimport { cn } from \"../../utils/cn\";\n\n/** Empty state size variant definitions mapping sizes to their Tailwind classes. */\nexport const SF_EMPTY_VARIANTS = {\n size: {\n sm: {\n classes: \"px-6 py-8 gap-4\",\n description: \"Compact empty state for smaller containers\",\n },\n base: {\n classes: \"px-10 py-16 gap-6\",\n description: \"Default empty state size\",\n },\n lg: {\n classes: \"px-12 py-20 gap-8\",\n description: \"Large empty state for prominent placement\",\n },\n },\n} as const;\n\nexport const SF_EMPTY_DEFAULT_VARIANTS = {\n size: \"base\",\n} as const;\n\nexport type SFEmptySize = keyof typeof SF_EMPTY_VARIANTS.size;\n\nexport interface SFEmptyVariantsProps {\n /**\n * Size of the empty state container.\n * - `\"sm\"` — Compact empty state for smaller containers\n * - `\"base\"` — Default empty state size\n * - `\"lg\"` — Large empty state for prominent placement\n * @default \"base\"\n */\n size?: SFEmptySize;\n}\n\nexport function emptyVariants({\n size = SF_EMPTY_DEFAULT_VARIANTS.size,\n}: SFEmptyVariantsProps = {}) {\n return cn(\n \"flex w-full flex-col items-center rounded-xl border border-sf-fill bg-sf-control text-sf-default\",\n SF_EMPTY_VARIANTS.size[size].classes\n );\n}\n\n/**\n * Empty state component props.\n *\n * @example\n * ```tsx\n * <Empty\n * icon={<PackageIcon size={48} />}\n * title=\"No packages found\"\n * description=\"Get started by installing your first package.\"\n * commandLine=\"npm install @signalflare-ai/ui\"\n * />\n * ```\n */\nexport interface EmptyProps extends SFEmptyVariantsProps {\n /** Decorative icon displayed above the title (e.g. from `@phosphor-icons/react`). */\n icon?: React.ReactNode;\n /** Primary heading text for the empty state. */\n title: string;\n /** Secondary description text displayed below the title. */\n description?: string;\n /** Shell command displayed in a copyable code block. */\n commandLine?: string;\n /** Additional content (buttons, links) rendered below the description. */\n contents?: React.ReactNode;\n /** Additional CSS classes merged via `cn()`. */\n className?: string;\n}\n\n/**\n * Placeholder shown when a list, table, or page has no content to display.\n *\n * @example\n * ```tsx\n * <Empty title=\"No results found\" description=\"Try adjusting your search.\" />\n * ```\n */\nexport function Empty({\n icon,\n title,\n description,\n commandLine,\n contents,\n size = \"base\",\n className,\n}: EmptyProps) {\n const [emptyStateCopied, setEmptyStateCopied] = useState<boolean>(false);\n\n return (\n <div className={cn(emptyVariants({ size }), className)}>\n {icon}\n <Text variant=\"heading2\" wrap=\"natural\" as=\"h2\">\n {title}\n </Text>\n\n {description && (\n <Text\n wrap=\"natural\"\n as=\"p\"\n DANGEROUS_className=\"max-w-140 text-center text-sf-strong\"\n >\n {description}\n </Text>\n )}\n\n {commandLine && (\n <div\n className={cn(\n \"group/cmd relative inline-flex h-10 max-w-8/10 transform-gpu items-center gap-2 rounded-lg font-mono shadow-sm\",\n \"bg-sf-overlay pr-2 pl-3\",\n \"transition-all duration-300 hover:border-sf-interact/80 hover:shadow-md\",\n \"border border-sf-fill/60\"\n )}\n >\n <span className=\"text-xs text-sf-inactive select-none\">$</span>\n <span className=\"no-scrollbar overflow-scroll text-[14px] whitespace-nowrap text-sf-brand\">\n {commandLine}\n </span>\n <Button\n className=\"group\"\n size=\"sm\"\n variant=\"ghost\"\n shape=\"square\"\n aria-label=\"Copy command\"\n onClick={async () => {\n setEmptyStateCopied(true);\n setTimeout(() => {\n setEmptyStateCopied(false);\n }, 1000);\n await navigator.clipboard.writeText(commandLine);\n }}\n >\n {emptyStateCopied ? (\n <CheckIcon\n size={16}\n className=\"animate-bounce-in text-sf-success\"\n />\n ) : (\n <CopyIcon\n size={16}\n className=\"text-sf-inactive group-hover:text-sf-brand\"\n />\n )}\n </Button>\n </div>\n )}\n\n {contents}\n </div>\n );\n}\n"],"mappings":";;;;;;;;;AAQA,IAAa,oBAAoB,EAC/B,MAAM;CACJ,IAAI;EACF,SAAS;EACT,aAAa;CACf;CACA,MAAM;EACJ,SAAS;EACT,aAAa;CACf;CACA,IAAI;EACF,SAAS;EACT,aAAa;CACf;AACF,EACF;AAEA,IAAa,4BAA4B,EACvC,MAAM,OACR;AAeA,SAAgB,cAAc,EAC5B,OAAO,0BAA0B,SACT,CAAC,GAAG;CAC5B,OAAO,GACL,oGACA,kBAAkB,KAAK,MAAM,OAC/B;AACF;;;;;;;;;AAsCA,SAAgB,MAAM,EACpB,MACA,OACA,aACA,aACA,UACA,OAAO,QACP,aACa;CACb,MAAM,CAAC,kBAAkB,uBAAuB,SAAkB,KAAK;CAEvE,OACE,qBAAC,OAAD;EAAK,WAAW,GAAG,cAAc,EAAE,KAAK,CAAC,GAAG,SAAS;YAArD;GACG;GACD,oBAAC,MAAD;IAAM,SAAQ;IAAW,MAAK;IAAU,IAAG;cACxC;GACG,CAAA;GAEL,eACC,oBAAC,MAAD;IACE,MAAK;IACL,IAAG;IACH,qBAAoB;cAEnB;GACG,CAAA;GAGP,eACC,qBAAC,OAAD;IACE,WAAW,GACT,kHACA,2BACA,2EACA,0BACF;cANF;KAQE,oBAAC,QAAD;MAAM,WAAU;gBAAuC;KAAO,CAAA;KAC9D,oBAAC,QAAD;MAAM,WAAU;gBACb;KACG,CAAA;KACN,oBAAC,QAAD;MACE,WAAU;MACV,MAAK;MACL,SAAQ;MACR,OAAM;MACN,cAAW;MACX,SAAS,YAAY;OACnB,oBAAoB,IAAI;OACxB,iBAAiB;QACf,oBAAoB,KAAK;OAC3B,GAAG,GAAI;OACP,MAAM,UAAU,UAAU,UAAU,WAAW;MACjD;gBAEC,mBACC,oBAAC,WAAD;OACE,MAAM;OACN,WAAU;MACX,CAAA,IAED,oBAAC,UAAD;OACE,MAAM;OACN,WAAU;MACX,CAAA;KAEG,CAAA;IACL;;GAGN;EACE;;AAET"}
@@ -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 { jsx, jsxs } from "react/jsx-runtime";
5
5
  import { Field } from "@base-ui/react/field";
6
6
  //#region src/components/field/field.tsx
@@ -54,4 +54,4 @@ function Field$1({ children, label, required, labelTooltip, error, description,
54
54
  //#endregion
55
55
  export { fieldVariants as i, SF_FIELD_DEFAULT_VARIANTS as n, SF_FIELD_VARIANTS as r, Field$1 as t };
56
56
 
57
- //# sourceMappingURL=field-B_yVof52.js.map
57
+ //# sourceMappingURL=field-DBpFzzBS.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"field-B_yVof52.js","names":[],"sources":["../src/components/field/field.tsx"],"sourcesContent":["import { Field as FieldBase } from \"@base-ui/react/field\";\nimport type { ReactNode } from \"react\";\n\nimport { cn } from \"../../utils/cn\";\nimport { Label } from \"../label\";\n\n/** Field variant definitions (currently empty, reserved for future additions). */\nexport const SF_FIELD_VARIANTS = {\n // Field currently has no variant options but structure is ready for future additions\n} as const;\n\nexport const SF_FIELD_DEFAULT_VARIANTS = {} as const;\n\n// Derived types from SF_FIELD_VARIANTS\nexport interface SFFieldVariantsProps {\n /**\n * When true, places the control (checkbox/switch) before the label visually.\n * When false (default), places the label before the control.\n * Used to support different layout patterns (e.g., iOS-style toggles on the right).\n */\n controlFirst?: boolean;\n}\n\nexport function fieldVariants({\n controlFirst = false,\n}: SFFieldVariantsProps = {}) {\n return cn(\n // Base styles - vertical layout (default)\n \"grid gap-2\",\n\n // Horizontal layout for checkbox and switch\n // Default: Grid auto-reverses in RTL (desired)\n \"has-[input[type=checkbox]]:grid-cols-[auto_1fr] has-[input[type=checkbox]]:items-center\",\n \"has-[[role=switch]]:grid-cols-[auto_1fr] has-[[role=switch]]:items-center\",\n\n // Control first: use flexbox with row-reverse to flip visual order without affecting text direction\n // flex-row-reverse in LTR: Control→Label, in RTL: Label→Control (opposite of grid default)\n controlFirst && [\n \"has-[input[type=checkbox]]:flex has-[input[type=checkbox]]:flex-row-reverse has-[input[type=checkbox]]:flex-wrap has-[input[type=checkbox]]:items-center\",\n \"has-[[role=switch]]:flex has-[[role=switch]]:flex-row-reverse has-[[role=switch]]:flex-wrap has-[[role=switch]]:items-center\",\n \"[&>label]:flex-1\",\n ]\n );\n}\n\n/**\n * Match type for field validation errors.\n * Can be a boolean or a key from the browser's ValidityState interface.\n * Source: BaseErrorProps[\"match\"] (ComponentPropsWithoutRef<typeof FieldBase.Error>)\n */\nexport type FieldErrorMatch =\n | boolean\n | \"badInput\"\n | \"customError\"\n | \"patternMismatch\"\n | \"rangeOverflow\"\n | \"rangeUnderflow\"\n | \"stepMismatch\"\n | \"tooLong\"\n | \"tooShort\"\n | \"typeMismatch\"\n | \"valid\"\n | \"valueMissing\";\n\n/**\n * Field component props — wraps a form control with label, description, and error message.\n *\n * @example\n * ```tsx\n * <Field label=\"Email\" required>\n * <Input placeholder=\"you@example.com\" />\n * </Field>\n *\n * <Field label=\"Phone\" required={false} description=\"We'll only use this for account recovery.\">\n * <Input placeholder=\"+1 555-0000\" />\n * </Field>\n * ```\n */\nexport interface FieldProps extends SFFieldVariantsProps {\n /** The form control element(s) to wrap (Input, Select, Checkbox, etc.). */\n children: ReactNode;\n /** The label content — can be a string or any React node. */\n label: ReactNode;\n /**\n * When explicitly `false`, shows gray \"(optional)\" text after the label.\n * When `true` or `undefined`, no indicator is shown.\n */\n required?: boolean;\n /** Tooltip content displayed next to the label via an info icon. */\n labelTooltip?: ReactNode;\n /** Validation error with a message and a browser `ValidityState` match key. */\n error?: {\n message: ReactNode;\n match: FieldErrorMatch;\n };\n /** Helper text displayed below the control (hidden when `error` is present). */\n description?: ReactNode;\n /** When `true`, places the control before the label (for checkbox/switch layouts). */\n controlFirst?: boolean;\n}\n\n/**\n * Form field wrapper that provides a label, optional description, and error display\n * around any form control. Built on Base UI Field primitives.\n *\n * @example\n * ```tsx\n * <Field label=\"Username\">\n * <Input placeholder=\"Choose a username\" />\n * </Field>\n * ```\n */\nexport function Field({\n children,\n label,\n required,\n labelTooltip,\n error,\n description,\n controlFirst = false,\n}: FieldProps) {\n // Show \"(optional)\" when required is explicitly false\n const showOptional = required === false;\n\n return (\n <FieldBase.Root className={fieldVariants({ controlFirst })}>\n <FieldBase.Label className=\"text-base font-medium text-sf-default\">\n <Label showOptional={showOptional} tooltip={labelTooltip} asContent>\n {label}\n </Label>\n </FieldBase.Label>\n {children}\n {error ? (\n <FieldBase.Error\n className={cn(\n \"text-sm text-sf-danger\",\n // Span full width in horizontal layout\n \"col-span-full\"\n )}\n match={error.match}\n >\n {error.message}\n </FieldBase.Error>\n ) : (\n description && (\n <FieldBase.Description\n className={cn(\n \"text-sm leading-snug text-sf-subtle\",\n // Span full width in horizontal layout\n \"col-span-full\"\n )}\n >\n {description}\n </FieldBase.Description>\n )\n )}\n </FieldBase.Root>\n );\n}\n"],"mappings":";;;;;;;AAOA,IAAa,oBAAoB,EAEhC;AAED,IAAa,4BAA4B,EAAE;AAY3C,SAAgB,cAAc,EAC5B,eAAe,UACS,EAAE,EAAE;AAC5B,QAAO,GAEL,cAIA,2FACA,6EAIA,gBAAgB;EACd;EACA;EACA;EACD,CACF;;;;;;;;;;;;;AAsEH,SAAgB,QAAM,EACpB,UACA,OACA,UACA,cACA,OACA,aACA,eAAe,SACF;CAEb,MAAM,eAAe,aAAa;AAElC,QACE,qBAAC,MAAU,MAAX;EAAgB,WAAW,cAAc,EAAE,cAAc,CAAC;YAA1D;GACE,oBAAC,MAAU,OAAX;IAAiB,WAAU;cACzB,oBAAC,OAAD;KAAqB;KAAc,SAAS;KAAc,WAAA;eACvD;KACK,CAAA;IACQ,CAAA;GACjB;GACA,QACC,oBAAC,MAAU,OAAX;IACE,WAAW,GACT,0BAEA,gBACD;IACD,OAAO,MAAM;cAEZ,MAAM;IACS,CAAA,GAElB,eACE,oBAAC,MAAU,aAAX;IACE,WAAW,GACT,uCAEA,gBACD;cAEA;IACqB,CAAA;GAGb"}
1
+ {"version":3,"file":"field-DBpFzzBS.js","names":[],"sources":["../src/components/field/field.tsx"],"sourcesContent":["import { Field as FieldBase } from \"@base-ui/react/field\";\nimport type { ReactNode } from \"react\";\n\nimport { cn } from \"../../utils/cn\";\nimport { Label } from \"../label\";\n\n/** Field variant definitions (currently empty, reserved for future additions). */\nexport const SF_FIELD_VARIANTS = {\n // Field currently has no variant options but structure is ready for future additions\n} as const;\n\nexport const SF_FIELD_DEFAULT_VARIANTS = {} as const;\n\n// Derived types from SF_FIELD_VARIANTS\nexport interface SFFieldVariantsProps {\n /**\n * When true, places the control (checkbox/switch) before the label visually.\n * When false (default), places the label before the control.\n * Used to support different layout patterns (e.g., iOS-style toggles on the right).\n */\n controlFirst?: boolean;\n}\n\nexport function fieldVariants({\n controlFirst = false,\n}: SFFieldVariantsProps = {}) {\n return cn(\n // Base styles - vertical layout (default)\n \"grid gap-2\",\n\n // Horizontal layout for checkbox and switch\n // Default: Grid auto-reverses in RTL (desired)\n \"has-[input[type=checkbox]]:grid-cols-[auto_1fr] has-[input[type=checkbox]]:items-center\",\n \"has-[[role=switch]]:grid-cols-[auto_1fr] has-[[role=switch]]:items-center\",\n\n // Control first: use flexbox with row-reverse to flip visual order without affecting text direction\n // flex-row-reverse in LTR: Control→Label, in RTL: Label→Control (opposite of grid default)\n controlFirst && [\n \"has-[input[type=checkbox]]:flex has-[input[type=checkbox]]:flex-row-reverse has-[input[type=checkbox]]:flex-wrap has-[input[type=checkbox]]:items-center\",\n \"has-[[role=switch]]:flex has-[[role=switch]]:flex-row-reverse has-[[role=switch]]:flex-wrap has-[[role=switch]]:items-center\",\n \"[&>label]:flex-1\",\n ]\n );\n}\n\n/**\n * Match type for field validation errors.\n * Can be a boolean or a key from the browser's ValidityState interface.\n * Source: BaseErrorProps[\"match\"] (ComponentPropsWithoutRef<typeof FieldBase.Error>)\n */\nexport type FieldErrorMatch =\n | boolean\n | \"badInput\"\n | \"customError\"\n | \"patternMismatch\"\n | \"rangeOverflow\"\n | \"rangeUnderflow\"\n | \"stepMismatch\"\n | \"tooLong\"\n | \"tooShort\"\n | \"typeMismatch\"\n | \"valid\"\n | \"valueMissing\";\n\n/**\n * Field component props — wraps a form control with label, description, and error message.\n *\n * @example\n * ```tsx\n * <Field label=\"Email\" required>\n * <Input placeholder=\"you@example.com\" />\n * </Field>\n *\n * <Field label=\"Phone\" required={false} description=\"We'll only use this for account recovery.\">\n * <Input placeholder=\"+1 555-0000\" />\n * </Field>\n * ```\n */\nexport interface FieldProps extends SFFieldVariantsProps {\n /** The form control element(s) to wrap (Input, Select, Checkbox, etc.). */\n children: ReactNode;\n /** The label content — can be a string or any React node. */\n label: ReactNode;\n /**\n * When explicitly `false`, shows gray \"(optional)\" text after the label.\n * When `true` or `undefined`, no indicator is shown.\n */\n required?: boolean;\n /** Tooltip content displayed next to the label via an info icon. */\n labelTooltip?: ReactNode;\n /** Validation error with a message and a browser `ValidityState` match key. */\n error?: {\n message: ReactNode;\n match: FieldErrorMatch;\n };\n /** Helper text displayed below the control (hidden when `error` is present). */\n description?: ReactNode;\n /** When `true`, places the control before the label (for checkbox/switch layouts). */\n controlFirst?: boolean;\n}\n\n/**\n * Form field wrapper that provides a label, optional description, and error display\n * around any form control. Built on Base UI Field primitives.\n *\n * @example\n * ```tsx\n * <Field label=\"Username\">\n * <Input placeholder=\"Choose a username\" />\n * </Field>\n * ```\n */\nexport function Field({\n children,\n label,\n required,\n labelTooltip,\n error,\n description,\n controlFirst = false,\n}: FieldProps) {\n // Show \"(optional)\" when required is explicitly false\n const showOptional = required === false;\n\n return (\n <FieldBase.Root className={fieldVariants({ controlFirst })}>\n <FieldBase.Label className=\"text-base font-medium text-sf-default\">\n <Label showOptional={showOptional} tooltip={labelTooltip} asContent>\n {label}\n </Label>\n </FieldBase.Label>\n {children}\n {error ? (\n <FieldBase.Error\n className={cn(\n \"text-sm text-sf-danger\",\n // Span full width in horizontal layout\n \"col-span-full\"\n )}\n match={error.match}\n >\n {error.message}\n </FieldBase.Error>\n ) : (\n description && (\n <FieldBase.Description\n className={cn(\n \"text-sm leading-snug text-sf-subtle\",\n // Span full width in horizontal layout\n \"col-span-full\"\n )}\n >\n {description}\n </FieldBase.Description>\n )\n )}\n </FieldBase.Root>\n );\n}\n"],"mappings":";;;;;;;AAOA,IAAa,oBAAoB,CAEjC;AAEA,IAAa,4BAA4B,CAAC;AAY1C,SAAgB,cAAc,EAC5B,eAAe,UACS,CAAC,GAAG;CAC5B,OAAO,GAEL,cAIA,2FACA,6EAIA,gBAAgB;EACd;EACA;EACA;CACF,CACF;AACF;;;;;;;;;;;;AAqEA,SAAgB,QAAM,EACpB,UACA,OACA,UACA,cACA,OACA,aACA,eAAe,SACF;CAEb,MAAM,eAAe,aAAa;CAElC,OACE,qBAAC,MAAU,MAAX;EAAgB,WAAW,cAAc,EAAE,aAAa,CAAC;YAAzD;GACE,oBAAC,MAAU,OAAX;IAAiB,WAAU;cACzB,oBAAC,OAAD;KAAqB;KAAc,SAAS;KAAc,WAAA;eACvD;IACI,CAAA;GACQ,CAAA;GAChB;GACA,QACC,oBAAC,MAAU,OAAX;IACE,WAAW,GACT,0BAEA,eACF;IACA,OAAO,MAAM;cAEZ,MAAM;GACQ,CAAA,IAEjB,eACE,oBAAC,MAAU,aAAX;IACE,WAAW,GACT,uCAEA,eACF;cAEC;GACoB,CAAA;EAGb;;AAEpB"}
@@ -1,11 +1,11 @@
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 { t as Checkbox } from "./checkbox-D7p4QKsC.js";
5
- import { t as Input } from "./input-B2bbijRh.js";
6
- import { t as InputGroup } from "./input-ClB_E4Lb.js";
7
- import { t as DropdownMenu } from "./dropdown-B_nrGXjV.js";
8
- import { t as Popover } from "./popover-SRoJaCZr.js";
2
+ import { t as cn } from "./cn-CmAOpn49.js";
3
+ import { t as Button } from "./button-BHOgXJRU.js";
4
+ import { t as Checkbox } from "./checkbox-Cy_OCyay.js";
5
+ import { t as Input } from "./input-GkfMQZC_.js";
6
+ import { t as InputGroup } from "./input-COmx2M_R.js";
7
+ import { t as DropdownMenu } from "./dropdown-XzbnRLYR.js";
8
+ import { t as Popover } from "./popover-BY-e9co1.js";
9
9
  import { useCallback, useEffect, useMemo, useState } from "react";
10
10
  import { jsx, jsxs } from "react/jsx-runtime";
11
11
  import { CaretDown, Check, MagnifyingGlass, Plus, X } from "@phosphor-icons/react";
@@ -261,8 +261,8 @@ function FilterValueEditor({ field, values, onChange, onClose, i18n }) {
261
261
  const handleValueChange = useCallback((newValues) => {
262
262
  setLocalValues(newValues);
263
263
  const validation = validateFilterValue(field, newValues);
264
- if (!validation.valid) setValidationError(validation.message ?? i18n.validationError);
265
- else setValidationError(null);
264
+ if (validation.valid) setValidationError(null);
265
+ else setValidationError(validation.message ?? i18n.validationError);
266
266
  }, [field, i18n.validationError]);
267
267
  const handleApply = useCallback(() => {
268
268
  const validation = validateFilterValue(field, localValues);
@@ -679,4 +679,4 @@ Filters.displayName = "Filters";
679
679
  //#endregion
680
680
  export { validateFilterValue as _, DEFAULT_MULTISELECT_OPERATORS as a, DEFAULT_TEXT_OPERATORS as c, formatFilterValue as d, getFieldByKey as f, mergeI18n as g, groupFields as h, DEFAULT_I18N as i, createFilter as l, getValueLabel as m, SF_FILTERS_DEFAULT_VARIANTS as n, DEFAULT_OPERATORS as o, getFieldOperators as p, SF_FILTERS_VARIANTS as r, DEFAULT_SELECT_OPERATORS as s, Filters as t, createFilterGroup as u };
681
681
 
682
- //# sourceMappingURL=filters-cpJCY21R.js.map
682
+ //# sourceMappingURL=filters-SmEl93za.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"filters-SmEl93za.js","names":[],"sources":["../src/components/filters/helpers.ts","../src/components/filters/filters.tsx"],"sourcesContent":["import type {\n Filter,\n FilterFieldConfig,\n FilterOperator,\n FilterI18nConfig,\n} from \"./types\";\n\n// ============================================================================\n// Default Operators by Field Type\n// ============================================================================\n\n/** Default operators for text fields */\nexport const DEFAULT_TEXT_OPERATORS: FilterOperator[] = [\n { value: \"is\", label: \"is\" },\n { value: \"is_not\", label: \"is not\" },\n { value: \"contains\", label: \"contains\" },\n { value: \"does_not_contain\", label: \"does not contain\" },\n { value: \"starts_with\", label: \"starts with\" },\n { value: \"ends_with\", label: \"ends with\" },\n { value: \"is_empty\", label: \"is empty\" },\n { value: \"is_not_empty\", label: \"is not empty\" },\n];\n\n/** Default operators for select fields */\nexport const DEFAULT_SELECT_OPERATORS: FilterOperator[] = [\n { value: \"is\", label: \"is\" },\n { value: \"is_not\", label: \"is not\" },\n { value: \"is_empty\", label: \"is empty\" },\n { value: \"is_not_empty\", label: \"is not empty\" },\n];\n\n/** Default operators for multiselect fields */\nexport const DEFAULT_MULTISELECT_OPERATORS: FilterOperator[] = [\n { value: \"is_any_of\", label: \"is any of\" },\n { value: \"is_none_of\", label: \"is none of\" },\n { value: \"is_all_of\", label: \"is all of\" },\n { value: \"is_empty\", label: \"is empty\" },\n { value: \"is_not_empty\", label: \"is not empty\" },\n];\n\n/** Map of field types to their default operators */\nexport const DEFAULT_OPERATORS: Record<string, FilterOperator[]> = {\n text: DEFAULT_TEXT_OPERATORS,\n select: DEFAULT_SELECT_OPERATORS,\n multiselect: DEFAULT_MULTISELECT_OPERATORS,\n};\n\n/** Get default operator for a field type */\nexport function getDefaultOperatorForFieldType(\n type: string,\n operators?: FilterOperator[]\n): string {\n if (operators && operators.length > 0) {\n return operators[0].value;\n }\n const defaults = DEFAULT_OPERATORS[type];\n return defaults?.[0]?.value ?? \"is\";\n}\n\n// ============================================================================\n// Filter Factory Functions\n// ============================================================================\n\n/**\n * Create a new filter with a unique ID.\n *\n * @example\n * ```tsx\n * const filter = createFilter(\"status\", \"is\", [\"active\"]);\n * setFilters(prev => [...prev, filter]);\n * ```\n */\nexport function createFilter(\n field: string,\n operator: string,\n values: string[]\n): Filter {\n return {\n id: crypto.randomUUID(),\n field,\n operator,\n values,\n };\n}\n\n/**\n * Create multiple filters at once, each with a unique ID.\n *\n * @example\n * ```tsx\n * const filters = createFilterGroup([\n * { field: \"status\", operator: \"is\", values: [\"active\"] },\n * { field: \"priority\", operator: \"is_any_of\", values: [\"high\", \"critical\"] },\n * ]);\n * ```\n */\nexport function createFilterGroup(\n filters: Array<Omit<Filter, \"id\">>\n): Filter[] {\n return filters.map((f) => ({\n ...f,\n id: crypto.randomUUID(),\n }));\n}\n\n// ============================================================================\n// i18n Defaults\n// ============================================================================\n\n/** Default i18n configuration */\nexport const DEFAULT_I18N: FilterI18nConfig = {\n addFilter: \"Add Filter\",\n clearAll: \"Clear All\",\n searchPlaceholder: \"Search fields...\",\n noResults: \"No fields found\",\n operators: {\n is: \"is\",\n is_not: \"is not\",\n contains: \"contains\",\n does_not_contain: \"does not contain\",\n starts_with: \"starts with\",\n ends_with: \"ends with\",\n is_empty: \"is empty\",\n is_not_empty: \"is not empty\",\n is_any_of: \"is any of\",\n is_none_of: \"is none of\",\n is_all_of: \"is all of\",\n },\n valueLabel: \"Value\",\n noValueLabel: \"None\",\n removeFilter: \"Remove filter\",\n changeOperator: \"Change operator\",\n changeValue: \"Change value\",\n maxSelectionsReached: \"Maximum selections reached\",\n validationError: \"Invalid value\",\n};\n\n/** Merge partial i18n config with defaults */\nexport function mergeI18n(\n partial?: Partial<FilterI18nConfig>\n): FilterI18nConfig {\n return {\n ...DEFAULT_I18N,\n ...partial,\n operators: {\n ...DEFAULT_I18N.operators,\n ...partial?.operators,\n },\n };\n}\n\n// ============================================================================\n// Field Helpers\n// ============================================================================\n\n/** Get operators for a field, falling back to defaults */\nexport function getFieldOperators(field: FilterFieldConfig): FilterOperator[] {\n if (field.operators && field.operators.length > 0) {\n return field.operators;\n }\n return DEFAULT_OPERATORS[field.type] ?? DEFAULT_TEXT_OPERATORS;\n}\n\n/** Get field configuration by key */\nexport function getFieldByKey(\n fields: FilterFieldConfig[],\n key: string\n): FilterFieldConfig | undefined {\n return fields.find((f) => f.key === key);\n}\n\n/** Group fields by their group property */\nexport function groupFields(\n fields: FilterFieldConfig[]\n): Map<string, FilterFieldConfig[]> {\n const groups = new Map<string, FilterFieldConfig[]>();\n\n for (const field of fields) {\n const group = field.group ?? \"Fields\";\n if (!groups.has(group)) {\n groups.set(group, []);\n }\n groups.get(group)!.push(field);\n }\n\n return groups;\n}\n\n/** Check if a filter value is valid for a field */\nexport function validateFilterValue(\n field: FilterFieldConfig,\n values: string[]\n): { valid: boolean; message?: string } {\n // Check max selections\n if (field.maxSelections && values.length > field.maxSelections) {\n return {\n valid: false,\n message: `Maximum ${field.maxSelections} selections allowed`,\n };\n }\n\n // Run custom validation if provided\n if (field.validation) {\n const result = field.validation(values);\n if (typeof result === \"boolean\") {\n return { valid: result, message: result ? undefined : \"Invalid value\" };\n }\n return result;\n }\n\n return { valid: true };\n}\n\n// ============================================================================\n// Value Formatting\n// ============================================================================\n\n/** Format a filter value for display in the filter pill */\nexport function formatFilterValue(\n values: string[],\n field: FilterFieldConfig\n): string {\n // Use custom renderer if provided\n if (field.customValueRenderer) {\n // Return a placeholder - the actual rendering happens in React\n return \"...\";\n }\n\n // Empty values\n if (values.length === 0) {\n return \"None\";\n }\n\n // Single value\n if (values.length === 1) {\n const value = values[0];\n // Try to find option label\n if (field.options) {\n const option = field.options.find((o) => o.value === value);\n if (option) return option.label;\n }\n return String(value);\n }\n\n // Multiple values\n if (field.options) {\n const labels = values.map((v) => {\n const option = field.options!.find((o) => o.value === v);\n return option?.label ?? String(v);\n });\n return `${labels.slice(0, 2).join(\", \")}${labels.length > 2 ? ` +${labels.length - 2}` : \"\"}`;\n }\n\n return `${values.length} selected`;\n}\n\n/** Get the label for a filter value from options */\nexport function getValueLabel(\n value: string,\n options?: Array<{ value: string; label: string }>\n): string {\n if (!options) return String(value);\n const option = options.find((o) => o.value === value);\n return option?.label ?? String(value);\n}\n","\"use client\";\n\nimport {\n Check,\n CaretDown,\n MagnifyingGlass,\n Plus,\n X,\n} from \"@phosphor-icons/react\";\nimport {\n useCallback,\n useEffect,\n useMemo,\n useState,\n type ReactNode,\n} from \"react\";\n\nimport { cn } from \"../../utils/cn\";\nimport { Button } from \"../button\";\nimport { Checkbox } from \"../checkbox\";\nimport { DropdownMenu } from \"../dropdown\";\nimport { Input, InputGroup } from \"../input\";\nimport { Popover } from \"../popover\";\nimport {\n formatFilterValue,\n getDefaultOperatorForFieldType,\n getFieldOperators,\n groupFields,\n mergeI18n,\n validateFilterValue,\n createFilter,\n} from \"./helpers\";\nimport type {\n Filter,\n FilterCustomRendererProps,\n FilterFieldConfig,\n FiltersProps,\n FilterI18nConfig,\n} from \"./types\";\n\nexport { createFilter, createFilterGroup } from \"./helpers\";\n\nexport type {\n Filter,\n FilterFieldConfig,\n FilterOption,\n FilterOperator,\n FilterI18nConfig,\n FiltersProps,\n FilterCustomRendererProps,\n} from \"./types\";\n\n// ============================================================================\n// Variants\n// ============================================================================\n\n/** Filters size variant definitions */\nexport const SF_FILTERS_VARIANTS = {\n size: {\n sm: {\n classes: \"text-xs\",\n description: \"Small filter items\",\n },\n default: {\n classes: \"text-sm\",\n description: \"Default filter items\",\n },\n lg: {\n classes: \"text-base\",\n description: \"Large filter items\",\n },\n },\n} as const;\n\n/** Default variants for Filters */\nexport const SF_FILTERS_DEFAULT_VARIANTS = {\n size: \"default\",\n} as const;\n\n// ============================================================================\n// Filter Value Editor (internal)\n// ============================================================================\n\ninterface FilterValueEditorProps {\n field: FilterFieldConfig;\n values: string[];\n onChange: (values: string[]) => void;\n onClose: () => void;\n i18n: FilterI18nConfig;\n}\n\nfunction FilterValueEditor({\n field,\n values,\n onChange,\n onClose,\n i18n,\n}: FilterValueEditorProps) {\n const [searchQuery, setSearchQuery] = useState(\"\");\n const [localValues, setLocalValues] = useState<string[]>(values);\n const [validationError, setValidationError] = useState<string | null>(null);\n\n const options = useMemo(() => {\n if (!field.options) return [];\n if (!searchQuery) return field.options;\n return field.options.filter((o: { label: string }) =>\n o.label.toLowerCase().includes(searchQuery.toLowerCase())\n );\n }, [field.options, searchQuery]);\n\n const handleValueChange = useCallback(\n (newValues: string[]) => {\n setLocalValues(newValues);\n const validation = validateFilterValue(field, newValues);\n if (validation.valid) {\n setValidationError(null);\n } else {\n setValidationError(validation.message ?? i18n.validationError);\n }\n },\n [field, i18n.validationError]\n );\n\n const handleApply = useCallback(() => {\n const validation = validateFilterValue(field, localValues);\n if (!validation.valid) {\n setValidationError(validation.message ?? i18n.validationError);\n return;\n }\n onChange(localValues);\n onClose();\n }, [field, localValues, onChange, onClose, i18n.validationError]);\n\n // Text type\n if (field.type === \"text\") {\n return (\n <div className=\"flex flex-col gap-2 p-2\">\n <Input\n value={String(localValues[0] ?? \"\")}\n onChange={(e) => handleValueChange([e.target.value])}\n placeholder={field.placeholder}\n className=\"w-full\"\n />\n <div className=\"flex justify-end gap-2\">\n <Button variant=\"secondary\" size=\"sm\" onClick={onClose}>\n Cancel\n </Button>\n <Button size=\"sm\" onClick={handleApply}>\n Apply\n </Button>\n </div>\n </div>\n );\n }\n\n // Select type\n if (field.type === \"select\") {\n return (\n <div className=\"flex max-h-72 flex-col gap-2\">\n {field.searchable && (\n <div className=\"border-b border-sf-line pb-2\">\n <InputGroup className=\"w-full\">\n <InputGroup.Input\n value={searchQuery}\n onChange={(e) => setSearchQuery(e.target.value)}\n placeholder={i18n.searchPlaceholder}\n className=\"w-full\"\n />\n <InputGroup.Button>\n <MagnifyingGlass className=\"size-4\" />\n </InputGroup.Button>\n </InputGroup>\n </div>\n )}\n <div className=\"flex flex-col gap-0.5 overflow-auto\">\n {options.map((option) => (\n <button\n key={String(option.value)}\n type=\"button\"\n onClick={() => {\n handleValueChange([option.value]);\n handleApply();\n }}\n className={cn(\n \"flex items-center justify-between rounded-md px-2 py-1.5 text-sm\",\n \"hover:bg-sf-tint\",\n localValues[0] === option.value && \"bg-sf-tint\"\n )}\n >\n <span className=\"flex items-center gap-2\">\n {option.icon}\n {option.label}\n </span>\n {localValues[0] === option.value && (\n <Check className=\"size-4 text-sf-brand\" />\n )}\n </button>\n ))}\n {options.length === 0 && (\n <div className=\"py-4 text-center text-sm text-sf-subtle\">\n {i18n.noResults}\n </div>\n )}\n </div>\n </div>\n );\n }\n\n // Multiselect type\n if (field.type === \"multiselect\") {\n const isMaxReached =\n field.maxSelections !== undefined &&\n localValues.length >= field.maxSelections;\n\n return (\n <div className=\"flex max-h-72 w-56 flex-col gap-2\">\n {field.searchable && (\n <div className=\"border-b border-sf-line pb-2\">\n <InputGroup className=\"w-full\">\n <InputGroup.Input\n value={searchQuery}\n onChange={(e) => setSearchQuery(e.target.value)}\n placeholder={i18n.searchPlaceholder}\n className=\"w-full\"\n />\n <InputGroup.Button>\n <MagnifyingGlass className=\"size-4\" />\n </InputGroup.Button>\n </InputGroup>\n </div>\n )}\n <div className=\"flex flex-col gap-0.5 overflow-auto\">\n {options.map((option) => {\n const isSelected = localValues.includes(option.value);\n const isDisabled = isMaxReached && !isSelected;\n\n return (\n <label\n key={String(option.value)}\n className={cn(\n \"flex cursor-pointer items-center gap-2 rounded-md px-2 py-1.5 text-sm\",\n !isDisabled && \"hover:bg-sf-tint\",\n isDisabled && \"cursor-not-allowed opacity-50\"\n )}\n >\n <Checkbox\n checked={isSelected}\n disabled={isDisabled}\n onCheckedChange={(checked) => {\n if (checked) {\n handleValueChange([...localValues, option.value]);\n } else {\n handleValueChange(\n localValues.filter((v) => v !== option.value)\n );\n }\n }}\n />\n <span className=\"flex items-center gap-2\">\n {option.icon}\n {option.label}\n </span>\n </label>\n );\n })}\n {options.length === 0 && (\n <div className=\"py-4 text-center text-sm text-sf-subtle\">\n {i18n.noResults}\n </div>\n )}\n </div>\n {isMaxReached && (\n <div className=\"text-xs text-sf-subtle\">\n {i18n.maxSelectionsReached}\n </div>\n )}\n {validationError && (\n <div className=\"text-xs text-sf-danger\">{validationError}</div>\n )}\n <div className=\"flex justify-end gap-2 border-t border-sf-line pt-2\">\n <Button variant=\"secondary\" size=\"sm\" onClick={onClose}>\n Cancel\n </Button>\n <Button size=\"sm\" onClick={handleApply}>\n Apply\n </Button>\n </div>\n </div>\n );\n }\n\n // Custom type\n if (field.type === \"custom\" && field.customRenderer) {\n const props: FilterCustomRendererProps = {\n values: localValues,\n onChange: handleValueChange,\n options: field.options,\n placeholder: field.placeholder,\n field,\n operator: \"is\",\n };\n\n return (\n <div className=\"flex flex-col gap-2 p-2\">\n {field.customRenderer(props)}\n <div className=\"flex justify-end gap-2\">\n <Button variant=\"secondary\" size=\"sm\" onClick={onClose}>\n Cancel\n </Button>\n <Button size=\"sm\" onClick={handleApply}>\n Apply\n </Button>\n </div>\n </div>\n );\n }\n\n return null;\n}\n\n// ============================================================================\n// Filter Item (internal)\n// ============================================================================\n\ninterface FilterItemProps {\n filter: Filter;\n field: FilterFieldConfig;\n size: \"sm\" | \"default\" | \"lg\";\n i18n: FilterI18nConfig;\n onRemove: () => void;\n onOperatorChange: (operator: string) => void;\n onValuesChange: (values: string[]) => void;\n}\n\nfunction FilterItem({\n filter,\n field,\n size,\n i18n,\n onRemove,\n onOperatorChange,\n onValuesChange,\n}: FilterItemProps) {\n const [valuePopoverOpen, setValuePopoverOpen] = useState(false);\n const operators = useMemo(() => getFieldOperators(field), [field]);\n\n const sizeClasses = {\n sm: \"text-xs py-0.5 px-1.5\",\n default: \"text-sm py-1 px-2\",\n lg: \"text-base py-1.5 px-2.5\",\n };\n\n const displayValue = useMemo(() => {\n if (field.customValueRenderer) {\n return field.customValueRenderer(filter.values, field.options);\n }\n return formatFilterValue(filter.values, field);\n }, [field, filter.values]);\n\n return (\n <div\n className={cn(\n \"inline-flex items-center gap-0 rounded-md border border-sf-line bg-sf-tint\",\n sizeClasses[size]\n )}\n >\n {/* Field label */}\n <span className=\"flex items-center gap-1 whitespace-nowrap font-medium text-sf-default\">\n {field.icon}\n {field.label}\n </span>\n\n {/* Separator */}\n <span className=\"mx-1.5 h-3 w-px bg-sf-fill\" />\n\n {/* Operator dropdown */}\n <DropdownMenu>\n <DropdownMenu.Trigger className=\"inline-flex cursor-pointer items-center gap-1 whitespace-nowrap text-sf-strong hover:text-sf-default\">\n {operators.find((o) => o.value === filter.operator)?.label ??\n filter.operator}\n <CaretDown className=\"size-3\" />\n </DropdownMenu.Trigger>\n <DropdownMenu.Content>\n {operators.map((op) => (\n <DropdownMenu.Item\n key={op.value}\n selected={filter.operator === op.value}\n onClick={() => onOperatorChange(op.value)}\n >\n {op.label}\n </DropdownMenu.Item>\n ))}\n </DropdownMenu.Content>\n </DropdownMenu>\n\n {/* Separator */}\n <span className=\"mx-1.5 h-3 w-px bg-sf-fill\" />\n\n {/* Value editor popover */}\n <Popover open={valuePopoverOpen} onOpenChange={setValuePopoverOpen}>\n <Popover.Trigger\n asChild\n className=\"inline-flex cursor-pointer items-center gap-1 whitespace-nowrap text-sf-strong hover:text-sf-default\"\n >\n <button type=\"button\" aria-label={i18n.changeValue}>\n <span className=\"max-w-32 truncate\">\n {filter.values.length === 0 ? i18n.noValueLabel : displayValue}\n </span>\n <CaretDown className=\"size-3\" />\n </button>\n </Popover.Trigger>\n <Popover.Content className=\"w-auto min-w-48\">\n <FilterValueEditor\n field={field}\n values={filter.values}\n onChange={onValuesChange}\n onClose={() => setValuePopoverOpen(false)}\n i18n={i18n}\n />\n </Popover.Content>\n </Popover>\n\n {/* Remove button */}\n <button\n type=\"button\"\n onClick={onRemove}\n aria-label={i18n.removeFilter}\n className=\"ml-1.5 inline-flex items-center justify-center rounded p-0.5 text-sf-subtle hover:bg-sf-overlay hover:text-sf-default\"\n >\n <X className=\"size-3.5\" />\n </button>\n </div>\n );\n}\n\n// ============================================================================\n// Filter Add Menu (internal)\n// ============================================================================\n\ninterface FilterAddMenuProps {\n fields: FilterFieldConfig[];\n filters: Filter[];\n size: \"sm\" | \"default\" | \"lg\";\n trigger?: ReactNode;\n showSearchInput?: boolean;\n allowMultiple?: boolean;\n i18n: FilterI18nConfig;\n onAddFilter: (filter: Filter) => void;\n}\n\nfunction FilterAddMenu({\n fields,\n filters,\n size,\n trigger,\n showSearchInput = true,\n allowMultiple = true,\n i18n,\n onAddFilter,\n}: FilterAddMenuProps) {\n const [open, setOpen] = useState(false);\n const [searchQuery, setSearchQuery] = useState(\"\");\n\n const groupedFields = useMemo(() => groupFields(fields), [fields]);\n\n const availableFields = useMemo(() => {\n if (allowMultiple) return fields;\n const usedKeys = new Set(filters.map((f) => f.field));\n return fields.filter((f) => !usedKeys.has(f.key));\n }, [fields, filters, allowMultiple]);\n\n const filteredGroups = useMemo(() => {\n if (!searchQuery) return groupedFields;\n\n const filtered = new Map<string, FilterFieldConfig[]>();\n for (const [group, groupFields] of groupedFields) {\n const matching = groupFields.filter(\n (f) =>\n f.label.toLowerCase().includes(searchQuery.toLowerCase()) ||\n f.key.toLowerCase().includes(searchQuery.toLowerCase())\n );\n if (matching.length > 0) {\n filtered.set(group, matching);\n }\n }\n return filtered;\n }, [groupedFields, searchQuery]);\n\n const handleFieldClick = useCallback(\n (field: FilterFieldConfig) => {\n const operator =\n field.defaultOperator ??\n getDefaultOperatorForFieldType(field.type, field.operators);\n const newFilter = createFilter(field.key, operator, []);\n onAddFilter(newFilter);\n setOpen(false);\n setSearchQuery(\"\");\n },\n [onAddFilter]\n );\n\n const sizeClasses = {\n sm: \"text-xs h-7 px-2\",\n default: \"text-sm h-8 px-2.5\",\n lg: \"text-base h-9 px-3\",\n };\n\n return (\n <Popover open={open} onOpenChange={setOpen}>\n <Popover.Trigger asChild>\n {trigger ?? (\n <Button\n variant=\"secondary\"\n size=\"sm\"\n className={cn(\n \"inline-flex items-center gap-1 whitespace-nowrap\",\n sizeClasses[size]\n )}\n >\n <Plus className=\"size-3.5\" />\n {i18n.addFilter}\n </Button>\n )}\n </Popover.Trigger>\n <Popover.Content className=\"w-64 p-2\">\n {showSearchInput && (\n <div className=\"mb-2\">\n <InputGroup className=\"w-full\">\n <InputGroup.Input\n value={searchQuery}\n onChange={(e) => setSearchQuery(e.target.value)}\n placeholder={i18n.searchPlaceholder}\n className=\"w-full\"\n />\n <InputGroup.Button>\n <MagnifyingGlass className=\"size-4\" />\n </InputGroup.Button>\n </InputGroup>\n </div>\n )}\n <div className=\"max-h-72 overflow-auto\">\n {filteredGroups.size === 0 ? (\n <div className=\"py-4 text-center text-sm text-sf-subtle\">\n {i18n.noResults}\n </div>\n ) : (\n Array.from(filteredGroups.entries()).map(\n ([group, groupFields], groupIndex) => (\n <div key={group}>\n {groupIndex > 0 && <div className=\"my-2 h-px bg-sf-line\" />}\n <div className=\"mb-1 px-2 text-xs font-medium text-sf-subtle\">\n {group}\n </div>\n <div className=\"flex flex-col gap-0.5\">\n {groupFields.map((field) => (\n <button\n key={field.key}\n type=\"button\"\n onClick={() => handleFieldClick(field)}\n disabled={\n !availableFields.some((f) => f.key === field.key)\n }\n className={cn(\n \"flex items-center gap-2 rounded-md px-2 py-1.5 text-left text-sm\",\n \"hover:bg-sf-tint\",\n \"disabled:cursor-not-allowed disabled:opacity-50\"\n )}\n >\n {field.icon}\n {field.label}\n </button>\n ))}\n </div>\n </div>\n )\n )\n )}\n </div>\n </Popover.Content>\n </Popover>\n );\n}\n\n// ============================================================================\n// Main Filters Component\n// ============================================================================\n\n/**\n * Filters component for building and managing active filter conditions.\n *\n * Supports multiple filter types (text, select, multiselect, custom), operators,\n * and an \"Add Filter\" popover interface. Designed to work standalone or with\n * DataGrid for advanced data filtering.\n *\n * @example\n * ```tsx\n * const [filters, setFilters] = useState<Filter[]>([]);\n * const fields: FilterFieldConfig[] = [\n * { key: \"status\", label: \"Status\", type: \"select\", options: [\n * { value: \"active\", label: \"Active\" },\n * { value: \"inactive\", label: \"Inactive\" },\n * ]},\n * { key: \"name\", label: \"Name\", type: \"text\" },\n * ];\n *\n * <Filters\n * filters={filters}\n * fields={fields}\n * onChange={setFilters}\n * />\n * ```\n */\nexport function Filters({\n filters,\n fields,\n onChange,\n size = SF_FILTERS_DEFAULT_VARIANTS.size,\n trigger,\n showSearchInput = true,\n allowMultiple = true,\n enableShortcut = true,\n shortcutKey = \"k\",\n shortcutLabel,\n i18n: i18nProp,\n className,\n menuPopupClassName,\n}: FiltersProps) {\n const i18n = useMemo(() => mergeI18n(i18nProp), [i18nProp]);\n\n // Keyboard shortcut\n useEffect(() => {\n if (!enableShortcut) return;\n\n const handleKeyDown = (e: KeyboardEvent) => {\n if ((e.metaKey || e.ctrlKey) && e.key === shortcutKey) {\n e.preventDefault();\n // The add menu popover will need to be opened via a ref or state\n // For now, this is a placeholder for the shortcut behavior\n }\n };\n\n document.addEventListener(\"keydown\", handleKeyDown);\n return () => document.removeEventListener(\"keydown\", handleKeyDown);\n }, [enableShortcut, shortcutKey]);\n\n const handleAddFilter = useCallback(\n (filter: Filter) => {\n onChange([...filters, filter]);\n },\n [filters, onChange]\n );\n\n const handleRemoveFilter = useCallback(\n (id: string) => {\n onChange(filters.filter((f) => f.id !== id));\n },\n [filters, onChange]\n );\n\n const handleOperatorChange = useCallback(\n (id: string, operator: string) => {\n onChange(filters.map((f) => (f.id === id ? { ...f, operator } : f)));\n },\n [filters, onChange]\n );\n\n const handleValuesChange = useCallback(\n (id: string, values: string[]) => {\n onChange(filters.map((f) => (f.id === id ? { ...f, values } : f)));\n },\n [filters, onChange]\n );\n\n const handleClearAll = useCallback(() => {\n onChange([]);\n }, [onChange]);\n\n const fieldMap = useMemo(() => {\n const map = new Map<string, FilterFieldConfig>();\n for (const field of fields) {\n map.set(field.key, field);\n }\n return map;\n }, [fields]);\n\n return (\n <div className={cn(\"flex flex-wrap items-center gap-2\", className)}>\n {/* Active filter pills */}\n {filters.map((filter) => {\n const field = fieldMap.get(filter.field);\n if (!field) return null;\n\n return (\n <FilterItem\n key={filter.id}\n filter={filter}\n field={field}\n size={size}\n i18n={i18n}\n onRemove={() => handleRemoveFilter(filter.id)}\n onOperatorChange={(op) => handleOperatorChange(filter.id, op)}\n onValuesChange={(vals) => handleValuesChange(filter.id, vals)}\n />\n );\n })}\n\n {/* Add filter menu */}\n <div className={menuPopupClassName}>\n <FilterAddMenu\n fields={fields}\n filters={filters}\n size={size}\n trigger={trigger}\n showSearchInput={showSearchInput}\n allowMultiple={allowMultiple}\n i18n={i18n}\n onAddFilter={handleAddFilter}\n />\n </div>\n\n {/* Clear all button */}\n {filters.length > 0 && (\n <Button\n variant=\"ghost\"\n size=\"sm\"\n onClick={handleClearAll}\n className=\"text-sf-subtle hover:text-sf-default\"\n >\n {i18n.clearAll}\n </Button>\n )}\n\n {/* Keyboard shortcut hint */}\n {enableShortcut && shortcutLabel && (\n <span className=\"ml-auto text-xs text-sf-subtle\">{shortcutLabel}</span>\n )}\n </div>\n );\n}\n\nFilters.displayName = \"Filters\";\n"],"mappings":"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"}