@liveroom-tech/react-immersive 5.1.0 → 5.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +486 -57
- package/dist/binding-builder.css +1 -1
- package/dist/binding-builder.js +17 -13
- package/dist/binding-builder.mjs +1 -1
- package/dist/chunk-4NLJSD3S.mjs +1 -0
- package/dist/chunk-B7REIGDG.mjs +1 -0
- package/dist/{chunk-WN6GMMHF.mjs → chunk-HYFJ5DYJ.mjs} +1 -1
- package/dist/chunk-QC3NT76G.mjs +3 -0
- package/dist/chunk-T3M3BQ7H.mjs +32 -0
- package/dist/chunk-ZPK67UG7.mjs +1 -0
- package/dist/hosted.css +1 -1
- package/dist/hosted.d.mts +4 -3
- package/dist/hosted.d.ts +4 -3
- package/dist/hosted.js +16 -12
- package/dist/hosted.mjs +1 -1
- package/dist/index.css +1 -1
- package/dist/index.d.mts +39 -8
- package/dist/index.d.ts +39 -8
- package/dist/index.js +14 -10
- package/dist/index.mjs +1 -1
- package/dist/materialVariants-DnZe9eMC.d.mts +309 -0
- package/dist/materialVariants-DnZe9eMC.d.ts +309 -0
- package/dist/modelInfo-BYebMPdZ.d.mts +43 -0
- package/dist/modelInfo-XfUQO7C_.d.ts +43 -0
- package/dist/{ModelViewer-Bj-KjiDL.d.mts → modelViewerProps-CIZ2R_Fv.d.ts} +82 -10
- package/dist/{ModelViewer-BkQ73y6N.d.ts → modelViewerProps-DoRiTZMn.d.mts} +82 -10
- package/dist/{objectCatalog-BIeXURoq.d.ts → rendererBackend-QwMzISTn.d.mts} +32 -4
- package/dist/{objectCatalog-BIeXURoq.d.mts → rendererBackend-QwMzISTn.d.ts} +32 -4
- package/dist/simple-model-viewer.css +1 -1
- package/dist/simple-model-viewer.d.mts +32 -4
- package/dist/simple-model-viewer.d.ts +32 -4
- package/dist/simple-model-viewer.js +3 -3
- package/dist/simple-model-viewer.mjs +1 -1
- package/dist/utils.d.mts +5 -4
- package/dist/utils.d.ts +5 -4
- package/dist/utils.js +1 -1
- package/dist/utils.mjs +1 -1
- package/package.json +2 -1
- package/dist/chunk-32WCLPTZ.mjs +0 -1
- package/dist/chunk-CSGNL4XU.mjs +0 -3
- package/dist/chunk-F2ILTIPG.mjs +0 -28
- package/dist/chunk-V6GALFL5.mjs +0 -1
- package/dist/modelInfo-DnkmTGMd.d.mts +0 -23
- package/dist/modelInfo-DnkmTGMd.d.ts +0 -23
package/dist/binding-builder.mjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
"use client";import{a as i,c as r}from"./chunk-SEESCGUS.mjs";import{a as e}from"./chunk-MMO7KCYU.mjs";import{a as n}from"./chunk-
|
|
1
|
+
"use client";import{a as i,c as r}from"./chunk-SEESCGUS.mjs";import{a as e}from"./chunk-MMO7KCYU.mjs";import{a as n}from"./chunk-QC3NT76G.mjs";import"./chunk-T3M3BQ7H.mjs";import"./chunk-ZPK67UG7.mjs";import"./chunk-B7REIGDG.mjs";import"./chunk-4NLJSD3S.mjs";import"./chunk-JR557W27.mjs";import{jsx as B}from"react/jsx-runtime";function o(d){return e("binding-builder","BindingBuilder"),B(n,{...r(d,i)})}export{o as BindingBuilder};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
var S={verifyingLicense:"Verifying License",checkingYourLicenseKey:"Checking your license key...",invalidLicense:"Invalid License",licenseHasBeenRevokedOrHasExpired:"License has been revoked or has expired",failedToLoadPleaseContactTheSiteAdministrator:"Failed to load. Please contact the site administrator.",contextRestoringTitle:"Reloading viewer\u2026",contextLostTitle:"3D view interrupted",contextRestoringMessage:"Rebuilding the 3D view. Please wait\u2026",contextLostMessage:"The graphics connection was interrupted. The viewer will rebuild when it returns, or you can reload it now.",reloadViewer:"Reload viewer",texturePositioningHint:"Drag to move \xB7 Scroll to zoom \xB7 Click elsewhere to finish",texturePositioningStartHint:"Double-click to move or zoom",dismiss:"Dismiss",missingUVsAreShownInMagenta:"Missing UVs are shown in magenta.",viewThisModelInARWithAppleQuickLook:"View this model in AR with Apple Quick Look",viewInAR:"View in AR",openThisExperienceOnAPhoneForAR:"Open this experience on a phone for AR",openOnPhone:"Open on phone",viewThisModelInYourSpace:"View this model in your space",viewThisModelInVR:"View this model in VR",closePhoneHandoff:"Close phone handoff",arScanCode:"Scan the code and choose AR.",qrCodeToOpenThisModelOnAPhone:"QR code to open this model on a phone",disableUVChecker:"Disable UV checker",enableUVChecker:"Enable UV checker",explodedView:"Exploded view",explodeAmount:"Explode amount",removeSectionCut:"Remove section cut",sectionCut:"Section cut",sectionAxis:"Section axis",sectionPosition:"Section position",keepTheOtherSide:"Keep the other side",pauseCinematic:"Pause cinematic",playCinematic:"Play cinematic",stopCinematicAndResetCamera:"Stop cinematic and reset camera",cancel:"Cancel",annotationCategories:"Annotation categories",annotations:"Annotations",all:"All",uncategorized:"Uncategorized",decalDragHint:"Drag the decal on the object. Release to save; Escape to cancel.",showAll:"Show all",materialVariants:"Material variants",startGuidedTour:"Start guided tour",guidedTour:"Guided Tour",previousAnnotation:"Previous annotation",previous:"Prev",stopGuidedTour:"Stop guided tour",nextAnnotation:"Next annotation",next:"Next",exitFullscreen:"Exit fullscreen",enterFullscreen:"Enter fullscreen",resetCameraView:"Reset camera view",orbitControl:"Orbit Control",pointLock:"Point Lock",cameraController:"Camera controller",cameraControllerSettings:"Camera controller settings",downloadGLB:"Download GLB",downloadPNG:"Download PNG",downloadUVLayout:"Download UV Layout",videoFormat:"Video format",auto:"Auto",recordTurntableVideo:"Record turntable video",recordCinematicVideo:"Record cinematic video",videoUnsupported:"Video recording is not supported in this browser.",downloadOptions:"Download options",exporting:"Exporting\u2026",download:"Download",annotationTitlePlaceholder:"Title *",description:"Description",ok:"OK",arRelocate:"Relocate",tapToPlace:"Tap to place",closeAnnotation:"Close annotation",learnMore:"Learn more",stopMeasuring:"Stop measuring",startMeasuring:"Start measuring",toggleBoundingDimensions:"Toggle bounding dimensions",measurementTool:"Measurement tool",distance:"Distance",angle:"Angle",area:"Area",pointToPlane:"Point to plane",measurementSnapping:"Measurement snapping",noSnapping:"No snapping",snapAuto:"Snap: auto",snapVertex:"Snap: vertex",snapEdge:"Snap: edge",undoMeasurementPoint:"Undo measurement point",clearMeasurements:"Clear measurements",finishArea:"Finish area",openSceneObjectsPanel:"Open scene objects panel",sceneObjects:"SCENE OBJECTS",searchNodesLabels:"Search nodes, labels",closeSceneObjectsPanel:"Close scene objects panel",objectNavigator:"Objects in the 3D view",compareBefore:"Before",compareAfter:"After",compareDivider:"Comparison divider",viewIn3D:"View in 3D",objectNavigatorHint:"Arrow keys browse \xB7 Enter selects \xB7 Esc clears",selectionCleared:"Selection cleared",cameraKeyboardHelp:"3D view. Arrow keys orbit, Shift with Up or Down zooms, and W, A, S, D, Space and C move the camera.",isolate:"Isolate",hide:"Hide",show:"Show",closePanel:"Close panel",actions:"Actions",openPanel:"Open panel",close:"Close",position:"Position",decalNudgeHint:"Click to fine-tune \xB7 Hold to move",decalNudgeControls:"Move decal in small steps",text:"Text",yourText:"Your text",textToAdd:"Text to add",textColour:"Text colour",addText:"Add text",image:"Image",chooseImage:"Choose image",imageToAdd:"Image to add",added:"Added",colour:"Colour",size:"Size",turn:"Turn",rotation:"Rotation",dragTheDecalAcrossTheObjectsSurface:"Drag the decal across the object's surface",move:"Move",remove:"Remove",noneAddedYet:"None added yet",done:"Done",moveForward:"Move forward",moveLeft:"Move left",moveRight:"Move right",moveBackward:"Move backward",sceneSettings:"Scene Settings",background:"Background",backgroundColor:"Background Color",environment:"Environment",autoRotate:"Auto Rotate",lighting:"Lighting",exposure:"Exposure",ambientLightIntensity:"Ambient Light Intensity",ambientLightColor:"Ambient Light Color",directLightIntensity:"Direct Light Intensity",directLightColor:"Direct Light Color",searchObjects:"Search objects",uploadedModel:"Uploaded model",clear:"Clear",chooseModel:"Choose model",loadingModel:"Loading model...",releaseToLoadYourModel:"Release to load your model",arFindSurface:"Move your device over a flat surface",arReleaseToPlace:"Release to place",arGestureHint:"Pinch to resize \xB7 Twist to rotate",angleFirstArmHint:"Pick the first arm",angleVertexHint:"Pick the angle's vertex",angleSecondArmHint:"Pick the second arm",angleNewHint:"Pick a point to start a new angle",areaNewHint:"Pick a point to start a new area",areaCornersHint:"Pick polygon corners in order, then Finish area",pointToPlaneFaceHint:"Pick the reference face",pointToPlanePointHint:"Pick a point to measure its perpendicular distance",pointToPlaneNewHint:"Pick a face to start a new measurement",distanceHint:"Pick points on the model to measure distances",visibleEntries:"{count} visible entries",objectCount:"{count} objects",annotationMarker:"Annotation {id}: {title}",recordingVideo:"Recording video \xB7 {progress}%",isolatedObjects:"Isolated: {count} objects",largeModelWarning:"Very large model ({millions}M triangles) \u2014 it may render and move slowly on this device, and click/hover selection on the model is disabled. Use the objects panel to select parts.",preparingLargeModel:"Preparing large model ({millions}M triangles) \u2014 the first display can take a while on this device...",enterAR:"Enter AR",enterVR:"Enter VR",decalImage:"Image {index}",decalText:"Text {index}",decalAdded:"{count} added",up:"up",down:"down",left:"left",right:"right",moveDecal:"Move decal {direction}",moveDecalOnSurface:"Move {direction} on the visible surface",showAllObject:"Show all {name}",isolateObject:"Isolate {name}",isolatedObject:"Isolated: {name}",hideObject:"Hide {name}",showObject:"Show {name}",objectSelected:"{name} selected",objectNavigatorPosition:"{position} of {count}",compareDividerValue:"{before} {percent}%, {after} {rest}%",bindingMismatchOne:"1 object binding doesn't match this model",bindingMismatchMany:"{count} object bindings don't match this model",simpleLargeModelWarning:"Very large model detected ({millions}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.",dropModelHint:"Drag and drop {formats} here",loadErrorTitle:"This model couldn't be loaded",loadErrorNotFound:"Nothing was found at this address ({status}). Check that modelUrl points to the file.",loadErrorDenied:"The server refused access to the file ({status}). Check that the file is public, or that a signed URL hasn't expired.",loadErrorStatus:"The server responded with {status} when the file was requested.",loadErrorNetwork:"The download was blocked or failed. Check that the URL is correct and, if the file is on another domain, that its server allows cross-origin requests (CORS) from this site.",loadErrorHtml:"The server sent back a web page instead of a model. There's probably no file at this path: many servers answer a missing file with their index.html.",loadErrorInvalidFile:"The file couldn't be read as {format}. Check that it's a valid {format} file.",loadErrorInvalidExplicitFormat:"The file couldn't be read as {format}. Check that it's a valid {format} file and that modelFormat matches it.",loadErrorMissingFormat:"The file couldn't be read as {format}. The URL has no file extension, so set modelFormat to the file's format.",loadErrorPointCloud:"This PLY file is a point cloud: it has points but no faces, and the viewer shows meshes. Turn it into a mesh first, for example with MeshLab or Blender.",measurementReferenceFaceRequired:"Pick a triangle face to define the reference plane.",measurementTooManyPoints:"Finish or clear this measurement before adding more points.",measurementAngleDistinct:"Pick a point away from the angle's vertex.",areaMinimumPoints:"Pick at least three points to finish the area.",areaDistinctPoints:"Area points must be distinct.",areaStraightLine:"Area points must not lie on one straight line.",areaNotPlanar:"Area points must lie on one plane.",areaEdgesCross:"Area edges must not cross or touch each other.",areaZero:"The polygon has no measurable area.",decalSurfaceMissing:"Could not find a surface on this object for the decal.",decalDirectionMissing:"No visible surface in that direction. Try another arrow or rotate the view.",fullscreenExitFailed:"Could not exit fullscreen. Press Escape to exit.",fullscreenEnterFailed:"Could not enter fullscreen. Check your browser or iframe fullscreen permissions and try again.",uvCoordinatesMissing:"This model does not contain UV coordinates.",uvExportFailed:"Could not create the UV layout archive.",videoExportFailed:"Could not export the video.",videoNotReady:"Viewer not ready for video export.",videoExitXR:"Exit the XR session before recording a video.",videoAlreadyRecording:"A video export is already in progress.",videoPathRequired:"Enable a cinematic camera path before recording it.",videoDurationInvalid:"Video duration must be greater than 0 and at most 300 seconds.",videoFrameRateInvalid:"Video frame rate must be between 1 and 60.",videoBitrateInvalid:"Video bitrate must be a positive number.",videoContextLost:"Video export stopped because the WebGL context was lost.",videoTimedOut:"Video export timed out. Keep the viewer tab visible while recording.",videoEncodingFailed:"The browser could not encode the video.",videoEmpty:"The browser produced an empty video.",videoDidNotStart:"Video recording did not start.",videoWebMUnsupported:"Video recording as WEBM is not supported in this browser.",videoMP4Unsupported:"Video recording as MP4 is not supported in this browser.",videoGIFUnsupported:"Video recording as GIF is not supported in this browser.",videoGifWidthInvalid:"GIF width must be a whole number of pixels from 16 to 4096.",environmentApartment:"apartment",environmentCity:"city",environmentDawn:"dawn",environmentForest:"forest",environmentLobby:"lobby",environmentNight:"night",environmentPark:"park",environmentStudio:"studio",environmentSunset:"sunset",environmentWarehouse:"warehouse",color:"Color",material:"Material",texturePreview:"texture preview",noTextureApplied:"No texture applied",noTextureCoordinates:"This part has no texture coordinates, so an image can't be placed on it.",replaceImage:"Replace image",uploadImage:"Upload image",removeTexture:"Remove texture",texturePosition:"Texture position",offsetX:"Offset X",offsetY:"Offset Y",confirmTexturePosition:"Confirm this texture position and exit positioning mode",donePositioning:"Done positioning",textureOffsetHint:"Double-click the object in the preview to drag its texture directly (scroll to zoom), or edit its offset numerically.",actionToggleLight:"Toggle Light",actionChangeLightColor:"Change Light Color",actionSetBrightness:"Set Brightness",actionChangeColor:"Change Color",actionChangeMaterial:"Change Material",actionToggleVisibility:"Toggle Visibility"};function E(e,t,n={}){return(e?.[t]??S[t]).replace(/\{(\w+)\}/g,(s,l)=>Object.prototype.hasOwnProperty.call(n,l)?String(n[l]):s)}var L=new Map(Object.entries(S).map(([e,t])=>[t,e]));function X(e,t){let n=L.get(t);return n?E(e,n):t}var w="KHR_materials_variants",V="riMaterialVariants",P="riMaterialVariantGroups";function c(e){return typeof e=="object"&&e!==null&&!Array.isArray(e)}function O(e){if(!c(e)||!c(e.extensions))return[];let t=e.extensions[w];if(!c(t)||!Array.isArray(t.variants))return[];let n=new Set;return t.variants.map((o,s)=>{let l=c(o)&&typeof o.name=="string"&&o.name?o.name:`Variant ${s+1}`,d=l;for(let g=2;n.has(d);g+=1)d=`${l} (${g})`;return n.add(d),d})}function q(e){let t=e.userData?.gltfExtensions;if(!c(t))return[];let n=t[w];return!c(n)||!Array.isArray(n.mappings)?[]:n.mappings.filter(o=>c(o)&&Number.isInteger(o.material)&&Array.isArray(o.variants)&&o.variants.every(Number.isInteger))}function Q(e,t){for(let n=t.length-1;n>=0;n-=1){let o=t[n];if(o<0)continue;let s=e.find(l=>l.variants.includes(o));if(s)return s.material}return null}var D=/^\s*(.+?)\s*(?::|\s\/\s)\s*(.+?)\s*$/;function N(e){let t=Math.min(Math.max(e,0),1),n=t<=.0031308?t*12.92:1.055*t**(1/2.4)-.055;return Math.round(n*255)}function j(e){if(!c(e))return;let t=c(e.pbrMetallicRoughness)?e.pbrMetallicRoughness:{};if(t.baseColorTexture!==void 0)return;let n=Array.isArray(t.baseColorFactor)?t.baseColorFactor:[1,1,1,1];if(n.slice(0,3).every(o=>typeof o=="number"))return`#${n.slice(0,3).map(o=>N(o).toString(16).padStart(2,"0")).join("")}`}function I(e,t){if(t.length===0)return[];let n=c(e)?e:{},o=Array.isArray(n.meshes)?n.meshes:[],s=Array.isArray(n.accessors)?n.accessors:[],l=Array.isArray(n.materials)?n.materials:[],d=t.map(()=>new Set),g=t.map(()=>new Map);o.forEach((r,a)=>{(c(r)&&Array.isArray(r.primitives)?r.primitives:[]).forEach((p,i)=>{if(!c(p))return;let m=c(p.extensions)?p.extensions[w]:void 0;if(!c(m)||!Array.isArray(m.mappings))return;let b=c(p.attributes)?p.attributes.POSITION:void 0,x=typeof b=="number"?s[b]:void 0,R=c(x)&&typeof x.count=="number"?x.count:1;for(let M of m.mappings)if(!(!c(M)||!Number.isInteger(M.material)||!Array.isArray(M.variants)))for(let y of M.variants){if(!Number.isInteger(y)||!d[y])continue;d[y].add(`${a}/${i}`);let A=g[y],C=M.material;A.set(C,(A.get(C)??0)+R)}})});let T=t.map((r,a)=>{let u=null;for(let[i,m]of g[a])(u===null||m>(g[a].get(u)??0))&&(u=i);let p=u===null?void 0:j(l[u]);return{name:r,label:r,...p?{swatch:p}:{}}}),f=t.map(()=>-1),h=[],v=new Map;return t.forEach((r,a)=>{let u=D.exec(r);if(!u)return;let[,p,i]=u;v.has(p)||(v.set(p,h.length),h.push({name:p,members:[]})),f[a]=v.get(p),h[f[a]].members.push(a),T[a].label=i}),t.map((r,a)=>a).filter(r=>f[r]<0).sort((r,a)=>+(d[r].size===0)-+(d[a].size===0)).forEach(r=>{let a=h.map((i,m)=>({group:i,groupIndex:m})).filter(({group:i})=>i.name===null&&i.members.some(m=>d[r].size===0||d[m].size===0?!1:[...d[r]].some(b=>d[m].has(b)))).map(({groupIndex:i})=>i);if(a.length===0&&d[r].size===0){let i=h.findIndex(m=>m.name===null);i>=0&&a.push(i)}if(a.length===0){f[r]=h.length,h.push({name:null,members:[r]});return}let[u,...p]=a;for(let i of p){for(let m of h[i].members)f[m]=u;h[u].members.push(...h[i].members),h[i].members=[]}f[r]=u,h[u].members.push(r)}),h.filter(r=>r.members.length>0).sort((r,a)=>Math.min(...r.members)-Math.min(...a.members)).map(r=>({name:r.name,variants:[...r.members].sort((a,u)=>a-u).map(a=>T[a])}))}function J(e,t,n){let o=n.find(l=>l.variants.some(d=>d.name===t)),s=new Set(o?.variants.map(l=>l.name)??[t]);return[...e.filter(l=>!s.has(l)),t]}function Z(e){if(Array.isArray(e.activeVariants))return e.activeVariants.filter(n=>typeof n=="string");let t=e.materialVariant;return typeof t=="string"&&t?[t]:[]}function ee(e){let t=e.parser,n=O(t?.json);if(!(!t||n.length===0))return e.scene.userData[V]=n,e.scene.userData[P]=I(t.json,n),{names:n,resolveMaterial:async(o,s)=>{let l={geometry:s.geometry,material:await t.getDependency("material",o),isPoints:s.isPoints,isLine:s.isLine};return t.assignFinalMaterial(l),l.material}}}function F(e){let t=e.userData?.[V];return Array.isArray(t)&&t.every(n=>typeof n=="string")?t:[]}function te(e){let t=e.userData?.[P];if(Array.isArray(t))return t;let n=F(e);return n.length>0?[{name:null,variants:n.map(o=>({name:o,label:o}))}]:[]}function ne(e,t){let{materialVariant:n,...o}=e;return{...o,activeVariants:t}}import{AdditiveBlending as B,BackSide as G,DoubleSide as U,FrontSide as H,NoColorSpace as K,NormalBlending as _,SRGBColorSpace as z,Vector2 as k}from"three";function pe(e){let t=!0;return e?.traverse(n=>{let o=n.isMesh?n.geometry:null;o&&!o.getAttribute("uv")&&(t=!1)}),t}function me(e){return!!(e&&typeof e=="object"&&"clone"in e&&"color"in e&&"metalness"in e&&"roughness"in e)}function he(e){return!!(e&&typeof e=="object"&&"isMeshPhysicalMaterial"in e&&e.isMeshPhysicalMaterial)}function ge(e){return!!(e&&"isMesh"in e&&e.isMesh)}var fe=["texture","metalnessMap","roughnessMap","emissiveMap","alphaMap","normalMap","bumpMap","aoMap","displacementMap","clearcoatMap","clearcoatRoughnessMap","clearcoatNormalMap","anisotropyMap","transmissionMap","thicknessMap","sheenColorMap","sheenRoughnessMap","specularIntensityMap","specularColorMap"],Me={texture:"map",metalnessMap:"metalnessMap",roughnessMap:"roughnessMap",emissiveMap:"emissiveMap",alphaMap:"alphaMap",normalMap:"normalMap",bumpMap:"bumpMap",aoMap:"aoMap",displacementMap:"displacementMap",clearcoatMap:"clearcoatMap",clearcoatRoughnessMap:"clearcoatRoughnessMap",clearcoatNormalMap:"clearcoatNormalMap",anisotropyMap:"anisotropyMap",transmissionMap:"transmissionMap",thicknessMap:"thicknessMap",sheenColorMap:"sheenColorMap",sheenRoughnessMap:"sheenRoughnessMap",specularIntensityMap:"specularIntensityMap",specularColorMap:"specularColorMap"},Y=new Set(["texture","emissiveMap","sheenColorMap","specularColorMap"]);function be(e){return Y.has(e)?z:K}function ye(e,t){return e?.[t]?.path}function ve(e,t){let n=e?.[t]?.offset;if(!n)return;let[o,s]=n;if(!(!Number.isFinite(o)||!Number.isFinite(s)))return o===0&&s===0?void 0:[o,s]}function xe(e,t){let n=e?.[t]?.scale;if(!(!Number.isFinite(n)||!n))return n===1?void 0:n}function we(e,t){let n=e?.[t]?.rotation;if(!(!Number.isFinite(n)||!n))return n}function Te(e){return e==="back"?G:e==="double"?U:H}function Ae(e){return e==="additive"?B:_}function Ce(e,t=1,n=t){if(e&&typeof e=="object"){let o=e;if(typeof o.x=="number"&&Number.isFinite(o.x)&&typeof o.y=="number"&&Number.isFinite(o.y))return new k(o.x,o.y)}return new k(t,n)}function Se(e){return Number.isFinite(e)&&e>0?e:1}function Ve(e,t){return e?.animations.clips.find(n=>n.sourceName===t)}function Pe(e){return e?.loopMode??"repeat"}export{S as a,E as b,X as c,pe as d,me as e,he as f,ge as g,fe as h,Me as i,be as j,ye as k,ve as l,xe as m,we as n,Te as o,Ae as p,Ce as q,Se as r,Ve as s,Pe as t,q as u,Q as v,J as w,Z as x,ee as y,F as z,te as A,ne as B};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{d as O}from"./chunk-4NLJSD3S.mjs";var f=Object.freeze([{id:"change-color",label:"Change Color",handling:"viewer",description:"Opens a color picker docked under the action and commits the result to style.material.baseColor."},{id:"change-material",label:"Change Material",handling:"viewer",description:"Opens the material picker so the viewer can swap the object's texture."},{id:"add-text",label:"Add Text",handling:"viewer",description:"Opens a text box docked under the action; the viewer's user types, clicks the object to place it, and can resize, turn, move, or remove it. Saved to the binding's decals."},{id:"add-image",label:"Add Image",handling:"viewer",description:"Lets the viewer's user choose an image, click the object to place it, and resize, turn, move, or remove it. Saved to the binding's decals."},{id:"toggle-visibility",label:"Toggle Visibility",handling:"viewer",description:"Flips the binding's visible flag."},{id:"toggle-light",label:"Toggle Light",handling:"viewer",description:"Turns the scene lights attached to this object on or off, or the object's own glow when none is attached."},{id:"change-light-color",label:"Change Light Color",handling:"viewer",description:"Opens a color picker docked under the action for the scene lights attached to this object, or the object's own glow."},{id:"set-brightness",label:"Set Brightness",handling:"viewer",description:"Opens a brightness slider docked under the action for the scene lights attached to this object, or the object's own glow."}]),Y="__custom__";function A(n){return f.find(e=>e.id===n)}var x=f.filter(n=>n.handling==="viewer").map(n=>n.id),E=new Set(["","New Action",...f.map(n=>n.label)]);function X(n){return E.has(n.trim())}function j(n,e){let t=Array.from({length:e.length+1},(r,i)=>i);for(let r=1;r<=n.length;r+=1){let i=[r];for(let l=1;l<=e.length;l+=1){let s=t[l-1]+(n[r-1]===e[l-1]?0:1);i[l]=Math.min(i[l-1]+1,t[l]+1,s)}t=i}return t[e.length]}function Z(n){if(A(n))return null;let e=n.trim().toLowerCase();if(!e)return null;let t=e.replace(/[^a-z0-9]/g,""),r=null;for(let i of f){let l=Math.min(j(e,i.id),j(t,i.id.replace(/[^a-z0-9]/g,"")));(!r||l<r.distance)&&(r={id:i.id,distance:l})}return r&&r.distance<=2?r.id:null}function J(n){let e=n.trim();return e?/\.(hdr|exr|jpg|jpeg|png|webp)(?:[?#].*)?$/i.test(e):!1}var Q=["none","directional","point","spot","hemisphere"],ee=["pbr","matcap","uv-checker"],ne=["apartment","city","dawn","forest","lobby","night","park","studio","sunset","warehouse"];var te=["sporadic","constantMild","constantWild"],re=["linear","radial","mirroredLinear"],ie=["verySmall","small","medium","large","veryLarge","huge"],oe=["x","y","z"],ae={enabled:!1,axis:"y",position:.5,flip:!1},I={clips:[],autoplayClip:null},k={autofocus:{enabled:!1,focusDistance:5,focusRange:5,focalLength:.02,bokehScale:6,target:[0,0,0],mouse:!0,debug:0,manual:!1,smoothTime:.25},toneMapping:{enabled:!1,mode:"aces",exposure:1,resolution:256,whitePoint:4,middleGrey:.6,minLuminance:.01,averageLuminance:1,adaptationRate:1},brightnessContrast:{enabled:!1,brightness:0,contrast:0},hueSaturation:{enabled:!1,hue:0,saturation:0},colorAverage:{enabled:!1},dotScreen:{enabled:!1,angle:Math.PI/2,scale:1},glitch:{enabled:!1,mode:"sporadic",delay:[1.5,3.5],duration:[.6,1],strength:[.3,1],chromaticAberrationOffset:[0,0],columns:.05,ratio:.85},ssao:{enabled:!1,samples:30,rings:4,intensity:8,radius:.25,bias:.025,luminanceInfluence:.6,fade:.01,minRadiusScale:.33,worldDistanceThreshold:20,worldDistanceFalloff:5,worldProximityThreshold:6,worldProximityFalloff:3},bloom:{enabled:!1,intensity:.3,luminanceThreshold:.9,luminanceSmoothing:.2,mipmapBlur:!0,radius:0,levels:8},godRays:{enabled:!1,sunPosition:[5,10,5],samples:60,density:.96,decay:.9,weight:.4,exposure:.6,clampMax:1,blur:!0,kernelSize:"small"},grid:{enabled:!1,scale:1,lineWidth:0},noise:{enabled:!1,opacity:1,premultiply:!1},depthOfField:{enabled:!1,focusDistance:5,focusRange:5,focalLength:.02,bokehScale:6},chromaticAberration:{enabled:!1,offsetX:.002,offsetY:.002,radialModulation:!1,modulationOffset:.15},lensflare:{enabled:!1,lensPosition:[-25,6,-60],smoothTime:.07,glareSize:.2,flareSize:.01,flareSpeed:.01,flareShape:.01,animated:!0,anamorphic:!1,colorGain:"#141414",haloScale:.5,secondaryGhosts:!0,aditionalStreaks:!0,ghostScale:0,opacity:1,starBurst:!1},vignette:{enabled:!1,offset:.3,darkness:.3,eskil:!1},smaa:{enabled:!1},sepia:{enabled:!1,intensity:0},scanline:{enabled:!1,density:1.25},pixelation:{enabled:!1,granularity:5},outline:{enabled:!1,selectionLayer:10,edgeStrength:2.5,pulseSpeed:0,visibleEdgeColor:"#ffffff",hiddenEdgeColor:"#22090a",kernelSize:"large",blur:!1,xRay:!0},selectiveBloom:{enabled:!1,selectionLayer:10,intensity:1,luminanceThreshold:.9,luminanceSmoothing:.025,kernelSize:"large",mipmapBlur:!0,inverted:!1,ignoreBackground:!1},ramp:{enabled:!1,rampType:"linear",rampStart:[.5,.5],rampEnd:[1,1],startColor:"#000000",endColor:"#ffffff",opacity:.5,rampBias:.5,rampGain:.5,rampMask:!1,rampInvert:!1}},se={model:{rotation:[0,0,0],showAdvancedRotation:!1,renderer:"pbr",shading:"lit",autoRotate:!1,autoRotateSpeed:1},camera:{fieldOfView:50,showAdvancedSettings:!1},lighting:{ambient:{intensity:.25,color:"#ffffff"},lights:[{id:"light-hemi",type:"hemisphere",color:"#ffffff",intensity:.3,position:[0,1,0],attachedToCamera:!1,castShadow:!1,shadowBias:-5e-4,visible:!0},{id:"light-key",type:"directional",color:"#ffffff",intensity:2.5,position:[6,12,6],attachedToCamera:!1,castShadow:!0,shadowBias:-5e-4,visible:!0},{id:"light-fill",type:"directional",color:"#ffffff",intensity:0,position:[-6,8,-6],attachedToCamera:!1,castShadow:!1,shadowBias:-5e-4,visible:!0}]},shadows:{enabled:!0,mapSize:2048,bias:-5e-4,normalBias:.02,radius:3},environment:{source:"preset",preset:"apartment",customEnvironmentUrl:"",intensity:.25,rotation:0,shadowLight:{enabled:!1,intensity:2.5,bias:-5e-4}},wireframe:{enabled:!1,color:"#000000",opacity:1},background:{enabled:!1,type:"color",color:"#1c1c1d",imageUrl:""},groundShadows:{enabled:!1,mode:"shadowCatcher",intensity:.7,borderFade:1,height:0,size:10},postProcessing:k,animations:I,annotations:[]};function B(n,e){if(n[e])return e;let t=Object.entries(n).find(([,i])=>i.id===e)?.[0];return t||(Object.entries(n).find(([,i])=>i.modelObjectId===e)?.[0]??null)}function R(n){return typeof n=="object"&&!Array.isArray(n)}function N(n,e){return"group"in e?n.group===e.group:"tag"in e?n.tags?.includes(e.tag)??!1:(n.type??"other")===e.type}function p(n,e){if(R(e))return Object.entries(n).filter(([,i])=>N(i,e)).map(([i])=>i);let r=(typeof e=="string"?[e]:e).map(i=>B(n,i)).filter(i=>i!==null);return[...new Set(r)]}function ue(n,e){return p(n,e).map(t=>n[t]).filter(t=>t!==void 0)}var D="#ff3b30",L=Object.freeze({}),w=n=>n;function _(n){return typeof n=="object"&&n!==null&&!Array.isArray(n)}function P(n,e){let t=n.metadata;for(let r of e.split(".")){if(!_(t))return;t=t[r]}return t}function z(n,e){if("metric"in e){let t=n.metrics?.[e.metric];return!(typeof t!="number"||!Number.isFinite(t)||e.above!==void 0&&!(t>e.above)||e.below!==void 0&&!(t<e.below))}if("status"in e){let t=n.status??"normal";return Array.isArray(e.status)?e.status.includes(t):e.status===t}return P(n,e.metadata)===e.equals}function G(n){let e=n.trim().replace(/^#/,""),t=e.length===3?e.split("").map(r=>r+r).join(""):e;return/^[0-9a-f]{6}$/i.test(t)?[0,2,4].map(r=>parseInt(t.slice(r,r+2),16)):null}var h=n=>`#${n.map(e=>Math.round(e).toString(16).padStart(2,"0")).join("")}`;function F(n,e){let t=n.map(([o,a])=>({at:o,rgb:G(a)})).filter(o=>Number.isFinite(o.at)&&o.rgb!==null).sort((o,a)=>o.at-a.at);if(t.length===0||!Number.isFinite(e))return null;if(e<=t[0].at)return h(t[0].rgb);let r=t[t.length-1];if(e>=r.at)return h(r.rgb);let i=t.findIndex(o=>o.at>=e),l=t[i-1],s=t[i],c=s.at===l.at?1:(e-l.at)/(s.at-l.at);return h(l.rgb.map((o,a)=>o+(s.rgb[a]-o)*c))}function ge(n,e){if(!e?.length)return{bindings:n,pulses:L,sourceOf:w};let t=new Map,r={};for(let s of e){let c=s.target?p(n,s.target):Object.keys(n),o=s.when?Array.isArray(s.when)?s.when:[s.when]:[];for(let a of c){let m=n[a];if(!o.every(d=>z(m,d)))continue;let u={...s.material};if(s.colorScale){let d=m.metrics?.[s.colorScale.metric],b=typeof d=="number"?F(s.colorScale.stops,d):null;b&&(u={...u,[s.colorScale.channel??"baseColor"]:b})}if(s.pulse){let d=s.pulse===!0?{}:s.pulse;r[a]={color:d.color??D,speed:d.speed!==void 0&&d.speed>0?d.speed:1};let b=u.emissiveIntensity??t.get(a)?.emissiveIntensity??m.style?.material?.emissiveIntensity;b!==void 0&&b>0||(u.emissiveIntensity=1)}Object.keys(u).length>0&&t.set(a,{...t.get(a),...u})}}if(t.size===0)return{bindings:n,pulses:r,sourceOf:w};let i={...n},l=new WeakMap;for(let[s,c]of t){let o=n[s],a={...o,style:{...o.style,material:{...o.style?.material,...c}}};i[s]=a,l.set(a,o)}return{bindings:i,pulses:r,sourceOf:s=>l.get(s)??s}}var V=.12,C=new Set;function U(n,e){return e?new Set(p(n,e.target)):C}function he(n,e){let t=U(n.bindings,e);if(!e||t.size===0)return{...n,setAside:C};let r=Math.min(Math.max(e.ghostOpacity??V,0),1),i={...n.bindings},l=new WeakMap,s=new Set;for(let[c,o]of Object.entries(n.bindings)){if(t.has(c))continue;s.add(c);let a=e.mode==="hide"?{...o,visible:!1}:{...o,style:{...o.style,material:{...o.style?.material,opacity:Math.min(o.style?.material?.opacity??1,r)}}};i[c]=a,l.set(a,n.sourceOf(o))}return{bindings:i,pulses:n.pulses,sourceOf:c=>l.get(c)??n.sourceOf(c),setAside:s}}var y=Symbol("react-immersive.model-node-id");function W(n,e){Object.defineProperty(n,y,{value:e,configurable:!0})}function S(n){let e=new Map;n.traverse(o=>{if(!o.name)return;let a=e.get(o.name);a?a.push(o):e.set(o.name,[o])});let t=Object.create(null),r=new WeakMap,i=new Map,l=new Set(Array.from(e,([o,a])=>a.length===1?o:null).filter(o=>o!==null)),s=new Set,c=(o,a)=>{W(o,a),t[a]=o,r.set(o,a),s.add(a)};for(let[o,a]of e)a.length===1&&c(a[0],o);for(let[o,a]of e){if(a.length<2)continue;let m=[];a.forEach((u,d)=>{let b=`${o} [${d+1}]`,g=b,T=2;for(;l.has(g)||s.has(g);)g=`${b}.${T++}`;c(u,g),m.push(g)}),i.set(o,m)}return{nodesById:t,idByNode:r,duplicateNames:i}}function Se(n){return n[y]??n.name??null}function Oe(n,e){let t=null,r=[];return n.traverse(i=>{i[y]===e&&(t=i),i.name===e&&r.push(i)}),t??(r.length===1?r[0]:null)}function $(n){return n.trim().replace(/([a-z0-9])([A-Z])/g,"$1-$2").replace(/[_\s]+/g,"-").replace(/[^a-zA-Z0-9-]/g,"-").replace(/-+/g,"-").replace(/^-|-$/g,"").toLowerCase()}function K(n){return n.replace(/([a-z0-9])([A-Z])/g,"$1 $2").replace(/[_-]+/g," ").replace(/\s+/g," ").trim().replace(/\b\w/g,e=>e.toUpperCase())}function H(n){let e=n.toLowerCase();return e.includes("light")?"light":e.includes("wheel")||e.includes("rim")||e.includes("tire")?"wheel":e.includes("glass")||e.includes("window")||e.includes("windshield")||e.includes("sunroof")?"glass":e.includes("seat")||e.includes("dashboard")||e.includes("console")||e.includes("doorpanel")?"interior":e.includes("floor")?"floor":e.includes("wall")?"wall":e.includes("door")?"door":e.includes("chair")||e.includes("table")||e.includes("sofa")||e.includes("bed")?"furniture":"other"}function M(n,e=!0){return n==="light"||n.endsWith("light")?[{id:"toggle-light",label:"Toggle Light",type:"command"},{id:"change-light-color",label:"Change Light Color",type:"command"},{id:"set-brightness",label:"Set Brightness",type:"command"}]:[{id:"change-color",label:"Change Color",type:"command"},...e?[{id:"change-material",label:"Change Material",type:"command"}]:[],{id:"toggle-visibility",label:"Toggle Visibility",type:"command"}]}function v(n,e=!0){let t=H(n);return{id:$(n),modelObjectId:n,type:t,label:K(n),status:"normal",selectable:!0,hoverable:!0,visible:!0,style:{},actions:M(t,e),metrics:{},metadata:{}}}function Ce(n,e){return Object.fromEntries(n.map(t=>[t,v(t,!e?.has(t))]))}function Me(n,e){let t=new Set,r={};for(let i of n){let l=v(i,!e?.has(i)),s=l.id||"object",c=s;for(let a=2;t.has(c);a++)c=`${s}-${a}`;t.add(c),l.id=c;let o=(l.actions??[]).filter(a=>x.includes(a.id));l.actions=o.length>0?o:M("other",!e?.has(i)),r[i]=l}return r}function ve(n){let e=new Set;for(let[t,r]of Object.entries(S(n).nodesById))O(r)||e.add(t);return e}function Te(n){let{nodesById:e}=S(n),t=[];for(let[r,i]of Object.entries(e)){let l=i;l.isMesh&&l.geometry&&i.name&&t.push(r)}return t.sort((r,i)=>r.localeCompare(i))}var Ee=["front","back","double"],Ie=["normal","additive"];export{f as a,Y as b,A as c,x as d,X as e,Z as f,B as g,J as h,Q as i,ee as j,ne as k,te as l,re as m,ie as n,oe as o,ae as p,se as q,S as r,Se as s,Oe as t,p as u,ue as v,z as w,F as x,ge as y,U as z,he as A,K as B,H as C,v as D,Ce as E,Me as F,ve as G,Te as H,Ee as I,Ie as J};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{u as p}from"./chunk-
|
|
1
|
+
import{u as p}from"./chunk-B7REIGDG.mjs";function c(n){if(typeof n!="object"||n===null)return!1;let e=Object.getPrototypeOf(n);return e===Object.prototype||e===null}function o(n,e){if(!c(e))return e;let i=c(n)?{...n}:{};for(let r of Object.keys(e)){let t=e[r];i[r]=c(t)?o(i[r],t):t}return i}function B(n){return Array.isArray(n)&&n.length>0&&typeof n[0]!="string"}function T(n,e,i){let r=B(e)?e:[{ids:e,patch:i??{}}],t=n;for(let d of r)for(let g of p(t,d.ids)){let s=t[g];if(!s)continue;let a=o(s,d.patch);t===n&&(t={...n}),t[g]=a}return t}function O(n){return{style:{material:n}}}function x(n,e){return o(n,e)}var f={type:"point",color:"#ffffff",intensity:1,position:[0,0,0],distance:0,decay:2,attachedToCamera:!1,castShadow:!1,shadowBias:-5e-4,visible:!0};function m(n){return{...f,...n}}function P(n){return n}export{T as a,O as b,x as c,m as d,P as e};
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import{A as bi,B as pi,a as po,d as Ea,e as An,f as ja,g as yt,h as qt,i as On,j as Ia,k as xo,l as Ja,m as Xa,n as Za,o as ei,p as Ze,q as oi,r as ai,s as ii,t as ri,u as si,v as li,w as di,x as Co,y as ci}from"./chunk-T3M3BQ7H.mjs";import{I as Ln,J as ti,v as Oa,x as uo,y as La}from"./chunk-ZPK67UG7.mjs";import{B as ni,E as zn,G as yo,H as wo,I as ui,J as mi,a as mo,b as Rn,c as Mn,e as go,f as za,h as Fa,i as Ha,j as Va,k as Ga,l as Ua,m as $a,n as Jt,o as Ka,p as _a,q as Xt,t as fo,u as vo,w as Qa}from"./chunk-B7REIGDG.mjs";import{A as qa,B as ho,h as Da,w as Wa,x as Ya}from"./chunk-4NLJSD3S.mjs";import{useCallback as ne,useEffect as Je,useMemo as Gt,useRef as ie,useState as V}from"react";import{Vector3 as Cb}from"three";import{Ellipsis as Sb,Pin as kb,PinOff as Nb,SlidersHorizontal as Tb,SquareSplitHorizontal as Pb}from"lucide-react";import{useEffect as El,useId as Dl,useRef as gi,useState as fi}from"react";import{ChevronDown as jl,History as Il,Trash2 as Fl}from"lucide-react";import{Fragment as xi,jsx as wt,jsxs as pt}from"react/jsx-runtime";function So({label:t,icon:n,title:i,align:r="left",children:e}){let[o,d]=fi(!1),l=gi(null),b=gi(null),w=Dl();return El(()=>{if(!o)return;let A=s=>{l.current?.contains(s.target)||d(!1)},k=s=>{s.key==="Escape"&&(d(!1),b.current?.focus())};return window.addEventListener("pointerdown",A),window.addEventListener("keydown",k),()=>{window.removeEventListener("pointerdown",A),window.removeEventListener("keydown",k)}},[o]),pt("div",{className:"bb-headerMenuWrapper",ref:l,children:[pt("button",{ref:b,type:"button",className:`bb-headerButton ${t?"":"bb-headerButton--icon"} ${o?"bb-headerButton--open":""}`,onClick:()=>d(A=>!A),title:i,"aria-label":t?void 0:i,"aria-expanded":o,"aria-controls":o?w:void 0,children:[n,t?pt(xi,{children:[t,wt(jl,{size:12,"aria-hidden":"true"})]}):null]}),o?wt("div",{id:w,className:`bb-headerMenu bb-headerMenu--${r}`,role:"group","aria-label":i,children:e(()=>d(!1))}):null]})}function hi({onRestore:t,onRemove:n,restoreDisabled:i,close:r}){let[e,o]=fi(!1);return e&&n?pt("div",{className:"bb-headerMenuConfirm",role:"alertdialog","aria-label":"Remove model",children:[wt("p",{children:"Remove the model and its bindings from the editor? Your edits are saved first, so Restore last session can bring them back."}),pt("div",{className:"bb-headerMenuConfirmActions",children:[wt("button",{type:"button",className:"bb-headerMenuItem",onClick:()=>o(!1),children:"Cancel"}),wt("button",{type:"button",className:"bb-headerMenuItem bb-headerMenuItem--danger",onClick:()=>{r(),n()},autoFocus:!0,children:"Remove"})]})]}):pt(xi,{children:[t?pt("button",{type:"button",className:"bb-headerMenuItem",disabled:i,onClick:()=>{r(),t()},title:"Restore your last session: the model, its object bindings, and scene settings saved in this browser",children:[wt(Il,{size:14,"aria-hidden":"true"}),"Restore last session"]}):null,n?pt("button",{type:"button",className:"bb-headerMenuItem bb-headerMenuItem--danger",onClick:()=>o(!0),children:[wt(Fl,{size:14,"aria-hidden":"true"}),"Remove model\u2026"]}):null]})}import{useCallback as Hl,useEffect as Vl,useMemo as Gl,useRef as Ul}from"react";import{jsx as vi,jsxs as $l}from"react/jsx-runtime";function yi({liveViewerRef:t,renderBefore:n,split:i,onSplitChange:r,labels:e,beforeAction:o}){let d=Ul(null),l=Gl(()=>ci(),[]);Vl(()=>()=>l.detach(),[l]);let b=Hl(w=>{let A=t.current;A&&l.attach(0,A.raw.controls,A.invalidate),l.attach(1,w.raw.controls,w.invalidate)},[l,t]);return $l("div",{ref:d,className:"ri-compare ri-compare--overlay",style:{"--ri-compare-split":`${i*100}%`},children:[vi("div",{className:"ri-compare__layer ri-compare__layer--before",children:n(b)}),vi(bi,{split:i,onSplitChange:r,labels:e,containerRef:d,beforeAction:o})]})}var Kl="react-immersive:binding-builder";var Dt="session",St="model",jt="textures",Zt="current";var Ct=null;function Dn(){return Ct||(Ct=new Promise((t,n)=>{if(typeof indexedDB>"u"){n(new Error("IndexedDB is not available in this environment."));return}let i=indexedDB.open(Kl,2);i.onupgradeneeded=()=>{let r=i.result;r.objectStoreNames.contains(Dt)||r.createObjectStore(Dt),r.objectStoreNames.contains(St)||r.createObjectStore(St),r.objectStoreNames.contains(jt)||r.createObjectStore(jt)},i.onsuccess=()=>{let r=i.result;r.onversionchange=()=>{r.close(),Ct=null},t(r)},i.onerror=()=>n(i.error??new Error("Failed to open IndexedDB."))}),Ct.catch(()=>{Ct=null}),Ct)}function jn(t){return new Promise((n,i)=>{t.oncomplete=()=>n(),t.onerror=()=>i(t.error??new Error("IndexedDB transaction failed.")),t.onabort=()=>i(t.error??new Error("IndexedDB transaction aborted."))})}function ko(t){return new Promise((n,i)=>{t.onsuccess=()=>n(t.result),t.onerror=()=>i(t.error??new Error("IndexedDB request failed."))})}function En(t){return t!==null&&typeof t=="object"&&!Array.isArray(t)}function _l(t){if(!En(t)||t.version!==1)return!1;let n=t.model;return typeof t.savedAt=="number"&&En(t.bindings)&&En(t.sceneConfig)&&En(n)&&typeof n.name=="string"&&(n.kind==="file"&&typeof n.key=="string"||n.kind==="url"&&typeof n.url=="string")}async function wi(t,n){let i=await Dn(),r={...t,version:1,savedAt:Date.now()},e=i.transaction([Dt,St],"readwrite"),o=jn(e);if(e.objectStore(Dt).put(r,Zt),r.model.kind==="file"&&n){let d={key:r.model.key,blob:n,name:n.name,type:n.type,lastModified:n.lastModified};e.objectStore(St).put(d,Zt)}else r.model.kind==="url"&&e.objectStore(St).delete(Zt);return await o,r}async function Ci(){let n=(await Dn()).transaction([Dt,St],"readonly"),i=jn(n),[r,e]=await Promise.all([ko(n.objectStore(Dt).get(Zt)),ko(n.objectStore(St).get(Zt))]);return await i,_l(r)?r.model.kind==="url"?{session:r,file:null}:!e||e.key!==r.model.key?null:{session:r,file:new File([e.blob],e.name,{type:e.type,lastModified:e.lastModified})}:null}async function In(t,n){let r=(await Dn()).transaction(jt,"readwrite"),e=jn(r),o={blob:n,name:n.name,type:n.type,savedAt:Date.now()};r.objectStore(jt).put(o,t),await e}async function Qt(t){let i=(await Dn()).transaction(jt,"readonly"),r=jn(i),e=await ko(i.objectStore(jt).get(t));return await r,e?new File([e.blob],e.name,{type:e.type,lastModified:e.savedAt}):null}import{useState as oc,useEffect as ac}from"react";import{useState as nd}from"react";import{ChevronDown as od,ChevronLeft as ad,ChevronRight as id,RotateCcw as rd}from"lucide-react";import{HexColorInput as sd,HexColorPicker as ld}from"react-colorful";import{useLayoutEffect as ki,useRef as No,useState as To}from"react";import{createPortal as Yl}from"react-dom";import{ChevronDown as ql,Info as Jl}from"lucide-react";import{HexColorInput as Xl,HexColorPicker as Zl}from"react-colorful";function ut(t){let n=t.replace("#","").match(/.{2}/g).map(r=>parseInt(r,16)/255).map(r=>r<=.03928?r/12.92:Math.pow((r+.055)/1.055,2.4));return .2126*n[0]+.7152*n[1]+.0722*n[2]>.179?"#000":"#fff"}import{useEffect as Wl}from"react";function Si(t,n,i){Wl(()=>{if(!i)return;let r=Array.isArray(t)?t:[t],e=o=>{let d=o.target;r.some(b=>b.current?.contains(d))||n()};return document.addEventListener("pointerdown",e,!0),()=>{document.removeEventListener("pointerdown",e,!0)}},[t,n,i])}import{jsx as Y,jsxs as Me}from"react/jsx-runtime";function en({anchorRef:t,onClose:n,children:i}){let r=No(null),[e,o]=To(null);return Si([r,t],n,!0),ki(()=>{let d=t.current;if(!d)return;let l=d.getBoundingClientRect(),b=222,w=8,A=Math.min(Math.max(l.right-b,w),window.innerWidth-b-w),k=Math.min(l.bottom+6,window.innerHeight-200);o({top:k,left:A})},[t]),e?Yl(Y("div",{ref:r,className:"se-colorPickerPopover",style:{position:"fixed",top:e.top,left:e.left},children:i}),document.body):null}function Ql(t){return t.replace(/([a-z0-9])([A-Z])/g,"$1 $2").replace(/[_-]+/g," ").replace(/\s+/g," ").trim().replace(/\b\w/g,n=>n.toUpperCase())}function rt({title:t,children:n}){return Me("section",{className:"se-section",children:[Y("h3",{className:"se-sectionTitle",children:t}),Y("div",{className:"se-sectionBody",children:n})]})}function q({title:t,open:n,onToggle:i,trailing:r,children:e,disabled:o,tooltip:d}){let l=d?`${d}`:t;return Me("section",{className:"se-panel",children:[Me("button",{type:"button",className:"se-panelHeader",onClick:i,"aria-expanded":n,title:l,children:[Me("span",{className:"se-panelHeaderMain",children:[Y(ql,{size:16,className:`se-panelChevron ${n?"se-panelChevron--open":""}`}),Y("span",{className:"se-panelTitle",children:t}),d?Y("span",{className:"se-panelHelp",title:l,"aria-label":l,role:"img",onClick:b=>b.stopPropagation(),children:Y(Jl,{size:13})}):null]}),r?Y("span",{className:"se-panelTrailing",onClick:b=>b.stopPropagation(),children:r}):null]}),n?Y("div",{className:"se-panelBody",style:o?{opacity:.45,pointerEvents:"none"}:void 0,children:e}):null]})}function X({checked:t,onChange:n,label:i}){return Me("label",{className:"se-switch","aria-label":i,children:[Y("input",{type:"checkbox",checked:t,onChange:r=>n(r.target.checked)}),Y("span",{className:"se-switchTrack",children:Y("span",{className:"se-switchThumb"})})]})}function N({label:t,value:n,min:i,max:r,step:e,formatValue:o,onChange:d,disabled:l=!1}){return Me("label",{className:`se-field ${l?"se-field--disabled":""}`,children:[Me("span",{className:"se-fieldLabel",children:[t,Y("span",{className:"se-fieldValue",children:o?o(n):n})]}),Y("input",{className:"se-slider",type:"range",min:i,max:r,step:e,value:n,onChange:b=>d(Number(b.target.value)),disabled:l})]})}function J({label:t,checked:n,onChange:i}){return Me("label",{className:"se-field se-fieldInline",children:[Y("span",{className:"se-fieldLabel",children:t}),Y("input",{type:"checkbox",className:"se-checkbox",checked:n,onChange:r=>i(r.target.checked)})]})}function Ee({label:t,value:n,options:i,onChange:r}){return Me("label",{className:"se-field se-fieldInline",children:[Y("span",{className:"se-fieldLabel",children:t}),Y("select",{className:"se-select",value:n,onChange:e=>r(e.target.value),children:i.map(e=>Y("option",{value:e,children:Ql(e)},e))})]})}function Le({label:t,value:n,onChange:i}){let[r,e]=To(!1),o=No(null);return Me("div",{className:"se-field",children:[Me("div",{className:"se-fieldInline",children:[Y("span",{className:"se-fieldLabel",children:t}),Y("span",{ref:o,style:{display:"inline-flex"},children:Y(Xl,{prefixed:!0,className:"se-swatch",onClick:()=>e(d=>!d),style:{background:n,color:ut(n)},color:n,onChange:i})})]}),r?Y(en,{anchorRef:o,onClose:()=>e(!1),children:Y(Zl,{color:n,onChange:i})}):null]})}function Ni({value:t,min:n,max:i,step:r,onChange:e}){let[o,d]=To(String(t)),l=No(!1);return ki(()=>{l.current||d(String(t))},[t]),Y("input",{type:"number",className:"se-numberInput",min:n,max:i,step:r,value:o,onFocus:()=>{l.current=!0},onChange:b=>{let w=b.target.value;d(w),w!==""&&w!=="-"&&!Number.isNaN(Number(w))&&e(Number(w))},onBlur:()=>{l.current=!1,d(String(t))}})}function mt({label:t,value:n,min:i,max:r,step:e,onChange:o}){return Me("div",{className:"se-field",children:[Y("span",{className:"se-fieldLabel",children:t}),Y("div",{className:"se-vectorRow",children:["X","Y","Z"].map((l,b)=>Me("label",{className:"se-vectorAxis",children:[Y("span",{children:l}),Y(Ni,{value:n[b],min:i,max:r,step:e,onChange:w=>{let A=[...n];A[b]=w,o(A)}})]},l))})]})}function kt({label:t,value:n,min:i,max:r,step:e,onChange:o}){return Me("div",{className:"se-field",children:[Y("span",{className:"se-fieldLabel",children:t}),Y("div",{className:"se-vectorRow",children:["X","Y"].map((l,b)=>Me("label",{className:"se-vectorAxis",children:[Y("span",{children:l}),Y(Ni,{value:n[b],min:i,max:r,step:e,onChange:w=>{let A=[...n];A[b]=w,o(A)}})]},l))})]})}var Ti={free:0,starter:1,growth:2};function Pi(t){return t==="starter"||t==="growth"||t==="scale"?t==="scale"?"growth":t:"free"}function _e(t,n){return Ti[t]>=Ti[n]}var Bi={free:"Free",starter:"Starter",growth:"Growth"};import{Lock as ed}from"lucide-react";import{jsx as td,jsxs as Ri}from"react/jsx-runtime";function Ne({requiredTier:t,feature:n}){return Ri("div",{className:"bb-tierLock",children:[td(ed,{size:16}),Ri("p",{className:"bb-tierLockMessage",children:[n," requires the ",Bi[t]," plan or higher."]})]})}import{Fragment as Fn,jsx as O,jsxs as te}from"react/jsx-runtime";var dd=["lit","unlit","normals"],cd=["color","image","environment"];function Mi(t){let n=t%360;return n<0?n+360:n}function It({title:t,open:n,onToggle:i,children:r,trailing:e}){return te("section",{className:"se-panel",children:[te("button",{type:"button",className:"se-panelHeader",onClick:i,"aria-expanded":n,children:[te("span",{className:"se-panelHeaderMain",children:[O(od,{size:16,className:`se-panelChevron ${n?"se-panelChevron--open":""}`}),O("span",{className:"se-panelTitle",children:t})]}),e?O("span",{className:"se-panelTrailing",onClick:o=>o.stopPropagation(),children:e}):null]}),n?O("div",{className:"se-panelBody",children:r}):null]})}function Po({config:t,onChange:n,materialVariantGroups:i=[]}){let{model:r,camera:e,wireframe:o,background:d,environment:l}=t,b=Ya(r),w=i.length>0?b.filter(a=>!i.some(u=>u.variants.some(z=>z.name===a))):[],{tier:A}=Ze(),k=_e(A,"starter"),s=Ln(),[h,S]=nd({general:!0,camera:!0,autoRotate:!1,section:!1,wireframe:!1,background:!1}),m=a=>S(u=>({...u,[a]:!u[a]})),f=a=>n({...t,model:a}),y=a=>n({...t,camera:a}),p=t.section??_a,g=a=>n({...t,section:{...p,...a}}),T=a=>n({...t,wireframe:a}),x=a=>n({...t,background:a}),v=a=>n({...t,environment:a}),P=a=>{v({...l,source:"preset",preset:a})};return te("div",{className:"se-generalContent",children:[te(It,{title:"General",open:h.general,onToggle:()=>m("general"),children:[te("div",{className:"se-field",children:[te("div",{className:"se-fieldLabel",children:[O("span",{children:"Straighten model"}),O("button",{type:"button",className:"se-iconButton",onClick:()=>f({...r,rotation:[0,0,0]}),"aria-label":"Reset model rotation",children:O(rd,{size:16})})]}),O("div",{className:"se-axisStepperGrid",children:["X","Y","Z"].map((a,u)=>te("div",{className:"se-axisStepper",children:[O("button",{type:"button",className:"se-axisStepperButton",onClick:()=>{let z=[...r.rotation];z[u]=Mi(z[u]-90),f({...r,rotation:z})},"aria-label":`Rotate ${a} axis backward`,children:O(ad,{size:16})}),O("span",{className:"se-axisStepperLabel",children:a}),O("button",{type:"button",className:"se-axisStepperButton",onClick:()=>{let z=[...r.rotation];z[u]=Mi(z[u]+90),f({...r,rotation:z})},"aria-label":`Rotate ${a} axis forward`,children:O(id,{size:16})})]},a))})]}),O(mt,{label:"Rotation",value:r.rotation,min:0,max:360,step:1,onChange:a=>f({...r,rotation:a})}),te("div",{className:"se-field",children:[O("span",{className:"se-fieldLabel",children:"Renderer"}),O("div",{className:"se-segmentedControl se-segmentedControl--renderer",children:Va.map(a=>O("button",{type:"button",className:`se-segmentedOption ${r.renderer===a?"se-segmentedOption--active":""}`,onClick:()=>f({...r,renderer:a}),children:a==="uv-checker"?"UV CHECKER":a.toUpperCase()},a))})]}),O(Ee,{label:"Shading",value:r.shading,options:dd,onChange:a=>f({...r,shading:a})}),i.map((a,u)=>{let z=b.find(D=>a.variants.some($=>$.name===D));return te("label",{className:"se-field se-fieldInline",children:[O("span",{className:"se-fieldLabel",children:a.name??"Material variant"}),te("select",{className:"se-select",value:z??"",onChange:D=>{let $=D.target.value,ze=b.filter(gt=>gt!==z);f(ho(r,$?Wa(ze,$,i):ze))},children:[O("option",{value:"",children:"Model default"}),a.variants.map(D=>O("option",{value:D.name,children:D.label},D.name))]})]},a.name??`group-${u}`)}),w.length>0?te("div",{className:"se-placeholder se-placeholder--spaced",children:["Not in this model: ",w.join(", "),"."," ",O("button",{type:"button",className:"se-linkButton",onClick:()=>f(ho(r,b.filter(a=>!w.includes(a)))),children:"Remove"})]}):null]}),O(It,{title:"Camera",open:h.camera,onToggle:()=>m("camera"),children:O(N,{label:"Field Of View",value:e.fieldOfView,min:20,max:100,step:.1,formatValue:a=>`${a.toFixed(3)}\xB0`,onChange:a=>y({...e,fieldOfView:a})})}),te(It,{title:"Auto Rotate",open:h.autoRotate,onToggle:()=>m("autoRotate"),trailing:te("label",{className:"se-switch","aria-label":"Toggle auto rotate",children:[O("input",{type:"checkbox",checked:r.autoRotate??!1,onChange:a=>f({...r,autoRotate:a.target.checked})}),O("span",{className:"se-switchTrack",children:O("span",{className:"se-switchThumb"})})]}),children:[r.autoRotate&&s?O("div",{className:"se-placeholder se-placeholder--spaced",children:"Your device is set to reduce motion, so this preview won't turn. Visitors without that setting will see it."}):null,r.autoRotate?O(N,{label:"Rotation Speed",value:r.autoRotateSpeed??1,min:.1,max:3,step:.1,formatValue:a=>`${a.toFixed(1)}x`,onChange:a=>f({...r,autoRotateSpeed:a})}):O("div",{className:"se-placeholder",children:"Enable auto rotate to adjust its speed."})]}),O(It,{title:"Section Cut",open:h.section,onToggle:()=>m("section"),trailing:te("label",{className:"se-switch","aria-label":"Toggle section cut",children:[O("input",{type:"checkbox",checked:p.enabled,onChange:a=>g({enabled:a.target.checked})}),O("span",{className:"se-switchTrack",children:O("span",{className:"se-switchThumb"})})]}),children:p.enabled?te(Fn,{children:[te("div",{className:"se-field",children:[O("span",{className:"se-fieldLabel",children:"Cut across"}),O("div",{className:"se-segmentedControl",children:Ka.map(a=>O("button",{type:"button",className:`se-segmentedOption ${p.axis===a?"se-segmentedOption--active":""}`,onClick:()=>g({axis:a}),children:a.toUpperCase()},a))})]}),O(N,{label:"Position",value:p.position,min:0,max:1,step:.01,formatValue:a=>`${Math.round(a*100)}%`,onChange:a=>g({position:a})}),O(J,{label:"Keep the other side",checked:p.flip,onChange:a=>g({flip:a})})]}):O("div",{className:"se-placeholder",children:"Cut the model open to see inside. Drag the plane in the preview, or set it here."})}),O(It,{title:"Wireframe",open:h.wireframe,onToggle:()=>m("wireframe"),trailing:te("label",{className:"se-switch","aria-label":"Toggle wireframe preview",children:[O("input",{type:"checkbox",checked:k&&o.enabled,disabled:!k,onChange:a=>T({...o,enabled:a.target.checked})}),O("span",{className:"se-switchTrack",children:O("span",{className:"se-switchThumb"})})]}),children:k?te(Fn,{children:[O(N,{label:"Opacity",value:o.opacity,min:0,max:1,step:.01,onChange:a=>T({...o,opacity:a})}),O(Le,{label:"Wire color",value:o.color,onChange:a=>T({...o,color:a})})]}):O(Ne,{requiredTier:"starter",feature:"Wireframe preview"})}),O(It,{title:"Background",open:h.background,onToggle:()=>m("background"),trailing:te("label",{className:"se-switch","aria-label":"Toggle scene background",children:[O("input",{type:"checkbox",checked:d.enabled,onChange:a=>x({...d,enabled:a.target.checked})}),O("span",{className:"se-switchTrack",children:O("span",{className:"se-switchThumb"})})]}),children:d.enabled?te(Fn,{children:[te("div",{className:"se-field",children:[O("span",{className:"se-fieldLabel",children:"Background type"}),O("div",{className:"se-segmentedControl",children:cd.map(a=>O("button",{type:"button",className:`se-segmentedOption ${d.type===a?"se-segmentedOption--active":""}`,onClick:()=>x({...d,type:a}),children:a},a))})]}),d.type==="environment"?k?te(Fn,{children:[te("div",{className:"se-field",children:[O("span",{className:"se-fieldLabel",children:"Environment source"}),te("div",{className:"se-segmentedControl",children:[O("button",{type:"button",className:`se-segmentedOption ${l.source==="preset"?"se-segmentedOption--active":""}`,onClick:()=>v({...l,source:"preset"}),children:"PRESET"}),O("button",{type:"button",className:`se-segmentedOption ${l.source==="custom"?"se-segmentedOption--active":""}`,onClick:()=>v({...l,source:"custom"}),children:"CUSTOM"})]})]}),l.source==="preset"?O(Ee,{label:"Environment preset",value:l.preset,options:Ga,onChange:P}):te("label",{className:"se-field",children:[O("span",{className:"se-fieldLabel",children:"Custom environment URL"}),O("input",{type:"text",className:"se-textInput",placeholder:"https://example.com/environment.hdr",value:l.customEnvironmentUrl,onChange:a=>v({...l,customEnvironmentUrl:a.target.value})}),O("span",{className:"bb-note",children:"Enter a HDR, EXR, JPG, JPEG, PNG, or WEBP URL."}),l.customEnvironmentUrl.trim()&&!Fa(l.customEnvironmentUrl)?O("span",{className:"bb-note",style:{color:"#fca5a5"},children:"Invalid image/HDRI URL."}):null]}),O(N,{label:"Environment intensity",value:l.intensity,min:0,max:3,step:.05,onChange:a=>v({...l,intensity:a})})]}):O(Ne,{requiredTier:"starter",feature:"Environment backgrounds"}):null,d.type==="image"?te("label",{className:"se-field",children:[O("span",{className:"se-fieldLabel",children:"Background image URL"}),O("input",{type:"text",className:"se-textInput",placeholder:"https://example.com/background.jpg",value:d.imageUrl,onChange:a=>x({...d,imageUrl:a.target.value})})]}):null,d.type==="color"?te("div",{className:"se-field",children:[O("span",{className:"se-fieldLabel",children:"Background color"}),O("div",{className:"se-inlineColorPicker",children:O(ld,{color:d.color,onChange:a=>x({...d,color:a})})}),O("div",{className:"se-fieldInline",children:O(sd,{prefixed:!0,className:"se-swatch",style:{background:d.color,color:ut(d.color)},color:d.color,onChange:a=>x({...d,color:a})})})]}):null]}):O("div",{className:"se-placeholder",children:"Background rendering is disabled for this scene preset."})})]})}import{useState as pd}from"react";import{jsx as j,jsxs as tn}from"react/jsx-runtime";function Ai({pp:t,set:n,open:i,toggle:r}){let{ssao:e}=t;return tn(q,{title:"SSAO",tooltip:"Adds soft contact shadows in corners, creases, and tight spaces.",open:i.ssao,onToggle:()=>r("ssao"),disabled:!e.enabled,trailing:j(X,{checked:e.enabled,onChange:o=>n("ssao",{...e,enabled:o}),label:"Toggle SSAO"}),children:[j(N,{label:"Samples",value:e.samples,min:1,max:64,step:1,onChange:o=>n("ssao",{...e,samples:o})}),j(N,{label:"Rings",value:e.rings,min:1,max:12,step:1,onChange:o=>n("ssao",{...e,rings:o})}),j(N,{label:"Intensity",value:e.intensity,min:0,max:20,step:.5,onChange:o=>n("ssao",{...e,intensity:o})}),j(N,{label:"Radius",value:e.radius,min:.01,max:1,step:.01,onChange:o=>n("ssao",{...e,radius:o})}),j(N,{label:"Bias",value:e.bias,min:0,max:.1,step:.001,onChange:o=>n("ssao",{...e,bias:o})}),j(N,{label:"Luminance Influence",value:e.luminanceInfluence,min:0,max:1,step:.01,onChange:o=>n("ssao",{...e,luminanceInfluence:o})}),j(N,{label:"Fade",value:e.fade,min:0,max:.1,step:.001,onChange:o=>n("ssao",{...e,fade:o})}),j(N,{label:"Min Radius Scale",value:e.minRadiusScale,min:0,max:1,step:.01,onChange:o=>n("ssao",{...e,minRadiusScale:o})}),j(N,{label:"World Distance Threshold",value:e.worldDistanceThreshold,min:0,max:100,step:.1,onChange:o=>n("ssao",{...e,worldDistanceThreshold:o})}),j(N,{label:"World Distance Falloff",value:e.worldDistanceFalloff,min:0,max:20,step:.1,onChange:o=>n("ssao",{...e,worldDistanceFalloff:o})}),j(N,{label:"World Proximity Threshold",value:e.worldProximityThreshold,min:0,max:100,step:.1,onChange:o=>n("ssao",{...e,worldProximityThreshold:o})}),j(N,{label:"World Proximity Falloff",value:e.worldProximityFalloff,min:0,max:20,step:.1,onChange:o=>n("ssao",{...e,worldProximityFalloff:o})})]})}function Oi({pp:t,set:n,open:i,toggle:r}){let{autofocus:e}=t;return tn(q,{title:"Auto focus",tooltip:"Keeps the focus plane tracking a subject so the image stays sharp where you want it.",open:i.autofocus,onToggle:()=>r("autofocus"),disabled:!e.enabled,trailing:j(X,{checked:e.enabled,onChange:o=>n("autofocus",{...e,enabled:o}),label:"Toggle Autofocus"}),children:[j(N,{label:"Focus Distance",value:e.focusDistance,min:0,max:50,step:.1,onChange:o=>n("autofocus",{...e,focusDistance:o})}),j(N,{label:"Focus Range",value:e.focusRange,min:.1,max:50,step:.1,onChange:o=>n("autofocus",{...e,focusRange:o})}),j(N,{label:"Focal Length",value:e.focalLength,min:0,max:1,step:.01,onChange:o=>n("autofocus",{...e,focalLength:o})}),j(N,{label:"Bokeh Scale",value:e.bokehScale,min:0,max:20,step:.1,onChange:o=>n("autofocus",{...e,bokehScale:o})}),j(mt,{label:"Target",value:e.target,min:-100,max:100,step:.1,onChange:o=>n("autofocus",{...e,target:o})}),j(J,{label:"Mouse Follow",checked:e.mouse,onChange:o=>n("autofocus",{...e,mouse:o})}),j(J,{label:"Manual Update",checked:e.manual,onChange:o=>n("autofocus",{...e,manual:o})}),j(N,{label:"Debug",value:e.debug,min:0,max:1,step:.01,onChange:o=>n("autofocus",{...e,debug:o})}),j(N,{label:"Smooth Time",value:e.smoothTime,min:0,max:2,step:.01,onChange:o=>n("autofocus",{...e,smoothTime:o})})]})}function Li({pp:t,set:n,open:i,toggle:r}){let{godRays:e}=t;return tn(q,{title:"God Rays",tooltip:"Creates light shafts that streak outward from a bright sun or light source.",open:i.godRays,onToggle:()=>r("godRays"),disabled:!e.enabled,trailing:j(X,{checked:e.enabled,onChange:o=>n("godRays",{...e,enabled:o}),label:"Toggle GodRays"}),children:[j(mt,{label:"Sun Position",value:e.sunPosition,min:-100,max:100,step:.1,onChange:o=>n("godRays",{...e,sunPosition:o})}),j(N,{label:"Samples",value:e.samples,min:1,max:128,step:1,onChange:o=>n("godRays",{...e,samples:o})}),j(N,{label:"Density",value:e.density,min:0,max:2,step:.01,onChange:o=>n("godRays",{...e,density:o})}),j(N,{label:"Decay",value:e.decay,min:0,max:1,step:.01,onChange:o=>n("godRays",{...e,decay:o})}),j(N,{label:"Weight",value:e.weight,min:0,max:2,step:.01,onChange:o=>n("godRays",{...e,weight:o})}),j(N,{label:"Exposure",value:e.exposure,min:0,max:2,step:.01,onChange:o=>n("godRays",{...e,exposure:o})}),j(N,{label:"Clamp Max",value:e.clampMax,min:0,max:2,step:.01,onChange:o=>n("godRays",{...e,clampMax:o})}),j(J,{label:"Blur",checked:e.blur,onChange:o=>n("godRays",{...e,blur:o})}),j(Ee,{label:"Kernel Size",value:e.kernelSize,options:Jt,onChange:o=>n("godRays",{...e,kernelSize:o})})]})}function zi({pp:t,set:n,open:i,toggle:r}){let{lensflare:e}=t;return tn(q,{title:"Lens Flare",tooltip:"Adds camera flare artifacts and glow from a bright light source.",open:i.lensflare,onToggle:()=>r("lensflare"),disabled:!e.enabled,trailing:j(X,{checked:e.enabled,onChange:o=>n("lensflare",{...e,enabled:o}),label:"Toggle Lensflare"}),children:[j(mt,{label:"Lens Position",value:e.lensPosition,min:-100,max:100,step:.1,onChange:o=>n("lensflare",{...e,lensPosition:o})}),j(N,{label:"Smooth Time",value:e.smoothTime,min:0,max:1,step:.01,onChange:o=>n("lensflare",{...e,smoothTime:o})}),j(N,{label:"Glare Size",value:e.glareSize,min:0,max:1,step:.01,onChange:o=>n("lensflare",{...e,glareSize:o})}),j(N,{label:"Flare Size",value:e.flareSize,min:0,max:.1,step:.001,onChange:o=>n("lensflare",{...e,flareSize:o})}),j(N,{label:"Flare Speed",value:e.flareSpeed,min:0,max:.2,step:.001,onChange:o=>n("lensflare",{...e,flareSpeed:o})}),j(N,{label:"Flare Shape",value:e.flareShape,min:0,max:.2,step:.001,onChange:o=>n("lensflare",{...e,flareShape:o})}),j(J,{label:"Animated",checked:e.animated,onChange:o=>n("lensflare",{...e,animated:o})}),j(J,{label:"Anamorphic",checked:e.anamorphic,onChange:o=>n("lensflare",{...e,anamorphic:o})}),j(Le,{label:"Color Gain",value:e.colorGain,onChange:o=>n("lensflare",{...e,colorGain:o})}),j(N,{label:"Halo Scale",value:e.haloScale,min:0,max:2,step:.01,onChange:o=>n("lensflare",{...e,haloScale:o})}),j(J,{label:"Secondary Ghosts",checked:e.secondaryGhosts,onChange:o=>n("lensflare",{...e,secondaryGhosts:o})}),j(J,{label:"Additional Streaks",checked:e.aditionalStreaks,onChange:o=>n("lensflare",{...e,aditionalStreaks:o})}),j(N,{label:"Ghost Scale",value:e.ghostScale,min:0,max:1,step:.01,onChange:o=>n("lensflare",{...e,ghostScale:o})}),j(N,{label:"Opacity",value:e.opacity,min:0,max:1,step:.01,onChange:o=>n("lensflare",{...e,opacity:o})}),j(J,{label:"Star Burst",checked:e.starBurst,onChange:o=>n("lensflare",{...e,starBurst:o})})]})}function Ei({pp:t,set:n,open:i,toggle:r}){let{depthOfField:e}=t;return tn(q,{title:"Depth Of Field",tooltip:"Blurs areas that sit away from the focal plane for a camera-like look.",open:i.depthOfField,onToggle:()=>r("depthOfField"),disabled:!e.enabled,trailing:j(X,{checked:e.enabled,onChange:o=>n("depthOfField",{...e,enabled:o}),label:"Toggle DepthOfField"}),children:[j(N,{label:"Focus Distance",value:e.focusDistance,min:0,max:50,step:.1,onChange:o=>n("depthOfField",{...e,focusDistance:o})}),j(N,{label:"Focus Range",value:e.focusRange,min:.1,max:50,step:.1,onChange:o=>n("depthOfField",{...e,focusRange:o})}),j(N,{label:"Focal Length",value:e.focalLength,min:0,max:1,step:.01,onChange:o=>n("depthOfField",{...e,focalLength:o})}),j(N,{label:"Bokeh Scale",value:e.bokehScale,min:0,max:20,step:.1,onChange:o=>n("depthOfField",{...e,bokehScale:o})})]})}import{jsx as _,jsxs as Ft}from"react/jsx-runtime";var bd=["linear","reinhard","aces"];function Di({pp:t,set:n,open:i,toggle:r}){let{colorAverage:e}=t;return _(q,{title:"Color Average",tooltip:"Blends the frame toward a single average color for a washed-out stylized look.",open:i.colorAverage,onToggle:()=>r("colorAverage"),disabled:!e.enabled,trailing:_(X,{checked:e.enabled,onChange:o=>n("colorAverage",{...e,enabled:o}),label:"Toggle ColorAverage"}),children:_("div",{className:"se-placeholder",children:"Averages the frame color using the docs default blend mode."})})}function ji({pp:t,set:n,open:i,toggle:r}){let{brightnessContrast:e}=t;return Ft(q,{title:"Brightness Contrast",tooltip:"Raises or lowers overall brightness and contrast across the scene.",open:i.brightnessContrast,onToggle:()=>r("brightnessContrast"),disabled:!e.enabled,trailing:_(X,{checked:e.enabled,onChange:o=>n("brightnessContrast",{...e,enabled:o}),label:"Toggle BrightnessContrast"}),children:[_(N,{label:"Brightness",value:e.brightness,min:-1,max:1,step:.01,onChange:o=>n("brightnessContrast",{...e,brightness:o})}),_(N,{label:"Contrast",value:e.contrast,min:-1,max:1,step:.01,onChange:o=>n("brightnessContrast",{...e,contrast:o})})]})}function Ii({pp:t,set:n,open:i,toggle:r}){let{hueSaturation:e}=t;return Ft(q,{title:"Hue Saturation",tooltip:"Shifts the hue and saturation to tint the whole image.",open:i.hueSaturation,onToggle:()=>r("hueSaturation"),disabled:!e.enabled,trailing:_(X,{checked:e.enabled,onChange:o=>n("hueSaturation",{...e,enabled:o}),label:"Toggle HueSaturation"}),children:[_(N,{label:"Hue",value:e.hue,min:-Math.PI,max:Math.PI,step:.01,formatValue:o=>`${o.toFixed(2)} rad`,onChange:o=>n("hueSaturation",{...e,hue:o})}),_(N,{label:"Saturation",value:e.saturation,min:-1,max:1,step:.01,onChange:o=>n("hueSaturation",{...e,saturation:o})})]})}function Fi({pp:t,set:n,open:i,toggle:r}){let{vignette:e}=t;return Ft(q,{title:"Vignette",tooltip:"Darkens the edges of the screen so the center feels more focused.",open:i.vignette,onToggle:()=>r("vignette"),disabled:!e.enabled,trailing:_(X,{checked:e.enabled,onChange:o=>n("vignette",{...e,enabled:o}),label:"Toggle Vignette"}),children:[_(N,{label:"Offset",value:e.offset,min:0,max:1,step:.01,onChange:o=>n("vignette",{...e,offset:o})}),_(N,{label:"Darkness",value:e.darkness,min:0,max:1,step:.01,onChange:o=>n("vignette",{...e,darkness:o})}),_(J,{label:"Eskil",checked:e.eskil,onChange:o=>n("vignette",{...e,eskil:o})})]})}function Hi({pp:t,set:n,open:i,toggle:r}){let{bloom:e}=t;return Ft(q,{title:"Bloom",tooltip:"Makes bright areas glow and bleed softly into nearby pixels.",open:i.bloom,onToggle:()=>r("bloom"),disabled:!e.enabled,trailing:_(X,{checked:e.enabled,onChange:o=>n("bloom",{...e,enabled:o}),label:"Toggle Bloom"}),children:[_(N,{label:"Threshold",value:e.luminanceThreshold,min:0,max:1,step:.01,onChange:o=>n("bloom",{...e,luminanceThreshold:o})}),_(N,{label:"Smoothing",value:e.luminanceSmoothing,min:0,max:1,step:.01,onChange:o=>n("bloom",{...e,luminanceSmoothing:o})}),_(N,{label:"Intensity",value:e.intensity,min:0,max:3,step:.05,onChange:o=>n("bloom",{...e,intensity:o})}),_(J,{label:"Mipmap Blur",checked:e.mipmapBlur,onChange:o=>n("bloom",{...e,mipmapBlur:o})}),_(N,{label:"Radius",value:e.radius,min:0,max:1,step:.01,onChange:o=>n("bloom",{...e,radius:o})}),_(N,{label:"Levels",value:e.levels,min:1,max:16,step:1,onChange:o=>n("bloom",{...e,levels:o})})]})}function Vi({pp:t,set:n,open:i,toggle:r}){let{toneMapping:e}=t;return Ft(q,{title:"Tone Mapping",tooltip:"Remaps HDR lighting to screen output and controls exposure style.",open:i.toneMapping,onToggle:()=>r("toneMapping"),disabled:!e.enabled,trailing:_(X,{checked:e.enabled,onChange:o=>n("toneMapping",{...e,enabled:o}),label:"Toggle ToneMapping"}),children:[Ft("div",{className:"se-field",children:[_("span",{className:"se-fieldLabel",children:"Mode"}),_("div",{className:"se-segmentedControl",children:bd.map(o=>_("button",{type:"button",className:`se-segmentedOption ${e.mode===o?"se-segmentedOption--active":""}`,onClick:()=>n("toneMapping",{...e,mode:o}),children:o==="aces"?"Filmic":o.charAt(0).toUpperCase()+o.slice(1)},o))})]}),_(N,{label:"Resolution",value:e.resolution,min:64,max:4096,step:64,onChange:o=>n("toneMapping",{...e,resolution:o})}),_(N,{label:"White Point",value:e.whitePoint,min:0,max:16,step:.01,onChange:o=>n("toneMapping",{...e,whitePoint:o})}),_(N,{label:"Middle Grey",value:e.middleGrey,min:0,max:1,step:.01,onChange:o=>n("toneMapping",{...e,middleGrey:o})}),_(N,{label:"Min Luminance",value:e.minLuminance,min:0,max:1,step:.01,onChange:o=>n("toneMapping",{...e,minLuminance:o})}),_(N,{label:"Average Luminance",value:e.averageLuminance,min:0,max:4,step:.01,onChange:o=>n("toneMapping",{...e,averageLuminance:o})}),_(N,{label:"Adaptation Rate",value:e.adaptationRate,min:0,max:10,step:.01,onChange:o=>n("toneMapping",{...e,adaptationRate:o})}),_(N,{label:"Exposure",value:e.exposure,min:0,max:3,step:.01,onChange:o=>n("toneMapping",{...e,exposure:o})})]})}function Gi({pp:t,set:n,open:i,toggle:r}){let{sepia:e}=t;return _(q,{title:"Sepia",tooltip:"Adds a warm vintage brown tint to the entire image.",open:i.sepia,onToggle:()=>r("sepia"),disabled:!e.enabled,trailing:_(X,{checked:e.enabled,onChange:o=>n("sepia",{...e,enabled:o}),label:"Toggle Sepia"}),children:_(N,{label:"Intensity",value:e.intensity,min:0,max:1,step:.01,onChange:o=>n("sepia",{...e,intensity:o})})})}import{jsx as U,jsxs as Ht}from"react/jsx-runtime";function Ui({pp:t,set:n,open:i,toggle:r}){let{dotScreen:e}=t;return Ht(q,{title:"Dot Screen",tooltip:"Overlays a halftone dot pattern for a printed or retro look.",open:i.dotScreen,onToggle:()=>r("dotScreen"),disabled:!e.enabled,trailing:U(X,{checked:e.enabled,onChange:o=>n("dotScreen",{...e,enabled:o}),label:"Toggle DotScreen"}),children:[U(N,{label:"Angle",value:e.angle,min:0,max:Math.PI*2,step:.01,formatValue:o=>`${o.toFixed(2)} rad`,onChange:o=>n("dotScreen",{...e,angle:o})}),U(N,{label:"Scale",value:e.scale,min:.1,max:10,step:.05,onChange:o=>n("dotScreen",{...e,scale:o})})]})}function $i({pp:t,set:n,open:i,toggle:r}){let{glitch:e}=t;return Ht(q,{title:"Glitch",tooltip:"Introduces digital distortion, tearing, and scan noise.",open:i.glitch,onToggle:()=>r("glitch"),disabled:!e.enabled,trailing:U(X,{checked:e.enabled,onChange:o=>n("glitch",{...e,enabled:o}),label:"Toggle Glitch"}),children:[U(Ee,{label:"Mode",value:e.mode,options:Ua,onChange:o=>n("glitch",{...e,mode:o})}),U(kt,{label:"Delay",value:e.delay,min:0,max:10,step:.01,onChange:o=>n("glitch",{...e,delay:o})}),U(kt,{label:"Duration",value:e.duration,min:0,max:5,step:.01,onChange:o=>n("glitch",{...e,duration:o})}),U(kt,{label:"Strength",value:e.strength,min:0,max:2,step:.01,onChange:o=>n("glitch",{...e,strength:o})}),U(kt,{label:"Chromatic Aberration Offset",value:e.chromaticAberrationOffset,min:0,max:.02,step:1e-4,onChange:o=>n("glitch",{...e,chromaticAberrationOffset:o})}),U(N,{label:"Columns",value:e.columns,min:0,max:.5,step:.001,onChange:o=>n("glitch",{...e,columns:o})}),U(N,{label:"Ratio",value:e.ratio,min:0,max:1,step:.01,onChange:o=>n("glitch",{...e,ratio:o})})]})}function Ki({pp:t,set:n,open:i,toggle:r}){let{grid:e}=t;return Ht(q,{title:"Grid",tooltip:"Adds a visual grid overlay that feels retro or debug-like.",open:i.grid,onToggle:()=>r("grid"),disabled:!e.enabled,trailing:U(X,{checked:e.enabled,onChange:o=>n("grid",{...e,enabled:o}),label:"Toggle Grid"}),children:[U(N,{label:"Scale",value:e.scale,min:.1,max:10,step:.05,onChange:o=>n("grid",{...e,scale:o})}),U(N,{label:"Line Width",value:e.lineWidth,min:0,max:1,step:.01,onChange:o=>n("grid",{...e,lineWidth:o})})]})}function _i({pp:t,set:n,open:i,toggle:r}){let{chromaticAberration:e}=t;return Ht(q,{title:"Chromatic Aberration",tooltip:"Separates color channels slightly to mimic lens fringing.",open:i.chromaticAberration,onToggle:()=>r("chromaticAberration"),disabled:!e.enabled,trailing:U(X,{checked:e.enabled,onChange:o=>n("chromaticAberration",{...e,enabled:o}),label:"Toggle ChromaticAberration"}),children:[U(N,{label:"Offset X",value:e.offsetX,min:0,max:.02,step:1e-4,onChange:o=>n("chromaticAberration",{...e,offsetX:o})}),U(N,{label:"Offset Y",value:e.offsetY,min:0,max:.02,step:1e-4,onChange:o=>n("chromaticAberration",{...e,offsetY:o})}),U(J,{label:"Radial Modulation",checked:e.radialModulation,onChange:o=>n("chromaticAberration",{...e,radialModulation:o})}),U(N,{label:"Modulation Offset",value:e.modulationOffset,min:0,max:1,step:.01,onChange:o=>n("chromaticAberration",{...e,modulationOffset:o})})]})}function Wi({pp:t,set:n,open:i,toggle:r}){let{noise:e}=t;return Ht(q,{title:"Noise",tooltip:"Adds film grain or static noise to the rendered image.",open:i.noise,onToggle:()=>r("noise"),disabled:!e.enabled,trailing:U(X,{checked:e.enabled,onChange:o=>n("noise",{...e,enabled:o}),label:"Toggle Noise"}),children:[U(N,{label:"Amount",value:e.opacity,min:0,max:1,step:.01,onChange:o=>n("noise",{...e,opacity:o})}),U(J,{label:"Premultiply",checked:e.premultiply,onChange:o=>n("noise",{...e,premultiply:o})})]})}function Yi({pp:t,set:n,open:i,toggle:r}){let{scanline:e}=t;return U(q,{title:"Scan Line",tooltip:"Draws horizontal CRT-style scan lines over the frame.",open:i.scanline,onToggle:()=>r("scanline"),disabled:!e.enabled,trailing:U(X,{checked:e.enabled,onChange:o=>n("scanline",{...e,enabled:o}),label:"Toggle Scanline"}),children:U(N,{label:"Density",value:e.density,min:0,max:10,step:.25,onChange:o=>n("scanline",{...e,density:o})})})}function qi({pp:t,set:n,open:i,toggle:r}){let{pixelation:e}=t;return U(q,{title:"Pixelation",tooltip:"Reduces detail into larger pixels for a blocky stylized effect.",open:i.pixelation,onToggle:()=>r("pixelation"),disabled:!e.enabled,trailing:U(X,{checked:e.enabled,onChange:o=>n("pixelation",{...e,enabled:o}),label:"Toggle Pixelation"}),children:U(N,{label:"Granularity",value:e.granularity,min:0,max:20,step:1,onChange:o=>n("pixelation",{...e,granularity:o})})})}function Ji({pp:t,set:n,open:i,toggle:r}){let{ramp:e}=t;return Ht(q,{title:"Ramp",tooltip:"Adds a screen-space color gradient, or masks effects earlier in the stack.",open:i.ramp,onToggle:()=>r("ramp"),disabled:!e.enabled,trailing:U(X,{checked:e.enabled,onChange:o=>n("ramp",{...e,enabled:o}),label:"Toggle Ramp"}),children:[U(Ee,{label:"Ramp Type",value:e.rampType,options:$a,onChange:o=>n("ramp",{...e,rampType:o})}),U(kt,{label:"Ramp Start",value:e.rampStart,min:0,max:1,step:.01,onChange:o=>n("ramp",{...e,rampStart:o})}),U(kt,{label:"Ramp End",value:e.rampEnd,min:0,max:1,step:.01,onChange:o=>n("ramp",{...e,rampEnd:o})}),U(Le,{label:"Start Color",value:e.startColor,onChange:o=>n("ramp",{...e,startColor:o})}),U(Le,{label:"End Color",value:e.endColor,onChange:o=>n("ramp",{...e,endColor:o})}),!e.rampMask&&U(N,{label:"Gradient Opacity",value:e.opacity??.5,min:0,max:1,step:.01,onChange:o=>n("ramp",{...e,opacity:o})}),U(N,{label:"Bias",value:e.rampBias,min:0,max:1,step:.01,onChange:o=>n("ramp",{...e,rampBias:o})}),U(N,{label:"Gain",value:e.rampGain,min:0,max:1,step:.01,onChange:o=>n("ramp",{...e,rampGain:o})}),U(J,{label:"Mask Earlier Effects",checked:e.rampMask,onChange:o=>n("ramp",{...e,rampMask:o})}),U(J,{label:"Invert",checked:e.rampInvert,onChange:o=>n("ramp",{...e,rampInvert:o})})]})}import{jsx as be,jsxs as er}from"react/jsx-runtime";function Xi({pp:t,set:n,open:i,toggle:r}){let{outline:e}=t;return er(q,{title:"Outline",tooltip:"Draws a visible edge around the selected object binding.",open:i.outline,onToggle:()=>r("outline"),disabled:!e.enabled,trailing:be(X,{checked:e.enabled,onChange:o=>n("outline",{...e,enabled:o}),label:"Toggle Outline"}),children:[be("div",{className:"se-placeholder",children:"Outlines the currently selected object binding in the model editor."}),be(N,{label:"Selection Layer",value:e.selectionLayer,min:0,max:20,step:1,onChange:o=>n("outline",{...e,selectionLayer:o})}),be(N,{label:"Edge Strength",value:e.edgeStrength,min:0,max:10,step:.1,onChange:o=>n("outline",{...e,edgeStrength:o})}),be(N,{label:"Pulse Speed",value:e.pulseSpeed,min:0,max:10,step:.1,onChange:o=>n("outline",{...e,pulseSpeed:o})}),be(Le,{label:"Visible Edge Color",value:e.visibleEdgeColor,onChange:o=>n("outline",{...e,visibleEdgeColor:o})}),be(Le,{label:"Hidden Edge Color",value:e.hiddenEdgeColor,onChange:o=>n("outline",{...e,hiddenEdgeColor:o})}),be(Ee,{label:"Kernel Size",value:e.kernelSize,options:Jt,onChange:o=>n("outline",{...e,kernelSize:o})}),be(J,{label:"Blur",checked:e.blur,onChange:o=>n("outline",{...e,blur:o})}),be(J,{label:"X-Ray",checked:e.xRay,onChange:o=>n("outline",{...e,xRay:o})})]})}function Zi({pp:t,set:n,open:i,toggle:r}){let{selectiveBloom:e}=t;return er(q,{title:"Selective Bloom",tooltip:"Applies bloom only to objects assigned to the selected layer.",open:i.selectiveBloom,onToggle:()=>r("selectiveBloom"),disabled:!e.enabled,trailing:be(X,{checked:e.enabled,onChange:o=>n("selectiveBloom",{...e,enabled:o}),label:"Toggle SelectiveBloom"}),children:[be("div",{className:"se-placeholder",children:"Applies bloom to the currently selected object binding."}),be(N,{label:"Selection Layer",value:e.selectionLayer,min:0,max:20,step:1,onChange:o=>n("selectiveBloom",{...e,selectionLayer:o})}),be(N,{label:"Intensity",value:e.intensity,min:0,max:5,step:.05,onChange:o=>n("selectiveBloom",{...e,intensity:o})}),be(N,{label:"Threshold",value:e.luminanceThreshold,min:0,max:1,step:.01,onChange:o=>n("selectiveBloom",{...e,luminanceThreshold:o})}),be(N,{label:"Smoothing",value:e.luminanceSmoothing,min:0,max:1,step:.01,onChange:o=>n("selectiveBloom",{...e,luminanceSmoothing:o})}),be(Ee,{label:"Kernel Size",value:e.kernelSize,options:Jt,onChange:o=>n("selectiveBloom",{...e,kernelSize:o})}),be(J,{label:"Mipmap Blur",checked:e.mipmapBlur,onChange:o=>n("selectiveBloom",{...e,mipmapBlur:o})}),be(J,{label:"Inverted",checked:e.inverted,onChange:o=>n("selectiveBloom",{...e,inverted:o})}),be(J,{label:"Ignore Background",checked:e.ignoreBackground,onChange:o=>n("selectiveBloom",{...e,ignoreBackground:o})})]})}function Qi({pp:t,set:n,open:i,toggle:r}){let{smaa:e}=t;return be(q,{title:"SMAA",tooltip:"Reduces jagged edges with subpixel anti-aliasing.",open:i.smaa,onToggle:()=>r("smaa"),trailing:be(X,{checked:e.enabled,onChange:o=>n("smaa",{...e,enabled:o}),label:"Toggle SMAA"}),children:be("div",{className:"se-placeholder",children:"Subpixel Morphological Anti-Aliasing smooths jagged edges in post-process."})})}import{jsx as pe,jsxs as ud}from"react/jsx-runtime";function Bo({config:t,onChange:n}){let[i,r]=pd({autofocus:!1,colorAverage:!1,dotScreen:!1,glitch:!1,godRays:!1,grid:!1,lensflare:!1,outline:!1,selectiveBloom:!1,ramp:!1,ssao:!1,brightnessContrast:!1,hueSaturation:!1,depthOfField:!1,chromaticAberration:!1,vignette:!1,bloom:!1,toneMapping:!1,noise:!1,sepia:!1,scanline:!1,pixelation:!1,smaa:!1}),e=b=>r(w=>({...w,[b]:!w[b]})),o=t.postProcessing,l={pp:o,set:(b,w)=>n({...t,postProcessing:{...o,[b]:w}}),open:i,toggle:e};return ud("div",{className:"se-generalContent",children:[pe(Ai,{...l}),pe(Oi,{...l}),pe(Di,{...l}),pe(Ui,{...l}),pe($i,{...l}),pe(Li,{...l}),pe(Ki,{...l}),pe(zi,{...l}),pe(Xi,{...l}),pe(Zi,{...l}),pe(ji,{...l}),pe(Ii,{...l}),pe(Ei,{...l}),pe(_i,{...l}),pe(Fi,{...l}),pe(Hi,{...l}),pe(Vi,{...l}),pe(Wi,{...l}),pe(Gi,{...l}),pe(Yi,{...l}),pe(qi,{...l}),pe(Ji,{...l}),pe(Qi,{...l})]})}import{useState as tr,useSyncExternalStore as md}from"react";import{Eye as gd,EyeOff as fd,Plus as hd,Trash2 as xd}from"lucide-react";import{Fragment as nr,jsx as F,jsxs as De}from"react/jsx-runtime";var vd=["512","1024","2048","4096"],or={none:"None",directional:"Direction",point:"Point",spot:"Spot",hemisphere:"Hemi"};function yd({index:t,light:n,selected:i,onSelect:r,onToggleVisible:e}){return De("div",{className:`se-lightRow ${i?"se-lightRow--active":""}`,onClick:r,children:[De("span",{className:"se-lightRowLabel",children:[t+1,": ",or[n.type]]}),F("button",{type:"button",className:"se-iconButton","aria-label":n.visible?"Hide light":"Show light",onClick:o=>{o.stopPropagation(),e()},children:n.visible?F(gd,{size:14}):F(fd,{size:14})})]})}function wd(){return{id:crypto.randomUUID(),type:"directional",color:"#ffffff",intensity:1,position:[5,10,5],attachedToCamera:!1,castShadow:!1,shadowBias:-5e-4,visible:!0}}function Ro({config:t,onChange:n}){let[i,r]=tr({lights:!0,shadows:!1,groundShadows:!1,environment:!1,envShadow:!1}),e=md(ai,ii),[o,d]=tr(t.lighting.lights[0]?.id??null),l=e??o,b=a=>{d(a),oi(a)},w=a=>r(u=>({...u,[a]:!u[a]})),{tier:A}=Ze(),k=_e(A,"starter"),{lighting:s,shadows:h,groundShadows:S,environment:m}=t,f=a=>n({...t,lighting:a}),y=a=>n({...t,shadows:a}),p=a=>n({...t,groundShadows:a}),g=a=>n({...t,environment:a}),T=(a,u)=>{f({...s,lights:s.lights.map(z=>z.id===a?{...z,...u}:z)})},x=s.lights.find(a=>a.id===l)??null,v=()=>{let a=wd();f({...s,lights:[...s.lights,a]}),b(a.id)},P=()=>{if(!x)return;let a=s.lights.filter(u=>u.id!==x.id);f({...s,lights:a}),b(a[0]?.id??null)};return De("div",{className:"se-generalContent",children:[De(q,{title:"Lights",open:i.lights,onToggle:()=>w("lights"),children:[F("div",{className:"se-lightList",children:s.lights.map((a,u)=>F(yd,{index:u,light:a,selected:a.id===l,onSelect:()=>b(a.id),onToggleVisible:()=>T(a.id,{visible:!a.visible})},a.id))}),De("div",{className:"se-lightActions",children:[F("button",{type:"button",className:"se-iconButton",onClick:v,title:"Add light",children:F(hd,{size:14})}),x&&s.lights.length>1&&F("button",{type:"button",className:"se-iconButton",onClick:P,title:"Remove selected light",children:F(xd,{size:14})})]}),x?De("div",{className:"se-lightProps",children:[De("div",{className:"se-field",children:[F("span",{className:"se-fieldLabel",children:"Type"}),F("div",{className:"se-segmentedControl",style:{gridAutoColumns:"1fr"},children:Ha.map(a=>F("button",{type:"button",className:`se-segmentedOption ${x.type===a?"se-segmentedOption--active":""}`,onClick:()=>T(x.id,{type:a}),children:or[a]},a))})]}),F(Le,{label:"Color",value:x.color,onChange:a=>T(x.id,{color:a})}),F(N,{label:"Intensity",value:x.intensity,min:0,max:10,step:.1,onChange:a=>T(x.id,{intensity:a})}),x.type!=="hemisphere"&&x.type!=="none"&&F(mt,{label:"Position",value:x.position,min:-100,max:100,step:.05,onChange:a=>T(x.id,{position:a})}),x.type==="spot"&&De(nr,{children:[F(N,{label:"Angle",value:x.angle??Math.PI/6,min:0,max:Math.PI/2,step:.01,formatValue:a=>`${Math.round(a*180/Math.PI)}\xB0`,onChange:a=>T(x.id,{angle:a})}),F(N,{label:"Penumbra",value:x.penumbra??.2,min:0,max:1,step:.01,onChange:a=>T(x.id,{penumbra:a})}),F(N,{label:"Distance",value:x.distance??0,min:0,max:100,step:.5,onChange:a=>T(x.id,{distance:a})}),F(N,{label:"Decay",value:x.decay??2,min:0,max:4,step:.1,onChange:a=>T(x.id,{decay:a})})]}),F(J,{label:"Attached to camera",checked:x.attachedToCamera,onChange:a=>T(x.id,{attachedToCamera:a})}),F(J,{label:"Cast shadows",checked:x.castShadow,onChange:a=>T(x.id,{castShadow:a})}),F(N,{label:"Shadow bias",value:x.shadowBias,min:-.01,max:.01,step:1e-4,onChange:a=>T(x.id,{shadowBias:a})})]}):null]}),De(q,{title:"Shadows",open:i.shadows,onToggle:()=>w("shadows"),disabled:!h.enabled,trailing:F(X,{checked:h.enabled,onChange:a=>y({...h,enabled:a}),label:"Toggle shadows"}),children:[F(Ee,{label:"Map size",value:String(h.mapSize),options:vd,onChange:a=>y({...h,mapSize:Number(a)})}),F(N,{label:"Bias",value:h.bias,min:-.01,max:.01,step:1e-4,onChange:a=>y({...h,bias:a})}),F(N,{label:"Normal bias",value:h.normalBias,min:0,max:.2,step:.01,onChange:a=>y({...h,normalBias:a})}),F(N,{label:"Radius (softness)",value:h.radius,min:0,max:20,step:.5,onChange:a=>y({...h,radius:a})})]}),De(q,{title:"Ground Shadows",open:i.groundShadows,onToggle:()=>w("groundShadows"),disabled:!S.enabled,trailing:F(X,{checked:S.enabled,onChange:a=>p({...S,enabled:a}),label:"Toggle ground shadows"}),children:[De("div",{className:"se-field",children:[F("span",{className:"se-fieldLabel",children:"Mode"}),F("div",{className:"se-segmentedControl",style:{gridAutoColumns:"1fr"},children:["shadowCatcher"].map(a=>F("button",{type:"button",className:`se-segmentedOption ${S.mode===a?"se-segmentedOption--active":""}`,onClick:()=>p({...S,mode:a}),children:a==="shadowCatcher"?"Shadow Catcher":"Baked AO"},a))})]}),S.mode==="bakedAO"&&F("div",{className:"se-placeholder",children:"Requires pre-baked AO textures \u2014 not yet available."}),F(N,{label:"Intensity",value:S.intensity,min:0,max:1,step:.01,onChange:a=>p({...S,intensity:a})}),F(N,{label:"Border fade",value:S.borderFade,min:0,max:10,step:.1,onChange:a=>p({...S,borderFade:a})}),F(N,{label:"Height",value:S.height,min:-5,max:5,step:.1,onChange:a=>p({...S,height:a})}),F(N,{label:"Size",value:S.size,min:1,max:50,step:.5,onChange:a=>p({...S,size:a})})]}),F(q,{title:"Environment",open:i.environment,onToggle:()=>w("environment"),children:k?De(nr,{children:[F(N,{label:"Orientation",value:m.rotation,min:0,max:360,step:1,formatValue:a=>`${a}\xB0`,onChange:a=>g({...m,rotation:a})}),F(N,{label:"Brightness",value:m.intensity,min:0,max:3,step:.05,onChange:a=>g({...m,intensity:a})}),De(q,{title:"Shadow",open:i.envShadow,onToggle:()=>w("envShadow"),trailing:F(X,{checked:m.shadowLight.enabled,onChange:a=>g({...m,shadowLight:{...m.shadowLight,enabled:a}}),label:"Toggle environment shadow light"}),disabled:!m.shadowLight.enabled,children:[F(N,{label:"Light intensity",value:m.shadowLight.intensity,min:0,max:20,step:.1,onChange:a=>g({...m,shadowLight:{...m.shadowLight,intensity:a}})}),F(N,{label:"Shadow bias",value:m.shadowLight.bias,min:-.01,max:.01,step:1e-4,onChange:a=>g({...m,shadowLight:{...m.shadowLight,bias:a}})})]})]}):F(Ne,{requiredTier:"starter",feature:"Environment lighting"})})]})}import{useMemo as Cd,useState as Sd}from"react";import{ChevronDown as kd,Pause as ar,Play as Nd,Rewind as Td,Square as Pd,Trash2 as Bd}from"lucide-react";import{jsx as K,jsxs as ue}from"react/jsx-runtime";var Rd={playing:"Playing",paused:"Paused",finished:"Finished"},ir={repeat:"Looping",once:"Play once","ping-pong":"Ping-pong"};function Md(t){if(!Number.isFinite(t)||t<=0)return"Unknown duration";let n=Math.round(t*10)/10;if(n<60)return`${n.toFixed(1)}s`;let i=Math.floor(n/60),r=(n%60).toFixed(1).padStart(4,"0");return`${i}:${r}`}function rr(t){let n=Number.isFinite(t)&&t>0?t:0;if(n<60)return`${n.toFixed(1)}s`;let i=Math.floor(n/60),r=(n%60).toFixed(1).padStart(4,"0");return`${i}:${r}`}function Ad(t){return Number.isFinite(t)?Math.min(3,Math.max(.1,Number(t.toFixed(2)))):1}function Mo({config:t,onChange:n,clipDetails:i,active:r,play:e,pause:o,stop:d,setSpeed:l,seek:b}){let[w,A]=Sd(!1),k=Cd(()=>new Map(i.map(v=>[v.sourceName,v.duration])),[i]),s=t.animations.clips.filter(v=>!v.hidden),h=t.animations.clips.filter(v=>v.hidden),S=(v,P=t.animations.autoplayClip)=>{n({...t,animations:{clips:v(t.animations.clips),autoplayClip:P}})},m=(v,P)=>{S(a=>a.map(u=>u.sourceName===v?P(u):u))},f=(v,P)=>{m(v,a=>({...a,loopMode:P}))},y=(v,P)=>{let a=Ad(P);m(v,u=>({...u,speed:a})),r.some(u=>u.clip===v)&&l(a,v)},p=(v,P)=>{m(v,a=>({...a,displayName:P}))},g=v=>{let P=t.animations.autoplayClip===v?null:v;n({...t,animations:{...t.animations,autoplayClip:P}})},T=v=>{S(P=>P.map(a=>a.sourceName===v?{...a,hidden:!0}:a),t.animations.autoplayClip===v?null:t.animations.autoplayClip),r.some(P=>P.clip===v)&&d(v)},x=v=>{S(P=>P.map(a=>a.sourceName===v?{...a,hidden:!1}:a))};return t.animations.clips.length===0?K(rt,{title:"Animations",children:K("div",{className:"se-helperCard",children:"Upload a model with embedded animations to manage playback, naming, autoplay, and per-clip speed here."})}):ue(rt,{title:"Animations",children:[s.length===0&&K("div",{className:"se-helperCard",children:K("span",{children:"Preview clips directly in the viewer (several can play at once), choose one optional autoplay animation, and use soft delete to hide clips without modifying the GLB."})}),s.length===0?K("div",{className:"se-placeholder",children:"All animations are currently removed. Restore a clip below to make it available again."}):K("div",{className:"se-animationList",children:s.map(v=>{let P=r.find($=>$.clip===v.sourceName),a=P?.status==="playing",u=P?.time??0,z=k.get(v.sourceName)??0,D=P?Rd[P.status]:"Ready";return ue("article",{className:`se-animationCard ${P?"se-animationCard--active":""}`,children:[ue("div",{className:"se-animationHeader",children:[ue("div",{className:"se-animationHeading",children:[ue("div",{className:"se-animationTitleRow",children:[K("span",{className:"se-animationStatus",children:D}),t.animations.autoplayClip===v.sourceName?K("span",{className:"se-animationBadge",children:"Autoplay"}):null]}),K("div",{className:"se-animationSource",children:v.sourceName})]}),K("button",{type:"button",className:"se-animationDangerButton",onClick:()=>T(v.sourceName),title:"Remove animation",children:K(Bd,{size:16})})]}),ue("div",{className:"se-field",children:[K("span",{className:"se-fieldLabel",children:"Display name"}),K("input",{className:"se-textInput",value:v.displayName,onChange:$=>p(v.sourceName,$.target.value),placeholder:"Animation name"})]}),ue("div",{className:"se-animationMeta",children:[K("span",{children:Md(z)}),K("span",{children:ir[v.loopMode]??ir.repeat}),ue("span",{children:[v.speed.toFixed(2),"x"]})]}),ue("div",{className:"se-animationButtonRow",children:[K("button",{type:"button",className:"se-animationButton se-animationButton--icon",onClick:()=>a&&!P?.reverse?o(v.sourceName):e(v.sourceName,{alongside:!0}),"aria-label":a&&!P?.reverse?"Pause":"Play",title:a&&!P?.reverse?"Pause":"Play",children:a&&!P?.reverse?K(ar,{size:16}):K(Nd,{size:16})}),K("button",{type:"button",className:"se-animationButton se-animationButton--icon",onClick:()=>a&&P?.reverse?o(v.sourceName):e(v.sourceName,{alongside:!0,reverse:!0}),"aria-label":a&&P?.reverse?"Pause":"Play backwards",title:a&&P?.reverse?"Pause":"Play backwards",children:a&&P?.reverse?K(ar,{size:16}):K(Td,{size:16})}),K("button",{type:"button",className:"se-animationButton se-animationButton--icon",onClick:()=>d(v.sourceName),disabled:!P,"aria-label":"Stop",title:"Stop",children:K(Pd,{size:16})})]}),ue("div",{className:"se-animationSeekRow",children:[K("input",{className:"se-slider se-animationSeek",type:"range",min:0,max:Math.max(z,.001),step:.01,value:Math.min(u,z),disabled:!P||z<=0,onChange:$=>b(Number($.target.value),v.sourceName),"aria-label":"Seek"}),ue("span",{className:"se-animationSeekTime",children:[rr(Math.min(u,z))," / ",rr(z)]})]}),ue("div",{className:"se-animationGrid",children:[ue("label",{className:"se-field",children:[K("span",{className:"se-fieldLabel",children:"Loop mode"}),ue("select",{className:"se-select",value:v.loopMode,onChange:$=>f(v.sourceName,$.target.value),children:[K("option",{value:"repeat",children:"Loop"}),K("option",{value:"once",children:"Play Once"}),K("option",{value:"ping-pong",children:"Ping-Pong"})]})]}),ue("label",{className:"se-field",children:[ue("span",{className:"se-fieldLabel",children:["Speed",ue("span",{className:"se-fieldValue",children:[v.speed.toFixed(2),"x"]})]}),ue("div",{className:"se-animationSpeedRow",children:[K("input",{className:"se-slider",type:"range",min:.1,max:3,step:.1,value:v.speed,onChange:$=>y(v.sourceName,Number($.target.value))}),K("input",{className:"se-numberInput se-animationSpeedInput",type:"number",min:.1,max:3,step:.1,value:v.speed,onChange:$=>y(v.sourceName,Number($.target.value))})]})]})]}),K("button",{type:"button",className:`se-animationAutoplayButton ${t.animations.autoplayClip===v.sourceName?"se-animationAutoplayButton--active":""}`,onClick:()=>g(v.sourceName),children:t.animations.autoplayClip===v.sourceName?"Disable autoplay":"Set as autoplay"})]},v.sourceName)})}),h.length>0?ue("section",{className:"se-removedAnimations",children:[K("button",{type:"button",className:"se-panelHeader",onClick:()=>A(v=>!v),children:ue("span",{className:"se-panelHeaderMain",children:[K(kd,{size:16,className:`se-panelChevron ${w?"se-panelChevron--open":""}`}),ue("span",{className:"se-panelTitle",children:["Removed Animations (",h.length,")"]})]})}),w?K("div",{className:"se-removedAnimationList",children:h.map(v=>ue("div",{className:"se-removedAnimationRow",children:[ue("div",{children:[K("div",{className:"se-removedAnimationName",children:v.displayName||v.sourceName}),K("div",{className:"se-animationSource",children:v.sourceName})]}),K("button",{type:"button",className:"se-animationButton",onClick:()=>x(v.sourceName),children:"Restore"})]},v.sourceName))}):null]}):null]})}import{useState as Ao}from"react";import{Eye as Od,Pencil as Ld,Trash2 as zd}from"lucide-react";import{jsx as H,jsxs as W}from"react/jsx-runtime";function Oo({config:t,onChange:n,cameraState:i,onPreviewView:r}){let[e,o]=Ao(null),[d,l]=Ao(""),[b,w]=Ao(""),A=f=>{o(structuredClone(f)),l(f.minDistance?.toString()??""),w(f.maxDistance?.toString()??"")},k=d.trim()===""?void 0:Number(d),s=b.trim()===""?void 0:Number(b),h=[k,s].some(f=>f!==void 0&&(!Number.isFinite(f)||f<0))?"Distances must be non-negative numbers.":k!==void 0&&s!==void 0&&k>s?"Maximum distance must be at least the minimum.":e?.images?.some(f=>f.src.trim()&&!xo(f.src))||e?.links?.some(f=>f.href.trim()&&!xo(f.href))?"Use an HTTP(S) URL or a relative path for images and links.":null,S=()=>{if(!e?.title.trim()||h)return;let f={...e,title:e.title.trim(),category:e.category?.trim()||void 0,minDistance:k,maxDistance:s,images:e.images?.filter(y=>y.src.trim()).map(y=>({...y,src:y.src.trim()})),links:e.links?.filter(y=>y.href.trim()).map(y=>({...y,href:y.href.trim(),label:y.label.trim()||"Learn more"}))};n({...t,annotations:t.annotations.map(y=>y.id===e.id?f:y)}),o(null)},m=f=>{window.confirm("Delete this annotation?")&&(n({...t,annotations:t.annotations.filter(y=>y.id!==f).map((y,p)=>({...y,id:p+1}))}),o(null))};return W(rt,{title:"Annotations",children:[t.annotations.length===0?H("div",{className:"bb-emptyAnnotations",children:"No annotations yet. Double-click on the model to add one."}):H("div",{className:"se-annotationList",children:t.annotations.map(f=>W("div",{className:"se-annotationRow",children:[W("span",{className:"se-annotationNumber",children:["#",f.id]}),W("div",{className:"se-annotationSummary",children:[W("div",{className:"se-annotationHeading",children:[H("span",{className:"se-annotationTitle",title:f.title,children:f.title}),f.category?.trim()&&H("span",{className:"se-annotationCategory",title:f.category,children:f.category})]}),f.description&&H("p",{className:"se-annotationDescription",title:f.description,children:f.description})]}),W("div",{className:"se-annotationActions",children:[Ja(f.cameraView)&&H("button",{type:"button",className:"se-annotationAction",disabled:!r,onClick:()=>r?.(f.cameraView),title:"Preview saved view","aria-label":`Preview saved view for ${f.title}`,children:H(Od,{size:15,"aria-hidden":"true"})}),H("button",{type:"button",className:"se-annotationAction",onClick:()=>A(f),title:"Edit annotation","aria-label":`Edit ${f.title}`,children:H(Ld,{size:15,"aria-hidden":"true"})}),H("button",{type:"button",className:"se-annotationAction se-annotationAction--delete",onClick:()=>m(f.id),title:"Delete annotation","aria-label":`Delete ${f.title}`,children:H(zd,{size:15,"aria-hidden":"true"})})]})]},f.id))}),e&&H("div",{className:"bb-editAnnotationOverlay",onClick:()=>o(null),children:W("div",{className:"bb-editAnnotationPopup",onKeyDown:f=>{f.key==="Escape"&&(f.stopPropagation(),o(null))},role:"dialog","aria-modal":"true","aria-labelledby":"annotation-edit-title",onClick:f=>f.stopPropagation(),children:[W("div",{className:"bb-editAnnotationHeader",children:[H("h3",{id:"annotation-edit-title",className:"bb-editAnnotationTitle",children:"Edit annotation"}),H("button",{className:"bb-editAnnotationClose","aria-label":"Close annotation editor",onClick:()=>o(null),children:"\xD7"})]}),W("div",{className:"bb-editAnnotationBody",children:[W("label",{className:"bb-field",children:[H("span",{className:"bb-label",children:"Title"}),H("input",{className:"bb-input",autoFocus:!0,value:e.title,onChange:f=>o({...e,title:f.target.value})})]}),W("label",{className:"bb-field",children:[H("span",{className:"bb-label",children:"Description"}),H("textarea",{className:"bb-textarea",rows:3,value:e.description,onChange:f=>o({...e,description:f.target.value})})]}),W("label",{className:"bb-field",children:[H("span",{className:"bb-label",children:"Category"}),H("input",{className:"bb-input",value:e.category??"",onChange:f=>o({...e,category:f.target.value}),placeholder:"For example, Features"})]}),W("p",{className:"se-annotationCoordinates",children:["Position: [",e.worldPosition.map(f=>f.toFixed(2)).join(", "),"]"]}),W("fieldset",{className:"bb-annotationFields",children:[H("legend",{children:"Saved camera view"}),H("p",{children:e.cameraView?"Tours use this saved view. Clear it to restore automatic close-up zoom.":"Tours automatically zoom in on the marker. Capture a view to use custom framing."}),W("div",{className:"bb-annotationFieldActions",children:[H("button",{className:"bb-button",disabled:!i,onClick:()=>i&&o({...e,cameraView:structuredClone(i)}),children:"Capture current view"}),H("button",{className:"bb-button",disabled:!e.cameraView||!r,onClick:()=>e.cameraView&&r?.(e.cameraView),children:"Preview"}),H("button",{className:"bb-button",disabled:!e.cameraView,onClick:()=>o({...e,cameraView:void 0}),children:"Clear view"})]})]}),W("fieldset",{className:"bb-annotationFields",children:[H("legend",{children:"Marker distance (scene units)"}),H("p",{children:"Leave blank to show markers at any distance."}),W("div",{className:"bb-annotationDistanceFields",children:[W("label",{className:"bb-field",children:[H("span",{className:"bb-label",children:"Minimum distance"}),H("input",{className:"bb-input",type:"number",min:"0",step:"any",value:d,onChange:f=>l(f.target.value)})]}),W("label",{className:"bb-field",children:[H("span",{className:"bb-label",children:"Maximum distance"}),H("input",{className:"bb-input",type:"number",min:"0",step:"any",value:b,onChange:f=>w(f.target.value)})]})]})]}),W("fieldset",{className:"bb-annotationFields",children:[H("legend",{children:"Images"}),e.images?.map((f,y)=>W("div",{className:"bb-annotationMediaRow",children:[W("label",{className:"bb-field",children:[W("span",{className:"bb-label",children:["Image URL ",y+1]}),H("input",{className:"bb-input",value:f.src,onChange:p=>o({...e,images:e.images.map((g,T)=>T===y?{...g,src:p.target.value}:g)}),placeholder:"https://example.com/image.jpg"})]}),W("label",{className:"bb-field",children:[W("span",{className:"bb-label",children:["Image description ",y+1]}),H("input",{className:"bb-input",value:f.alt??"",onChange:p=>o({...e,images:e.images.map((g,T)=>T===y?{...g,alt:p.target.value}:g)})})]}),W("button",{className:"bb-button",onClick:()=>o({...e,images:e.images.filter((p,g)=>g!==y)}),children:["Remove image ",y+1]})]},y)),H("button",{className:"bb-button",onClick:()=>o({...e,images:[...e.images??[],{src:"",alt:""}]}),children:"Add image"})]}),W("fieldset",{className:"bb-annotationFields",children:[H("legend",{children:"Links"}),e.links?.map((f,y)=>W("div",{className:"bb-annotationMediaRow",children:[W("label",{className:"bb-field",children:[W("span",{className:"bb-label",children:["Link URL ",y+1]}),H("input",{className:"bb-input",value:f.href,onChange:p=>o({...e,links:e.links.map((g,T)=>T===y?{...g,href:p.target.value}:g)}),placeholder:"https://example.com/details"})]}),W("label",{className:"bb-field",children:[W("span",{className:"bb-label",children:["Link label ",y+1]}),H("input",{className:"bb-input",value:f.label,onChange:p=>o({...e,links:e.links.map((g,T)=>T===y?{...g,label:p.target.value}:g)})})]}),W("button",{className:"bb-button",onClick:()=>o({...e,links:e.links.filter((p,g)=>g!==y)}),children:["Remove link ",y+1]})]},y)),H("button",{className:"bb-button",onClick:()=>o({...e,links:[...e.links??[],{href:"",label:""}]}),children:"Add link"})]}),h&&H("p",{role:"alert",children:h}),W("div",{className:"bb-editAnnotationActions",children:[H("button",{className:"bb-button",onClick:()=>o(null),children:"Cancel"}),H("button",{className:"bb-button bb-button--primary",disabled:!e.title.trim()||!!h,onClick:S,children:"Save"}),H("button",{className:"bb-button bb-button--danger",onClick:()=>m(e.id),children:"Delete"})]})]})]})})]})}import{useState as Ed,useCallback as Nt}from"react";import{ArrowDown as Dd,ArrowUp as jd,MapPin as Id,Plus as Fd,Trash2 as Hd,Settings as Vd}from"lucide-react";import{Fragment as Ud,jsx as oe,jsxs as ye}from"react/jsx-runtime";var Gd={enabled:!0,waypoints:[],loop:!0,autoPlay:!1},Tt=3.5;function Lo({config:t,onChange:n,cameraState:i,onPreviewWaypoint:r}){let e=t.cinematic??Gd,o=Ln(),{waypoints:d}=e,l=Nt((p,g)=>{if(p.length<2)return 0;let T=0;for(let x=0;x<p.length-1;x++){let v=p[x].segmentDuration??Tt;T+=v}return g&&p.length>1&&(T+=p[p.length-1].segmentDuration??Tt),Math.max(T,0)},[]),b=Nt(p=>{n({...t,cinematic:{...e,...p}})},[t,e,n]),w=Nt(()=>{if(!i)return;let p={position:[...i.position],target:[...i.target],...i.azimuthAngle!=null?{azimuthAngle:i.azimuthAngle}:{},...i.polarAngle!=null?{polarAngle:i.polarAngle}:{},segmentDuration:Tt},g=[...d,p],T=l(g,e.loop);b({waypoints:g,duration:T})},[i,d,e.loop,l,b]),A=Nt(p=>{let g=d.filter((x,v)=>v!==p),T=l(g,e.loop);b({waypoints:g,duration:T})},[d,e.loop,l,b]),k=Nt((p,g)=>{let T=p+g;if(T<0||T>=d.length)return;let x=[...d];[x[p],x[T]]=[x[T],x[p]];let v=l(x,e.loop);b({waypoints:x,duration:v})},[d,e.loop,l,b]),s=Nt((p,g)=>{let T=d.map((v,P)=>P===p?{...v,...g}:v),x=l(T,e.loop);b({waypoints:T,duration:x})},[d,e.loop,l,b]),[h,S]=Ed(!1),m=d.some(p=>p.segmentDuration!==void 0),f=Nt(p=>p>=d.length-1?Tt:d[p]?.segmentDuration??Tt,[d]),y=d.length>=2;return ye(rt,{title:"Cinematic Camera",children:[oe("p",{className:"se-cinematicHint",children:"Frame the model in the viewer, then capture it as a waypoint. The camera glides through the waypoints in order \u2014 enable and press play in the viewer to preview."}),ye("button",{type:"button",className:"bb-button bb-button--primary se-cinematicAdd",onClick:w,disabled:!i,title:"Capture the current camera view as a waypoint",children:[oe(Fd,{size:15}),"Add waypoint from current view"]}),ye("div",{className:"se-customizeToggle",children:[ye("label",{className:"se-toggleLabel",children:[oe("input",{type:"checkbox",checked:h,onChange:p=>S(p.target.checked)}),oe(Vd,{size:14}),oe("span",{children:"Customize durations between waypoints"})]}),h&&ye("span",{className:"se-toggleHint",children:["Set duration for each segment between waypoints: 1\u21922, 2\u21923, etc. Default: ",Tt,"s"]})]}),d.length===0?oe("div",{className:"bb-emptyAnnotations",children:"No waypoints yet. Position the camera and add your first one."}):ye(Ud,{children:[oe("div",{className:"se-waypointList",children:d.map((p,g)=>{let T=f(g),x=g===d.length-1,v=p.segmentDuration!==void 0&&p.segmentDuration!==Tt;return ye("div",{children:[ye("div",{className:"se-waypointCard",children:[oe("div",{className:"se-waypointBadge",children:g+1}),ye("div",{className:"se-waypointBody",children:[ye("div",{className:"se-waypointCoords",children:["pos [",p.position.map(P=>P.toFixed(1)).join(", "),"]"]}),ye("div",{className:"se-waypointCoords",children:["look [",p.target.map(P=>P.toFixed(1)).join(", "),"]"]}),h&&!x&&ye("div",{className:`se-customBadge ${v?"se-customBadge--custom":"se-customBadge--default"}`,children:[T.toFixed(1),"s",!v&&" (default)"]})]}),ye("div",{className:"se-waypointActions",children:[oe("button",{className:"se-waypointAction",onClick:()=>r?.(p),title:"Fly camera to this waypoint",disabled:!r,children:oe(Id,{size:15})}),oe("button",{className:"se-waypointAction",onClick:()=>k(g,-1),title:"Move up",disabled:g===0,children:oe(jd,{size:15})}),oe("button",{className:"se-waypointAction",onClick:()=>k(g,1),title:"Move down",disabled:x,children:oe(Dd,{size:15})}),oe("button",{className:"se-waypointAction se-waypointAction--delete",onClick:()=>A(g),title:"Delete waypoint",children:oe(Hd,{size:15})})]})]}),h&&!x&&ye("div",{className:"se-segmentBetween",children:[ye("div",{className:"se-segmentLabel",children:[g+1," \u2192 ",g+2,!p.segmentDuration&&" (default)"]}),ye("div",{className:"se-segmentControls",children:[oe("span",{className:"se-durationLabel",children:"Duration:"}),oe("input",{type:"range",className:"se-segmentSlider",min:1,max:20,step:.5,value:T,onChange:P=>{let a=parseFloat(P.target.value);s(g,{segmentDuration:a})}}),ye("span",{className:"se-segmentValue",children:[T.toFixed(1),"s"]}),ye("div",{className:"se-presetButtons",children:[[2,4,6,8].map(P=>ye("button",{className:"se-presetButton",onClick:()=>s(g,{segmentDuration:P}),children:[P,"s"]},`preset-${g}-${P}`)),oe("button",{className:"se-presetButton se-presetButton--default",onClick:()=>{let P=d.map((u,z)=>{if(z===g){let{segmentDuration:D,...$}=u;return $}return u}),a=l(P,e.loop);b({waypoints:P,duration:a})},children:"Reset"})]})]})]})]},`waypoint-wrapper-${g}`)})}),ye("div",{className:"se-totalDuration",children:[oe("span",{className:"se-totalLabel",children:"Total duration:"}),oe("span",{className:"se-totalValue",children:y?(e.duration??l(d,e.loop)).toFixed(1)+"s":"-"}),!y&&oe("span",{className:"se-totalHint",children:"(need at least 2 waypoints)"})]})]}),oe(J,{label:"Enable cinematic camera",checked:e.enabled,onChange:p=>b({enabled:p})}),oe(J,{label:"Loop",checked:e.loop,onChange:p=>{let g=p,T=l(d,g);b({loop:g,duration:T})}}),oe(J,{label:"Auto-play on load",checked:e.autoPlay,onChange:p=>b({autoPlay:p})}),e.autoPlay&&o?oe("div",{className:"se-placeholder se-placeholder--spaced",children:"Your device is set to reduce motion, so this preview won't play on its own. Visitors without that setting will see it."}):null,!h&&y&&oe(N,{label:"Duration",value:e.duration??l(d,e.loop),min:4,max:120,step:1,formatValue:p=>`${p}s`,onChange:p=>b({duration:p})})]})}import{useMemo as $d,useRef as Kd,useState as ur}from"react";import{HexColorInput as _d,HexColorPicker as Wd}from"react-colorful";import{ArrowDown as Yd,ArrowUp as qd,ChevronDown as Jd,Plus as zo,Trash2 as Xd,X as lr}from"lucide-react";var sr=["other","body","light","wheel","glass","interior","floor","wall","door","furniture","decor","electronics","seat","table","chair","window","sofa","bed","engine","headlight"],Hn=["normal","hidden","selected","disabled"];import{Fragment as pr,jsx as L,jsxs as de}from"react/jsx-runtime";var Eo={all:"All objects",group:"Group",tag:"Tag",type:"Type",object:"One object"},dr={metric:"Metric",status:"Status",metadata:"Metadata"},Zd={metric:"",stops:[[0,"#3b82f6"],[100,"#ef4444"]]};function Qd(t){return t===void 0?"all":typeof t=="string"||Array.isArray(t)?"object":"group"in t?"group":"tag"in t?"tag":"type"}function nn(t){return t===void 0?"":typeof t=="string"?t:Array.isArray(t)?t[0]??"":"group"in t?t.group:"tag"in t?t.tag:t.type}function cr(t,n){if(t!=="all")return t==="object"?n:t==="group"?{group:n}:t==="tag"?{tag:n}:{type:n}}function ec(t){return"metric"in t?"metric":"status"in t?"status":"metadata"}function br(t){return t==="metric"?{metric:""}:t==="status"?{status:["disabled"]}:{metadata:"",equals:""}}function tc(t){let n=t.trim();return n==="true"?!0:n==="false"?!1:n==="null"?null:n!==""&&Number.isFinite(Number(n))?Number(n):t}function Do(t){return t.trim()===""||!Number.isFinite(Number(t))?void 0:Number(t)}function mr(t,n="",i=0){return typeof t!="object"||t===null||Array.isArray(t)?n?[n]:[]:i>2?n?[n]:[]:Object.entries(t).flatMap(([r,e])=>mr(e,n?`${n}.${r}`:r,i+1))}var on=t=>[...new Set(t.filter(n=>!!n))].sort((n,i)=>n.localeCompare(i));function Qe({label:t,children:n}){return de("label",{className:"se-field",children:[L("span",{className:"se-fieldLabel",children:t}),n]})}function an({label:t,checked:n,color:i,onToggle:r,onColorChange:e}){let[o,d]=ur(!1),l=Kd(null);return de("div",{className:"se-field se-fieldInline",children:[de("label",{className:"se-ruleLook",children:[L("input",{type:"checkbox",className:"se-checkbox",checked:n,onChange:b=>r(b.target.checked)}),t]}),n&&i!==void 0&&e?L("span",{ref:l,style:{display:"inline-flex"},children:L(_d,{prefixed:!0,className:"se-swatch","aria-label":`${t} value`,onClick:()=>d(b=>!b),style:{background:i,color:ut(i)},color:i,onChange:e})}):null,o?L(en,{anchorRef:l,onClose:()=>d(!1),children:L(Wd,{color:i,onChange:e})}):null]})}function nc({title:t,open:n,onToggle:i,actions:r,children:e}){return de("section",{className:"se-panel",children:[de("div",{className:"se-ruleHeader",children:[L("button",{type:"button",className:"se-panelHeader",onClick:i,"aria-expanded":n,children:de("span",{className:"se-panelHeaderMain",children:[L(Jd,{size:16,className:`se-panelChevron ${n?"se-panelChevron--open":""}`}),L("span",{className:"se-panelTitle",children:t})]})}),L("span",{className:"se-ruleActions",children:r})]}),n?L("div",{className:"se-panelBody",children:e}):null]})}function jo({config:t,onChange:n,objectBindings:i}){let r=t.styleRules??[],[e,o]=ur(r[0]?.id??null),d=$d(()=>{let s=Object.values(i);return{groups:on(s.map(h=>h.group)),tags:on(s.flatMap(h=>h.tags??[])),types:on(s.map(h=>h.type??"other")),objects:s.map(h=>({id:h.id,label:h.label||h.id})).sort((h,S)=>h.label.localeCompare(S.label)),metrics:on(s.flatMap(h=>Object.keys(h.metrics??{}))),metadata:on(s.flatMap(h=>mr(h.metadata)))}},[i]),l=s=>n({...t,styleRules:s}),b=(s,h)=>l(r.map(S=>S.id===s?h(S):S)),w=()=>{let s=crypto.randomUUID();l([...r,{id:s,label:`Rule ${r.length+1}`,when:[{status:["disabled"]}],material:{baseColor:"#9ca3af"}}]),o(s)},A=(s,h)=>{let S=[...r],[m]=S.splice(s,1);S.splice(s+h,0,m),l(S)},k=s=>{let h=s.target?vo(i,s.target):Object.keys(i),S=s.when?Array.isArray(s.when)?s.when:[s.when]:[];return h.filter(m=>S.every(f=>Qa(i[m],f))).length};return de(rt,{title:"Style rules",children:[L("div",{className:"se-helperCard se-ruleIntro",children:"Restyle objects from their data while the app runs: a colour from a metric, grey when disabled, a pulse for an alarm. Set an object's metrics, status, and metadata in the Object tab to try a rule here. Later rules win over earlier ones."}),L("datalist",{id:"se-ruleMetrics",children:d.metrics.map(s=>L("option",{value:s},s))}),L("datalist",{id:"se-ruleMetadata",children:d.metadata.map(s=>L("option",{value:s},s))}),r.map((s,h)=>{let S=s.when?Array.isArray(s.when)?s.when:[s.when]:[],m=Qd(s.target),f=s.material??{},y=s.pulse===!0?{}:s.pulse||void 0,p=s.target?vo(i,s.target).length:Object.keys(i).length,g=a=>b(s.id,u=>({...u,when:a.length>0?a:void 0})),T=(a,u)=>g(S.map((z,D)=>D===a?u:z)),x=a=>b(s.id,u=>{let z={...u.material,...a};for(let D of Object.keys(z))z[D]===void 0&&delete z[D];return{...u,material:Object.keys(z).length>0?z:void 0}}),v=a=>b(s.id,u=>({...u,colorScale:a})),P=m==="group"?d.groups:m==="tag"?d.tags:m==="type"?d.types:[];return de(nc,{title:s.label||`Rule ${h+1}`,open:e===s.id,onToggle:()=>o(a=>a===s.id?null:s.id),actions:de(pr,{children:[L("button",{type:"button",className:"se-iconButton",onClick:()=>A(h,-1),disabled:h===0,"aria-label":"Move rule up",title:"Move up",children:L(qd,{size:14})}),L("button",{type:"button",className:"se-iconButton",onClick:()=>A(h,1),disabled:h===r.length-1,"aria-label":"Move rule down",title:"Move down",children:L(Yd,{size:14})}),L("button",{type:"button",className:"se-iconButton",onClick:()=>l(r.filter(a=>a.id!==s.id)),"aria-label":"Delete rule",title:"Delete rule",children:L(Xd,{size:14})})]}),children:[L(Qe,{label:"Name",children:L("input",{className:"se-textInput",value:s.label??"",placeholder:`Rule ${h+1}`,onChange:a=>b(s.id,u=>({...u,label:a.target.value}))})}),de("div",{className:"se-ruleGrid",children:[L(Qe,{label:"Applies to",children:L("select",{className:"se-select",value:m,onChange:a=>{let u=a.target.value,z=u==="object"?d.objects[0]?.id:u==="group"?d.groups[0]:u==="tag"?d.tags[0]:u==="type"?d.types[0]:"";b(s.id,D=>({...D,target:cr(u,z??"")}))},children:Object.keys(Eo).map(a=>L("option",{value:a,children:Eo[a]},a))})}),m!=="all"?L(Qe,{label:Eo[m],children:de("select",{className:"se-select",value:nn(s.target),onChange:a=>b(s.id,u=>({...u,target:cr(m,a.target.value)})),children:[m==="object"?d.objects.map(a=>L("option",{value:a.id,children:a.label},a.id)):P.map(a=>L("option",{value:a,children:a},a)),(m==="object"?d.objects.some(a=>a.id===nn(s.target)):P.includes(nn(s.target)))?null:L("option",{value:nn(s.target),children:nn(s.target)||"None in this model"})]})}):null]}),L("div",{className:"se-fieldLabel",children:"When"}),S.length===0?L("div",{className:"se-ruleHint",children:"Always applies."}):null,S.map((a,u)=>{let z=ec(a);return de("div",{className:"se-ruleCondition",children:[de("div",{className:"se-ruleConditionHeader",children:[L("select",{className:"se-select","aria-label":"Condition type",value:z,onChange:D=>T(u,br(D.target.value)),children:Object.keys(dr).map(D=>L("option",{value:D,children:dr[D]},D))}),L("button",{type:"button",className:"se-iconButton","aria-label":"Remove condition",title:"Remove condition",onClick:()=>g(S.filter((D,$)=>$!==u)),children:L(lr,{size:14})})]}),"metric"in a?de("div",{className:"se-ruleGrid se-ruleGrid--three",children:[L(Qe,{label:"Metric",children:L("input",{className:"se-textInput",list:"se-ruleMetrics",value:a.metric,placeholder:"temperature",onChange:D=>T(u,{...a,metric:D.target.value})})}),L(Qe,{label:"Above",children:L("input",{className:"se-numberInput",type:"number",value:a.above??"",placeholder:"any",onChange:D=>T(u,{...a,above:Do(D.target.value)})})}),L(Qe,{label:"Below",children:L("input",{className:"se-numberInput",type:"number",value:a.below??"",placeholder:"any",onChange:D=>T(u,{...a,below:Do(D.target.value)})})})]}):"status"in a?L("div",{className:"se-ruleStatuses",children:Hn.map(D=>{let $=[].concat(a.status).includes(D);return de("label",{className:"se-ruleStatus",children:[L("input",{type:"checkbox",className:"se-checkbox",checked:$,onChange:()=>{let ze=[].concat(a.status),gt=$?ze.filter(Mt=>Mt!==D):[...ze,D];T(u,{status:gt})}}),D]},D)})}):de("div",{className:"se-ruleGrid",children:[L(Qe,{label:"Key",children:L("input",{className:"se-textInput",list:"se-ruleMetadata",value:a.metadata,placeholder:"alarm.state",onChange:D=>T(u,{...a,metadata:D.target.value})})}),L(Qe,{label:"Equals",children:L("input",{className:"se-textInput",value:a.equals===null?"null":String(a.equals),placeholder:"fault",onChange:D=>T(u,{...a,equals:tc(D.target.value)})})})]})]},u)}),de("button",{type:"button",className:"se-animationButton",onClick:()=>g([...S,br("metric")]),children:[L(zo,{size:14})," Add condition"]}),L("div",{className:"se-fieldLabel",children:"Look"}),L(an,{label:"Colour",checked:f.baseColor!==void 0,color:f.baseColor,onToggle:a=>x({baseColor:a?"#9ca3af":void 0}),onColorChange:a=>x({baseColor:a})}),L(an,{label:"Opacity",checked:f.opacity!==void 0,onToggle:a=>x({opacity:a?.4:void 0})}),f.opacity!==void 0?L(N,{label:"Opacity",value:f.opacity,min:0,max:1,step:.05,formatValue:a=>`${Math.round(a*100)}%`,onChange:a=>x({opacity:a})}):null,L(an,{label:"Glow",checked:f.emissive!==void 0,color:f.emissive,onToggle:a=>x({emissive:a?"#ff3b30":void 0,emissiveIntensity:a?f.emissiveIntensity??1:void 0}),onColorChange:a=>x({emissive:a})}),L(an,{label:"Colour from a metric",checked:s.colorScale!==void 0,onToggle:a=>v(a?{...Zd,metric:d.metrics[0]??""}:void 0)}),s.colorScale?de("div",{className:"se-ruleCondition",children:[de("div",{className:"se-ruleGrid",children:[L(Qe,{label:"Metric",children:L("input",{className:"se-textInput",list:"se-ruleMetrics",value:s.colorScale.metric,placeholder:"temperature",onChange:a=>v({...s.colorScale,metric:a.target.value})})}),L(Qe,{label:"Sets",children:de("select",{className:"se-select",value:s.colorScale.channel??"baseColor",onChange:a=>v({...s.colorScale,channel:a.target.value}),children:[L("option",{value:"baseColor",children:"Colour"}),L("option",{value:"emissive",children:"Glow colour"})]})})]}),s.colorScale.stops.map(([a,u],z)=>{let D=$=>v({...s.colorScale,stops:s.colorScale.stops.map((ze,gt)=>gt===z?$:ze)});return de("div",{className:"se-ruleStop",children:[L("input",{className:"se-numberInput",type:"number","aria-label":"Stop value",value:a,onChange:$=>D([Do($.target.value)??0,u])}),L(Le,{label:`At ${a}`,value:u,onChange:$=>D([a,$])}),L("button",{type:"button",className:"se-iconButton","aria-label":"Remove stop",title:"Remove stop",disabled:s.colorScale.stops.length<=1,onClick:()=>v({...s.colorScale,stops:s.colorScale.stops.filter(($,ze)=>ze!==z)}),children:L(lr,{size:14})})]},z)}),de("button",{type:"button",className:"se-animationButton",onClick:()=>{let a=s.colorScale.stops,u=a[a.length-1];v({...s.colorScale,stops:[...a,[(u?.[0]??0)+10,u?.[1]??"#ffffff"]]})},children:[L(zo,{size:14})," Add stop"]})]}):null,L(an,{label:"Pulse",checked:y!==void 0,color:y?.color??"#ff3b30",onToggle:a=>b(s.id,u=>({...u,pulse:a?{color:"#ff3b30",speed:1}:void 0})),onColorChange:a=>b(s.id,u=>({...u,pulse:{...y,color:a}}))}),y?L(pr,{children:L(N,{label:"Pulses per second",value:y.speed??1,min:.2,max:4,step:.1,formatValue:a=>a.toFixed(1),onChange:a=>b(s.id,u=>({...u,pulse:{...y,speed:a}}))})}):null,de("div",{className:"se-ruleHint se-ruleMatches",children:["Matches ",k(s)," of ",p," ",p===1?"object":"objects"," right now."]})]},s.id)}),de("button",{type:"button",className:"se-animationButton",onClick:w,children:[L(zo,{size:14})," Add rule"]})]})}import{Box as ic,Clapperboard as rc,MessageSquareText as sc,Palette as lc,Sparkles as dc,Spotlight as cc,Video as bc}from"lucide-react";import{jsx as he,jsxs as gc}from"react/jsx-runtime";var pc=[{label:"General",icon:he(ic,{})},{label:"Lighting",icon:he(cc,{})},{label:"Animations",icon:he(rc,{})},{label:"Post Processing",icon:he(dc,{})},{label:"Annotations",icon:he(sc,{})},{label:"Cinematic",icon:he(bc,{})},{label:"Rules",icon:he(lc,{})}],gr={active:[],play:()=>{},pause:()=>{},stop:()=>{},setSpeed:()=>{},seek:()=>{}},uc=[],mc={};function Io({config:t,onChange:n,activeSubTab:i,onActiveSubTabChange:r,cameraState:e=null,onPreviewWaypoint:o,animationClipDetails:d=[],materialVariantGroups:l=uc,objectBindings:b=mc,animationPlayback:w=gr}){let[A,k]=oc("General"),s=i??A,h=w??gr,{tier:S}=Ze(),m=_e(S,"starter"),f=_e(S,"growth");ac(()=>{i!==void 0&&k(i)},[i]);let y=p=>{i===void 0&&k(p),r?.(p)};return gc("div",{className:"se-tabContent",children:[he("div",{className:"se-subTabRow",children:pc.map(p=>he("button",{type:"button",title:p.label,"aria-label":p.label,"aria-pressed":s===p.label,className:`se-subTab ${s===p.label?"se-subTab--active":""}`,onClick:()=>y(p.label),children:p.icon},p.label))}),s==="General"&&he(Po,{config:t,onChange:n,materialVariantGroups:l}),s==="Lighting"&&he(Ro,{config:t,onChange:n}),s==="Animations"&&(m?he(Mo,{config:t,onChange:n,clipDetails:d,active:h.active,play:h.play,pause:h.pause,stop:h.stop,setSpeed:h.setSpeed,seek:h.seek}):he(Ne,{requiredTier:"starter",feature:"Animation configuration"})),s==="Post Processing"&&(f?he(Bo,{config:t,onChange:n}):he(Ne,{requiredTier:"growth",feature:"Post-processing effects"})),s==="Annotations"&&(m?he(Oo,{config:t,onChange:n,cameraState:e,onPreviewView:o}):he(Ne,{requiredTier:"starter",feature:"Annotations"})),s==="Cinematic"&&(m?he(Lo,{config:t,onChange:n,cameraState:e,onPreviewWaypoint:o}):he(Ne,{requiredTier:"starter",feature:"Cinematic camera"})),s==="Rules"&&(m?he(jo,{config:t,onChange:n,objectBindings:b}):he(Ne,{requiredTier:"starter",feature:"Style rules"}))]})}import{ChevronDown as fr,Info as hr}from"lucide-react";import{jsx as Ae,jsxs as Pt}from"react/jsx-runtime";function xr({title:t,trailing:n,children:i,disabled:r,open:e,onToggle:o,tooltip:d}){let l=d?`${d}`:t;return Pt("div",{className:"bb-materialPanel",children:[Pt("button",{type:"button",className:"bb-materialPanelHeader",onClick:o,"aria-expanded":e,title:l,children:[Pt("div",{className:"bb-materialPanelTitleWrap",children:[Ae(fr,{size:14,className:`bb-materialPanelChevron ${e?"bb-materialPanelChevron--open":""}`}),Ae("span",{className:"bb-materialPanelTitle",children:t}),d?Ae("span",{className:"bb-materialPanelHelp",title:l,"aria-label":l,role:"img",onClick:b=>b.stopPropagation(),children:Ae(hr,{size:12})}):null]}),n?Ae("div",{onClick:b=>b.stopPropagation(),children:n}):null]}),e?Ae("div",{className:"bb-materialPanelBody",style:r?{opacity:.45,pointerEvents:"none"}:void 0,children:i}):null]})}function Pe({title:t,open:n,onToggle:i,trailing:r,children:e,tooltip:o}){let d=o?`${t}: ${o}`:t;return Pt("div",{className:"bb-section",children:[Pt("button",{type:"button",className:"bb-sectionHeaderButton",onClick:i,"aria-expanded":n,title:d,children:[Pt("span",{className:"bb-sectionHeaderMain",children:[Ae(fr,{size:15,className:`bb-sectionChevron ${n?"bb-sectionChevron--open":""}`}),Ae("h2",{className:"bb-sectionTitle",children:t}),o?Ae("span",{className:"bb-sectionHelp",title:d,"aria-label":d,role:"img",onClick:l=>l.stopPropagation(),children:Ae(hr,{size:13})}):null]}),r?Ae("span",{onClick:l=>l.stopPropagation(),children:r}):null]}),n?Ae("div",{className:"bb-sectionBody",children:e}):null]})}function vr({checked:t,onChange:n,label:i}){return Pt("label",{className:"se-switch","aria-label":i,children:[Ae("input",{type:"checkbox",checked:t,onChange:r=>n(r.target.checked)}),Ae("span",{className:"se-switchTrack",children:Ae("span",{className:"se-switchThumb"})})]})}import{useState as Cr}from"react";import{Trash2 as Nc}from"lucide-react";import{jsx as Fo}from"react/jsx-runtime";function je({panelKey:t,title:n,tooltip:i,toggleLabel:r,controls:e,children:o,requiredTier:d}){let{openMaterialPanels:l,materialPanelEnabled:b,onToggleMaterialPanel:w,onSetMaterialPanelState:A}=e,k=d?.locked??!1;return Fo(xr,{title:n,tooltip:i,disabled:k||!b[t],open:l[t],onToggle:()=>w(t),trailing:Fo(vr,{checked:!k&&b[t],onChange:k?()=>{}:s=>A(t,s),label:r??`Toggle ${n}`}),children:k&&d?Fo(Ne,{requiredTier:d.tier,feature:n}):o})}import{createContext as fc,useContext as hc,useRef as yr,useState as xc}from"react";import{HexColorInput as vc,HexColorPicker as yc}from"react-colorful";import{FileUp as wc,Minus as Cc,Plus as Sc}from"lucide-react";import{jsx as ae,jsxs as et}from"react/jsx-runtime";var Ho=fc(null);function we({label:t,value:n,placeholder:i,onChange:r}){let e=yr(null),o=hc(Ho);return et("div",{className:"bb-field bb-field--full",children:[ae("label",{className:"bb-label",children:t}),et("div",{className:"bb-fileField",title:o??void 0,children:[ae("input",{className:"bb-input bb-fileField-input",placeholder:i,value:n,disabled:!!o&&!n,onChange:d=>{let l=d.target.value;!l&&n&&qt(n),r(l)}}),ae("button",{type:"button",className:"bb-fileFieldButton",disabled:!!o,onClick:()=>e.current?.click(),"aria-label":`Select file for ${t}`,title:`Select file for ${t}`,children:ae(wc,{size:20})}),ae("input",{ref:e,type:"file",accept:"image/png,image/jpeg,image/webp,image/avif",className:"bb-hiddenInput",onChange:d=>{let l=d.target.files?.[0];if(!l)return;let b=An(l);n&&n!==b&&qt(n),yt(b,URL.createObjectURL(l)),r(b),d.target.value=""}})]})]})}function st({label:t,value:n,fallback:i="#ffffff",variant:r="swatch",onChange:e}){let[o,d]=xc(!1),l=n||i,b=yr(null);return et("div",{className:"bb-field",children:[ae("span",{className:"bb-label",children:t}),ae("div",{className:"se-fieldInline",children:ae("span",{ref:b,className:r==="input"?"bb-colorFieldAnchor":void 0,style:r==="swatch"?{display:"inline-flex"}:void 0,children:ae(vc,{prefixed:!0,className:r==="input"?"bb-input bb-colorInput":"se-swatch","aria-label":t,onClick:()=>d(w=>!w),style:{background:l,color:ut(l)},color:l,onChange:e})})}),o?ae(en,{anchorRef:b,onClose:()=>d(!1),children:ae(yc,{color:l,onChange:e})}):null]})}function rn({label:t,checked:n,onChange:i}){return et("label",{className:"bb-checkbox",children:[ae("input",{type:"checkbox",checked:n,onChange:r=>i(r.target.checked)}),t]})}function wr({label:t,value:n,min:i,max:r,step:e,placeholder:o,disabled:d,onChange:l}){return et("div",{className:"bb-field",children:[ae("label",{className:"bb-label",children:t}),ae("input",{className:"bb-input",type:"number",min:i,max:r,step:e,placeholder:o,disabled:d,value:n??"",onChange:b=>l(b.target.value===""?void 0:Number(b.target.value))})]})}function kc(t,n){let i=n<1?Math.ceil(-Math.log10(n)):0,r=10**Math.max(i,0);return Math.round(t*r)/r}function Vo({label:t,value:n,min:i,max:r,step:e=.01,disabled:o,onChange:d}){let l=n??0,b=A=>{let k=A;return i!==void 0&&(k=Math.max(i,k)),r!==void 0&&(k=Math.min(r,k)),k},w=A=>{d(b(kc(l+A*e,e)))};return et("div",{className:"bb-field",children:[ae("label",{className:"bb-label",children:t}),et("div",{className:"bb-numberStepper",children:[ae("button",{type:"button",className:"bb-numberStepper-btn",disabled:o,onClick:()=>w(-1),"aria-label":`Decrease ${t}`,title:`Decrease ${t}`,children:ae(Cc,{size:12})}),ae("input",{className:"bb-input bb-numberStepper-input",type:"number",min:i,max:r,step:e,disabled:o,value:l,onChange:A=>{A.target.value!==""&&d(b(Number(A.target.value)))}}),ae("button",{type:"button",className:"bb-numberStepper-btn",disabled:o,onClick:()=>w(1),"aria-label":`Increase ${t}`,title:`Increase ${t}`,children:ae(Sc,{size:12})})]})]})}function Vt({label:t,value:n,options:i,onChange:r}){return et("div",{className:"bb-field",children:[ae("label",{className:"bb-label",children:t}),ae("select",{className:"bb-select",value:n,onChange:e=>r(e.target.value),children:i.map(e=>ae("option",{value:e,children:e},e))})]})}function Z({label:t,value:n,min:i,max:r,step:e,onChange:o}){return et("div",{className:"bb-field bb-field--full",children:[ae("label",{className:"bb-label",children:t}),et("div",{className:"bb-sliderField",children:[ae("input",{className:`bb-slider ${n===void 0?"bb-slider--unset":""}`,type:"range",min:i,max:r,step:e,value:n??i,onChange:l=>o(Number(l.target.value))}),ae("input",{className:"bb-input bb-input--compact",type:"number",min:i,max:r,step:e,value:n??"",onChange:l=>o(l.target.value===""?void 0:Number(l.target.value))})]})]})}import{Fragment as kr,jsx as B,jsxs as me}from"react/jsx-runtime";var Sr="This object has no texture coordinates (UVs), so image maps can't be placed on it. Colors and the other settings work, and Decals can put an image on it.";function Nr({selectedItem:t,selectedMaterial:n,pbrWorkflow:i,onPbrWorkflowChange:r,openMaterialPanels:e,materialPanelEnabled:o,onToggleMaterialPanel:d,onSetMaterialPanelState:l,updateSelectedMaterial:b,setSelectedTexturePath:w,isTexturePositioningEnabled:A,onConfirmTexturePosition:k,takesImage:s=!0}){let h={openMaterialPanels:e,materialPanelEnabled:o,onToggleMaterialPanel:d,onSetMaterialPanelState:l},{tier:S}=Ze(),m=_e(S,"starter"),f={tier:"starter",locked:!m},[y,p]=Cr("roughness"),[g,T]=Cr("factor"),x=(a,u)=>{b(t,z=>{if(!z?.texture?.path)return z??{};let D=z.texture.offset??[0,0],$=[D[0],D[1]];return $[a]=u,{...z,texture:{...z.texture,offset:$}}})},v=a=>{b(t,u=>{if(!u?.texture?.path)return u??{};let z=(a%360+360)%360;return{...u,texture:{...u.texture,rotation:z*Math.PI/180}}})},P=()=>{w(t,"texture","")};return me(Ho.Provider,{value:s?null:Sr,children:[s?null:B("p",{className:"bb-note bb-materialNotice",children:Sr}),B(je,{panelKey:"pbr",title:"PBR Maps",tooltip:"Controls the base color and workflow used for physically based shading.",controls:h,children:m?me("div",{className:"bb-grid",children:[B(Vt,{label:"Workflow",value:i,options:["metalness","specular"],onChange:r}),B("div",{className:"bb-field bb-field--full",children:B("p",{className:"bb-note",style:{margin:0},children:i==="metalness"?"Metalness workflow maps directly to the underlying physical material.":"Specular workflow exposes the same physical material with non-metal specular controls; it does not switch to a separate spec/gloss shader."})}),B(we,{label:i==="specular"?"Albedo texture path":"Base color texture path",placeholder:"materials/oak-wood.jpg",value:n?.texture?.path??"",onChange:a=>w(t,"texture",a)}),n?.texture?.path?me("div",{className:"bb-field bb-field--full",children:[me("div",{className:"bb-fieldLabel",style:{display:"flex",alignItems:"center",justifyContent:"space-between"},children:[B("span",{className:"bb-label",children:"Texture position"}),me("button",{type:"button",className:"bb-button bb-button--ghost",onClick:P,title:"Remove the base color texture and its position offset",children:[B(Nc,{size:14,style:{marginRight:4,verticalAlign:"-2px"}}),"Remove texture"]})]}),me("div",{className:"bb-grid",style:{marginTop:6},children:[B(Vo,{label:"Offset X",value:n?.texture?.offset?.[0]??0,step:.01,onChange:a=>x(0,a)}),B(Vo,{label:"Offset Y",value:n?.texture?.offset?.[1]??0,step:.01,onChange:a=>x(1,a)})]}),B(Z,{label:"Rotation",value:((n?.texture?.rotation??0)*180/Math.PI%360+360)%360,min:0,max:360,step:1,onChange:a=>v(a??0)}),A?B("button",{type:"button",className:"bb-button bb-button--primary",style:{marginTop:8},onClick:k,title:"Confirm this texture position and exit positioning mode",children:"Done positioning"}):B("p",{className:"bb-note",style:{margin:"6px 0 0"},children:"Double-click the object in the preview to drag its texture directly (scroll to zoom), or edit its offset numerically once positioning."})]}):null,B(st,{label:i==="specular"?"Albedo color":"Base color",value:n?.baseColor??"#ffffff",onChange:a=>b(t,u=>({...u,baseColor:a}))}),i==="metalness"?me(kr,{children:[B(Z,{label:"Metalness",value:n?.metalness,min:0,max:1,step:.01,onChange:a=>b(t,u=>({...u,metalness:a}))}),B(we,{label:"Metalness map path",placeholder:"materials/body-metalness.jpg",value:n?.metalnessMap?.path??"",onChange:a=>w(t,"metalnessMap",a)})]}):me(kr,{children:[B(Z,{label:"Specular intensity",value:n?.specularIntensity,min:0,max:1,step:.01,onChange:a=>b(t,u=>({...u,specularIntensity:a}))}),B(st,{label:"Specular color",value:n?.specularColor??"#ffffff",onChange:a=>b(t,u=>({...u,specularColor:a}))}),B(we,{label:"Specular intensity map path",placeholder:"materials/body-specular-intensity.jpg",value:n?.specularIntensityMap?.path??"",onChange:a=>w(t,"specularIntensityMap",a)}),B(we,{label:"Specular color map path",placeholder:"materials/body-specular-color.jpg",value:n?.specularColorMap?.path??"",onChange:a=>w(t,"specularColorMap",a)})]}),B(Z,{label:"Specular F0 / reflectivity",value:n?.reflectivity,min:0,max:1,step:.01,onChange:a=>b(t,u=>({...u,reflectivity:a}))})]}):me("div",{className:"bb-grid",children:[B(st,{label:"Base color",value:n?.baseColor??"#ffffff",onChange:a=>b(t,u=>({...u,baseColor:a}))}),B(Z,{label:"Metalness",value:n?.metalness,min:0,max:1,step:.01,onChange:a=>b(t,u=>({...u,metalness:a}))}),B("div",{className:"bb-field bb-field--full",children:B(Ne,{requiredTier:"starter",feature:"Texture maps, the specular workflow, and reflectivity"})})]})}),B(je,{panelKey:"roughness",requiredTier:f,title:"Roughness / Glossiness",tooltip:"Adjusts how matte or shiny the surface appears.",toggleLabel:"Toggle Roughness and Glossiness",controls:h,children:me("div",{className:"bb-grid",children:[B(Vt,{label:"Mode",value:y,options:["roughness","glossiness"],onChange:p}),B("div",{className:"bb-field bb-field--full",children:B("p",{className:"bb-note",style:{margin:0},children:y==="roughness"?"Roughness: 0 is glossy, 1 is matte.":"Glossiness is the inverse of roughness (glossiness = 1 \u2212 roughness)"})}),y==="roughness"?B(Z,{label:"Roughness",value:n?.roughness,min:0,max:1,step:.01,onChange:a=>b(t,u=>({...u,roughness:a}))}):B(Z,{label:"Glossiness",value:n?.roughness===void 0?void 0:1-n.roughness,min:0,max:1,step:.01,onChange:a=>b(t,u=>({...u,roughness:a===void 0?void 0:1-a}))}),B(we,{label:y==="glossiness"?"Glossiness map path (applied as roughness)":"Roughness map path",placeholder:"materials/body-roughness.jpg",value:n?.roughnessMap?.path??"",onChange:a=>w(t,"roughnessMap",a)})]})}),B(je,{panelKey:"emission",requiredTier:f,title:"Emission",tooltip:"Makes the material self-illuminated with emissive color and intensity.",controls:h,children:me("div",{className:"bb-grid",children:[B(st,{label:"Emissive color",value:n?.emissive??"#000000",fallback:"#000000",onChange:a=>b(t,u=>({...u,emissive:a}))}),B(Z,{label:"Emissive intensity",value:n?.emissiveIntensity,min:0,max:10,step:.1,onChange:a=>b(t,u=>({...u,emissiveIntensity:a}))}),B(we,{label:"Emissive map path",placeholder:"materials/body-emissive.jpg",value:n?.emissiveMap?.path??"",onChange:a=>w(t,"emissiveMap",a)})]})}),B(je,{panelKey:"opacity",requiredTier:f,title:"Opacity",tooltip:"Controls transparency, alpha testing, and blending behavior.",controls:h,children:me("div",{className:"bb-grid",children:[B(Z,{label:"Opacity",value:n?.opacity,min:0,max:1,step:.01,onChange:a=>b(t,u=>({...u,opacity:a}))}),B(Z,{label:"Alpha test",value:n?.alphaTest,min:0,max:1,step:.01,onChange:a=>b(t,u=>({...u,alphaTest:a}))}),B(we,{label:"Alpha map path",placeholder:"materials/body-alpha.png",value:n?.alphaMap?.path??"",onChange:a=>w(t,"alphaMap",a)}),B(Vt,{label:"Blending mode",value:n?.blendingMode??"normal",options:mi,onChange:a=>b(t,u=>({...u,blendingMode:a}))}),me("div",{className:"bb-field",children:[B("label",{className:"bb-label",children:"Alpha hash"}),B("div",{className:"bb-checkboxRow",children:B(rn,{label:"Use alpha hash",checked:n?.alphaHash??!1,onChange:a=>b(t,u=>({...u,alphaHash:a}))})})]}),me("div",{className:"bb-field",children:[B("label",{className:"bb-label",children:"Dithering"}),B("div",{className:"bb-checkboxRow",children:B(rn,{label:"Use dithering",checked:n?.dithering??!1,onChange:a=>b(t,u=>({...u,dithering:a}))})})]})]})}),me(je,{panelKey:"normalBump",requiredTier:f,title:"Normal & Bump",tooltip:"Adds surface detail without changing the actual mesh shape.",toggleLabel:"Toggle Normal and Bump",controls:h,children:[me("div",{className:"bb-grid",children:[B(we,{label:"Normal map path",placeholder:"materials/body-normal.jpg",value:n?.normalMap?.path??"",onChange:a=>w(t,"normalMap",a)}),B(Z,{label:"Normal scale",value:n?.normalScale,min:0,max:5,step:.01,onChange:a=>b(t,u=>({...u,normalScale:a}))}),B(we,{label:"Bump map path",placeholder:"materials/body-bump.jpg",value:n?.bumpMap?.path??"",onChange:a=>w(t,"bumpMap",a)}),B(Z,{label:"Bump scale",value:n?.bumpScale,min:0,max:5,step:.01,onChange:a=>b(t,u=>({...u,bumpScale:a}))})]}),B("div",{className:"bb-checkboxRow",style:{marginTop:12},children:B(rn,{label:"Flip normal Y",checked:n?.flipNormalY??!1,onChange:a=>b(t,u=>({...u,flipNormalY:a}))})})]}),B(je,{panelKey:"displacement",requiredTier:f,title:"Displacement",tooltip:"Offsets geometry using a texture to create real surface height.",controls:h,children:me("div",{className:"bb-grid",children:[B(we,{label:"Displacement map path",placeholder:"materials/body-displacement.jpg",value:n?.displacementMap?.path??"",onChange:a=>w(t,"displacementMap",a)}),B(Z,{label:"Displacement scale",value:n?.displacementScale,min:-5,max:5,step:.01,onChange:a=>b(t,u=>({...u,displacementScale:a}))}),B(Z,{label:"Displacement bias",value:n?.displacementBias,min:-5,max:5,step:.01,onChange:a=>b(t,u=>({...u,displacementBias:a}))})]})}),B(je,{panelKey:"ao",requiredTier:f,title:"Ambient Occlusion",tooltip:"Darkens creases and contact areas to add depth.",controls:h,children:me("div",{className:"bb-grid",children:[B(we,{label:"AO map path",placeholder:"materials/body-ao.jpg",value:n?.aoMap?.path??"",onChange:a=>w(t,"aoMap",a)}),B(Z,{label:"AO intensity",value:n?.aoMapIntensity,min:0,max:5,step:.01,onChange:a=>b(t,u=>({...u,aoMapIntensity:a}))})]})}),me(je,{panelKey:"clearcoat",requiredTier:f,title:"Clearcoat",tooltip:"Adds a glossy protective layer on top of the base material.",controls:h,children:[me("div",{className:"bb-grid",children:[B(we,{label:"Clearcoat map path",placeholder:"materials/body-clearcoat.jpg",value:n?.clearcoatMap?.path??"",onChange:a=>w(t,"clearcoatMap",a)}),B(Z,{label:"Clearcoat",value:n?.clearcoat,min:0,max:1,step:.01,onChange:a=>b(t,u=>({...u,clearcoat:a}))}),B(we,{label:"Clearcoat roughness map path",placeholder:"materials/body-clearcoat-roughness.jpg",value:n?.clearcoatRoughnessMap?.path??"",onChange:a=>w(t,"clearcoatRoughnessMap",a)}),B(Z,{label:"Clearcoat roughness",value:n?.clearcoatRoughness,min:0,max:1,step:.01,onChange:a=>b(t,u=>({...u,clearcoatRoughness:a}))}),B(we,{label:"Clearcoat normal map path",placeholder:"materials/body-clearcoat-normal.jpg",value:n?.clearcoatNormalMap?.path??"",onChange:a=>w(t,"clearcoatNormalMap",a)}),B(Z,{label:"Clearcoat normal scale",value:n?.clearcoatNormalScale,min:0,max:5,step:.01,onChange:a=>b(t,u=>({...u,clearcoatNormalScale:a}))})]}),B("div",{className:"bb-checkboxRow",style:{marginTop:12},children:B(rn,{label:"Flip clearcoat normal Y",checked:n?.flipClearcoatNormalY??!1,onChange:a=>b(t,u=>({...u,flipClearcoatNormalY:a}))})})]}),B(je,{panelKey:"sheen",requiredTier:f,title:"Sheen",tooltip:"Adds a soft fabric-like sheen on grazing angles.",controls:h,children:me("div",{className:"bb-grid",children:[B(Z,{label:"Sheen",value:n?.sheen,min:0,max:1,step:.01,onChange:a=>b(t,u=>({...u,sheen:a}))}),B(st,{label:"Sheen color",value:n?.sheenColor??"#ffffff",onChange:a=>b(t,u=>({...u,sheenColor:a}))}),B(we,{label:"Sheen color map path",placeholder:"materials/body-sheen-color.jpg",value:n?.sheenColorMap?.path??"",onChange:a=>w(t,"sheenColorMap",a)}),B(Z,{label:"Sheen roughness",value:n?.sheenRoughness,min:0,max:1,step:.01,onChange:a=>b(t,u=>({...u,sheenRoughness:a}))}),B(we,{label:"Sheen roughness map path",placeholder:"materials/body-sheen-roughness.jpg",value:n?.sheenRoughnessMap?.path??"",onChange:a=>w(t,"sheenRoughnessMap",a)})]})}),B(je,{panelKey:"anisotropy",requiredTier:f,title:"Anisotropy",tooltip:"Stretches reflections in one direction for brushed or fiber-like surfaces.",controls:h,children:me("div",{className:"bb-grid",children:[B(Z,{label:"Intensity",value:n?.anisotropy,min:0,max:1,step:.01,onChange:a=>b(t,u=>({...u,anisotropy:a}))}),B(Vt,{label:"Tilt direction",value:g,options:["factor","texture"],onChange:T}),g==="factor"?B(Z,{label:"Rotation (rad)",value:n?.anisotropyRotation,min:0,max:6.28,step:.01,onChange:a=>b(t,u=>({...u,anisotropyRotation:a}))}):B(we,{label:"Anisotropy map path",placeholder:"materials/body-anisotropy.jpg",value:n?.anisotropyMap?.path??"",onChange:a=>w(t,"anisotropyMap",a)})]})}),B(je,{panelKey:"transmission",requiredTier:f,title:"Transmission & Volume",tooltip:"Controls glass-like transmission and how light travels through volume.",toggleLabel:"Toggle Transmission and Volume",controls:h,children:me("div",{className:"bb-grid",children:[B(Z,{label:"Transmission",value:n?.transmission,min:0,max:1,step:.01,onChange:a=>b(t,u=>({...u,transmission:a}))}),B(we,{label:"Transmission map path",placeholder:"materials/body-transmission.jpg",value:n?.transmissionMap?.path??"",onChange:a=>w(t,"transmissionMap",a)}),B(Z,{label:"Thickness",value:n?.thickness,min:0,max:5,step:.01,onChange:a=>b(t,u=>({...u,thickness:a}))}),B(we,{label:"Thickness map path",placeholder:"materials/body-thickness.jpg",value:n?.thicknessMap?.path??"",onChange:a=>w(t,"thicknessMap",a)}),B(st,{label:"Volume tint",value:n?.attenuationColor??"#ffffff",onChange:a=>b(t,u=>({...u,attenuationColor:a}))}),B(wr,{label:"Attenuation distance",value:n?.attenuationDistance,min:0,step:.01,placeholder:"Infinity when unset",onChange:a=>b(t,u=>({...u,attenuationDistance:a}))})]})}),B(je,{panelKey:"faces",requiredTier:f,title:"Faces Rendering",tooltip:"Chooses which side of the mesh renders and how backfaces are handled.",controls:h,children:B("div",{className:"bb-grid",children:B(Vt,{label:"Side",value:n?.side??"front",options:ui,onChange:a=>b(t,u=>({...u,side:a}))})})})]})}var Tr=[{id:"wood",label:"Wood",swatch:"#8b5a2b",material:{baseColor:"#8b5a2b",metalness:0,roughness:.75,reflectivity:.04}},{id:"brushed-metal",label:"Brushed Metal",swatch:"linear-gradient(135deg, #cfcfcf, #8a8a8a)",material:{baseColor:"#c8c8c8",metalness:1,roughness:.35}},{id:"chrome",label:"Polished Chrome",swatch:"linear-gradient(135deg, #ffffff, #9aa0a6)",material:{baseColor:"#e8e8e8",metalness:1,roughness:.05}},{id:"gold",label:"Gold",swatch:"linear-gradient(135deg, #ffe9a8, #c89b2c)",material:{baseColor:"#e6b325",metalness:1,roughness:.2}},{id:"copper",label:"Copper",swatch:"linear-gradient(135deg, #e3a576, #8a4a26)",material:{baseColor:"#b87333",metalness:1,roughness:.3}},{id:"glass",label:"Glass",swatch:"linear-gradient(135deg, rgba(255,255,255,0.9), rgba(180,210,230,0.4))",material:{baseColor:"#ffffff",metalness:0,roughness:.02,reflectivity:.5,opacity:1,transmission:1,thickness:.5,attenuationColor:"#ffffff",attenuationDistance:1}},{id:"frosted-glass",label:"Frosted Glass",swatch:"linear-gradient(135deg, rgba(255,255,255,0.85), rgba(210,225,235,0.6))",material:{baseColor:"#ffffff",metalness:0,roughness:.4,reflectivity:.3,opacity:1,transmission:.9,thickness:.5}},{id:"plastic-glossy",label:"Glossy Plastic",swatch:"#dadada",material:{baseColor:"#dadada",metalness:0,roughness:.25,reflectivity:.5,clearcoat:.3,clearcoatRoughness:.1}},{id:"plastic-matte",label:"Matte Plastic",swatch:"#9a9a9a",material:{baseColor:"#9a9a9a",metalness:0,roughness:.85,reflectivity:.04}},{id:"rubber",label:"Rubber",swatch:"#1a1a1a",material:{baseColor:"#1a1a1a",metalness:0,roughness:.9,reflectivity:.02}},{id:"fabric",label:"Fabric",swatch:"#9c8a6b",material:{baseColor:"#9c8a6b",metalness:0,roughness:.95,sheen:.4,sheenColor:"#ffffff",sheenRoughness:.6}},{id:"ceramic",label:"Ceramic",swatch:"#f5f5f0",material:{baseColor:"#f5f5f0",metalness:0,roughness:.15,clearcoat:.6,clearcoatRoughness:.1}},{id:"concrete",label:"Concrete",swatch:"#9b9b93",material:{baseColor:"#9b9b93",metalness:0,roughness:.95,reflectivity:.03}}];import{jsx as Go,jsxs as Tc}from"react/jsx-runtime";function Pr({disabled:t,onApply:n}){return Go("div",{className:"bb-presetGallery",children:Tr.map(i=>Tc("button",{type:"button",className:"bb-presetSwatch",disabled:t,title:`Apply ${i.label} preset`,onClick:()=>n(i.material),children:[Go("span",{className:"bb-presetSwatchColor",style:{background:i.swatch}}),Go("span",{className:"bb-presetSwatchLabel",children:i.label})]},i.id))})}import{jsx as Bt,jsxs as Uo}from"react/jsx-runtime";function Br({selectedItem:t,selectedBinding:n,open:i,onToggle:r,updateBinding:e,idError:o}){return Bt(Pe,{title:"Identity",open:i,onToggle:r,children:Uo("div",{className:"bb-grid",children:[Uo("div",{className:"bb-field bb-field--full",children:[Bt("label",{className:"bb-label",children:"Model Node ID"}),Bt("span",{className:"bb-note",children:"This is the exact mesh name from the imported model and stays locked."}),Bt("input",{className:"bb-input bb-readonly",value:n.modelObjectId,readOnly:!0})]}),Uo("div",{className:"bb-field bb-field--full",children:[Bt("label",{className:"bb-label",children:"ID"}),Bt("input",{className:`bb-input ${o?"bb-input--error":""}`,value:n.id,onChange:d=>e(t,l=>({...l,id:d.target.value}))}),o?Bt("span",{className:"bb-status bb-status--error",children:o}):null]})]})})}import{useEffect as Pc,useState as Rr}from"react";import{jsx as Be,jsxs as We}from"react/jsx-runtime";function Mr({selectedItem:t,selectedBinding:n,open:i,onToggle:r,updateBinding:e}){let[o,d]=Rr(n.group??""),[l,b]=Rr(n.tags?.join(", ")??"");Pc(()=>{d(n.group??""),b(n.tags?.join(", ")??"")},[t,n.group,n.tags]);let w=()=>{e(t,k=>({...k,group:o.trim()||void 0}))},A=()=>{let k=[...new Set(l.split(",").map(s=>s.trim()).filter(Boolean))];e(t,s=>({...s,tags:k.length>0?k:void 0}))};return We(Pe,{title:"Basics",open:i,onToggle:r,children:[We("div",{className:"bb-grid",children:[We("div",{className:"bb-field",children:[Be("label",{className:"bb-label",children:"Label"}),Be("input",{className:"bb-input",value:n.label??"",onChange:k=>e(t,s=>({...s,label:k.target.value}))})]}),We("div",{className:"bb-field",children:[Be("label",{className:"bb-label",children:"Type"}),Be("input",{className:"bb-input",list:"binding-type-suggestions",value:n.type??"other",onChange:k=>e(t,s=>({...s,type:k.target.value}))}),Be("datalist",{id:"binding-type-suggestions",children:sr.map(k=>Be("option",{value:k},k))})]}),We("div",{className:"bb-field",children:[Be("label",{className:"bb-label",children:"Status"}),Be("select",{className:"bb-select",value:n.status??"normal",onChange:k=>e(t,s=>({...s,status:k.target.value})),children:Hn.map(k=>Be("option",{value:k,children:k},k))})]}),We("div",{className:"bb-field",children:[Be("label",{className:"bb-label",children:"Group"}),Be("input",{className:"bb-input",placeholder:"paint",value:o,onChange:k=>d(k.target.value),onBlur:w,onKeyDown:k=>{k.key==="Enter"&&k.currentTarget.blur()}})]}),We("div",{className:"bb-field",children:[Be("label",{className:"bb-label",children:"Tags"}),Be("input",{className:"bb-input",placeholder:"exterior, configurable",value:l,onChange:k=>b(k.target.value),onBlur:A,onKeyDown:k=>{k.key==="Enter"&&k.currentTarget.blur()}})]})]}),We("div",{className:"bb-checkboxRow",style:{marginTop:12},children:[We("label",{className:"bb-checkbox",children:[Be("input",{type:"checkbox",checked:n.selectable??!1,onChange:k=>e(t,s=>({...s,selectable:k.target.checked}))}),"selectable"]}),We("label",{className:"bb-checkbox",children:[Be("input",{type:"checkbox",checked:n.hoverable??!1,onChange:k=>e(t,s=>({...s,hoverable:k.target.checked}))}),"hoverable"]}),We("label",{className:"bb-checkbox",children:[Be("input",{type:"checkbox",checked:n.visible??!1,onChange:k=>e(t,s=>({...s,visible:k.target.checked}))}),"visible"]})]})]})}import{useEffect as Bc,useState as Rc}from"react";import{Fragment as Ac,jsx as xe,jsxs as Ve}from"react/jsx-runtime";var Ar=mo.filter(t=>t.handling==="viewer"),Mc=mo.filter(t=>t.handling==="host");function Or({selectedItem:t,selectedBinding:n,open:i,onToggle:r,updateBinding:e,takesImage:o=!0}){let[d,l]=Rc(new Set);Bc(()=>{l(new Set)},[t]);let b=n.actions??[],w=(s,h)=>e(t,S=>({...S,actions:(S.actions??[]).map((m,f)=>f===s?h(m):m)})),A=s=>{e(t,h=>({...h,actions:(h.actions??[]).filter((S,m)=>m!==s)})),l(h=>{let S=new Set;return h.forEach(m=>{m<s?S.add(m):m>s&&S.add(m-1)}),S})},k=(s,h)=>l(S=>{let m=new Set(S);return h?m.add(s):m.delete(s),m});return Ve(Pe,{title:"Actions",open:i,onToggle:r,children:[xe("div",{className:"bb-actionList",children:b.map((s,h)=>{let S=Mn(s.id),m=d.has(h)||!S,f=s.id.trim(),y=S?null:za(s.id),p=f.length>0&&b.some((g,T)=>T!==h&&g.id.trim()===f);return Ve("div",{className:"bb-actionCard",children:[Ve("div",{className:"bb-actionCardHeader",children:[Ve("div",{className:"bb-actionCardTitle",children:["Action ",h+1]}),xe("div",{className:"bb-actionCardMeta",children:s.type})]}),Ve("div",{className:"bb-actionGrid",children:[Ve("div",{className:"bb-field",children:[xe("label",{className:"bb-label",children:"Action ID"}),Ve("select",{className:"bb-select",value:m?Rn:s.id,onChange:g=>{let T=g.target.value;if(T===Rn){k(h,!0);return}k(h,!1);let x=Mn(T);w(h,v=>({...v,id:T,label:x&&go(v.label)?x.label:v.label}))},children:[xe("optgroup",{label:"Handled by the viewer",children:Ar.map(g=>xe("option",{value:g.id,children:g.id},g.id))}),xe("optgroup",{label:"Handled by your app",children:Mc.map(g=>xe("option",{value:g.id,children:g.id},g.id))}),xe("option",{value:Rn,children:"Custom\u2026"})]})]}),m?Ve("div",{className:"bb-field",children:[xe("label",{className:"bb-label",children:"Custom action ID"}),xe("input",{className:"bb-input",value:s.id,placeholder:"open-datasheet",onChange:g=>{k(h,!0),w(h,T=>({...T,id:g.target.value}))}})]}):null,Ve("div",{className:"bb-field",children:[xe("label",{className:"bb-label",children:"Label"}),xe("input",{className:"bb-input",value:s.label,onChange:g=>w(h,T=>({...T,label:g.target.value}))})]}),S?.id==="change-material"&&!o?xe("span",{className:"bb-note",style:{color:"#fcd34d"},children:"This object has no texture coordinates, so an image picked here can't be placed on it, and the viewer says so. Change Color and Add Image work."}):S?xe("span",{className:"bb-note",children:S.description}):f.length===0?xe("span",{className:"bb-note",style:{color:"#fca5a5"},children:"An action ID is required, the button renders but can never be identified in onAction."}):Ve("span",{className:"bb-note",style:{color:"#fcd34d"},children:["Unrecognised ID, the viewer has no built-in behavior for it. Add declarative effects and execute them with useViewerActions, or handle it in onAction.",y?Ve(Ac,{children:[" Did you mean ",xe("button",{type:"button",className:"bb-linkButton",onClick:()=>{k(h,!1);let g=Mn(y);w(h,T=>({...T,id:y,label:g&&go(T.label)?g.label:T.label}))},children:y}),"?"]}):null]}),s.effects?.length?Ve("span",{className:"bb-note",children:[s.effects.length," declarative effect",s.effects.length===1?"":"s",", execute with useViewerActions."]}):null,p?xe("span",{className:"bb-note",style:{color:"#fcd34d"},children:"Another action on this binding uses the same ID, they will render as two identical buttons."}):null]}),xe("div",{className:"bb-actionFooter",children:xe("button",{type:"button",className:"bb-button bb-button--ghost bb-actionRemove",onClick:()=>A(h),children:"Remove Action"})})]},h)})}),xe("div",{style:{marginTop:10},children:xe("button",{type:"button",className:"bb-button",onClick:()=>{let s=Ar.find(h=>!b.some(S=>S.id===h.id));e(t,h=>({...h,actions:[...h.actions??[],{id:s?.id??"",label:s?.label??"New Action",type:"command"}]})),s||k(b.length,!0)},children:"Add Action"})})]})}import{useRef as Oc}from"react";import{ImagePlus as Lc,Move as zc,Trash2 as Ec,Type as Dc}from"lucide-react";import{Fragment as zr,jsx as fe,jsxs as Ye}from"react/jsx-runtime";var Lr=()=>`decal-${Date.now().toString(36)}-${Math.random().toString(36).slice(2,8)}`;function Er({selectedItem:t,selectedBinding:n,open:i,onToggle:r,updateBinding:e,placement:o,onPlacementChange:d,defaultSize:l,onImageFile:b,onNudge:w}){let{tier:A}=Ze(),k=Oc(null),s=n.decals??[],h=o?.nodeKey===t?o:null,S=y=>e(t,p=>({...p,decals:y.length>0?y:void 0})),m=(y,p)=>S(s.map(g=>g.id===y?{...g,...p}:g)),f=y=>{y.image&&qt(y.image),h?.decal.id===y.id&&d(null),S(s.filter(p=>p.id!==y.id))};return fe(Pe,{title:"Decals",open:i,onToggle:r,tooltip:"Print a logo, image, or text on the selected object's surface.",children:_e(A,"starter")?Ye(zr,{children:[Ye("div",{className:"bb-decalActions",children:[Ye("button",{type:"button",className:"bb-button bb-button--ghost",onClick:()=>k.current?.click(),children:[fe(Lc,{size:15})," Add image"]}),Ye("button",{type:"button",className:"bb-button bb-button--ghost",onClick:()=>d({nodeKey:t,decal:{id:Lr(),text:"Your text",color:"#ffffff",size:l}}),children:[fe(Dc,{size:15})," Add text"]}),fe("input",{ref:k,type:"file",accept:"image/png,image/jpeg,image/webp,image/avif,image/svg+xml",className:"bb-hiddenInput",onChange:y=>{let p=y.target.files?.[0];if(y.target.value="",!p)return;let g=An(p);yt(g,URL.createObjectURL(p)),b?.(g,p),d({nodeKey:t,decal:{id:Lr(),image:g,size:l}})}})]}),s.length===0&&!h?fe("div",{className:"bb-decalEmpty",children:"No decals on this object yet."}):null,s.map(y=>Ye("div",{className:"bb-decalCard",children:[Ye("div",{className:"bb-decalCardHeader",children:[fe("span",{className:"bb-decalKind",children:y.image?"Image":"Text"}),fe("span",{className:"bb-decalName",title:y.image??y.text,children:y.image??y.text}),fe("button",{type:"button",className:"bb-iconButton",title:"Move: drag the decal in the preview","aria-label":"Move decal","aria-pressed":h?.decal.id===y.id,onClick:()=>{let{position:p,normal:g,...T}=y;d(h?.decal.id===y.id?null:{nodeKey:t,decal:T,moving:!0})},children:fe(zc,{size:15})}),fe("button",{type:"button",className:"bb-iconButton bb-iconButton--danger",title:"Delete decal","aria-label":"Delete decal",onClick:()=>f(y),children:fe(Ec,{size:15})})]}),fe(Ea,{onNudge:p=>w(y.id,p)}),Ye("div",{className:"bb-grid",children:[y.image?null:Ye(zr,{children:[Ye("div",{className:"bb-field bb-field--full",children:[fe("label",{className:"bb-label",children:"Text"}),fe("input",{className:"bb-input",value:y.text??"",onChange:p=>m(y.id,{text:p.target.value})})]}),fe(st,{label:"Colour",variant:"input",value:y.color??"#ffffff",onChange:p=>m(y.id,{color:p})}),Ye("div",{className:"bb-field",children:[fe("label",{className:"bb-label",children:"Weight"}),Ye("select",{className:"bb-input bb-decalWeight",value:y.fontWeight??"bold",onChange:p=>m(y.id,{fontWeight:p.target.value}),children:[fe("option",{value:"bold",children:"Bold"}),fe("option",{value:"normal",children:"Regular"})]})]})]}),fe(Z,{label:"Size",value:Number(y.size.toFixed(4)),min:Number((l/20).toPrecision(2)),max:Number((l*6).toPrecision(2)),step:Number((l/50).toPrecision(1)),onChange:p=>p!==void 0&&p>0&&m(y.id,{size:p})}),fe(Z,{label:"Rotation (\xB0)",value:Math.round((y.rotation??0)*180/Math.PI),min:-180,max:180,step:1,onChange:p=>m(y.id,{rotation:(p??0)*Math.PI/180})}),fe(Z,{label:"Opacity",value:y.opacity??1,min:0,max:1,step:.05,onChange:p=>m(y.id,{opacity:p??1})})]})]},y.id))]}):fe(Ne,{requiredTier:"starter",feature:"Decals"})})}import{MapPin as jc,Trash2 as Ic}from"lucide-react";import{Fragment as Fc,jsx as Ge,jsxs as Ie}from"react/jsx-runtime";function Dr({selectedBinding:t,open:n,onToggle:i,cameraState:r,formattedCameraState:e,savedCameraPosition:o,onSaveCameraPosition:d,onGoToSavedCamera:l,onClearSavedCamera:b,onResetView:w,onFitScene:A}){return Ie(Pe,{title:"Camera Position",open:n,onToggle:i,children:[Ie("div",{className:"se-waypointCard bb-cameraWaypoint",children:[Ge("span",{className:"bb-cameraLiveBadge",children:"LIVE"}),Ie("div",{className:"se-waypointBody",children:[Ge("div",{className:"bb-cameraWaypointLabel",children:"Current view"}),r?Ie(Fc,{children:[Ie("div",{className:"se-waypointCoords",children:["pos ",e?.position]}),Ie("div",{className:"se-waypointCoords",children:["look ",e?.target]})]}):Ge("div",{className:"se-waypointCoords",children:"Move the camera to see live position"})]})]}),Ie("div",{className:"bb-cameraControls bb-cameraControls--centered",children:[Ge("button",{type:"button",className:"bb-button bb-button--primary",onClick:d,disabled:!r,children:"Save"}),Ge("button",{type:"button",className:"bb-button bb-button--ghost",onClick:w,children:"Reset View"}),Ge("button",{type:"button",className:"bb-button bb-button--ghost",onClick:A,children:"Fit Scene"})]}),o?.position&&o?.target&&Ie("div",{className:"se-waypointCard bb-cameraWaypoint",children:[Ge("span",{className:"bb-cameraSavedBadge",children:"SAVED"}),Ie("div",{className:"se-waypointBody",children:[Ie("div",{className:"bb-cameraWaypointLabel",children:["For ",t.label]}),Ie("div",{className:"se-waypointCoords",children:["pos [",o.position.map(k=>k.toFixed(1)).join(", "),"]"]}),Ie("div",{className:"se-waypointCoords",children:["look [",o.target.map(k=>k.toFixed(1)).join(", "),"]"]})]}),Ie("div",{className:"se-waypointActions",children:[Ge("button",{className:"se-waypointAction",onClick:l,title:"Fly camera to the saved position",children:Ge(jc,{size:15})}),Ge("button",{className:"se-waypointAction se-waypointAction--delete",onClick:b,title:"Delete saved position",children:Ge(Ic,{size:15})})]})]}),Ge("span",{className:"bb-note",children:'Tip: Position the camera how you want, then click "Save" to store this position for the selected object. The camera position updates in real-time as you navigate.'})]})}import{useLayoutEffect as Hc,useRef as Vc,useState as Gc}from"react";import{Move3d as Uc,RotateCcw as $c}from"lucide-react";import{jsx as ce,jsxs as qe}from"react/jsx-runtime";var jr=["X","Y","Z"];var Kc=.1;function $o(t){let n=t%360;return n<0?n+360:n}function Ir(t){return $o(t*180/Math.PI)}function Fr(t){return t*Math.PI/180}function _c(t,n,i){let r=[...t],e=Ir(t[n]);return r[n]=Fr($o(e+i)),r}function Hr({value:t,min:n=-1/0,max:i=1/0,step:r=.1,disabled:e=!1,onChange:o,formatValue:d=w=>Number(w.toFixed(3)),ariaLabel:l,className:b}){let w=d(t),[A,k]=Gc(String(w)),s=Vc(!1);return Hc(()=>{s.current||k(String(w))},[w]),ce("input",{type:"number",className:b,step:r,min:n===-1/0?void 0:n,max:i===1/0?void 0:i,value:A,disabled:e,"aria-label":l,onFocus:()=>{s.current=!0},onChange:h=>{let S=h.target.value;if(k(S),S===""||S==="-")return;let m=Number(S);if(Number.isFinite(m)){let f=Math.max(n,Math.min(i,m));o(f)}},onBlur:()=>{s.current=!1,k(String(d(t)))}})}function Wc({value:t,min:n=-1/0,max:i=1/0,step:r=.1,disabled:e=!1,onChange:o,formatValue:d=b=>Number(b.toFixed(3)),label:l}){return ce("div",{className:"bb-transformAxesGrid",children:jr.map((b,w)=>qe("div",{className:"bb-transformAxis",children:[ce("span",{className:"se-axisStepperLabel bb-transformAxisLabel",children:b}),ce("div",{className:"bb-transformAxisControl",children:ce(Hr,{className:"se-numberInput bb-transformNumberInput",step:r,min:n,max:i,value:t[w],disabled:e,formatValue:d,ariaLabel:`${b} ${l?.toLowerCase()||""}`,onChange:A=>{let k=[...t];k[w]=A,o(k)}})})]},b))})}function Vr({selectedItem:t,selectedBinding:n,open:i,onToggle:r,updateBinding:e,moveModeEnabled:o,onToggleMoveMode:d,transformSpace:l,onTransformSpaceChange:b,originalTransform:w}){let A=n.transform?.rotation??w?.rotation??[0,0,0],k=n.transform?.position??w?.position??[0,0,0],s=(p,g)=>{let T=p.transform?.rotation??w?.rotation??[0,0,0],x=p.transform?.position??w?.position??[0,0,0],v=p.transform?.scale??w?.scale??[1,1,1],P=w?.pivotLocal??[0,0,0],a=si(x,T,g,v,P,w?.rotationOrder??"XYZ");return{...p,transform:{...p.transform,position:a,rotation:g}}},h=(p,g)=>{t&&e(t,T=>{let x=T.transform?.rotation??w?.rotation??[0,0,0],v=_c(x,p,g);return s(T,v)})},S=(p,g)=>{t&&e(t,T=>{let v=[...T.transform?.rotation??w?.rotation??[0,0,0]];return v[p]=Fr($o(g)),s(T,v)})},m=(p,g)=>{t&&e(t,T=>{let v=[...T.transform?.position??w?.position??[0,0,0]];return v[p]=g,{...T,transform:{...T.transform,position:v}}})},f=(p,g)=>{t&&m(p,k[p]+g)},y=()=>{!t||!w||e(t,p=>{let g={...p.transform};return delete g.position,delete g.rotation,{...p,transform:Object.keys(g).length>0?g:void 0}})};return qe(Pe,{title:"Move & Rotate",open:i,onToggle:r,tooltip:"Enable the transform gizmo to move or rotate the selected mesh on any axis. Rotation uses the object's visible center while exported position and rotation remain local GLTF transforms.",children:[qe("div",{className:"se-field",children:[qe("div",{className:"se-fieldLabel",children:[qe("span",{children:[ce(Uc,{size:14,style:{marginRight:6,verticalAlign:"-2px"}}),"Transform gizmo"]}),qe("label",{className:"se-switch","aria-label":"Toggle move mode",children:[ce("input",{type:"checkbox",checked:o,onChange:p=>d(p.target.checked)}),ce("span",{className:"se-switchTrack",children:ce("span",{className:"se-switchThumb"})})]})]}),ce("span",{className:"bb-note",children:"Select a mesh \xB7 drag the colored arrows or planes to move"})]}),qe("div",{className:"se-field",style:{marginTop:10},children:[ce("div",{className:"se-fieldLabel",children:ce("span",{children:"Axis space"})}),ce("div",{className:"se-segmentedControl",children:["world","local"].map(p=>ce("button",{type:"button",className:`se-segmentedOption ${l===p?"se-segmentedOption--active":""}`,onClick:()=>b(p),children:p},p))})]}),qe("div",{className:"se-field",style:{marginTop:10},children:[ce("div",{className:"se-fieldLabel",children:ce("span",{children:"Rotation (degrees)"})}),ce("div",{className:"bb-transformAxesGrid",children:jr.map((p,g)=>{let T=Math.round(Ir(A[g]));return qe("div",{className:"bb-transformAxis",children:[ce("span",{className:"se-axisStepperLabel bb-transformAxisLabel",children:p}),ce("div",{className:"bb-transformAxisControl",children:ce(Hr,{className:"se-numberInput bb-transformNumberInput",step:1,min:0,max:359,value:T,disabled:!t,formatValue:x=>Math.round(x),ariaLabel:`${p} rotation in degrees`,onChange:x=>S(g,x)})})]},p)})})]}),qe("div",{className:"se-field",style:{marginTop:10},children:[ce("div",{className:"se-fieldLabel",children:ce("span",{children:"Position"})}),ce(Wc,{value:k,min:-1/0,max:1/0,step:Kc,disabled:!t,label:"position",onChange:p=>{t&&e(t,g=>({...g,transform:{...g.transform,position:p}}))}})]}),qe("button",{type:"button",className:"bb-button bb-button--ghost",style:{marginTop:10,display:"inline-flex",alignItems:"center",gap:6},disabled:!t||!w,onClick:y,title:"Restore this node's position and rotation to what they were in the original model",children:[ce($c,{size:14}),"Restore original position & rotation"]})]})}import{memo as Yc,useMemo as Gr,useState as qc}from"react";import{Focus as Jc}from"lucide-react";import{Fragment as Zc,jsx as lt,jsxs as dt}from"react/jsx-runtime";var Ur=Yc(Xc);function Xc({bindings:t,selectedItem:n,onSelect:i,onHover:r,isOpen:e=!0,onToggle:o,isolatedItem:d=null,onIsolate:l}){let[b,w]=qc(""),A=Gr(()=>Object.keys(t),[t]),k=Gr(()=>{let s=b.trim().toLowerCase();return s?A.filter(h=>{let S=t[h];return h.toLowerCase().includes(s)||S.label?.toLowerCase().includes(s)||(S.type??"other").toLowerCase().includes(s)}):A},[t,A,b]);return dt("aside",{className:`bb-sidebar bb-sidebar--right ${e?"":"bb-sidebar--collapsed"}`,children:[dt("div",{className:"bb-header bb-header--sidebar",children:[!e&<("button",{type:"button",className:"bb-sidebarToggle",onClick:()=>o?.(!0),"aria-label":"Open scene nodes sidebar",title:"Open scene nodes",children:"\u2190"}),e&&dt(Zc,{children:[dt("div",{children:[lt("div",{className:"bb-sectionKicker",children:"Scene Nodes"}),dt("div",{className:"bb-sectionHeading",children:[k.length," visible entries"]})]}),lt("button",{type:"button",className:"bb-sidebarToggle",onClick:()=>o?.(!1),"aria-label":"Close scene nodes sidebar",title:"Close scene nodes",children:"\u2192"})]})]}),e&&dt("section",{className:"bb-nodeList",children:[lt("div",{className:"bb-search",children:lt("input",{className:"bb-input",placeholder:"Search nodes, labels, or types",value:b,onChange:s=>w(s.target.value)})}),lt("div",{className:"bb-nodeItems",children:k.map(s=>{let h=t[s],S=s===n,m=s===d;return dt("div",{className:`bb-nodeRow ${d&&!m?"bb-nodeRow--setAside":""}`,children:[dt("button",{type:"button",className:`bb-nodeButton ${S?"bb-nodeButton--active":""}`,onClick:()=>i(s),onMouseEnter:()=>r?.(s),onMouseLeave:()=>r?.(null),children:[lt("span",{className:"bb-nodeName",children:s}),dt("span",{className:"bb-nodeMeta",children:[h.type??"other",h.label===ni(s)?"":h.label||"\xB7 Untitled"]})]}),l?lt("button",{type:"button",className:`bb-nodeIsolate ${m?"bb-nodeIsolate--active":""}`,onClick:()=>l(m?null:s),title:m?"Show all":"Isolate in the preview","aria-label":`${m?"Show all":"Isolate"} ${s}`,"aria-pressed":m,children:lt(Jc,{size:14,"aria-hidden":"true"})}):null]},s)})})]})]})}import{jsx as Vn,jsxs as $r}from"react/jsx-runtime";function Ko({title:t,label:n,open:i,onToggle:r,draft:e,error:o,example:d,onDraftChange:l,onCommit:b}){return Vn(Pe,{title:t,open:i,onToggle:r,children:$r("div",{className:"bb-field",children:[Vn("label",{className:"bb-label",children:n}),Vn("textarea",{className:"bb-textarea",value:e,onChange:w=>l(w.target.value),onBlur:b}),o?Vn("span",{className:"bb-status bb-status--error",children:o}):$r("span",{className:"bb-note",children:["Use a JSON object like ",d,"."]})]})})}function Kr(t,n){let i=new Map(t.animations.clips.map(o=>[o.sourceName,o])),r=n.map(({sourceName:o})=>i.get(o)??{sourceName:o,displayName:o,hidden:!1,loopMode:"repeat",speed:1}),e=t.animations.autoplayClip&&r.some(o=>o.sourceName===t.animations.autoplayClip&&!o.hidden)?t.animations.autoplayClip:null;return{clips:r,autoplayClip:e}}function Gn(t){return t!==null&&typeof t=="object"&&!Array.isArray(t)}function sn(t,n){if(!Gn(t)||!Gn(n))return n??t;let i={...t};for(let[r,e]of Object.entries(n)){let o=i[r];i[r]=Gn(o)&&Gn(e)?sn(o,e):e}return i}import{useCallback as ln,useReducer as Qc,useRef as eb}from"react";var tb=100;function nb(t,n){switch(n.type){case"set":{let i=typeof n.updater=="function"?n.updater(t.present):n.updater;if(i===t.present)return t;let r=n.track?t.edits+1:t.edits,e=!n.track&&t.edits===0?i:t.baseline;return n.coalesce?{...t,present:i,future:[],edits:r,baseline:e}:{past:[...t.past,t.present].slice(-tb),present:i,future:[],edits:r,baseline:e}}case"undo":{if(t.past.length===0)return t;let i=t.past[t.past.length-1];return{...t,past:t.past.slice(0,-1),present:i,future:[t.present,...t.future],edits:t.edits+1}}case"redo":{if(t.future.length===0)return t;let[i,...r]=t.future;return{...t,past:[...t.past,t.present],present:i,future:r,edits:t.edits+1}}case"reset":return{past:[],present:n.value,future:[],edits:n.track?t.edits+1:0,baseline:n.track?t.baseline:n.value}}}function _o(t,n=600){let[i,r]=Qc(nb,{past:[],present:t,future:[],edits:0,baseline:t}),e=eb(0),o=ln(A=>{let k=Date.now(),s=k-e.current<n;e.current=k,r({type:"set",updater:A,coalesce:s,track:!0})},[n]),d=ln(A=>{let k=Date.now()-e.current<n;r({type:"set",updater:A,coalesce:k,track:!1})},[n]),l=ln(()=>{e.current=0,r({type:"undo"})},[]),b=ln(()=>{e.current=0,r({type:"redo"})},[]),w=ln((A,k)=>{e.current=0,r({type:"reset",value:A,track:k?.asEdit??!1})},[]);return{value:i.present,setValue:o,setValueUntracked:d,undo:l,redo:b,reset:w,canUndo:i.past.length>0,canRedo:i.future.length>0,edits:i.edits,baseline:i.baseline}}import{useCallback as ob,useEffect as Wo}from"react";var ab=500;function _r({autosaveEnabled:t,hasEdits:n,modelUrl:i,bindings:r,sceneConfig:e,onTextureUpload:o,modelSourceRef:d,pendingLoadRef:l,storedModelKeyRef:b,pendingAutosaveRef:w,autosaveFailureShownRef:A,setStatusMessage:k,setStatusTone:s}){let h=ob(async(S,m)=>{if(o)return o(S,m);let f=URL.createObjectURL(S);if(t)try{await In(f,S)}catch(y){console.warn("[BindingBuilder] Could not store texture file for autosave:",y)}return f},[o,t]);return Wo(()=>{if(!t||!n||!i)return;let S=d.current;if(!S)return;let m=()=>{if(w.current===m&&(w.current=null),l.current)return;let{model:y,file:p}=S,g=y.kind==="file"&&b.current!==y.key?p:void 0;wi({model:y,bindings:r,sceneConfig:e},g).then(()=>{b.current=y.kind==="file"?y.key:null,A.current=!1}).catch(T=>{console.warn("[BindingBuilder] Autosave failed:",T),!A.current&&(A.current=!0,k("Couldn't autosave this session \u2014 the browser refused to store it, possibly for lack of space. Export your work to keep it."),s("error"))})};w.current=m;let f=window.setTimeout(m,ab);return()=>window.clearTimeout(f)},[t,n,i,r,e]),Wo(()=>{if(!t)return;let S=()=>w.current?.(),m=()=>{document.visibilityState==="hidden"&&S()};return window.addEventListener("pagehide",S),document.addEventListener("visibilitychange",m),()=>{window.removeEventListener("pagehide",S),document.removeEventListener("visibilitychange",m),S()}},[t]),Wo(()=>{if(!t||!i||!n)return;let S=m=>{w.current?.(),m.preventDefault(),m.returnValue=""};return window.addEventListener("beforeunload",S),()=>window.removeEventListener("beforeunload",S)},[t,i,n]),{handleTextureUpload:h}}import{ListRestart as pb,Redo2 as ub,Undo2 as mb,Upload as gb}from"lucide-react";import{useEffect as ib,useRef as rb,useState as sb}from"react";import{ChevronDown as lb,Download as db,FileCode2 as cb,FileJson as bb}from"lucide-react";import{jsx as Un,jsxs as dn}from"react/jsx-runtime";function Wr({disabled:t,exporting:n,onExportJson:i,onExportTs:r}){let[e,o]=sb(!1),d=rb(null);return ib(()=>{if(!e)return;let l=b=>{d.current?.contains(b.target)||o(!1)};return window.addEventListener("pointerdown",l),()=>window.removeEventListener("pointerdown",l)},[e]),dn("div",{className:"bb-exportMenuWrapper",ref:d,children:[dn("button",{type:"button",className:"bb-button bb-button--ghost",disabled:t||n,onClick:()=>o(l=>!l),title:"Export",children:[Un(db,{size:14}),n?"Exporting\u2026":"Export",Un(lb,{size:12})]}),e&&dn("div",{className:"bb-exportMenu",children:[dn("button",{type:"button",className:"bb-exportMenuItem",onClick:()=>{o(!1),i()},children:[Un(bb,{size:14}),"JSON"]}),dn("button",{type:"button",className:"bb-exportMenuItem",onClick:()=>{o(!1),r()},children:[Un(cb,{size:14}),"TypeScript"]})]})]})}import{jsx as tt,jsxs as Yo}from"react/jsx-runtime";function qo({canUndo:t,canRedo:n,onUndo:i,onRedo:r,onReset:e,resetDisabled:o,resetTitle:d,onImport:l,importDisabled:b,importTitle:w,exportDisabled:A,exporting:k,onExportJson:s,onExportTs:h}){return Yo("div",{className:"bb-toolbar",children:[Yo("div",{className:"bb-toolbarGroup",children:[tt("button",{type:"button",className:"bb-iconButton",disabled:!t,onClick:i,title:"Undo (Cmd/Ctrl+Z)",children:tt(mb,{size:16})}),tt("button",{type:"button",className:"bb-iconButton",disabled:o,onClick:e,title:d,children:tt(pb,{size:16})}),tt("button",{type:"button",className:"bb-iconButton",disabled:!n,onClick:r,title:"Redo (Cmd/Ctrl+Shift+Z)",children:tt(ub,{size:16})})]}),tt("div",{className:"bb-toolbarDivider"}),Yo("button",{type:"button",className:"bb-button bb-button--ghost",disabled:b,onClick:l,title:w,children:[tt(gb,{size:14}),"Import"]}),tt("div",{className:"bb-toolbarDivider"}),tt(Wr,{disabled:A,exporting:k,onExportJson:s,onExportTs:h})]})}import{AlertTriangle as fb,History as hb,X as Yr}from"lucide-react";import{jsx as Te,jsxs as Ue}from"react/jsx-runtime";function xb(t){let n=new Date(t);return n.toDateString()===new Date().toDateString()?`today at ${n.toLocaleTimeString([],{hour:"numeric",minute:"2-digit"})}`:n.toLocaleString([],{dateStyle:"medium",timeStyle:"short"})}function qr({target:t,onCancel:n,onConfirm:i}){return Te("div",{className:"bb-reset-overlay",onClick:n,children:Ue("div",{className:"bb-reset-dialog",onClick:r=>r.stopPropagation(),children:[Ue("div",{className:"bb-reset-header",children:[Ue("h3",{className:"bb-reset-title",children:[Te(fb,{size:20,className:"bb-icon-warning"}),"Confirm Reset"]}),Te("button",{className:"bb-reset-close",onClick:n,children:Te(Yr,{size:20})})]}),Ue("div",{className:"bb-reset-body",children:[Ue("p",{className:"bb-reset-message",children:["Are you sure you want to reset"," ",Te("strong",{children:t==="bindings"?"Object Bindings":"Scene Config"}),"?"]}),Te("p",{className:"bb-reset-details",children:t==="bindings"?"This will remove all your custom changes to object properties, groups, tags, transforms, materials, actions, camera positions, metrics, and metadata.":"This will restore all scene settings (camera, lighting, environment, background, animations, annotations, etc.) to their default values."}),Te("p",{className:"bb-reset-warning",children:"This action cannot be undone!"})]}),Ue("div",{className:"bb-reset-footer",children:[Te("button",{className:"bb-reset-btn",onClick:n,children:"Cancel"}),Te("button",{className:"bb-reset-btn-danger",onClick:i,children:"Reset"})]})]})})}function Jr({modelName:t,savedAt:n,onCancel:i,onConfirm:r}){return Te("div",{className:"bb-reset-overlay",onClick:i,children:Ue("div",{className:"bb-reset-dialog",onClick:e=>e.stopPropagation(),children:[Ue("div",{className:"bb-reset-header",children:[Ue("h3",{className:"bb-reset-title",children:[Te(hb,{size:20,className:"bb-icon-restore"}),"Restore Last Session"]}),Te("button",{className:"bb-reset-close",onClick:i,children:Te(Yr,{size:20})})]}),Ue("div",{className:"bb-reset-body",children:[Ue("p",{className:"bb-reset-message",children:["Restore ",Te("strong",{children:t}),", saved ",xb(n),"?"]}),Te("p",{className:"bb-reset-details",children:"This reloads that model with its object bindings and scene settings, replacing what's in the editor now."})]}),Ue("div",{className:"bb-reset-footer",children:[Te("button",{className:"bb-reset-btn",onClick:i,children:"Cancel"}),Te("button",{className:"bb-reset-btn-restore",onClick:r,children:"Restore"})]})]})})}import{strToU8 as vb}from"fflate";function Xr(t){return JSON.stringify(t,null,2)}function Zr(t){return['import { defineObjectBindings } from "@liveroom-tech/react-immersive/utils";',"",`export const objectBindings = defineObjectBindings(${JSON.stringify(t,null,2)});`,""].join(`
|
|
2
|
+
`)}function Qr(t){return JSON.stringify(t,null,2)}function es(t){return['import type { SceneConfig } from "@liveroom-tech/react-immersive/utils";',"",`export const sceneConfig: SceneConfig = ${JSON.stringify(t,null,2)};`,""].join(`
|
|
3
|
+
`)}function cn(t,n,i){On(new Blob([n],{type:i}),t)}function Jo(t){return JSON.stringify(t??{},null,2)}function Xo(t){return`[${t[0].toFixed(3)}, ${t[1].toFixed(3)}, ${t[2].toFixed(3)}]`}function yb(t){return(t.decals??[]).map(n=>n.image).filter(n=>!!n?.trim())}function wb(t){let n=t.style?.material;return n?Object.values(n).filter(i=>!!i&&typeof i=="object"&&typeof i.path=="string"&&i.path.trim().length>0).map(i=>i.path):[]}async function ts(t){let n=new Set;for(let e of Object.values(t)){for(let o of wb(e))n.add(o);for(let o of yb(e))n.add(o)}let i=[],r=[];return await Promise.all(Array.from(n).map(async e=>{let o=ja(e);if(o)try{let d=await fetch(o);if(!d.ok)throw new Error(String(d.status));i.push({path:e,blob:await d.blob()});return}catch{r.push(e);return}try{let d=await Qt(e);d&&i.push({path:e,blob:d})}catch{}})),{assets:i,failedPaths:r}}async function Zo(t,n,i,r,e){if(e.length===0){cn(t,n,i);return}let o={[t]:vb(n)};for(let l of e)o[l.path]=new Uint8Array(await l.blob.arrayBuffer());let d=await Ia(o);On(new Blob([d],{type:"application/zip"}),r)}async function $n(t){return await Promise.all(Object.entries(t).map(async([n,i])=>{for(let e of i.decals??[])if(e.image)try{let o=await Qt(e.image);o&&yt(e.image,URL.createObjectURL(o))}catch(o){console.warn(`[BindingBuilder] Could not rehydrate a decal image on "${n}":`,o)}let r=i.style?.material;if(r)for(let e of Da){let d=r[e]?.path;if(d)try{let l=await Qt(d);if(!l){console.warn(`[BindingBuilder] No stored texture found for "${n}"'s ${e} ("${d}"). If this is meant to be an uploaded file rather than a hosted URL, it was uploaded before texture autosave existed (or this browser's storage was cleared) \u2014 re-upload it once so it's stored for future restores.`);continue}let b=URL.createObjectURL(l);yt(d,b)}catch(l){console.warn(`[BindingBuilder] Could not rehydrate "${n}"'s ${e}:`,l)}}})),t}function ns({bindings:t,setBindings:n,setSceneConfig:i,nodeKeys:r,sceneConfigInputRef:e,setIsExporting:o,setStatusMessage:d,setStatusTone:l}){let b=async S=>{o(!0);try{let{assets:m,failedPaths:f}=await ts(t);S==="json"?await Zo("objectBindings.json",Xr(t),"application/json","objectBindings.zip",m):await Zo("objectBindings.ts",Zr(t),"text/typescript","objectBindings-ts.zip",m),f.length>0?(d(`Exported, but ${f.length} uploaded image${f.length===1?"":"s"} couldn't be bundled: ${f.join(", ")}.`),l("error")):m.length>0&&(d(`Exported with ${m.length} uploaded image${m.length===1?"":"s"} bundled into the zip.`),l("success"))}catch(m){let f=m instanceof Error?m.message:"Unknown export error.";d(`Failed to export bindings: ${f}`),l("error")}finally{o(!1)}},w=async S=>{if(!r.length){d("Load a model before importing bindings."),l("error");return}let m;try{m=JSON.parse(await S.text())}catch{d(`${S.name} is not valid JSON.`),l("error");return}if(m===null||typeof m!="object"||Array.isArray(m)){d("Expected a JSON object mapping object IDs to bindings."),l("error");return}let f=new Map;for(let v of Object.values(m))if(v!==null&&typeof v=="object"&&typeof v.id=="string"&&typeof v.type=="string"&&typeof v.modelObjectId=="string"){let P=v;f.set(P.modelObjectId,P)}if(f.size===0){d(`${S.name} doesn't look like an exported bindings file.`),l("error");return}let y={...t},p={},g=0;for(let v of Object.keys(y)){let P=f.get(v);P&&(y[v]=P,p[v]=P,g++)}if(g===0){d(`None of the object IDs in ${S.name} match this model \u2014 nothing imported.`),l("error");return}let T=await $n(p);Object.assign(y,T),n(y);let x=f.size-g;d(x>0?`Imported ${g} binding${g===1?"":"s"} from ${S.name} (${x} skipped \u2014 not in this model).`:`Imported ${g} binding${g===1?"":"s"} from ${S.name}.`),l("success")},A=async S=>{let m=S.target.files?.[0];m&&(await w(m),S.target.value="")},k=()=>{e.current?.click()},s=async S=>{let m;try{m=JSON.parse(await S.text())}catch{d(`${S.name} is not valid JSON.`),l("error");return}if(m===null||typeof m!="object"||Array.isArray(m)){d("Expected a JSON object with scene config sections."),l("error");return}let f=["model","camera","lighting","wireframe","shadows","environment","background","groundShadows","postProcessing","animations","annotations","cinematic","styleRules","section"],y=m,p=f.filter(g=>y[g]!==void 0);if(p.length===0){d(`${S.name} doesn't look like an exported scene config file.`),l("error");return}i(g=>{let T={...g};for(let x of p)T[x]=sn(g[x],y[x]);return T}),d(`Imported ${p.length} section${p.length===1?"":"s"} from ${S.name}.`),l("success")};return{handleExportBindings:b,importBindingsFile:w,handleImportBindingsChange:A,openSceneConfigImportPicker:k,importSceneConfigFile:s,handleImportSceneConfigChange:async S=>{let m=S.target.files?.[0];m&&(await s(m),S.target.value="")}}}var Qo={pbr:["texture","baseColor","metalness","metalnessMap","specularIntensity","specularIntensityMap","specularColor","specularColorMap","reflectivity"],roughness:["roughness","roughnessMap"],emission:["emissive","emissiveIntensity","emissiveMap"],opacity:["opacity","alphaMap","alphaTest","alphaHash","dithering","blendingMode"],normalBump:["normalMap","normalScale","flipNormalY","bumpMap","bumpScale"],displacement:["displacementMap","displacementScale","displacementBias"],ao:["aoMap","aoMapIntensity"],clearcoat:["clearcoat","clearcoatMap","clearcoatRoughness","clearcoatRoughnessMap","clearcoatNormalMap","clearcoatNormalScale","flipClearcoatNormalY"],sheen:["sheen","sheenColor","sheenColorMap","sheenRoughness","sheenRoughnessMap"],anisotropy:["anisotropy","anisotropyRotation","anisotropyMap"],transmission:["transmission","transmissionMap","thickness","thicknessMap","attenuationColor","attenuationDistance"],faces:["side"]},os=Object.keys(Qo);function as(t){if(t==null)return!1;if(typeof t=="string")return t.trim().length>0;if(typeof t=="number")return Number.isFinite(t);if(typeof t=="boolean")return t;if(typeof t=="object"&&"path"in t){let n=t.path;return typeof n=="string"&&n.trim().length>0}return!1}function ea(t){if(t)return Object.values(t).some(as)?t:void 0}function $e(t,n){return t?Qo[n].some(i=>as(t[i])):!1}function ta(t){return{pbr:$e(t,"pbr"),roughness:$e(t,"roughness"),emission:$e(t,"emission"),opacity:$e(t,"opacity"),normalBump:$e(t,"normalBump"),displacement:$e(t,"displacement"),ao:$e(t,"ao"),clearcoat:$e(t,"clearcoat"),sheen:$e(t,"sheen"),anisotropy:$e(t,"anisotropy"),transmission:$e(t,"transmission"),faces:$e(t,"faces")}}function na(t,n){if(n)return{...t,style:{...t.style,material:n}};if(!t.style)return t;let{material:i,...r}=t.style;return{...t,style:Object.keys(r).length>0?r:void 0}}function is(t,n){if(!t)return;let i={...t};for(let r of Qo[n])delete i[r];return i}import{Fragment as Rt,jsx as E,jsxs as ve}from"react/jsx-runtime";var rs="/room.glb";function Bb(){return`${Date.now().toString(36)}-${Math.random().toString(36).slice(2,10)}`}function ss(t){return`Couldn't reload ${t} from your last session. It's still saved in this browser.`}function Rb({licenseKey:t,licenseValidationUrl:n,dracoDecoderPath:i,ktx2TranscoderPath:r,meshopt:e,project:o,onProjectChange:d,projectChangeDebounceMs:l=350,onModelUpload:b,onTextureUpload:w,onEditLeaseChange:A,allowModelChange:k=!0}){let s=ie(null),h=ie(null),S=ie(null),[m,f]=V(o?.model.url??null),[y,p]=V(o?.model.name??""),[g,T]=V(o?.model??null),[x,v]=V(null),P=_o(o?.objectBindings??{}),a=P.value,u=P.setValue,[z,D]=V(!1),[$,ze]=V(null),gt=Gt(()=>$?{target:$}:null,[$]),[Mt,ft]=V(null);Je(()=>ft(null),[x,m]),Je(()=>Zn(null),[m]);let[ls,ds]=V([]),[oa,cs]=V(()=>new Set),[bs,ht]=V(null),[aa,ps]=V(!1),[ia,Q]=V("Load the demo model or upload a GLB, GLTF, OBJ, FBX, USDZ, STL, or PLY model to generate bindings."),[bn,re]=V("default"),[us,Ut]=V(!1),[ra,pn]=V("{}"),[sa,un]=V("{}"),[ms,mn]=V(null),[gs,gn]=V(null),[fs,$t]=V(!1),[At,hs]=V(!1),[xs,vs]=V(!1),[nt,ys]=V({identity:!0,basics:!0,material:!1,decals:!1,actions:!1,camera:!1,transform:!1,metrics:!1,metadata:!1}),[ws,Cs]=V({pbr:!1,roughness:!1,emission:!1,opacity:!1,normalBump:!1,displacement:!1,ao:!1,clearcoat:!1,sheen:!1,anisotropy:!1,transmission:!1,faces:!1}),ot=c=>ys(C=>({...C,[c]:!C[c]})),Ss=c=>Cs(C=>({...C,[c]:!C[c]})),[at,Kn]=V("object"),[Kt,la]=V("General"),[ks,Ns]=V("metalness"),[Ts,_n]=V(ta()),da=ie(null),[ca,Ps]=V(!1),[Wn,Bs]=V(!0),[Yn,Rs]=V(!0),[Ms,ba]=V(!1),[fn,pa]=V(null),[hn,qn]=V(null),[Jn,ua]=V(!1),[ma,As]=V("world"),Xn=ie({}),ke=_o(o?.sceneConfig??Xt),Re=ke.value,xn=ke.setValue,_t=ke.setValueUntracked,[vn,Os]=V(!1),[Ls,zs]=V(.5),[Ot,Zn]=V(null),ga=Ot??{bindings:P.baseline,sceneConfig:ke.baseline},[fa,Qn]=V("orbit"),[Es,ha]=V(!1),eo=ie(void 0),to=ne(()=>{ha(!0),clearTimeout(eo.current),eo.current=setTimeout(()=>ha(!1),5e3)},[]);Je(()=>()=>clearTimeout(eo.current),[]),Je(()=>{m&&!z&&to()},[m,z,to]);let Ce=fa==="pointerLock",[xa,Ds]=V(null),va=ie(null),js=xa?.objectKey===x&&xa?.textureKey==="texture",[Is,yn]=V(null),[Fs,no]=V(null),Wt=Xa(t,n),ya=Pi(Wt.tier),Hs=Gt(()=>({isInsideEditor:!0,activeTab:at,activeSubTab:Kt,tier:ya,setActiveTab:Kn,setActiveSubTab:la}),[at,Kt,ya]),Ke=ie(null),Lt=ie(0),it=ie(0),wa=ie(o?`${o.id}:${o.revision}`:null),Ca=ie(null),Sa=ie(!1),zt=ie(!1),wn=ie(o?{modelUrl:o.model.url,bindings:o.objectBindings,sceneConfig:o.sceneConfig}:null),Cn=ie(void 0),xt=ie(0),Se=ie(null),Fe=ie(o?{requestId:0,modelName:o.model.name??"model",modelUrl:o.model.url,storedBindings:o.objectBindings,streaming:!!o.model.tilesetUrl}:null),ct=ie(null),oo=ie(null),Sn=ie(null),Vs=ie(!1),vt=ie(null),kn=ie(null),{cameraState:se,resetView:ka,focusObject:Na,fitScene:Ta,setCameraState:Nn,handleCameraChange:Gs,handleViewerReady:Us}=Za(),$s=ne(c=>{Ce||Nn({position:c.position,target:c.target,fov:c.fov??se?.fov??null,zoom:c.zoom??se?.zoom??1,azimuthAngle:c.azimuthAngle,polarAngle:c.polarAngle},!0)},[Ce,Nn,se]),Tn=pi(),ge=x?a[x]??null:null,ao=ge?.style?.material,Pa=!oa.has(ge?.modelObjectId??x??""),bt=ge?.cameraState,Ks=se?{position:Xo(se.position),target:Xo(se.target)}:null,_s=ne(c=>{xn(C=>{let R=C.annotations.map(I=>I.id).join(","),M=c.map(I=>I.id).join(",");return R===M?C:{...C,annotations:c}})},[]),Ws=ne(c=>{yn(c?{annotation:c}:null)},[]);Je(()=>{if(!ge){pn("{}"),un("{}"),mn(null),gn(null);return}pn(Jo(ge.metrics)),un(Jo(ge.metadata)),mn(null),gn(null)},[ge]),Je(()=>{let c=ta(ao);if(da.current!==x){da.current=x,_n(c);return}_n(C=>{let R=!1,M={...C};for(let I of os)c[I]&&!C[I]&&(M[I]=!0,R=!0);return R?M:C})},[x,ao]),Je(()=>()=>{Ke.current?.cleanup(),Se.current&&clearTimeout(Se.current)},[]);let Yt=ne((c,C)=>{let R=zn(c);if(C){let M=new Map(Object.values(C).map(I=>[I.modelObjectId,I]));for(let I of c){let ee=M.get(I);ee&&(R[I]=ee)}}return R},[]);Je(()=>{if(!o)return;let c=`${o.id}:${o.revision}`;if(wa.current===c)return;wa.current=c;let C=m!==o.model.url||g?.tilesetUrl!==o.model.tilesetUrl||g?.assetVersion!==o.model.assetVersion,R=a!==o.objectBindings,M=Re!==o.sceneConfig;(C||R||M)&&(zt.current=!0),T(o.model),p(o.model.name??"model");let I=o.objectBindings;if(R){let ee=Ca.current;I=ee?Yt(ee,o.objectBindings):o.objectBindings,P.reset(I)}if(M&&ke.reset(o.sceneConfig),C){let ee=++it.current;Fe.current={requestId:ee,modelName:o.model.name??"model",modelUrl:o.model.url,storedBindings:o.objectBindings,streaming:!!o.model.tilesetUrl},vt.current=null,v(null),D(!0),f(o.model.url)}wn.current={modelUrl:o.model.url,bindings:I,sceneConfig:o.sceneConfig}},[a,Yt,o,m,Re,g,P,ke]);let io=ie(d);io.current=d,Je(()=>{if(!o||!io.current||!m)return;if(!Sa.current){Sa.current=!0;return}let c=wn.current;if(m===o.model.url&&a===o.objectBindings&&Re===o.sceneConfig||c!==null&&m===c.modelUrl&&a===c.bindings&&Re===c.sceneConfig){zt.current=!1;return}if(Fe.current)return;if(zt.current){zt.current=!1;return}let C=window.setTimeout(()=>{io.current?.({projectId:o.id,baseRevision:o.revision,model:{...g??o.model,url:m,name:y||o.model.name},objectBindings:a,sceneConfig:Re},"local")},l);return()=>window.clearTimeout(C)},[a,y,m,o,l,g,Re]),Je(()=>{let c=C=>{if(C.key.toLowerCase()!=="z"||!(C.metaKey||C.ctrlKey))return;let R=C.target,M=R?.tagName;if(M==="INPUT"||M==="TEXTAREA"||R?.isContentEditable)return;C.preventDefault();let I=at==="scene"?ke:P;C.shiftKey?I.redo():I.undo()};return window.addEventListener("keydown",c),()=>window.removeEventListener("keydown",c)},[at,P,ke]);let ro=!o&&k,Ys=P.edits>0||ke.edits>0,{handleTextureUpload:qs}=_r({autosaveEnabled:ro,hasEdits:Ys,modelUrl:m,bindings:a,sceneConfig:Re,onTextureUpload:w,modelSourceRef:ct,pendingLoadRef:Fe,storedModelKeyRef:oo,pendingAutosaveRef:Sn,autosaveFailureShownRef:Vs,setStatusMessage:Q,setStatusTone:re});Je(()=>{if(z||bn==="default"||bn==="success")return;Ut(!0);let c=window.setTimeout(()=>Ut(!1),4e3);return()=>window.clearTimeout(c)},[ia,bn,z]);let Xe=Gt(()=>Object.keys(a),[a]),Js=Gt(()=>!x||!ge?null:ge.id.trim()?Object.entries(a).some(([R,M])=>R!==x&&M.id===ge.id)?"Another binding already uses this ID.":null:"ID is required.",[a,x,ge]),He=(c,C)=>{u(R=>({...R,[c]:C(R[c])}))},so=(c,C)=>{He(c,R=>{let M=ea(C(R.style?.material));return na(R,M)})},Xs=(c,C,R)=>{so(c,M=>({...M,[C]:R?{path:R}:void 0}))},Zs=(c,C)=>{_n(R=>({...R,[c]:C})),!C&&x&&He(x,R=>{let M=ea(is(R.style?.material,c));return na(R,M)})},lo=ne((c,C,R)=>{let M=wo(c),I=zn(M,yo(c));if(R){let le=new Map(Object.values(R).map(G=>[G.modelObjectId,G]));for(let G of M){let Oe=le.get(G);Oe&&(I[G]=Oe)}}c.updateMatrixWorld(!0);let ee={};for(let le of M){let G=fo(c,le);if(!G){ee[le]={position:[0,0,0],rotation:[0,0,0],scale:[1,1,1],pivotLocal:[0,0,0],rotationOrder:"XYZ"};continue}let Oe=ri(G);ee[le]={position:[G.position.x,G.position.y,G.position.z],rotation:[G.rotation.x,G.rotation.y,G.rotation.z],scale:[G.scale.x,G.scale.y,G.scale.z],pivotLocal:[Oe.x,Oe.y,Oe.z],rotationOrder:G.rotation.order}}Xn.current=ee,P.reset(I),v(M[0]??null),R||_t(le=>({...le,annotations:[]})),Q(`Generated ${M.length} bindings from ${C}.`),re("success"),xt.current=100,ht(100),Se.current&&clearTimeout(Se.current),Se.current=setTimeout(()=>{Se.current=null,D(!1),ht(null)},400)},[P,_t]),co=(c,C,R,M)=>{Sn.current?.();let I=++it.current;D(!0),ht(null),xt.current=0,Se.current&&(clearTimeout(Se.current),Se.current=null),Cn.current=R;let ee=R?R/1048576:0;Q(ee>=100?`Reading ${C} (${Math.round(ee)}MB \u2014 large file, this can take a while)...`:`Reading ${C} and generating starter bindings...`),re("default"),p(C),T(M??{url:c,name:C}),yn(null);let le=vt.current;if(c===m&&le?.url===c){Fe.current=null,lo(le.scene,C);return}Fe.current={requestId:I,modelName:C,modelUrl:c,streaming:!!M?.tilesetUrl},f(c),P.reset({}),v(null)},Qs=ne(c=>{let C=Fe.current;if(!(!C||C.requestId!==it.current)){if(Fe.current=null,vt.current={url:C.modelUrl,scene:c},ft(null),ds(qa(c)),cs(C.streaming?new Set:yo(c)),ze(null),C.streaming){Q(`Streaming ${C.modelName}.`),re("success"),D(!1);return}C.storedBindings&&(zt.current=!0),lo(c,C.modelName,C.storedBindings),C.restoring&&Q(`Restored your last session with ${C.modelName}.`)}},[lo]),el=ne(c=>{let C=c.map(M=>M.name);if(C.length===0)return;Ca.current=C,zt.current=!0;let R=Yt(C,o?.objectBindings);if(P.reset(R),o){let M=wn.current;wn.current={modelUrl:M?.modelUrl??o.model.url,bindings:R,sceneConfig:M?.sceneConfig??o.sceneConfig}}v(M=>M??C[0]??null),Q(`Streaming ${C.length} bindable objects.`),re("success"),D(!1)},[Yt,P,o]),tl=ne(c=>{let C=Fe.current;!C||C.requestId!==it.current||(Fe.current=null,console.error(c),C.restoring?(ct.current=null,f(null),Q(ss(C.modelName))):Q(La(c)?`${C.modelName} is a point cloud: it has points but no faces. Turn it into a mesh first, for example with MeshLab or Blender.`:`Could not read ${C.modelName}. Make sure the file is a valid GLB, GLTF, OBJ, FBX, USDZ, STL, or PLY asset.`),re("error"),Se.current&&(clearTimeout(Se.current),Se.current=null),xt.current=0,D(!1),ht(null))},[]),nl=ne(c=>{let C=null;if(c.lengthComputable&&c.total>0)C=c.loaded/c.total*100;else{let M=Cn.current;M&&M>0&&(C=c.loaded/M*100)}if(C===null)return;let R=Math.min(90,Math.floor(C/10)*10);R>xt.current&&(xt.current=R,ht(R)),C>=99.5&&Q(M=>M.startsWith("Finalizing")?M:"Finalizing model \u2014 parsing geometry and textures (large files can take a moment here)...")},[]),ol=ne(c=>{Tn.handleAnimationsReady(c);let C=c.clipDetails??c.clips.map(R=>({sourceName:R,duration:0}));_t(R=>({...R,animations:Kr(R,C)}))},[Tn,_t]),Mb=async()=>{Ke.current?.cleanup(),Ke.current=null,ct.current={model:{kind:"url",url:rs,name:"room.glb"}},await co(rs,"room.glb")},Ba=async c=>{if(!k)return;if(b){try{D(!0),Q(`Uploading ${c.name}...`),re("default");let R=await b(c);ct.current={model:{kind:"url",url:R.url,name:R.name??c.name}},await co(R.url,R.name??c.name,c.size,R)}catch(R){D(!1),Q(R instanceof Error?R.message:`Could not upload ${c.name}.`),re("error")}return}let C;try{C=await uo(c)}catch(R){Q(R instanceof Error?R.message:"Could not read model file. Upload a .glb, .gltf, .obj, .fbx, .usdz, .stl, .ply, or .zip asset."),re("error");return}Ke.current?.cleanup(),Ke.current=C,ct.current={model:{kind:"file",key:Bb(),name:C.name},file:c},await co(C.url,C.name,c.size,{url:C.url,name:C.name})},al=async c=>{let C=c.target.files?.[0];C&&(await Ba(C),c.target.value="")},il=()=>{Sn.current?.(),Ke.current?.cleanup(),Ke.current=null,vt.current=null,Fe.current=null,ct.current=null,Xn.current={},Lt.current=0,$t(!1),Se.current&&(clearTimeout(Se.current),Se.current=null),xt.current=0,ht(null),Cn.current=void 0,f(null),p(""),T(null),v(null),yn(null),P.reset({}),pn("{}"),un("{}"),mn(null),gn(null),no(null),ua(!1),_t(c=>({...c,animations:Xt.animations,annotations:[]})),Q("Load the demo model or upload a GLB, GLTF, OBJ, FBX, USDZ, STL, or PLY model to generate bindings."),re("default")},rl=()=>{s.current?.click()},sl=()=>{h.current?.click()},{handleExportBindings:Ra,handleImportBindingsChange:ll,openSceneConfigImportPicker:dl,handleImportSceneConfigChange:cl}=ns({bindings:a,setBindings:u,setSceneConfig:xn,nodeKeys:Xe,sceneConfigInputRef:S,setIsExporting:ps,setStatusMessage:Q,setStatusTone:re}),bl=c=>{c.preventDefault(),c.stopPropagation(),!(z||m)&&(Lt.current+=1,$t(!0))},pl=c=>{c.preventDefault(),c.stopPropagation(),!(z||m)&&(c.dataTransfer.dropEffect="copy",$t(!0))},ul=c=>{c.preventDefault(),c.stopPropagation(),!(z||m)&&(Lt.current=Math.max(0,Lt.current-1),Lt.current===0&&$t(!1))},ml=async c=>{if(c.preventDefault(),c.stopPropagation(),Lt.current=0,$t(!1),z||m)return;let C=c.dataTransfer.files?.[0];C&&await Ba(C)},Ma=(c,C,R)=>{if(!x)return;let M;try{M=JSON.parse(C)}catch{R("Invalid JSON");return}if(M===null||typeof M!="object"||Array.isArray(M)){R("Expected a JSON object");return}if(c==="metrics"&&Object.values(M).some(ee=>typeof ee!="number"||!Number.isFinite(ee))){R("Metrics values must be numbers");return}He(x,I=>({...I,[c]:M})),R(null)},gl=ne((c,C)=>{ro&&In(c,C).catch(R=>console.warn("[BindingBuilder] Could not store decal image for autosave:",R))},[ro]),fl=Gt(()=>{let c=vt.current?.scene,R=(c&&x?fo(c,x):null)?.geometry;if(!R)return .2;R.boundingBox||R.computeBoundingBox();let M=R.boundingBox?.getSize(new Cb),I=M?Math.max(M.x,M.y,M.z):0;return I>0&&Number.isFinite(I)?I/3:.2},[x,m,z]),hl=Gt(()=>{if(!Mt?.moving)return null;let{nodeKey:c,decal:C}=Mt,R=a[c],M=R?.decals?.find(I=>I.id===C.id);return M?{objectId:R.modelObjectId??c,decal:M,onCancel:()=>ft(null),onCommit:I=>{u(ee=>{let le=ee[c];return le?{...ee,[c]:{...le,decals:le.decals?.map(G=>G.id===M.id?{...G,...I}:G)}}:ee}),ft(null)}}:null},[a,Mt,u]),xl=ne((c,C)=>{if(!x)return;let R=a[x],M=R?.decals?.find(G=>G.id===c);if(!M)return;let I=kn.current,ee=I?.raw.nodes[R.modelObjectId??x],le=di(ee,I?.raw.controls.camera,M,C);if(!le){Q("No visible surface in that direction. Try another arrow or rotate the view."),re("error"),Ut(!0);return}ft(null),Ut(!1),He(x,G=>({...G,decals:G.decals?.map(Oe=>Oe.id===c?{...Oe,...le}:Oe)}))},[a,x,He]),vl=ne(c=>{if(!c||c.moving){ft(c);return}let C=kn.current,R=a[c.nodeKey],M=C?.raw.nodes[R?.modelObjectId??c.nodeKey],I=li(M,C?.raw.controls.camera);if(!I){Q("Could not find a surface on this object for the decal."),re("error"),Ut(!0);return}let ee={...c.decal,...I};u(le=>{let G=le[c.nodeKey];if(!G)return le;let Oe=(G.decals??[]).filter(Et=>Et.id!==ee.id);return{...le,[c.nodeKey]:{...G,decals:[...Oe,ee]}}}),ft({...c,moving:!0})},[a,u]),yl=ne(c=>{if(Ce){Qn("orbit");return}if(!c){v(null);return}let C=Object.entries(a).find(([R,M])=>M===c||R===c.modelObjectId||M.modelObjectId===c.modelObjectId)?.[0]??null;v(C)},[Ce,a]),wl=ne(async c=>{if(Ce){Qn("orbit");return}v(c),no(null),await Na(c)},[Ce,Na]),Cl=ne(c=>{no(c?a[c]??null:null)},[a]),Sl=ne(c=>vs(!c),[]),kl=ne(()=>{if(Ce){Q("Camera positions aren't available while Pointer Lock is the active camera controller."),re("error");return}if(!x||!se)return;let c={position:se.position,target:se.target,...se.fov!=null?{fov:se.fov}:{},zoom:se.zoom};He(x,C=>({...C,cameraState:c}))},[Ce,x,se]),Nl=ne(()=>{if(Ce){Q("Camera positions aren't available while Pointer Lock is the active camera controller."),re("error");return}!bt?.position||!bt?.target||Nn({position:bt.position,target:bt.target,fov:bt.fov??se?.fov??null,zoom:bt.zoom??se?.zoom??1},!0)},[Ce,bt,Nn,se]),Tl=ne(()=>{Ce||x&&He(x,c=>({...c,cameraState:void 0}))},[Ce,x]),Pl=ne(async()=>{if(Ce){Q("Reset View isn't available while Pointer Lock is the active camera controller."),re("error");return}await ka()},[Ce,ka]),Bl=ne(async()=>{if(Ce){Q("Fit Scene isn't available while Pointer Lock is the active camera controller."),re("error");return}await Ta()},[Ce,Ta]),Rl=ne(()=>{Q("Texture position saved."),re("success"),va.current?.()},[]),Aa=ne(c=>{pa(c),ba(!0)},[]),Pn=ne(()=>{ba(!1),pa(null)},[]),Ml=ne(()=>{if(fn==="bindings"){if(!Xe.length){Pn();return}let c=zn(Xe,oa);P.reset(c,{asEdit:!0}),v(Xe[0]??null),Q("Object bindings reset to default values."),re("success")}else fn==="scene"&&(ke.reset(Xt,{asEdit:!0}),Q("Scene config reset to default values."),re("success"));Pn()},[fn,Xe,P,ke,Pn]),Al=ne(()=>{qn(null)},[]),Ol=async()=>{let c;try{c=await Ci()}catch(C){console.warn("[BindingBuilder] Could not read the saved session:",C),Q("Couldn't read the saved session from this browser."),re("error");return}if(!c){Q("No saved session in this browser yet \u2014 one is saved as soon as you edit a model."),re("error");return}qn(c)},Ll=async()=>{let c=hn;if(qn(null),!c)return;let{session:C,file:R}=c,{model:M}=C;Sn.current=null;let I=sn(Xt,C.sceneConfig),ee=it.current,le=await $n(C.bindings);if(it.current!==ee)return;let G;if(M.kind==="file"){if(!R)return;let Et=it.current,Bn;try{Bn=await uo(R)}catch(zl){console.warn("[BindingBuilder] Could not read the saved model:",zl),Q(ss(M.name)),re("error");return}if(it.current!==Et){Bn.cleanup();return}Ke.current?.cleanup(),Ke.current=Bn,G=Bn.url}else{G=M.url;let Et=vt.current;if(G===m&&Et?.url===G&&!Fe.current){ct.current={model:M},oo.current=null,P.reset(Yt(wo(Et.scene),le)),ke.reset(I),Q(`Restored your last session with ${M.name}.`),re("success");return}Ke.current?.cleanup(),Ke.current=null}ct.current={model:M,file:R??void 0},oo.current=M.kind==="file"?M.key:null;let Oe=++it.current;D(!0),ht(null),xt.current=0,Se.current&&(clearTimeout(Se.current),Se.current=null),Cn.current=R?.size,Q(`Restoring your last session with ${M.name}...`),re("default"),p(M.name),T({url:G,name:M.name}),yn(null),v(null),vt.current=null,P.reset({}),ke.reset(I),Fe.current={requestId:Oe,modelName:M.name,modelUrl:G,storedBindings:le,restoring:!0},f(G)};if(Wt.status==="checking")return E("div",{className:"bb-root bb-root--licenseChecking",children:E(po,{title:"Verifying License",message:"Checking your license key..."})});if(Wt.status==="invalid")return E("div",{className:"bb-root bb-root--licenseInvalid",children:E(po,{tone:"error",title:"Invalid License",message:Wt.isLocalDomain?Wt.reason??"License has been revoked or has expired":"Failed to load. Please contact the site administrator."})});let bo=Ce?E(Rt,{children:"Click the preview to look around \xB7 Esc to release"}):Jn?E(Rt,{children:"Select a mesh \xB7 drag the colored arrows, planes, or rings"}):Es&&Yn?ve(Rt,{children:[E("kbd",{children:"W"}),E("kbd",{children:"A"}),E("kbd",{children:"S"}),E("kbd",{children:"D"})," move \xB7 ",E("kbd",{children:"Space"}),"/",E("kbd",{children:"C"})," up \xB7 down \xB7 drag to look"]}):null;return ve(ei.Provider,{value:Hs,children:[ve("div",{className:"bb-root",children:[E("input",{ref:s,type:"file",accept:Oa,className:"bb-hiddenInput",onChange:al,disabled:z}),E("input",{ref:h,type:"file",accept:".json,application/json",className:"bb-hiddenInput",onChange:ll,disabled:z}),E("input",{ref:S,type:"file",accept:".json,application/json",className:"bb-hiddenInput",onChange:cl,disabled:z}),ve("aside",{className:`bb-sidebar bb-sidebar--left ${At?"bb-sidebar--collapsed":""}`,children:[ve("div",{className:"bb-header bb-header--sidebar",children:[!At&&E("h1",{className:"bb-title",children:"Binding Builder"}),E("button",{type:"button",className:"bb-sidebarToggle",onClick:()=>hs(c=>!c),"aria-label":At?"Open editor sidebar":"Collapse editor sidebar",title:At?"Open editor":"Collapse editor",children:At?"\u2192":"\u2190"})]}),!At&&ve(Rt,{children:[ve("div",{className:"bb-tabRow",children:[E("button",{type:"button",className:`bb-tab ${at==="object"?"bb-tab--active":""}`,onClick:()=>Kn("object"),children:"Object"}),E("button",{type:"button",className:`bb-tab ${at==="scene"?"bb-tab--active":""}`,onClick:()=>Kn("scene"),children:"Scene"})]}),E("section",{className:"bb-editor",children:at==="scene"?E(Rt,{children:m?E(Io,{config:Re,onChange:xn,activeSubTab:Kt,onActiveSubTabChange:la,cameraState:(Kt==="Cinematic"||Kt==="Annotations")&&se?{position:se.position,target:se.target,azimuthAngle:se.azimuthAngle,polarAngle:se.polarAngle,fov:se.fov,zoom:se.zoom}:null,onPreviewWaypoint:$s,animationClipDetails:Tn.clipDetails,animationPlayback:Tn,materialVariantGroups:ls,objectBindings:a}):E("div",{className:"bb-emptyEditor",children:"Upload a model to edit its scene settings."})}):!ge||!x?E("div",{className:"bb-emptyEditor",children:"Select a generated node binding to edit its values."}):ve(Rt,{children:[E("div",{className:"bb-editorHeader",children:ve("div",{children:[E("div",{className:"bb-sectionKicker",children:"Editing Binding"}),E("h2",{className:"bb-editorTitle",children:ge.label||x}),ve("div",{className:"bb-editorMeta",children:[E("span",{children:ge.type}),E("span",{children:ge.modelObjectId})]})]})}),E(Br,{selectedItem:x,selectedBinding:ge,open:nt.identity,onToggle:()=>ot("identity"),updateBinding:He,idError:Js}),E(Mr,{selectedItem:x,selectedBinding:ge,open:nt.basics,onToggle:()=>ot("basics"),updateBinding:He}),ve(Pe,{title:"Material",open:nt.material,onToggle:()=>ot("material"),tooltip:"Edit the selected object's base material, textures, and surface properties.",children:[E(Pr,{disabled:!x,onApply:c=>x&&so(x,C=>({...C,...c}))}),E(Nr,{selectedItem:x,selectedMaterial:ao,pbrWorkflow:ks,onPbrWorkflowChange:Ns,openMaterialPanels:ws,materialPanelEnabled:Ts,onToggleMaterialPanel:Ss,onSetMaterialPanelState:Zs,updateSelectedMaterial:so,setSelectedTexturePath:Xs,isTexturePositioningEnabled:js,onConfirmTexturePosition:Rl,takesImage:Pa})]}),E(Er,{selectedItem:x,selectedBinding:ge,open:nt.decals,onToggle:()=>ot("decals"),updateBinding:He,placement:Mt,onPlacementChange:vl,defaultSize:fl,onImageFile:gl,onNudge:xl}),E(Or,{selectedItem:x,selectedBinding:ge,open:nt.actions,onToggle:()=>ot("actions"),updateBinding:He,takesImage:Pa}),E(Dr,{selectedBinding:ge,open:nt.camera,onToggle:()=>ot("camera"),cameraState:se,formattedCameraState:Ks,savedCameraPosition:bt,onSaveCameraPosition:kl,onGoToSavedCamera:Nl,onClearSavedCamera:Tl,onResetView:Pl,onFitScene:Bl}),E(Vr,{selectedItem:x,selectedBinding:ge,open:nt.transform,onToggle:()=>ot("transform"),updateBinding:He,moveModeEnabled:Jn,onToggleMoveMode:ua,transformSpace:ma,onTransformSpaceChange:As,originalTransform:Xn.current[x]??null}),E(Ko,{title:"Metrics",label:"Metrics JSON",open:nt.metrics,onToggle:()=>ot("metrics"),draft:ra,error:ms,example:'{"area": 42}',onDraftChange:pn,onCommit:()=>Ma("metrics",ra,mn)}),E(Ko,{title:"Metadata",label:"Metadata JSON",open:nt.metadata,onToggle:()=>ot("metadata"),draft:sa,error:gs,example:'{"room": "kitchen"}',onDraftChange:un,onCommit:()=>Ma("metadata",sa,gn)})]})}),at==="object"&&E(qo,{canUndo:P.canUndo,canRedo:P.canRedo,onUndo:P.undo,onRedo:P.redo,onReset:()=>Aa("bindings"),resetDisabled:!Xe.length,resetTitle:"Reset object bindings to default",onImport:sl,importDisabled:!Xe.length||z,importTitle:"Re-apply a previously exported objectBindings.json onto this model",exportDisabled:!Xe.length||aa,exporting:aa,onExportJson:()=>Ra("json"),onExportTs:()=>Ra("ts")}),at==="scene"&&E(qo,{canUndo:ke.canUndo,canRedo:ke.canRedo,onUndo:ke.undo,onRedo:ke.redo,onReset:()=>Aa("scene"),resetTitle:"Reset scene config to default",onImport:dl,importDisabled:!Xe.length||z,importTitle:"Re-apply a previously exported sceneConfig.json",exportDisabled:!Xe.length||z,onExportJson:()=>cn("sceneConfig.json",Qr(Re),"application/json"),onExportTs:()=>cn("sceneConfig.ts",es(Re),"text/typescript")})]})]}),ve("main",{className:"bb-previewShell",children:[ve("div",{className:"bb-previewHeader",children:[E(So,{label:"View",icon:E(Tb,{size:14,"aria-hidden":"true"}),title:"Preview options",children:()=>ve(Rt,{children:[ve("label",{className:"bb-headerMenuItem",children:[E("input",{type:"checkbox",checked:ca,onChange:c=>Ps(c.target.checked)}),"Zoom on selected"]}),ve("label",{className:"bb-headerMenuItem",children:[E("input",{type:"checkbox",checked:Wn,onChange:c=>Bs(c.target.checked)}),"Highlight on hover"]}),ve("label",{className:"bb-headerMenuItem",children:[E("input",{type:"checkbox",checked:Yn,onChange:c=>Rs(c.target.checked)}),"Camera controller"]})]})}),E("div",{className:"bb-previewMeta",children:E("span",{title:x??void 0,children:x?`Focused: ${x}`:"Select a node to inspect it"})}),m&&ve("button",{type:"button",className:`bb-compareButton ${vn?"bb-compareButton--active":""}`,onClick:()=>{Os(c=>!c),Zn(null)},"aria-pressed":vn,title:"Compare: drag a divider across the preview to see it before and after your changes",children:[E(Pb,{size:14}),"Compare"]}),k&&!o&&E(So,{icon:E(Sb,{size:16,"aria-hidden":"true"}),title:"More model actions",align:"right",children:c=>E(hi,{close:c,onRestore:Ol,restoreDisabled:z,onRemove:m?il:void 0})})]}),ve("div",{className:"bb-preview",onFocus:c=>{c.currentTarget.contains(c.relatedTarget)||to()},children:[E(ti,{visible:z||us,message:ia,tone:bn,progress:bs??void 0}),m&&E("div",{className:`bb-canvasHint ${bo?"bb-canvasHint--visible":""} ${vn?"bb-canvasHint--belowCompare":""}`,"aria-hidden":!bo,children:bo}),m?E(Co,{loading:"eager",modelUrl:m,tilesetUrl:g?.tilesetUrl,objectBindings:a,selectedObject:ge,onObjectSelect:yl,onObjectBindingsChange:u,onTextureUpload:qs,onObjectEditLeaseChange:(c,C)=>A?.(c.modelObjectId||c.id,C),showObjectBindingDataPanel:!1,showSceneObjectsPanel:!1,onCameraChange:Gs,onViewerReady:c=>{kn.current=c,Us(c)},onAnnotationsChange:_s,activeAnnotation:Is?.annotation??null,onActiveAnnotationChange:Ws,onAnimationsReady:ol,onSceneLoaded:Qs,onLoadError:tl,onObjectCatalog:g?.tilesetUrl?el:void 0,onProgress:nl,onCameraControllerChange:Qn,cameraControllerType:fa,onTexturePositioningChange:Ds,endTexturePositioningRef:va,licenseKey:t,licenseValidationUrl:n,dracoDecoderPath:i,ktx2TranscoderPath:r,meshopt:e,sceneConfig:Re,onSceneConfigChange:xn,preserveDrawingBuffer:!0,disableZoom:!1,zoomOnSelected:ca,highlightOnHover:Wn,enableCameraControls:Yn,moveModeEnabled:Jn,objectTransformSpace:ma,enableKeyboardNavigation:!0,showViewGizmo:!0,showSectionTools:Re.section?.enabled??!1,isolation:gt,onIsolationChange:()=>ze(null),showIsolateControls:!0,decalMove:hl,panelHoveredObject:Wn?Fs:null,showLoadingOverlay:!1,autoRotate:Ce?!1:Re.model.autoRotate??!1,autoRotateSpeed:Re.model.autoRotateSpeed??1}):E("div",{className:`bb-previewPlaceholder ${fs?"bb-previewPlaceholder--dragActive":""}`,onDragEnter:bl,onDragOver:pl,onDragLeave:ul,onDrop:ml,children:ve("div",{children:[E("div",{children:"Upload a GLB, GLTF, OBJ, FBX, USDZ, STL, or PLY model, or drag a supported model/ZIP bundle here to generate editable object bindings."}),k?E("button",{type:"button",className:"bb-previewPlaceholderButton",onClick:rl,disabled:z,children:"Upload"}):null]})}),m&&vn?E(yi,{liveViewerRef:kn,split:Ls,onSplitChange:zs,labels:[Ot?"Pinned":"Before","Now"],beforeAction:ve("button",{type:"button",className:"ri-compare__labelAction",onClick:()=>Zn(c=>c?null:{bindings:a,sceneConfig:Re}),"aria-pressed":!!Ot,title:Ot?"Unpin: compare with the project as it was opened again":"Pin as before: compare later changes with how the preview looks now",children:[Ot?E(Nb,{size:12}):E(kb,{size:12}),Ot?"Unpin":"Pin"]}),renderBefore:c=>E(Co,{loading:"eager",modelUrl:m,tilesetUrl:g?.tilesetUrl,objectBindings:ga.bindings,sceneConfig:ga.sceneConfig,licenseKey:t,licenseValidationUrl:n,dracoDecoderPath:i,ktx2TranscoderPath:r,meshopt:e,preset:"minimal",showLoadingOverlay:!1,showObjectNavigator:!1,selectedObject:null,zoomOnSelected:!1,highlightOnHover:!1,autoRotate:!1,cinematic:!1,onViewerReady:c})}):null]})]}),E(Ur,{bindings:a,selectedItem:x,onSelect:wl,onHover:Cl,isOpen:!xs,onToggle:Sl,isolatedItem:$,onIsolate:ze})]}),Ms&&E(qr,{target:fn,onCancel:Pn,onConfirm:Ml}),hn&&E(Jr,{modelName:hn.session.model.name,savedAt:hn.session.savedAt,onCancel:Al,onConfirm:Ll})]})}export{Rb as a};
|