@signalflare-ai/ui 0.5.0 → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (316) hide show
  1. package/CHANGELOG.md +117 -1
  2. package/ai/USAGE.md +64 -0
  3. package/ai/component-registry.json +492 -618
  4. package/ai/component-registry.md +167 -85
  5. package/ai/schemas.ts +545 -102
  6. package/bin/sf.js +2 -3
  7. package/dist/.build-complete +1 -1
  8. package/dist/ai/schemas.d.ts +1659 -5532
  9. package/dist/ai/schemas.d.ts.map +1 -1
  10. package/dist/{ai-actions-DG1dhDMP.js → ai-actions-DSVeQn4e.js} +1 -1
  11. package/dist/{ai-actions-DG1dhDMP.js.map → ai-actions-DSVeQn4e.js.map} +1 -1
  12. package/dist/{ai-agent-card-BbtL4NII.js → ai-agent-card-BXHwhWAU.js} +1 -1
  13. package/dist/{ai-agent-card-BbtL4NII.js.map → ai-agent-card-BXHwhWAU.js.map} +1 -1
  14. package/dist/{ai-approval-Mb7-BY6i.js → ai-approval-aa0qvjFN.js} +1 -1
  15. package/dist/{ai-approval-Mb7-BY6i.js.map → ai-approval-aa0qvjFN.js.map} +1 -1
  16. package/dist/{ai-code-block-BI_z0UVR.js → ai-code-block-BgtIxtZZ.js} +1 -1
  17. package/dist/{ai-code-block-BI_z0UVR.js.map → ai-code-block-BgtIxtZZ.js.map} +1 -1
  18. package/dist/{ai-conversation-DYtExcrw.js → ai-conversation-CArP7C8K.js} +1 -1
  19. package/dist/{ai-conversation-DYtExcrw.js.map → ai-conversation-CArP7C8K.js.map} +1 -1
  20. package/dist/{ai-info-banner-BpzauUAY.js → ai-info-banner-uFxHHwBA.js} +1 -1
  21. package/dist/{ai-info-banner-BpzauUAY.js.map → ai-info-banner-uFxHHwBA.js.map} +1 -1
  22. package/dist/{ai-message-CV8SBoHM.js → ai-message-BjnFznXy.js} +1 -1
  23. package/dist/{ai-message-CV8SBoHM.js.map → ai-message-BjnFznXy.js.map} +1 -1
  24. package/dist/{ai-mission-header-ByYkJ6YP.js → ai-mission-header-08__gULL.js} +1 -1
  25. package/dist/{ai-mission-header-ByYkJ6YP.js.map → ai-mission-header-08__gULL.js.map} +1 -1
  26. package/dist/ai-part-group-DBtgTgAn.js +277 -0
  27. package/dist/ai-part-group-DBtgTgAn.js.map +1 -0
  28. package/dist/ai-prompt-input-Dy1LfxPk.js +1541 -0
  29. package/dist/ai-prompt-input-Dy1LfxPk.js.map +1 -0
  30. package/dist/{ai-question-Dp1g9k2o.js → ai-question-CHHoDJMg.js} +1 -1
  31. package/dist/{ai-question-Dp1g9k2o.js.map → ai-question-CHHoDJMg.js.map} +1 -1
  32. package/dist/{ai-reasoning-UAmNx_LD.js → ai-reasoning-CnL6ZSr5.js} +84 -5
  33. package/dist/ai-reasoning-CnL6ZSr5.js.map +1 -0
  34. package/dist/{ai-response-BWoVsNQG.js → ai-response-BEUg3xvd.js} +13 -16
  35. package/dist/ai-response-BEUg3xvd.js.map +1 -0
  36. package/dist/{ai-shimmer-BpOmfonu.js → ai-shimmer-By5_L05p.js} +1 -1
  37. package/dist/{ai-shimmer-BpOmfonu.js.map → ai-shimmer-By5_L05p.js.map} +1 -1
  38. package/dist/{ai-status-badge-WhbKVeqn.js → ai-status-badge-BGYGWYF6.js} +1 -1
  39. package/dist/{ai-status-badge-WhbKVeqn.js.map → ai-status-badge-BGYGWYF6.js.map} +1 -1
  40. package/dist/{ai-streaming-text-ClL7FwvD.js → ai-streaming-text-CMfoThV0.js} +1 -1
  41. package/dist/{ai-streaming-text-ClL7FwvD.js.map → ai-streaming-text-CMfoThV0.js.map} +1 -1
  42. package/dist/{ai-subagent-BruGN1UE.js → ai-subagent-DcPRqkAA.js} +1 -1
  43. package/dist/{ai-subagent-BruGN1UE.js.map → ai-subagent-DcPRqkAA.js.map} +1 -1
  44. package/dist/{ai-suggestion-CNsCZj5P.js → ai-suggestion-MgeCg5Ar.js} +1 -1
  45. package/dist/{ai-suggestion-CNsCZj5P.js.map → ai-suggestion-MgeCg5Ar.js.map} +1 -1
  46. package/dist/{ai-task-list-B9CpMDYN.js → ai-task-list-Da9zIm00.js} +9 -12
  47. package/dist/ai-task-list-Da9zIm00.js.map +1 -0
  48. package/dist/{ai-timeline-Bb5ntsr3.js → ai-timeline-Cwu045IR.js} +1 -1
  49. package/dist/ai-timeline-Cwu045IR.js.map +1 -0
  50. package/dist/{ai-tool-BGH8nQ_D.js → ai-tool-Cn1O4xjP.js} +168 -11
  51. package/dist/ai-tool-Cn1O4xjP.js.map +1 -0
  52. package/dist/{ai-usage-bar-BI-p-JBk.js → ai-usage-bar-DjS12DMp.js} +1 -1
  53. package/dist/{ai-usage-bar-BI-p-JBk.js.map → ai-usage-bar-DjS12DMp.js.map} +1 -1
  54. package/dist/catalog.js +3 -3
  55. package/dist/catalog.js.map +1 -1
  56. package/dist/{chart-Bes4MN3C.js → chart-BK3sVPnD.js} +442 -248
  57. package/dist/chart-BK3sVPnD.js.map +1 -0
  58. package/dist/{checkbox-CPX7lBaU.js → checkbox-DYhUmZNw.js} +4 -4
  59. package/dist/checkbox-DYhUmZNw.js.map +1 -0
  60. package/dist/{clipboard-text-92YeCybc.js → clipboard-text-ssybngLw.js} +2 -2
  61. package/dist/{clipboard-text-92YeCybc.js.map → clipboard-text-ssybngLw.js.map} +1 -1
  62. package/dist/{code-DE1Yy1Cu.js → code-Cx-QSoOT.js} +2 -2
  63. package/dist/{code-DE1Yy1Cu.js.map → code-Cx-QSoOT.js.map} +1 -1
  64. package/dist/{combobox-B0bLdsX8.js → combobox-C0iW6a0r.js} +2 -2
  65. package/dist/{combobox-B0bLdsX8.js.map → combobox-C0iW6a0r.js.map} +1 -1
  66. package/dist/command-line/cli.js +22 -27
  67. package/dist/{command-palette-CBTY8EiF.js → command-palette-DGzioeki.js} +2 -2
  68. package/dist/command-palette-DGzioeki.js.map +1 -0
  69. package/dist/components/ai-actions.js +1 -1
  70. package/dist/components/ai-agent-card.js +1 -1
  71. package/dist/components/ai-approval.js +1 -1
  72. package/dist/components/ai-code-block.js +1 -1
  73. package/dist/components/ai-conversation.js +1 -1
  74. package/dist/components/ai-info-banner.js +1 -1
  75. package/dist/components/ai-message.js +1 -1
  76. package/dist/components/ai-mission-header.js +1 -1
  77. package/dist/components/ai-part-group.js +3 -0
  78. package/dist/components/ai-prompt-input.js +2 -2
  79. package/dist/components/ai-question.js +1 -1
  80. package/dist/components/ai-reasoning.js +1 -1
  81. package/dist/components/ai-response.js +1 -1
  82. package/dist/components/ai-shimmer.js +1 -1
  83. package/dist/components/ai-status-badge.js +1 -1
  84. package/dist/components/ai-streaming-text.js +1 -1
  85. package/dist/components/ai-subagent.js +1 -1
  86. package/dist/components/ai-suggestion.js +1 -1
  87. package/dist/components/ai-task-list.js +1 -1
  88. package/dist/components/ai-timeline.js +1 -1
  89. package/dist/components/ai-tool.js +1 -1
  90. package/dist/components/ai-usage-bar.js +1 -1
  91. package/dist/components/chart.js +3 -2
  92. package/dist/components/checkbox.js +1 -1
  93. package/dist/components/clipboard-text.js +1 -1
  94. package/dist/components/code.js +1 -1
  95. package/dist/components/combobox.js +1 -1
  96. package/dist/components/command-palette.js +1 -1
  97. package/dist/components/data-grid.js +1 -1
  98. package/dist/components/date-picker.js +1 -1
  99. package/dist/components/dropdown.js +1 -1
  100. package/dist/components/filters.js +1 -1
  101. package/dist/components/input.js +2 -2
  102. package/dist/components/link.js +2 -2
  103. package/dist/components/link.js.map +1 -1
  104. package/dist/components/pagination.js +1 -1
  105. package/dist/components/radio.js +1 -1
  106. package/dist/components/select.js +1 -1
  107. package/dist/components/sensitive-input.js +1 -1
  108. package/dist/components/sidebar.js +1 -1
  109. package/dist/components/sparkline.js +3 -0
  110. package/dist/components/stat-card.js +3 -0
  111. package/dist/components/table.js +1 -1
  112. package/dist/components/text-roll.js +3 -0
  113. package/dist/components/theme-toggle.js +1 -1
  114. package/dist/components/use-agent-harness.js +1 -1
  115. package/dist/{data-grid-UJ9ja5cu.js → data-grid-CG76N_hK.js} +6 -6
  116. package/dist/data-grid-CG76N_hK.js.map +1 -0
  117. package/dist/{date-picker-ebekkC3R.js → date-picker-Dqg9L4xu.js} +2 -2
  118. package/dist/{date-picker-ebekkC3R.js.map → date-picker-Dqg9L4xu.js.map} +1 -1
  119. package/dist/{dist-BNlyONdD.js → dist-1-gcEL2L.js} +224 -135
  120. package/dist/dist-1-gcEL2L.js.map +1 -0
  121. package/dist/{dropdown-J5T4pHaR.js → dropdown-qnEYRFXZ.js} +2 -2
  122. package/dist/{dropdown-J5T4pHaR.js.map → dropdown-qnEYRFXZ.js.map} +1 -1
  123. package/dist/echart-DURZEyai.js +314 -0
  124. package/dist/echart-DURZEyai.js.map +1 -0
  125. package/dist/{filters-BdBogf7D.js → filters-Bw_U6ZTx.js} +5 -5
  126. package/dist/filters-Bw_U6ZTx.js.map +1 -0
  127. package/dist/flow-BRsYUCJa.js.map +1 -1
  128. package/dist/genui.js +2 -2
  129. package/dist/genui.js.map +1 -1
  130. package/dist/index.js +45 -42
  131. package/dist/index.js.map +1 -1
  132. package/dist/{input-BxQAnXki.js → input-DXYUjGgD.js} +2 -2
  133. package/dist/{input-BxQAnXki.js.map → input-DXYUjGgD.js.map} +1 -1
  134. package/dist/{input-Cn25I4o5.js → input-DddtBN-g.js} +2 -2
  135. package/dist/{input-Cn25I4o5.js.map → input-DddtBN-g.js.map} +1 -1
  136. package/dist/layer-card-BME0eljh.js.map +1 -1
  137. package/dist/{pagination-C_YqCy8l.js → pagination-BVqdlONY.js} +2 -2
  138. package/dist/{pagination-C_YqCy8l.js.map → pagination-BVqdlONY.js.map} +1 -1
  139. package/dist/primitives/otp-field.js +2 -0
  140. package/dist/primitives.js +1 -0
  141. package/dist/{radio-B7zg1wUI.js → radio-BNSwOt3B.js} +3 -3
  142. package/dist/radio-BNSwOt3B.js.map +1 -0
  143. package/dist/{select-9p721G00.js → select-1w2aebGQ.js} +2 -2
  144. package/dist/select-1w2aebGQ.js.map +1 -0
  145. package/dist/{sensitive-input-D5je2NLl.js → sensitive-input-82Cez3vj.js} +2 -2
  146. package/dist/{sensitive-input-D5je2NLl.js.map → sensitive-input-82Cez3vj.js.map} +1 -1
  147. package/dist/{sidebar-DOwBrq57.js → sidebar-CAsCmSpM.js} +3 -3
  148. package/dist/sidebar-CAsCmSpM.js.map +1 -0
  149. package/dist/sparkline-DdbeM4Ai.js +108 -0
  150. package/dist/sparkline-DdbeM4Ai.js.map +1 -0
  151. package/dist/src/blocks/agent-harness/agent-harness.d.ts +30 -9
  152. package/dist/src/blocks/agent-harness/agent-harness.d.ts.map +1 -1
  153. package/dist/src/blocks/agent-harness/agent-harness.stories.tsx +114 -0
  154. package/dist/src/blocks/agent-harness/agent-harness.tsx +144 -63
  155. package/dist/src/blocks/commander/commander.stories.tsx +31 -0
  156. package/dist/src/blocks/dashboard-grid/dashboard-grid.d.ts +48 -0
  157. package/dist/src/blocks/dashboard-grid/dashboard-grid.d.ts.map +1 -0
  158. package/dist/src/blocks/dashboard-grid/dashboard-grid.stories.tsx +19 -0
  159. package/dist/src/blocks/dashboard-grid/dashboard-grid.tsx +110 -0
  160. package/dist/src/blocks/dashboard-grid/index.d.ts +2 -0
  161. package/dist/src/blocks/dashboard-grid/index.d.ts.map +1 -0
  162. package/dist/src/blocks/delete-resource/delete-resource.stories.tsx +31 -0
  163. package/dist/src/blocks/map-block/map-block.stories.tsx +41 -0
  164. package/dist/src/blocks/metrics-overview/index.d.ts +2 -0
  165. package/dist/src/blocks/metrics-overview/index.d.ts.map +1 -0
  166. package/dist/src/blocks/metrics-overview/metrics-overview.d.ts +67 -0
  167. package/dist/src/blocks/metrics-overview/metrics-overview.d.ts.map +1 -0
  168. package/dist/src/blocks/metrics-overview/metrics-overview.stories.tsx +26 -0
  169. package/dist/src/blocks/metrics-overview/metrics-overview.tsx +139 -0
  170. package/dist/src/blocks/page-header/page-header.stories.tsx +56 -0
  171. package/dist/src/blocks/resource-list/resource-list.stories.tsx +31 -0
  172. package/dist/src/catalog/catalog.d.ts +1 -1
  173. package/dist/src/catalog/index.d.ts +1 -1
  174. package/dist/src/catalog/types.d.ts +1 -1
  175. package/dist/src/command-line/build-cli.d.ts +1 -1
  176. package/dist/src/command-line/cli.d.ts +1 -1
  177. package/dist/src/command-line/commands/add.d.ts +1 -1
  178. package/dist/src/command-line/commands/add.d.ts.map +1 -1
  179. package/dist/src/command-line/commands/ai.d.ts.map +1 -1
  180. package/dist/src/command-line/commands/blocks.d.ts +1 -1
  181. package/dist/src/command-line/commands/blocks.d.ts.map +1 -1
  182. package/dist/src/command-line/commands/doc.d.ts +1 -1
  183. package/dist/src/command-line/commands/doc.d.ts.map +1 -1
  184. package/dist/src/command-line/commands/ls.d.ts +1 -1
  185. package/dist/src/command-line/commands/ls.d.ts.map +1 -1
  186. package/dist/src/command-line/commands/migrate.d.ts +3 -3
  187. package/dist/src/command-line/commands/migrate.d.ts.map +1 -1
  188. package/dist/src/command-line/utils/config.d.ts +1 -1
  189. package/dist/src/command-line/utils/transformer.d.ts +1 -1
  190. package/dist/src/components/ai-part-group/ai-part-group.d.ts +134 -0
  191. package/dist/src/components/ai-part-group/ai-part-group.d.ts.map +1 -0
  192. package/dist/src/components/ai-part-group/index.d.ts +2 -0
  193. package/dist/src/components/ai-part-group/index.d.ts.map +1 -0
  194. package/dist/src/components/ai-prompt-input/ai-prompt-input.d.ts +196 -7
  195. package/dist/src/components/ai-prompt-input/ai-prompt-input.d.ts.map +1 -1
  196. package/dist/src/components/ai-prompt-input/controller.d.ts +41 -0
  197. package/dist/src/components/ai-prompt-input/controller.d.ts.map +1 -0
  198. package/dist/src/components/ai-prompt-input/index.d.ts +3 -1
  199. package/dist/src/components/ai-prompt-input/index.d.ts.map +1 -1
  200. package/dist/src/components/ai-prompt-input/types.d.ts +86 -0
  201. package/dist/src/components/ai-prompt-input/types.d.ts.map +1 -0
  202. package/dist/src/components/ai-reasoning/ai-reasoning.d.ts +17 -1
  203. package/dist/src/components/ai-reasoning/ai-reasoning.d.ts.map +1 -1
  204. package/dist/src/components/ai-response/ai-response.d.ts +1 -2
  205. package/dist/src/components/ai-response/ai-response.d.ts.map +1 -1
  206. package/dist/src/components/ai-task-list/ai-task-list.d.ts.map +1 -1
  207. package/dist/src/components/ai-tool/ai-tool.d.ts +17 -1
  208. package/dist/src/components/ai-tool/ai-tool.d.ts.map +1 -1
  209. package/dist/src/components/chart/area-chart.d.ts +69 -0
  210. package/dist/src/components/chart/area-chart.d.ts.map +1 -0
  211. package/dist/src/components/chart/bar-chart.d.ts +60 -0
  212. package/dist/src/components/chart/bar-chart.d.ts.map +1 -0
  213. package/dist/src/components/chart/color.d.ts +56 -0
  214. package/dist/src/components/chart/color.d.ts.map +1 -1
  215. package/dist/src/components/chart/echart.d.ts.map +1 -1
  216. package/dist/src/components/chart/index.d.ts +5 -0
  217. package/dist/src/components/chart/index.d.ts.map +1 -1
  218. package/dist/src/components/chart/pie-chart.d.ts +64 -0
  219. package/dist/src/components/chart/pie-chart.d.ts.map +1 -0
  220. package/dist/src/components/chart/scatter-chart.d.ts +57 -0
  221. package/dist/src/components/chart/scatter-chart.d.ts.map +1 -0
  222. package/dist/src/components/chart/stacked-bar-chart.d.ts +59 -0
  223. package/dist/src/components/chart/stacked-bar-chart.d.ts.map +1 -0
  224. package/dist/src/components/chart/timeseries-chart.d.ts.map +1 -1
  225. package/dist/src/components/code/code.d.ts +1 -1
  226. package/dist/src/components/command-palette/command-palette.d.ts +1 -1
  227. package/dist/src/components/data-grid/data-grid.d.ts.map +1 -1
  228. package/dist/src/components/data-grid/index.d.ts +1 -1
  229. package/dist/src/components/data-grid/index.d.ts.map +1 -1
  230. package/dist/src/components/data-grid/types.d.ts.map +1 -1
  231. package/dist/src/components/date-picker/date-picker.d.ts +2 -2
  232. package/dist/src/components/filters/filters.d.ts.map +1 -1
  233. package/dist/src/components/filters/helpers.d.ts.map +1 -1
  234. package/dist/src/components/filters/types.d.ts.map +1 -1
  235. package/dist/src/components/layer-card/layer-card.d.ts +1 -1
  236. package/dist/src/components/link/link.d.ts +2 -2
  237. package/dist/src/components/radio/radio.d.ts +1 -1
  238. package/dist/src/components/select/select.d.ts +1 -1
  239. package/dist/src/components/sidebar/sidebar.d.ts +2 -2
  240. package/dist/src/components/sparkline/index.d.ts +2 -0
  241. package/dist/src/components/sparkline/index.d.ts.map +1 -0
  242. package/dist/src/components/sparkline/sparkline.d.ts +52 -0
  243. package/dist/src/components/sparkline/sparkline.d.ts.map +1 -0
  244. package/dist/src/components/stat-card/index.d.ts +2 -0
  245. package/dist/src/components/{ai-loader → stat-card}/index.d.ts.map +1 -1
  246. package/dist/src/components/stat-card/stat-card.d.ts +80 -0
  247. package/dist/src/components/stat-card/stat-card.d.ts.map +1 -0
  248. package/dist/src/components/text-roll/index.d.ts +2 -0
  249. package/dist/src/components/text-roll/index.d.ts.map +1 -0
  250. package/dist/src/components/text-roll/text-roll.d.ts +49 -0
  251. package/dist/src/components/text-roll/text-roll.d.ts.map +1 -0
  252. package/dist/src/components/toast/toast.d.ts.map +1 -1
  253. package/dist/src/components/use-agent-harness/use-agent-harness.d.ts +2 -2
  254. package/dist/src/genui/genui.d.ts.map +1 -1
  255. package/dist/src/index.d.ts +5 -2
  256. package/dist/src/index.d.ts.map +1 -1
  257. package/dist/src/primitives/index.d.ts +1 -0
  258. package/dist/src/primitives/index.d.ts.map +1 -1
  259. package/dist/src/primitives/otp-field.d.ts +13 -0
  260. package/dist/src/primitives/otp-field.d.ts.map +1 -0
  261. package/dist/src/registry/index.d.ts +1 -1
  262. package/dist/src/registry/types.d.ts +1 -1
  263. package/dist/stat-card-CEZscNh8.js +103 -0
  264. package/dist/stat-card-CEZscNh8.js.map +1 -0
  265. package/dist/styles/sf-binding.css +20 -62
  266. package/dist/styles/sf-standalone.css +2 -2
  267. package/dist/styles/shadcn.css +120 -0
  268. package/dist/styles/theme-blue-tint.css +98 -0
  269. package/dist/styles/theme-fedramp.css +3 -12
  270. package/dist/styles/theme-minimal.css +26 -104
  271. package/dist/styles/theme-sf.css +96 -114
  272. package/dist/{table-CIMx0Oq0.js → table-Rv4JMy0B.js} +2 -2
  273. package/dist/{table-CIMx0Oq0.js.map → table-Rv4JMy0B.js.map} +1 -1
  274. package/dist/text-roll-BZ3I1umc.js +79 -0
  275. package/dist/text-roll-BZ3I1umc.js.map +1 -0
  276. package/dist/{theme-toggle-Dpgnoj_Q.js → theme-toggle-Bhu681D7.js} +1 -1
  277. package/dist/{theme-toggle-Dpgnoj_Q.js.map → theme-toggle-Bhu681D7.js.map} +1 -1
  278. package/dist/{use-agent-harness-DZzcn96L.js → use-agent-harness-BMyF8pTq.js} +5 -5
  279. package/dist/use-agent-harness-BMyF8pTq.js.map +1 -0
  280. package/package.json +48 -19
  281. package/scripts/component-registry/discovery.ts +2 -2
  282. package/scripts/component-registry/index.ts +1 -1
  283. package/scripts/component-registry/props-filter.ts +1 -1
  284. package/scripts/component-registry/utils.ts +5 -5
  285. package/scripts/component-registry/variant-parser.ts +124 -19
  286. package/scripts/convert-demos-to-stories.ts +253 -0
  287. package/scripts/css-build.ts +4 -3
  288. package/scripts/generate-primitives.ts +11 -3
  289. package/scripts/theme-generator/config.ts +339 -71
  290. package/scripts/theme-generator/generate-css.ts +17 -3
  291. package/scripts/theme-generator/index.ts +3 -3
  292. package/scripts/theme-generator/migrate.ts +1 -1
  293. package/dist/ai-loader-Cr3eQkNS.js +0 -134
  294. package/dist/ai-loader-Cr3eQkNS.js.map +0 -1
  295. package/dist/ai-prompt-input-Bo1YuJly.js +0 -769
  296. package/dist/ai-prompt-input-Bo1YuJly.js.map +0 -1
  297. package/dist/ai-reasoning-UAmNx_LD.js.map +0 -1
  298. package/dist/ai-response-BWoVsNQG.js.map +0 -1
  299. package/dist/ai-task-list-B9CpMDYN.js.map +0 -1
  300. package/dist/ai-timeline-Bb5ntsr3.js.map +0 -1
  301. package/dist/ai-tool-BGH8nQ_D.js.map +0 -1
  302. package/dist/chart-Bes4MN3C.js.map +0 -1
  303. package/dist/checkbox-CPX7lBaU.js.map +0 -1
  304. package/dist/command-palette-CBTY8EiF.js.map +0 -1
  305. package/dist/components/ai-loader.js +0 -3
  306. package/dist/data-grid-UJ9ja5cu.js.map +0 -1
  307. package/dist/dist-BNlyONdD.js.map +0 -1
  308. package/dist/filters-BdBogf7D.js.map +0 -1
  309. package/dist/radio-B7zg1wUI.js.map +0 -1
  310. package/dist/select-9p721G00.js.map +0 -1
  311. package/dist/sidebar-DOwBrq57.js.map +0 -1
  312. package/dist/src/components/ai-loader/ai-loader.d.ts +0 -44
  313. package/dist/src/components/ai-loader/ai-loader.d.ts.map +0 -1
  314. package/dist/src/components/ai-loader/index.d.ts +0 -2
  315. package/dist/styles/theme-navigator.css +0 -137
  316. package/dist/use-agent-harness-DZzcn96L.js.map +0 -1
@@ -1,769 +0,0 @@
1
- "use client";
2
- import { t as cn } from "./cn-YROP2_ox.js";
3
- import { t as Tooltip } from "./tooltip-Cb7QW-7H.js";
4
- import { t as Button } from "./button-De0267YU.js";
5
- import { t as InputGroup } from "./input-Cn25I4o5.js";
6
- import { Fragment, createContext, useCallback, useContext, useEffect, useLayoutEffect, useMemo, useRef, useState } from "react";
7
- import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
8
- import { ArrowUpIcon, CaretDownIcon, FileIcon, FileTextIcon, ImageIcon, MicrophoneIcon, PaperclipIcon, PlusIcon, SpinnerGapIcon, SquareIcon, XIcon } from "@phosphor-icons/react";
9
- import { Menu } from "@base-ui/react/menu";
10
- //#region src/components/ai-prompt-input/ai-prompt-input.tsx
11
- var SF_AI_PROMPT_INPUT_VARIANTS = { status: {
12
- idle: {
13
- classes: "",
14
- description: "Ready to accept input"
15
- },
16
- submitted: {
17
- classes: "",
18
- description: "Waiting for response (shows spinner)"
19
- },
20
- streaming: {
21
- classes: "",
22
- description: "Streaming response (shows stop)"
23
- },
24
- error: {
25
- classes: "",
26
- description: "Error state (shows X)"
27
- }
28
- } };
29
- var SF_AI_PROMPT_INPUT_DEFAULT_VARIANTS = { status: "idle" };
30
- var PromptInputContext = createContext(null);
31
- var ProviderAttachmentsContext = createContext(null);
32
- var usePromptInputController = () => {
33
- const ctx = useContext(PromptInputContext);
34
- if (!ctx) throw new Error("Wrap your component inside <PromptInputProvider> to use usePromptInputController().");
35
- return ctx;
36
- };
37
- var useOptionalPromptInputController = () => useContext(PromptInputContext);
38
- var useProviderAttachments = () => {
39
- const ctx = useContext(ProviderAttachmentsContext);
40
- if (!ctx) throw new Error("Wrap your component inside <PromptInputProvider> to use useProviderAttachments().");
41
- return ctx;
42
- };
43
- var useOptionalProviderAttachments = () => useContext(ProviderAttachmentsContext);
44
- /**
45
- * Optional global provider that lifts PromptInput state outside of PromptInput.
46
- * If you don't use it, PromptInput stays fully self-managed.
47
- *
48
- * @example
49
- * ```tsx
50
- * <PromptInputProvider>
51
- * <PromptInput onSubmit={handleSubmit}>...</PromptInput>
52
- * </PromptInputProvider>
53
- * ```
54
- */
55
- function PromptInputProvider({ initialInput = "", children }) {
56
- const [textInput, setTextInput] = useState(initialInput);
57
- const clearInput = useCallback(() => setTextInput(""), []);
58
- const [attachmentItems, setAttachmentItems] = useState([]);
59
- const fileInputRef = useRef(null);
60
- const openRef = useRef(() => {});
61
- const add = useCallback((files) => {
62
- const incoming = Array.from(files);
63
- if (incoming.length === 0) return;
64
- setAttachmentItems((prev) => prev.concat(incoming.map((file) => ({
65
- id: `${Date.now()}-${Math.random()}`,
66
- url: URL.createObjectURL(file),
67
- mediaType: file.type,
68
- filename: file.name
69
- }))));
70
- }, []);
71
- const remove = useCallback((id) => {
72
- setAttachmentItems((prev) => {
73
- const found = prev.find((f) => f.id === id);
74
- if (found?.url) URL.revokeObjectURL(found.url);
75
- return prev.filter((f) => f.id !== id);
76
- });
77
- }, []);
78
- const clear = useCallback(() => {
79
- setAttachmentItems((prev) => {
80
- for (const f of prev) if (f.url) URL.revokeObjectURL(f.url);
81
- return [];
82
- });
83
- }, []);
84
- const openFileDialog = useCallback(() => {
85
- openRef.current?.();
86
- }, []);
87
- const attachments = useMemo(() => ({
88
- files: attachmentItems,
89
- add,
90
- remove,
91
- clear,
92
- openFileDialog,
93
- fileInputRef
94
- }), [
95
- attachmentItems,
96
- add,
97
- remove,
98
- clear,
99
- openFileDialog
100
- ]);
101
- const __registerFileInput = useCallback((ref, open) => {
102
- fileInputRef.current = ref.current;
103
- openRef.current = open;
104
- }, []);
105
- const controller = useMemo(() => ({
106
- textInput: {
107
- value: textInput,
108
- setInput: setTextInput,
109
- clear: clearInput
110
- },
111
- attachments,
112
- __registerFileInput
113
- }), [
114
- textInput,
115
- clearInput,
116
- attachments,
117
- __registerFileInput
118
- ]);
119
- return /* @__PURE__ */ jsx(PromptInputContext.Provider, {
120
- value: controller,
121
- children: /* @__PURE__ */ jsx(ProviderAttachmentsContext.Provider, {
122
- value: attachments,
123
- children
124
- })
125
- });
126
- }
127
- var LocalAttachmentsContext = createContext(null);
128
- var usePromptInputAttachments = () => {
129
- const provider = useOptionalProviderAttachments();
130
- const local = useContext(LocalAttachmentsContext);
131
- const context = provider ?? local;
132
- if (!context) throw new Error("usePromptInputAttachments must be used within a PromptInput or PromptInputProvider");
133
- return context;
134
- };
135
- /** Convert a blob URL to a base64 data URL for serialization. */
136
- async function convertBlobToDataUrl(url) {
137
- const blob = await (await fetch(url)).blob();
138
- return new Promise((resolve, reject) => {
139
- const reader = new FileReader();
140
- reader.addEventListener("loadend", () => resolve(reader.result));
141
- reader.addEventListener("error", () => reject(/* @__PURE__ */ new Error("FileReader error")));
142
- reader.readAsDataURL(blob);
143
- });
144
- }
145
- function makeAttachmentId() {
146
- return `${Date.now()}-${Math.random()}`;
147
- }
148
- /**
149
- * Prompt input form. Can be self-managed or controlled via `PromptInputProvider`.
150
- *
151
- * @example
152
- * ```tsx
153
- * <PromptInput onSubmit={({ text, files }) => send(text, files)}>
154
- * <PromptInputAttachments>{(f) => <PromptInputAttachment data={f} />}</PromptInputAttachments>
155
- * <PromptInputTextarea placeholder="Ask anything…" />
156
- * <PromptInputToolbar>
157
- * <PromptInputTools>
158
- * <PromptInputAttachButton />
159
- * </PromptInputTools>
160
- * <PromptInputSubmit />
161
- * </PromptInputToolbar>
162
- * </PromptInput>
163
- * ```
164
- */
165
- var PromptInput = ({ className, accept, multiple, globalDrop, maxFiles, maxFileSize, onError, onSubmit, children, backLayer, backLayerTitle = "Context", backLayerOpen, onBackLayerOpenChange, autoOpenBackLayerWhen, ...props }) => {
166
- const hasBackLayer = backLayer !== void 0;
167
- const controller = useOptionalPromptInputController();
168
- const usingProvider = !!controller;
169
- const inputRef = useRef(null);
170
- const anchorRef = useRef(null);
171
- const formRef = useRef(null);
172
- useEffect(() => {
173
- const root = anchorRef.current?.closest("form");
174
- if (root instanceof HTMLFormElement) formRef.current = root;
175
- }, []);
176
- useEffect(() => {
177
- if (autoOpenBackLayerWhen) onBackLayerOpenChange?.(true);
178
- }, [autoOpenBackLayerWhen, onBackLayerOpenChange]);
179
- const [items, setItems] = useState([]);
180
- const files = usingProvider ? controller.attachments.files : items;
181
- const openFileDialogLocal = useCallback(() => {
182
- inputRef.current?.click();
183
- }, []);
184
- const matchesAccept = useCallback((f) => {
185
- if (!accept || accept.trim() === "") return true;
186
- if (accept.includes("image/*")) return f.type.startsWith("image/");
187
- return true;
188
- }, [accept]);
189
- const addLocal = useCallback((fileList) => {
190
- const incoming = Array.from(fileList);
191
- const accepted = incoming.filter((f) => matchesAccept(f));
192
- if (incoming.length && accepted.length === 0) {
193
- onError?.({
194
- code: "accept",
195
- message: "No files match the accepted types."
196
- });
197
- return;
198
- }
199
- const withinSize = (f) => maxFileSize ? f.size <= maxFileSize : true;
200
- const sized = accepted.filter(withinSize);
201
- if (accepted.length > 0 && sized.length === 0) {
202
- onError?.({
203
- code: "max_file_size",
204
- message: "All files exceed the maximum size."
205
- });
206
- return;
207
- }
208
- setItems((prev) => {
209
- const capacity = typeof maxFiles === "number" ? Math.max(0, maxFiles - prev.length) : void 0;
210
- const capped = typeof capacity === "number" ? sized.slice(0, capacity) : sized;
211
- if (typeof capacity === "number" && sized.length > capacity) onError?.({
212
- code: "max_files",
213
- message: "Too many files. Some were not added."
214
- });
215
- const next = capped.map((file) => ({
216
- id: makeAttachmentId(),
217
- url: URL.createObjectURL(file),
218
- mediaType: file.type,
219
- filename: file.name
220
- }));
221
- return prev.concat(next);
222
- });
223
- }, [
224
- matchesAccept,
225
- maxFiles,
226
- maxFileSize,
227
- onError
228
- ]);
229
- const add = usingProvider ? (f) => controller.attachments.add(f) : addLocal;
230
- const remove = usingProvider ? (id) => controller.attachments.remove(id) : (id) => setItems((prev) => {
231
- const found = prev.find((f) => f.id === id);
232
- if (found?.url) URL.revokeObjectURL(found.url);
233
- return prev.filter((f) => f.id !== id);
234
- });
235
- const clear = usingProvider ? () => controller.attachments.clear() : () => setItems((prev) => {
236
- for (const f of prev) if (f.url) URL.revokeObjectURL(f.url);
237
- return [];
238
- });
239
- const openFileDialog = usingProvider ? () => controller.attachments.openFileDialog() : openFileDialogLocal;
240
- useEffect(() => {
241
- if (!usingProvider) return;
242
- controller.__registerFileInput(inputRef, () => inputRef.current?.click());
243
- }, [usingProvider, controller]);
244
- useEffect(() => {
245
- const form = formRef.current;
246
- if (!form) return;
247
- const onDragOver = (e) => {
248
- if (e.dataTransfer?.types?.includes("Files")) e.preventDefault();
249
- };
250
- const onDrop = (e) => {
251
- if (e.dataTransfer?.types?.includes("Files")) e.preventDefault();
252
- if (e.dataTransfer?.files && e.dataTransfer.files.length > 0) add(e.dataTransfer.files);
253
- };
254
- form.addEventListener("dragover", onDragOver);
255
- form.addEventListener("drop", onDrop);
256
- return () => {
257
- form.removeEventListener("dragover", onDragOver);
258
- form.removeEventListener("drop", onDrop);
259
- };
260
- }, [add]);
261
- useEffect(() => {
262
- if (!globalDrop) return;
263
- const onDragOver = (e) => {
264
- if (e.dataTransfer?.types?.includes("Files")) e.preventDefault();
265
- };
266
- const onDrop = (e) => {
267
- if (e.dataTransfer?.types?.includes("Files")) e.preventDefault();
268
- if (e.dataTransfer?.files && e.dataTransfer.files.length > 0) add(e.dataTransfer.files);
269
- };
270
- document.addEventListener("dragover", onDragOver);
271
- document.addEventListener("drop", onDrop);
272
- return () => {
273
- document.removeEventListener("dragover", onDragOver);
274
- document.removeEventListener("drop", onDrop);
275
- };
276
- }, [add, globalDrop]);
277
- useEffect(() => {
278
- return () => {
279
- if (!usingProvider) {
280
- for (const f of files) if (f.url) URL.revokeObjectURL(f.url);
281
- }
282
- };
283
- }, [usingProvider, files]);
284
- const handleFileInputChange = (event) => {
285
- if (event.currentTarget.files) add(event.currentTarget.files);
286
- };
287
- const ctx = useMemo(() => ({
288
- files,
289
- add,
290
- remove,
291
- clear,
292
- openFileDialog,
293
- fileInputRef: inputRef
294
- }), [
295
- files,
296
- add,
297
- remove,
298
- clear,
299
- openFileDialog
300
- ]);
301
- const handleSubmit = (event) => {
302
- event.preventDefault();
303
- const form = event.currentTarget;
304
- const text = usingProvider ? controller.textInput.value : new FormData(form).get("message") || "";
305
- if (!usingProvider) form.reset();
306
- const doSubmit = async () => {
307
- const convertedFiles = await Promise.all(files.map(async (item) => {
308
- if (item.url.startsWith("blob:")) return {
309
- ...item,
310
- url: await convertBlobToDataUrl(item.url)
311
- };
312
- return item;
313
- }));
314
- try {
315
- await onSubmit({
316
- text,
317
- files: convertedFiles
318
- }, event);
319
- clear();
320
- if (usingProvider) controller.textInput.clear();
321
- } catch {}
322
- };
323
- doSubmit().catch(() => {});
324
- };
325
- const isBackLayerOpen = backLayerOpen ?? false;
326
- const inputShell = hasBackLayer ? /* @__PURE__ */ jsxs("div", {
327
- className: "flex w-full flex-col overflow-hidden rounded-xl bg-sf-elevated ring ring-sf-line/50",
328
- children: [
329
- /* @__PURE__ */ jsxs("button", {
330
- "aria-expanded": isBackLayerOpen,
331
- "aria-label": isBackLayerOpen ? "Collapse context" : "Expand context",
332
- className: "flex w-full items-center justify-between gap-2 px-3 py-2 text-left",
333
- onClick: () => onBackLayerOpenChange?.(!isBackLayerOpen),
334
- type: "button",
335
- children: [/* @__PURE__ */ jsx("span", {
336
- className: "text-sm font-medium text-sf-subtle uppercase tracking-wide select-none",
337
- children: backLayerTitle
338
- }), /* @__PURE__ */ jsx(CaretDownIcon, { className: cn("size-3.5 text-sf-subtle transition-transform duration-200", isBackLayerOpen && "rotate-180") })]
339
- }),
340
- /* @__PURE__ */ jsx(PromptInputBackLayerPanel, {
341
- open: isBackLayerOpen,
342
- children: backLayer
343
- }),
344
- /* @__PURE__ */ jsx("div", {
345
- className: "flex flex-col overflow-hidden rounded-xl bg-sf-base ring ring-sf-line/50 focus-within:ring-sf-ring",
346
- children
347
- })
348
- ]
349
- }) : /* @__PURE__ */ jsx(InputGroup, { children });
350
- const inner = /* @__PURE__ */ jsxs(Fragment$1, { children: [
351
- /* @__PURE__ */ jsx("span", {
352
- "aria-hidden": "true",
353
- className: "hidden",
354
- ref: anchorRef
355
- }),
356
- /* @__PURE__ */ jsx("input", {
357
- accept,
358
- "aria-label": "Upload files",
359
- className: "hidden",
360
- multiple,
361
- onChange: handleFileInputChange,
362
- ref: inputRef,
363
- type: "file"
364
- }),
365
- /* @__PURE__ */ jsx("form", {
366
- className: cn("w-full", className),
367
- onSubmit: handleSubmit,
368
- ...props,
369
- children: inputShell
370
- })
371
- ] });
372
- return usingProvider ? inner : /* @__PURE__ */ jsx(LocalAttachmentsContext.Provider, {
373
- value: ctx,
374
- children: inner
375
- });
376
- };
377
- var PromptInputBody = ({ className, ...props }) => /* @__PURE__ */ jsx("div", {
378
- className: cn("contents", className),
379
- ...props
380
- });
381
- function PromptInputBackLayerPanel({ open, children }) {
382
- const isOpen = open ?? false;
383
- return /* @__PURE__ */ jsx("div", {
384
- "aria-hidden": !isOpen,
385
- className: "grid",
386
- style: {
387
- gridTemplateRows: isOpen ? "1fr" : "0fr",
388
- opacity: isOpen ? 1 : 0,
389
- transition: "grid-template-rows 200ms ease-out, opacity 200ms ease-out"
390
- },
391
- children: /* @__PURE__ */ jsx("div", {
392
- className: "min-h-0 overflow-hidden",
393
- children
394
- })
395
- });
396
- }
397
- /**
398
- * Container for back-layer content (HITL approvals, task lists, agent status,
399
- * etc.). Pass instances of this as the `backLayer` prop on `PromptInput`.
400
- *
401
- * @example
402
- * ```tsx
403
- * <PromptInput
404
- * onSubmit={handleSubmit}
405
- * backLayer={<PromptInputBackLayer>...</PromptInputBackLayer>}
406
- * backLayerOpen={open}
407
- * onBackLayerOpenChange={setOpen}
408
- * >
409
- * <PromptInputTextarea />
410
- * <PromptInputToolbar>
411
- * <PromptInputTools />
412
- * <PromptInputSubmit />
413
- * </PromptInputToolbar>
414
- * </PromptInput>
415
- * ```
416
- */
417
- function PromptInputBackLayer({ children, className }) {
418
- return /* @__PURE__ */ jsx("div", {
419
- className: cn("flex flex-col gap-2 px-3 py-2.5 text-sm text-sf-default", className),
420
- children
421
- });
422
- }
423
- var handleTextareaKeyDown = (e) => {
424
- if (e.key === "Enter") {
425
- if (e.nativeEvent.isComposing) return;
426
- if (e.shiftKey) return;
427
- e.preventDefault();
428
- e.currentTarget.form?.requestSubmit();
429
- }
430
- };
431
- /**
432
- * Auto-resizing textarea for the prompt. Submits on Enter (Shift+Enter for newline).
433
- * Pastes files into attachments.
434
- */
435
- var PromptInputTextarea = ({ onChange, className, placeholder = "What would you like to know?", ...props }) => {
436
- const controller = useOptionalPromptInputController();
437
- const attachments = usePromptInputAttachments();
438
- const handlePaste = (event) => {
439
- const items = event.clipboardData?.items;
440
- if (!items) return;
441
- const pastedFiles = [];
442
- for (const item of items) if (item.kind === "file") {
443
- const file = item.getAsFile();
444
- if (file) pastedFiles.push(file);
445
- }
446
- if (pastedFiles.length > 0) {
447
- event.preventDefault();
448
- attachments.add(pastedFiles);
449
- }
450
- };
451
- const controlledProps = controller ? {
452
- value: controller.textInput.value,
453
- onChange: (e) => {
454
- controller.textInput.setInput(e.currentTarget.value);
455
- onChange?.(e);
456
- }
457
- } : { onChange };
458
- return /* @__PURE__ */ jsx("textarea", {
459
- className: cn("field-sizing-content max-h-48 min-h-16 w-full resize-none border-0 bg-transparent px-3 py-2 text-sm text-sf-default outline-none placeholder:text-sf-inactive", className),
460
- name: "message",
461
- onKeyDown: handleTextareaKeyDown,
462
- onPaste: handlePaste,
463
- placeholder,
464
- rows: 1,
465
- ...props,
466
- ...controlledProps
467
- });
468
- };
469
- var PromptInputToolbar = ({ className, ...props }) => /* @__PURE__ */ jsx("div", {
470
- className: cn("flex items-center justify-between gap-1 px-2 py-1.5", className),
471
- ...props
472
- });
473
- var PromptInputTools = ({ className, ...props }) => /* @__PURE__ */ jsx("div", {
474
- className: cn("flex items-center gap-1", className),
475
- ...props
476
- });
477
- var PromptInputButton = ({ variant = "ghost", size = "sm", className, ...props }) => /* @__PURE__ */ jsx(Button, {
478
- className: cn("text-sf-subtle hover:text-sf-default", className),
479
- size,
480
- type: "button",
481
- variant,
482
- ...props
483
- });
484
- /**
485
- * Submit button. Icon changes based on `status`:
486
- * - `idle` → send arrow
487
- * - `submitted` → spinner
488
- * - `streaming` → stop square
489
- * - `error` → X
490
- */
491
- var PromptInputSubmit = ({ className, variant = "primary", size = "sm", status = "idle", children, ...props }) => {
492
- let Icon;
493
- if (status === "submitted") Icon = /* @__PURE__ */ jsx(SpinnerGapIcon, { className: "size-4 animate-spin" });
494
- else if (status === "streaming") Icon = /* @__PURE__ */ jsx(SquareIcon, { className: "size-4" });
495
- else if (status === "error") Icon = /* @__PURE__ */ jsx(XIcon, { className: "size-4" });
496
- else Icon = /* @__PURE__ */ jsx(ArrowUpIcon, { className: "size-4" });
497
- return /* @__PURE__ */ jsx(Button, {
498
- "aria-label": "Submit",
499
- className: cn(className),
500
- size,
501
- type: "submit",
502
- variant,
503
- ...props,
504
- children: children ?? Icon
505
- });
506
- };
507
- var DropdownMenu = Menu;
508
- var PromptInputActionMenu = (props) => /* @__PURE__ */ jsx(DropdownMenu.Root, { ...props });
509
- var PromptInputActionMenuTrigger = ({ className, children, "aria-label": ariaLabel = "More actions", ...props }) => /* @__PURE__ */ jsx(DropdownMenu.Trigger, { render: /* @__PURE__ */ jsx(Button, {
510
- "aria-label": ariaLabel,
511
- className: cn("text-sf-subtle hover:text-sf-default", className),
512
- size: "sm",
513
- type: "button",
514
- variant: "ghost",
515
- ...props,
516
- children: children ?? /* @__PURE__ */ jsx(PlusIcon, { className: "size-4" })
517
- }) });
518
- var PromptInputActionMenuContent = ({ className, children, ...props }) => /* @__PURE__ */ jsx(DropdownMenu.Positioner, {
519
- className: "z-50",
520
- side: "top",
521
- align: "start",
522
- ...props,
523
- children: /* @__PURE__ */ jsx(DropdownMenu.Popup, {
524
- className: cn("min-w-[160px] rounded-lg bg-sf-elevated p-1 shadow-md", "data-[starting-style]:opacity-0 data-[ending-style]:opacity-0 transition-opacity duration-100", className),
525
- children
526
- })
527
- });
528
- var PromptInputActionMenuItem = ({ className, ...props }) => /* @__PURE__ */ jsx(DropdownMenu.Item, {
529
- className: cn("flex cursor-pointer select-none items-center gap-2 rounded-md px-2 py-1.5 text-sm text-sf-default outline-none", "data-highlighted:bg-sf-tint", className),
530
- ...props
531
- });
532
- var PromptInputActionAddAttachments = ({ label = "Add photos or files", ...props }) => {
533
- const attachments = usePromptInputAttachments();
534
- const handleSelect = useCallback(() => {
535
- attachments.openFileDialog();
536
- }, [attachments]);
537
- return /* @__PURE__ */ jsxs(PromptInputActionMenuItem, {
538
- ...props,
539
- onSelect: handleSelect,
540
- children: [/* @__PURE__ */ jsx(ImageIcon, { className: "size-4" }), label]
541
- });
542
- };
543
- var PromptInputModeSelector = ({ modes, value, onChange }) => {
544
- if (modes.length === 0) return null;
545
- const displayName = modes.find((m) => m.modeId === value)?.modeName ?? value ?? modes[0]?.modeName;
546
- return /* @__PURE__ */ jsx("div", {
547
- className: cn("flex items-center gap-0.5 rounded-md bg-sf-tint p-0.5"),
548
- role: "group",
549
- "aria-label": "Select mode",
550
- children: modes.map((mode) => {
551
- const isSelected = mode.modeId === value || mode.modeName === displayName;
552
- return /* @__PURE__ */ jsx("button", {
553
- "aria-pressed": isSelected,
554
- className: cn("cursor-pointer rounded-[4px] px-2 py-0.5 text-[11px] font-medium transition-colors", isSelected ? "bg-sf-elevated text-sf-default shadow-sm" : "text-sf-subtle hover:text-sf-default"),
555
- onClick: () => onChange?.(mode.modeId),
556
- type: "button",
557
- children: mode.modeName
558
- }, mode.modeId);
559
- })
560
- });
561
- };
562
- var IMAGE_EXTS = new Set([
563
- "jpg",
564
- "jpeg",
565
- "png",
566
- "gif",
567
- "webp",
568
- "svg"
569
- ]);
570
- function getFileIcon(filename) {
571
- const ext = filename.split(".").pop()?.toLowerCase() ?? "";
572
- if (IMAGE_EXTS.has(ext)) return /* @__PURE__ */ jsx(ImageIcon, { className: "size-3.5" });
573
- if ([
574
- "pdf",
575
- "doc",
576
- "docx",
577
- "txt",
578
- "md"
579
- ].includes(ext)) return /* @__PURE__ */ jsx(FileTextIcon, { className: "size-3.5" });
580
- return /* @__PURE__ */ jsx(FileIcon, { className: "size-3.5" });
581
- }
582
- /**
583
- * Single attachment chip for images or files. Includes a remove button.
584
- */
585
- function PromptInputAttachment({ data, className, ...props }) {
586
- const attachments = usePromptInputAttachments();
587
- const isImage = data.mediaType?.startsWith("image/") && data.url;
588
- const handleRemove = useCallback(() => {
589
- attachments.remove(data.id);
590
- }, [attachments, data.id]);
591
- if (isImage) return /* @__PURE__ */ jsxs("div", {
592
- className: cn("group relative size-14 overflow-hidden rounded-md", className),
593
- ...props,
594
- children: [/* @__PURE__ */ jsx("img", {
595
- alt: data.filename || "attachment",
596
- className: "size-full object-cover",
597
- src: data.url
598
- }), /* @__PURE__ */ jsx(Button, {
599
- "aria-label": "Remove attachment",
600
- className: "absolute top-1 right-1 size-5 rounded-full bg-sf-overlay/80 p-0 opacity-0 backdrop-blur-sm transition-opacity group-hover:opacity-100",
601
- onClick: handleRemove,
602
- size: "sm",
603
- type: "button",
604
- variant: "ghost",
605
- children: /* @__PURE__ */ jsx(XIcon, { className: "size-3" })
606
- })]
607
- });
608
- const ext = data.filename.split(".").pop()?.toUpperCase() ?? "FILE";
609
- const name = data.filename.replace(/\.[^/.]+$/, "");
610
- return /* @__PURE__ */ jsxs("div", {
611
- className: cn("group relative inline-flex h-8 items-center gap-2 rounded-md bg-sf-tint/50 px-2 text-sm", className),
612
- ...props,
613
- children: [
614
- /* @__PURE__ */ jsx("div", {
615
- className: "flex size-5 shrink-0 items-center justify-center text-sf-subtle",
616
- children: getFileIcon(data.filename)
617
- }),
618
- /* @__PURE__ */ jsx(Tooltip, {
619
- content: data.filename,
620
- children: /* @__PURE__ */ jsx("span", {
621
- className: "max-w-[160px] truncate font-medium text-sf-default",
622
- children: name || "File"
623
- })
624
- }),
625
- /* @__PURE__ */ jsx("span", {
626
- className: "rounded bg-sf-tint px-1 py-0.5 font-semibold text-sf-subtle text-[10px] uppercase",
627
- children: ext
628
- }),
629
- /* @__PURE__ */ jsx(Button, {
630
- "aria-label": "Remove attachment",
631
- className: "ml-0.5 size-4 shrink-0 rounded-full p-0 opacity-0 transition-opacity group-hover:opacity-100",
632
- onClick: handleRemove,
633
- size: "sm",
634
- type: "button",
635
- variant: "ghost",
636
- children: /* @__PURE__ */ jsx(XIcon, { className: "size-3" })
637
- })
638
- ]
639
- });
640
- }
641
- /**
642
- * Renders all attachments using a render prop. Hidden when no files.
643
- * Animates height as files are added/removed.
644
- */
645
- function PromptInputAttachments({ className, children, ...props }) {
646
- const attachments = usePromptInputAttachments();
647
- const [height, setHeight] = useState(0);
648
- const contentRef = useRef(null);
649
- useLayoutEffect(() => {
650
- const el = contentRef.current;
651
- if (!el) return;
652
- const ro = new ResizeObserver(() => {
653
- setHeight(el.getBoundingClientRect().height);
654
- });
655
- ro.observe(el);
656
- setHeight(el.getBoundingClientRect().height);
657
- return () => ro.disconnect();
658
- }, []);
659
- useLayoutEffect(() => {
660
- const el = contentRef.current;
661
- if (el) setHeight(el.getBoundingClientRect().height);
662
- }, [attachments.files.length]);
663
- if (attachments.files.length === 0) return null;
664
- return /* @__PURE__ */ jsx("div", {
665
- "aria-live": "polite",
666
- className: cn("overflow-hidden px-2 transition-[height] duration-200 ease-out", className),
667
- style: { height: attachments.files.length ? height : 0 },
668
- ...props,
669
- children: /* @__PURE__ */ jsx("div", {
670
- className: "flex flex-wrap gap-2 py-1",
671
- ref: contentRef,
672
- children: attachments.files.map((file) => /* @__PURE__ */ jsx(Fragment, { children: children(file) }, file.id))
673
- })
674
- });
675
- }
676
- /**
677
- * Voice input button. Uses the Web Speech API (Chrome/Edge). Hidden on unsupported browsers.
678
- * Pulses while listening.
679
- */
680
- var PromptInputSpeechButton = ({ className, textareaRef, onTranscriptionChange, "aria-label": ariaLabel = "Voice input", ...props }) => {
681
- const [isListening, setIsListening] = useState(false);
682
- const [recognition, setRecognition] = useState(null);
683
- const recognitionRef = useRef(null);
684
- useEffect(() => {
685
- if (typeof window === "undefined") return;
686
- const SR = window.SpeechRecognition ?? window.webkitSpeechRecognition;
687
- if (!SR) return;
688
- const sr = new SR();
689
- sr.continuous = true;
690
- sr.interimResults = true;
691
- sr.lang = "en-US";
692
- const handleStart = () => setIsListening(true);
693
- const handleEnd = () => setIsListening(false);
694
- const handleResult = (event) => {
695
- const e = event;
696
- let final = "";
697
- for (const result of Array.from({ length: e.results.length }, (_, i) => e.results[i])) if (result?.isFinal && result[0]?.transcript) final += result[0].transcript;
698
- if (final && textareaRef?.current) {
699
- const ta = textareaRef.current;
700
- const next = ta.value + (ta.value ? " " : "") + final;
701
- ta.value = next;
702
- ta.dispatchEvent(new Event("input", { bubbles: true }));
703
- onTranscriptionChange?.(next);
704
- }
705
- };
706
- const handleError = (_event) => setIsListening(false);
707
- sr.addEventListener("start", handleStart);
708
- sr.addEventListener("end", handleEnd);
709
- sr.addEventListener("result", handleResult);
710
- sr.addEventListener("error", handleError);
711
- recognitionRef.current = sr;
712
- setRecognition(sr);
713
- return () => {
714
- sr.removeEventListener("start", handleStart);
715
- sr.removeEventListener("end", handleEnd);
716
- sr.removeEventListener("result", handleResult);
717
- sr.removeEventListener("error", handleError);
718
- recognitionRef.current?.stop();
719
- };
720
- }, [textareaRef, onTranscriptionChange]);
721
- const handleToggleListening = useCallback(() => {
722
- if (!recognition) return;
723
- const sr = recognition;
724
- if (isListening) sr.stop();
725
- else sr.start();
726
- }, [recognition, isListening]);
727
- const button = /* @__PURE__ */ jsx(Button, {
728
- "aria-label": ariaLabel,
729
- className: cn("text-sf-subtle hover:text-sf-default transition-all", isListening && "animate-pulse text-sf-brand", className),
730
- disabled: !recognition,
731
- onClick: handleToggleListening,
732
- size: "sm",
733
- type: "button",
734
- variant: "ghost",
735
- ...props,
736
- children: /* @__PURE__ */ jsx(MicrophoneIcon, { className: "size-4" })
737
- });
738
- if (!recognition) return null;
739
- return /* @__PURE__ */ jsx(Tooltip, {
740
- content: isListening ? "Stop listening" : "Voice input",
741
- children: button
742
- });
743
- };
744
- /**
745
- * Convenience button that opens the file dialog directly (no dropdown needed).
746
- */
747
- var PromptInputAttachButton = ({ "aria-label": ariaLabel = "Attach file", className, ...props }) => {
748
- const attachments = usePromptInputAttachments();
749
- const handleClick = useCallback(() => {
750
- attachments.openFileDialog();
751
- }, [attachments]);
752
- return /* @__PURE__ */ jsx(Tooltip, {
753
- content: ariaLabel,
754
- children: /* @__PURE__ */ jsx(Button, {
755
- "aria-label": ariaLabel,
756
- className: cn("text-sf-subtle hover:text-sf-default", className),
757
- onClick: handleClick,
758
- size: "sm",
759
- type: "button",
760
- variant: "ghost",
761
- ...props,
762
- children: /* @__PURE__ */ jsx(PaperclipIcon, { className: "size-4" })
763
- })
764
- });
765
- };
766
- //#endregion
767
- export { usePromptInputController as C, usePromptInputAttachments as S, PromptInputTextarea as _, PromptInputActionMenuItem as a, SF_AI_PROMPT_INPUT_DEFAULT_VARIANTS as b, PromptInputAttachment as c, PromptInputBody as d, PromptInputButton as f, PromptInputSubmit as g, PromptInputSpeechButton as h, PromptInputActionMenuContent as i, PromptInputAttachments as l, PromptInputProvider as m, PromptInputActionAddAttachments as n, PromptInputActionMenuTrigger as o, PromptInputModeSelector as p, PromptInputActionMenu as r, PromptInputAttachButton as s, PromptInput as t, PromptInputBackLayer as u, PromptInputToolbar as v, useProviderAttachments as w, SF_AI_PROMPT_INPUT_VARIANTS as x, PromptInputTools as y };
768
-
769
- //# sourceMappingURL=ai-prompt-input-Bo1YuJly.js.map