@heyramzi/ui 0.0.0-stage → 1.53.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 (564) hide show
  1. package/COMPONENTS.md +133 -0
  2. package/README.md +136 -2
  3. package/package.json +217 -3
  4. package/scripts/lib/sync-core.mjs +113 -0
  5. package/scripts/relative-imports.mjs +39 -0
  6. package/scripts/sf-symbol.mjs +93 -0
  7. package/scripts/sync-shadcn.mjs +354 -0
  8. package/scripts/sync-transitions.mjs +146 -0
  9. package/scripts/validate-apple-symbol-exports.mjs +45 -0
  10. package/src/agents/agent-avatar.svelte +592 -0
  11. package/src/agents/agent-cast.svelte +197 -0
  12. package/src/agents/demo.svelte +125 -0
  13. package/src/agents/helpers.ts +58 -0
  14. package/src/agents/index.ts +11 -0
  15. package/src/agents/page-state.ts +70 -0
  16. package/src/agents/types.ts +74 -0
  17. package/src/agents/vendor/LICENSE +21 -0
  18. package/src/agents/vendor/color.ts +155 -0
  19. package/src/agents/vendor/draw.ts +840 -0
  20. package/src/agents/vendor/engine.ts +845 -0
  21. package/src/agents/vendor/mesh.ts +838 -0
  22. package/src/agents/vendor/plastic.ts +4958 -0
  23. package/src/agents/vendor/presets.ts +103 -0
  24. package/src/agents/vendor/shapes.ts +41 -0
  25. package/src/agents/vendor/ticker.ts +67 -0
  26. package/src/agents/vendor/types.ts +261 -0
  27. package/src/agents/vendor/wear.ts +1699 -0
  28. package/src/ai/ai-button/AiButton.svelte +86 -0
  29. package/src/ai/ai-button/index.ts +4 -0
  30. package/src/ai/confirmation/Confirmation.svelte +54 -0
  31. package/src/ai/confirmation/ConfirmationAccepted.svelte +23 -0
  32. package/src/ai/confirmation/ConfirmationAction.svelte +53 -0
  33. package/src/ai/confirmation/ConfirmationActions.svelte +24 -0
  34. package/src/ai/confirmation/ConfirmationFailed.svelte +23 -0
  35. package/src/ai/confirmation/ConfirmationRejected.svelte +23 -0
  36. package/src/ai/confirmation/ConfirmationRequest.svelte +25 -0
  37. package/src/ai/confirmation/ConfirmationTitle.svelte +25 -0
  38. package/src/ai/confirmation/confirmation-context.svelte.ts +22 -0
  39. package/src/ai/confirmation/index.ts +50 -0
  40. package/src/ai/generation-progress/GenerationProgress.svelte +354 -0
  41. package/src/ai/generation-progress/index.ts +7 -0
  42. package/src/ai/index.ts +111 -0
  43. package/src/ai/loading-state/PixelLoader.svelte +138 -0
  44. package/src/ai/loading-state/index.ts +5 -0
  45. package/src/ai/prompt-input/PromptInput.svelte +56 -0
  46. package/src/ai/prompt-input/PromptInputBody.svelte +19 -0
  47. package/src/ai/prompt-input/PromptInputSubmit.svelte +79 -0
  48. package/src/ai/prompt-input/PromptInputTextarea.svelte +74 -0
  49. package/src/ai/prompt-input/PromptInputToolbar.svelte +19 -0
  50. package/src/ai/prompt-input/index.ts +34 -0
  51. package/src/ai/reasoning/Reasoning.svelte +50 -0
  52. package/src/ai/reasoning/ReasoningContent.svelte +27 -0
  53. package/src/ai/reasoning/ReasoningTrigger.svelte +48 -0
  54. package/src/ai/reasoning/index.ts +22 -0
  55. package/src/ai/reasoning/reasoning-context.svelte.ts +20 -0
  56. package/src/ai/response/Response.css +32 -0
  57. package/src/ai/response/Response.svelte +130 -0
  58. package/src/ai/response/index.ts +5 -0
  59. package/src/ai/suggestion/Suggestion.svelte +43 -0
  60. package/src/ai/suggestion/Suggestions.svelte +25 -0
  61. package/src/ai/suggestion/index.ts +14 -0
  62. package/src/ai/thinking-dots/ThinkingDots.svelte +42 -0
  63. package/src/ai/thinking-dots/index.ts +5 -0
  64. package/src/ai/typing-dots/TypingDots.css +39 -0
  65. package/src/ai/typing-dots/TypingDots.svelte +27 -0
  66. package/src/ai/typing-dots/index.ts +10 -0
  67. package/src/ai/voice-waveform/VoiceWaveform.css +40 -0
  68. package/src/ai/voice-waveform/VoiceWaveform.svelte +46 -0
  69. package/src/ai/voice-waveform/index.ts +5 -0
  70. package/src/ambient.d.ts +4 -0
  71. package/src/animations/README.md +84 -0
  72. package/src/animations/avatar-group-hover.css +47 -0
  73. package/src/animations/card-tilt.css +74 -0
  74. package/src/animations/digit-pop-in.css +78 -0
  75. package/src/animations/dropdown.css +121 -0
  76. package/src/animations/index.css +23 -0
  77. package/src/animations/input-clear-dissolve.css +86 -0
  78. package/src/animations/input-shake.css +114 -0
  79. package/src/animations/learn-more-hover.css +48 -0
  80. package/src/animations/like-button.css +93 -0
  81. package/src/animations/modal.css +75 -0
  82. package/src/animations/page-side-by-side.css +63 -0
  83. package/src/animations/plus-menu-morph.css +97 -0
  84. package/src/animations/resize.css +20 -0
  85. package/src/animations/shimmer-text.css +72 -0
  86. package/src/animations/spinning-counter.css +52 -0
  87. package/src/animations/success-check.css +120 -0
  88. package/src/animations/text-swap.css +40 -0
  89. package/src/animations/text-swap.ts +40 -0
  90. package/src/animations/thinking-states.css +65 -0
  91. package/src/animations/upstream-coverage.test.ts +65 -0
  92. package/src/components/copy/clipboard.test.ts +206 -0
  93. package/src/components/copy/clipboard.ts +49 -0
  94. package/src/components/copy/copied.svelte.ts +39 -0
  95. package/src/components/copy/copy-button.svelte +175 -0
  96. package/src/components/copy/copy-button.test.ts +110 -0
  97. package/src/components/copy/index.ts +3 -0
  98. package/src/components/data-table/data-table.test.ts +134 -0
  99. package/src/components/data-table/data-table.ts +77 -0
  100. package/src/components/data-table/index.ts +20 -0
  101. package/src/components/data-table/infinite-scroll.svelte +69 -0
  102. package/src/components/data-table/pagination.svelte +62 -0
  103. package/src/components/data-table/row-arrow.svelte +28 -0
  104. package/src/components/data-table/row-context-menu.svelte +106 -0
  105. package/src/components/data-table/row-context-menu.test.ts +18 -0
  106. package/src/components/data-table/sortable-head.svelte +56 -0
  107. package/src/components/data-table/table-skeleton.svelte +83 -0
  108. package/src/components/hold-to-confirm/hold-to-confirm.svelte +232 -0
  109. package/src/components/hold-to-confirm/index.ts +1 -0
  110. package/src/components/icon/icon.svelte +23 -0
  111. package/src/components/icon/index.ts +1 -0
  112. package/src/components/language-flag/index.ts +1 -0
  113. package/src/components/language-flag/language-flag.svelte +60 -0
  114. package/src/components/list-page/detail-empty.svelte +50 -0
  115. package/src/components/list-page/detail-header.svelte +107 -0
  116. package/src/components/list-page/detail-panel.svelte +90 -0
  117. package/src/components/list-page/detail-row.svelte +36 -0
  118. package/src/components/list-page/detail-stack.svelte +33 -0
  119. package/src/components/list-page/empty-state.svelte +91 -0
  120. package/src/components/list-page/filter-item.svelte +49 -0
  121. package/src/components/list-page/filter-popover.svelte +88 -0
  122. package/src/components/list-page/filter-section.ts +12 -0
  123. package/src/components/list-page/grouped-list.svelte +116 -0
  124. package/src/components/list-page/index.ts +28 -0
  125. package/src/components/list-page/list-page-shell.svelte +195 -0
  126. package/src/components/list-page/list-table.ts +19 -0
  127. package/src/components/list-page/master-detail.svelte +206 -0
  128. package/src/components/list-page/master-detail.test.ts +37 -0
  129. package/src/components/list-page/notice-bar.svelte +68 -0
  130. package/src/components/list-page/prev-next.svelte +104 -0
  131. package/src/components/list-page/queue-rail.ts +25 -0
  132. package/src/components/list-page/rail-body.svelte +29 -0
  133. package/src/components/list-page/rail-empty.svelte +51 -0
  134. package/src/components/list-page/rail-head.svelte +49 -0
  135. package/src/components/list-page/rail-row.svelte +163 -0
  136. package/src/components/list-page/section-host.ts +24 -0
  137. package/src/components/list-page/section-label.svelte +39 -0
  138. package/src/components/list-page/step.test.ts +21 -0
  139. package/src/components/list-page/step.ts +10 -0
  140. package/src/components/list-page/toolbar-search.svelte +63 -0
  141. package/src/components/list-page/toolbar-trigger.ts +23 -0
  142. package/src/components/list-page/types.ts +1 -0
  143. package/src/components/locale-switch/index.ts +1 -0
  144. package/src/components/locale-switch/locale-switch.svelte +59 -0
  145. package/src/components/mark/index.ts +1 -0
  146. package/src/components/mark/mark.svelte +70 -0
  147. package/src/components/open-in/index.ts +6 -0
  148. package/src/components/open-in/open-in.svelte +106 -0
  149. package/src/components/picker/index.ts +4 -0
  150. package/src/components/picker/mark-picker.svelte +84 -0
  151. package/src/components/picker/picker.svelte +143 -0
  152. package/src/components/picker/trigger.ts +42 -0
  153. package/src/components/picker/types.ts +26 -0
  154. package/src/components/segmented/animated-tabs.svelte +175 -0
  155. package/src/components/segmented/collapse.test.ts +49 -0
  156. package/src/components/segmented/collapse.ts +39 -0
  157. package/src/components/segmented/index.ts +41 -0
  158. package/src/components/segmented/section-runs.svelte +79 -0
  159. package/src/components/segmented/segment.svelte +106 -0
  160. package/src/components/segmented/segmented-filter.svelte +125 -0
  161. package/src/components/segmented/segmented-nav.svelte +82 -0
  162. package/src/components/segmented/segmented-overflow.svelte +85 -0
  163. package/src/components/segmented/segmented-track.svelte +181 -0
  164. package/src/components/segmented/segmented.test.ts +20 -0
  165. package/src/components/segmented/segmented.ts +80 -0
  166. package/src/components/star-rating-input/index.ts +9 -0
  167. package/src/components/star-rating-input/star-rating-input.svelte +256 -0
  168. package/src/components/svg/index.ts +1 -0
  169. package/src/components/svg/svg.svelte +9 -0
  170. package/src/design/index.css +270 -0
  171. package/src/design/polish.css +159 -0
  172. package/src/effects/animated-beam/AnimatedBeam.svelte +132 -0
  173. package/src/effects/animated-beam/diagrams/BeamSvg.svelte +91 -0
  174. package/src/effects/animated-beam/index.ts +2 -0
  175. package/src/effects/animated-beam/path-calculator.svelte.ts +70 -0
  176. package/src/effects/animated-beam/types.ts +23 -0
  177. package/src/effects/border-beam/BorderBeam.svelte +223 -0
  178. package/src/effects/border-beam/css.test.ts +46 -0
  179. package/src/effects/border-beam/css.ts +574 -0
  180. package/src/effects/border-beam/presets.ts +699 -0
  181. package/src/effects/border-beam/register-properties.test.ts +74 -0
  182. package/src/effects/border-beam/register-properties.ts +73 -0
  183. package/src/effects/border-beam/types.ts +38 -0
  184. package/src/effects/image-comparison/ImageComparison.css +100 -0
  185. package/src/effects/image-comparison/ImageComparison.svelte +209 -0
  186. package/src/effects/image-comparison/compare.test.ts +17 -0
  187. package/src/effects/image-comparison/compare.ts +5 -0
  188. package/src/effects/image-reveal/ImageReveal.css +10 -0
  189. package/src/effects/image-reveal/ImageReveal.svelte +357 -0
  190. package/src/effects/image-reveal/index.ts +2 -0
  191. package/src/effects/image-reveal/types.ts +35 -0
  192. package/src/effects/interactive-hover-button/InteractiveHoverButton.svelte +338 -0
  193. package/src/effects/magic-card/MagicCard.css +47 -0
  194. package/src/effects/magic-card/MagicCard.svelte +57 -0
  195. package/src/effects/magnetic/magnetic.ts +81 -0
  196. package/src/effects/marquee/Marquee.css +78 -0
  197. package/src/effects/marquee/Marquee.svelte +160 -0
  198. package/src/effects/progressive-blur/ProgressiveBlur.css +9 -0
  199. package/src/effects/progressive-blur/ProgressiveBlur.svelte +63 -0
  200. package/src/effects/reveal/AnimatedGroup.svelte +101 -0
  201. package/src/effects/reveal/InView.svelte +77 -0
  202. package/src/effects/reveal/TextEffect.svelte +142 -0
  203. package/src/effects/reveal/index.ts +11 -0
  204. package/src/effects/reveal/observe.test.ts +60 -0
  205. package/src/effects/reveal/observe.ts +65 -0
  206. package/src/effects/reveal/reveal.css +141 -0
  207. package/src/effects/reveal/types.ts +32 -0
  208. package/src/effects/shader-gradient/ShaderGradient.svelte +227 -0
  209. package/src/effects/shader-gradient/color.ts +44 -0
  210. package/src/effects/shader-gradient/index.ts +5 -0
  211. package/src/effects/shader-gradient/renderer.ts +456 -0
  212. package/src/effects/shader-gradient/shaders.ts +324 -0
  213. package/src/effects/shader-gradient/types.ts +68 -0
  214. package/src/effects/spotlight/Spotlight.css +14 -0
  215. package/src/effects/spotlight/Spotlight.svelte +61 -0
  216. package/src/effects/theme-toggle/ThemeToggle.css +214 -0
  217. package/src/effects/theme-toggle/ThemeToggle.svelte +126 -0
  218. package/src/gallery.test.ts +52 -0
  219. package/src/icons/TradeIcon.svelte +16 -0
  220. package/src/icons/apple-symbol-exports.ts +135 -0
  221. package/src/icons/sf-symbols.ts +527 -0
  222. package/src/icons/trades.ts +89 -0
  223. package/src/index.ts +53 -0
  224. package/src/lib/arrive.ts +26 -0
  225. package/src/lib/icon-types.ts +17 -0
  226. package/src/lib/layout.ts +8 -0
  227. package/src/lib/panel.ts +21 -0
  228. package/src/lib/sliding-pill.ts +68 -0
  229. package/src/lib/theme-transition.ts +79 -0
  230. package/src/lib/tone.ts +48 -0
  231. package/src/shadcn/accordion/accordion-content.svelte +22 -0
  232. package/src/shadcn/accordion/accordion-item.svelte +17 -0
  233. package/src/shadcn/accordion/accordion-trigger.svelte +44 -0
  234. package/src/shadcn/accordion/accordion.svelte +19 -0
  235. package/src/shadcn/accordion/index.ts +16 -0
  236. package/src/shadcn/alert/alert-description.svelte +23 -0
  237. package/src/shadcn/alert/alert-title.svelte +20 -0
  238. package/src/shadcn/alert/alert.svelte +46 -0
  239. package/src/shadcn/alert/index.ts +14 -0
  240. package/src/shadcn/alert-dialog/alert-dialog-action.svelte +18 -0
  241. package/src/shadcn/alert-dialog/alert-dialog-cancel.svelte +18 -0
  242. package/src/shadcn/alert-dialog/alert-dialog-content.svelte +29 -0
  243. package/src/shadcn/alert-dialog/alert-dialog-description.svelte +17 -0
  244. package/src/shadcn/alert-dialog/alert-dialog-footer.svelte +20 -0
  245. package/src/shadcn/alert-dialog/alert-dialog-header.svelte +20 -0
  246. package/src/shadcn/alert-dialog/alert-dialog-overlay.svelte +17 -0
  247. package/src/shadcn/alert-dialog/alert-dialog-portal.svelte +7 -0
  248. package/src/shadcn/alert-dialog/alert-dialog-title.svelte +17 -0
  249. package/src/shadcn/alert-dialog/alert-dialog-trigger.svelte +7 -0
  250. package/src/shadcn/alert-dialog/alert-dialog.svelte +7 -0
  251. package/src/shadcn/alert-dialog/index.ts +37 -0
  252. package/src/shadcn/attachment/attachment-action.svelte +23 -0
  253. package/src/shadcn/attachment/attachment-actions.svelte +23 -0
  254. package/src/shadcn/attachment/attachment-content.svelte +23 -0
  255. package/src/shadcn/attachment/attachment-description.svelte +23 -0
  256. package/src/shadcn/attachment/attachment-group.svelte +23 -0
  257. package/src/shadcn/attachment/attachment-media.svelte +44 -0
  258. package/src/shadcn/attachment/attachment-title.svelte +23 -0
  259. package/src/shadcn/attachment/attachment-trigger.svelte +29 -0
  260. package/src/shadcn/attachment/attachment.svelte +55 -0
  261. package/src/shadcn/attachment/index.ts +40 -0
  262. package/src/shadcn/avatar/avatar-badge.svelte +26 -0
  263. package/src/shadcn/avatar/avatar-fallback.svelte +20 -0
  264. package/src/shadcn/avatar/avatar-group-count.svelte +23 -0
  265. package/src/shadcn/avatar/avatar-group.svelte +23 -0
  266. package/src/shadcn/avatar/avatar-image.svelte +17 -0
  267. package/src/shadcn/avatar/avatar.svelte +26 -0
  268. package/src/shadcn/avatar/index.ts +22 -0
  269. package/src/shadcn/badge/badge.svelte +54 -0
  270. package/src/shadcn/badge/index.ts +2 -0
  271. package/src/shadcn/breadcrumb/breadcrumb-ellipsis.svelte +23 -0
  272. package/src/shadcn/breadcrumb/breadcrumb-item.svelte +20 -0
  273. package/src/shadcn/breadcrumb/breadcrumb-link.svelte +31 -0
  274. package/src/shadcn/breadcrumb/breadcrumb-list.svelte +23 -0
  275. package/src/shadcn/breadcrumb/breadcrumb-page.svelte +23 -0
  276. package/src/shadcn/breadcrumb/breadcrumb-separator.svelte +27 -0
  277. package/src/shadcn/breadcrumb/breadcrumb.svelte +21 -0
  278. package/src/shadcn/breadcrumb/index.ts +25 -0
  279. package/src/shadcn/bubble/bubble-content.svelte +31 -0
  280. package/src/shadcn/bubble/bubble-group.svelte +20 -0
  281. package/src/shadcn/bubble/bubble-reactions.svelte +52 -0
  282. package/src/shadcn/bubble/bubble.svelte +58 -0
  283. package/src/shadcn/bubble/index.ts +25 -0
  284. package/src/shadcn/button/button.svelte +121 -0
  285. package/src/shadcn/button/index.ts +17 -0
  286. package/src/shadcn/calendar/calendar-caption.svelte +76 -0
  287. package/src/shadcn/calendar/calendar-cell.svelte +19 -0
  288. package/src/shadcn/calendar/calendar-day.svelte +35 -0
  289. package/src/shadcn/calendar/calendar-grid-body.svelte +12 -0
  290. package/src/shadcn/calendar/calendar-grid-head.svelte +12 -0
  291. package/src/shadcn/calendar/calendar-grid-row.svelte +12 -0
  292. package/src/shadcn/calendar/calendar-grid.svelte +16 -0
  293. package/src/shadcn/calendar/calendar-head-cell.svelte +19 -0
  294. package/src/shadcn/calendar/calendar-header.svelte +19 -0
  295. package/src/shadcn/calendar/calendar-heading.svelte +16 -0
  296. package/src/shadcn/calendar/calendar-month-select.svelte +44 -0
  297. package/src/shadcn/calendar/calendar-month.svelte +15 -0
  298. package/src/shadcn/calendar/calendar-months.svelte +19 -0
  299. package/src/shadcn/calendar/calendar-nav.svelte +19 -0
  300. package/src/shadcn/calendar/calendar-next-button.svelte +31 -0
  301. package/src/shadcn/calendar/calendar-prev-button.svelte +31 -0
  302. package/src/shadcn/calendar/calendar-year-select.svelte +43 -0
  303. package/src/shadcn/calendar/calendar.svelte +124 -0
  304. package/src/shadcn/calendar/index.ts +40 -0
  305. package/src/shadcn/card/card-action.svelte +23 -0
  306. package/src/shadcn/card/card-content.svelte +20 -0
  307. package/src/shadcn/card/card-description.svelte +20 -0
  308. package/src/shadcn/card/card-footer.svelte +23 -0
  309. package/src/shadcn/card/card-header.svelte +23 -0
  310. package/src/shadcn/card/card-title.svelte +29 -0
  311. package/src/shadcn/card/card.svelte +25 -0
  312. package/src/shadcn/card/index.ts +25 -0
  313. package/src/shadcn/checkbox/checkbox.svelte +38 -0
  314. package/src/shadcn/checkbox/index.ts +6 -0
  315. package/src/shadcn/code-block/code-block-actions.svelte +23 -0
  316. package/src/shadcn/code-block/code-block-content.svelte +55 -0
  317. package/src/shadcn/code-block/code-block-copy-button.svelte +10 -0
  318. package/src/shadcn/code-block/code-block-footer.svelte +20 -0
  319. package/src/shadcn/code-block/code-block-header.svelte +23 -0
  320. package/src/shadcn/code-block/code-block-line.svelte +71 -0
  321. package/src/shadcn/code-block/code-block-title.svelte +23 -0
  322. package/src/shadcn/code-block/code-block.svelte +47 -0
  323. package/src/shadcn/code-block/index.ts +42 -0
  324. package/src/shadcn/collapsible/collapsible-content.svelte +7 -0
  325. package/src/shadcn/collapsible/collapsible-trigger.svelte +7 -0
  326. package/src/shadcn/collapsible/collapsible.svelte +11 -0
  327. package/src/shadcn/collapsible/index.ts +13 -0
  328. package/src/shadcn/command/command-dialog.svelte +66 -0
  329. package/src/shadcn/command/command-empty.svelte +17 -0
  330. package/src/shadcn/command/command-group.svelte +40 -0
  331. package/src/shadcn/command/command-input.svelte +64 -0
  332. package/src/shadcn/command/command-item.svelte +37 -0
  333. package/src/shadcn/command/command-link-item.svelte +20 -0
  334. package/src/shadcn/command/command-list.svelte +20 -0
  335. package/src/shadcn/command/command-loading.svelte +7 -0
  336. package/src/shadcn/command/command-separator.svelte +17 -0
  337. package/src/shadcn/command/command-shortcut.svelte +23 -0
  338. package/src/shadcn/command/command.svelte +28 -0
  339. package/src/shadcn/command/index.ts +40 -0
  340. package/src/shadcn/context-menu/context-menu-checkbox-item.svelte +41 -0
  341. package/src/shadcn/context-menu/context-menu-content.svelte +28 -0
  342. package/src/shadcn/context-menu/context-menu-group-heading.svelte +21 -0
  343. package/src/shadcn/context-menu/context-menu-group.svelte +7 -0
  344. package/src/shadcn/context-menu/context-menu-item.svelte +27 -0
  345. package/src/shadcn/context-menu/context-menu-label.svelte +27 -0
  346. package/src/shadcn/context-menu/context-menu-portal.svelte +7 -0
  347. package/src/shadcn/context-menu/context-menu-radio-group.svelte +16 -0
  348. package/src/shadcn/context-menu/context-menu-radio-item.svelte +35 -0
  349. package/src/shadcn/context-menu/context-menu-separator.svelte +17 -0
  350. package/src/shadcn/context-menu/context-menu-shortcut.svelte +23 -0
  351. package/src/shadcn/context-menu/context-menu-sub-content.svelte +25 -0
  352. package/src/shadcn/context-menu/context-menu-sub-trigger.svelte +29 -0
  353. package/src/shadcn/context-menu/context-menu-sub.svelte +7 -0
  354. package/src/shadcn/context-menu/context-menu-trigger.svelte +17 -0
  355. package/src/shadcn/context-menu/context-menu.svelte +7 -0
  356. package/src/shadcn/context-menu/index.ts +52 -0
  357. package/src/shadcn/dialog/dialog-close.svelte +11 -0
  358. package/src/shadcn/dialog/dialog-content.svelte +57 -0
  359. package/src/shadcn/dialog/dialog-description.svelte +20 -0
  360. package/src/shadcn/dialog/dialog-footer.svelte +32 -0
  361. package/src/shadcn/dialog/dialog-header.svelte +20 -0
  362. package/src/shadcn/dialog/dialog-overlay.svelte +20 -0
  363. package/src/shadcn/dialog/dialog-portal.svelte +7 -0
  364. package/src/shadcn/dialog/dialog-title.svelte +17 -0
  365. package/src/shadcn/dialog/dialog-trigger.svelte +11 -0
  366. package/src/shadcn/dialog/dialog.svelte +7 -0
  367. package/src/shadcn/dialog/index.ts +34 -0
  368. package/src/shadcn/dropdown-menu/dropdown-menu-checkbox-group.svelte +16 -0
  369. package/src/shadcn/dropdown-menu/dropdown-menu-checkbox-item.svelte +43 -0
  370. package/src/shadcn/dropdown-menu/dropdown-menu-content.svelte +31 -0
  371. package/src/shadcn/dropdown-menu/dropdown-menu-group-heading.svelte +22 -0
  372. package/src/shadcn/dropdown-menu/dropdown-menu-group.svelte +7 -0
  373. package/src/shadcn/dropdown-menu/dropdown-menu-item.svelte +29 -0
  374. package/src/shadcn/dropdown-menu/dropdown-menu-label.svelte +27 -0
  375. package/src/shadcn/dropdown-menu/dropdown-menu-portal.svelte +7 -0
  376. package/src/shadcn/dropdown-menu/dropdown-menu-radio-group.svelte +16 -0
  377. package/src/shadcn/dropdown-menu/dropdown-menu-radio-item.svelte +34 -0
  378. package/src/shadcn/dropdown-menu/dropdown-menu-separator.svelte +17 -0
  379. package/src/shadcn/dropdown-menu/dropdown-menu-shortcut.svelte +23 -0
  380. package/src/shadcn/dropdown-menu/dropdown-menu-sub-content.svelte +20 -0
  381. package/src/shadcn/dropdown-menu/dropdown-menu-sub-trigger.svelte +29 -0
  382. package/src/shadcn/dropdown-menu/dropdown-menu-sub.svelte +7 -0
  383. package/src/shadcn/dropdown-menu/dropdown-menu-trigger.svelte +7 -0
  384. package/src/shadcn/dropdown-menu/dropdown-menu.svelte +7 -0
  385. package/src/shadcn/dropdown-menu/index.ts +56 -0
  386. package/src/shadcn/dropdown-menu/menu-item.ts +43 -0
  387. package/src/shadcn/empty/empty-content.svelte +23 -0
  388. package/src/shadcn/empty/empty-description.svelte +23 -0
  389. package/src/shadcn/empty/empty-header.svelte +20 -0
  390. package/src/shadcn/empty/empty-media.svelte +41 -0
  391. package/src/shadcn/empty/empty-title.svelte +20 -0
  392. package/src/shadcn/empty/empty.svelte +23 -0
  393. package/src/shadcn/empty/index.ts +22 -0
  394. package/src/shadcn/field/field-content.svelte +20 -0
  395. package/src/shadcn/field/field-description.svelte +25 -0
  396. package/src/shadcn/field/field-error.svelte +58 -0
  397. package/src/shadcn/field/field-group.svelte +23 -0
  398. package/src/shadcn/field/field-label.svelte +26 -0
  399. package/src/shadcn/field/field-legend.svelte +29 -0
  400. package/src/shadcn/field/field-separator.svelte +35 -0
  401. package/src/shadcn/field/field-set.svelte +24 -0
  402. package/src/shadcn/field/field-title.svelte +23 -0
  403. package/src/shadcn/field/field.svelte +53 -0
  404. package/src/shadcn/field/index.ts +36 -0
  405. package/src/shadcn/field/simple-field.svelte +71 -0
  406. package/src/shadcn/field/simple-field.test.ts +47 -0
  407. package/src/shadcn/hooks/highlighter.ts +132 -0
  408. package/src/shadcn/hooks/is-mobile.svelte.ts +9 -0
  409. package/src/shadcn/hooks/use-highlighted-code.svelte.ts +98 -0
  410. package/src/shadcn/hover-card/hover-card-content.svelte +31 -0
  411. package/src/shadcn/hover-card/hover-card-portal.svelte +7 -0
  412. package/src/shadcn/hover-card/hover-card-trigger.svelte +7 -0
  413. package/src/shadcn/hover-card/hover-card.svelte +7 -0
  414. package/src/shadcn/hover-card/index.ts +15 -0
  415. package/src/shadcn/input/index.ts +9 -0
  416. package/src/shadcn/input/input.svelte +48 -0
  417. package/src/shadcn/input/secret-input.svelte +75 -0
  418. package/src/shadcn/input-otp/index.ts +15 -0
  419. package/src/shadcn/input-otp/input-otp-group.svelte +20 -0
  420. package/src/shadcn/input-otp/input-otp-separator.svelte +25 -0
  421. package/src/shadcn/input-otp/input-otp-slot.svelte +26 -0
  422. package/src/shadcn/input-otp/input-otp.svelte +22 -0
  423. package/src/shadcn/kbd/index.ts +10 -0
  424. package/src/shadcn/kbd/kbd-group.svelte +20 -0
  425. package/src/shadcn/kbd/kbd.svelte +23 -0
  426. package/src/shadcn/label/index.ts +7 -0
  427. package/src/shadcn/label/label.svelte +20 -0
  428. package/src/shadcn/marker/index.ts +15 -0
  429. package/src/shadcn/marker/marker-content.svelte +23 -0
  430. package/src/shadcn/marker/marker-icon.svelte +21 -0
  431. package/src/shadcn/marker/marker.svelte +52 -0
  432. package/src/shadcn/message/index.ts +22 -0
  433. package/src/shadcn/message/message-avatar.svelte +23 -0
  434. package/src/shadcn/message/message-content.svelte +23 -0
  435. package/src/shadcn/message/message-footer.svelte +23 -0
  436. package/src/shadcn/message/message-group.svelte +20 -0
  437. package/src/shadcn/message/message-header.svelte +23 -0
  438. package/src/shadcn/message/message.svelte +27 -0
  439. package/src/shadcn/message-scroller/index.ts +28 -0
  440. package/src/shadcn/message-scroller/message-scroller-button.svelte +52 -0
  441. package/src/shadcn/message-scroller/message-scroller-content.svelte +17 -0
  442. package/src/shadcn/message-scroller/message-scroller-item.svelte +22 -0
  443. package/src/shadcn/message-scroller/message-scroller-provider.svelte +7 -0
  444. package/src/shadcn/message-scroller/message-scroller-viewport.svelte +20 -0
  445. package/src/shadcn/message-scroller/message-scroller.svelte +20 -0
  446. package/src/shadcn/popover/index.ts +28 -0
  447. package/src/shadcn/popover/popover-close.svelte +7 -0
  448. package/src/shadcn/popover/popover-content.svelte +38 -0
  449. package/src/shadcn/popover/popover-description.svelte +20 -0
  450. package/src/shadcn/popover/popover-header.svelte +20 -0
  451. package/src/shadcn/popover/popover-portal.svelte +7 -0
  452. package/src/shadcn/popover/popover-title.svelte +15 -0
  453. package/src/shadcn/popover/popover-trigger.svelte +17 -0
  454. package/src/shadcn/popover/popover.svelte +7 -0
  455. package/src/shadcn/progress/index.ts +7 -0
  456. package/src/shadcn/progress/progress.svelte +30 -0
  457. package/src/shadcn/radio-group/index.ts +10 -0
  458. package/src/shadcn/radio-group/radio-group-item.svelte +32 -0
  459. package/src/shadcn/radio-group/radio-group.svelte +19 -0
  460. package/src/shadcn/scroll-area/index.ts +10 -0
  461. package/src/shadcn/scroll-area/scroll-area-scrollbar.svelte +30 -0
  462. package/src/shadcn/scroll-area/scroll-area.svelte +43 -0
  463. package/src/shadcn/select/index.ts +37 -0
  464. package/src/shadcn/select/select-content.svelte +45 -0
  465. package/src/shadcn/select/select-group-heading.svelte +21 -0
  466. package/src/shadcn/select/select-group.svelte +17 -0
  467. package/src/shadcn/select/select-item.svelte +38 -0
  468. package/src/shadcn/select/select-label.svelte +20 -0
  469. package/src/shadcn/select/select-portal.svelte +7 -0
  470. package/src/shadcn/select/select-scroll-down-button.svelte +23 -0
  471. package/src/shadcn/select/select-scroll-up-button.svelte +23 -0
  472. package/src/shadcn/select/select-separator.svelte +18 -0
  473. package/src/shadcn/select/select-trigger.svelte +33 -0
  474. package/src/shadcn/select/select.svelte +11 -0
  475. package/src/shadcn/separator/index.ts +7 -0
  476. package/src/shadcn/separator/separator.svelte +23 -0
  477. package/src/shadcn/sheet/index.ts +34 -0
  478. package/src/shadcn/sheet/sheet-close.svelte +7 -0
  479. package/src/shadcn/sheet/sheet-content.svelte +73 -0
  480. package/src/shadcn/sheet/sheet-description.svelte +17 -0
  481. package/src/shadcn/sheet/sheet-footer.svelte +20 -0
  482. package/src/shadcn/sheet/sheet-header.svelte +20 -0
  483. package/src/shadcn/sheet/sheet-overlay.svelte +20 -0
  484. package/src/shadcn/sheet/sheet-portal.svelte +7 -0
  485. package/src/shadcn/sheet/sheet-title.svelte +17 -0
  486. package/src/shadcn/sheet/sheet-trigger.svelte +7 -0
  487. package/src/shadcn/sheet/sheet.css +48 -0
  488. package/src/shadcn/sheet/sheet.svelte +7 -0
  489. package/src/shadcn/sidebar/constants.ts +6 -0
  490. package/src/shadcn/sidebar/context.svelte.ts +81 -0
  491. package/src/shadcn/sidebar/index.ts +75 -0
  492. package/src/shadcn/sidebar/sidebar-content.svelte +24 -0
  493. package/src/shadcn/sidebar/sidebar-footer.svelte +21 -0
  494. package/src/shadcn/sidebar/sidebar-group-action.svelte +33 -0
  495. package/src/shadcn/sidebar/sidebar-group-content.svelte +21 -0
  496. package/src/shadcn/sidebar/sidebar-group-label.svelte +33 -0
  497. package/src/shadcn/sidebar/sidebar-group.svelte +21 -0
  498. package/src/shadcn/sidebar/sidebar-header.svelte +21 -0
  499. package/src/shadcn/sidebar/sidebar-input.svelte +21 -0
  500. package/src/shadcn/sidebar/sidebar-inset.svelte +23 -0
  501. package/src/shadcn/sidebar/sidebar-menu-action.svelte +37 -0
  502. package/src/shadcn/sidebar/sidebar-menu-badge.svelte +24 -0
  503. package/src/shadcn/sidebar/sidebar-menu-button.svelte +103 -0
  504. package/src/shadcn/sidebar/sidebar-menu-item.svelte +21 -0
  505. package/src/shadcn/sidebar/sidebar-menu-skeleton.svelte +36 -0
  506. package/src/shadcn/sidebar/sidebar-menu-sub-button.svelte +39 -0
  507. package/src/shadcn/sidebar/sidebar-menu-sub-item.svelte +21 -0
  508. package/src/shadcn/sidebar/sidebar-menu-sub.svelte +24 -0
  509. package/src/shadcn/sidebar/sidebar-menu.svelte +21 -0
  510. package/src/shadcn/sidebar/sidebar-provider.svelte +62 -0
  511. package/src/shadcn/sidebar/sidebar-rail.svelte +36 -0
  512. package/src/shadcn/sidebar/sidebar-separator.svelte +19 -0
  513. package/src/shadcn/sidebar/sidebar-trigger.svelte +37 -0
  514. package/src/shadcn/sidebar/sidebar.svelte +109 -0
  515. package/src/shadcn/skeleton/index.ts +7 -0
  516. package/src/shadcn/skeleton/skeleton.svelte +17 -0
  517. package/src/shadcn/slider/index.ts +7 -0
  518. package/src/shadcn/slider/slider.svelte +52 -0
  519. package/src/shadcn/sonner/index.ts +1 -0
  520. package/src/shadcn/sonner/sonner.svelte +31 -0
  521. package/src/shadcn/spinner/index.ts +1 -0
  522. package/src/shadcn/spinner/spinner.svelte +26 -0
  523. package/src/shadcn/switch/index.ts +7 -0
  524. package/src/shadcn/switch/switch.svelte +31 -0
  525. package/src/shadcn/table/index.ts +28 -0
  526. package/src/shadcn/table/table-body.svelte +20 -0
  527. package/src/shadcn/table/table-caption.svelte +20 -0
  528. package/src/shadcn/table/table-cell.svelte +20 -0
  529. package/src/shadcn/table/table-footer.svelte +20 -0
  530. package/src/shadcn/table/table-head.svelte +23 -0
  531. package/src/shadcn/table/table-header.svelte +20 -0
  532. package/src/shadcn/table/table-row.svelte +23 -0
  533. package/src/shadcn/table/table.svelte +25 -0
  534. package/src/shadcn/tabs/index.ts +16 -0
  535. package/src/shadcn/tabs/tabs-content.svelte +17 -0
  536. package/src/shadcn/tabs/tabs-list.svelte +36 -0
  537. package/src/shadcn/tabs/tabs-trigger.svelte +20 -0
  538. package/src/shadcn/tabs/tabs.svelte +19 -0
  539. package/src/shadcn/textarea/index.ts +7 -0
  540. package/src/shadcn/textarea/textarea.svelte +23 -0
  541. package/src/shadcn/toggle/index.ts +13 -0
  542. package/src/shadcn/toggle/toggle.svelte +53 -0
  543. package/src/shadcn/toggle-group/index.ts +10 -0
  544. package/src/shadcn/toggle-group/toggle-group-item.svelte +35 -0
  545. package/src/shadcn/toggle-group/toggle-group.svelte +66 -0
  546. package/src/shadcn/tooltip/context.ts +16 -0
  547. package/src/shadcn/tooltip/index.ts +19 -0
  548. package/src/shadcn/tooltip/tooltip-content.svelte +38 -0
  549. package/src/shadcn/tooltip/tooltip-portal.svelte +7 -0
  550. package/src/shadcn/tooltip/tooltip-provider.svelte +16 -0
  551. package/src/shadcn/tooltip/tooltip-trigger.svelte +7 -0
  552. package/src/shadcn/tooltip/tooltip.svelte +19 -0
  553. package/src/shadcn/trace/index.ts +29 -0
  554. package/src/shadcn/trace/trace-collapsible-content.svelte +29 -0
  555. package/src/shadcn/trace/trace-collapsible-trigger.svelte +29 -0
  556. package/src/shadcn/trace/trace-collapsible.svelte +20 -0
  557. package/src/shadcn/trace/trace-description.svelte +20 -0
  558. package/src/shadcn/trace/trace-icon.svelte +24 -0
  559. package/src/shadcn/trace/trace-line.svelte +31 -0
  560. package/src/shadcn/trace/trace-title.svelte +20 -0
  561. package/src/shadcn/trace/trace.svelte +23 -0
  562. package/src/shadcn/utilities.css +549 -0
  563. package/src/test-setup.ts +34 -0
  564. package/src/tokens.css +993 -0
@@ -0,0 +1,79 @@
1
+ <script lang="ts" module>
2
+ import type { Snippet } from "svelte";
3
+ import type { ButtonProps, ButtonSize, ButtonVariant } from "../../shadcn/button/index.js";
4
+
5
+ export type PromptInputStatus = "ready" | "submitted" | "streaming" | "error";
6
+
7
+ export interface PromptInputSubmitProps extends Omit<ButtonProps, "type" | "onclick"> {
8
+ status?: PromptInputStatus;
9
+ onStop?: () => void;
10
+ onclick?: (event: MouseEvent) => void;
11
+ /** Accessible name while idle. Translate at the call site. */
12
+ submitLabel?: string;
13
+ /** Accessible name while generating, when a click stops the run. */
14
+ stopLabel?: string;
15
+ class?: string;
16
+ variant?: ButtonVariant;
17
+ size?: ButtonSize;
18
+ children?: Snippet;
19
+ }
20
+ </script>
21
+
22
+ <script lang="ts">
23
+ import { cn } from "@heyramzi/utils";
24
+ import { Button } from "../../shadcn/button/index.js";
25
+ import { Spinner } from "../../shadcn/spinner/index.js";
26
+ import SendIcon from "phosphor-svelte/lib/PaperPlaneRight";
27
+ import SquareIcon from "phosphor-svelte/lib/Square";
28
+ import XIcon from "phosphor-svelte/lib/X";
29
+
30
+ let {
31
+ status = "ready",
32
+ onStop,
33
+ onclick,
34
+ submitLabel = "Submit",
35
+ stopLabel = "Stop",
36
+ variant = "default",
37
+ size = "default",
38
+ icon = true,
39
+ class: className,
40
+ children,
41
+ ...rest
42
+ }: PromptInputSubmitProps = $props();
43
+
44
+ const isGenerating = $derived(status === "submitted" || status === "streaming");
45
+ const buttonType = $derived<"button" | "submit">(isGenerating ? "button" : "submit");
46
+
47
+ function handleClick(event: MouseEvent) {
48
+ if (isGenerating) {
49
+ event.preventDefault();
50
+ onStop?.();
51
+ return;
52
+ }
53
+ onclick?.(event);
54
+ }
55
+ </script>
56
+
57
+ <Button
58
+ {...rest}
59
+ {variant}
60
+ {size}
61
+ {icon}
62
+ type={buttonType}
63
+ data-prompt-input-submit
64
+ onclick={handleClick}
65
+ aria-label={isGenerating ? stopLabel : submitLabel}
66
+ class={cn("gap-1.5", className)}
67
+ >
68
+ {#if children}
69
+ {@render children()}
70
+ {:else if status === "submitted"}
71
+ <Spinner />
72
+ {:else if status === "streaming"}
73
+ <SquareIcon class="size-4" />
74
+ {:else if status === "error"}
75
+ <XIcon class="size-4" />
76
+ {:else}
77
+ <SendIcon class="size-4" />
78
+ {/if}
79
+ </Button>
@@ -0,0 +1,74 @@
1
+ <script lang="ts" module>
2
+ import type { HTMLTextareaAttributes } from "svelte/elements";
3
+
4
+ export interface PromptInputTextareaProps extends Omit<
5
+ HTMLTextareaAttributes,
6
+ "value" | "name" | "onkeydown"
7
+ > {
8
+ value?: string;
9
+ name?: string;
10
+ class?: string;
11
+ /** WHY: opt-out of "Enter submits, Shift+Enter newline" if the consumer
12
+ * prefers explicit Cmd/Ctrl+Enter only. */
13
+ enterSubmits?: boolean;
14
+ }
15
+ </script>
16
+
17
+ <script lang="ts">
18
+ import { cn } from "@heyramzi/utils";
19
+
20
+ let {
21
+ class: className,
22
+ value = $bindable(""),
23
+ name = "message",
24
+ placeholder = "Ask anything",
25
+ enterSubmits = true,
26
+ ...rest
27
+ }: PromptInputTextareaProps = $props();
28
+
29
+ function handleKeyDown(event: KeyboardEvent) {
30
+ // WHY: Cmd/Ctrl+Enter always submits regardless of `enterSubmits`. Power
31
+ // users expect this even when plain Enter inserts a newline.
32
+ if ((event.metaKey || event.ctrlKey) && event.key === "Enter") {
33
+ event.preventDefault();
34
+ requestSubmit(event);
35
+ return;
36
+ }
37
+
38
+ if (!enterSubmits) return;
39
+ if (event.key !== "Enter") return;
40
+ if (event.isComposing) return;
41
+ if (event.shiftKey) return;
42
+
43
+ event.preventDefault();
44
+ requestSubmit(event);
45
+ }
46
+
47
+ function requestSubmit(event: KeyboardEvent) {
48
+ const form = (event.currentTarget as HTMLTextAreaElement).form;
49
+ if (!form) return;
50
+ const submit =
51
+ form.querySelector<HTMLButtonElement>("[data-prompt-input-submit]") ??
52
+ form.querySelector<HTMLButtonElement>('button[type="submit"]');
53
+ if (submit?.disabled) return;
54
+ if (submit) {
55
+ form.requestSubmit(submit);
56
+ } else {
57
+ form.requestSubmit();
58
+ }
59
+ }
60
+ </script>
61
+
62
+ <textarea
63
+ class={cn(
64
+ "field-sizing-content max-h-48 min-h-10 w-full resize-none border-0 bg-transparent p-3 text-sm outline-none",
65
+ "placeholder:text-[color:var(--muted-foreground,inherit)]",
66
+ "focus-visible:ring-0",
67
+ className,
68
+ )}
69
+ {name}
70
+ bind:value
71
+ onkeydown={handleKeyDown}
72
+ {placeholder}
73
+ {...rest}
74
+ ></textarea>
@@ -0,0 +1,19 @@
1
+ <script lang="ts" module>
2
+ import type { Snippet } from "svelte";
3
+ import type { HTMLAttributes } from "svelte/elements";
4
+
5
+ export interface PromptInputToolbarProps extends HTMLAttributes<HTMLDivElement> {
6
+ class?: string;
7
+ children?: Snippet;
8
+ }
9
+ </script>
10
+
11
+ <script lang="ts">
12
+ import { cn } from "@heyramzi/utils";
13
+
14
+ let { class: className, children, ...rest }: PromptInputToolbarProps = $props();
15
+ </script>
16
+
17
+ <div class={cn("flex items-center justify-between gap-2 px-2 py-1.5", className)} {...rest}>
18
+ {@render children?.()}
19
+ </div>
@@ -0,0 +1,34 @@
1
+ import PromptInput from "./PromptInput.svelte";
2
+ import PromptInputBody from "./PromptInputBody.svelte";
3
+ import PromptInputToolbar from "./PromptInputToolbar.svelte";
4
+ import PromptInputTextarea from "./PromptInputTextarea.svelte";
5
+ import PromptInputSubmit from "./PromptInputSubmit.svelte";
6
+
7
+ import type { PromptInputProps } from "./PromptInput.svelte";
8
+ import type { PromptInputBodyProps } from "./PromptInputBody.svelte";
9
+ import type { PromptInputToolbarProps } from "./PromptInputToolbar.svelte";
10
+ import type { PromptInputTextareaProps } from "./PromptInputTextarea.svelte";
11
+ import type {
12
+ PromptInputSubmitProps,
13
+ PromptInputStatus,
14
+ } from "./PromptInputSubmit.svelte";
15
+
16
+ export {
17
+ PromptInput,
18
+ PromptInputBody,
19
+ PromptInputToolbar,
20
+ PromptInputTextarea,
21
+ PromptInputSubmit,
22
+ type PromptInputProps,
23
+ type PromptInputBodyProps,
24
+ type PromptInputToolbarProps,
25
+ type PromptInputTextareaProps,
26
+ type PromptInputSubmitProps,
27
+ type PromptInputStatus,
28
+ //
29
+ PromptInput as Root,
30
+ PromptInputBody as Body,
31
+ PromptInputToolbar as Toolbar,
32
+ PromptInputTextarea as Textarea,
33
+ PromptInputSubmit as Submit,
34
+ };
@@ -0,0 +1,50 @@
1
+ <script lang="ts" module>
2
+ import type { Snippet } from "svelte";
3
+ import type { Collapsible as CollapsiblePrimitive } from "bits-ui";
4
+
5
+ export interface ReasoningProps extends CollapsiblePrimitive.RootProps {
6
+ isStreaming?: boolean;
7
+ duration?: number;
8
+ children?: Snippet;
9
+ }
10
+ </script>
11
+
12
+ <script lang="ts">
13
+ import { untrack } from "svelte";
14
+ import { cn } from "@heyramzi/utils";
15
+ import { Collapsible } from "../../shadcn/collapsible/index.js";
16
+ import { setReasoningContext } from "./reasoning-context.svelte.js";
17
+
18
+ let {
19
+ isStreaming = false,
20
+ open = $bindable(false),
21
+ duration = 0,
22
+ class: className,
23
+ children,
24
+ ...rest
25
+ }: ReasoningProps = $props();
26
+
27
+ // WHY: child parts read streaming/duration through these getters, so $derived in
28
+ // the trigger reruns whenever the props change.
29
+ setReasoningContext({
30
+ get isStreaming() {
31
+ return isStreaming;
32
+ },
33
+ get duration() {
34
+ return duration;
35
+ },
36
+ });
37
+
38
+ // WHY: auto-open on stream start and auto-close on stream end, but only on the
39
+ // transition itself so a user who toggles mid-stream is left alone.
40
+ let prev = untrack(() => isStreaming);
41
+ $effect(() => {
42
+ if (isStreaming && !prev) open = true;
43
+ else if (!isStreaming && prev) open = false;
44
+ prev = isStreaming;
45
+ });
46
+ </script>
47
+
48
+ <Collapsible bind:open class={cn("text-sm", className)} {...rest}>
49
+ {@render children?.()}
50
+ </Collapsible>
@@ -0,0 +1,27 @@
1
+ <script lang="ts" module>
2
+ import type { Snippet } from "svelte";
3
+ import type { Collapsible as CollapsiblePrimitive } from "bits-ui";
4
+
5
+ export interface ReasoningContentProps extends CollapsiblePrimitive.ContentProps {
6
+ children?: Snippet;
7
+ }
8
+ </script>
9
+
10
+ <script lang="ts">
11
+ import { cn } from "@heyramzi/utils";
12
+ import { CollapsibleContent } from "../../shadcn/collapsible/index.js";
13
+
14
+ let { class: className, children, ...rest }: ReasoningContentProps = $props();
15
+ </script>
16
+
17
+ <CollapsibleContent
18
+ class={cn(
19
+ "mt-3 border-l-2 pl-3 text-sm leading-relaxed",
20
+ "border-[color:var(--border,rgba(0,0,0,0.1))] text-[color:var(--muted-foreground,#71717a)]",
21
+ "overflow-hidden data-[state=open]:animate-collapsible-down data-[state=closed]:animate-collapsible-up motion-reduce:animate-none",
22
+ className,
23
+ )}
24
+ {...rest}
25
+ >
26
+ {@render children?.()}
27
+ </CollapsibleContent>
@@ -0,0 +1,48 @@
1
+ <script lang="ts" module>
2
+ import type { Snippet } from "svelte";
3
+ import type { Collapsible as CollapsiblePrimitive } from "bits-ui";
4
+
5
+ export interface ReasoningTriggerProps extends CollapsiblePrimitive.TriggerProps {
6
+ children?: Snippet;
7
+ }
8
+ </script>
9
+
10
+ <script lang="ts">
11
+ import { cn } from "@heyramzi/utils";
12
+ import BrainIcon from "phosphor-svelte/lib/Brain";
13
+ import ChevronDownIcon from "phosphor-svelte/lib/CaretDown";
14
+ import { CollapsibleTrigger } from "../../shadcn/collapsible/index.js";
15
+ import { getReasoningContext } from "./reasoning-context.svelte.js";
16
+
17
+ let { class: className, children, ...rest }: ReasoningTriggerProps = $props();
18
+
19
+ const ctx = getReasoningContext();
20
+
21
+ const label = $derived(
22
+ ctx.isStreaming
23
+ ? "Thinking..."
24
+ : ctx.duration > 0
25
+ ? `Thought for ${ctx.duration}s`
26
+ : "Reasoning",
27
+ );
28
+ </script>
29
+
30
+ <CollapsibleTrigger
31
+ class={cn(
32
+ "group flex w-full items-center gap-2 text-left",
33
+ "text-sm text-[color:var(--muted-foreground,#71717a)]",
34
+ "transition-colors hover:text-[color:var(--foreground,#09090b)]",
35
+ className,
36
+ )}
37
+ {...rest}
38
+ >
39
+ <BrainIcon class={cn("size-4 shrink-0", ctx.isStreaming && "animate-pulse")} />
40
+ {#if children}
41
+ {@render children()}
42
+ {:else}
43
+ <span>{label}</span>
44
+ {/if}
45
+ <ChevronDownIcon
46
+ class="size-4 shrink-0 transition-transform group-data-[state=open]:rotate-180"
47
+ />
48
+ </CollapsibleTrigger>
@@ -0,0 +1,22 @@
1
+ import Reasoning from "./Reasoning.svelte";
2
+ import ReasoningTrigger from "./ReasoningTrigger.svelte";
3
+ import ReasoningContent from "./ReasoningContent.svelte";
4
+
5
+ import type { ReasoningProps } from "./Reasoning.svelte";
6
+ import type { ReasoningTriggerProps } from "./ReasoningTrigger.svelte";
7
+ import type { ReasoningContentProps } from "./ReasoningContent.svelte";
8
+ import type { ReasoningContextValue } from "./reasoning-context.svelte.js";
9
+
10
+ export {
11
+ Reasoning,
12
+ ReasoningTrigger,
13
+ ReasoningContent,
14
+ type ReasoningProps,
15
+ type ReasoningTriggerProps,
16
+ type ReasoningContentProps,
17
+ type ReasoningContextValue,
18
+ //
19
+ Reasoning as Root,
20
+ ReasoningTrigger as Trigger,
21
+ ReasoningContent as Content,
22
+ };
@@ -0,0 +1,20 @@
1
+ import { getContext, setContext } from "svelte";
2
+
3
+ const REASONING_CONTEXT_KEY = Symbol("reasoning-context");
4
+
5
+ export interface ReasoningContextValue {
6
+ isStreaming: boolean;
7
+ duration: number;
8
+ }
9
+
10
+ export function setReasoningContext(value: ReasoningContextValue) {
11
+ setContext(REASONING_CONTEXT_KEY, value);
12
+ }
13
+
14
+ export function getReasoningContext(): ReasoningContextValue {
15
+ const context = getContext<ReasoningContextValue>(REASONING_CONTEXT_KEY);
16
+ if (!context) {
17
+ throw new Error("Reasoning parts must be used inside a <Reasoning>.");
18
+ }
19
+ return context;
20
+ }
@@ -0,0 +1,32 @@
1
+ /* WHY: the caret has to attach to the end of marked's {@html} output, which is
2
+ never touched by Svelte's scoping, so the last direct child is reached with
3
+ :global() while the parent class stays component-scoped. */
4
+ .ai-response.is-streaming > :last-child::after {
5
+ content: "";
6
+ display: inline-block;
7
+ width: 0.5ch;
8
+ height: 1em;
9
+ margin-left: 0.1ch;
10
+ vertical-align: text-bottom;
11
+ border-radius: 1px;
12
+ background: currentColor;
13
+ animation: ai-response-caret 1s steps(1, end) infinite;
14
+ }
15
+
16
+ @keyframes ai-response-caret {
17
+ 0%,
18
+ 50% {
19
+ opacity: 1;
20
+ }
21
+ 50.01%,
22
+ 100% {
23
+ opacity: 0;
24
+ }
25
+ }
26
+
27
+ @media (prefers-reduced-motion: reduce) {
28
+ .ai-response.is-streaming > :last-child::after {
29
+ animation: none;
30
+ opacity: 0.7;
31
+ }
32
+ }
@@ -0,0 +1,130 @@
1
+ <script lang="ts" module>
2
+ // =========================
3
+ // IMPORTS
4
+ // =========================
5
+
6
+ import { Marked } from "marked";
7
+ import type { HTMLAttributes } from "svelte/elements";
8
+
9
+ // =========================
10
+ // TYPES
11
+ // =========================
12
+
13
+ export interface ResponseProps extends HTMLAttributes<HTMLDivElement> {
14
+ content: string;
15
+ /** Render a blinking caret after the content while tokens are still arriving. */
16
+ streaming?: boolean;
17
+ class?: string;
18
+ }
19
+
20
+ // =========================
21
+ // FUNCTIONS (module scope: one shared, hardened parser)
22
+ // =========================
23
+
24
+ // WHY: marked does not sanitize. Rendering model/tool output with {@html} is an
25
+
26
+ // XSS sink, so we ship a markdown-only renderer: raw HTML is escaped (never injected as elements) and link/image URLs are scheme-checked.
27
+
28
+ // Pure JS, so it runs identically on the server and the client with no extra dependency.
29
+ const SAFE_SCHEME = /^(?:https?:|mailto:|tel:)/i;
30
+
31
+ function escapeHtml(value: string): string {
32
+ return value
33
+ .replace(/&/g, "&amp;")
34
+ .replace(/</g, "&lt;")
35
+ .replace(/>/g, "&gt;")
36
+ .replace(/"/g, "&quot;");
37
+ }
38
+
39
+ function safeUrl(raw: string | null | undefined): string | null {
40
+ if (!raw) return null;
41
+ // WHY: browsers drop tabs, newlines and control bytes from a URL, so "java\tscript:" runs as javascript:.
42
+ const href = [...raw]
43
+ .filter((c) => c.charCodeAt(0) > 31 && c.charCodeAt(0) !== 127)
44
+ .join("")
45
+ .trim();
46
+ // Relative URLs and same-page anchors carry no scheme, so they are safe.
47
+ if (href.startsWith("#") || href.startsWith("/") || href.startsWith(".")) return href;
48
+ if (SAFE_SCHEME.test(href)) return href;
49
+ if (!/^[a-z][a-z0-9+.-]*:/i.test(href)) return href; // no scheme => relative path
50
+ return null; // javascript:, data:, vbscript:, ...
51
+ }
52
+
53
+ const parser = new Marked({
54
+ gfm: true,
55
+ breaks: true,
56
+ renderer: {
57
+ html({ text }) {
58
+ return escapeHtml(text);
59
+ },
60
+ link({ href, title, tokens }) {
61
+ const safe = safeUrl(href);
62
+ const inner = this.parser.parseInline(tokens);
63
+ if (!safe) return inner; // strip the link, keep the visible text
64
+ const t = title ? ` title="${escapeHtml(title)}"` : "";
65
+ return `<a href="${escapeHtml(safe)}"${t} rel="noopener noreferrer nofollow" target="_blank">${inner}</a>`;
66
+ },
67
+ // WHY: an image tag fetches on render, so injected model output could leak context through its URL. A link waits for a click.
68
+ image({ href, text }) {
69
+ const safe = safeUrl(href);
70
+ const label = escapeHtml(text || href || "");
71
+ if (!safe) return label;
72
+ return `<a href="${escapeHtml(safe)}" rel="noopener noreferrer nofollow" target="_blank">${label}</a>`;
73
+ },
74
+ },
75
+ });
76
+ </script>
77
+
78
+ <script lang="ts">
79
+ // =========================
80
+ // IMPORTS
81
+ // =========================
82
+
83
+ import "./Response.css";
84
+ import { cn } from "@heyramzi/utils";
85
+
86
+ // =========================
87
+ // PROPS
88
+ // =========================
89
+
90
+ let { content, streaming = false, class: className, ...rest }: ResponseProps = $props();
91
+
92
+ // =========================
93
+ // DERIVED
94
+ // =========================
95
+
96
+ // WHY: parse() is sync when no async extensions are registered; {async:false}
97
+ // narrows the return type to string for the {@html} sink.
98
+ const html = $derived(parser.parse(content ?? "", { async: false }) as string);
99
+ </script>
100
+
101
+ <!-- =========================== -->
102
+ <!-- MARKUP -->
103
+ <!-- =========================== -->
104
+
105
+ <div
106
+ class={cn(
107
+ "ai-response text-sm leading-5 [overflow-wrap:anywhere]",
108
+ "[&>*:first-child]:mt-0 [&>*:last-child]:mb-0",
109
+ "[&_p]:my-2 [&_p:first-child]:mt-0 [&_p:last-child]:mb-0",
110
+ "[&_ul]:my-2 [&_ul]:ml-4 [&_ul]:list-disc",
111
+ "[&_ol]:my-2 [&_ol]:ml-4 [&_ol]:list-decimal",
112
+ "[&_li]:my-0.5",
113
+ "[&_strong]:font-semibold",
114
+ "[&_em]:italic",
115
+ "[&_code]:rounded [&_code]:bg-[color:var(--muted,rgba(0,0,0,0.06))] [&_code]:px-1 [&_code]:py-0.5 [&_code]:text-[0.875em]",
116
+ "[&_pre]:my-2 [&_pre]:overflow-x-auto [&_pre]:rounded-md [&_pre]:bg-[color:var(--muted,rgba(0,0,0,0.06))] [&_pre]:p-3",
117
+ "[&_pre_code]:bg-transparent [&_pre_code]:p-0",
118
+ "[&_a]:underline [&_a]:underline-offset-2",
119
+ "[&_h1]:mt-3 [&_h1]:mb-1 [&_h1]:text-base [&_h1]:font-semibold",
120
+ "[&_h2]:mt-3 [&_h2]:mb-1 [&_h2]:text-sm [&_h2]:font-semibold",
121
+ "[&_h3]:mt-2 [&_h3]:mb-1 [&_h3]:text-sm [&_h3]:font-medium",
122
+ "[&_img]:my-2 [&_img]:max-w-full [&_img]:rounded-md",
123
+ "[&_blockquote]:my-2 [&_blockquote]:border-l-2 [&_blockquote]:border-[color:var(--border,rgba(0,0,0,0.1))] [&_blockquote]:pl-3 [&_blockquote]:text-[color:var(--muted-foreground,inherit)]",
124
+ className,
125
+ )}
126
+ class:is-streaming={streaming}
127
+ {...rest}
128
+ >
129
+ {@html html}
130
+ </div>
@@ -0,0 +1,5 @@
1
+ import Response from "./Response.svelte";
2
+ import type { ResponseProps } from "./Response.svelte";
3
+
4
+ export { Response, type ResponseProps };
5
+ export default Response;
@@ -0,0 +1,43 @@
1
+ <script lang="ts" module>
2
+ import { Button, type ButtonProps } from "../../shadcn/button/index.js";
3
+
4
+ export interface SuggestionProps extends Omit<ButtonProps, "onclick" | "children"> {
5
+ suggestion: string;
6
+ onclick?: (suggestion: string) => void;
7
+ class?: string;
8
+ children?: import("svelte").Snippet;
9
+ }
10
+ </script>
11
+
12
+ <script lang="ts">
13
+ import { cn } from "@heyramzi/utils";
14
+
15
+ let {
16
+ suggestion,
17
+ onclick,
18
+ class: className,
19
+ variant = "outline",
20
+ size = "sm",
21
+ children,
22
+ ...rest
23
+ }: SuggestionProps = $props();
24
+
25
+ const handleClick = () => {
26
+ onclick?.(suggestion);
27
+ };
28
+ </script>
29
+
30
+ <Button
31
+ class={cn("cursor-pointer rounded-full px-4 whitespace-nowrap", className)}
32
+ onclick={handleClick}
33
+ {size}
34
+ type="button"
35
+ {variant}
36
+ {...rest}
37
+ >
38
+ {#if children}
39
+ {@render children()}
40
+ {:else}
41
+ {suggestion}
42
+ {/if}
43
+ </Button>
@@ -0,0 +1,25 @@
1
+ <script lang="ts">
2
+ import { cn } from "@heyramzi/utils";
3
+ import type { Snippet } from "svelte";
4
+ import type { HTMLAttributes } from "svelte/elements";
5
+
6
+ export interface SuggestionsProps extends HTMLAttributes<HTMLDivElement> {
7
+ children?: Snippet;
8
+ class?: string;
9
+ }
10
+
11
+ let { children, class: className, ...rest }: SuggestionsProps = $props();
12
+ </script>
13
+
14
+ <div
15
+ class={cn(
16
+ "flex w-full items-center gap-2 overflow-x-auto pb-1",
17
+ "[&::-webkit-scrollbar]:hidden",
18
+ "[scrollbar-width:none]",
19
+ className,
20
+ )}
21
+ role="list"
22
+ {...rest}
23
+ >
24
+ {@render children?.()}
25
+ </div>
@@ -0,0 +1,14 @@
1
+ import Suggestion from "./Suggestion.svelte";
2
+ import Suggestions from "./Suggestions.svelte";
3
+ import type { SuggestionProps } from "./Suggestion.svelte";
4
+ import type { SuggestionsProps } from "./Suggestions.svelte";
5
+
6
+ export {
7
+ Suggestion,
8
+ Suggestions,
9
+ type SuggestionProps,
10
+ type SuggestionsProps,
11
+ //
12
+ Suggestion as Item,
13
+ Suggestions as Root,
14
+ };
@@ -0,0 +1,42 @@
1
+ <script lang="ts">
2
+ // =========================
3
+ // IMPORTS
4
+ // =========================
5
+
6
+ import { cn } from "@heyramzi/utils";
7
+ import type { HTMLAttributes } from "svelte/elements";
8
+ import TypingDots from "../typing-dots/TypingDots.svelte";
9
+
10
+ // =========================
11
+ // TYPES
12
+ // =========================
13
+
14
+ export interface ThinkingDotsProps extends HTMLAttributes<HTMLDivElement> {
15
+ label?: string;
16
+ class?: string;
17
+ }
18
+
19
+ // =========================
20
+ // PROPS
21
+ // =========================
22
+
23
+ let { label = "Thinking", class: className, ...rest }: ThinkingDotsProps = $props();
24
+ </script>
25
+
26
+ <!-- =========================== -->
27
+ <!-- MARKUP -->
28
+ <!-- =========================== -->
29
+
30
+ <!-- WHY: the dots animation is the shared chat TypingDots primitive; this only
31
+ adds the AI "thinking" label so there is a single source for the dots. -->
32
+ <div
33
+ class={cn(
34
+ "inline-flex items-center gap-2 text-sm text-[color:var(--ai-thinking-fg,inherit)]",
35
+ className,
36
+ )}
37
+ role="status"
38
+ {...rest}
39
+ >
40
+ {#if label}<span>{label}</span>{/if}
41
+ <TypingDots />
42
+ </div>
@@ -0,0 +1,5 @@
1
+ import ThinkingDots from "./ThinkingDots.svelte";
2
+ import type { ThinkingDotsProps } from "./ThinkingDots.svelte";
3
+
4
+ export { ThinkingDots, type ThinkingDotsProps };
5
+ export default ThinkingDots;