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.
- package/dist/{asset-hydration-DowNdaOJ.d.cts → asset-hydration-B7yMDQE-.d.cts} +2 -2
- package/dist/{asset-hydration-DdFLdlqX.d.ts → asset-hydration-CbwQVAwh.d.ts} +2 -2
- package/dist/{camera-Di5R_Rwl.d.cts → camera-CVVG7z56.d.cts} +1 -1
- package/dist/{camera-AoTwBSoE.d.ts → camera-CoRYN_IV.d.ts} +1 -1
- package/dist/chatbot.d.cts +4 -4
- package/dist/chatbot.d.ts +4 -4
- package/dist/index.cjs +59 -15
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +6 -6
- package/dist/index.d.ts +6 -6
- package/dist/index.js +59 -15
- package/dist/index.js.map +1 -1
- package/dist/native.cjs +57 -14
- package/dist/native.cjs.map +1 -1
- package/dist/native.d.cts +2 -2
- package/dist/native.d.ts +2 -2
- package/dist/native.js +57 -14
- package/dist/native.js.map +1 -1
- package/dist/react.cjs +699 -255
- package/dist/react.cjs.map +1 -1
- package/dist/react.d.cts +10 -10
- package/dist/react.d.ts +10 -10
- package/dist/react.js +699 -255
- package/dist/react.js.map +1 -1
- package/dist/realtime.cjs +498 -129
- package/dist/realtime.cjs.map +1 -1
- package/dist/realtime.d.cts +6 -6
- package/dist/realtime.d.ts +6 -6
- package/dist/realtime.js +479 -129
- package/dist/realtime.js.map +1 -1
- package/dist/{shape-builders-Dedcl6tw.d.cts → shape-builders-BAWu-PxX.d.cts} +7 -3
- package/dist/{shape-builders-C7bxJBGR.d.ts → shape-builders-ClKv9tz9.d.ts} +7 -3
- package/dist/tldraw.cjs +56 -14
- package/dist/tldraw.cjs.map +1 -1
- package/dist/tldraw.d.cts +1 -1
- package/dist/tldraw.d.ts +1 -1
- package/dist/tldraw.js +56 -14
- package/dist/tldraw.js.map +1 -1
- package/dist/{types-DUW61Tjy.d.cts → types-BC9Xgfu6.d.cts} +11 -6
- package/dist/{types-Bnq2HtHQ.d.cts → types-BCCvY6ie.d.cts} +2 -0
- package/dist/{types-Bnq2HtHQ.d.ts → types-BCCvY6ie.d.ts} +2 -0
- package/dist/{types-B2Na677H.d.cts → types-BUPc2Zgw.d.cts} +1 -1
- package/dist/{types-zmUah-vP.d.ts → types-CYtq9Pr9.d.ts} +1 -1
- package/dist/{types-BBb8KoyW.d.ts → types-DlSVGX0w.d.ts} +11 -6
- package/package.json +3 -2
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { V as VectorSceneItem, R as Rect, L as LineEndpointsLocal, b as VectorPathPoint, a as ArrowBindings } from './types-
|
|
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
|
|
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-
|
|
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
|
|
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, "&").replace(/</g, "<").replace(/>/g, ">");
|
|
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 =
|
|
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 =
|
|
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
|
|
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(
|
|
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 = "#
|
|
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="
|
|
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="
|
|
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="
|
|
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 = "#
|
|
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
|
|
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
|
|
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: "#
|
|
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
|
-
|
|
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(
|