@heyramzi/ui 2.1.0 → 2.3.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 (317) hide show
  1. package/COMPONENTS.md +1 -1
  2. package/package.json +7 -8
  3. package/scripts/sync-shadcn.mjs +3 -4
  4. package/src/agents/agent-avatar.svelte +604 -575
  5. package/src/agents/agent-cast.svelte +179 -183
  6. package/src/agents/demo.svelte +125 -113
  7. package/src/agents/helpers.ts +23 -17
  8. package/src/agents/index.ts +4 -4
  9. package/src/agents/page-state.ts +6 -6
  10. package/src/agents/types.ts +6 -6
  11. package/src/ai/ai-button/AiButton.svelte +4 -12
  12. package/src/ai/generation-progress/GenerationProgress.svelte +10 -3
  13. package/src/ai/prompt-input/PromptInputTextarea.svelte +1 -2
  14. package/src/ai/response/Response.css +2 -3
  15. package/src/animations/avatar-group-hover.css +2 -16
  16. package/src/animations/card-tilt.css +3 -6
  17. package/src/animations/digit-pop-in.css +2 -15
  18. package/src/animations/dropdown.css +4 -17
  19. package/src/animations/input-clear-dissolve.css +5 -18
  20. package/src/animations/input-shake.css +9 -41
  21. package/src/animations/learn-more-hover.css +17 -9
  22. package/src/animations/like-button.css +2 -4
  23. package/src/animations/page-side-by-side.css +2 -10
  24. package/src/animations/plus-menu-morph.css +2 -5
  25. package/src/animations/shimmer-text.css +5 -18
  26. package/src/animations/spinning-counter.css +2 -6
  27. package/src/animations/success-check.css +2 -15
  28. package/src/animations/thinking-states.css +2 -7
  29. package/src/brand/brand.test.ts +21 -5
  30. package/src/brand/index.ts +4 -10
  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/canvas-cleanup.test.ts +1 -1
  49. package/src/canvas/headless/svg-figure.test.ts +5 -1
  50. package/src/canvas/lod/lod-switch.svelte +111 -106
  51. package/src/canvas/ops/ops.ts +1 -1
  52. package/src/canvas/pen/PenField.svelte +87 -81
  53. package/src/canvas/pen/PenOverlay.svelte +127 -127
  54. package/src/canvas/pen/ShapeNode.svelte +31 -32
  55. package/src/canvas/pen/TextNode.svelte +54 -53
  56. package/src/canvas/pen/host-field.test.svelte +7 -7
  57. package/src/canvas/pen/shapes.ts +7 -1
  58. package/src/canvas/screen/GlyphIcon.svelte +22 -17
  59. package/src/canvas/screen/PartView.svelte +138 -72
  60. package/src/canvas/screen/ScreenBody.svelte +81 -60
  61. package/src/canvas/screen/ScreenCard.svelte +20 -20
  62. package/src/canvas/ui/CanvasToolbar.svelte +173 -85
  63. package/src/canvas/ui/FrameLayer.svelte +59 -59
  64. package/src/canvas/ui/PenLayer.svelte +39 -30
  65. package/src/canvas/ui/StylePanel.svelte +119 -102
  66. package/src/canvas/ui/canvas-grid.svelte +137 -129
  67. package/src/charts/animated-value.svelte +1 -1
  68. package/src/charts/area-chart.css +2 -5
  69. package/src/charts/area-chart.svelte +1 -1
  70. package/src/charts/bar-chart.css +2 -3
  71. package/src/charts/bar-chart.svelte +1 -1
  72. package/src/charts/charts.css +5 -17
  73. package/src/charts/crosshair.svelte +1 -1
  74. package/src/charts/dashboard/dashboard-empty.svelte +25 -25
  75. package/src/charts/dashboard/dashboard-section.svelte +24 -24
  76. package/src/charts/dashboard/data-panel.svelte +50 -50
  77. package/src/charts/dashboard/data-sort-head.svelte +56 -56
  78. package/src/charts/dashboard/data-table.svelte +138 -138
  79. package/src/charts/dashboard/panel-grid.svelte +30 -30
  80. package/src/charts/dashboard/period-filter.svelte +25 -25
  81. package/src/charts/dashboard/rating-chip.svelte +19 -19
  82. package/src/charts/dashboard/stat-band.svelte +32 -32
  83. package/src/charts/dashboard/stat-tile.svelte +106 -99
  84. package/src/charts/donut-chart.svelte +1 -1
  85. package/src/charts/edge-fade.svelte +1 -1
  86. package/src/charts/figure.svelte +1 -1
  87. package/src/charts/gauge-chart.css +4 -7
  88. package/src/charts/gauge-chart.svelte +1 -1
  89. package/src/charts/hover-focus.svelte +1 -1
  90. package/src/charts/legend.css +1 -3
  91. package/src/charts/legend.svelte +1 -1
  92. package/src/charts/line-chart.svelte +1 -1
  93. package/src/charts/number-chart.css +6 -9
  94. package/src/charts/number-chart.svelte +1 -1
  95. package/src/charts/reference-line.svelte +19 -19
  96. package/src/charts/reveal.svelte +1 -1
  97. package/src/charts/ring-chart.css +2 -4
  98. package/src/charts/ring-chart.svelte +1 -1
  99. package/src/charts/sparkline.svelte +5 -2
  100. package/src/charts/stat-card.svelte +1 -1
  101. package/src/charts/time-series-chart.css +2 -5
  102. package/src/charts/trend-pill.css +2 -4
  103. package/src/charts/trend-pill.svelte +1 -1
  104. package/src/components/copy/copy-button.svelte +93 -98
  105. package/src/components/copy/copy-button.test.ts +10 -2
  106. package/src/components/data-table/infinite-scroll.svelte +42 -42
  107. package/src/components/data-table/pagination.svelte +34 -22
  108. package/src/components/data-table/row-arrow.svelte +19 -16
  109. package/src/components/data-table/row-context-menu.svelte +52 -52
  110. package/src/components/data-table/sortable-head.svelte +25 -25
  111. package/src/components/data-table/table-skeleton.svelte +41 -36
  112. package/src/components/docs/doc-page.svelte +18 -9
  113. package/src/components/docs/on-this-page.svelte +16 -3
  114. package/src/components/docs/scroll-spy.svelte.ts +2 -3
  115. package/src/components/field-row/field-row.svelte +10 -8
  116. package/src/components/hold-to-confirm/hold-to-confirm.svelte +5 -1
  117. package/src/components/icon/icon.svelte +14 -14
  118. package/src/components/language-flag/language-flag.svelte +3 -1
  119. package/src/components/list-page/detail-empty.svelte +34 -34
  120. package/src/components/list-page/detail-header.svelte +55 -47
  121. package/src/components/list-page/detail-panel.svelte +51 -59
  122. package/src/components/list-page/detail-row.svelte +19 -19
  123. package/src/components/list-page/detail-stack.svelte +21 -21
  124. package/src/components/list-page/empty-state.svelte +30 -30
  125. package/src/components/list-page/filter-item.svelte +20 -20
  126. package/src/components/list-page/filter-popover.svelte +60 -55
  127. package/src/components/list-page/grouped-list.svelte +4 -2
  128. package/src/components/list-page/index.ts +5 -1
  129. package/src/components/list-page/list-page-shell.svelte +2 -5
  130. package/src/components/list-page/master-detail.svelte +87 -88
  131. package/src/components/list-page/notice-bar.svelte +38 -38
  132. package/src/components/list-page/prev-next.svelte +63 -63
  133. package/src/components/list-page/rail-body.svelte +18 -18
  134. package/src/components/list-page/rail-empty.svelte +23 -30
  135. package/src/components/list-page/rail-head.svelte +24 -24
  136. package/src/components/list-page/rail-row.svelte +77 -73
  137. package/src/components/list-page/section-host.ts +2 -3
  138. package/src/components/locale-switch/locale-switch.svelte +41 -41
  139. package/src/components/mark/mark.svelte +34 -38
  140. package/src/components/open-in/index.ts +1 -5
  141. package/src/components/open-in/open-in.svelte +40 -40
  142. package/src/components/picker/mark-picker.svelte +49 -49
  143. package/src/components/picker/picker.svelte +5 -3
  144. package/src/components/section-header/section-header.test.ts +7 -1
  145. package/src/components/section-header/section-label.svelte +20 -20
  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/index.ts +1 -1
  158. package/src/components/table-view/table-view.svelte +352 -13
  159. package/src/components/table-view/table-view.test.ts +108 -1
  160. package/src/components/table-view/types.ts +22 -11
  161. package/src/components/tags-input/index.ts +13 -0
  162. package/src/components/tags-input/tags-input.svelte +305 -0
  163. package/src/components/tags-input/tags.test.ts +64 -0
  164. package/src/components/tags-input/tags.ts +142 -0
  165. package/src/components/theme/index.ts +2 -4
  166. package/src/components/theme/theme-provider.svelte +1 -3
  167. package/src/components/toolbar/toolbar-search.svelte +25 -25
  168. package/src/components/toolbar/toolbar.svelte +11 -7
  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/icons/trades.ts +1 -1
  191. package/src/inbox/README.md +1 -3
  192. package/src/inbox/inbox.test.ts +181 -138
  193. package/src/inbox/index.ts +20 -20
  194. package/src/inbox/logic.ts +114 -111
  195. package/src/inbox/thread-inbox.svelte +227 -151
  196. package/src/inbox/types.ts +130 -108
  197. package/src/lib/theme-transition.ts +2 -4
  198. package/src/lib/tone.ts +2 -4
  199. package/src/lib/utils.ts +2 -2
  200. package/src/modules.test.ts +79 -69
  201. package/src/onboarding/define-tours.test.ts +55 -40
  202. package/src/onboarding/define-tours.ts +23 -23
  203. package/src/onboarding/demo.svelte +24 -5
  204. package/src/onboarding/index.ts +1 -8
  205. package/src/onboarding/onboarding-provider.svelte +19 -7
  206. package/src/onboarding/onboarding.svelte.ts +16 -16
  207. package/src/onboarding/pick.test.ts +61 -52
  208. package/src/onboarding/pick.ts +16 -13
  209. package/src/onboarding/stores.test.ts +80 -80
  210. package/src/onboarding/stores.ts +41 -39
  211. package/src/onboarding/tour-card.svelte +30 -5
  212. package/src/onboarding/tour-runner.svelte +12 -3
  213. package/src/onboarding/types.ts +20 -12
  214. package/src/onboarding/wait.ts +22 -22
  215. package/src/panel/side-panel.svelte +94 -93
  216. package/src/record/demo-data.ts +291 -225
  217. package/src/record/field-section.svelte +38 -34
  218. package/src/record/fields.ts +148 -96
  219. package/src/record/format.ts +63 -56
  220. package/src/record/index.ts +49 -35
  221. package/src/record/info-list.svelte +145 -114
  222. package/src/record/kinds.ts +31 -31
  223. package/src/record/logic.ts +216 -214
  224. package/src/record/next-up.svelte +45 -34
  225. package/src/record/project-list.svelte +56 -50
  226. package/src/record/record-demo.svelte +130 -110
  227. package/src/record/record-header.svelte +37 -28
  228. package/src/record/record-shell.svelte +54 -54
  229. package/src/record/record-stats.svelte +25 -25
  230. package/src/record/record-timeline.svelte +134 -114
  231. package/src/record/record.test.ts +430 -309
  232. package/src/record/steps-rail.svelte +225 -216
  233. package/src/record/types.ts +234 -215
  234. package/src/record/where-we-are.svelte +62 -58
  235. package/src/shadcn/button/button.svelte +1 -1
  236. package/src/shadcn/card/card-title.svelte +1 -5
  237. package/src/shadcn/hooks/use-highlighted-code.svelte.ts +2 -13
  238. package/src/shadcn/sheet/sheet-content.svelte +2 -4
  239. package/src/shadcn/table/table-cell.svelte +2 -3
  240. package/src/shadcn/utilities.css +3 -8
  241. package/src/slides/Controls.svelte +150 -124
  242. package/src/slides/Deck.svelte +243 -238
  243. package/src/slides/Fragment.svelte +64 -57
  244. package/src/slides/Overview.svelte +106 -101
  245. package/src/slides/Presenter.svelte +300 -266
  246. package/src/slides/Slide.svelte +185 -170
  247. package/src/slides/SlideList.svelte +16 -12
  248. package/src/slides/ambient.d.ts +1 -1
  249. package/src/slides/bridges.ts +42 -23
  250. package/src/slides/deck-controller.svelte.ts +47 -35
  251. package/src/slides/demo-slides.svelte +330 -306
  252. package/src/slides/demo.svelte +164 -160
  253. package/src/slides/export/capture.ts +20 -16
  254. package/src/slides/export/ffmpeg.ts +43 -38
  255. package/src/slides/export/index.ts +5 -5
  256. package/src/slides/export/launch.ts +3 -1
  257. package/src/slides/export/pdf.ts +30 -27
  258. package/src/slides/export/types.ts +10 -8
  259. package/src/slides/index.ts +11 -11
  260. package/src/slides/labels.ts +22 -19
  261. package/src/slides/layout.ts +9 -2
  262. package/src/slides/model.ts +4 -4
  263. package/src/slides/navigation.ts +43 -31
  264. package/src/slides/theme.css +5 -7
  265. package/src/slides/types.ts +9 -10
  266. package/src/status/define-statuses.ts +17 -24
  267. package/src/status/index.ts +5 -5
  268. package/src/status/status-badge.svelte +3 -1
  269. package/src/status/status-dot.svelte +1 -3
  270. package/src/status/status-icon.svelte +1 -1
  271. package/src/status/status-types.ts +21 -21
  272. package/src/tasks/board-order.ts +2 -4
  273. package/src/tasks/demo.svelte +189 -31
  274. package/src/tasks/detail/detail-demo.svelte +73 -13
  275. package/src/tasks/detail/detail-types.ts +45 -45
  276. package/src/tasks/detail/task-detail.svelte +40 -10
  277. package/src/tasks/detail/task-property.svelte +8 -2
  278. package/src/tasks/detail/task-thread.svelte +53 -12
  279. package/src/tasks/gantt/gantt-bar.svelte +17 -6
  280. package/src/tasks/gantt/gantt-grid.svelte +40 -9
  281. package/src/tasks/gantt/gantt-group-row.svelte +8 -2
  282. package/src/tasks/gantt/gantt-header.svelte +9 -3
  283. package/src/tasks/gantt/gantt-task-row.svelte +26 -6
  284. package/src/tasks/gantt/gantt.css +2 -1
  285. package/src/tasks/gantt/gantt.test.ts +3 -1
  286. package/src/tasks/gantt/logic.test.ts +110 -20
  287. package/src/tasks/gantt/logic.ts +42 -6
  288. package/src/tasks/inbox/inbox-card.svelte +13 -5
  289. package/src/tasks/inbox/inbox-draft.svelte +1 -1
  290. package/src/tasks/inbox/inbox-logic.ts +6 -40
  291. package/src/tasks/inbox/inbox-statuses.ts +23 -23
  292. package/src/tasks/inbox/inbox-trace.svelte +9 -3
  293. package/src/tasks/inbox/inbox-types.ts +54 -58
  294. package/src/tasks/inbox/index.ts +22 -21
  295. package/src/tasks/index.ts +49 -52
  296. package/src/tasks/kanban-board.svelte +16 -12
  297. package/src/tasks/kanban-types.ts +2 -3
  298. package/src/tasks/presets/sales.ts +6 -6
  299. package/src/tasks/task-gantt.svelte +28 -8
  300. package/src/tasks/task-list.svelte +41 -17
  301. package/src/tasks/time/duration.ts +40 -40
  302. package/src/tasks/time/time-chip.svelte +9 -2
  303. package/src/tasks/time/time-dot.svelte +1 -1
  304. package/src/tasks/time/time-ring.svelte +11 -3
  305. package/src/tasks/time/time-tracker.svelte +57 -15
  306. package/src/tasks/time/time-types.ts +57 -57
  307. package/src/tasks/use-kanban-dnd.svelte.ts +2 -3
  308. package/src/thread/index.ts +7 -7
  309. package/src/thread/logic.ts +36 -33
  310. package/src/thread/thread.svelte +82 -16
  311. package/src/thread/thread.test.ts +58 -47
  312. package/src/thread/types.ts +68 -68
  313. package/src/tokens/craft.css +17 -53
  314. package/src/tokens/index.css +3 -13
  315. package/src/tokens/palette.css +13 -11
  316. package/src/tokens/primitives.css +10 -23
  317. package/src/tasks/inbox/inbox.svelte +0 -203
@@ -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>