From 61fdf0117861ec24af34ce5215d831ff31c494c6 Mon Sep 17 00:00:00 2001 From: "engine-labs-app[bot]" <140088366+engine-labs-app[bot]@users.noreply.github.com> Date: Thu, 20 Nov 2025 00:41:49 +0000 Subject: [PATCH] feat(plugin-thumbnail): integrate thumbnail plugin and add thumbnail sidebar UI --- components/pdf-container/pdf-container.tsx | 218 ++++++++++-------- .../plugin-selection-2/components/index.ts | 4 +- .../plugin-selection-2/hooks/index.ts | 2 +- .../pdf-container/thumbnail-sidebar.tsx | 52 +++++ components/pdf-container/toolbar.tsx | 24 +- package-lock.json | 18 ++ package.json | 1 + tsconfig.json | 2 +- 8 files changed, 215 insertions(+), 106 deletions(-) create mode 100644 components/pdf-container/thumbnail-sidebar.tsx diff --git a/components/pdf-container/pdf-container.tsx b/components/pdf-container/pdf-container.tsx index 0c51e66..6334bd8 100644 --- a/components/pdf-container/pdf-container.tsx +++ b/components/pdf-container/pdf-container.tsx @@ -13,6 +13,7 @@ import { RenderLayer, RenderPluginPackage } from "@embedpdf/plugin-render/react" import { Scroller, ScrollPluginPackage, ScrollStrategy } from "@embedpdf/plugin-scroll/react" import { SearchLayer, SearchPluginPackage } from "@embedpdf/plugin-search/react" import { SelectionLayer, SelectionPluginPackage } from "./plugin-selection-2" +import { ThumbnailPluginPackage } from "@embedpdf/plugin-thumbnail/react" import { TilingLayer, TilingPluginPackage } from "@embedpdf/plugin-tiling/react" import { Viewport, ViewportPluginPackage } from "@embedpdf/plugin-viewport/react" import { PinchWrapper, ZoomMode, ZoomPluginPackage } from "@embedpdf/plugin-zoom/react" @@ -21,6 +22,8 @@ import AnnotationStoreSync from "../annotation-store/annotation-store-sync" import { Spinner } from "../shadcn-ui/spinner" import { AnnotationLayer, AnnotationPluginPackage } from "./plugin-annotation-2" import Toolbar from "./toolbar" +import ThumbnailSidebar from "./thumbnail-sidebar" +import { Sidebar, SidebarContent, SidebarProvider } from "@/components/shadcn-ui/sidebar" const logger = new ConsoleLogger() @@ -46,106 +49,121 @@ export default function PDFContainer({ url }: PDFContainerProps) { } return ( -
-
- - {({ pluginsReady }) => { - return ( - - - - - {!pluginsReady && ( -
- -
- )} - {pluginsReady && ( - - ( - - {/* RednerLayer must go first */} - - - - - {/* SelectionLayer must go last */} - - - )} - /> - - )} -
-
- ) - }} -
+ +
+
+
+ + {({ pluginsReady }) => { + return ( + + + + + {!pluginsReady && ( +
+ +
+ )} + {pluginsReady && ( + + ( + + {/* RednerLayer must go first */} + + + + + {/* SelectionLayer must go last */} + + + )} + /> + + )} +
+
+ ) + }} +
+
+
+ + + + +
-
+ ) } diff --git a/components/pdf-container/plugin-selection-2/components/index.ts b/components/pdf-container/plugin-selection-2/components/index.ts index faf2083..1ce80e2 100644 --- a/components/pdf-container/plugin-selection-2/components/index.ts +++ b/components/pdf-container/plugin-selection-2/components/index.ts @@ -1,2 +1,2 @@ -export * from './selection-layer'; -export * from './copy-to-clipboard'; +export * from "./selection-layer" +export * from "./copy-to-clipboard" diff --git a/components/pdf-container/plugin-selection-2/hooks/index.ts b/components/pdf-container/plugin-selection-2/hooks/index.ts index 01269b6..af27ca4 100644 --- a/components/pdf-container/plugin-selection-2/hooks/index.ts +++ b/components/pdf-container/plugin-selection-2/hooks/index.ts @@ -1 +1 @@ -export * from './use-selection'; +export * from "./use-selection" diff --git a/components/pdf-container/thumbnail-sidebar.tsx b/components/pdf-container/thumbnail-sidebar.tsx new file mode 100644 index 0000000..17965f4 --- /dev/null +++ b/components/pdf-container/thumbnail-sidebar.tsx @@ -0,0 +1,52 @@ +"use client" + +import { useScroll } from "@embedpdf/plugin-scroll/react" +import { ThumbImg, ThumbnailsPane } from "@embedpdf/plugin-thumbnail/react" +import { ScrollArea } from "@/components/shadcn-ui/scroll-area" + +const ThumbnailSidebar = () => { + const { state, provides } = useScroll() + + return ( + +
+ + {(m) => { + const isActive = state.currentPage === m.pageIndex + 1 + return ( +
provides?.scrollToPage({ pageNumber: m.pageIndex + 1 })} + className="w-full cursor-pointer transition-colors hover:bg-gray-50" + > +
+ +
+ + {m.pageIndex + 1} + +
+ ) + }} +
+
+
+ ) +} + +export default ThumbnailSidebar diff --git a/components/pdf-container/toolbar.tsx b/components/pdf-container/toolbar.tsx index 738b08a..e616296 100644 --- a/components/pdf-container/toolbar.tsx +++ b/components/pdf-container/toolbar.tsx @@ -4,6 +4,7 @@ import { useZoom } from "@embedpdf/plugin-zoom/react" import { Download, Highlighter, + Images, Redo2, Trash2, Underline, @@ -11,10 +12,16 @@ import { ZoomIn, ZoomOut, } from "lucide-react" +import { useSidebar } from "@/components/shadcn-ui/sidebar" -const Toolbar = () => { +interface ToolbarProps { + "data-testid"?: string +} + +const Toolbar = ({ "data-testid": dataTestId }: ToolbarProps) => { const { provides: exportApi } = useExportCapability() const { provides: zoom } = useZoom() + const { toggleSidebar } = useSidebar() const { capability: annotationApi, @@ -36,7 +43,10 @@ const Toolbar = () => { ] return ( -
+
{tools.map((tool) => ( + +
+