canvu-react 0.3.10 → 0.3.12
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/asset-hydration-3Iv5xHxM.d.cts +27 -0
- package/dist/asset-hydration-BEG21hMp.d.ts +27 -0
- package/dist/chatbot.d.cts +2 -2
- package/dist/chatbot.d.ts +2 -2
- package/dist/index.cjs +469 -8
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +2 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.js +468 -9
- package/dist/index.js.map +1 -1
- package/dist/native.cjs +645 -704
- package/dist/native.cjs.map +1 -1
- package/dist/native.js +645 -704
- package/dist/native.js.map +1 -1
- package/dist/react.cjs +354 -137
- package/dist/react.cjs.map +1 -1
- package/dist/react.d.cts +9 -16
- package/dist/react.d.ts +9 -16
- package/dist/react.js +354 -138
- package/dist/react.js.map +1 -1
- package/dist/realtime.cjs +566 -55
- package/dist/realtime.cjs.map +1 -1
- package/dist/realtime.d.cts +40 -5
- package/dist/realtime.d.ts +40 -5
- package/dist/realtime.js +566 -56
- package/dist/realtime.js.map +1 -1
- package/dist/{shape-builders-DxPoOecg.d.cts → shape-builders-DFudWDFI.d.cts} +111 -1
- package/dist/{shape-builders-DTYvub8W.d.ts → shape-builders-ENwnK-zT.d.ts} +111 -1
- package/dist/{types-DgEArHkA.d.ts → types-BtAJFS_-.d.ts} +1 -0
- package/dist/{types-BtLGGw0r.d.cts → types-CTyASYIm.d.cts} +2 -105
- package/dist/{types-B58i5k-u.d.cts → types-DNwjgs5U.d.cts} +1 -0
- package/dist/{types-ChnTSRSe.d.ts → types-UvUy2Eed.d.ts} +2 -105
- package/package.json +1 -1
package/dist/react.d.cts
CHANGED
|
@@ -1,24 +1,16 @@
|
|
|
1
|
+
import { I as IndexedDbImageStore } from './asset-hydration-3Iv5xHxM.cjs';
|
|
2
|
+
export { H as HydratedSceneItemsWithAssetsResult, h as hydrateSceneItemsWithAssets } from './asset-hydration-3Iv5xHxM.cjs';
|
|
1
3
|
import { V as VectorSceneItem } from './types-CB0TZZuk.cjs';
|
|
2
|
-
import { V as VectorViewportAssetKind,
|
|
3
|
-
export {
|
|
4
|
-
import { V as
|
|
5
|
-
export { b as
|
|
4
|
+
import { V as VectorViewportAssetKind, u as VectorViewportAssetStore } from './shape-builders-DFudWDFI.cjs';
|
|
5
|
+
export { v as VectorViewportAssetHydrationRequest, w as VectorViewportAssetResolveRequest, x as VectorViewportAssetResolveResult, y as VectorViewportAssetUploadRequest, z as VectorViewportAssetUploadResult } from './shape-builders-DFudWDFI.cjs';
|
|
6
|
+
import { V as VectorToolDefinition, C as CanvasPlugin, B as BoardComponentPosition } from './types-CTyASYIm.cjs';
|
|
7
|
+
export { a as CanvasPluginComponentProps, b as CanvasPluginContribution, c as CanvasPluginItemsChangeMiddlewareContext, d as CanvasPluginRenderContext, e as CanvuChromeActiveToolStyle, f as CanvuChromeContext, g as CanvuChromeContextValue, h as CanvuChromeSelectionStyleChange, i as CanvuPluginContext, j as CanvuPluginContextValue, k as CanvuPluginViewportSnapshot, l as CustomShapePlacementOptions, N as NavMenu, m as NavMenuProps, P as PlacementPreview, n as VectorCanvas, o as VectorCanvasBody, p as VectorCanvasHeader, q as VectorCanvasMain, r as VectorCanvasRoot, s as VectorCanvasSlotProps, t as VectorCanvasSpacePosition, u as VectorCanvasSpaceProps, v as VectorCanvasToolbar, w as VectorCanvasToolbarProps, x as VectorCanvasViewportSurface, y as VectorSelectionInspector, z as VectorSelectionInspectorProps, A as VectorViewport, D as VectorViewportHandle, E as VectorViewportProps, W as WorldPointerDownDetail, F as createCanvuPlugin, G as getBoardPositionStyle, H as useCanvuChromeContext, I as useCanvuDocumentContext, J as useCanvuPluginContext, K as useCanvuPluginContribution, L as useCanvuResolvedTools, M as useCanvuViewportContext } from './types-CTyASYIm.cjs';
|
|
8
|
+
import { V as VectorCanvasPersistenceAdapter, a as VectorCanvasRemoteAdapter } from './types-DNwjgs5U.cjs';
|
|
9
|
+
export { b as VectorCanvasSnapshot } from './types-DNwjgs5U.cjs';
|
|
6
10
|
import * as react from 'react';
|
|
7
11
|
import { SVGProps, CSSProperties, ReactNode } from 'react';
|
|
8
12
|
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
9
13
|
import './camera-BwQjm5oh.cjs';
|
|
10
|
-
import './shape-builders-DxPoOecg.cjs';
|
|
11
|
-
|
|
12
|
-
declare class IndexedDbImageStore {
|
|
13
|
-
private dbPromise;
|
|
14
|
-
private getDb;
|
|
15
|
-
storeOriginal(blob: Blob): Promise<string>;
|
|
16
|
-
getOriginal(id: string): Promise<Blob | undefined>;
|
|
17
|
-
deleteOriginal(id: string): Promise<void>;
|
|
18
|
-
storeThumbnail(blob: Blob): Promise<string>;
|
|
19
|
-
getThumbnail(id: string): Promise<Blob | undefined>;
|
|
20
|
-
deleteThumbnail(id: string): Promise<void>;
|
|
21
|
-
}
|
|
22
14
|
|
|
23
15
|
/**
|
|
24
16
|
* Extra context for each item created by {@link ingestAssetFilesToSceneItems}.
|
|
@@ -118,6 +110,7 @@ type IngestAssetFilesToSceneItemsOptions = {
|
|
|
118
110
|
* Defaults to `1.5` for crisp zoom while keeping payloads reasonable.
|
|
119
111
|
*/
|
|
120
112
|
pdfScale?: number;
|
|
113
|
+
pdfPageConcurrency?: number;
|
|
121
114
|
/**
|
|
122
115
|
* Final hook to customize each created item after canvu attaches its own
|
|
123
116
|
* image metadata and any `assetStore.upload(...)` `pluginData`.
|
package/dist/react.d.ts
CHANGED
|
@@ -1,24 +1,16 @@
|
|
|
1
|
+
import { I as IndexedDbImageStore } from './asset-hydration-BEG21hMp.js';
|
|
2
|
+
export { H as HydratedSceneItemsWithAssetsResult, h as hydrateSceneItemsWithAssets } from './asset-hydration-BEG21hMp.js';
|
|
1
3
|
import { V as VectorSceneItem } from './types-CB0TZZuk.js';
|
|
2
|
-
import { V as VectorViewportAssetKind,
|
|
3
|
-
export {
|
|
4
|
-
import { V as
|
|
5
|
-
export { b as
|
|
4
|
+
import { V as VectorViewportAssetKind, u as VectorViewportAssetStore } from './shape-builders-ENwnK-zT.js';
|
|
5
|
+
export { v as VectorViewportAssetHydrationRequest, w as VectorViewportAssetResolveRequest, x as VectorViewportAssetResolveResult, y as VectorViewportAssetUploadRequest, z as VectorViewportAssetUploadResult } from './shape-builders-ENwnK-zT.js';
|
|
6
|
+
import { V as VectorToolDefinition, C as CanvasPlugin, B as BoardComponentPosition } from './types-UvUy2Eed.js';
|
|
7
|
+
export { a as CanvasPluginComponentProps, b as CanvasPluginContribution, c as CanvasPluginItemsChangeMiddlewareContext, d as CanvasPluginRenderContext, e as CanvuChromeActiveToolStyle, f as CanvuChromeContext, g as CanvuChromeContextValue, h as CanvuChromeSelectionStyleChange, i as CanvuPluginContext, j as CanvuPluginContextValue, k as CanvuPluginViewportSnapshot, l as CustomShapePlacementOptions, N as NavMenu, m as NavMenuProps, P as PlacementPreview, n as VectorCanvas, o as VectorCanvasBody, p as VectorCanvasHeader, q as VectorCanvasMain, r as VectorCanvasRoot, s as VectorCanvasSlotProps, t as VectorCanvasSpacePosition, u as VectorCanvasSpaceProps, v as VectorCanvasToolbar, w as VectorCanvasToolbarProps, x as VectorCanvasViewportSurface, y as VectorSelectionInspector, z as VectorSelectionInspectorProps, A as VectorViewport, D as VectorViewportHandle, E as VectorViewportProps, W as WorldPointerDownDetail, F as createCanvuPlugin, G as getBoardPositionStyle, H as useCanvuChromeContext, I as useCanvuDocumentContext, J as useCanvuPluginContext, K as useCanvuPluginContribution, L as useCanvuResolvedTools, M as useCanvuViewportContext } from './types-UvUy2Eed.js';
|
|
8
|
+
import { V as VectorCanvasPersistenceAdapter, a as VectorCanvasRemoteAdapter } from './types-BtAJFS_-.js';
|
|
9
|
+
export { b as VectorCanvasSnapshot } from './types-BtAJFS_-.js';
|
|
6
10
|
import * as react from 'react';
|
|
7
11
|
import { SVGProps, CSSProperties, ReactNode } from 'react';
|
|
8
12
|
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
9
13
|
import './camera-KwCYYPhm.js';
|
|
10
|
-
import './shape-builders-DTYvub8W.js';
|
|
11
|
-
|
|
12
|
-
declare class IndexedDbImageStore {
|
|
13
|
-
private dbPromise;
|
|
14
|
-
private getDb;
|
|
15
|
-
storeOriginal(blob: Blob): Promise<string>;
|
|
16
|
-
getOriginal(id: string): Promise<Blob | undefined>;
|
|
17
|
-
deleteOriginal(id: string): Promise<void>;
|
|
18
|
-
storeThumbnail(blob: Blob): Promise<string>;
|
|
19
|
-
getThumbnail(id: string): Promise<Blob | undefined>;
|
|
20
|
-
deleteThumbnail(id: string): Promise<void>;
|
|
21
|
-
}
|
|
22
14
|
|
|
23
15
|
/**
|
|
24
16
|
* Extra context for each item created by {@link ingestAssetFilesToSceneItems}.
|
|
@@ -118,6 +110,7 @@ type IngestAssetFilesToSceneItemsOptions = {
|
|
|
118
110
|
* Defaults to `1.5` for crisp zoom while keeping payloads reasonable.
|
|
119
111
|
*/
|
|
120
112
|
pdfScale?: number;
|
|
113
|
+
pdfPageConcurrency?: number;
|
|
121
114
|
/**
|
|
122
115
|
* Final hook to customize each created item after canvu attaches its own
|
|
123
116
|
* image metadata and any `assetStore.upload(...)` `pluginData`.
|
package/dist/react.js
CHANGED
|
@@ -921,35 +921,336 @@ function canvasToBlob2(canvas, mime, quality) {
|
|
|
921
921
|
);
|
|
922
922
|
});
|
|
923
923
|
}
|
|
924
|
+
function normalizePdfPageNumbers(pageNumbers, pageCount) {
|
|
925
|
+
if (!pageNumbers || pageNumbers.length === 0) {
|
|
926
|
+
return Array.from({ length: pageCount }, (_, index) => index + 1);
|
|
927
|
+
}
|
|
928
|
+
return [...new Set(pageNumbers)].filter((pageNumber) => pageNumber >= 1 && pageNumber <= pageCount).sort((left, right) => left - right);
|
|
929
|
+
}
|
|
930
|
+
async function runWithConcurrency(items, concurrency, execute) {
|
|
931
|
+
const results = new Array(items.length);
|
|
932
|
+
let nextIndex = 0;
|
|
933
|
+
const workerCount = Math.max(1, Math.min(concurrency, items.length));
|
|
934
|
+
await Promise.all(
|
|
935
|
+
Array.from({ length: workerCount }, async () => {
|
|
936
|
+
while (nextIndex < items.length) {
|
|
937
|
+
const currentIndex = nextIndex;
|
|
938
|
+
nextIndex += 1;
|
|
939
|
+
const item = items[currentIndex];
|
|
940
|
+
if (item === void 0) {
|
|
941
|
+
continue;
|
|
942
|
+
}
|
|
943
|
+
results[currentIndex] = await execute(item);
|
|
944
|
+
}
|
|
945
|
+
})
|
|
946
|
+
);
|
|
947
|
+
return results;
|
|
948
|
+
}
|
|
924
949
|
async function loadPdfToStore(file, store, options) {
|
|
925
950
|
const scale = options?.scale ?? 1.5;
|
|
951
|
+
const pageConcurrency = options?.pageConcurrency ?? 2;
|
|
926
952
|
const pdfjs = await getPdfJs();
|
|
927
953
|
const arrayBuffer = await file.arrayBuffer();
|
|
928
954
|
const pdf = await pdfjs.getDocument({ data: arrayBuffer }).promise;
|
|
929
|
-
const
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
tCtx
|
|
946
|
-
tCtx
|
|
955
|
+
const pageNumbers = normalizePdfPageNumbers(options?.pageNumbers, pdf.numPages);
|
|
956
|
+
return await runWithConcurrency(
|
|
957
|
+
pageNumbers,
|
|
958
|
+
pageConcurrency,
|
|
959
|
+
async (pageNumber) => {
|
|
960
|
+
const page = await pdf.getPage(pageNumber);
|
|
961
|
+
const { canvas, width, height } = await renderPageToCanvas(page, scale);
|
|
962
|
+
const mime = "image/png";
|
|
963
|
+
const pageBlob = await canvasToBlob2(canvas, mime);
|
|
964
|
+
const blobId = await store.storeOriginal(pageBlob);
|
|
965
|
+
const thumbScale = Math.min(1, 256 / Math.max(width, height));
|
|
966
|
+
const tw = Math.max(1, Math.round(width * thumbScale));
|
|
967
|
+
const th = Math.max(1, Math.round(height * thumbScale));
|
|
968
|
+
const thumbCanvas = document.createElement("canvas");
|
|
969
|
+
thumbCanvas.width = tw;
|
|
970
|
+
thumbCanvas.height = th;
|
|
971
|
+
const tCtx = thumbCanvas.getContext("2d");
|
|
972
|
+
if (tCtx) {
|
|
973
|
+
tCtx.imageSmoothingEnabled = true;
|
|
974
|
+
tCtx.imageSmoothingQuality = "high";
|
|
975
|
+
tCtx.drawImage(canvas, 0, 0, tw, th);
|
|
976
|
+
}
|
|
977
|
+
const thumbBlob = await canvasToBlob2(thumbCanvas, mime);
|
|
978
|
+
const thumbnailBlobId = await store.storeThumbnail(thumbBlob);
|
|
979
|
+
return {
|
|
980
|
+
blobId,
|
|
981
|
+
thumbnailBlobId,
|
|
982
|
+
width,
|
|
983
|
+
height,
|
|
984
|
+
pageNumber
|
|
985
|
+
};
|
|
947
986
|
}
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
987
|
+
);
|
|
988
|
+
}
|
|
989
|
+
|
|
990
|
+
// src/react/asset-hydration.ts
|
|
991
|
+
init_shape_builders();
|
|
992
|
+
var HYDRATION_CACHE_NAME = "canvu-asset-hydration-v1";
|
|
993
|
+
var DEFAULT_PDF_SCALE = 1.15;
|
|
994
|
+
var DEFAULT_PDF_PAGE_CONCURRENCY = 2;
|
|
995
|
+
var hydrationBlobPromises = /* @__PURE__ */ new Map();
|
|
996
|
+
function buildImageHydrationKey(assetId) {
|
|
997
|
+
return `image:${assetId}`;
|
|
998
|
+
}
|
|
999
|
+
function buildPdfHydrationKey(assetId, pageNumber, scale) {
|
|
1000
|
+
return `pdf:${assetId}:page:${pageNumber}:scale:${scale}`;
|
|
1001
|
+
}
|
|
1002
|
+
function getCacheRequest(key) {
|
|
1003
|
+
return new Request(
|
|
1004
|
+
`https://canvu.local/asset-hydration/${encodeURIComponent(key)}`
|
|
1005
|
+
);
|
|
1006
|
+
}
|
|
1007
|
+
async function openHydrationCache() {
|
|
1008
|
+
if (typeof caches === "undefined") return null;
|
|
1009
|
+
try {
|
|
1010
|
+
return await caches.open(HYDRATION_CACHE_NAME);
|
|
1011
|
+
} catch {
|
|
1012
|
+
return null;
|
|
951
1013
|
}
|
|
952
|
-
|
|
1014
|
+
}
|
|
1015
|
+
async function readCachedHydrationBlob(key) {
|
|
1016
|
+
const cache = await openHydrationCache();
|
|
1017
|
+
if (!cache) return null;
|
|
1018
|
+
try {
|
|
1019
|
+
const response = await cache.match(getCacheRequest(key));
|
|
1020
|
+
if (!response?.ok) return null;
|
|
1021
|
+
return await response.blob();
|
|
1022
|
+
} catch {
|
|
1023
|
+
return null;
|
|
1024
|
+
}
|
|
1025
|
+
}
|
|
1026
|
+
async function writeCachedHydrationBlob(key, blob) {
|
|
1027
|
+
const cache = await openHydrationCache();
|
|
1028
|
+
if (!cache) return;
|
|
1029
|
+
try {
|
|
1030
|
+
await cache.put(getCacheRequest(key), new Response(blob));
|
|
1031
|
+
} catch {
|
|
1032
|
+
}
|
|
1033
|
+
}
|
|
1034
|
+
async function fetchBlob(url) {
|
|
1035
|
+
try {
|
|
1036
|
+
const response = await fetch(url);
|
|
1037
|
+
if (!response.ok) return null;
|
|
1038
|
+
return await response.blob();
|
|
1039
|
+
} catch {
|
|
1040
|
+
return null;
|
|
1041
|
+
}
|
|
1042
|
+
}
|
|
1043
|
+
async function getHydrationBlob(key, preferCachedRasters, loader) {
|
|
1044
|
+
const cached = preferCachedRasters ? await readCachedHydrationBlob(key) : null;
|
|
1045
|
+
if (cached) return cached;
|
|
1046
|
+
const inFlight = hydrationBlobPromises.get(key);
|
|
1047
|
+
if (inFlight) return await inFlight;
|
|
1048
|
+
const nextPromise = (async () => {
|
|
1049
|
+
const blob = await loader();
|
|
1050
|
+
if (blob) {
|
|
1051
|
+
await writeCachedHydrationBlob(key, blob);
|
|
1052
|
+
}
|
|
1053
|
+
return blob;
|
|
1054
|
+
})();
|
|
1055
|
+
hydrationBlobPromises.set(key, nextPromise);
|
|
1056
|
+
try {
|
|
1057
|
+
return await nextPromise;
|
|
1058
|
+
} finally {
|
|
1059
|
+
hydrationBlobPromises.delete(key);
|
|
1060
|
+
}
|
|
1061
|
+
}
|
|
1062
|
+
function registerObjectUrl(objectUrls, blob) {
|
|
1063
|
+
const href = URL.createObjectURL(blob);
|
|
1064
|
+
objectUrls.push(href);
|
|
1065
|
+
return href;
|
|
1066
|
+
}
|
|
1067
|
+
function getHydrationRequests(items, assetStore, pdfScale) {
|
|
1068
|
+
if (!assetStore.getHydrationRequest) return [];
|
|
1069
|
+
return items.flatMap((item) => {
|
|
1070
|
+
const request = assetStore.getHydrationRequest?.(item);
|
|
1071
|
+
if (!request) return [];
|
|
1072
|
+
return [
|
|
1073
|
+
{
|
|
1074
|
+
request: {
|
|
1075
|
+
...request,
|
|
1076
|
+
scale: request.scale ?? pdfScale
|
|
1077
|
+
}
|
|
1078
|
+
}
|
|
1079
|
+
];
|
|
1080
|
+
});
|
|
1081
|
+
}
|
|
1082
|
+
function createPdfHydrationGroups(requests) {
|
|
1083
|
+
const groups = /* @__PURE__ */ new Map();
|
|
1084
|
+
for (const entry of requests) {
|
|
1085
|
+
if (entry.request.kind !== "pdf" || entry.request.pageNumber == null) continue;
|
|
1086
|
+
const scale = entry.request.scale ?? DEFAULT_PDF_SCALE;
|
|
1087
|
+
const key = `${entry.request.assetId}:${scale}`;
|
|
1088
|
+
const existingGroup = groups.get(key);
|
|
1089
|
+
if (existingGroup) {
|
|
1090
|
+
if (!existingGroup.pageNumbers.includes(entry.request.pageNumber)) {
|
|
1091
|
+
existingGroup.pageNumbers.push(entry.request.pageNumber);
|
|
1092
|
+
}
|
|
1093
|
+
continue;
|
|
1094
|
+
}
|
|
1095
|
+
groups.set(key, {
|
|
1096
|
+
assetId: entry.request.assetId,
|
|
1097
|
+
scale,
|
|
1098
|
+
pageNumbers: [entry.request.pageNumber]
|
|
1099
|
+
});
|
|
1100
|
+
}
|
|
1101
|
+
return [...groups.values()];
|
|
1102
|
+
}
|
|
1103
|
+
async function hydrateImageAssets(requests, resolvedAssetUrls, objectUrls, preferCachedRasters) {
|
|
1104
|
+
const uniqueAssetIds = [
|
|
1105
|
+
...new Set(requests.map((entry) => entry.request.assetId))
|
|
1106
|
+
];
|
|
1107
|
+
const hydratedEntries = await Promise.all(
|
|
1108
|
+
uniqueAssetIds.map(async (assetId) => {
|
|
1109
|
+
const resolvedAsset = resolvedAssetUrls[assetId];
|
|
1110
|
+
if (!resolvedAsset?.url) {
|
|
1111
|
+
return [assetId, null];
|
|
1112
|
+
}
|
|
1113
|
+
const blob = await getHydrationBlob(
|
|
1114
|
+
buildImageHydrationKey(assetId),
|
|
1115
|
+
preferCachedRasters,
|
|
1116
|
+
async () => await fetchBlob(resolvedAsset.url)
|
|
1117
|
+
);
|
|
1118
|
+
if (!blob) {
|
|
1119
|
+
return [assetId, null];
|
|
1120
|
+
}
|
|
1121
|
+
return [
|
|
1122
|
+
assetId,
|
|
1123
|
+
{
|
|
1124
|
+
href: registerObjectUrl(objectUrls, blob)
|
|
1125
|
+
}
|
|
1126
|
+
];
|
|
1127
|
+
})
|
|
1128
|
+
);
|
|
1129
|
+
return new Map(hydratedEntries);
|
|
1130
|
+
}
|
|
1131
|
+
async function hydratePdfAssets(requests, resolvedAssetUrls, objectUrls, options) {
|
|
1132
|
+
const hydratedPages = /* @__PURE__ */ new Map();
|
|
1133
|
+
const groups = createPdfHydrationGroups(requests);
|
|
1134
|
+
for (const group of groups) {
|
|
1135
|
+
const resolvedAsset = resolvedAssetUrls[group.assetId];
|
|
1136
|
+
if (!resolvedAsset?.url) {
|
|
1137
|
+
continue;
|
|
1138
|
+
}
|
|
1139
|
+
const missingPages = [];
|
|
1140
|
+
for (const pageNumber of group.pageNumbers) {
|
|
1141
|
+
const cacheKey = buildPdfHydrationKey(group.assetId, pageNumber, group.scale);
|
|
1142
|
+
const cachedBlob = await readCachedHydrationBlob(cacheKey);
|
|
1143
|
+
if (!cachedBlob) {
|
|
1144
|
+
missingPages.push(pageNumber);
|
|
1145
|
+
continue;
|
|
1146
|
+
}
|
|
1147
|
+
hydratedPages.set(cacheKey, {
|
|
1148
|
+
href: registerObjectUrl(objectUrls, cachedBlob)
|
|
1149
|
+
});
|
|
1150
|
+
}
|
|
1151
|
+
if (missingPages.length === 0) {
|
|
1152
|
+
continue;
|
|
1153
|
+
}
|
|
1154
|
+
const pdfBlob = await fetchBlob(resolvedAsset.url);
|
|
1155
|
+
if (!pdfBlob) {
|
|
1156
|
+
continue;
|
|
1157
|
+
}
|
|
1158
|
+
const renderedPages = await loadPdfToStore(pdfBlob, options.imageStore, {
|
|
1159
|
+
scale: group.scale,
|
|
1160
|
+
pageNumbers: missingPages,
|
|
1161
|
+
pageConcurrency: options.pdfPageConcurrency
|
|
1162
|
+
});
|
|
1163
|
+
for (const renderedPage of renderedPages) {
|
|
1164
|
+
const cacheKey = buildPdfHydrationKey(
|
|
1165
|
+
group.assetId,
|
|
1166
|
+
renderedPage.pageNumber,
|
|
1167
|
+
group.scale
|
|
1168
|
+
);
|
|
1169
|
+
const pageBlob = await options.imageStore.getOriginal(renderedPage.blobId);
|
|
1170
|
+
if (!pageBlob) {
|
|
1171
|
+
continue;
|
|
1172
|
+
}
|
|
1173
|
+
await writeCachedHydrationBlob(cacheKey, pageBlob);
|
|
1174
|
+
hydratedPages.set(cacheKey, {
|
|
1175
|
+
href: registerObjectUrl(objectUrls, pageBlob),
|
|
1176
|
+
width: renderedPage.width,
|
|
1177
|
+
height: renderedPage.height
|
|
1178
|
+
});
|
|
1179
|
+
}
|
|
1180
|
+
}
|
|
1181
|
+
return hydratedPages;
|
|
1182
|
+
}
|
|
1183
|
+
async function hydrateSceneItemsWithAssets(items, assetStore, options = {}) {
|
|
1184
|
+
if (!assetStore.resolve || !assetStore.getHydrationRequest) {
|
|
1185
|
+
return {
|
|
1186
|
+
items: [...items],
|
|
1187
|
+
objectUrls: []
|
|
1188
|
+
};
|
|
1189
|
+
}
|
|
1190
|
+
const pdfScale = options.pdfScale ?? DEFAULT_PDF_SCALE;
|
|
1191
|
+
const pdfPageConcurrency = options.pdfPageConcurrency ?? DEFAULT_PDF_PAGE_CONCURRENCY;
|
|
1192
|
+
const preferCachedRasters = options.preferCachedRasters ?? true;
|
|
1193
|
+
const imageStore = options.imageStore ?? new IndexedDbImageStore();
|
|
1194
|
+
const hydrationRequests = getHydrationRequests(items, assetStore, pdfScale);
|
|
1195
|
+
if (hydrationRequests.length === 0) {
|
|
1196
|
+
return {
|
|
1197
|
+
items: [...items],
|
|
1198
|
+
objectUrls: []
|
|
1199
|
+
};
|
|
1200
|
+
}
|
|
1201
|
+
const assetIds = [
|
|
1202
|
+
...new Set(hydrationRequests.map((entry) => entry.request.assetId))
|
|
1203
|
+
];
|
|
1204
|
+
const resolvedAssetUrls = await assetStore.resolve({ assetIds });
|
|
1205
|
+
const objectUrls = [];
|
|
1206
|
+
const hydratedImages = await hydrateImageAssets(
|
|
1207
|
+
hydrationRequests.filter((entry) => entry.request.kind === "image"),
|
|
1208
|
+
resolvedAssetUrls,
|
|
1209
|
+
objectUrls,
|
|
1210
|
+
preferCachedRasters
|
|
1211
|
+
);
|
|
1212
|
+
const hydratedPdfPages = await hydratePdfAssets(
|
|
1213
|
+
hydrationRequests.filter((entry) => entry.request.kind === "pdf"),
|
|
1214
|
+
resolvedAssetUrls,
|
|
1215
|
+
objectUrls,
|
|
1216
|
+
{
|
|
1217
|
+
imageStore,
|
|
1218
|
+
pdfPageConcurrency}
|
|
1219
|
+
);
|
|
1220
|
+
return {
|
|
1221
|
+
items: items.map((item) => {
|
|
1222
|
+
const request = assetStore.getHydrationRequest?.(item);
|
|
1223
|
+
if (!request || item.toolKind !== "image") return item;
|
|
1224
|
+
if (request.kind === "image") {
|
|
1225
|
+
const hydratedImage = hydratedImages.get(request.assetId);
|
|
1226
|
+
if (!hydratedImage) return item;
|
|
1227
|
+
return rebuildItemSvg({
|
|
1228
|
+
...item,
|
|
1229
|
+
imageRasterHref: hydratedImage.href,
|
|
1230
|
+
imageThumbnailHref: hydratedImage.href
|
|
1231
|
+
});
|
|
1232
|
+
}
|
|
1233
|
+
if (request.pageNumber == null) return item;
|
|
1234
|
+
const hydratedPdfPage = hydratedPdfPages.get(
|
|
1235
|
+
buildPdfHydrationKey(
|
|
1236
|
+
request.assetId,
|
|
1237
|
+
request.pageNumber,
|
|
1238
|
+
request.scale ?? pdfScale
|
|
1239
|
+
)
|
|
1240
|
+
);
|
|
1241
|
+
if (!hydratedPdfPage) return item;
|
|
1242
|
+
return rebuildItemSvg({
|
|
1243
|
+
...item,
|
|
1244
|
+
imageRasterHref: hydratedPdfPage.href,
|
|
1245
|
+
imageThumbnailHref: hydratedPdfPage.href,
|
|
1246
|
+
imageIntrinsicSize: {
|
|
1247
|
+
width: item.imageIntrinsicSize?.width ?? Math.max(1, Math.round(hydratedPdfPage.width ?? item.bounds.width)),
|
|
1248
|
+
height: item.imageIntrinsicSize?.height ?? Math.max(1, Math.round(hydratedPdfPage.height ?? item.bounds.height))
|
|
1249
|
+
}
|
|
1250
|
+
});
|
|
1251
|
+
}),
|
|
1252
|
+
objectUrls
|
|
1253
|
+
};
|
|
953
1254
|
}
|
|
954
1255
|
|
|
955
1256
|
// src/react/asset-ingestion.ts
|
|
@@ -992,6 +1293,7 @@ async function ingestAssetFilesToSceneItems(options) {
|
|
|
992
1293
|
gapWorld = 16,
|
|
993
1294
|
stepWorld = 48,
|
|
994
1295
|
pdfScale = 1.5,
|
|
1296
|
+
pdfPageConcurrency = 2,
|
|
995
1297
|
decorateItem,
|
|
996
1298
|
onError
|
|
997
1299
|
} = options;
|
|
@@ -1013,9 +1315,14 @@ async function ingestAssetFilesToSceneItems(options) {
|
|
|
1013
1315
|
continue;
|
|
1014
1316
|
}
|
|
1015
1317
|
try {
|
|
1016
|
-
const uploadResult = await uploadAssetIfNeeded(assetStore, file, kind);
|
|
1017
1318
|
if (kind === "pdf") {
|
|
1018
|
-
const pages = await
|
|
1319
|
+
const [uploadResult2, pages] = await Promise.all([
|
|
1320
|
+
uploadAssetIfNeeded(assetStore, file, kind),
|
|
1321
|
+
loadPdfToStore(file, imageStore, {
|
|
1322
|
+
scale: pdfScale,
|
|
1323
|
+
pageConcurrency: pdfPageConcurrency
|
|
1324
|
+
})
|
|
1325
|
+
]);
|
|
1019
1326
|
for (const page of pages) {
|
|
1020
1327
|
const fullUrl2 = await createBlobUrlFromStore(imageStore, page.blobId);
|
|
1021
1328
|
const naturalTopY2 = worldCenter.y - page.height / 2;
|
|
@@ -1052,7 +1359,7 @@ async function ingestAssetFilesToSceneItems(options) {
|
|
|
1052
1359
|
) : ""
|
|
1053
1360
|
},
|
|
1054
1361
|
itemContext2,
|
|
1055
|
-
|
|
1362
|
+
uploadResult2,
|
|
1056
1363
|
decorateItem
|
|
1057
1364
|
);
|
|
1058
1365
|
items.push(item2);
|
|
@@ -1063,10 +1370,11 @@ async function ingestAssetFilesToSceneItems(options) {
|
|
|
1063
1370
|
imageYOffsetAdjustment = 0;
|
|
1064
1371
|
continue;
|
|
1065
1372
|
}
|
|
1066
|
-
const
|
|
1067
|
-
file,
|
|
1068
|
-
imageStore
|
|
1069
|
-
);
|
|
1373
|
+
const [uploadResult, storedImage] = await Promise.all([
|
|
1374
|
+
uploadAssetIfNeeded(assetStore, file, kind),
|
|
1375
|
+
loadImageToStore(file, imageStore)
|
|
1376
|
+
]);
|
|
1377
|
+
const { blobId, thumbnailBlobId, width, height } = storedImage;
|
|
1070
1378
|
const fullUrl = await createBlobUrlFromStore(imageStore, blobId);
|
|
1071
1379
|
const thumbBlob = await imageStore.getThumbnail(thumbnailBlobId);
|
|
1072
1380
|
const thumbnailHref = thumbBlob ? URL.createObjectURL(thumbBlob) : null;
|
|
@@ -4226,16 +4534,14 @@ function itemHitTestWorldPoint(item, worldX, worldY, options) {
|
|
|
4226
4534
|
return true;
|
|
4227
4535
|
}
|
|
4228
4536
|
}
|
|
4537
|
+
return false;
|
|
4229
4538
|
}
|
|
4230
|
-
if (pts
|
|
4539
|
+
if (pts && pts.length === 1) {
|
|
4231
4540
|
const p = pts[0];
|
|
4232
|
-
if (p)
|
|
4233
|
-
|
|
4234
|
-
|
|
4235
|
-
|
|
4236
|
-
return true;
|
|
4237
|
-
}
|
|
4238
|
-
}
|
|
4541
|
+
if (!p) return false;
|
|
4542
|
+
const cw = itemLocalToWorld(p.x, p.y, item.x, item.y, w, h, rot);
|
|
4543
|
+
const dsq = (worldX - cw.x) ** 2 + (worldY - cw.y) ** 2;
|
|
4544
|
+
return dsq <= tolSq;
|
|
4239
4545
|
}
|
|
4240
4546
|
return hitTestFilledShape(item, worldX, worldY);
|
|
4241
4547
|
}
|
|
@@ -4780,101 +5086,12 @@ init_shape_builders();
|
|
|
4780
5086
|
var HANDLE_ORDER = ["nw", "n", "ne", "e", "se", "s", "sw", "w"];
|
|
4781
5087
|
var ERASER_TINT = "#cbd5e1";
|
|
4782
5088
|
var ERASER_TINT_OPACITY = 0.95;
|
|
5089
|
+
var ERASER_PREVIEW_OPACITY = 0.3;
|
|
4783
5090
|
function pointsToSmoothPath(points) {
|
|
4784
5091
|
if (points.length === 0) return null;
|
|
4785
5092
|
const d = smoothFreehandPointsToPathD(points);
|
|
4786
5093
|
return d || null;
|
|
4787
5094
|
}
|
|
4788
|
-
function renderEraserSkeleton(it, overlayStrokePx) {
|
|
4789
|
-
const b = normalizeRect(it.bounds);
|
|
4790
|
-
const tool = it.toolKind;
|
|
4791
|
-
const strokeWidth = Math.max(it.strokeWidth ?? 2, overlayStrokePx);
|
|
4792
|
-
const common = {
|
|
4793
|
-
stroke: ERASER_TINT,
|
|
4794
|
-
strokeWidth,
|
|
4795
|
-
strokeOpacity: ERASER_TINT_OPACITY,
|
|
4796
|
-
vectorEffect: "non-scaling-stroke",
|
|
4797
|
-
strokeLinecap: "round",
|
|
4798
|
-
strokeLinejoin: "round",
|
|
4799
|
-
fill: "none"
|
|
4800
|
-
};
|
|
4801
|
-
if (tool === "rect") {
|
|
4802
|
-
return /* @__PURE__ */ jsx("rect", { x: 0, y: 0, width: b.width, height: b.height, ...common });
|
|
4803
|
-
}
|
|
4804
|
-
if (tool === "ellipse") {
|
|
4805
|
-
return /* @__PURE__ */ jsx(
|
|
4806
|
-
"ellipse",
|
|
4807
|
-
{
|
|
4808
|
-
cx: b.width / 2,
|
|
4809
|
-
cy: b.height / 2,
|
|
4810
|
-
rx: Math.max(0, b.width / 2),
|
|
4811
|
-
ry: Math.max(0, b.height / 2),
|
|
4812
|
-
...common
|
|
4813
|
-
}
|
|
4814
|
-
);
|
|
4815
|
-
}
|
|
4816
|
-
if (tool === "line" || tool === "arrow") {
|
|
4817
|
-
const ln = it.line;
|
|
4818
|
-
if (!ln)
|
|
4819
|
-
return /* @__PURE__ */ jsx("rect", { x: 0, y: 0, width: b.width, height: b.height, ...common });
|
|
4820
|
-
const geometry = tool === "arrow" ? computeStraightArrowGeometry(
|
|
4821
|
-
ln,
|
|
4822
|
-
Math.max(it.strokeWidth ?? 2, overlayStrokePx)
|
|
4823
|
-
) : null;
|
|
4824
|
-
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
4825
|
-
/* @__PURE__ */ jsx(
|
|
4826
|
-
"line",
|
|
4827
|
-
{
|
|
4828
|
-
x1: ln.x1,
|
|
4829
|
-
y1: ln.y1,
|
|
4830
|
-
x2: geometry?.shaftEndX ?? ln.x2,
|
|
4831
|
-
y2: geometry?.shaftEndY ?? ln.y2,
|
|
4832
|
-
...common
|
|
4833
|
-
}
|
|
4834
|
-
),
|
|
4835
|
-
tool === "arrow" && geometry ? /* @__PURE__ */ jsx(
|
|
4836
|
-
"path",
|
|
4837
|
-
{
|
|
4838
|
-
d: `M ${geometry.headLeftX} ${geometry.headLeftY} L ${geometry.headTipX} ${geometry.headTipY} L ${geometry.headRightX} ${geometry.headRightY}`,
|
|
4839
|
-
...common
|
|
4840
|
-
}
|
|
4841
|
-
) : null
|
|
4842
|
-
] });
|
|
4843
|
-
}
|
|
4844
|
-
if (tool === "draw" || tool === "marker" || tool === "pencil" || tool === "brush") {
|
|
4845
|
-
const pts = it.pathPointsLocal ?? [];
|
|
4846
|
-
if (pts.length === 1) {
|
|
4847
|
-
const p = pts[0];
|
|
4848
|
-
if (!p) return null;
|
|
4849
|
-
return /* @__PURE__ */ jsx(
|
|
4850
|
-
"circle",
|
|
4851
|
-
{
|
|
4852
|
-
cx: p.x,
|
|
4853
|
-
cy: p.y,
|
|
4854
|
-
r: Math.max((it.strokeWidth ?? 2) / 2, 2),
|
|
4855
|
-
fill: ERASER_TINT,
|
|
4856
|
-
fillOpacity: 0.8,
|
|
4857
|
-
vectorEffect: "non-scaling-stroke"
|
|
4858
|
-
}
|
|
4859
|
-
);
|
|
4860
|
-
}
|
|
4861
|
-
const d = pointsToSmoothPath(pts);
|
|
4862
|
-
if (d) {
|
|
4863
|
-
return /* @__PURE__ */ jsx("path", { d, ...common, shapeRendering: "geometricPrecision" });
|
|
4864
|
-
}
|
|
4865
|
-
}
|
|
4866
|
-
return /* @__PURE__ */ jsx(
|
|
4867
|
-
"rect",
|
|
4868
|
-
{
|
|
4869
|
-
x: 0,
|
|
4870
|
-
y: 0,
|
|
4871
|
-
width: b.width,
|
|
4872
|
-
height: b.height,
|
|
4873
|
-
...common,
|
|
4874
|
-
strokeDasharray: "4 4"
|
|
4875
|
-
}
|
|
4876
|
-
);
|
|
4877
|
-
}
|
|
4878
5095
|
function InteractionOverlay({
|
|
4879
5096
|
camera,
|
|
4880
5097
|
cameraVersion: _cameraVersion,
|
|
@@ -5122,16 +5339,15 @@ function InteractionOverlay({
|
|
|
5122
5339
|
}
|
|
5123
5340
|
let eraserPreview = null;
|
|
5124
5341
|
if (eraserPreviewItems.length > 0) {
|
|
5125
|
-
eraserPreview = /* @__PURE__ */ jsx("g", { children: eraserPreviewItems.map((it) =>
|
|
5126
|
-
|
|
5127
|
-
|
|
5128
|
-
|
|
5129
|
-
|
|
5130
|
-
|
|
5131
|
-
|
|
5132
|
-
|
|
5133
|
-
|
|
5134
|
-
}) });
|
|
5342
|
+
eraserPreview = /* @__PURE__ */ jsx("g", { children: eraserPreviewItems.map((it) => /* @__PURE__ */ jsx(
|
|
5343
|
+
"g",
|
|
5344
|
+
{
|
|
5345
|
+
transform: formatItemPlacementTransform(it),
|
|
5346
|
+
opacity: ERASER_PREVIEW_OPACITY,
|
|
5347
|
+
dangerouslySetInnerHTML: { __html: it.childrenSvg }
|
|
5348
|
+
},
|
|
5349
|
+
`erase-preview-${it.id}`
|
|
5350
|
+
)) });
|
|
5135
5351
|
}
|
|
5136
5352
|
let marqueeCandidates = null;
|
|
5137
5353
|
if (marqueeCandidateItems.length > 0) {
|
|
@@ -8595,6 +8811,6 @@ function ViewportZoomControls({
|
|
|
8595
8811
|
);
|
|
8596
8812
|
}
|
|
8597
8813
|
|
|
8598
|
-
export { CanvuChromeContext, CanvuPluginContext, DEFAULT_OVERFLOW_TOOL_IDS, DEFAULT_VECTOR_CANVAS_STORAGE_KEY, DEFAULT_VECTOR_TOOLS, IconArrow, IconDraw, IconEllipse, IconHand, IconImage, IconLaser, IconLine, IconRect, IconSelect, IconText, NavMenu, ShapeContextMenu, VectorCanvas, VectorCanvasBody, VectorCanvasHeader, VectorCanvasMain, VectorCanvasRoot, VectorCanvasToolbar, VectorCanvasViewportSurface, VectorSelectionInspector, VectorToolbar, VectorViewport, ViewportZoomControls, createCanvuPlugin, createIndexedDbPersistenceAdapter, createLocalStoragePersistenceAdapter, createNoopPersistenceAdapter, createToolPlugin, cursorForVectorToolId, getBoardPositionStyle, ingestAssetFilesToSceneItems, useCanvuChromeContext, useCanvuDocumentContext, useCanvuPluginContext, useCanvuPluginContribution, useCanvuResolvedTools, useCanvuViewportContext, useVectorCanvasDocument };
|
|
8814
|
+
export { CanvuChromeContext, CanvuPluginContext, DEFAULT_OVERFLOW_TOOL_IDS, DEFAULT_VECTOR_CANVAS_STORAGE_KEY, DEFAULT_VECTOR_TOOLS, IconArrow, IconDraw, IconEllipse, IconHand, IconImage, IconLaser, IconLine, IconRect, IconSelect, IconText, NavMenu, ShapeContextMenu, VectorCanvas, VectorCanvasBody, VectorCanvasHeader, VectorCanvasMain, VectorCanvasRoot, VectorCanvasToolbar, VectorCanvasViewportSurface, VectorSelectionInspector, VectorToolbar, VectorViewport, ViewportZoomControls, createCanvuPlugin, createIndexedDbPersistenceAdapter, createLocalStoragePersistenceAdapter, createNoopPersistenceAdapter, createToolPlugin, cursorForVectorToolId, getBoardPositionStyle, hydrateSceneItemsWithAssets, ingestAssetFilesToSceneItems, useCanvuChromeContext, useCanvuDocumentContext, useCanvuPluginContext, useCanvuPluginContribution, useCanvuResolvedTools, useCanvuViewportContext, useVectorCanvasDocument };
|
|
8599
8815
|
//# sourceMappingURL=react.js.map
|
|
8600
8816
|
//# sourceMappingURL=react.js.map
|