diff --git a/examples/replace-content-example/README.md b/examples/replace-content-example/README.md new file mode 100644 index 0000000000..363c66360c --- /dev/null +++ b/examples/replace-content-example/README.md @@ -0,0 +1,26 @@ +# Replace Content Example + +A React example demonstrating how to replace document content with HTML or JSON using SuperDoc. + +## Features + +- Load DOCX documents +- Replace entire document or selection with custom content +- Switch between HTML and JSON input formats +- Side panel with content replacement controls + +## Usage + +1. Load a document using "Load Document" button +2. Open the side panel using the tab on the right +3. Choose replacement scope (Document or Selection) +4. Select content type (HTML or JSON) +5. Enter your content in the textarea +6. Click "Replace content" to apply changes + +## Running + +```bash +npm install +npm run dev +``` \ No newline at end of file diff --git a/examples/replace-content-example/demo-config.json b/examples/replace-content-example/demo-config.json new file mode 100644 index 0000000000..b2193840f3 --- /dev/null +++ b/examples/replace-content-example/demo-config.json @@ -0,0 +1,9 @@ +{ + "dirname": "replace-content-example", + "tags": [ + "editing", + "viewing", + "react" + ], + "title": "Replacing content with HTML/JSON" +} \ No newline at end of file diff --git a/examples/replace-content-example/demo-thumbnail.png b/examples/replace-content-example/demo-thumbnail.png new file mode 100644 index 0000000000..8425d2ff17 Binary files /dev/null and b/examples/replace-content-example/demo-thumbnail.png differ diff --git a/examples/replace-content-example/demo-video.mp4 b/examples/replace-content-example/demo-video.mp4 new file mode 100644 index 0000000000..4d7b4c9819 Binary files /dev/null and b/examples/replace-content-example/demo-video.mp4 differ diff --git a/examples/replace-content-example/index.html b/examples/replace-content-example/index.html new file mode 100644 index 0000000000..5a4e3e6da2 --- /dev/null +++ b/examples/replace-content-example/index.html @@ -0,0 +1,12 @@ + + + + + + SuperDoc React Example + + +
+ + + \ No newline at end of file diff --git a/examples/replace-content-example/package.json b/examples/replace-content-example/package.json new file mode 100644 index 0000000000..96123482ba --- /dev/null +++ b/examples/replace-content-example/package.json @@ -0,0 +1,19 @@ +{ + "name": "react-superdoc-example", + "private": true, + "version": "0.0.1", + "type": "module", + "scripts": { + "dev": "vite" + }, + "dependencies": { + "@harbour-enterprises/superdoc": "^0.14.15", + "highlight.js": "^11.11.1", + "react": "^19.0.0", + "react-dom": "^19.0.0" + }, + "devDependencies": { + "@vitejs/plugin-react": "^4.0.4", + "vite": "^7.0.5" + } +} diff --git a/examples/replace-content-example/public/sample.docx b/examples/replace-content-example/public/sample.docx new file mode 100644 index 0000000000..c89890fb5d Binary files /dev/null and b/examples/replace-content-example/public/sample.docx differ diff --git a/examples/replace-content-example/src/App.jsx b/examples/replace-content-example/src/App.jsx new file mode 100644 index 0000000000..fcf4e8c6a8 --- /dev/null +++ b/examples/replace-content-example/src/App.jsx @@ -0,0 +1,306 @@ +import { useRef, useReducer } from 'react'; +import DocumentEditor from './components/DocumentEditor'; + +function App() { + const [, _forceUpdate] = useReducer(x => x + 1, 0); + + const forceUpdate = async (uploadingFile = false) => { + // Save editor content to documentFileRef before forcing update + if (editorRef.current && editorRef.current.activeEditor && !uploadingFile) { + try { + const result = await editorRef.current.activeEditor.exportDocx(); + const DOCX = 'application/vnd.openxmlformats-officedocument.wordprocessingml.document'; + const blob = new Blob([result], { type: DOCX }); + const file = new File([blob], `document-${Date.now()}.docx`, { type: DOCX }); + documentFileRef.current = file; + console.log('Saved editor content as DOCX file to documentFileRef:', file); + } catch (error) { + console.warn('Could not save editor content:', error); + } + } + _forceUpdate(); + }; + +const exampleJSON = { + type: 'text', + marks: [ + { + type: 'aiAnimationMark', + attrs: { + class: 'sd-ai-text-appear', + dataMarkId: `ai-animation-${Date.now()}`, + }, + }, + ], + text: 'Hello, SuperDoc~!!', +}; + + const exampleHTML = '

Hello, SuperDoc~!!

'; + + const documentFileRef = useRef(null); + const drawerOpenRef = useRef(true); + const replacementScopeRef = useRef('document'); + const replacementContentTypeRef = useRef('html'); + const textareaRef = useRef(null); + + const editorRef = useRef(null); + const fileInputRef = useRef(null); + + const handleFileChange = (event) => { + const file = event.target.files?.[0]; + if (file) { + documentFileRef.current = file; + forceUpdate(true); + } + }; + + const handleEditorReady = (editorInstance) => { + console.log('SuperDoc editor is ready', editorInstance); + editorRef.current = editorInstance; + }; + + const handleReplacementScopeChange = (event) => { + replacementScopeRef.current = event.target.value; + forceUpdate(); + }; + + const handleReplacementContentTypeChange = (event) => { + replacementContentTypeRef.current = event.target.value; + // Update textarea content without triggering re-render + if (textareaRef.current) { + textareaRef.current.value = replacementContentTypeRef.current === 'json' ? JSON.stringify(exampleJSON, null, 2) : exampleHTML; + } + forceUpdate(); + }; + + const toggleDrawer = () => { + drawerOpenRef.current = !drawerOpenRef.current; + forceUpdate(); + }; + + const handleReplaceContent = () => { + // Get textarea value directly from DOM + const textareaContent = textareaRef.current ? textareaRef.current.value : ''; + + if (!editorRef.current) { + console.error('Editor not available'); + return; + } + + if (replacementScopeRef.current === 'document') { + // Select all content in the document + editorRef.current.activeEditor.commands.selectAll(); + } + + const replacementContent = replacementContentTypeRef.current === "json" ? JSON.parse(textareaContent) : textareaContent; + + // Insert the raw content with animation mark + editorRef.current.activeEditor.commands.insertContent(replacementContent); + }; + + return ( +
+
+

SuperDoc Example

+ + +
+ +
+ + +
+ {drawerOpenRef.current ? '◀' : '▶'} +
+ +
+
+

Content Replacement

+ +
+ + +
+ +
+ + +
+ +
+ +