@neurodyn/react-model-viewer 0.1.1 → 0.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +40 -2
- package/dist/index.js +206 -69
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -3,15 +3,50 @@ import { JSX } from 'react/jsx-runtime';
|
|
|
3
3
|
import type { default as React_2 } from 'react';
|
|
4
4
|
import * as React_3 from 'react';
|
|
5
5
|
|
|
6
|
+
/**
|
|
7
|
+
* How long a tap may wait on a host's own AR before the native launch goes
|
|
8
|
+
* ahead instead.
|
|
9
|
+
*
|
|
10
|
+
* Chrome lets a page navigate on behalf of a tap for about five seconds, and
|
|
11
|
+
* the Scene Viewer intent is such a navigation: sent any later, the browser
|
|
12
|
+
* drops it as one nobody asked for. A host that loads its AR on the tap races
|
|
13
|
+
* the load against this, so a slow connection gets Scene Viewer for this tap
|
|
14
|
+
* and the host's AR for the next, the download having gone on meanwhile.
|
|
15
|
+
*/
|
|
16
|
+
export declare const AR_TAP_WINDOW_MS = 3000;
|
|
17
|
+
|
|
6
18
|
/** What the host needs to open its own AR experience for the shown model. */
|
|
7
19
|
export declare interface ArLaunchTarget {
|
|
20
|
+
/**
|
|
21
|
+
* The API the viewer's widget session was issued by, when the host set one.
|
|
22
|
+
* A host continuing that session has to refresh it there.
|
|
23
|
+
*/
|
|
24
|
+
apiBaseUrl?: string;
|
|
25
|
+
/**
|
|
26
|
+
* The public key the viewer runs on — including one a QR handoff code
|
|
27
|
+
* resolved, which the host page never saw.
|
|
28
|
+
*/
|
|
29
|
+
apiKey?: string;
|
|
8
30
|
/** Material collection currently shown, which may differ from the entry url. */
|
|
9
31
|
hid?: string;
|
|
32
|
+
/** The viewer's UI language, so the host's AR speaks the same one. */
|
|
33
|
+
lang?: 'en' | 'ru';
|
|
34
|
+
/** The object's display name, for the host AR's accessible label. */
|
|
35
|
+
name?: string;
|
|
10
36
|
tinuuid: string;
|
|
37
|
+
/**
|
|
38
|
+
* A live token of the viewer's widget session, so the host's AR continues
|
|
39
|
+
* that session instead of activating a second one.
|
|
40
|
+
*/
|
|
41
|
+
widgetSessionToken?: string;
|
|
11
42
|
}
|
|
12
43
|
|
|
13
44
|
declare type DialogProps = React_3.ComponentProps<typeof DialogPrimitive.Root>
|
|
14
45
|
|
|
46
|
+
export declare function isIOSDevice(): boolean;
|
|
47
|
+
|
|
48
|
+
export declare function isMobileArDevice(): boolean;
|
|
49
|
+
|
|
15
50
|
/**
|
|
16
51
|
* Lets the host open its own AR experience instead of the native one.
|
|
17
52
|
*
|
|
@@ -27,9 +62,9 @@ export declare type ModelViewerArExperience = 'advanced' | 'standard';
|
|
|
27
62
|
|
|
28
63
|
declare type ModelViewerBackground = 'default' | 'transparent';
|
|
29
64
|
|
|
30
|
-
export declare function ModelViewerDialog({ tinuuid, apiKey, apiBaseUrl, appClipBundleId, initialWidgetSessionToken, handoffUrl, hid, lang, mode, sizeType, dimensionAxes, cameraOrbit, minCameraOrbit, maxCameraOrbit, ...props }: ModelViewerDialogProps): JSX.Element;
|
|
65
|
+
export declare function ModelViewerDialog({ tinuuid, apiKey, apiBaseUrl, appClipBundleId, initialWidgetSessionToken, handoffUrl, hid, lang, launchAr, mode, sizeType, dimensionAxes, cameraOrbit, minCameraOrbit, maxCameraOrbit, ...props }: ModelViewerDialogProps): JSX.Element;
|
|
31
66
|
|
|
32
|
-
export declare interface ModelViewerDialogProps extends Pick<ModelViewerRootProps, 'apiBaseUrl' | 'apiKey' | 'appClipBundleId' | 'cameraOrbit' | 'dimensionAxes' | 'handoffUrl' | 'hid' | 'initialWidgetSessionToken' | 'lang' | 'maxCameraOrbit' | 'minCameraOrbit' | 'mode' | 'sizeType' | 'tinuuid'>, Omit<DialogProps, 'children' | 'open' | 'defaultOpen' | 'onOpenChange' | 'modal'> {
|
|
67
|
+
export declare interface ModelViewerDialogProps extends Pick<ModelViewerRootProps, 'apiBaseUrl' | 'apiKey' | 'appClipBundleId' | 'cameraOrbit' | 'dimensionAxes' | 'handoffUrl' | 'hid' | 'initialWidgetSessionToken' | 'lang' | 'launchAr' | 'maxCameraOrbit' | 'minCameraOrbit' | 'mode' | 'sizeType' | 'tinuuid'>, Omit<DialogProps, 'children' | 'open' | 'defaultOpen' | 'onOpenChange' | 'modal'> {
|
|
33
68
|
/** The controlled open state of the dialog. Use with `onOpenChange`. */
|
|
34
69
|
open?: DialogProps['open'];
|
|
35
70
|
/** The initial open state when the dialog is uncontrolled. */
|
|
@@ -99,4 +134,7 @@ export declare type SizeAxis = 'x' | 'y' | 'z';
|
|
|
99
134
|
|
|
100
135
|
export declare type SizeType = 'cm' | 'inch';
|
|
101
136
|
|
|
137
|
+
/** The value, or `null` once the tap's window has passed; a rejection still rejects. */
|
|
138
|
+
export declare function withinTapWindow<T>(promise: Promise<T>, windowMs?: number): Promise<T | null>;
|
|
139
|
+
|
|
102
140
|
export { }
|
package/dist/index.js
CHANGED
|
@@ -494,6 +494,18 @@ var __webpack_modules__ = {
|
|
|
494
494
|
inset-block: calc(var(--spacing) * 0);
|
|
495
495
|
}
|
|
496
496
|
|
|
497
|
+
.start-2 {
|
|
498
|
+
inset-inline-start: calc(var(--spacing) * 2);
|
|
499
|
+
}
|
|
500
|
+
|
|
501
|
+
.end-2 {
|
|
502
|
+
inset-inline-end: calc(var(--spacing) * 2);
|
|
503
|
+
}
|
|
504
|
+
|
|
505
|
+
.end-4 {
|
|
506
|
+
inset-inline-end: calc(var(--spacing) * 4);
|
|
507
|
+
}
|
|
508
|
+
|
|
497
509
|
.top-0 {
|
|
498
510
|
top: calc(var(--spacing) * 0);
|
|
499
511
|
}
|
|
@@ -542,10 +554,6 @@ var __webpack_modules__ = {
|
|
|
542
554
|
right: calc(var(--spacing) * 3);
|
|
543
555
|
}
|
|
544
556
|
|
|
545
|
-
.right-4 {
|
|
546
|
-
right: calc(var(--spacing) * 4);
|
|
547
|
-
}
|
|
548
|
-
|
|
549
557
|
.right-6 {
|
|
550
558
|
right: calc(var(--spacing) * 6);
|
|
551
559
|
}
|
|
@@ -558,15 +566,7 @@ var __webpack_modules__ = {
|
|
|
558
566
|
left: calc(var(--spacing) * 0);
|
|
559
567
|
}
|
|
560
568
|
|
|
561
|
-
.left-1\\/2 {
|
|
562
|
-
left: 50%;
|
|
563
|
-
}
|
|
564
|
-
|
|
565
|
-
.left-2 {
|
|
566
|
-
left: calc(var(--spacing) * 2);
|
|
567
|
-
}
|
|
568
|
-
|
|
569
|
-
.left-\\[50\\%\\] {
|
|
569
|
+
.left-1\\/2, .left-\\[50\\%\\] {
|
|
570
570
|
left: 50%;
|
|
571
571
|
}
|
|
572
572
|
|
|
@@ -680,6 +680,14 @@ var __webpack_modules__ = {
|
|
|
680
680
|
margin-inline-start: -1px;
|
|
681
681
|
}
|
|
682
682
|
|
|
683
|
+
.ms-4 {
|
|
684
|
+
margin-inline-start: calc(var(--spacing) * 4);
|
|
685
|
+
}
|
|
686
|
+
|
|
687
|
+
.ms-auto {
|
|
688
|
+
margin-inline-start: auto;
|
|
689
|
+
}
|
|
690
|
+
|
|
683
691
|
.mt-1\\.5 {
|
|
684
692
|
margin-top: calc(var(--spacing) * 1.5);
|
|
685
693
|
}
|
|
@@ -708,14 +716,6 @@ var __webpack_modules__ = {
|
|
|
708
716
|
margin-left: calc(var(--spacing) * 1);
|
|
709
717
|
}
|
|
710
718
|
|
|
711
|
-
.ml-4 {
|
|
712
|
-
margin-left: calc(var(--spacing) * 4);
|
|
713
|
-
}
|
|
714
|
-
|
|
715
|
-
.ml-auto {
|
|
716
|
-
margin-left: auto;
|
|
717
|
-
}
|
|
718
|
-
|
|
719
719
|
.box-border {
|
|
720
720
|
box-sizing: border-box;
|
|
721
721
|
}
|
|
@@ -1854,6 +1854,26 @@ var __webpack_modules__ = {
|
|
|
1854
1854
|
padding-block: calc(var(--spacing) * 14);
|
|
1855
1855
|
}
|
|
1856
1856
|
|
|
1857
|
+
.ps-2 {
|
|
1858
|
+
padding-inline-start: calc(var(--spacing) * 2);
|
|
1859
|
+
}
|
|
1860
|
+
|
|
1861
|
+
.ps-3 {
|
|
1862
|
+
padding-inline-start: calc(var(--spacing) * 3);
|
|
1863
|
+
}
|
|
1864
|
+
|
|
1865
|
+
.ps-8 {
|
|
1866
|
+
padding-inline-start: calc(var(--spacing) * 8);
|
|
1867
|
+
}
|
|
1868
|
+
|
|
1869
|
+
.pe-2 {
|
|
1870
|
+
padding-inline-end: calc(var(--spacing) * 2);
|
|
1871
|
+
}
|
|
1872
|
+
|
|
1873
|
+
.pe-8 {
|
|
1874
|
+
padding-inline-end: calc(var(--spacing) * 8);
|
|
1875
|
+
}
|
|
1876
|
+
|
|
1857
1877
|
.pt-1\\.5 {
|
|
1858
1878
|
padding-top: calc(var(--spacing) * 1.5);
|
|
1859
1879
|
}
|
|
@@ -1870,10 +1890,6 @@ var __webpack_modules__ = {
|
|
|
1870
1890
|
padding-right: calc(var(--spacing) * 1);
|
|
1871
1891
|
}
|
|
1872
1892
|
|
|
1873
|
-
.pr-2 {
|
|
1874
|
-
padding-right: calc(var(--spacing) * 2);
|
|
1875
|
-
}
|
|
1876
|
-
|
|
1877
1893
|
.pr-2\\.5 {
|
|
1878
1894
|
padding-right: calc(var(--spacing) * 2.5);
|
|
1879
1895
|
}
|
|
@@ -1886,26 +1902,14 @@ var __webpack_modules__ = {
|
|
|
1886
1902
|
padding-right: calc(var(--spacing) * 5);
|
|
1887
1903
|
}
|
|
1888
1904
|
|
|
1889
|
-
.pr-8 {
|
|
1890
|
-
padding-right: calc(var(--spacing) * 8);
|
|
1891
|
-
}
|
|
1892
|
-
|
|
1893
1905
|
.pb-\\[0\\.3125rem\\] {
|
|
1894
1906
|
padding-bottom: 5px;
|
|
1895
1907
|
}
|
|
1896
1908
|
|
|
1897
|
-
.pl-2 {
|
|
1898
|
-
padding-left: calc(var(--spacing) * 2);
|
|
1899
|
-
}
|
|
1900
|
-
|
|
1901
1909
|
.pl-3 {
|
|
1902
1910
|
padding-left: calc(var(--spacing) * 3);
|
|
1903
1911
|
}
|
|
1904
1912
|
|
|
1905
|
-
.pl-8 {
|
|
1906
|
-
padding-left: calc(var(--spacing) * 8);
|
|
1907
|
-
}
|
|
1908
|
-
|
|
1909
1913
|
.text-center {
|
|
1910
1914
|
text-align: center;
|
|
1911
1915
|
}
|
|
@@ -1914,6 +1918,10 @@ var __webpack_modules__ = {
|
|
|
1914
1918
|
text-align: left;
|
|
1915
1919
|
}
|
|
1916
1920
|
|
|
1921
|
+
.text-start {
|
|
1922
|
+
text-align: start;
|
|
1923
|
+
}
|
|
1924
|
+
|
|
1917
1925
|
.align-middle {
|
|
1918
1926
|
vertical-align: middle;
|
|
1919
1927
|
}
|
|
@@ -4155,6 +4163,10 @@ var __webpack_modules__ = {
|
|
|
4155
4163
|
}
|
|
4156
4164
|
}
|
|
4157
4165
|
|
|
4166
|
+
.rtl\\:rotate-180:where(:dir(rtl), [dir="rtl"], [dir="rtl"] *) {
|
|
4167
|
+
rotate: 180deg;
|
|
4168
|
+
}
|
|
4169
|
+
|
|
4158
4170
|
.dark\\:bg-input\\/30:is(.dark *) {
|
|
4159
4171
|
background-color: var(--input);
|
|
4160
4172
|
}
|
|
@@ -4734,8 +4746,17 @@ var __webpack_modules__ = {
|
|
|
4734
4746
|
font-display: swap;
|
|
4735
4747
|
}
|
|
4736
4748
|
|
|
4749
|
+
@font-face {
|
|
4750
|
+
font-family: __tw4_shd_noto_arabic_7x4q2;
|
|
4751
|
+
src: url("https://fonts.gstatic.com/s/notosansarabic/v33/nwpCtLGrOAZMl5nJ_wfgRg3DrWFZWsnVBJ_sS6tlqHHFlj4wv4r4xA.woff2") format("woff2");
|
|
4752
|
+
font-weight: 100 900;
|
|
4753
|
+
font-style: normal;
|
|
4754
|
+
font-display: swap;
|
|
4755
|
+
unicode-range: U+6??, U+750-77F, U+870-891, U+897-8E1, U+8E3-8FF, U+200C-200E, U+2010-2011, U+204F, U+2E41, U+FB50-FDFF, U+FE70-FE74, U+FE76-FEFC;
|
|
4756
|
+
}
|
|
4757
|
+
|
|
4737
4758
|
:root {
|
|
4738
|
-
--v-font-family: "__tw4_shd_inter_7x4q2", sans-serif;
|
|
4759
|
+
--v-font-family: "__tw4_shd_inter_7x4q2", "__tw4_shd_noto_arabic_7x4q2", sans-serif;
|
|
4739
4760
|
font-family: var(--v-font-family);
|
|
4740
4761
|
font-feature-settings: "liga" 1, "calt" 1;
|
|
4741
4762
|
-webkit-font-smoothing: antialiased;
|
|
@@ -5374,6 +5395,15 @@ var __webpack_modules__ = {
|
|
|
5374
5395
|
font-style: normal;
|
|
5375
5396
|
font-display: swap;
|
|
5376
5397
|
}
|
|
5398
|
+
|
|
5399
|
+
@font-face {
|
|
5400
|
+
font-family: __tw4_shd_noto_arabic_7x4q2;
|
|
5401
|
+
src: url("https://fonts.gstatic.com/s/notosansarabic/v33/nwpCtLGrOAZMl5nJ_wfgRg3DrWFZWsnVBJ_sS6tlqHHFlj4wv4r4xA.woff2") format("woff2");
|
|
5402
|
+
font-weight: 100 900;
|
|
5403
|
+
font-style: normal;
|
|
5404
|
+
font-display: swap;
|
|
5405
|
+
unicode-range: U+6??, U+750-77F, U+870-891, U+897-8E1, U+8E3-8FF, U+200C-200E, U+2010-2011, U+204F, U+2E41, U+FB50-FDFF, U+FE70-FE74, U+FE76-FEFC;
|
|
5406
|
+
}
|
|
5377
5407
|
`,
|
|
5378
5408
|
""
|
|
5379
5409
|
]);
|
|
@@ -5831,7 +5861,7 @@ function DialogContent({ className, children, contentInsideOverlay = false, show
|
|
|
5831
5861
|
children,
|
|
5832
5862
|
showCloseButton && /*#__PURE__*/ jsxs(react_dialog_Close, {
|
|
5833
5863
|
"data-slot": "dialog-close",
|
|
5834
|
-
className: "focus-visible:ring-ring/30 absolute top-4
|
|
5864
|
+
className: "focus-visible:ring-ring/30 absolute top-4 end-4 inline-flex size-6 cursor-pointer items-center justify-center rounded-full text-icons-light transition-colors hover:text-icons-normal focus-visible:text-icons-dark focus-visible:ring-2 focus-visible:outline-hidden disabled:pointer-events-none [&_svg]:pointer-events-none [&_svg]:shrink-0",
|
|
5835
5865
|
children: [
|
|
5836
5866
|
/*#__PURE__*/ jsx(XIcon, {
|
|
5837
5867
|
className: "size-6"
|
|
@@ -6369,12 +6399,18 @@ function shouldRetryViewerQuery(failureCount, error) {
|
|
|
6369
6399
|
return failureCount < 2;
|
|
6370
6400
|
}
|
|
6371
6401
|
const WIDGET_SESSION_TOKEN_HEADER = 'x-widget-session-token';
|
|
6402
|
+
const APP_TYPE_HEADER = 'x-app-type';
|
|
6372
6403
|
const DEFAULT_REFRESH_THRESHOLD_MS = 30000;
|
|
6373
6404
|
const ALLOWED_PRODUCT_TYPES = new Set([
|
|
6374
6405
|
'core-ar',
|
|
6375
6406
|
'core-ar-shopify'
|
|
6376
6407
|
]);
|
|
6377
6408
|
const ASSUMED_HANDOFF_SESSION_TTL_SECONDS = 900;
|
|
6409
|
+
function getAppTypeHeaders(appType) {
|
|
6410
|
+
return appType ? {
|
|
6411
|
+
[APP_TYPE_HEADER]: appType
|
|
6412
|
+
} : {};
|
|
6413
|
+
}
|
|
6378
6414
|
async function activateCoreArWidgetSession(mode, requestConfig) {
|
|
6379
6415
|
const activation = await publicApiControllerActivateCoreAR({
|
|
6380
6416
|
mode
|
|
@@ -6385,6 +6421,7 @@ async function activateCoreArWidgetSession(mode, requestConfig) {
|
|
|
6385
6421
|
class ModelViewerWidgetSession {
|
|
6386
6422
|
apiBaseUrl;
|
|
6387
6423
|
apiKey;
|
|
6424
|
+
appTypeHeaders;
|
|
6388
6425
|
issueWidgetToken;
|
|
6389
6426
|
mode;
|
|
6390
6427
|
now;
|
|
@@ -6394,6 +6431,7 @@ class ModelViewerWidgetSession {
|
|
|
6394
6431
|
constructor(activationData, options){
|
|
6395
6432
|
this.apiBaseUrl = options.apiBaseUrl;
|
|
6396
6433
|
this.apiKey = options.apiKey;
|
|
6434
|
+
this.appTypeHeaders = getAppTypeHeaders(options.appType);
|
|
6397
6435
|
this.issueWidgetToken = options.issueWidgetToken ?? publicApiControllerIssueWidgetToken;
|
|
6398
6436
|
this.mode = options.mode;
|
|
6399
6437
|
this.now = options.now ?? Date.now;
|
|
@@ -6419,6 +6457,7 @@ class ModelViewerWidgetSession {
|
|
|
6419
6457
|
return {
|
|
6420
6458
|
baseURL: this.apiBaseUrl,
|
|
6421
6459
|
headers: {
|
|
6460
|
+
...this.appTypeHeaders,
|
|
6422
6461
|
[WIDGET_SESSION_TOKEN_HEADER]: await this.getTokenForRequest()
|
|
6423
6462
|
},
|
|
6424
6463
|
signal
|
|
@@ -6427,10 +6466,12 @@ class ModelViewerWidgetSession {
|
|
|
6427
6466
|
async recoverFromExpiry(signal) {
|
|
6428
6467
|
try {
|
|
6429
6468
|
await this.refresh();
|
|
6430
|
-
} catch
|
|
6469
|
+
} catch (error) {
|
|
6470
|
+
if (!this.apiKey) throw error;
|
|
6431
6471
|
this.session = this.toSnapshot(await activateCoreArWidgetSession(this.mode, {
|
|
6432
6472
|
baseURL: this.apiBaseUrl,
|
|
6433
6473
|
headers: {
|
|
6474
|
+
...this.appTypeHeaders,
|
|
6434
6475
|
'x-api-key': this.apiKey
|
|
6435
6476
|
},
|
|
6436
6477
|
signal
|
|
@@ -6445,7 +6486,12 @@ class ModelViewerWidgetSession {
|
|
|
6445
6486
|
}, {
|
|
6446
6487
|
baseURL: this.apiBaseUrl,
|
|
6447
6488
|
headers: {
|
|
6448
|
-
|
|
6489
|
+
...this.appTypeHeaders,
|
|
6490
|
+
...this.apiKey ? {
|
|
6491
|
+
'x-api-key': this.apiKey
|
|
6492
|
+
} : {
|
|
6493
|
+
[WIDGET_SESSION_TOKEN_HEADER]: this.session.token
|
|
6494
|
+
}
|
|
6449
6495
|
}
|
|
6450
6496
|
}).then((data)=>this.toSnapshot(parseWidgetSession(data))).then((session)=>{
|
|
6451
6497
|
this.session = session;
|
|
@@ -6462,7 +6508,28 @@ class ModelViewerWidgetSession {
|
|
|
6462
6508
|
};
|
|
6463
6509
|
}
|
|
6464
6510
|
}
|
|
6465
|
-
async function createModelViewerWidgetSession({ apiBaseUrl, apiKey, initialWidgetSessionToken, mode, signal }) {
|
|
6511
|
+
async function createModelViewerWidgetSession({ apiBaseUrl, apiKey, appType, initialWidgetSessionToken, mode, signal }) {
|
|
6512
|
+
if (initialWidgetSessionToken && !apiKey) try {
|
|
6513
|
+
const exchanged = await publicApiControllerIssueWidgetToken({
|
|
6514
|
+
mode,
|
|
6515
|
+
token: initialWidgetSessionToken
|
|
6516
|
+
}, {
|
|
6517
|
+
baseURL: apiBaseUrl,
|
|
6518
|
+
headers: {
|
|
6519
|
+
...getAppTypeHeaders(appType),
|
|
6520
|
+
[WIDGET_SESSION_TOKEN_HEADER]: initialWidgetSessionToken
|
|
6521
|
+
},
|
|
6522
|
+
signal
|
|
6523
|
+
});
|
|
6524
|
+
return new ModelViewerWidgetSession(parseWidgetSession(exchanged), {
|
|
6525
|
+
apiBaseUrl,
|
|
6526
|
+
apiKey,
|
|
6527
|
+
appType,
|
|
6528
|
+
mode
|
|
6529
|
+
});
|
|
6530
|
+
} catch (error) {
|
|
6531
|
+
if (signal?.aborted) throw error;
|
|
6532
|
+
}
|
|
6466
6533
|
if (initialWidgetSessionToken) return new ModelViewerWidgetSession({
|
|
6467
6534
|
expiresIn: ASSUMED_HANDOFF_SESSION_TTL_SECONDS,
|
|
6468
6535
|
sid: initialWidgetSessionToken,
|
|
@@ -6470,11 +6537,13 @@ async function createModelViewerWidgetSession({ apiBaseUrl, apiKey, initialWidge
|
|
|
6470
6537
|
}, {
|
|
6471
6538
|
apiBaseUrl,
|
|
6472
6539
|
apiKey,
|
|
6540
|
+
appType,
|
|
6473
6541
|
mode
|
|
6474
6542
|
});
|
|
6475
6543
|
const activationData = await activateCoreArWidgetSession(mode, {
|
|
6476
6544
|
baseURL: apiBaseUrl,
|
|
6477
6545
|
headers: {
|
|
6546
|
+
...getAppTypeHeaders(appType),
|
|
6478
6547
|
'x-api-key': apiKey
|
|
6479
6548
|
},
|
|
6480
6549
|
signal
|
|
@@ -6482,6 +6551,7 @@ async function createModelViewerWidgetSession({ apiBaseUrl, apiKey, initialWidge
|
|
|
6482
6551
|
return new ModelViewerWidgetSession(activationData, {
|
|
6483
6552
|
apiBaseUrl,
|
|
6484
6553
|
apiKey,
|
|
6554
|
+
appType,
|
|
6485
6555
|
mode
|
|
6486
6556
|
});
|
|
6487
6557
|
}
|
|
@@ -6511,6 +6581,7 @@ async function sendModelViewerWidgetEvent(session, event, options = {}) {
|
|
|
6511
6581
|
body: JSON.stringify({
|
|
6512
6582
|
event,
|
|
6513
6583
|
objectId: options.objectId ?? void 0,
|
|
6584
|
+
page_path: currentPagePath(),
|
|
6514
6585
|
timestamp: new Date().toISOString(),
|
|
6515
6586
|
variantId: options.variantId ?? void 0
|
|
6516
6587
|
}),
|
|
@@ -6537,12 +6608,13 @@ async function issueWidgetHandoffCode(session, params) {
|
|
|
6537
6608
|
expiresIn: data.expiresIn
|
|
6538
6609
|
};
|
|
6539
6610
|
}
|
|
6540
|
-
async function resolveWidgetHandoffCode(apiBaseUrl, code) {
|
|
6611
|
+
async function resolveWidgetHandoffCode(apiBaseUrl, code, appType) {
|
|
6541
6612
|
try {
|
|
6542
6613
|
const data = await widgetHandoffControllerResolveHandoff({
|
|
6543
6614
|
code
|
|
6544
6615
|
}, {
|
|
6545
|
-
baseURL: apiBaseUrl
|
|
6616
|
+
baseURL: apiBaseUrl,
|
|
6617
|
+
headers: getAppTypeHeaders(appType)
|
|
6546
6618
|
});
|
|
6547
6619
|
if (!data?.apiKey || !data.token) return null;
|
|
6548
6620
|
return {
|
|
@@ -6558,6 +6630,10 @@ function parseWidgetSession(value) {
|
|
|
6558
6630
|
if (!session || 'object' != typeof session || 'string' != typeof session.token || !session.token.trim() || 'string' != typeof session.sid || !session.sid.trim() || 'number' != typeof session.expiresIn || !Number.isFinite(session.expiresIn) || session.expiresIn <= 0) throw new TypeError('Invalid widget session response');
|
|
6559
6631
|
return session;
|
|
6560
6632
|
}
|
|
6633
|
+
function currentPagePath(locationRef = globalThis.location) {
|
|
6634
|
+
const path = locationRef?.pathname;
|
|
6635
|
+
return 'string' == typeof path && path.startsWith('/') ? path : void 0;
|
|
6636
|
+
}
|
|
6561
6637
|
const MODEL_VIEWER_URL = "https://integrations.vizbl.com/model-viewer";
|
|
6562
6638
|
const AR_DEVICE_REQUIREMENTS_DISCLAIMER = {
|
|
6563
6639
|
en: '*Requires AR-supported device and browser. We recommend iOS 18 or later with Safari, or Android 7.0 or later with Chrome.',
|
|
@@ -6597,6 +6673,7 @@ function useObjectData(tinuuid, initialHid, options) {
|
|
|
6597
6673
|
{
|
|
6598
6674
|
apiBaseUrl: options.apiBaseUrl ?? null,
|
|
6599
6675
|
apiKey: options.apiKey,
|
|
6676
|
+
appType: options.appType ?? null,
|
|
6600
6677
|
handoffCode: options.handoffCode ?? null,
|
|
6601
6678
|
initialHid: initialHid ?? null,
|
|
6602
6679
|
initialWidgetSessionToken: options.initialWidgetSessionToken ?? null,
|
|
@@ -6609,12 +6686,13 @@ function useObjectData(tinuuid, initialHid, options) {
|
|
|
6609
6686
|
refetchOnMount: 'always',
|
|
6610
6687
|
queryFn: async ({ signal })=>{
|
|
6611
6688
|
if (options.handoffCode) {
|
|
6612
|
-
const resolved = readHandoffResolution(options.handoffCode) ?? await resolveWidgetHandoffCode(options.apiBaseUrl ?? window.location.origin, options.handoffCode);
|
|
6689
|
+
const resolved = readHandoffResolution(options.handoffCode) ?? await resolveWidgetHandoffCode(options.apiBaseUrl ?? window.location.origin, options.handoffCode, options.appType);
|
|
6613
6690
|
if (!resolved) throw new WidgetHandoffExpiredError();
|
|
6614
6691
|
rememberHandoffResolution(options.handoffCode, resolved);
|
|
6615
6692
|
const widgetSession = await createModelViewerWidgetSession({
|
|
6616
6693
|
apiBaseUrl: options.apiBaseUrl,
|
|
6617
6694
|
apiKey: resolved.apiKey,
|
|
6695
|
+
appType: options.appType,
|
|
6618
6696
|
initialWidgetSessionToken: resolved.token,
|
|
6619
6697
|
mode: options.mode,
|
|
6620
6698
|
signal
|
|
@@ -6625,30 +6703,38 @@ function useObjectData(tinuuid, initialHid, options) {
|
|
|
6625
6703
|
widgetSession
|
|
6626
6704
|
};
|
|
6627
6705
|
}
|
|
6628
|
-
|
|
6706
|
+
const readAnonymously = async ()=>{
|
|
6629
6707
|
const object = await readObject({
|
|
6630
6708
|
tinuuid
|
|
6631
6709
|
}, {
|
|
6632
6710
|
baseURL: options.apiBaseUrl,
|
|
6711
|
+
headers: getAppTypeHeaders(options.appType),
|
|
6633
6712
|
signal
|
|
6634
6713
|
});
|
|
6635
6714
|
return {
|
|
6636
6715
|
object,
|
|
6637
6716
|
widgetSession: null
|
|
6638
6717
|
};
|
|
6639
|
-
}
|
|
6640
|
-
const widgetSession = await createModelViewerWidgetSession({
|
|
6641
|
-
apiBaseUrl: options.apiBaseUrl,
|
|
6642
|
-
apiKey: options.apiKey,
|
|
6643
|
-
initialWidgetSessionToken: options.initialWidgetSessionToken,
|
|
6644
|
-
mode: options.mode,
|
|
6645
|
-
signal
|
|
6646
|
-
});
|
|
6647
|
-
const object = await fetchModelViewerObject(tinuuid, initialHid, widgetSession, signal);
|
|
6648
|
-
return {
|
|
6649
|
-
object,
|
|
6650
|
-
widgetSession
|
|
6651
6718
|
};
|
|
6719
|
+
if (!options.apiKey && !options.initialWidgetSessionToken) return readAnonymously();
|
|
6720
|
+
try {
|
|
6721
|
+
const widgetSession = await createModelViewerWidgetSession({
|
|
6722
|
+
apiBaseUrl: options.apiBaseUrl,
|
|
6723
|
+
apiKey: options.apiKey,
|
|
6724
|
+
appType: options.appType,
|
|
6725
|
+
initialWidgetSessionToken: options.initialWidgetSessionToken,
|
|
6726
|
+
mode: options.mode,
|
|
6727
|
+
signal
|
|
6728
|
+
});
|
|
6729
|
+
const object = await fetchModelViewerObject(tinuuid, initialHid, widgetSession, signal);
|
|
6730
|
+
return {
|
|
6731
|
+
object,
|
|
6732
|
+
widgetSession
|
|
6733
|
+
};
|
|
6734
|
+
} catch (error) {
|
|
6735
|
+
if (options.apiKey || signal.aborted || 401 !== getErrorResponseStatus(error)) throw error;
|
|
6736
|
+
return readAnonymously();
|
|
6737
|
+
}
|
|
6652
6738
|
}
|
|
6653
6739
|
});
|
|
6654
6740
|
const object = data?.object ?? null;
|
|
@@ -6716,6 +6802,7 @@ function ModelViewerProvider({ children, tinuuid, apiKey, appClipBundleId, arExp
|
|
|
6716
6802
|
const { object, material, error, isLoading, setMaterialHid: setObjectMaterialHid, widgetSession } = useObjectData(tinuuid, hid, {
|
|
6717
6803
|
apiBaseUrl,
|
|
6718
6804
|
apiKey,
|
|
6805
|
+
appType: 'ru' === lang ? 'arizo' : 'vizbl',
|
|
6719
6806
|
handoffCode,
|
|
6720
6807
|
initialWidgetSessionToken,
|
|
6721
6808
|
mode
|
|
@@ -6834,6 +6921,7 @@ function ModelViewerProvider({ children, tinuuid, apiKey, appClipBundleId, arExp
|
|
|
6834
6921
|
widgetSession
|
|
6835
6922
|
]);
|
|
6836
6923
|
const contextValue = external_react_useMemo(()=>({
|
|
6924
|
+
apiBaseUrl,
|
|
6837
6925
|
apiKey,
|
|
6838
6926
|
appClipBundleId,
|
|
6839
6927
|
arExperience,
|
|
@@ -6865,6 +6953,7 @@ function ModelViewerProvider({ children, tinuuid, apiKey, appClipBundleId, arExp
|
|
|
6865
6953
|
setModelViewerEl,
|
|
6866
6954
|
trackEvent
|
|
6867
6955
|
}), [
|
|
6956
|
+
apiBaseUrl,
|
|
6868
6957
|
apiKey,
|
|
6869
6958
|
appClipBundleId,
|
|
6870
6959
|
arExperience,
|
|
@@ -6978,7 +7067,20 @@ async function launchArOverride(launchAr, target) {
|
|
|
6978
7067
|
return false;
|
|
6979
7068
|
}
|
|
6980
7069
|
}
|
|
6981
|
-
|
|
7070
|
+
const AR_TAP_WINDOW_MS = 3000;
|
|
7071
|
+
function withinTapWindow(promise, windowMs = AR_TAP_WINDOW_MS) {
|
|
7072
|
+
return new Promise((resolve, reject)=>{
|
|
7073
|
+
const timer = setTimeout(()=>resolve(null), windowMs);
|
|
7074
|
+
promise.then((value)=>{
|
|
7075
|
+
clearTimeout(timer);
|
|
7076
|
+
resolve(value);
|
|
7077
|
+
}, (error)=>{
|
|
7078
|
+
clearTimeout(timer);
|
|
7079
|
+
reject(error);
|
|
7080
|
+
});
|
|
7081
|
+
});
|
|
7082
|
+
}
|
|
7083
|
+
function buildModelViewerHandoffUrl({ apiKey, arExperience, baseUrl, hid, lang, mode, tinuuid, widgetSessionToken }) {
|
|
6982
7084
|
if (!baseUrl || !tinuuid) return null;
|
|
6983
7085
|
let url;
|
|
6984
7086
|
try {
|
|
@@ -6992,6 +7094,7 @@ function buildModelViewerHandoffUrl({ apiKey, arExperience, baseUrl, hid, mode,
|
|
|
6992
7094
|
else url.searchParams.delete('ar-experience');
|
|
6993
7095
|
if (hid) url.searchParams.set('hid', hid);
|
|
6994
7096
|
else url.searchParams.delete('hid');
|
|
7097
|
+
setLang(url, lang);
|
|
6995
7098
|
const fragment = new URLSearchParams(url.hash.slice(1));
|
|
6996
7099
|
if (apiKey) fragment.set('api-key', apiKey);
|
|
6997
7100
|
else fragment.delete('api-key');
|
|
@@ -7000,7 +7103,7 @@ function buildModelViewerHandoffUrl({ apiKey, arExperience, baseUrl, hid, mode,
|
|
|
7000
7103
|
url.hash = fragment.toString();
|
|
7001
7104
|
return url.toString();
|
|
7002
7105
|
}
|
|
7003
|
-
function buildModelViewerHandoffCodeUrl({ arExperience, baseUrl, code, hid, mode, tinuuid }) {
|
|
7106
|
+
function buildModelViewerHandoffCodeUrl({ arExperience, baseUrl, code, hid, lang, mode, tinuuid }) {
|
|
7004
7107
|
if (!baseUrl || !tinuuid) return null;
|
|
7005
7108
|
let url;
|
|
7006
7109
|
try {
|
|
@@ -7014,6 +7117,7 @@ function buildModelViewerHandoffCodeUrl({ arExperience, baseUrl, code, hid, mode
|
|
|
7014
7117
|
else url.searchParams.delete('ar-experience');
|
|
7015
7118
|
if (hid) url.searchParams.set('hid', hid);
|
|
7016
7119
|
else url.searchParams.delete('hid');
|
|
7120
|
+
setLang(url, lang);
|
|
7017
7121
|
const fragment = new URLSearchParams(url.hash.slice(1));
|
|
7018
7122
|
if (code) fragment.set('code', code);
|
|
7019
7123
|
else fragment.delete('code');
|
|
@@ -7023,9 +7127,14 @@ function buildModelViewerHandoffCodeUrl({ arExperience, baseUrl, code, hid, mode
|
|
|
7023
7127
|
function handoffCodeReissueDelayMs(expiresInSeconds) {
|
|
7024
7128
|
return Math.round(1000 * expiresInSeconds * 2 / 3);
|
|
7025
7129
|
}
|
|
7130
|
+
function setLang(url, lang) {
|
|
7131
|
+
if (lang) url.searchParams.set('lang', lang);
|
|
7132
|
+
else url.searchParams.delete('lang');
|
|
7133
|
+
}
|
|
7026
7134
|
const EVENT_FLUSH_TIMEOUT_MS = 300;
|
|
7135
|
+
const LAUNCH_TOKEN_TIMEOUT_MS = 800;
|
|
7027
7136
|
const HANDOFF_CODE_RETRY_MS = 15000;
|
|
7028
|
-
async function issueHandoffQrCode(widgetSession, { arExperience, baseUrl, hid, mode, tinuuid }) {
|
|
7137
|
+
async function issueHandoffQrCode(widgetSession, { arExperience, baseUrl, hid, lang, mode, tinuuid }) {
|
|
7029
7138
|
const { code, expiresIn } = await issueWidgetHandoffCode(widgetSession, {
|
|
7030
7139
|
arExperience,
|
|
7031
7140
|
hid,
|
|
@@ -7036,6 +7145,7 @@ async function issueHandoffQrCode(widgetSession, { arExperience, baseUrl, hid, m
|
|
|
7036
7145
|
baseUrl,
|
|
7037
7146
|
code,
|
|
7038
7147
|
hid,
|
|
7148
|
+
lang,
|
|
7039
7149
|
mode,
|
|
7040
7150
|
tinuuid
|
|
7041
7151
|
});
|
|
@@ -7054,7 +7164,7 @@ async function flushWidgetEvent(eventRequest) {
|
|
|
7054
7164
|
});
|
|
7055
7165
|
}
|
|
7056
7166
|
function AR({ disabled, onClick, onBeforeActivateAr, size = 'lg', ...props }) {
|
|
7057
|
-
const { apiKey, appClipBundleId, arExperience, containerEl, handoffUrl, isLoading, isModelLoading, lang, launchAr, material, mode, modelViewerEl, object, tinuuid, trackEvent, widgetSession } = useModelViewer();
|
|
7167
|
+
const { apiBaseUrl, apiKey, appClipBundleId, arExperience, containerEl, handoffUrl, isLoading, isModelLoading, lang, launchAr, material, mode, modelViewerEl, object, tinuuid, trackEvent, widgetSession } = useModelViewer();
|
|
7058
7168
|
const [open, setOpen] = useState(false);
|
|
7059
7169
|
const [qrState, setQrState] = useState({
|
|
7060
7170
|
status: 'loading'
|
|
@@ -7063,12 +7173,33 @@ function AR({ disabled, onClick, onBeforeActivateAr, size = 'lg', ...props }) {
|
|
|
7063
7173
|
const widgetSessionSid = widgetSession?.sid;
|
|
7064
7174
|
const isDisabled = isLoading || isModelLoading || null === material;
|
|
7065
7175
|
const arTarget = external_react_useMemo(()=>({
|
|
7176
|
+
apiBaseUrl,
|
|
7177
|
+
apiKey: widgetSession?.apiKey || apiKey || void 0,
|
|
7066
7178
|
hid: material?.hid,
|
|
7179
|
+
lang,
|
|
7180
|
+
name: object?.name ?? void 0,
|
|
7067
7181
|
tinuuid: object?.tinuuid ?? tinuuid
|
|
7068
7182
|
}), [
|
|
7183
|
+
apiBaseUrl,
|
|
7184
|
+
apiKey,
|
|
7185
|
+
lang,
|
|
7069
7186
|
material?.hid,
|
|
7187
|
+
object?.name,
|
|
7070
7188
|
object?.tinuuid,
|
|
7071
|
-
tinuuid
|
|
7189
|
+
tinuuid,
|
|
7190
|
+
widgetSession
|
|
7191
|
+
]);
|
|
7192
|
+
const launchHostAr = useCallback(async ()=>{
|
|
7193
|
+
if (!launchAr) return false;
|
|
7194
|
+
const widgetSessionToken = widgetSession ? await withinTapWindow(widgetSession.getTokenForRequest(), LAUNCH_TOKEN_TIMEOUT_MS).catch(()=>null) ?? widgetSession.token : void 0;
|
|
7195
|
+
return launchArOverride(launchAr, {
|
|
7196
|
+
...arTarget,
|
|
7197
|
+
widgetSessionToken
|
|
7198
|
+
});
|
|
7199
|
+
}, [
|
|
7200
|
+
arTarget,
|
|
7201
|
+
launchAr,
|
|
7202
|
+
widgetSession
|
|
7072
7203
|
]);
|
|
7073
7204
|
const directArExperience = resolveDirectArExperience(mode, arExperience);
|
|
7074
7205
|
const directArLaunchOptions = external_react_useMemo(()=>{
|
|
@@ -7116,7 +7247,7 @@ function AR({ disabled, onClick, onBeforeActivateAr, size = 'lg', ...props }) {
|
|
|
7116
7247
|
const timer = window.setTimeout(()=>{
|
|
7117
7248
|
(async ()=>{
|
|
7118
7249
|
if (autoLaunchKeyRef.current !== launchKey) return;
|
|
7119
|
-
if (await
|
|
7250
|
+
if (await launchHostAr()) return;
|
|
7120
7251
|
await flushWidgetEvent(trackEvent('ar_launched'));
|
|
7121
7252
|
if (autoLaunchKeyRef.current === launchKey) launchDirectAr(directArLaunchOptions);
|
|
7122
7253
|
})();
|
|
@@ -7126,10 +7257,9 @@ function AR({ disabled, onClick, onBeforeActivateAr, size = 'lg', ...props }) {
|
|
|
7126
7257
|
if (autoLaunchKeyRef.current === launchKey) autoLaunchKeyRef.current = null;
|
|
7127
7258
|
};
|
|
7128
7259
|
}, [
|
|
7129
|
-
arTarget,
|
|
7130
7260
|
directArLaunchOptions,
|
|
7131
7261
|
isLoading,
|
|
7132
|
-
|
|
7262
|
+
launchHostAr,
|
|
7133
7263
|
material?.hid,
|
|
7134
7264
|
mode,
|
|
7135
7265
|
trackEvent,
|
|
@@ -7149,6 +7279,7 @@ function AR({ disabled, onClick, onBeforeActivateAr, size = 'lg', ...props }) {
|
|
|
7149
7279
|
arExperience,
|
|
7150
7280
|
baseUrl,
|
|
7151
7281
|
hid: material?.hid,
|
|
7282
|
+
lang,
|
|
7152
7283
|
mode,
|
|
7153
7284
|
tinuuid: resolvedTinuuid
|
|
7154
7285
|
});
|
|
@@ -7165,6 +7296,7 @@ function AR({ disabled, onClick, onBeforeActivateAr, size = 'lg', ...props }) {
|
|
|
7165
7296
|
arExperience,
|
|
7166
7297
|
baseUrl,
|
|
7167
7298
|
hid: material?.hid,
|
|
7299
|
+
lang,
|
|
7168
7300
|
mode,
|
|
7169
7301
|
tinuuid: resolvedTinuuid
|
|
7170
7302
|
});
|
|
@@ -7179,6 +7311,7 @@ function AR({ disabled, onClick, onBeforeActivateAr, size = 'lg', ...props }) {
|
|
|
7179
7311
|
arExperience,
|
|
7180
7312
|
baseUrl,
|
|
7181
7313
|
hid: material?.hid,
|
|
7314
|
+
lang,
|
|
7182
7315
|
mode,
|
|
7183
7316
|
tinuuid: resolvedTinuuid,
|
|
7184
7317
|
widgetSessionToken: sessionToken
|
|
@@ -7202,6 +7335,7 @@ function AR({ disabled, onClick, onBeforeActivateAr, size = 'lg', ...props }) {
|
|
|
7202
7335
|
arExperience,
|
|
7203
7336
|
baseUrl: handoffUrl || MODEL_VIEWER_URL,
|
|
7204
7337
|
hid: material?.hid,
|
|
7338
|
+
lang,
|
|
7205
7339
|
mode,
|
|
7206
7340
|
tinuuid: object?.tinuuid ?? tinuuid
|
|
7207
7341
|
});
|
|
@@ -7223,6 +7357,7 @@ function AR({ disabled, onClick, onBeforeActivateAr, size = 'lg', ...props }) {
|
|
|
7223
7357
|
}, [
|
|
7224
7358
|
arExperience,
|
|
7225
7359
|
handoffUrl,
|
|
7360
|
+
lang,
|
|
7226
7361
|
material?.hid,
|
|
7227
7362
|
mode,
|
|
7228
7363
|
object?.tinuuid,
|
|
@@ -7233,7 +7368,7 @@ function AR({ disabled, onClick, onBeforeActivateAr, size = 'lg', ...props }) {
|
|
|
7233
7368
|
]);
|
|
7234
7369
|
const handleClick = async ()=>{
|
|
7235
7370
|
if (!modelViewerEl || isDisabled) return;
|
|
7236
|
-
if (await
|
|
7371
|
+
if (await launchHostAr()) return void onBeforeActivateAr?.();
|
|
7237
7372
|
if (directArLaunchOptions && isMobileArDevice()) {
|
|
7238
7373
|
onBeforeActivateAr?.();
|
|
7239
7374
|
await flushWidgetEvent(trackEvent('ar_launched'));
|
|
@@ -8070,7 +8205,7 @@ function ModelViewerRoot({ tinuuid, apiKey, appClipBundleId = 'com.us.vizbl.Clip
|
|
|
8070
8205
|
})
|
|
8071
8206
|
});
|
|
8072
8207
|
}
|
|
8073
|
-
function ModelViewerDialog({ tinuuid, apiKey, apiBaseUrl, appClipBundleId, initialWidgetSessionToken, handoffUrl, hid, lang = 'en', mode = 'ar-viewer', sizeType, dimensionAxes, cameraOrbit, minCameraOrbit, maxCameraOrbit, ...props }) {
|
|
8208
|
+
function ModelViewerDialog({ tinuuid, apiKey, apiBaseUrl, appClipBundleId, initialWidgetSessionToken, handoffUrl, hid, lang = 'en', launchAr, mode = 'ar-viewer', sizeType, dimensionAxes, cameraOrbit, minCameraOrbit, maxCameraOrbit, ...props }) {
|
|
8074
8209
|
const [container, setContainer] = useState(null);
|
|
8075
8210
|
return /*#__PURE__*/ jsxs(Fragment, {
|
|
8076
8211
|
children: [
|
|
@@ -8111,6 +8246,7 @@ function ModelViewerDialog({ tinuuid, apiKey, apiBaseUrl, appClipBundleId, initi
|
|
|
8111
8246
|
lang: lang,
|
|
8112
8247
|
handoffUrl: handoffUrl,
|
|
8113
8248
|
hid: hid,
|
|
8249
|
+
launchAr: launchAr,
|
|
8114
8250
|
sizeType: sizeType,
|
|
8115
8251
|
dimensionAxes: dimensionAxes,
|
|
8116
8252
|
cameraOrbit: cameraOrbit,
|
|
@@ -8202,4 +8338,5 @@ function ModelViewer({ tinuuid, apiKey, appClipBundleId, arExperience, hid, apiB
|
|
|
8202
8338
|
]
|
|
8203
8339
|
});
|
|
8204
8340
|
}
|
|
8205
|
-
|
|
8341
|
+
var __webpack_exports__AR_TAP_WINDOW_MS = 3000;
|
|
8342
|
+
export { ModelViewer, ModelViewerDialog, isIOSDevice, isMobileArDevice, withinTapWindow, __webpack_exports__AR_TAP_WINDOW_MS as AR_TAP_WINDOW_MS };
|