@heyramzi/ui 7.0.0 → 8.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (253) hide show
  1. package/COMPONENTS.md +28 -17
  2. package/README.md +5 -1
  3. package/package.json +25 -15
  4. package/scripts/sync-shadcn.mjs +17 -13
  5. package/scripts/sync-transitions.mjs +11 -11
  6. package/src/ai/ai-button/AiButton.svelte +86 -0
  7. package/src/ai/ai-button/index.ts +4 -0
  8. package/src/ai/confirmation/Confirmation.svelte +8 -8
  9. package/src/ai/confirmation/confirmation-context.svelte.ts +2 -2
  10. package/src/ai/generation-progress/GenerationProgress.svelte +354 -0
  11. package/src/ai/generation-progress/index.ts +7 -0
  12. package/src/ai/index.ts +16 -6
  13. package/src/ai/prompt-input/PromptInput.svelte +19 -1
  14. package/src/ai/prompt-input/PromptInputSubmit.svelte +9 -3
  15. package/src/ai/reasoning/Reasoning.svelte +11 -8
  16. package/src/ambient.d.ts +4 -0
  17. package/src/animations/README.md +14 -14
  18. package/src/animations/index.css +3 -14
  19. package/src/animations/upstream-coverage.test.ts +1 -1
  20. package/src/components/copy/clipboard.test.ts +206 -0
  21. package/src/components/copy/clipboard.ts +49 -0
  22. package/src/components/copy/copied.svelte.ts +39 -0
  23. package/src/components/copy/copy-button.svelte +175 -0
  24. package/src/components/copy/copy-button.test.ts +110 -0
  25. package/src/components/copy/index.ts +3 -0
  26. package/src/components/data-table/data-table.test.ts +134 -0
  27. package/src/components/data-table/data-table.ts +77 -0
  28. package/src/components/data-table/index.ts +20 -0
  29. package/src/components/data-table/infinite-scroll.svelte +69 -0
  30. package/src/components/data-table/pagination.svelte +62 -0
  31. package/src/components/data-table/row-arrow.svelte +28 -0
  32. package/src/components/data-table/row-context-menu.svelte +106 -0
  33. package/src/components/data-table/row-context-menu.test.ts +18 -0
  34. package/src/components/data-table/sortable-head.svelte +56 -0
  35. package/src/components/data-table/table-skeleton.svelte +83 -0
  36. package/src/components/hold-to-confirm/hold-to-confirm.svelte +232 -0
  37. package/src/components/hold-to-confirm/index.ts +1 -0
  38. package/src/components/icon/icon.svelte +23 -0
  39. package/src/components/icon/index.ts +1 -0
  40. package/src/components/language-flag/index.ts +1 -0
  41. package/src/components/language-flag/language-flag.svelte +60 -0
  42. package/src/components/list-page/detail-empty.svelte +50 -0
  43. package/src/components/list-page/detail-header.svelte +107 -0
  44. package/src/components/list-page/detail-panel.svelte +90 -0
  45. package/src/components/list-page/detail-row.svelte +36 -0
  46. package/src/components/list-page/detail-stack.svelte +33 -0
  47. package/src/components/list-page/empty-state.svelte +91 -0
  48. package/src/components/list-page/filter-item.svelte +49 -0
  49. package/src/components/list-page/filter-popover.svelte +88 -0
  50. package/src/components/list-page/filter-section.ts +12 -0
  51. package/src/components/list-page/grouped-list.svelte +116 -0
  52. package/src/components/list-page/index.ts +28 -0
  53. package/src/components/list-page/list-page-shell.svelte +195 -0
  54. package/src/components/list-page/list-table.ts +19 -0
  55. package/src/components/list-page/master-detail.svelte +206 -0
  56. package/src/components/list-page/master-detail.test.ts +37 -0
  57. package/src/components/list-page/notice-bar.svelte +68 -0
  58. package/src/components/list-page/prev-next.svelte +104 -0
  59. package/src/components/list-page/queue-rail.ts +25 -0
  60. package/src/components/list-page/rail-body.svelte +29 -0
  61. package/src/components/list-page/rail-empty.svelte +51 -0
  62. package/src/components/list-page/rail-head.svelte +49 -0
  63. package/src/components/list-page/rail-row.svelte +163 -0
  64. package/src/components/list-page/section-host.ts +24 -0
  65. package/src/components/list-page/section-label.svelte +39 -0
  66. package/src/components/list-page/step.test.ts +21 -0
  67. package/src/components/list-page/step.ts +10 -0
  68. package/src/components/list-page/toolbar-search.svelte +63 -0
  69. package/src/components/list-page/toolbar-trigger.ts +23 -0
  70. package/src/components/list-page/types.ts +1 -0
  71. package/src/components/locale-switch/index.ts +1 -0
  72. package/src/components/locale-switch/locale-switch.svelte +59 -0
  73. package/src/components/mark/index.ts +1 -0
  74. package/src/components/mark/mark.svelte +70 -0
  75. package/src/components/open-in/index.ts +6 -0
  76. package/src/components/open-in/open-in.svelte +106 -0
  77. package/src/components/picker/index.ts +4 -0
  78. package/src/components/picker/mark-picker.svelte +84 -0
  79. package/src/components/picker/picker.svelte +143 -0
  80. package/src/components/picker/trigger.ts +42 -0
  81. package/src/components/picker/types.ts +26 -0
  82. package/src/components/segmented/animated-tabs.svelte +175 -0
  83. package/src/components/segmented/collapse.test.ts +49 -0
  84. package/src/components/segmented/collapse.ts +39 -0
  85. package/src/components/segmented/index.ts +41 -0
  86. package/src/components/segmented/section-runs.svelte +79 -0
  87. package/src/components/segmented/segment.svelte +106 -0
  88. package/src/components/segmented/segmented-filter.svelte +125 -0
  89. package/src/components/segmented/segmented-nav.svelte +82 -0
  90. package/src/components/segmented/segmented-overflow.svelte +85 -0
  91. package/src/components/segmented/segmented-track.svelte +181 -0
  92. package/src/components/segmented/segmented.test.ts +20 -0
  93. package/src/components/segmented/segmented.ts +80 -0
  94. package/src/components/star-rating-input/index.ts +9 -0
  95. package/src/components/star-rating-input/star-rating-input.svelte +256 -0
  96. package/src/components/svg/index.ts +1 -0
  97. package/src/components/svg/svg.svelte +9 -0
  98. package/src/effects/border-beam/BorderBeam.svelte +1 -1
  99. package/src/effects/image-comparison/ImageComparison.css +42 -8
  100. package/src/effects/image-comparison/ImageComparison.svelte +138 -21
  101. package/src/effects/image-comparison/compare.test.ts +17 -0
  102. package/src/effects/image-comparison/compare.ts +5 -0
  103. package/src/effects/interactive-hover-button/InteractiveHoverButton.svelte +338 -0
  104. package/src/effects/magic-card/MagicCard.css +47 -0
  105. package/src/effects/magic-card/MagicCard.svelte +57 -0
  106. package/src/effects/marquee/Marquee.css +27 -1
  107. package/src/effects/marquee/Marquee.svelte +67 -3
  108. package/src/effects/reveal/index.ts +2 -1
  109. package/src/effects/reveal/observe.test.ts +60 -0
  110. package/src/effects/reveal/observe.ts +33 -1
  111. package/src/effects/reveal/types.ts +7 -0
  112. package/src/effects/theme-toggle/ThemeToggle.css +199 -6
  113. package/src/effects/theme-toggle/ThemeToggle.svelte +51 -26
  114. package/src/gallery.test.ts +52 -0
  115. package/src/index.ts +5 -1
  116. package/src/lib/panel.ts +7 -1
  117. package/src/lib/theme-transition.ts +37 -11
  118. package/src/lib/tone.ts +48 -0
  119. package/src/shadcn/accordion/accordion-trigger.svelte +15 -6
  120. package/src/shadcn/alert/alert.svelte +3 -1
  121. package/src/shadcn/badge/badge.svelte +8 -7
  122. package/src/shadcn/breadcrumb/breadcrumb-ellipsis.svelte +2 -2
  123. package/src/shadcn/breadcrumb/breadcrumb-separator.svelte +2 -2
  124. package/src/shadcn/calendar/calendar-month-select.svelte +2 -2
  125. package/src/shadcn/calendar/calendar-next-button.svelte +2 -2
  126. package/src/shadcn/calendar/calendar-prev-button.svelte +2 -2
  127. package/src/shadcn/calendar/calendar-year-select.svelte +2 -2
  128. package/src/shadcn/calendar/calendar.svelte +6 -0
  129. package/src/shadcn/code-block/code-block-copy-button.svelte +6 -55
  130. package/src/shadcn/command/index.ts +3 -0
  131. package/src/shadcn/field/index.ts +3 -0
  132. package/src/shadcn/field/simple-field.svelte +71 -0
  133. package/src/shadcn/field/simple-field.test.ts +47 -0
  134. package/src/shadcn/message-scroller/message-scroller-button.svelte +2 -2
  135. package/src/shadcn/radio-group/radio-group-item.svelte +3 -2
  136. package/src/shadcn/sheet/sheet-content.svelte +1 -0
  137. package/src/shadcn/sheet/sheet.css +48 -0
  138. package/src/shadcn/sonner/sonner.svelte +7 -10
  139. package/src/shadcn/toggle-group/toggle-group.svelte +10 -3
  140. package/src/shadcn/trace/trace-collapsible-trigger.svelte +2 -2
  141. package/src/ai/composer/Composer.css +0 -108
  142. package/src/ai/composer/Composer.svelte +0 -111
  143. package/src/ai/composer/index.ts +0 -10
  144. package/src/animations/accordion.css +0 -58
  145. package/src/animations/icon-swap.css +0 -43
  146. package/src/animations/notification-badge.css +0 -81
  147. package/src/animations/panel.css +0 -86
  148. package/src/animations/reasoning-stream.css +0 -49
  149. package/src/animations/skeleton-reveal.css +0 -97
  150. package/src/animations/streaming-text.css +0 -31
  151. package/src/animations/tabs-sliding.css +0 -83
  152. package/src/animations/texts-reveal.css +0 -70
  153. package/src/animations/tooltip.css +0 -72
  154. package/src/animations/view-transition-reveal.ts +0 -74
  155. package/src/lib/utils.ts +0 -45
  156. package/src/showcase/AiSection.svelte +0 -150
  157. package/src/showcase/AnimationsSection.svelte +0 -1658
  158. package/src/showcase/EffectsSection.svelte +0 -152
  159. package/src/showcase/ShadcnSection.svelte +0 -27
  160. package/src/showcase/ShowcaseImport.svelte +0 -126
  161. package/src/showcase/ShowcaseList.svelte +0 -132
  162. package/src/showcase/ShowcaseNav.svelte +0 -247
  163. package/src/showcase/ShowcaseSection.svelte +0 -112
  164. package/src/showcase/ShowcaseShell.svelte +0 -55
  165. package/src/showcase/ShowcaseStage.svelte +0 -342
  166. package/src/showcase/ShowcaseVariant.svelte +0 -109
  167. package/src/showcase/assets/image-reveal/art-1.jpg +0 -0
  168. package/src/showcase/assets/image-reveal/art-2.jpg +0 -0
  169. package/src/showcase/assets/image-reveal/art-3.jpg +0 -0
  170. package/src/showcase/check.svg +0 -1
  171. package/src/showcase/chevron-arms.svg +0 -2
  172. package/src/showcase/chevron-down.svg +0 -1
  173. package/src/showcase/copy.svg +0 -2
  174. package/src/showcase/demos/ai/confirmation.svelte +0 -59
  175. package/src/showcase/demos/ai/loading-state.svelte +0 -19
  176. package/src/showcase/demos/ai/prompt-input.svelte +0 -57
  177. package/src/showcase/demos/ai/reasoning.svelte +0 -19
  178. package/src/showcase/demos/ai/thinking-dots.svelte +0 -15
  179. package/src/showcase/demos/ai/voice-waveform.svelte +0 -24
  180. package/src/showcase/demos/effects/animated-beam.svelte +0 -50
  181. package/src/showcase/demos/effects/animated-group.svelte +0 -47
  182. package/src/showcase/demos/effects/border-beam-default.svelte +0 -20
  183. package/src/showcase/demos/effects/border-beam-line.svelte +0 -20
  184. package/src/showcase/demos/effects/border-beam-mono.svelte +0 -20
  185. package/src/showcase/demos/effects/border-beam-sunset.svelte +0 -20
  186. package/src/showcase/demos/effects/image-comparison.svelte +0 -25
  187. package/src/showcase/demos/effects/image-reveal.svelte +0 -49
  188. package/src/showcase/demos/effects/in-view.svelte +0 -41
  189. package/src/showcase/demos/effects/integrations-hub.svelte +0 -82
  190. package/src/showcase/demos/effects/magnetic.svelte +0 -31
  191. package/src/showcase/demos/effects/marquee.svelte +0 -33
  192. package/src/showcase/demos/effects/progressive-blur.svelte +0 -47
  193. package/src/showcase/demos/effects/spotlight.svelte +0 -40
  194. package/src/showcase/demos/effects/text-effect.svelte +0 -55
  195. package/src/showcase/demos/shadcn/accordion.svelte +0 -45
  196. package/src/showcase/demos/shadcn/alert-dialog.svelte +0 -23
  197. package/src/showcase/demos/shadcn/alert.svelte +0 -30
  198. package/src/showcase/demos/shadcn/attachment.svelte +0 -71
  199. package/src/showcase/demos/shadcn/avatar.svelte +0 -30
  200. package/src/showcase/demos/shadcn/badge.svelte +0 -26
  201. package/src/showcase/demos/shadcn/breadcrumb.svelte +0 -34
  202. package/src/showcase/demos/shadcn/bubble.svelte +0 -36
  203. package/src/showcase/demos/shadcn/button.svelte +0 -11
  204. package/src/showcase/demos/shadcn/calendar.svelte +0 -8
  205. package/src/showcase/demos/shadcn/card.svelte +0 -39
  206. package/src/showcase/demos/shadcn/checkbox.svelte +0 -39
  207. package/src/showcase/demos/shadcn/code-block.svelte +0 -80
  208. package/src/showcase/demos/shadcn/collapsible.svelte +0 -20
  209. package/src/showcase/demos/shadcn/command.svelte +0 -48
  210. package/src/showcase/demos/shadcn/context-menu.svelte +0 -54
  211. package/src/showcase/demos/shadcn/demo-harness.svelte +0 -12
  212. package/src/showcase/demos/shadcn/demos.test.ts +0 -20
  213. package/src/showcase/demos/shadcn/dialog.svelte +0 -38
  214. package/src/showcase/demos/shadcn/dropdown-menu.svelte +0 -59
  215. package/src/showcase/demos/shadcn/empty.svelte +0 -29
  216. package/src/showcase/demos/shadcn/field.svelte +0 -115
  217. package/src/showcase/demos/shadcn/hover-card.svelte +0 -32
  218. package/src/showcase/demos/shadcn/index.ts +0 -382
  219. package/src/showcase/demos/shadcn/input-otp.svelte +0 -19
  220. package/src/showcase/demos/shadcn/input.svelte +0 -5
  221. package/src/showcase/demos/shadcn/label.svelte +0 -11
  222. package/src/showcase/demos/shadcn/marker.svelte +0 -30
  223. package/src/showcase/demos/shadcn/message-scroller.svelte +0 -44
  224. package/src/showcase/demos/shadcn/message.svelte +0 -75
  225. package/src/showcase/demos/shadcn/popover.svelte +0 -36
  226. package/src/showcase/demos/shadcn/progress.svelte +0 -13
  227. package/src/showcase/demos/shadcn/radio-group.svelte +0 -19
  228. package/src/showcase/demos/shadcn/scroll-area.svelte +0 -18
  229. package/src/showcase/demos/shadcn/select.svelte +0 -29
  230. package/src/showcase/demos/shadcn/separator.svelte +0 -12
  231. package/src/showcase/demos/shadcn/sheet.svelte +0 -48
  232. package/src/showcase/demos/shadcn/skeleton.svelte +0 -11
  233. package/src/showcase/demos/shadcn/slider.svelte +0 -7
  234. package/src/showcase/demos/shadcn/sonner.svelte +0 -18
  235. package/src/showcase/demos/shadcn/spinner.svelte +0 -11
  236. package/src/showcase/demos/shadcn/switch.svelte +0 -9
  237. package/src/showcase/demos/shadcn/table.svelte +0 -76
  238. package/src/showcase/demos/shadcn/tabs.svelte +0 -62
  239. package/src/showcase/demos/shadcn/textarea.svelte +0 -5
  240. package/src/showcase/demos/shadcn/toggle-group.svelte +0 -18
  241. package/src/showcase/demos/shadcn/toggle.svelte +0 -14
  242. package/src/showcase/demos/shadcn/tooltip.svelte +0 -13
  243. package/src/showcase/demos/shadcn/trace.svelte +0 -51
  244. package/src/showcase/heart.svg +0 -1
  245. package/src/showcase/index.ts +0 -38
  246. package/src/showcase/kit.test.ts +0 -72
  247. package/src/showcase/kit.ts +0 -16
  248. package/src/showcase/plus.svg +0 -1
  249. package/src/showcase/showcase-shell.css +0 -91
  250. package/src/showcase/stacked-section.css +0 -15
  251. package/src/showcase/success-check.svg +0 -1
  252. package/src/showcase/types.ts +0 -29
  253. package/src/svg-raw.d.ts +0 -7
package/COMPONENTS.md CHANGED
@@ -23,12 +23,12 @@ The style layer lives in [`src/tokens.css`](./src/tokens.css) and the motion CSS
23
23
  - `checkbox` — Checkbox
24
24
  - `code-block` — CodeBlock. Highlight with `useHighlightedCode` from `@heyramzi/ui/shadcn/hooks/use-highlighted-code.svelte` (Shiki, ANSI too)
25
25
  - `collapsible` — Collapsible
26
- - `command` — Command
26
+ - `command` — Command, computeCommandScore (the scorer, for a custom `filter`)
27
27
  - `context-menu` — ContextMenu
28
28
  - `dialog` — Dialog
29
29
  - `dropdown-menu` — CheckboxGroup, CheckboxItem, Content, Portal, DropdownMenu, DropdownMenuCheckboxGroup
30
30
  - `empty` — Empty
31
- - `field` — Field
31
+ - `field` — Field and its parts, plus SimpleField: label, hint or error and the control, with the message linked by `aria-describedby`
32
32
  - `hover-card` — HoverCard
33
33
  - `input` — Input
34
34
  - `input-otp` — InputOtp
@@ -57,54 +57,66 @@ The style layer lives in [`src/tokens.css`](./src/tokens.css) and the motion CSS
57
57
  - `tooltip` — Tooltip
58
58
  - `trace` — Trace, an agent's steps: reasoning, tool calls and sources as status rows that can expand
59
59
 
60
+ ## Components (`src/components`)
61
+
62
+ Generic pieces built on the primitives, imported from `@heyramzi/ui/components/<name>`.
63
+
64
+ - `copy` — CopyButton, copyText, copyRichText, htmlToPlainText, Copied
65
+ - `data-table` — SortableHead, Pagination, InfiniteScroll, RowContextMenu, TableSkeleton, and the sort, page and filter helpers
66
+ - `hold-to-confirm` — HoldToConfirm, press and hold to confirm
67
+ - `icon` — Icon, a Phosphor component at a size
68
+ - `language-flag` — LanguageFlag
69
+ - `list-page` — ListPageShell, MasterDetail, GroupedList, RailRow and the rest of the master-detail page kit, NoticeBar, EmptyState, FilterPopover, setSectionHost
70
+ - `locale-switch` — LocaleSwitch, a language switch on SegmentedFilter
71
+ - `mark` — Mark, a logo or photo glyph with an initial fallback
72
+ - `open-in` — OpenIn, a link out to a tool that takes the tool's name, label and mark as a prop
73
+ - `picker` — Picker, MarkPicker, pickerTriggerClass, a command palette at popover scale
74
+ - `segmented` — AnimatedTabs (pill or underline), SegmentedFilter, SegmentedNav, SectionRuns, one bordered track with a sliding pill, a badge note and an overflow menu
75
+ - `star-rating-input` — StarRatingInput
76
+ - `svg` — Svg, an SVG file imported with `?raw`
77
+
60
78
  ## Effects (`src/effects`)
61
79
 
80
+ - `interactive-hover-button` — InteractiveHoverButton, a dot that grows into the fill
81
+
62
82
  - `animated-beam` — AnimatedBeam, AnimatedBeamProps, AnchorPosition
63
83
  - `border-beam` — BorderBeam
64
- - `image-comparison` — ImageComparison
84
+ - `image-comparison` — ImageComparison, a before/after wipe with a bindable position, side badges and a hint sweep
65
85
  - `image-reveal` — ImageReveal, ImageRevealProps, ImageRevealHandle
66
86
  - `magnetic` — magnetic
87
+ - `magic-card` — MagicCard. Props: `glow`, `radius`, `class`, `contentClass`; the glow colour is `--magic-card-glow` set on `class`.
67
88
  - `marquee` — Marquee
68
89
  - `progressive-blur` — ProgressiveBlur
69
90
  - `reveal` — InView, AnimatedGroup, TextEffect, observeInView, RevealPreset, RevealPer
70
91
  - `shader-gradient` — ShaderGradient, ShaderGradientProps, ShaderGradientUniforms
71
92
  - `spotlight` — Spotlight
72
- - `theme-toggle` — ThemeToggle, revealTheme. Props: `isDark`, `mode` (`light`, `dark`, `system`; swaps in the Monitor icon), `onToggle`, `variant` (`outline`, `ghost`, `inverted`; `inverted` boolean is an alias), `size`, `label`, `title`, `skipTransition`, `class`. `revealTheme(event, apply, { skip, duration, easing })` is the circular wipe on its own: `import { revealTheme } from "@heyramzi/ui"` (the `./lib/*` subpath points at `.js` and the source is `.ts`).
93
+ - `theme-toggle` — ThemeToggle, revealTheme. Props: `isDark`, `mode` (`light`, `dark`, `system`; swaps in the Monitor icon), `onToggle`, `variant` (`outline`, `ghost`, `inverted`, `slide`; `inverted` boolean is an alias; `slide` is a pill with a moving thumb, coloured by `--theme-toggle-thumb-light`, `--theme-toggle-thumb-dark`, `--theme-toggle-track`, `--theme-toggle-glow` and friends set on `class`), `size`, `label`, `title`, `skipTransition`, `class`. `revealTheme(event, apply, { skip, duration, easing })` is the circular wipe on its own: `import { revealTheme } from "@heyramzi/ui"` (the `./lib/*` subpath points at `.js` and the source is `.ts`).
73
94
 
74
95
  ## Animations (`src/animations`)
75
96
 
76
- - `accordion` — keyframe utilities
77
97
  - `avatar-group-hover` — keyframe utilities
78
98
  - `card-tilt` — keyframe utilities
79
99
  - `digit-pop-in` — keyframe utilities
80
100
  - `dropdown` — keyframe utilities
81
- - `icon-swap` — keyframe utilities
82
101
  - `input-clear-dissolve` — keyframe utilities
83
102
  - `input-shake` — keyframe utilities
84
103
  - `learn-more-hover` — keyframe utilities
85
104
  - `like-button` — keyframe utilities
86
105
  - `modal` — keyframe utilities
87
- - `notification-badge` — keyframe utilities
88
106
  - `page-side-by-side` — keyframe utilities
89
- - `panel` — keyframe utilities
90
107
  - `plus-menu-morph` — keyframe utilities
91
- - `reasoning-stream` — keyframe utilities
92
108
  - `resize` — keyframe utilities
93
109
  - `shimmer-text` — keyframe utilities
94
- - `skeleton-reveal` — keyframe utilities
95
110
  - `spinning-counter` — keyframe utilities
96
- - `streaming-text` — keyframe utilities
97
111
  - `success-check` — keyframe utilities
98
- - `tabs-sliding` — keyframe utilities
99
112
  - `text-swap` — keyframe utilities
100
- - `texts-reveal` — keyframe utilities
101
113
  - `thinking-states` — keyframe utilities
102
- - `tooltip` — keyframe utilities
103
114
 
104
115
  ## AI and chat (`src/ai`)
105
116
 
106
- - `composer` — Composer, ComposerProps
117
+ - `ai-button` — AiButton
107
118
  - `confirmation` — Confirmation, ConfirmationTitle, ConfirmationRequest, ConfirmationAccepted, ConfirmationRejected, ConfirmationActions, ConfirmationAction
119
+ - `generation-progress` — GenerationProgress
108
120
  - `loading-state` — PixelLoader
109
121
  - `prompt-input` — PromptInput, PromptInputBody, PromptInputToolbar, PromptInputTextarea, PromptInputSubmit
110
122
  - `reasoning` — Reasoning, ReasoningTrigger, ReasoningContent
@@ -116,7 +128,6 @@ The style layer lives in [`src/tokens.css`](./src/tokens.css) and the motion CSS
116
128
 
117
129
  ---
118
130
 
119
- Skipped on purpose: brand assets (logos, marks, brand renderer, language flags,
120
- locale switch), kanban, list, gantt and status (they live in `@heyramzi/tasks`), and charts
131
+ Skipped on purpose: brand assets (logos, marks, brand renderer), kanban, list, gantt and status (they live in `@heyramzi/tasks`), and charts
121
132
  (they live in `@heyramzi/charts`). The bot avatars
122
133
  are in `src/agents`, imported from `@heyramzi/ui/agents`.
package/README.md CHANGED
@@ -11,11 +11,12 @@ only a convenience.
11
11
  ## What is inside
12
12
 
13
13
  - `src/shadcn` shadcn-svelte primitives, generalized.
14
+ - `src/components` generic pieces on the primitives: segmented control, picker, copy button, data table, list page, hold to confirm and more.
14
15
  - `src/effects` animated borders, beams, marquee, spotlight, image reveal,
15
16
  image comparison, shimmer gradients and a theme toggle.
16
17
  - `src/animations` keyframe CSS for dropdowns, modals, tooltips, text swaps,
17
18
  success checks and the rest of the motion vocabulary.
18
- - `src/ai` chat and AI surfaces: composer, prompt input, response, reasoning, confirmation and loaders.
19
+ - `src/ai` chat and AI surfaces: prompt input, response, reasoning, confirmation and loaders.
19
20
  - `src/agents` bot avatars and a cast grid, imported from `@heyramzi/ui/agents`:
20
21
  `AgentAvatar` draws an eyes-only face from a name, role, shape and colour, and
21
22
  `AgentCast` lays a list of agents out as cards you can pick from.
@@ -41,6 +42,9 @@ Retheme by overriding any variable on `:root`, for example
41
42
  `--color-brand-indigo` or `--radius-lg`. Dark mode keys off a `.dark`
42
43
  class on `html`.
43
44
 
45
+ Rich text lives in [`@heyramzi/rich-editor`](https://github.com/heyramzi/ui/tree/main/packages/rich-editor),
46
+ so the kit doesn't pull Tiptap into every app.
47
+
44
48
  Charts live in their own package now,
45
49
  [`@heyramzi/charts`](https://github.com/heyramzi/ui/tree/main/packages/charts). It reads
46
50
  the same tokens, so import `tokens.css` once and both work.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@heyramzi/ui",
3
- "version": "7.0.0",
3
+ "version": "8.0.0",
4
4
  "description": "Svelte 5 UI primitives: effects, animations, and shared component CSS.",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -29,7 +29,16 @@
29
29
  "default": "./src/index.ts"
30
30
  },
31
31
  "./tokens.css": "./src/tokens.css",
32
- "./lib/*": "./src/lib/*",
32
+ "./lib/*.js": {
33
+ "svelte": "./src/lib/*.ts",
34
+ "types": "./src/lib/*.ts",
35
+ "default": "./src/lib/*.ts"
36
+ },
37
+ "./lib/*": {
38
+ "svelte": "./src/lib/*.ts",
39
+ "types": "./src/lib/*.ts",
40
+ "default": "./src/lib/*.ts"
41
+ },
33
42
  "./border-beam": {
34
43
  "svelte": "./src/effects/border-beam/BorderBeam.svelte",
35
44
  "default": "./src/effects/border-beam/BorderBeam.svelte"
@@ -55,6 +64,10 @@
55
64
  "svelte": "./src/effects/spotlight/Spotlight.svelte",
56
65
  "default": "./src/effects/spotlight/Spotlight.svelte"
57
66
  },
67
+ "./effects/magic-card": {
68
+ "svelte": "./src/effects/magic-card/MagicCard.svelte",
69
+ "default": "./src/effects/magic-card/MagicCard.svelte"
70
+ },
58
71
  "./effects/marquee": {
59
72
  "svelte": "./src/effects/marquee/Marquee.svelte",
60
73
  "default": "./src/effects/marquee/Marquee.svelte"
@@ -78,6 +91,10 @@
78
91
  "svelte": "./src/effects/progressive-blur/ProgressiveBlur.svelte",
79
92
  "default": "./src/effects/progressive-blur/ProgressiveBlur.svelte"
80
93
  },
94
+ "./effects/interactive-hover-button": {
95
+ "svelte": "./src/effects/interactive-hover-button/InteractiveHoverButton.svelte",
96
+ "default": "./src/effects/interactive-hover-button/InteractiveHoverButton.svelte"
97
+ },
81
98
  "./effects/image-comparison": {
82
99
  "svelte": "./src/effects/image-comparison/ImageComparison.svelte",
83
100
  "default": "./src/effects/image-comparison/ImageComparison.svelte"
@@ -115,16 +132,6 @@
115
132
  "./animations/*": {
116
133
  "default": "./src/animations/*"
117
134
  },
118
- "./showcase": {
119
- "svelte": "./src/showcase/index.ts",
120
- "types": "./src/showcase/index.ts",
121
- "default": "./src/showcase/index.ts"
122
- },
123
- "./showcase/kit": {
124
- "svelte": "./src/showcase/kit.ts",
125
- "types": "./src/showcase/kit.ts",
126
- "default": "./src/showcase/kit.ts"
127
- },
128
135
  "./shadcn/hooks/*": {
129
136
  "svelte": "./src/shadcn/hooks/*.ts",
130
137
  "types": "./src/shadcn/hooks/*.ts",
@@ -135,6 +142,11 @@
135
142
  "types": "./src/shadcn/*/index.ts",
136
143
  "default": "./src/shadcn/*/index.ts"
137
144
  },
145
+ "./components/*": {
146
+ "svelte": "./src/components/*/index.ts",
147
+ "types": "./src/components/*/index.ts",
148
+ "default": "./src/components/*/index.ts"
149
+ },
138
150
  "./shadcn/utilities.css": {
139
151
  "style": "./src/shadcn/utilities.css",
140
152
  "default": "./src/shadcn/utilities.css"
@@ -158,18 +170,16 @@
158
170
  },
159
171
  "dependencies": {
160
172
  "@heyramzi/utils": "^1.3.3",
161
- "@lucide/svelte": "^1.52.0",
162
173
  "@shadcn-svelte/primitives": "^0.0.1",
163
- "clsx": "^2.1.1",
164
174
  "marked": "^18.1.0",
165
175
  "phosphor-svelte": "^3.1.0",
166
176
  "shiki": "^4.5.0",
167
- "tailwind-merge": "^3.7.0",
168
177
  "tailwind-variants": "^3.3.1"
169
178
  },
170
179
  "devDependencies": {
171
180
  "@internationalized/date": "^3.12.4",
172
181
  "@sveltejs/vite-plugin-svelte": "^7.3.1",
182
+ "@types/node": "^26.6.4",
173
183
  "bits-ui": "^2.19.5",
174
184
  "jsdom": "^30.1.2",
175
185
  "mode-watcher": "^1.1.0",
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- /* Sync shadcn-svelte into src/shadcn and its demos into the showcase, three-way
2
+ /* Sync shadcn-svelte into src/shadcn and its demos into the site, three-way
3
3
  * per file against `.upstream/`. The rules and why: ../docs/decisions.md. */
4
4
 
5
5
  // pnpm sync:shadcn fetch, vendor, apply, report
@@ -8,7 +8,7 @@
8
8
  import { execFileSync } from "node:child_process";
9
9
  import { existsSync, readFileSync, readdirSync } from "node:fs";
10
10
  import { fileURLToPath } from "node:url";
11
- import { basename, dirname, resolve } from "node:path";
11
+ import { basename, dirname, relative, resolve } from "node:path";
12
12
  import {
13
13
  CHECK,
14
14
  classify,
@@ -56,16 +56,16 @@ const REROUTE = {
56
56
 
57
57
  const DOCS = "https://raw.githubusercontent.com/huntabyte/shadcn-svelte/main/docs";
58
58
  const DEMO_VENDOR = `${PKG}/.upstream/shadcn-demos`;
59
- const DEMO_LOCAL = `${PKG}/src/showcase/demos/shadcn`;
59
+ const DEMO_LOCAL = `${ROOT}/site/src/lib/shadcn-demos`;
60
60
  const DEMO_MANIFEST = `${DEMO_LOCAL}/index.ts`;
61
61
 
62
62
  /* The docs site's aliases. A demo is a docs file, not a registry payload, so it
63
63
  * carries `$lib/...` rather than the registry's `$UI$`. */
64
64
  const DEMO_ALIASES = [
65
- ["$lib/registry/ui/", "../src/shadcn"],
65
+ ["$lib/registry/ui/", "@heyramzi/ui/shadcn/"],
66
66
  // A handful reach their neighbour by relative path instead of the alias.
67
- ["../ui/", "../src/shadcn"],
68
- ["$lib/registry/hooks/", "../src/shadcn/hooks"],
67
+ ["../ui/", "@heyramzi/ui/shadcn/"],
68
+ ["$lib/registry/hooks/", "@heyramzi/ui/shadcn/hooks/"],
69
69
  ["$lib/utils.js", "@heyramzi/utils"],
70
70
  // The peer here is the runes build, published under its own name.
71
71
  ["@tabler/icons-svelte/", "@tabler/icons-svelte-runes/"],
@@ -107,12 +107,16 @@ const NO_DEMO = new Set([
107
107
  ]);
108
108
 
109
109
  const adapt = (text) => ALIASES.reduce((acc, [from, to]) => acc.replaceAll(from, to), text);
110
+ /* The site imports the kit the way a consumer does, so the exports map names a
111
+ * primitive without its `/index.js` and a hook without its `.js`. */
110
112
  const adaptDemo = (text) =>
111
- DEMO_ALIASES.reduce((acc, [from, to]) => acc.replaceAll(from, to), text);
113
+ DEMO_ALIASES.reduce((acc, [from, to]) => acc.replaceAll(from, to), text)
114
+ .replace(/(@heyramzi\/ui\/shadcn\/[a-z-]+)\/index\.js/g, "$1")
115
+ .replace(/(@heyramzi\/ui\/shadcn\/hooks\/[a-z-]+(?:\.svelte)?)\.js/g, "$1");
112
116
  const readIf = (path) => (existsSync(path) ? readFileSync(path, "utf8") : null);
113
117
  const route = (name, target) => `${PKG}/${REROUTE[`${name}/${target}`] ?? `src/shadcn/${target}`}`;
114
118
  /** Report a file by where it lives here, not by its upstream target. */
115
- const label = (path) => path.slice(PKG.length + 1);
119
+ const label = (path) => (path.startsWith(`${PKG}/`) ? path.slice(PKG.length + 1) : relative(ROOT, path));
116
120
 
117
121
  const pascal = (name) => name.replace(/(^|-)([a-z])/g, (_, __, c) => c.toUpperCase());
118
122
 
@@ -127,10 +131,10 @@ const meta = (doc, name) => {
127
131
  return { title: field("title") ?? pascal(name), note: field("description") ?? "" };
128
132
  };
129
133
 
130
- /** The demo's own shadcn imports, respelled as a consumer writes them. */
134
+ /** The demo's own shadcn imports, as it spells them for a consumer. */
131
135
  const publicImports = (demo) =>
132
- [...demo.matchAll(/import[^;]*?from\s+"#src\/shadcn\/([^"]+?)(?:\/index\.js)?";/g)]
133
- .map((m) => m[0].replace(/"[^"]+"/, `"@heyramzi/ui/shadcn/${m[1]}"`))
136
+ [...demo.matchAll(/import[^;]*?from\s+"@heyramzi\/ui\/shadcn\/[^"]+";/g)]
137
+ .map((m) => m[0])
134
138
  .join("\n");
135
139
 
136
140
  /* The section's list, generated: a primitive reaches the page by being synced,
@@ -145,7 +149,7 @@ async function writeManifest(demos) {
145
149
  " * own, and the sync rewrites this list. */",
146
150
  'import type { Component } from "svelte";',
147
151
  ...demos.map(
148
- (d) => `import ${pascal(d.name)}Demo from "../src/showcase/demos/shadcn/${d.name}.svelte";`,
152
+ (d) => `import ${pascal(d.name)}Demo from "./${d.name}.svelte";`,
149
153
  ),
150
154
  "",
151
155
  "export type ShadcnDemo = {",
@@ -267,7 +271,7 @@ const ours = readdirSync(LOCAL, { withFileTypes: true })
267
271
  for (const name of ours) buckets.unported.push(`${name} — in src/shadcn, not in the registry`);
268
272
 
269
273
  /* The docs site's own demo for each primitive, vendored on the same three-way
270
- * rule. Upstream writes them; the showcase renders them. */
274
+ * rule. Upstream writes them; the site renders them. */
271
275
  const demoNames = [...Object.keys(entries), ...LOCAL_ONLY]
272
276
  .filter((name) => !NO_DEMO.has(name))
273
277
  .toSorted();
@@ -46,7 +46,7 @@ const SRC = `${PKG}/src`;
46
46
  */
47
47
 
48
48
  /*
49
- * Most land in src/animations. Five do not, because a component already did the job and one behaviour gets one implementation: the last five entries name where each went instead.
49
+ * Fourteen of these name the component that owns the motion instead of a file in src/animations.
50
50
  */
51
51
 
52
52
  /*
@@ -55,31 +55,31 @@ const SRC = `${PKG}/src`;
55
55
  const PORTED = {
56
56
  "card-resize": "animations/resize.css",
57
57
  "number-pop-in": "animations/digit-pop-in.css",
58
- "notification-badge": "animations/notification-badge.css",
58
+ "notification-badge": "shadcn/badge/badge.svelte",
59
59
  "text-states-swap": "animations/text-swap.css",
60
60
  "menu-dropdown": "animations/dropdown.css",
61
61
  "modal-open-close": "animations/modal.css",
62
- "panel-reveal": "animations/panel.css",
62
+ "panel-reveal": "shadcn/sheet/sheet-content.svelte",
63
63
  "page-side-by-side": "animations/page-side-by-side.css",
64
- "icon-swap": "animations/icon-swap.css",
64
+ "icon-swap": "effects/theme-toggle/ThemeToggle.svelte",
65
65
  "success-check": "animations/success-check.css",
66
66
  "avatar-group-hover": "animations/avatar-group-hover.css",
67
67
  "error-state-shake": "animations/input-shake.css",
68
68
  "input-clear-with-dissolve": "animations/input-clear-dissolve.css",
69
- "skeleton-loader-and-reveal": "animations/skeleton-reveal.css",
70
- "texts-reveal": "animations/texts-reveal.css",
71
- "tabs-sliding": "animations/tabs-sliding.css",
69
+ "skeleton-loader-and-reveal": "shadcn/skeleton/skeleton.svelte",
70
+ "texts-reveal": "effects/reveal/TextEffect.svelte",
71
+ "tabs-sliding": "shadcn/tabs/tabs-list.svelte",
72
72
  "shimmer-text": "animations/shimmer-text.css",
73
- "tooltip-open-close": "animations/tooltip.css",
73
+ "tooltip-open-close": "shadcn/tooltip/tooltip-content.svelte",
74
74
  "3d-tilt": "animations/card-tilt.css",
75
75
  "dropdown-menu-morph": "animations/plus-menu-morph.css",
76
- accordion: "animations/accordion.css",
76
+ accordion: "shadcn/accordion/accordion-content.svelte",
77
77
  "like-button": "animations/like-button.css",
78
78
  "learn-more-hover": "animations/learn-more-hover.css",
79
79
  "spinning-counter": "animations/spinning-counter.css",
80
80
  "thinking-states": "animations/thinking-states.css",
81
- "reasoning-stream": "animations/reasoning-stream.css",
82
- "streaming-text": "animations/streaming-text.css",
81
+ "reasoning-stream": "ai/reasoning/ReasoningContent.svelte",
82
+ "streaming-text": "effects/reveal/TextEffect.svelte",
83
83
  toggle: "shadcn/switch/switch.svelte",
84
84
  "checkbox-check": "shadcn/checkbox/checkbox.svelte",
85
85
  "toast-open-close": "shadcn/sonner/sonner.svelte",
@@ -0,0 +1,86 @@
1
+ <script lang="ts" module>
2
+ import type { ButtonProps } from "../../shadcn/button/index.js";
3
+
4
+ export type AiStatus = "idle" | "processing" | "done";
5
+
6
+ export interface AiButtonProps {
7
+ status?: AiStatus;
8
+ label?: string;
9
+ processingLabel?: string;
10
+ variant?: ButtonProps["variant"];
11
+ size?: ButtonProps["size"];
12
+ disabled?: boolean;
13
+ onclick?: (e: MouseEvent) => void;
14
+ class?: string;
15
+ iconOnly?: boolean;
16
+ }
17
+ </script>
18
+
19
+ <script lang="ts">
20
+ // =========================
21
+ // IMPORTS
22
+ // =========================
23
+ import { cn } from "@heyramzi/utils";
24
+ import { Sparkle } from "phosphor-svelte";
25
+ import { Spinner } from "../../shadcn/spinner/index.js";
26
+ import { Button } from "../../shadcn/button/index.js";
27
+
28
+ // =========================
29
+ // PROPS
30
+ // =========================
31
+ let {
32
+ status = "idle",
33
+ label = "Generate",
34
+ processingLabel = "Processing...",
35
+ variant = "outline",
36
+ size = "sm",
37
+ disabled = false,
38
+ onclick,
39
+ class: className,
40
+ iconOnly = false,
41
+ }: AiButtonProps = $props();
42
+ </script>
43
+
44
+ <!-- ===========================
45
+ MARKUP
46
+ =========================== -->
47
+ {#if iconOnly}
48
+ <Button
49
+ {variant}
50
+ size="sm"
51
+ icon
52
+ disabled={disabled || status === "processing"}
53
+ onclick={onclick}
54
+ class={cn(
55
+ "relative",
56
+ status === "processing" && "pointer-events-none",
57
+ className,
58
+ )}
59
+ >
60
+ {#if status === "processing"}
61
+ <Spinner class="size-4" />
62
+ {:else}
63
+ <Sparkle class="size-4" weight="fill" />
64
+ {/if}
65
+ </Button>
66
+ {:else}
67
+ <Button
68
+ {variant}
69
+ {size}
70
+ disabled={disabled || status === "processing"}
71
+ onclick={onclick}
72
+ class={cn(
73
+ "gap-1.5",
74
+ status === "processing" && "pointer-events-none",
75
+ className,
76
+ )}
77
+ >
78
+ {#if status === "processing"}
79
+ <Spinner class="size-3.5" />
80
+ <span>{processingLabel}</span>
81
+ {:else}
82
+ <Sparkle class="size-3.5" weight="fill" />
83
+ <span>{label}</span>
84
+ {/if}
85
+ </Button>
86
+ {/if}
@@ -0,0 +1,4 @@
1
+ import AiButton from "./AiButton.svelte";
2
+ import type { AiButtonProps, AiStatus } from "./AiButton.svelte";
3
+
4
+ export { AiButton, type AiButtonProps, type AiStatus };
@@ -23,15 +23,15 @@
23
23
  ...rest
24
24
  }: ConfirmationProps = $props();
25
25
 
26
- // WHY: setContext runs once on mount but the value is referenced reactively via the proxy Svelte sets up on objects passed to setContext.
27
-
28
- // State changes rerun any $derived in child components.
29
- const ctx = $state({ kind, executing });
30
- $effect(() => {
31
- ctx.kind = kind;
32
- ctx.executing = executing;
26
+ // WHY getters: setContext runs once on mount, so the parts read the props through these and rerun their $derived when a prop changes.
27
+ setConfirmationContext({
28
+ get kind() {
29
+ return kind;
30
+ },
31
+ get executing() {
32
+ return executing;
33
+ },
33
34
  });
34
- setConfirmationContext(ctx);
35
35
  </script>
36
36
 
37
37
  {#if kind !== "idle"}
@@ -5,8 +5,8 @@ const CONFIRMATION_CONTEXT_KEY = Symbol("confirmation-context");
5
5
  export type ConfirmationState = "idle" | "requested" | "accepted" | "rejected" | "failed";
6
6
 
7
7
  export interface ConfirmationContextValue {
8
- kind: ConfirmationState;
9
- executing: boolean;
8
+ readonly kind: ConfirmationState;
9
+ readonly executing: boolean;
10
10
  }
11
11
 
12
12
  export function setConfirmationContext(value: ConfirmationContextValue) {