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 +91 -2
- package/dist/native.cjs.map +1 -1
- package/dist/native.d.cts +24 -1
- package/dist/native.d.ts +24 -1
- package/dist/native.js +91 -2
- package/dist/native.js.map +1 -1
- package/package.json +1 -1
package/dist/native.d.cts
CHANGED
|
@@ -189,6 +189,19 @@ declare const DEFAULT_NATIVE_VECTOR_TOOLS: readonly NativeVectorToolDefinition[]
|
|
|
189
189
|
*/
|
|
190
190
|
declare function NativeVectorToolbar({ value, onChange, tools, overflowToolIds, overflowMenuAccessibilityLabel, disabled, disabledToolIds, showToolLockToggle, toolLocked, onToolLockedChange, density, accessibilityLabel, style, contentContainerStyle, overflowPanelStyle, toolButtonStyle, activeToolButtonStyle, toolLabelStyle, activeToolLabelStyle, renderToolIcon, renderToolLockIcon, renderOverflowIcon, renderOverflowChevronIcon, renderToolButton, }: NativeVectorToolbarProps): react_jsx_runtime.JSX.Element;
|
|
191
191
|
|
|
192
|
+
type NativeRemotePresenceHitTarget = "cursor" | "label";
|
|
193
|
+
type NativeRemotePresenceHit = {
|
|
194
|
+
readonly peer: RemotePresencePeer;
|
|
195
|
+
readonly followId: string;
|
|
196
|
+
readonly target: NativeRemotePresenceHitTarget;
|
|
197
|
+
readonly screenX: number;
|
|
198
|
+
readonly screenY: number;
|
|
199
|
+
readonly worldX: number;
|
|
200
|
+
readonly worldY: number;
|
|
201
|
+
readonly clientId?: string;
|
|
202
|
+
readonly peerId?: string;
|
|
203
|
+
};
|
|
204
|
+
|
|
192
205
|
type NativeCustomShapePlacementOptions = {
|
|
193
206
|
readonly toolId: string;
|
|
194
207
|
readonly createItem: (args: {
|
|
@@ -215,6 +228,15 @@ type NativeWorldPointerDownDetail = {
|
|
|
215
228
|
readonly screenX: number;
|
|
216
229
|
readonly screenY: number;
|
|
217
230
|
};
|
|
231
|
+
/**
|
|
232
|
+
* Detail emitted when a native pointer/touch begins on a remote realtime
|
|
233
|
+
* participant label or cursor.
|
|
234
|
+
*
|
|
235
|
+
* Pass `followId` into your `followedPeerId` state for
|
|
236
|
+
* `useRealtimePeerFollow(...)`. For realtime-session peers this is the
|
|
237
|
+
* connection `clientId`, matching the session peer `id`.
|
|
238
|
+
*/
|
|
239
|
+
type NativeRemotePresencePressDetail = NativeRemotePresenceHit;
|
|
218
240
|
/**
|
|
219
241
|
* Optional override for a link item inserted from the native link tool.
|
|
220
242
|
*
|
|
@@ -287,6 +309,7 @@ type NativeVectorViewportProps = {
|
|
|
287
309
|
readonly onLinkToolRequest?: (detail: NativeLinkToolRequestDetail) => void;
|
|
288
310
|
readonly linkToolDialogLabels?: NativeLinkToolDialogLabels;
|
|
289
311
|
readonly onWorldPointerDown?: (detail: NativeWorldPointerDownDetail) => void;
|
|
312
|
+
readonly onRemotePresencePress?: (detail: NativeRemotePresencePressDetail) => void;
|
|
290
313
|
readonly onWorldPointerMove?: (world: {
|
|
291
314
|
readonly x: number;
|
|
292
315
|
readonly y: number;
|
|
@@ -434,4 +457,4 @@ type SvgNode = SvgRectNode | SvgEllipseNode | SvgCircleNode | SvgLineNode | SvgP
|
|
|
434
457
|
*/
|
|
435
458
|
declare function parseSvgFragment(xml: string): SvgNode[];
|
|
436
459
|
|
|
437
|
-
export { CanvuLinkData, DEFAULT_NATIVE_OVERFLOW_TOOL_IDS, DEFAULT_NATIVE_VECTOR_TOOLS, NATIVE_STYLE_PALETTE, type NativeCustomShapePlacementOptions, NativeInteractionOverlay, type NativeInteractionOverlayProps, type NativeLinkToolDialogLabels, type NativeLinkToolInsertOptions, type NativeLinkToolRequestDetail, NativeSceneRenderer, type NativeSceneRendererProps, NativeShapeRenderer, type NativeShapeRendererProps, type NativeStyleColor, NativeVectorStyleInspector, type NativeVectorStyleInspectorProps, type NativeVectorStyleToolId, type NativeVectorToolDefinition, NativeVectorToolbar, type NativeVectorToolbarDensity, type NativeVectorToolbarProps, type NativeVectorToolbarRenderOverflowInput, type NativeVectorToolbarRenderToolInput, type NativeVectorToolbarRenderToolLockInput, NativeVectorViewport, type NativeVectorViewportHandle, type NativeVectorViewportProps, type NativeWorldPointerDownDetail, type PlacementPreview, type SvgNode, VectorSceneItem, nativeStyleColorWithOpacity, normalizeNativeStyleHex, parseSvgFragment };
|
|
460
|
+
export { CanvuLinkData, DEFAULT_NATIVE_OVERFLOW_TOOL_IDS, DEFAULT_NATIVE_VECTOR_TOOLS, NATIVE_STYLE_PALETTE, type NativeCustomShapePlacementOptions, NativeInteractionOverlay, type NativeInteractionOverlayProps, type NativeLinkToolDialogLabels, type NativeLinkToolInsertOptions, type NativeLinkToolRequestDetail, type NativeRemotePresencePressDetail, NativeSceneRenderer, type NativeSceneRendererProps, NativeShapeRenderer, type NativeShapeRendererProps, type NativeStyleColor, NativeVectorStyleInspector, type NativeVectorStyleInspectorProps, type NativeVectorStyleToolId, type NativeVectorToolDefinition, NativeVectorToolbar, type NativeVectorToolbarDensity, type NativeVectorToolbarProps, type NativeVectorToolbarRenderOverflowInput, type NativeVectorToolbarRenderToolInput, type NativeVectorToolbarRenderToolLockInput, NativeVectorViewport, type NativeVectorViewportHandle, type NativeVectorViewportProps, type NativeWorldPointerDownDetail, type PlacementPreview, type SvgNode, VectorSceneItem, nativeStyleColorWithOpacity, normalizeNativeStyleHex, parseSvgFragment };
|
package/dist/native.d.ts
CHANGED
|
@@ -189,6 +189,19 @@ declare const DEFAULT_NATIVE_VECTOR_TOOLS: readonly NativeVectorToolDefinition[]
|
|
|
189
189
|
*/
|
|
190
190
|
declare function NativeVectorToolbar({ value, onChange, tools, overflowToolIds, overflowMenuAccessibilityLabel, disabled, disabledToolIds, showToolLockToggle, toolLocked, onToolLockedChange, density, accessibilityLabel, style, contentContainerStyle, overflowPanelStyle, toolButtonStyle, activeToolButtonStyle, toolLabelStyle, activeToolLabelStyle, renderToolIcon, renderToolLockIcon, renderOverflowIcon, renderOverflowChevronIcon, renderToolButton, }: NativeVectorToolbarProps): react_jsx_runtime.JSX.Element;
|
|
191
191
|
|
|
192
|
+
type NativeRemotePresenceHitTarget = "cursor" | "label";
|
|
193
|
+
type NativeRemotePresenceHit = {
|
|
194
|
+
readonly peer: RemotePresencePeer;
|
|
195
|
+
readonly followId: string;
|
|
196
|
+
readonly target: NativeRemotePresenceHitTarget;
|
|
197
|
+
readonly screenX: number;
|
|
198
|
+
readonly screenY: number;
|
|
199
|
+
readonly worldX: number;
|
|
200
|
+
readonly worldY: number;
|
|
201
|
+
readonly clientId?: string;
|
|
202
|
+
readonly peerId?: string;
|
|
203
|
+
};
|
|
204
|
+
|
|
192
205
|
type NativeCustomShapePlacementOptions = {
|
|
193
206
|
readonly toolId: string;
|
|
194
207
|
readonly createItem: (args: {
|
|
@@ -215,6 +228,15 @@ type NativeWorldPointerDownDetail = {
|
|
|
215
228
|
readonly screenX: number;
|
|
216
229
|
readonly screenY: number;
|
|
217
230
|
};
|
|
231
|
+
/**
|
|
232
|
+
* Detail emitted when a native pointer/touch begins on a remote realtime
|
|
233
|
+
* participant label or cursor.
|
|
234
|
+
*
|
|
235
|
+
* Pass `followId` into your `followedPeerId` state for
|
|
236
|
+
* `useRealtimePeerFollow(...)`. For realtime-session peers this is the
|
|
237
|
+
* connection `clientId`, matching the session peer `id`.
|
|
238
|
+
*/
|
|
239
|
+
type NativeRemotePresencePressDetail = NativeRemotePresenceHit;
|
|
218
240
|
/**
|
|
219
241
|
* Optional override for a link item inserted from the native link tool.
|
|
220
242
|
*
|
|
@@ -287,6 +309,7 @@ type NativeVectorViewportProps = {
|
|
|
287
309
|
readonly onLinkToolRequest?: (detail: NativeLinkToolRequestDetail) => void;
|
|
288
310
|
readonly linkToolDialogLabels?: NativeLinkToolDialogLabels;
|
|
289
311
|
readonly onWorldPointerDown?: (detail: NativeWorldPointerDownDetail) => void;
|
|
312
|
+
readonly onRemotePresencePress?: (detail: NativeRemotePresencePressDetail) => void;
|
|
290
313
|
readonly onWorldPointerMove?: (world: {
|
|
291
314
|
readonly x: number;
|
|
292
315
|
readonly y: number;
|
|
@@ -434,4 +457,4 @@ type SvgNode = SvgRectNode | SvgEllipseNode | SvgCircleNode | SvgLineNode | SvgP
|
|
|
434
457
|
*/
|
|
435
458
|
declare function parseSvgFragment(xml: string): SvgNode[];
|
|
436
459
|
|
|
437
|
-
export { CanvuLinkData, DEFAULT_NATIVE_OVERFLOW_TOOL_IDS, DEFAULT_NATIVE_VECTOR_TOOLS, NATIVE_STYLE_PALETTE, type NativeCustomShapePlacementOptions, NativeInteractionOverlay, type NativeInteractionOverlayProps, type NativeLinkToolDialogLabels, type NativeLinkToolInsertOptions, type NativeLinkToolRequestDetail, NativeSceneRenderer, type NativeSceneRendererProps, NativeShapeRenderer, type NativeShapeRendererProps, type NativeStyleColor, NativeVectorStyleInspector, type NativeVectorStyleInspectorProps, type NativeVectorStyleToolId, type NativeVectorToolDefinition, NativeVectorToolbar, type NativeVectorToolbarDensity, type NativeVectorToolbarProps, type NativeVectorToolbarRenderOverflowInput, type NativeVectorToolbarRenderToolInput, type NativeVectorToolbarRenderToolLockInput, NativeVectorViewport, type NativeVectorViewportHandle, type NativeVectorViewportProps, type NativeWorldPointerDownDetail, type PlacementPreview, type SvgNode, VectorSceneItem, nativeStyleColorWithOpacity, normalizeNativeStyleHex, parseSvgFragment };
|
|
460
|
+
export { CanvuLinkData, DEFAULT_NATIVE_OVERFLOW_TOOL_IDS, DEFAULT_NATIVE_VECTOR_TOOLS, NATIVE_STYLE_PALETTE, type NativeCustomShapePlacementOptions, NativeInteractionOverlay, type NativeInteractionOverlayProps, type NativeLinkToolDialogLabels, type NativeLinkToolInsertOptions, type NativeLinkToolRequestDetail, type NativeRemotePresencePressDetail, NativeSceneRenderer, type NativeSceneRendererProps, NativeShapeRenderer, type NativeShapeRendererProps, type NativeStyleColor, NativeVectorStyleInspector, type NativeVectorStyleInspectorProps, type NativeVectorStyleToolId, type NativeVectorToolDefinition, NativeVectorToolbar, type NativeVectorToolbarDensity, type NativeVectorToolbarProps, type NativeVectorToolbarRenderOverflowInput, type NativeVectorToolbarRenderToolInput, type NativeVectorToolbarRenderToolLockInput, NativeVectorViewport, type NativeVectorViewportHandle, type NativeVectorViewportProps, type NativeWorldPointerDownDetail, type PlacementPreview, type SvgNode, VectorSceneItem, nativeStyleColorWithOpacity, normalizeNativeStyleHex, parseSvgFragment };
|
package/dist/native.js
CHANGED
|
@@ -4672,6 +4672,84 @@ function resizeItemByHandle(item, start, handle, currentWorld) {
|
|
|
4672
4672
|
}
|
|
4673
4673
|
return { ...item, x: nb.x, y: nb.y, bounds: nb };
|
|
4674
4674
|
}
|
|
4675
|
+
|
|
4676
|
+
// src/native/native-remote-presence-hit-test.ts
|
|
4677
|
+
var REMOTE_CURSOR_SCREEN_PX2 = 22;
|
|
4678
|
+
var REMOTE_LABEL_SCREEN_PX2 = 12;
|
|
4679
|
+
var REMOTE_LABEL_OFFSET_X = 14;
|
|
4680
|
+
var REMOTE_LABEL_BASELINE_OFFSET_Y = 18;
|
|
4681
|
+
var REMOTE_LABEL_AVERAGE_CHAR_PX = 7;
|
|
4682
|
+
var REMOTE_LABEL_MAX_WIDTH_PX = 180;
|
|
4683
|
+
var REMOTE_LABEL_MIN_HIT_WIDTH_PX = 44;
|
|
4684
|
+
var REMOTE_LABEL_HIT_PADDING_X = 10;
|
|
4685
|
+
var REMOTE_LABEL_HIT_PADDING_Y = 10;
|
|
4686
|
+
var REMOTE_CURSOR_MIN_HIT_SIZE_PX = 36;
|
|
4687
|
+
function pointInScreenRect(point, rect) {
|
|
4688
|
+
return point.x >= rect.x && point.x <= rect.x + rect.width && point.y >= rect.y && point.y <= rect.y + rect.height;
|
|
4689
|
+
}
|
|
4690
|
+
function displayLabelForPeer(peer) {
|
|
4691
|
+
const displayName = peer.displayName?.trim();
|
|
4692
|
+
if (displayName) return displayName;
|
|
4693
|
+
return null;
|
|
4694
|
+
}
|
|
4695
|
+
function followIdForPeer(peer) {
|
|
4696
|
+
return peer.clientId ?? peer.peerId ?? peer.id;
|
|
4697
|
+
}
|
|
4698
|
+
function estimateLabelWidth(label) {
|
|
4699
|
+
return Math.max(
|
|
4700
|
+
REMOTE_LABEL_MIN_HIT_WIDTH_PX,
|
|
4701
|
+
Math.min(REMOTE_LABEL_MAX_WIDTH_PX, label.length * REMOTE_LABEL_AVERAGE_CHAR_PX)
|
|
4702
|
+
);
|
|
4703
|
+
}
|
|
4704
|
+
function buildHit(peer, camera, point, target) {
|
|
4705
|
+
const world = camera.screenToWorld(point.x, point.y);
|
|
4706
|
+
return {
|
|
4707
|
+
peer,
|
|
4708
|
+
followId: followIdForPeer(peer),
|
|
4709
|
+
target,
|
|
4710
|
+
screenX: point.x,
|
|
4711
|
+
screenY: point.y,
|
|
4712
|
+
worldX: world.worldX,
|
|
4713
|
+
worldY: world.worldY,
|
|
4714
|
+
...peer.clientId ? { clientId: peer.clientId } : {},
|
|
4715
|
+
...peer.peerId ? { peerId: peer.peerId } : {}
|
|
4716
|
+
};
|
|
4717
|
+
}
|
|
4718
|
+
function hitTestNativeRemotePresence(peers, camera, point) {
|
|
4719
|
+
for (let index = peers.length - 1; index >= 0; index -= 1) {
|
|
4720
|
+
const peer = peers[index];
|
|
4721
|
+
if (!peer || peer.isSelf || !peer.cursor) continue;
|
|
4722
|
+
const cursorScreen = camera.worldToScreen(peer.cursor.x, peer.cursor.y);
|
|
4723
|
+
const label = displayLabelForPeer(peer);
|
|
4724
|
+
if (label) {
|
|
4725
|
+
const labelX = cursorScreen.screenX + REMOTE_LABEL_OFFSET_X;
|
|
4726
|
+
const labelBaselineY = cursorScreen.screenY + REMOTE_LABEL_BASELINE_OFFSET_Y;
|
|
4727
|
+
const labelRect = {
|
|
4728
|
+
x: labelX - REMOTE_LABEL_HIT_PADDING_X,
|
|
4729
|
+
y: labelBaselineY - REMOTE_LABEL_SCREEN_PX2 - REMOTE_LABEL_HIT_PADDING_Y,
|
|
4730
|
+
width: estimateLabelWidth(label) + REMOTE_LABEL_HIT_PADDING_X * 2,
|
|
4731
|
+
height: REMOTE_LABEL_SCREEN_PX2 + REMOTE_LABEL_HIT_PADDING_Y * 2
|
|
4732
|
+
};
|
|
4733
|
+
if (pointInScreenRect(point, labelRect)) {
|
|
4734
|
+
return buildHit(peer, camera, point, "label");
|
|
4735
|
+
}
|
|
4736
|
+
}
|
|
4737
|
+
const cursorHitSize = Math.max(
|
|
4738
|
+
REMOTE_CURSOR_MIN_HIT_SIZE_PX,
|
|
4739
|
+
REMOTE_CURSOR_SCREEN_PX2
|
|
4740
|
+
);
|
|
4741
|
+
const cursorRect = {
|
|
4742
|
+
x: cursorScreen.screenX - (cursorHitSize - REMOTE_CURSOR_SCREEN_PX2) / 2,
|
|
4743
|
+
y: cursorScreen.screenY - (cursorHitSize - REMOTE_CURSOR_SCREEN_PX2) / 2,
|
|
4744
|
+
width: cursorHitSize,
|
|
4745
|
+
height: cursorHitSize
|
|
4746
|
+
};
|
|
4747
|
+
if (pointInScreenRect(point, cursorRect)) {
|
|
4748
|
+
return buildHit(peer, camera, point, "cursor");
|
|
4749
|
+
}
|
|
4750
|
+
}
|
|
4751
|
+
return null;
|
|
4752
|
+
}
|
|
4675
4753
|
var DEFAULT_NATIVE_LINK_TOOL_DIALOG_LABELS = {
|
|
4676
4754
|
title: "Add link",
|
|
4677
4755
|
description: "Paste the link you want to add to the board.",
|
|
@@ -4768,6 +4846,7 @@ var NativeVectorViewport = forwardRef(function NativeVectorViewport2({
|
|
|
4768
4846
|
onLinkToolRequest,
|
|
4769
4847
|
linkToolDialogLabels,
|
|
4770
4848
|
onWorldPointerDown,
|
|
4849
|
+
onRemotePresencePress,
|
|
4771
4850
|
onWorldPointerMove,
|
|
4772
4851
|
onWorldPointerLeave,
|
|
4773
4852
|
onPlacementPreviewChange,
|
|
@@ -4791,6 +4870,8 @@ var NativeVectorViewport = forwardRef(function NativeVectorViewport2({
|
|
|
4791
4870
|
onLinkToolRequestRef.current = onLinkToolRequest;
|
|
4792
4871
|
const onWorldPointerDownRef = useRef(onWorldPointerDown);
|
|
4793
4872
|
onWorldPointerDownRef.current = onWorldPointerDown;
|
|
4873
|
+
const onRemotePresencePressRef = useRef(onRemotePresencePress);
|
|
4874
|
+
onRemotePresencePressRef.current = onRemotePresencePress;
|
|
4794
4875
|
const onWorldPointerMoveRef = useRef(onWorldPointerMove);
|
|
4795
4876
|
onWorldPointerMoveRef.current = onWorldPointerMove;
|
|
4796
4877
|
const onWorldPointerLeaveRef = useRef(onWorldPointerLeave);
|
|
@@ -4811,6 +4892,8 @@ var NativeVectorViewport = forwardRef(function NativeVectorViewport2({
|
|
|
4811
4892
|
itemsRef.current = items;
|
|
4812
4893
|
const selectedIdsRef = useRef(selectedIds);
|
|
4813
4894
|
selectedIdsRef.current = selectedIds;
|
|
4895
|
+
const remotePresenceRef = useRef(remotePresence);
|
|
4896
|
+
remotePresenceRef.current = remotePresence;
|
|
4814
4897
|
const dragStateRef = useRef({ kind: "idle" });
|
|
4815
4898
|
const [placementPreview, setPlacementPreviewState] = useState(null);
|
|
4816
4899
|
const setRealtimePlacementPreview = useCallback(
|
|
@@ -4970,13 +5053,19 @@ var NativeVectorViewport = forwardRef(function NativeVectorViewport2({
|
|
|
4970
5053
|
const sx = point.x;
|
|
4971
5054
|
const sy = point.y;
|
|
4972
5055
|
updateToolCursorPoint(point);
|
|
5056
|
+
const cam = cameraRef.current;
|
|
5057
|
+
if (!cam) return;
|
|
5058
|
+
const remotePresenceHit = interactive && onRemotePresencePressRef.current ? hitTestNativeRemotePresence(remotePresenceRef.current, cam, point) : null;
|
|
5059
|
+
if (remotePresenceHit) {
|
|
5060
|
+
dragStateRef.current = { kind: "idle" };
|
|
5061
|
+
onRemotePresencePressRef.current?.(remotePresenceHit);
|
|
5062
|
+
return;
|
|
5063
|
+
}
|
|
4973
5064
|
if (!interactive) {
|
|
4974
5065
|
dragStateRef.current = { kind: "pan" };
|
|
4975
5066
|
return;
|
|
4976
5067
|
}
|
|
4977
5068
|
const tool = toolIdRef.current;
|
|
4978
|
-
const cam = cameraRef.current;
|
|
4979
|
-
if (!cam) return;
|
|
4980
5069
|
const { worldX, worldY } = screenToWorld(sx, sy);
|
|
4981
5070
|
onWorldPointerMoveRef.current?.({ x: worldX, y: worldY });
|
|
4982
5071
|
if (tool === "hand") {
|