From 6d026aa241bd04d779332078196c3c3a2c878748 Mon Sep 17 00:00:00 2001 From: Gaagul Gigi Date: Mon, 27 Nov 2023 09:34:03 +0530 Subject: [PATCH 1/3] Added preview for image in EditorContent --- src/components/EditorContent/ImagePreview.jsx | 37 +++++++++++++++++ src/components/EditorContent/index.jsx | 41 +++++++++++++------ src/index.scss | 1 + src/styles/editor/_image-preview.scss | 29 +++++++++++++ 4 files changed, 96 insertions(+), 12 deletions(-) create mode 100644 src/components/EditorContent/ImagePreview.jsx create mode 100644 src/styles/editor/_image-preview.scss diff --git a/src/components/EditorContent/ImagePreview.jsx b/src/components/EditorContent/ImagePreview.jsx new file mode 100644 index 00000000..72186b3c --- /dev/null +++ b/src/components/EditorContent/ImagePreview.jsx @@ -0,0 +1,37 @@ +import React, { useRef, useState } from "react"; + +import { useOnClickOutside } from "neetocommons/react-utils"; +import { CloseCircle } from "neetoicons"; +import { Button, Spinner } from "neetoui"; + +const ImagePreview = ({ imagePreviewUrl, setImagePreviewUrl }) => { + const [isLoading, setIsLoading] = useState(true); + + const imagePreviewRef = useRef(null); + + useOnClickOutside(imagePreviewRef, () => setImagePreviewUrl(null), { + enabled: true, + }); + + return ( +
+
+
+ {isLoading && } + Image Preview setIsLoading(false)} + /> +
+ ); +}; + +export default ImagePreview; diff --git a/src/components/EditorContent/index.jsx b/src/components/EditorContent/index.jsx index 92055bfb..278712f9 100644 --- a/src/components/EditorContent/index.jsx +++ b/src/components/EditorContent/index.jsx @@ -1,4 +1,4 @@ -import React, { useEffect, useRef } from "react"; +import React, { useEffect, useRef, useState } from "react"; import classnames from "classnames"; import DOMPurify from "dompurify"; @@ -6,6 +6,7 @@ import CopyToClipboardButton from "neetomolecules/CopyToClipboardButton"; import { createRoot } from "react-dom/client"; import { EDITOR_CONTENT_CLASSNAME, SANITIZE_OPTIONS } from "./constants"; +import ImagePreview from "./ImagePreview"; import { highlightCode, substituteVariables } from "./utils"; const EditorContent = ({ @@ -14,6 +15,7 @@ const EditorContent = ({ className, ...otherProps }) => { + const [imagePreviewUrl, setImagePreviewUrl] = useState(null); const editorContentRef = useRef(null); const htmlContent = substituteVariables(highlightCode(content), variables); @@ -37,6 +39,16 @@ const EditorContent = ({ ); preTag.appendChild(button); }); + + const figureTags = editorContentRef.current?.querySelectorAll("figure"); + figureTags.forEach(figureTag => { + const image = figureTag.querySelector("img"); + if (!image) return; + figureTag.style.cursor = "pointer"; + figureTag.addEventListener("click", () => { + setImagePreviewUrl(image.src); + }); + }); }; useEffect(() => { @@ -44,17 +56,22 @@ const EditorContent = ({ }, [content]); return ( -
+ <> +
+ {imagePreviewUrl && ( + + )} + ); }; diff --git a/src/index.scss b/src/index.scss index e467a127..d76db390 100644 --- a/src/index.scss +++ b/src/index.scss @@ -7,6 +7,7 @@ @import "./styles/editor/editor-content"; @import "./styles/editor/menu"; @import "./styles/editor/media-uploader"; +@import "./styles/editor/image-preview"; @import "./styles/editor/emoji"; @import "./styles/editor/table"; @import "./styles/editor/link-popover"; diff --git a/src/styles/editor/_image-preview.scss b/src/styles/editor/_image-preview.scss new file mode 100644 index 00000000..bdfbfc46 --- /dev/null +++ b/src/styles/editor/_image-preview.scss @@ -0,0 +1,29 @@ +.image-preview-wrapper { + position: fixed; + top: 0; + left: 0; + width: 100%; + height: 100%; + background: rgba(0, 0, 0, 0.5); + display: flex; + justify-content: center; + align-items: center; + z-index: 999999; + + .close-button { + position: absolute; + top: 5%; + right: 5%; + } + + .image-preview { + max-width: 70%; + max-height: 70%; + } + + .spinner { + i { + background-color: rgb(var(--neeto-ui-gray-300)); + } + } +} From ab5d018bbef93e42bfe172d5bbb3508bb4012e21 Mon Sep 17 00:00:00 2001 From: Gaagul Gigi Date: Wed, 6 Dec 2023 23:16:55 +0530 Subject: [PATCH 2/3] Updated styles of ImagePreview --- src/components/EditorContent/ImagePreview.jsx | 25 +++++++++++++++---- src/styles/editor/_image-preview.scss | 6 ++--- 2 files changed, 23 insertions(+), 8 deletions(-) diff --git a/src/components/EditorContent/ImagePreview.jsx b/src/components/EditorContent/ImagePreview.jsx index 72186b3c..ec2bfc0b 100644 --- a/src/components/EditorContent/ImagePreview.jsx +++ b/src/components/EditorContent/ImagePreview.jsx @@ -1,8 +1,9 @@ -import React, { useRef, useState } from "react"; +import React, { useEffect, useRef, useState } from "react"; import { useOnClickOutside } from "neetocommons/react-utils"; -import { CloseCircle } from "neetoicons"; +import { Close } from "neetoicons"; import { Button, Spinner } from "neetoui"; +import { createPortal } from "react-dom"; const ImagePreview = ({ imagePreviewUrl, setImagePreviewUrl }) => { const [isLoading, setIsLoading] = useState(true); @@ -13,11 +14,24 @@ const ImagePreview = ({ imagePreviewUrl, setImagePreviewUrl }) => { enabled: true, }); - return ( + useEffect(() => { + document.addEventListener( + "keydown", + e => e.key === "Escape" && setImagePreviewUrl(null) + ); + + return () => + document.removeEventListener( + "keydown", + e => e.key === "Escape" && setImagePreviewUrl(null) + ); + }, []); + + return createPortal(
+
, + document.body ); }; diff --git a/src/styles/editor/_image-preview.scss b/src/styles/editor/_image-preview.scss index bdfbfc46..3529e8b8 100644 --- a/src/styles/editor/_image-preview.scss +++ b/src/styles/editor/_image-preview.scss @@ -4,7 +4,7 @@ left: 0; width: 100%; height: 100%; - background: rgba(0, 0, 0, 0.5); + background: rgba(var(--neeto-ui-gray-800), 0.5); display: flex; justify-content: center; align-items: center; @@ -12,8 +12,8 @@ .close-button { position: absolute; - top: 5%; - right: 5%; + top: 5px; + right: 5px; } .image-preview { From c9045c51de122305e095fcd1aeb822b093db1da5 Mon Sep 17 00:00:00 2001 From: Gaagul Gigi Date: Wed, 6 Dec 2023 23:34:08 +0530 Subject: [PATCH 3/3] Updatd conditions to satisfy ImagePreview --- src/components/EditorContent/index.jsx | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/components/EditorContent/index.jsx b/src/components/EditorContent/index.jsx index 278712f9..3b1b9c92 100644 --- a/src/components/EditorContent/index.jsx +++ b/src/components/EditorContent/index.jsx @@ -3,6 +3,7 @@ import React, { useEffect, useRef, useState } from "react"; import classnames from "classnames"; import DOMPurify from "dompurify"; import CopyToClipboardButton from "neetomolecules/CopyToClipboardButton"; +import { not } from "ramda"; import { createRoot } from "react-dom/client"; import { EDITOR_CONTENT_CLASSNAME, SANITIZE_OPTIONS } from "./constants"; @@ -43,7 +44,13 @@ const EditorContent = ({ const figureTags = editorContentRef.current?.querySelectorAll("figure"); figureTags.forEach(figureTag => { const image = figureTag.querySelector("img"); - if (!image) return; + const link = figureTag.querySelector("a"); + if ( + !image || + not(window.getComputedStyle(link).pointerEvents === "none") + ) { + return; + } figureTag.style.cursor = "pointer"; figureTag.addEventListener("click", () => { setImagePreviewUrl(image.src);