canvu-react 0.3.32 → 0.3.33
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/index.cjs +167 -39
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +167 -39
- package/dist/index.js.map +1 -1
- package/dist/native.cjs +167 -39
- package/dist/native.cjs.map +1 -1
- package/dist/native.js +167 -39
- package/dist/native.js.map +1 -1
- package/dist/react.cjs +168 -40
- package/dist/react.cjs.map +1 -1
- package/dist/react.js +168 -40
- package/dist/react.js.map +1 -1
- package/dist/realtime.cjs +1 -1
- package/dist/realtime.cjs.map +1 -1
- package/dist/realtime.js +1 -1
- package/dist/realtime.js.map +1 -1
- package/dist/tldraw.cjs +167 -39
- package/dist/tldraw.cjs.map +1 -1
- package/dist/tldraw.js +167 -39
- package/dist/tldraw.js.map +1 -1
- package/package.json +1 -1
package/dist/tldraw.cjs
CHANGED
|
@@ -228,24 +228,153 @@ function svgNumber(value) {
|
|
|
228
228
|
const rounded = Math.round(value * 100) / 100;
|
|
229
229
|
return Number.isInteger(rounded) ? String(rounded) : String(rounded);
|
|
230
230
|
}
|
|
231
|
-
function
|
|
232
|
-
|
|
233
|
-
return Math.PI * (3 * (rx + ry) - Math.sqrt((3 * rx + ry) * (rx + 3 * ry)));
|
|
234
|
-
}
|
|
235
|
-
function architecturalCloudScallopCount(rx, ry, amplitude) {
|
|
236
|
-
const perimeter = approximateEllipsePerimeter(rx, ry);
|
|
237
|
-
const targetScallopLength = Math.max(10, amplitude * 2);
|
|
231
|
+
function architecturalCloudScallopCount(perimeter, amplitude) {
|
|
232
|
+
const targetScallopLength = Math.max(18, amplitude * 2.45);
|
|
238
233
|
let count = Math.max(12, Math.round(perimeter / targetScallopLength));
|
|
239
234
|
if (count % 2 === 1) count += 1;
|
|
240
235
|
return count;
|
|
241
236
|
}
|
|
242
|
-
function
|
|
243
|
-
const
|
|
244
|
-
const
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
237
|
+
function roundedRectMetrics(width, height, inset, radius) {
|
|
238
|
+
const left = inset;
|
|
239
|
+
const top = inset;
|
|
240
|
+
const right = width - inset;
|
|
241
|
+
const bottom = height - inset;
|
|
242
|
+
const rectWidth = Math.max(0, right - left);
|
|
243
|
+
const rectHeight = Math.max(0, bottom - top);
|
|
244
|
+
const normalizedRadius = Math.max(
|
|
245
|
+
0,
|
|
246
|
+
Math.min(radius, rectWidth / 2, rectHeight / 2)
|
|
247
|
+
);
|
|
248
|
+
const centerX = width / 2;
|
|
249
|
+
const topHalfLength = Math.max(0, right - normalizedRadius - centerX);
|
|
250
|
+
const horizontalLength = Math.max(0, rectWidth - normalizedRadius * 2);
|
|
251
|
+
const verticalLength = Math.max(0, rectHeight - normalizedRadius * 2);
|
|
252
|
+
const arcLength = normalizedRadius * (Math.PI / 2);
|
|
253
|
+
return {
|
|
254
|
+
left,
|
|
255
|
+
top,
|
|
256
|
+
right,
|
|
257
|
+
bottom,
|
|
258
|
+
radius: normalizedRadius,
|
|
259
|
+
centerX,
|
|
260
|
+
topHalfLength,
|
|
261
|
+
horizontalLength,
|
|
262
|
+
verticalLength,
|
|
263
|
+
arcLength,
|
|
264
|
+
perimeter: horizontalLength * 2 + verticalLength * 2 + Math.PI * 2 * normalizedRadius
|
|
265
|
+
};
|
|
266
|
+
}
|
|
267
|
+
function pointOnLine(startX, startY, endX, endY, t) {
|
|
268
|
+
return [startX + (endX - startX) * t, startY + (endY - startY) * t];
|
|
269
|
+
}
|
|
270
|
+
function pointOnArc(centerX, centerY, radius, startAngle, endAngle, t) {
|
|
271
|
+
const theta = startAngle + (endAngle - startAngle) * t;
|
|
272
|
+
return [centerX + Math.cos(theta) * radius, centerY + Math.sin(theta) * radius];
|
|
273
|
+
}
|
|
274
|
+
function pointOnRoundedRectPath(metrics, distance) {
|
|
275
|
+
if (metrics.perimeter <= 0) return [metrics.centerX, metrics.top];
|
|
276
|
+
let remaining = (distance % metrics.perimeter + metrics.perimeter) % metrics.perimeter;
|
|
277
|
+
const consume = (length) => {
|
|
278
|
+
if (length <= 1e-9) return null;
|
|
279
|
+
if (remaining <= length) return remaining / length;
|
|
280
|
+
remaining -= length;
|
|
281
|
+
return null;
|
|
282
|
+
};
|
|
283
|
+
let t = consume(metrics.topHalfLength);
|
|
284
|
+
if (t != null) {
|
|
285
|
+
return pointOnLine(
|
|
286
|
+
metrics.centerX,
|
|
287
|
+
metrics.top,
|
|
288
|
+
metrics.right - metrics.radius,
|
|
289
|
+
metrics.top,
|
|
290
|
+
t
|
|
291
|
+
);
|
|
292
|
+
}
|
|
293
|
+
t = consume(metrics.arcLength);
|
|
294
|
+
if (t != null) {
|
|
295
|
+
return pointOnArc(
|
|
296
|
+
metrics.right - metrics.radius,
|
|
297
|
+
metrics.top + metrics.radius,
|
|
298
|
+
metrics.radius,
|
|
299
|
+
-Math.PI / 2,
|
|
300
|
+
0,
|
|
301
|
+
t
|
|
302
|
+
);
|
|
303
|
+
}
|
|
304
|
+
t = consume(metrics.verticalLength);
|
|
305
|
+
if (t != null) {
|
|
306
|
+
return pointOnLine(
|
|
307
|
+
metrics.right,
|
|
308
|
+
metrics.top + metrics.radius,
|
|
309
|
+
metrics.right,
|
|
310
|
+
metrics.bottom - metrics.radius,
|
|
311
|
+
t
|
|
312
|
+
);
|
|
313
|
+
}
|
|
314
|
+
t = consume(metrics.arcLength);
|
|
315
|
+
if (t != null) {
|
|
316
|
+
return pointOnArc(
|
|
317
|
+
metrics.right - metrics.radius,
|
|
318
|
+
metrics.bottom - metrics.radius,
|
|
319
|
+
metrics.radius,
|
|
320
|
+
0,
|
|
321
|
+
Math.PI / 2,
|
|
322
|
+
t
|
|
323
|
+
);
|
|
324
|
+
}
|
|
325
|
+
t = consume(metrics.horizontalLength);
|
|
326
|
+
if (t != null) {
|
|
327
|
+
return pointOnLine(
|
|
328
|
+
metrics.right - metrics.radius,
|
|
329
|
+
metrics.bottom,
|
|
330
|
+
metrics.left + metrics.radius,
|
|
331
|
+
metrics.bottom,
|
|
332
|
+
t
|
|
333
|
+
);
|
|
334
|
+
}
|
|
335
|
+
t = consume(metrics.arcLength);
|
|
336
|
+
if (t != null) {
|
|
337
|
+
return pointOnArc(
|
|
338
|
+
metrics.left + metrics.radius,
|
|
339
|
+
metrics.bottom - metrics.radius,
|
|
340
|
+
metrics.radius,
|
|
341
|
+
Math.PI / 2,
|
|
342
|
+
Math.PI,
|
|
343
|
+
t
|
|
344
|
+
);
|
|
345
|
+
}
|
|
346
|
+
t = consume(metrics.verticalLength);
|
|
347
|
+
if (t != null) {
|
|
348
|
+
return pointOnLine(
|
|
349
|
+
metrics.left,
|
|
350
|
+
metrics.bottom - metrics.radius,
|
|
351
|
+
metrics.left,
|
|
352
|
+
metrics.top + metrics.radius,
|
|
353
|
+
t
|
|
354
|
+
);
|
|
355
|
+
}
|
|
356
|
+
t = consume(metrics.arcLength);
|
|
357
|
+
if (t != null) {
|
|
358
|
+
return pointOnArc(
|
|
359
|
+
metrics.left + metrics.radius,
|
|
360
|
+
metrics.top + metrics.radius,
|
|
361
|
+
metrics.radius,
|
|
362
|
+
Math.PI,
|
|
363
|
+
Math.PI * 1.5,
|
|
364
|
+
t
|
|
365
|
+
);
|
|
366
|
+
}
|
|
367
|
+
t = consume(metrics.topHalfLength);
|
|
368
|
+
if (t != null) {
|
|
369
|
+
return pointOnLine(
|
|
370
|
+
metrics.left + metrics.radius,
|
|
371
|
+
metrics.top,
|
|
372
|
+
metrics.centerX,
|
|
373
|
+
metrics.top,
|
|
374
|
+
t
|
|
375
|
+
);
|
|
376
|
+
}
|
|
377
|
+
return [metrics.centerX, metrics.top];
|
|
249
378
|
}
|
|
250
379
|
function buildRectSvg(width, height, style = DEFAULT_STROKE_STYLE) {
|
|
251
380
|
return `<rect width="${width}" height="${height}" fill="none" stroke="${style.stroke}" stroke-width="${style.strokeWidth}" rx="4"${strokeOpacityAttr(style)} />`;
|
|
@@ -260,35 +389,34 @@ function buildArchitecturalCloudPathD(width, height, strokeWidth = DEFAULT_STROK
|
|
|
260
389
|
const h = Math.max(0, height);
|
|
261
390
|
if (w <= 0 || h <= 0) return "";
|
|
262
391
|
const inset = Math.max(0.5, strokeWidth / 2);
|
|
263
|
-
const
|
|
264
|
-
const
|
|
265
|
-
if (
|
|
266
|
-
const baseExponent = 3.6;
|
|
392
|
+
const outerWidth = Math.max(0, w - inset * 2);
|
|
393
|
+
const outerHeight = Math.max(0, h - inset * 2);
|
|
394
|
+
if (outerWidth <= 0 || outerHeight <= 0) return "";
|
|
267
395
|
const amplitude = Math.min(
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
Math.max(
|
|
396
|
+
outerWidth * 0.12,
|
|
397
|
+
outerHeight * 0.12,
|
|
398
|
+
Math.max(5, Math.min(14, Math.min(w, h) * 0.07))
|
|
271
399
|
);
|
|
272
|
-
const
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
const
|
|
278
|
-
const
|
|
279
|
-
|
|
280
|
-
|
|
400
|
+
const radius = Math.min(
|
|
401
|
+
outerWidth / 2,
|
|
402
|
+
outerHeight / 2,
|
|
403
|
+
Math.max(amplitude * 2.5, outerHeight * 0.43)
|
|
404
|
+
);
|
|
405
|
+
const outer = roundedRectMetrics(w, h, inset, radius);
|
|
406
|
+
const inner = roundedRectMetrics(
|
|
407
|
+
w,
|
|
408
|
+
h,
|
|
409
|
+
inset + amplitude,
|
|
410
|
+
Math.max(0, radius - amplitude)
|
|
411
|
+
);
|
|
412
|
+
const scallopCount = architecturalCloudScallopCount(outer.perimeter, amplitude);
|
|
413
|
+
const [startX, startY] = pointOnRoundedRectPath(inner, 0);
|
|
281
414
|
const segments = [`M${svgNumber(startX)} ${svgNumber(startY)}`];
|
|
282
415
|
for (let index = 0; index < scallopCount; index += 1) {
|
|
283
|
-
const
|
|
284
|
-
const
|
|
285
|
-
const
|
|
286
|
-
const [
|
|
287
|
-
segmentMid,
|
|
288
|
-
outerRx,
|
|
289
|
-
outerRy
|
|
290
|
-
);
|
|
291
|
-
const [endX, endY] = pointOnArchitecturalCloud(segmentEnd, innerRx, innerRy);
|
|
416
|
+
const controlDistance = (index + 0.5) / scallopCount * outer.perimeter;
|
|
417
|
+
const endDistance = (index + 1) / scallopCount * inner.perimeter;
|
|
418
|
+
const [controlX, controlY] = pointOnRoundedRectPath(outer, controlDistance);
|
|
419
|
+
const [endX, endY] = pointOnRoundedRectPath(inner, endDistance);
|
|
292
420
|
segments.push(
|
|
293
421
|
`Q${svgNumber(controlX)} ${svgNumber(controlY)} ${svgNumber(endX)} ${svgNumber(endY)}`
|
|
294
422
|
);
|