canvu-react 0.4.34 → 0.4.36
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 +409 -6
- package/dist/native.cjs.map +1 -1
- package/dist/native.d.cts +52 -2
- package/dist/native.d.ts +52 -2
- package/dist/native.js +407 -8
- 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.d.cts
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { C as CanvuLinkData } from './link-item-DwzXOwU5.cjs';
|
|
2
|
+
export { D as DEFAULT_LINK_CARD_SIZE, c as createLinkItem, g as getLinkData, i as isLinkItem } from './link-item-DwzXOwU5.cjs';
|
|
1
3
|
import { C as Camera2D, S as StrokeStyle } from './shape-builders-CKEMjivV.cjs';
|
|
2
4
|
export { o as createFreehandStrokeItem, q as createImageItem, t as createShapeId } from './shape-builders-CKEMjivV.cjs';
|
|
3
5
|
import { V as VectorSceneItem, R as Rect } from './types-BCCvY6ie.cjs';
|
|
@@ -162,7 +164,7 @@ type NativeVectorToolbarProps = {
|
|
|
162
164
|
readonly renderOverflowChevronIcon?: (input: NativeVectorToolbarRenderOverflowInput) => ReactNode;
|
|
163
165
|
readonly renderToolButton?: (input: NativeVectorToolbarRenderToolInput) => ReactNode;
|
|
164
166
|
};
|
|
165
|
-
declare const DEFAULT_NATIVE_OVERFLOW_TOOL_IDS: readonly ["rect", "ellipse", "architectural-cloud", "line", "marker", "laser", "image"];
|
|
167
|
+
declare const DEFAULT_NATIVE_OVERFLOW_TOOL_IDS: readonly ["rect", "ellipse", "architectural-cloud", "line", "marker", "laser", "image", "link"];
|
|
166
168
|
/**
|
|
167
169
|
* Default mobile-friendly tool list for {@link NativeVectorToolbar}.
|
|
168
170
|
*
|
|
@@ -213,6 +215,46 @@ type NativeWorldPointerDownDetail = {
|
|
|
213
215
|
readonly screenX: number;
|
|
214
216
|
readonly screenY: number;
|
|
215
217
|
};
|
|
218
|
+
/**
|
|
219
|
+
* Optional override for a link item inserted from the native link tool.
|
|
220
|
+
*
|
|
221
|
+
* Use this when your app has already reserved an item id or wants to place the
|
|
222
|
+
* link card at a custom box. Most apps can omit it and use the default card
|
|
223
|
+
* centered on the tapped world point.
|
|
224
|
+
*/
|
|
225
|
+
type NativeLinkToolInsertOptions = {
|
|
226
|
+
readonly id?: string;
|
|
227
|
+
readonly bounds?: Rect;
|
|
228
|
+
};
|
|
229
|
+
/**
|
|
230
|
+
* Detail passed when the built-in native `"link"` tool receives a tap.
|
|
231
|
+
*
|
|
232
|
+
* This is the high-level native integration point: show an app-native URL
|
|
233
|
+
* dialog, then call {@link NativeLinkToolRequestDetail.insertLink} with the
|
|
234
|
+
* submitted link metadata. Use `onWorldPointerDown` only for fully custom tools
|
|
235
|
+
* or when you do not want canvu to insert the card.
|
|
236
|
+
*
|
|
237
|
+
* @example
|
|
238
|
+
* ```tsx
|
|
239
|
+
* <NativeVectorViewport
|
|
240
|
+
* toolId={toolId}
|
|
241
|
+
* onLinkToolRequest={(detail) => {
|
|
242
|
+
* openLinkDialog({
|
|
243
|
+
* onSubmit: (href) => detail.insertLink({ href }),
|
|
244
|
+
* });
|
|
245
|
+
* }}
|
|
246
|
+
* />
|
|
247
|
+
* ```
|
|
248
|
+
*/
|
|
249
|
+
type NativeLinkToolRequestDetail = {
|
|
250
|
+
readonly toolId: "link";
|
|
251
|
+
readonly worldX: number;
|
|
252
|
+
readonly worldY: number;
|
|
253
|
+
readonly screenX: number;
|
|
254
|
+
readonly screenY: number;
|
|
255
|
+
readonly suggestedBounds: Rect;
|
|
256
|
+
readonly insertLink: (link: CanvuLinkData, options?: NativeLinkToolInsertOptions) => VectorSceneItem | null;
|
|
257
|
+
};
|
|
216
258
|
type NativeVectorViewportProps = {
|
|
217
259
|
readonly items: readonly VectorSceneItem[];
|
|
218
260
|
readonly selectedIds?: readonly string[];
|
|
@@ -223,6 +265,14 @@ type NativeVectorViewportProps = {
|
|
|
223
265
|
readonly onSelectionChange?: (ids: string[]) => void;
|
|
224
266
|
readonly onItemsChange?: (items: VectorSceneItem[]) => void;
|
|
225
267
|
readonly onToolChangeRequest?: (toolId: string) => void;
|
|
268
|
+
/**
|
|
269
|
+
* Called after the built-in native `"link"` tool is tapped on the canvas.
|
|
270
|
+
*
|
|
271
|
+
* Use this to open your app's native modal or sheet for URL entry. Call
|
|
272
|
+
* `detail.insertLink(...)` after the user confirms to append and select the
|
|
273
|
+
* link card at the tapped world point.
|
|
274
|
+
*/
|
|
275
|
+
readonly onLinkToolRequest?: (detail: NativeLinkToolRequestDetail) => void;
|
|
226
276
|
readonly onWorldPointerDown?: (detail: NativeWorldPointerDownDetail) => void;
|
|
227
277
|
readonly onWorldPointerMove?: (world: {
|
|
228
278
|
readonly x: number;
|
|
@@ -369,4 +419,4 @@ type SvgNode = SvgRectNode | SvgEllipseNode | SvgCircleNode | SvgLineNode | SvgP
|
|
|
369
419
|
*/
|
|
370
420
|
declare function parseSvgFragment(xml: string): SvgNode[];
|
|
371
421
|
|
|
372
|
-
export { DEFAULT_NATIVE_OVERFLOW_TOOL_IDS, DEFAULT_NATIVE_VECTOR_TOOLS, NATIVE_STYLE_PALETTE, type NativeCustomShapePlacementOptions, NativeInteractionOverlay, type NativeInteractionOverlayProps, NativeSceneRenderer, type NativeSceneRendererProps, NativeShapeRenderer, type NativeShapeRendererProps, type NativeStyleColor, NativeVectorStyleInspector, type NativeVectorStyleInspectorProps, type NativeVectorStyleToolId, type NativeVectorToolDefinition, NativeVectorToolbar, type NativeVectorToolbarDensity, type NativeVectorToolbarProps, type NativeVectorToolbarRenderOverflowInput, type NativeVectorToolbarRenderToolInput, type NativeVectorToolbarRenderToolLockInput, NativeVectorViewport, type NativeVectorViewportHandle, type NativeVectorViewportProps, type NativeWorldPointerDownDetail, type PlacementPreview, type SvgNode, VectorSceneItem, nativeStyleColorWithOpacity, normalizeNativeStyleHex, parseSvgFragment };
|
|
422
|
+
export { CanvuLinkData, DEFAULT_NATIVE_OVERFLOW_TOOL_IDS, DEFAULT_NATIVE_VECTOR_TOOLS, NATIVE_STYLE_PALETTE, type NativeCustomShapePlacementOptions, NativeInteractionOverlay, type NativeInteractionOverlayProps, type NativeLinkToolInsertOptions, type NativeLinkToolRequestDetail, NativeSceneRenderer, type NativeSceneRendererProps, NativeShapeRenderer, type NativeShapeRendererProps, type NativeStyleColor, NativeVectorStyleInspector, type NativeVectorStyleInspectorProps, type NativeVectorStyleToolId, type NativeVectorToolDefinition, NativeVectorToolbar, type NativeVectorToolbarDensity, type NativeVectorToolbarProps, type NativeVectorToolbarRenderOverflowInput, type NativeVectorToolbarRenderToolInput, type NativeVectorToolbarRenderToolLockInput, NativeVectorViewport, type NativeVectorViewportHandle, type NativeVectorViewportProps, type NativeWorldPointerDownDetail, type PlacementPreview, type SvgNode, VectorSceneItem, nativeStyleColorWithOpacity, normalizeNativeStyleHex, parseSvgFragment };
|
package/dist/native.d.ts
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { C as CanvuLinkData } from './link-item-IW4GTnxl.js';
|
|
2
|
+
export { D as DEFAULT_LINK_CARD_SIZE, c as createLinkItem, g as getLinkData, i as isLinkItem } from './link-item-IW4GTnxl.js';
|
|
1
3
|
import { C as Camera2D, S as StrokeStyle } from './shape-builders-Cyh8zvDG.js';
|
|
2
4
|
export { o as createFreehandStrokeItem, q as createImageItem, t as createShapeId } from './shape-builders-Cyh8zvDG.js';
|
|
3
5
|
import { V as VectorSceneItem, R as Rect } from './types-BCCvY6ie.js';
|
|
@@ -162,7 +164,7 @@ type NativeVectorToolbarProps = {
|
|
|
162
164
|
readonly renderOverflowChevronIcon?: (input: NativeVectorToolbarRenderOverflowInput) => ReactNode;
|
|
163
165
|
readonly renderToolButton?: (input: NativeVectorToolbarRenderToolInput) => ReactNode;
|
|
164
166
|
};
|
|
165
|
-
declare const DEFAULT_NATIVE_OVERFLOW_TOOL_IDS: readonly ["rect", "ellipse", "architectural-cloud", "line", "marker", "laser", "image"];
|
|
167
|
+
declare const DEFAULT_NATIVE_OVERFLOW_TOOL_IDS: readonly ["rect", "ellipse", "architectural-cloud", "line", "marker", "laser", "image", "link"];
|
|
166
168
|
/**
|
|
167
169
|
* Default mobile-friendly tool list for {@link NativeVectorToolbar}.
|
|
168
170
|
*
|
|
@@ -213,6 +215,46 @@ type NativeWorldPointerDownDetail = {
|
|
|
213
215
|
readonly screenX: number;
|
|
214
216
|
readonly screenY: number;
|
|
215
217
|
};
|
|
218
|
+
/**
|
|
219
|
+
* Optional override for a link item inserted from the native link tool.
|
|
220
|
+
*
|
|
221
|
+
* Use this when your app has already reserved an item id or wants to place the
|
|
222
|
+
* link card at a custom box. Most apps can omit it and use the default card
|
|
223
|
+
* centered on the tapped world point.
|
|
224
|
+
*/
|
|
225
|
+
type NativeLinkToolInsertOptions = {
|
|
226
|
+
readonly id?: string;
|
|
227
|
+
readonly bounds?: Rect;
|
|
228
|
+
};
|
|
229
|
+
/**
|
|
230
|
+
* Detail passed when the built-in native `"link"` tool receives a tap.
|
|
231
|
+
*
|
|
232
|
+
* This is the high-level native integration point: show an app-native URL
|
|
233
|
+
* dialog, then call {@link NativeLinkToolRequestDetail.insertLink} with the
|
|
234
|
+
* submitted link metadata. Use `onWorldPointerDown` only for fully custom tools
|
|
235
|
+
* or when you do not want canvu to insert the card.
|
|
236
|
+
*
|
|
237
|
+
* @example
|
|
238
|
+
* ```tsx
|
|
239
|
+
* <NativeVectorViewport
|
|
240
|
+
* toolId={toolId}
|
|
241
|
+
* onLinkToolRequest={(detail) => {
|
|
242
|
+
* openLinkDialog({
|
|
243
|
+
* onSubmit: (href) => detail.insertLink({ href }),
|
|
244
|
+
* });
|
|
245
|
+
* }}
|
|
246
|
+
* />
|
|
247
|
+
* ```
|
|
248
|
+
*/
|
|
249
|
+
type NativeLinkToolRequestDetail = {
|
|
250
|
+
readonly toolId: "link";
|
|
251
|
+
readonly worldX: number;
|
|
252
|
+
readonly worldY: number;
|
|
253
|
+
readonly screenX: number;
|
|
254
|
+
readonly screenY: number;
|
|
255
|
+
readonly suggestedBounds: Rect;
|
|
256
|
+
readonly insertLink: (link: CanvuLinkData, options?: NativeLinkToolInsertOptions) => VectorSceneItem | null;
|
|
257
|
+
};
|
|
216
258
|
type NativeVectorViewportProps = {
|
|
217
259
|
readonly items: readonly VectorSceneItem[];
|
|
218
260
|
readonly selectedIds?: readonly string[];
|
|
@@ -223,6 +265,14 @@ type NativeVectorViewportProps = {
|
|
|
223
265
|
readonly onSelectionChange?: (ids: string[]) => void;
|
|
224
266
|
readonly onItemsChange?: (items: VectorSceneItem[]) => void;
|
|
225
267
|
readonly onToolChangeRequest?: (toolId: string) => void;
|
|
268
|
+
/**
|
|
269
|
+
* Called after the built-in native `"link"` tool is tapped on the canvas.
|
|
270
|
+
*
|
|
271
|
+
* Use this to open your app's native modal or sheet for URL entry. Call
|
|
272
|
+
* `detail.insertLink(...)` after the user confirms to append and select the
|
|
273
|
+
* link card at the tapped world point.
|
|
274
|
+
*/
|
|
275
|
+
readonly onLinkToolRequest?: (detail: NativeLinkToolRequestDetail) => void;
|
|
226
276
|
readonly onWorldPointerDown?: (detail: NativeWorldPointerDownDetail) => void;
|
|
227
277
|
readonly onWorldPointerMove?: (world: {
|
|
228
278
|
readonly x: number;
|
|
@@ -369,4 +419,4 @@ type SvgNode = SvgRectNode | SvgEllipseNode | SvgCircleNode | SvgLineNode | SvgP
|
|
|
369
419
|
*/
|
|
370
420
|
declare function parseSvgFragment(xml: string): SvgNode[];
|
|
371
421
|
|
|
372
|
-
export { DEFAULT_NATIVE_OVERFLOW_TOOL_IDS, DEFAULT_NATIVE_VECTOR_TOOLS, NATIVE_STYLE_PALETTE, type NativeCustomShapePlacementOptions, NativeInteractionOverlay, type NativeInteractionOverlayProps, NativeSceneRenderer, type NativeSceneRendererProps, NativeShapeRenderer, type NativeShapeRendererProps, type NativeStyleColor, NativeVectorStyleInspector, type NativeVectorStyleInspectorProps, type NativeVectorStyleToolId, type NativeVectorToolDefinition, NativeVectorToolbar, type NativeVectorToolbarDensity, type NativeVectorToolbarProps, type NativeVectorToolbarRenderOverflowInput, type NativeVectorToolbarRenderToolInput, type NativeVectorToolbarRenderToolLockInput, NativeVectorViewport, type NativeVectorViewportHandle, type NativeVectorViewportProps, type NativeWorldPointerDownDetail, type PlacementPreview, type SvgNode, VectorSceneItem, nativeStyleColorWithOpacity, normalizeNativeStyleHex, parseSvgFragment };
|
|
422
|
+
export { CanvuLinkData, DEFAULT_NATIVE_OVERFLOW_TOOL_IDS, DEFAULT_NATIVE_VECTOR_TOOLS, NATIVE_STYLE_PALETTE, type NativeCustomShapePlacementOptions, NativeInteractionOverlay, type NativeInteractionOverlayProps, type NativeLinkToolInsertOptions, type NativeLinkToolRequestDetail, NativeSceneRenderer, type NativeSceneRendererProps, NativeShapeRenderer, type NativeShapeRendererProps, type NativeStyleColor, NativeVectorStyleInspector, type NativeVectorStyleInspectorProps, type NativeVectorStyleToolId, type NativeVectorToolDefinition, NativeVectorToolbar, type NativeVectorToolbarDensity, type NativeVectorToolbarProps, type NativeVectorToolbarRenderOverflowInput, type NativeVectorToolbarRenderToolInput, type NativeVectorToolbarRenderToolLockInput, NativeVectorViewport, type NativeVectorViewportHandle, type NativeVectorViewportProps, type NativeWorldPointerDownDetail, type PlacementPreview, type SvgNode, VectorSceneItem, nativeStyleColorWithOpacity, normalizeNativeStyleHex, parseSvgFragment };
|
package/dist/native.js
CHANGED
|
@@ -1,11 +1,9 @@
|
|
|
1
1
|
import getStroke from 'perfect-freehand';
|
|
2
|
-
import { Group, Canvas, Rect, Circle, Path, RoundedRect, Oval, DashPathEffect, Line, vec, matchFont, Text,
|
|
2
|
+
import { Group, Canvas, Rect, Circle, Path, RoundedRect, Oval, DashPathEffect, Line, vec, matchFont, Text, Image } from '@shopify/react-native-skia';
|
|
3
3
|
import { memo, forwardRef, useState, useRef, useCallback, useEffect, useMemo, useImperativeHandle } from 'react';
|
|
4
4
|
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
5
5
|
import { StyleSheet, PanResponder, View, Pressable, Text as Text$1, ScrollView } from 'react-native';
|
|
6
6
|
|
|
7
|
-
// src/scene/shape-builders.ts
|
|
8
|
-
|
|
9
7
|
// src/math/rect.ts
|
|
10
8
|
function rectsIntersect(a, b) {
|
|
11
9
|
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;
|
|
@@ -22,12 +20,36 @@ function normalizeRect(r) {
|
|
|
22
20
|
}
|
|
23
21
|
|
|
24
22
|
// src/scene/custom-shape.ts
|
|
23
|
+
function expandCustomShapeTemplate(template, width, height) {
|
|
24
|
+
return template.replace(/\{\{w\}\}/g, String(width)).replace(/\{\{h\}\}/g, String(height)).replace(/\{\{width\}\}/g, String(width)).replace(/\{\{height\}\}/g, String(height));
|
|
25
|
+
}
|
|
26
|
+
function resolveCustomInner(content, size) {
|
|
27
|
+
if ("render" in content) {
|
|
28
|
+
return content.render(size);
|
|
29
|
+
}
|
|
30
|
+
return expandCustomShapeTemplate(content.svg, size.width, size.height);
|
|
31
|
+
}
|
|
25
32
|
function buildCustomShapeChildrenSvg(inner, intrinsic, bounds) {
|
|
26
33
|
const b = normalizeRect(bounds);
|
|
27
34
|
const sx = b.width / intrinsic.width;
|
|
28
35
|
const sy = b.height / intrinsic.height;
|
|
29
36
|
return `<g transform="scale(${sx},${sy})">${inner}</g>`;
|
|
30
37
|
}
|
|
38
|
+
function createCustomShapeItem(id, bounds, content) {
|
|
39
|
+
const r = normalizeRect(bounds);
|
|
40
|
+
const intrinsic = { width: r.width, height: r.height };
|
|
41
|
+
const inner = resolveCustomInner(content, intrinsic);
|
|
42
|
+
return {
|
|
43
|
+
id,
|
|
44
|
+
x: r.x,
|
|
45
|
+
y: r.y,
|
|
46
|
+
bounds: { ...r },
|
|
47
|
+
toolKind: "custom",
|
|
48
|
+
customIntrinsicSize: intrinsic,
|
|
49
|
+
customInnerSvg: inner,
|
|
50
|
+
childrenSvg: buildCustomShapeChildrenSvg(inner, intrinsic, r)
|
|
51
|
+
};
|
|
52
|
+
}
|
|
31
53
|
|
|
32
54
|
// src/scene/link-item.ts
|
|
33
55
|
var LINK_PLUGIN_KEY = "canvuLink";
|
|
@@ -140,6 +162,9 @@ function getLinkData(item) {
|
|
|
140
162
|
const entry = item.pluginData?.[LINK_PLUGIN_KEY];
|
|
141
163
|
return isCanvuLinkData(entry) ? entry : null;
|
|
142
164
|
}
|
|
165
|
+
function isLinkItem(item) {
|
|
166
|
+
return getLinkData(item) != null;
|
|
167
|
+
}
|
|
143
168
|
function rebuildLinkItemSvg(item) {
|
|
144
169
|
const link = getLinkData(item);
|
|
145
170
|
if (!link) return item;
|
|
@@ -173,6 +198,26 @@ function rebuildLinkItemSvg(item) {
|
|
|
173
198
|
childrenSvg: buildLinkCardSvg(width, height, link)
|
|
174
199
|
};
|
|
175
200
|
}
|
|
201
|
+
function createLinkItem(id, bounds, link) {
|
|
202
|
+
const width = bounds.width || DEFAULT_LINK_CARD_WIDTH;
|
|
203
|
+
const height = bounds.height || DEFAULT_LINK_CARD_HEIGHT;
|
|
204
|
+
const item = createCustomShapeItem(
|
|
205
|
+
id,
|
|
206
|
+
{ ...bounds, width, height },
|
|
207
|
+
{ render: (size) => buildLinkCardSvg(size.width, size.height, link) }
|
|
208
|
+
);
|
|
209
|
+
return rebuildLinkItemSvg({
|
|
210
|
+
...item,
|
|
211
|
+
pluginData: {
|
|
212
|
+
...item.pluginData ?? {},
|
|
213
|
+
[LINK_PLUGIN_KEY]: link
|
|
214
|
+
}
|
|
215
|
+
});
|
|
216
|
+
}
|
|
217
|
+
var DEFAULT_LINK_CARD_SIZE = {
|
|
218
|
+
width: DEFAULT_LINK_CARD_WIDTH,
|
|
219
|
+
height: DEFAULT_LINK_CARD_HEIGHT
|
|
220
|
+
};
|
|
176
221
|
|
|
177
222
|
// src/scene/text-svg.ts
|
|
178
223
|
function escapeSvgTextContent(s) {
|
|
@@ -1399,6 +1444,179 @@ function smoothFreehandPointsToPathD(points) {
|
|
|
1399
1444
|
return d;
|
|
1400
1445
|
}
|
|
1401
1446
|
|
|
1447
|
+
// src/native/native-link-card.ts
|
|
1448
|
+
function linkHostname(href) {
|
|
1449
|
+
try {
|
|
1450
|
+
return new URL(href).hostname.replace(/^www\./, "");
|
|
1451
|
+
} catch {
|
|
1452
|
+
return href;
|
|
1453
|
+
}
|
|
1454
|
+
}
|
|
1455
|
+
function linkProtocol(href) {
|
|
1456
|
+
try {
|
|
1457
|
+
return new URL(href).protocol;
|
|
1458
|
+
} catch {
|
|
1459
|
+
return "";
|
|
1460
|
+
}
|
|
1461
|
+
}
|
|
1462
|
+
function linkInitial(value) {
|
|
1463
|
+
const first = value.trim().charAt(0).toUpperCase();
|
|
1464
|
+
return first || "L";
|
|
1465
|
+
}
|
|
1466
|
+
function buildNativeLinkCardDisplay(link) {
|
|
1467
|
+
const hostname = linkHostname(link.href);
|
|
1468
|
+
const title = link.title?.trim() || hostname || "Link";
|
|
1469
|
+
return {
|
|
1470
|
+
title,
|
|
1471
|
+
subtitle: hostname || link.href,
|
|
1472
|
+
initial: linkInitial(hostname || title),
|
|
1473
|
+
secure: linkProtocol(link.href) === "https:"
|
|
1474
|
+
};
|
|
1475
|
+
}
|
|
1476
|
+
function createNativeLinkCardBoundsAtPoint(point) {
|
|
1477
|
+
return {
|
|
1478
|
+
x: point.x - DEFAULT_LINK_CARD_SIZE.width / 2,
|
|
1479
|
+
y: point.y - DEFAULT_LINK_CARD_SIZE.height / 2,
|
|
1480
|
+
width: DEFAULT_LINK_CARD_SIZE.width,
|
|
1481
|
+
height: DEFAULT_LINK_CARD_SIZE.height
|
|
1482
|
+
};
|
|
1483
|
+
}
|
|
1484
|
+
var DEFAULT_NATIVE_IMAGE_CACHE_MAX_ENTRIES = 96;
|
|
1485
|
+
function disposeCachedImage(image) {
|
|
1486
|
+
try {
|
|
1487
|
+
image.dispose?.();
|
|
1488
|
+
} catch {
|
|
1489
|
+
}
|
|
1490
|
+
}
|
|
1491
|
+
function createNativeImageCache({
|
|
1492
|
+
loadImage,
|
|
1493
|
+
maxEntries = DEFAULT_NATIVE_IMAGE_CACHE_MAX_ENTRIES
|
|
1494
|
+
}) {
|
|
1495
|
+
const safeMaxEntries = Math.max(1, Math.round(maxEntries));
|
|
1496
|
+
const entries = /* @__PURE__ */ new Map();
|
|
1497
|
+
let clock = 0;
|
|
1498
|
+
const touchEntry = (entry) => {
|
|
1499
|
+
clock += 1;
|
|
1500
|
+
entry.lastUsed = clock;
|
|
1501
|
+
};
|
|
1502
|
+
const createEntry = () => {
|
|
1503
|
+
clock += 1;
|
|
1504
|
+
return {
|
|
1505
|
+
lastUsed: clock,
|
|
1506
|
+
retainCount: 0
|
|
1507
|
+
};
|
|
1508
|
+
};
|
|
1509
|
+
const prune = () => {
|
|
1510
|
+
const cachedEntries = [...entries.entries()].filter(
|
|
1511
|
+
(entry) => entry[1].image != null && entry[1].retainCount === 0
|
|
1512
|
+
);
|
|
1513
|
+
if (cachedEntries.length <= safeMaxEntries) return;
|
|
1514
|
+
const evictedEntries = cachedEntries.sort(
|
|
1515
|
+
(leftEntry, rightEntry) => leftEntry[1].lastUsed - rightEntry[1].lastUsed
|
|
1516
|
+
).slice(0, cachedEntries.length - safeMaxEntries);
|
|
1517
|
+
for (const [href, entry] of evictedEntries) {
|
|
1518
|
+
entries.delete(href);
|
|
1519
|
+
disposeCachedImage(entry.image);
|
|
1520
|
+
}
|
|
1521
|
+
};
|
|
1522
|
+
const getCached = (href) => {
|
|
1523
|
+
const entry = entries.get(href);
|
|
1524
|
+
if (!entry?.image) return null;
|
|
1525
|
+
touchEntry(entry);
|
|
1526
|
+
return entry.image;
|
|
1527
|
+
};
|
|
1528
|
+
const load = async (href) => {
|
|
1529
|
+
const cachedImage = getCached(href);
|
|
1530
|
+
if (cachedImage) return cachedImage;
|
|
1531
|
+
const existingEntry = entries.get(href);
|
|
1532
|
+
if (existingEntry?.promise) return await existingEntry.promise;
|
|
1533
|
+
const entry = existingEntry ?? createEntry();
|
|
1534
|
+
const promise = loadImage(href).then((image) => {
|
|
1535
|
+
if (!image) {
|
|
1536
|
+
if (entry.retainCount === 0) entries.delete(href);
|
|
1537
|
+
return null;
|
|
1538
|
+
}
|
|
1539
|
+
entry.image = image;
|
|
1540
|
+
entry.promise = void 0;
|
|
1541
|
+
touchEntry(entry);
|
|
1542
|
+
prune();
|
|
1543
|
+
return image;
|
|
1544
|
+
}).catch((error) => {
|
|
1545
|
+
entries.delete(href);
|
|
1546
|
+
throw error;
|
|
1547
|
+
});
|
|
1548
|
+
entry.promise = promise;
|
|
1549
|
+
entries.set(href, entry);
|
|
1550
|
+
return await promise;
|
|
1551
|
+
};
|
|
1552
|
+
const retain = (href) => {
|
|
1553
|
+
const entry = entries.get(href) ?? createEntry();
|
|
1554
|
+
entry.retainCount += 1;
|
|
1555
|
+
touchEntry(entry);
|
|
1556
|
+
entries.set(href, entry);
|
|
1557
|
+
let released = false;
|
|
1558
|
+
return () => {
|
|
1559
|
+
if (released) return;
|
|
1560
|
+
released = true;
|
|
1561
|
+
entry.retainCount = Math.max(0, entry.retainCount - 1);
|
|
1562
|
+
if (!entry.image && !entry.promise && entry.retainCount === 0) {
|
|
1563
|
+
entries.delete(href);
|
|
1564
|
+
return;
|
|
1565
|
+
}
|
|
1566
|
+
prune();
|
|
1567
|
+
};
|
|
1568
|
+
};
|
|
1569
|
+
const clear = () => {
|
|
1570
|
+
for (const entry of entries.values()) {
|
|
1571
|
+
if (entry.image) disposeCachedImage(entry.image);
|
|
1572
|
+
}
|
|
1573
|
+
entries.clear();
|
|
1574
|
+
};
|
|
1575
|
+
const size = () => [...entries.values()].filter((entry) => entry.image != null).length;
|
|
1576
|
+
return { getCached, load, retain, clear, size };
|
|
1577
|
+
}
|
|
1578
|
+
async function loadSkiaImageFromHref(href) {
|
|
1579
|
+
const { Skia } = await import('@shopify/react-native-skia');
|
|
1580
|
+
const data = await Skia.Data.fromURI(href);
|
|
1581
|
+
return Skia.Image.MakeImageFromEncoded(data);
|
|
1582
|
+
}
|
|
1583
|
+
var nativeSkiaImageCache = createNativeImageCache({
|
|
1584
|
+
loadImage: loadSkiaImageFromHref
|
|
1585
|
+
});
|
|
1586
|
+
function useCachedSkiaImage(href) {
|
|
1587
|
+
const [loadedImage, setLoadedImage] = useState(
|
|
1588
|
+
() => href ? { href, image: nativeSkiaImageCache.getCached(href) } : null
|
|
1589
|
+
);
|
|
1590
|
+
useEffect(() => {
|
|
1591
|
+
if (!href) {
|
|
1592
|
+
setLoadedImage(null);
|
|
1593
|
+
return;
|
|
1594
|
+
}
|
|
1595
|
+
const releaseImage = nativeSkiaImageCache.retain(href);
|
|
1596
|
+
const cachedImage = nativeSkiaImageCache.getCached(href);
|
|
1597
|
+
if (cachedImage) {
|
|
1598
|
+
setLoadedImage({ href, image: cachedImage });
|
|
1599
|
+
return releaseImage;
|
|
1600
|
+
}
|
|
1601
|
+
let active = true;
|
|
1602
|
+
setLoadedImage({ href, image: null });
|
|
1603
|
+
void nativeSkiaImageCache.load(href).then(
|
|
1604
|
+
(loadedImage2) => {
|
|
1605
|
+
if (active) setLoadedImage({ href, image: loadedImage2 });
|
|
1606
|
+
},
|
|
1607
|
+
() => {
|
|
1608
|
+
if (active) setLoadedImage({ href, image: null });
|
|
1609
|
+
}
|
|
1610
|
+
);
|
|
1611
|
+
return () => {
|
|
1612
|
+
active = false;
|
|
1613
|
+
releaseImage();
|
|
1614
|
+
};
|
|
1615
|
+
}, [href]);
|
|
1616
|
+
if (!href || loadedImage?.href !== href) return null;
|
|
1617
|
+
return loadedImage.image;
|
|
1618
|
+
}
|
|
1619
|
+
|
|
1402
1620
|
// src/native/skia-transform.ts
|
|
1403
1621
|
function parseNum(s) {
|
|
1404
1622
|
return Number(s);
|
|
@@ -1662,7 +1880,7 @@ function SvgNodeItem({ node }) {
|
|
|
1662
1880
|
function SvgImageNodeItem({
|
|
1663
1881
|
node
|
|
1664
1882
|
}) {
|
|
1665
|
-
const image =
|
|
1883
|
+
const image = useCachedSkiaImage(node.href);
|
|
1666
1884
|
if (!image) return null;
|
|
1667
1885
|
return /* @__PURE__ */ jsx(
|
|
1668
1886
|
Image,
|
|
@@ -1952,7 +2170,119 @@ function localBounds(bounds) {
|
|
|
1952
2170
|
const b = normalizeRect(bounds);
|
|
1953
2171
|
return { w: Math.max(0, b.width), h: Math.max(0, b.height) };
|
|
1954
2172
|
}
|
|
2173
|
+
function truncateText(value, maxChars) {
|
|
2174
|
+
if (value.length <= maxChars) return value;
|
|
2175
|
+
return `${value.slice(0, Math.max(0, maxChars - 3)).trimEnd()}...`;
|
|
2176
|
+
}
|
|
2177
|
+
function NativeLinkCardRenderer({
|
|
2178
|
+
item,
|
|
2179
|
+
link
|
|
2180
|
+
}) {
|
|
2181
|
+
const bounds = normalizeRect(item.bounds);
|
|
2182
|
+
const scaleX = Math.max(0.01, bounds.width / DEFAULT_LINK_CARD_SIZE.width);
|
|
2183
|
+
const scaleY = Math.max(0.01, bounds.height / DEFAULT_LINK_CARD_SIZE.height);
|
|
2184
|
+
const display = buildNativeLinkCardDisplay(link);
|
|
2185
|
+
const titleFont = matchFont({ fontSize: 14.5, fontWeight: "700" });
|
|
2186
|
+
const subtitleFont = matchFont({ fontSize: 12.5 });
|
|
2187
|
+
const initialFont = matchFont({ fontSize: 17, fontWeight: "700" });
|
|
2188
|
+
const title = truncateText(display.title, 28);
|
|
2189
|
+
const subtitle = truncateText(display.subtitle, display.secure ? 28 : 31);
|
|
2190
|
+
const subtitleX = display.secure ? 82 : 69;
|
|
2191
|
+
const subtitleWidth = display.secure ? 188 : 201;
|
|
2192
|
+
return /* @__PURE__ */ jsxs(Group, { transform: [{ scaleX }, { scaleY }], children: [
|
|
2193
|
+
/* @__PURE__ */ jsx(
|
|
2194
|
+
RoundedRect,
|
|
2195
|
+
{
|
|
2196
|
+
x: 0,
|
|
2197
|
+
y: 0,
|
|
2198
|
+
width: DEFAULT_LINK_CARD_SIZE.width,
|
|
2199
|
+
height: DEFAULT_LINK_CARD_SIZE.height,
|
|
2200
|
+
r: 16,
|
|
2201
|
+
color: "#ffffff",
|
|
2202
|
+
style: "fill",
|
|
2203
|
+
antiAlias: true
|
|
2204
|
+
}
|
|
2205
|
+
),
|
|
2206
|
+
/* @__PURE__ */ jsx(
|
|
2207
|
+
RoundedRect,
|
|
2208
|
+
{
|
|
2209
|
+
x: 0.5,
|
|
2210
|
+
y: 0.5,
|
|
2211
|
+
width: DEFAULT_LINK_CARD_SIZE.width - 1,
|
|
2212
|
+
height: DEFAULT_LINK_CARD_SIZE.height - 1,
|
|
2213
|
+
r: 15.5,
|
|
2214
|
+
color: "#dfe4ea",
|
|
2215
|
+
style: "stroke",
|
|
2216
|
+
strokeWidth: 1,
|
|
2217
|
+
antiAlias: true
|
|
2218
|
+
}
|
|
2219
|
+
),
|
|
2220
|
+
/* @__PURE__ */ jsx(
|
|
2221
|
+
RoundedRect,
|
|
2222
|
+
{
|
|
2223
|
+
x: 14,
|
|
2224
|
+
y: 14,
|
|
2225
|
+
width: 42,
|
|
2226
|
+
height: 42,
|
|
2227
|
+
r: 11,
|
|
2228
|
+
color: "#315bd6",
|
|
2229
|
+
style: "fill",
|
|
2230
|
+
antiAlias: true
|
|
2231
|
+
}
|
|
2232
|
+
),
|
|
2233
|
+
/* @__PURE__ */ jsx(
|
|
2234
|
+
Text,
|
|
2235
|
+
{
|
|
2236
|
+
x: 29.5,
|
|
2237
|
+
y: 41,
|
|
2238
|
+
text: display.initial,
|
|
2239
|
+
color: "#ffffff",
|
|
2240
|
+
font: initialFont
|
|
2241
|
+
}
|
|
2242
|
+
),
|
|
2243
|
+
/* @__PURE__ */ jsx(Group, { clip: { x: 69, y: 13, width: 215, height: 24 }, children: /* @__PURE__ */ jsx(Text, { x: 69, y: 32, text: title, color: "#1f2937", font: titleFont }) }),
|
|
2244
|
+
display.secure ? /* @__PURE__ */ jsxs(Group, { transform: [{ translateX: 69 }, { translateY: 41 }], children: [
|
|
2245
|
+
/* @__PURE__ */ jsx(
|
|
2246
|
+
Rect,
|
|
2247
|
+
{
|
|
2248
|
+
x: 1.5,
|
|
2249
|
+
y: 4.5,
|
|
2250
|
+
width: 7,
|
|
2251
|
+
height: 6,
|
|
2252
|
+
color: "#6b7280",
|
|
2253
|
+
style: "stroke",
|
|
2254
|
+
strokeWidth: 1.3
|
|
2255
|
+
}
|
|
2256
|
+
),
|
|
2257
|
+
/* @__PURE__ */ jsx(
|
|
2258
|
+
Path,
|
|
2259
|
+
{
|
|
2260
|
+
path: "M3 4.5 V3 a2 2 0 0 1 4 0 v1.5",
|
|
2261
|
+
color: "#6b7280",
|
|
2262
|
+
style: "stroke",
|
|
2263
|
+
strokeWidth: 1.3,
|
|
2264
|
+
strokeCap: "round",
|
|
2265
|
+
strokeJoin: "round"
|
|
2266
|
+
}
|
|
2267
|
+
)
|
|
2268
|
+
] }) : null,
|
|
2269
|
+
/* @__PURE__ */ jsx(Group, { clip: { x: subtitleX, y: 34, width: subtitleWidth, height: 22 }, children: /* @__PURE__ */ jsx(
|
|
2270
|
+
Text,
|
|
2271
|
+
{
|
|
2272
|
+
x: subtitleX,
|
|
2273
|
+
y: 51,
|
|
2274
|
+
text: subtitle,
|
|
2275
|
+
color: "#6b7280",
|
|
2276
|
+
font: subtitleFont
|
|
2277
|
+
}
|
|
2278
|
+
) })
|
|
2279
|
+
] });
|
|
2280
|
+
}
|
|
1955
2281
|
function NativeShapeRenderer({ item }) {
|
|
2282
|
+
const link = getLinkData(item);
|
|
2283
|
+
if (link) {
|
|
2284
|
+
return /* @__PURE__ */ jsx(NativeLinkCardRenderer, { item, link });
|
|
2285
|
+
}
|
|
1956
2286
|
const style = resolveStrokeStyle(item);
|
|
1957
2287
|
const k = item.toolKind;
|
|
1958
2288
|
if (k === "rect") {
|
|
@@ -3375,9 +3705,14 @@ var DEFAULT_NATIVE_OVERFLOW_TOOL_IDS = [
|
|
|
3375
3705
|
"line",
|
|
3376
3706
|
"marker",
|
|
3377
3707
|
"laser",
|
|
3378
|
-
"image"
|
|
3708
|
+
"image",
|
|
3709
|
+
"link"
|
|
3379
3710
|
];
|
|
3380
3711
|
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";
|
|
3712
|
+
var LINK_TOOL_ICON_PATHS = [
|
|
3713
|
+
"M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71",
|
|
3714
|
+
"M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"
|
|
3715
|
+
];
|
|
3381
3716
|
function NativeCloudToolIcon({
|
|
3382
3717
|
color,
|
|
3383
3718
|
size = 19,
|
|
@@ -3396,6 +3731,25 @@ function NativeCloudToolIcon({
|
|
|
3396
3731
|
}
|
|
3397
3732
|
) }) });
|
|
3398
3733
|
}
|
|
3734
|
+
function NativeLinkToolIcon({
|
|
3735
|
+
color,
|
|
3736
|
+
size = 20,
|
|
3737
|
+
strokeWidth = 2.4
|
|
3738
|
+
}) {
|
|
3739
|
+
const scale = size / 24;
|
|
3740
|
+
return /* @__PURE__ */ jsx(Canvas, { style: { width: size, height: size }, children: /* @__PURE__ */ jsx(Group, { transform: [{ scale }], children: LINK_TOOL_ICON_PATHS.map((path) => /* @__PURE__ */ jsx(
|
|
3741
|
+
Path,
|
|
3742
|
+
{
|
|
3743
|
+
path,
|
|
3744
|
+
color,
|
|
3745
|
+
style: "stroke",
|
|
3746
|
+
strokeWidth,
|
|
3747
|
+
strokeCap: "round",
|
|
3748
|
+
strokeJoin: "round"
|
|
3749
|
+
},
|
|
3750
|
+
path
|
|
3751
|
+
)) }) });
|
|
3752
|
+
}
|
|
3399
3753
|
var DEFAULT_NATIVE_VECTOR_TOOLS = [
|
|
3400
3754
|
{ id: "hand", label: "Hand", shortcutHint: "H", shortLabel: "H" },
|
|
3401
3755
|
{ id: "select", label: "Select", shortcutHint: "V", shortLabel: "V" },
|
|
@@ -3433,7 +3787,8 @@ var DEFAULT_NATIVE_VECTOR_TOOLS = [
|
|
|
3433
3787
|
shortLabel: "E"
|
|
3434
3788
|
},
|
|
3435
3789
|
{ id: "text", label: "Text", shortcutHint: "T", shortLabel: "T" },
|
|
3436
|
-
{ id: "image", label: "File", shortcutHint: "I", shortLabel: "I" }
|
|
3790
|
+
{ id: "image", label: "File", shortcutHint: "I", shortLabel: "I" },
|
|
3791
|
+
{ id: "link", label: "Link", shortcutHint: "N", shortLabel: "L" }
|
|
3437
3792
|
];
|
|
3438
3793
|
function splitToolbarTools(tools, overflowToolIds) {
|
|
3439
3794
|
const overflowIds = new Set(overflowToolIds);
|
|
@@ -3695,6 +4050,9 @@ function renderNativeToolFallback(tool, foregroundColor, toolLabelStyle) {
|
|
|
3695
4050
|
if (tool.id === "architectural-cloud") {
|
|
3696
4051
|
return /* @__PURE__ */ jsx(NativeCloudToolIcon, { color: foregroundColor });
|
|
3697
4052
|
}
|
|
4053
|
+
if (tool.id === "link") {
|
|
4054
|
+
return /* @__PURE__ */ jsx(NativeLinkToolIcon, { color: foregroundColor });
|
|
4055
|
+
}
|
|
3698
4056
|
return /* @__PURE__ */ jsx(Text$1, { style: [styles2.shortLabel, { color: foregroundColor }, toolLabelStyle], children: tool.shortLabel ?? tool.label.slice(0, 1).toUpperCase() });
|
|
3699
4057
|
}
|
|
3700
4058
|
var styles2 = StyleSheet.create({
|
|
@@ -4375,6 +4733,7 @@ var NativeVectorViewport = forwardRef(function NativeVectorViewport2({
|
|
|
4375
4733
|
onSelectionChange,
|
|
4376
4734
|
onItemsChange,
|
|
4377
4735
|
onToolChangeRequest,
|
|
4736
|
+
onLinkToolRequest,
|
|
4378
4737
|
onWorldPointerDown,
|
|
4379
4738
|
onWorldPointerMove,
|
|
4380
4739
|
onWorldPointerLeave,
|
|
@@ -4394,6 +4753,8 @@ var NativeVectorViewport = forwardRef(function NativeVectorViewport2({
|
|
|
4394
4753
|
toolLockedRef.current = toolLocked;
|
|
4395
4754
|
const onToolChangeRequestRef = useRef(onToolChangeRequest);
|
|
4396
4755
|
onToolChangeRequestRef.current = onToolChangeRequest;
|
|
4756
|
+
const onLinkToolRequestRef = useRef(onLinkToolRequest);
|
|
4757
|
+
onLinkToolRequestRef.current = onLinkToolRequest;
|
|
4397
4758
|
const onWorldPointerDownRef = useRef(onWorldPointerDown);
|
|
4398
4759
|
onWorldPointerDownRef.current = onWorldPointerDown;
|
|
4399
4760
|
const onWorldPointerMoveRef = useRef(onWorldPointerMove);
|
|
@@ -4736,7 +5097,7 @@ var NativeVectorViewport = forwardRef(function NativeVectorViewport2({
|
|
|
4736
5097
|
});
|
|
4737
5098
|
return;
|
|
4738
5099
|
}
|
|
4739
|
-
if (tool === "note" || tool === "text") {
|
|
5100
|
+
if (tool === "link" || tool === "note" || tool === "text") {
|
|
4740
5101
|
dragStateRef.current = {
|
|
4741
5102
|
kind: "tap",
|
|
4742
5103
|
tool,
|
|
@@ -5072,6 +5433,44 @@ var NativeVectorViewport = forwardRef(function NativeVectorViewport2({
|
|
|
5072
5433
|
const screenDy = point.y - st.startScreen.y;
|
|
5073
5434
|
if (Math.hypot(screenDx, screenDy) > TAP_PX) return;
|
|
5074
5435
|
const change = onItemsChangeRef.current;
|
|
5436
|
+
if (st.tool === "link") {
|
|
5437
|
+
const suggestedBounds = createNativeLinkCardBoundsAtPoint(st.startWorld);
|
|
5438
|
+
const insertLink = (link, options = {}) => {
|
|
5439
|
+
const currentChange = onItemsChangeRef.current;
|
|
5440
|
+
if (!currentChange) return null;
|
|
5441
|
+
const id = options.id ?? createShapeId();
|
|
5442
|
+
const item = createLinkItem(id, options.bounds ?? suggestedBounds, link);
|
|
5443
|
+
currentChange([...itemsRef.current, item]);
|
|
5444
|
+
onSelectionChangeRef.current?.([id]);
|
|
5445
|
+
requestSelectToolAfterUse();
|
|
5446
|
+
return item;
|
|
5447
|
+
};
|
|
5448
|
+
const requestLink = onLinkToolRequestRef.current;
|
|
5449
|
+
if (requestLink) {
|
|
5450
|
+
requestLink({
|
|
5451
|
+
toolId: "link",
|
|
5452
|
+
worldX: st.startWorld.x,
|
|
5453
|
+
worldY: st.startWorld.y,
|
|
5454
|
+
screenX: st.startScreen.x,
|
|
5455
|
+
screenY: st.startScreen.y,
|
|
5456
|
+
suggestedBounds,
|
|
5457
|
+
insertLink
|
|
5458
|
+
});
|
|
5459
|
+
return;
|
|
5460
|
+
}
|
|
5461
|
+
const handleWorldPointerDown = onWorldPointerDownRef.current;
|
|
5462
|
+
if (handleWorldPointerDown) {
|
|
5463
|
+
handleWorldPointerDown({
|
|
5464
|
+
toolId: "link",
|
|
5465
|
+
worldX: st.startWorld.x,
|
|
5466
|
+
worldY: st.startWorld.y,
|
|
5467
|
+
screenX: st.startScreen.x,
|
|
5468
|
+
screenY: st.startScreen.y
|
|
5469
|
+
});
|
|
5470
|
+
requestSelectToolAfterUse();
|
|
5471
|
+
}
|
|
5472
|
+
return;
|
|
5473
|
+
}
|
|
5075
5474
|
if (!change) return;
|
|
5076
5475
|
if (st.tool === "text") {
|
|
5077
5476
|
const id = createShapeId();
|
|
@@ -5339,6 +5738,6 @@ var NativeVectorViewport = forwardRef(function NativeVectorViewport2({
|
|
|
5339
5738
|
);
|
|
5340
5739
|
});
|
|
5341
5740
|
|
|
5342
|
-
export { DEFAULT_NATIVE_OVERFLOW_TOOL_IDS, DEFAULT_NATIVE_VECTOR_TOOLS, NATIVE_STYLE_PALETTE, NativeInteractionOverlay, NativeSceneRenderer, NativeShapeRenderer, NativeVectorStyleInspector, NativeVectorToolbar, NativeVectorViewport, createFreehandStrokeItem, createImageItem, createShapeId, nativeStyleColorWithOpacity, normalizeNativeStyleHex, parseSvgFragment };
|
|
5741
|
+
export { DEFAULT_LINK_CARD_SIZE, DEFAULT_NATIVE_OVERFLOW_TOOL_IDS, DEFAULT_NATIVE_VECTOR_TOOLS, NATIVE_STYLE_PALETTE, NativeInteractionOverlay, NativeSceneRenderer, NativeShapeRenderer, NativeVectorStyleInspector, NativeVectorToolbar, NativeVectorViewport, createFreehandStrokeItem, createImageItem, createLinkItem, createShapeId, getLinkData, isLinkItem, nativeStyleColorWithOpacity, normalizeNativeStyleHex, parseSvgFragment };
|
|
5343
5742
|
//# sourceMappingURL=native.js.map
|
|
5344
5743
|
//# sourceMappingURL=native.js.map
|