@webspatial/react-sdk 1.2.1 → 1.4.0

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/web/index.js CHANGED
@@ -2,7 +2,7 @@
2
2
  (function(){
3
3
  if(typeof window === 'undefined') return;
4
4
  if(!window.__webspatialsdk__) window.__webspatialsdk__ = {}
5
- window.__webspatialsdk__['react-sdk-version'] = "1.2.1"
5
+ window.__webspatialsdk__['react-sdk-version'] = "1.4.0"
6
6
  window.__webspatialsdk__['XR_ENV'] = "web"
7
7
  })()
8
8
 
@@ -170,18 +170,12 @@ var SpatialContainerRefProxy = class {
170
170
  if (prop === "__raw") {
171
171
  return target;
172
172
  }
173
- if (prop === "clientDepth") {
173
+ if (prop === "xrClientDepth") {
174
174
  return target.style.getPropertyValue(SpatialCustomStyleVars.depth);
175
175
  }
176
- if (prop === "offsetBack") {
176
+ if (prop === "xrOffsetBack") {
177
177
  return target.style.getPropertyValue(SpatialCustomStyleVars.back);
178
178
  }
179
- if (prop === "getBoundingClientRect") {
180
- return dom.__getBoundingClientRect;
181
- }
182
- if (prop === "getBoundingClientCube") {
183
- return dom.__getBoundingClientCube;
184
- }
185
179
  if (prop === "style") {
186
180
  if (!self.styleProxy) {
187
181
  self.styleProxy = new Proxy(target.style, {
@@ -849,7 +843,7 @@ var TransformVisibilityTaskContainer = forwardRef2(
849
843
  );
850
844
 
851
845
  // src/spatialized-container/SpatializedContainer.tsx
852
- import { forwardRef as forwardRef4, useContext as useContext6, useEffect as useEffect10, useMemo as useMemo2 } from "react";
846
+ import { forwardRef as forwardRef4, useContext as useContext7, useEffect as useEffect10, useMemo as useMemo2 } from "react";
853
847
 
854
848
  // src/noRuntime.ts
855
849
  var Spatial = class {
@@ -893,6 +887,20 @@ var Spatial = class {
893
887
  function isSSREnv() {
894
888
  return false;
895
889
  }
890
+ var PhysicalMetrics = {
891
+ pointToPhysical: (point, options) => {
892
+ return point / 1360;
893
+ },
894
+ physicalToPoint: (physical, options) => {
895
+ return physical * 1360;
896
+ },
897
+ getValue: () => ({
898
+ meterToPtUnscaled: 1360,
899
+ meterToPtScaled: 1360
900
+ }),
901
+ subscribe: (cb) => {
902
+ }
903
+ };
896
904
 
897
905
  // src/utils/getSession.ts
898
906
  var spatial = null;
@@ -938,37 +946,6 @@ function enableDebugTool() {
938
946
  });
939
947
  }
940
948
 
941
- // src/spatialized-container/transform-utils.ts
942
- function toSceneSpatial(point, spatializedElement) {
943
- return spatializedElement.__toSceneSpace(point);
944
- }
945
- function toLocalSpace(point, spatializedElement) {
946
- return spatializedElement.__toLocalSpace(point);
947
- }
948
- function convertDOMRectToSceneSpace(originalRect, matrix) {
949
- const topLeft = new DOMPoint(originalRect.left, originalRect.top);
950
- const topRight = new DOMPoint(originalRect.right, originalRect.top);
951
- const bottomRight = new DOMPoint(originalRect.right, originalRect.bottom);
952
- const bottomLeft = new DOMPoint(originalRect.left, originalRect.bottom);
953
- const transformedTopLeft = matrix.transformPoint(topLeft);
954
- const transformedTopRight = matrix.transformPoint(topRight);
955
- const transformedBottomRight = matrix.transformPoint(bottomRight);
956
- const transformedBottomLeft = matrix.transformPoint(bottomLeft);
957
- const allPoints = [
958
- transformedTopLeft,
959
- transformedTopRight,
960
- transformedBottomRight,
961
- transformedBottomLeft
962
- ];
963
- const xCoords = allPoints.map((point) => point.x);
964
- const yCoords = allPoints.map((point) => point.y);
965
- const newMinX = Math.min(...xCoords);
966
- const newMaxX = Math.max(...xCoords);
967
- const newMinY = Math.min(...yCoords);
968
- const newMaxY = Math.max(...yCoords);
969
- return new DOMRect(newMinX, newMinY, newMaxX - newMinX, newMaxY - newMinY);
970
- }
971
-
972
949
  // src/spatialized-container/context/PortalInstanceContext.ts
973
950
  var PortalInstanceObject = class {
974
951
  spatialId;
@@ -1053,40 +1030,8 @@ var PortalInstanceObject = class {
1053
1030
  isFixedPosition: computedStyle.getPropertyValue("position") === "fixed"
1054
1031
  };
1055
1032
  this.updateSpatializedElementProperties();
1056
- const __getBoundingClientCube = () => {
1057
- return this.spatializedElement?.cubeInfo;
1058
- };
1059
- const __getBoundingClientRect = () => {
1060
- if (!this.spatializedElement?.transform) {
1061
- return null;
1062
- }
1063
- const domRect = new DOMRect(
1064
- 0,
1065
- 0,
1066
- this.domRect?.width,
1067
- this.domRect?.height
1068
- );
1069
- return convertDOMRectToSceneSpace(
1070
- domRect,
1071
- this.spatializedElement?.transform
1072
- );
1073
- };
1074
- const __toSceneSpace = (point) => {
1075
- return new DOMPoint(point.x, point.y, point.z).matrixTransform(
1076
- this.spatializedElement?.transform
1077
- );
1078
- };
1079
- const __toLocalSpace = (point) => {
1080
- return new DOMPoint(point.x, point.y, point.z).matrixTransform(
1081
- this.spatializedElement?.transformInv
1082
- );
1083
- };
1084
1033
  const __innerSpatializedElement = () => this.spatializedElement;
1085
1034
  Object.assign(dom, {
1086
- __getBoundingClientCube,
1087
- __getBoundingClientRect,
1088
- __toSceneSpace,
1089
- __toLocalSpace,
1090
1035
  __innerSpatializedElement
1091
1036
  });
1092
1037
  }
@@ -1204,18 +1149,19 @@ function useSync2DFrame(spatialId, portalInstanceObject, spatializedContainerObj
1204
1149
  }
1205
1150
 
1206
1151
  // src/spatialized-container/hooks/useSpatializedElement.ts
1207
- import { useEffect as useEffect6, useState as useState3 } from "react";
1152
+ import { useEffect as useEffect6, useRef as useRef4, useState as useState3 } from "react";
1208
1153
  function useSpatializedElement(createSpatializedElement2, portalInstanceObject) {
1209
1154
  const [spatializedElement, setSpatializedElement] = useState3();
1155
+ const elementRef = useRef4(void 0);
1210
1156
  useEffect6(() => {
1211
1157
  let isDestroyed = false;
1212
- let spatializedElement2;
1213
1158
  createSpatializedElement2().then(
1214
1159
  (inSpatializedElement) => {
1160
+ if (!inSpatializedElement) return;
1215
1161
  if (!isDestroyed) {
1216
- spatializedElement2 = inSpatializedElement;
1217
- portalInstanceObject.attachSpatializedElement(spatializedElement2);
1218
- setSpatializedElement(spatializedElement2);
1162
+ elementRef.current = inSpatializedElement;
1163
+ portalInstanceObject.attachSpatializedElement(inSpatializedElement);
1164
+ setSpatializedElement(inSpatializedElement);
1219
1165
  } else {
1220
1166
  inSpatializedElement?.destroy();
1221
1167
  }
@@ -1223,9 +1169,11 @@ function useSpatializedElement(createSpatializedElement2, portalInstanceObject)
1223
1169
  );
1224
1170
  return () => {
1225
1171
  isDestroyed = true;
1226
- if (spatializedElement2) {
1227
- spatializedElement2.destroy();
1228
- spatializedElement2 = void 0;
1172
+ const el = elementRef.current;
1173
+ if (el) {
1174
+ el.destroy();
1175
+ elementRef.current = void 0;
1176
+ setSpatializedElement(void 0);
1229
1177
  }
1230
1178
  };
1231
1179
  }, [createSpatializedElement2, portalInstanceObject]);
@@ -1234,6 +1182,18 @@ function useSpatializedElement(createSpatializedElement2, portalInstanceObject)
1234
1182
 
1235
1183
  // src/spatialized-container/PortalSpatializedContainer.tsx
1236
1184
  import { Fragment, jsx as jsx3, jsxs } from "react/jsx-runtime";
1185
+ function constrainedAxisToVec3(input) {
1186
+ if (input == null) return { x: 0, y: 0, z: 0 };
1187
+ if (Array.isArray(input)) {
1188
+ return { x: input[0] ?? 0, y: input[1] ?? 0, z: input[2] ?? 0 };
1189
+ }
1190
+ const v = input;
1191
+ return { x: v.x, y: v.y, z: v.z };
1192
+ }
1193
+ function constrainedAxisKey(input) {
1194
+ const v = constrainedAxisToVec3(input);
1195
+ return `${v.x},${v.y},${v.z}`;
1196
+ }
1237
1197
  function renderPlaceholderInSubPortal(portalInstanceObject, El) {
1238
1198
  const spatialId = portalInstanceObject.spatialId;
1239
1199
  const inPortalInstanceEnv = !!portalInstanceObject.parentPortalInstanceObject;
@@ -1272,6 +1232,7 @@ function PortalSpatializedContainer(props) {
1272
1232
  onSpatialRotateEnd,
1273
1233
  onSpatialMagnify,
1274
1234
  onSpatialMagnifyEnd,
1235
+ spatialEventOptions,
1275
1236
  [SpatialID]: spatialId,
1276
1237
  ...restProps
1277
1238
  } = props;
@@ -1343,14 +1304,27 @@ function PortalSpatializedContainer(props) {
1343
1304
  spatializedElement.onSpatialDragStart = onSpatialDragStart;
1344
1305
  }
1345
1306
  }, [spatializedElement, onSpatialDragStart]);
1307
+ const rotateConstraintKey = constrainedAxisKey(
1308
+ spatialEventOptions?.constrainedToAxis
1309
+ );
1310
+ useEffect7(() => {
1311
+ if (!spatializedElement) return;
1312
+ const axis = constrainedAxisToVec3(spatialEventOptions?.constrainedToAxis);
1313
+ void spatializedElement.updateProperties({ rotateConstrainedToAxis: axis });
1314
+ }, [spatializedElement, rotateConstraintKey]);
1346
1315
  return /* @__PURE__ */ jsxs(PortalInstanceContext.Provider, { value: portalInstanceObject, children: [
1347
1316
  spatializedElement && portalInstanceObject.dom && /* @__PURE__ */ jsx3(Content, { spatializedElement, ...restProps }),
1348
1317
  PlaceholderEl
1349
1318
  ] });
1350
1319
  }
1351
1320
 
1321
+ // src/reality/context/InsideAttachmentContext.tsx
1322
+ import { createContext as createContext4, useContext as useContext5 } from "react";
1323
+ var InsideAttachmentContext = createContext4(false);
1324
+ var useInsideAttachment = () => useContext5(InsideAttachmentContext);
1325
+
1352
1326
  // src/spatialized-container/hooks/useSpatialEvents.ts
1353
- function createEventProxy(event, currentTargetGetter, offsetXGetter, offsetYGetter, offsetZGetter) {
1327
+ function createEventProxy(event, currentTargetGetter, offsetXGetter, offsetYGetter, offsetZGetter, clientXGetter, clientYGetter, clientZGetter, translationXGetter, translationYGetter, translationZGetter, quaternionGetter, magnificationGetter) {
1354
1328
  return new Proxy(event, {
1355
1329
  get(target, prop) {
1356
1330
  if (prop === "currentTarget") {
@@ -1371,18 +1345,50 @@ function createEventProxy(event, currentTargetGetter, offsetXGetter, offsetYGett
1371
1345
  if (prop === "offsetZ" && offsetZGetter) {
1372
1346
  return offsetZGetter(target) ?? 0;
1373
1347
  }
1348
+ if (prop === "clientX" && clientXGetter) {
1349
+ return clientXGetter(target) ?? 0;
1350
+ }
1351
+ if (prop === "clientY" && clientYGetter) {
1352
+ return clientYGetter(target) ?? 0;
1353
+ }
1354
+ if (prop === "clientZ" && clientZGetter) {
1355
+ return clientZGetter(target) ?? 0;
1356
+ }
1357
+ if (prop === "translationX" && translationXGetter) {
1358
+ return translationXGetter(target) ?? 0;
1359
+ }
1360
+ if (prop === "translationY" && translationYGetter) {
1361
+ return translationYGetter(target) ?? 0;
1362
+ }
1363
+ if (prop === "translationZ" && translationZGetter) {
1364
+ return translationZGetter(target) ?? 0;
1365
+ }
1366
+ if (prop === "quaternion" && quaternionGetter) {
1367
+ return quaternionGetter(target) ?? { x: 0, y: 0, z: 0, w: 1 };
1368
+ }
1369
+ if (prop === "magnification" && magnificationGetter) {
1370
+ return magnificationGetter(target) ?? 1;
1371
+ }
1374
1372
  return Reflect.get(target, prop);
1375
1373
  }
1376
1374
  });
1377
1375
  }
1378
- function createEventHandler(handler, currentTargetGetter, offsetXGetter, offsetYGetter, offsetZGetter) {
1376
+ function createEventHandler(handler, currentTargetGetter, offsetXGetter, offsetYGetter, offsetZGetter, clientXGetter, clientYGetter, clientZGetter, translationXGetter, translationYGetter, translationZGetter, quaternionGetter, magnificationGetter) {
1379
1377
  return handler ? (event) => {
1380
1378
  const proxyEvent = createEventProxy(
1381
1379
  event,
1382
1380
  currentTargetGetter,
1383
1381
  offsetXGetter,
1384
1382
  offsetYGetter,
1385
- offsetZGetter
1383
+ offsetZGetter,
1384
+ clientXGetter,
1385
+ clientYGetter,
1386
+ clientZGetter,
1387
+ translationXGetter,
1388
+ translationYGetter,
1389
+ translationZGetter,
1390
+ quaternionGetter,
1391
+ magnificationGetter
1386
1392
  );
1387
1393
  handler(proxyEvent);
1388
1394
  } : void 0;
@@ -1391,13 +1397,27 @@ function useSpatialEventsBase(spatialEvents, currentTargetGetter) {
1391
1397
  const onSpatialTap = createEventHandler(
1392
1398
  spatialEvents.onSpatialTap,
1393
1399
  currentTargetGetter,
1400
+ // offsetX/Y/Z come from local coordinates
1394
1401
  (ev) => ev.detail?.location3D?.x,
1395
1402
  (ev) => ev.detail?.location3D?.y,
1396
- (ev) => ev.detail?.location3D?.z
1403
+ (ev) => ev.detail?.location3D?.z,
1404
+ // clientX/Y/Z come from global scene coordinates
1405
+ (ev) => ev.detail?.globalLocation3D?.x,
1406
+ (ev) => ev.detail?.globalLocation3D?.y,
1407
+ (ev) => ev.detail?.globalLocation3D?.z
1397
1408
  );
1398
1409
  const onSpatialDrag = createEventHandler(
1399
1410
  spatialEvents.onSpatialDrag,
1400
- currentTargetGetter
1411
+ currentTargetGetter,
1412
+ void 0,
1413
+ void 0,
1414
+ void 0,
1415
+ void 0,
1416
+ void 0,
1417
+ void 0,
1418
+ (ev) => ev.detail?.translation3D?.x,
1419
+ (ev) => ev.detail?.translation3D?.y,
1420
+ (ev) => ev.detail?.translation3D?.z
1401
1421
  );
1402
1422
  const onSpatialDragEnd = createEventHandler(
1403
1423
  spatialEvents.onSpatialDragEnd,
@@ -1405,7 +1425,17 @@ function useSpatialEventsBase(spatialEvents, currentTargetGetter) {
1405
1425
  );
1406
1426
  const onSpatialRotate = createEventHandler(
1407
1427
  spatialEvents.onSpatialRotate,
1408
- currentTargetGetter
1428
+ currentTargetGetter,
1429
+ void 0,
1430
+ void 0,
1431
+ void 0,
1432
+ void 0,
1433
+ void 0,
1434
+ void 0,
1435
+ void 0,
1436
+ void 0,
1437
+ void 0,
1438
+ (ev) => ev.detail?.quaternion
1409
1439
  );
1410
1440
  const onSpatialRotateEnd = createEventHandler(
1411
1441
  spatialEvents.onSpatialRotateEnd,
@@ -1413,7 +1443,18 @@ function useSpatialEventsBase(spatialEvents, currentTargetGetter) {
1413
1443
  );
1414
1444
  const onSpatialMagnify = createEventHandler(
1415
1445
  spatialEvents.onSpatialMagnify,
1416
- currentTargetGetter
1446
+ currentTargetGetter,
1447
+ void 0,
1448
+ void 0,
1449
+ void 0,
1450
+ void 0,
1451
+ void 0,
1452
+ void 0,
1453
+ void 0,
1454
+ void 0,
1455
+ void 0,
1456
+ void 0,
1457
+ (ev) => ev.detail?.magnification
1417
1458
  );
1418
1459
  const onSpatialMagnifyEnd = createEventHandler(
1419
1460
  spatialEvents.onSpatialMagnifyEnd,
@@ -1424,7 +1465,10 @@ function useSpatialEventsBase(spatialEvents, currentTargetGetter) {
1424
1465
  currentTargetGetter,
1425
1466
  (ev) => ev.detail?.startLocation3D?.x,
1426
1467
  (ev) => ev.detail?.startLocation3D?.y,
1427
- (ev) => ev.detail?.startLocation3D?.z
1468
+ (ev) => ev.detail?.startLocation3D?.z,
1469
+ (ev) => ev.detail?.globalLocation3D?.x,
1470
+ (ev) => ev.detail?.globalLocation3D?.y,
1471
+ (ev) => ev.detail?.globalLocation3D?.z
1428
1472
  );
1429
1473
  return {
1430
1474
  onSpatialTap,
@@ -1453,9 +1497,9 @@ function useSpatialEventsWhenSpatializedContainerExist(spatialEvents, spatialId,
1453
1497
  }
1454
1498
 
1455
1499
  // src/ssr/SSRContext.tsx
1456
- import { createContext as createContext4, useState as useState4, useEffect as useEffect8 } from "react";
1500
+ import { createContext as createContext5, useState as useState4, useEffect as useEffect8 } from "react";
1457
1501
  import { jsx as jsx4 } from "react/jsx-runtime";
1458
- var SSRContext = createContext4(false);
1502
+ var SSRContext = createContext5(false);
1459
1503
  var SSRProvider = ({
1460
1504
  isSSR: initialIsSSR = true,
1461
1505
  children
@@ -1473,9 +1517,9 @@ var SSRProvider = ({
1473
1517
  import { forwardRef as forwardRef3 } from "react";
1474
1518
 
1475
1519
  // src/ssr/useSSRPhase.tsx
1476
- import { useContext as useContext5, useState as useState5, useEffect as useEffect9 } from "react";
1520
+ import { useContext as useContext6, useState as useState5, useEffect as useEffect9 } from "react";
1477
1521
  function useSSRPhase() {
1478
- const isSSRContext = useContext5(SSRContext);
1522
+ const isSSRContext = useContext6(SSRContext);
1479
1523
  const isServer = typeof window === "undefined";
1480
1524
  const [hydrated, setHydrated] = useState5(false);
1481
1525
  useEffect9(() => setHydrated(true), []);
@@ -1511,33 +1555,49 @@ function withSSRSupported(Component) {
1511
1555
 
1512
1556
  // src/spatialized-container/SpatializedContainer.tsx
1513
1557
  import { jsx as jsx6, jsxs as jsxs2 } from "react/jsx-runtime";
1558
+ function DegradedContainer({
1559
+ innerRef,
1560
+ ...inprops
1561
+ }) {
1562
+ const {
1563
+ component: Component,
1564
+ children,
1565
+ ["enable-xr"]: _enableXR,
1566
+ onSpatialTap: _onSpatialTap,
1567
+ onSpatialDragStart: _onSpatialDragStart,
1568
+ onSpatialDrag: _onSpatialDrag,
1569
+ onSpatialDragEnd: _onSpatialDragEnd,
1570
+ onSpatialRotate: _onSpatialRotate,
1571
+ onSpatialRotateEnd: _onSpatialRotateEnd,
1572
+ onSpatialMagnify: _onSpatialMagnify,
1573
+ onSpatialMagnifyEnd: _onSpatialMagnifyEnd,
1574
+ spatialEventOptions: _spatialEventOptions,
1575
+ spatializedContent: _content,
1576
+ createSpatializedElement: _create,
1577
+ getExtraSpatializedElementProperties: _getExtra,
1578
+ extraRefProps: _extraRef,
1579
+ sizingMode: _sizingMode,
1580
+ ...restProps
1581
+ } = inprops;
1582
+ return /* @__PURE__ */ jsx6(Component, { ref: innerRef, ...restProps, children });
1583
+ }
1514
1584
  function SpatializedContainerBase(inprops, ref) {
1515
1585
  const isWebSpatialEnv = getSession() !== null;
1516
- if (!isWebSpatialEnv) {
1517
- const {
1518
- component: Component,
1519
- spatializedContent,
1520
- createSpatializedElement: createSpatializedElement2,
1521
- getExtraSpatializedElementProperties: getExtraSpatializedElementProperties2,
1522
- onSpatialTap: onSpatialTap2,
1523
- onSpatialDragStart: onSpatialDragStart2,
1524
- onSpatialDrag: onSpatialDrag2,
1525
- onSpatialDragEnd: onSpatialDragEnd2,
1526
- onSpatialRotate: onSpatialRotate2,
1527
- onSpatialRotateEnd: onSpatialRotateEnd2,
1528
- onSpatialMagnify: onSpatialMagnify2,
1529
- onSpatialMagnifyEnd: onSpatialMagnifyEnd2,
1530
- extraRefProps: extraRefProps2,
1531
- ...restProps
1532
- } = inprops;
1533
- return /* @__PURE__ */ jsx6(Component, { ref, ...restProps });
1586
+ const insideAttachment = useInsideAttachment();
1587
+ if (!isWebSpatialEnv || insideAttachment) {
1588
+ if (insideAttachment) {
1589
+ console.warn(
1590
+ `[WebSpatial] ${inprops.component || "Spatial element"} cannot be used inside AttachmentAsset. Rendering as plain HTML.`
1591
+ );
1592
+ }
1593
+ return /* @__PURE__ */ jsx6(DegradedContainer, { ...inprops, innerRef: ref });
1534
1594
  }
1535
- const layer = useContext6(SpatialLayerContext) + 1;
1536
- const rootSpatializedContainerObject = useContext6(
1595
+ const layer = useContext7(SpatialLayerContext) + 1;
1596
+ const rootSpatializedContainerObject = useContext7(
1537
1597
  SpatializedContainerContext
1538
1598
  );
1539
1599
  const inSpatializedContainer = !!rootSpatializedContainerObject;
1540
- const portalInstanceObject = useContext6(PortalInstanceContext);
1600
+ const portalInstanceObject = useContext7(PortalInstanceContext);
1541
1601
  const inPortalInstanceEnv = !!portalInstanceObject;
1542
1602
  const isInStandardInstance = !inPortalInstanceEnv;
1543
1603
  const spatialId = useMemo2(() => {
@@ -1598,6 +1658,7 @@ function SpatializedContainerBase(inprops, ref) {
1598
1658
  spatializedContent,
1599
1659
  createSpatializedElement: createSpatializedElement2,
1600
1660
  getExtraSpatializedElementProperties: getExtraSpatializedElementProperties2,
1661
+ spatialEventOptions: _nestedSpatialEventOptions,
1601
1662
  ...restProps
1602
1663
  } = props;
1603
1664
  return /* @__PURE__ */ jsxs2(SpatialLayerContext.Provider, { value: layer, children: [
@@ -1648,6 +1709,7 @@ function SpatializedContainerBase(inprops, ref) {
1648
1709
  spatializedContent,
1649
1710
  createSpatializedElement: createSpatializedElement2,
1650
1711
  getExtraSpatializedElementProperties: getExtraSpatializedElementProperties2,
1712
+ spatialEventOptions: _rootSpatialEventOptions,
1651
1713
  ...restProps
1652
1714
  } = props;
1653
1715
  return /* @__PURE__ */ jsx6(SpatialLayerContext.Provider, { value: layer, children: /* @__PURE__ */ jsxs2(
@@ -1691,28 +1753,47 @@ var SpatializedContainer = withSSRSupported(
1691
1753
  );
1692
1754
 
1693
1755
  // src/spatialized-container/Spatialized2DElementContainer.tsx
1756
+ import { createPortal as createPortal2 } from "react-dom";
1694
1757
  import {
1695
1758
  forwardRef as forwardRef5,
1696
- useContext as useContext7,
1697
- useEffect as useEffect11
1759
+ useContext as useContext8,
1760
+ useEffect as useEffect12
1698
1761
  } from "react";
1699
- import { createPortal as createPortal2 } from "react-dom";
1700
- import { jsx as jsx7 } from "react/jsx-runtime";
1701
- function asyncLoadStyleToChildWindow(childWindow, n) {
1762
+
1763
+ // src/utils/windowStyleSync.ts
1764
+ function asyncLoadStyleToChildWindow(childWindow, link, isCurrent) {
1702
1765
  return new Promise((resolve) => {
1703
- n.href += "?uniqueURL=" + Math.random();
1704
- n.onerror = function(error) {
1705
- console.error("Failed to load style link", n.href);
1706
- resolve(false);
1766
+ const { href } = link;
1767
+ const sep = href.includes("?") ? "&" : "?";
1768
+ link.href = `${href}${sep}uniqueURL=${Math.random()}`;
1769
+ let finished = false;
1770
+ const finish = (ok) => {
1771
+ if (finished) return;
1772
+ finished = true;
1773
+ resolve(ok);
1707
1774
  };
1708
- n.onload = function() {
1709
- resolve(true);
1775
+ link.onerror = () => {
1776
+ finish(false);
1777
+ };
1778
+ link.onload = () => {
1779
+ if (!isCurrent()) {
1780
+ link.parentNode?.removeChild(link);
1781
+ finish(false);
1782
+ return;
1783
+ }
1784
+ finish(true);
1710
1785
  };
1711
1786
  setTimeout(() => {
1712
- childWindow.document.head.appendChild(n);
1787
+ if (!isCurrent()) {
1788
+ finish(false);
1789
+ return;
1790
+ }
1791
+ childWindow.document.head.appendChild(link);
1713
1792
  }, 50);
1714
1793
  });
1715
1794
  }
1795
+ var WEBSPATIAL_SYNC_ATTR = "data-webspatial-sync";
1796
+ var WEBSPATIAL_SYNC_KEY_ATTR = "data-webspatial-sync-key";
1716
1797
  function setOpenWindowStyle(openedWindow) {
1717
1798
  openedWindow.document.documentElement.style.cssText += document.documentElement.style.cssText;
1718
1799
  openedWindow.document.documentElement.style.backgroundColor = "transparent";
@@ -1724,23 +1805,118 @@ function setOpenWindowStyle(openedWindow) {
1724
1805
  openedWindow.document.body.style.minWidth = "fit-content";
1725
1806
  openedWindow.document.body.style.background = "transparent";
1726
1807
  }
1808
+ var controllers = /* @__PURE__ */ new WeakMap();
1809
+ function getController(childWindow) {
1810
+ const prev = controllers.get(childWindow);
1811
+ if (prev) return prev;
1812
+ const next = { version: 0 };
1813
+ controllers.set(childWindow, next);
1814
+ return next;
1815
+ }
1727
1816
  async function syncParentHeadToChild(childWindow) {
1817
+ const controller = getController(childWindow);
1818
+ const version2 = ++controller.version;
1728
1819
  const styleLoadedPromises = [];
1729
- for (let i = 0; i < document.head.children.length; i++) {
1730
- let n = document.head.children[i].cloneNode(true);
1731
- if (n.nodeName == "LINK" && n.rel == "stylesheet" && n.href) {
1732
- const promise = asyncLoadStyleToChildWindow(
1733
- childWindow,
1734
- n
1735
- );
1736
- styleLoadedPromises.push(promise);
1737
- } else {
1738
- childWindow.document.head.appendChild(n);
1739
- }
1820
+ const { head } = childWindow.document;
1821
+ const isCurrent = () => controller.version === version2;
1822
+ const parentStyles = Array.from(document.head.querySelectorAll("style"));
1823
+ const parentStylesheets = Array.from(
1824
+ document.head.querySelectorAll('link[rel="stylesheet"][href]')
1825
+ );
1826
+ const desiredStylesheetKeys = /* @__PURE__ */ new Set();
1827
+ for (const link of parentStylesheets) {
1828
+ if (link.href) desiredStylesheetKeys.add(link.href);
1829
+ }
1830
+ const existingSyncedLinks = Array.from(
1831
+ head.querySelectorAll(
1832
+ `link[rel="stylesheet"][${WEBSPATIAL_SYNC_ATTR}="1"]`
1833
+ )
1834
+ );
1835
+ for (const link of existingSyncedLinks) {
1836
+ const key = link.getAttribute(WEBSPATIAL_SYNC_KEY_ATTR) ?? link.href;
1837
+ if (!desiredStylesheetKeys.has(key)) link.parentNode?.removeChild(link);
1838
+ }
1839
+ const prevSyncedStyles = head.querySelectorAll(
1840
+ `style[${WEBSPATIAL_SYNC_ATTR}="1"]`
1841
+ );
1842
+ prevSyncedStyles.forEach((n) => n.parentNode?.removeChild(n));
1843
+ for (const styleEl of parentStyles) {
1844
+ const node = styleEl.cloneNode(true);
1845
+ node.setAttribute(WEBSPATIAL_SYNC_ATTR, "1");
1846
+ head.appendChild(node);
1847
+ }
1848
+ const currentKeys = /* @__PURE__ */ new Set();
1849
+ const currentSyncedLinks = Array.from(
1850
+ head.querySelectorAll(
1851
+ `link[rel="stylesheet"][${WEBSPATIAL_SYNC_ATTR}="1"]`
1852
+ )
1853
+ );
1854
+ for (const link of currentSyncedLinks) {
1855
+ currentKeys.add(link.getAttribute(WEBSPATIAL_SYNC_KEY_ATTR) ?? link.href);
1856
+ }
1857
+ for (const link of parentStylesheets) {
1858
+ const key = link.href;
1859
+ if (!key || currentKeys.has(key)) continue;
1860
+ const node = link.cloneNode(true);
1861
+ node.setAttribute(WEBSPATIAL_SYNC_ATTR, "1");
1862
+ node.setAttribute(WEBSPATIAL_SYNC_KEY_ATTR, key);
1863
+ styleLoadedPromises.push(
1864
+ asyncLoadStyleToChildWindow(childWindow, node, isCurrent)
1865
+ );
1740
1866
  }
1741
1867
  childWindow.document.documentElement.className = document.documentElement.className;
1742
1868
  return Promise.all(styleLoadedPromises);
1743
1869
  }
1870
+
1871
+ // src/utils/useSyncHeadStyles.ts
1872
+ import { useEffect as useEffect11 } from "react";
1873
+ function defaultShouldSync(mutations) {
1874
+ if (!Array.isArray(mutations) || mutations.length === 0) return false;
1875
+ for (const mutation of mutations) {
1876
+ const nodes = [
1877
+ ...Array.from(mutation.addedNodes),
1878
+ ...Array.from(mutation.removedNodes)
1879
+ ];
1880
+ for (const node of nodes) {
1881
+ if (!(node instanceof Element)) continue;
1882
+ const tag = node.tagName;
1883
+ if (tag === "STYLE") return true;
1884
+ if (tag === "LINK") {
1885
+ const { rel } = node;
1886
+ if (rel && rel.toLowerCase() === "stylesheet") return true;
1887
+ }
1888
+ }
1889
+ }
1890
+ return false;
1891
+ }
1892
+ function useSyncHeadStyles(childWindow, options) {
1893
+ const delayMs = 100;
1894
+ const subtree = options?.subtree ?? false;
1895
+ const immediate = options?.immediate ?? true;
1896
+ useEffect11(() => {
1897
+ if (!childWindow) return;
1898
+ let timer;
1899
+ const scheduleSync = () => {
1900
+ if (timer) window.clearTimeout(timer);
1901
+ timer = window.setTimeout(() => {
1902
+ syncParentHeadToChild(childWindow);
1903
+ }, delayMs);
1904
+ };
1905
+ if (immediate) scheduleSync();
1906
+ const observer = new MutationObserver((mutations) => {
1907
+ if (!defaultShouldSync(mutations)) return;
1908
+ scheduleSync();
1909
+ });
1910
+ observer.observe(document.head, { childList: true, subtree });
1911
+ return () => {
1912
+ if (timer) window.clearTimeout(timer);
1913
+ observer.disconnect();
1914
+ };
1915
+ }, [childWindow, delayMs, subtree, immediate]);
1916
+ }
1917
+
1918
+ // src/spatialized-container/Spatialized2DElementContainer.tsx
1919
+ import { jsx as jsx7 } from "react/jsx-runtime";
1744
1920
  function getJSXPortalInstance(inProps, portalInstanceObject) {
1745
1921
  const { component: El, style: inStyle = {}, ...props } = inProps;
1746
1922
  const extraStyle = {
@@ -1766,19 +1942,8 @@ function getJSXPortalInstance(inProps, portalInstanceObject) {
1766
1942
  };
1767
1943
  return /* @__PURE__ */ jsx7(El, { style, ...props });
1768
1944
  }
1769
- function useSyncHeaderStyle(windowProxy) {
1770
- useEffect11(() => {
1771
- const headObserver = new MutationObserver((_) => {
1772
- syncParentHeadToChild(windowProxy);
1773
- });
1774
- headObserver.observe(document.head, { childList: true, subtree: true });
1775
- return () => {
1776
- headObserver.disconnect();
1777
- };
1778
- }, []);
1779
- }
1780
1945
  function useSyncDocumentTitle(windowProxy, spatializedElement, name) {
1781
- useEffect11(() => {
1946
+ useEffect12(() => {
1782
1947
  windowProxy.document.title = name;
1783
1948
  spatializedElement.updateProperties({
1784
1949
  name
@@ -1788,11 +1953,13 @@ function useSyncDocumentTitle(windowProxy, spatializedElement, name) {
1788
1953
  function SpatializedContent(props) {
1789
1954
  const { spatializedElement, ...restProps } = props;
1790
1955
  const spatialized2DElement = spatializedElement;
1791
- const windowProxy = spatialized2DElement.windowProxy;
1792
- useSyncHeaderStyle(windowProxy);
1956
+ const { windowProxy } = spatialized2DElement;
1957
+ useSyncHeadStyles(windowProxy, {
1958
+ subtree: false
1959
+ });
1793
1960
  const name = restProps["data-name"] || "";
1794
1961
  useSyncDocumentTitle(windowProxy, spatialized2DElement, name);
1795
- const portalInstanceObject = useContext7(
1962
+ const portalInstanceObject = useContext8(
1796
1963
  PortalInstanceContext
1797
1964
  );
1798
1965
  const JSXPortalInstance = getJSXPortalInstance(
@@ -1817,14 +1984,14 @@ function getExtraSpatializedElementProperties(computedStyle) {
1817
1984
  }
1818
1985
  async function createSpatializedElement() {
1819
1986
  const spatializedElement = await getSession().createSpatialized2DElement();
1820
- const windowProxy = spatializedElement.windowProxy;
1987
+ const { windowProxy } = spatializedElement;
1821
1988
  setOpenWindowStyle(windowProxy);
1822
1989
  await syncParentHeadToChild(windowProxy);
1823
1990
  const viewport = windowProxy.document.querySelector('meta[name="viewport"]');
1824
1991
  if (viewport) {
1825
1992
  viewport?.setAttribute(
1826
1993
  "content",
1827
- ` initial-scale=1.0, maximum-scale=1.0, user-scalable=no`
1994
+ " initial-scale=1.0, maximum-scale=1.0, user-scalable=no"
1828
1995
  );
1829
1996
  } else {
1830
1997
  const meta = windowProxy.document.createElement("meta");
@@ -1854,12 +2021,10 @@ var Spatialized2DElementContainer = forwardRef5(
1854
2021
  import {
1855
2022
  forwardRef as forwardRef6,
1856
2023
  useCallback as useCallback6,
1857
- useContext as useContext8,
1858
- useEffect as useEffect12,
2024
+ useContext as useContext9,
2025
+ useEffect as useEffect13,
1859
2026
  useMemo as useMemo3,
1860
- useState as useState6,
1861
- useImperativeHandle,
1862
- useRef as useRef4
2027
+ useRef as useRef5
1863
2028
  } from "react";
1864
2029
  import { Fragment as Fragment2, jsx as jsx8 } from "react/jsx-runtime";
1865
2030
  function getAbsoluteURL(url) {
@@ -1896,16 +2061,16 @@ function createLoadSuccessEvent(targetGetter) {
1896
2061
  function SpatializedContent2(props) {
1897
2062
  const { src, spatializedElement, onLoad, onError } = props;
1898
2063
  const spatializedStatic3DElement = spatializedElement;
1899
- const portalInstanceObject = useContext8(
2064
+ const portalInstanceObject = useContext9(
1900
2065
  PortalInstanceContext
1901
2066
  );
1902
2067
  const currentSrc = useMemo3(() => getAbsoluteURL(src), [src]);
1903
- useEffect12(() => {
2068
+ useEffect13(() => {
1904
2069
  if (src) {
1905
2070
  spatializedStatic3DElement.updateProperties({ modelURL: currentSrc });
1906
2071
  }
1907
2072
  }, [currentSrc]);
1908
- useEffect12(() => {
2073
+ useEffect13(() => {
1909
2074
  if (onLoad) {
1910
2075
  spatializedStatic3DElement.onLoadCallback = () => {
1911
2076
  onLoad(
@@ -1918,7 +2083,7 @@ function SpatializedContent2(props) {
1918
2083
  spatializedStatic3DElement.onLoadCallback = void 0;
1919
2084
  }
1920
2085
  }, [onLoad]);
1921
- useEffect12(() => {
2086
+ useEffect13(() => {
1922
2087
  if (onError) {
1923
2088
  spatializedStatic3DElement.onLoadFailureCallback = () => {
1924
2089
  onError(
@@ -1934,14 +2099,12 @@ function SpatializedContent2(props) {
1934
2099
  return /* @__PURE__ */ jsx8(Fragment2, {});
1935
2100
  }
1936
2101
  function SpatializedStatic3DElementContainerBase(props, ref) {
1937
- const containerRef = useRef4(null);
1938
- const [elementCreated, setElementCreated] = useState6(false);
1939
- useImperativeHandle(ref, () => elementCreated ? containerRef.current : null, [elementCreated]);
1940
- const createSpatializedElement2 = useCallback6(async () => {
1941
- const element = await getSession().createSpatializedStatic3DElement();
1942
- setElementCreated(true);
1943
- return element;
1944
- }, [setElementCreated]);
2102
+ const promiseRef = useRef5(null);
2103
+ const createSpatializedElement2 = useCallback6(() => {
2104
+ const url = getAbsoluteURL(props.src);
2105
+ promiseRef.current = getSession().createSpatializedStatic3DElement(url);
2106
+ return promiseRef.current;
2107
+ }, []);
1945
2108
  const extraRefProps = useCallback6(
1946
2109
  (domProxy) => {
1947
2110
  let modelTransform = new DOMMatrixReadOnly();
@@ -1950,14 +2113,10 @@ function SpatializedStatic3DElementContainerBase(props, ref) {
1950
2113
  return getAbsoluteURL(props.src);
1951
2114
  },
1952
2115
  get ready() {
1953
- const spatializedElement = domProxy.__spatializedElement;
1954
- const promise = spatializedElement.ready.then((success) => {
1955
- if (success) {
1956
- return createLoadSuccessEvent(() => domProxy);
1957
- }
2116
+ return promiseRef.current.then((spatializedElement) => spatializedElement.ready).then((success) => {
2117
+ if (success) return createLoadSuccessEvent(() => domProxy);
1958
2118
  throw createLoadFailureEvent(() => domProxy);
1959
2119
  });
1960
- return promise;
1961
2120
  },
1962
2121
  get entityTransform() {
1963
2122
  return modelTransform;
@@ -1965,7 +2124,7 @@ function SpatializedStatic3DElementContainerBase(props, ref) {
1965
2124
  set entityTransform(value) {
1966
2125
  modelTransform = value;
1967
2126
  const spatializedElement = domProxy.__spatializedElement;
1968
- spatializedElement.updateModelTransform(modelTransform);
2127
+ spatializedElement?.updateModelTransform(modelTransform);
1969
2128
  }
1970
2129
  };
1971
2130
  },
@@ -1974,7 +2133,7 @@ function SpatializedStatic3DElementContainerBase(props, ref) {
1974
2133
  return /* @__PURE__ */ jsx8(
1975
2134
  SpatializedContainer,
1976
2135
  {
1977
- ref: containerRef,
2136
+ ref,
1978
2137
  component: "div",
1979
2138
  createSpatializedElement: createSpatializedElement2,
1980
2139
  spatializedContent: SpatializedContent2,
@@ -2036,10 +2195,10 @@ function initScene(name, callback) {
2036
2195
  import { forwardRef as forwardRef9 } from "react";
2037
2196
 
2038
2197
  // src/spatialized-container-monitor/useMonitorDomChange.tsx
2039
- import { useRef as useRef5, useEffect as useEffect13, useMemo as useMemo4 } from "react";
2198
+ import { useRef as useRef6, useEffect as useEffect14, useMemo as useMemo4 } from "react";
2040
2199
  function useMonitorDomChange(inRef) {
2041
- const ref = useRef5(null);
2042
- useEffect13(() => {
2200
+ const ref = useRef6(null);
2201
+ useEffect14(() => {
2043
2202
  const observer = new MutationObserver((mutationsList) => {
2044
2203
  notifyDOMUpdate(mutationsList);
2045
2204
  });
@@ -2075,9 +2234,9 @@ function useMonitorDomChange(inRef) {
2075
2234
  }
2076
2235
 
2077
2236
  // src/spatialized-container-monitor/useMonitorDocumentHeaderChange.tsx
2078
- import { useEffect as useEffect14 } from "react";
2237
+ import { useEffect as useEffect15 } from "react";
2079
2238
  function useMonitorDocumentHeaderChange() {
2080
- useEffect14(() => {
2239
+ useEffect15(() => {
2081
2240
  const observer = new MutationObserver((mutationsList) => {
2082
2241
  notifyUpdateStandInstanceLayout();
2083
2242
  });
@@ -2137,17 +2296,70 @@ import { forwardRef as forwardRef11 } from "react";
2137
2296
  import { forwardRef as forwardRef10 } from "react";
2138
2297
 
2139
2298
  // src/reality/context/RealityContext.tsx
2140
- import { createContext as createContext5, useContext as useContext9 } from "react";
2141
- var RealityContext = createContext5(null);
2142
- var useRealityContext = () => useContext9(RealityContext);
2299
+ import { createContext as createContext6, useContext as useContext10 } from "react";
2300
+ var RealityContext = createContext6(null);
2301
+ var useRealityContext = () => useContext10(RealityContext);
2143
2302
 
2144
2303
  // src/reality/context/ParentContext.tsx
2145
- import { createContext as createContext6, useContext as useContext10 } from "react";
2146
- var ParentContext = createContext6(null);
2147
- var useParentContext = () => useContext10(ParentContext);
2304
+ import { createContext as createContext7, useContext as useContext11 } from "react";
2305
+ var ParentContext = createContext7(null);
2306
+ var useParentContext = () => useContext11(ParentContext);
2307
+
2308
+ // src/reality/context/AttachmentContext.tsx
2309
+ import { createContext as createContext8, useContext as useContext12 } from "react";
2310
+ var AttachmentRegistry = class {
2311
+ // name → (instanceId → container)
2312
+ containers = /* @__PURE__ */ new Map();
2313
+ listeners = /* @__PURE__ */ new Map();
2314
+ addContainer(name, instanceId, container) {
2315
+ if (!this.containers.has(name)) {
2316
+ this.containers.set(name, /* @__PURE__ */ new Map());
2317
+ }
2318
+ this.containers.get(name).set(instanceId, container);
2319
+ this.notifyListeners(name);
2320
+ }
2321
+ removeContainer(name, instanceId) {
2322
+ this.containers.get(name)?.delete(instanceId);
2323
+ if (this.containers.get(name)?.size === 0) {
2324
+ this.containers.delete(name);
2325
+ }
2326
+ this.notifyListeners(name);
2327
+ }
2328
+ getContainers(name) {
2329
+ const map = this.containers.get(name);
2330
+ if (!map) return [];
2331
+ return Array.from(map, ([instanceId, container]) => ({
2332
+ instanceId,
2333
+ container
2334
+ }));
2335
+ }
2336
+ onContainersChange(name, cb) {
2337
+ const current = this.getContainers(name);
2338
+ if (current.length > 0) {
2339
+ cb(current);
2340
+ }
2341
+ const prev = this.listeners.get(name);
2342
+ if (prev) prev([]);
2343
+ this.listeners.set(name, cb);
2344
+ return () => {
2345
+ if (this.listeners.get(name) === cb) {
2346
+ this.listeners.delete(name);
2347
+ }
2348
+ };
2349
+ }
2350
+ notifyListeners(name) {
2351
+ const cs = this.getContainers(name);
2352
+ this.listeners.get(name)?.(cs);
2353
+ }
2354
+ destroy() {
2355
+ this.containers.clear();
2356
+ this.listeners.clear();
2357
+ }
2358
+ };
2359
+ var AttachmentContext = createContext8(null);
2148
2360
 
2149
2361
  // src/reality/hooks/useEntityTransform.tsx
2150
- import { useEffect as useEffect15, useRef as useRef6 } from "react";
2362
+ import { useEffect as useEffect16, useRef as useRef7 } from "react";
2151
2363
 
2152
2364
  // src/reality/utils/ResourceRegistry.ts
2153
2365
  var ResourceRegistry = class {
@@ -2228,8 +2440,8 @@ var AbortResourceManager = class {
2228
2440
 
2229
2441
  // src/reality/hooks/useEntityTransform.tsx
2230
2442
  function useEntityTransform(entity, { position, rotation, scale }) {
2231
- const last = useRef6({});
2232
- useEffect15(() => {
2443
+ const last = useRef7({});
2444
+ useEffect16(() => {
2233
2445
  if (!entity) return;
2234
2446
  const shouldUpdate = !shallowEqualVec3(last.current.position, position) || !shallowEqualRotation(last.current.rotation, rotation) || !shallowEqualVec3(last.current.scale, scale);
2235
2447
  if (!shouldUpdate) return;
@@ -2248,7 +2460,7 @@ function useEntityTransform(entity, { position, rotation, scale }) {
2248
2460
  }
2249
2461
 
2250
2462
  // src/reality/hooks/useEntityEvent.tsx
2251
- import { useEffect as useEffect17, useRef as useRef8 } from "react";
2463
+ import { useEffect as useEffect18, useRef as useRef9 } from "react";
2252
2464
 
2253
2465
  // src/reality/type.ts
2254
2466
  var eventMap = {
@@ -2259,19 +2471,17 @@ var eventMap = {
2259
2471
  onSpatialDrag: "spatialdrag",
2260
2472
  onSpatialDragEnd: "spatialdragend",
2261
2473
  // rotate
2262
- onSpatialRotateStart: "spatialrotatestart",
2263
2474
  onSpatialRotate: "spatialrotate",
2264
2475
  onSpatialRotateEnd: "spatialrotateend",
2265
2476
  // magnify
2266
- onSpatialMagnifyStart: "spatialmagnifystart",
2267
2477
  onSpatialMagnify: "spatialmagnify",
2268
2478
  onSpatialMagnifyEnd: "spatialmagnifyend"
2269
2479
  };
2270
2480
 
2271
2481
  // src/reality/hooks/useEntityRef.tsx
2272
- import { useImperativeHandle as useImperativeHandle2 } from "react";
2482
+ import { useImperativeHandle } from "react";
2273
2483
  var useEntityRef = (ref, instance) => {
2274
- useImperativeHandle2(ref, () => instance);
2484
+ useImperativeHandle(ref, () => instance);
2275
2485
  };
2276
2486
  var EntityRef = class {
2277
2487
  _entity;
@@ -2338,7 +2548,8 @@ var EntityRef = class {
2338
2548
  }
2339
2549
  };
2340
2550
 
2341
- // src/reality/hooks/useEntityEvent.tsx
2551
+ // src/reality/hooks/useRealityEvents.tsx
2552
+ import { useEffect as useEffect19, useRef as useRef10 } from "react";
2342
2553
  function createEventProxy2(ev, instance) {
2343
2554
  return new Proxy(ev, {
2344
2555
  get(target, prop) {
@@ -2385,44 +2596,99 @@ function createEventProxy2(ev, instance) {
2385
2596
  }
2386
2597
  return void 0;
2387
2598
  }
2599
+ if (prop === "translationX") {
2600
+ const type = target.type;
2601
+ if (type === "spatialdrag") {
2602
+ return target.detail?.translation3D?.x ?? 0;
2603
+ }
2604
+ return void 0;
2605
+ }
2606
+ if (prop === "translationY") {
2607
+ const type = target.type;
2608
+ if (type === "spatialdrag") {
2609
+ return target.detail?.translation3D?.y ?? 0;
2610
+ }
2611
+ return void 0;
2612
+ }
2613
+ if (prop === "translationZ") {
2614
+ const type = target.type;
2615
+ if (type === "spatialdrag") {
2616
+ return target.detail?.translation3D?.z ?? 0;
2617
+ }
2618
+ return void 0;
2619
+ }
2620
+ if (prop === "quaternion") {
2621
+ const type = target.type;
2622
+ if (type === "spatialrotate") {
2623
+ return target.detail?.quaternion ?? {
2624
+ x: 0,
2625
+ y: 0,
2626
+ z: 0,
2627
+ w: 1
2628
+ };
2629
+ }
2630
+ return void 0;
2631
+ }
2632
+ if (prop === "magnification") {
2633
+ const type = target.type;
2634
+ if (type === "spatialmagnify") {
2635
+ return target.detail?.magnification ?? 1;
2636
+ }
2637
+ return void 0;
2638
+ }
2639
+ if (prop === "clientX") {
2640
+ const type = target.type;
2641
+ if (type === "spatialtap" || type === "spatialdragstart") {
2642
+ return target.detail?.globalLocation3D?.x ?? 0;
2643
+ }
2644
+ return void 0;
2645
+ }
2646
+ if (prop === "clientY") {
2647
+ const type = target.type;
2648
+ if (type === "spatialtap" || type === "spatialdragstart") {
2649
+ return target.detail?.globalLocation3D?.y ?? 0;
2650
+ }
2651
+ return void 0;
2652
+ }
2653
+ if (prop === "clientZ") {
2654
+ const type = target.type;
2655
+ if (type === "spatialtap" || type === "spatialdragstart") {
2656
+ return target.detail?.globalLocation3D?.z ?? 0;
2657
+ }
2658
+ return void 0;
2659
+ }
2388
2660
  const val = target[prop];
2389
2661
  return typeof val === "function" ? val.bind(target) : val;
2390
2662
  }
2391
2663
  });
2392
2664
  }
2393
- var useEntityEvent = ({ instance, ...handlers }) => {
2394
- const eventsSetRef = useRef8(/* @__PURE__ */ new Set());
2395
- useEffect17(() => {
2396
- const entity = instance.entity;
2397
- if (!entity) return;
2665
+ var useRealityEvents = ({ instance, ...handlers }) => {
2666
+ const eventsSetRef = useRef10(/* @__PURE__ */ new Set());
2667
+ useEffect19(() => {
2668
+ if (!instance) return;
2398
2669
  Object.entries(eventMap).forEach(([reactKey, spatialEvent]) => {
2399
2670
  const handlerFn = handlers[reactKey];
2400
2671
  if (!handlerFn) return;
2401
2672
  const wrapped = (ev) => handlerFn(createEventProxy2(ev, instance));
2402
- entity.addEvent(spatialEvent, wrapped);
2403
- eventsSetRef.current.add(reactKey);
2673
+ instance.addEvent(spatialEvent, wrapped);
2674
+ eventsSetRef.current.add(spatialEvent);
2404
2675
  });
2405
2676
  return () => {
2406
- };
2407
- }, [instance.entity, ...Object.values(handlers)]);
2408
- useEffect17(() => {
2409
- const entity = instance.entity;
2410
- if (!entity) return;
2411
- return () => {
2412
- for (let x of eventsSetRef.current) {
2413
- entity.removeEvent(x);
2677
+ if (instance) {
2678
+ for (let x of eventsSetRef.current) {
2679
+ instance.removeEvent(x);
2680
+ }
2681
+ eventsSetRef.current.clear();
2414
2682
  }
2415
- eventsSetRef.current.clear();
2416
2683
  };
2417
- }, [instance.entity]);
2418
- return null;
2684
+ }, [instance, ...Object.values(handlers)]);
2419
2685
  };
2420
2686
 
2421
2687
  // src/reality/hooks/useEntityId.tsx
2422
- import { useEffect as useEffect18 } from "react";
2688
+ import { useEffect as useEffect20 } from "react";
2423
2689
  var useEntityId = ({ id, entity }) => {
2424
2690
  const ctx = useRealityContext();
2425
- useEffect18(() => {
2691
+ useEffect20(() => {
2426
2692
  if (!id || !entity || !ctx) return;
2427
2693
  ctx.resourceRegistry.add(id, Promise.resolve(entity));
2428
2694
  return () => {
@@ -2433,31 +2699,21 @@ var useEntityId = ({ id, entity }) => {
2433
2699
  };
2434
2700
 
2435
2701
  // src/reality/hooks/useEntity.tsx
2436
- import { useEffect as useEffect19, useRef as useRef9 } from "react";
2702
+ import { useEffect as useEffect21, useRef as useRef11 } from "react";
2437
2703
  var useEntity = ({
2438
2704
  ref,
2439
2705
  id,
2440
2706
  position,
2441
2707
  rotation,
2442
2708
  scale,
2443
- onSpatialTap,
2444
- onSpatialDragStart,
2445
- onSpatialDrag,
2446
- onSpatialDragEnd,
2447
- // onSpatialRotateStart,
2448
- onSpatialRotate,
2449
- onSpatialRotateEnd,
2450
- // onSpatialMagnifyStart,
2451
- onSpatialMagnify,
2452
- onSpatialMagnifyEnd,
2453
- // TODO: add other event handlers
2709
+ enableInput,
2454
2710
  createEntity
2455
2711
  }) => {
2456
2712
  const ctx = useRealityContext();
2457
2713
  const parent = useParentContext();
2458
- const instanceRef = useRef9(new EntityRef(null, ctx));
2714
+ const instanceRef = useRef11(new EntityRef(null, ctx));
2459
2715
  const forceUpdate = useForceUpdate2();
2460
- useEffect19(() => {
2716
+ useEffect21(() => {
2461
2717
  if (!ctx) return;
2462
2718
  const controller = new AbortController();
2463
2719
  const init = async () => {
@@ -2490,26 +2746,20 @@ var useEntity = ({
2490
2746
  useEntityId({ id, entity: instanceRef.current.entity });
2491
2747
  useEntityTransform(instanceRef.current.entity, { position, rotation, scale });
2492
2748
  useEntityRef(ref, instanceRef.current);
2493
- useEntityEvent({
2494
- instance: instanceRef.current,
2495
- onSpatialTap,
2496
- onSpatialDragStart,
2497
- onSpatialDrag,
2498
- onSpatialDragEnd,
2499
- // onSpatialRotateStart,
2500
- onSpatialRotate,
2501
- onSpatialRotateEnd,
2502
- // onSpatialMagnifyStart,
2503
- onSpatialMagnify,
2504
- onSpatialMagnifyEnd
2505
- });
2749
+ useEffect21(() => {
2750
+ const ent = instanceRef.current.entity;
2751
+ if (!ent) return;
2752
+ if (enableInput !== void 0) {
2753
+ ent.enableInput = !!enableInput;
2754
+ }
2755
+ }, [instanceRef.current.entity, enableInput]);
2506
2756
  return instanceRef.current.entity;
2507
2757
  };
2508
2758
 
2509
2759
  // src/reality/hooks/useForceUpdate.tsx
2510
- import { useCallback as useCallback7, useState as useState8 } from "react";
2760
+ import { useCallback as useCallback7, useState as useState7 } from "react";
2511
2761
  var useForceUpdate2 = () => {
2512
- const [, setTick] = useState8(0);
2762
+ const [, setTick] = useState7(0);
2513
2763
  return useCallback7(() => setTick((tick) => tick + 1), []);
2514
2764
  };
2515
2765
 
@@ -2614,11 +2864,14 @@ var BoxEntity = forwardRef13(
2614
2864
  );
2615
2865
 
2616
2866
  // src/reality/components/UnlitMaterial.tsx
2617
- import { useEffect as useEffect20, useRef as useRef10 } from "react";
2618
- var UnlitMaterial = ({ children, ...options }) => {
2867
+ import { useEffect as useEffect22, useRef as useRef12 } from "react";
2868
+ var UnlitMaterial = ({
2869
+ children,
2870
+ ...options
2871
+ }) => {
2619
2872
  const ctx = useRealityContext();
2620
- const materialRef = useRef10();
2621
- useEffect20(() => {
2873
+ const materialRef = useRef12();
2874
+ useEffect22(() => {
2622
2875
  if (!ctx) return;
2623
2876
  const { session, reality, resourceRegistry } = ctx;
2624
2877
  const init = async () => {
@@ -2734,7 +2987,7 @@ var SceneGraph = ({ children }) => {
2734
2987
  };
2735
2988
 
2736
2989
  // src/reality/components/ModelAsset.tsx
2737
- import { useEffect as useEffect21, useRef as useRef11 } from "react";
2990
+ import { useEffect as useEffect23, useRef as useRef13 } from "react";
2738
2991
  var resolveAssetUrl = (url) => {
2739
2992
  if (url.startsWith("http://") || url.startsWith("https://")) {
2740
2993
  return url;
@@ -2743,8 +2996,8 @@ var resolveAssetUrl = (url) => {
2743
2996
  };
2744
2997
  var ModelAsset = ({ children, ...options }) => {
2745
2998
  const ctx = useRealityContext();
2746
- const materialRef = useRef11();
2747
- useEffect21(() => {
2999
+ const materialRef = useRef13();
3000
+ useEffect23(() => {
2748
3001
  const controller = new AbortController();
2749
3002
  if (!ctx) return;
2750
3003
  const { session, reality, resourceRegistry } = ctx;
@@ -2811,13 +3064,20 @@ var ModelEntity = forwardRef18(
2811
3064
  import {
2812
3065
  forwardRef as forwardRef19,
2813
3066
  useCallback as useCallback8,
2814
- useEffect as useEffect22,
2815
- useRef as useRef12,
2816
- useState as useState9
3067
+ useEffect as useEffect24,
3068
+ useRef as useRef14,
3069
+ useState as useState8
2817
3070
  } from "react";
2818
3071
  import { Fragment as Fragment3, jsx as jsx22, jsxs as jsxs3 } from "react/jsx-runtime";
2819
3072
  var Reality = forwardRef19(
2820
3073
  function RealityBase({ children, ...inProps }, ref) {
3074
+ const insideAttachment = useInsideAttachment();
3075
+ if (insideAttachment) {
3076
+ console.warn(
3077
+ "[WebSpatial] Reality cannot be used inside AttachmentAsset."
3078
+ );
3079
+ return null;
3080
+ }
2821
3081
  const {
2822
3082
  onSpatialTap,
2823
3083
  onSpatialDragStart,
@@ -2829,16 +3089,17 @@ var Reality = forwardRef19(
2829
3089
  onSpatialMagnifyEnd,
2830
3090
  ...props
2831
3091
  } = inProps;
2832
- const ctxRef = useRef12(null);
2833
- const creationId = useRef12(0);
2834
- const [isReady, setIsReady] = useState9(false);
3092
+ const ctxRef = useRef14(null);
3093
+ const creationId = useRef14(0);
3094
+ const [isReady, setIsReady] = useState8(false);
2835
3095
  const cleanupReality = useCallback8(() => {
3096
+ ctxRef.current?.attachmentRegistry.destroy();
2836
3097
  ctxRef.current?.resourceRegistry.destroy();
2837
3098
  ctxRef.current?.reality.destroy();
2838
3099
  ctxRef.current = null;
2839
3100
  setIsReady(false);
2840
3101
  }, []);
2841
- useEffect22(() => {
3102
+ useEffect24(() => {
2842
3103
  return () => {
2843
3104
  creationId.current++;
2844
3105
  cleanupReality();
@@ -2847,15 +3108,18 @@ var Reality = forwardRef19(
2847
3108
  const createReality = useCallback8(async () => {
2848
3109
  const id = ++creationId.current;
2849
3110
  const resourceRegistry = new ResourceRegistry();
3111
+ const attachmentRegistry = new AttachmentRegistry();
2850
3112
  const session = await getSession();
2851
3113
  if (!session) {
2852
3114
  resourceRegistry.destroy();
3115
+ attachmentRegistry.destroy();
2853
3116
  return null;
2854
3117
  }
2855
3118
  const reality = await session.createSpatializedDynamic3DElement();
2856
3119
  const isCancelled = () => id !== creationId.current;
2857
3120
  if (isCancelled()) {
2858
3121
  resourceRegistry.destroy();
3122
+ attachmentRegistry.destroy();
2859
3123
  reality.destroy();
2860
3124
  return null;
2861
3125
  }
@@ -2863,21 +3127,39 @@ var Reality = forwardRef19(
2863
3127
  const result = await session.getSpatialScene().addSpatializedElement(reality);
2864
3128
  if (!result.success || isCancelled()) {
2865
3129
  resourceRegistry.destroy();
3130
+ attachmentRegistry.destroy();
2866
3131
  reality.destroy();
2867
3132
  return null;
2868
3133
  }
2869
3134
  cleanupReality();
2870
- ctxRef.current = { session, reality, resourceRegistry };
3135
+ ctxRef.current = {
3136
+ session,
3137
+ reality,
3138
+ resourceRegistry,
3139
+ attachmentRegistry
3140
+ };
2871
3141
  setIsReady(true);
2872
3142
  return reality;
2873
3143
  } catch (err) {
2874
3144
  console.error("[createReality] failed", err);
2875
3145
  resourceRegistry.destroy();
3146
+ attachmentRegistry.destroy();
2876
3147
  reality.destroy();
2877
3148
  return null;
2878
3149
  }
2879
3150
  }, [cleanupReality]);
2880
3151
  const content = useCallback8(() => /* @__PURE__ */ jsx22(Fragment3, {}), []);
3152
+ useRealityEvents({
3153
+ instance: ctxRef.current?.reality ?? null,
3154
+ onSpatialTap,
3155
+ onSpatialDragStart,
3156
+ onSpatialDrag,
3157
+ onSpatialDragEnd,
3158
+ onSpatialRotate,
3159
+ onSpatialRotateEnd,
3160
+ onSpatialMagnify,
3161
+ onSpatialMagnifyEnd
3162
+ });
2881
3163
  return /* @__PURE__ */ jsxs3(RealityContext.Provider, { value: ctxRef.current, children: [
2882
3164
  /* @__PURE__ */ jsx22(
2883
3165
  SpatializedContainer,
@@ -2894,13 +3176,145 @@ var Reality = forwardRef19(
2894
3176
  }
2895
3177
  );
2896
3178
 
3179
+ // src/reality/components/AttachmentAsset.tsx
3180
+ import { useEffect as useEffect25, useState as useState9 } from "react";
3181
+ import { createPortal as createPortal3 } from "react-dom";
3182
+ import { jsx as jsx23 } from "react/jsx-runtime";
3183
+ var AttachmentAsset = ({
3184
+ name,
3185
+ children
3186
+ }) => {
3187
+ const ctx = useRealityContext();
3188
+ const [containers, setContainers] = useState9([]);
3189
+ useEffect25(() => {
3190
+ if (!ctx) return;
3191
+ return ctx.attachmentRegistry.onContainersChange(name, setContainers);
3192
+ }, [ctx, name]);
3193
+ if (!containers.length) return null;
3194
+ return /* @__PURE__ */ jsx23(InsideAttachmentContext.Provider, { value: true, children: containers.map(
3195
+ ({ instanceId, container }) => createPortal3(children, container, instanceId)
3196
+ ) });
3197
+ };
3198
+
3199
+ // src/reality/components/AttachmentEntity.tsx
3200
+ import { useEffect as useEffect26, useRef as useRef15, useState as useState10 } from "react";
3201
+ var instanceCounter = 0;
3202
+ var AttachmentEntity = ({
3203
+ attachment: attachmentName,
3204
+ position,
3205
+ size
3206
+ }) => {
3207
+ const ctx = useRealityContext();
3208
+ const parent = useParentContext();
3209
+ const attachmentRef = useRef15(null);
3210
+ const parentIdRef = useRef15(null);
3211
+ const instanceIdRef = useRef15(`att_${++instanceCounter}`);
3212
+ const attachmentNameRef = useRef15(attachmentName);
3213
+ const [childWindow, setChildWindow] = useState10(null);
3214
+ useEffect26(() => {
3215
+ if (!ctx || !parent) return;
3216
+ if (attachmentRef.current) return;
3217
+ const parentId = parent.id;
3218
+ parentIdRef.current = parentId;
3219
+ let cancelled = false;
3220
+ const init = async () => {
3221
+ try {
3222
+ const att = await ctx.session.createAttachmentEntity({
3223
+ parentEntityId: parentId,
3224
+ position: position ?? [0, 0, 0],
3225
+ size,
3226
+ ownerViewId: ctx.reality.id
3227
+ });
3228
+ if (cancelled) {
3229
+ att.destroy();
3230
+ return;
3231
+ }
3232
+ const windowProxy = att.getWindowProxy();
3233
+ setOpenWindowStyle(windowProxy);
3234
+ windowProxy.document.body.style.display = "block";
3235
+ windowProxy.document.body.style.minWidth = "100%";
3236
+ windowProxy.document.body.style.maxWidth = "100%";
3237
+ windowProxy.document.body.style.minHeight = "100%";
3238
+ const viewport = windowProxy.document.querySelector(
3239
+ 'meta[name="viewport"]'
3240
+ );
3241
+ if (!viewport) {
3242
+ const meta = windowProxy.document.createElement("meta");
3243
+ meta.name = "viewport";
3244
+ meta.content = "width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no";
3245
+ windowProxy.document.head.appendChild(meta);
3246
+ }
3247
+ const base = windowProxy.document.createElement("base");
3248
+ base.href = document.baseURI;
3249
+ windowProxy.document.head.appendChild(base);
3250
+ attachmentRef.current = att;
3251
+ setChildWindow(windowProxy);
3252
+ ctx.attachmentRegistry.addContainer(
3253
+ attachmentNameRef.current,
3254
+ instanceIdRef.current,
3255
+ att.getContainer()
3256
+ );
3257
+ } catch (error) {
3258
+ console.error("[AttachmentEntity] init error:", error);
3259
+ }
3260
+ };
3261
+ init();
3262
+ return () => {
3263
+ cancelled = true;
3264
+ const att = attachmentRef.current;
3265
+ if (att) {
3266
+ ctx.attachmentRegistry.removeContainer(
3267
+ attachmentNameRef.current,
3268
+ instanceIdRef.current
3269
+ );
3270
+ att.destroy();
3271
+ attachmentRef.current = null;
3272
+ setChildWindow(null);
3273
+ }
3274
+ };
3275
+ }, [ctx, parent]);
3276
+ useEffect26(() => {
3277
+ if (!ctx) return;
3278
+ const att = attachmentRef.current;
3279
+ const prevName = attachmentNameRef.current;
3280
+ if (att && prevName !== attachmentName) {
3281
+ ctx.attachmentRegistry.removeContainer(prevName, instanceIdRef.current);
3282
+ ctx.attachmentRegistry.addContainer(
3283
+ attachmentName,
3284
+ instanceIdRef.current,
3285
+ att.getContainer()
3286
+ );
3287
+ attachmentNameRef.current = attachmentName;
3288
+ } else {
3289
+ attachmentNameRef.current = attachmentName;
3290
+ }
3291
+ }, [ctx, attachmentName]);
3292
+ useSyncHeadStyles(childWindow, { subtree: false });
3293
+ useEffect26(() => {
3294
+ if (!attachmentRef.current) return;
3295
+ attachmentRef.current.update({ position, size });
3296
+ }, [position?.[0], position?.[1], position?.[2], size?.width, size?.height]);
3297
+ return null;
3298
+ };
3299
+
3300
+ // src/reality/components/Material.tsx
3301
+ import { jsx as jsx24 } from "react/jsx-runtime";
3302
+ var Material = (props) => {
3303
+ if (props.type === "unlit") {
3304
+ const { type, ...rest } = props;
3305
+ return /* @__PURE__ */ jsx24(UnlitMaterial, { ...rest });
3306
+ }
3307
+ return null;
3308
+ };
3309
+
2897
3310
  // src/Model.tsx
2898
3311
  import { forwardRef as forwardRef20 } from "react";
2899
- import { jsx as jsx23 } from "react/jsx-runtime";
3312
+ import { jsx as jsx25 } from "react/jsx-runtime";
2900
3313
  var spatial2 = new Spatial();
2901
3314
  function ModelBase(props, ref) {
3315
+ const insideAttachment = useInsideAttachment();
2902
3316
  const { "enable-xr": enableXR, ...restProps } = props;
2903
- if (!enableXR || !spatial2.runInSpatialWeb()) {
3317
+ if (!enableXR || !spatial2.runInSpatialWeb() || insideAttachment) {
2904
3318
  const {
2905
3319
  onSpatialTap,
2906
3320
  onSpatialDragStart,
@@ -2910,28 +3324,125 @@ function ModelBase(props, ref) {
2910
3324
  onSpatialRotateEnd,
2911
3325
  onSpatialMagnify,
2912
3326
  onSpatialMagnifyEnd,
3327
+ spatialEventOptions: _spatialEventOptions,
2913
3328
  ...modelProps
2914
3329
  } = restProps;
2915
- return /* @__PURE__ */ jsx23("model", { ref, ...modelProps });
3330
+ return /* @__PURE__ */ jsx25("model", { ref, ...modelProps });
2916
3331
  }
2917
- return /* @__PURE__ */ jsx23(SpatializedStatic3DElementContainer, { ref, ...restProps });
3332
+ return /* @__PURE__ */ jsx25(SpatializedStatic3DElementContainer, { ref, ...restProps });
2918
3333
  }
2919
3334
  var Model = withSSRSupported(forwardRef20(ModelBase));
2920
3335
  Model.displayName = "Model";
2921
3336
 
3337
+ // src/useMetrics.tsx
3338
+ import { useSyncExternalStore } from "react";
3339
+ function useMetrics() {
3340
+ useSyncExternalStore(PhysicalMetrics.subscribe, PhysicalMetrics.getValue);
3341
+ const { pointToPhysical, physicalToPoint } = PhysicalMetrics;
3342
+ return { pointToPhysical, physicalToPoint };
3343
+ }
3344
+
3345
+ // src/jsx/jsx-shared.ts
3346
+ import { jsxDEV as _jsxDEV } from "react/jsx-dev-runtime";
3347
+ import reactJSXRuntime from "react/jsx-runtime";
3348
+ import { createElement as reactCreateElement } from "react";
3349
+ var attributeFlag = "enable-xr";
3350
+ var styleFlag = "enableXr";
3351
+ var classFlag = "__enableXr__";
3352
+ var xrMonitorFlag = "enable-xr-monitor";
3353
+ function replaceToSpatialPrimitiveType(type, props) {
3354
+ if (type === Model) {
3355
+ return type;
3356
+ }
3357
+ const propsObject = props;
3358
+ if (attributeFlag in propsObject) {
3359
+ delete propsObject[attributeFlag];
3360
+ return withSpatialized2DElementContainer(type);
3361
+ }
3362
+ if (xrMonitorFlag in propsObject) {
3363
+ delete propsObject[xrMonitorFlag];
3364
+ return withSpatialMonitor(type);
3365
+ }
3366
+ if (propsObject && propsObject.style && styleFlag in propsObject.style) {
3367
+ delete propsObject.style[styleFlag];
3368
+ return withSpatialized2DElementContainer(type);
3369
+ }
3370
+ if (propsObject && typeof propsObject.className === "string") {
3371
+ const originalClassNames = propsObject.className.split(" ");
3372
+ const idx = originalClassNames.indexOf(classFlag);
3373
+ if (idx !== -1) {
3374
+ originalClassNames.splice(idx, 1);
3375
+ propsObject.className = originalClassNames.join(" ");
3376
+ return withSpatialized2DElementContainer(type);
3377
+ }
3378
+ }
3379
+ return type;
3380
+ }
3381
+ function createElement(...args) {
3382
+ const [type, props, ...rest] = args;
3383
+ const newType = replaceToSpatialPrimitiveType(type, props);
3384
+ return reactCreateElement(newType, props, ...rest);
3385
+ }
3386
+
3387
+ // src/utils/convertCoordinate.ts
3388
+ function resolveSpatialObjectId(target) {
3389
+ if (typeof window !== "undefined" && target === window) {
3390
+ const scene = getSession()?.getSpatialScene();
3391
+ return scene?.id ?? "";
3392
+ }
3393
+ const maybeEntity = target;
3394
+ if (maybeEntity && typeof maybeEntity === "object" && "entity" in maybeEntity) {
3395
+ return maybeEntity.entity?.id ?? null;
3396
+ }
3397
+ const dom = target?.__raw ?? target;
3398
+ if (dom && typeof dom === "object") {
3399
+ const spatializedElement = dom.__spatializedElement ?? dom.__innerSpatializedElement?.();
3400
+ if (spatializedElement && spatializedElement.id) {
3401
+ return spatializedElement.id;
3402
+ }
3403
+ }
3404
+ return null;
3405
+ }
3406
+ async function convertCoordinate(position, { from, to }) {
3407
+ try {
3408
+ const fromId = resolveSpatialObjectId(from);
3409
+ const toId = resolveSpatialObjectId(to);
3410
+ if (fromId === null || toId === null) {
3411
+ console.warn(
3412
+ "convertCoordinate error: from or to is not a valid coordinate convertible"
3413
+ );
3414
+ return position;
3415
+ }
3416
+ const spatialScene = getSession()?.getSpatialScene();
3417
+ if (!spatialScene) return position;
3418
+ const ret = await spatialScene.convertCoordinate(position, fromId, toId);
3419
+ return ret ?? position;
3420
+ } catch (error) {
3421
+ console.warn("convertCoordinate error:", error);
3422
+ return position;
3423
+ }
3424
+ }
3425
+
2922
3426
  // src/index.ts
2923
- var version = "1.2.1";
3427
+ var version = "1.4.0";
2924
3428
  if (typeof window !== "undefined") {
2925
3429
  initPolyfill();
2926
3430
  }
2927
3431
  export {
3432
+ AttachmentAsset,
3433
+ AttachmentEntity,
3434
+ BoxEntity as Box,
2928
3435
  BoxEntity,
3436
+ ConeEntity as Cone,
2929
3437
  ConeEntity,
3438
+ CylinderEntity as Cylinder,
2930
3439
  CylinderEntity,
2931
3440
  Entity,
3441
+ Material,
2932
3442
  Model,
2933
3443
  ModelAsset,
2934
3444
  ModelEntity,
3445
+ PlaneEntity as Plane,
2935
3446
  PlaneEntity,
2936
3447
  Reality,
2937
3448
  SSRProvider,
@@ -2940,14 +3451,17 @@ export {
2940
3451
  Spatialized2DElementContainer,
2941
3452
  SpatializedContainer,
2942
3453
  SpatializedStatic3DElementContainer,
3454
+ SphereEntity as Sphere,
2943
3455
  SphereEntity,
2944
3456
  UnlitMaterial,
3457
+ SceneGraph as World,
3458
+ convertCoordinate,
3459
+ createElement,
2945
3460
  enableDebugTool,
2946
3461
  eventMap,
2947
3462
  initPolyfill,
2948
3463
  initScene,
2949
- toLocalSpace,
2950
- toSceneSpatial,
3464
+ useMetrics,
2951
3465
  version,
2952
3466
  withSpatialMonitor,
2953
3467
  withSpatialized2DElementContainer