Skip to content

Commit 7043ac8

Browse files
committed
zoom controls
1 parent a334a63 commit 7043ac8

File tree

3 files changed

+75
-0
lines changed

3 files changed

+75
-0
lines changed

.changeset/rude-mails-switch.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
---
2+
"htmldocs": patch
3+
"@htmldocs/render": patch
4+
---
5+
6+
add zoom controls

packages/htmldocs/src/app/preview/[...slug]/preview.tsx

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import { DocumentSize } from "~/lib/types";
1313
import { DocumentContextProvider } from '~/contexts/document-context';
1414
import { JSONSchema7, JSONSchema7Definition } from 'json-schema';
1515
import chalk from 'chalk';
16+
import { MagnifyingGlassPlus, MagnifyingGlassMinus, ArrowClockwise } from '@phosphor-icons/react';
1617

1718
interface PreviewProps {
1819
slug: string;
@@ -54,6 +55,8 @@ const Preview = ({
5455
iframe1: renderedDocumentMetadata?.markup,
5556
});
5657

58+
const [zoomLevel, setZoomLevel] = React.useState(1);
59+
5760
// Utility function to generate a simple hash from the markup
5861
const generateHash = (str: string) => {
5962
let hash = 0;
@@ -191,6 +194,46 @@ const Preview = ({
191194

192195
const previewProps = 'previewProps' in renderingResult ? renderingResult.previewProps : {};
193196

197+
const handleZoom = (newZoom: number) => {
198+
setZoomLevel(newZoom);
199+
const iframe = document.querySelector(`iframe[title="${slug}-${activeIframeId}"]`);
200+
if (iframe) {
201+
(iframe as HTMLIFrameElement).contentWindow?.postMessage({
202+
type: 'zoom',
203+
level: newZoom
204+
}, '*');
205+
}
206+
};
207+
208+
const ZoomControls = () => (
209+
<div className="absolute top-4 right-6 z-30 flex gap-1 bg-background/80 backdrop-blur-sm p-1.5 rounded-lg shadow-md border border-border">
210+
<button
211+
onClick={() => handleZoom(Math.max(0.75, zoomLevel - 0.25))}
212+
className="p-1.5 hover:bg-muted rounded-md transition-colors"
213+
title="Zoom Out"
214+
>
215+
<MagnifyingGlassMinus className="text-foreground" size={16} />
216+
</button>
217+
<span className="flex items-center min-w-[3.5rem] justify-center text-sm text-foreground">
218+
{Math.round(zoomLevel * 100)}%
219+
</span>
220+
<button
221+
onClick={() => handleZoom(Math.min(4, zoomLevel + 0.25))}
222+
className="p-1.5 hover:bg-muted rounded-md transition-colors"
223+
title="Zoom In"
224+
>
225+
<MagnifyingGlassPlus className="text-foreground" size={16} />
226+
</button>
227+
<button
228+
onClick={() => handleZoom(1)}
229+
className="p-1.5 hover:bg-muted rounded-md transition-colors"
230+
title="Reset Zoom"
231+
>
232+
<ArrowClockwise className="text-foreground" size={16} />
233+
</button>
234+
</div>
235+
);
236+
194237
return (
195238
<DocumentContextProvider
196239
initialDocumentPreviewProps={previewProps}
@@ -217,6 +260,7 @@ const Preview = ({
217260
{Object.keys(iframes).map((id) =>
218261
renderIframe(id, id === activeIframeId)
219262
)}
263+
<ZoomControls />
220264
</div>
221265
) : null}
222266
<Toaster />

packages/render/src/renderAsync.ts

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -169,6 +169,31 @@ export const renderAsync = async (
169169
// Handle window resize
170170
window.addEventListener("resize", scaleToFit);
171171
172+
// Handle zoom messages from parent
173+
window.addEventListener("message", (event) => {
174+
if (event.data.type === "zoom") {
175+
const htmlElement = document.querySelector("html");
176+
if (htmlElement) {
177+
htmlElement.style.zoom = event.data.level;
178+
// Store zoom level in localStorage
179+
localStorage.setItem("zoomLevel", event.data.level);
180+
}
181+
}
182+
});
183+
184+
// Apply stored zoom level on load
185+
try {
186+
const storedZoom = localStorage.getItem("zoomLevel");
187+
if (storedZoom) {
188+
const htmlElement = document.querySelector("html");
189+
if (htmlElement) {
190+
htmlElement.style.zoom = storedZoom;
191+
}
192+
}
193+
} catch (err) {
194+
console.error("Error applying stored zoom:", err);
195+
}
196+
172197
// Register Paged.js handler when API is available
173198
if (typeof Paged !== "undefined") {
174199
class MyHandler extends Paged.Handler {

0 commit comments

Comments
 (0)