canvu-react 0.4.44 → 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 +208 -31
- package/dist/native.cjs.map +1 -1
- package/dist/native.js +209 -32
- 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
|
|
|
@@ -957,6 +957,9 @@ function rebuildItemSvg(item) {
|
|
|
957
957
|
}
|
|
958
958
|
return item;
|
|
959
959
|
}
|
|
960
|
+
function applyStrokeToItem(item, patch) {
|
|
961
|
+
return rebuildItemSvg({ ...item, ...patch });
|
|
962
|
+
}
|
|
960
963
|
function createRectangleItem(id, bounds, style) {
|
|
961
964
|
const r = normalizeRect(bounds);
|
|
962
965
|
const s = { ...DEFAULT_STROKE_STYLE, ...style };
|
|
@@ -1860,6 +1863,63 @@ function smoothFreehandPointsToPathD(points) {
|
|
|
1860
1863
|
return d;
|
|
1861
1864
|
}
|
|
1862
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
|
+
|
|
1863
1923
|
// src/native/native-link-card.ts
|
|
1864
1924
|
function linkHostname(href) {
|
|
1865
1925
|
try {
|
|
@@ -2862,7 +2922,12 @@ function NativeShapeRenderer({ item }) {
|
|
|
2862
2922
|
)) });
|
|
2863
2923
|
}
|
|
2864
2924
|
if ((k === "draw" || k === "pencil" || k === "brush" || k === "marker") && item.pathPointsLocal && item.pathPointsLocal.length > 0) {
|
|
2865
|
-
const payload =
|
|
2925
|
+
const payload = getNativeFreehandSvgPayload({
|
|
2926
|
+
itemId: item.id,
|
|
2927
|
+
pathPointsLocal: item.pathPointsLocal,
|
|
2928
|
+
style,
|
|
2929
|
+
toolKind: k
|
|
2930
|
+
});
|
|
2866
2931
|
if (!payload) return null;
|
|
2867
2932
|
const color = rgba(style.stroke, style.strokeOpacity);
|
|
2868
2933
|
if (payload.kind === "circle") {
|
|
@@ -5166,6 +5231,36 @@ function hitTestNativeRemotePresence(peers, camera, point) {
|
|
|
5166
5231
|
}
|
|
5167
5232
|
return null;
|
|
5168
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
|
+
}
|
|
5169
5264
|
var DEFAULT_NATIVE_LINK_TOOL_DIALOG_LABELS = {
|
|
5170
5265
|
title: "Add link",
|
|
5171
5266
|
description: "Paste the link you want to add to the board.",
|
|
@@ -5191,6 +5286,14 @@ function isPlacementTool(toolId) {
|
|
|
5191
5286
|
function isDefaultMarkerToolStyle(style) {
|
|
5192
5287
|
return style.stroke === MARKER_TOOL_STYLE.stroke && style.strokeWidth === MARKER_TOOL_STYLE.strokeWidth && style.strokeOpacity === MARKER_TOOL_STYLE.strokeOpacity;
|
|
5193
5288
|
}
|
|
5289
|
+
function getNativeStyleInspectorToolId(item) {
|
|
5290
|
+
const kind = item.toolKind;
|
|
5291
|
+
if (kind === "marker") return "marker";
|
|
5292
|
+
if (kind === "draw" || kind === "pencil" || kind === "brush" || kind === "rect" || kind === "ellipse" || kind === "architectural-cloud" || kind === "line" || kind === "arrow") {
|
|
5293
|
+
return "draw";
|
|
5294
|
+
}
|
|
5295
|
+
return null;
|
|
5296
|
+
}
|
|
5194
5297
|
function placementPreviewForTool(toolId, start, end) {
|
|
5195
5298
|
if (toolId === "rect" || toolId === "ellipse" || toolId === "architectural-cloud") {
|
|
5196
5299
|
return { kind: toolId, rect: rectFromCorners(start, end) };
|
|
@@ -5304,13 +5407,41 @@ var NativeVectorViewport = forwardRef(function NativeVectorViewport2({
|
|
|
5304
5407
|
customPlacementsRef.current = customPlacements;
|
|
5305
5408
|
const onSelectionChangeRef = useRef(onSelectionChange);
|
|
5306
5409
|
onSelectionChangeRef.current = onSelectionChange;
|
|
5307
|
-
const
|
|
5308
|
-
|
|
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;
|
|
5309
5417
|
const selectedIdsRef = useRef(selectedIds);
|
|
5310
5418
|
selectedIdsRef.current = selectedIds;
|
|
5311
5419
|
const remotePresenceRef = useRef(remotePresence);
|
|
5312
5420
|
remotePresenceRef.current = remotePresence;
|
|
5313
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
|
+
}, []);
|
|
5314
5445
|
const [placementPreview, setPlacementPreviewState] = useState(null);
|
|
5315
5446
|
const setRealtimePlacementPreview = useCallback(
|
|
5316
5447
|
(nextPreview) => {
|
|
@@ -5451,15 +5582,48 @@ var NativeVectorViewport = forwardRef(function NativeVectorViewport2({
|
|
|
5451
5582
|
const hideToolCursor = useCallback(() => {
|
|
5452
5583
|
}, []);
|
|
5453
5584
|
const selectedItems = useMemo(
|
|
5454
|
-
() =>
|
|
5455
|
-
[
|
|
5585
|
+
() => activeItems.filter((item) => selectedIds.includes(item.id)),
|
|
5586
|
+
[activeItems, selectedIds]
|
|
5456
5587
|
);
|
|
5588
|
+
const selectedStyleInspectorState = useMemo(() => {
|
|
5589
|
+
const styleableItems = selectedItems.filter(
|
|
5590
|
+
(item) => !item.locked && getNativeStyleInspectorToolId(item) !== null
|
|
5591
|
+
);
|
|
5592
|
+
if (styleableItems.length === 0) return null;
|
|
5593
|
+
const toolId2 = styleableItems.every((item) => item.toolKind === "marker") ? "marker" : "draw";
|
|
5594
|
+
const primaryItem = toolId2 === "marker" ? styleableItems[0] : styleableItems.find((item) => item.toolKind !== "marker") ?? styleableItems[0];
|
|
5595
|
+
if (!primaryItem) return null;
|
|
5596
|
+
return {
|
|
5597
|
+
toolId: toolId2,
|
|
5598
|
+
value: resolveStrokeStyle(primaryItem)
|
|
5599
|
+
};
|
|
5600
|
+
}, [selectedItems]);
|
|
5457
5601
|
const sceneItems = useMemo(() => {
|
|
5458
|
-
if (eraserPreviewIds.length === 0) return
|
|
5602
|
+
if (eraserPreviewIds.length === 0) return activeItems;
|
|
5459
5603
|
const hidden = new Set(eraserPreviewIds);
|
|
5460
|
-
return
|
|
5461
|
-
}, [
|
|
5604
|
+
return activeItems.filter((item) => !hidden.has(item.id));
|
|
5605
|
+
}, [activeItems, eraserPreviewIds]);
|
|
5462
5606
|
const showResizeHandles = interactive && selectedItems.length === 1 && !selectedItems[0]?.locked && supportsNativeResizeHandles(selectedItems[0]);
|
|
5607
|
+
const patchSelectedItemsStrokeStyle = useCallback(
|
|
5608
|
+
(patch) => {
|
|
5609
|
+
const change = onItemsChangeRef.current;
|
|
5610
|
+
if (!change) return;
|
|
5611
|
+
const selectedIdSet = new Set(selectedIdsRef.current);
|
|
5612
|
+
if (selectedIdSet.size === 0) return;
|
|
5613
|
+
let changed = false;
|
|
5614
|
+
const nextItems = itemsRef.current.map((item) => {
|
|
5615
|
+
if (!selectedIdSet.has(item.id) || item.locked || getNativeStyleInspectorToolId(item) === null) {
|
|
5616
|
+
return item;
|
|
5617
|
+
}
|
|
5618
|
+
changed = true;
|
|
5619
|
+
return applyStrokeToItem(item, patch);
|
|
5620
|
+
});
|
|
5621
|
+
if (!changed) return;
|
|
5622
|
+
change(nextItems);
|
|
5623
|
+
patchCurrentStrokeStyle(patch);
|
|
5624
|
+
},
|
|
5625
|
+
[patchCurrentStrokeStyle]
|
|
5626
|
+
);
|
|
5463
5627
|
const lastPinchDist = useRef(null);
|
|
5464
5628
|
const lastPanPoint = useRef(null);
|
|
5465
5629
|
const beginDragAtScreenPoint = useCallback(
|
|
@@ -5736,21 +5900,13 @@ var NativeVectorViewport = forwardRef(function NativeVectorViewport2({
|
|
|
5736
5900
|
const dy = worldY - st.startWorld.y;
|
|
5737
5901
|
const change = onItemsChangeRef.current;
|
|
5738
5902
|
if (!change) return;
|
|
5739
|
-
const
|
|
5740
|
-
|
|
5741
|
-
|
|
5742
|
-
|
|
5743
|
-
|
|
5744
|
-
x: snap.x + dx,
|
|
5745
|
-
y: snap.y + dy,
|
|
5746
|
-
bounds: {
|
|
5747
|
-
...snap.bounds,
|
|
5748
|
-
x: snap.bounds.x + dx,
|
|
5749
|
-
y: snap.bounds.y + dy
|
|
5750
|
-
}
|
|
5751
|
-
};
|
|
5903
|
+
const nextItems = moveNativeTransientItems({
|
|
5904
|
+
items: itemsRef.current,
|
|
5905
|
+
snapshots: st.snapshots,
|
|
5906
|
+
dx,
|
|
5907
|
+
dy
|
|
5752
5908
|
});
|
|
5753
|
-
|
|
5909
|
+
setTransientItemsPreview(nextItems);
|
|
5754
5910
|
return;
|
|
5755
5911
|
}
|
|
5756
5912
|
if (st.kind === "rotate") {
|
|
@@ -5763,7 +5919,13 @@ var NativeVectorViewport = forwardRef(function NativeVectorViewport2({
|
|
|
5763
5919
|
st.startPointerAngleRad,
|
|
5764
5920
|
angle
|
|
5765
5921
|
);
|
|
5766
|
-
|
|
5922
|
+
setTransientItemsPreview(
|
|
5923
|
+
replaceNativeTransientItem({
|
|
5924
|
+
items: itemsRef.current,
|
|
5925
|
+
itemId: st.id,
|
|
5926
|
+
item: next
|
|
5927
|
+
})
|
|
5928
|
+
);
|
|
5767
5929
|
return;
|
|
5768
5930
|
}
|
|
5769
5931
|
if (st.kind === "resize") {
|
|
@@ -5773,7 +5935,13 @@ var NativeVectorViewport = forwardRef(function NativeVectorViewport2({
|
|
|
5773
5935
|
x: worldX,
|
|
5774
5936
|
y: worldY
|
|
5775
5937
|
});
|
|
5776
|
-
|
|
5938
|
+
setTransientItemsPreview(
|
|
5939
|
+
replaceNativeTransientItem({
|
|
5940
|
+
items: itemsRef.current,
|
|
5941
|
+
itemId: st.id,
|
|
5942
|
+
item: next
|
|
5943
|
+
})
|
|
5944
|
+
);
|
|
5777
5945
|
return;
|
|
5778
5946
|
}
|
|
5779
5947
|
if (st.kind === "marquee") {
|
|
@@ -5823,6 +5991,7 @@ var NativeVectorViewport = forwardRef(function NativeVectorViewport2({
|
|
|
5823
5991
|
requestRender,
|
|
5824
5992
|
screenToWorld,
|
|
5825
5993
|
setRealtimePlacementPreview,
|
|
5994
|
+
setTransientItemsPreview,
|
|
5826
5995
|
updateToolCursorPoint
|
|
5827
5996
|
]
|
|
5828
5997
|
);
|
|
@@ -5864,10 +6033,12 @@ var NativeVectorViewport = forwardRef(function NativeVectorViewport2({
|
|
|
5864
6033
|
}
|
|
5865
6034
|
if (st.kind === "move") {
|
|
5866
6035
|
dragStateRef.current = { kind: "idle" };
|
|
6036
|
+
commitTransientItemsPreview();
|
|
5867
6037
|
return;
|
|
5868
6038
|
}
|
|
5869
6039
|
if (st.kind === "resize" || st.kind === "rotate") {
|
|
5870
6040
|
dragStateRef.current = { kind: "idle" };
|
|
6041
|
+
commitTransientItemsPreview();
|
|
5871
6042
|
return;
|
|
5872
6043
|
}
|
|
5873
6044
|
if (st.kind === "marquee") {
|
|
@@ -6077,6 +6248,7 @@ var NativeVectorViewport = forwardRef(function NativeVectorViewport2({
|
|
|
6077
6248
|
requestSelectToolAfterUse,
|
|
6078
6249
|
screenToWorld,
|
|
6079
6250
|
setRealtimePlacementPreview,
|
|
6251
|
+
commitTransientItemsPreview,
|
|
6080
6252
|
updateToolCursorPoint
|
|
6081
6253
|
]
|
|
6082
6254
|
);
|
|
@@ -6167,6 +6339,7 @@ var NativeVectorViewport = forwardRef(function NativeVectorViewport2({
|
|
|
6167
6339
|
notifyWorldPointerLeave();
|
|
6168
6340
|
dragStateRef.current = { kind: "idle" };
|
|
6169
6341
|
setRealtimePlacementPreview(null);
|
|
6342
|
+
clearTransientItemsPreview();
|
|
6170
6343
|
setLaserTrail([]);
|
|
6171
6344
|
setEraserTrail([]);
|
|
6172
6345
|
setEraserPreviewIds([]);
|
|
@@ -6180,7 +6353,8 @@ var NativeVectorViewport = forwardRef(function NativeVectorViewport2({
|
|
|
6180
6353
|
requestRender,
|
|
6181
6354
|
hideToolCursor,
|
|
6182
6355
|
notifyWorldPointerLeave,
|
|
6183
|
-
setRealtimePlacementPreview
|
|
6356
|
+
setRealtimePlacementPreview,
|
|
6357
|
+
clearTransientItemsPreview
|
|
6184
6358
|
]
|
|
6185
6359
|
);
|
|
6186
6360
|
useImperativeHandle(
|
|
@@ -6205,6 +6379,9 @@ var NativeVectorViewport = forwardRef(function NativeVectorViewport2({
|
|
|
6205
6379
|
[requestRender, size]
|
|
6206
6380
|
);
|
|
6207
6381
|
const activeStyleToolId = toolId === "draw" || toolId === "marker" ? toolId : null;
|
|
6382
|
+
const styleInspectorToolId = selectedStyleInspectorState?.toolId ?? activeStyleToolId;
|
|
6383
|
+
const styleInspectorValue = selectedStyleInspectorState?.value ?? strokeStyleState;
|
|
6384
|
+
const styleInspectorChange = selectedStyleInspectorState ? patchSelectedItemsStrokeStyle : patchCurrentStrokeStyle;
|
|
6208
6385
|
const nativeLinkDialogLabels = {
|
|
6209
6386
|
...DEFAULT_NATIVE_LINK_TOOL_DIALOG_LABELS,
|
|
6210
6387
|
...linkToolDialogLabels ?? {}
|
|
@@ -6247,8 +6424,8 @@ var NativeVectorViewport = forwardRef(function NativeVectorViewport2({
|
|
|
6247
6424
|
placementPreview,
|
|
6248
6425
|
laserTrail,
|
|
6249
6426
|
eraserTrail,
|
|
6250
|
-
eraserPreviewItems:
|
|
6251
|
-
(
|
|
6427
|
+
eraserPreviewItems: activeItems.filter(
|
|
6428
|
+
(item) => eraserPreviewIds.includes(item.id)
|
|
6252
6429
|
),
|
|
6253
6430
|
previewStrokeStyle: strokeStyleState,
|
|
6254
6431
|
remotePresence
|
|
@@ -6271,7 +6448,7 @@ var NativeVectorViewport = forwardRef(function NativeVectorViewport2({
|
|
|
6271
6448
|
children: overlay
|
|
6272
6449
|
}
|
|
6273
6450
|
) : null,
|
|
6274
|
-
interactive && showStyleInspector &&
|
|
6451
|
+
interactive && showStyleInspector && styleInspectorToolId ? /* @__PURE__ */ jsx(
|
|
6275
6452
|
View,
|
|
6276
6453
|
{
|
|
6277
6454
|
pointerEvents: "box-none",
|
|
@@ -6294,9 +6471,9 @@ var NativeVectorViewport = forwardRef(function NativeVectorViewport2({
|
|
|
6294
6471
|
children: /* @__PURE__ */ jsx(
|
|
6295
6472
|
NativeVectorStyleInspector,
|
|
6296
6473
|
{
|
|
6297
|
-
toolId:
|
|
6298
|
-
value:
|
|
6299
|
-
onChange:
|
|
6474
|
+
toolId: styleInspectorToolId,
|
|
6475
|
+
value: styleInspectorValue,
|
|
6476
|
+
onChange: styleInspectorChange
|
|
6300
6477
|
}
|
|
6301
6478
|
)
|
|
6302
6479
|
}
|