canvu-react 0.4.41 → 0.4.42

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 CHANGED
@@ -4678,6 +4678,84 @@ function resizeItemByHandle(item, start, handle, currentWorld) {
4678
4678
  }
4679
4679
  return { ...item, x: nb.x, y: nb.y, bounds: nb };
4680
4680
  }
4681
+
4682
+ // src/native/native-remote-presence-hit-test.ts
4683
+ var REMOTE_CURSOR_SCREEN_PX2 = 22;
4684
+ var REMOTE_LABEL_SCREEN_PX2 = 12;
4685
+ var REMOTE_LABEL_OFFSET_X = 14;
4686
+ var REMOTE_LABEL_BASELINE_OFFSET_Y = 18;
4687
+ var REMOTE_LABEL_AVERAGE_CHAR_PX = 7;
4688
+ var REMOTE_LABEL_MAX_WIDTH_PX = 180;
4689
+ var REMOTE_LABEL_MIN_HIT_WIDTH_PX = 44;
4690
+ var REMOTE_LABEL_HIT_PADDING_X = 10;
4691
+ var REMOTE_LABEL_HIT_PADDING_Y = 10;
4692
+ var REMOTE_CURSOR_MIN_HIT_SIZE_PX = 36;
4693
+ function pointInScreenRect(point, rect) {
4694
+ return point.x >= rect.x && point.x <= rect.x + rect.width && point.y >= rect.y && point.y <= rect.y + rect.height;
4695
+ }
4696
+ function displayLabelForPeer(peer) {
4697
+ const displayName = peer.displayName?.trim();
4698
+ if (displayName) return displayName;
4699
+ return null;
4700
+ }
4701
+ function followIdForPeer(peer) {
4702
+ return peer.clientId ?? peer.peerId ?? peer.id;
4703
+ }
4704
+ function estimateLabelWidth(label) {
4705
+ return Math.max(
4706
+ REMOTE_LABEL_MIN_HIT_WIDTH_PX,
4707
+ Math.min(REMOTE_LABEL_MAX_WIDTH_PX, label.length * REMOTE_LABEL_AVERAGE_CHAR_PX)
4708
+ );
4709
+ }
4710
+ function buildHit(peer, camera, point, target) {
4711
+ const world = camera.screenToWorld(point.x, point.y);
4712
+ return {
4713
+ peer,
4714
+ followId: followIdForPeer(peer),
4715
+ target,
4716
+ screenX: point.x,
4717
+ screenY: point.y,
4718
+ worldX: world.worldX,
4719
+ worldY: world.worldY,
4720
+ ...peer.clientId ? { clientId: peer.clientId } : {},
4721
+ ...peer.peerId ? { peerId: peer.peerId } : {}
4722
+ };
4723
+ }
4724
+ function hitTestNativeRemotePresence(peers, camera, point) {
4725
+ for (let index = peers.length - 1; index >= 0; index -= 1) {
4726
+ const peer = peers[index];
4727
+ if (!peer || peer.isSelf || !peer.cursor) continue;
4728
+ const cursorScreen = camera.worldToScreen(peer.cursor.x, peer.cursor.y);
4729
+ const label = displayLabelForPeer(peer);
4730
+ if (label) {
4731
+ const labelX = cursorScreen.screenX + REMOTE_LABEL_OFFSET_X;
4732
+ const labelBaselineY = cursorScreen.screenY + REMOTE_LABEL_BASELINE_OFFSET_Y;
4733
+ const labelRect = {
4734
+ x: labelX - REMOTE_LABEL_HIT_PADDING_X,
4735
+ y: labelBaselineY - REMOTE_LABEL_SCREEN_PX2 - REMOTE_LABEL_HIT_PADDING_Y,
4736
+ width: estimateLabelWidth(label) + REMOTE_LABEL_HIT_PADDING_X * 2,
4737
+ height: REMOTE_LABEL_SCREEN_PX2 + REMOTE_LABEL_HIT_PADDING_Y * 2
4738
+ };
4739
+ if (pointInScreenRect(point, labelRect)) {
4740
+ return buildHit(peer, camera, point, "label");
4741
+ }
4742
+ }
4743
+ const cursorHitSize = Math.max(
4744
+ REMOTE_CURSOR_MIN_HIT_SIZE_PX,
4745
+ REMOTE_CURSOR_SCREEN_PX2
4746
+ );
4747
+ const cursorRect = {
4748
+ x: cursorScreen.screenX - (cursorHitSize - REMOTE_CURSOR_SCREEN_PX2) / 2,
4749
+ y: cursorScreen.screenY - (cursorHitSize - REMOTE_CURSOR_SCREEN_PX2) / 2,
4750
+ width: cursorHitSize,
4751
+ height: cursorHitSize
4752
+ };
4753
+ if (pointInScreenRect(point, cursorRect)) {
4754
+ return buildHit(peer, camera, point, "cursor");
4755
+ }
4756
+ }
4757
+ return null;
4758
+ }
4681
4759
  var DEFAULT_NATIVE_LINK_TOOL_DIALOG_LABELS = {
4682
4760
  title: "Add link",
4683
4761
  description: "Paste the link you want to add to the board.",
@@ -4774,6 +4852,7 @@ var NativeVectorViewport = react.forwardRef(function NativeVectorViewport2({
4774
4852
  onLinkToolRequest,
4775
4853
  linkToolDialogLabels,
4776
4854
  onWorldPointerDown,
4855
+ onRemotePresencePress,
4777
4856
  onWorldPointerMove,
4778
4857
  onWorldPointerLeave,
4779
4858
  onPlacementPreviewChange,
@@ -4797,6 +4876,8 @@ var NativeVectorViewport = react.forwardRef(function NativeVectorViewport2({
4797
4876
  onLinkToolRequestRef.current = onLinkToolRequest;
4798
4877
  const onWorldPointerDownRef = react.useRef(onWorldPointerDown);
4799
4878
  onWorldPointerDownRef.current = onWorldPointerDown;
4879
+ const onRemotePresencePressRef = react.useRef(onRemotePresencePress);
4880
+ onRemotePresencePressRef.current = onRemotePresencePress;
4800
4881
  const onWorldPointerMoveRef = react.useRef(onWorldPointerMove);
4801
4882
  onWorldPointerMoveRef.current = onWorldPointerMove;
4802
4883
  const onWorldPointerLeaveRef = react.useRef(onWorldPointerLeave);
@@ -4817,6 +4898,8 @@ var NativeVectorViewport = react.forwardRef(function NativeVectorViewport2({
4817
4898
  itemsRef.current = items;
4818
4899
  const selectedIdsRef = react.useRef(selectedIds);
4819
4900
  selectedIdsRef.current = selectedIds;
4901
+ const remotePresenceRef = react.useRef(remotePresence);
4902
+ remotePresenceRef.current = remotePresence;
4820
4903
  const dragStateRef = react.useRef({ kind: "idle" });
4821
4904
  const [placementPreview, setPlacementPreviewState] = react.useState(null);
4822
4905
  const setRealtimePlacementPreview = react.useCallback(
@@ -4976,13 +5059,19 @@ var NativeVectorViewport = react.forwardRef(function NativeVectorViewport2({
4976
5059
  const sx = point.x;
4977
5060
  const sy = point.y;
4978
5061
  updateToolCursorPoint(point);
5062
+ const cam = cameraRef.current;
5063
+ if (!cam) return;
5064
+ const remotePresenceHit = interactive && onRemotePresencePressRef.current ? hitTestNativeRemotePresence(remotePresenceRef.current, cam, point) : null;
5065
+ if (remotePresenceHit) {
5066
+ dragStateRef.current = { kind: "idle" };
5067
+ onRemotePresencePressRef.current?.(remotePresenceHit);
5068
+ return;
5069
+ }
4979
5070
  if (!interactive) {
4980
5071
  dragStateRef.current = { kind: "pan" };
4981
5072
  return;
4982
5073
  }
4983
5074
  const tool = toolIdRef.current;
4984
- const cam = cameraRef.current;
4985
- if (!cam) return;
4986
5075
  const { worldX, worldY } = screenToWorld(sx, sy);
4987
5076
  onWorldPointerMoveRef.current?.({ x: worldX, y: worldY });
4988
5077
  if (tool === "hand") {