@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.
- package/README.md +23 -0
- package/dist/{SequencesTab-LTMJTB76.mjs → SequencesTab-JZEE5WAM.mjs} +1 -1
- package/dist/binding-builder.d.mts +3 -3
- package/dist/binding-builder.d.ts +3 -3
- package/dist/binding-builder.js +41 -41
- package/dist/binding-builder.mjs +1 -1
- package/dist/{chunk-NMRTI3NQ.mjs → chunk-3GA7JFNH.mjs} +1 -1
- package/dist/chunk-3I7PPFUV.mjs +1 -0
- package/dist/{chunk-IT2PUTJS.mjs → chunk-CHMFH4D4.mjs} +1 -1
- package/dist/{chunk-RSUXTWM6.mjs → chunk-CUDL77ZY.mjs} +1 -1
- package/dist/{chunk-XKJQC3N5.mjs → chunk-IEKGBS46.mjs} +1 -1
- package/dist/chunk-LU3BQ7WG.mjs +69 -0
- package/dist/chunk-QZNUWZG7.mjs +50 -0
- package/dist/{chunk-WU3SQZGD.mjs → chunk-TI2YXAHW.mjs} +2 -2
- package/dist/hosted.d.mts +3 -3
- package/dist/hosted.d.ts +3 -3
- package/dist/hosted.js +40 -40
- package/dist/hosted.mjs +1 -1
- package/dist/index.d.mts +8 -4
- package/dist/index.d.ts +8 -4
- package/dist/index.js +36 -36
- package/dist/index.mjs +1 -1
- package/dist/{modelFileResolver-Bq4pW9vc.d.mts → modelFileResolver-An1aQ0D3.d.mts} +3 -0
- package/dist/{modelFileResolver-Bq4pW9vc.d.ts → modelFileResolver-An1aQ0D3.d.ts} +3 -0
- package/dist/{modelViewerProps-BnrJO5DK.d.ts → modelViewerProps-BnVflYRA.d.mts} +21 -3
- package/dist/{modelViewerProps-wjBT4fks.d.mts → modelViewerProps-H_K454u_.d.ts} +21 -3
- package/dist/{publicProps-BZPMIRwj.d.ts → publicProps-AdNUI06n.d.ts} +1 -1
- package/dist/{publicProps-CW5X_HFh.d.mts → publicProps-BOQBJBA_.d.mts} +1 -1
- package/dist/simple-model-viewer.d.mts +6 -2
- package/dist/simple-model-viewer.d.ts +6 -2
- package/dist/simple-model-viewer.js +5 -5
- package/dist/simple-model-viewer.mjs +1 -1
- package/dist/utils.d.mts +4 -4
- package/dist/utils.d.ts +4 -4
- package/dist/utils.js +15 -15
- package/dist/utils.mjs +1 -1
- package/package.json +7 -5
- package/dist/chunk-2LGQKX6Z.mjs +0 -50
- package/dist/chunk-LEOHZ5HM.mjs +0 -69
- 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-
|
|
3
|
-
import './modelViewerProps-
|
|
4
|
-
import './modelFileResolver-
|
|
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-
|
|
3
|
-
import './modelViewerProps-
|
|
4
|
-
import './modelFileResolver-
|
|
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
|
|