@open-slide/core 0.0.9 → 0.0.10

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.
@@ -3,6 +3,7 @@ import { ChevronLeft, Download, FileCode2, FileText, Loader2, Pencil, Play } fro
3
3
  import { type RefObject, useCallback, useEffect, useMemo, useRef, useState } from 'react';
4
4
  import { Link, useParams, useSearchParams } from 'react-router-dom';
5
5
  import { toast } from 'sonner';
6
+ import { AssetView } from '@/components/AssetView';
6
7
  import { CommentWidget } from '@/components/inspector/CommentWidget';
7
8
  import { InspectOverlay } from '@/components/inspector/InspectOverlay';
8
9
  import { InspectorPanel } from '@/components/inspector/InspectorPanel';
@@ -19,7 +20,7 @@ import {
19
20
  DropdownMenuItem,
20
21
  DropdownMenuTrigger,
21
22
  } from '@/components/ui/dropdown-menu';
22
- import { Separator } from '@/components/ui/separator';
23
+ import { Tabs, TabsList, TabsTrigger } from '@/components/ui/tabs';
23
24
  import { useFolders } from '@/lib/folders';
24
25
  import { useWheelPageNavigation } from '@/lib/useWheelPageNavigation';
25
26
  import { cn } from '@/lib/utils';
@@ -65,6 +66,7 @@ export function Slide() {
65
66
  const pageCount = pages.length;
66
67
  const rawIndex = Number(searchParams.get('p') ?? '1') - 1;
67
68
  const index = Number.isFinite(rawIndex) ? Math.max(0, Math.min(pageCount - 1, rawIndex)) : 0;
69
+ const view = searchParams.get('view') === 'assets' ? 'assets' : 'slides';
68
70
 
69
71
  const goTo = useCallback(
70
72
  (i: number) => {
@@ -171,15 +173,50 @@ export function Slide() {
171
173
  <header className="relative flex shrink-0 items-center justify-between border-b bg-card px-3 py-2 md:px-5 md:py-3">
172
174
  <div className="flex items-center gap-2 md:gap-3">
173
175
  {showSlideBrowser && (
174
- <>
175
- <Button asChild variant="ghost" size="sm" className="px-2 md:px-3">
176
- <Link to="/">
177
- <ChevronLeft className="size-4" />
178
- <span className="hidden md:inline">Home</span>
179
- </Link>
180
- </Button>
181
- <Separator orientation="vertical" className="hidden h-5 md:block" />
182
- </>
176
+ <Button asChild variant="ghost" size="sm" className="px-2 md:px-3">
177
+ <Link to="/">
178
+ <ChevronLeft className="size-4" />
179
+ <span className="hidden md:inline">Home</span>
180
+ </Link>
181
+ </Button>
182
+ )}
183
+ {import.meta.env.DEV && (
184
+ <Tabs
185
+ value={view}
186
+ onValueChange={(next) => {
187
+ setSearchParams(
188
+ (prev) => {
189
+ const params = new URLSearchParams(prev);
190
+ if (next === 'assets') params.set('view', 'assets');
191
+ else params.delete('view');
192
+ return params;
193
+ },
194
+ { replace: true },
195
+ );
196
+ }}
197
+ >
198
+ <TabsList className="relative h-7 rounded-md p-0.5 group-data-[orientation=horizontal]/tabs:h-7">
199
+ <div
200
+ aria-hidden
201
+ className="pointer-events-none absolute top-0.5 bottom-0.5 left-0.5 w-[calc(50%-2px)] rounded-[5px] bg-background shadow-sm transition-transform duration-200 ease-out"
202
+ style={{
203
+ transform: view === 'assets' ? 'translateX(100%)' : 'translateX(0)',
204
+ }}
205
+ />
206
+ <TabsTrigger
207
+ value="slides"
208
+ className="relative z-10 h-6 px-3 text-xs data-[state=active]:bg-transparent data-[state=active]:shadow-none dark:data-[state=active]:bg-transparent"
209
+ >
210
+ Slides
211
+ </TabsTrigger>
212
+ <TabsTrigger
213
+ value="assets"
214
+ className="relative z-10 h-6 px-3 text-xs data-[state=active]:bg-transparent data-[state=active]:shadow-none dark:data-[state=active]:bg-transparent"
215
+ >
216
+ Assets
217
+ </TabsTrigger>
218
+ </TabsList>
219
+ </Tabs>
183
220
  )}
184
221
  </div>
185
222
 
@@ -190,7 +227,7 @@ export function Slide() {
190
227
  </div>
191
228
 
192
229
  <div className="flex items-center gap-1.5">
193
- {allowHtmlDownload && (
230
+ {view === 'slides' && allowHtmlDownload && (
194
231
  <DropdownMenu>
195
232
  <DropdownMenuTrigger
196
233
  type="button"
@@ -264,51 +301,59 @@ export function Slide() {
264
301
  </DropdownMenuContent>
265
302
  </DropdownMenu>
266
303
  )}
267
- <InspectToggleButton />
268
- <Button size="sm" onClick={() => setPlaying(true)} className="px-2 md:px-3">
269
- <Play className="size-4" />
270
- <span className="hidden md:inline">Play</span>
271
- <kbd className="ml-1 hidden rounded bg-primary-foreground/20 px-1 text-[10px] md:inline">
272
- F
273
- </kbd>
274
- </Button>
304
+ {view === 'slides' && <InspectToggleButton />}
305
+ {view === 'slides' && (
306
+ <Button size="sm" onClick={() => setPlaying(true)} className="px-2 md:px-3">
307
+ <Play className="size-4" />
308
+ <span className="hidden md:inline">Play</span>
309
+ <kbd className="ml-1 hidden rounded bg-primary-foreground/20 px-1 text-[10px] md:inline">
310
+ F
311
+ </kbd>
312
+ </Button>
313
+ )}
275
314
  </div>
276
315
  </header>
277
316
 
278
- <div className="flex min-h-0 flex-1">
279
- <div className="hidden w-[17rem] shrink-0 md:block">
280
- <ThumbnailRail pages={pages} current={index} onSelect={goTo} />
317
+ {view === 'assets' ? (
318
+ <div className="min-h-0 flex-1">
319
+ <AssetView slideId={slideId} />
281
320
  </div>
282
- <main
283
- ref={slideViewportRef}
284
- data-inspector-root
285
- className="relative min-h-0 min-w-0 flex-1 bg-background p-2 md:p-8"
286
- >
287
- <SlideWheelNavigation
288
- targetRef={slideViewportRef}
289
- onPrev={() => goTo(index - 1)}
290
- onNext={() => goTo(index + 1)}
291
- canPrev={index > 0}
292
- canNext={index < pageCount - 1}
293
- />
294
- <SlideCanvas>
295
- <CurrentPage />
296
- </SlideCanvas>
297
- <ClickNavZones
298
- onPrev={() => goTo(index - 1)}
299
- onNext={() => goTo(index + 1)}
300
- canPrev={index > 0}
301
- canNext={index < pageCount - 1}
302
- />
303
- <InspectOverlay />
304
- <SaveBar />
305
- <CommentWidget />
306
- <div className="pointer-events-none absolute bottom-3 left-1/2 z-10 -translate-x-1/2 rounded-full bg-black/50 px-2.5 py-0.5 text-[11px] font-medium tabular-nums text-white backdrop-blur md:hidden">
307
- {index + 1} / {pageCount}
321
+ ) : (
322
+ <div className="flex min-h-0 flex-1">
323
+ <div className="hidden w-[17rem] shrink-0 md:block">
324
+ <ThumbnailRail pages={pages} current={index} onSelect={goTo} />
308
325
  </div>
309
- </main>
310
- <InspectorPanel />
311
- </div>
326
+ <main
327
+ ref={slideViewportRef}
328
+ data-inspector-root
329
+ className="relative min-h-0 min-w-0 flex-1 bg-background p-2 md:p-8"
330
+ >
331
+ <SlideWheelNavigation
332
+ targetRef={slideViewportRef}
333
+ onPrev={() => goTo(index - 1)}
334
+ onNext={() => goTo(index + 1)}
335
+ canPrev={index > 0}
336
+ canNext={index < pageCount - 1}
337
+ />
338
+ <SlideCanvas>
339
+ <CurrentPage />
340
+ </SlideCanvas>
341
+ <ClickNavZones
342
+ onPrev={() => goTo(index - 1)}
343
+ onNext={() => goTo(index + 1)}
344
+ canPrev={index > 0}
345
+ canNext={index < pageCount - 1}
346
+ />
347
+ <InspectOverlay />
348
+ <SaveBar />
349
+ <CommentWidget />
350
+ <div className="pointer-events-none absolute bottom-3 left-1/2 z-10 -translate-x-1/2 rounded-full bg-black/50 px-2.5 py-0.5 text-[11px] font-medium tabular-nums text-white backdrop-blur md:hidden">
351
+ {index + 1} / {pageCount}
352
+ </div>
353
+ </main>
354
+ <InspectorPanel />
355
+ </div>
356
+ )}
312
357
  </div>
313
358
  </InspectorProvider>
314
359
  );