@heyramzi/ui 2.0.1 → 2.2.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 (341) hide show
  1. package/package.json +48 -24
  2. package/scripts/sync-shadcn.mjs +3 -4
  3. package/src/agents/agent-avatar.svelte +604 -575
  4. package/src/agents/agent-cast.svelte +179 -183
  5. package/src/agents/demo.svelte +125 -113
  6. package/src/agents/helpers.ts +23 -17
  7. package/src/agents/index.ts +4 -4
  8. package/src/agents/page-state.ts +6 -6
  9. package/src/agents/types.ts +6 -6
  10. package/src/ai/ai-button/AiButton.svelte +4 -12
  11. package/src/ai/generation-progress/GenerationProgress.svelte +10 -3
  12. package/src/ai/prompt-input/PromptInputTextarea.svelte +1 -2
  13. package/src/ai/response/Response.css +2 -3
  14. package/src/animations/avatar-group-hover.css +2 -16
  15. package/src/animations/card-tilt.css +3 -6
  16. package/src/animations/digit-pop-in.css +2 -15
  17. package/src/animations/dropdown.css +4 -17
  18. package/src/animations/input-clear-dissolve.css +5 -18
  19. package/src/animations/input-shake.css +9 -41
  20. package/src/animations/learn-more-hover.css +17 -9
  21. package/src/animations/like-button.css +2 -4
  22. package/src/animations/page-side-by-side.css +2 -10
  23. package/src/animations/plus-menu-morph.css +2 -5
  24. package/src/animations/shimmer-text.css +5 -18
  25. package/src/animations/spinning-counter.css +2 -6
  26. package/src/animations/success-check.css +2 -15
  27. package/src/animations/thinking-states.css +2 -7
  28. package/src/brand/brand.test.ts +21 -5
  29. package/src/brand/index.ts +4 -10
  30. package/src/canvas/README.md +9 -12
  31. package/src/canvas/card/card-frame.svelte +43 -39
  32. package/src/canvas/card/resize-handles.svelte +89 -80
  33. package/src/canvas/chrome/chrome-zoom.svelte +101 -100
  34. package/src/canvas/chrome/lock-badge.svelte +8 -8
  35. package/src/canvas/chrome/side-handles.svelte +24 -19
  36. package/src/canvas/chrome/size-chip.svelte +30 -30
  37. package/src/canvas/chrome/snap-guides.svelte +20 -20
  38. package/src/canvas/components/icons/ToolIcon.svelte +8 -8
  39. package/src/canvas/components/shared/svg/PreviewSvg.svelte +19 -19
  40. package/src/canvas/components/shared/svg/ShapeOutline.svelte +71 -48
  41. package/src/canvas/components/shared/svg/StrokeNode.svelte +21 -27
  42. package/src/canvas/components/shared/svg/TextRule.svelte +25 -17
  43. package/src/canvas/edges/bend-handle.svelte +46 -46
  44. package/src/canvas/edges/edge-gradient.svelte +10 -10
  45. package/src/canvas/edges/gradient-edge.svelte +45 -29
  46. package/src/canvas/editor/lock.test.ts +6 -1
  47. package/src/canvas/editor/style.ts +7 -1
  48. package/src/canvas/headless/svg-figure.test.ts +5 -1
  49. package/src/canvas/lod/lod-switch.svelte +111 -106
  50. package/src/canvas/pen/PenField.svelte +87 -81
  51. package/src/canvas/pen/PenOverlay.svelte +127 -127
  52. package/src/canvas/pen/ShapeNode.svelte +31 -32
  53. package/src/canvas/pen/TextNode.svelte +54 -53
  54. package/src/canvas/pen/host-field.test.svelte +7 -7
  55. package/src/canvas/pen/shapes.ts +7 -1
  56. package/src/canvas/screen/GlyphIcon.svelte +22 -17
  57. package/src/canvas/screen/PartView.svelte +138 -72
  58. package/src/canvas/screen/ScreenBody.svelte +81 -60
  59. package/src/canvas/screen/ScreenCard.svelte +20 -20
  60. package/src/canvas/ui/CanvasToolbar.svelte +173 -85
  61. package/src/canvas/ui/FrameLayer.svelte +59 -59
  62. package/src/canvas/ui/PenLayer.svelte +39 -30
  63. package/src/canvas/ui/StylePanel.svelte +119 -102
  64. package/src/canvas/ui/canvas-grid.svelte +137 -129
  65. package/src/charts/animated-value.svelte +1 -1
  66. package/src/charts/area-chart.css +2 -5
  67. package/src/charts/area-chart.svelte +1 -1
  68. package/src/charts/bar-chart.css +2 -3
  69. package/src/charts/bar-chart.svelte +1 -1
  70. package/src/charts/charts.css +5 -17
  71. package/src/charts/crosshair.svelte +1 -1
  72. package/src/charts/dashboard/dashboard-empty.svelte +25 -25
  73. package/src/charts/dashboard/dashboard-section.svelte +24 -24
  74. package/src/charts/dashboard/data-panel.svelte +50 -50
  75. package/src/charts/dashboard/data-sort-head.svelte +56 -56
  76. package/src/charts/dashboard/data-table.svelte +138 -138
  77. package/src/charts/dashboard/panel-grid.svelte +30 -30
  78. package/src/charts/dashboard/period-filter.svelte +25 -25
  79. package/src/charts/dashboard/rating-chip.svelte +19 -19
  80. package/src/charts/dashboard/stat-band.svelte +32 -32
  81. package/src/charts/dashboard/stat-tile.svelte +106 -99
  82. package/src/charts/donut-chart.svelte +1 -1
  83. package/src/charts/edge-fade.svelte +1 -1
  84. package/src/charts/figure.svelte +1 -1
  85. package/src/charts/gauge-chart.css +4 -7
  86. package/src/charts/gauge-chart.svelte +1 -1
  87. package/src/charts/hover-focus.svelte +1 -1
  88. package/src/charts/legend.css +1 -3
  89. package/src/charts/legend.svelte +1 -1
  90. package/src/charts/line-chart.svelte +1 -1
  91. package/src/charts/number-chart.css +6 -9
  92. package/src/charts/number-chart.svelte +1 -1
  93. package/src/charts/reference-line.svelte +19 -19
  94. package/src/charts/reveal.svelte +1 -1
  95. package/src/charts/ring-chart.css +2 -4
  96. package/src/charts/ring-chart.svelte +1 -1
  97. package/src/charts/sparkline.svelte +5 -2
  98. package/src/charts/stat-card.svelte +1 -1
  99. package/src/charts/time-series-chart.css +2 -5
  100. package/src/charts/trend-pill.css +2 -4
  101. package/src/charts/trend-pill.svelte +1 -1
  102. package/src/components/copy/copy-button.svelte +93 -98
  103. package/src/components/copy/copy-button.test.ts +10 -2
  104. package/src/components/data-table/infinite-scroll.svelte +42 -42
  105. package/src/components/data-table/pagination.svelte +34 -22
  106. package/src/components/data-table/row-arrow.svelte +19 -16
  107. package/src/components/data-table/row-context-menu.svelte +52 -52
  108. package/src/components/data-table/sortable-head.svelte +25 -25
  109. package/src/components/data-table/table-skeleton.svelte +41 -36
  110. package/src/components/docs/doc-page.svelte +18 -9
  111. package/src/components/docs/on-this-page.svelte +16 -3
  112. package/src/components/docs/scroll-spy.svelte.ts +2 -3
  113. package/src/components/field-row/field-row.svelte +10 -8
  114. package/src/components/hold-to-confirm/hold-to-confirm.svelte +5 -1
  115. package/src/components/icon/icon.svelte +14 -14
  116. package/src/components/language-flag/language-flag.svelte +3 -1
  117. package/src/components/list-page/detail-empty.svelte +34 -34
  118. package/src/components/list-page/detail-header.svelte +55 -47
  119. package/src/components/list-page/detail-panel.svelte +51 -59
  120. package/src/components/list-page/detail-row.svelte +19 -19
  121. package/src/components/list-page/detail-stack.svelte +21 -21
  122. package/src/components/list-page/empty-state.svelte +30 -30
  123. package/src/components/list-page/filter-item.svelte +20 -20
  124. package/src/components/list-page/filter-popover.svelte +60 -55
  125. package/src/components/list-page/grouped-list.svelte +4 -2
  126. package/src/components/list-page/index.ts +8 -4
  127. package/src/components/list-page/list-page-shell.svelte +2 -5
  128. package/src/components/list-page/master-detail.svelte +87 -88
  129. package/src/components/list-page/notice-bar.svelte +38 -38
  130. package/src/components/list-page/prev-next.svelte +63 -63
  131. package/src/components/list-page/rail-body.svelte +18 -18
  132. package/src/components/list-page/rail-empty.svelte +23 -30
  133. package/src/components/list-page/rail-head.svelte +24 -24
  134. package/src/components/list-page/rail-row.svelte +77 -73
  135. package/src/components/list-page/section-host.ts +2 -3
  136. package/src/components/locale-switch/locale-switch.svelte +41 -41
  137. package/src/components/mark/mark.svelte +34 -38
  138. package/src/components/open-in/index.ts +1 -5
  139. package/src/components/open-in/open-in.svelte +40 -40
  140. package/src/components/picker/mark-picker.svelte +49 -49
  141. package/src/components/picker/picker.svelte +5 -3
  142. package/src/components/section-header/index.ts +1 -0
  143. package/src/components/section-header/section-header.svelte +1 -1
  144. package/src/components/section-header/section-header.test.ts +7 -1
  145. package/src/components/section-header/section-label.svelte +39 -0
  146. package/src/components/segmented/animated-tabs.svelte +31 -2
  147. package/src/components/segmented/collapse.test.ts +2 -1
  148. package/src/components/segmented/index.ts +2 -0
  149. package/src/components/segmented/segment.svelte +52 -49
  150. package/src/components/segmented/segmented-filter.svelte +79 -80
  151. package/src/components/segmented/segmented-nav.svelte +34 -40
  152. package/src/components/segmented/segmented-overflow.svelte +53 -50
  153. package/src/components/segmented/segmented-track.svelte +62 -46
  154. package/src/components/segmented/segmented.ts +2 -3
  155. package/src/components/star-rating-input/star-rating-input.svelte +103 -103
  156. package/src/components/svg/svg.svelte +4 -4
  157. package/src/components/table-view/table-view.svelte +17 -2
  158. package/src/components/table-view/table-view.test.ts +7 -1
  159. package/src/components/table-view/types.ts +11 -11
  160. package/src/components/tags-input/index.ts +13 -0
  161. package/src/components/tags-input/tags-input.svelte +305 -0
  162. package/src/components/tags-input/tags.test.ts +64 -0
  163. package/src/components/tags-input/tags.ts +142 -0
  164. package/src/components/theme/index.ts +2 -4
  165. package/src/components/theme/theme-provider.svelte +1 -3
  166. package/src/components/toolbar/index.ts +2 -0
  167. package/src/components/{list-page → toolbar}/toolbar-search.svelte +25 -25
  168. package/src/components/toolbar/toolbar.svelte +13 -9
  169. package/src/components/toolbar/toolbar.test.ts +10 -1
  170. package/src/design/index.css +21 -78
  171. package/src/design/polish.css +26 -35
  172. package/src/editor/editor-toolbar.svelte +104 -99
  173. package/src/editor/editor.svelte +296 -266
  174. package/src/editor/image-toolbar.svelte +20 -22
  175. package/src/editor/index.ts +1 -4
  176. package/src/editor/inline-editor.svelte +280 -238
  177. package/src/editor/markdown.ts +15 -15
  178. package/src/editor/renderer.svelte +71 -71
  179. package/src/editor/slash-menu.svelte +24 -27
  180. package/src/effects/animated-beam/diagrams/BeamSvg.svelte +1 -1
  181. package/src/effects/image-comparison/ImageComparison.svelte +11 -1
  182. package/src/effects/interactive-hover-button/InteractiveHoverButton.svelte +59 -46
  183. package/src/effects/magic-card/MagicCard.css +14 -7
  184. package/src/effects/marquee/Marquee.svelte +3 -5
  185. package/src/effects/reveal/observe.ts +0 -3
  186. package/src/effects/spotlight/Spotlight.svelte +1 -1
  187. package/src/effects/theme-toggle/ThemeToggle.css +25 -22
  188. package/src/effects/theme-toggle/ThemeToggle.svelte +6 -7
  189. package/src/gallery.test.ts +14 -4
  190. package/src/inbox/README.md +27 -0
  191. package/src/inbox/inbox.test.ts +214 -0
  192. package/src/inbox/index.ts +31 -0
  193. package/src/inbox/logic.ts +169 -0
  194. package/src/inbox/thread-inbox.svelte +439 -0
  195. package/src/inbox/types.ts +161 -0
  196. package/src/lib/theme-transition.ts +2 -4
  197. package/src/lib/tone.ts +2 -4
  198. package/src/lib/utils.ts +2 -2
  199. package/src/modules.test.ts +105 -0
  200. package/src/onboarding/define-tours.test.ts +55 -40
  201. package/src/onboarding/define-tours.ts +23 -23
  202. package/src/onboarding/demo.svelte +24 -5
  203. package/src/onboarding/index.ts +1 -8
  204. package/src/onboarding/onboarding-provider.svelte +19 -7
  205. package/src/onboarding/onboarding.svelte.ts +16 -16
  206. package/src/onboarding/pick.test.ts +61 -52
  207. package/src/onboarding/pick.ts +16 -13
  208. package/src/onboarding/stores.test.ts +80 -80
  209. package/src/onboarding/stores.ts +41 -39
  210. package/src/onboarding/tour-card.svelte +30 -5
  211. package/src/onboarding/tour-runner.svelte +12 -3
  212. package/src/onboarding/types.ts +20 -12
  213. package/src/onboarding/wait.ts +22 -22
  214. package/src/panel/README.md +5 -0
  215. package/src/panel/index.ts +2 -0
  216. package/src/panel/side-panel.svelte +194 -0
  217. package/src/record/README.md +3 -0
  218. package/src/record/demo-data.ts +352 -0
  219. package/src/record/field-section.svelte +57 -0
  220. package/src/record/fields.ts +194 -0
  221. package/src/record/format.ts +94 -0
  222. package/src/{tasks/record → record}/index.ts +49 -35
  223. package/src/{tasks/record → record}/info-list.svelte +145 -114
  224. package/src/record/kinds.ts +42 -0
  225. package/src/record/logic.ts +326 -0
  226. package/src/record/next-up.svelte +81 -0
  227. package/src/{tasks/record → record}/project-list.svelte +56 -50
  228. package/src/{tasks/record → record}/record-demo.svelte +130 -110
  229. package/src/{tasks/record → record}/record-header.svelte +37 -28
  230. package/src/{tasks/record → record}/record-shell.svelte +54 -54
  231. package/src/record/record-stats.svelte +48 -0
  232. package/src/record/record-timeline.svelte +251 -0
  233. package/src/record/record.test.ts +471 -0
  234. package/src/{tasks/record → record}/steps-rail.svelte +225 -216
  235. package/src/record/types.ts +299 -0
  236. package/src/record/where-we-are.svelte +125 -0
  237. package/src/shadcn/button/button.svelte +1 -1
  238. package/src/shadcn/card/card-title.svelte +1 -5
  239. package/src/shadcn/hooks/use-highlighted-code.svelte.ts +2 -13
  240. package/src/shadcn/sheet/sheet-content.svelte +2 -4
  241. package/src/shadcn/table/table-cell.svelte +2 -3
  242. package/src/shadcn/utilities.css +3 -8
  243. package/src/slides/Controls.svelte +150 -124
  244. package/src/slides/Deck.svelte +243 -238
  245. package/src/slides/Fragment.svelte +64 -57
  246. package/src/slides/Overview.svelte +106 -101
  247. package/src/slides/Presenter.svelte +300 -266
  248. package/src/slides/Slide.svelte +185 -170
  249. package/src/slides/SlideList.svelte +16 -12
  250. package/src/slides/ambient.d.ts +1 -1
  251. package/src/slides/bridges.ts +42 -23
  252. package/src/slides/deck-controller.svelte.ts +47 -35
  253. package/src/slides/demo-slides.svelte +330 -306
  254. package/src/slides/demo.svelte +164 -160
  255. package/src/slides/export/capture.ts +20 -16
  256. package/src/slides/export/ffmpeg.ts +43 -38
  257. package/src/slides/export/index.ts +5 -5
  258. package/src/slides/export/launch.ts +3 -1
  259. package/src/slides/export/pdf.ts +30 -27
  260. package/src/slides/export/types.ts +10 -8
  261. package/src/slides/index.ts +11 -11
  262. package/src/slides/labels.ts +22 -19
  263. package/src/slides/layout.ts +9 -2
  264. package/src/slides/model.ts +4 -4
  265. package/src/slides/navigation.ts +43 -31
  266. package/src/slides/theme.css +5 -7
  267. package/src/slides/types.ts +9 -10
  268. package/src/status/README.md +18 -0
  269. package/src/status/define-statuses.ts +25 -0
  270. package/src/status/index.ts +11 -0
  271. package/src/{tasks → status}/status-badge.svelte +3 -1
  272. package/src/{tasks → status}/status-dot.svelte +1 -3
  273. package/src/{tasks → status}/status-icon.svelte +1 -1
  274. package/src/status/status-types.ts +40 -0
  275. package/src/tasks/README.md +1 -1
  276. package/src/tasks/board-order.ts +2 -4
  277. package/src/tasks/demo.svelte +192 -34
  278. package/src/tasks/detail/detail-demo.svelte +75 -15
  279. package/src/tasks/detail/detail-types.ts +45 -45
  280. package/src/tasks/detail/task-detail.svelte +40 -10
  281. package/src/tasks/detail/task-property.svelte +8 -2
  282. package/src/tasks/detail/task-thread.svelte +53 -12
  283. package/src/tasks/gantt/gantt-bar.svelte +17 -6
  284. package/src/tasks/gantt/gantt-grid.svelte +40 -9
  285. package/src/tasks/gantt/gantt-group-row.svelte +8 -2
  286. package/src/tasks/gantt/gantt-header.svelte +9 -3
  287. package/src/tasks/gantt/gantt-task-row.svelte +26 -6
  288. package/src/tasks/gantt/gantt.css +2 -1
  289. package/src/tasks/gantt/gantt.test.ts +4 -2
  290. package/src/tasks/gantt/logic.test.ts +110 -20
  291. package/src/tasks/gantt/logic.ts +42 -6
  292. package/src/tasks/inbox/inbox-card.svelte +15 -7
  293. package/src/tasks/inbox/inbox-draft.svelte +1 -1
  294. package/src/tasks/inbox/inbox-logic.ts +6 -40
  295. package/src/tasks/inbox/inbox-statuses.ts +24 -24
  296. package/src/tasks/inbox/inbox-trace.svelte +9 -3
  297. package/src/tasks/inbox/inbox-types.ts +54 -58
  298. package/src/tasks/inbox/index.ts +22 -21
  299. package/src/tasks/index.ts +52 -53
  300. package/src/tasks/kanban-board.svelte +16 -12
  301. package/src/tasks/kanban-types.ts +2 -3
  302. package/src/tasks/presets/sales.ts +7 -7
  303. package/src/tasks/task-gantt.svelte +28 -8
  304. package/src/tasks/task-list.svelte +41 -17
  305. package/src/tasks/time/duration.ts +40 -40
  306. package/src/tasks/time/time-chip.svelte +9 -2
  307. package/src/tasks/time/time-dot.svelte +1 -1
  308. package/src/tasks/time/time-ring.svelte +11 -3
  309. package/src/tasks/time/time-tracker.svelte +57 -15
  310. package/src/tasks/time/time-types.ts +57 -57
  311. package/src/tasks/use-kanban-dnd.svelte.ts +2 -3
  312. package/src/thread/README.md +31 -0
  313. package/src/thread/index.ts +12 -0
  314. package/src/thread/logic.ts +61 -0
  315. package/src/thread/thread.svelte +432 -0
  316. package/src/thread/thread.test.ts +73 -0
  317. package/src/thread/types.ts +93 -0
  318. package/src/tokens/craft.css +17 -53
  319. package/src/tokens/index.css +3 -13
  320. package/src/tokens/palette.css +13 -11
  321. package/src/tokens/primitives.css +10 -23
  322. package/src/components/list-page/section-label.svelte +0 -39
  323. package/src/tasks/define-statuses.ts +0 -32
  324. package/src/tasks/inbox/inbox.svelte +0 -203
  325. package/src/tasks/record/demo-data.ts +0 -286
  326. package/src/tasks/record/field-section.svelte +0 -53
  327. package/src/tasks/record/fields.ts +0 -142
  328. package/src/tasks/record/format.ts +0 -87
  329. package/src/tasks/record/kinds.ts +0 -42
  330. package/src/tasks/record/logic.ts +0 -324
  331. package/src/tasks/record/next-up.svelte +0 -70
  332. package/src/tasks/record/record-stats.svelte +0 -48
  333. package/src/tasks/record/record-timeline.svelte +0 -231
  334. package/src/tasks/record/record.test.ts +0 -350
  335. package/src/tasks/record/types.ts +0 -280
  336. package/src/tasks/record/where-we-are.svelte +0 -121
  337. package/src/tasks/side-panel.svelte +0 -193
  338. package/src/tasks/status-types.ts +0 -40
  339. /package/src/components/{list-page → toolbar}/toolbar-trigger.ts +0 -0
  340. /package/src/{tasks → panel}/side-panel-types.ts +0 -0
  341. /package/src/{tasks/record → record}/gutter.ts +0 -0
@@ -1,271 +1,276 @@
1
1
  <script lang="ts">
2
- import './theme.css';
3
- import { flushSync, onMount, setContext, untrack } from 'svelte';
4
- import { attachBridge, attachChannel, attachUrlSync } from './bridges.js';
5
- import Controls from './Controls.svelte';
6
- import { DeckController } from './deck-controller.svelte.js';
7
- import Overview from './Overview.svelte';
8
- import SlideList from './SlideList.svelte';
9
- import { DECK_KEY, DEFAULT_CANVAS, type DeckProps } from './types.js';
2
+ import "./theme.css";
3
+ import { flushSync, onMount, setContext, untrack } from "svelte";
4
+ import { attachBridge, attachChannel, attachUrlSync } from "./bridges.js";
5
+ import Controls from "./Controls.svelte";
6
+ import { DeckController } from "./deck-controller.svelte.js";
7
+ import Overview from "./Overview.svelte";
8
+ import SlideList from "./SlideList.svelte";
9
+ import { DECK_KEY, DEFAULT_CANVAS, type DeckProps } from "./types.js";
10
10
 
11
- let {
12
- index = $bindable(0),
13
- step = $bindable(0),
14
- controller = $bindable(),
15
- id,
16
- title,
17
- locale,
18
- canvas = DEFAULT_CANVAS,
19
- theme = 'ink',
20
- transition = 'fade',
21
- slides,
22
- registry,
23
- progress = true,
24
- controls = true,
25
- loop = false,
26
- keyboard = true,
27
- fragments = true,
28
- urlSync = false,
29
- bridge = false,
30
- sync,
31
- presenter,
32
- labels,
33
- class: className,
34
- style,
35
- onchange,
36
- children,
37
- }: DeckProps = $props();
11
+ let {
12
+ index = $bindable(0),
13
+ step = $bindable(0),
14
+ controller = $bindable(),
15
+ id,
16
+ title,
17
+ locale,
18
+ canvas = DEFAULT_CANVAS,
19
+ theme = "ink",
20
+ transition = "fade",
21
+ slides,
22
+ registry,
23
+ progress = true,
24
+ controls = true,
25
+ loop = false,
26
+ keyboard = true,
27
+ fragments = true,
28
+ urlSync = false,
29
+ bridge = false,
30
+ sync,
31
+ presenter,
32
+ labels,
33
+ class: className,
34
+ style,
35
+ onchange,
36
+ children,
37
+ }: DeckProps = $props();
38
38
 
39
- /* The accessors read and write the bindable props, so the controller keeps no copy of them. */
40
- const deck = new DeckController({
41
- get index() {
42
- return index;
43
- },
44
- set index(value) {
45
- index = value;
46
- },
47
- get step() {
48
- return step;
49
- },
50
- set step(value) {
51
- step = value;
52
- },
53
- get loop() {
54
- return loop;
55
- },
56
- get fragments() {
57
- return fragments;
58
- },
59
- get keyboard() {
60
- return keyboard;
61
- },
62
- get presenter() {
63
- return !!presenter;
64
- },
65
- get controls() {
66
- return controls;
67
- },
68
- get canvas() {
69
- return canvas;
70
- },
71
- get labels() {
72
- return labels;
73
- },
74
- transition: viewTransition,
75
- });
76
- controller = deck;
77
- setContext(DECK_KEY, deck);
39
+ /* The accessors read and write the bindable props, so the controller keeps no copy of them. */
40
+ const deck = new DeckController({
41
+ get index() {
42
+ return index;
43
+ },
44
+ set index(value) {
45
+ index = value;
46
+ },
47
+ get step() {
48
+ return step;
49
+ },
50
+ set step(value) {
51
+ step = value;
52
+ },
53
+ get loop() {
54
+ return loop;
55
+ },
56
+ get fragments() {
57
+ return fragments;
58
+ },
59
+ get keyboard() {
60
+ return keyboard;
61
+ },
62
+ get presenter() {
63
+ return !!presenter;
64
+ },
65
+ get controls() {
66
+ return controls;
67
+ },
68
+ get canvas() {
69
+ return canvas;
70
+ },
71
+ get labels() {
72
+ return labels;
73
+ },
74
+ transition: viewTransition,
75
+ });
76
+ controller = deck;
77
+ setContext(DECK_KEY, deck);
78
78
 
79
- let root = $state<HTMLElement>();
80
- let stage = $state<HTMLElement>();
79
+ let root = $state<HTMLElement>();
80
+ let stage = $state<HTMLElement>();
81
81
 
82
- /* Morph hands the swap to the browser, which animates elements sharing a `data-morph` name. */
83
- function viewTransition(update: () => void) {
84
- const reduced = matchMedia('(prefers-reduced-motion: reduce)').matches;
85
- if (transition !== 'morph' || reduced || !document.startViewTransition) return update();
86
- document.documentElement.dataset.deckVt = '';
87
- const run = document.startViewTransition(() => flushSync(update));
88
- run.finished.finally(() => delete document.documentElement.dataset.deckVt);
89
- }
82
+ /* Morph hands the swap to the browser, which animates elements sharing a `data-morph` name. */
83
+ function viewTransition(update: () => void) {
84
+ const reduced = matchMedia("(prefers-reduced-motion: reduce)").matches;
85
+ if (transition !== "morph" || reduced || !document.startViewTransition) return update();
86
+ document.documentElement.dataset.deckVt = "";
87
+ const run = document.startViewTransition(() => flushSync(update));
88
+ run.finished.finally(() => delete document.documentElement.dataset.deckVt);
89
+ }
90
90
 
91
- onMount(() => deck.mount());
91
+ onMount(() => deck.mount());
92
92
 
93
- $effect(() => deck.listen((position) => onchange?.(position.index, position.step)));
94
- $effect(() => {
95
- const options = urlSync;
96
- if (options) return untrack(() => attachUrlSync(deck, options === true ? {} : options));
97
- });
98
- $effect(() => {
99
- const options = bridge;
100
- if (options) return untrack(() => attachBridge(deck, options === true ? {} : options));
101
- });
102
- $effect(() => {
103
- const name = sync;
104
- if (name) return untrack(() => attachChannel(deck, name));
105
- });
93
+ $effect(() => deck.listen((position) => onchange?.(position.index, position.step)));
94
+ $effect(() => {
95
+ const options = urlSync;
96
+ if (options) return untrack(() => attachUrlSync(deck, options === true ? {} : options));
97
+ });
98
+ $effect(() => {
99
+ const options = bridge;
100
+ if (options) return untrack(() => attachBridge(deck, options === true ? {} : options));
101
+ });
102
+ $effect(() => {
103
+ const name = sync;
104
+ if (name) return untrack(() => attachChannel(deck, name));
105
+ });
106
106
 
107
- $effect(() => {
108
- const el = stage;
109
- if (!el) return;
110
- const measure = () => (deck.size = { w: el.offsetWidth, h: el.offsetHeight });
111
- measure();
112
- const observer = new ResizeObserver(measure);
113
- observer.observe(el);
114
- return () => observer.disconnect();
115
- });
107
+ $effect(() => {
108
+ const el = stage;
109
+ if (!el) return;
110
+ const measure = () => (deck.size = { w: el.offsetWidth, h: el.offsetHeight });
111
+ measure();
112
+ const observer = new ResizeObserver(measure);
113
+ observer.observe(el);
114
+ return () => observer.disconnect();
115
+ });
116
116
 
117
- async function toggleFullscreen() {
118
- try {
119
- if (document.fullscreenElement) await document.exitFullscreen();
120
- else await root?.requestFullscreen();
121
- } catch {
122
- /* A browser without the API, or a denied request. */
123
- }
124
- }
117
+ async function toggleFullscreen() {
118
+ try {
119
+ if (document.fullscreenElement) await document.exitFullscreen();
120
+ else await root?.requestFullscreen();
121
+ } catch {
122
+ /* A browser without the API, or a denied request. */
123
+ }
124
+ }
125
125
 
126
- const openPresenter = $derived(
127
- presenter ? () => void window.open(presenter, `heyramzi-slides-${id ?? ''}`, 'popup,width=1280,height=800') : undefined,
128
- );
126
+ const openPresenter = $derived(
127
+ presenter
128
+ ? () =>
129
+ void window.open(presenter, `heyramzi-slides-${id ?? ""}`, "popup,width=1280,height=800")
130
+ : undefined,
131
+ );
129
132
 
130
- function onkeydown(event: KeyboardEvent) {
131
- const action = deck.handleKey(event);
132
- if (action === 'fullscreen') void toggleFullscreen();
133
- else if (action === 'presenter') openPresenter?.();
134
- }
133
+ function onkeydown(event: KeyboardEvent) {
134
+ const action = deck.handleKey(event);
135
+ if (action === "fullscreen") void toggleFullscreen();
136
+ else if (action === "presenter") openPresenter?.();
137
+ }
135
138
 
136
- let swipe: { x: number; y: number } | null = null;
137
- function onpointerdown(event: PointerEvent) {
138
- deck.activate();
139
- swipe = event.pointerType === 'mouse' ? null : { x: event.clientX, y: event.clientY };
140
- }
141
- function onpointerup(event: PointerEvent) {
142
- if (!swipe || deck.overview) return;
143
- const dx = event.clientX - swipe.x;
144
- const dy = event.clientY - swipe.y;
145
- swipe = null;
146
- if (Math.abs(dx) < 48 || Math.abs(dx) < Math.abs(dy)) return;
147
- if (dx < 0) deck.next();
148
- else deck.prev();
149
- }
139
+ let swipe: { x: number; y: number } | null = null;
140
+ function onpointerdown(event: PointerEvent) {
141
+ deck.activate();
142
+ swipe = event.pointerType === "mouse" ? null : { x: event.clientX, y: event.clientY };
143
+ }
144
+ function onpointerup(event: PointerEvent) {
145
+ if (!swipe || deck.overview) return;
146
+ const dx = event.clientX - swipe.x;
147
+ const dy = event.clientY - swipe.y;
148
+ swipe = null;
149
+ if (Math.abs(dx) < 48 || Math.abs(dx) < Math.abs(dy)) return;
150
+ if (dx < 0) deck.next();
151
+ else deck.prev();
152
+ }
150
153
  </script>
151
154
 
152
155
  <svelte:head>
153
- {@html `<style>@page{size:${canvas.w}px ${canvas.h}px;margin:0}</style>`}
156
+ {@html `<style>@page{size:${canvas.w}px ${canvas.h}px;margin:0}</style>`}
154
157
  </svelte:head>
155
158
  <svelte:window {onkeydown} />
156
159
 
157
160
  <!-- svelte-ignore a11y_no_noninteractive_tabindex -->
158
161
  <!-- svelte-ignore a11y_no_noninteractive_element_interactions -->
159
162
  <div
160
- bind:this={root}
161
- class={['deck', `deck--${theme}`, className]}
162
- style:aspect-ratio="{canvas.w} / {canvas.h}"
163
- style:--deck-dir={deck.direction}
164
- {style}
165
- lang={locale}
166
- role="region"
167
- aria-roledescription={deck.labels.deckRole}
168
- aria-label={title ?? deck.labels.deck}
169
- tabindex="0"
170
- data-deck={id}
171
- data-view={deck.view}
172
- data-transition={transition}
173
- data-morphing={deck.morphing || undefined}
174
- onfocusin={() => deck.activate()}
175
- onpointerenter={() => deck.activate()}
176
- {onpointerdown}
177
- {onpointerup}
163
+ bind:this={root}
164
+ class={["deck", `deck--${theme}`, className]}
165
+ style:aspect-ratio="{canvas.w} / {canvas.h}"
166
+ style:--deck-dir={deck.direction}
167
+ {style}
168
+ lang={locale}
169
+ role="region"
170
+ aria-roledescription={deck.labels.deckRole}
171
+ aria-label={title ?? deck.labels.deck}
172
+ tabindex="0"
173
+ data-deck={id}
174
+ data-view={deck.view}
175
+ data-transition={transition}
176
+ data-morphing={deck.morphing || undefined}
177
+ onfocusin={() => deck.activate()}
178
+ onpointerenter={() => deck.activate()}
179
+ {onpointerdown}
180
+ {onpointerup}
178
181
  >
179
- <div bind:this={stage} class="deck__stage">
180
- {#if slides && registry}
181
- <SlideList {slides} {registry} unknownLabel={deck.labels.unknownType} />
182
- {:else}
183
- {@render children?.()}
184
- {/if}
185
- {#if deck.overview}
186
- <Overview {deck} returnFocus={root} />
187
- {/if}
188
- </div>
182
+ <div bind:this={stage} class="deck__stage">
183
+ {#if slides && registry}
184
+ <SlideList {slides} {registry} unknownLabel={deck.labels.unknownType} />
185
+ {:else}
186
+ {@render children?.()}
187
+ {/if}
188
+ {#if deck.overview}
189
+ <Overview {deck} returnFocus={root} />
190
+ {/if}
191
+ </div>
189
192
 
190
- <div class="deck__sr" aria-live="polite" aria-atomic="true">{deck.labels.slide(deck.ordinal.n, deck.ordinal.of)}</div>
193
+ <div class="deck__sr" aria-live="polite" aria-atomic="true">
194
+ {deck.labels.slide(deck.ordinal.n, deck.ordinal.of)}
195
+ </div>
191
196
 
192
- {#if progress}
193
- <div
194
- class="deck__progress deck__chrome"
195
- role="progressbar"
196
- aria-label={deck.labels.progress}
197
- aria-valuemin="1"
198
- aria-valuemax={deck.ordinal.of}
199
- aria-valuenow={deck.ordinal.n}
200
- aria-valuetext={deck.labels.slide(deck.ordinal.n, deck.ordinal.of)}
201
- >
202
- <div class="deck__progress-fill" style:transform="scaleX({deck.progress})"></div>
203
- </div>
204
- {/if}
197
+ {#if progress}
198
+ <div
199
+ class="deck__progress deck__chrome"
200
+ role="progressbar"
201
+ aria-label={deck.labels.progress}
202
+ aria-valuemin="1"
203
+ aria-valuemax={deck.ordinal.of}
204
+ aria-valuenow={deck.ordinal.n}
205
+ aria-valuetext={deck.labels.slide(deck.ordinal.n, deck.ordinal.of)}
206
+ >
207
+ <div class="deck__progress-fill" style:transform="scaleX({deck.progress})"></div>
208
+ </div>
209
+ {/if}
205
210
 
206
- {#if controls}
207
- <Controls {deck} onpresenter={openPresenter} onfullscreen={toggleFullscreen} />
208
- {/if}
211
+ {#if controls}
212
+ <Controls {deck} onpresenter={openPresenter} onfullscreen={toggleFullscreen} />
213
+ {/if}
209
214
  </div>
210
215
 
211
216
  <style>
212
- .deck {
213
- position: relative;
214
- display: block;
215
- width: 100%;
216
- height: 100%;
217
- min-height: 0;
218
- overflow: hidden;
219
- container-type: inline-size;
220
- background: var(--deck-letterbox);
221
- color: var(--deck-fg);
222
- font-family: var(--deck-font);
223
- outline: none;
224
- touch-action: pan-y;
225
- -webkit-tap-highlight-color: transparent;
226
- }
227
- .deck:focus-visible {
228
- outline: 2px solid var(--deck-accent);
229
- outline-offset: -2px;
230
- }
231
- .deck:fullscreen {
232
- background: var(--deck-bg);
233
- }
217
+ .deck {
218
+ position: relative;
219
+ display: block;
220
+ width: 100%;
221
+ height: 100%;
222
+ min-height: 0;
223
+ overflow: hidden;
224
+ container-type: inline-size;
225
+ background: var(--deck-letterbox);
226
+ color: var(--deck-fg);
227
+ font-family: var(--deck-font);
228
+ outline: none;
229
+ touch-action: pan-y;
230
+ -webkit-tap-highlight-color: transparent;
231
+ }
232
+ .deck:focus-visible {
233
+ outline: 2px solid var(--deck-accent);
234
+ outline-offset: -2px;
235
+ }
236
+ .deck:fullscreen {
237
+ background: var(--deck-bg);
238
+ }
234
239
 
235
- .deck__stage {
236
- position: absolute;
237
- inset: 0;
238
- overflow: hidden;
239
- }
240
+ .deck__stage {
241
+ position: absolute;
242
+ inset: 0;
243
+ overflow: hidden;
244
+ }
240
245
 
241
- .deck__progress {
242
- position: absolute;
243
- right: 0;
244
- bottom: 0;
245
- left: 0;
246
- z-index: 5;
247
- height: 3px;
248
- background: var(--deck-line);
249
- }
250
- .deck__progress-fill {
251
- height: 100%;
252
- background: var(--deck-accent);
253
- transform-origin: 0 50%;
254
- transition: transform var(--deck-t-morph) var(--deck-ease);
255
- }
246
+ .deck__progress {
247
+ position: absolute;
248
+ right: 0;
249
+ bottom: 0;
250
+ left: 0;
251
+ z-index: 5;
252
+ height: 3px;
253
+ background: var(--deck-line);
254
+ }
255
+ .deck__progress-fill {
256
+ height: 100%;
257
+ background: var(--deck-accent);
258
+ transform-origin: 0 50%;
259
+ transition: transform var(--deck-t-morph) var(--deck-ease);
260
+ }
256
261
 
257
- .deck__sr {
258
- position: absolute;
259
- width: 1px;
260
- height: 1px;
261
- overflow: hidden;
262
- clip-path: inset(50%);
263
- white-space: nowrap;
264
- }
262
+ .deck__sr {
263
+ position: absolute;
264
+ width: 1px;
265
+ height: 1px;
266
+ overflow: hidden;
267
+ clip-path: inset(50%);
268
+ white-space: nowrap;
269
+ }
265
270
 
266
- @media (prefers-reduced-motion: reduce) {
267
- .deck__progress-fill {
268
- transition: none;
269
- }
270
- }
271
+ @media (prefers-reduced-motion: reduce) {
272
+ .deck__progress-fill {
273
+ transition: none;
274
+ }
275
+ }
271
276
  </style>
@@ -1,71 +1,78 @@
1
1
  <script lang="ts">
2
- import { getContext, type Snippet } from 'svelte';
3
- import { SLIDE_KEY, type SlideContext } from './types.js';
2
+ import { getContext, type Snippet } from "svelte";
3
+ import { SLIDE_KEY, type SlideContext } from "./types.js";
4
4
 
5
- interface Props {
6
- /** Reveal at this step. `1` is the first press of the arrow key. */
7
- step?: number;
8
- /** How it arrives: `rise` (default), `fade` or `scale`. */
9
- reveal?: 'rise' | 'fade' | 'scale';
10
- /** The element to render, so a fragment can be an `li` inside a `ul`. */
11
- as?: string;
12
- class?: string;
13
- style?: string;
14
- children?: Snippet;
15
- };
5
+ interface Props {
6
+ /** Reveal at this step. `1` is the first press of the arrow key. */
7
+ step?: number;
8
+ /** How it arrives: `rise` (default), `fade` or `scale`. */
9
+ reveal?: "rise" | "fade" | "scale";
10
+ /** The element to render, so a fragment can be an `li` inside a `ul`. */
11
+ as?: string;
12
+ class?: string;
13
+ style?: string;
14
+ children?: Snippet;
15
+ }
16
16
 
17
- let { step = 1, reveal = 'rise', as: tag = 'div', class: className, style, children }: Props = $props();
17
+ let {
18
+ step = 1,
19
+ reveal = "rise",
20
+ as: tag = "div",
21
+ class: className,
22
+ style,
23
+ children,
24
+ }: Props = $props();
18
25
 
19
- const slide = getContext<SlideContext | undefined>(SLIDE_KEY);
20
- const visible = $derived(slide ? slide.shown(step) : true);
26
+ const slide = getContext<SlideContext | undefined>(SLIDE_KEY);
27
+ const visible = $derived(slide ? slide.shown(step) : true);
21
28
 
22
- /* Fragments that share a step arrive one after another, in the order they mounted. */
23
- let order = $state(0);
24
- $effect(() => {
25
- if (!slide) return;
26
- const joined = slide.join(step);
27
- order = joined.order;
28
- return joined.leave;
29
- });
29
+ /* Fragments that share a step arrive one after another, in the order they mounted. */
30
+ let order = $state(0);
31
+ $effect(() => {
32
+ if (!slide) return;
33
+ const joined = slide.join(step);
34
+ order = joined.order;
35
+ return joined.leave;
36
+ });
30
37
  </script>
31
38
 
32
39
  <svelte:element
33
- this={tag}
34
- class={['deck-fragment', className]}
35
- {style}
36
- style:--frag-i={order}
37
- data-reveal={reveal}
38
- data-visible={visible}
39
- aria-hidden={!visible}
40
- inert={!visible}
40
+ this={tag}
41
+ class={["deck-fragment", className]}
42
+ {style}
43
+ style:--frag-i={order}
44
+ data-reveal={reveal}
45
+ data-visible={visible}
46
+ aria-hidden={!visible}
47
+ inert={!visible}
41
48
  >
42
- {@render children?.()}
49
+ {@render children?.()}
43
50
  </svelte:element>
44
51
 
45
52
  <style>
46
- .deck-fragment {
47
- opacity: 0;
48
- transition:
49
- opacity var(--deck-t-slide) var(--deck-ease),
50
- transform var(--deck-t-slide) var(--deck-ease);
51
- }
52
- .deck-fragment[data-reveal='rise'] {
53
- transform: translateY(var(--deck-shift));
54
- }
55
- .deck-fragment[data-reveal='scale'] {
56
- transform: scale(var(--scale-large, 0.96));
57
- }
58
- .deck-fragment[data-visible='true'] {
59
- opacity: 1;
60
- transform: none;
61
- transition-delay: calc(var(--frag-i) * var(--deck-stagger));
62
- }
53
+ .deck-fragment {
54
+ opacity: 0;
55
+ transition:
56
+ opacity var(--deck-t-slide) var(--deck-ease),
57
+ transform var(--deck-t-slide) var(--deck-ease);
58
+ }
59
+ .deck-fragment[data-reveal="rise"] {
60
+ transform: translateY(var(--deck-shift));
61
+ }
62
+ .deck-fragment[data-reveal="scale"] {
63
+ transform: scale(var(--scale-large, 0.96));
64
+ }
65
+ .deck-fragment[data-visible="true"] {
66
+ opacity: 1;
67
+ transform: none;
68
+ transition-delay: calc(var(--frag-i) * var(--deck-stagger));
69
+ }
63
70
 
64
- @media (prefers-reduced-motion: reduce) {
65
- .deck-fragment {
66
- transform: none !important;
67
- transition: opacity var(--deck-t-quick) linear;
68
- transition-delay: 0s !important;
69
- }
70
- }
71
+ @media (prefers-reduced-motion: reduce) {
72
+ .deck-fragment {
73
+ transform: none !important;
74
+ transition: opacity var(--deck-t-quick) linear;
75
+ transition-delay: 0s !important;
76
+ }
77
+ }
71
78
  </style>