@open-slide/core 0.0.2 → 0.0.4

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 (35) hide show
  1. package/bin.js +2 -0
  2. package/dist/{build-DJGuOT6x.js → build-CuoESF2g.js} +1 -1
  3. package/dist/cli/bin.js +5 -5
  4. package/dist/config-DF58h0l4.js +641 -0
  5. package/dist/{dev-0SG0ArzD.js → dev-rlOZacWo.js} +1 -1
  6. package/dist/index.d.ts +7 -9
  7. package/dist/{preview-61Aawrlg.js → preview-DCrD9X36.js} +1 -1
  8. package/dist/vite/index.js +1 -1
  9. package/package.json +7 -4
  10. package/src/app/App.tsx +2 -2
  11. package/src/app/components/ClickNavZones.tsx +34 -0
  12. package/src/app/components/Player.tsx +26 -7
  13. package/src/app/components/ThumbnailRail.tsx +5 -5
  14. package/src/app/components/inspector/CommentPopover.tsx +3 -11
  15. package/src/app/components/inspector/InspectOverlay.tsx +15 -4
  16. package/src/app/components/inspector/InspectorProvider.tsx +12 -5
  17. package/src/app/components/sidebar/FolderItem.tsx +188 -0
  18. package/src/app/components/sidebar/IconPicker.tsx +59 -0
  19. package/src/app/components/sidebar/Sidebar.tsx +118 -0
  20. package/src/app/components/ui/dialog.tsx +141 -0
  21. package/src/app/components/ui/dropdown-menu.tsx +228 -0
  22. package/src/app/components/ui/popover.tsx +72 -0
  23. package/src/app/components/ui/tabs.tsx +79 -0
  24. package/src/app/lib/export-html.ts +313 -0
  25. package/src/app/lib/folders.ts +166 -0
  26. package/src/app/lib/inspector/fiber.ts +2 -2
  27. package/src/app/lib/inspector/useComments.ts +8 -8
  28. package/src/app/lib/sdk.ts +18 -5
  29. package/src/app/lib/slides.ts +8 -0
  30. package/src/app/routes/Home.tsx +540 -63
  31. package/src/app/routes/Slide.tsx +298 -0
  32. package/src/app/virtual.d.ts +4 -4
  33. package/dist/config-Opp2R1Jf.js +0 -335
  34. package/src/app/lib/decks.ts +0 -8
  35. package/src/app/routes/Deck.tsx +0 -185
@@ -1,185 +0,0 @@
1
- import { ChevronLeft, ChevronRight, Play } from 'lucide-react';
2
- import { useCallback, useEffect, useMemo, useState } from 'react';
3
- import { Link, useParams, useSearchParams } from 'react-router-dom';
4
- import { CommentWidget } from '@/components/inspector/CommentWidget';
5
- import { InspectOverlay } from '@/components/inspector/InspectOverlay';
6
- import { InspectorProvider, InspectToggleButton } from '@/components/inspector/InspectorProvider';
7
- import { Button } from '@/components/ui/button';
8
- import { Separator } from '@/components/ui/separator';
9
- import { Player } from '../components/Player';
10
- import { SlideCanvas } from '../components/SlideCanvas';
11
- import { ThumbnailRail } from '../components/ThumbnailRail';
12
- import { loadDeck } from '../lib/decks';
13
- import type { DeckModule } from '../lib/sdk';
14
-
15
- export function Deck() {
16
- const { deckId = '' } = useParams();
17
- const [searchParams, setSearchParams] = useSearchParams();
18
- const [deck, setDeck] = useState<DeckModule | null>(null);
19
- const [error, setError] = useState<string | null>(null);
20
- const [playing, setPlaying] = useState(false);
21
-
22
- useEffect(() => {
23
- let cancelled = false;
24
- setDeck(null);
25
- setError(null);
26
- loadDeck(deckId)
27
- .then((mod) => {
28
- if (!cancelled) setDeck(mod);
29
- })
30
- .catch((e) => {
31
- if (!cancelled) setError(String(e?.message ?? e));
32
- });
33
- return () => {
34
- cancelled = true;
35
- };
36
- }, [deckId]);
37
-
38
- const pages = useMemo(() => deck?.default ?? [], [deck]);
39
- const pageCount = pages.length;
40
- const rawIndex = Number(searchParams.get('p') ?? '1') - 1;
41
- const index = Number.isFinite(rawIndex) ? Math.max(0, Math.min(pageCount - 1, rawIndex)) : 0;
42
-
43
- const goTo = useCallback(
44
- (i: number) => {
45
- const clamped = Math.max(0, Math.min(pageCount - 1, i));
46
- setSearchParams(
47
- (prev) => {
48
- const next = new URLSearchParams(prev);
49
- next.set('p', String(clamped + 1));
50
- return next;
51
- },
52
- { replace: true },
53
- );
54
- },
55
- [pageCount, setSearchParams],
56
- );
57
-
58
- useEffect(() => {
59
- if (playing) return;
60
- const onKey = (e: KeyboardEvent) => {
61
- if (e.target instanceof HTMLElement && e.target.matches('input, textarea')) return;
62
- if (e.key === 'ArrowRight' || e.key === 'PageDown') {
63
- e.preventDefault();
64
- goTo(index + 1);
65
- } else if (e.key === 'ArrowLeft' || e.key === 'PageUp') {
66
- e.preventDefault();
67
- goTo(index - 1);
68
- } else if (e.key === 'f' || e.key === 'F') {
69
- setPlaying(true);
70
- }
71
- };
72
- window.addEventListener('keydown', onKey);
73
- return () => window.removeEventListener('keydown', onKey);
74
- }, [index, goTo, playing]);
75
-
76
- if (error) {
77
- return (
78
- <div className="mx-auto max-w-3xl px-8 py-16 text-muted-foreground">
79
- <Link to="/" className="text-sm font-medium text-primary hover:underline">
80
- ← Home
81
- </Link>
82
- <h2 className="mt-4 text-xl font-semibold text-foreground">Failed to load deck</h2>
83
- <pre className="mt-4 overflow-auto rounded-md border bg-card p-4 text-xs whitespace-pre-wrap shadow-sm">
84
- {error}
85
- </pre>
86
- </div>
87
- );
88
- }
89
-
90
- if (!deck) {
91
- return (
92
- <div className="mx-auto max-w-3xl px-8 py-16 text-sm text-muted-foreground">
93
- Loading {deckId}…
94
- </div>
95
- );
96
- }
97
-
98
- if (pageCount === 0) {
99
- return (
100
- <div className="mx-auto max-w-3xl px-8 py-16 text-muted-foreground">
101
- <Link to="/" className="text-sm font-medium text-primary hover:underline">
102
- ← Home
103
- </Link>
104
- <h2 className="mt-4 text-xl font-semibold text-foreground">Empty deck</h2>
105
- <p className="mt-2 text-sm">
106
- <code className="rounded bg-muted px-1.5 py-0.5 font-mono text-xs">
107
- slides/{deckId}/index.tsx
108
- </code>{' '}
109
- must{' '}
110
- <code className="rounded bg-muted px-1.5 py-0.5 font-mono text-xs">export default</code> a
111
- non-empty array of components.
112
- </p>
113
- </div>
114
- );
115
- }
116
-
117
- if (playing) {
118
- return (
119
- <Player pages={pages} index={index} onIndexChange={goTo} onExit={() => setPlaying(false)} />
120
- );
121
- }
122
-
123
- const CurrentPage = pages[index];
124
- const title = deck.meta?.title ?? deckId;
125
-
126
- return (
127
- <InspectorProvider deckId={deckId}>
128
- <div className="flex h-screen flex-col overflow-hidden bg-background">
129
- <header className="flex shrink-0 items-center gap-4 border-b bg-card px-5 py-3">
130
- <Button asChild variant="ghost" size="sm">
131
- <Link to="/">
132
- <ChevronLeft className="size-4" />
133
- Home
134
- </Link>
135
- </Button>
136
- <Separator orientation="vertical" className="h-5" />
137
- <h1 className="flex-1 text-center text-sm font-semibold tracking-tight">{title}</h1>
138
- <InspectToggleButton />
139
- <Button size="sm" onClick={() => setPlaying(true)}>
140
- <Play className="size-4" />
141
- Play <kbd className="ml-1 rounded bg-primary-foreground/20 px-1 text-[10px]">F</kbd>
142
- </Button>
143
- </header>
144
-
145
- <div className="flex min-h-0 flex-1">
146
- <div className="w-[17rem] shrink-0">
147
- <ThumbnailRail pages={pages} current={index} onSelect={goTo} />
148
- </div>
149
- <main className="relative min-h-0 min-w-0 flex-1 bg-background p-8">
150
- <SlideCanvas>
151
- <CurrentPage />
152
- </SlideCanvas>
153
- <InspectOverlay />
154
- </main>
155
- </div>
156
-
157
- <footer className="flex shrink-0 items-center justify-center gap-4 border-t bg-card p-3">
158
- <Button
159
- variant="outline"
160
- size="sm"
161
- onClick={() => goTo(index - 1)}
162
- disabled={index === 0}
163
- >
164
- <ChevronLeft className="size-4" />
165
- Prev
166
- </Button>
167
- <span className="min-w-16 text-center text-sm text-muted-foreground tabular-nums">
168
- {index + 1} / {pageCount}
169
- </span>
170
- <Button
171
- variant="outline"
172
- size="sm"
173
- onClick={() => goTo(index + 1)}
174
- disabled={index === pageCount - 1}
175
- >
176
- Next
177
- <ChevronRight className="size-4" />
178
- </Button>
179
- </footer>
180
-
181
- <CommentWidget />
182
- </div>
183
- </InspectorProvider>
184
- );
185
- }