canvu-react 0.3.24 → 0.3.25
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/index.cjs +49 -30
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +8 -1
- package/dist/index.d.ts +8 -1
- package/dist/index.js +49 -31
- package/dist/index.js.map +1 -1
- package/dist/react.cjs +105 -30
- package/dist/react.cjs.map +1 -1
- package/dist/react.js +105 -30
- package/dist/react.js.map +1 -1
- package/package.json +1 -1
package/dist/react.js
CHANGED
|
@@ -711,6 +711,47 @@ var init_shape_builders = __esm({
|
|
|
711
711
|
}
|
|
712
712
|
});
|
|
713
713
|
|
|
714
|
+
// src/image/canvas-encode.ts
|
|
715
|
+
var DEFAULT_FALLBACK_MIME_TYPES = ["image/png"];
|
|
716
|
+
var tryCanvasToBlob = (canvas, mimeType, quality) => new Promise((resolve) => {
|
|
717
|
+
canvas.toBlob((blob) => resolve(blob), mimeType, quality);
|
|
718
|
+
});
|
|
719
|
+
var blobFromDataUrl = async (dataUrl) => {
|
|
720
|
+
const response = await fetch(dataUrl);
|
|
721
|
+
const blob = await response.blob();
|
|
722
|
+
if (blob.size === 0) {
|
|
723
|
+
throw new Error("Failed to encode canvas to blob");
|
|
724
|
+
}
|
|
725
|
+
return blob;
|
|
726
|
+
};
|
|
727
|
+
async function encodeCanvasToBlob(canvas, options) {
|
|
728
|
+
const primaryMimeType = options?.mimeType ?? "image/png";
|
|
729
|
+
const quality = options?.quality;
|
|
730
|
+
const mimeTypes = [
|
|
731
|
+
primaryMimeType,
|
|
732
|
+
...options?.fallbackMimeTypes ?? DEFAULT_FALLBACK_MIME_TYPES
|
|
733
|
+
].filter(
|
|
734
|
+
(mimeType, index, mimeTypeList) => mimeTypeList.indexOf(mimeType) === index
|
|
735
|
+
);
|
|
736
|
+
for (const mimeType of mimeTypes) {
|
|
737
|
+
const blob = await tryCanvasToBlob(
|
|
738
|
+
canvas,
|
|
739
|
+
mimeType,
|
|
740
|
+
mimeType === primaryMimeType ? quality : void 0
|
|
741
|
+
);
|
|
742
|
+
if (blob) {
|
|
743
|
+
return blob;
|
|
744
|
+
}
|
|
745
|
+
}
|
|
746
|
+
for (const mimeType of mimeTypes) {
|
|
747
|
+
const dataUrl = canvas.toDataURL(mimeType, quality);
|
|
748
|
+
if (dataUrl && dataUrl !== "data:,") {
|
|
749
|
+
return blobFromDataUrl(dataUrl);
|
|
750
|
+
}
|
|
751
|
+
}
|
|
752
|
+
throw new Error("Failed to encode canvas to blob");
|
|
753
|
+
}
|
|
754
|
+
|
|
714
755
|
// src/image/indexed-db-image-store.ts
|
|
715
756
|
var DB_NAME = "canvu-image-store";
|
|
716
757
|
var DB_VERSION = 1;
|
|
@@ -829,19 +870,7 @@ function decodeImageToCanvas(blob, maxDimension) {
|
|
|
829
870
|
});
|
|
830
871
|
}
|
|
831
872
|
function canvasToBlob(canvas, mime, quality) {
|
|
832
|
-
return
|
|
833
|
-
canvas.toBlob(
|
|
834
|
-
(blob) => {
|
|
835
|
-
if (!blob) {
|
|
836
|
-
reject(new Error("Could not encode blob"));
|
|
837
|
-
return;
|
|
838
|
-
}
|
|
839
|
-
resolve(blob);
|
|
840
|
-
},
|
|
841
|
-
mime,
|
|
842
|
-
quality
|
|
843
|
-
);
|
|
844
|
-
});
|
|
873
|
+
return encodeCanvasToBlob(canvas, { mimeType: mime, quality });
|
|
845
874
|
}
|
|
846
875
|
async function loadImageToStore(file, store) {
|
|
847
876
|
const originalBlob = file;
|
|
@@ -909,21 +938,6 @@ async function renderPageToCanvas(page, scale) {
|
|
|
909
938
|
await page.render({ canvas, viewport }).promise;
|
|
910
939
|
return { canvas, width: w, height: h };
|
|
911
940
|
}
|
|
912
|
-
function canvasToBlob2(canvas, mime, quality) {
|
|
913
|
-
return new Promise((resolve, reject) => {
|
|
914
|
-
canvas.toBlob(
|
|
915
|
-
(blob) => {
|
|
916
|
-
if (!blob) {
|
|
917
|
-
reject(new Error("Could not encode blob"));
|
|
918
|
-
return;
|
|
919
|
-
}
|
|
920
|
-
resolve(blob);
|
|
921
|
-
},
|
|
922
|
-
mime,
|
|
923
|
-
quality
|
|
924
|
-
);
|
|
925
|
-
});
|
|
926
|
-
}
|
|
927
941
|
function normalizePdfPageNumbers(pageNumbers, pageCount) {
|
|
928
942
|
if (!pageNumbers || pageNumbers.length === 0) {
|
|
929
943
|
return Array.from({ length: pageCount }, (_, index) => index + 1);
|
|
@@ -985,7 +999,7 @@ async function loadPdfToStore(file, store, options) {
|
|
|
985
999
|
const page = await pdf.getPage(pageNumber);
|
|
986
1000
|
const { canvas, width, height } = await renderPageToCanvas(page, scale);
|
|
987
1001
|
const mime = "image/png";
|
|
988
|
-
const pageBlob = await
|
|
1002
|
+
const pageBlob = await encodeCanvasToBlob(canvas, { mimeType: mime });
|
|
989
1003
|
const blobId = await store.storeOriginal(pageBlob);
|
|
990
1004
|
const thumbnailBlobId = storeThumbnails ? await (async () => {
|
|
991
1005
|
const thumbScale = Math.min(1, 256 / Math.max(width, height));
|
|
@@ -1000,7 +1014,9 @@ async function loadPdfToStore(file, store, options) {
|
|
|
1000
1014
|
tCtx.imageSmoothingQuality = "high";
|
|
1001
1015
|
tCtx.drawImage(canvas, 0, 0, tw, th);
|
|
1002
1016
|
}
|
|
1003
|
-
const thumbBlob = await
|
|
1017
|
+
const thumbBlob = await encodeCanvasToBlob(thumbCanvas, {
|
|
1018
|
+
mimeType: mime
|
|
1019
|
+
});
|
|
1004
1020
|
return await store.storeThumbnail(thumbBlob);
|
|
1005
1021
|
})() : "";
|
|
1006
1022
|
const pageResult = {
|
|
@@ -7398,6 +7414,40 @@ var VectorViewport = forwardRef(
|
|
|
7398
7414
|
onWorldPointerLeaveRef.current = onWorldPointerLeave;
|
|
7399
7415
|
const onPlacementPreviewChangeRef = useRef(onPlacementPreviewChange);
|
|
7400
7416
|
onPlacementPreviewChangeRef.current = onPlacementPreviewChange;
|
|
7417
|
+
const directRemoteStrokePreviewRef = useRef(false);
|
|
7418
|
+
const remoteStrokePreviewFrameRef = useRef(null);
|
|
7419
|
+
const pendingRemoteStrokePreviewRef = useRef(null);
|
|
7420
|
+
const flushRemoteStrokePreview = useCallback(() => {
|
|
7421
|
+
remoteStrokePreviewFrameRef.current = null;
|
|
7422
|
+
const pending = pendingRemoteStrokePreviewRef.current;
|
|
7423
|
+
if (!pending) return;
|
|
7424
|
+
onPlacementPreviewChangeRef.current?.({
|
|
7425
|
+
kind: "stroke",
|
|
7426
|
+
tool: pending.tool,
|
|
7427
|
+
points: pending.points
|
|
7428
|
+
});
|
|
7429
|
+
}, []);
|
|
7430
|
+
const emitRemoteStrokePreview = useCallback(
|
|
7431
|
+
(tool, points) => {
|
|
7432
|
+
if (tool === "laser") return;
|
|
7433
|
+
directRemoteStrokePreviewRef.current = true;
|
|
7434
|
+
pendingRemoteStrokePreviewRef.current = { tool, points };
|
|
7435
|
+
if (remoteStrokePreviewFrameRef.current != null) return;
|
|
7436
|
+
remoteStrokePreviewFrameRef.current = requestAnimationFrame(
|
|
7437
|
+
flushRemoteStrokePreview
|
|
7438
|
+
);
|
|
7439
|
+
},
|
|
7440
|
+
[flushRemoteStrokePreview]
|
|
7441
|
+
);
|
|
7442
|
+
const emitRemoteStrokePreviewClear = useCallback(() => {
|
|
7443
|
+
if (remoteStrokePreviewFrameRef.current != null) {
|
|
7444
|
+
cancelAnimationFrame(remoteStrokePreviewFrameRef.current);
|
|
7445
|
+
remoteStrokePreviewFrameRef.current = null;
|
|
7446
|
+
}
|
|
7447
|
+
pendingRemoteStrokePreviewRef.current = null;
|
|
7448
|
+
directRemoteStrokePreviewRef.current = false;
|
|
7449
|
+
onPlacementPreviewChangeRef.current?.(null);
|
|
7450
|
+
}, []);
|
|
7401
7451
|
const overlayCameraTickRef = useRef(false);
|
|
7402
7452
|
overlayCameraTickRef.current = interactive || remotePresence != null && remotePresence.length > 0 || presenceOverlay != null;
|
|
7403
7453
|
const pruneEraserTrail = useCallback(
|
|
@@ -7516,6 +7566,7 @@ var VectorViewport = forwardRef(
|
|
|
7516
7566
|
if (itemId) {
|
|
7517
7567
|
renderSceneWithLivePenStroke(null);
|
|
7518
7568
|
}
|
|
7569
|
+
emitRemoteStrokePreviewClear();
|
|
7519
7570
|
setPlacementPreview(null);
|
|
7520
7571
|
commitCompletedStroke({
|
|
7521
7572
|
tool,
|
|
@@ -7527,6 +7578,7 @@ var VectorViewport = forwardRef(
|
|
|
7527
7578
|
},
|
|
7528
7579
|
[
|
|
7529
7580
|
commitCompletedStroke,
|
|
7581
|
+
emitRemoteStrokePreviewClear,
|
|
7530
7582
|
releaseInteractionPointer,
|
|
7531
7583
|
renderSceneWithLivePenStroke
|
|
7532
7584
|
]
|
|
@@ -7638,8 +7690,18 @@ var VectorViewport = forwardRef(
|
|
|
7638
7690
|
};
|
|
7639
7691
|
}, [onWorldPointerMove]);
|
|
7640
7692
|
useEffect(() => {
|
|
7693
|
+
if (directRemoteStrokePreviewRef.current && placementPreview === null) {
|
|
7694
|
+
return;
|
|
7695
|
+
}
|
|
7641
7696
|
onPlacementPreviewChangeRef.current?.(placementPreview);
|
|
7642
7697
|
}, [placementPreview]);
|
|
7698
|
+
useEffect(() => {
|
|
7699
|
+
return () => {
|
|
7700
|
+
if (remoteStrokePreviewFrameRef.current != null) {
|
|
7701
|
+
cancelAnimationFrame(remoteStrokePreviewFrameRef.current);
|
|
7702
|
+
}
|
|
7703
|
+
};
|
|
7704
|
+
}, []);
|
|
7643
7705
|
useEffect(() => {
|
|
7644
7706
|
const scene = sceneRef.current;
|
|
7645
7707
|
if (scene) {
|
|
@@ -8633,6 +8695,7 @@ var VectorViewport = forwardRef(
|
|
|
8633
8695
|
setPlacementPreview(null);
|
|
8634
8696
|
} else if (directPenStroke) {
|
|
8635
8697
|
setPlacementPreview(null);
|
|
8698
|
+
emitRemoteStrokePreview(tool, [startPoint]);
|
|
8636
8699
|
} else {
|
|
8637
8700
|
setPlacementPreview({
|
|
8638
8701
|
kind: "stroke",
|
|
@@ -8674,6 +8737,7 @@ var VectorViewport = forwardRef(
|
|
|
8674
8737
|
[
|
|
8675
8738
|
applePencilNav,
|
|
8676
8739
|
captureInteractionPointer,
|
|
8740
|
+
emitRemoteStrokePreview,
|
|
8677
8741
|
finalizeStrokeDragState,
|
|
8678
8742
|
renderSceneWithLivePenStroke,
|
|
8679
8743
|
screenToWorld
|
|
@@ -8732,6 +8796,7 @@ var VectorViewport = forwardRef(
|
|
|
8732
8796
|
activeInteractionPointerIdRef.current = e.pointerId;
|
|
8733
8797
|
activeInteractionPointerTargetRef.current = null;
|
|
8734
8798
|
setPlacementPreview(null);
|
|
8799
|
+
emitRemoteStrokePreview(tool, [startPoint]);
|
|
8735
8800
|
debugApplePencilPointer("native-pointerdown", {
|
|
8736
8801
|
pointerType: e.pointerType,
|
|
8737
8802
|
pointerId: e.pointerId,
|
|
@@ -8749,6 +8814,7 @@ var VectorViewport = forwardRef(
|
|
|
8749
8814
|
};
|
|
8750
8815
|
}, [
|
|
8751
8816
|
applePencilNav,
|
|
8817
|
+
emitRemoteStrokePreview,
|
|
8752
8818
|
finalizeStrokeDragState,
|
|
8753
8819
|
interactive,
|
|
8754
8820
|
renderSceneWithLivePenStroke,
|
|
@@ -8832,6 +8898,7 @@ var VectorViewport = forwardRef(
|
|
|
8832
8898
|
activeInteractionPointerTargetRef.current = null;
|
|
8833
8899
|
activeInteractionTouchIdRef.current = touch.identifier;
|
|
8834
8900
|
setPlacementPreview(null);
|
|
8901
|
+
emitRemoteStrokePreview(tool, [startPoint]);
|
|
8835
8902
|
debugApplePencilPointer("touchstart-stroke", {
|
|
8836
8903
|
touchId: touch.identifier,
|
|
8837
8904
|
touchType: touchKind(touch),
|
|
@@ -8863,6 +8930,7 @@ var VectorViewport = forwardRef(
|
|
|
8863
8930
|
renderSceneWithLivePenStroke(item);
|
|
8864
8931
|
}
|
|
8865
8932
|
setPlacementPreview(null);
|
|
8933
|
+
emitRemoteStrokePreview(st.tool, interpolated);
|
|
8866
8934
|
}
|
|
8867
8935
|
debugApplePencilPointer("touchmove-stroke", {
|
|
8868
8936
|
touchId: touch.identifier,
|
|
@@ -8925,6 +8993,7 @@ var VectorViewport = forwardRef(
|
|
|
8925
8993
|
};
|
|
8926
8994
|
}, [
|
|
8927
8995
|
applePencilNav,
|
|
8996
|
+
emitRemoteStrokePreview,
|
|
8928
8997
|
finalizeStrokeDragState,
|
|
8929
8998
|
interactive,
|
|
8930
8999
|
renderSceneWithLivePenStroke,
|
|
@@ -8979,6 +9048,7 @@ var VectorViewport = forwardRef(
|
|
|
8979
9048
|
renderSceneWithLivePenStroke(item);
|
|
8980
9049
|
}
|
|
8981
9050
|
setPlacementPreview(null);
|
|
9051
|
+
emitRemoteStrokePreview(st.tool, interpolated);
|
|
8982
9052
|
return;
|
|
8983
9053
|
}
|
|
8984
9054
|
if (st.tool === "laser") {
|
|
@@ -9120,6 +9190,9 @@ var VectorViewport = forwardRef(
|
|
|
9120
9190
|
}
|
|
9121
9191
|
const cam = cameraRef.current;
|
|
9122
9192
|
if (!cam) {
|
|
9193
|
+
if (st.kind === "stroke") {
|
|
9194
|
+
emitRemoteStrokePreviewClear();
|
|
9195
|
+
}
|
|
9123
9196
|
if (st.kind === "erase") {
|
|
9124
9197
|
eraserPreviewIdsRef.current.clear();
|
|
9125
9198
|
setEraserPreviewIds([]);
|
|
@@ -9351,6 +9424,8 @@ var VectorViewport = forwardRef(
|
|
|
9351
9424
|
document.removeEventListener("pointercancel", onUp);
|
|
9352
9425
|
};
|
|
9353
9426
|
}, [
|
|
9427
|
+
emitRemoteStrokePreview,
|
|
9428
|
+
emitRemoteStrokePreviewClear,
|
|
9354
9429
|
interactive,
|
|
9355
9430
|
pruneEraserTrail,
|
|
9356
9431
|
pruneLaserTrail,
|