@liveroom-tech/react-immersive 4.3.0 → 5.0.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.
Files changed (46) hide show
  1. package/README.md +697 -83
  2. package/dist/ModelViewer-CbbJT85n.d.mts +448 -0
  3. package/dist/ModelViewer-DOexHkJC.d.ts +448 -0
  4. package/dist/binding-builder.css +1 -0
  5. package/dist/binding-builder.d.mts +6 -0
  6. package/dist/binding-builder.d.ts +6 -0
  7. package/dist/binding-builder.js +3694 -0
  8. package/dist/binding-builder.mjs +1 -0
  9. package/dist/chunk-7EW6JZ46.mjs +27 -0
  10. package/dist/chunk-BGYK4Y2Y.mjs +1 -0
  11. package/dist/chunk-MMO7KCYU.mjs +3 -0
  12. package/dist/chunk-NVY7N7CU.mjs +3 -0
  13. package/dist/chunk-SEESCGUS.mjs +1 -0
  14. package/dist/chunk-WFEYRUZC.mjs +1 -0
  15. package/dist/chunk-XTLSAYAQ.mjs +1 -0
  16. package/dist/hosted.css +1 -1
  17. package/dist/hosted.d.mts +33 -13
  18. package/dist/hosted.d.ts +33 -13
  19. package/dist/hosted.js +11 -8
  20. package/dist/hosted.mjs +1 -1
  21. package/dist/index.css +1 -1
  22. package/dist/index.d.mts +107 -83
  23. package/dist/index.d.ts +107 -83
  24. package/dist/index.js +11 -8
  25. package/dist/index.mjs +1 -1
  26. package/dist/modelInfo-CEmmvVCH.d.mts +17 -0
  27. package/dist/modelInfo-CEmmvVCH.d.ts +17 -0
  28. package/dist/{objectBinding-CBRYMYk6.d.ts → objectCatalog-5W8n5xNQ.d.mts} +55 -3
  29. package/dist/{objectBinding-CBRYMYk6.d.mts → objectCatalog-5W8n5xNQ.d.ts} +55 -3
  30. package/dist/publicProps-tJuWZgT3.d.mts +12 -0
  31. package/dist/publicProps-tJuWZgT3.d.ts +12 -0
  32. package/dist/simple-model-viewer.css +1 -0
  33. package/dist/simple-model-viewer.d.mts +38 -0
  34. package/dist/simple-model-viewer.d.ts +38 -0
  35. package/dist/simple-model-viewer.js +3666 -0
  36. package/dist/simple-model-viewer.mjs +1 -0
  37. package/dist/utils.d.mts +49 -3
  38. package/dist/utils.d.ts +49 -3
  39. package/dist/utils.js +1 -1
  40. package/dist/utils.mjs +1 -1
  41. package/package.json +28 -18
  42. package/dist/chunk-7X37KAPE.mjs +0 -1
  43. package/dist/chunk-GYB4BOVW.mjs +0 -26
  44. package/dist/chunk-K7DMBJBJ.mjs +0 -1
  45. package/dist/publicProps-BST1E8an.d.mts +0 -349
  46. package/dist/publicProps-Bv3_PCP0.d.ts +0 -349
package/dist/index.mjs CHANGED
@@ -1 +1 @@
1
- "use client";import{a as he,b as Ne,c as Ce,d as ze,e as ln,f as He}from"./chunk-7X37KAPE.mjs";import{a as nt,b as rt,c as it,d as ot,e as at,f as st,g as lt,h as ct,i as dt,j as pt,k as ut,l as gt,m as ft,n as mt,o as rn,p as on,q as bt}from"./chunk-GYB4BOVW.mjs";import{h as nn,i as ee,j as an,k as sn}from"./chunk-K7DMBJBJ.mjs";import"./chunk-JR557W27.mjs";var ht={licenseKey:!0,dracoDecoderPath:!0,ktx2TranscoderPath:!0,meshopt:!0},vt={licenseValidationUrl:!0,onObjectEditLeaseChange:!0};function wt(e,t){let n={};for(let r of Object.keys(t))r in e&&(n[r]=e[r]);return n}function yt(e,t){let n={...e};for(let r of Object.keys(t))delete n[r];return n}import{jsx as cn}from"react/jsx-runtime";function xt(e){return cn(mt,{...yt(e,vt)})}import{jsx as dn}from"react/jsx-runtime";function Ct(e){return dn(bt,{...wt(e,ht)})}import{useRef as ge,useState as K,useCallback as J,useEffect as te,useMemo as Re,Component as pn,Suspense as Fe}from"react";import{CameraControls as un,Environment as gn}from"@react-three/drei";import{useFrame as Rt,useThree as Se}from"@react-three/fiber";import{Canvas as fn}from"@react-three/fiber";import{Box3 as mn,MeshStandardMaterial as bn,PerspectiveCamera as hn,Vector3 as vn}from"three";import{SkeletonUtils as wn}from"three-stdlib";import{X as Xe,Check as Bt,Settings as yn,ChevronDown as xn,Boxes as Cn,Trash2 as Sn,Upload as Ke,AlertTriangle as Vn}from"lucide-react";import{Fragment as jt,jsx as s,jsxs as E}from"react/jsx-runtime";var St={color:"#93c5fd",intensity:.05},Mn=["apartment","city","dawn","forest","lobby","night","park","studio","sunset","warehouse"];function On(e){return!!(e&&"isMesh"in e&&e.isMesh)}function Vt(e,t){Array.isArray(e)?e.forEach(t):t(e)}function jn(e,t){if(!t)return;let n=t.camera;if(!(n instanceof hn))return;let r=new mn().setFromObject(e).getSize(new vn).length();!Number.isFinite(r)||r<=0||(n.near=r/100,n.far=r*100,n.updateProjectionMatrix(),t.maxDistance=r*10)}var $e=class extends pn{constructor(){super(...arguments);this.state={hasError:!1}}static getDerivedStateFromError(){return{hasError:!0}}componentDidCatch(n){this.props.onLoadError?.(n)}render(){return this.state.hasError?null:this.props.children}};function Rn({url:e,format:t,dracoDecoderPath:n,ktx2TranscoderPath:r,meshopt:a,hiddenKeys:v,selectedKey:f,panelHoveredKey:S,nodeRefsOut:w,onMeshesReady:j,onModelLoaded:M,onLoadProgress:R,onMeshClick:A,highlightOnHover:y}){let{scene:B}=dt(e,{dracoDecoderPath:n,ktx2TranscoderPath:r,meshopt:a},t,R),T=Se(l=>l.invalidate),{setCanvasCursor:F,restoreCanvasCursor:u}=gt(),[V,_]=K(null),x=Re(()=>wn.clone(B),[B]),I=Re(()=>{let l={};return x.traverse(b=>{if(!On(b))return;let k=b.name||b.uuid;l[k]={key:k,label:b.name||b.type,ref:b}}),l},[x]),H=Re(()=>{let l={};for(let[b,{ref:k}]of Object.entries(I)){let U=(Array.isArray(k.material)?k.material:[k.material]).map(D=>{let i=(pt(D)??new bn).clone();return i.userData.baseColor=i.color.clone(),i.userData.baseMap=i.map,i.userData.baseEmissive=i.emissive.clone(),i.userData.baseEmissiveMap=i.emissiveMap,i.userData.baseEmissiveIntensity=i.emissiveIntensity,i});l[b]=Array.isArray(k.material)?U:U[0]}return l},[I]);te(()=>()=>{Object.values(H).forEach(l=>Vt(l,b=>b.dispose()))},[H]);let c=ge(null);te(()=>{c.current!==e&&(c.current=e,x.updateWorldMatrix(!0,!0),ut(x),j(I),M(x))},[e,x,I,j,M]),te(()=>{let l=new AbortController;return ot(x,l.signal),()=>{l.abort(),at(x)}},[x]);let m=Re(()=>!rt(x),[x]);te(()=>{for(let[l,{ref:b}]of Object.entries(I))w.current[l]=b},[I,w]),te(()=>{!y&&V!==null&&(_(null),u())},[y,V,u]),te(()=>{for(let[l,{ref:b}]of Object.entries(I)){b.visible=!v.has(l);let k=H[l];if(!k)continue;b.material=k;let q=y&&V===l,U=y&&S===l;Vt(k,D=>{if(D.color.copy(D.userData.baseColor),D.map=D.userData.baseMap??null,D.emissive.copy(D.userData.baseEmissive),D.emissiveMap=D.userData.baseEmissiveMap??null,D.emissiveIntensity=D.userData.baseEmissiveIntensity,U||q){let de=!!D.userData.baseEmissiveMap;D.emissive.set(St.color),D.emissiveIntensity=de?D.userData.baseEmissiveIntensity:St.intensity}D.needsUpdate=!0})}T()},[I,H,V,f,S,y,v,T]);let p=l=>{let b=l;for(;b;){let k=b.name||b.uuid;if(I[k])return k;b=b.parent}return null},C=m?{onClick:l=>{let b=p(l.object);b&&(l.stopPropagation(),A(b))},...y?{onPointerOver:l=>{let b=p(l.object);b&&(l.stopPropagation(),F("pointer"),_(b))},onPointerOut:l=>{l.stopPropagation(),u(),_(null)}}:{}}:{};return s("primitive",{object:x,...C})}function Bn({scene:e,controlsRef:t,refitOnResize:n,onInitialFitComplete:r}){let a=ge(!1),v=Se(w=>w.invalidate),f=Se(w=>w.size),S=ge(null);return te(()=>{a.current=!1,v()},[v,e]),Rt(()=>{if(!a.current){if(!e||!t.current){v();return}a.current=!0,jn(e,t.current),t.current.fitToBox(e,!0,{paddingTop:.5,paddingBottom:.5,paddingLeft:.5,paddingRight:.5}).catch(()=>{}).finally(r)}}),te(()=>{if(!(!n||!a.current||!e||!t.current))return S.current&&clearTimeout(S.current),S.current=setTimeout(()=>{t.current?.fitToBox(e,!0,{paddingTop:.5,paddingBottom:.5,paddingLeft:.5,paddingRight:.5}).catch(()=>{}),v()},150),()=>{S.current&&clearTimeout(S.current)}},[f.width,f.height,n]),null}function _n({exposure:e}){let t=Se(r=>r.gl),n=Se(r=>r.invalidate);return te(()=>{t.toneMappingExposure=e,n()},[t,e,n]),null}function kn({enabled:e,controlsRef:t}){let n=Se(r=>r.invalidate);return Rt((r,a)=>{!e||!t.current||(t.current.rotate(a*.2,0,!1),n())}),null}function Be(e){return Array.from(e.types).includes("Files")}function Mt({label:e,checked:t,onChange:n}){return E("div",{className:"env-row",children:[s("span",{className:"env-row__label",children:e}),s("div",{className:"env-row__value",children:s("button",{className:"env-checkbox-btn",onClick:()=>n(!t),children:s("span",{className:`env-checkbox${t?" env-checkbox--checked":""}`,children:t&&s(Bt,{size:9,strokeWidth:2,color:"white"})})})})]})}function Ue({label:e,value:t,onChange:n}){return E("div",{className:"env-row",children:[s("span",{className:"env-row__label",children:e}),s("div",{className:"env-row__value",children:E("div",{className:"env-color-swatch",style:{background:t},children:[s("span",{className:"env-color-swatch__hex",children:t}),s("input",{type:"color",className:"env-color-swatch__input",value:t,onChange:r=>n(r.target.value)})]})})]})}function We({label:e,value:t,min:n,max:r,step:a,onChange:v}){return E("div",{className:"env-row",children:[s("span",{className:"env-row__label",children:e}),E("div",{className:"env-row__value env-row__value--slider",children:[s("input",{type:"range",className:"env-slider",min:n,max:r,step:a,value:t,onChange:f=>v(Number(f.target.value))}),s("span",{className:"env-slider__value",children:t.toFixed(2)})]})]})}function En({label:e,value:t,options:n,onChange:r}){return E("div",{className:"env-row",children:[s("span",{className:"env-row__label",children:e}),s("div",{className:"env-row__value",children:s("select",{className:"env-select",value:t,onChange:a=>r(a.target.value),children:n.map(a=>s("option",{value:a,children:a},a))})})]})}function Ot({title:e,children:t}){let[n,r]=K(!1);return E("div",{className:"env-section",children:[E("button",{className:"env-section__header",onClick:()=>r(a=>!a),children:[s(xn,{size:12,strokeWidth:2,className:`env-section__chevron${n?" env-section__chevron--collapsed":""}`}),s("span",{children:e})]}),!n&&s("div",{className:"env-section__body",children:t})]})}function Pn({isOpen:e,onToggle:t,settings:n,onChange:r}){return E("div",{className:`left-panel-wrapper ${e?"left-panel-wrapper--open":"left-panel-wrapper--closed"}`,children:[!e&&s("button",{className:"side-panel__open-btn side-panel__open-btn--left",onClick:()=>t(!0),children:s(yn,{size:20,strokeWidth:1.8})}),E("div",{className:`side-panel side-panel--left ${e?"side-panel--open-left":"side-panel--closed-left"}`,"aria-hidden":!e,children:[s("div",{className:"side-panel__header",children:E("div",{className:"side-panel__header-top",children:[s("span",{className:"side-panel__eyebrow",children:"Scene Settings"}),s("button",{className:"side-panel__close-btn",onClick:()=>t(!1),title:"Close",children:s(Xe,{size:12,strokeWidth:1.6})})]})}),E("div",{className:"env-controls",children:[E(Ot,{title:"Background",children:[s(Mt,{label:"Background",checked:n.backgroundEnabled,onChange:a=>r("backgroundEnabled",a)}),s(Ue,{label:"Background Color",value:n.backgroundColor,onChange:a=>r("backgroundColor",a)}),s(En,{label:"Environment",value:n.envPreset,options:Mn,onChange:a=>r("envPreset",a)}),s(Mt,{label:"Auto Rotate",checked:n.autoRotate,onChange:a=>r("autoRotate",a)})]}),E(Ot,{title:"Lighting",children:[s(We,{label:"Exposure",value:n.exposure,min:0,max:2,step:.05,onChange:a=>r("exposure",a)}),s(We,{label:"Ambient Light Intensity",value:n.ambientIntensity,min:0,max:3,step:.05,onChange:a=>r("ambientIntensity",a)}),s(Ue,{label:"Ambient Light Color",value:n.ambientColor,onChange:a=>r("ambientColor",a)}),s(We,{label:"Direct Light Intensity",value:n.directionalIntensity,min:0,max:5,step:.05,onChange:a=>r("directionalIntensity",a)}),s(Ue,{label:"Direct Light Color",value:n.directionalColor,onChange:a=>r("directionalColor",a)})]})]})]})]})}function Tn({meshKeys:e,hiddenKeys:t,selectedKey:n,isOpen:r,onToggle:a,onFocus:v,onHover:f,onToggleVisibility:S}){let[w,j]=K(""),[M,R]=K(null),A=Object.values(e).filter(y=>y.label.toLowerCase().includes(w.toLowerCase()));return E("div",{className:`right-panel-wrapper ${r?"right-panel-wrapper--open":"right-panel-wrapper--closed"}`,children:[!r&&s("button",{className:"side-panel__open-btn",onClick:()=>a(!0),children:s(Cn,{size:20,strokeWidth:1.8})}),E("div",{className:`side-panel ${r?"side-panel--open":"side-panel--closed"}`,"aria-hidden":!r,children:[E("div",{className:"side-panel__header",children:[E("div",{className:"side-panel__header-top",children:[s("span",{className:"side-panel__eyebrow",children:"SCENE OBJECTS"}),s("button",{className:"side-panel__close-btn",onClick:()=>a(!1),title:"Close",children:s(Xe,{size:12,strokeWidth:1.6})})]}),E("p",{className:"side-panel__title",children:[A.length," objects"]})]}),s("div",{className:"side-panel__search-wrap",children:s("input",{className:"side-panel__search",type:"text",placeholder:"Search objects",value:w,onChange:y=>j(y.target.value)})}),s("div",{className:"side-panel__list",children:A.map(({key:y,label:B})=>{let T=!t.has(y),F=n===y,u=M===y;return E("div",{onClick:()=>v(y),onMouseEnter:()=>{R(y),f(y)},onMouseLeave:()=>{R(null),f(null)},className:["side-panel__row",u?"side-panel__row--hovered":"",F?"side-panel__row--selected":""].filter(Boolean).join(" "),children:[s("span",{className:`side-panel__label${u||F?" side-panel__label--hovered":""}`,children:B}),s("button",{className:"side-panel__vis-btn",title:T?"Hide":"Show",onClick:V=>{V.stopPropagation(),S(y)},children:s("span",{className:`side-panel__checkbox${T?" side-panel__checkbox--checked":""}`,children:T&&s(Bt,{size:9,strokeWidth:5,color:"white"})})})]},y)})})]})]})}function _t({modelUrl:e,modelFormat:t,dracoDecoderPath:n,ktx2TranscoderPath:r,meshopt:a=!0,backgroundColor:v="#1a1a1a",showSceneObjectsPanel:f=!0,showSceneSettingsPanel:S=!0,enableModelUpload:w=!1,zoomOnSelected:j=!1,highlightOnHover:M=!1,showLoadingOverlay:R=!0,refitOnResize:A=!0,backgroundEnabled:y=!1,autoRotate:B=!1,envPreset:T="city",exposure:F=1,ambientIntensity:u=.6,ambientColor:V="#ffffff",directionalIntensity:_=1.2,directionalColor:x="#ffffff",onModelLoaded:I,onLoadError:H}){let c=ge(null),m=ge({}),p=ge(null),C=ge(null),l=ge(0),[b,k]=K(null),[q,U]=K(null),[D,de]=K(!1),[i,o]=K({}),[g,d]=K(new Set),[O,L]=K(null),[P,N]=K(null),[Y,G]=K(null),[pe,se]=K(null),[re,W]=K(!1),[Q,le]=K(!1),[ce,me]=K(!1),[oe,ve]=K(null),[Ae,be]=K(!1),[ie,Le]=K(()=>typeof window>"u"?!0:window.innerWidth>900),[je,Kt]=K(()=>typeof window>"u"?!0:window.innerWidth>900),[Z,Ie]=K({backgroundEnabled:y,backgroundColor:v,autoRotate:B,envPreset:T,exposure:F,ambientIntensity:u,ambientColor:V,directionalIntensity:_,directionalColor:x}),ue=w?Y:e,we=J(()=>{k(null),U(null),de(!1),o({}),d(new Set),L(null),N(null),W(!1),me(!1),ve(null)},[]),ye=J(()=>{C.current?.cleanup(),C.current=null},[]),Ut=J(()=>{ye(),G(null),se(null),we(),Ie({backgroundEnabled:y,backgroundColor:v,autoRotate:B,envPreset:T,exposure:F,ambientIntensity:u,ambientColor:V,directionalIntensity:_,directionalColor:x})},[V,u,B,v,y,x,_,T,F,we,ye]),et=J(async h=>{le(!0);try{let $=await ct(h);ye(),C.current=$,G($.url),se($.name),we()}catch($){W(!0),H?.($)}finally{le(!1)}},[H,we,ye]),De=J(h=>{let $=h?.[0];$&&et($)},[et]);te(()=>()=>{ye()},[ye]);let Wt=J((h,$)=>{Ie(xe=>({...xe,[h]:$}))},[]);te(()=>{Ie(h=>({...h,backgroundColor:v}))},[v]),te(()=>{we()},[ue,we]);let $t=J(h=>{o(h),d(new Set),L(null)},[]),Xt=J(h=>{k(h),W(!1);let $=it(h);U($>nt?$:null),de(!1),ve(null),I?.(h)},[I]),Gt=J(h=>{W(!0),ve(null),H?.(h)},[H]),qt=J(h=>{h.lengthComputable&&h.total>0&&ve(h.loaded/h.total*100)},[]),tt=J(h=>{if(L(h),!j)return;let $=m.current[h];!$||!c.current||c.current.fitToBox($,!0,{paddingTop:.5,paddingBottom:.5,paddingLeft:.5,paddingRight:.5}).catch(()=>{})},[j]),Jt=J(h=>{d($=>{let xe=new Set($);return xe.has(h)?xe.delete(h):xe.add(h),xe})},[]),Yt=J(h=>{!w||!Be(h.dataTransfer)||(h.preventDefault(),h.stopPropagation(),l.current+=1,be(!0))},[w]),Qt=J(h=>{!w||!Be(h.dataTransfer)||(h.preventDefault(),h.stopPropagation(),h.dataTransfer.dropEffect="copy",be(!0))},[w]),Zt=J(h=>{!w||!Be(h.dataTransfer)||(h.preventDefault(),h.stopPropagation(),l.current=Math.max(0,l.current-1),l.current===0&&be(!1))},[w]),en=J(h=>{!w||!Be(h.dataTransfer)||(h.preventDefault(),h.stopPropagation(),l.current=0,be(!1),De(h.dataTransfer.files))},[w,De]),tn=R&&(Q||!!(ue&&!re&&(!b||!ce)));return E("div",{className:"smv-root",style:{background:Z.backgroundColor},onDragEnter:Yt,onDragOver:Qt,onDragLeave:Zt,onDrop:en,children:[S&&ue&&s(Pn,{isOpen:je,onToggle:Kt,settings:Z,onChange:Wt}),E("div",{className:"smv-canvasArea",children:[q!==null&&!D&&E("div",{className:"smv-largeModelBanner",children:[s(Vn,{size:14,className:"smv-largeModelBanner__icon"}),E("span",{children:["Very large model detected (",Math.round(q/1e6),"M triangles) \u2014 it may render and move slowly on this device, and click/hover selection on the model is disabled. Use the scene objects panel to select parts."]}),s("button",{type:"button",className:"smv-largeModelBanner__dismiss",onClick:()=>de(!0),"aria-label":"Dismiss",children:s(Xe,{size:12})})]}),w?E(jt,{children:[s("input",{ref:p,type:"file",accept:lt,className:"smv-upload-input",onChange:h=>{De(h.target.files),h.currentTarget.value=""}}),ue?s("div",{className:"smv-upload-toolbar",children:E(jt,{children:[s("span",{className:"smv-upload-toolbar__name",children:pe??"Uploaded model"}),E("button",{type:"button",className:"smv-upload-toolbar__button smv-upload-toolbar__button--ghost",onClick:Ut,children:[s(Sn,{size:14}),"Clear"]})]})}):null]}):null,ue?s(fn,{dpr:[1,2],frameloop:"demand",resize:{debounce:0,scroll:!1},raycaster:{firstHitOnly:!0},style:{background:Z.backgroundColor},camera:{position:[0,0,5],fov:45,near:.1,far:1e3},children:E(Fe,{fallback:null,children:[s("ambientLight",{intensity:Z.ambientIntensity,color:Z.ambientColor}),s("directionalLight",{position:[-4,5,7],intensity:Z.directionalIntensity,color:Z.directionalColor,castShadow:!0}),s("directionalLight",{position:[-5,5,5],intensity:.5}),s(Fe,{fallback:null,children:s(gn,{preset:Z.envPreset,background:Z.backgroundEnabled})}),s(_n,{exposure:Z.exposure}),s(kn,{enabled:Z.autoRotate,controlsRef:c}),s($e,{onLoadError:Gt,children:s(Fe,{fallback:null,children:s(Rn,{url:ue,format:Y?void 0:t,dracoDecoderPath:n,ktx2TranscoderPath:r,meshopt:a,hiddenKeys:g,selectedKey:O,panelHoveredKey:P,nodeRefsOut:m,onMeshesReady:$t,onModelLoaded:Xt,onLoadProgress:qt,onMeshClick:tt,highlightOnHover:M})})},ue),s(Bn,{scene:b,controlsRef:c,refitOnResize:A,onInitialFitComplete:()=>me(!0)}),s(un,{ref:c,makeDefault:!0,smoothTime:.3})]})}):s("div",{className:"smv-upload-empty-state",style:{background:Z.backgroundColor},children:E("div",{className:"smv-upload-empty-state__card",children:[s("div",{className:"smv-upload-empty-state__icon",children:s(Ke,{size:24})}),E("p",{className:"smv-upload-empty-state__body",children:["Drag and drop ",s("code",{children:".glb"}),", ",s("code",{children:".gltf"}),","," ",s("code",{children:".obj"}),", ",s("code",{children:".fbx"}),", ",s("code",{children:".usdz"}),", or"," ",s("code",{children:".zip"})," here"]}),E("button",{type:"button",className:"smv-upload-empty-state__button",onClick:()=>p.current?.click(),children:[s(Ke,{size:15}),"Choose model"]})]})}),s(ft,{visible:tn,message:"Loading model...",progress:Q?void 0:oe??void 0}),w&&Ae?s("div",{className:"smv-upload-drop-overlay",children:E("div",{className:"smv-upload-drop-overlay__card",children:[s(Ke,{size:20}),s("span",{children:"Release to load your model"})]})}):null]}),f&&ue&&s(Tn,{meshKeys:i,hiddenKeys:g,selectedKey:O,isOpen:ie,onToggle:Le,onFocus:tt,onHover:N,onToggleVisibility:Jt})]})}import{useCallback as kt,useState as An}from"react";function Ln(e=null){let[t,n]=An(e),r=kt(v=>{n(v)},[n]),a=kt(()=>{n(null)},[]);return{selectedObjectBinding:t,setSelectedObjectBinding:n,handleObjectSelect:r,clearSelection:a}}import{useMemo as In}from"react";function Dn(e,t){return In(()=>{if(!t)return null;let n=e[t];return n||(Object.values(e).find(r=>r.id===t||r.modelObjectId===t)??null)},[e,t])}import{useMemo as Nn}from"react";function zn(e){return Nn(()=>Object.values(e).map(t=>t.modelObjectId),[e])}import{useCallback as X,useMemo as Et,useState as Hn}from"react";var Pt={baseColor:"texture",metalness:"metalnessMap",roughness:"roughnessMap",emissive:"emissiveMap",alpha:"alphaMap",normal:"normalMap",bump:"bumpMap",ao:"aoMap",displacement:"displacementMap",clearcoat:"clearcoatMap",clearcoatRoughness:"clearcoatRoughnessMap",clearcoatNormal:"clearcoatNormalMap",anisotropy:"anisotropyMap",transmission:"transmissionMap",thickness:"thicknessMap",sheenColor:"sheenColorMap",sheenRoughness:"sheenRoughnessMap",specularIntensity:"specularIntensityMap",specularColor:"specularColorMap"};function Tt(e){if(e)return Object.fromEntries(Object.entries(e).map(([t,n])=>[t,n&&typeof n=="object"?{...n}:n]))}function Fn(e){return Object.fromEntries(Object.entries(e).filter(([,t])=>t.visible===!1).map(([t])=>[t,!0]))}function Kn(e){let[t,n]=Hn(e),r=X((c,m)=>{n(p=>m===void 0?Ce(p,c):Ce(p,c,m))},[]),a=X((c,m)=>r(c,ze(m)),[r]),v=X((c,m)=>a(c,{baseColor:m}),[a]),f=X((c,m,p="baseColor")=>{let C=Pt[p],l=typeof m=="string"?{path:m}:m;r(c,{style:{material:{[C]:l}}})},[r]),S=X((c,m="baseColor")=>{let p=Pt[m];r(c,{style:{material:{[p]:void 0}}})},[r]),w=X((c,m)=>{n(p=>{let C=ee(p,c);if(!C)return p;let l=Tt(p[C]?.style?.material),b=he(p,m);if(b.length===0)return p;let k=p;for(let q of b){let U=p[q];U&&(k===p&&(k={...p}),k[q]={...U,style:{...U.style,material:Tt(l)}})}return k})},[]),j=X(c=>r(c,{style:{material:void 0}}),[r]),M=X((c,m)=>r(c,{transform:m}),[r]),R=X(c=>r(c,{transform:void 0}),[r]),A=X((c,m)=>r(c,{metadata:m}),[r]),y=X(c=>Ne(t,c),[t]),B=X(c=>he(t,c).map(m=>t[m]?.id??m),[t]),T=X(c=>{let m=ee(t,c);return m?t[m]?.style?.material??null:null},[t]),F=X(c=>r(c,{visible:!1}),[r]),u=X(c=>r(c,{visible:!0}),[r]),V=X(c=>{n(m=>{let p=he(m,c).reduce((C,l)=>{let b=m[l];return b&&C.push({ids:l,patch:{visible:b.visible===!1}}),C},[]);return Ce(m,p)})},[n]),_=X(()=>{n(c=>Ce(c,Object.keys(c),{visible:!0}))},[n]),x=Et(()=>Fn(t),[t]),I=Et(()=>Object.keys(x).map(c=>t[c]?.id??c),[x,t]),H=X(c=>{let m=ee(t,c);return m?t[m]?.visible===!1:!1},[t]);return{objectBindings:t,setObjectBindings:n,updateObjectBindings:r,setMaterial:a,setBaseColor:v,setTexture:f,clearTexture:S,copyMaterial:w,resetMaterial:j,getMaterial:T,setTransform:M,resetTransform:R,updateMetadata:A,selectObjectBindings:y,selectObjectBindingIds:B,hiddenObjects:x,hiddenObjectIds:I,hideObject:F,showObject:u,toggleObjectVisibility:V,isObjectHidden:H,clearHiddenObjects:_}}import{useCallback as ne,useMemo as Un,useRef as Wn,useState as $n}from"react";var Xn={type:"point",color:"#ffffff",intensity:1,position:[0,0,0],distance:0,decay:2,attachedToCamera:!1,castShadow:!1,shadowBias:-5e-4,visible:!0};function Gn(e){let t=Wn(null),[n,r]=$n(()=>{let u=typeof e=="function"?e():e;return t.current=u,u}),a=ne(u=>{r(V=>{let _=typeof u=="function"?u(V):u;return He(V,_)})},[]),v=ne(()=>{let u=t.current;u&&r(u)},[]),f=ne((u,V)=>{a(_=>({lighting:{lights:_.lighting.lights.map(x=>x.id===u?{...x,...V}:x)}}))},[a]),S=ne(u=>{a(V=>V.lighting.lights.some(_=>_.id===u.id)?{}:{lighting:{lights:[...V.lighting.lights,{...Xn,...u}]}})},[a]),w=ne(u=>{a(V=>({lighting:{lights:V.lighting.lights.filter(_=>_.id!==u)}}))},[a]),j=ne((u,V)=>f(u,{intensity:V}),[f]),M=ne((u,V)=>f(u,{color:V}),[f]),R=ne(u=>f(u,{visible:!0}),[f]),A=ne(u=>f(u,{visible:!1}),[f]),y=ne(u=>{a(V=>({lighting:{lights:V.lighting.lights.map(_=>_.id===u?{..._,visible:!_.visible}:_)}}))},[a]),B=ne((u,V)=>f(u,{attachment:V,attachedToCamera:!1}),[f]),T=ne(u=>f(u,{attachment:void 0}),[f]),F=Un(()=>({items:n.lighting.lights,get:u=>n.lighting.lights.find(V=>V.id===u),add:S,update:f,remove:w,setIntensity:j,setColor:M,show:R,hide:A,toggle:y,attach:B,detach:T}),[n.lighting.lights,S,f,w,j,M,R,A,y,B,T]);return{sceneConfig:n,setSceneConfig:r,updateSceneConfig:a,resetSceneConfig:v,lights:F}}import{useCallback as qn,useState as Jn}from"react";function Yn(){let[e,t]=Jn(null),n=qn(r=>{t(r)},[t]);return{hoveredObjectBinding:e,handleHoveredObject:n}}import{useCallback as Ge,useState as Me}from"react";import{Box3 as Qn,Vector3 as At}from"three";function _e(e){return[e.x,e.y,e.z]}function Zn(){let[e,t]=Me(!0),[n,r]=Me(!1),[a,v]=Me(null),[f,S]=Me(null),[w,j]=Me(0),M=Ge(y=>{let B=new Qn().setFromObject(y),T=B.min.clone(),F=B.max.clone(),u=new At,V=new At,_=0;y.traverse(x=>{"isMesh"in x&&x.isMesh&&(_+=1)}),B.getCenter(u),B.getSize(V),S({min:_e(T),max:_e(F),center:_e(u),size:_e(V)}),j(_),v(null),t(!1),r(!0)},[]),R=Ge(y=>{v(y),S(null),j(0),t(!1),r(!1)},[]),A=Ge(()=>{t(!0),r(!1),v(null),S(null),j(0)},[]);return{isLoading:e,isReady:n,error:a,bounds:f,objectCount:w,handleModelLoaded:M,handleLoadError:R,resetModelState:A}}import{useCallback as qe}from"react";function er({bindings:e,scene:t,camera:n,animations:r,onAction:a}){let{objectBindings:v,updateObjectBindings:f,showObject:S,hideObject:w,toggleObjectVisibility:j}=e,M=t?.updateSceneConfig,R=n?.focusObject,A=n?.fitScene,y=n?.resetView,B=n?.setCameraTarget,T=n?.setCameraState,F=r?.play,u=r?.pause,V=r?.stop,_=r?.setSpeed,x=r?.seek,I=qe(m=>{let p=ee(v,m);return p?v[p]?.actions??[]:[]},[v]),H=qe(async m=>{for(let p of m.action.effects??[]){if("objectBindings"in p){f(p.target,p.objectBindings);continue}if("sceneConfig"in p){M?.(p.sceneConfig);continue}if("visibility"in p){p.visibility==="show"?S(p.target):p.visibility==="hide"?w(p.target):j(p.target);continue}if("camera"in p){let l=p.camera;l.type==="focus-object"?await R?.(l.objectId??m.objectId):l.type==="fit-scene"?await A?.():l.type==="reset"?await y?.():l.type==="set-target"?await B?.(l.target,l.transition??!0):await T?.(l.state,l.transition??!0);continue}let C=p.animation;C.type==="play"?F?.(C.clip):C.type==="pause"?u?.():C.type==="stop"?V?.():C.type==="set-speed"?_?.(C.speed):x?.(C.time)}await a?.(m)},[A,R,w,a,u,F,y,x,_,T,B,S,V,j,f,M]),c=qe(async(m,p)=>{let C=ee(v,m);if(!C)return null;let l=v[C],b=l?.actions?.find(q=>q.id===p);if(!l||!b)return null;let k={objectId:C,action:b,binding:l};return await H(k),k},[H,v]);return{getActionsForObject:I,handleAction:H,runAction:c}}import{useCallback as ke,useRef as Lt}from"react";function tr(e){return typeof e=="function"?e:e?.handleViewerReady??null}function nr(...e){let t=Lt(null),n=Lt(e);n.current=e;let r=ke(S=>{t.current=S;let w=new Set;for(let j of n.current){let M=tr(j);M&&!w.has(M)&&(w.add(M),M(S))}},[]),a=ke(()=>t.current,[]),v=ke(S=>{let w=t.current;return w?w.captureImage(S):Promise.reject(new Error("ModelViewer is not ready yet."))},[]),f=ke(()=>{let S=t.current;return S?(S.invalidate(),!0):!1},[]);return{handleViewerReady:r,getViewer:a,captureImage:v,invalidate:f}}import{useCallback as z,useEffect as rr,useRef as ae}from"react";import{Material as ir,PointLight as or,Vector3 as ar}from"three";var Qe=["emissiveIntensity","opacity","metalness","roughness","transmission","clearcoat","clearcoatRoughness","ior","thickness"],Ee=1;function Pe(e){return typeof e=="string"?[e]:e}function Te(e,t=0,n=1){return Math.min(n,Math.max(t,e))}function Je(e,t){return e+Math.random()*(t-e)}function It([e,t],n){return e+(t-e)*n}function Ye([e,t],n){return[e[0]+(t[0]-e[0])*n,e[1]+(t[1]-e[1])*n,e[2]+(t[2]-e[2])*n]}function Dt(e,t){let n=Te(e);switch(t){case"ease-in":return n*n;case"ease-out":return 1-(1-n)*(1-n);case"ease-in-out":return n<.5?2*n*n:1-Math.pow(-2*n+2,2)/2;default:return n}}function sr(e){let t=e.material;return t?(Array.isArray(t)?t:[t]).filter(n=>n instanceof ir):[]}function lr(e){let t={opacity:e.opacity,transparent:e.transparent};e.color&&(t.baseColor=`#${e.color.getHexString()}`),e.emissive&&(t.emissive=`#${e.emissive.getHexString()}`);for(let n of Qe){let r=e[n];typeof r=="number"&&(t[n]=r)}return t}function Nt(e,t){t.baseColor!==void 0&&e.color&&e.color.set(t.baseColor),t.emissive!==void 0&&e.emissive&&e.emissive.set(t.emissive);for(let n of Qe){let r=t[n];r!==void 0&&typeof e[n]=="number"&&(e[n]=r)}t.transparent!==void 0&&(e.transparent=t.transparent),e.needsUpdate=!0}function cr(e){return{position:[e.position.x,e.position.y,e.position.z],rotation:[e.rotation.x,e.rotation.y,e.rotation.z],scale:[e.scale.x,e.scale.y,e.scale.z],visible:e.visible}}function dr(e,t){if(t.position&&e.position.set(...t.position),t.rotation&&e.rotation.set(...t.rotation),t.scale!==void 0){let n=typeof t.scale=="number"?[t.scale,t.scale,t.scale]:t.scale;e.scale.set(...n)}t.visible!==void 0&&(e.visible=t.visible),e.updateMatrix(),e.updateMatrixWorld(!0)}function pr(e={}){let t=ae(e);t.current=e;let n=ae(null),r=ae(null),a=ae(null),v=ae(new Map),f=ae(new Map),S=ae(new Map),w=ae(new Map),j=z(i=>{let o=n.current;if(!o)return null;let g=ee(o.objectBindings,i);return o.nodeRefs[i]??(g?o.nodeRefs[g]:null)??(o.scene?st(o.scene,i):null)??null},[]),M=z(i=>{let o=n.current;return o?typeof i=="object"&&!Array.isArray(i)?he(o.objectBindings,i):Pe(i).map(g=>ee(o.objectBindings,g)??g):typeof i=="string"?[i]:Array.isArray(i)?i:[]},[]),R=z(()=>{n.current?.invalidate()},[]),A=z((i,o)=>{let g=!1;for(let d of M(i)){let O=j(d);if(O)for(let L of sr(O))S.current.has(L)||S.current.set(L,lr(L)),Nt(L,o),g=!0}return g},[j,M]),y=z((i,o)=>{let g=A(i,o);return g&&R(),g},[R,A]),B=z((i,o)=>{let g=!1;for(let d of M(i)){let O=j(d);O&&(w.current.has(O)||w.current.set(O,cr(O)),dr(O,o),g=!0)}return g},[j,M]),T=z((i,o)=>{let g=B(i,o);return g&&R(),g},[R,B]),F=z(i=>{let o=j(i);if(!o)return null;o.updateWorldMatrix(!0,!1);let g=o.getWorldPosition(new ar);return[g.x,g.y,g.z]},[j]),u=z(i=>{let o=f.current.get(i);return o?(o.light.removeFromParent(),o.light.dispose(),f.current.delete(i),R(),!0):!1},[R]),V=z(i=>{let o=j(i.target);if(!o)return!1;let g=f.current.get(i.id),d=g?.light??new or;return g&&g.target!==i.target&&d.removeFromParent(),d.name=`react-immersive-runtime-light:${i.id}`,d.color.set(i.color??"#ffffff"),d.intensity=i.intensity??1,d.distance=i.distance??0,d.decay=i.decay??2,d.castShadow=i.castShadow??!1,d.position.set(...i.offset??[0,0,0]),d.parent!==o&&o.add(d),f.current.set(i.id,{light:d,target:i.target}),R(),!0},[R,j]),_=z((i,o)=>{let g=f.current.get(i);if(!g)return!1;if(o.target&&o.target!==g.target){let d=j(o.target);if(!d)return!1;g.light.removeFromParent(),d.add(g.light),g.target=o.target}return o.color!==void 0&&g.light.color.set(o.color),o.intensity!==void 0&&(g.light.intensity=o.intensity),o.distance!==void 0&&(g.light.distance=o.distance),o.decay!==void 0&&(g.light.decay=o.decay),o.offset!==void 0&&g.light.position.set(...o.offset),o.castShadow!==void 0&&(g.light.castShadow=o.castShadow),R(),!0},[R,j]),x=z((i,o)=>{let g=d=>o[d%o.length]??0;for(let d of i.materials??[])M(d.targets).forEach((O,L)=>{let P=g(L),N={};for(let Y of Qe){let G=d.values[Y];G&&(N[Y]=It(G,P))}A(O,N)});for(let d of i.transforms??[])M(d.targets).forEach((O,L)=>{let P=g(L),N={};d.values.position&&(N.position=Ye(d.values.position,P)),d.values.rotation&&(N.rotation=Ye(d.values.rotation,P)),d.values.scale&&(N.scale=Ye(d.values.scale,P)),B(O,N)});for(let d of i.lights??[])Pe(d.lights).forEach((O,L)=>{let P=f.current.get(O);P&&(P.light.intensity=It(d.intensity,g(L)))})},[M,A,B]),I=ae(()=>{}),H=ae(()=>{});H.current=i=>{a.current=null;let o=!1;for(let[g,d]of v.current){d.startedAt===null&&(d.startedAt=i);let O=d.lastFrameAt??i;d.lastFrameAt=i;let L=d.override&&d.override.until>i?d.override.level:null;d.override&&L===null&&(d.override=null);let P=d.update(i,i-d.startedAt,Math.min(100,i-O),L);o=!0,P||(v.current.delete(g),d.onComplete?.())}o&&R(),v.current.size>0&&I.current()},I.current=()=>{a.current!==null||typeof requestAnimationFrame>"u"||(a.current=requestAnimationFrame(i=>H.current(i)))};let c=z(i=>(v.current.set(i.id,i),I.current(),i.id),[]),m=z((i,o={})=>{let g=o.id??`transition-${Ee++}`,d=Math.max(1,o.duration??400),O=o.easing??"ease-in-out";return c({id:g,startedAt:null,lastFrameAt:null,override:null,onComplete:o.onComplete,update:(L,P,N,Y)=>{let G=Y??Dt(P/d,O);return x(i,[G]),P<d}})},[x,c]),p=z((i,o={})=>{let g=o.id??`pulse-${Ee++}`,d=Math.max(1,o.duration??1e3),O=o.minLevel??0,L=o.maxLevel??1,P=o.repeat??1/0,N=o.synchronized??!0,Y=Math.max(1,...[...i.materials??[],...i.transforms??[]].map(G=>M(G.targets).length),...(i.lights??[]).map(G=>Pe(G.lights).length));return c({id:g,startedAt:null,lastFrameAt:null,override:null,onComplete:o.onComplete,update:(G,pe,se,re)=>{let W=pe/d,Q=Array.from({length:N?1:Y},(le,ce)=>{if(re!==null)return re;let me=W+(N?0:ce/Y),oe=.5-Math.cos(me%1*Math.PI*2)/2;return O+(L-O)*oe});return x(i,Q),P===1/0||W<P}})},[x,c,M]),C=z((i,o={})=>{let g=o.id??`timeline-${Ee++}`,d=o.repeat??1,O=i.map(P=>({...P,duration:Math.max(1,P.duration),hold:Math.max(0,P.hold??0)})),L=Math.max(1,O.reduce((P,N)=>P+N.duration+N.hold,0));return c({id:g,startedAt:null,lastFrameAt:null,override:null,onComplete:o.onComplete,update:(P,N,Y,G)=>{if(O.length===0||d<=0)return!1;let pe=N/L;if(d!==1/0&&pe>=d){for(let W of O)x(W.channels,[1]);return!1}let se=N%L,re=0;for(let W of O){let Q=re+W.duration,le=Q+W.hold;if(se>=Q){x(W.channels,[G??1]),re=le;continue}if(se>=re){let ce=G??Dt((se-re)/W.duration,W.easing??"ease-in-out");x(W.channels,[ce]);break}}return!0}})},[x,c]),l=z((i,o={})=>{let g=o.id??`flicker-${Ee++}`,d=o.synchronized??!0,O=o.minLevel??.15,L=o.maxLevel??1,P=o.interval??[45,160],N=typeof P=="number"?[P,P]:P,Y=[Math.max(1,Math.min(...N)),Math.max(1,Math.max(...N))],G=Te(o.response??.7,.01,1),pe=Te(o.blackoutChance??.08),se=Te(o.flashChance??.12),re=o.flashLevel??1.15,W=Math.max(1,...[...i.materials??[],...i.transforms??[]].map(oe=>M(oe.targets).length),...(i.lights??[]).map(oe=>Pe(oe.lights).length)),Q=d?1:W,le=Array.from({length:Q},()=>O),ce=Array.from({length:Q},()=>O),me=Array.from({length:Q},()=>0);return c({id:g,startedAt:null,lastFrameAt:null,override:null,onComplete:o.onComplete,update:(oe,ve,Ae,be)=>{for(let ie=0;ie<Q;ie+=1){if(be!==null)ce[ie]=be;else if(oe>=me[ie]){let je=Math.random();ce[ie]=je<pe?Je(0,Math.min(.04,O)):je<pe+se?re:Je(O,L),me[ie]=oe+Je(...Y)}let Le=1-Math.pow(1-G,Math.max(1,Ae)/16.67);le[ie]+=(ce[ie]-le[ie])*Le}return x(i,le),o.duration===void 0||ve<o.duration}})},[x,c,M]),b=z((i,o,g)=>{let d=v.current.get(i);if(!d)return!1;let O=typeof performance>"u"?Date.now():performance.now();return d.override={level:o,until:O+Math.max(0,g)},I.current(),!0},[]),k=z(i=>v.current.delete(i),[]),q=z(()=>{v.current.clear(),a.current!==null&&typeof cancelAnimationFrame<"u"&&(cancelAnimationFrame(a.current),a.current=null)},[]),U=z(()=>{for(let[i,o]of S.current)Nt(i,o);S.current.clear();for(let[i,o]of w.current)i.position.set(...o.position),i.rotation.set(...o.rotation),i.scale.set(...o.scale),i.visible=o.visible,i.updateMatrix(),i.updateMatrixWorld(!0);w.current.clear();for(let i of f.current.values())i.light.removeFromParent(),i.light.dispose();f.current.clear(),R()},[R]),D=z(()=>{q(),U()},[U,q]),de=z(i=>{r.current&&r.current!==i.scene&&U(),n.current=i,r.current=i.scene,t.current.onViewerReady?.(i)},[U]);return rr(()=>()=>{D(),n.current=null,r.current=null},[D]),{handleViewerReady:de,setMaterial:y,setTransform:T,getWorldPosition:F,addPointLight:V,updatePointLight:_,removePointLight:u,transition:m,timeline:C,pulse:p,flicker:l,overrideEffect:b,stopEffect:k,stopAllEffects:q,resetRuntime:D}}import{useCallback as Ve,useEffect as Ze,useRef as fe,useState as ur}from"react";function Ft(e){return typeof e=="object"&&e!==null&&!Array.isArray(e)}function Oe(e){return typeof e=="number"&&Number.isFinite(e)}function zt(e){return Array.isArray(e)&&e.length===3&&e.every(Oe)}function gr(e){return!Ft(e)||!zt(e.position)||!zt(e.target)||e.fov!==null&&!Oe(e.fov)||!Oe(e.zoom)||e.zoom<=0||e.azimuthAngle!==void 0&&!Oe(e.azimuthAngle)||e.polarAngle!==void 0&&!Oe(e.polarAngle)?null:{position:e.position,target:e.target,fov:e.fov,zoom:e.zoom,azimuthAngle:e.azimuthAngle,polarAngle:e.polarAngle}}function fr(e){if(!Ft(e))return null;let t;if(e.camera!==void 0){let a=gr(e.camera);if(!a)return null;t=a}let n;if(e.hidden!==void 0){if(!Array.isArray(e.hidden)||!e.hidden.every(a=>typeof a=="string"))return null;n=e.hidden}let r;if(e.selected===null||typeof e.selected=="string")r=e.selected;else if(e.selected!==void 0)return null;return{camera:t,hidden:n,selected:r}}function Ht(e,t,n){let r=Object.values(t).filter(a=>a.visible===!1).map(a=>a.id);return{camera:e??void 0,hidden:r,selected:n?.id??null}}function mr({cameraState:e,setCameraState:t,objectBindings:n,onObjectBindingsChange:r,selectedObjectBinding:a,setSelectedObjectBinding:v,paramKey:f="view",debounceMs:S=400,autoSync:w=!0}){let j=fe(null),M=fe(null),R=fe(null),A=fe(null),y=fe(null),B=Ve(()=>{y.current!==null&&(window.clearTimeout(y.current),y.current=null),R.current=null,A.current=null},[]),T=Ve(()=>{let p=Ht(e,n,a);return`${f}=${encodeURIComponent(JSON.stringify(p))}`},[e,n,a,f]),F=Ve(()=>{let p=new URL(window.location.href);return p.hash=T(),p.toString()},[T]),u=Ve(p=>{let C=new URL(window.location.href);C.hash=p,window.history.replaceState(null,"",C.toString()),M.current=p,j.current=new URLSearchParams(C.hash.slice(1)).get(f)},[f]),V=Ve(()=>{B(),u(T())},[T,B,u]),_=fe({cameraState:e,objectBindings:n,selectedObjectBinding:a});_.current={cameraState:e,objectBindings:n,selectedObjectBinding:a};let[x,I]=ur(!1);Ze(()=>{if(!w||!x){B();return}let p=_.current,C=Ht(p.cameraState,p.objectBindings,p.selectedObjectBinding),l=`${f}=${encodeURIComponent(JSON.stringify(C))}`;if(l===M.current){B();return}l===R.current&&S===A.current||(B(),R.current=l,A.current=S,y.current=window.setTimeout(()=>{y.current=null,R.current=null,A.current=null,u(l)},Math.max(0,S)))},[w,e,B,S,n,f,x,a,u]),Ze(()=>B,[B]);let H=fe(null),c=fe(null),m=Ve(async()=>{I(!0);let p=window.location.hash.startsWith("#")?window.location.hash.slice(1):window.location.hash,C=new URLSearchParams(p).get(f);if(!C)return H.current=null,!1;if(C===j.current||C===H.current||C===c.current)return!1;let l;try{l=JSON.parse(C)}catch{return!1}let b=fr(l);if(!b)return!1;c.current=C;try{if(b.camera&&await t(b.camera,!1),b.hidden){let k=new Set(b.hidden);r(Object.fromEntries(Object.entries(n).map(([q,U])=>[q,{...U,visible:!k.has(U.id)}])))}if(b.selected!==void 0){let k=b.selected?ee(n,b.selected):null;v(k?n[k]:null)}return H.current=C,!0}finally{c.current===C&&(c.current=null)}},[n,r,f,t,v]);return Ze(()=>{let p=()=>{m().catch(()=>{})};return window.addEventListener("hashchange",p),()=>{window.removeEventListener("hashchange",p)}},[m]),{getShareUrl:F,syncUrl:V,restoreFromUrl:m}}export{Ct as BindingBuilder,nn as DEFAULT_SCENE_CONFIG,sn as MATERIAL_BLENDING_MODES,an as MATERIAL_SIDES,xt as ModelViewer,_t as SimpleModelViewer,ln as defineObjectBindings,ze as material,Ce as patchBindings,He as patchSceneConfig,he as selectBindingKeys,Ne as selectBindings,Dn as useObjectBinding,zn as useObjectBindingIds,Kn as useObjectBindings,Gn as useSceneConfig,mr as useShareableViewerState,er as useViewerActions,on as useViewerAnimations,rn as useViewerCamera,nr as useViewerConnection,pr as useViewerEffects,Yn as useViewerHover,Zn as useViewerModel,Ln as useViewerSelection};
1
+ "use client";import{b as De,d as Ne}from"./chunk-SEESCGUS.mjs";import{a as ze}from"./chunk-MMO7KCYU.mjs";import{a as ee,b as we,c as re,d as ye,e as Ve,f as Ce,g as gt}from"./chunk-WFEYRUZC.mjs";import{b as at,j as he,r as _e,s as Oe}from"./chunk-7EW6JZ46.mjs";import"./chunk-XTLSAYAQ.mjs";import{a as ct,c as lt,g as N,o as le,r as Ue,t as dt,u as ut,v as ft,w as Fe,y as mt,z as pt}from"./chunk-BGYK4Y2Y.mjs";import"./chunk-JR557W27.mjs";import{jsx as bt}from"react/jsx-runtime";function We(e){return ze("model-viewer","ModelViewer"),bt(_e,{...Ne(e,De)})}import{useCallback as pe,useRef as Ze}from"react";import{useCallback as k,useMemo as $e,useState as ht}from"react";var Ke={baseColor:"texture",metalness:"metalnessMap",roughness:"roughnessMap",emissive:"emissiveMap",alpha:"alphaMap",normal:"normalMap",bump:"bumpMap",ao:"aoMap",displacement:"displacementMap",clearcoat:"clearcoatMap",clearcoatRoughness:"clearcoatRoughnessMap",clearcoatNormal:"clearcoatNormalMap",anisotropy:"anisotropyMap",transmission:"transmissionMap",thickness:"thicknessMap",sheenColor:"sheenColorMap",sheenRoughness:"sheenRoughnessMap",specularIntensity:"specularIntensityMap",specularColor:"specularColorMap"};function Ge(e){if(e)return Object.fromEntries(Object.entries(e).map(([t,r])=>[t,r&&typeof r=="object"?{...r}:r]))}function wt(e){return Object.fromEntries(Object.entries(e).filter(([,t])=>t.visible===!1).map(([t])=>[t,!0]))}function je(e){let[t,r]=ht(e),s=k((o,u)=>{r(a=>u===void 0?re(a,o):re(a,o,u))},[]),d=k((o,u)=>s(o,ye(u)),[s]),b=k((o,u)=>d(o,{baseColor:u}),[d]),g=k((o,u,a="baseColor")=>{let m=Ke[a],O=typeof u=="string"?{path:u}:u;s(o,{style:{material:{[m]:O}}})},[s]),p=k((o,u="baseColor")=>{let a=Ke[u];s(o,{style:{material:{[a]:void 0}}})},[s]),j=k((o,u)=>{r(a=>{let m=N(a,o);if(!m)return a;let O=Ge(a[m]?.style?.material),L=ee(a,u);if(L.length===0)return a;let U=a;for(let $ of L){let W=a[$];W&&(U===a&&(U={...a}),U[$]={...W,style:{...W.style,material:Ge(O)}})}return U})},[]),V=k(o=>s(o,{style:{material:void 0}}),[s]),y=k((o,u)=>s(o,{transform:u}),[s]),h=k(o=>s(o,{transform:void 0}),[s]),x=k((o,u)=>s(o,{metadata:u}),[s]),A=k(o=>we(t,o),[t]),v=k(o=>ee(t,o).map(u=>t[u]?.id??u),[t]),I=k(o=>{let u=N(t,o);return u?t[u]?.style?.material??null:null},[t]),E=k(o=>s(o,{visible:!1}),[s]),f=k(o=>s(o,{visible:!0}),[s]),C=k(o=>{r(u=>{let a=ee(u,o).reduce((m,O)=>{let L=u[O];return L&&m.push({ids:O,patch:{visible:L.visible===!1}}),m},[]);return re(u,a)})},[r]),M=k(()=>{r(o=>re(o,Object.keys(o),{visible:!0}))},[r]),B=$e(()=>wt(t),[t]),D=$e(()=>Object.keys(B).map(o=>t[o]?.id??o),[B,t]),H=k(o=>{let u=N(t,o);return u?t[u]?.visible===!1:!1},[t]);return{objectBindings:t,setObjectBindings:r,updateObjectBindings:s,setMaterial:d,setBaseColor:b,setTexture:g,clearTexture:p,copyMaterial:j,resetMaterial:V,getMaterial:I,setTransform:y,resetTransform:h,updateMetadata:x,selectObjectBindings:A,selectObjectBindingIds:v,hiddenObjects:B,hiddenObjectIds:D,hideObject:E,showObject:f,toggleObjectVisibility:C,isObjectHidden:H,clearHiddenObjects:M}}import{useCallback as z,useMemo as yt,useRef as Vt,useState as Ct}from"react";function Se(e){let t=Vt(null),[r,s]=Ct(()=>{let f=typeof e=="function"?e():e;return t.current=f,f}),d=z(f=>{s(C=>{let M=typeof f=="function"?f(C):f;return Ve(C,M)})},[]),b=z(()=>{let f=t.current;f&&s(f)},[]),g=z((f,C)=>{d(M=>({lighting:{lights:M.lighting.lights.map(B=>B.id===f?{...B,...C}:B)}}))},[d]),p=z(f=>{d(C=>C.lighting.lights.some(M=>M.id===f.id)?{}:{lighting:{lights:[...C.lighting.lights,Ce(f)]}})},[d]),j=z(f=>{d(C=>({lighting:{lights:C.lighting.lights.filter(M=>M.id!==f)}}))},[d]),V=z((f,C)=>g(f,{intensity:C}),[g]),y=z((f,C)=>g(f,{color:C}),[g]),h=z(f=>g(f,{visible:!0}),[g]),x=z(f=>g(f,{visible:!1}),[g]),A=z(f=>{d(C=>({lighting:{lights:C.lighting.lights.map(M=>M.id===f?{...M,visible:!M.visible}:M)}}))},[d]),v=z((f,C)=>g(f,{attachment:C,attachedToCamera:!1}),[g]),I=z(f=>g(f,{attachment:void 0}),[g]),E=yt(()=>({items:r.lighting.lights,get:f=>r.lighting.lights.find(C=>C.id===f),add:p,update:g,remove:j,setIntensity:V,setColor:y,show:h,hide:x,toggle:A,attach:v,detach:I}),[r.lighting.lights,p,g,j,V,y,h,x,A,v,I]);return{sceneConfig:r,setSceneConfig:s,updateSceneConfig:d,resetSceneConfig:b,lights:E}}import{useCallback as Be}from"react";function ve({bindings:e,scene:t,camera:r,animations:s,onAction:d}){let{objectBindings:b,updateObjectBindings:g,showObject:p,hideObject:j,toggleObjectVisibility:V}=e,y=t?.updateSceneConfig,h=r?.focusObject,x=r?.fitScene,A=r?.resetView,v=r?.setCameraTarget,I=r?.setCameraState,E=s?.play,f=s?.pause,C=s?.stop,M=s?.setSpeed,B=s?.seek,D=Be(u=>{let a=N(b,u);return a?b[a]?.actions??[]:[]},[b]),H=Be(async u=>{for(let a of u.action.effects??[]){if("objectBindings"in a){g(a.target,a.objectBindings);continue}if("sceneConfig"in a){y?.(a.sceneConfig);continue}if("visibility"in a){a.visibility==="show"?p(a.target):a.visibility==="hide"?j(a.target):V(a.target);continue}if("camera"in a){let O=a.camera;O.type==="focus-object"?await h?.(O.objectId??u.objectId):O.type==="fit-scene"?await x?.():O.type==="reset"?await A?.():O.type==="set-target"?await v?.(O.target,O.transition??!0):await I?.(O.state,O.transition??!0);continue}let m=a.animation;m.type==="play"?E?.(m.clip):m.type==="pause"?f?.():m.type==="stop"?C?.():m.type==="set-speed"?M?.(m.speed):B?.(m.time)}await d?.(u)},[x,h,j,d,f,E,A,B,M,I,v,p,C,V,g,y]),o=Be(async(u,a)=>{let m=N(b,u);if(!m)return null;let O=b[m],L=O?.actions?.find($=>$.id===a);if(!O||!L)return null;let U={objectId:m,action:L,binding:O};return await H(U),U},[H,b]);return{getActionsForObject:D,handleAction:H,runAction:o}}import{useCallback as de,useRef as Je}from"react";function Ot(e){return typeof e=="function"?e:e?.handleViewerReady??null}function Me(...e){let t=Je(null),r=Je(e);r.current=e;let s=de(p=>{t.current=p;let j=new Set;for(let V of r.current){let y=Ot(V);y&&!j.has(y)&&(j.add(y),y(p))}},[]),d=de(()=>t.current,[]),b=de(p=>{let j=t.current;return j?j.captureImage(p):Promise.reject(new Error("ModelViewer is not ready yet."))},[]),g=de(()=>{let p=t.current;return p?(p.invalidate(),!0):!1},[]);return{handleViewerReady:s,getViewer:d,captureImage:b,invalidate:g}}import{useCallback as R,useEffect as jt,useRef as G}from"react";import{Material as St,PointLight as Bt,Vector3 as vt}from"three";var Ae=["emissiveIntensity","opacity","metalness","roughness","transmission","clearcoat","clearcoatRoughness","ior","thickness"],ue=1;function fe(e){return typeof e=="string"?[e]:e}function ge(e,t=0,r=1){return Math.min(r,Math.max(t,e))}function Re(e,t){return e+Math.random()*(t-e)}function Xe([e,t],r){return e+(t-e)*r}function xe([e,t],r){return[e[0]+(t[0]-e[0])*r,e[1]+(t[1]-e[1])*r,e[2]+(t[2]-e[2])*r]}function qe(e,t){let r=ge(e);switch(t){case"ease-in":return r*r;case"ease-out":return 1-(1-r)*(1-r);case"ease-in-out":return r<.5?2*r*r:1-Math.pow(-2*r+2,2)/2;default:return r}}function Mt(e){let t=e.material;return t?(Array.isArray(t)?t:[t]).filter(r=>r instanceof St):[]}function Rt(e){let t={opacity:e.opacity,transparent:e.transparent};e.color&&(t.baseColor=`#${e.color.getHexString()}`),e.emissive&&(t.emissive=`#${e.emissive.getHexString()}`);for(let r of Ae){let s=e[r];typeof s=="number"&&(t[r]=s)}return t}function Ye(e,t){t.baseColor!==void 0&&e.color&&e.color.set(t.baseColor),t.emissive!==void 0&&e.emissive&&e.emissive.set(t.emissive);for(let r of Ae){let s=t[r];s!==void 0&&typeof e[r]=="number"&&(e[r]=s)}t.transparent!==void 0&&(e.transparent=t.transparent),e.needsUpdate=!0}function xt(e){return{position:[e.position.x,e.position.y,e.position.z],rotation:[e.rotation.x,e.rotation.y,e.rotation.z],scale:[e.scale.x,e.scale.y,e.scale.z],visible:e.visible}}function At(e,t){if(t.position&&e.position.set(...t.position),t.rotation&&e.rotation.set(...t.rotation),t.scale!==void 0){let r=typeof t.scale=="number"?[t.scale,t.scale,t.scale]:t.scale;e.scale.set(...r)}t.visible!==void 0&&(e.visible=t.visible),e.updateMatrix(),e.updateMatrixWorld(!0)}function Pe(e={}){let t=G(e);t.current=e;let r=G(null),s=G(null),d=G(null),b=G(new Map),g=G(new Map),p=G(new Map),j=G(new Map),V=R(n=>{let i=r.current;if(!i)return null;let l=N(i.objectBindings,n);return i.raw.nodes[n]??(l?i.raw.nodes[l]:null)??(i.raw.scene?Ue(i.raw.scene,n):null)??null},[]),y=R(n=>{let i=r.current;return i?typeof n=="object"&&!Array.isArray(n)?ee(i.objectBindings,n):fe(n).map(l=>N(i.objectBindings,l)??l):typeof n=="string"?[n]:Array.isArray(n)?n:[]},[]),h=R(()=>{r.current?.invalidate()},[]),x=R((n,i)=>{let l=!1;for(let c of y(n)){let w=V(c);if(w)for(let P of Mt(w))p.current.has(P)||p.current.set(P,Rt(P)),Ye(P,i),l=!0}return l},[V,y]),A=R((n,i)=>{let l=x(n,i);return l&&h(),l},[h,x]),v=R((n,i)=>{let l=!1;for(let c of y(n)){let w=V(c);w&&(j.current.has(w)||j.current.set(w,xt(w)),At(w,i),l=!0)}return l},[V,y]),I=R((n,i)=>{let l=v(n,i);return l&&h(),l},[h,v]),E=R(n=>{let i=V(n);if(!i)return null;i.updateWorldMatrix(!0,!1);let l=i.getWorldPosition(new vt);return[l.x,l.y,l.z]},[V]),f=R(n=>{let i=g.current.get(n);return i?(i.light.removeFromParent(),i.light.dispose(),g.current.delete(n),h(),!0):!1},[h]),C=R(n=>{let i=V(n.target);if(!i)return!1;let l=g.current.get(n.id),c=l?.light??new Bt;return l&&l.target!==n.target&&c.removeFromParent(),c.name=`react-immersive-runtime-light:${n.id}`,c.color.set(n.color??"#ffffff"),c.intensity=n.intensity??1,c.distance=n.distance??0,c.decay=n.decay??2,c.castShadow=n.castShadow??!1,c.position.set(...n.offset??[0,0,0]),c.parent!==i&&i.add(c),g.current.set(n.id,{light:c,target:n.target}),h(),!0},[h,V]),M=R((n,i)=>{let l=g.current.get(n);if(!l)return!1;if(i.target&&i.target!==l.target){let c=V(i.target);if(!c)return!1;l.light.removeFromParent(),c.add(l.light),l.target=i.target}return i.color!==void 0&&l.light.color.set(i.color),i.intensity!==void 0&&(l.light.intensity=i.intensity),i.distance!==void 0&&(l.light.distance=i.distance),i.decay!==void 0&&(l.light.decay=i.decay),i.offset!==void 0&&l.light.position.set(...i.offset),i.castShadow!==void 0&&(l.light.castShadow=i.castShadow),h(),!0},[h,V]),B=R((n,i)=>{let l=c=>i[c%i.length]??0;for(let c of n.materials??[])y(c.targets).forEach((w,P)=>{let S=l(P),T={};for(let K of Ae){let F=c.values[K];F&&(T[K]=Xe(F,S))}x(w,T)});for(let c of n.transforms??[])y(c.targets).forEach((w,P)=>{let S=l(P),T={};c.values.position&&(T.position=xe(c.values.position,S)),c.values.rotation&&(T.rotation=xe(c.values.rotation,S)),c.values.scale&&(T.scale=xe(c.values.scale,S)),v(w,T)});for(let c of n.lights??[])fe(c.lights).forEach((w,P)=>{let S=g.current.get(w);S&&(S.light.intensity=Xe(c.intensity,l(P)))})},[y,x,v]),D=G(()=>{}),H=G(()=>{});H.current=n=>{d.current=null;let i=!1;for(let[l,c]of b.current){c.startedAt===null&&(c.startedAt=n);let w=c.lastFrameAt??n;c.lastFrameAt=n;let P=c.override&&c.override.until>n?c.override.level:null;c.override&&P===null&&(c.override=null);let S=c.update(n,n-c.startedAt,Math.min(100,n-w),P);i=!0,S||(b.current.delete(l),c.onComplete?.())}i&&h(),b.current.size>0&&D.current()},D.current=()=>{d.current!==null||typeof requestAnimationFrame>"u"||(d.current=requestAnimationFrame(n=>H.current(n)))};let o=R(n=>(b.current.set(n.id,n),D.current(),n.id),[]),u=R((n,i={})=>{let l=i.id??`transition-${ue++}`,c=Math.max(1,i.duration??400),w=i.easing??"ease-in-out";return o({id:l,startedAt:null,lastFrameAt:null,override:null,onComplete:i.onComplete,update:(P,S,T,K)=>{let F=K??qe(S/c,w);return B(n,[F]),S<c}})},[B,o]),a=R((n,i={})=>{let l=i.id??`pulse-${ue++}`,c=Math.max(1,i.duration??1e3),w=i.minLevel??0,P=i.maxLevel??1,S=i.repeat??1/0,T=i.synchronized??!0,K=Math.max(1,...[...n.materials??[],...n.transforms??[]].map(F=>y(F.targets).length),...(n.lights??[]).map(F=>fe(F.lights).length));return o({id:l,startedAt:null,lastFrameAt:null,override:null,onComplete:i.onComplete,update:(F,te,ne,J)=>{let _=te/c,X=Array.from({length:T?1:K},(ie,Z)=>{if(J!==null)return J;let ce=_+(T?0:Z/K),Y=.5-Math.cos(ce%1*Math.PI*2)/2;return w+(P-w)*Y});return B(n,X),S===1/0||_<S}})},[B,o,y]),m=R((n,i={})=>{let l=i.id??`timeline-${ue++}`,c=i.repeat??1,w=n.map(S=>({...S,duration:Math.max(1,S.duration),hold:Math.max(0,S.hold??0)})),P=Math.max(1,w.reduce((S,T)=>S+T.duration+T.hold,0));return o({id:l,startedAt:null,lastFrameAt:null,override:null,onComplete:i.onComplete,update:(S,T,K,F)=>{if(w.length===0||c<=0)return!1;let te=T/P;if(c!==1/0&&te>=c){for(let _ of w)B(_.channels,[1]);return!1}let ne=T%P,J=0;for(let _ of w){let X=J+_.duration,ie=X+_.hold;if(ne>=X){B(_.channels,[F??1]),J=ie;continue}if(ne>=J){let Z=F??qe((ne-J)/_.duration,_.easing??"ease-in-out");B(_.channels,[Z]);break}}return!0}})},[B,o]),O=R((n,i={})=>{let l=i.id??`flicker-${ue++}`,c=i.synchronized??!0,w=i.minLevel??.15,P=i.maxLevel??1,S=i.interval??[45,160],T=typeof S=="number"?[S,S]:S,K=[Math.max(1,Math.min(...T)),Math.max(1,Math.max(...T))],F=ge(i.response??.7,.01,1),te=ge(i.blackoutChance??.08),ne=ge(i.flashChance??.12),J=i.flashLevel??1.15,_=Math.max(1,...[...n.materials??[],...n.transforms??[]].map(Y=>y(Y.targets).length),...(n.lights??[]).map(Y=>fe(Y.lights).length)),X=c?1:_,ie=Array.from({length:X},()=>w),Z=Array.from({length:X},()=>w),ce=Array.from({length:X},()=>0);return o({id:l,startedAt:null,lastFrameAt:null,override:null,onComplete:i.onComplete,update:(Y,rt,ot,ke)=>{for(let q=0;q<X;q+=1){if(ke!==null)Z[q]=ke;else if(Y>=ce[q]){let He=Math.random();Z[q]=He<te?Re(0,Math.min(.04,w)):He<te+ne?J:Re(w,P),ce[q]=Y+Re(...K)}let st=1-Math.pow(1-F,Math.max(1,ot)/16.67);ie[q]+=(Z[q]-ie[q])*st}return B(n,ie),i.duration===void 0||rt<i.duration}})},[B,o,y]),L=R((n,i,l)=>{let c=b.current.get(n);if(!c)return!1;let w=typeof performance>"u"?Date.now():performance.now();return c.override={level:i,until:w+Math.max(0,l)},D.current(),!0},[]),U=R(n=>b.current.delete(n),[]),$=R(()=>{b.current.clear(),d.current!==null&&typeof cancelAnimationFrame<"u"&&(cancelAnimationFrame(d.current),d.current=null)},[]),W=R(()=>{for(let[n,i]of p.current)Ye(n,i);p.current.clear();for(let[n,i]of j.current)n.position.set(...i.position),n.rotation.set(...i.rotation),n.scale.set(...i.scale),n.visible=i.visible,n.updateMatrix(),n.updateMatrixWorld(!0);j.current.clear();for(let n of g.current.values())n.light.removeFromParent(),n.light.dispose();g.current.clear(),h()},[h]),be=R(()=>{$(),W()},[W,$]),it=R(n=>{s.current&&s.current!==n.raw.scene&&W(),r.current=n,s.current=n.raw.scene,t.current.onViewerReady?.(n)},[W]);return jt(()=>()=>{be(),r.current=null,s.current=null},[be]),{handleViewerReady:it,setMaterial:A,setTransform:I,getWorldPosition:E,addPointLight:C,updatePointLight:M,removePointLight:f,transition:u,timeline:m,pulse:a,flicker:O,overrideEffect:L,stopEffect:U,stopAllEffects:$,resetRuntime:be}}import{useCallback as Pt,useState as Et}from"react";function Ee(){let[e,t]=Et(null),r=Pt(s=>{t(s)},[t]);return{hoveredObjectBinding:e,handleHoveredObject:r}}import{useCallback as me,useState as oe}from"react";function Te(){let[e,t]=oe(!0),[r,s]=oe(!1),[d,b]=oe(null),[g,p]=oe(null),[j,V]=oe(0),[y,h]=oe([]),x=me(E=>{p(E.bounds),V(E.objectCount),b(null),t(!1),s(!0)},[]),A=me(E=>h(E),[]),v=me(E=>{b(E),p(null),V(0),h([]),t(!1),s(!1)},[]),I=me(()=>{t(!0),s(!1),b(null),p(null),V(0),h([])},[]);return{isLoading:e,isReady:r,error:d,bounds:g,objectCount:j,objects:y,handleModelLoaded:x,handleObjectCatalog:A,handleLoadError:v,resetModelState:I}}import{useCallback as Qe,useState as Tt}from"react";function Le(e=null){let[t,r]=Tt(e),s=Qe(b=>{r(b)},[r]),d=Qe(()=>{r(null)},[]);return{selectedObjectBinding:t,setSelectedObjectBinding:r,handleObjectSelect:s,clearSelection:d}}var Lt={};function It(e={}){let t=Ze(e);t.current=e;let r=Ze(e.bindings===void 0||e.bindings==="auto"),s=je(()=>{let o=t.current.bindings;return o===void 0||o==="auto"?Lt:typeof o=="function"?o():o}),d=Se(()=>{let o=t.current.sceneConfig;return o===void 0?le:typeof o=="function"?o():o}),b=Le(),g=Ee(),p=he(e.camera),j=Te(),V=Oe(),y=Pe(),h=Me(p,y),x=ve({bindings:s,scene:d,camera:p,animations:V,onAction:e.onAction}),{setObjectBindings:A}=s,{handleObjectCatalog:v}=j,I=pe(o=>{v(o),r.current&&A(u=>{let a=Fe(o.map(m=>m.name));for(let m of Object.keys(a))u[m]&&(a[m]=u[m]);return a})},[v,A]),{handleObjectSelect:E}=b,f=pe(o=>{E(o),t.current.onObjectSelect?.(o)},[E]),{handleHoveredObject:C}=g,M=pe(o=>{C(o),t.current.onObjectHover?.(o)},[C]),{handleLoadError:B}=j,D=pe(o=>{B(o),t.current.onLoadError?.(o)},[B]),H=e.sceneConfig!==void 0||d.sceneConfig!==le;return{props:{objectBindings:s.objectBindings,onObjectBindingsChange:A,selectedObject:b.selectedObjectBinding,onObjectSelect:f,onObjectHover:M,onCameraChange:p.handleCameraChange,onViewerReady:h.handleViewerReady,onModelLoaded:j.handleModelLoaded,onLoadError:D,onObjectCatalog:I,onAnimationsReady:V.handleAnimationsReady,onAction:x.handleAction,onSceneConfigChange:d.setSceneConfig,...H?{sceneConfig:d.sceneConfig}:{}},bindings:s,selection:b,hover:g,camera:p,model:j,animations:V,actions:x,scene:d,effects:y,connection:h}}import{useMemo as kt}from"react";function Ht(e,t){return kt(()=>{if(!t)return null;let r=e[t];return r||(Object.values(e).find(s=>s.id===t||s.modelObjectId===t)??null)},[e,t])}import{useMemo as Ut}from"react";function Ft(e){return Ut(()=>Object.values(e).map(t=>t.modelObjectId),[e])}import{useCallback as se,useEffect as Ie,useRef as Q,useState as _t}from"react";function nt(e){return typeof e=="object"&&e!==null&&!Array.isArray(e)}function ae(e){return typeof e=="number"&&Number.isFinite(e)}function et(e){return Array.isArray(e)&&e.length===3&&e.every(ae)}function Dt(e){return!nt(e)||!et(e.position)||!et(e.target)||e.fov!==null&&!ae(e.fov)||!ae(e.zoom)||e.zoom<=0||e.azimuthAngle!==void 0&&!ae(e.azimuthAngle)||e.polarAngle!==void 0&&!ae(e.polarAngle)?null:{position:e.position,target:e.target,fov:e.fov,zoom:e.zoom,azimuthAngle:e.azimuthAngle,polarAngle:e.polarAngle}}function Nt(e){if(!nt(e))return null;let t;if(e.camera!==void 0){let d=Dt(e.camera);if(!d)return null;t=d}let r;if(e.hidden!==void 0){if(!Array.isArray(e.hidden)||!e.hidden.every(d=>typeof d=="string"))return null;r=e.hidden}let s;if(e.selected===null||typeof e.selected=="string")s=e.selected;else if(e.selected!==void 0)return null;return{camera:t,hidden:r,selected:s}}function tt(e,t,r){let s=Object.values(t).filter(d=>d.visible===!1).map(d=>d.id);return{camera:e??void 0,hidden:s,selected:r?.id??null}}function zt({cameraState:e,setCameraState:t,objectBindings:r,onObjectBindingsChange:s,selectedObjectBinding:d,setSelectedObjectBinding:b,paramKey:g="view",debounceMs:p=400,autoSync:j=!0}){let V=Q(null),y=Q(null),h=Q(null),x=Q(null),A=Q(null),v=se(()=>{A.current!==null&&(window.clearTimeout(A.current),A.current=null),h.current=null,x.current=null},[]),I=se(()=>{let a=tt(e,r,d);return`${g}=${encodeURIComponent(JSON.stringify(a))}`},[e,r,d,g]),E=se(()=>{let a=new URL(window.location.href);return a.hash=I(),a.toString()},[I]),f=se(a=>{let m=new URL(window.location.href);m.hash=a,window.history.replaceState(null,"",m.toString()),y.current=a,V.current=new URLSearchParams(m.hash.slice(1)).get(g)},[g]),C=se(()=>{v(),f(I())},[I,v,f]),M=Q({cameraState:e,objectBindings:r,selectedObjectBinding:d});M.current={cameraState:e,objectBindings:r,selectedObjectBinding:d};let[B,D]=_t(!1);Ie(()=>{if(!j||!B){v();return}let a=M.current,m=tt(a.cameraState,a.objectBindings,a.selectedObjectBinding),O=`${g}=${encodeURIComponent(JSON.stringify(m))}`;if(O===y.current){v();return}O===h.current&&p===x.current||(v(),h.current=O,x.current=p,A.current=window.setTimeout(()=>{A.current=null,h.current=null,x.current=null,f(O)},Math.max(0,p)))},[j,e,v,p,r,g,B,d,f]),Ie(()=>v,[v]);let H=Q(null),o=Q(null),u=se(async()=>{D(!0);let a=window.location.hash.startsWith("#")?window.location.hash.slice(1):window.location.hash,m=new URLSearchParams(a).get(g);if(!m)return H.current=null,!1;if(m===V.current||m===H.current||m===o.current)return!1;let O;try{O=JSON.parse(m)}catch{return!1}let L=Nt(O);if(!L)return!1;o.current=m;try{if(L.camera&&await t(L.camera,!1),L.hidden){let U=new Set(L.hidden);s(Object.fromEntries(Object.entries(r).map(([$,W])=>[$,{...W,visible:!U.has(W.id)}])))}if(L.selected!==void 0){let U=L.selected?N(r,L.selected):null;b(U?r[U]:null)}return H.current=m,!0}finally{o.current===m&&(o.current=null)}},[r,s,g,t,b]);return Ie(()=>{let a=()=>{u().catch(()=>{})};return window.addEventListener("hashchange",a),()=>{window.removeEventListener("hashchange",a)}},[u]),{getShareUrl:E,syncUrl:C,restoreFromUrl:u}}export{ct as ACTION_CATALOG,le as DEFAULT_SCENE_CONFIG,pt as MATERIAL_BLENDING_MODES,mt as MATERIAL_SIDES,at as MODEL_VIEWER_PRESETS,We as ModelViewer,ft as buildBindingsFromNodes,ut as createDefaultBinding,gt as defineObjectBindings,lt as findCatalogAction,dt as inferType,ye as material,re as patchBindings,Ve as patchSceneConfig,Ce as sceneLight,ee as selectBindingKeys,we as selectBindings,Ht as useObjectBinding,Ft as useObjectBindingIds,je as useObjectBindings,Se as useSceneConfig,zt as useShareableViewerState,It as useViewer,ve as useViewerActions,Oe as useViewerAnimations,he as useViewerCamera,Me as useViewerConnection,Pe as useViewerEffects,Ee as useViewerHover,Te as useViewerModel,Le as useViewerSelection};
@@ -0,0 +1,17 @@
1
+ type ModelFormat = "glb" | "gltf" | "obj" | "fbx" | "usdz";
2
+
3
+ type ViewerModelBounds = {
4
+ min: [number, number, number];
5
+ max: [number, number, number];
6
+ center: [number, number, number];
7
+ size: [number, number, number];
8
+ };
9
+ /** What `onModelLoaded` reports about a model that finished loading. */
10
+ type ViewerModelInfo = {
11
+ /** Bounds in world space, where the viewer placed the model. */
12
+ bounds: ViewerModelBounds;
13
+ /** Number of meshes in the loaded scene. */
14
+ objectCount: number;
15
+ };
16
+
17
+ export type { ModelFormat as M, ViewerModelBounds as V, ViewerModelInfo as a };
@@ -0,0 +1,17 @@
1
+ type ModelFormat = "glb" | "gltf" | "obj" | "fbx" | "usdz";
2
+
3
+ type ViewerModelBounds = {
4
+ min: [number, number, number];
5
+ max: [number, number, number];
6
+ center: [number, number, number];
7
+ size: [number, number, number];
8
+ };
9
+ /** What `onModelLoaded` reports about a model that finished loading. */
10
+ type ViewerModelInfo = {
11
+ /** Bounds in world space, where the viewer placed the model. */
12
+ bounds: ViewerModelBounds;
13
+ /** Number of meshes in the loaded scene. */
14
+ objectCount: number;
15
+ };
16
+
17
+ export type { ModelFormat as M, ViewerModelBounds as V, ViewerModelInfo as a };
@@ -3,9 +3,24 @@ type ViewerCameraState = {
3
3
  target: [number, number, number];
4
4
  fov: number | null;
5
5
  zoom: number;
6
+ /**
7
+ * The camera's orbit angles, in radians, captured so setCameraState can
8
+ * restore the exact rotation (position and target alone are ambiguous
9
+ * straight above or below the target). Pass the state back as-is; to move
10
+ * the camera to angles you choose, use orbitTo, which takes degrees.
11
+ */
6
12
  azimuthAngle?: number;
7
13
  polarAngle?: number;
8
14
  };
15
+ /** Where ModelViewer's camera starts. Setting it skips the automatic fit. */
16
+ type ViewerCameraConfig = {
17
+ position?: [number, number, number];
18
+ /** Vertical field of view in degrees. */
19
+ fov?: number;
20
+ near?: number;
21
+ far?: number;
22
+ zoom?: number;
23
+ };
9
24
 
10
25
  type DeepPartial<T> = T extends readonly unknown[] ? T : T extends object ? {
11
26
  [K in keyof T]?: DeepPartial<T[K]>;
@@ -353,6 +368,11 @@ type SceneAnnotationMarker = {
353
368
  type SceneCinematicWaypoint = {
354
369
  position: [number, number, number];
355
370
  target: [number, number, number];
371
+ /**
372
+ * Orbit angles in radians, captured with the view in BindingBuilder. They
373
+ * keep the rotation when position and target are vertically aligned; older
374
+ * scene configs without them still work.
375
+ */
356
376
  azimuthAngle?: number;
357
377
  polarAngle?: number;
358
378
  segmentDuration?: number;
@@ -442,10 +462,19 @@ type ObjectBindingAction = {
442
462
  type: "command";
443
463
  effects?: ObjectActionEffect[];
444
464
  };
445
- type ObjectBindingType = "body" | "other" | "glass" | "windshield" | "rear-windshield" | "window" | "sunroof" | "wheel" | "rim" | "tire" | "brake-caliper" | "brake-disc" | "suspension" | "spring" | "shock-absorber" | "axle" | "control-arm" | "interior" | "seat" | "headrest" | "seatbelt" | "dashboard" | "steering-wheel" | "gear-shift" | "center-console" | "armrest" | "door-panel" | "carpet" | "headliner" | "sun-visor" | "pedal" | "instrument-cluster" | "infotainment" | "glove-box" | "engine" | "gearbox" | "radiator" | "battery" | "fuel-tank" | "air-filter" | "intercooler" | "alternator" | "turbo" | "light" | "headlight" | "taillight" | "fog-light" | "indicator" | "daytime-running-light" | "interior-light" | "ambient-light" | "floor" | "floor-tile" | "floor-board" | "floor-mat" | "ceiling" | "ceiling-tile" | "wall" | "wall-tile" | "wall-panel" | "wall-trim" | "baseboard" | "crown-molding" | "column" | "pillar" | "beam" | "arch" | "stairs" | "step" | "railing" | "balustrade" | "window-frame" | "window-sill" | "blind" | "curtain" | "shutter" | "door" | "door-frame" | "door-knob" | "furniture" | "sofa" | "armchair" | "ottoman" | "bed" | "headboard" | "mattress" | "nightstand" | "dresser" | "wardrobe" | "closet" | "shelf" | "bookcase" | "desk" | "office-chair" | "dining-table" | "dining-chair" | "bar-stool" | "bench" | "cabinet" | "sideboard" | "coffee-table" | "side-table" | "tv-stand" | "kitchen-island" | "countertop" | "sink" | "bathtub" | "shower" | "toilet" | "vanity" | "decor" | "rug" | "cushion" | "throw" | "curtain-rod" | "artwork" | "mirror" | "vase" | "plant" | "pot" | "candle" | "frame" | "sculpture" | "clock" | "lamp" | "floor-lamp" | "table-lamp" | "pendant-light" | "chandelier" | "sconce" | "ceiling-fan" | "electronics" | "tv" | "monitor" | "speaker" | "soundbar" | "projector" | "remote" | "console" | "router" | "smart-hub" | "thermostat" | "appliance" | "refrigerator" | "oven" | "microwave" | "dishwasher" | "washing-machine" | "dryer" | "air-conditioner" | "heater" | "ventilation" | "root" | "bone" | "joint" | "socket" | "pivot" | "head" | "face" | "eye" | "eyelid" | "eyebrow" | "mouth" | "teeth" | "tongue" | "ear" | "nose" | "hair" | "beard" | "neck" | "torso" | "chest" | "abdomen" | "back" | "shoulder" | "upper-arm" | "forearm" | "hand" | "finger" | "thumb" | "hip" | "thigh" | "shin" | "foot" | "toe" | "tail" | "wing" | "tentacle" | "clothing" | "hat" | "helmet" | "visor" | "mask" | "goggles" | "glasses" | "jacket" | "shirt" | "pants" | "skirt" | "shoes" | "boots" | "gloves" | "belt" | "watch" | "bag" | "backpack" | "jewelry" | "necklace" | "ring" | "armor" | "chest-plate" | "pauldron" | "gauntlet" | "greave" | "shield" | "weapon" | "blade" | "edge" | "tip" | "guard" | "grip" | "pommel" | "barrel" | "stock" | "scope" | "trigger" | "magazine" | "muzzle" | "gear" | "piston" | "lever" | "valve" | "pump" | "motor" | "rotor" | "blade-prop" | "nozzle" | "pipe" | "tube" | "cable" | "wire" | "connector" | "panel" | "hatch" | "vent" | "antenna" | "sensor" | "camera" | "screen" | "dial" | "button" | "knob" | "switch" | "gauge" | "terrain" | "ground" | "rock" | "cliff" | "water" | "ocean" | "river" | "lake" | "wave" | "foam" | "sky" | "cloud" | "sun" | "moon" | "star" | "fog" | "foliage" | "tree" | "branch" | "leaf" | "grass" | "bush" | "flower" | "soil" | "sand" | "snow" | "ice" | "facade" | "foundation" | "roof-structure" | "chimney" | "balcony" | "porch" | "pathway" | "fence" | "gate" | "wall-exterior";
465
+ /**
466
+ * What kind of object a binding is, for grouping and filtering. The listed
467
+ * values are suggestions; any string works.
468
+ */
469
+ type ObjectBindingType = "body" | "other" | "glass" | "windshield" | "rear-windshield" | "window" | "sunroof" | "wheel" | "rim" | "tire" | "brake-caliper" | "brake-disc" | "suspension" | "spring" | "shock-absorber" | "axle" | "control-arm" | "interior" | "seat" | "headrest" | "seatbelt" | "dashboard" | "steering-wheel" | "gear-shift" | "center-console" | "armrest" | "door-panel" | "carpet" | "headliner" | "sun-visor" | "pedal" | "instrument-cluster" | "infotainment" | "glove-box" | "engine" | "gearbox" | "radiator" | "battery" | "fuel-tank" | "air-filter" | "intercooler" | "alternator" | "turbo" | "light" | "headlight" | "taillight" | "fog-light" | "indicator" | "daytime-running-light" | "interior-light" | "ambient-light" | "floor" | "floor-tile" | "floor-board" | "floor-mat" | "ceiling" | "ceiling-tile" | "wall" | "wall-tile" | "wall-panel" | "wall-trim" | "baseboard" | "crown-molding" | "column" | "pillar" | "beam" | "arch" | "stairs" | "step" | "railing" | "balustrade" | "window-frame" | "window-sill" | "blind" | "curtain" | "shutter" | "door" | "door-frame" | "door-knob" | "furniture" | "sofa" | "armchair" | "ottoman" | "bed" | "headboard" | "mattress" | "nightstand" | "dresser" | "wardrobe" | "closet" | "shelf" | "bookcase" | "desk" | "office-chair" | "dining-table" | "dining-chair" | "bar-stool" | "bench" | "cabinet" | "sideboard" | "coffee-table" | "side-table" | "tv-stand" | "kitchen-island" | "countertop" | "sink" | "bathtub" | "shower" | "toilet" | "vanity" | "decor" | "rug" | "cushion" | "throw" | "curtain-rod" | "artwork" | "mirror" | "vase" | "plant" | "pot" | "candle" | "frame" | "sculpture" | "clock" | "lamp" | "floor-lamp" | "table-lamp" | "pendant-light" | "chandelier" | "sconce" | "ceiling-fan" | "electronics" | "tv" | "monitor" | "speaker" | "soundbar" | "projector" | "remote" | "console" | "router" | "smart-hub" | "thermostat" | "appliance" | "refrigerator" | "oven" | "microwave" | "dishwasher" | "washing-machine" | "dryer" | "air-conditioner" | "heater" | "ventilation" | "root" | "bone" | "joint" | "socket" | "pivot" | "head" | "face" | "eye" | "eyelid" | "eyebrow" | "mouth" | "teeth" | "tongue" | "ear" | "nose" | "hair" | "beard" | "neck" | "torso" | "chest" | "abdomen" | "back" | "shoulder" | "upper-arm" | "forearm" | "hand" | "finger" | "thumb" | "hip" | "thigh" | "shin" | "foot" | "toe" | "tail" | "wing" | "tentacle" | "clothing" | "hat" | "helmet" | "visor" | "mask" | "goggles" | "glasses" | "jacket" | "shirt" | "pants" | "skirt" | "shoes" | "boots" | "gloves" | "belt" | "watch" | "bag" | "backpack" | "jewelry" | "necklace" | "ring" | "armor" | "chest-plate" | "pauldron" | "gauntlet" | "greave" | "shield" | "weapon" | "blade" | "edge" | "tip" | "guard" | "grip" | "pommel" | "barrel" | "stock" | "scope" | "trigger" | "magazine" | "muzzle" | "gear" | "piston" | "lever" | "valve" | "pump" | "motor" | "rotor" | "blade-prop" | "nozzle" | "pipe" | "tube" | "cable" | "wire" | "connector" | "panel" | "hatch" | "vent" | "antenna" | "sensor" | "camera" | "screen" | "dial" | "button" | "knob" | "switch" | "gauge" | "terrain" | "ground" | "rock" | "cliff" | "water" | "ocean" | "river" | "lake" | "wave" | "foam" | "sky" | "cloud" | "sun" | "moon" | "star" | "fog" | "foliage" | "tree" | "branch" | "leaf" | "grass" | "bush" | "flower" | "soil" | "sand" | "snow" | "ice" | "facade" | "foundation" | "roof-structure" | "chimney" | "balcony" | "porch" | "pathway" | "fence" | "gate" | "wall-exterior" | (string & {});
446
470
  type ObjectBindingStatus = "normal" | "hidden" | "selected" | "disabled";
447
471
  type ObjectBindingTextureSlot = {
448
472
  path: string;
473
+ /** UV position offset [u, v]. */
474
+ offset?: [number, number];
475
+ /** UV zoom scale. 1 = default, >1 = zoom in, <1 = zoom out. */
476
+ scale?: number;
477
+ rotation?: number;
449
478
  };
450
479
  type ObjectBindingTextureChannel = "baseColor" | "metalness" | "roughness" | "emissive" | "alpha" | "normal" | "bump" | "ao" | "displacement" | "clearcoat" | "clearcoatRoughness" | "clearcoatNormal" | "anisotropy" | "transmission" | "thickness" | "sheenColor" | "sheenRoughness" | "specularIntensity" | "specularColor";
451
480
  type ObjectBindingTransform = {
@@ -525,7 +554,8 @@ type ObjectBindingStyle = {
525
554
  };
526
555
  type ObjectBinding = {
527
556
  id: string;
528
- type: ObjectBindingType;
557
+ /** Defaults to `"other"`. */
558
+ type?: ObjectBindingType;
529
559
  modelObjectId: string;
530
560
  label?: string;
531
561
  group?: string;
@@ -548,5 +578,27 @@ type ObjectActionEvent = {
548
578
  screenX?: number;
549
579
  screenY?: number;
550
580
  };
581
+ /** A double-click, right-click, or long-press on a model object. */
582
+ type ObjectPointerEvent = {
583
+ binding: ObjectBinding;
584
+ /** Viewport coordinates, e.g. to place a menu with `position: fixed`. */
585
+ clientX: number;
586
+ clientY: number;
587
+ /** `"mouse"`, `"pen"`, or `"touch"`. */
588
+ pointerType: string;
589
+ };
590
+
591
+ /** One bindable object in a model, as reported by `onObjectCatalog`. */
592
+ type ViewerObjectInfo = {
593
+ /** The node identifier bindings are keyed by. */
594
+ name: string;
595
+ triangles: number;
596
+ /**
597
+ * Axis-aligned bounds in the model's own units, in Z-up coordinates (the 3D
598
+ * Tiles convention): a glTF point (x, y, z) is (x, -z, y) here.
599
+ */
600
+ minimum: [number, number, number];
601
+ maximum: [number, number, number];
602
+ };
551
603
 
552
- export { type AnimationAction as A, type BindingEdit as B, type CameraAction as C, DEFAULT_SCENE_CONFIG as D, type SceneLightType as E, type SceneModelRenderer as F, type VisibilityActionEffect as G, material as H, patchBindings as I, patchSceneConfig as J, selectBindingKeys as K, selectBindings as L, MATERIAL_BLENDING_MODES as M, type ObjectActionEffect as O, type SceneAnimationClipConfig as S, type ViewerCameraState as V, type AnimationActionEffect as a, type AnimationLoopMode as b, type CameraActionEffect as c, MATERIAL_SIDES as d, type ObjectActionEvent as e, type ObjectBinding as f, type ObjectBindingAction as g, type ObjectBindingMaterial as h, type ObjectBindingMaterialBlendingMode as i, type ObjectBindingMaterialSide as j, type ObjectBindingPatch as k, type ObjectBindingSelector as l, type ObjectBindingTarget as m, type ObjectBindingTextureChannel as n, type ObjectBindingTextureSlot as o, type ObjectBindingTransform as p, type ObjectBindingsActionEffect as q, type SceneAnimationConfig as r, type SceneAnnotationMarker as s, type SceneCinematicConfig as t, type SceneCinematicWaypoint as u, type SceneConfig as v, type SceneConfigActionEffect as w, type SceneConfigPatch as x, type SceneLight as y, type SceneLightAttachment as z };
604
+ export { type SceneWireframeConfig as $, type AnimationAction as A, type BindingEdit as B, type CameraAction as C, DEFAULT_SCENE_CONFIG as D, type EnvironmentPreset as E, type SceneCameraConfig as F, type GlitchModeName as G, type SceneCinematicConfig as H, type SceneCinematicWaypoint as I, type SceneConfig as J, type KernelSizeName as K, type SceneConfigActionEffect as L, MATERIAL_BLENDING_MODES as M, type SceneConfigPatch as N, type ObjectActionEffect as O, type SceneEnvironmentConfig as P, type SceneGroundShadowConfig as Q, type RampTypeName as R, type SceneAnimationClipConfig as S, type SceneLight as T, type SceneLightAttachment as U, type SceneLightType as V, type SceneLightingConfig as W, type SceneModelConfig as X, type SceneModelRenderer as Y, type ScenePostProcessingConfig as Z, type SceneShadowConfig as _, type AnimationActionEffect as a, type ViewerCameraConfig as a0, type ViewerCameraState as a1, type ViewerObjectInfo as a2, type VisibilityActionEffect as a3, material as a4, patchBindings as a5, patchSceneConfig as a6, selectBindingKeys as a7, selectBindings as a8, type AnimationLoopMode as b, type CameraActionEffect as c, type DeepPartial as d, MATERIAL_SIDES as e, type ObjectActionEvent as f, type ObjectBinding as g, type ObjectBindingAction as h, type ObjectBindingCameraState as i, type ObjectBindingMaterial as j, type ObjectBindingMaterialBlendingMode as k, type ObjectBindingMaterialSide as l, type ObjectBindingPatch as m, type ObjectBindingSelector as n, type ObjectBindingStatus as o, type ObjectBindingStyle as p, type ObjectBindingTarget as q, type ObjectBindingTextureChannel as r, type ObjectBindingTextureSlot as s, type ObjectBindingTransform as t, type ObjectBindingType as u, type ObjectBindingsActionEffect as v, type ObjectPointerEvent as w, type SceneAnimationConfig as x, type SceneAnnotationMarker as y, type SceneBackgroundConfig as z };
@@ -3,9 +3,24 @@ type ViewerCameraState = {
3
3
  target: [number, number, number];
4
4
  fov: number | null;
5
5
  zoom: number;
6
+ /**
7
+ * The camera's orbit angles, in radians, captured so setCameraState can
8
+ * restore the exact rotation (position and target alone are ambiguous
9
+ * straight above or below the target). Pass the state back as-is; to move
10
+ * the camera to angles you choose, use orbitTo, which takes degrees.
11
+ */
6
12
  azimuthAngle?: number;
7
13
  polarAngle?: number;
8
14
  };
15
+ /** Where ModelViewer's camera starts. Setting it skips the automatic fit. */
16
+ type ViewerCameraConfig = {
17
+ position?: [number, number, number];
18
+ /** Vertical field of view in degrees. */
19
+ fov?: number;
20
+ near?: number;
21
+ far?: number;
22
+ zoom?: number;
23
+ };
9
24
 
10
25
  type DeepPartial<T> = T extends readonly unknown[] ? T : T extends object ? {
11
26
  [K in keyof T]?: DeepPartial<T[K]>;
@@ -353,6 +368,11 @@ type SceneAnnotationMarker = {
353
368
  type SceneCinematicWaypoint = {
354
369
  position: [number, number, number];
355
370
  target: [number, number, number];
371
+ /**
372
+ * Orbit angles in radians, captured with the view in BindingBuilder. They
373
+ * keep the rotation when position and target are vertically aligned; older
374
+ * scene configs without them still work.
375
+ */
356
376
  azimuthAngle?: number;
357
377
  polarAngle?: number;
358
378
  segmentDuration?: number;
@@ -442,10 +462,19 @@ type ObjectBindingAction = {
442
462
  type: "command";
443
463
  effects?: ObjectActionEffect[];
444
464
  };
445
- type ObjectBindingType = "body" | "other" | "glass" | "windshield" | "rear-windshield" | "window" | "sunroof" | "wheel" | "rim" | "tire" | "brake-caliper" | "brake-disc" | "suspension" | "spring" | "shock-absorber" | "axle" | "control-arm" | "interior" | "seat" | "headrest" | "seatbelt" | "dashboard" | "steering-wheel" | "gear-shift" | "center-console" | "armrest" | "door-panel" | "carpet" | "headliner" | "sun-visor" | "pedal" | "instrument-cluster" | "infotainment" | "glove-box" | "engine" | "gearbox" | "radiator" | "battery" | "fuel-tank" | "air-filter" | "intercooler" | "alternator" | "turbo" | "light" | "headlight" | "taillight" | "fog-light" | "indicator" | "daytime-running-light" | "interior-light" | "ambient-light" | "floor" | "floor-tile" | "floor-board" | "floor-mat" | "ceiling" | "ceiling-tile" | "wall" | "wall-tile" | "wall-panel" | "wall-trim" | "baseboard" | "crown-molding" | "column" | "pillar" | "beam" | "arch" | "stairs" | "step" | "railing" | "balustrade" | "window-frame" | "window-sill" | "blind" | "curtain" | "shutter" | "door" | "door-frame" | "door-knob" | "furniture" | "sofa" | "armchair" | "ottoman" | "bed" | "headboard" | "mattress" | "nightstand" | "dresser" | "wardrobe" | "closet" | "shelf" | "bookcase" | "desk" | "office-chair" | "dining-table" | "dining-chair" | "bar-stool" | "bench" | "cabinet" | "sideboard" | "coffee-table" | "side-table" | "tv-stand" | "kitchen-island" | "countertop" | "sink" | "bathtub" | "shower" | "toilet" | "vanity" | "decor" | "rug" | "cushion" | "throw" | "curtain-rod" | "artwork" | "mirror" | "vase" | "plant" | "pot" | "candle" | "frame" | "sculpture" | "clock" | "lamp" | "floor-lamp" | "table-lamp" | "pendant-light" | "chandelier" | "sconce" | "ceiling-fan" | "electronics" | "tv" | "monitor" | "speaker" | "soundbar" | "projector" | "remote" | "console" | "router" | "smart-hub" | "thermostat" | "appliance" | "refrigerator" | "oven" | "microwave" | "dishwasher" | "washing-machine" | "dryer" | "air-conditioner" | "heater" | "ventilation" | "root" | "bone" | "joint" | "socket" | "pivot" | "head" | "face" | "eye" | "eyelid" | "eyebrow" | "mouth" | "teeth" | "tongue" | "ear" | "nose" | "hair" | "beard" | "neck" | "torso" | "chest" | "abdomen" | "back" | "shoulder" | "upper-arm" | "forearm" | "hand" | "finger" | "thumb" | "hip" | "thigh" | "shin" | "foot" | "toe" | "tail" | "wing" | "tentacle" | "clothing" | "hat" | "helmet" | "visor" | "mask" | "goggles" | "glasses" | "jacket" | "shirt" | "pants" | "skirt" | "shoes" | "boots" | "gloves" | "belt" | "watch" | "bag" | "backpack" | "jewelry" | "necklace" | "ring" | "armor" | "chest-plate" | "pauldron" | "gauntlet" | "greave" | "shield" | "weapon" | "blade" | "edge" | "tip" | "guard" | "grip" | "pommel" | "barrel" | "stock" | "scope" | "trigger" | "magazine" | "muzzle" | "gear" | "piston" | "lever" | "valve" | "pump" | "motor" | "rotor" | "blade-prop" | "nozzle" | "pipe" | "tube" | "cable" | "wire" | "connector" | "panel" | "hatch" | "vent" | "antenna" | "sensor" | "camera" | "screen" | "dial" | "button" | "knob" | "switch" | "gauge" | "terrain" | "ground" | "rock" | "cliff" | "water" | "ocean" | "river" | "lake" | "wave" | "foam" | "sky" | "cloud" | "sun" | "moon" | "star" | "fog" | "foliage" | "tree" | "branch" | "leaf" | "grass" | "bush" | "flower" | "soil" | "sand" | "snow" | "ice" | "facade" | "foundation" | "roof-structure" | "chimney" | "balcony" | "porch" | "pathway" | "fence" | "gate" | "wall-exterior";
465
+ /**
466
+ * What kind of object a binding is, for grouping and filtering. The listed
467
+ * values are suggestions; any string works.
468
+ */
469
+ type ObjectBindingType = "body" | "other" | "glass" | "windshield" | "rear-windshield" | "window" | "sunroof" | "wheel" | "rim" | "tire" | "brake-caliper" | "brake-disc" | "suspension" | "spring" | "shock-absorber" | "axle" | "control-arm" | "interior" | "seat" | "headrest" | "seatbelt" | "dashboard" | "steering-wheel" | "gear-shift" | "center-console" | "armrest" | "door-panel" | "carpet" | "headliner" | "sun-visor" | "pedal" | "instrument-cluster" | "infotainment" | "glove-box" | "engine" | "gearbox" | "radiator" | "battery" | "fuel-tank" | "air-filter" | "intercooler" | "alternator" | "turbo" | "light" | "headlight" | "taillight" | "fog-light" | "indicator" | "daytime-running-light" | "interior-light" | "ambient-light" | "floor" | "floor-tile" | "floor-board" | "floor-mat" | "ceiling" | "ceiling-tile" | "wall" | "wall-tile" | "wall-panel" | "wall-trim" | "baseboard" | "crown-molding" | "column" | "pillar" | "beam" | "arch" | "stairs" | "step" | "railing" | "balustrade" | "window-frame" | "window-sill" | "blind" | "curtain" | "shutter" | "door" | "door-frame" | "door-knob" | "furniture" | "sofa" | "armchair" | "ottoman" | "bed" | "headboard" | "mattress" | "nightstand" | "dresser" | "wardrobe" | "closet" | "shelf" | "bookcase" | "desk" | "office-chair" | "dining-table" | "dining-chair" | "bar-stool" | "bench" | "cabinet" | "sideboard" | "coffee-table" | "side-table" | "tv-stand" | "kitchen-island" | "countertop" | "sink" | "bathtub" | "shower" | "toilet" | "vanity" | "decor" | "rug" | "cushion" | "throw" | "curtain-rod" | "artwork" | "mirror" | "vase" | "plant" | "pot" | "candle" | "frame" | "sculpture" | "clock" | "lamp" | "floor-lamp" | "table-lamp" | "pendant-light" | "chandelier" | "sconce" | "ceiling-fan" | "electronics" | "tv" | "monitor" | "speaker" | "soundbar" | "projector" | "remote" | "console" | "router" | "smart-hub" | "thermostat" | "appliance" | "refrigerator" | "oven" | "microwave" | "dishwasher" | "washing-machine" | "dryer" | "air-conditioner" | "heater" | "ventilation" | "root" | "bone" | "joint" | "socket" | "pivot" | "head" | "face" | "eye" | "eyelid" | "eyebrow" | "mouth" | "teeth" | "tongue" | "ear" | "nose" | "hair" | "beard" | "neck" | "torso" | "chest" | "abdomen" | "back" | "shoulder" | "upper-arm" | "forearm" | "hand" | "finger" | "thumb" | "hip" | "thigh" | "shin" | "foot" | "toe" | "tail" | "wing" | "tentacle" | "clothing" | "hat" | "helmet" | "visor" | "mask" | "goggles" | "glasses" | "jacket" | "shirt" | "pants" | "skirt" | "shoes" | "boots" | "gloves" | "belt" | "watch" | "bag" | "backpack" | "jewelry" | "necklace" | "ring" | "armor" | "chest-plate" | "pauldron" | "gauntlet" | "greave" | "shield" | "weapon" | "blade" | "edge" | "tip" | "guard" | "grip" | "pommel" | "barrel" | "stock" | "scope" | "trigger" | "magazine" | "muzzle" | "gear" | "piston" | "lever" | "valve" | "pump" | "motor" | "rotor" | "blade-prop" | "nozzle" | "pipe" | "tube" | "cable" | "wire" | "connector" | "panel" | "hatch" | "vent" | "antenna" | "sensor" | "camera" | "screen" | "dial" | "button" | "knob" | "switch" | "gauge" | "terrain" | "ground" | "rock" | "cliff" | "water" | "ocean" | "river" | "lake" | "wave" | "foam" | "sky" | "cloud" | "sun" | "moon" | "star" | "fog" | "foliage" | "tree" | "branch" | "leaf" | "grass" | "bush" | "flower" | "soil" | "sand" | "snow" | "ice" | "facade" | "foundation" | "roof-structure" | "chimney" | "balcony" | "porch" | "pathway" | "fence" | "gate" | "wall-exterior" | (string & {});
446
470
  type ObjectBindingStatus = "normal" | "hidden" | "selected" | "disabled";
447
471
  type ObjectBindingTextureSlot = {
448
472
  path: string;
473
+ /** UV position offset [u, v]. */
474
+ offset?: [number, number];
475
+ /** UV zoom scale. 1 = default, >1 = zoom in, <1 = zoom out. */
476
+ scale?: number;
477
+ rotation?: number;
449
478
  };
450
479
  type ObjectBindingTextureChannel = "baseColor" | "metalness" | "roughness" | "emissive" | "alpha" | "normal" | "bump" | "ao" | "displacement" | "clearcoat" | "clearcoatRoughness" | "clearcoatNormal" | "anisotropy" | "transmission" | "thickness" | "sheenColor" | "sheenRoughness" | "specularIntensity" | "specularColor";
451
480
  type ObjectBindingTransform = {
@@ -525,7 +554,8 @@ type ObjectBindingStyle = {
525
554
  };
526
555
  type ObjectBinding = {
527
556
  id: string;
528
- type: ObjectBindingType;
557
+ /** Defaults to `"other"`. */
558
+ type?: ObjectBindingType;
529
559
  modelObjectId: string;
530
560
  label?: string;
531
561
  group?: string;
@@ -548,5 +578,27 @@ type ObjectActionEvent = {
548
578
  screenX?: number;
549
579
  screenY?: number;
550
580
  };
581
+ /** A double-click, right-click, or long-press on a model object. */
582
+ type ObjectPointerEvent = {
583
+ binding: ObjectBinding;
584
+ /** Viewport coordinates, e.g. to place a menu with `position: fixed`. */
585
+ clientX: number;
586
+ clientY: number;
587
+ /** `"mouse"`, `"pen"`, or `"touch"`. */
588
+ pointerType: string;
589
+ };
590
+
591
+ /** One bindable object in a model, as reported by `onObjectCatalog`. */
592
+ type ViewerObjectInfo = {
593
+ /** The node identifier bindings are keyed by. */
594
+ name: string;
595
+ triangles: number;
596
+ /**
597
+ * Axis-aligned bounds in the model's own units, in Z-up coordinates (the 3D
598
+ * Tiles convention): a glTF point (x, y, z) is (x, -z, y) here.
599
+ */
600
+ minimum: [number, number, number];
601
+ maximum: [number, number, number];
602
+ };
551
603
 
552
- export { type AnimationAction as A, type BindingEdit as B, type CameraAction as C, DEFAULT_SCENE_CONFIG as D, type SceneLightType as E, type SceneModelRenderer as F, type VisibilityActionEffect as G, material as H, patchBindings as I, patchSceneConfig as J, selectBindingKeys as K, selectBindings as L, MATERIAL_BLENDING_MODES as M, type ObjectActionEffect as O, type SceneAnimationClipConfig as S, type ViewerCameraState as V, type AnimationActionEffect as a, type AnimationLoopMode as b, type CameraActionEffect as c, MATERIAL_SIDES as d, type ObjectActionEvent as e, type ObjectBinding as f, type ObjectBindingAction as g, type ObjectBindingMaterial as h, type ObjectBindingMaterialBlendingMode as i, type ObjectBindingMaterialSide as j, type ObjectBindingPatch as k, type ObjectBindingSelector as l, type ObjectBindingTarget as m, type ObjectBindingTextureChannel as n, type ObjectBindingTextureSlot as o, type ObjectBindingTransform as p, type ObjectBindingsActionEffect as q, type SceneAnimationConfig as r, type SceneAnnotationMarker as s, type SceneCinematicConfig as t, type SceneCinematicWaypoint as u, type SceneConfig as v, type SceneConfigActionEffect as w, type SceneConfigPatch as x, type SceneLight as y, type SceneLightAttachment as z };
604
+ export { type SceneWireframeConfig as $, type AnimationAction as A, type BindingEdit as B, type CameraAction as C, DEFAULT_SCENE_CONFIG as D, type EnvironmentPreset as E, type SceneCameraConfig as F, type GlitchModeName as G, type SceneCinematicConfig as H, type SceneCinematicWaypoint as I, type SceneConfig as J, type KernelSizeName as K, type SceneConfigActionEffect as L, MATERIAL_BLENDING_MODES as M, type SceneConfigPatch as N, type ObjectActionEffect as O, type SceneEnvironmentConfig as P, type SceneGroundShadowConfig as Q, type RampTypeName as R, type SceneAnimationClipConfig as S, type SceneLight as T, type SceneLightAttachment as U, type SceneLightType as V, type SceneLightingConfig as W, type SceneModelConfig as X, type SceneModelRenderer as Y, type ScenePostProcessingConfig as Z, type SceneShadowConfig as _, type AnimationActionEffect as a, type ViewerCameraConfig as a0, type ViewerCameraState as a1, type ViewerObjectInfo as a2, type VisibilityActionEffect as a3, material as a4, patchBindings as a5, patchSceneConfig as a6, selectBindingKeys as a7, selectBindings as a8, type AnimationLoopMode as b, type CameraActionEffect as c, type DeepPartial as d, MATERIAL_SIDES as e, type ObjectActionEvent as f, type ObjectBinding as g, type ObjectBindingAction as h, type ObjectBindingCameraState as i, type ObjectBindingMaterial as j, type ObjectBindingMaterialBlendingMode as k, type ObjectBindingMaterialSide as l, type ObjectBindingPatch as m, type ObjectBindingSelector as n, type ObjectBindingStatus as o, type ObjectBindingStyle as p, type ObjectBindingTarget as q, type ObjectBindingTextureChannel as r, type ObjectBindingTextureSlot as s, type ObjectBindingTransform as t, type ObjectBindingType as u, type ObjectBindingsActionEffect as v, type ObjectPointerEvent as w, type SceneAnimationConfig as x, type SceneAnnotationMarker as y, type SceneBackgroundConfig as z };
@@ -0,0 +1,12 @@
1
+ /** Props of `BindingBuilder`. */
2
+ type BindingBuilderProps = {
3
+ licenseKey: string;
4
+ /** Directory containing the DRACO decoder files, or false. */
5
+ dracoDecoderPath?: string | false;
6
+ /** Directory containing the Basis/KTX2 transcoder files, or false. */
7
+ ktx2TranscoderPath?: string | false;
8
+ /** Enable the bundled Meshopt decoder. Defaults to true. */
9
+ meshopt?: boolean;
10
+ };
11
+
12
+ export type { BindingBuilderProps as B };
@@ -0,0 +1,12 @@
1
+ /** Props of `BindingBuilder`. */
2
+ type BindingBuilderProps = {
3
+ licenseKey: string;
4
+ /** Directory containing the DRACO decoder files, or false. */
5
+ dracoDecoderPath?: string | false;
6
+ /** Directory containing the Basis/KTX2 transcoder files, or false. */
7
+ ktx2TranscoderPath?: string | false;
8
+ /** Enable the bundled Meshopt decoder. Defaults to true. */
9
+ meshopt?: boolean;
10
+ };
11
+
12
+ export type { BindingBuilderProps as B };
@@ -0,0 +1 @@
1
+ .bb-loadingOverlay{position:absolute;inset:0;z-index:5;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:16px;padding:24px;text-align:center;border-radius:14px;background:#f8fafcd1;backdrop-filter:blur(2px)}.bb-loadingSpinner{width:40px;height:40px;border-radius:999px;border:3px solid rgba(148,163,184,.3);border-top-color:#2563eb;animation:bb-spin .8s linear infinite}.bb-loadingProgressRow{display:flex;align-items:center;gap:8px;width:100%;max-width:240px}.bb-loadingProgress{flex:1;height:6px;border-radius:999px;background:#94a3b84d;overflow:hidden}.bb-loadingProgress__bar{height:100%;border-radius:inherit;background:#2563eb;transition:width .15s ease-out}.bb-loadingProgress__label{flex-shrink:0;min-width:34px;text-align:right;color:#475569;font-size:12px;font-weight:600;font-variant-numeric:tabular-nums}.bb-loadingMessage{max-width:320px;color:#475569;font-size:13px;font-weight:600;line-height:1.5}:root{--ri-styles-simple-model-viewer: 1}.smv-root{--smv-panel-font-family: Inter, "Segoe UI", Helvetica, Arial, sans-serif;--smv-panel-bg: #141824;--smv-panel-bg-strong: #1a1f2e;--smv-panel-bg-strong-hover: #252b3b;--smv-panel-border: rgba(255, 255, 255, .06);--smv-panel-border-strong: rgba(255, 255, 255, .08);--smv-panel-border-active: rgba(255, 255, 255, .18);--smv-panel-shadow-left: 4px 0 24px rgba(0, 0, 0, .35);--smv-panel-shadow-right: -4px 0 24px rgba(0, 0, 0, .35);--smv-panel-text: #f1f5f9;--smv-panel-text-emphasis: #ffffff;--smv-panel-text-muted: #94a3b8;--smv-panel-text-subtle: #64748b;--smv-panel-surface: rgba(255, 255, 255, .05);--smv-panel-surface-hover: rgba(255, 255, 255, .1);--smv-panel-surface-soft: rgba(255, 255, 255, .04);--smv-panel-accent: #3b82f6;--smv-panel-accent-contrast: #ffffff;position:relative;width:100%;height:100%;min-height:0;overflow:hidden;display:flex;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;text-rendering:optimizeLegibility;font-synthesis:none}.smv-canvasArea{flex:1;position:relative;min-width:0}.smv-upload-input{display:none}.smv-upload-toolbar{position:absolute;top:12px;left:50%;z-index:120;display:flex;align-items:center;gap:10px;max-width:calc(100% - 32px);padding:5px 6px;border:1px solid var(--smv-panel-border-strong);border-radius:10px;background:#141824e0;color:var(--smv-panel-text);box-shadow:0 16px 30px #00000047;backdrop-filter:blur(14px);transform:translate(-50%)}.smv-upload-toolbar__name{max-width:260px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;color:var(--smv-panel-text-muted);font-size:12px;font-weight:500}.smv-upload-toolbar__button{display:inline-flex;align-items:center;gap:7px;min-height:34px;padding:0 14px;border:1px solid rgba(255,255,255,.08);border-radius:10px;background:#3b82f62e;color:var(--smv-panel-text-emphasis);font-size:12px;font-weight:600;cursor:pointer}.smv-upload-toolbar__button--ghost{background:var(--smv-panel-surface);color:var(--smv-panel-text-muted)}.smv-upload-empty-state{display:flex;align-items:center;justify-content:center;width:100%;height:100%;padding:24px}.smv-upload-empty-state__card{width:min(440px,100%);padding:28px;border:1px dashed rgba(255,255,255,.2);border-radius:8px;color:var(--smv-panel-text);text-align:center;box-shadow:0 24px 40px #00000047;backdrop-filter:blur(14px)}.smv-upload-empty-state__icon{display:inline-flex;align-items:center;justify-content:center;width:56px;height:56px;margin-bottom:18px;border-radius:10px;background:#3b82f62e;color:#bfdbfe}.smv-upload-empty-state__title{margin:0 0 10px;color:var(--smv-panel-text-emphasis);font-size:24px;line-height:1.15}.smv-upload-empty-state__body{margin:0 0 18px;color:var(--smv-panel-text-muted);font-size:14px;font-weight:700;line-height:1.6}.smv-upload-empty-state__body code{color:var(--smv-panel-text-emphasis);font-family:var(--smv-panel-font-family)}.smv-upload-empty-state__button{display:inline-flex;align-items:center;gap:8px;min-height:40px;padding:0 18px;border:none;border-radius:8px;background:#3b82f6;color:#eff6ff;font-size:13px;font-weight:700;cursor:pointer}.smv-upload-drop-overlay{position:absolute;inset:0;z-index:130;display:flex;align-items:center;justify-content:center;padding:24px;background:#080c147a;backdrop-filter:blur(4px)}.smv-upload-drop-overlay__card{display:inline-flex;align-items:center;gap:10px;padding:16px 20px;border:1px dashed rgba(191,219,254,.75);border-radius:10px;background:#1e293beb;color:#dbeafe;font-size:14px;font-weight:700;box-shadow:0 18px 36px #00000047}.smv-canvasArea .bb-loadingOverlay{position:absolute;inset:0;z-index:110;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:16px;padding:24px;text-align:center;border-radius:14px;background:#0f172a75;backdrop-filter:blur(1px)}.smv-canvasArea .bb-loadingSpinner{width:40px;height:40px;border-radius:999px;border:3px solid rgba(226,232,240,.24);border-top-color:#93c5fd;animation:bb-spin .8s linear infinite}.smv-canvasArea .bb-loadingProgressRow{display:flex;align-items:center;gap:8px;width:100%;max-width:240px}.smv-canvasArea .bb-loadingProgress{flex:1;height:6px;border-radius:999px;background:#e2e8f03d;overflow:hidden}.smv-canvasArea .bb-loadingProgress__bar{height:100%;border-radius:inherit;background:#93c5fd;transition:width .15s ease-out}.smv-canvasArea .bb-loadingProgress__label{flex-shrink:0;min-width:34px;text-align:right;color:#f7f8fa;font-size:12px;font-weight:600;font-variant-numeric:tabular-nums}.smv-canvasArea .bb-loadingMessage{max-width:320px;color:#f7f8fa;font-size:13px;font-weight:600;line-height:1.5}@keyframes bb-spin{to{transform:rotate(360deg)}}.right-panel-wrapper{height:100%;transition:width .45s cubic-bezier(.4,0,.2,1);overflow:visible}.right-panel-wrapper--open{width:300px;flex-shrink:0}.right-panel-wrapper--closed{width:0;flex-shrink:0}.left-panel-wrapper{height:100%;transition:width .45s cubic-bezier(.4,0,.2,1);overflow:visible;order:-1}.left-panel-wrapper--open{width:280px;flex-shrink:0}.left-panel-wrapper--closed{width:0;flex-shrink:0}.side-panel__open-btn.side-panel__open-btn--left{left:12px;right:auto}.side-panel.side-panel--left{left:0;right:auto;width:280px;transform:translate(-100%);border-left:none;border-right:1px solid var(--smv-panel-border);box-shadow:var(--smv-panel-shadow-left)}.side-panel.side-panel--open-left{transform:translate(0)}.side-panel.side-panel--closed-left{transform:translate(-100%)}.env-controls{display:flex;flex-direction:column;overflow-y:auto;flex:1}.env-section{border-bottom:1px solid var(--smv-panel-border-strong)}.env-section__header{display:flex;align-items:center;gap:6px;width:100%;padding:9px 14px;border:none;background:var(--smv-panel-surface-soft);color:var(--smv-panel-text-muted);font-size:11px;font-weight:700;letter-spacing:.04em;text-transform:uppercase;cursor:pointer}.env-section__chevron{transition:transform .15s}.env-section__chevron--collapsed{transform:rotate(-90deg)}.env-section__body{display:flex;flex-direction:column}.env-row{display:flex;gap:6px;align-items:center;min-height:32px;border-bottom:1px solid var(--smv-panel-surface)}.env-row__label{flex:0 0 42%;padding:0 0 0 14px;font-size:11.5px;font-weight:500;color:var(--smv-panel-text-muted);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.env-row__value{flex:1;display:flex;align-items:center;padding:5px 10px 5px 8px;min-width:0}.env-row__value--slider{gap:6px}.env-checkbox-btn{display:flex;align-items:center;cursor:pointer;background:none;border:none;padding:0}.env-checkbox{width:15px;height:15px;border-radius:3px;border:1.5px solid var(--smv-panel-border-active);background:var(--smv-panel-surface-soft);display:flex;align-items:center;justify-content:center;transition:background .15s,border-color .15s}.env-checkbox--checked{background:var(--smv-panel-accent);border-color:var(--smv-panel-accent)}.env-select{width:100%;padding:5px 8px;border-radius:4px;border:none;background:var(--smv-panel-surface-hover);color:var(--smv-panel-text);font-size:11.5px;outline:none;box-sizing:border-box;text-transform:capitalize}.env-color-swatch{position:relative;width:100%;height:22px;border-radius:4px;border:1px solid rgba(255,255,255,.15);display:flex;align-items:center;justify-content:center;overflow:hidden;cursor:pointer}.env-color-swatch__hex{font-size:10.5px;font-weight:700;color:#0f172a;text-shadow:0 1px 1px rgba(255,255,255,.35);pointer-events:none;text-transform:uppercase}.env-color-swatch__input{position:absolute;inset:0;width:100%;height:100%;border:none;padding:0;opacity:0;cursor:pointer}.env-slider{flex:1;accent-color:var(--smv-panel-accent);cursor:pointer;min-width:0}.env-slider__value{flex-shrink:0;min-width:32px;padding:2px 5px;border-radius:4px;background:var(--smv-panel-surface-hover);color:var(--smv-panel-accent);font-size:10.5px;font-weight:600;text-align:center}.side-panel__open-btn{position:absolute;top:12px;right:12px;display:flex;align-items:center;gap:7px;padding:7px 13px;border-radius:7px;border:1px solid var(--smv-panel-border-strong);background:var(--smv-panel-bg-strong);cursor:pointer;font-size:13px;font-weight:500;color:var(--smv-panel-text);z-index:190;transition:background .15s}.side-panel__open-btn:hover{background:var(--smv-panel-bg-strong-hover)}.side-panel{position:absolute;top:0;right:0;width:300px;height:100%;background:var(--smv-panel-bg);display:flex;flex-direction:column;font-family:var(--smv-panel-font-family);transform:translate(100%);transition:transform .45s cubic-bezier(.4,0,.2,1);z-index:200;border-left:1px solid var(--smv-panel-border);box-shadow:var(--smv-panel-shadow-right)}.side-panel--open{transform:translate(0)}.side-panel--closed{transform:translate(100%)}.side-panel__header{padding:24px 20px 16px;border-bottom:1px solid var(--smv-panel-border-strong)}.side-panel__header-top{display:flex;align-items:center;justify-content:space-between;margin-bottom:4px}.side-panel__eyebrow{font-size:15px;font-weight:700;letter-spacing:.12em;color:var(--smv-panel-text-subtle);text-transform:uppercase}.side-panel__title{font-size:22px;font-weight:700;color:var(--smv-panel-text);margin:0;line-height:1.2}.side-panel__close-btn{display:flex;align-items:center;justify-content:center;width:30px;height:30px;border-radius:8px;border:1px solid var(--smv-panel-border-strong);background:var(--smv-panel-surface);cursor:pointer;color:var(--smv-panel-text-muted);transition:background .15s,color .15s;flex-shrink:0}.side-panel__close-btn:hover{background:var(--smv-panel-surface-hover);color:var(--smv-panel-text)}.side-panel__search-wrap{padding:14px 16px;border-bottom:1px solid var(--smv-panel-border-strong)}.side-panel__search{width:100%;padding:10px 14px;border-radius:10px;border:1px solid var(--smv-panel-border-strong);background:var(--smv-panel-surface);color:var(--smv-panel-text);font-size:13px;outline:none;box-sizing:border-box;transition:border-color .15s,background .15s}.side-panel__search::placeholder{color:var(--smv-panel-text-subtle)}.side-panel__search:focus{border-color:var(--smv-panel-border-active);background:var(--smv-panel-surface-hover)}.side-panel__list{display:flex;flex-direction:column;padding:10px 0;overflow-y:auto;flex:1}.side-panel__list::-webkit-scrollbar{width:4px}.side-panel__list::-webkit-scrollbar-track{background:transparent}.side-panel__list::-webkit-scrollbar-thumb{background:var(--smv-panel-surface-hover);border-radius:4px}.side-panel__row{display:flex;align-items:center;justify-content:space-between;padding:12px 20px;cursor:pointer;transition:background .12s;border-bottom:1px solid var(--smv-panel-surface-soft)}.side-panel__row:hover,.side-panel__row--hovered{background:var(--smv-panel-surface)}.side-panel__label{font-size:14px;font-weight:600;color:var(--smv-panel-text);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;flex:1}.side-panel__label--hovered{color:var(--smv-panel-text-emphasis)}.side-panel__vis-btn{display:flex;align-items:center;flex-shrink:0;cursor:pointer;background:none;border:none;padding:0;margin-left:10px}.side-panel__checkbox{width:16px;height:16px;border-radius:4px;border:1.5px solid var(--smv-panel-border-active);background:transparent;display:flex;align-items:center;justify-content:center;transition:background .15s,border-color .15s}.side-panel__checkbox--checked{background:var(--smv-panel-accent);border-color:var(--smv-panel-accent)}@media(max-width:900px){.smv-upload-toolbar{top:56px;gap:8px;max-width:calc(100% - 24px);padding:8px 10px}.smv-upload-toolbar__name{max-width:140px}.right-panel-wrapper--open,.left-panel-wrapper--open{width:0}.side-panel,.side-panel.side-panel--left{width:min(300px,85vw)}}.smv-largeModelBanner{position:absolute;bottom:12px;left:50%;transform:translate(-50%);z-index:20;display:flex;align-items:center;gap:8px;padding:7px 12px 7px 10px;border-radius:8px;background:#1e1400e0;border:1px solid rgba(251,191,36,.35);backdrop-filter:blur(6px);-webkit-backdrop-filter:blur(6px);color:#fbbf24;font-size:12px;font-weight:500;line-height:1.4;pointer-events:auto;max-width:calc(100% - 32px);text-align:center}.smv-largeModelBanner__icon{flex-shrink:0}.smv-largeModelBanner__dismiss{flex-shrink:0;display:flex;align-items:center;justify-content:center;margin-left:4px;padding:2px;background:none;border:none;border-radius:4px;color:#fbbf24b3;cursor:pointer;transition:color .15s ease,background .15s ease}.smv-largeModelBanner__dismiss:hover{color:#fbbf24;background:#fbbf241f}
@@ -0,0 +1,38 @@
1
+ import * as react from 'react';
2
+ import { M as ModelFormat, a as ViewerModelInfo } from './modelInfo-CEmmvVCH.mjs';
3
+ export { V as ViewerModelBounds } from './modelInfo-CEmmvVCH.mjs';
4
+ import { PresetsType } from '@react-three/drei/helpers/environment-assets';
5
+
6
+ type SimpleModelViewerProps = {
7
+ modelUrl: string;
8
+ /** Explicit format for extensionless or signed model URLs. */
9
+ modelFormat?: ModelFormat;
10
+ /** Directory containing the DRACO decoder files, or false. */
11
+ dracoDecoderPath?: string | false;
12
+ /** Directory containing the Basis/KTX2 transcoder files, or false. */
13
+ ktx2TranscoderPath?: string | false;
14
+ /** Enable the bundled Meshopt decoder. Defaults to true. */
15
+ meshopt?: boolean;
16
+ backgroundColor?: string;
17
+ showSceneObjectsPanel?: boolean;
18
+ showSceneSettingsPanel?: boolean;
19
+ enableModelUpload?: boolean;
20
+ zoomOnSelected?: boolean;
21
+ highlightOnHover?: boolean;
22
+ showLoadingOverlay?: boolean;
23
+ refitOnResize?: boolean;
24
+ backgroundEnabled?: boolean;
25
+ autoRotate?: boolean;
26
+ envPreset?: PresetsType;
27
+ exposure?: number;
28
+ ambientIntensity?: number;
29
+ ambientColor?: string;
30
+ directionalIntensity?: number;
31
+ directionalColor?: string;
32
+ /** The model finished loading: its bounds and mesh count. */
33
+ onModelLoaded?: (model: ViewerModelInfo) => void;
34
+ onLoadError?: (error: unknown) => void;
35
+ };
36
+ declare function SimpleModelViewer({ modelUrl, modelFormat, dracoDecoderPath, ktx2TranscoderPath, meshopt, backgroundColor, showSceneObjectsPanel, showSceneSettingsPanel, enableModelUpload, zoomOnSelected, highlightOnHover, showLoadingOverlay, refitOnResize, backgroundEnabled, autoRotate, envPreset, exposure, ambientIntensity, ambientColor, directionalIntensity, directionalColor, onModelLoaded, onLoadError, }: SimpleModelViewerProps): react.JSX.Element;
37
+
38
+ export { ModelFormat, SimpleModelViewer, type SimpleModelViewerProps, ViewerModelInfo };
@@ -0,0 +1,38 @@
1
+ import * as react from 'react';
2
+ import { M as ModelFormat, a as ViewerModelInfo } from './modelInfo-CEmmvVCH.js';
3
+ export { V as ViewerModelBounds } from './modelInfo-CEmmvVCH.js';
4
+ import { PresetsType } from '@react-three/drei/helpers/environment-assets';
5
+
6
+ type SimpleModelViewerProps = {
7
+ modelUrl: string;
8
+ /** Explicit format for extensionless or signed model URLs. */
9
+ modelFormat?: ModelFormat;
10
+ /** Directory containing the DRACO decoder files, or false. */
11
+ dracoDecoderPath?: string | false;
12
+ /** Directory containing the Basis/KTX2 transcoder files, or false. */
13
+ ktx2TranscoderPath?: string | false;
14
+ /** Enable the bundled Meshopt decoder. Defaults to true. */
15
+ meshopt?: boolean;
16
+ backgroundColor?: string;
17
+ showSceneObjectsPanel?: boolean;
18
+ showSceneSettingsPanel?: boolean;
19
+ enableModelUpload?: boolean;
20
+ zoomOnSelected?: boolean;
21
+ highlightOnHover?: boolean;
22
+ showLoadingOverlay?: boolean;
23
+ refitOnResize?: boolean;
24
+ backgroundEnabled?: boolean;
25
+ autoRotate?: boolean;
26
+ envPreset?: PresetsType;
27
+ exposure?: number;
28
+ ambientIntensity?: number;
29
+ ambientColor?: string;
30
+ directionalIntensity?: number;
31
+ directionalColor?: string;
32
+ /** The model finished loading: its bounds and mesh count. */
33
+ onModelLoaded?: (model: ViewerModelInfo) => void;
34
+ onLoadError?: (error: unknown) => void;
35
+ };
36
+ declare function SimpleModelViewer({ modelUrl, modelFormat, dracoDecoderPath, ktx2TranscoderPath, meshopt, backgroundColor, showSceneObjectsPanel, showSceneSettingsPanel, enableModelUpload, zoomOnSelected, highlightOnHover, showLoadingOverlay, refitOnResize, backgroundEnabled, autoRotate, envPreset, exposure, ambientIntensity, ambientColor, directionalIntensity, directionalColor, onModelLoaded, onLoadError, }: SimpleModelViewerProps): react.JSX.Element;
37
+
38
+ export { ModelFormat, SimpleModelViewer, type SimpleModelViewerProps, ViewerModelInfo };