1+ <template >
2+ <div class =" document-editor" >
3+ <div :key =" documentKey" class =" editor-container" >
4+ <div id =" superdoc-toolbar" class =" toolbar" ></div >
5+ <div id =" superdoc" class =" editor" ></div >
6+ </div >
7+ </div >
8+ </template >
9+
10+ <script setup>
11+ import { onMounted , onUnmounted , ref , shallowRef , watch } from ' vue' ;
12+ import { SuperDoc } from ' @harbour-enterprises/superdoc' ;
13+ import ' @harbour-enterprises/superdoc/style.css' ;
14+
15+ // Import our custom node plugin
16+ import { myCustomNode } from ' ../plugins/MyCustomNodePlugin' ;
17+
18+ const props = defineProps ({
19+ documentId: {
20+ type: String ,
21+ required: true
22+ },
23+ initialData: {
24+ type: File ,
25+ default: null
26+ },
27+ readOnly: {
28+ type: Boolean ,
29+ default: false
30+ }
31+ });
32+
33+ const emit = defineEmits ([' editor-ready' , ' editor-error' ]);
34+
35+ // Use ref to track the editor instance
36+ const editor = shallowRef (null );
37+ const documentKey = ref (0 );
38+
39+ // Function to safely destroy editor
40+ const destroyEditor = () => {
41+ if (editor .value ) {
42+ editor .value = null ;
43+ }
44+ };
45+
46+ // Function to initialize editor
47+ const initializeEditor = async () => {
48+ if (props .initialData ) {
49+ // If initialData is provided, load the document
50+ await initializeLoadedFile ();
51+ } else {
52+ // Otherwise, create a blank document
53+ await initializeBlankDocument ();
54+ }
55+ };
56+
57+ const hooks = {
58+ onFocus : () => {
59+ console .log (' Editor focused' );
60+ },
61+ onBlur : () => {
62+ console .log (' Editor lost focus' );
63+ },
64+ onReady : () => {
65+ emit (' editor-ready' , editor .value );
66+
67+ // Let's insert our custom node into the document after the editor is ready
68+ editor .value ? .activeEditor .commands .insertContent (`
69+ <div data-node-type='customNode' id='some-id-123'>Custom Node Content</div>
70+ ` );
71+
72+ // Now instead of using the generic insertContent, we can use our custom node command
73+ editor .value .activeEditor .commands .insertCustomNode ({
74+ id: ' second-node-id' ,
75+ content: ' Display this text!' ,
76+ })
77+
78+ // Let's check our current HTML
79+ const html = editor .value ? .activeEditor .getHTML ();
80+ console .debug (' Editor HTML:' , html);
81+ },
82+ onError: (error ) => {
83+ emit (' editor-error' , error);
84+ },
85+ };
86+
87+ // Configuration modules: We can customize the toolbar here
88+ const modules = {
89+ toolbar: {
90+ selector: ' superdoc-toolbar' ,
91+ toolbarGroups: [' center' ],
92+ excludeItems: [' underline' ],
93+ }
94+ };
95+
96+ const initializeBlankDocument = async () => {
97+ editor .value = new SuperDoc ({
98+ selector: ' #superdoc' ,
99+ toolbar: ' superdoc-toolbar' ,
100+ format: ' docx' ,
101+ documentMode: props .readOnly ? ' viewing' : ' editing' ,
102+
103+ // Listen for various editor events
104+ ... hooks,
105+
106+ // Include customized modules
107+ modules: {
108+ ... modules,
109+ },
110+
111+ // Register our custom node here
112+ editorExtensions: [myCustomNode],
113+ });
114+ };
115+
116+ const initializeLoadedFile = async () => {
117+ try {
118+ // Ensure cleanup of previous instance
119+ destroyEditor ();
120+
121+ // Create new editor instance
122+ editor .value = new SuperDoc ({
123+ selector: ' #superdoc' ,
124+ toolbar: ' superdoc-toolbar' ,
125+ documentMode: props .readOnly ? ' viewing' : ' editing' ,
126+ documents: [{
127+ id: props .documentId ,
128+ type: ' docx' ,
129+ data: props .initialData
130+ }],
131+
132+ // Listen for various editor events
133+ ... hooks,
134+
135+ // Include customized modules
136+ ... modules,
137+
138+ // Register our custom node here
139+ editorExtensions: [myCustomNode],
140+ });
141+ } catch (error) {
142+ console .error (' Failed to initialize editor:' , error);
143+ emit (' editor-error' , error);
144+ }
145+ };
146+
147+ // Watch for changes in props that should trigger re-initialization
148+ watch (
149+ () => [props .documentId , props .initialData , props .readOnly ],
150+ () => {
151+ initializeEditor ();
152+ }
153+ );
154+
155+ onMounted (() => {
156+ initializeEditor ();
157+ });
158+
159+ onUnmounted (() => {
160+ destroyEditor ();
161+ });
162+ < / script>
163+
164+ < style>
165+ /** Adding global style for our custom node class here, but more commonly you'd place this in your main style.css */
166+ .my - custom- node- default- class {
167+ background- color: #1355FF ;
168+ border- radius: 8px ;
169+ cursor: pointer;
170+ color: white;
171+ display: inline- block;
172+ padding: 2px 8px ;
173+ font- size: 12px ;
174+ }
175+ .my - custom- node- default- class : hover {
176+ background- color: #0a3dff ;
177+ }
178+ < / style>
179+
180+ < style scoped>
181+ .editor - container {
182+ display: flex;
183+ flex- direction: column;
184+ align- items: center;
185+ }
186+ .document - editor {
187+ display: flex;
188+ flex- direction: column;
189+ height: 100 % ;
190+ width: 100 % ;
191+ }
192+
193+ .toolbar {
194+ flex: 0 0 auto;
195+ border- bottom: 1px solid #eee;
196+ min- height: 40px ; /* Ensure toolbar has minimum height */
197+ }
198+
199+ .editor {
200+ flex: 1 1 auto;
201+ overflow: auto;
202+ margin- top: 10px ;
203+ min- height: 400px ; /* Ensure editor has minimum height */
204+ }
205+ < / style>
0 commit comments