canvu-react 0.3.39 → 0.4.0

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.
Files changed (45) hide show
  1. package/dist/{asset-hydration-DowNdaOJ.d.cts → asset-hydration-B7yMDQE-.d.cts} +2 -2
  2. package/dist/{asset-hydration-DdFLdlqX.d.ts → asset-hydration-CbwQVAwh.d.ts} +2 -2
  3. package/dist/{camera-Di5R_Rwl.d.cts → camera-CVVG7z56.d.cts} +1 -1
  4. package/dist/{camera-AoTwBSoE.d.ts → camera-CoRYN_IV.d.ts} +1 -1
  5. package/dist/chatbot.d.cts +4 -4
  6. package/dist/chatbot.d.ts +4 -4
  7. package/dist/index.cjs +59 -15
  8. package/dist/index.cjs.map +1 -1
  9. package/dist/index.d.cts +6 -6
  10. package/dist/index.d.ts +6 -6
  11. package/dist/index.js +59 -15
  12. package/dist/index.js.map +1 -1
  13. package/dist/native.cjs +57 -14
  14. package/dist/native.cjs.map +1 -1
  15. package/dist/native.d.cts +2 -2
  16. package/dist/native.d.ts +2 -2
  17. package/dist/native.js +57 -14
  18. package/dist/native.js.map +1 -1
  19. package/dist/react.cjs +699 -255
  20. package/dist/react.cjs.map +1 -1
  21. package/dist/react.d.cts +10 -10
  22. package/dist/react.d.ts +10 -10
  23. package/dist/react.js +699 -255
  24. package/dist/react.js.map +1 -1
  25. package/dist/realtime.cjs +498 -129
  26. package/dist/realtime.cjs.map +1 -1
  27. package/dist/realtime.d.cts +6 -6
  28. package/dist/realtime.d.ts +6 -6
  29. package/dist/realtime.js +479 -129
  30. package/dist/realtime.js.map +1 -1
  31. package/dist/{shape-builders-Dedcl6tw.d.cts → shape-builders-BAWu-PxX.d.cts} +7 -3
  32. package/dist/{shape-builders-C7bxJBGR.d.ts → shape-builders-ClKv9tz9.d.ts} +7 -3
  33. package/dist/tldraw.cjs +56 -14
  34. package/dist/tldraw.cjs.map +1 -1
  35. package/dist/tldraw.d.cts +1 -1
  36. package/dist/tldraw.d.ts +1 -1
  37. package/dist/tldraw.js +56 -14
  38. package/dist/tldraw.js.map +1 -1
  39. package/dist/{types-DUW61Tjy.d.cts → types-BC9Xgfu6.d.cts} +11 -6
  40. package/dist/{types-Bnq2HtHQ.d.cts → types-BCCvY6ie.d.cts} +2 -0
  41. package/dist/{types-Bnq2HtHQ.d.ts → types-BCCvY6ie.d.ts} +2 -0
  42. package/dist/{types-B2Na677H.d.cts → types-BUPc2Zgw.d.cts} +1 -1
  43. package/dist/{types-zmUah-vP.d.ts → types-CYtq9Pr9.d.ts} +1 -1
  44. package/dist/{types-BBb8KoyW.d.ts → types-DlSVGX0w.d.ts} +11 -6
  45. package/package.json +3 -2
package/dist/native.cjs CHANGED
@@ -178,11 +178,14 @@ function escapeHtmlText(s) {
178
178
  return s.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
179
179
  }
180
180
  var DEFAULT_TEXT_FONT_SIZE = 18;
181
+ var TEXT_FONT_FAMILY = "Inter, -apple-system, BlinkMacSystemFont, ui-sans-serif, system-ui, sans-serif";
181
182
  var LINE_HEIGHT_RATIO = 22 / 18;
182
- var FIRST_LINE_BASELINE_RATIO = 24 / 18;
183
+ var FIRST_LINE_BASELINE_RATIO = 20 / 18;
184
+ var EDIT_TOP_PAD_RATIO = 4 / 18;
185
+ var BOTTOM_PAD_RATIO = 4 / 18;
183
186
  var PLACEHOLDER = "Tap to type";
184
187
  var MIN_TEXT_BOX_W = 40;
185
- var MIN_TEXT_BOX_H = 36;
188
+ var MIN_TEXT_BOX_H = 26;
186
189
  var TEXT_PAD_X = 4;
187
190
  var MAX_TEXT_MEASURE_CACHE_ENTRIES = 2e3;
188
191
  var sharedMeasureContext;
@@ -228,7 +231,7 @@ function measureTextBoundsLocal(content, fontSize = DEFAULT_TEXT_FONT_SIZE) {
228
231
  let maxInnerW = 0;
229
232
  const ctx = getSharedMeasureContext();
230
233
  if (ctx) {
231
- ctx.font = `${fontSize}px system-ui, sans-serif`;
234
+ ctx.font = `${fontSize}px ${TEXT_FONT_FAMILY}`;
232
235
  for (const line of lines) {
233
236
  const toMeasure = trimmed.length === 0 ? PLACEHOLDER : line.length === 0 ? " " : line;
234
237
  maxInnerW = Math.max(maxInnerW, ctx.measureText(toMeasure).width);
@@ -244,22 +247,22 @@ function measureTextBoundsLocal(content, fontSize = DEFAULT_TEXT_FONT_SIZE) {
244
247
  const width = Math.max(minW, TEXT_PAD_X * 2 + maxInnerW);
245
248
  const height = Math.max(
246
249
  MIN_TEXT_BOX_H,
247
- baselineY + (lines.length - 1) * lh + Math.max(8, fontSize * 0.35)
250
+ baselineY + (lines.length - 1) * lh + Math.max(4, fontSize * BOTTOM_PAD_RATIO)
248
251
  );
249
252
  const measured = { width, height };
250
253
  cacheMeasuredBounds(cacheKey, measured);
251
254
  return measured;
252
255
  }
253
- function buildTextSvg(content, _width, _height, fillColor = "#2563eb", fontSize = DEFAULT_TEXT_FONT_SIZE) {
256
+ function buildTextSvg(content, _width, _height, fillColor = "#1d1d1d", fontSize = DEFAULT_TEXT_FONT_SIZE) {
254
257
  const lh = lineHeightFor(fontSize);
255
258
  const y0 = firstLineBaselineY(fontSize);
256
259
  const trimmed = content.trim();
257
260
  if (trimmed.length === 0) {
258
- return `<text x="4" y="${y0}" font-size="${fontSize}" font-family="system-ui,sans-serif" fill="#94a3b8" font-style="italic">${escapeSvgTextContent(PLACEHOLDER)}</text>`;
261
+ return `<text x="4" y="${y0}" font-size="${fontSize}" font-family="${TEXT_FONT_FAMILY}" fill="#94a3b8" font-style="italic">${escapeSvgTextContent(PLACEHOLDER)}</text>`;
259
262
  }
260
263
  const lines = content.split("\n");
261
264
  if (lines.length === 1) {
262
- return `<text x="4" y="${y0}" font-size="${fontSize}" font-family="system-ui,sans-serif" fill="${fillColor}">${escapeSvgTextContent(lines[0] ?? "")}</text>`;
265
+ return `<text x="4" y="${y0}" font-size="${fontSize}" font-family="${TEXT_FONT_FAMILY}" fill="${fillColor}">${escapeSvgTextContent(lines[0] ?? "")}</text>`;
263
266
  }
264
267
  const parts = [];
265
268
  for (let i = 0; i < lines.length; i++) {
@@ -270,23 +273,24 @@ function buildTextSvg(content, _width, _height, fillColor = "#2563eb", fontSize
270
273
  parts.push(`<tspan x="4" dy="${lh}">${escapeSvgTextContent(line)}</tspan>`);
271
274
  }
272
275
  }
273
- return `<text x="4" y="${y0}" font-size="${fontSize}" font-family="system-ui,sans-serif" fill="${fillColor}">${parts.join("")}</text>`;
276
+ return `<text x="4" y="${y0}" font-size="${fontSize}" font-family="${TEXT_FONT_FAMILY}" fill="${fillColor}">${parts.join("")}</text>`;
274
277
  }
275
- function buildTextFixedBoundsSvg(content, width, height, fillColor = "#2563eb", fontSize = DEFAULT_TEXT_FONT_SIZE) {
278
+ function buildTextFixedBoundsSvg(content, width, height, fillColor = "#1d1d1d", fontSize = DEFAULT_TEXT_FONT_SIZE) {
276
279
  const w = Math.max(1, width);
277
280
  const h = Math.max(1, height);
278
281
  const lh = lineHeightFor(fontSize);
279
282
  const trimmed = content.trim();
283
+ const padTop = EDIT_TOP_PAD_RATIO * fontSize;
280
284
  if (trimmed.length === 0) {
281
- return `<foreignObject width="${w}" height="${h}"><div xmlns="http://www.w3.org/1999/xhtml" style="box-sizing:border-box;width:100%;height:100%;margin:0;padding:2px 4px;font-size:${fontSize}px;line-height:${lh}px;font-family:system-ui,sans-serif;white-space:pre-wrap;word-wrap:break-word;overflow:hidden;color:#94a3b8;font-style:italic">${escapeHtmlText(PLACEHOLDER)}</div></foreignObject>`;
285
+ return `<foreignObject width="${w}" height="${h}"><div xmlns="http://www.w3.org/1999/xhtml" style="box-sizing:border-box;width:100%;height:100%;margin:0;padding:${padTop}px 4px 0 4px;font-size:${fontSize}px;line-height:${lh}px;font-family:${TEXT_FONT_FAMILY};white-space:pre-wrap;word-wrap:break-word;overflow:hidden;color:#94a3b8;font-style:italic">${escapeHtmlText(PLACEHOLDER)}</div></foreignObject>`;
282
286
  }
283
287
  const body = escapeHtmlText(content);
284
- return `<foreignObject width="${w}" height="${h}"><div xmlns="http://www.w3.org/1999/xhtml" style="box-sizing:border-box;width:100%;height:100%;margin:0;padding:2px 4px;font-size:${fontSize}px;line-height:${lh}px;font-family:system-ui,sans-serif;white-space:pre-wrap;word-wrap:break-word;overflow:hidden;color:${fillColor}">${body}</div></foreignObject>`;
288
+ return `<foreignObject width="${w}" height="${h}"><div xmlns="http://www.w3.org/1999/xhtml" style="box-sizing:border-box;width:100%;height:100%;margin:0;padding:${padTop}px 4px 0 4px;font-size:${fontSize}px;line-height:${lh}px;font-family:${TEXT_FONT_FAMILY};white-space:pre-wrap;word-wrap:break-word;overflow:hidden;color:${fillColor}">${body}</div></foreignObject>`;
285
289
  }
286
290
 
287
291
  // src/scene/shape-builders.ts
288
292
  var DEFAULT_STROKE_STYLE = {
289
- stroke: "#2563eb",
293
+ stroke: "#1d1d1d",
290
294
  strokeWidth: 2
291
295
  };
292
296
  var TOOL_FREEHAND_DEFAULTS = {
@@ -343,7 +347,8 @@ function resolveStrokeStyle(item) {
343
347
  return {
344
348
  stroke: item.stroke ?? DEFAULT_STROKE_STYLE.stroke,
345
349
  strokeWidth: item.strokeWidth ?? DEFAULT_STROKE_STYLE.strokeWidth,
346
- strokeOpacity: item.strokeOpacity
350
+ strokeOpacity: item.strokeOpacity,
351
+ strokeDash: item.strokeDash
347
352
  };
348
353
  }
349
354
  function strokeOpacityAttr(style) {
@@ -672,6 +677,30 @@ function buildDrawDotSvg(r, style = DEFAULT_STROKE_STYLE) {
672
677
  const op = style.strokeOpacity != null ? ` fill-opacity="${style.strokeOpacity}"` : "";
673
678
  return `<circle cx="${r}" cy="${r}" r="${r}" fill="${style.stroke}" shape-rendering="geometricPrecision"${op} />`;
674
679
  }
680
+ function dashArrayForDrawStroke(strokeWidth) {
681
+ const dash = Math.max(strokeWidth * 1.8, 4);
682
+ const gap = Math.max(strokeWidth * 1.4, 3);
683
+ return `${dash} ${gap}`;
684
+ }
685
+ function buildSmoothedCenterlinePath(points) {
686
+ if (points.length < 2) return null;
687
+ const first = points[0];
688
+ if (!first) return null;
689
+ let d = `M ${first.x} ${first.y}`;
690
+ for (let i = 1; i < points.length - 1; i++) {
691
+ const a = points[i];
692
+ const b = points[i + 1];
693
+ if (!a || !b) continue;
694
+ const midX = (a.x + b.x) / 2;
695
+ const midY = (a.y + b.y) / 2;
696
+ d += ` Q ${a.x} ${a.y} ${midX} ${midY}`;
697
+ }
698
+ const last = points[points.length - 1];
699
+ if (last) {
700
+ d += ` L ${last.x} ${last.y}`;
701
+ }
702
+ return d;
703
+ }
675
704
  function computeFreehandSvgPayload(pathPointsLocal, style, toolKind, strokeComplete = true) {
676
705
  if (pathPointsLocal.length === 0) return null;
677
706
  if (pathPointsLocal.length === 1) {
@@ -686,6 +715,18 @@ function computeFreehandSvgPayload(pathPointsLocal, style, toolKind, strokeCompl
686
715
  fillOpacity: style.strokeOpacity
687
716
  };
688
717
  }
718
+ if (style.strokeDash === "dashed" && (toolKind === "draw" || toolKind === "pencil")) {
719
+ const d2 = buildSmoothedCenterlinePath(pathPointsLocal);
720
+ if (!d2) return null;
721
+ return {
722
+ kind: "strokePath",
723
+ d: d2,
724
+ stroke: style.stroke,
725
+ strokeWidth: style.strokeWidth,
726
+ strokeOpacity: style.strokeOpacity,
727
+ strokeDasharray: dashArrayForDrawStroke(style.strokeWidth)
728
+ };
729
+ }
689
730
  const hasPressure = pathPointsLocal.some(
690
731
  (p) => p.pressure != null && Number.isFinite(p.pressure)
691
732
  );
@@ -728,7 +769,8 @@ function freehandPayloadToSvgString(payload) {
728
769
  strokeWidth: payload.strokeWidth,
729
770
  strokeOpacity: payload.strokeOpacity
730
771
  });
731
- return `<path d="${payload.d}" fill="none" stroke="${payload.stroke}" stroke-width="${payload.strokeWidth}" stroke-linecap="round" stroke-linejoin="round" shape-rendering="geometricPrecision"${op} />`;
772
+ const dash = payload.strokeDasharray ? ` stroke-dasharray="${payload.strokeDasharray}"` : "";
773
+ return `<path d="${payload.d}" fill="none" stroke="${payload.stroke}" stroke-width="${payload.strokeWidth}" stroke-linecap="round" stroke-linejoin="round" shape-rendering="geometricPrecision"${op}${dash} />`;
732
774
  }
733
775
  function buildFreehandPathSvg(pathPointsLocal, style, toolKind, strokeComplete = true) {
734
776
  const payload = computeFreehandSvgPayload(
@@ -880,6 +922,7 @@ function createFreehandStrokeItem(id, pointsWorld, toolKind, style) {
880
922
  stroke: merged.stroke,
881
923
  strokeWidth: merged.strokeWidth,
882
924
  ...merged.strokeOpacity != null ? { strokeOpacity: merged.strokeOpacity } : {},
925
+ ...merged.strokeDash != null ? { strokeDash: merged.strokeDash } : {},
883
926
  pathPointsLocal,
884
927
  childrenSvg: ""
885
928
  });