canvu-react 0.4.45 → 0.4.46
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/native.cjs +157 -27
- package/dist/native.cjs.map +1 -1
- package/dist/native.js +158 -28
- package/dist/native.js.map +1 -1
- package/package.json +1 -1
package/dist/native.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import getStroke from 'perfect-freehand';
|
|
2
2
|
import { Group, Canvas, Rect, Circle, Path, RoundedRect, Oval, DashPathEffect, Line, vec, matchFont, Text as Text$1, Image } from '@shopify/react-native-skia';
|
|
3
|
-
import { memo, forwardRef, useState, useRef,
|
|
3
|
+
import { memo, forwardRef, useState, useRef, useEffect, useCallback, useMemo, useImperativeHandle } from 'react';
|
|
4
4
|
import { StyleSheet, PanResponder, View, Modal, Text, TextInput, Pressable, ScrollView, Image as Image$1 } from 'react-native';
|
|
5
5
|
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
6
6
|
|
|
@@ -1863,6 +1863,63 @@ function smoothFreehandPointsToPathD(points) {
|
|
|
1863
1863
|
return d;
|
|
1864
1864
|
}
|
|
1865
1865
|
|
|
1866
|
+
// src/native/native-freehand-payload-cache.ts
|
|
1867
|
+
var MAX_NATIVE_FREEHAND_PAYLOAD_CACHE_SIZE = 800;
|
|
1868
|
+
var pathSignatureCache = /* @__PURE__ */ new WeakMap();
|
|
1869
|
+
var payloadCache = /* @__PURE__ */ new Map();
|
|
1870
|
+
function hashNumber(hash, value) {
|
|
1871
|
+
const normalizedValue = Math.round(value * 100);
|
|
1872
|
+
return Math.imul(hash ^ normalizedValue, 16777619) >>> 0;
|
|
1873
|
+
}
|
|
1874
|
+
function getPathPointsSignature(pathPointsLocal) {
|
|
1875
|
+
const cachedSignature = pathSignatureCache.get(pathPointsLocal);
|
|
1876
|
+
if (cachedSignature) return cachedSignature;
|
|
1877
|
+
const hash = pathPointsLocal.reduce((currentHash, point) => {
|
|
1878
|
+
const withX = hashNumber(currentHash, point.x);
|
|
1879
|
+
const withY = hashNumber(withX, point.y);
|
|
1880
|
+
return hashNumber(withY, point.pressure ?? -1);
|
|
1881
|
+
}, 2166136261);
|
|
1882
|
+
const signature = `${pathPointsLocal.length}:${hash}`;
|
|
1883
|
+
pathSignatureCache.set(pathPointsLocal, signature);
|
|
1884
|
+
return signature;
|
|
1885
|
+
}
|
|
1886
|
+
function getStyleSignature(style) {
|
|
1887
|
+
return [
|
|
1888
|
+
style.stroke,
|
|
1889
|
+
style.strokeWidth,
|
|
1890
|
+
style.strokeOpacity ?? "",
|
|
1891
|
+
style.strokeDash ?? ""
|
|
1892
|
+
].join(":");
|
|
1893
|
+
}
|
|
1894
|
+
function getPayloadCacheKey(input) {
|
|
1895
|
+
return [
|
|
1896
|
+
input.itemId,
|
|
1897
|
+
input.toolKind,
|
|
1898
|
+
getStyleSignature(input.style),
|
|
1899
|
+
getPathPointsSignature(input.pathPointsLocal)
|
|
1900
|
+
].join("|");
|
|
1901
|
+
}
|
|
1902
|
+
function storePayload(key, payload) {
|
|
1903
|
+
payloadCache.set(key, payload);
|
|
1904
|
+
if (payloadCache.size > MAX_NATIVE_FREEHAND_PAYLOAD_CACHE_SIZE) {
|
|
1905
|
+
const oldestKey = payloadCache.keys().next().value;
|
|
1906
|
+
if (oldestKey !== void 0) {
|
|
1907
|
+
payloadCache.delete(oldestKey);
|
|
1908
|
+
}
|
|
1909
|
+
}
|
|
1910
|
+
return payload;
|
|
1911
|
+
}
|
|
1912
|
+
function getNativeFreehandSvgPayload(input) {
|
|
1913
|
+
const key = getPayloadCacheKey(input);
|
|
1914
|
+
if (payloadCache.has(key)) {
|
|
1915
|
+
return payloadCache.get(key) ?? null;
|
|
1916
|
+
}
|
|
1917
|
+
return storePayload(
|
|
1918
|
+
key,
|
|
1919
|
+
computeFreehandSvgPayload(input.pathPointsLocal, input.style, input.toolKind)
|
|
1920
|
+
);
|
|
1921
|
+
}
|
|
1922
|
+
|
|
1866
1923
|
// src/native/native-link-card.ts
|
|
1867
1924
|
function linkHostname(href) {
|
|
1868
1925
|
try {
|
|
@@ -2865,7 +2922,12 @@ function NativeShapeRenderer({ item }) {
|
|
|
2865
2922
|
)) });
|
|
2866
2923
|
}
|
|
2867
2924
|
if ((k === "draw" || k === "pencil" || k === "brush" || k === "marker") && item.pathPointsLocal && item.pathPointsLocal.length > 0) {
|
|
2868
|
-
const payload =
|
|
2925
|
+
const payload = getNativeFreehandSvgPayload({
|
|
2926
|
+
itemId: item.id,
|
|
2927
|
+
pathPointsLocal: item.pathPointsLocal,
|
|
2928
|
+
style,
|
|
2929
|
+
toolKind: k
|
|
2930
|
+
});
|
|
2869
2931
|
if (!payload) return null;
|
|
2870
2932
|
const color = rgba(style.stroke, style.strokeOpacity);
|
|
2871
2933
|
if (payload.kind === "circle") {
|
|
@@ -5169,6 +5231,36 @@ function hitTestNativeRemotePresence(peers, camera, point) {
|
|
|
5169
5231
|
}
|
|
5170
5232
|
return null;
|
|
5171
5233
|
}
|
|
5234
|
+
|
|
5235
|
+
// src/native/native-transient-items.ts
|
|
5236
|
+
function moveNativeTransientItems({
|
|
5237
|
+
items,
|
|
5238
|
+
snapshots,
|
|
5239
|
+
dx,
|
|
5240
|
+
dy
|
|
5241
|
+
}) {
|
|
5242
|
+
return items.map((item) => {
|
|
5243
|
+
const snapshot = snapshots[item.id];
|
|
5244
|
+
if (!snapshot) return item;
|
|
5245
|
+
return {
|
|
5246
|
+
...snapshot,
|
|
5247
|
+
x: snapshot.x + dx,
|
|
5248
|
+
y: snapshot.y + dy,
|
|
5249
|
+
bounds: {
|
|
5250
|
+
...snapshot.bounds,
|
|
5251
|
+
x: snapshot.bounds.x + dx,
|
|
5252
|
+
y: snapshot.bounds.y + dy
|
|
5253
|
+
}
|
|
5254
|
+
};
|
|
5255
|
+
});
|
|
5256
|
+
}
|
|
5257
|
+
function replaceNativeTransientItem({
|
|
5258
|
+
items,
|
|
5259
|
+
itemId,
|
|
5260
|
+
item: replacement
|
|
5261
|
+
}) {
|
|
5262
|
+
return items.map((item) => item.id === itemId ? replacement : item);
|
|
5263
|
+
}
|
|
5172
5264
|
var DEFAULT_NATIVE_LINK_TOOL_DIALOG_LABELS = {
|
|
5173
5265
|
title: "Add link",
|
|
5174
5266
|
description: "Paste the link you want to add to the board.",
|
|
@@ -5315,13 +5407,41 @@ var NativeVectorViewport = forwardRef(function NativeVectorViewport2({
|
|
|
5315
5407
|
customPlacementsRef.current = customPlacements;
|
|
5316
5408
|
const onSelectionChangeRef = useRef(onSelectionChange);
|
|
5317
5409
|
onSelectionChangeRef.current = onSelectionChange;
|
|
5318
|
-
const
|
|
5319
|
-
|
|
5410
|
+
const [transientItems, setTransientItems] = useState(
|
|
5411
|
+
null
|
|
5412
|
+
);
|
|
5413
|
+
const transientItemsRef = useRef(null);
|
|
5414
|
+
const activeItems = transientItems ?? items;
|
|
5415
|
+
const itemsRef = useRef(activeItems);
|
|
5416
|
+
itemsRef.current = activeItems;
|
|
5320
5417
|
const selectedIdsRef = useRef(selectedIds);
|
|
5321
5418
|
selectedIdsRef.current = selectedIds;
|
|
5322
5419
|
const remotePresenceRef = useRef(remotePresence);
|
|
5323
5420
|
remotePresenceRef.current = remotePresence;
|
|
5324
5421
|
const dragStateRef = useRef({ kind: "idle" });
|
|
5422
|
+
useEffect(() => {
|
|
5423
|
+
const committedItems = items;
|
|
5424
|
+
if (transientItemsRef.current === null && itemsRef.current === committedItems) {
|
|
5425
|
+
return;
|
|
5426
|
+
}
|
|
5427
|
+
transientItemsRef.current = null;
|
|
5428
|
+
setTransientItems(null);
|
|
5429
|
+
}, [items]);
|
|
5430
|
+
const setTransientItemsPreview = useCallback((nextItems) => {
|
|
5431
|
+
transientItemsRef.current = nextItems;
|
|
5432
|
+
setTransientItems(nextItems);
|
|
5433
|
+
}, []);
|
|
5434
|
+
const clearTransientItemsPreview = useCallback(() => {
|
|
5435
|
+
transientItemsRef.current = null;
|
|
5436
|
+
setTransientItems(null);
|
|
5437
|
+
}, []);
|
|
5438
|
+
const commitTransientItemsPreview = useCallback(() => {
|
|
5439
|
+
const nextItems = transientItemsRef.current;
|
|
5440
|
+
const change = onItemsChangeRef.current;
|
|
5441
|
+
if (!nextItems || !change) return false;
|
|
5442
|
+
change(nextItems);
|
|
5443
|
+
return true;
|
|
5444
|
+
}, []);
|
|
5325
5445
|
const [placementPreview, setPlacementPreviewState] = useState(null);
|
|
5326
5446
|
const setRealtimePlacementPreview = useCallback(
|
|
5327
5447
|
(nextPreview) => {
|
|
@@ -5462,8 +5582,8 @@ var NativeVectorViewport = forwardRef(function NativeVectorViewport2({
|
|
|
5462
5582
|
const hideToolCursor = useCallback(() => {
|
|
5463
5583
|
}, []);
|
|
5464
5584
|
const selectedItems = useMemo(
|
|
5465
|
-
() =>
|
|
5466
|
-
[
|
|
5585
|
+
() => activeItems.filter((item) => selectedIds.includes(item.id)),
|
|
5586
|
+
[activeItems, selectedIds]
|
|
5467
5587
|
);
|
|
5468
5588
|
const selectedStyleInspectorState = useMemo(() => {
|
|
5469
5589
|
const styleableItems = selectedItems.filter(
|
|
@@ -5479,10 +5599,10 @@ var NativeVectorViewport = forwardRef(function NativeVectorViewport2({
|
|
|
5479
5599
|
};
|
|
5480
5600
|
}, [selectedItems]);
|
|
5481
5601
|
const sceneItems = useMemo(() => {
|
|
5482
|
-
if (eraserPreviewIds.length === 0) return
|
|
5602
|
+
if (eraserPreviewIds.length === 0) return activeItems;
|
|
5483
5603
|
const hidden = new Set(eraserPreviewIds);
|
|
5484
|
-
return
|
|
5485
|
-
}, [
|
|
5604
|
+
return activeItems.filter((item) => !hidden.has(item.id));
|
|
5605
|
+
}, [activeItems, eraserPreviewIds]);
|
|
5486
5606
|
const showResizeHandles = interactive && selectedItems.length === 1 && !selectedItems[0]?.locked && supportsNativeResizeHandles(selectedItems[0]);
|
|
5487
5607
|
const patchSelectedItemsStrokeStyle = useCallback(
|
|
5488
5608
|
(patch) => {
|
|
@@ -5780,21 +5900,13 @@ var NativeVectorViewport = forwardRef(function NativeVectorViewport2({
|
|
|
5780
5900
|
const dy = worldY - st.startWorld.y;
|
|
5781
5901
|
const change = onItemsChangeRef.current;
|
|
5782
5902
|
if (!change) return;
|
|
5783
|
-
const
|
|
5784
|
-
|
|
5785
|
-
|
|
5786
|
-
|
|
5787
|
-
|
|
5788
|
-
x: snap.x + dx,
|
|
5789
|
-
y: snap.y + dy,
|
|
5790
|
-
bounds: {
|
|
5791
|
-
...snap.bounds,
|
|
5792
|
-
x: snap.bounds.x + dx,
|
|
5793
|
-
y: snap.bounds.y + dy
|
|
5794
|
-
}
|
|
5795
|
-
};
|
|
5903
|
+
const nextItems = moveNativeTransientItems({
|
|
5904
|
+
items: itemsRef.current,
|
|
5905
|
+
snapshots: st.snapshots,
|
|
5906
|
+
dx,
|
|
5907
|
+
dy
|
|
5796
5908
|
});
|
|
5797
|
-
|
|
5909
|
+
setTransientItemsPreview(nextItems);
|
|
5798
5910
|
return;
|
|
5799
5911
|
}
|
|
5800
5912
|
if (st.kind === "rotate") {
|
|
@@ -5807,7 +5919,13 @@ var NativeVectorViewport = forwardRef(function NativeVectorViewport2({
|
|
|
5807
5919
|
st.startPointerAngleRad,
|
|
5808
5920
|
angle
|
|
5809
5921
|
);
|
|
5810
|
-
|
|
5922
|
+
setTransientItemsPreview(
|
|
5923
|
+
replaceNativeTransientItem({
|
|
5924
|
+
items: itemsRef.current,
|
|
5925
|
+
itemId: st.id,
|
|
5926
|
+
item: next
|
|
5927
|
+
})
|
|
5928
|
+
);
|
|
5811
5929
|
return;
|
|
5812
5930
|
}
|
|
5813
5931
|
if (st.kind === "resize") {
|
|
@@ -5817,7 +5935,13 @@ var NativeVectorViewport = forwardRef(function NativeVectorViewport2({
|
|
|
5817
5935
|
x: worldX,
|
|
5818
5936
|
y: worldY
|
|
5819
5937
|
});
|
|
5820
|
-
|
|
5938
|
+
setTransientItemsPreview(
|
|
5939
|
+
replaceNativeTransientItem({
|
|
5940
|
+
items: itemsRef.current,
|
|
5941
|
+
itemId: st.id,
|
|
5942
|
+
item: next
|
|
5943
|
+
})
|
|
5944
|
+
);
|
|
5821
5945
|
return;
|
|
5822
5946
|
}
|
|
5823
5947
|
if (st.kind === "marquee") {
|
|
@@ -5867,6 +5991,7 @@ var NativeVectorViewport = forwardRef(function NativeVectorViewport2({
|
|
|
5867
5991
|
requestRender,
|
|
5868
5992
|
screenToWorld,
|
|
5869
5993
|
setRealtimePlacementPreview,
|
|
5994
|
+
setTransientItemsPreview,
|
|
5870
5995
|
updateToolCursorPoint
|
|
5871
5996
|
]
|
|
5872
5997
|
);
|
|
@@ -5908,10 +6033,12 @@ var NativeVectorViewport = forwardRef(function NativeVectorViewport2({
|
|
|
5908
6033
|
}
|
|
5909
6034
|
if (st.kind === "move") {
|
|
5910
6035
|
dragStateRef.current = { kind: "idle" };
|
|
6036
|
+
commitTransientItemsPreview();
|
|
5911
6037
|
return;
|
|
5912
6038
|
}
|
|
5913
6039
|
if (st.kind === "resize" || st.kind === "rotate") {
|
|
5914
6040
|
dragStateRef.current = { kind: "idle" };
|
|
6041
|
+
commitTransientItemsPreview();
|
|
5915
6042
|
return;
|
|
5916
6043
|
}
|
|
5917
6044
|
if (st.kind === "marquee") {
|
|
@@ -6121,6 +6248,7 @@ var NativeVectorViewport = forwardRef(function NativeVectorViewport2({
|
|
|
6121
6248
|
requestSelectToolAfterUse,
|
|
6122
6249
|
screenToWorld,
|
|
6123
6250
|
setRealtimePlacementPreview,
|
|
6251
|
+
commitTransientItemsPreview,
|
|
6124
6252
|
updateToolCursorPoint
|
|
6125
6253
|
]
|
|
6126
6254
|
);
|
|
@@ -6211,6 +6339,7 @@ var NativeVectorViewport = forwardRef(function NativeVectorViewport2({
|
|
|
6211
6339
|
notifyWorldPointerLeave();
|
|
6212
6340
|
dragStateRef.current = { kind: "idle" };
|
|
6213
6341
|
setRealtimePlacementPreview(null);
|
|
6342
|
+
clearTransientItemsPreview();
|
|
6214
6343
|
setLaserTrail([]);
|
|
6215
6344
|
setEraserTrail([]);
|
|
6216
6345
|
setEraserPreviewIds([]);
|
|
@@ -6224,7 +6353,8 @@ var NativeVectorViewport = forwardRef(function NativeVectorViewport2({
|
|
|
6224
6353
|
requestRender,
|
|
6225
6354
|
hideToolCursor,
|
|
6226
6355
|
notifyWorldPointerLeave,
|
|
6227
|
-
setRealtimePlacementPreview
|
|
6356
|
+
setRealtimePlacementPreview,
|
|
6357
|
+
clearTransientItemsPreview
|
|
6228
6358
|
]
|
|
6229
6359
|
);
|
|
6230
6360
|
useImperativeHandle(
|
|
@@ -6294,8 +6424,8 @@ var NativeVectorViewport = forwardRef(function NativeVectorViewport2({
|
|
|
6294
6424
|
placementPreview,
|
|
6295
6425
|
laserTrail,
|
|
6296
6426
|
eraserTrail,
|
|
6297
|
-
eraserPreviewItems:
|
|
6298
|
-
(
|
|
6427
|
+
eraserPreviewItems: activeItems.filter(
|
|
6428
|
+
(item) => eraserPreviewIds.includes(item.id)
|
|
6299
6429
|
),
|
|
6300
6430
|
previewStrokeStyle: strokeStyleState,
|
|
6301
6431
|
remotePresence
|