@liveroom-tech/react-immersive 5.0.2 → 5.1.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 +580 -38
- package/dist/{ModelViewer-DOexHkJC.d.ts → ModelViewer-Bj-KjiDL.d.mts} +91 -42
- package/dist/{ModelViewer-CbbJT85n.d.mts → ModelViewer-BkQ73y6N.d.ts} +91 -42
- package/dist/binding-builder.css +1 -1
- package/dist/binding-builder.js +13 -12
- package/dist/binding-builder.mjs +1 -1
- package/dist/chunk-32WCLPTZ.mjs +1 -0
- package/dist/chunk-CSGNL4XU.mjs +3 -0
- package/dist/chunk-F2ILTIPG.mjs +28 -0
- package/dist/chunk-V6GALFL5.mjs +1 -0
- package/dist/chunk-WN6GMMHF.mjs +1 -0
- package/dist/hosted.css +1 -1
- package/dist/hosted.d.mts +3 -3
- package/dist/hosted.d.ts +3 -3
- package/dist/hosted.js +12 -11
- package/dist/hosted.mjs +1 -1
- package/dist/index.css +1 -1
- package/dist/index.d.mts +54 -10
- package/dist/index.d.ts +54 -10
- package/dist/index.js +11 -10
- package/dist/index.mjs +1 -1
- package/dist/{modelInfo-CEmmvVCH.d.mts → modelInfo-DnkmTGMd.d.mts} +6 -0
- package/dist/{modelInfo-CEmmvVCH.d.ts → modelInfo-DnkmTGMd.d.ts} +6 -0
- package/dist/{objectCatalog-5W8n5xNQ.d.ts → objectCatalog-BIeXURoq.d.mts} +276 -5
- package/dist/{objectCatalog-5W8n5xNQ.d.mts → objectCatalog-BIeXURoq.d.ts} +276 -5
- package/dist/simple-model-viewer.d.mts +2 -2
- package/dist/simple-model-viewer.d.ts +2 -2
- package/dist/simple-model-viewer.js +3 -3
- package/dist/simple-model-viewer.mjs +1 -1
- package/dist/utils.d.mts +2 -2
- package/dist/utils.d.ts +2 -2
- package/dist/utils.js +1 -1
- package/dist/utils.mjs +1 -1
- package/package.json +1 -1
- package/dist/chunk-3GX7DOGS.mjs +0 -3
- package/dist/chunk-AH5NAZWX.mjs +0 -27
- package/dist/chunk-BGYK4Y2Y.mjs +0 -1
- package/dist/chunk-WFEYRUZC.mjs +0 -1
- package/dist/chunk-XTLSAYAQ.mjs +0 -1
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-CSGNL4XU.mjs";import"./chunk-F2ILTIPG.mjs";import"./chunk-V6GALFL5.mjs";import"./chunk-32WCLPTZ.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 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."}]),H="__custom__";function T(n){return f.find(e=>e.id===n)}var O=f.filter(n=>n.handling==="viewer").map(n=>n.id),A=new Set(["","New Action",...f.map(n=>n.label)]);function Y(n){return A.has(n.trim())}function S(n,e){let t=Array.from({length:e.length+1},(o,r)=>r);for(let o=1;o<=n.length;o+=1){let r=[o];for(let l=1;l<=e.length;l+=1){let a=t[l-1]+(n[o-1]===e[l-1]?0:1);r[l]=Math.min(r[l-1]+1,t[l]+1,a)}t=r}return t[e.length]}function X(n){if(T(n))return null;let e=n.trim().toLowerCase();if(!e)return null;let t=e.replace(/[^a-z0-9]/g,""),o=null;for(let r of f){let l=Math.min(S(e,r.id),S(t,r.id.replace(/[^a-z0-9]/g,"")));(!o||l<o.distance)&&(o={id:r.id,distance:l})}return o&&o.distance<=2?o.id:null}function q(n){let e=n.trim();return e?/\.(hdr|exr|jpg|jpeg|png|webp)(?:[?#].*)?$/i.test(e):!1}var J=["none","directional","point","spot","hemisphere"],Q=["pbr","matcap","uv-checker"],ee=["apartment","city","dawn","forest","lobby","night","park","studio","sunset","warehouse"];var ne=["sporadic","constantMild","constantWild"],te=["linear","radial","mirroredLinear"],re=["verySmall","small","medium","large","veryLarge","huge"],ie=["x","y","z"],oe={enabled:!1,axis:"y",position:.5,flip:!1},E={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}},ae={model:{rotation:[0,0,0],showAdvancedRotation:!1,renderer:"pbr",shading:"lit",autoRotate:!1,autoRotateSpeed:1,materialVariant:null},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:E,annotations:[]};function j(n,e){if(n[e])return e;let t=Object.entries(n).find(([,r])=>r.id===e)?.[0];return t||(Object.entries(n).find(([,r])=>r.modelObjectId===e)?.[0]??null)}function I(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(I(e))return Object.entries(n).filter(([,r])=>N(r,e)).map(([r])=>r);let o=(typeof e=="string"?[e]:e).map(r=>j(n,r)).filter(r=>r!==null);return[...new Set(o)]}function de(n,e){return p(n,e).map(t=>n[t]).filter(t=>t!==void 0)}var R="#ff3b30",D=Object.freeze({}),B=n=>n;function L(n){return typeof n=="object"&&n!==null&&!Array.isArray(n)}function _(n,e){let t=n.metadata;for(let o of e.split(".")){if(!L(t))return;t=t[o]}return t}function P(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 _(n,e.metadata)===e.equals}function z(n){let e=n.trim().replace(/^#/,""),t=e.length===3?e.split("").map(o=>o+o).join(""):e;return/^[0-9a-f]{6}$/i.test(t)?[0,2,4].map(o=>parseInt(t.slice(o,o+2),16)):null}var h=n=>`#${n.map(e=>Math.round(e).toString(16).padStart(2,"0")).join("")}`;function G(n,e){let t=n.map(([i,s])=>({at:i,rgb:z(s)})).filter(i=>Number.isFinite(i.at)&&i.rgb!==null).sort((i,s)=>i.at-s.at);if(t.length===0||!Number.isFinite(e))return null;if(e<=t[0].at)return h(t[0].rgb);let o=t[t.length-1];if(e>=o.at)return h(o.rgb);let r=t.findIndex(i=>i.at>=e),l=t[r-1],a=t[r],c=a.at===l.at?1:(e-l.at)/(a.at-l.at);return h(l.rgb.map((i,s)=>i+(a.rgb[s]-i)*c))}function me(n,e){if(!e?.length)return{bindings:n,pulses:D,sourceOf:B};let t=new Map,o={};for(let a of e){let c=a.target?p(n,a.target):Object.keys(n),i=a.when?Array.isArray(a.when)?a.when:[a.when]:[];for(let s of c){let m=n[s];if(!i.every(d=>P(m,d)))continue;let u={...a.material};if(a.colorScale){let d=m.metrics?.[a.colorScale.metric],b=typeof d=="number"?G(a.colorScale.stops,d):null;b&&(u={...u,[a.colorScale.channel??"baseColor"]:b})}if(a.pulse){let d=a.pulse===!0?{}:a.pulse;o[s]={color:d.color??R,speed:d.speed!==void 0&&d.speed>0?d.speed:1};let b=u.emissiveIntensity??t.get(s)?.emissiveIntensity??m.style?.material?.emissiveIntensity;b!==void 0&&b>0||(u.emissiveIntensity=1)}Object.keys(u).length>0&&t.set(s,{...t.get(s),...u})}}if(t.size===0)return{bindings:n,pulses:o,sourceOf:B};let r={...n},l=new WeakMap;for(let[a,c]of t){let i=n[a],s={...i,style:{...i.style,material:{...i.style?.material,...c}}};r[a]=s,l.set(s,i)}return{bindings:r,pulses:o,sourceOf:a=>l.get(a)??a}}var F=.12,x=new Set;function V(n,e){return e?new Set(p(n,e.target)):x}function fe(n,e){let t=V(n.bindings,e);if(!e||t.size===0)return{...n,setAside:x};let o=Math.min(Math.max(e.ghostOpacity??F,0),1),r={...n.bindings},l=new WeakMap,a=new Set;for(let[c,i]of Object.entries(n.bindings)){if(t.has(c))continue;a.add(c);let s=e.mode==="hide"?{...i,visible:!1}:{...i,style:{...i.style,material:{...i.style?.material,opacity:Math.min(i.style?.material?.opacity??1,o)}}};r[c]=s,l.set(s,n.sourceOf(i))}return{bindings:r,pulses:n.pulses,sourceOf:c=>l.get(c)??n.sourceOf(c),setAside:a}}var y=Symbol("react-immersive.model-node-id");function U(n,e){Object.defineProperty(n,y,{value:e,configurable:!0})}function w(n){let e=new Map;n.traverse(i=>{if(!i.name)return;let s=e.get(i.name);s?s.push(i):e.set(i.name,[i])});let t=Object.create(null),o=new WeakMap,r=new Map,l=new Set(Array.from(e,([i,s])=>s.length===1?i:null).filter(i=>i!==null)),a=new Set,c=(i,s)=>{U(i,s),t[s]=i,o.set(i,s),a.add(s)};for(let[i,s]of e)s.length===1&&c(s[0],i);for(let[i,s]of e){if(s.length<2)continue;let m=[];s.forEach((u,d)=>{let b=`${i} [${d+1}]`,g=b,v=2;for(;l.has(g)||a.has(g);)g=`${b}.${v++}`;c(u,g),m.push(g)}),r.set(i,m)}return{nodesById:t,idByNode:o,duplicateNames:r}}function ye(n){return n[y]??n.name??null}function Se(n,e){let t=null,o=[];return n.traverse(r=>{r[y]===e&&(t=r),r.name===e&&o.push(r)}),t??(o.length===1?o[0]:null)}function W(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 $(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 K(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 C(n){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"},{id:"change-material",label:"Change Material",type:"command"},{id:"toggle-visibility",label:"Toggle Visibility",type:"command"}]}function M(n){let e=K(n);return{id:W(n),modelObjectId:n,type:e,label:$(n),status:"normal",selectable:!0,hoverable:!0,visible:!0,style:{},actions:C(e),metrics:{},metadata:{}}}function xe(n){return Object.fromEntries(n.map(e=>[e,M(e)]))}function we(n){let e=new Set,t={};for(let o of n){let r=M(o),l=r.id||"object",a=l;for(let i=2;e.has(a);i++)a=`${l}-${i}`;e.add(a),r.id=a;let c=(r.actions??[]).filter(i=>O.includes(i.id));r.actions=c.length>0?c:C("other"),t[o]=r}return t}function Ce(n){let{nodesById:e}=w(n),t=[];for(let[o,r]of Object.entries(e)){let l=r;l.isMesh&&l.geometry&&r.name&&t.push(o)}return t.sort((o,r)=>o.localeCompare(r))}var ve=["front","back","double"],Te=["normal","additive"];export{f as a,H as b,T as c,O as d,Y as e,X as f,j as g,q as h,J as i,Q as j,ee as k,ne as l,te as m,re as n,ie as o,oe as p,ae as q,w as r,ye as s,Se as t,p as u,de as v,P as w,G as x,me as y,V as z,fe as A,$ as B,K as C,M as D,xe as E,we as F,Ce as G,ve as H,Te as I};
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import{a as Zn,c as ma,d as Nn,e as fa,f as xt,g as _t,h as ha,i as xa,j as Tn,k as va,l as Ra,m as Ma,n as Oa,o as Ze,p as Ea,q as ja,r as Da,s as Ia,t as Fa,u as Ha,v as Ga}from"./chunk-F2ILTIPG.mjs";import{A as Ba,I as za,f as pa,h as Qn,j as ga}from"./chunk-V6GALFL5.mjs";import{B as La,E as Pn,G as ao,H as Va,I as $a,a as eo,b as Sn,c as kn,e as to,f as ua,h as ya,i as wa,j as Ca,k as Sa,l as ka,m as Na,n as Wt,o as Ta,p as Pa,q as Yt,t as no,u as oo,w as Aa}from"./chunk-32WCLPTZ.mjs";import{useCallback as te,useEffect as Ye,useMemo as Dt,useRef as se,useState as K}from"react";import{Vector3 as gc}from"three";import{Redo2 as Cr,Undo2 as Sr,Upload as kr,ListRestart as Nr,History as Tr,X as Pr,AlertTriangle as fc}from"lucide-react";var Js="react-immersive:binding-builder";var At="session",yt="model",Ot="textures",qt="current";var vt=null;function Rn(){return vt||(vt=new Promise((t,n)=>{if(typeof indexedDB>"u"){n(new Error("IndexedDB is not available in this environment."));return}let i=indexedDB.open(Js,2);i.onupgradeneeded=()=>{let r=i.result;r.objectStoreNames.contains(At)||r.createObjectStore(At),r.objectStoreNames.contains(yt)||r.createObjectStore(yt),r.objectStoreNames.contains(Ot)||r.createObjectStore(Ot)},i.onsuccess=()=>{let r=i.result;r.onversionchange=()=>{r.close(),vt=null},t(r)},i.onerror=()=>n(i.error??new Error("Failed to open IndexedDB."))}),vt.catch(()=>{vt=null}),vt)}function Mn(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 io(t){return new Promise((n,i)=>{t.onsuccess=()=>n(t.result),t.onerror=()=>i(t.error??new Error("IndexedDB request failed."))})}function Bn(t){return t!==null&&typeof t=="object"&&!Array.isArray(t)}function Xs(t){if(!Bn(t)||t.version!==1)return!1;let n=t.model;return typeof t.savedAt=="number"&&Bn(t.bindings)&&Bn(t.sceneConfig)&&Bn(n)&&typeof n.name=="string"&&(n.kind==="file"&&typeof n.key=="string"||n.kind==="url"&&typeof n.url=="string")}async function Ua(t,n){let i=await Rn(),r={...t,version:1,savedAt:Date.now()},e=i.transaction([At,yt],"readwrite"),o=Mn(e);if(e.objectStore(At).put(r,qt),r.model.kind==="file"&&n){let u={key:r.model.key,blob:n,name:n.name,type:n.type,lastModified:n.lastModified};e.objectStore(yt).put(u,qt)}else r.model.kind==="url"&&e.objectStore(yt).delete(qt);return await o,r}async function Ka(){let n=(await Rn()).transaction([At,yt],"readonly"),i=Mn(n),[r,e]=await Promise.all([io(n.objectStore(At).get(qt)),io(n.objectStore(yt).get(qt))]);return await i,Xs(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 ro(t,n){let r=(await Rn()).transaction(Ot,"readwrite"),e=Mn(r),o={blob:n,name:n.name,type:n.type,savedAt:Date.now()};r.objectStore(Ot).put(o,t),await e}async function Jt(t){let i=(await Rn()).transaction(Ot,"readonly"),r=Mn(i),e=await io(i.objectStore(Ot).get(t));return await r,e?new File([e.blob],e.name,{type:e.type,lastModified:e.savedAt}):null}import{useState as sd,useEffect as ld}from"react";import{useState as sl}from"react";import{ChevronDown as ll,ChevronLeft as dl,ChevronRight as cl,RotateCcw as bl}from"lucide-react";import{HexColorInput as pl,HexColorPicker as ul}from"react-colorful";import{useLayoutEffect as Wa,useRef as so,useState as lo}from"react";import{createPortal as Qs}from"react-dom";import{ChevronDown as el,Info as tl}from"lucide-react";import{HexColorInput as nl,HexColorPicker as ol}from"react-colorful";function pt(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 Zs}from"react";function _a(t,n,i){Zs(()=>{if(!i)return;let r=Array.isArray(t)?t:[t],e=o=>{let u=o.target;r.some(f=>f.current?.contains(u))||n()};return document.addEventListener("pointerdown",e,!0),()=>{document.removeEventListener("pointerdown",e,!0)}},[t,n,i])}import{jsx as J,jsxs as Re}from"react/jsx-runtime";function Xt({anchorRef:t,onClose:n,children:i}){let r=so(null),[e,o]=lo(null);return _a([r,t],n,!0),Wa(()=>{let u=t.current;if(!u)return;let b=u.getBoundingClientRect(),f=222,C=8,M=Math.min(Math.max(b.right-f,C),window.innerWidth-f-C),m=Math.min(b.bottom+6,window.innerHeight-200);o({top:m,left:M})},[t]),e?Qs(J("div",{ref:r,className:"se-colorPickerPopover",style:{position:"fixed",top:e.top,left:e.left},children:i}),document.body):null}function al(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 it({title:t,children:n}){return Re("section",{className:"se-section",children:[J("h3",{className:"se-sectionTitle",children:t}),J("div",{className:"se-sectionBody",children:n})]})}function X({title:t,open:n,onToggle:i,trailing:r,children:e,disabled:o,tooltip:u}){let b=u?`${u}`:t;return Re("section",{className:"se-panel",children:[Re("button",{type:"button",className:"se-panelHeader",onClick:i,"aria-expanded":n,title:b,children:[Re("span",{className:"se-panelHeaderMain",children:[J(el,{size:16,className:`se-panelChevron ${n?"se-panelChevron--open":""}`}),J("span",{className:"se-panelTitle",children:t}),u?J("span",{className:"se-panelHelp",title:b,"aria-label":b,role:"img",onClick:f=>f.stopPropagation(),children:J(tl,{size:13})}):null]}),r?J("span",{className:"se-panelTrailing",onClick:f=>f.stopPropagation(),children:r}):null]}),n?J("div",{className:"se-panelBody",style:o?{opacity:.45,pointerEvents:"none"}:void 0,children:e}):null]})}function Q({checked:t,onChange:n,label:i}){return Re("label",{className:"se-switch","aria-label":i,children:[J("input",{type:"checkbox",checked:t,onChange:r=>n(r.target.checked)}),J("span",{className:"se-switchTrack",children:J("span",{className:"se-switchThumb"})})]})}function w({label:t,value:n,min:i,max:r,step:e,formatValue:o,onChange:u,disabled:b=!1}){return Re("label",{className:`se-field ${b?"se-field--disabled":""}`,children:[Re("span",{className:"se-fieldLabel",children:[t,J("span",{className:"se-fieldValue",children:o?o(n):n})]}),J("input",{className:"se-slider",type:"range",min:i,max:r,step:e,value:n,onChange:f=>u(Number(f.target.value)),disabled:b})]})}function Z({label:t,checked:n,onChange:i}){return Re("label",{className:"se-field se-fieldInline",children:[J("span",{className:"se-fieldLabel",children:t}),J("input",{type:"checkbox",className:"se-checkbox",checked:n,onChange:r=>i(r.target.checked)})]})}function ze({label:t,value:n,options:i,onChange:r}){return Re("label",{className:"se-field se-fieldInline",children:[J("span",{className:"se-fieldLabel",children:t}),J("select",{className:"se-select",value:n,onChange:e=>r(e.target.value),children:i.map(e=>J("option",{value:e,children:al(e)},e))})]})}function Ae({label:t,value:n,onChange:i}){let[r,e]=lo(!1),o=so(null);return Re("div",{className:"se-field",children:[Re("div",{className:"se-fieldInline",children:[J("span",{className:"se-fieldLabel",children:t}),J("span",{ref:o,style:{display:"inline-flex"},children:J(nl,{prefixed:!0,className:"se-swatch",onClick:()=>e(u=>!u),style:{background:n,color:pt(n)},color:n,onChange:i})})]}),r?J(Xt,{anchorRef:o,onClose:()=>e(!1),children:J(ol,{color:n,onChange:i})}):null]})}function Ya({value:t,min:n,max:i,step:r,onChange:e}){let[o,u]=lo(String(t)),b=so(!1);return Wa(()=>{b.current||u(String(t))},[t]),J("input",{type:"number",className:"se-numberInput",min:n,max:i,step:r,value:o,onFocus:()=>{b.current=!0},onChange:f=>{let C=f.target.value;u(C),C!==""&&C!=="-"&&!Number.isNaN(Number(C))&&e(Number(C))},onBlur:()=>{b.current=!1,u(String(t))}})}function ut({label:t,value:n,min:i,max:r,step:e,onChange:o}){return Re("div",{className:"se-field",children:[J("span",{className:"se-fieldLabel",children:t}),J("div",{className:"se-vectorRow",children:["X","Y","Z"].map((b,f)=>Re("label",{className:"se-vectorAxis",children:[J("span",{children:b}),J(Ya,{value:n[f],min:i,max:r,step:e,onChange:C=>{let M=[...n];M[f]=C,o(M)}})]},b))})]})}function wt({label:t,value:n,min:i,max:r,step:e,onChange:o}){return Re("div",{className:"se-field",children:[J("span",{className:"se-fieldLabel",children:t}),J("div",{className:"se-vectorRow",children:["X","Y"].map((b,f)=>Re("label",{className:"se-vectorAxis",children:[J("span",{children:b}),J(Ya,{value:n[f],min:i,max:r,step:e,onChange:C=>{let M=[...n];M[f]=C,o(M)}})]},b))})]})}var qa={free:0,starter:1,growth:2};function Ja(t){return t==="starter"||t==="growth"||t==="scale"?t==="scale"?"growth":t:"free"}function Ue(t,n){return qa[t]>=qa[n]}var Xa={free:"Free",starter:"Starter",growth:"Growth"};import{Lock as il}from"lucide-react";import{jsx as rl,jsxs as Za}from"react/jsx-runtime";function ke({requiredTier:t,feature:n}){return Za("div",{className:"bb-tierLock",children:[rl(il,{size:16}),Za("p",{className:"bb-tierLockMessage",children:[n," requires the ",Xa[t]," plan or higher."]})]})}import{Fragment as An,jsx as A,jsxs as ae}from"react/jsx-runtime";var ml=["lit","unlit","normals"],gl=["color","image","environment"];function Qa(t){let n=t%360;return n<0?n+360:n}function zt({title:t,open:n,onToggle:i,children:r,trailing:e}){return ae("section",{className:"se-panel",children:[ae("button",{type:"button",className:"se-panelHeader",onClick:i,"aria-expanded":n,children:[ae("span",{className:"se-panelHeaderMain",children:[A(ll,{size:16,className:`se-panelChevron ${n?"se-panelChevron--open":""}`}),A("span",{className:"se-panelTitle",children:t})]}),e?A("span",{className:"se-panelTrailing",onClick:o=>o.stopPropagation(),children:e}):null]}),n?A("div",{className:"se-panelBody",children:r}):null]})}function co({config:t,onChange:n,materialVariants:i=[]}){let{model:r,camera:e,wireframe:o,background:u,environment:b}=t,{tier:f}=Ze(),C=Ue(f,"starter"),[M,m]=sl({general:!0,camera:!0,autoRotate:!1,section:!1,wireframe:!1,background:!1}),l=c=>m(h=>({...h,[c]:!h[c]})),S=c=>n({...t,model:c}),B=c=>n({...t,camera:c}),v=t.section??Pa,F=c=>n({...t,section:{...v,...c}}),x=c=>n({...t,wireframe:c}),g=c=>n({...t,background:c}),N=c=>n({...t,environment:c}),z=c=>{N({...b,source:"preset",preset:c})};return ae("div",{className:"se-generalContent",children:[ae(zt,{title:"General",open:M.general,onToggle:()=>l("general"),children:[ae("div",{className:"se-field",children:[ae("div",{className:"se-fieldLabel",children:[A("span",{children:"Straighten model"}),A("button",{type:"button",className:"se-iconButton",onClick:()=>S({...r,rotation:[0,0,0]}),"aria-label":"Reset model rotation",children:A(bl,{size:16})})]}),A("div",{className:"se-axisStepperGrid",children:["X","Y","Z"].map((c,h)=>ae("div",{className:"se-axisStepper",children:[A("button",{type:"button",className:"se-axisStepperButton",onClick:()=>{let d=[...r.rotation];d[h]=Qa(d[h]-90),S({...r,rotation:d})},"aria-label":`Rotate ${c} axis backward`,children:A(dl,{size:16})}),A("span",{className:"se-axisStepperLabel",children:c}),A("button",{type:"button",className:"se-axisStepperButton",onClick:()=>{let d=[...r.rotation];d[h]=Qa(d[h]+90),S({...r,rotation:d})},"aria-label":`Rotate ${c} axis forward`,children:A(cl,{size:16})})]},c))})]}),A(ut,{label:"Rotation",value:r.rotation,min:0,max:360,step:1,onChange:c=>S({...r,rotation:c})}),ae("div",{className:"se-field",children:[A("span",{className:"se-fieldLabel",children:"Renderer"}),A("div",{className:"se-segmentedControl se-segmentedControl--renderer",children:Ca.map(c=>A("button",{type:"button",className:`se-segmentedOption ${r.renderer===c?"se-segmentedOption--active":""}`,onClick:()=>S({...r,renderer:c}),children:c==="uv-checker"?"UV CHECKER":c.toUpperCase()},c))})]}),A(ze,{label:"Shading",value:r.shading,options:ml,onChange:c=>S({...r,shading:c})}),i.length>0?ae("label",{className:"se-field se-fieldInline",children:[A("span",{className:"se-fieldLabel",children:"Material variant"}),ae("select",{className:"se-select",value:r.materialVariant??"",onChange:c=>S({...r,materialVariant:c.target.value||null}),children:[A("option",{value:"",children:"Model default"}),i.map(c=>A("option",{value:c,children:c},c)),r.materialVariant&&!i.includes(r.materialVariant)?ae("option",{value:r.materialVariant,children:[r.materialVariant," (not in this model)"]}):null]})]}):null]}),A(zt,{title:"Camera",open:M.camera,onToggle:()=>l("camera"),children:A(w,{label:"Field Of View",value:e.fieldOfView,min:20,max:100,step:.1,formatValue:c=>`${c.toFixed(3)}\xB0`,onChange:c=>B({...e,fieldOfView:c})})}),A(zt,{title:"Auto Rotate",open:M.autoRotate,onToggle:()=>l("autoRotate"),trailing:ae("label",{className:"se-switch","aria-label":"Toggle auto rotate",children:[A("input",{type:"checkbox",checked:r.autoRotate??!1,onChange:c=>S({...r,autoRotate:c.target.checked})}),A("span",{className:"se-switchTrack",children:A("span",{className:"se-switchThumb"})})]}),children:r.autoRotate?A(w,{label:"Rotation Speed",value:r.autoRotateSpeed??1,min:.1,max:3,step:.1,formatValue:c=>`${c.toFixed(1)}x`,onChange:c=>S({...r,autoRotateSpeed:c})}):A("div",{className:"se-placeholder",children:"Enable auto rotate to adjust its speed."})}),A(zt,{title:"Section Cut",open:M.section,onToggle:()=>l("section"),trailing:ae("label",{className:"se-switch","aria-label":"Toggle section cut",children:[A("input",{type:"checkbox",checked:v.enabled,onChange:c=>F({enabled:c.target.checked})}),A("span",{className:"se-switchTrack",children:A("span",{className:"se-switchThumb"})})]}),children:v.enabled?ae(An,{children:[ae("div",{className:"se-field",children:[A("span",{className:"se-fieldLabel",children:"Cut across"}),A("div",{className:"se-segmentedControl",children:Ta.map(c=>A("button",{type:"button",className:`se-segmentedOption ${v.axis===c?"se-segmentedOption--active":""}`,onClick:()=>F({axis:c}),children:c.toUpperCase()},c))})]}),A(w,{label:"Position",value:v.position,min:0,max:1,step:.01,formatValue:c=>`${Math.round(c*100)}%`,onChange:c=>F({position:c})}),A(Z,{label:"Keep the other side",checked:v.flip,onChange:c=>F({flip:c})})]}):A("div",{className:"se-placeholder",children:"Cut the model open to see inside. Drag the plane in the preview, or set it here."})}),A(zt,{title:"Wireframe",open:M.wireframe,onToggle:()=>l("wireframe"),trailing:ae("label",{className:"se-switch","aria-label":"Toggle wireframe preview",children:[A("input",{type:"checkbox",checked:C&&o.enabled,disabled:!C,onChange:c=>x({...o,enabled:c.target.checked})}),A("span",{className:"se-switchTrack",children:A("span",{className:"se-switchThumb"})})]}),children:C?ae(An,{children:[A(w,{label:"Opacity",value:o.opacity,min:0,max:1,step:.01,onChange:c=>x({...o,opacity:c})}),A(Ae,{label:"Wire color",value:o.color,onChange:c=>x({...o,color:c})})]}):A(ke,{requiredTier:"starter",feature:"Wireframe preview"})}),A(zt,{title:"Background",open:M.background,onToggle:()=>l("background"),trailing:ae("label",{className:"se-switch","aria-label":"Toggle scene background",children:[A("input",{type:"checkbox",checked:u.enabled,onChange:c=>g({...u,enabled:c.target.checked})}),A("span",{className:"se-switchTrack",children:A("span",{className:"se-switchThumb"})})]}),children:u.enabled?ae(An,{children:[ae("div",{className:"se-field",children:[A("span",{className:"se-fieldLabel",children:"Background type"}),A("div",{className:"se-segmentedControl",children:gl.map(c=>A("button",{type:"button",className:`se-segmentedOption ${u.type===c?"se-segmentedOption--active":""}`,onClick:()=>g({...u,type:c}),children:c},c))})]}),u.type==="environment"?C?ae(An,{children:[ae("div",{className:"se-field",children:[A("span",{className:"se-fieldLabel",children:"Environment source"}),ae("div",{className:"se-segmentedControl",children:[A("button",{type:"button",className:`se-segmentedOption ${b.source==="preset"?"se-segmentedOption--active":""}`,onClick:()=>N({...b,source:"preset"}),children:"PRESET"}),A("button",{type:"button",className:`se-segmentedOption ${b.source==="custom"?"se-segmentedOption--active":""}`,onClick:()=>N({...b,source:"custom"}),children:"CUSTOM"})]})]}),b.source==="preset"?A(ze,{label:"Environment preset",value:b.preset,options:Sa,onChange:z}):ae("label",{className:"se-field",children:[A("span",{className:"se-fieldLabel",children:"Custom environment URL"}),A("input",{type:"text",className:"se-textInput",placeholder:"https://example.com/environment.hdr",value:b.customEnvironmentUrl,onChange:c=>N({...b,customEnvironmentUrl:c.target.value})}),A("span",{className:"bb-note",children:"Enter a HDR, EXR, JPG, JPEG, PNG, or WEBP URL."}),b.customEnvironmentUrl.trim()&&!ya(b.customEnvironmentUrl)?A("span",{className:"bb-note",style:{color:"#fca5a5"},children:"Invalid image/HDRI URL."}):null]}),A(w,{label:"Environment intensity",value:b.intensity,min:0,max:3,step:.05,onChange:c=>N({...b,intensity:c})})]}):A(ke,{requiredTier:"starter",feature:"Environment backgrounds"}):null,u.type==="image"?ae("label",{className:"se-field",children:[A("span",{className:"se-fieldLabel",children:"Background image URL"}),A("input",{type:"text",className:"se-textInput",placeholder:"https://example.com/background.jpg",value:u.imageUrl,onChange:c=>g({...u,imageUrl:c.target.value})})]}):null,u.type==="color"?ae("div",{className:"se-field",children:[A("span",{className:"se-fieldLabel",children:"Background color"}),A("div",{className:"se-inlineColorPicker",children:A(ul,{color:u.color,onChange:c=>g({...u,color:c})})}),A("div",{className:"se-fieldInline",children:A(pl,{prefixed:!0,className:"se-swatch",style:{background:u.color,color:pt(u.color)},color:u.color,onChange:c=>g({...u,color:c})})})]}):null]}):A("div",{className:"se-placeholder",children:"Background rendering is disabled for this scene preset."})})]})}import{useState as hl}from"react";import{jsx as E,jsxs as Zt}from"react/jsx-runtime";function ei({pp:t,set:n,open:i,toggle:r}){let{ssao:e}=t;return Zt(X,{title:"SSAO",tooltip:"Adds soft contact shadows in corners, creases, and tight spaces.",open:i.ssao,onToggle:()=>r("ssao"),disabled:!e.enabled,trailing:E(Q,{checked:e.enabled,onChange:o=>n("ssao",{...e,enabled:o}),label:"Toggle SSAO"}),children:[E(w,{label:"Samples",value:e.samples,min:1,max:64,step:1,onChange:o=>n("ssao",{...e,samples:o})}),E(w,{label:"Rings",value:e.rings,min:1,max:12,step:1,onChange:o=>n("ssao",{...e,rings:o})}),E(w,{label:"Intensity",value:e.intensity,min:0,max:20,step:.5,onChange:o=>n("ssao",{...e,intensity:o})}),E(w,{label:"Radius",value:e.radius,min:.01,max:1,step:.01,onChange:o=>n("ssao",{...e,radius:o})}),E(w,{label:"Bias",value:e.bias,min:0,max:.1,step:.001,onChange:o=>n("ssao",{...e,bias:o})}),E(w,{label:"Luminance Influence",value:e.luminanceInfluence,min:0,max:1,step:.01,onChange:o=>n("ssao",{...e,luminanceInfluence:o})}),E(w,{label:"Fade",value:e.fade,min:0,max:.1,step:.001,onChange:o=>n("ssao",{...e,fade:o})}),E(w,{label:"Min Radius Scale",value:e.minRadiusScale,min:0,max:1,step:.01,onChange:o=>n("ssao",{...e,minRadiusScale:o})}),E(w,{label:"World Distance Threshold",value:e.worldDistanceThreshold,min:0,max:100,step:.1,onChange:o=>n("ssao",{...e,worldDistanceThreshold:o})}),E(w,{label:"World Distance Falloff",value:e.worldDistanceFalloff,min:0,max:20,step:.1,onChange:o=>n("ssao",{...e,worldDistanceFalloff:o})}),E(w,{label:"World Proximity Threshold",value:e.worldProximityThreshold,min:0,max:100,step:.1,onChange:o=>n("ssao",{...e,worldProximityThreshold:o})}),E(w,{label:"World Proximity Falloff",value:e.worldProximityFalloff,min:0,max:20,step:.1,onChange:o=>n("ssao",{...e,worldProximityFalloff:o})})]})}function ti({pp:t,set:n,open:i,toggle:r}){let{autofocus:e}=t;return Zt(X,{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:E(Q,{checked:e.enabled,onChange:o=>n("autofocus",{...e,enabled:o}),label:"Toggle Autofocus"}),children:[E(w,{label:"Focus Distance",value:e.focusDistance,min:0,max:50,step:.1,onChange:o=>n("autofocus",{...e,focusDistance:o})}),E(w,{label:"Focus Range",value:e.focusRange,min:.1,max:50,step:.1,onChange:o=>n("autofocus",{...e,focusRange:o})}),E(w,{label:"Focal Length",value:e.focalLength,min:0,max:1,step:.01,onChange:o=>n("autofocus",{...e,focalLength:o})}),E(w,{label:"Bokeh Scale",value:e.bokehScale,min:0,max:20,step:.1,onChange:o=>n("autofocus",{...e,bokehScale:o})}),E(ut,{label:"Target",value:e.target,min:-100,max:100,step:.1,onChange:o=>n("autofocus",{...e,target:o})}),E(Z,{label:"Mouse Follow",checked:e.mouse,onChange:o=>n("autofocus",{...e,mouse:o})}),E(Z,{label:"Manual Update",checked:e.manual,onChange:o=>n("autofocus",{...e,manual:o})}),E(w,{label:"Debug",value:e.debug,min:0,max:1,step:.01,onChange:o=>n("autofocus",{...e,debug:o})}),E(w,{label:"Smooth Time",value:e.smoothTime,min:0,max:2,step:.01,onChange:o=>n("autofocus",{...e,smoothTime:o})})]})}function ni({pp:t,set:n,open:i,toggle:r}){let{godRays:e}=t;return Zt(X,{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:E(Q,{checked:e.enabled,onChange:o=>n("godRays",{...e,enabled:o}),label:"Toggle GodRays"}),children:[E(ut,{label:"Sun Position",value:e.sunPosition,min:-100,max:100,step:.1,onChange:o=>n("godRays",{...e,sunPosition:o})}),E(w,{label:"Samples",value:e.samples,min:1,max:128,step:1,onChange:o=>n("godRays",{...e,samples:o})}),E(w,{label:"Density",value:e.density,min:0,max:2,step:.01,onChange:o=>n("godRays",{...e,density:o})}),E(w,{label:"Decay",value:e.decay,min:0,max:1,step:.01,onChange:o=>n("godRays",{...e,decay:o})}),E(w,{label:"Weight",value:e.weight,min:0,max:2,step:.01,onChange:o=>n("godRays",{...e,weight:o})}),E(w,{label:"Exposure",value:e.exposure,min:0,max:2,step:.01,onChange:o=>n("godRays",{...e,exposure:o})}),E(w,{label:"Clamp Max",value:e.clampMax,min:0,max:2,step:.01,onChange:o=>n("godRays",{...e,clampMax:o})}),E(Z,{label:"Blur",checked:e.blur,onChange:o=>n("godRays",{...e,blur:o})}),E(ze,{label:"Kernel Size",value:e.kernelSize,options:Wt,onChange:o=>n("godRays",{...e,kernelSize:o})})]})}function oi({pp:t,set:n,open:i,toggle:r}){let{lensflare:e}=t;return Zt(X,{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:E(Q,{checked:e.enabled,onChange:o=>n("lensflare",{...e,enabled:o}),label:"Toggle Lensflare"}),children:[E(ut,{label:"Lens Position",value:e.lensPosition,min:-100,max:100,step:.1,onChange:o=>n("lensflare",{...e,lensPosition:o})}),E(w,{label:"Smooth Time",value:e.smoothTime,min:0,max:1,step:.01,onChange:o=>n("lensflare",{...e,smoothTime:o})}),E(w,{label:"Glare Size",value:e.glareSize,min:0,max:1,step:.01,onChange:o=>n("lensflare",{...e,glareSize:o})}),E(w,{label:"Flare Size",value:e.flareSize,min:0,max:.1,step:.001,onChange:o=>n("lensflare",{...e,flareSize:o})}),E(w,{label:"Flare Speed",value:e.flareSpeed,min:0,max:.2,step:.001,onChange:o=>n("lensflare",{...e,flareSpeed:o})}),E(w,{label:"Flare Shape",value:e.flareShape,min:0,max:.2,step:.001,onChange:o=>n("lensflare",{...e,flareShape:o})}),E(Z,{label:"Animated",checked:e.animated,onChange:o=>n("lensflare",{...e,animated:o})}),E(Z,{label:"Anamorphic",checked:e.anamorphic,onChange:o=>n("lensflare",{...e,anamorphic:o})}),E(Ae,{label:"Color Gain",value:e.colorGain,onChange:o=>n("lensflare",{...e,colorGain:o})}),E(w,{label:"Halo Scale",value:e.haloScale,min:0,max:2,step:.01,onChange:o=>n("lensflare",{...e,haloScale:o})}),E(Z,{label:"Secondary Ghosts",checked:e.secondaryGhosts,onChange:o=>n("lensflare",{...e,secondaryGhosts:o})}),E(Z,{label:"Additional Streaks",checked:e.aditionalStreaks,onChange:o=>n("lensflare",{...e,aditionalStreaks:o})}),E(w,{label:"Ghost Scale",value:e.ghostScale,min:0,max:1,step:.01,onChange:o=>n("lensflare",{...e,ghostScale:o})}),E(w,{label:"Opacity",value:e.opacity,min:0,max:1,step:.01,onChange:o=>n("lensflare",{...e,opacity:o})}),E(Z,{label:"Star Burst",checked:e.starBurst,onChange:o=>n("lensflare",{...e,starBurst:o})})]})}function ai({pp:t,set:n,open:i,toggle:r}){let{depthOfField:e}=t;return Zt(X,{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:E(Q,{checked:e.enabled,onChange:o=>n("depthOfField",{...e,enabled:o}),label:"Toggle DepthOfField"}),children:[E(w,{label:"Focus Distance",value:e.focusDistance,min:0,max:50,step:.1,onChange:o=>n("depthOfField",{...e,focusDistance:o})}),E(w,{label:"Focus Range",value:e.focusRange,min:.1,max:50,step:.1,onChange:o=>n("depthOfField",{...e,focusRange:o})}),E(w,{label:"Focal Length",value:e.focalLength,min:0,max:1,step:.01,onChange:o=>n("depthOfField",{...e,focalLength:o})}),E(w,{label:"Bokeh Scale",value:e.bokehScale,min:0,max:20,step:.1,onChange:o=>n("depthOfField",{...e,bokehScale:o})})]})}import{jsx as q,jsxs as Lt}from"react/jsx-runtime";var fl=["linear","reinhard","aces"];function ii({pp:t,set:n,open:i,toggle:r}){let{colorAverage:e}=t;return q(X,{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:q(Q,{checked:e.enabled,onChange:o=>n("colorAverage",{...e,enabled:o}),label:"Toggle ColorAverage"}),children:q("div",{className:"se-placeholder",children:"Averages the frame color using the docs default blend mode."})})}function ri({pp:t,set:n,open:i,toggle:r}){let{brightnessContrast:e}=t;return Lt(X,{title:"Brightness Contrast",tooltip:"Raises or lowers overall brightness and contrast across the scene.",open:i.brightnessContrast,onToggle:()=>r("brightnessContrast"),disabled:!e.enabled,trailing:q(Q,{checked:e.enabled,onChange:o=>n("brightnessContrast",{...e,enabled:o}),label:"Toggle BrightnessContrast"}),children:[q(w,{label:"Brightness",value:e.brightness,min:-1,max:1,step:.01,onChange:o=>n("brightnessContrast",{...e,brightness:o})}),q(w,{label:"Contrast",value:e.contrast,min:-1,max:1,step:.01,onChange:o=>n("brightnessContrast",{...e,contrast:o})})]})}function si({pp:t,set:n,open:i,toggle:r}){let{hueSaturation:e}=t;return Lt(X,{title:"Hue Saturation",tooltip:"Shifts the hue and saturation to tint the whole image.",open:i.hueSaturation,onToggle:()=>r("hueSaturation"),disabled:!e.enabled,trailing:q(Q,{checked:e.enabled,onChange:o=>n("hueSaturation",{...e,enabled:o}),label:"Toggle HueSaturation"}),children:[q(w,{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})}),q(w,{label:"Saturation",value:e.saturation,min:-1,max:1,step:.01,onChange:o=>n("hueSaturation",{...e,saturation:o})})]})}function li({pp:t,set:n,open:i,toggle:r}){let{vignette:e}=t;return Lt(X,{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:q(Q,{checked:e.enabled,onChange:o=>n("vignette",{...e,enabled:o}),label:"Toggle Vignette"}),children:[q(w,{label:"Offset",value:e.offset,min:0,max:1,step:.01,onChange:o=>n("vignette",{...e,offset:o})}),q(w,{label:"Darkness",value:e.darkness,min:0,max:1,step:.01,onChange:o=>n("vignette",{...e,darkness:o})}),q(Z,{label:"Eskil",checked:e.eskil,onChange:o=>n("vignette",{...e,eskil:o})})]})}function di({pp:t,set:n,open:i,toggle:r}){let{bloom:e}=t;return Lt(X,{title:"Bloom",tooltip:"Makes bright areas glow and bleed softly into nearby pixels.",open:i.bloom,onToggle:()=>r("bloom"),disabled:!e.enabled,trailing:q(Q,{checked:e.enabled,onChange:o=>n("bloom",{...e,enabled:o}),label:"Toggle Bloom"}),children:[q(w,{label:"Threshold",value:e.luminanceThreshold,min:0,max:1,step:.01,onChange:o=>n("bloom",{...e,luminanceThreshold:o})}),q(w,{label:"Smoothing",value:e.luminanceSmoothing,min:0,max:1,step:.01,onChange:o=>n("bloom",{...e,luminanceSmoothing:o})}),q(w,{label:"Intensity",value:e.intensity,min:0,max:3,step:.05,onChange:o=>n("bloom",{...e,intensity:o})}),q(Z,{label:"Mipmap Blur",checked:e.mipmapBlur,onChange:o=>n("bloom",{...e,mipmapBlur:o})}),q(w,{label:"Radius",value:e.radius,min:0,max:1,step:.01,onChange:o=>n("bloom",{...e,radius:o})}),q(w,{label:"Levels",value:e.levels,min:1,max:16,step:1,onChange:o=>n("bloom",{...e,levels:o})})]})}function ci({pp:t,set:n,open:i,toggle:r}){let{toneMapping:e}=t;return Lt(X,{title:"Tone Mapping",tooltip:"Remaps HDR lighting to screen output and controls exposure style.",open:i.toneMapping,onToggle:()=>r("toneMapping"),disabled:!e.enabled,trailing:q(Q,{checked:e.enabled,onChange:o=>n("toneMapping",{...e,enabled:o}),label:"Toggle ToneMapping"}),children:[Lt("div",{className:"se-field",children:[q("span",{className:"se-fieldLabel",children:"Mode"}),q("div",{className:"se-segmentedControl",children:fl.map(o=>q("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))})]}),q(w,{label:"Resolution",value:e.resolution,min:64,max:4096,step:64,onChange:o=>n("toneMapping",{...e,resolution:o})}),q(w,{label:"White Point",value:e.whitePoint,min:0,max:16,step:.01,onChange:o=>n("toneMapping",{...e,whitePoint:o})}),q(w,{label:"Middle Grey",value:e.middleGrey,min:0,max:1,step:.01,onChange:o=>n("toneMapping",{...e,middleGrey:o})}),q(w,{label:"Min Luminance",value:e.minLuminance,min:0,max:1,step:.01,onChange:o=>n("toneMapping",{...e,minLuminance:o})}),q(w,{label:"Average Luminance",value:e.averageLuminance,min:0,max:4,step:.01,onChange:o=>n("toneMapping",{...e,averageLuminance:o})}),q(w,{label:"Adaptation Rate",value:e.adaptationRate,min:0,max:10,step:.01,onChange:o=>n("toneMapping",{...e,adaptationRate:o})}),q(w,{label:"Exposure",value:e.exposure,min:0,max:3,step:.01,onChange:o=>n("toneMapping",{...e,exposure:o})})]})}function bi({pp:t,set:n,open:i,toggle:r}){let{sepia:e}=t;return q(X,{title:"Sepia",tooltip:"Adds a warm vintage brown tint to the entire image.",open:i.sepia,onToggle:()=>r("sepia"),disabled:!e.enabled,trailing:q(Q,{checked:e.enabled,onChange:o=>n("sepia",{...e,enabled:o}),label:"Toggle Sepia"}),children:q(w,{label:"Intensity",value:e.intensity,min:0,max:1,step:.01,onChange:o=>n("sepia",{...e,intensity:o})})})}import{jsx as $,jsxs as Et}from"react/jsx-runtime";function pi({pp:t,set:n,open:i,toggle:r}){let{dotScreen:e}=t;return Et(X,{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:$(Q,{checked:e.enabled,onChange:o=>n("dotScreen",{...e,enabled:o}),label:"Toggle DotScreen"}),children:[$(w,{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})}),$(w,{label:"Scale",value:e.scale,min:.1,max:10,step:.05,onChange:o=>n("dotScreen",{...e,scale:o})})]})}function ui({pp:t,set:n,open:i,toggle:r}){let{glitch:e}=t;return Et(X,{title:"Glitch",tooltip:"Introduces digital distortion, tearing, and scan noise.",open:i.glitch,onToggle:()=>r("glitch"),disabled:!e.enabled,trailing:$(Q,{checked:e.enabled,onChange:o=>n("glitch",{...e,enabled:o}),label:"Toggle Glitch"}),children:[$(ze,{label:"Mode",value:e.mode,options:ka,onChange:o=>n("glitch",{...e,mode:o})}),$(wt,{label:"Delay",value:e.delay,min:0,max:10,step:.01,onChange:o=>n("glitch",{...e,delay:o})}),$(wt,{label:"Duration",value:e.duration,min:0,max:5,step:.01,onChange:o=>n("glitch",{...e,duration:o})}),$(wt,{label:"Strength",value:e.strength,min:0,max:2,step:.01,onChange:o=>n("glitch",{...e,strength:o})}),$(wt,{label:"Chromatic Aberration Offset",value:e.chromaticAberrationOffset,min:0,max:.02,step:1e-4,onChange:o=>n("glitch",{...e,chromaticAberrationOffset:o})}),$(w,{label:"Columns",value:e.columns,min:0,max:.5,step:.001,onChange:o=>n("glitch",{...e,columns:o})}),$(w,{label:"Ratio",value:e.ratio,min:0,max:1,step:.01,onChange:o=>n("glitch",{...e,ratio:o})})]})}function mi({pp:t,set:n,open:i,toggle:r}){let{grid:e}=t;return Et(X,{title:"Grid",tooltip:"Adds a visual grid overlay that feels retro or debug-like.",open:i.grid,onToggle:()=>r("grid"),disabled:!e.enabled,trailing:$(Q,{checked:e.enabled,onChange:o=>n("grid",{...e,enabled:o}),label:"Toggle Grid"}),children:[$(w,{label:"Scale",value:e.scale,min:.1,max:10,step:.05,onChange:o=>n("grid",{...e,scale:o})}),$(w,{label:"Line Width",value:e.lineWidth,min:0,max:1,step:.01,onChange:o=>n("grid",{...e,lineWidth:o})})]})}function gi({pp:t,set:n,open:i,toggle:r}){let{chromaticAberration:e}=t;return Et(X,{title:"Chromatic Aberration",tooltip:"Separates color channels slightly to mimic lens fringing.",open:i.chromaticAberration,onToggle:()=>r("chromaticAberration"),disabled:!e.enabled,trailing:$(Q,{checked:e.enabled,onChange:o=>n("chromaticAberration",{...e,enabled:o}),label:"Toggle ChromaticAberration"}),children:[$(w,{label:"Offset X",value:e.offsetX,min:0,max:.02,step:1e-4,onChange:o=>n("chromaticAberration",{...e,offsetX:o})}),$(w,{label:"Offset Y",value:e.offsetY,min:0,max:.02,step:1e-4,onChange:o=>n("chromaticAberration",{...e,offsetY:o})}),$(Z,{label:"Radial Modulation",checked:e.radialModulation,onChange:o=>n("chromaticAberration",{...e,radialModulation:o})}),$(w,{label:"Modulation Offset",value:e.modulationOffset,min:0,max:1,step:.01,onChange:o=>n("chromaticAberration",{...e,modulationOffset:o})})]})}function fi({pp:t,set:n,open:i,toggle:r}){let{noise:e}=t;return Et(X,{title:"Noise",tooltip:"Adds film grain or static noise to the rendered image.",open:i.noise,onToggle:()=>r("noise"),disabled:!e.enabled,trailing:$(Q,{checked:e.enabled,onChange:o=>n("noise",{...e,enabled:o}),label:"Toggle Noise"}),children:[$(w,{label:"Amount",value:e.opacity,min:0,max:1,step:.01,onChange:o=>n("noise",{...e,opacity:o})}),$(Z,{label:"Premultiply",checked:e.premultiply,onChange:o=>n("noise",{...e,premultiply:o})})]})}function hi({pp:t,set:n,open:i,toggle:r}){let{scanline:e}=t;return $(X,{title:"Scan Line",tooltip:"Draws horizontal CRT-style scan lines over the frame.",open:i.scanline,onToggle:()=>r("scanline"),disabled:!e.enabled,trailing:$(Q,{checked:e.enabled,onChange:o=>n("scanline",{...e,enabled:o}),label:"Toggle Scanline"}),children:$(w,{label:"Density",value:e.density,min:0,max:10,step:.25,onChange:o=>n("scanline",{...e,density:o})})})}function xi({pp:t,set:n,open:i,toggle:r}){let{pixelation:e}=t;return $(X,{title:"Pixelation",tooltip:"Reduces detail into larger pixels for a blocky stylized effect.",open:i.pixelation,onToggle:()=>r("pixelation"),disabled:!e.enabled,trailing:$(Q,{checked:e.enabled,onChange:o=>n("pixelation",{...e,enabled:o}),label:"Toggle Pixelation"}),children:$(w,{label:"Granularity",value:e.granularity,min:0,max:20,step:1,onChange:o=>n("pixelation",{...e,granularity:o})})})}function vi({pp:t,set:n,open:i,toggle:r}){let{ramp:e}=t;return Et(X,{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:$(Q,{checked:e.enabled,onChange:o=>n("ramp",{...e,enabled:o}),label:"Toggle Ramp"}),children:[$(ze,{label:"Ramp Type",value:e.rampType,options:Na,onChange:o=>n("ramp",{...e,rampType:o})}),$(wt,{label:"Ramp Start",value:e.rampStart,min:0,max:1,step:.01,onChange:o=>n("ramp",{...e,rampStart:o})}),$(wt,{label:"Ramp End",value:e.rampEnd,min:0,max:1,step:.01,onChange:o=>n("ramp",{...e,rampEnd:o})}),$(Ae,{label:"Start Color",value:e.startColor,onChange:o=>n("ramp",{...e,startColor:o})}),$(Ae,{label:"End Color",value:e.endColor,onChange:o=>n("ramp",{...e,endColor:o})}),!e.rampMask&&$(w,{label:"Gradient Opacity",value:e.opacity??.5,min:0,max:1,step:.01,onChange:o=>n("ramp",{...e,opacity:o})}),$(w,{label:"Bias",value:e.rampBias,min:0,max:1,step:.01,onChange:o=>n("ramp",{...e,rampBias:o})}),$(w,{label:"Gain",value:e.rampGain,min:0,max:1,step:.01,onChange:o=>n("ramp",{...e,rampGain:o})}),$(Z,{label:"Mask Earlier Effects",checked:e.rampMask,onChange:o=>n("ramp",{...e,rampMask:o})}),$(Z,{label:"Invert",checked:e.rampInvert,onChange:o=>n("ramp",{...e,rampInvert:o})})]})}import{jsx as ce,jsxs as Si}from"react/jsx-runtime";function yi({pp:t,set:n,open:i,toggle:r}){let{outline:e}=t;return Si(X,{title:"Outline",tooltip:"Draws a visible edge around the selected object binding.",open:i.outline,onToggle:()=>r("outline"),disabled:!e.enabled,trailing:ce(Q,{checked:e.enabled,onChange:o=>n("outline",{...e,enabled:o}),label:"Toggle Outline"}),children:[ce("div",{className:"se-placeholder",children:"Outlines the currently selected object binding in the model editor."}),ce(w,{label:"Selection Layer",value:e.selectionLayer,min:0,max:20,step:1,onChange:o=>n("outline",{...e,selectionLayer:o})}),ce(w,{label:"Edge Strength",value:e.edgeStrength,min:0,max:10,step:.1,onChange:o=>n("outline",{...e,edgeStrength:o})}),ce(w,{label:"Pulse Speed",value:e.pulseSpeed,min:0,max:10,step:.1,onChange:o=>n("outline",{...e,pulseSpeed:o})}),ce(Ae,{label:"Visible Edge Color",value:e.visibleEdgeColor,onChange:o=>n("outline",{...e,visibleEdgeColor:o})}),ce(Ae,{label:"Hidden Edge Color",value:e.hiddenEdgeColor,onChange:o=>n("outline",{...e,hiddenEdgeColor:o})}),ce(ze,{label:"Kernel Size",value:e.kernelSize,options:Wt,onChange:o=>n("outline",{...e,kernelSize:o})}),ce(Z,{label:"Blur",checked:e.blur,onChange:o=>n("outline",{...e,blur:o})}),ce(Z,{label:"X-Ray",checked:e.xRay,onChange:o=>n("outline",{...e,xRay:o})})]})}function wi({pp:t,set:n,open:i,toggle:r}){let{selectiveBloom:e}=t;return Si(X,{title:"Selective Bloom",tooltip:"Applies bloom only to objects assigned to the selected layer.",open:i.selectiveBloom,onToggle:()=>r("selectiveBloom"),disabled:!e.enabled,trailing:ce(Q,{checked:e.enabled,onChange:o=>n("selectiveBloom",{...e,enabled:o}),label:"Toggle SelectiveBloom"}),children:[ce("div",{className:"se-placeholder",children:"Applies bloom to the currently selected object binding."}),ce(w,{label:"Selection Layer",value:e.selectionLayer,min:0,max:20,step:1,onChange:o=>n("selectiveBloom",{...e,selectionLayer:o})}),ce(w,{label:"Intensity",value:e.intensity,min:0,max:5,step:.05,onChange:o=>n("selectiveBloom",{...e,intensity:o})}),ce(w,{label:"Threshold",value:e.luminanceThreshold,min:0,max:1,step:.01,onChange:o=>n("selectiveBloom",{...e,luminanceThreshold:o})}),ce(w,{label:"Smoothing",value:e.luminanceSmoothing,min:0,max:1,step:.01,onChange:o=>n("selectiveBloom",{...e,luminanceSmoothing:o})}),ce(ze,{label:"Kernel Size",value:e.kernelSize,options:Wt,onChange:o=>n("selectiveBloom",{...e,kernelSize:o})}),ce(Z,{label:"Mipmap Blur",checked:e.mipmapBlur,onChange:o=>n("selectiveBloom",{...e,mipmapBlur:o})}),ce(Z,{label:"Inverted",checked:e.inverted,onChange:o=>n("selectiveBloom",{...e,inverted:o})}),ce(Z,{label:"Ignore Background",checked:e.ignoreBackground,onChange:o=>n("selectiveBloom",{...e,ignoreBackground:o})})]})}function Ci({pp:t,set:n,open:i,toggle:r}){let{smaa:e}=t;return ce(X,{title:"SMAA",tooltip:"Reduces jagged edges with subpixel anti-aliasing.",open:i.smaa,onToggle:()=>r("smaa"),trailing:ce(Q,{checked:e.enabled,onChange:o=>n("smaa",{...e,enabled:o}),label:"Toggle SMAA"}),children:ce("div",{className:"se-placeholder",children:"Subpixel Morphological Anti-Aliasing smooths jagged edges in post-process."})})}import{jsx as be,jsxs as xl}from"react/jsx-runtime";function bo({config:t,onChange:n}){let[i,r]=hl({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=f=>r(C=>({...C,[f]:!C[f]})),o=t.postProcessing,b={pp:o,set:(f,C)=>n({...t,postProcessing:{...o,[f]:C}}),open:i,toggle:e};return xl("div",{className:"se-generalContent",children:[be(ei,{...b}),be(ti,{...b}),be(ii,{...b}),be(pi,{...b}),be(ui,{...b}),be(ni,{...b}),be(mi,{...b}),be(oi,{...b}),be(yi,{...b}),be(wi,{...b}),be(ri,{...b}),be(si,{...b}),be(ai,{...b}),be(gi,{...b}),be(li,{...b}),be(di,{...b}),be(ci,{...b}),be(fi,{...b}),be(bi,{...b}),be(hi,{...b}),be(xi,{...b}),be(vi,{...b}),be(Ci,{...b})]})}import{useState as ki,useSyncExternalStore as vl}from"react";import{Eye as yl,EyeOff as wl,Plus as Cl,Trash2 as Sl}from"lucide-react";import{Fragment as Ni,jsx as G,jsxs as Le}from"react/jsx-runtime";var kl=["512","1024","2048","4096"],Ti={none:"None",directional:"Direction",point:"Point",spot:"Spot",hemisphere:"Hemi"};function Nl({index:t,light:n,selected:i,onSelect:r,onToggleVisible:e}){return Le("div",{className:`se-lightRow ${i?"se-lightRow--active":""}`,onClick:r,children:[Le("span",{className:"se-lightRowLabel",children:[t+1,": ",Ti[n.type]]}),G("button",{type:"button",className:"se-iconButton","aria-label":n.visible?"Hide light":"Show light",onClick:o=>{o.stopPropagation(),e()},children:n.visible?G(yl,{size:14}):G(wl,{size:14})})]})}function Tl(){return{id:crypto.randomUUID(),type:"directional",color:"#ffffff",intensity:1,position:[5,10,5],attachedToCamera:!1,castShadow:!1,shadowBias:-5e-4,visible:!0}}function po({config:t,onChange:n}){let[i,r]=ki({lights:!0,shadows:!1,groundShadows:!1,environment:!1,envShadow:!1}),e=vl(ja,Da),[o,u]=ki(t.lighting.lights[0]?.id??null),b=e??o,f=a=>{u(a),Ea(a)},C=a=>r(R=>({...R,[a]:!R[a]})),{tier:M}=Ze(),m=Ue(M,"starter"),{lighting:l,shadows:S,groundShadows:B,environment:v}=t,F=a=>n({...t,lighting:a}),x=a=>n({...t,shadows:a}),g=a=>n({...t,groundShadows:a}),N=a=>n({...t,environment:a}),z=(a,R)=>{F({...l,lights:l.lights.map(H=>H.id===a?{...H,...R}:H)})},c=l.lights.find(a=>a.id===b)??null,h=()=>{let a=Tl();F({...l,lights:[...l.lights,a]}),f(a.id)},d=()=>{if(!c)return;let a=l.lights.filter(R=>R.id!==c.id);F({...l,lights:a}),f(a[0]?.id??null)};return Le("div",{className:"se-generalContent",children:[Le(X,{title:"Lights",open:i.lights,onToggle:()=>C("lights"),children:[G("div",{className:"se-lightList",children:l.lights.map((a,R)=>G(Nl,{index:R,light:a,selected:a.id===b,onSelect:()=>f(a.id),onToggleVisible:()=>z(a.id,{visible:!a.visible})},a.id))}),Le("div",{className:"se-lightActions",children:[G("button",{type:"button",className:"se-iconButton",onClick:h,title:"Add light",children:G(Cl,{size:14})}),c&&l.lights.length>1&&G("button",{type:"button",className:"se-iconButton",onClick:d,title:"Remove selected light",children:G(Sl,{size:14})})]}),c?Le("div",{className:"se-lightProps",children:[Le("div",{className:"se-field",children:[G("span",{className:"se-fieldLabel",children:"Type"}),G("div",{className:"se-segmentedControl",style:{gridAutoColumns:"1fr"},children:wa.map(a=>G("button",{type:"button",className:`se-segmentedOption ${c.type===a?"se-segmentedOption--active":""}`,onClick:()=>z(c.id,{type:a}),children:Ti[a]},a))})]}),G(Ae,{label:"Color",value:c.color,onChange:a=>z(c.id,{color:a})}),G(w,{label:"Intensity",value:c.intensity,min:0,max:10,step:.1,onChange:a=>z(c.id,{intensity:a})}),c.type!=="hemisphere"&&c.type!=="none"&&G(ut,{label:"Position",value:c.position,min:-100,max:100,step:.05,onChange:a=>z(c.id,{position:a})}),c.type==="spot"&&Le(Ni,{children:[G(w,{label:"Angle",value:c.angle??Math.PI/6,min:0,max:Math.PI/2,step:.01,formatValue:a=>`${Math.round(a*180/Math.PI)}\xB0`,onChange:a=>z(c.id,{angle:a})}),G(w,{label:"Penumbra",value:c.penumbra??.2,min:0,max:1,step:.01,onChange:a=>z(c.id,{penumbra:a})}),G(w,{label:"Distance",value:c.distance??0,min:0,max:100,step:.5,onChange:a=>z(c.id,{distance:a})}),G(w,{label:"Decay",value:c.decay??2,min:0,max:4,step:.1,onChange:a=>z(c.id,{decay:a})})]}),G(Z,{label:"Attached to camera",checked:c.attachedToCamera,onChange:a=>z(c.id,{attachedToCamera:a})}),G(Z,{label:"Cast shadows",checked:c.castShadow,onChange:a=>z(c.id,{castShadow:a})}),G(w,{label:"Shadow bias",value:c.shadowBias,min:-.01,max:.01,step:1e-4,onChange:a=>z(c.id,{shadowBias:a})})]}):null]}),Le(X,{title:"Shadows",open:i.shadows,onToggle:()=>C("shadows"),disabled:!S.enabled,trailing:G(Q,{checked:S.enabled,onChange:a=>x({...S,enabled:a}),label:"Toggle shadows"}),children:[G(ze,{label:"Map size",value:String(S.mapSize),options:kl,onChange:a=>x({...S,mapSize:Number(a)})}),G(w,{label:"Bias",value:S.bias,min:-.01,max:.01,step:1e-4,onChange:a=>x({...S,bias:a})}),G(w,{label:"Normal bias",value:S.normalBias,min:0,max:.2,step:.01,onChange:a=>x({...S,normalBias:a})}),G(w,{label:"Radius (softness)",value:S.radius,min:0,max:20,step:.5,onChange:a=>x({...S,radius:a})})]}),Le(X,{title:"Ground Shadows",open:i.groundShadows,onToggle:()=>C("groundShadows"),disabled:!B.enabled,trailing:G(Q,{checked:B.enabled,onChange:a=>g({...B,enabled:a}),label:"Toggle ground shadows"}),children:[Le("div",{className:"se-field",children:[G("span",{className:"se-fieldLabel",children:"Mode"}),G("div",{className:"se-segmentedControl",style:{gridAutoColumns:"1fr"},children:["shadowCatcher"].map(a=>G("button",{type:"button",className:`se-segmentedOption ${B.mode===a?"se-segmentedOption--active":""}`,onClick:()=>g({...B,mode:a}),children:a==="shadowCatcher"?"Shadow Catcher":"Baked AO"},a))})]}),B.mode==="bakedAO"&&G("div",{className:"se-placeholder",children:"Requires pre-baked AO textures \u2014 not yet available."}),G(w,{label:"Intensity",value:B.intensity,min:0,max:1,step:.01,onChange:a=>g({...B,intensity:a})}),G(w,{label:"Border fade",value:B.borderFade,min:0,max:10,step:.1,onChange:a=>g({...B,borderFade:a})}),G(w,{label:"Height",value:B.height,min:-5,max:5,step:.1,onChange:a=>g({...B,height:a})}),G(w,{label:"Size",value:B.size,min:1,max:50,step:.5,onChange:a=>g({...B,size:a})})]}),G(X,{title:"Environment",open:i.environment,onToggle:()=>C("environment"),children:m?Le(Ni,{children:[G(w,{label:"Orientation",value:v.rotation,min:0,max:360,step:1,formatValue:a=>`${a}\xB0`,onChange:a=>N({...v,rotation:a})}),G(w,{label:"Brightness",value:v.intensity,min:0,max:3,step:.05,onChange:a=>N({...v,intensity:a})}),Le(X,{title:"Shadow",open:i.envShadow,onToggle:()=>C("envShadow"),trailing:G(Q,{checked:v.shadowLight.enabled,onChange:a=>N({...v,shadowLight:{...v.shadowLight,enabled:a}}),label:"Toggle environment shadow light"}),disabled:!v.shadowLight.enabled,children:[G(w,{label:"Light intensity",value:v.shadowLight.intensity,min:0,max:20,step:.1,onChange:a=>N({...v,shadowLight:{...v.shadowLight,intensity:a}})}),G(w,{label:"Shadow bias",value:v.shadowLight.bias,min:-.01,max:.01,step:1e-4,onChange:a=>N({...v,shadowLight:{...v.shadowLight,bias:a}})})]})]}):G(ke,{requiredTier:"starter",feature:"Environment lighting"})})]})}import{useMemo as Pl,useState as Bl}from"react";import{ChevronDown as Rl,Pause as Pi,Play as Ml,Rewind as Al,Square as Ol,Trash2 as zl}from"lucide-react";import{jsx as W,jsxs as pe}from"react/jsx-runtime";var Ll={playing:"Playing",paused:"Paused",finished:"Finished"},Bi={repeat:"Looping",once:"Play once","ping-pong":"Ping-pong"};function El(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 Ri(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 jl(t){return Number.isFinite(t)?Math.min(3,Math.max(.1,Number(t.toFixed(2)))):1}function uo({config:t,onChange:n,clipDetails:i,active:r,play:e,pause:o,stop:u,setSpeed:b,seek:f}){let[C,M]=Bl(!1),m=Pl(()=>new Map(i.map(h=>[h.sourceName,h.duration])),[i]),l=t.animations.clips.filter(h=>!h.hidden),S=t.animations.clips.filter(h=>h.hidden),B=(h,d=t.animations.autoplayClip)=>{n({...t,animations:{clips:h(t.animations.clips),autoplayClip:d}})},v=(h,d)=>{B(a=>a.map(R=>R.sourceName===h?d(R):R))},F=(h,d)=>{v(h,a=>({...a,loopMode:d}))},x=(h,d)=>{let a=jl(d);v(h,R=>({...R,speed:a})),r.some(R=>R.clip===h)&&b(a,h)},g=(h,d)=>{v(h,a=>({...a,displayName:d}))},N=h=>{let d=t.animations.autoplayClip===h?null:h;n({...t,animations:{...t.animations,autoplayClip:d}})},z=h=>{B(d=>d.map(a=>a.sourceName===h?{...a,hidden:!0}:a),t.animations.autoplayClip===h?null:t.animations.autoplayClip),r.some(d=>d.clip===h)&&u(h)},c=h=>{B(d=>d.map(a=>a.sourceName===h?{...a,hidden:!1}:a))};return t.animations.clips.length===0?W(it,{title:"Animations",children:W("div",{className:"se-helperCard",children:"Upload a model with embedded animations to manage playback, naming, autoplay, and per-clip speed here."})}):pe(it,{title:"Animations",children:[l.length===0&&W("div",{className:"se-helperCard",children:W("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."})}),l.length===0?W("div",{className:"se-placeholder",children:"All animations are currently removed. Restore a clip below to make it available again."}):W("div",{className:"se-animationList",children:l.map(h=>{let d=r.find(ne=>ne.clip===h.sourceName),a=d?.status==="playing",R=d?.time??0,H=m.get(h.sourceName)??0,D=d?Ll[d.status]:"Ready";return pe("article",{className:`se-animationCard ${d?"se-animationCard--active":""}`,children:[pe("div",{className:"se-animationHeader",children:[pe("div",{className:"se-animationHeading",children:[pe("div",{className:"se-animationTitleRow",children:[W("span",{className:"se-animationStatus",children:D}),t.animations.autoplayClip===h.sourceName?W("span",{className:"se-animationBadge",children:"Autoplay"}):null]}),W("div",{className:"se-animationSource",children:h.sourceName})]}),W("button",{type:"button",className:"se-animationDangerButton",onClick:()=>z(h.sourceName),title:"Remove animation",children:W(zl,{size:16})})]}),pe("div",{className:"se-field",children:[W("span",{className:"se-fieldLabel",children:"Display name"}),W("input",{className:"se-textInput",value:h.displayName,onChange:ne=>g(h.sourceName,ne.target.value),placeholder:"Animation name"})]}),pe("div",{className:"se-animationMeta",children:[W("span",{children:El(H)}),W("span",{children:Bi[h.loopMode]??Bi.repeat}),pe("span",{children:[h.speed.toFixed(2),"x"]})]}),pe("div",{className:"se-animationButtonRow",children:[W("button",{type:"button",className:"se-animationButton se-animationButton--icon",onClick:()=>a&&!d?.reverse?o(h.sourceName):e(h.sourceName,{alongside:!0}),"aria-label":a&&!d?.reverse?"Pause":"Play",title:a&&!d?.reverse?"Pause":"Play",children:a&&!d?.reverse?W(Pi,{size:16}):W(Ml,{size:16})}),W("button",{type:"button",className:"se-animationButton se-animationButton--icon",onClick:()=>a&&d?.reverse?o(h.sourceName):e(h.sourceName,{alongside:!0,reverse:!0}),"aria-label":a&&d?.reverse?"Pause":"Play backwards",title:a&&d?.reverse?"Pause":"Play backwards",children:a&&d?.reverse?W(Pi,{size:16}):W(Al,{size:16})}),W("button",{type:"button",className:"se-animationButton se-animationButton--icon",onClick:()=>u(h.sourceName),disabled:!d,"aria-label":"Stop",title:"Stop",children:W(Ol,{size:16})})]}),pe("div",{className:"se-animationSeekRow",children:[W("input",{className:"se-slider se-animationSeek",type:"range",min:0,max:Math.max(H,.001),step:.01,value:Math.min(R,H),disabled:!d||H<=0,onChange:ne=>f(Number(ne.target.value),h.sourceName),"aria-label":"Seek"}),pe("span",{className:"se-animationSeekTime",children:[Ri(Math.min(R,H))," / ",Ri(H)]})]}),pe("div",{className:"se-animationGrid",children:[pe("label",{className:"se-field",children:[W("span",{className:"se-fieldLabel",children:"Loop mode"}),pe("select",{className:"se-select",value:h.loopMode,onChange:ne=>F(h.sourceName,ne.target.value),children:[W("option",{value:"repeat",children:"Loop"}),W("option",{value:"once",children:"Play Once"}),W("option",{value:"ping-pong",children:"Ping-Pong"})]})]}),pe("label",{className:"se-field",children:[pe("span",{className:"se-fieldLabel",children:["Speed",pe("span",{className:"se-fieldValue",children:[h.speed.toFixed(2),"x"]})]}),pe("div",{className:"se-animationSpeedRow",children:[W("input",{className:"se-slider",type:"range",min:.1,max:3,step:.1,value:h.speed,onChange:ne=>x(h.sourceName,Number(ne.target.value))}),W("input",{className:"se-numberInput se-animationSpeedInput",type:"number",min:.1,max:3,step:.1,value:h.speed,onChange:ne=>x(h.sourceName,Number(ne.target.value))})]})]})]}),W("button",{type:"button",className:`se-animationAutoplayButton ${t.animations.autoplayClip===h.sourceName?"se-animationAutoplayButton--active":""}`,onClick:()=>N(h.sourceName),children:t.animations.autoplayClip===h.sourceName?"Disable autoplay":"Set as autoplay"})]},h.sourceName)})}),S.length>0?pe("section",{className:"se-removedAnimations",children:[W("button",{type:"button",className:"se-panelHeader",onClick:()=>M(h=>!h),children:pe("span",{className:"se-panelHeaderMain",children:[W(Rl,{size:16,className:`se-panelChevron ${C?"se-panelChevron--open":""}`}),pe("span",{className:"se-panelTitle",children:["Removed Animations (",S.length,")"]})]})}),C?W("div",{className:"se-removedAnimationList",children:S.map(h=>pe("div",{className:"se-removedAnimationRow",children:[pe("div",{children:[W("div",{className:"se-removedAnimationName",children:h.displayName||h.sourceName}),W("div",{className:"se-animationSource",children:h.sourceName})]}),W("button",{type:"button",className:"se-animationButton",onClick:()=>c(h.sourceName),children:"Restore"})]},h.sourceName))}):null]}):null]})}import{useState as Mi}from"react";import{Pencil as Dl,Trash2 as Il}from"lucide-react";import{jsx as Se,jsxs as Fe}from"react/jsx-runtime";function mo({config:t,onChange:n}){let[i,r]=Mi(null),[e,o]=Mi({title:"",description:""}),u=t.annotations,b=m=>{r(m),o({title:m.title,description:m.description||""})},f=()=>{if(!i||!e.title.trim())return;let m=u.map(l=>l.id===i.id?{...l,title:e.title.trim(),description:e.description||""}:l);n({...t,annotations:m}),r(null),o({title:"",description:""})},C=m=>{if(window.confirm("Delete this annotation?")){let S=u.filter(B=>B.id!==m).map((B,v)=>({...B,id:v+1}));n({...t,annotations:S}),r(null),o({title:"",description:""})}},M=()=>{r(null),o({title:"",description:""})};return Fe(it,{title:"Annotations",children:[t.annotations.length===0?Se("div",{className:"bb-emptyAnnotations",children:"No annotations yet. Double-click on the model to add one."}):Se("div",{className:"bb-annotationsList",children:t.annotations.map(m=>Fe("div",{className:"bb-annotationCard",children:[Fe("div",{className:"bb-annotationHeader",children:[Fe("div",{className:"bb-annotationBadge",children:["#",m.id]}),Fe("div",{className:"bb-annotationActions",children:[Se("button",{className:"bb-annotationAction bb-annotationAction--edit",onClick:()=>b(m),title:"Edit annotation",children:Se(Dl,{size:16})}),Se("button",{className:"bb-annotationAction bb-annotationAction--delete",onClick:()=>C(m.id),title:"Delete annotation",children:Se(Il,{size:16})})]})]}),Se("div",{className:"bb-annotationTitle",children:m.title}),m.description&&Se("div",{className:"bb-annotationDescription",children:m.description}),Fe("div",{className:"bb-annotationPosition",children:["Position: [",m.worldPosition[0].toFixed(2),","," ",m.worldPosition[1].toFixed(2),","," ",m.worldPosition[2].toFixed(2),"]"]})]},m.id))}),i&&Se("div",{className:"bb-editAnnotationOverlay",onClick:M,children:Fe("div",{className:"bb-editAnnotationPopup",onClick:m=>m.stopPropagation(),children:[Fe("div",{className:"bb-editAnnotationHeader",children:[Se("h3",{className:"bb-editAnnotationTitle",children:"Edit Annotation"}),Se("button",{className:"bb-editAnnotationClose",onClick:M,children:"\xD7"})]}),Fe("div",{className:"bb-editAnnotationBody",children:[Fe("div",{className:"bb-field",children:[Se("label",{className:"bb-label",children:"Title"}),Se("input",{className:"bb-input",value:e.title,onChange:m=>o({...e,title:m.target.value}),placeholder:"Enter annotation title"})]}),Fe("div",{className:"bb-field",children:[Se("label",{className:"bb-label",children:"Description"}),Se("textarea",{className:"bb-textarea",value:e.description,onChange:m=>o({...e,description:m.target.value}),placeholder:"Enter annotation description",rows:3})]}),Fe("div",{className:"bb-editAnnotationActions",children:[Se("button",{className:"bb-button",onClick:M,children:"Cancel"}),Se("button",{className:"bb-button bb-button--primary",onClick:f,disabled:!e.title.trim(),children:"Save"}),Se("button",{className:"bb-button bb-button--danger",onClick:()=>C(i.id),children:"Delete"})]})]})]})})]})}import{useState as Fl,useCallback as Ct}from"react";import{ArrowDown as Hl,ArrowUp as Gl,MapPin as Vl,Plus as $l,Trash2 as Ul,Settings as Kl}from"lucide-react";import{Fragment as Wl,jsx as ie,jsxs as xe}from"react/jsx-runtime";var _l={enabled:!0,waypoints:[],loop:!0,autoPlay:!1},St=3.5;function go({config:t,onChange:n,cameraState:i,onPreviewWaypoint:r}){let e=t.cinematic??_l,{waypoints:o}=e,u=Ct((x,g)=>{if(x.length<2)return 0;let N=0;for(let z=0;z<x.length-1;z++){let c=x[z].segmentDuration??St;N+=c}return g&&x.length>1&&(N+=x[x.length-1].segmentDuration??St),Math.max(N,0)},[]),b=Ct(x=>{n({...t,cinematic:{...e,...x}})},[t,e,n]),f=Ct(()=>{if(!i)return;let x={position:[...i.position],target:[...i.target],...i.azimuthAngle!=null?{azimuthAngle:i.azimuthAngle}:{},...i.polarAngle!=null?{polarAngle:i.polarAngle}:{},segmentDuration:St},g=[...o,x],N=u(g,e.loop);b({waypoints:g,duration:N})},[i,o,e.loop,u,b]),C=Ct(x=>{let g=o.filter((z,c)=>c!==x),N=u(g,e.loop);b({waypoints:g,duration:N})},[o,e.loop,u,b]),M=Ct((x,g)=>{let N=x+g;if(N<0||N>=o.length)return;let z=[...o];[z[x],z[N]]=[z[N],z[x]];let c=u(z,e.loop);b({waypoints:z,duration:c})},[o,e.loop,u,b]),m=Ct((x,g)=>{let N=o.map((c,h)=>h===x?{...c,...g}:c),z=u(N,e.loop);b({waypoints:N,duration:z})},[o,e.loop,u,b]),[l,S]=Fl(!1),B=o.some(x=>x.segmentDuration!==void 0),v=Ct(x=>x>=o.length-1?St:o[x]?.segmentDuration??St,[o]),F=o.length>=2;return xe(it,{title:"Cinematic Camera",children:[ie("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."}),xe("button",{type:"button",className:"bb-button bb-button--primary se-cinematicAdd",onClick:f,disabled:!i,title:"Capture the current camera view as a waypoint",children:[ie($l,{size:15}),"Add waypoint from current view"]}),xe("div",{className:"se-customizeToggle",children:[xe("label",{className:"se-toggleLabel",children:[ie("input",{type:"checkbox",checked:l,onChange:x=>S(x.target.checked)}),ie(Kl,{size:14}),ie("span",{children:"Customize durations between waypoints"})]}),l&&xe("span",{className:"se-toggleHint",children:["Set duration for each segment between waypoints: 1\u21922, 2\u21923, etc. Default: ",St,"s"]})]}),o.length===0?ie("div",{className:"bb-emptyAnnotations",children:"No waypoints yet. Position the camera and add your first one."}):xe(Wl,{children:[ie("div",{className:"se-waypointList",children:o.map((x,g)=>{let N=v(g),z=g===o.length-1,c=x.segmentDuration!==void 0&&x.segmentDuration!==St;return xe("div",{children:[xe("div",{className:"se-waypointCard",children:[ie("div",{className:"se-waypointBadge",children:g+1}),xe("div",{className:"se-waypointBody",children:[xe("div",{className:"se-waypointCoords",children:["pos [",x.position.map(h=>h.toFixed(1)).join(", "),"]"]}),xe("div",{className:"se-waypointCoords",children:["look [",x.target.map(h=>h.toFixed(1)).join(", "),"]"]}),l&&!z&&xe("div",{className:`se-customBadge ${c?"se-customBadge--custom":"se-customBadge--default"}`,children:[N.toFixed(1),"s",!c&&" (default)"]})]}),xe("div",{className:"se-waypointActions",children:[ie("button",{className:"se-waypointAction",onClick:()=>r?.(x),title:"Fly camera to this waypoint",disabled:!r,children:ie(Vl,{size:15})}),ie("button",{className:"se-waypointAction",onClick:()=>M(g,-1),title:"Move up",disabled:g===0,children:ie(Gl,{size:15})}),ie("button",{className:"se-waypointAction",onClick:()=>M(g,1),title:"Move down",disabled:z,children:ie(Hl,{size:15})}),ie("button",{className:"se-waypointAction se-waypointAction--delete",onClick:()=>C(g),title:"Delete waypoint",children:ie(Ul,{size:15})})]})]}),l&&!z&&xe("div",{className:"se-segmentBetween",children:[xe("div",{className:"se-segmentLabel",children:[g+1," \u2192 ",g+2,!x.segmentDuration&&" (default)"]}),xe("div",{className:"se-segmentControls",children:[ie("span",{className:"se-durationLabel",children:"Duration:"}),ie("input",{type:"range",className:"se-segmentSlider",min:1,max:20,step:.5,value:N,onChange:h=>{let d=parseFloat(h.target.value);m(g,{segmentDuration:d})}}),xe("span",{className:"se-segmentValue",children:[N.toFixed(1),"s"]}),xe("div",{className:"se-presetButtons",children:[[2,4,6,8].map(h=>xe("button",{className:"se-presetButton",onClick:()=>m(g,{segmentDuration:h}),children:[h,"s"]},`preset-${g}-${h}`)),ie("button",{className:"se-presetButton se-presetButton--default",onClick:()=>{let h=o.map((a,R)=>{if(R===g){let{segmentDuration:H,...D}=a;return D}return a}),d=u(h,e.loop);b({waypoints:h,duration:d})},children:"Reset"})]})]})]})]},`waypoint-wrapper-${g}`)})}),xe("div",{className:"se-totalDuration",children:[ie("span",{className:"se-totalLabel",children:"Total duration:"}),ie("span",{className:"se-totalValue",children:F?(e.duration??u(o,e.loop)).toFixed(1)+"s":"-"}),!F&&ie("span",{className:"se-totalHint",children:"(need at least 2 waypoints)"})]})]}),ie(Z,{label:"Enable cinematic camera",checked:e.enabled,onChange:x=>b({enabled:x})}),ie(Z,{label:"Loop",checked:e.loop,onChange:x=>{let g=x,N=u(o,g);b({loop:g,duration:N})}}),ie(Z,{label:"Auto-play on load",checked:e.autoPlay,onChange:x=>b({autoPlay:x})}),!l&&F&&ie(w,{label:"Duration",value:e.duration??u(o,e.loop),min:4,max:120,step:1,formatValue:x=>`${x}s`,onChange:x=>b({duration:x})})]})}import{useMemo as Yl,useRef as ql,useState as Di}from"react";import{HexColorInput as Jl,HexColorPicker as Xl}from"react-colorful";import{ArrowDown as Zl,ArrowUp as Ql,ChevronDown as ed,Plus as fo,Trash2 as td,X as Oi}from"lucide-react";var Ai=["other","body","light","wheel","glass","interior","floor","wall","door","furniture","decor","electronics","seat","table","chair","window","sofa","bed","engine","headlight"],On=["normal","hidden","selected","disabled"];import{Fragment as ji,jsx as O,jsxs as le}from"react/jsx-runtime";var ho={all:"All objects",group:"Group",tag:"Tag",type:"Type",object:"One object"},zi={metric:"Metric",status:"Status",metadata:"Metadata"},nd={metric:"",stops:[[0,"#3b82f6"],[100,"#ef4444"]]};function od(t){return t===void 0?"all":typeof t=="string"||Array.isArray(t)?"object":"group"in t?"group":"tag"in t?"tag":"type"}function Qt(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 Li(t,n){if(t!=="all")return t==="object"?n:t==="group"?{group:n}:t==="tag"?{tag:n}:{type:n}}function ad(t){return"metric"in t?"metric":"status"in t?"status":"metadata"}function Ei(t){return t==="metric"?{metric:""}:t==="status"?{status:["disabled"]}:{metadata:"",equals:""}}function id(t){let n=t.trim();return n==="true"?!0:n==="false"?!1:n==="null"?null:n!==""&&Number.isFinite(Number(n))?Number(n):t}function xo(t){return t.trim()===""||!Number.isFinite(Number(t))?void 0:Number(t)}function Ii(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])=>Ii(e,n?`${n}.${r}`:r,i+1))}var en=t=>[...new Set(t.filter(n=>!!n))].sort((n,i)=>n.localeCompare(i));function Qe({label:t,children:n}){return le("label",{className:"se-field",children:[O("span",{className:"se-fieldLabel",children:t}),n]})}function tn({label:t,checked:n,color:i,onToggle:r,onColorChange:e}){let[o,u]=Di(!1),b=ql(null);return le("div",{className:"se-field se-fieldInline",children:[le("label",{className:"se-ruleLook",children:[O("input",{type:"checkbox",className:"se-checkbox",checked:n,onChange:f=>r(f.target.checked)}),t]}),n&&i!==void 0&&e?O("span",{ref:b,style:{display:"inline-flex"},children:O(Jl,{prefixed:!0,className:"se-swatch","aria-label":`${t} value`,onClick:()=>u(f=>!f),style:{background:i,color:pt(i)},color:i,onChange:e})}):null,o?O(Xt,{anchorRef:b,onClose:()=>u(!1),children:O(Xl,{color:i,onChange:e})}):null]})}function rd({title:t,open:n,onToggle:i,actions:r,children:e}){return le("section",{className:"se-panel",children:[le("div",{className:"se-ruleHeader",children:[O("button",{type:"button",className:"se-panelHeader",onClick:i,"aria-expanded":n,children:le("span",{className:"se-panelHeaderMain",children:[O(ed,{size:16,className:`se-panelChevron ${n?"se-panelChevron--open":""}`}),O("span",{className:"se-panelTitle",children:t})]})}),O("span",{className:"se-ruleActions",children:r})]}),n?O("div",{className:"se-panelBody",children:e}):null]})}function vo({config:t,onChange:n,objectBindings:i}){let r=t.styleRules??[],[e,o]=Di(r[0]?.id??null),u=Yl(()=>{let l=Object.values(i);return{groups:en(l.map(S=>S.group)),tags:en(l.flatMap(S=>S.tags??[])),types:en(l.map(S=>S.type??"other")),objects:l.map(S=>({id:S.id,label:S.label||S.id})).sort((S,B)=>S.label.localeCompare(B.label)),metrics:en(l.flatMap(S=>Object.keys(S.metrics??{}))),metadata:en(l.flatMap(S=>Ii(S.metadata)))}},[i]),b=l=>n({...t,styleRules:l}),f=(l,S)=>b(r.map(B=>B.id===l?S(B):B)),C=()=>{let l=crypto.randomUUID();b([...r,{id:l,label:`Rule ${r.length+1}`,when:[{status:["disabled"]}],material:{baseColor:"#9ca3af"}}]),o(l)},M=(l,S)=>{let B=[...r],[v]=B.splice(l,1);B.splice(l+S,0,v),b(B)},m=l=>{let S=l.target?oo(i,l.target):Object.keys(i),B=l.when?Array.isArray(l.when)?l.when:[l.when]:[];return S.filter(v=>B.every(F=>Aa(i[v],F))).length};return le(it,{title:"Style rules",children:[O("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."}),O("datalist",{id:"se-ruleMetrics",children:u.metrics.map(l=>O("option",{value:l},l))}),O("datalist",{id:"se-ruleMetadata",children:u.metadata.map(l=>O("option",{value:l},l))}),r.map((l,S)=>{let B=l.when?Array.isArray(l.when)?l.when:[l.when]:[],v=od(l.target),F=l.material??{},x=l.pulse===!0?{}:l.pulse||void 0,g=l.target?oo(i,l.target).length:Object.keys(i).length,N=a=>f(l.id,R=>({...R,when:a.length>0?a:void 0})),z=(a,R)=>N(B.map((H,D)=>D===a?R:H)),c=a=>f(l.id,R=>{let H={...R.material,...a};for(let D of Object.keys(H))H[D]===void 0&&delete H[D];return{...R,material:Object.keys(H).length>0?H:void 0}}),h=a=>f(l.id,R=>({...R,colorScale:a})),d=v==="group"?u.groups:v==="tag"?u.tags:v==="type"?u.types:[];return le(rd,{title:l.label||`Rule ${S+1}`,open:e===l.id,onToggle:()=>o(a=>a===l.id?null:l.id),actions:le(ji,{children:[O("button",{type:"button",className:"se-iconButton",onClick:()=>M(S,-1),disabled:S===0,"aria-label":"Move rule up",title:"Move up",children:O(Ql,{size:14})}),O("button",{type:"button",className:"se-iconButton",onClick:()=>M(S,1),disabled:S===r.length-1,"aria-label":"Move rule down",title:"Move down",children:O(Zl,{size:14})}),O("button",{type:"button",className:"se-iconButton",onClick:()=>b(r.filter(a=>a.id!==l.id)),"aria-label":"Delete rule",title:"Delete rule",children:O(td,{size:14})})]}),children:[O(Qe,{label:"Name",children:O("input",{className:"se-textInput",value:l.label??"",placeholder:`Rule ${S+1}`,onChange:a=>f(l.id,R=>({...R,label:a.target.value}))})}),le("div",{className:"se-ruleGrid",children:[O(Qe,{label:"Applies to",children:O("select",{className:"se-select",value:v,onChange:a=>{let R=a.target.value,H=R==="object"?u.objects[0]?.id:R==="group"?u.groups[0]:R==="tag"?u.tags[0]:R==="type"?u.types[0]:"";f(l.id,D=>({...D,target:Li(R,H??"")}))},children:Object.keys(ho).map(a=>O("option",{value:a,children:ho[a]},a))})}),v!=="all"?O(Qe,{label:ho[v],children:le("select",{className:"se-select",value:Qt(l.target),onChange:a=>f(l.id,R=>({...R,target:Li(v,a.target.value)})),children:[v==="object"?u.objects.map(a=>O("option",{value:a.id,children:a.label},a.id)):d.map(a=>O("option",{value:a,children:a},a)),(v==="object"?u.objects.some(a=>a.id===Qt(l.target)):d.includes(Qt(l.target)))?null:O("option",{value:Qt(l.target),children:Qt(l.target)||"None in this model"})]})}):null]}),O("div",{className:"se-fieldLabel",children:"When"}),B.length===0?O("div",{className:"se-ruleHint",children:"Always applies."}):null,B.map((a,R)=>{let H=ad(a);return le("div",{className:"se-ruleCondition",children:[le("div",{className:"se-ruleConditionHeader",children:[O("select",{className:"se-select","aria-label":"Condition type",value:H,onChange:D=>z(R,Ei(D.target.value)),children:Object.keys(zi).map(D=>O("option",{value:D,children:zi[D]},D))}),O("button",{type:"button",className:"se-iconButton","aria-label":"Remove condition",title:"Remove condition",onClick:()=>N(B.filter((D,ne)=>ne!==R)),children:O(Oi,{size:14})})]}),"metric"in a?le("div",{className:"se-ruleGrid se-ruleGrid--three",children:[O(Qe,{label:"Metric",children:O("input",{className:"se-textInput",list:"se-ruleMetrics",value:a.metric,placeholder:"temperature",onChange:D=>z(R,{...a,metric:D.target.value})})}),O(Qe,{label:"Above",children:O("input",{className:"se-numberInput",type:"number",value:a.above??"",placeholder:"any",onChange:D=>z(R,{...a,above:xo(D.target.value)})})}),O(Qe,{label:"Below",children:O("input",{className:"se-numberInput",type:"number",value:a.below??"",placeholder:"any",onChange:D=>z(R,{...a,below:xo(D.target.value)})})})]}):"status"in a?O("div",{className:"se-ruleStatuses",children:On.map(D=>{let ne=[].concat(a.status).includes(D);return le("label",{className:"se-ruleStatus",children:[O("input",{type:"checkbox",className:"se-checkbox",checked:ne,onChange:()=>{let qe=[].concat(a.status),Ft=ne?qe.filter(Tt=>Tt!==D):[...qe,D];z(R,{status:Ft})}}),D]},D)})}):le("div",{className:"se-ruleGrid",children:[O(Qe,{label:"Key",children:O("input",{className:"se-textInput",list:"se-ruleMetadata",value:a.metadata,placeholder:"alarm.state",onChange:D=>z(R,{...a,metadata:D.target.value})})}),O(Qe,{label:"Equals",children:O("input",{className:"se-textInput",value:a.equals===null?"null":String(a.equals),placeholder:"fault",onChange:D=>z(R,{...a,equals:id(D.target.value)})})})]})]},R)}),le("button",{type:"button",className:"se-animationButton",onClick:()=>N([...B,Ei("metric")]),children:[O(fo,{size:14})," Add condition"]}),O("div",{className:"se-fieldLabel",children:"Look"}),O(tn,{label:"Colour",checked:F.baseColor!==void 0,color:F.baseColor,onToggle:a=>c({baseColor:a?"#9ca3af":void 0}),onColorChange:a=>c({baseColor:a})}),O(tn,{label:"Opacity",checked:F.opacity!==void 0,onToggle:a=>c({opacity:a?.4:void 0})}),F.opacity!==void 0?O(w,{label:"Opacity",value:F.opacity,min:0,max:1,step:.05,formatValue:a=>`${Math.round(a*100)}%`,onChange:a=>c({opacity:a})}):null,O(tn,{label:"Glow",checked:F.emissive!==void 0,color:F.emissive,onToggle:a=>c({emissive:a?"#ff3b30":void 0,emissiveIntensity:a?F.emissiveIntensity??1:void 0}),onColorChange:a=>c({emissive:a})}),O(tn,{label:"Colour from a metric",checked:l.colorScale!==void 0,onToggle:a=>h(a?{...nd,metric:u.metrics[0]??""}:void 0)}),l.colorScale?le("div",{className:"se-ruleCondition",children:[le("div",{className:"se-ruleGrid",children:[O(Qe,{label:"Metric",children:O("input",{className:"se-textInput",list:"se-ruleMetrics",value:l.colorScale.metric,placeholder:"temperature",onChange:a=>h({...l.colorScale,metric:a.target.value})})}),O(Qe,{label:"Sets",children:le("select",{className:"se-select",value:l.colorScale.channel??"baseColor",onChange:a=>h({...l.colorScale,channel:a.target.value}),children:[O("option",{value:"baseColor",children:"Colour"}),O("option",{value:"emissive",children:"Glow colour"})]})})]}),l.colorScale.stops.map(([a,R],H)=>{let D=ne=>h({...l.colorScale,stops:l.colorScale.stops.map((qe,Ft)=>Ft===H?ne:qe)});return le("div",{className:"se-ruleStop",children:[O("input",{className:"se-numberInput",type:"number","aria-label":"Stop value",value:a,onChange:ne=>D([xo(ne.target.value)??0,R])}),O(Ae,{label:`At ${a}`,value:R,onChange:ne=>D([a,ne])}),O("button",{type:"button",className:"se-iconButton","aria-label":"Remove stop",title:"Remove stop",disabled:l.colorScale.stops.length<=1,onClick:()=>h({...l.colorScale,stops:l.colorScale.stops.filter((ne,qe)=>qe!==H)}),children:O(Oi,{size:14})})]},H)}),le("button",{type:"button",className:"se-animationButton",onClick:()=>{let a=l.colorScale.stops,R=a[a.length-1];h({...l.colorScale,stops:[...a,[(R?.[0]??0)+10,R?.[1]??"#ffffff"]]})},children:[O(fo,{size:14})," Add stop"]})]}):null,O(tn,{label:"Pulse",checked:x!==void 0,color:x?.color??"#ff3b30",onToggle:a=>f(l.id,R=>({...R,pulse:a?{color:"#ff3b30",speed:1}:void 0})),onColorChange:a=>f(l.id,R=>({...R,pulse:{...x,color:a}}))}),x?O(ji,{children:O(w,{label:"Pulses per second",value:x.speed??1,min:.2,max:4,step:.1,formatValue:a=>a.toFixed(1),onChange:a=>f(l.id,R=>({...R,pulse:{...x,speed:a}}))})}):null,le("div",{className:"se-ruleHint se-ruleMatches",children:["Matches ",m(l)," of ",g," ",g===1?"object":"objects"," right now."]})]},l.id)}),le("button",{type:"button",className:"se-animationButton",onClick:C,children:[O(fo,{size:14})," Add rule"]})]})}import{Box as dd,Clapperboard as cd,MessageSquareText as bd,Palette as pd,Sparkles as ud,Spotlight as md,Video as gd}from"lucide-react";import{jsx as he,jsxs as vd}from"react/jsx-runtime";var fd=[{label:"General",icon:he(dd,{})},{label:"Lighting",icon:he(md,{})},{label:"Animations",icon:he(cd,{})},{label:"Post Processing",icon:he(ud,{})},{label:"Annotations",icon:he(bd,{})},{label:"Cinematic",icon:he(gd,{})},{label:"Rules",icon:he(pd,{})}],Fi={active:[],play:()=>{},pause:()=>{},stop:()=>{},setSpeed:()=>{},seek:()=>{}},hd=[],xd={};function yo({config:t,onChange:n,activeSubTab:i,onActiveSubTabChange:r,cameraState:e=null,onPreviewWaypoint:o,animationClipDetails:u=[],materialVariants:b=hd,objectBindings:f=xd,animationPlayback:C=Fi}){let[M,m]=sd("General"),l=i??M,S=C??Fi,{tier:B}=Ze(),v=Ue(B,"starter"),F=Ue(B,"growth");ld(()=>{i!==void 0&&m(i)},[i]);let x=g=>{i===void 0&&m(g),r?.(g)};return vd("div",{className:"se-tabContent",children:[he("div",{className:"se-subTabRow",children:fd.map(g=>he("button",{type:"button",title:g.label,"aria-label":g.label,"aria-pressed":l===g.label,className:`se-subTab ${l===g.label?"se-subTab--active":""}`,onClick:()=>x(g.label),children:g.icon},g.label))}),l==="General"&&he(co,{config:t,onChange:n,materialVariants:b}),l==="Lighting"&&he(po,{config:t,onChange:n}),l==="Animations"&&(v?he(uo,{config:t,onChange:n,clipDetails:u,active:S.active,play:S.play,pause:S.pause,stop:S.stop,setSpeed:S.setSpeed,seek:S.seek}):he(ke,{requiredTier:"starter",feature:"Animation configuration"})),l==="Post Processing"&&(F?he(bo,{config:t,onChange:n}):he(ke,{requiredTier:"growth",feature:"Post-processing effects"})),l==="Annotations"&&(v?he(mo,{config:t,onChange:n}):he(ke,{requiredTier:"starter",feature:"Annotations"})),l==="Cinematic"&&(v?he(go,{config:t,onChange:n,cameraState:e,onPreviewWaypoint:o}):he(ke,{requiredTier:"starter",feature:"Cinematic camera"})),l==="Rules"&&(v?he(vo,{config:t,onChange:n,objectBindings:f}):he(ke,{requiredTier:"starter",feature:"Style rules"}))]})}import{ChevronDown as Hi,Info as Gi}from"lucide-react";import{jsx as Me,jsxs as kt}from"react/jsx-runtime";function Vi({title:t,trailing:n,children:i,disabled:r,open:e,onToggle:o,tooltip:u}){let b=u?`${u}`:t;return kt("div",{className:"bb-materialPanel",children:[kt("button",{type:"button",className:"bb-materialPanelHeader",onClick:o,"aria-expanded":e,title:b,children:[kt("div",{className:"bb-materialPanelTitleWrap",children:[Me(Hi,{size:14,className:`bb-materialPanelChevron ${e?"bb-materialPanelChevron--open":""}`}),Me("span",{className:"bb-materialPanelTitle",children:t}),u?Me("span",{className:"bb-materialPanelHelp",title:b,"aria-label":b,role:"img",onClick:f=>f.stopPropagation(),children:Me(Gi,{size:12})}):null]}),n?Me("div",{onClick:f=>f.stopPropagation(),children:n}):null]}),e?Me("div",{className:"bb-materialPanelBody",style:r?{opacity:.45,pointerEvents:"none"}:void 0,children:i}):null]})}function Te({title:t,open:n,onToggle:i,trailing:r,children:e,tooltip:o}){let u=o?`${t}: ${o}`:t;return kt("div",{className:"bb-section",children:[kt("button",{type:"button",className:"bb-sectionHeaderButton",onClick:i,"aria-expanded":n,title:u,children:[kt("span",{className:"bb-sectionHeaderMain",children:[Me(Hi,{size:15,className:`bb-sectionChevron ${n?"bb-sectionChevron--open":""}`}),Me("h2",{className:"bb-sectionTitle",children:t}),o?Me("span",{className:"bb-sectionHelp",title:u,"aria-label":u,role:"img",onClick:b=>b.stopPropagation(),children:Me(Gi,{size:13})}):null]}),r?Me("span",{onClick:b=>b.stopPropagation(),children:r}):null]}),n?Me("div",{className:"bb-sectionBody",children:e}):null]})}function $i({checked:t,onChange:n,label:i}){return kt("label",{className:"se-switch","aria-label":i,children:[Me("input",{type:"checkbox",checked:t,onChange:r=>n(r.target.checked)}),Me("span",{className:"se-switchTrack",children:Me("span",{className:"se-switchThumb"})})]})}import{useState as _i}from"react";import{Trash2 as Pd}from"lucide-react";import{jsx as wo}from"react/jsx-runtime";function Ee({panelKey:t,title:n,tooltip:i,toggleLabel:r,controls:e,children:o,requiredTier:u}){let{openMaterialPanels:b,materialPanelEnabled:f,onToggleMaterialPanel:C,onSetMaterialPanelState:M}=e,m=u?.locked??!1;return wo(Vi,{title:n,tooltip:i,disabled:m||!f[t],open:b[t],onToggle:()=>C(t),trailing:wo($i,{checked:!m&&f[t],onChange:m?()=>{}:l=>M(t,l),label:r??`Toggle ${n}`}),children:m&&u?wo(ke,{requiredTier:u.tier,feature:n}):o})}import{useRef as Ui,useState as yd}from"react";import{HexColorInput as wd,HexColorPicker as Cd}from"react-colorful";import{FileUp as Sd,Minus as kd,Plus as Nd}from"lucide-react";import{jsx as re,jsxs as et}from"react/jsx-runtime";function ve({label:t,value:n,placeholder:i,onChange:r}){let e=Ui(null);return et("div",{className:"bb-field bb-field--full",children:[re("label",{className:"bb-label",children:t}),et("div",{className:"bb-fileField",children:[re("input",{className:"bb-input bb-fileField-input",placeholder:i,value:n,onChange:o=>{let u=o.target.value;!u&&n&&_t(n),r(u)}}),re("button",{type:"button",className:"bb-fileFieldButton",onClick:()=>e.current?.click(),"aria-label":`Select file for ${t}`,title:`Select file for ${t}`,children:re(Sd,{size:20})}),re("input",{ref:e,type:"file",accept:"image/png,image/jpeg,image/webp,image/avif",className:"bb-hiddenInput",onChange:o=>{let u=o.target.files?.[0];if(!u)return;let b=Nn(u);n&&n!==b&&_t(n),xt(b,URL.createObjectURL(u)),r(b),o.target.value=""}})]})]})}function rt({label:t,value:n,fallback:i="#ffffff",variant:r="swatch",onChange:e}){let[o,u]=yd(!1),b=n||i,f=Ui(null);return et("div",{className:"bb-field",children:[re("span",{className:"bb-label",children:t}),re("div",{className:"se-fieldInline",children:re("span",{ref:f,className:r==="input"?"bb-colorFieldAnchor":void 0,style:r==="swatch"?{display:"inline-flex"}:void 0,children:re(wd,{prefixed:!0,className:r==="input"?"bb-input bb-colorInput":"se-swatch","aria-label":t,onClick:()=>u(C=>!C),style:{background:b,color:pt(b)},color:b,onChange:e})})}),o?re(Xt,{anchorRef:f,onClose:()=>u(!1),children:re(Cd,{color:b,onChange:e})}):null]})}function nn({label:t,checked:n,onChange:i}){return et("label",{className:"bb-checkbox",children:[re("input",{type:"checkbox",checked:n,onChange:r=>i(r.target.checked)}),t]})}function Ki({label:t,value:n,min:i,max:r,step:e,placeholder:o,disabled:u,onChange:b}){return et("div",{className:"bb-field",children:[re("label",{className:"bb-label",children:t}),re("input",{className:"bb-input",type:"number",min:i,max:r,step:e,placeholder:o,disabled:u,value:n??"",onChange:f=>b(f.target.value===""?void 0:Number(f.target.value))})]})}function Td(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 Co({label:t,value:n,min:i,max:r,step:e=.01,disabled:o,onChange:u}){let b=n??0,f=M=>{let m=M;return i!==void 0&&(m=Math.max(i,m)),r!==void 0&&(m=Math.min(r,m)),m},C=M=>{u(f(Td(b+M*e,e)))};return et("div",{className:"bb-field",children:[re("label",{className:"bb-label",children:t}),et("div",{className:"bb-numberStepper",children:[re("button",{type:"button",className:"bb-numberStepper-btn",disabled:o,onClick:()=>C(-1),"aria-label":`Decrease ${t}`,title:`Decrease ${t}`,children:re(kd,{size:12})}),re("input",{className:"bb-input bb-numberStepper-input",type:"number",min:i,max:r,step:e,disabled:o,value:b,onChange:M=>{M.target.value!==""&&u(f(Number(M.target.value)))}}),re("button",{type:"button",className:"bb-numberStepper-btn",disabled:o,onClick:()=>C(1),"aria-label":`Increase ${t}`,title:`Increase ${t}`,children:re(Nd,{size:12})})]})]})}function jt({label:t,value:n,options:i,onChange:r}){return et("div",{className:"bb-field",children:[re("label",{className:"bb-label",children:t}),re("select",{className:"bb-select",value:n,onChange:e=>r(e.target.value),children:i.map(e=>re("option",{value:e,children:e},e))})]})}function ee({label:t,value:n,min:i,max:r,step:e,onChange:o}){return et("div",{className:"bb-field bb-field--full",children:[re("label",{className:"bb-label",children:t}),et("div",{className:"bb-sliderField",children:[re("input",{className:`bb-slider ${n===void 0?"bb-slider--unset":""}`,type:"range",min:i,max:r,step:e,value:n??i,onChange:b=>o(Number(b.target.value))}),re("input",{className:"bb-input bb-input--compact",type:"number",min:i,max:r,step:e,value:n??"",onChange:b=>o(b.target.value===""?void 0:Number(b.target.value))})]})]})}import{Fragment as So,jsx as P,jsxs as ue}from"react/jsx-runtime";function Wi({selectedItem:t,selectedMaterial:n,pbrWorkflow:i,onPbrWorkflowChange:r,openMaterialPanels:e,materialPanelEnabled:o,onToggleMaterialPanel:u,onSetMaterialPanelState:b,updateSelectedMaterial:f,setSelectedTexturePath:C,isTexturePositioningEnabled:M,onConfirmTexturePosition:m}){let l={openMaterialPanels:e,materialPanelEnabled:o,onToggleMaterialPanel:u,onSetMaterialPanelState:b},{tier:S}=Ze(),B=Ue(S,"starter"),v={tier:"starter",locked:!B},[F,x]=_i("roughness"),[g,N]=_i("factor"),z=(d,a)=>{f(t,R=>{if(!R?.texture?.path)return R??{};let H=R.texture.offset??[0,0],D=[H[0],H[1]];return D[d]=a,{...R,texture:{...R.texture,offset:D}}})},c=d=>{f(t,a=>{if(!a?.texture?.path)return a??{};let R=(d%360+360)%360;return{...a,texture:{...a.texture,rotation:R*Math.PI/180}}})},h=()=>{C(t,"texture","")};return ue(So,{children:[P(Ee,{panelKey:"pbr",title:"PBR Maps",tooltip:"Controls the base color and workflow used for physically based shading.",controls:l,children:B?ue("div",{className:"bb-grid",children:[P(jt,{label:"Workflow",value:i,options:["metalness","specular"],onChange:r}),P("div",{className:"bb-field bb-field--full",children:P("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."})}),P(ve,{label:i==="specular"?"Albedo texture path":"Base color texture path",placeholder:"materials/oak-wood.jpg",value:n?.texture?.path??"",onChange:d=>C(t,"texture",d)}),n?.texture?.path?ue("div",{className:"bb-field bb-field--full",children:[ue("div",{className:"bb-fieldLabel",style:{display:"flex",alignItems:"center",justifyContent:"space-between"},children:[P("span",{className:"bb-label",children:"Texture position"}),ue("button",{type:"button",className:"bb-button bb-button--ghost",onClick:h,title:"Remove the base color texture and its position offset",children:[P(Pd,{size:14,style:{marginRight:4,verticalAlign:"-2px"}}),"Remove texture"]})]}),ue("div",{className:"bb-grid",style:{marginTop:6},children:[P(Co,{label:"Offset X",value:n?.texture?.offset?.[0]??0,step:.01,onChange:d=>z(0,d)}),P(Co,{label:"Offset Y",value:n?.texture?.offset?.[1]??0,step:.01,onChange:d=>z(1,d)})]}),P(ee,{label:"Rotation",value:((n?.texture?.rotation??0)*180/Math.PI%360+360)%360,min:0,max:360,step:1,onChange:d=>c(d??0)}),M?P("button",{type:"button",className:"bb-button bb-button--primary",style:{marginTop:8},onClick:m,title:"Confirm this texture position and exit positioning mode",children:"Done positioning"}):P("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,P(rt,{label:i==="specular"?"Albedo color":"Base color",value:n?.baseColor??"#ffffff",onChange:d=>f(t,a=>({...a,baseColor:d}))}),i==="metalness"?ue(So,{children:[P(ee,{label:"Metalness",value:n?.metalness,min:0,max:1,step:.01,onChange:d=>f(t,a=>({...a,metalness:d}))}),P(ve,{label:"Metalness map path",placeholder:"materials/body-metalness.jpg",value:n?.metalnessMap?.path??"",onChange:d=>C(t,"metalnessMap",d)})]}):ue(So,{children:[P(ee,{label:"Specular intensity",value:n?.specularIntensity,min:0,max:1,step:.01,onChange:d=>f(t,a=>({...a,specularIntensity:d}))}),P(rt,{label:"Specular color",value:n?.specularColor??"#ffffff",onChange:d=>f(t,a=>({...a,specularColor:d}))}),P(ve,{label:"Specular intensity map path",placeholder:"materials/body-specular-intensity.jpg",value:n?.specularIntensityMap?.path??"",onChange:d=>C(t,"specularIntensityMap",d)}),P(ve,{label:"Specular color map path",placeholder:"materials/body-specular-color.jpg",value:n?.specularColorMap?.path??"",onChange:d=>C(t,"specularColorMap",d)})]}),P(ee,{label:"Specular F0 / reflectivity",value:n?.reflectivity,min:0,max:1,step:.01,onChange:d=>f(t,a=>({...a,reflectivity:d}))})]}):ue("div",{className:"bb-grid",children:[P(rt,{label:"Base color",value:n?.baseColor??"#ffffff",onChange:d=>f(t,a=>({...a,baseColor:d}))}),P(ee,{label:"Metalness",value:n?.metalness,min:0,max:1,step:.01,onChange:d=>f(t,a=>({...a,metalness:d}))}),P("div",{className:"bb-field bb-field--full",children:P(ke,{requiredTier:"starter",feature:"Texture maps, the specular workflow, and reflectivity"})})]})}),P(Ee,{panelKey:"roughness",requiredTier:v,title:"Roughness / Glossiness",tooltip:"Adjusts how matte or shiny the surface appears.",toggleLabel:"Toggle Roughness and Glossiness",controls:l,children:ue("div",{className:"bb-grid",children:[P(jt,{label:"Mode",value:F,options:["roughness","glossiness"],onChange:x}),P("div",{className:"bb-field bb-field--full",children:P("p",{className:"bb-note",style:{margin:0},children:F==="roughness"?"Roughness: 0 is glossy, 1 is matte.":"Glossiness is the inverse of roughness (glossiness = 1 \u2212 roughness)"})}),F==="roughness"?P(ee,{label:"Roughness",value:n?.roughness,min:0,max:1,step:.01,onChange:d=>f(t,a=>({...a,roughness:d}))}):P(ee,{label:"Glossiness",value:n?.roughness===void 0?void 0:1-n.roughness,min:0,max:1,step:.01,onChange:d=>f(t,a=>({...a,roughness:d===void 0?void 0:1-d}))}),P(ve,{label:F==="glossiness"?"Glossiness map path (applied as roughness)":"Roughness map path",placeholder:"materials/body-roughness.jpg",value:n?.roughnessMap?.path??"",onChange:d=>C(t,"roughnessMap",d)})]})}),P(Ee,{panelKey:"emission",requiredTier:v,title:"Emission",tooltip:"Makes the material self-illuminated with emissive color and intensity.",controls:l,children:ue("div",{className:"bb-grid",children:[P(rt,{label:"Emissive color",value:n?.emissive??"#000000",fallback:"#000000",onChange:d=>f(t,a=>({...a,emissive:d}))}),P(ee,{label:"Emissive intensity",value:n?.emissiveIntensity,min:0,max:10,step:.1,onChange:d=>f(t,a=>({...a,emissiveIntensity:d}))}),P(ve,{label:"Emissive map path",placeholder:"materials/body-emissive.jpg",value:n?.emissiveMap?.path??"",onChange:d=>C(t,"emissiveMap",d)})]})}),P(Ee,{panelKey:"opacity",requiredTier:v,title:"Opacity",tooltip:"Controls transparency, alpha testing, and blending behavior.",controls:l,children:ue("div",{className:"bb-grid",children:[P(ee,{label:"Opacity",value:n?.opacity,min:0,max:1,step:.01,onChange:d=>f(t,a=>({...a,opacity:d}))}),P(ee,{label:"Alpha test",value:n?.alphaTest,min:0,max:1,step:.01,onChange:d=>f(t,a=>({...a,alphaTest:d}))}),P(ve,{label:"Alpha map path",placeholder:"materials/body-alpha.png",value:n?.alphaMap?.path??"",onChange:d=>C(t,"alphaMap",d)}),P(jt,{label:"Blending mode",value:n?.blendingMode??"normal",options:$a,onChange:d=>f(t,a=>({...a,blendingMode:d}))}),ue("div",{className:"bb-field",children:[P("label",{className:"bb-label",children:"Alpha hash"}),P("div",{className:"bb-checkboxRow",children:P(nn,{label:"Use alpha hash",checked:n?.alphaHash??!1,onChange:d=>f(t,a=>({...a,alphaHash:d}))})})]}),ue("div",{className:"bb-field",children:[P("label",{className:"bb-label",children:"Dithering"}),P("div",{className:"bb-checkboxRow",children:P(nn,{label:"Use dithering",checked:n?.dithering??!1,onChange:d=>f(t,a=>({...a,dithering:d}))})})]})]})}),ue(Ee,{panelKey:"normalBump",requiredTier:v,title:"Normal & Bump",tooltip:"Adds surface detail without changing the actual mesh shape.",toggleLabel:"Toggle Normal and Bump",controls:l,children:[ue("div",{className:"bb-grid",children:[P(ve,{label:"Normal map path",placeholder:"materials/body-normal.jpg",value:n?.normalMap?.path??"",onChange:d=>C(t,"normalMap",d)}),P(ee,{label:"Normal scale",value:n?.normalScale,min:0,max:5,step:.01,onChange:d=>f(t,a=>({...a,normalScale:d}))}),P(ve,{label:"Bump map path",placeholder:"materials/body-bump.jpg",value:n?.bumpMap?.path??"",onChange:d=>C(t,"bumpMap",d)}),P(ee,{label:"Bump scale",value:n?.bumpScale,min:0,max:5,step:.01,onChange:d=>f(t,a=>({...a,bumpScale:d}))})]}),P("div",{className:"bb-checkboxRow",style:{marginTop:12},children:P(nn,{label:"Flip normal Y",checked:n?.flipNormalY??!1,onChange:d=>f(t,a=>({...a,flipNormalY:d}))})})]}),P(Ee,{panelKey:"displacement",requiredTier:v,title:"Displacement",tooltip:"Offsets geometry using a texture to create real surface height.",controls:l,children:ue("div",{className:"bb-grid",children:[P(ve,{label:"Displacement map path",placeholder:"materials/body-displacement.jpg",value:n?.displacementMap?.path??"",onChange:d=>C(t,"displacementMap",d)}),P(ee,{label:"Displacement scale",value:n?.displacementScale,min:-5,max:5,step:.01,onChange:d=>f(t,a=>({...a,displacementScale:d}))}),P(ee,{label:"Displacement bias",value:n?.displacementBias,min:-5,max:5,step:.01,onChange:d=>f(t,a=>({...a,displacementBias:d}))})]})}),P(Ee,{panelKey:"ao",requiredTier:v,title:"Ambient Occlusion",tooltip:"Darkens creases and contact areas to add depth.",controls:l,children:ue("div",{className:"bb-grid",children:[P(ve,{label:"AO map path",placeholder:"materials/body-ao.jpg",value:n?.aoMap?.path??"",onChange:d=>C(t,"aoMap",d)}),P(ee,{label:"AO intensity",value:n?.aoMapIntensity,min:0,max:5,step:.01,onChange:d=>f(t,a=>({...a,aoMapIntensity:d}))})]})}),ue(Ee,{panelKey:"clearcoat",requiredTier:v,title:"Clearcoat",tooltip:"Adds a glossy protective layer on top of the base material.",controls:l,children:[ue("div",{className:"bb-grid",children:[P(ve,{label:"Clearcoat map path",placeholder:"materials/body-clearcoat.jpg",value:n?.clearcoatMap?.path??"",onChange:d=>C(t,"clearcoatMap",d)}),P(ee,{label:"Clearcoat",value:n?.clearcoat,min:0,max:1,step:.01,onChange:d=>f(t,a=>({...a,clearcoat:d}))}),P(ve,{label:"Clearcoat roughness map path",placeholder:"materials/body-clearcoat-roughness.jpg",value:n?.clearcoatRoughnessMap?.path??"",onChange:d=>C(t,"clearcoatRoughnessMap",d)}),P(ee,{label:"Clearcoat roughness",value:n?.clearcoatRoughness,min:0,max:1,step:.01,onChange:d=>f(t,a=>({...a,clearcoatRoughness:d}))}),P(ve,{label:"Clearcoat normal map path",placeholder:"materials/body-clearcoat-normal.jpg",value:n?.clearcoatNormalMap?.path??"",onChange:d=>C(t,"clearcoatNormalMap",d)}),P(ee,{label:"Clearcoat normal scale",value:n?.clearcoatNormalScale,min:0,max:5,step:.01,onChange:d=>f(t,a=>({...a,clearcoatNormalScale:d}))})]}),P("div",{className:"bb-checkboxRow",style:{marginTop:12},children:P(nn,{label:"Flip clearcoat normal Y",checked:n?.flipClearcoatNormalY??!1,onChange:d=>f(t,a=>({...a,flipClearcoatNormalY:d}))})})]}),P(Ee,{panelKey:"sheen",requiredTier:v,title:"Sheen",tooltip:"Adds a soft fabric-like sheen on grazing angles.",controls:l,children:ue("div",{className:"bb-grid",children:[P(ee,{label:"Sheen",value:n?.sheen,min:0,max:1,step:.01,onChange:d=>f(t,a=>({...a,sheen:d}))}),P(rt,{label:"Sheen color",value:n?.sheenColor??"#ffffff",onChange:d=>f(t,a=>({...a,sheenColor:d}))}),P(ve,{label:"Sheen color map path",placeholder:"materials/body-sheen-color.jpg",value:n?.sheenColorMap?.path??"",onChange:d=>C(t,"sheenColorMap",d)}),P(ee,{label:"Sheen roughness",value:n?.sheenRoughness,min:0,max:1,step:.01,onChange:d=>f(t,a=>({...a,sheenRoughness:d}))}),P(ve,{label:"Sheen roughness map path",placeholder:"materials/body-sheen-roughness.jpg",value:n?.sheenRoughnessMap?.path??"",onChange:d=>C(t,"sheenRoughnessMap",d)})]})}),P(Ee,{panelKey:"anisotropy",requiredTier:v,title:"Anisotropy",tooltip:"Stretches reflections in one direction for brushed or fiber-like surfaces.",controls:l,children:ue("div",{className:"bb-grid",children:[P(ee,{label:"Intensity",value:n?.anisotropy,min:0,max:1,step:.01,onChange:d=>f(t,a=>({...a,anisotropy:d}))}),P(jt,{label:"Tilt direction",value:g,options:["factor","texture"],onChange:N}),g==="factor"?P(ee,{label:"Rotation (rad)",value:n?.anisotropyRotation,min:0,max:6.28,step:.01,onChange:d=>f(t,a=>({...a,anisotropyRotation:d}))}):P(ve,{label:"Anisotropy map path",placeholder:"materials/body-anisotropy.jpg",value:n?.anisotropyMap?.path??"",onChange:d=>C(t,"anisotropyMap",d)})]})}),P(Ee,{panelKey:"transmission",requiredTier:v,title:"Transmission & Volume",tooltip:"Controls glass-like transmission and how light travels through volume.",toggleLabel:"Toggle Transmission and Volume",controls:l,children:ue("div",{className:"bb-grid",children:[P(ee,{label:"Transmission",value:n?.transmission,min:0,max:1,step:.01,onChange:d=>f(t,a=>({...a,transmission:d}))}),P(ve,{label:"Transmission map path",placeholder:"materials/body-transmission.jpg",value:n?.transmissionMap?.path??"",onChange:d=>C(t,"transmissionMap",d)}),P(ee,{label:"Thickness",value:n?.thickness,min:0,max:5,step:.01,onChange:d=>f(t,a=>({...a,thickness:d}))}),P(ve,{label:"Thickness map path",placeholder:"materials/body-thickness.jpg",value:n?.thicknessMap?.path??"",onChange:d=>C(t,"thicknessMap",d)}),P(rt,{label:"Volume tint",value:n?.attenuationColor??"#ffffff",onChange:d=>f(t,a=>({...a,attenuationColor:d}))}),P(Ki,{label:"Attenuation distance",value:n?.attenuationDistance,min:0,step:.01,placeholder:"Infinity when unset",onChange:d=>f(t,a=>({...a,attenuationDistance:d}))})]})}),P(Ee,{panelKey:"faces",requiredTier:v,title:"Faces Rendering",tooltip:"Chooses which side of the mesh renders and how backfaces are handled.",controls:l,children:P("div",{className:"bb-grid",children:P(jt,{label:"Side",value:n?.side??"front",options:Va,onChange:d=>f(t,a=>({...a,side:d}))})})})]})}var Yi=[{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 ko,jsxs as Bd}from"react/jsx-runtime";function qi({disabled:t,onApply:n}){return ko("div",{className:"bb-presetGallery",children:Yi.map(i=>Bd("button",{type:"button",className:"bb-presetSwatch",disabled:t,title:`Apply ${i.label} preset`,onClick:()=>n(i.material),children:[ko("span",{className:"bb-presetSwatchColor",style:{background:i.swatch}}),ko("span",{className:"bb-presetSwatchLabel",children:i.label})]},i.id))})}import{useEffect as Rd,useRef as Md,useState as Ad}from"react";import{ChevronDown as Od,Download as zd,FileCode2 as Ld,FileJson as Ed}from"lucide-react";import{jsx as zn,jsxs as on}from"react/jsx-runtime";function No({disabled:t,exporting:n,onExportJson:i,onExportTs:r}){let[e,o]=Ad(!1),u=Md(null);return Rd(()=>{if(!e)return;let b=f=>{u.current?.contains(f.target)||o(!1)};return window.addEventListener("pointerdown",b),()=>window.removeEventListener("pointerdown",b)},[e]),on("div",{className:"bb-exportMenuWrapper",ref:u,children:[on("button",{type:"button",className:"bb-button bb-button--ghost",disabled:t||n,onClick:()=>o(b=>!b),title:"Export",children:[zn(zd,{size:14}),n?"Exporting\u2026":"Export",zn(Od,{size:12})]}),e&&on("div",{className:"bb-exportMenu",children:[on("button",{type:"button",className:"bb-exportMenuItem",onClick:()=>{o(!1),i()},children:[zn(Ed,{size:14}),"JSON"]}),on("button",{type:"button",className:"bb-exportMenuItem",onClick:()=>{o(!1),r()},children:[zn(Ld,{size:14}),"TypeScript"]})]})]})}import{jsx as Nt,jsxs as To}from"react/jsx-runtime";function Ji({selectedItem:t,selectedBinding:n,open:i,onToggle:r,updateBinding:e,idError:o}){return Nt(Te,{title:"Identity",open:i,onToggle:r,children:To("div",{className:"bb-grid",children:[To("div",{className:"bb-field bb-field--full",children:[Nt("label",{className:"bb-label",children:"Model Node ID"}),Nt("span",{className:"bb-note",children:"This is the exact mesh name from the imported model and stays locked."}),Nt("input",{className:"bb-input bb-readonly",value:n.modelObjectId,readOnly:!0})]}),To("div",{className:"bb-field bb-field--full",children:[Nt("label",{className:"bb-label",children:"ID"}),Nt("input",{className:`bb-input ${o?"bb-input--error":""}`,value:n.id,onChange:u=>e(t,b=>({...b,id:u.target.value}))}),o?Nt("span",{className:"bb-status bb-status--error",children:o}):null]})]})})}import{useEffect as jd,useState as Xi}from"react";import{jsx as Pe,jsxs as Ke}from"react/jsx-runtime";function Zi({selectedItem:t,selectedBinding:n,open:i,onToggle:r,updateBinding:e}){let[o,u]=Xi(n.group??""),[b,f]=Xi(n.tags?.join(", ")??"");jd(()=>{u(n.group??""),f(n.tags?.join(", ")??"")},[t,n.group,n.tags]);let C=()=>{e(t,m=>({...m,group:o.trim()||void 0}))},M=()=>{let m=[...new Set(b.split(",").map(l=>l.trim()).filter(Boolean))];e(t,l=>({...l,tags:m.length>0?m:void 0}))};return Ke(Te,{title:"Basics",open:i,onToggle:r,children:[Ke("div",{className:"bb-grid",children:[Ke("div",{className:"bb-field",children:[Pe("label",{className:"bb-label",children:"Label"}),Pe("input",{className:"bb-input",value:n.label??"",onChange:m=>e(t,l=>({...l,label:m.target.value}))})]}),Ke("div",{className:"bb-field",children:[Pe("label",{className:"bb-label",children:"Type"}),Pe("input",{className:"bb-input",list:"binding-type-suggestions",value:n.type??"other",onChange:m=>e(t,l=>({...l,type:m.target.value}))}),Pe("datalist",{id:"binding-type-suggestions",children:Ai.map(m=>Pe("option",{value:m},m))})]}),Ke("div",{className:"bb-field",children:[Pe("label",{className:"bb-label",children:"Status"}),Pe("select",{className:"bb-select",value:n.status??"normal",onChange:m=>e(t,l=>({...l,status:m.target.value})),children:On.map(m=>Pe("option",{value:m,children:m},m))})]}),Ke("div",{className:"bb-field",children:[Pe("label",{className:"bb-label",children:"Group"}),Pe("input",{className:"bb-input",placeholder:"paint",value:o,onChange:m=>u(m.target.value),onBlur:C,onKeyDown:m=>{m.key==="Enter"&&m.currentTarget.blur()}})]}),Ke("div",{className:"bb-field",children:[Pe("label",{className:"bb-label",children:"Tags"}),Pe("input",{className:"bb-input",placeholder:"exterior, configurable",value:b,onChange:m=>f(m.target.value),onBlur:M,onKeyDown:m=>{m.key==="Enter"&&m.currentTarget.blur()}})]})]}),Ke("div",{className:"bb-checkboxRow",style:{marginTop:12},children:[Ke("label",{className:"bb-checkbox",children:[Pe("input",{type:"checkbox",checked:n.selectable??!1,onChange:m=>e(t,l=>({...l,selectable:m.target.checked}))}),"selectable"]}),Ke("label",{className:"bb-checkbox",children:[Pe("input",{type:"checkbox",checked:n.hoverable??!1,onChange:m=>e(t,l=>({...l,hoverable:m.target.checked}))}),"hoverable"]}),Ke("label",{className:"bb-checkbox",children:[Pe("input",{type:"checkbox",checked:n.visible??!1,onChange:m=>e(t,l=>({...l,visible:m.target.checked}))}),"visible"]})]})]})}import{useEffect as Dd,useState as Id}from"react";import{Fragment as Hd,jsx as ye,jsxs as He}from"react/jsx-runtime";var Qi=eo.filter(t=>t.handling==="viewer"),Fd=eo.filter(t=>t.handling==="host");function er({selectedItem:t,selectedBinding:n,open:i,onToggle:r,updateBinding:e}){let[o,u]=Id(new Set);Dd(()=>{u(new Set)},[t]);let b=n.actions??[],f=(m,l)=>e(t,S=>({...S,actions:(S.actions??[]).map((B,v)=>v===m?l(B):B)})),C=m=>{e(t,l=>({...l,actions:(l.actions??[]).filter((S,B)=>B!==m)})),u(l=>{let S=new Set;return l.forEach(B=>{B<m?S.add(B):B>m&&S.add(B-1)}),S})},M=(m,l)=>u(S=>{let B=new Set(S);return l?B.add(m):B.delete(m),B});return He(Te,{title:"Actions",open:i,onToggle:r,children:[ye("div",{className:"bb-actionList",children:b.map((m,l)=>{let S=kn(m.id),B=o.has(l)||!S,v=m.id.trim(),F=S?null:ua(m.id),x=v.length>0&&b.some((g,N)=>N!==l&&g.id.trim()===v);return He("div",{className:"bb-actionCard",children:[He("div",{className:"bb-actionCardHeader",children:[He("div",{className:"bb-actionCardTitle",children:["Action ",l+1]}),ye("div",{className:"bb-actionCardMeta",children:m.type})]}),He("div",{className:"bb-actionGrid",children:[He("div",{className:"bb-field",children:[ye("label",{className:"bb-label",children:"Action ID"}),He("select",{className:"bb-select",value:B?Sn:m.id,onChange:g=>{let N=g.target.value;if(N===Sn){M(l,!0);return}M(l,!1);let z=kn(N);f(l,c=>({...c,id:N,label:z&&to(c.label)?z.label:c.label}))},children:[ye("optgroup",{label:"Handled by the viewer",children:Qi.map(g=>ye("option",{value:g.id,children:g.id},g.id))}),ye("optgroup",{label:"Handled by your app",children:Fd.map(g=>ye("option",{value:g.id,children:g.id},g.id))}),ye("option",{value:Sn,children:"Custom\u2026"})]})]}),B?He("div",{className:"bb-field",children:[ye("label",{className:"bb-label",children:"Custom action ID"}),ye("input",{className:"bb-input",value:m.id,placeholder:"open-datasheet",onChange:g=>{M(l,!0),f(l,N=>({...N,id:g.target.value}))}})]}):null,He("div",{className:"bb-field",children:[ye("label",{className:"bb-label",children:"Label"}),ye("input",{className:"bb-input",value:m.label,onChange:g=>f(l,N=>({...N,label:g.target.value}))})]}),S?ye("span",{className:"bb-note",children:S.description}):v.length===0?ye("span",{className:"bb-note",style:{color:"#fca5a5"},children:"An action ID is required, the button renders but can never be identified in onAction."}):He("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.",F?He(Hd,{children:[" Did you mean ",ye("button",{type:"button",className:"bb-linkButton",onClick:()=>{M(l,!1);let g=kn(F);f(l,N=>({...N,id:F,label:g&&to(N.label)?g.label:N.label}))},children:F}),"?"]}):null]}),m.effects?.length?He("span",{className:"bb-note",children:[m.effects.length," declarative effect",m.effects.length===1?"":"s",", execute with useViewerActions."]}):null,x?ye("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]}),ye("div",{className:"bb-actionFooter",children:ye("button",{type:"button",className:"bb-button bb-button--ghost bb-actionRemove",onClick:()=>C(l),children:"Remove Action"})})]},l)})}),ye("div",{style:{marginTop:10},children:ye("button",{type:"button",className:"bb-button",onClick:()=>{let m=Qi.find(l=>!b.some(S=>S.id===l.id));e(t,l=>({...l,actions:[...l.actions??[],{id:m?.id??"",label:m?.label??"New Action",type:"command"}]})),m||M(b.length,!0)},children:"Add Action"})})]})}import{useRef as Gd}from"react";import{ImagePlus as Vd,Move as $d,Trash2 as Ud,Type as Kd}from"lucide-react";import{Fragment as nr,jsx as ge,jsxs as _e}from"react/jsx-runtime";var tr=()=>`decal-${Date.now().toString(36)}-${Math.random().toString(36).slice(2,8)}`;function or({selectedItem:t,selectedBinding:n,open:i,onToggle:r,updateBinding:e,placement:o,onPlacementChange:u,defaultSize:b,onImageFile:f,onNudge:C}){let{tier:M}=Ze(),m=Gd(null),l=n.decals??[],S=o?.nodeKey===t?o:null,B=x=>e(t,g=>({...g,decals:x.length>0?x:void 0})),v=(x,g)=>B(l.map(N=>N.id===x?{...N,...g}:N)),F=x=>{x.image&&_t(x.image),S?.decal.id===x.id&&u(null),B(l.filter(g=>g.id!==x.id))};return ge(Te,{title:"Decals",open:i,onToggle:r,tooltip:"Print a logo, image, or text on the selected object's surface.",children:Ue(M,"starter")?_e(nr,{children:[_e("div",{className:"bb-decalActions",children:[_e("button",{type:"button",className:"bb-button bb-button--ghost",onClick:()=>m.current?.click(),children:[ge(Vd,{size:15})," Add image"]}),_e("button",{type:"button",className:"bb-button bb-button--ghost",onClick:()=>u({nodeKey:t,decal:{id:tr(),text:"Your text",color:"#ffffff",size:b}}),children:[ge(Kd,{size:15})," Add text"]}),ge("input",{ref:m,type:"file",accept:"image/png,image/jpeg,image/webp,image/avif,image/svg+xml",className:"bb-hiddenInput",onChange:x=>{let g=x.target.files?.[0];if(x.target.value="",!g)return;let N=Nn(g);xt(N,URL.createObjectURL(g)),f?.(N,g),u({nodeKey:t,decal:{id:tr(),image:N,size:b}})}})]}),l.length===0&&!S?ge("div",{className:"bb-decalEmpty",children:"No decals on this object yet."}):null,l.map(x=>_e("div",{className:"bb-decalCard",children:[_e("div",{className:"bb-decalCardHeader",children:[ge("span",{className:"bb-decalKind",children:x.image?"Image":"Text"}),ge("span",{className:"bb-decalName",title:x.image??x.text,children:x.image??x.text}),ge("button",{type:"button",className:"bb-iconButton",title:"Move: drag the decal in the preview","aria-label":"Move decal","aria-pressed":S?.decal.id===x.id,onClick:()=>{let{position:g,normal:N,...z}=x;u(S?.decal.id===x.id?null:{nodeKey:t,decal:z,moving:!0})},children:ge($d,{size:15})}),ge("button",{type:"button",className:"bb-iconButton bb-iconButton--danger",title:"Delete decal","aria-label":"Delete decal",onClick:()=>F(x),children:ge(Ud,{size:15})})]}),ge(ma,{onNudge:g=>C(x.id,g)}),_e("div",{className:"bb-grid",children:[x.image?null:_e(nr,{children:[_e("div",{className:"bb-field bb-field--full",children:[ge("label",{className:"bb-label",children:"Text"}),ge("input",{className:"bb-input",value:x.text??"",onChange:g=>v(x.id,{text:g.target.value})})]}),ge(rt,{label:"Colour",variant:"input",value:x.color??"#ffffff",onChange:g=>v(x.id,{color:g})}),_e("div",{className:"bb-field",children:[ge("label",{className:"bb-label",children:"Weight"}),_e("select",{className:"bb-input bb-decalWeight",value:x.fontWeight??"bold",onChange:g=>v(x.id,{fontWeight:g.target.value}),children:[ge("option",{value:"bold",children:"Bold"}),ge("option",{value:"normal",children:"Regular"})]})]})]}),ge(ee,{label:"Size",value:Number(x.size.toFixed(4)),min:Number((b/20).toPrecision(2)),max:Number((b*6).toPrecision(2)),step:Number((b/50).toPrecision(1)),onChange:g=>g!==void 0&&g>0&&v(x.id,{size:g})}),ge(ee,{label:"Rotation (\xB0)",value:Math.round((x.rotation??0)*180/Math.PI),min:-180,max:180,step:1,onChange:g=>v(x.id,{rotation:(g??0)*Math.PI/180})}),ge(ee,{label:"Opacity",value:x.opacity??1,min:0,max:1,step:.05,onChange:g=>v(x.id,{opacity:g??1})})]})]},x.id))]}):ge(ke,{requiredTier:"starter",feature:"Decals"})})}import{MapPin as _d,Trash2 as Wd}from"lucide-react";import{Fragment as Yd,jsx as Ge,jsxs as je}from"react/jsx-runtime";function ar({selectedBinding:t,open:n,onToggle:i,cameraState:r,formattedCameraState:e,savedCameraPosition:o,onSaveCameraPosition:u,onGoToSavedCamera:b,onClearSavedCamera:f,onResetView:C,onFitScene:M}){return je(Te,{title:"Camera Position",open:n,onToggle:i,children:[je("div",{className:"se-waypointCard bb-cameraWaypoint",children:[Ge("span",{className:"bb-cameraLiveBadge",children:"LIVE"}),je("div",{className:"se-waypointBody",children:[Ge("div",{className:"bb-cameraWaypointLabel",children:"Current view"}),r?je(Yd,{children:[je("div",{className:"se-waypointCoords",children:["pos ",e?.position]}),je("div",{className:"se-waypointCoords",children:["look ",e?.target]})]}):Ge("div",{className:"se-waypointCoords",children:"Move the camera to see live position"})]})]}),je("div",{className:"bb-cameraControls bb-cameraControls--centered",children:[Ge("button",{type:"button",className:"bb-button bb-button--primary",onClick:u,disabled:!r,children:"Save"}),Ge("button",{type:"button",className:"bb-button bb-button--ghost",onClick:C,children:"Reset View"}),Ge("button",{type:"button",className:"bb-button bb-button--ghost",onClick:M,children:"Fit Scene"})]}),o?.position&&o?.target&&je("div",{className:"se-waypointCard bb-cameraWaypoint",children:[Ge("span",{className:"bb-cameraSavedBadge",children:"SAVED"}),je("div",{className:"se-waypointBody",children:[je("div",{className:"bb-cameraWaypointLabel",children:["For ",t.label]}),je("div",{className:"se-waypointCoords",children:["pos [",o.position.map(m=>m.toFixed(1)).join(", "),"]"]}),je("div",{className:"se-waypointCoords",children:["look [",o.target.map(m=>m.toFixed(1)).join(", "),"]"]})]}),je("div",{className:"se-waypointActions",children:[Ge("button",{className:"se-waypointAction",onClick:b,title:"Fly camera to the saved position",children:Ge(_d,{size:15})}),Ge("button",{className:"se-waypointAction se-waypointAction--delete",onClick:f,title:"Delete saved position",children:Ge(Wd,{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 qd,useRef as Jd,useState as Xd}from"react";import{Move3d as Zd,RotateCcw as Qd}from"lucide-react";import{jsx as de,jsxs as We}from"react/jsx-runtime";var ir=["X","Y","Z"];var ec=.1;function Po(t){let n=t%360;return n<0?n+360:n}function rr(t){return Po(t*180/Math.PI)}function sr(t){return t*Math.PI/180}function tc(t,n,i){let r=[...t],e=rr(t[n]);return r[n]=sr(Po(e+i)),r}function lr({value:t,min:n=-1/0,max:i=1/0,step:r=.1,disabled:e=!1,onChange:o,formatValue:u=C=>Number(C.toFixed(3)),ariaLabel:b,className:f}){let C=u(t),[M,m]=Xd(String(C)),l=Jd(!1);return qd(()=>{l.current||m(String(C))},[C]),de("input",{type:"number",className:f,step:r,min:n===-1/0?void 0:n,max:i===1/0?void 0:i,value:M,disabled:e,"aria-label":b,onFocus:()=>{l.current=!0},onChange:S=>{let B=S.target.value;if(m(B),B===""||B==="-")return;let v=Number(B);if(Number.isFinite(v)){let F=Math.max(n,Math.min(i,v));o(F)}},onBlur:()=>{l.current=!1,m(String(u(t)))}})}function nc({value:t,min:n=-1/0,max:i=1/0,step:r=.1,disabled:e=!1,onChange:o,formatValue:u=f=>Number(f.toFixed(3)),label:b}){return de("div",{className:"bb-transformAxesGrid",children:ir.map((f,C)=>We("div",{className:"bb-transformAxis",children:[de("span",{className:"se-axisStepperLabel bb-transformAxisLabel",children:f}),de("div",{className:"bb-transformAxisControl",children:de(lr,{className:"se-numberInput bb-transformNumberInput",step:r,min:n,max:i,value:t[C],disabled:e,formatValue:u,ariaLabel:`${f} ${b?.toLowerCase()||""}`,onChange:M=>{let m=[...t];m[C]=M,o(m)}})})]},f))})}function dr({selectedItem:t,selectedBinding:n,open:i,onToggle:r,updateBinding:e,moveModeEnabled:o,onToggleMoveMode:u,transformSpace:b,onTransformSpaceChange:f,originalTransform:C}){let M=n.transform?.rotation??C?.rotation??[0,0,0],m=n.transform?.position??C?.position??[0,0,0],l=(g,N)=>{let z=g.transform?.rotation??C?.rotation??[0,0,0],c=g.transform?.position??C?.position??[0,0,0],h=g.transform?.scale??C?.scale??[1,1,1],d=C?.pivotLocal??[0,0,0],a=Fa(c,z,N,h,d,C?.rotationOrder??"XYZ");return{...g,transform:{...g.transform,position:a,rotation:N}}},S=(g,N)=>{t&&e(t,z=>{let c=z.transform?.rotation??C?.rotation??[0,0,0],h=tc(c,g,N);return l(z,h)})},B=(g,N)=>{t&&e(t,z=>{let h=[...z.transform?.rotation??C?.rotation??[0,0,0]];return h[g]=sr(Po(N)),l(z,h)})},v=(g,N)=>{t&&e(t,z=>{let h=[...z.transform?.position??C?.position??[0,0,0]];return h[g]=N,{...z,transform:{...z.transform,position:h}}})},F=(g,N)=>{t&&v(g,m[g]+N)},x=()=>{!t||!C||e(t,g=>{let N={...g.transform};return delete N.position,delete N.rotation,{...g,transform:Object.keys(N).length>0?N:void 0}})};return We(Te,{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:[We("div",{className:"se-field",children:[We("div",{className:"se-fieldLabel",children:[We("span",{children:[de(Zd,{size:14,style:{marginRight:6,verticalAlign:"-2px"}}),"Transform gizmo"]}),We("label",{className:"se-switch","aria-label":"Toggle move mode",children:[de("input",{type:"checkbox",checked:o,onChange:g=>u(g.target.checked)}),de("span",{className:"se-switchTrack",children:de("span",{className:"se-switchThumb"})})]})]}),de("span",{className:"bb-note",children:"Select a mesh \xB7 drag the colored arrows or planes to move"})]}),We("div",{className:"se-field",style:{marginTop:10},children:[de("div",{className:"se-fieldLabel",children:de("span",{children:"Axis space"})}),de("div",{className:"se-segmentedControl",children:["world","local"].map(g=>de("button",{type:"button",className:`se-segmentedOption ${b===g?"se-segmentedOption--active":""}`,onClick:()=>f(g),children:g},g))})]}),We("div",{className:"se-field",style:{marginTop:10},children:[de("div",{className:"se-fieldLabel",children:de("span",{children:"Rotation (degrees)"})}),de("div",{className:"bb-transformAxesGrid",children:ir.map((g,N)=>{let z=Math.round(rr(M[N]));return We("div",{className:"bb-transformAxis",children:[de("span",{className:"se-axisStepperLabel bb-transformAxisLabel",children:g}),de("div",{className:"bb-transformAxisControl",children:de(lr,{className:"se-numberInput bb-transformNumberInput",step:1,min:0,max:359,value:z,disabled:!t,formatValue:c=>Math.round(c),ariaLabel:`${g} rotation in degrees`,onChange:c=>B(N,c)})})]},g)})})]}),We("div",{className:"se-field",style:{marginTop:10},children:[de("div",{className:"se-fieldLabel",children:de("span",{children:"Position"})}),de(nc,{value:m,min:-1/0,max:1/0,step:ec,disabled:!t,label:"position",onChange:g=>{t&&e(t,N=>({...N,transform:{...N.transform,position:g}}))}})]}),We("button",{type:"button",className:"bb-button bb-button--ghost",style:{marginTop:10,display:"inline-flex",alignItems:"center",gap:6},disabled:!t||!C,onClick:x,title:"Restore this node's position and rotation to what they were in the original model",children:[de(Qd,{size:14}),"Restore original position & rotation"]})]})}import{memo as oc,useMemo as cr,useState as ac}from"react";import{Focus as ic}from"lucide-react";import{Fragment as sc,jsx as st,jsxs as lt}from"react/jsx-runtime";var br=oc(rc);function rc({bindings:t,selectedItem:n,onSelect:i,onHover:r,isOpen:e=!0,onToggle:o,isolatedItem:u=null,onIsolate:b}){let[f,C]=ac(""),M=cr(()=>Object.keys(t),[t]),m=cr(()=>{let l=f.trim().toLowerCase();return l?M.filter(S=>{let B=t[S];return S.toLowerCase().includes(l)||B.label?.toLowerCase().includes(l)||(B.type??"other").toLowerCase().includes(l)}):M},[t,M,f]);return lt("aside",{className:`bb-sidebar bb-sidebar--right ${e?"":"bb-sidebar--collapsed"}`,children:[lt("div",{className:"bb-header bb-header--sidebar",children:[!e&&st("button",{type:"button",className:"bb-sidebarToggle",onClick:()=>o?.(!0),"aria-label":"Open scene nodes sidebar",title:"Open scene nodes",children:"\u2190"}),e&<(sc,{children:[lt("div",{children:[st("div",{className:"bb-sectionKicker",children:"Scene Nodes"}),lt("div",{className:"bb-sectionHeading",children:[m.length," visible entries"]})]}),st("button",{type:"button",className:"bb-sidebarToggle",onClick:()=>o?.(!1),"aria-label":"Close scene nodes sidebar",title:"Close scene nodes",children:"\u2192"})]})]}),e&<("section",{className:"bb-nodeList",children:[st("div",{className:"bb-search",children:st("input",{className:"bb-input",placeholder:"Search nodes, labels, or types",value:f,onChange:l=>C(l.target.value)})}),st("div",{className:"bb-nodeItems",children:m.map(l=>{let S=t[l],B=l===n,v=l===u;return lt("div",{className:`bb-nodeRow ${u&&!v?"bb-nodeRow--setAside":""}`,children:[lt("button",{type:"button",className:`bb-nodeButton ${B?"bb-nodeButton--active":""}`,onClick:()=>i(l),onMouseEnter:()=>r?.(l),onMouseLeave:()=>r?.(null),children:[st("span",{className:"bb-nodeName",children:l}),lt("span",{className:"bb-nodeMeta",children:[S.type??"other",S.label===La(l)?"":S.label||"\xB7 Untitled"]})]}),b?st("button",{type:"button",className:`bb-nodeIsolate ${v?"bb-nodeIsolate--active":""}`,onClick:()=>b(v?null:l),title:v?"Show all":"Isolate in the preview","aria-label":`${v?"Show all":"Isolate"} ${l}`,"aria-pressed":v,children:st(ic,{size:14,"aria-hidden":"true"})}):null]},l)})})]})]})}import{jsx as Ln,jsxs as pr}from"react/jsx-runtime";function Bo({title:t,label:n,open:i,onToggle:r,draft:e,error:o,example:u,onDraftChange:b,onCommit:f}){return Ln(Te,{title:t,open:i,onToggle:r,children:pr("div",{className:"bb-field",children:[Ln("label",{className:"bb-label",children:n}),Ln("textarea",{className:"bb-textarea",value:e,onChange:C=>b(C.target.value),onBlur:f}),o?Ln("span",{className:"bb-status bb-status--error",children:o}):pr("span",{className:"bb-note",children:["Use a JSON object like ",u,"."]})]})})}function ur(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}}import{useCallback as an,useReducer as lc,useRef as dc}from"react";var cc=100;function bc(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;return n.coalesce?{...t,present:i,future:[],edits:r}:{past:[...t.past,t.present].slice(-cc),present:i,future:[],edits:r}}case"undo":{if(t.past.length===0)return t;let i=t.past[t.past.length-1];return{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{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}}}function Ro(t,n=600){let[i,r]=lc(bc,{past:[],present:t,future:[],edits:0}),e=dc(0),o=an(M=>{let m=Date.now(),l=m-e.current<n;e.current=m,r({type:"set",updater:M,coalesce:l,track:!0})},[n]),u=an(M=>{let m=Date.now()-e.current<n;r({type:"set",updater:M,coalesce:m,track:!1})},[n]),b=an(()=>{e.current=0,r({type:"undo"})},[]),f=an(()=>{e.current=0,r({type:"redo"})},[]),C=an((M,m)=>{e.current=0,r({type:"reset",value:M,track:m?.asEdit??!1})},[]);return{value:i.present,setValue:o,setValueUntracked:u,undo:b,redo:f,reset:C,canUndo:i.past.length>0,canRedo:i.future.length>0,edits:i.edits}}import{strToU8 as pc}from"fflate";function mr(t){return JSON.stringify(t,null,2)}function gr(t){return['import { defineObjectBindings } from "@liveroom-tech/react-immersive/utils";',"",`export const objectBindings = defineObjectBindings(${JSON.stringify(t,null,2)});`,""].join(`
|
|
2
|
+
`)}function fr(t){return JSON.stringify(t,null,2)}function hr(t){return['import type { SceneConfig } from "@liveroom-tech/react-immersive/utils";',"",`export const sceneConfig: SceneConfig = ${JSON.stringify(t,null,2)};`,""].join(`
|
|
3
|
+
`)}function rn(t,n,i){Tn(new Blob([n],{type:i}),t)}function Mo(t){return JSON.stringify(t??{},null,2)}function Ao(t){return`[${t[0].toFixed(3)}, ${t[1].toFixed(3)}, ${t[2].toFixed(3)}]`}function uc(t){return(t.decals??[]).map(n=>n.image).filter(n=>!!n?.trim())}function mc(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 xr(t){let n=new Set;for(let e of Object.values(t)){for(let o of mc(e))n.add(o);for(let o of uc(e))n.add(o)}let i=[],r=[];return await Promise.all(Array.from(n).map(async e=>{let o=fa(e);if(o)try{let u=await fetch(o);if(!u.ok)throw new Error(String(u.status));i.push({path:e,blob:await u.blob()});return}catch{r.push(e);return}try{let u=await Jt(e);u&&i.push({path:e,blob:u})}catch{}})),{assets:i,failedPaths:r}}async function Oo(t,n,i,r,e){if(e.length===0){rn(t,n,i);return}let o={[t]:pc(n)};for(let b of e)o[b.path]=new Uint8Array(await b.blob.arrayBuffer());let u=await va(o);Tn(new Blob([u],{type:"application/zip"}),r)}var zo={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"]},vr=Object.keys(zo);function yr(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 Lo(t){if(t)return Object.values(t).some(yr)?t:void 0}function Ve(t,n){return t?zo[n].some(i=>yr(t[i])):!1}function Eo(t){return{pbr:Ve(t,"pbr"),roughness:Ve(t,"roughness"),emission:Ve(t,"emission"),opacity:Ve(t,"opacity"),normalBump:Ve(t,"normalBump"),displacement:Ve(t,"displacement"),ao:Ve(t,"ao"),clearcoat:Ve(t,"clearcoat"),sheen:Ve(t,"sheen"),anisotropy:Ve(t,"anisotropy"),transmission:Ve(t,"transmission"),faces:Ve(t,"faces")}}function jo(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 wr(t,n){if(!t)return;let i={...t};for(let r of zo[n])delete i[r];return i}import{Fragment as It,jsx as T,jsxs as U}from"react/jsx-runtime";var Br="/room.glb",hc=500;function xc(){return`${Date.now().toString(36)}-${Math.random().toString(36).slice(2,10)}`}function Rr(t){return`Couldn't reload ${t} from your last session. It's still saved in this browser.`}function vc(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 En(t){return t!==null&&typeof t=="object"&&!Array.isArray(t)}function Do(t,n){if(!En(t)||!En(n))return n??t;let i={...t};for(let[r,e]of Object.entries(n)){let o=i[r];i[r]=En(o)&&En(e)?Do(o,e):e}return i}function yc({licenseKey:t,licenseValidationUrl:n,dracoDecoderPath:i,ktx2TranscoderPath:r,meshopt:e,project:o,onProjectChange:u,projectChangeDebounceMs:b=350,onModelUpload:f,onTextureUpload:C,onEditLeaseChange:M,allowModelChange:m=!0}){let l=se(null),S=se(null),B=se(null),[v,F]=K(o?.model.url??null),[x,g]=K(o?.model.name??""),[N,z]=K(o?.model??null),[c,h]=K(null),d=Ro(o?.objectBindings??{}),a=d.value,R=d.setValue,[H,D]=K(!1),[ne,qe]=K(null),Ft=Dt(()=>ne?{target:ne}:null,[ne]),[Tt,mt]=K(null);Ye(()=>mt(null),[c,v]);let[Mr,Ar]=K([]),[Or,gt]=K(null),[Io,Fo]=K(!1),[Ho,V]=K("Load the demo model or upload a GLB, GLTF, OBJ, FBX, or USDZ model to generate bindings."),[sn,_]=K("default"),[zr,Ht]=K(!1),[Go,ln]=K("{}"),[Vo,dn]=K("{}"),[Lr,cn]=K(null),[Er,bn]=K(null),[jr,Gt]=K(!1),[Pt,Dr]=K(!1),[Ir,Fr]=K(!1),[tt,Hr]=K({identity:!0,basics:!0,material:!1,decals:!1,actions:!1,camera:!1,transform:!1,metrics:!1,metadata:!1}),[Gr,Vr]=K({pbr:!1,roughness:!1,emission:!1,opacity:!1,normalBump:!1,displacement:!1,ao:!1,clearcoat:!1,sheen:!1,anisotropy:!1,transmission:!1,faces:!1}),nt=s=>Hr(p=>({...p,[s]:!p[s]})),$r=s=>Vr(p=>({...p,[s]:!p[s]})),[ot,jn]=K("object"),[pn,$o]=K("General"),[Ur,Kr]=K("metalness"),[_r,Dn]=K(Eo()),Uo=se(null),[Ko,Wr]=K(!1),[In,Yr]=K(!0),[_o,qr]=K(!0),[Jr,Wo]=K(!1),[Vt,Yo]=K(null),[un,Fn]=K(null),[Hn,qo]=K(!1),[Jo,Xr]=K("world"),Gn=se({}),Ne=Ro(o?.sceneConfig??Yt),Be=Ne.value,mn=Ne.setValue,$t=Ne.setValueUntracked,[Xo,Vn]=K("orbit"),we=Xo==="pointerLock",[Zo,Zr]=K(null),Qo=se(null),Qr=Zo?.objectKey===c&&Zo?.textureKey==="texture",[es,gn]=K(null),[ts,$n]=K(null),Ut=Ra(t,n),ea=Ja(Ut.tier),ns=Dt(()=>({isInsideEditor:!0,activeTab:ot,activeSubTab:pn,tier:ea,setActiveTab:jn,setActiveSubTab:$o}),[ot,pn,ea]),$e=se(null),Bt=se(0),at=se(0),ta=se(o?`${o.id}:${o.revision}`:null),na=se(null),oa=se(!1),Rt=se(!1),fn=se(o?{modelUrl:o.model.url,bindings:o.objectBindings,sceneConfig:o.sceneConfig}:null),hn=se(void 0),ft=se(0),Ce=se(null),De=se(o?{requestId:0,modelName:o.model.name??"model",modelUrl:o.model.url,storedBindings:o.objectBindings,streaming:!!o.model.tilesetUrl}:null),dt=se(null),xn=se(null),ct=se(null),Un=se(!1),ht=se(null),Kn=se(null),{cameraState:me,resetView:aa,focusObject:ia,fitScene:ra,setCameraState:vn,handleCameraChange:os,handleViewerReady:as}=Ma(),is=te(s=>{we||vn({position:s.position,target:s.target,fov:me?.fov??null,zoom:me?.zoom??1,azimuthAngle:s.azimuthAngle,polarAngle:s.polarAngle},!0)},[we,vn,me]),yn=Ga(),fe=c?a[c]??null:null,_n=fe?.style?.material,bt=fe?.cameraState,rs=me?{position:Ao(me.position),target:Ao(me.target)}:null,ss=te(s=>{mn(p=>{let y=p.annotations.map(L=>L.id).join(","),k=s.map(L=>L.id).join(",");return y===k?p:{...p,annotations:s}})},[]),ls=te(s=>{gn(s?{annotation:s}:null)},[]);Ye(()=>{if(!fe){ln("{}"),dn("{}"),cn(null),bn(null);return}ln(Mo(fe.metrics)),dn(Mo(fe.metadata)),cn(null),bn(null)},[fe]),Ye(()=>{let s=Eo(_n);if(Uo.current!==c){Uo.current=c,Dn(s);return}Dn(p=>{let y=!1,k={...p};for(let L of vr)s[L]&&!p[L]&&(k[L]=!0,y=!0);return y?k:p})},[c,_n]),Ye(()=>()=>{$e.current?.cleanup(),Ce.current&&clearTimeout(Ce.current)},[]);let Kt=te((s,p)=>{let y=Pn(s);if(p){let k=new Map(Object.values(p).map(L=>[L.modelObjectId,L]));for(let L of s){let I=k.get(L);I&&(y[L]=I)}}return y},[]);Ye(()=>{if(!o)return;let s=`${o.id}:${o.revision}`;if(ta.current===s)return;ta.current=s;let p=v!==o.model.url||N?.tilesetUrl!==o.model.tilesetUrl||N?.assetVersion!==o.model.assetVersion,y=a!==o.objectBindings,k=Be!==o.sceneConfig;(p||y||k)&&(Rt.current=!0),z(o.model),g(o.model.name??"model");let L=o.objectBindings;if(y){let I=na.current;L=I?Kt(I,o.objectBindings):o.objectBindings,d.reset(L)}if(k&&Ne.reset(o.sceneConfig),p){let I=++at.current;De.current={requestId:I,modelName:o.model.name??"model",modelUrl:o.model.url,storedBindings:o.objectBindings,streaming:!!o.model.tilesetUrl},ht.current=null,h(null),D(!0),F(o.model.url)}fn.current={modelUrl:o.model.url,bindings:L,sceneConfig:o.sceneConfig}},[a,Kt,o,v,Be,N,d,Ne]);let Wn=se(u);Wn.current=u,Ye(()=>{if(!o||!Wn.current||!v)return;if(!oa.current){oa.current=!0;return}let s=fn.current;if(v===o.model.url&&a===o.objectBindings&&Be===o.sceneConfig||s!==null&&v===s.modelUrl&&a===s.bindings&&Be===s.sceneConfig){Rt.current=!1;return}if(De.current)return;if(Rt.current){Rt.current=!1;return}let p=window.setTimeout(()=>{Wn.current?.({projectId:o.id,baseRevision:o.revision,model:{...N??o.model,url:v,name:x||o.model.name},objectBindings:a,sceneConfig:Be},"local")},b);return()=>window.clearTimeout(p)},[a,x,v,o,b,N,Be]),Ye(()=>{let s=p=>{if(p.key.toLowerCase()!=="z"||!(p.metaKey||p.ctrlKey))return;let y=p.target,k=y?.tagName;if(k==="INPUT"||k==="TEXTAREA"||y?.isContentEditable)return;p.preventDefault();let L=ot==="scene"?Ne:d;p.shiftKey?L.redo():L.undo()};return window.addEventListener("keydown",s),()=>window.removeEventListener("keydown",s)},[ot,d,Ne]);let Je=!o&&m,wn=d.edits>0||Ne.edits>0,ds=te(async(s,p)=>{if(C)return C(s,p);let y=URL.createObjectURL(s);if(Je)try{await ro(y,s)}catch(k){console.warn("[BindingBuilder] Could not store texture file for autosave:",k)}return y},[C,Je]),sa=te(async s=>(await Promise.all(Object.entries(s).map(async([p,y])=>{for(let L of y.decals??[])if(L.image)try{let I=await Jt(L.image);I&&xt(L.image,URL.createObjectURL(I))}catch(I){console.warn(`[BindingBuilder] Could not rehydrate a decal image on "${p}":`,I)}let k=y.style?.material;if(k)for(let L of ga){let Y=k[L]?.path;if(Y)try{let j=await Jt(Y);if(!j){console.warn(`[BindingBuilder] No stored texture found for "${p}"'s ${L} ("${Y}"). 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 oe=URL.createObjectURL(j);xt(Y,oe)}catch(j){console.warn(`[BindingBuilder] Could not rehydrate "${p}"'s ${L}:`,j)}}})),s),[]);Ye(()=>{if(!Je||!wn||!v)return;let s=dt.current;if(!s)return;let p=()=>{if(ct.current===p&&(ct.current=null),De.current)return;let{model:k,file:L}=s,I=k.kind==="file"&&xn.current!==k.key?L:void 0;Ua({model:k,bindings:a,sceneConfig:Be},I).then(()=>{xn.current=k.kind==="file"?k.key:null,Un.current=!1}).catch(Y=>{console.warn("[BindingBuilder] Autosave failed:",Y),!Un.current&&(Un.current=!0,V("Couldn't autosave this session \u2014 the browser refused to store it, possibly for lack of space. Export your work to keep it."),_("error"))})};ct.current=p;let y=window.setTimeout(p,hc);return()=>window.clearTimeout(y)},[Je,wn,v,a,Be]),Ye(()=>{if(!Je)return;let s=()=>ct.current?.(),p=()=>{document.visibilityState==="hidden"&&s()};return window.addEventListener("pagehide",s),document.addEventListener("visibilitychange",p),()=>{window.removeEventListener("pagehide",s),document.removeEventListener("visibilitychange",p),s()}},[Je]),Ye(()=>{if(!Je||!v||!wn)return;let s=p=>{ct.current?.(),p.preventDefault(),p.returnValue=""};return window.addEventListener("beforeunload",s),()=>window.removeEventListener("beforeunload",s)},[Je,v,wn]),Ye(()=>{if(H||sn==="default"||sn==="success")return;Ht(!0);let s=window.setTimeout(()=>Ht(!1),4e3);return()=>window.clearTimeout(s)},[Ho,sn,H]);let Xe=Dt(()=>Object.keys(a),[a]),cs=Dt(()=>!c||!fe?null:fe.id.trim()?Object.entries(a).some(([y,k])=>y!==c&&k.id===fe.id)?"Another binding already uses this ID.":null:"ID is required.",[a,c,fe]),Ie=(s,p)=>{R(y=>({...y,[s]:p(y[s])}))},Yn=(s,p)=>{Ie(s,y=>{let k=Lo(p(y.style?.material));return jo(y,k)})},bs=(s,p,y)=>{Yn(s,k=>({...k,[p]:y?{path:y}:void 0}))},ps=(s,p)=>{Dn(y=>({...y,[s]:p})),!p&&c&&Ie(c,y=>{let k=Lo(wr(y.style?.material,s));return jo(y,k)})},qn=te((s,p,y)=>{let k=ao(s),L=Pn(k);if(y){let Y=new Map(Object.values(y).map(j=>[j.modelObjectId,j]));for(let j of k){let oe=Y.get(j);oe&&(L[j]=oe)}}s.updateMatrixWorld(!0);let I={};for(let Y of k){let j=no(s,Y);if(!j){I[Y]={position:[0,0,0],rotation:[0,0,0],scale:[1,1,1],pivotLocal:[0,0,0],rotationOrder:"XYZ"};continue}let oe=Ia(j);I[Y]={position:[j.position.x,j.position.y,j.position.z],rotation:[j.rotation.x,j.rotation.y,j.rotation.z],scale:[j.scale.x,j.scale.y,j.scale.z],pivotLocal:[oe.x,oe.y,oe.z],rotationOrder:j.rotation.order}}Gn.current=I,d.reset(L),h(k[0]??null),y||$t(Y=>({...Y,annotations:[]})),V(`Generated ${k.length} bindings from ${p}.`),_("success"),ft.current=100,gt(100),Ce.current&&clearTimeout(Ce.current),Ce.current=setTimeout(()=>{Ce.current=null,D(!1),gt(null)},400)},[d,$t]),Jn=(s,p,y,k)=>{ct.current?.();let L=++at.current;D(!0),gt(null),ft.current=0,Ce.current&&(clearTimeout(Ce.current),Ce.current=null),hn.current=y;let I=y?y/1048576:0;V(I>=100?`Reading ${p} (${Math.round(I)}MB \u2014 large file, this can take a while)...`:`Reading ${p} and generating starter bindings...`),_("default"),g(p),z(k??{url:s,name:p}),gn(null);let Y=ht.current;if(s===v&&Y?.url===s){De.current=null,qn(Y.scene,p);return}De.current={requestId:L,modelName:p,modelUrl:s,streaming:!!k?.tilesetUrl},F(s),d.reset({}),h(null)},us=te(s=>{let p=De.current;if(!(!p||p.requestId!==at.current)){if(De.current=null,ht.current={url:p.modelUrl,scene:s},mt(null),Ar(Ba(s)),qe(null),p.streaming){V(`Streaming ${p.modelName}.`),_("success"),D(!1);return}p.storedBindings&&(Rt.current=!0),qn(s,p.modelName,p.storedBindings),p.restoring&&V(`Restored your last session with ${p.modelName}.`)}},[qn]),ms=te(s=>{let p=s.map(k=>k.name);if(p.length===0)return;na.current=p,Rt.current=!0;let y=Kt(p,o?.objectBindings);if(d.reset(y),o){let k=fn.current;fn.current={modelUrl:k?.modelUrl??o.model.url,bindings:y,sceneConfig:k?.sceneConfig??o.sceneConfig}}h(k=>k??p[0]??null),V(`Streaming ${p.length} bindable objects.`),_("success"),D(!1)},[Kt,d,o]),gs=te(s=>{let p=De.current;!p||p.requestId!==at.current||(De.current=null,console.error(s),p.restoring?(dt.current=null,F(null),V(Rr(p.modelName))):V(`Could not read ${p.modelName}. Make sure the file is a valid GLB, GLTF, OBJ, FBX, or USDZ asset.`),_("error"),Ce.current&&(clearTimeout(Ce.current),Ce.current=null),ft.current=0,D(!1),gt(null))},[]),fs=te(s=>{let p=null;if(s.lengthComputable&&s.total>0)p=s.loaded/s.total*100;else{let k=hn.current;k&&k>0&&(p=s.loaded/k*100)}if(p===null)return;let y=Math.min(90,Math.floor(p/10)*10);y>ft.current&&(ft.current=y,gt(y)),p>=99.5&&V(k=>k.startsWith("Finalizing")?k:"Finalizing model \u2014 parsing geometry and textures (large files can take a moment here)...")},[]),hs=te(s=>{yn.handleAnimationsReady(s);let p=s.clipDetails??s.clips.map(y=>({sourceName:y,duration:0}));$t(y=>({...y,animations:ur(y,p)}))},[yn,$t]),wc=async()=>{$e.current?.cleanup(),$e.current=null,dt.current={model:{kind:"url",url:Br,name:"room.glb"}},await Jn(Br,"room.glb")},la=async s=>{if(!m)return;if(f){try{D(!0),V(`Uploading ${s.name}...`),_("default");let y=await f(s);dt.current={model:{kind:"url",url:y.url,name:y.name??s.name}},await Jn(y.url,y.name??s.name,s.size,y)}catch(y){D(!1),V(y instanceof Error?y.message:`Could not upload ${s.name}.`),_("error")}return}let p;try{p=await Qn(s)}catch(y){V(y instanceof Error?y.message:"Could not read model file. Upload a .glb, .gltf, .obj, .fbx, .usdz, or .zip asset."),_("error");return}$e.current?.cleanup(),$e.current=p,dt.current={model:{kind:"file",key:xc(),name:p.name},file:s},await Jn(p.url,p.name,s.size,{url:p.url,name:p.name})},xs=async s=>{let p=s.target.files?.[0];p&&(await la(p),s.target.value="")},vs=()=>{ct.current?.(),$e.current?.cleanup(),$e.current=null,ht.current=null,De.current=null,dt.current=null,Gn.current={},Bt.current=0,Gt(!1),Ce.current&&(clearTimeout(Ce.current),Ce.current=null),ft.current=0,gt(null),hn.current=void 0,F(null),g(""),z(null),h(null),gn(null),d.reset({}),ln("{}"),dn("{}"),cn(null),bn(null),$n(null),qo(!1),$t(s=>({...s,animations:Yt.animations,annotations:[]})),V("Load the demo model or upload a GLB, GLTF, OBJ, FBX, or USDZ model to generate bindings."),_("default")},ys=()=>{l.current?.click()},ws=()=>{S.current?.click()},da=async s=>{Fo(!0);try{let{assets:p,failedPaths:y}=await xr(a);s==="json"?await Oo("objectBindings.json",mr(a),"application/json","objectBindings.zip",p):await Oo("objectBindings.ts",gr(a),"text/typescript","objectBindings-ts.zip",p),y.length>0?(V(`Exported, but ${y.length} uploaded image${y.length===1?"":"s"} couldn't be bundled: ${y.join(", ")}.`),_("error")):p.length>0&&(V(`Exported with ${p.length} uploaded image${p.length===1?"":"s"} bundled into the zip.`),_("success"))}catch(p){let y=p instanceof Error?p.message:"Unknown export error.";V(`Failed to export bindings: ${y}`),_("error")}finally{Fo(!1)}},Cs=async s=>{if(!Xe.length){V("Load a model before importing bindings."),_("error");return}let p;try{p=JSON.parse(await s.text())}catch{V(`${s.name} is not valid JSON.`),_("error");return}if(p===null||typeof p!="object"||Array.isArray(p)){V("Expected a JSON object mapping object IDs to bindings."),_("error");return}let y=new Map;for(let oe of Object.values(p))if(oe!==null&&typeof oe=="object"&&typeof oe.id=="string"&&typeof oe.type=="string"&&typeof oe.modelObjectId=="string"){let Oe=oe;y.set(Oe.modelObjectId,Oe)}if(y.size===0){V(`${s.name} doesn't look like an exported bindings file.`),_("error");return}let k={...a},L={},I=0;for(let oe of Object.keys(k)){let Oe=y.get(oe);Oe&&(k[oe]=Oe,L[oe]=Oe,I++)}if(I===0){V(`None of the object IDs in ${s.name} match this model \u2014 nothing imported.`),_("error");return}let Y=await sa(L);Object.assign(k,Y),R(k);let j=y.size-I;V(j>0?`Imported ${I} binding${I===1?"":"s"} from ${s.name} (${j} skipped \u2014 not in this model).`:`Imported ${I} binding${I===1?"":"s"} from ${s.name}.`),_("success")},Ss=async s=>{let p=s.target.files?.[0];p&&(await Cs(p),s.target.value="")},ks=()=>{B.current?.click()},Ns=async s=>{let p;try{p=JSON.parse(await s.text())}catch{V(`${s.name} is not valid JSON.`),_("error");return}if(p===null||typeof p!="object"||Array.isArray(p)){V("Expected a JSON object with scene config sections."),_("error");return}let y=["model","camera","lighting","wireframe","shadows","environment","background","groundShadows","postProcessing","animations","annotations","cinematic","styleRules","section"],k=p,L=y.filter(I=>k[I]!==void 0);if(L.length===0){V(`${s.name} doesn't look like an exported scene config file.`),_("error");return}mn(I=>{let Y={...I};for(let j of L)Y[j]=Do(I[j],k[j]);return Y}),V(`Imported ${L.length} section${L.length===1?"":"s"} from ${s.name}.`),_("success")},Ts=async s=>{let p=s.target.files?.[0];p&&(await Ns(p),s.target.value="")},Ps=s=>{s.preventDefault(),s.stopPropagation(),!(H||v)&&(Bt.current+=1,Gt(!0))},Bs=s=>{s.preventDefault(),s.stopPropagation(),!(H||v)&&(s.dataTransfer.dropEffect="copy",Gt(!0))},Rs=s=>{s.preventDefault(),s.stopPropagation(),!(H||v)&&(Bt.current=Math.max(0,Bt.current-1),Bt.current===0&&Gt(!1))},Ms=async s=>{if(s.preventDefault(),s.stopPropagation(),Bt.current=0,Gt(!1),H||v)return;let p=s.dataTransfer.files?.[0];p&&await la(p)},ca=(s,p,y)=>{if(!c)return;let k;try{k=JSON.parse(p)}catch{y("Invalid JSON");return}if(k===null||typeof k!="object"||Array.isArray(k)){y("Expected a JSON object");return}if(s==="metrics"&&Object.values(k).some(I=>typeof I!="number"||!Number.isFinite(I))){y("Metrics values must be numbers");return}Ie(c,L=>({...L,[s]:k})),y(null)},As=te((s,p)=>{Je&&ro(s,p).catch(y=>console.warn("[BindingBuilder] Could not store decal image for autosave:",y))},[Je]),Os=Dt(()=>{let s=ht.current?.scene,y=(s&&c?no(s,c):null)?.geometry;if(!y)return .2;y.boundingBox||y.computeBoundingBox();let k=y.boundingBox?.getSize(new gc),L=k?Math.max(k.x,k.y,k.z):0;return L>0&&Number.isFinite(L)?L/3:.2},[c,v,H]),zs=Dt(()=>{if(!Tt?.moving)return null;let{nodeKey:s,decal:p}=Tt,y=a[s],k=y?.decals?.find(L=>L.id===p.id);return k?{objectId:y.modelObjectId??s,decal:k,onCancel:()=>mt(null),onCommit:L=>{R(I=>{let Y=I[s];return Y?{...I,[s]:{...Y,decals:Y.decals?.map(j=>j.id===k.id?{...j,...L}:j)}}:I}),mt(null)}}:null},[a,Tt,R]),Ls=te((s,p)=>{if(!c)return;let y=a[c],k=y?.decals?.find(j=>j.id===s);if(!k)return;let L=Kn.current,I=L?.raw.nodes[y.modelObjectId??c],Y=xa(I,L?.raw.controls.camera,k,p);if(!Y){V("No visible surface in that direction. Try another arrow or rotate the view."),_("error"),Ht(!0);return}mt(null),Ht(!1),Ie(c,j=>({...j,decals:j.decals?.map(oe=>oe.id===s?{...oe,...Y}:oe)}))},[a,c,Ie]),Es=te(s=>{if(!s||s.moving){mt(s);return}let p=Kn.current,y=a[s.nodeKey],k=p?.raw.nodes[y?.modelObjectId??s.nodeKey],L=ha(k,p?.raw.controls.camera);if(!L){V("Could not find a surface on this object for the decal."),_("error"),Ht(!0);return}let I={...s.decal,...L};R(Y=>{let j=Y[s.nodeKey];if(!j)return Y;let oe=(j.decals??[]).filter(Oe=>Oe.id!==I.id);return{...Y,[s.nodeKey]:{...j,decals:[...oe,I]}}}),mt({...s,moving:!0})},[a,R]),js=te(s=>{if(we){Vn("orbit");return}if(!s){h(null);return}let p=Object.entries(a).find(([y,k])=>k===s||y===s.modelObjectId||k.modelObjectId===s.modelObjectId)?.[0]??null;h(p)},[we,a]),Ds=te(async s=>{if(we){Vn("orbit");return}h(s),$n(null),await ia(s)},[we,ia]),Is=te(s=>{$n(s?a[s]??null:null)},[a]),Fs=te(s=>Fr(!s),[]),Hs=te(()=>{if(we){V("Camera positions aren't available while Pointer Lock is the active camera controller."),_("error");return}if(!c||!me)return;let s={position:me.position,target:me.target,...me.fov!=null?{fov:me.fov}:{},zoom:me.zoom};Ie(c,p=>({...p,cameraState:s}))},[we,c,me]),Gs=te(()=>{if(we){V("Camera positions aren't available while Pointer Lock is the active camera controller."),_("error");return}!bt?.position||!bt?.target||vn({position:bt.position,target:bt.target,fov:bt.fov??me?.fov??null,zoom:bt.zoom??me?.zoom??1},!0)},[we,bt,vn,me]),Vs=te(()=>{we||c&&Ie(c,s=>({...s,cameraState:void 0}))},[we,c]),$s=te(async()=>{if(we){V("Reset View isn't available while Pointer Lock is the active camera controller."),_("error");return}await aa()},[we,aa]),Us=te(async()=>{if(we){V("Fit Scene isn't available while Pointer Lock is the active camera controller."),_("error");return}await ra()},[we,ra]),Ks=te(()=>{V("Texture position saved."),_("success"),Qo.current?.()},[]),ba=te(s=>{Yo(s),Wo(!0)},[]),Mt=te(()=>{Wo(!1),Yo(null)},[]),_s=te(()=>{if(Vt==="bindings"){if(!Xe.length){Mt();return}let s=Pn(Xe);d.reset(s,{asEdit:!0}),h(Xe[0]??null),V("Object bindings reset to default values."),_("success")}else Vt==="scene"&&(Ne.reset(Yt,{asEdit:!0}),V("Scene config reset to default values."),_("success"));Mt()},[Vt,Xe,d,Ne,Mt]),Xn=te(()=>{Fn(null)},[]),Ws=async()=>{let s;try{s=await Ka()}catch(p){console.warn("[BindingBuilder] Could not read the saved session:",p),V("Couldn't read the saved session from this browser."),_("error");return}if(!s){V("No saved session in this browser yet \u2014 one is saved as soon as you edit a model."),_("error");return}Fn(s)},Ys=async()=>{let s=un;if(Fn(null),!s)return;let{session:p,file:y}=s,{model:k}=p;ct.current=null;let L=Do(Yt,p.sceneConfig),I=at.current,Y=await sa(p.bindings);if(at.current!==I)return;let j;if(k.kind==="file"){if(!y)return;let Oe=at.current,Cn;try{Cn=await Qn(y)}catch(qs){console.warn("[BindingBuilder] Could not read the saved model:",qs),V(Rr(k.name)),_("error");return}if(at.current!==Oe){Cn.cleanup();return}$e.current?.cleanup(),$e.current=Cn,j=Cn.url}else{j=k.url;let Oe=ht.current;if(j===v&&Oe?.url===j&&!De.current){dt.current={model:k},xn.current=null,d.reset(Kt(ao(Oe.scene),Y)),Ne.reset(L),V(`Restored your last session with ${k.name}.`),_("success");return}$e.current?.cleanup(),$e.current=null}dt.current={model:k,file:y??void 0},xn.current=k.kind==="file"?k.key:null;let oe=++at.current;D(!0),gt(null),ft.current=0,Ce.current&&(clearTimeout(Ce.current),Ce.current=null),hn.current=y?.size,V(`Restoring your last session with ${k.name}...`),_("default"),g(k.name),z({url:j,name:k.name}),gn(null),h(null),ht.current=null,d.reset({}),Ne.reset(L),De.current={requestId:oe,modelName:k.name,modelUrl:j,storedBindings:Y,restoring:!0},F(j)};return Ut.status==="checking"?T("div",{className:"bb-root bb-root--licenseChecking",children:T(Zn,{title:"Verifying License",message:"Checking your license key..."})}):Ut.status==="invalid"?T("div",{className:"bb-root bb-root--licenseInvalid",children:T(Zn,{tone:"error",title:"Invalid License",message:Ut.isLocalDomain?Ut.reason??"License has been revoked or has expired":"Failed to load. Please contact the site administrator."})}):U(Oa.Provider,{value:ns,children:[U("div",{className:"bb-root",children:[T("input",{ref:l,type:"file",accept:pa,className:"bb-hiddenInput",onChange:xs,disabled:H}),T("input",{ref:S,type:"file",accept:".json,application/json",className:"bb-hiddenInput",onChange:Ss,disabled:H}),T("input",{ref:B,type:"file",accept:".json,application/json",className:"bb-hiddenInput",onChange:Ts,disabled:H}),U("aside",{className:`bb-sidebar bb-sidebar--left ${Pt?"bb-sidebar--collapsed":""}`,children:[U("div",{className:"bb-header bb-header--sidebar",children:[!Pt&&T("h1",{className:"bb-title",children:"Binding Builder"}),T("button",{type:"button",className:"bb-sidebarToggle",onClick:()=>Dr(s=>!s),"aria-label":Pt?"Open editor sidebar":"Collapse editor sidebar",title:Pt?"Open editor":"Collapse editor",children:Pt?"\u2192":"\u2190"})]}),!Pt&&U(It,{children:[U("div",{className:"bb-tabRow",children:[T("button",{type:"button",className:`bb-tab ${ot==="object"?"bb-tab--active":""}`,onClick:()=>jn("object"),children:"Object"}),T("button",{type:"button",className:`bb-tab ${ot==="scene"?"bb-tab--active":""}`,onClick:()=>jn("scene"),children:"Scene"})]}),T("section",{className:"bb-editor",children:ot==="scene"?T(It,{children:v?T(yo,{config:Be,onChange:mn,activeSubTab:pn,onActiveSubTabChange:$o,cameraState:pn==="Cinematic"&&me?{position:me.position,target:me.target,azimuthAngle:me.azimuthAngle,polarAngle:me.polarAngle}:null,onPreviewWaypoint:is,animationClipDetails:yn.clipDetails,animationPlayback:yn,materialVariants:Mr,objectBindings:a}):T("div",{className:"bb-emptyEditor",children:"Upload a model to edit its scene settings."})}):!fe||!c?T("div",{className:"bb-emptyEditor",children:"Select a generated node binding to edit its values."}):U(It,{children:[T("div",{className:"bb-editorHeader",children:U("div",{children:[T("div",{className:"bb-sectionKicker",children:"Editing Binding"}),T("h2",{className:"bb-editorTitle",children:fe.label||c}),U("div",{className:"bb-editorMeta",children:[T("span",{children:fe.type}),T("span",{children:fe.modelObjectId})]})]})}),T(Ji,{selectedItem:c,selectedBinding:fe,open:tt.identity,onToggle:()=>nt("identity"),updateBinding:Ie,idError:cs}),T(Zi,{selectedItem:c,selectedBinding:fe,open:tt.basics,onToggle:()=>nt("basics"),updateBinding:Ie}),U(Te,{title:"Material",open:tt.material,onToggle:()=>nt("material"),tooltip:"Edit the selected object's base material, textures, and surface properties.",children:[T(qi,{disabled:!c,onApply:s=>c&&Yn(c,p=>({...p,...s}))}),T(Wi,{selectedItem:c,selectedMaterial:_n,pbrWorkflow:Ur,onPbrWorkflowChange:Kr,openMaterialPanels:Gr,materialPanelEnabled:_r,onToggleMaterialPanel:$r,onSetMaterialPanelState:ps,updateSelectedMaterial:Yn,setSelectedTexturePath:bs,isTexturePositioningEnabled:Qr,onConfirmTexturePosition:Ks})]}),T(or,{selectedItem:c,selectedBinding:fe,open:tt.decals,onToggle:()=>nt("decals"),updateBinding:Ie,placement:Tt,onPlacementChange:Es,defaultSize:Os,onImageFile:As,onNudge:Ls}),T(er,{selectedItem:c,selectedBinding:fe,open:tt.actions,onToggle:()=>nt("actions"),updateBinding:Ie}),T(ar,{selectedBinding:fe,open:tt.camera,onToggle:()=>nt("camera"),cameraState:me,formattedCameraState:rs,savedCameraPosition:bt,onSaveCameraPosition:Hs,onGoToSavedCamera:Gs,onClearSavedCamera:Vs,onResetView:$s,onFitScene:Us}),T(dr,{selectedItem:c,selectedBinding:fe,open:tt.transform,onToggle:()=>nt("transform"),updateBinding:Ie,moveModeEnabled:Hn,onToggleMoveMode:qo,transformSpace:Jo,onTransformSpaceChange:Xr,originalTransform:Gn.current[c]??null}),T(Bo,{title:"Metrics",label:"Metrics JSON",open:tt.metrics,onToggle:()=>nt("metrics"),draft:Go,error:Lr,example:'{"area": 42}',onDraftChange:ln,onCommit:()=>ca("metrics",Go,cn)}),T(Bo,{title:"Metadata",label:"Metadata JSON",open:tt.metadata,onToggle:()=>nt("metadata"),draft:Vo,error:Er,example:'{"room": "kitchen"}',onDraftChange:dn,onCommit:()=>ca("metadata",Vo,bn)})]})}),ot==="object"&&U("div",{className:"bb-toolbar",children:[U("div",{className:"bb-toolbarGroup",children:[T("button",{type:"button",className:"bb-iconButton",disabled:!d.canUndo,onClick:d.undo,title:"Undo (Cmd/Ctrl+Z)",children:T(Sr,{size:16})}),T("button",{type:"button",className:"bb-iconButton",disabled:!Xe.length,onClick:()=>ba("bindings"),title:"Reset object bindings to default",children:T(Nr,{size:16})}),T("button",{type:"button",className:"bb-iconButton",disabled:!d.canRedo,onClick:d.redo,title:"Redo (Cmd/Ctrl+Shift+Z)",children:T(Cr,{size:16})})]}),T("div",{className:"bb-toolbarDivider"}),U("button",{type:"button",className:"bb-button bb-button--ghost",disabled:!Xe.length||H,onClick:ws,title:"Re-apply a previously exported objectBindings.json onto this model",children:[T(kr,{size:14}),"Import"]}),T("div",{className:"bb-toolbarDivider"}),T(No,{disabled:!Xe.length||Io,exporting:Io,onExportJson:()=>da("json"),onExportTs:()=>da("ts")})]}),ot==="scene"&&U("div",{className:"bb-toolbar",children:[U("div",{className:"bb-toolbarGroup",children:[T("button",{type:"button",className:"bb-iconButton",disabled:!Ne.canUndo,onClick:Ne.undo,title:"Undo (Cmd/Ctrl+Z)",children:T(Sr,{size:16})}),T("button",{type:"button",className:"bb-iconButton",onClick:()=>ba("scene"),title:"Reset scene config to default",children:T(Nr,{size:16})}),T("button",{type:"button",className:"bb-iconButton",disabled:!Ne.canRedo,onClick:Ne.redo,title:"Redo (Cmd/Ctrl+Shift+Z)",children:T(Cr,{size:16})})]}),T("div",{className:"bb-toolbarDivider"}),U("button",{type:"button",className:"bb-button bb-button--ghost",disabled:!Xe.length||H,onClick:ks,title:"Re-apply a previously exported sceneConfig.json",children:[T(kr,{size:14}),"Import"]}),T("div",{className:"bb-toolbarDivider"}),T(No,{disabled:!Xe.length||H,onExportJson:()=>rn("sceneConfig.json",fr(Be),"application/json"),onExportTs:()=>rn("sceneConfig.ts",hr(Be),"text/typescript")})]})]})]}),U("main",{className:"bb-previewShell",children:[U("div",{className:"bb-previewHeader",children:[U("div",{className:"bb-previewToggles",children:[U("label",{className:"bb-checkbox bb-checkbox--compact",style:{color:"black"},children:[T("input",{type:"checkbox",checked:Ko,onChange:s=>Wr(s.target.checked)}),"Zoom on selected"]}),U("label",{className:"bb-checkbox bb-checkbox--compact",style:{color:"black"},children:[T("input",{type:"checkbox",checked:In,onChange:s=>Yr(s.target.checked)}),"Highlight on hover"]}),U("label",{className:"bb-checkbox bb-checkbox--compact",style:{color:"black"},children:[T("input",{type:"checkbox",checked:_o,onChange:s=>qr(s.target.checked)}),"Camera controller"]})]}),U("div",{className:"bb-previewControlsColumn",children:[U("div",{className:"bb-previewControls",children:[T("div",{className:"bb-previewMeta",children:T("span",{children:c?`Focused: ${c}`:"Select a node to inspect it"})}),m&&!o&&T("button",{type:"button",className:"bb-restoreSessionButton",disabled:H,onClick:Ws,title:"Restore your last session \u2014 the model, its object bindings, and scene settings saved in this browser","aria-label":"Restore last session",children:T(Tr,{size:14})}),v&&m&&!o&&T("button",{type:"button",className:"bb-button bb-button--ghost bb-removeModelButton",onClick:vs,children:"Remove model"})]}),v&&T("div",{className:"bb-moveHint",children:we?T(It,{children:"Click the preview to look around \xB7 Esc to release"}):Hn?T(It,{children:"Select a mesh \xB7 drag the colored arrows, planes, or rings"}):U(It,{children:[T("kbd",{children:"W"}),T("kbd",{children:"A"}),T("kbd",{children:"S"}),T("kbd",{children:"D"})," move \xB7 ",T("kbd",{children:"Space"}),"/",T("kbd",{children:"C"})," up \xB7 down \xB7 drag to look"]})})]})]}),U("div",{className:"bb-preview",children:[T(za,{visible:H||zr,message:Ho,tone:sn,progress:Or??void 0}),v?T(Ha,{modelUrl:v,tilesetUrl:N?.tilesetUrl,objectBindings:a,selectedObject:fe,onObjectSelect:js,onObjectBindingsChange:R,onTextureUpload:ds,onObjectEditLeaseChange:(s,p)=>M?.(s.modelObjectId||s.id,p),showObjectBindingDataPanel:!1,showSceneObjectsPanel:!1,onCameraChange:os,onViewerReady:s=>{Kn.current=s,as(s)},onAnnotationsChange:ss,activeAnnotation:es?.annotation??null,onActiveAnnotationChange:ls,onAnimationsReady:hs,onSceneLoaded:us,onLoadError:gs,onObjectCatalog:N?.tilesetUrl?ms:void 0,onProgress:fs,onCameraControllerChange:Vn,cameraControllerType:Xo,onTexturePositioningChange:Zr,endTexturePositioningRef:Qo,licenseKey:t,licenseValidationUrl:n,dracoDecoderPath:i,ktx2TranscoderPath:r,meshopt:e,sceneConfig:Be,onSceneConfigChange:mn,preserveDrawingBuffer:!0,disableZoom:!1,zoomOnSelected:Ko,highlightOnHover:In,enableCameraControls:_o,moveModeEnabled:Hn,objectTransformSpace:Jo,enableKeyboardNavigation:!0,showViewGizmo:!0,showSectionTools:Be.section?.enabled??!1,isolation:Ft,onIsolationChange:()=>qe(null),showIsolateControls:!0,decalMove:zs,panelHoveredObject:In?ts:null,showLoadingOverlay:!1,autoRotate:we?!1:Be.model.autoRotate??!1,autoRotateSpeed:Be.model.autoRotateSpeed??1}):T("div",{className:`bb-previewPlaceholder ${jr?"bb-previewPlaceholder--dragActive":""}`,onDragEnter:Ps,onDragOver:Bs,onDragLeave:Rs,onDrop:Ms,children:U("div",{children:[T("div",{children:"Upload a GLB, GLTF, OBJ, FBX, or USDZ model, or drag a supported model/ZIP bundle here to generate editable object bindings."}),m?T("button",{type:"button",className:"bb-previewPlaceholderButton",onClick:ys,disabled:H,children:"Upload"}):null]})})]})]}),T(br,{bindings:a,selectedItem:c,onSelect:Ds,onHover:Is,isOpen:!Ir,onToggle:Fs,isolatedItem:ne,onIsolate:qe})]}),Jr&&T("div",{className:"bb-reset-overlay",onClick:Mt,children:U("div",{className:"bb-reset-dialog",onClick:s=>s.stopPropagation(),children:[U("div",{className:"bb-reset-header",children:[U("h3",{className:"bb-reset-title",children:[T(fc,{size:20,className:"bb-icon-warning"}),"Confirm Reset"]}),T("button",{className:"bb-reset-close",onClick:Mt,children:T(Pr,{size:20})})]}),U("div",{className:"bb-reset-body",children:[U("p",{className:"bb-reset-message",children:["Are you sure you want to reset"," ",T("strong",{children:Vt==="bindings"?"Object Bindings":"Scene Config"}),"?"]}),T("p",{className:"bb-reset-details",children:Vt==="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."}),T("p",{className:"bb-reset-warning",children:"This action cannot be undone!"})]}),U("div",{className:"bb-reset-footer",children:[T("button",{className:"bb-reset-btn",onClick:Mt,children:"Cancel"}),T("button",{className:"bb-reset-btn-danger",onClick:_s,children:"Reset"})]})]})}),un&&T("div",{className:"bb-reset-overlay",onClick:Xn,children:U("div",{className:"bb-reset-dialog",onClick:s=>s.stopPropagation(),children:[U("div",{className:"bb-reset-header",children:[U("h3",{className:"bb-reset-title",children:[T(Tr,{size:20,className:"bb-icon-restore"}),"Restore Last Session"]}),T("button",{className:"bb-reset-close",onClick:Xn,children:T(Pr,{size:20})})]}),U("div",{className:"bb-reset-body",children:[U("p",{className:"bb-reset-message",children:["Restore ",T("strong",{children:un.session.model.name}),", saved ",vc(un.session.savedAt),"?"]}),T("p",{className:"bb-reset-details",children:"This reloads that model with its object bindings and scene settings, replacing what's in the editor now."})]}),U("div",{className:"bb-reset-footer",children:[T("button",{className:"bb-reset-btn",onClick:Xn,children:"Cancel"}),T("button",{className:"bb-reset-btn-restore",onClick:Ys,children:"Restore"})]})]})})]})}export{yc as a};
|