sparkdesign 0.0.1 → 0.2.6

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 (403) hide show
  1. package/README.md +279 -5
  2. package/cli/dist/commands/add.js +84 -0
  3. package/cli/dist/commands/diff.js +54 -0
  4. package/cli/dist/commands/init.js +96 -0
  5. package/cli/dist/commands/list.js +25 -0
  6. package/cli/dist/index.js +37 -0
  7. package/cli/dist/utils/config.js +53 -0
  8. package/cli/dist/utils/registry.js +34 -0
  9. package/cli/dist/utils/tokens.js +90 -0
  10. package/cli/dist/utils/transform.js +19 -0
  11. package/cli/registry/basic/alert-dialog.tsx +180 -0
  12. package/cli/registry/basic/avatar.tsx +120 -0
  13. package/cli/registry/basic/button.tsx +100 -0
  14. package/cli/registry/basic/collapse.tsx +94 -0
  15. package/cli/registry/basic/collapsible-card.tsx +230 -0
  16. package/cli/registry/basic/collapsible.tsx +21 -0
  17. package/cli/registry/basic/dropdown-menu.tsx +254 -0
  18. package/cli/registry/basic/icon-button.tsx +66 -0
  19. package/cli/registry/basic/icons-inline.tsx +206 -0
  20. package/cli/registry/basic/kbd.tsx +50 -0
  21. package/cli/registry/basic/option-list.tsx +125 -0
  22. package/cli/registry/basic/pagination.tsx +132 -0
  23. package/cli/registry/basic/progress.tsx +42 -0
  24. package/cli/registry/basic/radio-group.tsx +69 -0
  25. package/cli/registry/basic/resizable.tsx +67 -0
  26. package/cli/registry/basic/scrollbar.tsx +114 -0
  27. package/cli/registry/basic/select.tsx +177 -0
  28. package/cli/registry/basic/skeleton.tsx +33 -0
  29. package/cli/registry/basic/slider.tsx +55 -0
  30. package/cli/registry/basic/sonner.tsx +104 -0
  31. package/cli/registry/basic/spinner.tsx +17 -0
  32. package/cli/registry/basic/switch.tsx +49 -0
  33. package/cli/registry/basic/table.tsx +117 -0
  34. package/cli/registry/basic/tabs.tsx +85 -0
  35. package/cli/registry/basic/tag.tsx +161 -0
  36. package/cli/registry/basic/theme-from-document.ts +10 -0
  37. package/cli/registry/basic/toggle.tsx +223 -0
  38. package/cli/registry/basic/tooltip.tsx +80 -0
  39. package/cli/registry/basic/typography.tsx +201 -0
  40. package/cli/registry/chat/browser-use-part.tsx +166 -0
  41. package/cli/registry/chat/chat-input/chat-input-folder-selector.tsx +185 -0
  42. package/cli/registry/chat/chat-input/chat-input-model-switcher.tsx +131 -0
  43. package/cli/registry/chat/chat-input/chat-input-textarea.tsx +67 -0
  44. package/cli/registry/chat/chat-input/compound.tsx +334 -0
  45. package/cli/registry/chat/chat-input/context.tsx +189 -0
  46. package/cli/registry/chat/chat-input/folder-permission-dialog.tsx +61 -0
  47. package/cli/registry/chat/chat-input/index.tsx +123 -0
  48. package/cli/registry/chat/chat-input/types.ts +77 -0
  49. package/cli/registry/chat/chat-input/useAutoResizeTextarea.ts +20 -0
  50. package/cli/registry/chat/code-block-part.tsx +151 -0
  51. package/cli/registry/chat/file-attachment.tsx +44 -0
  52. package/cli/registry/chat/file-card.tsx +68 -0
  53. package/cli/registry/chat/file-review-part.tsx +259 -0
  54. package/cli/registry/chat/folder-button.tsx +169 -0
  55. package/cli/registry/chat/generated-images-grid.tsx +56 -0
  56. package/cli/registry/chat/generation-status-bar.tsx +72 -0
  57. package/cli/registry/chat/image-attachment.tsx +166 -0
  58. package/cli/registry/chat/image-generating.tsx +281 -0
  59. package/cli/registry/chat/markdown.tsx +146 -0
  60. package/cli/registry/chat/mermaid-part.tsx +90 -0
  61. package/cli/registry/chat/permission-card.tsx +178 -0
  62. package/cli/registry/chat/plan-part.tsx +168 -0
  63. package/cli/registry/chat/question-part.tsx +70 -0
  64. package/cli/registry/chat/queue-indicator.tsx +234 -0
  65. package/cli/registry/chat/reasoning-step.tsx +358 -0
  66. package/cli/registry/chat/related-prompts.tsx +91 -0
  67. package/cli/registry/chat/request.tsx +38 -0
  68. package/cli/registry/chat/response.tsx +271 -0
  69. package/cli/registry/chat/send-button.tsx +94 -0
  70. package/cli/registry/chat/sidebar-menu.tsx +177 -0
  71. package/cli/registry/chat/streaming-markdown-block.tsx +111 -0
  72. package/cli/registry/chat/suggestion-part.tsx +165 -0
  73. package/cli/registry/chat/task-part.tsx +109 -0
  74. package/cli/registry/chat/terminal-code-block-part.tsx +69 -0
  75. package/cli/registry/chat/thinking-indicator.tsx +91 -0
  76. package/cli/registry/chat/tool-invocation-card.tsx +132 -0
  77. package/cli/registry/chat/user-question/UserQuestionCard.tsx +198 -0
  78. package/cli/registry/chat/user-question/UserQuestionFooter.tsx +66 -0
  79. package/cli/registry/chat/user-question/UserQuestionHeader.tsx +64 -0
  80. package/cli/registry/chat/user-question/index.tsx +340 -0
  81. package/cli/registry/chat/user-question/types.ts +61 -0
  82. package/cli/registry/chat/user-question/useUserQuestionKeyboard.ts +127 -0
  83. package/cli/registry/chat/user-question/useUserQuestionState.ts +165 -0
  84. package/cli/registry/chat/user-question-answer.tsx +62 -0
  85. package/cli/registry/lib/file-icon-maps.ts +150 -0
  86. package/cli/registry/lib/use-mermaid-render.ts +76 -0
  87. package/cli/registry/lib/utils.ts +6 -0
  88. package/cli/registry/meta.json +1 -0
  89. package/cli/registry/tokens/scale.css +299 -0
  90. package/cli/registry/tokens/theme.css +633 -0
  91. package/dist/_basePickBy-DnQN8w3y.js +151 -0
  92. package/dist/_basePickBy-a-kPMlkg.cjs +1 -0
  93. package/dist/_baseUniq-B-N2NQ50.js +614 -0
  94. package/dist/_baseUniq-Cc_zbSif.cjs +1 -0
  95. package/dist/arc-BQBhijZ6.js +83 -0
  96. package/dist/arc-mWQt0Yph.cjs +1 -0
  97. package/dist/architectureDiagram-VXUJARFQ-BMZEucno.cjs +36 -0
  98. package/dist/architectureDiagram-VXUJARFQ-DTdjD3Bp.js +4661 -0
  99. package/dist/blockDiagram-VD42YOAC-CzHn0yob.js +2256 -0
  100. package/dist/blockDiagram-VD42YOAC-DDxdHAlz.cjs +122 -0
  101. package/dist/c4Diagram-YG6GDRKO-4Gz0I4gj.cjs +10 -0
  102. package/dist/c4Diagram-YG6GDRKO-BIy--yVN.js +1580 -0
  103. package/dist/channel-BQn0o8bs.js +5 -0
  104. package/dist/channel-DaN7XniJ.cjs +1 -0
  105. package/dist/chunk-4BX2VUAB-BlQFTQqz.cjs +1 -0
  106. package/dist/chunk-4BX2VUAB-Czitj3Kc.js +8 -0
  107. package/dist/chunk-55IACEB6-DXacNZbO.js +8 -0
  108. package/dist/chunk-55IACEB6-DnDxpye9.cjs +1 -0
  109. package/dist/chunk-B4BG7PRW-CBdN0q_V.js +1375 -0
  110. package/dist/chunk-B4BG7PRW-DbGvUkGO.cjs +165 -0
  111. package/dist/chunk-DI55MBZ5-D1YJMs6x.cjs +220 -0
  112. package/dist/chunk-DI55MBZ5-NCQTvayw.js +1370 -0
  113. package/dist/chunk-FMBD7UC4-CsGMbrtr.js +19 -0
  114. package/dist/chunk-FMBD7UC4-Di7cUUh5.cjs +15 -0
  115. package/dist/chunk-QN33PNHL-0j5LC8Lm.cjs +1 -0
  116. package/dist/chunk-QN33PNHL-3GERZBRm.js +19 -0
  117. package/dist/chunk-QZHKN3VN-AVEY9ImQ.js +15 -0
  118. package/dist/chunk-QZHKN3VN-s8Z0a8mc.cjs +1 -0
  119. package/dist/chunk-TZMSLE5B-CAf87HPt.cjs +1 -0
  120. package/dist/chunk-TZMSLE5B-sbiflal0.js +64 -0
  121. package/dist/classDiagram-2ON5EDUG-Ct9JLIN2.cjs +1 -0
  122. package/dist/classDiagram-2ON5EDUG-Dzfrft3a.js +16 -0
  123. package/dist/classDiagram-v2-WZHVMYZB-Ct9JLIN2.cjs +1 -0
  124. package/dist/classDiagram-v2-WZHVMYZB-Dzfrft3a.js +16 -0
  125. package/dist/clone-Cde_NQ8V.js +8 -0
  126. package/dist/clone-DCNjWuM2.cjs +1 -0
  127. package/dist/cose-bilkent-S5V4N54A-0uLijMro.cjs +1 -0
  128. package/dist/cose-bilkent-S5V4N54A-Bb08N431.js +2608 -0
  129. package/dist/cytoscape.esm-CNUX3VTg.cjs +321 -0
  130. package/dist/cytoscape.esm-Cvf3sx9F.js +18704 -0
  131. package/dist/dagre-6UL2VRFP-CY_Wz5Zd.js +444 -0
  132. package/dist/dagre-6UL2VRFP-Dxe7_qZc.cjs +4 -0
  133. package/dist/defaultLocale-BgPVtth8.js +171 -0
  134. package/dist/defaultLocale-C4wbwF1n.cjs +1 -0
  135. package/dist/diagram-PSM6KHXK-D2bdb7MT.js +531 -0
  136. package/dist/diagram-PSM6KHXK-YF69SUjY.cjs +24 -0
  137. package/dist/diagram-QEK2KX5R-BpUSoh0-.js +217 -0
  138. package/dist/diagram-QEK2KX5R-DZPGteon.cjs +43 -0
  139. package/dist/diagram-S2PKOQOG-ht-zdvFG.cjs +24 -0
  140. package/dist/diagram-S2PKOQOG-zFeLJ50Z.js +142 -0
  141. package/dist/erDiagram-Q2GNP2WA-B38iJ6ts.js +841 -0
  142. package/dist/erDiagram-Q2GNP2WA-RgS80DDU.cjs +60 -0
  143. package/dist/flowDiagram-NV44I4VS-BHilOs2p.cjs +162 -0
  144. package/dist/flowDiagram-NV44I4VS-BrBJcoce.js +1620 -0
  145. package/dist/fonts/KaTeX_AMS-Regular.ttf +0 -0
  146. package/dist/fonts/KaTeX_AMS-Regular.woff +0 -0
  147. package/dist/fonts/KaTeX_AMS-Regular.woff2 +0 -0
  148. package/dist/fonts/KaTeX_Caligraphic-Bold.ttf +0 -0
  149. package/dist/fonts/KaTeX_Caligraphic-Bold.woff +0 -0
  150. package/dist/fonts/KaTeX_Caligraphic-Bold.woff2 +0 -0
  151. package/dist/fonts/KaTeX_Caligraphic-Regular.ttf +0 -0
  152. package/dist/fonts/KaTeX_Caligraphic-Regular.woff +0 -0
  153. package/dist/fonts/KaTeX_Caligraphic-Regular.woff2 +0 -0
  154. package/dist/fonts/KaTeX_Fraktur-Bold.ttf +0 -0
  155. package/dist/fonts/KaTeX_Fraktur-Bold.woff +0 -0
  156. package/dist/fonts/KaTeX_Fraktur-Bold.woff2 +0 -0
  157. package/dist/fonts/KaTeX_Fraktur-Regular.ttf +0 -0
  158. package/dist/fonts/KaTeX_Fraktur-Regular.woff +0 -0
  159. package/dist/fonts/KaTeX_Fraktur-Regular.woff2 +0 -0
  160. package/dist/fonts/KaTeX_Main-Bold.ttf +0 -0
  161. package/dist/fonts/KaTeX_Main-Bold.woff +0 -0
  162. package/dist/fonts/KaTeX_Main-Bold.woff2 +0 -0
  163. package/dist/fonts/KaTeX_Main-BoldItalic.ttf +0 -0
  164. package/dist/fonts/KaTeX_Main-BoldItalic.woff +0 -0
  165. package/dist/fonts/KaTeX_Main-BoldItalic.woff2 +0 -0
  166. package/dist/fonts/KaTeX_Main-Italic.ttf +0 -0
  167. package/dist/fonts/KaTeX_Main-Italic.woff +0 -0
  168. package/dist/fonts/KaTeX_Main-Italic.woff2 +0 -0
  169. package/dist/fonts/KaTeX_Main-Regular.ttf +0 -0
  170. package/dist/fonts/KaTeX_Main-Regular.woff +0 -0
  171. package/dist/fonts/KaTeX_Main-Regular.woff2 +0 -0
  172. package/dist/fonts/KaTeX_Math-BoldItalic.ttf +0 -0
  173. package/dist/fonts/KaTeX_Math-BoldItalic.woff +0 -0
  174. package/dist/fonts/KaTeX_Math-BoldItalic.woff2 +0 -0
  175. package/dist/fonts/KaTeX_Math-Italic.ttf +0 -0
  176. package/dist/fonts/KaTeX_Math-Italic.woff +0 -0
  177. package/dist/fonts/KaTeX_Math-Italic.woff2 +0 -0
  178. package/dist/fonts/KaTeX_SansSerif-Bold.ttf +0 -0
  179. package/dist/fonts/KaTeX_SansSerif-Bold.woff +0 -0
  180. package/dist/fonts/KaTeX_SansSerif-Bold.woff2 +0 -0
  181. package/dist/fonts/KaTeX_SansSerif-Italic.ttf +0 -0
  182. package/dist/fonts/KaTeX_SansSerif-Italic.woff +0 -0
  183. package/dist/fonts/KaTeX_SansSerif-Italic.woff2 +0 -0
  184. package/dist/fonts/KaTeX_SansSerif-Regular.ttf +0 -0
  185. package/dist/fonts/KaTeX_SansSerif-Regular.woff +0 -0
  186. package/dist/fonts/KaTeX_SansSerif-Regular.woff2 +0 -0
  187. package/dist/fonts/KaTeX_Script-Regular.ttf +0 -0
  188. package/dist/fonts/KaTeX_Script-Regular.woff +0 -0
  189. package/dist/fonts/KaTeX_Script-Regular.woff2 +0 -0
  190. package/dist/fonts/KaTeX_Size1-Regular.ttf +0 -0
  191. package/dist/fonts/KaTeX_Size1-Regular.woff +0 -0
  192. package/dist/fonts/KaTeX_Size1-Regular.woff2 +0 -0
  193. package/dist/fonts/KaTeX_Size2-Regular.ttf +0 -0
  194. package/dist/fonts/KaTeX_Size2-Regular.woff +0 -0
  195. package/dist/fonts/KaTeX_Size2-Regular.woff2 +0 -0
  196. package/dist/fonts/KaTeX_Size3-Regular.ttf +0 -0
  197. package/dist/fonts/KaTeX_Size3-Regular.woff +0 -0
  198. package/dist/fonts/KaTeX_Size3-Regular.woff2 +0 -0
  199. package/dist/fonts/KaTeX_Size4-Regular.ttf +0 -0
  200. package/dist/fonts/KaTeX_Size4-Regular.woff +0 -0
  201. package/dist/fonts/KaTeX_Size4-Regular.woff2 +0 -0
  202. package/dist/fonts/KaTeX_Typewriter-Regular.ttf +0 -0
  203. package/dist/fonts/KaTeX_Typewriter-Regular.woff +0 -0
  204. package/dist/fonts/KaTeX_Typewriter-Regular.woff2 +0 -0
  205. package/dist/ganttDiagram-JELNMOA3-pZiJeFio.cjs +267 -0
  206. package/dist/ganttDiagram-JELNMOA3-tw6FhkWJ.js +2670 -0
  207. package/dist/gitGraphDiagram-V2S2FVAM-BWn5uIK5.js +699 -0
  208. package/dist/gitGraphDiagram-V2S2FVAM-DKKeG-9R.cjs +65 -0
  209. package/dist/graph-DIbblrZP.cjs +1 -0
  210. package/dist/graph-DPcK91G3.js +247 -0
  211. package/dist/infoDiagram-HS3SLOUP-B8gwwhct.cjs +2 -0
  212. package/dist/infoDiagram-HS3SLOUP-D47PNcP_.js +24 -0
  213. package/dist/init-CHZsXQcr.cjs +1 -0
  214. package/dist/init-DjUOC4st.js +16 -0
  215. package/dist/journeyDiagram-XKPGCS4Q-BG3cfhyU.js +834 -0
  216. package/dist/journeyDiagram-XKPGCS4Q-D8DVLJof.cjs +139 -0
  217. package/dist/kanban-definition-3W4ZIXB7-4OCnEouP.cjs +89 -0
  218. package/dist/kanban-definition-3W4ZIXB7-CWi_ssF9.js +719 -0
  219. package/dist/katex.css +1 -0
  220. package/dist/layout-Byuh8f-J.cjs +1 -0
  221. package/dist/layout-CdLdvj1j.js +1335 -0
  222. package/dist/linear-C2Q_PI9B.js +259 -0
  223. package/dist/linear-C69aPBW1.cjs +1 -0
  224. package/dist/mermaid.core-DBwAx_jp.cjs +249 -0
  225. package/dist/mermaid.core-gFR0XUlD.js +15300 -0
  226. package/dist/mindmap-definition-VGOIOE7T-8P7obVV4.cjs +68 -0
  227. package/dist/mindmap-definition-VGOIOE7T-DnOa7WJ9.js +784 -0
  228. package/dist/ordinal-B6-f3MAq.js +61 -0
  229. package/dist/ordinal-CagbB1m8.cjs +1 -0
  230. package/dist/pieDiagram-ADFJNKIX-5NAlvhMo.js +161 -0
  231. package/dist/pieDiagram-ADFJNKIX-CQBG4yR9.cjs +30 -0
  232. package/dist/qoder-design.css +2 -0
  233. package/dist/quadrantDiagram-AYHSOK5B-Oe4y7RZ0.cjs +7 -0
  234. package/dist/quadrantDiagram-AYHSOK5B-rh2DPEP1.js +1022 -0
  235. package/dist/registry/basic/alert-dialog.d.ts +40 -0
  236. package/dist/registry/basic/avatar.d.ts +30 -0
  237. package/dist/registry/basic/button.d.ts +16 -0
  238. package/dist/registry/basic/collapse.d.ts +22 -0
  239. package/dist/registry/basic/collapsible-card.d.ts +34 -0
  240. package/dist/registry/basic/collapsible.d.ts +15 -0
  241. package/dist/registry/basic/dropdown-menu.d.ts +52 -0
  242. package/dist/registry/basic/icon-button.d.ts +12 -0
  243. package/dist/registry/basic/icons-inline.d.ts +51 -0
  244. package/dist/registry/basic/kbd.d.ts +23 -0
  245. package/dist/registry/basic/option-list.d.ts +16 -0
  246. package/dist/registry/basic/pagination.d.ts +33 -0
  247. package/dist/registry/basic/progress.d.ts +18 -0
  248. package/dist/registry/basic/radio-group.d.ts +25 -0
  249. package/dist/registry/basic/resizable.d.ts +318 -0
  250. package/dist/registry/basic/scrollbar.d.ts +12 -0
  251. package/dist/registry/basic/select.d.ts +35 -0
  252. package/dist/registry/basic/skeleton.d.ts +10 -0
  253. package/dist/registry/basic/slider.d.ts +16 -0
  254. package/dist/registry/basic/sonner.d.ts +23 -0
  255. package/dist/registry/basic/spinner.d.ts +5 -0
  256. package/dist/registry/basic/switch.d.ts +20 -0
  257. package/dist/registry/basic/table.d.ts +18 -0
  258. package/dist/registry/basic/tabs.d.ts +29 -0
  259. package/dist/registry/basic/tag.d.ts +23 -0
  260. package/dist/registry/basic/theme-from-document.d.ts +10 -0
  261. package/dist/registry/basic/toggle.d.ts +29 -0
  262. package/dist/registry/basic/tooltip.d.ts +34 -0
  263. package/dist/registry/basic/typography.d.ts +76 -0
  264. package/dist/registry/chat/browser-use-part.d.ts +28 -0
  265. package/dist/registry/chat/chat-input/chat-input-folder-selector.d.ts +22 -0
  266. package/dist/registry/chat/chat-input/chat-input-model-switcher.d.ts +12 -0
  267. package/dist/registry/chat/chat-input/chat-input-textarea.d.ts +9 -0
  268. package/dist/registry/chat/chat-input/compound.d.ts +97 -0
  269. package/dist/registry/chat/chat-input/context.d.ts +64 -0
  270. package/dist/registry/chat/chat-input/folder-permission-dialog.d.ts +11 -0
  271. package/dist/registry/chat/chat-input/index.d.ts +34 -0
  272. package/dist/registry/chat/chat-input/types.d.ts +79 -0
  273. package/dist/registry/chat/chat-input/useAutoResizeTextarea.d.ts +7 -0
  274. package/dist/registry/chat/code-block-part.d.ts +23 -0
  275. package/dist/registry/chat/file-attachment.d.ts +19 -0
  276. package/dist/registry/chat/file-card.d.ts +10 -0
  277. package/dist/registry/chat/file-review-part.d.ts +30 -0
  278. package/dist/registry/chat/folder-button.d.ts +20 -0
  279. package/dist/registry/chat/generated-images-grid.d.ts +15 -0
  280. package/dist/registry/chat/generation-status-bar.d.ts +19 -0
  281. package/dist/registry/chat/image-attachment.d.ts +19 -0
  282. package/dist/registry/chat/image-generating.d.ts +15 -0
  283. package/dist/registry/chat/markdown.d.ts +8 -0
  284. package/dist/registry/chat/mermaid-part.d.ts +17 -0
  285. package/dist/registry/chat/permission-card.d.ts +24 -0
  286. package/dist/registry/chat/plan-part.d.ts +30 -0
  287. package/dist/registry/chat/question-part.d.ts +24 -0
  288. package/dist/registry/chat/queue-indicator.d.ts +27 -0
  289. package/dist/registry/chat/reasoning-step.d.ts +35 -0
  290. package/dist/registry/chat/related-prompts.d.ts +23 -0
  291. package/dist/registry/chat/request.d.ts +6 -0
  292. package/dist/registry/chat/response.d.ts +28 -0
  293. package/dist/registry/chat/send-button.d.ts +17 -0
  294. package/dist/registry/chat/sidebar-menu.d.ts +23 -0
  295. package/dist/registry/chat/streaming-markdown-block.d.ts +8 -0
  296. package/dist/registry/chat/suggestion-part.d.ts +28 -0
  297. package/dist/registry/chat/task-part.d.ts +28 -0
  298. package/dist/registry/chat/terminal-code-block-part.d.ts +18 -0
  299. package/dist/registry/chat/thinking-indicator.d.ts +14 -0
  300. package/dist/registry/chat/tool-invocation-card.d.ts +20 -0
  301. package/dist/registry/chat/user-question/UserQuestionCard.d.ts +30 -0
  302. package/dist/registry/chat/user-question/UserQuestionFooter.d.ts +18 -0
  303. package/dist/registry/chat/user-question/UserQuestionHeader.d.ts +20 -0
  304. package/dist/registry/chat/user-question/index.d.ts +7 -0
  305. package/dist/registry/chat/user-question/types.d.ts +52 -0
  306. package/dist/registry/chat/user-question/useUserQuestionKeyboard.d.ts +18 -0
  307. package/dist/registry/chat/user-question/useUserQuestionState.d.ts +26 -0
  308. package/dist/registry/chat/user-question-answer.d.ts +13 -0
  309. package/dist/registry/lib/file-icon-maps.d.ts +20 -0
  310. package/dist/registry/lib/use-mermaid-render.d.ts +5 -0
  311. package/dist/registry/lib/utils.d.ts +11 -0
  312. package/dist/requirementDiagram-UZGBJVZJ-DcWaCuXr.js +850 -0
  313. package/dist/requirementDiagram-UZGBJVZJ-gfdlrFiq.cjs +64 -0
  314. package/dist/sankeyDiagram-TZEHDZUN-CQIKFwD0.js +810 -0
  315. package/dist/sankeyDiagram-TZEHDZUN-DvPtzQvC.cjs +10 -0
  316. package/dist/scale.css +307 -0
  317. package/dist/sequenceDiagram-WL72ISMW-BNrsMagL.cjs +145 -0
  318. package/dist/sequenceDiagram-WL72ISMW-iCX3ckKx.js +2511 -0
  319. package/dist/spark-design.cjs.js +265 -0
  320. package/dist/spark-design.es.js +13207 -0
  321. package/dist/src/components/chat/BrowserUsePart/index.d.ts +7 -0
  322. package/dist/src/components/chat/ChatInput/index.d.ts +29 -0
  323. package/dist/src/components/chat/CodeBlockPart/index.d.ts +7 -0
  324. package/dist/src/components/chat/CollapsibleCard/index.d.ts +7 -0
  325. package/dist/src/components/chat/FileAttachment/index.d.ts +3 -0
  326. package/dist/src/components/chat/FileCard/index.d.ts +3 -0
  327. package/dist/src/components/chat/FileReviewPart/index.d.ts +7 -0
  328. package/dist/src/components/chat/FolderButton/index.d.ts +5 -0
  329. package/dist/src/components/chat/GeneratedImagesGrid/index.d.ts +7 -0
  330. package/dist/src/components/chat/GenerationStatusBar/index.d.ts +7 -0
  331. package/dist/src/components/chat/ImageAttachment/index.d.ts +3 -0
  332. package/dist/src/components/chat/ImageGenerating/index.d.ts +6 -0
  333. package/dist/src/components/chat/Markdown/demo-content.d.ts +1 -0
  334. package/dist/src/components/chat/Markdown/index.d.ts +7 -0
  335. package/dist/src/components/chat/MermaidPart/index.d.ts +6 -0
  336. package/dist/src/components/chat/PermissionCard/index.d.ts +4 -0
  337. package/dist/src/components/chat/PlanPart/index.d.ts +6 -0
  338. package/dist/src/components/chat/QuestionPart/index.d.ts +6 -0
  339. package/dist/src/components/chat/QueueIndicator/index.d.ts +4 -0
  340. package/dist/src/components/chat/ReasoningStep/index.d.ts +7 -0
  341. package/dist/src/components/chat/RelatedPrompts/index.d.ts +6 -0
  342. package/dist/src/components/chat/Request/index.d.ts +7 -0
  343. package/dist/src/components/chat/Response/StreamingMarkdownBlock.d.ts +6 -0
  344. package/dist/src/components/chat/Response/index.d.ts +6 -0
  345. package/dist/src/components/chat/SendButton/index.d.ts +5 -0
  346. package/dist/src/components/chat/SidebarMenu/index.d.ts +4 -0
  347. package/dist/src/components/chat/SuggestionPart/index.d.ts +6 -0
  348. package/dist/src/components/chat/TaskPart/index.d.ts +7 -0
  349. package/dist/src/components/chat/TerminalCodeBlockPart/index.d.ts +6 -0
  350. package/dist/src/components/chat/ThinkingIndicator/index.d.ts +6 -0
  351. package/dist/src/components/chat/ToolInvocationCard/index.d.ts +4 -0
  352. package/dist/src/components/chat/UserQuestion/index.d.ts +5 -0
  353. package/dist/src/components/chat/UserQuestionAnswer/index.d.ts +3 -0
  354. package/dist/src/components/foundation/AlertDialog/index.d.ts +20 -0
  355. package/dist/src/components/foundation/Avatar/index.d.ts +7 -0
  356. package/dist/src/components/foundation/Button/index.d.ts +7 -0
  357. package/dist/src/components/foundation/Collapse/index.d.ts +15 -0
  358. package/dist/src/components/foundation/Collapsible/index.d.ts +7 -0
  359. package/dist/src/components/foundation/CollapsibleSection/index.d.ts +43 -0
  360. package/dist/src/components/foundation/DropdownMenu/index.d.ts +19 -0
  361. package/dist/src/components/foundation/EllipsisText/index.d.ts +53 -0
  362. package/dist/src/components/foundation/IconButton/index.d.ts +7 -0
  363. package/dist/src/components/foundation/Kbd/index.d.ts +7 -0
  364. package/dist/src/components/foundation/OptionList/index.d.ts +7 -0
  365. package/dist/src/components/foundation/Pagination/index.d.ts +7 -0
  366. package/dist/src/components/foundation/Progress/index.d.ts +7 -0
  367. package/dist/src/components/foundation/RadioGroup/index.d.ts +7 -0
  368. package/dist/src/components/foundation/Resizable/index.d.ts +7 -0
  369. package/dist/src/components/foundation/Scrollbar/index.d.ts +7 -0
  370. package/dist/src/components/foundation/Select/index.d.ts +17 -0
  371. package/dist/src/components/foundation/Skeleton/index.d.ts +7 -0
  372. package/dist/src/components/foundation/Slider/index.d.ts +7 -0
  373. package/dist/src/components/foundation/Spinner/index.d.ts +7 -0
  374. package/dist/src/components/foundation/Switch/index.d.ts +38 -0
  375. package/dist/src/components/foundation/Table/index.d.ts +7 -0
  376. package/dist/src/components/foundation/Tabs/index.d.ts +7 -0
  377. package/dist/src/components/foundation/Tag/index.d.ts +10 -0
  378. package/dist/src/components/foundation/Toast/index.d.ts +12 -0
  379. package/dist/src/components/foundation/Toggle/index.d.ts +7 -0
  380. package/dist/src/components/foundation/Tooltip/index.d.ts +21 -0
  381. package/dist/src/components/foundation/Typography/index.d.ts +7 -0
  382. package/dist/src/components/index.d.ts +136 -0
  383. package/dist/src/icons/context.d.ts +26 -0
  384. package/dist/src/icons/types.d.ts +18 -0
  385. package/dist/src/lib/ThemeStyleContext.d.ts +21 -0
  386. package/dist/src/lib/file-icon.d.ts +16 -0
  387. package/dist/src/lib/i18n.d.ts +12 -0
  388. package/dist/src/lib/index.d.ts +10 -0
  389. package/dist/src/lib/motion.d.ts +22 -0
  390. package/dist/src/lib/utils.d.ts +11 -0
  391. package/dist/stateDiagram-FKZM4ZOC-DBvJ_eeL.cjs +1 -0
  392. package/dist/stateDiagram-FKZM4ZOC-ZVsJlaHJ.js +263 -0
  393. package/dist/stateDiagram-v2-4FDKWEC3-CB_nTHcE.js +16 -0
  394. package/dist/stateDiagram-v2-4FDKWEC3-Xkx17v6T.cjs +1 -0
  395. package/dist/theme.css +804 -0
  396. package/dist/timeline-definition-IT6M3QCI-BmGkYQiz.cjs +61 -0
  397. package/dist/timeline-definition-IT6M3QCI-Ck8zTt6w.js +795 -0
  398. package/dist/treemap-GDKQZRPO-B9sfERx8.js +17922 -0
  399. package/dist/treemap-GDKQZRPO-BVfJRs0Z.cjs +160 -0
  400. package/dist/xychartDiagram-PRI3JC2R-By_S8NzN.js +1340 -0
  401. package/dist/xychartDiagram-PRI3JC2R-CNfDrGxM.cjs +7 -0
  402. package/package.json +111 -9
  403. package/index.js +0 -5
@@ -0,0 +1,271 @@
1
+ import { useEffect, useMemo, useState } from 'react'
2
+ import type { HTMLAttributes, ReactNode } from 'react'
3
+ import { cn } from '@/lib/utils'
4
+ import { MarkdownBody } from './markdown'
5
+ import { ThinkingIndicator } from './thinking-indicator'
6
+ import { ImageGenerating } from './image-generating'
7
+ import { ReasoningStep } from './reasoning-step'
8
+ import type { ReasoningStepDetail } from './reasoning-step'
9
+ import { StreamingMarkdownBlock } from './streaming-markdown-block'
10
+
11
+ export type ResponsePhase = 'thinking' | 'streaming' | 'done' | 'imageGenerating'
12
+ export type ResponseStepToolType = 'read' | 'edit' | 'search'
13
+
14
+ export interface ResponseStep {
15
+ text: string
16
+ description?: string
17
+ details?: ReasoningStepDetail[]
18
+ toolType?: ResponseStepToolType
19
+ }
20
+
21
+ export interface ResponseRound {
22
+ step: ResponseStep
23
+ simpleMd: string
24
+ }
25
+
26
+ export interface ResponseProps extends HTMLAttributes<HTMLDivElement> {
27
+ simulate?: boolean
28
+ phase?: ResponsePhase
29
+ rounds?: ResponseRound[]
30
+ finalMarkdown?: string
31
+ onSimulateComplete?: () => void
32
+ onStepChange?: (text: string, toolType?: ResponseStepToolType) => void
33
+ /** 主库可注入带 Lottie 的 ThinkingIndicator,与独立 ThinkingIndicator 动效一致 */
34
+ thinkingIndicator?: ReactNode
35
+ }
36
+
37
+ const DEMO_STEP_1: ResponseStep = {
38
+ text: 'Scanning local photo library',
39
+ description: 'Indexing metadata and building a rename plan',
40
+ details: [
41
+ { type: 'action', action: 'Discover photos', desc: 'Found 1,000 images in /Pictures/Unsorted' },
42
+ { type: 'action', action: 'Extract metadata', desc: 'Read EXIF timestamps, GPS, and camera model' },
43
+ { type: 'action', action: 'Detect duplicates', desc: 'Hash-based matching + perceptual similarity' },
44
+ ],
45
+ }
46
+
47
+ const DEMO_STEP_2: ResponseStep = {
48
+ text: 'Classifying photos into albums',
49
+ description: 'Clustering by time, location, and scene',
50
+ details: [
51
+ { type: 'action', action: 'Time buckets', desc: 'Group into events using temporal gaps' },
52
+ { type: 'action', action: 'Location clusters', desc: 'Reverse geocode GPS into city/area labels' },
53
+ { type: 'action', action: 'Scene tags', desc: 'Detect indoor/outdoor, portraits, food, and documents' },
54
+ ],
55
+ }
56
+
57
+ const DEMO_STEP_3: ResponseStep = {
58
+ text: 'Renaming files safely',
59
+ description: 'Dry-run, collision check, then atomic move',
60
+ details: [
61
+ { type: 'action', action: 'Dry run', desc: 'Preview 1,000 rename operations' },
62
+ { type: 'action', action: 'Collision handling', desc: 'Append counter suffix to avoid overwrites' },
63
+ { type: 'action', action: 'Write changes', desc: 'Move files into album folders' },
64
+ ],
65
+ }
66
+
67
+ const DEMO_ROUNDS: ResponseRound[] = [
68
+ { step: DEMO_STEP_1, simpleMd: "I'm **scanning** your library and building the index. Found 1,000 photos in `Pictures/Unsorted`; EXIF and duplicates are being analyzed.\n\n" },
69
+ { step: DEMO_STEP_2, simpleMd: "**Classifying** into albums by time, location, and scene. Time buckets and GPS labels are done; next I'll tag indoor/outdoor and document vs. portrait.\n\n" },
70
+ { step: DEMO_STEP_3, simpleMd: "**Dry-run** is done and collision handling is in place. No overwrites; an audit log (CSV) is ready. Pending your confirmation to run the renames.\n\n" },
71
+ ]
72
+
73
+ const DEMO_FINAL_MD = `## Plan
74
+
75
+ I will organize your **1,000 local photos** by building an index, clustering them into albums, and then performing a safe rename + move operation.
76
+
77
+ ### Folder structure
78
+
79
+ \`\`\`text
80
+ Pictures/
81
+ Organized/
82
+ 2026-01-18 — San Francisco — Golden Gate Park/
83
+ 2026-01-05 — Home — Documents/
84
+ 2025-12-31 — New Year's Eve/
85
+ _Duplicates/
86
+ _Unsorted/
87
+ \`\`\`
88
+
89
+ ### Naming scheme
90
+
91
+ \`YYYY-MM-DD_HH-mm-ss__<Location>__<Scene>__<Counter>.<ext>\`
92
+
93
+ Example:
94
+
95
+ \`2026-01-18_15-42-11__San-Francisco__Outdoor__001.jpg\`
96
+
97
+ ### Safety checks
98
+
99
+ - [x] Dry-run all operations
100
+ - [x] Detect collisions and append counters
101
+ - [x] Keep an audit log (CSV)
102
+ - [ ] Execute moves (requires confirmation)
103
+
104
+ ---
105
+
106
+ ## Next step
107
+
108
+ If you want, I can generate a **preview report** first (top 50 renames + album summary) before applying changes.
109
+ `
110
+
111
+ type BlockType = 'think' | 'composer' | 'md'
112
+
113
+ function buildBlocks(rounds: ResponseRound[], finalMd: string): { type: BlockType; step?: ResponseStep; md?: string }[] {
114
+ const blocks: { type: BlockType; step?: ResponseStep; md?: string }[] = []
115
+ for (const r of rounds) {
116
+ blocks.push({ type: 'think' })
117
+ blocks.push({ type: 'composer', step: r.step })
118
+ blocks.push({ type: 'md', md: r.simpleMd })
119
+ }
120
+ blocks.push({ type: 'think' })
121
+ blocks.push({ type: 'md', md: finalMd })
122
+ return blocks
123
+ }
124
+
125
+ const DEFAULT_THINK = <ThinkingIndicator text="Qoder is thinking..." />
126
+
127
+ export function Response({
128
+ simulate = true,
129
+ phase = 'thinking',
130
+ rounds,
131
+ finalMarkdown,
132
+ onSimulateComplete,
133
+ onStepChange,
134
+ thinkingIndicator,
135
+ className,
136
+ ...props
137
+ }: ResponseProps) {
138
+ const thinkNode = thinkingIndicator ?? DEFAULT_THINK
139
+ const allRounds = rounds ?? DEMO_ROUNDS
140
+ const finalMd = finalMarkdown ?? DEMO_FINAL_MD
141
+ const blocks = useMemo(() => buildBlocks(allRounds, finalMd), [allRounds, finalMd])
142
+ const [visibleIndex, setVisibleIndex] = useState(0)
143
+ const isSimDone = simulate ? visibleIndex >= blocks.length - 1 : phase === 'done'
144
+ const currentBlock = blocks[visibleIndex] ?? null
145
+ const showThink = currentBlock?.type === 'think'
146
+
147
+ useEffect(() => {
148
+ if (!simulate || blocks.length === 0) return
149
+ const block = blocks[visibleIndex] ?? null
150
+ if (block?.type === 'composer' && block.step) {
151
+ onStepChange?.(block.step.text, block.step.toolType)
152
+ } else if (block?.type === 'think') {
153
+ onStepChange?.('Thinking...')
154
+ }
155
+ if (visibleIndex >= blocks.length) {
156
+ onSimulateComplete?.()
157
+ }
158
+ }, [simulate, blocks, visibleIndex, onStepChange, onSimulateComplete])
159
+
160
+ useEffect(() => {
161
+ if (!simulate || blocks.length === 0) return
162
+ setVisibleIndex(0)
163
+ }, [simulate, blocks.length])
164
+
165
+ useEffect(() => {
166
+ if (!simulate || blocks.length === 0) return
167
+ const block = blocks[visibleIndex] ?? null
168
+ if (block?.type === 'think' || block?.type === 'composer') {
169
+ const id = window.setTimeout(() => setVisibleIndex((v) => Math.min(v + 1, blocks.length)), 580)
170
+ return () => window.clearTimeout(id)
171
+ }
172
+ }, [simulate, blocks, visibleIndex])
173
+
174
+ const effectiveShowThink = simulate ? showThink : phase === 'thinking' || phase === 'streaming'
175
+
176
+ const contentElements = useMemo(() => {
177
+ const el: ReactNode[] = []
178
+ const upTo = simulate ? Math.min(visibleIndex, blocks.length - 1) : blocks.length - 1
179
+ let lastVisibleComposerIndex = -1
180
+ for (let j = 0; j <= upTo; j++) {
181
+ if (blocks[j]?.type === 'composer') lastVisibleComposerIndex = j
182
+ }
183
+ for (let i = 0; i <= upTo; i++) {
184
+ const b = blocks[i]
185
+ if (!b) continue
186
+ if (b.type === 'think') {
187
+ if (simulate && i === visibleIndex) {
188
+ el.push(<span key={`think-${i}`}>{thinkNode}</span>)
189
+ }
190
+ continue
191
+ }
192
+ if (b.type === 'composer' && b.step) {
193
+ const inProgress = i === lastVisibleComposerIndex && !isSimDone
194
+ el.push(
195
+ <ReasoningStep
196
+ key={i}
197
+ text={b.step.text}
198
+ description={b.step.description}
199
+ details={b.step.details}
200
+ status={inProgress ? 'in-progress' : 'completed'}
201
+ />
202
+ )
203
+ }
204
+ if (b.type === 'md' && b.md) {
205
+ el.push(
206
+ <div key={`md-${i}`} className="mt-1">
207
+ <StreamingMarkdownBlock
208
+ content={b.md}
209
+ isActive={i === upTo}
210
+ onStreamComplete={() => {
211
+ setVisibleIndex((v) => Math.min(v + 1, blocks.length))
212
+ if (i + 1 >= blocks.length) onSimulateComplete?.()
213
+ }}
214
+ />
215
+ </div>
216
+ )
217
+ }
218
+ }
219
+ return el
220
+ }, [simulate, visibleIndex, blocks, isSimDone, onSimulateComplete, thinkNode])
221
+
222
+ if (phase === 'imageGenerating') {
223
+ return (
224
+ <div className={cn('flex flex-col gap-3 font-body', className)} {...props}>
225
+ <ImageGenerating width="320px" height="240px" />
226
+ </div>
227
+ )
228
+ }
229
+
230
+ if (!simulate) {
231
+ const staticEl: ReactNode[] = []
232
+ for (let i = 0; i < blocks.length; i++) {
233
+ const b = blocks[i]
234
+ if (!b) continue
235
+ if (b.type === 'composer' && b.step) {
236
+ staticEl.push(
237
+ <ReasoningStep
238
+ key={i}
239
+ text={b.step.text}
240
+ description={b.step.description}
241
+ details={b.step.details}
242
+ status="completed"
243
+ disableExpandAnimation
244
+ />
245
+ )
246
+ }
247
+ if (b.type === 'md' && b.md) {
248
+ staticEl.push(
249
+ <div key={`md-${i}`} className="mt-1">
250
+ <MarkdownBody>{b.md}</MarkdownBody>
251
+ </div>
252
+ )
253
+ }
254
+ }
255
+ return (
256
+ <div className={cn('flex flex-col gap-3 font-body', className)} {...props}>
257
+ <div className="flex flex-col gap-1">{staticEl}</div>
258
+ {(phase === 'thinking' || phase === 'streaming') && thinkNode}
259
+ </div>
260
+ )
261
+ }
262
+
263
+ return (
264
+ <div className={cn('flex flex-col gap-3 font-body', className)} {...props}>
265
+ <div className="flex flex-col gap-1">{contentElements}</div>
266
+ {effectiveShowThink && !simulate && thinkNode}
267
+ </div>
268
+ )
269
+ }
270
+
271
+ Response.displayName = 'Response'
@@ -0,0 +1,94 @@
1
+ import { forwardRef } from 'react'
2
+ import type { ButtonHTMLAttributes, ReactNode } from 'react'
3
+ import { cva, type VariantProps } from 'class-variance-authority'
4
+ import { SendPlaneLine, StopLine, MicLine } from '../basic/icons-inline'
5
+
6
+ const sendButtonVariants = cva(
7
+ 'inline-flex items-center justify-center rounded-full p-1.5 transition-colors duration-200 focus:outline-none disabled:opacity-50 disabled:cursor-not-allowed cursor-pointer transition-transform active:scale-95 active:translate-y-px',
8
+ {
9
+ variants: {
10
+ status: {
11
+ normal:
12
+ 'SendButton-send bg-bg-highlight hover:bg-bg-highlight-hover active:opacity-80',
13
+ generating:
14
+ 'bg-primary hover:bg-primary-hover active:opacity-80',
15
+ recording:
16
+ 'SendButton-send bg-bg-highlight hover:bg-bg-highlight-hover active:opacity-80',
17
+ stopRecording:
18
+ 'bg-error-bg hover:bg-error-bg-hover active:opacity-80',
19
+ },
20
+ },
21
+ defaultVariants: {
22
+ status: 'normal',
23
+ },
24
+ }
25
+ )
26
+
27
+ const sendButtonIconVariants = cva('inline-flex h-4 w-4 shrink-0 items-center justify-center [&>*]:block [&>*]:leading-none', {
28
+ variants: {
29
+ status: {
30
+ normal: 'text-text-on-primary',
31
+ generating: 'text-text-on-primary',
32
+ recording: 'text-text-on-primary',
33
+ stopRecording: 'text-error',
34
+ },
35
+ },
36
+ defaultVariants: {
37
+ status: 'normal',
38
+ },
39
+ })
40
+
41
+ const iconClass = 'w-4 h-4'
42
+
43
+ export interface SendButtonProps
44
+ extends ButtonHTMLAttributes<HTMLButtonElement>,
45
+ VariantProps<typeof sendButtonVariants> {
46
+ status?: 'normal' | 'generating' | 'recording' | 'stopRecording'
47
+ /** 主库可注入 useIcon('send');不传则用 registry 内联图标 */
48
+ sendIcon?: ReactNode
49
+ stopIcon?: ReactNode
50
+ micIcon?: ReactNode
51
+ }
52
+
53
+ export const SendButton = forwardRef<HTMLButtonElement, SendButtonProps>(
54
+ (
55
+ {
56
+ status = 'normal',
57
+ disabled = false,
58
+ className,
59
+ sendIcon,
60
+ stopIcon,
61
+ micIcon,
62
+ ...props
63
+ },
64
+ ref
65
+ ) => {
66
+ const defaultSend = sendIcon ?? <SendPlaneLine className={iconClass} />
67
+ const defaultStop = stopIcon ?? <StopLine className={iconClass} />
68
+ const defaultMic = micIcon ?? <MicLine className={iconClass} />
69
+ const iconByStatus =
70
+ status === 'normal'
71
+ ? defaultSend
72
+ : status === 'generating' || status === 'stopRecording'
73
+ ? defaultStop
74
+ : defaultMic
75
+
76
+ return (
77
+ <button
78
+ ref={ref}
79
+ type="button"
80
+ className={sendButtonVariants({ status, className })}
81
+ disabled={disabled}
82
+ {...props}
83
+ >
84
+ <span className={sendButtonIconVariants({ status })}>
85
+ {iconByStatus}
86
+ </span>
87
+ </button>
88
+ )
89
+ }
90
+ )
91
+
92
+ SendButton.displayName = 'SendButton'
93
+
94
+ export { sendButtonVariants, sendButtonIconVariants }
@@ -0,0 +1,177 @@
1
+ import { forwardRef, useState } from 'react'
2
+ import type { HTMLAttributes, ReactNode } from 'react'
3
+ import { cn } from '@/lib/utils'
4
+ import {
5
+ DropdownMenu,
6
+ DropdownMenuContent,
7
+ DropdownMenuItem,
8
+ DropdownMenuTrigger,
9
+ } from '../basic/dropdown-menu'
10
+ import { MoreLine } from '../basic/icons-inline'
11
+
12
+ export interface SidebarMenuItemAction {
13
+ id: string
14
+ label: string
15
+ icon?: ReactNode
16
+ onClick?: () => void
17
+ destructive?: boolean
18
+ }
19
+
20
+ export interface SidebarMenuItem {
21
+ id: string
22
+ label: string
23
+ icon?: ReactNode
24
+ disabled?: boolean
25
+ actions?: SidebarMenuItemAction[]
26
+ }
27
+
28
+ export interface SidebarMenuProps extends HTMLAttributes<HTMLDivElement> {
29
+ items: SidebarMenuItem[]
30
+ selectedId?: string
31
+ onItemClick?: (item: SidebarMenuItem) => void
32
+ width?: string
33
+ moreIcon?: ReactNode
34
+ }
35
+
36
+ const moreClass = 'w-4 h-4'
37
+
38
+ export const SidebarMenu = forwardRef<HTMLDivElement, SidebarMenuProps>(
39
+ (
40
+ {
41
+ items,
42
+ selectedId,
43
+ onItemClick,
44
+ width = 'w-52',
45
+ className,
46
+ moreIcon,
47
+ ...props
48
+ },
49
+ ref
50
+ ) => {
51
+ const [openDropdownId, setOpenDropdownId] = useState<string | null>(null)
52
+ const baseStyles = 'flex flex-col gap-1.5 rounded-md bg-transparent'
53
+ const defaultMore = moreIcon ?? <MoreLine className={moreClass} />
54
+
55
+ return (
56
+ <div ref={ref} className={cn(baseStyles, width, className)} {...props}>
57
+ {items.map((item) => {
58
+ const isSelected = selectedId === item.id
59
+ const isDisabled = item.disabled
60
+ const isOpen = openDropdownId === item.id
61
+
62
+ return (
63
+ <div
64
+ key={item.id}
65
+ className={cn(
66
+ 'group flex items-center gap-2 py-1 px-2 rounded-md text-sm leading-sm transition-colors',
67
+ 'focus-within:outline-none min-w-0',
68
+ isDisabled && 'opacity-50 cursor-not-allowed',
69
+ !isDisabled && 'cursor-pointer',
70
+ isSelected
71
+ ? 'bg-fill-secondary text-text'
72
+ : 'bg-transparent text-text-secondary hover:bg-fill-secondary hover:text-text'
73
+ )}
74
+ >
75
+ <button
76
+ onClick={() => {
77
+ if (!isDisabled) onItemClick?.(item)
78
+ setOpenDropdownId(null)
79
+ }}
80
+ disabled={isDisabled}
81
+ className="flex-1 text-left truncate min-w-0 outline-none bg-transparent border-none p-0 cursor-pointer"
82
+ >
83
+ {item.label}
84
+ </button>
85
+ {item.actions && item.actions.length > 0 ? (
86
+ <div onClick={(e) => e.stopPropagation()}>
87
+ <DropdownMenu
88
+ open={isOpen}
89
+ onOpenChange={(open) => {
90
+ setOpenDropdownId(open ? item.id : null)
91
+ }}
92
+ >
93
+ <DropdownMenuTrigger asChild>
94
+ <button
95
+ className={cn(
96
+ 'flex items-center justify-center p-1 rounded outline-none transition-all duration-200 relative z-10 cursor-pointer hover:bg-fill-primary'
97
+ )}
98
+ style={{ pointerEvents: 'auto' }}
99
+ onClick={(e) => e.stopPropagation()}
100
+ onMouseDown={(e) => e.stopPropagation()}
101
+ >
102
+ <span
103
+ className={cn(
104
+ 'transition-opacity pointer-events-none flex items-center justify-center',
105
+ isSelected ? 'opacity-100' : 'opacity-0 group-hover:opacity-100'
106
+ )}
107
+ >
108
+ {item.icon ?? (
109
+ <span
110
+ className={cn(
111
+ 'w-4 h-4 inline-flex items-center justify-center',
112
+ isSelected ? 'text-text' : 'text-text-secondary'
113
+ )}
114
+ >
115
+ {defaultMore}
116
+ </span>
117
+ )}
118
+ </span>
119
+ </button>
120
+ </DropdownMenuTrigger>
121
+ <DropdownMenuContent align="end">
122
+ {item.actions.map((action) => (
123
+ <DropdownMenuItem
124
+ key={action.id}
125
+ variant={action.destructive ? 'destructive' : 'default'}
126
+ onClick={(e) => {
127
+ e.stopPropagation()
128
+ setOpenDropdownId(null)
129
+ action.onClick?.()
130
+ }}
131
+ >
132
+ {action.icon && (
133
+ <span className="mr-2 w-4 h-4 flex items-center justify-center">
134
+ {action.icon}
135
+ </span>
136
+ )}
137
+ {action.label}
138
+ </DropdownMenuItem>
139
+ ))}
140
+ </DropdownMenuContent>
141
+ </DropdownMenu>
142
+ </div>
143
+ ) : (
144
+ <span
145
+ className="flex-shrink-0 w-4 h-4 flex items-center justify-center"
146
+ onClick={(e) => e.stopPropagation()}
147
+ >
148
+ {item.icon ? (
149
+ <span
150
+ className={cn(
151
+ 'transition-opacity pointer-events-none',
152
+ isSelected ? 'opacity-100' : 'opacity-0 group-hover:opacity-100'
153
+ )}
154
+ >
155
+ {item.icon}
156
+ </span>
157
+ ) : (
158
+ <span
159
+ className={cn(
160
+ 'w-4 h-4 inline-flex items-center justify-center transition-opacity pointer-events-none',
161
+ isSelected ? 'opacity-100 text-text' : 'opacity-0 group-hover:opacity-100 text-text-secondary'
162
+ )}
163
+ >
164
+ {defaultMore}
165
+ </span>
166
+ )}
167
+ </span>
168
+ )}
169
+ </div>
170
+ )
171
+ })}
172
+ </div>
173
+ )
174
+ }
175
+ )
176
+
177
+ SidebarMenu.displayName = 'SidebarMenu'
@@ -0,0 +1,111 @@
1
+ import { useEffect, useMemo, useRef, useState } from 'react'
2
+ import { MarkdownBody } from './markdown'
3
+
4
+ function segmentForStreaming(text: string): string[] {
5
+ const tokens: string[] = []
6
+ let i = 0
7
+ const isCJK = (c: string) => /[\u4e00-\u9fff\u3040-\u30ff]/.test(c)
8
+ const isWordChar = (c: string) => /[a-zA-Z0-9']/.test(c)
9
+ while (i < text.length) {
10
+ const c = text[i]!
11
+ if (isCJK(c)) {
12
+ tokens.push(c)
13
+ i += 1
14
+ } else if (isWordChar(c)) {
15
+ let end = i
16
+ while (end < text.length && isWordChar(text[end]!)) end += 1
17
+ tokens.push(text.slice(i, end))
18
+ i = end
19
+ } else {
20
+ let end = i
21
+ while (end < text.length && !isCJK(text[end]!) && !isWordChar(text[end]!)) end += 1
22
+ tokens.push(text.slice(i, end))
23
+ i = end
24
+ }
25
+ }
26
+ return tokens
27
+ }
28
+
29
+ function splitCompletedBlocks(visibleText: string): { completed: string; partial: string } {
30
+ const blocks = visibleText.split(/\n\n+/)
31
+ if (blocks.length <= 1) return { completed: '', partial: visibleText }
32
+ const partial = blocks.pop() ?? ''
33
+ const completed = blocks.join('\n\n')
34
+ return { completed, partial }
35
+ }
36
+
37
+ export interface StreamingMarkdownBlockProps {
38
+ content: string
39
+ isActive: boolean
40
+ onStreamComplete?: () => void
41
+ tokenDelayMs?: number
42
+ className?: string
43
+ }
44
+
45
+ const TOKENS_PER_TICK = 3
46
+
47
+ export function StreamingMarkdownBlock({
48
+ content,
49
+ isActive,
50
+ onStreamComplete,
51
+ tokenDelayMs = 14,
52
+ className,
53
+ }: StreamingMarkdownBlockProps) {
54
+ const tokens = useMemo(() => segmentForStreaming(content), [content])
55
+ const [visibleCount, setVisibleCount] = useState(0)
56
+ const onStreamCompleteRef = useRef(onStreamComplete)
57
+ onStreamCompleteRef.current = onStreamComplete
58
+
59
+ const visibleText = useMemo(
60
+ () => tokens.slice(0, visibleCount).join(''),
61
+ [tokens, visibleCount]
62
+ )
63
+ const { completed, partial } = useMemo(() => splitCompletedBlocks(visibleText), [visibleText])
64
+
65
+ useEffect(() => {
66
+ if (!isActive) return
67
+ setVisibleCount(0)
68
+ const len = tokens.length
69
+ if (len === 0) {
70
+ onStreamCompleteRef.current?.()
71
+ return
72
+ }
73
+ let k = 0
74
+ const id = setInterval(() => {
75
+ k = Math.min(k + TOKENS_PER_TICK, len)
76
+ setVisibleCount(k)
77
+ if (k >= len) {
78
+ clearInterval(id)
79
+ onStreamCompleteRef.current?.()
80
+ }
81
+ }, tokenDelayMs)
82
+ return () => clearInterval(id)
83
+ }, [isActive, content, tokens.length, tokenDelayMs])
84
+
85
+ const isStreaming = isActive && visibleCount < tokens.length
86
+
87
+ if (tokens.length === 0) return null
88
+
89
+ if (isStreaming) {
90
+ return (
91
+ <div className={className}>
92
+ {completed ? (
93
+ <div className="streaming-completed">
94
+ <MarkdownBody>{completed}</MarkdownBody>
95
+ </div>
96
+ ) : null}
97
+ {partial ? (
98
+ <span className="streaming-partial text-sm leading-sm text-text streaming-token-fade-in">
99
+ {partial}
100
+ </span>
101
+ ) : null}
102
+ </div>
103
+ )
104
+ }
105
+
106
+ return (
107
+ <div className={className}>
108
+ <MarkdownBody>{content}</MarkdownBody>
109
+ </div>
110
+ )
111
+ }