@heyramzi/ui 1.54.2 → 2.0.1

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 (363) hide show
  1. package/COMPONENTS.md +3 -2
  2. package/README.md +34 -9
  3. package/package.json +205 -13
  4. package/scripts/sync-shadcn.mjs +2 -0
  5. package/src/ai/generation-progress/GenerationProgress.svelte +12 -12
  6. package/src/ambient.d.ts +8 -0
  7. package/src/brand/brand.test.ts +67 -0
  8. package/src/brand/index.ts +137 -0
  9. package/src/canvas/README.md +236 -0
  10. package/src/canvas/card/card-frame.svelte +61 -0
  11. package/src/canvas/card/card.css +39 -0
  12. package/src/canvas/card/resize-handles.svelte +119 -0
  13. package/src/canvas/card/resize.ts +33 -0
  14. package/src/canvas/chrome/chrome-zoom.svelte +120 -0
  15. package/src/canvas/chrome/chrome.css +231 -0
  16. package/src/canvas/chrome/lock-badge.svelte +18 -0
  17. package/src/canvas/chrome/side-handles.svelte +30 -0
  18. package/src/canvas/chrome/size-chip.svelte +45 -0
  19. package/src/canvas/chrome/snap-guides.svelte +69 -0
  20. package/src/canvas/components/icons/ToolIcon.svelte +30 -0
  21. package/src/canvas/components/shared/svg/PreviewSvg.svelte +67 -0
  22. package/src/canvas/components/shared/svg/ShapeOutline.svelte +76 -0
  23. package/src/canvas/components/shared/svg/StrokeNode.svelte +69 -0
  24. package/src/canvas/components/shared/svg/TextRule.svelte +37 -0
  25. package/src/canvas/edges/bend-handle.svelte +76 -0
  26. package/src/canvas/edges/edge-gradient.svelte +30 -0
  27. package/src/canvas/edges/edge-path.test.ts +58 -0
  28. package/src/canvas/edges/edge-path.ts +293 -0
  29. package/src/canvas/edges/gradient-edge.svelte +43 -0
  30. package/src/canvas/editor/context-menu.test.ts +65 -0
  31. package/src/canvas/editor/context-menu.ts +48 -0
  32. package/src/canvas/editor/dispatch.svelte.test.ts +243 -0
  33. package/src/canvas/editor/dispatch.svelte.ts +205 -0
  34. package/src/canvas/editor/editor-context.ts +62 -0
  35. package/src/canvas/editor/editor-mode.ts +67 -0
  36. package/src/canvas/editor/frame.ts +98 -0
  37. package/src/canvas/editor/hand-context.ts +15 -0
  38. package/src/canvas/editor/history-core.test.ts +239 -0
  39. package/src/canvas/editor/history-core.ts +247 -0
  40. package/src/canvas/editor/keymap.test.ts +161 -0
  41. package/src/canvas/editor/keymap.ts +151 -0
  42. package/src/canvas/editor/layout-actions.test.ts +156 -0
  43. package/src/canvas/editor/layout-actions.ts +219 -0
  44. package/src/canvas/editor/lock.test.ts +68 -0
  45. package/src/canvas/editor/lock.ts +87 -0
  46. package/src/canvas/editor/rebase.test.ts +208 -0
  47. package/src/canvas/editor/rebase.ts +272 -0
  48. package/src/canvas/editor/style.ts +184 -0
  49. package/src/canvas/editor/text-field-context.ts +41 -0
  50. package/src/canvas/editor/z-order.test.ts +75 -0
  51. package/src/canvas/editor/z-order.ts +87 -0
  52. package/src/canvas/headless/alignment.test.ts +59 -0
  53. package/src/canvas/headless/alignment.ts +23 -0
  54. package/src/canvas/headless/break-apart-find.ts +418 -0
  55. package/src/canvas/headless/break-apart-pieces.ts +104 -0
  56. package/src/canvas/headless/break-apart-plan.ts +439 -0
  57. package/src/canvas/headless/break-apart-style.ts +106 -0
  58. package/src/canvas/headless/break-apart.ts +244 -0
  59. package/src/canvas/headless/canvas-cleanup.test.ts +181 -0
  60. package/src/canvas/headless/canvas-cleanup.ts +102 -0
  61. package/src/canvas/headless/edge-anchors.test.ts +70 -0
  62. package/src/canvas/headless/edge-anchors.ts +143 -0
  63. package/src/canvas/headless/edge-memo.test.ts +58 -0
  64. package/src/canvas/headless/edge-memo.ts +32 -0
  65. package/src/canvas/headless/edge-serialization.test.ts +55 -0
  66. package/src/canvas/headless/edge-serialization.ts +32 -0
  67. package/src/canvas/headless/figure-geometry.ts +293 -0
  68. package/src/canvas/headless/fit-viewport.test.ts +85 -0
  69. package/src/canvas/headless/fit-viewport.ts +137 -0
  70. package/src/canvas/headless/grid.test.ts +34 -0
  71. package/src/canvas/headless/grid.ts +94 -0
  72. package/src/canvas/headless/icon-node.test.ts +23 -0
  73. package/src/canvas/headless/icon-node.ts +66 -0
  74. package/src/canvas/headless/index.ts +9 -0
  75. package/src/canvas/headless/linkify.test.ts +23 -0
  76. package/src/canvas/headless/linkify.ts +25 -0
  77. package/src/canvas/headless/pen-marks.ts +133 -0
  78. package/src/canvas/headless/sketch.test.ts +99 -0
  79. package/src/canvas/headless/sketch.ts +302 -0
  80. package/src/canvas/headless/snap-guides.test.ts +61 -0
  81. package/src/canvas/headless/snap-guides.ts +146 -0
  82. package/src/canvas/headless/svg-figure.test.ts +49 -0
  83. package/src/canvas/headless/svg-figure.ts +176 -0
  84. package/src/canvas/headless/table-layout.test.ts +158 -0
  85. package/src/canvas/headless/table-layout.ts +309 -0
  86. package/src/canvas/index.ts +35 -0
  87. package/src/canvas/lod/lod-mode.svelte.ts +30 -0
  88. package/src/canvas/lod/lod-switch.svelte +140 -0
  89. package/src/canvas/lod/render-all.svelte.ts +52 -0
  90. package/src/canvas/ops/arrange.ts +108 -0
  91. package/src/canvas/ops/ops.test.ts +98 -0
  92. package/src/canvas/ops/ops.ts +347 -0
  93. package/src/canvas/pen/PenField.svelte +128 -0
  94. package/src/canvas/pen/PenField.test.ts +87 -0
  95. package/src/canvas/pen/PenOverlay.svelte +172 -0
  96. package/src/canvas/pen/ShapeNode.svelte +64 -0
  97. package/src/canvas/pen/TextNode.svelte +97 -0
  98. package/src/canvas/pen/colors.ts +28 -0
  99. package/src/canvas/pen/eraser.ts +46 -0
  100. package/src/canvas/pen/geometry.ts +148 -0
  101. package/src/canvas/pen/host-field.test.svelte +13 -0
  102. package/src/canvas/pen/index.ts +40 -0
  103. package/src/canvas/pen/ops.ts +16 -0
  104. package/src/canvas/pen/pen-session.ts +177 -0
  105. package/src/canvas/pen/pen.css +149 -0
  106. package/src/canvas/pen/plugin.ts +139 -0
  107. package/src/canvas/pen/shapes.ts +104 -0
  108. package/src/canvas/pen/stroke-path.ts +54 -0
  109. package/src/canvas/pen/types.ts +96 -0
  110. package/src/canvas/pen/ui.ts +26 -0
  111. package/src/canvas/plugin.test.ts +45 -0
  112. package/src/canvas/plugin.ts +159 -0
  113. package/src/canvas/screen/GlyphIcon.svelte +25 -0
  114. package/src/canvas/screen/PartView.svelte +176 -0
  115. package/src/canvas/screen/ScreenBody.svelte +142 -0
  116. package/src/canvas/screen/ScreenCard.svelte +32 -0
  117. package/src/canvas/screen/glyphs/button.svg +1 -0
  118. package/src/canvas/screen/glyphs/close.svg +1 -0
  119. package/src/canvas/screen/glyphs/down.svg +1 -0
  120. package/src/canvas/screen/glyphs/header.svg +1 -0
  121. package/src/canvas/screen/glyphs/hills.svg +1 -0
  122. package/src/canvas/screen/glyphs/image.svg +1 -0
  123. package/src/canvas/screen/glyphs/input.svg +1 -0
  124. package/src/canvas/screen/glyphs/list.svg +1 -0
  125. package/src/canvas/screen/glyphs/modal.svg +1 -0
  126. package/src/canvas/screen/glyphs/plus.svg +1 -0
  127. package/src/canvas/screen/glyphs/up.svg +1 -0
  128. package/src/canvas/screen/glyphs.ts +40 -0
  129. package/src/canvas/screen/labels.ts +41 -0
  130. package/src/canvas/screen/parts.ts +164 -0
  131. package/src/canvas/screen/plugin.ts +67 -0
  132. package/src/canvas/screen/screen.css +593 -0
  133. package/src/canvas/screen/types.ts +47 -0
  134. package/src/canvas/screen/ui.ts +13 -0
  135. package/src/canvas/test-utils.ts +18 -0
  136. package/src/canvas/types.ts +53 -0
  137. package/src/canvas/ui/CanvasToolbar.svelte +169 -0
  138. package/src/canvas/ui/FrameLayer.svelte +116 -0
  139. package/src/canvas/ui/PenLayer.svelte +39 -0
  140. package/src/canvas/ui/StylePanel.svelte +268 -0
  141. package/src/canvas/ui/canvas-grid.svelte +156 -0
  142. package/src/canvas/ui/canvas-ui.css +350 -0
  143. package/src/canvas/ui/forward-wheel.ts +29 -0
  144. package/src/canvas/ui/icons.ts +124 -0
  145. package/src/canvas/ui/place-panel.ts +80 -0
  146. package/src/canvas/ui/shortcut-tip.test.ts +16 -0
  147. package/src/canvas/ui/shortcut-tip.ts +17 -0
  148. package/src/canvas/ui/tools.ts +146 -0
  149. package/src/charts/README.md +104 -0
  150. package/src/charts/ambient.d.ts +4 -0
  151. package/src/charts/animated-value.css +7 -0
  152. package/src/charts/animated-value.svelte +110 -0
  153. package/src/charts/area-chart.css +29 -0
  154. package/src/charts/area-chart.svelte +204 -0
  155. package/src/charts/bar-chart.css +119 -0
  156. package/src/charts/bar-chart.svelte +275 -0
  157. package/src/charts/charts.css +201 -0
  158. package/src/charts/crosshair.svelte +35 -0
  159. package/src/charts/dashboard/chart.ts +5 -0
  160. package/src/charts/dashboard/dashboard-empty.svelte +55 -0
  161. package/src/charts/dashboard/dashboard-section.svelte +58 -0
  162. package/src/charts/dashboard/data-panel.svelte +81 -0
  163. package/src/charts/dashboard/data-sort-head.svelte +102 -0
  164. package/src/charts/dashboard/data-table.svelte +278 -0
  165. package/src/charts/dashboard/data-table.ts +26 -0
  166. package/src/charts/dashboard/index.ts +25 -0
  167. package/src/charts/dashboard/panel-grid.svelte +43 -0
  168. package/src/charts/dashboard/period-filter.svelte +53 -0
  169. package/src/charts/dashboard/rating-chip.svelte +35 -0
  170. package/src/charts/dashboard/stat-band.svelte +47 -0
  171. package/src/charts/dashboard/stat-tile.svelte +176 -0
  172. package/src/charts/dashboard/windows.ts +8 -0
  173. package/src/charts/donut-chart.css +56 -0
  174. package/src/charts/donut-chart.svelte +158 -0
  175. package/src/charts/edge-fade.svelte +43 -0
  176. package/src/charts/edge-fade.ts +16 -0
  177. package/src/charts/figure.css +100 -0
  178. package/src/charts/figure.svelte +122 -0
  179. package/src/charts/gauge-chart.css +94 -0
  180. package/src/charts/gauge-chart.svelte +302 -0
  181. package/src/charts/hover-band.test.ts +30 -0
  182. package/src/charts/hover-band.ts +21 -0
  183. package/src/charts/hover-focus.svelte +85 -0
  184. package/src/charts/index.ts +31 -0
  185. package/src/charts/legend.css +136 -0
  186. package/src/charts/legend.svelte +112 -0
  187. package/src/charts/line-chart.css +26 -0
  188. package/src/charts/line-chart.svelte +256 -0
  189. package/src/charts/motion.ts +19 -0
  190. package/src/charts/number-chart.css +179 -0
  191. package/src/charts/number-chart.svelte +187 -0
  192. package/src/charts/primitives/chart-container.svelte +57 -0
  193. package/src/charts/primitives/chart-style.svelte +36 -0
  194. package/src/charts/primitives/chart-tooltip.svelte +161 -0
  195. package/src/charts/primitives/chart-utils.ts +54 -0
  196. package/src/charts/primitives/index.ts +11 -0
  197. package/src/charts/reference-line.css +18 -0
  198. package/src/charts/reference-line.svelte +31 -0
  199. package/src/charts/reveal.svelte +61 -0
  200. package/src/charts/ring-chart.css +104 -0
  201. package/src/charts/ring-chart.svelte +166 -0
  202. package/src/charts/sparkline.css +45 -0
  203. package/src/charts/sparkline.svelte +141 -0
  204. package/src/charts/stat-card.css +105 -0
  205. package/src/charts/stat-card.svelte +267 -0
  206. package/src/charts/time-series-chart.css +28 -0
  207. package/src/charts/time-series-chart.svelte +179 -0
  208. package/src/charts/trend-pill.css +38 -0
  209. package/src/charts/trend-pill.svelte +48 -0
  210. package/src/components/copy/copy-button.svelte +1 -1
  211. package/src/components/docs/doc-page.svelte +1 -1
  212. package/src/components/docs/on-this-page.svelte +2 -2
  213. package/src/components/list-page/empty-state.svelte +1 -1
  214. package/src/components/list-page/filter-popover.svelte +1 -1
  215. package/src/components/list-page/section-label.svelte +1 -1
  216. package/src/components/segmented/segment.svelte +4 -4
  217. package/src/components/theme/theme-provider.svelte +6 -4
  218. package/src/components/toolbar/index.ts +5 -0
  219. package/src/components/toolbar/toolbar.svelte +168 -0
  220. package/src/components/toolbar/toolbar.test.ts +66 -0
  221. package/src/editor/README.md +58 -0
  222. package/src/editor/ambient.d.ts +1 -0
  223. package/src/editor/block-id.ts +77 -0
  224. package/src/editor/block-ops.test.ts +237 -0
  225. package/src/editor/block-ops.ts +157 -0
  226. package/src/editor/content.css +418 -0
  227. package/src/editor/editor-toolbar.svelte +303 -0
  228. package/src/editor/editor.svelte +469 -0
  229. package/src/editor/extensions.ts +145 -0
  230. package/src/editor/image-toolbar.svelte +123 -0
  231. package/src/editor/index.ts +17 -0
  232. package/src/editor/inline-editor.svelte +261 -0
  233. package/src/editor/markdown-escaping.test.ts +158 -0
  234. package/src/editor/markdown-marks.test.ts +89 -0
  235. package/src/editor/markdown-test-helpers.ts +13 -0
  236. package/src/editor/markdown-youtube.test.ts +93 -0
  237. package/src/editor/markdown.test.ts +250 -0
  238. package/src/editor/markdown.ts +511 -0
  239. package/src/editor/renderer.svelte +92 -0
  240. package/src/editor/serializer.test.ts +133 -0
  241. package/src/editor/serializer.ts +370 -0
  242. package/src/editor/slash-items.ts +115 -0
  243. package/src/editor/slash-menu.svelte +159 -0
  244. package/src/editor/youtube-url.ts +35 -0
  245. package/src/effects/interactive-hover-button/InteractiveHoverButton.svelte +13 -13
  246. package/src/gallery.test.ts +20 -1
  247. package/src/lib/result.ts +19 -0
  248. package/src/onboarding/README.md +120 -0
  249. package/src/onboarding/define-tours.test.ts +50 -0
  250. package/src/onboarding/define-tours.ts +31 -0
  251. package/src/onboarding/demo.svelte +86 -0
  252. package/src/onboarding/index.ts +12 -0
  253. package/src/onboarding/onboarding-provider.svelte +120 -0
  254. package/src/onboarding/onboarding.svelte.ts +24 -0
  255. package/src/onboarding/pick.test.ts +79 -0
  256. package/src/onboarding/pick.ts +36 -0
  257. package/src/onboarding/stores.test.ts +103 -0
  258. package/src/onboarding/stores.ts +58 -0
  259. package/src/onboarding/tour-card.svelte +70 -0
  260. package/src/onboarding/tour-runner.svelte +197 -0
  261. package/src/onboarding/types.ts +34 -0
  262. package/src/onboarding/wait.ts +29 -0
  263. package/src/shadcn/command/command-input.svelte +1 -1
  264. package/src/slides/Controls.svelte +138 -0
  265. package/src/slides/Deck.svelte +271 -0
  266. package/src/slides/Fragment.svelte +71 -0
  267. package/src/slides/Overview.svelte +113 -0
  268. package/src/slides/Presenter.svelte +292 -0
  269. package/src/slides/README.md +89 -0
  270. package/src/slides/Slide.svelte +179 -0
  271. package/src/slides/SlideList.svelte +19 -0
  272. package/src/slides/ambient.d.ts +1 -0
  273. package/src/slides/bridges.ts +69 -0
  274. package/src/slides/deck-controller.svelte.ts +292 -0
  275. package/src/slides/demo-slides.svelte +358 -0
  276. package/src/slides/demo.svelte +176 -0
  277. package/src/slides/export/capture.ts +113 -0
  278. package/src/slides/export/ffmpeg.ts +120 -0
  279. package/src/slides/export/index.ts +9 -0
  280. package/src/slides/export/launch.ts +10 -0
  281. package/src/slides/export/pdf.ts +152 -0
  282. package/src/slides/export/types.ts +48 -0
  283. package/src/slides/index.ts +19 -0
  284. package/src/slides/labels.ts +48 -0
  285. package/src/slides/layout.ts +51 -0
  286. package/src/slides/model.ts +47 -0
  287. package/src/slides/navigation.ts +100 -0
  288. package/src/slides/theme.css +205 -0
  289. package/src/slides/types.ts +86 -0
  290. package/src/tasks/README.md +312 -0
  291. package/src/tasks/ambient.d.ts +3 -0
  292. package/src/tasks/board-order.ts +137 -0
  293. package/src/tasks/dates.ts +31 -0
  294. package/src/tasks/define-statuses.ts +32 -0
  295. package/src/tasks/demo.svelte +389 -0
  296. package/src/tasks/detail/detail-demo.svelte +186 -0
  297. package/src/tasks/detail/detail-types.ts +54 -0
  298. package/src/tasks/detail/task-chip.svelte +28 -0
  299. package/src/tasks/detail/task-detail.svelte +315 -0
  300. package/src/tasks/detail/task-property.svelte +17 -0
  301. package/src/tasks/detail/task-thread.svelte +258 -0
  302. package/src/tasks/gantt/gantt-bar.svelte +243 -0
  303. package/src/tasks/gantt/gantt-grid.svelte +94 -0
  304. package/src/tasks/gantt/gantt-group-row.svelte +55 -0
  305. package/src/tasks/gantt/gantt-header.svelte +71 -0
  306. package/src/tasks/gantt/gantt-task-row.svelte +186 -0
  307. package/src/tasks/gantt/gantt.css +22 -0
  308. package/src/tasks/gantt/gantt.test.ts +77 -0
  309. package/src/tasks/gantt/logic.test.ts +163 -0
  310. package/src/tasks/gantt/logic.ts +248 -0
  311. package/src/tasks/inbox/inbox-card.svelte +283 -0
  312. package/src/tasks/inbox/inbox-draft.svelte +84 -0
  313. package/src/tasks/inbox/inbox-logic.ts +55 -0
  314. package/src/tasks/inbox/inbox-statuses.ts +48 -0
  315. package/src/tasks/inbox/inbox-trace.svelte +45 -0
  316. package/src/tasks/inbox/inbox-types.ts +108 -0
  317. package/src/tasks/inbox/inbox.svelte +203 -0
  318. package/src/tasks/inbox/index.ts +23 -0
  319. package/src/tasks/index.ts +85 -0
  320. package/src/tasks/kanban-board.svelte +561 -0
  321. package/src/tasks/kanban-column.svelte +117 -0
  322. package/src/tasks/kanban-drag.ts +38 -0
  323. package/src/tasks/kanban-types.ts +65 -0
  324. package/src/tasks/presets/sales.ts +16 -0
  325. package/src/tasks/record/demo-data.ts +286 -0
  326. package/src/tasks/record/field-section.svelte +53 -0
  327. package/src/tasks/record/fields.ts +142 -0
  328. package/src/tasks/record/format.ts +87 -0
  329. package/src/tasks/record/gutter.ts +2 -0
  330. package/src/tasks/record/index.ts +54 -0
  331. package/src/tasks/record/info-list.svelte +316 -0
  332. package/src/tasks/record/kinds.ts +42 -0
  333. package/src/tasks/record/logic.ts +324 -0
  334. package/src/tasks/record/next-up.svelte +70 -0
  335. package/src/tasks/record/project-list.svelte +133 -0
  336. package/src/tasks/record/record-demo.svelte +324 -0
  337. package/src/tasks/record/record-header.svelte +70 -0
  338. package/src/tasks/record/record-shell.svelte +138 -0
  339. package/src/tasks/record/record-stats.svelte +48 -0
  340. package/src/tasks/record/record-timeline.svelte +231 -0
  341. package/src/tasks/record/record.test.ts +350 -0
  342. package/src/tasks/record/steps-rail.svelte +474 -0
  343. package/src/tasks/record/types.ts +280 -0
  344. package/src/tasks/record/where-we-are.svelte +121 -0
  345. package/src/tasks/reorder.ts +19 -0
  346. package/src/tasks/side-panel-types.ts +16 -0
  347. package/src/tasks/side-panel.svelte +193 -0
  348. package/src/tasks/status-badge.svelte +63 -0
  349. package/src/tasks/status-dot.svelte +228 -0
  350. package/src/tasks/status-icon.svelte +30 -0
  351. package/src/tasks/status-types.ts +40 -0
  352. package/src/tasks/task-gantt.svelte +230 -0
  353. package/src/tasks/task-list.svelte +470 -0
  354. package/src/tasks/task-types.ts +33 -0
  355. package/src/tasks/time/duration.ts +69 -0
  356. package/src/tasks/time/time-chip.svelte +62 -0
  357. package/src/tasks/time/time-dot.svelte +58 -0
  358. package/src/tasks/time/time-ring.svelte +74 -0
  359. package/src/tasks/time/time-tracker.svelte +565 -0
  360. package/src/tasks/time/time-types.ts +74 -0
  361. package/src/tasks/use-kanban-dnd.svelte.ts +173 -0
  362. package/src/tokens/base.css +5 -5
  363. package/src/tokens/palette.css +115 -120
@@ -0,0 +1,159 @@
1
+ <script lang="ts">
2
+ // =========================
3
+ // IMPORTS
4
+ // =========================
5
+ import type { SlashItem } from "./slash-items.js";
6
+
7
+ // =========================
8
+ // TYPES
9
+ // =========================
10
+ interface Props {
11
+ items: SlashItem[];
12
+ pos: { top: number; left: number };
13
+ selectedIndex: number;
14
+ /** The menu element, so the parent can close it on an outside click. */
15
+ el?: HTMLDivElement;
16
+ onselect: (item: SlashItem) => void;
17
+ }
18
+
19
+ // =========================
20
+ // PROPS
21
+ // =========================
22
+ let { items, pos, selectedIndex = $bindable(), el = $bindable(), onselect }: Props = $props();
23
+ </script>
24
+
25
+ <!-- =========================== -->
26
+ <!-- MARKUP -->
27
+ <!-- =========================== -->
28
+ <div
29
+ bind:this={el}
30
+ class="slash-menu"
31
+ style="top: {pos.top}px; left: {pos.left}px;"
32
+ role="listbox"
33
+ >
34
+ {#each items as item, i}
35
+ <button
36
+ type="button"
37
+ class="slash-item"
38
+ class:selected={i === selectedIndex}
39
+ onclick={() => onselect(item)}
40
+ onpointerenter={() => selectedIndex = i}
41
+ role="option"
42
+ aria-selected={i === selectedIndex}
43
+ >
44
+ <span class="slash-icon">
45
+ <item.icon size={18} />
46
+ </span>
47
+ <span class="slash-text">
48
+ <span class="slash-label">{item.label}</span>
49
+ <span class="slash-desc">{item.description}</span>
50
+ </span>
51
+ </button>
52
+ {/each}
53
+ </div>
54
+
55
+ <!-- =========================== -->
56
+ <!-- STYLE -->
57
+ <!-- =========================== -->
58
+ <style>
59
+ /* ---- SLASH COMMAND MENU ---- */
60
+ .slash-menu {
61
+ position: absolute;
62
+ z-index: 50;
63
+ min-width: 260px;
64
+ max-height: 340px;
65
+ overflow-y: auto;
66
+ padding: 6px;
67
+ background: var(--color-popover);
68
+ border: 1px solid var(--color-border);
69
+ border-radius: var(--radius-xl);
70
+ box-shadow: var(--elev-overlay);
71
+ animation: slash-enter var(--duration-fast) var(--ease-out);
72
+ }
73
+
74
+ @keyframes slash-enter {
75
+ from {
76
+ opacity: 0;
77
+ transform: translateY(-3px) scale(0.98);
78
+ }
79
+ to {
80
+ opacity: 1;
81
+ transform: translateY(0) scale(1);
82
+ }
83
+ }
84
+
85
+ .slash-item {
86
+ display: flex;
87
+ align-items: center;
88
+ gap: 0.75rem;
89
+ width: 100%;
90
+ padding: 0.5rem 0.625rem;
91
+ border: none;
92
+ border-radius: var(--radius-md);
93
+ background: transparent;
94
+ color: var(--color-foreground);
95
+ cursor: pointer;
96
+ text-align: left;
97
+ transition: background-color var(--duration-micro) var(--ease-smooth-out);
98
+ }
99
+
100
+ .slash-item.selected {
101
+ background: var(--color-accent);
102
+ }
103
+
104
+ @media (hover: hover) and (pointer: fine) {
105
+ .slash-item:hover {
106
+ background: var(--color-accent);
107
+ }
108
+ }
109
+
110
+ .slash-icon {
111
+ display: flex;
112
+ align-items: center;
113
+ justify-content: center;
114
+ width: 2rem;
115
+ height: 2rem;
116
+ border-radius: var(--radius-sm);
117
+ background: var(--color-muted);
118
+ color: var(--color-muted-foreground);
119
+ flex-shrink: 0;
120
+ transition: background-color var(--duration-micro) var(--ease-smooth-out), color var(--duration-micro) var(--ease-smooth-out);
121
+ }
122
+
123
+ .slash-item.selected .slash-icon {
124
+ background: oklch(from var(--color-brand) l c h / 0.1);
125
+ color: var(--color-brand);
126
+ }
127
+
128
+ @media (hover: hover) and (pointer: fine) {
129
+ .slash-item:hover .slash-icon {
130
+ background: oklch(from var(--color-brand) l c h / 0.1);
131
+ color: var(--color-brand);
132
+ }
133
+ }
134
+
135
+ .slash-text {
136
+ display: flex;
137
+ flex-direction: column;
138
+ gap: 0;
139
+ min-width: 0;
140
+ }
141
+
142
+ .slash-label {
143
+ font-size: 0.8125rem;
144
+ font-weight: 500;
145
+ line-height: 1.3;
146
+ }
147
+
148
+ .slash-desc {
149
+ font-size: 0.6875rem;
150
+ color: var(--color-muted-foreground);
151
+ line-height: 1.3;
152
+ }
153
+
154
+ @media (prefers-reduced-motion: reduce) {
155
+ .slash-menu {
156
+ animation: none;
157
+ }
158
+ }
159
+ </style>
@@ -0,0 +1,35 @@
1
+ // No markdown-it here, so the editor can import it without the markdown engine.
2
+
3
+ export const YOUTUBE_ID_RE = /^[A-Za-z0-9_-]{11}$/;
4
+
5
+ export type YoutubeRef = { videoId: string; start: number };
6
+
7
+ function toUrl(url: string): URL | null {
8
+ try {
9
+ return new URL(url);
10
+ } catch {
11
+ return null;
12
+ }
13
+ }
14
+
15
+ function videoIdOf(parsed: URL): string | null {
16
+ const host = parsed.hostname.replace(/^www\./, "");
17
+ if (host === "youtu.be") return parsed.pathname.slice(1);
18
+ if (host !== "youtube.com" && host !== "m.youtube.com") return null;
19
+ if (parsed.pathname === "/watch") return parsed.searchParams.get("v");
20
+ if (parsed.pathname.startsWith("/embed/")) return parsed.pathname.slice("/embed/".length);
21
+ return null;
22
+ }
23
+
24
+ /**
25
+ * Reads youtube.com/watch?v=ID, youtu.be/ID and youtube.com/embed/ID. A `t`
26
+ * param in seconds becomes `start`.
27
+ */
28
+ export function parseYoutubeUrl(url: string): YoutubeRef | null {
29
+ const parsed = toUrl(url);
30
+ if (!parsed) return null;
31
+ const videoId = videoIdOf(parsed);
32
+ if (!videoId || !YOUTUBE_ID_RE.test(videoId)) return null;
33
+ const t = parseInt(parsed.searchParams.get("t") ?? "", 10);
34
+ return { videoId, start: Number.isFinite(t) && t > 0 ? t : 0 };
35
+ }
@@ -233,13 +233,13 @@ let classes = $derived(
233
233
  transition: opacity var(--duration-fast) var(--ease-smooth-out), transform var(--duration-fast) var(--ease-smooth-out);
234
234
  }
235
235
 
236
- /* terra-600, not terra-400: the dot becomes the hover fill under a cream
237
- label, and cream on terra-400 is 3.24:1. It works in both themes. */
236
+ /* signal-600, not signal-400: the dot becomes the hover fill under a paper
237
+ label, and paper on signal-400 fails AA. It works in both themes. */
238
238
  .cta-hover__dot {
239
239
  width: 8px;
240
240
  height: 8px;
241
241
  border-radius: 50%;
242
- background: var(--color-terra-600);
242
+ background: var(--color-signal-600);
243
243
  flex-shrink: 0;
244
244
  transition: transform var(--duration-fast) var(--ease-smooth-out);
245
245
  }
@@ -264,9 +264,9 @@ let classes = $derived(
264
264
  transition:
265
265
  transform var(--duration-fast) var(--ease-smooth-out),
266
266
  opacity var(--duration-fast) var(--ease-smooth-out);
267
- /* The reveal label always lands on the terra-600 dot fill, where cream
267
+ /* The reveal label always lands on the signal-600 dot fill, where paper
268
268
  clears AA at button-label sizes. */
269
- color: var(--color-brand-cream);
269
+ color: var(--color-paper);
270
270
  pointer-events: none;
271
271
  }
272
272
 
@@ -279,16 +279,16 @@ let classes = $derived(
279
279
  /* Coral fill, heavier than the ink default. It comes after the .dark rules
280
280
  so one set of colors covers both themes. */
281
281
  .cta-hover--coral {
282
- /* Cream label on terra-600: on terra-400 it's 3.24:1 and fails AA. */
283
- color: var(--color-brand-cream);
282
+ /* Paper label on signal-600: on signal-400 it fails AA. */
283
+ color: var(--color-paper);
284
284
  }
285
285
 
286
286
  .cta-hover--coral::after {
287
- background: var(--color-terra-600);
287
+ background: var(--color-signal-600);
288
288
  }
289
289
 
290
290
  .cta-hover--coral.cta-hover--no-beam {
291
- background: var(--color-terra-600);
291
+ background: var(--color-signal-600);
292
292
  }
293
293
 
294
294
  .cta-hover--coral::before,
@@ -296,17 +296,17 @@ let classes = $derived(
296
296
  background: conic-gradient(
297
297
  transparent 0deg,
298
298
  transparent 220deg,
299
- var(--color-brand-cream) 280deg,
300
- var(--color-terra-200) 320deg,
299
+ var(--color-paper) 280deg,
300
+ var(--color-signal-200) 320deg,
301
301
  transparent 360deg
302
302
  );
303
303
  }
304
304
 
305
- /* Ink dot on coral, so hover turns the button black under a cream label
305
+ /* Ink dot on coral, so hover turns the button black under a paper label
306
306
  instead of washing it out to cream. */
307
307
  .cta-hover--coral .cta-hover__dot,
308
308
  :global(.dark) .cta-hover--coral .cta-hover__dot {
309
- background: var(--color-brand-ink);
309
+ background: var(--color-ink);
310
310
  }
311
311
 
312
312
  @media (hover: hover) and (pointer: fine) {
@@ -28,7 +28,12 @@ const SITE = join(PKG, "..", "..", "site", "src", "lib");
28
28
 
29
29
  describe("site gallery coverage", () => {
30
30
  it("gives every animation a stage", () => {
31
- const section = readFileSync(join(SITE, "demos", "motion.svelte"), "utf8");
31
+ // Each animation's stage is its own file under demos/motion/.
32
+ const stages = join(SITE, "demos", "motion");
33
+ const section = readdirSync(stages)
34
+ .filter((file) => file.endsWith(".svelte"))
35
+ .map((file) => readFileSync(join(stages, file), "utf8"))
36
+ .join("\n");
32
37
  const missing = readdirSync(join(PKG, "src", "animations"))
33
38
  .filter((file) => file.endsWith(".css") && file !== "index.css")
34
39
  .filter((file) => !section.includes(`animations/${file.replace(".css", "")}`));
@@ -43,6 +48,20 @@ describe("site gallery coverage", () => {
43
48
  expect(vendored.filter((name) => !manifest.includes(`name: "${name}"`))).toEqual([]);
44
49
  });
45
50
 
51
+ it("gives every component, AI part and effect a place on the site", () => {
52
+ const walk = (dir: string): string[] =>
53
+ readdirSync(dir, { withFileTypes: true }).flatMap((d) =>
54
+ d.isDirectory() ? walk(join(dir, d.name)) : /\.(svelte|ts)$/.test(d.name) ? [join(dir, d.name)] : [],
55
+ );
56
+ const site = walk(join(SITE, "..")).map((file) => readFileSync(file, "utf8")).join("\n");
57
+ const parts = ["components", "ai", "effects"].flatMap((top) =>
58
+ readdirSync(join(PKG, "src", top), { withFileTypes: true })
59
+ .filter((d) => d.isDirectory())
60
+ .map((d) => `${top}/${d.name}`),
61
+ );
62
+ expect(parts.filter((part) => !site.includes(`${part}/`) && !site.includes(`${part}"`))).toEqual([]);
63
+ });
64
+
46
65
  it("keeps a demo file behind every listed primitive", () => {
47
66
  const manifest = readFileSync(join(SITE, "shadcn-demos", "index.ts"), "utf8");
48
67
  const listed = [...manifest.matchAll(/name: "([a-z-]+)"/g)].map((m) => m[1]);
@@ -0,0 +1,19 @@
1
+ // A small Result type, so a throw becomes a value the caller has to look at.
2
+
3
+ export type Result<T, E = Error> = { ok: true; value: T } | { ok: false; error: E };
4
+
5
+ export function tryCatch<T>(fn: () => T): Result<T> {
6
+ try {
7
+ return { ok: true, value: fn() };
8
+ } catch (e) {
9
+ return { ok: false, error: e instanceof Error ? e : new Error(String(e)) };
10
+ }
11
+ }
12
+
13
+ export async function tryCatchAsync<T>(fn: () => Promise<T>): Promise<Result<T>> {
14
+ try {
15
+ return { ok: true, value: await fn() };
16
+ } catch (e) {
17
+ return { ok: false, error: e instanceof Error ? e : new Error(String(e)) };
18
+ }
19
+ }
@@ -0,0 +1,120 @@
1
+ # @heyramzi/ui/onboarding
2
+
3
+ Svelte 5 page tours. A dimmed page, one lit element and a short card per step, shown once per page and
4
+ remembered per person. Live at [ui.heyramzi.com/onboarding](https://ui.heyramzi.com/onboarding).
5
+
6
+ It builds on [`@zag-js/tour`](https://zagjs.com/components/svelte/tour) (MIT) for spotlight geometry, focus and
7
+ keys, and draws the card itself with the rest of `@heyramzi/ui`, so it looks like the rest of your app.
8
+ `phosphor-svelte` and `svelte` are peers.
9
+
10
+ ```
11
+ pnpm add @heyramzi/ui phosphor-svelte
12
+ ```
13
+
14
+ ## Define the tours
15
+
16
+ A tour belongs to a SvelteKit route id, so params never matter. `steps` points at elements by CSS selector. `intro`
17
+ is one centred card with no target, for a page's first visit.
18
+
19
+ ```ts
20
+ import { defineTours } from "@heyramzi/ui/onboarding";
21
+
22
+ export const tours = defineTours([
23
+ {
24
+ id: "home",
25
+ route: "/(app)",
26
+ kind: "intro",
27
+ title: "The week in one place",
28
+ body: "Open work sits on the left. Anything late floats to the top.",
29
+ },
30
+ {
31
+ id: "projects-board",
32
+ version: 1,
33
+ route: "/(app)/projects",
34
+ kind: "steps",
35
+ steps: [
36
+ { target: '[data-tour="new-project"]', title: "Start here", body: "A name and a client. That's all." },
37
+ ],
38
+ },
39
+ ]);
40
+ ```
41
+
42
+ `defineTours` throws on a repeated id, a route that isn't a route id, and a `steps` tour with fewer than 1 or more
43
+ than 6 steps. Past 6, people skip.
44
+
45
+ ## Mount it once
46
+
47
+ Put the provider in the root layout, next to the page slot.
48
+
49
+ ```svelte
50
+ <script lang="ts">
51
+ import { page } from "$app/state";
52
+ import { OnboardingProvider, localStorageStore } from "@heyramzi/ui/onboarding";
53
+ import { tours } from "$lib/tours";
54
+
55
+ const strings = {
56
+ next: "Next",
57
+ back: "Back",
58
+ done: "Got it",
59
+ skip: "Skip the tour",
60
+ progress: (n: number, total: number) => `Step ${n} of ${total}`,
61
+ };
62
+ </script>
63
+
64
+ <OnboardingProvider {tours} store={localStorageStore()} {strings} routeId={page.route.id} />
65
+ ```
66
+
67
+ On every navigation it picks the first unseen tour for the route, waits up to 2 seconds for the first step's target,
68
+ drops steps whose target never shows, and starts. A tour with no target on the page starts nothing. One tour per page
69
+ view, never two stacked. Strings are yours, so translate them before you pass them in.
70
+
71
+ | Prop | Default | |
72
+ | --- | --- | --- |
73
+ | `tours` | | From `defineTours`. |
74
+ | `store` | | A `SeenStore`. |
75
+ | `strings` | | `next`, `back`, `done`, `skip`, `progress(n, total)`. |
76
+ | `routeId` | | `page.route.id`. |
77
+ | `enabled` | `true` | Set `false` while signed out. |
78
+ | `replayKey` | `true` | Press `?` to replay. |
79
+ | `waitMs` | `2000` | How long to wait for the first target. |
80
+
81
+ ## Replay
82
+
83
+ ```ts
84
+ import { onboarding } from "@heyramzi/ui/onboarding";
85
+
86
+ onboarding.replay(); // this page's tour
87
+ onboarding.replay("home"); // a named tour
88
+ onboarding.hasTour; // true when this page has one
89
+ ```
90
+
91
+ Replay writes no seen-state. `onboarding.hasTour` is reactive, so a "Show me around" menu item can hide itself on
92
+ pages without a tour.
93
+
94
+ ## Seen-state
95
+
96
+ `SeenStore` is three methods. `load` runs once per session and returns tour id to the version seen.
97
+
98
+ ```ts
99
+ interface SeenStore {
100
+ load(): Promise<Record<string, number>>;
101
+ markSeen(tourId: string, version: number, outcome: "completed" | "dismissed"): Promise<void>;
102
+ reset(tourId?: string): Promise<void>;
103
+ }
104
+ ```
105
+
106
+ The store keeps a version, not a boolean. Raise a tour's `version` after the page changes and everyone sees it
107
+ again. `localStorageStore(key?)` and `memoryStore(initial?)` come with the package and also live at
108
+ `@heyramzi/ui/onboarding/stores`. Server stores belong in the app: a table keyed by user and tour id, and a `fetch`
109
+ adapter.
110
+
111
+ If `load` rejects, no tour shows that session.
112
+
113
+ ## Phones and motion
114
+
115
+ Under 640px every step is a bottom sheet over the page, and the target scrolls above it. With
116
+ `prefers-reduced-motion` the spotlight and card stop animating.
117
+
118
+ ## License
119
+
120
+ MIT
@@ -0,0 +1,50 @@
1
+ import { describe, expect, it } from "vite-plus/test";
2
+ import { defineTours } from "./define-tours.js";
3
+ import type { Step, Tour } from "./types.js";
4
+
5
+ const step = (n: number): Step => ({ target: `[data-tour="s${n}"]`, title: `Title ${n}`, body: `Body ${n}` });
6
+ const steps = (count: number) => Array.from({ length: count }, (_, i) => step(i + 1));
7
+ const board = (over: Partial<Extract<Tour, { kind: "steps" }>> = {}): Tour => ({
8
+ id: "board",
9
+ route: "/(app)/projects",
10
+ kind: "steps",
11
+ steps: steps(3),
12
+ ...over,
13
+ });
14
+
15
+ describe("defineTours", () => {
16
+ it("returns the tours it was given", () => {
17
+ const list = [board(), { id: "home", route: "/(app)", kind: "intro", title: "Hi", body: "Welcome." } as const];
18
+ expect(defineTours(list)).toBe(list);
19
+ });
20
+
21
+ it("rejects a repeated id", () => {
22
+ expect(() => defineTours([board(), board({ route: "/(app)/other" })])).toThrow(/"board".*used twice/);
23
+ });
24
+
25
+ it("takes 1 to 6 steps", () => {
26
+ expect(() => defineTours([board({ steps: steps(1) })])).not.toThrow();
27
+ expect(() => defineTours([board({ steps: steps(6) })])).not.toThrow();
28
+ expect(() => defineTours([board({ steps: [] })])).toThrow(/0 steps/);
29
+ expect(() => defineTours([board({ steps: steps(7) })])).toThrow(/7 steps/);
30
+ });
31
+
32
+ it("rejects a route that isn't a route id", () => {
33
+ expect(() => defineTours([board({ route: "projects" })])).toThrow(/not a route id/);
34
+ });
35
+
36
+ it("rejects a bad version", () => {
37
+ expect(() => defineTours([board({ version: 0 })])).toThrow(/version/);
38
+ expect(() => defineTours([board({ version: 1.5 })])).toThrow(/version/);
39
+ expect(() => defineTours([board({ version: 2 })])).not.toThrow();
40
+ });
41
+
42
+ it("rejects a step with no target or no words", () => {
43
+ expect(() => defineTours([board({ steps: [{ ...step(1), target: " " }] })])).toThrow(/step 1 has no target/);
44
+ expect(() => defineTours([board({ steps: [{ ...step(1), body: "" }] })])).toThrow(/title and a body/);
45
+ });
46
+
47
+ it("rejects an intro with no title", () => {
48
+ expect(() => defineTours([{ id: "home", route: "/(app)", kind: "intro", title: "", body: "x" }])).toThrow(/intro/);
49
+ });
50
+ });
@@ -0,0 +1,31 @@
1
+ import { MAX_STEPS, type Tour } from "./types.js";
2
+
3
+ function fail(id: string, problem: string): never {
4
+ throw new Error(`tour "${id}": ${problem}`);
5
+ }
6
+
7
+ /** Returns the tours as written, after checking what a typo would hide until a user hits it. */
8
+ export function defineTours<const T extends readonly Tour[]>(tours: T): T {
9
+ const ids = new Set<string>();
10
+ for (const tour of tours) {
11
+ const { id } = tour;
12
+ if (!id || !id.trim()) throw new Error("a tour needs an id");
13
+ if (ids.has(id)) fail(id, "its id is used twice");
14
+ ids.add(id);
15
+ if (!tour.route.startsWith("/")) fail(id, `route "${tour.route}" is not a route id`);
16
+ const version = tour.version ?? 1;
17
+ if (!Number.isInteger(version) || version < 1) fail(id, "version is a whole number from 1");
18
+ if (tour.kind === "intro") {
19
+ if (!tour.title || !tour.body) fail(id, "an intro needs a title and a body");
20
+ continue;
21
+ }
22
+ if (tour.steps.length < 1 || tour.steps.length > MAX_STEPS) {
23
+ fail(id, `has ${tour.steps.length} steps, and a tour takes 1 to ${MAX_STEPS}`);
24
+ }
25
+ tour.steps.forEach((step, i) => {
26
+ if (!step.target.trim()) fail(id, `step ${i + 1} has no target`);
27
+ if (!step.title || !step.body) fail(id, `step ${i + 1} needs a title and a body`);
28
+ });
29
+ }
30
+ return tours;
31
+ }
@@ -0,0 +1,86 @@
1
+ <script lang="ts">
2
+ import { Button } from "../shadcn/button/index.js";
3
+ import { Badge } from "../shadcn/badge/index.js";
4
+ import { Plus } from "phosphor-svelte";
5
+ import OnboardingProvider from "./onboarding-provider.svelte";
6
+ import { defineTours } from "./define-tours.js";
7
+ import { memoryStore } from "./stores.js";
8
+ import type { Strings } from "./types.js";
9
+
10
+ const tours = defineTours([
11
+ {
12
+ id: "demo:intro",
13
+ route: "/demo/intro",
14
+ kind: "intro",
15
+ title: "The week in one place",
16
+ body: "Open work sits on the left. Anything late floats to the top.",
17
+ },
18
+ {
19
+ id: "demo:board",
20
+ route: "/demo/board",
21
+ kind: "steps",
22
+ steps: [
23
+ { target: '[data-tour="demo-new"]', title: "Start here", body: "A new project takes a name and a client. That's all.", placement: "bottom-end" },
24
+ { target: '[data-tour="demo-filter"]', title: "Narrow it down", body: "Late shows what slipped. Mine shows what's yours.", placement: "bottom-start" },
25
+ { target: '[data-tour="demo-list"]', title: "Open a row", body: "Click a project to see its tasks, files and notes.", placement: "top" },
26
+ ],
27
+ },
28
+ ]);
29
+
30
+ const strings: Strings = {
31
+ next: "Next",
32
+ back: "Back",
33
+ done: "Got it",
34
+ skip: "Skip the tour",
35
+ progress: (n, total) => `Step ${n} of ${total}`,
36
+ };
37
+
38
+ const rows = [
39
+ { name: "Brand refresh", client: "Northwind", tone: "success" as const, label: "On track" },
40
+ { name: "Pricing page", client: "Acme", tone: "warning" as const, label: "Late" },
41
+ { name: "Launch email", client: "Globex", tone: "neutral" as const, label: "Draft" },
42
+ ];
43
+
44
+ let routeId = $state<string | null>(null);
45
+ let run = $state(0);
46
+ let store = $state(memoryStore());
47
+
48
+ // A fresh store each time, so the button always has an unseen tour to show.
49
+ function start(route: string) {
50
+ store = memoryStore();
51
+ routeId = route;
52
+ run += 1;
53
+ }
54
+ </script>
55
+
56
+ <div class="flex flex-col gap-4">
57
+ <div class="flex flex-wrap gap-2">
58
+ <Button variant="outline" size="sm" onclick={() => start("/demo/board")}>Show the page tour</Button>
59
+ <Button variant="outline" size="sm" onclick={() => start("/demo/intro")}>Show the intro card</Button>
60
+ </div>
61
+
62
+ <div class="bg-card ring-foreground/10 flex flex-col gap-4 rounded-xl p-4 ring-1">
63
+ <div class="flex items-center justify-between gap-3">
64
+ <h2 class="text-sm font-semibold">Projects</h2>
65
+ <Button size="sm" data-tour="demo-new"><Plus weight="bold" />New project</Button>
66
+ </div>
67
+ <div class="flex gap-1.5" data-tour="demo-filter">
68
+ <Badge variant="outline">All</Badge>
69
+ <Badge variant="outline">Late</Badge>
70
+ <Badge variant="outline">Mine</Badge>
71
+ </div>
72
+ <ul class="divide-border border-border divide-y rounded-lg border" data-tour="demo-list">
73
+ {#each rows as row (row.name)}
74
+ <li class="flex items-center justify-between gap-3 px-3 py-2.5 text-sm">
75
+ <span class="min-w-0 truncate font-medium">{row.name}</span>
76
+ <span class="text-muted-foreground hidden sm:block">{row.client}</span>
77
+ <Badge variant="outline">{row.label}</Badge>
78
+ </li>
79
+ {/each}
80
+ </ul>
81
+ </div>
82
+ </div>
83
+
84
+ {#key run}
85
+ <OnboardingProvider {tours} {store} {strings} {routeId} replayKey={false} />
86
+ {/key}
@@ -0,0 +1,12 @@
1
+ export { default as OnboardingProvider } from "./onboarding-provider.svelte";
2
+ export { onboarding } from "./onboarding.svelte.js";
3
+ export { defineTours } from "./define-tours.js";
4
+ export { localStorageStore, memoryStore } from "./stores.js";
5
+ export type {
6
+ Outcome,
7
+ Placement,
8
+ SeenStore,
9
+ Step,
10
+ Strings,
11
+ Tour,
12
+ } from "./types.js";