canvu-react 0.4.18 → 0.4.19
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 +151 -146
- package/dist/native.cjs.map +1 -1
- package/dist/native.js +151 -146
- package/dist/native.js.map +1 -1
- package/package.json +1 -1
package/dist/native.js
CHANGED
|
@@ -4002,6 +4002,7 @@ function nativeFallbackToolCursorPoint(size) {
|
|
|
4002
4002
|
}
|
|
4003
4003
|
|
|
4004
4004
|
// src/native/native-vector-interactions.ts
|
|
4005
|
+
var NATIVE_SELECTION_HANDLE_HIT_RADIUS_PX = 24;
|
|
4005
4006
|
function supportsNativeResizeHandles(item) {
|
|
4006
4007
|
const k = item?.toolKind;
|
|
4007
4008
|
if (k === "rect" || k === "ellipse" || k === "architectural-cloud" || k === "line" || k === "arrow" || k === "image" || k === "text") {
|
|
@@ -4023,7 +4024,7 @@ function hitTestNativeSelectionHandle({
|
|
|
4023
4024
|
if (!supportsNativeResizeHandles(selectedItem)) return null;
|
|
4024
4025
|
const bounds = normalizeRect(selectedItem.bounds);
|
|
4025
4026
|
const rotation = selectedItem.rotation ?? 0;
|
|
4026
|
-
const handleRadiusWorld =
|
|
4027
|
+
const handleRadiusWorld = NATIVE_SELECTION_HANDLE_HIT_RADIUS_PX / Math.max(zoom, 1e-9);
|
|
4027
4028
|
const rotateOffsetWorld = 24 / Math.max(zoom, 1e-9);
|
|
4028
4029
|
if (hitTestRotateHandle(
|
|
4029
4030
|
bounds,
|
|
@@ -4330,12 +4331,6 @@ var NativeVectorViewport = forwardRef(function NativeVectorViewport2({
|
|
|
4330
4331
|
useEffect(() => {
|
|
4331
4332
|
showFallbackToolCursor(toolId);
|
|
4332
4333
|
}, [showFallbackToolCursor, toolId]);
|
|
4333
|
-
const handlePointerMove = useCallback(
|
|
4334
|
-
(event) => {
|
|
4335
|
-
updateToolCursorPoint(screenPointFromPointerEvent(event));
|
|
4336
|
-
},
|
|
4337
|
-
[updateToolCursorPoint]
|
|
4338
|
-
);
|
|
4339
4334
|
const selectedItems = useMemo(
|
|
4340
4335
|
() => items.filter((it) => selectedIds.includes(it.id)),
|
|
4341
4336
|
[items, selectedIds]
|
|
@@ -4348,6 +4343,153 @@ var NativeVectorViewport = forwardRef(function NativeVectorViewport2({
|
|
|
4348
4343
|
const showResizeHandles = interactive && selectedItems.length === 1 && !selectedItems[0]?.locked && supportsNativeResizeHandles(selectedItems[0]);
|
|
4349
4344
|
const lastPinchDist = useRef(null);
|
|
4350
4345
|
const lastPanPoint = useRef(null);
|
|
4346
|
+
const applyDragMoveAtScreenPoint = useCallback(
|
|
4347
|
+
(point, pagePoint) => {
|
|
4348
|
+
const cam = cameraRef.current;
|
|
4349
|
+
if (!cam) return;
|
|
4350
|
+
updateToolCursorPoint(point);
|
|
4351
|
+
const { worldX, worldY } = screenToWorld(point.x, point.y);
|
|
4352
|
+
const st = dragStateRef.current;
|
|
4353
|
+
if (st.kind === "pan") {
|
|
4354
|
+
const current = pagePoint ?? point;
|
|
4355
|
+
if (lastPanPoint.current) {
|
|
4356
|
+
const dx = current.x - lastPanPoint.current.x;
|
|
4357
|
+
const dy = current.y - lastPanPoint.current.y;
|
|
4358
|
+
cam.x += dx;
|
|
4359
|
+
cam.y += dy;
|
|
4360
|
+
requestRender();
|
|
4361
|
+
}
|
|
4362
|
+
lastPanPoint.current = current;
|
|
4363
|
+
return;
|
|
4364
|
+
}
|
|
4365
|
+
lastPanPoint.current = null;
|
|
4366
|
+
if (st.kind === "draw") {
|
|
4367
|
+
const pts = st.points;
|
|
4368
|
+
const last = pts[pts.length - 1];
|
|
4369
|
+
const dx = worldX - (last?.x ?? worldX);
|
|
4370
|
+
const dy = worldY - (last?.y ?? worldY);
|
|
4371
|
+
const shouldAppendPoint = Math.hypot(dx, dy) > 0.5 / cam.zoom;
|
|
4372
|
+
if (shouldAppendPoint) {
|
|
4373
|
+
pts.push({ x: worldX, y: worldY });
|
|
4374
|
+
}
|
|
4375
|
+
if (st.tool === "laser") {
|
|
4376
|
+
if (shouldAppendPoint) {
|
|
4377
|
+
setLaserTrail((prev) => [
|
|
4378
|
+
...prev,
|
|
4379
|
+
{ x: worldX, y: worldY, t: Date.now() }
|
|
4380
|
+
]);
|
|
4381
|
+
}
|
|
4382
|
+
return;
|
|
4383
|
+
}
|
|
4384
|
+
setPlacementPreview({
|
|
4385
|
+
kind: "stroke",
|
|
4386
|
+
tool: st.tool,
|
|
4387
|
+
points: [...pts],
|
|
4388
|
+
style: { ...strokeStyleRef.current }
|
|
4389
|
+
});
|
|
4390
|
+
return;
|
|
4391
|
+
}
|
|
4392
|
+
if (st.kind === "move") {
|
|
4393
|
+
const dx = worldX - st.startWorld.x;
|
|
4394
|
+
const dy = worldY - st.startWorld.y;
|
|
4395
|
+
const change = onItemsChangeRef.current;
|
|
4396
|
+
if (!change) return;
|
|
4397
|
+
const nextList = itemsRef.current.map((it) => {
|
|
4398
|
+
const snap = st.snapshots[it.id];
|
|
4399
|
+
if (!snap) return it;
|
|
4400
|
+
return {
|
|
4401
|
+
...snap,
|
|
4402
|
+
x: snap.x + dx,
|
|
4403
|
+
y: snap.y + dy,
|
|
4404
|
+
bounds: {
|
|
4405
|
+
...snap.bounds,
|
|
4406
|
+
x: snap.bounds.x + dx,
|
|
4407
|
+
y: snap.bounds.y + dy
|
|
4408
|
+
}
|
|
4409
|
+
};
|
|
4410
|
+
});
|
|
4411
|
+
change(nextList);
|
|
4412
|
+
return;
|
|
4413
|
+
}
|
|
4414
|
+
if (st.kind === "rotate") {
|
|
4415
|
+
const change = onItemsChangeRef.current;
|
|
4416
|
+
if (!change) return;
|
|
4417
|
+
const angle = Math.atan2(worldY - st.pivotWorld.y, worldX - st.pivotWorld.x);
|
|
4418
|
+
const next = applyRotationFromPointer(
|
|
4419
|
+
st.snapshot,
|
|
4420
|
+
st.startRotation,
|
|
4421
|
+
st.startPointerAngleRad,
|
|
4422
|
+
angle
|
|
4423
|
+
);
|
|
4424
|
+
change(itemsRef.current.map((item) => item.id === st.id ? next : item));
|
|
4425
|
+
return;
|
|
4426
|
+
}
|
|
4427
|
+
if (st.kind === "resize") {
|
|
4428
|
+
const change = onItemsChangeRef.current;
|
|
4429
|
+
if (!change) return;
|
|
4430
|
+
const next = resizeItemByHandle(st.snapshot, st.start, st.handle, {
|
|
4431
|
+
x: worldX,
|
|
4432
|
+
y: worldY
|
|
4433
|
+
});
|
|
4434
|
+
change(itemsRef.current.map((item) => item.id === st.id ? next : item));
|
|
4435
|
+
return;
|
|
4436
|
+
}
|
|
4437
|
+
if (st.kind === "marquee") {
|
|
4438
|
+
const a = st.startWorld;
|
|
4439
|
+
const b = { x: worldX, y: worldY };
|
|
4440
|
+
const rect = {
|
|
4441
|
+
x: Math.min(a.x, b.x),
|
|
4442
|
+
y: Math.min(a.y, b.y),
|
|
4443
|
+
width: Math.abs(b.x - a.x),
|
|
4444
|
+
height: Math.abs(b.y - a.y)
|
|
4445
|
+
};
|
|
4446
|
+
setPlacementPreview({ kind: "marquee", rect });
|
|
4447
|
+
return;
|
|
4448
|
+
}
|
|
4449
|
+
if (st.kind === "erase") {
|
|
4450
|
+
setEraserTrail((prev) => [...prev, { x: worldX, y: worldY, t: Date.now() }]);
|
|
4451
|
+
const toErase = collectEraserTargetsAtWorldPoint(
|
|
4452
|
+
itemsRef.current,
|
|
4453
|
+
worldX,
|
|
4454
|
+
worldY,
|
|
4455
|
+
{ lineHitWorld: 10 / cam.zoom, ignoreLocked: true }
|
|
4456
|
+
);
|
|
4457
|
+
for (const id of toErase) {
|
|
4458
|
+
eraserPreviewIdSetRef.current.add(id);
|
|
4459
|
+
}
|
|
4460
|
+
setEraserPreviewIds(Array.from(eraserPreviewIdSetRef.current));
|
|
4461
|
+
return;
|
|
4462
|
+
}
|
|
4463
|
+
if (st.kind === "place") {
|
|
4464
|
+
setPlacementPreview(
|
|
4465
|
+
placementPreviewForTool(st.tool, st.startWorld, {
|
|
4466
|
+
x: worldX,
|
|
4467
|
+
y: worldY
|
|
4468
|
+
})
|
|
4469
|
+
);
|
|
4470
|
+
return;
|
|
4471
|
+
}
|
|
4472
|
+
if (st.kind === "custom-place") {
|
|
4473
|
+
setPlacementPreview({
|
|
4474
|
+
kind: "rect",
|
|
4475
|
+
rect: rectFromCorners(st.startWorld, { x: worldX, y: worldY })
|
|
4476
|
+
});
|
|
4477
|
+
return;
|
|
4478
|
+
}
|
|
4479
|
+
},
|
|
4480
|
+
[requestRender, screenToWorld, updateToolCursorPoint]
|
|
4481
|
+
);
|
|
4482
|
+
const handlePointerMove = useCallback(
|
|
4483
|
+
(event) => {
|
|
4484
|
+
const point = screenPointFromPointerEvent(event);
|
|
4485
|
+
if (dragStateRef.current.kind !== "idle") {
|
|
4486
|
+
applyDragMoveAtScreenPoint(point, point);
|
|
4487
|
+
return;
|
|
4488
|
+
}
|
|
4489
|
+
updateToolCursorPoint(point);
|
|
4490
|
+
},
|
|
4491
|
+
[applyDragMoveAtScreenPoint, updateToolCursorPoint]
|
|
4492
|
+
);
|
|
4351
4493
|
const panResponder = useMemo(
|
|
4352
4494
|
() => PanResponder.create({
|
|
4353
4495
|
onStartShouldSetPanResponder: () => true,
|
|
@@ -4574,145 +4716,7 @@ var NativeVectorViewport = forwardRef(function NativeVectorViewport2({
|
|
|
4574
4716
|
return;
|
|
4575
4717
|
}
|
|
4576
4718
|
lastPinchDist.current = null;
|
|
4577
|
-
|
|
4578
|
-
const { worldX, worldY } = screenToWorld(sx, sy);
|
|
4579
|
-
const st = dragStateRef.current;
|
|
4580
|
-
if (st.kind === "pan") {
|
|
4581
|
-
const current = { x: pageX, y: pageY };
|
|
4582
|
-
if (lastPanPoint.current) {
|
|
4583
|
-
const dx = current.x - lastPanPoint.current.x;
|
|
4584
|
-
const dy = current.y - lastPanPoint.current.y;
|
|
4585
|
-
cam.x += dx;
|
|
4586
|
-
cam.y += dy;
|
|
4587
|
-
requestRender();
|
|
4588
|
-
}
|
|
4589
|
-
lastPanPoint.current = current;
|
|
4590
|
-
return;
|
|
4591
|
-
}
|
|
4592
|
-
lastPanPoint.current = null;
|
|
4593
|
-
if (st.kind === "draw") {
|
|
4594
|
-
const pts = st.points;
|
|
4595
|
-
const last = pts[pts.length - 1];
|
|
4596
|
-
const dx = worldX - (last?.x ?? worldX);
|
|
4597
|
-
const dy = worldY - (last?.y ?? worldY);
|
|
4598
|
-
const shouldAppendPoint = Math.hypot(dx, dy) > 0.5 / cam.zoom;
|
|
4599
|
-
if (shouldAppendPoint) {
|
|
4600
|
-
pts.push({ x: worldX, y: worldY });
|
|
4601
|
-
}
|
|
4602
|
-
if (st.tool === "laser") {
|
|
4603
|
-
if (shouldAppendPoint) {
|
|
4604
|
-
setLaserTrail((prev) => [
|
|
4605
|
-
...prev,
|
|
4606
|
-
{ x: worldX, y: worldY, t: Date.now() }
|
|
4607
|
-
]);
|
|
4608
|
-
}
|
|
4609
|
-
return;
|
|
4610
|
-
}
|
|
4611
|
-
setPlacementPreview({
|
|
4612
|
-
kind: "stroke",
|
|
4613
|
-
tool: st.tool,
|
|
4614
|
-
points: [...pts],
|
|
4615
|
-
style: { ...strokeStyleRef.current }
|
|
4616
|
-
});
|
|
4617
|
-
return;
|
|
4618
|
-
}
|
|
4619
|
-
if (st.kind === "move") {
|
|
4620
|
-
const dx = worldX - st.startWorld.x;
|
|
4621
|
-
const dy = worldY - st.startWorld.y;
|
|
4622
|
-
const change = onItemsChangeRef.current;
|
|
4623
|
-
if (!change) return;
|
|
4624
|
-
const nextList = itemsRef.current.map((it) => {
|
|
4625
|
-
const snap = st.snapshots[it.id];
|
|
4626
|
-
if (!snap) return it;
|
|
4627
|
-
return {
|
|
4628
|
-
...snap,
|
|
4629
|
-
x: snap.x + dx,
|
|
4630
|
-
y: snap.y + dy,
|
|
4631
|
-
bounds: {
|
|
4632
|
-
...snap.bounds,
|
|
4633
|
-
x: snap.bounds.x + dx,
|
|
4634
|
-
y: snap.bounds.y + dy
|
|
4635
|
-
}
|
|
4636
|
-
};
|
|
4637
|
-
});
|
|
4638
|
-
change(nextList);
|
|
4639
|
-
return;
|
|
4640
|
-
}
|
|
4641
|
-
if (st.kind === "rotate") {
|
|
4642
|
-
const change = onItemsChangeRef.current;
|
|
4643
|
-
if (!change) return;
|
|
4644
|
-
const angle = Math.atan2(
|
|
4645
|
-
worldY - st.pivotWorld.y,
|
|
4646
|
-
worldX - st.pivotWorld.x
|
|
4647
|
-
);
|
|
4648
|
-
const next = applyRotationFromPointer(
|
|
4649
|
-
st.snapshot,
|
|
4650
|
-
st.startRotation,
|
|
4651
|
-
st.startPointerAngleRad,
|
|
4652
|
-
angle
|
|
4653
|
-
);
|
|
4654
|
-
change(
|
|
4655
|
-
itemsRef.current.map((item) => item.id === st.id ? next : item)
|
|
4656
|
-
);
|
|
4657
|
-
return;
|
|
4658
|
-
}
|
|
4659
|
-
if (st.kind === "resize") {
|
|
4660
|
-
const change = onItemsChangeRef.current;
|
|
4661
|
-
if (!change) return;
|
|
4662
|
-
const next = resizeItemByHandle(st.snapshot, st.start, st.handle, {
|
|
4663
|
-
x: worldX,
|
|
4664
|
-
y: worldY
|
|
4665
|
-
});
|
|
4666
|
-
change(
|
|
4667
|
-
itemsRef.current.map((item) => item.id === st.id ? next : item)
|
|
4668
|
-
);
|
|
4669
|
-
return;
|
|
4670
|
-
}
|
|
4671
|
-
if (st.kind === "marquee") {
|
|
4672
|
-
const a = st.startWorld;
|
|
4673
|
-
const b = { x: worldX, y: worldY };
|
|
4674
|
-
const rect = {
|
|
4675
|
-
x: Math.min(a.x, b.x),
|
|
4676
|
-
y: Math.min(a.y, b.y),
|
|
4677
|
-
width: Math.abs(b.x - a.x),
|
|
4678
|
-
height: Math.abs(b.y - a.y)
|
|
4679
|
-
};
|
|
4680
|
-
setPlacementPreview({ kind: "marquee", rect });
|
|
4681
|
-
return;
|
|
4682
|
-
}
|
|
4683
|
-
if (st.kind === "erase") {
|
|
4684
|
-
setEraserTrail((prev) => [
|
|
4685
|
-
...prev,
|
|
4686
|
-
{ x: worldX, y: worldY, t: Date.now() }
|
|
4687
|
-
]);
|
|
4688
|
-
const toErase = collectEraserTargetsAtWorldPoint(
|
|
4689
|
-
itemsRef.current,
|
|
4690
|
-
worldX,
|
|
4691
|
-
worldY,
|
|
4692
|
-
{ lineHitWorld: 10 / cam.zoom, ignoreLocked: true }
|
|
4693
|
-
);
|
|
4694
|
-
for (const id of toErase) {
|
|
4695
|
-
eraserPreviewIdSetRef.current.add(id);
|
|
4696
|
-
}
|
|
4697
|
-
setEraserPreviewIds(Array.from(eraserPreviewIdSetRef.current));
|
|
4698
|
-
return;
|
|
4699
|
-
}
|
|
4700
|
-
if (st.kind === "place") {
|
|
4701
|
-
setPlacementPreview(
|
|
4702
|
-
placementPreviewForTool(st.tool, st.startWorld, {
|
|
4703
|
-
x: worldX,
|
|
4704
|
-
y: worldY
|
|
4705
|
-
})
|
|
4706
|
-
);
|
|
4707
|
-
return;
|
|
4708
|
-
}
|
|
4709
|
-
if (st.kind === "custom-place") {
|
|
4710
|
-
setPlacementPreview({
|
|
4711
|
-
kind: "rect",
|
|
4712
|
-
rect: rectFromCorners(st.startWorld, { x: worldX, y: worldY })
|
|
4713
|
-
});
|
|
4714
|
-
return;
|
|
4715
|
-
}
|
|
4719
|
+
applyDragMoveAtScreenPoint({ x: sx, y: sy }, { x: pageX, y: pageY });
|
|
4716
4720
|
},
|
|
4717
4721
|
onPanResponderRelease: (evt) => {
|
|
4718
4722
|
lastPinchDist.current = null;
|
|
@@ -4946,6 +4950,7 @@ var NativeVectorViewport = forwardRef(function NativeVectorViewport2({
|
|
|
4946
4950
|
}
|
|
4947
4951
|
}),
|
|
4948
4952
|
[
|
|
4953
|
+
applyDragMoveAtScreenPoint,
|
|
4949
4954
|
screenToWorld,
|
|
4950
4955
|
requestRender,
|
|
4951
4956
|
requestSelectToolAfterUse,
|