canvu-react 0.3.31 → 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 +168 -30
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +168 -30
- package/dist/index.js.map +1 -1
- package/dist/native.cjs +168 -30
- package/dist/native.cjs.map +1 -1
- package/dist/native.js +168 -30
- package/dist/native.js.map +1 -1
- package/dist/react.cjs +170 -32
- package/dist/react.cjs.map +1 -1
- package/dist/react.js +170 -32
- package/dist/react.js.map +1 -1
- package/dist/realtime.cjs +2 -2
- package/dist/realtime.cjs.map +1 -1
- package/dist/realtime.js +2 -2
- package/dist/realtime.js.map +1 -1
- package/dist/tldraw.cjs +168 -30
- package/dist/tldraw.cjs.map +1 -1
- package/dist/tldraw.js +168 -30
- package/dist/tldraw.js.map +1 -1
- package/package.json +1 -1
package/dist/tldraw.cjs
CHANGED
|
@@ -228,17 +228,154 @@ 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
|
}
|
|
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];
|
|
378
|
+
}
|
|
242
379
|
function buildRectSvg(width, height, style = DEFAULT_STROKE_STYLE) {
|
|
243
380
|
return `<rect width="${width}" height="${height}" fill="none" stroke="${style.stroke}" stroke-width="${style.strokeWidth}" rx="4"${strokeOpacityAttr(style)} />`;
|
|
244
381
|
}
|
|
@@ -252,33 +389,34 @@ function buildArchitecturalCloudPathD(width, height, strokeWidth = DEFAULT_STROK
|
|
|
252
389
|
const h = Math.max(0, height);
|
|
253
390
|
if (w <= 0 || h <= 0) return "";
|
|
254
391
|
const inset = Math.max(0.5, strokeWidth / 2);
|
|
255
|
-
const
|
|
256
|
-
const
|
|
257
|
-
if (
|
|
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 "";
|
|
258
395
|
const amplitude = Math.min(
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
Math.max(
|
|
396
|
+
outerWidth * 0.12,
|
|
397
|
+
outerHeight * 0.12,
|
|
398
|
+
Math.max(5, Math.min(14, Math.min(w, h) * 0.07))
|
|
399
|
+
);
|
|
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)
|
|
262
411
|
);
|
|
263
|
-
const
|
|
264
|
-
const
|
|
265
|
-
const scallopCount = architecturalCloudScallopCount(innerRx, innerRy, amplitude);
|
|
266
|
-
const angleStep = Math.PI * 2 / scallopCount;
|
|
267
|
-
const cx = w / 2;
|
|
268
|
-
const cy = h / 2;
|
|
269
|
-
const startAngle = -Math.PI / 2;
|
|
270
|
-
const pointOnEllipse = (theta, radiusX, radiusY) => [
|
|
271
|
-
cx + Math.cos(theta) * radiusX,
|
|
272
|
-
cy + Math.sin(theta) * radiusY
|
|
273
|
-
];
|
|
274
|
-
const [startX, startY] = pointOnEllipse(startAngle, innerRx, innerRy);
|
|
412
|
+
const scallopCount = architecturalCloudScallopCount(outer.perimeter, amplitude);
|
|
413
|
+
const [startX, startY] = pointOnRoundedRectPath(inner, 0);
|
|
275
414
|
const segments = [`M${svgNumber(startX)} ${svgNumber(startY)}`];
|
|
276
415
|
for (let index = 0; index < scallopCount; index += 1) {
|
|
277
|
-
const
|
|
278
|
-
const
|
|
279
|
-
const
|
|
280
|
-
const [
|
|
281
|
-
const [endX, endY] = pointOnEllipse(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);
|
|
282
420
|
segments.push(
|
|
283
421
|
`Q${svgNumber(controlX)} ${svgNumber(controlY)} ${svgNumber(endX)} ${svgNumber(endY)}`
|
|
284
422
|
);
|