@webspatial/react-sdk 1.6.1 → 1.7.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/README.md +9 -0
- package/dist/default/index.d.ts +73 -6
- package/dist/default/index.js +1118 -701
- package/dist/default/index.js.map +1 -1
- package/dist/jsx/jsx-dev-runtime.d.ts +27 -23
- package/dist/jsx/jsx-dev-runtime.js +4 -3
- package/dist/jsx/jsx-dev-runtime.js.map +1 -1
- package/dist/jsx/jsx-dev-runtime.web.js +1 -1
- package/dist/jsx/jsx-runtime.js +4 -3
- package/dist/jsx/jsx-runtime.js.map +1 -1
- package/dist/jsx/jsx-runtime.web.js +1 -1
- package/dist/web/index.d.ts +73 -6
- package/dist/web/index.js +1132 -704
- package/dist/web/index.js.map +1 -1
- package/package.json +6 -6
package/dist/web/index.js
CHANGED
|
@@ -2,498 +2,17 @@
|
|
|
2
2
|
(function(){
|
|
3
3
|
if(typeof window === 'undefined') return;
|
|
4
4
|
if(!window.__webspatialsdk__) window.__webspatialsdk__ = {}
|
|
5
|
-
window.__webspatialsdk__['react-sdk-version'] = "1.
|
|
5
|
+
window.__webspatialsdk__['react-sdk-version'] = "1.7.0"
|
|
6
6
|
window.__webspatialsdk__['XR_ENV'] = "web"
|
|
7
7
|
})()
|
|
8
8
|
|
|
9
9
|
|
|
10
|
-
// src/spatialized-container/hooks/useDomProxy.ts
|
|
11
|
-
import { useCallback, useEffect, useRef } from "react";
|
|
12
|
-
|
|
13
|
-
// src/spatialized-container/types.ts
|
|
14
|
-
var SpatialCustomStyleVars = {
|
|
15
|
-
back: "--xr-back",
|
|
16
|
-
depth: "--xr-depth",
|
|
17
|
-
backgroundMaterial: "--xr-background-material",
|
|
18
|
-
xrZIndex: "--xr-z-index"
|
|
19
|
-
};
|
|
20
|
-
|
|
21
|
-
// src/spatialized-container/utils.ts
|
|
22
|
-
function getInheritedStyleProps(computedStyle) {
|
|
23
|
-
var propNames = [
|
|
24
|
-
"azimuth",
|
|
25
|
-
"borderCollapse",
|
|
26
|
-
"borderSpacing",
|
|
27
|
-
"captionSide",
|
|
28
|
-
"color",
|
|
29
|
-
"cursor",
|
|
30
|
-
"direction",
|
|
31
|
-
// 'elevation',
|
|
32
|
-
"emptyCells",
|
|
33
|
-
"fontFamily",
|
|
34
|
-
"fontSize",
|
|
35
|
-
"fontStyle",
|
|
36
|
-
"fontVariant",
|
|
37
|
-
"fontWeight",
|
|
38
|
-
"font",
|
|
39
|
-
"letterSpacing",
|
|
40
|
-
"lineHeight",
|
|
41
|
-
"listStyleImage",
|
|
42
|
-
"listStylePosition",
|
|
43
|
-
"listStyleType",
|
|
44
|
-
"listStyle",
|
|
45
|
-
"orphans",
|
|
46
|
-
// 'pitchRange',
|
|
47
|
-
// 'pitch',
|
|
48
|
-
"quotes",
|
|
49
|
-
// 'richness',
|
|
50
|
-
// 'speakHeader',
|
|
51
|
-
// 'speakNumeral',
|
|
52
|
-
// 'speakPunctuation',
|
|
53
|
-
// 'speak',
|
|
54
|
-
// 'speechRate',
|
|
55
|
-
// 'stress',
|
|
56
|
-
"textAlign",
|
|
57
|
-
"textIndent",
|
|
58
|
-
"textTransform",
|
|
59
|
-
"visibility",
|
|
60
|
-
// 'voiceFamily',
|
|
61
|
-
// 'volume',
|
|
62
|
-
"whiteSpace",
|
|
63
|
-
"widows",
|
|
64
|
-
"wordSpacing",
|
|
65
|
-
// background also need to be synced
|
|
66
|
-
"background",
|
|
67
|
-
// position also need to be synced
|
|
68
|
-
"position",
|
|
69
|
-
"width",
|
|
70
|
-
"height",
|
|
71
|
-
"display",
|
|
72
|
-
// content-visibility also need to be synced
|
|
73
|
-
"contentVisibility"
|
|
74
|
-
];
|
|
75
|
-
var props = {};
|
|
76
|
-
for (var cssName of propNames) {
|
|
77
|
-
if (computedStyle[cssName]) {
|
|
78
|
-
props[cssName] = computedStyle[cssName];
|
|
79
|
-
}
|
|
80
|
-
}
|
|
81
|
-
return props;
|
|
82
|
-
}
|
|
83
|
-
function parseTransformOrigin(computedStyle) {
|
|
84
|
-
const transformOriginProperty = computedStyle.getPropertyValue("transform-origin");
|
|
85
|
-
const [x, y] = transformOriginProperty.split(" ").map(parseFloat);
|
|
86
|
-
const width = parseFloat(computedStyle.getPropertyValue("width"));
|
|
87
|
-
const height = parseFloat(computedStyle.getPropertyValue("height"));
|
|
88
|
-
return {
|
|
89
|
-
x: width > 0 ? x / width : 0.5,
|
|
90
|
-
y: height > 0 ? y / height : 0.5,
|
|
91
|
-
z: 0.5
|
|
92
|
-
};
|
|
93
|
-
}
|
|
94
|
-
function parseBorderRadius(borderProperty, width) {
|
|
95
|
-
if (borderProperty === "") {
|
|
96
|
-
return 0;
|
|
97
|
-
}
|
|
98
|
-
if (borderProperty.endsWith("%")) {
|
|
99
|
-
return width * parseFloat(borderProperty) / 100;
|
|
100
|
-
}
|
|
101
|
-
return parseFloat(borderProperty);
|
|
102
|
-
}
|
|
103
|
-
function parseCornerRadius(computedStyle) {
|
|
104
|
-
const width = parseFloat(computedStyle.getPropertyValue("width"));
|
|
105
|
-
const topLeftPropertyValue = computedStyle.getPropertyValue(
|
|
106
|
-
"border-top-left-radius"
|
|
107
|
-
);
|
|
108
|
-
const topRightPropertyValue = computedStyle.getPropertyValue(
|
|
109
|
-
"border-top-right-radius"
|
|
110
|
-
);
|
|
111
|
-
const bottomLeftPropertyValue = computedStyle.getPropertyValue(
|
|
112
|
-
"border-bottom-left-radius"
|
|
113
|
-
);
|
|
114
|
-
const bottomRightPropertyValue = computedStyle.getPropertyValue(
|
|
115
|
-
"border-bottom-right-radius"
|
|
116
|
-
);
|
|
117
|
-
const cornerRadius = {
|
|
118
|
-
topLeading: parseBorderRadius(topLeftPropertyValue, width),
|
|
119
|
-
bottomLeading: parseBorderRadius(bottomLeftPropertyValue, width),
|
|
120
|
-
topTrailing: parseBorderRadius(topRightPropertyValue, width),
|
|
121
|
-
bottomTrailing: parseBorderRadius(bottomRightPropertyValue, width)
|
|
122
|
-
};
|
|
123
|
-
return cornerRadius;
|
|
124
|
-
}
|
|
125
|
-
function extractAndRemoveCustomProperties(cssText, properties) {
|
|
126
|
-
if (!cssText) {
|
|
127
|
-
return { extractedValues: {}, filteredCssText: "" };
|
|
128
|
-
}
|
|
129
|
-
const extractedValues = {};
|
|
130
|
-
const rules = cssText.split(";");
|
|
131
|
-
const filteredRules = rules.filter((rule) => {
|
|
132
|
-
const [key, value] = rule.split(":").map((part) => part.trim());
|
|
133
|
-
if (properties.includes(key)) {
|
|
134
|
-
extractedValues[key] = value;
|
|
135
|
-
return false;
|
|
136
|
-
}
|
|
137
|
-
return true;
|
|
138
|
-
});
|
|
139
|
-
const filteredCssText = filteredRules.join(";").trim();
|
|
140
|
-
return { extractedValues, filteredCssText };
|
|
141
|
-
}
|
|
142
|
-
function joinToCSSText(cssKV) {
|
|
143
|
-
const rules = Object.entries(cssKV).map(([key, value]) => `${key}: ${value}`);
|
|
144
|
-
return rules.join(";");
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
// src/spatialized-container/hooks/useDomProxy.ts
|
|
148
|
-
var SpatialContainerRefProxy = class {
|
|
149
|
-
transformVisibilityTaskContainerDom = null;
|
|
150
|
-
/** Raw Standard host element (styled root). Used to mirror class onto the transform probe. */
|
|
151
|
-
standardRawDom = null;
|
|
152
|
-
standardClassObserver = null;
|
|
153
|
-
/**
|
|
154
|
-
* When set, Standard's DOM className is forwarded here so TransformVisibilityTaskContainer
|
|
155
|
-
* can render it from React state (avoids React clobbering imperative class updates).
|
|
156
|
-
*/
|
|
157
|
-
mirrorClassNotify = null;
|
|
158
|
-
/** Last class string applied to the probe + used to skip redundant syncs. */
|
|
159
|
-
lastMirroredClassName = null;
|
|
160
|
-
/** Coalesce multiple class sync triggers in the same turn (Observer + classList, etc.). */
|
|
161
|
-
classSyncMicrotaskQueued = false;
|
|
162
|
-
ref;
|
|
163
|
-
domProxy;
|
|
164
|
-
styleProxy;
|
|
165
|
-
// extre ref props, used to add extra props to ref
|
|
166
|
-
extraRefProps;
|
|
167
|
-
constructor(ref, extraRefProps) {
|
|
168
|
-
this.ref = ref;
|
|
169
|
-
this.extraRefProps = extraRefProps;
|
|
170
|
-
}
|
|
171
|
-
setMirrorClassNotify(fn) {
|
|
172
|
-
this.mirrorClassNotify = fn;
|
|
173
|
-
if (fn && this.standardRawDom) {
|
|
174
|
-
this.flushSyncTransformClassFromStandard(true);
|
|
175
|
-
}
|
|
176
|
-
}
|
|
177
|
-
disconnectStandardClassObserver() {
|
|
178
|
-
this.standardClassObserver?.disconnect();
|
|
179
|
-
this.standardClassObserver = null;
|
|
180
|
-
}
|
|
181
|
-
attachStandardClassObserver() {
|
|
182
|
-
this.disconnectStandardClassObserver();
|
|
183
|
-
if (!this.standardRawDom) {
|
|
184
|
-
return;
|
|
185
|
-
}
|
|
186
|
-
this.standardClassObserver = new MutationObserver(() => {
|
|
187
|
-
this.scheduleSyncTransformClassFromStandard();
|
|
188
|
-
});
|
|
189
|
-
this.standardClassObserver.observe(this.standardRawDom, {
|
|
190
|
-
attributes: true,
|
|
191
|
-
attributeFilter: ["class"]
|
|
192
|
-
});
|
|
193
|
-
}
|
|
194
|
-
/**
|
|
195
|
-
* Merge multiple sync requests (e.g. classList hook + MutationObserver) into one microtask.
|
|
196
|
-
*/
|
|
197
|
-
scheduleSyncTransformClassFromStandard() {
|
|
198
|
-
if (this.classSyncMicrotaskQueued) {
|
|
199
|
-
return;
|
|
200
|
-
}
|
|
201
|
-
this.classSyncMicrotaskQueued = true;
|
|
202
|
-
queueMicrotask(() => {
|
|
203
|
-
this.classSyncMicrotaskQueued = false;
|
|
204
|
-
this.flushSyncTransformClassFromStandard(false);
|
|
205
|
-
});
|
|
206
|
-
}
|
|
207
|
-
/**
|
|
208
|
-
* Source of truth: Standard host DOM (incl. styled-components runtime class changes).
|
|
209
|
-
* @param force when true, skip same-string short-circuit (e.g. mirror notify just registered).
|
|
210
|
-
*/
|
|
211
|
-
flushSyncTransformClassFromStandard(force) {
|
|
212
|
-
if (!this.standardRawDom) {
|
|
213
|
-
return;
|
|
214
|
-
}
|
|
215
|
-
const name = this.standardRawDom.className;
|
|
216
|
-
const probe = this.transformVisibilityTaskContainerDom;
|
|
217
|
-
if (!force && probe && probe.className === name && this.lastMirroredClassName === name) {
|
|
218
|
-
return;
|
|
219
|
-
}
|
|
220
|
-
this.lastMirroredClassName = name;
|
|
221
|
-
if (probe) {
|
|
222
|
-
probe.className = name;
|
|
223
|
-
}
|
|
224
|
-
this.mirrorClassNotify?.(name);
|
|
225
|
-
}
|
|
226
|
-
updateStandardSpatializedContainerDom(dom) {
|
|
227
|
-
const self = this;
|
|
228
|
-
if (!dom) {
|
|
229
|
-
this.disconnectStandardClassObserver();
|
|
230
|
-
this.standardRawDom = null;
|
|
231
|
-
this.lastMirroredClassName = null;
|
|
232
|
-
this.domProxy = void 0;
|
|
233
|
-
this.styleProxy = void 0;
|
|
234
|
-
this.updateDomProxyToRef();
|
|
235
|
-
return;
|
|
236
|
-
}
|
|
237
|
-
this.standardRawDom = dom;
|
|
238
|
-
let cacheExtraRefProps;
|
|
239
|
-
const domProxy = new Proxy(
|
|
240
|
-
dom,
|
|
241
|
-
{
|
|
242
|
-
get(target, prop) {
|
|
243
|
-
if (prop === "__raw") {
|
|
244
|
-
return target;
|
|
245
|
-
}
|
|
246
|
-
if (prop === "xrClientDepth") {
|
|
247
|
-
return target.style.getPropertyValue(SpatialCustomStyleVars.depth);
|
|
248
|
-
}
|
|
249
|
-
if (prop === "xrOffsetBack") {
|
|
250
|
-
return target.style.getPropertyValue(SpatialCustomStyleVars.back);
|
|
251
|
-
}
|
|
252
|
-
if (prop === "style") {
|
|
253
|
-
if (!self.styleProxy) {
|
|
254
|
-
self.styleProxy = new Proxy(target.style, {
|
|
255
|
-
get(target2, prop2) {
|
|
256
|
-
if (prop2 === "visibility" || prop2 === "transform") {
|
|
257
|
-
return self.transformVisibilityTaskContainerDom?.style.getPropertyValue(
|
|
258
|
-
prop2
|
|
259
|
-
);
|
|
260
|
-
}
|
|
261
|
-
const value2 = Reflect.get(target2, prop2);
|
|
262
|
-
if (typeof value2 === "function") {
|
|
263
|
-
if (prop2 === "setProperty" || prop2 === "removeProperty" || prop2 === "getPropertyValue") {
|
|
264
|
-
return function(...args) {
|
|
265
|
-
const validProperties = ["visibility", "transform"];
|
|
266
|
-
const [property] = args;
|
|
267
|
-
if (validProperties.includes(property)) {
|
|
268
|
-
if (prop2 === "setProperty") {
|
|
269
|
-
const [, kValue] = args;
|
|
270
|
-
self.transformVisibilityTaskContainerDom?.style.setProperty(
|
|
271
|
-
property,
|
|
272
|
-
kValue
|
|
273
|
-
);
|
|
274
|
-
} else if (prop2 === "removeProperty") {
|
|
275
|
-
self.transformVisibilityTaskContainerDom?.style.removeProperty(
|
|
276
|
-
property
|
|
277
|
-
);
|
|
278
|
-
} else if (prop2 === "getPropertyValue") {
|
|
279
|
-
return self.transformVisibilityTaskContainerDom?.style.getPropertyValue(
|
|
280
|
-
property
|
|
281
|
-
);
|
|
282
|
-
}
|
|
283
|
-
} else {
|
|
284
|
-
return value2.apply(this, args);
|
|
285
|
-
}
|
|
286
|
-
}.bind(target2);
|
|
287
|
-
} else {
|
|
288
|
-
return value2.bind(target2);
|
|
289
|
-
}
|
|
290
|
-
} else {
|
|
291
|
-
return value2;
|
|
292
|
-
}
|
|
293
|
-
},
|
|
294
|
-
set(target2, prop2, value2) {
|
|
295
|
-
if (prop2 === "visibility") {
|
|
296
|
-
self.transformVisibilityTaskContainerDom?.style.setProperty(
|
|
297
|
-
"visibility",
|
|
298
|
-
value2
|
|
299
|
-
);
|
|
300
|
-
return true;
|
|
301
|
-
}
|
|
302
|
-
if (prop2 === "transform") {
|
|
303
|
-
self.transformVisibilityTaskContainerDom?.style.setProperty(
|
|
304
|
-
"transform",
|
|
305
|
-
value2
|
|
306
|
-
);
|
|
307
|
-
return true;
|
|
308
|
-
}
|
|
309
|
-
if (prop2 === SpatialCustomStyleVars.backgroundMaterial) {
|
|
310
|
-
target2.setProperty(
|
|
311
|
-
SpatialCustomStyleVars.backgroundMaterial,
|
|
312
|
-
value2
|
|
313
|
-
);
|
|
314
|
-
} else if (prop2 === SpatialCustomStyleVars.back) {
|
|
315
|
-
target2.setProperty(
|
|
316
|
-
SpatialCustomStyleVars.back,
|
|
317
|
-
value2
|
|
318
|
-
);
|
|
319
|
-
} else if (prop2 === SpatialCustomStyleVars.xrZIndex) {
|
|
320
|
-
target2.setProperty(
|
|
321
|
-
SpatialCustomStyleVars.xrZIndex,
|
|
322
|
-
value2
|
|
323
|
-
);
|
|
324
|
-
} else if (prop2 === SpatialCustomStyleVars.depth) {
|
|
325
|
-
target2.setProperty(
|
|
326
|
-
SpatialCustomStyleVars.depth,
|
|
327
|
-
value2
|
|
328
|
-
);
|
|
329
|
-
} else if (prop2 === "cssText") {
|
|
330
|
-
const toFilteredCSSProperties = ["transform", "visibility"];
|
|
331
|
-
const { extractedValues, filteredCssText } = extractAndRemoveCustomProperties(
|
|
332
|
-
value2,
|
|
333
|
-
toFilteredCSSProperties
|
|
334
|
-
);
|
|
335
|
-
toFilteredCSSProperties.forEach((key) => {
|
|
336
|
-
if (extractedValues[key]) {
|
|
337
|
-
self.transformVisibilityTaskContainerDom?.style.setProperty(
|
|
338
|
-
key,
|
|
339
|
-
extractedValues[key]
|
|
340
|
-
);
|
|
341
|
-
} else {
|
|
342
|
-
target2.removeProperty(key);
|
|
343
|
-
}
|
|
344
|
-
});
|
|
345
|
-
const appendedCSSText = joinToCSSText({
|
|
346
|
-
transform: "none",
|
|
347
|
-
visibility: "hidden"
|
|
348
|
-
});
|
|
349
|
-
return Reflect.set(
|
|
350
|
-
target2,
|
|
351
|
-
prop2,
|
|
352
|
-
[appendedCSSText, filteredCssText].join(";")
|
|
353
|
-
);
|
|
354
|
-
}
|
|
355
|
-
return Reflect.set(target2, prop2, value2);
|
|
356
|
-
}
|
|
357
|
-
});
|
|
358
|
-
}
|
|
359
|
-
return self.styleProxy;
|
|
360
|
-
}
|
|
361
|
-
if (typeof prop === "string" && self.extraRefProps) {
|
|
362
|
-
if (!cacheExtraRefProps) {
|
|
363
|
-
cacheExtraRefProps = self.extraRefProps(domProxy);
|
|
364
|
-
}
|
|
365
|
-
const extraProps = cacheExtraRefProps;
|
|
366
|
-
if (extraProps.hasOwnProperty(prop)) {
|
|
367
|
-
return extraProps[prop];
|
|
368
|
-
}
|
|
369
|
-
}
|
|
370
|
-
const value = Reflect.get(target, prop);
|
|
371
|
-
if (typeof value === "function") {
|
|
372
|
-
if ("removeAttribute" === prop) {
|
|
373
|
-
return function(...args) {
|
|
374
|
-
const [property] = args;
|
|
375
|
-
if (property === "style") {
|
|
376
|
-
dom.style.cssText = "visibility: hidden; transition: none; transform: none;";
|
|
377
|
-
if (self.transformVisibilityTaskContainerDom) {
|
|
378
|
-
self.transformVisibilityTaskContainerDom.style.visibility = "";
|
|
379
|
-
self.transformVisibilityTaskContainerDom.style.transform = "";
|
|
380
|
-
}
|
|
381
|
-
return true;
|
|
382
|
-
}
|
|
383
|
-
if (property === "class") {
|
|
384
|
-
domProxy.className = "xr-spatial-default";
|
|
385
|
-
return true;
|
|
386
|
-
}
|
|
387
|
-
};
|
|
388
|
-
}
|
|
389
|
-
return value.bind(target);
|
|
390
|
-
}
|
|
391
|
-
return value;
|
|
392
|
-
},
|
|
393
|
-
set(target, prop, value) {
|
|
394
|
-
if (prop === "className") {
|
|
395
|
-
if (value && String(value).indexOf("xr-spatial-default") === -1) {
|
|
396
|
-
value = value + " xr-spatial-default";
|
|
397
|
-
}
|
|
398
|
-
}
|
|
399
|
-
if (typeof prop === "string" && self.extraRefProps) {
|
|
400
|
-
if (!cacheExtraRefProps) {
|
|
401
|
-
cacheExtraRefProps = self.extraRefProps(domProxy);
|
|
402
|
-
}
|
|
403
|
-
cacheExtraRefProps[prop] = value;
|
|
404
|
-
}
|
|
405
|
-
const ok = Reflect.set(target, prop, value);
|
|
406
|
-
if (ok && prop === "className") {
|
|
407
|
-
self.scheduleSyncTransformClassFromStandard();
|
|
408
|
-
}
|
|
409
|
-
return ok;
|
|
410
|
-
}
|
|
411
|
-
}
|
|
412
|
-
);
|
|
413
|
-
this.domProxy = domProxy;
|
|
414
|
-
this.styleProxy = void 0;
|
|
415
|
-
this.updateDomProxyToRef();
|
|
416
|
-
Object.assign(dom, {
|
|
417
|
-
__targetProxy: domProxy
|
|
418
|
-
});
|
|
419
|
-
this.attachStandardClassObserver();
|
|
420
|
-
this.scheduleSyncTransformClassFromStandard();
|
|
421
|
-
}
|
|
422
|
-
updateTransformVisibilityTaskContainerDom(dom) {
|
|
423
|
-
this.transformVisibilityTaskContainerDom = dom;
|
|
424
|
-
if (!dom) {
|
|
425
|
-
this.lastMirroredClassName = null;
|
|
426
|
-
}
|
|
427
|
-
this.scheduleSyncTransformClassFromStandard();
|
|
428
|
-
this.updateDomProxyToRef();
|
|
429
|
-
}
|
|
430
|
-
updateDomProxyToRef() {
|
|
431
|
-
const ref = this.ref;
|
|
432
|
-
if (!ref) {
|
|
433
|
-
return;
|
|
434
|
-
}
|
|
435
|
-
if (this.domProxy && this.transformVisibilityTaskContainerDom) {
|
|
436
|
-
if (typeof ref === "function") {
|
|
437
|
-
ref(this.domProxy);
|
|
438
|
-
} else {
|
|
439
|
-
ref.current = this.domProxy;
|
|
440
|
-
}
|
|
441
|
-
} else {
|
|
442
|
-
if (typeof ref === "function") {
|
|
443
|
-
ref(null);
|
|
444
|
-
} else {
|
|
445
|
-
ref.current = null;
|
|
446
|
-
}
|
|
447
|
-
}
|
|
448
|
-
}
|
|
449
|
-
updateRef(ref) {
|
|
450
|
-
this.ref = ref;
|
|
451
|
-
}
|
|
452
|
-
};
|
|
453
|
-
function hijackGetComputedStyle() {
|
|
454
|
-
const rawFn = window.getComputedStyle.bind(window);
|
|
455
|
-
window.getComputedStyle = (element, pseudoElt) => {
|
|
456
|
-
const dom = element.__raw;
|
|
457
|
-
if (dom) {
|
|
458
|
-
return rawFn(dom, pseudoElt);
|
|
459
|
-
}
|
|
460
|
-
return rawFn(element, pseudoElt);
|
|
461
|
-
};
|
|
462
|
-
}
|
|
463
|
-
function useDomProxy(ref, extraRefProps) {
|
|
464
|
-
const spatialContainerRefProxy = useRef(
|
|
465
|
-
new SpatialContainerRefProxy(ref, extraRefProps)
|
|
466
|
-
);
|
|
467
|
-
useEffect(() => {
|
|
468
|
-
spatialContainerRefProxy.current.updateRef(ref);
|
|
469
|
-
}, [ref]);
|
|
470
|
-
const transformVisibilityTaskContainerCallback = useCallback(
|
|
471
|
-
(el) => {
|
|
472
|
-
spatialContainerRefProxy.current.updateTransformVisibilityTaskContainerDom(
|
|
473
|
-
el
|
|
474
|
-
);
|
|
475
|
-
},
|
|
476
|
-
[]
|
|
477
|
-
);
|
|
478
|
-
const standardSpatializedContainerCallback = useCallback(
|
|
479
|
-
(el) => {
|
|
480
|
-
spatialContainerRefProxy.current.updateStandardSpatializedContainerDom(el);
|
|
481
|
-
},
|
|
482
|
-
[]
|
|
483
|
-
);
|
|
484
|
-
return {
|
|
485
|
-
transformVisibilityTaskContainerCallback,
|
|
486
|
-
standardSpatializedContainerCallback,
|
|
487
|
-
spatialContainerRefProxy
|
|
488
|
-
};
|
|
489
|
-
}
|
|
490
|
-
|
|
491
10
|
// src/spatialized-container/hooks/use2DFrameDetector.ts
|
|
492
11
|
import {
|
|
493
12
|
useContext,
|
|
494
13
|
useLayoutEffect,
|
|
495
|
-
useEffect
|
|
496
|
-
useCallback
|
|
14
|
+
useEffect,
|
|
15
|
+
useCallback
|
|
497
16
|
} from "react";
|
|
498
17
|
|
|
499
18
|
// src/spatialized-container/context/SpatializedContainerContext.ts
|
|
@@ -620,11 +139,11 @@ function use2DFrameDetector(ref) {
|
|
|
620
139
|
const spatializedContainerObject = useContext(
|
|
621
140
|
SpatializedContainerContext
|
|
622
141
|
);
|
|
623
|
-
const notify2DFrameChange =
|
|
142
|
+
const notify2DFrameChange = useCallback(() => {
|
|
624
143
|
ref.current && spatializedContainerObject.notify2DFramePlaceHolderChange(ref.current);
|
|
625
144
|
}, [ref.current, spatializedContainerObject]);
|
|
626
145
|
useLayoutEffect(notify2DFrameChange, [notify2DFrameChange]);
|
|
627
|
-
|
|
146
|
+
useEffect(() => {
|
|
628
147
|
if (!ref.current || !spatializedContainerObject) {
|
|
629
148
|
console.warn(
|
|
630
149
|
"Ref is not attached to the DOM or spatializedContainerObject is not available"
|
|
@@ -636,7 +155,7 @@ function use2DFrameDetector(ref) {
|
|
|
636
155
|
window.removeEventListener("resize", notify2DFrameChange);
|
|
637
156
|
};
|
|
638
157
|
}, []);
|
|
639
|
-
|
|
158
|
+
useEffect(() => {
|
|
640
159
|
if (!ref.current) {
|
|
641
160
|
console.warn("Ref is not attached to the DOM");
|
|
642
161
|
return;
|
|
@@ -647,7 +166,7 @@ function use2DFrameDetector(ref) {
|
|
|
647
166
|
ro.disconnect();
|
|
648
167
|
};
|
|
649
168
|
}, []);
|
|
650
|
-
|
|
169
|
+
useEffect(() => {
|
|
651
170
|
if (!ref.current) {
|
|
652
171
|
console.warn("Ref is not attached to the DOM");
|
|
653
172
|
return;
|
|
@@ -666,17 +185,17 @@ function use2DFrameDetector(ref) {
|
|
|
666
185
|
// src/spatialized-container/StandardSpatializedContainer.tsx
|
|
667
186
|
import {
|
|
668
187
|
forwardRef,
|
|
669
|
-
useCallback as
|
|
188
|
+
useCallback as useCallback2,
|
|
670
189
|
useContext as useContext2,
|
|
671
|
-
useEffect as
|
|
672
|
-
useRef
|
|
190
|
+
useEffect as useEffect2,
|
|
191
|
+
useRef,
|
|
673
192
|
useState
|
|
674
193
|
} from "react";
|
|
675
194
|
import { jsx } from "react/jsx-runtime";
|
|
676
195
|
function useSpatialTransformVisibilityWatcher(spatialId) {
|
|
677
196
|
const [transformExist, setTransformExist] = useState(false);
|
|
678
197
|
const spatializedContainerObject = useContext2(SpatializedContainerContext);
|
|
679
|
-
|
|
198
|
+
useEffect2(() => {
|
|
680
199
|
const fn = (spatialTransform) => {
|
|
681
200
|
setTransformExist(spatialTransform.transform !== "none");
|
|
682
201
|
};
|
|
@@ -691,8 +210,8 @@ function useSpatialTransformVisibilityWatcher(spatialId) {
|
|
|
691
210
|
return transformExist;
|
|
692
211
|
}
|
|
693
212
|
function useInternalRef(ref) {
|
|
694
|
-
const refInternal =
|
|
695
|
-
const refInternalCallback =
|
|
213
|
+
const refInternal = useRef(null);
|
|
214
|
+
const refInternalCallback = useCallback2(
|
|
696
215
|
(node) => {
|
|
697
216
|
refInternal.current = node;
|
|
698
217
|
if (typeof ref === "function") {
|
|
@@ -718,43 +237,70 @@ function StandardSpatializedContainerBase(props, ref) {
|
|
|
718
237
|
use2DFrameDetector(refInternal);
|
|
719
238
|
}
|
|
720
239
|
const transformExist = useSpatialTransformVisibilityWatcher(props[SpatialID]);
|
|
721
|
-
const extraStyle = {
|
|
722
|
-
visibility: "hidden",
|
|
723
|
-
transition: "none",
|
|
724
|
-
transform: transformExist ? "translateZ(0)" : "none"
|
|
725
|
-
};
|
|
726
|
-
const style = { ...inStyle, ...extraStyle };
|
|
727
240
|
const classNames = className ? `${className} xr-spatial-default` : "xr-spatial-default";
|
|
728
241
|
return /* @__PURE__ */ jsx(
|
|
729
242
|
Component,
|
|
730
243
|
{
|
|
731
244
|
ref: refInternalCallback,
|
|
732
|
-
style,
|
|
245
|
+
style: inStyle,
|
|
733
246
|
className: classNames,
|
|
734
|
-
...restProps
|
|
247
|
+
...restProps,
|
|
248
|
+
"data-xr-host": "",
|
|
249
|
+
"data-xr-transform-active": transformExist ? "" : void 0
|
|
735
250
|
}
|
|
736
251
|
);
|
|
737
252
|
}
|
|
738
253
|
var StandardSpatializedContainer = forwardRef(
|
|
739
254
|
StandardSpatializedContainerBase
|
|
740
255
|
);
|
|
741
|
-
|
|
742
|
-
|
|
256
|
+
var SPATIAL_DEFAULT_STYLE_CSS = `
|
|
257
|
+
:where(.xr-spatial-default) {
|
|
258
|
+
--xr-back: 0;
|
|
259
|
+
--xr-depth: 0;
|
|
260
|
+
--xr-z-index: 0;
|
|
261
|
+
--xr-background-material: none;
|
|
262
|
+
}
|
|
263
|
+
.xr-spatial-default[data-xr-host] {
|
|
264
|
+
visibility: hidden !important;
|
|
265
|
+
transition: none !important;
|
|
266
|
+
transform: none !important;
|
|
267
|
+
}
|
|
268
|
+
.xr-spatial-default[data-xr-host][data-xr-transform-active] {
|
|
269
|
+
transform: translateZ(0) !important;
|
|
270
|
+
}
|
|
271
|
+
`;
|
|
272
|
+
var SPATIAL_DEFAULT_STYLE_MARKER = "data-xr-spatial-default-style";
|
|
273
|
+
function ensureSpatialDefaultStyleInRoot(root) {
|
|
274
|
+
const queryRoot = root === document ? document.head : root;
|
|
275
|
+
if (queryRoot.querySelector(`style[${SPATIAL_DEFAULT_STYLE_MARKER}]`)) {
|
|
276
|
+
return;
|
|
277
|
+
}
|
|
278
|
+
const ownerDoc = root === document ? document : root.ownerDocument || document;
|
|
279
|
+
const styleElement = ownerDoc.createElement("style");
|
|
743
280
|
styleElement.type = "text/css";
|
|
744
|
-
styleElement.
|
|
745
|
-
|
|
281
|
+
styleElement.setAttribute(SPATIAL_DEFAULT_STYLE_MARKER, "");
|
|
282
|
+
styleElement.innerHTML = SPATIAL_DEFAULT_STYLE_CSS;
|
|
283
|
+
if (root === document) {
|
|
284
|
+
document.head.appendChild(styleElement);
|
|
285
|
+
} else {
|
|
286
|
+
;
|
|
287
|
+
root.appendChild(styleElement);
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
function injectSpatialDefaultStyle() {
|
|
291
|
+
ensureSpatialDefaultStyleInRoot(document);
|
|
746
292
|
}
|
|
747
293
|
|
|
748
294
|
// src/spatialized-container/TransformVisibilityTaskContainer.tsx
|
|
749
295
|
import {
|
|
750
296
|
forwardRef as forwardRef2,
|
|
751
|
-
useCallback as
|
|
752
|
-
useRef as
|
|
297
|
+
useCallback as useCallback4,
|
|
298
|
+
useRef as useRef2
|
|
753
299
|
} from "react";
|
|
754
300
|
import { createPortal } from "react-dom";
|
|
755
301
|
|
|
756
302
|
// src/spatialized-container/hooks/useSpatialTransformVisibility.ts
|
|
757
|
-
import { useCallback as
|
|
303
|
+
import { useCallback as useCallback3, useContext as useContext3, useEffect as useEffect3 } from "react";
|
|
758
304
|
|
|
759
305
|
// src/notifyUpdateStandInstanceLayout.ts
|
|
760
306
|
function notifyUpdateStandInstanceLayout() {
|
|
@@ -784,7 +330,7 @@ function parseTransformAndVisibilityProperties(node) {
|
|
|
784
330
|
}
|
|
785
331
|
function useSpatialTransformVisibility(spatialId, ref) {
|
|
786
332
|
const spatializedContainerObject = useContext3(SpatializedContainerContext);
|
|
787
|
-
const checkSpatialStyleUpdate =
|
|
333
|
+
const checkSpatialStyleUpdate = useCallback3(() => {
|
|
788
334
|
if (!ref.current) {
|
|
789
335
|
return;
|
|
790
336
|
}
|
|
@@ -796,10 +342,10 @@ function useSpatialTransformVisibility(spatialId, ref) {
|
|
|
796
342
|
spatialTransformVisibility
|
|
797
343
|
);
|
|
798
344
|
}, []);
|
|
799
|
-
|
|
345
|
+
useEffect3(() => {
|
|
800
346
|
checkSpatialStyleUpdate();
|
|
801
347
|
}, [checkSpatialStyleUpdate]);
|
|
802
|
-
|
|
348
|
+
useEffect3(() => {
|
|
803
349
|
const observer = new MutationObserver((mutationsList) => {
|
|
804
350
|
checkSpatialStyleUpdate();
|
|
805
351
|
});
|
|
@@ -815,7 +361,7 @@ function useSpatialTransformVisibility(spatialId, ref) {
|
|
|
815
361
|
observer.disconnect();
|
|
816
362
|
};
|
|
817
363
|
}, []);
|
|
818
|
-
|
|
364
|
+
useEffect3(() => {
|
|
819
365
|
const headObserver = new MutationObserver((mutations) => {
|
|
820
366
|
checkSpatialStyleUpdate();
|
|
821
367
|
});
|
|
@@ -824,7 +370,7 @@ function useSpatialTransformVisibility(spatialId, ref) {
|
|
|
824
370
|
headObserver.disconnect();
|
|
825
371
|
};
|
|
826
372
|
}, []);
|
|
827
|
-
|
|
373
|
+
useEffect3(() => {
|
|
828
374
|
const onDomUpdated = (event) => {
|
|
829
375
|
checkSpatialStyleUpdate();
|
|
830
376
|
};
|
|
@@ -858,8 +404,8 @@ function createOrGetCSSParserDivContainer() {
|
|
|
858
404
|
return cssParserDivContainer;
|
|
859
405
|
}
|
|
860
406
|
function useInternalRef2(ref) {
|
|
861
|
-
const refInternal =
|
|
862
|
-
const refInternalCallback =
|
|
407
|
+
const refInternal = useRef2(null);
|
|
408
|
+
const refInternalCallback = useCallback4(
|
|
863
409
|
(node) => {
|
|
864
410
|
refInternal.current = node;
|
|
865
411
|
if (typeof ref === "function") {
|
|
@@ -909,11 +455,29 @@ import {
|
|
|
909
455
|
useCallback as useCallback6,
|
|
910
456
|
useContext as useContext7,
|
|
911
457
|
useEffect as useEffect10,
|
|
458
|
+
useLayoutEffect as useLayoutEffect2,
|
|
912
459
|
useMemo as useMemo2,
|
|
460
|
+
useRef as useRef5,
|
|
913
461
|
useState as useState6
|
|
914
462
|
} from "react";
|
|
915
463
|
|
|
916
464
|
// src/noRuntime.ts
|
|
465
|
+
function supports(name, _tokens) {
|
|
466
|
+
if (name === "useMetrics" || name === "convertCoordinate") {
|
|
467
|
+
return true;
|
|
468
|
+
}
|
|
469
|
+
return false;
|
|
470
|
+
}
|
|
471
|
+
var WebSpatialRuntimeError = class extends Error {
|
|
472
|
+
capability;
|
|
473
|
+
constructor(capability, message) {
|
|
474
|
+
super(
|
|
475
|
+
message ?? `Capability "${capability}" is not supported in this WebSpatial runtime`
|
|
476
|
+
);
|
|
477
|
+
this.name = "WebSpatialRuntimeError";
|
|
478
|
+
this.capability = capability;
|
|
479
|
+
}
|
|
480
|
+
};
|
|
917
481
|
var Spatial = class {
|
|
918
482
|
/**
|
|
919
483
|
* Requests a session object from the browser
|
|
@@ -984,19 +548,153 @@ function getSession() {
|
|
|
984
548
|
if (_currentSession) {
|
|
985
549
|
return _currentSession;
|
|
986
550
|
}
|
|
987
|
-
_currentSession = spatial.requestSession();
|
|
988
|
-
return _currentSession;
|
|
551
|
+
_currentSession = spatial.requestSession();
|
|
552
|
+
return _currentSession;
|
|
553
|
+
}
|
|
554
|
+
|
|
555
|
+
// src/spatialized-container/context/SpatialLayerContext.ts
|
|
556
|
+
import { createContext as createContext2 } from "react";
|
|
557
|
+
var SpatialLayerContext = createContext2(0);
|
|
558
|
+
|
|
559
|
+
// src/spatialized-container/PortalSpatializedContainer.tsx
|
|
560
|
+
import { useMemo, useContext as useContext4, useEffect as useEffect6 } from "react";
|
|
561
|
+
|
|
562
|
+
// src/spatialized-container/context/PortalInstanceContext.ts
|
|
563
|
+
import { createContext as createContext3 } from "react";
|
|
564
|
+
|
|
565
|
+
// src/spatialized-container/utils.ts
|
|
566
|
+
function getInheritedStyleProps(computedStyle) {
|
|
567
|
+
var propNames = [
|
|
568
|
+
"azimuth",
|
|
569
|
+
"borderCollapse",
|
|
570
|
+
"borderSpacing",
|
|
571
|
+
"captionSide",
|
|
572
|
+
"color",
|
|
573
|
+
"cursor",
|
|
574
|
+
"direction",
|
|
575
|
+
// 'elevation',
|
|
576
|
+
"emptyCells",
|
|
577
|
+
"fontFamily",
|
|
578
|
+
"fontSize",
|
|
579
|
+
"fontStyle",
|
|
580
|
+
"fontVariant",
|
|
581
|
+
"fontWeight",
|
|
582
|
+
"font",
|
|
583
|
+
"letterSpacing",
|
|
584
|
+
"lineHeight",
|
|
585
|
+
"listStyleImage",
|
|
586
|
+
"listStylePosition",
|
|
587
|
+
"listStyleType",
|
|
588
|
+
"listStyle",
|
|
589
|
+
"orphans",
|
|
590
|
+
// 'pitchRange',
|
|
591
|
+
// 'pitch',
|
|
592
|
+
"quotes",
|
|
593
|
+
// 'richness',
|
|
594
|
+
// 'speakHeader',
|
|
595
|
+
// 'speakNumeral',
|
|
596
|
+
// 'speakPunctuation',
|
|
597
|
+
// 'speak',
|
|
598
|
+
// 'speechRate',
|
|
599
|
+
// 'stress',
|
|
600
|
+
"textAlign",
|
|
601
|
+
"textIndent",
|
|
602
|
+
"textTransform",
|
|
603
|
+
"visibility",
|
|
604
|
+
// 'voiceFamily',
|
|
605
|
+
// 'volume',
|
|
606
|
+
"whiteSpace",
|
|
607
|
+
"widows",
|
|
608
|
+
"wordSpacing",
|
|
609
|
+
// background also need to be synced
|
|
610
|
+
"background",
|
|
611
|
+
// position also need to be synced
|
|
612
|
+
"position",
|
|
613
|
+
"width",
|
|
614
|
+
"height",
|
|
615
|
+
"display",
|
|
616
|
+
// content-visibility also need to be synced
|
|
617
|
+
"contentVisibility"
|
|
618
|
+
];
|
|
619
|
+
var props = {};
|
|
620
|
+
for (var cssName of propNames) {
|
|
621
|
+
if (computedStyle[cssName]) {
|
|
622
|
+
props[cssName] = computedStyle[cssName];
|
|
623
|
+
}
|
|
624
|
+
}
|
|
625
|
+
return props;
|
|
626
|
+
}
|
|
627
|
+
function parseTransformOrigin(computedStyle) {
|
|
628
|
+
const transformOriginProperty = computedStyle.getPropertyValue("transform-origin");
|
|
629
|
+
const [x, y] = transformOriginProperty.split(" ").map(parseFloat);
|
|
630
|
+
const width = parseFloat(computedStyle.getPropertyValue("width"));
|
|
631
|
+
const height = parseFloat(computedStyle.getPropertyValue("height"));
|
|
632
|
+
return {
|
|
633
|
+
x: width > 0 ? x / width : 0.5,
|
|
634
|
+
y: height > 0 ? y / height : 0.5,
|
|
635
|
+
z: 0.5
|
|
636
|
+
};
|
|
637
|
+
}
|
|
638
|
+
function parseBorderRadius(borderProperty, width) {
|
|
639
|
+
if (borderProperty === "") {
|
|
640
|
+
return 0;
|
|
641
|
+
}
|
|
642
|
+
if (borderProperty.endsWith("%")) {
|
|
643
|
+
return width * parseFloat(borderProperty) / 100;
|
|
644
|
+
}
|
|
645
|
+
return parseFloat(borderProperty);
|
|
646
|
+
}
|
|
647
|
+
function parseCornerRadius(computedStyle) {
|
|
648
|
+
const width = parseFloat(computedStyle.getPropertyValue("width"));
|
|
649
|
+
const topLeftPropertyValue = computedStyle.getPropertyValue(
|
|
650
|
+
"border-top-left-radius"
|
|
651
|
+
);
|
|
652
|
+
const topRightPropertyValue = computedStyle.getPropertyValue(
|
|
653
|
+
"border-top-right-radius"
|
|
654
|
+
);
|
|
655
|
+
const bottomLeftPropertyValue = computedStyle.getPropertyValue(
|
|
656
|
+
"border-bottom-left-radius"
|
|
657
|
+
);
|
|
658
|
+
const bottomRightPropertyValue = computedStyle.getPropertyValue(
|
|
659
|
+
"border-bottom-right-radius"
|
|
660
|
+
);
|
|
661
|
+
const cornerRadius = {
|
|
662
|
+
topLeading: parseBorderRadius(topLeftPropertyValue, width),
|
|
663
|
+
bottomLeading: parseBorderRadius(bottomLeftPropertyValue, width),
|
|
664
|
+
topTrailing: parseBorderRadius(topRightPropertyValue, width),
|
|
665
|
+
bottomTrailing: parseBorderRadius(bottomRightPropertyValue, width)
|
|
666
|
+
};
|
|
667
|
+
return cornerRadius;
|
|
668
|
+
}
|
|
669
|
+
function extractAndRemoveCustomProperties(cssText, properties) {
|
|
670
|
+
if (!cssText) {
|
|
671
|
+
return { extractedValues: {}, filteredCssText: "" };
|
|
672
|
+
}
|
|
673
|
+
const extractedValues = {};
|
|
674
|
+
const rules = cssText.split(";");
|
|
675
|
+
const filteredRules = rules.filter((rule) => {
|
|
676
|
+
const [key, value] = rule.split(":").map((part) => part.trim());
|
|
677
|
+
if (properties.includes(key)) {
|
|
678
|
+
extractedValues[key] = value;
|
|
679
|
+
return false;
|
|
680
|
+
}
|
|
681
|
+
return true;
|
|
682
|
+
});
|
|
683
|
+
const filteredCssText = filteredRules.join(";").trim();
|
|
684
|
+
return { extractedValues, filteredCssText };
|
|
685
|
+
}
|
|
686
|
+
function joinToCSSText(cssKV) {
|
|
687
|
+
const rules = Object.entries(cssKV).map(([key, value]) => `${key}: ${value}`);
|
|
688
|
+
return rules.join(";");
|
|
989
689
|
}
|
|
990
690
|
|
|
991
|
-
// src/spatialized-container/
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
// src/spatialized-container/context/PortalInstanceContext.ts
|
|
999
|
-
import { createContext as createContext3 } from "react";
|
|
691
|
+
// src/spatialized-container/types.ts
|
|
692
|
+
var SpatialCustomStyleVars = {
|
|
693
|
+
back: "--xr-back",
|
|
694
|
+
depth: "--xr-depth",
|
|
695
|
+
backgroundMaterial: "--xr-background-material",
|
|
696
|
+
xrZIndex: "--xr-z-index"
|
|
697
|
+
};
|
|
1000
698
|
|
|
1001
699
|
// src/utils/debugTool.ts
|
|
1002
700
|
async function inspectCurrentSpatialScene() {
|
|
@@ -1014,6 +712,18 @@ function enableDebugTool() {
|
|
|
1014
712
|
});
|
|
1015
713
|
}
|
|
1016
714
|
|
|
715
|
+
// src/utils/urlUtils.ts
|
|
716
|
+
function getAbsoluteUrl(url) {
|
|
717
|
+
if (typeof window === "undefined" || !window.location?.href) {
|
|
718
|
+
return url;
|
|
719
|
+
}
|
|
720
|
+
try {
|
|
721
|
+
return new URL(url, window.location.href).href;
|
|
722
|
+
} catch {
|
|
723
|
+
return url;
|
|
724
|
+
}
|
|
725
|
+
}
|
|
726
|
+
|
|
1017
727
|
// src/spatialized-container/context/PortalInstanceContext.ts
|
|
1018
728
|
var PortalInstanceObject = class {
|
|
1019
729
|
spatialId;
|
|
@@ -1198,14 +908,14 @@ var PortalInstanceContext = createContext3(
|
|
|
1198
908
|
);
|
|
1199
909
|
|
|
1200
910
|
// src/spatialized-container/hooks/useSync2DFrame.ts
|
|
1201
|
-
import { useEffect as
|
|
911
|
+
import { useEffect as useEffect4, useState as useState2 } from "react";
|
|
1202
912
|
function useForceUpdate() {
|
|
1203
913
|
const [, setToggle] = useState2(false);
|
|
1204
914
|
return () => setToggle((toggle) => !toggle);
|
|
1205
915
|
}
|
|
1206
916
|
function useSync2DFrame(spatialId, portalInstanceObject, spatializedContainerObject) {
|
|
1207
917
|
const forceUpdate = useForceUpdate();
|
|
1208
|
-
|
|
918
|
+
useEffect4(() => {
|
|
1209
919
|
spatializedContainerObject.on2DFrameChange(spatialId, () => {
|
|
1210
920
|
portalInstanceObject.notify2DFrameChange();
|
|
1211
921
|
forceUpdate();
|
|
@@ -1217,11 +927,11 @@ function useSync2DFrame(spatialId, portalInstanceObject, spatializedContainerObj
|
|
|
1217
927
|
}
|
|
1218
928
|
|
|
1219
929
|
// src/spatialized-container/hooks/useSpatializedElement.ts
|
|
1220
|
-
import { useEffect as
|
|
930
|
+
import { useEffect as useEffect5, useRef as useRef3, useState as useState3 } from "react";
|
|
1221
931
|
function useSpatializedElement(createSpatializedElement2, portalInstanceObject) {
|
|
1222
932
|
const [spatializedElement, setSpatializedElement] = useState3();
|
|
1223
|
-
const elementRef =
|
|
1224
|
-
|
|
933
|
+
const elementRef = useRef3(void 0);
|
|
934
|
+
useEffect5(() => {
|
|
1225
935
|
let isDestroyed = false;
|
|
1226
936
|
createSpatializedElement2().then(
|
|
1227
937
|
(inSpatializedElement) => {
|
|
@@ -1317,7 +1027,7 @@ function PortalSpatializedContainer(props) {
|
|
|
1317
1027
|
),
|
|
1318
1028
|
[]
|
|
1319
1029
|
);
|
|
1320
|
-
|
|
1030
|
+
useEffect6(() => {
|
|
1321
1031
|
portalInstanceObject.init();
|
|
1322
1032
|
return () => {
|
|
1323
1033
|
portalInstanceObject.destroy();
|
|
@@ -1332,58 +1042,416 @@ function PortalSpatializedContainer(props) {
|
|
|
1332
1042
|
portalInstanceObject,
|
|
1333
1043
|
props.component
|
|
1334
1044
|
);
|
|
1335
|
-
|
|
1045
|
+
useEffect6(() => {
|
|
1336
1046
|
if (spatializedElement) {
|
|
1337
1047
|
spatializedElement.onSpatialTap = onSpatialTap;
|
|
1338
1048
|
}
|
|
1339
|
-
}, [spatializedElement, onSpatialTap]);
|
|
1340
|
-
|
|
1341
|
-
if (spatializedElement) {
|
|
1342
|
-
spatializedElement.onSpatialDrag = onSpatialDrag;
|
|
1049
|
+
}, [spatializedElement, onSpatialTap]);
|
|
1050
|
+
useEffect6(() => {
|
|
1051
|
+
if (spatializedElement) {
|
|
1052
|
+
spatializedElement.onSpatialDrag = onSpatialDrag;
|
|
1053
|
+
}
|
|
1054
|
+
}, [spatializedElement, onSpatialDrag]);
|
|
1055
|
+
useEffect6(() => {
|
|
1056
|
+
if (spatializedElement) {
|
|
1057
|
+
spatializedElement.onSpatialDragEnd = onSpatialDragEnd;
|
|
1058
|
+
}
|
|
1059
|
+
}, [spatializedElement, onSpatialDragEnd]);
|
|
1060
|
+
useEffect6(() => {
|
|
1061
|
+
if (spatializedElement) {
|
|
1062
|
+
spatializedElement.onSpatialRotate = onSpatialRotate;
|
|
1063
|
+
}
|
|
1064
|
+
}, [spatializedElement, onSpatialRotate]);
|
|
1065
|
+
useEffect6(() => {
|
|
1066
|
+
if (spatializedElement) {
|
|
1067
|
+
spatializedElement.onSpatialRotateEnd = onSpatialRotateEnd;
|
|
1068
|
+
}
|
|
1069
|
+
}, [spatializedElement, onSpatialRotateEnd]);
|
|
1070
|
+
useEffect6(() => {
|
|
1071
|
+
if (spatializedElement) {
|
|
1072
|
+
spatializedElement.onSpatialMagnify = onSpatialMagnify;
|
|
1073
|
+
}
|
|
1074
|
+
}, [spatializedElement, onSpatialMagnify]);
|
|
1075
|
+
useEffect6(() => {
|
|
1076
|
+
if (spatializedElement) {
|
|
1077
|
+
spatializedElement.onSpatialMagnifyEnd = onSpatialMagnifyEnd;
|
|
1078
|
+
}
|
|
1079
|
+
}, [spatializedElement, onSpatialMagnifyEnd]);
|
|
1080
|
+
useEffect6(() => {
|
|
1081
|
+
if (spatializedElement) {
|
|
1082
|
+
spatializedElement.onSpatialDragStart = onSpatialDragStart;
|
|
1083
|
+
}
|
|
1084
|
+
}, [spatializedElement, onSpatialDragStart]);
|
|
1085
|
+
const rotateConstraintKey = constrainedAxisKey(
|
|
1086
|
+
spatialEventOptions?.constrainedToAxis
|
|
1087
|
+
);
|
|
1088
|
+
useEffect6(() => {
|
|
1089
|
+
if (!spatializedElement) return;
|
|
1090
|
+
const axis = constrainedAxisToVec3(spatialEventOptions?.constrainedToAxis);
|
|
1091
|
+
void spatializedElement.updateProperties({ rotateConstrainedToAxis: axis });
|
|
1092
|
+
}, [spatializedElement, rotateConstraintKey]);
|
|
1093
|
+
return /* @__PURE__ */ jsxs(PortalInstanceContext.Provider, { value: portalInstanceObject, children: [
|
|
1094
|
+
spatializedElement && portalInstanceObject.dom && /* @__PURE__ */ jsx3(Content, { spatializedElement, ...restProps }),
|
|
1095
|
+
PlaceholderEl
|
|
1096
|
+
] });
|
|
1097
|
+
}
|
|
1098
|
+
|
|
1099
|
+
// src/spatialized-container/hooks/useDomProxy.ts
|
|
1100
|
+
import { useCallback as useCallback5, useEffect as useEffect7, useRef as useRef4 } from "react";
|
|
1101
|
+
var SpatialContainerRefProxy = class {
|
|
1102
|
+
transformVisibilityTaskContainerDom = null;
|
|
1103
|
+
/** Raw Standard host element (styled root). Used to mirror class onto the transform probe. */
|
|
1104
|
+
standardRawDom = null;
|
|
1105
|
+
standardClassObserver = null;
|
|
1106
|
+
/**
|
|
1107
|
+
* When set, Standard's DOM className is forwarded here so TransformVisibilityTaskContainer
|
|
1108
|
+
* can render it from React state (avoids React clobbering imperative class updates).
|
|
1109
|
+
*/
|
|
1110
|
+
mirrorClassNotify = null;
|
|
1111
|
+
/** Last class string applied to the probe + used to skip redundant syncs. */
|
|
1112
|
+
lastMirroredClassName = null;
|
|
1113
|
+
/** Coalesce multiple class sync triggers in the same turn (Observer + classList, etc.). */
|
|
1114
|
+
classSyncMicrotaskQueued = false;
|
|
1115
|
+
ref;
|
|
1116
|
+
domProxy;
|
|
1117
|
+
/** Last value dispatched to `ref` (undefined = none yet); avoids duplicate null/proxy writes. */
|
|
1118
|
+
lastOutgoingToRef = void 0;
|
|
1119
|
+
installedProperties = [];
|
|
1120
|
+
// extre ref props, used to add extra props to ref
|
|
1121
|
+
extraRefProps;
|
|
1122
|
+
constructor(ref, extraRefProps) {
|
|
1123
|
+
this.ref = ref;
|
|
1124
|
+
this.extraRefProps = extraRefProps;
|
|
1125
|
+
}
|
|
1126
|
+
setMirrorClassNotify(fn) {
|
|
1127
|
+
this.mirrorClassNotify = fn;
|
|
1128
|
+
if (fn && this.standardRawDom) {
|
|
1129
|
+
this.flushSyncTransformClassFromStandard(true);
|
|
1130
|
+
}
|
|
1131
|
+
}
|
|
1132
|
+
disconnectStandardClassObserver() {
|
|
1133
|
+
this.standardClassObserver?.disconnect();
|
|
1134
|
+
this.standardClassObserver = null;
|
|
1135
|
+
}
|
|
1136
|
+
attachStandardClassObserver() {
|
|
1137
|
+
this.disconnectStandardClassObserver();
|
|
1138
|
+
if (!this.standardRawDom) {
|
|
1139
|
+
return;
|
|
1140
|
+
}
|
|
1141
|
+
this.standardClassObserver = new MutationObserver(() => {
|
|
1142
|
+
this.ensureSpatialDefaultClass();
|
|
1143
|
+
this.scheduleSyncTransformClassFromStandard();
|
|
1144
|
+
});
|
|
1145
|
+
this.standardClassObserver.observe(this.standardRawDom, {
|
|
1146
|
+
attributes: true,
|
|
1147
|
+
attributeFilter: ["class"]
|
|
1148
|
+
});
|
|
1149
|
+
}
|
|
1150
|
+
ensureSpatialDefaultClass() {
|
|
1151
|
+
const dom = this.standardRawDom;
|
|
1152
|
+
if (!dom) return;
|
|
1153
|
+
if (dom.classList.contains("xr-spatial-default")) return;
|
|
1154
|
+
dom.classList.add("xr-spatial-default");
|
|
1155
|
+
}
|
|
1156
|
+
/**
|
|
1157
|
+
* Merge multiple sync requests (e.g. classList hook + MutationObserver) into one microtask.
|
|
1158
|
+
*/
|
|
1159
|
+
scheduleSyncTransformClassFromStandard() {
|
|
1160
|
+
if (this.classSyncMicrotaskQueued) {
|
|
1161
|
+
return;
|
|
1162
|
+
}
|
|
1163
|
+
this.classSyncMicrotaskQueued = true;
|
|
1164
|
+
queueMicrotask(() => {
|
|
1165
|
+
this.classSyncMicrotaskQueued = false;
|
|
1166
|
+
this.flushSyncTransformClassFromStandard(false);
|
|
1167
|
+
});
|
|
1168
|
+
}
|
|
1169
|
+
/**
|
|
1170
|
+
* Source of truth: Standard host DOM (incl. styled-components runtime class changes).
|
|
1171
|
+
* @param force when true, skip same-string short-circuit (e.g. mirror notify just registered).
|
|
1172
|
+
*/
|
|
1173
|
+
flushSyncTransformClassFromStandard(force) {
|
|
1174
|
+
if (!this.standardRawDom) {
|
|
1175
|
+
return;
|
|
1176
|
+
}
|
|
1177
|
+
const name = this.standardRawDom.className;
|
|
1178
|
+
const probe = this.transformVisibilityTaskContainerDom;
|
|
1179
|
+
if (!force && probe && probe.className === name && this.lastMirroredClassName === name) {
|
|
1180
|
+
return;
|
|
1181
|
+
}
|
|
1182
|
+
this.lastMirroredClassName = name;
|
|
1183
|
+
if (probe) {
|
|
1184
|
+
probe.className = name;
|
|
1185
|
+
}
|
|
1186
|
+
this.mirrorClassNotify?.(name);
|
|
1187
|
+
}
|
|
1188
|
+
updateStandardSpatializedContainerDom(dom) {
|
|
1189
|
+
if (!dom) {
|
|
1190
|
+
this.disconnectStandardClassObserver();
|
|
1191
|
+
this.clearInstalledProperties();
|
|
1192
|
+
this.standardRawDom = null;
|
|
1193
|
+
this.lastMirroredClassName = null;
|
|
1194
|
+
this.domProxy = void 0;
|
|
1195
|
+
this.updateDomProxyToRef();
|
|
1196
|
+
return;
|
|
1197
|
+
}
|
|
1198
|
+
if (this.standardRawDom === dom && this.domProxy) {
|
|
1199
|
+
this.scheduleSyncTransformClassFromStandard();
|
|
1200
|
+
return;
|
|
1201
|
+
}
|
|
1202
|
+
this.clearInstalledProperties();
|
|
1203
|
+
this.standardRawDom = dom;
|
|
1204
|
+
this.domProxy = dom;
|
|
1205
|
+
this.installSpatialRefBehavior(dom);
|
|
1206
|
+
const root = dom.getRootNode();
|
|
1207
|
+
if (root === document || root instanceof ShadowRoot) {
|
|
1208
|
+
ensureSpatialDefaultStyleInRoot(root);
|
|
1209
|
+
}
|
|
1210
|
+
this.attachStandardClassObserver();
|
|
1211
|
+
this.updateDomProxyToRef();
|
|
1212
|
+
this.scheduleSyncTransformClassFromStandard();
|
|
1213
|
+
}
|
|
1214
|
+
clearInstalledProperties() {
|
|
1215
|
+
const dom = this.standardRawDom;
|
|
1216
|
+
if (!dom) return;
|
|
1217
|
+
for (const prop of this.installedProperties) {
|
|
1218
|
+
delete dom[prop];
|
|
1219
|
+
}
|
|
1220
|
+
this.installedProperties = [];
|
|
1221
|
+
}
|
|
1222
|
+
defineDomProperty(dom, prop, descriptor) {
|
|
1223
|
+
Object.defineProperty(dom, prop, {
|
|
1224
|
+
configurable: true,
|
|
1225
|
+
...descriptor
|
|
1226
|
+
});
|
|
1227
|
+
this.installedProperties.push(prop);
|
|
1228
|
+
}
|
|
1229
|
+
installSpatialRefBehavior(dom) {
|
|
1230
|
+
const self = this;
|
|
1231
|
+
const rawStyle = dom.style;
|
|
1232
|
+
const rawRemoveProperty = rawStyle.removeProperty.bind(rawStyle);
|
|
1233
|
+
const rawGetPropertyValue = rawStyle.getPropertyValue.bind(rawStyle);
|
|
1234
|
+
const rawRemoveAttribute = dom.removeAttribute.bind(dom);
|
|
1235
|
+
const spatialStyleProperties = ["visibility", "transform"];
|
|
1236
|
+
const styleProxy = new Proxy(rawStyle, {
|
|
1237
|
+
get(target, prop) {
|
|
1238
|
+
if (prop === "visibility" || prop === "transform") {
|
|
1239
|
+
return self.transformVisibilityTaskContainerDom?.style.getPropertyValue(
|
|
1240
|
+
prop
|
|
1241
|
+
);
|
|
1242
|
+
}
|
|
1243
|
+
const value = Reflect.get(target, prop);
|
|
1244
|
+
if (typeof value === "function") {
|
|
1245
|
+
if (prop === "setProperty" || prop === "removeProperty" || prop === "getPropertyValue") {
|
|
1246
|
+
return function(...args) {
|
|
1247
|
+
const [property] = args;
|
|
1248
|
+
if (spatialStyleProperties.includes(property)) {
|
|
1249
|
+
if (prop === "setProperty") {
|
|
1250
|
+
const [, kValue, priority] = args;
|
|
1251
|
+
self.transformVisibilityTaskContainerDom?.style.setProperty(
|
|
1252
|
+
property,
|
|
1253
|
+
kValue,
|
|
1254
|
+
priority
|
|
1255
|
+
);
|
|
1256
|
+
} else if (prop === "removeProperty") {
|
|
1257
|
+
return self.transformVisibilityTaskContainerDom?.style.removeProperty(
|
|
1258
|
+
property
|
|
1259
|
+
);
|
|
1260
|
+
} else if (prop === "getPropertyValue") {
|
|
1261
|
+
return self.transformVisibilityTaskContainerDom?.style.getPropertyValue(
|
|
1262
|
+
property
|
|
1263
|
+
);
|
|
1264
|
+
}
|
|
1265
|
+
return void 0;
|
|
1266
|
+
}
|
|
1267
|
+
return value.apply(this, args);
|
|
1268
|
+
}.bind(target);
|
|
1269
|
+
}
|
|
1270
|
+
return value.bind(target);
|
|
1271
|
+
}
|
|
1272
|
+
return value;
|
|
1273
|
+
},
|
|
1274
|
+
set(target, prop, value) {
|
|
1275
|
+
if (prop === "visibility") {
|
|
1276
|
+
self.transformVisibilityTaskContainerDom?.style.setProperty(
|
|
1277
|
+
"visibility",
|
|
1278
|
+
value
|
|
1279
|
+
);
|
|
1280
|
+
return true;
|
|
1281
|
+
}
|
|
1282
|
+
if (prop === "transform") {
|
|
1283
|
+
self.transformVisibilityTaskContainerDom?.style.setProperty(
|
|
1284
|
+
"transform",
|
|
1285
|
+
value
|
|
1286
|
+
);
|
|
1287
|
+
return true;
|
|
1288
|
+
}
|
|
1289
|
+
if (Object.values(SpatialCustomStyleVars).includes(prop)) {
|
|
1290
|
+
target.setProperty(prop, value);
|
|
1291
|
+
return true;
|
|
1292
|
+
}
|
|
1293
|
+
if (prop === "cssText") {
|
|
1294
|
+
const { extractedValues, filteredCssText } = extractAndRemoveCustomProperties(
|
|
1295
|
+
value,
|
|
1296
|
+
spatialStyleProperties
|
|
1297
|
+
);
|
|
1298
|
+
spatialStyleProperties.forEach((key) => {
|
|
1299
|
+
if (extractedValues[key]) {
|
|
1300
|
+
self.transformVisibilityTaskContainerDom?.style.setProperty(
|
|
1301
|
+
key,
|
|
1302
|
+
extractedValues[key]
|
|
1303
|
+
);
|
|
1304
|
+
} else {
|
|
1305
|
+
rawRemoveProperty(key);
|
|
1306
|
+
}
|
|
1307
|
+
});
|
|
1308
|
+
const appendedCSSText = joinToCSSText({
|
|
1309
|
+
transform: "none",
|
|
1310
|
+
visibility: "hidden"
|
|
1311
|
+
});
|
|
1312
|
+
return Reflect.set(
|
|
1313
|
+
target,
|
|
1314
|
+
prop,
|
|
1315
|
+
[appendedCSSText, filteredCssText].join(";")
|
|
1316
|
+
);
|
|
1317
|
+
}
|
|
1318
|
+
return Reflect.set(target, prop, value);
|
|
1319
|
+
}
|
|
1320
|
+
});
|
|
1321
|
+
this.defineDomProperty(dom, "style", {
|
|
1322
|
+
get() {
|
|
1323
|
+
return styleProxy;
|
|
1324
|
+
},
|
|
1325
|
+
set(value) {
|
|
1326
|
+
styleProxy.cssText = String(value);
|
|
1327
|
+
}
|
|
1328
|
+
});
|
|
1329
|
+
this.defineDomProperty(dom, "className", {
|
|
1330
|
+
get() {
|
|
1331
|
+
return dom.getAttribute("class") ?? "";
|
|
1332
|
+
},
|
|
1333
|
+
set(value) {
|
|
1334
|
+
dom.setAttribute("class", String(value));
|
|
1335
|
+
if (!dom.classList.contains("xr-spatial-default")) {
|
|
1336
|
+
dom.classList.add("xr-spatial-default");
|
|
1337
|
+
}
|
|
1338
|
+
self.scheduleSyncTransformClassFromStandard();
|
|
1339
|
+
}
|
|
1340
|
+
});
|
|
1341
|
+
this.defineDomProperty(dom, "removeAttribute", {
|
|
1342
|
+
value(property) {
|
|
1343
|
+
if (property === "style") {
|
|
1344
|
+
rawStyle.cssText = "visibility: hidden; transition: none; transform: none;";
|
|
1345
|
+
self.transformVisibilityTaskContainerDom?.style.removeProperty(
|
|
1346
|
+
"visibility"
|
|
1347
|
+
);
|
|
1348
|
+
self.transformVisibilityTaskContainerDom?.style.removeProperty(
|
|
1349
|
+
"transform"
|
|
1350
|
+
);
|
|
1351
|
+
return;
|
|
1352
|
+
}
|
|
1353
|
+
if (property === "class") {
|
|
1354
|
+
dom.className = "xr-spatial-default";
|
|
1355
|
+
return;
|
|
1356
|
+
}
|
|
1357
|
+
return rawRemoveAttribute(property);
|
|
1358
|
+
}
|
|
1359
|
+
});
|
|
1360
|
+
if (supports("xrClientDepth")) {
|
|
1361
|
+
this.defineDomProperty(dom, "xrClientDepth", {
|
|
1362
|
+
get() {
|
|
1363
|
+
return rawGetPropertyValue(SpatialCustomStyleVars.depth);
|
|
1364
|
+
}
|
|
1365
|
+
});
|
|
1366
|
+
}
|
|
1367
|
+
if (supports("xrOffsetBack")) {
|
|
1368
|
+
this.defineDomProperty(dom, "xrOffsetBack", {
|
|
1369
|
+
get() {
|
|
1370
|
+
return rawGetPropertyValue(SpatialCustomStyleVars.back);
|
|
1371
|
+
}
|
|
1372
|
+
});
|
|
1343
1373
|
}
|
|
1344
|
-
|
|
1345
|
-
|
|
1346
|
-
|
|
1347
|
-
|
|
1374
|
+
if (this.extraRefProps) {
|
|
1375
|
+
const extraProps = this.extraRefProps(dom);
|
|
1376
|
+
for (const prop of Object.keys(extraProps)) {
|
|
1377
|
+
this.defineDomProperty(dom, prop, {
|
|
1378
|
+
get() {
|
|
1379
|
+
return extraProps[prop];
|
|
1380
|
+
},
|
|
1381
|
+
set(value) {
|
|
1382
|
+
extraProps[prop] = value;
|
|
1383
|
+
}
|
|
1384
|
+
});
|
|
1385
|
+
}
|
|
1348
1386
|
}
|
|
1349
|
-
}
|
|
1350
|
-
|
|
1351
|
-
|
|
1352
|
-
|
|
1387
|
+
}
|
|
1388
|
+
updateTransformVisibilityTaskContainerDom(dom) {
|
|
1389
|
+
this.transformVisibilityTaskContainerDom = dom;
|
|
1390
|
+
if (!dom) {
|
|
1391
|
+
this.lastMirroredClassName = null;
|
|
1353
1392
|
}
|
|
1354
|
-
|
|
1355
|
-
|
|
1356
|
-
|
|
1357
|
-
|
|
1393
|
+
this.scheduleSyncTransformClassFromStandard();
|
|
1394
|
+
this.updateDomProxyToRef();
|
|
1395
|
+
}
|
|
1396
|
+
updateDomProxyToRef() {
|
|
1397
|
+
const ref = this.ref;
|
|
1398
|
+
if (!ref) {
|
|
1399
|
+
return;
|
|
1358
1400
|
}
|
|
1359
|
-
|
|
1360
|
-
|
|
1361
|
-
|
|
1362
|
-
spatializedElement.onSpatialMagnify = onSpatialMagnify;
|
|
1401
|
+
const next = this.domProxy && this.transformVisibilityTaskContainerDom ? this.domProxy : null;
|
|
1402
|
+
if (this.lastOutgoingToRef === next) {
|
|
1403
|
+
return;
|
|
1363
1404
|
}
|
|
1364
|
-
|
|
1365
|
-
|
|
1366
|
-
|
|
1367
|
-
|
|
1405
|
+
this.lastOutgoingToRef = next;
|
|
1406
|
+
if (next) {
|
|
1407
|
+
if (typeof ref === "function") {
|
|
1408
|
+
ref(next);
|
|
1409
|
+
} else {
|
|
1410
|
+
ref.current = next;
|
|
1411
|
+
}
|
|
1412
|
+
} else {
|
|
1413
|
+
if (typeof ref === "function") {
|
|
1414
|
+
ref(null);
|
|
1415
|
+
} else {
|
|
1416
|
+
ref.current = null;
|
|
1417
|
+
}
|
|
1368
1418
|
}
|
|
1369
|
-
}
|
|
1370
|
-
|
|
1371
|
-
if (
|
|
1372
|
-
|
|
1419
|
+
}
|
|
1420
|
+
updateRef(ref) {
|
|
1421
|
+
if (this.ref === ref) {
|
|
1422
|
+
return;
|
|
1373
1423
|
}
|
|
1374
|
-
|
|
1375
|
-
|
|
1376
|
-
|
|
1424
|
+
this.ref = ref;
|
|
1425
|
+
this.lastOutgoingToRef = void 0;
|
|
1426
|
+
this.updateDomProxyToRef();
|
|
1427
|
+
}
|
|
1428
|
+
};
|
|
1429
|
+
function useDomProxy(ref, extraRefProps) {
|
|
1430
|
+
const spatialContainerRefProxy = useRef4(
|
|
1431
|
+
new SpatialContainerRefProxy(ref, extraRefProps)
|
|
1377
1432
|
);
|
|
1378
1433
|
useEffect7(() => {
|
|
1379
|
-
|
|
1380
|
-
|
|
1381
|
-
|
|
1382
|
-
|
|
1383
|
-
|
|
1384
|
-
|
|
1385
|
-
|
|
1386
|
-
|
|
1434
|
+
spatialContainerRefProxy.current.updateRef(ref);
|
|
1435
|
+
}, [ref]);
|
|
1436
|
+
const transformVisibilityTaskContainerCallback = useCallback5(
|
|
1437
|
+
(el) => {
|
|
1438
|
+
spatialContainerRefProxy.current.updateTransformVisibilityTaskContainerDom(
|
|
1439
|
+
el
|
|
1440
|
+
);
|
|
1441
|
+
},
|
|
1442
|
+
[]
|
|
1443
|
+
);
|
|
1444
|
+
const standardSpatializedContainerCallback = useCallback5(
|
|
1445
|
+
(el) => {
|
|
1446
|
+
spatialContainerRefProxy.current.updateStandardSpatializedContainerDom(el);
|
|
1447
|
+
},
|
|
1448
|
+
[]
|
|
1449
|
+
);
|
|
1450
|
+
return {
|
|
1451
|
+
transformVisibilityTaskContainerCallback,
|
|
1452
|
+
standardSpatializedContainerCallback,
|
|
1453
|
+
spatialContainerRefProxy
|
|
1454
|
+
};
|
|
1387
1455
|
}
|
|
1388
1456
|
|
|
1389
1457
|
// src/reality/context/InsideAttachmentContext.tsx
|
|
@@ -1625,6 +1693,7 @@ function withSSRSupported(Component) {
|
|
|
1625
1693
|
import { jsx as jsx6, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
1626
1694
|
function DegradedContainer({
|
|
1627
1695
|
innerRef,
|
|
1696
|
+
enableOnSpatialContentReadyFallback,
|
|
1628
1697
|
...inprops
|
|
1629
1698
|
}) {
|
|
1630
1699
|
const {
|
|
@@ -1645,9 +1714,48 @@ function DegradedContainer({
|
|
|
1645
1714
|
getExtraSpatializedElementProperties: _getExtra,
|
|
1646
1715
|
extraRefProps: _extraRef,
|
|
1647
1716
|
sizingMode: _sizingMode,
|
|
1717
|
+
onSpatialContentReady: _onSpatialContentReady,
|
|
1648
1718
|
...restProps
|
|
1649
1719
|
} = inprops;
|
|
1650
|
-
|
|
1720
|
+
const [hostEl, setHostEl] = useState6(null);
|
|
1721
|
+
const callbackRef = useRef5(_onSpatialContentReady);
|
|
1722
|
+
callbackRef.current = _onSpatialContentReady;
|
|
1723
|
+
useLayoutEffect2(() => {
|
|
1724
|
+
if (!enableOnSpatialContentReadyFallback || !hostEl || !hostEl.isConnected || !callbackRef.current) {
|
|
1725
|
+
return () => {
|
|
1726
|
+
};
|
|
1727
|
+
}
|
|
1728
|
+
let cleanup;
|
|
1729
|
+
try {
|
|
1730
|
+
cleanup = callbackRef.current({ host: hostEl });
|
|
1731
|
+
} catch (e) {
|
|
1732
|
+
if (process.env.NODE_ENV !== "production") {
|
|
1733
|
+
console.error("[WebSpatial] onSpatialContentReady threw", e);
|
|
1734
|
+
}
|
|
1735
|
+
}
|
|
1736
|
+
return () => {
|
|
1737
|
+
if (typeof cleanup !== "function") return;
|
|
1738
|
+
try {
|
|
1739
|
+
cleanup();
|
|
1740
|
+
} catch (e) {
|
|
1741
|
+
if (process.env.NODE_ENV !== "production") {
|
|
1742
|
+
console.error("[WebSpatial] onSpatialContentReady cleanup threw", e);
|
|
1743
|
+
}
|
|
1744
|
+
}
|
|
1745
|
+
};
|
|
1746
|
+
}, [enableOnSpatialContentReadyFallback, hostEl]);
|
|
1747
|
+
const setHostRef = useCallback6(
|
|
1748
|
+
(node) => {
|
|
1749
|
+
if (typeof innerRef === "function") {
|
|
1750
|
+
innerRef(node);
|
|
1751
|
+
} else if (innerRef != null) {
|
|
1752
|
+
innerRef.current = node;
|
|
1753
|
+
}
|
|
1754
|
+
setHostEl(node);
|
|
1755
|
+
},
|
|
1756
|
+
[innerRef]
|
|
1757
|
+
);
|
|
1758
|
+
return /* @__PURE__ */ jsx6(Component, { ref: setHostRef, ...restProps, children });
|
|
1651
1759
|
}
|
|
1652
1760
|
function SpatializedContainerBase(inprops, ref) {
|
|
1653
1761
|
const isWebSpatialEnv = getSession() !== null;
|
|
@@ -1658,7 +1766,14 @@ function SpatializedContainerBase(inprops, ref) {
|
|
|
1658
1766
|
`[WebSpatial] ${inprops.component || "Spatial element"} cannot be used inside AttachmentAsset. Rendering as plain HTML.`
|
|
1659
1767
|
);
|
|
1660
1768
|
}
|
|
1661
|
-
return /* @__PURE__ */ jsx6(
|
|
1769
|
+
return /* @__PURE__ */ jsx6(
|
|
1770
|
+
DegradedContainer,
|
|
1771
|
+
{
|
|
1772
|
+
...inprops,
|
|
1773
|
+
innerRef: ref,
|
|
1774
|
+
enableOnSpatialContentReadyFallback: !isWebSpatialEnv && !insideAttachment
|
|
1775
|
+
}
|
|
1776
|
+
);
|
|
1662
1777
|
}
|
|
1663
1778
|
const layer = useContext7(SpatialLayerContext) + 1;
|
|
1664
1779
|
const rootSpatializedContainerObject = useContext7(
|
|
@@ -1741,6 +1856,7 @@ function SpatializedContainerBase(inprops, ref) {
|
|
|
1741
1856
|
createSpatializedElement: createSpatializedElement2,
|
|
1742
1857
|
getExtraSpatializedElementProperties: getExtraSpatializedElementProperties2,
|
|
1743
1858
|
spatialEventOptions: _nestedSpatialEventOptions,
|
|
1859
|
+
onSpatialContentReady: _nestedOnSpatialContentReady,
|
|
1744
1860
|
...restProps
|
|
1745
1861
|
} = props;
|
|
1746
1862
|
return /* @__PURE__ */ jsxs2(SpatialLayerContext.Provider, { value: layer, children: [
|
|
@@ -1804,6 +1920,7 @@ function SpatializedContainerBase(inprops, ref) {
|
|
|
1804
1920
|
createSpatializedElement: createSpatializedElement2,
|
|
1805
1921
|
getExtraSpatializedElementProperties: getExtraSpatializedElementProperties2,
|
|
1806
1922
|
spatialEventOptions: _rootSpatialEventOptions,
|
|
1923
|
+
onSpatialContentReady: _rootOnSpatialContentReady,
|
|
1807
1924
|
...restProps
|
|
1808
1925
|
} = props;
|
|
1809
1926
|
return /* @__PURE__ */ jsx6(SpatialLayerContext.Provider, { value: layer, children: /* @__PURE__ */ jsxs2(
|
|
@@ -1850,8 +1967,10 @@ var SpatializedContainer = withSSRSupported(
|
|
|
1850
1967
|
import { createPortal as createPortal2 } from "react-dom";
|
|
1851
1968
|
import {
|
|
1852
1969
|
forwardRef as forwardRef5,
|
|
1970
|
+
useCallback as useCallback7,
|
|
1853
1971
|
useContext as useContext8,
|
|
1854
|
-
useEffect as useEffect12
|
|
1972
|
+
useEffect as useEffect12,
|
|
1973
|
+
useState as useState7
|
|
1855
1974
|
} from "react";
|
|
1856
1975
|
|
|
1857
1976
|
// src/utils/windowStyleSync.ts
|
|
@@ -1964,55 +2083,145 @@ async function syncParentHeadToChild(childWindow) {
|
|
|
1964
2083
|
|
|
1965
2084
|
// src/utils/useSyncHeadStyles.ts
|
|
1966
2085
|
import { useEffect as useEffect11 } from "react";
|
|
1967
|
-
function
|
|
1968
|
-
if (!Array.isArray(mutations) || mutations.length === 0) return
|
|
2086
|
+
function getSyncTiming(mutations) {
|
|
2087
|
+
if (!Array.isArray(mutations) || mutations.length === 0) return null;
|
|
2088
|
+
let hasDelayed = false;
|
|
1969
2089
|
for (const mutation of mutations) {
|
|
2090
|
+
if (mutation.type === "characterData") {
|
|
2091
|
+
const parent = mutation.target.parentElement;
|
|
2092
|
+
if (parent?.tagName === "STYLE") return "immediate";
|
|
2093
|
+
}
|
|
1970
2094
|
const nodes = [
|
|
2095
|
+
mutation.target,
|
|
1971
2096
|
...Array.from(mutation.addedNodes),
|
|
1972
2097
|
...Array.from(mutation.removedNodes)
|
|
1973
2098
|
];
|
|
1974
2099
|
for (const node of nodes) {
|
|
1975
2100
|
if (!(node instanceof Element)) continue;
|
|
1976
2101
|
const tag = node.tagName;
|
|
1977
|
-
if (tag === "STYLE") return
|
|
2102
|
+
if (tag === "STYLE") return "immediate";
|
|
1978
2103
|
if (tag === "LINK") {
|
|
1979
2104
|
const { rel } = node;
|
|
1980
|
-
if (rel && rel.toLowerCase() === "stylesheet")
|
|
2105
|
+
if (rel && rel.toLowerCase() === "stylesheet") hasDelayed = true;
|
|
1981
2106
|
}
|
|
1982
2107
|
}
|
|
1983
2108
|
}
|
|
1984
|
-
return
|
|
2109
|
+
return hasDelayed ? "delayed" : null;
|
|
1985
2110
|
}
|
|
1986
2111
|
function useSyncHeadStyles(childWindow, options) {
|
|
1987
2112
|
const delayMs = 100;
|
|
1988
|
-
const subtree = options?.subtree ??
|
|
2113
|
+
const subtree = options?.subtree ?? true;
|
|
1989
2114
|
const immediate = options?.immediate ?? true;
|
|
1990
2115
|
useEffect11(() => {
|
|
1991
2116
|
if (!childWindow) return;
|
|
1992
2117
|
let timer;
|
|
1993
|
-
|
|
2118
|
+
let immediateQueued = false;
|
|
2119
|
+
let disposed = false;
|
|
2120
|
+
const scheduleSync = (timing = "delayed") => {
|
|
1994
2121
|
if (timer) window.clearTimeout(timer);
|
|
2122
|
+
if (timing === "immediate") {
|
|
2123
|
+
if (immediateQueued) return;
|
|
2124
|
+
immediateQueued = true;
|
|
2125
|
+
queueMicrotask(() => {
|
|
2126
|
+
immediateQueued = false;
|
|
2127
|
+
if (disposed) return;
|
|
2128
|
+
syncParentHeadToChild(childWindow);
|
|
2129
|
+
});
|
|
2130
|
+
return;
|
|
2131
|
+
}
|
|
1995
2132
|
timer = window.setTimeout(() => {
|
|
2133
|
+
if (disposed) return;
|
|
1996
2134
|
syncParentHeadToChild(childWindow);
|
|
1997
2135
|
}, delayMs);
|
|
1998
2136
|
};
|
|
1999
2137
|
if (immediate) scheduleSync();
|
|
2000
2138
|
const observer = new MutationObserver((mutations) => {
|
|
2001
|
-
|
|
2002
|
-
|
|
2139
|
+
const timing = getSyncTiming(mutations);
|
|
2140
|
+
if (!timing) return;
|
|
2141
|
+
scheduleSync(timing);
|
|
2142
|
+
});
|
|
2143
|
+
observer.observe(document.head, {
|
|
2144
|
+
childList: true,
|
|
2145
|
+
characterData: true,
|
|
2146
|
+
subtree
|
|
2003
2147
|
});
|
|
2004
|
-
observer.observe(document.head, { childList: true, subtree });
|
|
2005
2148
|
return () => {
|
|
2149
|
+
disposed = true;
|
|
2006
2150
|
if (timer) window.clearTimeout(timer);
|
|
2007
2151
|
observer.disconnect();
|
|
2008
2152
|
};
|
|
2009
2153
|
}, [childWindow, delayMs, subtree, immediate]);
|
|
2010
2154
|
}
|
|
2011
2155
|
|
|
2156
|
+
// src/spatialized-container/hooks/useSpatialContentReady.ts
|
|
2157
|
+
import { useLayoutEffect as useLayoutEffect3, useRef as useRef6 } from "react";
|
|
2158
|
+
var isDev = process.env.NODE_ENV !== "production";
|
|
2159
|
+
function safeInvokeCleanup(cleanup) {
|
|
2160
|
+
if (!cleanup) return;
|
|
2161
|
+
try {
|
|
2162
|
+
cleanup();
|
|
2163
|
+
} catch (e) {
|
|
2164
|
+
if (isDev) {
|
|
2165
|
+
console.error("[WebSpatial] onSpatialContentReady cleanup threw", e);
|
|
2166
|
+
}
|
|
2167
|
+
}
|
|
2168
|
+
}
|
|
2169
|
+
function useSpatialContentReady(params) {
|
|
2170
|
+
const {
|
|
2171
|
+
spatializedElement,
|
|
2172
|
+
portalInstanceObject,
|
|
2173
|
+
hostElement,
|
|
2174
|
+
onSpatialContentReady
|
|
2175
|
+
} = params;
|
|
2176
|
+
const callbackRef = useRef6(onSpatialContentReady);
|
|
2177
|
+
callbackRef.current = onSpatialContentReady;
|
|
2178
|
+
useLayoutEffect3(() => {
|
|
2179
|
+
const dom = portalInstanceObject.dom;
|
|
2180
|
+
const isReady = !!(spatializedElement && dom && hostElement && hostElement.isConnected);
|
|
2181
|
+
if (!isReady || !hostElement) {
|
|
2182
|
+
return () => {
|
|
2183
|
+
};
|
|
2184
|
+
}
|
|
2185
|
+
const cb = callbackRef.current;
|
|
2186
|
+
let cleanupFromCallback;
|
|
2187
|
+
if (cb) {
|
|
2188
|
+
try {
|
|
2189
|
+
const ret = cb({ host: hostElement });
|
|
2190
|
+
cleanupFromCallback = typeof ret === "function" ? ret : void 0;
|
|
2191
|
+
} catch (e) {
|
|
2192
|
+
if (isDev) {
|
|
2193
|
+
console.error("[WebSpatial] onSpatialContentReady threw", e);
|
|
2194
|
+
}
|
|
2195
|
+
}
|
|
2196
|
+
}
|
|
2197
|
+
return () => {
|
|
2198
|
+
safeInvokeCleanup(cleanupFromCallback);
|
|
2199
|
+
};
|
|
2200
|
+
}, [spatializedElement, portalInstanceObject.dom, hostElement]);
|
|
2201
|
+
}
|
|
2202
|
+
|
|
2012
2203
|
// src/spatialized-container/Spatialized2DElementContainer.tsx
|
|
2013
2204
|
import { jsx as jsx7 } from "react/jsx-runtime";
|
|
2014
|
-
function
|
|
2015
|
-
|
|
2205
|
+
function mergeRefs(...refs) {
|
|
2206
|
+
return (value) => {
|
|
2207
|
+
for (const ref of refs) {
|
|
2208
|
+
if (ref == null) continue;
|
|
2209
|
+
if (typeof ref === "function") {
|
|
2210
|
+
ref(value);
|
|
2211
|
+
} else {
|
|
2212
|
+
;
|
|
2213
|
+
ref.current = value;
|
|
2214
|
+
}
|
|
2215
|
+
}
|
|
2216
|
+
};
|
|
2217
|
+
}
|
|
2218
|
+
function getJSXPortalInstance(inProps, portalInstanceObject, hostRef) {
|
|
2219
|
+
const {
|
|
2220
|
+
component: El,
|
|
2221
|
+
style: inStyle = {},
|
|
2222
|
+
ref: userRef,
|
|
2223
|
+
...props
|
|
2224
|
+
} = inProps;
|
|
2016
2225
|
const extraStyle = {
|
|
2017
2226
|
visibility: "visible",
|
|
2018
2227
|
position: "relative",
|
|
@@ -2034,7 +2243,8 @@ function getJSXPortalInstance(inProps, portalInstanceObject) {
|
|
|
2034
2243
|
...inheritedPortalStyle,
|
|
2035
2244
|
...extraStyle
|
|
2036
2245
|
};
|
|
2037
|
-
|
|
2246
|
+
const mergedRef = hostRef != null ? mergeRefs(hostRef, userRef) : userRef;
|
|
2247
|
+
return /* @__PURE__ */ jsx7(El, { ref: mergedRef, style, ...props });
|
|
2038
2248
|
}
|
|
2039
2249
|
function useSyncDocumentTitle(windowProxy, spatializedElement, name) {
|
|
2040
2250
|
useEffect12(() => {
|
|
@@ -2045,20 +2255,31 @@ function useSyncDocumentTitle(windowProxy, spatializedElement, name) {
|
|
|
2045
2255
|
}, [name]);
|
|
2046
2256
|
}
|
|
2047
2257
|
function SpatializedContent(props) {
|
|
2048
|
-
const { spatializedElement, ...restProps } = props;
|
|
2258
|
+
const { spatializedElement, onSpatialContentReady, ...restProps } = props;
|
|
2049
2259
|
const spatialized2DElement = spatializedElement;
|
|
2050
2260
|
const { windowProxy } = spatialized2DElement;
|
|
2261
|
+
const [hostEl, setHostEl] = useState7(null);
|
|
2262
|
+
const portalInstanceObject = useContext8(
|
|
2263
|
+
PortalInstanceContext
|
|
2264
|
+
);
|
|
2265
|
+
useSpatialContentReady({
|
|
2266
|
+
spatializedElement,
|
|
2267
|
+
portalInstanceObject,
|
|
2268
|
+
hostElement: hostEl,
|
|
2269
|
+
onSpatialContentReady
|
|
2270
|
+
});
|
|
2051
2271
|
useSyncHeadStyles(windowProxy, {
|
|
2052
2272
|
subtree: false
|
|
2053
2273
|
});
|
|
2054
2274
|
const name = restProps["data-name"] || "";
|
|
2055
2275
|
useSyncDocumentTitle(windowProxy, spatialized2DElement, name);
|
|
2056
|
-
const
|
|
2057
|
-
|
|
2058
|
-
);
|
|
2276
|
+
const setHostCallback = useCallback7((el) => {
|
|
2277
|
+
setHostEl(el);
|
|
2278
|
+
}, []);
|
|
2059
2279
|
const JSXPortalInstance = getJSXPortalInstance(
|
|
2060
2280
|
restProps,
|
|
2061
|
-
portalInstanceObject
|
|
2281
|
+
portalInstanceObject,
|
|
2282
|
+
setHostCallback
|
|
2062
2283
|
);
|
|
2063
2284
|
return createPortal2(JSXPortalInstance, windowProxy.document.body);
|
|
2064
2285
|
}
|
|
@@ -2116,11 +2337,11 @@ import {
|
|
|
2116
2337
|
Children,
|
|
2117
2338
|
forwardRef as forwardRef6,
|
|
2118
2339
|
isValidElement,
|
|
2119
|
-
useCallback as
|
|
2340
|
+
useCallback as useCallback8,
|
|
2120
2341
|
useContext as useContext9,
|
|
2121
2342
|
useEffect as useEffect13,
|
|
2122
2343
|
useMemo as useMemo3,
|
|
2123
|
-
useRef as
|
|
2344
|
+
useRef as useRef7
|
|
2124
2345
|
} from "react";
|
|
2125
2346
|
import { Fragment as Fragment2, jsx as jsx8 } from "react/jsx-runtime";
|
|
2126
2347
|
function getAbsoluteURL(url) {
|
|
@@ -2165,24 +2386,57 @@ function collectSources(children) {
|
|
|
2165
2386
|
return sources;
|
|
2166
2387
|
}
|
|
2167
2388
|
function SpatializedContent2(props) {
|
|
2168
|
-
const {
|
|
2389
|
+
const {
|
|
2390
|
+
src,
|
|
2391
|
+
poster,
|
|
2392
|
+
children,
|
|
2393
|
+
spatializedElement,
|
|
2394
|
+
onLoad,
|
|
2395
|
+
onError,
|
|
2396
|
+
autoPlay,
|
|
2397
|
+
loop,
|
|
2398
|
+
loading = "eager"
|
|
2399
|
+
} = props;
|
|
2169
2400
|
const portalInstanceObject = useContext9(PortalInstanceContext);
|
|
2401
|
+
const wasVisible = useRef7(false);
|
|
2170
2402
|
const modelURL = useMemo3(() => getAbsoluteURL(src), [src]);
|
|
2403
|
+
const posterURL = useMemo3(() => getAbsoluteURL(poster), [poster]);
|
|
2171
2404
|
const sources = useMemo3(() => collectSources(children), [children]);
|
|
2405
|
+
const sourcesKey = useMemo3(() => JSON.stringify(sources), [sources]);
|
|
2406
|
+
useEffect13(() => {
|
|
2407
|
+
wasVisible.current = false;
|
|
2408
|
+
const target = portalInstanceObject.dom;
|
|
2409
|
+
if (loading !== "lazy" || !target) {
|
|
2410
|
+
wasVisible.current = true;
|
|
2411
|
+
return;
|
|
2412
|
+
}
|
|
2413
|
+
const observer = new IntersectionObserver((entries) => {
|
|
2414
|
+
if (entries.some((entry) => entry.isIntersecting)) {
|
|
2415
|
+
wasVisible.current = true;
|
|
2416
|
+
observer.disconnect();
|
|
2417
|
+
spatializedElement.updateProperties({ loading: "eager" });
|
|
2418
|
+
}
|
|
2419
|
+
});
|
|
2420
|
+
observer.observe(target);
|
|
2421
|
+
return () => observer.disconnect();
|
|
2422
|
+
}, [modelURL, sourcesKey, portalInstanceObject]);
|
|
2172
2423
|
useEffect13(() => {
|
|
2424
|
+
if (loading !== "lazy") wasVisible.current = true;
|
|
2173
2425
|
spatializedElement.updateProperties({
|
|
2174
|
-
modelURL: modelURL ?? "",
|
|
2426
|
+
modelURL: modelURL ?? (spatializedElement.modelUrl ? "" : modelURL),
|
|
2175
2427
|
sources,
|
|
2176
2428
|
autoplay: autoPlay,
|
|
2177
|
-
loop
|
|
2429
|
+
loop,
|
|
2430
|
+
posterURL: posterURL ?? "",
|
|
2431
|
+
loading: loading === "lazy" && wasVisible.current ? "eager" : loading
|
|
2178
2432
|
});
|
|
2179
|
-
}, [modelURL,
|
|
2433
|
+
}, [modelURL, sourcesKey, autoPlay, loop, posterURL, loading]);
|
|
2180
2434
|
useEffect13(() => {
|
|
2181
2435
|
if (onLoad) {
|
|
2182
2436
|
spatializedElement.onLoadCallback = () => {
|
|
2183
2437
|
onLoad(
|
|
2184
2438
|
createLoadSuccessEvent(
|
|
2185
|
-
() => portalInstanceObject.dom
|
|
2439
|
+
() => portalInstanceObject.dom
|
|
2186
2440
|
)
|
|
2187
2441
|
);
|
|
2188
2442
|
};
|
|
@@ -2195,7 +2449,7 @@ function SpatializedContent2(props) {
|
|
|
2195
2449
|
spatializedElement.onLoadFailureCallback = () => {
|
|
2196
2450
|
onError(
|
|
2197
2451
|
createLoadFailureEvent(
|
|
2198
|
-
() => portalInstanceObject.dom
|
|
2452
|
+
() => portalInstanceObject.dom
|
|
2199
2453
|
)
|
|
2200
2454
|
);
|
|
2201
2455
|
};
|
|
@@ -2206,15 +2460,16 @@ function SpatializedContent2(props) {
|
|
|
2206
2460
|
return /* @__PURE__ */ jsx8(Fragment2, {});
|
|
2207
2461
|
}
|
|
2208
2462
|
function SpatializedStatic3DElementContainerBase(props, ref) {
|
|
2209
|
-
const promiseRef =
|
|
2210
|
-
const createSpatializedElement2 =
|
|
2463
|
+
const promiseRef = useRef7(null);
|
|
2464
|
+
const createSpatializedElement2 = useCallback8(() => {
|
|
2211
2465
|
promiseRef.current = getSession().createSpatializedStatic3DElement(
|
|
2212
2466
|
getAbsoluteURL(props.src),
|
|
2213
|
-
collectSources(props.children)
|
|
2467
|
+
collectSources(props.children),
|
|
2468
|
+
props.loading === "lazy" ? "lazy" : "eager"
|
|
2214
2469
|
);
|
|
2215
2470
|
return promiseRef.current;
|
|
2216
2471
|
}, []);
|
|
2217
|
-
const extraRefProps =
|
|
2472
|
+
const extraRefProps = useCallback8(
|
|
2218
2473
|
(domProxy) => {
|
|
2219
2474
|
let modelTransform = new DOMMatrixReadOnly();
|
|
2220
2475
|
return {
|
|
@@ -2261,6 +2516,16 @@ function SpatializedStatic3DElementContainerBase(props, ref) {
|
|
|
2261
2516
|
if (spatializedElement) {
|
|
2262
2517
|
spatializedElement.playbackRate = value;
|
|
2263
2518
|
}
|
|
2519
|
+
},
|
|
2520
|
+
get currentTime() {
|
|
2521
|
+
const spatializedElement = domProxy.__spatializedElement;
|
|
2522
|
+
return spatializedElement?.currentTime ?? 0;
|
|
2523
|
+
},
|
|
2524
|
+
set currentTime(value) {
|
|
2525
|
+
const spatializedElement = domProxy.__spatializedElement;
|
|
2526
|
+
if (spatializedElement) {
|
|
2527
|
+
spatializedElement.currentTime = value;
|
|
2528
|
+
}
|
|
2264
2529
|
}
|
|
2265
2530
|
};
|
|
2266
2531
|
},
|
|
@@ -2317,11 +2582,15 @@ function withSpatialized2DElementContainer(Component) {
|
|
|
2317
2582
|
|
|
2318
2583
|
// src/spatialized-container/index.ts
|
|
2319
2584
|
function initPolyfill() {
|
|
2320
|
-
hijackGetComputedStyle();
|
|
2321
2585
|
injectSpatialDefaultStyle();
|
|
2322
2586
|
initCSSParserDivContainer();
|
|
2323
2587
|
}
|
|
2324
2588
|
|
|
2589
|
+
// src/webSpatialRuntime.ts
|
|
2590
|
+
var WebSpatialRuntime = {
|
|
2591
|
+
supports
|
|
2592
|
+
};
|
|
2593
|
+
|
|
2325
2594
|
// src/initScene.web.ts
|
|
2326
2595
|
function initScene(name, callback) {
|
|
2327
2596
|
return;
|
|
@@ -2331,9 +2600,9 @@ function initScene(name, callback) {
|
|
|
2331
2600
|
import { forwardRef as forwardRef9 } from "react";
|
|
2332
2601
|
|
|
2333
2602
|
// src/spatialized-container-monitor/useMonitorDomChange.tsx
|
|
2334
|
-
import { useRef as
|
|
2603
|
+
import { useRef as useRef8, useEffect as useEffect14, useMemo as useMemo4 } from "react";
|
|
2335
2604
|
function useMonitorDomChange(inRef) {
|
|
2336
|
-
const ref =
|
|
2605
|
+
const ref = useRef8(null);
|
|
2337
2606
|
useEffect14(() => {
|
|
2338
2607
|
const observer = new MutationObserver((mutationsList) => {
|
|
2339
2608
|
notifyDOMUpdate(mutationsList);
|
|
@@ -2495,37 +2764,87 @@ var AttachmentRegistry = class {
|
|
|
2495
2764
|
var AttachmentContext = createContext8(null);
|
|
2496
2765
|
|
|
2497
2766
|
// src/reality/hooks/useEntityTransform.tsx
|
|
2498
|
-
import { useEffect as useEffect16, useRef as
|
|
2767
|
+
import { useEffect as useEffect16, useRef as useRef9 } from "react";
|
|
2499
2768
|
|
|
2500
2769
|
// src/reality/utils/ResourceRegistry.ts
|
|
2501
2770
|
var ResourceRegistry = class {
|
|
2771
|
+
/** Every id maps to a promise — either the real resource from add(), or a placeholder until then. */
|
|
2502
2772
|
resources = /* @__PURE__ */ new Map();
|
|
2773
|
+
/** If get() ran first, we stash resolve/reject so add() can complete the waiting promise. */
|
|
2774
|
+
deferreds = /* @__PURE__ */ new Map();
|
|
2775
|
+
/** Subscribers are notified whenever an id gets a fresh resolved or failed resource attempt. */
|
|
2776
|
+
listeners = /* @__PURE__ */ new Map();
|
|
2503
2777
|
add(id, resource) {
|
|
2504
2778
|
this.resources.set(id, resource);
|
|
2779
|
+
const deferred = this.deferreds.get(id);
|
|
2780
|
+
if (deferred) {
|
|
2781
|
+
resource.then(deferred.resolve).catch(
|
|
2782
|
+
(err) => deferred.reject(err instanceof Error ? err : new Error(String(err)))
|
|
2783
|
+
);
|
|
2784
|
+
this.deferreds.delete(id);
|
|
2785
|
+
}
|
|
2786
|
+
resource.then(() => this.notify(id)).catch(() => this.notify(id));
|
|
2787
|
+
}
|
|
2788
|
+
subscribe(id, listener) {
|
|
2789
|
+
const listeners = this.listeners.get(id) ?? /* @__PURE__ */ new Set();
|
|
2790
|
+
listeners.add(listener);
|
|
2791
|
+
this.listeners.set(id, listeners);
|
|
2792
|
+
return () => {
|
|
2793
|
+
listeners.delete(listener);
|
|
2794
|
+
if (listeners.size === 0) {
|
|
2795
|
+
this.listeners.delete(id);
|
|
2796
|
+
}
|
|
2797
|
+
};
|
|
2798
|
+
}
|
|
2799
|
+
notify(id) {
|
|
2800
|
+
const listeners = this.listeners.get(id);
|
|
2801
|
+
if (!listeners) return;
|
|
2802
|
+
for (const listener of Array.from(listeners)) {
|
|
2803
|
+
listener();
|
|
2804
|
+
}
|
|
2805
|
+
}
|
|
2806
|
+
get(id) {
|
|
2807
|
+
const existing = this.resources.get(id);
|
|
2808
|
+
if (existing) {
|
|
2809
|
+
return existing;
|
|
2810
|
+
}
|
|
2811
|
+
const promise = new Promise((resolve, reject) => {
|
|
2812
|
+
this.deferreds.set(id, { resolve, reject });
|
|
2813
|
+
});
|
|
2814
|
+
this.resources.set(id, promise);
|
|
2815
|
+
return promise;
|
|
2505
2816
|
}
|
|
2506
2817
|
remove(id) {
|
|
2507
2818
|
this.resources.delete(id);
|
|
2819
|
+
this.deferreds.delete(id);
|
|
2820
|
+
this.notify(id);
|
|
2508
2821
|
}
|
|
2509
|
-
//
|
|
2510
|
-
// This does not cancel in-flight creation; it schedules destruction after resolution
|
|
2822
|
+
// Same as remove, but when the promise resolves, destroy the spatial object (best-effort).
|
|
2511
2823
|
removeAndDestroy(id) {
|
|
2512
2824
|
const p = this.resources.get(id);
|
|
2513
2825
|
if (p) {
|
|
2514
|
-
p.then((
|
|
2826
|
+
p.then((obj) => obj.destroy()).catch(() => {
|
|
2515
2827
|
});
|
|
2516
2828
|
}
|
|
2517
2829
|
this.resources.delete(id);
|
|
2518
|
-
|
|
2519
|
-
|
|
2520
|
-
return this.resources.get(id);
|
|
2830
|
+
this.deferreds.delete(id);
|
|
2831
|
+
this.notify(id);
|
|
2521
2832
|
}
|
|
2522
2833
|
destroy() {
|
|
2834
|
+
for (const [id, deferred] of this.deferreds) {
|
|
2835
|
+
deferred.reject(
|
|
2836
|
+
new Error(`ResourceRegistry destroyed \u2014 "${id}" never resolved`)
|
|
2837
|
+
);
|
|
2838
|
+
}
|
|
2839
|
+
this.deferreds.clear();
|
|
2840
|
+
const ids = Array.from(this.resources.keys());
|
|
2841
|
+
for (const id of ids) {
|
|
2842
|
+
this.notify(id);
|
|
2843
|
+
}
|
|
2844
|
+
this.listeners.clear();
|
|
2523
2845
|
const pending = Array.from(this.resources.values());
|
|
2524
2846
|
this.resources.clear();
|
|
2525
|
-
pending.
|
|
2526
|
-
(promise) => promise.then((spatialObj) => spatialObj.destroy()).catch(() => {
|
|
2527
|
-
})
|
|
2528
|
-
);
|
|
2847
|
+
void Promise.allSettled(pending.map((p) => p.then((obj) => obj.destroy())));
|
|
2529
2848
|
}
|
|
2530
2849
|
};
|
|
2531
2850
|
|
|
@@ -2557,15 +2876,14 @@ function shallowEqualArray(a, b) {
|
|
|
2557
2876
|
|
|
2558
2877
|
// src/reality/utils/AbortResourceManager.ts
|
|
2559
2878
|
var AbortResourceManager = class {
|
|
2879
|
+
resources = [];
|
|
2880
|
+
aborted = false;
|
|
2560
2881
|
constructor(signal) {
|
|
2561
|
-
this.signal = signal;
|
|
2562
2882
|
signal.addEventListener("abort", () => {
|
|
2563
2883
|
this.aborted = true;
|
|
2564
2884
|
void this.dispose();
|
|
2565
2885
|
});
|
|
2566
2886
|
}
|
|
2567
|
-
resources = [];
|
|
2568
|
-
aborted = false;
|
|
2569
2887
|
async addResource(factory) {
|
|
2570
2888
|
if (this.aborted) throw new DOMException("Aborted", "AbortError");
|
|
2571
2889
|
const resource = await factory();
|
|
@@ -2590,7 +2908,7 @@ var AbortResourceManager = class {
|
|
|
2590
2908
|
|
|
2591
2909
|
// src/reality/hooks/useEntityTransform.tsx
|
|
2592
2910
|
function useEntityTransform(entity, { position, rotation, scale }) {
|
|
2593
|
-
const last =
|
|
2911
|
+
const last = useRef9({});
|
|
2594
2912
|
useEffect16(() => {
|
|
2595
2913
|
if (!entity) return;
|
|
2596
2914
|
const shouldUpdate = !shallowEqualVec3(last.current.position, position) || !shallowEqualRotation(last.current.rotation, rotation) || !shallowEqualVec3(last.current.scale, scale);
|
|
@@ -2610,7 +2928,7 @@ function useEntityTransform(entity, { position, rotation, scale }) {
|
|
|
2610
2928
|
}
|
|
2611
2929
|
|
|
2612
2930
|
// src/reality/hooks/useEntityEvent.tsx
|
|
2613
|
-
import { useEffect as
|
|
2931
|
+
import { useEffect as useEffect17, useRef as useRef10 } from "react";
|
|
2614
2932
|
|
|
2615
2933
|
// src/reality/type.ts
|
|
2616
2934
|
var eventMap = {
|
|
@@ -2812,8 +3130,8 @@ function createEventProxy2(ev, instance) {
|
|
|
2812
3130
|
});
|
|
2813
3131
|
}
|
|
2814
3132
|
var useEntityEvent = ({ instance, ...handlers }) => {
|
|
2815
|
-
const eventsSetRef =
|
|
2816
|
-
|
|
3133
|
+
const eventsSetRef = useRef10(/* @__PURE__ */ new Set());
|
|
3134
|
+
useEffect17(() => {
|
|
2817
3135
|
const entity = instance.entity;
|
|
2818
3136
|
if (!entity) return;
|
|
2819
3137
|
Object.entries(eventMap).forEach(([reactKey, spatialEvent]) => {
|
|
@@ -2826,7 +3144,7 @@ var useEntityEvent = ({ instance, ...handlers }) => {
|
|
|
2826
3144
|
return () => {
|
|
2827
3145
|
};
|
|
2828
3146
|
}, [instance.entity, ...Object.values(handlers)]);
|
|
2829
|
-
|
|
3147
|
+
useEffect17(() => {
|
|
2830
3148
|
const entity = instance.entity;
|
|
2831
3149
|
if (!entity) return;
|
|
2832
3150
|
return () => {
|
|
@@ -2840,7 +3158,7 @@ var useEntityEvent = ({ instance, ...handlers }) => {
|
|
|
2840
3158
|
};
|
|
2841
3159
|
|
|
2842
3160
|
// src/reality/hooks/useRealityEvents.tsx
|
|
2843
|
-
import { useEffect as
|
|
3161
|
+
import { useEffect as useEffect18, useRef as useRef11 } from "react";
|
|
2844
3162
|
function createEventProxy3(ev, instance) {
|
|
2845
3163
|
return new Proxy(ev, {
|
|
2846
3164
|
get(target, prop) {
|
|
@@ -2954,8 +3272,8 @@ function createEventProxy3(ev, instance) {
|
|
|
2954
3272
|
});
|
|
2955
3273
|
}
|
|
2956
3274
|
var useRealityEvents = ({ instance, ...handlers }) => {
|
|
2957
|
-
const eventsSetRef =
|
|
2958
|
-
|
|
3275
|
+
const eventsSetRef = useRef11(/* @__PURE__ */ new Set());
|
|
3276
|
+
useEffect18(() => {
|
|
2959
3277
|
if (!instance) return;
|
|
2960
3278
|
Object.entries(eventMap).forEach(([reactKey, spatialEvent]) => {
|
|
2961
3279
|
const handlerFn = handlers[reactKey];
|
|
@@ -2976,10 +3294,10 @@ var useRealityEvents = ({ instance, ...handlers }) => {
|
|
|
2976
3294
|
};
|
|
2977
3295
|
|
|
2978
3296
|
// src/reality/hooks/useEntityId.tsx
|
|
2979
|
-
import { useEffect as
|
|
3297
|
+
import { useEffect as useEffect19 } from "react";
|
|
2980
3298
|
var useEntityId = ({ id, entity }) => {
|
|
2981
3299
|
const ctx = useRealityContext();
|
|
2982
|
-
|
|
3300
|
+
useEffect19(() => {
|
|
2983
3301
|
if (!id || !entity || !ctx) return;
|
|
2984
3302
|
ctx.resourceRegistry.add(id, Promise.resolve(entity));
|
|
2985
3303
|
return () => {
|
|
@@ -2990,7 +3308,7 @@ var useEntityId = ({ id, entity }) => {
|
|
|
2990
3308
|
};
|
|
2991
3309
|
|
|
2992
3310
|
// src/reality/hooks/useEntity.tsx
|
|
2993
|
-
import { useEffect as
|
|
3311
|
+
import { useEffect as useEffect20, useRef as useRef12 } from "react";
|
|
2994
3312
|
var useEntity = ({
|
|
2995
3313
|
ref,
|
|
2996
3314
|
id,
|
|
@@ -3011,9 +3329,9 @@ var useEntity = ({
|
|
|
3011
3329
|
}) => {
|
|
3012
3330
|
const ctx = useRealityContext();
|
|
3013
3331
|
const parent = useParentContext();
|
|
3014
|
-
const instanceRef =
|
|
3332
|
+
const instanceRef = useRef12(new EntityRef(null, ctx));
|
|
3015
3333
|
const forceUpdate = useForceUpdate2();
|
|
3016
|
-
|
|
3334
|
+
useEffect20(() => {
|
|
3017
3335
|
if (!ctx) return;
|
|
3018
3336
|
const controller = new AbortController();
|
|
3019
3337
|
const init = async () => {
|
|
@@ -3062,7 +3380,7 @@ var useEntity = ({
|
|
|
3062
3380
|
onSpatialMagnify,
|
|
3063
3381
|
onSpatialMagnifyEnd
|
|
3064
3382
|
});
|
|
3065
|
-
|
|
3383
|
+
useEffect20(() => {
|
|
3066
3384
|
const ent = instanceRef.current.entity;
|
|
3067
3385
|
if (!ent) return;
|
|
3068
3386
|
if (enableInput !== void 0) {
|
|
@@ -3073,10 +3391,10 @@ var useEntity = ({
|
|
|
3073
3391
|
};
|
|
3074
3392
|
|
|
3075
3393
|
// src/reality/hooks/useForceUpdate.tsx
|
|
3076
|
-
import { useCallback as
|
|
3394
|
+
import { useCallback as useCallback9, useState as useState9 } from "react";
|
|
3077
3395
|
var useForceUpdate2 = () => {
|
|
3078
|
-
const [, setTick] =
|
|
3079
|
-
return
|
|
3396
|
+
const [, setTick] = useState9(0);
|
|
3397
|
+
return useCallback9(() => setTick((tick) => tick + 1), []);
|
|
3080
3398
|
};
|
|
3081
3399
|
|
|
3082
3400
|
// src/reality/components/BaseEntity.tsx
|
|
@@ -3115,18 +3433,18 @@ var Entity = forwardRef11((props, ref) => {
|
|
|
3115
3433
|
import { forwardRef as forwardRef13 } from "react";
|
|
3116
3434
|
|
|
3117
3435
|
// src/reality/components/GeometryEntity.tsx
|
|
3118
|
-
import { forwardRef as forwardRef12, useEffect as
|
|
3436
|
+
import { forwardRef as forwardRef12, useEffect as useEffect21, useRef as useRef13 } from "react";
|
|
3119
3437
|
import { jsx as jsx14 } from "react/jsx-runtime";
|
|
3120
3438
|
var GeometryEntity = forwardRef12(
|
|
3121
3439
|
({ id, children, name, materials, geometryOptions, createGeometry, ...rest }, ref) => {
|
|
3122
3440
|
const ctx = useRealityContext();
|
|
3123
|
-
const entityRef =
|
|
3124
|
-
const componentRef =
|
|
3125
|
-
const mutableRef =
|
|
3441
|
+
const entityRef = useRef13(null);
|
|
3442
|
+
const componentRef = useRef13(null);
|
|
3443
|
+
const mutableRef = useRef13({
|
|
3126
3444
|
lastSnapshot: null,
|
|
3127
3445
|
rebuildGen: 0
|
|
3128
3446
|
});
|
|
3129
|
-
|
|
3447
|
+
useEffect21(() => {
|
|
3130
3448
|
const { lastSnapshot } = mutableRef.current;
|
|
3131
3449
|
if (!ctx || !entityRef.current || lastSnapshot === null) return;
|
|
3132
3450
|
const geometryChanged = !shallowEqualObject(
|
|
@@ -3248,22 +3566,50 @@ var BoxEntity = forwardRef13(
|
|
|
3248
3566
|
);
|
|
3249
3567
|
|
|
3250
3568
|
// src/reality/components/UnlitMaterial.tsx
|
|
3251
|
-
import { useEffect as
|
|
3569
|
+
import { useEffect as useEffect22, useRef as useRef14, useState as useState10 } from "react";
|
|
3252
3570
|
var UnlitMaterial = ({
|
|
3253
3571
|
children,
|
|
3254
3572
|
...options
|
|
3255
3573
|
}) => {
|
|
3256
3574
|
const ctx = useRealityContext();
|
|
3257
|
-
const materialRef =
|
|
3258
|
-
const isInitializedRef =
|
|
3259
|
-
|
|
3575
|
+
const materialRef = useRef14(void 0);
|
|
3576
|
+
const isInitializedRef = useRef14(false);
|
|
3577
|
+
const [textureRevision, setTextureRevision] = useState10(0);
|
|
3578
|
+
useEffect22(() => {
|
|
3579
|
+
if (!ctx || !options.textureId) return;
|
|
3580
|
+
return ctx.resourceRegistry.subscribe(options.textureId, () => {
|
|
3581
|
+
setTextureRevision((v) => v + 1);
|
|
3582
|
+
});
|
|
3583
|
+
}, [ctx, options.textureId]);
|
|
3584
|
+
useEffect22(() => {
|
|
3260
3585
|
if (!ctx) return;
|
|
3261
|
-
|
|
3586
|
+
let cancelled = false;
|
|
3587
|
+
const materialId = options.id;
|
|
3588
|
+
const { session, resourceRegistry } = ctx;
|
|
3262
3589
|
const init = async () => {
|
|
3263
|
-
const materialPromise = session.createUnlitMaterial(options);
|
|
3264
|
-
resourceRegistry.add(options.id, materialPromise);
|
|
3265
3590
|
try {
|
|
3591
|
+
let textureIdForNative = options.textureId;
|
|
3592
|
+
if (options.textureId) {
|
|
3593
|
+
const texturePromise = resourceRegistry.get(options.textureId);
|
|
3594
|
+
try {
|
|
3595
|
+
const textureResource = await texturePromise;
|
|
3596
|
+
if (cancelled) return;
|
|
3597
|
+
textureIdForNative = textureResource.id;
|
|
3598
|
+
} catch {
|
|
3599
|
+
textureIdForNative = "";
|
|
3600
|
+
}
|
|
3601
|
+
}
|
|
3602
|
+
if (cancelled) return;
|
|
3603
|
+
const commandOptions = {
|
|
3604
|
+
color: options.color,
|
|
3605
|
+
textureId: textureIdForNative,
|
|
3606
|
+
transparent: options.transparent,
|
|
3607
|
+
opacity: options.opacity
|
|
3608
|
+
};
|
|
3609
|
+
const materialPromise = session.createUnlitMaterial(commandOptions);
|
|
3610
|
+
resourceRegistry.add(materialId, materialPromise);
|
|
3266
3611
|
const mat = await materialPromise;
|
|
3612
|
+
if (cancelled) return;
|
|
3267
3613
|
materialRef.current = mat;
|
|
3268
3614
|
isInitializedRef.current = true;
|
|
3269
3615
|
} catch (error) {
|
|
@@ -3272,22 +3618,110 @@ var UnlitMaterial = ({
|
|
|
3272
3618
|
};
|
|
3273
3619
|
init();
|
|
3274
3620
|
return () => {
|
|
3275
|
-
|
|
3621
|
+
cancelled = true;
|
|
3622
|
+
resourceRegistry.removeAndDestroy(materialId);
|
|
3276
3623
|
materialRef.current = void 0;
|
|
3277
3624
|
isInitializedRef.current = false;
|
|
3278
3625
|
};
|
|
3279
|
-
}, [ctx]);
|
|
3626
|
+
}, [ctx, options.id]);
|
|
3627
|
+
useEffect22(() => {
|
|
3628
|
+
if (!ctx || !isInitializedRef.current || !materialRef.current) return;
|
|
3629
|
+
let cancelled = false;
|
|
3630
|
+
void (async () => {
|
|
3631
|
+
const updates = {};
|
|
3632
|
+
if (options.color !== void 0) updates.color = options.color;
|
|
3633
|
+
if (options.transparent !== void 0)
|
|
3634
|
+
updates.transparent = options.transparent;
|
|
3635
|
+
if (options.opacity !== void 0) updates.opacity = options.opacity;
|
|
3636
|
+
if (options.textureId !== void 0) {
|
|
3637
|
+
if (options.textureId === "") {
|
|
3638
|
+
updates.textureId = "";
|
|
3639
|
+
} else {
|
|
3640
|
+
const texturePromise = ctx.resourceRegistry.get(options.textureId);
|
|
3641
|
+
try {
|
|
3642
|
+
const textureResource = await texturePromise;
|
|
3643
|
+
if (cancelled) return;
|
|
3644
|
+
updates.textureId = textureResource.id;
|
|
3645
|
+
} catch {
|
|
3646
|
+
updates.textureId = "";
|
|
3647
|
+
}
|
|
3648
|
+
}
|
|
3649
|
+
}
|
|
3650
|
+
if (cancelled || Object.keys(updates).length === 0) return;
|
|
3651
|
+
const mat = materialRef.current;
|
|
3652
|
+
if (mat) {
|
|
3653
|
+
void mat.updateProperties(updates).catch(() => {
|
|
3654
|
+
});
|
|
3655
|
+
}
|
|
3656
|
+
})();
|
|
3657
|
+
return () => {
|
|
3658
|
+
cancelled = true;
|
|
3659
|
+
};
|
|
3660
|
+
}, [
|
|
3661
|
+
ctx,
|
|
3662
|
+
options.color,
|
|
3663
|
+
options.textureId,
|
|
3664
|
+
options.transparent,
|
|
3665
|
+
options.opacity,
|
|
3666
|
+
textureRevision
|
|
3667
|
+
]);
|
|
3668
|
+
return null;
|
|
3669
|
+
};
|
|
3670
|
+
|
|
3671
|
+
// src/reality/components/Texture.tsx
|
|
3672
|
+
import { useEffect as useEffect23, useRef as useRef15 } from "react";
|
|
3673
|
+
var Texture = ({
|
|
3674
|
+
children,
|
|
3675
|
+
id,
|
|
3676
|
+
url,
|
|
3677
|
+
onLoad,
|
|
3678
|
+
onError
|
|
3679
|
+
}) => {
|
|
3680
|
+
const ctx = useRealityContext();
|
|
3681
|
+
const textureRef = useRef15(null);
|
|
3682
|
+
const urlRevisionRef = useRef15(0);
|
|
3683
|
+
useEffect23(() => {
|
|
3684
|
+
if (!ctx) return;
|
|
3685
|
+
const { resourceRegistry } = ctx;
|
|
3686
|
+
const capturedId = id;
|
|
3687
|
+
return () => {
|
|
3688
|
+
textureRef.current = null;
|
|
3689
|
+
resourceRegistry.removeAndDestroy(capturedId);
|
|
3690
|
+
};
|
|
3691
|
+
}, [ctx, id]);
|
|
3280
3692
|
useEffect23(() => {
|
|
3281
|
-
if (!
|
|
3282
|
-
const
|
|
3283
|
-
|
|
3284
|
-
|
|
3285
|
-
|
|
3286
|
-
|
|
3287
|
-
|
|
3288
|
-
|
|
3289
|
-
|
|
3290
|
-
|
|
3693
|
+
if (!ctx) return;
|
|
3694
|
+
const { session, resourceRegistry } = ctx;
|
|
3695
|
+
const revision = ++urlRevisionRef.current;
|
|
3696
|
+
let cancelled = false;
|
|
3697
|
+
void (async () => {
|
|
3698
|
+
const resolvedUrl = getAbsoluteUrl(url);
|
|
3699
|
+
try {
|
|
3700
|
+
if (textureRef.current) {
|
|
3701
|
+
await textureRef.current.updateProperties({ url: resolvedUrl });
|
|
3702
|
+
if (cancelled || revision !== urlRevisionRef.current) return;
|
|
3703
|
+
resourceRegistry.notify(id);
|
|
3704
|
+
onLoad?.();
|
|
3705
|
+
return;
|
|
3706
|
+
}
|
|
3707
|
+
const texturePromise = session.createTexture({ url: resolvedUrl });
|
|
3708
|
+
resourceRegistry.add(id, texturePromise);
|
|
3709
|
+
const tex = await texturePromise;
|
|
3710
|
+
if (cancelled || revision !== urlRevisionRef.current) {
|
|
3711
|
+
tex.destroy();
|
|
3712
|
+
return;
|
|
3713
|
+
}
|
|
3714
|
+
textureRef.current = tex;
|
|
3715
|
+
onLoad?.();
|
|
3716
|
+
} catch (error) {
|
|
3717
|
+
if (cancelled || revision !== urlRevisionRef.current) return;
|
|
3718
|
+
onError?.(error);
|
|
3719
|
+
}
|
|
3720
|
+
})();
|
|
3721
|
+
return () => {
|
|
3722
|
+
cancelled = true;
|
|
3723
|
+
};
|
|
3724
|
+
}, [ctx, id, url]);
|
|
3291
3725
|
return null;
|
|
3292
3726
|
};
|
|
3293
3727
|
|
|
@@ -3386,23 +3820,17 @@ var SceneGraph = ({ children }) => {
|
|
|
3386
3820
|
};
|
|
3387
3821
|
|
|
3388
3822
|
// src/reality/components/ModelAsset.tsx
|
|
3389
|
-
import { useEffect as useEffect24, useRef as
|
|
3390
|
-
var resolveAssetUrl = (url) => {
|
|
3391
|
-
if (url.startsWith("http://") || url.startsWith("https://")) {
|
|
3392
|
-
return url;
|
|
3393
|
-
}
|
|
3394
|
-
return new URL(url, window.location.href).href;
|
|
3395
|
-
};
|
|
3823
|
+
import { useEffect as useEffect24, useRef as useRef16 } from "react";
|
|
3396
3824
|
var ModelAsset = ({ children, ...options }) => {
|
|
3397
3825
|
const ctx = useRealityContext();
|
|
3398
|
-
const materialRef =
|
|
3826
|
+
const materialRef = useRef16(void 0);
|
|
3399
3827
|
useEffect24(() => {
|
|
3400
3828
|
const controller = new AbortController();
|
|
3401
3829
|
if (!ctx) return;
|
|
3402
|
-
const { session,
|
|
3830
|
+
const { session, resourceRegistry } = ctx;
|
|
3403
3831
|
const init = async () => {
|
|
3404
3832
|
try {
|
|
3405
|
-
const resolvedUrl =
|
|
3833
|
+
const resolvedUrl = getAbsoluteUrl(options.src);
|
|
3406
3834
|
const modelAssetPromise = session.createModelAsset({ url: resolvedUrl });
|
|
3407
3835
|
resourceRegistry.add(options.id, modelAssetPromise);
|
|
3408
3836
|
const mat = await modelAssetPromise;
|
|
@@ -3426,13 +3854,13 @@ var ModelAsset = ({ children, ...options }) => {
|
|
|
3426
3854
|
};
|
|
3427
3855
|
|
|
3428
3856
|
// src/reality/components/ModelEntity.tsx
|
|
3429
|
-
import { forwardRef as forwardRef18, useEffect as useEffect25, useRef as
|
|
3857
|
+
import { forwardRef as forwardRef18, useEffect as useEffect25, useRef as useRef17 } from "react";
|
|
3430
3858
|
import { jsx as jsx21 } from "react/jsx-runtime";
|
|
3431
3859
|
var ModelEntity = forwardRef18(
|
|
3432
3860
|
({ id, model, children, name, materials, ...rest }, ref) => {
|
|
3433
3861
|
const ctx = useRealityContext();
|
|
3434
|
-
const entityRef =
|
|
3435
|
-
const lastMaterialsRef =
|
|
3862
|
+
const entityRef = useRef17(null);
|
|
3863
|
+
const lastMaterialsRef = useRef17(void 0);
|
|
3436
3864
|
useEffect25(() => {
|
|
3437
3865
|
if (!ctx || !entityRef.current) return;
|
|
3438
3866
|
const next = materials ?? [];
|
|
@@ -3441,9 +3869,7 @@ var ModelEntity = forwardRef18(
|
|
|
3441
3869
|
lastMaterialsRef.current = next;
|
|
3442
3870
|
const apply = async () => {
|
|
3443
3871
|
try {
|
|
3444
|
-
const materialList = (await Promise.all(
|
|
3445
|
-
next.map((mid) => ctx.resourceRegistry.get(mid))
|
|
3446
|
-
)).filter(Boolean);
|
|
3872
|
+
const materialList = (await Promise.all(next.map((mid) => ctx.resourceRegistry.get(mid)))).filter(Boolean);
|
|
3447
3873
|
if (entityRef.current) {
|
|
3448
3874
|
await entityRef.current.setMaterials(materialList);
|
|
3449
3875
|
}
|
|
@@ -3476,9 +3902,7 @@ var ModelEntity = forwardRef18(
|
|
|
3476
3902
|
entityRef.current = ent;
|
|
3477
3903
|
if (materials && materials.length > 0) {
|
|
3478
3904
|
const materialList = (await Promise.all(
|
|
3479
|
-
materials.map(
|
|
3480
|
-
(mid) => ctx2.resourceRegistry.get(mid)
|
|
3481
|
-
)
|
|
3905
|
+
materials.map((mid) => ctx2.resourceRegistry.get(mid))
|
|
3482
3906
|
)).filter(Boolean);
|
|
3483
3907
|
if (materialList.length > 0 && !signal.aborted) {
|
|
3484
3908
|
await ent.setMaterials(materialList);
|
|
@@ -3499,10 +3923,10 @@ var ModelEntity = forwardRef18(
|
|
|
3499
3923
|
// src/reality/components/Reality.tsx
|
|
3500
3924
|
import {
|
|
3501
3925
|
forwardRef as forwardRef19,
|
|
3502
|
-
useCallback as
|
|
3926
|
+
useCallback as useCallback10,
|
|
3503
3927
|
useEffect as useEffect26,
|
|
3504
|
-
useRef as
|
|
3505
|
-
useState as
|
|
3928
|
+
useRef as useRef18,
|
|
3929
|
+
useState as useState11
|
|
3506
3930
|
} from "react";
|
|
3507
3931
|
import { Fragment as Fragment3, jsx as jsx22, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
3508
3932
|
var Reality = forwardRef19(
|
|
@@ -3525,10 +3949,10 @@ var Reality = forwardRef19(
|
|
|
3525
3949
|
onSpatialMagnifyEnd,
|
|
3526
3950
|
...props
|
|
3527
3951
|
} = inProps;
|
|
3528
|
-
const ctxRef =
|
|
3529
|
-
const creationId =
|
|
3530
|
-
const [isReady, setIsReady] =
|
|
3531
|
-
const cleanupReality =
|
|
3952
|
+
const ctxRef = useRef18(null);
|
|
3953
|
+
const creationId = useRef18(0);
|
|
3954
|
+
const [isReady, setIsReady] = useState11(false);
|
|
3955
|
+
const cleanupReality = useCallback10(() => {
|
|
3532
3956
|
ctxRef.current?.attachmentRegistry.destroy();
|
|
3533
3957
|
ctxRef.current?.resourceRegistry.destroy();
|
|
3534
3958
|
ctxRef.current?.reality.destroy();
|
|
@@ -3541,7 +3965,7 @@ var Reality = forwardRef19(
|
|
|
3541
3965
|
cleanupReality();
|
|
3542
3966
|
};
|
|
3543
3967
|
}, [cleanupReality]);
|
|
3544
|
-
const createReality =
|
|
3968
|
+
const createReality = useCallback10(async () => {
|
|
3545
3969
|
const id = ++creationId.current;
|
|
3546
3970
|
const resourceRegistry = new ResourceRegistry();
|
|
3547
3971
|
const attachmentRegistry = new AttachmentRegistry();
|
|
@@ -3584,7 +4008,7 @@ var Reality = forwardRef19(
|
|
|
3584
4008
|
return null;
|
|
3585
4009
|
}
|
|
3586
4010
|
}, [cleanupReality]);
|
|
3587
|
-
const content =
|
|
4011
|
+
const content = useCallback10(() => /* @__PURE__ */ jsx22(Fragment3, {}), []);
|
|
3588
4012
|
useRealityEvents({
|
|
3589
4013
|
instance: ctxRef.current?.reality ?? null,
|
|
3590
4014
|
onSpatialTap,
|
|
@@ -3613,7 +4037,7 @@ var Reality = forwardRef19(
|
|
|
3613
4037
|
);
|
|
3614
4038
|
|
|
3615
4039
|
// src/reality/components/AttachmentAsset.tsx
|
|
3616
|
-
import { useEffect as useEffect27, useState as
|
|
4040
|
+
import { useEffect as useEffect27, useState as useState12 } from "react";
|
|
3617
4041
|
import { createPortal as createPortal3 } from "react-dom";
|
|
3618
4042
|
import { jsx as jsx23 } from "react/jsx-runtime";
|
|
3619
4043
|
var AttachmentAsset = ({
|
|
@@ -3621,7 +4045,7 @@ var AttachmentAsset = ({
|
|
|
3621
4045
|
children
|
|
3622
4046
|
}) => {
|
|
3623
4047
|
const ctx = useRealityContext();
|
|
3624
|
-
const [containers, setContainers] =
|
|
4048
|
+
const [containers, setContainers] = useState12([]);
|
|
3625
4049
|
useEffect27(() => {
|
|
3626
4050
|
if (!ctx) return;
|
|
3627
4051
|
return ctx.attachmentRegistry.onContainersChange(name, setContainers);
|
|
@@ -3633,7 +4057,7 @@ var AttachmentAsset = ({
|
|
|
3633
4057
|
};
|
|
3634
4058
|
|
|
3635
4059
|
// src/reality/components/AttachmentEntity.tsx
|
|
3636
|
-
import { useEffect as useEffect28, useRef as
|
|
4060
|
+
import { useEffect as useEffect28, useRef as useRef19, useState as useState13 } from "react";
|
|
3637
4061
|
var instanceCounter = 0;
|
|
3638
4062
|
var AttachmentEntity = ({
|
|
3639
4063
|
attachment: attachmentName,
|
|
@@ -3642,11 +4066,11 @@ var AttachmentEntity = ({
|
|
|
3642
4066
|
}) => {
|
|
3643
4067
|
const ctx = useRealityContext();
|
|
3644
4068
|
const parent = useParentContext();
|
|
3645
|
-
const attachmentRef =
|
|
3646
|
-
const parentIdRef =
|
|
3647
|
-
const instanceIdRef =
|
|
3648
|
-
const attachmentNameRef =
|
|
3649
|
-
const [childWindow, setChildWindow] =
|
|
4069
|
+
const attachmentRef = useRef19(null);
|
|
4070
|
+
const parentIdRef = useRef19(null);
|
|
4071
|
+
const instanceIdRef = useRef19(`att_${++instanceCounter}`);
|
|
4072
|
+
const attachmentNameRef = useRef19(attachmentName);
|
|
4073
|
+
const [childWindow, setChildWindow] = useState13(null);
|
|
3650
4074
|
useEffect28(() => {
|
|
3651
4075
|
if (!ctx || !parent) return;
|
|
3652
4076
|
if (attachmentRef.current) return;
|
|
@@ -3725,7 +4149,7 @@ var AttachmentEntity = ({
|
|
|
3725
4149
|
attachmentNameRef.current = attachmentName;
|
|
3726
4150
|
}
|
|
3727
4151
|
}, [ctx, attachmentName]);
|
|
3728
|
-
useSyncHeadStyles(childWindow
|
|
4152
|
+
useSyncHeadStyles(childWindow);
|
|
3729
4153
|
useEffect28(() => {
|
|
3730
4154
|
if (!attachmentRef.current) return;
|
|
3731
4155
|
attachmentRef.current.update({ position, size });
|
|
@@ -3787,7 +4211,7 @@ var styleFlag = "enableXr";
|
|
|
3787
4211
|
var classFlag = "__enableXr__";
|
|
3788
4212
|
var xrMonitorFlag = "enable-xr-monitor";
|
|
3789
4213
|
function replaceToSpatialPrimitiveType(type, props) {
|
|
3790
|
-
if (type === Model) {
|
|
4214
|
+
if (type === Model || type === Reality) {
|
|
3791
4215
|
return type;
|
|
3792
4216
|
}
|
|
3793
4217
|
const propsObject = props;
|
|
@@ -3830,7 +4254,7 @@ function resolveSpatialObjectId(target) {
|
|
|
3830
4254
|
if (maybeEntity && typeof maybeEntity === "object" && "entity" in maybeEntity) {
|
|
3831
4255
|
return maybeEntity.entity?.id ?? null;
|
|
3832
4256
|
}
|
|
3833
|
-
const dom = target
|
|
4257
|
+
const dom = target;
|
|
3834
4258
|
if (dom && typeof dom === "object") {
|
|
3835
4259
|
const spatializedElement = dom.__spatializedElement ?? dom.__innerSpatializedElement?.();
|
|
3836
4260
|
if (spatializedElement && spatializedElement.id) {
|
|
@@ -3860,7 +4284,7 @@ async function convertCoordinate(position, { from, to }) {
|
|
|
3860
4284
|
}
|
|
3861
4285
|
|
|
3862
4286
|
// src/index.ts
|
|
3863
|
-
var version = "1.
|
|
4287
|
+
var version = "1.7.0";
|
|
3864
4288
|
if (typeof window !== "undefined") {
|
|
3865
4289
|
initPolyfill();
|
|
3866
4290
|
}
|
|
@@ -3889,12 +4313,16 @@ export {
|
|
|
3889
4313
|
SpatializedStatic3DElementContainer,
|
|
3890
4314
|
SphereEntity as Sphere,
|
|
3891
4315
|
SphereEntity,
|
|
4316
|
+
Texture,
|
|
3892
4317
|
UnlitMaterial,
|
|
4318
|
+
WebSpatialRuntime,
|
|
4319
|
+
WebSpatialRuntimeError,
|
|
3893
4320
|
SceneGraph as World,
|
|
3894
4321
|
convertCoordinate,
|
|
3895
4322
|
createElement,
|
|
3896
4323
|
enableDebugTool,
|
|
3897
4324
|
eventMap,
|
|
4325
|
+
getAbsoluteUrl,
|
|
3898
4326
|
initPolyfill,
|
|
3899
4327
|
initScene,
|
|
3900
4328
|
useMetrics,
|