Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[help] How to prevent click event propagation when clicking on an image inside TransformComponent? #519

Open
namidapoo opened this issue Dec 6, 2024 · 0 comments

Comments

@namidapoo
Copy link

Hi, thank you for maintaining this amazing library!
I'm using react-zoom-pan-pinch in my Next.js project, and I encountered an issue with event propagation.

demo

I want to close the modal when the user clicks outside the image area.
I'm trying it out with alerts first.
I think I only need to prevent the event from propagating when the user clicks on the image, but it's not working.
If I comment out the TransformWrapper and TransformComponent, it works as intended.
How can I achieve this while still using the TransformWrapper and TransformComponent?

import type { Dispatch, FC, SetStateAction } from "react";
import {
  Dialog,
  DialogContent,
  DialogDescription,
  DialogHeader,
  DialogTitle,
} from "@/components/ui/dialog";
import {
  TransformWrapper,
  TransformComponent,
  useControls,
} from "react-zoom-pan-pinch";
import { DialogClose } from "@radix-ui/react-dialog";
import { Minus, Plus, SearchX, X } from "lucide-react";
import { cn } from "@/lib/utils";

type Props = {
  open: boolean;
  onOpenChange: Dispatch<SetStateAction<boolean>>;
};

const PreviewModal: FC<Props> = ({ open, onOpenChange }) => {
  return (
    <Dialog open={open} onOpenChange={onOpenChange}>
      <DialogContent
        className="h-screen min-w-full flex items-center justify-center p-0 border-none bg-transparent"
        onClick={() => alert("clicked")}
      >
        <div className="w-full h-full relative">
          <DialogHeader className="absolute top-0 left-0 bg-black w-full z-10 opacity-50 h-14 text-white flex">
            <div className="flex items-center justify-between px-4 my-auto">
              <div>
                <DialogTitle>title</DialogTitle>
                <DialogDescription>description</DialogDescription>
              </div>
              <DialogClose className="rounded-sm opacity-70 ring-offset-background transition-opacity hover:opacity-100 disabled:pointer-events-none data-[state=open]:bg-accent data-[state=open]:text-muted-foreground">
                <X className="h-4 w-4" />
                <span className="sr-only">Close</span>
              </DialogClose>
            </div>
          </DialogHeader>

          <TransformWrapper minScale={0.5}>
            <MyControl className="absolute bottom-4 left-1/2 transform -translate-x-1/2 z-10" />
            <TransformComponent
              contentStyle={{
                width: "100%",
                height: "100%",
              }}
              wrapperStyle={{
                width: "100%",
                height: "100%",
              }}
            >
              <div className="w-[calc(100%-24rem)] h-[calc(100%-12rem)] mx-auto my-auto flex bg-red-400">
                <img
                  src="https://placehold.jp/300x200.png"
                  alt="Preview"
                  className="max-w-full max-h-full object-contain mx-auto"
                  onClick={(e) => e.stopPropagation()}
                />
              </div>
            </TransformComponent>
          </TransformWrapper>
        </div>
      </DialogContent>
    </Dialog>
  );
};

export default PreviewModal;

type MyControlProps = {
  className?: string;
};

const MyControl: FC<MyControlProps> = ({ className }) => {
  const { zoomIn, zoomOut, resetTransform } = useControls();

  return (
    <div
      className={cn(
        "inline-flex items-center gap-4 rounded-full bg-black/40 p-1 shadow-md",
        className
      )}
    >
      <button
        type="button"
        onClick={() => zoomOut()}
        className="rounded-full p-2 text-white"
      >
        <Minus />
      </button>
      <button
        type="button"
        onClick={() => resetTransform()}
        className="rounded-full p-2 text-white"
      >
        <SearchX />
      </button>
      <button
        type="button"
        onClick={() => zoomIn()}
        className="rounded-full p-2 text-white"
      >
        <Plus />
      </button>
    </div>
  );
};

If there is any information you are missing, please don't hesitate to let me know.
I will provide it immediately.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant