Image Zoom
brandonjt/image-zoomFreeBlock
An interactive image viewer for React apps. Easily zoom, drag, resize, and rotate images with smooth controls. Perfect for galleries, portfolios, or any UI where users need to explore images in detail.
Live preview
live · rendered by the registry
Rendered by brandonjt on their own page — this is the component running, not a screenshot of it.Install it
npx shadcn@latest add https://brandonjuliothenaro.my.id/r/image-zoom.jsonSource
1import { Button } from "@/components/ui/button";2import {3 Dialog,4 DialogContent,5 DialogDescription,6 DialogHeader,7 DialogTitle,8 DialogTrigger,9} from "@/components/ui/dialog";10import {11 IterationCwIcon,12 MinusIcon,13 PlusIcon,14 RotateCwSquareIcon,15} from "lucide-react";16import { motion, useMotionValue, useSpring } from "motion/react";17import Image, { type ImageProps } from "next/image";18import React from "react";1920export const ImageZoom: React.ComponentType<ImageProps> = (imageProps) => {21 return (22 <Dialog>23 <DialogTrigger asChild>24 <Button25 variant="ghost"26 className="relative size-32 overflow-hidden"27 size="icon"28 >29 <Image30 {...imageProps}31 alt={imageProps.alt || ""}32 layout="fill"33 className="object-cover"34 />35 </Button>36 </DialogTrigger>37 <DialogContent className="sm:max-w-[90vw]">38 <DialogHeader>39 <DialogTitle>Image Zoom</DialogTitle>40 <DialogDescription>Image Zoom Description</DialogDescription>41 </DialogHeader>42 <ImageZoomManipulator43 src={imageProps.src.toString()}44 alt={imageProps.alt || ""}45 />46 </DialogContent>47 </Dialog>48 );49};5051export const ImageZoomManipulator: React.ComponentType<52 React.ComponentProps<typeof motion.img>53> = (imageProps) => {54 const [originalDragConstraints, setOriginalDragConstraints] = React.useState({55 top: 0,56 left: 0,57 right: 0,58 bottom: 0,59 });6061 const [currentDragConstraints, setCurrentDragConstraints] = React.useState({62 top: 0,63 left: 0,64 right: 0,65 bottom: 0,66 });6768 const containerRef = React.useRef<HTMLDivElement | null>(null);6970 const scale = useSpring(1, { visualDuration: 0.3, bounce: 0.35 });71 scale.on("change", (value) => {72 setCurrentDragConstraints({73 top: originalDragConstraints.top * value * 0.7,74 left: originalDragConstraints.left * value * 0.7,75 right: originalDragConstraints.right * value * 0.7,76 bottom: originalDragConstraints.bottom * value * 0.7,77 });78 });7980 const rotate = useSpring(0, { visualDuration: 0.35, bounce: 0.2 });8182 const x = useMotionValue(0);83 const y = useMotionValue(0);8485 const [isMounted, setIsMounted] = React.useState(false);8687 React.useEffect(() => {88 setIsMounted(true);89 }, []);9091 return (92 <motion.div93 ref={(ref) => {94 if (containerRef.current) return;9596// … truncated
What it pulls in
npm packages
Other registry items
Files it writes
More from brandonjt
All 2 items| Component | Registry | Kind | Access | Installs | Command |
|---|---|---|---|---|---|
| iOS Mail Tabsios-mail-tabs | brandonjt | Blocks | Free | 2 deps |
