@kandiforge/kandi-office 0.16.161 → 0.17.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/services/IDocumentService.d.ts +8 -1
- package/dist/services/TauriDocumentService.d.ts +5 -2
- package/dist/services/TauriDocumentService.js +46 -6
- package/dist/services/TauriDocumentService.js.map +1 -1
- package/dist/services/WasmDocumentService.d.ts +7 -2
- package/dist/services/WasmDocumentService.js +25 -3
- package/dist/services/WasmDocumentService.js.map +1 -1
- package/dist/viewers/DocxViewer.css +43 -46
- package/dist/viewers/DocxViewer.js +49 -100
- package/dist/viewers/DocxViewer.js.map +1 -1
- package/dist/viewers/XlsxViewer.css +9 -37
- package/dist/viewers/pdf/PdfViewer.js +17 -8
- package/dist/viewers/pdf/PdfViewer.js.map +1 -1
- package/dist/viewers/pdf/components/views/ContinuousScrollView.d.ts +1 -1
- package/dist/viewers/pdf/components/views/ContinuousScrollView.js +50 -36
- package/dist/viewers/pdf/components/views/ContinuousScrollView.js.map +1 -1
- package/dist/viewers/pdf/components/views/SinglePageView.d.ts +1 -1
- package/dist/viewers/pdf/components/views/SinglePageView.js +26 -16
- package/dist/viewers/pdf/components/views/SinglePageView.js.map +1 -1
- package/dist/viewers/pdf/components/views/ThumbnailGridView.js +23 -9
- package/dist/viewers/pdf/components/views/ThumbnailGridView.js.map +1 -1
- package/dist/viewers/pdf/hooks/usePdfDocument.d.ts +2 -0
- package/dist/viewers/pdf/hooks/usePdfDocument.js +84 -30
- package/dist/viewers/pdf/hooks/usePdfDocument.js.map +1 -1
- package/dist/viewers/pdf/types.d.ts +1 -0
- package/dist/wasm/types.d.ts +89 -0
- package/dist/wasm/xlsx.d.ts +8 -0
- package/dist/wasm/xlsx.js +34 -0
- package/dist/wasm/xlsx.js.map +1 -0
- package/package.json +1 -1
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { LayoutPage, PptxExtractedData } from '../wasm/types';
|
|
1
|
+
import type { LayoutPage, PptxExtractedData, XlsxDocument, XlsxLayout } from '../wasm/types';
|
|
2
2
|
export interface PptxDocumentHandle {
|
|
3
3
|
slideCount: number;
|
|
4
4
|
slideJsons: string[];
|
|
@@ -9,6 +9,10 @@ export interface DocxDocumentHandle {
|
|
|
9
9
|
documentJson: string;
|
|
10
10
|
pages: LayoutPage[];
|
|
11
11
|
}
|
|
12
|
+
export interface XlsxDocumentHandle {
|
|
13
|
+
document: XlsxDocument;
|
|
14
|
+
layouts: XlsxLayout[];
|
|
15
|
+
}
|
|
12
16
|
export interface PdfDocumentHandle {
|
|
13
17
|
pageCount: number;
|
|
14
18
|
path?: string;
|
|
@@ -28,6 +32,8 @@ export interface IDocumentService {
|
|
|
28
32
|
openDocx(source: ArrayBuffer | string): Promise<DocxDocumentHandle>;
|
|
29
33
|
getDocxPages(handle: DocxDocumentHandle): Promise<LayoutPage[]>;
|
|
30
34
|
renderDocxPage(page: LayoutPage, canvas: HTMLCanvasElement): Promise<void>;
|
|
35
|
+
openXlsx(source: ArrayBuffer | string): Promise<XlsxDocumentHandle>;
|
|
36
|
+
renderXlsxSheet(layout: XlsxLayout, canvas: HTMLCanvasElement): Promise<void>;
|
|
31
37
|
openPdf(source: ArrayBuffer | string): Promise<PdfDocumentHandle>;
|
|
32
38
|
getPdfPageCount(handle: PdfDocumentHandle): number;
|
|
33
39
|
getPdfPageDimensions(handle: PdfDocumentHandle, page: number): Promise<{
|
|
@@ -35,6 +41,7 @@ export interface IDocumentService {
|
|
|
35
41
|
height: number;
|
|
36
42
|
}>;
|
|
37
43
|
renderPdfPage(handle: PdfDocumentHandle, page: number, canvas: HTMLCanvasElement, dpi?: number): Promise<string>;
|
|
44
|
+
renderPdfPageToCanvas(handle: PdfDocumentHandle, page: number, canvas: HTMLCanvasElement, dpi?: number): Promise<void>;
|
|
38
45
|
closePdf(handle: PdfDocumentHandle): Promise<void>;
|
|
39
46
|
openMarkdown(source: ArrayBuffer | string): Promise<{
|
|
40
47
|
content: string;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import type { IDocumentService, PptxDocumentHandle, DocxDocumentHandle, PdfDocumentHandle, SlideInfo } from './IDocumentService';
|
|
2
|
-
import type { LayoutPage } from '../wasm/types';
|
|
1
|
+
import type { IDocumentService, PptxDocumentHandle, DocxDocumentHandle, XlsxDocumentHandle, PdfDocumentHandle, SlideInfo } from './IDocumentService';
|
|
2
|
+
import type { LayoutPage, XlsxLayout } from '../wasm/types';
|
|
3
3
|
export declare class TauriDocumentService implements IDocumentService {
|
|
4
4
|
openPptx(source: ArrayBuffer | string): Promise<PptxDocumentHandle>;
|
|
5
5
|
getSlides(handle: PptxDocumentHandle): Promise<SlideInfo[]>;
|
|
@@ -8,12 +8,15 @@ export declare class TauriDocumentService implements IDocumentService {
|
|
|
8
8
|
openDocx(source: ArrayBuffer | string): Promise<DocxDocumentHandle>;
|
|
9
9
|
getDocxPages(handle: DocxDocumentHandle): Promise<LayoutPage[]>;
|
|
10
10
|
renderDocxPage(page: LayoutPage, canvas: HTMLCanvasElement): Promise<void>;
|
|
11
|
+
openXlsx(source: ArrayBuffer | string): Promise<XlsxDocumentHandle>;
|
|
12
|
+
renderXlsxSheet(layout: XlsxLayout, canvas: HTMLCanvasElement): Promise<void>;
|
|
11
13
|
openPdf(source: ArrayBuffer | string): Promise<PdfDocumentHandle>;
|
|
12
14
|
getPdfPageCount(handle: PdfDocumentHandle): number;
|
|
13
15
|
getPdfPageDimensions(handle: PdfDocumentHandle, pageNum: number): Promise<{
|
|
14
16
|
width: number;
|
|
15
17
|
height: number;
|
|
16
18
|
}>;
|
|
19
|
+
renderPdfPageToCanvas(handle: PdfDocumentHandle, pageNum: number, canvas: HTMLCanvasElement, dpi?: number): Promise<void>;
|
|
17
20
|
renderPdfPage(_handle: PdfDocumentHandle, pageNum: number, _canvas: HTMLCanvasElement, dpi?: number): Promise<string>;
|
|
18
21
|
closePdf(_handle: PdfDocumentHandle): Promise<void>;
|
|
19
22
|
openMarkdown(source: ArrayBuffer | string): Promise<{
|
|
@@ -41,12 +41,14 @@ export class TauriDocumentService {
|
|
|
41
41
|
throw new Error('TauriDocumentService requires a file path string for DOCX, not ArrayBuffer');
|
|
42
42
|
}
|
|
43
43
|
const invoke = await getInvoke();
|
|
44
|
-
await invoke('
|
|
45
|
-
const
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
44
|
+
const bytes = await invoke('read_file_bytes', { path: source });
|
|
45
|
+
const buffer = new Uint8Array(bytes).buffer;
|
|
46
|
+
const { initWasm } = await import('../wasm/wasm-loader');
|
|
47
|
+
const { processDocx } = await import('../wasm/docx');
|
|
48
|
+
await initWasm();
|
|
49
|
+
const measureCanvas = document.createElement('canvas');
|
|
50
|
+
const { documentJson, pages } = await processDocx(buffer, measureCanvas);
|
|
51
|
+
return { documentJson, pages };
|
|
50
52
|
}
|
|
51
53
|
async getDocxPages(handle) {
|
|
52
54
|
return handle.pages;
|
|
@@ -57,6 +59,25 @@ export class TauriDocumentService {
|
|
|
57
59
|
await init();
|
|
58
60
|
await wasmRender(page, canvas);
|
|
59
61
|
}
|
|
62
|
+
async openXlsx(source) {
|
|
63
|
+
if (typeof source !== 'string') {
|
|
64
|
+
throw new Error('TauriDocumentService requires a file path string for XLSX, not ArrayBuffer');
|
|
65
|
+
}
|
|
66
|
+
const invoke = await getInvoke();
|
|
67
|
+
const bytes = await invoke('read_file_bytes', { path: source });
|
|
68
|
+
const buffer = new Uint8Array(bytes).buffer;
|
|
69
|
+
const { initWasm } = await import('../wasm/wasm-loader');
|
|
70
|
+
const { processXlsx } = await import('../wasm/xlsx');
|
|
71
|
+
await initWasm();
|
|
72
|
+
const { document, layouts } = await processXlsx(buffer);
|
|
73
|
+
return { document, layouts };
|
|
74
|
+
}
|
|
75
|
+
async renderXlsxSheet(layout, canvas) {
|
|
76
|
+
const { initWasm } = await import('../wasm/wasm-loader');
|
|
77
|
+
const { renderXlsxSheet: wasmRender } = await import('../wasm/xlsx');
|
|
78
|
+
await initWasm();
|
|
79
|
+
await wasmRender(layout, canvas);
|
|
80
|
+
}
|
|
60
81
|
async openPdf(source) {
|
|
61
82
|
if (typeof source !== 'string') {
|
|
62
83
|
throw new Error('TauriDocumentService requires a file path string for PDF, not ArrayBuffer');
|
|
@@ -78,6 +99,25 @@ export class TauriDocumentService {
|
|
|
78
99
|
});
|
|
79
100
|
return { width, height };
|
|
80
101
|
}
|
|
102
|
+
async renderPdfPageToCanvas(handle, pageNum, canvas, dpi = 150) {
|
|
103
|
+
const dataUri = await this.renderPdfPage(handle, pageNum, canvas, dpi);
|
|
104
|
+
const img = new Image();
|
|
105
|
+
await new Promise((resolve, reject) => {
|
|
106
|
+
img.onload = () => {
|
|
107
|
+
canvas.width = img.naturalWidth;
|
|
108
|
+
canvas.height = img.naturalHeight;
|
|
109
|
+
const ctx = canvas.getContext('2d');
|
|
110
|
+
if (!ctx) {
|
|
111
|
+
reject(new Error('Failed to get canvas 2d context'));
|
|
112
|
+
return;
|
|
113
|
+
}
|
|
114
|
+
ctx.drawImage(img, 0, 0);
|
|
115
|
+
resolve();
|
|
116
|
+
};
|
|
117
|
+
img.onerror = () => reject(new Error('Failed to load rendered page image'));
|
|
118
|
+
img.src = dataUri;
|
|
119
|
+
});
|
|
120
|
+
}
|
|
81
121
|
async renderPdfPage(_handle, pageNum, _canvas, dpi = 150) {
|
|
82
122
|
const invoke = await getInvoke();
|
|
83
123
|
return invoke('pdf_render_page_to_image', {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TauriDocumentService.js","sourceRoot":"","sources":["../../src/services/TauriDocumentService.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"TauriDocumentService.js","sourceRoot":"","sources":["../../src/services/TauriDocumentService.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import type { IDocumentService, PptxDocumentHandle, DocxDocumentHandle, PdfDocumentHandle, SlideInfo } from './IDocumentService';
|
|
2
|
-
import type { LayoutPage } from '../wasm/types';
|
|
1
|
+
import type { IDocumentService, PptxDocumentHandle, DocxDocumentHandle, XlsxDocumentHandle, PdfDocumentHandle, SlideInfo } from './IDocumentService';
|
|
2
|
+
import type { LayoutPage, XlsxLayout } from '../wasm/types';
|
|
3
3
|
export declare class WasmDocumentService implements IDocumentService {
|
|
4
4
|
openPptx(source: ArrayBuffer | string): Promise<PptxDocumentHandle>;
|
|
5
5
|
getSlides(handle: PptxDocumentHandle): Promise<SlideInfo[]>;
|
|
@@ -8,12 +8,17 @@ export declare class WasmDocumentService implements IDocumentService {
|
|
|
8
8
|
openDocx(source: ArrayBuffer | string): Promise<DocxDocumentHandle>;
|
|
9
9
|
getDocxPages(handle: DocxDocumentHandle): Promise<LayoutPage[]>;
|
|
10
10
|
renderDocxPage(page: LayoutPage, canvas: HTMLCanvasElement): Promise<void>;
|
|
11
|
+
openXlsx(source: ArrayBuffer | string): Promise<XlsxDocumentHandle>;
|
|
12
|
+
renderXlsxSheet(layout: XlsxLayout, canvas: HTMLCanvasElement): Promise<void>;
|
|
11
13
|
openPdf(source: ArrayBuffer | string): Promise<PdfDocumentHandle>;
|
|
12
14
|
getPdfPageCount(handle: PdfDocumentHandle): number;
|
|
13
15
|
getPdfPageDimensions(handle: PdfDocumentHandle, pageNum: number): Promise<{
|
|
14
16
|
width: number;
|
|
15
17
|
height: number;
|
|
16
18
|
}>;
|
|
19
|
+
private _getPdfPage;
|
|
20
|
+
private _renderToCanvas;
|
|
21
|
+
renderPdfPageToCanvas(handle: PdfDocumentHandle, pageNum: number, canvas: HTMLCanvasElement, dpi?: number): Promise<void>;
|
|
17
22
|
renderPdfPage(handle: PdfDocumentHandle, pageNum: number, canvas: HTMLCanvasElement, dpi?: number): Promise<string>;
|
|
18
23
|
closePdf(handle: PdfDocumentHandle): Promise<void>;
|
|
19
24
|
openMarkdown(source: ArrayBuffer | string): Promise<{
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { extractPptx, parsePptxSlides, renderSlideToCanvas } from '../wasm/pptx';
|
|
2
2
|
import { processDocx, renderDocxPage as wasmRenderDocxPage } from '../wasm/docx';
|
|
3
|
+
import { processXlsx, renderXlsxSheet as wasmRenderXlsxSheet } from '../wasm/xlsx';
|
|
3
4
|
import { initWasm } from '../wasm/wasm-loader';
|
|
4
5
|
export class WasmDocumentService {
|
|
5
6
|
async openPptx(source) {
|
|
@@ -53,6 +54,18 @@ export class WasmDocumentService {
|
|
|
53
54
|
await initWasm();
|
|
54
55
|
await wasmRenderDocxPage(page, canvas);
|
|
55
56
|
}
|
|
57
|
+
async openXlsx(source) {
|
|
58
|
+
if (typeof source === 'string') {
|
|
59
|
+
throw new Error('WasmDocumentService requires ArrayBuffer for XLSX, not a file path');
|
|
60
|
+
}
|
|
61
|
+
await initWasm();
|
|
62
|
+
const { document, layouts } = await processXlsx(source);
|
|
63
|
+
return { document, layouts };
|
|
64
|
+
}
|
|
65
|
+
async renderXlsxSheet(layout, canvas) {
|
|
66
|
+
await initWasm();
|
|
67
|
+
await wasmRenderXlsxSheet(layout, canvas);
|
|
68
|
+
}
|
|
56
69
|
async openPdf(source) {
|
|
57
70
|
if (typeof source === 'string') {
|
|
58
71
|
throw new Error('WasmDocumentService requires ArrayBuffer for PDF, not a file path');
|
|
@@ -76,9 +89,12 @@ export class WasmDocumentService {
|
|
|
76
89
|
const viewport = page.getViewport({ scale: 1 });
|
|
77
90
|
return { width: viewport.width, height: viewport.height };
|
|
78
91
|
}
|
|
79
|
-
async
|
|
92
|
+
async _getPdfPage(handle, pageNum) {
|
|
80
93
|
const doc = handle.doc;
|
|
81
|
-
|
|
94
|
+
return doc.getPage(pageNum + 1);
|
|
95
|
+
}
|
|
96
|
+
async _renderToCanvas(handle, pageNum, canvas, dpi) {
|
|
97
|
+
const page = await this._getPdfPage(handle, pageNum);
|
|
82
98
|
const scale = dpi / 72;
|
|
83
99
|
const viewport = page.getViewport({ scale });
|
|
84
100
|
canvas.width = viewport.width;
|
|
@@ -87,7 +103,13 @@ export class WasmDocumentService {
|
|
|
87
103
|
if (!ctx)
|
|
88
104
|
throw new Error('Failed to get canvas 2d context');
|
|
89
105
|
await page.render({ canvasContext: ctx, viewport }).promise;
|
|
90
|
-
|
|
106
|
+
}
|
|
107
|
+
async renderPdfPageToCanvas(handle, pageNum, canvas, dpi = 150) {
|
|
108
|
+
await this._renderToCanvas(handle, pageNum, canvas, dpi);
|
|
109
|
+
}
|
|
110
|
+
async renderPdfPage(handle, pageNum, canvas, dpi = 150) {
|
|
111
|
+
await this._renderToCanvas(handle, pageNum, canvas, dpi);
|
|
112
|
+
return canvas.toDataURL('image/jpeg', 0.85);
|
|
91
113
|
}
|
|
92
114
|
async closePdf(handle) {
|
|
93
115
|
const doc = handle.doc;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"WasmDocumentService.js","sourceRoot":"","sources":["../../src/services/WasmDocumentService.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"WasmDocumentService.js","sourceRoot":"","sources":["../../src/services/WasmDocumentService.ts"],"names":[],"mappings":"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"}
|
|
@@ -5,6 +5,8 @@
|
|
|
5
5
|
background: var(--document-bg);
|
|
6
6
|
}
|
|
7
7
|
|
|
8
|
+
/* ── Filmstrip sidebar ── */
|
|
9
|
+
|
|
8
10
|
.docx-filmstrip {
|
|
9
11
|
width: 200px;
|
|
10
12
|
background: var(--surface);
|
|
@@ -13,10 +15,40 @@
|
|
|
13
15
|
flex-direction: column;
|
|
14
16
|
overflow-y: auto;
|
|
15
17
|
flex-shrink: 0;
|
|
18
|
+
transition: width 0.2s ease;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
.docx-filmstrip.collapsed {
|
|
22
|
+
width: 36px;
|
|
23
|
+
overflow: hidden;
|
|
16
24
|
}
|
|
17
25
|
|
|
18
|
-
.docx-filmstrip
|
|
19
|
-
|
|
26
|
+
.docx-filmstrip-header {
|
|
27
|
+
display: flex;
|
|
28
|
+
align-items: center;
|
|
29
|
+
gap: 8px;
|
|
30
|
+
padding: 8px 12px;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
.docx-filmstrip-toggle {
|
|
34
|
+
background: none;
|
|
35
|
+
border: 1px solid var(--border-default);
|
|
36
|
+
border-radius: 4px;
|
|
37
|
+
color: var(--text-secondary);
|
|
38
|
+
cursor: pointer;
|
|
39
|
+
padding: 2px 6px;
|
|
40
|
+
font-size: 11px;
|
|
41
|
+
line-height: 1;
|
|
42
|
+
transition: background 0.15s, color 0.15s;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
.docx-filmstrip-toggle:hover {
|
|
46
|
+
background: var(--surface-elevated);
|
|
47
|
+
color: var(--text-primary);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
.docx-filmstrip-header h3 {
|
|
51
|
+
margin: 0;
|
|
20
52
|
font-size: 14px;
|
|
21
53
|
font-weight: 600;
|
|
22
54
|
color: var(--text-secondary);
|
|
@@ -80,6 +112,8 @@
|
|
|
80
112
|
color: var(--text-muted);
|
|
81
113
|
}
|
|
82
114
|
|
|
115
|
+
/* ── Main viewer ── */
|
|
116
|
+
|
|
83
117
|
.docx-viewer-main {
|
|
84
118
|
flex: 1;
|
|
85
119
|
display: flex;
|
|
@@ -96,6 +130,11 @@
|
|
|
96
130
|
gap: 20px;
|
|
97
131
|
}
|
|
98
132
|
|
|
133
|
+
.docx-page-canvas {
|
|
134
|
+
background: var(--document-surface);
|
|
135
|
+
box-shadow: var(--shadow-md, 0 2px 8px rgba(0, 0, 0, 0.3));
|
|
136
|
+
}
|
|
137
|
+
|
|
99
138
|
.docx-page-controls {
|
|
100
139
|
display: flex;
|
|
101
140
|
gap: 16px;
|
|
@@ -127,6 +166,8 @@
|
|
|
127
166
|
opacity: 0.5;
|
|
128
167
|
}
|
|
129
168
|
|
|
169
|
+
/* ── Loading / error / empty states ── */
|
|
170
|
+
|
|
130
171
|
.docx-viewer {
|
|
131
172
|
width: 100%;
|
|
132
173
|
height: 100%;
|
|
@@ -160,50 +201,6 @@
|
|
|
160
201
|
margin-top: 0;
|
|
161
202
|
}
|
|
162
203
|
|
|
163
|
-
.docx-page {
|
|
164
|
-
background: var(--document-surface);
|
|
165
|
-
box-shadow: var(--shadow-md, 0 2px 8px rgba(0, 0, 0, 0.3));
|
|
166
|
-
margin-bottom: 20px;
|
|
167
|
-
font-family: 'Calibri', 'Arial', sans-serif;
|
|
168
|
-
font-size: 11pt;
|
|
169
|
-
line-height: 1.15;
|
|
170
|
-
color: var(--document-text, #000);
|
|
171
|
-
}
|
|
172
|
-
|
|
173
|
-
.docx-paragraph {
|
|
174
|
-
margin-bottom: 8pt;
|
|
175
|
-
white-space: pre-wrap;
|
|
176
|
-
word-wrap: break-word;
|
|
177
|
-
}
|
|
178
|
-
|
|
179
|
-
.docx-paragraph:empty {
|
|
180
|
-
min-height: 1em;
|
|
181
|
-
}
|
|
182
|
-
|
|
183
|
-
.docx-table {
|
|
184
|
-
width: 100%;
|
|
185
|
-
border-collapse: collapse;
|
|
186
|
-
margin: 12pt 0;
|
|
187
|
-
}
|
|
188
|
-
|
|
189
|
-
.docx-table td {
|
|
190
|
-
border: 1px solid var(--border-default);
|
|
191
|
-
padding: 4pt 8pt;
|
|
192
|
-
vertical-align: top;
|
|
193
|
-
}
|
|
194
|
-
|
|
195
|
-
.docx-info {
|
|
196
|
-
color: var(--text-primary);
|
|
197
|
-
font-size: 12px;
|
|
198
|
-
padding: 10px;
|
|
199
|
-
background: var(--surface-elevated);
|
|
200
|
-
border-radius: 4px;
|
|
201
|
-
}
|
|
202
|
-
|
|
203
|
-
.docx-info span + span {
|
|
204
|
-
margin-left: 8px;
|
|
205
|
-
}
|
|
206
|
-
|
|
207
204
|
.empty-state {
|
|
208
205
|
color: var(--text-primary);
|
|
209
206
|
font-size: 16px;
|
|
@@ -1,18 +1,16 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
-
import { useEffect, useState, useRef } from 'react';
|
|
2
|
+
import { useEffect, useState, useRef, useCallback } from 'react';
|
|
3
3
|
import { getDocumentService } from '../services/documentServiceRegistry';
|
|
4
4
|
|
|
5
5
|
export function DocxViewer({ fileData, filePath } = {}) {
|
|
6
|
-
const [paragraphs, setParagraphs] = useState([]);
|
|
7
|
-
const [tables, setTables] = useState([]);
|
|
8
|
-
const [structure, setStructure] = useState(null);
|
|
9
6
|
const [pages, setPages] = useState([]);
|
|
10
7
|
const [currentPage, setCurrentPage] = useState(0);
|
|
11
8
|
const [loading, setLoading] = useState(true);
|
|
12
9
|
const [error, setError] = useState(null);
|
|
13
10
|
const [thumbnails, setThumbnails] = useState(new Map());
|
|
14
|
-
const [
|
|
15
|
-
const
|
|
11
|
+
const [sidebarCollapsed, setSidebarCollapsed] = useState(false);
|
|
12
|
+
const canvasRef = useRef(null);
|
|
13
|
+
const docHandleRef = useRef(null);
|
|
16
14
|
useEffect(() => {
|
|
17
15
|
const loadDocument = async () => {
|
|
18
16
|
try {
|
|
@@ -20,43 +18,13 @@ export function DocxViewer({ fileData, filePath } = {}) {
|
|
|
20
18
|
const service = getDocumentService();
|
|
21
19
|
if (fileData) {
|
|
22
20
|
const handle = await service.openDocx(fileData);
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
setStructure({
|
|
26
|
-
paragraph_count: parsed.paragraphs?.length ?? 0,
|
|
27
|
-
table_count: parsed.tables?.length ?? 0,
|
|
28
|
-
page_width: parsed.page_width ?? 612,
|
|
29
|
-
page_height: parsed.page_height ?? 792,
|
|
30
|
-
margins: parsed.margins ?? { top: 72, bottom: 72, left: 72, right: 72 },
|
|
31
|
-
});
|
|
32
|
-
const wasmParas = (parsed.paragraphs ?? []).map((p, i) => ({
|
|
33
|
-
index: i,
|
|
34
|
-
text: p.runs?.map((r) => r.text).join('') ?? '',
|
|
35
|
-
runs: (p.runs ?? []).map((r) => ({
|
|
36
|
-
text: r.text,
|
|
37
|
-
style: {
|
|
38
|
-
bold: r.bold ?? false,
|
|
39
|
-
italic: r.italic ?? false,
|
|
40
|
-
underline: r.underline ?? false,
|
|
41
|
-
font_family: r.font_family,
|
|
42
|
-
font_size: r.font_size,
|
|
43
|
-
color: r.color,
|
|
44
|
-
},
|
|
45
|
-
})),
|
|
46
|
-
has_style: false,
|
|
47
|
-
has_numbering: false,
|
|
48
|
-
}));
|
|
49
|
-
setParagraphs(wasmParas);
|
|
50
|
-
setTables([]);
|
|
21
|
+
docHandleRef.current = handle;
|
|
22
|
+
setPages(handle.pages);
|
|
51
23
|
}
|
|
52
|
-
else {
|
|
53
|
-
const
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
const paraData = await invoke('docx_get_paragraphs', {});
|
|
57
|
-
setParagraphs(paraData.paragraphs);
|
|
58
|
-
const tableData = await invoke('docx_get_tables', {});
|
|
59
|
-
setTables(tableData.tables);
|
|
24
|
+
else if (filePath) {
|
|
25
|
+
const handle = await service.openDocx(filePath);
|
|
26
|
+
docHandleRef.current = handle;
|
|
27
|
+
setPages(handle.pages);
|
|
60
28
|
}
|
|
61
29
|
setLoading(false);
|
|
62
30
|
}
|
|
@@ -68,53 +36,57 @@ export function DocxViewer({ fileData, filePath } = {}) {
|
|
|
68
36
|
};
|
|
69
37
|
loadDocument();
|
|
70
38
|
}, [fileData, filePath]);
|
|
71
|
-
|
|
72
|
-
if (!
|
|
39
|
+
const renderCurrentPage = useCallback(async () => {
|
|
40
|
+
if (!canvasRef.current || pages.length === 0)
|
|
41
|
+
return;
|
|
42
|
+
const page = pages[currentPage];
|
|
43
|
+
if (!page)
|
|
73
44
|
return;
|
|
74
|
-
const
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
});
|
|
45
|
+
const canvas = canvasRef.current;
|
|
46
|
+
canvas.width = page.width;
|
|
47
|
+
canvas.height = page.height;
|
|
48
|
+
try {
|
|
49
|
+
const service = getDocumentService();
|
|
50
|
+
await service.renderDocxPage(page, canvas);
|
|
81
51
|
}
|
|
82
|
-
|
|
83
|
-
|
|
52
|
+
catch (err) {
|
|
53
|
+
console.error('Failed to render DOCX page:', err);
|
|
84
54
|
}
|
|
85
|
-
|
|
86
|
-
|
|
55
|
+
}, [pages, currentPage]);
|
|
56
|
+
useEffect(() => {
|
|
57
|
+
renderCurrentPage();
|
|
58
|
+
}, [renderCurrentPage]);
|
|
87
59
|
useEffect(() => {
|
|
88
60
|
if (pages.length === 0)
|
|
89
61
|
return;
|
|
90
62
|
const generateThumbnails = async () => {
|
|
63
|
+
const service = getDocumentService();
|
|
91
64
|
for (let i = 0; i < pages.length; i++) {
|
|
92
|
-
const pageElement = pageRefs.current.get(i);
|
|
93
|
-
if (!pageElement)
|
|
94
|
-
continue;
|
|
95
65
|
try {
|
|
96
|
-
const
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
const
|
|
66
|
+
const page = pages[i];
|
|
67
|
+
const aspectRatio = page.width / page.height;
|
|
68
|
+
const thumbWidth = 200;
|
|
69
|
+
const thumbHeight = Math.round(thumbWidth / aspectRatio);
|
|
70
|
+
const fullCanvas = document.createElement('canvas');
|
|
71
|
+
fullCanvas.width = page.width;
|
|
72
|
+
fullCanvas.height = page.height;
|
|
73
|
+
await service.renderDocxPage(page, fullCanvas);
|
|
74
|
+
const thumbCanvas = document.createElement('canvas');
|
|
75
|
+
thumbCanvas.width = thumbWidth;
|
|
76
|
+
thumbCanvas.height = thumbHeight;
|
|
77
|
+
const ctx = thumbCanvas.getContext('2d');
|
|
100
78
|
if (!ctx)
|
|
101
79
|
continue;
|
|
102
|
-
ctx.
|
|
103
|
-
|
|
104
|
-
ctx.fillStyle = '#333';
|
|
105
|
-
ctx.font = '48px Arial';
|
|
106
|
-
ctx.textAlign = 'center';
|
|
107
|
-
ctx.textBaseline = 'middle';
|
|
108
|
-
ctx.fillText(`${i + 1}`, canvas.width / 2, canvas.height / 2);
|
|
109
|
-
const dataUrl = canvas.toDataURL();
|
|
80
|
+
ctx.drawImage(fullCanvas, 0, 0, thumbWidth, thumbHeight);
|
|
81
|
+
const dataUrl = thumbCanvas.toDataURL('image/png');
|
|
110
82
|
setThumbnails(prev => new Map(prev).set(i, dataUrl));
|
|
111
83
|
}
|
|
112
84
|
catch (err) {
|
|
113
|
-
console.error(
|
|
85
|
+
console.error(`Failed to generate thumbnail for page ${i}:`, err);
|
|
114
86
|
}
|
|
115
87
|
}
|
|
116
88
|
};
|
|
117
|
-
|
|
89
|
+
generateThumbnails();
|
|
118
90
|
}, [pages]);
|
|
119
91
|
if (loading) {
|
|
120
92
|
return (_jsx("div", { className: "docx-viewer loading", children: _jsx("div", { className: "loading-spinner", children: "Loading document..." }) }));
|
|
@@ -125,33 +97,10 @@ export function DocxViewer({ fileData, filePath } = {}) {
|
|
|
125
97
|
if (pages.length === 0) {
|
|
126
98
|
return (_jsx("div", { className: "docx-viewer", children: _jsx("div", { className: "empty-state", children: "No content to display" }) }));
|
|
127
99
|
}
|
|
128
|
-
const
|
|
129
|
-
return (_jsxs("div", { className: "docx-viewer-container", children: [_jsxs("aside", { className: "docx-filmstrip", children: [_jsx("h3", { children: "Pages" }), _jsx("div", { className: "docx-thumbnail-list", children: pages.map((_, pageIdx) => (_jsxs("div", { className: `docx-thumbnail ${currentPage === pageIdx ? 'active' : ''}`, onClick: () => setCurrentPage(pageIdx), children: [_jsx("div", { className: "docx-thumbnail-number", children: pageIdx + 1 }), thumbnails.has(pageIdx) ? (_jsx("img", { src: thumbnails.get(pageIdx), alt: `Page ${pageIdx + 1}` })) : (_jsx("div", { className: "docx-thumbnail-loading", children: "Loading..." }))] }, pageIdx))) })] }), _jsx("main", { className: "docx-viewer-main", children: _jsxs("div", { className: "docx-page-container", children: [
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
},
|
|
133
|
-
width: structure ? `${structure.page_width}px` : '612px',
|
|
134
|
-
minHeight: structure ? `${structure.page_height}px` : '792px',
|
|
135
|
-
padding: structure
|
|
136
|
-
? `${structure.margins.top}px ${structure.margins.right}px ${structure.margins.bottom}px ${structure.margins.left}px`
|
|
137
|
-
: '72px'
|
|
138
|
-
}, children: [currentPageContent.paragraphs.map((para) => (_jsx("div", { className: "docx-paragraph", children: para.runs.map((run, runIdx) => {
|
|
139
|
-
const style = {
|
|
140
|
-
fontWeight: run.style.bold ? 'bold' : 'normal',
|
|
141
|
-
fontStyle: run.style.italic ? 'italic' : 'normal',
|
|
142
|
-
textDecoration: run.style.underline ? 'underline' : 'none',
|
|
143
|
-
};
|
|
144
|
-
if (run.style.font_family) {
|
|
145
|
-
style.fontFamily = run.style.font_family;
|
|
146
|
-
}
|
|
147
|
-
if (run.style.font_size) {
|
|
148
|
-
style.fontSize = `${run.style.font_size}pt`;
|
|
149
|
-
}
|
|
150
|
-
if (run.style.color) {
|
|
151
|
-
const c = run.style.color;
|
|
152
|
-
style.color = `rgba(${c.r}, ${c.g}, ${c.b}, ${c.a ?? 1})`;
|
|
153
|
-
}
|
|
154
|
-
return (_jsx("span", { style: style, children: run.text }, runIdx));
|
|
155
|
-
}) }, para.index))), currentPageContent.tables.map((table) => (_jsx("table", { className: "docx-table", children: _jsx("tbody", { children: table.rows.map((row) => (_jsx("tr", { children: row.cells.map((cell) => (_jsx("td", { children: cell.text }, cell.cell_index))) }, row.row_index))) }) }, table.table_index)))] }), _jsxs("div", { className: "docx-page-controls", children: [_jsx("button", { onClick: () => setCurrentPage(Math.max(0, currentPage - 1)), disabled: currentPage === 0, children: "\u2190 Previous" }), _jsxs("span", { children: ["Page ", currentPage + 1, " of ", pages.length] }), _jsx("button", { onClick: () => setCurrentPage(Math.min(pages.length - 1, currentPage + 1)), disabled: currentPage === pages.length - 1, children: "Next \u2192" })] })] }) })] }));
|
|
100
|
+
const page = pages[currentPage];
|
|
101
|
+
return (_jsxs("div", { className: "docx-viewer-container", children: [_jsxs("aside", { className: `docx-filmstrip ${sidebarCollapsed ? 'collapsed' : ''}`, children: [_jsxs("div", { className: "docx-filmstrip-header", children: [_jsx("button", { className: "docx-filmstrip-toggle", onClick: () => setSidebarCollapsed(!sidebarCollapsed), title: sidebarCollapsed ? 'Show pages' : 'Hide pages', children: sidebarCollapsed ? '\u25B6' : '\u25C0' }), !sidebarCollapsed && _jsx("h3", { children: "Pages" })] }), !sidebarCollapsed && (_jsx("div", { className: "docx-thumbnail-list", children: pages.map((_, pageIdx) => (_jsxs("div", { className: `docx-thumbnail ${currentPage === pageIdx ? 'active' : ''}`, onClick: () => setCurrentPage(pageIdx), children: [_jsx("div", { className: "docx-thumbnail-number", children: pageIdx + 1 }), thumbnails.has(pageIdx) ? (_jsx("img", { src: thumbnails.get(pageIdx), alt: `Page ${pageIdx + 1}` })) : (_jsx("div", { className: "docx-thumbnail-loading", children: "Loading..." }))] }, pageIdx))) }))] }), _jsx("main", { className: "docx-viewer-main", children: _jsxs("div", { className: "docx-page-container", children: [_jsx("canvas", { ref: canvasRef, className: "docx-page-canvas", style: {
|
|
102
|
+
width: `${page.width}px`,
|
|
103
|
+
height: `${page.height}px`,
|
|
104
|
+
} }), _jsxs("div", { className: "docx-page-controls", children: [_jsx("button", { onClick: () => setCurrentPage(Math.max(0, currentPage - 1)), disabled: currentPage === 0, children: "\u2190 Previous" }), _jsxs("span", { children: ["Page ", currentPage + 1, " of ", pages.length] }), _jsx("button", { onClick: () => setCurrentPage(Math.min(pages.length - 1, currentPage + 1)), disabled: currentPage === pages.length - 1, children: "Next \u2192" })] })] }) })] }));
|
|
156
105
|
}
|
|
157
106
|
//# sourceMappingURL=DocxViewer.js.map
|