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) => (