"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, AnyExtension } 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, ItalicIcon, BoldIcon } from 'lucide-react'; import './style.css'; // @ts-ignore const RibbonTab = ({ label, isActive, onClick, children }) => (
{isActive && (
{children}
)}
); const RibbonGroup = ({ title, children }) => (
{children}
{title}
); const RibbonButton = ({ icon: Icon, label, onClick, isActive, size = 'medium', dropdown = false }) => ( ); 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: [ StarterKit.configure({ history: false }) as unknown as AnyExtension, 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 */}
setFileName(e.target.value)} className="title-input" placeholder="Document name" />
{/* Ribbon */}
{activeTab === 'home' && (
document.execCommand('copy')} isActive={undefined} /> document.execCommand('paste')} isActive={undefined} /> document.execCommand('cut')} isActive={undefined} />
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')} />
{ setTextColor(e.target.value); editor.chain().focus().setColor(e.target.value).run(); }} className="color-picker" />
{ setHighlightColor(e.target.value); editor.chain().focus().setHighlight({ color: e.target.value }).run(); }} className="color-picker" />
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' && (
{zoom}%
setZoom(parseInt(e.target.value))} className="zoom-slider" />
)}
{/* 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}
{zoom}%
{/* Hidden file input */}
); }