canvu-react 0.4.16 → 0.4.18
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 +648 -17
- package/dist/native.cjs.map +1 -1
- package/dist/native.d.cts +20 -1
- package/dist/native.d.ts +20 -1
- package/dist/native.js +648 -17
- package/dist/native.js.map +1 -1
- package/package.json +1 -1
package/dist/native.cjs
CHANGED
|
@@ -946,6 +946,10 @@ function worldToItemLocal(wx, wy, itemX, itemY, w, h, rotationRad) {
|
|
|
946
946
|
const ly = sin * dx + cos * dy;
|
|
947
947
|
return { x: c.x + lx, y: c.y + ly };
|
|
948
948
|
}
|
|
949
|
+
function itemPivotWorld(item) {
|
|
950
|
+
const r = normalizeRect(item.bounds);
|
|
951
|
+
return { x: r.x + r.width / 2, y: r.y + r.height / 2 };
|
|
952
|
+
}
|
|
949
953
|
function boundsAabbForRotatedItem(item) {
|
|
950
954
|
const rot = getItemRotationRad(item);
|
|
951
955
|
if (Math.abs(rot) < 1e-12 && item.bounds.width >= 0 && item.bounds.height >= 0) {
|
|
@@ -976,6 +980,7 @@ function boundsAabbForRotatedItem(item) {
|
|
|
976
980
|
}
|
|
977
981
|
|
|
978
982
|
// src/interaction/resize-handles.ts
|
|
983
|
+
var HANDLE_IDS = ["nw", "n", "ne", "e", "se", "s", "sw", "w"];
|
|
979
984
|
function getHandleWorldPosition(bounds, id) {
|
|
980
985
|
const r = normalizeRect(bounds);
|
|
981
986
|
const cx = r.x + r.width / 2;
|
|
@@ -999,6 +1004,30 @@ function getHandleWorldPosition(bounds, id) {
|
|
|
999
1004
|
return { x: r.x, y: cy };
|
|
1000
1005
|
}
|
|
1001
1006
|
}
|
|
1007
|
+
function hitTestResizeHandle(bounds, worldX, worldY, radiusWorld, rotationRad = 0) {
|
|
1008
|
+
const r = normalizeRect(bounds);
|
|
1009
|
+
const pl = worldToItemLocal(
|
|
1010
|
+
worldX,
|
|
1011
|
+
worldY,
|
|
1012
|
+
r.x,
|
|
1013
|
+
r.y,
|
|
1014
|
+
r.width,
|
|
1015
|
+
r.height,
|
|
1016
|
+
rotationRad
|
|
1017
|
+
);
|
|
1018
|
+
const localBounds2 = { x: 0, y: 0, width: r.width, height: r.height };
|
|
1019
|
+
let best = null;
|
|
1020
|
+
let bestD = radiusWorld;
|
|
1021
|
+
for (const id of HANDLE_IDS) {
|
|
1022
|
+
const p = getHandleWorldPosition(localBounds2, id);
|
|
1023
|
+
const d = Math.hypot(pl.x - p.x, pl.y - p.y);
|
|
1024
|
+
if (d <= bestD) {
|
|
1025
|
+
bestD = d;
|
|
1026
|
+
best = id;
|
|
1027
|
+
}
|
|
1028
|
+
}
|
|
1029
|
+
return best;
|
|
1030
|
+
}
|
|
1002
1031
|
function getHandleWorldPositionRotated(bounds, handle, rotationRad) {
|
|
1003
1032
|
const r = normalizeRect(bounds);
|
|
1004
1033
|
const p = getHandleWorldPosition(
|
|
@@ -1019,6 +1048,10 @@ function getRotationHandleWorldPosition(bounds, rotationRad, handleOffsetWorld)
|
|
|
1019
1048
|
rotationRad
|
|
1020
1049
|
);
|
|
1021
1050
|
}
|
|
1051
|
+
function hitTestRotateHandle(bounds, rotationRad, worldX, worldY, radiusWorld, handleOffsetWorld) {
|
|
1052
|
+
const p = getRotationHandleWorldPosition(bounds, rotationRad, handleOffsetWorld);
|
|
1053
|
+
return Math.hypot(worldX - p.x, worldY - p.y) <= radiusWorld;
|
|
1054
|
+
}
|
|
1022
1055
|
function rectFromCorners(a, b) {
|
|
1023
1056
|
const minX = Math.min(a.x, b.x);
|
|
1024
1057
|
const maxX = Math.max(a.x, b.x);
|
|
@@ -1026,6 +1059,155 @@ function rectFromCorners(a, b) {
|
|
|
1026
1059
|
const maxY = Math.max(a.y, b.y);
|
|
1027
1060
|
return { x: minX, y: minY, width: maxX - minX, height: maxY - minY };
|
|
1028
1061
|
}
|
|
1062
|
+
function clampMinSize(r, min) {
|
|
1063
|
+
const n = normalizeRect(r);
|
|
1064
|
+
return {
|
|
1065
|
+
x: n.x,
|
|
1066
|
+
y: n.y,
|
|
1067
|
+
width: Math.max(min, n.width),
|
|
1068
|
+
height: Math.max(min, n.height)
|
|
1069
|
+
};
|
|
1070
|
+
}
|
|
1071
|
+
function computeResizeBounds(bounds, handle, currentWorld) {
|
|
1072
|
+
const r = normalizeRect(bounds);
|
|
1073
|
+
const x0 = r.x;
|
|
1074
|
+
const y0 = r.y;
|
|
1075
|
+
const x1 = r.x + r.width;
|
|
1076
|
+
const y1 = r.y + r.height;
|
|
1077
|
+
const minSize = 8;
|
|
1078
|
+
switch (handle) {
|
|
1079
|
+
case "nw":
|
|
1080
|
+
return clampMinSize(rectFromCorners(currentWorld, { x: x1, y: y1 }), minSize);
|
|
1081
|
+
case "ne":
|
|
1082
|
+
return clampMinSize(rectFromCorners(currentWorld, { x: x0, y: y1 }), minSize);
|
|
1083
|
+
case "se":
|
|
1084
|
+
return clampMinSize(rectFromCorners(currentWorld, { x: x0, y: y0 }), minSize);
|
|
1085
|
+
case "sw":
|
|
1086
|
+
return clampMinSize(rectFromCorners(currentWorld, { x: x1, y: y0 }), minSize);
|
|
1087
|
+
case "n":
|
|
1088
|
+
return clampMinSize(
|
|
1089
|
+
rectFromCorners({ x: x0, y: currentWorld.y }, { x: x1, y: y1 }),
|
|
1090
|
+
minSize
|
|
1091
|
+
);
|
|
1092
|
+
case "s":
|
|
1093
|
+
return clampMinSize(
|
|
1094
|
+
rectFromCorners({ x: x0, y: y0 }, { x: x1, y: currentWorld.y }),
|
|
1095
|
+
minSize
|
|
1096
|
+
);
|
|
1097
|
+
case "e":
|
|
1098
|
+
return clampMinSize(
|
|
1099
|
+
rectFromCorners({ x: x0, y: y0 }, { x: currentWorld.x, y: y1 }),
|
|
1100
|
+
minSize
|
|
1101
|
+
);
|
|
1102
|
+
case "w":
|
|
1103
|
+
return clampMinSize(
|
|
1104
|
+
rectFromCorners({ x: currentWorld.x, y: y0 }, { x: x1, y: y1 }),
|
|
1105
|
+
minSize
|
|
1106
|
+
);
|
|
1107
|
+
default:
|
|
1108
|
+
return r;
|
|
1109
|
+
}
|
|
1110
|
+
}
|
|
1111
|
+
function computeResizeBoundsFixedAspect(bounds, handle, currentWorld, aspect) {
|
|
1112
|
+
const r = normalizeRect(bounds);
|
|
1113
|
+
const x0 = r.x;
|
|
1114
|
+
const y0 = r.y;
|
|
1115
|
+
const x1 = r.x + r.width;
|
|
1116
|
+
const y1 = r.y + r.height;
|
|
1117
|
+
const w = r.width;
|
|
1118
|
+
const h = r.height;
|
|
1119
|
+
const minSize = 8;
|
|
1120
|
+
const a = Math.max(1e-9, aspect);
|
|
1121
|
+
function cornerAspectRect(anchor, cursor) {
|
|
1122
|
+
const dx = cursor.x - anchor.x;
|
|
1123
|
+
const dy = cursor.y - anchor.y;
|
|
1124
|
+
const aw = Math.abs(dx);
|
|
1125
|
+
const ah = Math.abs(dy);
|
|
1126
|
+
let W;
|
|
1127
|
+
let H;
|
|
1128
|
+
if (aw < 1e-12 && ah < 1e-12) {
|
|
1129
|
+
W = minSize;
|
|
1130
|
+
H = minSize / a;
|
|
1131
|
+
} else if (ah < 1e-12) {
|
|
1132
|
+
W = Math.max(minSize, aw);
|
|
1133
|
+
H = W / a;
|
|
1134
|
+
} else if (aw < 1e-12) {
|
|
1135
|
+
H = Math.max(minSize, ah);
|
|
1136
|
+
W = H * a;
|
|
1137
|
+
} else if (aw / ah > a) {
|
|
1138
|
+
W = aw;
|
|
1139
|
+
H = aw / a;
|
|
1140
|
+
} else {
|
|
1141
|
+
H = ah;
|
|
1142
|
+
W = ah * a;
|
|
1143
|
+
}
|
|
1144
|
+
if (W < minSize || H < minSize) {
|
|
1145
|
+
const scale = Math.max(minSize / W, minSize / H);
|
|
1146
|
+
W *= scale;
|
|
1147
|
+
H *= scale;
|
|
1148
|
+
}
|
|
1149
|
+
const sx = Math.sign(dx) || 1;
|
|
1150
|
+
const sy = Math.sign(dy) || 1;
|
|
1151
|
+
return rectFromCorners(anchor, {
|
|
1152
|
+
x: anchor.x + sx * W,
|
|
1153
|
+
y: anchor.y + sy * H
|
|
1154
|
+
});
|
|
1155
|
+
}
|
|
1156
|
+
switch (handle) {
|
|
1157
|
+
case "se":
|
|
1158
|
+
return cornerAspectRect({ x: x0, y: y0 }, currentWorld);
|
|
1159
|
+
case "nw":
|
|
1160
|
+
return cornerAspectRect({ x: x1, y: y1 }, currentWorld);
|
|
1161
|
+
case "ne":
|
|
1162
|
+
return cornerAspectRect({ x: x0, y: y1 }, currentWorld);
|
|
1163
|
+
case "sw":
|
|
1164
|
+
return cornerAspectRect({ x: x1, y: y0 }, currentWorld);
|
|
1165
|
+
case "e": {
|
|
1166
|
+
const rawW = currentWorld.x - x0;
|
|
1167
|
+
const aw = Math.max(minSize, Math.abs(rawW));
|
|
1168
|
+
const H = aw / a;
|
|
1169
|
+
const newY = y0 + h / 2 - H / 2;
|
|
1170
|
+
const sign = Math.sign(rawW) || 1;
|
|
1171
|
+
return normalizeRect({ x: x0, y: newY, width: sign * aw, height: H });
|
|
1172
|
+
}
|
|
1173
|
+
case "w": {
|
|
1174
|
+
const rawW = x1 - currentWorld.x;
|
|
1175
|
+
const aw = Math.max(minSize, Math.abs(rawW));
|
|
1176
|
+
const H = aw / a;
|
|
1177
|
+
const newY = y0 + h / 2 - H / 2;
|
|
1178
|
+
const sign = Math.sign(rawW) || 1;
|
|
1179
|
+
return normalizeRect({
|
|
1180
|
+
x: x1 - sign * aw,
|
|
1181
|
+
y: newY,
|
|
1182
|
+
width: sign * aw,
|
|
1183
|
+
height: H
|
|
1184
|
+
});
|
|
1185
|
+
}
|
|
1186
|
+
case "n": {
|
|
1187
|
+
const rawH = y1 - currentWorld.y;
|
|
1188
|
+
const ah = Math.max(minSize, Math.abs(rawH));
|
|
1189
|
+
const W = ah * a;
|
|
1190
|
+
const newX = x0 + w / 2 - W / 2;
|
|
1191
|
+
const sign = Math.sign(rawH) || 1;
|
|
1192
|
+
return normalizeRect({
|
|
1193
|
+
x: newX,
|
|
1194
|
+
y: y1 - sign * ah,
|
|
1195
|
+
width: W,
|
|
1196
|
+
height: sign * ah
|
|
1197
|
+
});
|
|
1198
|
+
}
|
|
1199
|
+
case "s": {
|
|
1200
|
+
const rawH = currentWorld.y - y0;
|
|
1201
|
+
const ah = Math.max(minSize, Math.abs(rawH));
|
|
1202
|
+
const W = ah * a;
|
|
1203
|
+
const newX = x0 + w / 2 - W / 2;
|
|
1204
|
+
const sign = Math.sign(rawH) || 1;
|
|
1205
|
+
return normalizeRect({ x: newX, y: y0, width: W, height: sign * ah });
|
|
1206
|
+
}
|
|
1207
|
+
default:
|
|
1208
|
+
return r;
|
|
1209
|
+
}
|
|
1210
|
+
}
|
|
1029
1211
|
|
|
1030
1212
|
// src/scene/freehand-path.ts
|
|
1031
1213
|
function smoothFreehandPointsToPathD(points) {
|
|
@@ -3587,6 +3769,211 @@ function collectEraserTargetsAtWorldPoint(items, worldX, worldY, options) {
|
|
|
3587
3769
|
return ids;
|
|
3588
3770
|
}
|
|
3589
3771
|
|
|
3772
|
+
// src/interaction/mutations.ts
|
|
3773
|
+
function computeNewBoundsForResize(item, sb, handle, currentWorld) {
|
|
3774
|
+
const rot = getItemRotationRad(item);
|
|
3775
|
+
if (Math.abs(rot) < 1e-12) {
|
|
3776
|
+
if (item.toolKind === "image") {
|
|
3777
|
+
let aspect;
|
|
3778
|
+
if (item.imageIntrinsicSize) {
|
|
3779
|
+
const iw = Math.max(1e-9, item.imageIntrinsicSize.width);
|
|
3780
|
+
const ih = Math.max(1e-9, item.imageIntrinsicSize.height);
|
|
3781
|
+
aspect = iw / ih;
|
|
3782
|
+
} else if (item.imageVectorLocalSize) {
|
|
3783
|
+
const lw = Math.max(1e-9, item.imageVectorLocalSize.width);
|
|
3784
|
+
const lh = Math.max(1e-9, item.imageVectorLocalSize.height);
|
|
3785
|
+
aspect = lw / lh;
|
|
3786
|
+
}
|
|
3787
|
+
return aspect !== void 0 ? computeResizeBoundsFixedAspect(sb, handle, currentWorld, aspect) : computeResizeBounds(sb, handle, currentWorld);
|
|
3788
|
+
}
|
|
3789
|
+
return computeResizeBounds(sb, handle, currentWorld);
|
|
3790
|
+
}
|
|
3791
|
+
const local = worldToItemLocal(
|
|
3792
|
+
currentWorld.x,
|
|
3793
|
+
currentWorld.y,
|
|
3794
|
+
sb.x,
|
|
3795
|
+
sb.y,
|
|
3796
|
+
sb.width,
|
|
3797
|
+
sb.height,
|
|
3798
|
+
rot
|
|
3799
|
+
);
|
|
3800
|
+
const localBounds2 = { x: 0, y: 0, width: sb.width, height: sb.height };
|
|
3801
|
+
let nbLocal;
|
|
3802
|
+
if (item.toolKind === "image") {
|
|
3803
|
+
let aspect;
|
|
3804
|
+
if (item.imageIntrinsicSize) {
|
|
3805
|
+
const iw = Math.max(1e-9, item.imageIntrinsicSize.width);
|
|
3806
|
+
const ih = Math.max(1e-9, item.imageIntrinsicSize.height);
|
|
3807
|
+
aspect = iw / ih;
|
|
3808
|
+
} else if (item.imageVectorLocalSize) {
|
|
3809
|
+
const lw = Math.max(1e-9, item.imageVectorLocalSize.width);
|
|
3810
|
+
const lh = Math.max(1e-9, item.imageVectorLocalSize.height);
|
|
3811
|
+
aspect = lw / lh;
|
|
3812
|
+
}
|
|
3813
|
+
nbLocal = aspect !== void 0 ? computeResizeBoundsFixedAspect(localBounds2, handle, local, aspect) : computeResizeBounds(localBounds2, handle, local);
|
|
3814
|
+
} else {
|
|
3815
|
+
nbLocal = computeResizeBounds(localBounds2, handle, local);
|
|
3816
|
+
}
|
|
3817
|
+
return {
|
|
3818
|
+
x: sb.x + nbLocal.x,
|
|
3819
|
+
y: sb.y + nbLocal.y,
|
|
3820
|
+
width: nbLocal.width,
|
|
3821
|
+
height: nbLocal.height
|
|
3822
|
+
};
|
|
3823
|
+
}
|
|
3824
|
+
function applyRotationFromPointer(item, startRotation, startPointerAngleRad, pointerAngleRad) {
|
|
3825
|
+
let delta = pointerAngleRad - startPointerAngleRad;
|
|
3826
|
+
while (delta > Math.PI) {
|
|
3827
|
+
delta -= 2 * Math.PI;
|
|
3828
|
+
}
|
|
3829
|
+
while (delta < -Math.PI) {
|
|
3830
|
+
delta += 2 * Math.PI;
|
|
3831
|
+
}
|
|
3832
|
+
return { ...item, rotation: startRotation + delta };
|
|
3833
|
+
}
|
|
3834
|
+
function resizeItemByHandle(item, start, handle, currentWorld) {
|
|
3835
|
+
const sb = normalizeRect(start.bounds);
|
|
3836
|
+
const newBoundsRaw = computeNewBoundsForResize(item, sb, handle, currentWorld);
|
|
3837
|
+
const nb = normalizeRect(newBoundsRaw);
|
|
3838
|
+
const k = item.toolKind;
|
|
3839
|
+
if (k === "rect") {
|
|
3840
|
+
const style = resolveStrokeStyle(item);
|
|
3841
|
+
return {
|
|
3842
|
+
...item,
|
|
3843
|
+
x: nb.x,
|
|
3844
|
+
y: nb.y,
|
|
3845
|
+
bounds: nb,
|
|
3846
|
+
childrenSvg: buildRectSvg(nb.width, nb.height, style)
|
|
3847
|
+
};
|
|
3848
|
+
}
|
|
3849
|
+
if (k === "ellipse") {
|
|
3850
|
+
const style = resolveStrokeStyle(item);
|
|
3851
|
+
return {
|
|
3852
|
+
...item,
|
|
3853
|
+
x: nb.x,
|
|
3854
|
+
y: nb.y,
|
|
3855
|
+
bounds: nb,
|
|
3856
|
+
childrenSvg: buildEllipseSvg(nb.width, nb.height, style)
|
|
3857
|
+
};
|
|
3858
|
+
}
|
|
3859
|
+
if (k === "architectural-cloud") {
|
|
3860
|
+
const style = resolveStrokeStyle(item);
|
|
3861
|
+
return {
|
|
3862
|
+
...item,
|
|
3863
|
+
x: nb.x,
|
|
3864
|
+
y: nb.y,
|
|
3865
|
+
bounds: nb,
|
|
3866
|
+
childrenSvg: buildArchitecturalCloudSvg(nb.width, nb.height, style)
|
|
3867
|
+
};
|
|
3868
|
+
}
|
|
3869
|
+
if (k === "text" && item.text !== void 0) {
|
|
3870
|
+
const sfw = Math.max(sb.width, 1e-6);
|
|
3871
|
+
const sfh = Math.max(sb.height, 1e-6);
|
|
3872
|
+
const baseFs = item.textFontSize ?? DEFAULT_TEXT_FONT_SIZE;
|
|
3873
|
+
const areaRatio = nb.width * nb.height / (sfw * sfh);
|
|
3874
|
+
const scale = Math.sqrt(Math.max(areaRatio, 1e-12));
|
|
3875
|
+
const nextFs = Math.min(256, Math.max(6, baseFs * scale));
|
|
3876
|
+
return rebuildItemSvg({
|
|
3877
|
+
...item,
|
|
3878
|
+
x: nb.x,
|
|
3879
|
+
y: nb.y,
|
|
3880
|
+
bounds: nb,
|
|
3881
|
+
textFixedBounds: true,
|
|
3882
|
+
textFontSize: nextFs
|
|
3883
|
+
});
|
|
3884
|
+
}
|
|
3885
|
+
if (k === "image") {
|
|
3886
|
+
if (item.imageRasterHref && item.imageIntrinsicSize) {
|
|
3887
|
+
return {
|
|
3888
|
+
...item,
|
|
3889
|
+
x: nb.x,
|
|
3890
|
+
y: nb.y,
|
|
3891
|
+
bounds: nb,
|
|
3892
|
+
childrenSvg: buildRasterImageChildrenSvg(
|
|
3893
|
+
item.imageRasterHref,
|
|
3894
|
+
item.imageIntrinsicSize,
|
|
3895
|
+
nb
|
|
3896
|
+
)
|
|
3897
|
+
};
|
|
3898
|
+
}
|
|
3899
|
+
if (item.imageVectorInnerSvg && item.imageVectorLocalSize) {
|
|
3900
|
+
const lw = Math.max(1e-6, item.imageVectorLocalSize.width);
|
|
3901
|
+
const lh = Math.max(1e-6, item.imageVectorLocalSize.height);
|
|
3902
|
+
const arB = nb.width / Math.max(1e-9, nb.height);
|
|
3903
|
+
const arI = lw / lh;
|
|
3904
|
+
let childrenSvg;
|
|
3905
|
+
if (Math.abs(arB - arI) < 1e-3) {
|
|
3906
|
+
const s = nb.width / lw;
|
|
3907
|
+
childrenSvg = `<g transform="scale(${s})">${item.imageVectorInnerSvg}</g>`;
|
|
3908
|
+
} else {
|
|
3909
|
+
const s = Math.min(nb.width / lw, nb.height / lh);
|
|
3910
|
+
const tx = (nb.width - lw * s) / 2;
|
|
3911
|
+
const ty = (nb.height - lh * s) / 2;
|
|
3912
|
+
childrenSvg = `<g transform="translate(${tx}, ${ty}) scale(${s})">${item.imageVectorInnerSvg}</g>`;
|
|
3913
|
+
}
|
|
3914
|
+
return {
|
|
3915
|
+
...item,
|
|
3916
|
+
x: nb.x,
|
|
3917
|
+
y: nb.y,
|
|
3918
|
+
bounds: nb,
|
|
3919
|
+
childrenSvg
|
|
3920
|
+
};
|
|
3921
|
+
}
|
|
3922
|
+
}
|
|
3923
|
+
if ((k === "line" || k === "arrow") && start.line) {
|
|
3924
|
+
const sfw = Math.max(sb.width, 1e-6);
|
|
3925
|
+
const sfh = Math.max(sb.height, 1e-6);
|
|
3926
|
+
const f = start.line;
|
|
3927
|
+
const u1 = f.x1 / sfw;
|
|
3928
|
+
const v1 = f.y1 / sfh;
|
|
3929
|
+
const u2 = f.x2 / sfw;
|
|
3930
|
+
const v2 = f.y2 / sfh;
|
|
3931
|
+
const newLine = {
|
|
3932
|
+
x1: u1 * nb.width,
|
|
3933
|
+
y1: v1 * nb.height,
|
|
3934
|
+
x2: u2 * nb.width,
|
|
3935
|
+
y2: v2 * nb.height
|
|
3936
|
+
};
|
|
3937
|
+
const style = resolveStrokeStyle(item);
|
|
3938
|
+
const childrenSvg = k === "arrow" ? buildArrowSvg(item.id, newLine, style) : buildLineSvg(newLine, style);
|
|
3939
|
+
return {
|
|
3940
|
+
...item,
|
|
3941
|
+
x: nb.x,
|
|
3942
|
+
y: nb.y,
|
|
3943
|
+
bounds: nb,
|
|
3944
|
+
line: newLine,
|
|
3945
|
+
childrenSvg
|
|
3946
|
+
};
|
|
3947
|
+
}
|
|
3948
|
+
if ((k === "draw" || k === "pencil" || k === "brush" || k === "marker") && item.pathPointsLocal && item.pathPointsLocal.length > 0) {
|
|
3949
|
+
const sfw = Math.max(sb.width, 1e-6);
|
|
3950
|
+
const sfh = Math.max(sb.height, 1e-6);
|
|
3951
|
+
const sx = nb.width / sfw;
|
|
3952
|
+
const sy = nb.height / sfh;
|
|
3953
|
+
const scaledPoints = item.pathPointsLocal.map((p) => ({
|
|
3954
|
+
x: p.x * sx,
|
|
3955
|
+
y: p.y * sy,
|
|
3956
|
+
...p.pressure != null ? { pressure: p.pressure } : {}
|
|
3957
|
+
}));
|
|
3958
|
+
return rebuildItemSvg({
|
|
3959
|
+
...item,
|
|
3960
|
+
x: nb.x,
|
|
3961
|
+
y: nb.y,
|
|
3962
|
+
bounds: nb,
|
|
3963
|
+
pathPointsLocal: scaledPoints
|
|
3964
|
+
});
|
|
3965
|
+
}
|
|
3966
|
+
if (k === "custom" && item.customIntrinsicSize && item.customInnerSvg) {
|
|
3967
|
+
return rebuildItemSvg({
|
|
3968
|
+
...item,
|
|
3969
|
+
x: nb.x,
|
|
3970
|
+
y: nb.y,
|
|
3971
|
+
bounds: nb
|
|
3972
|
+
});
|
|
3973
|
+
}
|
|
3974
|
+
return { ...item, x: nb.x, y: nb.y, bounds: nb };
|
|
3975
|
+
}
|
|
3976
|
+
|
|
3590
3977
|
// src/native/native-tool-cursors.ts
|
|
3591
3978
|
var ICON_SIZE = 24;
|
|
3592
3979
|
var CENTER_HOTSPOT = { x: 12, y: 12 };
|
|
@@ -3612,6 +3999,72 @@ function nativeCursorForVectorToolId(toolId) {
|
|
|
3612
3999
|
return null;
|
|
3613
4000
|
}
|
|
3614
4001
|
}
|
|
4002
|
+
function nativeCrosshairToolCursor() {
|
|
4003
|
+
return { kind: "crosshair", size: ICON_SIZE, hotspot: CENTER_HOTSPOT };
|
|
4004
|
+
}
|
|
4005
|
+
function nativeFallbackToolCursorPoint(size) {
|
|
4006
|
+
if (size.width <= 0 || size.height <= 0) return null;
|
|
4007
|
+
return { x: size.width / 2, y: size.height / 2 };
|
|
4008
|
+
}
|
|
4009
|
+
|
|
4010
|
+
// src/native/native-vector-interactions.ts
|
|
4011
|
+
function supportsNativeResizeHandles(item) {
|
|
4012
|
+
const k = item?.toolKind;
|
|
4013
|
+
if (k === "rect" || k === "ellipse" || k === "architectural-cloud" || k === "line" || k === "arrow" || k === "image" || k === "text") {
|
|
4014
|
+
return true;
|
|
4015
|
+
}
|
|
4016
|
+
if ((k === "draw" || k === "pencil" || k === "brush" || k === "marker") && item?.pathPointsLocal && item.pathPointsLocal.length > 0) {
|
|
4017
|
+
return true;
|
|
4018
|
+
}
|
|
4019
|
+
return k === "custom" && !!item?.customIntrinsicSize && !!item?.customInnerSvg;
|
|
4020
|
+
}
|
|
4021
|
+
function hitTestNativeSelectionHandle({
|
|
4022
|
+
selectedItem,
|
|
4023
|
+
selectedCount,
|
|
4024
|
+
worldPoint,
|
|
4025
|
+
zoom
|
|
4026
|
+
}) {
|
|
4027
|
+
if (selectedCount !== 1) return null;
|
|
4028
|
+
if (!selectedItem || selectedItem.locked) return null;
|
|
4029
|
+
if (!supportsNativeResizeHandles(selectedItem)) return null;
|
|
4030
|
+
const bounds = normalizeRect(selectedItem.bounds);
|
|
4031
|
+
const rotation = selectedItem.rotation ?? 0;
|
|
4032
|
+
const handleRadiusWorld = 6 / Math.max(zoom, 1e-9);
|
|
4033
|
+
const rotateOffsetWorld = 24 / Math.max(zoom, 1e-9);
|
|
4034
|
+
if (hitTestRotateHandle(
|
|
4035
|
+
bounds,
|
|
4036
|
+
rotation,
|
|
4037
|
+
worldPoint.x,
|
|
4038
|
+
worldPoint.y,
|
|
4039
|
+
handleRadiusWorld,
|
|
4040
|
+
rotateOffsetWorld
|
|
4041
|
+
)) {
|
|
4042
|
+
return { kind: "rotate" };
|
|
4043
|
+
}
|
|
4044
|
+
const handle = hitTestResizeHandle(
|
|
4045
|
+
bounds,
|
|
4046
|
+
worldPoint.x,
|
|
4047
|
+
worldPoint.y,
|
|
4048
|
+
handleRadiusWorld,
|
|
4049
|
+
rotation
|
|
4050
|
+
);
|
|
4051
|
+
return handle ? { kind: "resize", handle } : null;
|
|
4052
|
+
}
|
|
4053
|
+
function resolveNativeCustomPlacement(toolId, customPlacement, customPlacements) {
|
|
4054
|
+
if (customPlacement?.toolId === toolId) return customPlacement;
|
|
4055
|
+
return customPlacements?.find((placement) => placement.toolId === toolId) ?? null;
|
|
4056
|
+
}
|
|
4057
|
+
function nativeRotationDragStart(input) {
|
|
4058
|
+
const pivotWorld = itemPivotWorld(input.item);
|
|
4059
|
+
return {
|
|
4060
|
+
pivotWorld,
|
|
4061
|
+
startPointerAngleRad: Math.atan2(
|
|
4062
|
+
input.worldPoint.y - pivotWorld.y,
|
|
4063
|
+
input.worldPoint.x - pivotWorld.x
|
|
4064
|
+
),
|
|
4065
|
+
startRotation: input.item.rotation ?? 0
|
|
4066
|
+
};
|
|
4067
|
+
}
|
|
3615
4068
|
var MIN_PLACE_SIZE = 8;
|
|
3616
4069
|
var MIN_ARROW_DRAG_PX = 8;
|
|
3617
4070
|
var TAP_PX = 20;
|
|
@@ -3626,16 +4079,6 @@ function isPlacementTool(toolId) {
|
|
|
3626
4079
|
function isDefaultMarkerToolStyle(style) {
|
|
3627
4080
|
return style.stroke === MARKER_TOOL_STYLE.stroke && style.strokeWidth === MARKER_TOOL_STYLE.strokeWidth && style.strokeOpacity === MARKER_TOOL_STYLE.strokeOpacity;
|
|
3628
4081
|
}
|
|
3629
|
-
function supportsNativeResizeHandles(item) {
|
|
3630
|
-
const k = item?.toolKind;
|
|
3631
|
-
if (k === "rect" || k === "ellipse" || k === "architectural-cloud" || k === "line" || k === "arrow" || k === "image" || k === "text") {
|
|
3632
|
-
return true;
|
|
3633
|
-
}
|
|
3634
|
-
if ((k === "draw" || k === "pencil" || k === "brush" || k === "marker") && item?.pathPointsLocal && item.pathPointsLocal.length > 0) {
|
|
3635
|
-
return true;
|
|
3636
|
-
}
|
|
3637
|
-
return k === "custom" && !!item?.customIntrinsicSize && !!item?.customInnerSvg;
|
|
3638
|
-
}
|
|
3639
4082
|
function placementPreviewForTool(toolId, start, end) {
|
|
3640
4083
|
if (toolId === "rect" || toolId === "ellipse" || toolId === "architectural-cloud") {
|
|
3641
4084
|
return { kind: toolId, rect: rectFromCorners(start, end) };
|
|
@@ -3703,7 +4146,11 @@ var NativeVectorViewport = react.forwardRef(function NativeVectorViewport2({
|
|
|
3703
4146
|
onSelectionChange,
|
|
3704
4147
|
onItemsChange,
|
|
3705
4148
|
onToolChangeRequest,
|
|
4149
|
+
onWorldPointerDown,
|
|
3706
4150
|
onCameraChange,
|
|
4151
|
+
customPlacement,
|
|
4152
|
+
customPlacements = [],
|
|
4153
|
+
customCrosshairToolIds = [],
|
|
3707
4154
|
toolbar,
|
|
3708
4155
|
showStyleInspector = false,
|
|
3709
4156
|
styleInspectorPlacement = "bottom"
|
|
@@ -3716,10 +4163,18 @@ var NativeVectorViewport = react.forwardRef(function NativeVectorViewport2({
|
|
|
3716
4163
|
toolLockedRef.current = toolLocked;
|
|
3717
4164
|
const onToolChangeRequestRef = react.useRef(onToolChangeRequest);
|
|
3718
4165
|
onToolChangeRequestRef.current = onToolChangeRequest;
|
|
4166
|
+
const onWorldPointerDownRef = react.useRef(onWorldPointerDown);
|
|
4167
|
+
onWorldPointerDownRef.current = onWorldPointerDown;
|
|
3719
4168
|
const onCameraChangeRef = react.useRef(onCameraChange);
|
|
3720
4169
|
onCameraChangeRef.current = onCameraChange;
|
|
3721
4170
|
const onItemsChangeRef = react.useRef(onItemsChange);
|
|
3722
4171
|
onItemsChangeRef.current = onItemsChange;
|
|
4172
|
+
const customPlacementRef = react.useRef(customPlacement);
|
|
4173
|
+
customPlacementRef.current = customPlacement;
|
|
4174
|
+
const customPlacementsRef = react.useRef(customPlacements);
|
|
4175
|
+
customPlacementsRef.current = customPlacements;
|
|
4176
|
+
const customCrosshairToolIdsRef = react.useRef(customCrosshairToolIds);
|
|
4177
|
+
customCrosshairToolIdsRef.current = customCrosshairToolIds;
|
|
3723
4178
|
const onSelectionChangeRef = react.useRef(onSelectionChange);
|
|
3724
4179
|
onSelectionChangeRef.current = onSelectionChange;
|
|
3725
4180
|
const itemsRef = react.useRef(items);
|
|
@@ -3827,21 +4282,60 @@ var NativeVectorViewport = react.forwardRef(function NativeVectorViewport2({
|
|
|
3827
4282
|
setCameraTick((n) => n + 1);
|
|
3828
4283
|
onCameraChangeRef.current?.();
|
|
3829
4284
|
}, []);
|
|
3830
|
-
const
|
|
3831
|
-
const
|
|
3832
|
-
|
|
4285
|
+
const cursorForToolId = react.useCallback((nextToolId) => {
|
|
4286
|
+
const builtInCursor = nativeCursorForVectorToolId(nextToolId);
|
|
4287
|
+
if (builtInCursor) return builtInCursor;
|
|
4288
|
+
return customCrosshairToolIdsRef.current.includes(nextToolId) ? nativeCrosshairToolCursor() : null;
|
|
3833
4289
|
}, []);
|
|
4290
|
+
const onLayout = react.useCallback(
|
|
4291
|
+
(e) => {
|
|
4292
|
+
const { width, height } = e.nativeEvent.layout;
|
|
4293
|
+
const nextSize = { width, height };
|
|
4294
|
+
setSize(nextSize);
|
|
4295
|
+
if (!interactive) {
|
|
4296
|
+
setToolCursorPoint(null);
|
|
4297
|
+
return;
|
|
4298
|
+
}
|
|
4299
|
+
if (!cursorForToolId(toolIdRef.current)) {
|
|
4300
|
+
setToolCursorPoint(null);
|
|
4301
|
+
return;
|
|
4302
|
+
}
|
|
4303
|
+
setToolCursorPoint(
|
|
4304
|
+
(current) => current ?? nativeFallbackToolCursorPoint(nextSize)
|
|
4305
|
+
);
|
|
4306
|
+
},
|
|
4307
|
+
[cursorForToolId, interactive]
|
|
4308
|
+
);
|
|
3834
4309
|
const updateToolCursorPoint = react.useCallback(
|
|
3835
4310
|
(point) => {
|
|
3836
4311
|
if (!interactive) return;
|
|
3837
|
-
if (!
|
|
4312
|
+
if (!cursorForToolId(toolIdRef.current)) return;
|
|
3838
4313
|
setToolCursorPoint(point);
|
|
3839
4314
|
},
|
|
3840
|
-
[interactive]
|
|
4315
|
+
[cursorForToolId, interactive]
|
|
3841
4316
|
);
|
|
3842
4317
|
const hideToolCursor = react.useCallback(() => {
|
|
3843
4318
|
setToolCursorPoint(null);
|
|
3844
4319
|
}, []);
|
|
4320
|
+
const showFallbackToolCursor = react.useCallback(
|
|
4321
|
+
(nextToolId) => {
|
|
4322
|
+
if (!interactive) {
|
|
4323
|
+
setToolCursorPoint(null);
|
|
4324
|
+
return;
|
|
4325
|
+
}
|
|
4326
|
+
if (!cursorForToolId(nextToolId)) {
|
|
4327
|
+
setToolCursorPoint(null);
|
|
4328
|
+
return;
|
|
4329
|
+
}
|
|
4330
|
+
setToolCursorPoint(
|
|
4331
|
+
(current) => current ?? nativeFallbackToolCursorPoint(size)
|
|
4332
|
+
);
|
|
4333
|
+
},
|
|
4334
|
+
[cursorForToolId, interactive, size]
|
|
4335
|
+
);
|
|
4336
|
+
react.useEffect(() => {
|
|
4337
|
+
showFallbackToolCursor(toolId);
|
|
4338
|
+
}, [showFallbackToolCursor, toolId]);
|
|
3845
4339
|
const handlePointerMove = react.useCallback(
|
|
3846
4340
|
(event) => {
|
|
3847
4341
|
updateToolCursorPoint(screenPointFromPointerEvent(event));
|
|
@@ -3889,6 +4383,40 @@ var NativeVectorViewport = react.forwardRef(function NativeVectorViewport2({
|
|
|
3889
4383
|
return;
|
|
3890
4384
|
}
|
|
3891
4385
|
if (tool === "select") {
|
|
4386
|
+
const currentSelectedIds = selectedIdsRef.current;
|
|
4387
|
+
const selectedItem = currentSelectedIds.length === 1 ? itemsRef.current.find((item) => item.id === currentSelectedIds[0]) : void 0;
|
|
4388
|
+
const selectionHandle = hitTestNativeSelectionHandle({
|
|
4389
|
+
selectedItem,
|
|
4390
|
+
selectedCount: currentSelectedIds.length,
|
|
4391
|
+
worldPoint: { x: worldX, y: worldY },
|
|
4392
|
+
zoom: cam.zoom
|
|
4393
|
+
});
|
|
4394
|
+
if (selectionHandle && selectedItem) {
|
|
4395
|
+
if (selectionHandle.kind === "rotate") {
|
|
4396
|
+
const rotationStart = nativeRotationDragStart({
|
|
4397
|
+
item: selectedItem,
|
|
4398
|
+
worldPoint: { x: worldX, y: worldY }
|
|
4399
|
+
});
|
|
4400
|
+
dragStateRef.current = {
|
|
4401
|
+
kind: "rotate",
|
|
4402
|
+
id: selectedItem.id,
|
|
4403
|
+
snapshot: selectedItem,
|
|
4404
|
+
...rotationStart
|
|
4405
|
+
};
|
|
4406
|
+
return;
|
|
4407
|
+
}
|
|
4408
|
+
dragStateRef.current = {
|
|
4409
|
+
kind: "resize",
|
|
4410
|
+
id: selectedItem.id,
|
|
4411
|
+
handle: selectionHandle.handle,
|
|
4412
|
+
snapshot: selectedItem,
|
|
4413
|
+
start: {
|
|
4414
|
+
bounds: selectedItem.bounds,
|
|
4415
|
+
line: selectedItem.line
|
|
4416
|
+
}
|
|
4417
|
+
};
|
|
4418
|
+
return;
|
|
4419
|
+
}
|
|
3892
4420
|
const hit = hitTestWorldPoint(itemsRef.current, worldX, worldY, {
|
|
3893
4421
|
lineHitWorld: 10 / cam.zoom,
|
|
3894
4422
|
ignoreLocked: true
|
|
@@ -3981,6 +4509,25 @@ var NativeVectorViewport = react.forwardRef(function NativeVectorViewport2({
|
|
|
3981
4509
|
);
|
|
3982
4510
|
return;
|
|
3983
4511
|
}
|
|
4512
|
+
const customPlacement2 = resolveNativeCustomPlacement(
|
|
4513
|
+
tool,
|
|
4514
|
+
customPlacementRef.current,
|
|
4515
|
+
customPlacementsRef.current
|
|
4516
|
+
);
|
|
4517
|
+
if (customPlacement2) {
|
|
4518
|
+
dragStateRef.current = {
|
|
4519
|
+
kind: "custom-place",
|
|
4520
|
+
tool,
|
|
4521
|
+
placement: customPlacement2,
|
|
4522
|
+
startWorld: { x: worldX, y: worldY },
|
|
4523
|
+
startScreen: { x: sx, y: sy }
|
|
4524
|
+
};
|
|
4525
|
+
setPlacementPreview({
|
|
4526
|
+
kind: "rect",
|
|
4527
|
+
rect: { x: worldX, y: worldY, width: 0, height: 0 }
|
|
4528
|
+
});
|
|
4529
|
+
return;
|
|
4530
|
+
}
|
|
3984
4531
|
if (tool === "note" || tool === "text") {
|
|
3985
4532
|
dragStateRef.current = {
|
|
3986
4533
|
kind: "tap",
|
|
@@ -3990,6 +4537,18 @@ var NativeVectorViewport = react.forwardRef(function NativeVectorViewport2({
|
|
|
3990
4537
|
};
|
|
3991
4538
|
return;
|
|
3992
4539
|
}
|
|
4540
|
+
const handleWorldPointerDown = onWorldPointerDownRef.current;
|
|
4541
|
+
if (handleWorldPointerDown) {
|
|
4542
|
+
handleWorldPointerDown({
|
|
4543
|
+
toolId: tool,
|
|
4544
|
+
worldX,
|
|
4545
|
+
worldY,
|
|
4546
|
+
screenX: sx,
|
|
4547
|
+
screenY: sy
|
|
4548
|
+
});
|
|
4549
|
+
requestSelectToolAfterUse();
|
|
4550
|
+
return;
|
|
4551
|
+
}
|
|
3993
4552
|
dragStateRef.current = { kind: "pan" };
|
|
3994
4553
|
},
|
|
3995
4554
|
onPanResponderMove: (evt) => {
|
|
@@ -4085,6 +4644,36 @@ var NativeVectorViewport = react.forwardRef(function NativeVectorViewport2({
|
|
|
4085
4644
|
change(nextList);
|
|
4086
4645
|
return;
|
|
4087
4646
|
}
|
|
4647
|
+
if (st.kind === "rotate") {
|
|
4648
|
+
const change = onItemsChangeRef.current;
|
|
4649
|
+
if (!change) return;
|
|
4650
|
+
const angle = Math.atan2(
|
|
4651
|
+
worldY - st.pivotWorld.y,
|
|
4652
|
+
worldX - st.pivotWorld.x
|
|
4653
|
+
);
|
|
4654
|
+
const next = applyRotationFromPointer(
|
|
4655
|
+
st.snapshot,
|
|
4656
|
+
st.startRotation,
|
|
4657
|
+
st.startPointerAngleRad,
|
|
4658
|
+
angle
|
|
4659
|
+
);
|
|
4660
|
+
change(
|
|
4661
|
+
itemsRef.current.map((item) => item.id === st.id ? next : item)
|
|
4662
|
+
);
|
|
4663
|
+
return;
|
|
4664
|
+
}
|
|
4665
|
+
if (st.kind === "resize") {
|
|
4666
|
+
const change = onItemsChangeRef.current;
|
|
4667
|
+
if (!change) return;
|
|
4668
|
+
const next = resizeItemByHandle(st.snapshot, st.start, st.handle, {
|
|
4669
|
+
x: worldX,
|
|
4670
|
+
y: worldY
|
|
4671
|
+
});
|
|
4672
|
+
change(
|
|
4673
|
+
itemsRef.current.map((item) => item.id === st.id ? next : item)
|
|
4674
|
+
);
|
|
4675
|
+
return;
|
|
4676
|
+
}
|
|
4088
4677
|
if (st.kind === "marquee") {
|
|
4089
4678
|
const a = st.startWorld;
|
|
4090
4679
|
const b = { x: worldX, y: worldY };
|
|
@@ -4123,11 +4712,21 @@ var NativeVectorViewport = react.forwardRef(function NativeVectorViewport2({
|
|
|
4123
4712
|
);
|
|
4124
4713
|
return;
|
|
4125
4714
|
}
|
|
4715
|
+
if (st.kind === "custom-place") {
|
|
4716
|
+
setPlacementPreview({
|
|
4717
|
+
kind: "rect",
|
|
4718
|
+
rect: rectFromCorners(st.startWorld, { x: worldX, y: worldY })
|
|
4719
|
+
});
|
|
4720
|
+
return;
|
|
4721
|
+
}
|
|
4126
4722
|
},
|
|
4127
4723
|
onPanResponderRelease: (evt) => {
|
|
4128
4724
|
lastPinchDist.current = null;
|
|
4129
4725
|
lastPanPoint.current = null;
|
|
4130
|
-
|
|
4726
|
+
updateToolCursorPoint({
|
|
4727
|
+
x: evt.nativeEvent.locationX,
|
|
4728
|
+
y: evt.nativeEvent.locationY
|
|
4729
|
+
});
|
|
4131
4730
|
const st = dragStateRef.current;
|
|
4132
4731
|
if (st.kind === "draw") {
|
|
4133
4732
|
dragStateRef.current = { kind: "idle" };
|
|
@@ -4163,6 +4762,10 @@ var NativeVectorViewport = react.forwardRef(function NativeVectorViewport2({
|
|
|
4163
4762
|
dragStateRef.current = { kind: "idle" };
|
|
4164
4763
|
return;
|
|
4165
4764
|
}
|
|
4765
|
+
if (st.kind === "resize" || st.kind === "rotate") {
|
|
4766
|
+
dragStateRef.current = { kind: "idle" };
|
|
4767
|
+
return;
|
|
4768
|
+
}
|
|
4166
4769
|
if (st.kind === "marquee") {
|
|
4167
4770
|
dragStateRef.current = { kind: "idle" };
|
|
4168
4771
|
setPlacementPreview(null);
|
|
@@ -4260,6 +4863,34 @@ var NativeVectorViewport = react.forwardRef(function NativeVectorViewport2({
|
|
|
4260
4863
|
requestSelectToolAfterUse();
|
|
4261
4864
|
return;
|
|
4262
4865
|
}
|
|
4866
|
+
if (st.kind === "custom-place") {
|
|
4867
|
+
dragStateRef.current = { kind: "idle" };
|
|
4868
|
+
setPlacementPreview(null);
|
|
4869
|
+
const change = onItemsChangeRef.current;
|
|
4870
|
+
if (!change) return;
|
|
4871
|
+
const { worldX, worldY } = screenToWorld(
|
|
4872
|
+
evt.nativeEvent.locationX,
|
|
4873
|
+
evt.nativeEvent.locationY
|
|
4874
|
+
);
|
|
4875
|
+
const center = {
|
|
4876
|
+
x: (st.startWorld.x + worldX) / 2,
|
|
4877
|
+
y: (st.startWorld.y + worldY) / 2
|
|
4878
|
+
};
|
|
4879
|
+
const raw = rectFromCorners(st.startWorld, { x: worldX, y: worldY });
|
|
4880
|
+
const normalized = normalizeRect(raw);
|
|
4881
|
+
const bounds = normalized.width < MIN_PLACE_SIZE || normalized.height < MIN_PLACE_SIZE ? {
|
|
4882
|
+
x: center.x - 60,
|
|
4883
|
+
y: center.y - 40,
|
|
4884
|
+
width: 120,
|
|
4885
|
+
height: 80
|
|
4886
|
+
} : normalized;
|
|
4887
|
+
const id = createShapeId();
|
|
4888
|
+
const item = st.placement.createItem({ id, bounds });
|
|
4889
|
+
change([...itemsRef.current, item]);
|
|
4890
|
+
onSelectionChangeRef.current?.([id]);
|
|
4891
|
+
requestSelectToolAfterUse();
|
|
4892
|
+
return;
|
|
4893
|
+
}
|
|
4263
4894
|
if (st.kind === "tap") {
|
|
4264
4895
|
dragStateRef.current = { kind: "idle" };
|
|
4265
4896
|
const screenDx = evt.nativeEvent.locationX - st.startScreen.x;
|
|
@@ -4351,7 +4982,7 @@ var NativeVectorViewport = react.forwardRef(function NativeVectorViewport2({
|
|
|
4351
4982
|
[requestRender, size]
|
|
4352
4983
|
);
|
|
4353
4984
|
const activeStyleToolId = toolId === "draw" || toolId === "marker" ? toolId : null;
|
|
4354
|
-
const activeToolCursor =
|
|
4985
|
+
const activeToolCursor = cursorForToolId(toolId);
|
|
4355
4986
|
const toolCursor = activeToolCursor && toolCursorPoint ? { cursor: activeToolCursor, point: toolCursorPoint } : null;
|
|
4356
4987
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
4357
4988
|
reactNative.View,
|