canvu-react 0.3.39 → 0.3.40

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 +36 -0
  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 +36 -0
  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 +1 -1
@@ -1,4 +1,4 @@
1
- import { V as VectorSceneItem, R as Rect, L as LineEndpointsLocal, b as VectorPathPoint, a as ArrowBindings } from './types-Bnq2HtHQ.cjs';
1
+ import { V as VectorSceneItem, R as Rect, L as LineEndpointsLocal, b as VectorPathPoint, a as ArrowBindings } from './types-BCCvY6ie.cjs';
2
2
 
3
3
  /**
4
4
  * Kind of binary selected through the built-in canvu asset ingestion flow.
@@ -148,11 +148,14 @@ declare const DEFAULT_LINK_CARD_SIZE: {
148
148
  readonly height: 132;
149
149
  };
150
150
 
151
+ /** Stroke dash pattern for freehand drawings. `solid` = perfect-freehand fill; `dashed` = centerline stroke with dashes. */
152
+ type StrokeDash = "solid" | "dashed";
151
153
  /** Resolved stroke for SVG generation. */
152
154
  type StrokeStyle = {
153
155
  stroke: string;
154
156
  strokeWidth: number;
155
157
  strokeOpacity?: number;
158
+ strokeDash?: StrokeDash;
156
159
  };
157
160
  declare const DEFAULT_STROKE_STYLE: StrokeStyle;
158
161
  declare function resolveStrokeStyle(item: VectorSceneItem): StrokeStyle;
@@ -202,6 +205,7 @@ type FreehandSvgPayload = {
202
205
  stroke: string;
203
206
  strokeWidth: number;
204
207
  strokeOpacity?: number;
208
+ strokeDasharray?: string;
205
209
  };
206
210
  /**
207
211
  * Computes freehand geometry (perfect-freehand + fallback). Used by {@link buildFreehandPathSvg}
@@ -236,7 +240,7 @@ declare function lineEndpointsToLocal(bounds: Rect, worldEndA: {
236
240
  */
237
241
  declare function rebuildItemSvg(item: VectorSceneItem): VectorSceneItem;
238
242
  /** Updates stroke color / width / opacity and refreshes the item’s SVG. */
239
- declare function applyStrokeToItem(item: VectorSceneItem, patch: Partial<Pick<VectorSceneItem, "stroke" | "strokeWidth" | "strokeOpacity">>): VectorSceneItem;
243
+ declare function applyStrokeToItem(item: VectorSceneItem, patch: Partial<Pick<VectorSceneItem, "stroke" | "strokeWidth" | "strokeOpacity" | "strokeDash" | "textFontSize">>): VectorSceneItem;
240
244
  /** Creates a rectangle shape ready to append to your scene `items` array. */
241
245
  declare function createRectangleItem(id: string, bounds: Rect, style?: Partial<StrokeStyle>): VectorSceneItem;
242
246
  /** Creates an ellipse shape. */
@@ -265,7 +269,7 @@ declare function createLineItem(id: string, bounds: Rect, line: LineEndpointsLoc
265
269
  /** “Draw dot” tool: a small filled circle at (`worldX`, `worldY`). */
266
270
  declare function createDrawDotItem(id: string, worldX: number, worldY: number, radius: number, style?: Partial<StrokeStyle>): VectorSceneItem;
267
271
  /** Creates an editable text box (`stroke` is used as text fill). */
268
- declare function createTextItem(id: string, bounds: Rect, text?: string, style?: Partial<StrokeStyle>): VectorSceneItem;
272
+ declare function createTextItem(id: string, bounds: Rect, text?: string, style?: Partial<StrokeStyle>, textFontSize?: number): VectorSceneItem;
269
273
  /** Freehand stroke from world-space points (main pen or marker highlight). */
270
274
  declare function createFreehandStrokeItem(id: string, pointsWorld: readonly VectorPathPoint[], toolKind: "draw" | "marker", style?: Partial<StrokeStyle>): VectorSceneItem | null;
271
275
  /** Places a bitmap (e.g. `data:image/png;base64,...`) inside `bounds`. */
@@ -1,4 +1,4 @@
1
- import { V as VectorSceneItem, R as Rect, L as LineEndpointsLocal, b as VectorPathPoint, a as ArrowBindings } from './types-Bnq2HtHQ.js';
1
+ import { V as VectorSceneItem, R as Rect, L as LineEndpointsLocal, b as VectorPathPoint, a as ArrowBindings } from './types-BCCvY6ie.js';
2
2
 
3
3
  /**
4
4
  * Kind of binary selected through the built-in canvu asset ingestion flow.
@@ -148,11 +148,14 @@ declare const DEFAULT_LINK_CARD_SIZE: {
148
148
  readonly height: 132;
149
149
  };
150
150
 
151
+ /** Stroke dash pattern for freehand drawings. `solid` = perfect-freehand fill; `dashed` = centerline stroke with dashes. */
152
+ type StrokeDash = "solid" | "dashed";
151
153
  /** Resolved stroke for SVG generation. */
152
154
  type StrokeStyle = {
153
155
  stroke: string;
154
156
  strokeWidth: number;
155
157
  strokeOpacity?: number;
158
+ strokeDash?: StrokeDash;
156
159
  };
157
160
  declare const DEFAULT_STROKE_STYLE: StrokeStyle;
158
161
  declare function resolveStrokeStyle(item: VectorSceneItem): StrokeStyle;
@@ -202,6 +205,7 @@ type FreehandSvgPayload = {
202
205
  stroke: string;
203
206
  strokeWidth: number;
204
207
  strokeOpacity?: number;
208
+ strokeDasharray?: string;
205
209
  };
206
210
  /**
207
211
  * Computes freehand geometry (perfect-freehand + fallback). Used by {@link buildFreehandPathSvg}
@@ -236,7 +240,7 @@ declare function lineEndpointsToLocal(bounds: Rect, worldEndA: {
236
240
  */
237
241
  declare function rebuildItemSvg(item: VectorSceneItem): VectorSceneItem;
238
242
  /** Updates stroke color / width / opacity and refreshes the item’s SVG. */
239
- declare function applyStrokeToItem(item: VectorSceneItem, patch: Partial<Pick<VectorSceneItem, "stroke" | "strokeWidth" | "strokeOpacity">>): VectorSceneItem;
243
+ declare function applyStrokeToItem(item: VectorSceneItem, patch: Partial<Pick<VectorSceneItem, "stroke" | "strokeWidth" | "strokeOpacity" | "strokeDash" | "textFontSize">>): VectorSceneItem;
240
244
  /** Creates a rectangle shape ready to append to your scene `items` array. */
241
245
  declare function createRectangleItem(id: string, bounds: Rect, style?: Partial<StrokeStyle>): VectorSceneItem;
242
246
  /** Creates an ellipse shape. */
@@ -265,7 +269,7 @@ declare function createLineItem(id: string, bounds: Rect, line: LineEndpointsLoc
265
269
  /** “Draw dot” tool: a small filled circle at (`worldX`, `worldY`). */
266
270
  declare function createDrawDotItem(id: string, worldX: number, worldY: number, radius: number, style?: Partial<StrokeStyle>): VectorSceneItem;
267
271
  /** Creates an editable text box (`stroke` is used as text fill). */
268
- declare function createTextItem(id: string, bounds: Rect, text?: string, style?: Partial<StrokeStyle>): VectorSceneItem;
272
+ declare function createTextItem(id: string, bounds: Rect, text?: string, style?: Partial<StrokeStyle>, textFontSize?: number): VectorSceneItem;
269
273
  /** Freehand stroke from world-space points (main pen or marker highlight). */
270
274
  declare function createFreehandStrokeItem(id: string, pointsWorld: readonly VectorPathPoint[], toolKind: "draw" | "marker", style?: Partial<StrokeStyle>): VectorSceneItem | null;
271
275
  /** Places a bitmap (e.g. `data:image/png;base64,...`) inside `bounds`. */
package/dist/tldraw.cjs CHANGED
@@ -123,11 +123,14 @@ function escapeHtmlText2(s) {
123
123
  return s.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
124
124
  }
125
125
  var DEFAULT_TEXT_FONT_SIZE = 18;
126
+ var TEXT_FONT_FAMILY = "Inter, -apple-system, BlinkMacSystemFont, ui-sans-serif, system-ui, sans-serif";
126
127
  var LINE_HEIGHT_RATIO = 22 / 18;
127
- var FIRST_LINE_BASELINE_RATIO = 24 / 18;
128
+ var FIRST_LINE_BASELINE_RATIO = 20 / 18;
129
+ var EDIT_TOP_PAD_RATIO = 4 / 18;
130
+ var BOTTOM_PAD_RATIO = 4 / 18;
128
131
  var PLACEHOLDER = "Tap to type";
129
132
  var MIN_TEXT_BOX_W = 40;
130
- var MIN_TEXT_BOX_H = 36;
133
+ var MIN_TEXT_BOX_H = 26;
131
134
  var TEXT_PAD_X = 4;
132
135
  var MAX_TEXT_MEASURE_CACHE_ENTRIES = 2e3;
133
136
  var sharedMeasureContext;
@@ -173,7 +176,7 @@ function measureTextBoundsLocal(content, fontSize = DEFAULT_TEXT_FONT_SIZE) {
173
176
  let maxInnerW = 0;
174
177
  const ctx = getSharedMeasureContext();
175
178
  if (ctx) {
176
- ctx.font = `${fontSize}px system-ui, sans-serif`;
179
+ ctx.font = `${fontSize}px ${TEXT_FONT_FAMILY}`;
177
180
  for (const line of lines) {
178
181
  const toMeasure = trimmed.length === 0 ? PLACEHOLDER : line.length === 0 ? " " : line;
179
182
  maxInnerW = Math.max(maxInnerW, ctx.measureText(toMeasure).width);
@@ -189,22 +192,22 @@ function measureTextBoundsLocal(content, fontSize = DEFAULT_TEXT_FONT_SIZE) {
189
192
  const width = Math.max(minW, TEXT_PAD_X * 2 + maxInnerW);
190
193
  const height = Math.max(
191
194
  MIN_TEXT_BOX_H,
192
- baselineY + (lines.length - 1) * lh + Math.max(8, fontSize * 0.35)
195
+ baselineY + (lines.length - 1) * lh + Math.max(4, fontSize * BOTTOM_PAD_RATIO)
193
196
  );
194
197
  const measured = { width, height };
195
198
  cacheMeasuredBounds(cacheKey, measured);
196
199
  return measured;
197
200
  }
198
- function buildTextSvg(content, _width, _height, fillColor = "#2563eb", fontSize = DEFAULT_TEXT_FONT_SIZE) {
201
+ function buildTextSvg(content, _width, _height, fillColor = "#1d1d1d", fontSize = DEFAULT_TEXT_FONT_SIZE) {
199
202
  const lh = lineHeightFor(fontSize);
200
203
  const y0 = firstLineBaselineY(fontSize);
201
204
  const trimmed = content.trim();
202
205
  if (trimmed.length === 0) {
203
- return `<text x="4" y="${y0}" font-size="${fontSize}" font-family="system-ui,sans-serif" fill="#94a3b8" font-style="italic">${escapeSvgTextContent(PLACEHOLDER)}</text>`;
206
+ return `<text x="4" y="${y0}" font-size="${fontSize}" font-family="${TEXT_FONT_FAMILY}" fill="#94a3b8" font-style="italic">${escapeSvgTextContent(PLACEHOLDER)}</text>`;
204
207
  }
205
208
  const lines = content.split("\n");
206
209
  if (lines.length === 1) {
207
- return `<text x="4" y="${y0}" font-size="${fontSize}" font-family="system-ui,sans-serif" fill="${fillColor}">${escapeSvgTextContent(lines[0] ?? "")}</text>`;
210
+ return `<text x="4" y="${y0}" font-size="${fontSize}" font-family="${TEXT_FONT_FAMILY}" fill="${fillColor}">${escapeSvgTextContent(lines[0] ?? "")}</text>`;
208
211
  }
209
212
  const parts = [];
210
213
  for (let i = 0; i < lines.length; i++) {
@@ -215,23 +218,24 @@ function buildTextSvg(content, _width, _height, fillColor = "#2563eb", fontSize
215
218
  parts.push(`<tspan x="4" dy="${lh}">${escapeSvgTextContent(line)}</tspan>`);
216
219
  }
217
220
  }
218
- return `<text x="4" y="${y0}" font-size="${fontSize}" font-family="system-ui,sans-serif" fill="${fillColor}">${parts.join("")}</text>`;
221
+ return `<text x="4" y="${y0}" font-size="${fontSize}" font-family="${TEXT_FONT_FAMILY}" fill="${fillColor}">${parts.join("")}</text>`;
219
222
  }
220
- function buildTextFixedBoundsSvg(content, width, height, fillColor = "#2563eb", fontSize = DEFAULT_TEXT_FONT_SIZE) {
223
+ function buildTextFixedBoundsSvg(content, width, height, fillColor = "#1d1d1d", fontSize = DEFAULT_TEXT_FONT_SIZE) {
221
224
  const w = Math.max(1, width);
222
225
  const h = Math.max(1, height);
223
226
  const lh = lineHeightFor(fontSize);
224
227
  const trimmed = content.trim();
228
+ const padTop = EDIT_TOP_PAD_RATIO * fontSize;
225
229
  if (trimmed.length === 0) {
226
- 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">${escapeHtmlText2(PLACEHOLDER)}</div></foreignObject>`;
230
+ 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">${escapeHtmlText2(PLACEHOLDER)}</div></foreignObject>`;
227
231
  }
228
232
  const body = escapeHtmlText2(content);
229
- 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>`;
233
+ 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>`;
230
234
  }
231
235
 
232
236
  // src/scene/shape-builders.ts
233
237
  var DEFAULT_STROKE_STYLE = {
234
- stroke: "#2563eb",
238
+ stroke: "#1d1d1d",
235
239
  strokeWidth: 2
236
240
  };
237
241
  function perfectFreehandOptions(toolKind, style, strokeComplete, pressureAware = false) {
@@ -282,7 +286,8 @@ function resolveStrokeStyle(item) {
282
286
  return {
283
287
  stroke: item.stroke ?? DEFAULT_STROKE_STYLE.stroke,
284
288
  strokeWidth: item.strokeWidth ?? DEFAULT_STROKE_STYLE.strokeWidth,
285
- strokeOpacity: item.strokeOpacity
289
+ strokeOpacity: item.strokeOpacity,
290
+ strokeDash: item.strokeDash
286
291
  };
287
292
  }
288
293
  function strokeOpacityAttr(style) {
@@ -611,6 +616,30 @@ function buildDrawDotSvg(r, style = DEFAULT_STROKE_STYLE) {
611
616
  const op = style.strokeOpacity != null ? ` fill-opacity="${style.strokeOpacity}"` : "";
612
617
  return `<circle cx="${r}" cy="${r}" r="${r}" fill="${style.stroke}" shape-rendering="geometricPrecision"${op} />`;
613
618
  }
619
+ function dashArrayForDrawStroke(strokeWidth) {
620
+ const dash = Math.max(strokeWidth * 1.8, 4);
621
+ const gap = Math.max(strokeWidth * 1.4, 3);
622
+ return `${dash} ${gap}`;
623
+ }
624
+ function buildSmoothedCenterlinePath(points) {
625
+ if (points.length < 2) return null;
626
+ const first = points[0];
627
+ if (!first) return null;
628
+ let d = `M ${first.x} ${first.y}`;
629
+ for (let i = 1; i < points.length - 1; i++) {
630
+ const a = points[i];
631
+ const b = points[i + 1];
632
+ if (!a || !b) continue;
633
+ const midX = (a.x + b.x) / 2;
634
+ const midY = (a.y + b.y) / 2;
635
+ d += ` Q ${a.x} ${a.y} ${midX} ${midY}`;
636
+ }
637
+ const last = points[points.length - 1];
638
+ if (last) {
639
+ d += ` L ${last.x} ${last.y}`;
640
+ }
641
+ return d;
642
+ }
614
643
  function computeFreehandSvgPayload(pathPointsLocal, style, toolKind, strokeComplete = true) {
615
644
  if (pathPointsLocal.length === 0) return null;
616
645
  if (pathPointsLocal.length === 1) {
@@ -625,6 +654,18 @@ function computeFreehandSvgPayload(pathPointsLocal, style, toolKind, strokeCompl
625
654
  fillOpacity: style.strokeOpacity
626
655
  };
627
656
  }
657
+ if (style.strokeDash === "dashed" && (toolKind === "draw" || toolKind === "pencil")) {
658
+ const d2 = buildSmoothedCenterlinePath(pathPointsLocal);
659
+ if (!d2) return null;
660
+ return {
661
+ kind: "strokePath",
662
+ d: d2,
663
+ stroke: style.stroke,
664
+ strokeWidth: style.strokeWidth,
665
+ strokeOpacity: style.strokeOpacity,
666
+ strokeDasharray: dashArrayForDrawStroke(style.strokeWidth)
667
+ };
668
+ }
628
669
  const hasPressure = pathPointsLocal.some(
629
670
  (p) => p.pressure != null && Number.isFinite(p.pressure)
630
671
  );
@@ -667,7 +708,8 @@ function freehandPayloadToSvgString(payload) {
667
708
  strokeWidth: payload.strokeWidth,
668
709
  strokeOpacity: payload.strokeOpacity
669
710
  });
670
- return `<path d="${payload.d}" fill="none" stroke="${payload.stroke}" stroke-width="${payload.strokeWidth}" stroke-linecap="round" stroke-linejoin="round" shape-rendering="geometricPrecision"${op} />`;
711
+ const dash = payload.strokeDasharray ? ` stroke-dasharray="${payload.strokeDasharray}"` : "";
712
+ 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} />`;
671
713
  }
672
714
  function buildFreehandPathSvg(pathPointsLocal, style, toolKind, strokeComplete = true) {
673
715
  const payload = computeFreehandSvgPayload(