@heyramzi/ui 6.1.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 (332) hide show
  1. package/COMPONENTS.md +32 -40
  2. package/README.md +10 -4
  3. package/package.json +31 -29
  4. package/scripts/sync-shadcn.mjs +29 -16
  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 -24
  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 +17 -17
  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/sliding-pill.ts +68 -0
  118. package/src/lib/theme-transition.ts +41 -13
  119. package/src/lib/tone.ts +48 -0
  120. package/src/shadcn/accordion/accordion-trigger.svelte +15 -6
  121. package/src/shadcn/alert/alert.svelte +3 -1
  122. package/src/shadcn/badge/badge.svelte +8 -7
  123. package/src/shadcn/breadcrumb/breadcrumb-ellipsis.svelte +2 -2
  124. package/src/shadcn/breadcrumb/breadcrumb-separator.svelte +2 -2
  125. package/src/shadcn/calendar/calendar-month-select.svelte +2 -2
  126. package/src/shadcn/calendar/calendar-next-button.svelte +2 -2
  127. package/src/shadcn/calendar/calendar-prev-button.svelte +2 -2
  128. package/src/shadcn/calendar/calendar-year-select.svelte +2 -2
  129. package/src/shadcn/calendar/calendar.svelte +6 -0
  130. package/src/shadcn/code-block/code-block-actions.svelte +23 -0
  131. package/src/shadcn/code-block/code-block-content.svelte +55 -0
  132. package/src/shadcn/code-block/code-block-copy-button.svelte +10 -0
  133. package/src/shadcn/code-block/code-block-footer.svelte +20 -0
  134. package/src/shadcn/code-block/code-block-header.svelte +23 -0
  135. package/src/shadcn/code-block/code-block-line.svelte +71 -0
  136. package/src/shadcn/code-block/code-block-title.svelte +23 -0
  137. package/src/shadcn/code-block/code-block.svelte +47 -0
  138. package/src/shadcn/code-block/index.ts +42 -0
  139. package/src/shadcn/command/index.ts +3 -0
  140. package/src/shadcn/field/index.ts +3 -0
  141. package/src/shadcn/field/simple-field.svelte +71 -0
  142. package/src/shadcn/field/simple-field.test.ts +47 -0
  143. package/src/shadcn/hooks/highlighter.ts +132 -0
  144. package/src/shadcn/hooks/use-highlighted-code.svelte.ts +98 -0
  145. package/src/shadcn/kbd/index.ts +10 -0
  146. package/src/shadcn/kbd/kbd-group.svelte +20 -0
  147. package/src/shadcn/kbd/kbd.svelte +23 -0
  148. package/src/shadcn/message-scroller/index.ts +28 -0
  149. package/src/shadcn/message-scroller/message-scroller-button.svelte +52 -0
  150. package/src/shadcn/message-scroller/message-scroller-content.svelte +17 -0
  151. package/src/shadcn/message-scroller/message-scroller-item.svelte +22 -0
  152. package/src/shadcn/message-scroller/message-scroller-provider.svelte +7 -0
  153. package/src/shadcn/message-scroller/message-scroller-viewport.svelte +20 -0
  154. package/src/shadcn/message-scroller/message-scroller.svelte +20 -0
  155. package/src/shadcn/radio-group/radio-group-item.svelte +3 -2
  156. package/src/shadcn/sheet/sheet-content.svelte +1 -0
  157. package/src/shadcn/sheet/sheet.css +48 -0
  158. package/src/shadcn/sonner/sonner.svelte +7 -10
  159. package/src/shadcn/tabs/tabs-list.svelte +13 -2
  160. package/src/shadcn/tabs/tabs-trigger.svelte +1 -1
  161. package/src/shadcn/toggle-group/toggle-group.svelte +10 -3
  162. package/src/shadcn/trace/index.ts +29 -0
  163. package/src/shadcn/trace/trace-collapsible-content.svelte +29 -0
  164. package/src/shadcn/trace/trace-collapsible-trigger.svelte +29 -0
  165. package/src/shadcn/trace/trace-collapsible.svelte +20 -0
  166. package/src/shadcn/trace/trace-description.svelte +20 -0
  167. package/src/shadcn/trace/trace-icon.svelte +24 -0
  168. package/src/shadcn/trace/trace-line.svelte +31 -0
  169. package/src/shadcn/trace/trace-title.svelte +20 -0
  170. package/src/shadcn/trace/trace.svelte +23 -0
  171. package/src/ai/composer/Composer.css +0 -108
  172. package/src/ai/composer/Composer.svelte +0 -111
  173. package/src/ai/composer/index.ts +0 -10
  174. package/src/ai/conversation/Conversation.svelte +0 -28
  175. package/src/ai/conversation/ConversationContent.svelte +0 -35
  176. package/src/ai/conversation/ConversationEmptyState.svelte +0 -46
  177. package/src/ai/conversation/ConversationScrollButton.svelte +0 -51
  178. package/src/ai/conversation/index.ts +0 -33
  179. package/src/ai/conversation/stick-to-bottom-context.svelte.ts +0 -131
  180. package/src/animations/accordion.css +0 -58
  181. package/src/animations/icon-swap.css +0 -43
  182. package/src/animations/notification-badge.css +0 -81
  183. package/src/animations/panel.css +0 -86
  184. package/src/animations/reasoning-stream.css +0 -49
  185. package/src/animations/skeleton-reveal.css +0 -97
  186. package/src/animations/streaming-text.css +0 -31
  187. package/src/animations/tabs-sliding.css +0 -83
  188. package/src/animations/texts-reveal.css +0 -70
  189. package/src/animations/tooltip.css +0 -72
  190. package/src/animations/view-transition-reveal.ts +0 -74
  191. package/src/charts/animated-value.css +0 -7
  192. package/src/charts/animated-value.svelte +0 -110
  193. package/src/charts/area-chart.css +0 -29
  194. package/src/charts/area-chart.svelte +0 -195
  195. package/src/charts/bar-chart.css +0 -119
  196. package/src/charts/bar-chart.svelte +0 -269
  197. package/src/charts/charts.css +0 -201
  198. package/src/charts/crosshair.svelte +0 -35
  199. package/src/charts/donut-chart.css +0 -56
  200. package/src/charts/donut-chart.svelte +0 -158
  201. package/src/charts/edge-fade.svelte +0 -43
  202. package/src/charts/edge-fade.ts +0 -16
  203. package/src/charts/figure.css +0 -100
  204. package/src/charts/figure.svelte +0 -122
  205. package/src/charts/gauge-chart.css +0 -94
  206. package/src/charts/gauge-chart.svelte +0 -303
  207. package/src/charts/hover-band.test.ts +0 -30
  208. package/src/charts/hover-band.ts +0 -21
  209. package/src/charts/hover-focus.svelte +0 -85
  210. package/src/charts/index.ts +0 -30
  211. package/src/charts/legend.css +0 -131
  212. package/src/charts/legend.svelte +0 -112
  213. package/src/charts/line-chart.css +0 -26
  214. package/src/charts/line-chart.svelte +0 -256
  215. package/src/charts/motion.ts +0 -19
  216. package/src/charts/number-chart.css +0 -168
  217. package/src/charts/number-chart.svelte +0 -177
  218. package/src/charts/primitives/chart-container.svelte +0 -57
  219. package/src/charts/primitives/chart-style.svelte +0 -36
  220. package/src/charts/primitives/chart-tooltip.svelte +0 -161
  221. package/src/charts/primitives/chart-utils.ts +0 -54
  222. package/src/charts/primitives/index.ts +0 -11
  223. package/src/charts/reveal.svelte +0 -61
  224. package/src/charts/ring-chart.css +0 -96
  225. package/src/charts/ring-chart.svelte +0 -158
  226. package/src/charts/sparkline.css +0 -45
  227. package/src/charts/sparkline.svelte +0 -140
  228. package/src/charts/stat-card.css +0 -103
  229. package/src/charts/stat-card.svelte +0 -267
  230. package/src/charts/time-series-chart.css +0 -28
  231. package/src/charts/time-series-chart.svelte +0 -179
  232. package/src/charts/trend-pill.css +0 -38
  233. package/src/charts/trend-pill.svelte +0 -48
  234. package/src/lib/hooks/is-mobile.svelte.ts +0 -11
  235. package/src/lib/utils.ts +0 -45
  236. package/src/showcase/AiSection.svelte +0 -157
  237. package/src/showcase/AnimationsSection.svelte +0 -1658
  238. package/src/showcase/ChartsSection.svelte +0 -458
  239. package/src/showcase/EffectsSection.svelte +0 -152
  240. package/src/showcase/ShadcnSection.svelte +0 -27
  241. package/src/showcase/ShowcaseImport.svelte +0 -126
  242. package/src/showcase/ShowcaseList.svelte +0 -132
  243. package/src/showcase/ShowcaseNav.svelte +0 -247
  244. package/src/showcase/ShowcaseSection.svelte +0 -112
  245. package/src/showcase/ShowcaseShell.svelte +0 -55
  246. package/src/showcase/ShowcaseStage.svelte +0 -342
  247. package/src/showcase/ShowcaseVariant.svelte +0 -109
  248. package/src/showcase/assets/image-reveal/art-1.jpg +0 -0
  249. package/src/showcase/assets/image-reveal/art-2.jpg +0 -0
  250. package/src/showcase/assets/image-reveal/art-3.jpg +0 -0
  251. package/src/showcase/check.svg +0 -1
  252. package/src/showcase/chevron-arms.svg +0 -2
  253. package/src/showcase/chevron-down.svg +0 -1
  254. package/src/showcase/copy.svg +0 -2
  255. package/src/showcase/demos/ai/confirmation.svelte +0 -59
  256. package/src/showcase/demos/ai/conversation.svelte +0 -59
  257. package/src/showcase/demos/ai/loading-state.svelte +0 -19
  258. package/src/showcase/demos/ai/prompt-input.svelte +0 -57
  259. package/src/showcase/demos/ai/reasoning.svelte +0 -19
  260. package/src/showcase/demos/ai/thinking-dots.svelte +0 -15
  261. package/src/showcase/demos/ai/voice-waveform.svelte +0 -24
  262. package/src/showcase/demos/effects/animated-beam.svelte +0 -50
  263. package/src/showcase/demos/effects/animated-group.svelte +0 -47
  264. package/src/showcase/demos/effects/border-beam-default.svelte +0 -20
  265. package/src/showcase/demos/effects/border-beam-line.svelte +0 -20
  266. package/src/showcase/demos/effects/border-beam-mono.svelte +0 -20
  267. package/src/showcase/demos/effects/border-beam-sunset.svelte +0 -20
  268. package/src/showcase/demos/effects/image-comparison.svelte +0 -25
  269. package/src/showcase/demos/effects/image-reveal.svelte +0 -49
  270. package/src/showcase/demos/effects/in-view.svelte +0 -41
  271. package/src/showcase/demos/effects/integrations-hub.svelte +0 -82
  272. package/src/showcase/demos/effects/magnetic.svelte +0 -31
  273. package/src/showcase/demos/effects/marquee.svelte +0 -33
  274. package/src/showcase/demos/effects/progressive-blur.svelte +0 -47
  275. package/src/showcase/demos/effects/spotlight.svelte +0 -40
  276. package/src/showcase/demos/effects/text-effect.svelte +0 -55
  277. package/src/showcase/demos/shadcn/accordion.svelte +0 -45
  278. package/src/showcase/demos/shadcn/alert-dialog.svelte +0 -23
  279. package/src/showcase/demos/shadcn/alert.svelte +0 -30
  280. package/src/showcase/demos/shadcn/attachment.svelte +0 -71
  281. package/src/showcase/demos/shadcn/avatar.svelte +0 -30
  282. package/src/showcase/demos/shadcn/badge.svelte +0 -26
  283. package/src/showcase/demos/shadcn/breadcrumb.svelte +0 -34
  284. package/src/showcase/demos/shadcn/bubble.svelte +0 -36
  285. package/src/showcase/demos/shadcn/button.svelte +0 -11
  286. package/src/showcase/demos/shadcn/calendar.svelte +0 -8
  287. package/src/showcase/demos/shadcn/card.svelte +0 -39
  288. package/src/showcase/demos/shadcn/checkbox.svelte +0 -39
  289. package/src/showcase/demos/shadcn/collapsible.svelte +0 -20
  290. package/src/showcase/demos/shadcn/command.svelte +0 -48
  291. package/src/showcase/demos/shadcn/context-menu.svelte +0 -54
  292. package/src/showcase/demos/shadcn/demo-harness.svelte +0 -12
  293. package/src/showcase/demos/shadcn/demos.test.ts +0 -20
  294. package/src/showcase/demos/shadcn/dialog.svelte +0 -38
  295. package/src/showcase/demos/shadcn/dropdown-menu.svelte +0 -59
  296. package/src/showcase/demos/shadcn/empty.svelte +0 -29
  297. package/src/showcase/demos/shadcn/field.svelte +0 -115
  298. package/src/showcase/demos/shadcn/hover-card.svelte +0 -32
  299. package/src/showcase/demos/shadcn/index.ts +0 -358
  300. package/src/showcase/demos/shadcn/input-otp.svelte +0 -19
  301. package/src/showcase/demos/shadcn/input.svelte +0 -5
  302. package/src/showcase/demos/shadcn/label.svelte +0 -11
  303. package/src/showcase/demos/shadcn/marker.svelte +0 -30
  304. package/src/showcase/demos/shadcn/message.svelte +0 -75
  305. package/src/showcase/demos/shadcn/popover.svelte +0 -36
  306. package/src/showcase/demos/shadcn/progress.svelte +0 -13
  307. package/src/showcase/demos/shadcn/radio-group.svelte +0 -19
  308. package/src/showcase/demos/shadcn/scroll-area.svelte +0 -18
  309. package/src/showcase/demos/shadcn/select.svelte +0 -29
  310. package/src/showcase/demos/shadcn/separator.svelte +0 -12
  311. package/src/showcase/demos/shadcn/sheet.svelte +0 -48
  312. package/src/showcase/demos/shadcn/skeleton.svelte +0 -11
  313. package/src/showcase/demos/shadcn/slider.svelte +0 -7
  314. package/src/showcase/demos/shadcn/sonner.svelte +0 -18
  315. package/src/showcase/demos/shadcn/spinner.svelte +0 -11
  316. package/src/showcase/demos/shadcn/switch.svelte +0 -9
  317. package/src/showcase/demos/shadcn/table.svelte +0 -76
  318. package/src/showcase/demos/shadcn/tabs.svelte +0 -62
  319. package/src/showcase/demos/shadcn/textarea.svelte +0 -5
  320. package/src/showcase/demos/shadcn/toggle-group.svelte +0 -18
  321. package/src/showcase/demos/shadcn/toggle.svelte +0 -14
  322. package/src/showcase/demos/shadcn/tooltip.svelte +0 -13
  323. package/src/showcase/heart.svg +0 -1
  324. package/src/showcase/index.ts +0 -38
  325. package/src/showcase/kit.test.ts +0 -72
  326. package/src/showcase/kit.ts +0 -17
  327. package/src/showcase/plus.svg +0 -1
  328. package/src/showcase/showcase-shell.css +0 -91
  329. package/src/showcase/stacked-section.css +0 -15
  330. package/src/showcase/success-check.svg +0 -1
  331. package/src/showcase/types.ts +0 -29
  332. package/src/svg-raw.d.ts +0 -7
@@ -1,70 +0,0 @@
1
- /* Transitions.dev — Texts reveal */
2
- /* Source: https://github.com/Jakubantalik/transitions.dev */
3
-
4
- /*
5
- Usage:
6
- <div class="t-stagger">
7
- <strong class="t-stagger-line t-stagger-line--1">…</strong>
8
- <span class="t-stagger-line t-stagger-line--2">…</span>
9
- </div>
10
-
11
- State:
12
- Add .is-shown to play the staggered entrance. Add .is-hiding
13
- (and remove .is-shown) to fade out in place over 200ms,
14
- independent of the entrance timing.
15
-
16
- Add more lines with .t-stagger-line--N and
17
- transition-delay: calc(var(--stagger-stagger) * (N - 1)).
18
- */
19
-
20
- :root {
21
- --stagger-dur: var(--duration-very-slow, 500ms);
22
- --stagger-distance: var(--distance-medium, 12px);
23
- --stagger-stagger: var(--duration-stagger, 40ms);
24
- --stagger-blur: var(--blur-medium, 3px);
25
- --stagger-ease: var(--ease-smooth-out, cubic-bezier(0.22, 1, 0.36, 1));
26
- }
27
-
28
- /* Lines start translated down + blurred + invisible; .is-shown
29
- on the parent flips them to their resting state. The second
30
- line's transition-delay holds it back by --stagger-stagger so
31
- the eye lands on the headline first. */
32
- .t-stagger-line {
33
- display: block;
34
- opacity: 0;
35
- transform: translateY(var(--stagger-distance));
36
- filter: blur(var(--stagger-blur));
37
- transition:
38
- opacity var(--stagger-dur) var(--stagger-ease),
39
- transform var(--stagger-dur) var(--stagger-ease),
40
- filter var(--stagger-dur) var(--stagger-ease);
41
- will-change: transform, opacity, filter;
42
- }
43
- .t-stagger-line--2 {
44
- transition-delay: var(--stagger-stagger);
45
- }
46
-
47
- .t-stagger.is-shown .t-stagger-line {
48
- opacity: 1;
49
- transform: translateY(0);
50
- filter: blur(0);
51
- }
52
- /* Exit decouples from the stagger: same fade for every line,
53
- no Y return, no blur — so the disappearance reads as a single
54
- quiet fade instead of a reverse reveal. */
55
- .t-stagger.is-hiding .t-stagger-line {
56
- opacity: 0;
57
- transform: translateY(0);
58
- filter: blur(0);
59
- transition:
60
- opacity 200ms ease,
61
- transform 0s linear,
62
- filter 0s linear;
63
- transition-delay: 0s;
64
- }
65
-
66
- @media (prefers-reduced-motion: reduce) {
67
- .t-stagger-line {
68
- transition: none !important;
69
- }
70
- }
@@ -1,72 +0,0 @@
1
- /* Transitions.dev — Tooltip open / close */
2
- /* Source: https://github.com/Jakubantalik/transitions.dev */
3
-
4
- /*
5
- Usage:
6
- <span class="t-tt-wrap">
7
- <button class="t-tt-trigger" aria-describedby="tt-1">…</button>
8
- <span class="t-tt" id="tt-1" role="tooltip">Tooltip text</span>
9
- </span>
10
-
11
- Pure CSS — no JS. The wrap (not the trigger) is the hover
12
- target so the pointer can drift onto the tooltip without
13
- flicker. transition-delay only applies in the hover/focus
14
- rule, so leaving snaps it to 0 and the disappear plays
15
- immediately.
16
- */
17
-
18
- :root {
19
- --tt-in-dur: var(--duration-quick, 150ms);
20
- --tt-out-dur: 50ms;
21
- --tt-scale: var(--scale-small, 0.98);
22
- --tt-delay: 80ms;
23
- --tt-in-ease: var(--ease-out, ease-out);
24
- --tt-out-ease: var(--ease-out, ease-out);
25
- --tt-bg: #ffffff;
26
- --tt-fg: #2f2f2f;
27
- }
28
-
29
- .t-tt-wrap {
30
- position: relative;
31
- display: inline-block;
32
- }
33
- .t-tt {
34
- position: absolute;
35
- bottom: calc(100% + 8px);
36
- left: 50%;
37
- transform: translate(-50%, 0) scale(var(--tt-scale));
38
- transform-origin: 50% 100%;
39
- padding: 8px 12px;
40
- border-radius: 8px;
41
- background: var(--tt-bg);
42
- color: var(--tt-fg);
43
- white-space: nowrap;
44
- box-shadow:
45
- 0 0 0 1px rgba(0, 0, 0, 0.06),
46
- 0 2px 6px 0 rgba(0, 0, 0, 0.05),
47
- 0 4px 42px 0 rgba(0, 0, 0, 0.06);
48
- opacity: 0;
49
- pointer-events: none;
50
- /* Default rule controls the LEAVE state. transition-delay
51
- stays unset so leaving plays without delay. */
52
- transition:
53
- opacity var(--tt-out-dur) var(--tt-out-ease),
54
- transform var(--tt-out-dur) var(--tt-out-ease);
55
- }
56
- /* The delay belongs ONLY to the hover rule so leaving the
57
- trigger snaps the delay back to 0 and the disappear plays
58
- immediately. */
59
- .t-tt-wrap:hover .t-tt,
60
- .t-tt-trigger:focus-visible + .t-tt {
61
- opacity: 1;
62
- transform: translate(-50%, 0) scale(1);
63
- transition-duration: var(--tt-in-dur);
64
- transition-timing-function: var(--tt-in-ease);
65
- transition-delay: var(--tt-delay);
66
- }
67
-
68
- @media (prefers-reduced-motion: reduce) {
69
- .t-tt {
70
- transition: none !important;
71
- }
72
- }
@@ -1,74 +0,0 @@
1
- export type ViewTransitionRevealOrigin = MouseEvent | { x: number; y: number } | HTMLElement;
2
-
3
- export type ViewTransitionRevealOptions = {
4
- duration?: number;
5
- easing?: string;
6
- };
7
-
8
- const STYLE_ID = "heyramzi-view-transition-reveal";
9
-
10
- export function viewTransitionReveal(
11
- origin: ViewTransitionRevealOrigin,
12
- apply: () => void,
13
- options?: ViewTransitionRevealOptions,
14
- ): void {
15
- const prefersReduced = window.matchMedia("(prefers-reduced-motion: reduce)").matches;
16
-
17
- // WHY: feature-detect both API presence and reduced-motion to keep callers
18
- // from having to branch.
19
- if (typeof document === "undefined" || !document.startViewTransition || prefersReduced) {
20
- apply();
21
- return;
22
- }
23
-
24
- const { x, y } = resolveOrigin(origin);
25
- const duration = options?.duration ?? 400;
26
- const easing = options?.easing ?? "ease-in-out";
27
- const endRadius = Math.hypot(
28
- Math.max(x, window.innerWidth - x),
29
- Math.max(y, window.innerHeight - y),
30
- );
31
-
32
- ensureStyles();
33
-
34
- const transition = document.startViewTransition(() => {
35
- apply();
36
- });
37
-
38
- transition.ready.then(() => {
39
- document.documentElement.animate(
40
- {
41
- clipPath: [`circle(0px at ${x}px ${y}px)`, `circle(${endRadius}px at ${x}px ${y}px)`],
42
- },
43
- {
44
- duration,
45
- easing,
46
- pseudoElement: "::view-transition-new(root)",
47
- },
48
- );
49
- });
50
- }
51
-
52
- function resolveOrigin(origin: ViewTransitionRevealOrigin): { x: number; y: number } {
53
- if (origin instanceof HTMLElement) {
54
- const rect = origin.getBoundingClientRect();
55
- return { x: rect.left + rect.width / 2, y: rect.top + rect.height / 2 };
56
- }
57
- if (typeof MouseEvent !== "undefined" && origin instanceof MouseEvent) {
58
- const target = origin.currentTarget instanceof HTMLElement ? origin.currentTarget : null;
59
- if (target) {
60
- const rect = target.getBoundingClientRect();
61
- return { x: rect.left + rect.width / 2, y: rect.top + rect.height / 2 };
62
- }
63
- return { x: origin.clientX, y: origin.clientY };
64
- }
65
- return { x: origin.x, y: origin.y };
66
- }
67
-
68
- function ensureStyles(): void {
69
- if (document.getElementById(STYLE_ID)) return;
70
- const style = document.createElement("style");
71
- style.id = STYLE_ID;
72
- style.textContent = `::view-transition-old(root),::view-transition-new(root){animation:none;mix-blend-mode:normal;}`;
73
- document.head.appendChild(style);
74
- }
@@ -1,7 +0,0 @@
1
- /* Styles for AnimatedValue. Plain stylesheet (see area-chart.css for why).
2
- `.hr-animated-value` is the component's own namespaced fallback for tabular
3
- figures (it also carries the `tabular-nums` utility class). */
4
-
5
- .hr-animated-value {
6
- font-variant-numeric: tabular-nums;
7
- }
@@ -1,110 +0,0 @@
1
- <script lang="ts">
2
- // =========================
3
- // IMPORTS
4
- // =========================
5
- import "./animated-value.css";
6
- import { untrack } from "svelte";
7
- import { cn } from "@heyramzi/utils";
8
-
9
- // =========================
10
- // TYPES
11
- // =========================
12
- type Props = {
13
- /** Target number. The display counts up to it on mount and tweens on change. */
14
- value: number;
15
- /** Fixed decimal places when no `formatOptions` is given. */
16
- decimals?: number;
17
- /** Count-up duration in ms. */
18
- duration?: number;
19
- /** Custom formatter for the live number. Wins over `formatOptions`/`decimals`. */
20
- format?: (value: number) => string;
21
- /** Intl number formatting (currency, compact, percent, ...). Wins over `decimals`. */
22
- formatOptions?: Intl.NumberFormatOptions;
23
- /** BCP-47 locale for `formatOptions`. */
24
- locale?: string;
25
- /** Rendered before the number. */
26
- prefix?: string;
27
- /** Rendered after the number. */
28
- suffix?: string;
29
- class?: string;
30
- style?: string;
31
- };
32
-
33
- // =========================
34
- // PROPS
35
- // =========================
36
- let {
37
- value,
38
- decimals = 0,
39
- duration = 800,
40
- format,
41
- formatOptions,
42
- locale,
43
- prefix,
44
- suffix,
45
- class: className,
46
- style,
47
- }: Props = $props();
48
-
49
- // =========================
50
- // STATE
51
- // =========================
52
- let displayed = $state(0);
53
- let started = $state(false);
54
-
55
- // =========================
56
- // DERIVED
57
- // =========================
58
- const formatter = $derived(formatOptions ? new Intl.NumberFormat(locale, formatOptions) : null);
59
- const currentValue = $derived(started ? displayed : value);
60
- const text = $derived(
61
- format
62
- ? format(currentValue)
63
- : formatter
64
- ? formatter.format(currentValue)
65
- : currentValue.toFixed(decimals),
66
- );
67
-
68
- // ========================= EFFECTS ========================= WHY: $effect only runs in the browser, so SSR renders the final value (no flash).
69
-
70
- // `value` is the sole tracked dependency; `displayed` is read and written inside untrack() so the per-frame writes don't retrigger the effect (that self-dependency loops and Svelte bails, freezing the number).
71
-
72
- // The first run sweeps from 0; later value changes tween from the current display.
73
- $effect(() => {
74
- const target = value;
75
- let raf = 0;
76
- untrack(() => {
77
- const reduced =
78
- typeof window !== "undefined" &&
79
- window.matchMedia("(prefers-reduced-motion: reduce)").matches;
80
-
81
- const from = started ? displayed : 0;
82
- started = true;
83
-
84
- // WHY: snap (no tween) when motion is off, the delta is tiny, or the tab
85
-
86
- // is hidden. rAF is paused in background tabs, so animating there would leave the number stale until the tab is shown; snapping keeps it correct.
87
- if (reduced || document.hidden || Math.abs(target - from) < 0.005) {
88
- displayed = target;
89
- return;
90
- }
91
-
92
- const start = performance.now();
93
- const tick = (now: number) => {
94
- const t = Math.min((now - start) / duration, 1);
95
- const eased = 1 - (1 - t) ** 3;
96
- displayed = from + (target - from) * eased;
97
- if (t < 1) raf = requestAnimationFrame(tick);
98
- };
99
- raf = requestAnimationFrame(tick);
100
- });
101
- return () => cancelAnimationFrame(raf);
102
- });
103
- </script>
104
-
105
- <!-- =========================== -->
106
- <!-- MARKUP -->
107
- <!-- =========================== -->
108
- <span class={cn("hr-animated-value tabular-nums", className)} {style}
109
- >{prefix ?? ""}{text}{suffix ?? ""}</span
110
- >
@@ -1,29 +0,0 @@
1
- /* Styles for AreaChart. Shipped as a plain stylesheet (imported by the
2
- component) instead of a Svelte `<style>` block: a `<style>` block becomes a
3
- `?type=style&lang.css` virtual module that Tailwind v4's Vite plugin mis-parses
4
- when this package is consumed as source from node_modules (tailwindlabs/
5
- tailwindcss#20000). Selectors are namespaced under `.hr-area-chart`. */
6
-
7
- .hr-area-chart {
8
- width: 100%;
9
- display: flex;
10
- flex-direction: column;
11
- gap: 0.5rem;
12
- }
13
- .hr-area-chart .hr-chart-body {
14
- width: 100%;
15
- }
16
-
17
- .hr-area-chart .empty {
18
- display: flex;
19
- align-items: center;
20
- justify-content: center;
21
- height: 100%;
22
- border: 1px dashed var(--chart-grid, oklch(0.5 0.01 286 / 0.2));
23
- border-radius: 0.5rem;
24
- }
25
- .hr-area-chart .empty p {
26
- font-size: 0.8125rem;
27
- color: var(--chart-label, oklch(0.5 0.01 286));
28
- margin: 0;
29
- }
@@ -1,195 +0,0 @@
1
- <script lang="ts" generics="TData extends Record<string, unknown>">
2
- // =========================
3
- // IMPORTS
4
- // =========================
5
- import "./area-chart.css";
6
- import { Area, Axis, Chart, Highlight, LinearGradient, Spline, Svg, Tooltip } from "layerchart";
7
- import { curveMonotoneX } from "d3-shape";
8
- import Crosshair from "./crosshair.svelte";
9
- import EdgeFade from "./edge-fade.svelte";
10
- import { resolveEdgeFade } from "./edge-fade.js";
11
- import Figure from "./figure.svelte";
12
- import HoverFocus from "./hover-focus.svelte";
13
- import { DOMAIN_MOTION, TOOLTIP_GAP, TOOLTIP_TOP } from "./motion.js";
14
- import Reveal from "./reveal.svelte";
15
-
16
- // =========================
17
- // TYPES
18
- // =========================
19
- type Series = {
20
- key: keyof TData & string;
21
- label?: string;
22
- color?: string;
23
- };
24
-
25
- type Props = {
26
- data: TData[];
27
- xKey: keyof TData & string;
28
- yKey?: keyof TData & string;
29
- series?: Series[];
30
- color?: string;
31
- height?: number;
32
- stacked?: boolean;
33
- smooth?: boolean;
34
- /**
35
- * Softens the left and right ends of the filled area instead of cutting them off at the plot edge.
36
- */
37
-
38
- /*
39
- * `true` fades 8% of the width per side, a number sets the fraction (0-0.45), `false` keeps the hard edges.
40
- */
41
- edgeFade?: boolean | number;
42
- formatValue?: (v: number) => string;
43
- formatX?: (v: unknown) => string;
44
- xTicks?: number;
45
- class?: string;
46
- };
47
-
48
- // =========================
49
- // PROPS
50
- // =========================
51
- let {
52
- data,
53
- xKey,
54
- yKey,
55
- series: seriesInput,
56
- color = "var(--chart-1)",
57
- height = 240,
58
- stacked = false,
59
- smooth = true,
60
- edgeFade = true,
61
- formatValue = (v) => v.toLocaleString(),
62
- formatX = (v) => String(v),
63
- xTicks = 6,
64
- class: className,
65
- }: Props = $props();
66
-
67
- // =========================
68
- // STATE
69
- // =========================
70
- let active = $state<TData | null>(null);
71
-
72
- // ========================= FUNCTIONS ========================= WHY: called from the tooltip header's value expression so it re-runs on every active-point change; an unread {@const} side effect only evaluates once.
73
-
74
- // The microtask defers the state write out of template evaluation.
75
- function trackActive(d: TData): string {
76
- queueMicrotask(() => {
77
- active = d;
78
- });
79
- return formatX(d[xKey]);
80
- }
81
-
82
- // =========================
83
- // DERIVED
84
- // =========================
85
- const uid = `hr-area-${Math.random().toString(36).slice(2, 8)}`;
86
- const series = $derived(
87
- seriesInput && seriesInput.length > 0
88
- ? seriesInput.map((s, i) => ({
89
- key: s.key,
90
- label: s.label ?? s.key,
91
- color: s.color ?? `var(--chart-${(i % 5) + 1})`,
92
- }))
93
- : yKey
94
- ? [{ key: yKey, label: yKey, color }]
95
- : [],
96
- );
97
- const yMax = $derived.by(() => {
98
- if (stacked) {
99
- return Math.max(0, ...data.map((d) => series.reduce((s, k) => s + Number(d[k.key] ?? 0), 0)));
100
- }
101
- return Math.max(0, ...data.flatMap((d) => series.map((s) => Number(d[s.key] ?? 0))));
102
- });
103
- const curve = $derived(smooth ? curveMonotoneX : undefined);
104
- const fade = $derived(resolveEdgeFade(edgeFade));
105
- const fadeMask = $derived(fade > 0 ? `url(#${uid}-fade)` : undefined);
106
- const fallback = $derived(data.length > 0 ? data[data.length - 1] : null);
107
- const display = $derived(active ?? fallback);
108
- const figureRows = $derived(
109
- display
110
- ? series.map((s) => ({ value: Number(display[s.key]), label: s.label, color: s.color }))
111
- : null,
112
- );
113
- </script>
114
-
115
- <!-- =========================== -->
116
- <!-- AREA CHART -->
117
- <!-- =========================== -->
118
- <div
119
- class="hr-area-chart {className ?? ''}"
120
- role="img"
121
- aria-label="Area chart"
122
- onpointerleave={() => (active = null)}
123
- >
124
- {#if figureRows && display}
125
- <Figure series={figureRows} eyebrow={formatX(display[xKey])} format={formatValue} size="md" />
126
- {:else}
127
- <Figure value="—" eyebrow="Latest" size="md" />
128
- {/if}
129
-
130
- <div class="hr-chart-body" style:height="{height}px">
131
- {#if data.length === 0}
132
- <div class="empty"><p>No data</p></div>
133
- {:else}
134
- <Chart
135
- {data}
136
- x={xKey}
137
- y={series[0]?.key}
138
- yDomain={[0, yMax || 1]}
139
- yNice
140
- padding={{ left: 48, bottom: 28, top: 8, right: 12 }}
141
- tooltipContext={{ mode: "quadtree-x" }}
142
- motion={DOMAIN_MOTION}
143
- >
144
- <Svg>
145
- <Axis placement="left" format={(v) => formatValue(Number(v))} ticks={4} />
146
- <Axis placement="bottom" format={(v) => formatX(v)} ticks={xTicks} />
147
- <g class="hr-area-grid">
148
- <Axis placement="left" grid rule={false} ticks={4} format={() => ""} />
149
- </g>
150
- {#if fade > 0}
151
- <EdgeFade id="{uid}-fade" amount={fade} />
152
- {/if}
153
- <Crosshair id="{uid}-cross" />
154
- <HoverFocus>
155
- <Reveal>
156
- {#each series as s, i (s.key)}
157
- <LinearGradient id="{uid}-{i}" vertical>
158
- {#snippet stopsContent()}
159
- <stop offset="0%" stop-color={s.color} stop-opacity="0.45" />
160
- <stop offset="100%" stop-color={s.color} stop-opacity="0.04" />
161
- {/snippet}
162
- </LinearGradient>
163
- <!-- WHY `y1` and not `y`: layerchart's Area has no `y` prop, so every
164
- series drew the first series' shape and the gradients stacked on
165
- one path. See `Area.shared.svelte.js`. -->
166
- <Area y1={s.key} {curve} fill="url(#{uid}-{i})" mask={fadeMask} />
167
- <Spline y={s.key} {curve} style="stroke: {s.color}; fill: none" stroke-width="2" />
168
- {/each}
169
- </Reveal>
170
- {#snippet segment()}
171
- {#each series as s (s.key)}
172
- <Spline y={s.key} {curve} style="stroke: {s.color}; fill: none" stroke-width="2" />
173
- {/each}
174
- {/snippet}
175
- </HoverFocus>
176
- <Highlight points lines={{ style: `stroke: url(#${uid}-cross)` }} />
177
- </Svg>
178
- <Tooltip.Root x="data" y={TOOLTIP_TOP} xOffset={TOOLTIP_GAP}>
179
- {#snippet children({ data: d })}
180
- <Tooltip.Header value={trackActive(d as TData)} />
181
- <Tooltip.List>
182
- {#each series as s (s.key)}
183
- <Tooltip.Item
184
- label={s.label}
185
- value={formatValue(Number(d[s.key]))}
186
- color={s.color}
187
- />
188
- {/each}
189
- </Tooltip.List>
190
- {/snippet}
191
- </Tooltip.Root>
192
- </Chart>
193
- {/if}
194
- </div>
195
- </div>
@@ -1,119 +0,0 @@
1
- /* Styles for BarChart. Plain stylesheet (see area-chart.css for why). Selectors
2
- are namespaced under `.hr-bar-chart`. */
3
-
4
- /* WHY: self-contained visually-hidden styling so the data table reaches
5
- screen readers without depending on the consumer's CSS framework. */
6
- .hr-sr-only {
7
- position: absolute;
8
- width: 1px;
9
- height: 1px;
10
- padding: 0;
11
- margin: -1px;
12
- overflow: hidden;
13
- clip: rect(0, 0, 0, 0);
14
- white-space: nowrap;
15
- border: 0;
16
- }
17
- .hr-bar-chart {
18
- width: 100%;
19
- display: flex;
20
- flex-direction: column;
21
- gap: 0.5rem;
22
- }
23
- .hr-bar-chart .hr-chart-body {
24
- width: 100%;
25
- }
26
-
27
- /* WHY: height="fill" grows the chart to its parent's height (e.g. a card that
28
- stretches to match a taller sibling) instead of the fixed body height. The
29
- parent must be a flex column that gives this a determinate height. */
30
- .hr-bar-chart.hr-bar-fill {
31
- flex: 1 1 auto;
32
- min-height: 0;
33
- }
34
- .hr-bar-chart.hr-bar-fill .hr-chart-body {
35
- flex: 1 1 auto;
36
- min-height: 0;
37
- }
38
-
39
- .hr-bar-chart .empty {
40
- display: flex;
41
- align-items: center;
42
- justify-content: center;
43
- height: 100%;
44
- border: 1px dashed var(--chart-grid, oklch(0.5 0.01 286 / 0.2));
45
- border-radius: 0.5rem;
46
- }
47
- .hr-bar-chart .empty p {
48
- font-size: 0.8125rem;
49
- color: var(--chart-label, oklch(0.5 0.01 286));
50
- margin: 0;
51
- }
52
-
53
- /* WHY: Bars render as <path> elements, not <rect>. Selectors target the path's class directly. */
54
- .hr-bar-chart .hr-bar-bars {
55
- transform-box: fill-box;
56
- transform-origin: bottom;
57
- animation: hr-bar-grow var(--chart-motion-reveal, 1100ms)
58
- var(--chart-ease-reveal, cubic-bezier(0.85, 0, 0.15, 1)) both;
59
- transition: opacity var(--chart-motion-fast, 150ms) ease-in-out;
60
- }
61
- .hr-bar-chart .hr-bar-bars:nth-of-type(2) {
62
- animation-delay: var(--chart-stagger, 30ms);
63
- }
64
- .hr-bar-chart .hr-bar-bars:nth-of-type(3) {
65
- animation-delay: calc(var(--chart-stagger, 30ms) * 2);
66
- }
67
- .hr-bar-chart .hr-bar-bars:nth-of-type(4) {
68
- animation-delay: calc(var(--chart-stagger, 30ms) * 3);
69
- }
70
- .hr-bar-chart .hr-bar-bars:nth-of-type(5) {
71
- animation-delay: calc(var(--chart-stagger, 30ms) * 4);
72
- }
73
- .hr-bar-chart .hr-bar-bars:nth-of-type(6) {
74
- animation-delay: calc(var(--chart-stagger, 30ms) * 5);
75
- }
76
- .hr-bar-chart .hr-bar-bars:nth-of-type(7) {
77
- animation-delay: calc(var(--chart-stagger, 30ms) * 6);
78
- }
79
- .hr-bar-chart .hr-bar-bars:nth-of-type(8) {
80
- animation-delay: calc(var(--chart-stagger, 30ms) * 7);
81
- }
82
- .hr-bar-chart .hr-bar-bars:nth-of-type(9) {
83
- animation-delay: calc(var(--chart-stagger, 30ms) * 8);
84
- }
85
- .hr-bar-chart .hr-bar-bars:nth-of-type(10) {
86
- animation-delay: calc(var(--chart-stagger, 30ms) * 9);
87
- }
88
- .hr-bar-chart .hr-bar-bars:nth-of-type(11) {
89
- animation-delay: calc(var(--chart-stagger, 30ms) * 10);
90
- }
91
- .hr-bar-chart .hr-bar-bars:nth-of-type(n + 12) {
92
- animation-delay: calc(var(--chart-stagger, 30ms) * 11);
93
- }
94
- @keyframes hr-bar-grow {
95
- from {
96
- transform: scaleY(0);
97
- }
98
- }
99
- .hr-bar-horizontal .hr-bar-bars {
100
- transform-origin: left;
101
- animation-name: hr-bar-grow-x;
102
- }
103
- @keyframes hr-bar-grow-x {
104
- from {
105
- transform: scaleX(0);
106
- }
107
- }
108
- .hr-bar-chart.hr-bar-has-active .hr-bar-bars {
109
- opacity: 0.3;
110
- }
111
- .hr-bar-chart .hr-bar-active {
112
- pointer-events: none;
113
- }
114
-
115
- @media (prefers-reduced-motion: reduce) {
116
- .hr-bar-chart .hr-bar-bars {
117
- animation: none;
118
- }
119
- }