@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/default/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'] = "avp"
|
|
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,7 +455,9 @@ 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
|
|
|
@@ -928,19 +476,153 @@ function getSession() {
|
|
|
928
476
|
if (_currentSession) {
|
|
929
477
|
return _currentSession;
|
|
930
478
|
}
|
|
931
|
-
_currentSession = spatial.requestSession();
|
|
932
|
-
return _currentSession;
|
|
479
|
+
_currentSession = spatial.requestSession();
|
|
480
|
+
return _currentSession;
|
|
481
|
+
}
|
|
482
|
+
|
|
483
|
+
// src/spatialized-container/context/SpatialLayerContext.ts
|
|
484
|
+
import { createContext as createContext2 } from "react";
|
|
485
|
+
var SpatialLayerContext = createContext2(0);
|
|
486
|
+
|
|
487
|
+
// src/spatialized-container/PortalSpatializedContainer.tsx
|
|
488
|
+
import { useMemo, useContext as useContext4, useEffect as useEffect6 } from "react";
|
|
489
|
+
|
|
490
|
+
// src/spatialized-container/context/PortalInstanceContext.ts
|
|
491
|
+
import { createContext as createContext3 } from "react";
|
|
492
|
+
|
|
493
|
+
// src/spatialized-container/utils.ts
|
|
494
|
+
function getInheritedStyleProps(computedStyle) {
|
|
495
|
+
var propNames = [
|
|
496
|
+
"azimuth",
|
|
497
|
+
"borderCollapse",
|
|
498
|
+
"borderSpacing",
|
|
499
|
+
"captionSide",
|
|
500
|
+
"color",
|
|
501
|
+
"cursor",
|
|
502
|
+
"direction",
|
|
503
|
+
// 'elevation',
|
|
504
|
+
"emptyCells",
|
|
505
|
+
"fontFamily",
|
|
506
|
+
"fontSize",
|
|
507
|
+
"fontStyle",
|
|
508
|
+
"fontVariant",
|
|
509
|
+
"fontWeight",
|
|
510
|
+
"font",
|
|
511
|
+
"letterSpacing",
|
|
512
|
+
"lineHeight",
|
|
513
|
+
"listStyleImage",
|
|
514
|
+
"listStylePosition",
|
|
515
|
+
"listStyleType",
|
|
516
|
+
"listStyle",
|
|
517
|
+
"orphans",
|
|
518
|
+
// 'pitchRange',
|
|
519
|
+
// 'pitch',
|
|
520
|
+
"quotes",
|
|
521
|
+
// 'richness',
|
|
522
|
+
// 'speakHeader',
|
|
523
|
+
// 'speakNumeral',
|
|
524
|
+
// 'speakPunctuation',
|
|
525
|
+
// 'speak',
|
|
526
|
+
// 'speechRate',
|
|
527
|
+
// 'stress',
|
|
528
|
+
"textAlign",
|
|
529
|
+
"textIndent",
|
|
530
|
+
"textTransform",
|
|
531
|
+
"visibility",
|
|
532
|
+
// 'voiceFamily',
|
|
533
|
+
// 'volume',
|
|
534
|
+
"whiteSpace",
|
|
535
|
+
"widows",
|
|
536
|
+
"wordSpacing",
|
|
537
|
+
// background also need to be synced
|
|
538
|
+
"background",
|
|
539
|
+
// position also need to be synced
|
|
540
|
+
"position",
|
|
541
|
+
"width",
|
|
542
|
+
"height",
|
|
543
|
+
"display",
|
|
544
|
+
// content-visibility also need to be synced
|
|
545
|
+
"contentVisibility"
|
|
546
|
+
];
|
|
547
|
+
var props = {};
|
|
548
|
+
for (var cssName of propNames) {
|
|
549
|
+
if (computedStyle[cssName]) {
|
|
550
|
+
props[cssName] = computedStyle[cssName];
|
|
551
|
+
}
|
|
552
|
+
}
|
|
553
|
+
return props;
|
|
554
|
+
}
|
|
555
|
+
function parseTransformOrigin(computedStyle) {
|
|
556
|
+
const transformOriginProperty = computedStyle.getPropertyValue("transform-origin");
|
|
557
|
+
const [x, y] = transformOriginProperty.split(" ").map(parseFloat);
|
|
558
|
+
const width = parseFloat(computedStyle.getPropertyValue("width"));
|
|
559
|
+
const height = parseFloat(computedStyle.getPropertyValue("height"));
|
|
560
|
+
return {
|
|
561
|
+
x: width > 0 ? x / width : 0.5,
|
|
562
|
+
y: height > 0 ? y / height : 0.5,
|
|
563
|
+
z: 0.5
|
|
564
|
+
};
|
|
565
|
+
}
|
|
566
|
+
function parseBorderRadius(borderProperty, width) {
|
|
567
|
+
if (borderProperty === "") {
|
|
568
|
+
return 0;
|
|
569
|
+
}
|
|
570
|
+
if (borderProperty.endsWith("%")) {
|
|
571
|
+
return width * parseFloat(borderProperty) / 100;
|
|
572
|
+
}
|
|
573
|
+
return parseFloat(borderProperty);
|
|
574
|
+
}
|
|
575
|
+
function parseCornerRadius(computedStyle) {
|
|
576
|
+
const width = parseFloat(computedStyle.getPropertyValue("width"));
|
|
577
|
+
const topLeftPropertyValue = computedStyle.getPropertyValue(
|
|
578
|
+
"border-top-left-radius"
|
|
579
|
+
);
|
|
580
|
+
const topRightPropertyValue = computedStyle.getPropertyValue(
|
|
581
|
+
"border-top-right-radius"
|
|
582
|
+
);
|
|
583
|
+
const bottomLeftPropertyValue = computedStyle.getPropertyValue(
|
|
584
|
+
"border-bottom-left-radius"
|
|
585
|
+
);
|
|
586
|
+
const bottomRightPropertyValue = computedStyle.getPropertyValue(
|
|
587
|
+
"border-bottom-right-radius"
|
|
588
|
+
);
|
|
589
|
+
const cornerRadius = {
|
|
590
|
+
topLeading: parseBorderRadius(topLeftPropertyValue, width),
|
|
591
|
+
bottomLeading: parseBorderRadius(bottomLeftPropertyValue, width),
|
|
592
|
+
topTrailing: parseBorderRadius(topRightPropertyValue, width),
|
|
593
|
+
bottomTrailing: parseBorderRadius(bottomRightPropertyValue, width)
|
|
594
|
+
};
|
|
595
|
+
return cornerRadius;
|
|
596
|
+
}
|
|
597
|
+
function extractAndRemoveCustomProperties(cssText, properties) {
|
|
598
|
+
if (!cssText) {
|
|
599
|
+
return { extractedValues: {}, filteredCssText: "" };
|
|
600
|
+
}
|
|
601
|
+
const extractedValues = {};
|
|
602
|
+
const rules = cssText.split(";");
|
|
603
|
+
const filteredRules = rules.filter((rule) => {
|
|
604
|
+
const [key, value] = rule.split(":").map((part) => part.trim());
|
|
605
|
+
if (properties.includes(key)) {
|
|
606
|
+
extractedValues[key] = value;
|
|
607
|
+
return false;
|
|
608
|
+
}
|
|
609
|
+
return true;
|
|
610
|
+
});
|
|
611
|
+
const filteredCssText = filteredRules.join(";").trim();
|
|
612
|
+
return { extractedValues, filteredCssText };
|
|
613
|
+
}
|
|
614
|
+
function joinToCSSText(cssKV) {
|
|
615
|
+
const rules = Object.entries(cssKV).map(([key, value]) => `${key}: ${value}`);
|
|
616
|
+
return rules.join(";");
|
|
933
617
|
}
|
|
934
618
|
|
|
935
|
-
// src/spatialized-container/
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
// src/spatialized-container/context/PortalInstanceContext.ts
|
|
943
|
-
import { createContext as createContext3 } from "react";
|
|
619
|
+
// src/spatialized-container/types.ts
|
|
620
|
+
var SpatialCustomStyleVars = {
|
|
621
|
+
back: "--xr-back",
|
|
622
|
+
depth: "--xr-depth",
|
|
623
|
+
backgroundMaterial: "--xr-background-material",
|
|
624
|
+
xrZIndex: "--xr-z-index"
|
|
625
|
+
};
|
|
944
626
|
|
|
945
627
|
// src/utils/debugTool.ts
|
|
946
628
|
import { isSSREnv as isSSREnv2 } from "@webspatial/core-sdk";
|
|
@@ -959,6 +641,18 @@ function enableDebugTool() {
|
|
|
959
641
|
});
|
|
960
642
|
}
|
|
961
643
|
|
|
644
|
+
// src/utils/urlUtils.ts
|
|
645
|
+
function getAbsoluteUrl(url) {
|
|
646
|
+
if (typeof window === "undefined" || !window.location?.href) {
|
|
647
|
+
return url;
|
|
648
|
+
}
|
|
649
|
+
try {
|
|
650
|
+
return new URL(url, window.location.href).href;
|
|
651
|
+
} catch {
|
|
652
|
+
return url;
|
|
653
|
+
}
|
|
654
|
+
}
|
|
655
|
+
|
|
962
656
|
// src/spatialized-container/context/PortalInstanceContext.ts
|
|
963
657
|
var PortalInstanceObject = class {
|
|
964
658
|
spatialId;
|
|
@@ -1143,14 +837,14 @@ var PortalInstanceContext = createContext3(
|
|
|
1143
837
|
);
|
|
1144
838
|
|
|
1145
839
|
// src/spatialized-container/hooks/useSync2DFrame.ts
|
|
1146
|
-
import { useEffect as
|
|
840
|
+
import { useEffect as useEffect4, useState as useState2 } from "react";
|
|
1147
841
|
function useForceUpdate() {
|
|
1148
842
|
const [, setToggle] = useState2(false);
|
|
1149
843
|
return () => setToggle((toggle) => !toggle);
|
|
1150
844
|
}
|
|
1151
845
|
function useSync2DFrame(spatialId, portalInstanceObject, spatializedContainerObject) {
|
|
1152
846
|
const forceUpdate = useForceUpdate();
|
|
1153
|
-
|
|
847
|
+
useEffect4(() => {
|
|
1154
848
|
spatializedContainerObject.on2DFrameChange(spatialId, () => {
|
|
1155
849
|
portalInstanceObject.notify2DFrameChange();
|
|
1156
850
|
forceUpdate();
|
|
@@ -1162,11 +856,11 @@ function useSync2DFrame(spatialId, portalInstanceObject, spatializedContainerObj
|
|
|
1162
856
|
}
|
|
1163
857
|
|
|
1164
858
|
// src/spatialized-container/hooks/useSpatializedElement.ts
|
|
1165
|
-
import { useEffect as
|
|
859
|
+
import { useEffect as useEffect5, useRef as useRef3, useState as useState3 } from "react";
|
|
1166
860
|
function useSpatializedElement(createSpatializedElement2, portalInstanceObject) {
|
|
1167
861
|
const [spatializedElement, setSpatializedElement] = useState3();
|
|
1168
|
-
const elementRef =
|
|
1169
|
-
|
|
862
|
+
const elementRef = useRef3(void 0);
|
|
863
|
+
useEffect5(() => {
|
|
1170
864
|
let isDestroyed = false;
|
|
1171
865
|
createSpatializedElement2().then(
|
|
1172
866
|
(inSpatializedElement) => {
|
|
@@ -1262,7 +956,7 @@ function PortalSpatializedContainer(props) {
|
|
|
1262
956
|
),
|
|
1263
957
|
[]
|
|
1264
958
|
);
|
|
1265
|
-
|
|
959
|
+
useEffect6(() => {
|
|
1266
960
|
portalInstanceObject.init();
|
|
1267
961
|
return () => {
|
|
1268
962
|
portalInstanceObject.destroy();
|
|
@@ -1277,58 +971,417 @@ function PortalSpatializedContainer(props) {
|
|
|
1277
971
|
portalInstanceObject,
|
|
1278
972
|
props.component
|
|
1279
973
|
);
|
|
1280
|
-
|
|
974
|
+
useEffect6(() => {
|
|
1281
975
|
if (spatializedElement) {
|
|
1282
976
|
spatializedElement.onSpatialTap = onSpatialTap;
|
|
1283
977
|
}
|
|
1284
978
|
}, [spatializedElement, onSpatialTap]);
|
|
1285
|
-
|
|
979
|
+
useEffect6(() => {
|
|
1286
980
|
if (spatializedElement) {
|
|
1287
981
|
spatializedElement.onSpatialDrag = onSpatialDrag;
|
|
1288
982
|
}
|
|
1289
|
-
}, [spatializedElement, onSpatialDrag]);
|
|
1290
|
-
|
|
1291
|
-
if (spatializedElement) {
|
|
1292
|
-
spatializedElement.onSpatialDragEnd = onSpatialDragEnd;
|
|
983
|
+
}, [spatializedElement, onSpatialDrag]);
|
|
984
|
+
useEffect6(() => {
|
|
985
|
+
if (spatializedElement) {
|
|
986
|
+
spatializedElement.onSpatialDragEnd = onSpatialDragEnd;
|
|
987
|
+
}
|
|
988
|
+
}, [spatializedElement, onSpatialDragEnd]);
|
|
989
|
+
useEffect6(() => {
|
|
990
|
+
if (spatializedElement) {
|
|
991
|
+
spatializedElement.onSpatialRotate = onSpatialRotate;
|
|
992
|
+
}
|
|
993
|
+
}, [spatializedElement, onSpatialRotate]);
|
|
994
|
+
useEffect6(() => {
|
|
995
|
+
if (spatializedElement) {
|
|
996
|
+
spatializedElement.onSpatialRotateEnd = onSpatialRotateEnd;
|
|
997
|
+
}
|
|
998
|
+
}, [spatializedElement, onSpatialRotateEnd]);
|
|
999
|
+
useEffect6(() => {
|
|
1000
|
+
if (spatializedElement) {
|
|
1001
|
+
spatializedElement.onSpatialMagnify = onSpatialMagnify;
|
|
1002
|
+
}
|
|
1003
|
+
}, [spatializedElement, onSpatialMagnify]);
|
|
1004
|
+
useEffect6(() => {
|
|
1005
|
+
if (spatializedElement) {
|
|
1006
|
+
spatializedElement.onSpatialMagnifyEnd = onSpatialMagnifyEnd;
|
|
1007
|
+
}
|
|
1008
|
+
}, [spatializedElement, onSpatialMagnifyEnd]);
|
|
1009
|
+
useEffect6(() => {
|
|
1010
|
+
if (spatializedElement) {
|
|
1011
|
+
spatializedElement.onSpatialDragStart = onSpatialDragStart;
|
|
1012
|
+
}
|
|
1013
|
+
}, [spatializedElement, onSpatialDragStart]);
|
|
1014
|
+
const rotateConstraintKey = constrainedAxisKey(
|
|
1015
|
+
spatialEventOptions?.constrainedToAxis
|
|
1016
|
+
);
|
|
1017
|
+
useEffect6(() => {
|
|
1018
|
+
if (!spatializedElement) return;
|
|
1019
|
+
const axis = constrainedAxisToVec3(spatialEventOptions?.constrainedToAxis);
|
|
1020
|
+
void spatializedElement.updateProperties({ rotateConstrainedToAxis: axis });
|
|
1021
|
+
}, [spatializedElement, rotateConstraintKey]);
|
|
1022
|
+
return /* @__PURE__ */ jsxs(PortalInstanceContext.Provider, { value: portalInstanceObject, children: [
|
|
1023
|
+
spatializedElement && portalInstanceObject.dom && /* @__PURE__ */ jsx3(Content, { spatializedElement, ...restProps }),
|
|
1024
|
+
PlaceholderEl
|
|
1025
|
+
] });
|
|
1026
|
+
}
|
|
1027
|
+
|
|
1028
|
+
// src/spatialized-container/hooks/useDomProxy.ts
|
|
1029
|
+
import { useCallback as useCallback5, useEffect as useEffect7, useRef as useRef4 } from "react";
|
|
1030
|
+
import { supports } from "@webspatial/core-sdk";
|
|
1031
|
+
var SpatialContainerRefProxy = class {
|
|
1032
|
+
transformVisibilityTaskContainerDom = null;
|
|
1033
|
+
/** Raw Standard host element (styled root). Used to mirror class onto the transform probe. */
|
|
1034
|
+
standardRawDom = null;
|
|
1035
|
+
standardClassObserver = null;
|
|
1036
|
+
/**
|
|
1037
|
+
* When set, Standard's DOM className is forwarded here so TransformVisibilityTaskContainer
|
|
1038
|
+
* can render it from React state (avoids React clobbering imperative class updates).
|
|
1039
|
+
*/
|
|
1040
|
+
mirrorClassNotify = null;
|
|
1041
|
+
/** Last class string applied to the probe + used to skip redundant syncs. */
|
|
1042
|
+
lastMirroredClassName = null;
|
|
1043
|
+
/** Coalesce multiple class sync triggers in the same turn (Observer + classList, etc.). */
|
|
1044
|
+
classSyncMicrotaskQueued = false;
|
|
1045
|
+
ref;
|
|
1046
|
+
domProxy;
|
|
1047
|
+
/** Last value dispatched to `ref` (undefined = none yet); avoids duplicate null/proxy writes. */
|
|
1048
|
+
lastOutgoingToRef = void 0;
|
|
1049
|
+
installedProperties = [];
|
|
1050
|
+
// extre ref props, used to add extra props to ref
|
|
1051
|
+
extraRefProps;
|
|
1052
|
+
constructor(ref, extraRefProps) {
|
|
1053
|
+
this.ref = ref;
|
|
1054
|
+
this.extraRefProps = extraRefProps;
|
|
1055
|
+
}
|
|
1056
|
+
setMirrorClassNotify(fn) {
|
|
1057
|
+
this.mirrorClassNotify = fn;
|
|
1058
|
+
if (fn && this.standardRawDom) {
|
|
1059
|
+
this.flushSyncTransformClassFromStandard(true);
|
|
1060
|
+
}
|
|
1061
|
+
}
|
|
1062
|
+
disconnectStandardClassObserver() {
|
|
1063
|
+
this.standardClassObserver?.disconnect();
|
|
1064
|
+
this.standardClassObserver = null;
|
|
1065
|
+
}
|
|
1066
|
+
attachStandardClassObserver() {
|
|
1067
|
+
this.disconnectStandardClassObserver();
|
|
1068
|
+
if (!this.standardRawDom) {
|
|
1069
|
+
return;
|
|
1070
|
+
}
|
|
1071
|
+
this.standardClassObserver = new MutationObserver(() => {
|
|
1072
|
+
this.ensureSpatialDefaultClass();
|
|
1073
|
+
this.scheduleSyncTransformClassFromStandard();
|
|
1074
|
+
});
|
|
1075
|
+
this.standardClassObserver.observe(this.standardRawDom, {
|
|
1076
|
+
attributes: true,
|
|
1077
|
+
attributeFilter: ["class"]
|
|
1078
|
+
});
|
|
1079
|
+
}
|
|
1080
|
+
ensureSpatialDefaultClass() {
|
|
1081
|
+
const dom = this.standardRawDom;
|
|
1082
|
+
if (!dom) return;
|
|
1083
|
+
if (dom.classList.contains("xr-spatial-default")) return;
|
|
1084
|
+
dom.classList.add("xr-spatial-default");
|
|
1085
|
+
}
|
|
1086
|
+
/**
|
|
1087
|
+
* Merge multiple sync requests (e.g. classList hook + MutationObserver) into one microtask.
|
|
1088
|
+
*/
|
|
1089
|
+
scheduleSyncTransformClassFromStandard() {
|
|
1090
|
+
if (this.classSyncMicrotaskQueued) {
|
|
1091
|
+
return;
|
|
1092
|
+
}
|
|
1093
|
+
this.classSyncMicrotaskQueued = true;
|
|
1094
|
+
queueMicrotask(() => {
|
|
1095
|
+
this.classSyncMicrotaskQueued = false;
|
|
1096
|
+
this.flushSyncTransformClassFromStandard(false);
|
|
1097
|
+
});
|
|
1098
|
+
}
|
|
1099
|
+
/**
|
|
1100
|
+
* Source of truth: Standard host DOM (incl. styled-components runtime class changes).
|
|
1101
|
+
* @param force when true, skip same-string short-circuit (e.g. mirror notify just registered).
|
|
1102
|
+
*/
|
|
1103
|
+
flushSyncTransformClassFromStandard(force) {
|
|
1104
|
+
if (!this.standardRawDom) {
|
|
1105
|
+
return;
|
|
1106
|
+
}
|
|
1107
|
+
const name = this.standardRawDom.className;
|
|
1108
|
+
const probe = this.transformVisibilityTaskContainerDom;
|
|
1109
|
+
if (!force && probe && probe.className === name && this.lastMirroredClassName === name) {
|
|
1110
|
+
return;
|
|
1111
|
+
}
|
|
1112
|
+
this.lastMirroredClassName = name;
|
|
1113
|
+
if (probe) {
|
|
1114
|
+
probe.className = name;
|
|
1115
|
+
}
|
|
1116
|
+
this.mirrorClassNotify?.(name);
|
|
1117
|
+
}
|
|
1118
|
+
updateStandardSpatializedContainerDom(dom) {
|
|
1119
|
+
if (!dom) {
|
|
1120
|
+
this.disconnectStandardClassObserver();
|
|
1121
|
+
this.clearInstalledProperties();
|
|
1122
|
+
this.standardRawDom = null;
|
|
1123
|
+
this.lastMirroredClassName = null;
|
|
1124
|
+
this.domProxy = void 0;
|
|
1125
|
+
this.updateDomProxyToRef();
|
|
1126
|
+
return;
|
|
1127
|
+
}
|
|
1128
|
+
if (this.standardRawDom === dom && this.domProxy) {
|
|
1129
|
+
this.scheduleSyncTransformClassFromStandard();
|
|
1130
|
+
return;
|
|
1131
|
+
}
|
|
1132
|
+
this.clearInstalledProperties();
|
|
1133
|
+
this.standardRawDom = dom;
|
|
1134
|
+
this.domProxy = dom;
|
|
1135
|
+
this.installSpatialRefBehavior(dom);
|
|
1136
|
+
const root = dom.getRootNode();
|
|
1137
|
+
if (root === document || root instanceof ShadowRoot) {
|
|
1138
|
+
ensureSpatialDefaultStyleInRoot(root);
|
|
1139
|
+
}
|
|
1140
|
+
this.attachStandardClassObserver();
|
|
1141
|
+
this.updateDomProxyToRef();
|
|
1142
|
+
this.scheduleSyncTransformClassFromStandard();
|
|
1143
|
+
}
|
|
1144
|
+
clearInstalledProperties() {
|
|
1145
|
+
const dom = this.standardRawDom;
|
|
1146
|
+
if (!dom) return;
|
|
1147
|
+
for (const prop of this.installedProperties) {
|
|
1148
|
+
delete dom[prop];
|
|
1149
|
+
}
|
|
1150
|
+
this.installedProperties = [];
|
|
1151
|
+
}
|
|
1152
|
+
defineDomProperty(dom, prop, descriptor) {
|
|
1153
|
+
Object.defineProperty(dom, prop, {
|
|
1154
|
+
configurable: true,
|
|
1155
|
+
...descriptor
|
|
1156
|
+
});
|
|
1157
|
+
this.installedProperties.push(prop);
|
|
1158
|
+
}
|
|
1159
|
+
installSpatialRefBehavior(dom) {
|
|
1160
|
+
const self = this;
|
|
1161
|
+
const rawStyle = dom.style;
|
|
1162
|
+
const rawRemoveProperty = rawStyle.removeProperty.bind(rawStyle);
|
|
1163
|
+
const rawGetPropertyValue = rawStyle.getPropertyValue.bind(rawStyle);
|
|
1164
|
+
const rawRemoveAttribute = dom.removeAttribute.bind(dom);
|
|
1165
|
+
const spatialStyleProperties = ["visibility", "transform"];
|
|
1166
|
+
const styleProxy = new Proxy(rawStyle, {
|
|
1167
|
+
get(target, prop) {
|
|
1168
|
+
if (prop === "visibility" || prop === "transform") {
|
|
1169
|
+
return self.transformVisibilityTaskContainerDom?.style.getPropertyValue(
|
|
1170
|
+
prop
|
|
1171
|
+
);
|
|
1172
|
+
}
|
|
1173
|
+
const value = Reflect.get(target, prop);
|
|
1174
|
+
if (typeof value === "function") {
|
|
1175
|
+
if (prop === "setProperty" || prop === "removeProperty" || prop === "getPropertyValue") {
|
|
1176
|
+
return function(...args) {
|
|
1177
|
+
const [property] = args;
|
|
1178
|
+
if (spatialStyleProperties.includes(property)) {
|
|
1179
|
+
if (prop === "setProperty") {
|
|
1180
|
+
const [, kValue, priority] = args;
|
|
1181
|
+
self.transformVisibilityTaskContainerDom?.style.setProperty(
|
|
1182
|
+
property,
|
|
1183
|
+
kValue,
|
|
1184
|
+
priority
|
|
1185
|
+
);
|
|
1186
|
+
} else if (prop === "removeProperty") {
|
|
1187
|
+
return self.transformVisibilityTaskContainerDom?.style.removeProperty(
|
|
1188
|
+
property
|
|
1189
|
+
);
|
|
1190
|
+
} else if (prop === "getPropertyValue") {
|
|
1191
|
+
return self.transformVisibilityTaskContainerDom?.style.getPropertyValue(
|
|
1192
|
+
property
|
|
1193
|
+
);
|
|
1194
|
+
}
|
|
1195
|
+
return void 0;
|
|
1196
|
+
}
|
|
1197
|
+
return value.apply(this, args);
|
|
1198
|
+
}.bind(target);
|
|
1199
|
+
}
|
|
1200
|
+
return value.bind(target);
|
|
1201
|
+
}
|
|
1202
|
+
return value;
|
|
1203
|
+
},
|
|
1204
|
+
set(target, prop, value) {
|
|
1205
|
+
if (prop === "visibility") {
|
|
1206
|
+
self.transformVisibilityTaskContainerDom?.style.setProperty(
|
|
1207
|
+
"visibility",
|
|
1208
|
+
value
|
|
1209
|
+
);
|
|
1210
|
+
return true;
|
|
1211
|
+
}
|
|
1212
|
+
if (prop === "transform") {
|
|
1213
|
+
self.transformVisibilityTaskContainerDom?.style.setProperty(
|
|
1214
|
+
"transform",
|
|
1215
|
+
value
|
|
1216
|
+
);
|
|
1217
|
+
return true;
|
|
1218
|
+
}
|
|
1219
|
+
if (Object.values(SpatialCustomStyleVars).includes(prop)) {
|
|
1220
|
+
target.setProperty(prop, value);
|
|
1221
|
+
return true;
|
|
1222
|
+
}
|
|
1223
|
+
if (prop === "cssText") {
|
|
1224
|
+
const { extractedValues, filteredCssText } = extractAndRemoveCustomProperties(
|
|
1225
|
+
value,
|
|
1226
|
+
spatialStyleProperties
|
|
1227
|
+
);
|
|
1228
|
+
spatialStyleProperties.forEach((key) => {
|
|
1229
|
+
if (extractedValues[key]) {
|
|
1230
|
+
self.transformVisibilityTaskContainerDom?.style.setProperty(
|
|
1231
|
+
key,
|
|
1232
|
+
extractedValues[key]
|
|
1233
|
+
);
|
|
1234
|
+
} else {
|
|
1235
|
+
rawRemoveProperty(key);
|
|
1236
|
+
}
|
|
1237
|
+
});
|
|
1238
|
+
const appendedCSSText = joinToCSSText({
|
|
1239
|
+
transform: "none",
|
|
1240
|
+
visibility: "hidden"
|
|
1241
|
+
});
|
|
1242
|
+
return Reflect.set(
|
|
1243
|
+
target,
|
|
1244
|
+
prop,
|
|
1245
|
+
[appendedCSSText, filteredCssText].join(";")
|
|
1246
|
+
);
|
|
1247
|
+
}
|
|
1248
|
+
return Reflect.set(target, prop, value);
|
|
1249
|
+
}
|
|
1250
|
+
});
|
|
1251
|
+
this.defineDomProperty(dom, "style", {
|
|
1252
|
+
get() {
|
|
1253
|
+
return styleProxy;
|
|
1254
|
+
},
|
|
1255
|
+
set(value) {
|
|
1256
|
+
styleProxy.cssText = String(value);
|
|
1257
|
+
}
|
|
1258
|
+
});
|
|
1259
|
+
this.defineDomProperty(dom, "className", {
|
|
1260
|
+
get() {
|
|
1261
|
+
return dom.getAttribute("class") ?? "";
|
|
1262
|
+
},
|
|
1263
|
+
set(value) {
|
|
1264
|
+
dom.setAttribute("class", String(value));
|
|
1265
|
+
if (!dom.classList.contains("xr-spatial-default")) {
|
|
1266
|
+
dom.classList.add("xr-spatial-default");
|
|
1267
|
+
}
|
|
1268
|
+
self.scheduleSyncTransformClassFromStandard();
|
|
1269
|
+
}
|
|
1270
|
+
});
|
|
1271
|
+
this.defineDomProperty(dom, "removeAttribute", {
|
|
1272
|
+
value(property) {
|
|
1273
|
+
if (property === "style") {
|
|
1274
|
+
rawStyle.cssText = "visibility: hidden; transition: none; transform: none;";
|
|
1275
|
+
self.transformVisibilityTaskContainerDom?.style.removeProperty(
|
|
1276
|
+
"visibility"
|
|
1277
|
+
);
|
|
1278
|
+
self.transformVisibilityTaskContainerDom?.style.removeProperty(
|
|
1279
|
+
"transform"
|
|
1280
|
+
);
|
|
1281
|
+
return;
|
|
1282
|
+
}
|
|
1283
|
+
if (property === "class") {
|
|
1284
|
+
dom.className = "xr-spatial-default";
|
|
1285
|
+
return;
|
|
1286
|
+
}
|
|
1287
|
+
return rawRemoveAttribute(property);
|
|
1288
|
+
}
|
|
1289
|
+
});
|
|
1290
|
+
if (supports("xrClientDepth")) {
|
|
1291
|
+
this.defineDomProperty(dom, "xrClientDepth", {
|
|
1292
|
+
get() {
|
|
1293
|
+
return rawGetPropertyValue(SpatialCustomStyleVars.depth);
|
|
1294
|
+
}
|
|
1295
|
+
});
|
|
1296
|
+
}
|
|
1297
|
+
if (supports("xrOffsetBack")) {
|
|
1298
|
+
this.defineDomProperty(dom, "xrOffsetBack", {
|
|
1299
|
+
get() {
|
|
1300
|
+
return rawGetPropertyValue(SpatialCustomStyleVars.back);
|
|
1301
|
+
}
|
|
1302
|
+
});
|
|
1293
1303
|
}
|
|
1294
|
-
|
|
1295
|
-
|
|
1296
|
-
|
|
1297
|
-
|
|
1304
|
+
if (this.extraRefProps) {
|
|
1305
|
+
const extraProps = this.extraRefProps(dom);
|
|
1306
|
+
for (const prop of Object.keys(extraProps)) {
|
|
1307
|
+
this.defineDomProperty(dom, prop, {
|
|
1308
|
+
get() {
|
|
1309
|
+
return extraProps[prop];
|
|
1310
|
+
},
|
|
1311
|
+
set(value) {
|
|
1312
|
+
extraProps[prop] = value;
|
|
1313
|
+
}
|
|
1314
|
+
});
|
|
1315
|
+
}
|
|
1298
1316
|
}
|
|
1299
|
-
}
|
|
1300
|
-
|
|
1301
|
-
|
|
1302
|
-
|
|
1317
|
+
}
|
|
1318
|
+
updateTransformVisibilityTaskContainerDom(dom) {
|
|
1319
|
+
this.transformVisibilityTaskContainerDom = dom;
|
|
1320
|
+
if (!dom) {
|
|
1321
|
+
this.lastMirroredClassName = null;
|
|
1303
1322
|
}
|
|
1304
|
-
|
|
1305
|
-
|
|
1306
|
-
|
|
1307
|
-
|
|
1323
|
+
this.scheduleSyncTransformClassFromStandard();
|
|
1324
|
+
this.updateDomProxyToRef();
|
|
1325
|
+
}
|
|
1326
|
+
updateDomProxyToRef() {
|
|
1327
|
+
const ref = this.ref;
|
|
1328
|
+
if (!ref) {
|
|
1329
|
+
return;
|
|
1308
1330
|
}
|
|
1309
|
-
|
|
1310
|
-
|
|
1311
|
-
|
|
1312
|
-
spatializedElement.onSpatialMagnifyEnd = onSpatialMagnifyEnd;
|
|
1331
|
+
const next = this.domProxy && this.transformVisibilityTaskContainerDom ? this.domProxy : null;
|
|
1332
|
+
if (this.lastOutgoingToRef === next) {
|
|
1333
|
+
return;
|
|
1313
1334
|
}
|
|
1314
|
-
|
|
1315
|
-
|
|
1316
|
-
|
|
1317
|
-
|
|
1335
|
+
this.lastOutgoingToRef = next;
|
|
1336
|
+
if (next) {
|
|
1337
|
+
if (typeof ref === "function") {
|
|
1338
|
+
ref(next);
|
|
1339
|
+
} else {
|
|
1340
|
+
ref.current = next;
|
|
1341
|
+
}
|
|
1342
|
+
} else {
|
|
1343
|
+
if (typeof ref === "function") {
|
|
1344
|
+
ref(null);
|
|
1345
|
+
} else {
|
|
1346
|
+
ref.current = null;
|
|
1347
|
+
}
|
|
1318
1348
|
}
|
|
1319
|
-
}
|
|
1320
|
-
|
|
1321
|
-
|
|
1349
|
+
}
|
|
1350
|
+
updateRef(ref) {
|
|
1351
|
+
if (this.ref === ref) {
|
|
1352
|
+
return;
|
|
1353
|
+
}
|
|
1354
|
+
this.ref = ref;
|
|
1355
|
+
this.lastOutgoingToRef = void 0;
|
|
1356
|
+
this.updateDomProxyToRef();
|
|
1357
|
+
}
|
|
1358
|
+
};
|
|
1359
|
+
function useDomProxy(ref, extraRefProps) {
|
|
1360
|
+
const spatialContainerRefProxy = useRef4(
|
|
1361
|
+
new SpatialContainerRefProxy(ref, extraRefProps)
|
|
1322
1362
|
);
|
|
1323
1363
|
useEffect7(() => {
|
|
1324
|
-
|
|
1325
|
-
|
|
1326
|
-
|
|
1327
|
-
|
|
1328
|
-
|
|
1329
|
-
|
|
1330
|
-
|
|
1331
|
-
|
|
1364
|
+
spatialContainerRefProxy.current.updateRef(ref);
|
|
1365
|
+
}, [ref]);
|
|
1366
|
+
const transformVisibilityTaskContainerCallback = useCallback5(
|
|
1367
|
+
(el) => {
|
|
1368
|
+
spatialContainerRefProxy.current.updateTransformVisibilityTaskContainerDom(
|
|
1369
|
+
el
|
|
1370
|
+
);
|
|
1371
|
+
},
|
|
1372
|
+
[]
|
|
1373
|
+
);
|
|
1374
|
+
const standardSpatializedContainerCallback = useCallback5(
|
|
1375
|
+
(el) => {
|
|
1376
|
+
spatialContainerRefProxy.current.updateStandardSpatializedContainerDom(el);
|
|
1377
|
+
},
|
|
1378
|
+
[]
|
|
1379
|
+
);
|
|
1380
|
+
return {
|
|
1381
|
+
transformVisibilityTaskContainerCallback,
|
|
1382
|
+
standardSpatializedContainerCallback,
|
|
1383
|
+
spatialContainerRefProxy
|
|
1384
|
+
};
|
|
1332
1385
|
}
|
|
1333
1386
|
|
|
1334
1387
|
// src/reality/context/InsideAttachmentContext.tsx
|
|
@@ -1570,6 +1623,7 @@ function withSSRSupported(Component) {
|
|
|
1570
1623
|
import { jsx as jsx6, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
1571
1624
|
function DegradedContainer({
|
|
1572
1625
|
innerRef,
|
|
1626
|
+
enableOnSpatialContentReadyFallback,
|
|
1573
1627
|
...inprops
|
|
1574
1628
|
}) {
|
|
1575
1629
|
const {
|
|
@@ -1590,9 +1644,48 @@ function DegradedContainer({
|
|
|
1590
1644
|
getExtraSpatializedElementProperties: _getExtra,
|
|
1591
1645
|
extraRefProps: _extraRef,
|
|
1592
1646
|
sizingMode: _sizingMode,
|
|
1647
|
+
onSpatialContentReady: _onSpatialContentReady,
|
|
1593
1648
|
...restProps
|
|
1594
1649
|
} = inprops;
|
|
1595
|
-
|
|
1650
|
+
const [hostEl, setHostEl] = useState6(null);
|
|
1651
|
+
const callbackRef = useRef5(_onSpatialContentReady);
|
|
1652
|
+
callbackRef.current = _onSpatialContentReady;
|
|
1653
|
+
useLayoutEffect2(() => {
|
|
1654
|
+
if (!enableOnSpatialContentReadyFallback || !hostEl || !hostEl.isConnected || !callbackRef.current) {
|
|
1655
|
+
return () => {
|
|
1656
|
+
};
|
|
1657
|
+
}
|
|
1658
|
+
let cleanup;
|
|
1659
|
+
try {
|
|
1660
|
+
cleanup = callbackRef.current({ host: hostEl });
|
|
1661
|
+
} catch (e) {
|
|
1662
|
+
if (process.env.NODE_ENV !== "production") {
|
|
1663
|
+
console.error("[WebSpatial] onSpatialContentReady threw", e);
|
|
1664
|
+
}
|
|
1665
|
+
}
|
|
1666
|
+
return () => {
|
|
1667
|
+
if (typeof cleanup !== "function") return;
|
|
1668
|
+
try {
|
|
1669
|
+
cleanup();
|
|
1670
|
+
} catch (e) {
|
|
1671
|
+
if (process.env.NODE_ENV !== "production") {
|
|
1672
|
+
console.error("[WebSpatial] onSpatialContentReady cleanup threw", e);
|
|
1673
|
+
}
|
|
1674
|
+
}
|
|
1675
|
+
};
|
|
1676
|
+
}, [enableOnSpatialContentReadyFallback, hostEl]);
|
|
1677
|
+
const setHostRef = useCallback6(
|
|
1678
|
+
(node) => {
|
|
1679
|
+
if (typeof innerRef === "function") {
|
|
1680
|
+
innerRef(node);
|
|
1681
|
+
} else if (innerRef != null) {
|
|
1682
|
+
innerRef.current = node;
|
|
1683
|
+
}
|
|
1684
|
+
setHostEl(node);
|
|
1685
|
+
},
|
|
1686
|
+
[innerRef]
|
|
1687
|
+
);
|
|
1688
|
+
return /* @__PURE__ */ jsx6(Component, { ref: setHostRef, ...restProps, children });
|
|
1596
1689
|
}
|
|
1597
1690
|
function SpatializedContainerBase(inprops, ref) {
|
|
1598
1691
|
const isWebSpatialEnv = getSession() !== null;
|
|
@@ -1603,7 +1696,14 @@ function SpatializedContainerBase(inprops, ref) {
|
|
|
1603
1696
|
`[WebSpatial] ${inprops.component || "Spatial element"} cannot be used inside AttachmentAsset. Rendering as plain HTML.`
|
|
1604
1697
|
);
|
|
1605
1698
|
}
|
|
1606
|
-
return /* @__PURE__ */ jsx6(
|
|
1699
|
+
return /* @__PURE__ */ jsx6(
|
|
1700
|
+
DegradedContainer,
|
|
1701
|
+
{
|
|
1702
|
+
...inprops,
|
|
1703
|
+
innerRef: ref,
|
|
1704
|
+
enableOnSpatialContentReadyFallback: !isWebSpatialEnv && !insideAttachment
|
|
1705
|
+
}
|
|
1706
|
+
);
|
|
1607
1707
|
}
|
|
1608
1708
|
const layer = useContext7(SpatialLayerContext) + 1;
|
|
1609
1709
|
const rootSpatializedContainerObject = useContext7(
|
|
@@ -1686,6 +1786,7 @@ function SpatializedContainerBase(inprops, ref) {
|
|
|
1686
1786
|
createSpatializedElement: createSpatializedElement2,
|
|
1687
1787
|
getExtraSpatializedElementProperties: getExtraSpatializedElementProperties2,
|
|
1688
1788
|
spatialEventOptions: _nestedSpatialEventOptions,
|
|
1789
|
+
onSpatialContentReady: _nestedOnSpatialContentReady,
|
|
1689
1790
|
...restProps
|
|
1690
1791
|
} = props;
|
|
1691
1792
|
return /* @__PURE__ */ jsxs2(SpatialLayerContext.Provider, { value: layer, children: [
|
|
@@ -1749,6 +1850,7 @@ function SpatializedContainerBase(inprops, ref) {
|
|
|
1749
1850
|
createSpatializedElement: createSpatializedElement2,
|
|
1750
1851
|
getExtraSpatializedElementProperties: getExtraSpatializedElementProperties2,
|
|
1751
1852
|
spatialEventOptions: _rootSpatialEventOptions,
|
|
1853
|
+
onSpatialContentReady: _rootOnSpatialContentReady,
|
|
1752
1854
|
...restProps
|
|
1753
1855
|
} = props;
|
|
1754
1856
|
return /* @__PURE__ */ jsx6(SpatialLayerContext.Provider, { value: layer, children: /* @__PURE__ */ jsxs2(
|
|
@@ -1795,8 +1897,10 @@ var SpatializedContainer = withSSRSupported(
|
|
|
1795
1897
|
import { createPortal as createPortal2 } from "react-dom";
|
|
1796
1898
|
import {
|
|
1797
1899
|
forwardRef as forwardRef5,
|
|
1900
|
+
useCallback as useCallback7,
|
|
1798
1901
|
useContext as useContext8,
|
|
1799
|
-
useEffect as useEffect12
|
|
1902
|
+
useEffect as useEffect12,
|
|
1903
|
+
useState as useState7
|
|
1800
1904
|
} from "react";
|
|
1801
1905
|
|
|
1802
1906
|
// src/utils/windowStyleSync.ts
|
|
@@ -1909,55 +2013,145 @@ async function syncParentHeadToChild(childWindow) {
|
|
|
1909
2013
|
|
|
1910
2014
|
// src/utils/useSyncHeadStyles.ts
|
|
1911
2015
|
import { useEffect as useEffect11 } from "react";
|
|
1912
|
-
function
|
|
1913
|
-
if (!Array.isArray(mutations) || mutations.length === 0) return
|
|
2016
|
+
function getSyncTiming(mutations) {
|
|
2017
|
+
if (!Array.isArray(mutations) || mutations.length === 0) return null;
|
|
2018
|
+
let hasDelayed = false;
|
|
1914
2019
|
for (const mutation of mutations) {
|
|
2020
|
+
if (mutation.type === "characterData") {
|
|
2021
|
+
const parent = mutation.target.parentElement;
|
|
2022
|
+
if (parent?.tagName === "STYLE") return "immediate";
|
|
2023
|
+
}
|
|
1915
2024
|
const nodes = [
|
|
2025
|
+
mutation.target,
|
|
1916
2026
|
...Array.from(mutation.addedNodes),
|
|
1917
2027
|
...Array.from(mutation.removedNodes)
|
|
1918
2028
|
];
|
|
1919
2029
|
for (const node of nodes) {
|
|
1920
2030
|
if (!(node instanceof Element)) continue;
|
|
1921
2031
|
const tag = node.tagName;
|
|
1922
|
-
if (tag === "STYLE") return
|
|
2032
|
+
if (tag === "STYLE") return "immediate";
|
|
1923
2033
|
if (tag === "LINK") {
|
|
1924
2034
|
const { rel } = node;
|
|
1925
|
-
if (rel && rel.toLowerCase() === "stylesheet")
|
|
2035
|
+
if (rel && rel.toLowerCase() === "stylesheet") hasDelayed = true;
|
|
1926
2036
|
}
|
|
1927
2037
|
}
|
|
1928
2038
|
}
|
|
1929
|
-
return
|
|
2039
|
+
return hasDelayed ? "delayed" : null;
|
|
1930
2040
|
}
|
|
1931
2041
|
function useSyncHeadStyles(childWindow, options) {
|
|
1932
2042
|
const delayMs = 100;
|
|
1933
|
-
const subtree = options?.subtree ??
|
|
2043
|
+
const subtree = options?.subtree ?? true;
|
|
1934
2044
|
const immediate = options?.immediate ?? true;
|
|
1935
2045
|
useEffect11(() => {
|
|
1936
2046
|
if (!childWindow) return;
|
|
1937
2047
|
let timer;
|
|
1938
|
-
|
|
2048
|
+
let immediateQueued = false;
|
|
2049
|
+
let disposed = false;
|
|
2050
|
+
const scheduleSync = (timing = "delayed") => {
|
|
1939
2051
|
if (timer) window.clearTimeout(timer);
|
|
2052
|
+
if (timing === "immediate") {
|
|
2053
|
+
if (immediateQueued) return;
|
|
2054
|
+
immediateQueued = true;
|
|
2055
|
+
queueMicrotask(() => {
|
|
2056
|
+
immediateQueued = false;
|
|
2057
|
+
if (disposed) return;
|
|
2058
|
+
syncParentHeadToChild(childWindow);
|
|
2059
|
+
});
|
|
2060
|
+
return;
|
|
2061
|
+
}
|
|
1940
2062
|
timer = window.setTimeout(() => {
|
|
2063
|
+
if (disposed) return;
|
|
1941
2064
|
syncParentHeadToChild(childWindow);
|
|
1942
2065
|
}, delayMs);
|
|
1943
2066
|
};
|
|
1944
2067
|
if (immediate) scheduleSync();
|
|
1945
2068
|
const observer = new MutationObserver((mutations) => {
|
|
1946
|
-
|
|
1947
|
-
|
|
2069
|
+
const timing = getSyncTiming(mutations);
|
|
2070
|
+
if (!timing) return;
|
|
2071
|
+
scheduleSync(timing);
|
|
2072
|
+
});
|
|
2073
|
+
observer.observe(document.head, {
|
|
2074
|
+
childList: true,
|
|
2075
|
+
characterData: true,
|
|
2076
|
+
subtree
|
|
1948
2077
|
});
|
|
1949
|
-
observer.observe(document.head, { childList: true, subtree });
|
|
1950
2078
|
return () => {
|
|
2079
|
+
disposed = true;
|
|
1951
2080
|
if (timer) window.clearTimeout(timer);
|
|
1952
2081
|
observer.disconnect();
|
|
1953
2082
|
};
|
|
1954
2083
|
}, [childWindow, delayMs, subtree, immediate]);
|
|
1955
2084
|
}
|
|
1956
2085
|
|
|
2086
|
+
// src/spatialized-container/hooks/useSpatialContentReady.ts
|
|
2087
|
+
import { useLayoutEffect as useLayoutEffect3, useRef as useRef6 } from "react";
|
|
2088
|
+
var isDev = process.env.NODE_ENV !== "production";
|
|
2089
|
+
function safeInvokeCleanup(cleanup) {
|
|
2090
|
+
if (!cleanup) return;
|
|
2091
|
+
try {
|
|
2092
|
+
cleanup();
|
|
2093
|
+
} catch (e) {
|
|
2094
|
+
if (isDev) {
|
|
2095
|
+
console.error("[WebSpatial] onSpatialContentReady cleanup threw", e);
|
|
2096
|
+
}
|
|
2097
|
+
}
|
|
2098
|
+
}
|
|
2099
|
+
function useSpatialContentReady(params) {
|
|
2100
|
+
const {
|
|
2101
|
+
spatializedElement,
|
|
2102
|
+
portalInstanceObject,
|
|
2103
|
+
hostElement,
|
|
2104
|
+
onSpatialContentReady
|
|
2105
|
+
} = params;
|
|
2106
|
+
const callbackRef = useRef6(onSpatialContentReady);
|
|
2107
|
+
callbackRef.current = onSpatialContentReady;
|
|
2108
|
+
useLayoutEffect3(() => {
|
|
2109
|
+
const dom = portalInstanceObject.dom;
|
|
2110
|
+
const isReady = !!(spatializedElement && dom && hostElement && hostElement.isConnected);
|
|
2111
|
+
if (!isReady || !hostElement) {
|
|
2112
|
+
return () => {
|
|
2113
|
+
};
|
|
2114
|
+
}
|
|
2115
|
+
const cb = callbackRef.current;
|
|
2116
|
+
let cleanupFromCallback;
|
|
2117
|
+
if (cb) {
|
|
2118
|
+
try {
|
|
2119
|
+
const ret = cb({ host: hostElement });
|
|
2120
|
+
cleanupFromCallback = typeof ret === "function" ? ret : void 0;
|
|
2121
|
+
} catch (e) {
|
|
2122
|
+
if (isDev) {
|
|
2123
|
+
console.error("[WebSpatial] onSpatialContentReady threw", e);
|
|
2124
|
+
}
|
|
2125
|
+
}
|
|
2126
|
+
}
|
|
2127
|
+
return () => {
|
|
2128
|
+
safeInvokeCleanup(cleanupFromCallback);
|
|
2129
|
+
};
|
|
2130
|
+
}, [spatializedElement, portalInstanceObject.dom, hostElement]);
|
|
2131
|
+
}
|
|
2132
|
+
|
|
1957
2133
|
// src/spatialized-container/Spatialized2DElementContainer.tsx
|
|
1958
2134
|
import { jsx as jsx7 } from "react/jsx-runtime";
|
|
1959
|
-
function
|
|
1960
|
-
|
|
2135
|
+
function mergeRefs(...refs) {
|
|
2136
|
+
return (value) => {
|
|
2137
|
+
for (const ref of refs) {
|
|
2138
|
+
if (ref == null) continue;
|
|
2139
|
+
if (typeof ref === "function") {
|
|
2140
|
+
ref(value);
|
|
2141
|
+
} else {
|
|
2142
|
+
;
|
|
2143
|
+
ref.current = value;
|
|
2144
|
+
}
|
|
2145
|
+
}
|
|
2146
|
+
};
|
|
2147
|
+
}
|
|
2148
|
+
function getJSXPortalInstance(inProps, portalInstanceObject, hostRef) {
|
|
2149
|
+
const {
|
|
2150
|
+
component: El,
|
|
2151
|
+
style: inStyle = {},
|
|
2152
|
+
ref: userRef,
|
|
2153
|
+
...props
|
|
2154
|
+
} = inProps;
|
|
1961
2155
|
const extraStyle = {
|
|
1962
2156
|
visibility: "visible",
|
|
1963
2157
|
position: "relative",
|
|
@@ -1979,7 +2173,8 @@ function getJSXPortalInstance(inProps, portalInstanceObject) {
|
|
|
1979
2173
|
...inheritedPortalStyle,
|
|
1980
2174
|
...extraStyle
|
|
1981
2175
|
};
|
|
1982
|
-
|
|
2176
|
+
const mergedRef = hostRef != null ? mergeRefs(hostRef, userRef) : userRef;
|
|
2177
|
+
return /* @__PURE__ */ jsx7(El, { ref: mergedRef, style, ...props });
|
|
1983
2178
|
}
|
|
1984
2179
|
function useSyncDocumentTitle(windowProxy, spatializedElement, name) {
|
|
1985
2180
|
useEffect12(() => {
|
|
@@ -1990,20 +2185,31 @@ function useSyncDocumentTitle(windowProxy, spatializedElement, name) {
|
|
|
1990
2185
|
}, [name]);
|
|
1991
2186
|
}
|
|
1992
2187
|
function SpatializedContent(props) {
|
|
1993
|
-
const { spatializedElement, ...restProps } = props;
|
|
2188
|
+
const { spatializedElement, onSpatialContentReady, ...restProps } = props;
|
|
1994
2189
|
const spatialized2DElement = spatializedElement;
|
|
1995
2190
|
const { windowProxy } = spatialized2DElement;
|
|
2191
|
+
const [hostEl, setHostEl] = useState7(null);
|
|
2192
|
+
const portalInstanceObject = useContext8(
|
|
2193
|
+
PortalInstanceContext
|
|
2194
|
+
);
|
|
2195
|
+
useSpatialContentReady({
|
|
2196
|
+
spatializedElement,
|
|
2197
|
+
portalInstanceObject,
|
|
2198
|
+
hostElement: hostEl,
|
|
2199
|
+
onSpatialContentReady
|
|
2200
|
+
});
|
|
1996
2201
|
useSyncHeadStyles(windowProxy, {
|
|
1997
2202
|
subtree: false
|
|
1998
2203
|
});
|
|
1999
2204
|
const name = restProps["data-name"] || "";
|
|
2000
2205
|
useSyncDocumentTitle(windowProxy, spatialized2DElement, name);
|
|
2001
|
-
const
|
|
2002
|
-
|
|
2003
|
-
);
|
|
2206
|
+
const setHostCallback = useCallback7((el) => {
|
|
2207
|
+
setHostEl(el);
|
|
2208
|
+
}, []);
|
|
2004
2209
|
const JSXPortalInstance = getJSXPortalInstance(
|
|
2005
2210
|
restProps,
|
|
2006
|
-
portalInstanceObject
|
|
2211
|
+
portalInstanceObject,
|
|
2212
|
+
setHostCallback
|
|
2007
2213
|
);
|
|
2008
2214
|
return createPortal2(JSXPortalInstance, windowProxy.document.body);
|
|
2009
2215
|
}
|
|
@@ -2061,11 +2267,11 @@ import {
|
|
|
2061
2267
|
Children,
|
|
2062
2268
|
forwardRef as forwardRef6,
|
|
2063
2269
|
isValidElement,
|
|
2064
|
-
useCallback as
|
|
2270
|
+
useCallback as useCallback8,
|
|
2065
2271
|
useContext as useContext9,
|
|
2066
2272
|
useEffect as useEffect13,
|
|
2067
2273
|
useMemo as useMemo3,
|
|
2068
|
-
useRef as
|
|
2274
|
+
useRef as useRef7
|
|
2069
2275
|
} from "react";
|
|
2070
2276
|
import { Fragment as Fragment2, jsx as jsx8 } from "react/jsx-runtime";
|
|
2071
2277
|
function getAbsoluteURL(url) {
|
|
@@ -2110,24 +2316,57 @@ function collectSources(children) {
|
|
|
2110
2316
|
return sources;
|
|
2111
2317
|
}
|
|
2112
2318
|
function SpatializedContent2(props) {
|
|
2113
|
-
const {
|
|
2319
|
+
const {
|
|
2320
|
+
src,
|
|
2321
|
+
poster,
|
|
2322
|
+
children,
|
|
2323
|
+
spatializedElement,
|
|
2324
|
+
onLoad,
|
|
2325
|
+
onError,
|
|
2326
|
+
autoPlay,
|
|
2327
|
+
loop,
|
|
2328
|
+
loading = "eager"
|
|
2329
|
+
} = props;
|
|
2114
2330
|
const portalInstanceObject = useContext9(PortalInstanceContext);
|
|
2331
|
+
const wasVisible = useRef7(false);
|
|
2115
2332
|
const modelURL = useMemo3(() => getAbsoluteURL(src), [src]);
|
|
2333
|
+
const posterURL = useMemo3(() => getAbsoluteURL(poster), [poster]);
|
|
2116
2334
|
const sources = useMemo3(() => collectSources(children), [children]);
|
|
2335
|
+
const sourcesKey = useMemo3(() => JSON.stringify(sources), [sources]);
|
|
2336
|
+
useEffect13(() => {
|
|
2337
|
+
wasVisible.current = false;
|
|
2338
|
+
const target = portalInstanceObject.dom;
|
|
2339
|
+
if (loading !== "lazy" || !target) {
|
|
2340
|
+
wasVisible.current = true;
|
|
2341
|
+
return;
|
|
2342
|
+
}
|
|
2343
|
+
const observer = new IntersectionObserver((entries) => {
|
|
2344
|
+
if (entries.some((entry) => entry.isIntersecting)) {
|
|
2345
|
+
wasVisible.current = true;
|
|
2346
|
+
observer.disconnect();
|
|
2347
|
+
spatializedElement.updateProperties({ loading: "eager" });
|
|
2348
|
+
}
|
|
2349
|
+
});
|
|
2350
|
+
observer.observe(target);
|
|
2351
|
+
return () => observer.disconnect();
|
|
2352
|
+
}, [modelURL, sourcesKey, portalInstanceObject]);
|
|
2117
2353
|
useEffect13(() => {
|
|
2354
|
+
if (loading !== "lazy") wasVisible.current = true;
|
|
2118
2355
|
spatializedElement.updateProperties({
|
|
2119
|
-
modelURL: modelURL ?? "",
|
|
2356
|
+
modelURL: modelURL ?? (spatializedElement.modelUrl ? "" : modelURL),
|
|
2120
2357
|
sources,
|
|
2121
2358
|
autoplay: autoPlay,
|
|
2122
|
-
loop
|
|
2359
|
+
loop,
|
|
2360
|
+
posterURL: posterURL ?? "",
|
|
2361
|
+
loading: loading === "lazy" && wasVisible.current ? "eager" : loading
|
|
2123
2362
|
});
|
|
2124
|
-
}, [modelURL,
|
|
2363
|
+
}, [modelURL, sourcesKey, autoPlay, loop, posterURL, loading]);
|
|
2125
2364
|
useEffect13(() => {
|
|
2126
2365
|
if (onLoad) {
|
|
2127
2366
|
spatializedElement.onLoadCallback = () => {
|
|
2128
2367
|
onLoad(
|
|
2129
2368
|
createLoadSuccessEvent(
|
|
2130
|
-
() => portalInstanceObject.dom
|
|
2369
|
+
() => portalInstanceObject.dom
|
|
2131
2370
|
)
|
|
2132
2371
|
);
|
|
2133
2372
|
};
|
|
@@ -2140,7 +2379,7 @@ function SpatializedContent2(props) {
|
|
|
2140
2379
|
spatializedElement.onLoadFailureCallback = () => {
|
|
2141
2380
|
onError(
|
|
2142
2381
|
createLoadFailureEvent(
|
|
2143
|
-
() => portalInstanceObject.dom
|
|
2382
|
+
() => portalInstanceObject.dom
|
|
2144
2383
|
)
|
|
2145
2384
|
);
|
|
2146
2385
|
};
|
|
@@ -2151,15 +2390,16 @@ function SpatializedContent2(props) {
|
|
|
2151
2390
|
return /* @__PURE__ */ jsx8(Fragment2, {});
|
|
2152
2391
|
}
|
|
2153
2392
|
function SpatializedStatic3DElementContainerBase(props, ref) {
|
|
2154
|
-
const promiseRef =
|
|
2155
|
-
const createSpatializedElement2 =
|
|
2393
|
+
const promiseRef = useRef7(null);
|
|
2394
|
+
const createSpatializedElement2 = useCallback8(() => {
|
|
2156
2395
|
promiseRef.current = getSession().createSpatializedStatic3DElement(
|
|
2157
2396
|
getAbsoluteURL(props.src),
|
|
2158
|
-
collectSources(props.children)
|
|
2397
|
+
collectSources(props.children),
|
|
2398
|
+
props.loading === "lazy" ? "lazy" : "eager"
|
|
2159
2399
|
);
|
|
2160
2400
|
return promiseRef.current;
|
|
2161
2401
|
}, []);
|
|
2162
|
-
const extraRefProps =
|
|
2402
|
+
const extraRefProps = useCallback8(
|
|
2163
2403
|
(domProxy) => {
|
|
2164
2404
|
let modelTransform = new DOMMatrixReadOnly();
|
|
2165
2405
|
return {
|
|
@@ -2206,6 +2446,16 @@ function SpatializedStatic3DElementContainerBase(props, ref) {
|
|
|
2206
2446
|
if (spatializedElement) {
|
|
2207
2447
|
spatializedElement.playbackRate = value;
|
|
2208
2448
|
}
|
|
2449
|
+
},
|
|
2450
|
+
get currentTime() {
|
|
2451
|
+
const spatializedElement = domProxy.__spatializedElement;
|
|
2452
|
+
return spatializedElement?.currentTime ?? 0;
|
|
2453
|
+
},
|
|
2454
|
+
set currentTime(value) {
|
|
2455
|
+
const spatializedElement = domProxy.__spatializedElement;
|
|
2456
|
+
if (spatializedElement) {
|
|
2457
|
+
spatializedElement.currentTime = value;
|
|
2458
|
+
}
|
|
2209
2459
|
}
|
|
2210
2460
|
};
|
|
2211
2461
|
},
|
|
@@ -2262,11 +2512,19 @@ function withSpatialized2DElementContainer(Component) {
|
|
|
2262
2512
|
|
|
2263
2513
|
// src/spatialized-container/index.ts
|
|
2264
2514
|
function initPolyfill() {
|
|
2265
|
-
hijackGetComputedStyle();
|
|
2266
2515
|
injectSpatialDefaultStyle();
|
|
2267
2516
|
initCSSParserDivContainer();
|
|
2268
2517
|
}
|
|
2269
2518
|
|
|
2519
|
+
// src/webSpatialRuntime.ts
|
|
2520
|
+
import { supports as supports2 } from "@webspatial/core-sdk";
|
|
2521
|
+
var WebSpatialRuntime = {
|
|
2522
|
+
supports: supports2
|
|
2523
|
+
};
|
|
2524
|
+
|
|
2525
|
+
// src/index.ts
|
|
2526
|
+
import { WebSpatialRuntimeError } from "@webspatial/core-sdk";
|
|
2527
|
+
|
|
2270
2528
|
// src/initScene.ts
|
|
2271
2529
|
function initScene(name, callback, options) {
|
|
2272
2530
|
return getSession()?.initScene(name, callback, options);
|
|
@@ -2276,9 +2534,9 @@ function initScene(name, callback, options) {
|
|
|
2276
2534
|
import { forwardRef as forwardRef9 } from "react";
|
|
2277
2535
|
|
|
2278
2536
|
// src/spatialized-container-monitor/useMonitorDomChange.tsx
|
|
2279
|
-
import { useRef as
|
|
2537
|
+
import { useRef as useRef8, useEffect as useEffect14, useMemo as useMemo4 } from "react";
|
|
2280
2538
|
function useMonitorDomChange(inRef) {
|
|
2281
|
-
const ref =
|
|
2539
|
+
const ref = useRef8(null);
|
|
2282
2540
|
useEffect14(() => {
|
|
2283
2541
|
const observer = new MutationObserver((mutationsList) => {
|
|
2284
2542
|
notifyDOMUpdate(mutationsList);
|
|
@@ -2440,37 +2698,87 @@ var AttachmentRegistry = class {
|
|
|
2440
2698
|
var AttachmentContext = createContext8(null);
|
|
2441
2699
|
|
|
2442
2700
|
// src/reality/hooks/useEntityTransform.tsx
|
|
2443
|
-
import { useEffect as useEffect16, useRef as
|
|
2701
|
+
import { useEffect as useEffect16, useRef as useRef9 } from "react";
|
|
2444
2702
|
|
|
2445
2703
|
// src/reality/utils/ResourceRegistry.ts
|
|
2446
2704
|
var ResourceRegistry = class {
|
|
2705
|
+
/** Every id maps to a promise — either the real resource from add(), or a placeholder until then. */
|
|
2447
2706
|
resources = /* @__PURE__ */ new Map();
|
|
2707
|
+
/** If get() ran first, we stash resolve/reject so add() can complete the waiting promise. */
|
|
2708
|
+
deferreds = /* @__PURE__ */ new Map();
|
|
2709
|
+
/** Subscribers are notified whenever an id gets a fresh resolved or failed resource attempt. */
|
|
2710
|
+
listeners = /* @__PURE__ */ new Map();
|
|
2448
2711
|
add(id, resource) {
|
|
2449
2712
|
this.resources.set(id, resource);
|
|
2713
|
+
const deferred = this.deferreds.get(id);
|
|
2714
|
+
if (deferred) {
|
|
2715
|
+
resource.then(deferred.resolve).catch(
|
|
2716
|
+
(err) => deferred.reject(err instanceof Error ? err : new Error(String(err)))
|
|
2717
|
+
);
|
|
2718
|
+
this.deferreds.delete(id);
|
|
2719
|
+
}
|
|
2720
|
+
resource.then(() => this.notify(id)).catch(() => this.notify(id));
|
|
2721
|
+
}
|
|
2722
|
+
subscribe(id, listener) {
|
|
2723
|
+
const listeners = this.listeners.get(id) ?? /* @__PURE__ */ new Set();
|
|
2724
|
+
listeners.add(listener);
|
|
2725
|
+
this.listeners.set(id, listeners);
|
|
2726
|
+
return () => {
|
|
2727
|
+
listeners.delete(listener);
|
|
2728
|
+
if (listeners.size === 0) {
|
|
2729
|
+
this.listeners.delete(id);
|
|
2730
|
+
}
|
|
2731
|
+
};
|
|
2732
|
+
}
|
|
2733
|
+
notify(id) {
|
|
2734
|
+
const listeners = this.listeners.get(id);
|
|
2735
|
+
if (!listeners) return;
|
|
2736
|
+
for (const listener of Array.from(listeners)) {
|
|
2737
|
+
listener();
|
|
2738
|
+
}
|
|
2739
|
+
}
|
|
2740
|
+
get(id) {
|
|
2741
|
+
const existing = this.resources.get(id);
|
|
2742
|
+
if (existing) {
|
|
2743
|
+
return existing;
|
|
2744
|
+
}
|
|
2745
|
+
const promise = new Promise((resolve, reject) => {
|
|
2746
|
+
this.deferreds.set(id, { resolve, reject });
|
|
2747
|
+
});
|
|
2748
|
+
this.resources.set(id, promise);
|
|
2749
|
+
return promise;
|
|
2450
2750
|
}
|
|
2451
2751
|
remove(id) {
|
|
2452
2752
|
this.resources.delete(id);
|
|
2753
|
+
this.deferreds.delete(id);
|
|
2754
|
+
this.notify(id);
|
|
2453
2755
|
}
|
|
2454
|
-
//
|
|
2455
|
-
// This does not cancel in-flight creation; it schedules destruction after resolution
|
|
2756
|
+
// Same as remove, but when the promise resolves, destroy the spatial object (best-effort).
|
|
2456
2757
|
removeAndDestroy(id) {
|
|
2457
2758
|
const p = this.resources.get(id);
|
|
2458
2759
|
if (p) {
|
|
2459
|
-
p.then((
|
|
2760
|
+
p.then((obj) => obj.destroy()).catch(() => {
|
|
2460
2761
|
});
|
|
2461
2762
|
}
|
|
2462
2763
|
this.resources.delete(id);
|
|
2463
|
-
|
|
2464
|
-
|
|
2465
|
-
return this.resources.get(id);
|
|
2764
|
+
this.deferreds.delete(id);
|
|
2765
|
+
this.notify(id);
|
|
2466
2766
|
}
|
|
2467
2767
|
destroy() {
|
|
2768
|
+
for (const [id, deferred] of this.deferreds) {
|
|
2769
|
+
deferred.reject(
|
|
2770
|
+
new Error(`ResourceRegistry destroyed \u2014 "${id}" never resolved`)
|
|
2771
|
+
);
|
|
2772
|
+
}
|
|
2773
|
+
this.deferreds.clear();
|
|
2774
|
+
const ids = Array.from(this.resources.keys());
|
|
2775
|
+
for (const id of ids) {
|
|
2776
|
+
this.notify(id);
|
|
2777
|
+
}
|
|
2778
|
+
this.listeners.clear();
|
|
2468
2779
|
const pending = Array.from(this.resources.values());
|
|
2469
2780
|
this.resources.clear();
|
|
2470
|
-
pending.
|
|
2471
|
-
(promise) => promise.then((spatialObj) => spatialObj.destroy()).catch(() => {
|
|
2472
|
-
})
|
|
2473
|
-
);
|
|
2781
|
+
void Promise.allSettled(pending.map((p) => p.then((obj) => obj.destroy())));
|
|
2474
2782
|
}
|
|
2475
2783
|
};
|
|
2476
2784
|
|
|
@@ -2502,15 +2810,14 @@ function shallowEqualArray(a, b) {
|
|
|
2502
2810
|
|
|
2503
2811
|
// src/reality/utils/AbortResourceManager.ts
|
|
2504
2812
|
var AbortResourceManager = class {
|
|
2813
|
+
resources = [];
|
|
2814
|
+
aborted = false;
|
|
2505
2815
|
constructor(signal) {
|
|
2506
|
-
this.signal = signal;
|
|
2507
2816
|
signal.addEventListener("abort", () => {
|
|
2508
2817
|
this.aborted = true;
|
|
2509
2818
|
void this.dispose();
|
|
2510
2819
|
});
|
|
2511
2820
|
}
|
|
2512
|
-
resources = [];
|
|
2513
|
-
aborted = false;
|
|
2514
2821
|
async addResource(factory) {
|
|
2515
2822
|
if (this.aborted) throw new DOMException("Aborted", "AbortError");
|
|
2516
2823
|
const resource = await factory();
|
|
@@ -2535,7 +2842,7 @@ var AbortResourceManager = class {
|
|
|
2535
2842
|
|
|
2536
2843
|
// src/reality/hooks/useEntityTransform.tsx
|
|
2537
2844
|
function useEntityTransform(entity, { position, rotation, scale }) {
|
|
2538
|
-
const last =
|
|
2845
|
+
const last = useRef9({});
|
|
2539
2846
|
useEffect16(() => {
|
|
2540
2847
|
if (!entity) return;
|
|
2541
2848
|
const shouldUpdate = !shallowEqualVec3(last.current.position, position) || !shallowEqualRotation(last.current.rotation, rotation) || !shallowEqualVec3(last.current.scale, scale);
|
|
@@ -2555,7 +2862,7 @@ function useEntityTransform(entity, { position, rotation, scale }) {
|
|
|
2555
2862
|
}
|
|
2556
2863
|
|
|
2557
2864
|
// src/reality/hooks/useEntityEvent.tsx
|
|
2558
|
-
import { useEffect as
|
|
2865
|
+
import { useEffect as useEffect17, useRef as useRef10 } from "react";
|
|
2559
2866
|
|
|
2560
2867
|
// src/reality/type.ts
|
|
2561
2868
|
var eventMap = {
|
|
@@ -2757,8 +3064,8 @@ function createEventProxy2(ev, instance) {
|
|
|
2757
3064
|
});
|
|
2758
3065
|
}
|
|
2759
3066
|
var useEntityEvent = ({ instance, ...handlers }) => {
|
|
2760
|
-
const eventsSetRef =
|
|
2761
|
-
|
|
3067
|
+
const eventsSetRef = useRef10(/* @__PURE__ */ new Set());
|
|
3068
|
+
useEffect17(() => {
|
|
2762
3069
|
const entity = instance.entity;
|
|
2763
3070
|
if (!entity) return;
|
|
2764
3071
|
Object.entries(eventMap).forEach(([reactKey, spatialEvent]) => {
|
|
@@ -2771,7 +3078,7 @@ var useEntityEvent = ({ instance, ...handlers }) => {
|
|
|
2771
3078
|
return () => {
|
|
2772
3079
|
};
|
|
2773
3080
|
}, [instance.entity, ...Object.values(handlers)]);
|
|
2774
|
-
|
|
3081
|
+
useEffect17(() => {
|
|
2775
3082
|
const entity = instance.entity;
|
|
2776
3083
|
if (!entity) return;
|
|
2777
3084
|
return () => {
|
|
@@ -2785,7 +3092,7 @@ var useEntityEvent = ({ instance, ...handlers }) => {
|
|
|
2785
3092
|
};
|
|
2786
3093
|
|
|
2787
3094
|
// src/reality/hooks/useRealityEvents.tsx
|
|
2788
|
-
import { useEffect as
|
|
3095
|
+
import { useEffect as useEffect18, useRef as useRef11 } from "react";
|
|
2789
3096
|
function createEventProxy3(ev, instance) {
|
|
2790
3097
|
return new Proxy(ev, {
|
|
2791
3098
|
get(target, prop) {
|
|
@@ -2899,8 +3206,8 @@ function createEventProxy3(ev, instance) {
|
|
|
2899
3206
|
});
|
|
2900
3207
|
}
|
|
2901
3208
|
var useRealityEvents = ({ instance, ...handlers }) => {
|
|
2902
|
-
const eventsSetRef =
|
|
2903
|
-
|
|
3209
|
+
const eventsSetRef = useRef11(/* @__PURE__ */ new Set());
|
|
3210
|
+
useEffect18(() => {
|
|
2904
3211
|
if (!instance) return;
|
|
2905
3212
|
Object.entries(eventMap).forEach(([reactKey, spatialEvent]) => {
|
|
2906
3213
|
const handlerFn = handlers[reactKey];
|
|
@@ -2921,10 +3228,10 @@ var useRealityEvents = ({ instance, ...handlers }) => {
|
|
|
2921
3228
|
};
|
|
2922
3229
|
|
|
2923
3230
|
// src/reality/hooks/useEntityId.tsx
|
|
2924
|
-
import { useEffect as
|
|
3231
|
+
import { useEffect as useEffect19 } from "react";
|
|
2925
3232
|
var useEntityId = ({ id, entity }) => {
|
|
2926
3233
|
const ctx = useRealityContext();
|
|
2927
|
-
|
|
3234
|
+
useEffect19(() => {
|
|
2928
3235
|
if (!id || !entity || !ctx) return;
|
|
2929
3236
|
ctx.resourceRegistry.add(id, Promise.resolve(entity));
|
|
2930
3237
|
return () => {
|
|
@@ -2935,7 +3242,7 @@ var useEntityId = ({ id, entity }) => {
|
|
|
2935
3242
|
};
|
|
2936
3243
|
|
|
2937
3244
|
// src/reality/hooks/useEntity.tsx
|
|
2938
|
-
import { useEffect as
|
|
3245
|
+
import { useEffect as useEffect20, useRef as useRef12 } from "react";
|
|
2939
3246
|
var useEntity = ({
|
|
2940
3247
|
ref,
|
|
2941
3248
|
id,
|
|
@@ -2956,9 +3263,9 @@ var useEntity = ({
|
|
|
2956
3263
|
}) => {
|
|
2957
3264
|
const ctx = useRealityContext();
|
|
2958
3265
|
const parent = useParentContext();
|
|
2959
|
-
const instanceRef =
|
|
3266
|
+
const instanceRef = useRef12(new EntityRef(null, ctx));
|
|
2960
3267
|
const forceUpdate = useForceUpdate2();
|
|
2961
|
-
|
|
3268
|
+
useEffect20(() => {
|
|
2962
3269
|
if (!ctx) return;
|
|
2963
3270
|
const controller = new AbortController();
|
|
2964
3271
|
const init = async () => {
|
|
@@ -3007,7 +3314,7 @@ var useEntity = ({
|
|
|
3007
3314
|
onSpatialMagnify,
|
|
3008
3315
|
onSpatialMagnifyEnd
|
|
3009
3316
|
});
|
|
3010
|
-
|
|
3317
|
+
useEffect20(() => {
|
|
3011
3318
|
const ent = instanceRef.current.entity;
|
|
3012
3319
|
if (!ent) return;
|
|
3013
3320
|
if (enableInput !== void 0) {
|
|
@@ -3018,10 +3325,10 @@ var useEntity = ({
|
|
|
3018
3325
|
};
|
|
3019
3326
|
|
|
3020
3327
|
// src/reality/hooks/useForceUpdate.tsx
|
|
3021
|
-
import { useCallback as
|
|
3328
|
+
import { useCallback as useCallback9, useState as useState9 } from "react";
|
|
3022
3329
|
var useForceUpdate2 = () => {
|
|
3023
|
-
const [, setTick] =
|
|
3024
|
-
return
|
|
3330
|
+
const [, setTick] = useState9(0);
|
|
3331
|
+
return useCallback9(() => setTick((tick) => tick + 1), []);
|
|
3025
3332
|
};
|
|
3026
3333
|
|
|
3027
3334
|
// src/reality/components/BaseEntity.tsx
|
|
@@ -3060,18 +3367,18 @@ var Entity = forwardRef11((props, ref) => {
|
|
|
3060
3367
|
import { forwardRef as forwardRef13 } from "react";
|
|
3061
3368
|
|
|
3062
3369
|
// src/reality/components/GeometryEntity.tsx
|
|
3063
|
-
import { forwardRef as forwardRef12, useEffect as
|
|
3370
|
+
import { forwardRef as forwardRef12, useEffect as useEffect21, useRef as useRef13 } from "react";
|
|
3064
3371
|
import { jsx as jsx14 } from "react/jsx-runtime";
|
|
3065
3372
|
var GeometryEntity = forwardRef12(
|
|
3066
3373
|
({ id, children, name, materials, geometryOptions, createGeometry, ...rest }, ref) => {
|
|
3067
3374
|
const ctx = useRealityContext();
|
|
3068
|
-
const entityRef =
|
|
3069
|
-
const componentRef =
|
|
3070
|
-
const mutableRef =
|
|
3375
|
+
const entityRef = useRef13(null);
|
|
3376
|
+
const componentRef = useRef13(null);
|
|
3377
|
+
const mutableRef = useRef13({
|
|
3071
3378
|
lastSnapshot: null,
|
|
3072
3379
|
rebuildGen: 0
|
|
3073
3380
|
});
|
|
3074
|
-
|
|
3381
|
+
useEffect21(() => {
|
|
3075
3382
|
const { lastSnapshot } = mutableRef.current;
|
|
3076
3383
|
if (!ctx || !entityRef.current || lastSnapshot === null) return;
|
|
3077
3384
|
const geometryChanged = !shallowEqualObject(
|
|
@@ -3193,22 +3500,50 @@ var BoxEntity = forwardRef13(
|
|
|
3193
3500
|
);
|
|
3194
3501
|
|
|
3195
3502
|
// src/reality/components/UnlitMaterial.tsx
|
|
3196
|
-
import { useEffect as
|
|
3503
|
+
import { useEffect as useEffect22, useRef as useRef14, useState as useState10 } from "react";
|
|
3197
3504
|
var UnlitMaterial = ({
|
|
3198
3505
|
children,
|
|
3199
3506
|
...options
|
|
3200
3507
|
}) => {
|
|
3201
3508
|
const ctx = useRealityContext();
|
|
3202
|
-
const materialRef =
|
|
3203
|
-
const isInitializedRef =
|
|
3204
|
-
|
|
3509
|
+
const materialRef = useRef14(void 0);
|
|
3510
|
+
const isInitializedRef = useRef14(false);
|
|
3511
|
+
const [textureRevision, setTextureRevision] = useState10(0);
|
|
3512
|
+
useEffect22(() => {
|
|
3513
|
+
if (!ctx || !options.textureId) return;
|
|
3514
|
+
return ctx.resourceRegistry.subscribe(options.textureId, () => {
|
|
3515
|
+
setTextureRevision((v) => v + 1);
|
|
3516
|
+
});
|
|
3517
|
+
}, [ctx, options.textureId]);
|
|
3518
|
+
useEffect22(() => {
|
|
3205
3519
|
if (!ctx) return;
|
|
3206
|
-
|
|
3520
|
+
let cancelled = false;
|
|
3521
|
+
const materialId = options.id;
|
|
3522
|
+
const { session, resourceRegistry } = ctx;
|
|
3207
3523
|
const init = async () => {
|
|
3208
|
-
const materialPromise = session.createUnlitMaterial(options);
|
|
3209
|
-
resourceRegistry.add(options.id, materialPromise);
|
|
3210
3524
|
try {
|
|
3525
|
+
let textureIdForNative = options.textureId;
|
|
3526
|
+
if (options.textureId) {
|
|
3527
|
+
const texturePromise = resourceRegistry.get(options.textureId);
|
|
3528
|
+
try {
|
|
3529
|
+
const textureResource = await texturePromise;
|
|
3530
|
+
if (cancelled) return;
|
|
3531
|
+
textureIdForNative = textureResource.id;
|
|
3532
|
+
} catch {
|
|
3533
|
+
textureIdForNative = "";
|
|
3534
|
+
}
|
|
3535
|
+
}
|
|
3536
|
+
if (cancelled) return;
|
|
3537
|
+
const commandOptions = {
|
|
3538
|
+
color: options.color,
|
|
3539
|
+
textureId: textureIdForNative,
|
|
3540
|
+
transparent: options.transparent,
|
|
3541
|
+
opacity: options.opacity
|
|
3542
|
+
};
|
|
3543
|
+
const materialPromise = session.createUnlitMaterial(commandOptions);
|
|
3544
|
+
resourceRegistry.add(materialId, materialPromise);
|
|
3211
3545
|
const mat = await materialPromise;
|
|
3546
|
+
if (cancelled) return;
|
|
3212
3547
|
materialRef.current = mat;
|
|
3213
3548
|
isInitializedRef.current = true;
|
|
3214
3549
|
} catch (error) {
|
|
@@ -3217,22 +3552,110 @@ var UnlitMaterial = ({
|
|
|
3217
3552
|
};
|
|
3218
3553
|
init();
|
|
3219
3554
|
return () => {
|
|
3220
|
-
|
|
3555
|
+
cancelled = true;
|
|
3556
|
+
resourceRegistry.removeAndDestroy(materialId);
|
|
3221
3557
|
materialRef.current = void 0;
|
|
3222
3558
|
isInitializedRef.current = false;
|
|
3223
3559
|
};
|
|
3224
|
-
}, [ctx]);
|
|
3560
|
+
}, [ctx, options.id]);
|
|
3561
|
+
useEffect22(() => {
|
|
3562
|
+
if (!ctx || !isInitializedRef.current || !materialRef.current) return;
|
|
3563
|
+
let cancelled = false;
|
|
3564
|
+
void (async () => {
|
|
3565
|
+
const updates = {};
|
|
3566
|
+
if (options.color !== void 0) updates.color = options.color;
|
|
3567
|
+
if (options.transparent !== void 0)
|
|
3568
|
+
updates.transparent = options.transparent;
|
|
3569
|
+
if (options.opacity !== void 0) updates.opacity = options.opacity;
|
|
3570
|
+
if (options.textureId !== void 0) {
|
|
3571
|
+
if (options.textureId === "") {
|
|
3572
|
+
updates.textureId = "";
|
|
3573
|
+
} else {
|
|
3574
|
+
const texturePromise = ctx.resourceRegistry.get(options.textureId);
|
|
3575
|
+
try {
|
|
3576
|
+
const textureResource = await texturePromise;
|
|
3577
|
+
if (cancelled) return;
|
|
3578
|
+
updates.textureId = textureResource.id;
|
|
3579
|
+
} catch {
|
|
3580
|
+
updates.textureId = "";
|
|
3581
|
+
}
|
|
3582
|
+
}
|
|
3583
|
+
}
|
|
3584
|
+
if (cancelled || Object.keys(updates).length === 0) return;
|
|
3585
|
+
const mat = materialRef.current;
|
|
3586
|
+
if (mat) {
|
|
3587
|
+
void mat.updateProperties(updates).catch(() => {
|
|
3588
|
+
});
|
|
3589
|
+
}
|
|
3590
|
+
})();
|
|
3591
|
+
return () => {
|
|
3592
|
+
cancelled = true;
|
|
3593
|
+
};
|
|
3594
|
+
}, [
|
|
3595
|
+
ctx,
|
|
3596
|
+
options.color,
|
|
3597
|
+
options.textureId,
|
|
3598
|
+
options.transparent,
|
|
3599
|
+
options.opacity,
|
|
3600
|
+
textureRevision
|
|
3601
|
+
]);
|
|
3602
|
+
return null;
|
|
3603
|
+
};
|
|
3604
|
+
|
|
3605
|
+
// src/reality/components/Texture.tsx
|
|
3606
|
+
import { useEffect as useEffect23, useRef as useRef15 } from "react";
|
|
3607
|
+
var Texture = ({
|
|
3608
|
+
children,
|
|
3609
|
+
id,
|
|
3610
|
+
url,
|
|
3611
|
+
onLoad,
|
|
3612
|
+
onError
|
|
3613
|
+
}) => {
|
|
3614
|
+
const ctx = useRealityContext();
|
|
3615
|
+
const textureRef = useRef15(null);
|
|
3616
|
+
const urlRevisionRef = useRef15(0);
|
|
3617
|
+
useEffect23(() => {
|
|
3618
|
+
if (!ctx) return;
|
|
3619
|
+
const { resourceRegistry } = ctx;
|
|
3620
|
+
const capturedId = id;
|
|
3621
|
+
return () => {
|
|
3622
|
+
textureRef.current = null;
|
|
3623
|
+
resourceRegistry.removeAndDestroy(capturedId);
|
|
3624
|
+
};
|
|
3625
|
+
}, [ctx, id]);
|
|
3225
3626
|
useEffect23(() => {
|
|
3226
|
-
if (!
|
|
3227
|
-
const
|
|
3228
|
-
|
|
3229
|
-
|
|
3230
|
-
|
|
3231
|
-
|
|
3232
|
-
|
|
3233
|
-
|
|
3234
|
-
|
|
3235
|
-
|
|
3627
|
+
if (!ctx) return;
|
|
3628
|
+
const { session, resourceRegistry } = ctx;
|
|
3629
|
+
const revision = ++urlRevisionRef.current;
|
|
3630
|
+
let cancelled = false;
|
|
3631
|
+
void (async () => {
|
|
3632
|
+
const resolvedUrl = getAbsoluteUrl(url);
|
|
3633
|
+
try {
|
|
3634
|
+
if (textureRef.current) {
|
|
3635
|
+
await textureRef.current.updateProperties({ url: resolvedUrl });
|
|
3636
|
+
if (cancelled || revision !== urlRevisionRef.current) return;
|
|
3637
|
+
resourceRegistry.notify(id);
|
|
3638
|
+
onLoad?.();
|
|
3639
|
+
return;
|
|
3640
|
+
}
|
|
3641
|
+
const texturePromise = session.createTexture({ url: resolvedUrl });
|
|
3642
|
+
resourceRegistry.add(id, texturePromise);
|
|
3643
|
+
const tex = await texturePromise;
|
|
3644
|
+
if (cancelled || revision !== urlRevisionRef.current) {
|
|
3645
|
+
tex.destroy();
|
|
3646
|
+
return;
|
|
3647
|
+
}
|
|
3648
|
+
textureRef.current = tex;
|
|
3649
|
+
onLoad?.();
|
|
3650
|
+
} catch (error) {
|
|
3651
|
+
if (cancelled || revision !== urlRevisionRef.current) return;
|
|
3652
|
+
onError?.(error);
|
|
3653
|
+
}
|
|
3654
|
+
})();
|
|
3655
|
+
return () => {
|
|
3656
|
+
cancelled = true;
|
|
3657
|
+
};
|
|
3658
|
+
}, [ctx, id, url]);
|
|
3236
3659
|
return null;
|
|
3237
3660
|
};
|
|
3238
3661
|
|
|
@@ -3331,23 +3754,17 @@ var SceneGraph = ({ children }) => {
|
|
|
3331
3754
|
};
|
|
3332
3755
|
|
|
3333
3756
|
// src/reality/components/ModelAsset.tsx
|
|
3334
|
-
import { useEffect as useEffect24, useRef as
|
|
3335
|
-
var resolveAssetUrl = (url) => {
|
|
3336
|
-
if (url.startsWith("http://") || url.startsWith("https://")) {
|
|
3337
|
-
return url;
|
|
3338
|
-
}
|
|
3339
|
-
return new URL(url, window.location.href).href;
|
|
3340
|
-
};
|
|
3757
|
+
import { useEffect as useEffect24, useRef as useRef16 } from "react";
|
|
3341
3758
|
var ModelAsset = ({ children, ...options }) => {
|
|
3342
3759
|
const ctx = useRealityContext();
|
|
3343
|
-
const materialRef =
|
|
3760
|
+
const materialRef = useRef16(void 0);
|
|
3344
3761
|
useEffect24(() => {
|
|
3345
3762
|
const controller = new AbortController();
|
|
3346
3763
|
if (!ctx) return;
|
|
3347
|
-
const { session,
|
|
3764
|
+
const { session, resourceRegistry } = ctx;
|
|
3348
3765
|
const init = async () => {
|
|
3349
3766
|
try {
|
|
3350
|
-
const resolvedUrl =
|
|
3767
|
+
const resolvedUrl = getAbsoluteUrl(options.src);
|
|
3351
3768
|
const modelAssetPromise = session.createModelAsset({ url: resolvedUrl });
|
|
3352
3769
|
resourceRegistry.add(options.id, modelAssetPromise);
|
|
3353
3770
|
const mat = await modelAssetPromise;
|
|
@@ -3371,13 +3788,13 @@ var ModelAsset = ({ children, ...options }) => {
|
|
|
3371
3788
|
};
|
|
3372
3789
|
|
|
3373
3790
|
// src/reality/components/ModelEntity.tsx
|
|
3374
|
-
import { forwardRef as forwardRef18, useEffect as useEffect25, useRef as
|
|
3791
|
+
import { forwardRef as forwardRef18, useEffect as useEffect25, useRef as useRef17 } from "react";
|
|
3375
3792
|
import { jsx as jsx21 } from "react/jsx-runtime";
|
|
3376
3793
|
var ModelEntity = forwardRef18(
|
|
3377
3794
|
({ id, model, children, name, materials, ...rest }, ref) => {
|
|
3378
3795
|
const ctx = useRealityContext();
|
|
3379
|
-
const entityRef =
|
|
3380
|
-
const lastMaterialsRef =
|
|
3796
|
+
const entityRef = useRef17(null);
|
|
3797
|
+
const lastMaterialsRef = useRef17(void 0);
|
|
3381
3798
|
useEffect25(() => {
|
|
3382
3799
|
if (!ctx || !entityRef.current) return;
|
|
3383
3800
|
const next = materials ?? [];
|
|
@@ -3386,9 +3803,7 @@ var ModelEntity = forwardRef18(
|
|
|
3386
3803
|
lastMaterialsRef.current = next;
|
|
3387
3804
|
const apply = async () => {
|
|
3388
3805
|
try {
|
|
3389
|
-
const materialList = (await Promise.all(
|
|
3390
|
-
next.map((mid) => ctx.resourceRegistry.get(mid))
|
|
3391
|
-
)).filter(Boolean);
|
|
3806
|
+
const materialList = (await Promise.all(next.map((mid) => ctx.resourceRegistry.get(mid)))).filter(Boolean);
|
|
3392
3807
|
if (entityRef.current) {
|
|
3393
3808
|
await entityRef.current.setMaterials(materialList);
|
|
3394
3809
|
}
|
|
@@ -3421,9 +3836,7 @@ var ModelEntity = forwardRef18(
|
|
|
3421
3836
|
entityRef.current = ent;
|
|
3422
3837
|
if (materials && materials.length > 0) {
|
|
3423
3838
|
const materialList = (await Promise.all(
|
|
3424
|
-
materials.map(
|
|
3425
|
-
(mid) => ctx2.resourceRegistry.get(mid)
|
|
3426
|
-
)
|
|
3839
|
+
materials.map((mid) => ctx2.resourceRegistry.get(mid))
|
|
3427
3840
|
)).filter(Boolean);
|
|
3428
3841
|
if (materialList.length > 0 && !signal.aborted) {
|
|
3429
3842
|
await ent.setMaterials(materialList);
|
|
@@ -3444,10 +3857,10 @@ var ModelEntity = forwardRef18(
|
|
|
3444
3857
|
// src/reality/components/Reality.tsx
|
|
3445
3858
|
import {
|
|
3446
3859
|
forwardRef as forwardRef19,
|
|
3447
|
-
useCallback as
|
|
3860
|
+
useCallback as useCallback10,
|
|
3448
3861
|
useEffect as useEffect26,
|
|
3449
|
-
useRef as
|
|
3450
|
-
useState as
|
|
3862
|
+
useRef as useRef18,
|
|
3863
|
+
useState as useState11
|
|
3451
3864
|
} from "react";
|
|
3452
3865
|
import { Fragment as Fragment3, jsx as jsx22, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
3453
3866
|
var Reality = forwardRef19(
|
|
@@ -3470,10 +3883,10 @@ var Reality = forwardRef19(
|
|
|
3470
3883
|
onSpatialMagnifyEnd,
|
|
3471
3884
|
...props
|
|
3472
3885
|
} = inProps;
|
|
3473
|
-
const ctxRef =
|
|
3474
|
-
const creationId =
|
|
3475
|
-
const [isReady, setIsReady] =
|
|
3476
|
-
const cleanupReality =
|
|
3886
|
+
const ctxRef = useRef18(null);
|
|
3887
|
+
const creationId = useRef18(0);
|
|
3888
|
+
const [isReady, setIsReady] = useState11(false);
|
|
3889
|
+
const cleanupReality = useCallback10(() => {
|
|
3477
3890
|
ctxRef.current?.attachmentRegistry.destroy();
|
|
3478
3891
|
ctxRef.current?.resourceRegistry.destroy();
|
|
3479
3892
|
ctxRef.current?.reality.destroy();
|
|
@@ -3486,7 +3899,7 @@ var Reality = forwardRef19(
|
|
|
3486
3899
|
cleanupReality();
|
|
3487
3900
|
};
|
|
3488
3901
|
}, [cleanupReality]);
|
|
3489
|
-
const createReality =
|
|
3902
|
+
const createReality = useCallback10(async () => {
|
|
3490
3903
|
const id = ++creationId.current;
|
|
3491
3904
|
const resourceRegistry = new ResourceRegistry();
|
|
3492
3905
|
const attachmentRegistry = new AttachmentRegistry();
|
|
@@ -3529,7 +3942,7 @@ var Reality = forwardRef19(
|
|
|
3529
3942
|
return null;
|
|
3530
3943
|
}
|
|
3531
3944
|
}, [cleanupReality]);
|
|
3532
|
-
const content =
|
|
3945
|
+
const content = useCallback10(() => /* @__PURE__ */ jsx22(Fragment3, {}), []);
|
|
3533
3946
|
useRealityEvents({
|
|
3534
3947
|
instance: ctxRef.current?.reality ?? null,
|
|
3535
3948
|
onSpatialTap,
|
|
@@ -3558,7 +3971,7 @@ var Reality = forwardRef19(
|
|
|
3558
3971
|
);
|
|
3559
3972
|
|
|
3560
3973
|
// src/reality/components/AttachmentAsset.tsx
|
|
3561
|
-
import { useEffect as useEffect27, useState as
|
|
3974
|
+
import { useEffect as useEffect27, useState as useState12 } from "react";
|
|
3562
3975
|
import { createPortal as createPortal3 } from "react-dom";
|
|
3563
3976
|
import { jsx as jsx23 } from "react/jsx-runtime";
|
|
3564
3977
|
var AttachmentAsset = ({
|
|
@@ -3566,7 +3979,7 @@ var AttachmentAsset = ({
|
|
|
3566
3979
|
children
|
|
3567
3980
|
}) => {
|
|
3568
3981
|
const ctx = useRealityContext();
|
|
3569
|
-
const [containers, setContainers] =
|
|
3982
|
+
const [containers, setContainers] = useState12([]);
|
|
3570
3983
|
useEffect27(() => {
|
|
3571
3984
|
if (!ctx) return;
|
|
3572
3985
|
return ctx.attachmentRegistry.onContainersChange(name, setContainers);
|
|
@@ -3578,7 +3991,7 @@ var AttachmentAsset = ({
|
|
|
3578
3991
|
};
|
|
3579
3992
|
|
|
3580
3993
|
// src/reality/components/AttachmentEntity.tsx
|
|
3581
|
-
import { useEffect as useEffect28, useRef as
|
|
3994
|
+
import { useEffect as useEffect28, useRef as useRef19, useState as useState13 } from "react";
|
|
3582
3995
|
var instanceCounter = 0;
|
|
3583
3996
|
var AttachmentEntity = ({
|
|
3584
3997
|
attachment: attachmentName,
|
|
@@ -3587,11 +4000,11 @@ var AttachmentEntity = ({
|
|
|
3587
4000
|
}) => {
|
|
3588
4001
|
const ctx = useRealityContext();
|
|
3589
4002
|
const parent = useParentContext();
|
|
3590
|
-
const attachmentRef =
|
|
3591
|
-
const parentIdRef =
|
|
3592
|
-
const instanceIdRef =
|
|
3593
|
-
const attachmentNameRef =
|
|
3594
|
-
const [childWindow, setChildWindow] =
|
|
4003
|
+
const attachmentRef = useRef19(null);
|
|
4004
|
+
const parentIdRef = useRef19(null);
|
|
4005
|
+
const instanceIdRef = useRef19(`att_${++instanceCounter}`);
|
|
4006
|
+
const attachmentNameRef = useRef19(attachmentName);
|
|
4007
|
+
const [childWindow, setChildWindow] = useState13(null);
|
|
3595
4008
|
useEffect28(() => {
|
|
3596
4009
|
if (!ctx || !parent) return;
|
|
3597
4010
|
if (attachmentRef.current) return;
|
|
@@ -3670,7 +4083,7 @@ var AttachmentEntity = ({
|
|
|
3670
4083
|
attachmentNameRef.current = attachmentName;
|
|
3671
4084
|
}
|
|
3672
4085
|
}, [ctx, attachmentName]);
|
|
3673
|
-
useSyncHeadStyles(childWindow
|
|
4086
|
+
useSyncHeadStyles(childWindow);
|
|
3674
4087
|
useEffect28(() => {
|
|
3675
4088
|
if (!attachmentRef.current) return;
|
|
3676
4089
|
attachmentRef.current.update({ position, size });
|
|
@@ -3734,7 +4147,7 @@ var styleFlag = "enableXr";
|
|
|
3734
4147
|
var classFlag = "__enableXr__";
|
|
3735
4148
|
var xrMonitorFlag = "enable-xr-monitor";
|
|
3736
4149
|
function replaceToSpatialPrimitiveType(type, props) {
|
|
3737
|
-
if (type === Model) {
|
|
4150
|
+
if (type === Model || type === Reality) {
|
|
3738
4151
|
return type;
|
|
3739
4152
|
}
|
|
3740
4153
|
const propsObject = props;
|
|
@@ -3777,7 +4190,7 @@ function resolveSpatialObjectId(target) {
|
|
|
3777
4190
|
if (maybeEntity && typeof maybeEntity === "object" && "entity" in maybeEntity) {
|
|
3778
4191
|
return maybeEntity.entity?.id ?? null;
|
|
3779
4192
|
}
|
|
3780
|
-
const dom = target
|
|
4193
|
+
const dom = target;
|
|
3781
4194
|
if (dom && typeof dom === "object") {
|
|
3782
4195
|
const spatializedElement = dom.__spatializedElement ?? dom.__innerSpatializedElement?.();
|
|
3783
4196
|
if (spatializedElement && spatializedElement.id) {
|
|
@@ -3807,7 +4220,7 @@ async function convertCoordinate(position, { from, to }) {
|
|
|
3807
4220
|
}
|
|
3808
4221
|
|
|
3809
4222
|
// src/index.ts
|
|
3810
|
-
var version = "1.
|
|
4223
|
+
var version = "1.7.0";
|
|
3811
4224
|
if (typeof window !== "undefined") {
|
|
3812
4225
|
initPolyfill();
|
|
3813
4226
|
}
|
|
@@ -3836,12 +4249,16 @@ export {
|
|
|
3836
4249
|
SpatializedStatic3DElementContainer,
|
|
3837
4250
|
SphereEntity as Sphere,
|
|
3838
4251
|
SphereEntity,
|
|
4252
|
+
Texture,
|
|
3839
4253
|
UnlitMaterial,
|
|
4254
|
+
WebSpatialRuntime,
|
|
4255
|
+
WebSpatialRuntimeError,
|
|
3840
4256
|
SceneGraph as World,
|
|
3841
4257
|
convertCoordinate,
|
|
3842
4258
|
createElement,
|
|
3843
4259
|
enableDebugTool,
|
|
3844
4260
|
eventMap,
|
|
4261
|
+
getAbsoluteUrl,
|
|
3845
4262
|
initPolyfill,
|
|
3846
4263
|
initScene,
|
|
3847
4264
|
useMetrics,
|