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/index.js
CHANGED
|
@@ -1043,17 +1043,154 @@ function svgNumber(value) {
|
|
|
1043
1043
|
const rounded = Math.round(value * 100) / 100;
|
|
1044
1044
|
return Number.isInteger(rounded) ? String(rounded) : String(rounded);
|
|
1045
1045
|
}
|
|
1046
|
-
function
|
|
1047
|
-
|
|
1048
|
-
return Math.PI * (3 * (rx + ry) - Math.sqrt((3 * rx + ry) * (rx + 3 * ry)));
|
|
1049
|
-
}
|
|
1050
|
-
function architecturalCloudScallopCount(rx, ry, amplitude) {
|
|
1051
|
-
const perimeter = approximateEllipsePerimeter(rx, ry);
|
|
1052
|
-
const targetScallopLength = Math.max(10, amplitude * 2);
|
|
1046
|
+
function architecturalCloudScallopCount(perimeter, amplitude) {
|
|
1047
|
+
const targetScallopLength = Math.max(18, amplitude * 2.45);
|
|
1053
1048
|
let count = Math.max(12, Math.round(perimeter / targetScallopLength));
|
|
1054
1049
|
if (count % 2 === 1) count += 1;
|
|
1055
1050
|
return count;
|
|
1056
1051
|
}
|
|
1052
|
+
function roundedRectMetrics(width, height, inset, radius) {
|
|
1053
|
+
const left = inset;
|
|
1054
|
+
const top = inset;
|
|
1055
|
+
const right = width - inset;
|
|
1056
|
+
const bottom = height - inset;
|
|
1057
|
+
const rectWidth = Math.max(0, right - left);
|
|
1058
|
+
const rectHeight = Math.max(0, bottom - top);
|
|
1059
|
+
const normalizedRadius = Math.max(
|
|
1060
|
+
0,
|
|
1061
|
+
Math.min(radius, rectWidth / 2, rectHeight / 2)
|
|
1062
|
+
);
|
|
1063
|
+
const centerX = width / 2;
|
|
1064
|
+
const topHalfLength = Math.max(0, right - normalizedRadius - centerX);
|
|
1065
|
+
const horizontalLength = Math.max(0, rectWidth - normalizedRadius * 2);
|
|
1066
|
+
const verticalLength = Math.max(0, rectHeight - normalizedRadius * 2);
|
|
1067
|
+
const arcLength = normalizedRadius * (Math.PI / 2);
|
|
1068
|
+
return {
|
|
1069
|
+
left,
|
|
1070
|
+
top,
|
|
1071
|
+
right,
|
|
1072
|
+
bottom,
|
|
1073
|
+
radius: normalizedRadius,
|
|
1074
|
+
centerX,
|
|
1075
|
+
topHalfLength,
|
|
1076
|
+
horizontalLength,
|
|
1077
|
+
verticalLength,
|
|
1078
|
+
arcLength,
|
|
1079
|
+
perimeter: horizontalLength * 2 + verticalLength * 2 + Math.PI * 2 * normalizedRadius
|
|
1080
|
+
};
|
|
1081
|
+
}
|
|
1082
|
+
function pointOnLine(startX, startY, endX, endY, t) {
|
|
1083
|
+
return [startX + (endX - startX) * t, startY + (endY - startY) * t];
|
|
1084
|
+
}
|
|
1085
|
+
function pointOnArc(centerX, centerY, radius, startAngle, endAngle, t) {
|
|
1086
|
+
const theta = startAngle + (endAngle - startAngle) * t;
|
|
1087
|
+
return [centerX + Math.cos(theta) * radius, centerY + Math.sin(theta) * radius];
|
|
1088
|
+
}
|
|
1089
|
+
function pointOnRoundedRectPath(metrics, distance) {
|
|
1090
|
+
if (metrics.perimeter <= 0) return [metrics.centerX, metrics.top];
|
|
1091
|
+
let remaining = (distance % metrics.perimeter + metrics.perimeter) % metrics.perimeter;
|
|
1092
|
+
const consume = (length) => {
|
|
1093
|
+
if (length <= 1e-9) return null;
|
|
1094
|
+
if (remaining <= length) return remaining / length;
|
|
1095
|
+
remaining -= length;
|
|
1096
|
+
return null;
|
|
1097
|
+
};
|
|
1098
|
+
let t = consume(metrics.topHalfLength);
|
|
1099
|
+
if (t != null) {
|
|
1100
|
+
return pointOnLine(
|
|
1101
|
+
metrics.centerX,
|
|
1102
|
+
metrics.top,
|
|
1103
|
+
metrics.right - metrics.radius,
|
|
1104
|
+
metrics.top,
|
|
1105
|
+
t
|
|
1106
|
+
);
|
|
1107
|
+
}
|
|
1108
|
+
t = consume(metrics.arcLength);
|
|
1109
|
+
if (t != null) {
|
|
1110
|
+
return pointOnArc(
|
|
1111
|
+
metrics.right - metrics.radius,
|
|
1112
|
+
metrics.top + metrics.radius,
|
|
1113
|
+
metrics.radius,
|
|
1114
|
+
-Math.PI / 2,
|
|
1115
|
+
0,
|
|
1116
|
+
t
|
|
1117
|
+
);
|
|
1118
|
+
}
|
|
1119
|
+
t = consume(metrics.verticalLength);
|
|
1120
|
+
if (t != null) {
|
|
1121
|
+
return pointOnLine(
|
|
1122
|
+
metrics.right,
|
|
1123
|
+
metrics.top + metrics.radius,
|
|
1124
|
+
metrics.right,
|
|
1125
|
+
metrics.bottom - metrics.radius,
|
|
1126
|
+
t
|
|
1127
|
+
);
|
|
1128
|
+
}
|
|
1129
|
+
t = consume(metrics.arcLength);
|
|
1130
|
+
if (t != null) {
|
|
1131
|
+
return pointOnArc(
|
|
1132
|
+
metrics.right - metrics.radius,
|
|
1133
|
+
metrics.bottom - metrics.radius,
|
|
1134
|
+
metrics.radius,
|
|
1135
|
+
0,
|
|
1136
|
+
Math.PI / 2,
|
|
1137
|
+
t
|
|
1138
|
+
);
|
|
1139
|
+
}
|
|
1140
|
+
t = consume(metrics.horizontalLength);
|
|
1141
|
+
if (t != null) {
|
|
1142
|
+
return pointOnLine(
|
|
1143
|
+
metrics.right - metrics.radius,
|
|
1144
|
+
metrics.bottom,
|
|
1145
|
+
metrics.left + metrics.radius,
|
|
1146
|
+
metrics.bottom,
|
|
1147
|
+
t
|
|
1148
|
+
);
|
|
1149
|
+
}
|
|
1150
|
+
t = consume(metrics.arcLength);
|
|
1151
|
+
if (t != null) {
|
|
1152
|
+
return pointOnArc(
|
|
1153
|
+
metrics.left + metrics.radius,
|
|
1154
|
+
metrics.bottom - metrics.radius,
|
|
1155
|
+
metrics.radius,
|
|
1156
|
+
Math.PI / 2,
|
|
1157
|
+
Math.PI,
|
|
1158
|
+
t
|
|
1159
|
+
);
|
|
1160
|
+
}
|
|
1161
|
+
t = consume(metrics.verticalLength);
|
|
1162
|
+
if (t != null) {
|
|
1163
|
+
return pointOnLine(
|
|
1164
|
+
metrics.left,
|
|
1165
|
+
metrics.bottom - metrics.radius,
|
|
1166
|
+
metrics.left,
|
|
1167
|
+
metrics.top + metrics.radius,
|
|
1168
|
+
t
|
|
1169
|
+
);
|
|
1170
|
+
}
|
|
1171
|
+
t = consume(metrics.arcLength);
|
|
1172
|
+
if (t != null) {
|
|
1173
|
+
return pointOnArc(
|
|
1174
|
+
metrics.left + metrics.radius,
|
|
1175
|
+
metrics.top + metrics.radius,
|
|
1176
|
+
metrics.radius,
|
|
1177
|
+
Math.PI,
|
|
1178
|
+
Math.PI * 1.5,
|
|
1179
|
+
t
|
|
1180
|
+
);
|
|
1181
|
+
}
|
|
1182
|
+
t = consume(metrics.topHalfLength);
|
|
1183
|
+
if (t != null) {
|
|
1184
|
+
return pointOnLine(
|
|
1185
|
+
metrics.left + metrics.radius,
|
|
1186
|
+
metrics.top,
|
|
1187
|
+
metrics.centerX,
|
|
1188
|
+
metrics.top,
|
|
1189
|
+
t
|
|
1190
|
+
);
|
|
1191
|
+
}
|
|
1192
|
+
return [metrics.centerX, metrics.top];
|
|
1193
|
+
}
|
|
1057
1194
|
function buildRectSvg(width, height, style = DEFAULT_STROKE_STYLE) {
|
|
1058
1195
|
return `<rect width="${width}" height="${height}" fill="none" stroke="${style.stroke}" stroke-width="${style.strokeWidth}" rx="4"${strokeOpacityAttr(style)} />`;
|
|
1059
1196
|
}
|
|
@@ -1067,33 +1204,34 @@ function buildArchitecturalCloudPathD(width, height, strokeWidth = DEFAULT_STROK
|
|
|
1067
1204
|
const h = Math.max(0, height);
|
|
1068
1205
|
if (w <= 0 || h <= 0) return "";
|
|
1069
1206
|
const inset = Math.max(0.5, strokeWidth / 2);
|
|
1070
|
-
const
|
|
1071
|
-
const
|
|
1072
|
-
if (
|
|
1207
|
+
const outerWidth = Math.max(0, w - inset * 2);
|
|
1208
|
+
const outerHeight = Math.max(0, h - inset * 2);
|
|
1209
|
+
if (outerWidth <= 0 || outerHeight <= 0) return "";
|
|
1073
1210
|
const amplitude = Math.min(
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
Math.max(
|
|
1211
|
+
outerWidth * 0.12,
|
|
1212
|
+
outerHeight * 0.12,
|
|
1213
|
+
Math.max(5, Math.min(14, Math.min(w, h) * 0.07))
|
|
1077
1214
|
);
|
|
1078
|
-
const
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
const
|
|
1084
|
-
const
|
|
1085
|
-
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
|
|
1215
|
+
const radius = Math.min(
|
|
1216
|
+
outerWidth / 2,
|
|
1217
|
+
outerHeight / 2,
|
|
1218
|
+
Math.max(amplitude * 2.5, outerHeight * 0.43)
|
|
1219
|
+
);
|
|
1220
|
+
const outer = roundedRectMetrics(w, h, inset, radius);
|
|
1221
|
+
const inner = roundedRectMetrics(
|
|
1222
|
+
w,
|
|
1223
|
+
h,
|
|
1224
|
+
inset + amplitude,
|
|
1225
|
+
Math.max(0, radius - amplitude)
|
|
1226
|
+
);
|
|
1227
|
+
const scallopCount = architecturalCloudScallopCount(outer.perimeter, amplitude);
|
|
1228
|
+
const [startX, startY] = pointOnRoundedRectPath(inner, 0);
|
|
1090
1229
|
const segments = [`M${svgNumber(startX)} ${svgNumber(startY)}`];
|
|
1091
1230
|
for (let index = 0; index < scallopCount; index += 1) {
|
|
1092
|
-
const
|
|
1093
|
-
const
|
|
1094
|
-
const
|
|
1095
|
-
const [
|
|
1096
|
-
const [endX, endY] = pointOnEllipse(segmentEnd, innerRx, innerRy);
|
|
1231
|
+
const controlDistance = (index + 0.5) / scallopCount * outer.perimeter;
|
|
1232
|
+
const endDistance = (index + 1) / scallopCount * inner.perimeter;
|
|
1233
|
+
const [controlX, controlY] = pointOnRoundedRectPath(outer, controlDistance);
|
|
1234
|
+
const [endX, endY] = pointOnRoundedRectPath(inner, endDistance);
|
|
1097
1235
|
segments.push(
|
|
1098
1236
|
`Q${svgNumber(controlX)} ${svgNumber(controlY)} ${svgNumber(endX)} ${svgNumber(endY)}`
|
|
1099
1237
|
);
|