videobook 0.2.2 → 0.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.
@@ -1 +1 @@
1
- import{a as d,b as Lt,j as t,c as _t}from"./vendor-react-Dj7D1fD4.js";import{eb as Ut,bw as Pt,b_ as $t,bv as ye}from"./videobook-DZ58pKW5.js";import{S as Ke,r as Ht,s as Ot,t as Kt,v as qt,w as Vt,x as Wt}from"./ui-OHFUngrc.js";import{X as Gt,aq as Xt,c as qe,ar as Zt,as as Yt,D as Jt,f as Qt,k as Ve,m as We,W as ei,a as Ge,w as ti,F as ii}from"./vendor-icons-CGqhCIXV.js";import"./vendor-yctIZ9Dz.js";import"./vendor-mcp-DQ7EusT9.js";import"./vendor-remotion-CH1HXrlc.js";import"./vendor-flow-zBavaNEW.js";const ie=[{label:"0.5×",value:"1/2",numerator:1,denominator:2},{label:"0.75×",value:"3/4",numerator:3,denominator:4},{label:"1×",value:"1/1",numerator:1,denominator:1},{label:"1.5×",value:"3/2",numerator:3,denominator:2},{label:"2×",value:"2/1",numerator:2,denominator:1}],ai=[{value:"media",label:"Media"},{value:"music",label:"Music"},{value:"autocut",label:"Auto-cut"}],ni=20,si=60;function ri(s){return[...s.querySelectorAll('a[href], button:not([disabled]), input:not([disabled]), select:not([disabled]), [tabindex]:not([tabindex="-1"])')].filter(l=>l.getClientRects().length>0&&!l.closest("[hidden], [inert]"))}function x(s){return s.timelineStartFrame+s.durationFrames}const ae=$t;function Xe(s){return Math.max(ni,Math.min(si,Math.round(s)))}function li(s,l){const c=[...s].reverse().find(h=>h.frame<l),r=s.find(h=>h.frame>l);return{previous:c?.frame??null,next:r?.frame??null}}function oi(s,l){return l?s.clips.filter(c=>c.trackId===l).sort((c,r)=>c.timelineStartFrame-r.timelineStartFrame||c.clipId.localeCompare(r.clipId)):[]}function ci(s){if(!s||s.source.kind!=="timed")return"1/1";const l=s;return`${l.speed.numerator}/${l.speed.denominator}`}function di(s,l){if(s.source.kind!=="timed")return s.durationFrames;const c=s,r=c.source.range.durationTicks*c.source.range.timeBase.numerator/c.source.range.timeBase.denominator;return Math.max(1,Math.ceil(r*l))}function ui(s){const[l,c]=s.split("/").map(Number);if(!l||!c)return s;const r=l/c;return Number.isInteger(r)?`${r}×`:`${parseFloat(r.toFixed(2))}×`}function mi(s,l){const c=s.findIndex(r=>r.clipId===l.clipId);return c>=0?s[c+1]:void 0}function Ze(s,l,c){const r=l.findIndex(o=>o.clipId===s.clipId),h=r>0?l[r-1]:void 0,f=r>=0?l[r+1]:void 0;return{left:s.timelineStartFrame-(h?x(h):0),right:(f?f.timelineStartFrame:c)-x(s)}}function pi(s,l,c){if(s.source.kind!=="timed")return{before:s.timelineStartFrame,after:Number.MAX_SAFE_INTEGER};const r=s,h=r.speed.numerator/r.speed.denominator,f=r.source.range.timeBase.numerator/r.source.range.timeBase.denominator,o=r.source.range.startTick*f,w=(r.source.range.startTick+r.source.range.durationTicks)*f,ne=l?.duration??w,U=Math.floor(o*c/h),P=Math.floor(Math.max(0,ne-w)*c/h);return r.reverse?{before:P,after:U}:{before:U,after:P}}function fi(s){return/\.(avif|bmp|gif|jpe?g|png|webp)(?:$|\?)/i.test(s)}function bi(s){const l=_t.c(5),{asset:c}=s,r=c.thumbnailUrl??(c.mediaUrl&&fi(c.mediaUrl)?c.mediaUrl:null);if(r){let f;return l[0]!==r?(f=t.jsx("img",{src:r,alt:""}),l[0]=r,l[1]=f):f=l[1],f}if(c.mediaUrl){let f;return l[2]!==c.mediaUrl?(f=t.jsx("video",{src:c.mediaUrl,muted:!0,playsInline:!0,preload:"metadata",onLoadedMetadata:vi}),l[2]=c.mediaUrl,l[3]=f):f=l[3],f}let h;return l[4]===Symbol.for("react.memo_cache_sentinel")?(h=t.jsx(ii,{size:24}),l[4]=h):h=l[4],h}function vi(s){const l=s.currentTarget;l.duration>0&&(l.currentTime=Math.min(.12,l.duration*.15))}function hi(s,l){return s.status==="ready"||s.status==="applying"||s.status==="applied"?s.timelineLimitFrame:Math.max(1,...l.clips.map(x))}function wi({sequence:s,assets:l,audioArtifactId:c,setup:r,returnFocus:h,assembly:f,rhythm:o,address:w,initialFrame:ne=0,onFrameUpdate:U,onExport:P,onPlanDraft:Ye,onApplyDraft:Je,onApplySetup:Qe,onClose:se,onCommit:et,onCreateTrack:tt,onRefreshAssets:it,onRestore:Se,onReviewSetup:ke}){const $=d.useRef(null),at=d.useEffectEvent(se),[L,re]=d.useState(r.status!=="timeline"),[nt,Ie]=d.useState(34),[le,Ce]=d.useState({mode:"beats",fallback:"off"}),[st,we]=d.useState(!1),M=d.useRef(null),Ne=d.useRef(null),Me=d.useRef(null),[F,rt]=d.useState(ne),Fe=d.useCallback(e=>{rt(e),U(e)},[U]),[u,oe]=d.useState(null),[ce,lt]=d.useState(""),[C,q]=d.useState([]),ot=f.selectedClipId,N=f.selectClip,[Ee,E]=d.useState(null),[b,g]=d.useState(null),[Re,p]=d.useState(null),[de,V]=d.useState([]),[ue,W]=d.useState([]),[me,T]=d.useState(null),[G,H]=d.useState(()=>Ut(r.status)),O=l.find(e=>e.artifactId===(o.master?.source.artifactId??c)),S=[...s.tracks].sort((e,i)=>e.ordinal-i.ordinal).find(e=>e.kind==="video")??null,y=oi(s,S?.trackId??null),a=y.find(e=>e.clipId===ot)??null,X=d.useMemo(()=>new Map(l.map(e=>[e.artifactId,e])),[l]),Z=me?X.get(me):void 0,ct=d.useMemo(()=>l.flatMap(e=>e.mediaUrl?[{artifactId:e.artifactId,mediaUrl:e.mediaUrl}]:[]),[l]),pe=d.useMemo(()=>{const e=ce.trim().toLowerCase();return l.filter(i=>(i.type==="video"||i.type==="final")&&i.status==="ready"&&i.mediaUrl&&(!e||i.label.toLowerCase().includes(e)||i.artifactId.toLowerCase().includes(e)))},[l,ce]),v=o.master?o.master.timelineStartFrame+o.master.durationFrames:hi(r,s),j=s.frameRate.numerator/s.frameRate.denominator,fe=Math.max(0,...y.map(x)),Be=Math.max(0,fe-v),be=(r.status==="ready"||r.status==="applied"||r.status==="timeline")&&S!==null&&S.enabled&&!S.locked,_=a?Ee?.clipId===a.clipId?Ee:{clipId:a.clipId,startFrame:a.timelineStartFrame,endFrame:x(a)}:null,ve=a?X.get(a.source.artifactId):void 0,Te=a?pi(a,ve,j):{before:0,after:0},Y=a?y.findIndex(e=>e.clipId===a.clipId):-1,he=a?mi(y,a)?.timelineStartFrame??v:v,Ae=a?Ze(a,y,v):{left:0,right:0},dt=Y>0,ut=Y>=0&&Y<y.length-1,mt=dt||Ae.left>0,pt=ut||Ae.right>0,ft=!!(a&&he>x(a)),De=a?Math.max(0,a.timelineStartFrame-Te.before):0,ze=a?Math.min(v,x(a)+Te.after):v,J=ci(a),bt=ie.some(e=>e.value===J)?[...ie]:[{label:ui(J),value:J},...ie],Le=li(o.mapped,F),R=o.mapped.length>0,A=o.mapped.some(e=>e.bar),vt=o.analysis?.barSource==="estimated"&&!o.rhythm.settings.correction,K=o.status==="queued"||o.status==="analyzing",xe=le.mode==="bars"&&!A?le.fallback:le.mode,B=xe==="beats"&&!R||xe==="bars"&&!A?"off":xe,_e=[{value:"off",label:"Off"},{value:"beats",label:"Beats",disabled:!R,title:R?"Snap edits to beats":"Analyze beats or set a beat grid first"},{value:"bars",label:"Bars",disabled:!R,title:A?"Snap edits to bar starts":"Set up bar starts to enable bar snapping"}];function Q(e="beats"){N(null),re(!0),H("music"),e==="beats"&&we(!!o.master),Ce({mode:e,fallback:B}),e==="bars"&&requestAnimationFrame(()=>{const i=$.current?.querySelector('input[name="beats-per-bar"]');i?.focus(),i?.scrollIntoView({block:"nearest"})})}function Ue(e){if(e==="bars"&&!A){Q(e);return}Ce({mode:e,fallback:"off"})}d.useEffect(()=>{const e=$.current;e?.showModal(),e?.querySelector(".music-video-close")?.focus();const i=n=>{if(n.isComposing||n.keyCode===229||!(n.target instanceof Element)||n.target.closest("dialog")!==e)return;if(n.key==="Escape"){n.preventDefault(),at();return}if(n.key!=="Tab"||!e)return;const m=ri(e),I=m[0],D=m[m.length-1];n.shiftKey&&document.activeElement===I?(n.preventDefault(),D?.focus()):!n.shiftKey&&document.activeElement===D&&(n.preventDefault(),I?.focus())};return document.addEventListener("keydown",i),()=>{document.removeEventListener("keydown",i),e?.close(),Pt(h)}},[h]);const k=async(e,i)=>{if(b||u)return!1;if(!S)return p("Create a main video track before editing clips"),!1;if(r.status!=="ready"&&r.status!=="applied"&&r.status!=="timeline")return p("Wait for the soundtrack duration before editing clips"),!1;g(e),p(null);try{const n=await et(i,s);return V(m=>[...m,{beforeRevision:n.beforeRevision,afterRevision:n.sequence.revision}]),W([]),E(null),!0}catch(n){return p(n instanceof Error?n.message:String(n)),!1}finally{g(null)}},ee=e=>{const i=Math.max(0,Math.min(Math.max(v,...s.clips.map(x))-1,Math.round(e)));T(null),Fe(i),M.current?.seekTo(i)},ht=e=>{T(null),N(e.clipId),s.tracks.find(i=>i.trackId===e.trackId)?.kind==="audio"&&H("music"),E({clipId:e.clipId,startFrame:e.timelineStartFrame,endFrame:x(e)}),ee(e.timelineStartFrame)},xt=e=>{T(e),N(null),q(i=>i.includes(e)?i.filter(n=>n!==e):[...i,e])},gt=async()=>{!S||C.length===0||!await k("Adding clips",{kind:"append_clips",track_id:S.trackId,artifact_ids:C,timeline_limit_frame:o.master?v:Math.max(v,fe+C.reduce((i,n)=>i+Math.ceil((X.get(n)?.duration??0)*j),0)),fit:"source",visual_fit:"fit"})||(q([]),T(null))},jt=async e=>{S&&await k("Reordering clips",{kind:"reorder_clips",track_id:S.trackId,clip_ids:e,timeline_limit_frame:v})},yt=async e=>{if(!a||!S)return;const i=y.findIndex(z=>z.clipId===a.clipId),n=i+e;if(n>=0&&n<y.length){const z=y.map(zt=>zt.clipId),[Oe]=z.splice(i,1);if(!Oe)return;z.splice(n,0,Oe),await jt(z);return}const m=Ze(a,y,v),I=Math.max(1,Math.round(j)),D=e<0?-Math.min(I,m.left):Math.min(I,m.right);D!==0&&await k("Moving clip",{kind:"move",clip_id:a.clipId,track_id:S.trackId,timeline_start_frame:a.timelineStartFrame+D})},St=async()=>{if(!a||he<=x(a))return;const e=he-a.timelineStartFrame;if(a.source.kind!=="timed"){await k("Stretching clip",{kind:"trim",clip_id:a.clipId,timeline_start_frame:a.timelineStartFrame,duration_frames:e,edge:"end",ripple:!1,timeline_limit_frame:v});return}const i=a,n=di(a,j);await k("Stretching clip",{kind:"speed",clip_id:a.clipId,numerator:n,denominator:e,reverse:i.reverse,audio_policy:"mute",ripple:!1,timeline_limit_frame:v})},te=async(e,i,n)=>{if(!(!a||n<=i)&&!(i===a.timelineStartFrame&&n===x(a))){if(B!=="off"&&(e==="start"?i=ye(i,o.mapped,B):n=ye(n,o.mapped,B)),n<=i){p("Choose distinct beat boundaries or turn snapping off");return}await k("Trimming clip",{kind:"trim",clip_id:a.clipId,timeline_start_frame:i,duration_frames:n-i,edge:e,ripple:!1,timeline_limit_frame:v})}},ge=async()=>{if(!a||F<=a.timelineStartFrame||F>=x(a)){p("Place the playhead inside the selected clip before cutting");return}const e=ye(F,o.mapped,B);if(e<=a.timelineStartFrame||e>=x(a)){p("Choose a beat inside the selected clip, or turn snapping off");return}await k("Cutting clip",{kind:"split",clip_id:a.clipId,split_frame:e}),N(null)},Pe=async()=>{a&&(await k("Deleting clip",{kind:"delete",clip_id:a.clipId,ripple:!1}),N(null))},kt=async e=>{if(!a||a.source.kind!=="timed")return;const i=ie.find(z=>z.value===e),[n,m]=e.split("/").map(Number),I=i??(n&&m?{numerator:n,denominator:m}:null);if(!I)return;const D=a;await k("Retiming clip",{kind:"speed",clip_id:a.clipId,numerator:I.numerator,denominator:I.denominator,reverse:D.reverse,audio_policy:"mute",ripple:!1,timeline_limit_frame:v})},$e=async()=>{const e=de[de.length-1];if(!(!e||b)){g("Undoing edit"),p(null);try{await Se(e.beforeRevision,s.revision),V(i=>i.slice(0,-1)),W(i=>[...i,e]),N(null),E(null)}catch(i){p(i instanceof Error?i.message:String(i))}finally{g(null)}}},He=async()=>{const e=ue[ue.length-1];if(!(!e||b)){g("Redoing edit"),p(null);try{await Se(e.afterRevision,s.revision),W(i=>i.slice(0,-1)),V(i=>[...i,e]),N(null),E(null)}catch(i){p(i instanceof Error?i.message:String(i))}finally{g(null)}}},It=(e,i)=>{if(e==="split"&&ge(),e==="delete"&&Pe(),e==="undo"&&$e(),e==="redo"&&He(),e==="search"&&(re(!0),H("media"),requestAnimationFrame(()=>Ne.current?.focus())),e==="zoom-in"&&$.current?.querySelector('[aria-label="Zoom timeline in"]')?.click(),e==="zoom-out"&&$.current?.querySelector('[aria-label="Zoom timeline out"]')?.click(),e==="mark-in"&&a){const n=_?.endFrame??x(a);i<n&&(E({clipId:a.clipId,startFrame:i,endFrame:n}),te("start",i,n))}if(e==="mark-out"&&a){const n=_?.startFrame??a.timelineStartFrame;i>n&&(E({clipId:a.clipId,startFrame:n,endFrame:i}),te("end",n,i))}},Ct=async()=>{if(!(r.status!=="ready"||b)){g("Applying soundtrack"),p(null);try{await Qe()}catch(e){p(e instanceof Error?e.message:String(e))}finally{g(null)}}},wt=async e=>{if(!b){g("Creating soundtrack track"),p(null);try{const i=await tt(e);e==="audio"&&await ke(i)}catch(i){p(i instanceof Error?i.message:String(i))}finally{g(null)}}},Nt=e=>{if(e.defaultPrevented||e.nativeEvent.isComposing||e.nativeEvent.keyCode===229||e.target.closest('input, textarea, select, [contenteditable="true"], .canonical-player'))return;if(M.current){M.current.handleKeyDown(e);return}const n=Me.current,m=e.key.toLowerCase();!n||m!==" "&&m!=="k"||(e.preventDefault(),n.paused?n.play().catch(()=>{}):n.pause())},Mt=async e=>{if(!b){g("Planning draft"),p(null),M.current?.pause();try{const i=await Ye(e,s);oe(i),T(null),ee(e.start_frame)}catch(i){p(i instanceof Error?i.message:String(i))}finally{g(null)}}},Ft=async()=>{if(!(!u||b||u.uncovered.length)){g("Applying draft"),p(null),M.current?.pause();try{const e=await Je(u);V(i=>[...i,{beforeRevision:e.beforeRevision,afterRevision:e.sequence.revision}]),W([]),oe(null),N(null)}catch(e){p(e instanceof Error?e.message:String(e))}finally{g(null)}}},je=!be||!!b||!!u,Et=e=>{if(e.button!==0)return;const i=e.currentTarget;i.setPointerCapture(e.pointerId);const n=I=>{Ie(Xe((window.innerHeight-I.clientY)/window.innerHeight*100))},m=()=>{i.removeEventListener("pointermove",n),i.removeEventListener("pointerup",m),i.removeEventListener("pointercancel",m)};i.addEventListener("pointermove",n),i.addEventListener("pointerup",m),i.addEventListener("pointercancel",m)},Rt=e=>{const i=e.key==="ArrowUp"?2:e.key==="ArrowDown"?-2:0;i&&(e.preventDefault(),e.stopPropagation(),Ie(n=>Xe(n+i)))},Bt=()=>{M.current?.pause(),oe(null)},Tt=C.flatMap(e=>{const i=X.get(e);return i?[i]:[]}),At=A?vt?` · Estimated ${o.analysis?.beatsPerBar}-beat bars`:"":" · Bars not set",Dt=K?"Analyzing beats…":R?`${o.mapped.length} beats${o.analysis?.lowConfidence&&!o.rhythm.settings.correction?" · Review timing":""}${At}`:o.status==="no-beats"?"Analysis complete · No reliable beats found · Set a beat grid":o.master?"Analyze the soundtrack to enable snapping":"Choose a soundtrack for snapping";return Lt.createPortal(t.jsxs("dialog",{className:"music-video-editor timeline-preview-fullscreen","aria-label":w?`Timeline preview ${w}`:"Music video editor",style:{"--music-timeline-height":`${nt}dvh`},onCancel:e=>{e.preventDefault(),se()},ref:$,tabIndex:-1,onKeyDown:Nt,children:[t.jsxs("header",{className:"music-video-editor-header",children:[t.jsx("button",{className:"music-video-close mv-icon",type:"button",onClick:se,"aria-label":w?"Close timeline preview":"Close music video editor",children:t.jsx(Gt,{size:20})}),t.jsxs("div",{className:"music-video-title",children:[t.jsxs("h1",{children:[w?t.jsxs(t.Fragment,{children:["Timeline ",t.jsx("code",{children:w})]}):O?.label??"Music video",u&&t.jsx("span",{className:"mv-draft-badge",children:"Draft preview"})]}),t.jsxs("p",{children:[s.width,"×",s.height," · ",parseFloat(j.toFixed(2))," fps · ",ae(v,j)]})]}),t.jsxs("div",{className:"music-video-header-actions",children:[t.jsxs("button",{type:"button",className:"mv-quiet mv-tools-toggle","aria-pressed":L,"aria-label":L?"Hide tools":"Show tools",onClick:()=>re(e=>!e),children:[t.jsx(Xt,{size:16})," ",t.jsx("span",{children:L?"Hide tools":"Show tools"})]}),u?t.jsxs(t.Fragment,{children:[t.jsx("span",{className:"mv-draft-note",children:"Nothing changes until you apply."}),t.jsx("button",{type:"button",disabled:!!b,onClick:Bt,children:"Discard draft"}),t.jsxs("button",{type:"button",className:"mv-apply",disabled:!!b||u.uncovered.length>0,onClick:()=>{Ft()},children:[t.jsx(qe,{size:16})," Apply draft"]})]}):t.jsxs(t.Fragment,{children:[t.jsxs("button",{type:"button",className:"mv-quiet",disabled:!!b||de.length===0,onClick:()=>{$e()},children:[t.jsx(Zt,{size:16})," Undo"]}),t.jsxs("button",{type:"button",className:"mv-quiet",disabled:!!b||ue.length===0,onClick:()=>{He()},children:[t.jsx(Yt,{size:16})," Redo"]}),t.jsxs("button",{type:"button",className:"mv-primary",onClick:P,children:[t.jsx(Jt,{size:16})," Export"]})]})]})]}),t.jsxs("main",{className:["music-video-editor-main",L?"":"tools-hidden",a||u?"inspecting":""].filter(Boolean).join(" "),children:[t.jsxs("aside",{className:"music-video-library","aria-label":"Library",hidden:!L,children:[t.jsx("div",{className:"music-video-library-tabs",role:"tablist","aria-label":"Library views",children:ai.map(e=>t.jsx("button",{type:"button",role:"tab",id:`mv-tab-${e.value}`,"aria-controls":`mv-panel-${e.value}`,"aria-selected":G===e.value,onClick:()=>H(e.value),children:e.label},e.value))}),t.jsxs("section",{className:"music-video-source-panel",role:"tabpanel",id:"mv-panel-media","aria-labelledby":"mv-tab-media",hidden:G!=="media",children:[t.jsxs("div",{className:"mv-panel-head",children:[t.jsxs("label",{className:"music-video-search",children:[t.jsx(Qt,{size:15}),t.jsx("input",{ref:Ne,value:ce,onChange:e=>lt(e.target.value),placeholder:"Search this book","aria-label":"Search source clips"})]}),t.jsx("button",{type:"button",className:"mv-icon","aria-label":"Refresh media",title:"Refresh media",onClick:()=>{it().catch(e=>p(String(e)))},children:t.jsx(Ve,{size:15})})]}),t.jsxs("div",{className:"mv-panel-meta",children:[t.jsxs("span",{children:[C.length," of ",pe.length," selected"]}),C.length>0&&t.jsx("button",{type:"button",className:"mv-link",onClick:()=>q([]),children:"Clear"})]}),t.jsxs("div",{className:"music-video-source-list",children:[pe.map(e=>{const i=C.indexOf(e.artifactId),n=me===e.artifactId;return t.jsxs("button",{type:"button",className:[i>=0?"selected":"",n?"previewing":""].filter(Boolean).join(" "),"aria-pressed":i>=0,"aria-label":e.label,onClick:()=>xt(e.artifactId),children:[t.jsxs("span",{className:"music-video-source-thumb",children:[t.jsx(bi,{asset:e}),i>=0&&t.jsx("i",{children:i+1}),e.duration!==null&&t.jsx("small",{children:ae(Math.round(e.duration*j),j)})]}),t.jsx("span",{className:"music-video-source-name",title:e.label,children:e.label})]},e.artifactId)}),pe.length===0&&t.jsx("p",{children:"No ready video sources match this search."})]}),t.jsxs("footer",{className:"mv-panel-foot",children:[t.jsxs("button",{type:"button",className:"mv-primary music-video-add-selected",disabled:je||C.length===0,onClick:()=>{gt()},children:[t.jsx(We,{size:15})," Add ",C.length||""," to end"]}),t.jsxs("button",{type:"button",disabled:C.length===0,onClick:()=>H("autocut"),children:[t.jsx(ei,{size:15})," Auto-cut…"]})]})]}),t.jsxs("section",{className:"mv-music-panel",role:"tabpanel",id:"mv-panel-music","aria-labelledby":"mv-tab-music",hidden:G!=="music",children:[t.jsxs("div",{className:"music-video-setup-card","data-status":r.status,children:[t.jsxs("span",{className:"mv-kicker",children:[t.jsx(Ge,{size:13})," Soundtrack",O?` · ${O.label}`:""]}),r.status==="loading"&&t.jsx("p",{children:"Building the exact canonical setup plan…"}),r.status==="needs-audio-track"&&t.jsxs(t.Fragment,{children:[t.jsx("p",{children:r.message}),t.jsxs("button",{type:"button",className:"mv-primary",disabled:!!b,onClick:()=>{wt("audio")},children:[t.jsx(We,{size:15})," Create soundtrack track"]})]}),(r.status==="ready"||r.status==="applying")&&t.jsxs(t.Fragment,{children:[t.jsx("strong",{children:r.summary}),t.jsxs("p",{children:[r.operationCount," atomic operations · ends at ",ae(r.timelineLimitFrame,j)]}),r.warnings.map(e=>t.jsx("small",{children:e},e)),t.jsxs("button",{type:"button",className:"mv-primary",disabled:!!b,onClick:()=>{Ct()},children:[t.jsx(Ge,{size:15})," Apply soundtrack"]})]}),r.status==="applied"&&t.jsxs("strong",{className:"music-video-applied",children:[t.jsx(qe,{size:15})," Soundtrack applied"]}),r.status==="error"&&t.jsxs(t.Fragment,{children:[t.jsx("p",{className:"music-video-error",children:r.message}),t.jsxs("button",{type:"button",disabled:!!b,onClick:()=>{ke()},children:[t.jsx(Ve,{size:15})," Review again"]})]})]}),t.jsxs("div",{className:"mv-control",children:[t.jsx("span",{children:"Snap edits to"}),t.jsx(Ke,{label:"Snap to music",options:_e,value:B,onChange:Ue}),t.jsx("p",{className:"mv-hint",children:"Hold Alt while dragging to ignore snapping."})]}),t.jsx(Ht,{rhythm:o,sequence:s,assets:l,frame:F,correctionsOpen:st,onCorrectionsOpenChange:we})]}),t.jsx("section",{className:"mv-autocut-panel",role:"tabpanel",id:"mv-panel-autocut","aria-labelledby":"mv-tab-autocut",hidden:G!=="autocut",children:t.jsx(Ot,{sources:Tt,trackId:S?.trackId??null,startFrame:o.master?.timelineStartFrame??0,endFrame:v,fps:j,hasBars:A,busy:!!b,draft:u,onPlan:e=>{Mt(e)},onOrder:q})})]}),t.jsxs("section",{className:"music-video-preview-panel timeline-preview-body","aria-label":"Program monitor",children:[t.jsx("div",{className:"mv-monitor",children:Z?.mediaUrl?t.jsxs("div",{className:"music-video-source-preview",children:[t.jsx("video",{ref:Me,src:Z.mediaUrl,controls:!0,autoPlay:!0,muted:!0,playsInline:!0},Z.artifactId),t.jsxs("p",{children:[t.jsxs("span",{children:["Source · ",Z.label]}),t.jsx("button",{type:"button",onClick:()=>T(null),children:"Show sequence"})]})]}):t.jsx(Kt,{ref:M,sequence:u?.sequence??s,assets:ct,onFrameUpdate:Fe,initialFrame:F,presentation:"preview",allowFullscreen:!1,editingEnabled:!u,onKeyboardAction:It})}),t.jsx(qt,{frame:F,durationFrames:Math.max(v,fe),fps:j,previousBeat:Le.previous,nextBeat:Le.next,onTogglePlay:()=>{T(null),M.current?.togglePlay()},onSeek:ee})]}),t.jsxs("aside",{className:"music-video-inspector","aria-label":"Inspector",hidden:!L,children:[a&&!u&&t.jsx("button",{type:"button",className:"mv-link mv-back",onClick:()=>N(null),children:"← Back to library"}),u?t.jsxs("div",{className:"mv-draft-summary",children:[t.jsx("span",{className:"mv-kicker",children:"Draft review"}),t.jsx("strong",{children:u.plan.summary}),t.jsxs("p",{children:[u.shots.length," shots · replaces ",u.preview.diff.removedClipIds.length," clips"]}),u.uncovered.length>0&&t.jsx("p",{className:"music-video-error",children:"Gaps remain, so the draft can't be applied. Allow repeated footage or add sources in Auto-cut."}),u.warnings.map(e=>t.jsx("small",{children:e},e)),t.jsx("p",{className:"mv-hint",children:"The full shot list is in Auto-cut."})]}):a&&_?t.jsx(Vt,{clip:a,label:ve?.label??"Clip",thumbnailUrl:ve?.thumbnailUrl??null,index:Y+1,count:y.length,fps:j,trimStart:_.startFrame,trimEnd:_.endFrame,trimMin:De,trimMax:Math.max(_.endFrame,ze),speed:J,speedOptions:bt,retimable:a.source.kind==="timed",busy:!!b,editsDisabled:je,canMoveEarlier:mt,canMoveLater:pt,canStretch:ft,onTrim:(e,i,n)=>{E({clipId:a.clipId,startFrame:i,endFrame:n}),te(e,i,n)},onSpeed:e=>{kt(e)},onFit:e=>{k("Fitting clip",{kind:"transform",clip_id:a.clipId,fit:e})},onSplit:()=>{ge()},onStretch:()=>{St()},onMove:e=>{yt(e)},onDelete:()=>{Pe()}}):t.jsxs("div",{className:"mv-sequence-summary",children:[t.jsx("span",{className:"mv-kicker",children:"Sequence"}),t.jsxs("dl",{children:[t.jsx("dt",{children:"Frame"}),t.jsxs("dd",{children:[s.width," × ",s.height]}),t.jsx("dt",{children:"Rate"}),t.jsxs("dd",{children:[parseFloat(j.toFixed(2))," fps"]}),t.jsx("dt",{children:"Length"}),t.jsx("dd",{children:ae(v,j)}),t.jsx("dt",{children:"Clips"}),t.jsx("dd",{children:y.length})]}),y.length>0?t.jsx("p",{children:"Select a clip on the timeline to trim, retime or delete it."}):t.jsxs("ol",{className:"mv-steps",children:[t.jsx("li",{children:"Pick footage in Media"}),t.jsx("li",{children:"Choose a soundtrack in Music"}),t.jsx("li",{children:"Auto-cut, or add clips and trim by hand"})]})]})]}),t.jsxs("section",{className:"music-video-timeline-panel","aria-label":"Music video timeline",children:[t.jsx("button",{type:"button",className:"mv-resize-handle","aria-label":"Resize timeline",title:"Drag to resize the timeline (↑/↓)",onPointerDown:Et,onKeyDown:Rt}),t.jsx(Wt,{sequence:u?.sequence??s,assets:l,assembly:f,disabled:!!b||!!u,frame:F,address:w??"",onSeek:ee,onSelectClip:ht,onExport:P,presentation:"preview",onMoveClip:be?(e,i)=>{k("Moving clip",{kind:"move",clip_id:e.clipId,track_id:e.trackId,timeline_start_frame:i})}:void 0,onRemoveClip:e=>{k("Removing clip",{kind:"remove_clip",clip_id:e.clipId,ripple:!1})},onTrimClip:be?(e,i,n,m)=>{e.clipId===a?.clipId&&(E({clipId:e.clipId,startFrame:n,endFrame:m}),te(i,n,m))}:void 0,trimBounds:a?{min:De,max:Math.max(x(a),ze)}:void 0,rhythm:{masterClipId:o.master?.clipId??null,markers:o.mapped,analysis:o.analysis,snap:B},toolbar:t.jsxs(t.Fragment,{children:[t.jsx("span",{children:"Snap"}),t.jsx(Ke,{label:"Snap to music",options:_e,value:B,onChange:Ue}),!o.master&&t.jsx("button",{type:"button",disabled:o.busy,onClick:()=>Q(),children:"Choose soundtrack"}),o.master&&!R&&!K&&t.jsx("button",{type:"button",disabled:o.busy,onClick:()=>{o.analyze(!!o.analysis)},children:o.analysis?"Analyze again":"Analyze beats"}),K&&t.jsx("button",{type:"button",disabled:o.busy,onClick:()=>{o.cancel()},children:"Cancel analysis"}),o.master&&!R&&o.analysis&&!K&&t.jsx("button",{type:"button",disabled:o.busy,onClick:()=>Q(),children:"Set beat grid"}),R&&!A&&t.jsx("button",{type:"button",disabled:o.busy||K,onClick:()=>Q("bars"),children:"Set bars"}),t.jsxs("button",{type:"button",disabled:je||!a,title:"Split the selected clip at the playhead (S)",onClick:()=>{ge()},children:[t.jsx(ti,{size:14})," Split"]}),o.master&&t.jsxs("span",{className:"music-master-name",title:O?.label,children:["♪ ",O?.label??"Soundtrack"]}),t.jsx("span",{role:"status",children:Dt})]})}),Be>0&&t.jsxs("p",{children:[Be," frames beyond soundtrack"]})]})]}),t.jsxs("footer",{className:"music-video-status","aria-live":"polite",children:[t.jsx("span",{children:b??(u?"Draft ready · review it, then apply or discard":"Saved")}),(Re||o.error)&&t.jsx("strong",{role:"alert",children:Re||o.error}),t.jsx("span",{className:"mv-shortcuts",children:"Space play · J/L shuttle · ←/→ frame · I/O trim · S split · Delete · ⌘Z undo"})]})]}),document.body)}export{wi as MusicVideoEditor};
1
+ import{a as d,b as Lt,j as t,c as _t}from"./vendor-react-Dj7D1fD4.js";import{ec as Ut,bw as Pt,b_ as $t,bv as ye}from"./videobook-B5G0jMoi.js";import{S as Ke,r as Ht,s as Ot,t as Kt,v as qt,w as Vt,x as Wt}from"./ui-Cpr6zMTA.js";import{X as Gt,aq as Xt,c as qe,ar as Zt,as as Yt,D as Jt,f as Qt,k as Ve,m as We,W as ei,a as Ge,w as ti,F as ii}from"./vendor-icons-CGqhCIXV.js";import"./vendor-yctIZ9Dz.js";import"./vendor-mcp-DQ7EusT9.js";import"./vendor-remotion-CH1HXrlc.js";import"./vendor-flow-zBavaNEW.js";const ie=[{label:"0.5×",value:"1/2",numerator:1,denominator:2},{label:"0.75×",value:"3/4",numerator:3,denominator:4},{label:"1×",value:"1/1",numerator:1,denominator:1},{label:"1.5×",value:"3/2",numerator:3,denominator:2},{label:"2×",value:"2/1",numerator:2,denominator:1}],ai=[{value:"media",label:"Media"},{value:"music",label:"Music"},{value:"autocut",label:"Auto-cut"}],ni=20,si=60;function ri(s){return[...s.querySelectorAll('a[href], button:not([disabled]), input:not([disabled]), select:not([disabled]), [tabindex]:not([tabindex="-1"])')].filter(l=>l.getClientRects().length>0&&!l.closest("[hidden], [inert]"))}function x(s){return s.timelineStartFrame+s.durationFrames}const ae=$t;function Xe(s){return Math.max(ni,Math.min(si,Math.round(s)))}function li(s,l){const c=[...s].reverse().find(h=>h.frame<l),r=s.find(h=>h.frame>l);return{previous:c?.frame??null,next:r?.frame??null}}function oi(s,l){return l?s.clips.filter(c=>c.trackId===l).sort((c,r)=>c.timelineStartFrame-r.timelineStartFrame||c.clipId.localeCompare(r.clipId)):[]}function ci(s){if(!s||s.source.kind!=="timed")return"1/1";const l=s;return`${l.speed.numerator}/${l.speed.denominator}`}function di(s,l){if(s.source.kind!=="timed")return s.durationFrames;const c=s,r=c.source.range.durationTicks*c.source.range.timeBase.numerator/c.source.range.timeBase.denominator;return Math.max(1,Math.ceil(r*l))}function ui(s){const[l,c]=s.split("/").map(Number);if(!l||!c)return s;const r=l/c;return Number.isInteger(r)?`${r}×`:`${parseFloat(r.toFixed(2))}×`}function mi(s,l){const c=s.findIndex(r=>r.clipId===l.clipId);return c>=0?s[c+1]:void 0}function Ze(s,l,c){const r=l.findIndex(o=>o.clipId===s.clipId),h=r>0?l[r-1]:void 0,f=r>=0?l[r+1]:void 0;return{left:s.timelineStartFrame-(h?x(h):0),right:(f?f.timelineStartFrame:c)-x(s)}}function pi(s,l,c){if(s.source.kind!=="timed")return{before:s.timelineStartFrame,after:Number.MAX_SAFE_INTEGER};const r=s,h=r.speed.numerator/r.speed.denominator,f=r.source.range.timeBase.numerator/r.source.range.timeBase.denominator,o=r.source.range.startTick*f,w=(r.source.range.startTick+r.source.range.durationTicks)*f,ne=l?.duration??w,U=Math.floor(o*c/h),P=Math.floor(Math.max(0,ne-w)*c/h);return r.reverse?{before:P,after:U}:{before:U,after:P}}function fi(s){return/\.(avif|bmp|gif|jpe?g|png|webp)(?:$|\?)/i.test(s)}function bi(s){const l=_t.c(5),{asset:c}=s,r=c.thumbnailUrl??(c.mediaUrl&&fi(c.mediaUrl)?c.mediaUrl:null);if(r){let f;return l[0]!==r?(f=t.jsx("img",{src:r,alt:""}),l[0]=r,l[1]=f):f=l[1],f}if(c.mediaUrl){let f;return l[2]!==c.mediaUrl?(f=t.jsx("video",{src:c.mediaUrl,muted:!0,playsInline:!0,preload:"metadata",onLoadedMetadata:vi}),l[2]=c.mediaUrl,l[3]=f):f=l[3],f}let h;return l[4]===Symbol.for("react.memo_cache_sentinel")?(h=t.jsx(ii,{size:24}),l[4]=h):h=l[4],h}function vi(s){const l=s.currentTarget;l.duration>0&&(l.currentTime=Math.min(.12,l.duration*.15))}function hi(s,l){return s.status==="ready"||s.status==="applying"||s.status==="applied"?s.timelineLimitFrame:Math.max(1,...l.clips.map(x))}function wi({sequence:s,assets:l,audioArtifactId:c,setup:r,returnFocus:h,assembly:f,rhythm:o,address:w,initialFrame:ne=0,onFrameUpdate:U,onExport:P,onPlanDraft:Ye,onApplyDraft:Je,onApplySetup:Qe,onClose:se,onCommit:et,onCreateTrack:tt,onRefreshAssets:it,onRestore:Se,onReviewSetup:ke}){const $=d.useRef(null),at=d.useEffectEvent(se),[L,re]=d.useState(r.status!=="timeline"),[nt,Ie]=d.useState(34),[le,Ce]=d.useState({mode:"beats",fallback:"off"}),[st,we]=d.useState(!1),M=d.useRef(null),Ne=d.useRef(null),Me=d.useRef(null),[F,rt]=d.useState(ne),Fe=d.useCallback(e=>{rt(e),U(e)},[U]),[u,oe]=d.useState(null),[ce,lt]=d.useState(""),[C,q]=d.useState([]),ot=f.selectedClipId,N=f.selectClip,[Ee,E]=d.useState(null),[b,g]=d.useState(null),[Re,p]=d.useState(null),[de,V]=d.useState([]),[ue,W]=d.useState([]),[me,T]=d.useState(null),[G,H]=d.useState(()=>Ut(r.status)),O=l.find(e=>e.artifactId===(o.master?.source.artifactId??c)),S=[...s.tracks].sort((e,i)=>e.ordinal-i.ordinal).find(e=>e.kind==="video")??null,y=oi(s,S?.trackId??null),a=y.find(e=>e.clipId===ot)??null,X=d.useMemo(()=>new Map(l.map(e=>[e.artifactId,e])),[l]),Z=me?X.get(me):void 0,ct=d.useMemo(()=>l.flatMap(e=>e.mediaUrl?[{artifactId:e.artifactId,mediaUrl:e.mediaUrl}]:[]),[l]),pe=d.useMemo(()=>{const e=ce.trim().toLowerCase();return l.filter(i=>(i.type==="video"||i.type==="final")&&i.status==="ready"&&i.mediaUrl&&(!e||i.label.toLowerCase().includes(e)||i.artifactId.toLowerCase().includes(e)))},[l,ce]),v=o.master?o.master.timelineStartFrame+o.master.durationFrames:hi(r,s),j=s.frameRate.numerator/s.frameRate.denominator,fe=Math.max(0,...y.map(x)),Be=Math.max(0,fe-v),be=(r.status==="ready"||r.status==="applied"||r.status==="timeline")&&S!==null&&S.enabled&&!S.locked,_=a?Ee?.clipId===a.clipId?Ee:{clipId:a.clipId,startFrame:a.timelineStartFrame,endFrame:x(a)}:null,ve=a?X.get(a.source.artifactId):void 0,Te=a?pi(a,ve,j):{before:0,after:0},Y=a?y.findIndex(e=>e.clipId===a.clipId):-1,he=a?mi(y,a)?.timelineStartFrame??v:v,Ae=a?Ze(a,y,v):{left:0,right:0},dt=Y>0,ut=Y>=0&&Y<y.length-1,mt=dt||Ae.left>0,pt=ut||Ae.right>0,ft=!!(a&&he>x(a)),De=a?Math.max(0,a.timelineStartFrame-Te.before):0,ze=a?Math.min(v,x(a)+Te.after):v,J=ci(a),bt=ie.some(e=>e.value===J)?[...ie]:[{label:ui(J),value:J},...ie],Le=li(o.mapped,F),R=o.mapped.length>0,A=o.mapped.some(e=>e.bar),vt=o.analysis?.barSource==="estimated"&&!o.rhythm.settings.correction,K=o.status==="queued"||o.status==="analyzing",xe=le.mode==="bars"&&!A?le.fallback:le.mode,B=xe==="beats"&&!R||xe==="bars"&&!A?"off":xe,_e=[{value:"off",label:"Off"},{value:"beats",label:"Beats",disabled:!R,title:R?"Snap edits to beats":"Analyze beats or set a beat grid first"},{value:"bars",label:"Bars",disabled:!R,title:A?"Snap edits to bar starts":"Set up bar starts to enable bar snapping"}];function Q(e="beats"){N(null),re(!0),H("music"),e==="beats"&&we(!!o.master),Ce({mode:e,fallback:B}),e==="bars"&&requestAnimationFrame(()=>{const i=$.current?.querySelector('input[name="beats-per-bar"]');i?.focus(),i?.scrollIntoView({block:"nearest"})})}function Ue(e){if(e==="bars"&&!A){Q(e);return}Ce({mode:e,fallback:"off"})}d.useEffect(()=>{const e=$.current;e?.showModal(),e?.querySelector(".music-video-close")?.focus();const i=n=>{if(n.isComposing||n.keyCode===229||!(n.target instanceof Element)||n.target.closest("dialog")!==e)return;if(n.key==="Escape"){n.preventDefault(),at();return}if(n.key!=="Tab"||!e)return;const m=ri(e),I=m[0],D=m[m.length-1];n.shiftKey&&document.activeElement===I?(n.preventDefault(),D?.focus()):!n.shiftKey&&document.activeElement===D&&(n.preventDefault(),I?.focus())};return document.addEventListener("keydown",i),()=>{document.removeEventListener("keydown",i),e?.close(),Pt(h)}},[h]);const k=async(e,i)=>{if(b||u)return!1;if(!S)return p("Create a main video track before editing clips"),!1;if(r.status!=="ready"&&r.status!=="applied"&&r.status!=="timeline")return p("Wait for the soundtrack duration before editing clips"),!1;g(e),p(null);try{const n=await et(i,s);return V(m=>[...m,{beforeRevision:n.beforeRevision,afterRevision:n.sequence.revision}]),W([]),E(null),!0}catch(n){return p(n instanceof Error?n.message:String(n)),!1}finally{g(null)}},ee=e=>{const i=Math.max(0,Math.min(Math.max(v,...s.clips.map(x))-1,Math.round(e)));T(null),Fe(i),M.current?.seekTo(i)},ht=e=>{T(null),N(e.clipId),s.tracks.find(i=>i.trackId===e.trackId)?.kind==="audio"&&H("music"),E({clipId:e.clipId,startFrame:e.timelineStartFrame,endFrame:x(e)}),ee(e.timelineStartFrame)},xt=e=>{T(e),N(null),q(i=>i.includes(e)?i.filter(n=>n!==e):[...i,e])},gt=async()=>{!S||C.length===0||!await k("Adding clips",{kind:"append_clips",track_id:S.trackId,artifact_ids:C,timeline_limit_frame:o.master?v:Math.max(v,fe+C.reduce((i,n)=>i+Math.ceil((X.get(n)?.duration??0)*j),0)),fit:"source",visual_fit:"fit"})||(q([]),T(null))},jt=async e=>{S&&await k("Reordering clips",{kind:"reorder_clips",track_id:S.trackId,clip_ids:e,timeline_limit_frame:v})},yt=async e=>{if(!a||!S)return;const i=y.findIndex(z=>z.clipId===a.clipId),n=i+e;if(n>=0&&n<y.length){const z=y.map(zt=>zt.clipId),[Oe]=z.splice(i,1);if(!Oe)return;z.splice(n,0,Oe),await jt(z);return}const m=Ze(a,y,v),I=Math.max(1,Math.round(j)),D=e<0?-Math.min(I,m.left):Math.min(I,m.right);D!==0&&await k("Moving clip",{kind:"move",clip_id:a.clipId,track_id:S.trackId,timeline_start_frame:a.timelineStartFrame+D})},St=async()=>{if(!a||he<=x(a))return;const e=he-a.timelineStartFrame;if(a.source.kind!=="timed"){await k("Stretching clip",{kind:"trim",clip_id:a.clipId,timeline_start_frame:a.timelineStartFrame,duration_frames:e,edge:"end",ripple:!1,timeline_limit_frame:v});return}const i=a,n=di(a,j);await k("Stretching clip",{kind:"speed",clip_id:a.clipId,numerator:n,denominator:e,reverse:i.reverse,audio_policy:"mute",ripple:!1,timeline_limit_frame:v})},te=async(e,i,n)=>{if(!(!a||n<=i)&&!(i===a.timelineStartFrame&&n===x(a))){if(B!=="off"&&(e==="start"?i=ye(i,o.mapped,B):n=ye(n,o.mapped,B)),n<=i){p("Choose distinct beat boundaries or turn snapping off");return}await k("Trimming clip",{kind:"trim",clip_id:a.clipId,timeline_start_frame:i,duration_frames:n-i,edge:e,ripple:!1,timeline_limit_frame:v})}},ge=async()=>{if(!a||F<=a.timelineStartFrame||F>=x(a)){p("Place the playhead inside the selected clip before cutting");return}const e=ye(F,o.mapped,B);if(e<=a.timelineStartFrame||e>=x(a)){p("Choose a beat inside the selected clip, or turn snapping off");return}await k("Cutting clip",{kind:"split",clip_id:a.clipId,split_frame:e}),N(null)},Pe=async()=>{a&&(await k("Deleting clip",{kind:"delete",clip_id:a.clipId,ripple:!1}),N(null))},kt=async e=>{if(!a||a.source.kind!=="timed")return;const i=ie.find(z=>z.value===e),[n,m]=e.split("/").map(Number),I=i??(n&&m?{numerator:n,denominator:m}:null);if(!I)return;const D=a;await k("Retiming clip",{kind:"speed",clip_id:a.clipId,numerator:I.numerator,denominator:I.denominator,reverse:D.reverse,audio_policy:"mute",ripple:!1,timeline_limit_frame:v})},$e=async()=>{const e=de[de.length-1];if(!(!e||b)){g("Undoing edit"),p(null);try{await Se(e.beforeRevision,s.revision),V(i=>i.slice(0,-1)),W(i=>[...i,e]),N(null),E(null)}catch(i){p(i instanceof Error?i.message:String(i))}finally{g(null)}}},He=async()=>{const e=ue[ue.length-1];if(!(!e||b)){g("Redoing edit"),p(null);try{await Se(e.afterRevision,s.revision),W(i=>i.slice(0,-1)),V(i=>[...i,e]),N(null),E(null)}catch(i){p(i instanceof Error?i.message:String(i))}finally{g(null)}}},It=(e,i)=>{if(e==="split"&&ge(),e==="delete"&&Pe(),e==="undo"&&$e(),e==="redo"&&He(),e==="search"&&(re(!0),H("media"),requestAnimationFrame(()=>Ne.current?.focus())),e==="zoom-in"&&$.current?.querySelector('[aria-label="Zoom timeline in"]')?.click(),e==="zoom-out"&&$.current?.querySelector('[aria-label="Zoom timeline out"]')?.click(),e==="mark-in"&&a){const n=_?.endFrame??x(a);i<n&&(E({clipId:a.clipId,startFrame:i,endFrame:n}),te("start",i,n))}if(e==="mark-out"&&a){const n=_?.startFrame??a.timelineStartFrame;i>n&&(E({clipId:a.clipId,startFrame:n,endFrame:i}),te("end",n,i))}},Ct=async()=>{if(!(r.status!=="ready"||b)){g("Applying soundtrack"),p(null);try{await Qe()}catch(e){p(e instanceof Error?e.message:String(e))}finally{g(null)}}},wt=async e=>{if(!b){g("Creating soundtrack track"),p(null);try{const i=await tt(e);e==="audio"&&await ke(i)}catch(i){p(i instanceof Error?i.message:String(i))}finally{g(null)}}},Nt=e=>{if(e.defaultPrevented||e.nativeEvent.isComposing||e.nativeEvent.keyCode===229||e.target.closest('input, textarea, select, [contenteditable="true"], .canonical-player'))return;if(M.current){M.current.handleKeyDown(e);return}const n=Me.current,m=e.key.toLowerCase();!n||m!==" "&&m!=="k"||(e.preventDefault(),n.paused?n.play().catch(()=>{}):n.pause())},Mt=async e=>{if(!b){g("Planning draft"),p(null),M.current?.pause();try{const i=await Ye(e,s);oe(i),T(null),ee(e.start_frame)}catch(i){p(i instanceof Error?i.message:String(i))}finally{g(null)}}},Ft=async()=>{if(!(!u||b||u.uncovered.length)){g("Applying draft"),p(null),M.current?.pause();try{const e=await Je(u);V(i=>[...i,{beforeRevision:e.beforeRevision,afterRevision:e.sequence.revision}]),W([]),oe(null),N(null)}catch(e){p(e instanceof Error?e.message:String(e))}finally{g(null)}}},je=!be||!!b||!!u,Et=e=>{if(e.button!==0)return;const i=e.currentTarget;i.setPointerCapture(e.pointerId);const n=I=>{Ie(Xe((window.innerHeight-I.clientY)/window.innerHeight*100))},m=()=>{i.removeEventListener("pointermove",n),i.removeEventListener("pointerup",m),i.removeEventListener("pointercancel",m)};i.addEventListener("pointermove",n),i.addEventListener("pointerup",m),i.addEventListener("pointercancel",m)},Rt=e=>{const i=e.key==="ArrowUp"?2:e.key==="ArrowDown"?-2:0;i&&(e.preventDefault(),e.stopPropagation(),Ie(n=>Xe(n+i)))},Bt=()=>{M.current?.pause(),oe(null)},Tt=C.flatMap(e=>{const i=X.get(e);return i?[i]:[]}),At=A?vt?` · Estimated ${o.analysis?.beatsPerBar}-beat bars`:"":" · Bars not set",Dt=K?"Analyzing beats…":R?`${o.mapped.length} beats${o.analysis?.lowConfidence&&!o.rhythm.settings.correction?" · Review timing":""}${At}`:o.status==="no-beats"?"Analysis complete · No reliable beats found · Set a beat grid":o.master?"Analyze the soundtrack to enable snapping":"Choose a soundtrack for snapping";return Lt.createPortal(t.jsxs("dialog",{className:"music-video-editor timeline-preview-fullscreen","aria-label":w?`Timeline preview ${w}`:"Music video editor",style:{"--music-timeline-height":`${nt}dvh`},onCancel:e=>{e.preventDefault(),se()},ref:$,tabIndex:-1,onKeyDown:Nt,children:[t.jsxs("header",{className:"music-video-editor-header",children:[t.jsx("button",{className:"music-video-close mv-icon",type:"button",onClick:se,"aria-label":w?"Close timeline preview":"Close music video editor",children:t.jsx(Gt,{size:20})}),t.jsxs("div",{className:"music-video-title",children:[t.jsxs("h1",{children:[w?t.jsxs(t.Fragment,{children:["Timeline ",t.jsx("code",{children:w})]}):O?.label??"Music video",u&&t.jsx("span",{className:"mv-draft-badge",children:"Draft preview"})]}),t.jsxs("p",{children:[s.width,"×",s.height," · ",parseFloat(j.toFixed(2))," fps · ",ae(v,j)]})]}),t.jsxs("div",{className:"music-video-header-actions",children:[t.jsxs("button",{type:"button",className:"mv-quiet mv-tools-toggle","aria-pressed":L,"aria-label":L?"Hide tools":"Show tools",onClick:()=>re(e=>!e),children:[t.jsx(Xt,{size:16})," ",t.jsx("span",{children:L?"Hide tools":"Show tools"})]}),u?t.jsxs(t.Fragment,{children:[t.jsx("span",{className:"mv-draft-note",children:"Nothing changes until you apply."}),t.jsx("button",{type:"button",disabled:!!b,onClick:Bt,children:"Discard draft"}),t.jsxs("button",{type:"button",className:"mv-apply",disabled:!!b||u.uncovered.length>0,onClick:()=>{Ft()},children:[t.jsx(qe,{size:16})," Apply draft"]})]}):t.jsxs(t.Fragment,{children:[t.jsxs("button",{type:"button",className:"mv-quiet",disabled:!!b||de.length===0,onClick:()=>{$e()},children:[t.jsx(Zt,{size:16})," Undo"]}),t.jsxs("button",{type:"button",className:"mv-quiet",disabled:!!b||ue.length===0,onClick:()=>{He()},children:[t.jsx(Yt,{size:16})," Redo"]}),t.jsxs("button",{type:"button",className:"mv-primary",onClick:P,children:[t.jsx(Jt,{size:16})," Export"]})]})]})]}),t.jsxs("main",{className:["music-video-editor-main",L?"":"tools-hidden",a||u?"inspecting":""].filter(Boolean).join(" "),children:[t.jsxs("aside",{className:"music-video-library","aria-label":"Library",hidden:!L,children:[t.jsx("div",{className:"music-video-library-tabs",role:"tablist","aria-label":"Library views",children:ai.map(e=>t.jsx("button",{type:"button",role:"tab",id:`mv-tab-${e.value}`,"aria-controls":`mv-panel-${e.value}`,"aria-selected":G===e.value,onClick:()=>H(e.value),children:e.label},e.value))}),t.jsxs("section",{className:"music-video-source-panel",role:"tabpanel",id:"mv-panel-media","aria-labelledby":"mv-tab-media",hidden:G!=="media",children:[t.jsxs("div",{className:"mv-panel-head",children:[t.jsxs("label",{className:"music-video-search",children:[t.jsx(Qt,{size:15}),t.jsx("input",{ref:Ne,value:ce,onChange:e=>lt(e.target.value),placeholder:"Search this book","aria-label":"Search source clips"})]}),t.jsx("button",{type:"button",className:"mv-icon","aria-label":"Refresh media",title:"Refresh media",onClick:()=>{it().catch(e=>p(String(e)))},children:t.jsx(Ve,{size:15})})]}),t.jsxs("div",{className:"mv-panel-meta",children:[t.jsxs("span",{children:[C.length," of ",pe.length," selected"]}),C.length>0&&t.jsx("button",{type:"button",className:"mv-link",onClick:()=>q([]),children:"Clear"})]}),t.jsxs("div",{className:"music-video-source-list",children:[pe.map(e=>{const i=C.indexOf(e.artifactId),n=me===e.artifactId;return t.jsxs("button",{type:"button",className:[i>=0?"selected":"",n?"previewing":""].filter(Boolean).join(" "),"aria-pressed":i>=0,"aria-label":e.label,onClick:()=>xt(e.artifactId),children:[t.jsxs("span",{className:"music-video-source-thumb",children:[t.jsx(bi,{asset:e}),i>=0&&t.jsx("i",{children:i+1}),e.duration!==null&&t.jsx("small",{children:ae(Math.round(e.duration*j),j)})]}),t.jsx("span",{className:"music-video-source-name",title:e.label,children:e.label})]},e.artifactId)}),pe.length===0&&t.jsx("p",{children:"No ready video sources match this search."})]}),t.jsxs("footer",{className:"mv-panel-foot",children:[t.jsxs("button",{type:"button",className:"mv-primary music-video-add-selected",disabled:je||C.length===0,onClick:()=>{gt()},children:[t.jsx(We,{size:15})," Add ",C.length||""," to end"]}),t.jsxs("button",{type:"button",disabled:C.length===0,onClick:()=>H("autocut"),children:[t.jsx(ei,{size:15})," Auto-cut…"]})]})]}),t.jsxs("section",{className:"mv-music-panel",role:"tabpanel",id:"mv-panel-music","aria-labelledby":"mv-tab-music",hidden:G!=="music",children:[t.jsxs("div",{className:"music-video-setup-card","data-status":r.status,children:[t.jsxs("span",{className:"mv-kicker",children:[t.jsx(Ge,{size:13})," Soundtrack",O?` · ${O.label}`:""]}),r.status==="loading"&&t.jsx("p",{children:"Building the exact canonical setup plan…"}),r.status==="needs-audio-track"&&t.jsxs(t.Fragment,{children:[t.jsx("p",{children:r.message}),t.jsxs("button",{type:"button",className:"mv-primary",disabled:!!b,onClick:()=>{wt("audio")},children:[t.jsx(We,{size:15})," Create soundtrack track"]})]}),(r.status==="ready"||r.status==="applying")&&t.jsxs(t.Fragment,{children:[t.jsx("strong",{children:r.summary}),t.jsxs("p",{children:[r.operationCount," atomic operations · ends at ",ae(r.timelineLimitFrame,j)]}),r.warnings.map(e=>t.jsx("small",{children:e},e)),t.jsxs("button",{type:"button",className:"mv-primary",disabled:!!b,onClick:()=>{Ct()},children:[t.jsx(Ge,{size:15})," Apply soundtrack"]})]}),r.status==="applied"&&t.jsxs("strong",{className:"music-video-applied",children:[t.jsx(qe,{size:15})," Soundtrack applied"]}),r.status==="error"&&t.jsxs(t.Fragment,{children:[t.jsx("p",{className:"music-video-error",children:r.message}),t.jsxs("button",{type:"button",disabled:!!b,onClick:()=>{ke()},children:[t.jsx(Ve,{size:15})," Review again"]})]})]}),t.jsxs("div",{className:"mv-control",children:[t.jsx("span",{children:"Snap edits to"}),t.jsx(Ke,{label:"Snap to music",options:_e,value:B,onChange:Ue}),t.jsx("p",{className:"mv-hint",children:"Hold Alt while dragging to ignore snapping."})]}),t.jsx(Ht,{rhythm:o,sequence:s,assets:l,frame:F,correctionsOpen:st,onCorrectionsOpenChange:we})]}),t.jsx("section",{className:"mv-autocut-panel",role:"tabpanel",id:"mv-panel-autocut","aria-labelledby":"mv-tab-autocut",hidden:G!=="autocut",children:t.jsx(Ot,{sources:Tt,trackId:S?.trackId??null,startFrame:o.master?.timelineStartFrame??0,endFrame:v,fps:j,hasBars:A,busy:!!b,draft:u,onPlan:e=>{Mt(e)},onOrder:q})})]}),t.jsxs("section",{className:"music-video-preview-panel timeline-preview-body","aria-label":"Program monitor",children:[t.jsx("div",{className:"mv-monitor",children:Z?.mediaUrl?t.jsxs("div",{className:"music-video-source-preview",children:[t.jsx("video",{ref:Me,src:Z.mediaUrl,controls:!0,autoPlay:!0,muted:!0,playsInline:!0},Z.artifactId),t.jsxs("p",{children:[t.jsxs("span",{children:["Source · ",Z.label]}),t.jsx("button",{type:"button",onClick:()=>T(null),children:"Show sequence"})]})]}):t.jsx(Kt,{ref:M,sequence:u?.sequence??s,assets:ct,onFrameUpdate:Fe,initialFrame:F,presentation:"preview",allowFullscreen:!1,editingEnabled:!u,onKeyboardAction:It})}),t.jsx(qt,{frame:F,durationFrames:Math.max(v,fe),fps:j,previousBeat:Le.previous,nextBeat:Le.next,onTogglePlay:()=>{T(null),M.current?.togglePlay()},onSeek:ee})]}),t.jsxs("aside",{className:"music-video-inspector","aria-label":"Inspector",hidden:!L,children:[a&&!u&&t.jsx("button",{type:"button",className:"mv-link mv-back",onClick:()=>N(null),children:"← Back to library"}),u?t.jsxs("div",{className:"mv-draft-summary",children:[t.jsx("span",{className:"mv-kicker",children:"Draft review"}),t.jsx("strong",{children:u.plan.summary}),t.jsxs("p",{children:[u.shots.length," shots · replaces ",u.preview.diff.removedClipIds.length," clips"]}),u.uncovered.length>0&&t.jsx("p",{className:"music-video-error",children:"Gaps remain, so the draft can't be applied. Allow repeated footage or add sources in Auto-cut."}),u.warnings.map(e=>t.jsx("small",{children:e},e)),t.jsx("p",{className:"mv-hint",children:"The full shot list is in Auto-cut."})]}):a&&_?t.jsx(Vt,{clip:a,label:ve?.label??"Clip",thumbnailUrl:ve?.thumbnailUrl??null,index:Y+1,count:y.length,fps:j,trimStart:_.startFrame,trimEnd:_.endFrame,trimMin:De,trimMax:Math.max(_.endFrame,ze),speed:J,speedOptions:bt,retimable:a.source.kind==="timed",busy:!!b,editsDisabled:je,canMoveEarlier:mt,canMoveLater:pt,canStretch:ft,onTrim:(e,i,n)=>{E({clipId:a.clipId,startFrame:i,endFrame:n}),te(e,i,n)},onSpeed:e=>{kt(e)},onFit:e=>{k("Fitting clip",{kind:"transform",clip_id:a.clipId,fit:e})},onSplit:()=>{ge()},onStretch:()=>{St()},onMove:e=>{yt(e)},onDelete:()=>{Pe()}}):t.jsxs("div",{className:"mv-sequence-summary",children:[t.jsx("span",{className:"mv-kicker",children:"Sequence"}),t.jsxs("dl",{children:[t.jsx("dt",{children:"Frame"}),t.jsxs("dd",{children:[s.width," × ",s.height]}),t.jsx("dt",{children:"Rate"}),t.jsxs("dd",{children:[parseFloat(j.toFixed(2))," fps"]}),t.jsx("dt",{children:"Length"}),t.jsx("dd",{children:ae(v,j)}),t.jsx("dt",{children:"Clips"}),t.jsx("dd",{children:y.length})]}),y.length>0?t.jsx("p",{children:"Select a clip on the timeline to trim, retime or delete it."}):t.jsxs("ol",{className:"mv-steps",children:[t.jsx("li",{children:"Pick footage in Media"}),t.jsx("li",{children:"Choose a soundtrack in Music"}),t.jsx("li",{children:"Auto-cut, or add clips and trim by hand"})]})]})]}),t.jsxs("section",{className:"music-video-timeline-panel","aria-label":"Music video timeline",children:[t.jsx("button",{type:"button",className:"mv-resize-handle","aria-label":"Resize timeline",title:"Drag to resize the timeline (↑/↓)",onPointerDown:Et,onKeyDown:Rt}),t.jsx(Wt,{sequence:u?.sequence??s,assets:l,assembly:f,disabled:!!b||!!u,frame:F,address:w??"",onSeek:ee,onSelectClip:ht,onExport:P,presentation:"preview",onMoveClip:be?(e,i)=>{k("Moving clip",{kind:"move",clip_id:e.clipId,track_id:e.trackId,timeline_start_frame:i})}:void 0,onRemoveClip:e=>{k("Removing clip",{kind:"remove_clip",clip_id:e.clipId,ripple:!1})},onTrimClip:be?(e,i,n,m)=>{e.clipId===a?.clipId&&(E({clipId:e.clipId,startFrame:n,endFrame:m}),te(i,n,m))}:void 0,trimBounds:a?{min:De,max:Math.max(x(a),ze)}:void 0,rhythm:{masterClipId:o.master?.clipId??null,markers:o.mapped,analysis:o.analysis,snap:B},toolbar:t.jsxs(t.Fragment,{children:[t.jsx("span",{children:"Snap"}),t.jsx(Ke,{label:"Snap to music",options:_e,value:B,onChange:Ue}),!o.master&&t.jsx("button",{type:"button",disabled:o.busy,onClick:()=>Q(),children:"Choose soundtrack"}),o.master&&!R&&!K&&t.jsx("button",{type:"button",disabled:o.busy,onClick:()=>{o.analyze(!!o.analysis)},children:o.analysis?"Analyze again":"Analyze beats"}),K&&t.jsx("button",{type:"button",disabled:o.busy,onClick:()=>{o.cancel()},children:"Cancel analysis"}),o.master&&!R&&o.analysis&&!K&&t.jsx("button",{type:"button",disabled:o.busy,onClick:()=>Q(),children:"Set beat grid"}),R&&!A&&t.jsx("button",{type:"button",disabled:o.busy||K,onClick:()=>Q("bars"),children:"Set bars"}),t.jsxs("button",{type:"button",disabled:je||!a,title:"Split the selected clip at the playhead (S)",onClick:()=>{ge()},children:[t.jsx(ti,{size:14})," Split"]}),o.master&&t.jsxs("span",{className:"music-master-name",title:O?.label,children:["♪ ",O?.label??"Soundtrack"]}),t.jsx("span",{role:"status",children:Dt})]})}),Be>0&&t.jsxs("p",{children:[Be," frames beyond soundtrack"]})]})]}),t.jsxs("footer",{className:"music-video-status","aria-live":"polite",children:[t.jsx("span",{children:b??(u?"Draft ready · review it, then apply or discard":"Saved")}),(Re||o.error)&&t.jsx("strong",{role:"alert",children:Re||o.error}),t.jsx("span",{className:"mv-shortcuts",children:"Space play · J/L shuttle · ←/→ frame · I/O trim · S split · Delete · ⌘Z undo"})]})]}),document.body)}export{wi as MusicVideoEditor};