canvu-react 0.3.25 → 0.3.27
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 +1 -1
- package/dist/chatbot.d.ts +1 -1
- package/dist/react.cjs +81 -31
- package/dist/react.cjs.map +1 -1
- package/dist/react.d.cts +2 -2
- package/dist/react.d.ts +2 -2
- package/dist/react.js +81 -31
- package/dist/react.js.map +1 -1
- package/dist/realtime.cjs +211 -59
- package/dist/realtime.cjs.map +1 -1
- package/dist/realtime.d.cts +2 -2
- package/dist/realtime.d.ts +2 -2
- package/dist/realtime.js +207 -59
- package/dist/realtime.js.map +1 -1
- package/dist/{types-7kfWcm0L.d.cts → types-BLXR7g_L.d.cts} +7 -0
- package/dist/{types-C4k_AMvi.d.ts → types-Cm7IsgL4.d.ts} +7 -0
- package/package.json +1 -1
package/dist/realtime.d.cts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { P as PlacementPreview, R as RemotePresenceMarkupStroke, A as RemotePresencePeer, D as RemotePresenceCamera, E as RealtimeConnectionState, q as VectorViewportHandle, V as VectorToolDefinition, r as VectorViewportProps, C as CanvasPlugin, e as CanvasPluginRenderContext } from './types-
|
|
2
|
-
export { F as PresenceOverlayRenderContext } from './types-
|
|
1
|
+
import { P as PlacementPreview, R as RemotePresenceMarkupStroke, A as RemotePresencePeer, D as RemotePresenceCamera, E as RealtimeConnectionState, q as VectorViewportHandle, V as VectorToolDefinition, r as VectorViewportProps, C as CanvasPlugin, e as CanvasPluginRenderContext } from './types-BLXR7g_L.cjs';
|
|
2
|
+
export { F as PresenceOverlayRenderContext } from './types-BLXR7g_L.cjs';
|
|
3
3
|
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
4
4
|
import { C as Camera2D } from './camera-BwQjm5oh.cjs';
|
|
5
5
|
import { V as VectorSceneItem, R as Rect } from './types-CB0TZZuk.cjs';
|
package/dist/realtime.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { P as PlacementPreview, R as RemotePresenceMarkupStroke, A as RemotePresencePeer, D as RemotePresenceCamera, E as RealtimeConnectionState, q as VectorViewportHandle, V as VectorToolDefinition, r as VectorViewportProps, C as CanvasPlugin, e as CanvasPluginRenderContext } from './types-
|
|
2
|
-
export { F as PresenceOverlayRenderContext } from './types-
|
|
1
|
+
import { P as PlacementPreview, R as RemotePresenceMarkupStroke, A as RemotePresencePeer, D as RemotePresenceCamera, E as RealtimeConnectionState, q as VectorViewportHandle, V as VectorToolDefinition, r as VectorViewportProps, C as CanvasPlugin, e as CanvasPluginRenderContext } from './types-Cm7IsgL4.js';
|
|
2
|
+
export { F as PresenceOverlayRenderContext } from './types-Cm7IsgL4.js';
|
|
3
3
|
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
4
4
|
import { C as Camera2D } from './camera-KwCYYPhm.js';
|
|
5
5
|
import { V as VectorSceneItem, R as Rect } from './types-CB0TZZuk.js';
|
package/dist/realtime.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { MousePointer2, MessageSquare, Sparkles, Hand, Square, Circle, Minus, ArrowUpRight, PenLine, Highlighter, Eraser, Type, Image } from 'lucide-react';
|
|
2
|
+
import getStroke from 'perfect-freehand';
|
|
2
3
|
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
3
4
|
import { createContext, useState, useRef, useEffect, useMemo, useCallback, useLayoutEffect, useContext } from 'react';
|
|
4
5
|
|
|
@@ -9,9 +10,13 @@ function remoteMarkupStrokeFromPlacementPreview(preview) {
|
|
|
9
10
|
}
|
|
10
11
|
const tool = preview.tool;
|
|
11
12
|
const mapped = tool === "laser" || tool === "marker" || tool === "draw" ? tool : "draw";
|
|
13
|
+
const style = preview.style;
|
|
12
14
|
return {
|
|
13
15
|
points: preview.points,
|
|
14
|
-
tool: mapped
|
|
16
|
+
tool: mapped,
|
|
17
|
+
...style?.strokeWidth != null ? { strokeWidth: style.strokeWidth } : {},
|
|
18
|
+
...style?.stroke ? { stroke: style.stroke } : {},
|
|
19
|
+
...style?.strokeOpacity != null ? { strokeOpacity: style.strokeOpacity } : {}
|
|
15
20
|
};
|
|
16
21
|
}
|
|
17
22
|
|
|
@@ -67,6 +72,126 @@ function smoothFreehandPointsToPathD(points) {
|
|
|
67
72
|
return d;
|
|
68
73
|
}
|
|
69
74
|
|
|
75
|
+
// src/scene/custom-shape.ts
|
|
76
|
+
function expandCustomShapeTemplate(template, width, height) {
|
|
77
|
+
return template.replace(/\{\{w\}\}/g, String(width)).replace(/\{\{h\}\}/g, String(height)).replace(/\{\{width\}\}/g, String(width)).replace(/\{\{height\}\}/g, String(height));
|
|
78
|
+
}
|
|
79
|
+
function resolveCustomInner(content, size) {
|
|
80
|
+
if ("render" in content) {
|
|
81
|
+
return content.render(size);
|
|
82
|
+
}
|
|
83
|
+
return expandCustomShapeTemplate(content.svg, size.width, size.height);
|
|
84
|
+
}
|
|
85
|
+
function buildCustomShapeChildrenSvg(inner, intrinsic, bounds) {
|
|
86
|
+
const b = normalizeRect(bounds);
|
|
87
|
+
const sx = b.width / intrinsic.width;
|
|
88
|
+
const sy = b.height / intrinsic.height;
|
|
89
|
+
return `<g transform="scale(${sx},${sy})">${inner}</g>`;
|
|
90
|
+
}
|
|
91
|
+
function createCustomShapeItem(id, bounds, content) {
|
|
92
|
+
const r = normalizeRect(bounds);
|
|
93
|
+
const intrinsic = { width: r.width, height: r.height };
|
|
94
|
+
const inner = resolveCustomInner(content, intrinsic);
|
|
95
|
+
return {
|
|
96
|
+
id,
|
|
97
|
+
x: r.x,
|
|
98
|
+
y: r.y,
|
|
99
|
+
bounds: { ...r },
|
|
100
|
+
toolKind: "custom",
|
|
101
|
+
customIntrinsicSize: intrinsic,
|
|
102
|
+
customInnerSvg: inner,
|
|
103
|
+
childrenSvg: buildCustomShapeChildrenSvg(inner, intrinsic, r)
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
// src/scene/shape-builders.ts
|
|
108
|
+
function perfectFreehandOptions(toolKind, style, strokeComplete, pressureAware = false) {
|
|
109
|
+
const sw = style.strokeWidth;
|
|
110
|
+
const base2 = {
|
|
111
|
+
last: strokeComplete,
|
|
112
|
+
simulatePressure: true
|
|
113
|
+
};
|
|
114
|
+
if (toolKind === "draw" || toolKind === "pencil") {
|
|
115
|
+
if (pressureAware && toolKind === "draw") {
|
|
116
|
+
return {
|
|
117
|
+
...base2,
|
|
118
|
+
size: Math.max(2, sw * 1.05),
|
|
119
|
+
thinning: 0.42,
|
|
120
|
+
smoothing: 0.78,
|
|
121
|
+
streamline: 0.62,
|
|
122
|
+
simulatePressure: true
|
|
123
|
+
};
|
|
124
|
+
}
|
|
125
|
+
return {
|
|
126
|
+
...base2,
|
|
127
|
+
size: Math.max(2, sw * 1.18),
|
|
128
|
+
thinning: 0.12,
|
|
129
|
+
smoothing: 0.85,
|
|
130
|
+
streamline: 0.78,
|
|
131
|
+
simulatePressure: true
|
|
132
|
+
};
|
|
133
|
+
}
|
|
134
|
+
if (toolKind === "brush") {
|
|
135
|
+
return {
|
|
136
|
+
...base2,
|
|
137
|
+
size: Math.max(4, sw * 1.22),
|
|
138
|
+
thinning: 0.52,
|
|
139
|
+
smoothing: 0.64,
|
|
140
|
+
streamline: 0.68
|
|
141
|
+
};
|
|
142
|
+
}
|
|
143
|
+
return {
|
|
144
|
+
...base2,
|
|
145
|
+
size: Math.max(6, sw * 1.08),
|
|
146
|
+
thinning: 0.08,
|
|
147
|
+
smoothing: 0.88,
|
|
148
|
+
streamline: 0.84,
|
|
149
|
+
simulatePressure: true
|
|
150
|
+
};
|
|
151
|
+
}
|
|
152
|
+
function computeFreehandSvgPayload(pathPointsLocal, style, toolKind, strokeComplete = true) {
|
|
153
|
+
if (pathPointsLocal.length === 0) return null;
|
|
154
|
+
if (pathPointsLocal.length === 1) {
|
|
155
|
+
const p = pathPointsLocal[0];
|
|
156
|
+
if (!p) return null;
|
|
157
|
+
return {
|
|
158
|
+
kind: "circle",
|
|
159
|
+
cx: p.x,
|
|
160
|
+
cy: p.y,
|
|
161
|
+
r: Math.max(0.5, style.strokeWidth / 2),
|
|
162
|
+
fill: style.stroke,
|
|
163
|
+
fillOpacity: style.strokeOpacity
|
|
164
|
+
};
|
|
165
|
+
}
|
|
166
|
+
const hasPressure = pathPointsLocal.some(
|
|
167
|
+
(p) => p.pressure != null && Number.isFinite(p.pressure)
|
|
168
|
+
);
|
|
169
|
+
const input = hasPressure ? pathPointsLocal.map(
|
|
170
|
+
(p) => [p.x, p.y, Math.min(1, Math.max(0, p.pressure ?? 0.5))]
|
|
171
|
+
) : pathPointsLocal.map((p) => [p.x, p.y]);
|
|
172
|
+
const stroke = getStroke(
|
|
173
|
+
input,
|
|
174
|
+
perfectFreehandOptions(toolKind, style, strokeComplete, hasPressure)
|
|
175
|
+
);
|
|
176
|
+
if (stroke.length < 3) return null;
|
|
177
|
+
const first = stroke[0];
|
|
178
|
+
if (!first) return null;
|
|
179
|
+
let d = `M ${first[0]} ${first[1]} Q`;
|
|
180
|
+
for (let i = 0; i < stroke.length; i++) {
|
|
181
|
+
const a = stroke[i];
|
|
182
|
+
const b = stroke[(i + 1) % stroke.length];
|
|
183
|
+
if (!a || !b) continue;
|
|
184
|
+
d += ` ${a[0]} ${a[1]} ${(a[0] + b[0]) / 2} ${(a[1] + b[1]) / 2}`;
|
|
185
|
+
}
|
|
186
|
+
d += " Z";
|
|
187
|
+
return {
|
|
188
|
+
kind: "fillPath",
|
|
189
|
+
d,
|
|
190
|
+
fill: style.stroke,
|
|
191
|
+
fillOpacity: style.strokeOpacity
|
|
192
|
+
};
|
|
193
|
+
}
|
|
194
|
+
|
|
70
195
|
// src/react/presence/peer-color.ts
|
|
71
196
|
function defaultPresenceColorForId(id) {
|
|
72
197
|
let h = 2166136261;
|
|
@@ -91,6 +216,9 @@ function strokePaint(tool, fallback) {
|
|
|
91
216
|
return { stroke: fallback, strokeOpacity: 0.95, widthWorld: 3.5 };
|
|
92
217
|
}
|
|
93
218
|
}
|
|
219
|
+
function isFreehandTool(tool) {
|
|
220
|
+
return tool === "draw" || tool === "marker" || tool === "pencil" || tool === "brush";
|
|
221
|
+
}
|
|
94
222
|
function PresenceRemoteLayer({
|
|
95
223
|
camera,
|
|
96
224
|
cameraVersion: _cameraVersion,
|
|
@@ -126,35 +254,78 @@ function PresenceRemoteLayer({
|
|
|
126
254
|
const markup = peer.markupStroke;
|
|
127
255
|
let strokeNode = null;
|
|
128
256
|
if (markup && markup.points.length > 0) {
|
|
129
|
-
const
|
|
130
|
-
const
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
257
|
+
const fallbackPaint = strokePaint(markup.tool, color);
|
|
258
|
+
const paint = {
|
|
259
|
+
stroke: markup.stroke ?? fallbackPaint.stroke,
|
|
260
|
+
strokeOpacity: markup.strokeOpacity ?? fallbackPaint.strokeOpacity,
|
|
261
|
+
widthWorld: markup.strokeWidth ?? fallbackPaint.widthWorld
|
|
262
|
+
};
|
|
263
|
+
if (markup.tool === "laser") {
|
|
264
|
+
const d = markup.points.length >= 2 ? smoothFreehandPointsToPathD([...markup.points]) : null;
|
|
265
|
+
if (d) {
|
|
266
|
+
strokeNode = /* @__PURE__ */ jsx(
|
|
267
|
+
"path",
|
|
268
|
+
{
|
|
269
|
+
d,
|
|
270
|
+
fill: "none",
|
|
271
|
+
stroke: paint.stroke,
|
|
272
|
+
strokeOpacity: paint.strokeOpacity,
|
|
273
|
+
strokeWidth: Math.max(paint.widthWorld / z, overlayStrokePx),
|
|
274
|
+
strokeLinecap: "round",
|
|
275
|
+
strokeLinejoin: "round",
|
|
276
|
+
shapeRendering: "geometricPrecision",
|
|
277
|
+
vectorEffect: "non-scaling-stroke"
|
|
278
|
+
}
|
|
279
|
+
);
|
|
280
|
+
}
|
|
281
|
+
} else if (isFreehandTool(markup.tool)) {
|
|
282
|
+
const style = {
|
|
283
|
+
stroke: paint.stroke,
|
|
284
|
+
strokeWidth: paint.widthWorld,
|
|
285
|
+
...paint.strokeOpacity != null ? { strokeOpacity: paint.strokeOpacity } : {}
|
|
286
|
+
};
|
|
287
|
+
const payload = computeFreehandSvgPayload(
|
|
288
|
+
markup.points.map((p) => ({ x: p.x, y: p.y })),
|
|
289
|
+
style,
|
|
290
|
+
markup.tool,
|
|
291
|
+
false
|
|
145
292
|
);
|
|
146
|
-
|
|
147
|
-
const p0 = markup.points[0];
|
|
148
|
-
if (p0) {
|
|
293
|
+
if (payload?.kind === "circle") {
|
|
149
294
|
strokeNode = /* @__PURE__ */ jsx(
|
|
150
295
|
"circle",
|
|
151
296
|
{
|
|
152
|
-
cx:
|
|
153
|
-
cy:
|
|
154
|
-
r:
|
|
155
|
-
fill:
|
|
156
|
-
fillOpacity:
|
|
157
|
-
|
|
297
|
+
cx: payload.cx,
|
|
298
|
+
cy: payload.cy,
|
|
299
|
+
r: payload.r,
|
|
300
|
+
fill: payload.fill,
|
|
301
|
+
...payload.fillOpacity != null ? { fillOpacity: payload.fillOpacity } : {},
|
|
302
|
+
shapeRendering: "geometricPrecision"
|
|
303
|
+
}
|
|
304
|
+
);
|
|
305
|
+
} else if (payload?.kind === "fillPath") {
|
|
306
|
+
strokeNode = /* @__PURE__ */ jsx(
|
|
307
|
+
"path",
|
|
308
|
+
{
|
|
309
|
+
d: payload.d,
|
|
310
|
+
fill: payload.fill,
|
|
311
|
+
fillRule: "nonzero",
|
|
312
|
+
stroke: "none",
|
|
313
|
+
...payload.fillOpacity != null ? { fillOpacity: payload.fillOpacity } : {},
|
|
314
|
+
shapeRendering: "geometricPrecision"
|
|
315
|
+
}
|
|
316
|
+
);
|
|
317
|
+
} else if (payload?.kind === "strokePath") {
|
|
318
|
+
strokeNode = /* @__PURE__ */ jsx(
|
|
319
|
+
"path",
|
|
320
|
+
{
|
|
321
|
+
d: payload.d,
|
|
322
|
+
fill: "none",
|
|
323
|
+
stroke: payload.stroke,
|
|
324
|
+
strokeWidth: payload.strokeWidth,
|
|
325
|
+
...payload.strokeOpacity != null ? { strokeOpacity: payload.strokeOpacity } : {},
|
|
326
|
+
strokeLinecap: "round",
|
|
327
|
+
strokeLinejoin: "round",
|
|
328
|
+
shapeRendering: "geometricPrecision"
|
|
158
329
|
}
|
|
159
330
|
);
|
|
160
331
|
}
|
|
@@ -255,7 +426,16 @@ function parseMarkupStroke(value) {
|
|
|
255
426
|
if (x == null || y == null) return null;
|
|
256
427
|
return { x, y };
|
|
257
428
|
}).filter((point) => point != null);
|
|
258
|
-
|
|
429
|
+
const strokeWidth = getNumber(value.strokeWidth);
|
|
430
|
+
const stroke = getString(value.stroke);
|
|
431
|
+
const strokeOpacity = getNumber(value.strokeOpacity);
|
|
432
|
+
return {
|
|
433
|
+
points,
|
|
434
|
+
tool,
|
|
435
|
+
...strokeWidth != null ? { strokeWidth } : {},
|
|
436
|
+
...stroke ? { stroke } : {},
|
|
437
|
+
...strokeOpacity != null ? { strokeOpacity } : {}
|
|
438
|
+
};
|
|
259
439
|
}
|
|
260
440
|
function parsePresencePayload(value) {
|
|
261
441
|
if (!isRecord(value)) return void 0;
|
|
@@ -777,38 +957,6 @@ var DEFAULT_VECTOR_TOOLS = [
|
|
|
777
957
|
shortcutHint: "I"
|
|
778
958
|
}
|
|
779
959
|
];
|
|
780
|
-
|
|
781
|
-
// src/scene/custom-shape.ts
|
|
782
|
-
function expandCustomShapeTemplate(template, width, height) {
|
|
783
|
-
return template.replace(/\{\{w\}\}/g, String(width)).replace(/\{\{h\}\}/g, String(height)).replace(/\{\{width\}\}/g, String(width)).replace(/\{\{height\}\}/g, String(height));
|
|
784
|
-
}
|
|
785
|
-
function resolveCustomInner(content, size) {
|
|
786
|
-
if ("render" in content) {
|
|
787
|
-
return content.render(size);
|
|
788
|
-
}
|
|
789
|
-
return expandCustomShapeTemplate(content.svg, size.width, size.height);
|
|
790
|
-
}
|
|
791
|
-
function buildCustomShapeChildrenSvg(inner, intrinsic, bounds) {
|
|
792
|
-
const b = normalizeRect(bounds);
|
|
793
|
-
const sx = b.width / intrinsic.width;
|
|
794
|
-
const sy = b.height / intrinsic.height;
|
|
795
|
-
return `<g transform="scale(${sx},${sy})">${inner}</g>`;
|
|
796
|
-
}
|
|
797
|
-
function createCustomShapeItem(id, bounds, content) {
|
|
798
|
-
const r = normalizeRect(bounds);
|
|
799
|
-
const intrinsic = { width: r.width, height: r.height };
|
|
800
|
-
const inner = resolveCustomInner(content, intrinsic);
|
|
801
|
-
return {
|
|
802
|
-
id,
|
|
803
|
-
x: r.x,
|
|
804
|
-
y: r.y,
|
|
805
|
-
bounds: { ...r },
|
|
806
|
-
toolKind: "custom",
|
|
807
|
-
customIntrinsicSize: intrinsic,
|
|
808
|
-
customInnerSvg: inner,
|
|
809
|
-
childrenSvg: buildCustomShapeChildrenSvg(inner, intrinsic, r)
|
|
810
|
-
};
|
|
811
|
-
}
|
|
812
960
|
var iconProps = { size: 20, strokeWidth: 2 };
|
|
813
961
|
var COMMENT_PLUGIN_DATA_KEY = "realtimeComment";
|
|
814
962
|
var REALTIME_COMMENT_TOOL = {
|