canvu-react 0.4.41 → 0.4.43

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/native.cjs CHANGED
@@ -3,8 +3,8 @@
3
3
  var getStroke = require('perfect-freehand');
4
4
  var reactNativeSkia = require('@shopify/react-native-skia');
5
5
  var react = require('react');
6
- var jsxRuntime = require('react/jsx-runtime');
7
6
  var reactNative = require('react-native');
7
+ var jsxRuntime = require('react/jsx-runtime');
8
8
 
9
9
  function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
10
10
 
@@ -1175,6 +1175,422 @@ function boundsAabbForRotatedItem(item) {
1175
1175
  return { x: minX, y: minY, width: maxX - minX, height: maxY - minY };
1176
1176
  }
1177
1177
 
1178
+ // src/scene/clone-item.ts
1179
+ function cloneVectorSceneItemWithNewId(item) {
1180
+ const id = createShapeId();
1181
+ const copy = JSON.parse(JSON.stringify(item));
1182
+ let next = { ...copy, id };
1183
+ if (next.toolKind === "arrow" && next.line) {
1184
+ next = {
1185
+ ...next,
1186
+ childrenSvg: buildArrowSvg(id, next.line, resolveStrokeStyle(next))
1187
+ };
1188
+ }
1189
+ if (next.toolKind === "text" && next.text !== void 0) {
1190
+ return rebuildItemSvg(next);
1191
+ }
1192
+ if (next.toolKind === "custom" && next.customInnerSvg && next.customIntrinsicSize) {
1193
+ return rebuildItemSvg(next);
1194
+ }
1195
+ return next;
1196
+ }
1197
+
1198
+ // src/scene/managed-images.ts
1199
+ var MANAGED_KEY = "managed";
1200
+ var STACK_GAP_WORLD = 16;
1201
+ function isManagedImage(item) {
1202
+ const data = item.pluginData;
1203
+ return data != null && data[MANAGED_KEY] === true;
1204
+ }
1205
+ function markImageAsManaged(item) {
1206
+ return {
1207
+ ...item,
1208
+ locked: true,
1209
+ pluginData: { ...item.pluginData ?? {}, [MANAGED_KEY]: true }
1210
+ };
1211
+ }
1212
+ function restackManagedImages(items) {
1213
+ let anchorAabbY = Infinity;
1214
+ let anchorCenterX = 0;
1215
+ for (const item of items) {
1216
+ if (!isManagedImage(item)) continue;
1217
+ const aabb = boundsAabbForRotatedItem(item);
1218
+ if (aabb.y < anchorAabbY) {
1219
+ anchorAabbY = aabb.y;
1220
+ anchorCenterX = aabb.x + aabb.width / 2;
1221
+ }
1222
+ }
1223
+ if (!Number.isFinite(anchorAabbY)) return [...items];
1224
+ let cursorY = anchorAabbY;
1225
+ return items.map((item) => {
1226
+ if (!isManagedImage(item)) return item;
1227
+ const aabb = boundsAabbForRotatedItem(item);
1228
+ const centerY = cursorY + aabb.height / 2;
1229
+ const newX = anchorCenterX - item.bounds.width / 2;
1230
+ const newY = centerY - item.bounds.height / 2;
1231
+ cursorY += aabb.height + STACK_GAP_WORLD;
1232
+ if (item.bounds.x === newX && item.bounds.y === newY) return item;
1233
+ return {
1234
+ ...item,
1235
+ x: newX,
1236
+ y: newY,
1237
+ bounds: { ...item.bounds, x: newX, y: newY }
1238
+ };
1239
+ });
1240
+ }
1241
+ function copyManagedImage(items, id) {
1242
+ const idx = items.findIndex((i) => i.id === id);
1243
+ if (idx < 0) return [...items];
1244
+ const source = items[idx];
1245
+ if (!source) return [...items];
1246
+ const clone = markImageAsManaged(cloneVectorSceneItemWithNewId(source));
1247
+ const inserted = [...items.slice(0, idx + 1), clone, ...items.slice(idx + 1)];
1248
+ return restackManagedImages(inserted);
1249
+ }
1250
+ function rotateManagedImage(items, id) {
1251
+ return restackManagedImages(
1252
+ items.map(
1253
+ (i) => i.id === id ? { ...i, rotation: ((i.rotation ?? 0) + Math.PI / 2) % (Math.PI * 2) } : i
1254
+ )
1255
+ );
1256
+ }
1257
+ function deleteManagedImage(items, id) {
1258
+ return restackManagedImages(items.filter((i) => i.id !== id));
1259
+ }
1260
+ var defaultLabels = {
1261
+ title: "Images",
1262
+ focus: "Focus on canvas",
1263
+ duplicate: "Duplicate",
1264
+ rotate: "Rotate",
1265
+ delete: "Delete",
1266
+ collapse: "Collapse images menu",
1267
+ expand: "Open images menu"
1268
+ };
1269
+ var iconPaths = {
1270
+ images: ["M4 5h16v14H4z", "M4 15l4-4 3 3 5-6 4 5"],
1271
+ chevronRight: ["M9 18l6-6-6-6"],
1272
+ copy: ["M8 8h10v10H8z", "M6 16H4V4h12v2", "M13 11v4", "M11 13h4"],
1273
+ rotate: ["M21 12a9 9 0 1 1-2.64-6.36", "M21 3v6h-6"],
1274
+ trash: ["M3 6h18", "M8 6V4h8v2", "M6 6l1 15h10l1-15", "M10 11v6", "M14 11v6"],
1275
+ grip: ["M8 7h8", "M8 12h8", "M8 17h8"]
1276
+ };
1277
+ function NativeImagesMenuIcon({
1278
+ name,
1279
+ color = "#0f172a",
1280
+ size = 18
1281
+ }) {
1282
+ const scale = size / 24;
1283
+ return /* @__PURE__ */ jsxRuntime.jsx(reactNativeSkia.Canvas, { style: { width: size, height: size }, children: /* @__PURE__ */ jsxRuntime.jsx(reactNativeSkia.Group, { transform: [{ scale }], children: iconPaths[name].map((path) => /* @__PURE__ */ jsxRuntime.jsx(
1284
+ reactNativeSkia.Path,
1285
+ {
1286
+ path,
1287
+ color,
1288
+ style: "stroke",
1289
+ strokeWidth: 2,
1290
+ strokeCap: "round",
1291
+ strokeJoin: "round"
1292
+ },
1293
+ path
1294
+ )) }) });
1295
+ }
1296
+ function resolveLabels(labels) {
1297
+ return {
1298
+ ...defaultLabels,
1299
+ ...labels,
1300
+ duplicate: labels?.duplicate ?? labels?.copy ?? defaultLabels.duplicate
1301
+ };
1302
+ }
1303
+ function getDefaultImageUri(item) {
1304
+ return item.imageThumbnailHref ?? item.imageRasterHref ?? null;
1305
+ }
1306
+ function NativeImagesMenuAction({
1307
+ label,
1308
+ danger = false,
1309
+ children,
1310
+ onPress,
1311
+ style
1312
+ }) {
1313
+ return /* @__PURE__ */ jsxRuntime.jsx(
1314
+ reactNative.Pressable,
1315
+ {
1316
+ accessibilityRole: "button",
1317
+ accessibilityLabel: label,
1318
+ onPress,
1319
+ style: ({ pressed }) => [
1320
+ styles.actionButton,
1321
+ pressed && styles.actionButtonPressed,
1322
+ danger && styles.dangerActionButton,
1323
+ style
1324
+ ],
1325
+ children
1326
+ }
1327
+ );
1328
+ }
1329
+ function NativeImagesMenuRow({
1330
+ item,
1331
+ items,
1332
+ labels,
1333
+ onItemsChange,
1334
+ onFocusItem,
1335
+ getImageUri,
1336
+ renderThumbnail,
1337
+ rowStyle,
1338
+ actionButtonStyle
1339
+ }) {
1340
+ const imageUri = getImageUri(item);
1341
+ return /* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style: [styles.row, rowStyle], children: [
1342
+ /* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { style: styles.handle, children: /* @__PURE__ */ jsxRuntime.jsx(NativeImagesMenuIcon, { name: "grip", color: "#94a3b8" }) }),
1343
+ /* @__PURE__ */ jsxRuntime.jsx(
1344
+ reactNative.Pressable,
1345
+ {
1346
+ accessibilityRole: "button",
1347
+ accessibilityLabel: labels.focus,
1348
+ disabled: !onFocusItem,
1349
+ onPress: () => onFocusItem?.(item),
1350
+ style: styles.thumbnailButton,
1351
+ children: /* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style: styles.thumbnailBox, children: [
1352
+ renderThumbnail ? renderThumbnail(item) : null,
1353
+ !renderThumbnail && imageUri ? /* @__PURE__ */ jsxRuntime.jsx(reactNative.Image, { source: { uri: imageUri }, style: styles.thumbnailImage }) : null
1354
+ ] })
1355
+ }
1356
+ ),
1357
+ /* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style: styles.actionsColumn, children: [
1358
+ /* @__PURE__ */ jsxRuntime.jsx(
1359
+ NativeImagesMenuAction,
1360
+ {
1361
+ label: labels.duplicate,
1362
+ onPress: () => onItemsChange(copyManagedImage(items, item.id)),
1363
+ style: actionButtonStyle,
1364
+ children: /* @__PURE__ */ jsxRuntime.jsx(NativeImagesMenuIcon, { name: "copy" })
1365
+ }
1366
+ ),
1367
+ /* @__PURE__ */ jsxRuntime.jsx(
1368
+ NativeImagesMenuAction,
1369
+ {
1370
+ label: labels.rotate,
1371
+ onPress: () => onItemsChange(rotateManagedImage(items, item.id)),
1372
+ style: actionButtonStyle,
1373
+ children: /* @__PURE__ */ jsxRuntime.jsx(NativeImagesMenuIcon, { name: "rotate" })
1374
+ }
1375
+ ),
1376
+ /* @__PURE__ */ jsxRuntime.jsx(
1377
+ NativeImagesMenuAction,
1378
+ {
1379
+ label: labels.delete,
1380
+ danger: true,
1381
+ onPress: () => onItemsChange(deleteManagedImage(items, item.id)),
1382
+ style: actionButtonStyle,
1383
+ children: /* @__PURE__ */ jsxRuntime.jsx(NativeImagesMenuIcon, { name: "trash", color: "#b91c1c" })
1384
+ }
1385
+ )
1386
+ ] })
1387
+ ] });
1388
+ }
1389
+ function NativeImagesMenu({
1390
+ items,
1391
+ onItemsChange,
1392
+ onFocusItem,
1393
+ labels,
1394
+ defaultOpen = false,
1395
+ style,
1396
+ panelStyle,
1397
+ collapsedButtonStyle,
1398
+ rowStyle,
1399
+ actionButtonStyle,
1400
+ getImageUri = getDefaultImageUri,
1401
+ renderThumbnail
1402
+ }) {
1403
+ const managed = react.useMemo(() => items.filter(isManagedImage), [items]);
1404
+ const [collapsed, setCollapsed] = react.useState(!defaultOpen);
1405
+ if (managed.length === 0) return null;
1406
+ const resolvedLabels = resolveLabels(labels);
1407
+ if (collapsed) {
1408
+ return /* @__PURE__ */ jsxRuntime.jsx(
1409
+ reactNative.Pressable,
1410
+ {
1411
+ accessibilityRole: "button",
1412
+ accessibilityLabel: resolvedLabels.expand,
1413
+ onPress: () => setCollapsed(false),
1414
+ style: ({ pressed }) => [
1415
+ styles.collapsedButton,
1416
+ pressed && styles.collapsedButtonPressed,
1417
+ collapsedButtonStyle,
1418
+ style
1419
+ ],
1420
+ children: /* @__PURE__ */ jsxRuntime.jsx(NativeImagesMenuIcon, { name: "images", size: 20 })
1421
+ }
1422
+ );
1423
+ }
1424
+ return /* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style: [styles.panel, panelStyle, style], children: [
1425
+ /* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style: styles.header, children: [
1426
+ /* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style: styles.headerTitleRow, children: [
1427
+ /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: styles.headerTitle, children: resolvedLabels.title }),
1428
+ /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: styles.count, children: managed.length })
1429
+ ] }),
1430
+ /* @__PURE__ */ jsxRuntime.jsx(
1431
+ reactNative.Pressable,
1432
+ {
1433
+ accessibilityRole: "button",
1434
+ accessibilityLabel: resolvedLabels.collapse,
1435
+ onPress: () => setCollapsed(true),
1436
+ style: ({ pressed }) => [
1437
+ styles.collapseButton,
1438
+ pressed && styles.actionButtonPressed
1439
+ ],
1440
+ children: /* @__PURE__ */ jsxRuntime.jsx(NativeImagesMenuIcon, { name: "chevronRight", size: 20 })
1441
+ }
1442
+ )
1443
+ ] }),
1444
+ /* @__PURE__ */ jsxRuntime.jsx(
1445
+ reactNative.ScrollView,
1446
+ {
1447
+ style: styles.listScroll,
1448
+ contentContainerStyle: styles.listContent,
1449
+ showsVerticalScrollIndicator: false,
1450
+ children: managed.map((item) => /* @__PURE__ */ jsxRuntime.jsx(
1451
+ NativeImagesMenuRow,
1452
+ {
1453
+ item,
1454
+ items,
1455
+ labels: resolvedLabels,
1456
+ onItemsChange,
1457
+ onFocusItem,
1458
+ getImageUri,
1459
+ renderThumbnail,
1460
+ rowStyle,
1461
+ actionButtonStyle
1462
+ },
1463
+ item.id
1464
+ ))
1465
+ }
1466
+ )
1467
+ ] });
1468
+ }
1469
+ var styles = reactNative.StyleSheet.create({
1470
+ actionButton: {
1471
+ alignItems: "center",
1472
+ borderRadius: 6,
1473
+ height: 32,
1474
+ justifyContent: "center",
1475
+ width: 32
1476
+ },
1477
+ actionButtonPressed: {
1478
+ backgroundColor: "#f1f5f9"
1479
+ },
1480
+ actionsColumn: {
1481
+ alignItems: "center",
1482
+ gap: 4,
1483
+ justifyContent: "center"
1484
+ },
1485
+ collapseButton: {
1486
+ alignItems: "center",
1487
+ borderRadius: 8,
1488
+ height: 32,
1489
+ justifyContent: "center",
1490
+ width: 32
1491
+ },
1492
+ collapsedButton: {
1493
+ alignItems: "center",
1494
+ backgroundColor: "#ffffff",
1495
+ borderColor: "#e2e8f0",
1496
+ borderRadius: 10,
1497
+ borderWidth: 1,
1498
+ height: 44,
1499
+ justifyContent: "center",
1500
+ shadowColor: "#0f172a",
1501
+ shadowOffset: { width: 0, height: 8 },
1502
+ shadowOpacity: 0.12,
1503
+ shadowRadius: 24,
1504
+ width: 44
1505
+ },
1506
+ collapsedButtonPressed: {
1507
+ backgroundColor: "#f8fafc"
1508
+ },
1509
+ count: {
1510
+ color: "#64748b",
1511
+ fontSize: 14,
1512
+ fontWeight: "500"
1513
+ },
1514
+ dangerActionButton: {
1515
+ backgroundColor: "#fef2f2"
1516
+ },
1517
+ handle: {
1518
+ alignItems: "center",
1519
+ height: 128,
1520
+ justifyContent: "center",
1521
+ width: 28
1522
+ },
1523
+ header: {
1524
+ alignItems: "center",
1525
+ borderBottomColor: "#e2e8f0",
1526
+ borderBottomWidth: 1,
1527
+ flexDirection: "row",
1528
+ gap: 8,
1529
+ justifyContent: "space-between",
1530
+ paddingBottom: 8,
1531
+ paddingLeft: 14,
1532
+ paddingRight: 8,
1533
+ paddingTop: 8
1534
+ },
1535
+ headerTitle: {
1536
+ color: "#0f172a",
1537
+ fontSize: 14,
1538
+ fontWeight: "600",
1539
+ letterSpacing: 0.28
1540
+ },
1541
+ headerTitleRow: {
1542
+ alignItems: "center",
1543
+ flexDirection: "row",
1544
+ gap: 8
1545
+ },
1546
+ listContent: {
1547
+ gap: 6,
1548
+ padding: 8
1549
+ },
1550
+ listScroll: {
1551
+ maxHeight: 640
1552
+ },
1553
+ panel: {
1554
+ backgroundColor: "#ffffff",
1555
+ borderColor: "#e2e8f0",
1556
+ borderRadius: 10,
1557
+ borderWidth: 1,
1558
+ maxHeight: 820,
1559
+ overflow: "hidden",
1560
+ shadowColor: "#0f172a",
1561
+ shadowOffset: { width: 0, height: 10 },
1562
+ shadowOpacity: 0.12,
1563
+ shadowRadius: 40
1564
+ },
1565
+ row: {
1566
+ alignItems: "center",
1567
+ borderRadius: 10,
1568
+ flexDirection: "row",
1569
+ gap: 12,
1570
+ paddingBottom: 10,
1571
+ paddingLeft: 12,
1572
+ paddingRight: 12,
1573
+ paddingTop: 10
1574
+ },
1575
+ thumbnailBox: {
1576
+ alignItems: "center",
1577
+ backgroundColor: "#e2e8f0",
1578
+ borderRadius: 8,
1579
+ height: 128,
1580
+ justifyContent: "center",
1581
+ overflow: "hidden",
1582
+ width: 128
1583
+ },
1584
+ thumbnailButton: {
1585
+ alignItems: "center",
1586
+ justifyContent: "center"
1587
+ },
1588
+ thumbnailImage: {
1589
+ height: "100%",
1590
+ width: "100%"
1591
+ }
1592
+ });
1593
+
1178
1594
  // src/interaction/resize-handles.ts
1179
1595
  var HANDLE_IDS = ["nw", "n", "ne", "e", "se", "s", "sw", "w"];
1180
1596
  function getHandleWorldPosition(bounds, id) {
@@ -3385,12 +3801,12 @@ function DashPreview({
3385
3801
  dashed = false
3386
3802
  }) {
3387
3803
  const strokeHeight = Math.max(3, Math.min(6, width));
3388
- return /* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style: styles.dashPreviewTrack, children: [
3804
+ return /* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style: styles2.dashPreviewTrack, children: [
3389
3805
  /* @__PURE__ */ jsxRuntime.jsx(
3390
3806
  reactNative.View,
3391
3807
  {
3392
3808
  style: [
3393
- styles.dashPreviewStroke,
3809
+ styles2.dashPreviewStroke,
3394
3810
  {
3395
3811
  width: dashed ? 11 : 26,
3396
3812
  height: strokeHeight,
@@ -3404,7 +3820,7 @@ function DashPreview({
3404
3820
  reactNative.View,
3405
3821
  {
3406
3822
  style: [
3407
- styles.dashPreviewStroke,
3823
+ styles2.dashPreviewStroke,
3408
3824
  {
3409
3825
  width: 11,
3410
3826
  height: strokeHeight,
@@ -3448,29 +3864,29 @@ function RangeControl({
3448
3864
  }),
3449
3865
  [updateFromX]
3450
3866
  );
3451
- return /* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style: styles.rangeRow, children: [
3867
+ return /* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style: styles2.rangeRow, children: [
3452
3868
  /* @__PURE__ */ jsxRuntime.jsxs(
3453
3869
  reactNative.View,
3454
3870
  {
3455
- style: styles.rangeTrack,
3871
+ style: styles2.rangeTrack,
3456
3872
  onLayout: (event) => setTrackWidth(event.nativeEvent.layout.width),
3457
3873
  ...panResponder.panHandlers,
3458
3874
  children: [
3459
- /* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { style: styles.rangeBase }),
3460
- /* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { style: [styles.rangeFill, { width: `${normalized * 100}%` }] }),
3461
- /* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { style: [styles.rangeThumb, { left: `${normalized * 100}%` }] })
3875
+ /* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { style: styles2.rangeBase }),
3876
+ /* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { style: [styles2.rangeFill, { width: `${normalized * 100}%` }] }),
3877
+ /* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { style: [styles2.rangeThumb, { left: `${normalized * 100}%` }] })
3462
3878
  ]
3463
3879
  }
3464
3880
  ),
3465
- valueLabel ? /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: styles.rangeValue, children: valueLabel }) : null
3881
+ valueLabel ? /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: styles2.rangeValue, children: valueLabel }) : null
3466
3882
  ] });
3467
3883
  }
3468
3884
  function InspectorSection({
3469
3885
  label,
3470
3886
  children
3471
3887
  }) {
3472
- return /* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style: styles.section, children: [
3473
- /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: styles.sectionLabel, children: label }),
3888
+ return /* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style: styles2.section, children: [
3889
+ /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: styles2.sectionLabel, children: label }),
3474
3890
  children
3475
3891
  ] });
3476
3892
  }
@@ -3479,7 +3895,7 @@ function SegmentControl({
3479
3895
  value,
3480
3896
  onChange
3481
3897
  }) {
3482
- return /* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { style: styles.segmentGroup, children: segments.map((segment) => {
3898
+ return /* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { style: styles2.segmentGroup, children: segments.map((segment) => {
3483
3899
  const selected = segment.value === value;
3484
3900
  return /* @__PURE__ */ jsxRuntime.jsxs(
3485
3901
  reactNative.Pressable,
@@ -3488,15 +3904,15 @@ function SegmentControl({
3488
3904
  accessibilityState: { selected },
3489
3905
  accessibilityLabel: segment.label,
3490
3906
  onPress: () => onChange(segment.value),
3491
- style: [styles.segment, selected ? styles.segmentSelected : null],
3907
+ style: [styles2.segment, selected ? styles2.segmentSelected : null],
3492
3908
  children: [
3493
3909
  segment.preview,
3494
3910
  /* @__PURE__ */ jsxRuntime.jsx(
3495
3911
  reactNative.Text,
3496
3912
  {
3497
3913
  style: [
3498
- styles.segmentLabel,
3499
- selected ? styles.segmentLabelSelected : null
3914
+ styles2.segmentLabel,
3915
+ selected ? styles2.segmentLabelSelected : null
3500
3916
  ],
3501
3917
  children: segment.label
3502
3918
  }
@@ -3532,11 +3948,11 @@ function NativeVectorStyleInspector({
3532
3948
  reactNative.View,
3533
3949
  {
3534
3950
  pointerEvents: "auto",
3535
- style: [styles.shell, style],
3951
+ style: [styles2.shell, style],
3536
3952
  accessibilityRole: "summary",
3537
3953
  accessibilityLabel: toolId === "marker" ? "Configura\xE7\xF5es do marcador" : "Configura\xE7\xF5es da caneta",
3538
3954
  children: [
3539
- /* @__PURE__ */ jsxRuntime.jsx(InspectorSection, { label: "Cor", children: /* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { style: styles.palette, children: NATIVE_STYLE_PALETTE.map((color) => {
3955
+ /* @__PURE__ */ jsxRuntime.jsx(InspectorSection, { label: "Cor", children: /* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { style: styles2.palette, children: NATIVE_STYLE_PALETTE.map((color) => {
3540
3956
  const selected = hexesEqual(color.hex, hex);
3541
3957
  return /* @__PURE__ */ jsxRuntime.jsx(
3542
3958
  reactNative.Pressable,
@@ -3546,7 +3962,7 @@ function NativeVectorStyleInspector({
3546
3962
  accessibilityLabel: color.name,
3547
3963
  onPress: () => onChange({ stroke: color.hex }),
3548
3964
  style: [
3549
- styles.swatch,
3965
+ styles2.swatch,
3550
3966
  {
3551
3967
  backgroundColor: color.hex,
3552
3968
  borderWidth: selected ? 2 : 1,
@@ -3588,7 +4004,7 @@ function NativeVectorStyleInspector({
3588
4004
  }
3589
4005
  );
3590
4006
  }
3591
- var styles = reactNative.StyleSheet.create({
4007
+ var styles2 = reactNative.StyleSheet.create({
3592
4008
  shell: {
3593
4009
  minWidth: 240,
3594
4010
  paddingHorizontal: 14,
@@ -3900,7 +4316,7 @@ function NativeVectorToolbar({
3900
4316
  reactNative.View,
3901
4317
  {
3902
4318
  accessibilityLabel,
3903
- style: [styles2.shell, style],
4319
+ style: [styles3.shell, style],
3904
4320
  pointerEvents: "box-none",
3905
4321
  children: [
3906
4322
  /* @__PURE__ */ jsxRuntime.jsxs(
@@ -3909,8 +4325,8 @@ function NativeVectorToolbar({
3909
4325
  horizontal: true,
3910
4326
  showsHorizontalScrollIndicator: false,
3911
4327
  contentContainerStyle: [
3912
- styles2.content,
3913
- density === "comfortable" ? styles2.comfortableContent : void 0,
4328
+ styles3.content,
4329
+ density === "comfortable" ? styles3.comfortableContent : void 0,
3914
4330
  contentContainerStyle
3915
4331
  ],
3916
4332
  children: [
@@ -3927,21 +4343,21 @@ function NativeVectorToolbar({
3927
4343
  disabled: toolLockDisabled,
3928
4344
  onPress: toggleToolLock,
3929
4345
  style: ({ pressed }) => [
3930
- styles2.toolButton,
3931
- density === "comfortable" ? styles2.comfortableToolButton : void 0,
3932
- toolLocked ? styles2.activeToolButton : void 0,
3933
- pressed && !toolLockDisabled ? styles2.pressedToolButton : void 0,
3934
- toolLockDisabled ? styles2.disabledToolButton : void 0
4346
+ styles3.toolButton,
4347
+ density === "comfortable" ? styles3.comfortableToolButton : void 0,
4348
+ toolLocked ? styles3.activeToolButton : void 0,
4349
+ pressed && !toolLockDisabled ? styles3.pressedToolButton : void 0,
4350
+ toolLockDisabled ? styles3.disabledToolButton : void 0
3935
4351
  ],
3936
4352
  children: renderToolLockIcon?.({
3937
4353
  locked: toolLocked,
3938
4354
  disabled: toolLockDisabled,
3939
4355
  foregroundColor: "#18181b",
3940
4356
  onToggle: toggleToolLock
3941
- }) ?? /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: styles2.lockGlyph, children: toolLocked ? "L" : "U" })
4357
+ }) ?? /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: styles3.lockGlyph, children: toolLocked ? "L" : "U" })
3942
4358
  }
3943
4359
  ),
3944
- /* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { style: styles2.toolLockDivider })
4360
+ /* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { style: styles3.toolLockDivider })
3945
4361
  ] }) : null,
3946
4362
  toolbarTools.map(
3947
4363
  (tool) => renderNativeToolButton({
@@ -3959,7 +4375,7 @@ function NativeVectorToolbar({
3959
4375
  renderToolButton
3960
4376
  })
3961
4377
  ),
3962
- showOverflowMenu ? /* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { style: styles2.overflowSpacer }) : null,
4378
+ showOverflowMenu ? /* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { style: styles3.overflowSpacer }) : null,
3963
4379
  showOverflowMenu ? /* @__PURE__ */ jsxRuntime.jsxs(
3964
4380
  reactNative.Pressable,
3965
4381
  {
@@ -3973,27 +4389,27 @@ function NativeVectorToolbar({
3973
4389
  disabled,
3974
4390
  onPress: toggleOverflow,
3975
4391
  style: ({ pressed }) => [
3976
- styles2.overflowTrigger,
3977
- overflowOpen || activeOverflowTool ? styles2.activeToolButton : void 0,
3978
- pressed && !disabled ? styles2.pressedToolButton : void 0,
3979
- disabled ? styles2.disabledToolButton : void 0
4392
+ styles3.overflowTrigger,
4393
+ overflowOpen || activeOverflowTool ? styles3.activeToolButton : void 0,
4394
+ pressed && !disabled ? styles3.pressedToolButton : void 0,
4395
+ disabled ? styles3.disabledToolButton : void 0
3980
4396
  ],
3981
4397
  children: [
3982
- /* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { style: styles2.iconSlot, children: activeOverflowTool ? renderToolIcon?.({
4398
+ /* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { style: styles3.iconSlot, children: activeOverflowTool ? renderToolIcon?.({
3983
4399
  tool: activeOverflowTool,
3984
4400
  selected: true,
3985
4401
  disabled,
3986
4402
  foregroundColor: "#18181b",
3987
4403
  onSelect: () => onChange(activeOverflowTool.id)
3988
- }) ?? renderNativeToolFallback(activeOverflowTool, "#18181b") : renderOverflowIcon?.(overflowRenderInput) ?? /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: styles2.shapesGlyph, children: "S" }) }),
3989
- renderOverflowChevronIcon?.(overflowRenderInput) ?? /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: styles2.chevronGlyph, children: overflowOpen ? "^" : "v" })
4404
+ }) ?? renderNativeToolFallback(activeOverflowTool, "#18181b") : renderOverflowIcon?.(overflowRenderInput) ?? /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: styles3.shapesGlyph, children: "S" }) }),
4405
+ renderOverflowChevronIcon?.(overflowRenderInput) ?? /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: styles3.chevronGlyph, children: overflowOpen ? "^" : "v" })
3990
4406
  ]
3991
4407
  }
3992
4408
  ) : null
3993
4409
  ]
3994
4410
  }
3995
4411
  ),
3996
- overflowOpen && showOverflowMenu ? /* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { style: [styles2.overflowPanel, overflowPanelStyle], children: remainingOverflowTools.map(
4412
+ overflowOpen && showOverflowMenu ? /* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { style: [styles3.overflowPanel, overflowPanelStyle], children: remainingOverflowTools.map(
3997
4413
  (tool) => renderNativeToolButton({
3998
4414
  tool,
3999
4415
  value,
@@ -4004,7 +4420,7 @@ function NativeVectorToolbar({
4004
4420
  disabled,
4005
4421
  disabledIds,
4006
4422
  density: "compact",
4007
- toolButtonStyle: styles2.overflowToolButton,
4423
+ toolButtonStyle: styles3.overflowToolButton,
4008
4424
  activeToolButtonStyle,
4009
4425
  toolLabelStyle,
4010
4426
  activeToolLabelStyle,
@@ -4045,22 +4461,22 @@ function renderNativeToolButton(input) {
4045
4461
  disabled: toolDisabled,
4046
4462
  onPress: onSelect,
4047
4463
  style: ({ pressed }) => [
4048
- styles2.toolButton,
4049
- input.density === "comfortable" ? styles2.comfortableToolButton : void 0,
4464
+ styles3.toolButton,
4465
+ input.density === "comfortable" ? styles3.comfortableToolButton : void 0,
4050
4466
  input.toolButtonStyle,
4051
- selected ? styles2.activeToolButton : void 0,
4467
+ selected ? styles3.activeToolButton : void 0,
4052
4468
  selected ? input.activeToolButtonStyle : void 0,
4053
- pressed && !toolDisabled ? styles2.pressedToolButton : void 0,
4054
- toolDisabled ? styles2.disabledToolButton : void 0
4469
+ pressed && !toolDisabled ? styles3.pressedToolButton : void 0,
4470
+ toolDisabled ? styles3.disabledToolButton : void 0
4055
4471
  ],
4056
4472
  children: [
4057
- /* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { style: styles2.iconSlot, children: icon }),
4473
+ /* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { style: styles3.iconSlot, children: icon }),
4058
4474
  input.density === "comfortable" ? /* @__PURE__ */ jsxRuntime.jsx(
4059
4475
  reactNative.Text,
4060
4476
  {
4061
4477
  numberOfLines: 1,
4062
4478
  style: [
4063
- styles2.toolLabel,
4479
+ styles3.toolLabel,
4064
4480
  { color: foregroundColor },
4065
4481
  input.toolLabelStyle,
4066
4482
  selected ? input.activeToolLabelStyle : void 0
@@ -4080,9 +4496,9 @@ function renderNativeToolFallback(tool, foregroundColor, toolLabelStyle) {
4080
4496
  if (tool.id === "link") {
4081
4497
  return /* @__PURE__ */ jsxRuntime.jsx(NativeLinkToolIcon, { color: foregroundColor });
4082
4498
  }
4083
- return /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: [styles2.shortLabel, { color: foregroundColor }, toolLabelStyle], children: tool.shortLabel ?? tool.label.slice(0, 1).toUpperCase() });
4499
+ return /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: [styles3.shortLabel, { color: foregroundColor }, toolLabelStyle], children: tool.shortLabel ?? tool.label.slice(0, 1).toUpperCase() });
4084
4500
  }
4085
- var styles2 = reactNative.StyleSheet.create({
4501
+ var styles3 = reactNative.StyleSheet.create({
4086
4502
  shell: {
4087
4503
  borderRadius: 8,
4088
4504
  borderWidth: reactNative.StyleSheet.hairlineWidth,
@@ -4678,6 +5094,84 @@ function resizeItemByHandle(item, start, handle, currentWorld) {
4678
5094
  }
4679
5095
  return { ...item, x: nb.x, y: nb.y, bounds: nb };
4680
5096
  }
5097
+
5098
+ // src/native/native-remote-presence-hit-test.ts
5099
+ var REMOTE_CURSOR_SCREEN_PX2 = 22;
5100
+ var REMOTE_LABEL_SCREEN_PX2 = 12;
5101
+ var REMOTE_LABEL_OFFSET_X = 14;
5102
+ var REMOTE_LABEL_BASELINE_OFFSET_Y = 18;
5103
+ var REMOTE_LABEL_AVERAGE_CHAR_PX = 7;
5104
+ var REMOTE_LABEL_MAX_WIDTH_PX = 180;
5105
+ var REMOTE_LABEL_MIN_HIT_WIDTH_PX = 44;
5106
+ var REMOTE_LABEL_HIT_PADDING_X = 10;
5107
+ var REMOTE_LABEL_HIT_PADDING_Y = 10;
5108
+ var REMOTE_CURSOR_MIN_HIT_SIZE_PX = 36;
5109
+ function pointInScreenRect(point, rect) {
5110
+ return point.x >= rect.x && point.x <= rect.x + rect.width && point.y >= rect.y && point.y <= rect.y + rect.height;
5111
+ }
5112
+ function displayLabelForPeer(peer) {
5113
+ const displayName = peer.displayName?.trim();
5114
+ if (displayName) return displayName;
5115
+ return null;
5116
+ }
5117
+ function followIdForPeer(peer) {
5118
+ return peer.clientId ?? peer.peerId ?? peer.id;
5119
+ }
5120
+ function estimateLabelWidth(label) {
5121
+ return Math.max(
5122
+ REMOTE_LABEL_MIN_HIT_WIDTH_PX,
5123
+ Math.min(REMOTE_LABEL_MAX_WIDTH_PX, label.length * REMOTE_LABEL_AVERAGE_CHAR_PX)
5124
+ );
5125
+ }
5126
+ function buildHit(peer, camera, point, target) {
5127
+ const world = camera.screenToWorld(point.x, point.y);
5128
+ return {
5129
+ peer,
5130
+ followId: followIdForPeer(peer),
5131
+ target,
5132
+ screenX: point.x,
5133
+ screenY: point.y,
5134
+ worldX: world.worldX,
5135
+ worldY: world.worldY,
5136
+ ...peer.clientId ? { clientId: peer.clientId } : {},
5137
+ ...peer.peerId ? { peerId: peer.peerId } : {}
5138
+ };
5139
+ }
5140
+ function hitTestNativeRemotePresence(peers, camera, point) {
5141
+ for (let index = peers.length - 1; index >= 0; index -= 1) {
5142
+ const peer = peers[index];
5143
+ if (!peer || peer.isSelf || !peer.cursor) continue;
5144
+ const cursorScreen = camera.worldToScreen(peer.cursor.x, peer.cursor.y);
5145
+ const label = displayLabelForPeer(peer);
5146
+ if (label) {
5147
+ const labelX = cursorScreen.screenX + REMOTE_LABEL_OFFSET_X;
5148
+ const labelBaselineY = cursorScreen.screenY + REMOTE_LABEL_BASELINE_OFFSET_Y;
5149
+ const labelRect = {
5150
+ x: labelX - REMOTE_LABEL_HIT_PADDING_X,
5151
+ y: labelBaselineY - REMOTE_LABEL_SCREEN_PX2 - REMOTE_LABEL_HIT_PADDING_Y,
5152
+ width: estimateLabelWidth(label) + REMOTE_LABEL_HIT_PADDING_X * 2,
5153
+ height: REMOTE_LABEL_SCREEN_PX2 + REMOTE_LABEL_HIT_PADDING_Y * 2
5154
+ };
5155
+ if (pointInScreenRect(point, labelRect)) {
5156
+ return buildHit(peer, camera, point, "label");
5157
+ }
5158
+ }
5159
+ const cursorHitSize = Math.max(
5160
+ REMOTE_CURSOR_MIN_HIT_SIZE_PX,
5161
+ REMOTE_CURSOR_SCREEN_PX2
5162
+ );
5163
+ const cursorRect = {
5164
+ x: cursorScreen.screenX - (cursorHitSize - REMOTE_CURSOR_SCREEN_PX2) / 2,
5165
+ y: cursorScreen.screenY - (cursorHitSize - REMOTE_CURSOR_SCREEN_PX2) / 2,
5166
+ width: cursorHitSize,
5167
+ height: cursorHitSize
5168
+ };
5169
+ if (pointInScreenRect(point, cursorRect)) {
5170
+ return buildHit(peer, camera, point, "cursor");
5171
+ }
5172
+ }
5173
+ return null;
5174
+ }
4681
5175
  var DEFAULT_NATIVE_LINK_TOOL_DIALOG_LABELS = {
4682
5176
  title: "Add link",
4683
5177
  description: "Paste the link you want to add to the board.",
@@ -4774,6 +5268,7 @@ var NativeVectorViewport = react.forwardRef(function NativeVectorViewport2({
4774
5268
  onLinkToolRequest,
4775
5269
  linkToolDialogLabels,
4776
5270
  onWorldPointerDown,
5271
+ onRemotePresencePress,
4777
5272
  onWorldPointerMove,
4778
5273
  onWorldPointerLeave,
4779
5274
  onPlacementPreviewChange,
@@ -4797,6 +5292,8 @@ var NativeVectorViewport = react.forwardRef(function NativeVectorViewport2({
4797
5292
  onLinkToolRequestRef.current = onLinkToolRequest;
4798
5293
  const onWorldPointerDownRef = react.useRef(onWorldPointerDown);
4799
5294
  onWorldPointerDownRef.current = onWorldPointerDown;
5295
+ const onRemotePresencePressRef = react.useRef(onRemotePresencePress);
5296
+ onRemotePresencePressRef.current = onRemotePresencePress;
4800
5297
  const onWorldPointerMoveRef = react.useRef(onWorldPointerMove);
4801
5298
  onWorldPointerMoveRef.current = onWorldPointerMove;
4802
5299
  const onWorldPointerLeaveRef = react.useRef(onWorldPointerLeave);
@@ -4817,6 +5314,8 @@ var NativeVectorViewport = react.forwardRef(function NativeVectorViewport2({
4817
5314
  itemsRef.current = items;
4818
5315
  const selectedIdsRef = react.useRef(selectedIds);
4819
5316
  selectedIdsRef.current = selectedIds;
5317
+ const remotePresenceRef = react.useRef(remotePresence);
5318
+ remotePresenceRef.current = remotePresence;
4820
5319
  const dragStateRef = react.useRef({ kind: "idle" });
4821
5320
  const [placementPreview, setPlacementPreviewState] = react.useState(null);
4822
5321
  const setRealtimePlacementPreview = react.useCallback(
@@ -4976,13 +5475,19 @@ var NativeVectorViewport = react.forwardRef(function NativeVectorViewport2({
4976
5475
  const sx = point.x;
4977
5476
  const sy = point.y;
4978
5477
  updateToolCursorPoint(point);
5478
+ const cam = cameraRef.current;
5479
+ if (!cam) return;
5480
+ const remotePresenceHit = interactive && onRemotePresencePressRef.current ? hitTestNativeRemotePresence(remotePresenceRef.current, cam, point) : null;
5481
+ if (remotePresenceHit) {
5482
+ dragStateRef.current = { kind: "idle" };
5483
+ onRemotePresencePressRef.current?.(remotePresenceHit);
5484
+ return;
5485
+ }
4979
5486
  if (!interactive) {
4980
5487
  dragStateRef.current = { kind: "pan" };
4981
5488
  return;
4982
5489
  }
4983
5490
  const tool = toolIdRef.current;
4984
- const cam = cameraRef.current;
4985
- if (!cam) return;
4986
5491
  const { worldX, worldY } = screenToWorld(sx, sy);
4987
5492
  onWorldPointerMoveRef.current?.({ x: worldX, y: worldY });
4988
5493
  if (tool === "hand") {
@@ -5828,9 +6333,9 @@ var NativeVectorViewport = react.forwardRef(function NativeVectorViewport2({
5828
6333
  transparent: true,
5829
6334
  visible: pendingNativeLinkRequest !== null,
5830
6335
  onRequestClose: closeNativeLinkDialog,
5831
- children: /* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { style: styles3.nativeLinkDialogBackdrop, children: /* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style: styles3.nativeLinkDialogCard, children: [
5832
- /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: styles3.nativeLinkDialogTitle, children: nativeLinkDialogLabels.title }),
5833
- /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: styles3.nativeLinkDialogDescription, children: nativeLinkDialogLabels.description }),
6336
+ children: /* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { style: styles4.nativeLinkDialogBackdrop, children: /* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style: styles4.nativeLinkDialogCard, children: [
6337
+ /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: styles4.nativeLinkDialogTitle, children: nativeLinkDialogLabels.title }),
6338
+ /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: styles4.nativeLinkDialogDescription, children: nativeLinkDialogLabels.description }),
5834
6339
  /* @__PURE__ */ jsxRuntime.jsx(
5835
6340
  reactNative.TextInput,
5836
6341
  {
@@ -5842,21 +6347,21 @@ var NativeVectorViewport = react.forwardRef(function NativeVectorViewport2({
5842
6347
  onSubmitEditing: submitNativeLinkDialog,
5843
6348
  placeholder: nativeLinkDialogLabels.inputPlaceholder,
5844
6349
  returnKeyType: "done",
5845
- style: styles3.nativeLinkDialogInput,
6350
+ style: styles4.nativeLinkDialogInput,
5846
6351
  value: nativeLinkInputValue
5847
6352
  }
5848
6353
  ),
5849
- /* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style: styles3.nativeLinkDialogActions, children: [
6354
+ /* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style: styles4.nativeLinkDialogActions, children: [
5850
6355
  /* @__PURE__ */ jsxRuntime.jsx(
5851
6356
  reactNative.Pressable,
5852
6357
  {
5853
6358
  accessibilityRole: "button",
5854
6359
  onPress: closeNativeLinkDialog,
5855
6360
  style: ({ pressed }) => [
5856
- styles3.nativeLinkDialogButton,
5857
- pressed ? styles3.nativeLinkDialogButtonPressed : void 0
6361
+ styles4.nativeLinkDialogButton,
6362
+ pressed ? styles4.nativeLinkDialogButtonPressed : void 0
5858
6363
  ],
5859
- children: /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: styles3.nativeLinkDialogButtonText, children: nativeLinkDialogLabels.cancelLabel })
6364
+ children: /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: styles4.nativeLinkDialogButtonText, children: nativeLinkDialogLabels.cancelLabel })
5860
6365
  }
5861
6366
  ),
5862
6367
  /* @__PURE__ */ jsxRuntime.jsx(
@@ -5867,12 +6372,12 @@ var NativeVectorViewport = react.forwardRef(function NativeVectorViewport2({
5867
6372
  disabled: !nativeLinkCanSubmit,
5868
6373
  onPress: submitNativeLinkDialog,
5869
6374
  style: ({ pressed }) => [
5870
- styles3.nativeLinkDialogButton,
5871
- styles3.nativeLinkDialogPrimaryButton,
5872
- pressed && nativeLinkCanSubmit ? styles3.nativeLinkDialogPrimaryButtonPressed : void 0,
5873
- !nativeLinkCanSubmit ? styles3.nativeLinkDialogDisabledButton : void 0
6375
+ styles4.nativeLinkDialogButton,
6376
+ styles4.nativeLinkDialogPrimaryButton,
6377
+ pressed && nativeLinkCanSubmit ? styles4.nativeLinkDialogPrimaryButtonPressed : void 0,
6378
+ !nativeLinkCanSubmit ? styles4.nativeLinkDialogDisabledButton : void 0
5874
6379
  ],
5875
- children: /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: styles3.nativeLinkDialogPrimaryButtonText, children: nativeLinkDialogLabels.addLabel })
6380
+ children: /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: styles4.nativeLinkDialogPrimaryButtonText, children: nativeLinkDialogLabels.addLabel })
5876
6381
  }
5877
6382
  )
5878
6383
  ] })
@@ -5881,7 +6386,7 @@ var NativeVectorViewport = react.forwardRef(function NativeVectorViewport2({
5881
6386
  )
5882
6387
  ] });
5883
6388
  });
5884
- var styles3 = reactNative.StyleSheet.create({
6389
+ var styles4 = reactNative.StyleSheet.create({
5885
6390
  nativeLinkDialogBackdrop: {
5886
6391
  flex: 1,
5887
6392
  alignItems: "center",
@@ -5971,6 +6476,7 @@ exports.DEFAULT_LINK_CARD_SIZE = DEFAULT_LINK_CARD_SIZE;
5971
6476
  exports.DEFAULT_NATIVE_OVERFLOW_TOOL_IDS = DEFAULT_NATIVE_OVERFLOW_TOOL_IDS;
5972
6477
  exports.DEFAULT_NATIVE_VECTOR_TOOLS = DEFAULT_NATIVE_VECTOR_TOOLS;
5973
6478
  exports.NATIVE_STYLE_PALETTE = NATIVE_STYLE_PALETTE;
6479
+ exports.NativeImagesMenu = NativeImagesMenu;
5974
6480
  exports.NativeInteractionOverlay = NativeInteractionOverlay;
5975
6481
  exports.NativeSceneRenderer = NativeSceneRenderer;
5976
6482
  exports.NativeShapeRenderer = NativeShapeRenderer;