canvu-react 0.4.35 → 0.4.37
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-BFGZ3igr.d.cts → asset-hydration-Cy_2FyV5.d.cts} +1 -1
- package/dist/{asset-hydration-D6Q3TJL1.d.ts → asset-hydration-Dc7fsnTG.d.ts} +1 -1
- package/dist/{link-item-voRU0Up9.d.ts → asset-store-DQPRZEcy.d.ts} +2 -40
- package/dist/{link-item-Dncuz2d_.d.cts → asset-store-TzOPvlgn.d.cts} +2 -40
- package/dist/chatbot.d.cts +3 -2
- package/dist/chatbot.d.ts +3 -2
- package/dist/index.d.cts +3 -2
- package/dist/index.d.ts +3 -2
- package/dist/link-item-DwzXOwU5.d.cts +41 -0
- package/dist/link-item-IW4GTnxl.d.ts +41 -0
- package/dist/native.cjs +523 -73
- package/dist/native.cjs.map +1 -1
- package/dist/native.d.cts +65 -2
- package/dist/native.d.ts +65 -2
- package/dist/native.js +533 -87
- package/dist/native.js.map +1 -1
- package/dist/react.d.cts +7 -6
- package/dist/react.d.ts +7 -6
- package/dist/realtime.d.cts +3 -2
- package/dist/realtime.d.ts +3 -2
- package/dist/{types-DeDm865m.d.ts → types-B7xZAKVJ.d.ts} +2 -1
- package/dist/{types-NBYvslB-.d.cts → types-C4wI3Jyc.d.cts} +2 -1
- package/package.json +1 -1
package/dist/native.cjs
CHANGED
|
@@ -10,8 +10,6 @@ function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
|
|
|
10
10
|
|
|
11
11
|
var getStroke__default = /*#__PURE__*/_interopDefault(getStroke);
|
|
12
12
|
|
|
13
|
-
// src/scene/shape-builders.ts
|
|
14
|
-
|
|
15
13
|
// src/math/rect.ts
|
|
16
14
|
function rectsIntersect(a, b) {
|
|
17
15
|
return a.x < b.x + b.width && a.x + a.width > b.x && a.y < b.y + b.height && a.y + a.height > b.y;
|
|
@@ -28,12 +26,36 @@ function normalizeRect(r) {
|
|
|
28
26
|
}
|
|
29
27
|
|
|
30
28
|
// src/scene/custom-shape.ts
|
|
29
|
+
function expandCustomShapeTemplate(template, width, height) {
|
|
30
|
+
return template.replace(/\{\{w\}\}/g, String(width)).replace(/\{\{h\}\}/g, String(height)).replace(/\{\{width\}\}/g, String(width)).replace(/\{\{height\}\}/g, String(height));
|
|
31
|
+
}
|
|
32
|
+
function resolveCustomInner(content, size) {
|
|
33
|
+
if ("render" in content) {
|
|
34
|
+
return content.render(size);
|
|
35
|
+
}
|
|
36
|
+
return expandCustomShapeTemplate(content.svg, size.width, size.height);
|
|
37
|
+
}
|
|
31
38
|
function buildCustomShapeChildrenSvg(inner, intrinsic, bounds) {
|
|
32
39
|
const b = normalizeRect(bounds);
|
|
33
40
|
const sx = b.width / intrinsic.width;
|
|
34
41
|
const sy = b.height / intrinsic.height;
|
|
35
42
|
return `<g transform="scale(${sx},${sy})">${inner}</g>`;
|
|
36
43
|
}
|
|
44
|
+
function createCustomShapeItem(id, bounds, content) {
|
|
45
|
+
const r = normalizeRect(bounds);
|
|
46
|
+
const intrinsic = { width: r.width, height: r.height };
|
|
47
|
+
const inner = resolveCustomInner(content, intrinsic);
|
|
48
|
+
return {
|
|
49
|
+
id,
|
|
50
|
+
x: r.x,
|
|
51
|
+
y: r.y,
|
|
52
|
+
bounds: { ...r },
|
|
53
|
+
toolKind: "custom",
|
|
54
|
+
customIntrinsicSize: intrinsic,
|
|
55
|
+
customInnerSvg: inner,
|
|
56
|
+
childrenSvg: buildCustomShapeChildrenSvg(inner, intrinsic, r)
|
|
57
|
+
};
|
|
58
|
+
}
|
|
37
59
|
|
|
38
60
|
// src/scene/link-item.ts
|
|
39
61
|
var LINK_PLUGIN_KEY = "canvuLink";
|
|
@@ -146,6 +168,9 @@ function getLinkData(item) {
|
|
|
146
168
|
const entry = item.pluginData?.[LINK_PLUGIN_KEY];
|
|
147
169
|
return isCanvuLinkData(entry) ? entry : null;
|
|
148
170
|
}
|
|
171
|
+
function isLinkItem(item) {
|
|
172
|
+
return getLinkData(item) != null;
|
|
173
|
+
}
|
|
149
174
|
function rebuildLinkItemSvg(item) {
|
|
150
175
|
const link = getLinkData(item);
|
|
151
176
|
if (!link) return item;
|
|
@@ -179,6 +204,26 @@ function rebuildLinkItemSvg(item) {
|
|
|
179
204
|
childrenSvg: buildLinkCardSvg(width, height, link)
|
|
180
205
|
};
|
|
181
206
|
}
|
|
207
|
+
function createLinkItem(id, bounds, link) {
|
|
208
|
+
const width = bounds.width || DEFAULT_LINK_CARD_WIDTH;
|
|
209
|
+
const height = bounds.height || DEFAULT_LINK_CARD_HEIGHT;
|
|
210
|
+
const item = createCustomShapeItem(
|
|
211
|
+
id,
|
|
212
|
+
{ ...bounds, width, height },
|
|
213
|
+
{ render: (size) => buildLinkCardSvg(size.width, size.height, link) }
|
|
214
|
+
);
|
|
215
|
+
return rebuildLinkItemSvg({
|
|
216
|
+
...item,
|
|
217
|
+
pluginData: {
|
|
218
|
+
...item.pluginData ?? {},
|
|
219
|
+
[LINK_PLUGIN_KEY]: link
|
|
220
|
+
}
|
|
221
|
+
});
|
|
222
|
+
}
|
|
223
|
+
var DEFAULT_LINK_CARD_SIZE = {
|
|
224
|
+
width: DEFAULT_LINK_CARD_WIDTH,
|
|
225
|
+
height: DEFAULT_LINK_CARD_HEIGHT
|
|
226
|
+
};
|
|
182
227
|
|
|
183
228
|
// src/scene/text-svg.ts
|
|
184
229
|
function escapeSvgTextContent(s) {
|
|
@@ -1404,6 +1449,50 @@ function smoothFreehandPointsToPathD(points) {
|
|
|
1404
1449
|
d += ` Q ${pLast.x} ${pLast.y} ${pEnd.x} ${pEnd.y}`;
|
|
1405
1450
|
return d;
|
|
1406
1451
|
}
|
|
1452
|
+
|
|
1453
|
+
// src/native/native-link-card.ts
|
|
1454
|
+
function linkHostname(href) {
|
|
1455
|
+
try {
|
|
1456
|
+
return new URL(href).hostname.replace(/^www\./, "");
|
|
1457
|
+
} catch {
|
|
1458
|
+
return href;
|
|
1459
|
+
}
|
|
1460
|
+
}
|
|
1461
|
+
function linkProtocol(href) {
|
|
1462
|
+
try {
|
|
1463
|
+
return new URL(href).protocol;
|
|
1464
|
+
} catch {
|
|
1465
|
+
return "";
|
|
1466
|
+
}
|
|
1467
|
+
}
|
|
1468
|
+
function linkInitial(value) {
|
|
1469
|
+
const first = value.trim().charAt(0).toUpperCase();
|
|
1470
|
+
return first || "L";
|
|
1471
|
+
}
|
|
1472
|
+
function normalizeNativeLinkHref(value) {
|
|
1473
|
+
const trimmed = value.trim();
|
|
1474
|
+
if (!trimmed) return null;
|
|
1475
|
+
if (/^[a-z][a-z0-9+.-]*:/i.test(trimmed)) return trimmed;
|
|
1476
|
+
return `https://${trimmed}`;
|
|
1477
|
+
}
|
|
1478
|
+
function buildNativeLinkCardDisplay(link) {
|
|
1479
|
+
const hostname = linkHostname(link.href);
|
|
1480
|
+
const title = link.title?.trim() || hostname || "Link";
|
|
1481
|
+
return {
|
|
1482
|
+
title,
|
|
1483
|
+
subtitle: hostname || link.href,
|
|
1484
|
+
initial: linkInitial(hostname || title),
|
|
1485
|
+
secure: linkProtocol(link.href) === "https:"
|
|
1486
|
+
};
|
|
1487
|
+
}
|
|
1488
|
+
function createNativeLinkCardBoundsAtPoint(point) {
|
|
1489
|
+
return {
|
|
1490
|
+
x: point.x - DEFAULT_LINK_CARD_SIZE.width / 2,
|
|
1491
|
+
y: point.y - DEFAULT_LINK_CARD_SIZE.height / 2,
|
|
1492
|
+
width: DEFAULT_LINK_CARD_SIZE.width,
|
|
1493
|
+
height: DEFAULT_LINK_CARD_SIZE.height
|
|
1494
|
+
};
|
|
1495
|
+
}
|
|
1407
1496
|
var DEFAULT_NATIVE_IMAGE_CACHE_MAX_ENTRIES = 96;
|
|
1408
1497
|
function disposeCachedImage(image) {
|
|
1409
1498
|
try {
|
|
@@ -2093,7 +2182,119 @@ function localBounds(bounds) {
|
|
|
2093
2182
|
const b = normalizeRect(bounds);
|
|
2094
2183
|
return { w: Math.max(0, b.width), h: Math.max(0, b.height) };
|
|
2095
2184
|
}
|
|
2185
|
+
function truncateText(value, maxChars) {
|
|
2186
|
+
if (value.length <= maxChars) return value;
|
|
2187
|
+
return `${value.slice(0, Math.max(0, maxChars - 3)).trimEnd()}...`;
|
|
2188
|
+
}
|
|
2189
|
+
function NativeLinkCardRenderer({
|
|
2190
|
+
item,
|
|
2191
|
+
link
|
|
2192
|
+
}) {
|
|
2193
|
+
const bounds = normalizeRect(item.bounds);
|
|
2194
|
+
const scaleX = Math.max(0.01, bounds.width / DEFAULT_LINK_CARD_SIZE.width);
|
|
2195
|
+
const scaleY = Math.max(0.01, bounds.height / DEFAULT_LINK_CARD_SIZE.height);
|
|
2196
|
+
const display = buildNativeLinkCardDisplay(link);
|
|
2197
|
+
const titleFont = reactNativeSkia.matchFont({ fontSize: 14.5, fontWeight: "700" });
|
|
2198
|
+
const subtitleFont = reactNativeSkia.matchFont({ fontSize: 12.5 });
|
|
2199
|
+
const initialFont = reactNativeSkia.matchFont({ fontSize: 17, fontWeight: "700" });
|
|
2200
|
+
const title = truncateText(display.title, 28);
|
|
2201
|
+
const subtitle = truncateText(display.subtitle, display.secure ? 28 : 31);
|
|
2202
|
+
const subtitleX = display.secure ? 82 : 69;
|
|
2203
|
+
const subtitleWidth = display.secure ? 188 : 201;
|
|
2204
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(reactNativeSkia.Group, { transform: [{ scaleX }, { scaleY }], children: [
|
|
2205
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2206
|
+
reactNativeSkia.RoundedRect,
|
|
2207
|
+
{
|
|
2208
|
+
x: 0,
|
|
2209
|
+
y: 0,
|
|
2210
|
+
width: DEFAULT_LINK_CARD_SIZE.width,
|
|
2211
|
+
height: DEFAULT_LINK_CARD_SIZE.height,
|
|
2212
|
+
r: 16,
|
|
2213
|
+
color: "#ffffff",
|
|
2214
|
+
style: "fill",
|
|
2215
|
+
antiAlias: true
|
|
2216
|
+
}
|
|
2217
|
+
),
|
|
2218
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2219
|
+
reactNativeSkia.RoundedRect,
|
|
2220
|
+
{
|
|
2221
|
+
x: 0.5,
|
|
2222
|
+
y: 0.5,
|
|
2223
|
+
width: DEFAULT_LINK_CARD_SIZE.width - 1,
|
|
2224
|
+
height: DEFAULT_LINK_CARD_SIZE.height - 1,
|
|
2225
|
+
r: 15.5,
|
|
2226
|
+
color: "#dfe4ea",
|
|
2227
|
+
style: "stroke",
|
|
2228
|
+
strokeWidth: 1,
|
|
2229
|
+
antiAlias: true
|
|
2230
|
+
}
|
|
2231
|
+
),
|
|
2232
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2233
|
+
reactNativeSkia.RoundedRect,
|
|
2234
|
+
{
|
|
2235
|
+
x: 14,
|
|
2236
|
+
y: 14,
|
|
2237
|
+
width: 42,
|
|
2238
|
+
height: 42,
|
|
2239
|
+
r: 11,
|
|
2240
|
+
color: "#315bd6",
|
|
2241
|
+
style: "fill",
|
|
2242
|
+
antiAlias: true
|
|
2243
|
+
}
|
|
2244
|
+
),
|
|
2245
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2246
|
+
reactNativeSkia.Text,
|
|
2247
|
+
{
|
|
2248
|
+
x: 29.5,
|
|
2249
|
+
y: 41,
|
|
2250
|
+
text: display.initial,
|
|
2251
|
+
color: "#ffffff",
|
|
2252
|
+
font: initialFont
|
|
2253
|
+
}
|
|
2254
|
+
),
|
|
2255
|
+
/* @__PURE__ */ jsxRuntime.jsx(reactNativeSkia.Group, { clip: { x: 69, y: 13, width: 215, height: 24 }, children: /* @__PURE__ */ jsxRuntime.jsx(reactNativeSkia.Text, { x: 69, y: 32, text: title, color: "#1f2937", font: titleFont }) }),
|
|
2256
|
+
display.secure ? /* @__PURE__ */ jsxRuntime.jsxs(reactNativeSkia.Group, { transform: [{ translateX: 69 }, { translateY: 41 }], children: [
|
|
2257
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2258
|
+
reactNativeSkia.Rect,
|
|
2259
|
+
{
|
|
2260
|
+
x: 1.5,
|
|
2261
|
+
y: 4.5,
|
|
2262
|
+
width: 7,
|
|
2263
|
+
height: 6,
|
|
2264
|
+
color: "#6b7280",
|
|
2265
|
+
style: "stroke",
|
|
2266
|
+
strokeWidth: 1.3
|
|
2267
|
+
}
|
|
2268
|
+
),
|
|
2269
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2270
|
+
reactNativeSkia.Path,
|
|
2271
|
+
{
|
|
2272
|
+
path: "M3 4.5 V3 a2 2 0 0 1 4 0 v1.5",
|
|
2273
|
+
color: "#6b7280",
|
|
2274
|
+
style: "stroke",
|
|
2275
|
+
strokeWidth: 1.3,
|
|
2276
|
+
strokeCap: "round",
|
|
2277
|
+
strokeJoin: "round"
|
|
2278
|
+
}
|
|
2279
|
+
)
|
|
2280
|
+
] }) : null,
|
|
2281
|
+
/* @__PURE__ */ jsxRuntime.jsx(reactNativeSkia.Group, { clip: { x: subtitleX, y: 34, width: subtitleWidth, height: 22 }, children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
2282
|
+
reactNativeSkia.Text,
|
|
2283
|
+
{
|
|
2284
|
+
x: subtitleX,
|
|
2285
|
+
y: 51,
|
|
2286
|
+
text: subtitle,
|
|
2287
|
+
color: "#6b7280",
|
|
2288
|
+
font: subtitleFont
|
|
2289
|
+
}
|
|
2290
|
+
) })
|
|
2291
|
+
] });
|
|
2292
|
+
}
|
|
2096
2293
|
function NativeShapeRenderer({ item }) {
|
|
2294
|
+
const link = getLinkData(item);
|
|
2295
|
+
if (link) {
|
|
2296
|
+
return /* @__PURE__ */ jsxRuntime.jsx(NativeLinkCardRenderer, { item, link });
|
|
2297
|
+
}
|
|
2097
2298
|
const style = resolveStrokeStyle(item);
|
|
2098
2299
|
const k = item.toolKind;
|
|
2099
2300
|
if (k === "rect") {
|
|
@@ -3516,9 +3717,14 @@ var DEFAULT_NATIVE_OVERFLOW_TOOL_IDS = [
|
|
|
3516
3717
|
"line",
|
|
3517
3718
|
"marker",
|
|
3518
3719
|
"laser",
|
|
3519
|
-
"image"
|
|
3720
|
+
"image",
|
|
3721
|
+
"link"
|
|
3520
3722
|
];
|
|
3521
3723
|
var CLOUD_TOOL_ICON_PATH = "M17.5 19H8.5a6.5 6.5 0 1 1 6.17-8.55A4.75 4.75 0 0 1 17.5 9.5a4.75 4.75 0 0 1 0 9.5Z";
|
|
3724
|
+
var LINK_TOOL_ICON_PATHS = [
|
|
3725
|
+
"M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71",
|
|
3726
|
+
"M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"
|
|
3727
|
+
];
|
|
3522
3728
|
function NativeCloudToolIcon({
|
|
3523
3729
|
color,
|
|
3524
3730
|
size = 19,
|
|
@@ -3537,6 +3743,25 @@ function NativeCloudToolIcon({
|
|
|
3537
3743
|
}
|
|
3538
3744
|
) }) });
|
|
3539
3745
|
}
|
|
3746
|
+
function NativeLinkToolIcon({
|
|
3747
|
+
color,
|
|
3748
|
+
size = 20,
|
|
3749
|
+
strokeWidth = 2.4
|
|
3750
|
+
}) {
|
|
3751
|
+
const scale = size / 24;
|
|
3752
|
+
return /* @__PURE__ */ jsxRuntime.jsx(reactNativeSkia.Canvas, { style: { width: size, height: size }, children: /* @__PURE__ */ jsxRuntime.jsx(reactNativeSkia.Group, { transform: [{ scale }], children: LINK_TOOL_ICON_PATHS.map((path) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
3753
|
+
reactNativeSkia.Path,
|
|
3754
|
+
{
|
|
3755
|
+
path,
|
|
3756
|
+
color,
|
|
3757
|
+
style: "stroke",
|
|
3758
|
+
strokeWidth,
|
|
3759
|
+
strokeCap: "round",
|
|
3760
|
+
strokeJoin: "round"
|
|
3761
|
+
},
|
|
3762
|
+
path
|
|
3763
|
+
)) }) });
|
|
3764
|
+
}
|
|
3540
3765
|
var DEFAULT_NATIVE_VECTOR_TOOLS = [
|
|
3541
3766
|
{ id: "hand", label: "Hand", shortcutHint: "H", shortLabel: "H" },
|
|
3542
3767
|
{ id: "select", label: "Select", shortcutHint: "V", shortLabel: "V" },
|
|
@@ -3574,7 +3799,8 @@ var DEFAULT_NATIVE_VECTOR_TOOLS = [
|
|
|
3574
3799
|
shortLabel: "E"
|
|
3575
3800
|
},
|
|
3576
3801
|
{ id: "text", label: "Text", shortcutHint: "T", shortLabel: "T" },
|
|
3577
|
-
{ id: "image", label: "File", shortcutHint: "I", shortLabel: "I" }
|
|
3802
|
+
{ id: "image", label: "File", shortcutHint: "I", shortLabel: "I" },
|
|
3803
|
+
{ id: "link", label: "Link", shortcutHint: "N", shortLabel: "L" }
|
|
3578
3804
|
];
|
|
3579
3805
|
function splitToolbarTools(tools, overflowToolIds) {
|
|
3580
3806
|
const overflowIds = new Set(overflowToolIds);
|
|
@@ -3836,6 +4062,9 @@ function renderNativeToolFallback(tool, foregroundColor, toolLabelStyle) {
|
|
|
3836
4062
|
if (tool.id === "architectural-cloud") {
|
|
3837
4063
|
return /* @__PURE__ */ jsxRuntime.jsx(NativeCloudToolIcon, { color: foregroundColor });
|
|
3838
4064
|
}
|
|
4065
|
+
if (tool.id === "link") {
|
|
4066
|
+
return /* @__PURE__ */ jsxRuntime.jsx(NativeLinkToolIcon, { color: foregroundColor });
|
|
4067
|
+
}
|
|
3839
4068
|
return /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: [styles2.shortLabel, { color: foregroundColor }, toolLabelStyle], children: tool.shortLabel ?? tool.label.slice(0, 1).toUpperCase() });
|
|
3840
4069
|
}
|
|
3841
4070
|
var styles2 = reactNative.StyleSheet.create({
|
|
@@ -4434,6 +4663,13 @@ function resizeItemByHandle(item, start, handle, currentWorld) {
|
|
|
4434
4663
|
}
|
|
4435
4664
|
return { ...item, x: nb.x, y: nb.y, bounds: nb };
|
|
4436
4665
|
}
|
|
4666
|
+
var DEFAULT_NATIVE_LINK_TOOL_DIALOG_LABELS = {
|
|
4667
|
+
title: "Add link",
|
|
4668
|
+
description: "Paste the link you want to add to the board.",
|
|
4669
|
+
inputPlaceholder: "https://example.com",
|
|
4670
|
+
cancelLabel: "Cancel",
|
|
4671
|
+
addLabel: "Add"
|
|
4672
|
+
};
|
|
4437
4673
|
var MIN_PLACE_SIZE = 8;
|
|
4438
4674
|
var MIN_ARROW_DRAG_PX = 8;
|
|
4439
4675
|
var TAP_PX = 20;
|
|
@@ -4516,6 +4752,8 @@ var NativeVectorViewport = react.forwardRef(function NativeVectorViewport2({
|
|
|
4516
4752
|
onSelectionChange,
|
|
4517
4753
|
onItemsChange,
|
|
4518
4754
|
onToolChangeRequest,
|
|
4755
|
+
onLinkToolRequest,
|
|
4756
|
+
linkToolDialogLabels,
|
|
4519
4757
|
onWorldPointerDown,
|
|
4520
4758
|
onWorldPointerMove,
|
|
4521
4759
|
onWorldPointerLeave,
|
|
@@ -4535,6 +4773,8 @@ var NativeVectorViewport = react.forwardRef(function NativeVectorViewport2({
|
|
|
4535
4773
|
toolLockedRef.current = toolLocked;
|
|
4536
4774
|
const onToolChangeRequestRef = react.useRef(onToolChangeRequest);
|
|
4537
4775
|
onToolChangeRequestRef.current = onToolChangeRequest;
|
|
4776
|
+
const onLinkToolRequestRef = react.useRef(onLinkToolRequest);
|
|
4777
|
+
onLinkToolRequestRef.current = onLinkToolRequest;
|
|
4538
4778
|
const onWorldPointerDownRef = react.useRef(onWorldPointerDown);
|
|
4539
4779
|
onWorldPointerDownRef.current = onWorldPointerDown;
|
|
4540
4780
|
const onWorldPointerMoveRef = react.useRef(onWorldPointerMove);
|
|
@@ -4568,6 +4808,8 @@ var NativeVectorViewport = react.forwardRef(function NativeVectorViewport2({
|
|
|
4568
4808
|
);
|
|
4569
4809
|
const [eraserTrail, setEraserTrail] = react.useState([]);
|
|
4570
4810
|
const [laserTrail, setLaserTrail] = react.useState([]);
|
|
4811
|
+
const [pendingNativeLinkRequest, setPendingNativeLinkRequest] = react.useState(null);
|
|
4812
|
+
const [nativeLinkInputValue, setNativeLinkInputValue] = react.useState("");
|
|
4571
4813
|
const laserClearTimerRef = react.useRef(null);
|
|
4572
4814
|
const strokeStyleRef = react.useRef({ ...DEFAULT_STROKE_STYLE });
|
|
4573
4815
|
const markerStrokeStyleRef = react.useRef({ ...MARKER_TOOL_STYLE });
|
|
@@ -4645,6 +4887,21 @@ var NativeVectorViewport = react.forwardRef(function NativeVectorViewport2({
|
|
|
4645
4887
|
onToolChangeRequestRef.current?.("select");
|
|
4646
4888
|
}
|
|
4647
4889
|
}, []);
|
|
4890
|
+
const requestSelectToolAfterNativeLinkUse = react.useCallback(() => {
|
|
4891
|
+
onToolChangeRequestRef.current?.("select");
|
|
4892
|
+
}, []);
|
|
4893
|
+
const closeNativeLinkDialog = react.useCallback(() => {
|
|
4894
|
+
setPendingNativeLinkRequest(null);
|
|
4895
|
+
setNativeLinkInputValue("");
|
|
4896
|
+
}, []);
|
|
4897
|
+
const submitNativeLinkDialog = react.useCallback(() => {
|
|
4898
|
+
const href = normalizeNativeLinkHref(nativeLinkInputValue);
|
|
4899
|
+
if (!href || !pendingNativeLinkRequest) return;
|
|
4900
|
+
const inserted = pendingNativeLinkRequest.insertLink({ href });
|
|
4901
|
+
if (inserted) {
|
|
4902
|
+
closeNativeLinkDialog();
|
|
4903
|
+
}
|
|
4904
|
+
}, [closeNativeLinkDialog, nativeLinkInputValue, pendingNativeLinkRequest]);
|
|
4648
4905
|
if (!cameraRef.current) {
|
|
4649
4906
|
cameraRef.current = new Camera2D({ minZoom: 0.05, maxZoom: 32 });
|
|
4650
4907
|
}
|
|
@@ -4877,7 +5134,7 @@ var NativeVectorViewport = react.forwardRef(function NativeVectorViewport2({
|
|
|
4877
5134
|
});
|
|
4878
5135
|
return;
|
|
4879
5136
|
}
|
|
4880
|
-
if (tool === "note" || tool === "text") {
|
|
5137
|
+
if (tool === "link" || tool === "note" || tool === "text") {
|
|
4881
5138
|
dragStateRef.current = {
|
|
4882
5139
|
kind: "tap",
|
|
4883
5140
|
tool,
|
|
@@ -5213,6 +5470,43 @@ var NativeVectorViewport = react.forwardRef(function NativeVectorViewport2({
|
|
|
5213
5470
|
const screenDy = point.y - st.startScreen.y;
|
|
5214
5471
|
if (Math.hypot(screenDx, screenDy) > TAP_PX) return;
|
|
5215
5472
|
const change = onItemsChangeRef.current;
|
|
5473
|
+
if (st.tool === "link") {
|
|
5474
|
+
const suggestedBounds = createNativeLinkCardBoundsAtPoint(st.startWorld);
|
|
5475
|
+
const insertLink = (link, options = {}) => {
|
|
5476
|
+
const currentChange = onItemsChangeRef.current;
|
|
5477
|
+
if (!currentChange) return null;
|
|
5478
|
+
const id = options.id ?? createShapeId();
|
|
5479
|
+
const item = createLinkItem(id, options.bounds ?? suggestedBounds, link);
|
|
5480
|
+
currentChange([...itemsRef.current, item]);
|
|
5481
|
+
onSelectionChangeRef.current?.([id]);
|
|
5482
|
+
requestSelectToolAfterNativeLinkUse();
|
|
5483
|
+
return item;
|
|
5484
|
+
};
|
|
5485
|
+
const requestLink = onLinkToolRequestRef.current;
|
|
5486
|
+
if (requestLink) {
|
|
5487
|
+
requestLink({
|
|
5488
|
+
toolId: "link",
|
|
5489
|
+
worldX: st.startWorld.x,
|
|
5490
|
+
worldY: st.startWorld.y,
|
|
5491
|
+
screenX: st.startScreen.x,
|
|
5492
|
+
screenY: st.startScreen.y,
|
|
5493
|
+
suggestedBounds,
|
|
5494
|
+
insertLink
|
|
5495
|
+
});
|
|
5496
|
+
return;
|
|
5497
|
+
}
|
|
5498
|
+
setNativeLinkInputValue("");
|
|
5499
|
+
setPendingNativeLinkRequest({
|
|
5500
|
+
toolId: "link",
|
|
5501
|
+
worldX: st.startWorld.x,
|
|
5502
|
+
worldY: st.startWorld.y,
|
|
5503
|
+
screenX: st.startScreen.x,
|
|
5504
|
+
screenY: st.startScreen.y,
|
|
5505
|
+
suggestedBounds,
|
|
5506
|
+
insertLink
|
|
5507
|
+
});
|
|
5508
|
+
return;
|
|
5509
|
+
}
|
|
5216
5510
|
if (!change) return;
|
|
5217
5511
|
if (st.tool === "text") {
|
|
5218
5512
|
const id = createShapeId();
|
|
@@ -5260,6 +5554,7 @@ var NativeVectorViewport = react.forwardRef(function NativeVectorViewport2({
|
|
|
5260
5554
|
dragStateRef.current = { kind: "idle" };
|
|
5261
5555
|
},
|
|
5262
5556
|
[
|
|
5557
|
+
requestSelectToolAfterNativeLinkUse,
|
|
5263
5558
|
requestSelectToolAfterUse,
|
|
5264
5559
|
screenToWorld,
|
|
5265
5560
|
setRealtimePlacementPreview,
|
|
@@ -5391,7 +5686,13 @@ var NativeVectorViewport = react.forwardRef(function NativeVectorViewport2({
|
|
|
5391
5686
|
[requestRender, size]
|
|
5392
5687
|
);
|
|
5393
5688
|
const activeStyleToolId = toolId === "draw" || toolId === "marker" ? toolId : null;
|
|
5394
|
-
|
|
5689
|
+
const nativeLinkDialogLabels = {
|
|
5690
|
+
...DEFAULT_NATIVE_LINK_TOOL_DIALOG_LABELS,
|
|
5691
|
+
...linkToolDialogLabels ?? {}
|
|
5692
|
+
};
|
|
5693
|
+
const normalizedNativeLinkHref = normalizeNativeLinkHref(nativeLinkInputValue);
|
|
5694
|
+
const nativeLinkCanSubmit = pendingNativeLinkRequest !== null && normalizedNativeLinkHref !== null && onItemsChange != null;
|
|
5695
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
5395
5696
|
reactNative.View,
|
|
5396
5697
|
{
|
|
5397
5698
|
style: { flex: 1, overflow: "hidden" },
|
|
@@ -5405,81 +5706,227 @@ var NativeVectorViewport = react.forwardRef(function NativeVectorViewport2({
|
|
|
5405
5706
|
notifyWorldPointerLeave();
|
|
5406
5707
|
},
|
|
5407
5708
|
...panResponder.panHandlers,
|
|
5408
|
-
children:
|
|
5709
|
+
children: [
|
|
5710
|
+
size.width > 0 && size.height > 0 && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
5711
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
5712
|
+
NativeSceneRenderer,
|
|
5713
|
+
{
|
|
5714
|
+
items: sceneItems,
|
|
5715
|
+
camera,
|
|
5716
|
+
width: size.width,
|
|
5717
|
+
height: size.height
|
|
5718
|
+
}
|
|
5719
|
+
),
|
|
5720
|
+
interactive && /* @__PURE__ */ jsxRuntime.jsx(
|
|
5721
|
+
NativeInteractionOverlay,
|
|
5722
|
+
{
|
|
5723
|
+
camera,
|
|
5724
|
+
width: size.width,
|
|
5725
|
+
height: size.height,
|
|
5726
|
+
selectedItems,
|
|
5727
|
+
showResizeHandles,
|
|
5728
|
+
placementPreview,
|
|
5729
|
+
laserTrail,
|
|
5730
|
+
eraserTrail,
|
|
5731
|
+
eraserPreviewItems: items.filter(
|
|
5732
|
+
(it) => eraserPreviewIds.includes(it.id)
|
|
5733
|
+
),
|
|
5734
|
+
previewStrokeStyle: strokeStyleState,
|
|
5735
|
+
remotePresence
|
|
5736
|
+
}
|
|
5737
|
+
),
|
|
5738
|
+
interactive && showStyleInspector && activeStyleToolId ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
5739
|
+
reactNative.View,
|
|
5740
|
+
{
|
|
5741
|
+
pointerEvents: "box-none",
|
|
5742
|
+
style: styleInspectorPlacement === "top-left" ? {
|
|
5743
|
+
position: "absolute",
|
|
5744
|
+
left: 16,
|
|
5745
|
+
top: 104,
|
|
5746
|
+
alignItems: "flex-start"
|
|
5747
|
+
} : {
|
|
5748
|
+
position: "absolute",
|
|
5749
|
+
left: 16,
|
|
5750
|
+
right: 16,
|
|
5751
|
+
bottom: 84,
|
|
5752
|
+
alignItems: "center"
|
|
5753
|
+
},
|
|
5754
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
5755
|
+
NativeVectorStyleInspector,
|
|
5756
|
+
{
|
|
5757
|
+
toolId: activeStyleToolId,
|
|
5758
|
+
value: strokeStyleState,
|
|
5759
|
+
onChange: patchCurrentStrokeStyle
|
|
5760
|
+
}
|
|
5761
|
+
)
|
|
5762
|
+
}
|
|
5763
|
+
) : null,
|
|
5764
|
+
toolbar && /* @__PURE__ */ jsxRuntime.jsx(
|
|
5765
|
+
reactNative.View,
|
|
5766
|
+
{
|
|
5767
|
+
style: {
|
|
5768
|
+
position: "absolute",
|
|
5769
|
+
bottom: 16,
|
|
5770
|
+
left: 16,
|
|
5771
|
+
right: 16,
|
|
5772
|
+
flexDirection: "row",
|
|
5773
|
+
justifyContent: "center",
|
|
5774
|
+
alignItems: "center"
|
|
5775
|
+
},
|
|
5776
|
+
pointerEvents: "box-none",
|
|
5777
|
+
children: toolbar
|
|
5778
|
+
}
|
|
5779
|
+
)
|
|
5780
|
+
] }),
|
|
5409
5781
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
5410
|
-
|
|
5411
|
-
{
|
|
5412
|
-
items: sceneItems,
|
|
5413
|
-
camera,
|
|
5414
|
-
width: size.width,
|
|
5415
|
-
height: size.height
|
|
5416
|
-
}
|
|
5417
|
-
),
|
|
5418
|
-
interactive && /* @__PURE__ */ jsxRuntime.jsx(
|
|
5419
|
-
NativeInteractionOverlay,
|
|
5420
|
-
{
|
|
5421
|
-
camera,
|
|
5422
|
-
width: size.width,
|
|
5423
|
-
height: size.height,
|
|
5424
|
-
selectedItems,
|
|
5425
|
-
showResizeHandles,
|
|
5426
|
-
placementPreview,
|
|
5427
|
-
laserTrail,
|
|
5428
|
-
eraserTrail,
|
|
5429
|
-
eraserPreviewItems: items.filter(
|
|
5430
|
-
(it) => eraserPreviewIds.includes(it.id)
|
|
5431
|
-
),
|
|
5432
|
-
previewStrokeStyle: strokeStyleState,
|
|
5433
|
-
remotePresence
|
|
5434
|
-
}
|
|
5435
|
-
),
|
|
5436
|
-
interactive && showStyleInspector && activeStyleToolId ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
5437
|
-
reactNative.View,
|
|
5782
|
+
reactNative.Modal,
|
|
5438
5783
|
{
|
|
5439
|
-
|
|
5440
|
-
|
|
5441
|
-
|
|
5442
|
-
|
|
5443
|
-
|
|
5444
|
-
|
|
5445
|
-
|
|
5446
|
-
|
|
5447
|
-
|
|
5448
|
-
|
|
5449
|
-
|
|
5450
|
-
|
|
5451
|
-
|
|
5452
|
-
|
|
5453
|
-
|
|
5454
|
-
|
|
5455
|
-
|
|
5456
|
-
|
|
5457
|
-
|
|
5458
|
-
|
|
5459
|
-
|
|
5460
|
-
|
|
5461
|
-
|
|
5462
|
-
|
|
5463
|
-
|
|
5464
|
-
|
|
5465
|
-
|
|
5466
|
-
|
|
5467
|
-
|
|
5468
|
-
|
|
5469
|
-
|
|
5470
|
-
|
|
5471
|
-
|
|
5472
|
-
|
|
5473
|
-
|
|
5474
|
-
|
|
5475
|
-
|
|
5784
|
+
animationType: "fade",
|
|
5785
|
+
transparent: true,
|
|
5786
|
+
visible: pendingNativeLinkRequest !== null,
|
|
5787
|
+
onRequestClose: closeNativeLinkDialog,
|
|
5788
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { style: styles3.nativeLinkDialogBackdrop, children: /* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style: styles3.nativeLinkDialogCard, children: [
|
|
5789
|
+
/* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: styles3.nativeLinkDialogTitle, children: nativeLinkDialogLabels.title }),
|
|
5790
|
+
/* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: styles3.nativeLinkDialogDescription, children: nativeLinkDialogLabels.description }),
|
|
5791
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
5792
|
+
reactNative.TextInput,
|
|
5793
|
+
{
|
|
5794
|
+
accessibilityLabel: nativeLinkDialogLabels.title,
|
|
5795
|
+
autoCapitalize: "none",
|
|
5796
|
+
autoCorrect: false,
|
|
5797
|
+
keyboardType: "url",
|
|
5798
|
+
onChangeText: setNativeLinkInputValue,
|
|
5799
|
+
onSubmitEditing: submitNativeLinkDialog,
|
|
5800
|
+
placeholder: nativeLinkDialogLabels.inputPlaceholder,
|
|
5801
|
+
returnKeyType: "done",
|
|
5802
|
+
style: styles3.nativeLinkDialogInput,
|
|
5803
|
+
value: nativeLinkInputValue
|
|
5804
|
+
}
|
|
5805
|
+
),
|
|
5806
|
+
/* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style: styles3.nativeLinkDialogActions, children: [
|
|
5807
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
5808
|
+
reactNative.Pressable,
|
|
5809
|
+
{
|
|
5810
|
+
accessibilityRole: "button",
|
|
5811
|
+
onPress: closeNativeLinkDialog,
|
|
5812
|
+
style: ({ pressed }) => [
|
|
5813
|
+
styles3.nativeLinkDialogButton,
|
|
5814
|
+
pressed ? styles3.nativeLinkDialogButtonPressed : void 0
|
|
5815
|
+
],
|
|
5816
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: styles3.nativeLinkDialogButtonText, children: nativeLinkDialogLabels.cancelLabel })
|
|
5817
|
+
}
|
|
5818
|
+
),
|
|
5819
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
5820
|
+
reactNative.Pressable,
|
|
5821
|
+
{
|
|
5822
|
+
accessibilityRole: "button",
|
|
5823
|
+
accessibilityState: { disabled: !nativeLinkCanSubmit },
|
|
5824
|
+
disabled: !nativeLinkCanSubmit,
|
|
5825
|
+
onPress: submitNativeLinkDialog,
|
|
5826
|
+
style: ({ pressed }) => [
|
|
5827
|
+
styles3.nativeLinkDialogButton,
|
|
5828
|
+
styles3.nativeLinkDialogPrimaryButton,
|
|
5829
|
+
pressed && nativeLinkCanSubmit ? styles3.nativeLinkDialogPrimaryButtonPressed : void 0,
|
|
5830
|
+
!nativeLinkCanSubmit ? styles3.nativeLinkDialogDisabledButton : void 0
|
|
5831
|
+
],
|
|
5832
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: styles3.nativeLinkDialogPrimaryButtonText, children: nativeLinkDialogLabels.addLabel })
|
|
5833
|
+
}
|
|
5834
|
+
)
|
|
5835
|
+
] })
|
|
5836
|
+
] }) })
|
|
5476
5837
|
}
|
|
5477
5838
|
)
|
|
5478
|
-
]
|
|
5839
|
+
]
|
|
5479
5840
|
}
|
|
5480
5841
|
);
|
|
5481
5842
|
});
|
|
5843
|
+
var styles3 = reactNative.StyleSheet.create({
|
|
5844
|
+
nativeLinkDialogBackdrop: {
|
|
5845
|
+
flex: 1,
|
|
5846
|
+
alignItems: "center",
|
|
5847
|
+
justifyContent: "center",
|
|
5848
|
+
paddingHorizontal: 24,
|
|
5849
|
+
backgroundColor: "rgba(0, 0, 0, 0.45)"
|
|
5850
|
+
},
|
|
5851
|
+
nativeLinkDialogCard: {
|
|
5852
|
+
width: "100%",
|
|
5853
|
+
maxWidth: 480,
|
|
5854
|
+
padding: 24,
|
|
5855
|
+
borderRadius: 16,
|
|
5856
|
+
backgroundColor: "#ffffff",
|
|
5857
|
+
shadowColor: "#000000",
|
|
5858
|
+
shadowOpacity: 0.18,
|
|
5859
|
+
shadowRadius: 24,
|
|
5860
|
+
shadowOffset: { width: 0, height: 8 },
|
|
5861
|
+
elevation: 12
|
|
5862
|
+
},
|
|
5863
|
+
nativeLinkDialogTitle: {
|
|
5864
|
+
color: "#111827",
|
|
5865
|
+
fontSize: 24,
|
|
5866
|
+
fontWeight: "700",
|
|
5867
|
+
lineHeight: 30
|
|
5868
|
+
},
|
|
5869
|
+
nativeLinkDialogDescription: {
|
|
5870
|
+
marginTop: 12,
|
|
5871
|
+
color: "#6b7280",
|
|
5872
|
+
fontSize: 16,
|
|
5873
|
+
lineHeight: 22
|
|
5874
|
+
},
|
|
5875
|
+
nativeLinkDialogInput: {
|
|
5876
|
+
marginTop: 24,
|
|
5877
|
+
height: 52,
|
|
5878
|
+
paddingHorizontal: 14,
|
|
5879
|
+
borderRadius: 10,
|
|
5880
|
+
borderWidth: reactNative.StyleSheet.hairlineWidth,
|
|
5881
|
+
borderColor: "#d1d5db",
|
|
5882
|
+
color: "#111827",
|
|
5883
|
+
fontSize: 18,
|
|
5884
|
+
backgroundColor: "#ffffff"
|
|
5885
|
+
},
|
|
5886
|
+
nativeLinkDialogActions: {
|
|
5887
|
+
marginTop: 24,
|
|
5888
|
+
flexDirection: "row",
|
|
5889
|
+
justifyContent: "flex-end",
|
|
5890
|
+
gap: 12
|
|
5891
|
+
},
|
|
5892
|
+
nativeLinkDialogButton: {
|
|
5893
|
+
minWidth: 92,
|
|
5894
|
+
height: 48,
|
|
5895
|
+
alignItems: "center",
|
|
5896
|
+
justifyContent: "center",
|
|
5897
|
+
borderRadius: 10,
|
|
5898
|
+
borderWidth: reactNative.StyleSheet.hairlineWidth,
|
|
5899
|
+
borderColor: "#d1d5db",
|
|
5900
|
+
backgroundColor: "#ffffff",
|
|
5901
|
+
paddingHorizontal: 18
|
|
5902
|
+
},
|
|
5903
|
+
nativeLinkDialogButtonPressed: {
|
|
5904
|
+
backgroundColor: "#f3f4f6"
|
|
5905
|
+
},
|
|
5906
|
+
nativeLinkDialogButtonText: {
|
|
5907
|
+
color: "#111827",
|
|
5908
|
+
fontSize: 17,
|
|
5909
|
+
fontWeight: "600"
|
|
5910
|
+
},
|
|
5911
|
+
nativeLinkDialogPrimaryButton: {
|
|
5912
|
+
borderColor: "#18181b",
|
|
5913
|
+
backgroundColor: "#18181b"
|
|
5914
|
+
},
|
|
5915
|
+
nativeLinkDialogPrimaryButtonPressed: {
|
|
5916
|
+
backgroundColor: "#27272a"
|
|
5917
|
+
},
|
|
5918
|
+
nativeLinkDialogDisabledButton: {
|
|
5919
|
+
borderColor: "#9ca3af",
|
|
5920
|
+
backgroundColor: "#9ca3af"
|
|
5921
|
+
},
|
|
5922
|
+
nativeLinkDialogPrimaryButtonText: {
|
|
5923
|
+
color: "#ffffff",
|
|
5924
|
+
fontSize: 17,
|
|
5925
|
+
fontWeight: "700"
|
|
5926
|
+
}
|
|
5927
|
+
});
|
|
5482
5928
|
|
|
5929
|
+
exports.DEFAULT_LINK_CARD_SIZE = DEFAULT_LINK_CARD_SIZE;
|
|
5483
5930
|
exports.DEFAULT_NATIVE_OVERFLOW_TOOL_IDS = DEFAULT_NATIVE_OVERFLOW_TOOL_IDS;
|
|
5484
5931
|
exports.DEFAULT_NATIVE_VECTOR_TOOLS = DEFAULT_NATIVE_VECTOR_TOOLS;
|
|
5485
5932
|
exports.NATIVE_STYLE_PALETTE = NATIVE_STYLE_PALETTE;
|
|
@@ -5491,7 +5938,10 @@ exports.NativeVectorToolbar = NativeVectorToolbar;
|
|
|
5491
5938
|
exports.NativeVectorViewport = NativeVectorViewport;
|
|
5492
5939
|
exports.createFreehandStrokeItem = createFreehandStrokeItem;
|
|
5493
5940
|
exports.createImageItem = createImageItem;
|
|
5941
|
+
exports.createLinkItem = createLinkItem;
|
|
5494
5942
|
exports.createShapeId = createShapeId;
|
|
5943
|
+
exports.getLinkData = getLinkData;
|
|
5944
|
+
exports.isLinkItem = isLinkItem;
|
|
5495
5945
|
exports.nativeStyleColorWithOpacity = nativeStyleColorWithOpacity;
|
|
5496
5946
|
exports.normalizeNativeStyleHex = normalizeNativeStyleHex;
|
|
5497
5947
|
exports.parseSvgFragment = parseSvgFragment;
|