@webspatial/react-sdk 1.3.0 → 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.3.0"
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, {
@@ -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,6 +1304,14 @@ 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
@@ -1602,6 +1571,7 @@ function DegradedContainer({
1602
1571
  onSpatialRotateEnd: _onSpatialRotateEnd,
1603
1572
  onSpatialMagnify: _onSpatialMagnify,
1604
1573
  onSpatialMagnifyEnd: _onSpatialMagnifyEnd,
1574
+ spatialEventOptions: _spatialEventOptions,
1605
1575
  spatializedContent: _content,
1606
1576
  createSpatializedElement: _create,
1607
1577
  getExtraSpatializedElementProperties: _getExtra,
@@ -1688,6 +1658,7 @@ function SpatializedContainerBase(inprops, ref) {
1688
1658
  spatializedContent,
1689
1659
  createSpatializedElement: createSpatializedElement2,
1690
1660
  getExtraSpatializedElementProperties: getExtraSpatializedElementProperties2,
1661
+ spatialEventOptions: _nestedSpatialEventOptions,
1691
1662
  ...restProps
1692
1663
  } = props;
1693
1664
  return /* @__PURE__ */ jsxs2(SpatialLayerContext.Provider, { value: layer, children: [
@@ -1738,6 +1709,7 @@ function SpatializedContainerBase(inprops, ref) {
1738
1709
  spatializedContent,
1739
1710
  createSpatializedElement: createSpatializedElement2,
1740
1711
  getExtraSpatializedElementProperties: getExtraSpatializedElementProperties2,
1712
+ spatialEventOptions: _rootSpatialEventOptions,
1741
1713
  ...restProps
1742
1714
  } = props;
1743
1715
  return /* @__PURE__ */ jsx6(SpatialLayerContext.Provider, { value: layer, children: /* @__PURE__ */ jsxs2(
@@ -2052,7 +2024,7 @@ import {
2052
2024
  useContext as useContext9,
2053
2025
  useEffect as useEffect13,
2054
2026
  useMemo as useMemo3,
2055
- useRef as useRef4
2027
+ useRef as useRef5
2056
2028
  } from "react";
2057
2029
  import { Fragment as Fragment2, jsx as jsx8 } from "react/jsx-runtime";
2058
2030
  function getAbsoluteURL(url) {
@@ -2127,7 +2099,7 @@ function SpatializedContent2(props) {
2127
2099
  return /* @__PURE__ */ jsx8(Fragment2, {});
2128
2100
  }
2129
2101
  function SpatializedStatic3DElementContainerBase(props, ref) {
2130
- const promiseRef = useRef4(null);
2102
+ const promiseRef = useRef5(null);
2131
2103
  const createSpatializedElement2 = useCallback6(() => {
2132
2104
  const url = getAbsoluteURL(props.src);
2133
2105
  promiseRef.current = getSession().createSpatializedStatic3DElement(url);
@@ -2223,9 +2195,9 @@ function initScene(name, callback) {
2223
2195
  import { forwardRef as forwardRef9 } from "react";
2224
2196
 
2225
2197
  // src/spatialized-container-monitor/useMonitorDomChange.tsx
2226
- import { useRef as useRef5, useEffect as useEffect14, useMemo as useMemo4 } from "react";
2198
+ import { useRef as useRef6, useEffect as useEffect14, useMemo as useMemo4 } from "react";
2227
2199
  function useMonitorDomChange(inRef) {
2228
- const ref = useRef5(null);
2200
+ const ref = useRef6(null);
2229
2201
  useEffect14(() => {
2230
2202
  const observer = new MutationObserver((mutationsList) => {
2231
2203
  notifyDOMUpdate(mutationsList);
@@ -2355,7 +2327,11 @@ var AttachmentRegistry = class {
2355
2327
  }
2356
2328
  getContainers(name) {
2357
2329
  const map = this.containers.get(name);
2358
- return map ? Array.from(map.values()) : [];
2330
+ if (!map) return [];
2331
+ return Array.from(map, ([instanceId, container]) => ({
2332
+ instanceId,
2333
+ container
2334
+ }));
2359
2335
  }
2360
2336
  onContainersChange(name, cb) {
2361
2337
  const current = this.getContainers(name);
@@ -2383,7 +2359,7 @@ var AttachmentRegistry = class {
2383
2359
  var AttachmentContext = createContext8(null);
2384
2360
 
2385
2361
  // src/reality/hooks/useEntityTransform.tsx
2386
- import { useEffect as useEffect16, useRef as useRef6 } from "react";
2362
+ import { useEffect as useEffect16, useRef as useRef7 } from "react";
2387
2363
 
2388
2364
  // src/reality/utils/ResourceRegistry.ts
2389
2365
  var ResourceRegistry = class {
@@ -2464,7 +2440,7 @@ var AbortResourceManager = class {
2464
2440
 
2465
2441
  // src/reality/hooks/useEntityTransform.tsx
2466
2442
  function useEntityTransform(entity, { position, rotation, scale }) {
2467
- const last = useRef6({});
2443
+ const last = useRef7({});
2468
2444
  useEffect16(() => {
2469
2445
  if (!entity) return;
2470
2446
  const shouldUpdate = !shallowEqualVec3(last.current.position, position) || !shallowEqualRotation(last.current.rotation, rotation) || !shallowEqualVec3(last.current.scale, scale);
@@ -2484,7 +2460,7 @@ function useEntityTransform(entity, { position, rotation, scale }) {
2484
2460
  }
2485
2461
 
2486
2462
  // src/reality/hooks/useEntityEvent.tsx
2487
- import { useEffect as useEffect18, useRef as useRef8 } from "react";
2463
+ import { useEffect as useEffect18, useRef as useRef9 } from "react";
2488
2464
 
2489
2465
  // src/reality/type.ts
2490
2466
  var eventMap = {
@@ -2495,11 +2471,9 @@ var eventMap = {
2495
2471
  onSpatialDrag: "spatialdrag",
2496
2472
  onSpatialDragEnd: "spatialdragend",
2497
2473
  // rotate
2498
- onSpatialRotateStart: "spatialrotatestart",
2499
2474
  onSpatialRotate: "spatialrotate",
2500
2475
  onSpatialRotateEnd: "spatialrotateend",
2501
2476
  // magnify
2502
- onSpatialMagnifyStart: "spatialmagnifystart",
2503
2477
  onSpatialMagnify: "spatialmagnify",
2504
2478
  onSpatialMagnifyEnd: "spatialmagnifyend"
2505
2479
  };
@@ -2574,7 +2548,8 @@ var EntityRef = class {
2574
2548
  }
2575
2549
  };
2576
2550
 
2577
- // src/reality/hooks/useEntityEvent.tsx
2551
+ // src/reality/hooks/useRealityEvents.tsx
2552
+ import { useEffect as useEffect19, useRef as useRef10 } from "react";
2578
2553
  function createEventProxy2(ev, instance) {
2579
2554
  return new Proxy(ev, {
2580
2555
  get(target, prop) {
@@ -2687,39 +2662,33 @@ function createEventProxy2(ev, instance) {
2687
2662
  }
2688
2663
  });
2689
2664
  }
2690
- var useEntityEvent = ({ instance, ...handlers }) => {
2691
- const eventsSetRef = useRef8(/* @__PURE__ */ new Set());
2692
- useEffect18(() => {
2693
- const entity = instance.entity;
2694
- if (!entity) return;
2665
+ var useRealityEvents = ({ instance, ...handlers }) => {
2666
+ const eventsSetRef = useRef10(/* @__PURE__ */ new Set());
2667
+ useEffect19(() => {
2668
+ if (!instance) return;
2695
2669
  Object.entries(eventMap).forEach(([reactKey, spatialEvent]) => {
2696
2670
  const handlerFn = handlers[reactKey];
2697
2671
  if (!handlerFn) return;
2698
2672
  const wrapped = (ev) => handlerFn(createEventProxy2(ev, instance));
2699
- entity.addEvent(spatialEvent, wrapped);
2700
- eventsSetRef.current.add(reactKey);
2673
+ instance.addEvent(spatialEvent, wrapped);
2674
+ eventsSetRef.current.add(spatialEvent);
2701
2675
  });
2702
2676
  return () => {
2703
- };
2704
- }, [instance.entity, ...Object.values(handlers)]);
2705
- useEffect18(() => {
2706
- const entity = instance.entity;
2707
- if (!entity) return;
2708
- return () => {
2709
- for (let x of eventsSetRef.current) {
2710
- entity.removeEvent(x);
2677
+ if (instance) {
2678
+ for (let x of eventsSetRef.current) {
2679
+ instance.removeEvent(x);
2680
+ }
2681
+ eventsSetRef.current.clear();
2711
2682
  }
2712
- eventsSetRef.current.clear();
2713
2683
  };
2714
- }, [instance.entity]);
2715
- return null;
2684
+ }, [instance, ...Object.values(handlers)]);
2716
2685
  };
2717
2686
 
2718
2687
  // src/reality/hooks/useEntityId.tsx
2719
- import { useEffect as useEffect19 } from "react";
2688
+ import { useEffect as useEffect20 } from "react";
2720
2689
  var useEntityId = ({ id, entity }) => {
2721
2690
  const ctx = useRealityContext();
2722
- useEffect19(() => {
2691
+ useEffect20(() => {
2723
2692
  if (!id || !entity || !ctx) return;
2724
2693
  ctx.resourceRegistry.add(id, Promise.resolve(entity));
2725
2694
  return () => {
@@ -2730,31 +2699,21 @@ var useEntityId = ({ id, entity }) => {
2730
2699
  };
2731
2700
 
2732
2701
  // src/reality/hooks/useEntity.tsx
2733
- import { useEffect as useEffect20, useRef as useRef9 } from "react";
2702
+ import { useEffect as useEffect21, useRef as useRef11 } from "react";
2734
2703
  var useEntity = ({
2735
2704
  ref,
2736
2705
  id,
2737
2706
  position,
2738
2707
  rotation,
2739
2708
  scale,
2740
- onSpatialTap,
2741
- onSpatialDragStart,
2742
- onSpatialDrag,
2743
- onSpatialDragEnd,
2744
- // onSpatialRotateStart,
2745
- onSpatialRotate,
2746
- onSpatialRotateEnd,
2747
- // onSpatialMagnifyStart,
2748
- onSpatialMagnify,
2749
- onSpatialMagnifyEnd,
2750
- // TODO: add other event handlers
2709
+ enableInput,
2751
2710
  createEntity
2752
2711
  }) => {
2753
2712
  const ctx = useRealityContext();
2754
2713
  const parent = useParentContext();
2755
- const instanceRef = useRef9(new EntityRef(null, ctx));
2714
+ const instanceRef = useRef11(new EntityRef(null, ctx));
2756
2715
  const forceUpdate = useForceUpdate2();
2757
- useEffect20(() => {
2716
+ useEffect21(() => {
2758
2717
  if (!ctx) return;
2759
2718
  const controller = new AbortController();
2760
2719
  const init = async () => {
@@ -2787,19 +2746,13 @@ var useEntity = ({
2787
2746
  useEntityId({ id, entity: instanceRef.current.entity });
2788
2747
  useEntityTransform(instanceRef.current.entity, { position, rotation, scale });
2789
2748
  useEntityRef(ref, instanceRef.current);
2790
- useEntityEvent({
2791
- instance: instanceRef.current,
2792
- onSpatialTap,
2793
- onSpatialDragStart,
2794
- onSpatialDrag,
2795
- onSpatialDragEnd,
2796
- // onSpatialRotateStart,
2797
- onSpatialRotate,
2798
- onSpatialRotateEnd,
2799
- // onSpatialMagnifyStart,
2800
- onSpatialMagnify,
2801
- onSpatialMagnifyEnd
2802
- });
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]);
2803
2756
  return instanceRef.current.entity;
2804
2757
  };
2805
2758
 
@@ -2911,11 +2864,14 @@ var BoxEntity = forwardRef13(
2911
2864
  );
2912
2865
 
2913
2866
  // src/reality/components/UnlitMaterial.tsx
2914
- import { useEffect as useEffect21, useRef as useRef10 } from "react";
2915
- var UnlitMaterial = ({ children, ...options }) => {
2867
+ import { useEffect as useEffect22, useRef as useRef12 } from "react";
2868
+ var UnlitMaterial = ({
2869
+ children,
2870
+ ...options
2871
+ }) => {
2916
2872
  const ctx = useRealityContext();
2917
- const materialRef = useRef10();
2918
- useEffect21(() => {
2873
+ const materialRef = useRef12();
2874
+ useEffect22(() => {
2919
2875
  if (!ctx) return;
2920
2876
  const { session, reality, resourceRegistry } = ctx;
2921
2877
  const init = async () => {
@@ -3031,7 +2987,7 @@ var SceneGraph = ({ children }) => {
3031
2987
  };
3032
2988
 
3033
2989
  // src/reality/components/ModelAsset.tsx
3034
- import { useEffect as useEffect22, useRef as useRef11 } from "react";
2990
+ import { useEffect as useEffect23, useRef as useRef13 } from "react";
3035
2991
  var resolveAssetUrl = (url) => {
3036
2992
  if (url.startsWith("http://") || url.startsWith("https://")) {
3037
2993
  return url;
@@ -3040,8 +2996,8 @@ var resolveAssetUrl = (url) => {
3040
2996
  };
3041
2997
  var ModelAsset = ({ children, ...options }) => {
3042
2998
  const ctx = useRealityContext();
3043
- const materialRef = useRef11();
3044
- useEffect22(() => {
2999
+ const materialRef = useRef13();
3000
+ useEffect23(() => {
3045
3001
  const controller = new AbortController();
3046
3002
  if (!ctx) return;
3047
3003
  const { session, reality, resourceRegistry } = ctx;
@@ -3108,8 +3064,8 @@ var ModelEntity = forwardRef18(
3108
3064
  import {
3109
3065
  forwardRef as forwardRef19,
3110
3066
  useCallback as useCallback8,
3111
- useEffect as useEffect23,
3112
- useRef as useRef12,
3067
+ useEffect as useEffect24,
3068
+ useRef as useRef14,
3113
3069
  useState as useState8
3114
3070
  } from "react";
3115
3071
  import { Fragment as Fragment3, jsx as jsx22, jsxs as jsxs3 } from "react/jsx-runtime";
@@ -3133,8 +3089,8 @@ var Reality = forwardRef19(
3133
3089
  onSpatialMagnifyEnd,
3134
3090
  ...props
3135
3091
  } = inProps;
3136
- const ctxRef = useRef12(null);
3137
- const creationId = useRef12(0);
3092
+ const ctxRef = useRef14(null);
3093
+ const creationId = useRef14(0);
3138
3094
  const [isReady, setIsReady] = useState8(false);
3139
3095
  const cleanupReality = useCallback8(() => {
3140
3096
  ctxRef.current?.attachmentRegistry.destroy();
@@ -3143,7 +3099,7 @@ var Reality = forwardRef19(
3143
3099
  ctxRef.current = null;
3144
3100
  setIsReady(false);
3145
3101
  }, []);
3146
- useEffect23(() => {
3102
+ useEffect24(() => {
3147
3103
  return () => {
3148
3104
  creationId.current++;
3149
3105
  cleanupReality();
@@ -3193,6 +3149,17 @@ var Reality = forwardRef19(
3193
3149
  }
3194
3150
  }, [cleanupReality]);
3195
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
+ });
3196
3163
  return /* @__PURE__ */ jsxs3(RealityContext.Provider, { value: ctxRef.current, children: [
3197
3164
  /* @__PURE__ */ jsx22(
3198
3165
  SpatializedContainer,
@@ -3210,7 +3177,7 @@ var Reality = forwardRef19(
3210
3177
  );
3211
3178
 
3212
3179
  // src/reality/components/AttachmentAsset.tsx
3213
- import { useEffect as useEffect24, useState as useState9 } from "react";
3180
+ import { useEffect as useEffect25, useState as useState9 } from "react";
3214
3181
  import { createPortal as createPortal3 } from "react-dom";
3215
3182
  import { jsx as jsx23 } from "react/jsx-runtime";
3216
3183
  var AttachmentAsset = ({
@@ -3219,16 +3186,18 @@ var AttachmentAsset = ({
3219
3186
  }) => {
3220
3187
  const ctx = useRealityContext();
3221
3188
  const [containers, setContainers] = useState9([]);
3222
- useEffect24(() => {
3189
+ useEffect25(() => {
3223
3190
  if (!ctx) return;
3224
3191
  return ctx.attachmentRegistry.onContainersChange(name, setContainers);
3225
3192
  }, [ctx, name]);
3226
3193
  if (!containers.length) return null;
3227
- return /* @__PURE__ */ jsx23(InsideAttachmentContext.Provider, { value: true, children: containers.map((c, idx) => createPortal3(children, c, `${name}-${idx}`)) });
3194
+ return /* @__PURE__ */ jsx23(InsideAttachmentContext.Provider, { value: true, children: containers.map(
3195
+ ({ instanceId, container }) => createPortal3(children, container, instanceId)
3196
+ ) });
3228
3197
  };
3229
3198
 
3230
3199
  // src/reality/components/AttachmentEntity.tsx
3231
- import { useEffect as useEffect25, useRef as useRef13, useState as useState10 } from "react";
3200
+ import { useEffect as useEffect26, useRef as useRef15, useState as useState10 } from "react";
3232
3201
  var instanceCounter = 0;
3233
3202
  var AttachmentEntity = ({
3234
3203
  attachment: attachmentName,
@@ -3237,13 +3206,14 @@ var AttachmentEntity = ({
3237
3206
  }) => {
3238
3207
  const ctx = useRealityContext();
3239
3208
  const parent = useParentContext();
3240
- const attachmentRef = useRef13(null);
3241
- const parentIdRef = useRef13(null);
3242
- const instanceIdRef = useRef13(`att_${++instanceCounter}`);
3243
- const attachmentNameRef = useRef13(attachmentName);
3209
+ const attachmentRef = useRef15(null);
3210
+ const parentIdRef = useRef15(null);
3211
+ const instanceIdRef = useRef15(`att_${++instanceCounter}`);
3212
+ const attachmentNameRef = useRef15(attachmentName);
3244
3213
  const [childWindow, setChildWindow] = useState10(null);
3245
- useEffect25(() => {
3214
+ useEffect26(() => {
3246
3215
  if (!ctx || !parent) return;
3216
+ if (attachmentRef.current) return;
3247
3217
  const parentId = parent.id;
3248
3218
  parentIdRef.current = parentId;
3249
3219
  let cancelled = false;
@@ -3252,7 +3222,8 @@ var AttachmentEntity = ({
3252
3222
  const att = await ctx.session.createAttachmentEntity({
3253
3223
  parentEntityId: parentId,
3254
3224
  position: position ?? [0, 0, 0],
3255
- size
3225
+ size,
3226
+ ownerViewId: ctx.reality.id
3256
3227
  });
3257
3228
  if (cancelled) {
3258
3229
  att.destroy();
@@ -3264,7 +3235,6 @@ var AttachmentEntity = ({
3264
3235
  windowProxy.document.body.style.minWidth = "100%";
3265
3236
  windowProxy.document.body.style.maxWidth = "100%";
3266
3237
  windowProxy.document.body.style.minHeight = "100%";
3267
- await syncParentHeadToChild(windowProxy);
3268
3238
  const viewport = windowProxy.document.querySelector(
3269
3239
  'meta[name="viewport"]'
3270
3240
  );
@@ -3303,7 +3273,7 @@ var AttachmentEntity = ({
3303
3273
  }
3304
3274
  };
3305
3275
  }, [ctx, parent]);
3306
- useEffect25(() => {
3276
+ useEffect26(() => {
3307
3277
  if (!ctx) return;
3308
3278
  const att = attachmentRef.current;
3309
3279
  const prevName = attachmentNameRef.current;
@@ -3320,16 +3290,26 @@ var AttachmentEntity = ({
3320
3290
  }
3321
3291
  }, [ctx, attachmentName]);
3322
3292
  useSyncHeadStyles(childWindow, { subtree: false });
3323
- useEffect25(() => {
3293
+ useEffect26(() => {
3324
3294
  if (!attachmentRef.current) return;
3325
3295
  attachmentRef.current.update({ position, size });
3326
3296
  }, [position?.[0], position?.[1], position?.[2], size?.width, size?.height]);
3327
3297
  return null;
3328
3298
  };
3329
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
+
3330
3310
  // src/Model.tsx
3331
3311
  import { forwardRef as forwardRef20 } from "react";
3332
- import { jsx as jsx24 } from "react/jsx-runtime";
3312
+ import { jsx as jsx25 } from "react/jsx-runtime";
3333
3313
  var spatial2 = new Spatial();
3334
3314
  function ModelBase(props, ref) {
3335
3315
  const insideAttachment = useInsideAttachment();
@@ -3344,30 +3324,125 @@ function ModelBase(props, ref) {
3344
3324
  onSpatialRotateEnd,
3345
3325
  onSpatialMagnify,
3346
3326
  onSpatialMagnifyEnd,
3327
+ spatialEventOptions: _spatialEventOptions,
3347
3328
  ...modelProps
3348
3329
  } = restProps;
3349
- return /* @__PURE__ */ jsx24("model", { ref, ...modelProps });
3330
+ return /* @__PURE__ */ jsx25("model", { ref, ...modelProps });
3350
3331
  }
3351
- return /* @__PURE__ */ jsx24(SpatializedStatic3DElementContainer, { ref, ...restProps });
3332
+ return /* @__PURE__ */ jsx25(SpatializedStatic3DElementContainer, { ref, ...restProps });
3352
3333
  }
3353
3334
  var Model = withSSRSupported(forwardRef20(ModelBase));
3354
3335
  Model.displayName = "Model";
3355
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
+
3356
3426
  // src/index.ts
3357
- var version = "1.3.0";
3427
+ var version = "1.4.0";
3358
3428
  if (typeof window !== "undefined") {
3359
3429
  initPolyfill();
3360
3430
  }
3361
3431
  export {
3362
3432
  AttachmentAsset,
3363
3433
  AttachmentEntity,
3434
+ BoxEntity as Box,
3364
3435
  BoxEntity,
3436
+ ConeEntity as Cone,
3365
3437
  ConeEntity,
3438
+ CylinderEntity as Cylinder,
3366
3439
  CylinderEntity,
3367
3440
  Entity,
3441
+ Material,
3368
3442
  Model,
3369
3443
  ModelAsset,
3370
3444
  ModelEntity,
3445
+ PlaneEntity as Plane,
3371
3446
  PlaneEntity,
3372
3447
  Reality,
3373
3448
  SSRProvider,
@@ -3376,14 +3451,17 @@ export {
3376
3451
  Spatialized2DElementContainer,
3377
3452
  SpatializedContainer,
3378
3453
  SpatializedStatic3DElementContainer,
3454
+ SphereEntity as Sphere,
3379
3455
  SphereEntity,
3380
3456
  UnlitMaterial,
3457
+ SceneGraph as World,
3458
+ convertCoordinate,
3459
+ createElement,
3381
3460
  enableDebugTool,
3382
3461
  eventMap,
3383
3462
  initPolyfill,
3384
3463
  initScene,
3385
- toLocalSpace,
3386
- toSceneSpatial,
3464
+ useMetrics,
3387
3465
  version,
3388
3466
  withSpatialMonitor,
3389
3467
  withSpatialized2DElementContainer