"use client";
import History from '@tiptap/extension-history';
import Bold from '@tiptap/extension-bold'; // Import the extension
import Italic from '@tiptap/extension-italic'; // Import the extension
import { useState, useRef } from 'react';
import { useEditor, EditorContent, BubbleMenu } from '@tiptap/react';
import StarterKit from '@tiptap/starter-kit';
import TextStyle from '@tiptap/extension-text-style';
import FontFamily from '@tiptap/extension-font-family';
import Color from '@tiptap/extension-color';
import Highlight from '@tiptap/extension-highlight';
import TextAlign from '@tiptap/extension-text-align';
import Link from '@tiptap/extension-link';
import Image from '@tiptap/extension-image';
import Underline from '@tiptap/extension-underline';
import Table from '@tiptap/extension-table';
import TableCell from '@tiptap/extension-table-cell';
import TableHeader from '@tiptap/extension-table-header';
import TableRow from '@tiptap/extension-table-row';
import {
Underline as UnderlineIcon, AlignLeft, AlignCenter, AlignRight, AlignJustify,
Link as LinkIcon, Image as ImageIcon, Save, Table as TableIcon,
Type, Highlighter,
ChevronDown,
Undo, Redo, Copy
} from 'lucide-react';
import './style.css';
// @ts-ignore
const RibbonTab = ({ label, isActive, onClick, children }) => (
{label}
{isActive && (
{children}
)}
);
const RibbonGroup = ({ title, children }) => (
);
const RibbonButton = ({ icon: Icon, label, onClick, isActive, size = 'medium', dropdown = false }) => (
{size === 'large' && {label} }
{dropdown && }
);
export default function RibbonWordClone() {
const [fileName, setFileName] = useState('Document 1');
const [fontSize, setFontSize] = useState('12');
const [fontFamily, setFontFamily] = useState('Calibri');
const [textColor, setTextColor] = useState('#000000');
const [highlightColor, setHighlightColor] = useState('#ffff00');
const [activeTab, setActiveTab] = useState('home');
const [zoom, setZoom] = useState(100);
const [pages, setPages] = useState([1]);
const fileInputRef = useRef(null);
const editor = useEditor({
extensions: [
// @ts-ignore
StarterKit,
Bold,
Italic,
History,
TextStyle,
FontFamily,
Color,
Highlight.configure({ multicolor: true }),
TextAlign.configure({ types: ['heading', 'paragraph', 'tableCell'] }),
Link.configure({ openOnClick: false }),
Image,
Underline,
Table.configure({
resizable: true,
HTMLAttributes: {
class: 'editor-table',
},
}),
TableRow,
TableHeader,
TableCell,
],
content: `
${fileName}
Start typing your document here...
`,
// @ts-ignore
onUpdate: ({ editor }) => {
// Simulate multiple pages based on content height
const element = document.querySelector('.ProseMirror');
if (element) {
const contentHeight = element.scrollHeight;
const pageHeight = 1123; // A4 height in pixels at 96 DPI
const neededPages = Math.max(1, Math.ceil(contentHeight / pageHeight));
if (neededPages !== pages.length) {
setPages(Array.from({ length: neededPages }, (_, i) => i + 1));
}
}
},
});
const addImage = () => {
if (fileInputRef.current) {
fileInputRef.current.click();
}
};
const handleImageUpload = (e) => {
const file = e.target.files?.[0];
if (file && editor) {
const reader = new FileReader();
reader.onload = (event) => {
const imageUrl = event.target?.result;
// @ts-ignore
editor.chain().focus().setImage({ src: imageUrl }).run();
};
reader.readAsDataURL(file);
}
};
const saveDocument = () => {
if (editor) {
const content = editor.getHTML();
const blob = new Blob([content], { type: 'text/html' });
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = `${fileName}.html`;
a.click();
URL.revokeObjectURL(url);
}
};
if (!editor) {
return null;
}
return (
{/* Quick Access Toolbar */}
{/* Ribbon */}
setActiveTab('home')}
>
Home
setActiveTab('insert')}
>
Insert
setActiveTab('layout')}
>
Layout
setActiveTab('view')}
>
View
{activeTab === 'home' && (
document.execCommand('copy')} isActive={undefined} />
document.execCommand('paste')} isActive={undefined} />
document.execCommand('cut')} isActive={undefined} />
{
setFontFamily(e.target.value);
editor.chain().focus().setFontFamily(e.target.value).run();
}}
className="format-select"
style={{ width: '120px' }}
>
Calibri
Arial
Times New Roman
Georgia
Verdana
{
setFontSize(e.target.value);
// editor.chain().focus().setFontSize(e.target.value + 'pt').run();
}}
className="format-select"
style={{ width: '60px' }}
>
8
9
10
11
12
14
16
18
20
24
28
36
editor.chain().focus().toggleBold().run()}
isActive={editor.isActive('bold')}
/>
editor.chain().focus().toggleItalic().run()}
isActive={editor.isActive('italic')}
/>
editor.chain().focus().toggleUnderline().run()}
isActive={editor.isActive('underline')}
/>
editor.chain().focus().setTextAlign('left').run()}
isActive={editor.isActive({ textAlign: 'left' })}
/>
editor.chain().focus().setTextAlign('center').run()}
isActive={editor.isActive({ textAlign: 'center' })}
/>
editor.chain().focus().setTextAlign('right').run()}
isActive={editor.isActive({ textAlign: 'right' })}
/>
editor.chain().focus().setTextAlign('justify').run()}
isActive={editor.isActive({ textAlign: 'justify' })}
/>
)}
{activeTab === 'insert' && (
editor.chain().focus().insertTable({ rows: 3, cols: 3, withHeaderRow: true }).run()} isActive={undefined} />
{
const previousUrl = editor.getAttributes('link').href;
const url = window.prompt('URL', previousUrl);
if (url === null) return;
if (url === '') {
editor.chain().focus().extendMarkRange('link').unsetLink().run();
return;
}
editor.chain().focus().extendMarkRange('link').setLink({ href: url }).run();
}}
isActive={editor.isActive('link')}
/>
)}
{activeTab === 'view' && (
)}
{/* Editor Area */}
{pages.map((pageNum, index) => (
Page {pageNum}
{index === 0 && }
))}
{/* Bubble Menu */}
{editor && (
editor.chain().focus().toggleBold().run()}
isActive={editor.isActive('bold')}
/>
editor.chain().focus().toggleItalic().run()}
isActive={editor.isActive('italic')}
/>
editor.chain().focus().toggleUnderline().run()}
isActive={editor.isActive('underline')}
/>
{
const previousUrl = editor.getAttributes('link').href;
const url = window.prompt('URL', previousUrl);
if (url === null) return;
if (url === '') {
editor.chain().focus().extendMarkRange('link').unsetLink().run();
return;
}
editor.chain().focus().extendMarkRange('link').setLink({ href: url }).run();
}}
isActive={editor.isActive('link')}
/>
)}
{/* Status Bar */}
Page {pages.length} of {pages.length} | Words: {editor.storage.characterCount?.words() || 0}
setZoom(Math.max(50, zoom - 10))}>-
{zoom}%
setZoom(Math.min(200, zoom + 10))}>+
{/* Hidden file input */}
);
}