@neurodyn/react-model-viewer 0.0.4 → 0.0.6
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 +13 -3
- package/dist/index.js +121 -49
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -21,15 +21,15 @@ declare type DialogProps = React_3.ComponentProps<typeof DialogPrimitive.Root>
|
|
|
21
21
|
*/
|
|
22
22
|
export declare type LaunchArOverride = (target: ArLaunchTarget) => boolean | Promise<boolean>;
|
|
23
23
|
|
|
24
|
-
export declare function ModelViewer({ tinuuid, apiKey, appClipBundleId, arExperience, hid, apiBaseUrl, legacyApiBaseUrl, mode, initialWidgetSessionToken, handoffUrl, launchAr, sizeType, layout, background, viewerSurface, className, ...props }: ModelViewerProps & React_2.ComponentProps<'div'>): JSX.Element;
|
|
24
|
+
export declare function ModelViewer({ tinuuid, apiKey, appClipBundleId, arExperience, hid, apiBaseUrl, legacyApiBaseUrl, mode, initialWidgetSessionToken, handoffUrl, launchAr, sizeType, dimensionAxes, layout, background, viewerSurface, className, ...props }: ModelViewerProps & React_2.ComponentProps<'div'>): JSX.Element;
|
|
25
25
|
|
|
26
26
|
export declare type ModelViewerArExperience = 'advanced' | 'standard';
|
|
27
27
|
|
|
28
28
|
declare type ModelViewerBackground = 'default' | 'transparent';
|
|
29
29
|
|
|
30
|
-
export declare function ModelViewerDialog({ tinuuid, apiKey, apiBaseUrl, legacyApiBaseUrl, initialWidgetSessionToken, handoffUrl, hid, sizeType, ...props }: ModelViewerDialogProps): JSX.Element;
|
|
30
|
+
export declare function ModelViewerDialog({ tinuuid, apiKey, apiBaseUrl, legacyApiBaseUrl, initialWidgetSessionToken, handoffUrl, hid, sizeType, dimensionAxes, ...props }: ModelViewerDialogProps): JSX.Element;
|
|
31
31
|
|
|
32
|
-
declare interface ModelViewerDialogProps extends Pick<ModelViewerRootProps, 'apiBaseUrl' | 'apiKey' | 'handoffUrl' | 'hid' | 'initialWidgetSessionToken' | 'legacyApiBaseUrl' | 'sizeType' | 'tinuuid'>, Omit<DialogProps, 'children'> {
|
|
32
|
+
declare interface ModelViewerDialogProps extends Pick<ModelViewerRootProps, 'apiBaseUrl' | 'apiKey' | 'dimensionAxes' | 'handoffUrl' | 'hid' | 'initialWidgetSessionToken' | 'legacyApiBaseUrl' | 'sizeType' | 'tinuuid'>, Omit<DialogProps, 'children'> {
|
|
33
33
|
}
|
|
34
34
|
|
|
35
35
|
declare type ModelViewerLayout = 'default' | 'model';
|
|
@@ -62,6 +62,14 @@ declare interface ModelViewerRootProps {
|
|
|
62
62
|
launchAr?: LaunchArOverride;
|
|
63
63
|
/** Display unit for model dimensions. */
|
|
64
64
|
sizeType?: SizeType;
|
|
65
|
+
/** Which axes' measurements the "Show dimensions" overlay draws. Defaults to all three. */
|
|
66
|
+
dimensionAxes?: SizeAxis[];
|
|
67
|
+
/** Initial camera angle, in `<model-viewer>`'s own `"theta phi radius"` format. */
|
|
68
|
+
cameraOrbit?: string;
|
|
69
|
+
/** Lower bound for orbit dragging, same format as `cameraOrbit`. Matching `maxCameraOrbit` on an axis locks it. */
|
|
70
|
+
minCameraOrbit?: string;
|
|
71
|
+
/** Upper bound for orbit dragging, same format as `cameraOrbit`. Matching `minCameraOrbit` on an axis locks it. */
|
|
72
|
+
maxCameraOrbit?: string;
|
|
65
73
|
/** Controls which viewer UI elements are shown. */
|
|
66
74
|
layout?: ModelViewerLayout;
|
|
67
75
|
/** Controls the viewer container background. */
|
|
@@ -76,6 +84,8 @@ declare type ModelViewerSurface = 'dialog' | 'inline' | 'page';
|
|
|
76
84
|
|
|
77
85
|
export declare type ModelViewerWidgetMode = 'advanced-ar-view' | 'ar-view' | 'embedded-3d-viewer' | 'ar-viewer' | 'qr-code';
|
|
78
86
|
|
|
87
|
+
export declare type SizeAxis = 'x' | 'y' | 'z';
|
|
88
|
+
|
|
79
89
|
declare type SizeType = 'cm' | 'inch';
|
|
80
90
|
|
|
81
91
|
export { }
|
package/dist/index.js
CHANGED
|
@@ -2459,6 +2459,10 @@ button, input:where([type="button"], [type="reset"], [type="submit"]) {
|
|
|
2459
2459
|
stroke-dasharray: 2;
|
|
2460
2460
|
}
|
|
2461
2461
|
|
|
2462
|
+
.running {
|
|
2463
|
+
animation-play-state: running;
|
|
2464
|
+
}
|
|
2465
|
+
|
|
2462
2466
|
.group-focus-within\\/editor-mesh-item\\:text-icons-dark:is(:where(.group\\/editor-mesh-item):focus-within *) {
|
|
2463
2467
|
color: var(--v-icons-dark);
|
|
2464
2468
|
}
|
|
@@ -6529,12 +6533,32 @@ async function publicApiControllerReadObjectByTinuuid({ tinuuid }, params, confi
|
|
|
6529
6533
|
});
|
|
6530
6534
|
return res.data;
|
|
6531
6535
|
}
|
|
6536
|
+
function getErrorResponseStatus(error) {
|
|
6537
|
+
if (!isAxiosError(error)) return;
|
|
6538
|
+
return error.response?.status;
|
|
6539
|
+
}
|
|
6540
|
+
function getModelViewerApiError(error) {
|
|
6541
|
+
if (!isAxiosError(error)) return null;
|
|
6542
|
+
const status = error.response?.status;
|
|
6543
|
+
if (401 === status) return 'unauthorized';
|
|
6544
|
+
if (403 === status) return 'forbidden';
|
|
6545
|
+
if (402 === status) return 'payment-required';
|
|
6546
|
+
return null;
|
|
6547
|
+
}
|
|
6532
6548
|
const WIDGET_SESSION_TOKEN_HEADER = 'x-widget-session-token';
|
|
6533
6549
|
const DEFAULT_REFRESH_THRESHOLD_MS = 30000;
|
|
6534
6550
|
const ALLOWED_PRODUCT_TYPES = new Set([
|
|
6535
6551
|
'core-ar',
|
|
6536
6552
|
'core-ar-shopify'
|
|
6537
6553
|
]);
|
|
6554
|
+
const ASSUMED_HANDOFF_SESSION_TTL_SECONDS = 900;
|
|
6555
|
+
async function activateCoreArWidgetSession(mode, requestConfig) {
|
|
6556
|
+
const activation = await publicApiControllerActivateCoreAR({
|
|
6557
|
+
mode
|
|
6558
|
+
}, requestConfig);
|
|
6559
|
+
if ('string' != typeof activation.productType || !ALLOWED_PRODUCT_TYPES.has(activation.productType)) throw new TypeError('The API key is not enabled for Core AR');
|
|
6560
|
+
return parseWidgetSession(activation.widgetSession);
|
|
6561
|
+
}
|
|
6538
6562
|
class ModelViewerWidgetSession {
|
|
6539
6563
|
apiBaseUrl;
|
|
6540
6564
|
apiKey;
|
|
@@ -6577,6 +6601,19 @@ class ModelViewerWidgetSession {
|
|
|
6577
6601
|
signal
|
|
6578
6602
|
};
|
|
6579
6603
|
}
|
|
6604
|
+
async recoverFromExpiry(signal) {
|
|
6605
|
+
try {
|
|
6606
|
+
await this.refresh();
|
|
6607
|
+
} catch {
|
|
6608
|
+
this.session = this.toSnapshot(await activateCoreArWidgetSession(this.mode, {
|
|
6609
|
+
baseURL: this.apiBaseUrl,
|
|
6610
|
+
headers: {
|
|
6611
|
+
'x-api-key': this.apiKey
|
|
6612
|
+
},
|
|
6613
|
+
signal
|
|
6614
|
+
}));
|
|
6615
|
+
}
|
|
6616
|
+
}
|
|
6580
6617
|
refresh() {
|
|
6581
6618
|
if (this.refreshPromise) return this.refreshPromise;
|
|
6582
6619
|
this.refreshPromise = this.issueWidgetToken({
|
|
@@ -6603,37 +6640,38 @@ class ModelViewerWidgetSession {
|
|
|
6603
6640
|
}
|
|
6604
6641
|
}
|
|
6605
6642
|
async function createModelViewerWidgetSession({ apiBaseUrl, apiKey, initialWidgetSessionToken, mode, signal }) {
|
|
6606
|
-
|
|
6643
|
+
if (initialWidgetSessionToken) return new ModelViewerWidgetSession({
|
|
6644
|
+
expiresIn: ASSUMED_HANDOFF_SESSION_TTL_SECONDS,
|
|
6645
|
+
sid: initialWidgetSessionToken,
|
|
6646
|
+
token: initialWidgetSessionToken
|
|
6647
|
+
}, {
|
|
6648
|
+
apiBaseUrl,
|
|
6649
|
+
apiKey,
|
|
6650
|
+
mode
|
|
6651
|
+
});
|
|
6652
|
+
const activationData = await activateCoreArWidgetSession(mode, {
|
|
6607
6653
|
baseURL: apiBaseUrl,
|
|
6608
6654
|
headers: {
|
|
6609
6655
|
'x-api-key': apiKey
|
|
6610
6656
|
},
|
|
6611
6657
|
signal
|
|
6612
|
-
};
|
|
6613
|
-
|
|
6614
|
-
const refreshed = await publicApiControllerIssueWidgetToken({
|
|
6615
|
-
mode,
|
|
6616
|
-
token: initialWidgetSessionToken
|
|
6617
|
-
}, requestConfig);
|
|
6618
|
-
return new ModelViewerWidgetSession(parseWidgetSession(refreshed), {
|
|
6619
|
-
apiBaseUrl,
|
|
6620
|
-
apiKey,
|
|
6621
|
-
mode
|
|
6622
|
-
});
|
|
6623
|
-
} catch (error) {
|
|
6624
|
-
if (signal?.aborted) throw error;
|
|
6625
|
-
}
|
|
6626
|
-
const activation = await publicApiControllerActivateCoreAR({
|
|
6627
|
-
mode
|
|
6628
|
-
}, requestConfig);
|
|
6629
|
-
if ('string' != typeof activation.productType || !ALLOWED_PRODUCT_TYPES.has(activation.productType)) throw new TypeError('The API key is not enabled for Core AR');
|
|
6630
|
-
return new ModelViewerWidgetSession(parseWidgetSession(activation.widgetSession), {
|
|
6658
|
+
});
|
|
6659
|
+
return new ModelViewerWidgetSession(activationData, {
|
|
6631
6660
|
apiBaseUrl,
|
|
6632
6661
|
apiKey,
|
|
6633
6662
|
mode
|
|
6634
6663
|
});
|
|
6635
6664
|
}
|
|
6636
6665
|
async function fetchModelViewerObject(tinuuid, variantId, session, signal) {
|
|
6666
|
+
try {
|
|
6667
|
+
return await readObjectWithSession(tinuuid, variantId, session, signal);
|
|
6668
|
+
} catch (error) {
|
|
6669
|
+
if (401 !== getErrorResponseStatus(error)) throw error;
|
|
6670
|
+
await session.recoverFromExpiry(signal);
|
|
6671
|
+
return readObjectWithSession(tinuuid, variantId, session, signal);
|
|
6672
|
+
}
|
|
6673
|
+
}
|
|
6674
|
+
async function readObjectWithSession(tinuuid, variantId, session, signal) {
|
|
6637
6675
|
return publicApiControllerReadObjectByTinuuid({
|
|
6638
6676
|
tinuuid
|
|
6639
6677
|
}, {
|
|
@@ -6766,18 +6804,6 @@ function useObjectData(tinuuid, initialHid, options) {
|
|
|
6766
6804
|
widgetSession: data?.widgetSession ?? null
|
|
6767
6805
|
};
|
|
6768
6806
|
}
|
|
6769
|
-
function getErrorResponseStatus(error) {
|
|
6770
|
-
if (!isAxiosError(error)) return;
|
|
6771
|
-
return error.response?.status;
|
|
6772
|
-
}
|
|
6773
|
-
function getModelViewerApiError(error) {
|
|
6774
|
-
if (!isAxiosError(error)) return null;
|
|
6775
|
-
const status = error.response?.status;
|
|
6776
|
-
if (401 === status) return 'unauthorized';
|
|
6777
|
-
if (403 === status) return 'forbidden';
|
|
6778
|
-
if (402 === status) return 'payment-required';
|
|
6779
|
-
return null;
|
|
6780
|
-
}
|
|
6781
6807
|
const RECOVERY_STORAGE_KEY = 'vizbl-model-viewer-blank-canvas-recovery';
|
|
6782
6808
|
const RENDER_CHECK_DELAY_MS = 2000;
|
|
6783
6809
|
const SAMPLE_SIZE = 64;
|
|
@@ -6816,7 +6842,7 @@ function isCanvasBlank(modelViewerEl) {
|
|
|
6816
6842
|
return true;
|
|
6817
6843
|
}
|
|
6818
6844
|
const ModelViewerContext = /*#__PURE__*/ createContext(null);
|
|
6819
|
-
function ModelViewerProvider({ children, tinuuid, apiKey, appClipBundleId, arExperience, apiBaseUrl, legacyApiBaseUrl, mode, initialWidgetSessionToken, handoffUrl, hid, launchAr, layout, background, sizeType, viewerSurface }) {
|
|
6845
|
+
function ModelViewerProvider({ children, tinuuid, apiKey, appClipBundleId, arExperience, apiBaseUrl, legacyApiBaseUrl, mode, initialWidgetSessionToken, handoffUrl, hid, launchAr, layout, background, sizeType, dimensionAxes, cameraOrbit, minCameraOrbit, maxCameraOrbit, viewerSurface }) {
|
|
6820
6846
|
const { object, material, error, isLoading, setMaterialHid: setObjectMaterialHid, widgetSession } = useObjectData(tinuuid, hid, {
|
|
6821
6847
|
apiBaseUrl,
|
|
6822
6848
|
apiKey,
|
|
@@ -6944,6 +6970,10 @@ function ModelViewerProvider({ children, tinuuid, apiKey, appClipBundleId, arExp
|
|
|
6944
6970
|
background,
|
|
6945
6971
|
mode,
|
|
6946
6972
|
sizeType,
|
|
6973
|
+
dimensionAxes,
|
|
6974
|
+
cameraOrbit,
|
|
6975
|
+
minCameraOrbit,
|
|
6976
|
+
maxCameraOrbit,
|
|
6947
6977
|
isLoading,
|
|
6948
6978
|
isModelLoading,
|
|
6949
6979
|
state,
|
|
@@ -6970,6 +7000,10 @@ function ModelViewerProvider({ children, tinuuid, apiKey, appClipBundleId, arExp
|
|
|
6970
7000
|
background,
|
|
6971
7001
|
mode,
|
|
6972
7002
|
sizeType,
|
|
7003
|
+
dimensionAxes,
|
|
7004
|
+
cameraOrbit,
|
|
7005
|
+
minCameraOrbit,
|
|
7006
|
+
maxCameraOrbit,
|
|
6973
7007
|
isLoading,
|
|
6974
7008
|
isModelLoading,
|
|
6975
7009
|
state,
|
|
@@ -6989,6 +7023,11 @@ function useModelViewer() {
|
|
|
6989
7023
|
if (!context) throw new Error('useModelViewer must be used within a ModelViewerProvider');
|
|
6990
7024
|
return context;
|
|
6991
7025
|
}
|
|
7026
|
+
function resolveDirectArExperience(mode, arExperience) {
|
|
7027
|
+
if ('ar-view' === mode) return 'standard';
|
|
7028
|
+
if ('advanced-ar-view' === mode || 'ar-viewer' === mode || 'embedded-3d-viewer' === mode) return 'advanced';
|
|
7029
|
+
if ('qr-code' === mode) return arExperience;
|
|
7030
|
+
}
|
|
6992
7031
|
function getUserAgent() {
|
|
6993
7032
|
if ("u" < typeof navigator) return '';
|
|
6994
7033
|
return navigator.userAgent || navigator.vendor || '';
|
|
@@ -7008,7 +7047,7 @@ function isSupportedAppClipDevice() {
|
|
|
7008
7047
|
if (!isIOSDevice()) return false;
|
|
7009
7048
|
const versionText = getUserAgent().match(/\bOS (\d+)/)?.[1] ?? getUserAgent().match(/Version\/(\d+)/)?.[1];
|
|
7010
7049
|
if (!versionText) return false;
|
|
7011
|
-
return Number.parseInt(versionText, 10) >=
|
|
7050
|
+
return Number.parseInt(versionText, 10) >= 18;
|
|
7012
7051
|
}
|
|
7013
7052
|
function buildAppClipUrl(bundleId, tinuuid, hostname, hid) {
|
|
7014
7053
|
const url = new URL('https://appclip.apple.com/id');
|
|
@@ -7023,8 +7062,13 @@ function buildNativeArUrl(glbUrl, usdzUrl, objectType, ios = isIOSDevice()) {
|
|
|
7023
7062
|
const verticalPlacement = 'wall' === objectType || 'ceiling' === objectType ? '&enable_vertical_placement=true' : '';
|
|
7024
7063
|
return `intent://arvr.google.com/scene-viewer/1.0?file=${encodeURIComponent(new URL(glbUrl).toString())}&resizable=false${verticalPlacement}&mode=ar_preferred#Intent;scheme=https;package=com.google.android.googlequicksearchbox;action=android.intent.action.VIEW;end;`;
|
|
7025
7064
|
}
|
|
7026
|
-
function launchDirectAr(options) {
|
|
7027
|
-
if ('advanced' === options.experience && isSupportedAppClipDevice())
|
|
7065
|
+
function launchDirectAr(options, openAppClipInNewTab = false) {
|
|
7066
|
+
if ('advanced' === options.experience && isSupportedAppClipDevice()) {
|
|
7067
|
+
const appClipUrl = buildAppClipUrl(options.appClipBundleId, options.tinuuid, options.hostname, options.hid);
|
|
7068
|
+
if (openAppClipInNewTab) window.open(appClipUrl, '_blank');
|
|
7069
|
+
else window.location.assign(appClipUrl);
|
|
7070
|
+
return;
|
|
7071
|
+
}
|
|
7028
7072
|
const link = document.createElement('a');
|
|
7029
7073
|
const image = document.createElement('img');
|
|
7030
7074
|
link.rel = 'ar';
|
|
@@ -7093,7 +7137,7 @@ function AR({ disabled, onClick, onBeforeActivateAr, size = 'lg', ...props }) {
|
|
|
7093
7137
|
object?.tinuuid,
|
|
7094
7138
|
tinuuid
|
|
7095
7139
|
]);
|
|
7096
|
-
const directArExperience =
|
|
7140
|
+
const directArExperience = resolveDirectArExperience(mode, arExperience);
|
|
7097
7141
|
const directArLaunchOptions = external_react_useMemo(()=>{
|
|
7098
7142
|
const native = material?.native;
|
|
7099
7143
|
if (!directArExperience || !object || !native?.glbUrl || !native.usdzUrl || "u" < typeof window) return null;
|
|
@@ -7171,6 +7215,11 @@ function AR({ disabled, onClick, onBeforeActivateAr, size = 'lg', ...props }) {
|
|
|
7171
7215
|
if (await launchArOverride(launchAr, arTarget)) return void onBeforeActivateAr?.();
|
|
7172
7216
|
if (directArLaunchOptions && isMobileArDevice()) {
|
|
7173
7217
|
onBeforeActivateAr?.();
|
|
7218
|
+
if ('advanced' === directArLaunchOptions.experience && isSupportedAppClipDevice()) {
|
|
7219
|
+
launchDirectAr(directArLaunchOptions, true);
|
|
7220
|
+
trackEvent('ar_launched');
|
|
7221
|
+
return;
|
|
7222
|
+
}
|
|
7174
7223
|
await flushWidgetEvent(trackEvent('ar_launched'));
|
|
7175
7224
|
launchDirectAr(directArLaunchOptions);
|
|
7176
7225
|
} else if (modelViewerEl.canActivateAR) {
|
|
@@ -7371,6 +7420,10 @@ const DIMENSION_LABEL_CONFIGS = [
|
|
|
7371
7420
|
}
|
|
7372
7421
|
];
|
|
7373
7422
|
const DIMENSION_LABEL_SLOTS = DIMENSION_LABEL_CONFIGS.map((config)=>config.slot);
|
|
7423
|
+
const DIMENSION_LABEL_AXIS_BY_SLOT = new Map(DIMENSION_LABEL_CONFIGS.map((config)=>[
|
|
7424
|
+
config.slot,
|
|
7425
|
+
config.sizeAxis
|
|
7426
|
+
]));
|
|
7374
7427
|
const LINE_CONNECTIONS = [
|
|
7375
7428
|
{
|
|
7376
7429
|
lineIndex: 0,
|
|
@@ -7414,7 +7467,7 @@ const Hotspots = /*#__PURE__*/ memo(({ hiddenHotspots, isVisible, labels })=>{
|
|
|
7414
7467
|
children: HOTSPOT_CONFIGS.map((hotspot)=>{
|
|
7415
7468
|
const isDimensionLabel = hotspot.isDimensionLabel;
|
|
7416
7469
|
const labelData = labelsMap.get(hotspot.slot);
|
|
7417
|
-
const isHidden = !isVisible || !isDimensionLabel || hiddenHotspots.has(hotspot.slot);
|
|
7470
|
+
const isHidden = !isVisible || !isDimensionLabel || !labelData || hiddenHotspots.has(hotspot.slot);
|
|
7418
7471
|
return /*#__PURE__*/ jsx(button_Button, {
|
|
7419
7472
|
slot: hotspot.slot,
|
|
7420
7473
|
"data-position": hotspot.position,
|
|
@@ -7677,9 +7730,9 @@ function getHotspotConfig(slot) {
|
|
|
7677
7730
|
if (!config) throw new Error(`Missing hotspot config for slot "${slot}"`);
|
|
7678
7731
|
return config;
|
|
7679
7732
|
}
|
|
7680
|
-
function createDimensionLabels(modelViewerEl, sizeType) {
|
|
7733
|
+
function createDimensionLabels(modelViewerEl, sizeType, axes) {
|
|
7681
7734
|
const info = calculateBoundingBoxInfo(modelViewerEl);
|
|
7682
|
-
return DIMENSION_LABEL_CONFIGS.map(({ slot, sizeAxis, offsetMultiplier })=>{
|
|
7735
|
+
return DIMENSION_LABEL_CONFIGS.filter(({ sizeAxis })=>axes.includes(sizeAxis)).map(({ slot, sizeAxis, offsetMultiplier })=>{
|
|
7683
7736
|
const hotspotConfig = getHotspotConfig(slot);
|
|
7684
7737
|
return {
|
|
7685
7738
|
name: slot,
|
|
@@ -7696,7 +7749,7 @@ function syncLabelHotspots(modelViewerEl, labels) {
|
|
|
7696
7749
|
});
|
|
7697
7750
|
});
|
|
7698
7751
|
}
|
|
7699
|
-
function useDimensions({ isVisible }) {
|
|
7752
|
+
function useDimensions({ isVisible, axes }) {
|
|
7700
7753
|
const { glbUrl, isModelLoading, modelViewerEl, sizeType } = useModelViewer();
|
|
7701
7754
|
const [lines, setLines] = useState([]);
|
|
7702
7755
|
const [labels, setLabels] = useState([]);
|
|
@@ -7714,7 +7767,7 @@ function useDimensions({ isVisible }) {
|
|
|
7714
7767
|
]);
|
|
7715
7768
|
const calculateLabels = useCallback(()=>{
|
|
7716
7769
|
if (!modelViewerEl) return [];
|
|
7717
|
-
const dimensionLabels = createDimensionLabels(modelViewerEl, sizeType);
|
|
7770
|
+
const dimensionLabels = createDimensionLabels(modelViewerEl, sizeType, axes);
|
|
7718
7771
|
syncLabelHotspots(modelViewerEl, dimensionLabels);
|
|
7719
7772
|
return dimensionLabels.map((label)=>({
|
|
7720
7773
|
slot: label.name,
|
|
@@ -7723,13 +7776,16 @@ function useDimensions({ isVisible }) {
|
|
|
7723
7776
|
}));
|
|
7724
7777
|
}, [
|
|
7725
7778
|
modelViewerEl,
|
|
7726
|
-
sizeType
|
|
7779
|
+
sizeType,
|
|
7780
|
+
axes
|
|
7727
7781
|
]);
|
|
7728
7782
|
const updateLines = useCallback(()=>{
|
|
7729
7783
|
if (!modelViewerEl) return;
|
|
7730
7784
|
const newLines = [];
|
|
7731
7785
|
const hidden = new Set();
|
|
7732
7786
|
LINE_CONNECTIONS.forEach((connection)=>{
|
|
7787
|
+
const connectionAxis = connection.dimensionHotspot ? DIMENSION_LABEL_AXIS_BY_SLOT.get(connection.dimensionHotspot) : void 0;
|
|
7788
|
+
if (connectionAxis && !axes.includes(connectionAxis)) return;
|
|
7733
7789
|
const dotHotspot1 = modelViewerEl.queryHotspot(connection.hotspot1);
|
|
7734
7790
|
const dotHotspot2 = modelViewerEl.queryHotspot(connection.hotspot2);
|
|
7735
7791
|
const dimensionHotspot = connection.dimensionHotspot ? modelViewerEl.queryHotspot(connection.dimensionHotspot) : null;
|
|
@@ -7751,7 +7807,8 @@ function useDimensions({ isVisible }) {
|
|
|
7751
7807
|
setLines(newLines);
|
|
7752
7808
|
setHiddenHotspots((current)=>areSetsEqual(current, hidden) ? current : hidden);
|
|
7753
7809
|
}, [
|
|
7754
|
-
modelViewerEl
|
|
7810
|
+
modelViewerEl,
|
|
7811
|
+
axes
|
|
7755
7812
|
]);
|
|
7756
7813
|
useEffect(()=>{
|
|
7757
7814
|
if (!glbUrl || !isVisible || !isReady || !modelViewerEl || initializedSrc === glbUrl) return;
|
|
@@ -7796,7 +7853,7 @@ function useDimensions({ isVisible }) {
|
|
|
7796
7853
|
};
|
|
7797
7854
|
}
|
|
7798
7855
|
function ModelViewerContainer({ showDialogCloseButton = false }) {
|
|
7799
|
-
const { glbUrl, isModelLoading, object, previewUrl, state, setContainerEl, setModelViewerEl, usdzUrl, layout, background, trackEvent } = useModelViewer();
|
|
7856
|
+
const { glbUrl, isModelLoading, object, previewUrl, state, setContainerEl, setModelViewerEl, usdzUrl, layout, background, dimensionAxes, cameraOrbit, minCameraOrbit, maxCameraOrbit, trackEvent } = useModelViewer();
|
|
7800
7857
|
const [isDimensionsVisible, setDimensionsVisible] = useState(false);
|
|
7801
7858
|
const isModelLayout = 'model' === layout;
|
|
7802
7859
|
const showViewerLoader = 'loading' === state || 'ready' === state && isModelLoading;
|
|
@@ -7805,7 +7862,8 @@ function ModelViewerContainer({ showDialogCloseButton = false }) {
|
|
|
7805
7862
|
const canToggleDimensions = showControls && !isModelLayout && !isModelLoading;
|
|
7806
7863
|
const isDimensionsActive = isDimensionsVisible && canToggleDimensions;
|
|
7807
7864
|
const { lines, labels, hiddenHotspots } = useDimensions({
|
|
7808
|
-
isVisible: isDimensionsActive
|
|
7865
|
+
isVisible: isDimensionsActive,
|
|
7866
|
+
axes: dimensionAxes
|
|
7809
7867
|
});
|
|
7810
7868
|
const errorState = 'forbidden' === state || 'not-found' === state || 'unauthorized' === state || 'payment-required' === state ? state : null;
|
|
7811
7869
|
if (errorState) return /*#__PURE__*/ jsx("div", {
|
|
@@ -7833,6 +7891,9 @@ function ModelViewerContainer({ showDialogCloseButton = false }) {
|
|
|
7833
7891
|
poster: previewUrl ?? void 0,
|
|
7834
7892
|
ar: true,
|
|
7835
7893
|
cameraControls: true,
|
|
7894
|
+
cameraOrbit: cameraOrbit,
|
|
7895
|
+
minCameraOrbit: minCameraOrbit,
|
|
7896
|
+
maxCameraOrbit: maxCameraOrbit,
|
|
7836
7897
|
arModes: "webxr scene-viewer quick-look",
|
|
7837
7898
|
arScale: "fixed",
|
|
7838
7899
|
shadowIntensity: 1,
|
|
@@ -7911,6 +7972,11 @@ function ModelViewerContainer({ showDialogCloseButton = false }) {
|
|
|
7911
7972
|
function normalizeApiKey(apiKey) {
|
|
7912
7973
|
return apiKey?.trim() ?? '';
|
|
7913
7974
|
}
|
|
7975
|
+
const ALL_DIMENSION_AXES = [
|
|
7976
|
+
'x',
|
|
7977
|
+
'y',
|
|
7978
|
+
'z'
|
|
7979
|
+
];
|
|
7914
7980
|
const root_queryClient = new QueryClient({
|
|
7915
7981
|
defaultOptions: {
|
|
7916
7982
|
queries: {
|
|
@@ -7926,7 +7992,7 @@ const root_queryClient = new QueryClient({
|
|
|
7926
7992
|
}
|
|
7927
7993
|
}
|
|
7928
7994
|
});
|
|
7929
|
-
function ModelViewerRoot({ tinuuid, apiKey, appClipBundleId = 'com.us.vizbl.Clip', arExperience, hid, apiBaseUrl = "https://api.vizbl.com", legacyApiBaseUrl = "https://api.vizbl.com/v1", mode = 'embedded-3d-viewer', initialWidgetSessionToken, handoffUrl = "https://integrations.vizbl.com/model-viewer", launchAr, sizeType = 'cm', layout = 'default', background = 'default', showDialogCloseButton = false, viewerSurface = 'inline' }) {
|
|
7995
|
+
function ModelViewerRoot({ tinuuid, apiKey, appClipBundleId = 'com.us.vizbl.Clip', arExperience, hid, apiBaseUrl = "https://api.vizbl.com", legacyApiBaseUrl = "https://api.vizbl.com/v1", mode = 'embedded-3d-viewer', initialWidgetSessionToken, handoffUrl = "https://integrations.vizbl.com/model-viewer", launchAr, sizeType = 'cm', dimensionAxes = ALL_DIMENSION_AXES, cameraOrbit, minCameraOrbit, maxCameraOrbit, layout = 'default', background = 'default', showDialogCloseButton = false, viewerSurface = 'inline' }) {
|
|
7930
7996
|
const normalizedApiKey = normalizeApiKey(apiKey);
|
|
7931
7997
|
return /*#__PURE__*/ jsx(QueryClientProvider, {
|
|
7932
7998
|
client: root_queryClient,
|
|
@@ -7945,6 +8011,10 @@ function ModelViewerRoot({ tinuuid, apiKey, appClipBundleId = 'com.us.vizbl.Clip
|
|
|
7945
8011
|
layout: layout,
|
|
7946
8012
|
background: background,
|
|
7947
8013
|
sizeType: sizeType,
|
|
8014
|
+
dimensionAxes: dimensionAxes,
|
|
8015
|
+
cameraOrbit: cameraOrbit,
|
|
8016
|
+
minCameraOrbit: minCameraOrbit,
|
|
8017
|
+
maxCameraOrbit: maxCameraOrbit,
|
|
7948
8018
|
viewerSurface: viewerSurface,
|
|
7949
8019
|
children: /*#__PURE__*/ jsx(ModelViewerContainer, {
|
|
7950
8020
|
showDialogCloseButton: showDialogCloseButton
|
|
@@ -7952,7 +8022,7 @@ function ModelViewerRoot({ tinuuid, apiKey, appClipBundleId = 'com.us.vizbl.Clip
|
|
|
7952
8022
|
})
|
|
7953
8023
|
});
|
|
7954
8024
|
}
|
|
7955
|
-
function ModelViewerDialog({ tinuuid, apiKey, apiBaseUrl, legacyApiBaseUrl, initialWidgetSessionToken, handoffUrl, hid, sizeType, ...props }) {
|
|
8025
|
+
function ModelViewerDialog({ tinuuid, apiKey, apiBaseUrl, legacyApiBaseUrl, initialWidgetSessionToken, handoffUrl, hid, sizeType, dimensionAxes, ...props }) {
|
|
7956
8026
|
const [container, setContainer] = useState(null);
|
|
7957
8027
|
return /*#__PURE__*/ jsxs(Fragment, {
|
|
7958
8028
|
children: [
|
|
@@ -7993,6 +8063,7 @@ function ModelViewerDialog({ tinuuid, apiKey, apiBaseUrl, legacyApiBaseUrl, init
|
|
|
7993
8063
|
handoffUrl: handoffUrl,
|
|
7994
8064
|
hid: hid,
|
|
7995
8065
|
sizeType: sizeType,
|
|
8066
|
+
dimensionAxes: dimensionAxes,
|
|
7996
8067
|
showDialogCloseButton: true,
|
|
7997
8068
|
viewerSurface: "dialog"
|
|
7998
8069
|
})
|
|
@@ -8018,7 +8089,7 @@ function ModelViewerDialog({ tinuuid, apiKey, apiBaseUrl, legacyApiBaseUrl, init
|
|
|
8018
8089
|
]
|
|
8019
8090
|
});
|
|
8020
8091
|
}
|
|
8021
|
-
function ModelViewer({ tinuuid, apiKey, appClipBundleId, arExperience, hid, apiBaseUrl, legacyApiBaseUrl, mode, initialWidgetSessionToken, handoffUrl, launchAr, sizeType, layout, background, viewerSurface, className, ...props }) {
|
|
8092
|
+
function ModelViewer({ tinuuid, apiKey, appClipBundleId, arExperience, hid, apiBaseUrl, legacyApiBaseUrl, mode, initialWidgetSessionToken, handoffUrl, launchAr, sizeType, dimensionAxes, layout, background, viewerSurface, className, ...props }) {
|
|
8022
8093
|
const [container, setContainer] = useState(null);
|
|
8023
8094
|
return /*#__PURE__*/ jsxs(Fragment, {
|
|
8024
8095
|
children: [
|
|
@@ -8059,6 +8130,7 @@ function ModelViewer({ tinuuid, apiKey, appClipBundleId, arExperience, hid, apiB
|
|
|
8059
8130
|
hid: hid,
|
|
8060
8131
|
launchAr: launchAr,
|
|
8061
8132
|
sizeType: sizeType,
|
|
8133
|
+
dimensionAxes: dimensionAxes,
|
|
8062
8134
|
layout: layout,
|
|
8063
8135
|
background: background,
|
|
8064
8136
|
viewerSurface: viewerSurface
|