@xom11/whiteboard 0.9.1 → 0.10.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/{chunk-KEYZ5EZT.mjs → chunk-G7FR3AIV.mjs} +44 -5
- package/dist/chunk-G7FR3AIV.mjs.map +1 -0
- package/dist/{chunk-DU3RHKT5.mjs → chunk-PDKKDZ4H.mjs} +4 -4
- package/dist/{chunk-DU3RHKT5.mjs.map → chunk-PDKKDZ4H.mjs.map} +1 -1
- package/dist/chunk-PWIMZIB6.mjs +62 -0
- package/dist/chunk-PWIMZIB6.mjs.map +1 -0
- package/dist/chunk-WQOABS6N.mjs +197 -0
- package/dist/chunk-WQOABS6N.mjs.map +1 -0
- package/dist/geometry-2d.js +96 -12
- package/dist/geometry-2d.js.map +1 -1
- package/dist/geometry-2d.mjs +2 -2
- package/dist/geometry-3d.js +152 -93
- package/dist/geometry-3d.js.map +1 -1
- package/dist/geometry-3d.mjs +2 -2
- package/dist/{host-VDNAJMLC.mjs → host-DJETSFCG.mjs} +56 -12
- package/dist/host-DJETSFCG.mjs.map +1 -0
- package/dist/{host-PIIDSMVE.mjs → host-N6ACNJKI.mjs} +51 -12
- package/dist/host-N6ACNJKI.mjs.map +1 -0
- package/dist/index.d.mts +127 -1
- package/dist/index.d.ts +127 -1
- package/dist/index.js +1265 -174
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +991 -50
- package/dist/index.mjs.map +1 -1
- package/package.json +4 -1
- package/dist/chunk-DU2NFHRR.mjs +0 -103
- package/dist/chunk-DU2NFHRR.mjs.map +0 -1
- package/dist/chunk-IUVV52HO.mjs +0 -144
- package/dist/chunk-IUVV52HO.mjs.map +0 -1
- package/dist/chunk-KEYZ5EZT.mjs.map +0 -1
- package/dist/host-PIIDSMVE.mjs.map +0 -1
- package/dist/host-VDNAJMLC.mjs.map +0 -1
package/dist/index.d.mts
CHANGED
|
@@ -13,6 +13,7 @@ import { Geometry3DCustomData } from './geometry-3d.mjs';
|
|
|
13
13
|
export { geometry3dStamp, isGeometry3DCustomData } from './geometry-3d.mjs';
|
|
14
14
|
import { Graph2DCustomData } from './graph-2d.mjs';
|
|
15
15
|
export { graph2dStamp, isGraph2DCustomData } from './graph-2d.mjs';
|
|
16
|
+
import { PDFDocumentProxy } from 'pdfjs-dist';
|
|
16
17
|
import 'react';
|
|
17
18
|
|
|
18
19
|
interface SyncableAppState {
|
|
@@ -107,4 +108,129 @@ declare function restoreMissingStampFiles(api: any, elements: readonly ElementLi
|
|
|
107
108
|
|
|
108
109
|
type StampCustomData = GeometryCustomData | LatexCustomData | Geometry3DCustomData | Graph2DCustomData;
|
|
109
110
|
|
|
110
|
-
|
|
111
|
+
/**
|
|
112
|
+
* Rasterize PDF → PNG dataURLs cho từng trang.
|
|
113
|
+
*
|
|
114
|
+
* Worker config:
|
|
115
|
+
* - pdfjs-dist 5.x cần `GlobalWorkerOptions.workerSrc` (URL tới worker .mjs).
|
|
116
|
+
* - Mặc định trỏ CDN (jsdelivr). Consumer có thể override qua
|
|
117
|
+
* `configurePdfWorker(src)` trước khi gọi rasterize lần đầu.
|
|
118
|
+
* - Lý do CDN thay vì bundled worker: tsup không có cách clean để emit
|
|
119
|
+
* worker chunk ra cùng dist/ với URL ổn định, và consumer (Next.js)
|
|
120
|
+
* có thể self-host nếu cần offline.
|
|
121
|
+
*
|
|
122
|
+
* Lazy import pdfjs-dist để không phình bundle khi user không dùng PDF.
|
|
123
|
+
*/
|
|
124
|
+
|
|
125
|
+
/**
|
|
126
|
+
* Override workerSrc trước khi rasterize. Gọi từ consumer khi cần self-host
|
|
127
|
+
* worker file (vd offline mode, CSP cấm CDN).
|
|
128
|
+
*
|
|
129
|
+
* Mặc định nếu không gọi: dùng CDN jsdelivr theo version pdfjs-dist đã cài.
|
|
130
|
+
*/
|
|
131
|
+
declare function configurePdfWorker(workerSrc: string): void;
|
|
132
|
+
interface RasterizedPage {
|
|
133
|
+
pageNumber: number;
|
|
134
|
+
dataURL: string;
|
|
135
|
+
width: number;
|
|
136
|
+
height: number;
|
|
137
|
+
mimeType: 'image/png';
|
|
138
|
+
}
|
|
139
|
+
interface RasterizeOptions {
|
|
140
|
+
/** Scale render. Mặc định 2 (HiDPI sharp). */
|
|
141
|
+
scale?: number;
|
|
142
|
+
/** Danh sách trang 1-based. Mặc định: tất cả. */
|
|
143
|
+
pages?: number[];
|
|
144
|
+
/** Callback progress sau mỗi page. */
|
|
145
|
+
onProgress?: (done: number, total: number) => void;
|
|
146
|
+
/** AbortSignal để cancel giữa chừng. */
|
|
147
|
+
signal?: AbortSignal;
|
|
148
|
+
}
|
|
149
|
+
/**
|
|
150
|
+
* Load PDF chỉ để lấy `numPages` (vd hiển thị tổng số trang trên dialog).
|
|
151
|
+
* Caller phải tự đóng document bằng `closePdfDocument(doc)` khi xong.
|
|
152
|
+
*/
|
|
153
|
+
declare function loadPdfDocument(source: File | Blob | ArrayBuffer): Promise<PDFDocumentProxy>;
|
|
154
|
+
declare function closePdfDocument(doc: PDFDocumentProxy): Promise<void>;
|
|
155
|
+
/**
|
|
156
|
+
* Render danh sách trang ra PNG dataURL.
|
|
157
|
+
*
|
|
158
|
+
* Lưu ý:
|
|
159
|
+
* - Sử dụng `OffscreenCanvas` nếu có (browser hiện đại) để không touch DOM,
|
|
160
|
+
* fallback `<canvas>` document.createElement.
|
|
161
|
+
* - Mỗi page render xong sẽ release canvas (cho GC sớm với PDF nhiều trang).
|
|
162
|
+
*/
|
|
163
|
+
declare function rasterizePdf(doc: PDFDocumentProxy, options?: RasterizeOptions): Promise<RasterizedPage[]>;
|
|
164
|
+
|
|
165
|
+
type ExApi = any;
|
|
166
|
+
interface InsertRasterizedPagesOptions {
|
|
167
|
+
/** Scale dùng khi rasterize (để chia pixel → scene units). */
|
|
168
|
+
scale: number;
|
|
169
|
+
/** Toạ độ scene gốc cho page đầu tiên. Bỏ qua → giữa viewport. */
|
|
170
|
+
origin?: {
|
|
171
|
+
x: number;
|
|
172
|
+
y: number;
|
|
173
|
+
};
|
|
174
|
+
}
|
|
175
|
+
interface InsertRasterizedPagesResult {
|
|
176
|
+
insertedElementIds: string[];
|
|
177
|
+
fileIds: string[];
|
|
178
|
+
}
|
|
179
|
+
/**
|
|
180
|
+
* Chèn array `RasterizedPage` đã có sẵn vào scene. Tách ra để Whiteboard
|
|
181
|
+
* có thể: load doc → hỏi user range → rasterize → insert mà không phải gọi
|
|
182
|
+
* insertPdfPages (load lại từ ArrayBuffer 2 lần).
|
|
183
|
+
*/
|
|
184
|
+
declare function insertRasterizedPagesIntoScene(api: ExApi, rendered: RasterizedPage[], options: InsertRasterizedPagesOptions): InsertRasterizedPagesResult;
|
|
185
|
+
interface InsertPdfPagesOptions {
|
|
186
|
+
/** Trang cần chèn (1-based). Bỏ qua → chèn tất cả. */
|
|
187
|
+
pages?: number[];
|
|
188
|
+
/** Scale rasterize. Mặc định 2. */
|
|
189
|
+
scale?: number;
|
|
190
|
+
/** Toạ độ scene gốc cho page đầu tiên. Bỏ qua → giữa viewport. */
|
|
191
|
+
origin?: {
|
|
192
|
+
x: number;
|
|
193
|
+
y: number;
|
|
194
|
+
};
|
|
195
|
+
/** Progress callback. */
|
|
196
|
+
onProgress?: (done: number, total: number) => void;
|
|
197
|
+
/** AbortSignal. */
|
|
198
|
+
signal?: AbortSignal;
|
|
199
|
+
}
|
|
200
|
+
interface InsertPdfPagesResult {
|
|
201
|
+
insertedElementIds: string[];
|
|
202
|
+
pages: RasterizedPage[];
|
|
203
|
+
}
|
|
204
|
+
/**
|
|
205
|
+
* High-level: rasterize PDF + insert thành nhiều image element xếp dọc.
|
|
206
|
+
*
|
|
207
|
+
* Flow:
|
|
208
|
+
* 1. loadPdfDocument(source) → PDFDocumentProxy
|
|
209
|
+
* 2. rasterizePdf(doc, {pages, scale}) → RasterizedPage[]
|
|
210
|
+
* 3. Tạo fileId cho từng page, gọi api.addFiles batch.
|
|
211
|
+
* 4. Tính position: page 1 trung tâm viewport (hoặc origin), các page sau
|
|
212
|
+
* xếp dưới, cách PAGE_GAP.
|
|
213
|
+
* 5. api.updateScene({ elements: [...cũ, ...mới] })
|
|
214
|
+
*
|
|
215
|
+
* Không serialize PDF bytes — sau insert, các page là image element thuần,
|
|
216
|
+
* không thể re-edit qua double-click (theo design quyết định).
|
|
217
|
+
*/
|
|
218
|
+
declare function insertPdfPages(api: ExApi, source: File | Blob | ArrayBuffer, options?: InsertPdfPagesOptions): Promise<InsertPdfPagesResult>;
|
|
219
|
+
|
|
220
|
+
/**
|
|
221
|
+
* Parse chuỗi range trang dạng "1,3,5-10" → array số 1-based đã sort + dedupe.
|
|
222
|
+
*
|
|
223
|
+
* - Tokens cách nhau bằng dấu phẩy hoặc khoảng trắng.
|
|
224
|
+
* - Token có gạch "-" → range inclusive (5-10 = [5,6,7,8,9,10]).
|
|
225
|
+
* - Khoảng trắng quanh số bị bỏ qua.
|
|
226
|
+
* - Empty / chỉ space → [].
|
|
227
|
+
*
|
|
228
|
+
* Throws `Error` với message tiếng Việt khi:
|
|
229
|
+
* - Token không phải số / không phải range hợp lệ.
|
|
230
|
+
* - Số <= 0 hoặc > totalPages.
|
|
231
|
+
* - Range đảo ngược (vd "10-5") — coi là lỗi user thay vì auto-reverse để
|
|
232
|
+
* tránh nuốt typo.
|
|
233
|
+
*/
|
|
234
|
+
declare function parsePageRange(input: string, totalPages: number): number[];
|
|
235
|
+
|
|
236
|
+
export { ALL_STAMPS, DEFAULT_STAMPS, EXPERIMENTAL_STAMPS, type ExcalidrawSceneSnapshot, Geometry3DCustomData, GeometryCustomData, Graph2DCustomData, type InsertPdfPagesOptions, type InsertPdfPagesResult, type InsertRasterizedPagesOptions, type InsertRasterizedPagesResult, LatexCustomData, type RasterizeOptions, type RasterizedPage, STABLE_STAMPS, type StampCustomData, StampType, type SyncableAppState, Whiteboard, type WhiteboardProps, closePdfDocument, configurePdfWorker, findStampForCustomData, insertPdfPages, insertRasterizedPagesIntoScene, isStampElement, loadPdfDocument, parsePageRange, pickSyncableAppState, rasterizePdf, restoreMissingStampFiles };
|
package/dist/index.d.ts
CHANGED
|
@@ -13,6 +13,7 @@ import { Geometry3DCustomData } from './geometry-3d.js';
|
|
|
13
13
|
export { geometry3dStamp, isGeometry3DCustomData } from './geometry-3d.js';
|
|
14
14
|
import { Graph2DCustomData } from './graph-2d.js';
|
|
15
15
|
export { graph2dStamp, isGraph2DCustomData } from './graph-2d.js';
|
|
16
|
+
import { PDFDocumentProxy } from 'pdfjs-dist';
|
|
16
17
|
import 'react';
|
|
17
18
|
|
|
18
19
|
interface SyncableAppState {
|
|
@@ -107,4 +108,129 @@ declare function restoreMissingStampFiles(api: any, elements: readonly ElementLi
|
|
|
107
108
|
|
|
108
109
|
type StampCustomData = GeometryCustomData | LatexCustomData | Geometry3DCustomData | Graph2DCustomData;
|
|
109
110
|
|
|
110
|
-
|
|
111
|
+
/**
|
|
112
|
+
* Rasterize PDF → PNG dataURLs cho từng trang.
|
|
113
|
+
*
|
|
114
|
+
* Worker config:
|
|
115
|
+
* - pdfjs-dist 5.x cần `GlobalWorkerOptions.workerSrc` (URL tới worker .mjs).
|
|
116
|
+
* - Mặc định trỏ CDN (jsdelivr). Consumer có thể override qua
|
|
117
|
+
* `configurePdfWorker(src)` trước khi gọi rasterize lần đầu.
|
|
118
|
+
* - Lý do CDN thay vì bundled worker: tsup không có cách clean để emit
|
|
119
|
+
* worker chunk ra cùng dist/ với URL ổn định, và consumer (Next.js)
|
|
120
|
+
* có thể self-host nếu cần offline.
|
|
121
|
+
*
|
|
122
|
+
* Lazy import pdfjs-dist để không phình bundle khi user không dùng PDF.
|
|
123
|
+
*/
|
|
124
|
+
|
|
125
|
+
/**
|
|
126
|
+
* Override workerSrc trước khi rasterize. Gọi từ consumer khi cần self-host
|
|
127
|
+
* worker file (vd offline mode, CSP cấm CDN).
|
|
128
|
+
*
|
|
129
|
+
* Mặc định nếu không gọi: dùng CDN jsdelivr theo version pdfjs-dist đã cài.
|
|
130
|
+
*/
|
|
131
|
+
declare function configurePdfWorker(workerSrc: string): void;
|
|
132
|
+
interface RasterizedPage {
|
|
133
|
+
pageNumber: number;
|
|
134
|
+
dataURL: string;
|
|
135
|
+
width: number;
|
|
136
|
+
height: number;
|
|
137
|
+
mimeType: 'image/png';
|
|
138
|
+
}
|
|
139
|
+
interface RasterizeOptions {
|
|
140
|
+
/** Scale render. Mặc định 2 (HiDPI sharp). */
|
|
141
|
+
scale?: number;
|
|
142
|
+
/** Danh sách trang 1-based. Mặc định: tất cả. */
|
|
143
|
+
pages?: number[];
|
|
144
|
+
/** Callback progress sau mỗi page. */
|
|
145
|
+
onProgress?: (done: number, total: number) => void;
|
|
146
|
+
/** AbortSignal để cancel giữa chừng. */
|
|
147
|
+
signal?: AbortSignal;
|
|
148
|
+
}
|
|
149
|
+
/**
|
|
150
|
+
* Load PDF chỉ để lấy `numPages` (vd hiển thị tổng số trang trên dialog).
|
|
151
|
+
* Caller phải tự đóng document bằng `closePdfDocument(doc)` khi xong.
|
|
152
|
+
*/
|
|
153
|
+
declare function loadPdfDocument(source: File | Blob | ArrayBuffer): Promise<PDFDocumentProxy>;
|
|
154
|
+
declare function closePdfDocument(doc: PDFDocumentProxy): Promise<void>;
|
|
155
|
+
/**
|
|
156
|
+
* Render danh sách trang ra PNG dataURL.
|
|
157
|
+
*
|
|
158
|
+
* Lưu ý:
|
|
159
|
+
* - Sử dụng `OffscreenCanvas` nếu có (browser hiện đại) để không touch DOM,
|
|
160
|
+
* fallback `<canvas>` document.createElement.
|
|
161
|
+
* - Mỗi page render xong sẽ release canvas (cho GC sớm với PDF nhiều trang).
|
|
162
|
+
*/
|
|
163
|
+
declare function rasterizePdf(doc: PDFDocumentProxy, options?: RasterizeOptions): Promise<RasterizedPage[]>;
|
|
164
|
+
|
|
165
|
+
type ExApi = any;
|
|
166
|
+
interface InsertRasterizedPagesOptions {
|
|
167
|
+
/** Scale dùng khi rasterize (để chia pixel → scene units). */
|
|
168
|
+
scale: number;
|
|
169
|
+
/** Toạ độ scene gốc cho page đầu tiên. Bỏ qua → giữa viewport. */
|
|
170
|
+
origin?: {
|
|
171
|
+
x: number;
|
|
172
|
+
y: number;
|
|
173
|
+
};
|
|
174
|
+
}
|
|
175
|
+
interface InsertRasterizedPagesResult {
|
|
176
|
+
insertedElementIds: string[];
|
|
177
|
+
fileIds: string[];
|
|
178
|
+
}
|
|
179
|
+
/**
|
|
180
|
+
* Chèn array `RasterizedPage` đã có sẵn vào scene. Tách ra để Whiteboard
|
|
181
|
+
* có thể: load doc → hỏi user range → rasterize → insert mà không phải gọi
|
|
182
|
+
* insertPdfPages (load lại từ ArrayBuffer 2 lần).
|
|
183
|
+
*/
|
|
184
|
+
declare function insertRasterizedPagesIntoScene(api: ExApi, rendered: RasterizedPage[], options: InsertRasterizedPagesOptions): InsertRasterizedPagesResult;
|
|
185
|
+
interface InsertPdfPagesOptions {
|
|
186
|
+
/** Trang cần chèn (1-based). Bỏ qua → chèn tất cả. */
|
|
187
|
+
pages?: number[];
|
|
188
|
+
/** Scale rasterize. Mặc định 2. */
|
|
189
|
+
scale?: number;
|
|
190
|
+
/** Toạ độ scene gốc cho page đầu tiên. Bỏ qua → giữa viewport. */
|
|
191
|
+
origin?: {
|
|
192
|
+
x: number;
|
|
193
|
+
y: number;
|
|
194
|
+
};
|
|
195
|
+
/** Progress callback. */
|
|
196
|
+
onProgress?: (done: number, total: number) => void;
|
|
197
|
+
/** AbortSignal. */
|
|
198
|
+
signal?: AbortSignal;
|
|
199
|
+
}
|
|
200
|
+
interface InsertPdfPagesResult {
|
|
201
|
+
insertedElementIds: string[];
|
|
202
|
+
pages: RasterizedPage[];
|
|
203
|
+
}
|
|
204
|
+
/**
|
|
205
|
+
* High-level: rasterize PDF + insert thành nhiều image element xếp dọc.
|
|
206
|
+
*
|
|
207
|
+
* Flow:
|
|
208
|
+
* 1. loadPdfDocument(source) → PDFDocumentProxy
|
|
209
|
+
* 2. rasterizePdf(doc, {pages, scale}) → RasterizedPage[]
|
|
210
|
+
* 3. Tạo fileId cho từng page, gọi api.addFiles batch.
|
|
211
|
+
* 4. Tính position: page 1 trung tâm viewport (hoặc origin), các page sau
|
|
212
|
+
* xếp dưới, cách PAGE_GAP.
|
|
213
|
+
* 5. api.updateScene({ elements: [...cũ, ...mới] })
|
|
214
|
+
*
|
|
215
|
+
* Không serialize PDF bytes — sau insert, các page là image element thuần,
|
|
216
|
+
* không thể re-edit qua double-click (theo design quyết định).
|
|
217
|
+
*/
|
|
218
|
+
declare function insertPdfPages(api: ExApi, source: File | Blob | ArrayBuffer, options?: InsertPdfPagesOptions): Promise<InsertPdfPagesResult>;
|
|
219
|
+
|
|
220
|
+
/**
|
|
221
|
+
* Parse chuỗi range trang dạng "1,3,5-10" → array số 1-based đã sort + dedupe.
|
|
222
|
+
*
|
|
223
|
+
* - Tokens cách nhau bằng dấu phẩy hoặc khoảng trắng.
|
|
224
|
+
* - Token có gạch "-" → range inclusive (5-10 = [5,6,7,8,9,10]).
|
|
225
|
+
* - Khoảng trắng quanh số bị bỏ qua.
|
|
226
|
+
* - Empty / chỉ space → [].
|
|
227
|
+
*
|
|
228
|
+
* Throws `Error` với message tiếng Việt khi:
|
|
229
|
+
* - Token không phải số / không phải range hợp lệ.
|
|
230
|
+
* - Số <= 0 hoặc > totalPages.
|
|
231
|
+
* - Range đảo ngược (vd "10-5") — coi là lỗi user thay vì auto-reverse để
|
|
232
|
+
* tránh nuốt typo.
|
|
233
|
+
*/
|
|
234
|
+
declare function parsePageRange(input: string, totalPages: number): number[];
|
|
235
|
+
|
|
236
|
+
export { ALL_STAMPS, DEFAULT_STAMPS, EXPERIMENTAL_STAMPS, type ExcalidrawSceneSnapshot, Geometry3DCustomData, GeometryCustomData, Graph2DCustomData, type InsertPdfPagesOptions, type InsertPdfPagesResult, type InsertRasterizedPagesOptions, type InsertRasterizedPagesResult, LatexCustomData, type RasterizeOptions, type RasterizedPage, STABLE_STAMPS, type StampCustomData, StampType, type SyncableAppState, Whiteboard, type WhiteboardProps, closePdfDocument, configurePdfWorker, findStampForCustomData, insertPdfPages, insertRasterizedPagesIntoScene, isStampElement, loadPdfDocument, parsePageRange, pickSyncableAppState, rasterizePdf, restoreMissingStampFiles };
|