initial commit - code moved to separate repo
This commit is contained in:
196
components/TextEditor.tsx
Normal file
196
components/TextEditor.tsx
Normal file
@ -0,0 +1,196 @@
|
||||
import axiosInstance from '../src/axiosSecure';
|
||||
import dynamic from 'next/dynamic';
|
||||
|
||||
import React, { useState, useRef, useEffect, forwardRef, useImperativeHandle } from 'react';
|
||||
import 'react-quill/dist/quill.snow.css';
|
||||
|
||||
//!!! working
|
||||
//const ReactQuill = dynamic(() => import('react-quill'), { ssr: false });
|
||||
// const ImageResize = dynamic(() => import('quill-image-resize'), { ssr: false });
|
||||
|
||||
const ReactQuill = dynamic(
|
||||
async () => {
|
||||
const { default: RQ } = await import('react-quill');
|
||||
// const { default: ImageUploader } = await import('./ImageUploader/ImageUploader');
|
||||
const { default: ImageResize } = await import('quill-image-resize');
|
||||
RQ.Quill.register('modules/imageResize', ImageResize);
|
||||
return RQ;
|
||||
},
|
||||
{
|
||||
ssr: false,
|
||||
},
|
||||
);
|
||||
|
||||
|
||||
// import {
|
||||
// Dispatch,
|
||||
// LegacyRef,
|
||||
// memo,
|
||||
// SetStateAction,
|
||||
// useMemo,
|
||||
// } from 'react';
|
||||
|
||||
// interface IQuillEditor extends ReactQuillProps {
|
||||
// forwardedRef: LegacyRef<ReactQuill>;
|
||||
// }
|
||||
|
||||
// const QuillNoSSRWrapper = dynamic(
|
||||
// async () => {
|
||||
// const { default: RQ } = await import('react-quill');
|
||||
// // eslint-disable-next-line react/display-name
|
||||
// return function editor({ forwardedRef, ...props }: IQuillEditor) {
|
||||
// return <RQ ref={forwardedRef} {...props} />;
|
||||
// };
|
||||
// },
|
||||
// { ssr: false }
|
||||
// );
|
||||
|
||||
|
||||
const formats = [
|
||||
'header',
|
||||
'bold',
|
||||
'italic',
|
||||
'underline',
|
||||
'strike',
|
||||
'blockquote',
|
||||
'list',
|
||||
'bullet',
|
||||
'indent',
|
||||
'link',
|
||||
'image',
|
||||
'code',
|
||||
'color',
|
||||
'background',
|
||||
'code-block',
|
||||
'align',
|
||||
];
|
||||
|
||||
interface OnChangeHandler {
|
||||
(e: any): void;
|
||||
}
|
||||
|
||||
type Props = {
|
||||
value: string;
|
||||
placeholder: string;
|
||||
onChange: OnChangeHandler;
|
||||
prefix: string;
|
||||
};
|
||||
|
||||
const TextEditor: React.FC<Props> = forwardRef((props, ref) => {
|
||||
const { value, placeholder, onChange, prefix } = props;
|
||||
const quillRef = useRef(ref);
|
||||
|
||||
const handleOnChange = (e) => {
|
||||
if (quillRef.current) {
|
||||
const delta = quillRef.current.getEditor().getContents();
|
||||
const html = quillRef.current.getEditor().getHTML();
|
||||
onChange(html);
|
||||
}
|
||||
};
|
||||
useImperativeHandle(ref, () => ({
|
||||
getQuill: () => quillRef.current,
|
||||
}));
|
||||
|
||||
const imageHandler = async () => {
|
||||
const input = document.createElement('input');
|
||||
input.setAttribute('type', 'file');
|
||||
input.setAttribute('accept', 'image/*');
|
||||
input.click();
|
||||
|
||||
input.onchange = async () => {
|
||||
const uploadPromises = Array.from(input.files).map(async (item) => {
|
||||
const formData = new FormData();
|
||||
formData.append('image', item);
|
||||
formData.append('prefix', prefix);
|
||||
|
||||
try {
|
||||
const response = await axiosInstance.post('upload', formData);
|
||||
const imageUrl = response.data.imageUrl;
|
||||
|
||||
if (quillRef.current) {
|
||||
// const editor = quillRef.current.getEditor();
|
||||
const editor = quillRef.current.getQuill(); // Adjust based on your useImperativeHandle setup
|
||||
const range = editor.getSelection(true);
|
||||
editor.insertEmbed(range.index, 'image', imageUrl);
|
||||
|
||||
return range.index + 1;
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Error uploading image:', error);
|
||||
}
|
||||
});
|
||||
|
||||
const cursorPositions = await Promise.all(uploadPromises);
|
||||
const lastCursorPosition = cursorPositions.pop();
|
||||
if (lastCursorPosition !== undefined && quillRef.current) {
|
||||
const editor = quillRef.current.getEditor();
|
||||
editor.setSelection(lastCursorPosition);
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
const modules = React.useMemo(
|
||||
() => ({
|
||||
toolbar: {
|
||||
container: [
|
||||
// [{ 'size': ['small', false, 'large', 'huge'] }], // custom dropdown
|
||||
[{ header: [1, 2, 3, 4, 5, 6, false] }],
|
||||
['bold', 'italic', 'underline', 'strike', 'blockquote', 'code-block'],
|
||||
[{ list: 'ordered' }, { list: 'bullet' }, { indent: '-1' }, { indent: '+1' }],
|
||||
['link', 'image'],
|
||||
[{ color: [] }, { background: [] }, { align: [] }],
|
||||
['clean'],
|
||||
],
|
||||
// container: [
|
||||
// [{ 'font': [] }], // Dropdown to select font
|
||||
// [{ 'size': ['small', false, 'large', 'huge'] }], // Dropdown to select font size
|
||||
// [{ 'header': [1, 2, 3, 4, 5, 6, false] }],
|
||||
// ['bold', 'italic', 'underline', 'strike'], // toggled buttons
|
||||
// [{ 'script': 'sub' }, { 'script': 'super' }], // superscript/subscript
|
||||
// ['blockquote', 'code-block'],
|
||||
// [{ 'list': 'ordered' }, { 'list': 'bullet' }],
|
||||
// [{ 'indent': '-1' }, { 'indent': '+1' }], // indent/outdent
|
||||
// [{ 'direction': 'rtl' }], // text direction
|
||||
// [{ 'color': [] }, { 'background': [] }], // dropdown with defaults from theme
|
||||
// [{ 'align': [] }],
|
||||
// ['link', 'image', 'video'], // link and image, video
|
||||
// ['clean'] // remove formatting button
|
||||
// ],
|
||||
// we can't fix this so temporary disable it
|
||||
// handlers: {
|
||||
// image: imageHandler,
|
||||
// },
|
||||
},
|
||||
imageResize: true
|
||||
}),
|
||||
[imageHandler],
|
||||
);
|
||||
|
||||
//test if we ever get the ref!
|
||||
useEffect(() => {
|
||||
if (quillRef.current) {
|
||||
console.log('quillRef.current: ', quillRef.current);
|
||||
// You can now access the Quill instance directly via quillRef.current.getEditor()
|
||||
// This is useful for any setup or instance-specific adjustments you might need
|
||||
}
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<>
|
||||
<ReactQuill
|
||||
ref={quillRef}
|
||||
theme="snow"
|
||||
value={value || ''}
|
||||
modules={modules}
|
||||
formats={formats}
|
||||
onChange={onChange}
|
||||
style={{ height: '500px', width: '100%' }}
|
||||
placeholder={placeholder}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
// return <QuillNoSSRWrapper forwardedRef={ref} {...props} />;
|
||||
|
||||
});
|
||||
|
||||
export default TextEditor;
|
Reference in New Issue
Block a user