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