canvu-react 0.4.32 → 0.4.34
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/chatbot.d.cts +2 -1
- package/dist/chatbot.d.ts +2 -1
- package/dist/index.cjs +1 -10
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +1 -10
- package/dist/index.js.map +1 -1
- package/dist/native.cjs +240 -33
- package/dist/native.cjs.map +1 -1
- package/dist/native.d.cts +10 -1
- package/dist/native.d.ts +10 -1
- package/dist/native.js +241 -34
- package/dist/native.js.map +1 -1
- package/dist/react.cjs +2 -11
- package/dist/react.cjs.map +1 -1
- package/dist/react.d.cts +3 -2
- package/dist/react.d.ts +3 -2
- package/dist/react.js +2 -11
- package/dist/react.js.map +1 -1
- package/dist/realtime.cjs +18 -3
- package/dist/realtime.cjs.map +1 -1
- package/dist/realtime.d.cts +3 -2
- package/dist/realtime.d.ts +3 -2
- package/dist/realtime.js +18 -3
- package/dist/realtime.js.map +1 -1
- package/dist/realtimeNative.cjs +2124 -0
- package/dist/realtimeNative.cjs.map +1 -0
- package/dist/realtimeNative.d.cts +255 -0
- package/dist/realtimeNative.d.ts +255 -0
- package/dist/realtimeNative.js +2097 -0
- package/dist/realtimeNative.js.map +1 -0
- package/dist/tldraw.cjs +1 -10
- package/dist/tldraw.cjs.map +1 -1
- package/dist/tldraw.js +1 -10
- package/dist/tldraw.js.map +1 -1
- package/dist/types-B82WiQQh.d.ts +69 -0
- package/dist/types-BQUbxMgz.d.cts +69 -0
- package/dist/{types-UZYYwK-v.d.ts → types-DeDm865m.d.ts} +2 -67
- package/dist/{types-BS-YG8Hx.d.cts → types-NBYvslB-.d.cts} +2 -67
- package/package.json +7 -1
package/dist/native.d.cts
CHANGED
|
@@ -2,6 +2,7 @@ import { C as Camera2D, S as StrokeStyle } from './shape-builders-CKEMjivV.cjs';
|
|
|
2
2
|
export { o as createFreehandStrokeItem, q as createImageItem, t as createShapeId } from './shape-builders-CKEMjivV.cjs';
|
|
3
3
|
import { V as VectorSceneItem, R as Rect } from './types-BCCvY6ie.cjs';
|
|
4
4
|
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
5
|
+
import { R as RemotePresencePeer } from './types-BQUbxMgz.cjs';
|
|
5
6
|
import { StyleProp, ViewStyle, TextStyle } from 'react-native';
|
|
6
7
|
import * as react from 'react';
|
|
7
8
|
import { ReactNode } from 'react';
|
|
@@ -58,8 +59,9 @@ type NativeInteractionOverlayProps = {
|
|
|
58
59
|
readonly laserTrail?: readonly TimedTrailPoint[];
|
|
59
60
|
readonly eraserPreviewItems?: readonly VectorSceneItem[];
|
|
60
61
|
readonly previewStrokeStyle?: StrokeStyle;
|
|
62
|
+
readonly remotePresence?: readonly RemotePresencePeer[];
|
|
61
63
|
};
|
|
62
|
-
declare function NativeInteractionOverlay({ camera, width, height, selectedItems, showResizeHandles, placementPreview, eraserTrail, laserTrail, eraserPreviewItems, previewStrokeStyle, }: NativeInteractionOverlayProps): react_jsx_runtime.JSX.Element | null;
|
|
64
|
+
declare function NativeInteractionOverlay({ camera, width, height, selectedItems, showResizeHandles, placementPreview, eraserTrail, laserTrail, eraserPreviewItems, previewStrokeStyle, remotePresence, }: NativeInteractionOverlayProps): react_jsx_runtime.JSX.Element | null;
|
|
63
65
|
|
|
64
66
|
type NativeSceneRendererProps = {
|
|
65
67
|
readonly items: readonly VectorSceneItem[];
|
|
@@ -214,6 +216,7 @@ type NativeWorldPointerDownDetail = {
|
|
|
214
216
|
type NativeVectorViewportProps = {
|
|
215
217
|
readonly items: readonly VectorSceneItem[];
|
|
216
218
|
readonly selectedIds?: readonly string[];
|
|
219
|
+
readonly remotePresence?: readonly RemotePresencePeer[];
|
|
217
220
|
readonly toolId?: string;
|
|
218
221
|
readonly toolLocked?: boolean;
|
|
219
222
|
readonly interactive?: boolean;
|
|
@@ -221,6 +224,12 @@ type NativeVectorViewportProps = {
|
|
|
221
224
|
readonly onItemsChange?: (items: VectorSceneItem[]) => void;
|
|
222
225
|
readonly onToolChangeRequest?: (toolId: string) => void;
|
|
223
226
|
readonly onWorldPointerDown?: (detail: NativeWorldPointerDownDetail) => void;
|
|
227
|
+
readonly onWorldPointerMove?: (world: {
|
|
228
|
+
readonly x: number;
|
|
229
|
+
readonly y: number;
|
|
230
|
+
}) => void;
|
|
231
|
+
readonly onWorldPointerLeave?: () => void;
|
|
232
|
+
readonly onPlacementPreviewChange?: (preview: PlacementPreview | null) => void;
|
|
224
233
|
readonly onCameraChange?: () => void;
|
|
225
234
|
readonly customPlacement?: NativeCustomShapePlacementOptions;
|
|
226
235
|
readonly customPlacements?: readonly NativeCustomShapePlacementOptions[];
|
package/dist/native.d.ts
CHANGED
|
@@ -2,6 +2,7 @@ import { C as Camera2D, S as StrokeStyle } from './shape-builders-Cyh8zvDG.js';
|
|
|
2
2
|
export { o as createFreehandStrokeItem, q as createImageItem, t as createShapeId } from './shape-builders-Cyh8zvDG.js';
|
|
3
3
|
import { V as VectorSceneItem, R as Rect } from './types-BCCvY6ie.js';
|
|
4
4
|
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
5
|
+
import { R as RemotePresencePeer } from './types-B82WiQQh.js';
|
|
5
6
|
import { StyleProp, ViewStyle, TextStyle } from 'react-native';
|
|
6
7
|
import * as react from 'react';
|
|
7
8
|
import { ReactNode } from 'react';
|
|
@@ -58,8 +59,9 @@ type NativeInteractionOverlayProps = {
|
|
|
58
59
|
readonly laserTrail?: readonly TimedTrailPoint[];
|
|
59
60
|
readonly eraserPreviewItems?: readonly VectorSceneItem[];
|
|
60
61
|
readonly previewStrokeStyle?: StrokeStyle;
|
|
62
|
+
readonly remotePresence?: readonly RemotePresencePeer[];
|
|
61
63
|
};
|
|
62
|
-
declare function NativeInteractionOverlay({ camera, width, height, selectedItems, showResizeHandles, placementPreview, eraserTrail, laserTrail, eraserPreviewItems, previewStrokeStyle, }: NativeInteractionOverlayProps): react_jsx_runtime.JSX.Element | null;
|
|
64
|
+
declare function NativeInteractionOverlay({ camera, width, height, selectedItems, showResizeHandles, placementPreview, eraserTrail, laserTrail, eraserPreviewItems, previewStrokeStyle, remotePresence, }: NativeInteractionOverlayProps): react_jsx_runtime.JSX.Element | null;
|
|
63
65
|
|
|
64
66
|
type NativeSceneRendererProps = {
|
|
65
67
|
readonly items: readonly VectorSceneItem[];
|
|
@@ -214,6 +216,7 @@ type NativeWorldPointerDownDetail = {
|
|
|
214
216
|
type NativeVectorViewportProps = {
|
|
215
217
|
readonly items: readonly VectorSceneItem[];
|
|
216
218
|
readonly selectedIds?: readonly string[];
|
|
219
|
+
readonly remotePresence?: readonly RemotePresencePeer[];
|
|
217
220
|
readonly toolId?: string;
|
|
218
221
|
readonly toolLocked?: boolean;
|
|
219
222
|
readonly interactive?: boolean;
|
|
@@ -221,6 +224,12 @@ type NativeVectorViewportProps = {
|
|
|
221
224
|
readonly onItemsChange?: (items: VectorSceneItem[]) => void;
|
|
222
225
|
readonly onToolChangeRequest?: (toolId: string) => void;
|
|
223
226
|
readonly onWorldPointerDown?: (detail: NativeWorldPointerDownDetail) => void;
|
|
227
|
+
readonly onWorldPointerMove?: (world: {
|
|
228
|
+
readonly x: number;
|
|
229
|
+
readonly y: number;
|
|
230
|
+
}) => void;
|
|
231
|
+
readonly onWorldPointerLeave?: () => void;
|
|
232
|
+
readonly onPlacementPreviewChange?: (preview: PlacementPreview | null) => void;
|
|
224
233
|
readonly onCameraChange?: () => void;
|
|
225
234
|
readonly customPlacement?: NativeCustomShapePlacementOptions;
|
|
226
235
|
readonly customPlacements?: readonly NativeCustomShapePlacementOptions[];
|
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, useImage, Image } from '@shopify/react-native-skia';
|
|
3
|
-
import { memo, forwardRef, useState, useRef,
|
|
3
|
+
import { memo, forwardRef, useState, useRef, useCallback, useEffect, useMemo, useImperativeHandle } from 'react';
|
|
4
4
|
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
5
5
|
import { StyleSheet, PanResponder, View, Pressable, Text as Text$1, ScrollView } from 'react-native';
|
|
6
6
|
|
|
@@ -34,7 +34,7 @@ var LINK_PLUGIN_KEY = "canvuLink";
|
|
|
34
34
|
var DEFAULT_LINK_CARD_WIDTH = 320;
|
|
35
35
|
var DEFAULT_LINK_CARD_HEIGHT = 70;
|
|
36
36
|
var LINK_CARD_MIN_SCALE = 0.6;
|
|
37
|
-
var LINK_CARD_MAX_SCALE =
|
|
37
|
+
var LINK_CARD_MAX_SCALE = 6;
|
|
38
38
|
var LINK_CARD_ASPECT = DEFAULT_LINK_CARD_WIDTH / DEFAULT_LINK_CARD_HEIGHT;
|
|
39
39
|
var LINK_CARD_BORDER = "oklch(0.918 0.008 255)";
|
|
40
40
|
var LINK_CARD_BORDER_STRONG = "oklch(0.86 0.012 255)";
|
|
@@ -47,7 +47,6 @@ var formatNumber = (value) => {
|
|
|
47
47
|
const rounded = Math.round(value * 100) / 100;
|
|
48
48
|
return Object.is(rounded, -0) ? "0" : String(rounded);
|
|
49
49
|
};
|
|
50
|
-
var escapeXmlAttribute = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
51
50
|
var escapeHtmlText = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">");
|
|
52
51
|
var getLinkHostname = (href) => {
|
|
53
52
|
try {
|
|
@@ -72,7 +71,6 @@ var getLinkInitial = (hostname) => {
|
|
|
72
71
|
const first = hostname.trim().charAt(0).toUpperCase();
|
|
73
72
|
return first || "L";
|
|
74
73
|
};
|
|
75
|
-
var buildGoogleFaviconUrl = (hostname) => hostname ? `https://www.google.com/s2/favicons?domain=${encodeURIComponent(hostname)}&sz=64` : null;
|
|
76
74
|
var getStableLinkIdSuffix = (value) => {
|
|
77
75
|
let hash = 0;
|
|
78
76
|
for (const char of value) {
|
|
@@ -95,16 +93,13 @@ function buildLinkCardSvg(width, _height, link) {
|
|
|
95
93
|
const title = link.title?.trim() || hostname || "Link";
|
|
96
94
|
const protocol = getLinkProtocol(link.href);
|
|
97
95
|
const subtitle = hostname || link.href;
|
|
98
|
-
const favicon = link.favicon?.trim() || buildGoogleFaviconUrl(hostname);
|
|
99
96
|
const idSuffix = getStableLinkIdSuffix(`${hostname}:${link.href}`);
|
|
100
|
-
const clipId = `canvu-link-favicon-${idSuffix}`;
|
|
101
97
|
const gradientId = `canvu-link-favicon-gradient-${idSuffix}`;
|
|
102
98
|
const buttonX = contentWidth - padding - buttonSize;
|
|
103
99
|
const buttonY = (contentHeight - buttonSize) / 2;
|
|
104
100
|
const isSecure = protocol === "https:";
|
|
105
101
|
const subtitleX = isSecure ? textX + 13 : textX;
|
|
106
102
|
const subtitleWidth = isSecure ? textWidth - 13 : textWidth;
|
|
107
|
-
const faviconImage = favicon ? `<image class="canvu-link-favicon-img" href="${escapeXmlAttribute(favicon)}" x="${formatNumber(padding)}" y="${formatNumber(padding)}" width="${formatNumber(badgeSize)}" height="${formatNumber(badgeSize)}" preserveAspectRatio="xMidYMid slice" clip-path="url(#${clipId})" />` : "";
|
|
108
103
|
return `
|
|
109
104
|
<style>
|
|
110
105
|
.canvu-link-card-root .canvu-link-card { transition: transform .18s ease, filter .18s ease, stroke .18s ease; }
|
|
@@ -119,13 +114,9 @@ function buildLinkCardSvg(width, _height, link) {
|
|
|
119
114
|
<stop stop-color="${LINK_CARD_ACCENT}" />
|
|
120
115
|
<stop offset="1" stop-color="${LINK_CARD_ACCENT_DEEP}" />
|
|
121
116
|
</linearGradient>
|
|
122
|
-
<clipPath id="${clipId}">
|
|
123
|
-
<rect x="${formatNumber(padding)}" y="${formatNumber(padding)}" width="${formatNumber(badgeSize)}" height="${formatNumber(badgeSize)}" rx="11" />
|
|
124
|
-
</clipPath>
|
|
125
117
|
</defs>
|
|
126
118
|
<rect x="${formatNumber(padding)}" y="${formatNumber(padding)}" width="${formatNumber(badgeSize)}" height="${formatNumber(badgeSize)}" rx="11" fill="url(#${gradientId})" />
|
|
127
119
|
<text x="${formatNumber(padding + badgeSize / 2)}" y="${formatNumber(padding + badgeSize / 2 + 5)}" text-anchor="middle" font-family="system-ui,sans-serif" font-size="17" font-weight="700" fill="#ffffff">${escapeHtmlText(getLinkInitial(hostname))}</text>
|
|
128
|
-
${faviconImage}
|
|
129
120
|
${buildLinkTextBand({ x: textX, y: 16, width: textWidth, height: 19, text: title, fontSize: 14.5, color: LINK_CARD_TITLE_COLOR, fontWeight: 700 })}
|
|
130
121
|
${isSecure ? `<g transform="translate(${formatNumber(textX)},40)" stroke="${LINK_CARD_TEXT_COLOR}" stroke-width="1.3" stroke-linecap="round" stroke-linejoin="round" fill="none"><rect x="1.5" y="4.5" width="7" height="6" rx="1" /><path d="M3 4.5 V3 a2 2 0 0 1 4 0 v1.5" /></g>` : ""}
|
|
131
122
|
${buildLinkTextBand({ x: subtitleX, y: 36, width: subtitleWidth, height: 17, text: subtitle, fontSize: 12.5, color: LINK_CARD_TEXT_COLOR })}
|
|
@@ -1363,6 +1354,17 @@ function computeResizeBoundsFixedAspect(bounds, handle, currentWorld, aspect) {
|
|
|
1363
1354
|
}
|
|
1364
1355
|
}
|
|
1365
1356
|
|
|
1357
|
+
// src/react/presence/peer-color.ts
|
|
1358
|
+
function defaultPresenceColorForId(id) {
|
|
1359
|
+
let h = 2166136261;
|
|
1360
|
+
for (let i = 0; i < id.length; i++) {
|
|
1361
|
+
h ^= id.charCodeAt(i);
|
|
1362
|
+
h = Math.imul(h, 16777619);
|
|
1363
|
+
}
|
|
1364
|
+
const hue = (h >>> 0) % 360;
|
|
1365
|
+
return `hsl(${hue} 72% 42%)`;
|
|
1366
|
+
}
|
|
1367
|
+
|
|
1366
1368
|
// src/scene/freehand-path.ts
|
|
1367
1369
|
function smoothFreehandPointsToPathD(points) {
|
|
1368
1370
|
const n = points.length;
|
|
@@ -2281,6 +2283,26 @@ var HANDLE_ORDER = ["nw", "n", "ne", "e", "se", "s", "sw", "w"];
|
|
|
2281
2283
|
var ERASER_PREVIEW_OPACITY = 0.3;
|
|
2282
2284
|
var OVERLAY_STROKE_PX = 1.25;
|
|
2283
2285
|
var MARQUEE_DASH_PX = 4;
|
|
2286
|
+
var REMOTE_CURSOR_SCREEN_PX = 22;
|
|
2287
|
+
var REMOTE_LABEL_SCREEN_PX = 12;
|
|
2288
|
+
function remoteStrokePaint(tool, fallback) {
|
|
2289
|
+
if (tool === "laser") {
|
|
2290
|
+
return { stroke: LASER_TINT, strokeOpacity: 0.92, widthWorld: 4 };
|
|
2291
|
+
}
|
|
2292
|
+
if (tool === "marker") {
|
|
2293
|
+
return { stroke: fallback, strokeOpacity: 0.45, widthWorld: 14 };
|
|
2294
|
+
}
|
|
2295
|
+
if (tool === "brush") {
|
|
2296
|
+
return { stroke: fallback, strokeOpacity: 0.85, widthWorld: 5 };
|
|
2297
|
+
}
|
|
2298
|
+
if (tool === "pencil") {
|
|
2299
|
+
return { stroke: fallback, strokeOpacity: 0.9, widthWorld: 2.5 };
|
|
2300
|
+
}
|
|
2301
|
+
return { stroke: fallback, strokeOpacity: 0.95, widthWorld: 3.5 };
|
|
2302
|
+
}
|
|
2303
|
+
function isRemoteFreehandTool(tool) {
|
|
2304
|
+
return tool === "draw" || tool === "marker" || tool === "pencil" || tool === "brush";
|
|
2305
|
+
}
|
|
2284
2306
|
function pointsToSmoothPathD(points) {
|
|
2285
2307
|
if (points.length < 2) return null;
|
|
2286
2308
|
const d = smoothFreehandPointsToPathD(points);
|
|
@@ -2301,7 +2323,8 @@ function NativeInteractionOverlay({
|
|
|
2301
2323
|
eraserTrail,
|
|
2302
2324
|
laserTrail,
|
|
2303
2325
|
eraserPreviewItems = [],
|
|
2304
|
-
previewStrokeStyle
|
|
2326
|
+
previewStrokeStyle,
|
|
2327
|
+
remotePresence = []
|
|
2305
2328
|
}) {
|
|
2306
2329
|
const z = camera.zoom;
|
|
2307
2330
|
const camTransform = skiaCameraTransform(z, camera.x, camera.y);
|
|
@@ -2695,6 +2718,136 @@ function NativeInteractionOverlay({
|
|
|
2695
2718
|
)
|
|
2696
2719
|
] });
|
|
2697
2720
|
}, [laserTrail, z]);
|
|
2721
|
+
const remotePresenceElements = useMemo(() => {
|
|
2722
|
+
if (remotePresence.length === 0) return null;
|
|
2723
|
+
const labelFont = matchFont({ fontSize: REMOTE_LABEL_SCREEN_PX / z });
|
|
2724
|
+
const cursorSize = REMOTE_CURSOR_SCREEN_PX / z;
|
|
2725
|
+
const labelOffsetX = 14 / z;
|
|
2726
|
+
const labelOffsetY = 18 / z;
|
|
2727
|
+
return /* @__PURE__ */ jsx(Fragment, { children: remotePresence.map((peer) => {
|
|
2728
|
+
const color = peer.color ?? defaultPresenceColorForId(peer.id);
|
|
2729
|
+
const markup = peer.markupStroke;
|
|
2730
|
+
const cursor = peer.cursor;
|
|
2731
|
+
const camera2 = peer.camera;
|
|
2732
|
+
let strokeElement = null;
|
|
2733
|
+
if (markup && markup.points.length > 0) {
|
|
2734
|
+
const fallbackPaint = remoteStrokePaint(markup.tool, color);
|
|
2735
|
+
const paint = {
|
|
2736
|
+
stroke: markup.stroke ?? fallbackPaint.stroke,
|
|
2737
|
+
strokeOpacity: markup.strokeOpacity ?? fallbackPaint.strokeOpacity,
|
|
2738
|
+
widthWorld: markup.strokeWidth ?? fallbackPaint.widthWorld
|
|
2739
|
+
};
|
|
2740
|
+
if (markup.tool === "laser") {
|
|
2741
|
+
const d = markup.points.length >= 2 ? smoothFreehandPointsToPathD([...markup.points]) : null;
|
|
2742
|
+
if (d) {
|
|
2743
|
+
strokeElement = /* @__PURE__ */ jsx(
|
|
2744
|
+
Path,
|
|
2745
|
+
{
|
|
2746
|
+
path: d,
|
|
2747
|
+
color: colorWithOpacity(paint.stroke, paint.strokeOpacity),
|
|
2748
|
+
style: "stroke",
|
|
2749
|
+
strokeWidth: Math.max(paint.widthWorld, OVERLAY_STROKE_PX) / z,
|
|
2750
|
+
strokeCap: "round",
|
|
2751
|
+
strokeJoin: "round",
|
|
2752
|
+
antiAlias: true
|
|
2753
|
+
}
|
|
2754
|
+
);
|
|
2755
|
+
}
|
|
2756
|
+
}
|
|
2757
|
+
if (!strokeElement && isRemoteFreehandTool(markup.tool)) {
|
|
2758
|
+
const payload = computeFreehandSvgPayload(
|
|
2759
|
+
markup.points.map((point) => ({ x: point.x, y: point.y })),
|
|
2760
|
+
{
|
|
2761
|
+
stroke: paint.stroke,
|
|
2762
|
+
strokeWidth: paint.widthWorld,
|
|
2763
|
+
strokeOpacity: paint.strokeOpacity
|
|
2764
|
+
},
|
|
2765
|
+
markup.tool,
|
|
2766
|
+
markup.points.length === 2
|
|
2767
|
+
);
|
|
2768
|
+
if (payload?.kind === "circle") {
|
|
2769
|
+
strokeElement = /* @__PURE__ */ jsx(
|
|
2770
|
+
Circle,
|
|
2771
|
+
{
|
|
2772
|
+
cx: payload.cx,
|
|
2773
|
+
cy: payload.cy,
|
|
2774
|
+
r: payload.r,
|
|
2775
|
+
color: colorWithOpacity(payload.fill, payload.fillOpacity),
|
|
2776
|
+
style: "fill",
|
|
2777
|
+
antiAlias: true
|
|
2778
|
+
}
|
|
2779
|
+
);
|
|
2780
|
+
}
|
|
2781
|
+
if (payload?.kind === "fillPath") {
|
|
2782
|
+
strokeElement = /* @__PURE__ */ jsx(
|
|
2783
|
+
Path,
|
|
2784
|
+
{
|
|
2785
|
+
path: payload.d,
|
|
2786
|
+
color: colorWithOpacity(payload.fill, payload.fillOpacity),
|
|
2787
|
+
style: "fill",
|
|
2788
|
+
fillType: "winding",
|
|
2789
|
+
antiAlias: true
|
|
2790
|
+
}
|
|
2791
|
+
);
|
|
2792
|
+
}
|
|
2793
|
+
if (payload?.kind === "strokePath") {
|
|
2794
|
+
strokeElement = /* @__PURE__ */ jsx(
|
|
2795
|
+
Path,
|
|
2796
|
+
{
|
|
2797
|
+
path: payload.d,
|
|
2798
|
+
color: colorWithOpacity(payload.stroke, payload.strokeOpacity),
|
|
2799
|
+
style: "stroke",
|
|
2800
|
+
strokeWidth: payload.strokeWidth,
|
|
2801
|
+
strokeCap: "round",
|
|
2802
|
+
strokeJoin: "round",
|
|
2803
|
+
antiAlias: true
|
|
2804
|
+
}
|
|
2805
|
+
);
|
|
2806
|
+
}
|
|
2807
|
+
}
|
|
2808
|
+
}
|
|
2809
|
+
const cameraElement = camera2 ? /* @__PURE__ */ jsx(
|
|
2810
|
+
Rect,
|
|
2811
|
+
{
|
|
2812
|
+
x: -camera2.x / camera2.zoom,
|
|
2813
|
+
y: -camera2.y / camera2.zoom,
|
|
2814
|
+
width: camera2.viewportWidth / camera2.zoom,
|
|
2815
|
+
height: camera2.viewportHeight / camera2.zoom,
|
|
2816
|
+
color,
|
|
2817
|
+
style: "stroke",
|
|
2818
|
+
strokeWidth: overlayStrokeWorld,
|
|
2819
|
+
antiAlias: true,
|
|
2820
|
+
children: /* @__PURE__ */ jsx(DashPathEffect, { intervals: [marqueeDashWorld, marqueeDashWorld] })
|
|
2821
|
+
}
|
|
2822
|
+
) : null;
|
|
2823
|
+
const cursorElement = cursor ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
2824
|
+
/* @__PURE__ */ jsx(
|
|
2825
|
+
Path,
|
|
2826
|
+
{
|
|
2827
|
+
path: `M ${cursor.x} ${cursor.y} L ${cursor.x + cursorSize} ${cursor.y + cursorSize * 0.34} L ${cursor.x + cursorSize * 0.42} ${cursor.y + cursorSize * 0.44} L ${cursor.x + cursorSize * 0.58} ${cursor.y + cursorSize} Z`,
|
|
2828
|
+
color,
|
|
2829
|
+
style: "fill",
|
|
2830
|
+
antiAlias: true
|
|
2831
|
+
}
|
|
2832
|
+
),
|
|
2833
|
+
peer.displayName ? /* @__PURE__ */ jsx(
|
|
2834
|
+
Text,
|
|
2835
|
+
{
|
|
2836
|
+
x: cursor.x + labelOffsetX,
|
|
2837
|
+
y: cursor.y + labelOffsetY,
|
|
2838
|
+
text: peer.displayName,
|
|
2839
|
+
color,
|
|
2840
|
+
font: labelFont
|
|
2841
|
+
}
|
|
2842
|
+
) : null
|
|
2843
|
+
] }) : null;
|
|
2844
|
+
return /* @__PURE__ */ jsxs(Group, { children: [
|
|
2845
|
+
cameraElement,
|
|
2846
|
+
strokeElement,
|
|
2847
|
+
cursorElement
|
|
2848
|
+
] }, peer.clientId ?? peer.id);
|
|
2849
|
+
}) });
|
|
2850
|
+
}, [remotePresence, z, overlayStrokeWorld, marqueeDashWorld]);
|
|
2698
2851
|
if (width <= 0 || height <= 0) return null;
|
|
2699
2852
|
return /* @__PURE__ */ jsx(
|
|
2700
2853
|
Canvas,
|
|
@@ -2712,6 +2865,7 @@ function NativeInteractionOverlay({
|
|
|
2712
2865
|
laserTrailElements,
|
|
2713
2866
|
eraserTrailElements,
|
|
2714
2867
|
eraserPreviewElements,
|
|
2868
|
+
remotePresenceElements,
|
|
2715
2869
|
selectionElements
|
|
2716
2870
|
] })
|
|
2717
2871
|
}
|
|
@@ -4214,6 +4368,7 @@ function fitCameraToWorldRect(camera, viewportW, viewportH, worldRect, padding)
|
|
|
4214
4368
|
var NativeVectorViewport = forwardRef(function NativeVectorViewport2({
|
|
4215
4369
|
items,
|
|
4216
4370
|
selectedIds = [],
|
|
4371
|
+
remotePresence = [],
|
|
4217
4372
|
toolId = "hand",
|
|
4218
4373
|
toolLocked = false,
|
|
4219
4374
|
interactive = false,
|
|
@@ -4221,6 +4376,9 @@ var NativeVectorViewport = forwardRef(function NativeVectorViewport2({
|
|
|
4221
4376
|
onItemsChange,
|
|
4222
4377
|
onToolChangeRequest,
|
|
4223
4378
|
onWorldPointerDown,
|
|
4379
|
+
onWorldPointerMove,
|
|
4380
|
+
onWorldPointerLeave,
|
|
4381
|
+
onPlacementPreviewChange,
|
|
4224
4382
|
onCameraChange,
|
|
4225
4383
|
customPlacement,
|
|
4226
4384
|
customPlacements = [],
|
|
@@ -4238,6 +4396,12 @@ var NativeVectorViewport = forwardRef(function NativeVectorViewport2({
|
|
|
4238
4396
|
onToolChangeRequestRef.current = onToolChangeRequest;
|
|
4239
4397
|
const onWorldPointerDownRef = useRef(onWorldPointerDown);
|
|
4240
4398
|
onWorldPointerDownRef.current = onWorldPointerDown;
|
|
4399
|
+
const onWorldPointerMoveRef = useRef(onWorldPointerMove);
|
|
4400
|
+
onWorldPointerMoveRef.current = onWorldPointerMove;
|
|
4401
|
+
const onWorldPointerLeaveRef = useRef(onWorldPointerLeave);
|
|
4402
|
+
onWorldPointerLeaveRef.current = onWorldPointerLeave;
|
|
4403
|
+
const onPlacementPreviewChangeRef = useRef(onPlacementPreviewChange);
|
|
4404
|
+
onPlacementPreviewChangeRef.current = onPlacementPreviewChange;
|
|
4241
4405
|
const onCameraChangeRef = useRef(onCameraChange);
|
|
4242
4406
|
onCameraChangeRef.current = onCameraChange;
|
|
4243
4407
|
const onItemsChangeRef = useRef(onItemsChange);
|
|
@@ -4253,8 +4417,13 @@ var NativeVectorViewport = forwardRef(function NativeVectorViewport2({
|
|
|
4253
4417
|
const selectedIdsRef = useRef(selectedIds);
|
|
4254
4418
|
selectedIdsRef.current = selectedIds;
|
|
4255
4419
|
const dragStateRef = useRef({ kind: "idle" });
|
|
4256
|
-
const [placementPreview,
|
|
4257
|
-
|
|
4420
|
+
const [placementPreview, setPlacementPreviewState] = useState(null);
|
|
4421
|
+
const setRealtimePlacementPreview = useCallback(
|
|
4422
|
+
(nextPreview) => {
|
|
4423
|
+
setPlacementPreviewState(nextPreview);
|
|
4424
|
+
onPlacementPreviewChangeRef.current?.(nextPreview);
|
|
4425
|
+
},
|
|
4426
|
+
[]
|
|
4258
4427
|
);
|
|
4259
4428
|
const [eraserTrail, setEraserTrail] = useState([]);
|
|
4260
4429
|
const [laserTrail, setLaserTrail] = useState([]);
|
|
@@ -4348,6 +4517,16 @@ var NativeVectorViewport = forwardRef(function NativeVectorViewport2({
|
|
|
4348
4517
|
},
|
|
4349
4518
|
[]
|
|
4350
4519
|
);
|
|
4520
|
+
const notifyWorldPointerMove = useCallback(
|
|
4521
|
+
(point) => {
|
|
4522
|
+
const { worldX, worldY } = screenToWorld(point.x, point.y);
|
|
4523
|
+
onWorldPointerMoveRef.current?.({ x: worldX, y: worldY });
|
|
4524
|
+
},
|
|
4525
|
+
[screenToWorld]
|
|
4526
|
+
);
|
|
4527
|
+
const notifyWorldPointerLeave = useCallback(() => {
|
|
4528
|
+
onWorldPointerLeaveRef.current?.();
|
|
4529
|
+
}, []);
|
|
4351
4530
|
const requestRender = useCallback(() => {
|
|
4352
4531
|
setCameraTick((n) => n + 1);
|
|
4353
4532
|
onCameraChangeRef.current?.();
|
|
@@ -4387,6 +4566,7 @@ var NativeVectorViewport = forwardRef(function NativeVectorViewport2({
|
|
|
4387
4566
|
const cam = cameraRef.current;
|
|
4388
4567
|
if (!cam) return;
|
|
4389
4568
|
const { worldX, worldY } = screenToWorld(sx, sy);
|
|
4569
|
+
onWorldPointerMoveRef.current?.({ x: worldX, y: worldY });
|
|
4390
4570
|
if (tool === "hand") {
|
|
4391
4571
|
dragStateRef.current = { kind: "pan" };
|
|
4392
4572
|
return;
|
|
@@ -4472,7 +4652,7 @@ var NativeVectorViewport = forwardRef(function NativeVectorViewport2({
|
|
|
4472
4652
|
kind: "marquee",
|
|
4473
4653
|
startWorld: { x: worldX, y: worldY }
|
|
4474
4654
|
};
|
|
4475
|
-
|
|
4655
|
+
setRealtimePlacementPreview({
|
|
4476
4656
|
kind: "marquee",
|
|
4477
4657
|
rect: { x: worldX, y: worldY, width: 0, height: 0 }
|
|
4478
4658
|
});
|
|
@@ -4492,7 +4672,7 @@ var NativeVectorViewport = forwardRef(function NativeVectorViewport2({
|
|
|
4492
4672
|
}
|
|
4493
4673
|
setLaserTrail([{ x: worldX, y: worldY, t: Date.now() }]);
|
|
4494
4674
|
} else {
|
|
4495
|
-
|
|
4675
|
+
setRealtimePlacementPreview({
|
|
4496
4676
|
kind: "stroke",
|
|
4497
4677
|
tool,
|
|
4498
4678
|
points: [{ x: worldX, y: worldY }],
|
|
@@ -4525,7 +4705,7 @@ var NativeVectorViewport = forwardRef(function NativeVectorViewport2({
|
|
|
4525
4705
|
startWorld: { x: worldX, y: worldY },
|
|
4526
4706
|
startScreen: { x: sx, y: sy }
|
|
4527
4707
|
};
|
|
4528
|
-
|
|
4708
|
+
setRealtimePlacementPreview(
|
|
4529
4709
|
placementPreviewForTool(
|
|
4530
4710
|
tool,
|
|
4531
4711
|
{ x: worldX, y: worldY },
|
|
@@ -4550,7 +4730,7 @@ var NativeVectorViewport = forwardRef(function NativeVectorViewport2({
|
|
|
4550
4730
|
startWorld: { x: worldX, y: worldY },
|
|
4551
4731
|
startScreen: { x: sx, y: sy }
|
|
4552
4732
|
};
|
|
4553
|
-
|
|
4733
|
+
setRealtimePlacementPreview({
|
|
4554
4734
|
kind: "rect",
|
|
4555
4735
|
rect: { x: worldX, y: worldY, width: 0, height: 0 }
|
|
4556
4736
|
});
|
|
@@ -4579,7 +4759,13 @@ var NativeVectorViewport = forwardRef(function NativeVectorViewport2({
|
|
|
4579
4759
|
}
|
|
4580
4760
|
dragStateRef.current = { kind: "pan" };
|
|
4581
4761
|
},
|
|
4582
|
-
[
|
|
4762
|
+
[
|
|
4763
|
+
interactive,
|
|
4764
|
+
requestSelectToolAfterUse,
|
|
4765
|
+
screenToWorld,
|
|
4766
|
+
setRealtimePlacementPreview,
|
|
4767
|
+
updateToolCursorPoint
|
|
4768
|
+
]
|
|
4583
4769
|
);
|
|
4584
4770
|
const applyDragMoveAtScreenPoint = useCallback(
|
|
4585
4771
|
(point, pagePoint) => {
|
|
@@ -4587,6 +4773,7 @@ var NativeVectorViewport = forwardRef(function NativeVectorViewport2({
|
|
|
4587
4773
|
if (!cam) return;
|
|
4588
4774
|
updateToolCursorPoint(point);
|
|
4589
4775
|
const { worldX, worldY } = screenToWorld(point.x, point.y);
|
|
4776
|
+
onWorldPointerMoveRef.current?.({ x: worldX, y: worldY });
|
|
4590
4777
|
const st = dragStateRef.current;
|
|
4591
4778
|
if (st.kind === "pan") {
|
|
4592
4779
|
const current = pagePoint ?? point;
|
|
@@ -4619,7 +4806,7 @@ var NativeVectorViewport = forwardRef(function NativeVectorViewport2({
|
|
|
4619
4806
|
}
|
|
4620
4807
|
return;
|
|
4621
4808
|
}
|
|
4622
|
-
|
|
4809
|
+
setRealtimePlacementPreview({
|
|
4623
4810
|
kind: "stroke",
|
|
4624
4811
|
tool: st.tool,
|
|
4625
4812
|
points: [...pts],
|
|
@@ -4681,7 +4868,7 @@ var NativeVectorViewport = forwardRef(function NativeVectorViewport2({
|
|
|
4681
4868
|
width: Math.abs(b.x - a.x),
|
|
4682
4869
|
height: Math.abs(b.y - a.y)
|
|
4683
4870
|
};
|
|
4684
|
-
|
|
4871
|
+
setRealtimePlacementPreview({ kind: "marquee", rect });
|
|
4685
4872
|
return;
|
|
4686
4873
|
}
|
|
4687
4874
|
if (st.kind === "erase") {
|
|
@@ -4699,7 +4886,7 @@ var NativeVectorViewport = forwardRef(function NativeVectorViewport2({
|
|
|
4699
4886
|
return;
|
|
4700
4887
|
}
|
|
4701
4888
|
if (st.kind === "place") {
|
|
4702
|
-
|
|
4889
|
+
setRealtimePlacementPreview(
|
|
4703
4890
|
placementPreviewForTool(st.tool, st.startWorld, {
|
|
4704
4891
|
x: worldX,
|
|
4705
4892
|
y: worldY
|
|
@@ -4708,14 +4895,19 @@ var NativeVectorViewport = forwardRef(function NativeVectorViewport2({
|
|
|
4708
4895
|
return;
|
|
4709
4896
|
}
|
|
4710
4897
|
if (st.kind === "custom-place") {
|
|
4711
|
-
|
|
4898
|
+
setRealtimePlacementPreview({
|
|
4712
4899
|
kind: "rect",
|
|
4713
4900
|
rect: rectFromCorners(st.startWorld, { x: worldX, y: worldY })
|
|
4714
4901
|
});
|
|
4715
4902
|
return;
|
|
4716
4903
|
}
|
|
4717
4904
|
},
|
|
4718
|
-
[
|
|
4905
|
+
[
|
|
4906
|
+
requestRender,
|
|
4907
|
+
screenToWorld,
|
|
4908
|
+
setRealtimePlacementPreview,
|
|
4909
|
+
updateToolCursorPoint
|
|
4910
|
+
]
|
|
4719
4911
|
);
|
|
4720
4912
|
const finishDragAtScreenPoint = useCallback(
|
|
4721
4913
|
(point) => {
|
|
@@ -4725,7 +4917,7 @@ var NativeVectorViewport = forwardRef(function NativeVectorViewport2({
|
|
|
4725
4917
|
const st = dragStateRef.current;
|
|
4726
4918
|
if (st.kind === "draw") {
|
|
4727
4919
|
dragStateRef.current = { kind: "idle" };
|
|
4728
|
-
|
|
4920
|
+
setRealtimePlacementPreview(null);
|
|
4729
4921
|
if (st.tool === "laser") {
|
|
4730
4922
|
if (laserClearTimerRef.current) {
|
|
4731
4923
|
clearTimeout(laserClearTimerRef.current);
|
|
@@ -4763,7 +4955,7 @@ var NativeVectorViewport = forwardRef(function NativeVectorViewport2({
|
|
|
4763
4955
|
}
|
|
4764
4956
|
if (st.kind === "marquee") {
|
|
4765
4957
|
dragStateRef.current = { kind: "idle" };
|
|
4766
|
-
|
|
4958
|
+
setRealtimePlacementPreview(null);
|
|
4767
4959
|
const cam = cameraRef.current;
|
|
4768
4960
|
if (!cam) return;
|
|
4769
4961
|
const { worldX, worldY } = screenToWorld(point.x, point.y);
|
|
@@ -4794,7 +4986,7 @@ var NativeVectorViewport = forwardRef(function NativeVectorViewport2({
|
|
|
4794
4986
|
}
|
|
4795
4987
|
if (st.kind === "place") {
|
|
4796
4988
|
dragStateRef.current = { kind: "idle" };
|
|
4797
|
-
|
|
4989
|
+
setRealtimePlacementPreview(null);
|
|
4798
4990
|
const change = onItemsChangeRef.current;
|
|
4799
4991
|
if (!change) return;
|
|
4800
4992
|
const { worldX, worldY } = screenToWorld(point.x, point.y);
|
|
@@ -4851,7 +5043,7 @@ var NativeVectorViewport = forwardRef(function NativeVectorViewport2({
|
|
|
4851
5043
|
}
|
|
4852
5044
|
if (st.kind === "custom-place") {
|
|
4853
5045
|
dragStateRef.current = { kind: "idle" };
|
|
4854
|
-
|
|
5046
|
+
setRealtimePlacementPreview(null);
|
|
4855
5047
|
const change = onItemsChangeRef.current;
|
|
4856
5048
|
if (!change) return;
|
|
4857
5049
|
const { worldX, worldY } = screenToWorld(point.x, point.y);
|
|
@@ -4926,7 +5118,12 @@ var NativeVectorViewport = forwardRef(function NativeVectorViewport2({
|
|
|
4926
5118
|
}
|
|
4927
5119
|
dragStateRef.current = { kind: "idle" };
|
|
4928
5120
|
},
|
|
4929
|
-
[
|
|
5121
|
+
[
|
|
5122
|
+
requestSelectToolAfterUse,
|
|
5123
|
+
screenToWorld,
|
|
5124
|
+
setRealtimePlacementPreview,
|
|
5125
|
+
updateToolCursorPoint
|
|
5126
|
+
]
|
|
4930
5127
|
);
|
|
4931
5128
|
const handlePointerDown = useCallback(
|
|
4932
5129
|
(event) => {
|
|
@@ -4942,9 +5139,10 @@ var NativeVectorViewport = forwardRef(function NativeVectorViewport2({
|
|
|
4942
5139
|
applyDragMoveAtScreenPoint(point, point);
|
|
4943
5140
|
return;
|
|
4944
5141
|
}
|
|
5142
|
+
notifyWorldPointerMove(point);
|
|
4945
5143
|
updateToolCursorPoint(point);
|
|
4946
5144
|
},
|
|
4947
|
-
[applyDragMoveAtScreenPoint, updateToolCursorPoint]
|
|
5145
|
+
[applyDragMoveAtScreenPoint, notifyWorldPointerMove, updateToolCursorPoint]
|
|
4948
5146
|
);
|
|
4949
5147
|
const handlePointerUp = useCallback(
|
|
4950
5148
|
(event) => {
|
|
@@ -4963,6 +5161,7 @@ var NativeVectorViewport = forwardRef(function NativeVectorViewport2({
|
|
|
4963
5161
|
const sy = evt.nativeEvent.locationY;
|
|
4964
5162
|
if (touches && touches.length >= 2) {
|
|
4965
5163
|
hideToolCursor();
|
|
5164
|
+
notifyWorldPointerLeave();
|
|
4966
5165
|
dragStateRef.current = { kind: "pan" };
|
|
4967
5166
|
return;
|
|
4968
5167
|
}
|
|
@@ -4978,6 +5177,7 @@ var NativeVectorViewport = forwardRef(function NativeVectorViewport2({
|
|
|
4978
5177
|
const pageY = evt.nativeEvent.pageY;
|
|
4979
5178
|
if (touches && touches.length >= 2) {
|
|
4980
5179
|
hideToolCursor();
|
|
5180
|
+
notifyWorldPointerLeave();
|
|
4981
5181
|
const t0 = touches[0];
|
|
4982
5182
|
const t1 = touches[1];
|
|
4983
5183
|
if (t0 && t1) {
|
|
@@ -5009,8 +5209,9 @@ var NativeVectorViewport = forwardRef(function NativeVectorViewport2({
|
|
|
5009
5209
|
lastPinchDist.current = null;
|
|
5010
5210
|
lastPanPoint.current = null;
|
|
5011
5211
|
hideToolCursor();
|
|
5212
|
+
notifyWorldPointerLeave();
|
|
5012
5213
|
dragStateRef.current = { kind: "idle" };
|
|
5013
|
-
|
|
5214
|
+
setRealtimePlacementPreview(null);
|
|
5014
5215
|
setLaserTrail([]);
|
|
5015
5216
|
setEraserTrail([]);
|
|
5016
5217
|
setEraserPreviewIds([]);
|
|
@@ -5022,7 +5223,9 @@ var NativeVectorViewport = forwardRef(function NativeVectorViewport2({
|
|
|
5022
5223
|
beginDragAtScreenPoint,
|
|
5023
5224
|
finishDragAtScreenPoint,
|
|
5024
5225
|
requestRender,
|
|
5025
|
-
hideToolCursor
|
|
5226
|
+
hideToolCursor,
|
|
5227
|
+
notifyWorldPointerLeave,
|
|
5228
|
+
setRealtimePlacementPreview
|
|
5026
5229
|
]
|
|
5027
5230
|
);
|
|
5028
5231
|
useImperativeHandle(
|
|
@@ -5056,7 +5259,10 @@ var NativeVectorViewport = forwardRef(function NativeVectorViewport2({
|
|
|
5056
5259
|
onPointerMove: handlePointerMove,
|
|
5057
5260
|
onPointerUp: handlePointerUp,
|
|
5058
5261
|
onPointerEnter: handlePointerMove,
|
|
5059
|
-
onPointerLeave:
|
|
5262
|
+
onPointerLeave: () => {
|
|
5263
|
+
hideToolCursor();
|
|
5264
|
+
notifyWorldPointerLeave();
|
|
5265
|
+
},
|
|
5060
5266
|
...panResponder.panHandlers,
|
|
5061
5267
|
children: size.width > 0 && size.height > 0 && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
5062
5268
|
/* @__PURE__ */ jsx(
|
|
@@ -5082,7 +5288,8 @@ var NativeVectorViewport = forwardRef(function NativeVectorViewport2({
|
|
|
5082
5288
|
eraserPreviewItems: items.filter(
|
|
5083
5289
|
(it) => eraserPreviewIds.includes(it.id)
|
|
5084
5290
|
),
|
|
5085
|
-
previewStrokeStyle: strokeStyleState
|
|
5291
|
+
previewStrokeStyle: strokeStyleState,
|
|
5292
|
+
remotePresence
|
|
5086
5293
|
}
|
|
5087
5294
|
),
|
|
5088
5295
|
interactive && showStyleInspector && activeStyleToolId ? /* @__PURE__ */ jsx(
|