@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.
@@ -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'] = "avp"
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/utils/getSession.ts
855
849
  import { isSSREnv, Spatial } from "@webspatial/core-sdk";
@@ -897,37 +891,6 @@ function enableDebugTool() {
897
891
  });
898
892
  }
899
893
 
900
- // src/spatialized-container/transform-utils.ts
901
- function toSceneSpatial(point, spatializedElement) {
902
- return spatializedElement.__toSceneSpace(point);
903
- }
904
- function toLocalSpace(point, spatializedElement) {
905
- return spatializedElement.__toLocalSpace(point);
906
- }
907
- function convertDOMRectToSceneSpace(originalRect, matrix) {
908
- const topLeft = new DOMPoint(originalRect.left, originalRect.top);
909
- const topRight = new DOMPoint(originalRect.right, originalRect.top);
910
- const bottomRight = new DOMPoint(originalRect.right, originalRect.bottom);
911
- const bottomLeft = new DOMPoint(originalRect.left, originalRect.bottom);
912
- const transformedTopLeft = matrix.transformPoint(topLeft);
913
- const transformedTopRight = matrix.transformPoint(topRight);
914
- const transformedBottomRight = matrix.transformPoint(bottomRight);
915
- const transformedBottomLeft = matrix.transformPoint(bottomLeft);
916
- const allPoints = [
917
- transformedTopLeft,
918
- transformedTopRight,
919
- transformedBottomRight,
920
- transformedBottomLeft
921
- ];
922
- const xCoords = allPoints.map((point) => point.x);
923
- const yCoords = allPoints.map((point) => point.y);
924
- const newMinX = Math.min(...xCoords);
925
- const newMaxX = Math.max(...xCoords);
926
- const newMinY = Math.min(...yCoords);
927
- const newMaxY = Math.max(...yCoords);
928
- return new DOMRect(newMinX, newMinY, newMaxX - newMinX, newMaxY - newMinY);
929
- }
930
-
931
894
  // src/spatialized-container/context/PortalInstanceContext.ts
932
895
  var PortalInstanceObject = class {
933
896
  spatialId;
@@ -1012,40 +975,8 @@ var PortalInstanceObject = class {
1012
975
  isFixedPosition: computedStyle.getPropertyValue("position") === "fixed"
1013
976
  };
1014
977
  this.updateSpatializedElementProperties();
1015
- const __getBoundingClientCube = () => {
1016
- return this.spatializedElement?.cubeInfo;
1017
- };
1018
- const __getBoundingClientRect = () => {
1019
- if (!this.spatializedElement?.transform) {
1020
- return null;
1021
- }
1022
- const domRect = new DOMRect(
1023
- 0,
1024
- 0,
1025
- this.domRect?.width,
1026
- this.domRect?.height
1027
- );
1028
- return convertDOMRectToSceneSpace(
1029
- domRect,
1030
- this.spatializedElement?.transform
1031
- );
1032
- };
1033
- const __toSceneSpace = (point) => {
1034
- return new DOMPoint(point.x, point.y, point.z).matrixTransform(
1035
- this.spatializedElement?.transform
1036
- );
1037
- };
1038
- const __toLocalSpace = (point) => {
1039
- return new DOMPoint(point.x, point.y, point.z).matrixTransform(
1040
- this.spatializedElement?.transformInv
1041
- );
1042
- };
1043
978
  const __innerSpatializedElement = () => this.spatializedElement;
1044
979
  Object.assign(dom, {
1045
- __getBoundingClientCube,
1046
- __getBoundingClientRect,
1047
- __toSceneSpace,
1048
- __toLocalSpace,
1049
980
  __innerSpatializedElement
1050
981
  });
1051
982
  }
@@ -1163,18 +1094,19 @@ function useSync2DFrame(spatialId, portalInstanceObject, spatializedContainerObj
1163
1094
  }
1164
1095
 
1165
1096
  // src/spatialized-container/hooks/useSpatializedElement.ts
1166
- import { useEffect as useEffect6, useState as useState3 } from "react";
1097
+ import { useEffect as useEffect6, useRef as useRef4, useState as useState3 } from "react";
1167
1098
  function useSpatializedElement(createSpatializedElement2, portalInstanceObject) {
1168
1099
  const [spatializedElement, setSpatializedElement] = useState3();
1100
+ const elementRef = useRef4(void 0);
1169
1101
  useEffect6(() => {
1170
1102
  let isDestroyed = false;
1171
- let spatializedElement2;
1172
1103
  createSpatializedElement2().then(
1173
1104
  (inSpatializedElement) => {
1105
+ if (!inSpatializedElement) return;
1174
1106
  if (!isDestroyed) {
1175
- spatializedElement2 = inSpatializedElement;
1176
- portalInstanceObject.attachSpatializedElement(spatializedElement2);
1177
- setSpatializedElement(spatializedElement2);
1107
+ elementRef.current = inSpatializedElement;
1108
+ portalInstanceObject.attachSpatializedElement(inSpatializedElement);
1109
+ setSpatializedElement(inSpatializedElement);
1178
1110
  } else {
1179
1111
  inSpatializedElement?.destroy();
1180
1112
  }
@@ -1182,9 +1114,11 @@ function useSpatializedElement(createSpatializedElement2, portalInstanceObject)
1182
1114
  );
1183
1115
  return () => {
1184
1116
  isDestroyed = true;
1185
- if (spatializedElement2) {
1186
- spatializedElement2.destroy();
1187
- spatializedElement2 = void 0;
1117
+ const el = elementRef.current;
1118
+ if (el) {
1119
+ el.destroy();
1120
+ elementRef.current = void 0;
1121
+ setSpatializedElement(void 0);
1188
1122
  }
1189
1123
  };
1190
1124
  }, [createSpatializedElement2, portalInstanceObject]);
@@ -1193,6 +1127,18 @@ function useSpatializedElement(createSpatializedElement2, portalInstanceObject)
1193
1127
 
1194
1128
  // src/spatialized-container/PortalSpatializedContainer.tsx
1195
1129
  import { Fragment, jsx as jsx3, jsxs } from "react/jsx-runtime";
1130
+ function constrainedAxisToVec3(input) {
1131
+ if (input == null) return { x: 0, y: 0, z: 0 };
1132
+ if (Array.isArray(input)) {
1133
+ return { x: input[0] ?? 0, y: input[1] ?? 0, z: input[2] ?? 0 };
1134
+ }
1135
+ const v = input;
1136
+ return { x: v.x, y: v.y, z: v.z };
1137
+ }
1138
+ function constrainedAxisKey(input) {
1139
+ const v = constrainedAxisToVec3(input);
1140
+ return `${v.x},${v.y},${v.z}`;
1141
+ }
1196
1142
  function renderPlaceholderInSubPortal(portalInstanceObject, El) {
1197
1143
  const spatialId = portalInstanceObject.spatialId;
1198
1144
  const inPortalInstanceEnv = !!portalInstanceObject.parentPortalInstanceObject;
@@ -1231,6 +1177,7 @@ function PortalSpatializedContainer(props) {
1231
1177
  onSpatialRotateEnd,
1232
1178
  onSpatialMagnify,
1233
1179
  onSpatialMagnifyEnd,
1180
+ spatialEventOptions,
1234
1181
  [SpatialID]: spatialId,
1235
1182
  ...restProps
1236
1183
  } = props;
@@ -1302,14 +1249,27 @@ function PortalSpatializedContainer(props) {
1302
1249
  spatializedElement.onSpatialDragStart = onSpatialDragStart;
1303
1250
  }
1304
1251
  }, [spatializedElement, onSpatialDragStart]);
1252
+ const rotateConstraintKey = constrainedAxisKey(
1253
+ spatialEventOptions?.constrainedToAxis
1254
+ );
1255
+ useEffect7(() => {
1256
+ if (!spatializedElement) return;
1257
+ const axis = constrainedAxisToVec3(spatialEventOptions?.constrainedToAxis);
1258
+ void spatializedElement.updateProperties({ rotateConstrainedToAxis: axis });
1259
+ }, [spatializedElement, rotateConstraintKey]);
1305
1260
  return /* @__PURE__ */ jsxs(PortalInstanceContext.Provider, { value: portalInstanceObject, children: [
1306
1261
  spatializedElement && portalInstanceObject.dom && /* @__PURE__ */ jsx3(Content, { spatializedElement, ...restProps }),
1307
1262
  PlaceholderEl
1308
1263
  ] });
1309
1264
  }
1310
1265
 
1266
+ // src/reality/context/InsideAttachmentContext.tsx
1267
+ import { createContext as createContext4, useContext as useContext5 } from "react";
1268
+ var InsideAttachmentContext = createContext4(false);
1269
+ var useInsideAttachment = () => useContext5(InsideAttachmentContext);
1270
+
1311
1271
  // src/spatialized-container/hooks/useSpatialEvents.ts
1312
- function createEventProxy(event, currentTargetGetter, offsetXGetter, offsetYGetter, offsetZGetter) {
1272
+ function createEventProxy(event, currentTargetGetter, offsetXGetter, offsetYGetter, offsetZGetter, clientXGetter, clientYGetter, clientZGetter, translationXGetter, translationYGetter, translationZGetter, quaternionGetter, magnificationGetter) {
1313
1273
  return new Proxy(event, {
1314
1274
  get(target, prop) {
1315
1275
  if (prop === "currentTarget") {
@@ -1330,18 +1290,50 @@ function createEventProxy(event, currentTargetGetter, offsetXGetter, offsetYGett
1330
1290
  if (prop === "offsetZ" && offsetZGetter) {
1331
1291
  return offsetZGetter(target) ?? 0;
1332
1292
  }
1293
+ if (prop === "clientX" && clientXGetter) {
1294
+ return clientXGetter(target) ?? 0;
1295
+ }
1296
+ if (prop === "clientY" && clientYGetter) {
1297
+ return clientYGetter(target) ?? 0;
1298
+ }
1299
+ if (prop === "clientZ" && clientZGetter) {
1300
+ return clientZGetter(target) ?? 0;
1301
+ }
1302
+ if (prop === "translationX" && translationXGetter) {
1303
+ return translationXGetter(target) ?? 0;
1304
+ }
1305
+ if (prop === "translationY" && translationYGetter) {
1306
+ return translationYGetter(target) ?? 0;
1307
+ }
1308
+ if (prop === "translationZ" && translationZGetter) {
1309
+ return translationZGetter(target) ?? 0;
1310
+ }
1311
+ if (prop === "quaternion" && quaternionGetter) {
1312
+ return quaternionGetter(target) ?? { x: 0, y: 0, z: 0, w: 1 };
1313
+ }
1314
+ if (prop === "magnification" && magnificationGetter) {
1315
+ return magnificationGetter(target) ?? 1;
1316
+ }
1333
1317
  return Reflect.get(target, prop);
1334
1318
  }
1335
1319
  });
1336
1320
  }
1337
- function createEventHandler(handler, currentTargetGetter, offsetXGetter, offsetYGetter, offsetZGetter) {
1321
+ function createEventHandler(handler, currentTargetGetter, offsetXGetter, offsetYGetter, offsetZGetter, clientXGetter, clientYGetter, clientZGetter, translationXGetter, translationYGetter, translationZGetter, quaternionGetter, magnificationGetter) {
1338
1322
  return handler ? (event) => {
1339
1323
  const proxyEvent = createEventProxy(
1340
1324
  event,
1341
1325
  currentTargetGetter,
1342
1326
  offsetXGetter,
1343
1327
  offsetYGetter,
1344
- offsetZGetter
1328
+ offsetZGetter,
1329
+ clientXGetter,
1330
+ clientYGetter,
1331
+ clientZGetter,
1332
+ translationXGetter,
1333
+ translationYGetter,
1334
+ translationZGetter,
1335
+ quaternionGetter,
1336
+ magnificationGetter
1345
1337
  );
1346
1338
  handler(proxyEvent);
1347
1339
  } : void 0;
@@ -1350,13 +1342,27 @@ function useSpatialEventsBase(spatialEvents, currentTargetGetter) {
1350
1342
  const onSpatialTap = createEventHandler(
1351
1343
  spatialEvents.onSpatialTap,
1352
1344
  currentTargetGetter,
1345
+ // offsetX/Y/Z come from local coordinates
1353
1346
  (ev) => ev.detail?.location3D?.x,
1354
1347
  (ev) => ev.detail?.location3D?.y,
1355
- (ev) => ev.detail?.location3D?.z
1348
+ (ev) => ev.detail?.location3D?.z,
1349
+ // clientX/Y/Z come from global scene coordinates
1350
+ (ev) => ev.detail?.globalLocation3D?.x,
1351
+ (ev) => ev.detail?.globalLocation3D?.y,
1352
+ (ev) => ev.detail?.globalLocation3D?.z
1356
1353
  );
1357
1354
  const onSpatialDrag = createEventHandler(
1358
1355
  spatialEvents.onSpatialDrag,
1359
- currentTargetGetter
1356
+ currentTargetGetter,
1357
+ void 0,
1358
+ void 0,
1359
+ void 0,
1360
+ void 0,
1361
+ void 0,
1362
+ void 0,
1363
+ (ev) => ev.detail?.translation3D?.x,
1364
+ (ev) => ev.detail?.translation3D?.y,
1365
+ (ev) => ev.detail?.translation3D?.z
1360
1366
  );
1361
1367
  const onSpatialDragEnd = createEventHandler(
1362
1368
  spatialEvents.onSpatialDragEnd,
@@ -1364,7 +1370,17 @@ function useSpatialEventsBase(spatialEvents, currentTargetGetter) {
1364
1370
  );
1365
1371
  const onSpatialRotate = createEventHandler(
1366
1372
  spatialEvents.onSpatialRotate,
1367
- currentTargetGetter
1373
+ currentTargetGetter,
1374
+ void 0,
1375
+ void 0,
1376
+ void 0,
1377
+ void 0,
1378
+ void 0,
1379
+ void 0,
1380
+ void 0,
1381
+ void 0,
1382
+ void 0,
1383
+ (ev) => ev.detail?.quaternion
1368
1384
  );
1369
1385
  const onSpatialRotateEnd = createEventHandler(
1370
1386
  spatialEvents.onSpatialRotateEnd,
@@ -1372,7 +1388,18 @@ function useSpatialEventsBase(spatialEvents, currentTargetGetter) {
1372
1388
  );
1373
1389
  const onSpatialMagnify = createEventHandler(
1374
1390
  spatialEvents.onSpatialMagnify,
1375
- currentTargetGetter
1391
+ currentTargetGetter,
1392
+ void 0,
1393
+ void 0,
1394
+ void 0,
1395
+ void 0,
1396
+ void 0,
1397
+ void 0,
1398
+ void 0,
1399
+ void 0,
1400
+ void 0,
1401
+ void 0,
1402
+ (ev) => ev.detail?.magnification
1376
1403
  );
1377
1404
  const onSpatialMagnifyEnd = createEventHandler(
1378
1405
  spatialEvents.onSpatialMagnifyEnd,
@@ -1383,7 +1410,10 @@ function useSpatialEventsBase(spatialEvents, currentTargetGetter) {
1383
1410
  currentTargetGetter,
1384
1411
  (ev) => ev.detail?.startLocation3D?.x,
1385
1412
  (ev) => ev.detail?.startLocation3D?.y,
1386
- (ev) => ev.detail?.startLocation3D?.z
1413
+ (ev) => ev.detail?.startLocation3D?.z,
1414
+ (ev) => ev.detail?.globalLocation3D?.x,
1415
+ (ev) => ev.detail?.globalLocation3D?.y,
1416
+ (ev) => ev.detail?.globalLocation3D?.z
1387
1417
  );
1388
1418
  return {
1389
1419
  onSpatialTap,
@@ -1412,9 +1442,9 @@ function useSpatialEventsWhenSpatializedContainerExist(spatialEvents, spatialId,
1412
1442
  }
1413
1443
 
1414
1444
  // src/ssr/SSRContext.tsx
1415
- import { createContext as createContext4, useState as useState4, useEffect as useEffect8 } from "react";
1445
+ import { createContext as createContext5, useState as useState4, useEffect as useEffect8 } from "react";
1416
1446
  import { jsx as jsx4 } from "react/jsx-runtime";
1417
- var SSRContext = createContext4(false);
1447
+ var SSRContext = createContext5(false);
1418
1448
  var SSRProvider = ({
1419
1449
  isSSR: initialIsSSR = true,
1420
1450
  children
@@ -1432,9 +1462,9 @@ var SSRProvider = ({
1432
1462
  import { forwardRef as forwardRef3 } from "react";
1433
1463
 
1434
1464
  // src/ssr/useSSRPhase.tsx
1435
- import { useContext as useContext5, useState as useState5, useEffect as useEffect9 } from "react";
1465
+ import { useContext as useContext6, useState as useState5, useEffect as useEffect9 } from "react";
1436
1466
  function useSSRPhase() {
1437
- const isSSRContext = useContext5(SSRContext);
1467
+ const isSSRContext = useContext6(SSRContext);
1438
1468
  const isServer = typeof window === "undefined";
1439
1469
  const [hydrated, setHydrated] = useState5(false);
1440
1470
  useEffect9(() => setHydrated(true), []);
@@ -1470,33 +1500,49 @@ function withSSRSupported(Component) {
1470
1500
 
1471
1501
  // src/spatialized-container/SpatializedContainer.tsx
1472
1502
  import { jsx as jsx6, jsxs as jsxs2 } from "react/jsx-runtime";
1503
+ function DegradedContainer({
1504
+ innerRef,
1505
+ ...inprops
1506
+ }) {
1507
+ const {
1508
+ component: Component,
1509
+ children,
1510
+ ["enable-xr"]: _enableXR,
1511
+ onSpatialTap: _onSpatialTap,
1512
+ onSpatialDragStart: _onSpatialDragStart,
1513
+ onSpatialDrag: _onSpatialDrag,
1514
+ onSpatialDragEnd: _onSpatialDragEnd,
1515
+ onSpatialRotate: _onSpatialRotate,
1516
+ onSpatialRotateEnd: _onSpatialRotateEnd,
1517
+ onSpatialMagnify: _onSpatialMagnify,
1518
+ onSpatialMagnifyEnd: _onSpatialMagnifyEnd,
1519
+ spatialEventOptions: _spatialEventOptions,
1520
+ spatializedContent: _content,
1521
+ createSpatializedElement: _create,
1522
+ getExtraSpatializedElementProperties: _getExtra,
1523
+ extraRefProps: _extraRef,
1524
+ sizingMode: _sizingMode,
1525
+ ...restProps
1526
+ } = inprops;
1527
+ return /* @__PURE__ */ jsx6(Component, { ref: innerRef, ...restProps, children });
1528
+ }
1473
1529
  function SpatializedContainerBase(inprops, ref) {
1474
1530
  const isWebSpatialEnv = getSession() !== null;
1475
- if (!isWebSpatialEnv) {
1476
- const {
1477
- component: Component,
1478
- spatializedContent,
1479
- createSpatializedElement: createSpatializedElement2,
1480
- getExtraSpatializedElementProperties: getExtraSpatializedElementProperties2,
1481
- onSpatialTap: onSpatialTap2,
1482
- onSpatialDragStart: onSpatialDragStart2,
1483
- onSpatialDrag: onSpatialDrag2,
1484
- onSpatialDragEnd: onSpatialDragEnd2,
1485
- onSpatialRotate: onSpatialRotate2,
1486
- onSpatialRotateEnd: onSpatialRotateEnd2,
1487
- onSpatialMagnify: onSpatialMagnify2,
1488
- onSpatialMagnifyEnd: onSpatialMagnifyEnd2,
1489
- extraRefProps: extraRefProps2,
1490
- ...restProps
1491
- } = inprops;
1492
- return /* @__PURE__ */ jsx6(Component, { ref, ...restProps });
1531
+ const insideAttachment = useInsideAttachment();
1532
+ if (!isWebSpatialEnv || insideAttachment) {
1533
+ if (insideAttachment) {
1534
+ console.warn(
1535
+ `[WebSpatial] ${inprops.component || "Spatial element"} cannot be used inside AttachmentAsset. Rendering as plain HTML.`
1536
+ );
1537
+ }
1538
+ return /* @__PURE__ */ jsx6(DegradedContainer, { ...inprops, innerRef: ref });
1493
1539
  }
1494
- const layer = useContext6(SpatialLayerContext) + 1;
1495
- const rootSpatializedContainerObject = useContext6(
1540
+ const layer = useContext7(SpatialLayerContext) + 1;
1541
+ const rootSpatializedContainerObject = useContext7(
1496
1542
  SpatializedContainerContext
1497
1543
  );
1498
1544
  const inSpatializedContainer = !!rootSpatializedContainerObject;
1499
- const portalInstanceObject = useContext6(PortalInstanceContext);
1545
+ const portalInstanceObject = useContext7(PortalInstanceContext);
1500
1546
  const inPortalInstanceEnv = !!portalInstanceObject;
1501
1547
  const isInStandardInstance = !inPortalInstanceEnv;
1502
1548
  const spatialId = useMemo2(() => {
@@ -1557,6 +1603,7 @@ function SpatializedContainerBase(inprops, ref) {
1557
1603
  spatializedContent,
1558
1604
  createSpatializedElement: createSpatializedElement2,
1559
1605
  getExtraSpatializedElementProperties: getExtraSpatializedElementProperties2,
1606
+ spatialEventOptions: _nestedSpatialEventOptions,
1560
1607
  ...restProps
1561
1608
  } = props;
1562
1609
  return /* @__PURE__ */ jsxs2(SpatialLayerContext.Provider, { value: layer, children: [
@@ -1607,6 +1654,7 @@ function SpatializedContainerBase(inprops, ref) {
1607
1654
  spatializedContent,
1608
1655
  createSpatializedElement: createSpatializedElement2,
1609
1656
  getExtraSpatializedElementProperties: getExtraSpatializedElementProperties2,
1657
+ spatialEventOptions: _rootSpatialEventOptions,
1610
1658
  ...restProps
1611
1659
  } = props;
1612
1660
  return /* @__PURE__ */ jsx6(SpatialLayerContext.Provider, { value: layer, children: /* @__PURE__ */ jsxs2(
@@ -1650,28 +1698,47 @@ var SpatializedContainer = withSSRSupported(
1650
1698
  );
1651
1699
 
1652
1700
  // src/spatialized-container/Spatialized2DElementContainer.tsx
1701
+ import { createPortal as createPortal2 } from "react-dom";
1653
1702
  import {
1654
1703
  forwardRef as forwardRef5,
1655
- useContext as useContext7,
1656
- useEffect as useEffect11
1704
+ useContext as useContext8,
1705
+ useEffect as useEffect12
1657
1706
  } from "react";
1658
- import { createPortal as createPortal2 } from "react-dom";
1659
- import { jsx as jsx7 } from "react/jsx-runtime";
1660
- function asyncLoadStyleToChildWindow(childWindow, n) {
1707
+
1708
+ // src/utils/windowStyleSync.ts
1709
+ function asyncLoadStyleToChildWindow(childWindow, link, isCurrent) {
1661
1710
  return new Promise((resolve) => {
1662
- n.href += "?uniqueURL=" + Math.random();
1663
- n.onerror = function(error) {
1664
- console.error("Failed to load style link", n.href);
1665
- resolve(false);
1711
+ const { href } = link;
1712
+ const sep = href.includes("?") ? "&" : "?";
1713
+ link.href = `${href}${sep}uniqueURL=${Math.random()}`;
1714
+ let finished = false;
1715
+ const finish = (ok) => {
1716
+ if (finished) return;
1717
+ finished = true;
1718
+ resolve(ok);
1719
+ };
1720
+ link.onerror = () => {
1721
+ finish(false);
1666
1722
  };
1667
- n.onload = function() {
1668
- resolve(true);
1723
+ link.onload = () => {
1724
+ if (!isCurrent()) {
1725
+ link.parentNode?.removeChild(link);
1726
+ finish(false);
1727
+ return;
1728
+ }
1729
+ finish(true);
1669
1730
  };
1670
1731
  setTimeout(() => {
1671
- childWindow.document.head.appendChild(n);
1732
+ if (!isCurrent()) {
1733
+ finish(false);
1734
+ return;
1735
+ }
1736
+ childWindow.document.head.appendChild(link);
1672
1737
  }, 50);
1673
1738
  });
1674
1739
  }
1740
+ var WEBSPATIAL_SYNC_ATTR = "data-webspatial-sync";
1741
+ var WEBSPATIAL_SYNC_KEY_ATTR = "data-webspatial-sync-key";
1675
1742
  function setOpenWindowStyle(openedWindow) {
1676
1743
  openedWindow.document.documentElement.style.cssText += document.documentElement.style.cssText;
1677
1744
  openedWindow.document.documentElement.style.backgroundColor = "transparent";
@@ -1683,23 +1750,118 @@ function setOpenWindowStyle(openedWindow) {
1683
1750
  openedWindow.document.body.style.minWidth = "fit-content";
1684
1751
  openedWindow.document.body.style.background = "transparent";
1685
1752
  }
1753
+ var controllers = /* @__PURE__ */ new WeakMap();
1754
+ function getController(childWindow) {
1755
+ const prev = controllers.get(childWindow);
1756
+ if (prev) return prev;
1757
+ const next = { version: 0 };
1758
+ controllers.set(childWindow, next);
1759
+ return next;
1760
+ }
1686
1761
  async function syncParentHeadToChild(childWindow) {
1762
+ const controller = getController(childWindow);
1763
+ const version2 = ++controller.version;
1687
1764
  const styleLoadedPromises = [];
1688
- for (let i = 0; i < document.head.children.length; i++) {
1689
- let n = document.head.children[i].cloneNode(true);
1690
- if (n.nodeName == "LINK" && n.rel == "stylesheet" && n.href) {
1691
- const promise = asyncLoadStyleToChildWindow(
1692
- childWindow,
1693
- n
1694
- );
1695
- styleLoadedPromises.push(promise);
1696
- } else {
1697
- childWindow.document.head.appendChild(n);
1698
- }
1765
+ const { head } = childWindow.document;
1766
+ const isCurrent = () => controller.version === version2;
1767
+ const parentStyles = Array.from(document.head.querySelectorAll("style"));
1768
+ const parentStylesheets = Array.from(
1769
+ document.head.querySelectorAll('link[rel="stylesheet"][href]')
1770
+ );
1771
+ const desiredStylesheetKeys = /* @__PURE__ */ new Set();
1772
+ for (const link of parentStylesheets) {
1773
+ if (link.href) desiredStylesheetKeys.add(link.href);
1774
+ }
1775
+ const existingSyncedLinks = Array.from(
1776
+ head.querySelectorAll(
1777
+ `link[rel="stylesheet"][${WEBSPATIAL_SYNC_ATTR}="1"]`
1778
+ )
1779
+ );
1780
+ for (const link of existingSyncedLinks) {
1781
+ const key = link.getAttribute(WEBSPATIAL_SYNC_KEY_ATTR) ?? link.href;
1782
+ if (!desiredStylesheetKeys.has(key)) link.parentNode?.removeChild(link);
1783
+ }
1784
+ const prevSyncedStyles = head.querySelectorAll(
1785
+ `style[${WEBSPATIAL_SYNC_ATTR}="1"]`
1786
+ );
1787
+ prevSyncedStyles.forEach((n) => n.parentNode?.removeChild(n));
1788
+ for (const styleEl of parentStyles) {
1789
+ const node = styleEl.cloneNode(true);
1790
+ node.setAttribute(WEBSPATIAL_SYNC_ATTR, "1");
1791
+ head.appendChild(node);
1792
+ }
1793
+ const currentKeys = /* @__PURE__ */ new Set();
1794
+ const currentSyncedLinks = Array.from(
1795
+ head.querySelectorAll(
1796
+ `link[rel="stylesheet"][${WEBSPATIAL_SYNC_ATTR}="1"]`
1797
+ )
1798
+ );
1799
+ for (const link of currentSyncedLinks) {
1800
+ currentKeys.add(link.getAttribute(WEBSPATIAL_SYNC_KEY_ATTR) ?? link.href);
1801
+ }
1802
+ for (const link of parentStylesheets) {
1803
+ const key = link.href;
1804
+ if (!key || currentKeys.has(key)) continue;
1805
+ const node = link.cloneNode(true);
1806
+ node.setAttribute(WEBSPATIAL_SYNC_ATTR, "1");
1807
+ node.setAttribute(WEBSPATIAL_SYNC_KEY_ATTR, key);
1808
+ styleLoadedPromises.push(
1809
+ asyncLoadStyleToChildWindow(childWindow, node, isCurrent)
1810
+ );
1699
1811
  }
1700
1812
  childWindow.document.documentElement.className = document.documentElement.className;
1701
1813
  return Promise.all(styleLoadedPromises);
1702
1814
  }
1815
+
1816
+ // src/utils/useSyncHeadStyles.ts
1817
+ import { useEffect as useEffect11 } from "react";
1818
+ function defaultShouldSync(mutations) {
1819
+ if (!Array.isArray(mutations) || mutations.length === 0) return false;
1820
+ for (const mutation of mutations) {
1821
+ const nodes = [
1822
+ ...Array.from(mutation.addedNodes),
1823
+ ...Array.from(mutation.removedNodes)
1824
+ ];
1825
+ for (const node of nodes) {
1826
+ if (!(node instanceof Element)) continue;
1827
+ const tag = node.tagName;
1828
+ if (tag === "STYLE") return true;
1829
+ if (tag === "LINK") {
1830
+ const { rel } = node;
1831
+ if (rel && rel.toLowerCase() === "stylesheet") return true;
1832
+ }
1833
+ }
1834
+ }
1835
+ return false;
1836
+ }
1837
+ function useSyncHeadStyles(childWindow, options) {
1838
+ const delayMs = 100;
1839
+ const subtree = options?.subtree ?? false;
1840
+ const immediate = options?.immediate ?? true;
1841
+ useEffect11(() => {
1842
+ if (!childWindow) return;
1843
+ let timer;
1844
+ const scheduleSync = () => {
1845
+ if (timer) window.clearTimeout(timer);
1846
+ timer = window.setTimeout(() => {
1847
+ syncParentHeadToChild(childWindow);
1848
+ }, delayMs);
1849
+ };
1850
+ if (immediate) scheduleSync();
1851
+ const observer = new MutationObserver((mutations) => {
1852
+ if (!defaultShouldSync(mutations)) return;
1853
+ scheduleSync();
1854
+ });
1855
+ observer.observe(document.head, { childList: true, subtree });
1856
+ return () => {
1857
+ if (timer) window.clearTimeout(timer);
1858
+ observer.disconnect();
1859
+ };
1860
+ }, [childWindow, delayMs, subtree, immediate]);
1861
+ }
1862
+
1863
+ // src/spatialized-container/Spatialized2DElementContainer.tsx
1864
+ import { jsx as jsx7 } from "react/jsx-runtime";
1703
1865
  function getJSXPortalInstance(inProps, portalInstanceObject) {
1704
1866
  const { component: El, style: inStyle = {}, ...props } = inProps;
1705
1867
  const extraStyle = {
@@ -1725,19 +1887,8 @@ function getJSXPortalInstance(inProps, portalInstanceObject) {
1725
1887
  };
1726
1888
  return /* @__PURE__ */ jsx7(El, { style, ...props });
1727
1889
  }
1728
- function useSyncHeaderStyle(windowProxy) {
1729
- useEffect11(() => {
1730
- const headObserver = new MutationObserver((_) => {
1731
- syncParentHeadToChild(windowProxy);
1732
- });
1733
- headObserver.observe(document.head, { childList: true, subtree: true });
1734
- return () => {
1735
- headObserver.disconnect();
1736
- };
1737
- }, []);
1738
- }
1739
1890
  function useSyncDocumentTitle(windowProxy, spatializedElement, name) {
1740
- useEffect11(() => {
1891
+ useEffect12(() => {
1741
1892
  windowProxy.document.title = name;
1742
1893
  spatializedElement.updateProperties({
1743
1894
  name
@@ -1747,11 +1898,13 @@ function useSyncDocumentTitle(windowProxy, spatializedElement, name) {
1747
1898
  function SpatializedContent(props) {
1748
1899
  const { spatializedElement, ...restProps } = props;
1749
1900
  const spatialized2DElement = spatializedElement;
1750
- const windowProxy = spatialized2DElement.windowProxy;
1751
- useSyncHeaderStyle(windowProxy);
1901
+ const { windowProxy } = spatialized2DElement;
1902
+ useSyncHeadStyles(windowProxy, {
1903
+ subtree: false
1904
+ });
1752
1905
  const name = restProps["data-name"] || "";
1753
1906
  useSyncDocumentTitle(windowProxy, spatialized2DElement, name);
1754
- const portalInstanceObject = useContext7(
1907
+ const portalInstanceObject = useContext8(
1755
1908
  PortalInstanceContext
1756
1909
  );
1757
1910
  const JSXPortalInstance = getJSXPortalInstance(
@@ -1776,14 +1929,14 @@ function getExtraSpatializedElementProperties(computedStyle) {
1776
1929
  }
1777
1930
  async function createSpatializedElement() {
1778
1931
  const spatializedElement = await getSession().createSpatialized2DElement();
1779
- const windowProxy = spatializedElement.windowProxy;
1932
+ const { windowProxy } = spatializedElement;
1780
1933
  setOpenWindowStyle(windowProxy);
1781
1934
  await syncParentHeadToChild(windowProxy);
1782
1935
  const viewport = windowProxy.document.querySelector('meta[name="viewport"]');
1783
1936
  if (viewport) {
1784
1937
  viewport?.setAttribute(
1785
1938
  "content",
1786
- ` initial-scale=1.0, maximum-scale=1.0, user-scalable=no`
1939
+ " initial-scale=1.0, maximum-scale=1.0, user-scalable=no"
1787
1940
  );
1788
1941
  } else {
1789
1942
  const meta = windowProxy.document.createElement("meta");
@@ -1813,12 +1966,10 @@ var Spatialized2DElementContainer = forwardRef5(
1813
1966
  import {
1814
1967
  forwardRef as forwardRef6,
1815
1968
  useCallback as useCallback6,
1816
- useContext as useContext8,
1817
- useEffect as useEffect12,
1969
+ useContext as useContext9,
1970
+ useEffect as useEffect13,
1818
1971
  useMemo as useMemo3,
1819
- useState as useState6,
1820
- useImperativeHandle,
1821
- useRef as useRef4
1972
+ useRef as useRef5
1822
1973
  } from "react";
1823
1974
  import { Fragment as Fragment2, jsx as jsx8 } from "react/jsx-runtime";
1824
1975
  function getAbsoluteURL(url) {
@@ -1855,16 +2006,16 @@ function createLoadSuccessEvent(targetGetter) {
1855
2006
  function SpatializedContent2(props) {
1856
2007
  const { src, spatializedElement, onLoad, onError } = props;
1857
2008
  const spatializedStatic3DElement = spatializedElement;
1858
- const portalInstanceObject = useContext8(
2009
+ const portalInstanceObject = useContext9(
1859
2010
  PortalInstanceContext
1860
2011
  );
1861
2012
  const currentSrc = useMemo3(() => getAbsoluteURL(src), [src]);
1862
- useEffect12(() => {
2013
+ useEffect13(() => {
1863
2014
  if (src) {
1864
2015
  spatializedStatic3DElement.updateProperties({ modelURL: currentSrc });
1865
2016
  }
1866
2017
  }, [currentSrc]);
1867
- useEffect12(() => {
2018
+ useEffect13(() => {
1868
2019
  if (onLoad) {
1869
2020
  spatializedStatic3DElement.onLoadCallback = () => {
1870
2021
  onLoad(
@@ -1877,7 +2028,7 @@ function SpatializedContent2(props) {
1877
2028
  spatializedStatic3DElement.onLoadCallback = void 0;
1878
2029
  }
1879
2030
  }, [onLoad]);
1880
- useEffect12(() => {
2031
+ useEffect13(() => {
1881
2032
  if (onError) {
1882
2033
  spatializedStatic3DElement.onLoadFailureCallback = () => {
1883
2034
  onError(
@@ -1893,14 +2044,12 @@ function SpatializedContent2(props) {
1893
2044
  return /* @__PURE__ */ jsx8(Fragment2, {});
1894
2045
  }
1895
2046
  function SpatializedStatic3DElementContainerBase(props, ref) {
1896
- const containerRef = useRef4(null);
1897
- const [elementCreated, setElementCreated] = useState6(false);
1898
- useImperativeHandle(ref, () => elementCreated ? containerRef.current : null, [elementCreated]);
1899
- const createSpatializedElement2 = useCallback6(async () => {
1900
- const element = await getSession().createSpatializedStatic3DElement();
1901
- setElementCreated(true);
1902
- return element;
1903
- }, [setElementCreated]);
2047
+ const promiseRef = useRef5(null);
2048
+ const createSpatializedElement2 = useCallback6(() => {
2049
+ const url = getAbsoluteURL(props.src);
2050
+ promiseRef.current = getSession().createSpatializedStatic3DElement(url);
2051
+ return promiseRef.current;
2052
+ }, []);
1904
2053
  const extraRefProps = useCallback6(
1905
2054
  (domProxy) => {
1906
2055
  let modelTransform = new DOMMatrixReadOnly();
@@ -1909,14 +2058,10 @@ function SpatializedStatic3DElementContainerBase(props, ref) {
1909
2058
  return getAbsoluteURL(props.src);
1910
2059
  },
1911
2060
  get ready() {
1912
- const spatializedElement = domProxy.__spatializedElement;
1913
- const promise = spatializedElement.ready.then((success) => {
1914
- if (success) {
1915
- return createLoadSuccessEvent(() => domProxy);
1916
- }
2061
+ return promiseRef.current.then((spatializedElement) => spatializedElement.ready).then((success) => {
2062
+ if (success) return createLoadSuccessEvent(() => domProxy);
1917
2063
  throw createLoadFailureEvent(() => domProxy);
1918
2064
  });
1919
- return promise;
1920
2065
  },
1921
2066
  get entityTransform() {
1922
2067
  return modelTransform;
@@ -1924,7 +2069,7 @@ function SpatializedStatic3DElementContainerBase(props, ref) {
1924
2069
  set entityTransform(value) {
1925
2070
  modelTransform = value;
1926
2071
  const spatializedElement = domProxy.__spatializedElement;
1927
- spatializedElement.updateModelTransform(modelTransform);
2072
+ spatializedElement?.updateModelTransform(modelTransform);
1928
2073
  }
1929
2074
  };
1930
2075
  },
@@ -1933,7 +2078,7 @@ function SpatializedStatic3DElementContainerBase(props, ref) {
1933
2078
  return /* @__PURE__ */ jsx8(
1934
2079
  SpatializedContainer,
1935
2080
  {
1936
- ref: containerRef,
2081
+ ref,
1937
2082
  component: "div",
1938
2083
  createSpatializedElement: createSpatializedElement2,
1939
2084
  spatializedContent: SpatializedContent2,
@@ -1995,10 +2140,10 @@ function initScene(name, callback, options) {
1995
2140
  import { forwardRef as forwardRef9 } from "react";
1996
2141
 
1997
2142
  // src/spatialized-container-monitor/useMonitorDomChange.tsx
1998
- import { useRef as useRef5, useEffect as useEffect13, useMemo as useMemo4 } from "react";
2143
+ import { useRef as useRef6, useEffect as useEffect14, useMemo as useMemo4 } from "react";
1999
2144
  function useMonitorDomChange(inRef) {
2000
- const ref = useRef5(null);
2001
- useEffect13(() => {
2145
+ const ref = useRef6(null);
2146
+ useEffect14(() => {
2002
2147
  const observer = new MutationObserver((mutationsList) => {
2003
2148
  notifyDOMUpdate(mutationsList);
2004
2149
  });
@@ -2034,9 +2179,9 @@ function useMonitorDomChange(inRef) {
2034
2179
  }
2035
2180
 
2036
2181
  // src/spatialized-container-monitor/useMonitorDocumentHeaderChange.tsx
2037
- import { useEffect as useEffect14 } from "react";
2182
+ import { useEffect as useEffect15 } from "react";
2038
2183
  function useMonitorDocumentHeaderChange() {
2039
- useEffect14(() => {
2184
+ useEffect15(() => {
2040
2185
  const observer = new MutationObserver((mutationsList) => {
2041
2186
  notifyUpdateStandInstanceLayout();
2042
2187
  });
@@ -2096,17 +2241,70 @@ import { forwardRef as forwardRef11 } from "react";
2096
2241
  import { forwardRef as forwardRef10 } from "react";
2097
2242
 
2098
2243
  // src/reality/context/RealityContext.tsx
2099
- import { createContext as createContext5, useContext as useContext9 } from "react";
2100
- var RealityContext = createContext5(null);
2101
- var useRealityContext = () => useContext9(RealityContext);
2244
+ import { createContext as createContext6, useContext as useContext10 } from "react";
2245
+ var RealityContext = createContext6(null);
2246
+ var useRealityContext = () => useContext10(RealityContext);
2102
2247
 
2103
2248
  // src/reality/context/ParentContext.tsx
2104
- import { createContext as createContext6, useContext as useContext10 } from "react";
2105
- var ParentContext = createContext6(null);
2106
- var useParentContext = () => useContext10(ParentContext);
2249
+ import { createContext as createContext7, useContext as useContext11 } from "react";
2250
+ var ParentContext = createContext7(null);
2251
+ var useParentContext = () => useContext11(ParentContext);
2252
+
2253
+ // src/reality/context/AttachmentContext.tsx
2254
+ import { createContext as createContext8, useContext as useContext12 } from "react";
2255
+ var AttachmentRegistry = class {
2256
+ // name → (instanceId → container)
2257
+ containers = /* @__PURE__ */ new Map();
2258
+ listeners = /* @__PURE__ */ new Map();
2259
+ addContainer(name, instanceId, container) {
2260
+ if (!this.containers.has(name)) {
2261
+ this.containers.set(name, /* @__PURE__ */ new Map());
2262
+ }
2263
+ this.containers.get(name).set(instanceId, container);
2264
+ this.notifyListeners(name);
2265
+ }
2266
+ removeContainer(name, instanceId) {
2267
+ this.containers.get(name)?.delete(instanceId);
2268
+ if (this.containers.get(name)?.size === 0) {
2269
+ this.containers.delete(name);
2270
+ }
2271
+ this.notifyListeners(name);
2272
+ }
2273
+ getContainers(name) {
2274
+ const map = this.containers.get(name);
2275
+ if (!map) return [];
2276
+ return Array.from(map, ([instanceId, container]) => ({
2277
+ instanceId,
2278
+ container
2279
+ }));
2280
+ }
2281
+ onContainersChange(name, cb) {
2282
+ const current = this.getContainers(name);
2283
+ if (current.length > 0) {
2284
+ cb(current);
2285
+ }
2286
+ const prev = this.listeners.get(name);
2287
+ if (prev) prev([]);
2288
+ this.listeners.set(name, cb);
2289
+ return () => {
2290
+ if (this.listeners.get(name) === cb) {
2291
+ this.listeners.delete(name);
2292
+ }
2293
+ };
2294
+ }
2295
+ notifyListeners(name) {
2296
+ const cs = this.getContainers(name);
2297
+ this.listeners.get(name)?.(cs);
2298
+ }
2299
+ destroy() {
2300
+ this.containers.clear();
2301
+ this.listeners.clear();
2302
+ }
2303
+ };
2304
+ var AttachmentContext = createContext8(null);
2107
2305
 
2108
2306
  // src/reality/hooks/useEntityTransform.tsx
2109
- import { useEffect as useEffect15, useRef as useRef6 } from "react";
2307
+ import { useEffect as useEffect16, useRef as useRef7 } from "react";
2110
2308
 
2111
2309
  // src/reality/utils/ResourceRegistry.ts
2112
2310
  var ResourceRegistry = class {
@@ -2187,8 +2385,8 @@ var AbortResourceManager = class {
2187
2385
 
2188
2386
  // src/reality/hooks/useEntityTransform.tsx
2189
2387
  function useEntityTransform(entity, { position, rotation, scale }) {
2190
- const last = useRef6({});
2191
- useEffect15(() => {
2388
+ const last = useRef7({});
2389
+ useEffect16(() => {
2192
2390
  if (!entity) return;
2193
2391
  const shouldUpdate = !shallowEqualVec3(last.current.position, position) || !shallowEqualRotation(last.current.rotation, rotation) || !shallowEqualVec3(last.current.scale, scale);
2194
2392
  if (!shouldUpdate) return;
@@ -2207,7 +2405,7 @@ function useEntityTransform(entity, { position, rotation, scale }) {
2207
2405
  }
2208
2406
 
2209
2407
  // src/reality/hooks/useEntityEvent.tsx
2210
- import { useEffect as useEffect17, useRef as useRef8 } from "react";
2408
+ import { useEffect as useEffect18, useRef as useRef9 } from "react";
2211
2409
 
2212
2410
  // src/reality/type.ts
2213
2411
  var eventMap = {
@@ -2218,19 +2416,17 @@ var eventMap = {
2218
2416
  onSpatialDrag: "spatialdrag",
2219
2417
  onSpatialDragEnd: "spatialdragend",
2220
2418
  // rotate
2221
- onSpatialRotateStart: "spatialrotatestart",
2222
2419
  onSpatialRotate: "spatialrotate",
2223
2420
  onSpatialRotateEnd: "spatialrotateend",
2224
2421
  // magnify
2225
- onSpatialMagnifyStart: "spatialmagnifystart",
2226
2422
  onSpatialMagnify: "spatialmagnify",
2227
2423
  onSpatialMagnifyEnd: "spatialmagnifyend"
2228
2424
  };
2229
2425
 
2230
2426
  // src/reality/hooks/useEntityRef.tsx
2231
- import { useImperativeHandle as useImperativeHandle2 } from "react";
2427
+ import { useImperativeHandle } from "react";
2232
2428
  var useEntityRef = (ref, instance) => {
2233
- useImperativeHandle2(ref, () => instance);
2429
+ useImperativeHandle(ref, () => instance);
2234
2430
  };
2235
2431
  var EntityRef = class {
2236
2432
  _entity;
@@ -2297,7 +2493,8 @@ var EntityRef = class {
2297
2493
  }
2298
2494
  };
2299
2495
 
2300
- // src/reality/hooks/useEntityEvent.tsx
2496
+ // src/reality/hooks/useRealityEvents.tsx
2497
+ import { useEffect as useEffect19, useRef as useRef10 } from "react";
2301
2498
  function createEventProxy2(ev, instance) {
2302
2499
  return new Proxy(ev, {
2303
2500
  get(target, prop) {
@@ -2344,44 +2541,99 @@ function createEventProxy2(ev, instance) {
2344
2541
  }
2345
2542
  return void 0;
2346
2543
  }
2544
+ if (prop === "translationX") {
2545
+ const type = target.type;
2546
+ if (type === "spatialdrag") {
2547
+ return target.detail?.translation3D?.x ?? 0;
2548
+ }
2549
+ return void 0;
2550
+ }
2551
+ if (prop === "translationY") {
2552
+ const type = target.type;
2553
+ if (type === "spatialdrag") {
2554
+ return target.detail?.translation3D?.y ?? 0;
2555
+ }
2556
+ return void 0;
2557
+ }
2558
+ if (prop === "translationZ") {
2559
+ const type = target.type;
2560
+ if (type === "spatialdrag") {
2561
+ return target.detail?.translation3D?.z ?? 0;
2562
+ }
2563
+ return void 0;
2564
+ }
2565
+ if (prop === "quaternion") {
2566
+ const type = target.type;
2567
+ if (type === "spatialrotate") {
2568
+ return target.detail?.quaternion ?? {
2569
+ x: 0,
2570
+ y: 0,
2571
+ z: 0,
2572
+ w: 1
2573
+ };
2574
+ }
2575
+ return void 0;
2576
+ }
2577
+ if (prop === "magnification") {
2578
+ const type = target.type;
2579
+ if (type === "spatialmagnify") {
2580
+ return target.detail?.magnification ?? 1;
2581
+ }
2582
+ return void 0;
2583
+ }
2584
+ if (prop === "clientX") {
2585
+ const type = target.type;
2586
+ if (type === "spatialtap" || type === "spatialdragstart") {
2587
+ return target.detail?.globalLocation3D?.x ?? 0;
2588
+ }
2589
+ return void 0;
2590
+ }
2591
+ if (prop === "clientY") {
2592
+ const type = target.type;
2593
+ if (type === "spatialtap" || type === "spatialdragstart") {
2594
+ return target.detail?.globalLocation3D?.y ?? 0;
2595
+ }
2596
+ return void 0;
2597
+ }
2598
+ if (prop === "clientZ") {
2599
+ const type = target.type;
2600
+ if (type === "spatialtap" || type === "spatialdragstart") {
2601
+ return target.detail?.globalLocation3D?.z ?? 0;
2602
+ }
2603
+ return void 0;
2604
+ }
2347
2605
  const val = target[prop];
2348
2606
  return typeof val === "function" ? val.bind(target) : val;
2349
2607
  }
2350
2608
  });
2351
2609
  }
2352
- var useEntityEvent = ({ instance, ...handlers }) => {
2353
- const eventsSetRef = useRef8(/* @__PURE__ */ new Set());
2354
- useEffect17(() => {
2355
- const entity = instance.entity;
2356
- if (!entity) return;
2610
+ var useRealityEvents = ({ instance, ...handlers }) => {
2611
+ const eventsSetRef = useRef10(/* @__PURE__ */ new Set());
2612
+ useEffect19(() => {
2613
+ if (!instance) return;
2357
2614
  Object.entries(eventMap).forEach(([reactKey, spatialEvent]) => {
2358
2615
  const handlerFn = handlers[reactKey];
2359
2616
  if (!handlerFn) return;
2360
2617
  const wrapped = (ev) => handlerFn(createEventProxy2(ev, instance));
2361
- entity.addEvent(spatialEvent, wrapped);
2362
- eventsSetRef.current.add(reactKey);
2618
+ instance.addEvent(spatialEvent, wrapped);
2619
+ eventsSetRef.current.add(spatialEvent);
2363
2620
  });
2364
2621
  return () => {
2365
- };
2366
- }, [instance.entity, ...Object.values(handlers)]);
2367
- useEffect17(() => {
2368
- const entity = instance.entity;
2369
- if (!entity) return;
2370
- return () => {
2371
- for (let x of eventsSetRef.current) {
2372
- entity.removeEvent(x);
2622
+ if (instance) {
2623
+ for (let x of eventsSetRef.current) {
2624
+ instance.removeEvent(x);
2625
+ }
2626
+ eventsSetRef.current.clear();
2373
2627
  }
2374
- eventsSetRef.current.clear();
2375
2628
  };
2376
- }, [instance.entity]);
2377
- return null;
2629
+ }, [instance, ...Object.values(handlers)]);
2378
2630
  };
2379
2631
 
2380
2632
  // src/reality/hooks/useEntityId.tsx
2381
- import { useEffect as useEffect18 } from "react";
2633
+ import { useEffect as useEffect20 } from "react";
2382
2634
  var useEntityId = ({ id, entity }) => {
2383
2635
  const ctx = useRealityContext();
2384
- useEffect18(() => {
2636
+ useEffect20(() => {
2385
2637
  if (!id || !entity || !ctx) return;
2386
2638
  ctx.resourceRegistry.add(id, Promise.resolve(entity));
2387
2639
  return () => {
@@ -2392,31 +2644,21 @@ var useEntityId = ({ id, entity }) => {
2392
2644
  };
2393
2645
 
2394
2646
  // src/reality/hooks/useEntity.tsx
2395
- import { useEffect as useEffect19, useRef as useRef9 } from "react";
2647
+ import { useEffect as useEffect21, useRef as useRef11 } from "react";
2396
2648
  var useEntity = ({
2397
2649
  ref,
2398
2650
  id,
2399
2651
  position,
2400
2652
  rotation,
2401
2653
  scale,
2402
- onSpatialTap,
2403
- onSpatialDragStart,
2404
- onSpatialDrag,
2405
- onSpatialDragEnd,
2406
- // onSpatialRotateStart,
2407
- onSpatialRotate,
2408
- onSpatialRotateEnd,
2409
- // onSpatialMagnifyStart,
2410
- onSpatialMagnify,
2411
- onSpatialMagnifyEnd,
2412
- // TODO: add other event handlers
2654
+ enableInput,
2413
2655
  createEntity
2414
2656
  }) => {
2415
2657
  const ctx = useRealityContext();
2416
2658
  const parent = useParentContext();
2417
- const instanceRef = useRef9(new EntityRef(null, ctx));
2659
+ const instanceRef = useRef11(new EntityRef(null, ctx));
2418
2660
  const forceUpdate = useForceUpdate2();
2419
- useEffect19(() => {
2661
+ useEffect21(() => {
2420
2662
  if (!ctx) return;
2421
2663
  const controller = new AbortController();
2422
2664
  const init = async () => {
@@ -2449,26 +2691,20 @@ var useEntity = ({
2449
2691
  useEntityId({ id, entity: instanceRef.current.entity });
2450
2692
  useEntityTransform(instanceRef.current.entity, { position, rotation, scale });
2451
2693
  useEntityRef(ref, instanceRef.current);
2452
- useEntityEvent({
2453
- instance: instanceRef.current,
2454
- onSpatialTap,
2455
- onSpatialDragStart,
2456
- onSpatialDrag,
2457
- onSpatialDragEnd,
2458
- // onSpatialRotateStart,
2459
- onSpatialRotate,
2460
- onSpatialRotateEnd,
2461
- // onSpatialMagnifyStart,
2462
- onSpatialMagnify,
2463
- onSpatialMagnifyEnd
2464
- });
2694
+ useEffect21(() => {
2695
+ const ent = instanceRef.current.entity;
2696
+ if (!ent) return;
2697
+ if (enableInput !== void 0) {
2698
+ ent.enableInput = !!enableInput;
2699
+ }
2700
+ }, [instanceRef.current.entity, enableInput]);
2465
2701
  return instanceRef.current.entity;
2466
2702
  };
2467
2703
 
2468
2704
  // src/reality/hooks/useForceUpdate.tsx
2469
- import { useCallback as useCallback7, useState as useState8 } from "react";
2705
+ import { useCallback as useCallback7, useState as useState7 } from "react";
2470
2706
  var useForceUpdate2 = () => {
2471
- const [, setTick] = useState8(0);
2707
+ const [, setTick] = useState7(0);
2472
2708
  return useCallback7(() => setTick((tick) => tick + 1), []);
2473
2709
  };
2474
2710
 
@@ -2573,11 +2809,14 @@ var BoxEntity = forwardRef13(
2573
2809
  );
2574
2810
 
2575
2811
  // src/reality/components/UnlitMaterial.tsx
2576
- import { useEffect as useEffect20, useRef as useRef10 } from "react";
2577
- var UnlitMaterial = ({ children, ...options }) => {
2812
+ import { useEffect as useEffect22, useRef as useRef12 } from "react";
2813
+ var UnlitMaterial = ({
2814
+ children,
2815
+ ...options
2816
+ }) => {
2578
2817
  const ctx = useRealityContext();
2579
- const materialRef = useRef10();
2580
- useEffect20(() => {
2818
+ const materialRef = useRef12();
2819
+ useEffect22(() => {
2581
2820
  if (!ctx) return;
2582
2821
  const { session, reality, resourceRegistry } = ctx;
2583
2822
  const init = async () => {
@@ -2693,7 +2932,7 @@ var SceneGraph = ({ children }) => {
2693
2932
  };
2694
2933
 
2695
2934
  // src/reality/components/ModelAsset.tsx
2696
- import { useEffect as useEffect21, useRef as useRef11 } from "react";
2935
+ import { useEffect as useEffect23, useRef as useRef13 } from "react";
2697
2936
  var resolveAssetUrl = (url) => {
2698
2937
  if (url.startsWith("http://") || url.startsWith("https://")) {
2699
2938
  return url;
@@ -2702,8 +2941,8 @@ var resolveAssetUrl = (url) => {
2702
2941
  };
2703
2942
  var ModelAsset = ({ children, ...options }) => {
2704
2943
  const ctx = useRealityContext();
2705
- const materialRef = useRef11();
2706
- useEffect21(() => {
2944
+ const materialRef = useRef13();
2945
+ useEffect23(() => {
2707
2946
  const controller = new AbortController();
2708
2947
  if (!ctx) return;
2709
2948
  const { session, reality, resourceRegistry } = ctx;
@@ -2770,13 +3009,20 @@ var ModelEntity = forwardRef18(
2770
3009
  import {
2771
3010
  forwardRef as forwardRef19,
2772
3011
  useCallback as useCallback8,
2773
- useEffect as useEffect22,
2774
- useRef as useRef12,
2775
- useState as useState9
3012
+ useEffect as useEffect24,
3013
+ useRef as useRef14,
3014
+ useState as useState8
2776
3015
  } from "react";
2777
3016
  import { Fragment as Fragment3, jsx as jsx22, jsxs as jsxs3 } from "react/jsx-runtime";
2778
3017
  var Reality = forwardRef19(
2779
3018
  function RealityBase({ children, ...inProps }, ref) {
3019
+ const insideAttachment = useInsideAttachment();
3020
+ if (insideAttachment) {
3021
+ console.warn(
3022
+ "[WebSpatial] Reality cannot be used inside AttachmentAsset."
3023
+ );
3024
+ return null;
3025
+ }
2780
3026
  const {
2781
3027
  onSpatialTap,
2782
3028
  onSpatialDragStart,
@@ -2788,16 +3034,17 @@ var Reality = forwardRef19(
2788
3034
  onSpatialMagnifyEnd,
2789
3035
  ...props
2790
3036
  } = inProps;
2791
- const ctxRef = useRef12(null);
2792
- const creationId = useRef12(0);
2793
- const [isReady, setIsReady] = useState9(false);
3037
+ const ctxRef = useRef14(null);
3038
+ const creationId = useRef14(0);
3039
+ const [isReady, setIsReady] = useState8(false);
2794
3040
  const cleanupReality = useCallback8(() => {
3041
+ ctxRef.current?.attachmentRegistry.destroy();
2795
3042
  ctxRef.current?.resourceRegistry.destroy();
2796
3043
  ctxRef.current?.reality.destroy();
2797
3044
  ctxRef.current = null;
2798
3045
  setIsReady(false);
2799
3046
  }, []);
2800
- useEffect22(() => {
3047
+ useEffect24(() => {
2801
3048
  return () => {
2802
3049
  creationId.current++;
2803
3050
  cleanupReality();
@@ -2806,15 +3053,18 @@ var Reality = forwardRef19(
2806
3053
  const createReality = useCallback8(async () => {
2807
3054
  const id = ++creationId.current;
2808
3055
  const resourceRegistry = new ResourceRegistry();
3056
+ const attachmentRegistry = new AttachmentRegistry();
2809
3057
  const session = await getSession();
2810
3058
  if (!session) {
2811
3059
  resourceRegistry.destroy();
3060
+ attachmentRegistry.destroy();
2812
3061
  return null;
2813
3062
  }
2814
3063
  const reality = await session.createSpatializedDynamic3DElement();
2815
3064
  const isCancelled = () => id !== creationId.current;
2816
3065
  if (isCancelled()) {
2817
3066
  resourceRegistry.destroy();
3067
+ attachmentRegistry.destroy();
2818
3068
  reality.destroy();
2819
3069
  return null;
2820
3070
  }
@@ -2822,21 +3072,39 @@ var Reality = forwardRef19(
2822
3072
  const result = await session.getSpatialScene().addSpatializedElement(reality);
2823
3073
  if (!result.success || isCancelled()) {
2824
3074
  resourceRegistry.destroy();
3075
+ attachmentRegistry.destroy();
2825
3076
  reality.destroy();
2826
3077
  return null;
2827
3078
  }
2828
3079
  cleanupReality();
2829
- ctxRef.current = { session, reality, resourceRegistry };
3080
+ ctxRef.current = {
3081
+ session,
3082
+ reality,
3083
+ resourceRegistry,
3084
+ attachmentRegistry
3085
+ };
2830
3086
  setIsReady(true);
2831
3087
  return reality;
2832
3088
  } catch (err) {
2833
3089
  console.error("[createReality] failed", err);
2834
3090
  resourceRegistry.destroy();
3091
+ attachmentRegistry.destroy();
2835
3092
  reality.destroy();
2836
3093
  return null;
2837
3094
  }
2838
3095
  }, [cleanupReality]);
2839
3096
  const content = useCallback8(() => /* @__PURE__ */ jsx22(Fragment3, {}), []);
3097
+ useRealityEvents({
3098
+ instance: ctxRef.current?.reality ?? null,
3099
+ onSpatialTap,
3100
+ onSpatialDragStart,
3101
+ onSpatialDrag,
3102
+ onSpatialDragEnd,
3103
+ onSpatialRotate,
3104
+ onSpatialRotateEnd,
3105
+ onSpatialMagnify,
3106
+ onSpatialMagnifyEnd
3107
+ });
2840
3108
  return /* @__PURE__ */ jsxs3(RealityContext.Provider, { value: ctxRef.current, children: [
2841
3109
  /* @__PURE__ */ jsx22(
2842
3110
  SpatializedContainer,
@@ -2853,14 +3121,146 @@ var Reality = forwardRef19(
2853
3121
  }
2854
3122
  );
2855
3123
 
3124
+ // src/reality/components/AttachmentAsset.tsx
3125
+ import { useEffect as useEffect25, useState as useState9 } from "react";
3126
+ import { createPortal as createPortal3 } from "react-dom";
3127
+ import { jsx as jsx23 } from "react/jsx-runtime";
3128
+ var AttachmentAsset = ({
3129
+ name,
3130
+ children
3131
+ }) => {
3132
+ const ctx = useRealityContext();
3133
+ const [containers, setContainers] = useState9([]);
3134
+ useEffect25(() => {
3135
+ if (!ctx) return;
3136
+ return ctx.attachmentRegistry.onContainersChange(name, setContainers);
3137
+ }, [ctx, name]);
3138
+ if (!containers.length) return null;
3139
+ return /* @__PURE__ */ jsx23(InsideAttachmentContext.Provider, { value: true, children: containers.map(
3140
+ ({ instanceId, container }) => createPortal3(children, container, instanceId)
3141
+ ) });
3142
+ };
3143
+
3144
+ // src/reality/components/AttachmentEntity.tsx
3145
+ import { useEffect as useEffect26, useRef as useRef15, useState as useState10 } from "react";
3146
+ var instanceCounter = 0;
3147
+ var AttachmentEntity = ({
3148
+ attachment: attachmentName,
3149
+ position,
3150
+ size
3151
+ }) => {
3152
+ const ctx = useRealityContext();
3153
+ const parent = useParentContext();
3154
+ const attachmentRef = useRef15(null);
3155
+ const parentIdRef = useRef15(null);
3156
+ const instanceIdRef = useRef15(`att_${++instanceCounter}`);
3157
+ const attachmentNameRef = useRef15(attachmentName);
3158
+ const [childWindow, setChildWindow] = useState10(null);
3159
+ useEffect26(() => {
3160
+ if (!ctx || !parent) return;
3161
+ if (attachmentRef.current) return;
3162
+ const parentId = parent.id;
3163
+ parentIdRef.current = parentId;
3164
+ let cancelled = false;
3165
+ const init = async () => {
3166
+ try {
3167
+ const att = await ctx.session.createAttachmentEntity({
3168
+ parentEntityId: parentId,
3169
+ position: position ?? [0, 0, 0],
3170
+ size,
3171
+ ownerViewId: ctx.reality.id
3172
+ });
3173
+ if (cancelled) {
3174
+ att.destroy();
3175
+ return;
3176
+ }
3177
+ const windowProxy = att.getWindowProxy();
3178
+ setOpenWindowStyle(windowProxy);
3179
+ windowProxy.document.body.style.display = "block";
3180
+ windowProxy.document.body.style.minWidth = "100%";
3181
+ windowProxy.document.body.style.maxWidth = "100%";
3182
+ windowProxy.document.body.style.minHeight = "100%";
3183
+ const viewport = windowProxy.document.querySelector(
3184
+ 'meta[name="viewport"]'
3185
+ );
3186
+ if (!viewport) {
3187
+ const meta = windowProxy.document.createElement("meta");
3188
+ meta.name = "viewport";
3189
+ meta.content = "width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no";
3190
+ windowProxy.document.head.appendChild(meta);
3191
+ }
3192
+ const base = windowProxy.document.createElement("base");
3193
+ base.href = document.baseURI;
3194
+ windowProxy.document.head.appendChild(base);
3195
+ attachmentRef.current = att;
3196
+ setChildWindow(windowProxy);
3197
+ ctx.attachmentRegistry.addContainer(
3198
+ attachmentNameRef.current,
3199
+ instanceIdRef.current,
3200
+ att.getContainer()
3201
+ );
3202
+ } catch (error) {
3203
+ console.error("[AttachmentEntity] init error:", error);
3204
+ }
3205
+ };
3206
+ init();
3207
+ return () => {
3208
+ cancelled = true;
3209
+ const att = attachmentRef.current;
3210
+ if (att) {
3211
+ ctx.attachmentRegistry.removeContainer(
3212
+ attachmentNameRef.current,
3213
+ instanceIdRef.current
3214
+ );
3215
+ att.destroy();
3216
+ attachmentRef.current = null;
3217
+ setChildWindow(null);
3218
+ }
3219
+ };
3220
+ }, [ctx, parent]);
3221
+ useEffect26(() => {
3222
+ if (!ctx) return;
3223
+ const att = attachmentRef.current;
3224
+ const prevName = attachmentNameRef.current;
3225
+ if (att && prevName !== attachmentName) {
3226
+ ctx.attachmentRegistry.removeContainer(prevName, instanceIdRef.current);
3227
+ ctx.attachmentRegistry.addContainer(
3228
+ attachmentName,
3229
+ instanceIdRef.current,
3230
+ att.getContainer()
3231
+ );
3232
+ attachmentNameRef.current = attachmentName;
3233
+ } else {
3234
+ attachmentNameRef.current = attachmentName;
3235
+ }
3236
+ }, [ctx, attachmentName]);
3237
+ useSyncHeadStyles(childWindow, { subtree: false });
3238
+ useEffect26(() => {
3239
+ if (!attachmentRef.current) return;
3240
+ attachmentRef.current.update({ position, size });
3241
+ }, [position?.[0], position?.[1], position?.[2], size?.width, size?.height]);
3242
+ return null;
3243
+ };
3244
+
3245
+ // src/reality/components/Material.tsx
3246
+ import { jsx as jsx24 } from "react/jsx-runtime";
3247
+ var Material = (props) => {
3248
+ if (props.type === "unlit") {
3249
+ const { type, ...rest } = props;
3250
+ return /* @__PURE__ */ jsx24(UnlitMaterial, { ...rest });
3251
+ }
3252
+ return null;
3253
+ };
3254
+
2856
3255
  // src/Model.tsx
2857
3256
  import { forwardRef as forwardRef20 } from "react";
2858
3257
  import { Spatial as Spatial2 } from "@webspatial/core-sdk";
2859
- import { jsx as jsx23 } from "react/jsx-runtime";
3258
+ import { jsx as jsx25 } from "react/jsx-runtime";
2860
3259
  var spatial2 = new Spatial2();
2861
3260
  function ModelBase(props, ref) {
3261
+ const insideAttachment = useInsideAttachment();
2862
3262
  const { "enable-xr": enableXR, ...restProps } = props;
2863
- if (!enableXR || !spatial2.runInSpatialWeb()) {
3263
+ if (!enableXR || !spatial2.runInSpatialWeb() || insideAttachment) {
2864
3264
  const {
2865
3265
  onSpatialTap,
2866
3266
  onSpatialDragStart,
@@ -2870,28 +3270,126 @@ function ModelBase(props, ref) {
2870
3270
  onSpatialRotateEnd,
2871
3271
  onSpatialMagnify,
2872
3272
  onSpatialMagnifyEnd,
3273
+ spatialEventOptions: _spatialEventOptions,
2873
3274
  ...modelProps
2874
3275
  } = restProps;
2875
- return /* @__PURE__ */ jsx23("model", { ref, ...modelProps });
3276
+ return /* @__PURE__ */ jsx25("model", { ref, ...modelProps });
2876
3277
  }
2877
- return /* @__PURE__ */ jsx23(SpatializedStatic3DElementContainer, { ref, ...restProps });
3278
+ return /* @__PURE__ */ jsx25(SpatializedStatic3DElementContainer, { ref, ...restProps });
2878
3279
  }
2879
3280
  var Model = withSSRSupported(forwardRef20(ModelBase));
2880
3281
  Model.displayName = "Model";
2881
3282
 
3283
+ // src/useMetrics.tsx
3284
+ import { useSyncExternalStore } from "react";
3285
+ import { PhysicalMetrics } from "@webspatial/core-sdk";
3286
+ function useMetrics() {
3287
+ useSyncExternalStore(PhysicalMetrics.subscribe, PhysicalMetrics.getValue);
3288
+ const { pointToPhysical, physicalToPoint } = PhysicalMetrics;
3289
+ return { pointToPhysical, physicalToPoint };
3290
+ }
3291
+
3292
+ // src/jsx/jsx-shared.ts
3293
+ import { jsxDEV as _jsxDEV } from "react/jsx-dev-runtime";
3294
+ import reactJSXRuntime from "react/jsx-runtime";
3295
+ import { createElement as reactCreateElement } from "react";
3296
+ var attributeFlag = "enable-xr";
3297
+ var styleFlag = "enableXr";
3298
+ var classFlag = "__enableXr__";
3299
+ var xrMonitorFlag = "enable-xr-monitor";
3300
+ function replaceToSpatialPrimitiveType(type, props) {
3301
+ if (type === Model) {
3302
+ return type;
3303
+ }
3304
+ const propsObject = props;
3305
+ if (attributeFlag in propsObject) {
3306
+ delete propsObject[attributeFlag];
3307
+ return withSpatialized2DElementContainer(type);
3308
+ }
3309
+ if (xrMonitorFlag in propsObject) {
3310
+ delete propsObject[xrMonitorFlag];
3311
+ return withSpatialMonitor(type);
3312
+ }
3313
+ if (propsObject && propsObject.style && styleFlag in propsObject.style) {
3314
+ delete propsObject.style[styleFlag];
3315
+ return withSpatialized2DElementContainer(type);
3316
+ }
3317
+ if (propsObject && typeof propsObject.className === "string") {
3318
+ const originalClassNames = propsObject.className.split(" ");
3319
+ const idx = originalClassNames.indexOf(classFlag);
3320
+ if (idx !== -1) {
3321
+ originalClassNames.splice(idx, 1);
3322
+ propsObject.className = originalClassNames.join(" ");
3323
+ return withSpatialized2DElementContainer(type);
3324
+ }
3325
+ }
3326
+ return type;
3327
+ }
3328
+ function createElement(...args) {
3329
+ const [type, props, ...rest] = args;
3330
+ const newType = replaceToSpatialPrimitiveType(type, props);
3331
+ return reactCreateElement(newType, props, ...rest);
3332
+ }
3333
+
3334
+ // src/utils/convertCoordinate.ts
3335
+ function resolveSpatialObjectId(target) {
3336
+ if (typeof window !== "undefined" && target === window) {
3337
+ const scene = getSession()?.getSpatialScene();
3338
+ return scene?.id ?? "";
3339
+ }
3340
+ const maybeEntity = target;
3341
+ if (maybeEntity && typeof maybeEntity === "object" && "entity" in maybeEntity) {
3342
+ return maybeEntity.entity?.id ?? null;
3343
+ }
3344
+ const dom = target?.__raw ?? target;
3345
+ if (dom && typeof dom === "object") {
3346
+ const spatializedElement = dom.__spatializedElement ?? dom.__innerSpatializedElement?.();
3347
+ if (spatializedElement && spatializedElement.id) {
3348
+ return spatializedElement.id;
3349
+ }
3350
+ }
3351
+ return null;
3352
+ }
3353
+ async function convertCoordinate(position, { from, to }) {
3354
+ try {
3355
+ const fromId = resolveSpatialObjectId(from);
3356
+ const toId = resolveSpatialObjectId(to);
3357
+ if (fromId === null || toId === null) {
3358
+ console.warn(
3359
+ "convertCoordinate error: from or to is not a valid coordinate convertible"
3360
+ );
3361
+ return position;
3362
+ }
3363
+ const spatialScene = getSession()?.getSpatialScene();
3364
+ if (!spatialScene) return position;
3365
+ const ret = await spatialScene.convertCoordinate(position, fromId, toId);
3366
+ return ret ?? position;
3367
+ } catch (error) {
3368
+ console.warn("convertCoordinate error:", error);
3369
+ return position;
3370
+ }
3371
+ }
3372
+
2882
3373
  // src/index.ts
2883
- var version = "1.2.1";
3374
+ var version = "1.4.0";
2884
3375
  if (typeof window !== "undefined") {
2885
3376
  initPolyfill();
2886
3377
  }
2887
3378
  export {
3379
+ AttachmentAsset,
3380
+ AttachmentEntity,
3381
+ BoxEntity as Box,
2888
3382
  BoxEntity,
3383
+ ConeEntity as Cone,
2889
3384
  ConeEntity,
3385
+ CylinderEntity as Cylinder,
2890
3386
  CylinderEntity,
2891
3387
  Entity,
3388
+ Material,
2892
3389
  Model,
2893
3390
  ModelAsset,
2894
3391
  ModelEntity,
3392
+ PlaneEntity as Plane,
2895
3393
  PlaneEntity,
2896
3394
  Reality,
2897
3395
  SSRProvider,
@@ -2900,14 +3398,17 @@ export {
2900
3398
  Spatialized2DElementContainer,
2901
3399
  SpatializedContainer,
2902
3400
  SpatializedStatic3DElementContainer,
3401
+ SphereEntity as Sphere,
2903
3402
  SphereEntity,
2904
3403
  UnlitMaterial,
3404
+ SceneGraph as World,
3405
+ convertCoordinate,
3406
+ createElement,
2905
3407
  enableDebugTool,
2906
3408
  eventMap,
2907
3409
  initPolyfill,
2908
3410
  initScene,
2909
- toLocalSpace,
2910
- toSceneSpatial,
3411
+ useMetrics,
2911
3412
  version,
2912
3413
  withSpatialMonitor,
2913
3414
  withSpatialized2DElementContainer