canvu-react 0.3.13 → 0.3.16
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/README.md +14 -1
- package/dist/index.cjs +41 -15
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +41 -15
- package/dist/index.js.map +1 -1
- package/dist/react.cjs +114 -102
- package/dist/react.cjs.map +1 -1
- package/dist/react.d.cts +10 -1
- package/dist/react.d.ts +10 -1
- package/dist/react.js +114 -102
- package/dist/react.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -255,6 +255,11 @@ export function BoardImport() {
|
|
|
255
255
|
files: Array.from(files),
|
|
256
256
|
worldCenter: { x: 0, y: 0 },
|
|
257
257
|
assetStore,
|
|
258
|
+
pdfScale: 1.15,
|
|
259
|
+
pdfPageConcurrency: 2,
|
|
260
|
+
onItemsReady(nextItems) {
|
|
261
|
+
doc.onItemsChange([...doc.items, ...nextItems]);
|
|
262
|
+
},
|
|
258
263
|
decorateItem(item) {
|
|
259
264
|
return {
|
|
260
265
|
...item,
|
|
@@ -265,7 +270,6 @@ export function BoardImport() {
|
|
|
265
270
|
|
|
266
271
|
doc.onItemsChange([...doc.items, ...result.items]);
|
|
267
272
|
}
|
|
268
|
-
|
|
269
273
|
if (!doc.isHydrated) return null;
|
|
270
274
|
|
|
271
275
|
return (
|
|
@@ -300,6 +304,15 @@ export function BoardImport() {
|
|
|
300
304
|
}
|
|
301
305
|
```
|
|
302
306
|
|
|
307
|
+
canvu can now stream PDF pages into the canvas progressively through
|
|
308
|
+
`onItemsReady(...)`, skip PDF thumbnails during ingest, and use a lower initial
|
|
309
|
+
raster scale by default to improve time-to-first-render.
|
|
310
|
+
|
|
311
|
+
The native file tool now accepts multiple images and PDFs from the picker and
|
|
312
|
+
stacks every imported asset vertically. When the board already has uploaded
|
|
313
|
+
images or PDFs, new imports are inserted immediately after the existing stack
|
|
314
|
+
instead of overlapping previous content.
|
|
315
|
+
|
|
303
316
|
This helper is the same ingestion layer used internally by the native file
|
|
304
317
|
tool, so external imports do not need to reimplement PDF rasterization, local
|
|
305
318
|
blob persistence, or `pluginData` attachment.
|
package/dist/index.cjs
CHANGED
|
@@ -243,10 +243,32 @@ async function runWithConcurrency(items, concurrency, execute) {
|
|
|
243
243
|
async function loadPdfToStore(file, store, options) {
|
|
244
244
|
const scale = options?.scale ?? 1.5;
|
|
245
245
|
const pageConcurrency = options?.pageConcurrency ?? 2;
|
|
246
|
+
const storeThumbnails = options?.storeThumbnails ?? false;
|
|
246
247
|
const pdfjs = await getPdfJs();
|
|
247
248
|
const arrayBuffer = await file.arrayBuffer();
|
|
248
249
|
const pdf = await pdfjs.getDocument({ data: arrayBuffer }).promise;
|
|
249
250
|
const pageNumbers = normalizePdfPageNumbers(options?.pageNumbers, pdf.numPages);
|
|
251
|
+
const bufferedResults = /* @__PURE__ */ new Map();
|
|
252
|
+
let nextEmitIndex = 0;
|
|
253
|
+
let emitChain = Promise.resolve();
|
|
254
|
+
const queuePageEmission = async (pageResult) => {
|
|
255
|
+
bufferedResults.set(pageResult.pageNumber, pageResult);
|
|
256
|
+
const run = async () => {
|
|
257
|
+
while (nextEmitIndex < pageNumbers.length) {
|
|
258
|
+
const nextPageNumber = pageNumbers[nextEmitIndex];
|
|
259
|
+
if (nextPageNumber == null) break;
|
|
260
|
+
const bufferedResult = bufferedResults.get(nextPageNumber);
|
|
261
|
+
if (!bufferedResult) break;
|
|
262
|
+
bufferedResults.delete(nextPageNumber);
|
|
263
|
+
nextEmitIndex += 1;
|
|
264
|
+
await options?.onPageStored?.(bufferedResult);
|
|
265
|
+
}
|
|
266
|
+
};
|
|
267
|
+
const nextChain = emitChain.then(run, run);
|
|
268
|
+
emitChain = nextChain.catch(() => {
|
|
269
|
+
});
|
|
270
|
+
await nextChain;
|
|
271
|
+
};
|
|
250
272
|
return await runWithConcurrency(
|
|
251
273
|
pageNumbers,
|
|
252
274
|
pageConcurrency,
|
|
@@ -256,27 +278,31 @@ async function loadPdfToStore(file, store, options) {
|
|
|
256
278
|
const mime = "image/png";
|
|
257
279
|
const pageBlob = await canvasToBlob(canvas, mime);
|
|
258
280
|
const blobId = await store.storeOriginal(pageBlob);
|
|
259
|
-
const
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
tCtx
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
281
|
+
const thumbnailBlobId = storeThumbnails ? await (async () => {
|
|
282
|
+
const thumbScale = Math.min(1, 256 / Math.max(width, height));
|
|
283
|
+
const tw = Math.max(1, Math.round(width * thumbScale));
|
|
284
|
+
const th = Math.max(1, Math.round(height * thumbScale));
|
|
285
|
+
const thumbCanvas = document.createElement("canvas");
|
|
286
|
+
thumbCanvas.width = tw;
|
|
287
|
+
thumbCanvas.height = th;
|
|
288
|
+
const tCtx = thumbCanvas.getContext("2d");
|
|
289
|
+
if (tCtx) {
|
|
290
|
+
tCtx.imageSmoothingEnabled = true;
|
|
291
|
+
tCtx.imageSmoothingQuality = "high";
|
|
292
|
+
tCtx.drawImage(canvas, 0, 0, tw, th);
|
|
293
|
+
}
|
|
294
|
+
const thumbBlob = await canvasToBlob(thumbCanvas, mime);
|
|
295
|
+
return await store.storeThumbnail(thumbBlob);
|
|
296
|
+
})() : "";
|
|
297
|
+
const pageResult = {
|
|
274
298
|
blobId,
|
|
275
299
|
thumbnailBlobId,
|
|
276
300
|
width,
|
|
277
301
|
height,
|
|
278
302
|
pageNumber
|
|
279
303
|
};
|
|
304
|
+
await queuePageEmission(pageResult);
|
|
305
|
+
return pageResult;
|
|
280
306
|
}
|
|
281
307
|
);
|
|
282
308
|
}
|