@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.
- package/package.json +48 -24
- package/scripts/sync-shadcn.mjs +3 -4
- package/src/agents/agent-avatar.svelte +604 -575
- package/src/agents/agent-cast.svelte +179 -183
- package/src/agents/demo.svelte +125 -113
- package/src/agents/helpers.ts +23 -17
- package/src/agents/index.ts +4 -4
- package/src/agents/page-state.ts +6 -6
- package/src/agents/types.ts +6 -6
- package/src/ai/ai-button/AiButton.svelte +4 -12
- package/src/ai/generation-progress/GenerationProgress.svelte +10 -3
- package/src/ai/prompt-input/PromptInputTextarea.svelte +1 -2
- package/src/ai/response/Response.css +2 -3
- package/src/animations/avatar-group-hover.css +2 -16
- package/src/animations/card-tilt.css +3 -6
- package/src/animations/digit-pop-in.css +2 -15
- package/src/animations/dropdown.css +4 -17
- package/src/animations/input-clear-dissolve.css +5 -18
- package/src/animations/input-shake.css +9 -41
- package/src/animations/learn-more-hover.css +17 -9
- package/src/animations/like-button.css +2 -4
- package/src/animations/page-side-by-side.css +2 -10
- package/src/animations/plus-menu-morph.css +2 -5
- package/src/animations/shimmer-text.css +5 -18
- package/src/animations/spinning-counter.css +2 -6
- package/src/animations/success-check.css +2 -15
- package/src/animations/thinking-states.css +2 -7
- package/src/brand/brand.test.ts +21 -5
- package/src/brand/index.ts +4 -10
- package/src/canvas/README.md +9 -12
- package/src/canvas/card/card-frame.svelte +43 -39
- package/src/canvas/card/resize-handles.svelte +89 -80
- package/src/canvas/chrome/chrome-zoom.svelte +101 -100
- package/src/canvas/chrome/lock-badge.svelte +8 -8
- package/src/canvas/chrome/side-handles.svelte +24 -19
- package/src/canvas/chrome/size-chip.svelte +30 -30
- package/src/canvas/chrome/snap-guides.svelte +20 -20
- package/src/canvas/components/icons/ToolIcon.svelte +8 -8
- package/src/canvas/components/shared/svg/PreviewSvg.svelte +19 -19
- package/src/canvas/components/shared/svg/ShapeOutline.svelte +71 -48
- package/src/canvas/components/shared/svg/StrokeNode.svelte +21 -27
- package/src/canvas/components/shared/svg/TextRule.svelte +25 -17
- package/src/canvas/edges/bend-handle.svelte +46 -46
- package/src/canvas/edges/edge-gradient.svelte +10 -10
- package/src/canvas/edges/gradient-edge.svelte +45 -29
- package/src/canvas/editor/lock.test.ts +6 -1
- package/src/canvas/editor/style.ts +7 -1
- package/src/canvas/headless/svg-figure.test.ts +5 -1
- package/src/canvas/lod/lod-switch.svelte +111 -106
- package/src/canvas/pen/PenField.svelte +87 -81
- package/src/canvas/pen/PenOverlay.svelte +127 -127
- package/src/canvas/pen/ShapeNode.svelte +31 -32
- package/src/canvas/pen/TextNode.svelte +54 -53
- package/src/canvas/pen/host-field.test.svelte +7 -7
- package/src/canvas/pen/shapes.ts +7 -1
- package/src/canvas/screen/GlyphIcon.svelte +22 -17
- package/src/canvas/screen/PartView.svelte +138 -72
- package/src/canvas/screen/ScreenBody.svelte +81 -60
- package/src/canvas/screen/ScreenCard.svelte +20 -20
- package/src/canvas/ui/CanvasToolbar.svelte +173 -85
- package/src/canvas/ui/FrameLayer.svelte +59 -59
- package/src/canvas/ui/PenLayer.svelte +39 -30
- package/src/canvas/ui/StylePanel.svelte +119 -102
- package/src/canvas/ui/canvas-grid.svelte +137 -129
- package/src/charts/animated-value.svelte +1 -1
- package/src/charts/area-chart.css +2 -5
- package/src/charts/area-chart.svelte +1 -1
- package/src/charts/bar-chart.css +2 -3
- package/src/charts/bar-chart.svelte +1 -1
- package/src/charts/charts.css +5 -17
- package/src/charts/crosshair.svelte +1 -1
- package/src/charts/dashboard/dashboard-empty.svelte +25 -25
- package/src/charts/dashboard/dashboard-section.svelte +24 -24
- package/src/charts/dashboard/data-panel.svelte +50 -50
- package/src/charts/dashboard/data-sort-head.svelte +56 -56
- package/src/charts/dashboard/data-table.svelte +138 -138
- package/src/charts/dashboard/panel-grid.svelte +30 -30
- package/src/charts/dashboard/period-filter.svelte +25 -25
- package/src/charts/dashboard/rating-chip.svelte +19 -19
- package/src/charts/dashboard/stat-band.svelte +32 -32
- package/src/charts/dashboard/stat-tile.svelte +106 -99
- package/src/charts/donut-chart.svelte +1 -1
- package/src/charts/edge-fade.svelte +1 -1
- package/src/charts/figure.svelte +1 -1
- package/src/charts/gauge-chart.css +4 -7
- package/src/charts/gauge-chart.svelte +1 -1
- package/src/charts/hover-focus.svelte +1 -1
- package/src/charts/legend.css +1 -3
- package/src/charts/legend.svelte +1 -1
- package/src/charts/line-chart.svelte +1 -1
- package/src/charts/number-chart.css +6 -9
- package/src/charts/number-chart.svelte +1 -1
- package/src/charts/reference-line.svelte +19 -19
- package/src/charts/reveal.svelte +1 -1
- package/src/charts/ring-chart.css +2 -4
- package/src/charts/ring-chart.svelte +1 -1
- package/src/charts/sparkline.svelte +5 -2
- package/src/charts/stat-card.svelte +1 -1
- package/src/charts/time-series-chart.css +2 -5
- package/src/charts/trend-pill.css +2 -4
- package/src/charts/trend-pill.svelte +1 -1
- package/src/components/copy/copy-button.svelte +93 -98
- package/src/components/copy/copy-button.test.ts +10 -2
- package/src/components/data-table/infinite-scroll.svelte +42 -42
- package/src/components/data-table/pagination.svelte +34 -22
- package/src/components/data-table/row-arrow.svelte +19 -16
- package/src/components/data-table/row-context-menu.svelte +52 -52
- package/src/components/data-table/sortable-head.svelte +25 -25
- package/src/components/data-table/table-skeleton.svelte +41 -36
- package/src/components/docs/doc-page.svelte +18 -9
- package/src/components/docs/on-this-page.svelte +16 -3
- package/src/components/docs/scroll-spy.svelte.ts +2 -3
- package/src/components/field-row/field-row.svelte +10 -8
- package/src/components/hold-to-confirm/hold-to-confirm.svelte +5 -1
- package/src/components/icon/icon.svelte +14 -14
- package/src/components/language-flag/language-flag.svelte +3 -1
- package/src/components/list-page/detail-empty.svelte +34 -34
- package/src/components/list-page/detail-header.svelte +55 -47
- package/src/components/list-page/detail-panel.svelte +51 -59
- package/src/components/list-page/detail-row.svelte +19 -19
- package/src/components/list-page/detail-stack.svelte +21 -21
- package/src/components/list-page/empty-state.svelte +30 -30
- package/src/components/list-page/filter-item.svelte +20 -20
- package/src/components/list-page/filter-popover.svelte +60 -55
- package/src/components/list-page/grouped-list.svelte +4 -2
- package/src/components/list-page/index.ts +8 -4
- package/src/components/list-page/list-page-shell.svelte +2 -5
- package/src/components/list-page/master-detail.svelte +87 -88
- package/src/components/list-page/notice-bar.svelte +38 -38
- package/src/components/list-page/prev-next.svelte +63 -63
- package/src/components/list-page/rail-body.svelte +18 -18
- package/src/components/list-page/rail-empty.svelte +23 -30
- package/src/components/list-page/rail-head.svelte +24 -24
- package/src/components/list-page/rail-row.svelte +77 -73
- package/src/components/list-page/section-host.ts +2 -3
- package/src/components/locale-switch/locale-switch.svelte +41 -41
- package/src/components/mark/mark.svelte +34 -38
- package/src/components/open-in/index.ts +1 -5
- package/src/components/open-in/open-in.svelte +40 -40
- package/src/components/picker/mark-picker.svelte +49 -49
- package/src/components/picker/picker.svelte +5 -3
- package/src/components/section-header/index.ts +1 -0
- package/src/components/section-header/section-header.svelte +1 -1
- package/src/components/section-header/section-header.test.ts +7 -1
- package/src/components/section-header/section-label.svelte +39 -0
- package/src/components/segmented/animated-tabs.svelte +31 -2
- package/src/components/segmented/collapse.test.ts +2 -1
- package/src/components/segmented/index.ts +2 -0
- package/src/components/segmented/segment.svelte +52 -49
- package/src/components/segmented/segmented-filter.svelte +79 -80
- package/src/components/segmented/segmented-nav.svelte +34 -40
- package/src/components/segmented/segmented-overflow.svelte +53 -50
- package/src/components/segmented/segmented-track.svelte +62 -46
- package/src/components/segmented/segmented.ts +2 -3
- package/src/components/star-rating-input/star-rating-input.svelte +103 -103
- package/src/components/svg/svg.svelte +4 -4
- package/src/components/table-view/table-view.svelte +17 -2
- package/src/components/table-view/table-view.test.ts +7 -1
- package/src/components/table-view/types.ts +11 -11
- package/src/components/tags-input/index.ts +13 -0
- package/src/components/tags-input/tags-input.svelte +305 -0
- package/src/components/tags-input/tags.test.ts +64 -0
- package/src/components/tags-input/tags.ts +142 -0
- package/src/components/theme/index.ts +2 -4
- package/src/components/theme/theme-provider.svelte +1 -3
- package/src/components/toolbar/index.ts +2 -0
- package/src/components/{list-page → toolbar}/toolbar-search.svelte +25 -25
- package/src/components/toolbar/toolbar.svelte +13 -9
- package/src/components/toolbar/toolbar.test.ts +10 -1
- package/src/design/index.css +21 -78
- package/src/design/polish.css +26 -35
- package/src/editor/editor-toolbar.svelte +104 -99
- package/src/editor/editor.svelte +296 -266
- package/src/editor/image-toolbar.svelte +20 -22
- package/src/editor/index.ts +1 -4
- package/src/editor/inline-editor.svelte +280 -238
- package/src/editor/markdown.ts +15 -15
- package/src/editor/renderer.svelte +71 -71
- package/src/editor/slash-menu.svelte +24 -27
- package/src/effects/animated-beam/diagrams/BeamSvg.svelte +1 -1
- package/src/effects/image-comparison/ImageComparison.svelte +11 -1
- package/src/effects/interactive-hover-button/InteractiveHoverButton.svelte +59 -46
- package/src/effects/magic-card/MagicCard.css +14 -7
- package/src/effects/marquee/Marquee.svelte +3 -5
- package/src/effects/reveal/observe.ts +0 -3
- package/src/effects/spotlight/Spotlight.svelte +1 -1
- package/src/effects/theme-toggle/ThemeToggle.css +25 -22
- package/src/effects/theme-toggle/ThemeToggle.svelte +6 -7
- package/src/gallery.test.ts +14 -4
- package/src/inbox/README.md +27 -0
- package/src/inbox/inbox.test.ts +214 -0
- package/src/inbox/index.ts +31 -0
- package/src/inbox/logic.ts +169 -0
- package/src/inbox/thread-inbox.svelte +439 -0
- package/src/inbox/types.ts +161 -0
- package/src/lib/theme-transition.ts +2 -4
- package/src/lib/tone.ts +2 -4
- package/src/lib/utils.ts +2 -2
- package/src/modules.test.ts +105 -0
- package/src/onboarding/define-tours.test.ts +55 -40
- package/src/onboarding/define-tours.ts +23 -23
- package/src/onboarding/demo.svelte +24 -5
- package/src/onboarding/index.ts +1 -8
- package/src/onboarding/onboarding-provider.svelte +19 -7
- package/src/onboarding/onboarding.svelte.ts +16 -16
- package/src/onboarding/pick.test.ts +61 -52
- package/src/onboarding/pick.ts +16 -13
- package/src/onboarding/stores.test.ts +80 -80
- package/src/onboarding/stores.ts +41 -39
- package/src/onboarding/tour-card.svelte +30 -5
- package/src/onboarding/tour-runner.svelte +12 -3
- package/src/onboarding/types.ts +20 -12
- package/src/onboarding/wait.ts +22 -22
- package/src/panel/README.md +5 -0
- package/src/panel/index.ts +2 -0
- package/src/panel/side-panel.svelte +194 -0
- package/src/record/README.md +3 -0
- package/src/record/demo-data.ts +352 -0
- package/src/record/field-section.svelte +57 -0
- package/src/record/fields.ts +194 -0
- package/src/record/format.ts +94 -0
- package/src/{tasks/record → record}/index.ts +49 -35
- package/src/{tasks/record → record}/info-list.svelte +145 -114
- package/src/record/kinds.ts +42 -0
- package/src/record/logic.ts +326 -0
- package/src/record/next-up.svelte +81 -0
- package/src/{tasks/record → record}/project-list.svelte +56 -50
- package/src/{tasks/record → record}/record-demo.svelte +130 -110
- package/src/{tasks/record → record}/record-header.svelte +37 -28
- package/src/{tasks/record → record}/record-shell.svelte +54 -54
- package/src/record/record-stats.svelte +48 -0
- package/src/record/record-timeline.svelte +251 -0
- package/src/record/record.test.ts +471 -0
- package/src/{tasks/record → record}/steps-rail.svelte +225 -216
- package/src/record/types.ts +299 -0
- package/src/record/where-we-are.svelte +125 -0
- package/src/shadcn/button/button.svelte +1 -1
- package/src/shadcn/card/card-title.svelte +1 -5
- package/src/shadcn/hooks/use-highlighted-code.svelte.ts +2 -13
- package/src/shadcn/sheet/sheet-content.svelte +2 -4
- package/src/shadcn/table/table-cell.svelte +2 -3
- package/src/shadcn/utilities.css +3 -8
- package/src/slides/Controls.svelte +150 -124
- package/src/slides/Deck.svelte +243 -238
- package/src/slides/Fragment.svelte +64 -57
- package/src/slides/Overview.svelte +106 -101
- package/src/slides/Presenter.svelte +300 -266
- package/src/slides/Slide.svelte +185 -170
- package/src/slides/SlideList.svelte +16 -12
- package/src/slides/ambient.d.ts +1 -1
- package/src/slides/bridges.ts +42 -23
- package/src/slides/deck-controller.svelte.ts +47 -35
- package/src/slides/demo-slides.svelte +330 -306
- package/src/slides/demo.svelte +164 -160
- package/src/slides/export/capture.ts +20 -16
- package/src/slides/export/ffmpeg.ts +43 -38
- package/src/slides/export/index.ts +5 -5
- package/src/slides/export/launch.ts +3 -1
- package/src/slides/export/pdf.ts +30 -27
- package/src/slides/export/types.ts +10 -8
- package/src/slides/index.ts +11 -11
- package/src/slides/labels.ts +22 -19
- package/src/slides/layout.ts +9 -2
- package/src/slides/model.ts +4 -4
- package/src/slides/navigation.ts +43 -31
- package/src/slides/theme.css +5 -7
- package/src/slides/types.ts +9 -10
- package/src/status/README.md +18 -0
- package/src/status/define-statuses.ts +25 -0
- package/src/status/index.ts +11 -0
- package/src/{tasks → status}/status-badge.svelte +3 -1
- package/src/{tasks → status}/status-dot.svelte +1 -3
- package/src/{tasks → status}/status-icon.svelte +1 -1
- package/src/status/status-types.ts +40 -0
- package/src/tasks/README.md +1 -1
- package/src/tasks/board-order.ts +2 -4
- package/src/tasks/demo.svelte +192 -34
- package/src/tasks/detail/detail-demo.svelte +75 -15
- package/src/tasks/detail/detail-types.ts +45 -45
- package/src/tasks/detail/task-detail.svelte +40 -10
- package/src/tasks/detail/task-property.svelte +8 -2
- package/src/tasks/detail/task-thread.svelte +53 -12
- package/src/tasks/gantt/gantt-bar.svelte +17 -6
- package/src/tasks/gantt/gantt-grid.svelte +40 -9
- package/src/tasks/gantt/gantt-group-row.svelte +8 -2
- package/src/tasks/gantt/gantt-header.svelte +9 -3
- package/src/tasks/gantt/gantt-task-row.svelte +26 -6
- package/src/tasks/gantt/gantt.css +2 -1
- package/src/tasks/gantt/gantt.test.ts +4 -2
- package/src/tasks/gantt/logic.test.ts +110 -20
- package/src/tasks/gantt/logic.ts +42 -6
- package/src/tasks/inbox/inbox-card.svelte +15 -7
- package/src/tasks/inbox/inbox-draft.svelte +1 -1
- package/src/tasks/inbox/inbox-logic.ts +6 -40
- package/src/tasks/inbox/inbox-statuses.ts +24 -24
- package/src/tasks/inbox/inbox-trace.svelte +9 -3
- package/src/tasks/inbox/inbox-types.ts +54 -58
- package/src/tasks/inbox/index.ts +22 -21
- package/src/tasks/index.ts +52 -53
- package/src/tasks/kanban-board.svelte +16 -12
- package/src/tasks/kanban-types.ts +2 -3
- package/src/tasks/presets/sales.ts +7 -7
- package/src/tasks/task-gantt.svelte +28 -8
- package/src/tasks/task-list.svelte +41 -17
- package/src/tasks/time/duration.ts +40 -40
- package/src/tasks/time/time-chip.svelte +9 -2
- package/src/tasks/time/time-dot.svelte +1 -1
- package/src/tasks/time/time-ring.svelte +11 -3
- package/src/tasks/time/time-tracker.svelte +57 -15
- package/src/tasks/time/time-types.ts +57 -57
- package/src/tasks/use-kanban-dnd.svelte.ts +2 -3
- package/src/thread/README.md +31 -0
- package/src/thread/index.ts +12 -0
- package/src/thread/logic.ts +61 -0
- package/src/thread/thread.svelte +432 -0
- package/src/thread/thread.test.ts +73 -0
- package/src/thread/types.ts +93 -0
- package/src/tokens/craft.css +17 -53
- package/src/tokens/index.css +3 -13
- package/src/tokens/palette.css +13 -11
- package/src/tokens/primitives.css +10 -23
- package/src/components/list-page/section-label.svelte +0 -39
- package/src/tasks/define-statuses.ts +0 -32
- package/src/tasks/inbox/inbox.svelte +0 -203
- package/src/tasks/record/demo-data.ts +0 -286
- package/src/tasks/record/field-section.svelte +0 -53
- package/src/tasks/record/fields.ts +0 -142
- package/src/tasks/record/format.ts +0 -87
- package/src/tasks/record/kinds.ts +0 -42
- package/src/tasks/record/logic.ts +0 -324
- package/src/tasks/record/next-up.svelte +0 -70
- package/src/tasks/record/record-stats.svelte +0 -48
- package/src/tasks/record/record-timeline.svelte +0 -231
- package/src/tasks/record/record.test.ts +0 -350
- package/src/tasks/record/types.ts +0 -280
- package/src/tasks/record/where-we-are.svelte +0 -121
- package/src/tasks/side-panel.svelte +0 -193
- package/src/tasks/status-types.ts +0 -40
- /package/src/components/{list-page → toolbar}/toolbar-trigger.ts +0 -0
- /package/src/{tasks → panel}/side-panel-types.ts +0 -0
- /package/src/{tasks/record → record}/gutter.ts +0 -0
package/src/slides/Slide.svelte
CHANGED
|
@@ -1,179 +1,194 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
2
|
+
import { getContext, setContext, type Snippet } from "svelte";
|
|
3
|
+
import type { DeckController, SlideEntry } from "./deck-controller.svelte.js";
|
|
4
|
+
import {
|
|
5
|
+
DECK_KEY,
|
|
6
|
+
SLIDE_KEY,
|
|
7
|
+
type SlideAlign,
|
|
8
|
+
type SlideContext,
|
|
9
|
+
type SlideNotes,
|
|
10
|
+
} from "./types.js";
|
|
11
|
+
|
|
12
|
+
interface Props {
|
|
13
|
+
/** Accessible name, read after "Slide 3 of 12". */
|
|
14
|
+
label?: string;
|
|
15
|
+
/** Speaker notes for the presenter view. */
|
|
16
|
+
notes?: SlideNotes;
|
|
17
|
+
/** Skipped by paging and left out of the overview and print. */
|
|
18
|
+
hidden?: boolean;
|
|
19
|
+
/** `center` (default), `start`, or `bare` to lay the canvas out yourself. */
|
|
20
|
+
align?: SlideAlign;
|
|
21
|
+
class?: string;
|
|
22
|
+
style?: string;
|
|
23
|
+
children?: Snippet;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
let {
|
|
27
|
+
label,
|
|
28
|
+
notes,
|
|
29
|
+
hidden = false,
|
|
30
|
+
align = "center",
|
|
31
|
+
class: className,
|
|
32
|
+
style,
|
|
33
|
+
children,
|
|
34
|
+
}: Props = $props();
|
|
35
|
+
|
|
36
|
+
const deck = getContext<DeckController | undefined>(DECK_KEY);
|
|
37
|
+
if (!deck) throw new Error("<Slide> must be rendered inside <Deck>.");
|
|
38
|
+
|
|
39
|
+
let el = $state<HTMLElement | null>(null);
|
|
40
|
+
let steps = $state(0);
|
|
41
|
+
/* Fragments per step, so one leaving doesn't drop a step another still asks for. */
|
|
42
|
+
const counts = new Map<number, number>();
|
|
43
|
+
|
|
44
|
+
const entry: SlideEntry = {
|
|
45
|
+
id: Symbol("slide"),
|
|
46
|
+
get steps() {
|
|
47
|
+
return steps;
|
|
48
|
+
},
|
|
49
|
+
get hidden() {
|
|
50
|
+
return hidden;
|
|
51
|
+
},
|
|
52
|
+
get label() {
|
|
53
|
+
return label;
|
|
54
|
+
},
|
|
55
|
+
get notes() {
|
|
56
|
+
return notes;
|
|
57
|
+
},
|
|
58
|
+
get el() {
|
|
59
|
+
return el;
|
|
60
|
+
},
|
|
61
|
+
};
|
|
62
|
+
|
|
63
|
+
$effect(() => deck.register(entry));
|
|
64
|
+
|
|
65
|
+
const index = $derived(deck.entries.indexOf(entry));
|
|
66
|
+
const active = $derived(index >= 0 && deck.position.index === index);
|
|
67
|
+
const box = $derived(deck.boxOf(index));
|
|
68
|
+
const order = $derived(Math.max(0, deck.visible.indexOf(index)));
|
|
69
|
+
|
|
70
|
+
/* A slide that is leaving keeps the step it left at, so its fragments don't vanish mid-fade. */
|
|
71
|
+
let held = $state(0);
|
|
72
|
+
$effect.pre(() => {
|
|
73
|
+
if (active) held = deck.position.step;
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
const recount = () => (steps = counts.size ? Math.max(...counts.keys()) : 0);
|
|
77
|
+
|
|
78
|
+
setContext<SlideContext>(SLIDE_KEY, {
|
|
79
|
+
shown: (step) => deck.revealAll || step <= (active ? deck.position.step : held),
|
|
80
|
+
join(step) {
|
|
81
|
+
const order = counts.get(step) ?? 0;
|
|
82
|
+
counts.set(step, order + 1);
|
|
83
|
+
recount();
|
|
84
|
+
return {
|
|
85
|
+
order,
|
|
86
|
+
leave() {
|
|
87
|
+
const left = (counts.get(step) ?? 1) - 1;
|
|
88
|
+
if (left <= 0) counts.delete(step);
|
|
89
|
+
else counts.set(step, left);
|
|
90
|
+
recount();
|
|
91
|
+
},
|
|
92
|
+
};
|
|
93
|
+
},
|
|
94
|
+
});
|
|
95
|
+
|
|
96
|
+
/* A View Transition needs one element per name, so only the active slide holds its morph names. */
|
|
97
|
+
$effect(() => {
|
|
98
|
+
const names = el?.querySelectorAll<HTMLElement>("[data-morph]") ?? [];
|
|
99
|
+
for (const node of names)
|
|
100
|
+
node.style.viewTransitionName = active ? (node.dataset.morph ?? "") : "";
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
const where = $derived(deck.labels.slide(order + 1, deck.visible.length));
|
|
104
|
+
const name = $derived(label ? `${where}: ${label}` : where);
|
|
90
105
|
</script>
|
|
91
106
|
|
|
92
107
|
<section
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
+
bind:this={el}
|
|
109
|
+
class={["slide", className]}
|
|
110
|
+
style:--slide-w="{deck.canvas.w}px"
|
|
111
|
+
style:--slide-h="{deck.canvas.h}px"
|
|
112
|
+
style:--slide-scale={box?.scale}
|
|
113
|
+
style:--i={order}
|
|
114
|
+
style:transform={box ? `translate3d(${box.x}px, ${box.y}px, 0) scale(${box.scale})` : undefined}
|
|
115
|
+
{style}
|
|
116
|
+
{hidden}
|
|
117
|
+
data-active={active}
|
|
118
|
+
role="group"
|
|
119
|
+
aria-roledescription={deck.labels.slideRole}
|
|
120
|
+
aria-label={name}
|
|
121
|
+
aria-hidden={!active}
|
|
122
|
+
inert={!active || deck.overview}
|
|
108
123
|
>
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
124
|
+
<div class="slide__surface" data-align={align}>
|
|
125
|
+
{@render children?.()}
|
|
126
|
+
</div>
|
|
112
127
|
</section>
|
|
113
128
|
|
|
114
129
|
<style>
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
130
|
+
/* The box is a full canvas, moved and scaled from its top-left. */
|
|
131
|
+
.slide {
|
|
132
|
+
position: absolute;
|
|
133
|
+
top: 0;
|
|
134
|
+
left: 0;
|
|
135
|
+
z-index: 1;
|
|
136
|
+
width: var(--slide-w);
|
|
137
|
+
height: var(--slide-h);
|
|
138
|
+
transform-origin: 0 0;
|
|
139
|
+
visibility: hidden;
|
|
140
|
+
/* The old slide stays drawn for the length of the enter animation. */
|
|
141
|
+
transition: visibility 0s linear var(--deck-t-slide);
|
|
142
|
+
}
|
|
143
|
+
.slide[hidden] {
|
|
144
|
+
display: none;
|
|
145
|
+
}
|
|
146
|
+
.slide[data-active="true"] {
|
|
147
|
+
z-index: 2;
|
|
148
|
+
visibility: visible;
|
|
149
|
+
transition-delay: 0s;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
/* The overview shows every slide. They all leave the stack at once and settle in turn, later ones slower. */
|
|
153
|
+
:global(.deck[data-view="overview"]) .slide {
|
|
154
|
+
visibility: visible;
|
|
155
|
+
}
|
|
156
|
+
:global(.deck[data-morphing]) .slide {
|
|
157
|
+
transition:
|
|
158
|
+
visibility 0s linear calc(var(--deck-t-morph) + 10 * var(--deck-stagger)),
|
|
159
|
+
transform calc(var(--deck-t-morph) + min(var(--i), 10) * var(--deck-stagger)) var(--deck-ease);
|
|
160
|
+
}
|
|
161
|
+
/* Opening shows the slides at once, so only closing waits before hiding them. */
|
|
162
|
+
:global(.deck[data-morphing][data-view="overview"]) .slide {
|
|
163
|
+
transition-delay: 0s;
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
.slide__surface {
|
|
167
|
+
position: relative;
|
|
168
|
+
box-sizing: border-box;
|
|
169
|
+
width: 100%;
|
|
170
|
+
height: 100%;
|
|
171
|
+
overflow: hidden;
|
|
172
|
+
color: var(--deck-fg);
|
|
173
|
+
background: var(--deck-bg);
|
|
174
|
+
font-family: var(--deck-font);
|
|
175
|
+
animation: var(--deck-t-slide) var(--deck-ease) backwards;
|
|
176
|
+
}
|
|
177
|
+
:global(.deck[data-view="overview"]) .slide__surface {
|
|
178
|
+
/* Design px, so divide by the scale to get the same corner on every thumbnail. */
|
|
179
|
+
border-radius: calc(10px / var(--slide-scale, 1));
|
|
180
|
+
box-shadow: 0 0 0 calc(1px / var(--slide-scale, 1)) var(--deck-line);
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
.slide__surface[data-align="center"],
|
|
184
|
+
.slide__surface[data-align="start"] {
|
|
185
|
+
display: flex;
|
|
186
|
+
flex-direction: column;
|
|
187
|
+
justify-content: center;
|
|
188
|
+
padding: var(--deck-pad);
|
|
189
|
+
}
|
|
190
|
+
.slide__surface[data-align="center"] {
|
|
191
|
+
align-items: center;
|
|
192
|
+
text-align: center;
|
|
193
|
+
}
|
|
179
194
|
</style>
|
|
@@ -1,19 +1,23 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
|
-
|
|
3
|
-
|
|
2
|
+
import Slide from "./Slide.svelte";
|
|
3
|
+
import type { SlideInstance, SlideRegistry } from "./model.js";
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
interface Props {
|
|
6
|
+
slides: SlideInstance[];
|
|
7
|
+
registry: SlideRegistry;
|
|
8
|
+
unknownLabel: (type: string) => string;
|
|
9
|
+
}
|
|
6
10
|
|
|
7
|
-
|
|
11
|
+
let { slides, registry, unknownLabel }: Props = $props();
|
|
8
12
|
</script>
|
|
9
13
|
|
|
10
14
|
{#each slides as slide (slide.id)}
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
15
|
+
{@const definition = registry[slide.type]}
|
|
16
|
+
<Slide label={definition?.label} notes={slide.notes} hidden={slide.hidden} align="bare">
|
|
17
|
+
{#if definition}
|
|
18
|
+
<definition.layout content={slide.content} {slide} />
|
|
19
|
+
{:else}
|
|
20
|
+
<p class="deck-body" style:padding="var(--deck-pad)">{unknownLabel(slide.type)}</p>
|
|
21
|
+
{/if}
|
|
22
|
+
</Slide>
|
|
19
23
|
{/each}
|
package/src/slides/ambient.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
declare module
|
|
1
|
+
declare module "*.css";
|
package/src/slides/bridges.ts
CHANGED
|
@@ -1,18 +1,24 @@
|
|
|
1
1
|
/* The ways a deck talks to the outside: its URL, a parent frame, another window. Each returns a cleanup. */
|
|
2
2
|
|
|
3
|
-
import type { DeckController } from
|
|
4
|
-
import { parseSlideParam } from
|
|
5
|
-
import type { BridgeOptions, UrlSync } from
|
|
3
|
+
import type { DeckController } from "./deck-controller.svelte.js";
|
|
4
|
+
import { parseSlideParam } from "./navigation.js";
|
|
5
|
+
import type { BridgeOptions, UrlSync } from "./types.js";
|
|
6
6
|
|
|
7
7
|
/** Reads `?s=` once, then keeps it at the current slide. The write is a replace, so Back skips it. */
|
|
8
|
-
export function attachUrlSync(
|
|
9
|
-
|
|
10
|
-
|
|
8
|
+
export function attachUrlSync(
|
|
9
|
+
deck: DeckController,
|
|
10
|
+
{ param = "s", write }: UrlSync = {},
|
|
11
|
+
): () => void {
|
|
12
|
+
const initial = parseSlideParam(
|
|
13
|
+
new URL(location.href).searchParams.get(param),
|
|
14
|
+
deck.entries.length,
|
|
15
|
+
);
|
|
16
|
+
if (initial !== null) deck.go(initial, 0, "remote");
|
|
11
17
|
return deck.listen(({ index }) => {
|
|
12
18
|
const url = new URL(location.href);
|
|
13
19
|
url.searchParams.set(param, String(index + 1));
|
|
14
20
|
if (write) write(url);
|
|
15
|
-
else history.replaceState(history.state,
|
|
21
|
+
else history.replaceState(history.state, "", url);
|
|
16
22
|
});
|
|
17
23
|
}
|
|
18
24
|
|
|
@@ -20,48 +26,61 @@ export function attachUrlSync(deck: DeckController, { param = 's', write }: UrlS
|
|
|
20
26
|
* Lets a host page drive a deck in an iframe. In: `{type:'deck:nav', delta}` and
|
|
21
27
|
* `{type:'deck:go', index, step?}`. Out to the parent: `{type:'deck:change', index, step, total}`.
|
|
22
28
|
*/
|
|
23
|
-
export function attachBridge(
|
|
29
|
+
export function attachBridge(
|
|
30
|
+
deck: DeckController,
|
|
31
|
+
{ origin = location.origin }: BridgeOptions = {},
|
|
32
|
+
): () => void {
|
|
24
33
|
const onMessage = (event: MessageEvent) => {
|
|
25
|
-
if (origin !==
|
|
34
|
+
if (origin !== "*" && event.origin !== origin) return;
|
|
26
35
|
const data = event.data;
|
|
27
|
-
if (data?.type ===
|
|
36
|
+
if (data?.type === "deck:nav") {
|
|
28
37
|
if (data.delta === -1) deck.prev();
|
|
29
38
|
else if (data.delta === 1) deck.next();
|
|
30
|
-
} else if (data?.type ===
|
|
31
|
-
deck.go(data.index, Number.isInteger(data.step) ? data.step : 0,
|
|
39
|
+
} else if (data?.type === "deck:go" && Number.isInteger(data.index)) {
|
|
40
|
+
deck.go(data.index, Number.isInteger(data.step) ? data.step : 0, "remote");
|
|
32
41
|
}
|
|
33
42
|
};
|
|
34
|
-
window.addEventListener(
|
|
43
|
+
window.addEventListener("message", onMessage);
|
|
35
44
|
const stop = deck.listen(({ index, step }, source) => {
|
|
36
|
-
if (source ===
|
|
37
|
-
window.parent.postMessage(
|
|
45
|
+
if (source === "local" && window.parent !== window) {
|
|
46
|
+
window.parent.postMessage(
|
|
47
|
+
{ type: "deck:change", index, step, total: deck.visible.length },
|
|
48
|
+
origin,
|
|
49
|
+
);
|
|
38
50
|
}
|
|
39
51
|
});
|
|
40
52
|
return () => {
|
|
41
|
-
window.removeEventListener(
|
|
53
|
+
window.removeEventListener("message", onMessage);
|
|
42
54
|
stop();
|
|
43
55
|
};
|
|
44
56
|
}
|
|
45
57
|
|
|
46
|
-
type ChannelMessage =
|
|
58
|
+
type ChannelMessage =
|
|
59
|
+
| { type: "state"; from: string; index: number; step: number }
|
|
60
|
+
| { type: "hello"; from: string };
|
|
47
61
|
|
|
48
62
|
/** Mirrors the deck across windows of one origin: the audience screen and a presenter view. */
|
|
49
63
|
export function attachChannel(deck: DeckController, name: string): () => void {
|
|
50
|
-
if (typeof BroadcastChannel ===
|
|
64
|
+
if (typeof BroadcastChannel === "undefined") return () => {};
|
|
51
65
|
const channel = new BroadcastChannel(`heyramzi-slides:${name}`);
|
|
52
66
|
const self = crypto.randomUUID();
|
|
53
67
|
const send = (message: ChannelMessage) => channel.postMessage(message);
|
|
54
|
-
const state = ({ index, step } = deck.position): ChannelMessage => ({
|
|
68
|
+
const state = ({ index, step } = deck.position): ChannelMessage => ({
|
|
69
|
+
type: "state",
|
|
70
|
+
from: self,
|
|
71
|
+
index,
|
|
72
|
+
step,
|
|
73
|
+
});
|
|
55
74
|
|
|
56
75
|
channel.onmessage = ({ data }: MessageEvent<ChannelMessage>) => {
|
|
57
76
|
if (data.from === self) return;
|
|
58
|
-
if (data.type ===
|
|
59
|
-
else deck.go(data.index, data.step,
|
|
77
|
+
if (data.type === "hello") send(state());
|
|
78
|
+
else deck.go(data.index, data.step, "remote");
|
|
60
79
|
};
|
|
61
80
|
const stop = deck.listen((position, source) => {
|
|
62
|
-
if (source ===
|
|
81
|
+
if (source === "local") send(state(position));
|
|
63
82
|
});
|
|
64
|
-
send({ type:
|
|
83
|
+
send({ type: "hello", from: self });
|
|
65
84
|
return () => {
|
|
66
85
|
stop();
|
|
67
86
|
channel.close();
|