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,198 @@
1
+ import type { Dispatch, MutableRefObject, SetStateAction } from 'react'
2
+ import { useState } from 'react'
3
+ import { cn } from '@/lib/utils'
4
+ import { OptionList } from '../../basic/option-list'
5
+ import type { OptionItem } from '../../basic/option-list'
6
+ import type { UserQuestionItem, UserQuestionLabels } from './types'
7
+
8
+ export interface UserQuestionCardProps {
9
+ question: UserQuestionItem
10
+ qIndex: number
11
+ labels: Required<UserQuestionLabels>
12
+ answers: Record<string, string[]>
13
+ customInputs: Record<string, string>
14
+ focusedOptionIndex: number
15
+ isCurrentQuestion: boolean
16
+ isSubmitting: boolean
17
+ allQuestionsAnswered: boolean
18
+ questionsLength: number
19
+ questionRefs: MutableRefObject<Map<number, HTMLDivElement>>
20
+ customInputRefs: MutableRefObject<Map<string, HTMLInputElement>>
21
+ setCurrentQuestionIndex: (i: number) => void
22
+ setFocusedOptionIndex: (i: number) => void
23
+ setAnswers: Dispatch<SetStateAction<Record<string, string[]>>>
24
+ setCustomInputs: Dispatch<SetStateAction<Record<string, string>>>
25
+ getSelectedOptionIndex: (i: number) => number
26
+ shouldScrollToQuestionRef: MutableRefObject<boolean>
27
+ onOptionClick: (questionText: string, optionLabel: string, questionIndex: number) => void
28
+ onContinue: () => void
29
+ }
30
+
31
+ export function UserQuestionCard({
32
+ question,
33
+ qIndex,
34
+ labels,
35
+ answers,
36
+ customInputs,
37
+ focusedOptionIndex,
38
+ isCurrentQuestion,
39
+ isSubmitting,
40
+ allQuestionsAnswered,
41
+ questionsLength,
42
+ questionRefs,
43
+ customInputRefs,
44
+ setCurrentQuestionIndex,
45
+ setFocusedOptionIndex,
46
+ setAnswers,
47
+ setCustomInputs,
48
+ getSelectedOptionIndex,
49
+ shouldScrollToQuestionRef,
50
+ onOptionClick,
51
+ onContinue,
52
+ }: UserQuestionCardProps) {
53
+ const questionOptions = question.options || []
54
+ const [isInputFocused, setIsInputFocused] = useState(false)
55
+ const hasInputValue = !!(customInputs[question.question]?.trim())
56
+ const showUnderline = isInputFocused || hasInputValue
57
+
58
+ return (
59
+ <div
60
+ key={question.question}
61
+ ref={(el) => {
62
+ if (el) questionRefs.current.set(qIndex, el)
63
+ else questionRefs.current.delete(qIndex)
64
+ }}
65
+ className={cn(
66
+ 'transition-opacity duration-200',
67
+ isCurrentQuestion ? 'opacity-100' : 'opacity-40'
68
+ )}
69
+ >
70
+ <div className="flex items-start gap-3 pl-2 mb-3">
71
+ <div className="flex-shrink-0 w-5 flex items-center justify-center text-sm leading-sm font-medium text-text-tertiary">
72
+ {qIndex + 1}.
73
+ </div>
74
+ <div className="text-sm leading-sm font-medium text-text min-w-0 flex-1">
75
+ {question.question}
76
+ </div>
77
+ </div>
78
+ <OptionList
79
+ items={questionOptions.map((opt) => ({
80
+ id: opt.label,
81
+ label: opt.label,
82
+ description: opt.description,
83
+ }))}
84
+ selectedIds={answers[question.question]?.map((l) => l) || []}
85
+ focusedId={
86
+ isCurrentQuestion ? questionOptions[focusedOptionIndex]?.label : undefined
87
+ }
88
+ disabled={isSubmitting || !isCurrentQuestion}
89
+ onItemClick={(item: OptionItem, index: number) => {
90
+ if (!isCurrentQuestion) {
91
+ setCurrentQuestionIndex(qIndex)
92
+ setFocusedOptionIndex(getSelectedOptionIndex(qIndex))
93
+ return
94
+ }
95
+ onOptionClick(question.question, item.label, qIndex)
96
+ setFocusedOptionIndex(index)
97
+ }}
98
+ />
99
+ {question.allowCustomInput !== false && (
100
+ <div
101
+ className={cn(
102
+ 'w-full flex gap-3 pl-2 mt-3 transition-colors',
103
+ !isCurrentQuestion && 'opacity-40',
104
+ isSubmitting && 'opacity-50'
105
+ )}
106
+ >
107
+ <div
108
+ className={cn(
109
+ 'flex-shrink-0 w-5 h-5 rounded-full flex items-center justify-center text-xs leading-xs font-medium transition-colors',
110
+ (isCurrentQuestion && focusedOptionIndex === questionOptions.length) ||
111
+ customInputs[question.question]?.trim()
112
+ ? 'bg-primary-active text-text-on-primary'
113
+ : 'bg-fill-secondary text-text-tertiary'
114
+ )}
115
+ >
116
+ {questionOptions.length + 1}
117
+ </div>
118
+ <div className="flex-1 min-w-0 flex flex-col">
119
+ <div className="h-5 flex items-center">
120
+ <input
121
+ ref={(el) => {
122
+ if (el) customInputRefs.current.set(question.question, el)
123
+ else customInputRefs.current.delete(question.question)
124
+ }}
125
+ type="text"
126
+ value={customInputs[question.question] || ''}
127
+ style={{ outline: 'none', outlineOffset: 0, boxShadow: 'none', border: 'none' }}
128
+ onChange={(e) => {
129
+ const value = e.target.value
130
+ setCustomInputs((prev) => ({ ...prev, [question.question]: value }))
131
+ if (!question.multiSelect && value.trim()) {
132
+ setAnswers((prev) => ({
133
+ ...prev,
134
+ [question.question]: [],
135
+ }))
136
+ }
137
+ }}
138
+ onFocus={() => {
139
+ setIsInputFocused(true)
140
+ if (isCurrentQuestion) {
141
+ setFocusedOptionIndex(questionOptions.length)
142
+ if (!question.multiSelect) {
143
+ setAnswers((prev) => ({
144
+ ...prev,
145
+ [question.question]: [],
146
+ }))
147
+ }
148
+ }
149
+ }}
150
+ onBlur={() => setIsInputFocused(false)}
151
+ onKeyDown={(e) => {
152
+ if (e.key === 'Enter' && !e.shiftKey) {
153
+ e.preventDefault()
154
+ e.stopPropagation()
155
+ const currentCustomInput = customInputs[question.question]?.trim()
156
+ const currentSelectedOptions = answers[question.question] || []
157
+ const hasAnswer =
158
+ currentSelectedOptions.length > 0 || !!currentCustomInput
159
+ if (hasAnswer) {
160
+ if (allQuestionsAnswered) {
161
+ onContinue()
162
+ } else if (qIndex < questionsLength - 1) {
163
+ const nextIndex = qIndex + 1
164
+ shouldScrollToQuestionRef.current = true
165
+ setCurrentQuestionIndex(nextIndex)
166
+ setFocusedOptionIndex(0)
167
+ } else {
168
+ onContinue()
169
+ }
170
+ }
171
+ }
172
+ }}
173
+ placeholder={labels.customInputPlaceholder}
174
+ disabled={isSubmitting || !isCurrentQuestion}
175
+ className={cn(
176
+ 'w-full h-full py-0 bg-transparent text-sm leading-sm font-medium text-text',
177
+ 'placeholder:text-text-tertiary placeholder:font-normal',
178
+ 'border-0 rounded-none outline-none outline-offset-0',
179
+ 'focus:outline-none focus:outline-offset-0',
180
+ 'focus-visible:outline-none focus-visible:outline-offset-0',
181
+ 'ring-0 focus:ring-0 focus:ring-offset-0 focus-visible:ring-0 focus-visible:ring-offset-0 shadow-none',
182
+ 'disabled:cursor-not-allowed'
183
+ )}
184
+ />
185
+ </div>
186
+ <div
187
+ className="mt-1.5 overflow-hidden origin-left transition-[width] duration-200 ease-out"
188
+ style={{ width: showUnderline ? '100%' : '0%' }}
189
+ aria-hidden
190
+ >
191
+ <div className="h-px bg-[var(--color-border-tertiary)]" />
192
+ </div>
193
+ </div>
194
+ </div>
195
+ )}
196
+ </div>
197
+ )
198
+ }
@@ -0,0 +1,66 @@
1
+ import type { ReactNode } from 'react'
2
+ import { Button } from '../../basic/button'
3
+ import type { UserQuestionLabels } from './types'
4
+
5
+ export interface UserQuestionFooterProps {
6
+ labels: Required<UserQuestionLabels>
7
+ sparklingIcon: ReactNode
8
+ isSubmitting: boolean
9
+ hasCustomText: boolean
10
+ allQuestionsAnswered: boolean
11
+ onRecommend: () => void
12
+ onSkip: () => void
13
+ onContinue: () => void
14
+ }
15
+
16
+ export function UserQuestionFooter({
17
+ labels,
18
+ sparklingIcon,
19
+ isSubmitting,
20
+ hasCustomText,
21
+ allQuestionsAnswered,
22
+ onRecommend,
23
+ onSkip,
24
+ onContinue,
25
+ }: UserQuestionFooterProps) {
26
+ return (
27
+ <div className="flex items-center justify-between px-3 py-2">
28
+ <Button
29
+ variant="ghost"
30
+ size="sm"
31
+ onClick={onRecommend}
32
+ disabled={isSubmitting}
33
+ >
34
+ {sparklingIcon}
35
+ {labels.recommend}
36
+ </Button>
37
+ <div className="flex items-center gap-2">
38
+ {!allQuestionsAnswered && (
39
+ <Button
40
+ variant="ghost"
41
+ size="sm"
42
+ onClick={onSkip}
43
+ disabled={isSubmitting}
44
+ >
45
+ {labels.skipAll}
46
+ </Button>
47
+ )}
48
+ <Button
49
+ size="sm"
50
+ variant="secondary"
51
+ onClick={onContinue}
52
+ disabled={isSubmitting || hasCustomText || !allQuestionsAnswered}
53
+ >
54
+ {isSubmitting ? (
55
+ labels.sending
56
+ ) : (
57
+ <>
58
+ {allQuestionsAnswered ? labels.submit : labels.continue}
59
+ <span className="opacity-70"> ↵</span>
60
+ </>
61
+ )}
62
+ </Button>
63
+ </div>
64
+ </div>
65
+ )
66
+ }
@@ -0,0 +1,64 @@
1
+ import type { ReactNode } from 'react'
2
+ import { IconButton } from '../../basic/icon-button'
3
+ import type { UserQuestionItem } from './types'
4
+ import type { UserQuestionLabels } from './types'
5
+
6
+ export interface UserQuestionHeaderProps {
7
+ currentQuestion: UserQuestionItem | undefined
8
+ questionsLength: number
9
+ labels: Required<UserQuestionLabels>
10
+ chat4Icon: ReactNode
11
+ arrowUpSIcon: ReactNode
12
+ arrowDownSIcon: ReactNode
13
+ currentQuestionIndex: number
14
+ onPrevious: () => void
15
+ onNext: () => void
16
+ }
17
+
18
+ export function UserQuestionHeader({
19
+ currentQuestion,
20
+ questionsLength,
21
+ labels,
22
+ chat4Icon,
23
+ arrowUpSIcon,
24
+ arrowDownSIcon,
25
+ currentQuestionIndex,
26
+ onPrevious,
27
+ onNext,
28
+ }: UserQuestionHeaderProps) {
29
+ return (
30
+ <div className="flex items-center justify-between mb-2 -mt-2 px-3 pt-2 pb-2 rounded-t-xl bg-fill-tertiary">
31
+ <div className="flex items-center gap-1.5">
32
+ {chat4Icon}
33
+ <span className="text-xs leading-xs text-text-tertiary">
34
+ {currentQuestion?.header || labels.questionHeader}
35
+ </span>
36
+ <span className="text-text-tertiary/50">•</span>
37
+ <span className="text-xs leading-xs text-text-tertiary">
38
+ {currentQuestion?.multiSelect ? labels.multiSelect : labels.singleSelect}
39
+ </span>
40
+ </div>
41
+ {questionsLength > 1 && (
42
+ <div className="flex items-center gap-1">
43
+ <IconButton
44
+ size="sm"
45
+ variant="ghost"
46
+ onClick={onPrevious}
47
+ disabled={currentQuestionIndex === 0}
48
+ icon={arrowUpSIcon}
49
+ />
50
+ <span className="text-xs leading-xs text-text-tertiary px-1">
51
+ {currentQuestionIndex + 1} / {questionsLength}
52
+ </span>
53
+ <IconButton
54
+ size="sm"
55
+ variant="ghost"
56
+ onClick={onNext}
57
+ disabled={currentQuestionIndex === questionsLength - 1}
58
+ icon={arrowDownSIcon}
59
+ />
60
+ </div>
61
+ )}
62
+ </div>
63
+ )
64
+ }
@@ -0,0 +1,340 @@
1
+ import { memo, useCallback, forwardRef } from 'react'
2
+ import type { ReactNode } from 'react'
3
+ import { cn } from '@/lib/utils'
4
+ import { motion } from 'framer-motion'
5
+ import { Chat3Line, ArrowUpLine, ArrowDownSLine, SparklingLine } from '../../basic/icons-inline'
6
+ import {
7
+ DEFAULT_LABELS,
8
+ NO_PREFERENCE_VALUE,
9
+ type UserQuestionProps,
10
+ type UserQuestionHandle,
11
+ type UserQuestionItem,
12
+ } from './types'
13
+ import { useUserQuestionState } from './useUserQuestionState'
14
+ import { useUserQuestionKeyboard } from './useUserQuestionKeyboard'
15
+ import { UserQuestionHeader } from './UserQuestionHeader'
16
+ import { UserQuestionCard } from './UserQuestionCard'
17
+ import { UserQuestionFooter } from './UserQuestionFooter'
18
+ import { Scrollbar } from '../../basic/scrollbar'
19
+
20
+ export type {
21
+ UserQuestionOption,
22
+ UserQuestionItem,
23
+ UserQuestionLabels,
24
+ UserQuestionProps,
25
+ UserQuestionHandle,
26
+ } from './types'
27
+ export { DEFAULT_LABELS, NO_PREFERENCE_VALUE } from './types'
28
+ export { UserQuestionHeader } from './UserQuestionHeader'
29
+ export { UserQuestionCard } from './UserQuestionCard'
30
+ export { UserQuestionFooter } from './UserQuestionFooter'
31
+
32
+ const defaultChat4Icon: ReactNode = (
33
+ <Chat3Line className="w-4 h-4 shrink-0 text-text-tertiary" />
34
+ )
35
+ const defaultArrowUpSIcon = <ArrowUpLine />
36
+ const defaultArrowDownSIcon = <ArrowDownSLine />
37
+ const defaultSparklingIcon = <SparklingLine className="w-4 h-4 mr-1" />
38
+
39
+ export const UserQuestion = memo(
40
+ forwardRef<UserQuestionHandle, UserQuestionProps>(function UserQuestion(
41
+ {
42
+ questions,
43
+ resetKey,
44
+ onAnswer,
45
+ onSkip,
46
+ hasCustomText = false,
47
+ labels: labelsProp,
48
+ chat4Icon = defaultChat4Icon,
49
+ arrowUpSIcon = defaultArrowUpSIcon,
50
+ arrowDownSIcon = defaultArrowDownSIcon,
51
+ sparklingIcon = defaultSparklingIcon,
52
+ }: UserQuestionProps,
53
+ ref
54
+ ) {
55
+ const labels = { ...DEFAULT_LABELS, ...labelsProp }
56
+ const state = useUserQuestionState({ questions, resetKey, ref, onAnswer })
57
+
58
+ const {
59
+ currentQuestionIndex,
60
+ setCurrentQuestionIndex,
61
+ answers,
62
+ setAnswers,
63
+ customInputs,
64
+ setCustomInputs,
65
+ focusedOptionIndex,
66
+ setFocusedOptionIndex,
67
+ isSubmitting,
68
+ setIsSubmitting,
69
+ maxQuestionHeight,
70
+ scrollContainerRef,
71
+ questionRefs,
72
+ shouldScrollToQuestionRef,
73
+ customInputRefs,
74
+ getSelectedOptionIndex,
75
+ } = state
76
+
77
+ const currentQuestion = questions[currentQuestionIndex]
78
+ const currentOptions = currentQuestion?.options || []
79
+ const allQuestionsAnswered = questions.every(
80
+ (q) =>
81
+ (answers[q.question] || []).length > 0 ||
82
+ (customInputs[q.question]?.trim() || '').length > 0
83
+ )
84
+ const currentQuestionHasAnswer =
85
+ (answers[currentQuestion?.question] || []).length > 0 ||
86
+ (customInputs[currentQuestion?.question]?.trim() || '').length > 0
87
+
88
+ const handleOptionClick = useCallback(
89
+ (questionText: string, optionLabel: string, questionIndex: number) => {
90
+ const question = questions[questionIndex]
91
+ const allowMultiple = question?.multiSelect ?? false
92
+ const isLastQuestion = questionIndex === questions.length - 1
93
+ const currentAnswers = answers[questionText] || []
94
+ const isDeselecting = currentAnswers.includes(optionLabel)
95
+
96
+ setAnswers((prev) => {
97
+ const cur = prev[questionText] || []
98
+ if (allowMultiple) {
99
+ if (cur.includes(optionLabel)) {
100
+ return { ...prev, [questionText]: cur.filter((l) => l !== optionLabel) }
101
+ }
102
+ return { ...prev, [questionText]: [...cur, optionLabel] }
103
+ }
104
+ if (cur.includes(optionLabel)) return { ...prev, [questionText]: [] }
105
+ return { ...prev, [questionText]: [optionLabel] }
106
+ })
107
+
108
+ if (!allowMultiple) {
109
+ setCustomInputs((prev) => ({ ...prev, [questionText]: '' }))
110
+ }
111
+
112
+ const shouldAutoNext =
113
+ !allowMultiple && !isLastQuestion && !isDeselecting
114
+ if (shouldAutoNext) {
115
+ setTimeout(() => {
116
+ const nextIndex = questionIndex + 1
117
+ shouldScrollToQuestionRef.current = true
118
+ setCurrentQuestionIndex(nextIndex)
119
+ setFocusedOptionIndex(getSelectedOptionIndex(nextIndex))
120
+ }, 150)
121
+ }
122
+ },
123
+ [
124
+ questions,
125
+ answers,
126
+ setAnswers,
127
+ setCustomInputs,
128
+ setCurrentQuestionIndex,
129
+ setFocusedOptionIndex,
130
+ getSelectedOptionIndex,
131
+ shouldScrollToQuestionRef,
132
+ ]
133
+ )
134
+
135
+ const handlePrevious = useCallback(() => {
136
+ if (currentQuestionIndex > 0) {
137
+ const prevIndex = currentQuestionIndex - 1
138
+ shouldScrollToQuestionRef.current = true
139
+ setCurrentQuestionIndex(prevIndex)
140
+ setFocusedOptionIndex(getSelectedOptionIndex(prevIndex))
141
+ }
142
+ }, [currentQuestionIndex, setCurrentQuestionIndex, setFocusedOptionIndex, getSelectedOptionIndex, shouldScrollToQuestionRef])
143
+
144
+ const handleNext = useCallback(() => {
145
+ if (currentQuestionIndex < questions.length - 1) {
146
+ const nextIndex = currentQuestionIndex + 1
147
+ shouldScrollToQuestionRef.current = true
148
+ setCurrentQuestionIndex(nextIndex)
149
+ setFocusedOptionIndex(getSelectedOptionIndex(nextIndex))
150
+ }
151
+ }, [currentQuestionIndex, questions.length, setCurrentQuestionIndex, setFocusedOptionIndex, getSelectedOptionIndex, shouldScrollToQuestionRef])
152
+
153
+ const handleContinue = useCallback(() => {
154
+ if (isSubmitting) return
155
+ if (allQuestionsAnswered) {
156
+ setIsSubmitting(true)
157
+ const formatted: Record<string, string> = {}
158
+ for (const q of questions) {
159
+ const selected = answers[q.question] || []
160
+ const custom = customInputs[q.question]?.trim()
161
+ const parts: string[] = []
162
+ if (selected.length > 0) parts.push(...selected)
163
+ if (custom) parts.push(custom)
164
+ formatted[q.question] = parts.join(', ')
165
+ }
166
+ onAnswer(formatted)
167
+ } else {
168
+ const isUnanswered = (q: UserQuestionItem) =>
169
+ (answers[q.question] || []).length === 0 &&
170
+ (customInputs[q.question]?.trim() || '').length === 0
171
+ const len = questions.length
172
+ let nextUnansweredIndex = -1
173
+ for (let i = 1; i < len; i++) {
174
+ const idx = (currentQuestionIndex + i) % len
175
+ if (isUnanswered(questions[idx])) {
176
+ nextUnansweredIndex = idx
177
+ break
178
+ }
179
+ }
180
+ if (nextUnansweredIndex >= 0) {
181
+ shouldScrollToQuestionRef.current = true
182
+ setCurrentQuestionIndex(nextUnansweredIndex)
183
+ setFocusedOptionIndex(getSelectedOptionIndex(nextUnansweredIndex))
184
+ }
185
+ }
186
+ }, [
187
+ isSubmitting,
188
+ allQuestionsAnswered,
189
+ questions,
190
+ answers,
191
+ customInputs,
192
+ currentQuestionIndex,
193
+ onAnswer,
194
+ setIsSubmitting,
195
+ setCurrentQuestionIndex,
196
+ setFocusedOptionIndex,
197
+ getSelectedOptionIndex,
198
+ shouldScrollToQuestionRef,
199
+ ])
200
+
201
+ const handleSkipWithGuard = useCallback(() => {
202
+ if (isSubmitting) return
203
+ setIsSubmitting(true)
204
+ const finalAnswers: Record<string, string> = {}
205
+ for (const q of questions) {
206
+ const selected = answers[q.question] || []
207
+ const custom = customInputs[q.question]?.trim()
208
+ const hasAnswer = selected.length > 0 || !!custom
209
+ if (hasAnswer) {
210
+ const parts: string[] = []
211
+ if (selected.length > 0) parts.push(...selected)
212
+ if (custom) parts.push(custom)
213
+ finalAnswers[q.question] = parts.join(', ')
214
+ } else {
215
+ finalAnswers[q.question] = NO_PREFERENCE_VALUE
216
+ }
217
+ }
218
+ onAnswer(finalAnswers)
219
+ onSkip()
220
+ }, [isSubmitting, questions, answers, customInputs, onAnswer, onSkip, setIsSubmitting])
221
+
222
+ const handleRecommend = useCallback(() => {
223
+ if (isSubmitting) return
224
+ const recommended: Record<string, string[]> = {}
225
+ for (const q of questions) {
226
+ const first = q.options?.[0]
227
+ if (first) recommended[q.question] = [first.label]
228
+ }
229
+ setAnswers(recommended)
230
+ setCustomInputs({})
231
+ shouldScrollToQuestionRef.current = true
232
+ setCurrentQuestionIndex(questions.length - 1)
233
+ setFocusedOptionIndex(0)
234
+ setTimeout(() => {
235
+ if (scrollContainerRef.current) {
236
+ scrollContainerRef.current.scrollTo({
237
+ top: scrollContainerRef.current.scrollHeight,
238
+ behavior: 'smooth',
239
+ })
240
+ }
241
+ }, 50)
242
+ }, [
243
+ isSubmitting,
244
+ questions,
245
+ setAnswers,
246
+ setCustomInputs,
247
+ setCurrentQuestionIndex,
248
+ setFocusedOptionIndex,
249
+ shouldScrollToQuestionRef,
250
+ scrollContainerRef,
251
+ ])
252
+
253
+ useUserQuestionKeyboard({
254
+ isSubmitting,
255
+ currentQuestion,
256
+ currentOptions,
257
+ currentQuestionIndex,
258
+ questions,
259
+ focusedOptionIndex,
260
+ setFocusedOptionIndex,
261
+ currentQuestionHasAnswer,
262
+ getSelectedOptionIndex,
263
+ shouldScrollToQuestionRef,
264
+ setCurrentQuestionIndex,
265
+ handleOptionClick,
266
+ handleContinue,
267
+ })
268
+
269
+ if (questions.length === 0) return null
270
+
271
+ return (
272
+ <motion.div
273
+ initial={{ opacity: 0, y: 8 }}
274
+ animate={{ opacity: 1, y: 0 }}
275
+ transition={{ duration: 0.2, ease: [0.16, 1, 0.3, 1] }}
276
+ className={cn(
277
+ 'border rounded-t-xl border-b-0 border-border border-border-tertiary bg-bg-base overflow-hidden pt-2 pb-2'
278
+ )}
279
+ >
280
+ <UserQuestionHeader
281
+ currentQuestion={currentQuestion}
282
+ questionsLength={questions.length}
283
+ labels={labels}
284
+ chat4Icon={chat4Icon}
285
+ arrowUpSIcon={arrowUpSIcon}
286
+ arrowDownSIcon={arrowDownSIcon}
287
+ currentQuestionIndex={currentQuestionIndex}
288
+ onPrevious={handlePrevious}
289
+ onNext={handleNext}
290
+ />
291
+ <Scrollbar
292
+ ref={scrollContainerRef}
293
+ scrollbarVisibility="auto"
294
+ maxHeight={maxQuestionHeight ? maxQuestionHeight : undefined}
295
+ className="scroll-smooth"
296
+ >
297
+ <div className="space-y-4 px-3">
298
+ {questions.map((question, qIndex) => (
299
+ <UserQuestionCard
300
+ key={question.question}
301
+ question={question}
302
+ qIndex={qIndex}
303
+ labels={labels}
304
+ answers={answers}
305
+ customInputs={customInputs}
306
+ focusedOptionIndex={focusedOptionIndex}
307
+ isCurrentQuestion={qIndex === currentQuestionIndex}
308
+ isSubmitting={isSubmitting}
309
+ allQuestionsAnswered={allQuestionsAnswered}
310
+ questionsLength={questions.length}
311
+ questionRefs={questionRefs}
312
+ customInputRefs={customInputRefs}
313
+ setCurrentQuestionIndex={setCurrentQuestionIndex}
314
+ setFocusedOptionIndex={setFocusedOptionIndex}
315
+ setAnswers={setAnswers}
316
+ setCustomInputs={setCustomInputs}
317
+ getSelectedOptionIndex={getSelectedOptionIndex}
318
+ shouldScrollToQuestionRef={shouldScrollToQuestionRef}
319
+ onOptionClick={handleOptionClick}
320
+ onContinue={handleContinue}
321
+ />
322
+ ))}
323
+ </div>
324
+ </Scrollbar>
325
+ <UserQuestionFooter
326
+ labels={labels}
327
+ sparklingIcon={sparklingIcon}
328
+ isSubmitting={isSubmitting}
329
+ hasCustomText={hasCustomText}
330
+ allQuestionsAnswered={allQuestionsAnswered}
331
+ onRecommend={handleRecommend}
332
+ onSkip={handleSkipWithGuard}
333
+ onContinue={handleContinue}
334
+ />
335
+ </motion.div>
336
+ )
337
+ })
338
+ )
339
+
340
+ UserQuestion.displayName = 'UserQuestion'