Reputation: 11
I’m using react-quilljs to add posts to my blog, and now I need to implement a gallery feature using this library. I want to create a gallery in the format
<ul><li><img></li></ul>.
I’ve searched online and checked various resources, but I couldn’t figure out exactly how to implement this functionality. Has anyone already done something similar? I’d really appreciate any advice, examples, or guidance on how to make this work. npm lib - https://www.npmjs.com/package/react-quilljs
import Quill from 'quill';
const BlockEmbed = Quill.import('blots/block/embed');
class GalleryBlot extends BlockEmbed {
static create(value) {
const node = super.create();
if (value && value.images) {
const galleryContainer = document.createElement('div');
galleryContainer.classList.add('quill-gallery');
value.images.forEach((url) => {
const img = document.createElement('img');
img.setAttribute('src', url);
img.setAttribute('alt', 'Gallery Image');
galleryContainer.appendChild(img);
});
node.appendChild(galleryContainer);
}
return node;
}
static value(node) {
const images = [];
node.querySelectorAll('img').forEach((img) => {
images.push(img.getAttribute('src'));
});
console.log('GalleryBlot.value повертає:', images);
return { images };
}
}
GalleryBlot.blotName = 'gallery';
GalleryBlot.tagName = 'div';
GalleryBlot.className = 'quill-gallery';
Quill.register(GalleryBlot, true);
console.log(Quill.imports);
export default GalleryBlot;
part of the component code
'use client';
import { useQuill } from 'react-quilljs';
import { useEffect } from 'react';
import './module/GalleryBlot';
import 'quill/dist/quill.snow.css';
import './QuillJS.scss';
import styles from './QuillJS.module.scss';
const QuillJS = ({ quillValue, setQuillValue, curentLang }) => {
const { quill, quillRef, Quill } = useQuill();
useEffect(() => {
if (!quill) return;
quill.on('text-change', handleTextChange);
quill.getModule('toolbar').addHandler('image', selectLocalImage);
return () => {
quill.off('text-change', handleTextChange);
};
}, [quill, curentLang]);
useEffect(() => {
if (!quill) return;
quill.root.innerHTML = quillValue[curentLang] || '';
}, [quill, curentLang]);
const handleTextChange = () => {
setQuillValue((prev) => ({
...prev,
[curentLang]: quill.root.innerHTML,
}));
};
const selectLocalImage = () => {
const input = document.createElement('input');
input.setAttribute('type', 'file');
input.setAttribute('accept', 'image/*');
input.setAttribute('multiple', 'true');
input.click();
input.onchange = () => {
const files = Array.from(input.files);
if (files.length > 0) {
saveToServer(files);
}
};
};
const saveToServer = async (files) => {
const body = new FormData();
files.forEach((file, index) => body.append(`files-${index}`, file));
try {
const res = await fetch('/api/postImage', {
method: 'POST',
body,
});
const data = await res?.json();
if (res.ok && data.urls) {
if (files.length === 1) {
insertToEditor(data.urls[0]);
} else {
insertGalleryToEditor(data.urls);
}
} else {
console.error('Помилка завантаження зображення:', data.message);
}
} catch (error) {
console.error('Помилка завантаження зображення:', error);
}
};
const insertToEditor = (url) => {
const range = quill.getSelection();
quill.insertEmbed(range.index, 'image', url);
};
const insertGalleryToEditor = (urls) => {
const range = quill.getSelection();
quill.insertEmbed(range.index, 'gallery', urls);
};
return (
<li className={styles.QuillJS}>
<div ref={quillRef} />
</li>
);
};
export default QuillJS;
Upvotes: 0
Views: 32