@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,107 @@
1
+ <script lang="ts">
2
+ // =========================
3
+ // IMPORTS
4
+ // =========================
5
+ import type { Snippet } from "svelte";
6
+ import { cn } from "@heyramzi/utils";
7
+
8
+ // =========================
9
+ // TYPES
10
+ // =========================
11
+ type Props = {
12
+ // Answers three questions in one order: what is this, what state is it in,
13
+ // what can I do with it. Each queue page used to order them differently.
14
+ title: string;
15
+ // The state chip beside the title.
16
+ badge?: Snippet;
17
+ // A picture ahead of the title, like a video frame or a deck cover. Some
18
+ // records aren't recognisable from their title alone.
19
+ leading?: Snippet;
20
+ // Facts about the record, rendered as one dot-separated line under the
21
+ // title. Falsy entries drop out, so a caller can inline its conditionals.
22
+ meta?: Array<string | null | undefined | false>;
23
+ // A sentence under the meta line, when the record explains itself.
24
+ note?: string | null;
25
+ // What you can do to the record. Pinned right of the identity block, EXCEPT
26
+ // when a picture leads: see the note in the markup.
27
+ actions?: Snippet;
28
+ // The top-right control, a record's way out. Pass `undefined` when empty:
29
+ // an empty snippet is still truthy and reserves the corner.
30
+ corner?: Snippet;
31
+ // Hairline-separated rows below the identity block. Use `DetailRow`.
32
+ children?: Snippet;
33
+ class?: string;
34
+ };
35
+
36
+ // =========================
37
+ // PROPS
38
+ // =========================
39
+ let { title, badge, leading, meta, note, actions, corner, children, class: className }: Props =
40
+ $props();
41
+
42
+ // =========================
43
+ // DERIVED
44
+ // =========================
45
+ let facts = $derived((meta ?? []).filter((item): item is string => Boolean(item)));
46
+ // Actions stack under the meta when something else claims the right edge:
47
+ // a picture, or the corner. Pinned beside a corner, they left the title
48
+ // a third of the row.
49
+ let stackActions = $derived(Boolean(leading || corner));
50
+ </script>
51
+
52
+ <!-- =========================== -->
53
+ <!-- MARKUP -->
54
+ <!-- =========================== -->
55
+ <section class={cn("overflow-hidden rounded-xl border border-border bg-card", className)}>
56
+ <div class="flex flex-wrap items-start justify-between gap-x-4 gap-y-3 p-4">
57
+ {#if leading}
58
+ <div class="shrink-0">{@render leading()}</div>
59
+ {/if}
60
+ <div class="min-w-0 flow-root flex-1 basis-64">
61
+ <!-- The corner floats, so only the lines beside it give way. Reserved
62
+ across the whole row it took ~150px off every line and wrapped a
63
+ normal title to three. -->
64
+ {#if corner}
65
+ <div class="float-end ms-3">{@render corner()}</div>
66
+ {/if}
67
+ <!-- The badge sits inline in the h2 so it trails the last word. As a
68
+ flex sibling it wrapped to its own row on every two-line title. -->
69
+ <!-- No text-balance: it evens the lines out, so a two-line title stopped
70
+ short of the corner instead of running the full width. -->
71
+ <h2 class="min-w-0 font-heading text-lg font-semibold leading-snug tracking-tight">
72
+ {title}{#if badge}<span class="ms-2 inline-flex align-middle">{@render badge()}</span
73
+ >{/if}
74
+ </h2>
75
+ {#if facts.length > 0}
76
+ <!-- Each dot hangs off the fact it leads, so a wrapped line's dot stays
77
+ in the gutter. A standalone flex-item dot dangled on the line above. -->
78
+ <div class="mt-1 overflow-hidden">
79
+ <p class="-ms-3 flex flex-wrap items-center text-sm text-muted-foreground">
80
+ {#each facts as fact, i (i)}
81
+ <span
82
+ class="relative ps-3 before:absolute before:start-1 before:opacity-40 before:content-['·']"
83
+ >{fact}</span
84
+ >
85
+ {/each}
86
+ </p>
87
+ </div>
88
+ {/if}
89
+ {#if note}
90
+ <p class="mt-1 text-sm text-muted-foreground">{note}</p>
91
+ {/if}
92
+ <!-- With a picture or a corner, actions sit in this column. Pinned right
93
+ they wrapped under the picture and read like its caption. -->
94
+ {#if actions && stackActions}
95
+ <div class="clear-both flex flex-wrap items-center gap-2 pt-3">
96
+ {@render actions()}
97
+ </div>
98
+ {/if}
99
+ </div>
100
+ {#if actions && !stackActions}
101
+ <div class="flex flex-wrap items-center gap-2">{@render actions()}</div>
102
+ {/if}
103
+ </div>
104
+ {#if children}
105
+ {@render children()}
106
+ {/if}
107
+ </section>
@@ -0,0 +1,90 @@
1
+ <script lang="ts">
2
+ // =========================
3
+ // IMPORTS
4
+ // =========================
5
+ import type { Snippet } from "svelte";
6
+ import SectionLabel from "./section-label.svelte";
7
+ import { cn } from "@heyramzi/utils";
8
+ import { panelHeaderClass, panelShellClass } from "../../lib/panel.js";
9
+ import type { PhosphorIcon } from "../../lib/icon-types.js";
10
+
11
+ // =========================
12
+ // TYPES
13
+ // =========================
14
+ type Props = {
15
+ // One panel per idea in a detail pane. Hand-rolled copies drifted between
16
+ // 8px and 12px corners, so rounded-xl lives here once.
17
+ label?: string;
18
+ labelIcon?: PhosphorIcon;
19
+ // A mark the icon set does not carry (a platform logo), drawn ahead of the
20
+ // label at the same optical size.
21
+ labelLead?: Snippet;
22
+ // The right side of the header bar: a count, a hint, a button cluster.
23
+ actions?: Snippet;
24
+ // WHY: a panel whose body is a media grid or a full-bleed list supplies its
25
+ // own padding, so the shell must be able to step out of the way.
26
+ pad?: boolean;
27
+ // Takes the height the panels above it did not use, inside a `fill` stack.
28
+ // One panel per stack, and it is the one the reader works in.
29
+ grow?: boolean;
30
+ children: Snippet;
31
+ class?: string;
32
+ bodyClass?: string;
33
+ };
34
+
35
+ // =========================
36
+ // PROPS
37
+ // =========================
38
+ let {
39
+ label,
40
+ labelIcon,
41
+ labelLead,
42
+ actions,
43
+ pad = true,
44
+ grow = false,
45
+ children,
46
+ class: className,
47
+ bodyClass,
48
+ }: Props = $props();
49
+
50
+ // =========================
51
+ // DERIVED
52
+ // =========================
53
+ let hasHeader = $derived(Boolean(label || labelLead || actions));
54
+ </script>
55
+
56
+ <!-- =========================== -->
57
+ <!-- MARKUP -->
58
+ <!-- =========================== -->
59
+ <section
60
+ class={cn(
61
+ panelShellClass,
62
+ grow && "flex min-h-0 flex-1 flex-col",
63
+ className,
64
+ )}
65
+ >
66
+ {#if hasHeader}
67
+ <div
68
+ class={panelHeaderClass}
69
+ >
70
+ {#if label || labelLead}
71
+ <SectionLabel icon={labelIcon}>
72
+ {#if labelLead}
73
+ {@render labelLead()}
74
+ {/if}
75
+ {label}
76
+ </SectionLabel>
77
+ {:else}
78
+ <span></span>
79
+ {/if}
80
+ {#if actions}
81
+ <div class="flex min-w-0 flex-wrap items-center justify-end gap-2">
82
+ {@render actions()}
83
+ </div>
84
+ {/if}
85
+ </div>
86
+ {/if}
87
+ <div class={cn(pad && "p-4", grow && "flex min-h-0 flex-1 flex-col", bodyClass)}>
88
+ {@render children()}
89
+ </div>
90
+ </section>
@@ -0,0 +1,36 @@
1
+ <script lang="ts">
2
+ // =========================
3
+ // IMPORTS
4
+ // =========================
5
+ import type { Snippet } from "svelte";
6
+ import { cn } from "@heyramzi/utils";
7
+
8
+ // =========================
9
+ // TYPES
10
+ // =========================
11
+ type Props = {
12
+ // A hairline band inside `DetailHeader` or `DetailPanel` for the record's
13
+ // own facts, so the page never nests cards inside cards.
14
+ muted?: boolean;
15
+ children: Snippet;
16
+ class?: string;
17
+ };
18
+
19
+ // =========================
20
+ // PROPS
21
+ // =========================
22
+ let { muted = false, children, class: className }: Props = $props();
23
+ </script>
24
+
25
+ <!-- =========================== -->
26
+ <!-- MARKUP -->
27
+ <!-- =========================== -->
28
+ <div
29
+ class={cn(
30
+ "border-t border-border px-4 py-3 text-sm leading-relaxed",
31
+ muted && "text-xs text-muted-foreground",
32
+ className,
33
+ )}
34
+ >
35
+ {@render children()}
36
+ </div>
@@ -0,0 +1,33 @@
1
+ <script lang="ts">
2
+ // =========================
3
+ // IMPORTS
4
+ // =========================
5
+ import type { Snippet } from "svelte";
6
+ import { cn } from "@heyramzi/utils";
7
+
8
+ // =========================
9
+ // TYPES
10
+ // =========================
11
+ type Props = {
12
+ // A flat stack of panels at one gap. `xl:pr-1` keeps the top panel's
13
+ // corner clear of the shell's scrollbar.
14
+
15
+ // `fill` makes the stack at least as tall as its scroller, so a `grow`
16
+ // panel (like a writing box) takes the empty bottom third back.
17
+ fill?: boolean;
18
+ children: Snippet;
19
+ class?: string;
20
+ };
21
+
22
+ // =========================
23
+ // PROPS
24
+ // =========================
25
+ let { fill = false, children, class: className }: Props = $props();
26
+ </script>
27
+
28
+ <!-- =========================== -->
29
+ <!-- MARKUP -->
30
+ <!-- =========================== -->
31
+ <div class={cn("flex flex-col gap-4 xl:pr-1", fill && "min-h-full", className)}>
32
+ {@render children()}
33
+ </div>
@@ -0,0 +1,91 @@
1
+ <script lang="ts">
2
+ // =========================
3
+ // IMPORTS
4
+ // =========================
5
+ import { Button } from "../../shadcn/button/index.js";
6
+ import * as Empty from "../../shadcn/empty/index.js";
7
+ import type { PhosphorIcon, IconWeight } from "../../lib/icon-types.js";
8
+
9
+ // =========================
10
+ // TYPES
11
+ // =========================
12
+ interface Props {
13
+ icon?: PhosphorIcon;
14
+ iconWeight?: IconWeight;
15
+ title: string;
16
+ description?: string;
17
+ actionLabel?: string;
18
+ actionHref?: string;
19
+ onAction?: () => void;
20
+ }
21
+
22
+ // =========================
23
+ // PROPS
24
+ // =========================
25
+ let {
26
+ icon: Icon,
27
+ iconWeight,
28
+ title,
29
+ description,
30
+ actionLabel,
31
+ actionHref,
32
+ onAction,
33
+ }: Props = $props();
34
+ </script>
35
+
36
+ <!-- =========================== -->
37
+ <!-- MARKUP -->
38
+ <!-- =========================== -->
39
+ <!-- The four parts arrive in reading order. The stagger is what says the page
40
+ finished loading and is simply empty. -->
41
+ <Empty.Root class="t-empty py-16">
42
+ <Empty.Header class="max-w-md">
43
+ {#if Icon}
44
+ <Empty.Media class="mb-4 size-16 rounded-2xl bg-brand-indigo/10 text-brand-indigo">
45
+ <Icon weight={iconWeight} class="size-8" />
46
+ </Empty.Media>
47
+ {/if}
48
+ <Empty.Title class="font-heading text-lg font-semibold">{title}</Empty.Title>
49
+ {#if description}
50
+ <Empty.Description>{description}</Empty.Description>
51
+ {/if}
52
+ </Empty.Header>
53
+ {#if actionLabel && (actionHref || onAction)}
54
+ <Empty.Content>
55
+ {#if actionHref}
56
+ <Button href={actionHref}>{actionLabel}</Button>
57
+ {:else}
58
+ <Button onclick={onAction}>{actionLabel}</Button>
59
+ {/if}
60
+ </Empty.Content>
61
+ {/if}
62
+ </Empty.Root>
63
+
64
+ <!-- =========================== -->
65
+ <!-- STYLE -->
66
+ <!-- =========================== -->
67
+ <style>
68
+ /* Never `:nth-child` here: one such rule makes every DOM insert on the page restyle its later siblings. */
69
+ :global(.t-empty) > :global(*) {
70
+ animation: t-empty-in var(--duration-very-slow) var(--ease-smooth-out) both;
71
+ animation-delay: calc((sibling-index() - 1) * var(--duration-stagger));
72
+ }
73
+
74
+ @keyframes -global-t-empty-in {
75
+ from {
76
+ opacity: 0;
77
+ transform: translateY(var(--distance-small));
78
+ }
79
+ to {
80
+ opacity: 1;
81
+ transform: none;
82
+ }
83
+ }
84
+
85
+ @media (prefers-reduced-motion: reduce) {
86
+ :global(.t-empty) > :global(*) {
87
+ animation-duration: 1ms;
88
+ animation-delay: 0ms;
89
+ }
90
+ }
91
+ </style>
@@ -0,0 +1,49 @@
1
+ <script lang="ts">
2
+ // =========================
3
+ // IMPORTS
4
+ // =========================
5
+ import type { Snippet } from "svelte";
6
+ import { Checkbox } from "../../shadcn/checkbox/index.js";
7
+ import { Check } from "phosphor-svelte";
8
+ import { cn } from "@heyramzi/utils";
9
+
10
+ // =========================
11
+ // TYPES
12
+ // =========================
13
+ type Props = {
14
+ checked: boolean;
15
+ onclick: () => void;
16
+ variant?: "checkbox" | "radio";
17
+ children: Snippet;
18
+ };
19
+
20
+ // =========================
21
+ // PROPS
22
+ // =========================
23
+ let { checked, onclick, variant = "checkbox", children }: Props = $props();
24
+ </script>
25
+
26
+ <!-- =========================== -->
27
+ <!-- MARKUP -->
28
+ <!-- =========================== -->
29
+ <button
30
+ type="button"
31
+ class="flex items-center gap-2 rounded-lg px-2 py-1.5 text-sm transition-colors hover:bg-muted"
32
+ {onclick}
33
+ >
34
+ {#if variant === "radio"}
35
+ <span
36
+ class={cn(
37
+ "grid size-3.5 shrink-0 place-items-center rounded-full border transition-colors",
38
+ checked ? "border-primary bg-primary text-primary-foreground" : "border-border",
39
+ )}
40
+ >
41
+ {#if checked}
42
+ <Check class="size-2.5" weight="bold" />
43
+ {/if}
44
+ </span>
45
+ {:else}
46
+ <Checkbox {checked} />
47
+ {/if}
48
+ {@render children()}
49
+ </button>
@@ -0,0 +1,88 @@
1
+ <script lang="ts">
2
+ // =========================
3
+ // IMPORTS
4
+ // =========================
5
+ import type { Snippet } from "svelte";
6
+ import * as Popover from "../../shadcn/popover/index.js";
7
+ import { Funnel as FunnelIcon } from "phosphor-svelte";
8
+ import { cn } from "@heyramzi/utils";
9
+ import { Button } from "../../shadcn/button/index.js";
10
+ import { toolbarTriggerClass } from "./toolbar-trigger.js";
11
+ import type { PhosphorIcon } from "../../lib/icon-types.js";
12
+
13
+ // phosphor-svelte v2 (resolved here) and v3 (what consumers run) differ only in
14
+ // Component generics. The cast bridges that type-only gap.
15
+ const DefaultFunnelIcon = FunnelIcon as unknown as PhosphorIcon;
16
+
17
+ // =========================
18
+ // TYPES
19
+ // =========================
20
+ type Props = {
21
+ label: string;
22
+ icon?: PhosphorIcon;
23
+ count?: number;
24
+ active?: boolean;
25
+ onClear?: () => void;
26
+ align?: "start" | "center" | "end";
27
+ width?: `w-${string}`;
28
+ open?: boolean;
29
+ clearLabel?: string;
30
+ triggerClass?: string;
31
+ contentClass?: string;
32
+ children: Snippet;
33
+ trailing?: Snippet;
34
+ };
35
+
36
+ // =========================
37
+ // PROPS
38
+ // =========================
39
+ let {
40
+ label,
41
+ icon: IconComponent = DefaultFunnelIcon,
42
+ count = 0,
43
+ active,
44
+ onClear,
45
+ align = "start",
46
+ width = "w-52",
47
+ open = $bindable(false),
48
+ clearLabel = "Clear",
49
+ triggerClass,
50
+ contentClass,
51
+ children,
52
+ trailing,
53
+ }: Props = $props();
54
+
55
+ // =========================
56
+ // DERIVED
57
+ // =========================
58
+ let hasCount = $derived(count > 0);
59
+ let isActive = $derived(active ?? hasCount);
60
+ </script>
61
+
62
+ <!-- =========================== -->
63
+ <!-- MARKUP -->
64
+ <!-- =========================== -->
65
+ <Popover.Root bind:open>
66
+ <Popover.Trigger class={toolbarTriggerClass({ active: isActive, className: triggerClass })}>
67
+ <IconComponent class="size-3.5" />
68
+ <span>{label}</span>
69
+ {#if trailing}
70
+ {@render trailing()}
71
+ {/if}
72
+ {#if hasCount}
73
+ <span
74
+ class="ml-0.5 inline-flex size-4 items-center justify-center rounded-full bg-brand-indigo/15 text-[10px] font-semibold text-brand-indigo dark:text-brand-indigo-light"
75
+ >
76
+ {count}
77
+ </span>
78
+ {/if}
79
+ </Popover.Trigger>
80
+ <Popover.Content class={cn("p-2", width, contentClass)} {align}>
81
+ {@render children()}
82
+ {#if onClear && hasCount}
83
+ <Button variant="ghost" size="sm" class="mt-2 w-full text-xs text-muted-foreground" onclick={onClear}>
84
+ {clearLabel}
85
+ </Button>
86
+ {/if}
87
+ </Popover.Content>
88
+ </Popover.Root>
@@ -0,0 +1,12 @@
1
+ import { cn } from "@heyramzi/utils";
2
+
3
+ // The header for each control group in a toolbar popover, in one place so
4
+ // sections can't drift in size or weight.
5
+
6
+ // `first:` drops the leading header's top padding, since the popover pads itself.
7
+ export function filterSectionClass(className?: string): string {
8
+ return cn(
9
+ "px-2 pt-2 pb-1 text-[11px] font-medium uppercase tracking-wide text-muted-foreground first:pt-1",
10
+ className,
11
+ );
12
+ }
@@ -0,0 +1,116 @@
1
+ <script lang="ts" generics="TGroup">
2
+ // =========================
3
+ // IMPORTS
4
+ // =========================
5
+ import { untrack, type Snippet } from "svelte";
6
+ import { SvelteSet } from "svelte/reactivity";
7
+ import { CaretDown } from "phosphor-svelte";
8
+ import { cn } from "@heyramzi/utils";
9
+
10
+ // =========================
11
+ // TYPES
12
+ // =========================
13
+ type Props = {
14
+ groups: TGroup[];
15
+ getKey: (group: TGroup) => string;
16
+ defaultCollapsed?: string[];
17
+ /** WHY: a page that drives its own keyboard cursor has to know which rows
18
+ are on screen, and the collapsed set is the only thing that says so. */
19
+ onCollapsedChange?: (keys: string[]) => void;
20
+ header: Snippet<[TGroup, { collapsed: boolean }]>;
21
+ /** Controls beside the header, outside its toggle button so a click on
22
+ one doesn't collapse the group. Shown on hover of the header row. */
23
+ actions?: Snippet<[TGroup]>;
24
+ rows: Snippet<[TGroup]>;
25
+ class?: string;
26
+ onGroupDragOver?: (e: DragEvent, group: TGroup) => void;
27
+ onGroupDragLeave?: (e: DragEvent) => void;
28
+ onGroupDrop?: (e: DragEvent, group: TGroup) => void;
29
+ };
30
+
31
+ // =========================
32
+ // PROPS
33
+ // =========================
34
+ let {
35
+ groups,
36
+ getKey,
37
+ defaultCollapsed = [],
38
+ onCollapsedChange,
39
+ header,
40
+ actions,
41
+ rows,
42
+ class: className,
43
+ onGroupDragOver,
44
+ onGroupDragLeave,
45
+ onGroupDrop,
46
+ }: Props = $props();
47
+
48
+ // =========================
49
+ // STATE
50
+ // =========================
51
+ const collapsed = new SvelteSet<string>(untrack(() => defaultCollapsed));
52
+
53
+ // =========================
54
+ // FUNCTIONS
55
+ // =========================
56
+ function toggle(key: string) {
57
+ if (collapsed.has(key)) {
58
+ collapsed.delete(key);
59
+ } else {
60
+ collapsed.add(key);
61
+ }
62
+ onCollapsedChange?.([...collapsed]);
63
+ }
64
+ </script>
65
+
66
+ <!-- =========================== -->
67
+ <!-- MARKUP -->
68
+ <!-- =========================== -->
69
+ <div class={cn("flex w-full flex-col", className)}>
70
+ {#each groups as group, index (getKey(group))}
71
+ {@const key = getKey(group)}
72
+ {@const isCollapsed = collapsed.has(key)}
73
+ <div
74
+ class={cn(index > 0 && "mt-3 border-t border-border/50 pt-3")}
75
+ role={onGroupDragOver || onGroupDrop ? "group" : undefined}
76
+ ondragover={onGroupDragOver ? (e) => onGroupDragOver(e, group) : undefined}
77
+ ondragleave={onGroupDragLeave}
78
+ ondrop={onGroupDrop ? (e) => onGroupDrop(e, group) : undefined}
79
+ >
80
+ <div class="group/header flex items-center gap-1 rounded-lg transition-colors hover:bg-muted/60">
81
+ <button
82
+ type="button"
83
+ class="flex min-w-0 flex-1 cursor-pointer items-center gap-2.5 rounded-lg px-3 py-2 text-left"
84
+ onclick={() => toggle(key)}
85
+ aria-expanded={!isCollapsed}
86
+ >
87
+ <CaretDown
88
+ class={cn(
89
+ "size-3 shrink-0 text-muted-foreground/60 transition-transform duration-[var(--duration-fast)] ease-[var(--ease-smooth-out)]",
90
+ isCollapsed && "-rotate-90",
91
+ )}
92
+ weight="bold"
93
+ />
94
+ {@render header(group, { collapsed: isCollapsed })}
95
+ </button>
96
+ {#if actions}
97
+ <div
98
+ class="flex shrink-0 items-center gap-1 pe-2 opacity-0 transition-opacity group-hover/header:opacity-100 focus-within:opacity-100 any-pointer-coarse:opacity-100"
99
+ >
100
+ {@render actions(group)}
101
+ </div>
102
+ {/if}
103
+ </div>
104
+
105
+ {#if !isCollapsed}
106
+ <div>
107
+ {@render rows(group)}
108
+ </div>
109
+ {/if}
110
+ </div>
111
+ {/each}
112
+ </div>
113
+
114
+ <!-- No entrance motion. Four stacked animations made the last group of a
115
+ 40-row board arrive two seconds late. Working surfaces don't animate in. -->
116
+ <!-- No `overflow: hidden` either: it clipped anything a row opened. -->
@@ -0,0 +1,28 @@
1
+ export { default as DetailEmpty } from "./detail-empty.svelte";
2
+ export { default as DetailHeader } from "./detail-header.svelte";
3
+ export { default as DetailPanel } from "./detail-panel.svelte";
4
+ export { default as DetailRow } from "./detail-row.svelte";
5
+ export { default as DetailStack } from "./detail-stack.svelte";
6
+ export { default as EmptyState } from "./empty-state.svelte";
7
+ export { default as FilterItem } from "./filter-item.svelte";
8
+ export { default as PrevNext } from "./prev-next.svelte";
9
+ export { stepTo } from "./step.js";
10
+ export { default as NoticeBar } from "./notice-bar.svelte";
11
+ export { default as RailBody } from "./rail-body.svelte";
12
+ export { default as RailEmpty } from "./rail-empty.svelte";
13
+ export { default as RailHead } from "./rail-head.svelte";
14
+ export { default as RailRow } from "./rail-row.svelte";
15
+ export { default as SectionLabel } from "./section-label.svelte";
16
+ export { queueRailClass, queueRailWidth } from "./queue-rail.js";
17
+ export { default as FilterPopover } from "./filter-popover.svelte";
18
+ export { filterSectionClass } from "./filter-section.js";
19
+ export { default as GroupedList } from "./grouped-list.svelte";
20
+ export { default as ListPageShell } from "./list-page-shell.svelte";
21
+ export { default as MasterDetail } from "./master-detail.svelte";
22
+ // The segmented control isn't re-exported here. Two import paths drifted, so
23
+ // its one home is `@heyramzi/ui/components/segmented`.
24
+ export { default as ToolbarSearch } from "./toolbar-search.svelte";
25
+ export { toolbarTriggerClass } from "./toolbar-trigger.js";
26
+ export { listTable } from "./list-table.js";
27
+ export type { ViewMode } from "./types.js";
28
+ export { getSectionHost, setSectionHost, type SectionHost } from "./section-host.js";