timeline-canvas 1.0.9 → 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (35) hide show
  1. package/dist/{ContextMenuPlugin-B9TmnnaU.mjs → ContextMenuPlugin-6qe5xYCu.mjs} +1 -1
  2. package/dist/{ContextMenuPlugin-Crk3ma0O.d.mts → ContextMenuPlugin-D-SJ3frM.d.mts} +1 -1
  3. package/dist/{DarkThemePlugin-CRFdrOR3.mjs → DarkThemePlugin-GyV1mhmz.mjs} +1 -1
  4. package/dist/{DarkThemePlugin-IbJNx65n.d.mts → DarkThemePlugin-Ov8yWWT7.d.mts} +1 -1
  5. package/dist/{EventMediaPlugin-DPPdLbey.mjs → EventMediaPlugin-CawS6c0q.mjs} +1 -1
  6. package/dist/{EventMediaPlugin-daiUXxsT.d.mts → EventMediaPlugin-DNFZmJz5.d.mts} +1 -1
  7. package/dist/{EventTooltipPlugin-b5fqBb8j.d.mts → EventTooltipPlugin-BPx9AZt8.d.mts} +1 -1
  8. package/dist/EventTooltipPlugin-DNGXHYbN.mjs +1 -0
  9. package/dist/{LightThemePlugin-DrdhIHgA.d.mts → LightThemePlugin-Dw40Vr7u.d.mts} +1 -1
  10. package/dist/{LightThemePlugin-BOreTGti.mjs → LightThemePlugin-wHpjmbXj.mjs} +1 -1
  11. package/dist/{PerformanceOverlayPlugin-BFU4Le2k.d.mts → PerformanceOverlayPlugin-C6wYxsQg.d.mts} +1 -1
  12. package/dist/PerformanceOverlayPlugin-DlYhPYO-.mjs +1 -0
  13. package/dist/builtin-plugin/ContextMenuPlugin.d.mts +2 -2
  14. package/dist/builtin-plugin/ContextMenuPlugin.mjs +1 -1
  15. package/dist/builtin-plugin/DarkThemePlugin.d.mts +2 -2
  16. package/dist/builtin-plugin/DarkThemePlugin.mjs +1 -1
  17. package/dist/builtin-plugin/EventMediaPlugin.d.mts +2 -2
  18. package/dist/builtin-plugin/EventMediaPlugin.mjs +1 -1
  19. package/dist/builtin-plugin/EventTooltipPlugin.d.mts +2 -2
  20. package/dist/builtin-plugin/EventTooltipPlugin.mjs +1 -1
  21. package/dist/builtin-plugin/LightThemePlugin.d.mts +2 -2
  22. package/dist/builtin-plugin/LightThemePlugin.mjs +1 -1
  23. package/dist/builtin-plugin/MutexGuardPlugin.d.mts +1 -1
  24. package/dist/builtin-plugin/MutexGuardPlugin.mjs +1 -1
  25. package/dist/builtin-plugin/PerformanceOverlayPlugin.d.mts +2 -2
  26. package/dist/builtin-plugin/PerformanceOverlayPlugin.mjs +1 -1
  27. package/dist/index.d.mts +8 -8
  28. package/dist/index.mjs +1 -1
  29. package/dist/{types-D5-4YwEP.d.mts → types-pL-YHm8m.d.mts} +45 -4
  30. package/package.json +47 -50
  31. package/dist/EventTooltipPlugin-Ce6xChyf.mjs +0 -1
  32. package/dist/PerformanceOverlayPlugin-Bx-DkYbW.mjs +0 -1
  33. /package/dist/{Logger-Bwd6lZLT.mjs → Logger-CfVK3yFL.mjs} +0 -0
  34. /package/dist/{performanceMonitor-Cf-Ah4F7.mjs → performanceMonitor-BBherdD8.mjs} +0 -0
  35. /package/dist/{types-CkHQNcJ5.mjs → types-BvVk5Y9C.mjs} +0 -0
@@ -1 +1 @@
1
- import{i as e}from"./Logger-Bwd6lZLT.mjs";import{t}from"./types-CkHQNcJ5.mjs";const n=e(`ContextMenuPlugin`);function r(e={}){return{metadata:{name:`context-menu`,version:`1.0.0`,description:`Context menu as plugin, supports HTML takeover`,type:t.EXTENSION},activate(t){let r=t.config&&t.config.contextMenuHtml||void 0,i=e.htmlTemplate||(typeof r==`string`?r:void 0),a=!!i;a&&(!i||i.trim()===``)&&(n.warn(`htmlTemplate is empty, falling back to Canvas rendering`),a=!1),t.api.registerRenderLayer({name:`context-menu-overlay`,position:`overlay`,render(e,n,r,o){if(!r.enableContextMenu||!o.contextMenuVisible||!o.contextMenuEvent){let e=t.api.getData(`contextMenuContainer`)||null;e&&(e.style.display=`none`),o.contextMenuBounds=null;return}let{padding:s,itemHeight:c,borderRadius:l,borderWidth:u,minWidth:d,fontSize:f,fontFamily:p,fontWeight:m}=r.contextMenuStyle;e.save(),e.font=`${m} ${f}px ${p}`;let h=d,g=`${m}-${f}-${p}`,_=t.api.getData(`contextMenuTextWidthCache`)||{},v=_[g]||{};for(let t of r.contextMenuItems){let n=v[t.name],r=n===void 0?e.measureText(t.name).width:n;n===void 0&&(v[t.name]=r),h=Math.max(h,r+s*2)}_[g]=v,t.api.setData(`contextMenuTextWidthCache`,_);let y=h,b=r.contextMenuItems.length*c+s*2,x=t.timeline.getCanvas().getBoundingClientRect(),S=o.contextMenuX,C=o.contextMenuY;if(S+y>x.width&&(S=x.width-y-5),C+b>x.height&&(C=x.height-b-5),o.contextMenuBounds={x:S,y:C,width:y,height:b,itemHeight:c,padding:s},a){let n=t.api.getData(`contextMenuContainer`)||null;if(!n){n=document.createElement(`div`),n.style.position=`absolute`,n.style.zIndex=`1000`,n.style.boxShadow=`0 2px 10px rgba(0,0,0,0.3)`,n.style.border=`${u}px solid ${r.colors.contextMenuBorder}`,n.style.borderRadius=`${l}px`,n.style.font=`${m} ${f}px ${p}`,n.style.background=r.colors.contextMenuBackground,n.style.color=r.colors.contextMenuText;let e=t.timeline.getCanvas().parentElement||document.body;e.style.position=e.style.position||`relative`,e.appendChild(n),t.api.setData(`contextMenuContainer`,n)}if(n.style.display=`block`,n.style.left=`${S}px`,n.style.top=`${C}px`,n.style.width=`${y}px`,n.style.height=`${b}px`,i)n.innerHTML=i;else{let e=``;for(let t=0;t<r.contextMenuItems.length;t++){let n=r.contextMenuItems[t],i=o.hoveredContextMenuItem===t,a=i?r.colors.contextMenuHoverBackground:`transparent`,l=i?r.colors.contextMenuHoverText:r.colors.contextMenuText;e+=`<div style="height:${c}px; padding:${s}px; background:${a}; color:${l}; display:flex; align-items:center;">${n.name}</div>`}n.innerHTML=e}e.restore();return}e.shadowColor=`rgba(0, 0, 0, 0.3)`,e.shadowBlur=10,e.shadowOffsetX=0,e.shadowOffsetY=2,e.fillStyle=r.colors.contextMenuBackground,e.beginPath(),e.roundRect?e.roundRect(S,C,y,b,l):(e.moveTo(S+l,C),e.lineTo(S+y-l,C),e.quadraticCurveTo(S+y,C,S+y,C+l),e.lineTo(S+y,C+b-l),e.quadraticCurveTo(S+y,C+b,S+y-l,C+b),e.lineTo(S+l,C+b),e.quadraticCurveTo(S,C+b,S,C+b-l),e.lineTo(S,C+l),e.quadraticCurveTo(S,C,S+l,C)),e.fill(),e.shadowColor=`transparent`,e.strokeStyle=r.colors.contextMenuBorder,e.lineWidth=u,e.stroke(),e.font=`${m} ${f}px ${p}`;for(let t=0;t<r.contextMenuItems.length;t++){let n=r.contextMenuItems[t],i=C+s+t*c;o.hoveredContextMenuItem===t&&(e.fillStyle=r.colors.contextMenuHoverBackground,e.beginPath(),t===0?e.roundRect?e.roundRect(S+u,i,y-u*2,c,[l-u,l-u,0,0]):e.fillRect(S+u,i,y-u*2,c):t===r.contextMenuItems.length-1&&e.roundRect?e.roundRect(S+u,i,y-u*2,c,[0,0,l-u,l-u]):e.fillRect(S+u,i,y-u*2,c),e.fill()),e.fillStyle=o.hoveredContextMenuItem===t?r.colors.contextMenuHoverText:r.colors.contextMenuText,e.textAlign=`left`,e.textBaseline=`middle`,e.fillText(n.name,S+s,i+c/2)}e.restore()}})},deactivate(e){e.api.unregisterRenderLayer(`context-menu-overlay`);let t=e.api.getData(`contextMenuContainer`)||null;t&&t.parentElement&&t.parentElement.removeChild(t)},destroy(e){let t=e.api.getData(`contextMenuContainer`)||null;t&&t.parentElement&&t.parentElement.removeChild(t)}}}export{r as t};
1
+ import{i as e}from"./Logger-CfVK3yFL.mjs";import{t}from"./types-BvVk5Y9C.mjs";const n=e(`ContextMenuPlugin`);function r(e={}){return{metadata:{name:`context-menu`,version:`1.0.0`,description:`Context menu as plugin, supports HTML takeover`,type:t.EXTENSION},activate(t){let r=t.config&&t.config.contextMenuHtml||void 0,i=e.htmlTemplate||(typeof r==`string`?r:void 0),a=!!i;a&&(!i||i.trim()===``)&&(n.warn(`htmlTemplate is empty, falling back to Canvas rendering`),a=!1),t.api.registerRenderLayer({name:`context-menu-overlay`,position:`overlay`,render(e,n,r,o){if(!r.enableContextMenu||!o.contextMenuVisible||!o.contextMenuEvent){let e=t.api.getData(`contextMenuContainer`)||null;e&&(e.style.display=`none`),o.contextMenuBounds=null;return}let{padding:s,itemHeight:c,borderRadius:l,borderWidth:u,minWidth:d,fontSize:f,fontFamily:p,fontWeight:m}=r.contextMenuStyle;e.save(),e.font=`${m} ${f}px ${p}`;let h=d,g=`${m}-${f}-${p}`,_=t.api.getData(`contextMenuTextWidthCache`)||{},v=_[g]||{};for(let t of r.contextMenuItems){let n=v[t.name],r=n===void 0?e.measureText(t.name).width:n;n===void 0&&(v[t.name]=r),h=Math.max(h,r+s*2)}_[g]=v,t.api.setData(`contextMenuTextWidthCache`,_);let y=h,b=r.contextMenuItems.length*c+s*2,x=t.timeline.getCanvas().getBoundingClientRect(),S=o.contextMenuX,C=o.contextMenuY;if(S+y>x.width&&(S=x.width-y-5),C+b>x.height&&(C=x.height-b-5),o.contextMenuBounds={x:S,y:C,width:y,height:b,itemHeight:c,padding:s},a){let n=t.api.getData(`contextMenuContainer`)||null;if(!n){n=document.createElement(`div`),n.style.position=`absolute`,n.style.zIndex=`1000`,n.style.boxShadow=`0 2px 10px rgba(0,0,0,0.3)`,n.style.border=`${u}px solid ${r.colors.contextMenuBorder}`,n.style.borderRadius=`${l}px`,n.style.font=`${m} ${f}px ${p}`,n.style.background=r.colors.contextMenuBackground,n.style.color=r.colors.contextMenuText;let e=t.timeline.getCanvas().parentElement||document.body;e.style.position=e.style.position||`relative`,e.appendChild(n),t.api.setData(`contextMenuContainer`,n)}if(n.style.display=`block`,n.style.left=`${S}px`,n.style.top=`${C}px`,n.style.width=`${y}px`,n.style.height=`${b}px`,i)n.innerHTML=i;else{let e=``;for(let t=0;t<r.contextMenuItems.length;t++){let n=r.contextMenuItems[t],i=o.hoveredContextMenuItem===t,a=i?r.colors.contextMenuHoverBackground:`transparent`,l=i?r.colors.contextMenuHoverText:r.colors.contextMenuText;e+=`<div style="height:${c}px; padding:${s}px; background:${a}; color:${l}; display:flex; align-items:center;">${n.name}</div>`}n.innerHTML=e}e.restore();return}e.shadowColor=`rgba(0, 0, 0, 0.3)`,e.shadowBlur=10,e.shadowOffsetX=0,e.shadowOffsetY=2,e.fillStyle=r.colors.contextMenuBackground,e.beginPath(),e.roundRect?e.roundRect(S,C,y,b,l):(e.moveTo(S+l,C),e.lineTo(S+y-l,C),e.quadraticCurveTo(S+y,C,S+y,C+l),e.lineTo(S+y,C+b-l),e.quadraticCurveTo(S+y,C+b,S+y-l,C+b),e.lineTo(S+l,C+b),e.quadraticCurveTo(S,C+b,S,C+b-l),e.lineTo(S,C+l),e.quadraticCurveTo(S,C,S+l,C)),e.fill(),e.shadowColor=`transparent`,e.strokeStyle=r.colors.contextMenuBorder,e.lineWidth=u,e.stroke(),e.font=`${m} ${f}px ${p}`;for(let t=0;t<r.contextMenuItems.length;t++){let n=r.contextMenuItems[t],i=C+s+t*c;o.hoveredContextMenuItem===t&&(e.fillStyle=r.colors.contextMenuHoverBackground,e.beginPath(),t===0?e.roundRect?e.roundRect(S+u,i,y-u*2,c,[l-u,l-u,0,0]):e.fillRect(S+u,i,y-u*2,c):t===r.contextMenuItems.length-1&&e.roundRect?e.roundRect(S+u,i,y-u*2,c,[0,0,l-u,l-u]):e.fillRect(S+u,i,y-u*2,c),e.fill()),e.fillStyle=o.hoveredContextMenuItem===t?r.colors.contextMenuHoverText:r.colors.contextMenuText,e.textAlign=`left`,e.textBaseline=`middle`,e.fillText(n.name,S+s,i+c/2)}e.restore()}})},deactivate(e){e.api.unregisterRenderLayer(`context-menu-overlay`);let t=e.api.getData(`contextMenuContainer`)||null;t&&t.parentElement&&t.parentElement.removeChild(t)},destroy(e){let t=e.api.getData(`contextMenuContainer`)||null;t&&t.parentElement&&t.parentElement.removeChild(t)}}}export{r as t};
@@ -1,4 +1,4 @@
1
- import { t as TimelinePlugin } from "./types-D5-4YwEP.mjs";
1
+ import { t as TimelinePlugin } from "./types-pL-YHm8m.mjs";
2
2
 
3
3
  //#region src/plugins/builtin/ContextMenuPlugin.d.ts
4
4
  interface ContextMenuPluginOptions {
@@ -1 +1 @@
1
- import{t as e}from"./types-CkHQNcJ5.mjs";const t={canvasBackground:`#1E1E2E`,timelineBackground:`#2D2D3D`,trackBackground:`#2A2A3A`,trackBackgroundSelected:`#3A3A4A`,timelineText:`#CCCCDD`,timelineGrid:`#5A5A7A`,timelineSubGrid:`#3A3A4A`,trackText:`#CCCCDD`,eventColors:[`#FF6B6B`,`#4ECDC4`,`#45B7D1`,`#96CEB4`,`#FECA57`,`#FF9FF3`],eventText:`#FFFFFF`,eventBorder:`#FFFFFF`,eventBorderSelected:`#FFD700`,eventOverlay:`rgba(255, 255, 255, 0.2)`,dragPreviewValid:`rgba(100, 255, 100, 0.5)`,dragPreviewInvalid:`rgba(255, 100, 100, 0.5)`,dragPreviewBorderValid:`#00FF00`,dragPreviewBorderInvalid:`#FF0000`,timeIndicator:`#FF6B6B`,guideLine:`#00D9FF`,guideLineLabel:`#00D9FF`,dragTimeReferenceLine:`#FFD700`,dragTimeReferenceLabel:`#FFD700`,dragTimeReferenceLabelBackground:`rgba(0, 0, 0, 0)`,scrollbarTrack:`rgba(255, 255, 255, 0.6)`,scrollbarHandle:`rgba(150, 150, 150, 0.8)`,scrollbarHandleHover:`rgba(0, 0, 0, 0.85)`,scrollbarHandleHighlight:`rgba(255, 255, 255, 0.3)`,scrollbarBorder:`rgba(255, 255, 255, 0.9)`,contextMenuBackground:`#2D2D3D`,contextMenuBorder:`#5A5A7A`,contextMenuText:`#CCCCDD`,contextMenuHoverBackground:`#3A3A4A`,contextMenuHoverText:`#FFFFFF`,eventDurationLabel:`#FFD700`},n={metadata:{name:`theme-dark`,version:`1.0.0`,description:`Dark theme for timeline`,type:e.THEME},activate(e){e.config.colors={...e.config.colors,...t},e.api.registerRenderLayer({name:`theme-dark-background`,position:`background`,render(e,t,n){e.fillStyle=n.colors.canvasBackground,e.fillRect(0,0,t.width,t.height)}})},deactivate(e){e.api.unregisterRenderLayer(`theme-dark-background`)}};export{n as t};
1
+ import{t as e}from"./types-BvVk5Y9C.mjs";const t={canvasBackground:`#1E1E2E`,timelineBackground:`#2D2D3D`,trackBackground:`#2A2A3A`,trackBackgroundSelected:`#3A3A4A`,timelineText:`#CCCCDD`,timelineGrid:`#5A5A7A`,timelineSubGrid:`#3A3A4A`,trackText:`#CCCCDD`,eventColors:[`#FF6B6B`,`#4ECDC4`,`#45B7D1`,`#96CEB4`,`#FECA57`,`#FF9FF3`],eventText:`#FFFFFF`,eventBorder:`#FFFFFF`,eventBorderSelected:`#FFD700`,eventOverlay:`rgba(255, 255, 255, 0.2)`,dragPreviewValid:`rgba(100, 255, 100, 0.5)`,dragPreviewInvalid:`rgba(255, 100, 100, 0.5)`,dragPreviewBorderValid:`#00FF00`,dragPreviewBorderInvalid:`#FF0000`,timeIndicator:`#FF6B6B`,guideLine:`#00D9FF`,guideLineLabel:`#00D9FF`,dragTimeReferenceLine:`#FFD700`,dragTimeReferenceLabel:`#FFD700`,dragTimeReferenceLabelBackground:`rgba(0, 0, 0, 0)`,scrollbarTrack:`rgba(255, 255, 255, 0.6)`,scrollbarHandle:`rgba(150, 150, 150, 0.8)`,scrollbarHandleHover:`rgba(0, 0, 0, 0.85)`,scrollbarHandleHighlight:`rgba(255, 255, 255, 0.3)`,scrollbarBorder:`rgba(255, 255, 255, 0.9)`,contextMenuBackground:`#2D2D3D`,contextMenuBorder:`#5A5A7A`,contextMenuText:`#CCCCDD`,contextMenuHoverBackground:`#3A3A4A`,contextMenuHoverText:`#FFFFFF`,eventDurationLabel:`#FFD700`},n={metadata:{name:`theme-dark`,version:`1.0.0`,description:`Dark theme for timeline`,type:e.THEME},activate(e){e.config.colors={...e.config.colors,...t},e.api.registerRenderLayer({name:`theme-dark-background`,position:`background`,render(e,t,n){e.fillStyle=n.colors.canvasBackground,e.fillRect(0,0,t.width,t.height)}})},deactivate(e){e.api.unregisterRenderLayer(`theme-dark-background`)}};export{n as t};
@@ -1,4 +1,4 @@
1
- import { t as TimelinePlugin } from "./types-D5-4YwEP.mjs";
1
+ import { t as TimelinePlugin } from "./types-pL-YHm8m.mjs";
2
2
 
3
3
  //#region src/plugins/builtin/DarkThemePlugin.d.ts
4
4
  declare const DarkThemePlugin: TimelinePlugin;
@@ -1 +1 @@
1
- import{t as e}from"./types-CkHQNcJ5.mjs";function t(e,t=!0){let n=Math.round(e),r=Math.floor(n/3600),i=Math.floor(n%3600/60),a=n%60;return t?`${r.toString().padStart(2,`0`)}:${i.toString().padStart(2,`0`)}:${a.toString().padStart(2,`0`)}`:`${r.toString().padStart(2,`0`)}:${i.toString().padStart(2,`0`)}`}function n(){let e=new Date;return e.getHours()*3600+e.getMinutes()*60+e.getSeconds()}function r(e,t,n,r){return!n||e<r?t*60:[{threshold:10,seconds:.5},{threshold:8,seconds:1},{threshold:5,seconds:2},{threshold:3,seconds:5},{threshold:2,seconds:10},{threshold:0,seconds:15}].find(t=>e>=t.threshold)?.seconds??15}function i(e,t){return Math.round(e/t)*t}function a(e,t=3){let n=10**t;return Math.round(e*n)/n}function o(e,n){return`${t(e)} - ${t(n)}`}function s(e){return`持续 ${t(a(e))}`}function c(e,t,n,r,i,a,o=!1){e.beginPath(),e.moveTo(t+a,n),e.lineTo(t+r-a,n),e.arcTo(t+r,n,t+r,n+a,a),e.lineTo(t+r,n+i-a),e.arcTo(t+r,n+i,t+r-a,n+i,a),e.lineTo(t+a,n+i),e.arcTo(t,n+i,t,n+i-a,a),e.lineTo(t,n+a),e.arcTo(t,n,t+a,n,a),e.closePath(),o?e.stroke():e.fill()}function l(e,t,n,r,i,a){return n+(e-t)*r*i-a}const u={canvasBackground:`#1E1E2E`,timelineBackground:`#2D2D3D`,trackBackground:`#2A2A3A`,trackBackgroundSelected:`#3A3A4A`,timelineText:`#CCCCDD`,timelineGrid:`#5A5A7A`,timelineSubGrid:`#3A3A4A`,trackText:`#CCCCDD`,eventColors:[`#FF6B6B`,`#4ECDC4`,`#45B7D1`,`#96CEB4`,`#FECA57`,`#FF9FF3`],eventText:`#FFFFFF`,eventBorder:`#FFFFFF`,eventBorderSelected:`#FFD700`,eventOverlay:`rgba(255, 255, 255, 0.2)`,dragPreviewValid:`rgba(100, 255, 100, 0.5)`,dragPreviewInvalid:`rgba(255, 100, 100, 0.5)`,dragPreviewBorderValid:`#00FF00`,dragPreviewBorderInvalid:`#FF0000`,timeIndicator:`#FF6B6B`,guideLine:`#00D9FF`,guideLineLabel:`#00D9FF`,dragTimeReferenceLine:`#FFD700`,dragTimeReferenceLabel:`#FFD700`,dragTimeReferenceLabelBackground:`rgba(0, 0, 0, 0)`,scrollbarTrack:`rgba(255, 255, 255, 0.6)`,scrollbarHandle:`rgba(150, 150, 150, 0.8)`,scrollbarHandleHover:`rgba(0, 0, 0, 0.85)`,scrollbarHandleHighlight:`rgba(255, 255, 255, 0.3)`,scrollbarBorder:`rgba(255, 255, 255, 0.9)`,contextMenuBackground:`#2D2D3D`,contextMenuBorder:`#5A5A7A`,contextMenuText:`#CCCCDD`,contextMenuHoverBackground:`#3A3A4A`,contextMenuHoverText:`#FFFFFF`,eventDurationLabel:`#FFD700`},d={titleFontSize:`auto`,timeFontSize:`auto`,titleFontFamily:`Arial`,timeFontFamily:`Arial`,titleFontWeight:`bold`,timeFontWeight:`normal`,titleColor:null,timeColor:null,textAlign:`left`,verticalAlign:`middle`,titleOffsetY:0,timeOffsetY:0,showTitle:!0,showTime:!0,minHeightForTitle:40,minHeightForTime:50},f={borderRadius:2,enableSelectionGlow:!1,selectionGlowBlur:10},p=[{type:`edit`,name:`编辑`},{type:`delete`,name:`删除`},{type:`export`,name:`导出`}],m={fontSize:14,fontFamily:`Arial, sans-serif`,fontWeight:`normal`,padding:8,itemHeight:32,borderRadius:6,borderWidth:1,minWidth:120},h={timelineHeight:60,trackHeight:80,trackMargin:10,firstTrackTopMargin:10,secondWidth:100/3600,startTime:0,endTime:86400,startPaddingTime:.5,endPaddingTime:0,autoFitOnInit:!0,minAutoFitZoom:1,maxAutoFitZoom:3,timeUnit:`second`,timeFormat:`24h`,snapInterval:15,snapToSeconds:!0,secondPrecisionZoomThreshold:1.5,timeIndicatorWidth:3,timeIndicatorSnapThreshold:10,timeIndicatorHeadSize:12,timeIndicatorTriangleHeight:8,guideLineSnapThreshold:1,enableTimeIndicator:!0,enableEventResize:!0,enableEventSplit:!0,enableContextMenu:!0,resizeHandleWidth:8,minEventDuration:.25,debug:!1,enablePerformanceMonitor:!1,autoAddTrack:!0,autoRemoveEmptyLastTrack:!0,readOnly:!1,showEventDurationLabel:!0,formatEventDuration:null};function g(e){return{id:e.id,startTime:e.startTime,endTime:e.endTime,duration:e.duration,title:e.title,description:e.description,color:e.color,...e.readonly?{readonly:e.readonly}:{},...e.customData?{customData:{...e.customData}}:{}}}function _(){return{metadata:{name:`event-media`,version:`1.0.0`,description:`Render images and waveforms inside event blocks`,type:e.RENDER},async activate(e){let t=new Map,n=new Map,r=new Map;e.api.setData(`eventMediaImageCache`,t),e.api.setData(`eventMediaImageLoading`,n),e.api.setData(`eventMediaWaveCache`,r);let i=(t,n,r,i,a,o,s,l,u,d)=>{let f=e.api.getData(`eventMediaImageCache`),p=e.api.getData(`eventMediaImageLoading`),m=e.api.getData(`eventMediaWaveCache`),h=r.tracks[i].events[a],g=s+u,_=n.eventBlockStyle.borderRadius;t.save(),_>0?(c(t,o,g,l,d,_),t.clip()):(t.beginPath(),t.rect(o,g,l,d),t.clip());let v=h.media&&h.media.images||[];if(v.length>0&&f&&p)for(let e of v){let n=`${i}_${a}_${e.src}`,r=f.get(n);if(!r&&!p.get(n)){let t=fetch(e.src).then(e=>e.blob()).then(e=>createImageBitmap(e)).then(e=>(f.set(n,e),e)).catch(()=>void 0);p.set(n,t)}if(r=f.get(n),r){let n=e.fit||`cover`,i=e.opacity===void 0?.35:e.opacity,a=l,s=d;if(n!==`stretch`){let e=r.width,t=r.height,i=n===`cover`?Math.max(l/e,d/t):Math.min(l/e,d/t);a=Math.max(1,Math.floor(e*i)),s=Math.max(1,Math.floor(t*i))}let c=o+(l-a)/2,u=g+(d-s)/2,f=t.globalAlpha;t.globalAlpha=i,t.drawImage(r,0,0,r.width,r.height,c,u,a,s),t.globalAlpha=f}}let y=h.media&&h.media.waveform||void 0;if(y){let e=`${i}_${a}_wf`,n=m?m.get(e):void 0;if(!n){let t=y.data;n=Array.isArray(t)?new Float32Array(t):t,m&&m.set(e,n)}let r=y.opacity===void 0?.5:y.opacity,s=t.globalAlpha;t.globalAlpha=r,y.backgroundColor&&(t.fillStyle=y.backgroundColor,t.fillRect(o,g,l,d));let c=g+d/2,u=Math.max(1,Math.floor((d-2)/2));t.strokeStyle=y.color||`#00A0FF`,t.lineWidth=1,t.beginPath();let f=n.length;for(let e=0;e<l;e++){let r=Math.min(f-1,Math.max(0,Math.floor(e/Math.max(1,l-1)*f))),i=Math.max(-1,Math.min(1,n[r])),a=c-i*u,s=c+i*u;t.moveTo(o+e,a),t.lineTo(o+e,s)}t.stroke(),t.globalAlpha=s}t.restore()};e.api.registerEventHandler(`render:event:media`,i),e.api.setData(`eventMediaHandler`,i)},deactivate(e){let t=e.api.getData(`eventMediaHandler`);t&&e.api.unregisterEventHandler(`render:event:media`,t);let n=e.api.getData(`eventMediaImageCache`);n&&n.clear();let r=e.api.getData(`eventMediaImageLoading`);r&&r.clear();let i=e.api.getData(`eventMediaWaveCache`);i&&i.clear()}}}export{i as _,p as a,d as c,a as d,s as f,r as g,n as h,h as i,c as l,o as m,g as n,m as o,t as p,u as r,f as s,_ as t,l as u};
1
+ import{t as e}from"./types-BvVk5Y9C.mjs";function t(e,t=!0){let n=Math.round(e),r=Math.floor(n/3600),i=Math.floor(n%3600/60),a=n%60;return t?`${r.toString().padStart(2,`0`)}:${i.toString().padStart(2,`0`)}:${a.toString().padStart(2,`0`)}`:`${r.toString().padStart(2,`0`)}:${i.toString().padStart(2,`0`)}`}function n(){let e=new Date;return e.getHours()*3600+e.getMinutes()*60+e.getSeconds()}function r(e,t,n,r){return!n||e<r?t*60:[{threshold:10,seconds:.5},{threshold:8,seconds:1},{threshold:5,seconds:2},{threshold:3,seconds:5},{threshold:2,seconds:10},{threshold:0,seconds:15}].find(t=>e>=t.threshold)?.seconds??15}function i(e,t){return Math.round(e/t)*t}function a(e,t=3){let n=10**t;return Math.round(e*n)/n}function o(e,n){return`${t(e)} - ${t(n)}`}function s(e){return`持续 ${t(a(e))}`}function c(e,t,n,r,i,a,o=!1){e.beginPath(),e.moveTo(t+a,n),e.lineTo(t+r-a,n),e.arcTo(t+r,n,t+r,n+a,a),e.lineTo(t+r,n+i-a),e.arcTo(t+r,n+i,t+r-a,n+i,a),e.lineTo(t+a,n+i),e.arcTo(t,n+i,t,n+i-a,a),e.lineTo(t,n+a),e.arcTo(t,n,t+a,n,a),e.closePath(),o?e.stroke():e.fill()}function l(e,t,n,r,i,a){return n+(e-t)*r*i-a}const u={canvasBackground:`#1E1E2E`,timelineBackground:`#2D2D3D`,trackBackground:`#2A2A3A`,trackBackgroundSelected:`#3A3A4A`,timelineText:`#CCCCDD`,timelineGrid:`#5A5A7A`,timelineSubGrid:`#3A3A4A`,trackText:`#CCCCDD`,eventColors:[`#FF6B6B`,`#4ECDC4`,`#45B7D1`,`#96CEB4`,`#FECA57`,`#FF9FF3`],eventText:`#FFFFFF`,eventBorder:`#FFFFFF`,eventBorderSelected:`#FFD700`,eventOverlay:`rgba(255, 255, 255, 0.2)`,dragPreviewValid:`rgba(100, 255, 100, 0.5)`,dragPreviewInvalid:`rgba(255, 100, 100, 0.5)`,dragPreviewBorderValid:`#00FF00`,dragPreviewBorderInvalid:`#FF0000`,timeIndicator:`#FF6B6B`,guideLine:`#00D9FF`,guideLineLabel:`#00D9FF`,dragTimeReferenceLine:`#FFD700`,dragTimeReferenceLabel:`#FFD700`,dragTimeReferenceLabelBackground:`rgba(0, 0, 0, 0)`,scrollbarTrack:`rgba(255, 255, 255, 0.6)`,scrollbarHandle:`rgba(150, 150, 150, 0.8)`,scrollbarHandleHover:`rgba(0, 0, 0, 0.85)`,scrollbarHandleHighlight:`rgba(255, 255, 255, 0.3)`,scrollbarBorder:`rgba(255, 255, 255, 0.9)`,contextMenuBackground:`#2D2D3D`,contextMenuBorder:`#5A5A7A`,contextMenuText:`#CCCCDD`,contextMenuHoverBackground:`#3A3A4A`,contextMenuHoverText:`#FFFFFF`,eventDurationLabel:`#FFD700`},d={titleFontSize:`auto`,timeFontSize:`auto`,titleFontFamily:`Arial`,timeFontFamily:`Arial`,titleFontWeight:`bold`,timeFontWeight:`normal`,titleColor:null,timeColor:null,textAlign:`left`,verticalAlign:`middle`,titleOffsetY:0,timeOffsetY:0,showTitle:!0,showTime:!0,minHeightForTitle:40,minHeightForTime:50},f={borderRadius:2,enableSelectionGlow:!1,selectionGlowBlur:10},p=[{type:`edit`,name:`编辑`},{type:`delete`,name:`删除`},{type:`export`,name:`导出`}],m={fontSize:14,fontFamily:`Arial, sans-serif`,fontWeight:`normal`,padding:8,itemHeight:32,borderRadius:6,borderWidth:1,minWidth:120},h={timelineHeight:60,trackHeight:80,trackMargin:10,firstTrackTopMargin:10,secondWidth:100/3600,startTime:0,endTime:86400,startPaddingTime:.5,endPaddingTime:0,autoFitOnInit:!0,minAutoFitZoom:1,maxAutoFitZoom:3,timeUnit:`second`,timeFormat:`24h`,snapInterval:15,snapToSeconds:!0,secondPrecisionZoomThreshold:1.5,timeIndicatorWidth:3,timeIndicatorSnapThreshold:10,timeIndicatorHeadSize:12,timeIndicatorTriangleHeight:8,guideLineSnapThreshold:1,enableTimeIndicator:!0,enableEventResize:!0,enableEventSplit:!0,enableContextMenu:!0,resizeHandleWidth:8,minEventDuration:.25,debug:!1,enablePerformanceMonitor:!1,autoAddTrack:!0,autoRemoveEmptyLastTrack:!0,readOnly:!1,showEventDurationLabel:!0,formatEventDuration:null};function g(e){return{id:e.id,startTime:e.startTime,endTime:e.endTime,duration:e.duration,title:e.title,description:e.description,color:e.color,...e.readonly?{readonly:e.readonly}:{},...e.customData?{customData:{...e.customData}}:{}}}const _=new Map,v=new Map;function y(e,t,n,r){let i=_.get(e);if(i)return i;let a=new Path2D,o=r/2,s=Math.max(1,Math.floor((r-2)/2)),c=t.length,l=Math.max(1,n-1);for(let e=0;e<n;e++){let n=Math.min(c-1,Math.max(0,Math.floor(e/l*c))),r=Math.max(-1,Math.min(1,t[n]))*s;a.moveTo(e,o-r),a.lineTo(e,o+r)}return _.set(e,a),a}function b(e,t,n,r,i,a){let o=v.get(e);if(o&&o.width===n&&o.height===r)return o.bitmap;if(typeof OffscreenCanvas>`u`||n<=0||r<=0)return null;try{let o=Math.max(1,Math.ceil(n)),s=Math.max(1,Math.ceil(r)),c=new OffscreenCanvas(o,s),l=c.getContext(`2d`);if(!l)return null;a&&(l.fillStyle=a,l.fillRect(0,0,o,s));let u=y(`${e}_path`,t,o,s);l.strokeStyle=i,l.lineWidth=1,l.stroke(u);let d=c.transferToImageBitmap(),f=v.get(e);return f&&f.bitmap.close(),v.set(e,{bitmap:d,width:o,height:s}),d}catch{return null}}function x(){return{metadata:{name:`event-media`,version:`1.0.0`,description:`Render images and waveforms inside event blocks`,type:e.RENDER},async activate(e){let t=new Map,n=new Map,r=new Map;e.api.setData(`eventMediaImageCache`,t),e.api.setData(`eventMediaImageLoading`,n),e.api.setData(`eventMediaWaveCache`,r);let i=(t,n,r,i,a,o,s,l,u,d)=>{let f=e.api.getData(`eventMediaImageCache`),p=e.api.getData(`eventMediaImageLoading`),m=e.api.getData(`eventMediaWaveCache`),h=r.tracks[i].events[a],g=s+u,_=n.eventBlockStyle.borderRadius;t.save(),_>0?(c(t,o,g,l,d,_),t.clip()):(t.beginPath(),t.rect(o,g,l,d),t.clip());let v=h.media&&h.media.images||[];if(v.length>0&&f&&p)for(let e of v){let n=`${h.id??`${i}_${a}`}_${e.src}`,r=f.get(n);if(!r&&!p.get(n)){let t=fetch(e.src).then(e=>e.blob()).then(e=>createImageBitmap(e)).then(e=>(f.set(n,e),e)).catch(()=>void 0);p.set(n,t)}if(r=f.get(n),r){let n=e.fit||`cover`,i=e.opacity===void 0?.35:e.opacity,a=l,s=d;if(n!==`stretch`){let e=r.width,t=r.height,i=n===`cover`?Math.max(l/e,d/t):Math.min(l/e,d/t);a=Math.max(1,Math.floor(e*i)),s=Math.max(1,Math.floor(t*i))}let c=o+(l-a)/2,u=g+(d-s)/2,f=t.globalAlpha;t.globalAlpha=i,t.drawImage(r,0,0,r.width,r.height,c,u,a,s),t.globalAlpha=f}}let x=h.media&&h.media.waveform||void 0;if(x){let e=`${h.id??`${i}_${a}`}_wf`,n=m?m.get(e):void 0;if(!n){let t=x.data;n=Array.isArray(t)?new Float32Array(t):t,m&&m.set(e,n)}let r=x.opacity===void 0?.5:x.opacity,s=t.globalAlpha;t.globalAlpha=r;let c=x.color||`#00A0FF`,u=Math.max(1,Math.ceil(l)),f=Math.max(1,Math.ceil(d)),p=b(`${e}_${u}_${f}_${c}_${x.backgroundColor||``}`,n,u,f,c,x.backgroundColor);if(p)t.drawImage(p,o,g,l,d);else{x.backgroundColor&&(t.fillStyle=x.backgroundColor,t.fillRect(o,g,l,d));let r=y(`${e}_${u}_${f}`,n,u,f);t.save(),t.translate(o,g),t.strokeStyle=c,t.lineWidth=1,t.stroke(r),t.restore()}t.globalAlpha=s}t.restore()};e.api.registerEventHandler(`render:event:media`,i),e.api.setData(`eventMediaHandler`,i)},deactivate(e){let t=e.api.getData(`eventMediaHandler`);t&&e.api.unregisterEventHandler(`render:event:media`,t);let n=e.api.getData(`eventMediaImageCache`);n&&n.clear();let r=e.api.getData(`eventMediaImageLoading`);r&&r.clear();let i=e.api.getData(`eventMediaWaveCache`);i&&i.clear();for(let e of v.values())e.bitmap.close();v.clear(),_.clear()}}}export{i as _,p as a,d as c,a as d,s as f,r as g,n as h,h as i,c as l,o as m,g as n,m as o,t as p,u as r,f as s,x as t,l as u};
@@ -1,4 +1,4 @@
1
- import { t as TimelinePlugin } from "./types-D5-4YwEP.mjs";
1
+ import { t as TimelinePlugin } from "./types-pL-YHm8m.mjs";
2
2
 
3
3
  //#region src/plugins/builtin/EventMediaPlugin.d.ts
4
4
  declare function EventMediaPlugin(): TimelinePlugin;
@@ -1,4 +1,4 @@
1
- import { t as TimelinePlugin } from "./types-D5-4YwEP.mjs";
1
+ import { t as TimelinePlugin } from "./types-pL-YHm8m.mjs";
2
2
 
3
3
  //#region src/plugins/builtin/EventTooltipPlugin.d.ts
4
4
  interface EventTooltipPluginOptions {
@@ -0,0 +1 @@
1
+ import{i as e}from"./Logger-CfVK3yFL.mjs";import{t}from"./types-BvVk5Y9C.mjs";const n=e(`EventTooltipPlugin`);function r(e={}){let{htmlTemplate:r,showDelay:i=300,maxWidth:a=300,padding:o=8,borderRadius:s=4,backgroundColor:c=`#333`,textColor:l=`#fff`,borderColor:u=`#555`,fontSize:d=12,fontFamily:f=`Arial, sans-serif`}=e,p={visible:!1,title:``,x:0,y:0,trackIndex:-1,eventIndex:-1},m=null,h=null;function g(e,t,n){return e.measureText(t).width>n}return{metadata:{name:`event-tooltip`,version:`1.0.0`,description:`Tooltip plugin for displaying full event title when text is truncated`,type:t.EXTENSION},activate(e){let t=e.timeline.getCanvas(),_=!1,v=null,y=n=>{let r=t.getBoundingClientRect(),a=n.clientX-r.left,o=n.clientY-r.top,s=e.config,c=e.state,l=e.timeline.getEventAtPosition(a,o);if(l){let{trackIndex:n,eventIndex:r}=l,u=c.tracks[n]?.events[r];if(!u){x();return}if(h&&h.trackIndex===n&&h.eventIndex===r&&p.visible){p.x=a,p.y=o,e.timeline.draw();return}h={trackIndex:n,eventIndex:r},m&&=(clearTimeout(m),null);let d=u.duration*s.secondWidth*c.zoomLevel-20,f=t.getContext(`2d`);if(!f)return;let _=s.eventTextStyle,v=_.titleFontSize===`auto`?Math.max(10,Math.min(14,s.trackHeight*.175)):_.titleFontSize;f.font=`${_.titleFontWeight} ${v}px ${_.titleFontFamily}`,g(f,u.title,d)?m=setTimeout(()=>{p={visible:!0,title:u.title,x:a,y:o,trackIndex:n,eventIndex:r},e.timeline.draw()},i):x()}else x()},b=e=>{v=e,_||(_=!0,requestAnimationFrame(()=>{_=!1,v&&=(y(v),null)}))},x=()=>{m&&=(clearTimeout(m),null),h=null,p.visible&&(p.visible=!1,e.timeline.draw())},S=()=>{x()};t.addEventListener(`mousemove`,b),t.addEventListener(`mouseleave`,S),e.api.setData(`tooltipMouseMoveHandler`,b),e.api.setData(`tooltipMouseLeaveHandler`,S),e.api.registerRenderLayer({name:`event-tooltip-overlay`,position:`overlay`,render(t,i,m,h){if(!p.visible||!p.title){let t=e.api.getData(`tooltipContainer`)||null;t&&(t.style.display=`none`);return}let g=e.timeline.getCanvas().getBoundingClientRect(),_=p.x,v=p.y-10;t.save(),t.font=`${d}px ${f}`;let y=p.title.split(``),b=[],x=``;for(let e of y){let n=x+e;t.measureText(n).width>a-o*2?x?(b.push(x),x=e):b.push(e):x=n}x&&b.push(x);let S=0;for(let e of b){let n=t.measureText(e).width;S=Math.max(S,n)}S=Math.min(S+o*2,a);let C=d*1.4,w=b.length*C+o*2;if(v-=w,_+S>g.width&&(_=g.width-S-5),_<5&&(_=5),v<5&&(v=p.y+20),r){let i=r(p.title);if(!i||i.trim()===``)n.warn(`htmlTemplate returned empty content, falling back to Canvas rendering`);else{let n=e.api.getData(`tooltipContainer`)||null;if(!n){n=document.createElement(`div`),n.style.position=`absolute`,n.style.zIndex=`1001`,n.style.pointerEvents=`none`,n.style.boxShadow=`0 2px 8px rgba(0,0,0,0.3)`,n.style.border=`1px solid ${u}`,n.style.borderRadius=`${s}px`,n.style.padding=`${o}px`,n.style.fontSize=`${d}px`,n.style.fontFamily=f,n.style.backgroundColor=c,n.style.color=l,n.style.maxWidth=`${a}px`,n.style.wordWrap=`break-word`,n.style.whiteSpace=`pre-wrap`;let t=e.timeline.getCanvas().parentElement||document.body;t.style.position=t.style.position||`relative`,t.appendChild(n),e.api.setData(`tooltipContainer`,n)}n.style.display=`block`,n.style.left=`${_}px`,n.style.top=`${v}px`,n.innerHTML=i,t.restore();return}}if(t.shadowColor=`rgba(0, 0, 0, 0.3)`,t.shadowBlur=8,t.shadowOffsetX=0,t.shadowOffsetY=2,t.fillStyle=c,t.beginPath(),t.roundRect)t.roundRect(_,v,S,w,s);else{let e=_,n=v,r=S,i=w,a=s;t.moveTo(e+a,n),t.lineTo(e+r-a,n),t.quadraticCurveTo(e+r,n,e+r,n+a),t.lineTo(e+r,n+i-a),t.quadraticCurveTo(e+r,n+i,e+r-a,n+i),t.lineTo(e+a,n+i),t.quadraticCurveTo(e,n+i,e,n+i-a),t.lineTo(e,n+a),t.quadraticCurveTo(e,n,e+a,n)}t.fill(),t.shadowColor=`transparent`,t.shadowBlur=0,t.strokeStyle=u,t.lineWidth=1,t.stroke(),t.fillStyle=l,t.font=`${d}px ${f}`,t.textAlign=`left`,t.textBaseline=`top`;for(let e=0;e<b.length;e++)t.fillText(b[e],_+o,v+o+e*C);t.restore()}})},deactivate(e){let t=e.timeline.getCanvas(),n=e.api.getData(`tooltipMouseMoveHandler`),r=e.api.getData(`tooltipMouseLeaveHandler`);n&&t.removeEventListener(`mousemove`,n),r&&t.removeEventListener(`mouseleave`,r),m&&=(clearTimeout(m),null),e.api.unregisterRenderLayer(`event-tooltip-overlay`);let i=e.api.getData(`tooltipContainer`)||null;i&&i.parentElement&&i.parentElement.removeChild(i)},destroy(e){let t=e.api.getData(`tooltipContainer`)||null;t&&t.parentElement&&t.parentElement.removeChild(t),m&&=(clearTimeout(m),null)}}}export{r as t};
@@ -1,4 +1,4 @@
1
- import { t as TimelinePlugin } from "./types-D5-4YwEP.mjs";
1
+ import { t as TimelinePlugin } from "./types-pL-YHm8m.mjs";
2
2
 
3
3
  //#region src/plugins/builtin/LightThemePlugin.d.ts
4
4
  declare const LightThemePlugin: TimelinePlugin;
@@ -1 +1 @@
1
- import{t as e}from"./types-CkHQNcJ5.mjs";const t={canvasBackground:`#FFFFFF`,timelineBackground:`#FFFFFF`,trackBackground:`#FFFFFF`,trackBackgroundSelected:`rgba(63, 118, 252, 0.1)`,trackBackgroundOdd:`#FFFFFF`,trackBackgroundEven:`#F9FAFD`,timelineText:`#969BA5`,timelineGrid:`#E5E5E5`,timelineSubGrid:`#fff`,trackText:`#CCCCDD`,eventColors:[`rgba(63, 118, 252, 0.16)`],eventText:`#FFFFFF`,eventBorder:`#FFFFFF`,eventBorderSelected:`#3F76FC`,eventOverlay:`rgba(255, 255, 255, 0.2)`,dragPreviewValid:`rgba(100, 255, 100, 0.5)`,dragPreviewInvalid:`rgba(255, 100, 100, 0.5)`,dragPreviewBorderValid:`#00FF00`,dragPreviewBorderInvalid:`#FF0000`,timeIndicator:`#3F76FC`,guideLine:`#00D9FF`,guideLineLabel:`#00D9FF`,dragTimeReferenceLine:`#FFD700`,dragTimeReferenceLabel:`#FFD700`,dragTimeReferenceLabelBackground:`rgba(0, 0, 0, 0)`,scrollbarTrack:`rgba(63, 118, 252, 0.08)`,scrollbarHandle:`rgba(63, 118, 252, 0.5)`,scrollbarHandleHover:`rgba(63, 118, 252, 0.8)`,scrollbarHandleHighlight:`rgba(63, 118, 252, 0.12)`,scrollbarBorder:`rgba(63, 118, 252, 0.6)`,contextMenuBackground:`#2D2D3D`,contextMenuBorder:`#5A5A7A`,contextMenuText:`#CCCCDD`,contextMenuHoverBackground:`#4a00e0`,contextMenuHoverText:`#FFFFFF`,eventDurationLabel:`#3F76FC`},n={metadata:{name:`theme-light`,version:`1.0.0`,description:`Light theme for timeline`,type:e.THEME},activate(e){e.config.colors={...e.config.colors,...t},e.api.registerRenderLayer({name:`theme-light-background`,position:`background`,render(e,t,n){e.fillStyle=n.colors.canvasBackground,e.fillRect(0,0,t.width,t.height)}})},deactivate(e){e.api.unregisterRenderLayer(`theme-light-background`)}};export{n as t};
1
+ import{t as e}from"./types-BvVk5Y9C.mjs";const t={canvasBackground:`#FFFFFF`,timelineBackground:`#FFFFFF`,trackBackground:`#FFFFFF`,trackBackgroundSelected:`rgba(63, 118, 252, 0.1)`,trackBackgroundOdd:`#FFFFFF`,trackBackgroundEven:`#F9FAFD`,timelineText:`#969BA5`,timelineGrid:`#E5E5E5`,timelineSubGrid:`#fff`,trackText:`#CCCCDD`,eventColors:[`rgba(63, 118, 252, 0.16)`],eventText:`#FFFFFF`,eventBorder:`#FFFFFF`,eventBorderSelected:`#3F76FC`,eventOverlay:`rgba(255, 255, 255, 0.2)`,dragPreviewValid:`rgba(100, 255, 100, 0.5)`,dragPreviewInvalid:`rgba(255, 100, 100, 0.5)`,dragPreviewBorderValid:`#00FF00`,dragPreviewBorderInvalid:`#FF0000`,timeIndicator:`#3F76FC`,guideLine:`#00D9FF`,guideLineLabel:`#00D9FF`,dragTimeReferenceLine:`#FFD700`,dragTimeReferenceLabel:`#FFD700`,dragTimeReferenceLabelBackground:`rgba(0, 0, 0, 0)`,scrollbarTrack:`rgba(63, 118, 252, 0.08)`,scrollbarHandle:`rgba(63, 118, 252, 0.5)`,scrollbarHandleHover:`rgba(63, 118, 252, 0.8)`,scrollbarHandleHighlight:`rgba(63, 118, 252, 0.12)`,scrollbarBorder:`rgba(63, 118, 252, 0.6)`,contextMenuBackground:`#2D2D3D`,contextMenuBorder:`#5A5A7A`,contextMenuText:`#CCCCDD`,contextMenuHoverBackground:`#4a00e0`,contextMenuHoverText:`#FFFFFF`,eventDurationLabel:`#3F76FC`},n={metadata:{name:`theme-light`,version:`1.0.0`,description:`Light theme for timeline`,type:e.THEME},activate(e){e.config.colors={...e.config.colors,...t},e.api.registerRenderLayer({name:`theme-light-background`,position:`background`,render(e,t,n){e.fillStyle=n.colors.canvasBackground,e.fillRect(0,0,t.width,t.height)}})},deactivate(e){e.api.unregisterRenderLayer(`theme-light-background`)}};export{n as t};
@@ -1,4 +1,4 @@
1
- import { t as TimelinePlugin } from "./types-D5-4YwEP.mjs";
1
+ import { t as TimelinePlugin } from "./types-pL-YHm8m.mjs";
2
2
 
3
3
  //#region src/plugins/builtin/PerformanceOverlayPlugin.d.ts
4
4
  declare const PerformanceOverlayPlugin: TimelinePlugin;
@@ -0,0 +1 @@
1
+ import{t as e}from"./performanceMonitor-BBherdD8.mjs";import{t}from"./types-BvVk5Y9C.mjs";const n={metadata:{name:`performance-overlay`,version:`1.0.0`,description:`Draw performance metrics overlay`,type:t.TOOL},activate(t){let n=new e(t.config.enablePerformanceMonitor||t.config.debug);t.api.setPerformanceProvider(n),t.api.setData(`perfMonitor`,n),t.api.setData(`perfOverlayPos`,{x:10,y:10}),t.api.setData(`perfOverlayDragging`,!1),t.api.setData(`perfOverlayOffset`,{x:0,y:0});let r=t.timeline.getCanvas(),i=e=>{let n=r.getBoundingClientRect(),i=e.clientX-n.left,a=e.clientY-n.top,o=t.api.getData(`perfOverlaySize`),s=t.api.getData(`perfOverlayPos`)||{x:10,y:10};o&&i>=s.x&&i<=s.x+o.width&&a>=s.y&&a<=s.y+o.height&&(t.api.setData(`perfOverlayDragging`,!0),t.api.setData(`perfOverlayOffset`,{x:i-s.x,y:a-s.y}),e.stopPropagation(),e.preventDefault())},a=e=>{if(!t.api.getData(`perfOverlayDragging`))return;let n=r.getBoundingClientRect(),i=e.clientX-n.left,a=e.clientY-n.top,o=t.api.getData(`perfOverlayOffset`)||{x:0,y:0},s=t.api.getData(`perfOverlaySize`)||{width:0,height:0},c=i-o.x,l=a-o.y;c=Math.max(0,Math.min(n.width-s.width,c)),l=Math.max(0,Math.min(n.height-s.height,l)),t.api.setData(`perfOverlayPos`,{x:c,y:l}),t.timeline.draw(),e.stopPropagation(),e.preventDefault()},o=e=>{t.api.getData(`perfOverlayDragging`)&&t.api.setData(`perfOverlayDragging`,!1)};r.addEventListener(`mousedown`,i,{capture:!0}),r.addEventListener(`mousemove`,a,{capture:!0}),window.addEventListener(`mouseup`,o,{capture:!0}),t.api.setData(`perfOverlayListeners`,{onMouseDown:i,onMouseMove:a,onMouseUp:o}),t.api.registerRenderLayer({name:`performance-overlay`,position:`overlay`,render(e){let n=t.api.getData(`perfMonitor`),r=!!(t.config.enablePerformanceMonitor||t.config.debug);if(n)if(r)n.enable();else{n.disable(),n.clear();return}else if(!r)return;let i=t.api.getPerformanceStats(),a=t.api.getFPS(),o=Array.from(i.entries()),s=[`background`,`tracks`,`timeline`,`interaction`,`guideLines`,`scrollbar`,`overlay`,`dragPreview`],c=t.timeline.getLastLayerTimes?t.timeline.getLastLayerTimes():void 0,l=c?s.filter(e=>c[e]!==void 0).length:0,u=c?1+l:0,d=25+(1+(i.size===0?1:o.length)+u)*20+30,f=t.api.getData(`perfOverlayPos`)||{x:10,y:10};t.api.setData(`perfOverlaySize`,{width:280,height:d}),e.fillStyle=`rgba(0, 0, 0, 0.8)`,e.fillRect(f.x,f.y,280,d),e.strokeStyle=`rgba(100, 255, 100, 0.6)`,e.lineWidth=2,e.strokeRect(f.x,f.y,280,d),e.fillStyle=`#00FF00`,e.font=`bold 16px monospace`,e.textAlign=`left`,e.fillText(`性能监控报告`,f.x+10,f.y+20);let p=f.y+20+25;if(e.fillStyle=a>=55?`#00FF00`:a>=30?`#FFFF00`:`#FF0000`,e.font=`bold 14px monospace`,e.fillText(`FPS: ${a.toFixed(1)}`,f.x+10,p),e.font=`12px monospace`,p+=20,c){e.fillStyle=`#00FFFF`,e.font=`bold 12px monospace`,e.fillText(`Layer Times (ms):`,f.x+10,p),p+=20,e.font=`12px monospace`,e.fillStyle=`#FFFFFF`;for(let t of s)c[t]!==void 0&&(e.fillText(`${t}: ${c[t].toFixed(2)}`,f.x+10,p),p+=20)}i.size===0?(e.fillStyle=`#FFFFFF`,e.fillText(`Collecting...`,f.x+10,p),p+=20):o.forEach(([t,n])=>{let r=`#00FF00`;n.average>16&&(r=`#FFFF00`),n.average>33&&(r=`#FF0000`),e.fillStyle=r;let i=`${t}: ${n.average.toFixed(2)}ms (${n.min.toFixed(1)}-${n.max.toFixed(1)})`;e.fillText(i,f.x+10,p),p+=20})}})},deactivate(e){e.api.unregisterRenderLayer(`performance-overlay`);let t=e.api.getData(`perfOverlayListeners`),n=e.timeline.getCanvas();t&&(n.removeEventListener(`mousedown`,t.onMouseDown,!0),n.removeEventListener(`mousemove`,t.onMouseMove,!0),window.removeEventListener(`mouseup`,t.onMouseUp,!0))}};export{n as t};
@@ -1,3 +1,3 @@
1
- import "../types-D5-4YwEP.mjs";
2
- import { t as ContextMenuPlugin } from "../ContextMenuPlugin-Crk3ma0O.mjs";
1
+ import "../types-pL-YHm8m.mjs";
2
+ import { t as ContextMenuPlugin } from "../ContextMenuPlugin-D-SJ3frM.mjs";
3
3
  export { ContextMenuPlugin };
@@ -1 +1 @@
1
- import"../Logger-Bwd6lZLT.mjs";import"../types-CkHQNcJ5.mjs";import{t as e}from"../ContextMenuPlugin-B9TmnnaU.mjs";export{e as ContextMenuPlugin};
1
+ import{t as e}from"../ContextMenuPlugin-6qe5xYCu.mjs";export{e as ContextMenuPlugin};
@@ -1,3 +1,3 @@
1
- import "../types-D5-4YwEP.mjs";
2
- import { t as DarkThemePlugin } from "../DarkThemePlugin-IbJNx65n.mjs";
1
+ import "../types-pL-YHm8m.mjs";
2
+ import { t as DarkThemePlugin } from "../DarkThemePlugin-Ov8yWWT7.mjs";
3
3
  export { DarkThemePlugin as DarkTheme, DarkThemePlugin };
@@ -1 +1 @@
1
- import"../types-CkHQNcJ5.mjs";import{t as e}from"../DarkThemePlugin-CRFdrOR3.mjs";export{e as DarkTheme,e as DarkThemePlugin};
1
+ import{t as e}from"../DarkThemePlugin-GyV1mhmz.mjs";export{e as DarkTheme,e as DarkThemePlugin};
@@ -1,3 +1,3 @@
1
- import "../types-D5-4YwEP.mjs";
2
- import { t as EventMediaPlugin } from "../EventMediaPlugin-daiUXxsT.mjs";
1
+ import "../types-pL-YHm8m.mjs";
2
+ import { t as EventMediaPlugin } from "../EventMediaPlugin-DNFZmJz5.mjs";
3
3
  export { EventMediaPlugin };
@@ -1 +1 @@
1
- import{t as e}from"../EventMediaPlugin-DPPdLbey.mjs";import"../performanceMonitor-Cf-Ah4F7.mjs";import"../types-CkHQNcJ5.mjs";export{e as EventMediaPlugin};
1
+ import{t as e}from"../EventMediaPlugin-CawS6c0q.mjs";export{e as EventMediaPlugin};
@@ -1,3 +1,3 @@
1
- import "../types-D5-4YwEP.mjs";
2
- import { t as EventTooltipPlugin } from "../EventTooltipPlugin-b5fqBb8j.mjs";
1
+ import "../types-pL-YHm8m.mjs";
2
+ import { t as EventTooltipPlugin } from "../EventTooltipPlugin-BPx9AZt8.mjs";
3
3
  export { EventTooltipPlugin };
@@ -1 +1 @@
1
- import"../Logger-Bwd6lZLT.mjs";import"../types-CkHQNcJ5.mjs";import{t as e}from"../EventTooltipPlugin-Ce6xChyf.mjs";export{e as EventTooltipPlugin};
1
+ import{t as e}from"../EventTooltipPlugin-DNGXHYbN.mjs";export{e as EventTooltipPlugin};
@@ -1,3 +1,3 @@
1
- import "../types-D5-4YwEP.mjs";
2
- import { t as LightThemePlugin } from "../LightThemePlugin-DrdhIHgA.mjs";
1
+ import "../types-pL-YHm8m.mjs";
2
+ import { t as LightThemePlugin } from "../LightThemePlugin-Dw40Vr7u.mjs";
3
3
  export { LightThemePlugin as LightTheme, LightThemePlugin };
@@ -1 +1 @@
1
- import"../types-CkHQNcJ5.mjs";import{t as e}from"../LightThemePlugin-BOreTGti.mjs";export{e as LightTheme,e as LightThemePlugin};
1
+ import{t as e}from"../LightThemePlugin-wHpjmbXj.mjs";export{e as LightTheme,e as LightThemePlugin};
@@ -1,4 +1,4 @@
1
- import { t as TimelinePlugin } from "../types-D5-4YwEP.mjs";
1
+ import { t as TimelinePlugin } from "../types-pL-YHm8m.mjs";
2
2
 
3
3
  //#region src/plugins/builtin/MutexGuardPlugin.d.ts
4
4
  declare function MutexGuardPlugin(): TimelinePlugin;
@@ -1 +1 @@
1
- import{t as e}from"../types-CkHQNcJ5.mjs";function t(){return{metadata:{name:`MutexGuardPlugin`,version:`1.0.0`,description:`Disallow parallel existence of mutex-tagged events across tracks`,type:e.EXTENSION},activate(e){e.api.registerEventHandler(`validate:event:move`,t=>{let{fromTrackIndex:n,fromEventIndex:r,newStartTime:i,duration:a}=t,o=e.state,s=i+a,c=o.tracks[n]?.events[r];if(!c)return!0;let l=Array.isArray(c.customData?.mutex)?c.customData.mutex:[];if(l.length===0)return!0;for(let e=0;e<o.tracks.length;e++){let t=o.tracks[e];for(let a=0;a<t.events.length;a++){if(e===n&&a===r)continue;let o=t.events[a],c=Array.isArray(o.customData?.mutex)?o.customData.mutex:[];if(c.length!==0&&l.some(e=>c.includes(e))&&!(s<=o.startTime||i>=o.endTime))return!1}}return!0})}}}export{t as MutexGuardPlugin};
1
+ import{t as e}from"../types-BvVk5Y9C.mjs";function t(){return{metadata:{name:`MutexGuardPlugin`,version:`1.0.0`,description:`Disallow parallel existence of mutex-tagged events across tracks`,type:e.EXTENSION},activate(e){e.api.registerEventHandler(`validate:event:move`,t=>{let{fromTrackIndex:n,fromEventIndex:r,newStartTime:i,duration:a}=t,o=e.state,s=i+a,c=o.tracks[n]?.events[r];if(!c)return!0;let l=Array.isArray(c.customData?.mutex)?c.customData.mutex:[];if(l.length===0)return!0;for(let e=0;e<o.tracks.length;e++){let t=o.tracks[e];for(let a=0;a<t.events.length;a++){if(e===n&&a===r)continue;let o=t.events[a],c=Array.isArray(o.customData?.mutex)?o.customData.mutex:[];if(c.length!==0&&l.some(e=>c.includes(e))&&!(s<=o.startTime||i>=o.endTime))return!1}}return!0})}}}export{t as MutexGuardPlugin};
@@ -1,3 +1,3 @@
1
- import "../types-D5-4YwEP.mjs";
2
- import { t as PerformanceOverlayPlugin } from "../PerformanceOverlayPlugin-BFU4Le2k.mjs";
1
+ import "../types-pL-YHm8m.mjs";
2
+ import { t as PerformanceOverlayPlugin } from "../PerformanceOverlayPlugin-C6wYxsQg.mjs";
3
3
  export { PerformanceOverlayPlugin };
@@ -1 +1 @@
1
- import"../performanceMonitor-Cf-Ah4F7.mjs";import"../types-CkHQNcJ5.mjs";import{t as e}from"../PerformanceOverlayPlugin-Bx-DkYbW.mjs";export{e as PerformanceOverlayPlugin};
1
+ import{t as e}from"../PerformanceOverlayPlugin-DlYhPYO-.mjs";export{e as PerformanceOverlayPlugin};
package/dist/index.d.mts CHANGED
@@ -1,13 +1,13 @@
1
- import { C as ZoomData, S as Track, _ as TimelineColors, a as ContextMenuItem, b as TimelineOptions, c as EventClickData, d as EventMoveData, f as EventTextStyle, g as TimelineCallbacks, h as TimeIndicatorMoveData, i as ContextMenuData, l as EventDeleteData, m as LoadDataFormat, n as Timeline, o as ContextMenuStyle, p as EventUpdateData, r as ChangeType, s as EventAddData, u as EventEditData, v as TimelineConfig, x as TimelineState, y as TimelineEvent } from "./types-D5-4YwEP.mjs";
2
- import { t as ContextMenuPlugin } from "./ContextMenuPlugin-Crk3ma0O.mjs";
3
- import { t as DarkThemePlugin } from "./DarkThemePlugin-IbJNx65n.mjs";
4
- import { t as EventMediaPlugin } from "./EventMediaPlugin-daiUXxsT.mjs";
5
- import { t as EventTooltipPlugin } from "./EventTooltipPlugin-b5fqBb8j.mjs";
6
- import { t as LightThemePlugin } from "./LightThemePlugin-DrdhIHgA.mjs";
7
- import { t as PerformanceOverlayPlugin } from "./PerformanceOverlayPlugin-BFU4Le2k.mjs";
1
+ import { C as Track, S as TimelineState, _ as TimelineCallbacks, a as ContextMenuItem, b as TimelineEvent, c as EventClickData, d as EventMoveData, f as EventTextStyle, g as TimeIndicatorMoveData, h as LoadDataFormat, i as ContextMenuData, l as EventDeleteData, m as InteractionTarget, n as Timeline, o as ContextMenuStyle, p as EventUpdateData, r as ChangeType, s as EventAddData, u as EventEditData, v as TimelineColors, w as ZoomData, x as TimelineOptions, y as TimelineConfig } from "./types-pL-YHm8m.mjs";
2
+ import { t as ContextMenuPlugin } from "./ContextMenuPlugin-D-SJ3frM.mjs";
3
+ import { t as DarkThemePlugin } from "./DarkThemePlugin-Ov8yWWT7.mjs";
4
+ import { t as EventMediaPlugin } from "./EventMediaPlugin-DNFZmJz5.mjs";
5
+ import { t as EventTooltipPlugin } from "./EventTooltipPlugin-BPx9AZt8.mjs";
6
+ import { t as LightThemePlugin } from "./LightThemePlugin-Dw40Vr7u.mjs";
7
+ import { t as PerformanceOverlayPlugin } from "./PerformanceOverlayPlugin-C6wYxsQg.mjs";
8
8
 
9
9
  //#region src/utils/time.d.ts
10
10
  declare function formatTime(seconds: number, showSeconds?: boolean): string;
11
11
  declare function getCurrentTime(): number;
12
12
  //#endregion
13
- export { type ChangeType, type ContextMenuData, type ContextMenuItem, ContextMenuPlugin, type ContextMenuStyle, DarkThemePlugin, type EventAddData, type EventClickData, type EventDeleteData, type EventEditData, EventMediaPlugin, type EventMoveData, type EventTextStyle, EventTooltipPlugin, type EventUpdateData, LightThemePlugin, type LoadDataFormat, PerformanceOverlayPlugin, type TimeIndicatorMoveData, Timeline, type TimelineCallbacks, type TimelineColors, type TimelineConfig, type TimelineEvent, type TimelineOptions, type TimelineState, type Track, type ZoomData, formatTime, getCurrentTime };
13
+ export { type ChangeType, type ContextMenuData, type ContextMenuItem, ContextMenuPlugin, type ContextMenuStyle, DarkThemePlugin, type EventAddData, type EventClickData, type EventDeleteData, type EventEditData, EventMediaPlugin, type EventMoveData, type EventTextStyle, EventTooltipPlugin, type EventUpdateData, type InteractionTarget, LightThemePlugin, type LoadDataFormat, PerformanceOverlayPlugin, type TimeIndicatorMoveData, Timeline, type TimelineCallbacks, type TimelineColors, type TimelineConfig, type TimelineEvent, type TimelineOptions, type TimelineState, type Track, type ZoomData, formatTime, getCurrentTime };
package/dist/index.mjs CHANGED
@@ -1 +1 @@
1
- import{_ as e,a as t,c as n,d as r,f as i,g as a,h as o,i as s,l as c,m as l,n as u,o as d,p as f,r as p,s as m,t as h,u as g}from"./EventMediaPlugin-DPPdLbey.mjs";import"./performanceMonitor-Cf-Ah4F7.mjs";import{i as _,n as v,r as y,t as b}from"./Logger-Bwd6lZLT.mjs";import"./types-CkHQNcJ5.mjs";import{t as x}from"./LightThemePlugin-BOreTGti.mjs";import{t as S}from"./DarkThemePlugin-CRFdrOR3.mjs";import{t as C}from"./ContextMenuPlugin-B9TmnnaU.mjs";import{t as w}from"./PerformanceOverlayPlugin-Bx-DkYbW.mjs";import{t as T}from"./EventTooltipPlugin-Ce6xChyf.mjs";var E=class{constructor(e,t){this.H_SCROLLBAR_PADDING=13,this.config=e,this.state=t}getContentWidth(e){if(this.cwZoom===e&&this.cwValue!==void 0)return this.cwValue;let t=this.config.endTime+this.config.endPaddingTime-this.config.startTime,n=this.config.startPaddingTime+t*this.config.secondWidth*e;return this.cwZoom=e,this.cwValue=n,n}invalidateCache(){this.cwZoom=void 0,this.cwValue=void 0}getContentHeight(){return this.config.timelineHeight+this.config.firstTrackTopMargin+this.state.tracks.length*(this.config.trackHeight+this.config.trackMargin)}computeMaxScrollX(e,t){let n=this.getContentWidth(e);return Math.max(0,n-t)}computeMaxScrollY(e){let t=this.getContentHeight();return Math.max(0,t-e)}hasHorizontalScrollbar(e,t){return this.getContentWidth(t)>e}getAvailableHeight(e,t,n){return e-(this.hasHorizontalScrollbar(t,n)?this.H_SCROLLBAR_PADDING:0)}computeMaxScrollYWithPadding(e,t,n){let r=this.getContentHeight(),i=this.getAvailableHeight(e,t,n);return Math.max(0,r-i)}};const D=_(`RenderPipeline`);var O=class{constructor(){this.renderers=new Map,this.renderOrder=[`background`,`tracks`,`timeline`,`guideLines`,`indicator`,`interaction`,`scrollbar`,`overlay`],this.stats={layerTimes:{},totalTime:0,renderedLayers:0,skippedLayers:0}}registerRenderer(e,t){this.renderers.set(e,t)}unregisterRenderer(e){this.renderers.delete(e)}setRenderOrder(e){this.renderOrder=e}render(e,t={}){let n=performance.now(),{forceFullRender:r=!1,dirtyLayers:i,skipPerfMeasure:a=!1}=t;D.debugStyled(b.pipeline,`▶ Render Start`,`forceFullRender=${r}`,i?`dirtyLayers=[${Array.from(i).join(`, `)}]`:`dirtyLayers=all`),this.stats.renderedLayers=0,this.stats.skippedLayers=0,this.stats.layerTimes={};for(let t of this.renderOrder){let n=this.renderers.get(t);if(!n)continue;if(!this.shouldRenderLayer(t,n,e,r,i)){this.stats.skippedLayers++,D.debugStyled(b.pipelineSkip,` ⊘ Layer "${t}" skipped`);continue}let o=a?0:performance.now();D.debugStyled(b.pipelineLayer,` ● Layer "${t}" rendering...`);try{n.render(e),this.stats.renderedLayers++}catch(e){D.error(`Error rendering layer "${t}":`,e)}a||(this.stats.layerTimes[t]=performance.now()-o)}return this.stats.totalTime=performance.now()-n,this.prevContext=e,D.debugStyled(b.pipeline,`◀ Render End`,`rendered=${this.stats.renderedLayers}, skipped=${this.stats.skippedLayers}, time=${this.stats.totalTime.toFixed(2)}ms`),{...this.stats}}shouldRenderLayer(e,t,n,r,i){return r?!0:i?!!i.has(e):t.shouldRender&&this.prevContext?t.shouldRender(n,this.prevContext):!0}getStats(){return{...this.stats}}clearPrevContext(){this.prevContext=void 0}getRegisteredRenderers(){return this.renderers}},k=class{constructor(){this.name=`Timeline`,this.layer=`timeline`}render(e){let{ctx:t,config:n,state:r,width:i}=e;t.fillStyle=n.colors.timelineBackground,t.fillRect(0,0,i,n.timelineHeight);let a=[{threshold:10,main:10,sub:2,format:`HMS`},{threshold:8,main:30,sub:10,format:`HMS`},{threshold:5,main:60,sub:15,format:`HMS`},{threshold:3,main:300,sub:60,format:`HM`},{threshold:2,main:600,sub:120,format:`HM`},{threshold:1,main:1800,sub:600,format:`HM`},{threshold:.5,main:3600,sub:900,format:`H`},{threshold:0,main:7200,sub:1800,format:`H`}],o=a.find(e=>r.zoomLevel>=e.threshold)||a[a.length-1],s=n.startTime+(r.scrollX-n.startPaddingTime)/(n.secondWidth*r.zoomLevel),c=s+i/(n.secondWidth*r.zoomLevel),l=Math.max(n.startTime,Math.floor(s)),u=Math.min(n.endTime+n.endPaddingTime,Math.ceil(c));this.renderMainTicks(t,n,r,o,l,u,i),this.renderSubTicks(t,n,r,o,l,u,i),r.zoomLevel>=10&&this.renderMicroTicks(t,n,r,o,l,u,i)}renderMainTicks(e,t,n,r,i,a,o){let s=r.main,c=Math.floor(i/s)*s,l=-80;e.strokeStyle=t.colors.timelineGrid,e.lineWidth=1.5,e.fillStyle=t.colors.timelineText,e.font=`12px Arial`;for(let i=c;i<=a;i+=s){let a=i-t.startTime,s=t.startPaddingTime+a*t.secondWidth*n.zoomLevel-n.scrollX;if(s>=-50&&s<=o+50){let n=i>t.endTime;s-l>=80&&(e.strokeStyle=n?`rgba(150, 155, 165, 0.3)`:t.colors.timelineGrid,e.beginPath(),e.moveTo(s,0),e.lineTo(s,20),e.stroke(),e.fillStyle=n?`rgba(150, 155, 165, 0.4)`:t.colors.timelineText,e.textAlign=`center`,e.fillText(this.formatTime(i,r.format),s+28,20),l=s)}}}renderSubTicks(e,t,n,r,i,a,o){let s=r.sub,c=r.main,l=Math.floor(i/s)*s;e.lineWidth=1,e.strokeStyle=t.colors.timelineSubGrid;for(let r=l;r<=a;r+=s){if(r%c===0)continue;let i=r-t.startTime,a=t.startPaddingTime+i*t.secondWidth*n.zoomLevel-n.scrollX;a>=0&&a<=o&&(e.globalAlpha=r>t.endTime?.3:.75,e.beginPath(),e.moveTo(a,0),e.lineTo(a,8),e.stroke(),e.globalAlpha=1)}}renderMicroTicks(e,t,n,r,i,a,o){let s=r.sub/2,c=Math.floor(i/s)*s;e.lineWidth=1,e.strokeStyle=t.colors.timelineSubGrid,e.globalAlpha=.3;for(let i=c;i<=a;i+=s){if(i%r.sub===0)continue;let a=i-t.startTime,s=t.startPaddingTime+a*t.secondWidth*n.zoomLevel-n.scrollX;s>=0&&s<=o&&(e.beginPath(),e.moveTo(s,0),e.lineTo(s,4),e.stroke())}e.globalAlpha=1}formatTime(e,t){let n=Math.floor(e/3600),r=Math.floor(e%3600/60),i=Math.floor(e%60);switch(t){case`HMS`:return`${n.toString().padStart(2,`0`)}:${r.toString().padStart(2,`0`)}:${i.toString().padStart(2,`0`)}`;case`HM`:return`${n.toString().padStart(2,`0`)}:${r.toString().padStart(2,`0`)}`;case`H`:return`${n.toString().padStart(2,`0`)}:00`;default:return`${n.toString().padStart(2,`0`)}:${r.toString().padStart(2,`0`)}`}}shouldRender(e,t){if(!t)return!0;let{config:n,state:r}=e,{config:i,state:a}=t;return r.zoomLevel!==a.zoomLevel||r.scrollX!==a.scrollX||n.startTime!==i.startTime||n.endTime!==i.endTime||n.timelineHeight!==i.timelineHeight}};const A=_(`EventsRenderer`);var j=class{renderEvents(e,t,n,r,i,a,o,s){let l=s??a.width,u=n.tracks[r],d=Math.max(5,t.trackHeight*.0625),f=t.trackHeight-d*2,p=t.eventTextStyle,m=p.titleFontSize===`auto`?Math.max(10,Math.min(14,t.trackHeight*.175)):p.titleFontSize,h=p.timeFontSize===`auto`?Math.max(8,Math.min(12,t.trackHeight*.15)):p.timeFontSize;A.debugStyled(b.eventRender,`Track ${r}: ${u.events.length} events`);for(let s=0;s<u.events.length;s++){let g=u.events[s];if(n.draggingEvent&&n.draggingEvent.isDragging&&n.draggingEvent.trackIndex===r&&n.draggingEvent.eventIndex===s){A.debugStyled(b.eventSkip,` ⊘ Event[${s}] "${g.title}" skipped (dragging)`);continue}let _=t.startPaddingTime+(g.startTime-t.startTime)*t.secondWidth*n.zoomLevel-n.scrollX,v=g.duration*t.secondWidth*n.zoomLevel;if(_+v<0||_>l){A.debugStyled(b.eventSkip,` ⊘ Event[${s}] "${g.title}" culled (out of viewport)`);continue}A.debugStyled(b.eventInfo,` ● Event[${s}]`,{title:g.title,startTime:g.startTime,endTime:g.endTime,duration:g.duration,x:_.toFixed(1),width:v.toFixed(1)});let y=n.selectedEvent&&n.selectedEvent.trackIndex===r&&n.selectedEvent.eventIndex===s,x=n.highlightedEvent&&n.highlightedEvent.trackIndex===r&&n.highlightedEvent.eventIndex===s,S=n.timeIndicatorHighlightedEvents.some(e=>e.trackIndex===r&&e.eventIndex===s),C=n.timeIndicatorPosition,w=C>g.startTime&&C<g.endTime,T=!n.isManualSelection&&S&&w,E=y||x||T;e.save();let D=t.eventBlockStyle.borderRadius;e.fillStyle=g.color,D>0?(c(e,_,i+d,v,f,D),e.fill()):e.fillRect(_,i+d,v,f),E&&(e.strokeStyle=t.colors.eventBorderSelected,e.lineWidth=2,t.eventBlockStyle.enableSelectionGlow&&(e.shadowColor=t.colors.eventBorderSelected,e.shadowBlur=t.eventBlockStyle.selectionGlowBlur),D>0?(c(e,_,i+d,v,f,D),e.stroke()):e.strokeRect(_,i+d,v,f),e.shadowBlur=0),E&&(e.fillStyle=t.colors.eventOverlay,D>0?(c(e,_,i+d,v,f,D),e.fill()):e.fillRect(_,i+d,v,f)),e.restore(),o&&o.emitEvent(`render:event:media`,e,a,t,n,r,s,_,i,v,d,f),this.drawEventText(e,t,g,_,i,v,d,m,h,p),t.enableEventResize&&this.drawResizeHandles(e,t,n,r,s,_,i,v,f,d),t.showEventDurationLabel&&E&&this.drawEventDurationLabel(e,t,g,_,i,v,d),t.enableEventSplit&&n.hoveredSplitLine&&!n.draggingEvent&&!n.resizingEvent&&!n.draggingTimeIndicator&&this.drawSplitLine(e,t,n,r,s,i,d,f)}}truncateText(e,t,n){if(n<=0)return``;if(e.measureText(t).width<=n)return t;if(e.measureText(`...`).width>=n)return`...`;let r=0,i=t.length,a=``;for(;r<i;){let o=Math.floor((r+i+1)/2),s=t.substring(0,o)+`...`;e.measureText(s).width<=n?(a=s,r=o):i=o-1}return a||`...`}drawEventText(e,t,n,r,i,a,o,s,c,u){let d=u.titleColor||t.colors.eventText,f=u.timeColor||t.colors.eventText,p={left:r+10,right:r+a-10,center:r+a/2}[u.textAlign]??r+a/2,m={top:i+o+s,middle:i+t.trackHeight/2,bottom:i+t.trackHeight-o}[u.verticalAlign]??i+o;e.textAlign=u.textAlign;let h=u.showTitle&&t.trackHeight>=u.minHeightForTitle,g=u.showTime&&t.trackHeight>=u.minHeightForTime,_=l(n.startTime,n.endTime),v=a-20;if(h){e.fillStyle=d,e.font=`${u.titleFontWeight} ${s}px ${u.titleFontFamily}`;let t=g?m-s/2+u.titleOffsetY:m+u.titleOffsetY,r=this.truncateText(e,n.title,v);e.fillText(r,p,t)}if(g){e.fillStyle=f,e.font=`${u.timeFontWeight} ${c}px ${u.timeFontFamily}`;let t=h?m+c+u.timeOffsetY:m+u.timeOffsetY,n=this.truncateText(e,_,v);e.fillText(n,p,t)}}drawResizeHandles(e,t,n,r,i,a,o,s,c,l){let u=n.hoveredResizeHandle&&n.hoveredResizeHandle.trackIndex===r&&n.hoveredResizeHandle.eventIndex===i,d=n.resizingEvent&&n.resizingEvent.trackIndex===r&&n.resizingEvent.eventIndex===i;if(n.selectedEvent&&n.selectedEvent.trackIndex===r&&n.selectedEvent.eventIndex===i||u||d){let r=t.resizeHandleWidth,i=`rgba(255, 255, 255, 0.8)`,f=`rgba(255, 255, 255, 1)`,p=u&&n.hoveredResizeHandle.edge===`left`,m=d&&n.resizingEvent.edge===`left`;e.fillStyle=p||m?f:i,e.fillRect(a-r/2,o+l,r,c);let h=u&&n.hoveredResizeHandle.edge===`right`,g=d&&n.resizingEvent.edge===`right`;e.fillStyle=h||g?f:i,e.fillRect(a+s-r/2,o+l,r,c)}}drawSplitLine(e,t,n,r,i,a,o,s){let c=n.hoveredSplitLine;if(c.trackIndex===r&&c.eventIndex===i){let r=(c.splitTime+t.startPaddingTime-t.startTime)*t.secondWidth*n.zoomLevel-n.scrollX;e.save(),e.strokeStyle=`rgba(255, 255, 0, 0.8)`,e.lineWidth=2,e.setLineDash([5,5]),e.beginPath(),e.moveTo(r,a+o),e.lineTo(r,a+o+s),e.stroke(),e.setLineDash([]),e.fillStyle=`rgba(255, 255, 0, 1)`,e.beginPath(),e.arc(r,a+o,4,0,Math.PI*2),e.fill(),e.beginPath(),e.arc(r,a+o+s,4,0,Math.PI*2),e.fill();let i=f(c.splitTime);e.font=`bold 11px Arial`,e.fillStyle=`rgba(255, 255, 0, 1)`,e.textAlign=`center`,e.fillText(`切割: ${i}`,r,a+o-5),e.restore()}}drawEventDurationLabel(e,t,n,r,a,o,s){e.save();let c=Math.round(n.duration*1e3)/1e3,l;l=t.formatEventDuration?t.formatEventDuration(c):i(c),e.font=`bold 11px Arial`,e.fillStyle=t.colors.eventDurationLabel,e.textAlign=`center`;let u=r+o/2,d=a+s-8;e.fillText(l,u,d),e.restore()}},M=class{constructor(){this.name=`Tracks`,this.layer=`tracks`}render(e){let{ctx:t,canvas:n,config:r,state:i,pluginManager:a,width:o,height:s}=e,c=r.startPaddingTime-i.scrollX,l=new j;for(let e=0;e<i.tracks.length;e++){let u=r.timelineHeight+r.firstTrackTopMargin+e*(r.trackHeight+r.trackMargin)-i.scrollY;if(u+r.trackHeight<r.timelineHeight||u>s)continue;let d;d=e===i.selectedTrack||i.highlightedEvent&&i.highlightedEvent.trackIndex===e||i.selectedEvent&&i.selectedEvent.trackIndex===e?r.colors.trackBackgroundSelected:r.colors.trackBackgroundOdd&&r.colors.trackBackgroundEven?e%2==0?r.colors.trackBackgroundOdd:r.colors.trackBackgroundEven:r.colors.trackBackground,t.fillStyle=d;let f=o-c;f>0&&t.fillRect(c,u,f,r.trackHeight),l.renderEvents(t,r,i,e,u,n,a,o)}}shouldRender(e,t){if(!t)return!0;let{config:n,state:r}=e,{config:i,state:a}=t;return r.tracks!==a.tracks||r.scrollY!==a.scrollY||r.scrollX!==a.scrollX||r.zoomLevel!==a.zoomLevel||r.selectedEvent!==a.selectedEvent||r.highlightedEvent!==a.highlightedEvent||n.trackHeight!==i.trackHeight||n.trackMargin!==i.trackMargin}},N=class{constructor(){this.name=`Scrollbar`,this.layer=`scrollbar`}render(e){let{ctx:t,config:n,state:r,width:i,height:a}=e;this.drawVerticalScrollbar(t,n,r,i,a),this.drawHorizontalScrollbar(t,n,r,i,a)}drawVerticalScrollbar(e,t,n,r,i){let a=t.startPaddingTime+(t.endTime+t.endPaddingTime-t.startTime)*t.secondWidth*n.zoomLevel>r?13:0,o=t.timelineHeight+t.firstTrackTopMargin+n.tracks.length*(t.trackHeight+t.trackMargin);if(o>i-a){let s=r-8-5,l=t.timelineHeight,u=i-t.timelineHeight-a-5;e.fillStyle=t.colors.scrollbarTrack,c(e,s,l,8,u,4);let d=(i-a-5)/o,f=Math.max(30,u*d),p=o-i+a+5,m=n.scrollY/p,h=l+(u-f)*m;e.fillStyle=n.draggingScrollbar?t.colors.scrollbarHandleHover:t.colors.scrollbarHandle,c(e,s,h,8,f,4),e.fillStyle=t.colors.scrollbarHandleHighlight,c(e,s,h,8,f/2,4),n.draggingScrollbar&&(e.strokeStyle=t.colors.scrollbarBorder,e.lineWidth=1,c(e,s,h,8,f,4,!0))}}drawHorizontalScrollbar(e,t,n,r,i){let a=t.startPaddingTime+(t.endTime+t.endPaddingTime-t.startTime)*t.secondWidth*n.zoomLevel;if(a<=r)return;let o=t.timelineHeight+t.firstTrackTopMargin+n.tracks.length*(t.trackHeight+t.trackMargin)>i?13:0,s=i-8-5,l=r-o;e.fillStyle=t.colors.scrollbarTrack,c(e,0,s,l,8,4);let u=r/a,d=Math.max(30,l*u),f=a-r,p=n.scrollX/f,m=0+(l-d)*p;e.fillStyle=n.draggingHorizontalScrollbar?t.colors.scrollbarHandleHover:t.colors.scrollbarHandle,c(e,m,s,d,8,4),e.fillStyle=t.colors.scrollbarHandleHighlight,c(e,m,s,d/2,8,4),n.draggingHorizontalScrollbar&&(e.strokeStyle=t.colors.scrollbarBorder,e.lineWidth=1,c(e,m,s,d,8,4,!0))}shouldRender(e,t){if(!t)return!0;let{state:n}=e,{state:r}=t;return n.scrollY!==r.scrollY||n.scrollX!==r.scrollX||n.draggingScrollbar!==r.draggingScrollbar||n.draggingHorizontalScrollbar!==r.draggingHorizontalScrollbar}},P=class{constructor(){this.name=`Indicator`,this.layer=`indicator`}render(e){let{ctx:t,config:n,state:r,width:i,height:a}=e;if(!n.enableTimeIndicator)return;let o=n.startPaddingTime+(r.timeIndicatorPosition-n.startTime)*n.secondWidth*r.zoomLevel-r.scrollX;if(o<-10||o>i+10)return;t.strokeStyle=n.colors.timeIndicator,t.lineWidth=n.timeIndicatorWidth,t.beginPath(),t.moveTo(o,n.timelineHeight),t.lineTo(o,a),t.stroke();let s=n.timeIndicatorHeadSize,c=n.timeIndicatorTriangleHeight,l=n.timelineHeight-s-c;t.fillStyle=n.colors.timeIndicator,t.fillRect(o-s/2,l,s,s),t.beginPath(),t.moveTo(o-s/2,l+s),t.lineTo(o+s/2,l+s),t.lineTo(o,l+s+c),t.closePath(),t.fill()}shouldRender(e,t){if(!t)return!0;let{config:n,state:r}=e,{config:i,state:a}=t;return n.enableTimeIndicator?r.timeIndicatorPosition!==a.timeIndicatorPosition||r.draggingTimeIndicator!==a.draggingTimeIndicator||r.scrollX!==a.scrollX||r.zoomLevel!==a.zoomLevel||n.timelineHeight!==i.timelineHeight:!1}},ee=class{constructor(){this.name=`GuideLines`,this.layer=`guideLines`}render(e){let{ctx:t,config:n,state:r,width:i,height:a}=e;if(t.save(),r.guideLines.length>0){t.strokeStyle=n.colors.guideLine,t.lineWidth=2,t.setLineDash([5,5]);for(let e of r.guideLines){let o=n.startPaddingTime+(e.time-n.startTime)*n.secondWidth*r.zoomLevel-r.scrollX;o<-10||o>i+10||(t.beginPath(),t.moveTo(o,n.timelineHeight),t.lineTo(o,a),t.stroke(),t.setLineDash([]),t.fillStyle=n.colors.guideLineLabel,t.font=`bold 11px Arial`,t.textAlign=`center`,t.fillText(f(e.time),o,n.timelineHeight-5),t.setLineDash([5,5]))}}if(r.dragTimeReference){let e=n.startPaddingTime+(r.dragTimeReference.time-n.startTime)*n.secondWidth*r.zoomLevel-r.scrollX;if(e>=-10&&e<=i+10){let i=r.dragTimeReference.y-r.scrollY;t.strokeStyle=n.colors.dragTimeReferenceLine,t.lineWidth=2,t.setLineDash([8,4]),t.beginPath(),t.moveTo(e,n.timelineHeight),t.lineTo(e,i),t.stroke(),t.setLineDash([]),t.fillStyle=n.colors.dragTimeReferenceLabel,t.font=`bold 12px Arial`,t.textAlign=`center`;let a=f(r.dragTimeReference.time),o=t.measureText(a).width;t.fillStyle=n.colors.dragTimeReferenceLabelBackground,t.fillRect(e-o/2-4,n.timelineHeight-14-4-5,o+8,22),t.fillStyle=n.colors.dragTimeReferenceLabel,t.fillText(a,e,n.timelineHeight-5)}}t.restore()}shouldRender(e,t){if(!t)return!0;let{state:n}=e,{state:r}=t;return n.guideLines!==r.guideLines||n.dragTimeReference!==r.dragTimeReference||n.scrollX!==r.scrollX||n.scrollY!==r.scrollY||n.zoomLevel!==r.zoomLevel}},F=class{constructor(){this.name=`Interaction`,this.layer=`interaction`}render(e){let{ctx:t,config:n,state:r}=e;!r.draggingEvent||!r.draggingEvent.isDragging||(this.renderDragPreview(t,n,r),this.renderDraggingEvent(t,n,r))}renderDragPreview(e,t,n){if(!n.draggingEvent||!n.tracks[n.draggingEvent.trackIndex])return;let r=n.tracks[n.draggingEvent.trackIndex].events[n.draggingEvent.eventIndex];if(!r)return;let i=n.draggingEvent.currentMouseY||0,a=n.draggingEvent.canMove!==!1,o=Math.floor((i-t.timelineHeight-t.firstTrackTopMargin)/(t.trackHeight+t.trackMargin)),s=Math.max(0,Math.min(n.tracks.length-1,o)),l=t.timelineHeight+t.firstTrackTopMargin+s*(t.trackHeight+t.trackMargin),u=(n.draggingEvent.currentMouseX||0)-n.dragOffsetX,d=r.duration*t.secondWidth*n.zoomLevel,f=Math.max(5,t.trackHeight*.0625),p=t.trackHeight-f*2,m=t.eventBlockStyle.borderRadius;e.save(),a?(e.fillStyle=t.colors.dragPreviewValid,e.strokeStyle=t.colors.dragPreviewBorderValid):(e.fillStyle=t.colors.dragPreviewInvalid,e.strokeStyle=t.colors.dragPreviewBorderInvalid),e.lineWidth=2,e.setLineDash([5,5]),e.globalAlpha=.6,m>0?(c(e,u,l-n.scrollY+f,d,p,m),e.fill(),e.stroke()):(e.fillRect(u,l-n.scrollY+f,d,p),e.strokeRect(u,l-n.scrollY+f,d,p)),e.restore()}renderDraggingEvent(e,t,n){if(!n.draggingEvent||!n.tracks[n.draggingEvent.trackIndex].events)return;let r=n.tracks[n.draggingEvent.trackIndex].events[n.draggingEvent.eventIndex];if(!r)return;let i=n.draggingEvent.currentMouseX||0,a=n.draggingEvent.currentMouseY||0,o=i-n.dragOffsetX,s=a-n.dragOffsetY-n.scrollY,l=r.duration*t.secondWidth*n.zoomLevel,u=Math.max(5,t.trackHeight*.0625),d=t.trackHeight-u*2;e.save();let f=t.eventBlockStyle.borderRadius;e.fillStyle=r.color,f>0?(c(e,o,s+u,l,d,f),e.fill()):e.fillRect(o,s+u,l,d),e.strokeStyle=t.colors.eventBorderSelected,e.lineWidth=2,t.eventBlockStyle.enableSelectionGlow&&(e.shadowColor=t.colors.eventBorderSelected,e.shadowBlur=t.eventBlockStyle.selectionGlowBlur),f>0?(c(e,o,s+u,l,d,f),e.stroke()):e.strokeRect(o,s+u,l,d),e.shadowBlur=0,e.fillStyle=t.colors.eventOverlay,f>0?(c(e,o,s+u,l,d,f),e.fill()):e.fillRect(o,s+u,l,d),e.restore(),this.renderEventText(e,t,r,o,s,l,u)}renderEventText(e,t,n,r,i,a,o){let s=t.eventTextStyle,c=s.titleColor||t.colors.eventText,l=s.timeColor||t.colors.eventText,u={left:r+10,right:r+a-10,center:r+a/2}[s.textAlign]??r+a/2,d={top:i+o,middle:i+t.trackHeight/2,bottom:i+t.trackHeight-o}[s.verticalAlign]??i+o;e.textAlign=s.textAlign;let p=s.showTitle&&t.trackHeight>=s.minHeightForTitle,m=s.showTime&&t.trackHeight>=s.minHeightForTime,h=s.titleFontSize===`auto`?Math.max(10,Math.min(14,t.trackHeight*.175)):s.titleFontSize,g=s.timeFontSize===`auto`?Math.max(8,Math.min(12,t.trackHeight*.15)):s.timeFontSize,_=`${f(n.startTime)} - ${f(n.endTime)}`;if(p){e.fillStyle=c,e.font=`${s.titleFontWeight} ${h}px ${s.titleFontFamily}`;let t=m?d-(typeof h==`number`?h:14)/2+s.titleOffsetY:d+s.titleOffsetY;e.fillText(n.title,u,t)}if(m){e.fillStyle=l,e.font=`${s.timeFontWeight} ${g}px ${s.timeFontFamily}`;let t=p?d+(typeof g==`number`?g:12)+s.timeOffsetY:d+s.timeOffsetY;e.fillText(_,u,t)}}shouldRender(e,t){if(!t)return!0;let{state:n}=e,{state:r}=t;return!!(n.draggingEvent!==r.draggingEvent||n.draggingEvent&&r.draggingEvent&&(n.draggingEvent.currentMouseX!==r.draggingEvent.currentMouseX||n.draggingEvent.currentMouseY!==r.draggingEvent.currentMouseY))}};function I(e,t,n,r,i,a){return{ctx:e,canvas:t,config:n,state:r,dpr:i,width:t.width/i,height:t.height/i,pluginManager:a}}const L=_(`DirtyCheck`);var R=class{constructor(e,t,n,r,i){this.cachedLogicalWidth=0,this.cachedLogicalHeight=0,this.cacheValid=!1,this.dirtyLayers=new Set([`background`,`tracks`,`timeline`,`guideLines`,`indicator`,`scrollbar`,`overlay`,`interaction`]),this.lastLayerTimes={},this.isFirstRender=!0,this.canvas=e,this.ctx=t,this.config=n,this.state=r,this.pluginManager=i,this.dpr=window.devicePixelRatio||1,this.logicalCanvas={width:0,height:0,getContext:this.canvas.getContext.bind(this.canvas)},this.viewport=new E(this.config,this.state),this.renderPipeline=new O,this.renderPipeline.registerRenderer(`timeline`,new k),this.renderPipeline.registerRenderer(`tracks`,new M),this.renderPipeline.registerRenderer(`guideLines`,new ee),this.renderPipeline.registerRenderer(`indicator`,new P),this.renderPipeline.registerRenderer(`scrollbar`,new N),this.renderPipeline.registerRenderer(`interaction`,new F)}setCanvasSize(e,t){let n=Math.floor(e*this.dpr),r=Math.floor(t*this.dpr);if(Math.abs(this.canvas.width-n)<1&&Math.abs(this.canvas.height-r)<1)return;this.canvas.width=n,this.canvas.height=r,this.canvas.style.width=`${e}px`,this.canvas.style.height=`${t}px`,this.invalidateCache();let i=this.getContentHeight(),a=Math.max(0,i-this.getCachedLogicalHeight());this.state.scrollY=Math.max(0,Math.min(a,this.state.scrollY)),this.state.zoomLevel<this.config.minAutoFitZoom&&(this.state.zoomLevel=this.config.minAutoFitZoom,this.state.scrollX=0),this.dirtyLayers.add(`tracks`),this.dirtyLayers.add(`timeline`),this.dirtyLayers.add(`indicator`),this.dirtyLayers.add(`scrollbar`),this.draw()}getCanvasLogicalWidth(){return this.canvas.width/this.dpr}getCanvasLogicalHeight(){return this.canvas.height/this.dpr}getCachedLogicalWidth(){return this.cacheValid||=(this.cachedLogicalWidth=this.canvas.width/this.dpr,this.cachedLogicalHeight=this.canvas.height/this.dpr,!0),this.cachedLogicalWidth}getCachedLogicalHeight(){return this.cacheValid||=(this.cachedLogicalWidth=this.canvas.width/this.dpr,this.cachedLogicalHeight=this.canvas.height/this.dpr,!0),this.cachedLogicalHeight}invalidateCache(){this.cacheValid=!1}draw(){if(this.dirtyLayers.size===0&&!this.isFirstRender)return;this.pluginManager.measureStart(`draw`);let e=this.ctx;e.save(),e.setTransform(1,0,0,1,0,0),e.clearRect(0,0,this.canvas.width,this.canvas.height),e.restore(),e.save(),e.scale(this.dpr,this.dpr);let t=this.canvas.width/this.dpr,n=this.canvas.height/this.dpr;this.logicalCanvas.width=t,this.logicalCanvas.height=n;let r=this.logicalCanvas,i=performance.now();this.pluginManager.renderBackground(e,r,this.config,this.state),this.lastLayerTimes.background=performance.now()-i;let a=I(e,this.canvas,this.config,this.state,this.dpr,this.pluginManager);this.dirtyLayers.size===0&&this.isFirstRender,this.renderPipeline.render(a,{forceFullRender:!0,dirtyLayers:void 0}),this.isFirstRender&&=!1;let o=this.renderPipeline.getStats();this.lastLayerTimes={...this.lastLayerTimes,...o.layerTimes},i=performance.now(),this.pluginManager.renderOverlay(e,r,this.config,this.state),this.lastLayerTimes.overlay=performance.now()-i,this.pluginManager.measureEnd(`draw`),e.restore(),this.dirtyLayers.clear()}getContentWidth(e){return this.viewport.getContentWidth(e)}getContentHeight(){return this.viewport.getContentHeight()}computeMaxScrollX(e){return this.viewport.computeMaxScrollX(e,this.getCachedLogicalWidth())}computeMaxScrollY(){return this.viewport.computeMaxScrollYWithPadding(this.getCachedLogicalHeight(),this.getCachedLogicalWidth(),this.state.zoomLevel)}hasHorizontalScrollbar(){return this.viewport.hasHorizontalScrollbar(this.getCachedLogicalWidth(),this.state.zoomLevel)}getAvailableHeight(){return this.viewport.getAvailableHeight(this.getCachedLogicalHeight(),this.getCachedLogicalWidth(),this.state.zoomLevel)}invalidateLayoutCache(){this.viewport.invalidateCache()}markDirty(e){L.debugStyled(b.dataUpdate,`✓ Marking layers dirty: [${e.join(`, `)}]`);for(let t of e)this.dirtyLayers.add(t)}markAllDirty(){L.debugStyled(b.dataUpdate,`✓ Marking ALL layers dirty`),this.dirtyLayers=new Set([`background`,`tracks`,`timeline`,`guideLines`,`indicator`,`scrollbar`,`overlay`,`interaction`])}getLastLayerTimes(){return{...this.lastLayerTimes}}},z=class{constructor(e){this.timeline=e}createContext(e){let t=this.timeline.getCanvas().getBoundingClientRect(),n=this.timeline.state;return{canvasX:e.clientX-t.left,canvasY:e.clientY-t.top,logicalX:e.clientX-t.left+n.scrollX,logicalY:e.clientY-t.top+n.scrollY,originalEvent:e,canvasWidth:t.width,canvasHeight:t.height}}handleMouseDown(e){return null}handleMouseMove(e){return null}handleMouseUp(e){return null}handleContextMenu(e){return null}};const B=_(`DraggingState`);var V=class extends z{constructor(e){super(e),this.name=`Dragging`,this.MOVE_THRESHOLD=5}onEnter(){this.timeline.beginIndexBatch()}onExit(){let e=this.timeline.state;e.guideLines=[],e.dragTimeReference=null,this.timeline.endIndexBatch(),this.timeline.autoRemoveEmptyLastTrack()}handleMouseMove(t){let{logicalX:n,logicalY:i}=t,o=this.timeline.config,s=this.timeline.state,c=this.timeline.getCanvas();if(!s.draggingEvent)return this.createIdleState();if(Math.sqrt((n-s.draggingEvent.startX)**2+(i-s.draggingEvent.startY)**2)>this.MOVE_THRESHOLD&&(s.draggingEvent.isDragging=!0),!s.draggingEvent.isDragging)return c.style.cursor=`move`,null;let{trackIndex:l,eventIndex:u}=s.draggingEvent;if(l<0||l>=s.tracks.length||u<0||u>=s.tracks[l].events.length)return B.warn(`当前错误的状态:`,{value:s.draggingEvent}),s.draggingEvent=null,this.createIdleState();let d=s.tracks[l].events[u];this.timeline.setStatus(`正在拖动: ${d.title}`);let f=(n-s.draggingEvent.startX)/(o.secondWidth*s.zoomLevel),p=s.draggingEvent.originalStartTime+f,m=Math.floor((i-o.timelineHeight-o.firstTrackTopMargin)/(o.trackHeight+o.trackMargin));if(o.autoAddTrack&&m>=s.tracks.length){let e={id:s.tracks.length,events:[]};s.tracks.push(e),this.timeline.setStatus(`自动新增轨道 ${s.tracks.length}`),this.timeline.callbacks.onTrackAdd&&this.timeline.callbacks.onTrackAdd(e)}m=Math.max(0,Math.min(s.tracks.length-1,m)),s.guideLines=this.timeline.calculateGuideLines(l,u,m,p,d.duration);let h=this.timeline.snapToGuideLines(p,d.duration);if(h!==null)p=h;else if(s.snapEnabled)if(o.enableTimeIndicator&&s.timeIndicatorSnapEnabled){let t=g(s.timeIndicatorPosition,o.startTime,o.startPaddingTime,o.secondWidth,s.zoomLevel,s.scrollX),n=o.startPaddingTime+(p-o.startTime)*o.secondWidth*s.zoomLevel-s.scrollX;if(Math.abs(n-t)<o.timeIndicatorSnapThreshold)p=s.timeIndicatorPosition;else{let t=a(s.zoomLevel,o.snapInterval,o.snapToSeconds,o.secondPrecisionZoomThreshold);p=e(p,t)}}else{let t=a(s.zoomLevel,o.snapInterval,o.snapToSeconds,o.secondPrecisionZoomThreshold);p=e(p,t)}p=Math.max(o.startTime,Math.min(o.endTime-d.duration,p));let _=o.timelineHeight+o.firstTrackTopMargin+m*(o.trackHeight+o.trackMargin)+o.trackHeight/2;s.dragTimeReference={time:p,y:_};let v=this.timeline.canMoveEvent(l,u,m,p,d.duration);if(v&&(d.startTime=p,d.endTime=r(p+d.duration),this.timeline.invalidateIndexTrack(l),m!==l)){let e=s.tracks[l].events.splice(u,1)[0];s.tracks[m].events.push(e),s.draggingEvent.trackIndex=m,s.draggingEvent.eventIndex=s.tracks[m].events.length-1,s.selectedTrack=m,s.selectedEvent&&s.selectedEvent.trackIndex===l&&s.selectedEvent.eventIndex===u&&(s.selectedEvent={trackIndex:m,eventIndex:s.tracks[m].events.length-1}),this.timeline.invalidateIndexTrack(m),this.timeline.invalidateIndexTrack(l)}return s.draggingEvent&&(s.draggingEvent.currentMouseX=n,s.draggingEvent.currentMouseY=i,s.draggingEvent.canMove=v),this.timeline.notifyChange(`events:move`),null}handleMouseUp(e){let t=this.timeline.state;if(!t.draggingEvent)return this.createIdleState();let{trackIndex:n,eventIndex:r,originalTrackIndex:i,originalEventIndex:a}=t.draggingEvent;if(n<0||n>=t.tracks.length)return B.warn(`无法找到拖拽的事件, 放弃操作`,{trackIndex:n,eventIndex:r}),t.draggingEvent=null,this.createIdleState();let o=t.tracks[n]?.events[r];if(!o)return B.warn(`无法找到拖拽的事件, 放弃操作`,{trackIndex:n,eventIndex:r}),t.draggingEvent=null,this.createIdleState();let s=t.selectedEvent&&t.selectedEvent.trackIndex===i&&t.selectedEvent.eventIndex===a;return t.draggingEvent.isDragging?(this.timeline.setStatus(`已放置: ${o.title} (${this.timeline.formatTime(o.startTime)} - ${this.timeline.formatTime(o.endTime)})`),s&&(t.selectedEvent={trackIndex:n,eventIndex:r}),this.timeline.callbacks.onEventMove&&this.timeline.callbacks.onEventMove({trackIndex:n,eventIndex:r,event:u(o),fromTrackIndex:i})):(t.selectedEvent={trackIndex:n,eventIndex:r},this.timeline.setStatus(`已选中: ${o.title}`),this.timeline.callbacks.onEventClick&&this.timeline.callbacks.onEventClick({trackIndex:n,eventIndex:r,event:u(o),trackName:`轨道 ${n+1}`,formattedTimeRange:`${this.timeline.formatTime(o.startTime)} - ${this.timeline.formatTime(o.endTime)}`})),t.draggingEvent=null,this.timeline.notifyChange(`events:move`),this.createIdleState()}createIdleState(){return new G(this.timeline)}},H=class extends z{constructor(e){super(e),this.name=`Resizing`}onEnter(){this.timeline.beginIndexBatch()}onExit(){this.timeline.endIndexBatch()}handleMouseMove(t){let{logicalX:n}=t,i=this.timeline.config,o=this.timeline.state;if(!o.resizingEvent)return this.createIdleState();let{trackIndex:s,eventIndex:c,edge:l,originalStartTime:u,originalDuration:d}=o.resizingEvent;if(s<0||s>=o.tracks.length||c<0||c>=o.tracks[s].events.length)return o.resizingEvent=null,this.createIdleState();let f=o.tracks[s].events[c],p=(n-o.resizingEvent.startX)/(i.secondWidth*o.zoomLevel);if(l===`left`){let t=u+p,n=r(u+d);if(o.snapEnabled){let n=a(o.zoomLevel,i.snapInterval,i.snapToSeconds,i.secondPrecisionZoomThreshold);t=e(t,n)}t=r(Math.max(i.startTime,t)),t=r(Math.min(t,n-i.minEventDuration));let l=r(n-t),m=!0;for(let e=0;e<o.tracks[s].events.length;e++){if(e===c)continue;let r=o.tracks[s].events[e],i=r.startTime,a=i+r.duration;if(t<a&&n>i){m=!1;break}}if(m){if(!this.timeline.canMoveEvent(s,c,s,t,l))return this.timeline.notifyChange(`events:update`),null;f.startTime=t,f.duration=r(l),f.endTime=n,this.timeline.invalidateIndexTrack(s)}}else{let t=d+p;if(o.snapEnabled){let n=a(o.zoomLevel,i.snapInterval,i.snapToSeconds,i.secondPrecisionZoomThreshold);t=r(e(u+t,n)-u)}else t=r(t);t=r(Math.max(i.minEventDuration,t)),t=r(Math.min(t,i.endTime-u));let n=u+t,l=!0;for(let e=0;e<o.tracks[s].events.length;e++){if(e===c)continue;let t=o.tracks[s].events[e],r=t.startTime;if(u<r+t.duration&&n>r){l=!1;break}}if(l){if(!this.timeline.canMoveEvent(s,c,s,u,t))return this.timeline.notifyChange(`events:update`),null;f.duration=r(t),f.endTime=r(u+t),this.timeline.invalidateIndexTrack(s)}}return this.timeline.notifyChange(`events:update`),this.timeline.setStatus(`调整大小: ${this.timeline.formatTime(f.startTime)} - ${this.timeline.formatTime(f.endTime)}`),null}handleMouseUp(e){let t=this.timeline.state;if(!t.resizingEvent)return this.createIdleState();let{trackIndex:n,eventIndex:r}=t.resizingEvent;if(n<0||n>=t.tracks.length||r<0||r>=t.tracks[n].events.length)return t.resizingEvent=null,this.createIdleState();let i=t.tracks[n].events[r];return t.resizingEvent=null,this.timeline.getCanvas().style.cursor=`default`,this.timeline.setStatus(`已调整事件大小: ${i.title}`),this.timeline.callbacks.onEventUpdate&&this.timeline.callbacks.onEventUpdate({type:`resize`,trackIndex:n,eventIndex:r,event:u(i)}),this.timeline.notifyChange(`events:update`),this.createIdleState()}createIdleState(){return new G(this.timeline)}},U=class extends z{constructor(e){super(e),this.name=`Scrolling`}handleMouseMove(e){let{canvasX:t,canvasY:n,canvasWidth:r,canvasHeight:i}=e,a=this.timeline.config,o=this.timeline.state;if(o.draggingScrollbar){let e=a.timelineHeight+a.firstTrackTopMargin+o.tracks.length*(a.trackHeight+a.trackMargin),t=i-(a.startPaddingTime+(a.endTime+a.endPaddingTime-a.startTime)*a.secondWidth*o.zoomLevel>r?13:0),s=t-a.timelineHeight-5,c=t/e,l=Math.max(30,s*c),u=Math.max(0,e-t),d=(n-a.timelineHeight-o.scrollbarDragOffset)/(s-l);return o.scrollY=Math.max(0,Math.min(u,d*u)),this.timeline.notifyChange(`scroll:y`),null}if(o.draggingHorizontalScrollbar){let e=a.startPaddingTime+(a.endTime+a.endPaddingTime-a.startTime)*a.secondWidth*o.zoomLevel,n=r,i=r/e,s=Math.max(30,n*i),c=Math.max(0,e-r),l=(t-o.horizontalScrollbarDragOffset)/(n-s);return o.scrollX=Math.max(0,Math.min(c,l*c)),this.timeline.notifyChange(`scroll:x`),null}return null}handleMouseUp(e){let t=this.timeline.state;return t.draggingScrollbar&&(t.draggingScrollbar=!1,this.timeline.setStatus(`就绪`)),t.draggingHorizontalScrollbar&&(t.draggingHorizontalScrollbar=!1,this.timeline.setStatus(`就绪`)),this.createIdleState()}createIdleState(){return new G(this.timeline)}},W=class extends z{constructor(e){super(e),this.name=`TimeIndicatorDrag`}handleMouseMove(t){let{canvasX:n}=t,r=this.timeline.config,i=this.timeline.state,o=this.timeline.getCanvas();if(!i.draggingTimeIndicator)return this.createIdleState();o.style.cursor=r.readOnly?`not-allowed`:`ew-resize`;let s=(n-i.timeIndicatorDragOffsetX+i.scrollX-r.startPaddingTime)/(r.secondWidth*i.zoomLevel)+r.startTime;if(i.snapEnabled){let t=a(i.zoomLevel,r.snapInterval,r.snapToSeconds,r.secondPrecisionZoomThreshold);s=e(s,t)}return s=Math.max(r.startTime,Math.min(r.endTime,s)),this.timeline.setTimeIndicator(s,!1),null}handleMouseUp(e){let t=this.timeline.state;return t.draggingTimeIndicator&&(t.draggingTimeIndicator=!1,this.timeline.setStatus(`时间指示器已放置: ${this.timeline.formatTime(t.timeIndicatorPosition)}`)),this.createIdleState()}createIdleState(){return new G(this.timeline)}},G=class extends z{constructor(e){super(e),this.name=`Idle`}handleMouseDown(e){let{canvasX:t,canvasY:n,logicalX:r,logicalY:i,canvasWidth:a,canvasHeight:o,originalEvent:s}=e,c=this.timeline.config,d=this.timeline.state,f=this.timeline.getCanvas(),p=c.readOnly;if(s.button===2)return null;if(d.contextMenuVisible){let e=d.contextMenuBounds;if(e){let r=e.x,i=e.y,a=e.width,o=e.height;if(t>=r&&t<=r+a&&n>=i&&n<=i+o){let t=Math.floor((n-i-e.padding)/e.itemHeight);if(t>=0&&t<c.contextMenuItems.length&&d.contextMenuEvent){let e=c.contextMenuItems[t],{trackIndex:n,eventIndex:r}=d.contextMenuEvent,i=d.tracks[n].events[r];if(i.readonly&&(e.type===`delete`||e.type===`edit`))return this.timeline.setStatus(`只读事件不可编辑或删除`),d.contextMenuVisible=!1,d.contextMenuEvent=null,this.timeline.notifyChange(`interaction:contextMenu`),null;this.timeline.callbacks.onContextMenu&&this.timeline.callbacks.onContextMenu({menuType:e.type,trackIndex:n,eventIndex:r,event:u(i)}),d.contextMenuVisible=!1,d.contextMenuEvent=null,this.timeline.notifyChange(`interaction:contextMenu`)}return null}else d.contextMenuVisible=!1,d.contextMenuEvent=null,this.timeline.notifyChange(`interaction:contextMenu`)}}let m=c.timelineHeight+c.firstTrackTopMargin+d.tracks.length*(c.trackHeight+c.trackMargin),h=this.timeline.getAvailableHeight();if(m>h){let e=a-8-5,r=c.timelineHeight,i=h-c.timelineHeight-5;if(t>=e&&t<=e+8&&n>=r&&n<=r+i){d.draggingScrollbar=!0;let e=h/m,t=Math.max(30,i*e),a=m-h,o=d.scrollY/a;return d.scrollbarDragOffset=n-(r+(i-t)*o),this.createScrollingState()}}let _=this.timeline.getContentWidthForZoom(d.zoomLevel);if(_>a){let e=o-8-5,r=a;if(n>=e&&n<=e+8&&t>=0&&t<=0+r){d.draggingHorizontalScrollbar=!0;let e=a/_,n=Math.max(30,r*e),i=_-a,o=d.scrollX/i;return d.horizontalScrollbarDragOffset=t-(0+(r-n)*o),this.createScrollingState()}}if(c.enableTimeIndicator&&!p){let e=g(d.timeIndicatorPosition,c.startTime,c.startPaddingTime,c.secondWidth,d.zoomLevel,d.scrollX),r=c.timeIndicatorHeadSize,i=c.timeIndicatorTriangleHeight,a=c.timelineHeight-r-i;if(t>=e-r/2&&t<=e+r/2&&n>=a&&n<=c.timelineHeight)return d.draggingTimeIndicator=!0,d.timeIndicatorDragOffsetX=t-e,this.createTimeIndicatorDragState()}if(i<c.timelineHeight)return null;if(c.enableEventResize&&!p){let e=this.timeline.getResizeHandle(r,i);if(e){let t=d.tracks[e.trackIndex].events[e.eventIndex];return t.readonly?(f.style.cursor=`not-allowed`,null):(d.resizingEvent={trackIndex:e.trackIndex,eventIndex:e.eventIndex,edge:e.edge,startX:r,originalStartTime:t.startTime,originalDuration:t.duration},this.createResizingState())}}let v=this.timeline.getEventAtPosition(t,n);if(v){let{trackIndex:e,eventIndex:t}=v,n=d.tracks[e].events[t],a=Date.now();if(d.lastClickEvent&&d.lastClickEvent.trackIndex===e&&d.lastClickEvent.eventIndex===t&&a-d.lastClickTime<300&&c.enableEventSplit){if(n.readonly)return this.timeline.setStatus(`只读事件不可切割`),d.lastClickTime=0,d.lastClickEvent=null,null;let i=(r-c.startPaddingTime)/(c.secondWidth*d.zoomLevel)+c.startTime;return this.timeline.splitEvent(e,t,i),d.lastClickTime=0,d.lastClickEvent=null,this.timeline.hideSplitLine(),null}if(d.lastClickEvent={trackIndex:e,eventIndex:t},d.lastClickTime=a,d.selectedEvent={trackIndex:e,eventIndex:t},d.isManualSelection=!0,d.highlightedEvent=null,d.selectedTrack=null,n.readonly||p)return f.style.cursor=`not-allowed`,this.timeline.setStatus(`已选中: ${n.title}`),this.timeline.callbacks.onEventHighlight&&this.timeline.callbacks.onEventHighlight({trackIndex:e,eventIndex:t,event:u(n)}),this.timeline.callbacks.onEventClick&&this.timeline.callbacks.onEventClick({trackIndex:e,eventIndex:t,event:u(n),trackName:`轨道 ${e+1}`,formattedTimeRange:l(n.startTime,n.endTime)}),this.timeline.notifyChange(`selection:change`),null;let o=c.startPaddingTime+(n.startTime-c.startTime)*c.secondWidth*d.zoomLevel-d.scrollX,s=c.timelineHeight+c.firstTrackTopMargin+e*(c.trackHeight+c.trackMargin);return d.draggingEvent={trackIndex:e,eventIndex:t,eventX:o,eventY:s,originalTrackIndex:e,originalEventIndex:t,originalStartTime:n.startTime,startX:r,startY:i,isDragging:!1},d.dragOffsetX=r-o,d.dragOffsetY=i-s,this.timeline.callbacks.onEventHighlight&&this.timeline.callbacks.onEventHighlight({trackIndex:e,eventIndex:t,event:u(n)}),this.timeline.notifyChange(`selection:change`),this.createDraggingState()}return d.selectedEvent=null,d.highlightedEvent=null,d.selectedTrack=null,d.isManualSelection=!1,this.timeline.callbacks.onEventHighlight&&this.timeline.callbacks.onEventHighlight({trackIndex:null,eventIndex:null,event:null}),this.timeline.notifyChange(`selection:change`),null}handleMouseMove(t){let{canvasX:n,canvasY:r,logicalX:i,logicalY:o}=t,s=this.timeline.config,c=this.timeline.state,l=this.timeline.getCanvas();if(c.contextMenuVisible){let e=c.contextMenuBounds;if(e){let t=e.x,i=e.y,a=e.width,o=e.height;if(n>=t&&n<=t+a&&r>=i&&r<=i+o){let t=Math.floor((r-i-e.padding)/e.itemHeight);return t>=0&&t<s.contextMenuItems.length?(c.hoveredContextMenuItem!==t&&(c.hoveredContextMenuItem=t,this.timeline.notifyChange(`interaction:contextMenu`)),l.style.cursor=`pointer`):c.hoveredContextMenuItem!==-1&&(c.hoveredContextMenuItem=-1,this.timeline.notifyChange(`interaction:contextMenu`)),null}else c.hoveredContextMenuItem!==-1&&(c.hoveredContextMenuItem=-1,this.timeline.notifyChange(`interaction:contextMenu`))}}if(o>=s.timelineHeight&&!s.readOnly){if(s.enableEventResize){let e=this.timeline.getResizeHandle(i,o);if(e)return c.tracks[e.trackIndex].events[e.eventIndex].readonly?(c.hoveredResizeHandle=null,l.style.cursor=`not-allowed`,this.timeline.hideSplitLine(),this.timeline.notifyChange(`interaction:hover`),null):(c.hoveredResizeHandle=e,l.style.cursor=`ew-resize`,this.timeline.hideSplitLine(),this.timeline.notifyChange(`interaction:hover`),null);c.hoveredResizeHandle=null}if(s.enableEventSplit){let t=this.timeline.getEventAtPosition(i,o);if(t){let{trackIndex:n,eventIndex:r}=t,o=c.tracks[n].events[r];if(o.readonly)return this.timeline.hideSplitLine(),l.style.cursor=`not-allowed`,this.timeline.notifyChange(`interaction:hover`),null;let u=(i-s.startPaddingTime)/(s.secondWidth*c.zoomLevel)+s.startTime;if(c.snapEnabled){let t=a(c.zoomLevel,s.snapInterval,s.snapToSeconds,s.secondPrecisionZoomThreshold);u=e(u,t)}let d=u-o.startTime,f=o.duration-d;if(u>o.startTime&&u<o.startTime+o.duration&&d>=s.minEventDuration&&f>=s.minEventDuration)return this.timeline.showSplitLine(n,r,u),l.style.cursor=`pointer`,this.timeline.notifyChange(`interaction:splitLine`),null}this.timeline.hideSplitLine()}else this.timeline.hideSplitLine()}if(s.enableTimeIndicator&&r<=s.timelineHeight){let e=g(c.timeIndicatorPosition,s.startTime,s.startPaddingTime,s.secondWidth,c.zoomLevel,c.scrollX),t=s.timeIndicatorHeadSize;if(n>=e-t/2&&n<=e+t/2&&r>=0&&r<=s.timeIndicatorHeadSize)return l.style.cursor=s.readOnly?`not-allowed`:`ew-resize`,null}let u=this.timeline.getEventAtPosition(n,r);if(u){let{trackIndex:e,eventIndex:t}=u,n=c.tracks[e].events[t];l.style.cursor=`pointer`,this.timeline.setStatus(`${n.title} (${this.timeline.formatTime(n.startTime)} - ${this.timeline.formatTime(n.endTime)})`)}else l.style.cursor=`default`;return null}handleContextMenu(e){e.originalEvent.preventDefault();let{canvasX:t,canvasY:n}=e,r=this.timeline.config,i=this.timeline.state;if(!r.enableContextMenu||r.readOnly||!this.timeline.isPluginLoaded(`context-menu`))return null;let a=this.timeline.getEventAtPosition(t,n);if(a){let{trackIndex:e,eventIndex:r}=a;i.contextMenuEvent={trackIndex:e,eventIndex:r},i.contextMenuVisible=!0,i.contextMenuX=t,i.contextMenuY=n,i.hoveredContextMenuItem=-1,this.timeline.notifyChange(`interaction:contextMenu`)}else i.contextMenuVisible=!1,i.contextMenuEvent=null,this.timeline.notifyChange(`interaction:contextMenu`);return null}createDraggingState(){return new V(this.timeline)}createResizingState(){return new H(this.timeline)}createScrollingState(){return new U(this.timeline)}createTimeIndicatorDragState(){return new W(this.timeline)}};const K=_(`StateMachine`);var q=class{constructor(e){this.timeline=e,this.rafId=null,this.pendingMouseMove=null,this.currentState=new G(e)}getCurrentStateName(){return this.currentState.name}transitionTo(e){if(!e||e===this.currentState)return;let t=this.currentState;t.onExit&&(K.debugStyled(b.stateExit,`◁ Exit: ${t.name}`),t.onExit(e)),this.currentState=e,e.onEnter&&(K.debugStyled(b.stateEnter,`▷ Enter: ${e.name}`),e.onEnter(t)),K.debugStyled(b.stateTransition,`⟳ Transition: ${t.name} → ${e.name}`)}createContext(e){let t=this.timeline.getCanvas().getBoundingClientRect(),n=this.timeline.state;return{canvasX:e.clientX-t.left,canvasY:e.clientY-t.top,logicalX:e.clientX-t.left+n.scrollX,logicalY:e.clientY-t.top+n.scrollY,originalEvent:e,canvasWidth:t.width,canvasHeight:t.height}}handleMouseDown(e){let t=this.createContext(e),n=this.currentState.handleMouseDown(t);this.transitionTo(n)}handleMouseMove(e){if(this.rafId!==null){this.pendingMouseMove=e;return}this.pendingMouseMove=e,this.rafId=requestAnimationFrame(()=>{this.pendingMouseMove&&=(this.handleMouseMoveImpl(this.pendingMouseMove),null),this.rafId=null})}handleMouseMoveImpl(e){let t=this.createContext(e),n=this.currentState.handleMouseMove(t);this.transitionTo(n)}handleMouseUp(e){this.rafId!==null&&(cancelAnimationFrame(this.rafId),this.rafId=null,this.pendingMouseMove=null);let t=e||new MouseEvent(`mouseup`),n=this.createContext(t),r=this.currentState.handleMouseUp(n);this.transitionTo(r)}handleContextMenu(e){let t=this.createContext(e),n=this.currentState.handleContextMenu(t);this.transitionTo(n)}destroy(){this.rafId!==null&&(cancelAnimationFrame(this.rafId),this.rafId=null),this.pendingMouseMove=null}},J=class{constructor(e){this.timeline=e}handleWheel(e){if(e.preventDefault(),e.ctrlKey||e.metaKey){let t=e.deltaY>0?.9:1.1;this.timeline.zoom(t)}else this.timeline.state.scrollY+=e.deltaY,this.timeline.adjustCanvasSize(),this.timeline.notifyChange(`scroll:y`)}},Y=class{constructor(e){this.baseContext=e,this.plugins=new Map,this.eventHandlers=new Map,this.renderLayers=new Map,this.pluginData=new Map}async loadPlugin(e){let{name:t,version:n}=e.metadata,r=`${t}@${n}`;if(this.plugins.has(r))return!1;let i=this.createPluginContext(r);try{return e.init&&await e.init(i),e.activate&&await e.activate(i),this.plugins.set(r,{plugin:e,context:i,active:!0}),!0}catch{return!1}}async unloadPlugin(e){let t=this.plugins.get(e);if(!t)return!1;try{t.plugin.deactivate&&await t.plugin.deactivate(t.context),t.plugin.destroy&&await t.plugin.destroy(t.context)}finally{this.cleanupPluginResources(e),this.plugins.delete(e)}return!0}createPluginContext(e){let t=new Map;this.pluginData.set(e,t);let n={registerRenderLayer:t=>this.registerRenderLayer(e,t),unregisterRenderLayer:t=>this.unregisterRenderLayer(e,t),registerEventHandler:(t,n)=>this.registerEventHandler(e,t,n),unregisterEventHandler:(t,n)=>this.unregisterEventHandler(e,t,n),showNotification:(t,n=`info`)=>{let r=_(`plugin:${e}`);switch(n){case`error`:r.error(t);break;case`warning`:r.warn(t);break;default:r.info(t)}},getData:e=>t.get(e),setData:(e,n)=>t.set(e,n),setPerformanceProvider:e=>{this.performanceProvider=e},getPerformanceStats:()=>this.performanceProvider?this.performanceProvider.getAllStats():new Map,getFPS:()=>this.performanceProvider?this.performanceProvider.getFPS():0};return{...this.baseContext,api:n}}registerEventHandler(e,t,n){let r=this.eventHandlers.get(t)||[];r.push(n),this.eventHandlers.set(t,r)}unregisterEventHandler(e,t,n){let r=this.eventHandlers.get(t);if(!r)return;let i=r.indexOf(n);i>=0&&r.splice(i,1),this.eventHandlers.set(t,r)}registerRenderLayer(e,t){this.renderLayers.set(t.name,t)}unregisterRenderLayer(e,t){this.renderLayers.delete(t)}cleanupPluginResources(e){this.pluginData.delete(e);for(let[t]of this.renderLayers)t.startsWith(e)&&this.renderLayers.delete(t)}emitEvent(e,...t){let n=this.eventHandlers.get(e);if(!(!n||n.length===0))for(let e of n)try{e(...t)}catch{}}validateEvent(e,...t){let n=this.eventHandlers.get(e);if(!n||n.length===0)return!0;for(let e of n)try{if(e(...t)===!1)return!1}catch{}return!0}renderBackground(e,t,n,r){for(let i of this.layersByPosition(`background`))i.render(e,t,n,r)}renderOverlay(e,t,n,r){for(let i of this.layersByPosition(`overlay`))i.render(e,t,n,r)}layersByPosition(e){return Array.from(this.renderLayers.values()).filter(t=>t.position===e)}getLoadedPlugins(){return Array.from(this.plugins.values()).map(e=>e.plugin)}isPluginLoaded(e){for(let[t]of this.plugins)if(t.startsWith(`${e}@`))return!0;return!1}measureStart(e){this.performanceProvider&&this.performanceProvider.startMeasurement(e)}measureEnd(e){this.performanceProvider&&this.performanceProvider.endMeasurement(e)}},X=class{constructor(e){this.logger=e}throw(e){throw this.logger.error(e),Error(e)}error(e){this.logger.error(e)}warn(e){this.logger.warn(e)}},Z=class{constructor(e){this.state={tracks:[],selectedTrack:null,selectedEvent:null,highlightedEvent:null,draggingEvent:null,dragOffsetX:0,dragOffsetY:0,resizingEvent:null,draggingTimeIndicator:!1,timeIndicatorDragOffsetX:0,draggingScrollbar:!1,scrollbarDragOffset:0,draggingHorizontalScrollbar:!1,horizontalScrollbarDragOffset:0,zoomLevel:1,scrollX:0,scrollY:0,snapEnabled:!0,timeIndicatorSnapEnabled:!0,contextMenuEvent:null,contextMenuVisible:!1,contextMenuX:0,contextMenuY:0,hoveredContextMenuItem:-1,timeIndicatorPosition:e.startTime,timeIndicatorHighlightedEvents:[],isManualSelection:!1,guideLines:[],dragTimeReference:null,hoveredResizeHandle:null,lastClickTime:0,lastClickEvent:null,hoveredSplitLine:null,statusText:`就绪`,contextMenuBounds:null,lastDrawTime:0}}setStatus(e,t){this.state.statusText=e,t&&t(e)}},Q=class{constructor(e){this.sortedIndices=new Map,this.dirtyTracks=new Set,this.batching=!1,this.state=e}invalidateTrack(e){this.dirtyTracks.add(e)}invalidateAll(){this.sortedIndices.clear(),this.dirtyTracks.clear()}beginBatch(){this.batching=!0}endBatch(){if(this.batching){for(let e of Array.from(this.dirtyTracks)){let t=this.state.tracks[e],n=t.events.map((e,t)=>t);n.sort((e,n)=>t.events[e].startTime-t.events[n].startTime),this.sortedIndices.set(e,n)}this.dirtyTracks.clear(),this.batching=!1}}ensureSorted(e){if(this.batching&&this.sortedIndices.has(e))return this.sortedIndices.get(e);if(this.dirtyTracks.has(e)||!this.sortedIndices.has(e)){let t=this.state.tracks[e],n=t.events.map((e,t)=>t);n.sort((e,n)=>t.events[e].startTime-t.events[n].startTime),this.sortedIndices.set(e,n),this.dirtyTracks.delete(e)}return this.sortedIndices.get(e)}getCandidatesByTime(e,t,n=0){let r=this.ensureSorted(e),i=this.state.tracks[e],a=0,o=r.length-1,s=-1,c=t+n;for(;a<=o;){let e=a+o>>1,t=r[e];i.events[t].startTime<=c?(s=e,a=e+1):o=e-1}if(s===-1)return[];let l=[];for(let e=s;e>=0;e--){let a=r[e],o=i.events[a];if(!(o.startTime>t+n)){if(o.endTime<t-n)break;l.push(a)}}for(let e=s+1;e<r.length;e++){let a=r[e];if(i.events[a].startTime>t+n)break;l.push(a)}return l}};const $=_(`ChangeScheduler`);var te=class{constructor(e,t,n){this.renderManager=null,this.drawFn=null,this.handlers=new Map,this.batchContext=null,this.isBatching=!1,this.state=e,this.callbacks=n,this.initializeHandlers()}setRenderManager(e){this.renderManager=e}setDrawFunction(e){this.drawFn=e}initializeHandlers(){this.handlers.set(`events:add`,{layers:[`tracks`,`timeline`,`scrollbar`,`indicator`],derive:()=>this.refreshHighlightList(),needsDraw:!0}),this.handlers.set(`events:update`,{layers:[`tracks`,`timeline`,`scrollbar`,`indicator`],derive:()=>this.refreshHighlightList(),needsDraw:!0}),this.handlers.set(`events:delete`,{layers:[`tracks`,`timeline`,`scrollbar`,`indicator`],derive:()=>this.refreshHighlightList(),needsDraw:!0}),this.handlers.set(`events:move`,{layers:[`tracks`,`timeline`,`scrollbar`,`guideLines`,`indicator`,`interaction`],derive:()=>this.refreshHighlightList(),needsDraw:!0}),this.handlers.set(`events:split`,{layers:[`tracks`,`timeline`,`scrollbar`,`indicator`],derive:()=>this.refreshHighlightList(),needsDraw:!0}),this.handlers.set(`tracks:add`,{layers:[`tracks`,`timeline`,`scrollbar`],derive:()=>this.refreshHighlightList(),needsDraw:!0}),this.handlers.set(`tracks:remove`,{layers:[`tracks`,`timeline`,`scrollbar`],derive:()=>this.refreshHighlightList(),needsDraw:!0}),this.handlers.set(`timeIndicator:move`,{layers:[`indicator`,`tracks`,`timeline`,`interaction`],derive:()=>this.computeHighlightList(),notify:()=>this.emitTimeIndicatorHighlight(),needsDraw:!0}),this.handlers.set(`timeIndicator:drag`,{layers:[`indicator`,`tracks`,`interaction`],derive:()=>this.computeHighlightList(),needsDraw:!0}),this.handlers.set(`scroll:x`,{layers:[`tracks`,`timeline`,`guideLines`,`indicator`,`scrollbar`,`interaction`],needsDraw:!0}),this.handlers.set(`scroll:y`,{layers:[`background`,`tracks`,`timeline`,`guideLines`,`indicator`,`scrollbar`,`interaction`,`overlay`],needsDraw:!0}),this.handlers.set(`zoom:change`,{layers:[`background`,`tracks`,`timeline`,`guideLines`,`indicator`,`scrollbar`,`interaction`,`overlay`],needsDraw:!0}),this.handlers.set(`selection:change`,{layers:[`tracks`,`interaction`,`indicator`],needsDraw:!0}),this.handlers.set(`highlight:change`,{layers:[`tracks`,`indicator`],needsDraw:!0}),this.handlers.set(`canvas:resize`,{layers:[`background`,`tracks`,`timeline`,`guideLines`,`indicator`,`scrollbar`,`interaction`,`overlay`],needsDraw:!0}),this.handlers.set(`data:load`,{layers:[`tracks`,`timeline`,`scrollbar`,`guideLines`],derive:()=>this.refreshHighlightList(),needsDraw:!0}),this.handlers.set(`theme:change`,{layers:[`background`,`tracks`,`timeline`,`overlay`],needsDraw:!0}),this.handlers.set(`interaction:hover`,{layers:[`tracks`,`interaction`],needsDraw:!0}),this.handlers.set(`interaction:contextMenu`,{layers:[`overlay`,`interaction`],needsDraw:!0}),this.handlers.set(`interaction:splitLine`,{layers:[`tracks`],needsDraw:!0}),this.handlers.set(`config:endTime`,{layers:[`background`,`tracks`,`timeline`,`guideLines`,`indicator`,`scrollbar`,`interaction`,`overlay`],needsDraw:!0}),this.handlers.set(`config:readOnly`,{layers:[`background`,`tracks`,`timeline`,`guideLines`,`indicator`,`scrollbar`,`interaction`,`overlay`],needsDraw:!0})}notify(e){let t=this.handlers.get(e);if(!t){$.warn(`Unknown change type: ${e}`);return}if(this.isBatching&&this.batchContext){this.batchContext.changes.add(e);for(let e of t.layers)this.batchContext.dirtyLayers.add(e);t.derive&&this.batchContext.pendingDerives.push(t.derive),t.notify&&this.batchContext.pendingNotifications.push(t.notify)}else this.processChange(t)}notifyMultiple(e){this.beginBatch();for(let t of e)this.notify(t);this.endBatch()}beginBatch(){if(this.isBatching){$.warn(`Already in batch mode`);return}this.isBatching=!0,this.batchContext={changes:new Set,dirtyLayers:new Set,pendingNotifications:[],pendingDerives:[]}}endBatch(){if(!this.isBatching||!this.batchContext){$.warn(`Not in batch mode`);return}let e=this.batchContext;if(this.isBatching=!1,this.batchContext=null,e.changes.size===0)return;let t=[...new Set(e.pendingDerives)];for(let e of t)e();this.renderManager&&e.dirtyLayers.size>0&&this.renderManager.markDirty(Array.from(e.dirtyLayers)),this.drawFn&&this.drawFn();let n=[...new Set(e.pendingNotifications)];for(let e of n)e()}processChange(e){e.derive&&e.derive(),this.renderManager&&e.layers.length>0&&this.renderManager.markDirty(e.layers),e.needsDraw&&this.drawFn&&this.drawFn(),e.notify&&e.notify()}refreshHighlightList(){this.state.timeIndicatorHighlightedEvents=this.detectHighlightedEvents(this.state.timeIndicatorPosition)}computeHighlightList(){let e=this.state.timeIndicatorPosition,t=this.detectHighlightedEvents(e),n=this.hasHighlightChanged(this.state.timeIndicatorHighlightedEvents,t);this.state.timeIndicatorHighlightedEvents=t,this._highlightChanged=n}hasHighlightChanged(e,t){if(e.length!==t.length)return!0;let n=(e,t)=>`${e}-${t}`,r=new Set(e.map(e=>n(e.trackIndex,e.eventIndex))),i=new Set(t.map(e=>n(e.trackIndex,e.eventIndex)));return!Array.from(i).every(e=>r.has(e))}detectHighlightedEvents(e){let t=[];for(let n=0;n<this.state.tracks.length;n++){let r=this.state.tracks[n];for(let i=0;i<r.events.length;i++){let a=r.events[i];e>=a.startTime&&e<a.endTime&&t.push({trackIndex:n,eventIndex:i})}}return t}emitTimeIndicatorHighlight(){if(this._highlightChanged){if(this.callbacks.onTimeIndicatorHighlight){let e=this.state.timeIndicatorPosition,t=this.state.timeIndicatorHighlightedEvents.map(({trackIndex:e,eventIndex:t})=>{let n=this.state.tracks[e].events[t];return{trackIndex:e,eventIndex:t,event:u(n)}});this.callbacks.onTimeIndicatorHighlight({position:e,highlightedEvents:t})}this._highlightChanged=!1}}registerHandler(e,t){this.handlers.set(e,t)}getLayersForChange(e){return this.handlers.get(e)?.layers||[]}updateCallbacks(e){this.callbacks=e}},ne=class{constructor(e,r={}){this.guideLinesCache=new Map,this.guideLinesCacheTimestamp=0,this.GUIDE_LINES_CACHE_TTL=500,this.eventListeners=null,this.currentThemePluginId=null,this.logger=new v({enabled:!0,level:r.debug?`debug`:`info`,prefix:`Timeline`,useGlobalConfig:!1}),y({enabled:!0,level:r.debug?`debug`:`info`}),this.errorHandler=new X(this.logger);let i=document.getElementById(e);(!i||!(i instanceof HTMLCanvasElement))&&this.errorHandler.throw(`Canvas element with id "${e}" not found`),this.canvas=i;let a=this.canvas.getContext(`2d`);if(a||this.errorHandler.throw(`Failed to get 2D context from canvas`),this.ctx=a,r.startPaddingTime===void 0&&(r.startPaddingTime=10),this.config={...s,...r,colors:{...p,...r.colors},eventTextStyle:{...n,...r.eventTextStyle},eventBlockStyle:{...m,...r.eventBlockStyle},contextMenuItems:r.contextMenuItems||t,contextMenuStyle:{...d,...r.contextMenuStyle}},this.logger.setLevel(this.config.debug?`debug`:`info`),this.callbacks={onEventAdd:r.onEventAdd||null,onEventUpdate:r.onEventUpdate||null,onEventDelete:r.onEventDelete||null,onEventMove:r.onEventMove||null,onEventClick:r.onEventClick||null,onEventEdit:r.onEventEdit||null,onContextMenu:r.onContextMenu||null,onTrackAdd:r.onTrackAdd||null,onTrackRemove:r.onTrackRemove||null,onTimeIndicatorMove:r.onTimeIndicatorMove||null,onZoom:r.onZoom||null,onStatusChange:r.onStatusChange||null,onEventHighlight:r.onEventHighlight||null,onTimeIndicatorHighlight:r.onTimeIndicatorHighlight||null},this.stateManager=new Z(this.config),this.state=this.stateManager.state,this.eventIndexManager=new Q(this.state),this.mouseHandler=new q(this),this.wheelHandler=new J(this),this.pluginManager=new Y({timeline:this,config:this.config,state:this.state}),r.theme){let e=`${r.theme.metadata.name}@${r.theme.metadata.version}`;this.pluginManager.loadPlugin(r.theme).then(t=>{t&&(this.currentThemePluginId=e)})}this.renderManager=new R(this.canvas,this.ctx,this.config,this.state,this.pluginManager),this.changeScheduler=new te(this.state,this.config,this.callbacks),this.changeScheduler.setRenderManager(this.renderManager),this.changeScheduler.setDrawFunction(()=>this.draw()),this.init(),this.setupEventListeners()}getCanvas(){return this.canvas}usePlugin(e){return this.pluginManager.loadPlugin(e)}getLoadedPlugins(){return this.pluginManager.getLoadedPlugins()}isPluginLoaded(e){return this.pluginManager.isPluginLoaded(e)}async removePlugin(e){return this.pluginManager.unloadPlugin(e)}async setTheme(e){let t=e===`dark`?S:x;return this.switchTheme(t)}async switchTheme(e){this.currentThemePluginId&&=(await this.pluginManager.unloadPlugin(this.currentThemePluginId),null);let t=`${e.metadata.name}@${e.metadata.version}`,n=await this.pluginManager.loadPlugin(e);return n&&(this.currentThemePluginId=t,this.notifyChange(`theme:change`)),n}init(){this.config.autoFitOnInit&&this.autoFitZoomToCanvas(),this.notifyChange(`data:load`)}getContentWidthForZoom(e){return this.renderManager.getContentWidth(e)}hasHorizontalScrollbar(){return this.renderManager.hasHorizontalScrollbar()}getAvailableHeight(){return this.renderManager.getAvailableHeight()}notifyChange(e){this.changeScheduler.notify(e)}beginChangeBatch(){this.changeScheduler.beginBatch()}endChangeBatch(){this.changeScheduler.endBatch()}markDirty(e){this.renderManager.markDirty(e)}getLastLayerTimes(){return this.renderManager.getLastLayerTimes()}beginIndexBatch(){this.eventIndexManager.beginBatch()}endIndexBatch(){this.eventIndexManager.endBatch()}invalidateIndexTrack(e){this.eventIndexManager.invalidateTrack(e)}invalidateIndexAll(){this.eventIndexManager.invalidateAll()}autoFitZoomToCanvas(){this.adjustCanvasSize();let e=this.renderManager.getCanvasLogicalWidth(),t=Math.max(this.config.minAutoFitZoom,this.state.zoomLevel,1),n=Math.max(this.config.maxAutoFitZoom,t);if(this.renderManager.getContentWidth(t)>=e){this.state.zoomLevel=t;return}for(;t<=n&&this.renderManager.getContentWidth(t)<e;)t+=.05;if(t<=n&&this.renderManager.getContentWidth(t)>=e){this.state.zoomLevel=parseFloat(t.toFixed(3)),this.setStatus(`自动缩放: ${Math.round(this.state.zoomLevel*100)}% 以铺满画布`);return}if(this.config.endPaddingTime===0){let t=e,r=this.renderManager.getContentWidth(n);if(r<t){let e=(t-r)/(this.config.secondWidth*n);this.config.endPaddingTime=Math.ceil(e),this.state.zoomLevel=n,this.setStatus(`自动缩放达到上限(${Math.round(n*100)}%),已自动增加留白 ${this.config.endPaddingTime} 秒以铺满画布`);return}}this.state.zoomLevel=n,this.setStatus(`自动缩放达到上限(${Math.round(n*100)}%),内容仍不足以完全铺满画布`),this.markDirty([`background`,`tracks`,`timeline`,`guideLines`,`indicator`,`scrollbar`,`interaction`,`overlay`])}setupEventListeners(){this.eventListeners={mousedown:e=>this.mouseHandler.handleMouseDown(e),mousemove:e=>this.mouseHandler.handleMouseMove(e),mouseup:e=>this.mouseHandler.handleMouseUp(e),mouseleave:()=>this.mouseHandler.handleMouseUp(),contextmenu:e=>this.mouseHandler.handleContextMenu(e),wheel:e=>this.wheelHandler.handleWheel(e)},this.canvas.addEventListener(`mousedown`,this.eventListeners.mousedown),this.canvas.addEventListener(`mousemove`,this.eventListeners.mousemove),this.canvas.addEventListener(`mouseup`,this.eventListeners.mouseup),this.canvas.addEventListener(`mouseleave`,this.eventListeners.mouseleave),this.canvas.addEventListener(`contextmenu`,this.eventListeners.contextmenu),this.canvas.addEventListener(`wheel`,this.eventListeners.wheel,{passive:!1}),this.setInitialCanvasSize()}setInitialCanvasSize(){let e=this.canvas.parentElement;if(!e){this.setCanvasSize(this.renderManager.getCanvasLogicalWidth(),this.config.canvasHeight||500);return}let t=e.getBoundingClientRect();this.setCanvasSize(t.width,t.height||this.config.canvasHeight||500)}setCanvasSize(e,t){this.renderManager.setCanvasSize(e,t)}getCanvasLogicalHeight(){return this.renderManager.getCanvasLogicalHeight()}getCachedLogicalHeight(){return this.renderManager.getCachedLogicalHeight()}adjustCanvasSize(){let e=this.renderManager.computeMaxScrollY();this.state.scrollY=Math.max(0,Math.min(e,this.state.scrollY)),this.notifyChange(`canvas:resize`)}addTrack(){let e={id:this.state.tracks.length,events:[]};this.state.tracks.push(e),this.adjustCanvasSize(),this.setStatus(`已添加轨道 ${this.state.tracks.length}`),this.callbacks.onTrackAdd&&this.callbacks.onTrackAdd(e)}removeTrack(){if(this.state.tracks.length<=1){this.setStatus(`至少需要保留一个轨道`);return}let e=this.state.tracks.pop();this.state.selectedTrack!==null&&this.state.selectedTrack>=this.state.tracks.length&&(this.state.selectedTrack=this.state.tracks.length>0?this.state.tracks.length-1:null),this.adjustCanvasSize(),this.setStatus(`已删除轨道,当前轨道数: ${this.state.tracks.length}`),this.callbacks.onTrackRemove&&this.callbacks.onTrackRemove(e)}autoRemoveEmptyLastTrack(){if(this.config.autoRemoveEmptyLastTrack&&!(this.state.tracks.length<=1)&&this.state.tracks[this.state.tracks.length-1].events.length===0){let e=this.state.tracks.pop();this.state.selectedTrack!==null&&this.state.selectedTrack>=this.state.tracks.length&&(this.state.selectedTrack=this.state.tracks.length>0?this.state.tracks.length-1:null),this.setStatus(`自动清理空轨道,当前轨道数: ${this.state.tracks.length}`),this.callbacks.onTrackRemove&&this.callbacks.onTrackRemove(e),this.adjustCanvasSize(),this.autoRemoveEmptyLastTrack()}}validateEventTime(e,t){let n=this.config.endTime+this.config.endPaddingTime,i,a;if(t>e&&t<=n)i=e,a=r(t-e);else if(t<=this.config.endTime-this.config.startTime&&e+t<=n)i=e,a=t;else return this.logger.error(`无效的时间范围: startTime=${e}, endTime=${t}`),null;return i<this.config.startTime?(this.logger.error(`开始时间不能进入左侧留白区域: startTime=${i}, minAllowed=${this.config.startTime}`),null):{startSec:i,duration:a}}addEvent(e,t,n,i,a=``,o,s=!1){if(e<0||e>=this.state.tracks.length)return;let c=this.validateEventTime(t,n);if(!c)return;let{startSec:l,duration:d}=c,f=this.state.tracks[e],p=r(d),m={id:f.events.length,startTime:l,endTime:r(l+p),duration:p,title:i,description:a,color:this.config.colors.eventColors[f.events.length%this.config.colors.eventColors.length],...s&&{readonly:s},...o&&{customData:o}};f.events.push(m),this.eventIndexManager.invalidateTrack(e),this.notifyChange(`events:add`),this.callbacks.onEventAdd&&this.callbacks.onEventAdd({trackIndex:e,event:u(m)})}updateEvent(e,t,n){if(e<0||e>=this.state.tracks.length)return this.logger.error(`无效的轨道索引`),!1;let r=this.state.tracks[e];if(t<0||t>=r.events.length)return this.logger.error(`无效的事件索引`),!1;let i=r.events[t],a=u(i);return Object.assign(i,n),this.eventIndexManager.invalidateTrack(e),this.notifyChange(`events:update`),this.setStatus(`已更新事件: ${i.title}`),this.callbacks.onEventUpdate&&this.callbacks.onEventUpdate({trackIndex:e,eventIndex:t,event:u(i),oldEvent:a}),!0}updateEventData(e,t,n){if(e<0||e>=this.state.tracks.length)return this.logger.error(`无效的轨道索引`),!1;let i=this.state.tracks[e];if(t<0||t>=i.events.length)return this.logger.error(`无效的事件索引`),!1;let a=i.events[t],o=u(a);return n.title!==void 0&&(a.title=n.title),n.startTime!==void 0&&(a.startTime=n.startTime,a.endTime=r(a.startTime+a.duration)),n.duration!==void 0&&(a.duration=r(n.duration),a.endTime=r(a.startTime+a.duration)),n.description!==void 0&&(a.description=n.description),this.eventIndexManager.invalidateTrack(e),this.notifyChange(`events:update`),this.setStatus(`已更新事件: ${a.title}`),this.callbacks.onEventUpdate&&this.callbacks.onEventUpdate({trackIndex:e,eventIndex:t,event:u(a),oldEvent:o}),!0}deleteEvent(e,t){if(e<0||e>=this.state.tracks.length)return!1;let n=this.state.tracks[e];if(t<0||t>=n.events.length)return!1;let r=u(n.events[t]);return n.events.splice(t,1),this.eventIndexManager.invalidateTrack(e),this.autoRemoveEmptyLastTrack(),this.notifyChange(`events:delete`),this.setStatus(`已删除事件: ${r.title}`),this.callbacks.onEventDelete&&this.callbacks.onEventDelete({trackIndex:e,eventIndex:t,event:r}),!0}loadData(e){if(!e||typeof e!=`object`)return this.logger.error(`无效的数据格式`),!1;this.state.tracks=[],this.state.selectedTrack=null,this.state.selectedEvent=null;let t=e.tracks||[];for(let e=0;e<t.length;e++){let n=t[e],i={id:this.state.tracks.length,events:[]},a=n.events||[];for(let e=0;e<a.length;e++){let t=a[e];if(!t.title)continue;let n,o;if(t.endTime!==void 0)n=t.startTime||0,o=r(t.endTime-n);else if(t.duration!==void 0)n=t.startTime||0,o=t.duration;else continue;let s=r(o),c={id:i.events.length,startTime:n,endTime:r(n+s),duration:s,title:t.title,description:t.description||``,color:t.color||this.config.colors.eventColors[i.events.length%this.config.colors.eventColors.length],...t.readonly&&{readonly:t.readonly},...t.customData&&{customData:t.customData}};i.events.push(c)}this.state.tracks.push(i)}return this.state.tracks.length===0&&this.addTrack(),this.eventIndexManager.invalidateAll(),e.timeIndicatorPosition!==void 0&&this.setTimeIndicator(e.timeIndicatorPosition),this.notifyChange(`data:load`),this.setStatus(`已加载 ${this.state.tracks.length} 个轨道`),!0}setTimeIndicator(t,n=!1){if(typeof t!=`number`||isNaN(t))return this.logger.error(`时间指示器位置必须是数字(秒)`),!1;if(n&&this.state.snapEnabled){let n=a(this.state.zoomLevel,this.config.snapInterval,this.config.snapToSeconds,this.config.secondPrecisionZoomThreshold);t=e(t,n)}return t=Math.max(this.config.startTime,Math.min(this.config.endTime,t)),this.state.timeIndicatorPosition=t,this.scrollToTimeIndicator(t),this.notifyChange(`timeIndicator:move`),this.setStatus(`时间指示器已移动到: ${f(t)}`),this.callbacks.onTimeIndicatorMove&&this.callbacks.onTimeIndicatorMove({position:t,time:f(t)}),!0}scrollToTimeIndicator(e){let t=g(e,this.config.startTime,this.config.startPaddingTime,this.config.secondWidth,this.state.zoomLevel,this.state.scrollX),n=this.renderManager.getCanvasLogicalWidth();if(t<50){let t=g(e,this.config.startTime,this.config.startPaddingTime,this.config.secondWidth,this.state.zoomLevel,0)-50,n=this.renderManager.computeMaxScrollX(this.state.zoomLevel);this.state.scrollX=Math.max(0,Math.min(n,t))}else if(t>n-50){let t=g(e,this.config.startTime,this.config.startPaddingTime,this.config.secondWidth,this.state.zoomLevel,0)-(n-50),r=this.renderManager.computeMaxScrollX(this.state.zoomLevel);this.state.scrollX=Math.max(0,Math.min(r,t))}this.markDirty([`background`,`tracks`,`timeline`,`guideLines`,`indicator`,`scrollbar`,`interaction`,`overlay`])}zoom(e){let t=this.state.zoomLevel,n=this.state.scrollX,r=this.renderManager.getCachedLogicalWidth()/2,i=(r+n)/(this.config.secondWidth*t);if(this.state.zoomLevel*=e,this.state.zoomLevel=Math.max(1,Math.min(1e3,this.state.zoomLevel)),t!==this.state.zoomLevel){let e=i*this.config.secondWidth*this.state.zoomLevel;this.state.scrollX=e-r;let t=this.renderManager.computeMaxScrollX(this.state.zoomLevel);this.state.scrollX=Math.max(0,Math.min(t,this.state.scrollX))}this.notifyChange(`zoom:change`),this.setStatus(`缩放级别: ${Math.round(this.state.zoomLevel*100)}%`),this.callbacks.onZoom&&t!==this.state.zoomLevel&&this.callbacks.onZoom({zoomLevel:this.state.zoomLevel,percentage:Math.round(this.state.zoomLevel*100)})}setZoomLevel(e){if(typeof e!=`number`||isNaN(e))return this.logger.error(`缩放级别必须是有效的数字`),!1;if(e<1||e>1e3)return this.logger.error(`缩放级别超出有效范围 (1-1000)`),!1;let t=this.state.zoomLevel,n=this.state.scrollX,r=this.renderManager.getCachedLogicalWidth()/2,i=(r+n)/(this.config.secondWidth*t);this.state.zoomLevel=e;let a=i*this.config.secondWidth*this.state.zoomLevel;this.state.scrollX=a-r;let o=this.renderManager.computeMaxScrollX(this.state.zoomLevel);return this.state.scrollX=Math.max(0,Math.min(o,this.state.scrollX)),this.notifyChange(`zoom:change`),this.setStatus(`缩放级别: ${Math.round(this.state.zoomLevel*100)}%`),this.callbacks.onZoom&&t!==this.state.zoomLevel&&this.callbacks.onZoom({zoomLevel:this.state.zoomLevel,percentage:Math.round(this.state.zoomLevel*100)}),!0}getZoomLevel(){return this.state.zoomLevel}setEndTime(e){if(typeof e!=`number`||isNaN(e))return this.logger.error(`结束时间必须是有效的数字(秒)`),!1;if(e<=this.config.startTime)return this.logger.error(`结束时间必须大于开始时间`),!1;this.state.tracks.some(t=>t.events.some(t=>t.endTime>e))&&this.logger.warn(`警告:有事件超出新的结束时间范围`);let t=this.config.endTime;this.config.endTime=e,this.renderManager.invalidateLayoutCache(),this.state.timeIndicatorPosition>e&&(this.state.timeIndicatorPosition=e);let n=this.renderManager.getContentWidth(this.state.zoomLevel),r=Math.max(0,n-this.renderManager.getCachedLogicalWidth());return this.state.scrollX=Math.max(0,Math.min(r,this.state.scrollX)),this.notifyChange(`config:endTime`),this.setStatus(`结束时间已更新: ${f(t)} → ${f(e)}`),!0}getEndTime(){return this.config.endTime}formatTime(e){return f(e)}setStatus(e){this.stateManager.setStatus(e,this.callbacks.onStatusChange||void 0)}getStatus(){return this.state.statusText}getEventAtPosition(e,t){let n=t+this.state.scrollY;if(n<this.config.timelineHeight)return null;let r=Math.floor((n-this.config.timelineHeight-this.config.firstTrackTopMargin)/(this.config.trackHeight+this.config.trackMargin));if(r<0||r>=this.state.tracks.length)return null;let i=this.state.tracks[r],a=Math.max(5,this.config.trackHeight*.0625),o=this.config.timelineHeight+this.config.firstTrackTopMargin+r*(this.config.trackHeight+this.config.trackMargin)-this.state.scrollY;if(t<o+a||t>o+this.config.trackHeight-a)return null;let s=(e+this.state.scrollX-this.config.startPaddingTime)/(this.config.secondWidth*this.state.zoomLevel)+this.config.startTime,c=this.eventIndexManager.getCandidatesByTime(r,s,0);if(c.length>0){c.sort((e,t)=>t-e);for(let t of c){let n=i.events[t],a=this.config.startPaddingTime+(n.startTime-this.config.startTime)*this.config.secondWidth*this.state.zoomLevel-this.state.scrollX,o=n.duration*this.config.secondWidth*this.state.zoomLevel;if(e>=a&&e<=a+o)return{trackIndex:r,eventIndex:t}}}return null}getResizeHandle(e,t){let n=t+this.state.scrollY;if(n<this.config.timelineHeight)return null;let r=Math.floor((n-this.config.timelineHeight-this.config.firstTrackTopMargin)/(this.config.trackHeight+this.config.trackMargin));if(r<0||r>=this.state.tracks.length)return null;let i=this.state.tracks[r],a=this.config.resizeHandleWidth,o=Math.max(5,this.config.trackHeight*.0625),s=this.config.timelineHeight+this.config.firstTrackTopMargin+r*(this.config.trackHeight+this.config.trackMargin)-this.state.scrollY;if(t<s+o||t>s+this.config.trackHeight-o)return null;let c=(e+this.state.scrollX-this.config.startPaddingTime)/(this.config.secondWidth*this.state.zoomLevel)+this.config.startTime,l=a/(this.config.secondWidth*this.state.zoomLevel),u=this.eventIndexManager.getCandidatesByTime(r,c,l);if(u.length>0){u.sort((e,t)=>t-e);for(let t of u){let n=i.events[t],o=this.config.startPaddingTime+(n.startTime-this.config.startTime)*this.config.secondWidth*this.state.zoomLevel-this.state.scrollX,s=n.duration*this.config.secondWidth*this.state.zoomLevel;if(e>=o-a/2&&e<=o+a/2)return{trackIndex:r,eventIndex:t,edge:`left`};if(e>=o+s-a/2&&e<=o+s+a/2)return{trackIndex:r,eventIndex:t,edge:`right`}}}return null}calculateGuideLines(e,t,n,r,i){let a=`${e}-${t}-${n}-${r.toFixed(3)}-${i.toFixed(3)}`,o=Date.now();if(o-this.guideLinesCacheTimestamp<this.GUIDE_LINES_CACHE_TTL){let e=this.guideLinesCache.get(a);if(e)return e}else this.guideLinesCache.clear(),this.guideLinesCacheTimestamp=o;let s=[],c=this.config.guideLineSnapThreshold,l=r+i,u=new Set;u.add(n),n>0&&u.add(n-1),n<this.state.tracks.length-1&&u.add(n+1);let d=(e,t,n)=>{let r=s.find(n=>Math.abs(n.time-e)<1e-4&&n.type===t);r?r.trackIndices.includes(n)||r.trackIndices.push(n):s.push({time:e,type:t,trackIndices:[n]})};for(let n of u){if(n<0||n>=this.state.tracks.length)continue;let i=this.state.tracks[n];if(i.events.length===0)continue;let a=[];for(let o=0;o<i.events.length;o++){if(n===e&&o===t)continue;let s=i.events[o];s.endTime<r-c||s.startTime>l+c||a.push(s)}if(a.length!==0)for(let e of a)Math.abs(e.startTime-r)<c&&d(e.startTime,`start`,n),Math.abs(e.endTime-l)<c&&d(e.endTime,`end`,n),Math.abs(e.endTime-r)<c&&d(e.endTime,`end`,n),Math.abs(e.startTime-l)<c&&d(e.startTime,`start`,n)}return this.guideLinesCache.set(a,s),s}snapToGuideLines(e,t){if(this.state.guideLines.length===0)return null;let n=this.config.guideLineSnapThreshold,r=e+t;for(let i of this.state.guideLines)if(i.type===`start`){if(Math.abs(i.time-e)<n)return i.time}else if(i.type===`end`&&Math.abs(i.time-r)<n)return i.time-t;return null}canMoveEvent(e,t,n,r,i){let a=r+i,o=this.config.endTime+this.config.endPaddingTime;if(r<this.config.startTime||a>o||n<0||n>=this.state.tracks.length)return!1;let s=this.state.tracks[n];for(let i=0;i<s.events.length;i++){if(n===e&&i===t)continue;let o=s.events[i];if(!(a<=o.startTime||r>=o.endTime))return!1}return!!this.pluginManager.validateEvent(`validate:event:move`,{fromTrackIndex:e,fromEventIndex:t,toTrackIndex:n,newStartTime:r,duration:i})}showSplitLine(e,t,n){(!this.state.hoveredSplitLine||this.state.hoveredSplitLine.trackIndex!==e||this.state.hoveredSplitLine.eventIndex!==t||Math.abs(this.state.hoveredSplitLine.splitTime-n)>.001)&&(this.state.hoveredSplitLine={trackIndex:e,eventIndex:t,splitTime:n},this.notifyChange(`interaction:splitLine`))}hideSplitLine(){this.state.hoveredSplitLine&&(this.state.hoveredSplitLine=null,this.notifyChange(`interaction:splitLine`))}splitEvent(e,t,n){if(e<0||e>=this.state.tracks.length)return!1;let i=this.state.tracks[e];if(t<0||t>=i.events.length)return!1;let a=i.events[t];if(n<=a.startTime+this.config.minEventDuration||n>=a.endTime-this.config.minEventDuration)return this.setStatus(`切割位置无效:切割后的事件块时长太短`),!1;let o={...a,id:a.id,duration:r(n-a.startTime),endTime:n,title:`${a.title} (1)`},s={...a,id:i.events.length,startTime:n,duration:r(a.endTime-n),endTime:r(a.endTime),title:`${a.title} (2)`};return i.events[t]=o,i.events.push(s),this.eventIndexManager.invalidateTrack(e),this.notifyChange(`events:split`),this.setStatus(`已切割事件: ${a.title}`),this.callbacks.onEventUpdate&&this.callbacks.onEventUpdate({type:`split`,trackIndex:e,eventIndex:t,event:u(a),firstEvent:u(o),secondEvent:u(s)}),!0}draw(){this.renderManager.draw()}setReadOnly(e){this.config.readOnly=e,e&&(this.state.selectedEvent=null,this.state.draggingEvent=null,this.state.resizingEvent=null,this.state.draggingTimeIndicator=!1,this.state.contextMenuVisible=!1,this.state.contextMenuEvent=null,this.state.hoveredResizeHandle=null,this.state.hoveredSplitLine=null,this.state.guideLines=[]),this.notifyChange(`config:readOnly`),this.setStatus(e?`已进入只读模式`:`已退出只读模式`)}highlightEvent(e,t){if(e<0||e>=this.state.tracks.length)return this.logger.error(`无效的轨道索引: ${e}`),!1;let n=this.state.tracks[e];if(t<0||t>=n.events.length)return this.logger.error(`无效的事件索引: ${t}`),!1;this.state.selectedEvent=null,this.state.selectedTrack=null,this.state.highlightedEvent={trackIndex:e,eventIndex:t};let r=n.events[t];return this.notifyChange(`highlight:change`),this.setStatus(`已高亮事件: ${r.title}`),!0}clearHighlight(){(this.state.highlightedEvent||this.state.selectedEvent)&&(this.state.highlightedEvent=null,this.state.selectedEvent=null,this.state.selectedTrack=null,this.notifyChange(`highlight:change`),this.setStatus(`已清除高亮`))}getHighlightedEvent(){return this.state.highlightedEvent}isReadOnly(){return this.config.readOnly}destroy(){this.guideLinesCache.clear(),this.eventListeners&&=(this.canvas.removeEventListener(`mousedown`,this.eventListeners.mousedown),this.canvas.removeEventListener(`mousemove`,this.eventListeners.mousemove),this.canvas.removeEventListener(`mouseup`,this.eventListeners.mouseup),this.canvas.removeEventListener(`mouseleave`,this.eventListeners.mouseleave),this.canvas.removeEventListener(`contextmenu`,this.eventListeners.contextmenu),this.canvas.removeEventListener(`wheel`,this.eventListeners.wheel),null),this.setStatus(`Timeline 已销毁`)}};export{C as ContextMenuPlugin,S as DarkThemePlugin,h as EventMediaPlugin,T as EventTooltipPlugin,x as LightThemePlugin,w as PerformanceOverlayPlugin,ne as Timeline,f as formatTime,o as getCurrentTime};
1
+ import{_ as e,a as t,c as n,d as r,f as i,g as a,h as o,i as s,l as c,m as l,n as u,o as d,p as f,r as p,s as m,t as h,u as g}from"./EventMediaPlugin-CawS6c0q.mjs";import{i as _,n as v,r as y,t as b}from"./Logger-CfVK3yFL.mjs";import{t as x}from"./types-BvVk5Y9C.mjs";import{t as S}from"./LightThemePlugin-wHpjmbXj.mjs";import{t as C}from"./DarkThemePlugin-GyV1mhmz.mjs";import{t as w}from"./ContextMenuPlugin-6qe5xYCu.mjs";import{t as T}from"./PerformanceOverlayPlugin-DlYhPYO-.mjs";import{t as E}from"./EventTooltipPlugin-DNGXHYbN.mjs";var ee=class{constructor(e,t){this.H_SCROLLBAR_PADDING=13,this.config=e,this.state=t}getContentWidth(e){if(this.cwZoom===e&&this.cwValue!==void 0)return this.cwValue;let t=this.config.endTime+this.config.endPaddingTime-this.config.startTime,n=this.config.startPaddingTime+t*this.config.secondWidth*e;return this.cwZoom=e,this.cwValue=n,n}invalidateCache(){this.cwZoom=void 0,this.cwValue=void 0}getContentHeight(){return this.config.timelineHeight+this.config.firstTrackTopMargin+this.state.tracks.length*(this.config.trackHeight+this.config.trackMargin)}computeMaxScrollX(e,t){let n=this.getContentWidth(e);return Math.max(0,n-t)}computeMaxScrollY(e){let t=this.getContentHeight();return Math.max(0,t-e)}hasHorizontalScrollbar(e,t){return this.getContentWidth(t)>e}getAvailableHeight(e,t,n){return e-(this.hasHorizontalScrollbar(t,n)?this.H_SCROLLBAR_PADDING:0)}computeMaxScrollYWithPadding(e,t,n){let r=this.getContentHeight(),i=this.getAvailableHeight(e,t,n);return Math.max(0,r-i)}};const D=_(`RenderPipeline`);let O=0;var k=class{constructor(){this.renderers=new Map,this.renderOrder=[`background`,`tracks`,`timeline`,`guideLines`,`indicator`,`interaction`,`scrollbar`,`overlay`],this.stats={layerTimes:{},totalTime:0,renderedLayers:0,skippedLayers:0}}registerRenderer(e,t){this.renderers.set(e,t)}unregisterRenderer(e){this.renderers.delete(e)}setRenderOrder(e){this.renderOrder=e}render(e,t={}){let n=performance.now(),{forceFullRender:r=!1,dirtyLayers:i,skipPerfMeasure:a=!1}=t,o=n-O>=250;o&&(O=n,D.debugStyled(b.pipeline,`▶ Render Start`,`forceFullRender=${r}`,i?`dirtyLayers=[${Array.from(i).join(`, `)}]`:`dirtyLayers=all`)),this.stats.renderedLayers=0,this.stats.skippedLayers=0,this.stats.layerTimes={};for(let t of this.renderOrder){let n=this.renderers.get(t);if(!n)continue;if(!this.shouldRenderLayer(t,n,e,r,i)){this.stats.skippedLayers++;continue}let o=a?0:performance.now();try{n.render(e),this.stats.renderedLayers++}catch(e){D.error(`Error rendering layer "${t}":`,e)}a||(this.stats.layerTimes[t]=performance.now()-o)}return this.stats.totalTime=performance.now()-n,o&&D.debugStyled(b.pipeline,`◀ Render End`,`rendered=${this.stats.renderedLayers}, skipped=${this.stats.skippedLayers}, time=${this.stats.totalTime.toFixed(2)}ms`),{...this.stats}}shouldRenderLayer(e,t,n,r,i){return r||!i?!0:i.has(e)}getStats(){return{...this.stats}}clearPrevContext(){}getRegisteredRenderers(){return this.renderers}},A=class{constructor(){this.name=`Timeline`,this.layer=`timeline`}render(e){let{ctx:t,config:n,state:r,width:i}=e;t.fillStyle=n.colors.timelineBackground,t.fillRect(0,0,i,n.timelineHeight);let a=[{threshold:10,main:10,sub:2,format:`HMS`},{threshold:8,main:30,sub:10,format:`HMS`},{threshold:5,main:60,sub:15,format:`HMS`},{threshold:3,main:300,sub:60,format:`HM`},{threshold:2,main:600,sub:120,format:`HM`},{threshold:1,main:1800,sub:600,format:`HM`},{threshold:.5,main:3600,sub:900,format:`H`},{threshold:0,main:7200,sub:1800,format:`H`}],o=a.find(e=>r.zoomLevel>=e.threshold)||a[a.length-1],s=n.startTime+(r.scrollX-n.startPaddingTime)/(n.secondWidth*r.zoomLevel),c=s+i/(n.secondWidth*r.zoomLevel),l=Math.max(n.startTime,Math.floor(s)),u=Math.min(n.endTime+n.endPaddingTime,Math.ceil(c));this.renderMainTicks(t,n,r,o,l,u,i),this.renderSubTicks(t,n,r,o,l,u,i),r.zoomLevel>=10&&this.renderMicroTicks(t,n,r,o,l,u,i)}renderMainTicks(e,t,n,r,i,a,o){let s=r.main,c=Math.floor(i/s)*s,l=-80;e.strokeStyle=t.colors.timelineGrid,e.lineWidth=1.5,e.fillStyle=t.colors.timelineText,e.font=`12px Arial`;for(let i=c;i<=a;i+=s){let a=i-t.startTime,s=t.startPaddingTime+a*t.secondWidth*n.zoomLevel-n.scrollX;if(s>=-50&&s<=o+50){let n=i>t.endTime;s-l>=80&&(e.strokeStyle=n?`rgba(150, 155, 165, 0.3)`:t.colors.timelineGrid,e.beginPath(),e.moveTo(s,0),e.lineTo(s,20),e.stroke(),e.fillStyle=n?`rgba(150, 155, 165, 0.4)`:t.colors.timelineText,e.textAlign=`center`,e.fillText(this.formatTime(i,r.format),s+28,20),l=s)}}}renderSubTicks(e,t,n,r,i,a,o){let s=r.sub,c=r.main,l=Math.floor(i/s)*s;e.lineWidth=1,e.strokeStyle=t.colors.timelineSubGrid;for(let r=l;r<=a;r+=s){if(r%c===0)continue;let i=r-t.startTime,a=t.startPaddingTime+i*t.secondWidth*n.zoomLevel-n.scrollX;a>=0&&a<=o&&(e.globalAlpha=r>t.endTime?.3:.75,e.beginPath(),e.moveTo(a,0),e.lineTo(a,8),e.stroke(),e.globalAlpha=1)}}renderMicroTicks(e,t,n,r,i,a,o){let s=r.sub/2,c=Math.floor(i/s)*s;e.lineWidth=1,e.strokeStyle=t.colors.timelineSubGrid,e.globalAlpha=.3;for(let i=c;i<=a;i+=s){if(i%r.sub===0)continue;let a=i-t.startTime,s=t.startPaddingTime+a*t.secondWidth*n.zoomLevel-n.scrollX;s>=0&&s<=o&&(e.beginPath(),e.moveTo(s,0),e.lineTo(s,4),e.stroke())}e.globalAlpha=1}formatTime(e,t){let n=Math.floor(e/3600),r=Math.floor(e%3600/60),i=Math.floor(e%60);switch(t){case`HMS`:return`${n.toString().padStart(2,`0`)}:${r.toString().padStart(2,`0`)}:${i.toString().padStart(2,`0`)}`;case`HM`:return`${n.toString().padStart(2,`0`)}:${r.toString().padStart(2,`0`)}`;case`H`:return`${n.toString().padStart(2,`0`)}:00`;default:return`${n.toString().padStart(2,`0`)}:${r.toString().padStart(2,`0`)}`}}shouldRender(e,t){if(!t)return!0;let{config:n,state:r}=e,{config:i,state:a}=t;return r.zoomLevel!==a.zoomLevel||r.scrollX!==a.scrollX||n.startTime!==i.startTime||n.endTime!==i.endTime||n.timelineHeight!==i.timelineHeight}};const j=_(`EventsRenderer`),M=new Map;var te=class{renderEvents(e,t,n,r,i,a,o,s){let l=s??a.width,u=n.tracks[r],d=Math.max(5,t.trackHeight*.0625),f=t.trackHeight-d*2,p=t.eventTextStyle,m=p.titleFontSize===`auto`?Math.max(10,Math.min(14,t.trackHeight*.175)):p.titleFontSize,h=p.timeFontSize===`auto`?Math.max(8,Math.min(12,t.trackHeight*.15)):p.timeFontSize,g=performance.now();g-(M.get(r)??0)>=500&&(M.set(r,g),j.debugStyled(b.eventRender,`Track ${r}: ${u.events.length} events`));for(let s=0;s<u.events.length;s++){let g=u.events[s];if(n.draggingEvent&&n.draggingEvent.isDragging&&n.draggingEvent.trackIndex===r&&n.draggingEvent.eventIndex===s)continue;let _=t.startPaddingTime+(g.startTime-t.startTime)*t.secondWidth*n.zoomLevel-n.scrollX,v=g.duration*t.secondWidth*n.zoomLevel;if(_+v<0||_>l)continue;let y=n.selectedEvent&&n.selectedEvent.trackIndex===r&&n.selectedEvent.eventIndex===s,b=n.highlightedEvent&&n.highlightedEvent.trackIndex===r&&n.highlightedEvent.eventIndex===s,x=n.timeIndicatorPosition,S=t.enableTimeIndicator&&!n.isManualSelection&&x>g.startTime&&x<g.endTime,C=y||b||S;e.save();let w=t.eventBlockStyle.borderRadius;e.fillStyle=g.color,w>0?(c(e,_,i+d,v,f,w),e.fill()):e.fillRect(_,i+d,v,f),C&&(e.strokeStyle=t.colors.eventBorderSelected,e.lineWidth=2,t.eventBlockStyle.enableSelectionGlow&&(e.shadowColor=t.colors.eventBorderSelected,e.shadowBlur=t.eventBlockStyle.selectionGlowBlur),w>0?(c(e,_,i+d,v,f,w),e.stroke()):e.strokeRect(_,i+d,v,f),e.shadowBlur=0),C&&(e.fillStyle=t.colors.eventOverlay,w>0?(c(e,_,i+d,v,f,w),e.fill()):e.fillRect(_,i+d,v,f)),e.restore(),o&&o.emitEvent(`render:event:media`,e,a,t,n,r,s,_,i,v,d,f),this.drawEventText(e,t,g,_,i,v,d,m,h,p),t.enableEventResize&&this.drawResizeHandles(e,t,n,r,s,_,i,v,f,d),t.showEventDurationLabel&&C&&this.drawEventDurationLabel(e,t,g,_,i,v,d),t.enableEventSplit&&n.hoveredSplitLine&&!n.draggingEvent&&!n.resizingEvent&&!n.draggingTimeIndicator&&this.drawSplitLine(e,t,n,r,s,i,d,f)}}truncateText(e,t,n){if(n<=0)return``;if(e.measureText(t).width<=n)return t;if(e.measureText(`...`).width>=n)return`...`;let r=0,i=t.length,a=``;for(;r<i;){let o=Math.floor((r+i+1)/2),s=t.substring(0,o)+`...`;e.measureText(s).width<=n?(a=s,r=o):i=o-1}return a||`...`}drawEventText(e,t,n,r,i,a,o,s,c,u){let d=u.titleColor||t.colors.eventText,f=u.timeColor||t.colors.eventText,p={left:r+10,right:r+a-10,center:r+a/2}[u.textAlign]??r+a/2,m={top:i+o+s,middle:i+t.trackHeight/2,bottom:i+t.trackHeight-o}[u.verticalAlign]??i+o;e.textAlign=u.textAlign;let h=u.showTitle&&t.trackHeight>=u.minHeightForTitle,g=u.showTime&&t.trackHeight>=u.minHeightForTime,_=l(n.startTime,n.endTime),v=a-20;if(h){e.fillStyle=d,e.font=`${u.titleFontWeight} ${s}px ${u.titleFontFamily}`;let t=g?m-s/2+u.titleOffsetY:m+u.titleOffsetY,r=this.truncateText(e,n.title,v);e.fillText(r,p,t)}if(g){e.fillStyle=f,e.font=`${u.timeFontWeight} ${c}px ${u.timeFontFamily}`;let t=h?m+c+u.timeOffsetY:m+u.timeOffsetY,n=this.truncateText(e,_,v);e.fillText(n,p,t)}}drawResizeHandles(e,t,n,r,i,a,o,s,c,l){let u=n.hoveredResizeHandle&&n.hoveredResizeHandle.trackIndex===r&&n.hoveredResizeHandle.eventIndex===i,d=n.resizingEvent&&n.resizingEvent.trackIndex===r&&n.resizingEvent.eventIndex===i;if(n.selectedEvent&&n.selectedEvent.trackIndex===r&&n.selectedEvent.eventIndex===i||u||d){let r=t.resizeHandleWidth,i=`rgba(255, 255, 255, 0.8)`,f=`rgba(255, 255, 255, 1)`,p=u&&n.hoveredResizeHandle.edge===`left`,m=d&&n.resizingEvent.edge===`left`;e.fillStyle=p||m?f:i,e.fillRect(a-r/2,o+l,r,c);let h=u&&n.hoveredResizeHandle.edge===`right`,g=d&&n.resizingEvent.edge===`right`;e.fillStyle=h||g?f:i,e.fillRect(a+s-r/2,o+l,r,c)}}drawSplitLine(e,t,n,r,i,a,o,s){let c=n.hoveredSplitLine;if(c.trackIndex===r&&c.eventIndex===i){let r=(c.splitTime+t.startPaddingTime-t.startTime)*t.secondWidth*n.zoomLevel-n.scrollX;e.save(),e.strokeStyle=`rgba(255, 255, 0, 0.8)`,e.lineWidth=2,e.setLineDash([5,5]),e.beginPath(),e.moveTo(r,a+o),e.lineTo(r,a+o+s),e.stroke(),e.setLineDash([]),e.fillStyle=`rgba(255, 255, 0, 1)`,e.beginPath(),e.arc(r,a+o,4,0,Math.PI*2),e.fill(),e.beginPath(),e.arc(r,a+o+s,4,0,Math.PI*2),e.fill();let i=f(c.splitTime);e.font=`bold 11px Arial`,e.fillStyle=`rgba(255, 255, 0, 1)`,e.textAlign=`center`,e.fillText(`切割: ${i}`,r,a+o-5),e.restore()}}drawEventDurationLabel(e,t,n,r,a,o,s){e.save();let c=Math.round(n.duration*1e3)/1e3,l;l=t.formatEventDuration?t.formatEventDuration(c):i(c),e.font=`bold 11px Arial`,e.fillStyle=t.colors.eventDurationLabel,e.textAlign=`center`;let u=r+o/2,d=a+s-8;e.fillText(l,u,d),e.restore()}},ne=class{constructor(){this.name=`Tracks`,this.layer=`tracks`,this.eventsRenderer=new te}render(e){let{ctx:t,canvas:n,config:r,state:i,pluginManager:a,width:o,height:s}=e,c=r.startPaddingTime-i.scrollX,l=this.eventsRenderer;for(let e=0;e<i.tracks.length;e++){let u=r.timelineHeight+r.firstTrackTopMargin+e*(r.trackHeight+r.trackMargin)-i.scrollY;if(u+r.trackHeight<r.timelineHeight||u>s)continue;let d;d=e===i.selectedTrack||i.highlightedEvent&&i.highlightedEvent.trackIndex===e||i.selectedEvent&&i.selectedEvent.trackIndex===e?r.colors.trackBackgroundSelected:r.colors.trackBackgroundOdd&&r.colors.trackBackgroundEven?e%2==0?r.colors.trackBackgroundOdd:r.colors.trackBackgroundEven:r.colors.trackBackground,t.fillStyle=d;let f=o-c;f>0&&t.fillRect(c,u,f,r.trackHeight),l.renderEvents(t,r,i,e,u,n,a,o)}}shouldRender(e,t){if(!t)return!0;let{config:n,state:r}=e,{config:i,state:a}=t;return r.tracks!==a.tracks||r.scrollY!==a.scrollY||r.scrollX!==a.scrollX||r.zoomLevel!==a.zoomLevel||r.selectedEvent!==a.selectedEvent||r.highlightedEvent!==a.highlightedEvent||n.trackHeight!==i.trackHeight||n.trackMargin!==i.trackMargin}},re=class{constructor(){this.name=`Scrollbar`,this.layer=`scrollbar`}render(e){let{ctx:t,config:n,state:r,width:i,height:a}=e;this.drawVerticalScrollbar(t,n,r,i,a),this.drawHorizontalScrollbar(t,n,r,i,a)}drawVerticalScrollbar(e,t,n,r,i){let a=t.startPaddingTime+(t.endTime+t.endPaddingTime-t.startTime)*t.secondWidth*n.zoomLevel>r?13:0,o=t.timelineHeight+t.firstTrackTopMargin+n.tracks.length*(t.trackHeight+t.trackMargin);if(o>i-a){let s=r-8-5,l=t.timelineHeight,u=i-t.timelineHeight-a-5;e.fillStyle=t.colors.scrollbarTrack,c(e,s,l,8,u,4);let d=(i-a-5)/o,f=Math.max(30,u*d),p=o-i+a+5,m=n.scrollY/p,h=l+(u-f)*m;e.fillStyle=n.draggingScrollbar?t.colors.scrollbarHandleHover:t.colors.scrollbarHandle,c(e,s,h,8,f,4),e.fillStyle=t.colors.scrollbarHandleHighlight,c(e,s,h,8,f/2,4),n.draggingScrollbar&&(e.strokeStyle=t.colors.scrollbarBorder,e.lineWidth=1,c(e,s,h,8,f,4,!0))}}drawHorizontalScrollbar(e,t,n,r,i){let a=t.startPaddingTime+(t.endTime+t.endPaddingTime-t.startTime)*t.secondWidth*n.zoomLevel;if(a<=r)return;let o=t.timelineHeight+t.firstTrackTopMargin+n.tracks.length*(t.trackHeight+t.trackMargin)>i?13:0,s=i-8-5,l=r-o;e.fillStyle=t.colors.scrollbarTrack,c(e,0,s,l,8,4);let u=r/a,d=Math.max(30,l*u),f=a-r,p=n.scrollX/f,m=0+(l-d)*p;e.fillStyle=n.draggingHorizontalScrollbar?t.colors.scrollbarHandleHover:t.colors.scrollbarHandle,c(e,m,s,d,8,4),e.fillStyle=t.colors.scrollbarHandleHighlight,c(e,m,s,d/2,8,4),n.draggingHorizontalScrollbar&&(e.strokeStyle=t.colors.scrollbarBorder,e.lineWidth=1,c(e,m,s,d,8,4,!0))}shouldRender(e,t){if(!t)return!0;let{state:n}=e,{state:r}=t;return n.scrollY!==r.scrollY||n.scrollX!==r.scrollX||n.draggingScrollbar!==r.draggingScrollbar||n.draggingHorizontalScrollbar!==r.draggingHorizontalScrollbar}},N=class{constructor(){this.name=`Indicator`,this.layer=`indicator`}render(e){let{ctx:t,config:n,state:r,width:i,height:a}=e;if(!n.enableTimeIndicator)return;let o=n.startPaddingTime+(r.timeIndicatorPosition-n.startTime)*n.secondWidth*r.zoomLevel-r.scrollX;if(o<-10||o>i+10)return;t.strokeStyle=n.colors.timeIndicator,t.lineWidth=n.timeIndicatorWidth,t.beginPath(),t.moveTo(o,n.timelineHeight),t.lineTo(o,a),t.stroke();let s=n.timeIndicatorHeadSize,c=n.timeIndicatorTriangleHeight,l=n.timelineHeight-s-c;t.fillStyle=n.colors.timeIndicator,t.fillRect(o-s/2,l,s,s),t.beginPath(),t.moveTo(o-s/2,l+s),t.lineTo(o+s/2,l+s),t.lineTo(o,l+s+c),t.closePath(),t.fill()}shouldRender(e,t){if(!t)return!0;let{config:n,state:r}=e,{config:i,state:a}=t;return n.enableTimeIndicator?r.timeIndicatorPosition!==a.timeIndicatorPosition||r.draggingTimeIndicator!==a.draggingTimeIndicator||r.scrollX!==a.scrollX||r.zoomLevel!==a.zoomLevel||n.timelineHeight!==i.timelineHeight:!1}},P=class{constructor(){this.name=`GuideLines`,this.layer=`guideLines`}render(e){let{ctx:t,config:n,state:r,width:i,height:a}=e;if(t.save(),r.guideLines.length>0){t.strokeStyle=n.colors.guideLine,t.lineWidth=2,t.setLineDash([5,5]);for(let e of r.guideLines){let o=n.startPaddingTime+(e.time-n.startTime)*n.secondWidth*r.zoomLevel-r.scrollX;o<-10||o>i+10||(t.beginPath(),t.moveTo(o,n.timelineHeight),t.lineTo(o,a),t.stroke(),t.setLineDash([]),t.fillStyle=n.colors.guideLineLabel,t.font=`bold 11px Arial`,t.textAlign=`center`,t.fillText(f(e.time),o,n.timelineHeight-5),t.setLineDash([5,5]))}}if(r.dragTimeReference){let e=n.startPaddingTime+(r.dragTimeReference.time-n.startTime)*n.secondWidth*r.zoomLevel-r.scrollX;if(e>=-10&&e<=i+10){let i=r.dragTimeReference.y-r.scrollY;t.strokeStyle=n.colors.dragTimeReferenceLine,t.lineWidth=2,t.setLineDash([8,4]),t.beginPath(),t.moveTo(e,n.timelineHeight),t.lineTo(e,i),t.stroke(),t.setLineDash([]),t.fillStyle=n.colors.dragTimeReferenceLabel,t.font=`bold 12px Arial`,t.textAlign=`center`;let a=f(r.dragTimeReference.time),o=t.measureText(a).width;t.fillStyle=n.colors.dragTimeReferenceLabelBackground,t.fillRect(e-o/2-4,n.timelineHeight-14-4-5,o+8,22),t.fillStyle=n.colors.dragTimeReferenceLabel,t.fillText(a,e,n.timelineHeight-5)}}t.restore()}shouldRender(e,t){if(!t)return!0;let{state:n}=e,{state:r}=t;return n.guideLines!==r.guideLines||n.dragTimeReference!==r.dragTimeReference||n.scrollX!==r.scrollX||n.scrollY!==r.scrollY||n.zoomLevel!==r.zoomLevel}},F=class{constructor(){this.name=`Interaction`,this.layer=`interaction`}render(e){let{ctx:t,config:n,state:r}=e;!r.draggingEvent||!r.draggingEvent.isDragging||(this.renderDragPreview(t,n,r),this.renderDraggingEvent(t,n,r))}renderDragPreview(e,t,n){if(!n.draggingEvent||!n.tracks[n.draggingEvent.trackIndex])return;let r=n.tracks[n.draggingEvent.trackIndex].events[n.draggingEvent.eventIndex];if(!r)return;let i=n.draggingEvent.currentMouseY||0,a=n.draggingEvent.canMove!==!1,o=Math.floor((i-t.timelineHeight-t.firstTrackTopMargin)/(t.trackHeight+t.trackMargin)),s=Math.max(0,Math.min(n.tracks.length-1,o)),l=t.timelineHeight+t.firstTrackTopMargin+s*(t.trackHeight+t.trackMargin),u=(n.draggingEvent.currentMouseX||0)-n.dragOffsetX,d=r.duration*t.secondWidth*n.zoomLevel,f=Math.max(5,t.trackHeight*.0625),p=t.trackHeight-f*2,m=t.eventBlockStyle.borderRadius;e.save(),a?(e.fillStyle=t.colors.dragPreviewValid,e.strokeStyle=t.colors.dragPreviewBorderValid):(e.fillStyle=t.colors.dragPreviewInvalid,e.strokeStyle=t.colors.dragPreviewBorderInvalid),e.lineWidth=2,e.setLineDash([5,5]),e.globalAlpha=.6,m>0?(c(e,u,l-n.scrollY+f,d,p,m),e.fill(),e.stroke()):(e.fillRect(u,l-n.scrollY+f,d,p),e.strokeRect(u,l-n.scrollY+f,d,p)),e.restore()}renderDraggingEvent(e,t,n){if(!n.draggingEvent||!n.tracks[n.draggingEvent.trackIndex].events)return;let r=n.tracks[n.draggingEvent.trackIndex].events[n.draggingEvent.eventIndex];if(!r)return;let i=n.draggingEvent.currentMouseX||0,a=n.draggingEvent.currentMouseY||0,o=i-n.dragOffsetX,s=a-n.dragOffsetY-n.scrollY,l=r.duration*t.secondWidth*n.zoomLevel,u=Math.max(5,t.trackHeight*.0625),d=t.trackHeight-u*2;e.save();let f=t.eventBlockStyle.borderRadius;e.fillStyle=r.color,f>0?(c(e,o,s+u,l,d,f),e.fill()):e.fillRect(o,s+u,l,d),e.strokeStyle=t.colors.eventBorderSelected,e.lineWidth=2,t.eventBlockStyle.enableSelectionGlow&&(e.shadowColor=t.colors.eventBorderSelected,e.shadowBlur=t.eventBlockStyle.selectionGlowBlur),f>0?(c(e,o,s+u,l,d,f),e.stroke()):e.strokeRect(o,s+u,l,d),e.shadowBlur=0,e.fillStyle=t.colors.eventOverlay,f>0?(c(e,o,s+u,l,d,f),e.fill()):e.fillRect(o,s+u,l,d),e.restore(),this.renderEventText(e,t,r,o,s,l,u)}renderEventText(e,t,n,r,i,a,o){let s=t.eventTextStyle,c=s.titleColor||t.colors.eventText,l=s.timeColor||t.colors.eventText,u={left:r+10,right:r+a-10,center:r+a/2}[s.textAlign]??r+a/2,d={top:i+o,middle:i+t.trackHeight/2,bottom:i+t.trackHeight-o}[s.verticalAlign]??i+o;e.textAlign=s.textAlign;let p=s.showTitle&&t.trackHeight>=s.minHeightForTitle,m=s.showTime&&t.trackHeight>=s.minHeightForTime,h=s.titleFontSize===`auto`?Math.max(10,Math.min(14,t.trackHeight*.175)):s.titleFontSize,g=s.timeFontSize===`auto`?Math.max(8,Math.min(12,t.trackHeight*.15)):s.timeFontSize,_=`${f(n.startTime)} - ${f(n.endTime)}`;if(p){e.fillStyle=c,e.font=`${s.titleFontWeight} ${h}px ${s.titleFontFamily}`;let t=m?d-(typeof h==`number`?h:14)/2+s.titleOffsetY:d+s.titleOffsetY;e.fillText(n.title,u,t)}if(m){e.fillStyle=l,e.font=`${s.timeFontWeight} ${g}px ${s.timeFontFamily}`;let t=p?d+(typeof g==`number`?g:12)+s.timeOffsetY:d+s.timeOffsetY;e.fillText(_,u,t)}}shouldRender(e,t){if(!t)return!0;let{state:n}=e,{state:r}=t;return!!(n.draggingEvent!==r.draggingEvent||n.draggingEvent&&r.draggingEvent&&(n.draggingEvent.currentMouseX!==r.draggingEvent.currentMouseX||n.draggingEvent.currentMouseY!==r.draggingEvent.currentMouseY))}};function I(e,t,n,r,i,a){return{ctx:e,canvas:t,config:n,state:r,dpr:i,width:t.width/i,height:t.height/i,pluginManager:a}}const L=_(`LayerBuffer`),R={background:`background`,tracks:`main`,timeline:`main`,guideLines:`main`,indicator:`main`,scrollbar:`main`,interaction:`interaction`,overlay:`overlay`},z=[`background`,`main`,`media`,`interaction`,`overlay`];function B(e,t){if(typeof OffscreenCanvas<`u`)try{let n=new OffscreenCanvas(e,t),r=n.getContext(`2d`);if(r)return{canvas:n,ctx:r}}catch{}let n=document.createElement(`canvas`);return n.width=e,n.height=t,{canvas:n,ctx:n.getContext(`2d`)}}var V=class{constructor(){this.buffers=new Map,this.width=0,this.height=0,this.dpr=1}initialize(e,t,n){this.width=e,this.height=t,this.dpr=n;let r=Math.max(1,Math.floor(e*n)),i=Math.max(1,Math.floor(t*n));for(let e of z){let t=this.buffers.get(e);if(t)t.canvas.width=r,t.canvas.height=i,t.dirty=!0;else{let{canvas:t,ctx:n}=B(r,i);this.buffers.set(e,{canvas:t,ctx:n,dirty:!0})}}L.debugStyled(b.pipeline,`LayerBufferManager initialized: ${r}x${i} (dpr=${n})`)}markDirtyFromLayers(e){for(let t of e){let e=R[t];if(e){let t=this.buffers.get(e);t&&(t.dirty=!0)}}}markDirty(e){let t=this.buffers.get(e);t&&(t.dirty=!0)}markAllDirty(){for(let e of this.buffers.values())e.dirty=!0}getBuffer(e){return this.buffers.get(e)}isDirty(e){return this.buffers.get(e)?.dirty??!0}clearDirty(e){let t=this.buffers.get(e);t&&(t.dirty=!1)}compositeToMain(e,t,n){e.save(),e.setTransform(1,0,0,1,0,0),e.clearRect(0,0,t,n);for(let t of z){let n=this.buffers.get(t);n&&e.drawImage(n.canvas,0,0)}e.restore()}isInitialized(){return this.buffers.size>0}getSize(){return{width:this.width,height:this.height,dpr:this.dpr}}dispose(){this.buffers.clear(),this.width=0,this.height=0}};const H=_(`DirtyCheck`);var U=class{constructor(e,t,n,r,i){this.cachedLogicalWidth=0,this.cachedLogicalHeight=0,this.cacheValid=!1,this.dirtyLayers=new Set([`background`,`tracks`,`timeline`,`guideLines`,`indicator`,`scrollbar`,`overlay`,`interaction`]),this.lastLayerTimes={},this.isFirstRender=!0,this.canvas=e,this.ctx=t,this.config=n,this.state=r,this.pluginManager=i,this.dpr=window.devicePixelRatio||1,this.logicalCanvas={width:0,height:0,getContext:this.canvas.getContext.bind(this.canvas)},this.viewport=new ee(this.config,this.state),this.layerBufferManager=new V,this.renderPipeline=new k,this.renderPipeline.registerRenderer(`timeline`,new A),this.renderPipeline.registerRenderer(`tracks`,new ne),this.renderPipeline.registerRenderer(`guideLines`,new P),this.renderPipeline.registerRenderer(`indicator`,new N),this.renderPipeline.registerRenderer(`scrollbar`,new re),this.renderPipeline.registerRenderer(`interaction`,new F)}setCanvasSize(e,t){let n=Math.floor(e*this.dpr),r=Math.floor(t*this.dpr);if(Math.abs(this.canvas.width-n)<1&&Math.abs(this.canvas.height-r)<1)return;this.canvas.width=n,this.canvas.height=r,this.canvas.style.width=`${e}px`,this.canvas.style.height=`${t}px`,this.invalidateCache();let i=this.getContentHeight(),a=Math.max(0,i-this.getCachedLogicalHeight());this.state.scrollY=Math.max(0,Math.min(a,this.state.scrollY)),this.state.zoomLevel<this.config.minAutoFitZoom&&(this.state.zoomLevel=this.config.minAutoFitZoom,this.state.scrollX=0),this.markAllDirty(),this.draw()}getCanvasLogicalWidth(){return this.canvas.width/this.dpr}getCanvasLogicalHeight(){return this.canvas.height/this.dpr}getCachedLogicalWidth(){return this.cacheValid||=(this.cachedLogicalWidth=this.canvas.width/this.dpr,this.cachedLogicalHeight=this.canvas.height/this.dpr,!0),this.cachedLogicalWidth}getCachedLogicalHeight(){return this.cacheValid||=(this.cachedLogicalWidth=this.canvas.width/this.dpr,this.cachedLogicalHeight=this.canvas.height/this.dpr,!0),this.cachedLogicalHeight}invalidateCache(){this.cacheValid=!1}draw(){if(this.dirtyLayers.size===0&&!this.isFirstRender)return;this.pluginManager.measureStart(`draw`);let e=this.canvas.width/this.dpr,t=this.canvas.height/this.dpr;this.logicalCanvas.width=e,this.logicalCanvas.height=t;let n=this.logicalCanvas,r=this.layerBufferManager.getSize();if((!this.layerBufferManager.isInitialized()||r.width!==e||r.height!==t||r.dpr!==this.dpr)&&this.layerBufferManager.initialize(e,t,this.dpr),this.isFirstRender?this.layerBufferManager.markAllDirty():this.layerBufferManager.markDirtyFromLayers(this.dirtyLayers),this.layerBufferManager.isDirty(`background`)){let e=this.layerBufferManager.getBuffer(`background`),t=performance.now();e.ctx.clearRect(0,0,e.canvas.width,e.canvas.height),e.ctx.save(),e.ctx.scale(this.dpr,this.dpr),this.pluginManager.renderBackground(e.ctx,n,this.config,this.state),e.ctx.restore(),this.layerBufferManager.clearDirty(`background`),this.lastLayerTimes.background=performance.now()-t}if(this.layerBufferManager.isDirty(`main`)){let e=this.layerBufferManager.getBuffer(`main`);e.ctx.clearRect(0,0,e.canvas.width,e.canvas.height),e.ctx.save(),e.ctx.scale(this.dpr,this.dpr);let t=I(e.ctx,this.canvas,this.config,this.state,this.dpr,this.pluginManager);this.renderPipeline.render(t,{forceFullRender:!1,dirtyLayers:new Set([`tracks`,`timeline`,`guideLines`,`indicator`,`scrollbar`])}),e.ctx.restore(),this.layerBufferManager.clearDirty(`main`);let n=this.renderPipeline.getStats();this.lastLayerTimes={...this.lastLayerTimes,...n.layerTimes}}if(this.layerBufferManager.isDirty(`media`)&&this.layerBufferManager.clearDirty(`media`),this.layerBufferManager.isDirty(`interaction`)){let e=this.layerBufferManager.getBuffer(`interaction`);e.ctx.clearRect(0,0,e.canvas.width,e.canvas.height),e.ctx.save(),e.ctx.scale(this.dpr,this.dpr);let t=I(e.ctx,this.canvas,this.config,this.state,this.dpr,this.pluginManager);this.renderPipeline.render(t,{forceFullRender:!1,dirtyLayers:new Set([`interaction`])}),e.ctx.restore(),this.layerBufferManager.clearDirty(`interaction`)}if(this.layerBufferManager.isDirty(`overlay`)){let e=this.layerBufferManager.getBuffer(`overlay`),t=performance.now();e.ctx.clearRect(0,0,e.canvas.width,e.canvas.height),e.ctx.save(),e.ctx.scale(this.dpr,this.dpr),this.pluginManager.renderOverlay(e.ctx,n,this.config,this.state),e.ctx.restore(),this.layerBufferManager.clearDirty(`overlay`),this.lastLayerTimes.overlay=performance.now()-t}this.layerBufferManager.compositeToMain(this.ctx,this.canvas.width,this.canvas.height),this.isFirstRender&&=!1,this.pluginManager.measureEnd(`draw`),this.dirtyLayers.clear()}getContentWidth(e){return this.viewport.getContentWidth(e)}getContentHeight(){return this.viewport.getContentHeight()}computeMaxScrollX(e){return this.viewport.computeMaxScrollX(e,this.getCachedLogicalWidth())}computeMaxScrollY(){return this.viewport.computeMaxScrollYWithPadding(this.getCachedLogicalHeight(),this.getCachedLogicalWidth(),this.state.zoomLevel)}hasHorizontalScrollbar(){return this.viewport.hasHorizontalScrollbar(this.getCachedLogicalWidth(),this.state.zoomLevel)}getAvailableHeight(){return this.viewport.getAvailableHeight(this.getCachedLogicalHeight(),this.getCachedLogicalWidth(),this.state.zoomLevel)}invalidateLayoutCache(){this.viewport.invalidateCache()}markDirty(e){H.debugStyled(b.dataUpdate,`✓ Marking layers dirty: [${e.join(`, `)}]`);for(let t of e)this.dirtyLayers.add(t)}markAllDirty(){H.debugStyled(b.dataUpdate,`✓ Marking ALL layers dirty`),this.dirtyLayers=new Set([`background`,`tracks`,`timeline`,`guideLines`,`indicator`,`scrollbar`,`overlay`,`interaction`]),this.layerBufferManager.markAllDirty()}getLastLayerTimes(){return{...this.lastLayerTimes}}},W=class{constructor(e){this.timeline=e}createContext(e){let t=this.timeline.getCanvas().getBoundingClientRect(),n=this.timeline.state;return{canvasX:e.clientX-t.left,canvasY:e.clientY-t.top,logicalX:e.clientX-t.left+n.scrollX,logicalY:e.clientY-t.top+n.scrollY,originalEvent:e,canvasWidth:t.width,canvasHeight:t.height}}handleMouseDown(e){return null}handleMouseMove(e){return null}handleMouseUp(e){return null}handleContextMenu(e){return null}};const G=_(`DraggingState`);var K=class extends W{constructor(e){super(e),this.name=`Dragging`,this.MOVE_THRESHOLD=5}onEnter(){this.timeline.beginIndexBatch()}onExit(){let e=this.timeline.state;e.guideLines=[],e.dragTimeReference=null,this.timeline.endIndexBatch(),this.timeline.autoRemoveEmptyLastTrack()}handleMouseMove(t){let{logicalX:n,logicalY:i}=t,o=this.timeline.config,s=this.timeline.state,c=this.timeline.getCanvas();if(!s.draggingEvent)return this.createIdleState();if(Math.sqrt((n-s.draggingEvent.startX)**2+(i-s.draggingEvent.startY)**2)>this.MOVE_THRESHOLD&&(s.draggingEvent.isDragging=!0),!s.draggingEvent.isDragging)return c.style.cursor=`move`,null;let{trackIndex:l,eventIndex:u}=s.draggingEvent;if(l<0||l>=s.tracks.length||u<0||u>=s.tracks[l].events.length)return G.warn(`当前错误的状态:`,{value:s.draggingEvent}),s.draggingEvent=null,this.createIdleState();let d=s.tracks[l].events[u];this.timeline.setStatus(`正在拖动: ${d.title}`);let f=(n-s.draggingEvent.startX)/(o.secondWidth*s.zoomLevel),p=s.draggingEvent.originalStartTime+f,m=Math.floor((i-o.timelineHeight-o.firstTrackTopMargin)/(o.trackHeight+o.trackMargin));if(o.autoAddTrack&&m>=s.tracks.length){let e={id:s.tracks.length,events:[]};s.tracks.push(e),this.timeline.setStatus(`自动新增轨道 ${s.tracks.length}`),this.timeline.callbacks.onTrackAdd&&this.timeline.callbacks.onTrackAdd(e)}m=Math.max(0,Math.min(s.tracks.length-1,m)),s.guideLines=this.timeline.calculateGuideLines(l,u,m,p,d.duration);let h=this.timeline.snapToGuideLines(p,d.duration);if(h!==null)p=h;else if(s.snapEnabled)if(o.enableTimeIndicator&&s.timeIndicatorSnapEnabled){let t=g(s.timeIndicatorPosition,o.startTime,o.startPaddingTime,o.secondWidth,s.zoomLevel,s.scrollX),n=o.startPaddingTime+(p-o.startTime)*o.secondWidth*s.zoomLevel-s.scrollX;if(Math.abs(n-t)<o.timeIndicatorSnapThreshold)p=s.timeIndicatorPosition;else{let t=a(s.zoomLevel,o.snapInterval,o.snapToSeconds,o.secondPrecisionZoomThreshold);p=e(p,t)}}else{let t=a(s.zoomLevel,o.snapInterval,o.snapToSeconds,o.secondPrecisionZoomThreshold);p=e(p,t)}p=Math.max(o.startTime,Math.min(o.endTime-d.duration,p));let _=o.timelineHeight+o.firstTrackTopMargin+m*(o.trackHeight+o.trackMargin)+o.trackHeight/2;s.dragTimeReference={time:p,y:_};let v=this.timeline.canMoveEvent(l,u,m,p,d.duration);if(v&&(d.startTime=p,d.endTime=r(p+d.duration),this.timeline.invalidateIndexTrack(l),m!==l)){let e=s.tracks[l].events.splice(u,1)[0];s.tracks[m].events.push(e),s.draggingEvent.trackIndex=m,s.draggingEvent.eventIndex=s.tracks[m].events.length-1,s.selectedTrack=m,s.selectedEvent&&s.selectedEvent.trackIndex===l&&(s.selectedEvent.eventIndex===u?s.selectedEvent={trackIndex:m,eventIndex:s.tracks[m].events.length-1}:s.selectedEvent.eventIndex>u&&(s.selectedEvent={...s.selectedEvent,eventIndex:s.selectedEvent.eventIndex-1})),this.timeline.invalidateIndexTrack(m),this.timeline.invalidateIndexTrack(l)}return s.draggingEvent&&(s.draggingEvent.currentMouseX=n,s.draggingEvent.currentMouseY=i,s.draggingEvent.canMove=v),this.timeline.notifyChange(`events:move`),null}handleMouseUp(e){let t=this.timeline.state;if(!t.draggingEvent)return this.createIdleState();let{trackIndex:n,eventIndex:r,originalTrackIndex:i,originalEventIndex:a}=t.draggingEvent;if(n<0||n>=t.tracks.length)return G.warn(`无法找到拖拽的事件, 放弃操作`,{trackIndex:n,eventIndex:r}),t.draggingEvent=null,this.createIdleState();let o=t.tracks[n]?.events[r];if(!o)return G.warn(`无法找到拖拽的事件, 放弃操作`,{trackIndex:n,eventIndex:r}),t.draggingEvent=null,this.createIdleState();let s=t.selectedEvent&&t.selectedEvent.trackIndex===i&&t.selectedEvent.eventIndex===a;return t.draggingEvent.isDragging?(this.timeline.setStatus(`已放置: ${o.title} (${this.timeline.formatTime(o.startTime)} - ${this.timeline.formatTime(o.endTime)})`),s&&(t.selectedEvent={trackIndex:n,eventIndex:r}),this.timeline.callbacks.onEventMove&&this.timeline.callbacks.onEventMove({trackIndex:n,eventIndex:r,event:u(o),fromTrackIndex:i})):(t.selectedEvent={trackIndex:n,eventIndex:r},this.timeline.setStatus(`已选中: ${o.title}`),this.timeline.callbacks.onEventClick&&this.timeline.callbacks.onEventClick({trackIndex:n,eventIndex:r,event:u(o),trackName:`轨道 ${n+1}`,formattedTimeRange:`${this.timeline.formatTime(o.startTime)} - ${this.timeline.formatTime(o.endTime)}`})),t.draggingEvent=null,this.timeline.notifyChange(`events:move`),this.createIdleState()}createIdleState(){return new X(this.timeline)}},q=class extends W{constructor(e){super(e),this.name=`Resizing`}onEnter(){this.timeline.beginIndexBatch()}onExit(){this.timeline.endIndexBatch()}handleMouseMove(t){let{logicalX:n}=t,i=this.timeline.config,o=this.timeline.state;if(!o.resizingEvent)return this.createIdleState();let{trackIndex:s,eventIndex:c,edge:l,originalStartTime:u,originalDuration:d}=o.resizingEvent;if(s<0||s>=o.tracks.length||c<0||c>=o.tracks[s].events.length)return o.resizingEvent=null,this.createIdleState();let f=o.tracks[s].events[c],p=(n-o.resizingEvent.startX)/(i.secondWidth*o.zoomLevel);if(l===`left`){let t=u+p,n=r(u+d);if(o.snapEnabled){let n=a(o.zoomLevel,i.snapInterval,i.snapToSeconds,i.secondPrecisionZoomThreshold);t=e(t,n)}t=r(Math.max(i.startTime,t)),t=r(Math.min(t,n-i.minEventDuration));let l=r(n-t),m=!0;for(let e=0;e<o.tracks[s].events.length;e++){if(e===c)continue;let r=o.tracks[s].events[e],i=r.startTime,a=i+r.duration;if(t<a&&n>i){m=!1;break}}if(m){if(!this.timeline.canMoveEvent(s,c,s,t,l))return this.timeline.notifyChange(`events:update`),null;f.startTime=t,f.duration=r(l),f.endTime=n,this.timeline.invalidateIndexTrack(s)}}else{let t=d+p;if(o.snapEnabled){let n=a(o.zoomLevel,i.snapInterval,i.snapToSeconds,i.secondPrecisionZoomThreshold);t=r(e(u+t,n)-u)}else t=r(t);t=r(Math.max(i.minEventDuration,t)),t=r(Math.min(t,i.endTime-u));let n=u+t,l=!0;for(let e=0;e<o.tracks[s].events.length;e++){if(e===c)continue;let t=o.tracks[s].events[e],r=t.startTime;if(u<r+t.duration&&n>r){l=!1;break}}if(l){if(!this.timeline.canMoveEvent(s,c,s,u,t))return this.timeline.notifyChange(`events:update`),null;f.duration=r(t),f.endTime=r(u+t),this.timeline.invalidateIndexTrack(s)}}return this.timeline.notifyChange(`events:update`),this.timeline.setStatus(`调整大小: ${this.timeline.formatTime(f.startTime)} - ${this.timeline.formatTime(f.endTime)}`),null}handleMouseUp(e){let t=this.timeline.state;if(!t.resizingEvent)return this.createIdleState();let{trackIndex:n,eventIndex:r}=t.resizingEvent;if(n<0||n>=t.tracks.length||r<0||r>=t.tracks[n].events.length)return t.resizingEvent=null,this.createIdleState();let i=t.tracks[n].events[r];return t.resizingEvent=null,this.timeline.getCanvas().style.cursor=`default`,this.timeline.setStatus(`已调整事件大小: ${i.title}`),this.timeline.callbacks.onEventUpdate&&this.timeline.callbacks.onEventUpdate({type:`resize`,trackIndex:n,eventIndex:r,event:u(i)}),this.timeline.notifyChange(`events:update`),this.createIdleState()}createIdleState(){return new X(this.timeline)}},J=class extends W{constructor(e){super(e),this.name=`Scrolling`}handleMouseMove(e){let{canvasX:t,canvasY:n,canvasWidth:r,canvasHeight:i}=e,a=this.timeline.config,o=this.timeline.state;if(o.draggingScrollbar){let e=a.timelineHeight+a.firstTrackTopMargin+o.tracks.length*(a.trackHeight+a.trackMargin),t=i-(a.startPaddingTime+(a.endTime+a.endPaddingTime-a.startTime)*a.secondWidth*o.zoomLevel>r?13:0),s=t-a.timelineHeight-5,c=t/e,l=Math.max(30,s*c),u=Math.max(0,e-t),d=(n-a.timelineHeight-o.scrollbarDragOffset)/(s-l);return o.scrollY=Math.max(0,Math.min(u,d*u)),this.timeline.notifyChange(`scroll:y`),null}if(o.draggingHorizontalScrollbar){let e=a.startPaddingTime+(a.endTime+a.endPaddingTime-a.startTime)*a.secondWidth*o.zoomLevel,n=r,i=r/e,s=Math.max(30,n*i),c=Math.max(0,e-r),l=(t-o.horizontalScrollbarDragOffset)/(n-s);return o.scrollX=Math.max(0,Math.min(c,l*c)),this.timeline.notifyChange(`scroll:x`),null}return null}handleMouseUp(e){let t=this.timeline.state;return t.draggingScrollbar&&(t.draggingScrollbar=!1,this.timeline.setStatus(`就绪`)),t.draggingHorizontalScrollbar&&(t.draggingHorizontalScrollbar=!1,this.timeline.setStatus(`就绪`)),this.createIdleState()}createIdleState(){return new X(this.timeline)}},Y=class extends W{constructor(e){super(e),this.name=`TimeIndicatorDrag`}handleMouseMove(t){let{canvasX:n}=t,r=this.timeline.config,i=this.timeline.state,o=this.timeline.getCanvas();if(!i.draggingTimeIndicator)return this.createIdleState();o.style.cursor=r.readOnly?`not-allowed`:`ew-resize`;let s=(n-i.timeIndicatorDragOffsetX+i.scrollX-r.startPaddingTime)/(r.secondWidth*i.zoomLevel)+r.startTime;if(i.snapEnabled){let t=a(i.zoomLevel,r.snapInterval,r.snapToSeconds,r.secondPrecisionZoomThreshold);s=e(s,t)}return s=Math.max(r.startTime,Math.min(r.endTime,s)),this.timeline.setTimeIndicatorDuringDrag(s),null}handleMouseUp(e){let t=this.timeline.state;return t.draggingTimeIndicator&&(t.draggingTimeIndicator=!1,this.timeline.setTimeIndicator(t.timeIndicatorPosition,!1)),this.createIdleState()}createIdleState(){return new X(this.timeline)}},X=class extends W{constructor(e){super(e),this.name=`Idle`}handleMouseDown(e){let{canvasX:t,canvasY:n,logicalX:r,logicalY:i,canvasWidth:a,canvasHeight:o,originalEvent:s}=e,c=this.timeline.config,d=this.timeline.state,f=this.timeline.getCanvas(),p=c.readOnly;if(s.button===2)return null;if(d.contextMenuVisible){let e=d.contextMenuBounds;if(e){let r=e.x,i=e.y,a=e.width,o=e.height;if(t>=r&&t<=r+a&&n>=i&&n<=i+o){let t=Math.floor((n-i-e.padding)/e.itemHeight);if(t>=0&&t<c.contextMenuItems.length&&d.contextMenuEvent){let e=c.contextMenuItems[t],{trackIndex:n,eventIndex:r}=d.contextMenuEvent,i=d.tracks[n].events[r];if(i.readonly&&(e.type===`delete`||e.type===`edit`))return this.timeline.setStatus(`只读事件不可编辑或删除`),d.contextMenuVisible=!1,d.contextMenuEvent=null,this.timeline.notifyChange(`interaction:contextMenu`),null;this.timeline.callbacks.onContextMenu&&this.timeline.callbacks.onContextMenu({menuType:e.type,trackIndex:n,eventIndex:r,event:u(i)}),d.contextMenuVisible=!1,d.contextMenuEvent=null,this.timeline.notifyChange(`interaction:contextMenu`)}return null}else d.contextMenuVisible=!1,d.contextMenuEvent=null,this.timeline.notifyChange(`interaction:contextMenu`)}}let m=c.timelineHeight+c.firstTrackTopMargin+d.tracks.length*(c.trackHeight+c.trackMargin),h=this.timeline.getAvailableHeight();if(m>h){let e=a-8-5,r=c.timelineHeight,i=h-c.timelineHeight-5;if(t>=e&&t<=e+8&&n>=r&&n<=r+i){d.draggingScrollbar=!0;let e=h/m,t=Math.max(30,i*e),a=m-h,o=d.scrollY/a;return d.scrollbarDragOffset=n-(r+(i-t)*o),this.createScrollingState()}}let _=this.timeline.getContentWidthForZoom(d.zoomLevel);if(_>a){let e=o-8-5,r=a;if(n>=e&&n<=e+8&&t>=0&&t<=0+r){d.draggingHorizontalScrollbar=!0;let e=a/_,n=Math.max(30,r*e),i=_-a,o=d.scrollX/i;return d.horizontalScrollbarDragOffset=t-(0+(r-n)*o),this.createScrollingState()}}if(c.enableTimeIndicator&&!p){let e=g(d.timeIndicatorPosition,c.startTime,c.startPaddingTime,c.secondWidth,d.zoomLevel,d.scrollX),r=c.timeIndicatorHeadSize,i=c.timeIndicatorTriangleHeight,a=c.timelineHeight-r-i;if(t>=e-r/2&&t<=e+r/2&&n>=a&&n<=c.timelineHeight)return d.draggingTimeIndicator=!0,d.timeIndicatorDragOffsetX=t-e,this.createTimeIndicatorDragState()}if(i<c.timelineHeight)return null;let v=this.timeline.getInteractionTarget(t,n);if(c.enableEventResize&&!p&&v.resizeEdge){let e=d.tracks[v.trackIndex].events[v.eventIndex];return e.readonly?(f.style.cursor=`not-allowed`,null):(d.resizingEvent={trackIndex:v.trackIndex,eventIndex:v.eventIndex,edge:v.resizeEdge,startX:r,originalStartTime:e.startTime,originalDuration:e.duration},this.createResizingState())}if(v.eventIndex!==null&&v.trackIndex!==null){let e=v.trackIndex,t=v.eventIndex,n=d.tracks[e].events[t],a=Date.now();if(d.lastClickEvent&&d.lastClickEvent.trackIndex===e&&d.lastClickEvent.eventIndex===t&&a-d.lastClickTime<300&&c.enableEventSplit){if(n.readonly)return this.timeline.setStatus(`只读事件不可切割`),d.lastClickTime=0,d.lastClickEvent=null,null;let i=(r-c.startPaddingTime)/(c.secondWidth*d.zoomLevel)+c.startTime;return this.timeline.splitEvent(e,t,i),d.lastClickTime=0,d.lastClickEvent=null,this.timeline.hideSplitLine(),null}if(d.lastClickEvent={trackIndex:e,eventIndex:t},d.lastClickTime=a,d.selectedEvent={trackIndex:e,eventIndex:t},d.isManualSelection=!0,d.highlightedEvent=null,d.selectedTrack=null,n.readonly||p)return f.style.cursor=`not-allowed`,this.timeline.setStatus(`已选中: ${n.title}`),this.timeline.callbacks.onEventHighlight&&this.timeline.callbacks.onEventHighlight({trackIndex:e,eventIndex:t,event:u(n)}),this.timeline.callbacks.onEventClick&&this.timeline.callbacks.onEventClick({trackIndex:e,eventIndex:t,event:u(n),trackName:`轨道 ${e+1}`,formattedTimeRange:l(n.startTime,n.endTime)}),this.timeline.notifyChange(`selection:change`),null;let o=c.startPaddingTime+(n.startTime-c.startTime)*c.secondWidth*d.zoomLevel-d.scrollX,s=c.timelineHeight+c.firstTrackTopMargin+e*(c.trackHeight+c.trackMargin);return d.draggingEvent={trackIndex:e,eventIndex:t,eventX:o,eventY:s,originalTrackIndex:e,originalEventIndex:t,originalStartTime:n.startTime,startX:r,startY:i,isDragging:!1},d.dragOffsetX=r-o,d.dragOffsetY=i-s,this.timeline.callbacks.onEventHighlight&&this.timeline.callbacks.onEventHighlight({trackIndex:e,eventIndex:t,event:u(n)}),this.timeline.notifyChange(`selection:change`),this.createDraggingState()}return d.selectedEvent=null,d.highlightedEvent=null,d.selectedTrack=null,d.isManualSelection=!1,this.timeline.callbacks.onEventHighlight&&this.timeline.callbacks.onEventHighlight({trackIndex:null,eventIndex:null,event:null}),this.timeline.notifyChange(`selection:change`),null}handleMouseMove(t){let{canvasX:n,canvasY:r,logicalX:i,logicalY:o}=t,s=this.timeline.config,c=this.timeline.state,l=this.timeline.getCanvas();if(c.contextMenuVisible){let e=c.contextMenuBounds;if(e){let t=e.x,i=e.y,a=e.width,o=e.height;if(n>=t&&n<=t+a&&r>=i&&r<=i+o){let t=Math.floor((r-i-e.padding)/e.itemHeight);return t>=0&&t<s.contextMenuItems.length?(c.hoveredContextMenuItem!==t&&(c.hoveredContextMenuItem=t,this.timeline.notifyChange(`interaction:contextMenu`)),l.style.cursor=`pointer`):c.hoveredContextMenuItem!==-1&&(c.hoveredContextMenuItem=-1,this.timeline.notifyChange(`interaction:contextMenu`)),null}else c.hoveredContextMenuItem!==-1&&(c.hoveredContextMenuItem=-1,this.timeline.notifyChange(`interaction:contextMenu`))}}let u=this.timeline.getInteractionTarget(n,r);if(o>=s.timelineHeight&&!s.readOnly){if(s.enableEventResize){if(u.resizeEdge)return c.tracks[u.trackIndex].events[u.eventIndex].readonly?(c.hoveredResizeHandle=null,l.style.cursor=`not-allowed`,this.timeline.hideSplitLine(),this.timeline.notifyChange(`interaction:hover`),null):(c.hoveredResizeHandle={trackIndex:u.trackIndex,eventIndex:u.eventIndex,edge:u.resizeEdge},l.style.cursor=`ew-resize`,this.timeline.hideSplitLine(),this.timeline.notifyChange(`interaction:hover`),null);c.hoveredResizeHandle=null}if(s.enableEventSplit){if(u.eventIndex!==null&&u.trackIndex!==null&&!u.resizeEdge){let t=u.trackIndex,n=u.eventIndex,r=c.tracks[t].events[n];if(r.readonly)return this.timeline.hideSplitLine(),l.style.cursor=`not-allowed`,this.timeline.notifyChange(`interaction:hover`),null;let o=(i-s.startPaddingTime)/(s.secondWidth*c.zoomLevel)+s.startTime;if(c.snapEnabled){let t=a(c.zoomLevel,s.snapInterval,s.snapToSeconds,s.secondPrecisionZoomThreshold);o=e(o,t)}let d=o-r.startTime,f=r.duration-d;if(o>r.startTime&&o<r.startTime+r.duration&&d>=s.minEventDuration&&f>=s.minEventDuration)return this.timeline.showSplitLine(t,n,o),l.style.cursor=`pointer`,this.timeline.notifyChange(`interaction:splitLine`),null}this.timeline.hideSplitLine()}else this.timeline.hideSplitLine()}if(s.enableTimeIndicator&&r<=s.timelineHeight){let e=g(c.timeIndicatorPosition,s.startTime,s.startPaddingTime,s.secondWidth,c.zoomLevel,c.scrollX),t=s.timeIndicatorHeadSize;if(n>=e-t/2&&n<=e+t/2&&r>=0&&r<=s.timeIndicatorHeadSize)return l.style.cursor=s.readOnly?`not-allowed`:`ew-resize`,null}if(u.eventIndex!==null&&u.trackIndex!==null&&!u.resizeEdge){let{trackIndex:e,eventIndex:t}={trackIndex:u.trackIndex,eventIndex:u.eventIndex},n=c.tracks[e].events[t];l.style.cursor=`pointer`,this.timeline.setStatus(`${n.title} (${this.timeline.formatTime(n.startTime)} - ${this.timeline.formatTime(n.endTime)})`)}else l.style.cursor=`default`;return null}handleContextMenu(e){e.originalEvent.preventDefault();let{canvasX:t,canvasY:n}=e,r=this.timeline.config,i=this.timeline.state;if(!r.enableContextMenu||r.readOnly||!this.timeline.isPluginLoaded(`context-menu`))return null;let a=this.timeline.getEventAtPosition(t,n);if(a){let{trackIndex:e,eventIndex:r}=a;i.contextMenuEvent={trackIndex:e,eventIndex:r},i.contextMenuVisible=!0,i.contextMenuX=t,i.contextMenuY=n,i.hoveredContextMenuItem=-1,this.timeline.notifyChange(`interaction:contextMenu`)}else i.contextMenuVisible=!1,i.contextMenuEvent=null,this.timeline.notifyChange(`interaction:contextMenu`);return null}createDraggingState(){return new K(this.timeline)}createResizingState(){return new q(this.timeline)}createScrollingState(){return new J(this.timeline)}createTimeIndicatorDragState(){return new Y(this.timeline)}};const Z=_(`StateMachine`);var ie=class{constructor(e){this.timeline=e,this.rafId=null,this.pendingMouseMove=null,this.currentState=new X(e)}getCurrentStateName(){return this.currentState.name}transitionTo(e){if(!e||e===this.currentState)return;let t=this.currentState;t.onExit&&(Z.debugStyled(b.stateExit,`◁ Exit: ${t.name}`),t.onExit(e)),this.currentState=e,e.onEnter&&(Z.debugStyled(b.stateEnter,`▷ Enter: ${e.name}`),e.onEnter(t)),Z.debugStyled(b.stateTransition,`⟳ Transition: ${t.name} → ${e.name}`)}createContext(e){let t=this.timeline.getCanvas().getBoundingClientRect(),n=this.timeline.state;return{canvasX:e.clientX-t.left,canvasY:e.clientY-t.top,logicalX:e.clientX-t.left+n.scrollX,logicalY:e.clientY-t.top+n.scrollY,originalEvent:e,canvasWidth:t.width,canvasHeight:t.height}}handleMouseDown(e){let t=this.createContext(e),n=this.currentState.handleMouseDown(t);this.transitionTo(n)}handleMouseMove(e){if(this.rafId!==null){this.pendingMouseMove=e;return}this.pendingMouseMove=e,this.rafId=requestAnimationFrame(()=>{this.pendingMouseMove&&=(this.handleMouseMoveImpl(this.pendingMouseMove),null),this.rafId=null})}handleMouseMoveImpl(e){let t=this.createContext(e),n=this.currentState.handleMouseMove(t);this.transitionTo(n)}handleMouseUp(e){this.rafId!==null&&(cancelAnimationFrame(this.rafId),this.rafId=null,this.pendingMouseMove=null);let t=e||new MouseEvent(`mouseup`),n=this.createContext(t),r=this.currentState.handleMouseUp(n);this.transitionTo(r)}handleContextMenu(e){let t=this.createContext(e),n=this.currentState.handleContextMenu(t);this.transitionTo(n)}destroy(){this.rafId!==null&&(cancelAnimationFrame(this.rafId),this.rafId=null),this.pendingMouseMove=null}},ae=class{constructor(e){this.timeline=e}handleWheel(e){if(e.preventDefault(),e.ctrlKey||e.metaKey){let t=e.deltaY>0?.9:1.1;this.timeline.zoom(t)}else this.timeline.state.scrollY+=e.deltaY,this.timeline.adjustCanvasSize(),this.timeline.notifyChange(`scroll:y`)}},oe=class{constructor(e){this.baseContext=e,this.plugins=new Map,this.eventHandlers=new Map,this.renderLayers=new Map,this.pluginData=new Map}async loadPlugin(e){let{name:t,version:n}=e.metadata,r=`${t}@${n}`;if(this.plugins.has(r))return!1;let i=this.createPluginContext(r);try{return e.init&&await e.init(i),e.activate&&await e.activate(i),this.plugins.set(r,{plugin:e,context:i,active:!0}),!0}catch{return!1}}async unloadPlugin(e){let t=this.plugins.get(e);if(!t)return!1;try{t.plugin.deactivate&&await t.plugin.deactivate(t.context),t.plugin.destroy&&await t.plugin.destroy(t.context)}finally{this.cleanupPluginResources(e),this.plugins.delete(e)}return!0}createPluginContext(e){let t=new Map;this.pluginData.set(e,t);let n={registerRenderLayer:t=>this.registerRenderLayer(e,t),unregisterRenderLayer:t=>this.unregisterRenderLayer(e,t),registerEventHandler:(t,n)=>this.registerEventHandler(e,t,n),unregisterEventHandler:(t,n)=>this.unregisterEventHandler(e,t,n),showNotification:(t,n=`info`)=>{let r=_(`plugin:${e}`);switch(n){case`error`:r.error(t);break;case`warning`:r.warn(t);break;default:r.info(t)}},getData:e=>t.get(e),setData:(e,n)=>t.set(e,n),setPerformanceProvider:e=>{this.performanceProvider=e},getPerformanceStats:()=>this.performanceProvider?this.performanceProvider.getAllStats():new Map,getFPS:()=>this.performanceProvider?this.performanceProvider.getFPS():0};return{...this.baseContext,api:n}}registerEventHandler(e,t,n){let r=this.eventHandlers.get(t)||[];r.push(n),this.eventHandlers.set(t,r)}unregisterEventHandler(e,t,n){let r=this.eventHandlers.get(t);if(!r)return;let i=r.indexOf(n);i>=0&&r.splice(i,1),this.eventHandlers.set(t,r)}registerRenderLayer(e,t){this.renderLayers.set(t.name,t)}unregisterRenderLayer(e,t){this.renderLayers.delete(t)}cleanupPluginResources(e){this.pluginData.delete(e);for(let[t]of this.renderLayers)t.startsWith(e)&&this.renderLayers.delete(t)}emitEvent(e,...t){let n=this.eventHandlers.get(e);if(!(!n||n.length===0))for(let e of n)try{e(...t)}catch{}}validateEvent(e,...t){let n=this.eventHandlers.get(e);if(!n||n.length===0)return!0;for(let e of n)try{if(e(...t)===!1)return!1}catch{}return!0}renderBackground(e,t,n,r){for(let i of this.layersByPosition(`background`))i.render(e,t,n,r)}renderOverlay(e,t,n,r){for(let i of this.layersByPosition(`overlay`))i.render(e,t,n,r)}layersByPosition(e){return Array.from(this.renderLayers.values()).filter(t=>t.position===e)}getLoadedPlugins(){return Array.from(this.plugins.values()).map(e=>e.plugin)}isPluginLoaded(e){for(let[t]of this.plugins)if(t.startsWith(`${e}@`))return!0;return!1}measureStart(e){this.performanceProvider&&this.performanceProvider.startMeasurement(e)}measureEnd(e){this.performanceProvider&&this.performanceProvider.endMeasurement(e)}},se=class{constructor(e){this.logger=e}throw(e){throw this.logger.error(e),Error(e)}error(e){this.logger.error(e)}warn(e){this.logger.warn(e)}},Q=class{constructor(e){this.state={tracks:[],selectedTrack:null,selectedEvent:null,highlightedEvent:null,draggingEvent:null,dragOffsetX:0,dragOffsetY:0,resizingEvent:null,draggingTimeIndicator:!1,timeIndicatorDragOffsetX:0,draggingScrollbar:!1,scrollbarDragOffset:0,draggingHorizontalScrollbar:!1,horizontalScrollbarDragOffset:0,zoomLevel:1,scrollX:0,scrollY:0,snapEnabled:!0,timeIndicatorSnapEnabled:!0,contextMenuEvent:null,contextMenuVisible:!1,contextMenuX:0,contextMenuY:0,hoveredContextMenuItem:-1,timeIndicatorPosition:e.startTime,timeIndicatorHighlightedEvents:[],isManualSelection:!1,guideLines:[],dragTimeReference:null,hoveredResizeHandle:null,lastClickTime:0,lastClickEvent:null,hoveredSplitLine:null,statusText:`就绪`,contextMenuBounds:null,lastDrawTime:0}}setStatus(e,t){this.state.statusText=e,t&&t(e)}},ce=class{constructor(e){this.sortedIndices=new Map,this.dirtyTracks=new Set,this.batching=!1,this.state=e}invalidateTrack(e){this.dirtyTracks.add(e)}invalidateAll(){this.sortedIndices.clear(),this.dirtyTracks.clear()}beginBatch(){this.batching=!0}endBatch(){if(this.batching){for(let e of Array.from(this.dirtyTracks)){let t=this.state.tracks[e],n=t.events.map((e,t)=>t);n.sort((e,n)=>t.events[e].startTime-t.events[n].startTime),this.sortedIndices.set(e,n)}this.dirtyTracks.clear(),this.batching=!1}}ensureSorted(e){if(this.batching&&this.sortedIndices.has(e)&&!this.dirtyTracks.has(e))return this.sortedIndices.get(e);if(this.dirtyTracks.has(e)||!this.sortedIndices.has(e)){let t=this.state.tracks[e],n=t.events.map((e,t)=>t);n.sort((e,n)=>t.events[e].startTime-t.events[n].startTime),this.sortedIndices.set(e,n),this.dirtyTracks.delete(e)}return this.sortedIndices.get(e)}getCandidatesByTime(e,t,n=0){let r=this.ensureSorted(e),i=this.state.tracks[e],a=0,o=r.length-1,s=-1,c=t+n;for(;a<=o;){let e=a+o>>1,t=r[e];i.events[t].startTime<=c?(s=e,a=e+1):o=e-1}if(s===-1)return[];let l=[];for(let e=s;e>=0;e--){let a=r[e],o=i.events[a];o.startTime>t+n||o.endTime<t-n||l.push(a)}for(let e=s+1;e<r.length;e++){let a=r[e];if(i.events[a].startTime>t+n)break;l.push(a)}return l}};const $=_(`ChangeScheduler`);var le=class{constructor(e,t,n){this.renderManager=null,this.eventIndexManager=null,this.drawFn=null,this.handlers=new Map,this.batchContext=null,this.isBatching=!1,this.state=e,this.config=t,this.callbacks=n,this.initializeHandlers()}setRenderManager(e){this.renderManager=e}setEventIndexManager(e){this.eventIndexManager=e}setDrawFunction(e){this.drawFn=e}initializeHandlers(){this.handlers.set(`events:add`,{layers:[`tracks`,`timeline`,`scrollbar`,`indicator`],derive:()=>this.refreshHighlightList(),needsDraw:!0}),this.handlers.set(`events:update`,{layers:[`tracks`,`timeline`,`scrollbar`,`indicator`],derive:()=>this.refreshHighlightList(),needsDraw:!0}),this.handlers.set(`events:delete`,{layers:[`tracks`,`timeline`,`scrollbar`,`indicator`],derive:()=>this.refreshHighlightList(),needsDraw:!0}),this.handlers.set(`events:move`,{layers:[`tracks`,`timeline`,`scrollbar`,`guideLines`,`indicator`,`interaction`],derive:()=>this.refreshHighlightList(),needsDraw:!0}),this.handlers.set(`events:split`,{layers:[`tracks`,`timeline`,`scrollbar`,`indicator`],derive:()=>this.refreshHighlightList(),needsDraw:!0}),this.handlers.set(`tracks:add`,{layers:[`tracks`,`timeline`,`scrollbar`],derive:()=>this.refreshHighlightList(),needsDraw:!0}),this.handlers.set(`tracks:remove`,{layers:[`tracks`,`timeline`,`scrollbar`],derive:()=>this.refreshHighlightList(),needsDraw:!0}),this.handlers.set(`timeIndicator:move`,{layers:[`indicator`,`tracks`,`timeline`,`interaction`],derive:()=>this.computeHighlightList(),notify:()=>this.emitTimeIndicatorHighlight(),needsDraw:!0}),this.handlers.set(`timeIndicator:drag`,{layers:[`indicator`,`tracks`,`interaction`],derive:()=>this.computeHighlightList(),needsDraw:!0}),this.handlers.set(`scroll:x`,{layers:[`tracks`,`timeline`,`guideLines`,`indicator`,`scrollbar`,`interaction`],needsDraw:!0}),this.handlers.set(`scroll:y`,{layers:[`tracks`,`timeline`,`guideLines`,`indicator`,`scrollbar`,`interaction`,`overlay`],needsDraw:!0}),this.handlers.set(`zoom:change`,{layers:[`background`,`tracks`,`timeline`,`guideLines`,`indicator`,`scrollbar`,`interaction`,`overlay`],needsDraw:!0}),this.handlers.set(`selection:change`,{layers:[`tracks`,`interaction`,`indicator`],needsDraw:!0}),this.handlers.set(`highlight:change`,{layers:[`tracks`,`indicator`],needsDraw:!0}),this.handlers.set(`canvas:resize`,{layers:[`background`,`tracks`,`timeline`,`guideLines`,`indicator`,`scrollbar`,`interaction`,`overlay`],needsDraw:!0}),this.handlers.set(`data:load`,{layers:[`tracks`,`timeline`,`scrollbar`,`guideLines`],derive:()=>this.refreshHighlightList(),needsDraw:!0}),this.handlers.set(`theme:change`,{layers:[`background`,`tracks`,`timeline`,`indicator`,`scrollbar`,`overlay`],needsDraw:!0}),this.handlers.set(`interaction:hover`,{layers:[`tracks`,`interaction`,`overlay`],needsDraw:!0}),this.handlers.set(`interaction:contextMenu`,{layers:[`overlay`,`interaction`],needsDraw:!0}),this.handlers.set(`interaction:splitLine`,{layers:[`tracks`],needsDraw:!0}),this.handlers.set(`config:debug`,{layers:[`overlay`],needsDraw:!0}),this.handlers.set(`config:timeIndicator`,{layers:[`indicator`,`tracks`,`interaction`],derive:()=>this.refreshHighlightList(),needsDraw:!0}),this.handlers.set(`config:endTime`,{layers:[`background`,`tracks`,`timeline`,`guideLines`,`indicator`,`scrollbar`,`interaction`,`overlay`],needsDraw:!0}),this.handlers.set(`config:readOnly`,{layers:[`tracks`,`interaction`,`overlay`],needsDraw:!0})}notify(e){let t=this.handlers.get(e);if(!t){$.warn(`Unknown change type: ${e}`);return}if(this.isBatching&&this.batchContext){this.batchContext.changes.add(e);for(let e of t.layers)this.batchContext.dirtyLayers.add(e);t.derive&&this.batchContext.pendingDerives.push(t.derive),t.notify&&this.batchContext.pendingNotifications.push(t.notify)}else this.processChange(t)}notifyMultiple(e){this.beginBatch();for(let t of e)this.notify(t);this.endBatch()}beginBatch(){if(this.isBatching){$.warn(`Already in batch mode`);return}this.isBatching=!0,this.batchContext={changes:new Set,dirtyLayers:new Set,pendingNotifications:[],pendingDerives:[]}}endBatch(){if(!this.isBatching||!this.batchContext){$.warn(`Not in batch mode`);return}let e=this.batchContext;if(this.isBatching=!1,this.batchContext=null,e.changes.size===0)return;let t=[...new Set(e.pendingDerives)];for(let e of t)e();this.renderManager&&e.dirtyLayers.size>0&&this.renderManager.markDirty(Array.from(e.dirtyLayers)),this.drawFn&&this.drawFn();let n=[...new Set(e.pendingNotifications)];for(let e of n)e()}processChange(e){e.derive&&e.derive(),this.renderManager&&e.layers.length>0&&this.renderManager.markDirty(e.layers),e.needsDraw&&this.drawFn&&this.drawFn(),e.notify&&e.notify()}refreshHighlightList(){this.state.timeIndicatorHighlightedEvents=this.detectHighlightedEvents(this.state.timeIndicatorPosition)}computeHighlightList(){let e=this.state.timeIndicatorPosition,t=this.detectHighlightedEvents(e),n=this.hasHighlightChanged(this.state.timeIndicatorHighlightedEvents,t);this.state.timeIndicatorHighlightedEvents=t,this._highlightChanged=n}hasHighlightChanged(e,t){if(e.length!==t.length)return!0;for(let n=0;n<e.length;n++)if(e[n].trackIndex!==t[n].trackIndex||e[n].eventIndex!==t[n].eventIndex)return!0;return!1}detectHighlightedEvents(e){if(!this.config.enableTimeIndicator)return[];let t=[];if(this.eventIndexManager)for(let n=0;n<this.state.tracks.length;n++){let r=this.eventIndexManager.getCandidatesByTime(n,e,0),i=this.state.tracks[n];for(let a of r){let r=i.events[a];r&&e>r.startTime&&e<r.endTime&&t.push({trackIndex:n,eventIndex:a})}}else for(let n=0;n<this.state.tracks.length;n++){let r=this.state.tracks[n];for(let i=0;i<r.events.length;i++){let a=r.events[i];e>a.startTime&&e<a.endTime&&t.push({trackIndex:n,eventIndex:i})}}return t}emitTimeIndicatorHighlight(){if(this._highlightChanged){if(this.callbacks.onTimeIndicatorHighlight){let e=this.state.timeIndicatorPosition,t=this.state.timeIndicatorHighlightedEvents.filter(({trackIndex:e,eventIndex:t})=>{let n=this.state.tracks[e];return n&&t<n.events.length}).map(({trackIndex:e,eventIndex:t})=>{let n=this.state.tracks[e].events[t];return{trackIndex:e,eventIndex:t,event:u(n)}});this.callbacks.onTimeIndicatorHighlight({position:e,highlightedEvents:t})}this._highlightChanged=!1}}registerHandler(e,t){this.handlers.set(e,t)}getLayersForChange(e){return this.handlers.get(e)?.layers||[]}updateCallbacks(e){this.callbacks=e}},ue=class i{constructor(e,r={}){this.guideLinesCache=new Map,this.guideLinesCacheTimestamp=0,this.GUIDE_LINES_CACHE_TTL=500,this.eventListeners=null,this.currentThemePluginId=null,this._lastEdgeScrollTime=0,this.logger=new v({enabled:!0,level:r.debug?`debug`:`info`,prefix:`Timeline`,useGlobalConfig:!1}),y({enabled:!0,level:r.debug?`debug`:`info`}),this.errorHandler=new se(this.logger);let i=document.getElementById(e);(!i||!(i instanceof HTMLCanvasElement))&&this.errorHandler.throw(`Canvas element with id "${e}" not found`),this.canvas=i;let a=this.canvas.getContext(`2d`);if(a||this.errorHandler.throw(`Failed to get 2D context from canvas`),this.ctx=a,r.startPaddingTime===void 0&&(r.startPaddingTime=10),this.config={...s,...r,colors:{...p,...r.colors},eventTextStyle:{...n,...r.eventTextStyle},eventBlockStyle:{...m,...r.eventBlockStyle},contextMenuItems:r.contextMenuItems||t,contextMenuStyle:{...d,...r.contextMenuStyle}},this.logger.setLevel(this.config.debug?`debug`:`info`),this.callbacks={onEventAdd:r.onEventAdd||null,onEventUpdate:r.onEventUpdate||null,onEventDelete:r.onEventDelete||null,onEventMove:r.onEventMove||null,onEventClick:r.onEventClick||null,onEventEdit:r.onEventEdit||null,onContextMenu:r.onContextMenu||null,onTrackAdd:r.onTrackAdd||null,onTrackRemove:r.onTrackRemove||null,onTimeIndicatorMove:r.onTimeIndicatorMove||null,onZoom:r.onZoom||null,onStatusChange:r.onStatusChange||null,onEventHighlight:r.onEventHighlight||null,onTimeIndicatorHighlight:r.onTimeIndicatorHighlight||null},this.stateManager=new Q(this.config),this.state=this.stateManager.state,this.eventIndexManager=new ce(this.state),this.mouseHandler=new ie(this),this.wheelHandler=new ae(this),this.pluginManager=new oe({timeline:this,config:this.config,state:this.state}),r.theme){let e=`${r.theme.metadata.name}@${r.theme.metadata.version}`;this.pluginManager.loadPlugin(r.theme).then(t=>{t&&(this.currentThemePluginId=e,this.notifyChange(`theme:change`))})}this.renderManager=new U(this.canvas,this.ctx,this.config,this.state,this.pluginManager),this.changeScheduler=new le(this.state,this.config,this.callbacks),this.changeScheduler.setRenderManager(this.renderManager),this.changeScheduler.setEventIndexManager(this.eventIndexManager),this.changeScheduler.setDrawFunction(()=>this.draw()),this.init(),this.setupEventListeners()}getCanvas(){return this.canvas}usePlugin(e){return this.pluginManager.loadPlugin(e).then(t=>(t&&e.metadata?.type===x.THEME&&(this.currentThemePluginId=`${e.metadata.name}@${e.metadata.version}`,this.notifyChange(`theme:change`)),t))}getLoadedPlugins(){return this.pluginManager.getLoadedPlugins()}isPluginLoaded(e){return this.pluginManager.isPluginLoaded(e)}async removePlugin(e){return this.pluginManager.unloadPlugin(e)}async setTheme(e){let t=e===`dark`?C:S;return this.switchTheme(t)}async switchTheme(e){this.currentThemePluginId&&=(await this.pluginManager.unloadPlugin(this.currentThemePluginId),null);let t=`${e.metadata.name}@${e.metadata.version}`,n=await this.pluginManager.loadPlugin(e);return n&&(this.currentThemePluginId=t,this.notifyChange(`theme:change`)),n}init(){this.config.autoFitOnInit&&this.autoFitZoomToCanvas(),this.notifyChange(`data:load`)}getContentWidthForZoom(e){return this.renderManager.getContentWidth(e)}hasHorizontalScrollbar(){return this.renderManager.hasHorizontalScrollbar()}getAvailableHeight(){return this.renderManager.getAvailableHeight()}notifyChange(e){this.changeScheduler.notify(e)}beginChangeBatch(){this.changeScheduler.beginBatch()}endChangeBatch(){this.changeScheduler.endBatch()}setDebug(e){this.config.debug!==e&&(this.config.debug=e,this.logger.setLevel(e?`debug`:`info`),y({level:e?`debug`:`info`}),this.notifyChange(`config:debug`))}setEnableTimeIndicator(e){this.config.enableTimeIndicator!==e&&(this.config.enableTimeIndicator=e,e||(this.state.draggingTimeIndicator=!1,this.state.timeIndicatorHighlightedEvents=[]),this.notifyChange(`config:timeIndicator`))}markDirty(e){this.renderManager.markDirty(e)}getLastLayerTimes(){return this.renderManager.getLastLayerTimes()}beginIndexBatch(){this.eventIndexManager.beginBatch()}endIndexBatch(){this.eventIndexManager.endBatch()}invalidateIndexTrack(e){this.eventIndexManager.invalidateTrack(e)}invalidateIndexAll(){this.eventIndexManager.invalidateAll()}autoFitZoomToCanvas(){this.adjustCanvasSize();let e=this.renderManager.getCanvasLogicalWidth(),t=Math.max(this.config.minAutoFitZoom,this.state.zoomLevel,1),n=Math.max(this.config.maxAutoFitZoom,t);if(this.renderManager.getContentWidth(t)>=e){this.state.zoomLevel=t;return}for(;t<=n&&this.renderManager.getContentWidth(t)<e;)t+=.05;if(t<=n&&this.renderManager.getContentWidth(t)>=e){this.state.zoomLevel=parseFloat(t.toFixed(3)),this.setStatus(`自动缩放: ${Math.round(this.state.zoomLevel*100)}% 以铺满画布`);return}if(this.config.endPaddingTime===0){let t=e,r=this.renderManager.getContentWidth(n);if(r<t){let e=(t-r)/(this.config.secondWidth*n);this.config.endPaddingTime=Math.ceil(e),this.state.zoomLevel=n,this.setStatus(`自动缩放达到上限(${Math.round(n*100)}%),已自动增加留白 ${this.config.endPaddingTime} 秒以铺满画布`);return}}this.state.zoomLevel=n,this.setStatus(`自动缩放达到上限(${Math.round(n*100)}%),内容仍不足以完全铺满画布`),this.markDirty([`background`,`tracks`,`timeline`,`guideLines`,`indicator`,`scrollbar`,`interaction`,`overlay`])}setupEventListeners(){this.eventListeners={mousedown:e=>this.mouseHandler.handleMouseDown(e),mousemove:e=>this.mouseHandler.handleMouseMove(e),mouseup:e=>this.mouseHandler.handleMouseUp(e),mouseleave:()=>this.mouseHandler.handleMouseUp(),contextmenu:e=>this.mouseHandler.handleContextMenu(e),wheel:e=>this.wheelHandler.handleWheel(e)},this.canvas.addEventListener(`mousedown`,this.eventListeners.mousedown),this.canvas.addEventListener(`mousemove`,this.eventListeners.mousemove),this.canvas.addEventListener(`mouseup`,this.eventListeners.mouseup),this.canvas.addEventListener(`mouseleave`,this.eventListeners.mouseleave),this.canvas.addEventListener(`contextmenu`,this.eventListeners.contextmenu),this.canvas.addEventListener(`wheel`,this.eventListeners.wheel,{passive:!1}),this.setInitialCanvasSize()}setInitialCanvasSize(){let e=this.canvas.parentElement;if(!e){this.setCanvasSize(this.renderManager.getCanvasLogicalWidth(),this.config.canvasHeight||500);return}let t=e.getBoundingClientRect();this.setCanvasSize(t.width,t.height||this.config.canvasHeight||500)}setCanvasSize(e,t){this.renderManager.setCanvasSize(e,t)}getCanvasLogicalHeight(){return this.renderManager.getCanvasLogicalHeight()}getCachedLogicalHeight(){return this.renderManager.getCachedLogicalHeight()}adjustCanvasSize(){let e=this.renderManager.computeMaxScrollY();this.state.scrollY=Math.max(0,Math.min(e,this.state.scrollY)),this.notifyChange(`canvas:resize`)}addTrack(){let e={id:this.state.tracks.length,events:[]};this.state.tracks.push(e),this.adjustCanvasSize(),this.setStatus(`已添加轨道 ${this.state.tracks.length}`),this.callbacks.onTrackAdd&&this.callbacks.onTrackAdd(e)}removeTrack(){if(this.state.tracks.length<=1){this.setStatus(`至少需要保留一个轨道`);return}let e=this.state.tracks.pop();this.state.selectedTrack!==null&&this.state.selectedTrack>=this.state.tracks.length&&(this.state.selectedTrack=this.state.tracks.length>0?this.state.tracks.length-1:null),this.adjustCanvasSize(),this.setStatus(`已删除轨道,当前轨道数: ${this.state.tracks.length}`),this.callbacks.onTrackRemove&&this.callbacks.onTrackRemove(e)}autoRemoveEmptyLastTrack(){if(this.config.autoRemoveEmptyLastTrack&&!(this.state.tracks.length<=1)&&this.state.tracks[this.state.tracks.length-1].events.length===0){let e=this.state.tracks.pop();this.state.selectedTrack!==null&&this.state.selectedTrack>=this.state.tracks.length&&(this.state.selectedTrack=this.state.tracks.length>0?this.state.tracks.length-1:null),this.setStatus(`自动清理空轨道,当前轨道数: ${this.state.tracks.length}`),this.callbacks.onTrackRemove&&this.callbacks.onTrackRemove(e),this.adjustCanvasSize(),this.autoRemoveEmptyLastTrack()}}validateEventTime(e,t){let n=this.config.endTime+this.config.endPaddingTime,i,a;if(t>e&&t<=n)i=e,a=r(t-e);else if(t<=this.config.endTime-this.config.startTime&&e+t<=n)i=e,a=t;else return this.logger.error(`无效的时间范围: startTime=${e}, endTime=${t}`),null;return i<this.config.startTime?(this.logger.error(`开始时间不能进入左侧留白区域: startTime=${i}, minAllowed=${this.config.startTime}`),null):{startSec:i,duration:a}}addEvent(e,t,n,i,a=``,o,s=!1){if(e<0||e>=this.state.tracks.length)return;let c=this.validateEventTime(t,n);if(!c)return;let{startSec:l,duration:d}=c,f=this.state.tracks[e],p=r(d),m={id:f.events.length,startTime:l,endTime:r(l+p),duration:p,title:i,description:a,color:this.config.colors.eventColors[f.events.length%this.config.colors.eventColors.length],...s&&{readonly:s},...o&&{customData:o}};f.events.push(m),this.eventIndexManager.invalidateTrack(e),this.notifyChange(`events:add`),this.callbacks.onEventAdd&&this.callbacks.onEventAdd({trackIndex:e,event:u(m)})}updateEvent(e,t,n){if(e<0||e>=this.state.tracks.length)return this.logger.error(`无效的轨道索引`),!1;let r=this.state.tracks[e];if(t<0||t>=r.events.length)return this.logger.error(`无效的事件索引`),!1;let i=r.events[t],a=u(i);return Object.assign(i,n),this.eventIndexManager.invalidateTrack(e),this.notifyChange(`events:update`),this.setStatus(`已更新事件: ${i.title}`),this.callbacks.onEventUpdate&&this.callbacks.onEventUpdate({trackIndex:e,eventIndex:t,event:u(i),oldEvent:a}),!0}updateEventData(e,t,n){if(e<0||e>=this.state.tracks.length)return this.logger.error(`无效的轨道索引`),!1;let i=this.state.tracks[e];if(t<0||t>=i.events.length)return this.logger.error(`无效的事件索引`),!1;let a=i.events[t],o=u(a);return n.title!==void 0&&(a.title=n.title),n.startTime!==void 0&&(a.startTime=n.startTime,a.endTime=r(a.startTime+a.duration)),n.duration!==void 0&&(a.duration=r(n.duration),a.endTime=r(a.startTime+a.duration)),n.description!==void 0&&(a.description=n.description),this.eventIndexManager.invalidateTrack(e),this.notifyChange(`events:update`),this.setStatus(`已更新事件: ${a.title}`),this.callbacks.onEventUpdate&&this.callbacks.onEventUpdate({trackIndex:e,eventIndex:t,event:u(a),oldEvent:o}),!0}deleteEvent(e,t){if(e<0||e>=this.state.tracks.length)return!1;let n=this.state.tracks[e];if(t<0||t>=n.events.length)return!1;let r=u(n.events[t]);return n.events.splice(t,1),this.eventIndexManager.invalidateTrack(e),this.autoRemoveEmptyLastTrack(),this.notifyChange(`events:delete`),this.setStatus(`已删除事件: ${r.title}`),this.callbacks.onEventDelete&&this.callbacks.onEventDelete({trackIndex:e,eventIndex:t,event:r}),!0}loadData(e){if(!e||typeof e!=`object`)return this.logger.error(`无效的数据格式`),!1;this.state.tracks=[],this.state.selectedTrack=null,this.state.selectedEvent=null;let t=e.tracks||[];for(let e=0;e<t.length;e++){let n=t[e],i={id:this.state.tracks.length,events:[]},a=n.events||[];for(let e=0;e<a.length;e++){let t=a[e];if(!t.title)continue;let n,o;if(t.endTime!==void 0)n=t.startTime||0,o=r(t.endTime-n);else if(t.duration!==void 0)n=t.startTime||0,o=t.duration;else continue;let s=r(o),c={id:i.events.length,startTime:n,endTime:r(n+s),duration:s,title:t.title,description:t.description||``,color:t.color||this.config.colors.eventColors[i.events.length%this.config.colors.eventColors.length],...t.readonly&&{readonly:t.readonly},...t.customData&&{customData:t.customData}};i.events.push(c)}this.state.tracks.push(i)}return this.state.tracks.length===0&&this.addTrack(),this.eventIndexManager.invalidateAll(),e.timeIndicatorPosition!==void 0&&this.setTimeIndicator(e.timeIndicatorPosition),this.notifyChange(`data:load`),this.setStatus(`已加载 ${this.state.tracks.length} 个轨道`),!0}setTimeIndicator(t,n=!1){if(typeof t!=`number`||isNaN(t))return this.logger.error(`时间指示器位置必须是数字(秒)`),!1;if(n&&this.state.snapEnabled){let n=a(this.state.zoomLevel,this.config.snapInterval,this.config.snapToSeconds,this.config.secondPrecisionZoomThreshold);t=e(t,n)}return t=Math.max(this.config.startTime,Math.min(this.config.endTime,t)),t===this.state.timeIndicatorPosition?!0:(this.state.timeIndicatorPosition=t,this.scrollToTimeIndicator(t),this.notifyChange(`timeIndicator:move`),this.setStatus(`时间指示器已移动到: ${f(t)}`),this.callbacks.onTimeIndicatorMove&&this.callbacks.onTimeIndicatorMove({position:t,time:f(t)}),!0)}setTimeIndicatorDuringDrag(e){e=Math.max(this.config.startTime,Math.min(this.config.endTime,e)),this.state.timeIndicatorPosition=e,this.scrollToTimeIndicatorThrottled(e),this.notifyChange(`timeIndicator:drag`)}static{this.EDGE_SCROLL_THROTTLE=80}static{this.EDGE_SCROLL_MARGIN=30}scrollToTimeIndicatorThrottled(e){let t=performance.now();if(t-this._lastEdgeScrollTime<i.EDGE_SCROLL_THROTTLE)return;let n=g(e,this.config.startTime,this.config.startPaddingTime,this.config.secondWidth,this.state.zoomLevel,this.state.scrollX),r=this.renderManager.getCanvasLogicalWidth(),a=i.EDGE_SCROLL_MARGIN;if(n>=a&&n<=r-a)return;this._lastEdgeScrollTime=t;let o=g(e,this.config.startTime,this.config.startPaddingTime,this.config.secondWidth,this.state.zoomLevel,0),s=this.renderManager.computeMaxScrollX(this.state.zoomLevel);n<a?this.state.scrollX=Math.max(0,Math.min(s,o-50)):this.state.scrollX=Math.max(0,Math.min(s,o-(r-50))),this.markDirty([`background`,`tracks`,`timeline`,`guideLines`,`indicator`,`scrollbar`,`interaction`,`overlay`])}scrollToTimeIndicator(e){let t=g(e,this.config.startTime,this.config.startPaddingTime,this.config.secondWidth,this.state.zoomLevel,this.state.scrollX),n=this.renderManager.getCanvasLogicalWidth(),r=!1;if(t<50){let t=g(e,this.config.startTime,this.config.startPaddingTime,this.config.secondWidth,this.state.zoomLevel,0)-50,n=this.renderManager.computeMaxScrollX(this.state.zoomLevel);this.state.scrollX=Math.max(0,Math.min(n,t)),r=!0}else if(t>n-50){let t=g(e,this.config.startTime,this.config.startPaddingTime,this.config.secondWidth,this.state.zoomLevel,0)-(n-50),i=this.renderManager.computeMaxScrollX(this.state.zoomLevel);this.state.scrollX=Math.max(0,Math.min(i,t)),r=!0}r&&this.markDirty([`background`,`tracks`,`timeline`,`guideLines`,`indicator`,`scrollbar`,`interaction`,`overlay`])}zoom(e){let t=this.state.zoomLevel,n=this.state.scrollX,r=this.renderManager.getCachedLogicalWidth()/2,i=(r+n)/(this.config.secondWidth*t);if(this.state.zoomLevel*=e,this.state.zoomLevel=Math.max(1,Math.min(1e3,this.state.zoomLevel)),t!==this.state.zoomLevel){let e=i*this.config.secondWidth*this.state.zoomLevel;this.state.scrollX=e-r;let t=this.renderManager.computeMaxScrollX(this.state.zoomLevel);this.state.scrollX=Math.max(0,Math.min(t,this.state.scrollX))}this.notifyChange(`zoom:change`),this.setStatus(`缩放级别: ${Math.round(this.state.zoomLevel*100)}%`),this.callbacks.onZoom&&t!==this.state.zoomLevel&&this.callbacks.onZoom({zoomLevel:this.state.zoomLevel,percentage:Math.round(this.state.zoomLevel*100)})}setZoomLevel(e){if(typeof e!=`number`||isNaN(e))return this.logger.error(`缩放级别必须是有效的数字`),!1;if(e<1||e>1e3)return this.logger.error(`缩放级别超出有效范围 (1-1000)`),!1;let t=this.state.zoomLevel,n=this.state.scrollX,r=this.renderManager.getCachedLogicalWidth()/2,i=(r+n)/(this.config.secondWidth*t);this.state.zoomLevel=e;let a=i*this.config.secondWidth*this.state.zoomLevel;this.state.scrollX=a-r;let o=this.renderManager.computeMaxScrollX(this.state.zoomLevel);return this.state.scrollX=Math.max(0,Math.min(o,this.state.scrollX)),this.notifyChange(`zoom:change`),this.setStatus(`缩放级别: ${Math.round(this.state.zoomLevel*100)}%`),this.callbacks.onZoom&&t!==this.state.zoomLevel&&this.callbacks.onZoom({zoomLevel:this.state.zoomLevel,percentage:Math.round(this.state.zoomLevel*100)}),!0}getZoomLevel(){return this.state.zoomLevel}setEndTime(e){if(typeof e!=`number`||isNaN(e))return this.logger.error(`结束时间必须是有效的数字(秒)`),!1;if(e<=this.config.startTime)return this.logger.error(`结束时间必须大于开始时间`),!1;this.state.tracks.some(t=>t.events.some(t=>t.endTime>e))&&this.logger.warn(`警告:有事件超出新的结束时间范围`);let t=this.config.endTime;this.config.endTime=e,this.renderManager.invalidateLayoutCache(),this.state.timeIndicatorPosition>e&&(this.state.timeIndicatorPosition=e);let n=this.renderManager.getContentWidth(this.state.zoomLevel),r=Math.max(0,n-this.renderManager.getCachedLogicalWidth());return this.state.scrollX=Math.max(0,Math.min(r,this.state.scrollX)),this.notifyChange(`config:endTime`),this.setStatus(`结束时间已更新: ${f(t)} → ${f(e)}`),!0}getEndTime(){return this.config.endTime}formatTime(e){return f(e)}setStatus(e){this.stateManager.setStatus(e,this.callbacks.onStatusChange||void 0)}getStatus(){return this.state.statusText}getInteractionTarget(e,t){let n={trackIndex:null,eventIndex:null,resizeEdge:null},r=t+this.state.scrollY;if(r<this.config.timelineHeight)return n;let i=Math.floor((r-this.config.timelineHeight-this.config.firstTrackTopMargin)/(this.config.trackHeight+this.config.trackMargin));if(i<0||i>=this.state.tracks.length)return n;n.trackIndex=i;let a=this.state.tracks[i],o=Math.max(5,this.config.trackHeight*.0625),s=this.config.timelineHeight+this.config.firstTrackTopMargin+i*(this.config.trackHeight+this.config.trackMargin)-this.state.scrollY;if(t<s+o||t>s+this.config.trackHeight-o)return n;let c=(e+this.state.scrollX-this.config.startPaddingTime)/(this.config.secondWidth*this.state.zoomLevel)+this.config.startTime,l=this.config.resizeHandleWidth,u=l/(this.config.secondWidth*this.state.zoomLevel),d=this.eventIndexManager.getCandidatesByTime(i,c,u);if(d.length===0)return n;let f=null,p=null,m=null;for(let t of d){let n=a.events[t],r=this.config.startPaddingTime+(n.startTime-this.config.startTime)*this.config.secondWidth*this.state.zoomLevel-this.state.scrollX,i=n.duration*this.config.secondWidth*this.state.zoomLevel;e>=r-l/2&&e<=r+l/2?(f===null||t>f)&&(f=t,p=`left`):e>=r+i-l/2&&e<=r+i+l/2&&(f===null||t>f)&&(f=t,p=`right`),e>=r&&e<=r+i&&(m===null||t>m)&&(m=t)}return f===null?m!==null&&(n.eventIndex=m):(n.eventIndex=f,n.resizeEdge=p),n}getEventAtPosition(e,t){let n=t+this.state.scrollY;if(n<this.config.timelineHeight)return null;let r=Math.floor((n-this.config.timelineHeight-this.config.firstTrackTopMargin)/(this.config.trackHeight+this.config.trackMargin));if(r<0||r>=this.state.tracks.length)return null;let i=this.state.tracks[r],a=Math.max(5,this.config.trackHeight*.0625),o=this.config.timelineHeight+this.config.firstTrackTopMargin+r*(this.config.trackHeight+this.config.trackMargin)-this.state.scrollY;if(t<o+a||t>o+this.config.trackHeight-a)return null;let s=(e+this.state.scrollX-this.config.startPaddingTime)/(this.config.secondWidth*this.state.zoomLevel)+this.config.startTime,c=this.eventIndexManager.getCandidatesByTime(r,s,0);if(c.length>0){let t=null;for(let n of c){let r=i.events[n],a=this.config.startPaddingTime+(r.startTime-this.config.startTime)*this.config.secondWidth*this.state.zoomLevel-this.state.scrollX,o=r.duration*this.config.secondWidth*this.state.zoomLevel;e>=a&&e<=a+o&&(t===null||n>t)&&(t=n)}if(t!==null)return{trackIndex:r,eventIndex:t}}return null}getResizeHandle(e,t){let n=t+this.state.scrollY;if(n<this.config.timelineHeight)return null;let r=Math.floor((n-this.config.timelineHeight-this.config.firstTrackTopMargin)/(this.config.trackHeight+this.config.trackMargin));if(r<0||r>=this.state.tracks.length)return null;let i=this.state.tracks[r],a=this.config.resizeHandleWidth,o=Math.max(5,this.config.trackHeight*.0625),s=this.config.timelineHeight+this.config.firstTrackTopMargin+r*(this.config.trackHeight+this.config.trackMargin)-this.state.scrollY;if(t<s+o||t>s+this.config.trackHeight-o)return null;let c=(e+this.state.scrollX-this.config.startPaddingTime)/(this.config.secondWidth*this.state.zoomLevel)+this.config.startTime,l=a/(this.config.secondWidth*this.state.zoomLevel),u=this.eventIndexManager.getCandidatesByTime(r,c,l);if(u.length>0){let t=null,n=null;for(let r of u){let o=i.events[r],s=this.config.startPaddingTime+(o.startTime-this.config.startTime)*this.config.secondWidth*this.state.zoomLevel-this.state.scrollX,c=o.duration*this.config.secondWidth*this.state.zoomLevel;e>=s-a/2&&e<=s+a/2?(t===null||r>t)&&(t=r,n=`left`):e>=s+c-a/2&&e<=s+c+a/2&&(t===null||r>t)&&(t=r,n=`right`)}if(t!==null)return{trackIndex:r,eventIndex:t,edge:n}}return null}calculateGuideLines(e,t,n,r,i){let a=`${e}-${t}-${n}-${r.toFixed(3)}-${i.toFixed(3)}`,o=Date.now();if(o-this.guideLinesCacheTimestamp<this.GUIDE_LINES_CACHE_TTL){let e=this.guideLinesCache.get(a);if(e)return e}else this.guideLinesCache.clear(),this.guideLinesCacheTimestamp=o;let s=[],c=this.config.guideLineSnapThreshold,l=r+i,u=new Set;u.add(n),n>0&&u.add(n-1),n<this.state.tracks.length-1&&u.add(n+1);let d=(e,t,n)=>{let r=s.find(n=>Math.abs(n.time-e)<1e-4&&n.type===t);r?r.trackIndices.includes(n)||r.trackIndices.push(n):s.push({time:e,type:t,trackIndices:[n]})};for(let n of u){if(n<0||n>=this.state.tracks.length)continue;let i=this.state.tracks[n];if(i.events.length===0)continue;let a=[];for(let o=0;o<i.events.length;o++){if(n===e&&o===t)continue;let s=i.events[o];s.endTime<r-c||s.startTime>l+c||a.push(s)}if(a.length!==0)for(let e of a)Math.abs(e.startTime-r)<c&&d(e.startTime,`start`,n),Math.abs(e.endTime-l)<c&&d(e.endTime,`end`,n),Math.abs(e.endTime-r)<c&&d(e.endTime,`end`,n),Math.abs(e.startTime-l)<c&&d(e.startTime,`start`,n)}return this.guideLinesCache.set(a,s),s}snapToGuideLines(e,t){if(this.state.guideLines.length===0)return null;let n=this.config.guideLineSnapThreshold,r=e+t;for(let i of this.state.guideLines)if(i.type===`start`){if(Math.abs(i.time-e)<n)return i.time}else if(i.type===`end`&&Math.abs(i.time-r)<n)return i.time-t;return null}canMoveEvent(e,t,n,r,i){let a=r+i,o=this.config.endTime+this.config.endPaddingTime;if(r<this.config.startTime||a>o||n<0||n>=this.state.tracks.length)return!1;let s=this.state.tracks[n];for(let i=0;i<s.events.length;i++){if(n===e&&i===t)continue;let o=s.events[i];if(!(a<=o.startTime||r>=o.endTime))return!1}return!!this.pluginManager.validateEvent(`validate:event:move`,{fromTrackIndex:e,fromEventIndex:t,toTrackIndex:n,newStartTime:r,duration:i})}showSplitLine(e,t,n){(!this.state.hoveredSplitLine||this.state.hoveredSplitLine.trackIndex!==e||this.state.hoveredSplitLine.eventIndex!==t||Math.abs(this.state.hoveredSplitLine.splitTime-n)>.001)&&(this.state.hoveredSplitLine={trackIndex:e,eventIndex:t,splitTime:n},this.notifyChange(`interaction:splitLine`))}hideSplitLine(){this.state.hoveredSplitLine&&(this.state.hoveredSplitLine=null,this.notifyChange(`interaction:splitLine`))}splitEvent(e,t,n){if(e<0||e>=this.state.tracks.length)return!1;let i=this.state.tracks[e];if(t<0||t>=i.events.length)return!1;let a=i.events[t];if(n<=a.startTime+this.config.minEventDuration||n>=a.endTime-this.config.minEventDuration)return this.setStatus(`切割位置无效:切割后的事件块时长太短`),!1;let o={...a,id:a.id,duration:r(n-a.startTime),endTime:n,title:`${a.title} (1)`},s={...a,id:i.events.length,startTime:n,duration:r(a.endTime-n),endTime:r(a.endTime),title:`${a.title} (2)`};return i.events[t]=o,i.events.push(s),this.eventIndexManager.invalidateTrack(e),this.notifyChange(`events:split`),this.setStatus(`已切割事件: ${a.title}`),this.callbacks.onEventUpdate&&this.callbacks.onEventUpdate({type:`split`,trackIndex:e,eventIndex:t,event:u(a),firstEvent:u(o),secondEvent:u(s)}),!0}draw(){this.renderManager.draw()}setReadOnly(e){this.config.readOnly=e,e&&(this.state.selectedEvent=null,this.state.draggingEvent=null,this.state.resizingEvent=null,this.state.draggingTimeIndicator=!1,this.state.contextMenuVisible=!1,this.state.contextMenuEvent=null,this.state.hoveredResizeHandle=null,this.state.hoveredSplitLine=null,this.state.guideLines=[]),this.notifyChange(`config:readOnly`),this.setStatus(e?`已进入只读模式`:`已退出只读模式`)}highlightEvent(e,t){if(e<0||e>=this.state.tracks.length)return this.logger.error(`无效的轨道索引: ${e}`),!1;let n=this.state.tracks[e];if(t<0||t>=n.events.length)return this.logger.error(`无效的事件索引: ${t}`),!1;this.state.selectedEvent=null,this.state.selectedTrack=null,this.state.highlightedEvent={trackIndex:e,eventIndex:t};let r=n.events[t];return this.notifyChange(`highlight:change`),this.setStatus(`已高亮事件: ${r.title}`),!0}clearHighlight(){(this.state.highlightedEvent||this.state.selectedEvent)&&(this.state.highlightedEvent=null,this.state.selectedEvent=null,this.state.selectedTrack=null,this.notifyChange(`highlight:change`),this.setStatus(`已清除高亮`))}getHighlightedEvent(){return this.state.highlightedEvent}isReadOnly(){return this.config.readOnly}destroy(){this.guideLinesCache.clear(),this.eventListeners&&=(this.canvas.removeEventListener(`mousedown`,this.eventListeners.mousedown),this.canvas.removeEventListener(`mousemove`,this.eventListeners.mousemove),this.canvas.removeEventListener(`mouseup`,this.eventListeners.mouseup),this.canvas.removeEventListener(`mouseleave`,this.eventListeners.mouseleave),this.canvas.removeEventListener(`contextmenu`,this.eventListeners.contextmenu),this.canvas.removeEventListener(`wheel`,this.eventListeners.wheel),null),this.setStatus(`Timeline 已销毁`)}};export{w as ContextMenuPlugin,C as DarkThemePlugin,h as EventMediaPlugin,E as EventTooltipPlugin,S as LightThemePlugin,T as PerformanceOverlayPlugin,ue as Timeline,f as formatTime,o as getCurrentTime};
@@ -204,6 +204,17 @@ interface HoveredSplitLine {
204
204
  eventIndex: number;
205
205
  splitTime: number;
206
206
  }
207
+ /**
208
+ * 统一命中:一次查询同时返回 resize handle 和事件体的命中信息
209
+ */
210
+ interface InteractionTarget {
211
+ /** 鼠标所在的轨道索引,若不在任何轨道上则为 null */
212
+ trackIndex: number | null;
213
+ /** 命中的事件索引(z-order 最高),若未命中任何事件则为 null */
214
+ eventIndex: number | null;
215
+ /** 若命中了 resize handle,标识是左边还是右边;否则为 null */
216
+ resizeEdge: "left" | "right" | null;
217
+ }
207
218
  interface ContextMenuEvent {
208
219
  trackIndex: number;
209
220
  eventIndex: number;
@@ -411,7 +422,7 @@ declare global {
411
422
  /**
412
423
  * 状态变更类型
413
424
  */
414
- type ChangeType = "events:add" | "events:update" | "events:delete" | "events:move" | "events:split" | "tracks:add" | "tracks:remove" | "timeIndicator:move" | "timeIndicator:drag" | "scroll:x" | "scroll:y" | "zoom:change" | "selection:change" | "highlight:change" | "canvas:resize" | "data:load" | "theme:change" | "interaction:hover" | "interaction:contextMenu" | "interaction:splitLine" | "config:endTime" | "config:readOnly";
425
+ type ChangeType = "events:add" | "events:update" | "events:delete" | "events:move" | "events:split" | "tracks:add" | "tracks:remove" | "timeIndicator:move" | "timeIndicator:drag" | "scroll:x" | "scroll:y" | "zoom:change" | "selection:change" | "highlight:change" | "canvas:resize" | "data:load" | "theme:change" | "interaction:hover" | "interaction:contextMenu" | "interaction:splitLine" | "config:debug" | "config:timeIndicator" | "config:endTime" | "config:readOnly";
415
426
  //#endregion
416
427
  //#region src/core/Timeline.d.ts
417
428
  declare class Timeline {
@@ -458,6 +469,8 @@ declare class Timeline {
458
469
  * 结束批量变更操作
459
470
  */
460
471
  endChangeBatch(): void;
472
+ setDebug(enabled: boolean): void;
473
+ setEnableTimeIndicator(enabled: boolean): void;
461
474
  markDirty(layers: Array<"background" | "tracks" | "timeline" | "guideLines" | "indicator" | "scrollbar" | "overlay" | "interaction">): void;
462
475
  getLastLayerTimes(): Record<string, number>;
463
476
  beginIndexBatch(): void;
@@ -486,6 +499,27 @@ declare class Timeline {
486
499
  deleteEvent(trackIndex: number, eventIndex: number): boolean;
487
500
  loadData(data: LoadDataFormat): boolean;
488
501
  setTimeIndicator(seconds: number, applySnap?: boolean): boolean;
502
+ /**
503
+ * 拖拽过程中的轻量时间指示器更新
504
+ *
505
+ * 与 setTimeIndicator 的区别:
506
+ * - 触发 "timeIndicator:drag" 而非 "timeIndicator:move"(不触发 onTimeIndicatorMove / emitTimeIndicatorHighlight 回调)
507
+ * - 不调用 setStatus
508
+ * - 使用节流的边界滚动而非每帧滚动
509
+ */
510
+ setTimeIndicatorDuringDrag(seconds: number): void;
511
+ /** 上一次边界滚动的时间戳 */
512
+ private _lastEdgeScrollTime;
513
+ /** 边界滚动节流间隔(ms) */
514
+ private static readonly EDGE_SCROLL_THROTTLE;
515
+ /** 距画布边缘多少 px 内触发滚动 */
516
+ private static readonly EDGE_SCROLL_MARGIN;
517
+ /**
518
+ * 拖拽过程中的节流边界滚动
519
+ * 仅当指示器距离画布边缘 < EDGE_SCROLL_MARGIN 时才调整 scrollX,
520
+ * 且受 EDGE_SCROLL_THROTTLE 节流。
521
+ */
522
+ private scrollToTimeIndicatorThrottled;
489
523
  private scrollToTimeIndicator;
490
524
  zoom(factor: number): void;
491
525
  setZoomLevel(zoomLevel: number): boolean;
@@ -495,6 +529,13 @@ declare class Timeline {
495
529
  formatTime(seconds: number): string;
496
530
  setStatus(text: string): void;
497
531
  getStatus(): string;
532
+ /**
533
+ * 统一命中:一次查询同时检测 resize handle 和事件体命中
534
+ * 内部使用 O(n) max-scan 代替排序,降低 CPU 开销
535
+ * @param canvasX 画布坐标 X(不含 scroll 偏移)
536
+ * @param canvasY 画布坐标 Y(不含 scroll 偏移)
537
+ */
538
+ getInteractionTarget(canvasX: number, canvasY: number): InteractionTarget;
498
539
  getEventAtPosition(x: number, y: number): {
499
540
  trackIndex: number;
500
541
  eventIndex: number;
@@ -542,13 +583,13 @@ declare enum PluginType {
542
583
  DATA_SOURCE = "data_source",
543
584
  THEME = "theme",
544
585
  TOOL = "tool",
545
- EXTENSION = "extension",
586
+ EXTENSION = "extension"
546
587
  }
547
588
  declare enum PluginPriority {
548
589
  LOW = 0,
549
590
  NORMAL = 50,
550
591
  HIGH = 100,
551
- CRITICAL = 200,
592
+ CRITICAL = 200
552
593
  }
553
594
  interface PluginMetadata {
554
595
  name: string;
@@ -597,4 +638,4 @@ interface PerformanceProvider {
597
638
  getFPS: () => number;
598
639
  }
599
640
  //#endregion
600
- export { ZoomData as C, Track as S, TimelineColors as _, ContextMenuItem as a, TimelineOptions as b, EventClickData as c, EventMoveData as d, EventTextStyle as f, TimelineCallbacks as g, TimeIndicatorMoveData as h, ContextMenuData as i, EventDeleteData as l, LoadDataFormat as m, Timeline as n, ContextMenuStyle as o, EventUpdateData as p, ChangeType as r, EventAddData as s, TimelinePlugin as t, EventEditData as u, TimelineConfig as v, TimelineState as x, TimelineEvent as y };
641
+ export { Track as C, TimelineState as S, TimelineCallbacks as _, ContextMenuItem as a, TimelineEvent as b, EventClickData as c, EventMoveData as d, EventTextStyle as f, TimeIndicatorMoveData as g, LoadDataFormat as h, ContextMenuData as i, EventDeleteData as l, InteractionTarget as m, Timeline as n, ContextMenuStyle as o, EventUpdateData as p, ChangeType as r, EventAddData as s, TimelinePlugin as t, EventEditData as u, TimelineColors as v, ZoomData as w, TimelineOptions as x, TimelineConfig as y };
package/package.json CHANGED
@@ -1,51 +1,48 @@
1
- {
2
- "name": "timeline-canvas",
3
- "version": "1.0.9",
4
- "description": "A powerful timeline component built with Canvas and TypeScript",
5
- "main": "dist/index.mjs",
6
- "module": "dist/index.mjs",
7
- "types": "dist/index.d.mts",
8
- "type": "module",
9
- "scripts": {
10
- "build": "tsdown",
11
- "dev": "tsdown --watch",
12
- "typecheck": "tsc -p tsconfig.json --noEmit",
13
- "lint": "oxlint src",
14
- "test": "echo \"Error: no test specified\" && exit 1"
15
- },
16
- "keywords": [
17
- "timeline",
18
- "canvas",
19
- "typescript",
20
- "event-timeline",
21
- "visual-timeline"
22
- ],
23
- "author": "sky <https://github.com/umbrella22>",
24
- "license": "MIT",
25
- "packageManager": "pnpm@10.18.1",
26
- "devDependencies": {
27
- "@types/node": "^24.10.1",
28
- "oxlint": "^1.30.0",
29
- "tsdown": "^0.16.8",
30
- "typescript": "^5.9.3",
31
- "vue": "^3.5.25"
32
- },
33
- "dependencies": {
34
- "immer": "^10.1.1"
35
- },
36
- "files": [
37
- "dist",
38
- "README.md",
39
- "README_CN.md"
40
- ],
41
- "exports": {
42
- ".": {
43
- "types": "./dist/index.d.mts",
44
- "import": "./dist/index.mjs"
45
- },
46
- "./builtin-plugin/*": {
47
- "types": "./dist/builtin-plugin/*.d.mts",
48
- "import": "./dist/builtin-plugin/*.mjs"
49
- }
50
- }
1
+ {
2
+ "name": "timeline-canvas",
3
+ "version": "1.2.0",
4
+ "description": "A powerful timeline component built with Canvas and TypeScript",
5
+ "main": "dist/index.mjs",
6
+ "module": "dist/index.mjs",
7
+ "types": "dist/index.d.mts",
8
+ "type": "module",
9
+ "scripts": {
10
+ "build": "tsdown",
11
+ "dev": "tsdown --watch",
12
+ "typecheck": "tsc -p tsconfig.json --noEmit",
13
+ "lint": "oxlint src",
14
+ "test": "echo \"Error: no test specified\" && exit 1"
15
+ },
16
+ "keywords": [
17
+ "timeline",
18
+ "canvas",
19
+ "typescript",
20
+ "event-timeline",
21
+ "visual-timeline"
22
+ ],
23
+ "author": "sky <https://github.com/umbrella22>",
24
+ "license": "MIT",
25
+ "packageManager": "pnpm@10.18.1",
26
+ "devDependencies": {
27
+ "@types/node": "^24.10.1",
28
+ "oxlint": "^1.43.0"
29
+ },
30
+ "dependencies": {
31
+ "immer": "^10.1.1"
32
+ },
33
+ "files": [
34
+ "dist",
35
+ "README.md",
36
+ "README_CN.md"
37
+ ],
38
+ "exports": {
39
+ ".": {
40
+ "types": "./dist/index.d.mts",
41
+ "import": "./dist/index.mjs"
42
+ },
43
+ "./builtin-plugin/*": {
44
+ "types": "./dist/builtin-plugin/*.d.mts",
45
+ "import": "./dist/builtin-plugin/*.mjs"
46
+ }
47
+ }
51
48
  }
@@ -1 +0,0 @@
1
- import{i as e}from"./Logger-Bwd6lZLT.mjs";import{t}from"./types-CkHQNcJ5.mjs";const n=e(`EventTooltipPlugin`);function r(e={}){let{htmlTemplate:r,showDelay:i=300,maxWidth:a=300,padding:o=8,borderRadius:s=4,backgroundColor:c=`#333`,textColor:l=`#fff`,borderColor:u=`#555`,fontSize:d=12,fontFamily:f=`Arial, sans-serif`}=e,p={visible:!1,title:``,x:0,y:0,trackIndex:-1,eventIndex:-1},m=null,h=null;function g(e,t,n){return e.measureText(t).width>n}return{metadata:{name:`event-tooltip`,version:`1.0.0`,description:`Tooltip plugin for displaying full event title when text is truncated`,type:t.EXTENSION},activate(e){let t=e.timeline.getCanvas(),_=n=>{let r=t.getBoundingClientRect(),a=n.clientX-r.left,o=n.clientY-r.top,s=e.config,c=e.state,l=e.timeline.getEventAtPosition(a,o);if(l){let{trackIndex:n,eventIndex:r}=l,u=c.tracks[n]?.events[r];if(!u){v();return}if(h&&h.trackIndex===n&&h.eventIndex===r&&p.visible){p.x=a,p.y=o,e.timeline.draw();return}h={trackIndex:n,eventIndex:r},m&&=(clearTimeout(m),null);let d=u.duration*s.secondWidth*c.zoomLevel-20,f=t.getContext(`2d`);if(!f)return;let _=s.eventTextStyle,y=_.titleFontSize===`auto`?Math.max(10,Math.min(14,s.trackHeight*.175)):_.titleFontSize;f.font=`${_.titleFontWeight} ${y}px ${_.titleFontFamily}`,g(f,u.title,d)?m=setTimeout(()=>{p={visible:!0,title:u.title,x:a,y:o,trackIndex:n,eventIndex:r},e.timeline.draw()},i):v()}else v()},v=()=>{m&&=(clearTimeout(m),null),h=null,p.visible&&(p.visible=!1,e.timeline.draw())},y=()=>{v()};t.addEventListener(`mousemove`,_),t.addEventListener(`mouseleave`,y),e.api.setData(`tooltipMouseMoveHandler`,_),e.api.setData(`tooltipMouseLeaveHandler`,y),e.api.registerRenderLayer({name:`event-tooltip-overlay`,position:`overlay`,render(t,i,m,h){if(!p.visible||!p.title){let t=e.api.getData(`tooltipContainer`)||null;t&&(t.style.display=`none`);return}let g=e.timeline.getCanvas().getBoundingClientRect(),_=p.x,v=p.y-10;t.save(),t.font=`${d}px ${f}`;let y=p.title.split(``),b=[],x=``;for(let e of y){let n=x+e;t.measureText(n).width>a-o*2?x?(b.push(x),x=e):b.push(e):x=n}x&&b.push(x);let S=0;for(let e of b){let n=t.measureText(e).width;S=Math.max(S,n)}S=Math.min(S+o*2,a);let C=d*1.4,w=b.length*C+o*2;if(v-=w,_+S>g.width&&(_=g.width-S-5),_<5&&(_=5),v<5&&(v=p.y+20),r){let i=r(p.title);if(!i||i.trim()===``)n.warn(`htmlTemplate returned empty content, falling back to Canvas rendering`);else{let n=e.api.getData(`tooltipContainer`)||null;if(!n){n=document.createElement(`div`),n.style.position=`absolute`,n.style.zIndex=`1001`,n.style.pointerEvents=`none`,n.style.boxShadow=`0 2px 8px rgba(0,0,0,0.3)`,n.style.border=`1px solid ${u}`,n.style.borderRadius=`${s}px`,n.style.padding=`${o}px`,n.style.fontSize=`${d}px`,n.style.fontFamily=f,n.style.backgroundColor=c,n.style.color=l,n.style.maxWidth=`${a}px`,n.style.wordWrap=`break-word`,n.style.whiteSpace=`pre-wrap`;let t=e.timeline.getCanvas().parentElement||document.body;t.style.position=t.style.position||`relative`,t.appendChild(n),e.api.setData(`tooltipContainer`,n)}n.style.display=`block`,n.style.left=`${_}px`,n.style.top=`${v}px`,n.innerHTML=i,t.restore();return}}if(t.shadowColor=`rgba(0, 0, 0, 0.3)`,t.shadowBlur=8,t.shadowOffsetX=0,t.shadowOffsetY=2,t.fillStyle=c,t.beginPath(),t.roundRect)t.roundRect(_,v,S,w,s);else{let e=_,n=v,r=S,i=w,a=s;t.moveTo(e+a,n),t.lineTo(e+r-a,n),t.quadraticCurveTo(e+r,n,e+r,n+a),t.lineTo(e+r,n+i-a),t.quadraticCurveTo(e+r,n+i,e+r-a,n+i),t.lineTo(e+a,n+i),t.quadraticCurveTo(e,n+i,e,n+i-a),t.lineTo(e,n+a),t.quadraticCurveTo(e,n,e+a,n)}t.fill(),t.shadowColor=`transparent`,t.shadowBlur=0,t.strokeStyle=u,t.lineWidth=1,t.stroke(),t.fillStyle=l,t.font=`${d}px ${f}`,t.textAlign=`left`,t.textBaseline=`top`;for(let e=0;e<b.length;e++)t.fillText(b[e],_+o,v+o+e*C);t.restore()}})},deactivate(e){let t=e.timeline.getCanvas(),n=e.api.getData(`tooltipMouseMoveHandler`),r=e.api.getData(`tooltipMouseLeaveHandler`);n&&t.removeEventListener(`mousemove`,n),r&&t.removeEventListener(`mouseleave`,r),m&&=(clearTimeout(m),null),e.api.unregisterRenderLayer(`event-tooltip-overlay`);let i=e.api.getData(`tooltipContainer`)||null;i&&i.parentElement&&i.parentElement.removeChild(i)},destroy(e){let t=e.api.getData(`tooltipContainer`)||null;t&&t.parentElement&&t.parentElement.removeChild(t),m&&=(clearTimeout(m),null)}}}export{r as t};
@@ -1 +0,0 @@
1
- import{t as e}from"./performanceMonitor-Cf-Ah4F7.mjs";import{t}from"./types-CkHQNcJ5.mjs";const n={metadata:{name:`performance-overlay`,version:`1.0.0`,description:`Draw performance metrics overlay`,type:t.TOOL},activate(t){let n=new e(t.config.enablePerformanceMonitor||t.config.debug);t.api.setPerformanceProvider(n),t.api.setData(`perfMonitor`,n),t.api.setData(`perfOverlayPos`,{x:10,y:10}),t.api.setData(`perfOverlayDragging`,!1),t.api.setData(`perfOverlayOffset`,{x:0,y:0});let r=t.timeline.getCanvas(),i=e=>{let n=r.getBoundingClientRect(),i=e.clientX-n.left,a=e.clientY-n.top,o=t.api.getData(`perfOverlaySize`),s=t.api.getData(`perfOverlayPos`)||{x:10,y:10};o&&i>=s.x&&i<=s.x+o.width&&a>=s.y&&a<=s.y+o.height&&(t.api.setData(`perfOverlayDragging`,!0),t.api.setData(`perfOverlayOffset`,{x:i-s.x,y:a-s.y}),e.stopPropagation(),e.preventDefault())},a=e=>{if(!t.api.getData(`perfOverlayDragging`))return;let n=r.getBoundingClientRect(),i=e.clientX-n.left,a=e.clientY-n.top,o=t.api.getData(`perfOverlayOffset`)||{x:0,y:0},s=t.api.getData(`perfOverlaySize`)||{width:0,height:0},c=i-o.x,l=a-o.y;c=Math.max(0,Math.min(n.width-s.width,c)),l=Math.max(0,Math.min(n.height-s.height,l)),t.api.setData(`perfOverlayPos`,{x:c,y:l}),t.timeline.draw(),e.stopPropagation(),e.preventDefault()},o=e=>{t.api.getData(`perfOverlayDragging`)&&t.api.setData(`perfOverlayDragging`,!1)};r.addEventListener(`mousedown`,i,{capture:!0}),r.addEventListener(`mousemove`,a,{capture:!0}),window.addEventListener(`mouseup`,o,{capture:!0}),t.api.setData(`perfOverlayListeners`,{onMouseDown:i,onMouseMove:a,onMouseUp:o}),t.api.registerRenderLayer({name:`performance-overlay`,position:`overlay`,render(e){let n=t.api.getData(`perfMonitor`),r=!!(t.config.enablePerformanceMonitor||t.config.debug);n&&(r?n.enable():n.disable());let i=t.api.getPerformanceStats();if(i.size===0)return;let a=t.api.getFPS(),o=Array.from(i.entries()),s=[`background`,`tracks`,`timeline`,`interaction`,`guideLines`,`scrollbar`,`overlay`,`dragPreview`],c=t.timeline.getLastLayerTimes?t.timeline.getLastLayerTimes():void 0,l=c?s.filter(e=>c[e]!==void 0).length:0,u=c?1+l:0,d=25+(1+o.length+u)*20+30,f=t.api.getData(`perfOverlayPos`)||{x:10,y:10};t.api.setData(`perfOverlaySize`,{width:280,height:d}),e.fillStyle=`rgba(0, 0, 0, 0.8)`,e.fillRect(f.x,f.y,280,d),e.strokeStyle=`rgba(100, 255, 100, 0.6)`,e.lineWidth=2,e.strokeRect(f.x,f.y,280,d),e.fillStyle=`#00FF00`,e.font=`bold 16px monospace`,e.textAlign=`left`,e.fillText(`性能监控报告`,f.x+10,f.y+20);let p=f.y+20+25;if(e.fillStyle=a>=55?`#00FF00`:a>=30?`#FFFF00`:`#FF0000`,e.font=`bold 14px monospace`,e.fillText(`FPS: ${a.toFixed(1)}`,f.x+10,p),e.font=`12px monospace`,p+=20,c){e.fillStyle=`#00FFFF`,e.font=`bold 12px monospace`,e.fillText(`Layer Times (ms):`,f.x+10,p),p+=20,e.font=`12px monospace`,e.fillStyle=`#FFFFFF`;for(let t of s)c[t]!==void 0&&(e.fillText(`${t}: ${c[t].toFixed(2)}`,f.x+10,p),p+=20)}o.forEach(([t,n])=>{let r=`#00FF00`;n.average>16&&(r=`#FFFF00`),n.average>33&&(r=`#FF0000`),e.fillStyle=r;let i=`${t}: ${n.average.toFixed(2)}ms (${n.min.toFixed(1)}-${n.max.toFixed(1)})`;e.fillText(i,f.x+10,p),p+=20})}})},deactivate(e){e.api.unregisterRenderLayer(`performance-overlay`);let t=e.api.getData(`perfOverlayListeners`),n=e.timeline.getCanvas();t&&(n.removeEventListener(`mousedown`,t.onMouseDown,!0),n.removeEventListener(`mousemove`,t.onMouseMove,!0),window.removeEventListener(`mouseup`,t.onMouseUp,!0))}};export{n as t};
File without changes