@liveroom-tech/react-immersive 6.2.2 → 6.2.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (40) hide show
  1. package/README.md +23 -0
  2. package/dist/{SequencesTab-LTMJTB76.mjs → SequencesTab-JZEE5WAM.mjs} +1 -1
  3. package/dist/binding-builder.d.mts +3 -3
  4. package/dist/binding-builder.d.ts +3 -3
  5. package/dist/binding-builder.js +41 -41
  6. package/dist/binding-builder.mjs +1 -1
  7. package/dist/{chunk-NMRTI3NQ.mjs → chunk-3GA7JFNH.mjs} +1 -1
  8. package/dist/chunk-3I7PPFUV.mjs +1 -0
  9. package/dist/{chunk-IT2PUTJS.mjs → chunk-CHMFH4D4.mjs} +1 -1
  10. package/dist/{chunk-RSUXTWM6.mjs → chunk-CUDL77ZY.mjs} +1 -1
  11. package/dist/{chunk-XKJQC3N5.mjs → chunk-IEKGBS46.mjs} +1 -1
  12. package/dist/chunk-LU3BQ7WG.mjs +69 -0
  13. package/dist/chunk-QZNUWZG7.mjs +50 -0
  14. package/dist/{chunk-WU3SQZGD.mjs → chunk-TI2YXAHW.mjs} +2 -2
  15. package/dist/hosted.d.mts +3 -3
  16. package/dist/hosted.d.ts +3 -3
  17. package/dist/hosted.js +40 -40
  18. package/dist/hosted.mjs +1 -1
  19. package/dist/index.d.mts +8 -4
  20. package/dist/index.d.ts +8 -4
  21. package/dist/index.js +36 -36
  22. package/dist/index.mjs +1 -1
  23. package/dist/{modelFileResolver-Bq4pW9vc.d.mts → modelFileResolver-An1aQ0D3.d.mts} +3 -0
  24. package/dist/{modelFileResolver-Bq4pW9vc.d.ts → modelFileResolver-An1aQ0D3.d.ts} +3 -0
  25. package/dist/{modelViewerProps-BnrJO5DK.d.ts → modelViewerProps-BnVflYRA.d.mts} +21 -3
  26. package/dist/{modelViewerProps-wjBT4fks.d.mts → modelViewerProps-H_K454u_.d.ts} +21 -3
  27. package/dist/{publicProps-BZPMIRwj.d.ts → publicProps-AdNUI06n.d.ts} +1 -1
  28. package/dist/{publicProps-CW5X_HFh.d.mts → publicProps-BOQBJBA_.d.mts} +1 -1
  29. package/dist/simple-model-viewer.d.mts +6 -2
  30. package/dist/simple-model-viewer.d.ts +6 -2
  31. package/dist/simple-model-viewer.js +5 -5
  32. package/dist/simple-model-viewer.mjs +1 -1
  33. package/dist/utils.d.mts +4 -4
  34. package/dist/utils.d.ts +4 -4
  35. package/dist/utils.js +15 -15
  36. package/dist/utils.mjs +1 -1
  37. package/package.json +7 -5
  38. package/dist/chunk-2LGQKX6Z.mjs +0 -50
  39. package/dist/chunk-LEOHZ5HM.mjs +0 -69
  40. package/dist/chunk-UAZ6I25Y.mjs +0 -1
package/README.md CHANGED
@@ -23,6 +23,11 @@ visibility, camera control, animations, annotations, and scene authoring.
23
23
  Import each component's stylesheet once. Give the viewer's container an explicit
24
24
  height. The package does not require Tailwind in the consuming application.
25
25
 
26
+ `SimpleModelViewer` exposes a named region even with both panels disabled. Set
27
+ `aria-label="Product preview"` or `aria-labelledby="product-heading"` to give it
28
+ a model-specific name. Its default name is "3D model viewer", translated through
29
+ `labels.modelViewer`; collapsed panel buttons also have localized names.
30
+
26
31
  ## Install
27
32
 
28
33
  In a React 19 application:
@@ -104,6 +109,24 @@ Pure data helpers, including `defineObjectBindings`, `patchBindings`,
104
109
  `patchSceneConfig`, and `selectBindings`, are available from the server-safe
105
110
  `@liveroom-tech/react-immersive/utils` entry.
106
111
 
112
+ To fly to an annotation and open its card from your own UI, call
113
+ `await viewer.connection.goToAnnotation(annotationId)`. The numeric ID comes
114
+ from `sceneConfig.annotations`. It restores a saved camera view or frames the
115
+ marker automatically, and returns `false` before connection or for an unknown
116
+ or filtered-out ID. Controlled cards still use `onActiveAnnotationChange`.
117
+ Hotspot markers expose their annotation title as a tooltip and accessible name.
118
+
119
+ `viewer.camera.focusObject(id, { padding: 0.2, paddingRight: 1 })` sets object-fit
120
+ padding in scene units. Per-side options override uniform padding; omitted
121
+ values keep the `0.5` default. Padding does not alter a binding's saved camera view.
122
+
123
+ With `enableXR` (or `xr={{ enabled: true }}`), an app-owned button can call
124
+ `await viewer.connection.startAR()`. Invoke it directly in the click handler
125
+ and catch launch errors. It starts WebXR AR when supported, otherwise launches
126
+ the supplied iOS USDZ or opens the configured-AR/phone handoff. It returns
127
+ `false` when disabled, unavailable, or not ready; `true` means the session
128
+ started or a platform handoff opened.
129
+
107
130
  ## Embed a hosted project without React
108
131
 
109
132
  For Shopify, WordPress, Webflow, or plain HTML, open a hosted project's **Share**
@@ -1 +1 @@
1
- import{e as ue}from"./chunk-SXN3YYD3.mjs";import{a as ne,b as se}from"./chunk-RSUXTWM6.mjs";import{e as H,f as oe,h as le,i as ce}from"./chunk-FGAJ2UT7.mjs";import"./chunk-NMRTI3NQ.mjs";import{b as j}from"./chunk-3PLML3PO.mjs";import{a as te,b as ae,c as L,d as ie,e as U,g as re}from"./chunk-LX3GXQNU.mjs";import"./chunk-UAZ6I25Y.mjs";import"./chunk-JR557W27.mjs";import{useEffect as ge,useMemo as we,useRef as je,useState as S}from"react";import{Copy as Ie,DiamondPlus as Ee,Plus as G,ScanLine as Pe,Trash2 as Q}from"lucide-react";import{useEffect as pe,useState as me}from"react";import{Fragment as de,jsx as g,jsxs as T}from"react/jsx-runtime";function I({label:p,value:o,onChange:r,min:l,max:u,step:f=.1,disabled:q=!1}){let[y,d]=me(String(Number(o.toFixed(5))));return pe(()=>d(String(Number(o.toFixed(5)))),[o]),T("label",{className:"sq-field",children:[g("span",{children:p}),g("input",{type:"number","aria-label":p,value:y,step:f,min:l,max:u,disabled:q,onChange:m=>d(m.target.value),onBlur:()=>{let m=y.trim()?Number(y):NaN;Number.isFinite(m)&&(l===void 0||m>=l)&&(u===void 0||m<=u)&&m!==o&&r(m),d(String(Number(o.toFixed(5))))},onKeyDown:m=>{m.stopPropagation(),m.key==="Enter"&&m.currentTarget.blur(),m.key==="Escape"&&(m.preventDefault(),d(String(o)))}})]})}function _({label:p,value:o,onChange:r}){let[l,u]=me(o);return pe(()=>u(o),[o]),T("label",{className:"sq-field",children:[g("span",{children:p}),g("input",{"aria-label":p,value:l,maxLength:256,onChange:f=>u(f.target.value),onBlur:()=>{l.trim()&&l.trim()!==o?r(l.trim()):u(o)},onKeyDown:f=>{f.stopPropagation(),f.key==="Enter"&&f.currentTarget.blur()}})]})}function X({label:p,value:o,onChange:r,degrees:l=!1}){return T("fieldset",{className:"sq-vector",children:[T("legend",{children:[p,l?" (\xB0)":""]}),g("div",{children:o.map((u,f)=>g(I,{label:["X","Y","Z"][f],value:l?u*180/Math.PI:u,onChange:q=>r(o.map((y,d)=>f===d?l?q*Math.PI/180:q:y))},f))})]})}function be({target:p,value:o,onChange:r}){if(p.kind==="camera"){let l=o;return T(de,{children:[g(X,{label:"Camera position",value:l.position,onChange:u=>r({...l,position:u})}),g(X,{label:"Camera target",value:l.target,onChange:u=>r({...l,target:u})}),T(de,{children:[l.fov!==null&&g(I,{label:"FOV (\xB0)",min:1,max:179,value:l.fov,onChange:u=>r({...l,fov:u})}),g(I,{label:"Zoom",min:.001,value:l.zoom,onChange:u=>r({...l,zoom:u})})]})]})}return Array.isArray(o)?g(X,{label:p.kind==="object"?p.property[0].toUpperCase()+p.property.slice(1):"Value",value:o,degrees:p.kind==="object"&&p.property==="rotation",onChange:r}):typeof o=="boolean"?T("label",{className:"sq-check",children:[g("input",{type:"checkbox",checked:o,onChange:l=>r(l.target.checked)}),"Visible"]}):typeof o=="string"?T("label",{className:"sq-field sq-color",children:[g("span",{children:"Color"}),g("input",{type:"color","aria-label":"Keyframe color",value:o,onChange:l=>r(l.target.value)}),g("code",{children:o})]}):g(I,{label:p.kind==="clip"?"Clip time (s)":"Value",min:0,max:p.kind==="object"&&p.property!=="emissiveIntensity"?1:void 0,step:.01,value:o,onChange:r})}import{Fragment as qe,jsx as t,jsxs as s}from"react/jsx-runtime";var E=()=>crypto.randomUUID(),fe={position:"Position",rotation:"Rotation",scale:"Scale",visible:"Visibility",baseColor:"Color",emissive:"Emissive color",opacity:"Opacity",roughness:"Roughness",metalness:"Metalness",emissiveIntensity:"Emissive intensity"},Ae={linear:"Linear","ease-in":"Ease in","ease-out":"Ease out","ease-in-out":"Ease in / out",step:"Hold / step"};function Me({config:p,onChange:o,controls:r,bindings:l,clipDetails:u}){let{tier:f}=le(),q=ne(r),y=we(()=>{try{return{sequences:U(p.sequences??[]),error:""}}catch(e){return{sequences:[],error:e instanceof Error?e.message:"Invalid sequence data."}}},[p.sequences]),d=y.sequences,[Y,m]=S(null),[ke,N]=S(null),[he,x]=S(null),[w,ve]=S("object"),[ye,xe]=S(""),[z,Se]=S("position"),[Z,Ne]=S(""),[J,A]=S(""),[K,B]=S(null),M=je(null),i=d.find(e=>e.id===Y)??d[0],c=i?.tracks.find(e=>e.id===ke)??i?.tracks[0],h=c?.keyframes.find(e=>e.id===he)??c?.keyframes[0],R=Object.values(l).filter((e,a,k)=>!e.removed&&k.findIndex(n=>n.modelObjectId===e.modelObjectId)===a),O=R.find(e=>e.modelObjectId===ye)??R[0],F=u.some(e=>e.sourceName===Z)?Z:u[0]?.sourceName;ge(()=>{i&&r&&q.sequenceId!==i.id&&r.select(i.id)},[r,i?.id,q]),ge(()=>()=>r?.stop(),[r]);let V=e=>{try{let a=U(e);o({...p,sequences:a}),A("")}catch(a){A(a instanceof Error?a.message:"Invalid sequence.")}},P=e=>V(d.map(a=>a.id===e.id?e:a)),D=e=>{i&&P({...i,tracks:i.tracks.map(a=>a.id===e.id?e:a)})},C=(e,a)=>{if(!i||!ie(a.value,e.target)){A("Use a valid value; scale components must be nonzero.");return}D(re(e,{...a,time:Math.max(0,Math.min(i.duration,a.time))})),N(e.id),x(a.id),r?.pause(),r?.seek(a.time)},W=()=>{if(d.length>=64)return;let e={id:E(),name:`Sequence ${d.length+1}`,duration:5,loop:!1,autoPlay:!1,tracks:[]};V([...d,e]),m(e.id),N(null),x(null)},v=w==="camera"?{kind:"camera"}:w==="clip"?F?{kind:"clip",clip:F}:null:O?{kind:"object",objectId:O.modelObjectId,property:z}:null,$=!!v&&i?.tracks.some(e=>L(e.target)===L(v)),Ce=()=>{if(!i||!v||$)return;let e=r?.capture(v);if(e==null){A("That target is not ready. Wait for the model, or choose another object/clip.");return}let a=v.kind==="clip"?Math.min(i.duration,u.find(n=>n.sourceName===v.clip)?.duration??i.duration):structuredClone(e),k={id:E(),name:v.kind==="camera"?"Camera":v.kind==="clip"?v.clip:`${O?.label||O?.modelObjectId} \xB7 ${fe[z]}`,target:v,keyframes:[{id:E(),time:0,value:e,easing:z==="visible"&&w==="object"?"step":"ease-in-out"},{id:E(),time:i.duration,value:a}]};P({...i,tracks:[...i.tracks,k]}),N(k.id),x(k.keyframes[1].id),r?.seek(i.duration)},Te=()=>{if(!c||!i||c.keyframes.length>=2048)return;let e=r?.capture(c.target);if(e==null){A("The selected target is unavailable.");return}let a={id:E(),time:Math.min(q.time,i.duration),value:e,easing:"ease-in-out"};C(c,a)};return s("section",{className:"sq-editor","aria-label":"Visual sequence authoring",children:[y.error&&t("p",{role:"alert",className:"sq-error",children:y.error}),H(f,"sequences",d.length)?null:t(ce,{requiredTier:oe("sequences",d.length),feature:"More sequences"}),i?s(qe,{children:[s("div",{className:"sq-toolbar",children:[t(j,{className:"se-select sq-toolbarPicker","aria-label":"Authored sequence",value:i.id,onChange:e=>{m(e.target.value),N(null),x(null),r?.select(e.target.value)},children:d.map(e=>t("option",{value:e.id,children:e.name},e.id))}),t("button",{type:"button",className:"se-iconButton",title:"Add sequence","aria-label":"Add sequence",disabled:d.length>=64||!H(f,"sequences",d.length),onClick:W,children:t(G,{size:14})}),t("button",{type:"button",className:"se-iconButton",title:"Duplicate sequence","aria-label":"Duplicate sequence",disabled:d.length>=64,onClick:()=>{let e={...structuredClone(i),id:E(),name:`${i.name} copy`.slice(0,256),autoPlay:!1};V([...d,e]),m(e.id)},children:t(Ie,{size:13})}),t("button",{type:"button",className:"se-iconButton",title:"Delete sequence","aria-label":"Delete sequence",onClick:()=>{r?.stop(),V(d.filter(e=>e.id!==i.id)),m(null)},children:t(Q,{size:13})}),t("span",{className:"sq-toolbarDivider"}),t(_,{label:"Name",value:i.name,onChange:e=>P({...i,name:e})}),t(I,{label:"Duration",min:.1,max:3600,value:i.duration,onChange:e=>P({...i,duration:e,tracks:i.tracks.map(a=>({...a,keyframes:a.keyframes.map(k=>({...k,time:k.time/i.duration*e}))}))})}),s("label",{className:"sq-check",children:[t("input",{type:"checkbox",checked:i.loop,onChange:e=>P({...i,loop:e.target.checked})}),"Loop"]}),s("label",{className:"sq-check",children:[t("input",{type:"checkbox",checked:i.autoPlay,onChange:e=>V(d.map(a=>({...a,autoPlay:a.id===i.id?e.target.checked:!1})))}),"Autoplay"]})]}),s("div",{className:"sq-body",children:[s("div",{className:"sq-main",children:[t(se,{controls:r,duration:i.duration,hasTracks:i.tracks.some(e=>!e.muted&&e.keyframes.length>0)}),s("div",{className:"sq-timeline","aria-label":"Sequence timeline",title:"Drag keys to retime. Arrow keys move 0.1s; Shift moves 0.01s. A key at the same time is replaced.",children:[s("div",{className:"sq-ruler",children:[t("span",{className:"sq-rulerTitle",children:"Tracks"}),t("div",{className:"sq-rulerScale",children:[0,.25,.5,.75,1].map(e=>s("span",{children:[(i.duration*e).toFixed(1),"s"]},e))})]}),!i.tracks.length&&t("p",{className:"sq-hint",children:"Add a track to create its start and end keyframes."}),i.tracks.map(e=>s("div",{className:`sq-track ${c?.id===e.id?"sq-track--active":""}`,children:[s("div",{className:"sq-trackLabel",children:[t("button",{type:"button",title:e.name,onClick:()=>{N(e.id),x(e.keyframes[0]?.id??null)},children:e.name}),s("label",{title:"Mute track",children:[t("input",{"aria-label":`Mute ${e.name}`,type:"checkbox",checked:!!e.muted,onChange:a=>D({...e,muted:a.target.checked})}),"Mute"]})]}),s("div",{className:"sq-lane",role:"group","aria-label":`${e.name} keyframes`,onDoubleClick:a=>{if(a.target!==a.currentTarget)return;let k=a.currentTarget.getBoundingClientRect(),n=Math.round(Math.max(0,Math.min(1,(a.clientX-k.left)/k.width))*i.duration*100)/100,b=r?.capture(e.target);b!=null&&C(e,{id:E(),time:n,value:b})},children:[t("span",{className:"sq-playhead",style:{left:`${q.time/i.duration*100}%`}}),e.keyframes.map(a=>{let k=K?.frameId===a.id&&K.trackId===e.id?K.time:a.time;return t("button",{type:"button",className:`sq-key ${h?.id===a.id&&c?.id===e.id?"sq-key--active":""}`,style:{left:`${k/i.duration*100}%`},"aria-label":`${e.name} keyframe at ${k.toFixed(2)} seconds`,"aria-pressed":h?.id===a.id&&c?.id===e.id,onClick:n=>{n.detail===0&&(N(e.id),x(a.id),r?.pause(),r?.seek(a.time))},onPointerDown:n=>{if(n.button!==0)return;n.preventDefault(),n.stopPropagation(),n.currentTarget.focus(),n.currentTarget.setPointerCapture(n.pointerId);let b=n.currentTarget.parentElement.getBoundingClientRect();M.current={track:e,frame:a,left:b.left,width:b.width,time:a.time},N(e.id),x(a.id),r?.pause(),r?.seek(a.time)},onPointerMove:n=>{let b=M.current;if(!b||b.frame.id!==a.id||b.track.id!==e.id)return;let ee=n.shiftKey?.01:.1;b.time=Math.min(i.duration,Math.max(0,Math.round((n.clientX-b.left)/b.width*i.duration/ee)*ee)),B({trackId:e.id,frameId:a.id,time:b.time}),r?.seek(b.time)},onPointerUp:()=>{let n=M.current;n&&(n.time!==n.frame.time&&C(n.track,{...n.frame,time:n.time}),M.current=null,B(null))},onPointerCancel:()=>{M.current=null,B(null),r?.seek(a.time)},onKeyDown:n=>{if(!["ArrowLeft","ArrowRight","Home","End"].includes(n.key))return;n.preventDefault(),n.stopPropagation();let b=n.key==="Home"?0:n.key==="End"?i.duration:a.time+(n.key==="ArrowLeft"?-1:1)*(n.shiftKey?.01:.1);C(e,{...a,time:b})}},a.id)})]})]},e.id))]})]}),s("aside",{className:"sq-side",children:[s(ue,{title:"Add track",children:[s("label",{className:"sq-field",children:[t("span",{children:"Type"}),s(j,{"aria-label":"Track type",value:w,onChange:e=>ve(e.target.value),children:[t("option",{value:"object",children:"Object"}),t("option",{value:"camera",children:"Camera"}),t("option",{value:"clip",children:"Animation clip"})]})]}),w==="object"&&s("label",{className:"sq-field",children:[t("span",{children:"Property"}),t(j,{"aria-label":"Track property",value:z,onChange:e=>Se(e.target.value),children:te.map(e=>t("option",{value:e,children:fe[e]},e))})]}),w==="object"&&s("label",{className:"sq-field",children:[t("span",{children:"Object"}),t(j,{"aria-label":"Track object",value:O?.modelObjectId??"",onChange:e=>xe(e.target.value),children:R.map(e=>t("option",{value:e.modelObjectId,children:e.label||e.modelObjectId},e.modelObjectId))})]}),w==="clip"&&s("label",{className:"sq-field",children:[t("span",{children:"Clip"}),t(j,{"aria-label":"Track animation clip",value:F??"",onChange:e=>Ne(e.target.value),children:u.map(e=>t("option",{value:e.sourceName,children:e.sourceName},e.sourceName))}),!u.length&&t("small",{children:"This model has no animation clips."})]}),t("div",{className:"rui-actions",children:s("button",{type:"button",className:"bb-button",onClick:Ce,disabled:!v||!q.ready||$||i.tracks.length>=128,children:[t(G,{size:13,"aria-hidden":"true"}),"Add track"]})}),$&&t("p",{className:"rui-note",children:"That property already has a track."})]}),c&&s("section",{className:"sq-inspector","aria-label":"Selected track and keyframe",children:[s("div",{className:"rui-groupHeader",children:[t("span",{children:"Selected track"}),t("button",{type:"button",className:"se-iconButton",title:"Delete track","aria-label":"Delete track",onClick:()=>{P({...i,tracks:i.tracks.filter(e=>e.id!==c.id)}),N(null),x(null)},children:t(Q,{size:13})})]}),t(_,{label:"Name",value:c.name,onChange:e=>D({...c,name:e})}),t("div",{className:"rui-actions",children:s("button",{type:"button",className:"bb-button",disabled:!q.ready||c.keyframes.length>=2048,onClick:Te,children:[t(Ee,{size:13,"aria-hidden":"true"}),"Add keyframe at playhead"]})}),h&&s(qe,{children:[s("div",{className:"rui-groupHeader",children:[t("span",{children:"Keyframe"}),t("button",{type:"button",className:"se-iconButton",title:"Delete keyframe","aria-label":"Delete keyframe",onClick:()=>{D({...c,keyframes:c.keyframes.filter(e=>e.id!==h.id)}),x(null)},children:t(Q,{size:14})})]}),t(I,{label:"Time",min:0,max:i.duration,value:h.time,step:.01,onChange:e=>C(c,{...h,time:e})}),s("label",{className:"sq-field",children:[t("span",{children:"Easing"}),t(j,{"aria-label":"Keyframe easing",value:c.target.kind==="object"&&c.target.property==="visible"?"step":h.easing??"ease-in-out",disabled:c.target.kind==="object"&&c.target.property==="visible",onChange:e=>C(c,{...h,easing:e.target.value}),children:ae.map(e=>t("option",{value:e,children:Ae[e]},e))})]}),t(be,{target:c.target,value:h.value,onChange:e=>C(c,{...h,value:e})}),t("div",{className:"rui-actions",children:s("button",{type:"button",className:"bb-button",disabled:!q.ready,onClick:()=>{let e=r?.capture(c.target);e!=null&&C(c,{...h,value:e})},children:[t(Pe,{size:13,"aria-hidden":"true"}),"Capture current value"]})})]})]})]})]})]}):s("div",{className:"sq-empty",children:[t("p",{children:"Add a sequence, then add tracks and capture keyframes on the timeline."}),s("button",{type:"button",className:"bb-button bb-button--primary",onClick:W,children:[t(G,{size:13,"aria-hidden":"true"}),"Create sequence"]})]}),(J||q.issues.length>0)&&t("div",{role:"status",className:"sq-error",children:J||q.issues.join(" ")})]})}export{Me as default};
1
+ import{e as ue}from"./chunk-SXN3YYD3.mjs";import{a as ne,b as se}from"./chunk-CUDL77ZY.mjs";import{e as H,f as oe,h as le,i as ce}from"./chunk-FGAJ2UT7.mjs";import"./chunk-3GA7JFNH.mjs";import{b as j}from"./chunk-3PLML3PO.mjs";import{a as te,b as ae,c as L,d as ie,e as U,g as re}from"./chunk-LX3GXQNU.mjs";import"./chunk-3I7PPFUV.mjs";import"./chunk-JR557W27.mjs";import{useEffect as ge,useMemo as we,useRef as je,useState as S}from"react";import{Copy as Ie,DiamondPlus as Ee,Plus as G,ScanLine as Pe,Trash2 as Q}from"lucide-react";import{useEffect as pe,useState as me}from"react";import{Fragment as de,jsx as g,jsxs as T}from"react/jsx-runtime";function I({label:p,value:o,onChange:r,min:l,max:u,step:f=.1,disabled:q=!1}){let[y,d]=me(String(Number(o.toFixed(5))));return pe(()=>d(String(Number(o.toFixed(5)))),[o]),T("label",{className:"sq-field",children:[g("span",{children:p}),g("input",{type:"number","aria-label":p,value:y,step:f,min:l,max:u,disabled:q,onChange:m=>d(m.target.value),onBlur:()=>{let m=y.trim()?Number(y):NaN;Number.isFinite(m)&&(l===void 0||m>=l)&&(u===void 0||m<=u)&&m!==o&&r(m),d(String(Number(o.toFixed(5))))},onKeyDown:m=>{m.stopPropagation(),m.key==="Enter"&&m.currentTarget.blur(),m.key==="Escape"&&(m.preventDefault(),d(String(o)))}})]})}function _({label:p,value:o,onChange:r}){let[l,u]=me(o);return pe(()=>u(o),[o]),T("label",{className:"sq-field",children:[g("span",{children:p}),g("input",{"aria-label":p,value:l,maxLength:256,onChange:f=>u(f.target.value),onBlur:()=>{l.trim()&&l.trim()!==o?r(l.trim()):u(o)},onKeyDown:f=>{f.stopPropagation(),f.key==="Enter"&&f.currentTarget.blur()}})]})}function X({label:p,value:o,onChange:r,degrees:l=!1}){return T("fieldset",{className:"sq-vector",children:[T("legend",{children:[p,l?" (\xB0)":""]}),g("div",{children:o.map((u,f)=>g(I,{label:["X","Y","Z"][f],value:l?u*180/Math.PI:u,onChange:q=>r(o.map((y,d)=>f===d?l?q*Math.PI/180:q:y))},f))})]})}function be({target:p,value:o,onChange:r}){if(p.kind==="camera"){let l=o;return T(de,{children:[g(X,{label:"Camera position",value:l.position,onChange:u=>r({...l,position:u})}),g(X,{label:"Camera target",value:l.target,onChange:u=>r({...l,target:u})}),T(de,{children:[l.fov!==null&&g(I,{label:"FOV (\xB0)",min:1,max:179,value:l.fov,onChange:u=>r({...l,fov:u})}),g(I,{label:"Zoom",min:.001,value:l.zoom,onChange:u=>r({...l,zoom:u})})]})]})}return Array.isArray(o)?g(X,{label:p.kind==="object"?p.property[0].toUpperCase()+p.property.slice(1):"Value",value:o,degrees:p.kind==="object"&&p.property==="rotation",onChange:r}):typeof o=="boolean"?T("label",{className:"sq-check",children:[g("input",{type:"checkbox",checked:o,onChange:l=>r(l.target.checked)}),"Visible"]}):typeof o=="string"?T("label",{className:"sq-field sq-color",children:[g("span",{children:"Color"}),g("input",{type:"color","aria-label":"Keyframe color",value:o,onChange:l=>r(l.target.value)}),g("code",{children:o})]}):g(I,{label:p.kind==="clip"?"Clip time (s)":"Value",min:0,max:p.kind==="object"&&p.property!=="emissiveIntensity"?1:void 0,step:.01,value:o,onChange:r})}import{Fragment as qe,jsx as t,jsxs as s}from"react/jsx-runtime";var E=()=>crypto.randomUUID(),fe={position:"Position",rotation:"Rotation",scale:"Scale",visible:"Visibility",baseColor:"Color",emissive:"Emissive color",opacity:"Opacity",roughness:"Roughness",metalness:"Metalness",emissiveIntensity:"Emissive intensity"},Ae={linear:"Linear","ease-in":"Ease in","ease-out":"Ease out","ease-in-out":"Ease in / out",step:"Hold / step"};function Me({config:p,onChange:o,controls:r,bindings:l,clipDetails:u}){let{tier:f}=le(),q=ne(r),y=we(()=>{try{return{sequences:U(p.sequences??[]),error:""}}catch(e){return{sequences:[],error:e instanceof Error?e.message:"Invalid sequence data."}}},[p.sequences]),d=y.sequences,[Y,m]=S(null),[ke,N]=S(null),[he,x]=S(null),[w,ve]=S("object"),[ye,xe]=S(""),[z,Se]=S("position"),[Z,Ne]=S(""),[J,A]=S(""),[K,B]=S(null),M=je(null),i=d.find(e=>e.id===Y)??d[0],c=i?.tracks.find(e=>e.id===ke)??i?.tracks[0],h=c?.keyframes.find(e=>e.id===he)??c?.keyframes[0],R=Object.values(l).filter((e,a,k)=>!e.removed&&k.findIndex(n=>n.modelObjectId===e.modelObjectId)===a),O=R.find(e=>e.modelObjectId===ye)??R[0],F=u.some(e=>e.sourceName===Z)?Z:u[0]?.sourceName;ge(()=>{i&&r&&q.sequenceId!==i.id&&r.select(i.id)},[r,i?.id,q]),ge(()=>()=>r?.stop(),[r]);let V=e=>{try{let a=U(e);o({...p,sequences:a}),A("")}catch(a){A(a instanceof Error?a.message:"Invalid sequence.")}},P=e=>V(d.map(a=>a.id===e.id?e:a)),D=e=>{i&&P({...i,tracks:i.tracks.map(a=>a.id===e.id?e:a)})},C=(e,a)=>{if(!i||!ie(a.value,e.target)){A("Use a valid value; scale components must be nonzero.");return}D(re(e,{...a,time:Math.max(0,Math.min(i.duration,a.time))})),N(e.id),x(a.id),r?.pause(),r?.seek(a.time)},W=()=>{if(d.length>=64)return;let e={id:E(),name:`Sequence ${d.length+1}`,duration:5,loop:!1,autoPlay:!1,tracks:[]};V([...d,e]),m(e.id),N(null),x(null)},v=w==="camera"?{kind:"camera"}:w==="clip"?F?{kind:"clip",clip:F}:null:O?{kind:"object",objectId:O.modelObjectId,property:z}:null,$=!!v&&i?.tracks.some(e=>L(e.target)===L(v)),Ce=()=>{if(!i||!v||$)return;let e=r?.capture(v);if(e==null){A("That target is not ready. Wait for the model, or choose another object/clip.");return}let a=v.kind==="clip"?Math.min(i.duration,u.find(n=>n.sourceName===v.clip)?.duration??i.duration):structuredClone(e),k={id:E(),name:v.kind==="camera"?"Camera":v.kind==="clip"?v.clip:`${O?.label||O?.modelObjectId} \xB7 ${fe[z]}`,target:v,keyframes:[{id:E(),time:0,value:e,easing:z==="visible"&&w==="object"?"step":"ease-in-out"},{id:E(),time:i.duration,value:a}]};P({...i,tracks:[...i.tracks,k]}),N(k.id),x(k.keyframes[1].id),r?.seek(i.duration)},Te=()=>{if(!c||!i||c.keyframes.length>=2048)return;let e=r?.capture(c.target);if(e==null){A("The selected target is unavailable.");return}let a={id:E(),time:Math.min(q.time,i.duration),value:e,easing:"ease-in-out"};C(c,a)};return s("section",{className:"sq-editor","aria-label":"Visual sequence authoring",children:[y.error&&t("p",{role:"alert",className:"sq-error",children:y.error}),H(f,"sequences",d.length)?null:t(ce,{requiredTier:oe("sequences",d.length),feature:"More sequences"}),i?s(qe,{children:[s("div",{className:"sq-toolbar",children:[t(j,{className:"se-select sq-toolbarPicker","aria-label":"Authored sequence",value:i.id,onChange:e=>{m(e.target.value),N(null),x(null),r?.select(e.target.value)},children:d.map(e=>t("option",{value:e.id,children:e.name},e.id))}),t("button",{type:"button",className:"se-iconButton",title:"Add sequence","aria-label":"Add sequence",disabled:d.length>=64||!H(f,"sequences",d.length),onClick:W,children:t(G,{size:14})}),t("button",{type:"button",className:"se-iconButton",title:"Duplicate sequence","aria-label":"Duplicate sequence",disabled:d.length>=64,onClick:()=>{let e={...structuredClone(i),id:E(),name:`${i.name} copy`.slice(0,256),autoPlay:!1};V([...d,e]),m(e.id)},children:t(Ie,{size:13})}),t("button",{type:"button",className:"se-iconButton",title:"Delete sequence","aria-label":"Delete sequence",onClick:()=>{r?.stop(),V(d.filter(e=>e.id!==i.id)),m(null)},children:t(Q,{size:13})}),t("span",{className:"sq-toolbarDivider"}),t(_,{label:"Name",value:i.name,onChange:e=>P({...i,name:e})}),t(I,{label:"Duration",min:.1,max:3600,value:i.duration,onChange:e=>P({...i,duration:e,tracks:i.tracks.map(a=>({...a,keyframes:a.keyframes.map(k=>({...k,time:k.time/i.duration*e}))}))})}),s("label",{className:"sq-check",children:[t("input",{type:"checkbox",checked:i.loop,onChange:e=>P({...i,loop:e.target.checked})}),"Loop"]}),s("label",{className:"sq-check",children:[t("input",{type:"checkbox",checked:i.autoPlay,onChange:e=>V(d.map(a=>({...a,autoPlay:a.id===i.id?e.target.checked:!1})))}),"Autoplay"]})]}),s("div",{className:"sq-body",children:[s("div",{className:"sq-main",children:[t(se,{controls:r,duration:i.duration,hasTracks:i.tracks.some(e=>!e.muted&&e.keyframes.length>0)}),s("div",{className:"sq-timeline","aria-label":"Sequence timeline",title:"Drag keys to retime. Arrow keys move 0.1s; Shift moves 0.01s. A key at the same time is replaced.",children:[s("div",{className:"sq-ruler",children:[t("span",{className:"sq-rulerTitle",children:"Tracks"}),t("div",{className:"sq-rulerScale",children:[0,.25,.5,.75,1].map(e=>s("span",{children:[(i.duration*e).toFixed(1),"s"]},e))})]}),!i.tracks.length&&t("p",{className:"sq-hint",children:"Add a track to create its start and end keyframes."}),i.tracks.map(e=>s("div",{className:`sq-track ${c?.id===e.id?"sq-track--active":""}`,children:[s("div",{className:"sq-trackLabel",children:[t("button",{type:"button",title:e.name,onClick:()=>{N(e.id),x(e.keyframes[0]?.id??null)},children:e.name}),s("label",{title:"Mute track",children:[t("input",{"aria-label":`Mute ${e.name}`,type:"checkbox",checked:!!e.muted,onChange:a=>D({...e,muted:a.target.checked})}),"Mute"]})]}),s("div",{className:"sq-lane",role:"group","aria-label":`${e.name} keyframes`,onDoubleClick:a=>{if(a.target!==a.currentTarget)return;let k=a.currentTarget.getBoundingClientRect(),n=Math.round(Math.max(0,Math.min(1,(a.clientX-k.left)/k.width))*i.duration*100)/100,b=r?.capture(e.target);b!=null&&C(e,{id:E(),time:n,value:b})},children:[t("span",{className:"sq-playhead",style:{left:`${q.time/i.duration*100}%`}}),e.keyframes.map(a=>{let k=K?.frameId===a.id&&K.trackId===e.id?K.time:a.time;return t("button",{type:"button",className:`sq-key ${h?.id===a.id&&c?.id===e.id?"sq-key--active":""}`,style:{left:`${k/i.duration*100}%`},"aria-label":`${e.name} keyframe at ${k.toFixed(2)} seconds`,"aria-pressed":h?.id===a.id&&c?.id===e.id,onClick:n=>{n.detail===0&&(N(e.id),x(a.id),r?.pause(),r?.seek(a.time))},onPointerDown:n=>{if(n.button!==0)return;n.preventDefault(),n.stopPropagation(),n.currentTarget.focus(),n.currentTarget.setPointerCapture(n.pointerId);let b=n.currentTarget.parentElement.getBoundingClientRect();M.current={track:e,frame:a,left:b.left,width:b.width,time:a.time},N(e.id),x(a.id),r?.pause(),r?.seek(a.time)},onPointerMove:n=>{let b=M.current;if(!b||b.frame.id!==a.id||b.track.id!==e.id)return;let ee=n.shiftKey?.01:.1;b.time=Math.min(i.duration,Math.max(0,Math.round((n.clientX-b.left)/b.width*i.duration/ee)*ee)),B({trackId:e.id,frameId:a.id,time:b.time}),r?.seek(b.time)},onPointerUp:()=>{let n=M.current;n&&(n.time!==n.frame.time&&C(n.track,{...n.frame,time:n.time}),M.current=null,B(null))},onPointerCancel:()=>{M.current=null,B(null),r?.seek(a.time)},onKeyDown:n=>{if(!["ArrowLeft","ArrowRight","Home","End"].includes(n.key))return;n.preventDefault(),n.stopPropagation();let b=n.key==="Home"?0:n.key==="End"?i.duration:a.time+(n.key==="ArrowLeft"?-1:1)*(n.shiftKey?.01:.1);C(e,{...a,time:b})}},a.id)})]})]},e.id))]})]}),s("aside",{className:"sq-side",children:[s(ue,{title:"Add track",children:[s("label",{className:"sq-field",children:[t("span",{children:"Type"}),s(j,{"aria-label":"Track type",value:w,onChange:e=>ve(e.target.value),children:[t("option",{value:"object",children:"Object"}),t("option",{value:"camera",children:"Camera"}),t("option",{value:"clip",children:"Animation clip"})]})]}),w==="object"&&s("label",{className:"sq-field",children:[t("span",{children:"Property"}),t(j,{"aria-label":"Track property",value:z,onChange:e=>Se(e.target.value),children:te.map(e=>t("option",{value:e,children:fe[e]},e))})]}),w==="object"&&s("label",{className:"sq-field",children:[t("span",{children:"Object"}),t(j,{"aria-label":"Track object",value:O?.modelObjectId??"",onChange:e=>xe(e.target.value),children:R.map(e=>t("option",{value:e.modelObjectId,children:e.label||e.modelObjectId},e.modelObjectId))})]}),w==="clip"&&s("label",{className:"sq-field",children:[t("span",{children:"Clip"}),t(j,{"aria-label":"Track animation clip",value:F??"",onChange:e=>Ne(e.target.value),children:u.map(e=>t("option",{value:e.sourceName,children:e.sourceName},e.sourceName))}),!u.length&&t("small",{children:"This model has no animation clips."})]}),t("div",{className:"rui-actions",children:s("button",{type:"button",className:"bb-button",onClick:Ce,disabled:!v||!q.ready||$||i.tracks.length>=128,children:[t(G,{size:13,"aria-hidden":"true"}),"Add track"]})}),$&&t("p",{className:"rui-note",children:"That property already has a track."})]}),c&&s("section",{className:"sq-inspector","aria-label":"Selected track and keyframe",children:[s("div",{className:"rui-groupHeader",children:[t("span",{children:"Selected track"}),t("button",{type:"button",className:"se-iconButton",title:"Delete track","aria-label":"Delete track",onClick:()=>{P({...i,tracks:i.tracks.filter(e=>e.id!==c.id)}),N(null),x(null)},children:t(Q,{size:13})})]}),t(_,{label:"Name",value:c.name,onChange:e=>D({...c,name:e})}),t("div",{className:"rui-actions",children:s("button",{type:"button",className:"bb-button",disabled:!q.ready||c.keyframes.length>=2048,onClick:Te,children:[t(Ee,{size:13,"aria-hidden":"true"}),"Add keyframe at playhead"]})}),h&&s(qe,{children:[s("div",{className:"rui-groupHeader",children:[t("span",{children:"Keyframe"}),t("button",{type:"button",className:"se-iconButton",title:"Delete keyframe","aria-label":"Delete keyframe",onClick:()=>{D({...c,keyframes:c.keyframes.filter(e=>e.id!==h.id)}),x(null)},children:t(Q,{size:14})})]}),t(I,{label:"Time",min:0,max:i.duration,value:h.time,step:.01,onChange:e=>C(c,{...h,time:e})}),s("label",{className:"sq-field",children:[t("span",{children:"Easing"}),t(j,{"aria-label":"Keyframe easing",value:c.target.kind==="object"&&c.target.property==="visible"?"step":h.easing??"ease-in-out",disabled:c.target.kind==="object"&&c.target.property==="visible",onChange:e=>C(c,{...h,easing:e.target.value}),children:ae.map(e=>t("option",{value:e,children:Ae[e]},e))})]}),t(be,{target:c.target,value:h.value,onChange:e=>C(c,{...h,value:e})}),t("div",{className:"rui-actions",children:s("button",{type:"button",className:"bb-button",disabled:!q.ready,onClick:()=>{let e=r?.capture(c.target);e!=null&&C(c,{...h,value:e})},children:[t(Pe,{size:13,"aria-hidden":"true"}),"Capture current value"]})})]})]})]})]})]}):s("div",{className:"sq-empty",children:[t("p",{children:"Add a sequence, then add tracks and capture keyframes on the timeline."}),s("button",{type:"button",className:"bb-button bb-button--primary",onClick:W,children:[t(G,{size:13,"aria-hidden":"true"}),"Create sequence"]})]}),(J||q.issues.length>0)&&t("div",{role:"status",className:"sq-error",children:J||q.issues.join(" ")})]})}export{Me as default};
@@ -1,7 +1,7 @@
1
1
  import * as react from 'react';
2
- import { B as BindingBuilderProps } from './publicProps-CW5X_HFh.mjs';
3
- import './modelViewerProps-wjBT4fks.mjs';
4
- import './modelFileResolver-Bq4pW9vc.mjs';
2
+ import { B as BindingBuilderProps } from './publicProps-BOQBJBA_.mjs';
3
+ import './modelViewerProps-BnVflYRA.mjs';
4
+ import './modelFileResolver-An1aQ0D3.mjs';
5
5
  import 'three';
6
6
  import '@react-three/drei';
7
7
 
@@ -1,7 +1,7 @@
1
1
  import * as react from 'react';
2
- import { B as BindingBuilderProps } from './publicProps-BZPMIRwj.js';
3
- import './modelViewerProps-BnrJO5DK.js';
4
- import './modelFileResolver-Bq4pW9vc.js';
2
+ import { B as BindingBuilderProps } from './publicProps-AdNUI06n.js';
3
+ import './modelViewerProps-H_K454u_.js';
4
+ import './modelFileResolver-An1aQ0D3.js';
5
5
  import 'three';
6
6
  import '@react-three/drei';
7
7