canvu-react 0.3.7 → 0.3.9

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/tldraw.js CHANGED
@@ -44,89 +44,6 @@ function createCustomShapeItem(id, bounds, content) {
44
44
  };
45
45
  }
46
46
 
47
- // src/scene/freehand-path.ts
48
- function dedupeFreehandPoints(points, minDist) {
49
- if (points.length <= 2) {
50
- return points.map((p) => ({ ...p }));
51
- }
52
- const minSq = minDist * minDist;
53
- const first = points[0];
54
- if (!first) return [];
55
- const out = [{ ...first }];
56
- for (let i = 1; i < points.length - 1; i++) {
57
- const p = points[i];
58
- const last = out[out.length - 1];
59
- if (!p || !last) continue;
60
- const dx = p.x - last.x;
61
- const dy = p.y - last.y;
62
- if (dx * dx + dy * dy >= minSq) {
63
- out.push({ ...p });
64
- }
65
- }
66
- const end = points[points.length - 1];
67
- const lastKept = out[out.length - 1];
68
- if (!end || !lastKept) return out;
69
- if ((end.x - lastKept.x) ** 2 + (end.y - lastKept.y) ** 2 > 1e-12) {
70
- out.push({ ...end });
71
- }
72
- return out;
73
- }
74
- function smoothFreehandPointsToPathD(points) {
75
- const n = points.length;
76
- if (n === 0) return "";
77
- if (n === 1) {
78
- const p = points[0];
79
- if (!p) return "";
80
- return `M ${p.x} ${p.y}`;
81
- }
82
- if (n === 2) {
83
- const a = points[0];
84
- const b = points[1];
85
- if (!a || !b) return "";
86
- return `M ${a.x} ${a.y} L ${b.x} ${b.y}`;
87
- }
88
- const p0 = points[0];
89
- if (!p0) return "";
90
- let d = `M ${p0.x} ${p0.y}`;
91
- let i = 1;
92
- for (; i < n - 2; i++) {
93
- const pi = points[i];
94
- const pi1 = points[i + 1];
95
- if (!pi || !pi1) continue;
96
- const xc = (pi.x + pi1.x) / 2;
97
- const yc = (pi.y + pi1.y) / 2;
98
- d += ` Q ${pi.x} ${pi.y} ${xc} ${yc}`;
99
- }
100
- const pLast = points[i];
101
- const pEnd = points[i + 1];
102
- if (!pLast || !pEnd) return d;
103
- d += ` Q ${pLast.x} ${pLast.y} ${pEnd.x} ${pEnd.y}`;
104
- return d;
105
- }
106
- function outlineStrokeToClosedPathD(outline) {
107
- const len = outline.length;
108
- if (len === 0) return "";
109
- const first = outline[0];
110
- if (!first) return "";
111
- if (len < 3) {
112
- let d2 = `M ${first[0]} ${first[1]}`;
113
- for (let i = 1; i < len; i++) {
114
- const pt = outline[i];
115
- if (!pt) continue;
116
- d2 += ` L ${pt[0]} ${pt[1]}`;
117
- }
118
- return `${d2} Z`;
119
- }
120
- let d = `M ${first[0]} ${first[1]} Q`;
121
- for (let i = 0; i < len; i++) {
122
- const p0 = outline[i];
123
- const p1 = outline[(i + 1) % len];
124
- if (!p0 || !p1) continue;
125
- d += ` ${p0[0]} ${p0[1]} ${(p0[0] + p1[0]) / 2} ${(p0[1] + p1[1]) / 2}`;
126
- }
127
- return `${d} Z`;
128
- }
129
-
130
47
  // src/scene/text-svg.ts
131
48
  function escapeSvgTextContent(s) {
132
49
  return s.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
@@ -258,18 +175,18 @@ function perfectFreehandOptions(toolKind, style, strokeComplete, pressureAware =
258
175
  ...base,
259
176
  size: Math.max(2, sw * 1.05),
260
177
  thinning: 0.42,
261
- smoothing: 0.56,
262
- streamline: 0.18,
263
- simulatePressure: false
178
+ smoothing: 0.78,
179
+ streamline: 0.62,
180
+ simulatePressure: true
264
181
  };
265
182
  }
266
183
  return {
267
184
  ...base,
268
185
  size: Math.max(2, sw * 1.18),
269
186
  thinning: 0.12,
270
- smoothing: 0.72,
271
- streamline: 0.42,
272
- simulatePressure: false
187
+ smoothing: 0.85,
188
+ streamline: 0.78,
189
+ simulatePressure: true
273
190
  };
274
191
  }
275
192
  if (toolKind === "brush") {
@@ -287,7 +204,7 @@ function perfectFreehandOptions(toolKind, style, strokeComplete, pressureAware =
287
204
  thinning: 0.08,
288
205
  smoothing: 0.88,
289
206
  streamline: 0.84,
290
- simulatePressure: false
207
+ simulatePressure: true
291
208
  };
292
209
  }
293
210
  function resolveStrokeStyle(item) {
@@ -357,70 +274,41 @@ function computeFreehandSvgPayload(pathPointsLocal, style, toolKind, strokeCompl
357
274
  if (pathPointsLocal.length === 1) {
358
275
  const p = pathPointsLocal[0];
359
276
  if (!p) return null;
360
- const r = Math.max(0.5, style.strokeWidth / 2);
361
- return {
362
- kind: "circle",
363
- cx: p.x,
364
- cy: p.y,
365
- r,
366
- fill: style.stroke,
367
- fillOpacity: style.strokeOpacity
368
- };
369
- }
370
- const minDist = Math.min(0.25, Math.max(0.02, style.strokeWidth * 0.02));
371
- const pts = dedupeFreehandPoints(pathPointsLocal, minDist);
372
- if (pts.length === 0) return null;
373
- if (pts.length === 1) {
374
- const p = pts[0];
375
- if (!p) return null;
376
- const r = Math.max(0.5, style.strokeWidth / 2);
377
277
  return {
378
278
  kind: "circle",
379
279
  cx: p.x,
380
280
  cy: p.y,
381
- r,
281
+ r: Math.max(0.5, style.strokeWidth / 2),
382
282
  fill: style.stroke,
383
283
  fillOpacity: style.strokeOpacity
384
284
  };
385
285
  }
386
- const hasPressure = toolKind === "draw" && pts.some((p) => p.pressure != null && Number.isFinite(p.pressure));
387
- if (toolKind === "draw" && !hasPressure) {
388
- const d2 = smoothFreehandPointsToPathD(pts);
389
- return {
390
- kind: "strokePath",
391
- d: d2,
392
- stroke: style.stroke,
393
- strokeWidth: style.strokeWidth,
394
- strokeOpacity: style.strokeOpacity
395
- };
396
- }
397
- const input = hasPressure ? pts.map(
286
+ const hasPressure = pathPointsLocal.some(
287
+ (p) => p.pressure != null && Number.isFinite(p.pressure)
288
+ );
289
+ const input = hasPressure ? pathPointsLocal.map(
398
290
  (p) => [p.x, p.y, Math.min(1, Math.max(0, p.pressure ?? 0.5))]
399
- ) : pts.map((p) => [p.x, p.y]);
400
- const opts = perfectFreehandOptions(toolKind, style, strokeComplete, hasPressure);
401
- let outline = [];
402
- try {
403
- const raw = getStroke(input, opts);
404
- outline = raw.map(([x, y]) => [x, y]);
405
- } catch {
406
- outline = [];
407
- }
408
- if (outline.length >= 3) {
409
- const d2 = outlineStrokeToClosedPathD(outline);
410
- return {
411
- kind: "fillPath",
412
- d: d2,
413
- fill: style.stroke,
414
- fillOpacity: style.strokeOpacity
415
- };
291
+ ) : pathPointsLocal.map((p) => [p.x, p.y]);
292
+ const stroke = getStroke(
293
+ input,
294
+ perfectFreehandOptions(toolKind, style, strokeComplete, hasPressure)
295
+ );
296
+ if (stroke.length < 3) return null;
297
+ const first = stroke[0];
298
+ if (!first) return null;
299
+ let d = `M ${first[0]} ${first[1]} Q`;
300
+ for (let i = 0; i < stroke.length; i++) {
301
+ const a = stroke[i];
302
+ const b = stroke[(i + 1) % stroke.length];
303
+ if (!a || !b) continue;
304
+ d += ` ${a[0]} ${a[1]} ${(a[0] + b[0]) / 2} ${(a[1] + b[1]) / 2}`;
416
305
  }
417
- const d = smoothFreehandPointsToPathD(pts);
306
+ d += " Z";
418
307
  return {
419
- kind: "strokePath",
308
+ kind: "fillPath",
420
309
  d,
421
- stroke: style.stroke,
422
- strokeWidth: style.strokeWidth,
423
- strokeOpacity: style.strokeOpacity
310
+ fill: style.stroke,
311
+ fillOpacity: style.strokeOpacity
424
312
  };
425
313
  }
426
314
  function freehandPayloadToSvgString(payload) {