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.cjs
CHANGED
|
@@ -40,7 +40,7 @@ var LINK_PLUGIN_KEY = "canvuLink";
|
|
|
40
40
|
var DEFAULT_LINK_CARD_WIDTH = 320;
|
|
41
41
|
var DEFAULT_LINK_CARD_HEIGHT = 70;
|
|
42
42
|
var LINK_CARD_MIN_SCALE = 0.6;
|
|
43
|
-
var LINK_CARD_MAX_SCALE =
|
|
43
|
+
var LINK_CARD_MAX_SCALE = 6;
|
|
44
44
|
var LINK_CARD_ASPECT = DEFAULT_LINK_CARD_WIDTH / DEFAULT_LINK_CARD_HEIGHT;
|
|
45
45
|
var LINK_CARD_BORDER = "oklch(0.918 0.008 255)";
|
|
46
46
|
var LINK_CARD_BORDER_STRONG = "oklch(0.86 0.012 255)";
|
|
@@ -53,7 +53,6 @@ var formatNumber = (value) => {
|
|
|
53
53
|
const rounded = Math.round(value * 100) / 100;
|
|
54
54
|
return Object.is(rounded, -0) ? "0" : String(rounded);
|
|
55
55
|
};
|
|
56
|
-
var escapeXmlAttribute = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
57
56
|
var escapeHtmlText = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">");
|
|
58
57
|
var getLinkHostname = (href) => {
|
|
59
58
|
try {
|
|
@@ -78,7 +77,6 @@ var getLinkInitial = (hostname) => {
|
|
|
78
77
|
const first = hostname.trim().charAt(0).toUpperCase();
|
|
79
78
|
return first || "L";
|
|
80
79
|
};
|
|
81
|
-
var buildGoogleFaviconUrl = (hostname) => hostname ? `https://www.google.com/s2/favicons?domain=${encodeURIComponent(hostname)}&sz=64` : null;
|
|
82
80
|
var getStableLinkIdSuffix = (value) => {
|
|
83
81
|
let hash = 0;
|
|
84
82
|
for (const char of value) {
|
|
@@ -101,16 +99,13 @@ function buildLinkCardSvg(width, _height, link) {
|
|
|
101
99
|
const title = link.title?.trim() || hostname || "Link";
|
|
102
100
|
const protocol = getLinkProtocol(link.href);
|
|
103
101
|
const subtitle = hostname || link.href;
|
|
104
|
-
const favicon = link.favicon?.trim() || buildGoogleFaviconUrl(hostname);
|
|
105
102
|
const idSuffix = getStableLinkIdSuffix(`${hostname}:${link.href}`);
|
|
106
|
-
const clipId = `canvu-link-favicon-${idSuffix}`;
|
|
107
103
|
const gradientId = `canvu-link-favicon-gradient-${idSuffix}`;
|
|
108
104
|
const buttonX = contentWidth - padding - buttonSize;
|
|
109
105
|
const buttonY = (contentHeight - buttonSize) / 2;
|
|
110
106
|
const isSecure = protocol === "https:";
|
|
111
107
|
const subtitleX = isSecure ? textX + 13 : textX;
|
|
112
108
|
const subtitleWidth = isSecure ? textWidth - 13 : textWidth;
|
|
113
|
-
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})" />` : "";
|
|
114
109
|
return `
|
|
115
110
|
<style>
|
|
116
111
|
.canvu-link-card-root .canvu-link-card { transition: transform .18s ease, filter .18s ease, stroke .18s ease; }
|
|
@@ -125,13 +120,9 @@ function buildLinkCardSvg(width, _height, link) {
|
|
|
125
120
|
<stop stop-color="${LINK_CARD_ACCENT}" />
|
|
126
121
|
<stop offset="1" stop-color="${LINK_CARD_ACCENT_DEEP}" />
|
|
127
122
|
</linearGradient>
|
|
128
|
-
<clipPath id="${clipId}">
|
|
129
|
-
<rect x="${formatNumber(padding)}" y="${formatNumber(padding)}" width="${formatNumber(badgeSize)}" height="${formatNumber(badgeSize)}" rx="11" />
|
|
130
|
-
</clipPath>
|
|
131
123
|
</defs>
|
|
132
124
|
<rect x="${formatNumber(padding)}" y="${formatNumber(padding)}" width="${formatNumber(badgeSize)}" height="${formatNumber(badgeSize)}" rx="11" fill="url(#${gradientId})" />
|
|
133
125
|
<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>
|
|
134
|
-
${faviconImage}
|
|
135
126
|
${buildLinkTextBand({ x: textX, y: 16, width: textWidth, height: 19, text: title, fontSize: 14.5, color: LINK_CARD_TITLE_COLOR, fontWeight: 700 })}
|
|
136
127
|
${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>` : ""}
|
|
137
128
|
${buildLinkTextBand({ x: subtitleX, y: 36, width: subtitleWidth, height: 17, text: subtitle, fontSize: 12.5, color: LINK_CARD_TEXT_COLOR })}
|
|
@@ -1369,6 +1360,17 @@ function computeResizeBoundsFixedAspect(bounds, handle, currentWorld, aspect) {
|
|
|
1369
1360
|
}
|
|
1370
1361
|
}
|
|
1371
1362
|
|
|
1363
|
+
// src/react/presence/peer-color.ts
|
|
1364
|
+
function defaultPresenceColorForId(id) {
|
|
1365
|
+
let h = 2166136261;
|
|
1366
|
+
for (let i = 0; i < id.length; i++) {
|
|
1367
|
+
h ^= id.charCodeAt(i);
|
|
1368
|
+
h = Math.imul(h, 16777619);
|
|
1369
|
+
}
|
|
1370
|
+
const hue = (h >>> 0) % 360;
|
|
1371
|
+
return `hsl(${hue} 72% 42%)`;
|
|
1372
|
+
}
|
|
1373
|
+
|
|
1372
1374
|
// src/scene/freehand-path.ts
|
|
1373
1375
|
function smoothFreehandPointsToPathD(points) {
|
|
1374
1376
|
const n = points.length;
|
|
@@ -2287,6 +2289,26 @@ var HANDLE_ORDER = ["nw", "n", "ne", "e", "se", "s", "sw", "w"];
|
|
|
2287
2289
|
var ERASER_PREVIEW_OPACITY = 0.3;
|
|
2288
2290
|
var OVERLAY_STROKE_PX = 1.25;
|
|
2289
2291
|
var MARQUEE_DASH_PX = 4;
|
|
2292
|
+
var REMOTE_CURSOR_SCREEN_PX = 22;
|
|
2293
|
+
var REMOTE_LABEL_SCREEN_PX = 12;
|
|
2294
|
+
function remoteStrokePaint(tool, fallback) {
|
|
2295
|
+
if (tool === "laser") {
|
|
2296
|
+
return { stroke: LASER_TINT, strokeOpacity: 0.92, widthWorld: 4 };
|
|
2297
|
+
}
|
|
2298
|
+
if (tool === "marker") {
|
|
2299
|
+
return { stroke: fallback, strokeOpacity: 0.45, widthWorld: 14 };
|
|
2300
|
+
}
|
|
2301
|
+
if (tool === "brush") {
|
|
2302
|
+
return { stroke: fallback, strokeOpacity: 0.85, widthWorld: 5 };
|
|
2303
|
+
}
|
|
2304
|
+
if (tool === "pencil") {
|
|
2305
|
+
return { stroke: fallback, strokeOpacity: 0.9, widthWorld: 2.5 };
|
|
2306
|
+
}
|
|
2307
|
+
return { stroke: fallback, strokeOpacity: 0.95, widthWorld: 3.5 };
|
|
2308
|
+
}
|
|
2309
|
+
function isRemoteFreehandTool(tool) {
|
|
2310
|
+
return tool === "draw" || tool === "marker" || tool === "pencil" || tool === "brush";
|
|
2311
|
+
}
|
|
2290
2312
|
function pointsToSmoothPathD(points) {
|
|
2291
2313
|
if (points.length < 2) return null;
|
|
2292
2314
|
const d = smoothFreehandPointsToPathD(points);
|
|
@@ -2307,7 +2329,8 @@ function NativeInteractionOverlay({
|
|
|
2307
2329
|
eraserTrail,
|
|
2308
2330
|
laserTrail,
|
|
2309
2331
|
eraserPreviewItems = [],
|
|
2310
|
-
previewStrokeStyle
|
|
2332
|
+
previewStrokeStyle,
|
|
2333
|
+
remotePresence = []
|
|
2311
2334
|
}) {
|
|
2312
2335
|
const z = camera.zoom;
|
|
2313
2336
|
const camTransform = skiaCameraTransform(z, camera.x, camera.y);
|
|
@@ -2701,6 +2724,136 @@ function NativeInteractionOverlay({
|
|
|
2701
2724
|
)
|
|
2702
2725
|
] });
|
|
2703
2726
|
}, [laserTrail, z]);
|
|
2727
|
+
const remotePresenceElements = react.useMemo(() => {
|
|
2728
|
+
if (remotePresence.length === 0) return null;
|
|
2729
|
+
const labelFont = reactNativeSkia.matchFont({ fontSize: REMOTE_LABEL_SCREEN_PX / z });
|
|
2730
|
+
const cursorSize = REMOTE_CURSOR_SCREEN_PX / z;
|
|
2731
|
+
const labelOffsetX = 14 / z;
|
|
2732
|
+
const labelOffsetY = 18 / z;
|
|
2733
|
+
return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: remotePresence.map((peer) => {
|
|
2734
|
+
const color = peer.color ?? defaultPresenceColorForId(peer.id);
|
|
2735
|
+
const markup = peer.markupStroke;
|
|
2736
|
+
const cursor = peer.cursor;
|
|
2737
|
+
const camera2 = peer.camera;
|
|
2738
|
+
let strokeElement = null;
|
|
2739
|
+
if (markup && markup.points.length > 0) {
|
|
2740
|
+
const fallbackPaint = remoteStrokePaint(markup.tool, color);
|
|
2741
|
+
const paint = {
|
|
2742
|
+
stroke: markup.stroke ?? fallbackPaint.stroke,
|
|
2743
|
+
strokeOpacity: markup.strokeOpacity ?? fallbackPaint.strokeOpacity,
|
|
2744
|
+
widthWorld: markup.strokeWidth ?? fallbackPaint.widthWorld
|
|
2745
|
+
};
|
|
2746
|
+
if (markup.tool === "laser") {
|
|
2747
|
+
const d = markup.points.length >= 2 ? smoothFreehandPointsToPathD([...markup.points]) : null;
|
|
2748
|
+
if (d) {
|
|
2749
|
+
strokeElement = /* @__PURE__ */ jsxRuntime.jsx(
|
|
2750
|
+
reactNativeSkia.Path,
|
|
2751
|
+
{
|
|
2752
|
+
path: d,
|
|
2753
|
+
color: colorWithOpacity(paint.stroke, paint.strokeOpacity),
|
|
2754
|
+
style: "stroke",
|
|
2755
|
+
strokeWidth: Math.max(paint.widthWorld, OVERLAY_STROKE_PX) / z,
|
|
2756
|
+
strokeCap: "round",
|
|
2757
|
+
strokeJoin: "round",
|
|
2758
|
+
antiAlias: true
|
|
2759
|
+
}
|
|
2760
|
+
);
|
|
2761
|
+
}
|
|
2762
|
+
}
|
|
2763
|
+
if (!strokeElement && isRemoteFreehandTool(markup.tool)) {
|
|
2764
|
+
const payload = computeFreehandSvgPayload(
|
|
2765
|
+
markup.points.map((point) => ({ x: point.x, y: point.y })),
|
|
2766
|
+
{
|
|
2767
|
+
stroke: paint.stroke,
|
|
2768
|
+
strokeWidth: paint.widthWorld,
|
|
2769
|
+
strokeOpacity: paint.strokeOpacity
|
|
2770
|
+
},
|
|
2771
|
+
markup.tool,
|
|
2772
|
+
markup.points.length === 2
|
|
2773
|
+
);
|
|
2774
|
+
if (payload?.kind === "circle") {
|
|
2775
|
+
strokeElement = /* @__PURE__ */ jsxRuntime.jsx(
|
|
2776
|
+
reactNativeSkia.Circle,
|
|
2777
|
+
{
|
|
2778
|
+
cx: payload.cx,
|
|
2779
|
+
cy: payload.cy,
|
|
2780
|
+
r: payload.r,
|
|
2781
|
+
color: colorWithOpacity(payload.fill, payload.fillOpacity),
|
|
2782
|
+
style: "fill",
|
|
2783
|
+
antiAlias: true
|
|
2784
|
+
}
|
|
2785
|
+
);
|
|
2786
|
+
}
|
|
2787
|
+
if (payload?.kind === "fillPath") {
|
|
2788
|
+
strokeElement = /* @__PURE__ */ jsxRuntime.jsx(
|
|
2789
|
+
reactNativeSkia.Path,
|
|
2790
|
+
{
|
|
2791
|
+
path: payload.d,
|
|
2792
|
+
color: colorWithOpacity(payload.fill, payload.fillOpacity),
|
|
2793
|
+
style: "fill",
|
|
2794
|
+
fillType: "winding",
|
|
2795
|
+
antiAlias: true
|
|
2796
|
+
}
|
|
2797
|
+
);
|
|
2798
|
+
}
|
|
2799
|
+
if (payload?.kind === "strokePath") {
|
|
2800
|
+
strokeElement = /* @__PURE__ */ jsxRuntime.jsx(
|
|
2801
|
+
reactNativeSkia.Path,
|
|
2802
|
+
{
|
|
2803
|
+
path: payload.d,
|
|
2804
|
+
color: colorWithOpacity(payload.stroke, payload.strokeOpacity),
|
|
2805
|
+
style: "stroke",
|
|
2806
|
+
strokeWidth: payload.strokeWidth,
|
|
2807
|
+
strokeCap: "round",
|
|
2808
|
+
strokeJoin: "round",
|
|
2809
|
+
antiAlias: true
|
|
2810
|
+
}
|
|
2811
|
+
);
|
|
2812
|
+
}
|
|
2813
|
+
}
|
|
2814
|
+
}
|
|
2815
|
+
const cameraElement = camera2 ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
2816
|
+
reactNativeSkia.Rect,
|
|
2817
|
+
{
|
|
2818
|
+
x: -camera2.x / camera2.zoom,
|
|
2819
|
+
y: -camera2.y / camera2.zoom,
|
|
2820
|
+
width: camera2.viewportWidth / camera2.zoom,
|
|
2821
|
+
height: camera2.viewportHeight / camera2.zoom,
|
|
2822
|
+
color,
|
|
2823
|
+
style: "stroke",
|
|
2824
|
+
strokeWidth: overlayStrokeWorld,
|
|
2825
|
+
antiAlias: true,
|
|
2826
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(reactNativeSkia.DashPathEffect, { intervals: [marqueeDashWorld, marqueeDashWorld] })
|
|
2827
|
+
}
|
|
2828
|
+
) : null;
|
|
2829
|
+
const cursorElement = cursor ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
2830
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2831
|
+
reactNativeSkia.Path,
|
|
2832
|
+
{
|
|
2833
|
+
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`,
|
|
2834
|
+
color,
|
|
2835
|
+
style: "fill",
|
|
2836
|
+
antiAlias: true
|
|
2837
|
+
}
|
|
2838
|
+
),
|
|
2839
|
+
peer.displayName ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
2840
|
+
reactNativeSkia.Text,
|
|
2841
|
+
{
|
|
2842
|
+
x: cursor.x + labelOffsetX,
|
|
2843
|
+
y: cursor.y + labelOffsetY,
|
|
2844
|
+
text: peer.displayName,
|
|
2845
|
+
color,
|
|
2846
|
+
font: labelFont
|
|
2847
|
+
}
|
|
2848
|
+
) : null
|
|
2849
|
+
] }) : null;
|
|
2850
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(reactNativeSkia.Group, { children: [
|
|
2851
|
+
cameraElement,
|
|
2852
|
+
strokeElement,
|
|
2853
|
+
cursorElement
|
|
2854
|
+
] }, peer.clientId ?? peer.id);
|
|
2855
|
+
}) });
|
|
2856
|
+
}, [remotePresence, z, overlayStrokeWorld, marqueeDashWorld]);
|
|
2704
2857
|
if (width <= 0 || height <= 0) return null;
|
|
2705
2858
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
2706
2859
|
reactNativeSkia.Canvas,
|
|
@@ -2718,6 +2871,7 @@ function NativeInteractionOverlay({
|
|
|
2718
2871
|
laserTrailElements,
|
|
2719
2872
|
eraserTrailElements,
|
|
2720
2873
|
eraserPreviewElements,
|
|
2874
|
+
remotePresenceElements,
|
|
2721
2875
|
selectionElements
|
|
2722
2876
|
] })
|
|
2723
2877
|
}
|
|
@@ -4220,6 +4374,7 @@ function fitCameraToWorldRect(camera, viewportW, viewportH, worldRect, padding)
|
|
|
4220
4374
|
var NativeVectorViewport = react.forwardRef(function NativeVectorViewport2({
|
|
4221
4375
|
items,
|
|
4222
4376
|
selectedIds = [],
|
|
4377
|
+
remotePresence = [],
|
|
4223
4378
|
toolId = "hand",
|
|
4224
4379
|
toolLocked = false,
|
|
4225
4380
|
interactive = false,
|
|
@@ -4227,6 +4382,9 @@ var NativeVectorViewport = react.forwardRef(function NativeVectorViewport2({
|
|
|
4227
4382
|
onItemsChange,
|
|
4228
4383
|
onToolChangeRequest,
|
|
4229
4384
|
onWorldPointerDown,
|
|
4385
|
+
onWorldPointerMove,
|
|
4386
|
+
onWorldPointerLeave,
|
|
4387
|
+
onPlacementPreviewChange,
|
|
4230
4388
|
onCameraChange,
|
|
4231
4389
|
customPlacement,
|
|
4232
4390
|
customPlacements = [],
|
|
@@ -4244,6 +4402,12 @@ var NativeVectorViewport = react.forwardRef(function NativeVectorViewport2({
|
|
|
4244
4402
|
onToolChangeRequestRef.current = onToolChangeRequest;
|
|
4245
4403
|
const onWorldPointerDownRef = react.useRef(onWorldPointerDown);
|
|
4246
4404
|
onWorldPointerDownRef.current = onWorldPointerDown;
|
|
4405
|
+
const onWorldPointerMoveRef = react.useRef(onWorldPointerMove);
|
|
4406
|
+
onWorldPointerMoveRef.current = onWorldPointerMove;
|
|
4407
|
+
const onWorldPointerLeaveRef = react.useRef(onWorldPointerLeave);
|
|
4408
|
+
onWorldPointerLeaveRef.current = onWorldPointerLeave;
|
|
4409
|
+
const onPlacementPreviewChangeRef = react.useRef(onPlacementPreviewChange);
|
|
4410
|
+
onPlacementPreviewChangeRef.current = onPlacementPreviewChange;
|
|
4247
4411
|
const onCameraChangeRef = react.useRef(onCameraChange);
|
|
4248
4412
|
onCameraChangeRef.current = onCameraChange;
|
|
4249
4413
|
const onItemsChangeRef = react.useRef(onItemsChange);
|
|
@@ -4259,8 +4423,13 @@ var NativeVectorViewport = react.forwardRef(function NativeVectorViewport2({
|
|
|
4259
4423
|
const selectedIdsRef = react.useRef(selectedIds);
|
|
4260
4424
|
selectedIdsRef.current = selectedIds;
|
|
4261
4425
|
const dragStateRef = react.useRef({ kind: "idle" });
|
|
4262
|
-
const [placementPreview,
|
|
4263
|
-
|
|
4426
|
+
const [placementPreview, setPlacementPreviewState] = react.useState(null);
|
|
4427
|
+
const setRealtimePlacementPreview = react.useCallback(
|
|
4428
|
+
(nextPreview) => {
|
|
4429
|
+
setPlacementPreviewState(nextPreview);
|
|
4430
|
+
onPlacementPreviewChangeRef.current?.(nextPreview);
|
|
4431
|
+
},
|
|
4432
|
+
[]
|
|
4264
4433
|
);
|
|
4265
4434
|
const [eraserTrail, setEraserTrail] = react.useState([]);
|
|
4266
4435
|
const [laserTrail, setLaserTrail] = react.useState([]);
|
|
@@ -4354,6 +4523,16 @@ var NativeVectorViewport = react.forwardRef(function NativeVectorViewport2({
|
|
|
4354
4523
|
},
|
|
4355
4524
|
[]
|
|
4356
4525
|
);
|
|
4526
|
+
const notifyWorldPointerMove = react.useCallback(
|
|
4527
|
+
(point) => {
|
|
4528
|
+
const { worldX, worldY } = screenToWorld(point.x, point.y);
|
|
4529
|
+
onWorldPointerMoveRef.current?.({ x: worldX, y: worldY });
|
|
4530
|
+
},
|
|
4531
|
+
[screenToWorld]
|
|
4532
|
+
);
|
|
4533
|
+
const notifyWorldPointerLeave = react.useCallback(() => {
|
|
4534
|
+
onWorldPointerLeaveRef.current?.();
|
|
4535
|
+
}, []);
|
|
4357
4536
|
const requestRender = react.useCallback(() => {
|
|
4358
4537
|
setCameraTick((n) => n + 1);
|
|
4359
4538
|
onCameraChangeRef.current?.();
|
|
@@ -4393,6 +4572,7 @@ var NativeVectorViewport = react.forwardRef(function NativeVectorViewport2({
|
|
|
4393
4572
|
const cam = cameraRef.current;
|
|
4394
4573
|
if (!cam) return;
|
|
4395
4574
|
const { worldX, worldY } = screenToWorld(sx, sy);
|
|
4575
|
+
onWorldPointerMoveRef.current?.({ x: worldX, y: worldY });
|
|
4396
4576
|
if (tool === "hand") {
|
|
4397
4577
|
dragStateRef.current = { kind: "pan" };
|
|
4398
4578
|
return;
|
|
@@ -4478,7 +4658,7 @@ var NativeVectorViewport = react.forwardRef(function NativeVectorViewport2({
|
|
|
4478
4658
|
kind: "marquee",
|
|
4479
4659
|
startWorld: { x: worldX, y: worldY }
|
|
4480
4660
|
};
|
|
4481
|
-
|
|
4661
|
+
setRealtimePlacementPreview({
|
|
4482
4662
|
kind: "marquee",
|
|
4483
4663
|
rect: { x: worldX, y: worldY, width: 0, height: 0 }
|
|
4484
4664
|
});
|
|
@@ -4498,7 +4678,7 @@ var NativeVectorViewport = react.forwardRef(function NativeVectorViewport2({
|
|
|
4498
4678
|
}
|
|
4499
4679
|
setLaserTrail([{ x: worldX, y: worldY, t: Date.now() }]);
|
|
4500
4680
|
} else {
|
|
4501
|
-
|
|
4681
|
+
setRealtimePlacementPreview({
|
|
4502
4682
|
kind: "stroke",
|
|
4503
4683
|
tool,
|
|
4504
4684
|
points: [{ x: worldX, y: worldY }],
|
|
@@ -4531,7 +4711,7 @@ var NativeVectorViewport = react.forwardRef(function NativeVectorViewport2({
|
|
|
4531
4711
|
startWorld: { x: worldX, y: worldY },
|
|
4532
4712
|
startScreen: { x: sx, y: sy }
|
|
4533
4713
|
};
|
|
4534
|
-
|
|
4714
|
+
setRealtimePlacementPreview(
|
|
4535
4715
|
placementPreviewForTool(
|
|
4536
4716
|
tool,
|
|
4537
4717
|
{ x: worldX, y: worldY },
|
|
@@ -4556,7 +4736,7 @@ var NativeVectorViewport = react.forwardRef(function NativeVectorViewport2({
|
|
|
4556
4736
|
startWorld: { x: worldX, y: worldY },
|
|
4557
4737
|
startScreen: { x: sx, y: sy }
|
|
4558
4738
|
};
|
|
4559
|
-
|
|
4739
|
+
setRealtimePlacementPreview({
|
|
4560
4740
|
kind: "rect",
|
|
4561
4741
|
rect: { x: worldX, y: worldY, width: 0, height: 0 }
|
|
4562
4742
|
});
|
|
@@ -4585,7 +4765,13 @@ var NativeVectorViewport = react.forwardRef(function NativeVectorViewport2({
|
|
|
4585
4765
|
}
|
|
4586
4766
|
dragStateRef.current = { kind: "pan" };
|
|
4587
4767
|
},
|
|
4588
|
-
[
|
|
4768
|
+
[
|
|
4769
|
+
interactive,
|
|
4770
|
+
requestSelectToolAfterUse,
|
|
4771
|
+
screenToWorld,
|
|
4772
|
+
setRealtimePlacementPreview,
|
|
4773
|
+
updateToolCursorPoint
|
|
4774
|
+
]
|
|
4589
4775
|
);
|
|
4590
4776
|
const applyDragMoveAtScreenPoint = react.useCallback(
|
|
4591
4777
|
(point, pagePoint) => {
|
|
@@ -4593,6 +4779,7 @@ var NativeVectorViewport = react.forwardRef(function NativeVectorViewport2({
|
|
|
4593
4779
|
if (!cam) return;
|
|
4594
4780
|
updateToolCursorPoint(point);
|
|
4595
4781
|
const { worldX, worldY } = screenToWorld(point.x, point.y);
|
|
4782
|
+
onWorldPointerMoveRef.current?.({ x: worldX, y: worldY });
|
|
4596
4783
|
const st = dragStateRef.current;
|
|
4597
4784
|
if (st.kind === "pan") {
|
|
4598
4785
|
const current = pagePoint ?? point;
|
|
@@ -4625,7 +4812,7 @@ var NativeVectorViewport = react.forwardRef(function NativeVectorViewport2({
|
|
|
4625
4812
|
}
|
|
4626
4813
|
return;
|
|
4627
4814
|
}
|
|
4628
|
-
|
|
4815
|
+
setRealtimePlacementPreview({
|
|
4629
4816
|
kind: "stroke",
|
|
4630
4817
|
tool: st.tool,
|
|
4631
4818
|
points: [...pts],
|
|
@@ -4687,7 +4874,7 @@ var NativeVectorViewport = react.forwardRef(function NativeVectorViewport2({
|
|
|
4687
4874
|
width: Math.abs(b.x - a.x),
|
|
4688
4875
|
height: Math.abs(b.y - a.y)
|
|
4689
4876
|
};
|
|
4690
|
-
|
|
4877
|
+
setRealtimePlacementPreview({ kind: "marquee", rect });
|
|
4691
4878
|
return;
|
|
4692
4879
|
}
|
|
4693
4880
|
if (st.kind === "erase") {
|
|
@@ -4705,7 +4892,7 @@ var NativeVectorViewport = react.forwardRef(function NativeVectorViewport2({
|
|
|
4705
4892
|
return;
|
|
4706
4893
|
}
|
|
4707
4894
|
if (st.kind === "place") {
|
|
4708
|
-
|
|
4895
|
+
setRealtimePlacementPreview(
|
|
4709
4896
|
placementPreviewForTool(st.tool, st.startWorld, {
|
|
4710
4897
|
x: worldX,
|
|
4711
4898
|
y: worldY
|
|
@@ -4714,14 +4901,19 @@ var NativeVectorViewport = react.forwardRef(function NativeVectorViewport2({
|
|
|
4714
4901
|
return;
|
|
4715
4902
|
}
|
|
4716
4903
|
if (st.kind === "custom-place") {
|
|
4717
|
-
|
|
4904
|
+
setRealtimePlacementPreview({
|
|
4718
4905
|
kind: "rect",
|
|
4719
4906
|
rect: rectFromCorners(st.startWorld, { x: worldX, y: worldY })
|
|
4720
4907
|
});
|
|
4721
4908
|
return;
|
|
4722
4909
|
}
|
|
4723
4910
|
},
|
|
4724
|
-
[
|
|
4911
|
+
[
|
|
4912
|
+
requestRender,
|
|
4913
|
+
screenToWorld,
|
|
4914
|
+
setRealtimePlacementPreview,
|
|
4915
|
+
updateToolCursorPoint
|
|
4916
|
+
]
|
|
4725
4917
|
);
|
|
4726
4918
|
const finishDragAtScreenPoint = react.useCallback(
|
|
4727
4919
|
(point) => {
|
|
@@ -4731,7 +4923,7 @@ var NativeVectorViewport = react.forwardRef(function NativeVectorViewport2({
|
|
|
4731
4923
|
const st = dragStateRef.current;
|
|
4732
4924
|
if (st.kind === "draw") {
|
|
4733
4925
|
dragStateRef.current = { kind: "idle" };
|
|
4734
|
-
|
|
4926
|
+
setRealtimePlacementPreview(null);
|
|
4735
4927
|
if (st.tool === "laser") {
|
|
4736
4928
|
if (laserClearTimerRef.current) {
|
|
4737
4929
|
clearTimeout(laserClearTimerRef.current);
|
|
@@ -4769,7 +4961,7 @@ var NativeVectorViewport = react.forwardRef(function NativeVectorViewport2({
|
|
|
4769
4961
|
}
|
|
4770
4962
|
if (st.kind === "marquee") {
|
|
4771
4963
|
dragStateRef.current = { kind: "idle" };
|
|
4772
|
-
|
|
4964
|
+
setRealtimePlacementPreview(null);
|
|
4773
4965
|
const cam = cameraRef.current;
|
|
4774
4966
|
if (!cam) return;
|
|
4775
4967
|
const { worldX, worldY } = screenToWorld(point.x, point.y);
|
|
@@ -4800,7 +4992,7 @@ var NativeVectorViewport = react.forwardRef(function NativeVectorViewport2({
|
|
|
4800
4992
|
}
|
|
4801
4993
|
if (st.kind === "place") {
|
|
4802
4994
|
dragStateRef.current = { kind: "idle" };
|
|
4803
|
-
|
|
4995
|
+
setRealtimePlacementPreview(null);
|
|
4804
4996
|
const change = onItemsChangeRef.current;
|
|
4805
4997
|
if (!change) return;
|
|
4806
4998
|
const { worldX, worldY } = screenToWorld(point.x, point.y);
|
|
@@ -4857,7 +5049,7 @@ var NativeVectorViewport = react.forwardRef(function NativeVectorViewport2({
|
|
|
4857
5049
|
}
|
|
4858
5050
|
if (st.kind === "custom-place") {
|
|
4859
5051
|
dragStateRef.current = { kind: "idle" };
|
|
4860
|
-
|
|
5052
|
+
setRealtimePlacementPreview(null);
|
|
4861
5053
|
const change = onItemsChangeRef.current;
|
|
4862
5054
|
if (!change) return;
|
|
4863
5055
|
const { worldX, worldY } = screenToWorld(point.x, point.y);
|
|
@@ -4932,7 +5124,12 @@ var NativeVectorViewport = react.forwardRef(function NativeVectorViewport2({
|
|
|
4932
5124
|
}
|
|
4933
5125
|
dragStateRef.current = { kind: "idle" };
|
|
4934
5126
|
},
|
|
4935
|
-
[
|
|
5127
|
+
[
|
|
5128
|
+
requestSelectToolAfterUse,
|
|
5129
|
+
screenToWorld,
|
|
5130
|
+
setRealtimePlacementPreview,
|
|
5131
|
+
updateToolCursorPoint
|
|
5132
|
+
]
|
|
4936
5133
|
);
|
|
4937
5134
|
const handlePointerDown = react.useCallback(
|
|
4938
5135
|
(event) => {
|
|
@@ -4948,9 +5145,10 @@ var NativeVectorViewport = react.forwardRef(function NativeVectorViewport2({
|
|
|
4948
5145
|
applyDragMoveAtScreenPoint(point, point);
|
|
4949
5146
|
return;
|
|
4950
5147
|
}
|
|
5148
|
+
notifyWorldPointerMove(point);
|
|
4951
5149
|
updateToolCursorPoint(point);
|
|
4952
5150
|
},
|
|
4953
|
-
[applyDragMoveAtScreenPoint, updateToolCursorPoint]
|
|
5151
|
+
[applyDragMoveAtScreenPoint, notifyWorldPointerMove, updateToolCursorPoint]
|
|
4954
5152
|
);
|
|
4955
5153
|
const handlePointerUp = react.useCallback(
|
|
4956
5154
|
(event) => {
|
|
@@ -4969,6 +5167,7 @@ var NativeVectorViewport = react.forwardRef(function NativeVectorViewport2({
|
|
|
4969
5167
|
const sy = evt.nativeEvent.locationY;
|
|
4970
5168
|
if (touches && touches.length >= 2) {
|
|
4971
5169
|
hideToolCursor();
|
|
5170
|
+
notifyWorldPointerLeave();
|
|
4972
5171
|
dragStateRef.current = { kind: "pan" };
|
|
4973
5172
|
return;
|
|
4974
5173
|
}
|
|
@@ -4984,6 +5183,7 @@ var NativeVectorViewport = react.forwardRef(function NativeVectorViewport2({
|
|
|
4984
5183
|
const pageY = evt.nativeEvent.pageY;
|
|
4985
5184
|
if (touches && touches.length >= 2) {
|
|
4986
5185
|
hideToolCursor();
|
|
5186
|
+
notifyWorldPointerLeave();
|
|
4987
5187
|
const t0 = touches[0];
|
|
4988
5188
|
const t1 = touches[1];
|
|
4989
5189
|
if (t0 && t1) {
|
|
@@ -5015,8 +5215,9 @@ var NativeVectorViewport = react.forwardRef(function NativeVectorViewport2({
|
|
|
5015
5215
|
lastPinchDist.current = null;
|
|
5016
5216
|
lastPanPoint.current = null;
|
|
5017
5217
|
hideToolCursor();
|
|
5218
|
+
notifyWorldPointerLeave();
|
|
5018
5219
|
dragStateRef.current = { kind: "idle" };
|
|
5019
|
-
|
|
5220
|
+
setRealtimePlacementPreview(null);
|
|
5020
5221
|
setLaserTrail([]);
|
|
5021
5222
|
setEraserTrail([]);
|
|
5022
5223
|
setEraserPreviewIds([]);
|
|
@@ -5028,7 +5229,9 @@ var NativeVectorViewport = react.forwardRef(function NativeVectorViewport2({
|
|
|
5028
5229
|
beginDragAtScreenPoint,
|
|
5029
5230
|
finishDragAtScreenPoint,
|
|
5030
5231
|
requestRender,
|
|
5031
|
-
hideToolCursor
|
|
5232
|
+
hideToolCursor,
|
|
5233
|
+
notifyWorldPointerLeave,
|
|
5234
|
+
setRealtimePlacementPreview
|
|
5032
5235
|
]
|
|
5033
5236
|
);
|
|
5034
5237
|
react.useImperativeHandle(
|
|
@@ -5062,7 +5265,10 @@ var NativeVectorViewport = react.forwardRef(function NativeVectorViewport2({
|
|
|
5062
5265
|
onPointerMove: handlePointerMove,
|
|
5063
5266
|
onPointerUp: handlePointerUp,
|
|
5064
5267
|
onPointerEnter: handlePointerMove,
|
|
5065
|
-
onPointerLeave:
|
|
5268
|
+
onPointerLeave: () => {
|
|
5269
|
+
hideToolCursor();
|
|
5270
|
+
notifyWorldPointerLeave();
|
|
5271
|
+
},
|
|
5066
5272
|
...panResponder.panHandlers,
|
|
5067
5273
|
children: size.width > 0 && size.height > 0 && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
5068
5274
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
@@ -5088,7 +5294,8 @@ var NativeVectorViewport = react.forwardRef(function NativeVectorViewport2({
|
|
|
5088
5294
|
eraserPreviewItems: items.filter(
|
|
5089
5295
|
(it) => eraserPreviewIds.includes(it.id)
|
|
5090
5296
|
),
|
|
5091
|
-
previewStrokeStyle: strokeStyleState
|
|
5297
|
+
previewStrokeStyle: strokeStyleState,
|
|
5298
|
+
remotePresence
|
|
5092
5299
|
}
|
|
5093
5300
|
),
|
|
5094
5301
|
interactive && showStyleInspector && activeStyleToolId ? /* @__PURE__ */ jsxRuntime.jsx(
|